Often, the toolchain installation phase can be the most frustrating part of a project. Now that you’re past it, you’re free to begin exploring the real depth of Zephyr and consider how you could make use of an RTOS in practice. Below is a quick overview of some basic concepts to understand, and some links and resources you can follow to explore more on your own.
Basic RTOS vocabulary
Threads:The core appeal of an RTOS is that it can run many different objectives at once, called Tasks, using a priority management system called a Scheduler. Tasks can be something like blinking an LED, sending a message over a serial terminal, or handling a motor driver - on an RTOS, the scheduler can juggle many different tasks at once, running each one until another one takes priority or a certain amount of time is exceeded. This makes it simple to handle large amounts of competing tasks in an organized and time-efficient way.
Determinism:RTOS systems are desired for their ability to be deterministic, defined as the ability to always complete specific objectives in a known amount of time. User-facing operating systems like Windows, OSX and Linux are not deterministic, allotting time to tasks like memory management or storage at any time, meaning they often experience delays or lags in operation. In many industrial, robotics and sensor applications, delays like these could lead to equipment damage, or even put lives in danger! An RTOS guarantees that tasks will be completed on time, making it an essential tool for these high performance fields.
Scheduling (pre-emptive and time-slice):Not every scheduler works the same way. A pre-emptive scheduler handles tasks based on priority - a low priority task like blinking a status LED might happen continuously, until a high-priority message send task or motor control task takes over for a while. High priority tasks can then cede control back to the low priority ones by using a
sleep()function. Another model is a time-slice scheduler, which gives each task a certain allotment of time to run per second. Time-slice schedulers are harder to make deterministic (see above) and thus are much less common than pre-emptive schedulers.
Semaphores and Mutexes:Often, different threads will need to use the same resource, such as a single I2C bus. But if one attempts to access it while the other is already using it, you could get strange behavior. A semaphore is a variable that is accessible to both threads, which can convey information about a shared resource. Often, a semaphore is simply a “locked/unlocked” binary variable that states whether a resource is in use - this kind of semaphore is called a mutex.
Message Queues:In other cases, longer and more detailed information needs to be distributed between threads. Most RTOS implementations include a Message Queue system, where threads can post messages to a shared list viewable by other threads. An example could be a system where many different tasks gather sensor data, but they all send it to a single processing task, using a data-carrier Message Queue.
- zephyrproject/zephyr/samples/synchronization: a great starting point for using threads. Two different threads trade the ability to print “hello world”, mediated by Semaphores.
- zephyrproject/zephyr/samples/philosophers: a more complex RTOS example, this project follows the classic RTOS “Dining Philosophers” problem, which involves competing threads and many essential concepts.
You can find out more about the classic examples here: https://docs.zephyrproject.org/latest/samples/classic.html
- Wikipedia has an excellent page on RTOS concepts, even for new programmers.
- For more advanced application development, including debugging, custom toolchains, and more, the Zephyr documentation has an exhaustive list of instructions. The docs are always a good place to start if you get stuck.
- Engaging with the Zephyr community: