nrf_drv_spi_transfer larger transfer size


I'm working with an SPI FLASH chip that has a page size 256. I noticed that when I call nrf_drv_spi_transfer(), the rx length of 256 rolls over the uint8_t container and is zero!

Digging deeper, I found that the RX size is used for nrf_spim_rx_buffer_set(), also taking the argument as uint8_t. This function sets p_spim->RXD.MAXCNT = length; MAXCNT is size uint32_t. Is there a reason I shouldn't mess with these sizes?

I'm also thinking I'd need a tx buffer size at least 256 to write a page at a time.

  • RXD.MAXCNT isn't 32 bit, only the lower 8 bits are used (see manual), which is why it's limited to 255 bytes and a uint8_t. You can use list mode with repeated transfers, or you can write something which doesn't use EasyDMA if you want to do more, or you can go 255 bytes at a time.

  • Somebody wasn't thinking this through at design time. For example with a nrf51 design I'm doing ~512 byte SPI transactions to clock pixels out to an oled display. The amount of CPU overhead to clock out one display frame is rather sad. With a nrf52 based design I am planning on using a display with 2x or 4x the pixels. Only 8 bits on MAXCNT and AMOUNT seems way too small, it isn't even enough to write a full page of a cheap SPI flash part. At 55nm how many picocents would it have cost to add a few more bits on the EasyDMA counters?

    Yes, I know I can use the list feature, but it seems like un-necessary extra complexity that could have been trivially fixed at design time with a few more counter bits.

  • I just ran into the same issue, but on an nRF51 without the EasyDMA limitation. I ported code from against an older SDK to SDK 10, and am transferring a 520 bytes stream from a SPI slave.

    I have changed the nrf_drv_spi uint8_t to uint16_t in a few spots as when using programmed I/O (i.e. byte-by-byte, driven by the CPU) there is no limitation in the SPI message lengths.

    I agree that silicon should have provided 256+ lengths.

    Also, it is a pity that driving the CS# line is not something the SPI or DMA can do.

    In another application where I am driving a 16-bit DAC, I have to toggle the CS# line active every other byte. I am doing this through the CPU. Both the PPI and DMA (on nRF52) do not seem to help me here.

    (I have tried the PPI, but as it every other byte, enabling/disabling PPI takes as much CPU synchronization as does toggling CS#).

  • Leon, if I understood correctly you managed to modify the driver to accept 16bits lengths? That seems not possible given that only 8bits are used in the RXD.MAXCNT register. Can you please give more info about your changes? I am new to nRF52. Thanks!

    I managed to use the List feature: