跟着韦东山老师学习JZ2440 u_boot的编写。
今天我们自己写一个简易的u_boot来启动kernel。
u_boot的启动流程我们默认分为两个阶段:
第一阶段 硬件驱动配置。
第二阶段 u_boot启动参数设置。
接下来我们先分析一下:
硬件驱动配置:
硬件启动流程
1、关看门狗。
2、设置CPU的工作时钟频率。(目前设置时钟工作频率是200MHz)
3、初始化SDRAM。
4、重定向代码。(当代码段大于4K的时候,需要把代码段从nand flash拷贝到sdram中运行)
这些工作主要在start.S中完成。关于nand flash的内容我们放到init.c中执行。
接下来上代码:
start.S
/**
******************************************************************************
* @file : start.S
* @version : none
* @date : 2019-12-16
* @brief : init JZ2440 Board peripheral
******************************************************************************
* @attention : JZ2440 EVAL BOARD
* @author : shao
* @personal : shao work stdio
******************************************************************************
*/
/**
* 注:init.S主要用来初始化第一阶段的硬件。
* 全部由汇编编写。
*/
#define S3C2440_MPLL_200MHZ ((0x5c<<12)|(0x01<<4)|(0x02))
#define MEM_CTL_BASE 0x48000000
.text
.global _start
_start:
/* 1. 关看门狗 */
ldr r0, =0x53000000
mov r1, #0x00
str r1, [r0]
/* 2. 设置时钟 */
ldr r0, =0x4C000014
mov r1, #0x03 // FCLK:HCLK:PCLK = 1:2:4
str r1, [r0]
/* 当FLCK != HCLK时, CPU必须由Fast mode改为 Asynchronous mode */
mrc p15, 0, r1, c1, c0, 0 /* 读出控制寄存器 */
orr r1, r1, #0xc0000000 /* 设置为“asynchronous bus mode” */
mcr p15, 0, r1, c1, c0, 0 /* 写入控制寄存器 */
/* MPLLCON = S3C2440_MPLL_200MHZ */
ldr r0, =0x4C000004
ldr r1, =S3C2440_MPLL_200MHZ
str r1, [r0]
/* 3. 初始化SDRAM(运行内存,代码重定位用) */
ldr r0, =MEM_CTL_BASE
adr r1, sdram_config /* sdram_config函数的当前地址 */
add r3, r0, #(13*4) /* 求和: r3 = r0+13*4 */
/* 循环向 MEM_CTL_BASE到MEM_CTL_BASE + 13*4的寄存器写入数据*/
1:
ldr r2, [r1], #4 /* r2=r1, r1地址加4 */
str r2, [r0], #4 /* r0=r2, r0地址加4 */
cmp r0, r3 /* 比较r0, r3是否相等 */
bne 1b /* 若果r0, r3 不相等,那么继续回到1b */
/* 4. 重定位 */
ldr sp, =0x34000000
bl nand_init
mov r0, #0 //传参的起始地址
ldr r1, =_start //srcAddr代码起始地址
ldr r2, =__bss_start //代码结束地址
sub r2, r2, r1 //代码长度,r2=r2-r1
/* 汇编调用C的时候,可以用r0~r3来传参数
* param1:r0
* param2: r1
* param3: r2
*/
bl copy_code_to_sdram
bl clear_bss
/* 5. 执行main */
ldr lr, =halt
ldr pc, =main
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
然后是init.c。在这里我们需要init一下uart,方便调试和信息输出。
/**
******************************************************************************
* @file : init.c
* @version : none
* @date : 2019-12-16
* @brief : init JZ2440 Board peripheral
******************************************************************************
* @attention : JZ2440 EVAL BOARD
* @author : shao
* @personal : shao work stdio
******************************************************************************
*/
/* NAND FLASH控制器 */
#define NFCONF (*((volatile unsigned long *)0x4E000000))
#define NFCONT (*((volatile unsigned long *)0x4E000004))
#define NFCMMD (*((volatile unsigned char *)0x4E000008))
#define NFADDR (*((volatile unsigned char *)0x4E00000C))
#define NFDATA (*((volatile unsigned char *)0x4E000010))
#define NFSTAT (*((volatile unsigned char *)0x4E000020))
//==========================串口设置=====================