cancel
Showing results for 
Search instead for 
Did you mean: 

Uart DMA does not receive after a while

ozgeplusplus
Associate

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;

 
UART_HandleTypeDef huart4;
UART_HandleTypeDef huart5;
DMA_HandleTypeDef hdma_uart4_tx;
DMA_HandleTypeDef hdma_uart4_rx;


void sendData(char *data) {
    if (txComplete) {
       txComplete = 0;
       for (int i = 0; i < 8; i++) {
       txdata[i] = data[i];
       }
       HAL_UART_Transmit_DMA(&huart4, txdata, 8);
    }
}
 
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart == &huart4) {
         txComplete = 1;
    }
}

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);
    }
}




int main(void)
{
//...
//...

HAL_UART_Receive_DMA(&huart4, (uint8_t *)Buf_1ch, 1);
__HAL_DMA_DISABLE_IT(&hdma_uart4_rx, DMA_IT_HT);
...
....
}


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);

}

4 REPLIES 4
Imen.D
ST Employee

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

When your question is answered, please close this topic by clicking "Accept as Solution".
Thanks
Imen
Gedo
Associate II
void sendData(char *data) {
    if (txComplete) {
////////////       txComplete = 0;
       for (int i = 0; i < 8; i++) {
       txdata[i] = data[i];
       }
       HAL_UART_Transmit_DMA(&huart4, txdata, 8);
 
 txComplete = 0; // I think you flag maybe is reset . but if it is happen probably you losing data
    }
}
Thomas LB
Associate III

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

Karl Yamashita
Lead II

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);
    }
}