diff options
Diffstat (limited to 'firmware/src')
| -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);  } | 
