cancel
Showing results for 
Search instead for 
Did you mean: 

HAL USART DMA buffer reset method?

BSang
Associate III

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.

12 REPLIES 12

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
Up vote any posts that you find helpful, it shows what's working..

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
Associate III

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.

BSang
Associate III

This is the code I'm thinking of.

char StartChar = '&';

char bluetoothCode = 'C' //or MAC Address first char

void HAL_UART_RxCpltCallback

{

if (huart->Instance == USART3)

{

if(rxBuffer[0] != StartChar || (strchr(rxBuffer, bluetoothCode) != null))

{

//reset RX buffer or count.

}

else if (rxBuffer[0] == StartChar)

{

 HAL_UART_Transmit_DMA(&huart1, rxBuffer, SIZE_OF_RX_TX);

     HAL_UART_Receive_DMA(&huart3, rxBuffer, SIZE_OF_RX_TX);

}

}

}

Trevor Jones
Senior

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:

Thanks Trevor, where did you find it?

Trevor Jones
Senior

I wrote it

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

can't found it.

T J
Lead

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;
}