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 unique system IRQ dispatcher is implemented here.
22 * This module also contains an interface to manage every source
23 * independently. It is possible to assign to every system IRQ
24 * a specific IRQ handler.
26 * \see sysirq_setHandler
27 * \see sysirq_setEnable
31 #include "at91sam7s.h"
33 #include <cfg/module.h>
34 #include <cfg/macros.h>
37 * Enable/disable the Periodic Interrupt Timer
40 INLINE void pit_setEnable(bool enable)
45 PIT_MR &= ~BV(PITIEN);
49 * Table containing all system irqs.
51 static SysIrq sysirq_tab[] =
53 /* PIT, Periodic Interval Timer (System timer)*/
56 .setEnable = pit_setEnable,
59 /* TODO: add other system sources here */
62 STATIC_ASSERT(countof(sysirq_tab) == SYSIRQ_CNT);
66 * System IRQ dispatcher.
67 * This is the entry point for all system IRQs in AT91.
68 * This function checks for interrupt enable state of
69 * various sources (system timer, etc..) and calls
70 * the corresponding handler.
72 static void sysirq_dispatcher(void)
74 #warning TODO add IRQ prologue/epilogue
75 for (unsigned i = 0; i < countof(sysirq_tab); i++)
77 if (sysirq_tab[i].enabled
78 && sysirq_tab[i].handler)
79 sysirq_tab[i].handler();
83 #define SYSIRQ_PRIORITY 0 ///< default priority for system irqs.
89 * Init system IRQ handling.
90 * \note all system interrupts are disabled.
92 void sysirq_init(void)
95 IRQ_SAVE_DISABLE(flags);
97 /* Disable all system interrupts */
98 for (unsigned i = 0; i < countof(sysirq_tab); i++)
99 sysirq_tab[i].setEnable(false);
101 /* Set the vector. */
102 AIC_SVR(SYSC_ID) = sysirq_dispatcher;
103 /* Initialize to edge triggered with defined priority. */
104 AIC_SMR(SYSC_ID) = AIC_SRCTYPE_INT_EDGE_TRIGGERED | SYSIRQ_PRIORITY;
105 /* Clear interrupt */
106 AIC_ICCR = BV(SYSC_ID);
114 * Helper function used to set handler for system IRQ \a irq.
116 void sysirq_setHandler(sysirq_t irq, sysirq_handler_t handler)
119 ASSERT(irq < SYSIRQ_CNT);
120 sysirq_tab[irq].handler = handler;
124 * Helper function used to enable/disable system IRQ \a irq.
126 void sysirq_setEnable(sysirq_t irq, bool enable)
129 ASSERT(irq < SYSIRQ_CNT);
131 sysirq_tab[irq].setEnable(enable);
132 sysirq_tab[irq].enabled = enable;
136 * Helper function used to get system IRQ \a irq state.
138 bool sysirq_enabled(sysirq_t irq)
141 ASSERT(irq < SYSIRQ_CNT);
143 return sysirq_tab[irq].enabled;