What is AVIX?
AVIX is a modern preemptive Real Time Operating System, offering features, in combination, not found in any competing product. AVIX is based on the segmented architecture which is one of the most advanced architectures available. The most prominent advantage AVIX offers is that it never disables interrupts, meanwhile offering full integration between Interrupt Service Routines and threads. This feature allows extremely high interrupt rates no competing product is able to reach. AVIX is available for a number of different micro controller families. A version for a specific family is called a port. The following ports are available:
|
|
AVIX for Cortex-M3
|
|
Atmel
|
AT91SAM3
|
|
Energy Micro
|
EFM32
|
|
NXP
|
LPC13x / LPC17x
|
|
Fujitsu
|
FM3
|
|
ST Micro
|
STM32
|
|
Texas Instruments
|
LM3S
|
|
Toshiba
|
TMPM3x0
|
|
AVIX for Cortex-M3 works for all above mentioned micro controller families.
|
|
AVIX for Cortex-M3 is fully CMSIS based and available for the IAR EWARM development environment using the ICCARM compiler and the KEIL MDK development environment using the ARMCC compiler on a single license.
|
|
|
 |
|
AVIX for PIC32MX
|
|
Microchip
|
PIC32MX
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AVIX for PIC32MX works for all members of the above mentioned micro controller family.
|
|
AVIX for PIC32MX is available for the Microchip MPLAB8x development environment using the C32 C compiler. AVIX for PIC32MX supports both versions 1.x and versions 2.x of the C32 compiler
|
|
|
 |
|
AVIX for PIC24-dsPIC
|
|
Microchip
|
PIC24F
|
|
Microchip
|
PIC24H
|
|
Microchip
|
dsPIC30F
|
|
Microchip
|
dsPIC33F
|
|
|
|
|
|
|
|
AVIX for PIC24-dsPIC works for all above mentioned micro controller families.
|
|
AVIX for PIC24-dsPIC is available for the Microchip MPLAB8x development environment using the Microchip C30 C compiler.
|
|
|
|
|
|
 |
 |
