EventFramework library allows the creation of an event-driven infrastructure in which small "threads" can handle events in a multithreaded execution context. The EventFramework can be configured to act as a cooperative or a fully-preemptive kernel with fixed-priority scheduling. Furthermore, this kernel matches run-to-completion semantics, and hence a single-stack configuration is enough to keep running this multithreaded execution environment. As running threads shares global stack, a huge quantity of RAM is saved in contrast with traditional RTOSes.

Dependents:   sensors_KL46Z_xmn

Committer:
raulMrello
Date:
Wed Oct 03 21:02:16 2012 +0000
Revision:
1:ec12f2e32faf
Parent:
0:9d09acc8f9d9
Nesting correction on RestoreContext interface.; Erase invalid comment-block

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 #include "EventFramework.h"
raulMrello 0:9d09acc8f9d9 24 #include "../Node/Node.h"
raulMrello 0:9d09acc8f9d9 25
raulMrello 0:9d09acc8f9d9 26 void EmptyFn(void){}
raulMrello 0:9d09acc8f9d9 27
raulMrello 0:9d09acc8f9d9 28 EventFramework::EventFramework(uint32_t schpol, void (*cbEI)(void), void (*lock)(void), void (*unlock)(void)){
raulMrello 0:9d09acc8f9d9 29 currPrio = 0xFFFF;
raulMrello 0:9d09acc8f9d9 30 nesting = 0;
raulMrello 0:9d09acc8f9d9 31 cbLock = EmptyFn;
raulMrello 0:9d09acc8f9d9 32 cbUnlock = EmptyFn;
raulMrello 0:9d09acc8f9d9 33 cbEnableInterrupts = EmptyFn;
raulMrello 0:9d09acc8f9d9 34 list = NULL;
raulMrello 0:9d09acc8f9d9 35 queue = NULL;
raulMrello 0:9d09acc8f9d9 36 event = NULL;
raulMrello 0:9d09acc8f9d9 37 ctflags |= (EventFramework::SCHED_KEY & schpol);
raulMrello 0:9d09acc8f9d9 38 if(cbEI){
raulMrello 0:9d09acc8f9d9 39 cbEnableInterrupts = cbEI;
raulMrello 0:9d09acc8f9d9 40 }
raulMrello 0:9d09acc8f9d9 41 if(lock){
raulMrello 0:9d09acc8f9d9 42 cbLock = lock;
raulMrello 0:9d09acc8f9d9 43 }
raulMrello 0:9d09acc8f9d9 44 if(unlock){
raulMrello 0:9d09acc8f9d9 45 cbUnlock = unlock;
raulMrello 0:9d09acc8f9d9 46 }
raulMrello 0:9d09acc8f9d9 47 }
raulMrello 0:9d09acc8f9d9 48
raulMrello 0:9d09acc8f9d9 49 EventFramework::~EventFramework(){
raulMrello 0:9d09acc8f9d9 50 if(list)
raulMrello 0:9d09acc8f9d9 51 delete list;
raulMrello 0:9d09acc8f9d9 52 if(queue)
raulMrello 0:9d09acc8f9d9 53 delete queue;
raulMrello 0:9d09acc8f9d9 54 }
raulMrello 0:9d09acc8f9d9 55
raulMrello 0:9d09acc8f9d9 56 void EventFramework::AddEvent(Event* ev){
raulMrello 0:9d09acc8f9d9 57 cbLock();
raulMrello 0:9d09acc8f9d9 58 if(!list){
raulMrello 0:9d09acc8f9d9 59 list = new List(ev);
raulMrello 0:9d09acc8f9d9 60 return;
raulMrello 0:9d09acc8f9d9 61 }
raulMrello 0:9d09acc8f9d9 62 AddEventToList(ev,list);
raulMrello 0:9d09acc8f9d9 63 cbUnlock();
raulMrello 0:9d09acc8f9d9 64 }
raulMrello 0:9d09acc8f9d9 65
raulMrello 0:9d09acc8f9d9 66 void EventFramework::AddPendingEvent(Event* ev){
raulMrello 0:9d09acc8f9d9 67 cbLock();
raulMrello 0:9d09acc8f9d9 68 if(!queue){
raulMrello 0:9d09acc8f9d9 69 queue = new List(ev);
raulMrello 0:9d09acc8f9d9 70 return;
raulMrello 0:9d09acc8f9d9 71 }
raulMrello 0:9d09acc8f9d9 72 AddEventToList(ev,queue);
raulMrello 0:9d09acc8f9d9 73 cbUnlock();
raulMrello 0:9d09acc8f9d9 74 }
raulMrello 0:9d09acc8f9d9 75
raulMrello 0:9d09acc8f9d9 76 void EventFramework::AddEventToList(Event* ev, List* plist){
raulMrello 0:9d09acc8f9d9 77 Node* node = plist->GetFirstNode();
raulMrello 0:9d09acc8f9d9 78 Event* data = (Event*)node->GetData();
raulMrello 0:9d09acc8f9d9 79 while(data->GetPrio() <= ev->GetPrio()){
raulMrello 0:9d09acc8f9d9 80 Node* next = node->GetNext();
raulMrello 0:9d09acc8f9d9 81 if(!next){
raulMrello 0:9d09acc8f9d9 82 plist->AddAfter(node, ev);
raulMrello 0:9d09acc8f9d9 83 return;
raulMrello 0:9d09acc8f9d9 84 }
raulMrello 0:9d09acc8f9d9 85 data = (Event*)next->GetData();
raulMrello 0:9d09acc8f9d9 86 node = next;
raulMrello 0:9d09acc8f9d9 87 }
raulMrello 0:9d09acc8f9d9 88 Node* newHead = plist->AddBefore(node, ev);
raulMrello 0:9d09acc8f9d9 89 if(newHead){
raulMrello 0:9d09acc8f9d9 90 plist->SetFirstNode(newHead);
raulMrello 0:9d09acc8f9d9 91 }
raulMrello 0:9d09acc8f9d9 92 }
raulMrello 0:9d09acc8f9d9 93
raulMrello 0:9d09acc8f9d9 94 void EventFramework::RemoveEvent(Event* ev){
raulMrello 0:9d09acc8f9d9 95 cbLock();
raulMrello 0:9d09acc8f9d9 96 list->RemoveItem(ev);
raulMrello 0:9d09acc8f9d9 97 cbUnlock();
raulMrello 0:9d09acc8f9d9 98 }
raulMrello 0:9d09acc8f9d9 99
raulMrello 0:9d09acc8f9d9 100 void EventFramework::AddEventListener(Event* ev, EventHandler* hnd, EventDispatchingRoutine* func){
raulMrello 0:9d09acc8f9d9 101 if(func){
raulMrello 0:9d09acc8f9d9 102 hnd->Attach(func);
raulMrello 0:9d09acc8f9d9 103 }
raulMrello 0:9d09acc8f9d9 104 ev->Subscribe(hnd);
raulMrello 0:9d09acc8f9d9 105 }
raulMrello 0:9d09acc8f9d9 106
raulMrello 0:9d09acc8f9d9 107 void EventFramework::RemoveEventListener(Event* ev, EventHandler* hnd){
raulMrello 0:9d09acc8f9d9 108 ev->Unsubscribe(hnd);
raulMrello 0:9d09acc8f9d9 109 }
raulMrello 0:9d09acc8f9d9 110
raulMrello 0:9d09acc8f9d9 111 void EventFramework::RemovePendingEvent(Event* ev){
raulMrello 0:9d09acc8f9d9 112 cbLock();
raulMrello 0:9d09acc8f9d9 113 queue->RemoveItem(ev);
raulMrello 0:9d09acc8f9d9 114 cbUnlock();
raulMrello 0:9d09acc8f9d9 115 delete ev;
raulMrello 0:9d09acc8f9d9 116 }
raulMrello 0:9d09acc8f9d9 117
raulMrello 0:9d09acc8f9d9 118 void EventFramework::PublishEvent(Event* evt, void* args){
raulMrello 0:9d09acc8f9d9 119 Event* raised = new Event(evt->GetPrio());
raulMrello 0:9d09acc8f9d9 120 raised->SetData(args);
raulMrello 0:9d09acc8f9d9 121 raised->SetBase(evt);
raulMrello 0:9d09acc8f9d9 122 cbLock();
raulMrello 0:9d09acc8f9d9 123 AddPendingEvent(raised);
raulMrello 0:9d09acc8f9d9 124 if(nesting){
raulMrello 0:9d09acc8f9d9 125 cbUnlock();
raulMrello 0:9d09acc8f9d9 126 return;
raulMrello 0:9d09acc8f9d9 127 }
raulMrello 0:9d09acc8f9d9 128 cbUnlock();
raulMrello 0:9d09acc8f9d9 129 if(IsPreemptive()){
raulMrello 0:9d09acc8f9d9 130 Schedule();
raulMrello 0:9d09acc8f9d9 131 }
raulMrello 0:9d09acc8f9d9 132 }
raulMrello 0:9d09acc8f9d9 133
raulMrello 0:9d09acc8f9d9 134 void EventFramework::Configure(uint32_t key, uint32_t value){
raulMrello 0:9d09acc8f9d9 135 ctflags &= ~key;
raulMrello 0:9d09acc8f9d9 136 ctflags |= (key & value);
raulMrello 0:9d09acc8f9d9 137 }
raulMrello 0:9d09acc8f9d9 138
raulMrello 0:9d09acc8f9d9 139 Event* EventFramework::GetEvent(void){
raulMrello 0:9d09acc8f9d9 140 return event;
raulMrello 0:9d09acc8f9d9 141 }
raulMrello 0:9d09acc8f9d9 142
raulMrello 0:9d09acc8f9d9 143 bool EventFramework::IsPreemptive(void){
raulMrello 0:9d09acc8f9d9 144 if((ctflags & SCHED_KEY) == SCHED_VALUE_PREEMPTIVE)
raulMrello 0:9d09acc8f9d9 145 return true;
raulMrello 0:9d09acc8f9d9 146 return false;
raulMrello 0:9d09acc8f9d9 147 }
raulMrello 0:9d09acc8f9d9 148
raulMrello 0:9d09acc8f9d9 149 void EventFramework::SaveContext(void){
raulMrello 0:9d09acc8f9d9 150 cbLock();
raulMrello 0:9d09acc8f9d9 151 nesting++;
raulMrello 0:9d09acc8f9d9 152 cbUnlock();
raulMrello 0:9d09acc8f9d9 153 }
raulMrello 0:9d09acc8f9d9 154
raulMrello 0:9d09acc8f9d9 155 void EventFramework::RestoreContext(void){
raulMrello 0:9d09acc8f9d9 156 cbLock();
raulMrello 0:9d09acc8f9d9 157 if(nesting > 1){
raulMrello 1:ec12f2e32faf 158 nesting--;
raulMrello 0:9d09acc8f9d9 159 cbUnlock();
raulMrello 0:9d09acc8f9d9 160 return;
raulMrello 0:9d09acc8f9d9 161 }
raulMrello 0:9d09acc8f9d9 162 nesting = 0;
raulMrello 0:9d09acc8f9d9 163 cbUnlock();
raulMrello 0:9d09acc8f9d9 164 if(cbEnableInterrupts){
raulMrello 0:9d09acc8f9d9 165 cbEnableInterrupts();
raulMrello 0:9d09acc8f9d9 166 }
raulMrello 0:9d09acc8f9d9 167 Schedule();
raulMrello 0:9d09acc8f9d9 168 }
raulMrello 0:9d09acc8f9d9 169
raulMrello 0:9d09acc8f9d9 170 void EventFramework::Schedule(void){
raulMrello 0:9d09acc8f9d9 171 volatile static uint16_t curr = 0xFFFF;
raulMrello 0:9d09acc8f9d9 172 volatile uint16_t prev;
raulMrello 0:9d09acc8f9d9 173 volatile uint16_t next;
raulMrello 0:9d09acc8f9d9 174
raulMrello 0:9d09acc8f9d9 175 for(;;){
raulMrello 0:9d09acc8f9d9 176 cbLock();
raulMrello 0:9d09acc8f9d9 177 // if no pending events, then quit
raulMrello 0:9d09acc8f9d9 178 if(!queue){
raulMrello 0:9d09acc8f9d9 179 cbUnlock();
raulMrello 0:9d09acc8f9d9 180 return;
raulMrello 0:9d09acc8f9d9 181 }
raulMrello 0:9d09acc8f9d9 182 // extract most priority event
raulMrello 0:9d09acc8f9d9 183 Node* firstNode = queue->GetFirstNode();
raulMrello 0:9d09acc8f9d9 184 Event* rdyEvent = (Event*)firstNode->GetData();
raulMrello 0:9d09acc8f9d9 185 next = rdyEvent->GetPrio();
raulMrello 0:9d09acc8f9d9 186
raulMrello 0:9d09acc8f9d9 187 // if worst then exit
raulMrello 0:9d09acc8f9d9 188 if(next >= currPrio){
raulMrello 0:9d09acc8f9d9 189 cbUnlock();
raulMrello 0:9d09acc8f9d9 190 return;
raulMrello 0:9d09acc8f9d9 191 }
raulMrello 0:9d09acc8f9d9 192
raulMrello 0:9d09acc8f9d9 193 // else update context
raulMrello 0:9d09acc8f9d9 194 prev = curr;
raulMrello 0:9d09acc8f9d9 195 curr = next;
raulMrello 0:9d09acc8f9d9 196 currPrio = curr;
raulMrello 0:9d09acc8f9d9 197
raulMrello 0:9d09acc8f9d9 198 // extract event from queue, if no more events, the free queue
raulMrello 0:9d09acc8f9d9 199 queue->Remove(firstNode);
raulMrello 0:9d09acc8f9d9 200 if(!queue->GetFirstNode()){
raulMrello 0:9d09acc8f9d9 201 delete queue;
raulMrello 0:9d09acc8f9d9 202 queue = NULL;
raulMrello 0:9d09acc8f9d9 203 }
raulMrello 0:9d09acc8f9d9 204
raulMrello 0:9d09acc8f9d9 205 // get event
raulMrello 0:9d09acc8f9d9 206 Node* nodeHnd = rdyEvent->GetBase()->GetList()->GetFirstNode();
raulMrello 0:9d09acc8f9d9 207 while(nodeHnd){
raulMrello 0:9d09acc8f9d9 208 EventHandler* hnd = (EventHandler*)nodeHnd->GetData();
raulMrello 0:9d09acc8f9d9 209 cbUnlock();
raulMrello 0:9d09acc8f9d9 210 hnd->Execute(rdyEvent->GetData());
raulMrello 0:9d09acc8f9d9 211 cbLock();
raulMrello 0:9d09acc8f9d9 212 nodeHnd = nodeHnd->GetNext();
raulMrello 0:9d09acc8f9d9 213 }
raulMrello 0:9d09acc8f9d9 214 delete rdyEvent;
raulMrello 0:9d09acc8f9d9 215 curr = prev;
raulMrello 0:9d09acc8f9d9 216 currPrio = curr;
raulMrello 0:9d09acc8f9d9 217 cbUnlock();
raulMrello 0:9d09acc8f9d9 218 }
raulMrello 0:9d09acc8f9d9 219 }
raulMrello 0:9d09acc8f9d9 220
raulMrello 0:9d09acc8f9d9 221
raulMrello 0:9d09acc8f9d9 222