|
31 | 31 | #include "nrfx_spim.h"
|
32 | 32 | #include "nrf_gpio.h"
|
33 | 33 |
|
34 |
| -// These are in order from ighest available frequency to lowest (32MHz first, then 8MHz). |
| 34 | +// These are in order from highest available frequency to lowest (32MHz first, then 8MHz). |
35 | 35 | STATIC spim_peripheral_t spim_peripherals[] = {
|
36 | 36 | #if NRFX_CHECK(NRFX_SPIM3_ENABLED)
|
37 | 37 | // SPIM3 exists only on nRF52840 and supports 32MHz max. All other SPIM's are only 8MHz max.
|
38 | 38 | // Allocate SPIM3 first.
|
39 | 39 | { .spim = NRFX_SPIM_INSTANCE(3),
|
40 | 40 | .max_frequency = 32000000,
|
41 |
| - .max_xfer_size = SPIM3_EASYDMA_MAXCNT_SIZE, |
| 41 | + .max_xfer_size = MIN(SPIM3_BUFFER_SIZE, (1UL << SPIM3_EASYDMA_MAXCNT_SIZE) - 1) |
42 | 42 | },
|
43 | 43 | #endif
|
44 | 44 | #if NRFX_CHECK(NRFX_SPIM2_ENABLED)
|
45 | 45 | // SPIM2 is not shared with a TWIM, so allocate before the shared ones.
|
46 | 46 | { .spim = NRFX_SPIM_INSTANCE(2),
|
47 | 47 | .max_frequency = 8000000,
|
48 |
| - .max_xfer_size = SPIM2_EASYDMA_MAXCNT_SIZE, |
| 48 | + .max_xfer_size = (1UL << SPIM2_EASYDMA_MAXCNT_SIZE) - 1 |
49 | 49 | },
|
50 | 50 | #endif
|
51 | 51 | #if NRFX_CHECK(NRFX_SPIM1_ENABLED)
|
52 | 52 | // SPIM1 and TWIM1 share an address.
|
53 | 53 | { .spim = NRFX_SPIM_INSTANCE(1),
|
54 | 54 | .max_frequency = 8000000,
|
55 |
| - .max_xfer_size = SPIM1_EASYDMA_MAXCNT_SIZE, |
| 55 | + .max_xfer_size = (1UL << SPIM1_EASYDMA_MAXCNT_SIZE) - 1 |
56 | 56 | },
|
57 | 57 | #endif
|
58 | 58 | #if NRFX_CHECK(NRFX_SPIM0_ENABLED)
|
59 | 59 | // SPIM0 and TWIM0 share an address.
|
60 | 60 | { .spim = NRFX_SPIM_INSTANCE(0),
|
61 | 61 | .max_frequency = 8000000,
|
62 |
| - .max_xfer_size = SPIM0_EASYDMA_MAXCNT_SIZE, |
| 62 | + .max_xfer_size = (1UL << SPIM0_EASYDMA_MAXCNT_SIZE) - 1 |
63 | 63 | },
|
64 | 64 | #endif
|
65 | 65 | };
|
@@ -232,104 +232,66 @@ void common_hal_busio_spi_unlock(busio_spi_obj_t *self) {
|
232 | 232 | }
|
233 | 233 |
|
234 | 234 | bool common_hal_busio_spi_write(busio_spi_obj_t *self, const uint8_t *data, size_t len) {
|
235 |
| - if (len == 0) { |
236 |
| - return true; |
237 |
| - } |
238 |
| - |
239 | 235 | const bool is_spim3 = self->spim_peripheral->spim.p_reg == NRF_SPIM3;
|
| 236 | + uint8_t *next_chunk = (uint8_t *) data; |
240 | 237 |
|
241 |
| - const uint32_t max_xfer_size = self->spim_peripheral->max_xfer_size; |
242 |
| - const uint32_t parts = len / max_xfer_size; |
243 |
| - const uint32_t remainder = len % max_xfer_size; |
244 |
| - |
245 |
| - for (uint32_t i = 0; i < parts; ++i) { |
246 |
| - uint8_t *start = (uint8_t *) (data + i * max_xfer_size); |
| 238 | + while (len > 0) { |
| 239 | + size_t chunk_size = MIN(len, self->spim_peripheral->max_xfer_size); |
| 240 | + uint8_t *chunk = next_chunk; |
247 | 241 | if (is_spim3) {
|
248 | 242 | // If SPIM3, copy into unused RAM block, and do DMA from there.
|
249 |
| - memcpy(spim3_transmit_buffer, start, max_xfer_size); |
250 |
| - start = spim3_transmit_buffer; |
| 243 | + memcpy(spim3_transmit_buffer, chunk, chunk_size); |
| 244 | + chunk = spim3_transmit_buffer; |
251 | 245 | }
|
252 |
| - const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX(start, max_xfer_size); |
253 |
| - if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS) |
| 246 | + const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX(chunk, chunk_size); |
| 247 | + if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS) { |
254 | 248 | return false;
|
255 |
| - } |
256 |
| - |
257 |
| - if (remainder > 0) { |
258 |
| - uint8_t *start = (uint8_t *) (data + parts * max_xfer_size); |
259 |
| - if (is_spim3) { |
260 |
| - // If SPIM3, copy into unused RAM block, and do DMA from there. |
261 |
| - memcpy(spim3_transmit_buffer, start, remainder); |
262 |
| - start = spim3_transmit_buffer; |
263 | 249 | }
|
264 |
| - const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_TX(start, remainder); |
265 |
| - if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS) |
266 |
| - return false; |
| 250 | + next_chunk += chunk_size; |
| 251 | + len -= chunk_size; |
267 | 252 | }
|
268 |
| - |
269 | 253 | return true;
|
270 | 254 | }
|
271 | 255 |
|
272 | 256 | bool common_hal_busio_spi_read(busio_spi_obj_t *self, uint8_t *data, size_t len, uint8_t write_value) {
|
273 |
| - if (len == 0) { |
274 |
| - return true; |
275 |
| - } |
276 |
| - |
277 |
| - const uint32_t max_xfer_size = self->spim_peripheral->max_xfer_size; |
278 |
| - const uint32_t parts = len / max_xfer_size; |
279 |
| - const uint32_t remainder = len % max_xfer_size; |
280 |
| - |
281 |
| - for (uint32_t i = 0; i < parts; ++i) { |
282 |
| - const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX(data + i * max_xfer_size, max_xfer_size); |
283 |
| - if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS) |
284 |
| - return false; |
285 |
| - } |
| 257 | + uint8_t *next_chunk = data; |
286 | 258 |
|
287 |
| - if (remainder > 0) { |
288 |
| - const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX(data + parts * max_xfer_size, remainder); |
289 |
| - if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS) |
| 259 | + while (len > 0) { |
| 260 | + size_t chunk_size = MIN(len, self->spim_peripheral->max_xfer_size); |
| 261 | + const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_XFER_RX(next_chunk, chunk_size); |
| 262 | + if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS) { |
290 | 263 | return false;
|
| 264 | + } |
| 265 | + next_chunk += chunk_size; |
| 266 | + len -= chunk_size; |
291 | 267 | }
|
292 |
| - |
293 | 268 | return true;
|
294 | 269 | }
|
295 | 270 |
|
296 | 271 | bool common_hal_busio_spi_transfer(busio_spi_obj_t *self, uint8_t *data_out, uint8_t *data_in, size_t len) {
|
297 |
| - if (len == 0) { |
298 |
| - return true; |
299 |
| - } |
300 |
| - |
301 | 272 | const bool is_spim3 = self->spim_peripheral->spim.p_reg == NRF_SPIM3;
|
| 273 | + uint8_t *next_chunk_out = data_out; |
| 274 | + uint8_t *next_chunk_in = data_in; |
302 | 275 |
|
303 |
| - const uint32_t max_xfer_size = self->spim_peripheral->max_xfer_size; |
304 |
| - const uint32_t parts = len / max_xfer_size; |
305 |
| - const uint32_t remainder = len % max_xfer_size; |
306 |
| - |
307 |
| - for (uint32_t i = 0; i < parts; ++i) { |
308 |
| - uint8_t *out_start = (uint8_t *) (data_out + i * max_xfer_size); |
| 276 | + while (len > 0) { |
| 277 | + uint8_t *chunk_out = next_chunk_out; |
| 278 | + size_t chunk_size = MIN(len, self->spim_peripheral->max_xfer_size); |
309 | 279 | if (is_spim3) {
|
310 | 280 | // If SPIM3, copy into unused RAM block, and do DMA from there.
|
311 |
| - memcpy(spim3_transmit_buffer, out_start, max_xfer_size); |
312 |
| - out_start = spim3_transmit_buffer; |
| 281 | + memcpy(spim3_transmit_buffer, chunk_out, chunk_size); |
| 282 | + chunk_out = spim3_transmit_buffer; |
313 | 283 | }
|
314 |
| - const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER(out_start, max_xfer_size, |
315 |
| - data_in + i * max_xfer_size, max_xfer_size); |
316 |
| - if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS) |
| 284 | + const nrfx_spim_xfer_desc_t xfer = |
| 285 | + NRFX_SPIM_SINGLE_XFER(next_chunk_out, chunk_size, |
| 286 | + next_chunk_in, chunk_size); |
| 287 | + if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS) { |
317 | 288 | return false;
|
318 |
| - } |
319 |
| - |
320 |
| - if (remainder > 0) { |
321 |
| - uint8_t *out_start = (uint8_t *) (data_out + parts * max_xfer_size); |
322 |
| - if (is_spim3) { |
323 |
| - // If SPIM3, copy into unused RAM block, and do DMA from there. |
324 |
| - memcpy(spim3_transmit_buffer, out_start, remainder); |
325 |
| - out_start = spim3_transmit_buffer; |
326 | 289 | }
|
327 |
| - const nrfx_spim_xfer_desc_t xfer = NRFX_SPIM_SINGLE_XFER(out_start, remainder, |
328 |
| - data_in + parts * max_xfer_size, remainder); |
329 |
| - if (nrfx_spim_xfer(&self->spim_peripheral->spim, &xfer, 0) != NRFX_SUCCESS) |
330 |
| - return false; |
331 |
| - } |
332 | 290 |
|
| 291 | + next_chunk_out += chunk_size; |
| 292 | + next_chunk_in += chunk_size; |
| 293 | + len -= chunk_size; |
| 294 | + } |
333 | 295 | return true;
|
334 | 296 | }
|
335 | 297 |
|
|
0 commit comments