cancel
Showing results for 
Search instead for 
Did you mean: 

Interrupt based LPUART with BLE application.

SPalr.1
Associate II

Hi

I'm working with STM32WB5MMG-dk. The purpose is to develop BLE Gateway.

The module has a custom GATT svc with 4 GATT char svc which sends and receive bytes, this data is been provided by MSP430 to STM32WB5 vice versa. So MSP430 acts as master whenever it wanna send some data to air it adds the data with few more bytes(4byte string) and the send it to STM32WB5 via UART the STM receives them and decode the the received data(by added 4byte string) and extracts the data bytes and send it via a appropriate GATT char svc to air. It happens the same way around STM receives data from air, depends on the GATT char svc the data is added with more bytes(4byte string) and sent to MSP via UART.

***Keeping in Mind for Developing a LOW POWER Application***

The UART need to work with Interrupts thus the STM remains in low power mode mostly with its usual RF ops.

To start Working with LPUART, created a dummy GAP, GATT svc with single GATT char(R,N,WOR) and thought of checking LPUART as bellow.

BLE Services works fine as intended. but no response from UART.

Note: GFG_HW_LPUART is disabled, SMPS Enable, CFG_LPM_SUPPORT Enable, disabled Debug traces**no debugging**. LPUART is running with HSI clk.

//Init Rx Call Back
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
 
 HAL_UART_Receive_IT(&hlpuart1, UART_Buffer, 10);
 
 if(HAL_UART_Transmit_IT(&hlpuart1, UART_Buffer, 10)!= HAL_OK)
 
 {
 
 	Error_Handler();
 
 }
 
}
/**
  * @brief LPUART1 Initialization Function
  * @param None
  * @retval None
  */
