cancel
Showing results for 
Search instead for 
Did you mean: 

ST25R100 with STM32G0 Freeze in rfalWorker

Mark12
Associate

I am currently trying to use the NFC09A1 together with an STM32G0. I am having multiple issues.

I am using ST25NFC_Embedded_Lib_ST25R200_1.8.0_2

I setup the platform and SPI. SPI communication is working properly. I checked the signals and I can also properly read the chips ID in the rfalInit.

Basically i am initializing with 

rfalNfcInitialize()

and then doing something like this:

    rfalNfcDiscoverParam discParam;
    rfalNfcDefaultDiscParams(&discParam);
    discParam.devLimit = 1;
    discParam.techs2Find = RFAL_NFC_POLL_TECH_A;

    if (rfalNfcDiscover(&discParam) != RFAL_ERR_NONE)
    {
        return Result::Error;
    }

    static rfalNfcDevice* nfcDevice;
    while (true)
    {
        rfalNfcWorker();
        HAL_Delay(500);
    }

On the SPI bus I can see traffic happening And also the Antenna seems to radiate a signal. However, after maybe 5-10 Cycles of the while loop the programm suddenly freezes. I seems that it gets stuck in this loop:

static ReturnCode rfalTransceiveRunBlockingTx( void )
{
    ReturnCode ret;
        
    do{
        rfalWorker();
        ret = rfalGetTransceiveStatus();
    }
    while( (rfalIsTransceiveInTx()) && (ret == RFAL_ERR_BUSY) );
    
    if( rfalIsTransceiveInRx() )
    {
        return RFAL_ERR_NONE;
    }
    
    return ret;
}

I am testing with an NXP NTAG215 which from my understanding should be NFC-A T2T, this is also the only configuration that I need working.

This is my rfal_platform. Where I also included the PIN setup:

/******************************************************************************
  * @attention
  *
  * COPYRIGHT 2018 STMicroelectronics, all rights reserved
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
  * AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  *
******************************************************************************/
/*! \file
 *
 *  \author
 *
 *  \brief Platform header file. Defining platform independent functionality.
 *
 */

#ifndef RFAL_PLATFORM_H
#define RFAL_PLATFORM_H

