36
36
#include "supervisor/shared/translate.h"
37
37
#include "common-hal/microcontroller/Pin.h"
38
38
39
+ // Note that any bugs introduced in this file can cause crashes at startup
40
+ // for chips using external SPI flash.
41
+
39
42
#define MAX_SPI 6 //TODO; replace this as part of periph cleanup
40
43
#define ALL_CLOCKS 0xFF
41
44
@@ -53,10 +56,10 @@ STATIC void spi_clock_disable(uint8_t mask);
53
56
STATIC uint32_t get_busclock (SPI_TypeDef * instance ) {
54
57
//SPI2 and 3 are on PCLK1, if they exist.
55
58
#ifdef SPI2
56
- if (instance == SPI2 ) return HAL_RCC_GetPCLK1Freq ();
59
+ if (instance == SPI2 ) return HAL_RCC_GetPCLK1Freq ();
57
60
#endif
58
61
#ifdef SPI3
59
- if (instance == SPI3 ) return HAL_RCC_GetPCLK1Freq ();
62
+ if (instance == SPI3 ) return HAL_RCC_GetPCLK1Freq ();
60
63
#endif
61
64
return HAL_RCC_GetPCLK2Freq ();
62
65
}
@@ -113,38 +116,80 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
113
116
uint8_t sck_len = sizeof (mcu_spi_sck_list )/sizeof (* mcu_spi_sck_list );
114
117
uint8_t mosi_len = sizeof (mcu_spi_mosi_list )/sizeof (* mcu_spi_mosi_list );
115
118
uint8_t miso_len = sizeof (mcu_spi_miso_list )/sizeof (* mcu_spi_miso_list );
116
-
117
119
bool spi_taken = false;
118
- //sck
119
- for (uint i = 0 ; i < sck_len ;i ++ ) {
120
+
121
+ //SCK is not optional. MOSI and MISO are
122
+ for (uint i = 0 ; i < sck_len ;i ++ ) {
120
123
if (mcu_spi_sck_list [i ].pin == sck ) {
121
- //mosi
122
- for (uint j = 0 ; j < mosi_len ;j ++ ) {
123
- if (mcu_spi_mosi_list [j ].pin == mosi ) {
124
- //miso
125
- for (uint k = 0 ; k < miso_len ;k ++ ) {
126
- if ((mcu_spi_miso_list [k ].pin == miso ) //everything needs the same index
127
- && (mcu_spi_sck_list [i ].spi_index == mcu_spi_mosi_list [j ].spi_index )
128
- && (mcu_spi_sck_list [i ].spi_index == mcu_spi_miso_list [k ].spi_index )) {
129
- //keep looking if the SPI is taken, edge case
130
- if (reserved_spi [mcu_spi_sck_list [i ].spi_index - 1 ]) {
131
- spi_taken = true;
132
- continue ;
124
+ //if both MOSI and MISO exist, loop search normally
125
+ if ((mosi != mp_const_none ) && (miso != mp_const_none )) {
126
+ //MOSI
127
+ for (uint j = 0 ; j < mosi_len ;j ++ ) {
128
+ if (mcu_spi_mosi_list [j ].pin == mosi ) {
129
+ //MISO
130
+ for (uint k = 0 ; k < miso_len ;k ++ ) {
131
+ if ((mcu_spi_miso_list [k ].pin == miso ) //everything needs the same index
132
+ && (mcu_spi_sck_list [i ].spi_index == mcu_spi_mosi_list [j ].spi_index )
133
+ && (mcu_spi_sck_list [i ].spi_index == mcu_spi_miso_list [k ].spi_index )) {
134
+ //keep looking if the SPI is taken, edge case
135
+ if (reserved_spi [mcu_spi_sck_list [i ].spi_index - 1 ]) {
136
+ spi_taken = true;
137
+ continue ;
138
+ }
139
+ //store pins if not
140
+ self -> sck = & mcu_spi_sck_list [i ];
141
+ self -> mosi = & mcu_spi_mosi_list [j ];
142
+ self -> miso = & mcu_spi_miso_list [k ];
143
+ break ;
133
144
}
134
- //store pins if not
135
- self -> sck = & mcu_spi_sck_list [i ];
136
- self -> mosi = & mcu_spi_mosi_list [j ];
137
- self -> miso = & mcu_spi_miso_list [k ];
138
- break ;
139
- }
140
- }
145
+ }
146
+ }
141
147
}
148
+ // if just MISO, reduce search
149
+ } else if (miso != mp_const_none ) {
150
+ for (uint j = 0 ; j < miso_len ;j ++ ) {
151
+ if ((mcu_spi_miso_list [j ].pin == miso ) //only SCK and MISO need the same index
152
+ && (mcu_spi_sck_list [i ].spi_index == mcu_spi_miso_list [j ].spi_index )) {
153
+ //keep looking if the SPI is taken, edge case
154
+ if (reserved_spi [mcu_spi_sck_list [i ].spi_index - 1 ]) {
155
+ spi_taken = true;
156
+ continue ;
157
+ }
158
+ //store pins if not
159
+ self -> sck = & mcu_spi_sck_list [i ];
160
+ self -> mosi = NULL ;
161
+ self -> miso = & mcu_spi_miso_list [j ];
162
+ break ;
163
+ }
164
+ }
165
+ // if just MOSI, reduce search
166
+ } else if (mosi != mp_const_none ) {
167
+ for (uint j = 0 ; j < mosi_len ;j ++ ) {
168
+ if ((mcu_spi_mosi_list [j ].pin == mosi ) //only SCK and MOSI need the same index
169
+ && (mcu_spi_sck_list [i ].spi_index == mcu_spi_mosi_list [j ].spi_index )) {
170
+ //keep looking if the SPI is taken, edge case
171
+ if (reserved_spi [mcu_spi_sck_list [i ].spi_index - 1 ]) {
172
+ spi_taken = true;
173
+ continue ;
174
+ }
175
+ //store pins if not
176
+ self -> sck = & mcu_spi_sck_list [i ];
177
+ self -> mosi = & mcu_spi_mosi_list [j ];
178
+ self -> miso = NULL ;
179
+ break ;
180
+ }
181
+ }
182
+ } else {
183
+ //throw an error immediately
184
+ mp_raise_ValueError (translate ("Must provide MISO or MOSI pin" ));
142
185
}
143
186
}
144
187
}
145
188
146
189
//handle typedef selection, errors
147
- if (self -> sck != NULL && self -> mosi != NULL && self -> miso != NULL ) {
190
+ if ( (self -> sck != NULL && self -> mosi != NULL && self -> miso != NULL ) ||
191
+ (self -> sck != NULL && self -> mosi != NULL && miso == mp_const_none ) ||
192
+ (self -> sck != NULL && self -> miso != NULL && mosi == mp_const_none )) {
148
193
SPIx = mcu_spi_banks [self -> sck -> spi_index - 1 ];
149
194
} else {
150
195
if (spi_taken ) {
@@ -163,26 +208,31 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
163
208
GPIO_InitStruct .Alternate = self -> sck -> altfn_index ;
164
209
HAL_GPIO_Init (pin_port (sck -> port ), & GPIO_InitStruct );
165
210
166
- GPIO_InitStruct .Pin = pin_mask (mosi -> number );
167
- GPIO_InitStruct .Mode = GPIO_MODE_AF_PP ;
168
- GPIO_InitStruct .Pull = GPIO_NOPULL ;
169
- GPIO_InitStruct .Speed = GPIO_SPEED_FREQ_VERY_HIGH ;
170
- GPIO_InitStruct .Alternate = self -> mosi -> altfn_index ;
171
- HAL_GPIO_Init (pin_port (mosi -> port ), & GPIO_InitStruct );
211
+ if (self -> mosi != NULL ) {
212
+ GPIO_InitStruct .Pin = pin_mask (mosi -> number );
213
+ GPIO_InitStruct .Mode = GPIO_MODE_AF_PP ;
214
+ GPIO_InitStruct .Pull = GPIO_NOPULL ;
215
+ GPIO_InitStruct .Speed = GPIO_SPEED_FREQ_VERY_HIGH ;
216
+ GPIO_InitStruct .Alternate = self -> mosi -> altfn_index ;
217
+ HAL_GPIO_Init (pin_port (mosi -> port ), & GPIO_InitStruct );
218
+ }
172
219
173
- GPIO_InitStruct .Pin = pin_mask (miso -> number );
174
- GPIO_InitStruct .Mode = GPIO_MODE_AF_PP ;
175
- GPIO_InitStruct .Pull = GPIO_NOPULL ;
176
- GPIO_InitStruct .Speed = GPIO_SPEED_FREQ_VERY_HIGH ;
177
- GPIO_InitStruct .Alternate = self -> miso -> altfn_index ;
178
- HAL_GPIO_Init (pin_port (miso -> port ), & GPIO_InitStruct );
220
+ if (self -> miso != NULL ) {
221
+ GPIO_InitStruct .Pin = pin_mask (miso -> number );
222
+ GPIO_InitStruct .Mode = GPIO_MODE_AF_PP ;
223
+ GPIO_InitStruct .Pull = GPIO_NOPULL ;
224
+ GPIO_InitStruct .Speed = GPIO_SPEED_FREQ_VERY_HIGH ;
225
+ GPIO_InitStruct .Alternate = self -> miso -> altfn_index ;
226
+ HAL_GPIO_Init (pin_port (miso -> port ), & GPIO_InitStruct );
227
+ }
179
228
180
229
spi_clock_enable (1 <<(self -> sck -> spi_index - 1 ));
181
230
reserved_spi [self -> sck -> spi_index - 1 ] = true;
182
231
183
232
self -> handle .Instance = SPIx ;
184
233
self -> handle .Init .Mode = SPI_MODE_MASTER ;
185
- self -> handle .Init .Direction = SPI_DIRECTION_2LINES ;
234
+ // Direction change only required for RX-only, see RefMan RM0090:884
235
+ self -> handle .Init .Direction = (self -> mosi == NULL ) ? SPI_CR1_RXONLY : SPI_DIRECTION_2LINES ;
186
236
self -> handle .Init .DataSize = SPI_DATASIZE_8BIT ;
187
237
self -> handle .Init .CLKPolarity = SPI_POLARITY_LOW ;
188
238
self -> handle .Init .CLKPhase = SPI_PHASE_1EDGE ;
@@ -203,17 +253,25 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
203
253
self -> bits = 8 ;
204
254
205
255
claim_pin (sck );
206
- claim_pin (mosi );
207
- claim_pin (miso );
256
+ if (self -> mosi != NULL ) {
257
+ claim_pin (mosi );
258
+ }
259
+ if (self -> miso != NULL ) {
260
+ claim_pin (miso );
261
+ }
208
262
}
209
263
210
264
void common_hal_busio_spi_never_reset (busio_spi_obj_t * self ) {
211
- for (size_t i = 0 ; i < MP_ARRAY_SIZE (mcu_spi_banks ); i ++ ) {
265
+ for (size_t i = 0 ; i < MP_ARRAY_SIZE (mcu_spi_banks ); i ++ ) {
212
266
if (mcu_spi_banks [i ] == self -> handle .Instance ) {
213
267
never_reset_spi [i ] = true;
214
268
never_reset_pin_number (self -> sck -> pin -> port , self -> sck -> pin -> number );
215
- never_reset_pin_number (self -> mosi -> pin -> port , self -> mosi -> pin -> number );
216
- never_reset_pin_number (self -> miso -> pin -> port , self -> miso -> pin -> number );
269
+ if (self -> mosi != NULL ) {
270
+ never_reset_pin_number (self -> mosi -> pin -> port , self -> mosi -> pin -> number );
271
+ }
272
+ if (self -> miso != NULL ) {
273
+ never_reset_pin_number (self -> miso -> pin -> port , self -> miso -> pin -> number );
274
+ }
217
275
break ;
218
276
}
219
277
}
@@ -229,8 +287,12 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
229
287
never_reset_spi [self -> sck -> spi_index - 1 ] = false;
230
288
231
289
reset_pin_number (self -> sck -> pin -> port ,self -> sck -> pin -> number );
232
- reset_pin_number (self -> mosi -> pin -> port ,self -> mosi -> pin -> number );
233
- reset_pin_number (self -> miso -> pin -> port ,self -> miso -> pin -> number );
290
+ if (self -> mosi != NULL ) {
291
+ reset_pin_number (self -> mosi -> pin -> port ,self -> mosi -> pin -> number );
292
+ }
293
+ if (self -> miso != NULL ) {
294
+ reset_pin_number (self -> miso -> pin -> port ,self -> miso -> pin -> number );
295
+ }
234
296
self -> sck = mp_const_none ;
235
297
self -> mosi = mp_const_none ;
236
298
self -> miso = mp_const_none ;
@@ -240,7 +302,9 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
240
302
uint32_t baudrate , uint8_t polarity , uint8_t phase , uint8_t bits ) {
241
303
//This resets the SPI, so check before updating it redundantly
242
304
if (baudrate == self -> baudrate && polarity == self -> polarity
243
- && phase == self -> phase && bits == self -> bits ) return true;
305
+ && phase == self -> phase && bits == self -> bits ) {
306
+ return true;
307
+ }
244
308
245
309
//Deinit SPI
246
310
HAL_SPI_DeInit (& self -> handle );
@@ -251,13 +315,6 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
251
315
252
316
self -> handle .Init .BaudRatePrescaler = stm32_baud_to_spi_div (baudrate , & self -> prescaler ,
253
317
get_busclock (self -> handle .Instance ));
254
- self -> handle .Init .Mode = SPI_MODE_MASTER ;
255
- self -> handle .Init .Direction = SPI_DIRECTION_2LINES ;
256
- self -> handle .Init .NSS = SPI_NSS_SOFT ;
257
- self -> handle .Init .FirstBit = SPI_FIRSTBIT_MSB ;
258
- self -> handle .Init .TIMode = SPI_TIMODE_DISABLE ;
259
- self -> handle .Init .CRCCalculation = SPI_CRCCALCULATION_DISABLE ;
260
- self -> handle .Init .CRCPolynomial = 10 ;
261
318
262
319
if (HAL_SPI_Init (& self -> handle ) != HAL_OK )
263
320
{
@@ -300,18 +357,27 @@ void common_hal_busio_spi_unlock(busio_spi_obj_t *self) {
300
357
301
358
bool common_hal_busio_spi_write (busio_spi_obj_t * self ,
302
359
const uint8_t * data , size_t len ) {
360
+ if (self -> mosi == NULL ) {
361
+ mp_raise_ValueError (translate ("No MOSI Pin" ));
362
+ }
303
363
HAL_StatusTypeDef result = HAL_SPI_Transmit (& self -> handle , (uint8_t * )data , (uint16_t )len , HAL_MAX_DELAY );
304
364
return result == HAL_OK ;
305
365
}
306
366
307
367
bool common_hal_busio_spi_read (busio_spi_obj_t * self ,
308
368
uint8_t * data , size_t len , uint8_t write_value ) {
369
+ if (self -> miso == NULL ) {
370
+ mp_raise_ValueError (translate ("No MISO Pin" ));
371
+ }
309
372
HAL_StatusTypeDef result = HAL_SPI_Receive (& self -> handle , data , (uint16_t )len , HAL_MAX_DELAY );
310
373
return result == HAL_OK ;
311
374
}
312
375
313
376
bool common_hal_busio_spi_transfer (busio_spi_obj_t * self ,
314
377
uint8_t * data_out , uint8_t * data_in , size_t len ) {
378
+ if (self -> miso == NULL || self -> mosi == NULL ) {
379
+ mp_raise_ValueError (translate ("Missing MISO or MOSI Pin" ));
380
+ }
315
381
HAL_StatusTypeDef result = HAL_SPI_TransmitReceive (& self -> handle ,
316
382
data_out , data_in , (uint16_t )len ,HAL_MAX_DELAY );
317
383
return result == HAL_OK ;
0 commit comments