cancel
Showing results for 
Search instead for 
Did you mean: 

HAL_UART_Transmit_DMA/IT Returning STATE_READY too fast

Sam V
Associate II
Posted on January 13, 2017 at 23:27

Preface: I have been working with the DMA/IT TX/RX successfully and this is the first I've ran into this problem.

When trying to transmit back to back, my second transmission cuts off half of the first. Now, I'm aware that I need to wait and after testing multiple different paths the only one that works is blocking and I feel like I should be able to do this without doing that.

1. Check if HAL_BUSY

This is my classic way of doing it, I usually wrap up a call in a tight while loop, and this historically worked:

while (HAL_UART_Transmit_DMA(huart, buffer, size) == HAL_BUSY);
�?

From what I understand, this will go instantly on first try, but second try will have to wait until first is finished. It is not working that way, the state is reset back to HAL_UART_STATE_READY too fast.

2. TxCpltCallback

I then tried to use callbacks with a ready flag, (multiple files zipped together, I tried both volatile and non with no change).

extern volatile int huart1_finished_tx = 1;
...
void transmit(UART_HandleTypeDef *huart, void* buffer, int size) {
if (huart->Instance == USART1) {
// Checks and waits if previous tx is not finished
while (!huart1_finished_tx);
// Sets transmit lock
huart1_finished_tx = 0;
}
// Transmit
while (HAL_UART_Transmit_DMA(huart, buffer, size) == HAL_BUSY);
}
...
/*
 * Unlock TX
 */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == USART1) {
huart1_finished_tx = 1;
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

This seemed like it should work, however it calls the TxCpltCallback too fast, the transmission hasn't finished yet and will write too fast causing overrunning of the previous data.

3. Tight loop version of 2

This way works, but is blocking and I want to avoid this.

extern volatile int huart1_finished_tx = 1;
...
void transmit(UART_HandleTypeDef *huart, void* buffer, int size) {
if (huart->Instance == USART1) {
// Sets transmit lock
huart1_finished_tx = 0;
// Transmit
while (HAL_UART_Transmit_DMA(huart, buffer, size) == HAL_BUSY);
// Checks and waits if previous tx is not finished
while (!huart1_finished_tx);
}
}
...
/*
 * Unlock TX
 */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
if (huart->Instance == USART1) {
huart1_finished_tx = 1;
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Any help would be appreciated, I would highly prefer to not have to sit and wait for a single transmission like this when I theoretically should be able to only wait when there are overlapping transmissions.

#dma #usart #tx
1 REPLY 1
T J
Lead
Posted on January 18, 2017 at 22:26

I used this: works like a dream, 460800 1Mbyte file from PC received and retransmitted, no issues..

my processor of choice in 48Mhz '091

void CheckTxDMABufferProgress(void)

{

    

        if ( DMABufHasData ){

        char uartState = HAL_UART_GetState(&huart1);

        if ((uartState == HAL_UART_STATE_READY) || (uartState == HAL_UART_STATE_BUSY_RX))  {

   

                DMABufHasData = false;    // sending now

            

                if (HAL_UART_Transmit_DMA(&huart1, (uint8_t *)Usart1TxDMABuffer + U1TxBufferPtrOUT ,U1TxBufferPtrIN - U1TxBufferPtrOUT) == HAL_OK){

                    HAL_UART_Transmit_DMA_Status = UartDMAsuccess;

                    U1TxBufferPtrOUT = U1TxBufferPtrIN;

                }

                else{   Error_Handler();                    /* Transfer error in transmission process */

                                HAL_UART_Transmit_DMA_Status = UartDMAfailed;

                }

            }

        }

}