韦东山 Linux开发板,从零开始构建bootloader(基于韦东山JZ2440V3开发板)

从零开始构建bootloader

项目步骤:

第一阶段:

​ 1、关看门狗;

​ 2、时钟初始化;

​ 3、内存初始化;

​ 4、NandFlash初始化;

​ 5、代码重定位(将flash中的代码复制到指定的内存地址处,也即代码段链接地址);

​ 6、跳转到main函数;

第二阶段:

​ 7、写main函数,在函数中设置要传给内核的参数;

​ 8、跳转到内核入口,启动内核

​ 9、制作链接脚本

第三阶段:

​ 10、编写Makefile文件;

​ 11、编译、下载、运行

1、编写start.S文件,初始化片上硬件

本文件需要完成的目标:

1.关看门狗

2.设置时钟

3.开启指令缓存,初始化SDRAM

4.重定位(把bootloader本身的代码从flash复制到它的链接地址(c函数编写),然后清空bss段(c函数编写))

5.跳转到main函数。

#define CLKDIVN 0X4C000014 /*设置FCLK:HCLK:PCLK的比例*/

#define MPLLCON 0x4C000004 /*设置FCLK频率*/

#define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))

#define S3C2440_MPLL_400MHZ ((0x5c<<12)|(0x01<<4)|(0x01))

#define WTCON 0x53000000 /*看门狗寄存器*/

#define BWSCON 0X48000000 /*BANK寄存器*/

.text /*设置代码段*/

.global _start /*定义全局变量,要被链接脚本用到*/

_start: /*_start跳转到这里实现硬件初始化*/

/* 1.关看门狗*/

ldr r0, =WTCON

mov r1, #0

str r1, [r0]

/* 2.设置时钟(必须设为异步总线模式) */

ldr r0, =CLKDIVN

mov r1, #5 /* FCLK:HCLK:PCLK=1:4:8 */

str r1, [r0]

mrc p15, 0, r1, c1, c0, 0 /*设置为asynchronous bus mode*/

orr r1, r1, #0xc0000000

mcr p15, 0, r1, c1, c0, 0

ldr r0, =MPLLCON /* 设置时钟频率FCLK为400MHZ */

ldr r1, =S3C2440_MPLL_400MHZ

str r1, [r0]

/* 3.使能ICache,加快指令访问速度;因为目前没有开启MMU,所以还不能开启数据缓存DCache */

mrc p15, 0, r0, c1, c0, 0 /* read control reg */

orr r0, r0, #(1<<12)

mcr p15, 0, r0, c1, c0, 0 /* write it back */

/* 4.初始化SDRAM */

ldr r0, =BWSCON

adr r1, sdram_config /* 使用adr跳转,因为SDRAM未初始化 */

add r3, r0, #(13*4)

1:

ldr r2, [r1], #4

str r2, [r0], #4

cmp r0, r3

bne 1b /*back to 1 when no equal*/

/* 4.重定位 */

ldr sp, =0x34000000 /*因为SDRAM大小为64MB,所以堆栈指针设在最高地址处*/

bl nand_init

mov r0, #0 /* src = r0 */

ldr r1, =_start /* dest = r1,_start为代码段的起始和链接地址0x30000000 */

ldr r2, =__bss_start

sub r2, r2, r1 /* len = r2,代码段长度*/

bl copy_code_to_sdram /* 调用C函数copy_code_to_sdram(src, dest, len)*/

bl clear_bss /* 清除bss段*/

/* 5.执行main */

ldr lr, =halt

ldr pc, =main

mov pc,lr /* 若main函数跳出后,使PC等于lr链接寄存器,避免程序跑飞 */

halt:

b halt /* 死循环,避免跑飞 */

sdram_config:

.long 0x22011110 //BWSCON

.long 0x00000700 //BANKCON0

.long 0x00000700 //BANKCON1

.long 0x00000700 //BANKCON2

.long 0x00000700 //BANKCON3

.long 0x00000700 //BANKCON4

.long 0x00000700 //BANKCON5

.long 0x00018005 //BANKCON6

.long 0x00018005 //BANKCON7

.long 0x008C04F4 // REFRESH

.long 0x000000B1 //BANKSIZE

.long 0x00000030 //MRSRB6

