Raul Martin / EventFramework Featured

Dependents:   sensors_KL46Z_xmn

Committer:
raulMrello
Date:
Mon Oct 01 10:38:45 2012 +0000
Revision:
0:9d09acc8f9d9
Release 1.00; EventFramework library allows the creation of an event-driven infrastructure for lightweight multithreaded applications with cooperative or fully-preemptive scheduling.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
raulMrello 0:9d09acc8f9d9 1 /* mbed EventFramework Library
raulMrello 0:9d09acc8f9d9 2 * Copyright (c) 2012 raulMrello
raulMrello 0:9d09acc8f9d9 3 *
raulMrello 0:9d09acc8f9d9 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
raulMrello 0:9d09acc8f9d9 5 * of this software and associated documentation files (the "Software"), to deal
raulMrello 0:9d09acc8f9d9 6 * in the Software without restriction, including without limitation the rights
raulMrello 0:9d09acc8f9d9 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
raulMrello 0:9d09acc8f9d9 8 * copies of the Software, and to permit persons to whom the Software is
raulMrello 0:9d09acc8f9d9 9 * furnished to do so, subject to the following conditions:
raulMrello 0:9d09acc8f9d9 10 *
raulMrello 0:9d09acc8f9d9 11 * The above copyright notice and this permission notice shall be included in
raulMrello 0:9d09acc8f9d9 12 * all copies or substantial portions of the Software.
raulMrello 0:9d09acc8f9d9 13 *
raulMrello 0:9d09acc8f9d9 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
raulMrello 0:9d09acc8f9d9 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
raulMrello 0:9d09acc8f9d9 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
raulMrello 0:9d09acc8f9d9 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
raulMrello 0:9d09acc8f9d9 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
raulMrello 0:9d09acc8f9d9 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
raulMrello 0:9d09acc8f9d9 20 * THE SOFTWARE.
raulMrello 0:9d09acc8f9d9 21 */
raulMrello 0:9d09acc8f9d9 22
raulMrello 0:9d09acc8f9d9 23 #ifndef _EVENT_FRAMEWORK_H_
raulMrello 0:9d09acc8f9d9 24 #define _EVENT_FRAMEWORK_H_
raulMrello 0:9d09acc8f9d9 25
raulMrello 0:9d09acc8f9d9 26 #include "../Types/Types.h"
raulMrello 0:9d09acc8f9d9 27 #include "../Event/Event.h"
raulMrello 0:9d09acc8f9d9 28 #include "../EventHandler/EventHandler.h"
raulMrello 0:9d09acc8f9d9 29 #include "../List/List.h"
raulMrello 0:9d09acc8f9d9 30
raulMrello 0:9d09acc8f9d9 31 /** EventFramework class
raulMrello 0:9d09acc8f9d9 32 *
raulMrello 0:9d09acc8f9d9 33 * EventFramework class allows the creation of an event-driven infrastructure in which small "threads" (EventHandler
raulMrello 0:9d09acc8f9d9 34 * instances) can handle events in a multithreaded execution context. As other traditional RTOSes, the EventFramework
raulMrello 0:9d09acc8f9d9 35 * can be configured to act as a cooperative or a fully-preemptive kernel with fixed-priority scheduling.
raulMrello 0:9d09acc8f9d9 36 * Furthermore, this kernel matches run-to-completion semantics, and hence a single-stack configuration
raulMrello 0:9d09acc8f9d9 37 * is enough to keep running this multithreaded execution environment. As all running tasks shares processor's
raulMrello 0:9d09acc8f9d9 38 * stack, a huge quantity of RAM is saved in contrast with traditional RTOSes.
raulMrello 0:9d09acc8f9d9 39 * This Framework has been designed to be extremely simple, but still powerful. Let's try it. Here comes an
raulMrello 0:9d09acc8f9d9 40 * example of use:
raulMrello 0:9d09acc8f9d9 41 *
raulMrello 0:9d09acc8f9d9 42 * @code
raulMrello 0:9d09acc8f9d9 43 * // Configuring and starting an EventFramework-based application formed by two threads who interchanges two events.
raulMrello 0:9d09acc8f9d9 44 * #include "mbed.h"
raulMrello 0:9d09acc8f9d9 45 * #include "EventFramework.h"
raulMrello 0:9d09acc8f9d9 46 *
raulMrello 0:9d09acc8f9d9 47 * // framework creation with fully-preemptive scheduling mechanism.
raulMrello 0:9d09acc8f9d9 48 * EventFramework kernel(EventFramework::SCHED_VALUE_PREEMPTIVE);
raulMrello 0:9d09acc8f9d9 49 *
raulMrello 0:9d09acc8f9d9 50 * // Events creation with priorities 0(max) and 65535(min).
raulMrello 0:9d09acc8f9d9 51 * Event ev1(65535);
raulMrello 0:9d09acc8f9d9 52 * Event ev2(0);
raulMrello 0:9d09acc8f9d9 53 *
raulMrello 0:9d09acc8f9d9 54 * // EventHandlers creation with priorities 0(max) and 65535(min)
raulMrello 0:9d09acc8f9d9 55 * EventHandler eh1(0);
raulMrello 0:9d09acc8f9d9 56 * EventHandler eh2(65535);
raulMrello 0:9d09acc8f9d9 57 *
raulMrello 0:9d09acc8f9d9 58 * // declaration of event dispatching functions that will be attached to previous EventHandlers
raulMrello 0:9d09acc8f9d9 59 * EventDispatchingRoutine ev1_handle_func;
raulMrello 0:9d09acc8f9d9 60 * EventDispatchingRoutine ev2_handle_func;
raulMrello 0:9d09acc8f9d9 61 *
raulMrello 0:9d09acc8f9d9 62 * int main() {
raulMrello 0:9d09acc8f9d9 63 * // events must be registered into the framework
raulMrello 0:9d09acc8f9d9 64 * kernel.AddEvent(&ev1);
raulMrello 0:9d09acc8f9d9 65 * kernel.AddEvent(&ev1);
raulMrello 0:9d09acc8f9d9 66 *
raulMrello 0:9d09acc8f9d9 67 * // handle [eh1] will process [ev1] events through [ev1_handle_func] routine. So it must attach that routine
raulMrello 0:9d09acc8f9d9 68 * // handle [eh2] will process [ev2] events through [ev2_handle_func] routine. So it must attach that routine
raulMrello 0:9d09acc8f9d9 69 * eh1.Attach(&ev1_handle_func);
raulMrello 0:9d09acc8f9d9 70 * eh2.Attach(&ev2_handle_func);
raulMrello 0:9d09acc8f9d9 71 *
raulMrello 0:9d09acc8f9d9 72 * // handlers are registered into the kernel to listen to specific events. [eh1] listens to [ev1], [eh2] listens to [ev2].
raulMrello 0:9d09acc8f9d9 73 * kernel.AddEventListener(&ev1, &eh1);
raulMrello 0:9d09acc8f9d9 74 * kernel.AddEventListener(&ev1, &eh2);
raulMrello 0:9d09acc8f9d9 75 *
raulMrello 0:9d09acc8f9d9 76 * // application starts. In this case task [eh1] is executed through the interface EventHandler::Execute.
raulMrello 0:9d09acc8f9d9 77 * eh1.Execute();
raulMrello 0:9d09acc8f9d9 78 *
raulMrello 0:9d09acc8f9d9 79 * // the event-driven kernel starts its operation.
raulMrello 0:9d09acc8f9d9 80 * while(1) {
raulMrello 0:9d09acc8f9d9 81 * kernel.Schedule();
raulMrello 0:9d09acc8f9d9 82 * }
raulMrello 0:9d09acc8f9d9 83 * }
raulMrello 0:9d09acc8f9d9 84 *
raulMrello 0:9d09acc8f9d9 85 * // user's implementation of the event handlers
raulMrello 0:9d09acc8f9d9 86 * uint32_t ev1_handle_func(void* me, void* args){
raulMrello 0:9d09acc8f9d9 87 * // add code here to process ev1 events and (optionally) publish ev2 events.
raulMrello 0:9d09acc8f9d9 88 * // howto: publishing an ev2 event and attaching the value of a variable [time].
raulMrello 0:9d09acc8f9d9 89 * uint32_t time = 1000;
raulMrello 0:9d09acc8f9d9 90 * kernel.PublishEvent(&ev2, (void*)time);
raulMrello 0:9d09acc8f9d9 91 * }
raulMrello 0:9d09acc8f9d9 92 *
raulMrello 0:9d09acc8f9d9 93 * uint32_t ev2_handle_func(void* me, void* args){
raulMrello 0:9d09acc8f9d9 94 * // add code here to process ev2 events and (optionally) publish ev1 events.
raulMrello 0:9d09acc8f9d9 95 * // howto: extracting the value of [time] variable attached to [ev1] event
raulMrello 0:9d09acc8f9d9 96 * uint32_t time = (uint32_t)args;
raulMrello 0:9d09acc8f9d9 97 *
raulMrello 0:9d09acc8f9d9 98 * // howto: publishing an ev1 event without data attached.
raulMrello 0:9d09acc8f9d9 99 * kernel.PublishEvent(&ev1, 0);
raulMrello 0:9d09acc8f9d9 100 * }
raulMrello 0:9d09acc8f9d9 101 * @endcode
raulMrello 0:9d09acc8f9d9 102 *
raulMrello 0:9d09acc8f9d9 103 */
raulMrello 0:9d09acc8f9d9 104
raulMrello 0:9d09acc8f9d9 105 class EventFramework{
raulMrello 0:9d09acc8f9d9 106 public:
raulMrello 0:9d09acc8f9d9 107 /** Creates an EventFramework instance. This constructor accepts up to four arguments:
raulMrello 0:9d09acc8f9d9 108 *
raulMrello 0:9d09acc8f9d9 109 * @param schpol is the selected scheduling policy: EventFramework::SCHED_VALUE_COOPERATIVE or EventFramework::SCHED_VALUE_PREEMPTIVE
raulMrello 0:9d09acc8f9d9 110 * @param cbEI is a (void (*)(void)) callback to enable all the interrupts of the processor.
raulMrello 0:9d09acc8f9d9 111 * @param lock is a (void (*)(void)) callback to enter into a critial region.
raulMrello 0:9d09acc8f9d9 112 * @param unlock is a (void (*)(void)) callback to exit from a critial region.
raulMrello 0:9d09acc8f9d9 113 */
raulMrello 0:9d09acc8f9d9 114 EventFramework(uint32_t schpol, void (*cbEI)(void)=NULL, void (*lock)(void)=NULL, void (*unlock)(void)=NULL);
raulMrello 0:9d09acc8f9d9 115
raulMrello 0:9d09acc8f9d9 116 /** Default destructor
raulMrello 0:9d09acc8f9d9 117 *
raulMrello 0:9d09acc8f9d9 118 * Deallocates reserved memory for an EventFramework instance.
raulMrello 0:9d09acc8f9d9 119 */
raulMrello 0:9d09acc8f9d9 120 ~EventFramework();
raulMrello 0:9d09acc8f9d9 121
raulMrello 0:9d09acc8f9d9 122 /** Registers a new Event into the framework.
raulMrello 0:9d09acc8f9d9 123 *
raulMrello 0:9d09acc8f9d9 124 * @param ev Event to be registered into the framework
raulMrello 0:9d09acc8f9d9 125 */
raulMrello 0:9d09acc8f9d9 126 void AddEvent(Event* ev);
raulMrello 0:9d09acc8f9d9 127
raulMrello 0:9d09acc8f9d9 128 /** Unregisters an existing Event from the framework.
raulMrello 0:9d09acc8f9d9 129 *
raulMrello 0:9d09acc8f9d9 130 * @param ev Event to be unregistered from the framework
raulMrello 0:9d09acc8f9d9 131 */
raulMrello 0:9d09acc8f9d9 132 void RemoveEvent(Event* ev);
raulMrello 0:9d09acc8f9d9 133
raulMrello 0:9d09acc8f9d9 134 /** Registers a new EventHandler to listen Event notifications. It can accept up to three arguments:
raulMrello 0:9d09acc8f9d9 135 *
raulMrello 0:9d09acc8f9d9 136 * @param ev Event instance to listen to.
raulMrello 0:9d09acc8f9d9 137 * @param hnd EventHandler who will listen to [ev] events.
raulMrello 0:9d09acc8f9d9 138 * @param func Event dispatching function to attach to [hnd] for [ev] events processing.
raulMrello 0:9d09acc8f9d9 139 */
raulMrello 0:9d09acc8f9d9 140 void AddEventListener(Event* ev, EventHandler* hnd, EventDispatchingRoutine* func=NULL);
raulMrello 0:9d09acc8f9d9 141
raulMrello 0:9d09acc8f9d9 142 /** Unregister an existing EventHandler listener from the framework.
raulMrello 0:9d09acc8f9d9 143 *
raulMrello 0:9d09acc8f9d9 144 * @param ev Event instance to which [hnd] is listening to.
raulMrello 0:9d09acc8f9d9 145 * @param hnd EventHandler to remove from the [ev] listener list.
raulMrello 0:9d09acc8f9d9 146 */
raulMrello 0:9d09acc8f9d9 147 void RemoveEventListener(Event* ev, EventHandler* hnd);
raulMrello 0:9d09acc8f9d9 148
raulMrello 0:9d09acc8f9d9 149 /** Publish an Event with (optionally) attached data.
raulMrello 0:9d09acc8f9d9 150 *
raulMrello 0:9d09acc8f9d9 151 * @param evt Event published to be processed.
raulMrello 0:9d09acc8f9d9 152 * @param args (optional) attached data reference. If not used then set 0.
raulMrello 0:9d09acc8f9d9 153 */
raulMrello 0:9d09acc8f9d9 154 void PublishEvent(Event* evt, void* args);
raulMrello 0:9d09acc8f9d9 155
raulMrello 0:9d09acc8f9d9 156 /** Configure specific features of the EventFramework.
raulMrello 0:9d09acc8f9d9 157 *
raulMrello 0:9d09acc8f9d9 158 * @param key feature key to update
raulMrello 0:9d09acc8f9d9 159 * @param value feature value to setup
raulMrello 0:9d09acc8f9d9 160 */
raulMrello 0:9d09acc8f9d9 161 void Configure(uint32_t key, uint32_t value);
raulMrello 0:9d09acc8f9d9 162
raulMrello 0:9d09acc8f9d9 163 /** Gets a reference of the Event in process.
raulMrello 0:9d09acc8f9d9 164 *
raulMrello 0:9d09acc8f9d9 165 * @returns Event reference of the Event in process.
raulMrello 0:9d09acc8f9d9 166 */
raulMrello 0:9d09acc8f9d9 167 Event* GetEvent(void);
raulMrello 0:9d09acc8f9d9 168
raulMrello 0:9d09acc8f9d9 169 /** Saves actual context on ISR entry. It allows ISR nesting in fully-preemptive scheduling.
raulMrello 0:9d09acc8f9d9 170 * Must be the first instruction on ISR entry.
raulMrello 0:9d09acc8f9d9 171 * Example:
raulMrello 0:9d09acc8f9d9 172 * @code
raulMrello 0:9d09acc8f9d9 173 * void ISR_Handler(void){
raulMrello 0:9d09acc8f9d9 174 * kernel.SaveContext();
raulMrello 0:9d09acc8f9d9 175 * // add here your isr code.
raulMrello 0:9d09acc8f9d9 176 * ....
raulMrello 0:9d09acc8f9d9 177 * kernel.RestoreContext();
raulMrello 0:9d09acc8f9d9 178 * }
raulMrello 0:9d09acc8f9d9 179 * @endcode
raulMrello 0:9d09acc8f9d9 180 *
raulMrello 0:9d09acc8f9d9 181 */
raulMrello 0:9d09acc8f9d9 182 void SaveContext(void);
raulMrello 0:9d09acc8f9d9 183
raulMrello 0:9d09acc8f9d9 184 /** Restores previous context on ISR exit. It must be the last instruction before ISR exit.
raulMrello 0:9d09acc8f9d9 185 * Example:
raulMrello 0:9d09acc8f9d9 186 * @code
raulMrello 0:9d09acc8f9d9 187 * void ISR_Handler(void){
raulMrello 0:9d09acc8f9d9 188 * kernel.SaveContext();
raulMrello 0:9d09acc8f9d9 189 * // add here your isr code.
raulMrello 0:9d09acc8f9d9 190 * ....
raulMrello 0:9d09acc8f9d9 191 * kernel.RestoreContext();
raulMrello 0:9d09acc8f9d9 192 * }
raulMrello 0:9d09acc8f9d9 193 * @endcode
raulMrello 0:9d09acc8f9d9 194 *
raulMrello 0:9d09acc8f9d9 195 */
raulMrello 0:9d09acc8f9d9 196 void RestoreContext(void);
raulMrello 0:9d09acc8f9d9 197
raulMrello 0:9d09acc8f9d9 198 /** Executes the EventFramework according with the selected scheduling policy.
raulMrello 0:9d09acc8f9d9 199 *
raulMrello 0:9d09acc8f9d9 200 */
raulMrello 0:9d09acc8f9d9 201 void Schedule(void);
raulMrello 0:9d09acc8f9d9 202
raulMrello 0:9d09acc8f9d9 203 /// Feature key to select the SCHEDULING execution model
raulMrello 0:9d09acc8f9d9 204 const static uint32_t SCHED_KEY = 0x00000001;
raulMrello 0:9d09acc8f9d9 205 /// Feature value to setup the SCHEDULING model as COOPERATIVE
raulMrello 0:9d09acc8f9d9 206 const static uint32_t SCHED_VALUE_COOPERATIVE = 0;
raulMrello 0:9d09acc8f9d9 207 /// Feature value to setup the SCHEDULING model as PREEMPTIVE
raulMrello 0:9d09acc8f9d9 208 const static uint32_t SCHED_VALUE_PREEMPTIVE = 1;
raulMrello 0:9d09acc8f9d9 209
raulMrello 0:9d09acc8f9d9 210 private:
raulMrello 0:9d09acc8f9d9 211 bool IsPreemptive(void);
raulMrello 0:9d09acc8f9d9 212 void AddEventToList(Event* ev, List* list);
raulMrello 0:9d09acc8f9d9 213 void AddPendingEvent(Event* ev);
raulMrello 0:9d09acc8f9d9 214 void RemovePendingEvent(Event* ev);
raulMrello 0:9d09acc8f9d9 215 uint8_t nesting;
raulMrello 0:9d09acc8f9d9 216 uint16_t currPrio;
raulMrello 0:9d09acc8f9d9 217 void (*cbEnableInterrupts)(void);
raulMrello 0:9d09acc8f9d9 218 void (*cbLock)(void);
raulMrello 0:9d09acc8f9d9 219 void (*cbUnlock)(void);
raulMrello 0:9d09acc8f9d9 220 List* list;
raulMrello 0:9d09acc8f9d9 221 List* queue;
raulMrello 0:9d09acc8f9d9 222 Event* event;
raulMrello 0:9d09acc8f9d9 223 uint32_t ctflags;
raulMrello 0:9d09acc8f9d9 224 };
raulMrello 0:9d09acc8f9d9 225
raulMrello 0:9d09acc8f9d9 226 #endif