AnsweredAssumed Answered

HAL_UART_Transmit_DMA/IT Returning STATE_READY too fast

Question asked by Voss.Sam.001 on Jan 13, 2017
Latest reply on Jan 18, 2017 by T J

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.

Outcomes