Features
|
|
|
AVIX is based on the Segmented Architecture. This architecture allows an RTOS to be fully operational without ever disabling interrupts.
Most competing RTOSes are based on the Unified Architecture. RTOSes based on the Unified Architecture frequently disable interrupts leading to problems with interrupt handling like jitter or even lost interrupts.
Both architectures allow RTOS functions to be used by interrupt handlers. The difference is that RTOSes based on the Unified Architecture allow interrupt handlers to directly call RTOS functions while RTOSes based on the Segmented Architecture need a user written helper function for this.
AVIX offers the best of both worlds by combining the advantages offered by the Segmented Architecture with the advantage of the Unified architecture. AVIX is a true Zero Latency RTOS meaning it never disables interrupts and still allows many RTOS functions to be called directly from the interrupt handler.
These combined features make AVIX a true hybrid RTOS combining extremely efficient interrupt handling with a user friendly programming model.
|
AVIX is based on the Segmented Architecture meaning it never disables interrupts. This offers numerous advantages:
- Interrupt latency equals that of the underlying hardware
- Interrupts are handled with very low or, for the highest priority interrupt, even zero jitter
- Interrupt rates can be extremely high, AVIX allows 400KHz for a 80MHz Microchip PIC32MX meaning it is able to process an interrupt every 2.5µs.!
- Interrupt handlers can be very short and efficient leading to a more responsive system
Still interrupt handlers are allowed to use many RTOS functions which is a requirement for any RTOS.
The name of this feature is Zero Latency since AVIX does not add a single cycle to the latency of interrupt handlers. More information about this feature can be found here.
Many competing products also claim to be Zero Latency. Not many of them however deserve this title since these interrupt handlers are not allowed to use RTOS functions. Therefore, these interrupt handlers are ‘stand alone’ and can not be integrated with the application unless custom functionality is written for this.
Since integrating interrupt handlers with the application is one of the main features of an RTOS, this makes the Zero Latency claim of those products useless which is why we prefer to call this feature ‘True Zero Latency’.
|
|
To decrease RAM usage, AVIX offers a dedicated Interrupt Stack.
Using an RTOS implies running multiple threads, each with its own stack. Since interrupts occur at unpredictable moments, each of these stacks has to provide space for the worst case interrupt nesting. As a result a lot of RAM is wasted.
To solve this problem, AVIX offers a dedicated system stack which is shared by all interrupt handlers. As a result, the stack of each individual thread does no longer need to reserve space for interrupt context saving resulting in much more RAM being available to the application.
For controllers offering an Interrupt Stack in hardware, this feature is deployed by AVIX. For controllers not offering a dedicated hardware Interrupt Stack, the mechanism is emulated in software offering the same advantages.
More details on this mechanism you find here.
|
|
AVIX is a true Hard Real Time RTOS. This means that most operations finish within a fixed worst case time. Internal data structures are designed such that manipulations of these structures is not influenced by the number of elements they contain, as is the case with many competing products.
Determining which thread should run next for instance is an operation which always takes the same maximum time, regardless the number of threads the application contains.
Using a Hard Real Time RTOS leads to a predictable and dependable system. Once the application works, one can be sure it remains working since function timing will always be the same. There will be no surprises that after the application has been active for some time one of the functions takes longer to complete than before and thus leads to system failure.
In general, timing is one of the more complex aspects of any embedded application. To assist in making an RTOS based application ‘timing correct’, formal methods exist like Rate Monotonic Analysis. These methods are used by many large company like Boeing. A prerequisite for this method to be usable is that the applied RTOS is Hard Real Time, a prerequisite offered by AVIX.
|
|
The most important scheduling mechanism offered by AVIX is Preemptive Scheduling.
Every thread under control of AVIX has a user defined priority. At any given moment, many threads can be Ready To Run since they are not blocked on a resource. It is the responsibility of AVIX to ensure of those threads that are Ready To Run, the one having the highest priority actually will run.
When a thread with a priority higher than the currently running thread becomes Ready to Run, AVIX instantaneously disables the currently running thread in favor of the new thread. The new thread is said to preempt the currently running thread.
Preemption always happens instantaneously and not, as is the case with some competing products, only after a fixed period of an internal timer has elapsed, leading to unacceptable latencies.
|
|
AVIX offers an additional scheduling mechanism in the form of Round Robin scheduling.
When more than one thread is given the same priority and these threads are Ready to Run, AVIX will run one of these threads for a fixed amount of time after which the next thread at that priority will be activated. After all threads at the same priority have run for the fixed amount of time, this process repeats. The amount of time a thread is allowed to run is called a time slice and the duration of a time slice is configurable
This mechanism works together with the preemptive scheduling mechanism. Under all circumstances AVIX guarantees the thread with the highest priority that is Ready to Run will run!
AVIX offers a unique Round Robin scheduling implementation. The granularity with which the time slice is measured is in the magnitude of microseconds. The importance of this is that AVIX guarantees that no thread will be subject to starvation, a term used when a thread has to wait very long to run or will never run at all. Competing products do not offer this fine granularity time slice management and therefore can not guarantee that Round Robin threads will not be the subject of starvation.
|
|
The Application Programming Interface of AVIX aids in fast and error proof software development.
This is obtained by making a number of interfaces to the API type safe such that programming errors are detected compile time instead of runtime, the latter being much harder to solve.
Every kernel object is identified with an id of an AVIX supplied type being unique for the type of kernel object. Threads are identified with an id of type tavixThreadId while mutexes are identified with an id of type tavixMutexId. These types are not interchangeable and mixing them leads to compilation errors aiding in finding programming errors at the earliest possible moment.
This also leads to a more compact implementation since a mutex function does not need to check whether the id it receives is that of a mutex. The type safe mechanism together with the compiler has already taken care of this.
Competing products often use ‘C’ type void* for kernel object identifiers leading to more elaborate code and the inability to find programming errors compile time.
The mechanism offered by AVIX comes with no overhead, not a single cycle. Furthermore, besides being used for kernel object id’s, it is also used for functions receiving parameters with a fixed set of values. This type of parameter is based on the same type safe mechanism offering the same advantages as mentioned above.
|
|
AVIX functions never return an error code. When the application calls a function and this function returns, it is considered to have succeeded.
AVIX does implement a number of runtime checks and in case one of these checks fails, instead of returning the problem to the caller, a central error handling function is called.
As a result application code is less complex since when calling a function, the application does not need to check for all kinds of possible errors. This in itself causes less programming errors since there is a relation between code complexity and programming errors.
AVIX allows the central error handling function to be user specified so in case of an error the application can decide what to do with it.
|
|
AVIX offers fast and deterministic context switching when a thread is preempted and another thread has to run.
In its fastest configuration a context switch only takes 55 CPU cycles for a Microchip controller. This takes less than 1.5 µs on a 16 bit controller running at 40 MIPS(1).
The context switch time is not influenced by the number of threads as is the case with many competing products. To accomplish this, the internal structures of AVIX are highly optimized. The time mentioned here is the time consumed by the heart of the scheduler, that is the time it takes from the moment it is known the current active thread needs to be preempted until the new thread continues running.
This time does not include the processing of the AVIX function leading to the preemption.
This time includes saving the complete context of the current active thread and restoring that of the newly activated thread.
(1) The context switch time is influenced by a number of configuration parameters. The maximum context switch time is needed when using round robin scheduling and tracing and saving the DSP addressing mode, PSVPAG and TBLPAG registers as part of the thread context. Even configured like this, the total context switch time is 105 CPU cycles which is still faster than most competing products.
|
|
For many configurations, AVIX runs out of the box.
Still a limited number of system parameters is configurable by changing values in a header file supplied for this purpose.
Among these parameters are those that make AVIX usable with every member of the micro controller family targeted for every possible custom hardware design.
Internally AVIX uses one of the controllers interrupts and one of the timers.
AVIX for Cortex-M3 uses the pendSV interrupt and the SysTick timer. When using AVIX for PIC24/dsPIC or AVIX for PIC32MX, the interrupt and timer can be configured so this will never conflict with the requirements of the application.
|
|
The main kernel object type offered by AVIX is a thread.
Threads contain the vast majority of an applications code and typically applications contain multiple threads. A thread is a function running under control of AVIX. The address of the function that is to be activated as a thread is handed over to AVIX by using AVIX function avixThread_Create.
This is comparable to a non-RTOS based application which must contain a function called ‘main’. The runtime system expects the application to implement this function. When started, the runtime will perform some initialization after which a call is made to ‘main’ to execute the applications code. This type of application can be considered single threaded; there is one ‘thread of execution’.
An AVIX based application is multithreaded meaning there is a ‘main’ like function for every thread. Since functions must have a unique name to prevent linker errors, the actual thread function is not called ‘main’ but each thread function receives a unique user specified name instead.
|
|
The purpose of a mutex is to ensure access to a resource shared between threads can not be preempted.
Once a thread accesses a mutex guarded resource, only when all required operations are performed and the mutex is released another thread is granted access to the resource.
A mutex is a synchronization object used to control access to a resource used by two ore more threads (shared resource). In this context, a shared resource can be anything that is not ‘private’ to the thread that wants to use it. Examples of shared resources are global variables, I/O devices and so on. The name mutex comes from mutual exclusion which is what it is used for. Using a mutex, a thread can prevent other threads from accessing a shared resource at the ‘same moment’.
AVIX mutexes offer an advanced implementation of the Priority Inheritance mechanism. This mechanism raises the priority of a thread owning a mutex might a higher priority thread desire to lock that mutex. Unlike many competing products, the AVIX priority inheritance mechanism works in nested situations and also for threads at the same priority which are scheduled Round Robin.
|
|
The purpose of a semaphore is to control access to resources with a bound number of instances from multiple threads.
When all resource instances are used, a semaphore ensures another thread can not use one of the resources until a using thread indicates to no longer need the resource.
A semaphore is a synchronization object maintaining a count conceptually representing a number of permits. A thread requiring a permit executes a semaphore lock function. When the semaphore has a permit available (internal count greater than zero), it decrements this count and the thread is allowed to continue. When no permit is available (count is zero), the thread enters the ‘Blocked state’ until another thread increments the count by calling the semaphore unlock function.
Semaphores are often used to control access to a shared resource or control access to a resource that contains multiple elements.
|
|
An event group is an AVIX kernel object maintaining a total of 16 event flags.
Threads can wait for a certain combination of event flags to become set. As long as the desired combination of event flags is not set, the thread will be Blocked. Event flags can be set, cleared or toggled by other threads where the waiting thread enters the ‘Ready state’ when the desired combination of flags becomes available.
AVIX offers two categories of event groups.
First a global event group can be explicitly created and other threads can obtain access to it by using the name given to this event group. This type of event group can be used by multiple threads to wait for the desired flags and at the same time by multiple threads to change the status of one or more flags.
Second, every thread has got a local thread event group, when the thread exists, its local event group exists. Functionally a thread event group is identical to a regular event group. The difference is that only the thread the event group belongs to can wait for it. To identify a thread event group, the id of the owning thread is used. It shall be obvious other threads can change the value of flags in a local event group the same way they can for a global event group.
Event groups can be ‘connected’ to message queues and timers to allow a thread to wait for multiple events.
|
|
Pipes offer an extremely fast and flexible communication mechanism between threads and Interrupt Service Routines and vice versa or between threads mutually.
Pipes implement a FIFO buffer that concurrently can be written to and read from by threads and Interrupt Service Routines Pipes have a fixed size which is determined during creation. A thread writing to a pipe enters the ‘Blocked State’ when not enough empty space is available. A thread reading from a pipe enters the ‘Blocked State’ if the desired amount of data is not present.
Pipes form the communication mechanism of choice between Interrupt Service Routines and threads. Applying pipes significantly ease the way to deal with interrupt driven devices. Pipes are especially suitable when data needs to be transferred between a device and a thread, either incoming or outgoing data. Besides transferring the actual data, Pipes also offer a mechanism to control the activity of the related device in a high level manner, without compromising performance. Pipes are not restricted to be used between Interrupt Service Routines and threads but can also be used to transfer data between threads mutually. In this case, only a subset of the functionality is used since controlling device activity is not an issue then.
AVIX allows the size of a basic element read from or written to a pipe to be specified. This is important since AVIX guarantees that a basic element is always processed atomically. Not doing so might lead to elaborate application level error handling. Competing products often only allow a basic element to have a size of 1 byte or the size of a pointer. Using these implementations for transferring multiple byte structures is only possible at the cost of complex and error sensitive application level code.
|
|
Message services allow a request to be sent to a thread in the form of a message. A messages is a block of memory with a fixed, though configurable, size. The semantics of the request are identified by the content placed in this memory by the requesting thread.
Message content consists of two parts. First there is a numeric value, the message type, identifying the request. This numeric value is user specified and should be agreed upon between the requesting and the receiving thread. Optionally the message body may contain additional data in case the type attribute does not provide sufficient information to fully specify the request. Both the structure and the content of the message body is again user specified.
Memory blocks used for messages are allocated from a dedicated memory pool created during AVIX initialization. The number of memory blocks in this pool is configurable. After allocating a message, it will be filled with the required information and sent to a thread. The receiving thread is responsible for returning this message block to the memory pool in case it is not needed for other purposes. When allocating a message from an empty message pool the thread will enter the ‘Blocked state’ until a message is present again in the message pool because it is freed by another thread.
Messages can be allocated and sent from a thread and directly from an Interrupt Service Routine. The destination of a message is always a thread.
Finally, AVIX allows an event group to be ‘connected’ to a message queue so the value of the specified event flag reflects the fact whether the message queue is empty or not.
|
|
Memory is one of the most important resources of a real time system. Most real time systems depend heavily on memory that can be allocated and freed again which allows for reuse of memory. Reuse is needed while memory often is a scarce resource. In general, real time systems can not make use of the ‘C’ runtime system provided heap offering malloc and free functions. A number of problems prevent this. First timing of the heap is not deterministic. Second, the heap can not be used from multiple threads. Finally heap fragmentation may render the heap unusable.
AVIX addresses these problems by offering memory management in the form of memory pools containing fixed size blocks. AVIX allows for the creation of multiple memory pools, each having blocks of a potentially different size so the application can use a memory pool that fits best to its requirements. When allocating a memory block, this is done from a specific pool. The allocation function returns the id of a block. When freeing the block again, all that is needed is its id. The application does not need to ‘remember’ which pool the block was allocated from; AVIX determines the correct pool to return the memory block to, based on internal bookkeeping information. This makes application development easier since the application does not need to maintain this bookkeeping. Additionally, for controllers offering extended RAM (EDS RAM for PIC24F or additional memory banks for Cortex-M3), AVIX allows memory pools to be created in this RAM also.
This can be compared to having multiple heaps where the application does not need to know what heap a memory block that is freed belongs to.
In contradiction with most competing products, AVIX allows memory blocks to be allocated and freed from an Interrupt Service Routine. This allows for extremely fast communication between Interrupt Service Routines and threads.
|
|
Managing time is one of the most important services offered by an RTOS. AVIX offers extensive timer functionality in the form of timer kernel objects.
When activating a timer it starts counting. After the specified period has elapsed, the timer expires. An expiring timer triggers actions. Two types of actions are possible:
- First, a timer is a waitable object. Threads can wait for a timer by calling avixTimer_Wait. As long as the timer is not expired, threads waiting for the timer are in the ‘Blocked state’ and do not consume any CPU cycles. Once the timer expires, all threads Blocked on the timer have their state changed to Ready.
- Second, an event group can be ‘connected’ to a timer. When the timer expires it will execute the specified action on the flags of this event group. This action can be clear, set or toggle of any desired number of flags. When this happens, the standard event group scenario is executed and threads blocked on the event group may have their state changed from Blocked to Ready. This allows for threads to wait for multiple types of objects at the same time.
When connecting an event group to a timer, still the timer can be used to wait for directly. This offers ultimate flexibility in the application of timers. Timers can be initialized having one of two types, single-shot or cyclic. The type of a timer is not determined during creation of the timer object but by using a separate function, avixTimer_Set. This allows a single-shot timer to be reinitialized as a cyclic timer and vice versa.
|
|
The micro controllers AVIX is available for offer advanced mechanisms to reduce energy consumption. Deploying these mechanisms is often difficult if not impossible since they require the application to know when there is nothing to do.
AVIX offers an idle thread, a thread that is active when no application threads are active. This offers a good starting point to activate a low power mode since the mere fact this idle thread is active implies that no application code needs to run.
Most RTOSes offer the possibility for the application to register a callback function to be called from the idle thread when it is active. Doing so places the burden of actually programming the controllers low power mode in the application.
AVIX goes a step further and has the code to activate the desired low power mode built right in.
For basic energy reduction, all the application has to do is call a single function specifying the desired low power mode. All details are subsequently taken care of by AVIX.
For advanced application specific energy reduction AVIX offers the interface to provide the application with all information required to do so.
Important to realize is that the level of energy saving realized entirely depends on the structure of the application and the load the application places on the micro controller. AVIX facilitates the possibility to obtain energy saving but does not guarantee any level of energy saving to be obtained.
|
|
The purpose of Exchange services is to offer a high level inter-thread communication mechanism supporting loose coupling, broadcasting and synchronization of threads operating at different speeds. Additionally, Exchange Services makes reuse of software components easier and facilitates extending an application by adding new functionality with the least possible or, most of the time, even no changes to existing code.
When creating an application, a designer is faced with many challenges. Besides correct functional and temporal behavior, it is advantageous to have the right level of modularity in order to ease development, testing and reuse of software components in other applications.
AVIX Exchange services assist in reaching these goals, not only leading to a decrease in initial development time but also make one feel more confident about the correctness of the resulting application.
More information can be found here.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
 |
 |
|
AVIX-RT © 2006-2011, All Rights Reserved
|
|
|
|
|
|
|