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
@@ -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
86
+
87
+ //sck is not optional. MOSI and MISO are
85
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,17 @@ 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 ) claim_pin (mosi );
223
+ if ( self -> miso != NULL ) claim_pin (miso );
174
224
}
175
225
176
226
void common_hal_busio_spi_never_reset (busio_spi_obj_t * self ) {
177
227
for (size_t i = 0 ; i < MP_ARRAY_SIZE (mcu_spi_banks ); i ++ ) {
178
228
if (mcu_spi_banks [i ] == self -> handle .Instance ) {
179
229
never_reset_spi [i ] = true;
180
230
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 );
231
+ if ( self -> mosi != NULL ) never_reset_pin_number (self -> mosi -> pin -> port , self -> mosi -> pin -> number );
232
+ if ( self -> miso != NULL ) never_reset_pin_number (self -> miso -> pin -> port , self -> miso -> pin -> number );
183
233
break ;
184
234
}
185
235
}
@@ -195,8 +245,8 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
195
245
never_reset_spi [self -> sck -> spi_index - 1 ] = false;
196
246
197
247
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 );
248
+ if ( self -> mosi != NULL ) reset_pin_number (self -> mosi -> pin -> port ,self -> mosi -> pin -> number );
249
+ if ( self -> miso != NULL ) reset_pin_number (self -> miso -> pin -> port ,self -> miso -> pin -> number );
200
250
self -> sck = mp_const_none ;
201
251
self -> mosi = mp_const_none ;
202
252
self -> miso = mp_const_none ;
@@ -243,13 +293,6 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
243
293
244
294
self -> handle .Init .BaudRatePrescaler = stm32_baud_to_spi_div (baudrate , & self -> prescaler ,
245
295
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
296
254
297
if (HAL_SPI_Init (& self -> handle ) != HAL_OK )
255
298
{
@@ -292,18 +335,22 @@ void common_hal_busio_spi_unlock(busio_spi_obj_t *self) {
292
335
293
336
bool common_hal_busio_spi_write (busio_spi_obj_t * self ,
294
337
const uint8_t * data , size_t len ) {
338
+ if (self -> mosi == NULL ) mp_raise_ValueError (translate ("No MOSI Pin" ));
295
339
HAL_StatusTypeDef result = HAL_SPI_Transmit (& self -> handle , (uint8_t * )data , (uint16_t )len , HAL_MAX_DELAY );
296
340
return result == HAL_OK ;
297
341
}
298
342
299
343
bool common_hal_busio_spi_read (busio_spi_obj_t * self ,
300
344
uint8_t * data , size_t len , uint8_t write_value ) {
345
+ if (self -> miso == NULL ) mp_raise_ValueError (translate ("No MISO Pin" ));
301
346
HAL_StatusTypeDef result = HAL_SPI_Receive (& self -> handle , data , (uint16_t )len , HAL_MAX_DELAY );
302
347
return result == HAL_OK ;
303
348
}
304
349
305
350
bool common_hal_busio_spi_transfer (busio_spi_obj_t * self ,
306
351
uint8_t * data_out , uint8_t * data_in , size_t len ) {
352
+ if (self -> miso == NULL ) mp_raise_ValueError (translate ("No MISO Pin" ));
353
+ if (self -> mosi == NULL ) mp_raise_ValueError (translate ("No MOSI Pin" ));
307
354
HAL_StatusTypeDef result = HAL_SPI_TransmitReceive (& self -> handle ,
308
355
data_out , data_in , (uint16_t )len ,HAL_MAX_DELAY );
309
356
return result == HAL_OK ;
0 commit comments