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

Unexpected EVENTS_ENDRX/EVENTS_ENDTX SPIM interrupts when only EVENTS_END interrupt enabled

There is an SPIM unexpected interrupt issue which I have replicated in a totally bare-bones piece of code using no Nordic library drivers. In my bare-bones SPI code I get 2 interrupts instead of the expected 1 at the end of every SPI transaction when only the EVENTS_END interrupt is enabled. This is checked by having a volatile counter which never resets; the count should match the expected number of SPI interrupts but in fact shows double (2x) the expected number. I suspect this to be an SPI errata, but have been too busy to chase it down.
With the same setup and function code, the following handler results in double interrupts for every transaction:

Modifying the interrupt handler to this code removes the problem, keep in mind EVENTS_ENDRX and EVENTS_ENDTX are not enabled::

The other odd thing is that either clearing ENDRX or clearing ENDTX fixes the issue; both do not need to be cleared.

This is the initialisation and repeated transfer code in both the above cases:

I will post this code in the bare-bones Git repo as I'm sure others will find it useful. Meanwhile I would like to not have the extra instructions in the interrupt handler in the interests of reducing cpu cycles

Parents
  • Hi,

    This is odd. There are no errata that should explain this, and if you look at the nrfx_spim implementation, you will see that it also use the END event only, and does not touch ENDRX or ENDTX. Are you by any chance using an old engineering sample of the nRF52832, or are you using a production version (rev 1 or rev 2)? Does it make a difference if you clear the event before incrementing mSpiInterruptCounter?

Reply
  • Hi,

    This is odd. There are no errata that should explain this, and if you look at the nrfx_spim implementation, you will see that it also use the END event only, and does not touch ENDRX or ENDTX. Are you by any chance using an old engineering sample of the nRF52832, or are you using a production version (rev 1 or rev 2)? Does it make a difference if you clear the event before incrementing mSpiInterruptCounter?

Children
  • Thanks for the response. We have Rev 1, I think, in a WLCSP package within a module:

    I will try a Rev.2 if we have one here. Interestingly your suggestion of moving the event clear within the interrupt to before the ++ fixes the problem. Looking at the generated assembly for the two instructions shows no difference when changing order. How does this work? Clearly this could be an issue within other interrupts.

  • Hi,

    Revision 1 and 2 should be the same, so that is OK. It looks like it was just a timing issue so that by clearing the event on the last line it was not actually cleared by the time the ISR exited, and therefor the interrupt was still active, and the ISR was called again. So you should make sure to clear the event earlier in the ISR, or read it back or similar to ensure that it is actually cleared before returning from the ISR.

  • Is the Data Synchronization Barrier instruction "dsb" implemented in the nRF52832? This code generates the interrupt 12 times instead of once:

    In debug mode, the following works ok and onlt generates a single interrupt:

    My understanding is that "dsb" ensures all bus activity completes before the instruction terminates and continues with the next; is that incorrect? See cmsis_gcc.h in .\components\toolchain\cmsis\include for definition

    I see that the instruction is used in nrf_log_frontend.c:

    Maybe this needs to be added to sample interrupt example code ..

  • Hi,

    First of all, the DSB instruction is implmented in the nRF52832. Secondly, "__DSB();" and "__ASM volatile ("dsb 0xF":::"memory");" should be equivalen.

    I am having some problems understanding this. Even if _DSB() was not working, clearing the event with "pSPIM->EVENTS_END = 0;" only takes a few cycles, so it should not be possible. Therefore I wonder how you can know that the interrupt is generated 12 times when not debugging using this code? Is something else happening simultaneously?