Skip to main content
Senior
January 25, 2024
Question

UART transmission Issue in stm32g4

  • January 25, 2024
  • 6 replies
  • 3306 views

Hi,
I am working with STM32G4.I am communicating with STM32G4 with other controller through  UART communication.
I can able to receive the data from other MCU to STM32G4 all the time but sometimes I can't able to transmit data from stm32g4 to other MCU.I used UART PollForConversion method  for development.
I receive the data from other MCU to STM32g4 for every 1sec.
Below is the STM32G4 side code:

 

uint8_t ocpp_txdata[64];
uint8_t ocpp_rxdata[8];
while(){
 HAL_UART_Receive(&huart5,ocpp_rxdata,7, 1000);
	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(&huart5, ocpp_txdata,19, 100);
 break;
 case 0x02:
 //trasmit data ocpp_txdata[0] to ocpp_txdata[13] 
 //ocpp_txdata[11],ocpp_txdata[12] is crc
 HAL_UART_Transmit(&huart5, ocpp_txdata,14, 100);
 break;
}
}
}

 

I can able to transmit the data from stm32g4 to other mcu but sometimes I can't.
What I observed is whenever I restated the system and if I remove the power in those cases initially I can't able to transmit.

Can anyone suggest what may be the issue.
I know interrupt mode for UART works better but I have to do with pollforconversion method only.

Thanks 

6 replies

Tesla DeLorean
Guru
January 25, 2024

Are you sure the data is received and in-sync with the correct CRC? Because if not, this code won't send anything back.

Output diagnostics to SWV or another UART for review.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Senior
January 25, 2024

Hi @Tesla DeLorean ,

I can able to see the transmitted data from STM32G4 to other mcu in dock light that means CRC is in sync. The problem is some times its not transmitting, Yes, may be that time CRC not in sync that's why I can able to receive but I can't able to transmit.
How to solve the issue like its happening sometimes not every time.
Coming to UART-its same with other uart also and  I am using UART not USART is that make any difference.

Thanks 

Tesla DeLorean
Guru
January 25, 2024

UART vs USART shouldn't make a difference. 

You ignore errors from the HAL and use blocking receive and transmit methods. The UART can concurrently do both. Your receive method is apt to miss characters. 

I suspect you removed code creating txdata frames.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Senior
January 25, 2024

Tx_data is correct only I just removed because it is just assigning the values.
below I mentioned that part

ocpp_txdata[0] = 0x23;
	 ocpp_txdata[1] = 0x12;
	 ocpp_txdata[2] = 0x12;
	 ocpp_txdata[3] = 0x02;
	 ocpp_txdata[4] = 0x01;
 ocpp_txdata[5] =0x00;
	 ocpp_txdata[6] =0x01;
 ocpp_txdata[7] 0x02;
	 ocpp_txdata[8] =0x04;
	 ocpp_txdata[9] =0x01;
 ocpp_txdata[10] =0x05;
 ocpp_txdata[11] =0x04;
	 ocpp_txdata[12] =0x02;
	 ocpp_txdata[13] =0x00;
 ocpp_txdata[14] =0x05;
	 ocpp_txdata[15] =0x05;
	 // compute CRC to place into last 2 bytes
	 uint16_t calculatedCRC = HAL_CRC_Calculate(&hcrc,(uint32_t *)&ocpp_txdata, 16);

	 ocpp_txdata[16] = (calculatedCRC >> 8) & 0xFF; //high CRC byte
	 ocpp_txdata[17] = calculatedCRC & 0xFF; //low CRC byte

 ocpp_txdata[18] = 0x04;
HAL_UART_Transmit(&huart5, ocpp_txdata,19, 100);


 Your receive method is apt to miss characters. 


Is there any other way please suggest
Thanks

Tesla DeLorean
Guru
January 25, 2024

>>Is there any other way please suggest

Byte-wise in the IRQ handler, into a ring-buffer, that you manager later, say in the foreground task.

HAL_UART_Transmit(&huart5, ocpp_txdata,19, 100); // Blocks for 18-19 character times

Would want to use a HAL_UART_ReceiveIT() cyclically so it catches all inbound data as it arrives. A non-HAL implementation is all possible and likely more efficient. 

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Senior
January 29, 2024

Hi @Tesla DeLorean ,
Below I modified the code with UART interrupt for reception. Can you suggest is it correct way or not?
I receive 7 bytes of data from other MCU to STM32G4 everytime.


@Tesla DeLorean wrote:

>>Is there any other way please suggest

Byte-wise in the IRQ handler, into a ring-buffer, that you manager later, say in the foreground task.

Would want to use a HAL_UART_ReceiveIT() cyclically so it catches all inbound data as it arrives. 


 

UART_HandleTypeDef huart5;
UART_RXBUFFER_SIZE 8
uint8_t ocpp_rxdata[UART_RXBUFFER_SIZE ];
uint8_t rx_index = 0;
uint8_t ocppalldata_received = 0;

