LMiC library swtiched to default eu868

Fork of LMiC by Semtech

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers oslmic.cpp Source File

oslmic.cpp

00001 /*******************************************************************************
00002  * Copyright (c) 2014-2015 IBM Corporation.
00003  * All rights reserved. This program and the accompanying materials
00004  * are made available under the terms of the Eclipse Public License v1.0
00005  * which accompanies this distribution, and is available at
00006  * http://www.eclipse.org/legal/epl-v10.html
00007  *
00008  * Contributors:
00009  *    IBM Zurich Research Lab - initial API, implementation and documentation
00010  *******************************************************************************/
00011 
00012 #include "lmic.h"
00013 
00014 // RUNTIME STATE
00015 static struct {
00016     osjob_t* scheduledjobs;
00017     osjob_t* runnablejobs;
00018 } OS;
00019 
00020 void os_init () {
00021     memset(&OS, 0x00, sizeof(OS));
00022     hal_init();
00023     radio_init();
00024     LMIC_init();
00025 }
00026 
00027 ostime_t os_getTime () {
00028     return hal_ticks();
00029 }
00030 
00031 static u1_t unlinkjob (osjob_t** pnext, osjob_t* job) {
00032     for( ; *pnext; pnext = &((*pnext)->next)) {
00033         if(*pnext == job) { // unlink
00034             *pnext = job->next;
00035             return 1;
00036         }
00037     }
00038     return 0;
00039 }
00040 
00041 // clear scheduled job
00042 void os_clearCallback (osjob_t* job) {
00043     hal_disableIRQs();
00044     unlinkjob(&OS.scheduledjobs, job) || unlinkjob(&OS.runnablejobs, job);
00045     hal_enableIRQs();
00046 }
00047 
00048 // schedule immediately runnable job
00049 void os_setCallback (osjob_t* job, osjobcb_t cb) {
00050     osjob_t** pnext;
00051     hal_disableIRQs();
00052     // remove if job was already queued
00053     os_clearCallback(job);
00054     // fill-in job
00055     job->func = cb;
00056     job->next = NULL;
00057     // add to end of run queue
00058     for(pnext=&OS.runnablejobs; *pnext; pnext=&((*pnext)->next));
00059     *pnext = job;
00060     hal_enableIRQs();
00061 }
00062 
00063 // schedule timed job
00064 void os_setTimedCallback (osjob_t* job, ostime_t time, osjobcb_t cb) {
00065     osjob_t** pnext;
00066     hal_disableIRQs();
00067     // remove if job was already queued
00068     os_clearCallback(job);
00069     // fill-in job
00070     job->deadline = time;
00071     job->func = cb;
00072     job->next = NULL;
00073     // insert into schedule
00074     for(pnext=&OS.scheduledjobs; *pnext; pnext=&((*pnext)->next)) {
00075         if((*pnext)->deadline - time > 0) { // (cmp diff, not abs!)
00076             // enqueue before next element and stop
00077             job->next = *pnext;
00078             break;
00079         }
00080     }
00081     *pnext = job;
00082     hal_enableIRQs();
00083 }
00084 
00085 // execute jobs from timer and from run queue
00086 void os_runloop () {
00087     while(1) {
00088         osjob_t* j = NULL;
00089         hal_disableIRQs();
00090         // check for runnable jobs
00091         if(OS.runnablejobs) {
00092             j = OS.runnablejobs;
00093             OS.runnablejobs = j->next;
00094         } else if(OS.scheduledjobs && hal_checkTimer(OS.scheduledjobs->deadline)) { // check for expired timed jobs
00095             j = OS.scheduledjobs;
00096             OS.scheduledjobs = j->next;
00097         } else { // nothing pending
00098             hal_sleep(); // wake by irq (timer already restarted)
00099         }
00100         hal_enableIRQs();
00101         if(j) { // run job callback
00102             j->func(j);
00103         }
00104     }
00105 }