I was reading an article a few weeks ago about thread pools in embedded software. That got me thinking. While I have used thread pools in my career, it has been many years since I last used a thread pool on a project. That lead me to thinking about what are my best practices are for threads in an embedded environment. In this context, embedded environment means a microcontroller running a thread scheduler (e.g. FreeRTOS).
How I utilize threads.
- I create all threads on startup and only terminate the threads on orderly shutdown before resetting the MCU. All of the threads have specific responsibilities that do not change over time.
- For example, many of my embedded projects, I have the following threads:
- Main. A dedicated thread used to create, start-up, and shutdown the application.
- Driver. Time critical drivers.
- UI. User Interface (when there is one).
- Application. The core business logic.
- NVRAM. Reading/writing persistent storage.
- Command Console.
- For example, many of my embedded projects, I have the following threads:
- Preemptive threads with N priority levels. However, the design of the application does not require or rely on any particular set of thread priorities for “correct” behavior, i.e. the application should be able to run, albeit sluggishly, if all threads had the same priority. The two exceptions to this rule are:
- A high priority driver thread, where the driver thread is used to execute “deferred” logic from interrupt service routines (ISRs). This allows the ISRs to be as short as possible, while the high priority driver thread preempts all of the application threads to execute time critical processing.
- A GUI thread with a raised priority (but lower than the driver thread) to provide responsiveness to the user.
- The majority of the threads execute as event loops, where events include things like software timers, change notifications, message passing, event flags, etc.
- A small number of threads with a forever loop that block on reading input streams. For example, a dedicated thread for a UART based command console.
How do you use threads?