
This article continues the review of the Nucleus SE
Services
Nucleus SE provides a set of tools that can be expected from any RTOS.
First, the Nucleus SE contains a fairly simple scheduler, however, thanks to the four options available, it provides flexibility. The scheduler supports Run to Completion, Round Robin, Time Slice, and Priority algorithms.
The Nucleus SE API includes about 50 service calls that provide developers with access to managing tasks, memory sections, signals, groups of event flags, semaphores, mailboxes, queues, pipelines, system time, application timers, and diagnostics.
')
In addition to simple task scheduling, Nucleus SE (optional) supports task suspension. This function can be “clean” (for example, as the result of an explicitly defined service API call suspension), it can be a “sleep” function (when the task is suspended for a certain period of time) or it can be the result of another API call in which the task is blocked (the so-called "conditional" suspension), waiting for access to the kernel resource. Unlike the RTOS Nucleus, the Nucleus SE does not support timeouts when blocking API calls.
The variety of mechanisms presented allows you to choose from the hierarchy of inter-task synchronization and communication tools: from semaphores to signals, event flags, mailboxes and queues / pipelines.
Previous articles in the series:
Article # 7. Nucleus SE: introductionArticle # 6. Other RTOS servicesArticle # 5. Interaction between tasks and synchronizationArticle # 4. Tasks, context switching and interruptsArticle # 3. Tasks and planningArticle # 2. RTOS: Structure and Real Time
Article # 1. RTOS: introduction.
Parameter check
When choosing the
NUSE_API_PARAMETER_CHECKING configuration, the code for verification of parameters is
included in all API functions: checking null pointers, object indexes, etc. Since this is additional code that requires additional memory, it will be reasonable to enable this function during debugging, but turn it off in the release build.
Configuration
Nucleus SE has a flexible structure, which gives us two positive points. On the one hand, the kernel can have a fine-modular configuration that satisfies the tasks of a particular application due to simple adjustment of the available functionality and simple memory management. On the other hand, the Nucleus SE code is easily transferred both between tools and between processors.
Naming conventions
Since the development of Nucleus SE was important clarity and ease of understanding of the code, the naming conventions were carefully thought out. Each character code has a
NUSE_ prefix
. Everything that follows this prefix obeys a set of simple rules.
API calls
Each API call function in the Nucleus SE starts with
NUSE_, which is almost always followed by the type of the object, followed by a mixed-case operation that is divided using an underscore. An example is the
NUSE_Queue_Send () function, which places messages in a queue.
Other functions and variables
The remaining functions and (global) variables in the Nucleus SE code also use the prefix NUSE_, but the rest of the name does not always have a “structure”. This is unimportant for a regular user of the kernel, since API functions will be enough for him.
Configuration symbols
Since the Nucleus SE is configured with #define characters, they are also subject to naming conventions. They are written only in upper case. The names of the API call activators match the names of the functions and are also written in upper case, for example,
NUSE_QUEUE_SEND.Other characters #define
Any other
#define characters (for example, API call parameters and return status values) that can be used by application code follow the same rules, they begin with
NUSE_ and are written in upper case. For example,
NUSE_SUCCESS.Data structures
All RTOSs have a set of data structures describing kernel objects. In most implementations, they are data structures in C that form linked lists, often with bidirectional and even circular communications. This is logical, since important data is conveniently encapsulated, and list items can be added or deleted as objects are created and deleted.
In Nucleus SE, all objects are static, so organizing all the structures of these objects into a simple list was an obvious solution. This reduces the volume and complexity of direct and reverse pointers. However, I decided to strengthen the optimization of the system and refused to use structures at all. In Nucleus SE, all data of kernel objects is represented by several simple arrays (also called tables) of different types, one for each object type and one more. There are several arguments in favor of such a decision:
- Nucleus SE was designed for compatibility with 8-bit structures. Most small CPUs do not have the best tools for implementing data structures in the C compiler. Simple arrays are much more efficient.
- Since the maximum allowed number of objects of each type is 16, and accessing the elements of each array requires four bits, one byte is often used. This is more efficient than the address, which usually takes 16 or 32 bits.
- It is necessary that the object's permanent data is stored in ROM (ROM) and not copied to RAM (RAM). Since the structure cannot be divided between ROM and RAM (in a traditional portable C), each type of object can have two structures, which is excessively complex. In the Nucleus SE, the object description tables can be located both in the ROM and in the RAM, in accordance with the requirements.
- Due to the highly configurable Nucleus SE ("ultra-high scalability"), some of these object descriptions may be optional, depending on the means chosen. This leads to the widespread use of conditional compilation. Structural definitions with built-in conditional compilation directives are very difficult to understand. Controlling the instantiation of individual arrays using this method is, in turn, fairly easy to understand.
All object data tables are subject to the hierarchical naming convention mentioned above. Thus, it is fairly easy to understand which tables are logically related.
Key Differences from the Nucleus RTOS
Although the Nucleus SE was designed with a high degree of compatibility with the Nucleus RTOS, some small and larger differences could not be avoided. They will be described in detail in the relevant articles, and a brief description is given below.
Object data
In Nucleus RTOS objects are created and deleted upon request. In Nucleus SE, all objects are created statically and are defined at build time.
Number of objects
Nucleus RTOS supports an indefinite number of objects of each type. Nucleus SE supports a maximum of sixteen objects of each type.
Object Names
Nucleus RTOS allows you to assign some types of objects text names that can be used when debugging. There is no such possibility in the Nucleus SE.
Task locking mechanism
The API task blocking mechanism in Nucleus SE is quite simple. When a resource is released, all pending tasks are resumed and compete with each other (with the help of the task scheduler) for resources. Losing tasks are again suspended (blocked). In Nucleus, the RTOS mechanism is more complex, only important tasks continue in it, which is more efficient.
API call timeout
When you call the blocking API, the Nucleus RTOS allows the developer to specify a timeout period after which the call will resume, even if the resource is not released. There is no such possibility in the Nucleus SE.
Scheduling tasks
The Nucleus RTOS Scheduler is flexible, efficient, and well-defined. Nucleus SE offers a set of schedulers, each of which is simple and effective enough for a reduced number of supported tasks: from 1 to 16.
Task Priorities
A system that uses Nucleus RTOS can have an arbitrary number of tasks that can be assigned one of 256 priority levels, and several tasks can have one priority level. Task priority levels can also change during execution. In Nucleus SE, if a priority scheduler is selected, each task must have a unique priority level that cannot be changed dynamically. There can be only one priority level for each task.
Interrupt handling
Nucleus RTOS supports the sophisticated two-level interrupt handler architecture, which allows for efficient interaction between the interrupt handler and kernel services. Nucleus SE uses a similar approach that supports both simple interrupt handlers that do not interact with the kernel (unmanaged interrupts) and interrupt handlers with full context that can use API calls (controlled interrupts).
Device drivers
Nucleus RTOS has a well thought out device driver architecture. Nucleus SE does not have such an architecture, leaving the developer with the task of distributing device management between tasks and the interrupt handler code.
Nucleus SE Spread
Nucleus SE source codes will be published as this series of articles develops. Available files will be provided upon request by email. Towards the end of a series of articles, a repository will be created for downloading all published files.
about the authorColin Walls has been working in the electronics industry for over thirty years, devoting much of his time to embedded software. He is now an embedded software engineer in Mentor Embedded (a division of Mentor Graphics). Colin Walls often speaks at conferences and seminars, author of numerous technical articles and two books on embedded software. Lives in the UK. Colin's professional
blog ,
e-mail