The interrupt timing of IRQ_DIRECT_CONNECT is different from expected.

Hello,

Currently, I am creating firmware that generates an IRQ_DIRECT_CONNECT interrupt at the timing when SPIM4 transfer is completed (ENDTX).

However, the interrupt timing is not at ENDTX but near the start of SPIM4 operation.

Since an interrupt occurs at the start, the current process is waiting for the ENDTX event within the interrupt. How should I set it to generate an interrupt at ENDTX?

IRQ_DIRECT_CONNECT and irq_enable settings:

IRQ_DIRECT_CONNECT(SPIM4_IRQn, 0,spim4_event_handler,IRQ_ZERO_LATENCY);
irq_enable(SPIM4_IRQn);

Interrupt handler settings:

static void spim4_event_handler(nrfx_spim_evt_t const*p_event, void *p_context)
{	
	while(NRF_SPIM4->EVENTS_ENDTX == 0){;}
	NRF_SPIM4 -> EVENTS_ENDTX = 0x00000000; 
}

Register settings before data transfer:

NRF_SPIM4 -> INTENCLR = 0x00080152;
NRF_SPIM4 -> INTENSET = 0x00000100;

Register settings after data transfer:

NRF_SPIM4 -> INTENCLR = 0x00000100;

best regard,

Parents
  • Hello,

    I think the SPIM peripheral in the nRF5340 does not directly support an ENDTx interrupt. Using a GPIO pin to monitor the state of the SPI lines (MISO or MOSI) and then configuring the GPIO pin to generate an interrupt when the line state changes such that it indicates the end of the transmission will be a solution for your use case. You can also consider using the software interrupt. Take a look at this thread, which explains this a bit briefly.

    Please expect a delay after this response. I will be responding after Tuesday next week, as it is Easter vacation here in Norway.

     Kind Regards,

    Abhijith

Reply
  • Hello,

    I think the SPIM peripheral in the nRF5340 does not directly support an ENDTx interrupt. Using a GPIO pin to monitor the state of the SPI lines (MISO or MOSI) and then configuring the GPIO pin to generate an interrupt when the line state changes such that it indicates the end of the transmission will be a solution for your use case. You can also consider using the software interrupt. Take a look at this thread, which explains this a bit briefly.

    Please expect a delay after this response. I will be responding after Tuesday next week, as it is Easter vacation here in Norway.

     Kind Regards,

    Abhijith

Children
  • Hello,

    Thank you for your reply.

    Although the nRF5340's SPIM peripheral does not directly support ENDTx interrupts, SPIM4_IRQn was defined in the include file nrf5340_application.h.

    Currently, the ENDTx interrupt is working in the program, but is there a concrete way to trigger it with ENDTx?

    best regard,

  • I would suggest that the ENDTX works as documented, but that the interrupt handler above is incorrectly written. The reason "the interrupt timing is not at ENDTX but near the start of SPIM4 operation" is likely to be that the clear of the event occurs from the previous SPIM4 transfer event, not the current transfer event, or ENDTX is triggered when a short TXD MAXCNT is exhausted in a longer SPIM4 transaction. Try changing this:

    static void spim4_event_handler(nrfx_spim_evt_t const*p_event, void *p_context)
    {	
    	while(NRF_SPIM4->EVENTS_ENDTX == 0){;}
    	NRF_SPIM4 -> EVENTS_ENDTX = 0x00000000; 
    }

    to this:

    // Handle and clear all triggering events
    static void spim4_event_handler(nrfx_spim_evt_t const*p_event, void *p_context)
    {	
    	if(NRF_SPIM4->EVENTS_ENDTX)
    	{
    	    NRF_SPIM4->EVENTS_ENDTX = 0;
    	}
    }

    For testing, one might test and clear every possible event in case there is some coding error, even though only ENDTX is required. In some ways ENDTX is not always the best choice, as incoming RX bytes beyond the active TX bytes (ie when sending shorter Tx then Rx using ORC padding bytes); END might be a safer choice.

    NRF_SPIM4 -> INTENSET = 0x00000040;
    // Handle and clear all triggering events
    static void spim4_event_handler(nrfx_spim_evt_t const*p_event, void *p_context)
    {	
    	if(NRF_SPIM4->EVENTS_END)
    	{
    	    NRF_SPIM4->EVENTS_END = 0;
    	}
    }

    "ORC: Byte transmitted after TXD.MAXCNT bytes have been transmitted in the case when RXD.MAXCNT is greater than TXD.MAXCNT" Note ENDTX is triggered when TXD MAXCNT is exhausted, not when SPIM4 transfer ends; perhaps try END instead.

  • Hello,

    Thank you for your reply.

    I modified the program as you pointed out, but as shown below, there was no change between before and after the modification.

    before:

    after:

    The timing at which Main loop processing finished is different from the timing at which interrupt processing finished.
    However, interrupt processing starts near the end.

    best regard,

  • Above:

    The timing at which Main loop processing finished is different from the timing at which interrupt processing finished.

    but correctly:

    The timing at which Main loop processing finished is different from the timing at which interrupt processing starts.

    Also, I feel it is strange that the Main loop ends around the start of SPIM4.

  • Neither trace above shows the problem described we were trying to fix:

    "However, the interrupt timing is not at ENDTX but near the start of SPIM4 operation. Since an interrupt occurs at the start, the current process is waiting for the ENDTX event within the interrupt. How should I set it to generate an interrupt at ENDTX?"

    Both traces look correct regarding the SPIM4 data transfer and the following event and consequential SPIM4 interrupt. Timing of the main loop pin toggle is quite separate; main loop will run on every event which will include wakeup on SPIM4 event, and Zephyr/RTOS threads (if any) and any other enabled event/interrupt. It is not clear what problem you are looking at.

    The start of the interrupt looks like it takes a long time to begin, but that is wholly dependent on the Zephyr/OS/sleep wake code and other higher-priority interrupts; maybe share the wakeup code ...

Related