cancel
Showing results for 
Search instead for 
Did you mean: 

Receptions issues in interrupt driven IO with USART2 when HAL_UART_Receive_IT() is called before HAL_UART_Transmit_IT()

valerio2
Associate II
Posted on July 14, 2016 at 12:45

Hi there,

here it is the environment: custom board with stm32f427, Cube FW 1.11, freeRTOS, eclipse mars. This is the scenario: UART IO with a bluetooth module via USART2 peripheral. I send some strings and receive others. There are two tasks, say TxTask and RxTask: TxTask transmits while RxTask receives by using HAL_UART_Transmit_IT and HAL_UART_Receive_IT, respectively. In turn each one of such tasks communicate with queues with two corresponding tasks which operate low priority jobs related to the transmitted and received strings. Receptions are one char at a time until a condition (i.e. \n received) is not met while at this stage transmissions are fixed length strings. The micro transmits periodically a string (every 500 ms) and receive from a remote user through a tablet some commands ending with \n. So at the very beginning TxTask starts to transmit and RxTask waits in reception. This is the expected behavior: if HAL_UART_Receive_IT is called before HAL_UART_Transmit_IT (and this ultimately depends upon the scheduler), then should be UART_Handle.RxState = HAL_UART_STATE_BUSY_RX until something is not received and regardless the transmission operations. This is what happens: when HAL_UART_Receive_IT(&UART_Handle, &ch, 1) is called before HAL_UART_Transmit_IT, after a while (I was not able to catch when) UART_Handle.RxState = HAL_UART_STATE_READY even if nothing has been received (the ISR has not been called), UART_Handle.RxXferSize = 64, UART_Handle.RxXferCount = 63, and clearly I cannot receive anything. The peripheral's reception buffer pointer points to the correct memory location &ch and, this is very odd, 64 corresponds to the transmitted string length. My patch: if I put a delay, within RxTask before entering the main loop, big enough to allow transmissions starting before receptions, then everything works very fine, on the contrary, since seems the scheduler starts RxTask before TxTask, I meet with what I have previously described. Here down below some code:


static
HAL_StatusTypeDef UART_BLUETOOTH_WriteData_IT(uint8_t *pBuffer, uint16_t Size)

{

HAL_StatusTypeDef status = HAL_OK;


xTaskToNotifyTx = xTaskGetCurrentTaskHandle(); 
/* This is a freertos notification facility used with the tx callback */


status = HAL_UART_Transmit_IT(&UART_BLUETOOTH_Handle, pBuffer, Size);


if
(ulTaskNotifyTake(pdTRUE, IO_TX_TIMEOUT/portTICK_PERIOD_MS) == 1)

{

if
(status != HAL_OK)

{

UART_BLUETOOTH_Error();

}


return
status;

}


else
return
HAL_TIMEOUT;

}


static
HAL_StatusTypeDef UART_BLUETOOTH_ReadData_IT(uint8_t *pChar)

{

xQueueReceive(bluetoothRxQueueH, pChar, portMAX_DELAY);


return
HAL_OK;

}

static
void
bluetoothRxTask(
void
const
*pvParameters)

{

uint8_t ch = 0;


vTaskDelay(30000/portTICK_PERIOD_MS); 
/* This is the ''big enough'' delay */


while
(1)

{

xTaskToNotifyRx = xTaskGetCurrentTaskHandle(); 
/* This is a freertos notification facility used with the rx callback */


HAL_UART_Receive_IT(&UART_BLUETOOTH_Handle, &ch, 1);


ulTaskNotifyTake(pdTRUE, portMAX_DELAY);


xQueueSendToBack(bluetoothRxQueueH, &ch, portMAX_DELAY);

}

}


void
bluetoothReceiveCallback(UART_HandleTypeDef *huart)

{

BaseType_t xHigherPriorityTaskWoken = pdFALSE;


vTaskNotifyGiveFromISR(xTaskToNotifyRx, &xHigherPriorityTaskWoken);


xTaskToNotifyRx = NULL;


portYIELD_FROM_ISR(xHigherPriorityTaskWoken);

}


void
bluetoothTransmitCallback(UART_HandleTypeDef *huart)

{

BaseType_t xHigherPriorityTaskWoken = pdFALSE;


vTaskNotifyGiveFromISR(xTaskToNotifyTx, &xHigherPriorityTaskWoken);


xTaskToNotifyTx = NULL;


portYIELD_FROM_ISR(xHigherPriorityTaskWoken);

}

Can anybody provide me some insight or, maybe, confirm a bug in the HALs? Regards.
1 REPLY 1
Walid FTITI_O
Senior II
Posted on August 22, 2016 at 13:08

Hi Thy,

It seems you have an overrun error due to pending interrupt.

In order to clear the pending interrupts we provide a specific macros in stm32f4xx_hal_uart.h file that can be used directly by the application (when needed).

Please refer to the Exported macro section in stm32f4xx_hal_uart.h file. The specific macro to clear the overrun pending interrupt is

__HAL_UART_CLEAR_OREFLAG()

Thus you can perform this to avoid overrun issue:

__HAL_UART_CLEAR_OREFLAG(…)
HAL_UART_Receive_IT(…)

-Hannibal-