Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/spring-mvc/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Embedded 如何用C编写ARM中断函数_Embedded_Interrupt_Bare Metal_Cortex M - Fatal编程技术网

Embedded 如何用C编写ARM中断函数

Embedded 如何用C编写ARM中断函数,embedded,interrupt,bare-metal,cortex-m,Embedded,Interrupt,Bare Metal,Cortex M,我正在LinuxMint 17.2 64b上使用工具链V4.8.2 我是一个业余爱好者,尝试使用TM4C123G板和它的常用功能(编码各种闪烁、uart等),但总是尽可能地保持接近金属,而不使用其他库(如CMSIS…)。也没有IDE(CCS,Keil…),只有Linux终端窗口,主板和I。。。所有这些主要是为了教育目的 问题:我一直在尝试实现常见的中断功能,如: EnableInt(清除特殊注册表PRIMASK的第0位、第I位): WaitForInt: WFI 禁用: CPSID I 例

我正在LinuxMint 17.2 64b上使用工具链V4.8.2

我是一个业余爱好者,尝试使用TM4C123G板和它的常用功能(编码各种闪烁、uart等),但总是尽可能地保持接近金属,而不使用其他库(如CMSIS…)。也没有IDE(CCS,Keil…),只有Linux终端窗口,主板和I。。。所有这些主要是为了教育目的

问题:我一直在尝试实现常见的中断功能,如:

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

WaitForInt:

WFI
禁用:

CPSID  I
例如,我将此函数添加到.c文件中以启用int:

void EnableInt(void)
{    __asm("    cpsie   i\n");
}
。。。这可以编译,但执行似乎不能正常工作(在最简单的blinky.c版本中,在c代码中调用EnableInt()后,我无法获得任何LED操作)。可以找到blinky.c代码

在.c文件中写入这些中断例程的正确方法是什么(理想情况下不使用其他库,而只是设置/清除相应寄存器的位

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


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

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

CPU由ARM提供的一些紧密耦合的“核心”外围设备支持。这些是大多数(如果不是全部)Cortex-M3/4 MCU的标准配置。MCU供应商可以配置某些功能,但基本操作始终相同

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

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

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

  • CPU中的PRIMASK/BASEMASK:最后一道防线。这些是全局中断门`PRIMASK类似于较小CPU状态寄存器中的中断启用位,基址掩码是中断优先级解析的一部分(只需在开始时忽略它)
  • 每个外围中断源的NVIC中断启用位。例如定时器、UART、SPI等。许多外围设备都有多个内部源连接到该NVIC线路。(例如UART接收和发送中断)
  • 外围设备本身的中断启用位。例如UART接收中断、tx中断、rxerror中断等
  • 某些外围设备可能没有内部位,因此最后一个位可能丢失

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

    最后,您需要MCU供应商提供的CMSIS标头(此处为TI)。这些应该为您的MCU定制。您可能需要提供一些“定义”


    而且,是的,这是很值得一读的东西。但在我看来,这是值得努力的。或者你可以从一本书开始。有一些方法可能有助于首先了解整个情况(从单个文档中获取确实很困难,但这是可能的)。

    想想当编译器的默认函数prologue在
    EnableInt
    的条目上设置堆栈帧,推送返回地址,然后asm强制返回而不拆下堆栈帧?或者更糟糕的是,你打开了优化,asm在呼叫站点内联,所以你“回到”胡说八道。您绝对不希望在内联asm中使用
    bx lr
    。对于使用AAPC的Cortex-M CPU,您不需要汇编程序。此外,除非绝对必要,否则不要锁定全局中断。阅读CMSIS,使用标准方式,而不是一些自制的东西。为什么在操作PRIMASK之后要在某个地方进行分支?这很有用,谢谢。当我超越blinky.c阶段时,我肯定会听从建议。@JeanAnthelme:我不是想推,但我可以问一下你为什么不接受答案吗?少了什么?
    void EnableInt(void)
    {    __asm("    cpsie   i\n");
    }