Index: firmware/kernel.c =================================================================== --- firmware/kernel.c (revision 31595) +++ firmware/kernel.c (working copy) @@ -1195,9 +1195,7 @@ * in 'semaphore_init'. */ void semaphore_release(struct semaphore *s) { -#if defined(HAVE_PRIORITY_SCHEDULING) && defined(irq_enabled_checkval) unsigned int result = THREAD_NONE; -#endif int oldlevel; oldlevel = disable_irq_save(); @@ -1209,11 +1207,7 @@ KERNEL_ASSERT(s->count == 0, "semaphore_release->threads queued but count=%d!\n", s->count); s->queue->retval = OBJ_WAIT_SUCCEEDED; /* indicate explicit wake */ -#if defined(HAVE_PRIORITY_SCHEDULING) && defined(irq_enabled_checkval) result = wakeup_thread(&s->queue); -#else - wakeup_thread(&s->queue); -#endif } else { @@ -1228,11 +1222,11 @@ corelock_unlock(&s->cl); restore_irq(oldlevel); -#if defined(HAVE_PRIORITY_SCHEDULING) && defined(irq_enabled_checkval) - /* No thread switch if IRQ disabled - it's probably called via ISR. - * switch_thread would as well enable them anyway. */ - if((result & THREAD_SWITCH) && irq_enabled_checkval(oldlevel)) +#if defined(HAVE_PRIORITY_SCHEDULING) && defined(is_thread_context) + /* No thread switch if not thread context */ + if((result & THREAD_SWITCH) && is_thread_context()) switch_thread(); #endif + (void)result; } #endif /* HAVE_SEMAPHORE_OBJECTS */ Index: firmware/target/arm/crt0.S =================================================================== --- firmware/target/arm/crt0.S (revision 31595) +++ firmware/target/arm/crt0.S (working copy) @@ -100,17 +100,23 @@ strhi r4, [r2], #4 bhi 1b - /* Set up stack for IRQ mode */ + /* Set up stack for IRQ mode */ msr cpsr_c, #0xd2 ldr sp, =irq_stack - /* Set up stack for FIQ mode */ + msr cpsr_c, #0xd3 +#if CONFIG_CPU == AS3525 || CONFIG_CPU == AS3525v2 + /* Let abort and undefined modes use irq stack */ + /* svc stack is for interrupt processing */ + ldr sp, =svc_stack +#else + /* Let svc, abort and undefined modes use irq stack */ + ldr sp, =irq_stack + + /* Set up stack for FIQ mode */ msr cpsr_c, #0xd1 ldr sp, =fiq_stack - - /* Let svc, abort and undefined modes use irq stack */ - msr cpsr_c, #0xd3 - ldr sp, =irq_stack +#endif msr cpsr_c, #0xd7 ldr sp, =irq_stack msr cpsr_c, #0xdb @@ -159,15 +165,19 @@ b UIE data_abort_handler: - sub r0, lr, #8 + sub r0, lr, #8 mov r1, #2 b UIE +.ltorg + /* 256 words of IRQ stack */ .space 256*4 irq_stack: -/* 256 words of FIQ stack */ +/* 256 words of FIQ/SVC stack */ .space 256*4 fiq_stack: +svc_stack: + end: Index: firmware/target/arm/as3525/system-as3525.c =================================================================== --- firmware/target/arm/as3525/system-as3525.c (revision 31595) +++ firmware/target/arm/as3525/system-as3525.c (working copy) @@ -37,7 +37,7 @@ extern __attribute__((weak,alias("UIRQ"))) void name (void) static void UIRQ (void) __attribute__((interrupt ("IRQ"))); -void irq_handler(void) __attribute__((interrupt ("IRQ"))); +void irq_handler(void) __attribute__((naked, interrupt ("IRQ"))); void fiq_handler(void) __attribute__((interrupt ("FIQ"))); default_interrupt(INT_WATCHDOG); @@ -107,6 +107,11 @@ static const struct { int source; void (*isr) (void); } vec_int_srcs[] = { /* Highest priority at the top of the list */ +#if defined(HAVE_HOTSWAP) || defined(HAVE_RDS_CAP) || \ + (defined(SANSA_FUZEV2) && !INCREASED_SCROLLWHEEL_POLLING) + /* If GPIOA ISR is interrupted, things seem to go wonky ?? */ + { INT_SRC_GPIOA, INT_GPIOA }, +#endif #ifdef HAVE_RECORDING { INT_SRC_I2SIN, INT_I2SIN }, /* For recording */ #endif @@ -120,10 +125,6 @@ { INT_SRC_TIMER2, INT_TIMER2 }, { INT_SRC_I2C_AUDIO, INT_I2C_AUDIO }, { INT_SRC_AUDIO, INT_AUDIO }, -#if defined(HAVE_HOTSWAP) || \ - (defined(SANSA_FUZEV2) && !INCREASED_SCROLLWHEEL_POLLING) - { INT_SRC_GPIOA, INT_GPIOA, }, -#endif /* Lowest priority at the end of the list */ }; @@ -143,6 +144,10 @@ VIC_VECT_ADDRS[i] = vec_int_srcs[i].isr; VIC_VECT_CNTLS[i] = (1<<5) | vec_int_srcs[i].source; } + + /* Reset priority hardware */ + for (i = 0; i < 32; i++) + *VIC_VECT_ADDR = 0; } void INT_GPIOA(void) @@ -163,8 +168,32 @@ void irq_handler(void) { - (*VIC_VECT_ADDR)(); /* call the isr */ - *VIC_VECT_ADDR = (void*)VIC_VECT_ADDR; /* any write will ack the irq */ + asm volatile ( + "sub lr, lr, #4 \n" /* Create return address */ + "stmfd sp!, { r0-r3, r12, lr } \n" /* Save what gets clobbered */ + "ldr r12, =0xc6010030 \n" /* Obtain VIC address (before SPSR read!) */ + "ldr r12, [r12] \n" + "mrs r14, spsr \n" /* Save SPSR_irq */ + "str r14, [sp, #-4]! \n" + "msr cpsr_c, #0x13 \n" /* Switch to SVC mode, enable IRQ */ + "and r0, sp, #4 \n" /* Align SVC stack to 8 bytes */ + "sub sp, sp, r0 \n" + "stmfd sp!, { r0, lr } \n" /* Save align fudge and LR_svc */ +#if ARM_ARCH >= 5 + "blx r12 \n" /* Call handler */ +#else + "mov lr, pc \n" + "bx r12 \n" +#endif + "ldmfd sp!, { r0, lr } \n" /* Pop align fugde and LR_svc */ + "add sp, sp, r0 \n" /* Undo alignment fudge */ + "msr cpsr_c, #0x92 \n" /* Mask IRQ, return to IRQ mode */ + "ldr r12, [sp], #4 \n" /* Pop SPSR_irq */ + "ldr r14, =0xc6010030 \n" /* Get VIC vector reg */ + "msr spsr_cxsf, r12 \n" /* Restore SPSR_irq */ + "str r14, [r14] \n" /* Ack end of ISR to VIC */ + "ldmfd sp!, { r0-r3, r12, pc }^ \n" /* Restore regs, and RFE */ + ); } void fiq_handler(void) Index: firmware/target/arm/as3525/fmradio-i2c-as3525.c =================================================================== --- firmware/target/arm/as3525/fmradio-i2c-as3525.c (revision 31595) +++ firmware/target/arm/as3525/fmradio-i2c-as3525.c (working copy) @@ -195,8 +195,8 @@ /* read and clear the interrupt */ if (GPIOA_MIS & (1<<4)) { semaphore_release(&rds_sema); + GPIOA_IC = (1<<4); } - GPIOA_IC = (1<<4); } /* Captures RDS data and processes it */ Index: firmware/target/arm/as3525/sd-as3525v2.c =================================================================== --- firmware/target/arm/as3525/sd-as3525v2.c (revision 31595) +++ firmware/target/arm/as3525/sd-as3525v2.c (working copy) @@ -1041,10 +1041,12 @@ void sd_gpioa_isr(void) { static struct timeout sd1_oneshot; - if (GPIOA_MIS & EXT_SD_BITS) + + if (GPIOA_RIS & EXT_SD_BITS) + { timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0); - /* acknowledge interrupt */ - GPIOA_IC = EXT_SD_BITS; + GPIOA_IC = EXT_SD_BITS; /* acknowledge interrupt */ + } } #endif /* HAVE_HOTSWAP */ Index: firmware/target/arm/as3525/sansa-fuzev2/button-fuzev2.c =================================================================== --- firmware/target/arm/as3525/sansa-fuzev2/button-fuzev2.c (revision 31595) +++ firmware/target/arm/as3525/sansa-fuzev2/button-fuzev2.c (working copy) @@ -30,6 +30,7 @@ #ifdef HAVE_SCROLLWHEEL #define SCROLLWHEEL_BITS (1<<7|1<<6) +#define SCROLLWHEEL_BITS_POS 6 /* TIMER units */ #define TIMER_TICK (KERNEL_TIMER_FREQ/HZ)/* how long a tick lasts */ #define TIMER_MS (TIMER_TICK/(1000/HZ))/* how long a ms lasts */ @@ -78,10 +79,17 @@ unsigned int btn = BUTTON_NONE; - if (old_wheel_value == wheel_tbl[0][wheel_value]) + if (hold_button) + { + } + else if (old_wheel_value == wheel_tbl[0][wheel_value]) + { btn = BUTTON_SCROLL_FWD; + } else if (old_wheel_value == wheel_tbl[1][wheel_value]) + { btn = BUTTON_SCROLL_BACK; + } if (btn == BUTTON_NONE) { @@ -200,11 +208,13 @@ { #if defined(HAVE_SCROLLWHEEL) /* scroll wheel handling */ - if (GPIOA_MIS & SCROLLWHEEL_BITS) - scrollwheel(GPIOA_PIN_MASK(0xc0) >> 6); + unsigned long bits = GPIOA_RIS & SCROLLWHEEL_BITS; - /* ack interrupt */ - GPIOA_IC = SCROLLWHEEL_BITS; + if (bits) + { + scrollwheel(GPIOA_PIN_MASK(SCROLLWHEEL_BITS) >> SCROLLWHEEL_BITS_POS); + GPIOA_IC = bits; /* ack interrupt */ + } #endif } @@ -225,8 +235,10 @@ int delay = 30; while(delay--) nop; + disable_irq(); + bool ccu_io_bit12 = CCU_IO & (1<<12); - bitclr32(&CCU_IO, 1<<12); + CCU_IO &= ~(1<<12); /* B1 is shared with FM i2c */ bool gpiob_pin0_dir = GPIOB_DIR & (1<<1); @@ -256,8 +268,10 @@ GPIOB_DIR |= 1<<1; if(ccu_io_bit12) - bitset32(&CCU_IO, 1<<12); + CCU_IO |= (1<<12); + enable_irq(); + #ifdef HAS_BUTTON_HOLD #ifndef BOOTLOADER /* light handling */ @@ -265,12 +279,6 @@ { hold_button = hold; backlight_hold_changed(hold); - /* mask scrollwheel irq so we don't need to check for - * the hold button in the isr */ - if (hold) - GPIOA_IE &= ~SCROLLWHEEL_BITS; - else - GPIOA_IE |= SCROLLWHEEL_BITS; } #else hold_button = hold; Index: firmware/target/arm/as3525/sd-as3525.c =================================================================== --- firmware/target/arm/as3525/sd-as3525.c (revision 31595) +++ firmware/target/arm/as3525/sd-as3525.c (working copy) @@ -178,10 +178,12 @@ void sd_gpioa_isr(void) { static struct timeout sd1_oneshot; + if (GPIOA_MIS & EXT_SD_BITS) + { timeout_register(&sd1_oneshot, sd1_oneshot_callback, (3*HZ/10), 0); - /* acknowledge interrupt */ - GPIOA_IC = EXT_SD_BITS; + GPIOA_IC = EXT_SD_BITS; /* acknowledge interrupt */ + } } #endif /* HAVE_HOTSWAP */ Index: firmware/target/arm/system-arm.h =================================================================== --- firmware/target/arm/system-arm.h (revision 31595) +++ firmware/target/arm/system-arm.h (working copy) @@ -76,6 +76,9 @@ #define ints_enabled_checkval(val) \ (((val) & IRQ_FIQ_STATUS) == 0) +/* We run in SYS mode */ +#define is_thread_context() \ + (get_processor_mode() == 0x1f) /* Core-level interrupt masking */ @@ -109,6 +112,13 @@ return (cpsr & status) == 0; } +static inline unsigned long get_processor_mode(void) +{ + unsigned long cpsr; + asm ("mrs %0, cpsr" : "=r"(cpsr)); + return cpsr & 0x1f; +} + /* ARM_ARCH version section for architecture*/ #if ARM_ARCH >= 6