打印

U-Boot移植全程指导即将发布了,欢迎大家前来观赏

[复制链接]
1867|7
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
zh5202|  楼主 | 2014-10-22 17:32 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
        经过快一个月的时间,终于将U-Boot相关的知识全部总结在一起,从入门——>熟悉——>理解——>深入的方式进行讲解,最终达到可针对不同版本的U-Boot进行移植。下面贴出**的目录,供大家参考(其中标红文字表示还未完成的部分):


相关帖子

沙发
zh5202|  楼主 | 2014-10-22 17:32 | 只看该作者
五、U-Boot源码熟悉
5.1 U-Boot的配置过程
5.1.1 U-Boot配置命令展开
5.1.2 mkconfig脚本分析
5.1.3 板级配置文件介绍
5.2 U-Boot的编译过程
5.2.1 U-Boot编译命令展开
5.2.2 U-Boot编译流程
5.2.3 Makefile文件分析
5.3 U-Boot启动流程介绍
5.3.1 U-Boot分析之源码第1阶段
5.3.1.1 设置中断向量表:cpu/arm920t/start.S
5.3.1.2 设置CPU为SVC32模式:start.S
5.3.1.3 关看门狗、关中断及设置时钟频率:start.S
5.3.1.4 CPU相关部件初始化
5.3.1.5 存储控制器初始化:board/smdk2410/lowlevel_init.S
5.3.1.6 代码重定向:cpu/arm920t/start.S
5.3.1.7 设置堆栈:start.S
5.3.1.8 清除BSS段:start.S
5.3.1.9 跳入第二阶段C入口执行:start.S
5.3.2 U-Boot分析之源码第2阶段
5.3.2.1 定义并初始化gd_t及bd_t结构体:lib_arm/board.c
5.3.2.2 计算U-Boot映像的大小:board.c
5.3.2.3 循环调用初始化函数:board.c
5.3.2.4 内存及Flash初始化:board.c
5.3.2.5 配置环境变量重定位:board.c
5.3.2.6 初始化IP地址及控制终端等:board.c
5.3.2.7 进入main_loop()主循环
5.3.2.8 检测启动延时与启动中断
5.3.2.9 进入U-Boot控制终端
5.4 U-Boot之核心内容:命令实现
5.4.1 U-Boot命令的实现流程
5.4.1.1 U-Boot命令的定义
5.4.1.2 U-Boot命令实现
5.4.2 添加一个自己的命令
5.5 U-Boot之终极目标:启动内核
5.5.1 启动内核之映像拷贝
5.5.2 启动内核之启动内核
5.5.2.1 do_bootm()函数
5.5.2.2 do_bootm_linux()函数
5.5.2.3 TAG参数的设置
六、U-Boot的移植
6.1 U-Boot的移植步骤
6.1.1 U-Boot的移植步骤
6.1.2 U-Boot的调试方法
七、U-Boot源码详解
7.1 run_command()函数实现
7.2 环境变量的实现
        接下来稍作休息,准备开始自己编写一个Bootloader来启动Linux内核,到时候还可提供源码,主要讲解方法。只要你手上有开发板,就可以按照同样的步骤编写一个简单的只为启动Linux内核为目的的Bootloader。
        然后再针对比较老版本的U-Boot和较新版本的U-Boot进行移植,提供移植的全过程详解。为大家提供移植U-Boot的全程讲解,希望能给大家的工作带来很大的帮助。
       最后,对于U-Boot中,一些比较好的功能实现(在内核中也有对应功能的实现,但代码不是很好理解)的源码进行分析,通过对这块的学习,可以加深自己阅读源代码的能力。更重要的是可以提高看Linux内核源代码的能力。
      总之,希望得到大家的鼎立支持!

使用特权

评论回复
板凳
zh5202|  楼主 | 2014-10-22 17:35 | 只看该作者
自己首先顶一个,整个文档很简介,挑选重点进行讲解,但又不至太难,以通俗的语言进行解释,再结合源代码进行分析。。。
嗯。。。这爽劲。。。
当前文档已经才58页,加上自己编写Bootloader章节及两个版本U-Boot的移植,应该会有100页左右。

使用特权

评论回复
地板
zh5202|  楼主 | 2014-10-22 17:48 | 只看该作者
不好意思哈,这里只是贴出了目录,是看不到具体内容的。下面贴出5.5.1小结的实际内容,供大家参考:
5.5.1 启动内核之映像拷贝
        实现内核拷贝的命令为:
nand read 0x30007fc0 0x60000 0x200000;
        其中,nand read表示使用nand操作命令,也说明内核保存在nand flash中;0x30007fc0表示要拷贝到内存的目标位置;0x60000表示内核在nand flash的偏移量;0x200000表示内核的大小。这里需要说明,0x60000 0x200000可以使用分区的名字代替,比如:
nand read 0x30007fc0 kernel;
        对于PC机而言每块硬盘的开始都有一块分区表,而嵌入式的nand flash是没有分区表的,那么nand flash的分区实现就只能在源代码中写死固定。因此,我们关心的是各个分区的起始地址(便宜地址)和大小,因此以上两种写法都是可以的。下面是一个分区的定义方法include/configs/xxxx.h配置文件中:
