Skip to main content
BSang
Associate II
August 27, 2019
Question

HAL USART DMA buffer reset method?

  • August 27, 2019
  • 6 replies
  • 5651 views

Hi Community,

I find a method to reset a buffer of USART DMA Buffer.

because I use USART DMA basically.

my system is consist of android smartphone, bluetooth and microcontroller(STM32F407VET), PC

when I click a button that implemented in a android, some packet is send to the bluetooth RX

and Bluetooth TX that connected to micro controller USART3 RX.

than Received USART3 Data directly send to USART1 and I can see the packet in PC program.

(So... long)

I learned about HAL USART DMA is need a fixed buffer size.

so I designed the system the length of the packet is always fixed.

But! when the Bluetooth is connected, the packet is occurred by Bluetooth like

"Connected X" (X is MAC address of Bluetooth)

Due to the packet that I don't want, DMA buffer is shifted.

like under example.

ex)​

Normal State

​buffer size 5

send "12345" => receive​ "12345"

Abnormal state​

send "12345" => add packet "ab"=>receive​ "ab123"​

For this reason, I would like to ask community How to reset DMA buffer.

Of course, using a ring buffer is best way, but I'm not have a code that work normally, and other is I can't understand the code algorithms.

Ask for help...

Thank.

This topic has been closed for replies.

6 replies

Tesla DeLorean
Guru
August 28, 2019

https://community.st.com/s/question/0D50X0000BFxPVhSQN/read-and-write-bluetooth-communication-byte-format

So more of a Synchronization issue.

The code in your other thread receives data into the buffer twice, and blocks (I assume)

Doing one byte at a time with DMA seems overkill.

Blocking doing 5 bytes and ping-pong between send/receive looks prone to lose data. You need to use DMA/IT versions that can function concurrently, and manages how much data comes in and goes out.

Fixed length receive really requires a continuous stream of data.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
BSang
BSangAuthor
Associate II
August 28, 2019

Thanks you!

That link is just test.

Now I'm not use DMA only one byte.

I set a length of DMA buffer, size 32byte.

I fixed a length of buffer(send / receive).

BSang
BSangAuthor
Associate II
August 28, 2019

So I check

HAL_UART_Receive_DMA(&huart1, rxBuffer, SIZE_OF_RX_TX);

function means that, USART1 RX channel wait untill RXbuffer size is same SIZE_OF_RX_TX.

SIZE_OF_RX_TX is define, 32byte,

finally, I think if I send and receive fixed packet, it is easy to use USART DMA.

but, I didn't think of Bluetooth make a packet itself...

Eventually I try to reset the DMA buffer (or counter) as soon as it detects a Bluetooth packet.

Trevor Jones
Senior
August 28, 2019

I have found this to be

void initUart1RxDMABuffer(void) {
 if (HAL_UART_Receive_DMA(&huart1, (uint8_t *)Usart1RxDMABuffer, U1RxBufSize) != HAL_OK)
 {
 sprintf(string, "initUart1RxDMABuffer Failed\n");
 puts1(string); 
 }
 else
 {
 sprintf(string, "initUart1RxDMABuffer OK!\n");
 puts1(string);
 }
}
char peekRxU1(int offset) {
 // offset of zero returns the next byte to be read
 int relativePtr = (U1RxBufferPtrOUT + offset) & (U1RxBufSize - 1); 
 char PeekRx = Usart1RxDMABuffer[relativePtr]; // just looking Don't increment pointer
return PeekRx;
}
char readU1(void) {
 char readByte = Usart1RxDMABuffer[U1RxBufferPtrOUT++];
 if (U1RxBufferPtrOUT >= U1RxBufSize) U1RxBufferPtrOUT = 0;
 return readByte;
}
char readableU1(void) {
 U1RxBufferPtrIN = U1RxBufSize - huart1.hdmarx->Instance->CNDTR;
 return U1RxBufferPtrIN - U1RxBufferPtrOUT;
} 
void clearRxBuffer(void) {
 U1RxBufferPtrIN = U1RxBufSize - huart1.hdmarx->Instance->CNDTR;
 U1RxBufferPtrOUT = U1RxBufferPtrIN;
}

the best way:

BSang
BSangAuthor
Associate II
August 28, 2019

Thanks Trevor, where did you find it?

Trevor Jones
Senior
August 28, 2019

I wrote it

BSang
BSangAuthor
Associate II
August 28, 2019

I'm trying use huart1.hdmarx->Instance->CNDTR, but CNDTR is not​ member of structure DMA_Stream_TypeDef

can't found it.

T J
Senior III
August 28, 2019

I use this on the F7, just looking over the code I sent you, in Peek(), there is a requirement that the Rx buffer size is 2^N

char readableU1(void) {
 U1RxBufferPtrIN = U1RxBufSize - huart1.hdmarx->Instance->NDTR;
 return U1RxBufferPtrIN - U1RxBufferPtrOUT;
} 

BSang
BSangAuthor
Associate II
August 28, 2019

Thanks TJ,

what type is U1RxBufferPtrIN  and U1RxBufferPtrOUT?

char readableU1(void) {

  U1RxBufferPtrIN = U1RxBufSize - huart1.hdmarx->Instance->CNDTR;

  return U1RxBufferPtrIN - U1RxBufferPtrOUT;

}  

readableU1 is means that USART1 RX Channel is available?

It is not a clear buffer methods?

T J
Senior III
August 28, 2019

uint32_t U1RxBufferPtrIN ;

uint32_t U1RxBufferPtrOUT=0;

make your buffer size 2^N like 256 or 512 or 1024 or 2048 or 4096 bytes

T J
Senior III
August 28, 2019

Yes, use clear clearRxBuffer() to make the U1RxBufferPtrOUT equal to the DMA pointerIN , U1RxBufferPtrIN

then when you do readableU1() there return value will be Zero...