移植uboot

我们这里将会介绍uboot的移植过程 我们以韦东山的uboot版本为材料 linux内核是3 版本进行讲解。

Uboot

下载下来uboot之后进行解压 然后我们需要知道底下的几个命令:

在readme中 我们可以知道利用make XXX_config ()其中XXX是板子的命名)我们就可以建立这个板子的设置了 我们的开发板是s3c2440 所以我们理应命令make s3c2440_config 但是uboot现在不支持2440  他只是支持2410 所以我们需要首先利用2410建立对2440板子的支持

 

那么既然使用make XX_config 来配置不同的板子 在board.cfg 这个文件 可以查看到利用make XX_config 之后make file会调用某一个板子的信息

 

在这里我们可以发现这里面的每一个列的意思是:Target, Arch, CPU, Board, name, Vendor, SOCOption.

 

仔细阅读Readme 的file tree 我们复制smdk2410的所有文件给smdk2440. 我们需要复制的文件是:

  1. board/Samsung 我们复制2410 文件夹 2440 这样子我们就有了专门给2440芯片
  2. 在uboot/include/configs 我们可以复制smdk2410.h 到smdk2440.h

这样子我们基本上 建立了一个基于smdk2440的uboot

 

让我们编译一下 make smdk2440_config 这个uboot烧到板子里面 我们会发现这里并不会启动板子。我们还是需要修改程序来使得这个uboot可以

 

所有的程序烧到板子上都必须首先配置如下的东西:

1. 时钟              //这样子我们就可以让程序在芯片上运转

2. 内存             //这样子我们就可以代码重定位以及所有的代码拷入内存

3. 串口 //这是为了看到打印出的信息

4. nandflash         //一般我们会把代码拷入nandflash arm启动的时候 芯片自动把前面4k拷贝到芯片内部的内存 好让我们做代码重定位.芯片不能直接读取nandflash里面的内容。上电时候芯片会读取自己内存里面0地址的地方而不会直接读取nandflash

5. nor flash         //norflash 不容易写入内容但是可以直接读取内容,芯片上电的时候芯片会指向norflash0地址开始读取程序

6. 网卡方便我们进行内核的下载

后面我会依照这个顺序依次的来说明如何修改uboot的代码

 

 

第一阶段 时钟

我们需要看2440的芯片手册:

  1. LOCKTIME 这个是PLL lock time count 这个是当芯片复位之后必须有一定的复位时间来等待芯片的时钟稳定。这里我们取值是0xFFFFFFFF
  2. 根据这个table把MDIV设置成0x5c PDIV 1 SDIV成为 1 (我们input frequency12Mh)输出的频率是400

 

  1. 另外我们还需要设置

 

 

设置这个表来得到FCLKPCLK的值 给外设提供时钟

HCLK 是给芯片的AHB提供时钟 而且根据说明书他的最高速度是136Mhz 而我们的FCLK400Mhz 那么我们HDVIN10的时候HCLK 的速度就是100Mhz = FCLK/8 之后PDIVN最大的值是68Mhz 那么PDIVN1的时候则PCLK50Mhz = HCLK/2

所以CLKDIV = 0x05

 

 

由于2440 这个芯片必须加上非同步程序才能开启时钟 所以加上这句话

 

此时完成时钟的配置。

 

初始化内存

 

 

如手册上所示P192(PDF page) 5-1 内存需要挂接在BANK6 这个地方 所以内存的起始地址就是从0x30000000开始。 初始化内存是初始化时钟之后必须紧接着做的一步因为所有的c程序都需要栈是必须建立在这个内存初始化的基础上。我们内存芯片采用的是两块EM63A165TS-6G 每一块都是32M字节 那么两个连在一起就是可以存储64M内容其中LADDR2连接到了A0的引脚就是说地址是16的地址。也就是说每次位置都是以16发生变化这个芯片是挂载到2440内存控制器上 所以只是需要配置时序就好不用理会真正的协议。

start.S 文件384行有一个函数叫做lowlevel_init.S 在这个里面有对sdram的初始化。

我们打开它来进行了解。

这个目录下 /work/u-boot-2012.04.01_final/board/samsung/smdk2440 找到我们的lowlevel_init.S 在里面设置内存。

有几个变量需要我们去注意:

  1. Tacs
  2. Tcos
  3. Tacc = 4
  4. Delayed

 

