Dependents: rtest LeonardoMbos OS_test Labo_TRSE_Drone ... more
mbos.h@6:cf660b28b2a4, 2012-01-09 (annotated)
- Committer:
- AndrewL
- Date:
- Mon Jan 09 03:11:46 2012 +0000
- Revision:
- 6:cf660b28b2a4
- Parent:
- 4:e740e08cbea9
Fixed error relating to timer events posted to tasks that are not waiting
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
AndrewL | 0:1dafafe7d505 | 1 | /*********************************************************************************** |
AndrewL | 0:1dafafe7d505 | 2 | * m b o s R T O S F O R m b e d (ARM CORTEX M3) |
AndrewL | 0:1dafafe7d505 | 3 | * |
AndrewL | 0:1dafafe7d505 | 4 | * Copyright (c) 2010 - 2011 Andrew Levido |
AndrewL | 0:1dafafe7d505 | 5 | * |
AndrewL | 0:1dafafe7d505 | 6 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED |
AndrewL | 0:1dafafe7d505 | 7 | * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
AndrewL | 0:1dafafe7d505 | 8 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT |
AndrewL | 0:1dafafe7d505 | 9 | * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
AndrewL | 0:1dafafe7d505 | 10 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
AndrewL | 0:1dafafe7d505 | 11 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
AndrewL | 0:1dafafe7d505 | 12 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
AndrewL | 0:1dafafe7d505 | 13 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
AndrewL | 0:1dafafe7d505 | 14 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
AndrewL | 0:1dafafe7d505 | 15 | */ |
AndrewL | 0:1dafafe7d505 | 16 | #ifndef MBOS_H |
AndrewL | 0:1dafafe7d505 | 17 | #define MBOS_H |
AndrewL | 0:1dafafe7d505 | 18 | |
AndrewL | 0:1dafafe7d505 | 19 | typedef unsigned int uint; |
AndrewL | 0:1dafafe7d505 | 20 | |
AndrewL | 0:1dafafe7d505 | 21 | /**A pre-emptive, mutlitasking real-time operating system for mbed applications. |
AndrewL | 0:1dafafe7d505 | 22 | * |
AndrewL | 0:1dafafe7d505 | 23 | * Allows the user to write their application in the form of independant tasks. |
AndrewL | 0:1dafafe7d505 | 24 | * The operating system manages a completely separate processor context for each |
AndrewL | 0:1dafafe7d505 | 25 | * task (processor registers and stack) and swaps between the tasks according to a |
AndrewL | 0:1dafafe7d505 | 26 | * simple scheduling algorithm. |
AndrewL | 0:1dafafe7d505 | 27 | * |
AndrewL | 0:1dafafe7d505 | 28 | * Tasks are allocated a priority, and the scheduler ensures that the task |
AndrewL | 0:1dafafe7d505 | 29 | * that with the highest priority that is not waiting for an event, has control of |
AndrewL | 0:1dafafe7d505 | 30 | * the processor. If more than one task shares the highest priority, they will be |
AndrewL | 0:1dafafe7d505 | 31 | * run sequentially in round-robin fashion. |
AndrewL | 0:1dafafe7d505 | 32 | * |
AndrewL | 0:1dafafe7d505 | 33 | * Each task may wait for one or more of up to 32 different events, each represented by |
AndrewL | 0:1dafafe7d505 | 34 | * one bit in the event flags word. Events may be posted by another task, by a mbos |
AndrewL | 0:1dafafe7d505 | 35 | * timer, or in response to some asynchronous event such as an peripheral interrupt. |
AndrewL | 0:1dafafe7d505 | 36 | * |
AndrewL | 0:1dafafe7d505 | 37 | * mbos implements the SysTick timer to generate a System Tick every millisecond. |
AndrewL | 0:1dafafe7d505 | 38 | * Scheduling occurs once every Tick, or whenever a task blocks or an event is posted. |
AndrewL | 0:1dafafe7d505 | 39 | * The user may create one-shot or continuous timers to post events to tasks. |
AndrewL | 0:1dafafe7d505 | 40 | * |
AndrewL | 0:1dafafe7d505 | 41 | * mbos implements a simple ceiling protocol resource locking mechanism To manage access |
AndrewL | 0:1dafafe7d505 | 42 | * to system resources. Tasks may take exclusive ownership of resources for a period. |
AndrewL | 0:1dafafe7d505 | 43 | * |
AndrewL | 0:1dafafe7d505 | 44 | * A typical simple example with two tasks, and one timer, might look like this: |
AndrewL | 0:1dafafe7d505 | 45 | * @code |
AndrewL | 4:e740e08cbea9 | 46 | * // mbos Blinky demonstration. |
AndrewL | 4:e740e08cbea9 | 47 | * // Task 1 toggles LED1 every second, under control of a timer. It then posts an event to |
AndrewL | 4:e740e08cbea9 | 48 | * // task 2 which flashed LED2 briefly. |
AndrewL | 4:e740e08cbea9 | 49 | * #include "mbed.h" |
AndrewL | 0:1dafafe7d505 | 50 | * #include "mbos.h" |
AndrewL | 0:1dafafe7d505 | 51 | * |
AndrewL | 4:e740e08cbea9 | 52 | * #define TASK1_ID 1 // Id for task 1 (idle task is 0) |
AndrewL | 4:e740e08cbea9 | 53 | * #define TASK1_PRIO 50 // priority for task 1 |
AndrewL | 4:e740e08cbea9 | 54 | * #define TASK1_STACK_SZ 32 // stack size for task 1 in words |
AndrewL | 4:e740e08cbea9 | 55 | * #define TASK2_ID 2 // Id for task 2 |
AndrewL | 4:e740e08cbea9 | 56 | * #define TASK2_PRIO 60 // priority for task 2 |
AndrewL | 4:e740e08cbea9 | 57 | * #define TASK2_STACK_SZ 32 // stack size for task 2 in words |
AndrewL | 4:e740e08cbea9 | 58 | * #define TIMER0_ID 0 // Id for timer 0 |
AndrewL | 4:e740e08cbea9 | 59 | * #define TIMER0_PERIOD 1000 // Time period in milliseconds |
AndrewL | 4:e740e08cbea9 | 60 | * #define TIMER0_EVENT 1 // Event flag (1 << 0) |
AndrewL | 4:e740e08cbea9 | 61 | * #define T1_TO_T2_EVENT 2 // Event flag (1 << 1) |
AndrewL | 0:1dafafe7d505 | 62 | * |
AndrewL | 4:e740e08cbea9 | 63 | * void task1(void); // task function prototypes |
AndrewL | 0:1dafafe7d505 | 64 | * void task2(void); |
AndrewL | 0:1dafafe7d505 | 65 | * |
AndrewL | 0:1dafafe7d505 | 66 | * DigitalOut led1(LED1); |
AndrewL | 0:1dafafe7d505 | 67 | * DigitalOut led2(LED2); |
AndrewL | 4:e740e08cbea9 | 68 | * mbos os(2, 1); // Instantiate mbos with 2 tasks & 1 timer |
AndrewL | 0:1dafafe7d505 | 69 | * |
AndrewL | 0:1dafafe7d505 | 70 | * int main(void) |
AndrewL | 0:1dafafe7d505 | 71 | * { |
AndrewL | 4:e740e08cbea9 | 72 | * // Configure tasks and timers |
AndrewL | 0:1dafafe7d505 | 73 | * os.CreateTask(TASK1_ID, TASK1_PRIO, TASK1_STACK_SZ, task1); |
AndrewL | 0:1dafafe7d505 | 74 | * os.CreateTask(TASK2_ID, TASK2_PRIO, TASK2_STACK_SZ, task2); |
AndrewL | 0:1dafafe7d505 | 75 | * os.CreateTimer(TIMER0_ID, TIMER0_EVENT, TASK1_ID); |
AndrewL | 4:e740e08cbea9 | 76 | * // Start mbos |
AndrewL | 0:1dafafe7d505 | 77 | * os.Start(); |
AndrewL | 4:e740e08cbea9 | 78 | * // never return! |
AndrewL | 0:1dafafe7d505 | 79 | * } |
AndrewL | 4:e740e08cbea9 | 80 | * |
AndrewL | 0:1dafafe7d505 | 81 | * void task1(void) |
AndrewL | 0:1dafafe7d505 | 82 | * { |
AndrewL | 0:1dafafe7d505 | 83 | * os.SetTimer(TIMER0_ID, TIMER0_PERIOD, TIMER0_PERIOD); |
AndrewL | 0:1dafafe7d505 | 84 | * while(1){ |
AndrewL | 4:e740e08cbea9 | 85 | * os.WaitEvent(TIMER0_EVENT); |
AndrewL | 4:e740e08cbea9 | 86 | * led1 = !led1; |
AndrewL | 4:e740e08cbea9 | 87 | * os.SetEvent(T1_TO_T2_EVENT, TASK2_ID); |
AndrewL | 4:e740e08cbea9 | 88 | * } |
AndrewL | 0:1dafafe7d505 | 89 | * } |
AndrewL | 4:e740e08cbea9 | 90 | * |
AndrewL | 0:1dafafe7d505 | 91 | * void task2(void) |
AndrewL | 0:1dafafe7d505 | 92 | * { |
AndrewL | 4:e740e08cbea9 | 93 | * while(1){ |
AndrewL | 4:e740e08cbea9 | 94 | * os.WaitEvent(T1_TO_T2_EVENT); |
AndrewL | 4:e740e08cbea9 | 95 | * led2 = 1; |
AndrewL | 4:e740e08cbea9 | 96 | * wait_ms(100); |
AndrewL | 4:e740e08cbea9 | 97 | * led2 = 0; |
AndrewL | 4:e740e08cbea9 | 98 | * } |
AndrewL | 0:1dafafe7d505 | 99 | * } |
AndrewL | 0:1dafafe7d505 | 100 | * @endcode |
AndrewL | 0:1dafafe7d505 | 101 | */ |
AndrewL | 0:1dafafe7d505 | 102 | |
AndrewL | 0:1dafafe7d505 | 103 | class mbos { |
AndrewL | 0:1dafafe7d505 | 104 | public: |
AndrewL | 2:af930cdf7cce | 105 | /** Create an mbos object. Instantiate mbos and define the number of tasks, timers |
AndrewL | 2:af930cdf7cce | 106 | * and resources. |
AndrewL | 0:1dafafe7d505 | 107 | * |
AndrewL | 2:af930cdf7cce | 108 | * @param ntasks The number of user tasks (1 .. 99). |
AndrewL | 2:af930cdf7cce | 109 | * @param ntimers Optional number of timers (0 .. 100). |
AndrewL | 2:af930cdf7cce | 110 | * @param nresources Optional number of resources (0 .. 100). |
AndrewL | 0:1dafafe7d505 | 111 | */ |
AndrewL | 0:1dafafe7d505 | 112 | mbos(uint ntasks, uint ntimers = 0, uint nresources = 0); |
AndrewL | 0:1dafafe7d505 | 113 | |
AndrewL | 2:af930cdf7cce | 114 | /** Start mbos. Optionally specify the size of the stack for a user-written idle task. |
AndrewL | 2:af930cdf7cce | 115 | * All tasks, timers and resources must be created before calling Start. |
AndrewL | 0:1dafafe7d505 | 116 | * |
AndrewL | 2:af930cdf7cce | 117 | * @param idlestacksize Size in words (>= 32) of the user-written idle task if present. |
AndrewL | 0:1dafafe7d505 | 118 | * @returns Never returns |
AndrewL | 0:1dafafe7d505 | 119 | */ |
AndrewL | 4:e740e08cbea9 | 120 | void Start(uint idlestacksize = 32); |
AndrewL | 0:1dafafe7d505 | 121 | |
AndrewL | 2:af930cdf7cce | 122 | /** Create an mbos task. Allocates and initialises data structures for the task. |
AndrewL | 0:1dafafe7d505 | 123 | * |
AndrewL | 2:af930cdf7cce | 124 | * @param taskid Unique ID for the task. (1 .. ntasks). |
AndrewL | 0:1dafafe7d505 | 125 | * @param priority Priority (0 .. 99) of the task. Tasks may share the same priority. |
AndrewL | 2:af930cdf7cce | 126 | * @param stacksize Size in words (>= 32) of the task's stack. |
AndrewL | 2:af930cdf7cce | 127 | * @param fun Pointer to the task function. Function must be of type static void, |
AndrewL | 2:af930cdf7cce | 128 | * and must return nothing. |
AndrewL | 0:1dafafe7d505 | 129 | */ |
AndrewL | 0:1dafafe7d505 | 130 | void CreateTask(uint taskid, uint priority, uint stacksz, void (*fun)(void)); |
AndrewL | 0:1dafafe7d505 | 131 | |
AndrewL | 2:af930cdf7cce | 132 | /** Get the ID of the current task. |
AndrewL | 0:1dafafe7d505 | 133 | * |
AndrewL | 2:af930cdf7cce | 134 | * @returns The ID (0 .. 99) of the calling task. |
AndrewL | 0:1dafafe7d505 | 135 | */ |
AndrewL | 0:1dafafe7d505 | 136 | uint GetTask(void); |
AndrewL | 0:1dafafe7d505 | 137 | |
AndrewL | 2:af930cdf7cce | 138 | /** Set the priority of the current task. Does nothing if called from the idle task. |
AndrewL | 0:1dafafe7d505 | 139 | * |
AndrewL | 0:1dafafe7d505 | 140 | * @param priority Priority (0 .. 99) to apply to the calling task. |
AndrewL | 0:1dafafe7d505 | 141 | */ |
AndrewL | 0:1dafafe7d505 | 142 | void SetPriority(uint priority); |
AndrewL | 0:1dafafe7d505 | 143 | |
AndrewL | 1:b453bba9c5c0 | 144 | /** Get the priority of the current task. |
AndrewL | 0:1dafafe7d505 | 145 | * |
AndrewL | 2:af930cdf7cce | 146 | * @returns The priority (0 .. 99) of the calling task. |
AndrewL | 0:1dafafe7d505 | 147 | */ |
AndrewL | 0:1dafafe7d505 | 148 | uint GetPriority(void); |
AndrewL | 0:1dafafe7d505 | 149 | |
AndrewL | 2:af930cdf7cce | 150 | /** Wait for an event or events. Causes the current task to block, waiting for the |
AndrewL | 2:af930cdf7cce | 151 | * specified event. Does nothing if called from the idle task, or if the event is NULL. |
AndrewL | 0:1dafafe7d505 | 152 | * |
AndrewL | 1:b453bba9c5c0 | 153 | * @param event Event flag(s) to wait for. |
AndrewL | 0:1dafafe7d505 | 154 | */ |
AndrewL | 0:1dafafe7d505 | 155 | void WaitEvent(uint event); |
AndrewL | 0:1dafafe7d505 | 156 | |
AndrewL | 3:6cb5413f143f | 157 | /** Post an event or events to a task. |
AndrewL | 2:af930cdf7cce | 158 | * Posts the nominated event(s) to the specified task. Forces a context switch if the events |
AndrewL | 2:af930cdf7cce | 159 | * are posted successfully. Does nothing if the task is not waiting, or is not waiting for |
AndrewL | 2:af930cdf7cce | 160 | * the posted event. |
AndrewL | 0:1dafafe7d505 | 161 | * |
AndrewL | 0:1dafafe7d505 | 162 | * @param event Event flag(s) to post. |
AndrewL | 0:1dafafe7d505 | 163 | * @param task The ID of the task to which to post the event(s). May not be idle task. |
AndrewL | 0:1dafafe7d505 | 164 | */ |
AndrewL | 0:1dafafe7d505 | 165 | void SetEvent(uint event, uint task); |
AndrewL | 0:1dafafe7d505 | 166 | |
AndrewL | 2:af930cdf7cce | 167 | /** Returns the event flag(s) which last caused the task to unblock. |
AndrewL | 0:1dafafe7d505 | 168 | * |
AndrewL | 0:1dafafe7d505 | 169 | * @returns The event flags. |
AndrewL | 0:1dafafe7d505 | 170 | */ |
AndrewL | 0:1dafafe7d505 | 171 | uint GetEvent(void); |
AndrewL | 0:1dafafe7d505 | 172 | |
AndrewL | 2:af930cdf7cce | 173 | /** Create a mbos timer. Allocates and initialises the data structures for the timer. |
AndrewL | 0:1dafafe7d505 | 174 | * |
AndrewL | 2:af930cdf7cce | 175 | * @param timerid Unique ID for the timer (0 .. ntimers - 1). |
AndrewL | 2:af930cdf7cce | 176 | * @param taskid The ID of the task to which the timer will post events. May not be |
AndrewL | 2:af930cdf7cce | 177 | * the idle task. |
AndrewL | 0:1dafafe7d505 | 178 | * @param event The event flag(s) that the timer should post on timeout. May not be NULL. |
AndrewL | 0:1dafafe7d505 | 179 | */ |
AndrewL | 0:1dafafe7d505 | 180 | void CreateTimer(uint timerid, uint taskid, uint event); |
AndrewL | 0:1dafafe7d505 | 181 | |
AndrewL | 2:af930cdf7cce | 182 | /** Starts an mbos timer. If the reload time is zero or omitted, the timer will be reset |
AndrewL | 2:af930cdf7cce | 183 | * once it has posted a single event, after time milliseconds. If the reload time is |
AndrewL | 2:af930cdf7cce | 184 | * non-zero, this value will be loaded into the timer on time-out, and the timer will |
AndrewL | 2:af930cdf7cce | 185 | * continue indefinitely. In this case the interval to the first event will be time, |
AndrewL | 2:af930cdf7cce | 186 | * and the interval between subsequent events will be reloadtime. |
AndrewL | 0:1dafafe7d505 | 187 | * |
AndrewL | 2:af930cdf7cce | 188 | * @param timerid The ID of the timer. |
AndrewL | 0:1dafafe7d505 | 189 | * @param time The period in milliseconds before the timer times out. |
AndrewL | 0:1dafafe7d505 | 190 | * @param reload The optional time to reload into the timer when it times out. |
AndrewL | 0:1dafafe7d505 | 191 | */ |
AndrewL | 0:1dafafe7d505 | 192 | void SetTimer(uint timerid, uint time, uint reload = 0); |
AndrewL | 4:e740e08cbea9 | 193 | |
AndrewL | 4:e740e08cbea9 | 194 | /** Redirects an mbos timer. Changes the task and event associated with a timer. If the timer |
AndrewL | 4:e740e08cbea9 | 195 | * is running, the fun ction has no effect. |
AndrewL | 4:e740e08cbea9 | 196 | * |
AndrewL | 4:e740e08cbea9 | 197 | * @param timerid The ID of the timer. |
AndrewL | 4:e740e08cbea9 | 198 | * @param taskid The ID of the task to which the timer will post events. May not be |
AndrewL | 4:e740e08cbea9 | 199 | * the idle task. |
AndrewL | 4:e740e08cbea9 | 200 | * @param event The event flag(s) that the timer should post on timeout. May not be NULL. |
AndrewL | 4:e740e08cbea9 | 201 | */ |
AndrewL | 4:e740e08cbea9 | 202 | void RedirectTimer(uint timerid, uint taskid, uint event); |
AndrewL | 0:1dafafe7d505 | 203 | |
AndrewL | 2:af930cdf7cce | 204 | /** Stops and clears an mbos timer. |
AndrewL | 0:1dafafe7d505 | 205 | * |
AndrewL | 2:af930cdf7cce | 206 | * @param timerid The ID of the timer to clear. |
AndrewL | 0:1dafafe7d505 | 207 | */ |
AndrewL | 0:1dafafe7d505 | 208 | void ClearTimer(uint timerid); |
AndrewL | 0:1dafafe7d505 | 209 | |
AndrewL | 2:af930cdf7cce | 210 | /** Creates an mbos resource. Allocates and initialises the data structures for the Resource. |
AndrewL | 0:1dafafe7d505 | 211 | * |
AndrewL | 2:af930cdf7cce | 212 | * @param resourceid Unique ID for the resource (0 .. nresource). |
AndrewL | 2:af930cdf7cce | 213 | * @param priority Priority of the resource (normally > than that of any task using the |
AndrewL | 2:af930cdf7cce | 214 | * resource). |
AndrewL | 0:1dafafe7d505 | 215 | */ |
AndrewL | 0:1dafafe7d505 | 216 | void CreateResource(uint resourceid, uint priority); |
AndrewL | 0:1dafafe7d505 | 217 | |
AndrewL | 2:af930cdf7cce | 218 | /** Locks an mbos resource and temporarily allocates the resource's priority to the calling |
AndrewL | 2:af930cdf7cce | 219 | * task. |
AndrewL | 2:af930cdf7cce | 220 | * Does nothing if the resource is already locked, or if called from the idle task. |
AndrewL | 0:1dafafe7d505 | 221 | * |
AndrewL | 2:af930cdf7cce | 222 | * @param resourceid The ID of the resource to lock. |
AndrewL | 2:af930cdf7cce | 223 | * @returns Zero if the resource was locked successfully, or the ID of the task that is |
AndrewL | 2:af930cdf7cce | 224 | * currently locking the resource, if not. |
AndrewL | 0:1dafafe7d505 | 225 | */ |
AndrewL | 0:1dafafe7d505 | 226 | uint LockResource(uint resourceid); |
AndrewL | 0:1dafafe7d505 | 227 | |
AndrewL | 2:af930cdf7cce | 228 | /** Tests whether a resource is locked or free, without changing its state. |
AndrewL | 0:1dafafe7d505 | 229 | * |
AndrewL | 2:af930cdf7cce | 230 | * @param resourceid The ID of the resouce to test. |
AndrewL | 2:af930cdf7cce | 231 | * @returns Zero if the resource is free, or the ID of the task that is currently |
AndrewL | 2:af930cdf7cce | 232 | * locking the resouce , if not. |
AndrewL | 0:1dafafe7d505 | 233 | |
AndrewL | 0:1dafafe7d505 | 234 | */ |
AndrewL | 0:1dafafe7d505 | 235 | uint TestResource(uint resourceid); |
AndrewL | 0:1dafafe7d505 | 236 | |
AndrewL | 0:1dafafe7d505 | 237 | /** Frees a resource |
AndrewL | 2:af930cdf7cce | 238 | * Frees an mbos resource and restores the calling task's original priority. Does nothing |
AndrewL | 2:af930cdf7cce | 239 | * if the resource is already free, if called from the idle task, or the resource was |
AndrewL | 2:af930cdf7cce | 240 | * locked by a different task. |
AndrewL | 0:1dafafe7d505 | 241 | * |
AndrewL | 2:af930cdf7cce | 242 | * @param resourceid The ID of the resource t free. |
AndrewL | 2:af930cdf7cce | 243 | * @returns Zero if the resource was freed successfully, or the ID of the task that is |
AndrewL | 2:af930cdf7cce | 244 | * locking the resource, if not. |
AndrewL | 0:1dafafe7d505 | 245 | */ |
AndrewL | 0:1dafafe7d505 | 246 | uint FreeResource(uint resource); |
AndrewL | 0:1dafafe7d505 | 247 | |
AndrewL | 0:1dafafe7d505 | 248 | private: |
AndrewL | 0:1dafafe7d505 | 249 | uint* _initstack(uint *stack, void (*fun)()); |
AndrewL | 0:1dafafe7d505 | 250 | }; |
AndrewL | 0:1dafafe7d505 | 251 | #endif |