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.

TRF7960A: Problem with read single/multiple blocks

Other Parts Discussed in Thread: TRF7960

Hi,

I implemented a read single/multiple blocks. It works fine in general but if I read block addresses over 0x30 (most frequently 0x30, 0x31, 0x32, 0x33), I cannot receive any other IRQ after read (the read is correct).

It happens often but not always and not always with the same block address.

To reset the problem I need to switch off the module.

Any idea? Thank you. 

Best regards

Alessandro

  • Hello Alessandro,

    To be able to replicate the issue you are seeing, I have a couple of questions:

    1. What tag are you reading?
    2. What is the size of that tag you are reading?
    3. Can you provide the source code for the TRF7960 driver?
    4. Do you have a logic analzyer screenshot of the case where you can't receive an IRQ?

    Best regards,

    Erick

  • Hello,

    thank you for the answer.

    I am using Plus tags of different sizes.

    Here is the code for Read Single Block (I do not have a logic analyzer in this moment, sorry).

    Best regards

    Alessandro

     

    void SPI_WriteBuffer(uint8_t* buffer, uint16_t index, uint16_t count)
    {
        buffer += index;
        SET_SS_LOW;
        while (count-- > 0)
        {
           SPI_WriteByte(*(buffer++));
        }
        while(!(SPSR & (1<<SPIF))); 
        SET_SS_HIGH;
    }

    ....

    // Read Single Block

    uint16_t data_size = 3;
    uint8_t flags = 0b00000010;
    if (uid)
    {
        data_size += 8;
        flags |= 0b00100000;
    }

    uint8_t command = 0x20;

    buffer[0] = 0x8f; // Reset FIFO
    buffer[1] = 0x91; // Send with CRC
    buffer[2] = 0x3d; // Continuous write starting from 1D 
    buffer[3] = (uint8_t)(data_size >> 8); // Data size (high byte)
    buffer[4] = (uint8_t)(data_size << 4); // Data size (low byte)
    buffer[5] = flags; // Flags
    buffer[6] = command; // Command
    if (uid)
    {
        for (uint8_t j=0; j<8; j++) // Copy UID (inverted)
        {
             buffer[7+j] = uid[8-1-j];
        }
    }
    buffer[i++] = block_address; // Block address

    ....

     

    This is the code for IRQ management (please see also the questions on code comments)

    TrfIrqResult SPI_TrfProcessIrq(bool anticollision, uint8_t *length)
    {
    static bool last_irq_state = FALSE;
    uint8_t read_bytes = 0;
    TrfIrqResult result = NoRead;

    if (TEST_IRQ_ON)
    {

    uint8_t irq_status = SPI_TrfReadIrqStatus();

    if (irq_status == (SPI_IRQ_TX_COMPLETED | SPI_IRQ_FIFO_STATE)) // Transmission (partial)
    {
    }
    else if (irq_status == SPI_IRQ_TX_COMPLETED) // Transmission completed
    {
        SPI_TrfResetFifo();
        if (anticollision)
        {
            Delay(50000);    // = 71ms. Less gives collision on Write (why ???)
            //SPI_TrfResetFifo();
            SPI_TrfTransmitNextSlot();    
        }
    }
    else if (irq_status == (SPI_IRQ_RX_STARTED | SPI_IRQ_FIFO_STATE)) // Reception (partial)
    {
        read_bytes = SPI_TrfReadFifo(FALSE);
        if (read_bytes == 0)
        {
            SPI_TrfReset();
            .... // Error
        }
        else
        {
            SPI_TrfResetIrqStatus();
            result = PartialRead;
        }
    }
    else if (irq_status == SPI_IRQ_RX_STARTED) // Reception completed
    {
        read_bytes = SPI_TrfReadFifo(TRUE);
        if (read_bytes == 0)
        {
            SPI_TrfReset();
            .... // Error
        }
        else
        {
            if (anticollision)
                  SPI_TrfReadRegister(TRF_ADDR_RSSI_LEVELS);
            SPI_TrfReset();
            result = EndRead;
        }

    }
    else if (irq_status == SPI_IRQ_NO_RESPONSE) // No response
    {
        SPI_TrfReadRegister(TRF_ADDR_RSSI_LEVELS);
    }
    else if (irq_status == SPI_IRQ_COLLISION) // Collision
    {
        SPI_TrfReadRegister(TRF_ADDR_COLLISION_POSITION);
    }
    else if (irq_status & SPI_IRQ_CRC_ERROR) // CRC error
    {
        SPI_TrfReset();
        ... // Error
    }
    else if (irq_status & SPI_IRQ_FRAME_ERROR) // Frame error
    {
        SPI_TrfReset();
        ... // Error
    }
    else // Interrupt register not properly set
    {
        // Inventory command rises an IRQ with irq_status = 0 (why???) so it is not correct to answer with an error in this case
        //SPI_TrfReset();
       .... // Error

    }

    }

    if (length)
        *length = read_bytes;

    return result;

    }

     

  • just to be precise... I clean up the code before send it so in the line

    buffer[i++] = block_address; // Block address

    the index of the array is correct (even if in the code I sent "i" is not defined)
  • It seems the problem it Tag-dependent.
    Using other Tags I have problem on other addresses or even I have no problem with new tags.

    So can be a problem of Tag degradation?
    It is strange becouse it seems I can always read the block at first read and after that any other command fails (no IRQ is received so timeout expires).
    Is there a way to avoid to reboot the RFID module?

    Thanks
  • I tried it with TI development kit. Sorry if I did not tried it before (it was not available to me).
    It also fails the reading on the same addresses of my software

    For example:
    12:26:39.327 --> 010B000304180020410000
    12:26:39.462 <-- 010B000304180020410000
    Request mode.
    [0110]

    So it seems some blocks can be damaged. It seems quite frequent. Is it normal?
    How can I manage these errors on my software?

    As I said I can read the first time and then I must reset RFID module becouse all other commands fails.
    The first time the read returns 00-00-00-01 instead of the expected 00-00-00-00
    In these cases, IRQs are the expected ones (0x80, 0x40) and there are no errors/collisions

    Thanks again
  • Alessandro - 

    the error code (0x0110) you are getting is telling you that you are requesting block data from a block # that does not exist. (is out of range)

    for plus tags (the largest one we offer) the memory addresses range from block 0x00 to 0x3F. You are requesting from block 0x41. Hence the error code coming back from the tag. 

    i can direct you to this document which should be a good reference for you. 

  • Hi Josh,

    thank you for the answer.
    Ok, I understand.
    I used sloa166a.pdf as reference and Fig. 1 at pag. 3 shows a range from 0x00 to 0x63 for Plus tags... but the real memory available is 256 bytes.

    Anyway I still have a problem reading some addresses on my software.
    To avoid confusion the following is the sequence I see:
    - Send read single block command (see the code on my first post)
    - Receive 0x80 and 0x40 and read the FIFO (FIFO contains the correct values)
    - Send commands ResetFifo (0x8F), StopDecoders (0x96) and a dummy ReadIrqStatus (0x4C)
    - Send any other command
    - No IRQ received (need to switch off the RFID module to reset)

    The problem is sistematic but it happens only for SOME addresses (if I change the tag, faulty addresses are different)... for most of the addresses everything works fine.
    Same addresses with TI Evalutation kit works fine.

    Best regards
    Alessandro
  • ok - that is my fault - i made the diagram in that document - its a typo of sorts. 63 (in decimal) = 0x3F (in hex)
    i'll get with our documentation guys and get that fixed.

    regarding your issue with IRQ, i think if you do continuous read on IRQ (i.e. 0x6C and 16 clocks as described in sloa155, section 7.3) then it will be fixed.

    www.ti.com/.../sloa155.pdf
  • In this moment in continuous read I put a dummy read "before"... so, write, dummy read, read. This seems to work in most cases but it causes the problem above.
    I tried to put a dummy read "after" but I still have the problem above (and obviously wrong reads)
    Removing dummy read I have wrong reads but I the problem above disappears.
    Following is my code for read/write registers. Can you take a look to see what is wrong?

    Thank you again.

    Best regards
    Alessandro

    /// Direct command to TRF (through SPI)
    void SPI_TrfDirectCommand(uint8_t command)
    {
    command = (command | 0x80) & 0x9F; // command + command code
    SET_SS_LOW;

    SPI_WriteByte(command);
    Delay(3);
    SPI_WriteByte(0x00); // Dummy write (alternatively a up/down clock cycle is needed)

    SET_SS_HIGH;
    Delay(5);
    }

    /// TRF read registers with continuous read (through SPI)
    void SPI_TrfReadRegisters(uint8_t address, uint8_t* registers, uint8_t count)
    {
    bool dummy_read = address != TRF_ADDR_IRQ_STATUS && count != 0x1F;

    address = (address | 0x60) & 0x7F;

    SET_SS_LOW;

    SPI_WriteByte(address);

    SPCR = SPI_SPCR_CONFIG | SPI_SPCR_CLOCK_PHASE;

    if (dummy_read)
    {
    Delay(5);
    SPI_ReadByte();
    }
    while (count--)
    {
    Delay(5);
    *(registers++) = SPI_ReadByte();
    }

    SPCR = SPI_SPCR_CONFIG;

    SET_SS_HIGH;
    }

    /// TRF read registers with single read (through SPI)
    void SPI_TrfReadSingleRegisters(uint8_t* addresses, uint8_t* registers, uint8_t count)
    {
    SET_SS_LOW;
    while (count--)
    {
    uint8_t address = (*(addresses++) | 0x40) & 0x5F;
    SPI_WriteByte(address);
    SSPCR = SPI_SPCR_CONFIG | SPI_SPCR_CLOCK_PHASE;
    Delay(5);
    *(registers++) = SPI_ReadByte();
    SPCR = SPI_SPCR_CONFIG ;
    }
    SET_SS_HIGH;
    }

    /// TRF write registers with single write (through SPI)
    void SPI_TrfWriteSingleRegisters(uint8_t* addresses, uint8_t* registers, uint8_t count)
    {
    SET_SS_LOW;
    while (count--)
    {
    SPI_WriteByte((*(addresses++)) & 0x1F);
    Delay(5);
    SPI_WriteByte(*(registers++));
    }
    SET_SS_HIGH;
    Delay(5);
    }

    /// TRF write registers with continuous write (through SPI)
    void SPI_TrfWriteRegisters(uint8_t address, uint8_t* registers, uint8_t count)
    {
    address = (address | 0x20) & 0x3f;
    SET_SS_LOW;
    SPI_WriteByte(address);
    while (count--)
    {
    SPI_WriteByte(*(registers++));
    }
    SET_SS_HIGH;
    Delay(5);
    }

  • Allesandro -

    put LSA or scope on it - should be like this

    COMMAND (RSB)

    EOTX IRQ

    EORX IRQ and FIFO status read and FIFO read

  • I solved adding a dummy write after reading FIFO.

    Thank you for your support.

    Best regards
    Alessandro