我们首先确定SRAMBWSCON

  1. [29:28]: 01 设置bank716 bit
  2. [25:24]: 01 设置bank6 16 bit
  3. [17:16]: 01 设置网卡bank4 16bit
  4. [13:12]: 01 设置bank3 16 bit
  5. [9:8]: 01 设置bank2 16 bit
  6. [5:4]: 01 设置bank1 16 bit

然后所有BANKCON0 ~ BANKCON5 都设置成0x700 这个是经验值

下面就是内存的时钟设置

首先我们用的是SDRAM所以我们[16:15]设置成11 是SDRAM

根据手册P18来设置这些

Tacs 设置0 因为手册里面tIH只有1ns

其余的都设置成0

最后两位SCAN设置成01 = 9 bit

Trcd 设置成01 3 clocks

 

REFRESH

[23]: enable the refresh function

[19:18]: 11 give 7 clocks

[7:0]: 1111 0100  (自己去计算)

 

BANKSIZE

[7] Enable burst operation

[5] SDRAM power down mode enable

[4] SCLK is active only during the access

[2:0]:  001 64M/64M

 

MRSRB 6 : CAS latencty 3 clock

MRSRB 7 :CAS latency 3 clock

 

串口

我们必须把串口调出来才能知道内存是否配置正确。

在arch/arm/lib 里面board_init_f.c 这个start.S 里面引用的。

其中init_sequence 这个数组里面存放了大部分初始化信息其中就有一个board_early_init_f 这里面是原来设置时钟的地方我们可以暂时的把它删掉

 

之后再serial_init 中serial_init_dev 里面_serial_setbrg 里面看到了get_PCLK()在其中s3c24x0_get_base_clock_power()函数get_HCLK() 里面发现了问题

 

其中我们的CONFIG_S3C2440根本没有被定义 所以我们必须首先定义这个变量 首先

Include/configs/Smdk2440.h 定义CONFIG_S3C2440. 然后拿去编译

编译之后 我们发现如下的错误

 

 

这个是关于s3c2410_nand问题我们查看之后发现(如下图)这个程序的结构体是定义了s3c2410_nand 之后才能用,我们现在不用管nandflash的事情所以说我们先可以不编译nandflash

 

这个文件是在/drivers/mtd/nand.c 文件, 我们需要找到drivers 文件夹下面的makeflie去去除这个文件编译

 

那么smdk2440.h里面去除这个define

我们smdk2440.h看到了这个宏是这么定义的

 

所以我们可以直接的把CONFIG_CMD_NAND这个宏定义直接去掉 再次进行编译。得出结果:

 

发现nand_info 没有被定义 那么我们现在可以直接的先把yaffs2定义去掉,在.h文件中去掉config_YAFFS2

 

最后编译出来的是如下情形

 

有个小问题就是为什么是405mz而不是400mhz 暂时未知 会在以后的时间加以改正。

 

已经找到原因请在s3c24x0/Speed.c 修改如下代码:

#if defined(CONFIG_S3C2440)

if (pllreg == MPLL)

return 2 * 100 * (CONFIG_SYS_CLK_FREQ / (3 << 1));

时钟的值固定下来就行了

至此第一阶段结束了。

 

 

第二阶段 代码重定位

  1. 支持nandflash启动

原来的代码在连接时加了-pie选项 这个选项会导致过于麻烦使得连接脚本里面多了(reldyn)信息 ,使得程序非常大不利于从nand启动 从定位之前的代码应该小于4k参考以前的start.S init.c 修改代码 所以我们要要做的是把连接的地址定死启动的时候直接从flash中拷贝过去。 

  1. 我们需要去掉 -pie

首先我们需要先初始化nandflash 让nandflash能够工作

初始化nandflash

我们使用的nandflash K9F2G08U0C, 把之前课程写过的nandflash的驱动放到这里面nand_init and nand_read 改成nand_init_ll and nand_read_ll 在makefileCOBJS 后面添加init.o

在init.c 中把一些内部的函数变成static的形式。

然后我们在回到start.s 里面 利用第223的栈来对nandflash进行初始化

 

 

 

我们改好的程序如下:

 

