Loading...
 

Zephyr project on STM32

   Zephyr Workbench, a VSCode extension to manage Zephyr on STM32.
It enables users to easily create, develop, and debug Zephyr applications.
Main features:
  • Install host dependencies.
  • Import toolchain and SDK.
  • Create, configure, build and manage apps.
  • Debug STM32.
You can directly download it from the VSCode marketplace
For more details, visit the Zephyr Workbench

System Workbench for STM32


Receiving Characters From UART Corrupts Memory

While attempting to debug missing characters in a string received through the UART interface, I found possible memory corruption in a temporary global variable used for debugging.

// pUART2Rx[2] is global:
uint8_t pUART2Rx[2]; /**< UART2 Rx DMA buffer for receiving commands */  

// Executed in an initialization function:
HAL_UART_Receive_DMA( &huart2, pUART2Rx, 2 );

// Temporary global to determine which callback
// is called first
volatile unsigned int uiUART_Count = 0;

/**
  * @brief  Rx Half Transfer completed callbacks.
  * @param  huart: UART handle
  * @retval None
  */
void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
{ volatile portBASE_TYPE xHigherPriorityTaskWoken;

  if( huart == &huart2 )
  { uiUART_Count++;
    if( uiUART_Count >=2 )
      // A convenient statement to break on:
      xHigherPriorityTaskWoken = pdFALSE;
    /* Code removed here to find out if it is taking too long to execute.
       */
  }
}

/**
  * @brief Rx Transfer completed callbacks
  * @param huart: uart handle
  * @retval None
  */
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{ volatile portBASE_TYPE xHigherPriorityTaskWoken;

  if( huart == &huart2 )
  {  uiUART_Count++;
  if( uiUART_Count >= 2 )
    // A convenient statement to break on:
    xHigherPriorityTaskWoken = pdFALSE;
     /* Code removed here to find out if it is taking too long to execute.
       */
  }
}

In the above code uiUART_Count is a temporary variable used to determine which callback is called first. Right up until the time some characters are sent to the processor’s UART the uiUART_Count variable is equal to zero, which is its initialzed value. As soon as characters are received by the UART and the first callback is called, and before the uiUART_Count++ statement is executed, the uiUART_Count value is 0xffffff00 according to the expressions tab.

The address of uiUART_Count is 0x200007c8. The Memory tab shows values of 0xffffff00 from 0x20000680 right up to and including where uiUART_Count is at 0x200007c8. Right after that address the memory values are 0x00000000 up to and including the 0x2000081C address.

This looks like memory is being filled with a test pattern between the time the characters are received and the callback is called. This test pattern is corrupting uiUART_Count. What could be doing this?

I am receiving the characters one at a time because the received characters are commands of varing length, and so it is necessary to test for a line terminator as each character is received. When the line terminator is received the command is executed. Another reason for receiving them one at a time is to echo the characters as they are received.

> // pUART2Rx2 is global:
> uint8_t pUART2Rx2; /**< UART2 Rx DMA buffer for receiving commands */
>
> // Exectuted in an initialization function:
> HAL_UART_Receive_DMA( &huart2, pUART2Rx, 2 );

It looks like you’ve declared pUART2Rx2 as a single byte, then configured the DMA to transfer two bytes.
But you also declare pUART2Rx2 then reference pUART2Rx, so I don’t see how this code compiles at all.


I have an alternate solution for your inputprocess, which may clear up the problem and not require the UART to receive one character at a time.

If you set up the UART with a DMA channel on the RX side in circular buffer mode it will keep recieveing characters regardless how you check and process them. You will then need to implement your own routines to get a character, and perhaps to detect when a character is present (kbhit()?) by looking at the DMA count values in the DMA handle block to index into the receive buffer when characters are received. You need to keep your own index pointing to the next character to be recieved when you extract a character. Make sure you wrap your index the same as the DMA counter does.

By setting it up this way, the UART will recieve characters continuously, and as long as you take them out of the buffer before the DMA wraps around you will never have a problem.

I generally use a buffersize of 256 bytes but you can change this depending on your traffic.

Somewhere in the startup of your program, you need to do one call to the HAL routine to start a recieve DMA transfer, pointing to the buffer where you want the DMA to store data. It will then keep filling the circular buffer and you can take characters out, check for your terminating characters, etc and always be ready for the next message.


 

Newest Forum Posts

  1. Монтаж камина с грилем в Москве - установка и барбекю by KpddomErorb, 2025-05-10 18:28
  2. SPI on Nucleo_STMH533RE by royjamil, 2025-05-04 20:13
  3. SPI on Nucleo_STMH533RE by higginsa1, 2025-03-25 07:37
  4. SPI on Nucleo_STMH533RE by royjamil, 2025-03-23 11:31
  5. SPI on Nucleo_STMH533RE by higginsa1, 2025-03-23 09:33
  6. Configuring DMA for ADC in SW? by sam.hodgson, 2025-03-04 12:58
  7. Build a project in "release" mode by info@creosrl.it, 2025-02-20 18:12
  8. Build a project in "release" mode by info@creosrl.it, 2025-02-20 17:05
  9. Build a project in "release" mode by tang, 2025-02-20 10:36
  10. Build a project in "release" mode by info@creosrl.it, 2025-02-19 17:35

Last-Modified Blogs