uboot分析之板卡初始化和启动内核

start.s完成后,跳转到start_armboot继续执行相关操作。

1.gd相关初始化。放在sdram中,记录一些相关信息。如环境变量等,下面会用到。

2.nor falsh识别及初始化

flash_init
    flash_detect_legacy (BANK_BASE(i), i) //jedec协议查找flash类型
        cmdset_intel_read_jedec_ids //获取厂家ID和设备ID
            	manufacturer_id = flash_read_uchar (info,MANUFACTURER_ID);//厂家ID
                device_id = flash_read_uchar (info,FLASH_OFFSET_DEVICE_ID); //设备ID
        jedec_flash_match(info, base)//得到厂家ID和设备ID后,进行匹配.
        //根据厂家ID和设备ID获取 名字,位宽,大小,flash区域信息
        /*******************************match array**********************************/
    		.mfr_id		= MANUFACTURER_AMD,
		    .dev_id		= AM29DL800BT,
		    .name		= "AMD AM29DL800BT",
		    .uaddr		= {
			    [0] = MTD_UADDR_0x0AAA_0x0555,  /* x8 */
			    [1] = MTD_UADDR_0x0555_0x02AA,  /* x16 */
		    },
		    .DevSize	= SIZE_1MiB,
		    .CmdSet		= P_ID_AMD_STD,
		    .NumEraseRegions= 6,
		    .regions	= {
			    ERASEINFO(0x10000,14),
			    ERASEINFO(0x04000,1),
			    ERASEINFO(0x08000,1),
			    ERASEINFO(0x02000,4),
			    ERASEINFO(0x08000,1),
			    ERASEINFO(0x04000,1)
                }
	    ***************************************************************************/
    flash_get_size//如果查找不到,就用cfj协议继续查找。
         __flash_detect_cfi // cfi 协议
                flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP, 'Q') //读Q
                flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 1, 'R')//读R
                flash_isequal (info, 0, FLASH_OFFSET_CFI_RESP + 2, 'Y') //读Y

3.nand falsh识别及初始化

nand_init
    nand_init_chip(&nand_info[i], &nand_chip[i], base_address[i]);
        board_nand_init(nand);//将片选,读写,判断读写完成命令,写到chip中。知道怎么发。最终给MTD
            s3c24x0_nand_inithw();//填好时序
            chip->IO_ADDR_R    = (void *)&s3c2410nand->NFDATA; //读flash
            chip->IO_ADDR_W    = (void *)&s3c2410nand->NFDATA; //写flash
            chip->hwcontrol    = s3c2410_nand_hwcontrol; 
            chip->dev_ready    = s3c2410_nand_devready;
            chip->select_chip  = s3c2410_nand_select_chip; //选中
        nand_scan(mtd, 1);
            struct nand_chip *this = mtd->priv;
            this->select_chip = nand_select_chip;//构造片选
            this->cmdfunc = nand_command;//构造命令
            this->select_chip(mtd, 0); //选中
            this->cmdfunc (mtd, NAND_CMD_READID, 0x00, -1);//发命令 cle信号
            nand_maf_id = this->read_byte(mtd);//读取厂家ID
            nand_dev_id = this->read_byte(mtd);//读取设备ID
            //相关oob设置
            mtd->read = nand_read;
            mtd->write = nand_write;  //MTD层应用chip中函数,组成MTD协议。知道如何发   

4.环境变量

4.1 环境变量初始化及重定位

    a. 从heap中分配一段空间,用于env_t结构
     b. 找到环境变量(或从内存中找或从nand中找),填充env_t结构
     c. 将gd->env_addr指向env_ptr->data。

env_init(void) // 先看开始循环体中此函数做了什么
	gd->env_addr  = (ulong)&default_environment[0]; //使用默认的环境变量
	gd->env_valid = 1; //valid

env_relocate //环境变量重定位。从nandflash的params分区中考到内存中
    env_ptr = (env_t *)malloc (CFG_ENV_SIZE); //从heap中分配一段内存
    env_relocate_spec ();