其中我们的_TEXT_BASE 表示的的是我们的代码应该考到那里去。 代码前面76有了关于_TEXT_BASE 定义 这个定义是告诉我们我们TEXT 是连接到哪里的。我们在这里改成0x33f00000 因为我们的内存是64Mhz 我们内存的起始地址是从0x300000000x34000000. 我们栈顶0x30000000到后面很大的一块地方是要放置新考进来的内核已经其他各种变量所以我们的uboot选择放在了内存的最后一片区域所以是放在了0x33f00000 0x34000000 一共给了uboot 1M空间 足够uboot的使用了。

 

所以下一步在smdk2440.h 里面更改CONFIG_SYS_TEXT_BASE 0x33f00000

然后 start.s 更改之后的代码

 

 

之后清除bss段:

 

之后就可以删除在board_init_f 中relocate_code 函数了。

 

 

 

删掉所有关于relocate_code在start.S 里面的代码

注意后面的board_init_r这个函数需要id dest_addr 这两个参数 其中这两个参数都是从board_init_f 的relocate_code 那里得出 所以我们需要更改board_init_f 这个函数能返回这两个参数board_init_r

其中dest_addrs 就是程序的连接地址。

其中第一个参数id就是board_init_f 里面relocate的参数ID 所以我们需要把board_init_f的改成return id的形式。

所以代码改成了:

 

下一步 修改Makefile 去掉-pie这个选项

修改arch/arm/config.mk 去掉-pie选项

 

修改连接脚本:

其中连接脚本是自动生成的!!! 所以当我们修改了连接地址之后 连接脚本自己也会有变化。找到arch/arm/cpu/u-boot.lds

把start.s init.c lowlevel.S 加到文件最前面

 

 

注意board.c addr 要等于CONFIG_SYS_TEXT_BASE 这样子addr就知道重定位的地址了 我们手动addrs 一个重定位的地址。

 

 

 

 

 

 

 

 

 

效果图:

 

 

支持norflash

首先我们看到我们的flash信息是 ***Failed*** 在源代码中查找这个信息看看是在哪里得到的:

Grep “Flash:” * -nR 发现arch/arm/lib/board.c 505 有这句话 所以去看是什么引起的这句话当我们使用nandflash的时候 肯定不可能在flash_init中返回正确的值。所以说我们在529行hang哪里改成 如果找不到nandflash就变成nand_flash is 0 kb 去掉hang()函数 去掉hang函数之后就可以向nandflash 代码运行

 

 

好,此时我们关注的是norflash 所以我们进入flash_init看一下代码 为什么norflash识别不出来

打印一下调试信息 使能debug 发现ID号码可以被打印出来,那么就是说明时序是对的 但是我们发现程序后面有一个匹配的函数jedec_flash_match 里面有一个jedec_table 里面会有很多的norflash类型 显然我们自己的norflash 可能不在这里 需要我们自己去填写。

我们首先去看norflash里面读出ID对不对。经过验证读出的设备ID是正确的 那么为什么还是识别不出 看起来jedec_table 里面没有我们norflash的信息

这个数组里面的元素如下:

.mfr_id  = 厂家ID

.dev_id  = 型号ID

.name   = 姓名

.uaddr   =  解锁地址

.DevSize  = 设备大小

.CmdSet   =

.NumEraseRegions = 1,  //norflash的擦出块假如norflash擦除的page都是一个size那么就是一个擦除区域 如果有不同的擦除的大小那么就是把它们都加起来 比如我们有三个128K 和四个64k那么我们就有2个擦除区域 一个128 一个64 我们的手册得知我们的擦除区域有4个 分别是16K *1 8K*2 32K* 1 64K* 31

Regions =  

          把每个块写进去。

我们的版本使用的是MT29LV160DB 我们在最后加一项我们自己的产品的型号程序如下

 

烧写之后变成如下效果

 

我们发现其中Flash有一个error就是too many flash sectors 我们只要把smdk2440.h 里面#define CONFIG_SYS_MAX_FLASH_SECT (19) 改成128 就行了。

 

下面介绍几个uboot里面运行的命令

  1. cp.b 30000000 80000 10000 : 按照字节30000000 里面内容拷到 80000里面去 其中长度为10000
  2. cmp.b 30000 80000 10000  比较30000000 80000 开始0x10000 的字节的差异
  3. md.b display memory in byte.

在这里我们会发现我们的栈设置的有问题,栈的位置一直在0x3000f80这个地方0x30000000太近了所以我们应该把栈设置的远离这个地方 因为这个地方是为了放置内核和新的ubootcode.

