2727#include "nrfx_spim.h"
2828#include "nrf_gpio.h"
2929
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+ },
3438#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+ };
3761
3862// Convert frequency to clock-speed-dependent value
3963static nrf_spim_frequency_t baudrate_to_spim_frequency (const uint32_t baudrate ) {
40- if (baudrate <= 125000 )
64+ if (baudrate <= 125000 ) {
4165 return NRF_SPIM_FREQ_125K ;
42-
43- if (baudrate <= 250000 )
66+ }
67+ if (baudrate <= 250000 ) {
4468 return NRF_SPIM_FREQ_250K ;
45-
46- if (baudrate <= 500000 )
69+ }
70+ if (baudrate <= 500000 ) {
4771 return NRF_SPIM_FREQ_500K ;
48-
49- if (baudrate <= 1000000 )
72+ }
73+ if (baudrate <= 1000000 ) {
5074 return NRF_SPIM_FREQ_1M ;
51-
52- if (baudrate <= 2000000 )
75+ }
76+ if (baudrate <= 2000000 ) {
5377 return NRF_SPIM_FREQ_2M ;
54-
55- if (baudrate <= 4000000 )
78+ }
79+ if (baudrate <= 4000000 ) {
5680 return NRF_SPIM_FREQ_4M ;
57-
58- if (baudrate <= 8000000 )
81+ }
82+ if (baudrate <= 8000000 ) {
5983 return NRF_SPIM_FREQ_8M ;
60-
84+ }
6185#ifdef SPIM_FREQUENCY_FREQUENCY_M16
62- if (baudrate <= 16000000 )
86+ if (baudrate <= 16000000 ) {
6387 return NRF_SPIM_FREQ_16M ;
88+ }
6489#endif
6590
6691#ifdef SPIM_FREQUENCY_FREQUENCY_M32
@@ -71,8 +96,18 @@ static nrf_spim_frequency_t baudrate_to_spim_frequency(const uint32_t baudrate)
7196}
7297
7398void 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+ }
76111
77112 nrfx_spim_config_t config = NRFX_SPIM_DEFAULT_CONFIG ;
78113 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 *
97132 self -> MISO_pin_number = NO_PIN ;
98133 }
99134
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 );
101136
102137 // A soft reset doesn't uninit the driver so we might end up with a invalid state
103138 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 );
106141 }
107142
108143 if (err != NRFX_SUCCESS ) {
@@ -119,7 +154,7 @@ void common_hal_busio_spi_deinit(busio_spi_obj_t *self) {
119154 if (common_hal_busio_spi_deinited (self ))
120155 return ;
121156
122- nrfx_spim_uninit (& self -> spim );
157+ nrfx_spim_uninit (& self -> spim_peripheral -> spim );
123158
124159 reset_pin_number (self -> clock_pin_number );
125160 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
131166 if (bits != 8 )
132167 return false;
133168
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 ));
135174
136175 nrf_spim_mode_t mode = NRF_SPIM_MODE_0 ;
137176 if (polarity ) {
@@ -140,7 +179,7 @@ bool common_hal_busio_spi_configure(busio_spi_obj_t *self, uint32_t baudrate, ui
140179 mode = (phase ) ? NRF_SPIM_MODE_1 : NRF_SPIM_MODE_0 ;
141180 }
142181
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 );
144183
145184 return true;
146185}
@@ -168,18 +207,19 @@ bool common_hal_busio_spi_write(busio_spi_obj_t *self, const uint8_t *data, size
168207 if (len == 0 )
169208 return true;
170209
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 ;
173213
174214 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 )
177217 return false;
178218 }
179219
180220 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 )
183223 return false;
184224 }
185225
@@ -190,18 +230,19 @@ bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len,
190230 if (len == 0 )
191231 return true;
192232
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 ;
195236
196237 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 )
199240 return false;
200241 }
201242
202243 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 )
205246 return false;
206247 }
207248
@@ -212,28 +253,30 @@ bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uin
212253 if (len == 0 )
213254 return true;
214255
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 ;
217260
218261 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 )
222265 return false;
223266 }
224267
225268 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 )
229272 return false;
230273 }
231274
232275 return true;
233276}
234277
235278uint32_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 ) {
237280 case NRF_SPIM_FREQ_125K :
238281 return 125000 ;
239282 case NRF_SPIM_FREQ_250K :
0 commit comments