.long 0x00000030 //MRSRB7

关于时钟频率的设置解释:

将CPU频率设为最大值400MHZ(内核启动时间7S变为6S,因为HCLK和PCLK频率没有改变)

然后分频系数FCLK:HCLK:PCLK需要设置为1:4:8。

因为HCLK最高133MHZ,这里需要设置为100MHZ,PCLK最高50MHZ,所以这里需要设置为50HZ,所以得出 CLKDIVN寄存器需要等于0X5即可。

具体为什么等于0x5,可以参考下图:

d5594a3c2aff18b928304b0496aa167b.png

通过查看数据手册,得知当FCLK取400MHZ时,设置MDIV为0X5C,PDIV为0x1,SDIV为0x1。

关于Cache的设置解释:

通过高速缓存存储器可以加快对内存的数据访问,在CAHE中有ICAHE(指令缓存)和DCAHE(数据缓存):

ICAHE: 指令缓存,用来存放执行这些数据的指令;

DCAHE:用来存放数据,需要开启MMU才能开启DCAHE。

在没开启ICAHE之前,CPU读取SDRAM地址数据时,每次都需要先访问一次地址值,在读数据.

当开了ICAHE后,第一次读取SDRAM地址数据时,ICAHE发现缓存里没有这个地址数据,然后将SDRAM中需要读取的那部分一大块内存数据都复制在缓存中,后面陆续读取数据就不会再访问SDRAM了,直到CPU没有找到地址数据后ICAHE再从SDRAM中重新复制

通过CP15协处理器来开启ICAHE:ICAHE控制位在CP15的寄存器C1中位12(如下图), 然后通过MRS和MSR向该位12置1,开启ICAHE.所以代码如下(放在SDRAM初始化之前):

mrc p15, 0, r0, c1, c0, 0 //将 CP15 的寄存器 C1 的值读到 r0 中

orr r0, r0, #(1<<12) //将r0中位12置1

mcr p15,0, r0,c1,c0,0 //开启ICAHE

2、编写init.c,用于重定位,bss段清除,初始化NandFlash

(1)编写nand_init()函数

准备知识:

我使用的NandFlash型号为K9F2G08U0M,通过查阅芯片手册获知该flash大小=2048块Block=128KPages=256MB=2Gb 。且其构成为:

1个设备=2048(Block)

1块Block=64(Pages)

1页=(2K+64)(Byte) 因为每个地址里都存放了一个字节,所以用Byte表示,其中64B是存放ECC的OOB地址,(ECC:存放判断位反转的校验码)

2db6ec2b8188387e5d21f02d619b628b.png

写过程:

写页

生成校验码ECC

写校验码到OOB页中

读过程:

读出页数据,并计算当前数据的ECC

读出存在OOB页里的原始ECC

比较两个校验码,相同则读成功,不同则出现了位反转,需重新读取。

15a0a473d0afe580a3c61f9d91c4f5cf.png

58eb388a69cefa21d7bc5b18e568b7c0.png

确定通信时序:

48e7a3117a06d1167458389ebb92cd68.png

26076dae6c0cb78f8fb643ea2b0daa8c.png

61b537c979c7b4aee8b5926bff12e1ea.png

通过图2和图1可以看出:

tCS:等待芯片使能CE的时间, tCS=20nS

tCLS和tALS:等待WE(写信号)结束的时间, tCLS=tALS=15nS

tWP:WE(写信号)维持时间, tWP=15nS

tALH:等待命令写入成功的时间, tALH=5nS

tCLH:等待地址写入成功的时间, tCLH=5nS

通过查看2440芯片手册,nandflash时序图,需要设置TACLS,TWRPH0和TWRPH1

TACLS:属于等待WE(写信号)就绪的时间,对比图2得出TACLS= tCLS- tWP=0nS

TWRPH0:属于WE(写信号)的时间, 对比图2得出TWRPH0= tWP=15nS

TWRPH1:属于等待命令写入成功的时间,对比图2得出TWRPH1=tALH=tCLH=5nS

在NFCONF寄存器中设置这三个参数

TACLS[13:12] :表示Duration(持续时间)=HCLK*TACLS,由于Duration=0nS,所以TACLS=0

TWRPH0 [10:8] :表示D

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值