From 775ca7a6b283339019783af24c4c424cdb0cebd1 Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Mon, 2 Jan 2012 10:03:37 +0000 Subject: time sharing --- kernel/Makefile.inc | 7 +- kernel/adc.c | 16 +++-- kernel/clock.c | 31 ++++----- kernel/dmx.c | 61 ++++++----------- kernel/dmx/Makefile | 12 ++-- kernel/heartbeat.c | 1 + kernel/kernel.c | 189 ++++++++++++++++++++++++++-------------------------- kernel/kernel.h | 23 ++++--- kernel/lcd3.c | 113 ++++++++++++------------------- kernel/ppm.c | 1 + kernel/rgb.c | 22 ++++-- kernel/tasks.h | 18 ++--- kernel/uart.c | 109 +++++++++++++++--------------- 13 files changed, 285 insertions(+), 318 deletions(-) diff --git a/kernel/Makefile.inc b/kernel/Makefile.inc index 1ecf7e2..ca57693 100644 --- a/kernel/Makefile.inc +++ b/kernel/Makefile.inc @@ -9,9 +9,10 @@ OBJCOPY= avr-objcopy OBJDUMP= avr-objdump SIZE= avr-size -CFLAGS= -Wall -Os -mmcu=${MCU} \ - -DF_CPU=${F_CPU} -DPRESCALE=${PRESCALE} -DBAUD=${BAUD} \ - -DSTACK=${STACK} -DTASKS=${TASKS} -DSEMAPHORES=${SEMAPHORES} +CFLAGS= -mmcu=${MCU} -Wall -Os \ + -DF_CPU=${F_CPU} -DPRESCALE=${PRESCALE} \ + -DBAUD=${BAUD} -DSTACK=${STACK} -DTASKS=${TASKS} \ + -DSEMAPHORES=${SEMAPHORES} -DPRIORITIES=${PRIORITIES} 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 5c7a35b..76c9c0d 100644 --- a/kernel/adc.c +++ b/kernel/adc.c @@ -16,13 +16,14 @@ */ #include +#include #include #include +#include #include "kernel.h" #include "tasks.h" #define MUXMASK 0x07 -#define DL MSEC(20) void adc(void *arg) @@ -33,14 +34,17 @@ adc(void *arg) ADCSRA |= (_BV(ADEN) | ADC_FLAGS); for (;;) { - if (bit_is_clear(ADCSRA, ADSC)) { + for (i = 0; i < ADCCHANNELS; i++) { + ADMUX = i & MUXMASK; + ADCSRA |= _BV(ADSC); + loop_until_bit_is_clear(ADCSRA, ADSC); //cli(); a->value[i] = ADCW; //sei(); - i = (i + 1) % ADCCHANNELS; - ADMUX = i; - ADCSRA |= _BV(ADSC); } - sleep(MSEC(500 / ADCCHANNELS)); + wait(0); + fprintf(stderr, "\n%8lx%8x", now(), a->value[0]); + signal(0); + sleep(MSEC(100)); } } diff --git a/kernel/clock.c b/kernel/clock.c index 4515d55..b96ac74 100644 --- a/kernel/clock.c +++ b/kernel/clock.c @@ -16,6 +16,7 @@ */ #include +#include #include #include #include @@ -25,29 +26,21 @@ void clock(void *arg) { - struct clockarg *a = arg; - uint8_t d, h, m, s; + uint8_t d, h, m, s, ds; - d = h = m = s = 0; + d = h = m = s = ds = 0; for (;;) { - s += 1; - if (s == 60) { - s = 0; - m += 1; - } - if (m == 60) { - m = 0; - h += 1; - } - if (h == 24) { - h = 0; - d += 1; - } + ++ds; + if (ds == 10) { ds = 0; ++s; } + if (s == 60) { s = 0; ++m; } + if (m == 60) { m = 0; ++h; } + if (h == 24) { h = 0; ++d; } - sprintf(a->lcd->first, "%8lx%8x", now(), a->adc->value[0]); - sprintf(a->lcd->second, "%4d:%.2d:%.2d:%.2d", d, h, m, s); + wait(0); + fprintf(stderr, "\r%4d:%.2d:%.2d:%.2d.%1d ", d, h, m, s, ds); + signal(0); - sleep(SEC(1)); + sleep(SEC1(1)); } } diff --git a/kernel/dmx.c b/kernel/dmx.c index d2827e7..49ff3fd 100644 --- a/kernel/dmx.c +++ b/kernel/dmx.c @@ -16,65 +16,46 @@ */ #include +#include #include #include #include +#include #include "kernel.h" #include "tasks.h" -struct adcarg adcarg; +enum { RT, High, Low }; +struct adcarg adcarg; struct ppmarg ppmarg = { adcarg.value }; - -struct lcdarg lcdarg; - -struct clockarg clockarg = { &lcdarg, &adcarg }; - struct rgbarg rgbargs = { 0, 0, 0, &adcarg.value[0] }; - struct pwmarg pwmargs[] = { - { &rgbargs.r, PB2 }, - { &rgbargs.g, PB3 }, - { &rgbargs.b, PB4 } + { &rgbargs.r, PB2, 1 }, + { &rgbargs.g, PB3, 2 }, + { &rgbargs.b, PB4, 3 } }; int main() { - init(STACK - 6); /* 42 */ - init_uart(); - -#define LOW 0 -#define MID 0 -#define HIGH 0 - -#if 1 - exec(heartbeat, NULL, STACK - 10, LOW); /* 38 */ -#endif - -#if 1 - exec(rgb, &rgbargs, STACK + 24, MID); /* 72 */ - exec(pwm, &pwmargs[0], STACK, HIGH); /* 48 */ - exec(pwm, &pwmargs[1], STACK, HIGH); /* 48 */ - exec(pwm, &pwmargs[2], STACK, HIGH); /* 48 */ - exec(adc, &adcarg, STACK - 6, LOW); /* 42 */ -#endif - -#if 1 - exec(lcd, &lcdarg, STACK, LOW); /* 48 */ - exec(clock, &clockarg, STACK + 24, LOW); /* 72 */ -#endif - -#if 0 - exec(cmd, &rgbargs, STACK, LOW); /* 48 */ -#endif - + uart_init(); + 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); #if 0 - exec(ppm, &ppmarg, STACK, LOW); /* 48 */ + exec(cmd, &rgbargs, 48); + exec(ppm, &ppmarg, 48); #endif for (;;) - _NOP(); + sleep_mode(); return 0; } diff --git a/kernel/dmx/Makefile b/kernel/dmx/Makefile index 654dee9..f65a6b7 100644 --- a/kernel/dmx/Makefile +++ b/kernel/dmx/Makefile @@ -3,14 +3,16 @@ MCU= atmega8 F_CPU= 16000000 #F_CPU= 14745600 -#PRESCALE= 1 # res 62.5nsec cycle 4msec -PRESCALE= 8 # res 0.5usec cycle 32.7msec +PRESCALE= 1 # res 62.5nsec cycle 4msec +#PRESCALE= 8 # res 0.5usec cycle 32.7msec #PRESCALE= 64 # res 4usec cycle 262msec #PRESCALE= 256 # res 16msec cycle 1 sec #PRESCALE= 1024 # res 64msec cycle 4 sec -STACK= 48 -TASKS= 9 # +1 idle -SEMAPHORES= 4 +#STACK= 48 +STACK= 80 +TASKS= 11 # +1 idle +SEMAPHORES= 6 +PRIORITIES= 4 BAUD= 9600 PROG= dmx diff --git a/kernel/heartbeat.c b/kernel/heartbeat.c index 7540ddc..fb5947a 100644 --- a/kernel/heartbeat.c +++ b/kernel/heartbeat.c @@ -16,6 +16,7 @@ */ #include +#include #include #include "kernel.h" #include "tasks.h" diff --git a/kernel/kernel.c b/kernel/kernel.c index dc29f57..7d2d6c2 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -27,10 +27,9 @@ #include "stack.h" #include "queue.h" -#define DEBUG 1 -#define NPRIO 2 +#define DEBUG 0 -enum State { TERMINATED, RTR, RUNQ, SLEEPING, WAITING }; +enum State { TERMINATED, RUNQ, TIMEQ, WAITQ, SIGNAL }; #define LO8(x) ((uint8_t)((uint16_t)(x))) #define HI8(x) ((uint8_t)((uint16_t)(x) >> 8)) @@ -44,14 +43,15 @@ struct task { uint16_t sp; /* stack pointer */ uint8_t state; uint8_t prio; - SIMPLEQ_ENTRY(task) link; + uint8_t sema; + TAILQ_ENTRY(task) link; }; struct kernel { - SIMPLEQ_HEAD(, task) runq[NPRIO]; - struct task *last; /* last allocated task */ + TAILQ_HEAD(queue, task) runq[PRIORITIES], timeq, waitq[SEMAPHORES]; + struct task task[1 + TASKS]; + struct task *nextfree; struct task *current; - struct task task[TASKS + 1]; uint16_t cycles; uint8_t *freemem; uint8_t semaphore[SEMAPHORES]; @@ -64,62 +64,90 @@ ISR(TIMER1_OVF_vect) ISR(TIMER1_COMPA_vect, ISR_NAKED) { - struct task *tp; + struct task *tp, *tmp; int32_t dist; uint32_t now; uint16_t nexthit; uint8_t prio; - /* save context */ PUSH_ALL(); - now = NOW(kernel.cycles, TCNT1); #if DEBUG PORTB ^= _BV(PB1); /* DEBUG */ #endif - /* save stack pointer and drop task from run-queue */ kernel.current->sp = SP; - if (kernel.current->state == RUNQ) - kernel.current->state = RTR; - SIMPLEQ_REMOVE_HEAD(&kernel.runq[kernel.current->prio], link); + TAILQ_REMOVE(&kernel.runq[kernel.current->prio], kernel.current, link); nexthit = 0xffff; - prio = 0; - - /* walk through tasks and assemble run-queue */ - for (tp = &kernel.task[1]; tp <= kernel.last; tp++) { - if (tp->state == SLEEPING) { - dist = DISTANCE(now, tp->release); - if (dist <= 0) - tp->state = RTR; - else if (dist < nexthit) - nexthit = dist; - } - if (tp->state == RTR) { - /* find highest priority */ - if (tp->prio > prio) - prio = tp->prio; - /* put task on queue */ - SIMPLEQ_INSERT_TAIL(&kernel.runq[tp->prio], tp, link); + + /* release waiting tasks */ + TAILQ_FOREACH_SAFE(tp, &kernel.timeq, link, tmp) { + dist = DISTANCE(now, tp->release); + if (dist <= 0) { 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; } - /* idle if all queues empty */ - if (prio == 0 && SIMPLEQ_EMPTY(&kernel.runq[prio])) { - SIMPLEQ_INSERT_TAIL(&kernel.runq[prio], kernel.task, link); - kernel.task->state = RUNQ; +again: + switch (kernel.current->state) { + case RUNQ: + TAILQ_INSERT_TAIL(&kernel.runq[kernel.current->prio], kernel.current, link); + break; + case TIMEQ: + TAILQ_FOREACH(tp, &kernel.timeq, link) + if (DISTANCE(kernel.current->release, tp->release) > 0) + 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) { + /* occupy semaphore */ + kernel.semaphore[kernel.current->sema] = 1; + kernel.current->state = RUNQ; + goto again; /* put current task back on runq */ + } else + TAILQ_INSERT_TAIL(&kernel.waitq[kernel.current->sema], 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; + + kernel.current->state = RUNQ; + goto again; /* put current task back on runq */ + default: + break; } - /* pick highest priority and restore stack pointer */ - kernel.current = SIMPLEQ_FIRST(&kernel.runq[prio]); + 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); + + kernel.current = TAILQ_FIRST(&kernel.runq[prio]); SP = kernel.current->sp; OCR1A = (uint16_t)(now + nexthit); - /* restore context */ POP_ALL(); reti(); } @@ -127,7 +155,7 @@ ISR(TIMER1_COMPA_vect, ISR_NAKED) void init(uint8_t stack) { - uint8_t prio; + uint8_t i; cli(); @@ -142,19 +170,22 @@ init(uint8_t stack) DDRB |= _BV(PB1); /* DEBUG */ #endif - for (prio = 0; prio < NPRIO; prio++) - SIMPLEQ_INIT(&kernel.runq[prio]); + memset(&kernel, 0, sizeof(kernel)); - kernel.cycles = 0; - kernel.freemem = (void *)(RAMEND - stack); - kernel.task->release = 0; - kernel.task->prio = 0; - kernel.task->state = RUNQ; - SIMPLEQ_INSERT_TAIL(&kernel.runq[0], kernel.task, link); + for (i = 0; i < PRIORITIES; i++) + TAILQ_INIT(&kernel.runq[i]); + TAILQ_INIT(&kernel.timeq); + for (i = 0; i < SEMAPHORES; i++) + TAILQ_INIT(&kernel.waitq[i]); - kernel.last = kernel.task; - kernel.current = kernel.task; + 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); sei(); } @@ -183,70 +214,37 @@ exec(void (*fun)(void *), void *args, uint8_t stack, uint8_t prio) sp -= 6; memset(sp, 0, 6); /* r26-r31 */ - t = ++kernel.last; - - t->release = 0; - - if (prio >= NPRIO) - prio = NPRIO - 1; + t = kernel.nextfree++; + t->release = NOW(kernel.cycles, TCNT1); t->prio = prio; - - t->state = RTR; - + t->sema = 0; t->sp = (uint16_t)sp; /* SP */ + t->state = TIMEQ; + TAILQ_INSERT_TAIL(&kernel.timeq, t, link); SCHEDULE(); } -#if 0 -void -semaphore(uint8_t sema, uint8_t val) -{ - cli(); - - kernel.semaphore[sema] = val; - - sei(); -} - void wait(uint8_t sema) { cli(); - if (kernel.semaphore[sema] == 0) { - kernel.running->state = WAITQ + sema; - SCHEDULE(); - } else { - --kernel.semaphore[sema]; - sei(); - } + kernel.current->sema = sema; + kernel.current->state = WAITQ; + + SCHEDULE(); } void signal(uint8_t sema) { - struct task *t, *rtr; - cli(); - rtr = kernel.task; - - for (t = &kernel.task[1]; t <= kernel.last; t++) { - if (t->state == WAITQ + sema) - if (DISTANCE(t->deadline, rtr->deadline) > 0) - rtr = t; - } + kernel.current->state = SIGNAL; - if (rtr != kernel.task) { - rtr->state = RUNQ; - SCHEDULE(); - } else { - ++kernel.semaphore[sema]; - sei(); - } + SCHEDULE(); } -#endif void sleep(uint32_t ticks) @@ -254,7 +252,7 @@ sleep(uint32_t ticks) cli(); kernel.current->release += ticks; - kernel.current->state = SLEEPING; + kernel.current->state = TIMEQ; SCHEDULE(); } @@ -271,6 +269,7 @@ suspend(void) cli(); kernel.current->state = TERMINATED; + SCHEDULE(); } diff --git a/kernel/kernel.h b/kernel/kernel.h index bf64b39..172fad7 100644 --- a/kernel/kernel.h +++ b/kernel/kernel.h @@ -19,27 +19,32 @@ #define __KERNEL_H #ifndef TASKS -#warning TASKS not set, fallback to default +#warning TASKS not set, fallback to default: 8 #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 -#define SEMAPHORES 8 +#warning SEMAPHORES not set, fallback to default: 4 +#define SEMAPHORES 4 #endif #ifndef STACK -#warning STACK not set, fallback to default +#warning STACK not set, fallback to default: 64 #define STACK 64 #endif #ifndef F_CPU -#warning F_CPU not set, fallback to default +#warning F_CPU not set, fallback to default: 16MHz #define F_CPU 16000000 #endif #ifndef PRESCALE -#warning PRESCALE not set, fallback to default +#warning PRESCALE not set, fallback to default: 1 #define PRESCALE 1 #endif @@ -93,10 +98,10 @@ void init(uint8_t stack); void exec(void (*fun)(void *), void *args, uint8_t stack, uint8_t prio); -void semaphore(uint8_t semnbr, uint8_t initVal); -void wait(uint8_t semnbr); -void signal(uint8_t semnbr); +void wait(uint8_t sema); +void signal(uint8_t sema); + void suspend(void); void sleep(uint32_t ticks); diff --git a/kernel/lcd3.c b/kernel/lcd3.c index e12a408..6bbb847 100644 --- a/kernel/lcd3.c +++ b/kernel/lcd3.c @@ -18,12 +18,15 @@ #define USE_DELAY #include +#include #include #include #include #include "kernel.h" #include "tasks.h" +FILE lcd_stream = FDEV_SETUP_STREAM(lcd_putchar, NULL, _FDEV_SETUP_WRITE); + #define CLEAR_DISPLAY _BV(0) #define RETURN_HOME _BV(1) @@ -47,7 +50,6 @@ #define TWO_LINES _BV(3) /* on 2 / off 1 line */ #define BIG_FONT _BV(2) /* on 5x10 / off 5x7 */ - #define SET_CGRAM_ADDRESS _BV(6) #define SET_DDRAM_ADDRESS _BV(7) #define BUSY_FLAG _BV(7) @@ -59,47 +61,15 @@ #define CLOCK PD6 #define E PD7 -#define write_cmd(x, delay) do { \ - write_byte((x), 0); \ - _delay_us(delay); \ -} while (0) - -#define write_data(x) do { \ - write_byte((x), 1); \ - _delay_us(43); \ -} while (0) - -#define move(line, row) do { \ - write_cmd(SET_DDRAM_ADDRESS | ((line) << 6) | (row), 39); \ -} while (0) - -#define clear() do { \ - write_cmd(CLEAR_DISPLAY, 1530); \ -} while (0) - -#define home() do { \ - write_cmd(RETURN_HOME, 1530); \ -} while (0) - - -/* recomended cycle 1us: 450ns on, 450ns off. - * this is beyond our resolution */ -#define wait_short() do { \ - _NOP(); \ -} while (0) - -#define strobe(port, bit) do { \ - port |= _BV(bit); \ - wait_short(); \ - port &= ~_BV(bit); \ -} while (0) - -#define setif(cond, port, bit) do { \ - if (cond) \ - port |= _BV(bit); \ - else \ - port &= ~_BV(bit); \ -} while (0) +/* recomended cycle: 450ns on, 450ns off. this is beyond our resolution */ +#define strobe(port, bit) do { port |= _BV(bit); _NOP(); port &= ~_BV(bit); } while (0) +#define setif(cond, port, bit) do { if (cond) (port) |= _BV(bit); else (port) &= ~_BV(bit); } while (0) +#define write_data(x) do { write_byte((x), 1); _delay_us(43); } while (0) +#define _write_cmd(x, delay) do { write_byte((x), 0); _delay_us(delay); } while (0) +#define write_cmd(x) _write_cmd((x), 39) +#define move(line, row) _write_cmd(SET_DDRAM_ADDRESS | ((line) << 6) | (row), 39) +#define clear() _write_cmd(CLEAR_DISPLAY, 1530) +#define home() _write_cmd(RETURN_HOME, 1530) static void write_byte(uint8_t byte, uint8_t rs) @@ -107,59 +77,60 @@ write_byte(uint8_t byte, uint8_t rs) uint8_t i; for (i = 0; i < 8; i++) { - setif(byte & (0x80 >> i), PORT, DATA); /* MSF */ + setif(byte & (0x80 >> i), PORT, DATA); /* MSF */ strobe(PORT, CLOCK); } + setif(rs, PORT, DATA); strobe(PORT, E); } -static void -mvputs(uint8_t line, uint8_t row, char *s) -{ - move(line, row); - while (*s) - write_data(*(s++)); -} - -static void -mvputch(uint8_t line, uint8_t row, char ch) -{ - move(line, row); - write_data(ch); -} - void -lcd(void *arg) +lcd_init(void) { - struct lcdarg *a = (struct lcdarg *)arg; - PORTDIR |= (_BV(DATA) | _BV(CLOCK) | _BV(E)); /* task init: wait >40ms */ - sleep(MSEC(40)); + _delay_ms(40); /* 8 bit, 2 line, 5x8 font */ - write_cmd(FUNCTION_SET | DATA_LENGTH_8BIT | TWO_LINES, 39); + write_cmd(FUNCTION_SET | DATA_LENGTH_8BIT | TWO_LINES); /* no BUSY_FLAG until now */ /* display on, cursor off, cursor blink off */ - write_cmd(ON_OFF_CONTROL | DISPLAY_ON, 39); + write_cmd(ON_OFF_CONTROL | DISPLAY_ON); /* clear display */ clear(); /* entry mode */ - write_cmd(ENTRY_MODE_SET | INC_DDRAM, 39); + write_cmd(ENTRY_MODE_SET | INC_DDRAM); home(); - *a->first = '\0'; - *a->second = '\0'; + stderr = &lcd_stream; +} - for (;;) { - mvputs(0, 0, a->first); - mvputs(1, 0, a->second); - sleep(MSEC(40)); +int +lcd_putchar(char c, FILE *fd) +{ + switch (c) { + case '\b': /* XXX */ + clear(); + /* FALLTHROUGH */ + case '\r': + home(); + break; + case '\n': + move(1, 0); + break; + case '\t': + c = ' '; + /* FALLTHROUGH */ + default: + write_data(c); + break; } + + return 0; } diff --git a/kernel/ppm.c b/kernel/ppm.c index 51dc0e5..3d22ac1 100644 --- a/kernel/ppm.c +++ b/kernel/ppm.c @@ -16,6 +16,7 @@ */ #include +#include #include #include #include "kernel.h" diff --git a/kernel/rgb.c b/kernel/rgb.c index ae5e119..0cf9a96 100644 --- a/kernel/rgb.c +++ b/kernel/rgb.c @@ -16,6 +16,7 @@ */ #include +#include #include #include #include "kernel.h" @@ -32,12 +33,21 @@ rgb(void *arg) for (;;) { i = (i + 1) % 360; - hsv(&r, &g, &b, i, v, v); + //hsv(&r, &g, &b, i, v, v); + hsv(&r, &g, &b, i, 255, 255); - //cli(); + wait(1); a->r = r; + signal(1); + + wait(2); a->g = g; + signal(2); + + wait(3); a->b = b; + signal(3); + v = *a->v >> 2; /* 10bit to 8bit */ //sei(); @@ -55,17 +65,21 @@ pwm(void *arg) DDRB |= _BV(a->pin); PORTB &= ~_BV(a->pin); +#define DIV (UINT8_MAX >> 1) + for (;;) { //cli(); + wait(a->sema); v = *a->value; + signal(a->sema); //sei(); - if ((on = SEC2(v) / INT8_MAX)) { + if ((on = SEC2(v) / DIV)) { PORTB |= _BV(a->pin); sleep(on); } - if ((off = SEC2(UINT8_MAX - v) / INT8_MAX)) { + if ((off = SEC2(UINT8_MAX - v) / DIV)) { PORTB &= ~_BV(a->pin); sleep(off); } diff --git a/kernel/tasks.h b/kernel/tasks.h index d89a8c3..98b637a 100644 --- a/kernel/tasks.h +++ b/kernel/tasks.h @@ -51,20 +51,14 @@ struct rgbarg { struct pwmarg { uint8_t *value; uint8_t pin; + uint8_t sema; }; struct adcarg { uint16_t value[ADCCHANNELS]; }; -struct lcdarg { - char first[18]; - char second[18]; - uint8_t x, y; -}; - struct clockarg { - struct lcdarg *lcd; struct adcarg *adc; }; @@ -72,14 +66,16 @@ struct ppmarg { uint16_t *value; }; -void init_uart(void); -int uart_getchar(void); -int uart_putchar(char); +void uart_init(void); +int uart_getchar(FILE *); +int uart_putchar(char, FILE *); + +void lcd_init(void); +int lcd_putchar(char, FILE *); void heartbeat(void *); void rgb(void *); void pwm(void *); -void lcd(void *); void adc(void *); void ppm(void *); void cmd(void *); diff --git a/kernel/uart.c b/kernel/uart.c index e3df551..8407113 100644 --- a/kernel/uart.c +++ b/kernel/uart.c @@ -31,69 +31,25 @@ #include "kernel.h" #include "tasks.h" -int -uart_putchar(char c) -{ - if (c == '\n') - uart_putchar('\r'); - loop_until_bit_is_set(UCSRA, UDRE); - UDR = c; - - return 0; -} - -int -uart_getchar(void) -{ - char c; - -#if 0 /* BLOCKING */ - loop_until_bit_is_set(UCSRA, RXC); -#else - if (bit_is_clear(UCSRA, RXC)) - return 0; -#endif - - if (bit_is_set(UCSRA, FE)) - return -2; /* EOF */ - if (bit_is_set(UCSRA, DOR)) - return -1; /* ERR */ - c = UDR; - - uart_putchar(c); /* ECHO */ - - switch (c) { - case '\r': - c = '\n'; - break; - case '\t': - c = ' '; - break; - default: - break; - } - - return c; -} +FILE uart_stream = FDEV_SETUP_STREAM(uart_putchar, uart_getchar, _FDEV_SETUP_RW); #ifdef USE_RXCIE ISR(SIG_UART_RECV) { - uint8_t c = UDR; - uint8_t *p = 0; + uint8_t c, *p; - switch (c) { + switch ((c = UDR)) { + case 'Z': /* zero */ + for (p = (uint8_t *)RAMSTART; p <= (uint8_t *)RAMEND; p++) + *p = 'A'; + /* FALLTHROUGH */ case 'R': /* reboot */ case '-': /* reboot */ wdt_enable(WDTO_15MS); break; case 'D': /* dump */ - while (p <= (uint8_t *)RAMEND) - uart_putchar(*p++); - break; - case 'N': /* zero */ - while (p <= (uint8_t *)RAMEND) - *p++ = 0xFF; + for (p = (uint8_t *)0; p <= (uint8_t *)RAMEND; p++) + uart_putchar(*p, NULL); break; case 'T': UCSRB |= _BV(UDRIE); @@ -105,7 +61,7 @@ ISR(SIG_UART_RECV) case '\n': break; default: - uart_putchar('?'); + uart_putchar('?', NULL); break; } } @@ -119,7 +75,7 @@ ISR(SIG_UART_DATA) #endif void -init_uart(void) +uart_init(void) { UCSRB = _BV(RXEN) | _BV(TXEN); #ifdef USE_RXCIE @@ -128,4 +84,47 @@ init_uart(void) UBRRH = UBRRH_VALUE; UBRRL = UBRRL_VALUE; UCSRA &= ~_BV(U2X); + + stdin = &uart_stream; + stdout = &uart_stream; +} + +int +uart_putchar(char c, FILE *fd) +{ + if (c == '\n') + uart_putchar('\r', fd); + loop_until_bit_is_set(UCSRA, UDRE); + UDR = c; + + return 0; +} + +int +uart_getchar(FILE *fd) +{ + char c; + + loop_until_bit_is_set(UCSRA, RXC); + + if (bit_is_set(UCSRA, FE)) + return -2; /* EOF */ + if (bit_is_set(UCSRA, DOR)) + return -1; /* ERR */ + + c = UDR; + uart_putchar(c, fd); /* ECHO */ + + switch (c) { + case '\r': + c = '\n'; + break; + case '\t': + c = ' '; + break; + default: + break; + } + + return c; } -- cgit v1.2.3