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
- //}
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 ];
78
41
79
42
static void config_periph_pin (const mcu_periph_obj_t * periph ) {
80
43
IOMUXC_SetPinMux (
@@ -97,115 +60,180 @@ 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
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;
105
77
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 );
109
-
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 ) {
129
+ break ;
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 ;
132
145
break ;
133
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
+ // for (uint32_t i = 0; i < sck_count; ++i) {
157
+ // if (mcu_spi_sck_list[i].pin != clock)
158
+ // continue;
159
+
160
+ // for (uint32_t j = 0; j < miso_count; ++j) {
161
+ // if (mcu_spi_miso_list[j].pin != miso)
162
+ // continue;
163
+
164
+ // if (mcu_spi_miso_list[j].bank_idx != mcu_spi_sck_list[i].bank_idx)
165
+ // continue;
166
+
167
+ // for (uint32_t k = 0; k < mosi_count; ++k) {
168
+ // if (mcu_spi_mosi_list[k].pin != mosi)
169
+ // continue;
170
+
171
+ // if (mcu_spi_mosi_list[k].bank_idx != mcu_spi_miso_list[j].bank_idx)
172
+ // continue;
173
+
174
+ // self->clock = &mcu_spi_sck_list[i];
175
+ // self->miso_pin = &mcu_spi_miso_list[j];
176
+ // self->mosi_pin = &mcu_spi_mosi_list[k];
177
+
178
+ // break;
179
+ // }
180
+ // }
181
+ // }
182
+
183
+ if (self -> clock != NULL && (self -> mosi != NULL || self -> miso != NULL )) {
184
+ self -> spi = mcu_spi_banks [self -> clock -> bank_idx - 1 ];
139
185
} else {
140
- self -> spi = mcu_spi_banks [self -> clock_pin -> bank_idx - 1 ];
186
+ if (spi_taken ) {
187
+ mp_raise_ValueError (translate ("Hardware busy, try alternative pins" ));
188
+ } else {
189
+ mp_raise_ValueError (translate ("Invalid SPI pin selection" ));
190
+ }
141
191
}
142
192
143
- config_periph_pin (self -> mosi_pin );
144
- config_periph_pin (self -> miso_pin );
145
- config_periph_pin (self -> clock_pin );
193
+ config_periph_pin (self -> clock );
194
+ if (self -> mosi != NULL ) {
195
+ config_periph_pin (self -> mosi );
196
+ }
197
+ if (self -> miso != NULL ) {
198
+ config_periph_pin (self -> miso );
199
+ }
200
+ reserved_spi [self -> clock -> bank_idx - 1 ] = true;
146
201
147
202
lpspi_master_config_t config = { 0 };
148
203
LPSPI_MasterGetDefaultConfig (& config );
149
204
150
205
// Always start at 250khz which is what SD cards need. They are sensitive to
151
206
// SPI bus noise before they are put into SPI mode.
152
207
config .baudRate = 250000 ;
153
-
154
208
LPSPI_MasterInit (self -> spi , & config , LPSPI_MASTER_CLK_FREQ );
155
-
156
209
LPSPI_Enable (self -> spi , false);
157
210
uint32_t tcrPrescaleValue ;
158
211
self -> baudrate = LPSPI_MasterSetBaudRate (self -> spi , config .baudRate , LPSPI_MASTER_CLK_FREQ , & tcrPrescaleValue );
159
212
LPSPI_Enable (self -> spi , true);
160
213
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
- // }
214
+ claim_pin (self -> clock -> pin );
215
+ if (self -> mosi != NULL ) {
216
+ claim_pin (self -> mosi -> pin );
217
+ }
218
+ if (self -> miso != NULL ) {
219
+ claim_pin (self -> miso -> pin );
220
+ }
182
221
}
183
222
184
223
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);
224
+ // TODO
190
225
}
191
226
192
227
bool common_hal_busio_spi_deinited (busio_spi_obj_t * self ) {
193
- return self -> clock_pin == NULL ;
228
+ return self -> clock == NULL ;
194
229
}
195
230
196
231
void common_hal_busio_spi_deinit (busio_spi_obj_t * self ) {
197
232
if (common_hal_busio_spi_deinited (self )) {
198
233
return ;
199
234
}
200
235
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 ;
236
+ self -> clock = NULL ;
209
237
}
210
238
211
239
bool common_hal_busio_spi_configure (busio_spi_obj_t * self ,
@@ -260,6 +288,9 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self,
260
288
if (len == 0 ) {
261
289
return true;
262
290
}
291
+ if (self -> mosi == NULL ) {
292
+ mp_raise_ValueError (translate ("No MOSI Pin" ));
293
+ }
263
294
264
295
lpspi_transfer_t xfer = { 0 };
265
296
xfer .txData = (uint8_t * )data ;
@@ -278,6 +309,9 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self,
278
309
if (len == 0 ) {
279
310
return true;
280
311
}
312
+ if (self -> miso == NULL ) {
313
+ mp_raise_ValueError (translate ("No MISO Pin" ));
314
+ }
281
315
282
316
LPSPI_SetDummyData (self -> spi , write_value );
283
317
@@ -296,6 +330,9 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin
296
330
if (len == 0 ) {
297
331
return true;
298
332
}
333
+ if (self -> miso == NULL || self -> mosi == NULL ) {
334
+ mp_raise_ValueError (translate ("Missing MISO or MOSI Pin" ));
335
+ }
299
336
300
337
LPSPI_SetDummyData (self -> spi , 0xFF );
301
338
0 commit comments