I'm trying to get UART transmit working over DMA on an stm32f405. This part of my application is designed to send out text strings as a command line interface. I have the RX part of the UART working with DMA fine (using 1 byte circular DMA to handle anything that comes in) but the TX side is proving a little more tricky.
I'm able to send out strings of data using: HAL_UART_Transmit_DMA(&handle, pData[], strlen(pData))
provided there is a delay between consecutive calls of the function. As soon as my program decides to send two strings one after another, the new data pointer is ignored.
By using while(HAL_UART_Transmit_DMA(...) != HAL_OK){}
I'm able to have the program wait the required time and send out consecutive strings.
This works for a while (few tens of transfers), then gets stuck due to HAL_NOT_OK.
For reference, my DMA settings are: DMA2 stream 7
, channel 4
, mem to periph
, periph inc disabled
, mem inc enabled
, mem and periph align byte
, normal mode (not circular)
, low priority
, fifo disabled
.
UART set to 9600 baud
, 8 bit word
, 1 stop bit
, no parity
, no hw control
, 16 oversampling
.
I'm trying to figure out if using FIFO will help me out here, though I'm not totally sure if i understand it yet. If i wanted to send out a single byte of data, could i do it with FIFO? is there a 1 word min limit here?
I have set up a tx complete callback
that im not currently using. I did wonder if there are any flags I'd need to clear during this interrupt but not sure..
Any help appreciated!
I have set up a tx complete callback that im not currently using. I did wonder if >there are any flags I'd need to clear during this interrupt but not sure.
You SHOULD wait for the tx complete
callback before using HAL_UART_Transmit_DMA
again. Something like:
bool txDoneFlag = false;
HAL_UART_Transmit_DMA(...)
while(!txDoneFlag);
txDoneFlag = false;
...
...
void HAL_UART_TxCpltCallback(){
txDoneFlag = true;
}
FIFO for the transmit is useful if you are transmitting at high baud rates (>1MBaud). What happens is that the processor can't feed the UART fast enough and then a buffer underflow related error can occur. You can also change the priority of the DMA channel feeding the UART.
Circular mode is not that useful for TX, as it will endlessly retransmit the data in the buffer, unless you've updated it in time. Though I find circular buffers very useful for receiving data.
I have also had issues where if the number of bytes transmitted was small (<10Bytes) that the DMA transmission would fail after a while. Using the IT function worked without issue. I was never able find the reason. Thus, for messages < 10 bytes, I use the IT transmit function and for messages >= 10 bytes, I use the DMA transmit function.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With