void MX_LPUART1_UART_Init(void)
{
 
  /* USER CODE BEGIN LPUART1_Init 0 */
 
  /* USER CODE END LPUART1_Init 0 */
 
  /* USER CODE BEGIN LPUART1_Init 1 */
 
  /* USER CODE END LPUART1_Init 1 */
  hlpuart1.Instance = LPUART1;
  hlpuart1.Init.BaudRate = 38400;
  hlpuart1.Init.WordLength = UART_WORDLENGTH_8B;
  hlpuart1.Init.StopBits = UART_STOPBITS_1;
  hlpuart1.Init.Parity = UART_PARITY_NONE;
  hlpuart1.Init.Mode = UART_MODE_TX_RX;
  hlpuart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  hlpuart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  hlpuart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  hlpuart1.FifoMode = UART_FIFOMODE_DISABLE;
  if (HAL_UART_Init(&hlpuart1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&hlpuart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&hlpuart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&hlpuart1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN LPUART1_Init 2 */
 
  /* make sure that no LPUART transfer is on-going */
 	while (__HAL_UART_GET_FLAG(&hlpuart1, USART_ISR_BUSY) == SET);
 
 	/* make sure that LPUART is ready to receive
 	 * (test carried out again later in HAL_UARTEx_StopModeWakeUpSourceConfig) */
 	while (__HAL_UART_GET_FLAG(&hlpuart1, USART_ISR_REACK) == RESET);
 
 	/* set the wake-up event:
 	 * specify wake-up on start-bit detection */
 	WakeUpSelection.WakeUpEvent = UART_WAKEUP_ON_STARTBIT;
 	if (HAL_UARTEx_StopModeWakeUpSourceConfig(&hlpuart1, WakeUpSelection) != HAL_OK)
 	{
 	  Error_Handler();
 	}
   /* Enable the LPUART Wake UP from STOP mode Interrupt */
   __HAL_UART_ENABLE_IT(&hlpuart1, UART_IT_WUF);
 
HAL_UART_Receive_IT(&hlpuart1, UART_Buffer, 10);
  /* USER CODE END LPUART1_Init 2 */
 
}
  

So The LPUART is not walking up. For BLE application the LPM states(sleep/Stop-x/standby ) are not the same at any given time. when i was working around simple LPUART with STOP mode with all the above MX_LPUART1_UART_Init() just had

while (1)

  {

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

    /* enable MCU wake-up by LPUART */

    HAL_UARTEx_EnableStopMode(&hlpuart1);

    /* enter STOP mode */

      HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);

      SystemClock_Config();

      /* Wake Up on start bit detection successful */

      HAL_UARTEx_DisableStopMode(&hlpuart1);

      /* wait for some delay */

      HAL_Delay(5);

  }

The UART was working fine. But with BLE not sure where the HAL_UARTEx_EnableStopMode/HAL_UARTEx_DisableStopMode to be defined. I tried defining them in stm32_lpm_if.c PWR_EnterStopMode/PWR_ExitStopMode but no luck.

7 REPLIES 7
Bubbles
ST Employee

Hello @SPalr.1​ ,

perhaps try looking at AN4635 and the examples going with that. It may help you.

BR,

J

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.

SPalr.1
Associate II

Hi @JHOUD​ ,

Thanks for directing me to AN4635, I've came across it many times. On a kind note, did you really spent time on digesting my question.

Any way thank you.

KR,

SP

Hi @SPalr.1​ ,

yes I know I didn't provide a complete answer. I'm not sure where to call the HAL_UARTEx_EnableStopMode/HAL_UARTEx_DisableStopMode but I'd try enabling it as soon as the configuration is done and avoid disabling it unless there is a problem with power consumption.

J

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.

Martin HUBIK
Associate III

Hello,

can you test the attached project? It is based on

STM32Cube_FW_WB_V1.12.0\Projects\P-NUCLEO-WB55.Nucleo\Applications\BLE\BLE_p2pServer\

The LPUART is used for application traces and it also allows reception in IRQ mode. LPUART is routed on pins

PA2 - LPUART_TX

PA3 - LPUART_RX

To test the project on WB Nucleo, use the LPUART interface to connect with terminal on your PC. Then observe the traces on LPUART and try to send a character to the target board. CM4 will wake up from STOP, toggle BLUE LED, prepare reception of next character and go back to STOP mode.

The consumption was verified with ST Power Shield and CubeMonPwr.

The project contains a git repository to easily track changes vs original.

Best regards,

Martin

SPalr.1
Associate II

Hi @Martin HUBIK​ 

Thanks for getting back, by trial and error method, I've reached this point a week ago(I know someone is working on the question, but not sure how to update them. sorry about that), there is still some bugs to sort out.

Let me start with your example, all good and every thing works as you mentioned when you send data byte by byte(aprox 278us delay between bytes), but the problem occurs when send continues bytes(long string). 1st the current shouts up 2nd radio stops. beauty is the LPUART will be still receive bytes(FOR the above example I even received a \r** STOP ADVERTISING **\r\n msg).

Delay between Byte and LED toggle in BLE_p2pServer_LPUART_STOP2 project

0693W00000GZfmyQAD.pngFor 8 bytesBLE_p2pServer_LPUART_STOP2 project with delay between each toggle ~85us

0693W00000GZfpTQAT.png***What I was trying since this post***

I tried changing the interrupt priority for LPUART from 0 to 1/6/15 with al this different priorities things work properly *No current shout out, *Radio Connection works and UART still work with the same byte by byte input. If I send a string of size more than 4 it will miss two bytes and catch 3rd byte.

Lets say I send 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10 for 5 times so total 50 bytes it receives 03-05-07-09-10-03-05-07-08-09-10-03-04-05-06-09-10-03-05-07 around 22 bytes. without affecting CM4/CM0 usual routine.

Than I tried enabling FIFO the performance improved, There is no packet drop for 1st 8-bytes also, As long as I send 8-byte string with small delay between them every thing works well. If the string length is more than 8 bytes the a byte drop again.

For 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08-------> x5times ****ALL GOOD AND received 40 byte****

09:41:30.187 Attribute value changed, handle: 0x0E, value (0x): 01-02-03-04

09:41:30.196 Attribute value changed, handle: 0x0E, value (0x): 05-06-07-08

09:41:30.312 Attribute value changed, handle: 0x0E, value (0x): 01-02-03-04

09:41:30.313 Attribute value changed, handle: 0x0E, value (0x): 05-06-07-08

09:41:30.437 Attribute value changed, handle: 0x0E, value (0x): 01-02-03-04

09:41:30.438 Attribute value changed, handle: 0x0E, value (0x): 05-06-07-08

09:41:30.562 Attribute value changed, handle: 0x0E, value (0x): 01-02-03-04

09:41:30.563 Attribute value changed, handle: 0x0E, value (0x): 05-06-07-08

09:41:30.687 Attribute value changed, handle: 0x0E, value (0x): 01-02-03-04

09:41:30.697 Attribute value changed, handle: 0x0E, value (0x): 05-06-07-08

For 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10-------> x5times ***PACKET DROP OBSERVED***

09:42:21.558 Attribute value changed, handle: 0x0E, value (0x): 01-02-03-04

09:42:21.567 Attribute value changed, handle: 0x0E, value (0x): 05-06-07-08

09:42:21.568 Attribute value changed, handle: 0x0E, value (0x): 10-02-03-04

09:42:21.568 Attribute value changed, handle: 0x0E, value (0x): 05-06-07-08

09:42:21.683 Attribute value changed, handle: 0x0E, value (0x): 09-10-01-02

09:42:21.683 Attribute value changed, handle: 0x0E, value (0x): 03-04-05-06

09:42:21.684 Attribute value changed, handle: 0x0E, value (0x): 07-08-10-02

09:42:21.684 Attribute value changed, handle: 0x0E, value (0x): 03-04-05-06

09:42:21.808 Attribute value changed, handle: 0x0E, value (0x): 07-08-09-10

09:42:21.809 Attribute value changed, handle: 0x0E, value (0x): 01-02-03-04

09:42:21.809 Attribute value changed, handle: 0x0E, value (0x): 05-06-07-09

So currently I'm at this point, With all your settings/**/changing LPUART priority/**/Not using DMA for TX/**/ above are my observation.

What dose LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_25); actually means. From where have you got this reference.

