diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2010-05-05 07:15:20 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2010-05-05 07:15:20 +0000 |
commit | 630b4fc55537721c68462e71d0910a3734baa852 (patch) | |
tree | 16ebb91388d2629e64a9f2260d91d1509ac56123 | |
parent | 9dd81ae53d87840a4cb6e9c4b90ecd2ca456835d (diff) | |
download | rockbox-630b4fc55537721c68462e71d0910a3734baa852.tar.gz rockbox-630b4fc55537721c68462e71d0910a3734baa852.zip |
i.MX31/Gigabeat S: The nested IRQ code was just totally wrong and not actually working anyway (which is why it wasn't crashing). AVIC doesn't seem truthful about priority of current ISR either :\. Sometimes there were channel swaps during really active DVFS due to FIFO underflow from a needed long delay in the ISR (100us, and IIS TX only has 45us reserve) and DMARQ *must* be serviced low-latency. Get it doing as was intended.tcctool_v1_0bootloader_fuze_v2
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@25822 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r-- | firmware/target/arm/imx31/avic-imx31.h | 33 | ||||
-rw-r--r-- | firmware/target/arm/imx31/dvfs_dptc-imx31.c | 2 |
2 files changed, 16 insertions, 19 deletions
diff --git a/firmware/target/arm/imx31/avic-imx31.h b/firmware/target/arm/imx31/avic-imx31.h index ba8f91cc1a..43fd726db3 100644 --- a/firmware/target/arm/imx31/avic-imx31.h +++ b/firmware/target/arm/imx31/avic-imx31.h | |||
@@ -218,33 +218,30 @@ void avic_set_int_type(enum IMX31_INT_LIST ints, enum INT_TYPE intstype); | |||
218 | #define AVIC_NIL_ENABLE 0x1f | 218 | #define AVIC_NIL_ENABLE 0x1f |
219 | void avic_set_ni_level(unsigned int level); | 219 | void avic_set_ni_level(unsigned int level); |
220 | 220 | ||
221 | |||
221 | /* Call a service routine while allowing preemption by interrupts of higher | 222 | /* Call a service routine while allowing preemption by interrupts of higher |
222 | * priority. r4-r7 must be preserved for epilogue code to restore context. */ | 223 | * priority. r4-r7 must be preserved for epilogue code to restore context. */ |
223 | #define AVIC_NESTED_NI_CALL_PROLOGUE() \ | 224 | #define AVIC_NESTED_NI_CALL_PROLOGUE(prio) \ |
224 | ({ asm volatile ( \ | 225 | ({ asm volatile ( \ |
225 | "sub lr, lr, #4 \n" /* prepare return address */ \ | 226 | "sub lr, lr, #4 \n" /* prepare return address */ \ |
226 | "stmfd sp!, { r0-r7, r12, lr } \n" /* preserve return context */ \ | 227 | "srsdb #0x12! \n" /* save LR_irq and SPSR_irq */ \ |
228 | "stmfd sp!, { r0-r3, r12 } \n" /* preserve context */ \ | ||
227 | "mov r0, #0x68000000 \n" /* AVIC_BASE_ADDR */ \ | 229 | "mov r0, #0x68000000 \n" /* AVIC_BASE_ADDR */ \ |
228 | "mrs r4, spsr \n" /* save SPSR_irq */ \ | 230 | "mov r1, %0 \n" /* load interrupt level */ \ |
229 | "ldr r5, [r0, #0x04] \n" /* save NIMASK */ \ | 231 | "ldr r2, [r0, #0x04] \n" /* save NIMASK */ \ |
230 | "ldr r1, [r0, #0x40] \n" /* load NIVECSR */ \ | 232 | "str r1, [r0, #0x04] \n" /* set interrupt level */ \ |
231 | "mov r2, sp \n" /* remember IRQ stack to use in call */ \ | 233 | "cpsie i, #0x13 \n" /* change to SVC mode, unmask IRQ */ \ |
232 | "str r1, [r0, #0x04] \n" /* copy NIVECSR to NIMASK */ \ | 234 | "stmfd sp!, { r2, lr } \n" /* push NIMASK and LR on SVC stack */ \ |
233 | "cps #0x13 \n" /* switch to SVC mode (+ unmask IRQ) */ \ | 235 | : : "i"(prio)); }) |
234 | "mov r6, sp \n" /* save SP_svc */ \ | ||
235 | "mov r7, lr \n" /* save LR_svc */ \ | ||
236 | "mov sp, r2 \n" /* switch to SP_irq */ \ | ||
237 | ); }) | ||
238 | 236 | ||
239 | #define AVIC_NESTED_NI_CALL_EPILOGUE() \ | 237 | #define AVIC_NESTED_NI_CALL_EPILOGUE() \ |
240 | ({ asm volatile ( \ | 238 | ({ asm volatile ( \ |
241 | "mov sp, r6 \n" /* restore SP_svc */ \ | 239 | "ldmfd sp!, { r2, lr } \n" /* pop original LR and NIMASK */ \ |
242 | "mov lr, r7 \n" /* restore LR_svc */ \ | 240 | "cpsid i, #0x12 \n" /* return to IRQ mode, mask IRQ */ \ |
243 | "cps #0x12 \n" /* return to IRQ mode (+ mask IRQ) */ \ | ||
244 | "mov r0, #0x68000000 \n" /* AVIC BASE ADDR */ \ | 241 | "mov r0, #0x68000000 \n" /* AVIC BASE ADDR */ \ |
245 | "msr spsr_cxsf, r4 \n" /* restore SPSR_irq */ \ | 242 | "str r2, [r0, #0x04] \n" /* restore NIMASK */ \ |
246 | "str r5, [r0, #0x04] \n" /* restore NIMASK */ \ | 243 | "ldmfd sp!, { r0-r3, r12 } \n" /* reload context */ \ |
247 | "ldmfd sp!, { r0-r7, r12, pc }^ \n" /* reload context and return */ \ | 244 | "rfefd sp! \n" /* move stacked SPSR to CPSR, return */ \ |
248 | ); }) | 245 | ); }) |
249 | 246 | ||
250 | #endif /* AVIC_IMX31_H */ | 247 | #endif /* AVIC_IMX31_H */ |
diff --git a/firmware/target/arm/imx31/dvfs_dptc-imx31.c b/firmware/target/arm/imx31/dvfs_dptc-imx31.c index 5e1a598428..680b015c81 100644 --- a/firmware/target/arm/imx31/dvfs_dptc-imx31.c +++ b/firmware/target/arm/imx31/dvfs_dptc-imx31.c | |||
@@ -230,7 +230,7 @@ static void __attribute__((used)) dvfs_int(void) | |||
230 | static __attribute__((naked, interrupt("IRQ"))) void CCM_DVFS_HANDLER(void) | 230 | static __attribute__((naked, interrupt("IRQ"))) void CCM_DVFS_HANDLER(void) |
231 | { | 231 | { |
232 | /* Audio can glitch with the long udelay if nested IRQ isn't allowed. */ | 232 | /* Audio can glitch with the long udelay if nested IRQ isn't allowed. */ |
233 | AVIC_NESTED_NI_CALL_PROLOGUE(); | 233 | AVIC_NESTED_NI_CALL_PROLOGUE(INT_PRIO_DVFS); |
234 | asm volatile ("bl dvfs_int"); | 234 | asm volatile ("bl dvfs_int"); |
235 | AVIC_NESTED_NI_CALL_EPILOGUE(); | 235 | AVIC_NESTED_NI_CALL_EPILOGUE(); |
236 | } | 236 | } |