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 361027289c
commit 4dc4614914
5 changed files with 95 additions and 36 deletions

View File

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

View File

@ -68,7 +68,7 @@
#define LPC214X_PLL_BASE 0xe01fc080 /* Phase Locked Loop (PLL) Base Address */
#define LPC214X_VPBDIV 0xe01fc100 /* VPBDIV 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 */

View File

@ -65,6 +65,10 @@
* 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
********************************************************************************/
@ -108,19 +112,34 @@ static void lpc214x_decodeirq( uint32 *regs)
PANIC(OSERR_ERREXCEPTION);
#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;
#warning "Need to decode the interrupt here"
uint32 pending = vic_getreg(LPC214X_VIC_IRQSTATUS_OFFSET) & 0x007fffff;
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 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 */
current_regs = NULL;
/* Unmask the last interrupt (global interrupts are still
* disabled.
*/
up_enable_irq(irq);
}
#endif
}

View File

@ -76,12 +76,14 @@ void up_irqinitialize(void)
{
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);
/* All IRQs, no FIQs */
/* Select all IRQs, no FIQs */
vic_putreg(0, LPC214X_VIC_INTSELECT_OFFSET);
@ -98,8 +100,6 @@ void up_irqinitialize(void)
vic_putreg(0, reg);
}
#warning "Not implemented"
/* currents_regs is non-NULL only while processing an interrupt */
current_regs = NULL;
@ -121,7 +121,16 @@ void up_irqinitialize(void)
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)
{
#warning "Not implemented"
}
/* Verify that the IRQ number is within range */
/****************************************************************************
* Name: up_maskack_irq
*
* Description:
* Mask the IRQ and acknowledge it
*
****************************************************************************/
if (irq < NR_IRQS)
{
/* Disable all interrupts */
void up_maskack_irq(int irq)
{
#warning "Not implemented"
irqstate_t flags = irqsave();
/* 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
*
* Description:
* Assign
* Attach a user-supplied handler to a vectored interrupt
*
****************************************************************************/
#ifndef CONFIG_VECTORED_INTERRUPTS
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
@ -169,13 +199,21 @@ void up_attach_vector(int irq, int vector, vic_vector_t handler)
* Name: up_detach_vector
*
* Description:
* Mask the IRQ and acknowledge it
* Detach a user-supplied handler from a vectored interrupt
*
****************************************************************************/
#ifndef CONFIG_VECTORED_INTERRUPTS
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

View File

@ -49,6 +49,12 @@
#define vic_getreg(o) getreg32(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
************************************************************************************/