Skip to main content
Associate II
August 3, 2026
Question

st25r3911b Tag Detection Issue

  • August 3, 2026
  • 8 replies
  • 130 views

So our System works fine most of the time but sometimes the Reader does not detect the tag and we observe that 
rfalNfcState are just keep fluctuating between RFAL_NFC_STATE_POLL_TECHDETECT and  RFAL_NFC_STATE_LISTEN_TECHDETECT  same as when no tag present in the field of Reader and it is not able to satisfy this if condition.

if( rfalNfcIsDevActivated( rfalNfcGetState() ) ) // this if condition

We observed that even if we do controller reset it doesn’t fix the issue only when we power cycle the reader{st25r3911b} it start working again normally.

I’m attaching the code with this i want your team to review it to let us know what exactly we are doing wrong which leading to this state where our rfal state machine not switching properly, With Restart_flag we are doing reinitialization i want you to review that whatever sequence we are following is correct or not 
 

Main.c  {Rfid Reinitialization sequence}

Please help us fix this issue and could you provide or help us that through software function or any register so that can we reset the reader without need to manually power cycle the reader.

Kindly find the attachments attached of main.c and demo.c.

8 replies

DDSAuthor
Associate II
August 3, 2026

One more observation which we made for interruptregister.status, we have attached the behavior in working state as well as non working state.
Kindly find the attachment below.

Brian TIDAL
ST Technical Moderator
August 3, 2026

Hello,

The following summary reflects the current understanding:

  • The system is based on an STM32 microcontroller (MCU) and an ST25R3911B.
  • The firmware runs under FreeRTOS™.
  • TASK03 runs the NFC demo cycle.
  • Only Type 5 tags are used to store and read data in the tag memory.
  • Restart_flag is set to true when an abnormal condition, for example, a timeout, occurs. This action restarts the ST25R3911B.

The following comments apply to the reviewed code:

  • The priorities of TASK03 and TASK04 do not match the comment.
  • HAL_GetTick() returns a uint32_t unsigned value, whereas t_rfid = HAL_GetTick() - t_0; uses signed arithmetic.
  • The code mixes RF abstraction layer (RFAL) high-layer calls, such as rfalNfc calls, with RFAL low-layer calls, such as rfalNfcvPollerInitialize. This use is not recommended.
  • st25r3911WriteRegister(02, 0x00) and st25r3911OscOn() inside the NFC demo cycle must be used with caution. Is the purpose to suspend the NFC feature temporarily? If yes, simply add a DEMO_ST_SUSPENDED state, enter this state with a rfalNfcDeactivate and exit this state with state = DEMO_ST_START_DISCOVERY;

Please clarify the following points:

  • Does the design use an STM32 Nucleo board with an X-NUCLEO-NFC05A1 expansion board, or a custom board?
  • How is the ST25 IRQ handled?
  • How is SPI communication protected between the ST25 IRQ interrupt service routine and the NFC task?
  • How is the NFC platform timer handled?
  • What is the priority of the FreeRTOS timer task, if it is used? The default timer task priority of 2 usually causes many issues. The priority should be higher than the priorities of the other tasks, typically 48.
  • Is the wake-up mode of the ST25R3911B used?
  • Which NFC features are enabled in RFAL platform.h ? Only RFAL_FEATURE_NFCV seems necessary in this application, and possibly RFAL_FEATURE_WAKEUP_MODE.

To restart the ST25R3911B:

  • Do not call rfalInitializerfalFieldOffrfalNfcvPollerInitialize, or rfalFieldOnAndStartGT.
  • Do not call st25r3911Initialize.
  • Call rfalDeinitialize, and then call demoIni.

To investigate further, connect a logic analyzer to SPI CLK, MOSI, MISO, CS, and ST25 IRQ, and provide the raw trace file.

Rgds

BT

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
Visitor II
August 7, 2026

Hey Brian,
Sorry for let response, I was out of town so could not reply.
I will try to Answer the question u have raised best of my knowledge; I have also Attached my Whole project {with Changes you suggested} Zip file along with it for better understanding.
 

