DioneOS (pronounced /djoneos/) is Real Time preemptive Operating System designated for microcontrollers.
Currently, the system works on Texas Instruments MSP430, MSP430X, ARM Cortex-M3.
Why you need a system for development of your firmware?
What were the main goals?
System features.
System performance.
Limitations and requirements
The price and licensing information (the page contains information how to purchase the system)
Why you need a system for development of your firmware?
If you developed a firmware you probably already faced a problem of sequential execution of a program. Even if the firmware is not very complex, it contains many jobs* that should work concurrently. For example, the firmware may consists of: main state machine controlling behaviour of the device, command processor, modem control module, handler of events on input pins etc. Each of these parts has its own requirements on CPU processing time. Their execution depends on input events that may trigger their activity or set into waiting state. They also need interconnection mechanism for mutual communication. For sure, they share some common data and access it from different locations asynchronously. As long as you don't use operating system you need to solve that problems by yourself.
In most cases it results in unclear structure of the firmware and potential threat of errors that are difficult to be tracked and eliminated. Informal structure cannot be properly described by a model and analysed on higher level of abstraction. Hence, it is difficult to convince oneself that the firmware has no design errors that would cause concurrency issues. In the naive design, interrupts are often disabled to guard access to common objects and many part of the code runs in interrupt service routines (ISR). Programmer must deal with the problem of switching CPU between the jobs - solved by compromised run-to-completion and voluntary redirection of the execution to other job. Another issue is when the job starts waiting for an event, or need to signal to others that something must be done. In that case it needs to trigger an action that must be done in different job. Finally, even if all problems seems to be solved, the structure of the code is affected by parts that imitate concurrency. The jobs are not well separated but form common code, that is difficult maintain and analyse. It is not good practice and design pattern for the firmware where quality requirement is very important.
The alternative is an operating system that provides all universal functionality that is required for semi-parallel execution of the jobs. The system provides a concept of threads - separated parts of the code that can implement only their functions. If the system is preemptive (like
DioneOS) it can switch CPU control from one thread to another automatically. The system provides typical, well known mechanisms for mutual synchronization (i.e. mutex, semaphore), time dependencies (timers) and communication between the threads (event, queue). When you use the system, all above features are ready when you start development of your firmware. You can focus on your application, because other work is already done and available for use. Moreover, standard elements and design patterns provided by the system force better firmware structure and clarity. It is also much easier to analyse the system behaviour because higher level model can be defined.
What were the main goals?
During the DioneOS system design and development I had always in mind a target and its resources. The main goal was a performance. Due to this requirement, many parts of the code has been optimised, some items are build in preprocessing or compilation time. System code responsible for switching between threads (context switching) has been written in assembler and optimised. Sequence of instructions generated by a compiler were checked and C source code was tuned if it was necessary.
I considered cooperation between threads and ISR and provided fast mechanism for context switching just after asynchronous trigger from ISR (some other systems do context switch only on system tick interrupt, that has disadvantage of increasing latency of triggering a thread from ISR). I tested and optimised switching time for minimal number of cycles spent in this function. Current version of the system can make a switch between threads in 10.4us - 16.9us depending on switch type and accompanying events
(refer to description for more information about context switch time).
System Features
System type
- preemptive
- maximum priority (each thread has unique priority)
- context switch on:
synchronization object change,
ISR exit,
timer expiration
- preemption control (independent on interrupt control)
Synchronization objects
-
mutex (nested calls in one thread are allowed),
Timing control
-
timers (with callback function)
Communication
-
ring buffer for non-uniform items (effective implementation of queue)
State machines
Memory management
-
memory pool (effective allocator, free of fragmentation issue)
- function for signalling events on chip pins (useful when tracking time dependencies and real time bugs )
- critical exception
os_bug() thrown in many system places when unrecoverable bug appears, when system behaviour would be undefined and unpredictable. The exception can be tracked even if the stack pointer register is corrupted. The exception mechanism is available for user, he can define his own bug codes and use it in application.
- marking deleted objects with specific pattern (useful in detection the usage of non-existing object)
- Many user configurable flags, that affects compiled code of the system
- User can configure and assign processor resources that are used for the operating system (chose the hardware timer, frequency of system tick interrupt, debug port for logic analyser)
Compatible with Code Composer Studio v.4 and its tools
If you need more details refer to description in respective files.
Limitations and Requirements
The system uses a few assumptions that helped to achieve better performance of the system functions:
* The system must be compiled under Texas Instruments Code Composer Studio v.4 (assembler parts are compliant with CCS dialect), or gcc version for Atmel AVR (e.g. WinAVR) depending on target architecure.
* Main objects are created at the system start-up (e.g. threads, memory pools, system tick timer), some of them cannot be deleted (e.g. threads).
* Threads have unique priorities
* Maximum number of threads is 16 (including obligatory IDLE thread)
* The idle thread has lowest priority and must always be ready (may be used to determine system load)
* (MSP430)System uses only RAM locations in 64KB (cannot be compiled with --large_memory_model), this does not affect usage of high FLASH for program, so large code can be still used.
* (AVR) System cannot use FLASH above 64KB, there is assumption that it uses 16 bit addressing * (MSP430) System uses 16 bits enums (cannot be yet compiled with --small_enum), (AVR) system requires 8 bits enums
* Nested interrupts are not allowed
* ISR uses interrupted thread stack for its execution
* Used microcontroller must have enough RAM and FLASH memories for system code, structures and threads requirements (e.g. stack). Below you may find some estimations:
Current version of the system uses 106 + Threads*20, that is 426 bytes for 16 threads. You must also reserve recommended minimum 130 bytes for stack per each thread, hence for 16 threads it would use ~3200 bytes including 160 bytes for initial C stack. This amount does not take into account memory pools and other user variables. Size of thread stack depends on number of nested calls, local variables, etc.
According to FLASH requirement, the system functions can fit into 4 KB.
Summary of System Requirements on Microcontroller
* MSP430 or MSP430X architecture,
* minimum 6KB of FLASH,
* minimum 4KB of RAM memory (you may decrease RAM consumption when your application does not need all 16 threads).
* AVR architecture
*
- Note:
- Above values are determined for the system. When you choose microcontroller you must take into account additional FLASH and RAM for your application. This extra size depends on your firmware complexity.
*) I intentionally used word 'job' to describe some abstract part of activity and avoid any connotation with task or thread.
**) ISR - Interrupt Service Routine