This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TRF7970A: Cannot reliably read/write to NFC tag (ISO15693) using TRF7970A

Part Number: TRF7970A
Other Parts Discussed in Thread: RF430FRL152H

Hello,

We are currently experiencing an issue with the TRF7970A. We are using NFC tags (ISO 15693) What's happening is as follows:

We are doing a single block write to our NFC tags. When we write the following bytes to the tag:

Block 00: Bytes: 00 AA AA AA AA AA AA AA
Block 01: Bytes: 01 BB BB BB BB BB BB BB
Block 02: Bytes: 02 CC CC CC CC CC CC CC
Block 03: Bytes: 03 DD DD DD DD DD DD DD

We see that the all blocks were written successfully (and we get a RX_COMPLETE interrupt response from the TRF7970A chip). But, when we try to read back the data from the blocks, this is what we see:

Block 00: Bytes: 00 AA AA AA AA AA AA AA
Block 01: Bytes: 00 00 00 00 00 00 00 00
Block 02: Bytes: 02 CC CC CC CC CC CC CC
Block 03: Bytes: 00 00 00 00 00 00 00 00

So, it looks like every odd block number is not written to. We tried the same with the TRF7970A EVM GUI and we get the same results.

Question is:

  1. Is there any errata on the TRF7970A that shows this issue?
  2. Can you give us the source code of TRF7970A EVM GUI for Visual Studio 2010 or greater so that we may debug the issue?