/**************************smdk2410_config.h*********************/
        #define CFG_ENV_IS_IN_NAND  1
        #define CFG_ENV_OFFSET      0x40000
        #define CFG_ENV_SIZE		0x20000	/* Total Size of Environment Sector */
/****************************************************************/
        tmp_env1 = (env_t *) malloc(CFG_ENV_SIZE);
        nand_read(&nand_info[0], CFG_ENV_OFFSET, &total,(u_char*) tmp_env1);//从nand中读取环境变量
       	free(env_ptr); //crc验证OK,释放开始的默认堆中分配的环境变量
        env_ptr = tmp_env1;//ok,把目前存放环境变量的地址赋给全局指针变量
    gd->env_addr = (ulong)&(env_ptr->data);// 把环境变量的数据指针保存在gd中

4.2 获取环境变量(以启动kernel为例)

/*就以bootcmd为例
#define CONFIG_BOOTCOMMAND	"nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0"
uboot输入 print后会显示:
bootcmd=nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0
下面分析 如何获取环境变量:
首先想到的是匹配名字,如先查找bootcmd,然后解析后面的内容。
*/
s = getenv ("bootcmd");
    val=envmatch((uchar *)name, i) //进行名字匹配,直到匹配成功
    return ((char *)env_get_addr(val)); //返回“=”后面的地址
//现在s = “nand read.jffs2 0x30007FC0 kernel; bootm 0x30007FC0”

4.3执行环境变量中的命令(以启动kernel为例)

//分析执行环境变量中的参数
run_command (s, 0);
    //首先分割字符串。;一行命令结束标志
    process_macros (token, finaltoken);
    parse_line (finaltoken, argv);//按照 ‘ ’,‘\t’分割字符串。放到argv[]中
    cmdtp = find_cmd(argv[0]);//查找命令
        // __u_boot_cmd_start放置在lds中,会在这段内存中查找,匹配名字
	    for (cmdtp = &__u_boot_cmd_start;cmdtp != &__u_boot_cmd_end;cmdtp++) 
    (cmdtp->cmd) (cmdtp, flag, argc, argv);//执行命令

//分析上面字符串,第一个命令时nand。根据“nand”名字匹配,找到do_nand函数。
//nand read.jffs2 0x30007FC0 kernel。从kernel分区中读到0x30007FC0内存中
U_BOOT_CMD(
    nand,   5,  1,  do_nand,
    "nand    - legacy NAND sub-system\n",
    "info  - show available NAND devices\n"
    "nand device [dev] - show or set current device\n"
    "nand read[.jffs2[s]]  addr off size\n"
    "nand write[.jffs2] addr off size - read/write `size' bytes starting\n"
    "    at offset `off' to/from memory address `addr'\n"
    "nand erase [clean] [off size] - erase `size' bytes from\n"
    "    offset `off' (entire device if not specified)\n"
    "nand bad - show bad blocks\n"
    "nand read.oob addr off size - read out-of-band data\n"
    "nand write.oob addr off size - read out-of-band data\n"
);
#define Struct_Section  __attribute__ ((unused,section (".u_boot_cmd")))
#define U_BOOT_CMD(name,maxargs,rep,cmd,usage,help) \
cmd_tbl_t __u_boot_cmd_##name Struct_Section = {#name, maxargs, rep, cmd, usage, help}


//bootm 0x30007FC0.从0x30007fc0boot kernel
同样按照上述方法查找到 执行do_bootm
do_bootm
    memmove (&header, (char *)addr, sizeof(image_header_t)); // 64字节uImage头
    switch (hdr->ih_comp)//根据头文件指示进行解压缩
    switch (hdr->ih_os)//Operating System	
        	    do_bootm_linux  (cmdtp, flag, argc, argv,addr, len_ptr, verify);//我们是linux
                    setup_start_tag (bd);//设置tag。uboot和kernel进行交接
                    setup_memory_tags (bd);//memroy
                    setup_end_tag (bd);//结束
                    theKernel (0, bd->bi_arch_number, bd->bi_boot_params);//机器ID,tag。uboot完成了最终的使命。

到此uboot算完事了。最重要的就是获取环境变量和分析并run_command命令。进入uboot,可以按help查看当前uboot支持哪些命令。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值