U-BOOT之stage1

AT91SAM9260

ARM926EJ-S

u-boot

 

.配置和编译链接

       配置:

Make (板级)XXX_config

       Make

       具体的Makefile中,

在配置项中还可以加入其他配置宏,用来增加新的配置宏定义或覆盖include/configs/<板名称>.h下的同名宏定义。比如:

echo "#define PHYS_SDRAM_SIZE 0x2000000" >> $(obj)include/config.h

(添加配置宏到config.h中)

 

在每个板级代码目录下,都有一个u-boot.lds文件,是一个GCC的链接脚本,表明了U-BOOT镜像的组成以及一些段位置的定义。

在AT91SAM9260上,设计了低级初始化部分,以支持从NAND启动。所有低级初始化用到的代码都必须位于前4KB位置。所以,文件u-boot.lds中,把这些代码放在镜像的前面,如下所示:(类似scatter文件)

SECTIONS

{

       . = 0x00000000;

 

       . = ALIGN(4);

       .text      :

       {

         cpu/arm926ejs/start.o (.text)

         cpu/arm926ejs/at91sam926x/nboot.o (.text)

         cpu/arm926ejs/at91sam926x/nboot.o (.rodata)

         cpu/arm926ejs/at91sam926x/ebi.o (.init.lowlevel)    

         *(.text)

       }

...

 

ebi.o中,不是所有代码都被低级初始化使用的,所以将低级初始化相关代码定义在.init.lowlevel段中。对应函数声明如下:

int __attribute__((__section__(".init.lowlevel")))  AT91F_InitSDRAM (u32 cr, u32 lpr)

镜像的运行期起始地址在config.mk中定义,如下所示:

sinclude $(OBJTREE)/board/$(BOARDDIR)/config.tmp

ifndef TEXT_BASE

TEXT_BASE = xxx(这个根据板级设置进行配置)

Endif

TEXT_BASE就表明了运行期起始地址。这里还包含了config.tmp文件,是为了可以在U-BOOT根目录下的Makfile文件中定义不同的起始地址

 

二.Start.s

启动UBOOT的一些要求,

      禁止中断,关闭MMU,SVC32模式,打开I-CACHE(指令缓存),关闭数据CACHE

对于CPU/ARM926EJS/start.s(同样,对于一些#define也依赖于XXX.h(板级头文件))

定义 _TEXT_BASE, _bss_start,_bss_end,_armboot_start,

初始化之后,b reset,Reset中,设置为SVC32 mode之后,

Bl cpu_init_crit(一般情况下不应该skip lowlevel init)

Cpu_init_crit打开I-CACHE,关闭D-CACHE,关闭MMU,然后ip寄存器保存lr的值,即lowlevel_init的返回地址,bl lowlevel_init(函数在lowlevel_init.s)

Cpu_init_crit返回后继续运行,跳转到C语言的接口start_armboot

(这在stage2中说明)

 

三.Lowlevel_init.s

       lowlevel_init首先设置栈寄存器SP,

然后

Mov r5,lr

Mov r6,ip

/*

*将寄存器lrip分别保存r5r6中。

*这两个寄存器分别存放函数cpu_init_crit调用本函数AT91F_LowLevelInit的返回地址

*以及ARM复位向量调用函数lowlevel_init的返回地址

*/

/*

*1.当使用bl或者blx跳转到子过程的时候,(lr)r14保存了返回地址,可以在调用过程结尾恢复。

*2.异常中断发生时,这个异常模式特定的物理R14被设置成该异常模式将要返回的地址。

*/      

bl AT91F_LowLevelInit(完成硬件初始化该函数在board_lowlevel_init.c中)

接着如果定义了从nand boot则第一次拷贝

Bl copy_start,

由于nand boot需要硬件将nand flash的前4K拷贝到内部的SDRAM0,其中vaild image detect要求偏移的第六向量,即0x14必须为要拷贝的长度,这里设置的是4K大小,查看u-boot.bin也可以看到0x14对应的数据位00100000

(具体的可以看AT91SAM9260SPEC中关于valid image detect部分)

这里将前4k的数据拷贝到_text_base起始的SDRAM地址,然后将程序的PC设置成加上_text_baselr的地址,在SDRAM上继续运行(而没有重新开始运行)

Bl copy_main(继续讲剩下的代码拷贝到SDRAM中,该函数在nboot.c中。)

 

四.Board_lowlevel_init.c

       a) AT91F_LowLevelInit完成硬件相关初始化

该函数执行过程如下:

1.如果有使用以太网(定义了配置宏CONFIG_DRIVER_ETHERCONFIG_CMD_NET),则配置以太网PHY接口的口线

2.如果允许了用户复位功能(定义了配置宏CONFIG_USR_RESET),则开启用户复位功能

3.禁止看门狗

4.调用函数AT91F_SetPLL设置锁相环PLLA,并配置CPU时钟和总线时钟

5.调用函数AT91F_AIC_DisableAll禁止所有AIC中断。函数AT91F_AIC_DisableAll设置寄存器AIC_IDCR禁止所有AIC中断,并设置寄存器AIC_ICCR清空所有未处理中断

6.连续调用8AT91F_AIC_AcknowledgeItadvance interrupt control)响应AIC中断:9G20/9260最多可以存储8个未处理的不同优先级中断,所以调用8次以全部清除。函数AT91F_AIC_AcknowledgeIt设置寄存器AIC_EOICR以表明中断结束

