如何设置异常发生时的回调函数?
How to set up a callback function when an Exception occurs?
在异常发生时如何设置回调一直困扰我一段时间。
我有这个测试代码:
void main()
{
long * bad = (long*)0x0A000000; //Invalid address
//When the following line gets executed
//it causes an error and the debugger sends me to an assembly file.
*bad = 123456789;
}
我发送到的程序集文件如下所示(真实文件的片段):
.macro DEFAULT_ISR_HANDLER name=
.thumb_func
.weak \name
\name:
1: b 1b /* endless loop */
.endm
DEFAULT_ISR_HANDLER SRC_IRQHandler /*Debugger stops on this line*/
据我了解,DEFAULT_ISR_HANDLER是一个定义了无限循环的宏。
我想要做的是在 C 文件中定义我自己的函数,当发生异常时我可以调用它,而不是调用 DEFAULT_ISR_HANDLER 宏中定义的内容。
我的问题是,如何在该程序集中定义调用特定 C 函数的宏?
希望我解释了自己。任何有关此主题的信息或指导都将受到赞赏。
如果相关,我使用的是 GCC ARM 编译器 v5。4_2016q3
谢谢,
艾萨克
编辑
我使用的是 Cortex-M3。
直到现在我才意识到我在谈论处理器异常。根据数据表,有一个包含 16 种异常类型的列表。
显然,它的工作方式是所有异常类型都被重定向到宏,宏依次调用一些拇指函数,然后是无限循环(根据上面的代码 DEFAULT_ISR_HANDLER)。
为了方便起见,我想做的是在C文件中定义自己的函数,这样每次出现任何类型的处理器异常时,我都可以控制如何进行。
你有两个选择:
只需定义一个带有 void SRC_IRQHandler(void)
签名的 C 函数,由于宏将默认处理程序定义为弱,您的函数将在链接阶段覆盖默认处理程序。
在您的项目中应该有一个地方 SRC_IRQHandler
被放置在 Cortex-M3 架构中所谓的 Vector Table 中。您可以将此函数的名称替换为您自己的 C 函数,当此中断(异常)发生时将调用您的函数。
cortex-m 系列通常有超过 16 个异常,加上该内核实现的中断数量,32、64、128、256。但它们基本上是相同的。 cortex-m 系列的工作方式是,如果你愿意,它们会为你执行 EABI 调用,它们会保留一些寄存器,然后在向量 table 中调用的地址开始执行,这样你就可以完成可以直接在 table 中获得正常编译的 C 函数的地址。从历史上看,您需要用一些代码来包装该函数以保存和恢复状态,并且指令集通常有一个特殊的 return 来自中断,但 cortex-m 他们做的有点不同。
所以知道下一个问题是如何在 table 中获取该地址,这取决于您的代码、构建系统等。这些处理程序可能设置为指向中的地址ram,也许你在 RTOS 上 运行 并且有一个函数你调用运行时来注册一个异常函数,然后 RTOS 更改代码或 ram 中的一些数据值,这些值绑定到它们的处理程序中,基本上环绕你的。或者你在汇编或其他一些特定于工具的东西中制作矢量 table (尽管汇编在那里,工作和简单)并且你简单地计算正确的条目数(或者添加一百个以上的条目以便你可以计算到正确的条目)并放置您的 C 函数的名称。
在 运行 仔细检查您是否已将处理程序地址放置在 interrupt/exception.
的正确物理地址之前,对结果进行反汇编或做一些其他检查是个好主意。
在异常发生时如何设置回调一直困扰我一段时间。
我有这个测试代码:
void main()
{
long * bad = (long*)0x0A000000; //Invalid address
//When the following line gets executed
//it causes an error and the debugger sends me to an assembly file.
*bad = 123456789;
}
我发送到的程序集文件如下所示(真实文件的片段):
.macro DEFAULT_ISR_HANDLER name=
.thumb_func
.weak \name
\name:
1: b 1b /* endless loop */
.endm
DEFAULT_ISR_HANDLER SRC_IRQHandler /*Debugger stops on this line*/
据我了解,DEFAULT_ISR_HANDLER是一个定义了无限循环的宏。 我想要做的是在 C 文件中定义我自己的函数,当发生异常时我可以调用它,而不是调用 DEFAULT_ISR_HANDLER 宏中定义的内容。
我的问题是,如何在该程序集中定义调用特定 C 函数的宏?
希望我解释了自己。任何有关此主题的信息或指导都将受到赞赏。
如果相关,我使用的是 GCC ARM 编译器 v5。4_2016q3
谢谢, 艾萨克
编辑
我使用的是 Cortex-M3。
直到现在我才意识到我在谈论处理器异常。根据数据表,有一个包含 16 种异常类型的列表。
显然,它的工作方式是所有异常类型都被重定向到宏,宏依次调用一些拇指函数,然后是无限循环(根据上面的代码 DEFAULT_ISR_HANDLER)。
为了方便起见,我想做的是在C文件中定义自己的函数,这样每次出现任何类型的处理器异常时,我都可以控制如何进行。
你有两个选择:
只需定义一个带有 void SRC_IRQHandler(void)
签名的 C 函数,由于宏将默认处理程序定义为弱,您的函数将在链接阶段覆盖默认处理程序。
在您的项目中应该有一个地方 SRC_IRQHandler
被放置在 Cortex-M3 架构中所谓的 Vector Table 中。您可以将此函数的名称替换为您自己的 C 函数,当此中断(异常)发生时将调用您的函数。
cortex-m 系列通常有超过 16 个异常,加上该内核实现的中断数量,32、64、128、256。但它们基本上是相同的。 cortex-m 系列的工作方式是,如果你愿意,它们会为你执行 EABI 调用,它们会保留一些寄存器,然后在向量 table 中调用的地址开始执行,这样你就可以完成可以直接在 table 中获得正常编译的 C 函数的地址。从历史上看,您需要用一些代码来包装该函数以保存和恢复状态,并且指令集通常有一个特殊的 return 来自中断,但 cortex-m 他们做的有点不同。
所以知道下一个问题是如何在 table 中获取该地址,这取决于您的代码、构建系统等。这些处理程序可能设置为指向中的地址ram,也许你在 RTOS 上 运行 并且有一个函数你调用运行时来注册一个异常函数,然后 RTOS 更改代码或 ram 中的一些数据值,这些值绑定到它们的处理程序中,基本上环绕你的。或者你在汇编或其他一些特定于工具的东西中制作矢量 table (尽管汇编在那里,工作和简单)并且你简单地计算正确的条目数(或者添加一百个以上的条目以便你可以计算到正确的条目)并放置您的 C 函数的名称。
在 运行 仔细检查您是否已将处理程序地址放置在 interrupt/exception.
的正确物理地址之前,对结果进行反汇编或做一些其他检查是个好主意。