27
27
#include "nrfx_spim.h"
28
28
#include "nrf_gpio.h"
29
29
30
- #if NRFX_SPIM3_ENABLED
31
- #define INST_NO 3
32
- #else
33
- #define INST_NO 2
30
+ STATIC spim_peripheral_t spim_peripherals [] = {
31
+ #if NRFX_CHECK (NRFX_SPIM3_ENABLED )
32
+ // SPIM3 exists only on nRF52840 and supports 32MHz max. All other SPIM's are only 8MHz max.
33
+ // Allocate SPIM3 first.
34
+ { .spim = NRFX_SPIM_INSTANCE (3 ),
35
+ .max_frequency_MHz = 32 ,
36
+ .max_xfer_size = SPIM3_EASYDMA_MAXCNT_SIZE ,
37
+ },
34
38
#endif
35
-
36
- #define MAX_XFER_SIZE ((1U << NRFX_CONCAT_3(SPIM, INST_NO, _EASYDMA_MAXCNT_SIZE)) - 1)
39
+ #if NRFX_CHECK (NRFX_SPIM2_ENABLED )
40
+ // SPIM2 is not shared with a TWIM, so allocate before the shared ones.
41
+ { .spim = NRFX_SPIM_INSTANCE (2 ),
42
+ .max_frequency_MHz = 8 ,
43
+ .max_xfer_size = SPIM2_EASYDMA_MAXCNT_SIZE ,
44
+ },
45
+ #endif
46
+ #if NRFX_CHECK (NRFX_SPIM1_ENABLED )
47
+ // SPIM1 and TWIM1 share an address.
48
+ { .spim = NRFX_SPIM_INSTANCE (1 ),
49
+ .max_frequency_MHz = 8 ,
50
+ .max_xfer_size = SPIM1_EASYDMA_MAXCNT_SIZE ,
51
+ },
52
+ #endif
53
+ #if NRFX_CHECK (NRFX_SPIM0_ENABLED )
54
+ // SPIM0 and TWIM0 share an address.
55
+ { .spim = NRFX_SPIM_INSTANCE (0 ),
56
+ .max_frequency_MHz = 8 ,
57
+ .max_xfer_size = SPIM0_EASYDMA_MAXCNT_SIZE ,
58
+ },
59
+ #endif
60
+ };
37
61
38
62
// Convert frequency to clock-speed-dependent value
39
63
static nrf_spim_frequency_t baudrate_to_spim_frequency (const uint32_t baudrate ) {
40
- if (baudrate <= 125000 )
64
+ if (baudrate <= 125000 ) {
41
65
return NRF_SPIM_FREQ_125K ;
42
-
43
- if (baudrate <= 250000 )
66
+ }
67
+ if (baudrate <= 250000 ) {
44
68
return NRF_SPIM_FREQ_250K ;
45
-
46
- if (baudrate <= 500000 )
69
+ }
70
+ if (baudrate <= 500000 ) {
47
71
return NRF_SPIM_FREQ_500K ;
48
-
49
- if (baudrate <= 1000000 )
72
+ }
73
+ if (baudrate <= 1000000 ) {
50
74
return NRF_SPIM_FREQ_1M ;
51
-
52
- if (baudrate <= 2000000 )
75
+ }
76
+ if (baudrate <= 2000000 ) {
53
77
return NRF_SPIM_FREQ_2M ;
54
-
55
- if (baudrate <= 4000000 )
78
+ }
79
+ if (baudrate <= 4000000 ) {
56
80
return NRF_SPIM_FREQ_4M ;
57
-
58
- if (baudrate <= 8000000 )
81
+ }
82
+ if (baudrate <= 8000000 ) {
59
83
return NRF_SPIM_FREQ_8M ;
60
-
84
+ }
61
85
#ifdef SPIM_FREQUENCY_FREQUENCY_M16
62
- if (baudrate <= 16000000 )
86
+ if (baudrate <= 16000000 ) {
63
87
return NRF_SPIM_FREQ_16M ;
88
+ }
64
89
#endif
65
90
66
91
#ifdef SPIM_FREQUENCY_FREQUENCY_M32
@@ -71,8 +96,18 @@ static nrf_spim_frequency_t baudrate_to_spim_frequency(const uint32_t baudrate)
71
96
}
72
97
73
98
void common_hal_busio_spi_construct (busio_spi_obj_t * self , const mcu_pin_obj_t * clock , const mcu_pin_obj_t * mosi , const mcu_pin_obj_t * miso ) {
74
- const nrfx_spim_t instance = NRFX_SPIM_INSTANCE (INST_NO );
75
- self -> spim = instance ;
99
+ // Find a free instance.
100
+ self -> spim_peripheral = NULL ;
101
+ for (size_t i = 0 ; i < MP_ARRAY_SIZE (spim_peripherals ); i ++ ) {
102
+ if ((spim_peripherals [i ].spim .p_reg -> ENABLE & SPIM_ENABLE_ENABLE_Msk ) == 0 ) {
103
+ self -> spim_peripheral = & spim_peripherals [i ];
104
+ break ;
105
+ }
106
+ }
107
+
108
+ if (self -> spim_peripheral == NULL ) {
109
+ mp_raise_ValueError (translate ("All SPI peripherals are in use" ));
110
+ }
76
111
77
112
nrfx_spim_config_t config = NRFX_SPIM_DEFAULT_CONFIG ;
78
113
config .frequency = NRF_SPIM_FREQ_8M ;
@@ -97,12 +132,12 @@ void common_hal_busio_spi_construct(busio_spi_obj_t *self, const mcu_pin_obj_t *
97
132
self -> MISO_pin_number = NO_PIN ;
98
133
}
99
134
100
- nrfx_err_t err = nrfx_spim_init (& self -> spim , & config , NULL , NULL );
135
+ nrfx_err_t err = nrfx_spim_init (& self -> spim_peripheral -> spim , & config , NULL , NULL );
101
136
102
137
// A soft reset doesn't uninit the driver so we might end up with a invalid state
103
138
if (err == NRFX_ERROR_INVALID_STATE ) {
104
- nrfx_spim_uninit (& self -> spim );
105
- err = nrfx_spim_init (& self -> spim , & config , NULL , NULL );
139
+ nrfx_spim_uninit (& self -> spim_peripheral -> spim );
140
+ err = nrfx_spim_init (& self -> spim_peripheral -> spim , & config , NULL , NULL );
106
141
}
107
142
108
143
if (err != NRFX_SUCCESS ) {
@@ -119,7 +154,7 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
119
154
if (common_hal_busio_spi_deinited (self ))
120
155
return ;
121
156
122
- nrfx_spim_uninit (& self -> spim );
157
+ nrfx_spim_uninit (& self -> spim_peripheral -> spim );
123
158
124
159
reset_pin_number (self -> clock_pin_number );
125
160
reset_pin_number (self -> MOSI_pin_number );
@@ -131,7 +166,11 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, ui
131
166
if (bits != 8 )
132
167
return false;
133
168
134
- nrf_spim_frequency_set (self -> spim .p_reg , baudrate_to_spim_frequency (baudrate ));
169
+ if (baudrate > self -> spim_peripheral -> max_frequency_MHz * 1000000 ) {
170
+ mp_raise_ValueError (translate ("Baud rate too high for this SPI peripheral" ));
171
+ return false;
172
+ }
173
+ nrf_spim_frequency_set (self -> spim_peripheral -> spim .p_reg , baudrate_to_spim_frequency (baudrate ));
135
174
136
175
nrf_spim_mode_t mode = NRF_SPIM_MODE_0 ;
137
176
if (polarity ) {
@@ -140,7 +179,7 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, ui
140
179
mode = (phase ) ? NRF_SPIM_MODE_1 : NRF_SPIM_MODE_0 ;
141
180
}
142
181
143
- nrf_spim_configure (self -> spim .p_reg , mode , NRF_SPIM_BIT_ORDER_MSB_FIRST );
182
+ nrf_spim_configure (self -> spim_peripheral -> spim .p_reg , mode , NRF_SPIM_BIT_ORDER_MSB_FIRST );
144
183
145
184
return true;
146
185
}
@@ -168,18 +207,19 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self, const uint8_t *data, size
168
207
if (len == 0 )
169
208
return true;
170
209
171
- const uint32_t parts = len / MAX_XFER_SIZE ;
172
- const uint32_t remainder = len % MAX_XFER_SIZE ;
210
+ const uint32_t max_xfer_size = self -> spim_peripheral -> max_xfer_size ;
211
+ const uint32_t parts = len / max_xfer_size ;
212
+ const uint32_t remainder = len % max_xfer_size ;
173
213
174
214
for (uint32_t i = 0 ; i < parts ; ++ i ) {
175
- const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX (data + i * MAX_XFER_SIZE , MAX_XFER_SIZE );
176
- if (nrfx_spim_xfer (& self -> spim , & xfer , 0 ) != NRFX_SUCCESS )
215
+ const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX (data + i * max_xfer_size , max_xfer_size );
216
+ if (nrfx_spim_xfer (& self -> spim_peripheral -> spim , & xfer , 0 ) != NRFX_SUCCESS )
177
217
return false;
178
218
}
179
219
180
220
if (remainder > 0 ) {
181
- const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX (data + parts * MAX_XFER_SIZE , remainder );
182
- if (nrfx_spim_xfer (& self -> spim , & xfer , 0 ) != NRFX_SUCCESS )
221
+ const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX (data + parts * max_xfer_size , remainder );
222
+ if (nrfx_spim_xfer (& self -> spim_peripheral -> spim , & xfer , 0 ) != NRFX_SUCCESS )
183
223
return false;
184
224
}
185
225
@@ -190,18 +230,19 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len,
190
230
if (len == 0 )
191
231
return true;
192
232
193
- const uint32_t parts = len / MAX_XFER_SIZE ;
194
- const uint32_t remainder = len % MAX_XFER_SIZE ;
233
+ const uint32_t max_xfer_size = self -> spim_peripheral -> max_xfer_size ;
234
+ const uint32_t parts = len / max_xfer_size ;
235
+ const uint32_t remainder = len % max_xfer_size ;
195
236
196
237
for (uint32_t i = 0 ; i < parts ; ++ i ) {
197
- const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX (data + i * MAX_XFER_SIZE , MAX_XFER_SIZE );
198
- if (nrfx_spim_xfer (& self -> spim , & xfer , 0 ) != NRFX_SUCCESS )
238
+ const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX (data + i * max_xfer_size , max_xfer_size );
239
+ if (nrfx_spim_xfer (& self -> spim_peripheral -> spim , & xfer , 0 ) != NRFX_SUCCESS )
199
240
return false;
200
241
}
201
242
202
243
if (remainder > 0 ) {
203
- const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX (data + parts * MAX_XFER_SIZE , remainder );
204
- if (nrfx_spim_xfer (& self -> spim , & xfer , 0 ) != NRFX_SUCCESS )
244
+ const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX (data + parts * max_xfer_size , remainder );
245
+ if (nrfx_spim_xfer (& self -> spim_peripheral -> spim , & xfer , 0 ) != NRFX_SUCCESS )
205
246
return false;
206
247
}
207
248
@@ -212,28 +253,30 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin
212
253
if (len == 0 )
213
254
return true;
214
255
215
- const uint32_t parts = len / MAX_XFER_SIZE ;
216
- const uint32_t remainder = len % MAX_XFER_SIZE ;
256
+
257
+ const uint32_t max_xfer_size = self -> spim_peripheral -> max_xfer_size ;
258
+ const uint32_t parts = len / max_xfer_size ;
259
+ const uint32_t remainder = len % max_xfer_size ;
217
260
218
261
for (uint32_t i = 0 ; i < parts ; ++ i ) {
219
- const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER (data_out + i * MAX_XFER_SIZE , MAX_XFER_SIZE ,
220
- data_in + i * MAX_XFER_SIZE , MAX_XFER_SIZE );
221
- if (nrfx_spim_xfer (& self -> spim , & xfer , 0 ) != NRFX_SUCCESS )
262
+ const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER (data_out + i * max_xfer_size , max_xfer_size ,
263
+ data_in + i * max_xfer_size , max_xfer_size );
264
+ if (nrfx_spim_xfer (& self -> spim_peripheral -> spim , & xfer , 0 ) != NRFX_SUCCESS )
222
265
return false;
223
266
}
224
267
225
268
if (remainder > 0 ) {
226
- const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER (data_out + parts * MAX_XFER_SIZE , remainder ,
227
- data_in + parts * MAX_XFER_SIZE , remainder );
228
- if (nrfx_spim_xfer (& self -> spim , & xfer , 0 ) != NRFX_SUCCESS )
269
+ const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER (data_out + parts * max_xfer_size , remainder ,
270
+ data_in + parts * max_xfer_size , remainder );
271
+ if (nrfx_spim_xfer (& self -> spim_peripheral -> spim , & xfer , 0 ) != NRFX_SUCCESS )
229
272
return false;
230
273
}
231
274
232
275
return true;
233
276
}
234
277
235
278
uint32_t common_hal_busio_spi_get_frequency (busio_spi_obj_t * self ) {
236
- switch (self -> spim .p_reg -> FREQUENCY ) {
279
+ switch (self -> spim_peripheral -> spim .p_reg -> FREQUENCY ) {
237
280
case NRF_SPIM_FREQ_125K :
238
281
return 125000 ;
239
282
case NRF_SPIM_FREQ_250K :
0 commit comments