forked from len0rd/rockbox
imx233: rework interrupt nesting, disabled for now
Rework the irq code, to put more code in the C part. When interrupt nesting is enable, Rockbox gets pretty unstable so disable it for now. Change-Id: Iee18b539c80ea408273f6082975faaa87d3ee1b6
This commit is contained in:
parent
556fa2c4cd
commit
db392245e2
1 changed files with 30 additions and 20 deletions
|
@ -127,6 +127,15 @@ static isr_t isr_table[INT_SRC_COUNT] =
|
||||||
static uint32_t irq_count_old[INT_SRC_COUNT];
|
static uint32_t irq_count_old[INT_SRC_COUNT];
|
||||||
static uint32_t irq_count[INT_SRC_COUNT];
|
static uint32_t irq_count[INT_SRC_COUNT];
|
||||||
|
|
||||||
|
unsigned imx233_icoll_get_priority(int src)
|
||||||
|
{
|
||||||
|
#if IMX233_SUBTARGET < 3780
|
||||||
|
return BF_RDn(ICOLL_PRIORITYn, src / 4, PRIORITYx(src % 4));
|
||||||
|
#else
|
||||||
|
return BF_RDn(ICOLL_INTERRUPTn, src, PRIORITY);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
struct imx233_icoll_irq_info_t imx233_icoll_get_irq_info(int src)
|
struct imx233_icoll_irq_info_t imx233_icoll_get_irq_info(int src)
|
||||||
{
|
{
|
||||||
struct imx233_icoll_irq_info_t info;
|
struct imx233_icoll_irq_info_t info;
|
||||||
|
@ -135,11 +144,7 @@ struct imx233_icoll_irq_info_t imx233_icoll_get_irq_info(int src)
|
||||||
#else
|
#else
|
||||||
info.enabled = BF_RDn(ICOLL_INTERRUPTn, src, ENABLE);
|
info.enabled = BF_RDn(ICOLL_INTERRUPTn, src, ENABLE);
|
||||||
#endif
|
#endif
|
||||||
#if IMX233_SUBTARGET < 3780
|
info.priority = imx233_icoll_get_priority(src);
|
||||||
info.priority = BF_RDn(ICOLL_PRIORITYn, src / 4, PRIORITYx(src % 4));
|
|
||||||
#else
|
|
||||||
info.priority = BF_RDn(ICOLL_INTERRUPTn, src, PRIORITY);
|
|
||||||
#endif
|
|
||||||
info.freq = irq_count_old[src];
|
info.freq = irq_count_old[src];
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
@ -163,16 +168,23 @@ static void UIRQ(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return the priority level */
|
/* return the priority level */
|
||||||
int _irq_handler(uint32_t vec)
|
void _irq_handler(void)
|
||||||
{
|
{
|
||||||
|
/* read vector and notify as side effect */
|
||||||
|
uint32_t vec = HW_ICOLL_VECTOR;
|
||||||
int irq_nr = (vec - HW_ICOLL_VBASE) / 4;
|
int irq_nr = (vec - HW_ICOLL_VBASE) / 4;
|
||||||
|
/* check for IRQ storm */
|
||||||
if(irq_count[irq_nr]++ > IRQ_STORM_THRESHOLD)
|
if(irq_count[irq_nr]++ > IRQ_STORM_THRESHOLD)
|
||||||
panicf("IRQ %d: storm detected", irq_nr);
|
panicf("IRQ %d: storm detected", irq_nr);
|
||||||
|
/* do some regular stat */
|
||||||
if(irq_nr == INT_SRC_TIMER(TIMER_TICK))
|
if(irq_nr == INT_SRC_TIMER(TIMER_TICK))
|
||||||
do_irq_stat();
|
do_irq_stat();
|
||||||
|
/* enable interrupts again */
|
||||||
|
//enable_irq();
|
||||||
|
/* process interrupt */
|
||||||
(*(isr_t *)vec)();
|
(*(isr_t *)vec)();
|
||||||
/* acknowledge completion of IRQ */
|
/* acknowledge completion of IRQ */
|
||||||
return imx233_icoll_get_irq_info(irq_nr).priority;
|
HW_ICOLL_LEVELACK = 1 << imx233_icoll_get_priority(irq_nr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void irq_handler(void)
|
void irq_handler(void)
|
||||||
|
@ -181,22 +193,20 @@ void irq_handler(void)
|
||||||
asm volatile(
|
asm volatile(
|
||||||
"sub lr, lr, #4 \n" /* Create return address */
|
"sub lr, lr, #4 \n" /* Create return address */
|
||||||
"stmfd sp!, { r0-r5, r12, lr } \n" /* Save what gets clobbered */
|
"stmfd sp!, { r0-r5, r12, lr } \n" /* Save what gets clobbered */
|
||||||
"ldr r5, =0x8001c290 \n" /* Save pointer to instruction */
|
"ldr r1, =0x8001c290 \n" /* Save pointer to instruction */
|
||||||
"str lr, [r5] \n" /* in HW_DIGCTL_SCRATCH0 */
|
"str lr, [r1] \n" /* in HW_DIGCTL_SCRATCH0 */
|
||||||
"ldr r4, =0x80000000 \n" /* Read HW_ICOLL_VECTOR */
|
|
||||||
"ldr r0, [r4] \n" /* and notify as side-effect */
|
|
||||||
"mrs lr, spsr \n" /* Save SPSR_irq */
|
"mrs lr, spsr \n" /* Save SPSR_irq */
|
||||||
"stmfd sp!, { lr } \n" /* Push it on the IRQ stack */
|
"stmfd sp!, { r1, lr } \n" /* Push it on the stack */
|
||||||
"msr cpsr_c, #0x13 \n" /* Switch to SVC mode, enable IRQ */
|
"msr cpsr_c, #0x93 \n" /* Switch to SVC mode, IRQ disabled */
|
||||||
"stmfd sp!, { lr } \n" /* Save lr_SVC */
|
"mov r4, lr \n" /* Save lr_SVC */
|
||||||
"blx _irq_handler \n" /* Process IRQ, returns ack level */
|
"and r5, sp, #4 \n" /* Align SVC stack */
|
||||||
"ldmfd sp!, { lr } \n" /* Restore lr_SVC */
|
"sub sp, sp, r5 \n" /* on 8-byte boundary */
|
||||||
|
"blx _irq_handler \n" /* Process IRQ */
|
||||||
|
"add sp, sp, r5 \n" /* Undo alignement */
|
||||||
|
"mov lr, r4 \n" /* Restore lr_SVC */
|
||||||
"msr cpsr_c, #0x92 \n" /* Mask IRQ, return to IRQ mode */
|
"msr cpsr_c, #0x92 \n" /* Mask IRQ, return to IRQ mode */
|
||||||
"ldmfd sp!, { lr } \n" /* Pop back SPSR */
|
"ldmfd sp!, { r1, lr } \n" /* Reload saved value */
|
||||||
"msr spsr_cxsf, lr \n" /* Restore SPSR_irq */
|
"msr spsr_cxsf, lr \n" /* Restore SPSR_irq */
|
||||||
"mov r3, #1 \n" /* Compute ack level value */
|
|
||||||
"lsl r0, r3, r0 \n" /* (1 << ack_lvl) */
|
|
||||||
"str r0, [r4, #0x10] \n" /* and write it to HW_ICOLL_LEVELACK */
|
|
||||||
"ldmfd sp!, { r0-r5, r12, pc }^ \n" /* Restore regs, and RFE */);
|
"ldmfd sp!, { r0-r5, r12, pc }^ \n" /* Restore regs, and RFE */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue