我不确定我是否遗漏了一些明显的东西,但是其他任何人都遇到过从ISR返回到某个随机位置的Cortex M0 +(或任何Cortex M系列)的任何问题从睡眠模式唤醒后的线程模式(例如,不返回到WFI指令下面的行)。它似乎在代码中间醒来,比如在for循环的中间或函数的中间。我使用的是ATSAMD218A微控制器,并且一直在使用Atmel Studio 7中的调试器。我试图找出问题并发现以下情况:
我一直在阅读ARMv6架构参考手册以及Cortex M0 +通用用户指南。不太清楚发生了什么,任何调试建议都会非常感激。有没有人更好地理解Cortex M系列的异常处理,并且可以指出我找到线程模式在ISR之后返回的内存地址的正确方向。如果您愿意,我可以提供代码,但即使是一段简单的代码,除了循环计数,睡眠然后唤醒都会造成麻烦。
EDIT 我已在下面添加了相关代码。它是最剥离的版本(*剥离)仍然会导致问题。我还没有包含RTC代码功能(使用DS3231RTC库),因为我相当确定它们没有任何效果。如果你认为我应该上传更多让我知道。
void configInterrupt(void){
NVIC_DisableIRQ(EIC_IRQn);
NVIC_ClearPendingIRQ(EIC_IRQn);
NVIC_SetPriority(EIC_IRQn, 0);
NVIC_EnableIRQ(EIC_IRQn);
// Enable GCLK for IEC (External Interrupt Controller)
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); // custom 'pinMode' function
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 EIC_Handler(void){
RTC_FLAG = 1; // my debug breakpoint is here, at this point the stack has already been pushed and I can see the PC value that will be popped off
int_count++;
EIC->INTFLAG.reg = 1 << 0;
}
void setup() {
configInterrupt();
configureRTC();
RTC_FLAG = 1;
}
void loop() {
if (RTC_FLAG == 1) {
RTC_FLAG = 0;
setNextAlarm();
}
for (int i = 0 ; i <= WINDOW-1 ; i++) {
String data = "";
rawVal = 0; // data gets read from sensor here (stripped)
data += String(rawVal);
data += ",";
distance = 0; // distance calculated from rawVal here (stripped)
data += String(distance);
data += ",";
mean = 0; // mean calculated in a function here (stripped)
data += String(mean);
data += ",";
data += String(int_count); // ISR returns here
// Data gets written to file here (stripped)
}
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
__DSB();
__WFI();
}
答案 0 :(得分:0)
我尝试使用Atmel ASF框架实现相同的代码段,查看API设置的寄存器以及顺序。他们通常也会参考勘误表并实施一项工作。
加载低功耗示例项目,它在电源模式之间切换,并按下xplained board按钮。如果它可以在你的主板上的模式之间跳转,你知道它不是那个部分。您可能必须将唤醒引脚移动到与硬件匹配的位置。