2024-08-22 09:00 AM
I'm working on a project using the STM32H563RIT6 microcontroller where I need to receive data over UART using DMA with idle line detection. The data is sent from a Python script using 'pyserial'. My setup is as follows:
typedef enum{ IDLE, SET_FREQUENCY, SPI_WRITE, SPI_READ, SPAM, TEST_CONN } UserCommand_t; typedef struct{ UserCommand_t Command; uint8_t RegAddr; uint16_t WriteData; uint32_t BufferCRC; } ConfigMsg_t; #define CRC_SIZE 4U ConfigMsg_t UART_Rx_MsgBuffer = {0}; ConfigMsg_t ConfigMsg = {0}; uint32_t CRCValue = 0; uint8_t RxSampleBuffer[20] = {0}; int CallCount = 0; int SizeBytes = 0; int CRCFailCount = 0; int main() { // Initialization and loop code printf("RxCount - %u: \t ", RxCount); for(int i = 0; i<sizeof(RxSampleBuffer); i++){ RxSampleBuffer[i] = 255; printf("%u \t", RxSampleBuffer[i]); } printf("\n"); HAL_UARTEx_ReceiveToIdle_DMA(&huart4, (uint8_t*)&UART_Rx_MsgBuffer, sizeof(ConfigMsg_t)); while(1){ } } void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){ RxCount++; SizeBytes = Size; CRCValue = HAL_CRC_Calculate(&hcrc, (uint32_t*)&UART_Rx_MsgBuffer, sizeof(ConfigMsg_t) - CRC_SIZE); memcpy(&RxSampleBuffer, &UART_Rx_MsgBuffer, sizeof(ConfigMsg_t)); if(UART_Rx_MsgBuffer.BufferCRC == CRCValue){ memcpy(&ConfigMsg, &UART_Rx_MsgBuffer, sizeof(ConfigMsg_t)); } else{ CRCFailCount++; } printf("RxCount - %u: \t ", RxCount); for(int i = 0; i<sizeof(RxSampleBuffer); i++){ printf("%u \t", RxSampleBuffer[i]); RxSampleBuffer[i] = 255; } printf("\n"); memset(&UART_Rx_MsgBuffer, '\0', sizeof(ConfigMsg_t)); HAL_UARTEx_ReceiveToIdle_DMA(&huart4, (uint8_t*)&RxSampleBuffer, sizeof(ConfigMsg_t)); }
When I transmit {5, 3, 0, 3, 50, 63, 42, 114} from 'pyserial', I get the following output:
RxCount - 0: 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
RxCount - 1: 5 3 0 3 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255
RxCount - 2: 0 0 0 0 0 0 42 114 255 255 255 255 255 255 255 255 255 255 255 255
The image below shows the Live Expressions window:
I'm experiencing an issue where the UART reception seems to split the incoming data into multiple callbacks, even though the data is being sent in a single transmission. Specifically:
My questions are:
Any insights or suggestions on how to properly configure the UART to avoid this issue would be greatly appreciated!
Thank You!
2024-08-26 08:08 AM
I`ve had a similar issue, when it was triggering both HT and FT callback for DMA reception, never filling the buffer properly storing only half of input data. In GPDMA I had adjusted burst size to 1 byte for RX(Increments destination addresses) and TX(Increments source addresses), that solved an issue for me, hopefully it helps.
2024-08-26 11:58 AM
Disable HT callback so that you only get an interrupt for a TC callback
__HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
2024-09-03 04:17 AM
Hello Karl,
Thank you for your reply. I have tried disabling the interrupt in the following ways and have received varying results, which are listed below:
Code:
/* USER CODE BEGIN 2 */
__HAL_DMA_DISABLE_IT(&handle_GPDMA1_Channel0, DMA_IT_HT);
printf("RxCount - %u: \t ", RxCount);
for(int i = 0; i<sizeof(RxSampleBuffer); i++){
RxSampleBuffer[i] = 255;
printf("%u \t", RxSampleBuffer[i]);
}
printf("\n");
HAL_UARTEx_ReceiveToIdle_DMA(&huart4, (uint8_t*)&UART_Rx_MsgBuffer, sizeof(ConfigMsg_t));
/* USER CODE END 2 */
/* Infinite loop */
Output:
RxCount - 0: 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
On transmitting {5, 3, 0, 3, 50, 63, 42, 114} from 'pyserial' for the first time:
RxCount - 1: 5 3 0 3 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255
RxCount - 2: 0 0 0 0 0 0 42 114 255 255 255 255 255 255 255 255 255 255 255 255
On transmitting the same data a second time:
RxCount - 3: 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255
RxCount - 4: 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255
Input:
{5, 3, 0, 3, 50, 63, 42, 114} from 'pyserial'
Output:
RxCount - 0: 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
First transmission:
RxCount - 1: 5 3 0 3 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255
RxCount - 2: 5 3 0 3 50 63 42 114 255 255 255 255 255 255 255 255 255 255 255 255
Second transmission:
RxCount - 3: 5 3 0 3 50 63 42 114 255 255 255 255 255 255 255 255 255 255 255 255
RxCount - 4: 5 3 0 3 50 63 42 114 255 255 255 255 255 255 255 255 255 255 255 255
The HAL_UARTEx_RxEventCallback is called twice for every transmission.
Code:
/* USER CODE BEGIN 2 */
/*
Code to print initial contents of RxSampleBuffer.
*/
//HAL_UART_Receive_DMA(&huart4, (uint8_t*)&UART_Rx_MsgBuffer, sizeof(UART_Rx_MsgBuffer));
HAL_UARTEx_ReceiveToIdle_DMA(&huart4, (uint8_t*)&UART_Rx_MsgBuffer, sizeof(ConfigMsg_t));
__HAL_DMA_DISABLE_IT(&handle_GPDMA1_Channel0, DMA_IT_HT);
/* USER CODE END 2 */
// Callback Function:
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){
RxCount++;
SizeBytes = Size;
CRCValue = HAL_CRC_Calculate(&hcrc, (uint32_t*)&UART_Rx_MsgBuffer, sizeof(ConfigMsg_t) - CRC_SIZE);
memcpy(&RxSampleBuffer, &UART_Rx_MsgBuffer, sizeof(ConfigMsg_t));
if(UART_Rx_MsgBuffer.BufferCRC == CRCValue){
memcpy(&ConfigMsg, &UART_Rx_MsgBuffer, sizeof(ConfigMsg_t));
}
else{
HAL_GPIO_TogglePin(LED_USER_GPIO_Port, LED_USER_Pin);
CRCFailCount++;
}
printf("RxCount - %u: \t ", RxCount);
for(int i = 0; i<sizeof(RxSampleBuffer); i++){
printf("%u \t", RxSampleBuffer[i]);
RxSampleBuffer[i] = 255;
}
printf("\n");
// memset(&UART_Rx_MsgBuffer, '\0', sizeof(ConfigMsg_t));
HAL_UARTEx_ReceiveToIdle_DMA(&huart4, (uint8_t*)&RxSampleBuffer, sizeof(ConfigMsg_t));
__HAL_DMA_DISABLE_IT(&handle_GPDMA1_Channel0, DMA_IT_HT);
}
Output:
RxCount - 0: 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
First Transmission:
RxCount - 1: 5 3 0 3 50 63 42 114 255 255 255 255 255 255 255 255 255 255 255 255
The data is received correctly for all subsequent transmissions.
However, on uncommenting 'memset(&UART_Rx_MsgBuffer, '\0', sizeof(ConfigMsg_t))' in HAL_UARTEx_RxEventCallback, the following data is received:
RxCount - 0: 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255 255
First Transmission:
RxCount - 1: 5 3 0 3 50 63 42 114 255 255 255 255 255 255 255 255 255 255 255 255
All subsequent transmissions:
RxCount - 2: 0 0 0 0 0 0 0 0 255 255 255 255 255 255 255 255 255 255 255 255
Although disabling the HT callback works to some extent, it is still unclear to me why the HAL_UARTEx_RxEventCallback is called multiple times, even though the data is being transmitted only once from PySerial. Additionally, I am unable to clear the UART_Rx_MsgBuffer before receiving new data. I would appreciate your advice and clarification on these issues.
Thank you.