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
eca2c452c4
commit
8e19dbc9a5
@ -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
|
||||||
|
@ -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 */
|
||||||
|
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
Loading…
Reference in New Issue
Block a user