cancel
Showing results for 
Search instead for 
Did you mean: 

UART interrupt reception issue in STM32G4

sireevenkat1
Senior


Hi,
I am working with STM32G4.I am communicating with STM32G4 with other controller through  UART interrupt communication. 
The data is transmitting and receiving between stm32g4 and other mcu. Some times I am not receiving the data properly from other controller to STM32G4,like SOF always 0x22 and EOF 0x04 always. data bytes not coming properly as expected .
Receiver buffer always should start with 0x22 and with 0x04 but whenever I didn't received the data what I observed is I am receiving the data not in order like SOF(0x22) coming in different byte of rx_bufer .so then I can't be transmit and receive the proper data.

below added code

 

uint8_t ocpp_rxdata[7];
uint8_t ocpp_txdata[64];
uint8_t ocppalldata_received = 0;
int main(){ 
//all initializations
HAL_UART_RegisterCallback(&huart5,HAL_UART_RX_COMPLETE_CB_ID,HAL_UART_RxCpltCallback);
  AL_UART_RegisterCallback(&huart5,HAL_UART_TX_COMPLETE_CB_ID,HAL_UART_TxCpltCallback);
  HAL_UART_Receive_IT(&huart5, ocpp_rxdata, 7);  /* USER CODE END 2 */
while(1){
  request();
}
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
   if (huart->Instance == huart5.Instance)  {
         alldata_received = 1;
}
}
void request()
{
	if (alldata_received) {
        uint16_t calculatedCRC;
	uint16_t receivedCRC;
      if(ocpp_rxdata[0]==0x22)
       { 	
    	  calculatedCRC = HAL_CRC_Calculate(&hcrc,(uint32_t *)&ocpp_rxdata, 4);    	 
    	  receivedCRC=ocpp_rxdata[4]<<8 | ocpp_rxdata[5];
    	  if(calculatedCRC==receivedCRC){
          switch(ocpp_rxdata[2])
          {
           case 0x01:
             //trasmit data ocpp_txdata[0] to ocpp_txdata[18] 
             //ocpp_txdata[16],ocpp_txdata[17] is crc
              HAL_UART_Transmit_IT(&huart5, ocpp_txdata,19);
                break;
             case 0x02:
             //trasmit data ocpp_txdata[0] to ocpp_txdata[13] 
             //ocpp_txdata[11],ocpp_txdata[12] is crc
              HAL_UART_Transmit_IT(&huart5, ocpp_txdata,14);
                break;
          }
       }
    else{
     crc_error();
    }
   }
	alldata_received = 0;
	HAL_UART_Receive_IT(&huart5, ocpp_rxdata, 7);
}
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
	memset(ocpp_rxdata, '\0',7); //empty the reception data buffer

}

 

 I changed receive buffer and transmit buffer to volatile and checked I am facing same issue and I also enabled UART in register in .ioc configuration.
Can anyone suggest what wrong in my code. Any suggestion will be helpful.
Thanks

4 REPLIES 4
TDK
Guru

Need a method to synchronze comunication so you don't start listening in the middle of a response. You can use HAL_UARTEx_ReceiveToIdle to do this, or set up a ring buffer and wait until the starting character comes in.

If you feel a post has answered your question, please click "Accept as Solution".
Billy OWEN
ST Employee

Hi @sireevenkat1 

 

The forum moderator had marked your post as needing a little more investigation and direct support. An online support case has been created on your behalf, please stand by for just a moment and you will hear from us.

 

Regards,

Billy

Karl Yamashita
Lead III

In the  HAL_UART_RxCpltCallback, you need to enable the interrupt again by calling HAL_UART_Receive_IT. That way the HAL driver can interrupt on new data right away. But there is a catch which i explain about using a ring buffer below.

 

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
	if (huart->Instance == huart5.Instance) {
		alldata_received = 1;
		HAL_UART_Receive_IT(&huart5, ocpp_rxdata, 7);
	}
}

 

You don't check HAL status so you don't know if calling HAL_UART_Transmit_IT was successful. The same goes for HAL_UART_Receive_IT

 

If your request() doesn't copy the valid packet to the tx buffer before the next interrupt, then your current rx buffer will be corrupted with new data. You should use a ring buffer to hold several packets in a queue.

 

See this project to see how to use a ring buffer to save a couple of packets in a queue and check for HAL status. It also uses HAL_UARTEx_ReceiveToIdle_IT which reduces data packets getting out of sync. 

https://github.com/karlyamashita/ParseTelemetryData/wiki

 

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.

Hi @Karl Yamashita ,


@Karl Yamashita wrote:

In the  HAL_UART_RxCpltCallback, you need to enable the interrupt again by calling HAL_UART_Receive_IT. That way the HAL driver can interrupt on new data right away. But there is a catch which i explain about using a ring buffer below.


I checked with this, what I observed is now I can able to receive the data in proper format from other MCU to stm32.Previous problem got solved i.e receiving data frames randomly.
but the issue is if I observe my reception and transmission format for some time, in between one frame of transmission and reception data is missing after that its working as expected.
For example for 10 minutes if I observe the data, randomly like after 3 min I am losing one data frame then after 2 min again I am missing the one data frame its happening like that . Is it common or need to be addressed?
Please suggest.


See this project to see how to use a ring buffer to save a couple of packets in a queue and check for HAL status. It also uses HAL_UARTEx_ReceiveToIdle_IT which reduces data packets getting out of sync. 

https://github.com/karlyamashita/ParseTelemetryData/wiki


HAL_UARTEx_ReceiveToIdle_IT : This one I will check and will come back.

Please suggest for above problem.
Thanks