1
votes

I am working on STM32L152VB-A controller. I am using FreeRTOS.
I used CubeMX to generate the code and I configured USART1 with global interrupts.
The non interrupt RX and TX (HAL_UART_Receive and HAL_UART_Transmit) is working.
But I am trying to make it work with interrupts.

Only after I called HAL_UART_Receive_IT, I am getting interrupt.
Since I couldn't know the receive data size, I am planning to receive characters one by one.

Since I use RTOS, I am confused about where to write HAL_UART_Receive_IT, as the message can come at any time. can anybody guide me??

PS: I tried calling the HAL_UART_Receive_IT inside ISR, but it is also not working.

2

2 Answers

3
votes

I think you're confusing HAL_UART_Receive_IT with a function which actually receives anything. This is not the case. This function merely enables the UART peripheral and its receive interrupt.

If you want to stick with the HAL library you need to pass a struct of type UART_HandleTypeDef as parameter to HAL_UART_Receive_IT which contains

  • a uint8_t* pointer to a receive buffer
  • a transfer counter for the number of elements you'd like to receive

As far as I know there is no way for receiving elements indefinitely with this framework because once the transfer counter reaches zero the receive interrupt gets disabled automatically. So if you need this you're probably better of writing the ISR yourself by overwriting the weak function defined by ST (most likely called "UARTx_IRQHandler").

To finally integrate the receive interrupt in FreeRTOS you've got two options:

  1. Receive data inside the ISR into a raw (uint8_t*) buffer like HAL does and use a critical section which temporarily disables the receive interrupt when accessing it.
  2. Receive data inside the ISR into a FreeRTOS queue using the interrupt safe API. The official FreeRTOS book chapter 6 explains this very well.
2
votes

I created the following task (consider a high priority):

void UARTReceiveTask(void const * argument)
{
  /* USER CODE BEGIN UARTReceiveTask */
  /* Infinite loop */
  for(;;)
  {
    osSemaphoreWait(BinarySemaphoreUARTHandle, osWaitForever);
    HAL_UART_Receive_IT(&huart3, message_received, 2);
  }
  /* USER CODE END UARTReceiveTask */
}

Then, if you are using HAL, you must know that HAL_UART_RxCpltCallback() is executed on the UART ISR, so I wrote:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
    if (huart->Instance == USART3){
        osSemaphoreRelease(BinarySemaphoreUARTHandle);
    }
}

I only followed the tips on the "Mastering the FreeRTOS" document (Chapter 6) to deferr interrupts to tasks.

I haven´t dug deep into it, but I know this info is important if you are working with FreeRTOS and Arm Cortex systems.

Hope I helped!