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:
parent
361027289c
commit
4dc4614914
@ -80,7 +80,9 @@
|
||||
* Public Types
|
||||
************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
typedef void (*vic_vector_t)(uint32 *regs);
|
||||
#endif
|
||||
|
||||
/************************************************************
|
||||
* Inline functions
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
************************************************************************************/
|
||||
|
Loading…
Reference in New Issue
Block a user