如何通过LM3S811的UART发送数据
How to send data through UART of LM3S811
我正在学习裸机编程,我尝试通过Qemu中的LM3S811的UART发送数据。但它没有在终端中打印任何字符。我提供了 .c 文件和链接描述文件。如果有任何链接可以帮助您从头开始学习裸机编程。谢谢
.c 文件
char stack[1024];
extern char etext;
extern char sdata;
extern char edata;
extern char sbss;
extern char ebss;
static char *bssp = (char *)0xDEADBEEF;
unsigned int *uart = (unsigned int *)0x4000C000;
void start()
{
char *from, *to;
from = &etext;
to = &sdata;
while (to != &edata) {
*to++ = *from++;
}
bssp = &sbss;
while (bssp != &ebss) {
*bssp++ = 0;
}
main();
while(1);
}
__attribute__((section(".vectors")))
void *vectors[] = {
stack + sizeof(stack),
start,
};
int main()
{
char *ptr = "Have a great day";
while (*ptr != '[=10=]') {
*uart = *ptr;
ptr++;
}
return 0;
}
链接描述文件:
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00010000
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00002000
}
SECTIONS {
.text : {
*(.vectors);
*(.text);
etext = .;
} > FLASH
.data : {
sdata = .;
*(.data);
edata = .;
} > SRAM AT >FLASH
.bss : {
sbss = .;
*(.bss);
ebss = .;
} > SRAM
.rodata : {
*(.rodata);
} > FLASH
}
所以从这个开始,然后去改变它
flash.s
.cpu cortex-m0
.thumb
.thumb_func
.global _start
_start:
.word 0x20001000
.word reset
.thumb_func
reset:
bl notmain
b hang
.thumb_func
hang: b .
.thumb_func
.globl PUT32
PUT32:
str r1,[r0]
bx lr
notmain.c
void PUT32 ( unsigned int, unsigned int );
#define UART_DR 0x4000C000
int notmain ( void )
{
char *ptr = "Have a great day";
while (*ptr != '[=11=]') {
PUT32(UART_DR,*ptr);
ptr++;
}
return(0);
}
flash.ld
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
}
建造
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m0 flash.s -o flash.o
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=cortex-m0 -mthumb -c notmain.c -o notmain.o
arm-none-eabi-ld -nostdlib -nostartfiles -T flash.ld flash.o notmain.o -o notmain.elf
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy -O binary notmain.elf notmain.bin
检查
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000009 andeq r0, r0, r9
00000008 <reset>:
8: f000 f804 bl 14 <notmain>
c: e7ff b.n e <hang>
所以矢量 table 看起来不错
18: 4c04 ldr r4, [pc, #16] ; (2c <notmain+0x18>)
1a: 4805 ldr r0, [pc, #20] ; (30 <notmain+0x1c>)
1c: 3401 adds r4, #1
1e: f7ff fff7 bl 10 <PUT32>
22: 7821 ldrb r1, [r4, #0]
24: 2900 cmp r1, #0
...
2c: 00000034 andeq r0, r0, r4, lsr r0
...
Disassembly of section .rodata:
00000034 <.rodata>:
34: 65766148 ldrbvs r6, [r6, #-328]! ; 0xfffffeb8
38: 67206120 strvs r6, [r0, -r0, lsr #2]!
3c: 74616572 strbtvc r6, [r1], #-1394 ; 0xfffffa8e
40: 79616420 stmdbvc r1!, {r5, r10, sp, lr}^
...
字符串似乎在 rodata 中,因此看起来也不错。
qemu-system-arm -M lm3s811evb -m 1M -nographic -kernel notmain.bin
Have a great day
ctrl-a 然后 x 退出 qemu
flash.s
.thumb
.global _start
_start:
.word 0x20001000
.word notmain
notmain.c
#define UART_DR (*((volatile unsigned int *)0x4000C000))
void notmain ( void )
{
char *ptr = "Have a great day";
while (*ptr != '[=18=]') {
UART_DR=*ptr;
ptr++;
}
while(1) continue;
}
flash.ld
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
}
建造
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m3 flash.s -o flash.o
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=cortex-m3 -mthumb -c notmain.c -o notmain.o
arm-none-eabi-ld -nostdlib -nostartfiles -T flash.ld flash.o notmain.o -o notmain.elf
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy -O binary notmain.elf notmain.bin
检查
Disassembly of section .text:
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000009 andeq r0, r0, r9
00000008 <notmain>:
向量table很好
00000008 <notmain>:
8: 2348 movs r3, #72 ; 0x48
a: 4a04 ldr r2, [pc, #16] ; (1c <notmain+0x14>)
c: 4904 ldr r1, [pc, #16] ; (20 <notmain+0x18>)
e: 600b str r3, [r1, #0]
10: f812 3f01 ldrb.w r3, [r2, #1]!
14: 2b00 cmp r3, #0
16: d1fa bne.n e <notmain+0x6>
18: e7fe b.n 18 <notmain+0x10>
1a: bf00 nop
1c: 00000024 andeq r0, r0, r4, lsr #32
20: 4000c000 andmi r12, r0, r0
Disassembly of section .rodata:
00000024 <.rodata>:
24: 65766148 ldrbvs r6, [r6, #-328]! ; 0xfffffeb8
28: 67206120 strvs r6, [r0, -r0, lsr #2]!
2c: 74616572 strbtvc r6, [r1], #-1394 ; 0xfffffa8e
30: 79616420 stmdbvc r1!, {r5, r10, sp, lr}^
...
这是一个有趣的解决方案,但看起来不错,字符串在 flash 中,等等。
qemu-system-arm -M lm3s811evb -m 1M -nographic -kernel notmain.bin
Have a great day
您需要检查构建的输出。
如果我建造它
00000000 <vectors>:
0: 20000408 andcs r0, r0, r8, lsl #8
4: 00000009 andeq r0, r0, r9
00000008 <start>:
非常奇怪的 sp 初始值,但无论如何,它应该可以工作是吗?
Disassembly of section .text:
00000000 <vectors>:
0: 20000408 andcs r0, r0, r8, lsl #8
4: 00000009 andeq r0, r0, r9
00000008 <start>:
8: b508 push {r3, lr}
a: 480d ldr r0, [pc, #52] ; (40 <start+0x38>) 20000008
c: 4b0d ldr r3, [pc, #52] ; (44 <start+0x3c>) 20000000
e: 4283 cmp r3, r0
10: d006 beq.n 20 <start+0x18>
12: 4a0d ldr r2, [pc, #52] ; (48 <start+0x40>) 00000058
14: f812 1b01 ldrb.w r1, [r2], #1
18: f803 1b01 strb.w r1, [r3], #1
1c: 4298 cmp r0, r3
1e: d1f9 bne.n 14 <start+0xc>
从 0x0x0058 复制 8 个字节到 0x20000000
20: 4b0a ldr r3, [pc, #40] ; (4c <start+0x44>) 20000008
22: 4a0b ldr r2, [pc, #44] ; (50 <start+0x48>) 20000408
24: 480b ldr r0, [pc, #44] ; (54 <start+0x4c>) 20000000
26: 4293 cmp r3, r2
28: bf18 it ne
2a: 2100 movne r1, #0
2c: 6043 str r3, [r0, #4]
2e: d004 beq.n 3a <start+0x32>
30: f803 1b01 strb.w r1, [r3], #1
34: 4293 cmp r3, r2
36: d1fb bne.n 30 <start+0x28>
38: 6043 str r3, [r0, #4]
0 从 0x20000008 到 0x20000408 清除堆栈,幸好局部变量不在堆栈上,而且你没有从这个函数中 returning。
3a: f000 f80d bl 58 <etext>
3e: e7fe b.n 3e <start+0x36>
40: 20000008 andcs r0, r0, r8
44: 20000000 andcs r0, r0, r0
48: 00000058 andeq r0, r0, r8, asr r0
4c: 20000008 andcs r0, r0, r8
50: 20000408 andcs r0, r0, r8, lsl #8
54: 20000000 andcs r0, r0, r0
Disassembly of section .data:
20000000 <uart>:
20000000: 4000c000 andmi r12, r0, r0
20000004 <bssp>:
20000004: deadbeef cdple 14, 10, cr11, cr13, cr15, {7}
Disassembly of section .bss:
20000008 <stack>:
...
hexdump -C notmain.bin
00000000 08 04 00 20 09 00 00 00 08 b5 0d 48 0d 4b 83 42 |... .......H.K.B|
00000010 06 d0 0d 4a 12 f8 01 1b 03 f8 01 1b 98 42 f9 d1 |...J.........B..|
00000020 0a 4b 0b 4a 0b 48 93 42 18 bf 00 21 43 60 04 d0 |.K.J.H.B...!C`..|
00000030 03 f8 01 1b 93 42 fb d1 43 60 00 f0 0d f8 fe e7 |.....B..C`......|
00000040 08 00 00 20 00 00 00 20 58 00 00 00 08 00 00 20 |... ... X...... |
00000050 08 04 00 20 00 00 00 20 61 20 05 4a 05 4b 11 68 |... ... a .J.K.h|
00000060 02 46 13 f8 01 0f 00 28 fa d1 0a 60 70 47 00 bf |.F.....(...`pG..|
00000070 00 00 00 20 81 00 00 00 00 c0 00 40 ef be ad de |... .......@....|
00000080 48 61 76 65 20 61 20 67 72 65 61 74 20 64 61 79 |Have a great day|
00000090 00 |.|
00000091
.data 肯定不在闪存中的 0x58 处,幸好你没有使用 .data
根据设计,您可能希望 .data 紧跟在 .text 之后,但最好只询问链接器确切的位置。此外,事情的排列方式也可能使 etext 不是下一节的开始。
如果我们试试这个
MEMORY
{
FLASH : ORIGIN = 0x00000000, LENGTH = 0x1000
SRAM : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > FLASH
.rodata : { *(.rodata*) } > FLASH
__data_rom_start__ = .;
.data : {
__data_start__ = .;
*(.data*)
} > SRAM AT > FLASH
__data_end__ = .;
__data_size__ = __data_end__ - __data_start__;
.bss : {
__bss_start__ = .;
*(.bss*)
} > SRAM
__bss_end__ = .;
__bss_size__ = __bss_end__ - __bss_start__;
}
.thumb
.global _start
_start:
.word 0x20001000
.word main
.word __data_rom_start__
.word __data_start__
.word __data_end__
.word __data_size__
.word __bss_start__
.word __bss_end__
.word __bss_size__
移除启动功能
Disassembly of section .text:
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000025 andeq r0, r0, r5, lsr #32
8: 00000055 andeq r0, r0, r5, asr r0
c: 20000000 andcs r0, r0, r0
10: 20000004 andcs r0, r0, r4
14: 00000004 andeq r0, r0, r4
18: 20000004 andcs r0, r0, r4
1c: 20000404 andcs r0, r0, r4, lsl #8
20: 00000400 andeq r0, r0, r0, lsl #8
Disassembly of section .text:
00000000 <_start>:
0: 20001000
4: 00000025
8: 00000055 __data_rom_start__
c: 20000000 __data_start__
10: 20000004 __data_end__
14: 00000004 __data_size__
18: 20000004 __bss_start__
1c: 20000404 __bss_end__
20: 00000400 __bss_size__
Disassembly of section .data:
20000000 <uart>:
20000000: 4000c000 andmi r12, r0, r0
hexdump -C notmain.bin
00000000 00 10 00 20 25 00 00 00 55 00 00 00 00 00 00 20 |... %...U...... |
00000010 04 00 00 20 04 00 00 00 04 00 00 20 04 04 00 20 |... ....... ... |
00000020 00 04 00 00 61 20 05 4a 05 4b 11 68 02 46 13 f8 |....a .J.K.h.F..|
00000030 01 0f 00 28 fa d1 0a 60 70 47 00 bf 00 00 00 20 |...(...`pG..... |
00000040 45 00 00 00 48 61 76 65 20 61 20 67 72 65 61 74 |E...Have a great|
00000050 20 64 61 79 00 00 c0 00 40 | day....@|
00000059
所以 .data 位于 0x55
现在:
MEMORY
{
FLASH : ORIGIN = 0x00000000, LENGTH = 0x1000
SRAM : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > FLASH
.rodata : { *(.rodata*) } > FLASH
__data_rom_start__ = .;
.data : {
__data_start__ = .;
*(.data*)
} > SRAM AT > FLASH
__data_end__ = .;
}
.thumb
.global _start
_start:
.word 0x20001000
.word reset
.thumb_func
reset:
ldr r0,=__data_rom_start__
ldr r1,=__data_start__
ldr r2,=__data_end__
data_loop:
ldrb r3,[r0]
strb r3,[r1]
add r0,r0,#1
add r1,r1,#1
cmp r1,r2
bne data_loop
bl main
b .
unsigned int *uart = (unsigned int *)0x4000C000;
int main()
{
char *ptr = "Have a great day";
while (*ptr != '[=30=]') {
*uart = *ptr;
ptr++;
}
return 0;
}
Disassembly of section .text:
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000009 andeq r0, r0, r9
00000008 <reset>:
8: 4805 ldr r0, [pc, #20] ; (20 <data_loop+0x12>)
a: 4906 ldr r1, [pc, #24] ; (24 <data_loop+0x16>)
c: 4a06 ldr r2, [pc, #24] ; (28 <data_loop+0x1a>)
0000000e <data_loop>:
e: 7803 ldrb r3, [r0, #0]
10: 700b strb r3, [r1, #0]
12: 3001 adds r0, #1
14: 3101 adds r1, #1
16: 4291 cmp r1, r2
18: d1f9 bne.n e <data_loop>
1a: f000 f807 bl 2c <main>
1e: e7fe b.n 1e <data_loop+0x10>
20: 0000005d andeq r0, r0, sp, asr r0
24: 20000000 andcs r0, r0, r0
28: 20000004 andcs r0, r0, r4
0000002c <main>:
2c: 2061 movs r0, #97 ; 0x61
2e: 4a05 ldr r2, [pc, #20] ; (44 <main+0x18>)
30: 4b05 ldr r3, [pc, #20] ; (48 <main+0x1c>)
32: 6811 ldr r1, [r2, #0]
34: 4602 mov r2, r0
36: f813 0f01 ldrb.w r0, [r3, #1]!
3a: 2800 cmp r0, #0
3c: d1fa bne.n 34 <main+0x8>
3e: 600a str r2, [r1, #0]
40: 4770 bx lr
42: bf00 nop
44: 20000000 andcs r0, r0, r0
48: 0000004d andeq r0, r0, sp, asr #32
Disassembly of section .rodata:
0000004c <__data_rom_start__-0x11>:
4c: 65766148 ldrbvs r6, [r6, #-328]! ; 0xfffffeb8
50: 67206120 strvs r6, [r0, -r0, lsr #2]!
54: 74616572 strbtvc r6, [r1], #-1394 ; 0xfffffa8e
58: 79616420 stmdbvc r1!, {r5, r10, sp, lr}^
...
Disassembly of section .data:
20000000 <uart>:
20000000: 4000c000 andmi r12, r0, r0
hexdump -C notmain.bin
00000000 00 10 00 20 09 00 00 00 05 48 06 49 06 4a 03 78 |... .....H.I.J.x|
00000010 0b 70 01 30 01 31 91 42 f9 d1 00 f0 07 f8 fe e7 |.p.0.1.B........|
00000020 5d 00 00 00 00 00 00 20 04 00 00 20 61 20 05 4a |]...... ... a .J|
00000030 05 4b 11 68 02 46 13 f8 01 0f 00 28 fa d1 0a 60 |.K.h.F.....(...`|
00000040 70 47 00 bf 00 00 00 20 4d 00 00 00 48 61 76 65 |pG..... M...Have|
00000050 20 61 20 67 72 65 61 74 20 64 61 79 00 00 c0 00 | a great day....|
00000060 40 |@|
00000061
qemu-system-arm -M lm3s811evb -m 1M -nographic -kernel notmain.bin
y
因为 uart 不是易失性的,所以如果您查看编译后的输出,它只会将最后一项 y 写入寄存器,循环的其余部分正在寻找字符串的结尾。但至少现在 .data 全局变量已经用正确的值初始化,所以它可以工作。
改成这个
volatile unsigned int *uart = (unsigned int *)0x4000C000;
int main()
{
char *ptr = "Have a great day";
while (*ptr != '[=31=]') {
*uart = *ptr;
ptr++;
}
return 0;
}
qemu-system-arm -M lm3s811evb -m 1M -nographic -kernel notmain.bin
Have a great day
我故意不 use/support .data 或 .bss 部分原因是非 portable 链接器脚本和 bootstraps 等。所以多烧一点有时会闪烁以避免它。使 bootstrap 和链接描述文件变得简单。但我会花更多时间在链接描述文件上,这样 bootstrap 看起来更像这样
ldr r0,=__data_rom_start__
ldr r1,=__data_start__
ldr r2,=__data_end__
data_loop:
ldm r0!,{r4,r5}
stm r1!,{r4,r5}
cmp r1,r2
bne data_loop
通过将两端的 .data 段对齐到 64 位对齐。也会根据需要为 .bss 执行此操作,但如果我假设 .bss 为零,那么我更有可能将所有 sram 归零而不仅仅是 bss,这将是我在复制 .data 之前做的第一件事.
ldr r0,=0x20000000
ldr r1,=0x20001000 <-- adjust for sram available/used in this part/app
mov r4,#0
mov r5,#0
mov r6,#0
mov r7,#0
sram_init:
stm r0!,{r4,r5,r6,r7}
cmp r1,r2
bne sram_init
我没有用于初始化堆栈或 bss,所以如图所示,我的 bootstrap 看起来像这样
reset:
bl notmain
b .
因为我确实想从 C 入口点 return(各种原因)。有时这样:
reset:
bl notmain
wfi_loop:
wfi
b wfi_loop
wfi、wfe 等等。其中一些内核将等待实现为 nop,因为它们不支持它们。
所以...
- 您的 .data init 似乎已损坏。 2) 它没有被定义为 volatile 3) 你不需要有一个 read/write (.data) 全局变量来指向一个寄存器,你可以通过不让它成为 .data 全局变量来节省 ram 和代码变量,而只是 #define 它。
我没有校对这么多,所以希望我所有的剪切和粘贴都能奏效。无论我是否正确粘贴它,它都在我的机器上正确地 运行,并且二进制文件看起来可以正常工作。
我正在学习裸机编程,我尝试通过Qemu中的LM3S811的UART发送数据。但它没有在终端中打印任何字符。我提供了 .c 文件和链接描述文件。如果有任何链接可以帮助您从头开始学习裸机编程。谢谢
.c 文件
char stack[1024];
extern char etext;
extern char sdata;
extern char edata;
extern char sbss;
extern char ebss;
static char *bssp = (char *)0xDEADBEEF;
unsigned int *uart = (unsigned int *)0x4000C000;
void start()
{
char *from, *to;
from = &etext;
to = &sdata;
while (to != &edata) {
*to++ = *from++;
}
bssp = &sbss;
while (bssp != &ebss) {
*bssp++ = 0;
}
main();
while(1);
}
__attribute__((section(".vectors")))
void *vectors[] = {
stack + sizeof(stack),
start,
};
int main()
{
char *ptr = "Have a great day";
while (*ptr != '[=10=]') {
*uart = *ptr;
ptr++;
}
return 0;
}
链接描述文件:
{
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00010000
SRAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00002000
}
SECTIONS {
.text : {
*(.vectors);
*(.text);
etext = .;
} > FLASH
.data : {
sdata = .;
*(.data);
edata = .;
} > SRAM AT >FLASH
.bss : {
sbss = .;
*(.bss);
ebss = .;
} > SRAM
.rodata : {
*(.rodata);
} > FLASH
}
所以从这个开始,然后去改变它
flash.s
.cpu cortex-m0
.thumb
.thumb_func
.global _start
_start:
.word 0x20001000
.word reset
.thumb_func
reset:
bl notmain
b hang
.thumb_func
hang: b .
.thumb_func
.globl PUT32
PUT32:
str r1,[r0]
bx lr
notmain.c
void PUT32 ( unsigned int, unsigned int );
#define UART_DR 0x4000C000
int notmain ( void )
{
char *ptr = "Have a great day";
while (*ptr != '[=11=]') {
PUT32(UART_DR,*ptr);
ptr++;
}
return(0);
}
flash.ld
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
}
建造
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m0 flash.s -o flash.o
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=cortex-m0 -mthumb -c notmain.c -o notmain.o
arm-none-eabi-ld -nostdlib -nostartfiles -T flash.ld flash.o notmain.o -o notmain.elf
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy -O binary notmain.elf notmain.bin
检查
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000009 andeq r0, r0, r9
00000008 <reset>:
8: f000 f804 bl 14 <notmain>
c: e7ff b.n e <hang>
所以矢量 table 看起来不错
18: 4c04 ldr r4, [pc, #16] ; (2c <notmain+0x18>)
1a: 4805 ldr r0, [pc, #20] ; (30 <notmain+0x1c>)
1c: 3401 adds r4, #1
1e: f7ff fff7 bl 10 <PUT32>
22: 7821 ldrb r1, [r4, #0]
24: 2900 cmp r1, #0
...
2c: 00000034 andeq r0, r0, r4, lsr r0
...
Disassembly of section .rodata:
00000034 <.rodata>:
34: 65766148 ldrbvs r6, [r6, #-328]! ; 0xfffffeb8
38: 67206120 strvs r6, [r0, -r0, lsr #2]!
3c: 74616572 strbtvc r6, [r1], #-1394 ; 0xfffffa8e
40: 79616420 stmdbvc r1!, {r5, r10, sp, lr}^
...
字符串似乎在 rodata 中,因此看起来也不错。
qemu-system-arm -M lm3s811evb -m 1M -nographic -kernel notmain.bin
Have a great day
ctrl-a 然后 x 退出 qemu
flash.s
.thumb
.global _start
_start:
.word 0x20001000
.word notmain
notmain.c
#define UART_DR (*((volatile unsigned int *)0x4000C000))
void notmain ( void )
{
char *ptr = "Have a great day";
while (*ptr != '[=18=]') {
UART_DR=*ptr;
ptr++;
}
while(1) continue;
}
flash.ld
MEMORY
{
rom : ORIGIN = 0x00000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
}
建造
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m3 flash.s -o flash.o
arm-none-eabi-gcc -Wall -O2 -ffreestanding -mcpu=cortex-m3 -mthumb -c notmain.c -o notmain.o
arm-none-eabi-ld -nostdlib -nostartfiles -T flash.ld flash.o notmain.o -o notmain.elf
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy -O binary notmain.elf notmain.bin
检查
Disassembly of section .text:
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000009 andeq r0, r0, r9
00000008 <notmain>:
向量table很好
00000008 <notmain>:
8: 2348 movs r3, #72 ; 0x48
a: 4a04 ldr r2, [pc, #16] ; (1c <notmain+0x14>)
c: 4904 ldr r1, [pc, #16] ; (20 <notmain+0x18>)
e: 600b str r3, [r1, #0]
10: f812 3f01 ldrb.w r3, [r2, #1]!
14: 2b00 cmp r3, #0
16: d1fa bne.n e <notmain+0x6>
18: e7fe b.n 18 <notmain+0x10>
1a: bf00 nop
1c: 00000024 andeq r0, r0, r4, lsr #32
20: 4000c000 andmi r12, r0, r0
Disassembly of section .rodata:
00000024 <.rodata>:
24: 65766148 ldrbvs r6, [r6, #-328]! ; 0xfffffeb8
28: 67206120 strvs r6, [r0, -r0, lsr #2]!
2c: 74616572 strbtvc r6, [r1], #-1394 ; 0xfffffa8e
30: 79616420 stmdbvc r1!, {r5, r10, sp, lr}^
...
这是一个有趣的解决方案,但看起来不错,字符串在 flash 中,等等。
qemu-system-arm -M lm3s811evb -m 1M -nographic -kernel notmain.bin
Have a great day
您需要检查构建的输出。
如果我建造它
00000000 <vectors>:
0: 20000408 andcs r0, r0, r8, lsl #8
4: 00000009 andeq r0, r0, r9
00000008 <start>:
非常奇怪的 sp 初始值,但无论如何,它应该可以工作是吗?
Disassembly of section .text:
00000000 <vectors>:
0: 20000408 andcs r0, r0, r8, lsl #8
4: 00000009 andeq r0, r0, r9
00000008 <start>:
8: b508 push {r3, lr}
a: 480d ldr r0, [pc, #52] ; (40 <start+0x38>) 20000008
c: 4b0d ldr r3, [pc, #52] ; (44 <start+0x3c>) 20000000
e: 4283 cmp r3, r0
10: d006 beq.n 20 <start+0x18>
12: 4a0d ldr r2, [pc, #52] ; (48 <start+0x40>) 00000058
14: f812 1b01 ldrb.w r1, [r2], #1
18: f803 1b01 strb.w r1, [r3], #1
1c: 4298 cmp r0, r3
1e: d1f9 bne.n 14 <start+0xc>
从 0x0x0058 复制 8 个字节到 0x20000000
20: 4b0a ldr r3, [pc, #40] ; (4c <start+0x44>) 20000008
22: 4a0b ldr r2, [pc, #44] ; (50 <start+0x48>) 20000408
24: 480b ldr r0, [pc, #44] ; (54 <start+0x4c>) 20000000
26: 4293 cmp r3, r2
28: bf18 it ne
2a: 2100 movne r1, #0
2c: 6043 str r3, [r0, #4]
2e: d004 beq.n 3a <start+0x32>
30: f803 1b01 strb.w r1, [r3], #1
34: 4293 cmp r3, r2
36: d1fb bne.n 30 <start+0x28>
38: 6043 str r3, [r0, #4]
0 从 0x20000008 到 0x20000408 清除堆栈,幸好局部变量不在堆栈上,而且你没有从这个函数中 returning。
3a: f000 f80d bl 58 <etext>
3e: e7fe b.n 3e <start+0x36>
40: 20000008 andcs r0, r0, r8
44: 20000000 andcs r0, r0, r0
48: 00000058 andeq r0, r0, r8, asr r0
4c: 20000008 andcs r0, r0, r8
50: 20000408 andcs r0, r0, r8, lsl #8
54: 20000000 andcs r0, r0, r0
Disassembly of section .data:
20000000 <uart>:
20000000: 4000c000 andmi r12, r0, r0
20000004 <bssp>:
20000004: deadbeef cdple 14, 10, cr11, cr13, cr15, {7}
Disassembly of section .bss:
20000008 <stack>:
...
hexdump -C notmain.bin
00000000 08 04 00 20 09 00 00 00 08 b5 0d 48 0d 4b 83 42 |... .......H.K.B|
00000010 06 d0 0d 4a 12 f8 01 1b 03 f8 01 1b 98 42 f9 d1 |...J.........B..|
00000020 0a 4b 0b 4a 0b 48 93 42 18 bf 00 21 43 60 04 d0 |.K.J.H.B...!C`..|
00000030 03 f8 01 1b 93 42 fb d1 43 60 00 f0 0d f8 fe e7 |.....B..C`......|
00000040 08 00 00 20 00 00 00 20 58 00 00 00 08 00 00 20 |... ... X...... |
00000050 08 04 00 20 00 00 00 20 61 20 05 4a 05 4b 11 68 |... ... a .J.K.h|
00000060 02 46 13 f8 01 0f 00 28 fa d1 0a 60 70 47 00 bf |.F.....(...`pG..|
00000070 00 00 00 20 81 00 00 00 00 c0 00 40 ef be ad de |... .......@....|
00000080 48 61 76 65 20 61 20 67 72 65 61 74 20 64 61 79 |Have a great day|
00000090 00 |.|
00000091
.data 肯定不在闪存中的 0x58 处,幸好你没有使用 .data
根据设计,您可能希望 .data 紧跟在 .text 之后,但最好只询问链接器确切的位置。此外,事情的排列方式也可能使 etext 不是下一节的开始。
如果我们试试这个
MEMORY
{
FLASH : ORIGIN = 0x00000000, LENGTH = 0x1000
SRAM : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > FLASH
.rodata : { *(.rodata*) } > FLASH
__data_rom_start__ = .;
.data : {
__data_start__ = .;
*(.data*)
} > SRAM AT > FLASH
__data_end__ = .;
__data_size__ = __data_end__ - __data_start__;
.bss : {
__bss_start__ = .;
*(.bss*)
} > SRAM
__bss_end__ = .;
__bss_size__ = __bss_end__ - __bss_start__;
}
.thumb
.global _start
_start:
.word 0x20001000
.word main
.word __data_rom_start__
.word __data_start__
.word __data_end__
.word __data_size__
.word __bss_start__
.word __bss_end__
.word __bss_size__
移除启动功能
Disassembly of section .text:
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000025 andeq r0, r0, r5, lsr #32
8: 00000055 andeq r0, r0, r5, asr r0
c: 20000000 andcs r0, r0, r0
10: 20000004 andcs r0, r0, r4
14: 00000004 andeq r0, r0, r4
18: 20000004 andcs r0, r0, r4
1c: 20000404 andcs r0, r0, r4, lsl #8
20: 00000400 andeq r0, r0, r0, lsl #8
Disassembly of section .text:
00000000 <_start>:
0: 20001000
4: 00000025
8: 00000055 __data_rom_start__
c: 20000000 __data_start__
10: 20000004 __data_end__
14: 00000004 __data_size__
18: 20000004 __bss_start__
1c: 20000404 __bss_end__
20: 00000400 __bss_size__
Disassembly of section .data:
20000000 <uart>:
20000000: 4000c000 andmi r12, r0, r0
hexdump -C notmain.bin
00000000 00 10 00 20 25 00 00 00 55 00 00 00 00 00 00 20 |... %...U...... |
00000010 04 00 00 20 04 00 00 00 04 00 00 20 04 04 00 20 |... ....... ... |
00000020 00 04 00 00 61 20 05 4a 05 4b 11 68 02 46 13 f8 |....a .J.K.h.F..|
00000030 01 0f 00 28 fa d1 0a 60 70 47 00 bf 00 00 00 20 |...(...`pG..... |
00000040 45 00 00 00 48 61 76 65 20 61 20 67 72 65 61 74 |E...Have a great|
00000050 20 64 61 79 00 00 c0 00 40 | day....@|
00000059
所以 .data 位于 0x55
现在:
MEMORY
{
FLASH : ORIGIN = 0x00000000, LENGTH = 0x1000
SRAM : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > FLASH
.rodata : { *(.rodata*) } > FLASH
__data_rom_start__ = .;
.data : {
__data_start__ = .;
*(.data*)
} > SRAM AT > FLASH
__data_end__ = .;
}
.thumb
.global _start
_start:
.word 0x20001000
.word reset
.thumb_func
reset:
ldr r0,=__data_rom_start__
ldr r1,=__data_start__
ldr r2,=__data_end__
data_loop:
ldrb r3,[r0]
strb r3,[r1]
add r0,r0,#1
add r1,r1,#1
cmp r1,r2
bne data_loop
bl main
b .
unsigned int *uart = (unsigned int *)0x4000C000;
int main()
{
char *ptr = "Have a great day";
while (*ptr != '[=30=]') {
*uart = *ptr;
ptr++;
}
return 0;
}
Disassembly of section .text:
00000000 <_start>:
0: 20001000 andcs r1, r0, r0
4: 00000009 andeq r0, r0, r9
00000008 <reset>:
8: 4805 ldr r0, [pc, #20] ; (20 <data_loop+0x12>)
a: 4906 ldr r1, [pc, #24] ; (24 <data_loop+0x16>)
c: 4a06 ldr r2, [pc, #24] ; (28 <data_loop+0x1a>)
0000000e <data_loop>:
e: 7803 ldrb r3, [r0, #0]
10: 700b strb r3, [r1, #0]
12: 3001 adds r0, #1
14: 3101 adds r1, #1
16: 4291 cmp r1, r2
18: d1f9 bne.n e <data_loop>
1a: f000 f807 bl 2c <main>
1e: e7fe b.n 1e <data_loop+0x10>
20: 0000005d andeq r0, r0, sp, asr r0
24: 20000000 andcs r0, r0, r0
28: 20000004 andcs r0, r0, r4
0000002c <main>:
2c: 2061 movs r0, #97 ; 0x61
2e: 4a05 ldr r2, [pc, #20] ; (44 <main+0x18>)
30: 4b05 ldr r3, [pc, #20] ; (48 <main+0x1c>)
32: 6811 ldr r1, [r2, #0]
34: 4602 mov r2, r0
36: f813 0f01 ldrb.w r0, [r3, #1]!
3a: 2800 cmp r0, #0
3c: d1fa bne.n 34 <main+0x8>
3e: 600a str r2, [r1, #0]
40: 4770 bx lr
42: bf00 nop
44: 20000000 andcs r0, r0, r0
48: 0000004d andeq r0, r0, sp, asr #32
Disassembly of section .rodata:
0000004c <__data_rom_start__-0x11>:
4c: 65766148 ldrbvs r6, [r6, #-328]! ; 0xfffffeb8
50: 67206120 strvs r6, [r0, -r0, lsr #2]!
54: 74616572 strbtvc r6, [r1], #-1394 ; 0xfffffa8e
58: 79616420 stmdbvc r1!, {r5, r10, sp, lr}^
...
Disassembly of section .data:
20000000 <uart>:
20000000: 4000c000 andmi r12, r0, r0
hexdump -C notmain.bin
00000000 00 10 00 20 09 00 00 00 05 48 06 49 06 4a 03 78 |... .....H.I.J.x|
00000010 0b 70 01 30 01 31 91 42 f9 d1 00 f0 07 f8 fe e7 |.p.0.1.B........|
00000020 5d 00 00 00 00 00 00 20 04 00 00 20 61 20 05 4a |]...... ... a .J|
00000030 05 4b 11 68 02 46 13 f8 01 0f 00 28 fa d1 0a 60 |.K.h.F.....(...`|
00000040 70 47 00 bf 00 00 00 20 4d 00 00 00 48 61 76 65 |pG..... M...Have|
00000050 20 61 20 67 72 65 61 74 20 64 61 79 00 00 c0 00 | a great day....|
00000060 40 |@|
00000061
qemu-system-arm -M lm3s811evb -m 1M -nographic -kernel notmain.bin
y
因为 uart 不是易失性的,所以如果您查看编译后的输出,它只会将最后一项 y 写入寄存器,循环的其余部分正在寻找字符串的结尾。但至少现在 .data 全局变量已经用正确的值初始化,所以它可以工作。
改成这个
volatile unsigned int *uart = (unsigned int *)0x4000C000;
int main()
{
char *ptr = "Have a great day";
while (*ptr != '[=31=]') {
*uart = *ptr;
ptr++;
}
return 0;
}
qemu-system-arm -M lm3s811evb -m 1M -nographic -kernel notmain.bin
Have a great day
我故意不 use/support .data 或 .bss 部分原因是非 portable 链接器脚本和 bootstraps 等。所以多烧一点有时会闪烁以避免它。使 bootstrap 和链接描述文件变得简单。但我会花更多时间在链接描述文件上,这样 bootstrap 看起来更像这样
ldr r0,=__data_rom_start__
ldr r1,=__data_start__
ldr r2,=__data_end__
data_loop:
ldm r0!,{r4,r5}
stm r1!,{r4,r5}
cmp r1,r2
bne data_loop
通过将两端的 .data 段对齐到 64 位对齐。也会根据需要为 .bss 执行此操作,但如果我假设 .bss 为零,那么我更有可能将所有 sram 归零而不仅仅是 bss,这将是我在复制 .data 之前做的第一件事.
ldr r0,=0x20000000
ldr r1,=0x20001000 <-- adjust for sram available/used in this part/app
mov r4,#0
mov r5,#0
mov r6,#0
mov r7,#0
sram_init:
stm r0!,{r4,r5,r6,r7}
cmp r1,r2
bne sram_init
我没有用于初始化堆栈或 bss,所以如图所示,我的 bootstrap 看起来像这样
reset:
bl notmain
b .
因为我确实想从 C 入口点 return(各种原因)。有时这样:
reset:
bl notmain
wfi_loop:
wfi
b wfi_loop
wfi、wfe 等等。其中一些内核将等待实现为 nop,因为它们不支持它们。
所以...
- 您的 .data init 似乎已损坏。 2) 它没有被定义为 volatile 3) 你不需要有一个 read/write (.data) 全局变量来指向一个寄存器,你可以通过不让它成为 .data 全局变量来节省 ram 和代码变量,而只是 #define 它。
我没有校对这么多,所以希望我所有的剪切和粘贴都能奏效。无论我是否正确粘贴它,它都在我的机器上正确地 运行,并且二进制文件看起来可以正常工作。