Cortex-M0+ 不响应 PendSV

问题描述

我在 RaspBerry Pi Pico(RP2040,Cortex-M0+ 内核,使用 JLink SWD 通过 VSCode cortex-debug 进行调试)上运行,我看到有关 PendSV 的奇怪行为。

就在此之前,SVCall 异常处理程序通过 ICSR 寄存器请求 PendSV。但是在异常返回时,不是尾链 PendSV,而是执行返回到调用代码并继续非异常执行。

ICSR 寄存器一直显示挂起的 PendSV,即使线程代码指令重复执行。系统处理程序优先级全部为零,IRQ 优先级较低。

enter image description here

根据 ARMv6-M 参考手册,PendSV 不能被禁用。

那么,我错过了什么会导致这种行为?

编辑添加

也许是调试器交互? JLink 软件 (v4.95d) 仍处于 Beta 阶段...

我看到调试器实际上可以禁用 PendSV 和 Systick - C1.5.1 Debug Stepping:“可选地,调试器可以将 DHCSR.C_MASKINTS 设置为 1,以防止发生 PendSV、SysTick 和外部可配置中断。这被描述为屏蔽这些中断。第 C1-326 页上的表 C1-7 总结了指令步进控制。"

解决方法

事实证明,问题是由单步执行写入 ICSR 中 PENDSVSET 位的指令引起的:该位已设置,VECTPENDING 字段显示 0xe,但 PendSV 从未触发。

在该指令上自由运行到后面的断点可以看到 PendSV 正确触发。

所以这确实是一个调试器交互。

这是否与@cooperised 建议的中断被禁止有关尚不清楚 - DHCSR 的 C_MASKINTS 位始终读取为零,但在此级别上看不到实际步骤操作期间如何操作该位。>

这让我想知道 JLink 执行步骤的方式是否会导致不可预测/不确定的行为 - 例如根据 C_MASKINTS 描述中的警告。或者,这可能只是在这种情况下 M0+ 中发生的情况,而我以前从未单步执行过此指令。

无论如何,解决方法就是不要单步执行设置 PENDSVSET 的指令。

编辑添加:

最后,@cooperised 是正确的。

在更加小心地准确区分单步执行(包括单步执行函数调用)和运行(包括运行到下一条指令)时,很明显单步执行会禁用包括 PendSV 在内的中断。