Linux开发环境搭建05---s3c2440最简BootLoader实现

一、JZ2440(S3C2440开发板)存储单元说明

JZ2440的基本参数如下:

SDRAM:64MB   0x3000 0000~ 0x3400 0000

Nand Flash:256MB  0x0000 0000 ~ 0x1000 0000

 

二、最简BootLoader启动流程分析

JZ2440开发板的启动分为Nor Flash启动和Nand Flash启动,这里以NandFlash启动为例进行说明s3c2440的启动流程。

1、启动模式选择

s3c2440支持两种启动模式:NAND和非NAND(这里是nor flash)。
具体采用的方式取决于OM0、OM1两个引脚

OM[1:0所决定的启动方式

OM[1:0]=00时,处理器从NANDFlash启动

OM[1:0]=01时,处理器从16位宽度的ROM启动

OM[1:0]=10时,处理器从32位宽度的ROM启动。

OM[1:0]=11时,处理器从TestMode启动。

 

 

2、上电启动

(1)当从NAND启动时

   cpu会自动从NAND flash中拷贝前4KB的数据放置在片内SRAM里(s3c2440是soc),同时把这段片内SRAM映射到nGCS0片选的空间(即0x00000000)。cpu是从0x00000000开始执行,也就是NAND flash里的前4KB内容。因为NAND FLASH连地址线都没有,不能直接把NAND映射到0x00000000,只好使用片内SRAM做一个载体。通过这个载体把nand flash中剩余的代码(u-boot、linux-kernel)复制到RAM(一般是SDRAM)中去执行

(2)当从非NAND flash(Nor Flash)启动时

nor flash被映射到0x00000000地址(就是nGCS0,这里就不需要片内SRAM来辅助了,所以片内SRAM的起始地址还是0x40000000). 然后cpu从0x00000000开始执行(也就是在Nor falsh中执行)。

 

三星的stepstone内置了一小块RAM(stepstone),然后从硬件上实现CPU上电后先读取nand flash最开始的一段代码到stepstone中去(当然,要设置硬件为nandflash启动方式),然后从stepstone起始处(被设置为RAM的0地址)去执行。这个stepstone一般很小(2410,2440是4K),所以它没办法放下一个功能复杂的bootloader(比如eboot),只能放一个功能很简单的,这就是需要nboot的原因了。nboot的功能十分单一,就是从nandflash复制image到RAM中去,然后跳转执行。

当将Nand Flash中的code拷贝到stepstone时,并未根据链接脚本中的链接地址,而是将代码的连接地址重新定位为0x00000000,并从0x00000000开始执行。(未确定)

 

3、最简boot实现流程

我们实现的最简boot主要功能是将内核代码从Nand Flash拷贝到内存(SDRAM)中,并跳转到相应的地址执行。由于最简boot本身代码较小(小于4KB),没有必须要再拷贝boot本身的代码到SDRAM中,只需要片内SRAM 4KB即可完成将内核代码从Nand Flash拷贝到内存(SDRAM)中

最简boot分为两个阶段:

1、第一阶段启动(start.s/init.c)

(1)start.s

初始化硬件:关看门狗、设置时钟、设置总线模式、设置锁相环频率、启动ICACHE、初始化SDRAM相关寄存器、设置堆栈地址sp,初始化NAND FLASH、清除bss段

 

(2)init.c

  如果bootloader比较大,要把它重定位到SDRAM

 

2、第二阶段启动(boot.c/setup.h)

A. 初始化串口,能够调试

B. 把内核从NANDFLASH(0x60000+64)读到SDRAM(0x30008000)

C. 设置"要传给Linux/EOS内核的参数",SDRAM存放地址0x30000100

D. 跳转执行内核(SDRAM =0x30008000)

具体实现代码见最后

 

三、最简BootLoader的编译

交叉编译环境的编译见上一节

与编译相关的文件主要有2个

(1)boot.lds文件

 boot.lds是链接脚本,说明编译后的各文件顺序如何在FLASH存储器中存放,即告诉链接器arm-linux-ld如何将*.o文件链接起来

 

  这儿是连接脚本里面的内容:*.lds,里面包含代码段(.text)、只读数据段(.rodata)、读写数据段(.data)、bss段(里面存放未初始化的全局变量、初始化为0的全局变量),这些段可以通过在汇编代码中指定,也可以使用GCC相关的宏指定某个符号(变量或函数)属于哪一个段。

  lds描述了输出文件的“映射图”:输出文件中各段、各文件怎么存放,最后连接成一个可执行的文件;

 

  通过*.lds生成可执行的链接脚本(elf)

 

 

SECTIONS {

        . =0x33f80000;    //自己随便找的,表示当前代码存放在SDRAM中地址为0x33f80000,

        .text : {*(.text) }   // 代码段

 

        . =ALIGN(4);      //对齐(当前地址取整)

        .rodata :{*(.rodata*)}   //只读数据段

 

        . = ALIGN(4);

        .data : {*(.data) }    //读写数据段

 

        . = ALIGN(4);

        __bss_start =.;             //二进制文件的大小

        .bss : {*(.bss)  *(COMMON) }   //初始值为0的全局变量

        __bss_end = .;

}

 

 

(2)Makefile

 

        #编译工具

        CC     = arm-linux-gcc                       //实际上是使用Makefile中使用自定义的变量,下面只要是不跳出该Makefile文件,该变量都是有效的       

        #链接工具

        LD     = arm-linux-ld       

        #将多个可重定位的目标模块归档为一个函数库文件

        AR     = arm-linux-ar

        #对象复制选项

        OBJCOPY =arm-linux-objcopy

        #用来显示二进制文件,查看反汇编代码

        OBJDUMP = arm-linux-objdump

        #编译选项

        CFLAGS                := -Wall -O2

        #编译选项

        CPPFLAGS          := -nostdinc -nostdlib -fno-builtin

        #要生成的目标文件

        objs := start.oinit.o boot.o

 

        #最终要生成的目标文件

        #使用boot.lds进行目标文件的连接,生成elf(可执行的连接脚本)

        boot.bin:$(objs)

               ${LD} -Tboot.lds -o boot.elf $^               # $^代表*.o文件,所有的依赖目标的集合。

 

          #-O:使用指定的格式输出文件   -S:不从源文件中复制重定位信息和符号信息到目标文件中去

          #整体上代表将ELF格式的可执行文件转换为二进制文件  $@:boot.bin

               ${OBJCOPY} -O binary -S boot.elf $@

 

            #反汇编所有段-D 指定反汇编时使用的架构-m  boot.elf可执行的连接文件   boot.dis最终生成的可以查看的汇编代码

               ${OBJDUMP} -D -m arm boot.elf > boot.dis      

        %.o:%.c

               ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

 

        %.o:%.S

               ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

 

        clean:

               rm -f *.o *.bin *.elf *.dis

 

 

 

四、编译后bin文件下载到NandFlash

使用JZ2440开发板自带的u-boot通过Nor Flash烧写Nand Flash

三秒——>空格—>qàopenJATG->

 

tftp 30000000 boot.bin

nand erase bootloader

nand write 30000000 bootloader

 

 

五、总结

Arm的启动都是从0地址开始,所不同的是地址的映射不一样。在arm上电的时候,要想让arm知道以某种方式(地址映射方式)运行,不可能通过你写的某段程序控制,因为这时候你的程序还没启动,这时候arm会通过引脚的电平来判断。

 

1.当引脚OM0跟OM1有一个是高电平时,这时地址0会映射到外部nGCS0片选的空间,也就是Norflash,程序就会从Norflash中启动,arm直接取Norflash中的指令运行。

 

2.当OM0跟OM1都为低电平,则0地址内部stepstone(一段4k的SRAM)开始。系统上电,arm会自动把NAND flash中的前4K内容拷贝到stepstone(也就是0地址),然后从0地址运行。

 

这时NANDFlash中的前4K就是启动代码(他的功能就是初始化硬件然后在把NANDFlash中的代码复制到RAM中,再把相应的指针指向该运行的地方)

 

 

为什么会有这两种启动方式,关键还是两种flash的不同特点造成,NORFLASH容量小,速度快,稳定性好,输入地址,然后给出读写信号即可从数据口得到数据,适合做程序存储器。NAND FLASH 总容量大,但是读写都需要复杂的时序,更适合做数据存储器。这种不同就造成了NORflash可以直接连接到arm的总线并且可以运行程序,而NANDflash必须搬移到内存(SDRAM)中运行。

 

   在实际的开发中,一般可以把bootloader烧入到Nor flash,程序运行可以通过串口交互,进行一定的操作,比如下载,调试。这样就很可以很方便的调试你的一些代码。Norflash中的Bootloader还可以烧录内核到Norflash等等功能。

 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值