This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

SPI delays between writes

I am currently using the 17.0.2 SDK to develop some code on the nrf52832 which involves streaming data via SPI to an external flash.  I need to stream this data at a ~50KHz rate.  The data to the flash consists of the write command (8bits) followed by the data (16bits), after which the write happens and the cycle is repeated.  I wrote some code to do this using the library functions.  The first code asserted CE once again after the data transfer and looked at the MISO pin (memory write status from the chip) to see when the write cycle was done (first picture).  I then modified the code to simply delay while the write cycle was happening (second picture).  As you can see in the pictures below, there is a very large amount of time that is "wasted" in both scenarios.  In particular, in the second scenario, there is a large amount of time where CE is low before the data is transferred and the again when CE is low after the data has been transferred.  These delays are such that I cannot meet the target rate.  In order to meet my target data rate I need to reduce these delays.  Are there things I can do in the library to reduce those delays or do I need to write my own SPI code?  This streaming code will likely run in the foreground and therefore can be blocking while it is running if it has to be.  Please let me know the best way to increase my data throughput.  Thanks!

SPI write with handshake

SPI write no handshake (timing only)

Parents Reply Children
  • He used the api nRF5_SDK_17.0.2_d674dde/integration/nrfx/legacy/nrf_drv_spi.h, add #include "nrf_drv_spi.h" at the top of you file. Also check out the the driver description of SPI Master in the documentation: https://infocenter.nordicsemi.com/index.jsp?topic=%2Fsdk_nrf5_v17.0.2%2Fhardware_driver_spi_master.html&cp=8_1_2_0_13 

    Best regards,
    Simon
  • Hi Simon,

    I am having trouble seeing any difference between what you are recommending and what I am currently doing.  I have always had #include nrf_drv_spi.h" as part of my file and I call the nrf_drv_spi_transfer just as it says in the link you provided (see line below).  It looks to me like I have been doing what you said and what is indicated in the link but this is what is giving me the long delays.

    APP_ERROR_CHECK(nrf_drv_spi_transfer(spi_inst, tx_buffer, tx_length, rx_buffer, rx_length));

    Can you please tell me what I might be missing?

    One additional note:  I think it is important to point out the that the delays that I need to get rid are the delay between when CE is asserted and when the data transmission starts, and the delay between when the data transmission has ended and CE is deasserted. These delays can be seen by referring to the second of the timing pictures at the start of this thread.

    Thanks,

    Tim

  • Simon,

    Since I didn't hear back from you I dug into the source code a bit and found that if I pass a NULL for the interrupt handler it will run as blocking code.  Running the code in blocking mode provides about a 15% speed increase, but the delay between /CE being asserted and data coming out, and the delay between data finishing and /CE being deasertted are still way to long.  Do you know why there is such latency?  Is there a way to remove that latency?  I am under a bit of time pressure so a prompt response would be greatly appreciated.

    Tim

  • Hi Tim,

    There is no direct hardware control of the CE pin when using SPI, so the application will need to handle the CE pin manually, typically there will be some delays due to the way it's implemented. E.g. there will interrupt latencies here du to possible wakeup before and after the SPI transfer, and possible delay due to the SoC framework if the softdevice is enabled and need to forward the interrupt to the application, not to mention some delay due to code execution handling the interrupt. Adding these up you may experience several us of delay before and after SPI transcation and CE pin. 

    The only real way to reduce this is to use PPI to handle the CE pin and SPI transcation. There is a discussion in this case how this can be done:
    https://devzone.nordicsemi.com/f/nordic-q-a/13523/ppi-to-spim-task-how-to

    Alternatively use the nRF52840 which have an SPIM3 interface with CE handling in hardware.

    Kenneth

  • Hi Kenneth,

    Thank you for the answer.  I understand your explanation.  Fortunately, running the SPI in blocking mode gets me just under my bandwidth limit, so I should be good to go.  However, I do have one additional question.  In my trying to optimize the CE assertion timing I put a bunch of set/clear commands together to see what the maximum GPIO toggle rate was.  If I remember right it was about 2uS per transition.  This seemed slower than I expected.  I am very new to the ARM architecture so my question might be ignorant, but I was wondering if there was a way to get faster IO response by changing the peripheral clock speed to the IO or by some other means.

    Thanks for your help,

    Tim

Related