2018-02-15 06:52 AM
Hello.
Ive worked with the two boards comm DMA sample program and it works but it only works half duplex.
The flow is:
Init UART handle,
Transmit dma
wait for tx interupt callback
reinitalize UART handle
Recieve dma
wait for rx interrupt callback
loop back to top
That sequence can be called over and over and it works. But, if you only initiialize the UART handle at the beginning, it does not work. You can make multiple transmit calls that work but calling receive dma after transmit (after waiting for tx callback) does not.
Does anyone have sample code for interrupt driven full duplex DMA UART tx & rx?
thanks
2018-02-15 07:52 AM
For the business case you'd really want to get with the FAE supporting your account, and push ST to provide clear examples, and debug common use cases for the HAL.
Reinitialization suggests a failure to clear internal states. Pay attention to error/status thrown by the library in these situations, and report those where dysfunction can be established.
https://community.st.com/0D50X00009XkePTSAZ
Related threads of evolving topic
https://community.st.com/0D50X00009XkWuASAV
https://community.st.com/0D50X00009XkWu9SAF
2018-02-15 11:41 AM
Thanks. I'll need to track down an FE but I would have thought this would be a pretty universally common way to want to drive a UART - interrupt/DMA. Should be a no brainer...
But, considering deadlines, I might instantiate a second UART that does TX only since the system seems to be OK with doing DMA transmits after DMA transmit. I'll use the RX side of UART1 1 and the TX side of UART 2 to the driver chip.... Seems like a basackward way of getting full duplex!
Unfortunately, bringing up the 2nd UART has it's own challenges....
2018-02-15 06:16 PM
>>
Should be a no brainer...
You'd think, but the HAL is a thick abstraction that frequently gets in its own way. Hardware is more than capable of walking and juggling at the same time.
2018-02-15 06:19 PM
Are you using the cube ?
I initialise the RXDMA once in startup.
void initUart1RxDMABuffer(void) {
if (HAL_UART_Receive_DMA(&huart1, (uint8_t *)Usart1RxDMABuffer, U1RxBufSize) != HAL_OK) { // Transfer error in reception process //_Error_Handler(__FILE__, __LINE__); char string[32]; sprintf(string, 'initUart1RxDMABuffer Failed\n'); puts1(string); } else { char string[32]; sprintf(string, 'initUart1RxDMABuffer OK!\n'); puts1(string); }}as I add bytes to the transmit DMA buffer, I set the flag TxDMA1BufHasData
void putc1(char saveByte) {
checkU1TxDMABufferLength(); //using normal buffer, not circular. Usart1TxDMABuffer[U1TxBufferPtrIN++] = saveByte; U1TxBufferPtrIN &= U1TxBufSize - 1; TxDMA1BufHasData = true; <- here }then in the foreground, I check if we need to initialse a txDMA stream. if there is data to send
CheckTx1DMA(){ <- check it here in foreground
if (TxDMA1BufHasData) { <- check it here in foreground
char uartState = HAL_UART_GetState(&huart1); if ((uartState == HAL_UART_STATE_READY) || (uartState == HAL_UART_STATE_BUSY_RX)) { TxDMA1BufHasData = false; // sending now if(HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Usart1TxDMABuffer + U1TxBufferPtrOUT, U1TxBufferPtrIN - U1TxBufferPtrOUT) == HAL_OK) { U1TxBufferPtrOUT = U1TxBufferPtrIN; Usart1TxDMABuffer[U1TxBufferPtrIN] = 0 ; // null } else { _Error_Handler(__FILE__, __LINE__); /* Transfer error in transmission process */ } } }}
char readableU1(void){
U1RxBufferPtrIN = U1RxBufSize - huart1.hdmarx->Instance->CNDTR; return U1RxBufferPtrIN - U1RxBufferPtrOUT;}char getc1(void) { char Rxbyte = Usart1RxDMABuffer[U1RxBufferPtrOUT++]; if (U1RxBufferPtrOUT >= U1RxBufSize) U1RxBufferPtrOUT = 0; return Rxbyte;}basic example:
// initialise Serial port 1 TxRxDMA buffer pointers
TxDMA1BufHasData = false;
U1TxBufferPtrIN = 0; U1TxBufferPtrOUT = 0; U1RxBufferPtrIN = 0; U1RxBufferPtrOUT = 0; DMA1BufAlmostFull = false; TxDMA1BufHasData = false; initUart1RxDMABuffer();while(1){
if ( mS has changed) // every mS
CheckTx1DMA(); // check anywhere in the foreground
}
in any function:
char string[32];
sprintf(string, ' processor temp is %d degrees\n', 42.3); puts1(string);if (readableU1())
{ char readByte = readU1(); if (readByte == 't') getFreshLoRaPacket = true; // from the CAN Rx packets pushed into a LoRa packetelse ...
2018-10-09 09:34 AM
I am trying to use USART3 with TX and RX DMA (stream3 and stream1). I can set TX buffer as RX buffer and have the characters loop back; but they don't seem to "stick" in SRAM. What may be happening?
2018-10-09 11:12 AM
Cache coherency?
What memory address is the buffer located?
Can you use DTCM memory?
2018-10-09 01:41 PM
DMA1_Stream1->M0AR = 0x2001 1850
maps to SRAM1; is that a problem?
2018-10-09 08:40 PM
It means you're going to have to manage the coherency issues of the CPU (cache/buffers) and Memory holding different content. Usually via DCache clean and invalidate functions.
Not familiar with these issues? Review the ENABLE_SD_DMA_CACHE_MAINTENANCE implementation here
STM32Cube_FW_F7_V1.9.0\Middlewares\Third_Party\FatFs\src\drivers\sd_diskio_dma_template.c