2021-04-06 01:22 AM
Hi,
I have implemented a smart card in software and the ccid class to interface it via the usb, everything works correctly even for long cryptographic operations (using wtx).
Now I wanted to extend the functionality of my card by adding the NFC interface and the chip I chose is the st25r3916 for possible future use as a reader as well.
I started from the demo_ce.c example in X-CUBE-NFC6 (STM32CubeExpansion_NFC6_V1.1.0) and everything works correctly until operations that take a short time to be performed, operations such as signature or key generation all fail by disconnecting the card from the reader.
What can I do to solve this problem? is there any way to implement the sending of the wtx packet in nfc as well?
Thanks and regards.
D.
Solved! Go to Solution.
2021-04-12 11:59 PM
Hi Pagano.paganino,
I looked in the code and indeed we don't have a fully non-blocking demo code. The underlying APIs are all meant to be used non-blocking. Looking into demoCE() you can instead of the do{}while call it multiple times. If you also transform it like this:
do
{
rfalNfcWorker();
switch( rfalNfcGetState() )
{
case RFAL_NFC_STATE_ACTIVATED:
err = rfalNfcDataExchangeStart( NULL, 0, &rxData, &rcvLen, 0 ); // First transceive without tx data to get first poller frame
if (ERR_NONE != err) break;
/* Intentional Fallthrough - call GetStatus once to get out of RFAL_NFC_STATE_ACTIVATED */
case RFAL_NFC_STATE_DATAEXCHANGE:
err = rfalNfcDataExchangeGetStatus();
break;
case RFAL_NFC_STATE_DATAEXCHANGE_DONE:
txLen = ( (nfcDev->type == RFAL_NFC_POLL_TYPE_NFCA) ? demoCeT4T( rxData, *rcvLen, txBuf, sizeof(txBuf) :( demoCeT3T( rxData, *rcvLen, txBuf, sizeof(txBuf) ) );
err = rfalNfcDataExchangeStart( txBuf, txLen, &rxData, &rcvLen, 0 );
break;
case RFAL_NFC_STATE_LISTEN_SLEEP:
default:
break;
}
}
while( (err == ERR_NONE) || (err == ERR_SLEEP_REQ) || (err==ERR_BUSY) );
You will then have it fully non-blocking. Just call it at a decent frequency. The alternative would be to use the notifyCb and only issue rfalNfcDataExchangeStart()/GetStatus() and keep the state information inside the your code.
Regards, Ulysses
2021-04-06 02:03 AM
Hi pagano.paganino,
sending wtx packets is implemented in RFAL. However you need to make sure to give RFAL time to perform such job by calling rfalNfcWorker() before FWT times out. The other alternative would be to change the used FWT (currently RFAL_ISODEP_DEFAULT_FWI with ~77ms is used).
Regards, Ulysses
2021-04-07 12:37 AM
Hi Ulysses,
I tried as you suggested to invoke rfalNfcWorker(), in detail I invoked it in a periodic timer every 50ms but the result does not change.
Any other suggestions?
Thanks
2021-04-07 12:52 AM
Hi pagano.paganino,
as mentioned above:
Inside rfalNfcListenActivation() please change atsParam.fwi = RFAL_ISODEP_DEFAULT_FWI; and give fwi a bigger value. You can consider increasing up to ~5secs. Of course this will have an impact on reactivity. How much time does your crypto take?
Otherwise please do Logic Analyzer traces of SPI + IRQ + trigger pin on calling rfalNfcWorker(). It could also be a timing issue or porting issue in the timer interface.
Best Regards, Ulysses
2021-04-07 01:11 AM
I tried to change the default value of the fwi but cryptographic operations can also take several seconds (e.g. rsa) and therefore the road to increase the value to the maximum possible is not viable.
2021-04-10 05:24 AM
Hi Ulysses,
where can i find an example of card emulation mode using non-blocking api?
All the examples I found are in blocking mode, any suggestions on where to find it or how to implement it?
Thanks and best Regards,
D.
2021-04-12 11:59 PM
Hi Pagano.paganino,
I looked in the code and indeed we don't have a fully non-blocking demo code. The underlying APIs are all meant to be used non-blocking. Looking into demoCE() you can instead of the do{}while call it multiple times. If you also transform it like this:
do
{
rfalNfcWorker();
switch( rfalNfcGetState() )
{
case RFAL_NFC_STATE_ACTIVATED:
err = rfalNfcDataExchangeStart( NULL, 0, &rxData, &rcvLen, 0 ); // First transceive without tx data to get first poller frame
if (ERR_NONE != err) break;
/* Intentional Fallthrough - call GetStatus once to get out of RFAL_NFC_STATE_ACTIVATED */
case RFAL_NFC_STATE_DATAEXCHANGE:
err = rfalNfcDataExchangeGetStatus();
break;
case RFAL_NFC_STATE_DATAEXCHANGE_DONE:
txLen = ( (nfcDev->type == RFAL_NFC_POLL_TYPE_NFCA) ? demoCeT4T( rxData, *rcvLen, txBuf, sizeof(txBuf) :( demoCeT3T( rxData, *rcvLen, txBuf, sizeof(txBuf) ) );
err = rfalNfcDataExchangeStart( txBuf, txLen, &rxData, &rcvLen, 0 );
break;
case RFAL_NFC_STATE_LISTEN_SLEEP:
default:
break;
}
}
while( (err == ERR_NONE) || (err == ERR_SLEEP_REQ) || (err==ERR_BUSY) );
You will then have it fully non-blocking. Just call it at a decent frequency. The alternative would be to use the notifyCb and only issue rfalNfcDataExchangeStart()/GetStatus() and keep the state information inside the your code.
Regards, Ulysses
2021-04-19 02:05 AM
@Ulysses HERNIOSUS_O Otherwise please do Logic Analyzer traces of SPI + IRQ + trigger pin on calling rfalNfcWorker(). It could also be a timing issue or porting issue in the timer interface.
I ordered a logic analyzer, as soon as I can give you more details I will update you about it.
Thanks and best Regards,
D.