assembly 我应该在固件中填充多少异常向量?

pod7payv  于 2022-12-13  发布在  其他
关注(0)|答案(2)|浏览(113)

我正在使用STM32F103C8T6 Blue Pill开发板与ARM进行交互。根据其Programming Manual(第2.3.4节向量表),总共有83个异常向量要设置。但是,this tutorial只填充前6个,this tutorial只填充前10个。奇怪的是,我可以验证这两个固件是否按预期执行,尽管缺少许多异常处理程序。
为了澄清一下,下面就是我所指的(link to original file)部分,正如您所看到的,只有前几个单词被分配了一个处理程序,后面的所有空间都用来存放.text部分。

.section .isr_vector
.align  2
.global _isr_vector
_isr_vector:
    .long   __StackTop /* we will need this later */
    .long   Reset_Handler
    .long   Default_Handler
    .long   Default_Handler
    .long   Default_Handler
    .long   Default_Handler
    .long   Default_Handler
    .long   0
    .long   0
    .long   0
    .long   0
    .long   Default_Handler
    .long   Default_Handler
    .long   0
    .long   Default_Handler
    .long   Default_Handler

这让我感到困惑:我需要填充的异常处理程序的最少数量是多少?2在我的用例中(这只不过是一个玩具项目),没有异常可以被排除,所以我可以只设置重置处理程序吗?
另外,《编程手册》规定“每个向量的最低有效位必须为1,表示异常处理程序是Thumb代码。”但是,上面的代码显然没有遵循这个约定,那么它如何在 Boot 时正确地调用重置处理程序呢?

368yc8dk

368yc8dk1#

理论上,您只能设置两个。初始堆栈和复位处理程序。如果您不调用任何中断(并且您的程序没有在硬故障中结束),则不必设置任何中断。

pcww981p

pcww981p2#

.thumb
.global _start
_start:
.word 0x20001000
.word one
.word two
.align
.thumb_func
one:
    b .
two:
    b .

arm-none-eabi-as so.s -o so.o
arm-none-eabi-ld -Ttext=0x08000000 so.o -o so.elf
arm-none-eabi-objdump -D so.elf

so.elf:     file format elf32-littlearm

Disassembly of section .text:

08000000 <_start>:
 8000000:   20001000    andcs   r1, r0, r0
 8000004:   0800000d    stmdaeq r0, {r0, r2, r3}
 8000008:   0800000e    stmdaeq r0, {r1, r2, r3}
    
0800000c <one>:
 800000c:   e7fe        b.n 800000c <one>

0800000e <two>:
 800000e:   e7fe        b.n 800000e <two>

首先,_start不是必需的,你会得到一个警告,把它放在那里更容易。
你需要把标签声明为一个函数在gnu汇编器中有几种方法可以做到这一点。.thumb_func很简单,它不一定是你可以在.thumb_func和标签之间有其他东西的那一行,但是下一个标签被标记为一个函数。
您将看到编译器的输出类似于以下内容(使用-save-temps或-S查看编译器输出),还有另一种方法可以在gas中声明函数,对于全尺寸的arm,您必须使用另一种方法。
你可以看到,当正确声明时,工具会照顾你,当你不正确声明时,你会在向量表中得到错误的地址,这将不起作用。
正如所回答的,最小值是两个条目,因为您需要在偏移/地址4处有一些内容。请注意,在这些STM32平台上启动时,0x 08000000Map到0x 0000000。如果您不需要任何其他值,则最小值是复位矢量。但是在一个偏移量处,你需要填充前四个字节。不妨在那里放一个堆栈指针初始值,稍后用同样的代码设置它。
向量表并没有什么神奇的地方,它只是一个地址空间,你可以进行提取和数据周期。
2是最小值,但如果最终出现对齐错误或其他错误,则会尝试在那里找到一个向量,如果是偶数,则会出现问题;如果是奇数,则会尝试从该地址执行(lsbit被从pc中剥离出来,里面没有奇数,它只是一种指示拇指对手臂的机制)。因此,虽然技术上是一个向量,重置是最小的,它可能是一个好主意,以涵盖前16(15)以防万一。

.thumb
.global _start
_start:

.word 0x20001000
.word reset
.word loop
.word loop

.word loop
.word loop
.word loop
.word loop

.word loop
.word loop
.word loop
.word loop

.word loop
.word loop
.word loop
.word loop

.thumb_func
reset:
    b .

.thumb_func
loop:
    b .

虽然您可以混合代码和向量,但如果您最终将中断处理程序用于外设,那么您可能不希望在异常之间和中断处理程序向量所在的位置混合代码。如果您真的非常需要闪存中的代码空间,那么从技术上讲,您可以...
至少P__J__的答案就是答案。我添加这个答案是为了涵盖lsbit问题。

相关问题