#define MTDPARTS_DEFAULT “mtdparts=nandflash0:256k@0(bootloader)”
                           “128k(params)”
                           “2m(kernel)”
                           “-(root)”
        那么如上命令是如何将内核拷贝到内存中去的呢?接下来看nand命令的函数实现do_bootm()。命令定义如下:
/* common/cmd_nand.c */
U_BOOT_CMD(nand, 5, 1, do_nand,
        "nand    - NAND sub-system\n",
        "info                  - show available NAND devices\n"
        "nand device [dev]     - show or set current device\n"
        "nand read[.jffs2]     - addr off|partition size\n"
        "nand write[.jffs2]    - addr off|partiton 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 dump[.oob] off - dump page\n"
        "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
        "nand markbad off - mark bad block at offset (UNSAFE)\n"
        "nand biterr off - make a bit error at offset (UNSAFE)\n"
        "nand lock [tight] [status] - bring nand to lock state or display locked pages\n"
        "nand unlock [offset] [size] - unlock section\n");
-------------------------------do_nand()函数开始-------------------------------------------
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
{
        int i, dev, ret;
        ulong addr, off, size;
        char *cmd, *s;
        nand_info_t *nand;
        int quiet = 0;
        const char *quiet_str = getenv("quiet");
       
        /* at least two arguments please */
        if (argc < 2)
                goto usage;
        if (quiet_str)
                quiet = simple_strtoul(quiet_str, NULL, 0) != 0;
       
        cmd = argv[1];  //获取命令的第二个参数
        . . .
        /* 第二参数验证 */
        if (strcmp(cmd, "bad") != 0 && strcmp(cmd, "erase") != 0 &&
            strncmp(cmd, "dump", 4) != 0 &&
            strncmp(cmd, "read", 4) != 0 && strncmp(cmd, "write", 5) != 0 &&
            strcmp(cmd, "scrub") != 0 && strcmp(cmd, "markbad") != 0 &&
            strcmp(cmd, "biterr") != 0 &&
            strcmp(cmd, "lock") != 0 && strcmp(cmd, "unlock") != 0 )
                goto usage;
               
        /* the following commands operate on the current device */
        if (nand_curr_device < 0 || nand_curr_device >= CFG_MAX_NAND_DEVICE ||
            !nand_info[nand_curr_device].name) {
                puts("\nno devices available\n");
                return 1;
        }
        /* 获取当前的nand flash */
        nand = &nand_info[nand_curr_device];
        . . .
        /* read write :读写操作 */
        if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
                int read;  /* 用于保存是读还是写操作 */
                if (argc < 4)
                        goto usage;
                /* 取出内存目标地址 */
                addr = (ulong)simple_strtoul(argv[2], NULL, 16);
                /* 判断是读还是写 */
                read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
                printf("\nNAND %s: ", read ? "read" : "write");
                /* 取出偏移量和大小 */
                if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
                        return 1;
                s = strchr(cmd, '.');  /* 取出第二个参数的后半部 */
                if (s != NULL &&
                    (!strcmp(s, ".jffs2") || !strcmp(s, ".e") || !strcmp(s, ".i"))) {
                        if (read) {
                                /* read */
                                nand_read_options_t opts;
                                memset(&opts, 0, sizeof(opts));
                                opts.buffer        = (u_char*) addr;
                                opts.length        = size;
                                opts.offset        = off;
                                opts.quiet      = quiet;
                                ret = nand_read_opts(nand, &opts);
                        } else {
                                /* write */
                                nand_write_options_t opts;
                                memset(&opts, 0, sizeof(opts));
                                opts.buffer        = (u_char*) addr;
                                opts.length        = size;
                                opts.offset        = off;
                                /* opts.forcejffs2 = 1; */
                                opts.pad        = 1;
                                opts.blockalign = 1;
                                opts.quiet      = quiet;
                                ret = nand_write_opts(nand, &opts);
                        }
                } else {
                        if (read)
                                ret = nand_read(nand, off, &size, (u_char *)addr);
                        else
                                ret = nand_write(nand, off, &size, (u_char *)addr);
                }
                printf(" %d bytes %s: %s\n", size,
                       read ? "read" : "written", ret ? "ERROR" : "OK");
               
                return ret == 0 ? 0 : 1;
        }  /* nand read write 执行完毕 */
        . . .
}
        最终调用nand_read_opts()/nand_read()函数将Linux内核从Nand Flash中的off处读取off长度的数据到内存的addr地址。详细的nand_read()函数在这里不讲解。

使用特权

评论回复
5
scottly| | 2014-10-22 18:03 | 只看该作者
楼主一步步来啊,怎么一下跳到5了,快更新

使用特权

评论回复
6
hongyancl| | 2014-10-23 09:00 | 只看该作者
楼主一步一步来啊

使用特权

评论回复
7
dyg540| | 2014-10-25 10:47 | 只看该作者
这个应该不错的

使用特权

评论回复
8
rxia| | 2015-4-8 18:40 | 只看该作者
等了很久了。。。。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:Need to harder study!Thank you for everyone had helped me.

5

主题

248

帖子

2

粉丝