Skip to main content
BSang
Associate II
Aug 27, 2019 11:43 PM UTC
Question

HAL USART DMA buffer reset method?

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.

12 replies

Tesla DeLorean
Guru
Aug 28, 2019 1:03 AM UTC

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
Aug 28, 2019 1:10 AM UTC

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
Aug 28, 2019 1:14 AM UTC

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
Aug 28, 2019 2:28 AM UTC

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
Aug 28, 2019 5:43 AM UTC

Thanks Trevor, where did you find it?

Trevor Jones
Senior
Aug 28, 2019 6:25 AM UTC

I wrote it

BSang
BSangAuthor
Associate II
Aug 28, 2019 6:35 AM UTC

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
Aug 28, 2019 7:50 AM UTC

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
Aug 28, 2019 7:57 AM UTC

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
Aug 28, 2019 9:03 AM UTC

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
Aug 28, 2019 9:23 AM UTC

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...