#include <cyg/hal/var_io.h> // platform registers
// -------------------------------------------------------------------------
-// Clock support
-
-static cyg_uint32 _period;
-
-void hal_clock_initialize(cyg_uint32 period)
-{
- CYG_ADDRESS timer = AT91_TC+AT91_TC_TC0;
-
- CYG_ASSERT(period < 0x10000, "Invalid clock period");
-
- // Disable counter
- HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_CLKDIS);
-
- // Set registers
- HAL_WRITE_UINT32(timer+AT91_TC_CMR, AT91_TC_CMR_CPCTRG | // Reset counter on CPC
- AT91_TC_CMR_CLKS_MCK32); // 1 MHz
- HAL_WRITE_UINT32(timer+AT91_TC_RC, period);
-
- // Start timer
- HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_TRIG | AT91_TC_CCR_CLKEN);
-
- // Enable timer 0 interrupt
- HAL_WRITE_UINT32(timer+AT91_TC_IER, AT91_TC_IER_CPC);
-}
+// Hardware init
-void hal_clock_reset(cyg_uint32 vector, cyg_uint32 period)
+void hal_hardware_init(void)
{
- CYG_ADDRESS timer = AT91_TC+AT91_TC_TC0;
- cyg_uint32 sr;
-
- CYG_ASSERT(period < 0x10000, "Invalid clock period");
-
- HAL_READ_UINT32(timer+AT91_TC_SR, sr); // Clear interrupt
+ unsigned i;
- if (period != _period) {
- hal_clock_initialize(period);
- }
- _period = period;
+ // Reset all interrupts
+ HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IDCR, 0xFFFFFFFF);
-}
+ // Flush internal priority level stack
+ for (i = 0; i < 8; ++i)
+ HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_EOI, 0xFFFFFFFF);
-void hal_clock_read(cyg_uint32 *pvalue)
-{
- CYG_ADDRESS timer = AT91_TC+AT91_TC_TC0;
- cyg_uint32 val;
+#ifdef HAL_PLF_HARDWARE_INIT
+ // Perform any platform specific initializations
+ HAL_PLF_HARDWARE_INIT();
+#endif
- HAL_READ_UINT32(timer+AT91_TC_CV, val);
- *pvalue = val;
+ // Set up eCos/ROM interfaces
+ hal_if_init();
}
-// -------------------------------------------------------------------------
-//
-// Delay for some number of micro-seconds
-// Use timer #2 in MCLOCK/32 mode.
-//
-void hal_delay_us(cyg_int32 usecs)
+#if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
+// Decode a system interrupt. Not all systems have all interrupts. So
+// code will only be generated for those interrupts which have a
+// defined value.
+static int sys_irq_handler(void)
{
- cyg_uint32 stat;
- cyg_uint64 ticks;
-#if defined(CYGHWR_HAL_ARM_AT91_JTST)
- // TC2 is reserved for AD/DA. Use TC1 instead.
- CYG_ADDRESS timer = AT91_TC+AT91_TC_TC1;
-#else
- CYG_ADDRESS timer = AT91_TC+AT91_TC_TC2;
+ cyg_uint32 sr, mr;
+
+#ifdef CYGNUM_HAL_INTERRUPT_PITC
+ // Periodic Interrupt Timer Controller
+ HAL_READ_UINT32((AT91_PITC+AT91_PITC_PISR), sr);
+ if (sr & AT91_PITC_PISR_PITS) {
+ return CYGNUM_HAL_INTERRUPT_PITC;
+ }
#endif
- // Calculate how many timer ticks the required number of
- // microseconds equate to. We do this calculation in 64 bit
- // arithmetic to avoid overflow.
- ticks = (((cyg_uint64)usecs) * ((cyg_uint64)CYGNUM_HAL_ARM_AT91_CLOCK_SPEED))/32000000LL;
-
- // Disable counter
- HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_CLKDIS);
-
- // Set registers
- HAL_WRITE_UINT32(timer+AT91_TC_CMR, AT91_TC_CMR_CLKS_MCK32); // 1MHz
- HAL_WRITE_UINT32(timer+AT91_TC_RA, 0);
- HAL_WRITE_UINT32(timer+AT91_TC_RC, ticks);
- // Clear status flags
- HAL_READ_UINT32(timer+AT91_TC_SR, stat);
-
- // Start timer
- HAL_WRITE_UINT32(timer+AT91_TC_CCR, AT91_TC_CCR_TRIG | AT91_TC_CCR_CLKEN);
-
- // Wait for the compare
- do {
- HAL_READ_UINT32(timer+AT91_TC_SR, stat);
- } while ((stat & AT91_TC_SR_CPC) == 0);
-}
+#ifdef CYGNUM_HAL_INTERRUPT_DBG
+ // Debug Unit
+ HAL_READ_UINT32((AT91_DBG + AT91_DBG_CSR), sr);
+ HAL_READ_UINT32((AT91_DBG + AT91_DBG_IMR), mr);
+ if (sr & mr) {
+ return CYGNUM_HAL_INTERRUPT_DBG;
+ }
+#endif
-// -------------------------------------------------------------------------
-// Hardware init
+#ifdef CYGNUM_HAL_INTERRUPT_RTTC
+ /* Real Time Timer. Check the interrupt is enabled, not that just
+ the status indicates there is an interrupt. It takes a while for
+ the status bit to clear. */
+ HAL_READ_UINT32((AT91_RTTC+AT91_RTTC_RTSR), sr);
+ HAL_READ_UINT32((AT91_RTTC+AT91_RTTC_RTMR), mr);
+ if (((mr & AT91_RTTC_RTMR_ALMIEN) &&
+ (sr & AT91_RTTC_RTSR_ALMS)) ||
+ ((mr & AT91_RTTC_RTMR_RTTINCIEN) &&
+ (sr & AT91_RTTC_RTSR_RTTINC))) {
+ return CYGNUM_HAL_INTERRUPT_RTTC;
+ }
+#endif
-void hal_hardware_init(void)
-{
- unsigned i;
+#ifdef CYGNUM_HAL_INTERRUPT_PMC
+ // Power Management Controller
+ HAL_READ_UINT32((AT91_PMC+AT91_PMC_IMR), mr);
+ HAL_READ_UINT32((AT91_PMC+AT91_PMC_SR), sr);
+ if ((sr & mr) &
+ (AT91_PMC_SR_MOSCS |
+ AT91_PMC_SR_LOCK |
+ AT91_PMC_SR_MCKRDY |
+ AT91_PMC_SR_PCK0RDY |
+ AT91_PMC_SR_PCK1RDY |
+ AT91_PMC_SR_PCK2RDY |
+ AT91_PMC_SR_PCK3RDY)) {
+ return CYGNUM_HAL_INTERRUPT_PMC;
+ }
+#endif
- // Reset all interrupts
- HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IDCR, 0xFFFFFFFF);
+#ifdef CYGNUM_HAL_INTERRUPT_MC
+ // Memory controller
+ HAL_READ_UINT32((AT91_MC+AT91_MC_FMR), mr);
+ HAL_READ_UINT32((AT91_MC+AT91_MC_FSR), sr);
+ if ((sr & mr) &
+ (AT91_MC_FSR_FRDY |
+ AT91_MC_FSR_LOCKE |
+ AT91_MC_FSR_PROGE)) {
+ return CYGNUM_HAL_INTERRUPT_MC;
+ }
+#endif
- // Flush internal priority level stack
- for (i = 0; i < 8; ++i)
- HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_EOI, 0xFFFFFFFF);
-
- // Set up eCos/ROM interfaces
- hal_if_init();
+#ifdef CYGNUM_HAL_INTERRUPT_WDTC
+ // Watchdog Timer Controller
+ HAL_READ_UINT32((AT91_WDTC+AT91_WDTC_WDSR), sr);
+ HAL_READ_UINT32((AT91_WDTC+AT91_WDTC_WDMR), mr);
+ if ((mr & AT91_WDTC_WDMR_FIEN) &&
+ sr & (AT91_WDTC_WDSR_UNDER |
+ AT91_WDTC_WDSR_ERROR)) {
+ return CYGNUM_HAL_INTERRUPT_WDTC;
+ }
+#endif
+#ifdef CYGNUM_HAL_INTERRUPT_RSTC
+ // Reset Controller
+ HAL_READ_UINT32((AT91_RST + AT91_RST_RSR), sr);
+ HAL_READ_UINT32((AT91_RST + AT91_RST_RMR), mr);
+ if (((mr & AT91_RST_RMR_URSTIEN) && (sr & AT91_RST_RSR_USER)) ||
+ ((mr & AT91_RST_RMR_BODIEN) && (sr & AT91_RST_RSR_BROWN)))
+ return CYGNUM_HAL_INTERRUPT_RSTC;
+#endif
+
+ return CYGNUM_HAL_INTERRUPT_NONE;
}
+#endif
// -------------------------------------------------------------------------
// This routine is called to respond to a hardware interrupt (IRQ). It
HAL_READ_UINT32(AT91_AIC+AT91_AIC_ISR, irq_num);
- // An invalid interrrupt source is treated as a spurious interrupt
+#if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
+ if (irq_num == CYGNUM_HAL_INTERRUPT_SYS) {
+ // determine the source of the system interrupt
+ irq_num = sys_irq_handler();
+ }
+#endif
+ // An invalid interrupt source is treated as a spurious interrupt
if (irq_num < CYGNUM_HAL_ISR_MIN || irq_num > CYGNUM_HAL_ISR_MAX)
irq_num = CYGNUM_HAL_INTERRUPT_NONE;
CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
+#if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
+ if (vector >= 32) {
+ HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IDCR,
+ (1 << CYGINT_HAL_ARM_AT91_SYS_INTERRUPT));
+ return;
+ }
+#endif
HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IDCR, (1<<vector));
}
CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
+#if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
+ if (vector >= 32) {
+ hal_interrupt_configure(CYGINT_HAL_ARM_AT91_SYS_INTERRUPT, true, true);
+ HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IECR,
+ (1 <<CYGINT_HAL_ARM_AT91_SYS_INTERRUPT));
+ return;
+ }
+#endif
HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IECR, (1<<vector));
}
CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX &&
vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
+#if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
+ if (vector >= 32)
+ return;
+#endif
if (level) {
if (up) {
mode = AT91_AIC_SMR_LEVEL_HI;
vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector");
CYG_ASSERT(level >= 0 && level <= 7, "Invalid level");
+#if CYGINT_HAL_ARM_AT91_SYS_INTERRUPT
+ if (vector >= 32)
+ return;
+#endif
+
HAL_READ_UINT32(AT91_AIC+(AT91_AIC_SMR0+(vector*4)), mode);
mode = (mode & ~AT91_AIC_SMR_PRIORITY) | level;
HAL_WRITE_UINT32(AT91_AIC+(AT91_AIC_SMR0+(vector*4)), mode);
}
+#ifndef AT91_RST
/* Use the watchdog to generate a reset */
void hal_at91_reset_cpu(void)
{
HAL_WRITE_UINT32(AT91_WD + AT91_WD_OMR, AT91_WD_OMR_OKEY);
HAL_WRITE_UINT32(AT91_WD + AT91_WD_CMR, AT91_WD_CMR_CKEY);
HAL_WRITE_UINT32(AT91_WD + AT91_WD_CR, AT91_WD_CR_RSTKEY);
- HAL_WRITE_UINT32(AT91_WD + AT91_WD_OMR, AT91_WD_OMR_OKEY | AT91_WD_OMR_RSTEN | AT91_WD_OMR_WDEN);
+ HAL_WRITE_UINT32(AT91_WD + AT91_WD_OMR,
+ (AT91_WD_OMR_OKEY |
+ AT91_WD_OMR_RSTEN |
+ AT91_WD_OMR_EXTEN | // also reset external circuitry
+ AT91_WD_OMR_WDEN));
while(1) CYG_EMPTY_STATEMENT;
}
-
+#else
+/* Use the Reset Controller to generate a reset */
+void hal_at91_reset_cpu(void)
+{
+ HAL_WRITE_UINT32(AT91_RST + AT91_RST_RCR,
+ AT91_RST_RCR_PROCRST |
+ AT91_RST_RCR_ICERST |
+ AT91_RST_RCR_PERRST |
+ AT91_RST_RCR_KEY);
+ while(1) CYG_EMPTY_STATEMENT;
+}
+#endif
//--------------------------------------------------------------------------
// EOF at91_misc.c