aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2012-02-23 12:46:51 +0000
committerDimitri Sokolyuk <demon@dim13.org>2012-02-23 12:46:51 +0000
commit2acb123fbf5dadf743db122e26fb96da4a58a84c (patch)
tree278061ad5cbaedfcf722651c45fddf585e49ed90
parent51649e040ba68812ae3666c1f1418642b734ae55 (diff)
remove priorities
simplify semaphores diff-time based time queue
-rw-r--r--kernel/Makefile.inc3
-rw-r--r--kernel/adc.c2
-rw-r--r--kernel/clock.c2
-rw-r--r--kernel/dmx.c18
-rw-r--r--kernel/dmx/Makefile4
-rw-r--r--kernel/kernel.c119
-rw-r--r--kernel/kernel.h14
-rw-r--r--kernel/tasks.h4
8 files changed, 74 insertions, 92 deletions
diff --git a/kernel/Makefile.inc b/kernel/Makefile.inc
index ca57693..f52bcbc 100644
--- a/kernel/Makefile.inc
+++ b/kernel/Makefile.inc
@@ -11,8 +11,7 @@ SIZE= avr-size
CFLAGS= -mmcu=${MCU} -Wall -Os \
-DF_CPU=${F_CPU} -DPRESCALE=${PRESCALE} \
- -DBAUD=${BAUD} -DSTACK=${STACK} -DTASKS=${TASKS} \
- -DSEMAPHORES=${SEMAPHORES} -DPRIORITIES=${PRIORITIES}
+ -DBAUD=${BAUD} -DSTACK=${STACK} -DTASKS=${TASKS}
LDFLAGS= -mmcu=${MCU} -Wl,-Map,${PROG}.map
.SUFFIXES: .lst .hex .bin .srec .ehex .ebin .esrec
diff --git a/kernel/adc.c b/kernel/adc.c
index aa23ffb..f91b5a8 100644
--- a/kernel/adc.c
+++ b/kernel/adc.c
@@ -44,7 +44,7 @@ adc(void *arg)
}
wait(0);
fprintf(stderr, "\n%8lx%8x", now(), a->value[0]);
- signal(0);
+ signal();
sleep(MSEC(100));
}
}
diff --git a/kernel/clock.c b/kernel/clock.c
index b96ac74..69939d0 100644
--- a/kernel/clock.c
+++ b/kernel/clock.c
@@ -39,7 +39,7 @@ clock(void *arg)
wait(0);
fprintf(stderr, "\r%4d:%.2d:%.2d:%.2d.%1d ", d, h, m, s, ds);
- signal(0);
+ signal();
sleep(SEC1(1));
}
diff --git a/kernel/dmx.c b/kernel/dmx.c
index 49ff3fd..d7369c8 100644
--- a/kernel/dmx.c
+++ b/kernel/dmx.c
@@ -24,11 +24,9 @@
#include "kernel.h"
#include "tasks.h"
-enum { RT, High, Low };
-
struct adcarg adcarg;
struct ppmarg ppmarg = { adcarg.value };
-struct rgbarg rgbargs = { 0, 0, 0, &adcarg.value[0] };
+struct rgbarg rgbargs = { 0, 0, 0, adcarg.value };
struct pwmarg pwmargs[] = {
{ &rgbargs.r, PB2, 1 },
{ &rgbargs.g, PB3, 2 },
@@ -42,13 +40,13 @@ main()
lcd_init();
init(48);
- exec(heartbeat, NULL, 48, Low);
- exec(rgb, &rgbargs, 72, High);
- exec(pwm, &pwmargs[0], 56, RT);
- exec(pwm, &pwmargs[1], 56, RT);
- exec(pwm, &pwmargs[2], 56, RT);
- exec(adc, &adcarg, 96, Low);
- exec(clock, NULL, 96, Low);
+ exec(heartbeat, NULL, 48);
+ exec(rgb, &rgbargs, 72);
+ exec(pwm, &pwmargs[0], 56);
+ exec(pwm, &pwmargs[1], 56);
+ exec(pwm, &pwmargs[2], 56);
+ exec(adc, &adcarg, 96);
+ exec(clock, NULL, 96);
#if 0
exec(cmd, &rgbargs, 48);
exec(ppm, &ppmarg, 48);
diff --git a/kernel/dmx/Makefile b/kernel/dmx/Makefile
index f65a6b7..64e5d2c 100644
--- a/kernel/dmx/Makefile
+++ b/kernel/dmx/Makefile
@@ -10,9 +10,7 @@ PRESCALE= 1 # res 62.5nsec cycle 4msec
#PRESCALE= 1024 # res 64msec cycle 4 sec
#STACK= 48
STACK= 80
-TASKS= 11 # +1 idle
-SEMAPHORES= 6
-PRIORITIES= 4
+TASKS= 11 # +1 idle = 12
BAUD= 9600
PROG= dmx
diff --git a/kernel/kernel.c b/kernel/kernel.c
index 7d04a56..b3cb22e 100644
--- a/kernel/kernel.c
+++ b/kernel/kernel.c
@@ -42,19 +42,19 @@ struct task {
uint32_t release;
uint16_t sp; /* stack pointer */
uint8_t state;
- uint8_t prio;
- uint8_t sema;
+ uint8_t chan; /* wait channel */
TAILQ_ENTRY(task) link;
};
struct kernel {
- TAILQ_HEAD(queue, task) runq[PRIORITIES], timeq, waitq[SEMAPHORES];
+ TAILQ_HEAD(queue, task) runq, timeq, waitq;
struct task task[1 + TASKS];
struct task *nextfree;
struct task *current;
+ uint32_t lastrun;
uint16_t cycles;
uint8_t *freemem;
- uint8_t semaphore[SEMAPHORES];
+ uint8_t semaphore;
} kernel;
ISR(TIMER1_OVF_vect)
@@ -65,88 +65,89 @@ ISR(TIMER1_OVF_vect)
ISR(TIMER1_COMPA_vect, ISR_NAKED)
{
struct task *tp, *tmp;
- int32_t dist;
+ int32_t round;
uint32_t now;
- uint16_t nexthit;
- uint8_t prio;
PUSH_ALL();
now = NOW(kernel.cycles, TCNT1);
+ round = DISTANCE(kernel.lastrun, now);
#if DEBUG
PORTB ^= _BV(PB1); /* DEBUG */
#endif
kernel.current->sp = SP;
- TAILQ_REMOVE(&kernel.runq[kernel.current->prio], kernel.current, link);
-
- nexthit = 0xffff;
+ TAILQ_REMOVE(&kernel.runq, kernel.current, link);
/* release waiting tasks */
TAILQ_FOREACH_SAFE(tp, &kernel.timeq, link, tmp) {
- dist = DISTANCE(now, tp->release);
- if (dist <= 0) {
+ if (tp->release <= round) {
tp->state = RUNQ;
TAILQ_REMOVE(&kernel.timeq, tp, link);
- TAILQ_INSERT_TAIL(&kernel.runq[tp->prio], tp, link);
- } else if (dist < nexthit)
- nexthit = dist;
- else
- break;
+ TAILQ_INSERT_TAIL(&kernel.runq, tp, link);
+ } else
+ tp->release -= round;
}
-again:
switch (kernel.current->state) {
case RUNQ:
- TAILQ_INSERT_TAIL(&kernel.runq[kernel.current->prio], kernel.current, link);
+ /* readd current task at the end of run queue */
+ /* idle is always in TERMINATED state and is skipped here */
+ TAILQ_INSERT_TAIL(&kernel.runq, kernel.current, link);
break;
case TIMEQ:
- TAILQ_FOREACH(tp, &kernel.timeq, link)
- if (DISTANCE(kernel.current->release, tp->release) > 0)
+ /* find right position on time queue */
+ TAILQ_FOREACH(tp, &kernel.timeq, link) {
+ if (kernel.current->release < tp->release)
break;
-
+ }
if (tp)
TAILQ_INSERT_BEFORE(tp, kernel.current, link);
else
TAILQ_INSERT_TAIL(&kernel.timeq, kernel.current, link);
break;
case WAITQ:
- if (kernel.semaphore[kernel.current->sema] == 0) {
+ if (kernel.semaphore & _BV(kernel.current->chan)) {
+ /* semaphore busy, go into wait queue */
+ TAILQ_INSERT_TAIL(&kernel.waitq, kernel.current, link);
+ } else {
/* occupy semaphore */
- kernel.semaphore[kernel.current->sema] = 1;
+ kernel.semaphore |= _BV(kernel.current->chan);
+ /* go into the end of run queue again */
kernel.current->state = RUNQ;
- goto again; /* put current task back on runq */
- } else
- TAILQ_INSERT_TAIL(&kernel.waitq[kernel.current->sema], kernel.current, link);
+ TAILQ_INSERT_TAIL(&kernel.runq, kernel.current, link);
+ }
break;
case SIGNAL:
- tp = TAILQ_FIRST(&kernel.waitq[kernel.current->sema]);
- if (tp) {
- tp->state = RUNQ;
- TAILQ_REMOVE(&kernel.waitq[kernel.current->sema], tp, link);
- TAILQ_INSERT_TAIL(&kernel.runq[tp->prio], tp, link);
- /* occupy semaphore */
- kernel.semaphore[kernel.current->sema] = 1;
- } else
- kernel.semaphore[kernel.current->sema] = 0;
-
+ /* release waiting tasks from wait queue */
+ TAILQ_FOREACH_SAFE(tp, &kernel.waitq, link, tmp) {
+ if (tp->chan == kernel.current->chan) {
+ TAILQ_REMOVE(&kernel.waitq, tp, link);
+ tp->state = RUNQ;
+ TAILQ_INSERT_TAIL(&kernel.runq, tp, link);
+ }
+ }
+
+ /* clear semaphore */
+ kernel.semaphore &= ~_BV(kernel.current->chan);
+ /* and go back to run queue */
kernel.current->state = RUNQ;
- goto again; /* put current task back on runq */
+ TAILQ_INSERT_TAIL(&kernel.runq, kernel.current, link);
+ break;
default:
break;
}
- for (prio = 0; prio < PRIORITIES - 1; prio++)
- if (!TAILQ_EMPTY(&kernel.runq[prio]))
- break;
-
- if (TAILQ_EMPTY(&kernel.runq[prio]))
- TAILQ_INSERT_TAIL(&kernel.runq[prio], &kernel.task[0], link);
+ /* idle if nothing to run */
+ if (TAILQ_EMPTY(&kernel.runq))
+ TAILQ_INSERT_TAIL(&kernel.runq, &kernel.task[0], link);
- kernel.current = TAILQ_FIRST(&kernel.runq[prio]);
+ kernel.current = TAILQ_FIRST(&kernel.runq);
SP = kernel.current->sp;
- OCR1A = (uint16_t)(now + nexthit);
+ tp = TAILQ_FIRST(&kernel.timeq);
+ OCR1A = (tp) ? (uint16_t)(now + tp->release) : 0xffff;
+ kernel.lastrun = now;
POP_ALL();
reti();
@@ -155,8 +156,6 @@ again:
void
init(uint8_t stack)
{
- uint8_t i;
-
cli();
/* Set up timer 1 */
@@ -173,25 +172,24 @@ init(uint8_t stack)
memset(&kernel, 0, sizeof(kernel));
- for (i = 0; i < PRIORITIES; i++)
- TAILQ_INIT(&kernel.runq[i]);
+ TAILQ_INIT(&kernel.runq);
TAILQ_INIT(&kernel.timeq);
- for (i = 0; i < SEMAPHORES; i++)
- TAILQ_INIT(&kernel.waitq[i]);
+ TAILQ_INIT(&kernel.waitq);
+ kernel.cycles = 0;
+ kernel.lastrun = NOW(kernel.cycles, TCNT1);
kernel.nextfree = &kernel.task[1];
kernel.freemem = (void *)(RAMEND - stack);
kernel.current = &kernel.task[0];
kernel.current->state = TERMINATED;
- kernel.current->prio = PRIORITIES - 1;
kernel.current->release = 0;
- TAILQ_INSERT_TAIL(&kernel.runq[PRIORITIES - 1], &kernel.task[0], link);
+ TAILQ_INSERT_TAIL(&kernel.runq, &kernel.task[0], link);
sei();
}
void
-exec(void (*fun)(void *), void *args, uint8_t stack, uint8_t prio)
+exec(void (*fun)(void *), void *args, uint8_t stack)
{
struct task *t;
uint8_t *sp;
@@ -216,8 +214,7 @@ exec(void (*fun)(void *), void *args, uint8_t stack, uint8_t prio)
t = kernel.nextfree++;
t->release = NOW(kernel.cycles, TCNT1);
- t->prio = prio;
- t->sema = 0;
+ t->chan = 0;
t->sp = (uint16_t)sp; /* SP */
t->state = TIMEQ;
TAILQ_INSERT_TAIL(&kernel.timeq, t, link);
@@ -226,18 +223,18 @@ exec(void (*fun)(void *), void *args, uint8_t stack, uint8_t prio)
}
void
-wait(uint8_t sema)
+wait(uint8_t chan)
{
cli();
- kernel.current->sema = sema;
+ kernel.current->chan = chan;
kernel.current->state = WAITQ;
SCHEDULE();
}
void
-signal(uint8_t sema)
+signal(void)
{
cli();
@@ -251,7 +248,7 @@ sleep(uint32_t ticks)
{
cli();
- kernel.current->release += ticks;
+ kernel.current->release = ticks;
kernel.current->state = TIMEQ;
SCHEDULE();
diff --git a/kernel/kernel.h b/kernel/kernel.h
index ed409b5..bfcd6f9 100644
--- a/kernel/kernel.h
+++ b/kernel/kernel.h
@@ -23,16 +23,6 @@
#define TASKS 8
#endif
-#ifndef PRIORITIES
-#warning PRIORITIES not set, fallback to default: 2
-#define PRIORITIES 2
-#endif
-
-#ifndef SEMAPHORES
-#warning SEMAPHORES not set, fallback to default: 4
-#define SEMAPHORES 4
-#endif
-
#ifndef STACK
#warning STACK not set, fallback to default: 64
#define STACK 64
@@ -97,10 +87,10 @@
/* __BEGIN_DECLS */
void init(uint8_t stack);
-void exec(void (*fun)(void *), void *args, uint8_t stack, uint8_t prio);
+void exec(void (*fun)(void *), void *args, uint8_t stack);
void wait(uint8_t sema);
-void signal(uint8_t sema);
+void signal(void);
void suspend(void);
void sleep(uint32_t ticks);
diff --git a/kernel/tasks.h b/kernel/tasks.h
index 8343a3a..6805fea 100644
--- a/kernel/tasks.h
+++ b/kernel/tasks.h
@@ -55,7 +55,7 @@ struct pwmarg {
};
struct adcarg {
- uint16_t value[ADCCHANNELS];
+ uint8_t value[ADCCHANNELS];
};
struct clockarg {
@@ -63,7 +63,7 @@ struct clockarg {
};
struct ppmarg {
- uint16_t *value;
+ uint8_t *value;
};
void uart_init(void);