Удалось-таки победить. Вот что вышло:
Это обработчик прерывания для среды IAR:
CODE
extern "C" void PendSV_Handler()
{
#if (defined __ARM_ARCH_6M__) // Cortex-M0(+)/Cortex-M1
asm volatile (
" CPSID I \n" // Prevent interruption during context switch
" MRS R0, PSP \n" // Load process stack pointer to R0
" SUBS R0, R0, #32 \n" // Adjust R0 to point to top of saved context in stack
" MOV R1, R0 \n" // Preserve R0
" MOV R2, R0 \n" // Preserve R0 (needed for os_context_switch_hook() call)
" STMIA R1!, {R4-R7} \n" // Save low portion of remaining registers (r4-7) on process stack
" MOV R4, R8 \n" // Move high portion of remaining registers (r8-11) to low registers
" MOV R5, R9 \n"
" MOV R6, R10 \n"
" MOV R7, R11 \n"
" STMIA R1!, {R4-R7} \n" // Save high portion of remaining registers (r8-11) on process stack
: :
);
asm volatile (
// At this point, entire context of process has been saved
" PUSH {LR} \n" // we must save LR (exc_return value) until exception return
" MOV R1, %0 \n" // load os_context_switch_hook() address;
" MOV R0, R2 \n" // Restore R0 (needed for os_context_switch_hook() call)
" BLX R1 \n" // call os_context_switch_hook();
// R0 is new process SP;
" ADDS R0, R0, #16 \n" // Adjust R0 to point to high registers (r8-11)
" LDMIA R0!, {R4-R7} \n" // Restore r8-11 from new process stack
" MOV R8, R4 \n" // Move restored values to high registers (r8-11)
" MOV R9, R5 \n"
" MOV R10, R6 \n"
" MOV R11, R7 \n"
" MSR PSP, R0 \n" // R0 at this point is new process SP
" SUBs R0, R0, #32 \n" // Adjust R0 to point to low registers
" LDMIA R0!, {R4-R7} \n" // Restore r4-7
" CPSIE I \n"
" POP {PC} \n" // Return to saved exc_return. Exception return will restore remaining context
: : "r" (os_context_switch_hook)
);
#else // #if (defined __ARM_ARCH_6M__)
#if (defined __SOFTFP__)
// M3/M4 cores without FPU
asm volatile (
" CPSID I \n" // Prevent interruption during context switch
" MRS R0, PSP \n" // PSP is process stack pointer
" STMDB R0!, {R4-R11} \n" // Save remaining regs r4-11 on process stack
// At this point, entire context of process has been saved
" PUSH {LR} \n" // we must save LR (exc_return value) until exception return
" LDR R1, =os_context_switch_hook \n" // call os_context_switch_hook();
" BLX R1 \n"
// R0 is new process SP;
" LDMIA R0!, {R4-R11} \n" // Restore r4-11 from new process stack
" MSR PSP, R0 \n" // Load PSP with new process SP
" CPSIE I \n"
" POP {PC} \n" // Return to saved exc_return. Exception return will restore remaining context
: :
);
#else // #if (defined __SOFTFP__)
// Core with FPU (cortex-M4F)
asm volatile (
" CPSID I \n" // Prevent interruption during context switch
" MRS R0, PSP \n" // PSP is process stack pointer
" TST LR, #0x10 \n" // exc_return[4]=0? (it means that current process
" IT EQ \n" // has active floating point context)
" VSTMDBEQ R0!, {S16-S31} \n" // if so - save it.
" STMDB R0!, {R4-R11, LR} \n" // save remaining regs r4-11 and LR on process stack
// At this point, entire context of process has been saved
" LDR R1, =os_context_switch_hook \n" // call os_context_switch_hook();
" BLX R1 \n"
// R0 is new process SP;
" LDMIA R0!, {R4-R11, LR} \n" // Restore r4-11 and LR from new process stack
" TST LR, #0x10 \n" // exc_return[4]=0? (it means that new process
" IT EQ \n" // has active floating point context)
" VLDMIAEQ R0!, {S16-S31} \n" // if so - restore it.
" MSR PSP, R0 \n" // Load PSP with new process SP
" CPSIE I \n"
" BX LR \n" // Return to saved exc_return. Exception return will restore remaining context
: :
);
#endif // #if (defined __SOFTFP__)
#endif // #if (defined __ARM_ARCH_6M__)
}
А это функция старта оси, также для среды IAR:
CODE
extern "C" NORETURN void os_start(stack_item_t *sp)
{
// Set PendSV lowest priority value
#if (defined SHP3_WORD_ACCESS)
SHPR3 |= (0xFF << 16);
#else
PendSvPriority = 0xFF;
#endif
#if (!defined __SOFTFP__)
FPCCR |= ASPEN | LSPEN;
#endif
asm volatile (
#if (defined __SOFTFP__) // code without FPU
" LDR R4, [%[stack], #(4 * 14)] \n" // Load process entry point into R4
" ADDS %[stack], #(4 * 16) \n" // emulate context restore
#else
" LDR R4, [%[stack], #(4 * 15)] \n" // Load process entry point into R4
" ADD %[stack], #(4 * 17) \n" // emulate context restore
#endif
" MSR PSP, %[stack] \n" // store process SP to PSP
" MOVS R0, #2 \n" // set up the current (thread) mode: use PSP as stack pointer, privileged level
" MSR CONTROL, R0 \n"
" ISB \n" // Insert a barrier
: [stack]"+r" (sp) // output
);
asm volatile (
" MOV R1, %0 \n" // Init and run system timer
" BLX R1 \n" //
" CPSIE I \n" // Enable interrupts at processor level
" BX R4 \n" // Jump to process exec() function
: :"r" (__init_system_timer) // output
);
}
В результате я перенёс некоторые функции, приведя в соответствие с версией для GCC и избавился от файла os_target_asm.s