Completes coding of basic interrupt handling logic

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@199 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo 2007-05-03 00:29:56 +00:00
parent eca2c452c4
commit 8e19dbc9a5
5 changed files with 95 additions and 36 deletions

View File

@ -80,7 +80,9 @@
* Public Types * Public Types
************************************************************/ ************************************************************/
#ifndef __ASSEMBLY__
typedef void (*vic_vector_t)(uint32 *regs); typedef void (*vic_vector_t)(uint32 *regs);
#endif
/************************************************************ /************************************************************
* Inline functions * Inline functions

View File

@ -68,7 +68,7 @@
#define LPC214X_PLL_BASE 0xe01fc080 /* Phase Locked Loop (PLL) Base Address */ #define LPC214X_PLL_BASE 0xe01fc080 /* Phase Locked Loop (PLL) Base Address */
#define LPC214X_VPBDIV 0xe01fc100 /* VPBDIV Address */ #define LPC214X_VPBDIV 0xe01fc100 /* VPBDIV Address */
#define LPC214X_EMC_BASE 0xffe00000 /* External Memory Controller (EMC) Base Address */ #define LPC214X_EMC_BASE 0xffe00000 /* External Memory Controller (EMC) Base Address */
#define LPC214X_VIC_BASE 0xffff0000 /* Vectored Interrupt Controller (VIC) Base */ #define LPC214X_VIC_BASE 0xfffff000 /* Vectored Interrupt Controller (VIC) Base */
/* UART0/1 Register Offsets */ /* UART0/1 Register Offsets */

View File

@ -65,6 +65,10 @@
* Private Data * Private Data
********************************************************************************/ ********************************************************************************/
/* This type arry maps 4 bits into the bit number of the lowest bit that it set */
static uint8 g_nibblemap[16] = { 0, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 };
/******************************************************************************** /********************************************************************************
* Private Functions * Private Functions
********************************************************************************/ ********************************************************************************/
@ -108,19 +112,34 @@ static void lpc214x_decodeirq( uint32 *regs)
PANIC(OSERR_ERREXCEPTION); PANIC(OSERR_ERREXCEPTION);
#else #else
/* Decode the interrupt. First, fetch the interrupt id register. */ /* Decode the interrupt. We have to do this by search for the lowest numbered
* non-zero bit in the interrupt status register.
*/
int irq = 0; uint32 pending = vic_getreg(LPC214X_VIC_IRQSTATUS_OFFSET) & 0x007fffff;
#warning "Need to decode the interrupt here" unsigned int nibble;
unsigned int irq_base;
unsigned int irq = NR_IRQS;
/* Verify that the resulting IRQ number is valie */ /* Search in groups of four bits. For 22 sources, this is at most five
* times through the loop.
*/
if ((unsigned)irq < NR_IRQS) for (nibble = pending & 0xff, irq_base = 0;
pending && irq < NR_IRQS;
pending >>= 4, nibble = pending & 0xff, irq_base += 4)
{ {
/* Mask and acknowledge the interrupt */ if (nibble)
{
irq = irq_base + g_nibblemap[nibble];
break;
}
}
up_maskack_irq(irq); /* Verify that the resulting IRQ number is valid */
if (irq < NR_IRQS)
{
/* Current regs non-zero indicates that we are processing an interrupt; /* Current regs non-zero indicates that we are processing an interrupt;
* current_regs is also used to manage interrupt level context switches. * current_regs is also used to manage interrupt level context switches.
*/ */
@ -134,12 +153,6 @@ static void lpc214x_decodeirq( uint32 *regs)
/* Indicate that we are no long in an interrupt handler */ /* Indicate that we are no long in an interrupt handler */
current_regs = NULL; current_regs = NULL;
/* Unmask the last interrupt (global interrupts are still
* disabled.
*/
up_enable_irq(irq);
} }
#endif #endif
} }

View File

