Sign Up for the Newsletter
The most up-to-date news and insights into the latest emerging technologies ... delivered right to your inbox!
Author William Lamie takes on the role of myth buster in looking at some common misperceptions about the use of RTOS in connected devices.
April 2, 2016
By William E. Lamie
According to the 2015 UBM Embedded Developer survey, more than 60% of current projects include real-time capabilities, more than a third include a GUI, and more than 70% report using an RTOS or scheduler of some kind. Among the remaining 30% who didn't use an RTOS, the main reason for not using one (79%) was that the application didn't need it. But myths prevail about the reasons for using (or not using) an RTOS. Here are our top 11 myths.
The embedded industry is already seeing strong migration away from 8- and 16-bit microprocessors due to requirements for enhanced device functionality as well as the attractive cost/performance attributes of new 32-bit microprocessors. IoT devices specifically require network connectivity and many will also include a graphical user interface (GUI). As a result, they generally require 32-bit microprocessors to provide the necessary address space and processing power.
Similar evolutions are occurring on the software side. Increased connectivity requirements alone necessitate the execution of communication protocol stacks on the 32-bit embedded microprocessor, which in turn necessitates the use of an RTOS. GUI design and runtime software from third parties typically rely on RTOS services as well.
Many legacy 8- and 16-bit devices employ a polling-loop software architecture to distribute processing time among their various threads.
Although easy to understand and appropriate in very simple devices, this approach suffers when used in more complex devices. The problem is that responsiveness of any thread in the loop is determined by the processing in the rest of the polling loop, making the worst-case responsiveness the worst-case processing through the polling loop. If processing in the polling loop changes dynamically, so does the responsiveness of each thread. As greater complexity is added to the polling loop, the more difficult it becomes to predict and meet real-time requirements, which can impact the reliability of IoT devices.
In contrast, the response time using an RTOS is constant. Moreover, the RTOS invisibly handles allocation of the processor to thread priorities, so the application software needn’t address how much processing time is taken by each thread. Even better, changes in the processing responsibilities of a given thread don’t impact the responsiveness of higher-priority threads.
Although an RTOS does introduce some overhead in API calls and context switching, the amount of overhead is small and constant and is likely less than a complex polling loop (see figure). For example, RTOS context switching on a Cortex-M typically takes less than 120 cycles (this can vary from architecture to architecture and RTOS to RTOS).
In order for a polling loop (or other RTOS alternative) to do better, it would have to be able to predict and guarantee that the worst-case delay in activating a thread would be less than 120 cycles (which is about 50-60 lines of C code). That means that the time taken to check each thread in the loop and execute the code for any active thread would have to be less than 60 instructions.
Even if no other thread had anything to do, just checking each thread would consume cycles, until the thread that requires servicing is checked. This might work for loops with 5-10 threads, but once the loop lengthens, those 60 instructions are inadequate. In a worst-case analysis, all of the intervening threads must be given processing time, making real-time response virtually impossible even for a minimal two-thread loop.
An RTOS context switch often is more efficient than a polling loop. With Express Logic’s ThreadX, the polling loop would need to improve on 120 cycles or less than 60 instructions total—a real challenge when all loops must be checked and executed.
Small device firmware projects (typically less than 32 kB of total memory) can be reasonably managed by one or two firmware developers who both must understand the run-time behavior and requirement of the device in total. That’s because the processor allocation logic is dispersed throughout the application code. However, steadily increasing functionality of the device, such as adding cloud communication protocols, expands the development team and not everyone understands the firmware processing requirements. Communication among the code modules developed by each team member must then be designed and implemented to allow for inter-thread synchronization and information exchange.
In contrast, an RTOS eases development when adding device functionality. With an RTOS, firmware developers can concentrate on their specific piece of the firmware and not have to worry about the processing requirements of the other firmware in the device. What’s more, they have inter-thread communication services (messaging, semaphores, etc.) that are efficient, consistent, and well-defined.
An RTOS invisibly handles the processor allocation logic so that real-time performance of a high-priority thread can easily be guaranteed—whether the firmware is 32 kB or 1 MB in size, and regardless of the number of threads in the application. This alone makes it easier to maintain the application and easier to add new features to a device. Also, most commercial RTOS offerings have an extensive set of pre-integrated middleware that makes it easy to add networking, file systems, USB, and graphical user interfaces.
Applications that use an RTOS access its service functions through an API, which makes the RTOS platform-independent.
That makes switching processors easier, since none of the application's service references have to be changed. The application will run anywhere the RTOS can run. With most popular commercial and open-source RTOSs, that means virtually any 32-bit processor architecture. This gives developers the benefit of application portability with minimal changes to their code.
An RTOS does require both instruction memory (usually flash memory) and RAM memory for its operation. However, a good commercial RTOS requires very little of either—typically on the order of 2 kB of instruction area memory and 1 kB of RAM. Of course, application needs in these areas also must be met, making it even more beneficial if the RTOS uses small amounts of memory for its operation.
While an RTOS requires processing cycles for performing context switches, executing API calls, etc., the processing cycles are directly related to what’s used by the application. For example, if an existing polling loop is executed (as-is) from a single thread in an RTOS, there’s no additional overhead. The polling loop would execute just as before.
RTOS processing overhead only happens when RTOS services are used. Also, without an RTOS, the application is responsible for all required processing, including the cycles used in polling, function calling, and interrupt servicing. Aside from the simplest applications, it’s likely that the RTOS cycles will turn out to be less than the application would consume if it had to do all of the work.
Learning to use an RTOS is proportional to what’s used in the application. For example, placing a legacy polling loop inside a single thread would require virtually no additional learning. But with the pitfalls associated with using a polling-loop architecture, the amount of time studying and re-studying the performance of the entire firmware will quickly dwarf any time spent learning how to use an RTOS, especially for a non-author of the original code. Having said that, most good commercial RTOS companies provide on-site training as well as a substantial amount of documentation. And, of course, a good commercial RTOS is also simple to understand and use!
The old adage “you get what you pay for” applies to RTOS products just like everything else. Free or open-source RTOS products simply don’t have the vested self-interest in being small, efficient, and easy to use. Not having a revenue stream also implies a lack of R&D, product evolution, and most importantly, the ability to fully support customers. An RTOS without dedicated support is like using “1234” as your password for everything—it might work, but it isn’t very smart and it will eventually catch up to you.
The starting point for most commercial RTOS licenses is on the order of $10K for a non-royalty license, with full source code and full support. This represents a tremendous value—only costing a couple of months of a typical embedded firmware developer’s salary. In addition, it’s a one-time license purchase and the license can be used forever. That developer costs you $5K to $10K each and every month.
While it’s hard to precisely state the criteria for an RTOS, when the total memory (ROM and RAM combined) of a device is less than 16 kB, there’s a good chance that using an RTOS is overkill. Such devices typically have a dedicated purpose and most often use an 8- or 16-bit microprocessor. Once device firmware exceeds 32 kB of total memory and/or utilizes a communication protocol (like all IoT devices) or GUI, it will almost certainly need an RTOS.
Even a small 32-kB, dedicated purpose non-IoT device could benefit by using an RTOS, simply to isolate foreground and background processing into two separate threads. This configuration would only cost an additional 3 kB in total memory for the RTOS, while making the device firmware much simpler and much easier to enhance in the future.
With the rapid growth of the IoT and the new devices being developed to exploit it, using an RTOS in the near future seemingly becomes more and more likely.
Article was originally published on Electronic Design.
You May Also Like