How can I invoke UART_Receive_IT() automatically when I receive a data?

usual-developer wrote on Thursday, April 18, 2019:

I am new to STM32 and freertos. I need to write a program to send and receive data from a module via UART port. I have to send(Transmit) a data to that module(for eg. M66). Then I would return to do some other tasks. once the M66 send a response to that, my seial-port-receive-function(HAL_UART_Receive_IT) has to be invoked and receive that response. How can I achieve this?

I have to complete this ASAP…Thanks in Advance

rtel wrote on Thursday, April 18, 2019:

You have a few options.

The below is not definitive because it completely depends on your
application. If you have a simple application where power consumption
doesn’t matter and its not doing anything most of the time, then you can
have a task that simply polls the UART to see if more data is available

  • as that is the simplest thing to do. Alternatively you could have a
    task that blocks for a short time in between each poll if it finds there
    is no data available, that will use less CPU time and allow lower
    priority tasks to run…then you can build up in complexity if you
    want a highly efficient system because you need to save as much power as
    possible, or the system needs as much spare CPU time as possible to do
    other compute then you would use a DMA to receive the data without using
    any CPU and then the DMA interrupts to unblock a task to process the
    received data only when it had been received. There are many ways for
    an interrupt to unblock a task, the most efficient of which is to use a
    direct to task notification.
    https://www.freertos.org/RTOS_Task_Notification_As_Counting_Semaphore.html

usual-developer wrote on Friday, April 19, 2019:

Thanks Richard…but in my case power consumption plays a major role. And Can you provide any example code for my problem, so that i can get a clear idea…Sorry for bothering…

heinbali01 wrote on Friday, April 19, 2019:

Have you checked the HAL libraries from ST? They have implemented all three methods that Richard mentions: polling, interrupt and DMA.
With the interrupt method, you would still have an interrupt per byte, which is expensive in terms of energy.

usual-developer wrote on Friday, April 19, 2019:

Yes Hein, I am thinking of using Interrupt method to receive the data from module. But my doubt is “will that HAL_UART_Receive_IT function invoke automatically once the data comes from module or do we have to call that function and wait till the data comes”?

heinbali01 wrote on Friday, April 19, 2019:

These questions are quite specific for ST/HAL, not FreeRTOS.
But as I understand it, HAL_UART_Receive_IT() enables the interrupt for reception and it will receive a number of bytes from within an ISR ( 1 byte = 1 interrupt ).
UART_Receive_IT is an example of an RX interrupt. It is called from HAL_UART_IRQHandler().

rtel wrote on Friday, April 19, 2019:

Thanks Richard…but in my case power consumption plays a major role.
And Can you provide any example code for my problem, so that i can get a
clear idea…Sorry for bothering…

The link I provided before contains example code. Did you read it?

richarddamon wrote on Friday, April 19, 2019:

My rememberance of HAL_UART_Receove_IT is that it checks if data has come in and been received by interrupts, and if so returns them. I think there is some callback you can define that will be called in the interrupt context for each character received. It does NOT provide any ‘task’ level call back of a character/message being received or an easy way to have a task block until a character is received.

This is typical of most manufacturer provide HAL Code, it isn’t tied to an OS, so can’t use OS primatives and actions like blocking.

I generally will write my own serial drivers, using the manufactures as a template, or perhaps even using pieces of them, to make my own driver. For a regular uart, I will typically have a FreeRTOS queue to queue characters that have been received, and the task that is reading from the uarts will pop the characters off that queue for processing, so that task will be blocked until a character arrives. Higher speed devices, with clearly defined message boundries might use instead a memory buffer that is filled with the message and a signal that the message is ready to process.

One important thing is how you divide task responsibilities in your program. Generally I create a task for each asyncronous source of information comming in that needs to be waited on. Since it sounds like the M66 can send you a message at any time, that means that there should be a task assigned to listening to it and processing what it is saying. If it only speaks back in answer to a command sent to it, then that might not need a dedicated task, as the task that got the command to send could send the command, and then block for the answer (letting other tasks run). If that task can’t afford to block, then you want a dedicated task to receiving from the M66.

The key is you need to DESIGN the system as a set of asyncrounous tasks running, doing what they need to do, to acheive your goal. Don’t think of it as a single ‘Program’ doing a sequence of steps, but you perhaps start at the program level, and break it down into somewhat independant sequences assigned to tasks.

richarddamon wrote on Friday, April 19, 2019:

My rememberance of HAL_UART_Receove_IT is that it checks if data has come in and been received by interrupts, and if so returns them. I think there is some callback you can define that will be called in the interrupt context for each character received. It does NOT provide any ‘task’ level call back of a character/message being received or an easy way to have a task block until a character is received.

This is typical of most manufacturer provide HAL Code, it isn’t tied to an OS, so can’t use OS primatives and actions like blocking.

I generally will write my own serial drivers, using the manufactures as a template, or perhaps even using pieces of them, to make my own driver. For a regular uart, I will typically have a FreeRTOS queue to queue characters that have been received, and the task that is reading from the uarts will pop the characters off that queue for processing, so that task will be blocked until a character arrives. Higher speed devices, with clearly defined message boundries might use instead a memory buffer that is filled with the message and a signal that the message is ready to process.

One important thing is how you divide task responsibilities in your program. Generally I create a task for each asyncronous source of information comming in that needs to be waited on. Since it sounds like the M66 can send you a message at any time, that means that there should be a task assigned to listening to it and processing what it is saying. If it only speaks back in answer to a command sent to it, then that might not need a dedicated task, as the task that got the command to send could send the command, and then block for the answer (letting other tasks run). If that task can’t afford to block, then you want a dedicated task to receiving from the M66.

The key is you need to DESIGN the system as a set of asyncrounous tasks running, doing what they need to do, to acheive your goal. Don’t think of it as a single ‘Program’ doing a sequence of steps, but you perhaps start at the program level, and break it down into somewhat independant sequences assigned to tasks.