Setting timeout in usart_os_read function

jhenges wrote on Monday, July 15, 2019:

The FreeRTOS USART support does not support the concept of a timeout value for the serial transaction. The current technique is to assume that the transfer will always block till it receives a character. In an RTOS environment, this may not (probably not) be the desired functionality.

The function usart_os_read containts the notion of a timeoout value, but it is always set to ~0 which means wait forever.

All that is needed is to set this a value to a of number of ticks to wait and you would have the desired operation.

There would be a couple of ways to do this.

One is to include a timeout parameter in the call to usart_os_read. This would be the most straight forward way to do this. However, there are probably lots of code pieces that would break.

Another is to create another version of the function with the new parameter included. However, having two function names which almost do the same thing is always confusing…

A third way would be to leave the function call alone and include a way to update the timeout parameter transparently.

To perform the third method, we would set up a table of timeout values that would represent the current timeout for a given io_descr value. We would do a lookup in table to see if there was a current timeout value for this io_descr value. If so, the value of timeout (in the function usart_os_read) would be set to this value and the timeout function would work normally.

If there was no entry in the table, the function would return the original value of ~0 which would imply infinite wait as it currently does.

The new code would consist of 4 functions:

  1. init_device_timeout_table
    This would initialize the search table so that no devices had a timeout.
  2. find_device_index
    This would find the desired io_descr value in a table and return the
    timeout value or ~0 if there was no entry in the table.
  3. set_device_timeout
    This would set the timeout to a desired value for a given io_descr.
  4. get_deevice_timeout
    This would find the value of the timeout for a given io_descr or ~0
    if there was no entry in the table.

The one line in the usart_os_read function that would change would be the iniitialization of the variable timeout. Currently this initialization is:
uint32_t timeout = ~0;
This would change to:
uint2_t = get_device_timeout(io_descr);

For device calls where timeout is unimportant, the existing code would work the same as it always has.

Where it is important to include an appropriate timeout value, an additional function call before the call to io_read would look like this:
set_device_timeout(&USART_1,timeout_value);

That call would set and keep the timeout value for that io_descr value (USART_1 in this case) until it was changed.

Any other io_read calls to a different io_descr value (USART_2 or USART_5 for instance) would behave as they do today.

These functions could included in the hal_usart_os.c file or put in a separate file. If they are put in the hal_usart_os.c file, there would probably also need to be forward declarations in hal_usart.h.

I have included three files:
hal_usart_os_timeout_fix.c which is an update to hal_usart_os.c
(note that this also includes the modifications from a previous posting on losing characters)

os_timeout.h which is an include file for the timeout functions

os_timeout.h which is the implementation of the timeout functions.

rtel wrote on Monday, July 15, 2019:

See here: https://sourceforge.net/p/freertos/discussion/382005/thread/2e4555b21d/ which notes that these are not actually FreeRTOS functions but functinos provided by the vendor.