uboot源代码分析-及s3c2440移植

Uboots3c2440移植笔记

 

虚拟机:VMWare - Ubuntu 14.04.1

开发板:s3c2440

编译器:arm-linux-gcc

U-bootu-boot-2009.08.tar.bz2

 

一:下载适当的U-boot版本并解压并配置交叉编译工具链

1、ftp://ftp.denx.de/pub/u-boot/网站上下载u-boot-2009.08.tar.bz2,拷贝至ubuntu

2、运用test@ubuntu:~/Documents$ tar -jxvf u-boot-2009.08.tar.bz2 解压

 

二:uboot目录结构说明

 

 

Uboot移植思想:

由于本次实验使用了NandFlash启动Uboot,NandFlash传输方式为非总线式访问,在NandFlash上电后自动将4K复制到片内内存SRAM中,然后在将后续的NandFlash的数据拷贝到SDRAM中,故可将Uboot分为两个部分stage1 stage2

stage1 :代码通常放在cpu/xxxx/start.S文件中,用汇编语言写成;

Stage2 :代码通常放在lib_xxxx/board.c文件中,他用C语言写成。

 

 

 

三、U-boot源码分析

==================================stage1阶段===================================

1、由于u-boot官方并没有针对s3c2440soc的直接可用的源码,故我们选择与之相近的S3c2410soc作为分析

①分析首要工作是通过分析链接脚本lds文件来查找程序的入口 故在uboot\cpu\arm920t\u-boot.lds中可查看到内存分配结构

 

 

 

② 在链接脚本中我们可以清楚的看到uboot链接的第一个文件是start.S文件 故我们查看uboot\cpu\arm920t\start.S

 

1)在start.S文件中 第一步:建立异常向量表

 

 

 

 

(2)start.S文件中 第二步:保存各个内存段的入口地址

 

 

(3)start.S文件中 第三步:关看门狗 屏蔽所有中断 设置时钟

 

 

 

(4)start.S文件中 第四步:跳转至 使能icache mmu

 

 

 

 

(5)start.S文件中 第五步:跳转 初始化SDRAM                                                                                                                                                          uboot\board\samsung\smdk2410\lowlevel_init.c

 

 

(6)start.S文件中 第六步:重定位relocate flash4k拷贝到sdram

 

1uboot中默认为NORFLASH拷贝至SDRAM (我们需求nandflash 注释此段)

 

 

2、自写NANDFLASH拷贝至SDRAM代码 初始化nandflash控制寄存器

 

3、调用自写nandflashsdram拷贝函数 uboot\board\samsung\smdk2410\nand_read.c

 

 

4、*注:自写函数需要在makefile中加上函数文件以确保得到编译链接(修改:uboot\board\samsung\smdk2410\Makefile

 

 

5、*注:自写函数nand_read.cstart.s文件重定位完成前需要用到 故需保证链接在前4k  (修改:uboot\cpu\arm920t\u-boot.lds

 

 

 

(7)start.S文件中 第七步:重定位完成  设置栈指针

 

 

(8)start.S文件中 第八步:重定位完成  清bss段 跳转start_armboot

 

 

 

 

==================================stage2阶段===================================

2、完成在SRAM4k的基本初始化过后,跳转至SDRAM中执行第一个函数start_armboot,完成各个外设的初始化,最终进入main_loop死循环执行CMD

 

==========================进入start_armboot配置初始化项========================

 

①分析start_armboot, 地址:uboot\lib_arm\board.c

 

1)在start_armboot.c文件中 第一步:清global_databoard_info

 

1、此时大致可以看出SDRAM中空间的分布图为:(gd_t后紧接着bd_t内存空间 图未标出)

 

 

①:分析gd_t结构体(uboot/include/asm-arm/global_data.h ====>arm架构通用的h文件)

 

 

②:分析bd_t结构体(uboot/include/asm-arm/u-boot.h ====>arm架构通用的h文件

 

*注:通过上面分析,我们可以从gb_t结构体间接的得到  bd_t开发板信息内存,  env 数据内存, 跳转表jump table内存

···可初步获得以下信息:CPU时钟

                          串口波特率

                          RAM位置大小信息

                          环境变量数据区

                          uboot传参数据区

                          IP地址

                          机器码......................................

 

 

  

2)在start_armboot.c文件中 第二步:调用初始化函数序列

 

 

①:分析初始化函数序列数组init_sequence重点:设置了相关的gb_t中属性和bd_t中属性 uboot\lib_arm\board.c

 

 

 

 

3)在start_armboot.c文件中 第三步:清MALLOC堆区

 

 

 

