cancel
Showing results for 
Search instead for 
Did you mean: 

UART with DMA and IT on STM32F446

fab04
Associate III

Hi everybody,

On my project, my µC receives data from a rapsberry pi on a serial bus.

For another project, I've used this method : https://github.com/MaJerle/stm32-usart-uart-dma-rx-tx/blob/main/projects/usart_rx_idle_line_irq_F4/Src/main.c to receive data with unknown length, it was working very well.

So, i'd like to use the same thing, but I have something that I don't understand.

For my test, Raspberry in sending the following frame every 10s ("DATA RASPBERRY"). My buffer has 64 bytes.

The following line gives me the position of cursor : 

pos = ARRAY_LEN(buffer_rx_dma_rs1) - __HAL_DMA_GET_COUNTER(huart->hdmarx);

So, the first time, it gives me 14, the second time 28 and the third time  32 (instead of 42), but 32 is the half of 64.

When I take a look on the values, ARRAY_LEN(buffer_rx_dma_rs1) = 64 and __HAL_DMA_GET_COUNTER(huart->hdmarx) = 22, but pos = 32, how is it possible that the substract operation is false ?

1 ACCEPTED SOLUTION

Accepted Solutions
fab04
Associate III

I just notice that I can disable the HT interrupt. Now, it works better.

View solution in original post

6 REPLIES 6
Guenael Cadier
ST Employee

Hi @fab04 
Regarding your question, could it be that the event that leads to getting 32 pos is the Half Transfer DMA interrupt ?
(whilst the 2 first ones are the IDLE events that occur after the first transmissions).
So, after 14 bytes received + pause => IDLE
after 14 bytes more + pause => IDLE
then 4 first bytes of next 14 will trigger DMA Half Transfer
then 10 following ones + pause => IDLE

FYI, some API have been added in STM32 HAL drivers, to handle this kind of use cases, or more globally to handle reception of unknown length. It has been based on example you are referring to.
For reference, you could find an F4 example, using this API here.
More details could also be found in this post.

Regards

Thank you for your reply.

 


@Guenael Cadier wrote:

Hi @fab04 
Regarding your question, could it be that the event that leads to getting 32 pos is the Half Transfer DMA interrupt ?

 


I think it's what happen. But why the reading value is wrong, very weird.

Concerning your link, I saw it yesterday, I tested it, and it was the same, but I'll retry it now, and let your inform.

Thank you.

fab04
Associate III

I just put this example.

My data are well received in aRxBufferUser (it's the DMA's buffer).

The final data that I want to bring back are located in pBufferReadyForReception or pBufferReadyForUser, I'm not sure.

If I take a look in these values, values are moving, because for me, if I look pBufferReadyForUser[0], the data must always be the character 'D', but in live expression, it changes at each time.

image2.png  image1.png

fab04
Associate III

I was looking the different values.

1st time : RPI sends a frame, µc receives it. Size = 14 (IT from idle)

2nd time : RPI sends a frame, µc receives it Size = 15 (IT from HT), uwNbReceivedChars = 1, copy of one character in pBufferReadyForUser[0],

then new IT (IT from idle), Size = 28, uwNbReceivedChars  = 13, but the copy starts also with pBufferReadyForUser[0], so the first character is deleted.

if (Size != old_pos)
	  {
	    /* Check if position of index in reception buffer has simply be increased
	       of if end of buffer has been reached */
	    if (Size > old_pos)
	    {
	      /* Current position is higher than previous one */
	      uwNbReceivedChars = Size - old_pos;
	      /* Copy received data in "User" buffer for evacuation */
	      for (i = 0; i < uwNbReceivedChars; i++)
	      {
	        pBufferReadyForUser[i] = aRXBufferUser[old_pos + i];
	      }
	    }
	    else
	    {
	      /* Current position is lower than previous one : end of buffer has been reached */
	      /* First copy data from current position till end of buffer */
	      uwNbReceivedChars = RX_BUFFER_SIZE - old_pos;
	      /* Copy received data in "User" buffer for evacuation */
	      for (i = 0; i < uwNbReceivedChars; i++)
	      {
	        pBufferReadyForUser[i] = aRXBufferUser[old_pos + i];
	      }
	      /* Check and continue with beginning of buffer */
	      if (Size > 0)
	      {
	        for (i = 0; i < Size; i++)
	        {
	          pBufferReadyForUser[uwNbReceivedChars + i] = aRXBufferUser[i];
	        }
	        uwNbReceivedChars += Size;
	      }
	    }

 

TDK
Super User

RxEventCallback gets called on IDLE event but also on HT. This is what is happening.

If you feel a post has answered your question, please click "Accept as Solution".
fab04
Associate III

I just notice that I can disable the HT interrupt. Now, it works better.