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,

  • I think your analysis of the interrupt is not correct, unless I'm missing something. The ENDTX interrupt occurs at the end of the TX buffer transmission, not at the start. If padding bytes are used via ORC to match a longer Rx buffer than the Tx buffer (ie keeps the SCLK running until Rx complete) then the ENDTX interrupt occurs before the end of the full SPIM4 transaction, but not at the start as I mentioned earlier. The way to know when the interrupt is active is to drive the port pin low at the start of the interrupt and high at the end of the interrupt in the interrupt code, which is what I assume you are doing, and that shows the active portion of the SPIM4 interrupt. This means that "The point where the interrupt occurred" marked on the trace is not correct; that might be the point at which code wrote to the SPIM4 peripheral to start a transaction, but it is not the interrupt itself. So the question is how did you determine that point?

    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)
    {
        PortPinLow(); // Drive port pin low here
    	if(NRF_SPIM4->EVENTS_END)
    	{
    	    NRF_SPIM4->EVENTS_END = 0;
    	}
    	... other stuff in interrupt
        PortPinHigh(); // Drive port pin high here
    }

    "This can be confirmed by the fact that GPIO switching disappears in the Main loop". Something is blocking; another interrupt, a blocking wait, or something which needs identifying; it is not the SPIM4 interrupt itself.

  • The start of the transaction is automatically executed by DPPI (SPIM3 PUBLISH_ENDRX -> SPIM4 SUBSCRIBE_START), and Main loop does nothing other than repeat GPIO switching.

    Does using DPPI cause this kind of phenomenon?

  • Hard diagnosing issues with only partial information; the delayed SPIM4 interrupt may be due to the SPIM3 interrupt if that takes significant time, what does SPIM3 interrupt do? Can you post the SPIM3 code? I ask again, why do you think SPIM4 interrupt occurs at the mark on the trace? I can state unequivocally that it does not.

    DPPI does not affect timing in the way you describe.

  • I'm sorry, I thought that SPIM3 did not use interrupts, but in reality, it used interrupts unintentionally.
    By disabling SPIM3 interrupts, an interrupt will now occur at SPIM4's ENDTX.

    Thank you very much for your help.

Related