thumb_func 指令未被考虑

问题描述 投票:0回答:1

我正在尝试使用裸程序集和链接器脚本为 STM32F103 组装一个小型应用程序。

这是我想出的:

链接器.ld:

MEMORY {
    FLASH : ORIGIN = 0x08000000, LENGTH = 64K
    SRAM : ORIGIN = 0x20000000, LENGTH = 20K
}

sp_initial_value = ORIGIN(SRAM) + LENGTH(SRAM);
vector_table_size = 0x130;

SECTIONS {
    vector_table ORIGIN(FLASH) : {
        LONG(sp_initial_value);
        LONG(reset_exception_handler);
    } > FLASH

    .text ADDR(vector_table) + vector_table_size :
    {
    } > FLASH
}

眨眼:

.cpu cortex-m3
.syntax unified
.thumb

.text

.global reset_exception_handler
.thumb_func
.type reset_exception_handler, %function
reset_exception_handler:

add r0, 1
b reset_exception_handler

生成文件:

blink-asm.bin: blink-asm.elf
    arm-none-eabi-objcopy -O binary blink-asm.elf blink-asm.bin

flash: blink-asm.bin
    st-flash write blink-asm.bin 0x08000000

blink-asm.elf: blink.o
    arm-none-eabi-ld -T linker.ld -o blink-asm.elf blink.o

blink.o: blink.s
    arm-none-eabi-as -o blink.o blink.s

clean:
    rm -f blink.o blink-asm.elf blink-asm.bin

这是blink-asm.bin 的十六进制:

hexdump -C blink-asm.bin 
00000000  00 50 00 20 30 01 00 08  00 00 00 00 00 00 00 00  |.P. 0...........|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000130  00 f1 01 00 ff f7 fc bf                           |........|

因此,将在 0x08000000 加载的第一个值是 20005000,这是 20k SRAM 的末尾。

第二个值是复位异常处理程序地址,即08000130。但是对于ARM,它必须用较低位进行编码,因此它实际上必须是08000131。如果我将当前应用程序代码加载到MCU,它将生成硬故障而不是运行reset_exception_handler。

当然,我可以在链接器脚本中编写

LONG(reset_exception_handler + 1);
,它就会按预期工作。

但是我实际上期望指令

.thumb_func
修改符号
reset_exception_handler

编写链接器脚本和汇编文件以便生成正确地址的正确方法是什么?

assembly linker arm stm32
1个回答
0
投票

想一或一不加一,如果你加一,那么当你正确使用工具时,加一现在会破坏它,或一你可以生存(稍后修复)。

如你的问题中所写(据我阅读)

MEMORY {
    FLASH : ORIGIN = 0x08000000, LENGTH = 64K
    SRAM : ORIGIN = 0x20000000, LENGTH = 20K
}

sp_initial_value = ORIGIN(SRAM) + LENGTH(SRAM);
vector_table_size = 0x130;

SECTIONS {
    vector_table ORIGIN(FLASH) : {
        LONG(sp_initial_value);
        LONG(reset_exception_handler);
    } > FLASH

    .text ADDR(vector_table) + vector_table_size :
    {
    } > FLASH
}

.cpu cortex-m3
.syntax unified
.thumb

.text

.global reset_exception_handler
.thumb_func
.type reset_exception_handler, %function
reset_exception_handler:

add r0, 1
b reset_exception_handler


Disassembly of section vector_table:

08000000 <sp_initial_value-0x18005000>:
 8000000:   20005000    andcs   r5, r0, r0
 8000004:   08000130    stmdaeq r0, {r4, r5, r8}

Disassembly of section .text:

08000130 <reset_exception_handler>:
 8000130:   f100 0001   add.w   r0, r0, #1
 8000134:   f7ff bffc   b.w 8000130 <reset_exception_handler>

没有理由为向量表提供单独的部分。尽可能避免链接器脚本,它不是解决问题的地方。

