Question
Receptions issues in interrupt driven IO with USART2 when HAL_UART_Receive_IT() is called before HAL_UART_Transmit_IT()
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.