7.允许CPU系统控制区部分时钟

8.配置SDRAM:依次按64MB32MB16MB三种容量调用函数AT91F_InitSDRAM进行配置并测试读写,直到找到匹配的配置。传递到函数AT91F_InitSDRAM的参数cfglpr定义如下:

(1)SDRAM配置寄存器值cfg:包括:

a. 4BANK16位总线

b. 时序TWR2TRC=9TRP=3, TRCD=3, TRAS=6TXSR=10;如果是9G20CAS3;否则为2

c. 根据SDRAM容量设置行数和列数

(2)SDRAM低功耗控制寄存器值lpr:宏BOARD_SDRAM_LPR,即允许在SDRAM空闲64个周期后自动进入自我刷新模式

9.调用函数AT91F_InitSMC配置NAND FLASH所在片选时序

 

b)  AT91F_SetPLL

该函数执行过程如下:

1、禁止电源管理控制器PMC的所有中断

2、检查主时钟是否已经起振(CKGR_MCFR寄存器的MAINRDY位),如果没有,则进行如下过程以启动主时钟

(1)设置寄存器CKGR_MOR:域OSCOUNT为最大,位MOSCEN1,以启动主时钟

(2)等待主时钟稳定:反复检查寄存器PMC_SR,直到位MOSCS1

3、配置锁相环PLLA并启动:即设置寄存器CKGR_PLLAR来配置锁相环PLLA,并反复检查寄存器PMC_SR,直到位LOCKA1。配置过程如下:

(1)PLLA稳定时间(域PLLACOUNT):为3542个慢时钟周期。9260/9G20PLLA启动时间根据ATMEL提供的计算公式得出。慢时钟可能是外部32.768KHZ或内部RC20KHZ以上,不定),这决定了不同的PLLA稳定时间的周期数。慢时钟源根据寄存器PMC_SROSC_SEL位决定

(2)乘法因子(MULA)和除法因子(DIVA):使用函数cpu_is_at91sam9g20判断处理器是9260还是9G20,如果是9260,则输出191.6928MHZ9G20则要输出796.2624MHZ。这还影响到域OUTA的取值,因为PLLA输出时钟不同频率下,必需设置不同的OUTA的值,这根据Datasheet中要求决定

4、配置CPU时钟和总线时钟:按照Datasheet要求的过程进行设置,如下:

检查寄存器PMC_MCKRCSS域,如果输入时钟源不是PLLA输出时钟,则单独修改输入时钟源为PLLA输出时钟,并反复检查寄存器PMC_SR,直到位MCKRDY1

如果处理器为9G20,则设置CPU时钟为PLLA输出时钟的1/2,总线时钟为PLLA输出时钟的1/6,即分别为398.1312MHZ132.7104MHZ。如果是9260,则CPU时钟就是PLLA输出时钟,而总线时钟则为PLLA输出时钟的1/2,分别为191.6928MHZ95.8464MHZ

