diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/src/os/blinkcode.c | 38 | ||||
-rw-r--r-- | firmware/src/os/main.c | 7 | ||||
-rw-r--r-- | firmware/src/os/pit.c | 33 | ||||
-rw-r--r-- | firmware/src/os/pit.h | 4 | ||||
-rw-r--r-- | firmware/src/os/system_irq.c | 73 |
5 files changed, 98 insertions, 57 deletions
diff --git a/firmware/src/os/blinkcode.c b/firmware/src/os/blinkcode.c index 8485392..22d4b25 100644 --- a/firmware/src/os/blinkcode.c +++ b/firmware/src/os/blinkcode.c @@ -19,14 +19,15 @@ enum blinkcode_state { BLINKCODE_STATE_DONE, }; -#define TIME_SILENT (1000) -#define TIME_INIT (1000) -#define TIME_BLINK (100) +#define TIME_SILENT (1*HZ) +#define TIME_INIT (1*HZ) +#define TIME_BLINK (HZ/4) struct blinker { struct timer_list timer; enum blinkcode_state state; - int8_t num; + int num; + int cur; u_int8_t led; }; @@ -36,12 +37,15 @@ static void blinkcode_cb(void *data) { /* we got called back by the timer */ struct blinker *bl = data; - + + DEBUGPCRF("(jiffies=%lu, data=%p, state=%u)", + jiffies, data, bl->state); switch (bl->state) { case BLINKCODE_STATE_NONE: led_switch(bl->led, 0); bl->state = BLINKCODE_STATE_SILENT; bl->timer.expires = jiffies + TIME_SILENT; + bl->cur = bl->num; break; case BLINKCODE_STATE_SILENT: /* we've finished the period of silence, turn led on */ @@ -53,22 +57,27 @@ static void blinkcode_cb(void *data) /* we've finished the period of init */ led_switch(bl->led, 0); bl->state = BLINKCODE_STATE_BLINK_OFF; - bl->timer.expires = jiffies + TIME_BLINK; + bl->timer.expires = jiffies + TIME_INIT; break; case BLINKCODE_STATE_BLINK_OFF: /* we've been off, turn on */ led_switch(bl->led, 1); bl->state = BLINKCODE_STATE_BLINK_ON; - bl->num--; - if (bl->num <= 0) { - bl->state = BLINKCODE_STATE_NONE; - return; - } + bl->cur--; + bl->timer.expires = jiffies + TIME_BLINK; + if (bl->cur <= 0) + bl->state = BLINKCODE_STATE_DONE; break; case BLINKCODE_STATE_BLINK_ON: /* we've been on, turn off */ led_switch(bl->led, 0); bl->state = BLINKCODE_STATE_BLINK_OFF; + bl->timer.expires = jiffies + TIME_BLINK; + break; + case BLINKCODE_STATE_DONE: + /* we've been on, turn off */ + led_switch(bl->led, 0); + return; break; } /* default case: re-add the timer */ @@ -77,13 +86,16 @@ static void blinkcode_cb(void *data) void blinkcode_set(int led, enum blinkcode_num num) { - if (led >= NUM_LEDS) + DEBUGPCRF("(jiffies=%lu, led=%u, num=%u)", jiffies, led, num); + + if (--led > NUM_LEDS) return; timer_del(&blink_state[led].timer); blink_state[led].num = num; blink_state[led].state = BLINKCODE_STATE_NONE; + blink_state[led].timer.expires = jiffies; if (num != BLINKCODE_NONE) timer_add(&blink_state[led].timer); @@ -97,5 +109,7 @@ void blinkcode_init(void) blink_state[i].num = 0; blink_state[i].state = BLINKCODE_STATE_NONE; blink_state[i].led = i+1; + blink_state[i].timer.data = &blink_state[i]; + blink_state[i].timer.function = &blinkcode_cb; } } diff --git a/firmware/src/os/main.c b/firmware/src/os/main.c index f39234b..0cc9d99 100644 --- a/firmware/src/os/main.c +++ b/firmware/src/os/main.c @@ -23,8 +23,12 @@ #include <include/lib_AT91SAM7.h> #include <os/dbgu.h> #include <os/led.h> +#include <os/blinkcode.h> #include <os/main.h> #include <os/power.h> +#include <os/system_irq.h> +#include <os/pit.h> +#include <os/wdt.h> #include <os/usbcmd_generic.h> #include <os/pcd_enumerate.h> #include "../openpcd.h" @@ -47,6 +51,7 @@ int main(void) AT91F_PIOA_CfgPMC(); wdt_init(); pit_init(); + blinkcode_init(); /* initialize USB */ req_ctx_init(); @@ -73,7 +78,7 @@ int main(void) /* Call application specific main idle function */ _main_func(); dbgu_rb_flush(); - wdt_restart(); + //wdt_restart(); #ifdef CONFIG_IDLE //cpu_idle(); #endif diff --git a/firmware/src/os/pit.c b/firmware/src/os/pit.c index 8bf13ba..6b68e84 100644 --- a/firmware/src/os/pit.c +++ b/firmware/src/os/pit.c @@ -26,6 +26,7 @@ #include <lib_AT91SAM7.h> #include <AT91SAM7.h> #include <os/pit.h> +#include <os/dbgu.h> #include <os/system_irq.h> #include "../openpcd.h" @@ -35,7 +36,7 @@ static struct timer_list *timers; -unsigned long jiffies; +volatile unsigned long jiffies; static void __timer_insert(struct timer_list *new) { @@ -63,7 +64,7 @@ static void __timer_insert(struct timer_list *new) } } -static void __timer_remove(struct timer_list *old) +static int __timer_remove(struct timer_list *old) { struct timer_list *tl, *tl_prev = NULL; @@ -73,18 +74,24 @@ static void __timer_remove(struct timer_list *old) timers = tl->next; else tl_prev->next = tl->next; + return 1; } tl_prev = tl; } + + return 0; } int timer_del(struct timer_list *tl) { unsigned long flags; + int ret; local_irq_save(flags); - __timer_remove(tl); + ret = __timer_remove(tl); local_irq_restore(flags); + + return ret; } void timer_add(struct timer_list *tl) @@ -98,21 +105,23 @@ void timer_add(struct timer_list *tl) static void pit_irq(u_int32_t sr) { - struct timer_list *tl; + struct timer_list *tl, *next; unsigned long flags; - jiffies += *AT91C_PITC_PIVR; + if (!(sr & 0x1)) + return; + + jiffies += *AT91C_PITC_PIVR >> 20; /* this is the most simple/stupid algorithm one can come up with, but * hey, we're on a small embedded platform with only a hand ful * of timers, at all */ - for (tl = timers; tl != 0; tl = tl->next) { - if (tl->expires >= jiffies) { - tl->function(tl->data); - local_irq_save(flags); + for (tl = timers; tl != NULL; tl = next) { + next = tl->next; + if (tl->expires <= jiffies) { /* delete timer from list */ - __timer_remove(tl); - local_irq_restore(flags); + timer_del(tl); + tl->function(tl->data); } } } @@ -130,7 +139,7 @@ void pit_init(void) { AT91F_PITC_CfgPMC(); - AT91F_PITInit(AT91C_BASE_PITC, 1000 /* uS */, 48 /* MHz */); + AT91F_PITInit(AT91C_BASE_PITC, 1000000/HZ /* uS */, 48 /* MHz */); sysirq_register(AT91SAM7_SYSIRQ_PIT, &pit_irq); diff --git a/firmware/src/os/pit.h b/firmware/src/os/pit.h index e941aeb..4a25cc1 100644 --- a/firmware/src/os/pit.h +++ b/firmware/src/os/pit.h @@ -3,6 +3,8 @@ #include <sys/types.h> +#define HZ 100 + /* This API (but not the code) is modelled after the Linux API */ struct timer_list { @@ -12,7 +14,7 @@ struct timer_list { void *data; }; -extern unsigned long jiffies; +extern volatile unsigned long jiffies; extern void timer_add(struct timer_list *timer); extern int timer_del(struct timer_list *timer); diff --git a/firmware/src/os/system_irq.c b/firmware/src/os/system_irq.c index 455791c..dc787eb 100644 --- a/firmware/src/os/system_irq.c +++ b/firmware/src/os/system_irq.c @@ -33,7 +33,7 @@ static sysirq_hdlr *sysirq_hdlrs[AT91SAM7_SYSIRQ_COUNT]; static void sys_irq(void) { u_int32_t sr; - DEBUGP("sys_irq: "); + DEBUGP("sys_irq "); /* Somehow Atmel decided to do really stupid interrupt sharing * for commonly-used interrupts such as the timer irq */ @@ -41,9 +41,8 @@ static void sys_irq(void) /* dbgu */ if (*AT91C_DBGU_IMR) { sr = *AT91C_DBGU_CSR; - DEBUGP("DBGU("); if (sr & *AT91C_DBGU_IMR) { - DEBUGP("found "); + DEBUGP("DBGU("); if (sysirq_hdlrs[AT91SAM7_SYSIRQ_DBGU]) { DEBUGP("handler "); sysirq_hdlrs[AT91SAM7_SYSIRQ_DBGU](sr); @@ -51,96 +50,108 @@ static void sys_irq(void) *AT91C_DBGU_IDR = *AT91C_DBGU_IMR; DEBUGP("no handler "); } + DEBUGP(") "); } - DEBUGP(") "); } /* pit_irq */ if (*AT91C_PITC_PIMR & AT91C_PITC_PITIEN) { sr = *AT91C_PITC_PISR; - DEBUGP("PIT("); if (sr & AT91C_PITC_PITS) { - DEBUGP("found "); if (sysirq_hdlrs[AT91SAM7_SYSIRQ_PIT]) { - DEBUGP("handler "); sysirq_hdlrs[AT91SAM7_SYSIRQ_PIT](sr); } else { + DEBUGP("no handler DISABLE_PIT "); *AT91C_PITC_PIMR &= ~AT91C_PITC_PITIEN; - DEBUGP("no handler "); } } - DEBUGP(") "); } /* rtt_irq */ if (*AT91C_RTTC_RTMR & (AT91C_RTTC_ALMIEN|AT91C_RTTC_RTTINCIEN)) { sr = *AT91C_RTTC_RTSR; - DEBUGP("RTT("); if (sr) { - if (sysirq_hdlrs[AT91SAM7_SYSIRQ_RTT]) + DEBUGP("RTT("); + if (sysirq_hdlrs[AT91SAM7_SYSIRQ_RTT]) { + DEBUGP("handler "); sysirq_hdlrs[AT91SAM7_SYSIRQ_RTT](sr); - else + } else { *AT91C_RTTC_RTMR &= ~(AT91C_RTTC_ALMIEN| AT91C_RTTC_RTTINCIEN); + DEBUGP("no handler "); + } + DEBUGP(") "); } - DEBUGP(") "); } /* pmc_irq */ if (*AT91C_PMC_IMR) { sr = *AT91C_PMC_SR; - DEBUGP("PMC("); if (sr & *AT91C_PMC_IMR) { - if (sysirq_hdlrs[AT91SAM7_SYSIRQ_PMC]) + DEBUGP("PMC("); + if (sysirq_hdlrs[AT91SAM7_SYSIRQ_PMC]) { + DEBUGP("handler "); sysirq_hdlrs[AT91SAM7_SYSIRQ_PMC](sr); - else + } else { *AT91C_PMC_IDR = *AT91C_PMC_IMR; + DEBUGP("no handler "); + } + DEBUGP(") "); } - DEBUGP(") "); } /* rstc_irq */ if (*AT91C_RSTC_RMR & (AT91C_RSTC_URSTIEN|AT91C_RSTC_BODIEN)) { sr = *AT91C_RSTC_RSR; - DEBUGP("RSTC("); if (sr & (AT91C_RSTC_URSTS|AT91C_RSTC_BODSTS)) { - if (sysirq_hdlrs[AT91SAM7_SYSIRQ_RSTC]) + DEBUGP("RSTC("); + if (sysirq_hdlrs[AT91SAM7_SYSIRQ_RSTC]) { + DEBUGP("handler "); sysirq_hdlrs[AT91SAM7_SYSIRQ_RSTC](sr); - else + } else { *AT91C_RSTC_RMR &= ~(AT91C_RSTC_URSTIEN| AT91C_RSTC_BODIEN); + DEBUGP("no handler "); + } + DEBUGP(") "); } - DEBUGP(") "); } /* mc_irq */ if (*AT91C_MC_FMR & (AT91C_MC_LOCKE | AT91C_MC_PROGE)) { sr = *AT91C_MC_FSR; - DEBUGP("EFC("); if ((*AT91C_MC_FMR & AT91C_MC_LOCKE && (sr & AT91C_MC_LOCKE))|| (*AT91C_MC_FMR & AT91C_MC_PROGE && (sr & AT91C_MC_PROGE))){ - if (sysirq_hdlrs[AT91SAM7_SYSIRQ_EFC]) + DEBUGP("EFC("); + if (sysirq_hdlrs[AT91SAM7_SYSIRQ_EFC]) { + DEBUGP("handler "); sysirq_hdlrs[AT91SAM7_SYSIRQ_EFC](sr); - else + } else { *AT91C_MC_FMR &= ~(AT91C_MC_LOCKE | AT91C_MC_PROGE); + DEBUGP("no handler "); + } + DEBUGP(") "); } - DEBUGP(") "); } /* wdt_irq */ if (*AT91C_WDTC_WDMR & AT91C_WDTC_WDFIEN) { sr = *AT91C_WDTC_WDSR; - DEBUGP("WDT("); if (sr) { - if (sysirq_hdlrs[AT91SAM7_SYSIRQ_WDT]) + DEBUGP("WDT("); + if (sysirq_hdlrs[AT91SAM7_SYSIRQ_WDT]) { + DEBUGP("handler "); sysirq_hdlrs[AT91SAM7_SYSIRQ_WDT](sr); - /* we can't disable it... */ + } else { + /* we can't disable it... */ + DEBUGP("no handler "); + } + DEBUGP(") "); } - DEBUGP(") "); } AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_SYS); - DEBUGPCR(""); + DEBUGPCR("END"); } void sysirq_register(enum sysirqs irq, sysirq_hdlr *hdlr) @@ -155,7 +166,7 @@ void sysirq_init(void) { AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS, OPENPCD_IRQ_PRIO_SYS, - AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, + AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, &sys_irq); AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS); } |