Add first ver (very) untested skel for AT91 timer.
authorbatt <batt@38d2e660-2303-0410-9eaa-f027e97ec537>
Sun, 7 Oct 2007 12:32:01 +0000 (12:32 +0000)
committerbatt <batt@38d2e660-2303-0410-9eaa-f027e97ec537>
Sun, 7 Oct 2007 12:32:01 +0000 (12:32 +0000)
git-svn-id: https://src.develer.com/svnoss/bertos/trunk@831 38d2e660-2303-0410-9eaa-f027e97ec537

drv/at91/sysirq.c [new file with mode: 0755]
drv/at91/sysirq.h [new file with mode: 0755]
drv/at91/timer.c [new file with mode: 0755]
drv/at91/timer.h [new file with mode: 0755]

diff --git a/drv/at91/sysirq.c b/drv/at91/sysirq.c
new file mode 100755 (executable)
index 0000000..b018cd6
--- /dev/null
@@ -0,0 +1,157 @@
+/**
+ * \file
+ * <!--
+ * Copyright 2007 Develer S.r.l. (http://www.develer.com/)
+ * This file is part of DevLib - See README.devlib for information.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \author Francesco Sacchi <batt@develer.com>
+ *
+ * \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 <cfg/cpu.h>
+
+#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 (executable)
index 0000000..f58c253
--- /dev/null
@@ -0,0 +1,49 @@
+/**
+ * \file
+ * <!--
+ * Copyright 2007 Develer S.r.l. (http://www.develer.com/)
+ * This file is part of DevLib - See README.devlib for information.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \author Francesco Sacchi <batt@develer.com>
+ *
+ * \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 (executable)
index 0000000..2b396fa
--- /dev/null
@@ -0,0 +1,58 @@
+/**
+ * \file
+ * <!--
+ * Copyright 2007 Develer S.r.l. (http://www.develer.com/)
+ * This file is part of DevLib - See README.devlib for information.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \author Francesco Sacchi <batt@develer.com>
+ *
+ * \brief Low-level timer module for Atmel AT91 (inplementation).
+ */
+
+#include <drv/timer_at91.h>
+#include <cfg/macros.h> // BV()
+
+#include <cfg/cpu.h>
+
+
+/** 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 (executable)
index 0000000..ca3ccdf
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * \file
+ * <!--
+ * Copyright 2007 Develer S.r.l. (http://www.develer.com/)
+ * This file is part of DevLib - See README.devlib for information.
+ * -->
+ *
+ * \version $Id$
+ *
+ * \author Francesco Sacchi <batt@develer.com>
+ *
+ * \brief Low-level timer module for Atmel AT91 (interface).
+ */
+
+#ifndef DRV_AT91_TIMER_H
+#define DRV_AT91_TIMER_H
+
+#include <appconfig.h>     /* CONFIG_TIMER */
+#include <cfg/compiler.h>  /* uint8_t */
+#include <hw_cpu.h>        /* 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 */