34
34
#include "common-hal/microcontroller/Pin.h"
35
35
#include "shared-bindings/microcontroller/Pin.h"
36
36
37
- #define NO_INSTANCE 0xff
37
+ #include "peripherals/broadcom/cpu.h"
38
+ #include "peripherals/broadcom/defines.h"
39
+ #include "peripherals/broadcom/gpio.h"
40
+ #include "peripherals/broadcom/pins.h"
41
+ #include "peripherals/broadcom/vcmailbox.h"
38
42
39
- STATIC bool never_reset_spi [2 ];
43
+ #if BCM_VERSION == 2711
44
+ #define NUM_SPI (7)
45
+ STATIC SPI0_Type * spi [NUM_SPI ] = {SPI0 , NULL , NULL , SPI3 , SPI4 , SPI5 , SPI6 };
46
+ STATIC SPI1_Type * aux_spi [NUM_SPI ] = {NULL , SPI1 , SPI2 , NULL , NULL , NULL , NULL };
47
+ #else
48
+ #define NUM_SPI (3)
49
+ STATIC SPI0_Type * spi [NUM_SPI ] = {SPI0 , NULL , NULL };
50
+ STATIC SPI1_Type * aux_spi [NUM_SPI ] = {NULL , SPI1 , SPI2 };
51
+ #endif
52
+
53
+ STATIC bool never_reset_spi [NUM_SPI ];
54
+ STATIC bool spi_in_use [NUM_SPI ];
40
55
41
56
void reset_spi (void ) {
42
- for (size_t i = 0 ; i < 2 ; i ++ ) {
57
+ for (size_t i = 0 ; i < NUM_SPI ; i ++ ) {
43
58
if (never_reset_spi [i ]) {
44
59
continue ;
45
60
}
46
61
47
- // TODO
62
+ if (i == 1 || i == 2 ) {
63
+ if (i == 1 ) {
64
+ AUX -> ENABLES_b .SPI_1 = false;
65
+ } else {
66
+ AUX -> ENABLES_b .SPI_2 = false;
67
+ }
68
+ aux_spi [i ]-> CNTL0 = 0 ;
69
+ } else {
70
+ // Set CS back to default. All 0 except read enable.
71
+ spi [i ]-> CS = SPI0_CS_REN_Msk ;
72
+ }
73
+
74
+ spi_in_use [i ] = false;
48
75
}
49
76
}
50
77
51
78
void common_hal_busio_spi_construct (busio_spi_obj_t * self ,
52
79
const mcu_pin_obj_t * clock , const mcu_pin_obj_t * mosi ,
53
80
const mcu_pin_obj_t * miso ) {
81
+ size_t instance_index = NUM_SPI ;
82
+ BP_Function_Enum clock_alt = 0 ;
83
+ BP_Function_Enum mosi_alt = 0 ;
84
+ BP_Function_Enum miso_alt = 0 ;
85
+ for (size_t i = 0 ; i < NUM_SPI ; i ++ ) {
86
+ if (spi_in_use [i ]) {
87
+ continue ;
88
+ }
89
+ if (!pin_find_alt (clock , PIN_FUNCTION_SPI , i , SPI_FUNCTION_SCLK , & clock_alt )) {
90
+ continue ;
91
+ }
92
+ if (mosi != NULL && !pin_find_alt (mosi , PIN_FUNCTION_SPI , i , SPI_FUNCTION_MOSI , & mosi_alt )) {
93
+ continue ;
94
+ }
95
+ if (miso != NULL && !pin_find_alt (miso , PIN_FUNCTION_SPI , i , SPI_FUNCTION_MISO , & miso_alt )) {
96
+ continue ;
97
+ }
98
+ instance_index = i ;
99
+ break ;
100
+ }
101
+ if (instance_index == NUM_SPI ) {
102
+ mp_raise_ValueError (translate ("Invalid pins" ));
103
+ }
104
+
105
+ self -> clock = clock ;
106
+ self -> MOSI = mosi ;
107
+ self -> MISO = miso ;
108
+ self -> index = instance_index ;
109
+ spi_in_use [instance_index ] = true;
110
+
111
+
112
+ if (instance_index == 1 ) {
113
+ AUX -> ENABLES_b .SPI_1 = true;
114
+ } else if (instance_index == 2 ) {
115
+ AUX -> ENABLES_b .SPI_2 = true;
116
+ }
117
+
118
+ common_hal_busio_spi_configure (self , 250000 , 0 , 0 , 8 );
54
119
120
+ COMPLETE_MEMORY_READS ;
121
+ gpio_set_pull (clock -> number , BP_PULL_NONE );
122
+ gpio_set_function (clock -> number , clock_alt );
123
+ if (mosi != NULL ) {
124
+ gpio_set_pull (mosi -> number , BP_PULL_NONE );
125
+ gpio_set_function (mosi -> number , mosi_alt );
126
+ }
127
+ if (miso != NULL ) {
128
+ gpio_set_pull (miso -> number , BP_PULL_NONE );
129
+ gpio_set_function (miso -> number , miso_alt );
130
+ }
55
131
}
56
132
57
133
void common_hal_busio_spi_never_reset (busio_spi_obj_t * self ) {
58
- // never_reset_spi[spi_get_index( self->peripheral) ] = true;
134
+ never_reset_spi [self -> index ] = true;
59
135
60
136
common_hal_never_reset_pin (self -> clock );
61
137
common_hal_never_reset_pin (self -> MOSI );
@@ -70,12 +146,22 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
70
146
if (common_hal_busio_spi_deinited (self )) {
71
147
return ;
72
148
}
73
- // never_reset_spi[spi_get_index( self->peripheral) ] = false;
149
+ never_reset_spi [self -> index ] = false;
74
150
75
151
common_hal_reset_pin (self -> clock );
76
152
common_hal_reset_pin (self -> MOSI );
77
153
common_hal_reset_pin (self -> MISO );
78
154
self -> clock = NULL ;
155
+
156
+ if (self -> index == 1 ||
157
+ self -> index == 2 ) {
158
+ aux_spi [self -> index ]-> CNTL0_b .ENABLE = false;
159
+ if (self -> index == 1 ) {
160
+ AUX -> ENABLES_b .SPI_1 = false;
161
+ } else if (self -> index == 2 ) {
162
+ AUX -> ENABLES_b .SPI_2 = false;
163
+ }
164
+ }
79
165
}
80
166
81
167
bool common_hal_busio_spi_configure (busio_spi_obj_t * self ,
@@ -87,13 +173,40 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self,
87
173
return true;
88
174
}
89
175
90
- // TODO
176
+ if (self -> index == 1 || self -> index == 2 ) {
177
+ SPI1_Type * p = aux_spi [self -> index ];
178
+ uint32_t source_clock = vcmailbox_get_clock_rate_measured (VCMAILBOX_CLOCK_CORE );
179
+ uint16_t clock_divider = source_clock / baudrate ;
180
+ if (source_clock % baudrate > 0 ) {
181
+ clock_divider += 2 ;
182
+ }
183
+
184
+ p -> CNTL0 = (clock_divider / 2 - 1 ) << SPI1_CNTL0_SPEED_Pos |
185
+ SPI1_CNTL0_ENABLE_Msk |
186
+ SPI1_CNTL0_MSB_FIRST_Msk |
187
+ (polarity == 1 ? SPI1_CNTL0_INVERT_CLK_Msk : 0 ) |
188
+ (phase == polarity ? SPI1_CNTL0_IN_RISING_Msk : SPI1_CNTL0_OUT_RISING_Msk ) |
189
+ 8 << SPI1_CNTL0_SHIFT_LENGTH_Pos ;
190
+ p -> CNTL1 = SPI1_CNTL1_MSB_FIRST_Msk ;
191
+ self -> real_frequency = source_clock / clock_divider ;
192
+ } else {
193
+ SPI0_Type * p = spi [self -> index ];
194
+ p -> CS = polarity << SPI0_CS_CPOL_Pos |
195
+ phase << SPI0_CS_CPHA_Pos ;
196
+ uint32_t source_clock = vcmailbox_get_clock_rate_measured (VCMAILBOX_CLOCK_CORE );
197
+ uint16_t clock_divider = source_clock / baudrate ;
198
+ if (source_clock % baudrate > 0 ) {
199
+ clock_divider += 2 ;
200
+ }
201
+
202
+ p -> CLK = clock_divider ;
203
+ self -> real_frequency = source_clock / clock_divider ;
204
+ }
91
205
92
206
self -> polarity = polarity ;
93
207
self -> phase = phase ;
94
208
self -> bits = bits ;
95
209
self -> target_frequency = baudrate ;
96
- self -> real_frequency = baudrate ; // TODO
97
210
98
211
return true;
99
212
}
@@ -115,18 +228,103 @@ void common_hal_busio_spi_unlock(busio_spi_obj_t *self) {
115
228
self -> has_lock = false;
116
229
}
117
230
231
+ STATIC void _spi_transfer (SPI0_Type * p ,
232
+ const uint8_t * data_out , size_t out_len ,
233
+ uint8_t * data_in , size_t in_len ) {
234
+ size_t len = MAX (out_len , in_len );
235
+ COMPLETE_MEMORY_READS ;
236
+ p -> DLEN = len ;
237
+ p -> CS |= SPI0_CS_TA_Msk | SPI0_CS_CLEAR_Msk ;
238
+ size_t in = 0 ;
239
+ size_t out = 0 ;
240
+ while (in < len ) {
241
+ while (out < len && p -> CS_b .TXD == 1 ) {
242
+ if (out_len == 1 ) {
243
+ p -> FIFO = data_out [0 ];
244
+ } else {
245
+ p -> FIFO = data_out [out ];
246
+ }
247
+ out ++ ;
248
+ }
249
+ // Wait for data to read (also means data has been sent.)
250
+ while (p -> CS_b .RXD == 0 ) {
251
+ RUN_BACKGROUND_TASKS ;
252
+ }
253
+ while (p -> CS_b .RXD == 1 ) {
254
+ uint8_t data = p -> FIFO ;
255
+ if (data_in != NULL ) {
256
+ data_in [in ] = data ;
257
+ } else {
258
+ (void )data ;
259
+ }
260
+ in ++ ;
261
+ }
262
+ }
263
+ p -> CS_b .TA = false;
264
+ COMPLETE_MEMORY_READS ;
265
+ }
266
+
267
+ STATIC void _aux_spi_transfer (SPI1_Type * p ,
268
+ const uint8_t * data_out , size_t out_len ,
269
+ uint8_t * data_in , size_t in_len ) {
270
+ size_t len = MAX (out_len , in_len );
271
+ p -> CNTL0 |= SPI1_CNTL0_CLEAR_FIFOS_Msk ;
272
+ p -> CNTL0 &= ~SPI1_CNTL0_CLEAR_FIFOS_Msk ;
273
+ size_t in = 0 ;
274
+ size_t out = 0 ;
275
+ while (in < len ) {
276
+ while (out < len && p -> STAT_b .TX_FULL == 0 ) {
277
+ if (out_len == 1 ) {
278
+ p -> TXHOLD0 = data_out [0 ] << 24 ;
279
+ } else {
280
+ p -> TXHOLD0 = data_out [out ] << 24 ;
281
+ }
282
+ out ++ ;
283
+ }
284
+ // Wait for data to read (also means data has been sent.)
285
+ while (p -> STAT_b .RX_EMPTY == 1 ) {
286
+ RUN_BACKGROUND_TASKS ;
287
+ }
288
+ while (p -> STAT_b .RX_EMPTY == 0 ) {
289
+ uint8_t data = p -> TXHOLD0 ;
290
+ if (data_in != NULL ) {
291
+ data_in [in ] = data ;
292
+ } else {
293
+ (void )data ;
294
+ }
295
+ in ++ ;
296
+ }
297
+ }
298
+ }
299
+
118
300
bool common_hal_busio_spi_write (busio_spi_obj_t * self ,
119
301
const uint8_t * data , size_t len ) {
120
- return false;
302
+ if (self -> index == 1 || self -> index == 2 ) {
303
+ _aux_spi_transfer (aux_spi [self -> index ], data , len , NULL , 0 );
304
+ } else {
305
+ _spi_transfer (spi [self -> index ], data , len , NULL , 0 );
306
+ }
307
+ return true;
121
308
}
122
309
123
310
bool common_hal_busio_spi_read (busio_spi_obj_t * self ,
124
311
uint8_t * data , size_t len , uint8_t write_value ) {
125
- return false;
312
+ if (self -> index == 1 || self -> index == 2 ) {
313
+ _aux_spi_transfer (aux_spi [self -> index ], & write_value , 1 , data , len );
314
+ } else {
315
+ _spi_transfer (spi [self -> index ], & write_value , 1 , data , len );
316
+ }
317
+ return true;
126
318
}
127
319
128
- bool common_hal_busio_spi_transfer (busio_spi_obj_t * self , const uint8_t * data_out , uint8_t * data_in , size_t len ) {
129
- return false;
320
+ bool common_hal_busio_spi_transfer (busio_spi_obj_t * self ,
321
+ const uint8_t * data_out , uint8_t * data_in , size_t len ) {
322
+ if (self -> index == 1 || self -> index == 2 ) {
323
+ _aux_spi_transfer (aux_spi [self -> index ], data_out , len , data_in , len );
324
+ } else {
325
+ _spi_transfer (spi [self -> index ], data_out , len , data_in , len );
326
+ }
327
+ return true;
130
328
}
131
329
132
330
uint32_t common_hal_busio_spi_get_frequency (busio_spi_obj_t * self ) {
0 commit comments