#ifdef __cplusplus
extern "C" {
#endif

/*
******************************************************************************
* INCLUDES
******************************************************************************
*/

#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <limits.h>
#include <math.h>
#include "main.h"
#include "spi.h"
#include "timer.h"
#include "logger.h"

#include "stm32g0xx_hal.h"

#define ST25R200
#define B1_Pin GPIO_PIN_13
#define B1_GPIO_Port GPIOC
#define LED_FIELD_Pin GPIO_PIN_1
#define LED_FIELD_GPIO_Port GPIOA
#define LED_A_Pin GPIO_PIN_4
#define LED_A_GPIO_Port GPIOA
#define LED_B_Pin GPIO_PIN_0
#define LED_B_GPIO_Port GPIOB
#define LED5_Pin GPIO_PIN_10
#define LED5_GPIO_Port GPIOB
#define LED_V_Pin GPIO_PIN_8
#define LED_V_GPIO_Port GPIOA

#define ST25R_IRQ_Pin GPIO_PIN_0
#define ST25R_IRQ_GPIO_Port GPIOA
#define ST25R_IRQ_EXTI_IRQn EXTI0_1_IRQn
#define ST25R_RST_Pin GPIO_PIN_11
#define ST25R_RST_GPIO_Port GPIOB

#define SPI1_CS_Pin GPIO_PIN_12
#define SPI1_CS_GPIO_Port GPIOB

#define LED_RX_Pin GPIO_PIN_4
#define LED_RX_GPIO_Port GPIOB

/*
******************************************************************************
* GLOBAL DEFINES
******************************************************************************
*/
#define ST25R_SS_PIN             SPI1_CS_Pin              /*!< GPIO pin used for ST25R SPI SS                */
#define ST25R_SS_PORT            SPI1_CS_GPIO_Port        /*!< GPIO port used for ST25R SPI SS port          */

#define ST25R_INT_PIN            ST25R_IRQ_Pin            /*!< GPIO pin used for ST25R External Interrupt    */
#define ST25R_INT_PORT           ST25R_IRQ_GPIO_Port      /*!< GPIO port used for ST25R External Interrupt   */

#define ST25R_RESET_PIN          ST25R_RST_Pin            /*!< GPIO pin used for ST25R Reset                 */
#define ST25R_RESET_PORT         ST25R_RST_GPIO_Port      /*!< GPIO port used for ST25R Reset                */


#ifdef LED_FIELD_Pin
#define PLATFORM_LED_FIELD_PIN   LED_FIELD_Pin            /*!< LED 1 GPIO pin used as field LED              */
#endif

#ifdef LED_FIELD_GPIO_Port
#define PLATFORM_LED_FIELD_PORT  LED_FIELD_GPIO_Port      /*!< LED 1 GPIO port used as field LED             */
#endif


#define PLATFORM_LED_A_PIN           LED_A_Pin            /*!< LED 2 GPIO pin used for LED A     */
#define PLATFORM_LED_A_PORT          LED_A_GPIO_Port      /*!< LED 2 GPIO port used for LED A    */
#define PLATFORM_LED_B_PIN           LED_B_Pin            /*!< LED 3 GPIO pin used for LED B     */
#define PLATFORM_LED_B_PORT          LED_B_GPIO_Port      /*!< LED 3 GPIO port used for LED B    */
#define PLATFORM_LED_F_PIN           LED5_Pin             /*!< LED 5 GPIO pin used for LED F     */
#define PLATFORM_LED_F_PORT          LED5_GPIO_Port       /*!< LED 5 GPIO port used for LED F    */
#define PLATFORM_LED_V_PIN           LED_V_Pin            /*!< LED 4 GPIO pin used for LED V     */
#define PLATFORM_LED_V_PORT          LED_V_GPIO_Port      /*!< LED 4 GPIO port used for LED V    */
#define PLATFORM_LED_AP2P_PIN        LED5_Pin             /*!< LED 5 GPIO pin used for LED AP2P  */
#define PLATFORM_LED_AP2P_PORT       LED5_GPIO_Port       /*!< LED 5 GPIO port used for LED AP2P */

#define PLATFORM_USER_BUTTON_PIN     B1_Pin               /*!< GPIO pin user button              */
#define PLATFORM_USER_BUTTON_PORT    B1_GPIO_Port         /*!< GPIO port user button             */


/*
******************************************************************************
* GLOBAL MACROS
******************************************************************************
*/
#define platformProtectST25RComm()                    do{ globalCommProtectCnt++; __DSB();NVIC_DisableIRQ(ST25R_IRQ_EXTI_IRQn);__DSB();__ISB();}while(0) /*!< Protect unique access to ST25R communication channel - IRQ disable on single thread environment (MCU) ; Mutex lock on a multi thread environment      */
#define platformUnprotectST25RComm()                  do{ if (--globalCommProtectCnt==0) {NVIC_EnableIRQ(ST25R_IRQ_EXTI_IRQn);} }while(0)                /*!< Unprotect unique access to ST25R communication channel - IRQ enable on a single thread environment (MCU) ; Mutex unlock on a multi thread environment */

#define platformProtectST25RIrqStatus()               platformProtectST25RComm()                    /*!< Protect unique access to IRQ status var - IRQ disable on single thread environment (MCU) ; Mutex lock on a multi thread environment */
#define platformUnprotectST25RIrqStatus()             platformUnprotectST25RComm()                  /*!< Unprotect the IRQ status var - IRQ enable on a single thread environment (MCU) ; Mutex unlock on a multi thread environment         */

#define platformLedOff( port, pin )                   platformGpioClear(port, pin)                  /*!< Turns the given LED Off                     */
#define platformLedOn( port, pin )                    platformGpioSet(port, pin)                    /*!< Turns the given LED On                      */
#define platformLedToggle( port, pin )                platformGpioToggle(port, pin)                 /*!< Toggles the given LED                       */

#define platformGpioSet( port, pin )                  HAL_GPIO_WritePin(port, pin, GPIO_PIN_SET)    /*!< Turns the given GPIO High                   */
#define platformGpioClear( port, pin )                HAL_GPIO_WritePin(port, pin, GPIO_PIN_RESET)  /*!< Turns the given GPIO Low                    */
#define platformGpioToggle( port, pin )               HAL_GPIO_TogglePin(port, pin)                 /*!< Toggles the given GPIO                      */
#define platformGpioIsHigh( port, pin )               (HAL_GPIO_ReadPin(port, pin) == GPIO_PIN_SET) /*!< Checks if the given LED is High             */
#define platformGpioIsLow( port, pin )                (!platformGpioIsHigh(port, pin))              /*!< Checks if the given LED is Low              */

#define platformTimerCreate( t )                      timerCalculateTimer(t)                        /*!< Create a timer with the given time (ms)     */
#define platformTimerIsExpired( timer )               timerIsExpired(timer)                         /*!< Checks if the given timer is expired        */
#define platformDelay( t )                            HAL_Delay(t)                                  /*!< Performs a delay for the given time (ms)    */

#define platformGetSysTick()                          HAL_GetTick()                                 /*!< Get System Tick ( 1 tick = 1 ms)            */

#define platformAssert( exp )                         assert_param( exp )                           /*!< Asserts whether the given expression is true*/
#define platformErrorHandle()                         Error_Handler()                               /*!< Global error handle\trap                    */


#define platformSpiSelect()                           platformGpioClear(ST25R_SS_PORT, ST25R_SS_PIN)/*!< SPI SS\CS: Chip|Slave Select                */
#define platformSpiDeselect()                         platformGpioSet(ST25R_SS_PORT, ST25R_SS_PIN)  /*!< SPI SS\CS: Chip|Slave Deselect              */
#define platformSpiTxRx( txBuf, rxBuf, len )          spiTxRx(txBuf, rxBuf, len)                    /*!< SPI transceive                              */


#define platformLog(...)                              logUsart(__VA_ARGS__)                         /*!< Log  method                                 */

/*
******************************************************************************
* GLOBAL VARIABLES
******************************************************************************
*/
extern uint8_t globalCommProtectCnt;                      /* Global Protection Counter provided per platform - instantiated in main.c    */

/*
******************************************************************************
* RFAL FEATURES CONFIGURATION
******************************************************************************
*/

#define RFAL_FEATURE_LISTEN_MODE               false      /*!< Enable/Disable RFAL support for Listen Mode                               */
#define RFAL_FEATURE_WAKEUP_MODE               true       /*!< Enable/Disable RFAL support for the Wake-Up mode                          */
#define RFAL_FEATURE_LOWPOWER_MODE             true       /*!< Enable/Disable RFAL support for the Low Power mode                        */
#define RFAL_FEATURE_NFCA                      true       /*!< 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                      false       /*!< Enable/Disable RFAL support for NFC-V (ISO15693)                          */
#define RFAL_FEATURE_T1T                       false       /*!< Enable/Disable RFAL support for T1T (Topaz)                               */
#define RFAL_FEATURE_T2T                       true       /*!< 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                    false       /*!< 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                   true       /*!< Enable/Disable RFAL support for ISO-DEP (ISO14443-4)                      */
#define RFAL_FEATURE_ISO_DEP_POLL              true       /*!< 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)                      */

#define RFAL_FEATURE_ISO_DEP_IBLOCK_MAX_LEN    256U       /*!< ISO-DEP I-Block max length. Please use values as defined by rfalIsoDepFSx */
#define RFAL_FEATURE_NFC_DEP_BLOCK_MAX_LEN     254U       /*!< NFC-DEP Block/Payload length. Allowed values: 64, 128, 192, 254           */
#define RFAL_FEATURE_NFC_RF_BUF_LEN            258U       /*!< RF buffer length used by RFAL NFC layer                                   */

#define RFAL_FEATURE_ISO_DEP_APDU_MAX_LEN      512U       /*!< ISO-DEP APDU max length. Please use multiples of I-Block max length       */
#define RFAL_FEATURE_NFC_DEP_PDU_MAX_LEN       512U       /*!< NFC-DEP PDU max length.                                                   */

/*
******************************************************************************
* RFAL CUSTOM SETTINGS
******************************************************************************
*/

#define platformTimerGetRemaining( timer )         (0U) /*!< Gets the remaining time until expiration    */

#ifndef platformProtectST25RIrqStatus
    #define platformProtectST25RIrqStatus()            /*!< Protect unique access to IRQ status var - IRQ disable on single thread environment (MCU) ; Mutex lock on a multi thread environment */
#endif /* platformProtectST25RIrqStatus */

#ifndef platformUnprotectST25RIrqStatus
    #define platformUnprotectST25RIrqStatus()          /*!< Unprotect the IRQ status var - IRQ enable on a single thread environment (MCU) ; Mutex unlock on a multi thread environment         */
#endif /* platformUnprotectST25RIrqStatus */

#ifndef platformProtectWorker
    #define platformProtectWorker()                    /* Protect RFAL Worker/Task/Process from concurrent execution on multi thread platforms   */
#endif /* platformProtectWorker */

#ifndef platformUnprotectWorker
    #define platformUnprotectWorker()                  /* Unprotect RFAL Worker/Task/Process from concurrent execution on multi thread platforms */
#endif /* platformUnprotectWorker */

#ifndef platformIrqST25RPinInitialize
    #define platformIrqST25RPinInitialize()            /*!< Initializes ST25R IRQ pin                     */
#endif /* platformIrqST25RPinInitialize */

#ifndef platformIrqST25RSetCallback
    #define platformIrqST25RSetCallback( cb )          /*!< Sets ST25R ISR callback                       */
#endif /* platformIrqST25RSetCallback */

#ifndef platformLedsInitialize
    #define platformLedsInitialize()                   /*!< Initializes the pins used as LEDs to outputs  */
#endif /* platformLedsInitialize */

#ifndef platformLedOff
    #define platformLedOff( port, pin )                /*!< Turns the given LED Off                       */
#endif /* platformLedOff */

#ifndef platformLedOn
    #define platformLedOn( port, pin )                 /*!< Turns the given LED On                        */
#endif /* platformLedOn */

#ifndef platformLedToggle
    #define platformLedToggle( port, pin )             /*!< Toggles the given LED                         */
#endif /* platformLedToggle */

#ifndef platformGetSysTick
    #define platformGetSysTick()                       /*!< Get System Tick ( 1 tick = 1 ms)              */
#endif /* platformGetSysTick */

#ifndef platformTimerDestroy
    #define platformTimerDestroy( timer )              /*!< Stops and released the given timer            */
#endif /* platformTimerDestroy */

#ifndef platformLog
    #define platformLog(...)                           /*!< Log method                                    */
#endif /* platformLog */

#ifndef platformAssert
    #define platformAssert( exp )                      /*!< Asserts whether the given expression is true */
#endif /* platformAssert */

#ifndef platformErrorHandle
    #define platformErrorHandle()                      /*!< Global error handler or trap                 */
#endif /* platformErrorHandle */

#ifdef __cplusplus
}
#endif