4)在start_armboot.c文件中 第四步:初始化基本的外设

 

 

①:*注:在上述初始化过程中对env环境变量进行了初始化与重定位

 

env_relocate函数:uboot/common/Env_nand.c(由于我们是重定位到nandflash 故只分析了env_nand.c文件中的env_relocate函数)

 

 

 

 

 

 

5)在start_armboot.c文件中 第五步:后续初始化

 

 

6)在start_armboot.c文件中 第六步:进入死循环main_loop处理CMD

 

 

 

==============================进入main_loop 处理CMD==========================

1、main_loop函数是在start_armboot函数执行完成后进入的第二个函数,死循环执行用于接收用户输入CMD并解析执行

 

①分析main_loop, 地址:uboot\common\main.c

 

 

 

1)在main_loop.c文件中 第一步:设置UBOOT启动次数和限制次数

 

*注:启动次数限制可以被用户设置一个启动次数,然后保存在Flash存储器的特定位置,当到达启动次数后,U-Boot无法启动。该功能适合一些商业产品,通过配置不同的License限制用户重新启动系统

 

 

2)在main_loop.c文件中 第二步:初始化Modem功能

 

 

3)在main_loop.c文件中 第三步:设置Uboot版本信息

 

4)在main_loop.c文件中 第四步:初始化CMD自动完成和HUSH功能

 

*注:设置命令行自动完成功能,该功能与Linuxshell类似,当用户输入一部分命令后,可以通过按下键盘上的Tab键补全命令的剩余部分,如果为减少uboot编译后大小,可通过宏定义剪裁uboot补全功能

 

 

5)在main_loop.c文件中 第五步:设置延时启动时间、检查启动次数

 

 

 

 

5)在main_loop.c文件中 第五步:执行进入kernel或者菜单项

 

    ①:如果bootdelay中途未跳出 并且环境变量存在启动内核kernel命令(自写) 则调用该命令执行函数(实质:通过调用命令执行函数的方式调用了内核入口函数  进入内核kernel

 

        *注:分析怎样判断是否跳出delay延时,通过调用abortboot函数得到的返回值来判断 1:跳出 0:未跳出

             判断思路:在delay延时过程中,轮询查看标准输入设备stdin是否接收到字符,如若接收到,则判断用户按下某个键,中断延时,返回1,并将按键字符保存在menukey中   (按下空格键才会满足menukey == CONFIG_MENUKEY条件进入菜单项,否则进入死循环命令)

            分析:abortboot函数 地址 uboot\common\main.c

 

 

①:如果bootdelay中途跳出,则将用户按键的字符与空格键(默认)对比,匹配则进入菜单项

 

 

 

 

6)在main_loop.c文件中 第六步:接收执行用户输入命令

 

①:在接收到用户输入的命令后,就调用run_commmand函数执行 因此我们继续分析解析和执行命令的函数run_commmand  地址:uboot\common\main.c

    1.)解析命令 并分割字符串保存到argv数组中

 

 

        2、)在u_boot_cmd段中的命令结构体遍历匹配命令并执行

 

 

 

