首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >皮层M0+ (SAMD21)不执行挂起的中断

皮层M0+ (SAMD21)不执行挂起的中断
EN

Stack Overflow用户
提问于 2016-06-22 04:47:55
回答 1查看 2K关注 0票数 3

当我试图让微控制器进入睡眠状态,然后唤醒它,作为一个中断驱动的应用程序时,我发现了这个问题。我注意到,我的代码没有从我的“睡眠”指令之后的代码行中恢复。

当我在使用调试器执行代码时手动触发中断时,在跳转到ISR之前,它会采取多个步骤(有时是2步,有时是50步,取决于代码)。

在尝试调试此问题时,我编写了一段非常简单的代码,其中显示了这个问题:

代码语言:javascript
运行
复制
#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。中断在NVIC中变为“未决”,但异常项要到代码的后面才会执行。

我在SAMD21数据表、Cortex M0+通用用户指南和ARM体系结构手册中阅读了很多关于中断和异常的文章。据推测,Cortex M系列具有低延迟中断,没有指令开销,因此在触发中断后,代码应该相对较快地跳转到ISR。

我已经多次阅读过Cortex M0+泛型指南的2.3.6以及ARM体系结构手册的B1.3.2,这两本手册都详细介绍了异常条目。SAMD21数据表似乎没有太多低级别的信息。

我试图隔离这个问题并识别设备行为中的任何模式,我注意到了一些事情。

它只在特定的代码行跳到ISR。例如,在上面的代码中,如果外部中断是在' loop ()‘开头触发的,那么无论' For’循环中有多少次迭代,当它到达字符串声明时,它都会跳转到ISR。如果我将字符串声明移到“for”循环上方,那么它几乎会立即跳转到ISR (在2或3个调试步骤之后)。

我尝试过插入延迟,NOPs和ISB,这不会影响它花费多长时间或使它立即跳跃。当我在软件中设置一个挂起的中断时,通过国家核生化中心的ISPR寄存器,也会出现同样的问题。我跟踪了Atmel Studio中的基本闪存,并注意到处理器当前状态被推送到的“堆栈”也不会立即改变。只有当我到达ISR中的第一行代码时,它才会改变。

我注意到的其他代码片段类似于字符串声明,并导致代码跳转到ISR中,这是电线库的endTransmission函数,SD卡库中的一些函数,Arduino延迟函数。

这是否与我一开始就使用调试器而干扰/不使用中断的事实有关?不过,我相当肯定问题发生在调试器出炉之前。编辑:通过阅读Cortex M0+技术参考手册和ARMv6手册,我找到了一个名为DHCSR的寄存器,它允许调试器屏蔽中断,但我无法想出如何访问这些寄存器。

的主要问题:除了PRIMASK和全局/个人启用寄存器位之外,还有什么可以阻止挂起的中断被执行呢?

编辑:遗漏了一段重要的信息,尽管我在Atmel Studio工作,但这个项目使用Arduino核心。

编辑:我注意到,在我手动触发一个中断之后,在我的下一个调试步骤中,它就会被挂在N维也纳->ISPR寄存器中。这让我相信中断被掩盖了(我已经检查了PRIMASK,全局启用和个人启用到目前为止没有运气)。

EN

回答 1

Stack Overflow用户

发布于 2016-06-23 15:19:37

String debugstring = "";是这个东西实际上是C++的线索。因此,必须将IRQ处理程序声明为纯C函数:

代码语言:javascript
运行
复制
extern "C" {
void EIC_Handler(void);
}
void EIC_Handler(void){
  int_count++;
  EIC->INTFLAG.reg = 1 << 0;
}

否则,函数是C++,an不作为IRQ处理程序,因为链接器本身无法识别它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/37958762

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档