How to suspend the task execution , waiting for a response from another task

b3nway wrote on Thursday, November 15, 2018:

Hi all,
I’m a beginner to Freertos, and I want to write a function API_get_uart_data() designed as part of a library.
The basic idea is to introduce an abtraction layer architecture in my firmware project.
Summarizing :
API_get_uart_data() returns NULL if no data is present on UART port
If a data is present in the queue, **API_get_uart_data() ** returns a pointer to data.

I have already implemented the task HAL_UART_task() which stores in a DATA queue the incoming messages from serial port.

This is a simple usecase:

my_application_task()
{
while (1)
{
if (API_get_uart_data() != NULL )
{
/*do something with the data … */
}
}
}

Now my question:

my_application_task() should be in [SUSPENDED] state until API_get_uart_data() returns a valid result

What could be the best way to implement this mechanism?

In other words, this is my current idea of a possible implementation:

UART_message* API_get_UART_data(void)
{
UART_message* temp_message = NULL;
current_task _handler = xTaskGetCurrentTaskHandle();
/* send message to HAL_UART queue ** with ( tempmessage , currenttask _handler )*/
** vTaskSuspend( current_task _handler);

//
/
HAL_UART_task() will ceck for a message in the DATA queue , changing temp_message if necessary.
/
now HAL_UART_task() resumes using vTaskResume( current_task _handler); /
/
*/

return tempmessage;

}

any advice and suggestions will be greatly appreciated.
Thanks.
Giorgio.

richarddamon wrote on Thursday, November 15, 2018:

You have defined your API badly for this task, as your API doesn’t block, so it must be polled, forcing the application to work around this limitation.

Redefine your API_get_uart_data to have a parameter for how long to wait for data, and if the timeout expires, return the null, and if not return the pointer to the data. Then the consumer can make the blocking call and wait for the data. This timeout value can then be passed to the queue fetch operation that the UART task has put the data in.

Personallly, I tend to have the UART ISR do most of the packing work of assembly the low level message and putting it onto a FreeRTOS queue, and then the application level UART task takes that data, with no intermediate ‘uart driver’ task in the middle. The receive side API is basically a simple call wrapper for that queue receive operation.

b3nway wrote on Thursday, November 15, 2018:

Hi Richard, thank you for the reply.
I agree with you about my not clever API definition, but at this moment I’m focusing on the possibilities provided by FreeRTOS in order to Suspend/Resume a desired task.
Maybe a dedicated semaphore could be considered as a valid alternative.
In any case, trying to explain better my expectations:

when API_get_uart_data() is called by my_application_task()

  1. A query is sent to AL_UART_task() , providing a pointer for the response
  2. my_application_task() is [SUSPENDED] by API_get_uart_data()
  3. when AL_UART_task() intercepts the query, it updates the provided response pointer and resumes my_application_task()
  4. updated response is returned by API_get_uart_data()

Is this a common architecture design in FreeRTOS?
What could be considered the most reasonable options in order to implement my idea?

Thanks.

Best Regards.
Giorgio.

richard_damon wrote on Thursday, November 15, 2018:

I would not use suspend/resume here as there is a fundamental data race.

I would have API_get_uart_data() block on something, either a semaphore, queue or direct to task notification for the answer to be ready

b3nway wrote on Friday, November 23, 2018:

Hi Richard, thank you for your suggestion.
I changed my strategy, implementing *API_set_callback_uart_data( void ) instead of API_get_uart_data().
Briefly:
**API_set_callback_uart_data (*function_ptr) ** starts a dedicated task , which is triggered by UART_DATA and calls function_ptr() .

This approach seems more efficient to me.
Regards.
Giorgio.