Skip to main content
Visitor II
April 19, 2020
Solved

Using X-CUBE-NFC3 with STM32L475 custom board and SPI2 instead of SPI1

  • April 19, 2020
  • 12 replies
  • 3153 views

For my first foray into the STM32 world I've been trying to get to read nfc tags with a STM32L475 and ST25R95 custom board. It is taking me a while to get used to the CUBE IDE, since including libraries many times results in errors, specially since I'm coming from the Arduino IDE.

As the title says I'm trying to adapt the included polling example(for the L476 board) to work with a custom board based on the STM32L475. I'm using the SPI2 port which I have inited in the main code, (pins PB12-PB15). I have made the changes in platform.h and st25r95_com.h to change hspi1 to hspi2. But still I always get initialization failed... any more places I should be changing SPI1 to SPI2?

Thank you for your time.

    This topic has been closed for replies.
    Best answer by Brian TIDAL

    Hi,

    Command >>>> 02*********** is a protocol Select. It used to configure ISO14443-A or B or Felica or ISO15693 protocols. it returns 0000 to inform that the command has been applied

    Command >>>> 09******** is a write register. it returns 0000 to inform that the register value has been updated

    Command >>>> 08******** is a read register. it returns 0001 + value of the register

    st25r95ReadReg: retCode: 00 or st25r95WriteReg: retCode: 00 are log for read or write register API. Therefore "retCode: 00" for those API just informs that the communication between the MCU and the ST25R95 is ok.

    The data exchanges with the tag are logged as:

    DATA >>>> 260100

    DATA <<<<(0x8700)  (retCode=4)

    As long as the respCode for data exchanges is different from 0x80 or 0x90 (e.g. 0x87), nothing has been received properly from the tag. In that case, it is likely an antenna issue.

    Rgds

    BT

    12 replies

    Technical Moderator
    April 20, 2020

    Hi,

    to select SPI mode on ST25R95, make sure to have:

    • SSI_0 --> High
    • SSi_1--> Low

    Also, make sure to have nIRQ_IN and nIRQ_OUT connected. On the Nucleo-L476RG

    • nIRQ_IN is connected to PA9 (GPIO mode: Output push pull, init output: low)
    • nIRQ_OUT is connected to PA10 (GPIO mode: Input mode)

    Regarding the SPI2, make sure to have:

    • Mode: Full Duplex Master
    • HW NSS signal disable
    • Basic param: 8bits Moto MSB first
    • NSS Signal type: software
    • clock:
      • CPOL Low, CPHA 1Edge,
      • frequency must be below 2 MHz (set the prescaler accordingly)
    • NSS:
      • I guess NSS is connected on PB12: it must be configured in GPIO_Output (not in SPI2_NSS). GPIO Mode: Output push pull, Init output: High

    In platform.h, make sure to have:

    #define platformSpiTxRx(txBuf, rxBuf, len)      HAL_SPI_TransmitReceive((&hspi2), (txBuf), (rxBuf), (len), 1000)  /*!< SPI transceive               */

    extern SPI_HandleTypeDef hspi2;

    Also, check that the ST25R95 is properly powered.

    If you still have some initialization issue,

    • can you probe SSI_0, SSI_1, IRQ_IN, IRQ_OUT, SPI2_CLK/MOSI/MISO, nSS_SPI with a logic analyzer and send me the trace

    Thanks

    Rgds

    BT

    NFerr.1Author
    Visitor II
    April 20, 2020

    First of all I'd like to thank you very much for your time Brian.

    The SPI mode is correctly picked, since we've hooked SSI_0 to VCC and SSI_1 to GND. SO that's a check.

    About IRQ_IN and OUT, they are currently not connected to the MCU, so I guess that's where the problem arises, since they are needed for SPI communication?

    Regarding the SPI2, this is how we are currently initializing it:

    hspi2.Instance = SPI2;

    hspi2.Init.Mode = SPI_MODE_MASTER;

    hspi2.Init.Direction = SPI_DIRECTION_2LINES;

    hspi2.Init.DataSize = SPI_DATASIZE_8BIT;

    hspi2.Init.CLKPolarity = SPI_POLARITY_LOW;

    hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;

    hspi2.Init.NSS = SPI_NSS_SOFT;

    hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_64;

    hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;

    hspi2.Init.TIMode = SPI_TIMODE_DISABLE;

    hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;

    hspi2.Init.CRCPolynomial = 7;

    hspi2.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;

    hspi2.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;

    and

     __HAL_RCC_SPI2_CLK_ENABLE();

    //INSIDE HAL_SPI_MspInit

    GPIO_InitStruct.Pin = GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15;

    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

    GPIO_InitStruct.Alternate = GPIO_AF5_SPI2;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    //NSS Declaration

    GPIO_InitStruct.Pin = nSPI_SS_Pin; //PIN 12

    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

    GPIO_InitStruct.Pull = GPIO_NOPULL;

    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

    HAL_GPIO_Init(nSPI_SS_GPIO_Port, &GPIO_InitStruct); //nSPI_SS_GPIO is declared to GPIOB

    So I think that is correctly setup.

    On platform.h

    #define ST25R95_INTERFACE_SPI

    and

    #define platformSpiTxRx(txBuf, rxBuf, len)      HAL_SPI_TransmitReceive((&hspi2), (txBuf), (rxBuf), (len), 1000)  /*!< SPI transceive               */

    and

    #if !(ST25R95_INTERFACE_UART) /* ST25R95_INTERFACE_SPI */

    extern SPI_HandleTypeDef hspi2;

    #else /* !ST25R95_INTERFACE_SPI */

    extern UART_HandleTypeDef huart1;

    #endif /* ST25R95_INTERFACE_SPI */

    Thank you once again for your time!

    Technical Moderator
    April 20, 2020

    Hi,

    nIRQ_IN is needed for the startup sequence as described in ST25R95 Datasheet § 3.2 Startup sequence. nIRQ_OUT is needed to detect when the ST25R95 is ready to send an answer to any command.

    Rgds

    BT

    NFerr.1Author
    Visitor II
    April 21, 2020

    With the soldered IRQ_OUT and IRQ_IN the initialization succeeds! It cannot detect tags yet but I think it might be due an incorrect antenna design from our PCB makers. The Output stays in :

    Intialization Succeeded

    1. Tap a tag to read its contents

    2. Present a tag to read its contents.

    I think it is detecting the tags since the serial monitor indicator stops flashing when I scan a card and then it starts flashing again after some time.

    Thank you very much!

    Technical Moderator
    April 21, 2020

    Hi

    you can turn #define ST25R95_DEBUG to true instead of false in .\Drivers\BSP\Components\ST25R95\st25r95_com.c and .\Drivers\BSP\Components\ST25R95\st25r95_com_spi.c

    You will see the protocol commands sent over SPI, in particular the SendReceive command.

    For example:

    DATA >>>> 260100 //Example of Inventory command

    DATA <<<<(0x8700)  (retCode=4) //ST25R95 return 0x8700 = Frame wait time out (no valid reception) 

    DATA >>>> 260100 //Example of Inventory command

    DATA <<<<(0x800D) 000064147D2D002302E0C2A8 00 (retCode=0) //ST25R95 returns the Inventory response received from the tag

    If a 0x87 respCode is received, this means either no tag in the field or no answer properly received.

    Feel free to share the log.

    Rgds

    BT

    NFerr.1Author
    Visitor II
    April 20, 2020

    Hello,

    I'll go see if that fixes the problem, I'll get back with more info soon.

    Thank you once again.

    Technical Moderator
    April 28, 2020

    Hi,

    can you detail how you measure the power consumption i.e. is it the overall power consumption including the STM32L4 part and the ST25R95 part? To reduce the overall power consumption, make sure to have the STM32L4 being in low power mode and having all unused GPIO being in analog config. STM32L4 has various low power mode (SLEEP, STOP0, STOP1, STOP2). If possible, I would recommend to use STOP2 (HAL_PWREx_EnterSTOP2Mode) which is the most efficient. Note: make sure to properly reconfigure the clocks when exiting from the STOPx mode as all high speed clocks are stopped when entering this mode (use SystemClock_Config(); to reconfigure the clock tree). See STM32L4 online training.

    For the ST25R95 part, the SwingsCnt parameter in the Idle command is already set to the recommended 0x3F value (64 pulses per burst) and the WUperiod is set to 0x24 (~300 ms between 2 detection bursts, see RFAL_ST25R95_IDLE_DEFAULT_WUPERIOD). This can be easily checked with an oscilloscope.

    Rgds

    BT

    NFerr.1Author
    Visitor II
    May 1, 2020

    Hello,

    I have two multimeters measuring current. One in the IDD pin, which measures the STM32L475 Power consumption (at the moment hovers around 100uA, but I know its possible to do better, I have tested sketches at around 1-2uA using stop mode). The other one is between the 3.3v of the ST25R95 and the board, to show how much current this board is pulling. At the moment I managed to improve it to around 1.2mA for the ST25R95 part. I'm more concerned with the power draw of the ST25R95 since the project will be installed with batteries, so I would like to get around 100uA if possible. In my understanding the best idea for lowering power consumption would be to increase the WUperiod alongside reducing the number of pulses per burst? I'm worried this will worsen the NFC detection a lot, since it will be the thing waking up our MCU.

    Thank you,

    Nuno

    Technical Moderator
    May 1, 2020

    Hi Nuno,

    Can you check with an scope that the HF oscillator (27.12 MHz) is properly switch off and periodically restarted for detection bursts (see yellow signal in AN3433 figure 4)?

    Can you check that the detection period is around 304 ms (i.e. time between 2 detections: duration between 2 yellow peak)?

    Can you measure the duration of a yellow peak, i.e duration of HF oscillator being ON and system being consuming power

    Can you check the detection burst duration (should be 4.7 µs)?

    For the ST25R95 part, what is the power consumption in ready mode with Field ON and in ready mode with Field OFF (you can put a breakpoint at the end of functions st25r95FieldOn or st25r95FieldOff, once the ProtocolSelect has been executed)

    If I am not wrong, in tag detection mode, the main power consumption contributor is VPS (the peak current on VPS_TX is 100mA but during only swingCount=3Fh i.e. 4.7 µs, therefore the average current on VPS_TX should be neglectable)

    Osc Start and Dac Start are maybe a little bit conservative: can you try to reduce from 0x60 to 0x40 in Idle[] = {ST25R95_COMMAND_IDLE, 0x0E, 0x0A, 0x21, 0x00, 0x38, 0x01, 0x18, 0x00, 0x20, 0x60, 0x60, 0x74, 0x84, 0x3F, 0x00}. What is the new power consumption?

    RFAL_ST25R95_IDLE_DEFAULT_WUPERIOD is 24h (i.e 304 ms). Can you try to change it to 49h (i.e. 600 ms). What is the new power consumption?

    By the way, what is your battery capacity and the expected autonomy?

    Rgds

    BT

    NFerr.1Author
    Visitor II
    May 10, 2020

    Hello Brian!

    I come with some news. With the Stop2 mode my STML475 is consuming around 1.6uA, so the MCU power consumption could be considered negligible by now.

    That leaves the ST25R95. Using another Nucleo NFC3 board, I could get around 100-110uA Average with the default wake up parameters and using both tweaks you have mentioned(in the idle command set I put both OSC start and DAC start to 0x40 and put the default wu period from 24h to 49h) I lowered it a bit to around 95uA, which is something, but a bit more than I was expecting. I have to change the WU Period in both the Idle command (in st25r95_com_spi) and in the definition in rfal_rfst25r95 right?

    We are dimensioning this project to work with one 3500mAh battery, and we are trying to last for at least a year of operation. This board will also have a modem onboard(NBIOT preferably if the place of installation allows).

    Technical Moderator
    May 11, 2020

    Hi Nuno,

    actually, st25r95SPIIdle() overwrites the default WUPeriod defined in Idle[] array, so it is only needed to update

    RFAL_ST25R95_IDLE_DEFAULT_WUPERIOD in rfal_rfst25r95.

    Can you try to keep the OSC start and DAC start to the recommended original value (0x60) and only modify the RFAL_ST25R95_IDLE_DEFAULT_WUPERIOD parameter to 49h and see what is the power consumption? I am just wondering whether OSC start and DAC start has a significant impact on power consumption but I cannot do measurements for the moment on my side.

    By the way, is 600ms (WUPeriod= 49h) acceptable for your application?

    Rgds

    BT

    NFerr.1Author
    Visitor II
    May 11, 2020

    Hello Brian,

    Putting the default parameters to the OSC Start and DAC start, seems to have almost no effect in the power consumption, but one thing that is weird is that on my first tests I was able to have around 100uA with the same settings I'm now getting 140-150uA from. I think I really have to get an oscilloscope to see if everything is correct with the bursts.

    As for the WUPeriod = 49h, meaning 600ms, its perfectly fine since it is not a time sensitive operation. But I've played with bigger WUPeriods and it did not seem to have a lot of effect in the total power consumption, so it might be due to the LEDs in the nucleo board? Sinking current even when they are not being used. Or maybe even other pins on the Nucleo NFC3 board.

    For now this gives us a good battery life, but we are trying to understand if it would be possible to lower it even further. Theoretically the x-nucleo-nfc05a1 would have a lower power consumption in wake up mode, is that correct? From the datasheet I understood that while the idle value without burst for the ST25R95/CR95 is around 60uA, while for the part used in the nfc05a1(ST25R3911B ) this idle current would be around 6uA.

    Thank you once again for your amazing support Brian,

    My best regards,

    Nuno

    Technical Moderator
    May 11, 2020

    Hi Nuno,

    as far as I remember, in low power mode, the ST25R3911B has a lower power consumption than the ST25R95/CR95HF. For your information, the RFAL API is the same for ST25R3911B, ST253916 and ST25R95/CR95HF. Therefore, you can reuse the same user source code with the different series.

    Rgds

    BT