2025-06-19 5:57 AM
Hello,
Tag reading was working perfectly on my previous setup.
I now want to migrate my project from an STM32G0B1RE to an STM32L073RZ. Since the Arduino UNO R3 physical pinout standard is respected, the X-NUCLEO-NFC08A1 shield (which uses SPI, IRQ, LEDs, etc.) remains pin-compatible across different STM32 Nucleo boards (G0, L0, L4, etc.), as long as they follow the UNO R3 layout.
So, I created a new project in STM32CubeMX targeting the STM32L073RZ, and reused the configuration from my working G0-based project.
Current status:
Initially, execution would stop inside `demoCycle()`, initialization was successful (I could see `Initialization succeeded` in the UART), but no tags could be read.
After fixing the IRQ setup, execution no longer reaches `demoCycle()`, it now stops at the call to `MX_X_CUBE_NFC6_Init()`.
Any idea what could be preventing `rfalNfcInitialize()` from completing correctly on the STM32L073RZ?
Thanks in advance!
Solved! Go to Solution.
2025-06-27 7:44 AM
Hi,
this is almost the same configuration except for the drive strength of the GPIO (the "speed" parameter): GPIO_SPEED_FREQ_LOW in your project and GPIO_SPEED_FREQ_VERY_HIGH in my test. With GPIO_SPEED_FREQ_LOW, when reading the IC identity register 3Fh, the last received bit is 0 instead of 1. Thus the IC Identity check fails.
This SPI behavior is documented in the section 2.15.3 Corrupted last bit of the ES0292 STM32L07xxx/L08xxx device errata. See the workaround section (e.g. use GPIO_SPEED_FREQ_VERY_HIGH).
This should help to fix your issue: this was not an easy one.
Rgds
BT
2025-06-19 7:34 AM
Hi,
make sure to rebuild an ioc STM32CubeMx project for the STM32L073RZ with the X-CUBE-NFC6 package and to generate from this ioc. I would recommend to not try to backport partial stuff from an STM32G0 project to a STM32L0 project.
"Any idea what could be preventing `rfalNfcInitialize()` from completing correctly on the STM32L073RZ": just set a break point inside st25r3916Initialize() and step in. Also, I would recommend to configure your IDE to enable the vector catch in order to stop the execution in case an exception occurs (such as hard fault).
Rgds
BT
2025-06-23 6:49 AM
Hi,
no NFC tag is ever detected, and the program appears to stop there. After debugging, I found that the demoCycle() function (called in MX_X_CUBE_NFC6_Process()) is not doing anything because the state variable remains stuck at DEMO_ST_NOTINIT.
In my older working project based on STM32G0, using the same X-CUBE-NFC6 stack, I noticed that NFC tag detection started automatically, even though I never manually set state = DEMO_ST_START_DISCOVERY
Could manually setting the state potentially resolve the issue? If so, how can I do it?
Thanks in advance!
2025-06-23 7:11 AM
Hi,
can you enable ST25R_SELFTEST and ST25R_SELFTEST_TIMER compilation switches to check that interrupt and timer are properly configured?
What is the return code of demoIni function? Do you see the "Initialization succeeded..\r\n" message?
Rgds
BT
2025-06-23 7:48 AM
2025-06-23 8:07 AM
Hi,
you can enable ST25R_SELFTEST and ST25R_SELFTEST_TIMER as preprocessor define symbols in your IDE. This will go to the compiler as -DST25R_SELFTEST and -DST25R_SELFTEST_TIMER. I guess you have properly done this and this is causing a call to _Error_Handler() that is an endless while(1).
Likely the interrupt configuration is wrong. Check that PA0 is configured as GPIO_EXTI0 and that EXTI line 0 and line 1 interrupt is enabled:
Check the configuration of PA0:
Make sure the EXTI0 priority is lower that the SYSTICK priority (i.e. the EXTI prio value is higher than the SYSTICK prio, 1 should be ok with SYSTICK prio=0).
Check the PA0 signal with a scope: during ST25R_SELFTEST, the ST25_IRQ should rise.
Rgds
BT
2025-06-24 2:24 AM
Hi,
The interrupt configuration for PA0 seems to be correct.
PA0 is set to GPIO_EXTI0 in CubeMX
The EXTI line 0 and line 1 interrupt is enabled in the NVIC tab
The generated handler EXTI0_1_IRQHandler() calls HAL_EXTI_IRQHandler(&H_EXTI_0); as expected
However, when I enable ST25R_SELFTEST, the program indeed enters the infinite loop in _Error_Handler(), as suspected.
Rgds
2025-06-24 2:46 AM
Hi
the selftest seems to fail when reading back a register value (i.e. a known value is written and then read back to check the SPI communication).
Make sure your SPI configuration is correct, in particular SPI Phase should be PHASE_2EDGE.
Can you connect a logic analyzer on SPI (CS/MOSI/MISO/CLK) + IRQ and share the trace?
Rgds
BT
2025-06-24 4:02 AM
Hi,
Here is the SPI configuration from the previous STM32G0-based project, where NFC tag reading was working correctly:
/* SPI1 init function */
__weak HAL_StatusTypeDef MX_SPI1_Init(SPI_HandleTypeDef* hspi)
{
HAL_StatusTypeDef ret = HAL_OK;
hspi->Instance = SPI1;
hspi->Init.Mode = SPI_MODE_MASTER;
hspi->Init.Direction = SPI_DIRECTION_2LINES;
hspi->Init.DataSize = SPI_DATASIZE_8BIT;
hspi->Init.CLKPolarity = SPI_POLARITY_LOW;
hspi->Init.CLKPhase = SPI_PHASE_2EDGE;
hspi->Init.NSS = SPI_NSS_SOFT;
hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
hspi->Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi->Init.TIMode = SPI_TIMODE_DISABLE;
hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi->Init.CRCPolynomial = 7;
hspi->Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi->Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
if (HAL_SPI_Init(hspi) != HAL_OK)
{
ret = HAL_ERROR;
}
return ret;
}
static void SPI1_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* USER CODE BEGIN SPI1_MspInit 0 */
/* USER CODE END SPI1_MspInit 0 */
/* Enable Peripheral clock */
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PA7 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = BUS_SPI1_SCK_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = BUS_SPI1_SCK_GPIO_AF;
HAL_GPIO_Init(BUS_SPI1_SCK_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = BUS_SPI1_MISO_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = BUS_SPI1_MISO_GPIO_AF;
HAL_GPIO_Init(BUS_SPI1_MISO_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = BUS_SPI1_MOSI_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = BUS_SPI1_MOSI_GPIO_AF;
HAL_GPIO_Init(BUS_SPI1_MOSI_GPIO_PORT, &GPIO_InitStruct);
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
}
static void SPI1_MspDeInit(SPI_HandleTypeDef* spiHandle)
{
/* USER CODE BEGIN SPI1_MspDeInit 0 */
/* USER CODE END SPI1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_SPI1_CLK_DISABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PA7 ------> SPI1_MOSI
*/
HAL_GPIO_DeInit(BUS_SPI1_SCK_GPIO_PORT, BUS_SPI1_SCK_GPIO_PIN);
HAL_GPIO_DeInit(BUS_SPI1_MISO_GPIO_PORT, BUS_SPI1_MISO_GPIO_PIN);
HAL_GPIO_DeInit(BUS_SPI1_MOSI_GPIO_PORT, BUS_SPI1_MOSI_GPIO_PIN);
/* Peripheral interrupt Deinit*/
HAL_NVIC_DisableIRQ(SPI1_IRQn);
/* USER CODE BEGIN SPI1_MspDeInit 1 */
/* USER CODE END SPI1_MspDeInit 1 */
}
And here is the SPI configuration from the current STM32L0-based project, where NFC tag reading is not working:
/* SPI1 init function */
__weak HAL_StatusTypeDef MX_SPI1_Init(SPI_HandleTypeDef* hspi)
{
HAL_StatusTypeDef ret = HAL_OK;
hspi->Instance = SPI1;
hspi->Init.Mode = SPI_MODE_MASTER;
hspi->Init.Direction = SPI_DIRECTION_2LINES;
hspi->Init.DataSize = SPI_DATASIZE_8BIT;
hspi->Init.CLKPolarity = SPI_POLARITY_LOW;
hspi->Init.CLKPhase = SPI_PHASE_2EDGE;
hspi->Init.NSS = SPI_NSS_SOFT;
hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
hspi->Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi->Init.TIMode = SPI_TIMODE_DISABLE;
hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi->Init.CRCPolynomial = 7;
if (HAL_SPI_Init(hspi) != HAL_OK)
{
ret = HAL_ERROR;
}
return ret;
}
static void SPI1_MspInit(SPI_HandleTypeDef* spiHandle)
{
GPIO_InitTypeDef GPIO_InitStruct;
/* USER CODE BEGIN SPI1_MspInit 0 */
/* USER CODE END SPI1_MspInit 0 */
/* Enable Peripheral clock */
__HAL_RCC_SPI1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PA7 ------> SPI1_MOSI
*/
GPIO_InitStruct.Pin = BUS_SPI1_SCK_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = BUS_SPI1_SCK_GPIO_AF;
HAL_GPIO_Init(BUS_SPI1_SCK_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = BUS_SPI1_MISO_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = BUS_SPI1_MISO_GPIO_AF;
HAL_GPIO_Init(BUS_SPI1_MISO_GPIO_PORT, &GPIO_InitStruct);
GPIO_InitStruct.Pin = BUS_SPI1_MOSI_GPIO_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.Alternate = BUS_SPI1_MOSI_GPIO_AF;
HAL_GPIO_Init(BUS_SPI1_MOSI_GPIO_PORT, &GPIO_InitStruct);
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(SPI1_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI1_IRQn);
/* USER CODE BEGIN SPI1_MspInit 1 */
/* USER CODE END SPI1_MspInit 1 */
}
static void SPI1_MspDeInit(SPI_HandleTypeDef* spiHandle)
{
/* USER CODE BEGIN SPI1_MspDeInit 0 */
/* USER CODE END SPI1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_SPI1_CLK_DISABLE();
/**SPI1 GPIO Configuration
PA5 ------> SPI1_SCK
PA6 ------> SPI1_MISO
PA7 ------> SPI1_MOSI
*/
HAL_GPIO_DeInit(BUS_SPI1_SCK_GPIO_PORT, BUS_SPI1_SCK_GPIO_PIN);
HAL_GPIO_DeInit(BUS_SPI1_MISO_GPIO_PORT, BUS_SPI1_MISO_GPIO_PIN);
HAL_GPIO_DeInit(BUS_SPI1_MOSI_GPIO_PORT, BUS_SPI1_MOSI_GPIO_PIN);
/* Peripheral interrupt Deinit*/
HAL_NVIC_DisableIRQ(SPI1_IRQn);
/* USER CODE BEGIN SPI1_MspDeInit 1 */
/* USER CODE END SPI1_MspDeInit 1 */
}
The only significant difference I noticed is that the G0 version includes:
hspi->Init.NSSPMode = SPI_NSS_PULSE_ENABLE;
Whereas this line is missing in the L0 configuration.
Could this omission affect communication with the ST25R3916B?
Also, is there anything else in the SPI peripheral or GPIO setup that might need to be adjusted when porting from STM32G0 to STM32L0 for proper SPI operation with the NFC reader?
2025-06-24 8:59 AM
Hi,
Can you connect a logic analyzer on SPI (CS/MOSI/MISO/CLK) + IRQ and share the trace?
On which pin is connected the SPI CS? Check the assignment on the arduino connector and check the configuration of this pin.
Rgds
BT