x
Dependencies: BLE_API mbed-dev-bin nRF51822
Fork of microbit-dal by
inc/core/MicroBitFiber.h@1:8aa5cdb4ab67, 2016-04-07 (annotated)
- Committer:
- Jonathan Austin
- Date:
- Thu Apr 07 01:33:22 2016 +0100
- Revision:
- 1:8aa5cdb4ab67
- Child:
- 41:da05ec75cd5d
Synchronized with git rev 55cb9199
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Jonathan Austin |
1:8aa5cdb4ab67 | 1 | /* |
Jonathan Austin |
1:8aa5cdb4ab67 | 2 | The MIT License (MIT) |
Jonathan Austin |
1:8aa5cdb4ab67 | 3 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 4 | Copyright (c) 2016 British Broadcasting Corporation. |
Jonathan Austin |
1:8aa5cdb4ab67 | 5 | This software is provided by Lancaster University by arrangement with the BBC. |
Jonathan Austin |
1:8aa5cdb4ab67 | 6 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 7 | Permission is hereby granted, free of charge, to any person obtaining a |
Jonathan Austin |
1:8aa5cdb4ab67 | 8 | copy of this software and associated documentation files (the "Software"), |
Jonathan Austin |
1:8aa5cdb4ab67 | 9 | to deal in the Software without restriction, including without limitation |
Jonathan Austin |
1:8aa5cdb4ab67 | 10 | the rights to use, copy, modify, merge, publish, distribute, sublicense, |
Jonathan Austin |
1:8aa5cdb4ab67 | 11 | and/or sell copies of the Software, and to permit persons to whom the |
Jonathan Austin |
1:8aa5cdb4ab67 | 12 | Software is furnished to do so, subject to the following conditions: |
Jonathan Austin |
1:8aa5cdb4ab67 | 13 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 14 | The above copyright notice and this permission notice shall be included in |
Jonathan Austin |
1:8aa5cdb4ab67 | 15 | all copies or substantial portions of the Software. |
Jonathan Austin |
1:8aa5cdb4ab67 | 16 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
Jonathan Austin |
1:8aa5cdb4ab67 | 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
Jonathan Austin |
1:8aa5cdb4ab67 | 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
Jonathan Austin |
1:8aa5cdb4ab67 | 20 | THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
Jonathan Austin |
1:8aa5cdb4ab67 | 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
Jonathan Austin |
1:8aa5cdb4ab67 | 22 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
Jonathan Austin |
1:8aa5cdb4ab67 | 23 | DEALINGS IN THE SOFTWARE. |
Jonathan Austin |
1:8aa5cdb4ab67 | 24 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 25 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 26 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 27 | * Functionality definitions for the MicroBit Fiber scheduler. |
Jonathan Austin |
1:8aa5cdb4ab67 | 28 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 29 | * This lightweight, non-preemptive scheduler provides a simple threading mechanism for two main purposes: |
Jonathan Austin |
1:8aa5cdb4ab67 | 30 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 31 | * 1) To provide a clean abstraction for application languages to use when building async behaviour (callbacks). |
Jonathan Austin |
1:8aa5cdb4ab67 | 32 | * 2) To provide ISR decoupling for EventModel events generated in an ISR context. |
Jonathan Austin |
1:8aa5cdb4ab67 | 33 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 34 | * TODO: Consider a split mode scheduler, that monitors used stack size, and maintains a dedicated, persistent |
Jonathan Austin |
1:8aa5cdb4ab67 | 35 | * stack for any long lived fibers with large stack |
Jonathan Austin |
1:8aa5cdb4ab67 | 36 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 37 | #ifndef MICROBIT_FIBER_H |
Jonathan Austin |
1:8aa5cdb4ab67 | 38 | #define MICROBIT_FIBER_H |
Jonathan Austin |
1:8aa5cdb4ab67 | 39 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 40 | #include "mbed.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 41 | #include "MicroBitConfig.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 42 | #include "MicroBitEvent.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 43 | #include "EventModel.h" |
Jonathan Austin |
1:8aa5cdb4ab67 | 44 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 45 | // Fiber Scheduler Flags |
Jonathan Austin |
1:8aa5cdb4ab67 | 46 | #define MICROBIT_SCHEDULER_RUNNING 0x01 |
Jonathan Austin |
1:8aa5cdb4ab67 | 47 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 48 | // Fiber Flags |
Jonathan Austin |
1:8aa5cdb4ab67 | 49 | #define MICROBIT_FIBER_FLAG_FOB 0x01 |
Jonathan Austin |
1:8aa5cdb4ab67 | 50 | #define MICROBIT_FIBER_FLAG_PARENT 0x02 |
Jonathan Austin |
1:8aa5cdb4ab67 | 51 | #define MICROBIT_FIBER_FLAG_CHILD 0x04 |
Jonathan Austin |
1:8aa5cdb4ab67 | 52 | #define MICROBIT_FIBER_FLAG_DO_NOT_PAGE 0x08 |
Jonathan Austin |
1:8aa5cdb4ab67 | 53 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 54 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 55 | * Thread Context for an ARM Cortex M0 core. |
Jonathan Austin |
1:8aa5cdb4ab67 | 56 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 57 | * This is probably overkill, but the ARMCC compiler uses a lot register optimisation |
Jonathan Austin |
1:8aa5cdb4ab67 | 58 | * in its calling conventions, so better safe than sorry! |
Jonathan Austin |
1:8aa5cdb4ab67 | 59 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 60 | struct Cortex_M0_TCB |
Jonathan Austin |
1:8aa5cdb4ab67 | 61 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 62 | uint32_t R0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 63 | uint32_t R1; |
Jonathan Austin |
1:8aa5cdb4ab67 | 64 | uint32_t R2; |
Jonathan Austin |
1:8aa5cdb4ab67 | 65 | uint32_t R3; |
Jonathan Austin |
1:8aa5cdb4ab67 | 66 | uint32_t R4; |
Jonathan Austin |
1:8aa5cdb4ab67 | 67 | uint32_t R5; |
Jonathan Austin |
1:8aa5cdb4ab67 | 68 | uint32_t R6; |
Jonathan Austin |
1:8aa5cdb4ab67 | 69 | uint32_t R7; |
Jonathan Austin |
1:8aa5cdb4ab67 | 70 | uint32_t R8; |
Jonathan Austin |
1:8aa5cdb4ab67 | 71 | uint32_t R9; |
Jonathan Austin |
1:8aa5cdb4ab67 | 72 | uint32_t R10; |
Jonathan Austin |
1:8aa5cdb4ab67 | 73 | uint32_t R11; |
Jonathan Austin |
1:8aa5cdb4ab67 | 74 | uint32_t R12; |
Jonathan Austin |
1:8aa5cdb4ab67 | 75 | uint32_t SP; |
Jonathan Austin |
1:8aa5cdb4ab67 | 76 | uint32_t LR; |
Jonathan Austin |
1:8aa5cdb4ab67 | 77 | uint32_t stack_base; |
Jonathan Austin |
1:8aa5cdb4ab67 | 78 | }; |
Jonathan Austin |
1:8aa5cdb4ab67 | 79 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 80 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 81 | * Representation of a single Fiber |
Jonathan Austin |
1:8aa5cdb4ab67 | 82 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 83 | struct Fiber |
Jonathan Austin |
1:8aa5cdb4ab67 | 84 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 85 | Cortex_M0_TCB tcb; // Thread context when last scheduled out. |
Jonathan Austin |
1:8aa5cdb4ab67 | 86 | uint32_t stack_bottom; // The start address of this Fiber's stack. The stack is heap allocated, and full descending. |
Jonathan Austin |
1:8aa5cdb4ab67 | 87 | uint32_t stack_top; // The end address of this Fiber's stack. |
Jonathan Austin |
1:8aa5cdb4ab67 | 88 | uint32_t context; // Context specific information. |
Jonathan Austin |
1:8aa5cdb4ab67 | 89 | uint32_t flags; // Information about this fiber. |
Jonathan Austin |
1:8aa5cdb4ab67 | 90 | Fiber **queue; // The queue this fiber is stored on. |
Jonathan Austin |
1:8aa5cdb4ab67 | 91 | Fiber *next, *prev; // Position of this Fiber on the run queue. |
Jonathan Austin |
1:8aa5cdb4ab67 | 92 | }; |
Jonathan Austin |
1:8aa5cdb4ab67 | 93 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 94 | extern Fiber *currentFiber; |
Jonathan Austin |
1:8aa5cdb4ab67 | 95 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 96 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 97 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 98 | * Initialises the Fiber scheduler. |
Jonathan Austin |
1:8aa5cdb4ab67 | 99 | * Creates a Fiber context around the calling thread, and adds it to the run queue as the current thread. |
Jonathan Austin |
1:8aa5cdb4ab67 | 100 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 101 | * This function must be called once only from the main thread, and before any other Fiber operation. |
Jonathan Austin |
1:8aa5cdb4ab67 | 102 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 103 | * @param _messageBus An event model, used to direct the priorities of the scheduler. |
Jonathan Austin |
1:8aa5cdb4ab67 | 104 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 105 | void scheduler_init(EventModel &_messageBus); |
Jonathan Austin |
1:8aa5cdb4ab67 | 106 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 107 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 108 | * Determines if the fiber scheduler is operational. |
Jonathan Austin |
1:8aa5cdb4ab67 | 109 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 110 | * @return 1 if the fber scheduler is running, 0 otherwise. |
Jonathan Austin |
1:8aa5cdb4ab67 | 111 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 112 | int fiber_scheduler_running(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 113 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 114 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 115 | * Exit point for all fibers. |
Jonathan Austin |
1:8aa5cdb4ab67 | 116 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 117 | * Any fiber reaching the end of its entry function will return here for recycling. |
Jonathan Austin |
1:8aa5cdb4ab67 | 118 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 119 | void release_fiber(void); |
Jonathan Austin |
1:8aa5cdb4ab67 | 120 | void release_fiber(void *param); |
Jonathan Austin |
1:8aa5cdb4ab67 | 121 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 122 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 123 | * Launches a fiber. |
Jonathan Austin |
1:8aa5cdb4ab67 | 124 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 125 | * @param ep the entry point for the fiber. |
Jonathan Austin |
1:8aa5cdb4ab67 | 126 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 127 | * @param cp the completion routine after ep has finished execution |
Jonathan Austin |
1:8aa5cdb4ab67 | 128 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 129 | void launch_new_fiber(void (*ep)(void), void (*cp)(void)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 130 | #ifdef __GCC__ |
Jonathan Austin |
1:8aa5cdb4ab67 | 131 | __attribute__((naked)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 132 | #endif |
Jonathan Austin |
1:8aa5cdb4ab67 | 133 | ; |
Jonathan Austin |
1:8aa5cdb4ab67 | 134 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 135 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 136 | * Launches a fiber with a parameter |
Jonathan Austin |
1:8aa5cdb4ab67 | 137 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 138 | * @param ep the entry point for the fiber. |
Jonathan Austin |
1:8aa5cdb4ab67 | 139 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 140 | * @param cp the completion routine after ep has finished execution |
Jonathan Austin |
1:8aa5cdb4ab67 | 141 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 142 | * @param pm the parameter to provide to ep and cp. |
Jonathan Austin |
1:8aa5cdb4ab67 | 143 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 144 | void launch_new_fiber_param(void (*ep)(void *), void (*cp)(void *), void *pm) |
Jonathan Austin |
1:8aa5cdb4ab67 | 145 | #ifdef __GCC__ |
Jonathan Austin |
1:8aa5cdb4ab67 | 146 | __attribute__((naked)) |
Jonathan Austin |
1:8aa5cdb4ab67 | 147 | #endif |
Jonathan Austin |
1:8aa5cdb4ab67 | 148 | ; |
Jonathan Austin |
1:8aa5cdb4ab67 | 149 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 150 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 151 | * Creates a new Fiber, and launches it. |
Jonathan Austin |
1:8aa5cdb4ab67 | 152 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 153 | * @param entry_fn The function the new Fiber will begin execution in. |
Jonathan Austin |
1:8aa5cdb4ab67 | 154 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 155 | * @param completion_fn The function called when the thread completes execution of entry_fn. |
Jonathan Austin |
1:8aa5cdb4ab67 | 156 | * Defaults to release_fiber. |
Jonathan Austin |
1:8aa5cdb4ab67 | 157 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 158 | * @return The new Fiber, or NULL if the operation could not be completed. |
Jonathan Austin |
1:8aa5cdb4ab67 | 159 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 160 | Fiber *create_fiber(void (*entry_fn)(void), void (*completion_fn)(void) = release_fiber); |
Jonathan Austin |
1:8aa5cdb4ab67 | 161 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 162 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 163 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 164 | * Creates a new parameterised Fiber, and launches it. |
Jonathan Austin |
1:8aa5cdb4ab67 | 165 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 166 | * @param entry_fn The function the new Fiber will begin execution in. |
Jonathan Austin |
1:8aa5cdb4ab67 | 167 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 168 | * @param param an untyped parameter passed into the entry_fn and completion_fn. |
Jonathan Austin |
1:8aa5cdb4ab67 | 169 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 170 | * @param completion_fn The function called when the thread completes execution of entry_fn. |
Jonathan Austin |
1:8aa5cdb4ab67 | 171 | * Defaults to release_fiber. |
Jonathan Austin |
1:8aa5cdb4ab67 | 172 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 173 | * @return The new Fiber, or NULL if the operation could not be completed. |
Jonathan Austin |
1:8aa5cdb4ab67 | 174 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 175 | Fiber *create_fiber(void (*entry_fn)(void *), void *param, void (*completion_fn)(void *) = release_fiber); |
Jonathan Austin |
1:8aa5cdb4ab67 | 176 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 177 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 178 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 179 | * Calls the Fiber scheduler. |
Jonathan Austin |
1:8aa5cdb4ab67 | 180 | * The calling Fiber will likely be blocked, and control given to another waiting fiber. |
Jonathan Austin |
1:8aa5cdb4ab67 | 181 | * Call this function to yield control of the processor when you have nothing more to do. |
Jonathan Austin |
1:8aa5cdb4ab67 | 182 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 183 | void schedule(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 184 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 185 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 186 | * Blocks the calling thread for the given period of time. |
Jonathan Austin |
1:8aa5cdb4ab67 | 187 | * The calling thread will be immediateley descheduled, and placed onto a |
Jonathan Austin |
1:8aa5cdb4ab67 | 188 | * wait queue until the requested amount of time has elapsed. |
Jonathan Austin |
1:8aa5cdb4ab67 | 189 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 190 | * @param t The period of time to sleep, in milliseconds. |
Jonathan Austin |
1:8aa5cdb4ab67 | 191 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 192 | * @note the fiber will not be be made runnable until after the elapsed time, but there |
Jonathan Austin |
1:8aa5cdb4ab67 | 193 | * are no guarantees precisely when the fiber will next be scheduled. |
Jonathan Austin |
1:8aa5cdb4ab67 | 194 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 195 | void fiber_sleep(unsigned long t); |
Jonathan Austin |
1:8aa5cdb4ab67 | 196 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 197 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 198 | * The timer callback, called from interrupt context once every SYSTEM_TICK_PERIOD_MS milliseconds. |
Jonathan Austin |
1:8aa5cdb4ab67 | 199 | * This function checks to determine if any fibers blocked on the sleep queue need to be woken up |
Jonathan Austin |
1:8aa5cdb4ab67 | 200 | * and made runnable. |
Jonathan Austin |
1:8aa5cdb4ab67 | 201 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 202 | void scheduler_tick(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 203 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 204 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 205 | * Blocks the calling thread until the specified event is raised. |
Jonathan Austin |
1:8aa5cdb4ab67 | 206 | * The calling thread will be immediateley descheduled, and placed onto a |
Jonathan Austin |
1:8aa5cdb4ab67 | 207 | * wait queue until the requested event is received. |
Jonathan Austin |
1:8aa5cdb4ab67 | 208 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 209 | * @param id The ID field of the event to listen for (e.g. MICROBIT_ID_BUTTON_A) |
Jonathan Austin |
1:8aa5cdb4ab67 | 210 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 211 | * @param value The value of the event to listen for (e.g. MICROBIT_BUTTON_EVT_CLICK) |
Jonathan Austin |
1:8aa5cdb4ab67 | 212 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 213 | * @return MICROBIT_OK, or MICROBIT_NOT_SUPPORTED if the fiber scheduler is not running, or associated with an EventModel. |
Jonathan Austin |
1:8aa5cdb4ab67 | 214 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 215 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 216 | * fiber_wait_for_event(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK); |
Jonathan Austin |
1:8aa5cdb4ab67 | 217 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 218 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 219 | * @note the fiber will not be be made runnable until after the event is raised, but there |
Jonathan Austin |
1:8aa5cdb4ab67 | 220 | * are no guarantees precisely when the fiber will next be scheduled. |
Jonathan Austin |
1:8aa5cdb4ab67 | 221 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 222 | int fiber_wait_for_event(uint16_t id, uint16_t value); |
Jonathan Austin |
1:8aa5cdb4ab67 | 223 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 224 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 225 | * Configures the fiber context for the current fiber to block on an event ID |
Jonathan Austin |
1:8aa5cdb4ab67 | 226 | * and value, but does not deschedule the fiber. |
Jonathan Austin |
1:8aa5cdb4ab67 | 227 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 228 | * @param id The ID field of the event to listen for (e.g. MICROBIT_ID_BUTTON_A) |
Jonathan Austin |
1:8aa5cdb4ab67 | 229 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 230 | * @param value The value of the event to listen for (e.g. MICROBIT_BUTTON_EVT_CLICK) |
Jonathan Austin |
1:8aa5cdb4ab67 | 231 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 232 | * @return MICROBIT_OK, or MICROBIT_NOT_SUPPORTED if the fiber scheduler is not running, or associated with an EventModel. |
Jonathan Austin |
1:8aa5cdb4ab67 | 233 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 234 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 235 | * fiber_wake_on_event(MICROBIT_ID_BUTTON_A, MICROBIT_BUTTON_EVT_CLICK); |
Jonathan Austin |
1:8aa5cdb4ab67 | 236 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 237 | * //perform some time critical operation. |
Jonathan Austin |
1:8aa5cdb4ab67 | 238 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 239 | * //deschedule the current fiber manually, waiting for the previously configured event. |
Jonathan Austin |
1:8aa5cdb4ab67 | 240 | * schedule(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 241 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 242 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 243 | int fiber_wake_on_event(uint16_t id, uint16_t value); |
Jonathan Austin |
1:8aa5cdb4ab67 | 244 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 245 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 246 | * Executes the given function asynchronously if necessary. |
Jonathan Austin |
1:8aa5cdb4ab67 | 247 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 248 | * Fibers are often used to run event handlers, however many of these event handlers are very simple functions |
Jonathan Austin |
1:8aa5cdb4ab67 | 249 | * that complete very quickly, bringing unecessary RAM overhead. |
Jonathan Austin |
1:8aa5cdb4ab67 | 250 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 251 | * This function takes a snapshot of the current processor context, then attempts to optimistically call the given function directly. |
Jonathan Austin |
1:8aa5cdb4ab67 | 252 | * We only create an additional fiber if that function performs a block operation. |
Jonathan Austin |
1:8aa5cdb4ab67 | 253 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 254 | * @param entry_fn The function to execute. |
Jonathan Austin |
1:8aa5cdb4ab67 | 255 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 256 | * @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER. |
Jonathan Austin |
1:8aa5cdb4ab67 | 257 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 258 | int invoke(void (*entry_fn)(void)); |
Jonathan Austin |
1:8aa5cdb4ab67 | 259 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 260 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 261 | * Executes the given function asynchronously if necessary, and offers the ability to provide a parameter. |
Jonathan Austin |
1:8aa5cdb4ab67 | 262 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 263 | * Fibers are often used to run event handlers, however many of these event handlers are very simple functions |
Jonathan Austin |
1:8aa5cdb4ab67 | 264 | * that complete very quickly, bringing unecessary RAM. overhead |
Jonathan Austin |
1:8aa5cdb4ab67 | 265 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 266 | * This function takes a snapshot of the current fiber context, then attempt to optimistically call the given function directly. |
Jonathan Austin |
1:8aa5cdb4ab67 | 267 | * We only create an additional fiber if that function performs a block operation. |
Jonathan Austin |
1:8aa5cdb4ab67 | 268 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 269 | * @param entry_fn The function to execute. |
Jonathan Austin |
1:8aa5cdb4ab67 | 270 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 271 | * @param param an untyped parameter passed into the entry_fn and completion_fn. |
Jonathan Austin |
1:8aa5cdb4ab67 | 272 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 273 | * @return MICROBIT_OK, or MICROBIT_INVALID_PARAMETER. |
Jonathan Austin |
1:8aa5cdb4ab67 | 274 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 275 | int invoke(void (*entry_fn)(void *), void *param); |
Jonathan Austin |
1:8aa5cdb4ab67 | 276 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 277 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 278 | * Resizes the stack allocation of the current fiber if necessary to hold the system stack. |
Jonathan Austin |
1:8aa5cdb4ab67 | 279 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 280 | * If the stack allocation is large enough to hold the current system stack, then this function does nothing. |
Jonathan Austin |
1:8aa5cdb4ab67 | 281 | * Otherwise, the the current allocation of the fiber is freed, and a larger block is allocated. |
Jonathan Austin |
1:8aa5cdb4ab67 | 282 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 283 | * @param f The fiber context to verify. |
Jonathan Austin |
1:8aa5cdb4ab67 | 284 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 285 | * @return The stack depth of the given fiber. |
Jonathan Austin |
1:8aa5cdb4ab67 | 286 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 287 | inline void verify_stack_size(Fiber *f); |
Jonathan Austin |
1:8aa5cdb4ab67 | 288 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 289 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 290 | * Event callback. Called from an instance of MicroBitMessageBus whenever an event is raised. |
Jonathan Austin |
1:8aa5cdb4ab67 | 291 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 292 | * This function checks to determine if any fibers blocked on the wait queue need to be woken up |
Jonathan Austin |
1:8aa5cdb4ab67 | 293 | * and made runnable due to the event. |
Jonathan Austin |
1:8aa5cdb4ab67 | 294 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 295 | * @param evt the event that has just been raised on an instance of MicroBitMessageBus. |
Jonathan Austin |
1:8aa5cdb4ab67 | 296 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 297 | void scheduler_event(MicroBitEvent evt); |
Jonathan Austin |
1:8aa5cdb4ab67 | 298 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 299 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 300 | * Determines if any fibers are waiting to be scheduled. |
Jonathan Austin |
1:8aa5cdb4ab67 | 301 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 302 | * @return The number of fibers currently on the run queue |
Jonathan Austin |
1:8aa5cdb4ab67 | 303 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 304 | int scheduler_runqueue_empty(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 305 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 306 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 307 | * Utility function to add the currenty running fiber to the given queue. |
Jonathan Austin |
1:8aa5cdb4ab67 | 308 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 309 | * Perform a simple add at the head, to avoid complexity, |
Jonathan Austin |
1:8aa5cdb4ab67 | 310 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 311 | * Queues are normally very short, so maintaining a doubly linked, sorted list typically outweighs the cost of |
Jonathan Austin |
1:8aa5cdb4ab67 | 312 | * brute force searching. |
Jonathan Austin |
1:8aa5cdb4ab67 | 313 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 314 | * @param f The fiber to add to the queue |
Jonathan Austin |
1:8aa5cdb4ab67 | 315 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 316 | * @param queue The run queue to add the fiber to. |
Jonathan Austin |
1:8aa5cdb4ab67 | 317 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 318 | void queue_fiber(Fiber *f, Fiber **queue); |
Jonathan Austin |
1:8aa5cdb4ab67 | 319 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 320 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 321 | * Utility function to the given fiber from whichever queue it is currently stored on. |
Jonathan Austin |
1:8aa5cdb4ab67 | 322 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 323 | * @param f the fiber to remove. |
Jonathan Austin |
1:8aa5cdb4ab67 | 324 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 325 | void dequeue_fiber(Fiber *f); |
Jonathan Austin |
1:8aa5cdb4ab67 | 326 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 327 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 328 | * Set of tasks to perform when idle. |
Jonathan Austin |
1:8aa5cdb4ab67 | 329 | * Service any background tasks that are required, and attempt a power efficient sleep. |
Jonathan Austin |
1:8aa5cdb4ab67 | 330 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 331 | void idle(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 332 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 333 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 334 | * The idle task, which is called when the runtime has no fibers that require execution. |
Jonathan Austin |
1:8aa5cdb4ab67 | 335 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 336 | * This function typically calls idle(). |
Jonathan Austin |
1:8aa5cdb4ab67 | 337 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 338 | void idle_task(); |
Jonathan Austin |
1:8aa5cdb4ab67 | 339 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 340 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 341 | * Adds a component to the array of idle thread components, which are processed |
Jonathan Austin |
1:8aa5cdb4ab67 | 342 | * when the run queue is empty. |
Jonathan Austin |
1:8aa5cdb4ab67 | 343 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 344 | * The system timer will poll isIdleCallbackNeeded on each component to determine |
Jonathan Austin |
1:8aa5cdb4ab67 | 345 | * if the scheduler should schedule the idle_task imminently. |
Jonathan Austin |
1:8aa5cdb4ab67 | 346 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 347 | * @param component The component to add to the array. |
Jonathan Austin |
1:8aa5cdb4ab67 | 348 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 349 | * @return MICROBIT_OK on success or MICROBIT_NO_RESOURCES if the fiber components array is full. |
Jonathan Austin |
1:8aa5cdb4ab67 | 350 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 351 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 352 | * MicroBitI2C i2c(I2C_SDA0, I2C_SCL0); |
Jonathan Austin |
1:8aa5cdb4ab67 | 353 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 354 | * // heap allocated - otherwise it will be paged out! |
Jonathan Austin |
1:8aa5cdb4ab67 | 355 | * MicroBitAccelerometer* accelerometer = new MicroBitAccelerometer(i2c); |
Jonathan Austin |
1:8aa5cdb4ab67 | 356 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 357 | * fiber_add_idle_component(accelerometer); |
Jonathan Austin |
1:8aa5cdb4ab67 | 358 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 359 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 360 | int fiber_add_idle_component(MicroBitComponent *component); |
Jonathan Austin |
1:8aa5cdb4ab67 | 361 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 362 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 363 | * Remove a component from the array of idle thread components |
Jonathan Austin |
1:8aa5cdb4ab67 | 364 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 365 | * @param component The component to remove from the idle component array. |
Jonathan Austin |
1:8aa5cdb4ab67 | 366 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 367 | * @return MICROBIT_OK on success. MICROBIT_INVALID_PARAMETER is returned if the given component has not been previously added. |
Jonathan Austin |
1:8aa5cdb4ab67 | 368 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 369 | * @code |
Jonathan Austin |
1:8aa5cdb4ab67 | 370 | * MicroBitI2C i2c(I2C_SDA0, I2C_SCL0); |
Jonathan Austin |
1:8aa5cdb4ab67 | 371 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 372 | * // heap allocated - otherwise it will be paged out! |
Jonathan Austin |
1:8aa5cdb4ab67 | 373 | * MicroBitAccelerometer* accelerometer = new MicroBitAccelerometer(i2c); |
Jonathan Austin |
1:8aa5cdb4ab67 | 374 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 375 | * fiber_add_idle_component(accelerometer); |
Jonathan Austin |
1:8aa5cdb4ab67 | 376 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 377 | * fiber_remove_idle_component(accelerometer); |
Jonathan Austin |
1:8aa5cdb4ab67 | 378 | * @endcode |
Jonathan Austin |
1:8aa5cdb4ab67 | 379 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 380 | int fiber_remove_idle_component(MicroBitComponent *component); |
Jonathan Austin |
1:8aa5cdb4ab67 | 381 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 382 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 383 | * Determines if the processor is executing in interrupt context. |
Jonathan Austin |
1:8aa5cdb4ab67 | 384 | * |
Jonathan Austin |
1:8aa5cdb4ab67 | 385 | * @return true if any the processor is currently executing any interrupt service routine. False otherwise. |
Jonathan Austin |
1:8aa5cdb4ab67 | 386 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 387 | inline int inInterruptContext() |
Jonathan Austin |
1:8aa5cdb4ab67 | 388 | { |
Jonathan Austin |
1:8aa5cdb4ab67 | 389 | return (((int)__get_IPSR()) & 0x003F) > 0; |
Jonathan Austin |
1:8aa5cdb4ab67 | 390 | } |
Jonathan Austin |
1:8aa5cdb4ab67 | 391 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 392 | /** |
Jonathan Austin |
1:8aa5cdb4ab67 | 393 | * Assembler Context switch routing. |
Jonathan Austin |
1:8aa5cdb4ab67 | 394 | * Defined in CortexContextSwitch.s. |
Jonathan Austin |
1:8aa5cdb4ab67 | 395 | */ |
Jonathan Austin |
1:8aa5cdb4ab67 | 396 | extern "C" void swap_context(Cortex_M0_TCB *from, Cortex_M0_TCB *to, uint32_t from_stack, uint32_t to_stack); |
Jonathan Austin |
1:8aa5cdb4ab67 | 397 | extern "C" void save_context(Cortex_M0_TCB *tcb, uint32_t stack); |
Jonathan Austin |
1:8aa5cdb4ab67 | 398 | extern "C" void save_register_context(Cortex_M0_TCB *tcb); |
Jonathan Austin |
1:8aa5cdb4ab67 | 399 | extern "C" void restore_register_context(Cortex_M0_TCB *tcb); |
Jonathan Austin |
1:8aa5cdb4ab67 | 400 | |
Jonathan Austin |
1:8aa5cdb4ab67 | 401 | #endif |