Dependents:   rtest LeonardoMbos OS_test Labo_TRSE_Drone ... more

mbos.h

Committer:
AndrewL
Date:
2012-01-09
Revision:
6:cf660b28b2a4
Parent:
4:e740e08cbea9

File content as of revision 6:cf660b28b2a4:

/***********************************************************************************
 *  m b o s   R T O S   F O R    m b e d  (ARM CORTEX M3)
 *
 * Copyright (c) 2010 - 2011 Andrew Levido
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#ifndef MBOS_H
#define MBOS_H

typedef unsigned int uint;

/**A pre-emptive, mutlitasking real-time operating system for mbed applications.
 *
 * Allows the user to write their application in the form of independant tasks.
 * The operating system manages a completely separate processor context for each
 * task (processor registers and stack) and swaps between the tasks according to a
 * simple scheduling algorithm.
 *
 * Tasks are allocated a priority, and the scheduler ensures that the task
 * that with the highest priority that is not waiting for an event, has control of
 * the processor. If more than one task shares the highest priority, they will be
 * run sequentially in round-robin fashion.
 *
 * Each task may wait for one or more of up to 32 different events, each represented by
 * one bit in the event flags word. Events may be posted by another task, by a mbos
 * timer, or in response to some asynchronous event such as an peripheral interrupt.
 *
 * mbos implements the SysTick timer to generate a System Tick every millisecond.
 * Scheduling occurs once every Tick, or whenever a task blocks or an event is posted.
 * The user may create one-shot or continuous timers to post events to tasks.
 *
 * mbos implements a simple ceiling protocol resource locking mechanism To manage access
 * to system resources. Tasks may take exclusive ownership of resources for a period.
 *
 * A typical simple example with two tasks, and one timer, might look like this:
 * @code
 * // mbos Blinky demonstration.
 * // Task 1 toggles LED1 every second, under control of a timer. It then posts an event to
 * // task 2 which flashed LED2 briefly.
 * #include "mbed.h"                    
 * #include "mbos.h"
 *
 * #define TASK1_ID                1       // Id for task 1 (idle task is 0)
 * #define TASK1_PRIO              50      // priority for task 1
 * #define TASK1_STACK_SZ          32      // stack size for task 1 in words 
 * #define TASK2_ID                2       // Id for task 2 
 * #define TASK2_PRIO              60      // priority for task 2
 * #define TASK2_STACK_SZ          32      // stack size for task 2 in words 
 * #define TIMER0_ID               0       // Id for timer 0
 * #define TIMER0_PERIOD           1000    // Time period in milliseconds
 * #define TIMER0_EVENT            1       // Event flag (1 << 0)
 * #define T1_TO_T2_EVENT          2       // Event flag (1 << 1)
 *
 * void task1(void);                       // task function prototypes
 * void task2(void);
 *
 * DigitalOut led1(LED1);
 * DigitalOut led2(LED2);
 * mbos os(2, 1);                          // Instantiate mbos with 2 tasks & 1 timer    
 *
 * int main(void)
 * {
 *     // Configure tasks and timers
 *     os.CreateTask(TASK1_ID, TASK1_PRIO, TASK1_STACK_SZ, task1);
 *     os.CreateTask(TASK2_ID, TASK2_PRIO, TASK2_STACK_SZ, task2);
 *     os.CreateTimer(TIMER0_ID, TIMER0_EVENT, TASK1_ID);
 *     // Start mbos
 *     os.Start();
 *     // never  return!
 * }
 *
 * void task1(void)
 * {
 *     os.SetTimer(TIMER0_ID, TIMER0_PERIOD, TIMER0_PERIOD);
 *     while(1){
 *         os.WaitEvent(TIMER0_EVENT);
 *         led1 = !led1;
 *         os.SetEvent(T1_TO_T2_EVENT, TASK2_ID);
 *     }
 * }
 *
 * void task2(void)
 * {
 *     while(1){
 *         os.WaitEvent(T1_TO_T2_EVENT);
 *         led2 = 1;
 *         wait_ms(100);
 *         led2 = 0;
 *     }
 * }
 * @endcode
 */

class mbos {
public:
    /** Create an mbos object. Instantiate mbos and define the number of tasks, timers 
     * and resources. 
     *
     * @param ntasks The number of user tasks (1 .. 99). 
     * @param ntimers Optional number of timers (0 ..  100).
     * @param nresources Optional number of resources (0 .. 100).
     */
    mbos(uint ntasks, uint ntimers = 0, uint nresources = 0);

    /** Start mbos. Optionally specify the size of the stack for a user-written idle task. 
     * All tasks, timers and resources must be created before calling Start. 
     *
     * @param idlestacksize Size in words (>= 32) of the user-written idle task if present. 
     * @returns Never returns
     */
    void Start(uint idlestacksize = 32);

