New user looking for tips

dcrocker wrote on Tuesday, January 02, 2018:

Hi all, I am about to start converting a project to use FreeRTOS. So I am looking for tips. Here is some background:

  • I have previous experience of RTOS (I used to be a developer of one), but no experience of FreeRTOS yet
  • The project is a successful 3D printer control firmware (RepRapFirmware) and the target for the FreeRTOS version will be ARM Cortex M4 and higher ATSAM processors
  • The project is somewhat object-oriented and mostly written in C++, but avoids dynamic memory allocation except during initialisation and configuration
  • The development tools are Eclipse and gcc
  • RAM is already quite tight, but we can afford around 10K (perhaps more) for FreeRTOS and the tasks and stacks, and most tasks shouldn’t need large stacks if we can run them in user mode so that interrupts are handled on a separate stack
  • For several months I have been ensuring that any new developments should be suitable to fit into a task-based model
  • It uses FatFS for SD card access, and some versions use LWIP to provide a TCP/IP stack
  • I was pleased to see that FreeRTOS complies with the MISRA-C coding standard, because I am familiar with it (I am a member of the MISRA-C++ Working Group, and a former member of the MISRA-C Working Group).

My questions:

  1. To get started, I propose to create a single task which executes the existing main loop code. The Idle task will never get a look-in. After this is working, I will split some of the functions currently executed in the main loop into other tasks. Does this sound a reasonable approach?
  2. Many of the functions executed by code that will eventialy be split into different tasks access the same data, mostly read-only, by calling accessor methods of the classes that hold that data. It may not be practical for me to use the MPU to partition the memory between tasks. At the same time, it would be nice if the tasks’ own stacks and other working memory could be protected from each other. Any suggestions on the best approach?
  3. Is there already a C++ wrapper for the more complex FreeRTOS data structures, to simplify the interface to message queues etc. from C++? It would need to be one that does not use dynamic memory allocation.
  4. I see that instead of FatFS and LWIP I could use FreeRTOS+FAT and FreeRTOS+TCP. Should I use them, or stick with FatFS and Lwip? I think both include some support for FreeRTOS already.
  5. Some of the existing functions performed by the main loop don’t really merit additional tasks, because they are not time-critical and the existing round-robin approach works well. Nevertheless, converting them to tasks or coroutines would avoid the need to use state machines in some cases. Should I use coroutines for them, or should I avoid coroutines because they are end-of-life as far as FreeRTOS development is concerned?
  6. Anything else I should be aware of before I start?

Thanks in advance - David

dcrocker wrote on Tuesday, January 02, 2018:

Two more questions:

  1. FreeRTOS needs to take over the systick vector, but my current code uses it to do various short operations at regular intervals. Is there an official way of hooking the systick interrupt, or should I just include a call to my own function near the start of xPortSysTickHandler ? Or can my application keep control of systick, and call xPortSysTickhandler ?
  2. What is the reason for making the systick interrupt have the lowest priority; and can I change it? The existing code has quite a lengthy ISR for generating step pulses, so I rely on the systick being able to interrupt it.

rtel wrote on Tuesday, January 02, 2018:

Hi all, I am about to start converting a project to use FreeRTOS.So I am
looking for tips. Here is some background:

Although it sounds like you are already experienced with an RTOS, for
familiarity it might still be beneficial to read the free book download
(although it is predominantly for FreeRTOS V8.x whereas now we are on
FreeRTOS V9.x, the FreeRTOS source code download contains links to
what’s new in V9 and what’s new in V10).

  • Memory is already quite tight, but we can afford around 10K (perhaps
    more) for FreeRTOS and the tasks and stacks, and most tasks
    shouldn’t need large stacks if we can run them in user mode so that
    interrupts are handled on a separate stack

On that part interrupts will already use their own stack - you don’t
need to do anything to make that happen.

My questions:

  1. To get started, I propose to create a single task which executes the
    existing main loop code. The Idle task will never get a look-in.
    After this is working, I will split some of the functions currently
    executed in the main loop into other tasks. Does this sound a
    reasonable approach?

Sounds like a good starting point - but not that, if a task deletes
itself (as opposed to getting deleted by another task) then the Idle
task must be given some execution time as it cleans up the stack and TCB
of the now deleted tasks.

  1. Many of the functions executed by code that will eventialy be split
    into different tasks access the same data, mostly read-only, by
    calling accessor methods of the classes that hold that data. I it
    may not be practical for me to use the MPU to partition the memory
    between tasks. At the same time, it would be nice if the tasks’ own
    stacks and other working memory could be protected from each other.
    Any suggestions on the best approach?

For absolute protection you would have to use the MPU, but it can be a
pain on a Cortex-M4 due to the size and alignment requirements of the
MPU regions. Even without the MPU you do have some stack overflow
protection but it will only trigger after an overflow has occurred so it
is considered a fatal error - with the MPU version it will trigger
before the overflow occurs.

  1. Is there already a C++ wrapper for the more complex FreeRTOS data
    structures, to simplify the interface to message queues etc. from
    C++? It would need to be one that does not use dynamic memory
    allocation.