所以我们的sp board_init_f 里面已经设置好了 但是需要我们用汇编语言给到sp中去详细的代码请看源码

所以我们加上了在汇编中加入了base_sp 在c语言中我们把得到了的sp的值返回给base_sp

 

支持nandflash

如果想支持nandflash 首先需要把config_cmd_nand这个宏定义定义上去 然后进行编译看看出什么错误。

我们发现出现在s3c2410_get_base_nand function中我们的一些结构体没有定 57我们还是在用s3c2440_nand 结构体其实此时应该用的是s3c2440结构体

我们nand结构体的原理

2440里面有一个nand的控制器

  1. 如果当CLE是高电平的话传输的是cmd
  2. 如果ALE是高电平的时候传输的地址
  3. 如果CLE是低电平的话是数据

我们拷贝一份drivers/mtd/nand/2410_nand.c 2440_nand.c 然后修改makefile去让其编译2440_nand.c

 

在makefile61行把s3c2410_nand.o 改成s3c2440_nand.o

 

配置文件smdk2440我们改成CONFIG_NAND_S3C2440 CONFIG_SYS_S3C2440_NAND_HECC

Nandflash 发信息的流程:

  1. 片选
  2. 发命令
  3. 发地址
  4. 发数据
  5. 判断状态

首先看s3c2440_nand.c里面board_nand_init里面nandflash进行初始化

然后我们在

 

我们这里的时间参数远远大于我们的理论值 所以不用改

后面我们在line146行发现这个S3C2410_NFCONF_EN是bit15 我们不需要所以我们先注释掉我们发现代码从146149 并不适用于我们的2440 所以需要修改

 

而且我们需要把2410更改2440

 

比如上图就应该改成s3c2440_nand s3c2440_get_base_nand()

