赞
踩
要是程序大于4k的时候怎么办?
前4k代码需要把整个程序读出,放到SDRAM(重定位)
片内基地址 | |
---|---|
NAND启动 | 0 |
NOR启动 | 0x4000,00000(可以像内存一样读,不能像内存一样写) |
MOV R0, #0
LDR R1,[R0]
STR R1,[R0] # 对nor flash 内存无效
程序中函数需要写的全局/静态变量,他们在bin中,卸载NOR上,直接修改变量无效
当我们需要直接修改全局/静态变量的值的时候,我们需要把全局/静态变量重定位到SDRAM上
#include "s3c2440_soc.h" #include "uart.h" void delay(volatile int d) { while(d--); } char g_Char = 'A'; const g_Char2 = 'B'; int g_A = 0; int g_B; int main(void) { unsigned char c; int i; uart_init(); while(1) { putchar(g_Char); g_Char ++; /* nor 启动是此代码无效*/ delay(100000); } return 0; }
代码所对应汇编
main.elf: file format elf32-littlearm Disassembly of section .text: 00000000 <_start>: 0: e3a00453 mov r0, #1392508928 ; 0x53000000 4: e3a01000 mov r1, #0 ; 0x0 8: e5801000 str r1, [r0] c: e3a00313 mov r0, #1275068416 ; 0x4c000000 10: e3e01000 mvn r1, #0 ; 0x0 14: e5801000 str r1, [r0] 18: e59f0044 ldr r0, [pc, #68] ; 64 <.text+0x64> 1c: e3a01005 mov r1, #5 ; 0x5 20: e5801000 str r1, [r0] 24: ee110f10 mrc 15, 0, r0, cr1, cr0, {0} 28: e3800103 orr r0, r0, #-1073741824 ; 0xc0000000 2c: ee010f10 mcr 15, 0, r0, cr1, cr0, {0} 30: e59f0030 ldr r0, [pc, #48] ; 68 <.text+0x68> 34: e59f1030 ldr r1, [pc, #48] ; 6c <.text+0x6c> 38: e5801000 str r1, [r0] 3c: e3a01000 mov r1, #0 ; 0x0 40: e5910000 ldr r0, [r1] 44: e5811000 str r1, [r1] 48: e5912000 ldr r2, [r1] 4c: e1510002 cmp r1, r2 50: e59fd018 ldr sp, [pc, #24] ; 70 <.text+0x70> 54: 03a0da01 moveq sp, #4096 ; 0x1000 58: 05810000 streq r0, [r1] 5c: eb000011 bl a8 <main> 00000060 <halt>: 60: eafffffe b 60 <halt> 64: 4c000014 stcmi 0, cr0, [r0], {20} 68: 4c000004 stcmi 0, cr0, [r0], {4} 6c: 0005c011 andeq ip, r5, r1, lsl r0 70: 40001000 andmi r1, r0, r0 00000074 <delay>: 74: e1a0c00d mov ip, sp 78: e92dd800 stmdb sp!, {fp, ip, lr, pc} 7c: e24cb004 sub fp, ip, #4 ; 0x4 80: e24dd004 sub sp, sp, #4 ; 0x4 84: e50b0010 str r0, [fp, #-16] 88: e51b3010 ldr r3, [fp, #-16] 8c: e2433001 sub r3, r3, #1 ; 0x1 90: e50b3010 str r3, [fp, #-16] 94: e51b3010 ldr r3, [fp, #-16] 98: e3730001 cmn r3, #1 ; 0x1 9c: 0a000000 beq a4 <delay+0x30> a0: eafffff8 b 88 <delay+0x14> a4: e89da808 ldmia sp, {r3, fp, sp, pc} 000000a8 <main>: a8: e1a0c00d mov ip, sp ac: e92dd800 stmdb sp!, {fp, ip, lr, pc} b0: e24cb004 sub fp, ip, #4 ; 0x4 b4: e24dd008 sub sp, sp, #8 ; 0x8 b8: eb00000d bl f4 <uart_init> bc: e59f302c ldr r3, [pc, #44] ; f0 <.text+0xf0> c0: e5d33000 ldrb r3, [r3] c4: e1a00003 mov r0, r3 c8: eb000035 bl 1a4 <putchar> cc: e59f201c ldr r2, [pc, #28] ; f0 <.text+0xf0> d0: e59f3018 ldr r3, [pc, #24] ; f0 <.text+0xf0> d4: e5d33000 ldrb r3, [r3] d8: e2833001 add r3, r3, #1 ; 0x1 dc: e5c23000 strb r3, [r2] e0: e3a00b61 mov r0, #99328 ; 0x18400 e4: e2800e2a add r0, r0, #672 ; 0x2a0 e8: ebffffe1 bl 74 <delay> ec: eafffff2 b bc <main+0x14> f0: 0000827c andeq r8, r0, ip, ror r2 000000f4 <uart_init>: f4: e1a0c00d mov ip, sp f8: e92dd800 stmdb sp!, {fp, ip, lr, pc} fc: e24cb004 sub fp, ip, #4 ; 0x4 100: e3a02456 mov r2, #1442840576 ; 0x56000000 104: e2822070 add r2, r2, #112 ; 0x70 108: e3a03456 mov r3, #1442840576 ; 0x56000000 10c: e2833070 add r3, r3, #112 ; 0x70 110: e5933000 ldr r3, [r3] 114: e20330f0 and r3, r3, #240 ; 0xf0 118: e5823000 str r3, [r2] 11c: e3a02456 mov r2, #1442840576 ; 0x56000000 120: e2822070 add r2, r2, #112 ; 0x70 124: e3a03456 mov r3, #1442840576 ; 0x56000000 128: e2833070 add r3, r3, #112 ; 0x70 12c: e5933000 ldr r3, [r3] 130: e38330a0 orr r3, r3, #160 ; 0xa0 134: e5823000 str r3, [r2] 138: e3a02456 mov r2, #1442840576 ; 0x56000000 13c: e2822078 add r2, r2, #120 ; 0x78 140: e3a03456 mov r3, #1442840576 ; 0x56000000 144: e2833078 add r3, r3, #120 ; 0x78 148: e5933000 ldr r3, [r3] 14c: e3c3300c bic r3, r3, #12 ; 0xc 150: e5823000 str r3, [r2] 154: e3a02245 mov r2, #1342177284 ; 0x50000004 158: e3a03245 mov r3, #1342177284 ; 0x50000004 15c: e5933000 ldr r3, [r3] 160: e3833b02 orr r3, r3, #2048 ; 0x800 164: e5823000 str r3, [r2] 168: e3a02245 mov r2, #1342177284 ; 0x50000004 16c: e3a03245 mov r3, #1342177284 ; 0x50000004 170: e5933000 ldr r3, [r3] 174: e3833005 orr r3, r3, #5 ; 0x5 178: e5823000 str r3, [r2] 17c: e3a03205 mov r3, #1342177280 ; 0x50000000 180: e2833028 add r3, r3, #40 ; 0x28 184: e3a0201a mov r2, #26 ; 0x1a 188: e5832000 str r2, [r3] 18c: e3a02205 mov r2, #1342177280 ; 0x50000000 190: e3a03205 mov r3, #1342177280 ; 0x50000000 194: e5933000 ldr r3, [r3] 198: e3833003 orr r3, r3, #3 ; 0x3 19c: e5823000 str r3, [r2] 1a0: e89da800 ldmia sp, {fp, sp, pc} 000001a4 <putchar>: 1a4: e1a0c00d mov ip, sp 1a8: e92dd800 stmdb sp!, {fp, ip, lr, pc} 1ac: e24cb004 sub fp, ip, #4 ; 0x4 1b0: e24dd004 sub sp, sp, #4 ; 0x4 1b4: e50b0010 str r0, [fp, #-16] 1b8: e3a03205 mov r3, #1342177280 ; 0x50000000 1bc: e2833010 add r3, r3, #16 ; 0x10 1c0: e5933000 ldr r3, [r3] 1c4: e2033004 and r3, r3, #4 ; 0x4 1c8: e3530000 cmp r3, #0 ; 0x0 1cc: 1a000000 bne 1d4 <putchar+0x30> 1d0: eafffff8 b 1b8 <putchar+0x14> 1d4: e3a03205 mov r3, #1342177280 ; 0x50000000 1d8: e2833020 add r3, r3, #32 ; 0x20 1dc: e51b2010 ldr r2, [fp, #-16] 1e0: e5c32000 strb r2, [r3] 1e4: e1a00003 mov r0, r3 1e8: e89da808 ldmia sp, {r3, fp, sp, pc} 000001ec <getchar>: 1ec: e1a0c00d mov ip, sp 1f0: e92dd800 stmdb sp!, {fp, ip, lr, pc} 1f4: e24cb004 sub fp, ip, #4 ; 0x4 1f8: e3a03205 mov r3, #1342177280 ; 0x50000000 1fc: e2833010 add r3, r3, #16 ; 0x10 200: e5933000 ldr r3, [r3] 204: e2033001 and r3, r3, #1 ; 0x1 208: e3530000 cmp r3, #0 ; 0x0 20c: 1a000000 bne 214 <getchar+0x28> 210: eafffff8 b 1f8 <getchar+0xc> 214: e3a03205 mov r3, #1342177280 ; 0x50000000 218: e2833024 add r3, r3, #36 ; 0x24 21c: e5d33000 ldrb r3, [r3] 220: e20330ff and r3, r3, #255 ; 0xff 224: e1a00003 mov r0, r3 228: e89da800 ldmia sp, {fp, sp, pc} 0000022c <puts>: 22c: e1a0c00d mov ip, sp 230: e92dd800 stmdb sp!, {fp, ip, lr, pc} 234: e24cb004 sub fp, ip, #4 ; 0x4 238: e24dd004 sub sp, sp, #4 ; 0x4 23c: e50b0010 str r0, [fp, #-16] 240: e51b3010 ldr r3, [fp, #-16] 244: e5d33000 ldrb r3, [r3] 248: e3530000 cmp r3, #0 ; 0x0 24c: 0a000007 beq 270 <puts+0x44> 250: e51b3010 ldr r3, [fp, #-16] 254: e5d33000 ldrb r3, [r3] 258: e1a00003 mov r0, r3 25c: ebffffd0 bl 1a4 <putchar> 260: e51b3010 ldr r3, [fp, #-16] 264: e2833001 add r3, r3, #1 ; 0x1 268: e50b3010 str r3, [fp, #-16] 26c: eafffff3 b 240 <puts+0x14> 270: e1a00003 mov r0, r3 274: e89da808 ldmia sp, {r3, fp, sp, pc} Disassembly of section .rodata: 00000278 <g_Char2>: 278: 00000042 andeq r0, r0, r2, asr #32 Disassembly of section .data: 0000827c <__data_start>: 827c: Address 0x827c is out of bounds. Disassembly of section .bss: 00008280 <g_A>: 8280: 00000000 andeq r0, r0, r0 00008284 <g_B>: 8284: 00000000 andeq r0, r0, r0 Disassembly of section .comment: 00000000 <.comment>: 0: 43434700 cmpmi r3, #0 ; 0x0 4: 4728203a undefined 8: 2029554e eorcs r5, r9, lr, asr #10 c: 2e342e33 mrccs 14, 1, r2, cr4, cr3, {1} 10: 47000035 smladxmi r0, r5, r0, r0 14: 203a4343 eorcss r4, sl, r3, asr #6 18: 554e4728 strplb r4, [lr, #-1832] 1c: 2e332029 cdpcs 0, 3, cr2, cr3, cr9, {1} 20: 00352e34 eoreqs r2, r5, r4, lsr lr
注: bss 和 commen段不保存在bin文件中
段 | |
---|---|
.text | 代码段 |
.data | 数据段(全局变量) |
.rodata | const 全局变量 |
.bss | 初始值为0,无初始值的全局变量 |
commen | 注释 |
SECTIONS {
…
secname start BLOCK(align) (NOLOAD) : AT ( ldadr )
{ contents } >region :phdr =fill
…
}
名称 | 作用 |
---|---|
sename | 段名 |
start | 起始地址,运行时地址(runtime addr ),重定位地址(relocate addr) |
AT ( ldadr ) | 加载地址(默认为 runtime addr) |
contents | start.o / *(.text) / start.0 *(.text) |
链接得到elf 文件 ,含有地址信息(loadaddr)
使用加载器(对于裸板时JTAG调试工具)(对于app 加载器也是app 把elf文件读入内存 读到loadaddr)
运行
如果loaddr 不等于 runtime addr 程序本身要重地位
elf —> bin
如果没有加载器,硬件机制启动
例:
SECTIONS {
.text 0 :{ *(.text) } # loadaddr = runtime addr = 0
.rodata :{ *(.rodata) }
.data 0x30000000 : AT(0x800) # loadaddr = 0x8000 runtimeaddr = 0x300000000
{
data_load_addr = LOADADDR(.data);
data_start = .; # 当前位置 地址
*(.data)
data_end = .;
}
.bss :{ *(.bss) *(.COMMON) }# runtime = 0x3xxxxxxx
}
bin文件 /elf 文件都不存 bss
bl sdram_init /*初始化 sdram */ /*重定位*/ ldr r1,= data_load_addr /*data段在bin文件中的地址,加载地址*/ ldr r2, = data_start /*data段在重定位地址,运行时地址*/ ldr r3, = data_end /*data段在重定位地址,运行时地址*/ cpy: ldrb r4,[r1] /*从r1读取1byte数据到r4*/ strb r4,[r2] /*把r4的值存放到r2的位置*/ add r1,r1,#1 /*r1 = r1+1*/ add r2,r2,#1 /* r2 = r2 +1*/ cmp r2,r3 /*比较r2和r3是否相同*/ bne cpy /*不相同 继续cpy*/ makefile all: arm-linux-gcc -c -o main.o main.c arm-linux-gcc -c -o uart.o uart.c arm-linux-gcc -c -o init.o init.c arm-linux-gcc -c -o start.o start.S # arm-linux-ld -Ttext 0 start.o main.o uart.o -o main.elf arm-linux-ld -T sdram.lds start.o main.o uart.o init.o -o main.elf arm-linux-objcopy -O binary -S main.elf main.bin arm-linux-objdump -D main.elf > main.dis clean: rm *.bin *.o *.elf *.dis
SECTIONS { .text 0 :{ *(.text) } .rodata :{ *(.rodata) } .data 0x30000000 : AT(0x800) { data_load_addr = LOADADDR(.data); data_start = .; *(.data) data_end = .; } bss_start = .; .bss :{ *(.bss) *(.COMMON) } bss_end = .; } ldr r1, = bss_start ldr r2, = bss_end mov r3, #0 # r3 = 0 clean: strb r3,[r1] add r1,r1,#1 cmp r1,r2 bne clean
现存:
因为NOR 为 16 位 的SDRAM 为 32位的 如果每次读取一位效率会非常第
ldrb 从nor 得到数据 :需要执行16次,访问NOR 16次
strb 写SDRAM :需要执行16次,访问SDRAM 16次
因为 SDRAM 是32位的所以一次操作最小的单位为;32位
如果读一个字节,内存控制器会去SDRAM 读出4个字节然后挑出CPU感兴趣的字节,
CPU把地址和数据发给内存控制器,内存控制把32位的数据发给SDRAM,同时还会发出数据屏蔽信号(DQM)屏蔽其他3字节数据
改进
使用ldr 和 str 每次4字节操作
指令str:无论存入地址为多少都是以4个字节为单位存入,也就是说无论存入地址是0x40000000或0x40000001或0x400000002或0x40000003,存入都是以0x40000000开始;
这里我们需要 链接命令
ALIGN(exp)
sdram.lds SECTIONS { .text 0 :{ *(.text) } .rodata :{ *(.rodata) } .data 0x30000000 : AT(0x800) { data_load_addr = LOADADDR(.data); . = ALIGN(4); data_start = .; *(.data) data_end = .; } . = ALIGN(4); # . = 0x30000002 所以 这里 . = 0x30000004 为了 对于str bss_start = .; .bss :{ *(.bss) *(.COMMON) } bss_end = .; } start.S /*重定位*/ ldr r1,= data_load_addr /*data段在bin文件中的地址,加载地址*/ ldr r2, = data_start /*data段在重定位地址,运行时地址*/ ldr r3, = data_end /*data段在重定位地址,运行时地址*/ cpy: ldr r4,[r1] /*从r1读取1byte数据到r4*/ str r4,[r2] /*把r4的值存放到r2的位置*/ add r1,r1,#4 /*r1 = r1+1*/ add r2,r2,#4 /* r2 = r2 +1*/ cmp r2,r3 /*比较r2和r3/ ble cpy /*如果r2<r则 继续 cpy*/ ldr r1, = bss_start ldr r2, = bss_end mov r3, #0 clean: str r3,[r1] add r1,r1,#4 cmp r1,r2 ble clean
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。