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

Any ideas on how to decrease SPI overhead time?

With the maximum SPI speed of 8 Mbps, I was expecting to be able to send 2 bytes in just a little over 2 us, but it takes a lot longer. It appears that the mandatory event wait time between bytes (to avoid overwriting the first one) is about 4 us and, if I include the time it takes to toggle the slave device CE line on and off, the total transmission time is about 10 us. This gives me a throughput of only about 1.6 Mbps.

Is there any way to speed that up? I'm even using some "INLINE" instructions (see below):

NRF_GPIO->OUTCLR = CE_BIT_POS;

dac_spi_base_address->TXD = (uint32_t)(tx_data[0]);

while (dac_spi_base_address->EVENTS_READY == 0U) { } dac_spi_base_address->EVENTS_READY = 0U; rx_data[0] = (uint8_t)dac_spi_base_address->RXD;

dac_spi_base_address->TXD = (uint32_t)(tx_data[1]);

while ((dac_spi_base_address->EVENTS_READY == 0U) /&& (counter < DAC_TIMEOUT_COUNTER)/) { } dac_spi_base_address->EVENTS_READY = 0U; rx_data[1] = (uint8_t)dac_spi_base_address->RXD;

NRF_GPIO->OUTSET = CE_BIT_POS;

Thank you for any ideas!

Gil

Parents
  • In the case of interrupt driven SPI, most of the overhead comes from the dispatch latency through the softdevice. To increase the speed of my driver instead of handling one byte in/out per interrupt I just say:

    while (hw->EVENTS_READY)
    {
        hw->EVENT_READY = 0;
        <send and receive>
    }
    

    This sped up my SPI code considerably with the side effect of staying in the interrupt handler for the entire transaction.

    It seems that even though the SPI interface is double buffered, it doesn't seem like the interrupt is triggered when the first byte is clocked in/out. In the single byte case I see a delay of ~82 cycles from the falling edge of the clock to the rising edge of a gpio when I enter my handler. In the double byte case I see the same 82 cycle delay, but it happens on the falling edge of the 16th SPI clock not the 8th clock as I would have expected.

    As a result of handling multiple bytes per interrupt I saw one annoying side effect. The nrf51 seems to be dispatching the SPI interrupt even when EVENTS_READY is 0. When I handle just one EVENTS_READY per interrupt I never see a EVENTS_READY==0 on entry to the interrupt. It looks like the internal interrupt bit pending is latched when the event happens. So handling multiple bytes per interrupt is only useful if your are doing fairly long transactions.

Reply
  • In the case of interrupt driven SPI, most of the overhead comes from the dispatch latency through the softdevice. To increase the speed of my driver instead of handling one byte in/out per interrupt I just say:

    while (hw->EVENTS_READY)
    {
        hw->EVENT_READY = 0;
        <send and receive>
    }
    

    This sped up my SPI code considerably with the side effect of staying in the interrupt handler for the entire transaction.

    It seems that even though the SPI interface is double buffered, it doesn't seem like the interrupt is triggered when the first byte is clocked in/out. In the single byte case I see a delay of ~82 cycles from the falling edge of the clock to the rising edge of a gpio when I enter my handler. In the double byte case I see the same 82 cycle delay, but it happens on the falling edge of the 16th SPI clock not the 8th clock as I would have expected.

    As a result of handling multiple bytes per interrupt I saw one annoying side effect. The nrf51 seems to be dispatching the SPI interrupt even when EVENTS_READY is 0. When I handle just one EVENTS_READY per interrupt I never see a EVENTS_READY==0 on entry to the interrupt. It looks like the internal interrupt bit pending is latched when the event happens. So handling multiple bytes per interrupt is only useful if your are doing fairly long transactions.

Children
No Data
Related