“第013课 代码重定位”的版本间的差异
Baiwen root(讨论 | 贡献) (创建页面,内容为“<categorytree mode=all style="float:right; clear:right; margin-left:1ex; border:1px solid gray; padding:0.7ex; background-color:white;">ARM裸机加强版</categoryt...”) |
Baiwen root(讨论 | 贡献) |
||
第1行: | 第1行: | ||
− | < | + | =第001节_段的概念_重定位的引入 = |
+ | S3C2440的CPU可以直接给SDRAM发送命令、给Nor Flash发送命令、给4K的片上SDRAM发送命令,但是不能直接给Nand Flsh发送命令 | ||
+ | |||
+ | 假如把程序烧写到Nand Flsh上,即向Nand Flsh烧入** bin** 文件,CPU是无法从Nand Flsh中取代码执行的。 | ||
+ | |||
+ | 为什还可以使用NAND启动? | ||
+ | 1. 上电后,Nand启动硬件会自动把Nand Flsh前4K复制到SRAM; | ||
+ | 2. CPU从0地址运行SRAM; | ||
+ | |||
+ | 如果我的程序大于4K怎么办? | ||
+ | 前4K的代码需要把整个程序读出来放到SDRAM(即代码重定位)。 | ||
+ | |||
+ | 如果从Nor Flash启动,会出现什么问题? | ||
+ | 将拨动开关拨到Nor Flash启动时,此时CPU认为的** 0地址 **在Nor Flash上面,片内内存SRAM的基地址就变成了0x40000000(Nand启动时片内内存SRAM的基地址基地址是0),由于Nor Flash特性:**可以像内存一样读,但不能像内存直接写**,因此需要把全局变量和静态变量重定位 放到SDRAM里。 | ||
+ | |||
+ | |||
+ | 例如执行如下几条汇编指令 | ||
+ | |||
+ | MOV R0, #0 | ||
+ | LDR R1, [R0] @读有效 | ||
+ | STR R1, [R0] @写无效 | ||
+ | |||
+ | 当程序中含有需要写的全局变量或静态变量时,假如是在Nand Flash可以正常操作,如果是在Nor Flash,修改无效。因此我们需要把全局变量和静态变量重定位 放到SDRAM | ||
+ | |||
+ | <syntaxhighlight lang="c" > | ||
+ | |||
+ | #include "s3c2440_soc.h" | ||
+ | #include "uart.h" | ||
+ | #include "init.h" | ||
+ | |||
+ | char g_Char = 'A'; //定义一个全局变量 | ||
+ | const char g_Char2 = 'B'; //定义固定的全局变量 | ||
+ | int g_A = 0; | ||
+ | int g_B; | ||
+ | |||
+ | int main(void) | ||
+ | { | ||
+ | uart0_init(); | ||
+ | |||
+ | while (1) | ||
+ | { | ||
+ | putchar(g_Char); /*让g_Char输出*/ | ||
+ | g_Char++; /* nor启动时, 此代码无效 */ | ||
+ | delay(1000000); | ||
+ | } | ||
+ | |||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | 编译运行查看是否有效果 | ||
+ | |||
+ | 查看sdram.dis文件 发现data数据段放在了0x00008474这个地址导致 程序太大 | ||
+ | |||
+ | 在makefile中加入这么一句话 | ||
+ | |||
+ | arm-linux-ld -Ttext 0 ** -Tdata 0x800 ** start.o led.o uart.o init.o main.o -o sdram.elf | ||
+ | |||
+ | 16进制的800就是十进制的2048 | ||
+ | 这时我们的bin文件就变为2049 | ||
+ | |||
+ | |||
+ | 烧写程序 | ||
+ | |||
+ | 烧写在NORFlash | ||
+ | 烧写在NANDFlash观察这两种的效果 | ||
+ | |||
+ | 设置成NANDFlash启动没有问题 显示ABCDE... | ||
+ | 设置成NORFlash启动显示AAA... | ||
+ | 对于NOR启动时g_Char++; /* nor启动时, 此代码无效 */ | ||
+ | |||
+ | |||
+ | <syntaxhighlight lang="c" > | ||
+ | Disassembly of section .data: | ||
+ | |||
+ | 00000800 <__data_start>: | ||
+ | 800: Address 0x800 is out of bounds. //数据段 | ||
+ | |||
+ | Disassembly of section .rodata: | ||
+ | //放在只读数据段内 | ||
+ | 00000474 <g_Char2>: //const char g_Char2 = 'B'; | ||
+ | 474: Address 0x474 is out of bounds. | ||
+ | |||
+ | Disassembly of section .bss: //bss段 | ||
+ | |||
+ | 00000804 <g_A>: //int g_A = 0; | ||
+ | |||
+ | 804: 00000000 andeq r0, r0, r0 | ||
+ | |||
+ | 00000808 <g_B>: //int g_B; | ||
+ | 808: 00000000 andeq r0, r0, r0 | ||
+ | Disassembly of section .comment: | ||
+ | |||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | 一个程序里面有 | ||
+ | * .text 代码段 | ||
+ | * .data 数据段 | ||
+ | * rodata 只读数据段(const全局变量) | ||
+ | * bss段 (初始值为0,无初始值的全局变量) | ||
+ | * commen 注释 | ||
+ | |||
+ | 其中bss段和commen 注释不保存在bin文件中。 | ||
+ | |||
+ | |||
+ | ='''《《所有章节目录》》'''= | ||
+ | <categorytree mode=all background*color:white;">ARM裸机加强版</categorytree> | ||
[[Category:ARM裸机加强版 ]] | [[Category:ARM裸机加强版 ]] |
2018年1月17日 (三) 17:07的版本
第001节_段的概念_重定位的引入
S3C2440的CPU可以直接给SDRAM发送命令、给Nor Flash发送命令、给4K的片上SDRAM发送命令,但是不能直接给Nand Flsh发送命令
假如把程序烧写到Nand Flsh上,即向Nand Flsh烧入** bin** 文件,CPU是无法从Nand Flsh中取代码执行的。
为什还可以使用NAND启动? 1. 上电后,Nand启动硬件会自动把Nand Flsh前4K复制到SRAM; 2. CPU从0地址运行SRAM;
如果我的程序大于4K怎么办? 前4K的代码需要把整个程序读出来放到SDRAM(即代码重定位)。
如果从Nor Flash启动,会出现什么问题? 将拨动开关拨到Nor Flash启动时,此时CPU认为的** 0地址 **在Nor Flash上面,片内内存SRAM的基地址就变成了0x40000000(Nand启动时片内内存SRAM的基地址基地址是0),由于Nor Flash特性:**可以像内存一样读,但不能像内存直接写**,因此需要把全局变量和静态变量重定位 放到SDRAM里。
例如执行如下几条汇编指令
MOV R0, #0 LDR R1, [R0] @读有效 STR R1, [R0] @写无效
当程序中含有需要写的全局变量或静态变量时,假如是在Nand Flash可以正常操作,如果是在Nor Flash,修改无效。因此我们需要把全局变量和静态变量重定位 放到SDRAM
#include "s3c2440_soc.h"
#include "uart.h"
#include "init.h"
char g_Char = 'A'; //定义一个全局变量
const char g_Char2 = 'B'; //定义固定的全局变量
int g_A = 0;
int g_B;
int main(void)
{
uart0_init();
while (1)
{
putchar(g_Char); /*让g_Char输出*/
g_Char++; /* nor启动时, 此代码无效 */
delay(1000000);
}
return 0;
}
编译运行查看是否有效果
查看sdram.dis文件 发现data数据段放在了0x00008474这个地址导致 程序太大
在makefile中加入这么一句话
arm-linux-ld -Ttext 0 ** -Tdata 0x800 ** start.o led.o uart.o init.o main.o -o sdram.elf
16进制的800就是十进制的2048 这时我们的bin文件就变为2049
烧写程序
烧写在NORFlash 烧写在NANDFlash观察这两种的效果
设置成NANDFlash启动没有问题 显示ABCDE... 设置成NORFlash启动显示AAA... 对于NOR启动时g_Char++; /* nor启动时, 此代码无效 */
Disassembly of section .data:
00000800 <__data_start>:
800: Address 0x800 is out of bounds. //数据段
Disassembly of section .rodata:
//放在只读数据段内
00000474 <g_Char2>: //const char g_Char2 = 'B';
474: Address 0x474 is out of bounds.
Disassembly of section .bss: //bss段
00000804 <g_A>: //int g_A = 0;
804: 00000000 andeq r0, r0, r0
00000808 <g_B>: //int g_B;
808: 00000000 andeq r0, r0, r0
Disassembly of section .comment:
一个程序里面有
- .text 代码段
- .data 数据段
- rodata 只读数据段(const全局变量)
- bss段 (初始值为0,无初始值的全局变量)
- commen 注释
其中bss段和commen 注释不保存在bin文件中。