Does the design use an STM32 Nucleo board with an X-NUCLEO-NFC05A1 expansion board, or a custom board?

Ans We are using Custom Board with ST25R911B with STM32f401.

How is the ST25 IRQ handled?

Ans We Have configured as external Interrupt with priority 2 and calling st25r3911Isr() fn in IRQ Handler.
 

ISR 

How is SPI communication protected between the ST25 IRQ interrupt service routine and the NFC task?

Ans Although we are not using any extensive protection just cs pin we are pulling low/High, Can you suggest what is best ?
 

Platform.h

     

st25r3911_com.c

How is the NFC platform timer handled?

Ans We are using same HAL_Get_Tick() functions which is based on Timer 2.

Platform.h

What is the priority of the FreeRTOS timer task, if it is used? The default timer task priority of 2 usually causes many issues. The priority should be higher than the priorities of the other tasks, typically 48

Ans  We are using systick timer for RTOS and it priority is 16.

 

Is the wake-up mode of the ST25R3911B used?

Ans Yes, we set it true, but not sure about whether it is truly used or not.
 

Platform.h

 We observed that sometimes not a single interrupt coming from the reader, And as we mentioned that with power cycle it is working again, even if we do controller reset it is not resolving so only which is power resetting additionally is our reader while doing power cycle so we implemented PNP based switching to power on and power off the reader but it is not resolving the issue as after doing power off and power on the reader only once interrupt triggers. so could you verify what we are missing in initialization process which happens with power recycle of whole system but not in our case.

void ST25R3911_PowerOff(void)
{

/* 2. Disable interrupt */
HAL_NVIC_DisableIRQ(EXTI1_IRQn);
HAL_NVIC_ClearPendingIRQ(EXTI1_IRQn);

/* 3. Wait for ongoing SPI transfer to finish */
uint32_t tick = HAL_GetTick();
while (HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY)
{
if ((HAL_GetTick() - tick) > 100) break;
}

/* 4. Deassert CS */
HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);

/* 5. Deinitialize SPI peripheral */
HAL_SPI_DeInit(&hspi1);

/* 6. Put SPI, CS, and EXTI pins into High-Impedance (Analog) mode */
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Pin = SPI1_NSS_Pin;
HAL_GPIO_Init(SPI1_NSS_GPIO_Port, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_5 | GPIO_PIN_6 | GPIO_PIN_7; // SCK, MISO, MOSI
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

GPIO_InitStruct.Pin = GPIO_PIN_1; // EXTI1 pin
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

/* 7. Turn OFF ST25 power rail */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_SET);

/* 8. Discharge delay */
osDelay(100);
}

void ST25R3911_PowerOn(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};

/* 1. RE-INITIALIZE CS PIN FIRST (Output High) */
GPIO_InitStruct.Pin = SPI1_NSS_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(SPI1_NSS_GPIO_Port, &GPIO_InitStruct);
HAL_GPIO_WritePin(SPI1_NSS_GPIO_Port, SPI1_NSS_Pin, GPIO_PIN_SET);

/* 2. RE-INITIALIZE EXTI PIN (Driven mode, NVIC disabled) */
GPIO_InitStruct.Pin = INTR_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(INTR_GPIO_Port, &GPIO_InitStruct);

/* 8. Enable NVIC interrupt AFTER demoIni() completes setup */
HAL_NVIC_SetPriority(EXTI1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI1_IRQn);


/* 3. RE-INITIALIZE SPI1 PERIPHERAL FIRST (Just like main) */
MX_SPI1_Init();
spiInit(&hspi1);

/* 4. NOW TURN ON ST25 POWER (SPI is ready waiting for it) */
HAL_GPIO_WritePin(GPIOB, GPIO_PIN_8, GPIO_PIN_RESET);

/* 5. Allow power rail and internal ST25 oscillator to stabilize */
osDelay(50);

/* 6. Clear any power-up noise/edges from EXTI hardware latch & NVIC */
/* 7. Initialize ST25 registers via SPI */
if (!demoIni())
{
y = 59;
return;
}

y = 0;
Ethercat_packet_data_ptr->Header = 0;



}

and this is where we are calling these function.

