目标:

1   添加头文件setup.h和serial.h

2   写main函数  

2.1 帮内核设置串口0, (内核启动会打印出启动信息)

2.2把内核读入到SDRAM

2.3设置参数(参考u-boot-1.1.6 /lib_arm/armlinux.C中do_bootm_linux()函数)

2.4跳转运行内核(参考u-boot-1.1.6/lib_arm/armlinux.C中do_bootm_linux()函数)

3 写tag参数函数

3.1 setup_start_tag (void);

3.2 setup_memory_tags(void);

3.3 setup_commandline_tag (char *cmdline);

3.4 setup_end_tag (void);

 4 写makefile文件

1 添加头文件setup.hserial.h

1.1     将lcd裸板程序中串口uart0初始化文件serial.c复制到my_bootloader目录中.并修改serial.c

1.2      因为TAG结构体定义是存在u-boot-1.1.6/include/asm-arm/setup.h中,所以设置TAG参数需要用到这个文件,将setup.h复制到my_bootloader目录中.

1.2.1  修改setup.h文件

删除以下不需要的代码:

#define __tag __attribute__((unused, __section__(".taglist")))

#define __tagtable(tag, fn) \

static struct tagtable __tagtable_##fn __tag = { tag, fn }

#define tag_member_present(tag,member)                                \

         ((unsigned long)(&((struct tag *)0L)->member + )  \

                   <= (tag)->hdr.size * )

添加以下代码:

#define  u32  unsigned  long
#define u16 unsigned int
#define u8 unsigned char

2. 新建my_bootloader/boor.c,用于存放main函数(main:由start.S跳转过来的).

main函数代码如下:

void main(void)

