当我尝试将微控制器置于休眠状态然后将其唤醒时,我发现了这个问题,这是一个中断驱动的应用程序。我注意到我的代码没有从我的“睡眠”之后的代码行中恢复。指令。
当我在使用调试器单步执行代码时手动触发中断时,它会在跳转到ISR之前需要多个步骤(有时为2,有时为50,具体取决于代码)。
在尝试调试此问题时,我编写了一段非常简单的代码来展示问题:
#include <Arduino.h>
// Setup and Loop declared in Arduino core
void configInterrupt(void);
volatile uint32_t debug = 0;
uint32_t int_count = 0;
void EIC_Handler(void){
int_count++;
EIC->INTFLAG.reg = 1 << 0;
}
void configInterrupt(void){
NVIC_DisableIRQ(EIC_IRQn);
NVIC_ClearPendingIRQ(EIC_IRQn);
NVIC_SetPriority(EIC_IRQn, 0);
NVIC_EnableIRQ(EIC_IRQn);
GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID(GCM_EIC));
EIC->WAKEUP.reg |= (1 << 0);
EIC->CONFIG[0].reg |= 0x2; // falling edge
pinConfig(16,INPUT,UP); // pin 16 as input with pullup
PORT->Group[0].PINCFG[16].bit.PMUXEN = 1; // enable peripheral muxing
PORT->Group[0].PMUX[8].bit.PMUXE = 0x0; // function A (EIC) = 0x0
EIC->INTENSET.reg = EIC_INTENSET_EXTINT(1 << 0);
EIC->CTRL.bit.ENABLE = 1;
}
void setup() {
configInterrupt();
}
void loop() {
for(int i = 0 ; i < 100 ; i++) debug++; // volatile so that the compiler doesn't touch
String debugstring = "";
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__DSB();
__WFI();
}
我正在使用外部中断进行调试,我使用跳线触发自己,这样我就知道应该何时触发它。我注意到的是,当我调试代码并逐步执行它时,如果我手动触发外部中断,那么它不会立即跳转到ISR。中断变为等待&#39;在NVIC中,例外条目不会在代码后面执行。
我已经阅读了很多关于SAMD21数据表中的中断和异常,Cortex M0 +通用用户指南和ARM体系结构手册。据推测,Cortex M系列具有低延迟中断,没有指令开销,因此看起来代码应该在触发中断后相对快速地跳转到ISR。
我已经多次阅读了Cortex M0 +通用指南的2.3.6以及ARM体系结构手册的B1.3.2,它们都非常详细地介绍了异常输入。 SAMD21数据表似乎没有太多低级信息。
我试图找出问题并找出设备行为中的任何模式,并且我注意到了一些事情。
它只在特定的代码行跳转到ISR。例如,在上面的代码中,如果在&#39; loop()&#39;开始时触发外部中断。它会在到达字符串声明时跳转到ISR,无论“#”中有多少次迭代。环。如果我将字符串声明移到&#39;上面。然后它会立即跳转到ISR(在2或3个调试步骤之后)。
我已尝试插入延迟,NOP和ISB,这些延迟不会影响所需的时间或使其立即跳转。 当我通过NVIC中的ISPR寄存器在软件中设置挂起中断时,会出现同样的问题。 我已经跟踪了Atmel Studio中的基本FLASH内存,并发现&#34; stack&#34;处理器的当前状态&#39;被推,也不会立即改变。它只会在我到达ISR中的第一行代码时发生变化。
我注意到的其他代码与String声明类似,导致代码跳转到ISR的是Wire库的endTransmission函数,SD卡库中的一些函数,Arduino延迟函数
这是否与我首先使用调试器干扰/不干扰中断的事实有关?在调试器出来之前,我确定问题已经发生了。编辑:通过Cortex M0 +技术参考手册和ARMv6手册阅读我找到了一个名为DHCSR的寄存器,它允许调试器屏蔽中断,但我无法解决如何访问这些寄存器的问题。
主要问题:除了PRIMASK和全局/个人使能寄存器位之外,还有什么可能阻止执行待处理中断?
编辑:遗漏了一条重要的信息,虽然我在Atmel Studio工作但该项目使用的是Arduino核心。
编辑:我注意到在手动触发中断后,在我的下一个调试步骤中,它在NVIC-&gt; ISPR寄存器中变为待处理状态。这让我相信中断在某处被掩盖了(我已经检查了PRIMASK,全局启用和个人启用到目前为止没有运气)。
答案 0 :(得分:0)
String debugstring = "";
是这个东西实际上是C ++的线索。
因此,您必须将IRQ处理程序声明为纯C函数:
extern "C" {
void EIC_Handler(void);
}
void EIC_Handler(void){
int_count++;
EIC->INTFLAG.reg = 1 << 0;
}
否则函数是C ++,它不能作为IRQ处理程序,因为链接器无法识别它。