void StartTask03(void const * argument)
{

/* USER CODE BEGIN StartTask03 */
/* Infinite loop */
for(;;)
{
#if Tasks_rtos_monitoiring
Ethercat_packet_data_ptr->instrument_version = last_used_month++;
Task3Alive = HAL_GetTick(); //added for experiment
#endif
#if read_block_testing
// if(bEcatOutputUpdateRunning)
#endif
#if !read_block_testing
uint8_t current = Instrument_write_ptr->Header;
if((current == 122) && ( Ethercat_packet_data_ptr->Status_word==144) )
{

ST25R3911_PowerOff();
Ethercat_packet_data_ptr->Status_word=146;
prev_header = 7;
}
if((current == 122) && ( Ethercat_packet_data_ptr->Status_word==146))
{
osDelay(10);
continue;
}
else if((current == 123) && (Ethercat_packet_data_ptr->Status_word==146 && prev_header != 5))
{ //Restart_flag=1;
ST25R3911_PowerOn();
prev_header = 5;
Ethercat_packet_data_ptr->Status_word=0;
}

if(bEcatOutputUpdateRunning)

#endif
{
t_0 = HAL_GetTick();
demoCycle();
t_rfid = HAL_GetTick() - t_0;

//exampleRfalPollerRun();

#if Int_verify

if ((Time_out_error_flag == 0xAA) || (Time_out_error_flag == 0x55))
{
Time_out_error_flag = 0;
count_int_time_out =0;
}
else
{
count_int_time_out++;

if(count_int_time_out >1000)
{
Restart_flag =1;
count_int_time_out =0;

}

}


#endif


if(Restart_flag && Instrument_write_ptr->Header != 25 )//&& Instrument_write_ptr->Header != 25
{
#if Tag_notdetect_issue
// Deinitialize the RFAL stack before re-initializing
rfalDeinitialize();
osDelay(100);

// Re-initialize using demoIni and update state variables
if (!demoIni()) {
y = 59;
} else {
y = 0;
Ethercat_packet_data_ptr->Header = 0;
// }
Restart_flag =0;
#if reset_verify
#if Tasks_rtos_monitoiring
Ethercat_packet_data_ptr->Tag_write_data.Last_used_Month = cnt_re++;
#endif
#endif
}
}

osDelay(4); //vTaskDelay(4); // osdelay changed from 4 msecs to 100 msecs by venkat on 8th jan 2025
}
/* USER CODE END StartTask03 */
}



  

Brian TIDAL
ST Technical Moderator
August 7, 2026

Hello,

To investigate further, connect a logic analyzer to SPI CLK, MOSI, MISO, CS, and ST25 IRQ, and provide the raw trace file. The raw trace file helps clarify the issue.

Enable the ST25R_SELFTEST compilation flag. The flag is used in st25r3911Initialize() to check SPI communication and interrupt handling.

Check VDD and make sure that it is within the specified range, 2.4 V to 5.5 V, during the various NFC activities. See table 98 in the datasheet.

Here are some comments about the additional information:

i/ RFAL configuration

Because only type 5 tags are used in the application, the RFAL configuration can be:

#define RFAL_FEATURE_LISTEN_MODE               false      
#define RFAL_FEATURE_WAKEUP_MODE false /* or true if you really use it*/
#define RFAL_FEATURE_NFCA false
#define RFAL_FEATURE_NFCB false
#define RFAL_FEATURE_NFCF false
#define RFAL_FEATURE_NFCV true
#define RFAL_FEATURE_T1T false
#define RFAL_FEATURE_T2T false
#define RFAL_FEATURE_T4T false
#define RFAL_FEATURE_ST25TB false
#define RFAL_FEATURE_ST25xV true
#define RFAL_FEATURE_DYNAMIC_ANALOG_CONFIG false
#define RFAL_FEATURE_DYNAMIC_POWER false
#define RFAL_FEATURE_ISO_DEP false
#define RFAL_FEATURE_ISO_DEP_POLL false
#define RFAL_FEATURE_ISO_DEP_LISTEN false
#define RFAL_FEATURE_NFC_DEP false

ii/ ST25 IRQ management

st25r3911Isr() performs an SPI read of the interrupt registers. In an RTOS, the interrupt service routine must be as short as possible. The ST25 embedded NFC library, STSW-ST25RLIB002, provides an example implementation of ST25 IRQ management for FreeRTOS™ with a dedicated interrupt service routine task. The example targets ST25R3916, but it can also be used for ST25R3911B.

iii/ SPI communication protection

Because st25r3911Isr() performs an SPI read, protect SPI accesses between calls from the interrupt service routine, or interrupt service routine task, and calls from the NFC task. See platformProtectST25RComm in the FreeRTOS™ example of the ST25 embedded NFC library with taskENTER_CRITICAL and taskEXIT_CRITICAL.

iv/ Power off/ power on

Does the PNP switch ST25 VDD off and on? Check that VDD is within the specified range.

Rgds

BT

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
Visitor II
August 8, 2026

Thanks Brian,
Capturing Signals with Logic Analyzer will be tough for us as we can’t be able to recreate the issue on the bench, only in system during procedure it is occurring. Although looking at suggested RTOS project there is lot we can improve so we will try to implement that.
And as of now we have implemented the switch what we are doing is that when we need to read the tag we are powering on the reader through PNP switch and after 10 second we are powering it off and again when we need to read, we are powering it on so it is like 10-15 power cycle of reader in 1 Hr procedure so we just want to know any side effects of it on hardware? What is best way if we want to implement this.

 

Rgds

Akshay

Ulysses HERNIOSUS
ST Technical Moderator
August 11, 2026

Hello Akshay,

 

I think it is key to better understand the issue. What is happening when it is unsuccessfully fluctuating between RFAL_NFC_STATE_POLL_TECHDETECT and  RFAL_NFC_STATE_LISTEN_TECHDETECT:

  • What is the state of the IRQ pin, is it maybe statically high?
  • Is the field still being turned on? Use a LED field detector or use a scope with the ground loop connected to the tip to see the 13.56MHz carrier.
  • Are the functions for technology detection still executed without error?
    • If there are unexpected errors: Please debug into it to find the variable or register causing this.
  • Provide register snapshots when the issue happens vs when the tag is in normal state simply not in the field. Maybe taken after rfalNfcvTechnologyDetection()
  • Does it only happen at higher or lower temperature?
  • ….

Most of this would become visible from a logic analyzer trace.

About resetting the device through a PNP: I am even not sure if 10 seconds are sufficient to properly reset the device as cap at VSP_D would need to deplete through internal high-ohmic logic to sufficiently low level. VSP_D is supplying the digital logic. I don’t have at hand numbers for the allowable number of power-cycles of the device. I will inform you if I find out.

BR, Ulysses

 

Visitor II
August 11, 2026

Hii Ulysses.
Actually, there are two possible problems we are facing mostly at higher temps (>55* C) as reader is inside Actuator

  1.   Interrupt trigger by timeout is coming as usual but not able to detect the tag irrespective of Distance. Here slave state is fluctuating between RFAL_NFC_STATE_POLL_TECHDETECT and  RFAL_NFC_STATE_LISTEN_TECHDETECT. 

     

  2. No single interrupt getting triggered from the reader. {in this state interrupt.status is 0000 and interrupt.mask is 0xff} in this state is stucking in RFAL_NFC_STATE_LISTEN_TECHDETECT.

Thing with Logic Analyzer is that if we are not able to recreate the issue on Bench and doing it with system is bit difficult, but from last two days after implementation of PNP switch thing we didn’t face the issue so what should we conclude? It is Hardware issue or software issue that with time we are not able to handle state machine and resources properly that it is leading to no interrupt condition?

Regards,
Akshay

Ulysses HERNIOSUS
ST Technical Moderator
August 11, 2026

Hi Akshay,

 

if you say it happens at 55degC I have some suspicion that it might relate to higher temperature. I would

  1. Try to see if it becomes reproducible if you artificially increase the temperature to  maybe 60degc or 70degC
  2. Which RFAL version are you using? >v2.6.0? In case your version is lower, then please perform an update!

Ulysses