You are viewing an older revision! See the latest version

RTOS

Table of Contents

    RTOS

    1. mbed RTOS
    2. CMSIS RTOS

    The mbed RTOS API is a simple C++ encapsulation of the CMSIS RTOS C API.

    Import librarymbed-rtos

    Official mbed Real Time Operating System based on the RTX implementation of the CMSIS-RTOS API open standard.

    Thread

    The Thread class allows defining, creating, and controlling thread functions in the system. The function main is a special thread function that is started at system initialization and has the initial priority osPriorityNormal.

    Import program

    00001 #include "mbed.h"
    00002 #include "rtos.h"
    00003  
    00004 DigitalOut led1(LED1);
    00005 DigitalOut led2(LED2);
    00006  
    00007 void led2_thread(void const *argument) {
    00008     while (true) {
    00009         led2 = !led2;
    00010         Thread::wait(1000);
    00011     }
    00012 }
    00013  
    00014 int main() {
    00015     Thread thread(led2_thread);
    00016     
    00017     while (true) {
    00018         led1 = !led1;
    00019         Thread::wait(500);
    00020     }
    00021 }
    

    main

    The main function is already the first thread scheduled by the rtos.

    [Repository '/users/mbed_official/code/rtos/docs/68e146c0e76b/classrtos_1_1Thread.html' not found]

    Mutex

    A Mutex is used to synchronize the execution of threads: for example to protect the access to a shared resource.

    ISR

    The Mutex methods cannot be called from interrupt service routines (ISR).

    /media/uploads/emilmont/mutex.png

    Import program

    00001 #include "mbed.h"
    00002 #include "rtos.h"
    00003 
    00004 Mutex stdio_mutex; 
    00005 
    00006 void notify(const char* name, int state) {
    00007     stdio_mutex.lock();
    00008     printf("%s: %d\n\r", name, state);
    00009     stdio_mutex.unlock();
    00010 }
    00011 
    00012 void test_thread(void const *args) {
    00013     while (true) {
    00014         notify((const char*)args, 0); Thread::wait(1000);
    00015         notify((const char*)args, 1); Thread::wait(1000);
    00016     }
    00017 }
    00018 
    00019 int main() {
    00020     Thread t2(test_thread, (void *)"Th 2");
    00021     Thread t3(test_thread, (void *)"Th 3");
    00022     
    00023     test_thread((void *)"Th 1");
    00024 }
    

    C standard library mutexes

    The ARM C standard library has already mutexes in place to protect the access to stdio, therefore on the M3 mbed the above example is not necessary. On the contrary, ARM microlib (used on the M0 mbed) does not provide default stdio mutexes making the above example a necessity.

    printf, malloc & new in ISR

    Because of the mutexes in the ARM C standard library you can not use printf, malloc and new in ISR!

    [Repository '/users/mbed_official/code/rtos/docs/68e146c0e76b/classrtos_1_1Mutex.html' not found]

    Semaphore

    A Semaphore is particularly useful to manage thread access to a pool of shared resources of a certain type.

    /media/uploads/emilmont/semaphore.png

    Import program

    00001 #include "mbed.h"
    00002 #include "rtos.h"
    00003 
    00004 Semaphore two_slots(2);
    00005 
    00006 void test_thread(void const *name) {
    00007     while (true) {
    00008         two_slots.wait();
    00009         printf("%s\n\r", (const char*)name);
    00010         Thread::wait(1000);
    00011         two_slots.release();
    00012     }
    00013 }
    00014 
    00015 int main (void) {
    00016     Thread t2(test_thread, (void *)"Th 2");
    00017     Thread t3(test_thread, (void *)"Th 3");
    00018     
    00019     test_thread((void *)"Th 1");
    00020 }
    

    [Repository '/users/mbed_official/code/rtos/docs/68e146c0e76b/classrtos_1_1Semaphore.html' not found]

    Signals

    Each Thread can be notified and wait for signals:

    Import program

    00001 #include "mbed.h"
    00002 #include "rtos.h"
    00003 
    00004 DigitalOut led(LED1);
    00005 
    00006 void led_thread(void const *argument) {
    00007     while (true) {
    00008         // Signal flags that are reported as event are automatically cleared.
    00009         Thread::signal_wait(0x1);
    00010         led = !led;
    00011     }
    00012 }
    00013 
    00014 int main (void) {
    00015     Thread thread(led_thread);
    00016     
    00017     while (true) {
    00018         Thread::wait(1000);
    00019         thread.signal_set(0x1);
    00020     }
    00021 }
    

    Queue

    A Queue allows you to queue pointers to data from producers threads to consumers threads:

    /media/uploads/emilmont/messagequeue.png

    Queue<message_t, 16> queue;
    
    message_t *message;
    
    queue.put(message);
    
    osEvent evt = queue.get();
    if (evt.status == osEventMessage) {
        message_t *message = (message_t*)evt.value.p;
    

    [Not converted]

    MemoryPool

    The MemoryPool class is used to define and manage fixed-size memory pools:

    MemoryPool<message_t, 16> mpool;
    
    message_t *message = mpool.alloc();
    
    mpool.free(message);
    

    [Not converted]

    [Not converted]

    Mail

    A Mail works like a queue with the added benefit of providing a memory pool for allocating messages (not only pointers).

    /media/uploads/emilmont/mailqueue.png

    [Not converted]

    [Not converted]

    RTOS Timer

    The RtosTimer class allows creating and and controlling of timer functions in the system. A timer function is called when a time period expires whereby both on-shot and periodic timers are possible. A timer can be started, restarted, or stopped. Timers are handled in the thread osTimerThread. Callback functions run under control of this thread and may use CMSIS-RTOS API calls.

    /media/uploads/emilmont/rtostimer.png

    [Not converted]

    [Not converted]

    Interrupt Service Routines

    The same RTOS API can be used in ISR. The only two warnings are:

    • Mutex can not be used.
    • Wait in ISR is not allowed: all the timeouts in method parameters have to be set to 0 (no wait).

    [Not converted]

    Default Timeouts

    The mbed rtos API has made the choice of defaulting to 0 timeout (no wait) for the producer methods, and osWaitForever (infinitive wait) for the consumer methods.

    A typical scenario for a producer could be a peripheral triggering an interrupt to notify an event: in the corresponding interrupt service routine you cannot wait (this would deadlock the entire system). On the other side, the consumer could be a background thread waiting for events: in this case the desired default behaviour is not using CPU cycles until this event is produced, hence the osWaitForever.

    No wait in ISR

    When calling an rtos object method in an ISR all the timeout parameters have to be set to 0 (no wait): waiting in ISR is not allowed.

    Stack Configuration

    The stack configuration is very dependent from the underling CMSIS-RTOS implementation.

    As first reference implementation we are using RTX. One of the limitation of the RTX implementation is that it requires to statically configure the maximum number of threads and the size of the memory pool for their stacks.

    This is our default configuration:

    mbed NXP LPC11U24mbed NXP LPC1768
    Max number of user threads + (timer)3 + (1)7 + (1)
    Default stack size in bytes0.5 Kb1 Kb

    configuration

    To edit the configuration:

    • Right-click the rtos library and select "Edit library...".
    • Modify RTX_Conf_CM.c as needed.

    Status and Error Codes

    The Status and Error Codes section lists all the return values that the CMSIS-RTOS functions will return:

    • osOK: function completed; no event occurred.
    • osEventSignal: function completed; signal event occurred.
    • osEventMessage: function completed; message event occurred.
    • osEventMail: function completed; mail event occurred.
    • osEventTimeout: function completed; timeout occurred.
    • osErrorParameter: parameter error: a mandatory parameter was missing or specified an incorrect object.
    • osErrorResource: resource not available: a specified resource was not available.
    • osErrorTimeoutResource: resource not available within given time: a specified resource was not available within the timeout period.
    • osErrorISR: not allowed in ISR context: the function cannot be called from interrupt service routines.
    • osErrorISRRecursive: function called multiple times from ISR with same object.
    • osErrorPriority: system cannot determine priority or thread has illegal priority.
    • osErrorNoMemory: system is out of memory: it was impossible to allocate or reserve memory for the operation.
    • osErrorValue: value of a parameter is out of range.
    • osErrorOS: unspecified RTOS error: run-time error but no other error message fits.

    osEvent

    The osEvent data structure is returned by get methods of Queue and Mail objects. This data structure contains both an error code and a pointer to the actual data:

    [Not converted]


    All wikipages