#endif /* RFAL_PLATFORM_H */

 

1 ACCEPTED SOLUTION

Accepted Solutions
Mark12
Associate

Ok found my main problem. I had not registered the other EXTI Interrupt since my used GPIO uses another one as the example:

 

void EXTI4_15_IRQHandler(void)
{
    /* USER CODE BEGIN EXTI0_IRQn 0 */

    /* USER CODE END EXTI0_IRQn 0 */
    HAL_GPIO_EXTI_IRQHandler(ST25R_IRQ_Pin);
    /* USER CODE BEGIN EXTI0_IRQn 1 */
    st25r200Isr();
    /* USER CODE END EXTI0_IRQn 1 */
}

 

View solution in original post

5 REPLIES 5
Ulysses HERNIOSUS
ST Employee

Hi,

please set ST25R_SELFTEST and ST25R_SELFTEST_TIMER and see if init passes or throws an error. 
If this works without errors, then please debug into this:

  1. When stuck is there still SPI traffic?
  2. When stuck: What is the state of INT line?
  3. Please do a logic analyzer trace (SPI+IRQ) which very often lets us pinpoint towards the proplem.

Regards, Ulysses

Brian TIDAL
ST Employee

Hi,

BrianTIDAL_0-1753717579955.png

I believe this is the cause of the issue you are observing. The ST25NFC_Embedded_Lib_ST25R200_1.8.0 demo_polling.c file implements a state machine that is absent from your code. The rfalNfcWorker() function performs technology detection and collision resolution. Once a tag is detected, it waits for an action from the application. Without this, nothing happens. 

