BY JEAN J. LABROSSE
Founder of Micrium and Software Architect at Silicon Labs
www.silabs.com
When you design embedded systems, one of the questions that you need to answer is whether your application requires a real-time operating system (RTOS). Many embedded designers have shied away from using an RTOS kernel because they fear that kernels disable interrupts when handling critical sections, and that can prevent deadlines from being met in time-sensitive applications.
What’s an RTOS?
An RTOS is a piece of software that manages the time of a central processing unit (CPU), microprocessing unit (MPU), or even a digital signal processor (DSP) as efficiently as possible. Most RTOS kernels are written in C and require a small portion of code written in assembly language to adapt the kernel to different CPU architectures.
A kernel provides many useful services to a programmer, including multitasking, interrupt management, inter-task communication and signaling, resource management, time management, and memory partition management. The application is basically split into multiple tasks, each one responsible for a portion of the application. A task is a simple program that thinks that it has the CPU all to itself. Each task is assigned a priority based on the importance of the task.
Most kernels used for embedded systems are “preemptive,” meaning that the kernel always executes the most important task that is ready to run. Preemptive kernels are also event-driven, which means that tasks are designed to wait for events to occur in order to execute. When the event occurs, the task executes and performs its function. If the event that the task is waiting for doesn’t occur, the kernel runs other tasks. Waiting for a task consumes zero CPU time; kernels allow you to avoid using polling loops, which is a bad use of the CPU’s time.
Many embedded programmers shy away from using an RTOS kernel because they fear that kernels add too much complexity to their application. It turns out that you only need a handful of services to get your project off the ground with a kernel. As for overhead, it’s true that an RTOS may require between 2% and 5% of the CPU’s resources to perform its duties.
More important, however, is the fact that RTOSes need to disable interrupts when entering critical sections. Depending on the CPU itself, the clock frequency, and whether memory accesses require wait states, an RTOS can disable interrupts for tens of microseconds. This limitation is generally not an issue for most embedded applications but can be problematic when every microsecond counts.
Bluetooth Low Energy (BLE)
The IoT devices are increasingly equipped with BLE links because, when combined with smartphones or similar handheld devices, BLE makes commissioning and configuration of these IoT devices simple and convenient.
BLE can have multiple operating modes, multiple connections, multiple advertisers, and so on, and some of them can even overlap.
Scanning mode: Device scans advertisement packets sent by other devices. Scanning is comprised of an interval between scans and a window of time during which a device is listening. The scanner changes the channel frequency at each interval. A response is required in 150 µs after receiving a request. This is called the interframe space (IFS).
Advertising mode: A BLE device can also perform advertising on its own, which can happen between 20 ms to three hours.
Connection mode: The Master sends a packet at each connection interval, and the BLE Slave device responds back to a Master after 150 µs, the IFS. If the Master has something else to send to the Slave, it sends a packet to the Slave after 150 μs. Devices send packets to each other until neither end has data to send.
One-hundred-and-fifty microseconds might seem like a long time for a 32-bit CPU, but there is much to do when processing an incoming request. Packets have flow control information indicating what sequence number to request from the other end; there may be address whitelist filtering that needs to be processed.
In practice, 120 µs to 130 µs of CPU time is consumed to perform these operations. Nothing bad typically happens if a packet can’t be processed within 150 µs; data throughput may drop slightly or opening a connection might be delayed. From a customer’s point of view, the behavior is the same as radio interference. However, continuously missing this deadline is not an option as it would make the end product unusable.
RTOSes in BLE applications
If an RTOS can potentially disable interrupts for tens of microseconds, then why would you consider using one in a BLE-based application? Well, the answer is that these time-critical events can be easily handled outside of the RTOS. Specifically, it’s possible to allocate specific time-sensitive interrupt service routines (ISRs) outside the reach of the RTOS. These are called non-kernel aware (nKA) ISRs, and as the name implies, they simply bypass the RTOS kernel. The nKA ISRs have a higher priority than kernel aware (KA) ISRs.
Fig. 1: ISR and task priorities on a Cortex-M3 CPU.
Fig. 1 shows the priority levels of ISRs and tasks for a typical Cortex-M3 CPU. If the RTOS needs to protect a critical section, it will set the Cortex-M3 CPU’s BASEPRI register to 0x40 and thus disable KA ISRs with priorities 0x40 and below. Because 0x00 and 0x20 are higher priorities, they will be allowed to interrupt the CPU, even if the RTOS is in the middle of a critical section.
Therefore, time-sensitive BLE ISRs can simply be assigned either priority 0x00 or 0x20, and when they occur, they will be processed immediately, irrespective of the state of lower-priority ISRs or tasks.
It’s possible that a task will provide setup information — operating modes, configuration, etc. — for the nKA ISR. An nKA ISR may also require further non-time-critical processing to be performed at the task level. So if an nKA ISR is not allowed to make any RTOS API calls, how does an nKA ISR communicate with a task? It’s fairly easy to set up shared memory, as shown in Fig. 2 .
Fig. 2: Communication between an nKA ISR and a task.
The nKA ISR deposits information into memory with whom it shares a task.
Because the nKA ISR cannot make any RTOS API calls, it needs to trigger a KA interrupt, which, in turn, will be allowed to make kernel calls. The ARM Cortex-M CPU’s nested vectored interrupt controller (NVIC) allows system designers to do just that, but the designer would need to identify an I/O device that is not used by the application and steal its interrupt vector to use for this purpose.
The KA ISR can thus signal the task to let it know that data is available in the shared RAM.
When all ISRs have completed, and the RTOS has decided that the signaled task is now the highest priority, the task can read the data sent to it by the nKA ISR.
The task can deposit information — as needed — for the nKA ISR in a shared region that is only read by the nKA ISR. Data is written in the shared RAM but can only be read when the “Data Available” flag is set. The ARM Cortex-M3 CPUs — and processors above — have special instructions that ensure that setting or clearing the “Data Available” flag can be done automatically to prevent race conditions and without having to disable global interrupts.
The nKA ISR would poll the data provided by the task. That’s typically not a problem because this would happen when the nKA ISR occurs anyway.
Summary
An RTOS and time-sensitive applications like BLE can easily coexist by making time-sensitive ISRs that are non-kernel aware. Using a scheme similar to this ensures that time-critical code is not affected by the presence of an RTOS. Meanwhile, an RTOS can make the most efficient use of the CPU for code that is not time-sensitive.
Learn more about Silicon Labs