This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
We are attempting to implement a timer interrupt based multi-tasking. The timer drives a 10KHz interrupt which is used to switch from lower priority tasks to a 10Khz task. Initially everything working fine with IRQ interrupts and SWI until the size of tasks grew such that, the timer interrupt driven context switch was required. The 10 KHz task runs correctly however the lower priority task which was interrupted does not function and no longer runs to completion. The SWI context switch is used at the end of a task to return to lower priority task. It is working as intended.
I am attaching the context switch code for IRQ context switch and SWI context switch.
Thanks in advance! would greatly appreciate help to debug this issue.
Nagaraj Hegde
.text .arm .align 8 .ref os_CurrentTask .ref getParam .ref fdHandler_SupervisorCall .ref osTask_Trap .ref osTask_TaskCompleted .ref osTask_NextUserTask .ref osTask_NextInitTask .ref osTimerTask .ref __STACK_INIT__ ;defined in the linker file .global __SP_INIT ___SP_INIT: .word __STACK_INIT__ ; ***************************************************************************** ; Macro: SAVE_CONTEXT ; Description: Save context of the current process ; ***************************************************************************** _osSaveContext_ .macro dsb ldr sp, _curTCB ldr sp, [sp] ; Load the current TCB (pointer dereference) ldr sp, [sp] ; Load the current Registers (pointer dereference) stmia sp, {r0-r14}^ ; Store r0-r14 (from user mode) add sp, sp, #60 ; Set sp to the TCB offset of lr mov r6, lr ; Push the link register onto the task stack. mrs r7, spsr ; Push the SPSR onto the task stack. vmrs r8, fpscr ; Save the task FP Staus register. vmrs r9, fpexc ; Copy fpexc into a general register stmia sp!, {r6-r9} ; Store lr, spsr, fpscr, fpexc vstmia sp!, {d0-d15} ; Store D0-D15 ldr sp, ___SP_INIT ; Give it the system stack to work with .endm ; ***************************************************************************** ; Macro: SAVE_CONTEXT ; Description: Save context of the current process when called from IRQ ; ***************************************************************************** _osIRQSaveContext_ .macro dsb ldr sp, _curTCB ldr sp, [sp] ; Load the current TCB (pointer dereference) ldr sp, [sp] ; Load the current Registers (pointer dereference) sub r14, r14, #4 ; Subtract 4 lr stmia sp, {r0-r14}^ ; Store r0-r14 (from IRQ mode) add sp, sp, #52 ; Set sp to the TCB offset of lr stmia sp, {sp}^ add sp, sp, #8 ; Set sp to the TCB offset of lr mov r6, lr ; Push the link register onto the task stack. mrs r7, spsr ; Push the SPSR onto the task stack. vmrs r8, fpscr ; Save the task FP Staus register. vmrs r9, fpexc ; Copy fpexc into a general register stmia sp!, {r6-r9} ; Store lr, spsr, fpscr, fpexc vstmia sp!, {d0-d15} ; Store D0-D15 ldr sp, ___SP_INIT ; Give it the system stack to work with .endm ; ***************************************************************************** ; Function: irq ; Description: IRQ Handler ; ***************************************************************************** .def _osIRQHandler_ .asmfunc _osIRQHandler_ _osIRQSaveContext_ bl osTimerTask b _osRestore_Context_ .endasmfunc ; ***************************************************************************** ; Function: _osRestore_Context_ ; Description: Restore context of the current process and transition to the ; user task ; ***************************************************************************** .def _osRestore_Context_ .asmfunc _osRestore_Context_ ldr sp, _curTCB ldr sp, [sp] ; Load the current TCB (pointer dereference) ldr sp, [sp] ; Load the current Registers (pointer dereference) ldr r1, [sp,#64] ; Get spsr from byte 64 of the TCB ldr r2, [sp,#68] ; Get fpscr from byte 68 of the TCB ldr r3, [sp,#72] ; Get fpexc from byte 72 of the TCB msr spsr_csxf, r1 ; Load spsr vmsr fpscr, r2 ; Load fpscr vmsr fpexc, r3 ; Load fpexc add sp, sp, #76 ; Set sp to the TCB location of D0-D15 vldmia sp, {d0-d15} ; Load D0-D15 sub sp, sp, #76 ; Set sp to the TCB location of R0-R14 ldmia sp, {r0-r14}^ ; Load r0-r14 (User) add sp, sp, #60 ; Set sp to the TCB location of lr rfeia sp .endasmfunc ; ***************************************************************************** ; Function: soft_int ; Description Soft Interrupt Handler ; ***************************************************************************** svc_jmptable: ; System Call .word osTask_Trap ; 0 .word osTask_TaskCompleted ; 1 .word osTask_NextUserTask ; 2 .word osTask_NextInitTask ; 3 ; r0 - call number ; r1 - parameter .def soft_int .asmfunc soft_int: _osSaveContext_ adr r4, svc_jmptable ; Load the address of the jump table adr r5, soft_int ; Load the address of the thing after the table add r4, r4, r0, lsl #2 ; Calculate the address of the requested system call mov r0, r1 ; Move the argument ldr r1, _getParam stmia r1!, {r0} adr lr, _osRestore_Context_ ; Set the link back to the context restore cmp r5, r4 ldrgt pc, [r4] ; Go there if we are actually in the table b _handleException_SI ; Otherwise... handle it as an error .endasmfunc _handleException_SI: bl fdHandler_SupervisorCall ; ***************************************************************************** _curTCB: .word os_CurrentTask _getParam: .word getParam ; *****************************************************************************
Hi Nagaraj Hegde2, Can you share the way you fix this problem. I am studying about context switch and it's very nice to receive your help. Besides, which board do you use for your code?
It contain many problems. One of majors is here:
ldmia sp, {r0-r14}^ ; Load r0-r14 (User)
SP register is same as R13. You have same register on both sides. Otherwise ARM deprecate SP in the list, see to ARM DDI 0406C.b page A8-399
Why do you not save process/task context on top of stack as usulay?