【问题标题】:How to code ARM interrupt functions in C如何在 C 中编写 ARM 中断函数
【发布时间】:2015-08-27 13:25:42
【问题描述】:

我在 LinuxMint 17.2 64b 上使用 arm-none-eabi-gcc 工具链 v 4.8.2。

在业余爱好者级别,我正在尝试使用 TM4C123G 板及其常用功能(编码各种 blinkies、uart 东西......)但总是试图在不使用其他库的情况下尽可能接近金属(例如CMSIS...) 尽可能。也没有 IDE(CCS、Keil...),只有 Linux 终端窗口、开发板和我...所有这些主要用于教育目的。

问题:我被困在尝试实现通常的中断功能,例如:

EnableInt(清除特殊注册表 PRIMASK 的第 0 位、第 I 位):

CPSIE  I 

WaitForInt:

WFI

DisableInt:

CPSID  I

例如,我将此函数添加到我的 .c 文件中用于 EnableInt :

void EnableInt(void)
{    __asm("    cpsie   i\n");
}

...这可以编译,但执行似乎无法正常工作(在最简单的 blinky.c 版本中,一旦我在 C 代码中调用 EnableInt(),我就无法获得任何 LED 动作)。 blinky.c 代码可以在here找到。

在 .c 文件中编写这些中断例程的正确方法是什么(最好不使用其他库,而只是设置/清除相应寄存器的位...)?

编辑:删除 bx lr 指令 - 但 EnableInt() 似乎没有更好的工作 - 仍在寻找解决方案。

EDIT2 : 实际上,如上定义的 EnableInt() 函数现在正在工作。我的 SysTick_Handler 被错误地映射到启动文件中的中断向量表(而我最初的问题是我在 Edit1 中删除的 bx lr 指令)。

【问题讨论】:

  • 想一想当编译器的默认函数序言在进入EnableInt 时设置一个堆栈帧,推送返回地址,然后您的asm 强制返回而不拆除该堆栈帧时会发生什么?或者更糟糕的是,您打开了优化,并且 asm 在调用站点被内联,所以您“返回”到废话。您绝对不希望bx lr 在内联汇编中。
  • 对于使用 AAPCS 的 Cortex-M CPU,您不需要汇编程序。此外,除非绝对必要,否则不要锁定全局中断。并阅读有关 CMSIS 的信息,使用标准方式,而不是一些自制的东西。为什么在操纵 PRIMASK 之后还要在某个地方分支??

标签: embedded interrupt bare-metal cortex-m


【解决方案1】:

Tivia MCU 集成的 ARM Cortex-M4 CPU 基本上不需要软件环境对进入/退出中断处理程序采取特殊操作。唯一的要求是使用 AAPCS 调用标准,如果为这个 CPU 编译,这应该是 gcc 的默认值。

ARM 提供的一些紧密耦合的“核心”外围设备支持 CPU。这些是大多数(如果不是全部)Cortex-M3/4 MCU 的标准配置。 MCU厂商可以配置一些特性,但基本操作都是一样的。

为简化软件开发,ARM 引入了 CMSIS 软件标准。这至少由一些头文件组成,这些头文件统一了对核心外围设备的访问和特殊 CPU 指令的使用。其中包括操作特殊 CPU 寄存器(如 PRIMASK、BASEMASK、OPTION 等)的内在函数。另一个头文件提供了核心外设和函数的定义,以在简单访问还不够的情况下操作其中的一些。

因此,这些外设之一支持 CPU 进行中断处理:NVIC(嵌套向量中断控制器)。这会再次对中断进行优先级排序,并将中断向量提供给 CPU,CPU 使用该向量来获取中断处理程序的地址。

NVIC 还包括所有中断源的启用位。因此,要让 CPU 处理中断,对于典型的 MCU,您必须在两个或三个位置启用中断:

  1. CPU 中的 PRIMASK/BASEMASK:最后一道防线。这些是全局中断门。 `PRIMASK 类似于较小 CPU 的状态寄存器中的中断使能位,BASEMASK 是中断优先级解决方案的一部分(一开始就忽略它)。
  2. 每个外设中断源的 NVIC 中断使能位。例如 Timer、UART、SPI 等。许多外设都有多个与此 NVIC 线路相关的内部源。 (例如 UART rx 和 tx 中断)。
  3. 外设本身的中断使能位。例如。 UART rx-interrupt、tx 中断、rxerror 中断等

某些外围设备可能没有内部位,因此最后一个可能会丢失。

为了让事情顺利进行,您应该阅读参考手册(家庭指南,或类似的),然后通常会有一些“编写 Cortex-M4”howto(例如 ST 有一个用于 STM32 系列)。您还应该从 ARM 获取文档(它们可以免费下载)。

最后,您需要 MCU 供应商(此处为 TI)提供的 CMSIS 标头。这些应该为您的 MCU 量身定制。您可能需要提供一些 `#define's。

而且,是的,这是很多值得阅读的东西。但 imo 值得付出努力。或者,您可以从一本书开始。有一些可能有助于首先了解整个情况(从单个文档中获取确实很难 - 但可能)。

【讨论】:

  • 这很有用,谢谢。当我超越 blinky.c 阶段时,我一定会听从建议。
  • @JeanAnthelme:不是想推,但请问您为什么不接受答案?缺少什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-23
  • 2019-08-26
  • 1970-01-01
  • 2013-12-24
相关资源
最近更新 更多