I recommend porting the demoIni(), demoCycle(), and demoT2t() functions into your application. Then, integrate your application code into the demoT2t() function.

Best regards,
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.

Agreed. I'm personally using it with a ST25R3916B, but should be the same.

If you only call rfalNfcWorker() in a loop and do nothing else, nothing much will happen anyway. I didn't know it could end up blocking, but in any case, it'll do no useful work.

I have personally implemented a NFC reader "task", which is a function called repeatedly, and the first thing it does is indeed call rfalNfcWorker(), but right after this call, it implements a state machine which handles the discovery ( rfalNfcDiscover() ) and up to the deactivation ( rfalNfcDeactivate() ).

As Brian suggested, refer to the demo_polling example (for instance) to see what must be done.

My guess as to rfalNfcWorker() eventually blocking is that you never call rfalNfcDeactivate(). Haven't looked at the source code of RFAL, but there's probably a reason linked to that.

Again, if you implement the whole state machine from discovery to deactivation, it should work just fine.

 

Mark12
Associate

Thanks for the help!

I now pretty much copied over the demo_polling.c and ported it. And I configured the Interuppt pin, that I didnt use before. However, Now I end up in a freeze even earlier, in this while loop:

/*******************************************************************************/
uint32_t st25r200WaitForInterruptsTimed( uint32_t mask, uint16_t tmo )
{
    uint32_t tmrDelay;
    uint32_t status;
    
    tmrDelay = platformTimerCreate( tmo );
    
    /* Run until specific interrupt has happen or the timer has expired */
    do 
    {
    #ifdef ST25R_POLL_IRQ
        st25r200CheckForReceivedInterrupts();
    #endif /* ST25R_POLL_IRQ */ 
        
        status = (st25r200interrupt.status & mask);
    } while( ( (!platformTimerIsExpired( tmrDelay )) || (tmo == 0U)) && (status == 0U) );

    platformTimerDestroy( tmrDelay );
    
    status = st25r200interrupt.status & mask;
    
    platformProtectST25RIrqStatus();
    st25r200interrupt.status &= ~status;
    platformUnprotectST25RIrqStatus();
    
    return status;
}

 I think my interrupt setup is correct. I use PIN9 on Port A:

    /*Configure GPIO pin : PA9 */
    GPIO_InitStruct.Pin = GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    HAL_NVIC_SetPriority(EXTI4_15_IRQn, 0, 0);
    HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);

#define ST25R_IRQ_Pin GPIO_PIN_9
#define ST25R_IRQ_GPIO_Port GPIOA
#define ST25R_IRQ_EXTI_IRQn EXTI4_15_IRQn

Mark12_0-1753736218912.png

 

Mark12
Associate

Ok found my main problem. I had not registered the other EXTI Interrupt since my used GPIO uses another one as the example:

 

void EXTI4_15_IRQHandler(void)
{
    /* USER CODE BEGIN EXTI0_IRQn 0 */

    /* USER CODE END EXTI0_IRQn 0 */
    HAL_GPIO_EXTI_IRQHandler(ST25R_IRQ_Pin);
    /* USER CODE BEGIN EXTI0_IRQn 1 */
    st25r200Isr();
    /* USER CODE END EXTI0_IRQn 1 */
}