diff -ru ecos_web_cvs/ecos/packages/hal/arm/lpc2xxx/var/current/ChangeLog ecos/ecos/packages/hal/arm/lpc2xxx/var/current/ChangeLog --- ecos_web_cvs/ecos/packages/hal/arm/lpc2xxx/var/current/ChangeLog 2007-07-02 07:47:58.000000000 +0200 +++ ecos/ecos/packages/hal/arm/lpc2xxx/var/current/ChangeLog 2007-07-10 08:06:09.000000000 +0200 @@ -1,3 +1,15 @@ +2007_07-10 Uwe Kindler + + * cdl/hal_arm_lpc2xxx.cdl: Added option + CYGNUM_HAL_KERNEL_COUNTERS_CLOCK_ISR_DEFAULT_PRIORITY for + configuration of priority of system clock interrupts. + + * src/lpc2xxx_misc.c: Added support for vectored interrupt + controller and up to 17 interrupt priorities. This improves + interrupt processing time and makes processing of vectored + interrupts more determenistic because no for loop is required + for detection of interrupt source. + 2007-06-04 Alexey Shusharin * src/hal_diag.c (cyg_hal_plf_serial_isr): Fixed issue with UART diff -ru ecos_web_cvs/ecos/packages/hal/arm/lpc2xxx/var/current/cdl/hal_arm_lpc2xxx.cdl ecos/ecos/packages/hal/arm/lpc2xxx/var/current/cdl/hal_arm_lpc2xxx.cdl --- ecos_web_cvs/ecos/packages/hal/arm/lpc2xxx/var/current/cdl/hal_arm_lpc2xxx.cdl 2007-03-23 10:42:35.000000000 +0100 +++ ecos/ecos/packages/hal/arm/lpc2xxx/var/current/cdl/hal_arm_lpc2xxx.cdl 2007-07-10 08:04:45.000000000 +0200 @@ -206,4 +206,20 @@ debugging via JTAG, as stopping the clock can prevent the debugger getting control of the system." } + + cdl_option CYGNUM_HAL_KERNEL_COUNTERS_CLOCK_ISR_DEFAULT_PRIORITY { + display "Default priority for the system clock interrupts" + flavor data + legal_values { 0 to 16 } + default_value 0 + description " + The LPC2xxx eCos HAL supports up to 17 interrupt levels. + Interrupt levels 0 - 15 are vectored IRQs. Vectored IRQs + have a higher priority then non vectored IRQs and they + are processed faster. Non vectored IRQs are all chained together + into one single slot and the ISR need to find out which interrupt + occured. The default value for the system clock interrupts is 0 - + this is the highest priority IRQ." + } + } diff -ru ecos_web_cvs/ecos/packages/hal/arm/lpc2xxx/var/current/src/lpc2xxx_misc.c ecos/ecos/packages/hal/arm/lpc2xxx/var/current/src/lpc2xxx_misc.c --- ecos_web_cvs/ecos/packages/hal/arm/lpc2xxx/var/current/src/lpc2xxx_misc.c 2006-08-01 08:02:58.000000000 +0200 +++ ecos/ecos/packages/hal/arm/lpc2xxx/var/current/src/lpc2xxx_misc.c 2007-07-10 08:05:30.000000000 +0200 @@ -240,6 +240,13 @@ lpc_set_vpbdiv(CYGNUM_HAL_ARM_LPC2XXX_VPBDIV, 1); #endif + // + // 0xFFFFFFFF indicates that this is a non vectored ISR + // This is the default setting for all interrupts + // + HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_VIC_BASE + + CYGARC_HAL_LPC2XXX_REG_VICDEFVECTADDR, 0xFFFFFFFF); + #ifdef HAL_PLF_HARDWARE_INIT // Perform any platform specific initializations HAL_PLF_HARDWARE_INIT(); @@ -254,22 +261,35 @@ // should interrogate the hardware and return the IRQ vector number. int hal_IRQ_handler(void) { - cyg_uint32 irq_num, irq_stat; - - // Find out which interrupt caused the IRQ. This picks the lowest - // if there are more than 1. - // FIXME:try to make use of the VIC for better latency. - // That will probably need changes to vectors.S and - // other int-related code + cyg_uint32 irq_num; + HAL_READ_UINT32(CYGARC_HAL_LPC2XXX_REG_VIC_BASE + - CYGARC_HAL_LPC2XXX_REG_VICIRQSTAT, irq_stat); - for (irq_num = 0; irq_num < 32; irq_num++) - if (irq_stat & (1 << irq_num)) - break; - - // If not a valid interrrupt source, treat as spurious interrupt - if (irq_num < CYGNUM_HAL_ISR_MIN || irq_num > CYGNUM_HAL_ISR_MAX) - irq_num = CYGNUM_HAL_INTERRUPT_NONE; + CYGARC_HAL_LPC2XXX_REG_VICVECTADDR, irq_num); + // + // if this is a non vectored ISR then we need to find out which interrupt + // caused the IRQ + // + if (0xFFFFFFFF == irq_num) + { + cyg_uint32 irq_stat; + + // Find out which interrupt caused the IRQ. This picks the lowest + // if there are more than 1. + HAL_READ_UINT32(CYGARC_HAL_LPC2XXX_REG_VIC_BASE + + CYGARC_HAL_LPC2XXX_REG_VICIRQSTAT, irq_stat); + irq_num = 0; + while (!(irq_stat & 0x01)) + { + irq_stat >>= 1; + irq_num++; + } + + // If not a valid interrrupt source, treat as spurious interrupt + if (irq_num < CYGNUM_HAL_ISR_MIN || irq_num > CYGNUM_HAL_ISR_MAX) + { + irq_num = CYGNUM_HAL_INTERRUPT_NONE; + } + } // if (0xFFFFFFFF == irq_num) return (irq_num); } @@ -420,12 +440,43 @@ CYGARC_HAL_LPC2XXX_REG_EXTINT, vector); } -// Change interrupt level. This is a non-operation on the LPC2XXX +// +// We support up to 17 interrupt levels +// Interrupts 0 - 15 are vectored interrupt requests. Vectored IRQs have +// the higher priority then non vectored IRQs, but only 16 of the 32 requests +// can be assigned to this category. Any of the 32 requests can be assigned +// to any of the 16 vectored IRQ slots, among which slot 0 has the highest +// priority and slot 15 has the lowest. Priority 16 indicates a non vectored +// IRQ. +// void hal_interrupt_set_level(int vector, int level) { CYG_ASSERT(vector <= CYGNUM_HAL_ISR_MAX && vector >= CYGNUM_HAL_ISR_MIN , "Invalid vector"); - CYG_ASSERT(level >= 0 && level <= 15, "Invalid level"); + CYG_ASSERT(level >= 0 && level <= 16, "Invalid level"); + + // + // If level is < 16 then this is a vectored ISR and we try to write + // the vector number of this ISR in the right slot of the vectored + // interrupt controller + // + if (level < 16) + { + cyg_uint32 addr_offset = level << 2; + cyg_uint32 reg_val; + + HAL_READ_UINT32(CYGARC_HAL_LPC2XXX_REG_VIC_BASE + + CYGARC_HAL_LPC2XXX_REG_VICVECTCNTL0 + addr_offset, reg_val); + CYG_ASSERT((reg_val == 0) || (reg_val == (vector | 0x20)), "Priority already used by another vector"); + HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_VIC_BASE + + CYGARC_HAL_LPC2XXX_REG_VICVECTCNTL0 + addr_offset, vector | 0x20); + // + // We do not store the adress of the ISR here but we store the vector number + // The hal_IRQ_handler then can faster determine the right vector number + // + HAL_WRITE_UINT32(CYGARC_HAL_LPC2XXX_REG_VIC_BASE + + CYGARC_HAL_LPC2XXX_REG_VICVECTADDR0 + addr_offset, vector); + } } // Use the watchdog to generate a reset