Please advise

  • Hello Masmur,

    The TRF7970A does not have any errata related to ISO15693 tag reading/writing. This issue is system/software related.

    The TRF7970AEVM and GUI is out of date software, is that what you are using to evaluate the device? If so, the issue may be due to software bugs in the EVM firmware which were never updated due to moving to newer software bases.

    If you can describe what software you are using as a base and also provide info on what tag you are writing to, I can offer advice on how to proceed to resolve this issue.
  • Hello Ralph,

    We are not using the EVM to evaluate rather debug any issues. We are using an STM32L4 CPU connected via SPI to the TRF7970A chip. This is a custom board that our company has developed but have used your EVM reference designs for it. We took the MSP firmware logic (downloaded from TI) that was written initially and ported it to the STM32L4 CPU. The tag we are using are Fujitsu ISO15693 gammatag.

    Here's the datasheet: www.fujitsu.com/downloads/MICRO/fme/fram/ds-mb89r118c.pdf


    So here's the scenario:

    1. First, we do an ISO15693 inventory scan (in single slot mode) and we receive the TAG ID successfully.
    2. Next, we send an ISO15693 system info command and retrieve the block size and # of blocks (block size is 0x7 and # of blocks is 0xf9).
    3. Next, we do an ISO15693 Single block write of data to block 0: 00 AA AA AA AA AA AA AA
    4. Followed by another single block write to block 1: 11 BB BB BB BB BB BB BB
    5. Followed by another single block write to block 2: 22 CC CC CC CC CC CC CC
    6. And finally the last single block write to block 3: 33 DD DD DD DD DD DD DD
    7. Then we try to read back the block 0 through 3 using ISO15693 single block read command and the results were mentioned in my first post and we see missing writes between blocks

    What we've observed: When we do the single block writes, we get a response 00 (i.e. no error) back from the tag. So, it is definitely not our firmware since the TRF7970A is responding correctly and sending an RX COMPLETE interrupt every time.

    I don't know what else to describe to you that the tag writes are not happening the way we expected.

  • Hello Masmur,

    The scenario is very clear to me, and it sounds like from a step by step method everything is done right, which is why I am suspecting software as the core issue. I agree that if you are getting an RX Complete with no error, that the data should be written correctly, but I have concerns depending on the firmware you using.

    Is the software with the MSP firmware logic you downloaded from TI the sloc300a package? That package had issues with reporting error codes, and had terrible error case handling. It may be possible that it is misreporting a success depending how much of the firmware was copied...

    I have tested with our SLOC297 firmware that I can write to our own 2kB FRAM tag, the RF430FRL152H, which also works in 8 byte mode, exactly how you are describing.

    In fact, if you have a TRF7970AEVM and are willing to modify it for SPI mode (if it isn't already in SPI mode), I can provide code the TRF7970AEVM that does exactly as described which would be based on SLOC297 instead. You can then test if it works for your Fujitsu tag. If it works, then we can be confident the issue is neither with reader device or tag.

    Would that be of interest for you?
  • Hi Ralph,

    Yes, I have a TRF7970EVM and it is actually running in SPI mode. So, you can provide me with the updated TRF7970AEVM code which might help. But the question I have is that since the TRF7970AEVM GUI code is obsolete, how can I possibly talk to the EVM? Do I write some scripts (i.e. Python maybe) to communicate over serial? Maybe you can give me a good suggestion on that point.

    So, When I looked back on what was my starting point on my code: I definitely used SLOC297c firmware code (not SLOC300a) to do the port. I have provided you with code excerpts of the IRQ what I've done so far.

    /*!
     * @brief   Processes the TRF7970 Interrupt
     */
    void TRF79xxA_processIRQ(void)
    {
        uint8_t length;
        uint8_t dummyRead;
    
        g_IrqFlag = TRF79xxA_readIrqStatus();
    
        // check for TX active and 32 bytes left in FIFO
        if (g_IrqFlag == (TRF79XXA_IRQ_STATUS_TX_COMPLETE | TRF79XXA_IRQ_STATUS_FIFO_HIGH_OR_LOW))
        {
            g_Status = TX_COMPLETE;
        }
        // check for TX complete
        else if (g_IrqFlag == TRF79XXA_IRQ_STATUS_TX_COMPLETE)
        {
            g_Status = TX_COMPLETE;
            TRF79xxA_resetFIFO();
        }
        // check for collision error
        else if ((g_IrqFlag & BITPOS_BIT1) == TRF79XXA_IRQ_STATUS_COLLISION_ERROR)
        {
            if ((g_GeneralSettings.IsoControl == 0x08) || (g_GeneralSettings.IsoControl == 0x88))
            {
                g_Status = COLLISION_ERROR;
                g_CollisionPosition = TRF79xxA_readRegister(TRF79XXA_COLLISION_POSITION);
    
                if (g_CollisionPosition > 0x20)
                {
                    length = g_CollisionPosition - 0x20;    // Number of valid bytes in FIFO
    
                    if ((length & 0x0F) != 0x00)
                    {
                        length += 0x10;     // add 1 byte if broken byte received
                    }
    
                    length = length >> 4;
    
                    if (length != 0x00)
                    {
                        // write the received data into buffer
                        g_TrfBuffer[g_FifoOffset] = TRF79XXA_FIFO;
                        TRF79xxA_readContinuous(&g_TrfBuffer[g_FifoOffset], length);
                        g_FifoOffset += length;
                    }
                }
                else
                {
                    g_FifoRxLength = TRF79xxA_readRegister(TRF79XXA_FIFO_STATUS);
                    #if (TRF79xxA_VERSION == 70)
                        g_FifoRxLength &= 0x7F;
                    #elif (TRF79xxA_VERSION == 60)
                        g_FifoRxLength = (0x0F & g_FifoRxLength) + 1;
                    #endif
    
                    g_TrfBuffer[g_FifoOffset] = TRF79XXA_FIFO;      // write the received bytes to the correct place of the buffer
                    TRF79xxA_readContinuous(&g_TrfBuffer[g_FifoOffset], g_FifoRxLength);
                    g_FifoOffset += g_FifoRxLength;
                }
            }
            // Covers all ISO 15693 Data rates for RFID mode with RX CRC on
            else if ((g_GeneralSettings.IsoControl & 0xF8) == 0x00)
            {
                g_Status = COLLISION_ERROR;
            }
            else
            {
                g_Status = PROTOCOL_ERROR;
            }
    
            // stop all decoders and reset fifo/irq status
            TRF79xxA_sendDirectCommand(TRF79XXA_STOP_DECODERS_CMD);
            TRF79xxA_resetFIFO();                   // reset the FIFO after TX
            TRF79xxA_resetIrqStatus();
        }
        // RX complete
        else if (g_IrqFlag == TRF79XXA_IRQ_STATUS_RX_COMPLETE)
        {
            // read FIFO status
            g_FifoRxLength = TRF79xxA_readRegister(TRF79XXA_FIFO_STATUS);
            #if (TRF79xxA_VERSION == 70)
                g_FifoRxLength &= 0x7F;
            #elif (TRF79xxA_VERSION == 60)
                g_FifoRxLength = (0x0F & g_FifoRxLength) + 1;
            #endif
            // read data out
            g_TrfBuffer[g_FifoOffset] = TRF79XXA_FIFO;
            // read continuous
            TRF79xxA_readContinuous(&g_TrfBuffer[g_FifoOffset], g_FifoRxLength + 1);    // we need one extra byte to read as we have read through the bytes
            g_FifoOffset += (g_FifoRxLength + 1);
            g_Status = RX_COMPLETE;
            // reset FIFO
            TRF79xxA_resetFIFO();
    
        }
        // RX active and 96 bytes already in FIFO
        else if (g_IrqFlag == (TRF79XXA_IRQ_STATUS_RX_COMPLETE | TRF79XXA_IRQ_STATUS_FIFO_HIGH_OR_LOW))
        {
            // read FIFO status
            g_FifoRxLength = TRF79xxA_readRegister(TRF79XXA_FIFO_STATUS);
            #if (TRF79xxA_VERSION == 70)
                g_FifoRxLength &= 0x7F;
            #elif (TRF79xxA_VERSION == 60)
                g_FifoRxLength = (0x0F & g_FifoRxLength) + 1;
            #endif
    
            // empty out the fifo by reading it
            if (NFC_FIFO_SIZE > (g_FifoOffset + g_FifoRxLength))
            {
                g_TrfBuffer[g_FifoOffset] = TRF79XXA_FIFO;
                // read continuous
                TRF79xxA_readContinuous(&g_TrfBuffer[g_FifoOffset], g_FifoRxLength + 1);
                g_FifoOffset += (g_FifoRxLength + 1);
                // reset FIFO
                TRF79xxA_resetFIFO();
            }
            else
            {
                g_Status = PROTOCOL_ERROR;
            }
    
            #if (TRF79xxA_VERSION == 70)
                // read FIFO status
                g_FifoRxLength = TRF79xxA_readRegister(TRF79XXA_FIFO_STATUS);
                g_FifoRxLength &= 0x7F;
    
                if (g_FifoRxLength > 0)
                {
                    g_Status = RX_WAIT_EXTENSION;
                }
                else
                {
                    g_FifoRxLength = g_FifoOffset;
                    g_Status = RX_COMPLETE;
                    return;
                }
            #elif (TRF79xxA_VERSION == 60)
                // Cannot rely on FIFO Status results to indicate number of bytes left, therefore always must go to RX_WAIT_EXTENSION state.
                g_Status = RX_WAIT_EXTENSION;
                g_FifoRxLength = g_FifoOffset;
            #endif
        }
        // RX has begun but not completed.
        // Space still exists in FIFO, just wait a bit longer to receive full
        else if (g_IrqFlag == (TRF79XXA_IRQ_STATUS_RX_COMPLETE | TRF79XXA_IRQ_STATUS_NO_RESPONSE))
        {
            // RX has begun but as not completed, space exists in FIFO still, just wait longer to receive full reply.
            g_Status = RX_WAIT_EXTENSION;
        }
        // CRC error
        else if ((g_IrqFlag & BITPOS_BIT4) == TRF79XXA_IRQ_STATUS_CRC_ERROR)
        {
            // receive 4 bytes
            if ((g_IrqFlag & BITPOS_BIT6) == TRF79XXA_IRQ_STATUS_RX_COMPLETE)
            {
                dummyRead = TRF79XXA_FIFO;
                TRF79xxA_readContinuous(&dummyRead, sizeof(dummyRead));
            }
    
            TRF79xxA_reset();
            g_Status = PROTOCOL_ERROR;
        }
        // Byte framing error
        else if ((g_IrqFlag & BITPOS_BIT2) == TRF79XXA_IRQ_STATUS_FRAMING_ERROR)
        {
            if ((g_IrqFlag & BITPOS_BIT5) == TRF79XXA_IRQ_STATUS_FIFO_HIGH_OR_LOW)
            {
                g_Status = RX_WAIT;
            }
            else if ((g_IrqFlag & BITPOS_BIT6) == TRF79XXA_IRQ_STATUS_RX_COMPLETE)
            {
                // this covers all ISO15693 data rate for RFID mode with RX CRC on
                if ((g_GeneralSettings.IsoControl & 0xF8) == 0x00)
                {
                    g_Status = COLLISION_ERROR;
                }
                else
                {
                    g_Status = PROTOCOL_ERROR;
                    TRF79xxA_reset();
                }
            }
            else
            {
                g_Status = PROTOCOL_ERROR;
                TRF79xxA_reset();
            }
        }
        // No response interrupt
        else if (g_IrqFlag == TRF79XXA_IRQ_STATUS_IDLE)
        {
            g_Status = NO_RESPONSE_RECEIVED;
        }
        // No response Interrupt
        else if (g_IrqFlag == TRF79XXA_IRQ_STATUS_NO_RESPONSE)
        {
            g_Status = NO_RESPONSE_RECEIVED_15693;
        }
        else
        {
            g_Status = PROTOCOL_ERROR;
    
            TRF79xxA_sendDirectCommand(TRF79XXA_STOP_DECODERS_CMD); // reset the FIFO after TX
            TRF79xxA_reset();
            TRF79xxA_resetIrqStatus();
        }
    
    }

  • Hello Masrur,

    It is good to hear you used SLOC297 as a basis, that should allow me to help far better! I was the primary developer for that software example so I know all the ins and outs. I am surprised you are having issues though.

    Anyways, the code I am attaching is based on the latest SLOC297 code, and as mentioned I tested it with the RF430FRL152H. I changed the NFC_appIso15693 to do some write blocks first and then it still reads out the whole tag data. Nothing too fancy, but it proves operation.

    I will review your ISR as well, but want to provide the firmware first so we can work in parallel.

    Link: 8712.TRF7970AEVM_RFID_Reader_Demo.zip

  • Hello Masrur,

    Also regarding the TRF7970AEVM GUI source, it's been shared on E2E before so I'll go ahead and link that post to you... e2e.ti.com/.../595674

    That said, we have obsoleted the EVM so there is no support being offered for the EVM, and especially not for the source code.
  • Hi Ralph,

    Just a clarification from before, I just double-checked the code again and one of the developers was using a multi-block write (not a single block write). I'm going to try to convert that code into a single block write instead and see but in the meantime: In the SLC297c firmware, is there an issue with multi-block write?

    Please advise.

    Thanks,
    Masrur
  • Hello Masrur,

    Write Multiple Block is not part of any firmware we deliver as it is an optional command and not many tags support it. I don't think that even in the past we released any code with that functionality. So if that function exists then it was likely developed by your developers.

    I can review the function and offer comments about anything that may be missing if that is the case, I am very familiar with ISO15693 specifications.