问题描述
我正在创建一个 rtos 系统,实时系统滴答 (1ms) 和触发 pendsv-用于切换任务。 systick 和 pendsv 的优先级与 0 相同(组 = 16;
汇编代码:
//#define USING_PUSH_POP
EXTERN GPIOA_BITBAND
EXTERN RTOS_GetCurrentcpu //cpu_TypeDef* RTOS_GetCurrentcpu();
EXTERN RTOS_GetNextcpu //cpu_TypeDef* RTOS_GetNextcpu();
PUBLIC PendSV_Handler
PUBLIC RTOS_ASM_Begin //void RTOS_ASM_ASM_Begin(cpu_TypeDef* cpu);
SECTION rtos_function:CODE
PendSV_Handler:
//PUSH in SP when interrupt
//Here - R0 - R1 - R2 - R3 - R12 - BACK_LR - BACK_PC - EAPSR
PUSH {LR}
LDR.W R0,=GPIOA_BITBAND //(1)
MOV R1,#1
STR R1,[R0,#0x180]
BL RTOS_GetCurrentcpu
CMP R0,#0
BEQ BREAK //if (NULL): back to current task
BL RTOS_ASM_SaveCurrentcpu
BL RTOS_GetNextcpu
CMP R0,#0
BEQ BREAK //if (NULL): back to current task
B RTOS_ASM_SwitchNextcpu
BREAK:
POP {PC}
//===================================
RTOS_ASM_Begin: //R0: cpu_TypeDef* Maincpu
PUSH {R1,LR}
STR LR,#28]
STR R1,#24]
ADDS R1,R0,#24
MOV SP,R1
BL RTOS_ASM_SaveCurrentcpu
POP {R1,PC}
//===================================
RTOS_ASM_SaveCurrentcpu: //R0: cpu_TypeDef* Currentcpu
#ifdef USING_PUSH_POP
MOVS R1,SP
STR SP,#(4 * 16)]
ADDS R0,#(4 * 16)
MOVS SP,R0
PUSH {R4-R11}
MOVS SP,R1
#else
STR R4,#(4 * 8 )]
STR R5,#(4 * 9 )]
STR R6,#(4 * 10)]
STR R7,#(4 * 11)]
STR R8,#(4 * 12)]
STR R9,#(4 * 13)]
STR R10,#(4 * 14)]
STR R11,#(4 * 15)]
STR SP,#(4 * 16)]
#endif
BX LR
//===================================
RTOS_ASM_SwitchNextcpu: //R0: cpu_TypeDef* Nextcpu
#ifdef USING_PUSH_POP
ADDS R1,#(4 * 8)
MOVS SP,R1
POP {R4-R11}
LDR SP,#(4 * 16)]
#else
LDR R4,#(4 * 8 )]
LDR R5,#(4 * 9 )]
LDR R6,#(4 * 10)]
LDR R7,#(4 * 11)]
LDR R8,#(4 * 12)]
LDR R9,#(4 * 13)]
LDR R10,#(4 * 14)]
LDR R11,#(4 * 15)]
LDR SP,#(4 * 16)]
#endif
LDR.W R0,=GPIOA_BITBAND //(2)
MOV R1,#0
STR R1,#0x180]
POP {PC}
//===================================
END
系统滴答句柄:
void SysTick_Handler()
{
GPIOB_BITBAND.ODR._10 ^= 1; //(3)
System.MsTick++;
if (TaskManager.Running)
RTOS_SWITCH_TRIGGER();
//SCB.ICSR.REG = BIT25;
SCB.ICSR.BITS.PENDSTCLR = 1;
}
解决方法
我现在的解决方案是使用 SVC 而不是 PendSV