keil stm32,使用汇编,散文件和c。如何将 C 代码入口点导出到程序集?
Keil stm32, using assembly, scatter file and c. How to export c code entry point to assembly?
为了结合.c和程序集,我想传递我的.c代码的起始地址,并将微控制器编程到知道它的程序从那个地址开始。由于我在汇编中写我的启动文件,我需要将.c代码起始地址传递给汇编,然后将此地址写入单片机的特定内存区域(这样微控制器就可以在RESET后开始在这个地址上执行)
尝试在 Keil 中为 stm32f103 创建一个具有以下结构的项目:
一些 .c 文件,例如 main.c(用于程序的主要部分)。
汇编语言的启动文件。它获取一些 .c 文件中编写的函数的入口地址,将传递给 Reset_Handler
分散文件,这样写的:
LR_IROM1 0x08000000 0x00010000 { ; load region size_region
ER_IROM1 0x08000000 0x00010000 { ; load address = execution address
*.o (RESET, +First) ; RESET is code section with I.V.T.
* (InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 0x20000000 0x00005000 { ; RW data
.ANY (+RW +ZI)
}
}
问题是将入口点传递给 .c 函数。 Reset_Handler,它需要 __main 传递的 .c 入口点(起始地址),如下所示:
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
LDR R0, =__main
BX R0
ENDP
关于入口点 __main,作为一个组件的答案 question 写成:
__main() is the compiler supplied entry point for your C code. It is not the main() function you write, but performs initialisation for the
standard library, static data, the heap before calling your `main()'
function.
那么,如何在我的程序集文件中获取这个入口点?
编辑>> 如果有人对 KEIL 的解决方案感兴趣,就在这里,就是这么简单!
简单组装startup.s文件:
AREA STACK, NOINIT, READWRITE
SPACE 0x400
Stack_top
AREA RESET, DATA, READONLY
dcd Stack_top
dcd Reset_Handler
EXPORT _InitMC
IMPORT notmain
AREA PROGRAM, CODE, READONLY
Reset_Handler PROC
bl notmain
ENDP
_InitMC PROC ;start of the assembly procedure
Loop
b Loop ;infinite loop
ENDP
END
简单的c文件:
extern int _InitMC();
int notmain(void) {
_InitMC();
return 0;
}
连接器与上述相同。
项目构建成功。
例如使用 gnu 工具链:
Bootstrap:
.cpu cortex-m0
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word loop
.word loop
.word loop
.thumb_func
reset:
bl notmain
b loop
.thumb_func
loop: b .
.align
.thumb_func
.globl fun
fun:
bx lr
.end
C 入口点(函数名称不相关,有时使用 main() 会增加垃圾,取决于 compiler/toolchain)
void fun ( unsigned int );
int notmain ( void )
{
unsigned int ra;
for(ra=0;ra<1000;ra++) fun(ra);
return(0);
}
链接描述文件
MEMORY
{
rom : ORIGIN = 0x08000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
}
建造
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -mcpu=cortex-m0 -march=armv6-m -c so.c -o so.thumb.o
arm-none-eabi-ld -o so.thumb.elf -T flash.ld flash.o so.thumb.o
arm-none-eabi-objdump -D so.thumb.elf > so.thumb.list
arm-none-eabi-objcopy so.thumb.elf so.thumb.bin -O binary
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -mcpu=cortex-m3 -march=armv7-m -c so.c -o so.thumb2.o
arm-none-eabi-ld -o so.thumb2.elf -T flash.ld flash.o so.thumb2.o
arm-none-eabi-objdump -D so.thumb2.elf > so.thumb2.list
arm-none-eabi-objcopy so.thumb2.elf so.thumb2.bin -O binary
结果(所有拇指版本)
Disassembly of section .text:
08000000 <_start>:
8000000: 20001000
8000004: 08000015
8000008: 0800001b
800000c: 0800001b
8000010: 0800001b
08000014 <reset>:
8000014: f000 f804 bl 8000020 <notmain>
8000018: e7ff b.n 800001a <loop>
0800001a <loop>:
800001a: e7fe b.n 800001a <loop>
0800001c <fun>:
800001c: 4770 bx lr
800001e: 46c0 nop ; (mov r8, r8)
08000020 <notmain>:
8000020: b570 push {r4, r5, r6, lr}
8000022: 25fa movs r5, #250 ; 0xfa
8000024: 2400 movs r4, #0
8000026: 00ad lsls r5, r5, #2
8000028: 0020 movs r0, r4
800002a: 3401 adds r4, #1
800002c: f7ff fff6 bl 800001c <fun>
8000030: 42ac cmp r4, r5
8000032: d1f9 bne.n 8000028 <notmain+0x8>
8000034: 2000 movs r0, #0
8000036: bd70 pop {r4, r5, r6, pc}
当然这必须用一些工具放在闪存的正确位置。
向量table被逻辑映射到stm32家族中的0x00000000。
08000000 <_start>:
8000000: 20001000
8000004: 08000015 <---- reset ORR 1
并且在这个最小代码中,重置处理程序调用 C 代码,C 代码乱七八糟 returns。从技术上讲,这是一个适用于大多数 stm32 的全功能程序(对于 ram 较少的那些,将堆栈 init 更改为较小的值,比如 0x20000400,它应该可以在任何地方使用 -mthumb 本身(armv4t)或添加 cortex-m0。好吧,不是 armv8ms他们在技术上不能支持所有的 armv6m,但我所知道的那个领域支持。
我没有 Kiel,所以不知道如何翻译成它,但它应该不会太复杂,只是语法。
为了结合.c和程序集,我想传递我的.c代码的起始地址,并将微控制器编程到知道它的程序从那个地址开始。由于我在汇编中写我的启动文件,我需要将.c代码起始地址传递给汇编,然后将此地址写入单片机的特定内存区域(这样微控制器就可以在RESET后开始在这个地址上执行)
尝试在 Keil 中为 stm32f103 创建一个具有以下结构的项目:
一些 .c 文件,例如 main.c(用于程序的主要部分)。
汇编语言的启动文件。它获取一些 .c 文件中编写的函数的入口地址,将传递给 Reset_Handler
分散文件,这样写的:
LR_IROM1 0x08000000 0x00010000 { ; load region size_region
ER_IROM1 0x08000000 0x00010000 { ; load address = execution address
*.o (RESET, +First) ; RESET is code section with I.V.T.
* (InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 0x20000000 0x00005000 { ; RW data
.ANY (+RW +ZI)
}
}
问题是将入口点传递给 .c 函数。 Reset_Handler,它需要 __main 传递的 .c 入口点(起始地址),如下所示:
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
LDR R0, =__main
BX R0
ENDP
关于入口点 __main,作为一个组件的答案 question 写成:
__main() is the compiler supplied entry point for your C code. It is not the main() function you write, but performs initialisation for the standard library, static data, the heap before calling your `main()' function.
那么,如何在我的程序集文件中获取这个入口点?
编辑>> 如果有人对 KEIL 的解决方案感兴趣,就在这里,就是这么简单!
简单组装startup.s文件:
AREA STACK, NOINIT, READWRITE
SPACE 0x400
Stack_top
AREA RESET, DATA, READONLY
dcd Stack_top
dcd Reset_Handler
EXPORT _InitMC
IMPORT notmain
AREA PROGRAM, CODE, READONLY
Reset_Handler PROC
bl notmain
ENDP
_InitMC PROC ;start of the assembly procedure
Loop
b Loop ;infinite loop
ENDP
END
简单的c文件:
extern int _InitMC();
int notmain(void) {
_InitMC();
return 0;
}
连接器与上述相同。 项目构建成功。
例如使用 gnu 工具链:
Bootstrap:
.cpu cortex-m0
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word loop
.word loop
.word loop
.thumb_func
reset:
bl notmain
b loop
.thumb_func
loop: b .
.align
.thumb_func
.globl fun
fun:
bx lr
.end
C 入口点(函数名称不相关,有时使用 main() 会增加垃圾,取决于 compiler/toolchain)
void fun ( unsigned int );
int notmain ( void )
{
unsigned int ra;
for(ra=0;ra<1000;ra++) fun(ra);
return(0);
}
链接描述文件
MEMORY
{
rom : ORIGIN = 0x08000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
}
建造
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -mcpu=cortex-m0 -march=armv6-m -c so.c -o so.thumb.o
arm-none-eabi-ld -o so.thumb.elf -T flash.ld flash.o so.thumb.o
arm-none-eabi-objdump -D so.thumb.elf > so.thumb.list
arm-none-eabi-objcopy so.thumb.elf so.thumb.bin -O binary
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -mcpu=cortex-m3 -march=armv7-m -c so.c -o so.thumb2.o
arm-none-eabi-ld -o so.thumb2.elf -T flash.ld flash.o so.thumb2.o
arm-none-eabi-objdump -D so.thumb2.elf > so.thumb2.list
arm-none-eabi-objcopy so.thumb2.elf so.thumb2.bin -O binary
结果(所有拇指版本)
Disassembly of section .text:
08000000 <_start>:
8000000: 20001000
8000004: 08000015
8000008: 0800001b
800000c: 0800001b
8000010: 0800001b
08000014 <reset>:
8000014: f000 f804 bl 8000020 <notmain>
8000018: e7ff b.n 800001a <loop>
0800001a <loop>:
800001a: e7fe b.n 800001a <loop>
0800001c <fun>:
800001c: 4770 bx lr
800001e: 46c0 nop ; (mov r8, r8)
08000020 <notmain>:
8000020: b570 push {r4, r5, r6, lr}
8000022: 25fa movs r5, #250 ; 0xfa
8000024: 2400 movs r4, #0
8000026: 00ad lsls r5, r5, #2
8000028: 0020 movs r0, r4
800002a: 3401 adds r4, #1
800002c: f7ff fff6 bl 800001c <fun>
8000030: 42ac cmp r4, r5
8000032: d1f9 bne.n 8000028 <notmain+0x8>
8000034: 2000 movs r0, #0
8000036: bd70 pop {r4, r5, r6, pc}
当然这必须用一些工具放在闪存的正确位置。
向量table被逻辑映射到stm32家族中的0x00000000。
08000000 <_start>:
8000000: 20001000
8000004: 08000015 <---- reset ORR 1
并且在这个最小代码中,重置处理程序调用 C 代码,C 代码乱七八糟 returns。从技术上讲,这是一个适用于大多数 stm32 的全功能程序(对于 ram 较少的那些,将堆栈 init 更改为较小的值,比如 0x20000400,它应该可以在任何地方使用 -mthumb 本身(armv4t)或添加 cortex-m0。好吧,不是 armv8ms他们在技术上不能支持所有的 armv6m,但我所知道的那个领域支持。
我没有 Kiel,所以不知道如何翻译成它,但它应该不会太复杂,只是语法。