int main(void) {
 //initialize all configured peripherals
 // Start UART reception in interrupt mode
 HAL_UART_Receive_IT(&huart5, ocpp_rxdata, sizeof(ocpp_rxdata));
 while (1) {
	ocpp_request();
 }
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
 if (huart->Instance == huart5) {
 if (rx_index < UART_RXBUFFER_SIZE) {
 ocpp_rxdata[rx_index++] = huart->Instance->RDR; // Read received data
 if (rx_index >= UART_RXBUFFER_SIZE) {
 ocppdata_received = 1; // Set flag when buffer is full
 }
 }
 }
}
void ocpp_request()
{
	if (ocppdata_received) {
 // Check CRC and start transmission
	 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:
					 ocpp_txdata[0] = 0x23;
					 ocpp_txdata[1] = 0x09;
					 ocpp_txdata[2] = 0x11;
					 ocpp_txdata[3] = 0x23;
					 ocpp_txdata[4] = 0x09;
					 ocpp_txdata[5] = 0x11;
 HAL_UART_Transmit(&huart5, ocpp_txdata, 6, 100);
 break;
 case 0x02:
					 ocpp_txdata[0] = 0x23;
					 ocpp_txdata[1] = 0x09;
					 ocpp_txdata[2] = 0x15;
					 ocpp_txdata[3] = 0x24;
					 ocpp_txdata[4] = 0x03;
					 ocpp_txdata[5] = 0x14;
 HAL_UART_Transmit(&huart5, ocpp_txdata, 6, 100);
 break;
 
 }
 }

 // Reset flags and buffer
 ocppdata_received = 0;
 rx_index = 0;
	HAL_UART_Receive_IT(&huart5, ocpp_rxdata, sizeof(ocpp_rxdata));
 }
	}
 }

 

 


Thanks

Pavel A.
Super User
January 25, 2024

whenever I restated the system and if I remove the power in those cases initially I can't able to transmit.

What means initially? Will the transmission start working by itself after some time or you have to reset the STM32 several times?

There is whole class of notorious issues with starting the app after power cycle vs. no power cycle, under debugger vs. no debugger - caused often by wrong connection of NRST or BOOT0 pins. And another class of notorious issues caused by bad power.

 

Senior
January 30, 2024

@Pavel A. wrote:

whenever I restated the system and if I remove the power in those cases initially I can't able to transmit.

What means initially? Will the transmission start working by itself after some time or you have to reset the STM32 several times?


Hi @Pavel A. ,
As per my observation till now most of the times either I have to reset the STM32 or I have to debug the program again to get it worked.
Few times transmission starting by it self after some time.
Initially I observed this issue while using the breakpoints whenever breakpoint occurs, transmission from STM32 to other MCU getting stopped but reception of data from other MCU to STM32 happening.
After that now I am observing above issue.
Boot0 pin is connected to GND through 10K resistor.
NRST pin is connected to reset switch setup.
Is both pins are correct?

Thanks

Pavel A.
Super User
January 29, 2024

Would want to use a HAL_UART_ReceiveIT() cyclically so it catches all inbound data as it arrives.

Sorry but this often is a recipe for failure. Every call to HAL_UART_ReceiveIT enables the RX interrupt and disables it on completion, creating time windows when interrupt is disabled. This is especially harmful with size = 1 and no FIFO,

>A non-HAL implementation is all possible and likely more efficient.

+1

 

Tesla DeLorean
Guru
January 29, 2024

>>Sorry but this often is a recipe for failure. 

I haven't looked at the implementation details in a while, but I'm pretty sure there shouldn't be any kind of race condition if the interrupt is reenabled within the interrupt handler / call-back. The trick would be not to wander off task doing things that take longer than the expected reception time.

Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
Pavel A.
Super User
January 29, 2024

 if the interrupt is reenabled within the interrupt handler / call-back

A higher priority interrupt can cut in and here you get it. The precious CPU cycles in the handler could be better used to save or compare the received bytes.

 

Senior
February 2, 2024

Hi @Pavel A. @Tesla DeLorean ,

I checked UART communication from pollforconversion to interrupt method. but I am facing the issue.The data is transmitting and receiving between stm32g4 and other mcu.Some time I am not receiving the data properly like SOF always 0x22 and EOF 0x04 always. data bytes not coming peroperly as expected so then i can't be tramit and receive the proper data.
below added code

int main(){ 
//all initializations
HAL_UART_RegisterCallback(&huart5,HAL_UART_RX_COMPLETE_CB_ID,HAL_UART_RxCpltCallback);
 HAL_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

}


Sometimes data reception and tramission happening normally only but sometimes I am receiving the in the proper format so receiver data byte are changing so can't able to receive or transmit.
Please suggest .
Thanks