cancel
Showing results for 
Search instead for 
Did you mean: 

How to use rfalNfcvPollerTransceiveReq() for custom commands (e.g. D2/D3/D4/D5)?

MERSI
Associate III

 

Hi all,

I’m using an ST25R3916 with RFAL on an STM32 and I’m trying to talk to an NXP NTAG 5 Boost (ISO15693/NFC-V) using its custom commands: READ/WRITE SRAM (0xD2/0xD3) and READ/WRITE I²C (0xD5/0xD4).

Plain ISO15693 commands work fine (e.g., ReadSingleBlock / WriteSingleBlock). For example, reading config block 0x37 returns:

 

 
REQ: flags 0x22, CMD 0x20, UID=<8 bytes>, DATA=0x37 RSP: 00 08 DB CF 00

Now I’d like to send the NXP customs via rfalNfcvPollerTransceiveReq(), but I’m not getting a response (often RFAL_ERR_TIMEOUT).


What I’m calling now

For customs I call rfalNfcvPollerTransceiveReq(cmd, flags, param, uid, payload, payloadLen, rx, rxLen, &rcvLen) like this:

  • flags: RFAL_NFCV_REQ_FLAG_DEFAULT (0x02, high data rate, no option bit)

  • param: 0x04 (NXP manufacturer code)

  • uid: 8-byte UID (addressed mode)

  • payload and length per the NTAG 5 Boost datasheet (see below)

  • rx: buffer big enough + checking rcvLen

Example (READ SRAM, command 0xD2:(

uint8_t tx[2] = { startBlock, (uint8_t)(numBlocks - 1) }; // request N blocks
uint8_t rx[1 + 4*64] = {0}; // RES_FLAGS + data uint16_t rcv = 0;
ReturnCode rc = rfalNfcvPollerTransceiveReq( 0xD2, // READ SRAM 
                                             RFAL_NFCV_REQ_FLAG_DEFAULT, // 0x02
                                             0x04, // NXP mfg code
                                             uid, // addressed mode
                                             tx,
                                             sizeof(tx),
                                             rx,
                                             sizeof(rx),
                                             &rcv );

Similarly for WRITE SRAM (0xD3) and I²C bridge (0xD4/0xD5).


Datasheet framing I’m following (READ/WRITE SRAM)

From the NTAG 5 Boost user manual (table looks like this):

READ SRAM (0xD2) request

  • Flags (8)

  • READ SRAM (8) = 0xD2

  • Manuf. code (8) = 0x04

  • UID (64, optional if addressed mode)

  • Block Address (8)

  • Number of Blocks (8) — value is N-1 (so 0x00 means 1 block)

  • CRC16

READ SRAM response (no error)

  • Flags (8)

  • (Number of Blocks + 1) × 32 bits Data

  • CRC16

WRITE SRAM (0xD3) request

  • Flags (8)

  • WRITE SRAM (8) = 0xD3

  • Manuf. code (8) = 0x04

  • UID (optional)

  • Block Address (8)

  • Number of Blocks (8) — N-1

  • Data = N × 4 bytes

  • CRC16

Only Option_flag = 0 is supported for D2/D3. Datasheet also says SRAM must be enabled and not protected.

My payload lengths follow that (READ: 2 bytes payload; WRITE: 2 + 4*N).


What works vs. what fails

  • ISO15693 ReadSingleBlock/WriteSingleBlock via rfalNfcvPollerReadSingleBlock() / ...WriteSingleBlock() → OK

  • NXP custom 0xD2/0xD3/0xD4/0xD5 via rfalNfcvPollerTransceiveReq() as above → mostly RFAL_ERR_TIMEOUT


Questions

  1. param field in rfalNfcvPollerTransceiveReq
    For customs should I always pass 0x04 (NXP mfg code)? Or should param be skipped (RFAL_NFCV_PARAM_SKIP) and the mfg code embedded somewhere else?

  2. Flags / Addressed mode
    Is RFAL_NFCV_REQ_FLAG_DEFAULT (0x02) correct for D2/D3/D4/D5?
    Should I also set RFAL_NFCV_REQ_FLAG_ADDRESS myself, or does RFAL add it automatically when uid != NULL?

  3. Option flag
    READ/WRITE SRAM specify “Only Option_flag = 0b is supported”. I’m keeping Option=0. Is that correct with RFAL (i.e., don’t set RFAL_NFCV_REQ_FLAG_OPTION)?

  4. Buffer sizes / rcvLen
    Is there any RFAL limit/quirk for rxBuf lengths on customs I should be aware of?

If anyone has a minimal working call for Custom Commands (e.g. NTAG 5 Boost 0xD2/0xD3) using rfalNfcvPollerTransceiveReq(), I’d really appreciate a short snippet showing the exact flags, param, and payload formatting.

Thanks!


MERSI_0-1755118326929.pngMERSI_1-1755118344726.png

 

1 ACCEPTED SOLUTION

Accepted Solutions
Ulysses HERNIOSUS
ST Employee

Hi,

looks about right. 

Ad 1) correct way for custom commands

ad 2) RFAL looks at uid==NULL and sets the addressed flag if there 