    /** Create an mbos task. Allocates and initialises data structures for the task.
     *
     * @param taskid Unique ID for the task. (1 .. ntasks).
     * @param priority Priority (0 .. 99) of the task. Tasks may share the same priority.
     * @param stacksize Size in words (>= 32) of the task's stack.
     * @param fun Pointer to the task function. Function must be of type static void, 
     * and must return nothing.
     */
    void CreateTask(uint taskid, uint priority, uint stacksz, void (*fun)(void));

    /** Get the ID of the current task.
     *
     * @returns The ID (0 .. 99) of the calling task.
     */
    uint GetTask(void);

    /** Set the priority of the current task.  Does nothing if called from the idle task.
     *
     * @param priority Priority (0 .. 99) to apply to the calling task.
     */
    void SetPriority(uint priority);

    /** Get the priority of the current task.
     *
     * @returns The priority (0 .. 99) of the calling task.
     */
    uint GetPriority(void);

    /** Wait for an event or events. Causes the current task to block, waiting for the 
     * specified event. Does nothing if called from the idle task, or if the event is NULL.
     *
     * @param event Event flag(s) to wait for.
     */
    void WaitEvent(uint event);

    /** Post an event or events to a task.
     * Posts the nominated event(s) to the specified task. Forces a context switch if the events
     * are posted successfully. Does nothing if the task is not waiting, or is not waiting for 
     * the posted event.
     *
     * @param event Event flag(s) to post. 
     * @param task The ID of the task to which to post the event(s). May not be idle task.
     */
    void SetEvent(uint event, uint task);

    /** Returns the event flag(s) which last caused the task to unblock.
     *
     * @returns The event flags.
     */
    uint GetEvent(void);

    /** Create a mbos timer. Allocates and initialises the data structures for the timer.
     *
     * @param timerid Unique ID for the timer (0 .. ntimers - 1). 
     * @param taskid The ID of the task to which the timer will post events. May not be 
     * the idle task.
     * @param event The event flag(s) that the timer should post on timeout. May not be NULL.
     */
    void CreateTimer(uint timerid, uint taskid, uint event);

    /** Starts an mbos timer. If the reload time is zero or omitted, the timer will be reset 
     * once it has posted a single event, after time milliseconds. If the reload time is
     * non-zero, this value will be loaded into the timer on time-out, and the timer will 
     * continue indefinitely. In this case the interval to the first event will be time, 
     * and the interval between subsequent events will be reloadtime.
     *
     * @param timerid The ID of the timer. 
     * @param time The period in milliseconds before the timer times out.
     * @param reload The optional time to reload into the timer when it times out.
     */
    void SetTimer(uint timerid, uint time, uint reload = 0);
    
    /** Redirects an mbos timer. Changes the task and event associated with a timer. If the timer
     * is running, the fun ction has no effect.
     *
     * @param timerid The ID of the timer.
     * @param taskid The ID of the task to which the timer will post events. May not be 
     * the idle task.
     * @param event The event flag(s) that the timer should post on timeout. May not be NULL.
     */
     void RedirectTimer(uint timerid, uint taskid, uint event); 

    /** Stops and clears an mbos timer.
     *
     * @param timerid The ID of the timer to clear. 
     */
    void ClearTimer(uint timerid);

    /** Creates an mbos resource. Allocates and initialises the data structures for the Resource.
     *
     * @param resourceid Unique ID for the resource (0 .. nresource).
     * @param priority Priority of the resource (normally > than that of any task using the 
     * resource).
     */
    void CreateResource(uint resourceid, uint priority);

    /** Locks an mbos resource and temporarily allocates the resource's priority to the calling 
     * task. 
     * Does nothing if the resource is already locked, or if called from the idle task.
     *
     * @param resourceid The ID of the resource to lock. 
     * @returns Zero if the resource was locked successfully, or the ID of the task that is
     * currently locking the resource, if not.
     */
    uint LockResource(uint resourceid);

    /** Tests whether a resource is locked or free, without changing its state.
     *
     * @param resourceid The ID of the resouce to test.
     * @returns Zero if the resource is free, or the ID of the task that is currently
     * locking the resouce , if not.

     */
    uint TestResource(uint resourceid);

    /** Frees a resource
     * Frees an mbos resource and restores the calling task's original priority. Does nothing 
     * if the resource is already free, if called from the idle task, or the resource was 
     * locked by a different task.
     *
     * @param resourceid The ID of the resource t free. 
     * @returns Zero if the resource was freed successfully, or the ID of the task that is
     * locking the resource, if not.
     */
    uint FreeResource(uint resource);

private:
    uint* _initstack(uint *stack, void (*fun)());
};
#endif