cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_UART_Receive_DMA calls RxCpltCallback, but receives no data

Lars Beiderbecke
Senior III

In my project, I'm using UART1 with DMA enabled, similar to this:

MX_GPIO_Init();
MX_DMA_Init();
MX_UART7_Init(); // initializes, and I assume, correctly
 
void DMA1_Stream1_IRQHandler(void) {
  HAL_DMA_IRQHandler(&hdma_uart7_tx);
}
 
void DMA1_Stream3_IRQHandler(void) {
  HAL_DMA_IRQHandler(&hdma_uart7_rx);
}
 
void UART7_IRQHandler(void) {
  HAL_UART_IRQHandler(&huart7);
}
 
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
  if (huart->Instance == UART7)
    complete = 1;
}
 
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
  error();
}

The setup was with CubeMX, and I included the IR-related stuff. The DMA is non-circular, with auto-increase for memory but not for the peripheral.

The code that receives data looks like this:

complete = 0;
HAL_UART_Receive_DMA(&huart7, buffer, size);
HAL_DELAY(5000); // <-- simplified
if (complete)
   return buffer;
 

But when doing so, the callback HAL_UART_RxCpltCallback is called (i.e., complete is set to 1), but the buffer contains no (new) data. Also, the IR doesn't fire immediately (this cannot be observed with this snippet here). The sending of data works.

What am I missing here? Did I forget some action or configuration? Could this be an interrupt issue, as I'm using various priorities here?

17 REPLIES 17
Lars Beiderbecke
Senior III

Errr, I think I just had an idea. I didn't mention what kind of STM32 I'm using, but its a F722. And that buffer is most likely located in DTCM RAM.

Now if I read that F722 architecture diagram correctly, then DMA cannot possibly write to DTCM RAM. Which kind of solves the mystery, although I would've expected an error here.

Does this make sense?

Lars Beiderbecke
Senior III

I did some further experiments. My latest assumption that DMA cannot write into DTCM is not the cause of the missing data, since locating the buffer in SRAM still doesn't yield any data.

The DeInit/Init sequence still helps, but only for the first Receive. For subsequent Receives, the Error callback is called.

The bit comparison also didn't provide any clues.

Are there any other suggestions?

Bob S
Principal

Use DMA in circular mode. Yes, I know you only want to receive a fixed size buffer. But using circular mode means the DMA and UART Rx remain enabled all the time and don't need to be re-enabled/closed/re-opened/etc. Unless you are putting the CPU into a deep sleep/power-down mode between communication bursts, I don't see the need to have peripherals started and then stopped (even though that is the way the HAL library is designed).

You can poll your DMA buffer for the proper # of bytes from your main polling loop (if you have one), or from a periodic timer interrupt. Or even design your buffer size to use the "half full" DMA interrupt. There are several other posts on this forum about using UARTS and DMA and how to tell how many bytes you have received. A quick search should find them.

Thanks! Put this way, it makes a lot of sense for me. I'll try it out!

No, unfortunately the result buffer is still untouched after switching to a circular RX buffer.

Bob S
Principal

Do you *EVER* get data in the buffer? I can't find it in this thread, but I thought when this started you said it worked for the first "message", but any following messages you got the "complete" flag but the data had not changed. Is that correct, and is that still the case (it works once then not again)?

Can you simplify your program to just the UART code (send and receive) and basic system init and verify that the problem still exists? If so, post THAT code (all of it). And an exact and detailed description of what happens (ex. program starts, receives one message, sends a response, gets the "complete" flag for the 2nd message but buffer contains XXXX, and the DMA registers contain *** (specifically the CNDTR and DMA_CCR registers). And how do you know the 2nd message is actually different than the first message (i.e. what is generating the messages)? I have lots of questions that would be easier answered if we could see the source.

T J
Lead

which error flag is being set ?

Hi Lars,

I've found the same issue and this solution works. However, I am wondering if you were able to find a better solution than DeInit() then Init()?

Best regards,