②:遍历匹配命令时,要通过在u_boot_cmd段中依次查找存储存储的命令结构体cmd_tbl_s ,故我们分析命令结构体的基本组成  地址:uboot\include\command.h

 

 

 

③:继续分析怎么将命令结构体存入到u_boot_cmd段中的,在uboot\common\command.h中我们可以发现U_BOOT_CMD宏定义

 

*注:##token(标号)连接符, #将变量转换为字符(变量两边加“”)

   __attribute__ ((unused,section (".u_boot_cmd"))) 表示将变量存在u_boot_cmd段中

 

 

④:自定义命令加入u_boot_cmd段中,思路就是用U_BOOT_CMD宏定义一个结构体变量,那么编译时就会将该结构体保存在u_boot_cmd段中,故命令uboot\common文件夹下c文件定义:下面以uboot\common\cmd_cache.c为例分析

    

    1、定义一个命令结构体并存储在u_boot_cmd

  

    

      2、定义命令所执行的函数do_icache,由结构体的属性定义所知 do_icache的函数类型必须满足int(*cmd)(struct cmd_tbl_s *, int, int, char *[]) 格式

 

 

3、在当前目录下的Makefile文件中添加目标文件cmd_cache.o确保该文件中变量能被编译链接

 

 

4、确保当前命令的宏定义开关为开启状态  所有命令的宏定义开关位于uboot\common\Config_cmd_all.h

 

 

总结:通过上述分析,我们可以初步的分析出执行命令的方式是死循环的从console中接受用户输入的CMD 并解析保存在argv数组中,然后在u_boot_cmd段中的结构体序列中遍历出所匹配的当前命令结构体,以便获得该命令要执行的函数指针,最终执行。

 

 

UBOOT移植JZ2440实战

 

1、解压uboot源码选择适当的uboot,由于2440并没有直接适配的uboot版本,故我们选择与之相近的samsung/smdk2410

 

2、进入/u-boot/board/samsung目录下 拷贝一份smdk2410并改名为my2440

 

 

 

 

3、进入my2440的目录下,修改必要的位置

  ①将my2440目录下的smdk2410.c文件名改为my2440.c

 

  ②更改对应的Makefile

 更改:

 

4、建立2440的头文件(里面存放在开发板相应的寄存器定义)

  ①进入uboot目录下的include/configs文件夹下

 

  ②建立一份my2440.h文件   直接拷贝smdk2410的头文件

 

 

5、uboot的根目录下的中Makefile中配置my2440的编译选项

 

说明:armCPU的架构

     arm920tCPU的类型

          my2440:对应board目录下的开发板目录

          Samsung:对应的board的厂商目录,如果没有厂商目录 写NULL

          S3c24x0cpu型号

注:编译选项第二行要Tab开始,因为去解释文档时要靠Tab字符定位,不写报错

 

 6、测试编译新建的my2440  出现以下字符则表示编译成功

 

 

 

1. 修改U-Boot Stage 1(汇编级)的平台相关代码

U-Boot第一阶段的代码包括:

(1) cpu/arm920t/start.S (平台无关,处理器架构相关,存放如u-boot.lds链接脚本文件)

(2) board/samsung/lowlevel_init.S (平台与处理器型号相关)

(3) board/samsung/config.mk (平台相关,设置TEXT_BASE)

(4) include/configs/my2440.h (平台相关,设置寄存器初值等)

 

四、根据ubootstage1stage2来具体分析启动流程

一般的ARM编译完整后 会调用外部的链接脚本进行相应的段分配,故我们可以通过lds链接文件来查看nandflash4k的代码(stage1阶段代码)分布情况

①查看make的编译信息可以看到链接脚本所在位置

 

②进入相应的文件夹 打开u-boot.lds

 

 

 

③故通过u-boot.lds我们发现最先放置在0x0地址处被运行的是cpu/arm920t/start.s

④运用source insight打开cpu/arm920t/start.s文件进行分析

 

 

 

 

你可能感兴趣的:(linux)