Linker ARM链接器如何知道异常表的停止位置?

Linker ARM链接器如何知道异常表的停止位置?,linker,arm,cortex-m3,Linker,Arm,Cortex M3,在查找基本的裸机Cortex-M3编程信息时,我遇到了与以下内容非常相似的情况(这里有一个很好的答案,稍后我将尝试查找) 这对我来说是有意义的,我理解它的作用,但对我来说没有意义的是链接器(或CPU,我不确定哪个…)如何知道异常表的结束和实际代码的开始。在我看来,从Cortex-M3文档中可以看出,表中可以有任意数量的外部中断 这是如何工作的,我应该读些什么来学习?这是我的代码,程序员而不是链接器需要知道发生了什么。cortex-m有不同的向量表,它们可能相当长,有许多单独的中断向量。以上只是某

在查找基本的裸机Cortex-M3编程信息时,我遇到了与以下内容非常相似的情况(这里有一个很好的答案,稍后我将尝试查找)

这对我来说是有意义的,我理解它的作用,但对我来说没有意义的是链接器(或CPU,我不确定哪个…)如何知道异常表的结束和实际代码的开始。在我看来,从Cortex-M3文档中可以看出,表中可以有任意数量的外部中断


这是如何工作的,我应该读些什么来学习?

这是我的代码,程序员而不是链接器需要知道发生了什么。cortex-m有不同的向量表,它们可能相当长,有许多单独的中断向量。以上只是某一天从一种味道中快速品尝出来的。如果您只使用重置向量,那么创建整个表时是否需要消耗更多内存位置?可能不会。您可能希望使其足够深,以覆盖未定义的异常和中止等,以便使用受控挂起来捕获它们。如果您只需要重置和一个中断,但该中断在表中很深,您可以制作一个巨大的表来覆盖这两个中断,或者如果您足够勇敢,可以在它们之间放置一些代码来恢复丢失的空间

要了解/阅读更多信息,您需要访问TRM技术参考手册,了解cortex-m内核cortex-m0、cortex-m3和cortex-m4以及armv7-m的手臂(cortex-m都属于armv7-m系列)。ARM是指ARM体系结构参考手册,它笼统地介绍了整个系列,但没有详细介绍核心特定的细节,通常在为ARM编程时,您需要一个ARM和正确的TRM(如果您需要进入任何低级别,如asm或特定寄存器)。所有这些都可以在arm网站infocenter.arm.com的左侧找到,查看架构或Cortex-M系列处理器

这些核心是新的足够他们可能没有超过原来的版本号。对于一些旧的内核,最好获取特定内核的TRM。以ARM11 Mpcore为例,如果供应商使用版本1.0(r1p0)的core,尽管手册上的标记已过时,但如果存在差异,您希望至少尝试使用版本1.0手册而不是版本2.0手册。供应商并不总是告诉你他们购买/使用了哪个版本,所以在整理如何编程或者什么勘误表适用于你,什么不适用时,这可能是一个问题。(由于不理解这一点,Linux充满了与ARM相关的错误,勘误表通常应用错误或应用到错误的内核,指令在错误的内核上使用或在错误的时间使用,等等)

当我第一次得到cortex-m3时,我可能为它编写了一个处理程序,然后在这里和那里剪切和粘贴,而不用费心去修复/更改它

核心(CPU、逻辑)明确知道支持多少中断,并且知道向量表的完整组成。内核边缘可能有控制信号,可能会改变这些类型的东西,供应商可能会将这些信号捆绑在一起或使其可编程,等等。无论该内核的逻辑是什么,都肯定知道向量表是什么样子,这取决于程序员根据需要使代码与硬件匹配。这一切都将在该核心的TRM中描述

编辑

逻辑中的硬编码将是每个事件或中断的地址或偏移量。因此,当中断或事件发生时,它将执行从该地址读取的内存

这只是一个闪存库,你给它一个地址键,一个读选通,一些数据就会出来。除非你把它们放在上下文中,否则它们没有任何意义。如果您在地址0x10处创建一些执行加载指令的代码,或者您可以分支到该地址,提取周期读取该位置以希望找到指令,并且如果事件具有该硬编码地址且读取发生在该地址,则它希望找到处理程序的地址,则可以在该地址处导致内存周期。但这只是一个记忆。就像文件系统中的文件一样,磁盘上只有字节。如果是jpeg,那么特定字节可能是像素,如果磁盘上的文件是程序,则偏移处的字节可能是指令。它只是一个字节

这些地址直接从逻辑生成。如今,逻辑是用编程语言编写的(通常是verilog或vhdl,或产生verilog或vhdl作为输出的更高级语言)。如果你要用你最喜欢的语言写一个程序,你可能会选择硬编码一些地址

x = (unsigned int *)0x1234;
或者,您可以选择使用结构、数组或某种其他编程风格,但一旦编译,它仍然会生成一些固定地址或偏移量:

unsigned int vector_table[256];
...
handler_address = vector_table[interrupt_base+interrupt_number];
...
因此,作为一个程序员,在这个低层次上,您必须知道硬件是否和何时读取这些地址之一,以及为什么。如果您从未使用中断,因为您从未启用任何中断,那么那些通常可能保存中断处理程序地址的内存位置现在是您可以用于任何需要的内存位置。如果你在我的很多,几乎所有的例子中看到,我只需要重置向量,其余的我不用。如果我不小心执行了未对齐的访问,我可能会意外地命中未定义的指令处理程序或数据中止,但我通常不会担心将处理程序放在那里。不管怎样,我都要撞车/吊死,所以我到了那里就会解决这个问题,到了那里就过桥。所以我通常满足于cortex-m的最小值堆栈地址和重置地址:

.cpu cortex-m3
.thumb

.word   0x20002000  /* stack top address */
.word   _start      /* 1 Reset */

.thumb_func
.global _start
_start:
    bl notmain
    b hang

.thumb_func
hang:   b .
是的,我已经在内存位置放置了一条两个字的指令bl notmain,用于
.cpu cortex-m3
.thumb

.word   0x20002000  /* stack top address */
.word   _start      /* 1 Reset */

.thumb_func
.global _start
_start:
    bl notmain
    b hang

.thumb_func
hang:   b .