cancel
Showing results for 
Search instead for 
Did you mean: 

Full duplex USART example for STM32F722

David Pekin
Senior
Posted on February 15, 2018 at 15:52

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

8 REPLIES 8
Posted on February 15, 2018 at 16:52

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

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
David Pekin
Senior
Posted on February 15, 2018 at 20:41

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

Posted on February 16, 2018 at 02:16

>>

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.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Posted on February 16, 2018 at 02:19

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 packet

        else ...

BShar
Associate II

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?

Cache coherency?

What memory address is the buffer located?

Can you use DTCM memory?

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
BShar
Associate II

DMA1_Stream1->M0AR = 0x2001 1850

maps to SRAM1; is that a problem?

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

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..