{

void (*theKernel)(int zero, int arch, unsigned int params); 

/*定义一个函数指针theKernel,其中第一个参数zero:0           */

/* arch:机器ID ,由于芯片类型很多,内核为了辨别芯片而定义的机器ID,其中2440芯片的ID号是362,*/

/* params :tag参数位置,这里我们的tag起始地址=0x30000100*/



  /*1 初 始 化 串 口 0 , 使 内 核 能 打 印 信 息  */

  uart0_init();                                             //调用serial.h头文件里的uart0_init()
puts(“uart0 init OK\r\n”); //打印uart0初始化 /*2从 nand flash 里 把 内 核 复 制 到 SDRAM 中 */ puts(“copy kernel from nand\r\n”); //打印内核复制
nand_read((0x60000+),0X30008000,0X200000); //烧写2MB,多烧写点避免出错 /* 0x60000+64:表示内核在nand(存储)地址上位置, 0X30008000:内核在sdram(运行)地址上位置 0X200000:内核长度2MB 因为Flash上存的内核格式是:uImage(64B头部(header) + 真正的内核 ) 在uboot界面中输入mtd命令可以看到: kernel分区位于 nand的0X00060000~0x00260000 所以在nand中真正的内核地址=0x60000+64, 在uboot界面中输入boot命令可以看到: Data Size: 1848656 Bytes =1.8 MB Load Address: 30008000 所以内核目的地址=0X30008000 长度=1.8MB */ /*3 设 置 T A G 参 数 */ puts(“set boot params\r\n”); //打印设置参数信息
setup_start_tag (void); //在0X30000100地址保存start_tag数据,
setup_memory_tags (void); //保存memory_tag数据,让内核知道内存多大
setup_commandline_tag (“boottargs=noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0”);
/*保存命令行bootargs参数,让内核知道根文件系统位置在/dev/mtdblock3,指定开机运行第一个脚本/linuxrc,指定打印串口0*/
setup_end_tag (void); //初始化tag结构体结束 /* 4 跳 转 执 行 */ puts(“boot kernel\r\n”); //打印启动内核
theKernel = (void (*)(int, int, unsigend int))0x30008000;
// 设置theKernel地址=0x30008000,用于后面启动内核
theKernel(,,0x300000100); //362:机器ID, 0x300000100: params(tag)地址
/*传递参数跳转执行到0x30008000启动内核, */
/*相当于: mov r0,#0 */
/*ldr r1,=362 */
/*ldr r2,= 0x300000100 */
/*mov pc,#0x30008000 */ puts(“kernel ERROR\r\n”); //打印内核启动出错 }

3.创建TAG参数函数(使main函数调用)

设置tag参数函数代码如下

#include “setup.h”              

static struct tag *params;               //定义个tag结构体变量params指针

setup_start_tag (void)                    //开始tag
{
params = (struct tag *) 0x30000100; //tag起始地址等于0X30000100
params->hdr.tag = ATAG_CORE; //头部常量tag=0x54410001
params->hdr.size = tag_size (tag_core); //size=5, params->u.core.flags = ;
params->u.core.pagesize = ;
params->u.core.rootdev = ;

params = tag_next (params); //parmas=( struct tag *)((u32 *)parmas+ params->hdr.size)
} // setup_start_tag (bd)保存tag参数如下:
setup_memory_tags (void) //内存tag
{ int i;
params->hdr.tag = ATAG_MEM; //头部常量tag=0x54410002
params->hdr.size = tag_size (tag_mem32); //size=4
params->u.mem.start = 0x30000000; //SDRAM起始地址
params->u.mem.size = 0x4000000; //SDRAM内存大小64M
params = tag_next (params); //指向下个tag
} // setup_memory_tag s(bd)保存tag参数如下: int strlen(char *str) //uboot不依赖任何库,所以需要自己写strlen函数
{
int i=;
while(str[i])
{
i++;
}
return i;
} void strcpy(char *dest, char *src)
{
while((*dest++=*src++)!=’\’&&*dest!=’\’);
} setup_commandline_tag (char *cmdline) //命令行tag
/**cmdline :指向命令行参数 */
/*一般为:“boottargs=noinitrd root=/dev/mtdblock3 init=/linuxrc console=ttySAC0” */
{
int len=strlen(cmdline)+; //计算cmdline长度,并加上结束符
params->hdr.tag = ATAG_CMDLINE; //头部常量tag=0x54410009
params->hdr.size =(sizeof (struct tag_header) +len+) >> ; /*size=(字符串长度+头部长度) >>2 */
/*“+3”表示:按4字节对齐,比如当总长度=(1,2,3,4)时,size=(总长度+3)>>2=1,实现4字节对齐 */
strcpy (params->u.cmdline.cmdline, cmdline); //复制形参字符串到params->u.cmdline.cmdline
params = tag_next (params); //执行下个tag
} setup_end_tag (void) //结束tag
{
params->hdr.tag = ;
params->hdr.size = ;
}

4 写makefile文件

4.1 首先将lcd裸板程序里的makefile复制到my_bootloader目录中,并修改.

备注:在makefile中‘=’与‘:=’的区别:

‘=’:无关位置的等于(比如:”x=a  y=$(x)  x=b”,那么y的值永远等于最后的值,等于 b ,而不是a)

‘:=’:有关位置的等于(比如:”x:=a  y:=$(x)  x:=b”,那么y的值取决于当时位置的值,等于 a ,而不是b)

代码如下:

CC      = arm-linux-gcc               //定义CC变量=arm-linux-gcc,简化书写,编译命令,(*.C,*.S)文件生成*.O文件

LD      = arm-linux-ld                 //连接命令,将多个*.O文件生成 boot.elf       

AR      = arm-linux-ar                 //库管理命令,这里没有用到 

OBJCOPY = arm-linux-objcopy            //复制/格式转换命令, boot.elf生成boot.dis

OBJDUMP = arm-linux-objdump           //反汇编命令,boot.bin生成boot.dis

CFLAGS           := -Wall -O2         //GCC编译参数,-Wall:显示所有错误和警告, -O2:采用2级编译优化

CPPFLAGS     := -nostdinc -fno-builtin       

//添加头文件参数,-nostdinc忽略缺省目录, -fno-builtin不连接系统标准启动文件和标准库文件(表示不用自带的strlen()等库函数)

objs := start.o init.o boot.o                     //定义objs变量,包含生成boot.bin目标文件需要的依赖文件

boot.bin: $(objs)                      //执行生成目标文件,首先是先满足objs所有依赖文件都拥有,才执行

         ${LD} -Tuboot.lds -o boot_elf $^

         ${OBJCOPY} -O binary -S boot_elf $@

         ${OBJDUMP} -D -m arm boot_elf > boot.dis

%.o:%.c                                //%通配符。生成xxx.o文件先要找到xxx.c文件

         ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<   //-c编译不连接。$@表示目标文件   $<表示第一个依赖文件

%.o:%.S

         ${CC} $(CPPFLAGS) $(CFLAGS) -c -o $@ $<

clean:

         rm -f *.bin *.elf *.dis *.o

第2阶段——编写uboot之启动内核和制作Makefile(2)的更多相关文章

  1. 第2阶段——编写uboot之硬件初始化和制作链接脚本lds(1)

    目标: 1.关看门狗 2.设置时钟 3.初始化SDRAM (初始化寄存器以及清除bss段) 4.重定位 (将nand/nor中代码COPY到链接地址上,需要初始化nandflash,读flash) 5 ...

  2. uboot如何启动内核

    2.7.1.uboot和内核到底是什么 2.7.1.1.uboot是一个裸机程序 (1)uboot的本质就是一个复杂点的裸机程序.和我们在ARM裸机全集中学习的每一个裸机程序并没有本质区别. 2.7. ...

  3. 第2阶段——编写uboot之编译测试以及改进(3)

    编译测试: 1.将写好的uboot复制到linux下面 2.make编译,然后将错误的地方修改,生成boot.bin (编译出错的解决方案:http://www.cnblogs.com/lifexy/ ...

  4. UBOOT启动内核过程

    1.摘要 (1).启动4步骤第一步:将内核搬移到DDR中第二步:校验内核格式.CRC等第三步:准备传参第四步:跳转执行内核(2).涉及到的主要函数是:do_bootm和do_bootm_linux(3 ...

  5. uboot学习之五-----uboot如何启动Linux内核

    uboot和内核到底是什么?uboot实质就是一个复杂的裸机程序:uboot可以被配置也可以做移植: 操作系统内核本身就是一个裸机程序,和我们学的uboot和其他裸机程序没有本质的区别:区别就是我们操 ...

  6. u-boot向linux内核传递启动参数(详细)

    U-BOOT 在启动内核时,会向内核传递一些参数.BootLoader 可以通过两种方法传递参数给内核,一种是旧的参数结构方式(parameter_struct),主要是 2.6 之前的内核使用的方式 ...

  7. uboot代码2:stage2代码,启动内核

    一.uboot最终目的: 1.读出内核 do_nand read kernel { flash上存的内核:uImage = 头部 + 真正的内核; } 2.启动内核. do_bootm_linux { ...

  8. u-boot向linux内核传递启动参数

    U-BOOT 在启动内核时,会向内核传递一些参数.BootLoader 可以通过两种方法传递参数给内核,一种是旧的参数结构方式(parameter_struct),主要是 2.6 之前的内核使用的方式 ...

  9. linux的几个内核镜像格式Image 和 u-boot启动内核和文件系统时的一些环境变量的设置

    关于编译powerpc linux的几个Image参考原文 http://blog.sina.com.cn/s/blog_86a30b0c0100wfzt.html 转载▼   PowerPC架构 L ...

随机推荐

  1. mk框架,一个基于react、nodejs全栈框架

    在这个前端技术爆炸的时代,不自己写套开源框架出门都不好意思跟别人打招呼,作为一个前端领域的小学生,去年年初接触了react,之后一发不可收拾爱上了它,近期重构了自己去年开源的一个项目,废话到此结束句号 ...

  2. caffe数据读取的双阻塞队列说明

    caffe的datareader类中 class QueuePair { public: explicit QueuePair(int size); ~QueuePair(); BlockingQue ...

  3. Cocoapods 应用第二部分-私有库相关

    我们在这里,使用的是 第一部分使用pod lib create YohunlUtilsPod 创建的framework工程来说明.其创建过程在此就不重复了,当然你也可以下载我已经创建好的demo ht ...

  4. 2.ssh密钥登陆(ssh无密码登陆)

    1.A主机生成密钥对 ssh-keygen  -t  rsa 2.将A主机的公钥发给B主机 scp  id_rsa.pub  linux2:/cloud                         ...

  5. bitset基础用法+心得

    今天上午听AntiLeaf学长讲课,获悉了bitset这种神奇的操作,还是大喊一句:stl大法吼啊! bitset是用来进行一些状态储存的操作.类似于一个标记数组,又类似于状压里面的二进制. 它与状压 ...

  6. CentOS 6.5安装JDK、Tomcat、Mysql

    安装JDK 1.下载JDK7 下载jdk-7u79-linux-x64.tar.gz 百度网盘下载地址:https://pan.baidu.com/s/1c1JZo2k 在Linux上新建/usr/j ...

  7. iOS 横竖屏切换解决方案

    iOS要实现横竖屏切换很简单,不需要使用任何第三方,只需要实现几个方法就可以了. 1.设置系统支持横竖屏[General]->[Targets]-> [Deployment info]-& ...

  8. Shell - 简明Shell编程

    本文是对Shell脚本编程的总结和回顾,所有涉及的脚本均已做了基本的调试和验证. [toc] 测试环境信息 [root@CentOS7 ~]# uname -a Linux CentOS7 3.10. ...

  9. JFFS2文件系统的移植

    Linux文件系统的移植-JFFS2 JFFS2是JFFS的后继者,由Red Hat重新改写而成.JFFS2的全名为JournallingFlash File System Version 2(闪存日 ...

  10. 前端应该知道的Web Components

    前端组件化的痛点 在前端组件化横行的今天,确实极大的提升了开发效率.不过有一个问题不得不被重视,拟引入的这些html.css.js代码有可能对你的其他代码造成影响. 虽然我们可以通过命名空间.闭包等一 ...