2023-08-16 11:56 PM - edited 2023-08-16 11:57 PM
Hello, I am doing UART communication with DMA in my project. When the communication first starts, there is no problem, but after about 10 minutes, the receive process ends. Can you check my codes?
volatile uint8_t txdata[8];
char rxdata[8]={'*','*','*','*','*','*','*','*'};
volatile uint8_t txComplete = 1;
uint8_t rxBuf[8];
uint8_t rxindex = 0;
uint8_t Buf_1ch[1];
uint8_t len=0;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart == &huart4) {
rxdata[rxindex] = Buf_1ch[0];
rxindex++;
if (rxindex >= 8 ){
rxindex = 0;
}
HAL_UART_Receive_DMA(&huart4, Buf_1ch, 1);
}
}
static void MX_UART4_Init(void)
{
/* USER CODE BEGIN UART4_Init 0 */
/* USER CODE END UART4_Init 0 */
/* USER CODE BEGIN UART4_Init 1 */
/* USER CODE END UART4_Init 1 */
huart4.Instance = UART4;
huart4.Init.BaudRate = 115200;
huart4.Init.WordLength = UART_WORDLENGTH_8B;
huart4.Init.StopBits = UART_STOPBITS_1;
huart4.Init.Parity = UART_PARITY_NONE;
huart4.Init.Mode = UART_MODE_TX_RX;
huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart4.Init.OverSampling = UART_OVERSAMPLING_16;
huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_UART_Init(&huart4) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
{
Error_Handler();
}
if (HAL_UARTEx_DisableFifoMode(&huart4) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN UART4_Init 2 */
/* USER CODE END UART4_Init 2 */
}
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMAMUX1_CLK_ENABLE();
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
/* DMA1_Channel2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn);
/* DMA1_Channel3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel3_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel3_IRQn);
/* DMAMUX_OVR_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMAMUX_OVR_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMAMUX_OVR_IRQn);
}
2023-08-20 11:24 AM
Hello @ozgeplusplus,
Welcome to the Community :)
Are clocks of UART, GPIO enabled in RCC? I advise you to read out and check content of UART, DMA and GPIO registers.
I recommend you the following articles which contain a list of examples about STM32 UART DMA RX/TX:
Imen
2023-08-20 12:13 PM
2023-10-02 05:14 AM
Hello @ozgeplusplus did you find the root cause ? In your original post you don't explain what are the sending mechanisms (loop forever sending as soon as transmit complete flag is set ?)
@Gedo I don't understand your answer, resetting the flag after the HAL_UART_Transmit_DMA() only add the risk of flag being set and reset before the function exit so that the communication stops. Can you elaborate your idea ?
Thank you,
Thomas
2023-10-02 12:48 PM
You don't check HAL status so if it returns HAL_BUSY and you don't flag it to recover later, then you'll never get it to receive.
bool uart4RxErrorFlag = false;
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
if (huart == &huart4) {
rxdata[rxindex] = Buf_1ch[0];
rxindex++;
if (rxindex >= 8 ){
rxindex = 0;
}
UART_EnableInterrupt(&huart4);
}
}
int main(void)
{
UART_EnableInterrupt(&huart4);
while(1)
{
UART_CheckUart4ErrorFlag();
}
}
void UART_EnableInterrupt(UART_HandleTypeDef *huart)
{
if(huart == &huart4)
{
if(HAL_UART_Receive_DMA(huart, (uint8_t *)Buf_1ch, 1) != HAL_OK)
{
uart4RxErrorFlag = 1;
}
}
}
void UART_CheckUart4ErrorFlag(void)
{
if(uart4RxErrorFlag)
{
uart4RxErrorFlag = false;
UART_EnableInterrupt(&huart4);
}
}
Using DMA to receive 1 byte at a time is useless. But since you're buffering 8 bytes, then use HAL_UARTEx_ReceiveToIdle_DMA and HAL_UARTEx_RxEventCallback instead.
void UART_EnableInterrupt(UART_HandleTypeDef *huart)
{
if(HAL_UARTEx_ReceiveToIdle_DMA(huart, rxdata, 16) != HAL_OK) // double the receive byte size of 8 to 16, that way half callback calls the HAL_UARTEx_RxEventCallback after 8 bytes are received
{
uart4RxErrorFlag = 1;
}
}
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
if(huart == &haurt4)
{
// set flag to indicate rxdata has 8 bytes and ready to be parsed in main while loop.
UART_EnableInterrupt(&huart4); // re-enable interrupt
}
}
void UART_CheckUart4ErrorFlag(void)
{
if(uart4RxErrorFlag)
{
uart4RxErrorFlag = false;
UART_EnableInterrupt(&huart4);
}
}