Loading...
 

SW4STM32 and SW4Linux fully supports the STM32MP1 asymmetric multicore Cortex/A7+M4 MPUs

   With System Workbench for Linux, Embedded Linux on the STM32MP1 family of MPUs from ST was never as simple to build and maintain, even for newcomers in the Linux world. And, if you install System Workbench for Linux in System Workbench for STM32 you can seamlessly develop and debug asymmetric applications running partly on Linux, partly on the Cortex-M4.
You can get more information from the ac6-tools website and download (registration required) various documents highlighting:

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.