Why is this packet drop happening?

Can you suggest me any next step...

Kind Regards,

@SPalr.1​ 

Martin HUBIK
Associate III

Hello SPalr.1,

all peripherals that have the ability to wake-up MCU from STOP mode must have the wake-up signal routed to EXTI. When the wake-up signal is enabled in EXTI it will trigger wake-up from STOP by enabling the internal LDO and starting the internal clock. In case of LPUART this signal is LPUART1 wakeup which is routed to EXTI_25. Once the MCU is woken up, it start to execute the LPUART ISR.

The FW architecture of low power modes with our BLE examples is such, that CM4 executes STOP mode entry and stop mode exit routines in critical section (all interrupts disabled). After wake-up the MCU doesn't jump to ISR directly but executes some critical code inside Stop mode exit routine.

More info on the architecture can be found in

AN5289 - Building wireless applications with STM32WB Series microcontrollers

Figure 6. Algorithm to enter Stop mode on CPU1

One of the things done in Stop mode exit routine is starting HSE oscillators which takes about 250us. This is enough to create overrun condition on LPUART RX when characters are send back to back. At Baud rate @115200 the character length is approximately 86us.

I modified the example so that it uses the internal RX FIFO, which can buffer up to 8 characters. In the LPUART RX callback (ISR context) a task is set (background context) which pus the received characters in a queue and sets up another LPURT reception. LPUART RX callback sets also second task (background context) which process the incoming data and echoes them back on LPUART TX once a New line character is found. I also configured a few GPIO debug signals to verify the timing with logic analyzer. Can you please test the code and let me know if you see any issue with it?

Best regards,

Martin

Hi @Martin HUBIK​ ,

Thanks for your time on investigating and coming up with a wise solution to deploy

LPUART with BLE applications.

In mean time I’ve come up with an alternative solution too, with no DMA, no EXTI_25, enabling FIFO and lowering the UART ISR priority to 6.

This was the same setup which I was working for a while and had issue with 1/2 byte dropping for every 8 bytes.

By the time you are working for the above solution I twining around many possibilities to make it happen and one attempt worked. JUST after enabling Single Sample (LPUART Advance Parameters, SDK hlpuart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_ENABLE; ) things seams to work fine. No more byte dropping.

But still it was confusing what “UART_ONE_BIT_SAMPLE_ENABLE�? have done to solving byte dropping.

I’ve attached my sample project for your reference.

If you have any idea on what one bit sampling might have done to solving the uart issue, please share it.