我正在创建一个 rtos 系统,系统滴答声(1ms)用于实时并触发用于切换任务的 pendsv。systick 和 pendsv 的优先级与 0 相同(组 = 16;<SCB.AIRCR.PRIGROUP = 0b011>)。当当前任务处于睡眠状态时,PendSv 也会由 <SCB.ICSR.PENDSVSET = 1> 触发。有时,PendSV 和 SysTick 同时发生,先执行 SysTick,再执行 PendSv。但是在 PendSV 执行之后,SysTick 又出现了。我尝试更改优先级,并在系统滴答句柄中清除 <SCB.ICSR.PENDSTCLR = 1> ,没有任何改变。你知道为什么,以及如何解决这个问题吗? 逻辑分析器
汇编代码:
//#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 , [R0, #28]
STR R1 , [R0, #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 , [R0, #(4 * 16)]
ADDS R0 , R0, #(4 * 16)
MOVS SP , R0
PUSH {R4-R11}
MOVS SP , R1
#else
STR R4 , [R0, #(4 * 8 )]
STR R5 , [R0, #(4 * 9 )]
STR R6 , [R0, #(4 * 10)]
STR R7 , [R0, #(4 * 11)]
STR R8 , [R0, #(4 * 12)]
STR R9 , [R0, #(4 * 13)]
STR R10, [R0, #(4 * 14)]
STR R11, [R0, #(4 * 15)]
STR SP , [R0, #(4 * 16)]
#endif
BX LR
//===================================
RTOS_ASM_SwitchNextCPU: //R0: CPU_TypeDef* NextCPU
#ifdef USING_PUSH_POP
ADDS R1 , R0, #(4 * 8)
MOVS SP , R1
POP {R4-R11}
LDR SP , [R0, #(4 * 16)]
#else
LDR R4 , [R0, #(4 * 8 )]
LDR R5 , [R0, #(4 * 9 )]
LDR R6 , [R0, #(4 * 10)]
LDR R7 , [R0, #(4 * 11)]
LDR R8 , [R0, #(4 * 12)]
LDR R9 , [R0, #(4 * 13)]
LDR R10, [R0, #(4 * 14)]
LDR R11, [R0, #(4 * 15)]
LDR SP , [R0, #(4 * 16)]
#endif
LDR.W R0, =GPIOA_BITBAND //(2)
MOV R1, #0
STR R1, [R0, #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;
}