如果在启用GDB之前附加了GDB,则SysTick中断不会触发

时间:2019-01-30 05:34:42

标签: arm embedded cortex-m gdbserver

我有一个用于半主机的ATSAMD21E18A微型计算机。为了使半主机正常工作,需要在第一个bkpt指令之前“附加” GDB。另一方面,我莫名其妙地发现,如果在配置GDB时已经附加了SysTick中断,则不会触发。如果我想触发SysTick中断,我必须执行一次重置(通过按钮关闭电源),并告诉GDB在尚未配置Micro的情况下继续运行(也就是说,它尚未发送断点或),然后在SysTick配置之后但到达initialise_monitor_handles之前按Ctrl-C初始化调试模式。

我已经验证了start函数仅在可重定位数据段上复制,将零段清零并设置正确的初始堆栈指针值。我们正在编写没有CMSIS这样的库的代码。

除了无需删除调试器(通过Atmel SAM-ICE的JLinkGDBServer),我还可以确认我没有问题,除了需要删除半托管的东西。

此外,即使中断本身不触发,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然后在没有显式的硬复位或软复位的情况下在GDB中运行load时,会发生问题。在这种情况下,SysTick不会触发中断。我的大部分调试工作都是这样,加载新代码并立即期望它能工作,因此我可以对其进行评估。仅运行monitor reset是比以前更好的解决方法,但是我仍然希望知道SysTick行为不当的原因!

1 个答案:

答案 0 :(得分:3)

我将访问《ARM®v6-M体系结构参考手册》,看看您是否可以从中获得一些指导。 https://static.docs.arm.com/ddi0419/d/DDI0419D_armv6m_arm.pdf

观察与您未在问题中包括的Systick有关的寄存器状态。如果您无法根据这些寄存器找出问题,请编辑您的问题,然后在此处发布寄存器值(NVIC ISER,与systick config相关的所有寄存器,DHCSR以及您认为相关的任何其他寄存器)。它们将是获得更多反馈的关键。

调试停止控制和状态寄存器(DHCSR)具有屏蔽包括systick在内的中断的功能。也许这是由调试器设置的吗?

bit 3 of the DHCSR looks relevant

我还要检查SYST_RVR(Systick重新加载值寄存器)是否设置为正常。

我没有代表对您的问题发表评论,但我希望这可以使您朝着富有成效的方向发展:)