2024-01-24 10:23 PM
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
2024-01-24 10:35 PM
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.
2024-01-24 10:52 PM
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
2024-01-24 11:01 PM
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.
2024-01-25 12:42 AM
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
2024-01-25 09:07 AM
> 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.
2024-01-25 09:53 AM
>>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.
2024-01-29 01:36 AM
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
2024-01-29 01:48 PM - edited 2024-01-29 01:49 PM
> 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
2024-01-29 02:19 PM
>>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.