25
25
* THE SOFTWARE.
26
26
*/
27
27
28
- //TODO
29
28
#include "shared-bindings/busio/SPI.h"
30
29
#include "py/mperrno.h"
31
30
#include "py/runtime.h"
35
34
36
35
#include <stdio.h>
37
36
38
- //bool never_reset_sercoms[SERCOM_INST_NUM];
39
- //
40
- //void never_reset_sercom(Sercom* sercom) {
41
- // // Reset all SERCOMs except the ones being used by on-board devices.
42
- // Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS;
43
- // for (int i = 0; i < SERCOM_INST_NUM; i++) {
44
- // if (sercom_instances[i] == sercom) {
45
- // never_reset_sercoms[i] = true;
46
- // break;
47
- // }
48
- // }
49
- //}
50
- //
51
- //void allow_reset_sercom(Sercom* sercom) {
52
- // // Reset all SERCOMs except the ones being used by on-board devices.
53
- // Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS;
54
- // for (int i = 0; i < SERCOM_INST_NUM; i++) {
55
- // if (sercom_instances[i] == sercom) {
56
- // never_reset_sercoms[i] = false;
57
- // break;
58
- // }
59
- // }
60
- //}
61
- //
62
- //void reset_sercoms(void) {
63
- // // Reset all SERCOMs except the ones being used by on-board devices.
64
- // Sercom *sercom_instances[SERCOM_INST_NUM] = SERCOM_INSTS;
65
- // for (int i = 0; i < SERCOM_INST_NUM; i++) {
66
- // if (never_reset_sercoms[i]) {
67
- // continue;
68
- // }
69
- // #ifdef MICROPY_HW_APA102_SERCOM
70
- // if (sercom_instances[i] == MICROPY_HW_APA102_SERCOM) {
71
- // continue;
72
- // }
73
- // #endif
74
- // // SWRST is same for all modes of SERCOMs.
75
- // sercom_instances[i]->SPI.CTRLA.bit.SWRST = 1;
76
- // }
77
- //}
78
-
79
- static void config_periph_pin (const mcu_periph_obj_t * periph ) {
37
+ //arrays use 0 based numbering: SPI1 is stored at index 0
38
+ #define MAX_SPI 4
39
+ STATIC bool reserved_spi [MAX_SPI ];
40
+ STATIC bool never_reset_spi [MAX_SPI ];
41
+
42
+ STATIC void config_periph_pin (const mcu_periph_obj_t * periph ) {
80
43
IOMUXC_SetPinMux (
81
44
periph -> pin -> mux_reg , periph -> mux_mode ,
82
45
periph -> input_reg , periph -> input_idx ,
@@ -97,115 +60,153 @@ static void config_periph_pin(const mcu_periph_obj_t *periph) {
97
60
98
61
#define LPSPI_MASTER_CLK_FREQ (CLOCK_GetFreq(kCLOCK_Usb1PllPfd0Clk) / (CLOCK_GetDiv(kCLOCK_LpspiDiv)))
99
62
63
+ void spi_reset (void ) {
64
+ for (int i = 0 ; i < MAX_SPI ; i ++ ) {
65
+ reserved_spi [i ] = false;
66
+ }
67
+ }
68
+
100
69
void common_hal_busio_spi_construct (busio_spi_obj_t * self ,
101
70
const mcu_pin_obj_t * clock , const mcu_pin_obj_t * mosi ,
102
71
const mcu_pin_obj_t * miso ) {
103
72
104
- // TODO: Allow none mosi or miso
105
-
106
- const uint32_t sck_count = sizeof (mcu_spi_sck_list ) / sizeof (mcu_periph_obj_t );
107
- const uint32_t miso_count = sizeof (mcu_spi_miso_list ) / sizeof (mcu_periph_obj_t );
108
- const uint32_t mosi_count = sizeof (mcu_spi_mosi_list ) / sizeof (mcu_periph_obj_t );
73
+ const uint32_t sck_count = MP_ARRAY_SIZE (mcu_spi_sck_list );
74
+ const uint32_t miso_count = MP_ARRAY_SIZE (mcu_spi_miso_list );
75
+ const uint32_t mosi_count = MP_ARRAY_SIZE (mcu_spi_mosi_list );
76
+ bool spi_taken = false;
109
77
110
- for (uint32_t i = 0 ; i < sck_count ; ++ i ) {
111
- if (mcu_spi_sck_list [i ].pin != clock )
78
+ for (uint i = 0 ; i < sck_count ; i ++ ) {
79
+ if (mcu_spi_sck_list [i ].pin != clock ) {
112
80
continue ;
113
-
114
- for (uint32_t j = 0 ; j < miso_count ; ++ j ) {
115
- if (mcu_spi_miso_list [j ].pin != miso )
116
- continue ;
117
-
118
- if (mcu_spi_miso_list [j ].bank_idx != mcu_spi_sck_list [i ].bank_idx )
119
- continue ;
120
-
121
- for (uint32_t k = 0 ; k < mosi_count ; ++ k ) {
122
- if (mcu_spi_mosi_list [k ].pin != mosi )
81
+ }
82
+ //if both MOSI and MISO exist, loop search normally
83
+ if ((mosi != NULL ) && (miso != NULL )) {
84
+ for (uint j = 0 ; j < mosi_count ; j ++ ) {
85
+ if ((mcu_spi_mosi_list [i ].pin != mosi )
86
+ || (mcu_spi_sck_list [i ].bank_idx != mcu_spi_mosi_list [j ].bank_idx )){
123
87
continue ;
124
-
125
- if (mcu_spi_mosi_list [k ].bank_idx != mcu_spi_miso_list [j ].bank_idx )
88
+ }
89
+ for (uint k = 0 ; k < miso_count ; k ++ ) {
90
+ if ((mcu_spi_miso_list [k ].pin != miso ) //everything needs the same index
91
+ || (mcu_spi_sck_list [i ].bank_idx != mcu_spi_miso_list [k ].bank_idx )) {
92
+ continue ;
93
+ }
94
+ //keep looking if the SPI is taken, edge case
95
+ if (reserved_spi [mcu_spi_sck_list [i ].bank_idx - 1 ]) {
96
+ spi_taken = true;
97
+ continue ;
98
+ }
99
+ //store pins if not
100
+ self -> clock = & mcu_spi_sck_list [i ];
101
+ self -> mosi = & mcu_spi_mosi_list [j ];
102
+ self -> miso = & mcu_spi_miso_list [k ];
103
+ break ;
104
+ }
105
+ if (self -> clock != NULL ) {
106
+ break ; // Multi-level break to pick lowest peripheral
107
+ }
108
+ }
109
+ if (self -> clock != NULL ) {
110
+ break ;
111
+ }
112
+ // if just MISO, reduce search
113
+ } else if (miso != NULL ) {
114
+ for (uint j = 0 ; j < miso_count ; j ++ ) {
115
+ if ((mcu_spi_miso_list [j ].pin != miso ) //only SCK and MISO need the same index
116
+ || (mcu_spi_sck_list [i ].bank_idx != mcu_spi_miso_list [j ].bank_idx )) {
126
117
continue ;
127
-
128
- self -> clock_pin = & mcu_spi_sck_list [i ];
129
- self -> miso_pin = & mcu_spi_miso_list [j ];
130
- self -> mosi_pin = & mcu_spi_mosi_list [k ];
131
-
118
+ }
119
+ if (reserved_spi [mcu_spi_sck_list [i ].bank_idx - 1 ]) {
120
+ spi_taken = true;
121
+ continue ;
122
+ }
123
+ self -> clock = & mcu_spi_sck_list [i ];
124
+ self -> mosi = NULL ;
125
+ self -> miso = & mcu_spi_miso_list [j ];
126
+ break ;
127
+ }
128
+ if (self -> clock != NULL ) {
132
129
break ;
133
130
}
131
+ // if just MOSI, reduce search
132
+ } else if (mosi != NULL ) {
133
+ for (uint j = 0 ; j < mosi_count ; j ++ ) {
134
+ if ((mcu_spi_mosi_list [j ].pin != mosi ) //only SCK and MOSI need the same index
135
+ || (mcu_spi_sck_list [i ].bank_idx != mcu_spi_mosi_list [j ].bank_idx )) {
136
+ continue ;
137
+ }
138
+ if (reserved_spi [mcu_spi_sck_list [i ].bank_idx - 1 ]) {
139
+ spi_taken = true;
140
+ continue ;
141
+ }
142
+ self -> clock = & mcu_spi_sck_list [i ];
143
+ self -> mosi = & mcu_spi_mosi_list [j ];
144
+ self -> miso = NULL ;
145
+ break ;
146
+ }
147
+ if (self -> clock != NULL ) {
148
+ break ;
149
+ }
150
+ } else {
151
+ //throw an error immediately
152
+ mp_raise_ValueError (translate ("Must provide MISO or MOSI pin" ));
134
153
}
135
154
}
136
155
137
- if (self -> clock_pin == NULL || self -> mosi_pin == NULL || self -> miso_pin == NULL ) {
138
- mp_raise_RuntimeError ( translate ( "Invalid SPI pin selection" )) ;
156
+ if (self -> clock != NULL && ( self -> mosi != NULL || self -> miso != NULL ) ) {
157
+ self -> spi = mcu_spi_banks [ self -> clock -> bank_idx - 1 ] ;
139
158
} else {
140
- self -> spi = mcu_spi_banks [self -> clock_pin -> bank_idx - 1 ];
159
+ if (spi_taken ) {
160
+ mp_raise_ValueError (translate ("Hardware busy, try alternative pins" ));
161
+ } else {
162
+ mp_raise_ValueError (translate ("Invalid SPI pin selection" ));
163
+ }
141
164
}
142
165
143
- config_periph_pin (self -> mosi_pin );
144
- config_periph_pin (self -> miso_pin );
145
- config_periph_pin (self -> clock_pin );
166
+ config_periph_pin (self -> clock );
167
+ if (self -> mosi != NULL ) {
168
+ config_periph_pin (self -> mosi );
169
+ }
170
+ if (self -> miso != NULL ) {
171
+ config_periph_pin (self -> miso );
172
+ }
173
+ reserved_spi [self -> clock -> bank_idx - 1 ] = true;
146
174
147
175
lpspi_master_config_t config = { 0 };
148
176
LPSPI_MasterGetDefaultConfig (& config );
149
177
150
178
// Always start at 250khz which is what SD cards need. They are sensitive to
151
179
// SPI bus noise before they are put into SPI mode.
152
180
config .baudRate = 250000 ;
153
-
154
181
LPSPI_MasterInit (self -> spi , & config , LPSPI_MASTER_CLK_FREQ );
155
-
156
182
LPSPI_Enable (self -> spi , false);
157
183
uint32_t tcrPrescaleValue ;
158
184
self -> baudrate = LPSPI_MasterSetBaudRate (self -> spi , config .baudRate , LPSPI_MASTER_CLK_FREQ , & tcrPrescaleValue );
159
185
LPSPI_Enable (self -> spi , true);
160
186
161
- claim_pin (self -> clock_pin -> pin );
162
-
163
- // if (mosi_none) {
164
- // self->MOSI_pin = NO_PIN;
165
- // } else {
166
- // gpio_set_pin_direction(mosi->number, GPIO_DIRECTION_OUT);
167
- // gpio_set_pin_pull_mode(mosi->number, GPIO_PULL_OFF);
168
- // gpio_set_pin_function(mosi->number, mosi_pinmux);
169
- // self->MOSI_pin = mosi->number;
170
- claim_pin (self -> mosi_pin -> pin );
171
- // }
172
-
173
- // if (miso_none) {
174
- // self->MISO_pin = NO_PIN;
175
- // } else {
176
- // gpio_set_pin_direction(miso->number, GPIO_DIRECTION_IN);
177
- // gpio_set_pin_pull_mode(miso->number, GPIO_PULL_OFF);
178
- // gpio_set_pin_function(miso->number, miso_pinmux);
179
- // self->MISO_pin = miso->number;
180
- claim_pin (self -> miso_pin -> pin );
181
- // }
187
+ claim_pin (self -> clock -> pin );
188
+ if (self -> mosi != NULL ) {
189
+ claim_pin (self -> mosi -> pin );
190
+ }
191
+ if (self -> miso != NULL ) {
192
+ claim_pin (self -> miso -> pin );
193
+ }
182
194
}
183
195
184
196
void common_hal_busio_spi_never_reset (busio_spi_obj_t * self ) {
185
- // never_reset_sercom(self->spi_desc.dev.prvt);
186
-
187
- // never_reset_pin_number(self->clock_pin);
188
- // never_reset_pin_number(self->MOSI_pin);
189
- // never_reset_pin_number(self->MISO_pin);
197
+ // TODO
190
198
}
191
199
192
200
bool common_hal_busio_spi_deinited (busio_spi_obj_t * self ) {
193
- return self -> clock_pin == NULL ;
201
+ return self -> clock == NULL ;
194
202
}
195
203
196
204
void common_hal_busio_spi_deinit (busio_spi_obj_t * self ) {
197
205
if (common_hal_busio_spi_deinited (self )) {
198
206
return ;
199
207
}
200
208
201
- // allow_reset_sercom(self->spi_desc.dev.prvt);
202
-
203
- // spi_m_sync_disable(&self->spi_desc);
204
- // spi_m_sync_deinit(&self->spi_desc);
205
- // reset_pin_number(self->clock_pin);
206
- // reset_pin_number(self->MOSI_pin);
207
- // reset_pin_number(self->MISO_pin);
208
- self -> clock_pin = NULL ;
209
+ self -> clock = NULL ;
209
210
}
210
211
211
212
bool common_hal_busio_spi_configure (busio_spi_obj_t * self ,
@@ -260,6 +261,9 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self,
260
261
if (len == 0 ) {
261
262
return true;
262
263
}
264
+ if (self -> mosi == NULL ) {
265
+ mp_raise_ValueError (translate ("No MOSI Pin" ));
266
+ }
263
267
264
268
lpspi_transfer_t xfer = { 0 };
265
269
xfer .txData = (uint8_t * )data ;
@@ -278,6 +282,9 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self,
278
282
if (len == 0 ) {
279
283
return true;
280
284
}
285
+ if (self -> miso == NULL ) {
286
+ mp_raise_ValueError (translate ("No MISO Pin" ));
287
+ }
281
288
282
289
LPSPI_SetDummyData (self -> spi , write_value );
283
290
@@ -296,6 +303,9 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin
296
303
if (len == 0 ) {
297
304
return true;
298
305
}
306
+ if (self -> miso == NULL || self -> mosi == NULL ) {
307
+ mp_raise_ValueError (translate ("Missing MISO or MOSI Pin" ));
308
+ }
299
309
300
310
LPSPI_SetDummyData (self -> spi , 0xFF );
301
311
0 commit comments