我正在尝试为我的MCU(tms570lc4357zwt,ARM Cortex-R5f)构建一个最小的启动代码,但是当我将其构建并将其转换为二进制格式时,所生成的 .bin 文件为0。
测试文件的结构为:
test
+--CMakeLists.txt
+--gnu.cmake
+--isr.S
+--linker.ld
我使用的工具版本为:
这是我最小的汇编代码(isr.S):
.arm
.global isr_vector
.global bootloader
.section .flash_code_isr_vector
isr_vector:
LDR pc, = bootloader /* reset. */
LDR pc, = 0x08000004 /* undefined instruction. */
LDR pc, = 0x08000008 /* system call. */
LDR pc, = 0x0800000C /* prefetch abort. */
LDR pc, = 0x08000010 /* data abort. */
LDR pc, = 0x08000014 /* reserved. */
LDR pc, = 0x08000018 /* IRQ. */
LDR pc, = 0x0800001C /* FIQ. */
.section .flash_code_bootloader
bootloader:
B .
并且我使用以下链接描述文件(linker.ld):
MEMORY
{
FLASH_TCM (rx) : ORIGIN = 0x00000000, LENGTH = 4M
RAM_TCM (rwx) : ORIGIN = 0x08000000, LENGTH = 512K
RAM_ECC (rwx) : ORIGIN = 0x08400000, LENGTH = 512K
}
ENTRY(isr_vector)
SECTIONS
{
.flash_code_isr_vector 0x00000000 :
{
KEEP(*(.flash_code_isr_vector))
} > FLASH_TCM
.flash_code_bootloader 0x00000100 :
{
*(.flash_code_bootloader)
} > FLASH_TCM
}
下面是我用来构建它的工具链文件(gnu.cmake)和cmake文件(CMakeLists.txt):
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM BOTH)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_C_COMPILER_WORKS TRUE)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
find_program(ASM_COMPILER arm-none-eabi-gcc)
find_program(C_COMPILER arm-none-eabi-gcc)
find_program(LINKER arm-none-eabi-gcc)
find_program(ARCHIVER arm-none-eabi-ar)
find_program(RANLIB arm-none-eabi-ranlib)
set(CMAKE_ASM_COMPILER ${ASM_COMPILER})
set(CMAKE_C_COMPILER ${C_COMPILER})
set(CMAKE_C_LINK_EXECUTABLE ${LINKER})
set(CMAKE_AR ${ARCHIVER})
set(CMAKE_RANLIB ${RANLIB})
add_compile_options(-mbig-endian
-march=armv7-r
-Wall
-Wextra)
add_link_options(-mbig-endian
-nostdlib
-Wall
-Wextra)
cmake_minimum_required(VERSION 3.0)
project(test VERSION 0.0.1 LANGUAGES ASM)
add_executable(isr.elf isr.S)
add_compile_options(isr.elf PRIVATE -O0 -g)
set_target_properties(isr.elf PROPERTIES
LINK_FLAGS "-T ${CMAKE_CURRENT_SOURCE_DIR}/linker.ld")
add_custom_target(isr.bin
DEPENDS isr.elf
COMMAND arm-none-eabi-objcopy -O binary isr.elf isr.bin
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
add_custom_target(isr.asm
DEPENDS isr.elf
COMMAND arm-none-eabi-objdump -D isr.elf > isr.asm
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
add_custom_target(isr.size
DEPENDS isr.elf
COMMAND arm-none-eabi-size isr.elf -A -t -x
WORKING_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
可以通过运行(在包含所有文件的文件夹中)mkdir build && cd build && cmake .. -DCMAKE_TOOLCHAIN_FILE=../gnu.cmake
现在出现问题:
当我问 .elf 的大小(调用isr.size
标签时),我得到
isr.elf :
section size addr
.flash_code_isr_vector 0x40 0x0
.flash_code_bootloader 0x4 0x100
.ARM.attributes 0x1d 0x0
Total 0x61
这似乎是合理的。现在,当我生成 .bin 文件(调用isr.bin
目标)时,生成的文件大小为0。有人知道为什么吗?因为当我反汇编 .elf 文件(调用isr.asm
目标)时,生成的汇编代码似乎是正确的:
isr.elf: file format elf32-bigarm
Disassembly of section .flash_code_isr_vector:
00000000 <isr_vector>:
0: e59ff018 ldr pc, [pc, #24] ; 20 <isr_vector+0x20>
4: e59ff018 ldr pc, [pc, #24] ; 24 <isr_vector+0x24>
8: e59ff018 ldr pc, [pc, #24] ; 28 <isr_vector+0x28>
c: e59ff018 ldr pc, [pc, #24] ; 2c <isr_vector+0x2c>
10: e59ff018 ldr pc, [pc, #24] ; 30 <isr_vector+0x30>
14: e59ff018 ldr pc, [pc, #24] ; 34 <isr_vector+0x34>
18: e59ff018 ldr pc, [pc, #24] ; 38 <isr_vector+0x38>
1c: e59ff018 ldr pc, [pc, #24] ; 3c <isr_vector+0x3c>
20: 00000100 andeq r0, r0, r0, lsl #2
24: 08000004 stmdaeq r0, {r2}
28: 08000008 stmdaeq r0, {r3}
2c: 0800000c stmdaeq r0, {r2, r3}
30: 08000010 stmdaeq r0, {r4}
34: 08000014 stmdaeq r0, {r2, r4}
38: 08000018 stmdaeq r0, {r3, r4}
3c: 0800001c stmdaeq r0, {r2, r3, r4}
Disassembly of section .flash_code_bootloader:
00000100 <bootloader>:
100: eafffffe b 100 <bootloader>
Disassembly of section .ARM.attributes:
00000000 <.ARM.attributes>:
0: 41000000 mrsmi r0, (UNDEF: 0)
4: 1c616561 cfstr64ne mvdx6, [r1], #-388 ; 0xfffffe7c
8: 62690001 rsbvs r0, r9, #1, 0
c: 00000012 andeq r0, r0, r2, lsl r0
10: 05372d52 ldreq r2, [r7, #-3410]! ; 0xfffff2ae
14: 00060a07 andeq r0, r6, r7, lsl #20
18: 52080109 andpl r0, r8, #1073741826 ; 0x40000002
1c: Address 0x000000000000001c is out of bounds.
谢谢。
答案 0 :(得分:4)
在汇编代码中,您没有将节标记为可分配的,因此在生成二进制文件时不会输出这些节。如果您已经用
转储了头文件arm-none-eabi-objdump -x isr.elf
输出看起来类似于:
isr.elf: file format elf32-bigarm isr.elf architecture: arm, flags 0x00000012: EXEC_P, HAS_SYMS start address 0x00000000 private flags = 5000200: [Version5 EABI] [soft-float ABI] Sections: Idx Name Size VMA LMA File off Algn 0 .flash_code_isr_vector 00000040 00000000 00000000 00000034 2**2 CONTENTS, READONLY 1 .flash_code_bootloadery 00000004 00000000 00000000 00000074 2**2 CONTENTS, READONLY 2 .ARM.attributes 0000001d 00000000 00000000 00000078 2**0 CONTENTS, READONLY
标志仅为CONTENTS
和READONLY
。它缺少ALLOC
(可分配)标志。由于您的部分似乎也是代码,因此我考虑通过添加isr.S
属性,例如:
"ax"
.arm
.global isr_vector
.global bootloader
.section .flash_code_isr_vector,"ax",%progbits
isr_vector:
LDR pc, = bootloader /* reset. */
LDR pc, = 0x08000004 /* undefined instruction. */
LDR pc, = 0x08000008 /* system call. */
LDR pc, = 0x0800000C /* prefetch abort. */
LDR pc, = 0x08000010 /* data abort. */
LDR pc, = 0x08000014 /* reserved. */
LDR pc, = 0x08000018 /* IRQ. */
LDR pc, = 0x0800001C /* FIQ. */
.section .flash_code_bootloader,"ax",%progbits
bootloader:
B .
如果您重建代码,则bin
文件应为非零值,并且ELF标头现在应类似于:
Sections: Idx Name Size VMA LMA File off Algn 0 .flash_code_isr_vector 00000040 00000000 00000000 00010000 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 1 .flash_code_bootloader 00000004 00000100 00000100 00010100 2**2 CONTENTS, ALLOC, LOAD, READONLY, CODE 2 .ARM.attributes 0000001d 00000000 00000000 00010104 2**0 CONTENTS, READONLY
.section
伪指令是documented for ELF,如下所示:
ELF版本
这是ELF节堆栈操作之一 指令。其他是.subsection(请参阅SubSection),.pushsection (请参阅PushSection)、. popsection(请参阅PopSection)和.previous(请参阅 上一个)。
对于ELF目标,.section指令的用法如下:
.section name [, "flags"[, @type[,flag_specific_arguments]]]
[snip]
可分配的部分
d部分是GNU_MBIND部分
e部分从可执行文件和共享库中排除。
w部分可写
x部分是可执行的
M部分是可合并的
S部分包含零个终止的字符串
G部门是部门组的成员
T部分用于线程本地存储
?该部分是先前当前部分的组的成员,如果 任何
[snip]
可选的type参数可以包含以下常量之一:
@progbits部分包含数据
@nobits部分不包含数据(即,该部分仅占用 空格)
[snip]
关于目标的注释,其中@字符是注释的开头(例如 然后使用另一个字符代替。例如ARM端口 使用%字符。