From: batt Date: Sun, 7 Oct 2007 12:32:01 +0000 (+0000) Subject: Add first ver (very) untested skel for AT91 timer. X-Git-Tag: 1.0.0~410 X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=338e860b340dd66f9f6ec92e692a7aa116b0d6a8;p=bertos.git Add first ver (very) untested skel for AT91 timer. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@831 38d2e660-2303-0410-9eaa-f027e97ec537 --- diff --git a/drv/at91/sysirq.c b/drv/at91/sysirq.c new file mode 100755 index 00000000..b018cd62 --- /dev/null +++ b/drv/at91/sysirq.c @@ -0,0 +1,157 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Francesco Sacchi + * + * \brief System irq handler for Atmel AT91 ARM7 processors. + * + * In Atmel AT91 ARM7TDMI processors, there are various + * peripheral interrupt sources. + * In general, every source has its own interrupt vector, so it + * is possible to assign a specific handler for each interrupt + * indipendently. + * However, there are a few sources called "system sources" that + * share a common IRQ line and vector, called "system irq". + * So a unic system irq handler is implemented here. + * This module also contains an interface to manage every source + * indipendently. It is possible to assign to every system irq + * a specific irq handler. + * + * \see sysirq_setHandler + * \see sysirq_setEnable + */ + +#include "sysirq.h" +#include "at91.h" +#include + +#warning Very untested! + +/** + * Returns the state of the Periodic Interval Timer + * interrupt. + */ +static bool pit_enable(void) +{ + return PIT_MR & BV(PITIEN); +} + +/** + * Returns the state of the Periodic Interval Timer + * interrupt. + * \return true is PIT has triggered and interrupt, false otherwise + */ +static bool pit_trigger(void) +{ + return PIT_SR & BV(PITS); +} + +/** + * Enable/disable the Periodic Interrupt Timer + * interrupt. + */ +static void pit_setEnable(bool enable) +{ + if (enable) + PIT_MR |= BV(PITIEN); + else + PIT_MR &= ~BV(PITIEN); +} + +/** + * Table containing all system irqs. + */ +static SysIrq sysirq_tab[] = +{ + /* PIT, Periodic Interval Timer (System timer)*/ + { + .enable = pit_enable, + .trigger = pit_trigger, + .setEnable = pit_setEnable, + .handler = NULL, + }, + /* TODO: add other system sources here */ +}; + +STATIC_ASSERT(countof(sysirq_tab) == SYSIRQ_CNT); + + +/** + * System IRQ handler. + * This is the entry point for all system IRQs in AT91. + * This function checks for interrupt enable state of + * various sources (system timer, etc..) and calls + * the corresponding handler. + */ +static void sysirq_handler(void) +{ + #warning TODO add IRQ prologue/epilogue + for (int i = 0; i < countof(sysirq_tab); i++) + { + if (sysirq_tab[i].enable() + && sysirq_tab[i].trigger() + && sysirq_tab[i].handler) + sysirq_tab[i].handler(); + } +} + +#define SYSIRQ_PRIORITY 0 ///< default priority for system irqs. + +/** + * Init system irq handling. + * \note all system interrupts are disabled. + */ +void sysirq_init(void) +{ + cpuflags_t flags; + IRQ_SAVE_DISABLE(flags); + + /* Disable all system interrupts */ + for (int i = 0; i < countof(sysirq_tab); i++) + sysirq_tab[i].setEnable(false); + + /* Set the vector. */ + AIC_SVR(SYSC_ID) = sysirq_handler; + /* Initialize to edge triggered with defined priority. */ + AIC_SMR(SYSC_ID) = BV(AIC_SRCTYPE_INT_EDGE_TRIGGERED) | SYSIRQ_PRIORITY; + /* Clear interrupt */ + AIC_ICCR = BV(SYSC_ID); + IRQ_RESTORE(flags); +} + + +/** + * Helper function used to set handler for system irq \a irq. + */ +void sysirq_setHandler(sysirq_t irq, sysirq_handler_t handler) +{ + ASSERT(irq >= 0); + ASSERT(irq < SYSIRQ_CNT); + sysirq_tab[irq].handler = handler; +} + +/** + * Helper function used to enable/disable system irq \a irq. + */ +void sysirq_setEnable(sysirq_t irq, bool enable) +{ + ASSERT(irq >= 0); + ASSERT(irq < SYSIRQ_CNT); + sysirq_tab[irq].setEnable(enable); +} + +/** + * Helper function used to get system irq \a irq state. + */ +bool sysirq_enable(sysirq_t irq) +{ + ASSERT(irq >= 0); + ASSERT(irq < SYSIRQ_CNT); + return sysirq_tab[irq].enable(); +} diff --git a/drv/at91/sysirq.h b/drv/at91/sysirq.h new file mode 100755 index 00000000..f58c253a --- /dev/null +++ b/drv/at91/sysirq.h @@ -0,0 +1,49 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Francesco Sacchi + * + * \brief System irq handler for Atmel AT91 ARM7 processors (interface). + */ + +#ifndef DRV_AT91_SYSIRQ_H +#define DRV_AT91_SYSIRQ_H + +typedef void (* sysirq_handler_t)(void); ///< Type for system irq handler. +typedef void (* sysirq_setEnable_t)(bool); ///< Type for system irq enable/disable function. +typedef bool (* sysirq_enable_t)(void); ///< Type for system irq enable getter. +typedef bool (* sysirq_trigger_t)(void); ///< Type for system irq trigger getter. + +/** + * Structure used to define a system interrupt source. + */ +typedef struct SysIrq +{ + sysirq_enable_t enable; ///< Getter for irq enable/disable state. + sysirq_trigger_t trigger; ///< Getter for irq trigger state. + sysirq_setEnable_t setEnable; ///< Setter for irq enable/disable state. + sysirq_handler_t handler; ///< IRQ handler. +} SysIrq; + +/** + * System IRQ ID list. + */ +typedef enum sysirq_t +{ + SYSIRQ_PIT, ///< Periodic Interval Timer + /* TODO: add all system irqs */ + SYSIRQ_CNT +} sysirq_t; + +void sysirq_init(void); +void sysirq_setHandler(sysirq_t irq, sysirq_handler_t handler); +void sysirq_setEnable(sysirq_t irq, bool enable); +bool sysirq_enable(sysirq_t irq); + +#endif /* ARCH_ARM_SYSIRQ_H */ diff --git a/drv/at91/timer.c b/drv/at91/timer.c new file mode 100755 index 00000000..2b396fa1 --- /dev/null +++ b/drv/at91/timer.c @@ -0,0 +1,58 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Francesco Sacchi + * + * \brief Low-level timer module for Atmel AT91 (inplementation). + */ + +#include +#include // BV() + +#include + + +/** HW dependent timer initialization */ +#if (CONFIG_TIMER == TIMER_ON_PIT) + #warning Very untested! + INLINE static void timer_hw_irq(void) + { + /* Reset counters, this is needed to start timer and interrupt flags */ + volatile uint32_t dummy = PIT_PIVR; + } + + + static void timer_hw_init(void) + { + cpuflags_t flags; + IRQ_SAVE_DISABLE(flags); + + PIT_MR = CLOCK_FREQ / (16 * TIMER_TICKS_PER_SEC) - 1; + /* Register system interrupt handler. */ + sysirq_setHandler(SYSIRQ_PIT, timer_handler); + + /* Enable interval timer and interval timer interrupts */ + PIT_MR |= BV(PIT_PITEN); + sysirq_setEnable(SYSIRQ_PIT, true); + + /* Reset counters, this is needed to start timer and interrupt flags */ + volatile uint32_t dummy = PIT_PIVR; + + IRQ_RESTORE(flags); + } + + INLINE hptime_t timer_hw_hpread(void) + { + /* In the upper part of PIT_PIIR there is unused data */ + return PIT_PIIR & 0xfffff; + } + +#else + #error Unimplemented value for CONFIG_TIMER +#endif /* CONFIG_TIMER */ diff --git a/drv/at91/timer.h b/drv/at91/timer.h new file mode 100755 index 00000000..ca3ccdfc --- /dev/null +++ b/drv/at91/timer.h @@ -0,0 +1,53 @@ +/** + * \file + * + * + * \version $Id$ + * + * \author Francesco Sacchi + * + * \brief Low-level timer module for Atmel AT91 (interface). + */ + +#ifndef DRV_AT91_TIMER_H +#define DRV_AT91_TIMER_H + +#include /* CONFIG_TIMER */ +#include /* uint8_t */ +#include /* CLOCK_FREQ */ + +/** + * \name Values for CONFIG_TIMER. + * + * Select which hardware timer interrupt to use for system clock and softtimers. + * + * \{ + */ +#define TIMER_ON_PIT 1 ///< System timer on Periodic interval timer + +#define TIMER_DEFAULT TIMER_ON_PIT ///< Default system timer +/* \} */ + +/* + * Hardware dependent timer initialization. + */ +#if (CONFIG_TIMER == TIMER_ON_PIT) + + #define DEFINE_TIMER_ISR void timer_handler(void) + #define TIMER_TICKS_PER_SEC 1000 + #define TIMER_HW_CNT FIXME + + /// Type of time expressed in ticks of the hardware high-precision timer + typedef uint32_t hptime_t; +#else + + #error Unimplemented value for CONFIG_TIMER +#endif /* CONFIG_TIMER */ + +/** Frequency of the hardware high-precision timer. */ +#define TIMER_HW_HPTICKS_PER_SEC FIXME + +#endif /* DRV_TIMER_AT91_H */