Showing results for 
Search instead for 
Did you mean: 

Running a modified version of NFC08A1 AP2P demo from RFAL examples -- not quite working correctly

Associate III


I am working on a version of the STM32L476RG_NUCLEO_AP2P_PROP_NFC8 demo included with the RFAL library examples, trying to get it going on a NUCLEO-F072RB.

I have my code running, and if I bring an L476RG flashed with the unmodified AP2P demo, the boards will transact, but the F0 board is always the initiator.  Previously, when using two L476RG boards and the original demo, they would change which was the initiator and target depending on the timing they were brought in proximity.

I've been debugging thoroughly, but I can't quite narrow down what my issue could be.  rfalNfcWorker() seems to be setting gNfc.state to the correct states: RFAL_NFC_STATE_POLL_TECHDETECT, RFAL_NFC_STATE_LISTEN_TECHDETECT, etc.  I've noticed when stepping through, though, that it never leaves RFAL_NFC_STATE_POLL_TECHDETECT, but if I set a breakpoint at the different cases in rfalNfcWorker() it will cycle through them during discovery.

My big issue: when I program two F0 boards with my modified version, I cannot get them to detect each other. It is almost like they are only looking for a listen target and never leave that state.

The way I cobbled this together is by starting a new project using the X-NFC-6 middleware, got pins and peripherals configured, then ported over the demoIni(), demoCycle(), etc, functions over right into main.c (just for the first steps in getting a working demo). I've attached it, if this is helpful.

Any pointers on where to look?  I've spent hours stepping through both my F0 version and the original AP2P demo for the L476RG, and I can't seem to see a different during run time.



Accepted Solutions
ST Employee

See X-CUBE-NFC6 Polling Demo on NUCLEO-L476 can't detect AP2P techs

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.

View solution in original post

ST Employee

Hi dwagner4,


I would go and investigate by first setting ST25R_SELFTEST to verify the timer and interrupt handling are indeed correct. If all good then in a next step I would attach a logic analyzer and compare the polling and timing (without a peer) to see differences to the STM32L4 based implementation: Interrupt line should be high only for very short times (few us). Compare the timing between interrupt pulses.

BR, Ulysses

Thank you, I enabled both ST25R_SELFTEST and ST25R_SELFTEST_TIMER.

ST25R_SELFTEST_TIMER throws a RFAL_ERR_SYSTEM at this block:



     * Check SW timer operation :
     *  - use the General Purpose timer to measure an amount of time
     *  - test whether an interrupt is seen when less time was given
     *  - test whether an interrupt is seen when sufficient time was given
    st25r3916EnableInterrupts( ST25R3916_IRQ_MASK_GPE );
    st25r3916SetStartGPTimer( (uint16_t)ST25R3916_TEST_TMR_TOUT_8FC, ST25R3916_REG_TIMER_EMV_CONTROL_gptc_no_trigger);
    if( st25r3916WaitForInterruptsTimed( ST25R3916_IRQ_MASK_GPE, (ST25R3916_TEST_TMR_TOUT - ST25R3916_TEST_TMR_TOUT_DELTA)) != 0U )
        return RFAL_ERR_SYSTEM;


Stepping into st25r3916WaitForInterruptsTimed(), the do block only iterates once, and returns status = 0x2000 instead of 0x0:


uint32_t st25r3916WaitForInterruptsTimed( 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 */
        status = (st25r3916interrupt.status & mask);
    } while( ( (!platformTimerIsExpired( tmrDelay )) || (tmo == 0U)) && (status == 0U) );
    platformTimerDestroy( tmrDelay );

    status = st25r3916interrupt.status & mask;
    st25r3916interrupt.status &= ~status;
    return status;


So something with the interrupt?

If I step back in the timer selftest and follow st25r3916EnableInterrupts(), it leads to st25r3916ModifyInterrupts(), which ultimately is supposed to write to a register using st25r3916WriteRegister(), but the internal if-statement in the for loop always evaluates true and nothing is ever written to the interrupt register:


void st25r3916ModifyInterrupts(uint32_t clr_mask, uint32_t set_mask)
    uint8_t  i;
    uint32_t old_mask;
    uint32_t new_mask;

    old_mask = st25r3916interrupt.mask;
    new_mask = ((~old_mask & set_mask) | (old_mask & clr_mask));
    st25r3916interrupt.mask &= ~clr_mask;
    st25r3916interrupt.mask |= set_mask;
    for(i=0; i<ST25R3916_INT_REGS_LEN; i++)
        if( ((new_mask >> (8U*i)) & 0xFFU) == 0U )
        st25r3916WriteRegister(ST25R3916_REG_IRQ_MASK_MAIN + i, (uint8_t)((st25r3916interrupt.mask>>(8U*i)) & 0xFFU) );


So I think there is some issue in enabling the interrupt?  I'm going to go back to the AP2P demo code running on the L476 to see what the difference is there (since it obviously passes the timer selftest).  I definitely have PA0 set as EXTI0, and NVIC set up for EXTI0 as well, on the F0 board.  I'll update soon.

Associate III

I decided to take a step back and just create a freshly generated project using the NFC08A1 PollingTagDetect demo flashed onto two F072RB boards.  In the default state, they detect each other polling for the different technologies just fine.

When I modify rfal_defConfig.h and rfal_features.h to turn off certain technologies and flash one of the boards, though, I can't get AP2P transaction to happen.


#define RFAL_FEATURE_LISTEN_MODE               true       /*!< 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             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                      true       /*!< 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                    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            true       /*!< Enable/Disable RFAL support for Listen mode (PICC) ISO-DEP (ISO14443-4)   */
#define RFAL_FEATURE_NFC_DEP                   true       /*!< 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.



#define RFAL_SUPPORT_MODE_POLL_NFCA                false          /*!< RFAL Poll NFCA mode support switch    */
#define RFAL_SUPPORT_MODE_POLL_NFCB                false          /*!< RFAL Poll NFCB mode support switch    */
#define RFAL_SUPPORT_MODE_POLL_NFCF                true          /*!< RFAL Poll NFCF mode support switch    */
#define RFAL_SUPPORT_MODE_POLL_NFCV                true          /*!< RFAL Poll NFCV mode support switch    */
#define RFAL_SUPPORT_MODE_POLL_ACTIVE_P2P          true          /*!< RFAL Poll AP2P mode support switch    */
#define RFAL_SUPPORT_MODE_LISTEN_NFCA              false          /*!< RFAL Listen NFCA mode support switch  */
#define RFAL_SUPPORT_MODE_LISTEN_NFCB              false         /*!< RFAL Listen NFCB mode support switch  */
#define RFAL_SUPPORT_MODE_LISTEN_NFCF              true          /*!< RFAL Listen NFCF mode support switch  */
#define RFAL_SUPPORT_MODE_LISTEN_ACTIVE_P2P        true          /*!< RFAL Listen AP2P mode support switch  */

It is still very strange.  The project example with the RFAL download (AP2P_PROP for L476RG board) will work with the F0 board. 

ST Employee

See X-CUBE-NFC6 Polling Demo on NUCLEO-L476 can't detect AP2P techs

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.