diff options
Diffstat (limited to 'firmware/src')
| -rw-r--r-- | firmware/src/openpcd.h | 2 | ||||
| -rw-r--r-- | firmware/src/os/dbgu.c | 12 | ||||
| -rw-r--r-- | firmware/src/os/main.c | 3 | ||||
| -rw-r--r-- | firmware/src/os/pit.c | 12 | ||||
| -rw-r--r-- | firmware/src/os/system_irq.c | 161 | ||||
| -rw-r--r-- | firmware/src/os/system_irq.h | 22 | ||||
| -rw-r--r-- | firmware/src/os/wdt.c | 4 | 
7 files changed, 200 insertions, 16 deletions
diff --git a/firmware/src/openpcd.h b/firmware/src/openpcd.h index 9ad7288..f17b16e 100644 --- a/firmware/src/openpcd.h +++ b/firmware/src/openpcd.h @@ -161,6 +161,8 @@  #define OPENPCD_IRQ_PRIO_SPI	AT91C_AIC_PRIOR_HIGHEST  #define OPENPCD_IRQ_PRIO_SSC	(AT91C_AIC_PRIOR_HIGHEST-1) +#define OPENPCD_IRQ_PRIO_SYS	(AT91C_AIC_PRIOR_HIGHEST-2) +#define OPENPCD_IRQ_PRIO_TC_FDT (AT91C_AIC_PRIOR_LOWEST+3)  #define OPENPCD_IRQ_PRIO_UDP	(AT91C_AIC_PRIOR_LOWEST+2)  #define OPENPCD_IRQ_PRIO_PIT	(AT91C_AIC_PRIOR_LOWEST+1)  #define OPENPCD_IRQ_PRIO_RC632	AT91C_AIC_PRIOR_LOWEST diff --git a/firmware/src/os/dbgu.c b/firmware/src/os/dbgu.c index 458aa4e..a3a5941 100644 --- a/firmware/src/os/dbgu.c +++ b/firmware/src/os/dbgu.c @@ -40,6 +40,7 @@  #include "../openpcd.h"  #include <os/led.h>  #include <os/main.h> +#include <os/system_irq.h>  #include <asm/system.h>  #include <compile.h> @@ -72,10 +73,10 @@ static void Send_reset(void)  //*----------------------------------------------------------------------------  //* Function Name       : DBGU_irq_handler -//* Object              : C handler interrupt function called by the interrupts -//*                       assembling routine +//* Object              : C handler interrupt function called by the sysirq +//*                       demultiplexer  //*---------------------------------------------------------------------------- -static void DBGU_irq_handler(void) +static void DBGU_irq_handler(u_int32_t sr)  {  	static char value; @@ -140,10 +141,7 @@ void AT91F_DBGU_Init(void)  	AT91F_US_EnableIt((AT91PS_USART) AT91C_BASE_DBGU, AT91C_US_RXRDY);  	//* open interrupt -	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS, USART_SYS_LEVEL, -			      AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, -			      DBGU_irq_handler); -	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS); +	sysirq_register(AT91SAM7_SYSIRQ_DBGU, &DBGU_irq_handler);  	AT91F_DBGU_Printk("\n\r");  	AT91F_DBGU_Printk("(C) 2006 by Harald Welte <hwelte@hmw-consulting.de>\n\r" diff --git a/firmware/src/os/main.c b/firmware/src/os/main.c index b9ed4dc..f39234b 100644 --- a/firmware/src/os/main.c +++ b/firmware/src/os/main.c @@ -41,11 +41,12 @@ int main(void)  {  	/* initialize LED and debug unit */  	led_init(); +	sysirq_init();  	AT91F_DBGU_Init();  	AT91F_PIOA_CfgPMC(); -  	wdt_init(); +	pit_init();  	/* initialize USB */  	req_ctx_init(); diff --git a/firmware/src/os/pit.c b/firmware/src/os/pit.c index 5c096cc..8bf13ba 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/system_irq.h>  #include "../openpcd.h" @@ -95,12 +96,12 @@ void timer_add(struct timer_list *tl)  	local_irq_restore(flags);  } -static void pit_irq(void) +static void pit_irq(u_int32_t sr)  {  	struct timer_list *tl;  	unsigned long flags; -	jiffies++; +	jiffies += *AT91C_PITC_PIVR;  	/* 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 @@ -131,10 +132,7 @@ void pit_init(void)  	AT91F_PITInit(AT91C_BASE_PITC, 1000 /* uS */, 48 /* MHz */); -	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS, -			      OPENPCD_IRQ_PRIO_PIT, -			      AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, -			      &pit_irq); +	sysirq_register(AT91SAM7_SYSIRQ_PIT, &pit_irq);	 -	//AT91F_PITEnableInt(AT91C_BASE_PITC); +	AT91F_PITEnableInt(AT91C_BASE_PITC);  } diff --git a/firmware/src/os/system_irq.c b/firmware/src/os/system_irq.c new file mode 100644 index 0000000..455791c --- /dev/null +++ b/firmware/src/os/system_irq.c @@ -0,0 +1,161 @@ +/* SAM7S system interrupt demultiplexer + * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de> + * + *  This program is free software; you can redistribute it and/or modify + *  it under the terms of the GNU General Public License as published by  + *  the Free Software Foundation; either version 2 of the License, or + *  (at your option) any later version. + * + *  This program is distributed in the hope that it will be useful, + *  but WITHOUT ANY WARRANTY; without even the implied warranty of + *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + *  GNU General Public License for more details. + * + *  You should have received a copy of the GNU General Public License + *  along with this program; if not, write to the Free Software + *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA + * + */ + +#undef DEBUG + +#include <sys/types.h> +#include <lib_AT91SAM7.h> +#include <AT91SAM7.h> + +#include <os/system_irq.h> +#include <os/dbgu.h> + +#include "../openpcd.h" + +static sysirq_hdlr *sysirq_hdlrs[AT91SAM7_SYSIRQ_COUNT]; + +static void sys_irq(void) +{ +	u_int32_t sr; +	DEBUGP("sys_irq: "); + +	/* Somehow Atmel decided to do really stupid interrupt sharing +	 * for commonly-used interrupts such as the timer irq */ + +	/* dbgu */ +	if (*AT91C_DBGU_IMR) { +		sr = *AT91C_DBGU_CSR; +		DEBUGP("DBGU("); +		if (sr & *AT91C_DBGU_IMR) { +			DEBUGP("found "); +			if (sysirq_hdlrs[AT91SAM7_SYSIRQ_DBGU]) { +				DEBUGP("handler "); +				sysirq_hdlrs[AT91SAM7_SYSIRQ_DBGU](sr); +			} else { +				*AT91C_DBGU_IDR = *AT91C_DBGU_IMR; +				DEBUGP("no handler "); +			} +		} +		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 { +				*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]) +				sysirq_hdlrs[AT91SAM7_SYSIRQ_RTT](sr); +			else +				*AT91C_RTTC_RTMR &= ~(AT91C_RTTC_ALMIEN| +						      AT91C_RTTC_RTTINCIEN); +		} +		DEBUGP(") "); +	} + +	/* pmc_irq */ +	if (*AT91C_PMC_IMR) { +		sr = *AT91C_PMC_SR; +		DEBUGP("PMC("); +		if (sr & *AT91C_PMC_IMR) { +			if (sysirq_hdlrs[AT91SAM7_SYSIRQ_PMC]) +				sysirq_hdlrs[AT91SAM7_SYSIRQ_PMC](sr); +			else +				*AT91C_PMC_IDR = *AT91C_PMC_IMR; +		} +		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]) +				sysirq_hdlrs[AT91SAM7_SYSIRQ_RSTC](sr); +			else +				*AT91C_RSTC_RMR &= ~(AT91C_RSTC_URSTIEN| +						     AT91C_RSTC_BODIEN); +		} +		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]) +		    		sysirq_hdlrs[AT91SAM7_SYSIRQ_EFC](sr); +			else +				*AT91C_MC_FMR &= ~(AT91C_MC_LOCKE | +						   AT91C_MC_PROGE); +		} +		DEBUGP(") "); +	} +	     +	/* wdt_irq */ +	if (*AT91C_WDTC_WDMR & AT91C_WDTC_WDFIEN) { +		sr = *AT91C_WDTC_WDSR; +		DEBUGP("WDT("); +		if (sr) { +			if (sysirq_hdlrs[AT91SAM7_SYSIRQ_WDT]) +				sysirq_hdlrs[AT91SAM7_SYSIRQ_WDT](sr); +			/* we can't disable it... */ +		} +		DEBUGP(") "); +	} +	AT91F_AIC_ClearIt(AT91C_BASE_AIC, AT91C_ID_SYS); +	DEBUGPCR(""); +} + +void sysirq_register(enum sysirqs irq, sysirq_hdlr *hdlr) +{ +	if (irq >= AT91SAM7_SYSIRQ_COUNT) +		return; + +	sysirq_hdlrs[irq] = hdlr; +} + +void sysirq_init(void) +{ +	AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS, +			      OPENPCD_IRQ_PRIO_SYS, +			      AT91C_AIC_SRCTYPE_INT_POSITIVE_EDGE, +			      &sys_irq); +	AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS); +} diff --git a/firmware/src/os/system_irq.h b/firmware/src/os/system_irq.h new file mode 100644 index 0000000..195b7b9 --- /dev/null +++ b/firmware/src/os/system_irq.h @@ -0,0 +1,22 @@ +#ifndef _SYSTEM_IRQ_H +#define _SYSTEM_IRQ_H + +#include <sys/types.h> + +enum sysirqs { +	AT91SAM7_SYSIRQ_PIT 	= 0, +	AT91SAM7_SYSIRQ_DBGU	= 1, +	AT91SAM7_SYSIRQ_EFC	= 2, +	AT91SAM7_SYSIRQ_WDT	= 3, +	AT91SAM7_SYSIRQ_RTT	= 4, +	AT91SAM7_SYSIRQ_RSTC	= 5, +	AT91SAM7_SYSIRQ_PMC	= 6, +	AT91SAM7_SYSIRQ_COUNT +}; + +typedef void sysirq_hdlr(u_int32_t sr); + +extern void sysirq_register(enum sysirqs irq, sysirq_hdlr *hdlr); +extern void sysirq_init(void); + +#endif diff --git a/firmware/src/os/wdt.c b/firmware/src/os/wdt.c index 5a3c809..55a0e70 100644 --- a/firmware/src/os/wdt.c +++ b/firmware/src/os/wdt.c @@ -21,10 +21,11 @@  #include <AT91SAM7.h>  #include <os/dbgu.h> +#include <os/system_irq.h>  #define WDT_DEBUG -static void wdt_irq(void) +static void wdt_irq(u_int32_t sr)  {  	DEBUGPCRF("================> WATCHDOG EXPIRED !!!!!");  } @@ -36,6 +37,7 @@ void wdt_restart(void)  void wdt_init(void)  { +	sysirq_register(AT91SAM7_SYSIRQ_WDT, &wdt_irq);  #ifdef WDT_DEBUG  	AT91F_WDTSetMode(AT91C_BASE_WDTC, (0xfff << 16) |  			 AT91C_WDTC_WDDBGHLT | AT91C_WDTC_WDIDLEHLT |  | 
