cancel
Showing results for 
Search instead for 
Did you mean: 

UART DMA TX/Rx problem w/ STM32F722 example

David Pekin
Senior
Posted on February 14, 2018 at 01:55

Hello,

I have a program using serial UART communicatons. I based the UART code on the example code UART_TwoBoards_ComDMA.  The system seems to work correctly when it is in command/response mode.  That means, I can send a serial packet from the PC to the F7.  It receives it, processes it, and sends the response back to the PC. It seems fairly reliable.  

I really don't understand why the UART is constantly reinitalized.  The code initializes the uart handle, then calls the TransmitDMA function, then reinitialize the UART handle and then calls the ReceiveDMA function.  Why is the reinitialization of the UART handle needed between the Transmit and Receive function??? 

While the system is working in the command/response mode, now I need to asynchronously transmit packets from the F7 to the PC based on a timer.  And I need to still handle the command/response from the PC correctly.  Unfortunately, when I start trying to send these packets everything starts to fall apart.  Once the async packets start sending to the PC, the system stops receiving command packets from the PC.

So I have the system in RX mode (ReceiveDMA function called) and the timer fires. The code reinitializes the UART handle (why is this necessary?) and then transmits the packet (TransmitDMA). The send code  waits for the UartReady == SET flag which indicates that the transmission is complete and then reinitializes the UART and calls the ReceiveDMA function again. 

The problem is that once the asynchronous transmit packets start (only once every second right now) the system fails to receive the command packets from the PC.  If I break in the debugger and turn off the asynchronous transmission, the command/response works correctly....   Below is the send code.

I would really like to setup and initialize the UART handle once and then just service the TX and RX callbacks.  Is there a way to do that?  

Thanks for any suggestions.

static void UART_Send(void)

{

HAL_StatusTypeDef retval;

// WHY do we need to reinitialize?

if(HAL_UART_DeInit(&UartHandle) != HAL_OK)

{

Error_Handler();

}

if(HAL_UART_Init(&UartHandle) != HAL_OK)

{

Error_Handler();

}

/*##-2- Start the transmission process #####################################*/

/* While the UART in reception process, user can transmit data through

'aTxBuffer' buffer */

UartReady = RESET;

do {

retval = HAL_UART_Transmit_DMA(&UartHandle, (uint8_t*)&cmd_Response, cmd_Response.msg_len+5); // + 5 for 3 byte header and 2 byte CRC

} while (retval != HAL_OK);  // I know  we need to handle the error condition here...

/*##-3- Wait for the end of the transfer ###################################*/

while (UartReady != SET) // this is set in the TX complete callback

{

}

/* Reset transmission flag */

UartReady = RESET;

/*##-4- Put UART peripheral in reception process ###########################*/

// WHY do we need to reinitialize?

if(HAL_UART_DeInit(&UartHandle) != HAL_OK)

{

Error_Handler();

}

if(HAL_UART_Init(&UartHandle) != HAL_OK)

{

Error_Handler();

}

// leave in receive mode

if(HAL_UART_Receive_DMA(&UartHandle, (uint8_t *)UART_aRxBuffer, sizeof(api_msg_t)) != HAL_OK)

{

Error_Handler();

}

}
5 REPLIES 5

Sorry, bumping old zombie unanswered questions off my feed

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

I think I may have an explanation. If I try to do full duplex TX and RX, I can make the characters appear from keyboard to screen but I can't see them in SRAM. The re-initialization may be a workaround.

On CM7 devices remember you have caching, and memory updated by a peripheral via DMA is not always visible to the CPU unless you address the coherency issues.

The HAL also layers on a lot of unnecessary complexity.

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

Since UART should work in full-duplex mode (theoretically) , I've built my own interrupt handler to try to explode this feature by reading the RDR=>DR registers and then writing to DR=>TDR registers. If you take a look at the ISR function to handle UART interrupts, this first receives and then transmits, not both at the same time, but maybe rx has higher priority since once HAL_UART_Receive_IT/DMA is called, HAL_UART_Transmit_IT/DMA doesn't work. unless a delay of about 100 milliseconds is applied. This must be a silicon bug and I believe STM32 microcontrollers are plenty of flaws.

The HAL has a host of issues, software induced race conditions and priority inversions being a subset of them, the silicon is surprisingly solid. Software guys always flag silicon bugs, but without a register level validation test case such reports are frequently ignored.

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