Skip to main content
Visitor II
October 7, 2024
Solved

STSW-ST25R-LIB using SPI while in IRQ context

  • October 7, 2024
  • 2 replies
  • 1985 views

Hello everyone,

in a project we are using the ST25R3916 chip to read RFID cards. To do this we are using the sources of the STSW-ST25R-LIB library. If the ST25R3916 sets its IRQ output, the routine st25r3916isr() is called. In this ISR the interrupt registers are read via SPI.

void st25r3916Isr( void )
{
 st25r3916CheckForReceivedInterrupts();
 ...
}

void st25r3916CheckForReceivedInterrupts( void )
{
 ...
 /* In case the IRQ is Edge (not Level) triggered read IRQs until done */
 while( platformGpioIsHigh( ST25R_INT_PORT, ST25R_INT_PIN ) )
 {
 st25r3916ReadMultipleRegisters( ST25R3916_REG_IRQ_MAIN, iregs, ST25R3916_INT_REGS_LEN );
 ...
 }
 ...
}

As other components can be connected to this SPI bus, no SPI communication is alowed in the context of an interrupt, as otherwise 2 SPI operations can overlap and this can lead to undesirable effects.

How can I get around this problem? Is there some kind of polling mode or how can I move the SPI operation into the context of the main loop?

Thank you for your support!

Best regards,
Andy

    This topic has been closed for replies.
    Best answer by Ulysses HERNIOSUS

    Hi Andy,

     

    just look at the ST25_IRQ line in the failing case. The IRQ line stays high for a very long time. Lookin at the IRQ just before there is an I_txe which  is read in around 60us. 70us after the starts the next IRQ  which goes un-handled. So something wrong with your timeouts maybe or your flag not working properly. With the GetInterrupt() it should repeatedly be called and see the pin being high. But apparently that doesn't happen.

    Did you also adapt the GetInterrupt() function or only the WaitFor..()?

    Ulysses 

    2 replies

    Technical Moderator
    October 7, 2024

    Hi Andy,

     

    IMO the freertos demo of the  STSW-ST25R-LIB shows a deferred interrupt, also the Linux port (stsw-st25r013) defers the interrupt reading.

    BR, Ulysses

     

     

    afr_e2Author
    Visitor II
    October 8, 2024

    Hi Ulysses,

    thank you for the reply. I checked both implementations and have seen, that both are using a mulithreading OS and spend a seperate thread to handle the ISR. In that case you can use a semaphore or mutex.

    In my project I'm not using a RTOS, its running completelly baremetal, so I cannot synchronize the ISR with a semaphore.

    Regards,
    Andy

    Super User
    October 8, 2024

    The standard way of solving this problem is to set a flag in the interrupt which you check for in the main loop to do the thing you want.

    // global
    volatile int flag = 0;
    
    // in interrupt
    void IRQHandler() {
     flag = 1;
    }
    
    // in main loop
    if (flag == 1) {
     flag = 0;
     // SPI operations here
    }

     

    afr_e2Author
    Visitor II
    October 8, 2024

    Hi TDK,

    thank you for your reply. I already tried to do so, but then I'm not able to read the card anymore. Maybe it takes too much time between irq rising and handling?!? So, is there any other possibility to synchronize the SPI access with the main loop?

    Greetz, Andy

    Technical Moderator
    October 8, 2024

    Hi Andy,

    not sure how you have actually done this.

    I recommend for your case to change functions st25r3916WaitForInterruptsTimed() and st25r3916GetInterrupt() to add at the beginning and inside the while a check for the interrupt pin or another interrupt flag as described by TDK to execute then the st25r3916Isr(). 

    It should also work without the flag but I don't recommend it as it will create lots of traffic on the SPI bus and makes debugging using Logic Analyzer difficult.

    BR, Ulysses