@ -76,12 +76,14 @@ void up_irqinitialize(void)
{ {
int reg; int reg;
/* Acknowledge and disable all interrupts */ /* Disable all interrupts. We do this by writing zero to the IntEnable
* register. This is equivalent to writing all ones to the IntClearEnable
* register.
*/
vic_putreg(0, LPC214X_VIC_INTENCLEAR_OFFSET);
vic_putreg(0, LPC214X_VIC_INTENABLE_OFFSET); vic_putreg(0, LPC214X_VIC_INTENABLE_OFFSET);
/* All IRQs, no FIQs */ /* Select all IRQs, no FIQs */
vic_putreg(0, LPC214X_VIC_INTSELECT_OFFSET); vic_putreg(0, LPC214X_VIC_INTSELECT_OFFSET);
@ -98,8 +100,6 @@ void up_irqinitialize(void)
vic_putreg(0, reg); vic_putreg(0, reg);
} }
#warning "Not implemented"
/* currents_regs is non-NULL only while processing an interrupt */ /* currents_regs is non-NULL only while processing an interrupt */
current_regs = NULL; current_regs = NULL;
@ -121,7 +121,16 @@ void up_irqinitialize(void)
void up_disable_irq(int irq) void up_disable_irq(int irq)
{ {
#warning "Not implemented" /* Verify that the IRQ number is within range */
if (irq < NR_IRQS)
{
/* Disable the irq by setting the corresponding bit in the VIC
* Interrupt Enable Clear register.
*/
vic_putreg((1 << irq), LPC214X_VIC_INTENCLEAR_OFFSET);
}
} }
/**************************************************************************** /****************************************************************************
@ -134,34 +143,55 @@ void up_disable_irq(int irq)
void up_enable_irq(int irq) void up_enable_irq(int irq)
{ {
#warning "Not implemented" /* Verify that the IRQ number is within range */
}
/**************************************************************************** if (irq < NR_IRQS)
* Name: up_maskack_irq {
* /* Disable all interrupts */
* Description:
* Mask the IRQ and acknowledge it
*
****************************************************************************/
void up_maskack_irq(int irq) irqstate_t flags = irqsave();
{
#warning "Not implemented" /* Enable the irq by setting the corresponding bit in the VIC
* Interrupt Enable register.
*/
uint32 val = vic_getreg(LPC214X_VIC_INTENABLE_OFFSET);
vic_putreg(val | (1 << irq), LPC214X_VIC_INTENCLEAR_OFFSET);
irqrestore(flags);
}
} }
/**************************************************************************** /****************************************************************************
* Name: up_attach_vector * Name: up_attach_vector
* *
* Description: * Description:
* Assign * Attach a user-supplied handler to a vectored interrupt
* *
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_VECTORED_INTERRUPTS #ifndef CONFIG_VECTORED_INTERRUPTS
void up_attach_vector(int irq, int vector, vic_vector_t handler) void up_attach_vector(int irq, int vector, vic_vector_t handler)
{ {
#warning "Not implemented" /* Verify that the IRQ number and vector number are within range */
if (irq < NR_IRQS && vector < 16 && handler)
{
int offset = vector << 2;
/* Disable all interrupts */
irqstate_t flags = irqsave();
/* Save the vector address */
vic_putreg((uint32)handler, LPC214X_VIC_VECTADDR0_OFFSET + offset);
/* Enable the vectored interrupt */
vic_putreg(((irq << LPC214X_VECTCNTL_IRQSHIFT) | LPC214X_VECTCNTL_ENABLE),
LPC214X_VIC_VECTCNTL0_OFFSET + offset);
irqrestore(flags);
}
} }
#endif #endif
@ -169,13 +199,21 @@ void up_attach_vector(int irq, int vector, vic_vector_t handler)
* Name: up_detach_vector * Name: up_detach_vector
* *
* Description: * Description:
* Mask the IRQ and acknowledge it * Detach a user-supplied handler from a vectored interrupt
* *
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_VECTORED_INTERRUPTS #ifndef CONFIG_VECTORED_INTERRUPTS
void up_detach_vector(int vector) void up_detach_vector(int vector)
{ {
#warning "Not implemented" /* Verify that the vector number is within range */
if (vector < 16)
{
/* Disable the vectored interrupt */
int offset = vector << 2;
vic_putreg(0, LPC214X_VIC_VECTCNTL0_OFFSET + offset);
}
} }
#endif #endif

View File

@ -49,6 +49,12 @@
#define vic_getreg(o) getreg32(LPC214X_VIC_BASE+(o)) #define vic_getreg(o) getreg32(LPC214X_VIC_BASE+(o))
#define vic_putreg(v,o) putreg32((v),LPC214X_VIC_BASE+(o)) #define vic_putreg(v,o) putreg32((v),LPC214X_VIC_BASE+(o))
// Vector Control Register bit definitions
#define LPC214X_VECTCNTL_IRQMASK (0x0000001f)
#define LPC214X_VECTCNTL_IRQSHIFT (0)
#define LPC214X_VECTCNTL_ENABLE (1 << 5)
/************************************************************************************ /************************************************************************************
* Public Types * Public Types
************************************************************************************/ ************************************************************************************/