2025-07-22 8:32 AM
Hello, everyone.
There is an issue related to USART3 DMA Receive of STM32F407.
I'd like to use 500 bytes of USART3 DMA Receive.
I wrote 500 bytes on UART Sender, but USART3 DMA Receive Callback is not working.
I checked UART_FLAG_IDLE because I wanted to know why.
When I checked IDLE Interrupt, it reads twice, 48 bytes each, and it doesn't read anymore. In total, only 96 bytes are read.
I would like to know why these symptoms occur and how to resolve them.
------ IDLE INTERRUPT CONFIRMATION CODE
void USART3_IRQHandler(void)
{
/* USER CODE BEGIN USART3_IRQn 0 */
if (__HAL_UART_GET_FLAG(&huart3, UART_FLAG_IDLE))
{
__HAL_UART_CLEAR_IDLEFLAG(&huart3);
uint16_t remaining = __HAL_DMA_GET_COUNTER(huart3.hdmarx);
uint16_t received = MAKE_SEND_DATA_LENGTH - remaining;
uint32_t curr_mem = huart3.hdmarx->Instance->CR & DMA_SxCR_CT ? 1 : 0;
extern void ProcessReceivedData(uint8_t *, uint16_t);
extern uint8_t recvUartHeaderData[NUM_BUFFERS][MAKE_SEND_DATA_LENGTH];
ProcessReceivedData((uint8_t *)huart3.pRxBuffPtr - (MAKE_SEND_DATA_LENGTH - remaining), received);
HAL_UART_Receive_DMA(&huart3, (uint8_t *)huart3.pRxBuffPtr - (MAKE_SEND_DATA_LENGTH - remaining), MAKE_SEND_DATA_LENGTH);
}
/* USER CODE END USART3_IRQn 0 */
HAL_UART_IRQHandler(&huart3);
/* USER CODE BEGIN USART3_IRQn 1 */
/* USER CODE END USART3_IRQn 1 */
}
------- The receive callback code that doesn't work is
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
UARTHEADER pUartHeader;
if (huart->Instance == USART3) {
memcpy(&pUartHeader, recvUartHeaderData[0]+PACKETHEADERLENGTH, 39/*sizeof(UARTHEADER)*/);
Process_UART_Block(&pUartHeader);
HAL_UART_Receive_DMA(&huart3, (uint8_t*)recvUartHeaderData[0], 48/*MAKE_SEND_DATA_LENGTH*/);
}
}
It is.
2025-07-22 9:16 AM
Did the DMA complete?
You'd likely need the IRQ Handler for the DMA controller (channel / stream) to be initiating any sort of call back.
Check the error/status reported by the DMA rather than the USART
2025-07-22 12:12 PM
Calling HAL_UART_Receive_DMA again before the transfer is complete won't achieve anything. It'll return HAL_BUSY.
If you want to process IDLE events, use HAL_UARTEx_ReceiveToIdle_DMA.
Checking and clearing flags within the IRQ handler should be left to HAL.
2025-07-22 12:13 PM
When posting code use the </> to insert code so that it's properly formatted and readable.
You have to be more specific on what you mean "The receive callback code that doesn't work is"?
Do you mean it's not interrupting? Not saving the data correctly?
Also, don't write code in USART3_IRQHandler. You want your code in HAL_UART_RxCpltCallback after HAL has already cleared flags.