Cortex-M3 SysTick 双中断

Posted

技术标签:

【中文标题】Cortex-M3 SysTick 双中断【英文标题】:Cortex-M3 SysTick double interrupt 【发布时间】:2021-05-28 11:32:36 【问题描述】:

我正在创建一个 rtos 系统,系统滴答声 (1ms) 用于实时并触发 pendsv-用于切换任务。 systick 和 pendsv 的优先级与 0 相同(组 = 16;)。当当前任务处于睡眠状态时,PendSv 也会由 触发。 有时,PendSV 和 SysTick 同时发生,先执行 SysTick,再执行 PendSv。但是在 PendSV 执行之后,SysTick 又出现了。 我尝试更改优先级,并在系统滴答句柄中清除 ,没有任何改变。 你知道为什么,以及如何解决这个问题吗? logic_analyzer

asm 代码:​​

//#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;

【问题讨论】:

【参考方案1】:

我现在的解决方案是使用 SVC 而不是 PendSV

【讨论】:

以上是关于Cortex-M3 SysTick 双中断的主要内容,如果未能解决你的问题,请参考以下文章

(转)UCOSII在任务切换与出入中断时堆栈指针的使用

STM32的RTC能产生毫秒级的中断吗

STM32 系统定时器(SysTick)

GPIO外部中断

Cortex-M架构SysTick系统定时器阻塞和非阻塞延时

Cortex-M4 上的 Systick 定时器:它的预分频器是啥?