Yes - but these are third party wrappers rather than something that is
directly supported by us. Have a look in the FreeRTOS interactive side
( http://interactive.freertos.org ).

  1. I see that instead of FatFS and LWIP I could use FreeRTOS+FAT and
    FreeRTOS+TCP. Should I use them, or stick with FatFS and Lwip? I
    think both include some support for FreeRTOS already.

FatFS has some crude thread safety mechanisms whereby each API function
is wrapped by a semaphore take/give if you configure it to do so. Lots
of people have issues using lwIP from a mult-threaded environment - it
will work fine but you have to get the configuration right and follow
its threading rules (don’t use the same socket from multiple threads,
etc.). Our own stacks are natively thread safe, but if you already have
something working with FatFS and lwIP it might be more effort than
required to switch.

  1. Some of the existing functions performed by the main loop don’t
    really merit additional tasks, because they are not time-critical
    and the existing round-robin approach works well. Nevertheless,
    converting them to tasks or coroutines would avoid the need to use
    state machines in some cases. Should I use coroutines for them, or
    should I avoid coroutines because they are end-of-life as far as
    FreeRTOS development is concerned?

Best to avoid coroutines as they have not been actively maintained for
some time.

rtel wrote on Tuesday, January 02, 2018:

  1. FreeRTOS needs to take over the systick vector, but my current code
    uses it to do various short operations at regular intervals. Is
    there an official way of hooking the systick interrupt, or should I
    just include a call to my own function near the start of
    xPortSysTickHandler ?

Yes, see FreeRTOS - RTOS hook (callback) functions for task stack overflows, tick interrupts, idle task, daemon task startup, and malloc failure (pvPortMalloc() returning NULL)

  1. What is the reason for making the systick interrupt have the lowest
    priority; and can I change it? The existing code has quite a lengthy
    ISR for generating step pulses, so I rely on the systick being able
    to interrupt it.

Yes the systick can (I think?) be made higher priority, but it is not
something we would advise non-expert users to do (your experience would
seem to make you an expert user, albeit not necessarily with FreeRTOS
yet) as it can lead to inefficiencies as the tick count changes within
code that is using it. Make sure to leave the PendSV at the lowest
priority though.

heinbali01 wrote on Tuesday, January 02, 2018:

Richard was just a bit quicker to give you answers, so there will be some overlap here below:

The Idle task will never get a look-in

What do you mean with this phrase? Won’t you ever call a blocking function?

… I will split some of the functions currently executed in the
main loop into other tasks. Does this sound a reasonable approach?

This sounds very vague to me, I suppose you know what you are doing.

At the same time, it would be nice if the tasks’ own stacks and
other working memory could be protected from each other. Any
suggestions on the best approach?

A memory stack is always private to a task, by definition. So are local data.
Static data in a function or module, and global data are accessible by all tasks. You will have to decide who can have access to these data.
When the access is read-only, you probably want to have a coherent snapshot of it, and copy a struct while the scheduler is temporarily disabled.
When reading variables that have the size of a register ( 32-bits ), you probably don’t need any protection, because the access is “atomic”.

I like the C++ approach, in which objects have private and public ( and protected ) methods and data.

Is there already a C++ wrapper for the more complex FreeRTOS data structures

Have a look at Richard Damon’s work here: GitHub - richard-damon/FreeRTOScpp: FreeRTOS C++ Wrappers

see that instead of FatFS and LWIP I could use FreeRTOS+FAT and FreeRTOS+TCP.
Should I use them, or stick with FatFS and Lwip? I think both include some
support for FreeRTOS already.

If you already have a project running with FatFS and lwIP, and if you’re satisfied with them, I’d keep on using them. But if you plan to do new projects, I’d have a look at the FreeRTOS libraries.
The +TCP and +FAT libraries have advantages, mostly because they are tightly coupled to the OS. Other public libraries will offer a “FreeRTOS port”.

FreeRTOS needs to take over the systick vector, but my current code uses
it to do various short operations at regular intervals. Is there an
official way of hooking the systick interrupt, or should I just include
a call to my own function near the start of xPortSysTickHandler ? Or can
my application keep control of systick, and call xPortSysTickhandler ?

Please google for “FreeRTOS configUSE_TICK_HOOK”. Your function will be called during every clock-tick. Be careful because your handler will be called from within an ISR. This means that you can only use FreeRTOS API’s that end with ..FromISR().

What is the reason for making the systick interrupt have the lowest
priority; and can I change it? The existing code has quite a lengthy
ISR for generating step pulses, so I rely on the systick being able
to interrupt it.

It sounds like you better use a TC interrupt that has a higher priority.
But please read the texts about ARM M4 and the interrupt priorities.

dcrocker wrote on Tuesday, January 02, 2018:

Thanks! From those replies and a little research I have done in the meantime, I think I know what to do. I’ll use the mechanism provided to hook the tick interrupt. I’ll stick with FatFS and Lwip at least for now, but I’ll protect them using mutexes or queues. I’ll improve the tick interrupt priority but I’ll make sure the the PendSV priority is the lowest one. I’m aware of the need to ensure that a task reads a coherent set of shared variables in a preemptive environment. I’ll take a look at the C++ wrappers that both of you pointed to me.