2025-05-29 11:31 AM
Hi,
I am working on a project, where I want to maximize the speed when using the mailbox with the ST25xV commands.
I use a ST25R3916B Reader and a ST25DV04K Tag.
The data exchange process in my application looks like this:
-(fast)write command
-(fast)read dyn config (polling: wait until message owner has changed)
-(fast)read response
I measure the time over the whole exchange and when I use the "fast" commands it somehow gets slower. I have read this forum post about the differences of the normal and "fast" commands. There it is mentioned that the fast commands double the response data rate. So I would expect at least a slight increase in speed and not it being slower. Can anybody explain this behaviour?
Also: any recommendations on how to further increase speed are highly welcome.
Rgds,
Jonas
2025-05-29 2:05 PM
Hi,
Do you use the RFAL and the related rfalST25xVPollerFastReadDynamicConfiguration/etc. or your own FW implementation on top of te ST25R3916B? If using the RFAL, can you provide the code being used? How do you measure the transceive duration: systick? cycle counter? Can you provide your measurement for fast and non fast cases?
Can you connect a logic analyzer on SPI (CLK/MOSI/MISO/CS) + IRQ and provide a trace for fast and non fast cases?
Note: it is not expected to have significant improvements with Fast Write Message as the response is only very few bytes. This command is designed to avoid reprogramming the reader bitrate during message read/message write sequence.
Rgds
BT
2025-05-29 2:50 PM
Hi,
Yes I use RFAL and related ST25xVPoller commands.
Here are the snippets where the commands are used:
Get Message owner:
static ftmDespumoMessageOwner_t ftmDespumoGetMessageOwner(void) {
uint8_t mbStatus = 0;
ReturnCode err;
#if DESPUMO_USE_ST25DV_FAST_CMDS == true
err = rfalST25xVPollerFastReadDynamicConfiguration(
RFAL_NFCV_REQ_FLAG_DEFAULT,
NULL, ST25DV_I2C_DYN_REG_MB_CTRL_ADDR, &mbStatus);
#else
err = rfalST25xVPollerReadDynamicConfiguration(RFAL_NFCV_REQ_FLAG_DEFAULT,
NULL, ST25DV_I2C_DYN_REG_MB_CTRL_ADDR, &mbStatus);
#endif
if (err == RFAL_ERR_NONE) {
if (mbStatus & ST25DV_I2C_DYN_REG_MB_CTRL_HOST_PUT_MSG) {
return FTM_DESPUMO_MESSAGE_TAG;
} else if (mbStatus & ST25DV_I2C_DYN_REG_MB_CTRL_RF_PUT_MSG) {
return FTM_DESPUMO_MESSAGE_READER;
} else {
return FTM_DESPUMO_MESSAGE_EMPTY;
}
}
return FTM_DESPUMO_MESSAGE_OWNER_ERROR;
}
Wait until mailbox is empty and then send command:
while (ftmDespumoGetMessageOwner() != FTM_DESPUMO_MESSAGE_EMPTY
&& !platformTimerIsExpired(timeout)) {
platformDelay(6); //don't spam because else the tag cannot write the response because its always busy
}
if (platformTimerIsExpired(timeout)) {
platformLog("Tag mailbox empty timeout.\n");
ftmDespumoResetMailbox();
return true;
}
/* write message */
#if DESPUMO_USE_ST25DV_FAST_CMDS == true
ret = rfalST25xVPollerFastWriteMessage(RFAL_NFCV_REQ_FLAG_DEFAULT, NULL,
cmdLen, cmd, txBuf, txBufLen);
#else
ret = rfalST25xVPollerWriteMessage(RFAL_NFCV_REQ_FLAG_DEFAULT, NULL, cmdLen,
cmd, txBuf, txBufLen);
#endif
Wait for response and then read message:
while (ftmDespumoGetMessageOwner() != FTM_DESPUMO_MESSAGE_TAG
&& !platformTimerIsExpired(timeout)) {
platformDelay(10); //don't spam because else the tag cannot write the response because its always busy
// 6ms should be stable (tested with 2000 consecutive set cronjob commands with max payload)
}
if (platformTimerIsExpired(timeout)) {
platformLog("Tag response timeout.\n");
ftmDespumoResetMailbox();
return true;
}
/* read message */
ReturnCode ret;
#if DESPUMO_USE_ST25DV_FAST_CMDS == true
ret = rfalST25xVPollerFastReadMessage(RFAL_NFCV_REQ_FLAG_DEFAULT, NULL, 0,
0, rspBuf, rspBufLen, rcvLen);
#else
ret = rfalST25xVPollerReadMessage(RFAL_NFCV_REQ_FLAG_DEFAULT, NULL, 0, 0,
rspBuf, rspBufLen, rcvLen);
#endif
I receive the Commands via USB and after checking if the frame is valid I forward it via NFC. The time is measured on the computer and starts when it sends the command and stops when the answer has arrived. I usually do 200 Iterations for the same command and readout consequentially and then take the average.
For 1 specific command I measured 29ms standard and 33 with fast commands. When measuring commands with bigger payloads the difference between standard and fast commands increases.
I don't have logic analyzer traces as of now, but I could provide them tomorrow.
@Brian TIDAL wrote:Note: it is not expected to have significant improvements with Fast Write Message as the response is only very few bytes. This command is designed to avoid reprogramming the reader bitrate during message read/message write sequence.
What exactly do you mean by response? When I talk about the response I mean the data that the tag-side uC puts in the mailbox as a response to my commands. But I now get a feeling that you talk about some NFC protocol interactions that are hidden deep in the RFAL. Because in my case the response might get bigger than "just a few bytes".
Rgds
2025-05-30 4:58 AM
Hi Jonas,
an RF transaction is basically a Command sent by the reader followed by a Response sent by the tag. When using standard ISO15693 commands, the same 26 kbps bit rate is used for both the Command and the Response. When using a fast command, the 52 kbps bit rate is only used for the Response sent by the tag whereas the Command still uses a 26kbps bit rate.
When using the Fast Read Message to read the full mailbox, the response is a 259 bytes frame: 1 (response flag) + 256 (payload) + 2 (CRC).
When using the Fast Write Message, the response is only a 3 bytes frame (response flag + CRC). Thus compared to the gain for Fast Read Message vs Read Message, the gain on Fast Write Message vs Write Message is very marginal. Same for Fast Read Dynamic Configuration vs Read Dynamic Configuration (4 bytes).
What I see in your code: after a message is written from RF side, a getMessageOwner is called without any delay and in case of error some retries are attempted every 10 ms. I suspect that in case of Fast Write Message, the getMessageOwner is performed slightly before compared to the Write Message case and thus colliding with mailbox reading from I2C (==> error ==> delay 10ms). I would suggest to instrument your code to store the tick before the Write Message then before the getMessageOwner then before and after the Read Message. Also I would store the number of retries for each getMessageOwner for a given sequence. I would print the values on the serial port just after the end of a given sequence to avoid introducing serial com delays inside the sequence. Then compare Fast and non-Fast. If you see more collision in getMessageOwner in case of Fast commands, I would suggest to add an short initial delay before the getMessageOwner and to reduce the 10ms delay.
By the way, and FTM implementation is available in the ST25 embedded NFC library (FTM demo). I would suggest to have a look on it.
Rgds
BT