Skip to main content
Visitor II
June 24, 2021
Solved

X-NUCLEO-NFCC06A1: long time to read RFID Card Tag

  • June 24, 2021
  • 12 replies
  • 4480 views

I using the Demo code for ST25R3916 It takes long time to read RFID Card Tag , what might be causing that ?

I am using X-NUCLEO-NFCC06A1 eval board with ST25R3916 CHIP

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

    Hi,

    ERR_IO is not normal and indicates an issue on SPI/IRQ. The other two cases you hinted are likely just different manifestations of the same problem.

    As hinted before Logic Analyzer traces are key in such a case.

    Regards, Ulysses

    12 replies

    Technical Moderator
    June 24, 2021

    Hi FNana.1,

    please share some more details what you are observing:

    • What type of RFID card?
    • Please define long time!
    • Are you using X-CUBE-NFC6? On which Nucleo?

    The demo uses a 500ms delay after finding a card before starting next discovery. Maybe that is the reason for your observation. But will need more details.

    Best Regards, Ulysses

    Technical Moderator
    June 25, 2021

    Hi,

    In addition to Ulysses answer: X-CUBE-NFC6 contains 2 demos (polling demo and ndef reading demo). Which one do you use?

    Also, the totalDuration parameter of the rfalNfcDiscoverParam has impacts on the tag detection. What is the value of the totalDuration in your application?

    The polling loop also tries to detect different technologies and then enter card emulation mode; if your application does not use all the various technologies, the detection of unused technologies can be removed (see techs2Find parameter).

    Rgds

    BT

    FNana.1Author
    Visitor II
    June 25, 2021

    Hi Brian TIDAL

    Thanks for your reply ,

    In addition to Ulysses answer: X-CUBE-NFC6 contains 2 demos (polling demo and ndef reading demo). Which one do you use?

    I am using the : STSW-ST25R013 Linux demo of ST25R3916 for Raspberry Pi using X-NUCLEO-NFC06A1 , Polling demo

    What is the value of the totalDuration in your application?

    discParam.totalDuration    = 1000U;

    My application going use most of technologies , already disabled some.

    Many thanks fro your help

    FNana.1Author
    Visitor II
    June 25, 2021

    Hi Ulysses ,

    Yes i have ported to iMX6 freescale board , which is the board ST25R3916 CHIP will be used .

    Anything i need to apart the ones you've mentioned above ?

    Many thanks

    FNana.1Author
    Visitor II
    July 16, 2021

    Hi Ulysses ,

    Sorry The C++ static_cast it is a mistake , in fact my colleague in parallel is looking to port it into c++ for the integration code and i have just copy paste the bit of code i wanted to send you and realized the mistake after , sorry . Nothing to worry about as i am working with original C code .

    Looks like the poll that was crashing is now solved but need to confirm . see below my question please .

    void* pthread_func()

    {

      struct gpioevent_data event;

      /* First check whether GPIOInit is done */

      if (!isGPIOInit) {

        fprintf(stderr, "GPIO is not initialized\n");

        return NULL;

      }

      /* poll interrupt line forever */

      while (true)

      {

        /* read() blocks the calling thread until some data becomes available */

        /* The port is used to contain the file descriptor of a given pin! */

        ssize_t s = read(ST25R_INT_PORT, &event, sizeof(event)); <<<< Is this really needed ? as it looks like it doesn't do anything with event ?

        /* Call RFAL Isr */

        platformIsr();

        /* Unlock Semaphore */

        sem_post(&rfal_sem);

      }

      return NULL;

    }

    Many thanks

    FNana.1Author
    Visitor II
    July 16, 2021
    void* pthread_func()
    {
     struct gpioevent_data event;
     
     /* First check whether GPIOInit is done */
     if (!isGPIOInit) {
     fprintf(stderr, "GPIO is not initialized\n");
     return NULL;
     }
     
     /* poll interrupt line forever */
     while (true)
     {
     /* read() blocks the calling thread until some data becomes available */
     /* The port is used to contain the file descriptor of a given pin! */
     
     ssize_t s = read(ST25R_INT_PORT, &event, sizeof(event)); // Is this really important please ? as it doesn't do anything with event
     
     /* Call RFAL Isr */
     platformIsr();
     
     /* Unlock Semaphore */
     sem_post(&rfal_sem);
     }
     
     return NULL;
    }

    Technical Moderator
    July 16, 2021

    Hi,

    as the comment says: It blocks until data becomes available = interrupt has happened. It also suspends execution of the thread until data becomes available.

    This avoid wasting the CPU and allows using it for other task.

    Regards, Ulysses

    FNana.1Author
    Visitor II
    July 16, 2021

    Hi Ulysses ,

    Yes i have got that thanks , but the line below doesn't do anything i think , it just read from file description ST25R_INT_PORT but doesn't do anything with the result

    ssize_t s = read(ST25R_INT_PORT, &event, sizeof(event)); // Is this really important please ? as it doesn't do

    This line below i think is the one that matchs what the comment says , please correct me if i am wrong ?

    /* Call RFAL Isr */

    platformIsr();

    Many thanks

    Technical Moderator
    July 16, 2021

    Hi,

    yes, one line waits and the other one actually checks the interrupt status register. If you remove the first line you will be at 100% CPU and lots of traffic on SPI (checking the interrupt status all the time).

    Regards, Ulysses

    FNana.1Author
    Visitor II
    July 16, 2021

    Thanks Ulysses ,

    so basically we can replace ssize_t s = read(ST25R_INT_PORT, &event, sizeof(event));

    By this ( see below ) and it should work ?

    <

    ret = poll(&poll_fd, 1, -1);

    if (ret < 1) {

    printf("Error: in polling for interrupt line\n");

    return NULL; 

    }

    if (poll_fd.revents & (POLLPRI|POLLERR))

    {

    lseek(poll_fd.fd, 0, SEEK_SET);

    read(poll_fd.fd, &c, 1);

    /* Call RFAL Isr */

    st25r3911Isr();

    }

    />

    Thanks

    Technical Moderator
    July 20, 2021

    Hi,

    probably. Likely this is the right code when using poll(). Are you saying that using only read() is not working for you? We have checked and on RPi it is working (read() blocks until new events on interrupt line have been received).

    Are you using old gpio (sysfs) interface?

    Regards, Ulysses

    P.S.: I meant using the button "</>" when writing, not using as verbal elements

    FNana.1Author
    Visitor II
    July 19, 2021

    Hi Ulysses ,

    Hope you had a great weekend .

    Please in below code , any reason why the rfalISO14443ATransceiveShortFrame return with ret = ERR_IO or ERR_WRONG_STATE

    <

    ReturnCode rfalNfcaPollerCheckPresence( rfal14443AShortFrameCmd cmd, rfalNfcaSensRes *sensRes )

    {

    ReturnCode ret;

    uint16_t rcvLen;

    /* Digital 1.1 6.10.1.3 For Commands ALL_REQ, SENS_REQ, SDD_REQ, and SEL_REQ, the NFC Forum Device *

    * MUST treat receipt of a Listen Frame at a time after FDT(Listen, min) as a Timeour Error */

    ret = rfalISO14443ATransceiveShortFrame( cmd, (uint8_t*)sensRes, (uint8_t)rfalConvBytesToBits(sizeof(rfalNfcaSensRes)), &rcvLen, RFAL_NFCA_FDTMIN );

    if( (ret == ERR_RF_COLLISION) || (ret == ERR_CRC) || (ret == ERR_NOMEM) || (ret == ERR_FRAMING) || (ret == ERR_PAR) )

    {

    ret = ERR_NONE;

    }

    return ret;

    }

    />

    rfalISO14443ATransceiveShortFrame is randomly missing to detect the presence of card but sometime is OK

    I guess when there is not the presence of a card this rfalISO14443ATransceiveShortFrame returns with ERR_TIMEOUT ?

    Many Thanks

    Technical Moderator
    July 20, 2021

    Hi Franklin,

    right, rfalISO14443ATransceiveShortFrame() return typically ERR_NONE in case a card is there and ERR_TIMEOUT when there is no card. In rare cases you could also see ERR_FRAMING, ERR_PARITY.

    ERR_IO or ERR_WRONG_STATE are indications that either communication to the ST25R3916 has problems or incorrect handling of APIs.

    As recommended before: Look into SPI using a Logic Analyzer: MOSI,MISO,SS,SCL,IRQ. You can also share traces here. Typically this helps a lot in root cause analysis.

    BR, Ulysses

    FNana.1Author
    Visitor II
    July 20, 2021

    Hi Ulysses ,

    so in void* pthread_func()

    1. Sorry my mistake on this " ssize_t s = read(ST25R_INT_PORT, &event, sizeof(event)) " I was using the wrong file descriptor
    2. I don't have this library libgpiod built in our current linux image therefore struct gpioevent_data is not detected
    3. I have replaced struct gpioevent_data by a simple variable char event[512] given that it is not used at all in the code
    4. below is the final replacement
     /* poll interrupt line forever */
     while (true)
     {
     /* read() blocks the calling thread until some data becomes available */
     /* The port is used to contain the file descriptor of a given pin! */
     ssize_t s = read(fd_readGPIO, &event, sizeof(event));
     /* Call RFAL Isr */
     platformIsr();
     
     /* Unlock Semaphore */
     sem_post(&rfal_sem);
     }

    FNana.1Author
    Visitor II
    July 20, 2021

    sorry i have clicked on answer too soon. this is the following .

     while (true)
     {
     /* read() blocks the calling thread until some data becomes available */
     /* The port is used to contain the file descriptor of a given pin! */
     ssize_t s = read(fd_readGPIO, &event, sizeof(event));
     /* Call RFAL Isr */
     platformIsr();
     
     /* Unlock Semaphore */
     sem_post(&rfal_sem);
     }

    I think it still going to play the same role as the original one , what do you think please ?

    We don't want for now to build the  libgpiod in our current image as we don't have time and we want to make a very minimal changes .

    Many thanks

    Technical Moderator
    July 20, 2021

    Hi Franklin,

    Not sure, above code looks more like polling the GPIO state and not the events(interrupts) coming from it.

    AFAIK we are not using the userspace libgpiod but are relying on low level ioctl for accessing the character device interface.

    If you want to use the deprecated sysfs interface then I could send you the previous version of STSW-ST25R013. Just let me know.

    Regards, Ulysses

    FNana.1Author
    Visitor II
    July 20, 2021

    Hi Ulysses ,

    Yes please that would be appreciated to send me the previous version of STSW-ST25R013 ( with deprecated sysfs) because we are currently using the sysfs we don't have libgpiod.

    Many thanks