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
@@ -49,10 +52,10 @@ STATIC void spi_clock_disable(uint8_t mask);
49
52
STATIC uint32_t get_busclock (SPI_TypeDef * instance ) {
50
53
//SPI2 and 3 are on PCLK1, if they exist.
51
54
#ifdef SPI2
52
- if (instance == SPI2 ) return HAL_RCC_GetPCLK1Freq ();
55
+ if (instance == SPI2 ) return HAL_RCC_GetPCLK1Freq ();
53
56
#endif
54
57
#ifdef SPI3
55
- if (instance == SPI3 ) return HAL_RCC_GetPCLK1Freq ();
58
+ if (instance == SPI3 ) return HAL_RCC_GetPCLK1Freq ();
56
59
#endif
57
60
return HAL_RCC_GetPCLK2Freq ();
58
61
}
@@ -79,38 +82,80 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
79
82
uint8_t sck_len = sizeof (mcu_spi_sck_list )/sizeof (* mcu_spi_sck_list );
80
83
uint8_t mosi_len = sizeof (mcu_spi_mosi_list )/sizeof (* mcu_spi_mosi_list );
81
84
uint8_t miso_len = sizeof (mcu_spi_miso_list )/sizeof (* mcu_spi_miso_list );
82
-
83
85
bool spi_taken = false;
84
- //sck
85
- for (uint i = 0 ; i < sck_len ;i ++ ) {
86
+
87
+ //SCK is not optional. MOSI and MISO are
88
+ for (uint i = 0 ; i < sck_len ;i ++ ) {
86
89
if (mcu_spi_sck_list [i ].pin == sck ) {
87
- //mosi
88
- for (uint j = 0 ; j < mosi_len ;j ++ ) {
89
- if (mcu_spi_mosi_list [j ].pin == mosi ) {
90
- //miso
91
- for (uint k = 0 ; k < miso_len ;k ++ ) {
92
- if ((mcu_spi_miso_list [k ].pin == miso ) //everything needs the same index
93
- && (mcu_spi_sck_list [i ].spi_index == mcu_spi_mosi_list [j ].spi_index )
94
- && (mcu_spi_sck_list [i ].spi_index == mcu_spi_miso_list [k ].spi_index )) {
95
- //keep looking if the SPI is taken, edge case
96
- if (reserved_spi [mcu_spi_sck_list [i ].spi_index - 1 ]) {
97
- spi_taken = true;
98
- continue ;
90
+ //if both MOSI and MISO exist, loop search normally
91
+ if ((mosi != mp_const_none ) && (miso != mp_const_none )) {
92
+ //MOSI
93
+ for (uint j = 0 ; j < mosi_len ;j ++ ) {
94
+ if (mcu_spi_mosi_list [j ].pin == mosi ) {
95
+ //MISO
96
+ for (uint k = 0 ; k < miso_len ;k ++ ) {
97
+ if ((mcu_spi_miso_list [k ].pin == miso ) //everything needs the same index
98
+ && (mcu_spi_sck_list [i ].spi_index == mcu_spi_mosi_list [j ].spi_index )
99
+ && (mcu_spi_sck_list [i ].spi_index == mcu_spi_miso_list [k ].spi_index )) {
100
+ //keep looking if the SPI is taken, edge case
101
+ if (reserved_spi [mcu_spi_sck_list [i ].spi_index - 1 ]) {
102
+ spi_taken = true;
103
+ continue ;
104
+ }
105
+ //store pins if not
106
+ self -> sck = & mcu_spi_sck_list [i ];
107
+ self -> mosi = & mcu_spi_mosi_list [j ];
108
+ self -> miso = & mcu_spi_miso_list [k ];
109
+ break ;
99
110
}
100
- //store pins if not
101
- self -> sck = & mcu_spi_sck_list [i ];
102
- self -> mosi = & mcu_spi_mosi_list [j ];
103
- self -> miso = & mcu_spi_miso_list [k ];
104
- break ;
105
- }
106
- }
111
+ }
112
+ }
107
113
}
114
+ // if just MISO, reduce search
115
+ } else if (miso != mp_const_none ) {
116
+ for (uint j = 0 ; j < miso_len ;j ++ ) {
117
+ if ((mcu_spi_miso_list [j ].pin == miso ) //only SCK and MISO need the same index
118
+ && (mcu_spi_sck_list [i ].spi_index == mcu_spi_miso_list [j ].spi_index )) {
119
+ //keep looking if the SPI is taken, edge case
120
+ if (reserved_spi [mcu_spi_sck_list [i ].spi_index - 1 ]) {
121
+ spi_taken = true;
122
+ continue ;
123
+ }
124
+ //store pins if not
125
+ self -> sck = & mcu_spi_sck_list [i ];
126
+ self -> mosi = NULL ;
127
+ self -> miso = & mcu_spi_miso_list [j ];
128
+ break ;
129
+ }
130
+ }
131
+ // if just MOSI, reduce search
132
+ } else if (mosi != mp_const_none ) {
133
+ for (uint j = 0 ; j < mosi_len ;j ++ ) {
134
+ if ((mcu_spi_mosi_list [j ].pin == mosi ) //only SCK and MOSI need the same index
135
+ && (mcu_spi_sck_list [i ].spi_index == mcu_spi_mosi_list [j ].spi_index )) {
136
+ //keep looking if the SPI is taken, edge case
137
+ if (reserved_spi [mcu_spi_sck_list [i ].spi_index - 1 ]) {
138
+ spi_taken = true;
139
+ continue ;
140
+ }
141
+ //store pins if not
142
+ self -> sck = & mcu_spi_sck_list [i ];
143
+ self -> mosi = & mcu_spi_mosi_list [j ];
144
+ self -> miso = NULL ;
145
+ break ;
146
+ }
147
+ }
148
+ } else {
149
+ //throw an error immediately
150
+ mp_raise_ValueError (translate ("Must provide MISO or MOSI pin" ));
108
151
}
109
152
}
110
153
}
111
154
112
155
//handle typedef selection, errors
113
- if (self -> sck != NULL && self -> mosi != NULL && self -> miso != NULL ) {
156
+ if ( (self -> sck != NULL && self -> mosi != NULL && self -> miso != NULL ) ||
157
+ (self -> sck != NULL && self -> mosi != NULL && miso == mp_const_none ) ||
158
+ (self -> sck != NULL && self -> miso != NULL && mosi == mp_const_none )) {
114
159
SPIx = mcu_spi_banks [self -> sck -> spi_index - 1 ];
115
160
} else {
116
161
if (spi_taken ) {
@@ -129,26 +174,31 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
129
174
GPIO_InitStruct .Alternate = self -> sck -> altfn_index ;
130
175
HAL_GPIO_Init (pin_port (sck -> port ), & GPIO_InitStruct );
131
176
132
- GPIO_InitStruct .Pin = pin_mask (mosi -> number );
133
- GPIO_InitStruct .Mode = GPIO_MODE_AF_PP ;
134
- GPIO_InitStruct .Pull = GPIO_NOPULL ;
135
- GPIO_InitStruct .Speed = GPIO_SPEED_FREQ_VERY_HIGH ;
136
- GPIO_InitStruct .Alternate = self -> mosi -> altfn_index ;
137
- HAL_GPIO_Init (pin_port (mosi -> port ), & GPIO_InitStruct );
177
+ if (self -> mosi != NULL ) {
178
+ GPIO_InitStruct .Pin = pin_mask (mosi -> number );
179
+ GPIO_InitStruct .Mode = GPIO_MODE_AF_PP ;
180
+ GPIO_InitStruct .Pull = GPIO_NOPULL ;
181
+ GPIO_InitStruct .Speed = GPIO_SPEED_FREQ_VERY_HIGH ;
182
+ GPIO_InitStruct .Alternate = self -> mosi -> altfn_index ;
183
+ HAL_GPIO_Init (pin_port (mosi -> port ), & GPIO_InitStruct );
184
+ }
138
185
139
- GPIO_InitStruct .Pin = pin_mask (miso -> number );
140
- GPIO_InitStruct .Mode = GPIO_MODE_AF_PP ;
141
- GPIO_InitStruct .Pull = GPIO_NOPULL ;
142
- GPIO_InitStruct .Speed = GPIO_SPEED_FREQ_VERY_HIGH ;
143
- GPIO_InitStruct .Alternate = self -> miso -> altfn_index ;
144
- HAL_GPIO_Init (pin_port (miso -> port ), & GPIO_InitStruct );
186
+ if (self -> miso != NULL ) {
187
+ GPIO_InitStruct .Pin = pin_mask (miso -> number );
188
+ GPIO_InitStruct .Mode = GPIO_MODE_AF_PP ;
189
+ GPIO_InitStruct .Pull = GPIO_NOPULL ;
190
+ GPIO_InitStruct .Speed = GPIO_SPEED_FREQ_VERY_HIGH ;
191
+ GPIO_InitStruct .Alternate = self -> miso -> altfn_index ;
192
+ HAL_GPIO_Init (pin_port (miso -> port ), & GPIO_InitStruct );
193
+ }
145
194
146
195
spi_clock_enable (1 <<(self -> sck -> spi_index - 1 ));
147
196
reserved_spi [self -> sck -> spi_index - 1 ] = true;
148
197
149
198
self -> handle .Instance = SPIx ;
150
199
self -> handle .Init .Mode = SPI_MODE_MASTER ;
151
- self -> handle .Init .Direction = SPI_DIRECTION_2LINES ;
200
+ // Direction change only required for RX-only, see RefMan RM0090:884
201
+ self -> handle .Init .Direction = (self -> mosi == NULL ) ? SPI_CR1_RXONLY : SPI_DIRECTION_2LINES ;
152
202
self -> handle .Init .DataSize = SPI_DATASIZE_8BIT ;
153
203
self -> handle .Init .CLKPolarity = SPI_POLARITY_LOW ;
154
204
self -> handle .Init .CLKPhase = SPI_PHASE_1EDGE ;
@@ -169,17 +219,25 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self,
169
219
self -> bits = 8 ;
170
220
171
221
claim_pin (sck );
172
- claim_pin (mosi );
173
- claim_pin (miso );
222
+ if (self -> mosi != NULL ) {
223
+ claim_pin (mosi );
224
+ }
225
+ if (self -> miso != NULL ) {
226
+ claim_pin (miso );
227
+ }
174
228
}
175
229
176
230
void common_hal_busio_spi_never_reset (busio_spi_obj_t * self ) {
177
- for (size_t i = 0 ; i < MP_ARRAY_SIZE (mcu_spi_banks ); i ++ ) {
231
+ for (size_t i = 0 ; i < MP_ARRAY_SIZE (mcu_spi_banks ); i ++ ) {
178
232
if (mcu_spi_banks [i ] == self -> handle .Instance ) {
179
233
never_reset_spi [i ] = true;
180
234
never_reset_pin_number (self -> sck -> pin -> port , self -> sck -> pin -> number );
181
- never_reset_pin_number (self -> mosi -> pin -> port , self -> mosi -> pin -> number );
182
- never_reset_pin_number (self -> miso -> pin -> port , self -> miso -> pin -> number );
235
+ if (self -> mosi != NULL ) {
236
+ never_reset_pin_number (self -> mosi -> pin -> port , self -> mosi -> pin -> number );
237
+ }
238
+ if (self -> miso != NULL ) {
239
+ never_reset_pin_number (self -> miso -> pin -> port , self -> miso -> pin -> number );
240
+ }
183
241
break ;
184
242
}
185
243
}
@@ -195,8 +253,12 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
195
253
never_reset_spi [self -> sck -> spi_index - 1 ] = false;
196
254
197
255
reset_pin_number (self -> sck -> pin -> port ,self -> sck -> pin -> number );
198
- reset_pin_number (self -> mosi -> pin -> port ,self -> mosi -> pin -> number );
199
- reset_pin_number (self -> miso -> pin -> port ,self -> miso -> pin -> number );
256
+ if (self -> mosi != NULL ) {
257
+ reset_pin_number (self -> mosi -> pin -> port ,self -> mosi -> pin -> number );
258
+ }
259
+ if (self -> miso != NULL ) {
260
+ reset_pin_number (self -> miso -> pin -> port ,self -> miso -> pin -> number );
261
+ }
200
262
self -> sck = mp_const_none ;
201
263
self -> mosi = mp_const_none ;
202
264
self -> miso = mp_const_none ;
@@ -232,7 +294,9 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
232
294
uint32_t baudrate , uint8_t polarity , uint8_t phase , uint8_t bits ) {
233
295
//This resets the SPI, so check before updating it redundantly
234
296
if (baudrate == self -> baudrate && polarity == self -> polarity
235
- && phase == self -> phase && bits == self -> bits ) return true;
297
+ && phase == self -> phase && bits == self -> bits ) {
298
+ return true;
299
+ }
236
300
237
301
//Deinit SPI
238
302
HAL_SPI_DeInit (& self -> handle );
@@ -243,13 +307,6 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
243
307
244
308
self -> handle .Init .BaudRatePrescaler = stm32_baud_to_spi_div (baudrate , & self -> prescaler ,
245
309
get_busclock (self -> handle .Instance ));
246
- self -> handle .Init .Mode = SPI_MODE_MASTER ;
247
- self -> handle .Init .Direction = SPI_DIRECTION_2LINES ;
248
- self -> handle .Init .NSS = SPI_NSS_SOFT ;
249
- self -> handle .Init .FirstBit = SPI_FIRSTBIT_MSB ;
250
- self -> handle .Init .TIMode = SPI_TIMODE_DISABLE ;
251
- self -> handle .Init .CRCCalculation = SPI_CRCCALCULATION_DISABLE ;
252
- self -> handle .Init .CRCPolynomial = 10 ;
253
310
254
311
if (HAL_SPI_Init (& self -> handle ) != HAL_OK )
255
312
{
@@ -292,18 +349,27 @@ void common_hal_busio_spi_unlock(busio_spi_obj_t *self) {
292
349
293
350
bool common_hal_busio_spi_write (busio_spi_obj_t * self ,
294
351
const uint8_t * data , size_t len ) {
352
+ if (self -> mosi == NULL ) {
353
+ mp_raise_ValueError (translate ("No MOSI Pin" ));
354
+ }
295
355
HAL_StatusTypeDef result = HAL_SPI_Transmit (& self -> handle , (uint8_t * )data , (uint16_t )len , HAL_MAX_DELAY );
296
356
return result == HAL_OK ;
297
357
}
298
358
299
359
bool common_hal_busio_spi_read (busio_spi_obj_t * self ,
300
360
uint8_t * data , size_t len , uint8_t write_value ) {
361
+ if (self -> miso == NULL ) {
362
+ mp_raise_ValueError (translate ("No MISO Pin" ));
363
+ }
301
364
HAL_StatusTypeDef result = HAL_SPI_Receive (& self -> handle , data , (uint16_t )len , HAL_MAX_DELAY );
302
365
return result == HAL_OK ;
303
366
}
304
367
305
368
bool common_hal_busio_spi_transfer (busio_spi_obj_t * self ,
306
369
uint8_t * data_out , uint8_t * data_in , size_t len ) {
370
+ if (self -> miso == NULL || self -> mosi == NULL ) {
371
+ mp_raise_ValueError (translate ("Missing MISO or MOSI Pin" ));
372
+ }
307
373
HAL_StatusTypeDef result = HAL_SPI_TransmitReceive (& self -> handle ,
308
374
data_out , data_in , (uint16_t )len ,HAL_MAX_DELAY );
309
375
return result == HAL_OK ;
0 commit comments