まさかのFreeRTOSがバグ?
投稿:2013-03-23
ユーザマニュアルのページ734「34.3.1.3.7 CONTROL register」にこんな事が書いてありました。
Remark: When changing the stack pointer, software must use an ISB instruction immediately after the MSR instruction. This ensures that instructions after the ISB execute using the new stack pointer. See Section 34.2.10.5 “ISB”
Remark: When changing the stack pointer, software must use an ISB instruction immediately after the MSR instruction. This ensures that instructions after the ISB execute using the new stack pointer. See Section 34.2.10.5 “ISB”
port.cにあるvPortSVCHandlerでスタックポインタを変更していますけれどisbを実行していません。
void vPortSVCHandler( void ) { __asm volatile ( " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ " msr psp, r0 \n" /* Restore the task stack pointer. */ " mov r0, #0 \n" " msr basepri, r0 \n" " orr r14, #0xd \n" " bx r14 \n" " \n" " .align 2 \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n" ); }そこでisbを追加しました。
void vPortSVCHandler( void ) { __asm volatile ( " ldr r3, pxCurrentTCBConst2 \n" /* Restore the context. */ " ldr r1, [r3] \n" /* Use pxCurrentTCBConst to get the pxCurrentTCB address. */ " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldmia r0!, {r4-r11} \n" /* Pop the registers that are not automatically saved on exception entry and the critical nesting count. */ " msr psp, r0 \n" /* Restore the task stack pointer. */ " isb \n" // プロセススタックポインタをパイプラインに反映させる(ユーザマニュアル ページ734) " mov r0, #0 \n" " msr basepri, r0 \n" " orr r14, #0xd \n" " bx r14 \n" " \n" " .align 2 \n" "pxCurrentTCBConst2: .word pxCurrentTCB \n" ); }
port.cにあるxPortPendSVHandlerでスタックポインタを変更していますけれどisbを実行していません。
void xPortPendSVHandler( void ) { /* This is a naked function. */ __asm volatile ( " mrs r0, psp \n" " \n" " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ " ldr r2, [r3] \n" " \n" " stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */ " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ " \n" " stmdb sp!, {r3, r14} \n" " mov r0, %0 \n" " msr basepri, r0 \n" " bl vTaskSwitchContext \n" " mov r0, #0 \n" " msr basepri, r0 \n" " ldmia sp!, {r3, r14} \n" " \n" /* Restore the context, including the critical nesting count. */ " ldr r1, [r3] \n" " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldmia r0!, {r4-r11} \n" /* Pop the registers. */ " msr psp, r0 \n" " bx r14 \n" " \n" " .align 2 \n" "pxCurrentTCBConst: .word pxCurrentTCB \n" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) ); }そこでisbを追加しました。
void xPortPendSVHandler( void ) { /* This is a naked function. */ __asm volatile ( " mrs r0, psp \n" " \n" " ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */ " ldr r2, [r3] \n" " \n" " stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */ " str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */ " \n" " stmdb sp!, {r3, r14} \n" " mov r0, %0 \n" " msr basepri, r0 \n" " bl vTaskSwitchContext \n" " mov r0, #0 \n" " msr basepri, r0 \n" " ldmia sp!, {r3, r14} \n" " \n" /* Restore the context, including the critical nesting count. */ " ldr r1, [r3] \n" " ldr r0, [r1] \n" /* The first item in pxCurrentTCB is the task top of stack. */ " ldmia r0!, {r4-r11} \n" /* Pop the registers. */ " msr psp, r0 \n" " isb \n" // プロセススタックポインタをパイプラインに反映させる(ユーザマニュアル ページ734) " bx r14 \n" " \n" " .align 2 \n" "pxCurrentTCBConst: .word pxCurrentTCB \n" ::"i"(configMAX_SYSCALL_INTERRUPT_PRIORITY) ); }
このページ全部。もうね、信じられるのは己の実力だけだから。