SPIS - Execution order in spis_irq_handler

I have for some while had a project running in which NRF52840 operates in SPI slave mode.  Using "modules\hal\nordic\nrfx\drivers\src\nrfx_spis.c"

Lately i have been stressing the system with higher data throughput in both direction and is observing packet loss in RX direction.

I have tracked it down and it seems that in the SPI event handler when processing NRFX_SPIS_XFER_DONE data in rx buffer is incorrect/empty.

In the "spis_irq_handler" the following is stated:

    // @note: as multiple events can be pending for processing, the correct event processing order

    // is as follows:

    // - SPI semaphore acquired event.

    // - SPI transaction complete event.

 In the situation when semaphore is requested (asynchronously)  while transfer is ongoing (buffer set #1), this means that as soon as transfer is done, both events will be pending, and the "acquired" event is processed first, and new buffer set #2 for next transaction are configured.

 

Next the transaction complete action is processed, but it now seems uncertain if the NRFX_SPIS_XFER_DONE  event corresponds to the buffer set (#1) initial configured or the one (#2) recently setup during "acquired event" processing. Content of the current configured buffer(#2) will in this case be empty leading to the packet loss I observe.

Reversing the order in the "isr" seems to solve the issue and to me it also seems logical to process the completed transaction before setting up new buffers and not the other way around.

Are you able to elaborate a bit on why the order described in the isr routine should be the correct one ?

Best regards

Anders

Parents
  • Hi,

     

    Effectively, the SPIS needs to setup the upcoming buffers before the CSN pin goes active.

    If you have an application that requires you to parse the incoming data before setting up the buffer, this can be tight when pushing high throughput.

     

    Are you logging from the ISR/event_handler? If so, you need to ensure that the logger thread is running in a deferred mode (ie. handling log data at a later point) via CONFIG_LOG_MODE_DEFERRED. 

    Reversing the order in the "isr" seems to solve the issue and to me it also seems logical to process the completed transaction before setting up new buffers and not the other way around.

    Have you scoped the lines to see how much delay (ie. processing time) is between each inactive to active CSN?

     

    Kind regards,

    Håkon

Reply
  • Hi,

     

    Effectively, the SPIS needs to setup the upcoming buffers before the CSN pin goes active.

    If you have an application that requires you to parse the incoming data before setting up the buffer, this can be tight when pushing high throughput.

     

    Are you logging from the ISR/event_handler? If so, you need to ensure that the logger thread is running in a deferred mode (ie. handling log data at a later point) via CONFIG_LOG_MODE_DEFERRED. 

    Reversing the order in the "isr" seems to solve the issue and to me it also seems logical to process the completed transaction before setting up new buffers and not the other way around.

    Have you scoped the lines to see how much delay (ie. processing time) is between each inactive to active CSN?

     

    Kind regards,

    Håkon

Children
  • Hi Håkon

    Thank you for fast reply.

    Surely the setup of upcoming buffers needs to be done fast in order to be ready for next transmission to avoid "DEF" output situation that will require retransmisson. However I still need securely detect incoming data from previous transaction.  When the events occur simultanously i don't see how to distinguish between the two buffer set. 

    As it is allowed to update the buffers (hence aquire the semaphore) repeately until transaction is started (CSN active), you cannot tell if the buffer update occures before or after the actual transaction, given the current isr execution order.

    I have an inter-packet time of 1 ms on the master side, so there should be enough time for processing. However the issue arrises when i have tx data that updates the spi buffers asynchronusly. When this happens during active transaction the update will be pendingm and the isr events occurs simultanously when CSN is going inactive, causing buffer update before beeing able to catch incoming data.

    In other words since there is no 1:1 relation BUFFER_SET_DONE and XFER_DONE. I need to have link between buffer setup and transaction complete to be sure to process the right buffer. When the "BUFFER_SET_DONE" is "overtaking" the XFER_DONE, in the isr it seem that this link is broken.  Reversing the execution order will ensure that the "XFER_DONE" is related to the latest BUFFER_SET_DONE.

    Regarding CONFIG_LOG_MODE_DEFERRED that a good point,  i will try that out, however i have very limit log in the isr/event handler.

    Regarding scoping inactive to active CSN, do you mean measurering on wire ?  Unfortunately I currently have no access to the physical connections (ie. no test points and everything routed in internal PCB layers). 

    BR

    Anders

  • Hi,

     

    Anders Esbensen said:

    Surely the setup of upcoming buffers needs to be done fast in order to be ready for next transmission to avoid "DEF" output situation that will require retransmisson. However I still need securely detect incoming data from previous transaction.  When the events occur simultanously i don't see how to distinguish between the two buffer set. 

    As it is allowed to update the buffers (hence aquire the semaphore) repeately until transaction is started (CSN active), you cannot tell if the buffer update occures before or after the actual transaction, given the current isr execution order.

    I have an inter-packet time of 1 ms on the master side, so there should be enough time for processing. However the issue arrises when i have tx data that updates the spi buffers asynchronusly. When this happens during active transaction the update will be pendingm and the isr events occurs simultanously when CSN is going inactive, causing buffer update before beeing able to catch incoming data.

    In other words since there is no 1:1 relation BUFFER_SET_DONE and XFER_DONE. I need to have link between buffer setup and transaction complete to be sure to process the right buffer. When the "BUFFER_SET_DONE" is "overtaking" the XFER_DONE, in the isr it seem that this link is broken.  Reversing the execution order will ensure that the "XFER_DONE" is related to the latest BUFFER_SET_DONE.

    Since you have an asynchonous update of the buffer, I understand that this can be problematic.

    Could you rather only update the buffer when the XFER_DONE event occurs? This should allow you do synchronize towards the SPIS transfer flow.

     

    Did you see any performance change when disabling or deferring the log from the event handler?

    Anders Esbensen said:
    Regarding scoping inactive to active CSN, do you mean measurering on wire ?  Unfortunately I currently have no access to the physical connections (ie. no test points and everything routed in internal PCB layers). 

    Yes, looking at the CSN/MISO/MOSI/CLK lines with a logic analyzer to see the timing of the bus, just to see that it behaves as you'd expect it to. This is very helpful if you experience any issues in the transport layer. Does the external sensor have a QFN package? If so, you can technically be able to solder on some "ears" (very thin wire) to the specific pins.

     

    Kind regards,

    Håkon

Related