我们发现这个程序需要大改因为24402410不同我们需要改变代码2440cont 寄存器里面的第一位是片选 所以改成(1<<1

 

board_nand_init中我们需要初始化使能flash 初始化ECC禁止片选

 

 

分析流程

  1. 先看单板初始化:设置nand结构体,设置片选
  2. nand_scan 函数

 

下面我们看nandscan

在nand.c中(nand.c 是不跟硬件相关的函数)里面nand_scan 函数

Nandscan是一个nandflash识别的函数

在nand_scan_ident中:

  1. 设置nand_set_defualts 函数:
  2. Nand_get_flash_type

  发出复位的命令

  发出ID的命令

 

之后厂家ID读设备ID

我们发现之前的selectchip有问题的

 

如上图所示

所以说我们需要自己完成chip_select

而且我们需要重新重构hwcontrol

 

 

然后烧录到板子当中用以下的命令来做测试

 

 

其中我们能看到NAND: 256 MiB 就说明已经被识别出来了

 

下面我们就要进行第三个阶段 网卡的移植, 这样子我们就能用过网卡快速的下载uboot和内核了。

第三部分 网卡的移植

在这里我们需要利用网卡的能力去下载内核和新的uboot程序 所以现在我们得先把uboot里面网卡启动起来 我们用的网卡是DM9000 在uboot中已经写好了我们在driver/net 目录下面的makefile中看看是否已经编译进去了DM9000

 

在这里我们发现我们既定义了CS8900定义了dm9000 所以说我们需要去掉CS8900这个网卡 找到smdk2440.h 然后去掉CONFIG_CS8900 加上CONFIG_DRIVER_DM9000

我们的网卡是一个内存协议的芯片所以他是接在内存的控制器上。

所以对于DM9000来说我们需要做的是:

  1. 设置内存控制器时序和位宽
  2. 确定访问地址

我们的网卡是接到了CS4 所以我们就可以确定基地址是0x20000000

在DM9000中有IO地址还有DATA地址 硬件设计中 Addr2接在了cmd引脚上面所以说是由addr2引脚控制发送cmd还是发送data

那么就是说我们的(1<<2左移2 控制芯片输出IO还是data 所以说设置为:

#define DM9000_DATA                  (CONFIG_DM9000_BASE + 4)

参考原理图我们会发现我们的网卡只有address2 连接在了cmd上面说明了输出DATA的地址是在(CONFIG_DM9000_BASE + 4)

而IO是在CONFIG_DM9000_BASE 上面

 

 

网卡的位宽是16 所以我们得把bank4相应的寄存器 设置成16

 

如上图下载之后会出现no Ethernet found 所以说还是有问题, 我们根据这句话找到是谁触发了这句话

 

我们进入这个文件看看究竟是怎么回事儿

在eth.c 367

发现了这句话 我们再看看前面的那个“Net”怎么打印出来的

发现board.c下面打印了这句话 说明了board.c对网卡进行了初始化。

 

应该eth_initialize 这里出了问题

 

我们发现这里根本没有跟DM9000进行初始化 所以需要更改

 

再次进行烧录

 

此时发现网卡已经被显示出来了。

我们做做实验看看网卡能不能用

使用工具是tftp

我们首先把tftp文件夹下面存放.bin 文件

然后我们需要更改板子上面的IP MAC IP

Set ipaddr 192.168.20.3

Set ethaddr 00:0c:29:22:cc:2d (这个是mac地址)

Ping 192.168.20.4

得到如下结果

 

 

我们用tftp试试能不能下载文件

设置 serverip

Set 192.168.20.4 (就是PCIP)

使用命令tftp 30000000 uImage 下载文件夹中的uImage 请注意我们必须把文件放入到tftp这个软件的文件夹下面!!

下载之后用bootm 30000000启动设备

 

发现可以启动 证明我们的网卡移植成功!!

 

第四部分 设置环境参数和变量

环境变量是存在flash某个地方中,当启动的时候系统会用户给的参数如果无效就使用默认的参数这些参数就是默认的环境参数和变量它是在代码中写死了。

我们板子里面的信息有“warning bad crc use default environment”

 

首先搜索using default environment. 我们common/env_common.c 这个文件中找到了这句话

然后我们找到了default_environment 这个数组:

在这里就是定义了我们所有的默认参数

首先看到的是config_bootargs 这个是传给内核的参数

我们smdk2440.h里面定义一下

我们规划是:

  1. 最前面uboot
  2. 中间放参数
  3. 后面放内核
  4. 最后放文件系统

 

console=ttySAC0 root=dev/mtdblock3 表示我们用串口0 打印信息 然后文件系统在第三个block

第0个blockuboot

第一个放参数

第二个放内核

第三个放文件系统

 

内核会根据这里的默认的环境变量信息来确定自己如何启动

#define CONFIG_BOOTCOMMAND "nand read 30000000 0 0xabc 0x200000; bootm 30000000"

Nand read 读30000000 nand的abc地址开始读 2Mb长度 我们现在没有规划好位置所以长度先随便写 然后30000000开始运行

更改ip相关内容

 

 

然后我们裁剪一下这个uboot把不要的都去掉

然后我们设置自己的分区:

注意我们下面烧写还是烧到norflash 但是我们也定义了支持nandflash

我们这在uboot中打 ?save 我们就能知道他是用的哪个函数

我们查出这个函数是saveenv

我们发现里面用在nandflash中的宏函数是CONFIG_ENV_IS_IN_NAND

在env_nand.c 中我们找到saveenv 里面有一个CONFIG_ENV_OFFSET宏定义这个就是我们的环境变量的偏移地址。 我们的环境变量的起始地址0x40000 所以应该设为这个变量

我们还需要知道大小#define CONFIG_ENV_SIZE 注意这个值必须是128K的整数倍。

下面是定义CONFIG_ENV_RANGE 这里我们设置和CONFIG_ENV_SIZE相同

利用protect off all unlock flash的保护 然后

Erase 0 3ffff

Cp.b 30000000 0 40000

然后重新启动设备。

 

之后我们需要利用mtdpart这个命令来设置分区

 

这么设置才能进行分区

 

然后我们发现每次我们想要用这个分区我们都是要执行一次mtdpart default 所以我们可以代码里面写入default这样子我们就不能每次都手工的执行这条命令了。

 

加入run_command 这个命令

然后我们就能看到分区了

 

此后我们需要把之前的CONFIG_BOOTCOMMAND 改成kernel

 

下载内核:

tftp 30000000 uImage;nand erase.part kernel;nand write 30000000 kernel

第四阶段完成

第五阶段 制作yaffs

Yaffs JFFS2 这两文件的区别

  1. JFFS2 启动速度慢 但是适合于nornandflash
  2. YAFFS2专门为了nandflash制作的文件系统。启动速度比JFFS2

测试之前请确保已经加载了uImage

 

首先我们先试试已经提供给的jffs2

命令 tftp 30000000 fs_mini_mdev.jffs2;

nand erase.part rootfs;

nand write.jffs2 30000000 0x00260000 5b89a8 (文件的长度)

 

对于JFFS2启动参数应该是改为

set bootargs console=ttySAC0 root=/dev/mtdblock3 rootfstype=jffs2

然后 命令boot

这样子我们的内核和root都写入了单板 现在板子里面就能跑Linux内核的系统了。

 

下面uboot支持我们的Yaffs系统:

烧写新的uboot

tftp 30000000 u-boot.bin;protect off all;erase 0 3ffff;cp.b 30000000 0 40000

烧写的命令是

tftp 30000000 fs_mini_mdev.yaffs2;nand erase.part rootfs;nand write.yaffs 30000000 260000 889bc0

 

set bootargs console=ttySAC0 root=/dev/mtdblock3 rootfstype=yaffs

我们发现nand_util.c 应该改成OBB_MTD_RAW 后面的的if(!rval) 改成if(rval)

 

然后就可以运行了(这里我的板子发现即使用了做好的uboot还是不行 估计是哪里出现了问题 还在查找)

 

如何制作补丁

   使用diff –urN [旧文件] [新文件] > [补丁文件]

   如何打补丁?

   Patch –p1 <[这里是补丁文件]

   P1: 如果已经在这个文件夹中了 省略这个文件夹

 

第二部分 内核的移植

我们这个版本是linux 3.4.2.

内核的启动过程

从nand flash 把内核传到内存,设置参数,里面有内存的起始地址大小,字符串命令参数。调用内核r0 里面存入0  r1里面存入板子的信息(机器ID  r2 里面存有参数的存放地址 

目的是为了启动应用程序

内核需要装载驱动程序 挂接根文件系统 启动应用程序。装载驱动程序 解析tag参数。

根据R1选择判断能否支持该机器调用跟机器相关的初始化函数

也就是说根据不同的板子初始化不同的函数。

 

在uboot中确定开发板的ID 然后内核会把从内存中得到的开发板的ID和自己本身的开发板进行比对 如果一致的则就调用这个开发板的底层程序 比如串口等等。

 

我们下载完内核之后编译一下。

首先我们tar xjf linux-3.4.2.tar.bz

然后修改makefile 让他支持arm-linux-gcc

 

我们需要的GCC版本是:4.4.3

在arch/arm/configs 里面我们能看到所有关于arm不同板子的配置

Make s3c2410_defconfig

我们用了2410配置但是在最后生成的.config我们能得到2440的板子

 

 

Make uImage 编译内核

 

然后烧到nandflash中去 我们发现里面乱码说明了可能是时钟的原因

但是之前我们看一下uboot里面设置的默认的机器id是什么

 

我们发现我们这里写的还是smdk2410 而不是smdk2440

在uboot中我们没有发现2440板子的machineID 但是linux里面应该是有的 但是如果找到呢 我们可以在uboot中随便设一个很大的machineID然后linux会提示我们什么板子ID是可以用的在里面我们就可以找到2440板子的ID号码了

 

然后我们就可以重新的set machId16a 或者也可以在uboot里面直接改过来。

在此我们就先不改了 而是利用set machid去改

Set machid 16a

但是此时我们还是打印出乱码 那么就是说明我们应该去改usart时钟了查看内核的代码:

 

这里的时钟应该改成12Mhz

然后还要设置set bootargs console=ttySAC0,115200 root=/dev/mtdblock3

就可以实现linux的移植了。

但是当我们写入nandflash在重新启动的时候发现了他还是crc 没通过 原因是因为我们的uImage 太大了所以我们后面会做裁剪和补丁。

 

制作根文件系统和修改内核分区

我们下载内核的时候发现分区不对

 

所以第一步我们要把分区弄对:

Grep “boot Agent” * -nR

我们arch/arm/mach-s3c24xx/common-smdk.c 里面找到这个boot Agent.我们开始对他修改

 

这里我们需要改成和uboot的分区是一样的。

 

 

下面移植busybox

我们选用的是busybox1.70

首先我们先进行busybox编译

首先make menuconfig

添加cross compile: arm-linux-

然后编译

创建一个新的文件(fs_mini_mdev_new)make install CONFIG_PREFIX=../fs_mini_mdev_new 把文件安装到这个文件夹里面。

有如下的东西就说明已经安装好了:

 

之后我们要在这个文件里面安装c库来支持这些文件

首先我们先看一下我们的交叉工具编译链在哪里 因为我们要烧到arm的板子上所以我们需要armc库来支持

echo $PATH

我们看到了这个库 这个库就是我们的arm-linux-gcc 存放自己的C库的地方/usr/local/arm/4.3.2/bin

我们进入这个这个地址/usr/local/arm/4.3.2/ 然后使用find –name lib 查看我们到底有多少的库我们发现

 

其中我们的armv4tarmv4t/usr/lib 这两个库都是应该考到我们的文件夹

我们fs_mini_mdev_new 底下创建一个库lib然后把上面两个文件夹.so 文件都考入这个lib里面

命令是cp arm-none-linux-gnueabi/libc/armv4t/lib/*so* /work/fs_mini_mdev_new/lib –d

        mkdir -p /work/fs_mini_mdev_new/usr/lib

cp arm-none-linux-gnueabi/libc/armv4t/usr/lib/*so* /work/fs_mini_mdev_new/usr/lib/ -d

之后要构造etc目录和dev目录

后面我们需要根据韦东山的视频来创建etc目录 我们会在后面把这块补上

在busybox启动之后 最开始执行的就是sysinit:/etc/init.d/rcs 这个脚本在这个脚本里面

造好etc之后 创建dev目录:

上电后执行initab里面的rcs 的mdev –s 他就会创建dev目录里面的内容 但是我们要先有两个字符型设备 null 和console

 

创建一个dev文件夹 然后

Mknod dev/console c 5 1

Mknod dev/null c 1 3

创建两个设备的节点

然后创建mkdir mnt proc tmp sys root这些目录

之后制作Jff2映像文件

这个命令是在可以执行mkfs的地方执行的

mkfs.jffs2 -n -s 2048 -e 128KiB -d ../fs_mini_mdev_new/ -o fs_mini_mdev_new.jffs2

然后烧写到板子里面去

其中烧写那一步是nand write.jffs2 30000000 260000 $filesize

然后烧写内核发现了如下的错误:

 

这个exitcode是非法指令 ,这是因为我们使用的是eabi接口

我们必须要在编译内核的时候加上这个eabi接口的定义才行。

什么eabi接口?

可执行成应用程序的二进制接口 我们会在以后查看到底是什么意思

但是现在我们需要把这个接口加上 内核的配置里面加入eabi接口

 

在这里添加上eabi接口

再次进行编译 烧写 看看这次行不行

 

Linux 启动成功!

下一个阶段: linux 支持yaffs系统。

 

 

 

移植Yaffs

我们去官网下载yaffs的库 然后readme 发现了打补丁命令

Cd work/yaffts2

./patch-ker.sh c m [linux 目录] /work/linux3.4.2

 

在linuxmake menuconfig 选中支持Yaffs 然后编译内核

发现出现了问题

 

 

我们来分析yaffs的代码。

发现大部分的代码都是没有加下划线 但是其中有一个函数没有声明。把改成d_make_root

 

改了错之后我们的内核就支持了Yaffs的系统 然后我们这个内核烧录进板子 然后制作yaffs映像文件 我们的nfs_root里面有下载好的工具 直接执行下面的命令:

mkyaffs2image ../fs_mini_mdev_new fs_mini_mdev_new.yaffs2

 

制作成功之后 我们就烧写进去

烧写yaffs

Nand write.yaffs 30000000 260000 $filesize

set bootargs console=ttySAC0,115200 root=/dev/mtdblock3

 

之后发现了一个bug

 

Driver/mtd/nand/nand_util.c  line 518

 

添加了这一行之后

重新加载uboot 然后重新下载yaffs 内核 最终就可以把内核移植进去了:

 

 

 

最后一个阶段:

剪裁linux内核

 

最后阶段 剪裁linux内核

 

我们发现我们的uImage 太大了 所以我们需要裁减一下

 

如图超过了2M

我们利用make menuconfig 裁减这个内核

我们也可以根据输出的启动信息来去掉无用的信息

我们uImage叫做uImage_new 烧进去看一下

 

至此 linux 从uboot到内核移植 全部完成!!

 

移植uboot

上一篇:[LeetCode] 1588. Sum of All Odd Length Subarrays


下一篇:Photoshop绘制超级逼真的立体齿轮