Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 | 
