This book comprises 17 chapters in all, spread across four sections. It isn't necessary to read the book straight through if you're already comfortable with some of the material. For example, if you're already comfortable with basic RTOS concepts and real-time systems, feel free to skip to Chapter 4, Selecting the Right MCU. The following are brief descriptions of the chapters that this book is made up of:
Chapter 1, Introducing Real-Time Systems, is a simple introduction to what an RTOS is and when and why to use one. Hardware and software alternatives to an MCU-based RTOS are also discussed.
Chapter 2, Understanding RTOS Tasks, provides a comparison of super loops with RTOS tasks, including various ways parallel operations can be achieved using both.
Chapter 3, Task Signaling and Communication Mechanisms, is a short introduction to more RTOS concepts with lots of diagrams. This chapter, along with Chapter 2, Understanding RTOS Tasks, should be useful as a reference and a quick refresher on the concepts and terminology, should you ever need it.
Chapter 4, Selecting the Right MCU, helps you understand what considerations should be made when selecting an MCU. After gaining an appreciation of the inter-dependency between hardware and firmware, we look at why it is so important that hardware and firmware engineers both have a hand in system design.
Chapter 5, Selecting an IDE, introduces and discusses various types of Integrated Development Environments (IDEs), including reasons why you might decide to choose one over another (or none at all). Instructions on setting up STM32CubeIDE and importing the example code are covered here.
Chapter 6, Debugging Tools for Real-Time Systems, covers tools for debugging embedded systems, including the debugging tool we'll be using throughout the remainder of the book – SEGGER Ozone and SEGGER SystemView visualization software. Instructions on how to use Ozone and SystemView are covered here. Hardware-based test equipment and some other useful tools for your embedded system development workflow are also included.
Chapter 7, The FreeRTOS Scheduler, teaches you the various ways to create tasks using FreeRTOS and how to troubleshoot startup failures. You will gain an understanding of task states and the different ways performance can be optimized.
Chapter 8, Protecting Data and Synchronizing Tasks, covers task synchronization using semaphores and data protection using mutexes, as well as how to avoid race conditions and priority inversion. Software timers are also covered.
Chapter 9, Intertask Communication, examines different ways of passing information between tasks, with different examples of using queues for passing information by value and reference, discussing the advantages and considerations of both approaches. We'll also learn about a lightweight intertask communication mechanism, the direct task notification, including a comparison of task notifications and queues.
Chapter 10, Drivers and ISRs, dives deep into several detailed examples of how to implement efficient drivers with various FreeRTOS primitives including semaphores, queues, and stream buffers. We'll also look at how FreeRTOS can be used in conjunction with MCU hardware such as DMA to provide extremely CPU-efficient driver implementations. This chapter works both directly with the MCUs peripheral registers and also with STM32 HAL code.
Chapter 11, Sharing Hardware Peripherals across Tasks, teaches you how to create drivers that can be safely used across multiple tasks while sharing hardware resources. We'll adapt the STM-supplied USB CDC implementation to be more user-friendly and efficient, wrapping it with a mutex and queues so it is safe to use across multiple tasks.
Chapter 12, Tips on Creating a Well-Abstracted Architecture, covers code reusability, flexibility, and hardware portability, with an eye on creating abstractions that make your job easier. Some suggestions for source code organization to help facilitate reuse are also covered.
Chapter 13, Creating Loose Coupling with Queues, is a culmination of all of the concepts covered in the book. It includes a fully fleshed-out example of a loosely coupled architecture used to create a properly abstracted, end-to-end application. We'll use the USB CDC virtual comm port developed earlier, as well as an LED abstraction, to create a loosely coupled, fully reusable LED sequencer using a command queue. This embedded application can be controlled from a PC with a cross-platform UI written in Python.
Chapter 14, Choosing an RTOS API, continues our high-level architecture discussion with a look at three different APIs available to use for accessing FreeRTOS functionality: the native FreeRTOS API, ARM's CMSIS-RTOS, and POSIX. Discussion topics include a comparison of the available features and why you might choose one of the others for different projects.
Chapter 15, FreeRTOS Memory Management, takes a close look at a few different options for memory management in FreeRTOS. We'll look at static versus dynamic allocation, as well as using a Memory Protection Unit (MPU).
Chapter 16, Multi-Processor and Multi-Core Systems, teaches you how multi-processor and multi-core systems are used for a variety of reasons – learn what they are and how to get the different parts of a system to communicate.
Chapter 17, Troubleshooting Tips and Next Steps, covers tips for troubleshooting systems, including tips on how to avoid stack overflows and how to troubleshoot a hung system. Some recommendations for the next steps are also covered.