summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2010-05-05 07:15:20 +0000
committerMichael Sevakis <jethead71@rockbox.org>2010-05-05 07:15:20 +0000
commit630b4fc55537721c68462e71d0910a3734baa852 (patch)
tree16ebb91388d2629e64a9f2260d91d1509ac56123
parent9dd81ae53d87840a4cb6e9c4b90ecd2ca456835d (diff)
downloadrockbox-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.h33
-rw-r--r--firmware/target/arm/imx31/dvfs_dptc-imx31.c2
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
219void avic_set_ni_level(unsigned int level); 219void 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)
230static __attribute__((naked, interrupt("IRQ"))) void CCM_DVFS_HANDLER(void) 230static __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}