反复检查寄存器PMC_SR,直到位MCKRDY1

 

c) __inline AT91F_InitSMC(void)

该函数分别配置寄存器SMC_SETUP3SMC_PULSE3SMC_CYCLE3SMC_CTRL3,即片选3的配置,包括:

(1)总线宽度:位于SMC_CTRL3,总线宽度根据宏CFG_NAND_WIDTH决定,如果包含位NAND_BUSWIDTH_16,则需要定义16位数据线;否则定义8位数据线

(2)片选类型:目前是支持读写、不使用NWAIT信号

(3)时序:9G209260主频不同,所以这些寄存器中存储的各种时序周期数也不同

 

五.Copy_mainnboot.c

       这里涉及到nand flash的操作,不过没有使用MTD框架

(1)    at91_nand_init

初始化主要的是口线的设置,相关寄存器的配置,包括R/B,CS

这里CLEALE与地址线相连所以操作地址时就操作了相应pin

(2)    nboot_get_flash_type

通过调用nboot_get_flash_type获取NAND FLASH类型,包括页大小,块大小,OOB区域大小。

1.      片选nand flash

2.      发送命令90,地址为0 读取前两字节的ID,(具体可参照u-bootNAND FLASH

如果第二个字节小于0XA1,则页大小不超过512字节,指定页大小为512字节,块大小为16KOOB16字节

否则,再读取两字节数据,ID号第4个字节可以获取页大小、块大小、OOB区域大小,并可知道是8位还是16 NAND FLASH,如下:

(a)01位内容确定页大小:1024* 2^x

(b)2位确定OOB区域大小:(页大小/512) * (8 * 2^x)

(c)45位确定块大小:64KB* 2^x

(d)6位:116NAND FLASH08NAND FLASH

3.    nboot_ecc_init

       通过页大小配置ECC寄存器,包括MR,CR

4. 通过页大小配置ECC校验字节位置和坏块标志字节,对于512字节的页,ECC校验字节位置为前4字节,坏块标志字节为5,6字节

5 关闭片选

(3)    找到起始页,发送命令0,行地址为0,列地址为当前页偏移,表明需要读取一页的数据,接着读取一页的数据(此数据保存于SDARM中,是BOOT的后续代码),检查是否坏块,检查数据是否有错误,如果只是1 bit的错误,则可以纠正,

否则,读取下一页的数据,重复以上工作,知道endp(_bss_start)

在读取下一页的数据之前,需反复调用函数nboot_devready,直到NAND FLASH就绪,这是因为部分NAND FLASH有自动递增功能,即读完一页内容后会自动把下页内容送入NAND FLASH缓冲区,在此期间NAND FLASH处于忙状态,不能响应指令。

 

六.u-boot.lds

       该文件为编译的链接文件,类似于scatter文件

       OUTPUT_FORMAT,OUTPUT_ARCH说明的使用的小端模式,体系为ARM体系

       ENTRY(_start)说明程序的入口地址是_start

       Nand boot需要将前4K的代码拷贝到内部SDRAM0中,所以在分配段时,尽量把stage1初始化的代码分配到前4K中。

       .text      :

       {

         cpu/arm926ejs/start.o    (.text)

         cpu/arm926ejs/at91sam926x/nboot.o (.text)

         cpu/arm926ejs/at91sam926x/nboot.o (.rodata)

         cpu/arm926ejs/at91sam926x/ebi.o (.init.lowlevel)   

         *(.text)

       }    

将汇编相关的放在最前面,这里将ebi.o中段名为.init.lowlevel中的内容放于.text段中,而这真是前面提到的AT91F_InitSDRAM接着分配的就是rodata data,

       __u_boot_cmd_start = .;

       .u_boot_cmd : { *(.u_boot_cmd) }

       __u_boot_cmd_end = .;

       这里将所有的u_boot_cmd命令分配到以_u_boot_cmd_start开始的地址上,便于后面通过命令名查找cmd_trl_t结构,然后调用相应的方法。

       最后就是_bss

       __bss_start = .;

       .bss : { *(.bss) }

       _end = .;

以上就是U-BOOT中的stage1部分,在下篇中会介绍stage2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值