2024-01-03 10:35 AM
Hello,
I have a similar problem as it was asked here
https://community.st.com/t5/st25-nfc-rfid-tags-and-readers/rfal-demo-question/m-p/157070#M2943
I am trying to read 15693 tags with a board I designed myself.
I adjusted the RFAL library to use my own SPI port and the GPIO I assigned for connection to the IRQ pin. The rest as I can tell was the GT timer which uses systick and is already handled.
Here are my setting
#define RFAL_FEATURE_LISTEN_MODE false /*!< Enable/Disable RFAL support for Listen Mode */
#define RFAL_FEATURE_WAKEUP_MODE false /*!< Enable/Disable RFAL support for the Wake-Up mode */
#define RFAL_FEATURE_LOWPOWER_MODE false /*!< Enable/Disable RFAL support for the Low Power mode */
#define RFAL_FEATURE_NFCA false /*!< Enable/Disable RFAL support for NFC-A (ISO14443A) */
#define RFAL_FEATURE_NFCB false /*!< Enable/Disable RFAL support for NFC-B (ISO14443B) */
#define RFAL_FEATURE_NFCF false /*!< Enable/Disable RFAL support for NFC-F (FeliCa) */
#define RFAL_FEATURE_NFCV true /*!< Enable/Disable RFAL support for NFC-V (ISO15693) */
#define RFAL_FEATURE_T1T false /*!< Enable/Disable RFAL support for T1T (Topaz) */
#define RFAL_FEATURE_T2T false /*!< Enable/Disable RFAL support for T2T */
#define RFAL_FEATURE_T4T false /*!< Enable/Disable RFAL support for T4T */
#define RFAL_FEATURE_ST25TB false /*!< Enable/Disable RFAL support for ST25TB */
#define RFAL_FEATURE_ST25xV true /*!< Enable/Disable RFAL support for ST25TV/ST25DV */
#define RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG false /*!< Enable/Disable Analog Configs to be dynamically updated (RAM) */
#define RFAL_FEATURE_DPO false /*!< Enable/Disable RFAL Dynamic Power Output support */
#define RFAL_FEATURE_ISO_DEP false /*!< Enable/Disable RFAL support for ISO-DEP (ISO14443-4) */
#define RFAL_FEATURE_ISO_DEP_POLL false /*!< Enable/Disable RFAL support for Poller mode (PCD) ISO-DEP (ISO14443-4) */
#define RFAL_FEATURE_ISO_DEP_LISTEN false /*!< Enable/Disable RFAL support for Listen mode (PICC) ISO-DEP (ISO14443-4) */
#define RFAL_FEATURE_NFC_DEP false /*!< Enable/Disable RFAL support for NFC-DEP (NFCIP1/P2P) */
and in my main I have
void test_rfid()
{
init_rfid();
while(1)
{
run_rfid();
}
}
which these two functions are the same functions as the example but simplified to only cover NFC-V
uint8_t init_rfid()
{
ReturnCode err;
err = rfalNfcInitialize();
if( err == ERR_NONE )
{
rfalNfcDefaultDiscParams( &discParam );
discParam.devLimit = 1U;
memcpy( &discParam.nfcid3, NFCID3, sizeof(NFCID3) );
memcpy( &discParam.GB, GB, sizeof(GB) );
discParam.GBLen = sizeof(GB);
discParam.p2pNfcaPrio = true;
discParam.notifyCb = demoNotif;
discParam.totalDuration = 1000U;
discParam.techs2Find = RFAL_NFC_TECH_NONE; /* For the demo, enable the NFC Technologies based on RFAL Feature switches */
#if RFAL_FEATURE_NFCV
discParam.techs2Find |= RFAL_NFC_POLL_TECH_V;
#endif /* RFAL_FEATURE_NFCV */
#ifdef ST25R95
discParam.isoDepFS = RFAL_ISODEP_FSXI_128; /* ST25R95 cannot support 256 bytes of data block */
#endif /* ST25R95 */
err = rfalNfcDiscover( &discParam );
if( err != ERR_NONE )
{
return false;
}
state = DEMO_ST_START_DISCOVERY;
return true;
}
return false;
}
void run_rfid()
{
static rfalNfcDevice *nfcDevice;
rfalNfcWorker(); /* Run RFAL worker periodically */
switch( state )
{
/*******************************************************************************/
case DEMO_ST_START_DISCOVERY:
multiSel = false;
state = DEMO_ST_DISCOVERY;
break;
/*******************************************************************************/
case DEMO_ST_DISCOVERY:
if( rfalNfcIsDevActivated( rfalNfcGetState() ) )
{
rfalNfcGetActiveDevice( &nfcDevice );
switch( nfcDevice->type )
{
/*******************************************************************************/
case RFAL_NFC_LISTEN_TYPE_NFCV:
{
uint8_t devUID[RFAL_NFCV_UID_LEN];
//platformLedOn(PLATFORM_LED_V_PORT, PLATFORM_LED_V_PIN);
memcpy( devUID, nfcDevice->nfcid, nfcDevice->nfcidLen ); /* Copy the UID into local var */
REVERSE_BYTES( devUID, RFAL_NFCV_UID_LEN ); /* Reverse the UID for display purposes */
//platformLog("ISO15693/NFC-V card found. UID: %s\r\n", hex2Str(devUID, RFAL_NFCV_UID_LEN));
char buffer[50];
sprintf(buffer, "ISO15693/NFC-V card found. UID: %x%x %x%x %x%x %x%x\r\n", devUID[0],devUID[1],devUID[2],devUID[3],devUID[4],devUID[5],devUID[6],devUID[7]);
HAL_UART_Transmit(&huart1, buffer, strlen(buffer), 5);
demoNfcv( &nfcDevice->dev.nfcv );
}
break;
default:
break;
}
rfalNfcDeactivate( RFAL_NFC_DEACTIVATE_DISCOVERY );
state = DEMO_ST_START_DISCOVERY;
}
break;
/*******************************************************************************/
case DEMO_ST_NOTINIT:
default:
break;
}
}
But I never get past
if( rfalNfcIsDevActivated( rfalNfcGetState() ) )
it is always in RFAL_NFC_STATE_POLL_TECHDETECT which seems like is not the correct state.
Here is my notif function
static void demoNotif( rfalNfcState st )
{
uint8_t devCnt;
rfalNfcDevice *dev;
if( st == RFAL_NFC_STATE_WAKEUP_MODE )
{
//platformLog("Wake Up mode started \r\n");
}
else if( st == RFAL_NFC_STATE_POLL_TECHDETECT )
{
if( discParam.wakeupEnabled )
{
//platformLog("Wake Up mode terminated. Polling for devices \r\n");
}
}
else if( st == RFAL_NFC_STATE_POLL_SELECT )
{
/* Check if in case of multiple devices, selection is already attempted */
if( (!multiSel) )
{
multiSel = true;
/* Multiple devices were found, activate first of them */
rfalNfcGetDevicesFound( &dev, &devCnt );
rfalNfcSelect( 0 );
//platformLog("Multiple Tags detected: %d \r\n", devCnt);
}
else
{
rfalNfcDeactivate( RFAL_NFC_DEACTIVATE_DISCOVERY );
}
}
else if( st == RFAL_NFC_STATE_START_DISCOVERY )
{
/* Clear multiple device selection flag */
multiSel = false;
}
}
I can also tell you my worker function always goes to line 1075 rfal_nfc.c
and never goes in
if( rfalIsGTExpired() ) /* Wait until Guard Time is fulfilled */
even though the timer is activated a few lines before.
Can you tell me what am I missing?
Solved! Go to Solution.
2024-01-16 09:56 AM
Hi,
after investigation in private, it appears that the IRQ_OUT pin is not connected whereas the RFAL is relying in this pin to read the responses from the ST25R95.
In that case the st25r95SPIPollRead function needs to be modified to use the SPI poll mode instead of the interrupt mode. Here is the modified function
/*******************************************************************************/
ReturnCode st25r95SPIPollRead(uint32_t timeout)
{
uint32_t timer;
ReturnCode retCode = ERR_NONE;
uint8_t response;
timer = platformTimerCreate(timeout);
do {
platformSpiSelect();
platformDelay(1);
st25r95SPISendReceiveByte(ST25R95_CONTROL_POLL);
response = st25r95SPISendReceiveByte(ST25R95_CONTROL_POLL);
platformSpiDeselect();
}
while (!ST25R95_POLL_DATA_CAN_BE_READ(response) && (timeout != 0) && !platformTimerIsExpired(timer));
if (!ST25R95_POLL_DATA_CAN_BE_READ(response))
{
retCode = ERR_TIMEOUT;
}
return (retCode);
}
Note that IRQ_OUT is needed for some features such as the WFE mode (see Idle command in the datasheet). Make sure not to use this WFE mode when the IRQ_OUT is not connected.
Rgds
BT
2024-01-03 10:53 AM
Hi,
can you connect a logic analyzer on SPI (CLK/MOSI/MISO/CS) + IRQ_IN + IRQ_OUT and send me the trace in private?
If you do not have logic analyzer, can you set ST25R95_DEBUG to true in st25r95_com.c and st25r95_com_spi.c and output the trace on a serial port?
Rgds
BT
2024-01-16 09:56 AM
Hi,
after investigation in private, it appears that the IRQ_OUT pin is not connected whereas the RFAL is relying in this pin to read the responses from the ST25R95.
In that case the st25r95SPIPollRead function needs to be modified to use the SPI poll mode instead of the interrupt mode. Here is the modified function
/*******************************************************************************/
ReturnCode st25r95SPIPollRead(uint32_t timeout)
{
uint32_t timer;
ReturnCode retCode = ERR_NONE;
uint8_t response;
timer = platformTimerCreate(timeout);
do {
platformSpiSelect();
platformDelay(1);
st25r95SPISendReceiveByte(ST25R95_CONTROL_POLL);
response = st25r95SPISendReceiveByte(ST25R95_CONTROL_POLL);
platformSpiDeselect();
}
while (!ST25R95_POLL_DATA_CAN_BE_READ(response) && (timeout != 0) && !platformTimerIsExpired(timer));
if (!ST25R95_POLL_DATA_CAN_BE_READ(response))
{
retCode = ERR_TIMEOUT;
}
return (retCode);
}
Note that IRQ_OUT is needed for some features such as the WFE mode (see Idle command in the datasheet). Make sure not to use this WFE mode when the IRQ_OUT is not connected.
Rgds
BT
2024-01-16 10:30 AM
Thank you, Brian and the team for your responsiveness and support.