4 * Copyright 2007 Develer S.r.l. (http://www.develer.com/)
5 * This file is part of DevLib - See README.devlib for information.
10 * \author Francesco Sacchi <batt@develer.com>
12 * \brief System irq handler for Atmel AT91 ARM7 processors.
14 * In Atmel AT91 ARM7TDMI processors, there are various
15 * peripheral interrupt sources.
16 * In general, every source has its own interrupt vector, so it
17 * is possible to assign a specific handler for each interrupt
19 * However, there are a few sources called "system sources" that
20 * share a common IRQ line and vector, called "system irq".
21 * So a unic system irq handler is implemented here.
22 * This module also contains an interface to manage every source
23 * indipendently. It is possible to assign to every system irq
24 * a specific irq handler.
26 * \see sysirq_setHandler
27 * \see sysirq_setEnable
34 #warning Very untested!
37 * Returns the state of the Periodic Interval Timer
40 static bool pit_enable(void)
42 return PIT_MR & BV(PITIEN);
46 * Returns the state of the Periodic Interval Timer
48 * \return true is PIT has triggered and interrupt, false otherwise
50 static bool pit_trigger(void)
52 return PIT_SR & BV(PITS);
56 * Enable/disable the Periodic Interrupt Timer
59 static void pit_setEnable(bool enable)
64 PIT_MR &= ~BV(PITIEN);
68 * Table containing all system irqs.
70 static SysIrq sysirq_tab[] =
72 /* PIT, Periodic Interval Timer (System timer)*/
75 .trigger = pit_trigger,
76 .setEnable = pit_setEnable,
79 /* TODO: add other system sources here */
82 STATIC_ASSERT(countof(sysirq_tab) == SYSIRQ_CNT);
87 * This is the entry point for all system IRQs in AT91.
88 * This function checks for interrupt enable state of
89 * various sources (system timer, etc..) and calls
90 * the corresponding handler.
92 static void sysirq_handler(void)
94 #warning TODO add IRQ prologue/epilogue
95 for (int i = 0; i < countof(sysirq_tab); i++)
97 if (sysirq_tab[i].enable()
98 && sysirq_tab[i].trigger()
99 && sysirq_tab[i].handler)
100 sysirq_tab[i].handler();
104 #define SYSIRQ_PRIORITY 0 ///< default priority for system irqs.
107 * Init system irq handling.
108 * \note all system interrupts are disabled.
110 void sysirq_init(void)
113 IRQ_SAVE_DISABLE(flags);
115 /* Disable all system interrupts */
116 for (int i = 0; i < countof(sysirq_tab); i++)
117 sysirq_tab[i].setEnable(false);
119 /* Set the vector. */
120 AIC_SVR(SYSC_ID) = sysirq_handler;
121 /* Initialize to edge triggered with defined priority. */
122 AIC_SMR(SYSC_ID) = BV(AIC_SRCTYPE_INT_EDGE_TRIGGERED) | SYSIRQ_PRIORITY;
123 /* Clear interrupt */
124 AIC_ICCR = BV(SYSC_ID);
130 * Helper function used to set handler for system irq \a irq.
132 void sysirq_setHandler(sysirq_t irq, sysirq_handler_t handler)
135 ASSERT(irq < SYSIRQ_CNT);
136 sysirq_tab[irq].handler = handler;
140 * Helper function used to enable/disable system irq \a irq.
142 void sysirq_setEnable(sysirq_t irq, bool enable)
145 ASSERT(irq < SYSIRQ_CNT);
146 sysirq_tab[irq].setEnable(enable);
150 * Helper function used to get system irq \a irq state.
152 bool sysirq_enable(sysirq_t irq)
155 ASSERT(irq < SYSIRQ_CNT);
156 return sysirq_tab[irq].enable();