nikos chalikias
/
mbos_test
Testing [Andrew L] mbos RTOS for mbed Simply by copying code for main.cpp from mbos.h-comments
Embed:
(wiki syntax)
Show/hide line numbers
mbos.cpp
00001 /*********************************************************************************** 00002 * m b o s R T O S F O R m b e d (ARM CORTEX M3) 00003 * 00004 * Copyright (c) 2010 - 2011 Andrew Levido 00005 * 00006 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED 00007 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00008 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT 00009 * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 00010 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT 00011 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00012 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 00013 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 00014 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 00015 */ 00016 #include "mbos.h" 00017 #include "mbed.h" 00018 00019 #define MAX_PRIO 99 // maximum priority 00020 #define READY MAX_PRIO + 1 // always > MAX_PRIO 00021 #define WAITING 0 // aways 0 00022 #define DEFAULT_IDLE_STACK_SZ 32 // in words 00023 #define MAX_TASKS 99 // tasks 0.. 99 including idle 00024 #define MAX_TIMERS 99 // timers 0..99 00025 #define MAX_RESOURCES 99 // resources 0..99 00026 #define MIN_STACKSZ 32 // enough to run an empty function 00027 #define TICKS_PER_SECOND 1000 // 1ms Ticks 00028 00029 typedef struct _tcb{ // task control block 00030 uint id; 00031 uint *stack; 00032 uint priostate; 00033 uint eventlist; 00034 uint eventmask; 00035 uint *stacklimit; 00036 }_tcb_t; 00037 00038 typedef struct _timer{ // timer cotrol block 00039 uint timer; 00040 uint reload; 00041 uint event; 00042 uint task; 00043 }_timer_t; 00044 00045 typedef struct _rcb{ // resource control block 00046 uint lock; 00047 uint priority; 00048 uint taskprio; 00049 }_resource_t; 00050 00051 extern "C" void _startos(void); // Assembly routine to start the scheduler 00052 extern "C" void _swap(void); // Assembly routine to set PendSV exception 00053 extern "C" void SysTick_Handler(void); // Override weak declaration in startup file 00054 extern "C" void _stackerror(uint task); // Stack error function called by assembler 00055 00056 extern void __attribute__((__weak__)) mbosIdleTask(void); // Allow user to write their own idle task 00057 00058 // Static Variables 00059 uint _hardstacklimit; // stack limit 00060 _tcb_t **_tasklist; // pointer to task list 00061 _tcb_t *_tasks; // pointer to task control block 0 00062 _timer_t *_timers; // pointer to timer control block 0 00063 _resource_t *_resources; // pointer to resource control block 0 00064 uint _numtasks; // number of tasks (including idle) 00065 uint _numtimers; // number of timers 00066 uint _numresources; // number of resources 00067 uint _tasklistsize; // task list length in bytes 00068 00069 // Default Idle Task ------------------------------------------------------------------- 00070 void _idletask(void) { while(1); } // Default idle task 00071 00072 // Constructor ------------------------------------------------------------------------- 00073 mbos::mbos(uint ntasks, uint ntimers, uint nresources) 00074 { 00075 uint i; 00076 00077 ntasks += 1; 00078 // Create the tcblist, zero initialised 00079 if(ntasks > MAX_TASKS || ntasks < 1) error("mbos::mbos - %i is an invalid number of tasks\n", ntasks); 00080 _tasklist = (_tcb_t**)calloc(sizeof(_tcb_t*), ntasks); 00081 if(_tasklist == 0) error("mbos::mbos - Insufficient memory to create Tasklist\n"); 00082 00083 // Create the tcbs 00084 _tasklist[0] = (_tcb_t*)calloc(sizeof(_tcb_t), ntasks); 00085 if(_tasklist[0] == 0) error("mbos::mbos - Insufficient memory to create TCBs\n"); 00086 for(i = 1; i < ntasks; i++){ 00087 _tasklist[i] = _tasklist[i - 1] + 1; 00088 } 00089 // Create the timers and clear them 00090 if(ntimers > MAX_TIMERS + 1) error("mbos::mbos - %i is an invalid number of Timers\n", ntimers); 00091 _timers = (_timer_t*)calloc(sizeof(_timer_t), ntimers); 00092 if(_timers == 0) error("mbos::mbos - Insufficient memory to create Timers"); 00093 00094 // create the resources & clear them 00095 if(nresources > MAX_RESOURCES + 1) error("mbos::mbos - %i is an invalid number of Resources\n", nresources); 00096 _resources = (_resource_t*)calloc(sizeof(_resource_t), nresources); 00097 if(_resources == 0) error("mbos::mbos - Insufficient memory to create Resources"); 00098 _hardstacklimit = (uint)malloc(1); 00099 if(_hardstacklimit == 0) error("mbos::mbos - Insufficient memory to create HardStackLimit"); 00100 _numtasks = ntasks; 00101 _numtimers = ntimers; 00102 _numresources = nresources; 00103 _tasks = _tasklist[0]; 00104 } 00105 // Create Tasks Function -------------------------------------------------------------- 00106 void mbos::CreateTask(uint id, uint priority, uint stacksz, void (*fun)(void)) 00107 { 00108 uint* stackbase; 00109 00110 // check bounds 00111 if(id >= _numtasks || id < 1) error("mbos::CreateTask - %i is an invalid task id\n", id); 00112 if(priority > MAX_PRIO) error("mbos::CreateTask - %i is an invalid priority for Task %i\n", priority, id); 00113 if(stacksz < MIN_STACKSZ) stacksz = MIN_STACKSZ; 00114 00115 // fill tcb 00116 if(_tasks[id].id == 0) _tasks[id].id = id; 00117 else error("mbos::CreateTask - Task %i already created\n", id); 00118 _tasks[id].priostate = READY + priority; 00119 _tasks[id].eventlist = 0; 00120 _tasks[id].eventmask = 0; 00121 stackbase = (uint*)malloc(stacksz * 4); 00122 if(stackbase == 0) error("mbos::CreateTask - Insufficient memory to create Task %i\n", id); 00123 _tasks[id].stacklimit = stackbase; 00124 _tasks[id].stack = _initstack(stackbase + stacksz, fun); 00125 } 00126 // Start OS function ------------------------------------------------------------------- 00127 void mbos::Start(uint stacksize) 00128 { 00129 uint * stackbase; 00130 00131 // Fill idle tcb and initialise idle stack 00132 _tasks[0].priostate = READY; 00133 _tasks[0].id = 0; 00134 _tasks[0].eventlist = 0; 00135 _tasks[0].eventmask = 0; 00136 if(mbosIdleTask){ 00137 if(stacksize < MIN_STACKSZ) stacksize = MIN_STACKSZ; 00138 stackbase = (uint*)malloc(stacksize * 4); 00139 if(stackbase == 0) error("mbos::Start - Insufficient memory to create idle task\n"); 00140 _tasks[0].stacklimit = stackbase; 00141 _tasks[0].stack = _initstack(stackbase + stacksize, mbosIdleTask); 00142 } 00143 else { 00144 stackbase = (uint*)malloc(DEFAULT_IDLE_STACK_SZ * 4); 00145 if(stackbase == 0) error("mbos::Start - Insufficient memory to create idle task\n"); 00146 _tasks[0].stacklimit = stackbase; 00147 _tasks[0].stack = _initstack(stackbase + DEFAULT_IDLE_STACK_SZ, _idletask); 00148 } 00149 _tasklistsize = 4 * (_numtasks - 1); 00150 SysTick_Config(SystemCoreClock / TICKS_PER_SECOND); 00151 NVIC_SetPriority(SysTick_IRQn, 0); 00152 _startos(); 00153 00154 while(1); 00155 } 00156 // OS Tick Function ------------------------------------------------------------------- 00157 void SysTick_Handler(void) 00158 { 00159 uint i; 00160 00161 __disable_irq(); 00162 00163 for(i = 0; i < _numtimers; i++){ 00164 if(_timers[i].timer){ 00165 _timers[i].timer--; 00166 if(_timers[i].timer == 0){ 00167 _timers[i].timer = _timers[i].reload; 00168 if(_tasks[_timers[i].task].eventmask & _timers[i].event){ 00169 _tasks[_timers[i].task].eventlist |= _timers[i].event; 00170 _tasks[_timers[i].task].priostate += READY; 00171 } 00172 } 00173 } 00174 } 00175 if((__return_address() & 0x08) == 0) { // called from Handler, so swap later 00176 __enable_irq(); 00177 return; 00178 } 00179 _swap(); 00180 __enable_irq(); 00181 } 00182 // Get Task id Function ----------------------------------------------------------------- 00183 uint mbos::GetTask(void) 00184 { 00185 return _tasklist[0]->id; 00186 } 00187 // Set Priority Function ---------------------------------------------------------------- 00188 void mbos::SetPriority(uint priority) 00189 { 00190 if(_tasklist[0]->id == 0) return; 00191 if(priority > MAX_PRIO) error("mbos::SetPriority - %i is an invalid priority\n", priority); 00192 _tasklist[0]->priostate = priority + READY; 00193 } 00194 // Get Priority Function ---------------------------------------------------------------- 00195 uint mbos::GetPriority(void) 00196 { 00197 return _tasklist[0]->priostate - READY; 00198 } 00199 // Wait Event Function ------------------------------------------------------------------ 00200 void mbos::WaitEvent(uint event) 00201 { 00202 if(_tasklist[0]->id == 0) return; 00203 if(event == 0) return; 00204 __disable_irq(); 00205 _tasklist[0]->eventlist = 0; 00206 _tasklist[0]->eventmask = event; 00207 _tasklist[0]->priostate -= READY; 00208 _swap(); 00209 __enable_irq(); 00210 } 00211 // Set Event Function -------------------------------------------------------------------- 00212 void mbos::SetEvent(uint event, uint task) 00213 { 00214 // check bounds 00215 if(task >= _numtasks || (task < 1)) return; 00216 00217 __disable_irq(); 00218 if(_tasks[task].eventmask & event){ 00219 _tasks[task].eventlist |= event; 00220 _tasks[task].priostate += READY; 00221 } 00222 else{ 00223 __enable_irq(); 00224 return; 00225 } 00226 _swap(); 00227 __enable_irq(); 00228 } 00229 // Get event Function ----------------------------------------------------------------- 00230 uint mbos::GetEvent(void) 00231 { 00232 return _tasklist[0]->eventlist; 00233 } 00234 // Create Timer Function -------------------------------------------------------------- 00235 void mbos::CreateTimer(uint id, uint task, uint event) 00236 { 00237 // check bounds 00238 if(id >= _numtimers) error("mbos::CreateTimer - %i is an invalid timer id\n", id); 00239 if(task < 1|| task >= _numtasks) error("mbos::CreateTimer - %i is an invalid task id for Timer %i\n", task, id); 00240 if(event == 0) error("mbos::CreateTimer - Can't use null event for Timer %i\n", id); 00241 00242 // fill tcb 00243 _timers[id].timer = 0; 00244 _timers[id].reload = 0; 00245 _timers[id].task = task; 00246 _timers[id].event = event; 00247 } 00248 // Set Timer Function ------------------------------------------------------------------- 00249 void mbos::SetTimer(uint id, uint time, uint reload) 00250 { 00251 // check bounds 00252 if(id >= _numtimers) error("mbos::SetTimer - %i is an invalid timer id\n", id); 00253 00254 __disable_irq(); 00255 _timers[id].timer = time; 00256 _timers[id].reload = reload; 00257 __enable_irq(); 00258 } 00259 // Redirect Timer Function ----------------------------------------------------------------- 00260 void mbos::RedirectTimer(uint id, uint task, uint event) 00261 { 00262 // check bounds 00263 if(id >= _numtimers) error("mbos::RedirectTimer - %i is an invalid timer id\n", id); 00264 if(task < 1|| task >= _numtasks) error("mbos::RedirectTimer - %i is an invalid task id for Timer %i\n", task, id); 00265 if(event == 0) error("mbos::RedirectTimer - Can't use null event for Timer %i\n", id); 00266 00267 __disable_irq(); 00268 if( _timers[id].timer == 0){ 00269 _timers[id].task = task; 00270 _timers[id].event = event; 00271 } 00272 __enable_irq(); 00273 } 00274 // Clear Timer Function ------------------------------------------------------------------- 00275 void mbos::ClearTimer(uint id) 00276 { 00277 // check bounds 00278 if(id >= _numtimers) error("mbos::ClearTimer - %i is an invalid timer id\n", id); 00279 00280 __disable_irq(); 00281 _timers[id].timer = 0; 00282 _timers[id].reload = 0; 00283 __enable_irq(); 00284 } 00285 // Create resources Function -------------------------------------------------------------- 00286 void mbos::CreateResource(uint id, uint priority) 00287 { 00288 // check bounds 00289 if(id >= _numresources) error("mbos::CreateResource - %i is an invalid resource id\n", id); 00290 if(priority > MAX_PRIO) error("mbos::CreateResource - %i is an invalid priority for Resource %i\n", priority, id); 00291 00292 // fill rcb 00293 _resources[id].priority = priority; 00294 _resources[id].lock = 0; 00295 } 00296 // Lock Resource Function -------------------------------------------------------------- 00297 uint mbos::LockResource(uint id) 00298 { 00299 // check bounds 00300 if(id >= _numresources) error("mbos::LockResource - %i is an invalid resource id\n", id); 00301 if(_tasklist[0]->id == 0 ||_resources[id].lock != 0) return _resources[id].lock; 00302 00303 __disable_irq(); 00304 _resources[id].lock = _tasklist[0]->id; 00305 _resources[id].taskprio = _tasklist[0]->priostate; 00306 _tasklist[0]->priostate = _resources[id].priority + READY; 00307 __enable_irq(); 00308 return 0; 00309 } 00310 // Test Resource Function -------------------------------------------------------------- 00311 uint mbos::TestResource(uint id) 00312 { 00313 // check bounds 00314 if(id >= _numresources) error("mbos::TestResource - %i is an invalid resource id\n", id); 00315 return(_resources[id].lock); 00316 } 00317 // Free Resource Function -------------------------------------------------------------- 00318 uint mbos::FreeResource(uint id) 00319 { 00320 // check bounds 00321 if(id >= _numresources) error("mbos::FreeResource - %i is an invalid resource id\n", id); 00322 if(_tasklist[0]->id == 0 || _tasklist[0]->id != _resources[id].lock) return _resources[id].lock; 00323 00324 __disable_irq(); 00325 _resources[id].lock = 0; 00326 _tasklist[0]->priostate = _resources[id].taskprio; 00327 __enable_irq(); 00328 return 0; 00329 } 00330 // Initialise stack function ----------------------------------------------------------- 00331 uint* mbos::_initstack(uint *stack, void (*fun)()) 00332 { 00333 stack -= 3; // leave a spare word 00334 *stack = 0x01000000; // Initial xPSR (reset value) 00335 stack--; 00336 *stack = (uint)fun - 1; // Start address of the task corrected 00337 stack--; 00338 *stack = 0; // LR 00339 stack -= 5; // R12, R3, R2, R1, R0 00340 stack -= 8; // R11, R10, R9, R8, R7, R6, R5, R4 00341 return stack; 00342 } 00343 // Stack Error function ---------------------------------------------------------------- 00344 void _stackerror(uint task) 00345 { 00346 error("Stack Overflow on Task %i\n", task); 00347 }
Generated on Wed Jul 13 2022 06:35:50 by 1.7.2