ad 3) correct

ad 4) rx buf needs to be able to cope also with the CRC (even if not recieved/wished for). If the CRC does not fit you would get a NO_MEM code.

You could do a logic analyzer trace and provide it here (SPI+IRQ). When doing so, please also enable the NFC-V debugging code inside rfal_rfst25r3916.c (#if 0 -> 1).

Are you sure the tag you are using is actually supporting the commands? Maybe you can verify using the manufacturers tools/apps.

BR, Ulysses

View solution in original post

5 REPLIES 5
Ulysses HERNIOSUS
ST Employee

Hi,

looks about right. 

Ad 1) correct way for custom commands

ad 2) RFAL looks at uid==NULL and sets the addressed flag if there 

ad 3) correct

ad 4) rx buf needs to be able to cope also with the CRC (even if not recieved/wished for). If the CRC does not fit you would get a NO_MEM code.

You could do a logic analyzer trace and provide it here (SPI+IRQ). When doing so, please also enable the NFC-V debugging code inside rfal_rfst25r3916.c (#if 0 -> 1).

Are you sure the tag you are using is actually supporting the commands? Maybe you can verify using the manufacturers tools/apps.

BR, Ulysses

Hi @Ulysses HERNIOSUS ,

if i debug the code currently the rfalTransceiveBlockingTxRx(...) in rfalTransceiveBlockingTxRx(...) does not return an error (return value = 0). 

Then it checks further down in this function if an error has been in the received frame (answer). 


/* Check if an error has been signalled */
if( (rxBuf[RFAL_NFCV_FLAG_POS] & (uint8_t)RFAL_NFCV_RES_FLAG_ERROR) != 0U )
{
return rfalNfcvParseError( rxBuf[RFAL_NFCV_DATASTART_POS] );
}

The Value of the error_pos equals 0xF (dec. 15). For all my custom commands. 
But i do not understand why. Therefore i guess it is a configuration problem of my used NFC I2C Bridge (NTAG5 Boost). Or what do you guess? Do you know what 0xF normally stands for? What does this error mean exactly?  

Ulysses HERNIOSUS
ST Employee

Hi,

according to ISO/IEC 15693-3: '0F' : Error with no information given or a specific error code is not supported.

I think the manufacturer DS should indicate more conditions when this 0Fh is reported. I think 8.2.6.2 of its DS indicates that "received command or option is not supported".

BR, Ulysses

Hi @Ulysses HERNIOSUS ,

Thank you so much so far :)
So the Commands for ReadI2C and WriteI2C should be executed the exact same way using the rfal - right? Or am i understanding the rfal function wrong? rx / sizeof(rx) can be larger then needed - or might this lead to a problem? 

So first i would write the ADC register i want to read out via WriteI2C and then immediately i would send a ReadI2C with the amount of data to read from the ADC (speficied by the ADC register). 

// I²C bridge (0xD4/0xD5)
uint8_t tx[2] = { i2c_slave_addr, data_length_rx }; 
uint8_t rx[data_length_rx ] = {0};
ReturnCode rc = rfalNfcvPollerTransceiveReq( 0xD4, 
RFAL_NFCV_REQ_FLAG_DEFAULT, // 0x02
0x04, // NXP mfg code
uid, // addressed mode
tx,
sizeof(tx),
rx,
sizeof(rx),
&rcv );

 

 

MERSI_0-1755781352316.png

 

Hi,

rx size should be at least two bytes bigger then needed when using ST25R39xx devices (as RFAL is internally using the Stream mode and does need to receive and check CRC in SW). It can be even bigger.

BR Ulysses