微芯片异常处理
在微芯片 ICD3 设备上运行我的程序时,异常处理看起来很奇怪。发生异常时程序将停止响应。在检查代码时,我注意到 default-general-exception-handler.c 将创建一个无限循环。这真的很令人困惑,因为我不知道错误发生在哪里以及原因是什么。这是否意味着 Microchip 不支持异常处理?或者有什么办法可以读取错误信息?
无限循环:
--- \home\c11067\work\C32\builds\pic32-microchip-release-1.12-20101221-rc2-20101221\pic32-libs\libc\stubs\default-general-exception-handler.c
9D00DD28 1000FFFF beq zero,zero,0x9d00dd28
9D00DD2C 00000000 nop
通过定义_general_exception_handler,它可以工作!
// declared static in case exception condition would prevent
// auto variable being created
static enum {
EXCEP_IRQ = 0, // interrupt
EXCEP_AdEL = 4, // address error exception (load or ifetch)
EXCEP_AdES, // address error exception (store)
EXCEP_IBE, // bus error (ifetch)
EXCEP_DBE, // bus error (load/store)
EXCEP_Sys, // syscall
EXCEP_Bp, // breakpoint
EXCEP_RI, // reserved instruction
EXCEP_CpU, // coprocessor unusable
EXCEP_Overflow, // arithmetic overflow
EXCEP_Trap, // trap (possible divide by zero)
EXCEP_IS1 = 16, // implementation specfic 1
EXCEP_CEU, // CorExtend Unuseable
EXCEP_C2E // coprocessor 2
} _excep_code;
static unsigned int _epc_code;
static unsigned int _excep_addr;
// this function overrides the normal _weak_ generic handler
void _general_exception_handler(void)
{
asm volatile("mfc0 %0,$13" : "=r" (_excep_code));
asm volatile("mfc0 %0,$14" : "=r" (_excep_addr));
_excep_code = (_excep_code & 0x0000007C) >> 2;
while (1) {
// Examine _excep_code to identify the type of exception
// Examine _excep_addr to find the address that caused the exception
}
}
While running my program on a microchip ICD3 device, the exception handling looks weird. The program will stop response while exception occurs. While checking the code, I noticed that the default-general-exception-handler.c will create an infinite loop. It is really confusing because I cannot know where the error occurs and what is the reason. Does that mean Microchip doesn't support exception handling? Or is there a way to read the error message?
infinite loop:
--- \home\c11067\work\C32\builds\pic32-microchip-release-1.12-20101221-rc2-20101221\pic32-libs\libc\stubs\default-general-exception-handler.c
9D00DD28 1000FFFF beq zero,zero,0x9d00dd28
9D00DD2C 00000000 nop
By defining a _general_exception_handler, it works!
// declared static in case exception condition would prevent
// auto variable being created
static enum {
EXCEP_IRQ = 0, // interrupt
EXCEP_AdEL = 4, // address error exception (load or ifetch)
EXCEP_AdES, // address error exception (store)
EXCEP_IBE, // bus error (ifetch)
EXCEP_DBE, // bus error (load/store)
EXCEP_Sys, // syscall
EXCEP_Bp, // breakpoint
EXCEP_RI, // reserved instruction
EXCEP_CpU, // coprocessor unusable
EXCEP_Overflow, // arithmetic overflow
EXCEP_Trap, // trap (possible divide by zero)
EXCEP_IS1 = 16, // implementation specfic 1
EXCEP_CEU, // CorExtend Unuseable
EXCEP_C2E // coprocessor 2
} _excep_code;
static unsigned int _epc_code;
static unsigned int _excep_addr;
// this function overrides the normal _weak_ generic handler
void _general_exception_handler(void)
{
asm volatile("mfc0 %0,$13" : "=r" (_excep_code));
asm volatile("mfc0 %0,$14" : "=r" (_excep_addr));
_excep_code = (_excep_code & 0x0000007C) >> 2;
while (1) {
// Examine _excep_code to identify the type of exception
// Examine _excep_addr to find the address that caused the exception
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在大多数微控制器上,除了您放置的代码之外,没有任何代码。在大多数情况下,如果发生异常并且您没有为其定义处理程序,则处理器将不知道如何显示“抱歉,发生系统错误”对话框。使用两个字节作为“分支到自身”指令足以产生对异常的可预测响应;如果没有特别了解任何更好的行动方案,分支到自身或强制重置可能是最好的回应。
PS--一些针对各种平台的编译器会省略未使用的中断或异常的向量;如果这种异常意外发生,就会发生奇怪的事情。一些编译器会生成强制立即重置的代码(请注意,如果启用了看门狗定时器,则跳转到自身最终将导致重置)。一些编译器生成立即从中断返回(这在某些 CPU 上可能是无用的,而在其他 CPU 上可能会导致不良行为)。我最喜欢的模式是让所有未使用的中断调用(而不是分支)UnexpectedInterrupt 标签,在没有任何显式定义的情况下,该标签将指向分支到自身指令。如果这样做,意外中断处理程序可以弹出堆栈并记录发生的意外中断类型。不过,除了我自己手动生成的中断向量表之外,我还没有看到这样的模式。
On most microcontrollers, there isn't any code beyond what you put there. In most cases, if an exception occurs and you haven't defined a handler for it, the processor would have no idea how to put up a "Sorry, a system error occurred" dialog box. Using two bytes for a "branch-to-self" instruction is enough to yield a predictable response to an exception; without particular knowledge of any better course of action, a branch-to-self or forced reset is probably as good a response as anything.
PS--Some compilers for various platforms will omit vectors for unused interrupts or exceptions; if such exceptions occur unexpectedly, weird and bizarre things can happen. Some compilers will produce code that will force an immediate reset (note that if watchdog timer is enabled, a jump-to-self will cause a reset, eventually). Some compilers generate an immediate return-from-interrupt (which on some CPU's may be useless, and on others can cause bad behavior). My favorite pattern would be to have all unused interrupts make a call (not a branch) to an UnexpectedInterrupt label, which in the absence of any explicit definition will point to a branch-to-self instruction. If one does that, an UnexpectedInterrupt handler can pop the stack and record what type of unexpected interrupt occurred. I've not seen such a pattern, though, outside my own manually-generated interrupt vector tables.
正如进一步 PIC32 异常调试的提示一样,异常代码和“CAUSE”寄存器中的所有位(在清除所有其他位之前读入 _excep_code 变量的值)定义如下:
PIC32 系列参考手册,第2.12.9 原因寄存器
http://ww1.microchip.com/downloads/en/DeviceDoc/61113C.pdf
Just as a heads-up for further PIC32 exception debugging, the exception codes and all the bits in the 'CAUSE' register (the value you're reading into your _excep_code variable before and-ing all the other bits away) are defined in:
PIC32 Family Reference Manual, Section 2.12.9 CAUSE Register
http://ww1.microchip.com/downloads/en/DeviceDoc/61113C.pdf