MEMORY {
    FLASH : ORIGIN = 0x08000000, LENGTH = 64K
    SRAM : ORIGIN = 0x20000000, LENGTH = 20K
}
sp_initial_value = ORIGIN(SRAM) + LENGTH(SRAM);
SECTIONS {
    .text   : { *(.text)   } > FLASH
    .rodata : { *(.rodata) } > FLASH
    .bss    : { *(.bss)    } > SRAM
}


.cpu cortex-m3
.syntax unified
.thumb
.text

.word sp_initial_value
.word reset_exception_handler

.thumb_func
reset_exception_handler:
    b .



08000000 <reset_exception_handler-0x8>:
 8000000:   20005000    andcs   r5, r0, r0
 8000004:   08000009    stmdaeq r0, {r0, r3}

08000008 <reset_exception_handler>:
 8000008:   e7fe        b.n 8000008 <reset_exception_handler>

更简单、更干净、更美好。并正确。

现在你也可以像你看到的 gcc 那样:

.cpu cortex-m3
.syntax unified
.thumb
.text

.word sp_initial_value
.word reset_exception_handler

.thumb_func
.type reset_exception_handler,%function
reset_exception_handler:
    b .

这只是多余的,选择一个。

.cpu cortex-m3
.syntax unified
.thumb
.text

.word sp_initial_value
.word reset_exception_handler

.type reset_exception_handler,%function
reset_exception_handler:
    b .


08000000 <reset_exception_handler-0x8>:
 8000000:   20005000    andcs   r5, r0, r0
 8000004:   08000009    stmdaeq r0, {r0, r3}

08000008 <reset_exception_handler>:
 8000008:   e7fe        b.n 8000008 <reset_exception_handler>

但你必须选择一个

.cpu cortex-m3
.syntax unified
.thumb
.text

.word sp_initial_value
.word reset_exception_handler

reset_exception_handler:
    b .


08000000 <reset_exception_handler-0x8>:
 8000000:   20005000    andcs   r5, r0, r0
 8000004:   08000008    stmdaeq r0, {r3}

08000008 <reset_exception_handler>:
 8000008:   e7fe        b.n 8000008 <reset_exception_handler>

.type..function 与位置无关,并且在arm 和thumb 模式下使用相同的语法,没有.arm_func。因此,如果您只是一个拇指/皮质-M 程序员和/或有点懒(我就是这种情况),那么 .thumb_func 很好,因为您可以剪切并粘贴它或键入它,而不必键入函数名称。但仅适用于拇指。拥有 .type 习惯会更好,因为您可以为所有函数执行此操作,但需要多做一点工作。

.cpu cortex-m3
.syntax unified
.thumb
.text

.type two,%function

.word sp_initial_value
.word reset_exception_handler
.word one
.word two

.thumb_func

one:
    b .
two: 
    b .
reset_exception_handler:
    b .

08000000 <one-0x10>:
 8000000:   20005000    andcs   r5, r0, r0
 8000004:   08000014    stmdaeq r0, {r2, r4}
 8000008:   08000011    stmdaeq r0, {r0, r4}
 800000c:   08000013    stmdaeq r0, {r0, r1, r4}

08000010 <one>:
 8000010:   e7fe        b.n 8000010 <one>

08000012 <two>:
 8000012:   e7fe        b.n 8000012 <two>

08000014 <reset_exception_handler>:
 8000014:   e7fe        b.n 8000014 <reset_exception_handler>

正如评论中基本回答的那样,没有理由假设链接器脚本知道拇指内容。 (链接器当然知道拇指)。另外,正如该评论中的回答,只需使用汇编语言。

而且正如所指出的,如果您没有放置至少最少数量的向量,那么如果您遇到其他问题,例如未对齐或未定义的指令等,那么您将出现故障并崩溃(理想情况下)或降落在某个奇怪的地方(重新)运行代码的一部分(不幸的是)。

除非您完成工作,否则中断本身不会发挥作用,我认为芯片供应商决定特定芯片/核心使用多少个中断(以及向量),最多可达该核心的最大值(不同的核心有不同的最大值)。

© www.soinside.com 2019 - 2024. All rights reserved.