我有一个ATSAMD21E18A微型,我正在使用半主机。为了使半主机工作,GDB需要在第一个bkpt指令之前“附加”。另一方面,我莫名其妙地发现,如果在配置GDB时已经连接了SysTick中断,则不会触发。如果我想要触发SysTick中断,我必须执行复位(通过按钮关闭电源)并告诉GDB在尚未配置微控制器时继续(也就是说,它没有发送断点或其他任何事情),然后在SysTick配置之后但在我们到达initialise_monitor_handles
之前按Ctrl-C初始化调试模式。
我已经验证了start函数只是复制可重定位数据段,将零段归零,并设置正确的初始堆栈指针值。我们正在编写没有像CMSIS这样的库的代码。
此外,我可以确认在没有连接调试器时没有问题(JLinkGDBServer通过Atmel SAM-ICE),除了需要删除半主机的东西。
此外,即使中断本身不触发,SysTick COUNT仍可正确计数。此外,ICSR中的SysTick挂起中断位PENDSTSET实际上是在发生这种情况时设置的。
我的代码如下:
int main()
{
// enable system timer interrupt
SYS_TICK->STATUS = 0; // (CSR)
SYS_TICK->PERIOD = 48000; // (RVR) fire at 1khz for 48mhz clock
SYS_TICK->STATUS = 0b111; // use processor clock, w/ interrupt, and enabled
SYS_TICK->COUNT = 1; // (CVR) avoid high unknown value
// dumb busy loop
util_idle_ms(2000); // <<< I hit Ctrl-C to break here!
initialise_monitor_handles();
// ... more system initialization and everything else
}
我在StackOverflow上看到了一些类似的看似问题,但它们似乎太模糊了,无法得到好的答案。
编辑:这里可能是在忙循环期间为不调用SysTick处理程序的运行所采用的相关寄存器值(没有硬复位,在配置SysTick之前连接了GDB):
SYS_TICK_CSR/STATUS: 0x10007
SYS_TICK_RVR/PERIOD: 48000
SYS_TICK_CVR/COUNT: 5245 (varies of course)
NVC_ISER: 0 (and we expect this since SysTick is considered an exception, and not an interrupt)
DHCSR: 0x30003/0x1030003 (C_MASKINTS is not set; I've seen both values show up)
ICSR: 0x400f00f (it really wants to run the SysTick handler)
PRIMASK: 0
xPSR: 0x2100000f (IPSR is 0x0f/SysTick)
并且对于调用SysTick处理程序的运行很好(在SysTick配置之后附加GDB的硬重置):
SYS_TICK_CSR/STATUS: 0x10007
SYS_TICK_RVR/PERIOD: 48000
SYS_TICK_CVR/COUNT: 16892 (varies of course)
NVC_ISER: 0
DHCSR: 0x10003/0x1030003 (I've seen both values show up)
ICSR: 0 (SysTick handler already run)
PRIMASK: 0
xPSR: 0x2100000f
所以这里的寄存器值似乎还没有向我透露任何新内容......请帮助告知我其他可能相关的寄存器!
仅仅是为了感兴趣,这对我来说很重要的原因是因为基于https://mcuoneclipse.com/2015/08/23/tutorial-using-gnu-profiling-gprof-with-arm-cortex-m/,我已经得到了gprof来处理这个芯片。虽然我必须在硬复位后的恰当时间点击Ctrl-C,但它确实有效这个!
编辑我发现我误解了我认为在GDB中运行load
执行软复位的地方。我已经发现虽然它将执行返回到复位向量,但各种外设和其他寄存器实际上并未复位。如果我使用monitor reset
在GDB中执行软复位,那么在延迟附加GDB期间我不需要Ctrl-C,并且SysTick和SemiHosting都可以工作。
配置SysTick时会出现问题,然后load
在GDB中运行,没有明确的硬重置或软重置。在这种情况下,SysTick不会触发中断。我的大多数调试都是这样的,加载新代码并立即期望它能够工作,所以我可以评估它。刚刚运行monitor reset
是比以前更好的解决方法,但我仍然更愿意知道SysTick不当行为的原因!
我将访问ARM®v6-M架构参考手册,看看是否可以从中获得一些指导。 https://static.docs.arm.com/ddi0419/d/DDI0419D_armv6m_arm.pdf
观察您未在问题中包含的与Systick相关的寄存器状态。如果您无法根据这些寄存器找出问题,请编辑您的问题并在此处发布寄存器值(NVIC ISER,与systick配置相关的所有寄存器,DHCSR以及您认为相关的任何其他寄存器)。它们将是获得更多反馈的关键。
调试暂停控制和状态寄存器(DHCSR)能够屏蔽包括systick在内的中断。也许这是由调试器设置的?
bit 3 of the DHCSR looks relevant
我还要检查SYST_RVR(Systick重载值寄存器)是否设置为理智。
我没有代表对您的问题发表评论,但我希望这可以让您朝着富有成效的方向前进:)