lv10系统移植

目录

前言

1.嵌入式系统移植导学

1.1 移植的目的

1.2流程

 1.3开发板启动过程

1.3.1 fs4412地址映射:

1.3.2 开发板启动过程

 1.3.3系统移植步骤

2.交叉开发环境搭建

3.uboot烧写与使用

3.1uboot模式

 3.2uboot帮助命令

 3.3uboot环境变量命令

 3.4uboot常用环境变量

 3.5uboot帮助命令

 3.6uboot存储器访问指令

 3.7uboot自启动环境变量

3.8实验4:  SD 卡启动盘制作

4.Linux内核的安装与加载

 4.1tftp加载Linux内核及rootfs

4.1.1uboot内核启动命令

4.1.2uboot自启动参数环境变量

 4.1.3详细步骤:

  4.2EMMC加载Linux内核及rootfs -- 成品阶段(有sd卡)

 4.3tftp加载Linux内核 nfs挂载rootfs --研发阶段

 4.4EMMC加载uboot-- 成品阶段(无sd卡)

5.交叉编译工具链

5.1ELF文件格式

5.1.1编译原理

 5.1.2gcc编译过程

 5.1.3交叉编译

  5.1.4交叉编译工具链

5.2 ELF文件格式

 5.2.1 ELF文件相关命令

5.3 BIN文件格式

 5.4交叉编译工具链常用工具

6.uboot移植

6.1 uboot源码获取

6.2 uboot特点

6.3 uboot源码结构

6.4 uboot配置

6.5 uboo编译

6.6 uboo移植

6.7 实验6 uboot移植

7.Linux内核移植

7.1 Linux内核特点

7.2 Linux内核源码下载

7.3 Linux内核源码结构

7.4Linux内核源码配置

7.5 make menuconfig

7.6 Linux内核源码编译

7.7 实验七 Linux 内核移植

8.Linux设备驱动移植

8.1设备树

8.2设备树语法概述

8.3linux内核驱动移植流程

8.4 实验八 网卡驱动移植

 9.根文件系统

 9.1根文件系统

 9.2根文件系统内容

9.3BusyBox

9.4 实验九 根文件系统移植

总结



前言


1.嵌入式系统移植导学

1.1 移植的目的

    不同架构的处理器指令集不兼容,即便是相同的处理器架构,板卡不同驱动代码也不兼容
    Linux是一个通用的内核并不是为某一个特定的处理器架构或板卡设计的,所以从官方获取Linux源码后我们要先经过相应的配置使其与我们当前的硬件平台相匹配后才能进行编译和安装

1.2流程

流程: 配置 ===> 编译 ===>安装

 windows和linux安装的对比:流程基本相同

 1.3开发板启动过程

1.3.1 fs4412地址映射:

 32个地址总线可以寻址4GB的内存空间,CPU自己使用了IGB,剩下3GB作为扩充内存使用

1.3.2 开发板启动过程

1. 开发板上电后首先运行SOC内部iROM中固化的代码(BL0),这段代码先对基本的软硬件环境(时钟等...)进行初始化,然后再检测拨码开关位置获取启动方式,然后再将对应存储器中的uboot搬移到内存,然后跳转到uboot运行。

2. uboot开始运行后首先对开发板上的软硬件环境做进一步初始化,然后将linux内核、设备树(dtb)、根文件系统(rootfs)从外部存储器(或网络)搬移到内存,然后跳转到linux运行。

3. linux开始运行后先对系统环境做初始化,当系统启动完成后,Linux再从内存中(或网络)挂载根文件系统。

 1.3.3系统移植步骤

系统移植步骤

uboot移植

linux内核移植(包含设备树)

根文件系统移植

2.交叉开发环境搭建

有三步:

1.配置ubantu网络为桥接,可以连接局域网的其他硬件设备。

2.tftp服务器 掌握 tftp环境搭建的基本方法,能够在 uboot 中使用 tftp 下载文件

3.nfs服务器 掌握 nfs环境搭建的基本方法,能够在开发板上使用 nfs 挂载根文件系统

每次打开ubuntu都需要重启
重启 tftp 服务,使配置生效
        sudo service tftpd-hpa restart
重启 nfs 服务,使配置生效
        sudo service nfs-kernel-server restart

 工作目录位置

进入到tftp服务器工作目录
cd /tftpboot/
进入到nfs服务器工作目录
cd /opt/4412/rootfs/

3.uboot烧写与使用

3.1uboot模式

 自启动模式
    uboot启动后若没有用户介入,倒计时结束后会自动执行自启动环境变量(bootcmd)中设置的命令(一般作加载和启动内核
 交互模式
    倒计时结束之前按下任意按键uboot会进入交互模式,交互模式下用户可输入uboot命令

 3.2uboot帮助命令

 help
    查看uboot支持的所有命令
 help 命令
    查看当前命令的使用方法    

 3.3uboot环境变量命令

 printenv
    打印uboot中所有的环境变量
 setenv
    设置指定的环境变量(保存在RAM中)
        setenv 环境变量 环境变量的值    

        例子: setenv ipaddr 192.168.1.100

 saveenv
    保存所有环境变量到EMMC中

 3.4uboot常用环境变量

 ipaddr
    uboot的IP地址

 serverip
    服务器的IP地址(即ubuntu的IP)    

 bootdelay
    进入自启动模式之前倒计时的秒数

 3.5uboot帮助命令

 loadb
    通过Kermit协议下载文件到指定的内存地址
        loadb  地址
 tftp
    通过tftp协议下载文件到指定的内存地址
        tftp  地址  文件名    --tftpboot可省略为tftp

注:使用tftp之前要配置好网络及tftp服务器

 3.6uboot存储器访问指令

 mmc read
    将EMMC中指定扇区中的内容读取到内存中指定的地址
    mmc read  <addr> <blk#> <cnt>
        addr:    内存地址
        blk#:    EMMC中的扇区编号
        cnt:    读取的扇区的个数

        例子: mmc read 0 0x40008000 0x800 0x1 --其中 0 代表mmc
 mmc write
    将内存中指定地址中的内容写入到EMMC中指定的扇区
        mmc write <addr> <blk#> <cnt>

        例子: mmc write 0 0x41000000 0x800 0x1 --其中 0 代表mmc

 3.7uboot自启动环境变量

 bootcmd
    自启动的环境变量
    该环境变量可以设置成一到多个uboot命令的集合(若有多个使用\;分割)
    自启动模式下uboot就会按照bootcmd中命令的顺序逐条执行

    eg:setenv + bootcmd 命令
        setenv bootcmd tftp 40008000 interface.bin\;go 40008000

3.8实验4:  SD 卡启动盘制作

【实验目的】
掌握 SD 卡启动盘的制作方法
【实验环境】
1 FS4412 实验平台
【实验步骤】
烧写工具默认从 0 扇区开始烧写,这里我们自己在 uboot 之前放一个 512 字节的空镜像
1 、将资料中“u-boot 镜像”中的 u-boot-fs4412.bin 拷贝到 ubuntu 的家目录下
2 、在终端输入如下命令,制作一个 512 字节的空镜像
$ sudo dd if=/dev/zero of=zero.bin count=1
显示如下信息,则表示制作成功
3 、 执行如下命令,将 uboot 追加到 zero.bin 之后生成 win-u-boot-fs4412.bin
$ cat zero.bin u-boot-fs4412.bin > win-u-boot-fs4412.bin
4 、 再执行如下命令,制作一个 1M 的空镜像(用于擦除 SD 卡中原有的数据)
$ sudo dd if=/dev/zero of=clear.bin count=2048
5 、 把生成的 win-u-boot-fs4412.bin clear.bin 拷贝到 windows
6 、 将 SD 卡插入到电脑上(卡槽 /USB 读卡器均可),使其在 windows 下识别(若不识别,
可能是已经在 ubuntu 中识别了,在可移动设备中将其断开即可) 7 、双击打开资料中“
ImageWriter ”下的“ Win32DiskImager
8 、 在弹出的界面中先选择要烧写的镜像文件( clear.bin ),然后选择要烧写的设备( SD 卡)
最后单击“ Write ”进行烧写
9 、 在弹出的对话框中单击“ Yes
10 、在弹出的对话框中单击“ OK ”完成烧写
因为 clear.bin 为空镜像,所以写入后 SD 卡中的前 2048 个扇区中的数据被擦除
11 、再选择 uboot 镜像完( win-u-boot-fs4412.bin ),然后单击“ Write ”进行烧写
12 、在弹出的对话框中单击“ Yes
13 、在弹出的对话框中单击“ OK ”完成烧写
14 、将 SD 卡插入开发板的卡槽,调整拨码开关为 SD 卡启动,查看 uboot 是否能正常启动
注: uboot 正常启动后 LED2 灯会点亮且终端上也会打印 uboot 相关的信息

4.Linux内核的安装与加载

 4.1tftp加载Linux内核及rootfs

4.1.1uboot内核启动命令

 bootm
    启动指定内存地址上的Linux内核并为内核传递参数
    bootm kernel-addr ramdisk-addr dtb-addr
    注:
        kernel-addr:    内核的下载地址  
        ramdisk-addr:    根文件系统的下载地址      
        dtb-addr:        设备树的下载地址
        若不使用相应的地址,对应的位置写“-”
    eg:
        bootm 0x41000000 - 0x42000000    

4.1.2uboot自启动参数环境变量

 bootargs

--这是uboot启动时,通过bootm传递给linux的参数。对uboot没用,是linux用的
    eg:
    setenv bootargs root=/dev/nfs nfsroot=xxx.xxx.xxx.xxx:/opt/4412/rootfs     
    rw console=ttySAC2,115200 init=/linuxrc ip=***.***.***.***
    注:
    root        根文件系统类型(nfs)
    nfsroot        网络文件系统路径(xxx.xxx.xxx.xxx:/opt/4412/rootfs)
    rw          操作网络文件系统的权限(rw)
    console        控制台(使用串口2,波特率115200)
    init            init进程的位置(/linuxrc)
    ip              linux启动后自身的IP(***.***.***.***)

 4.1.3详细步骤:

1 、 将资料中“ Linux 内核镜像”目录下的“uImage”和“exynos4412-fs4412.dtb ”拷贝到 ubuntu tftp 工作目录下

将资料中“根文件系统镜像”目录下的“ ramdisk ”也拷贝到 ubuntu tftp 工作目录下 。
修改这些文件的权限 :
$ sudo chmod 777 /tftpboot/*
2 tftp 服务器
$ sudo service tftpd-hpa restart
3 、 连接开发板与电脑,在 uboot 交互模式下,设置 uboot 的启动参数
# setenv ipaddr ***.***.***.***
# setenv serverip xxx.xxx.xxx.xxx
# setenv bootcmd tftp 0x41000000 uImage\;tftp 0x42000000 exynos4412-fs4412.dtb\;tftp
0x43000000 ramdisk.img\;bootm 0x41000000 0x43000000 0x42000000
# setenv bootargs root=/dev/nfs nfsroot=xxx.xxx.xxx.xxx:/opt/4412/rootfs/ rw
console=ttySAC2,115200 init=/linuxrc ip=***.***.***.***
1
xxx.xxx.xxx.xxx ubuntu 主机的 ip
***.***.***.*** 为开发板的 ip ,必须和 ubuntu
主机的 ip 在同一个网段(根据自己电脑情况进行设置)
2 :以上设置手动输入,命令粘贴可能会有中文符号
设置完成后保存这些参数
# saveenv
4 、 检查网络设置是否正确,使用网线连接开发板与电脑,然后给开发板重新上电,上电之
后观察 uboot 是否能通过 tftp 加载和启动内核,启动时是否能挂载根文件系统(
ext2 ),
启动完成后在终端上输入 linux 下的 shell 命令测试是否正常

  4.2EMMC加载Linux内核及rootfs -- 成品阶段(有sd卡)

通过上述方式我们虽然可以加载 Linux 内核和根文件系统并正常运行,但上述方式我们是把
内核镜像、设备树、根文件系统镜像都放到了 tftp 服务器上,然后开发板上电之后再通过
tftp 去下载这些文件到开发板的内存中运行;但在实际做一个产品的时候我们不可能每次开
机都通过网络去服务器上下载这些镜像,所以以下步骤我们就将这些镜像安装到开发板上
EMMC 中,然后从 EMMC 启动内核
1 给开发板重新上电, uboot 交互模式下 ,去下载并安装这些镜像
下载内核镜像到内存中
# tftp 0x41000000 uImage
将内核镜像写入到 EMMC 中指定的扇区
# mmc write 0 0x41000000 0x800 0x2000 显示如下信息表示安装成功
下载设备树到内存中
# tftp 0x41000000 exynos4412-fs4412.dtb
将设备树写入到 EMMC 中指定的扇区
# mmc write 0 0x41000000 0x2800 0x800
显示如下信息表示安装成功
下载根文件系统镜像到内存中
# tftp 0x41000000 ramdisk.img
将根文件系统镜像写入到 EMMC 中指定的扇区
# mmc write 0 0x41000000 0x3000 0x2000
显示如下信息表示安装成功
2、 因为要从 EMMC 驱动,所以还要修改 uboot 的启动参数
# setenv bootcmd mmc read 0 0x41000000 0x800 0x2000\;mmc read 0 0x42000000 0x2800
0x800\;mmc read 0 0x43000000 0x3000 0x2000\;bootm 0x41000000 0x43000000
0x42000000
若设置无法保存可尝试如下格式
# setenv bootcmd 'mmc read 0 0x41000000 0x800 0x2000;mmc read 0 0x42000000 0x2800
0x800;mmc read 0 0x43000000 0x3000 0x2000;bootm 0x41000000 0x43000000
0x42000000'
设置完成后保存这些参数
# saveenv
3 、 给开发板重新上电,上电之后观察内核是否能通过 EMMC 加载和启动内核,启动完成
后是否能挂载根文件系统(
ext2 ),在终端上输入 linux 下的 shell 命令测试是否正常

 4.3tftp加载Linux内核 nfs挂载rootfs --研发阶段

在后续的课程中我们会经常修改内核和设备数的源码,也会经常向根文件系统中添加一些
驱动或应用程序,这样每次修改之后我们都要重新将内核或根文件系统安装到 EMMC 中,
步骤会比较繁琐,开发效率也比较低,所以在 开发阶段 我们经常使用的方式是通过 tftp
载内核和设备树再通过 nfs 挂载根文件系统(后续课程都是使用这种方式),这样步骤
简单,效率也比较高,待产品定型之后在安装到 EMMC
1 、 将资料中“根文件系统镜像”目录下的“
rootfs.tar ”拷贝到 ubuntu nfs 工作目录下
解压跟文件系统到 nfs 工作目录
$ sudo tar xvf rootfs.tar.xz
解压完成后删除原有压缩包
$ sudo rm rootfs.tar.xz
2 、 修改 uboot 的启动参数
# setenv bootcmd tftp 0x41000000 uImage\;tftp 0x42000000 exynos4412-fs4412.dtb\;bootm
0x41000000 - 0x42000000
设置完成后保存这些参数
# saveenv
3 nfs 服务器
$ sudo service nfs-kernel-server restart
4 给开发板重新上电,上电之后观察内核是否能通过 tftp 加载和启动内核,启动完成后是
否能挂载根文件系统(
nfs ),在终端上输入 linux 下的 shell 命令测试是否正常,若启
动正常我们向 nfs 的工作目录中添加了新的文件之后可以在开发板直接看到

 4.4EMMC加载uboot-- 成品阶段(无sd卡)

以上的几种方式中我们既可以通过网络启动内核也可以将内核安装到 EMMC 中从本地
启动,但是对于 uboot 我们一直使用的是从 SD 卡启动,所以我们也可以将 uboot
装到 EMMC 中然后从 EMMC 启动 uboot ,这样就可以不使用 SD 卡了
1 将资料中“u-boot 镜像”目录下的“ u-boot-fs4412.bin ”拷贝到 ubuntu tftp 工作目录
2 、 给开发板重新上电,在 uboot 交互模式下,去下 载并安装 uboot
# tftp 0x41000000 u-boot-fs4412.bin
将内核镜像安装到 EMMC 中指定的扇区
# emmc open 0
# mmc write 0 0x41000000 0x0 0x800
# emmc close 0 显示如下信息表示安装成功
3 、 关闭开发板电源,调整拨码开关位置为 EMMC 启动
4 、 给开发板重新上电,观察 uboot 是否能正常启动
启动 EMMC 模式中的 uboot ,环境变量还需要根据实际需要重新设置 (linux内核,设备树,根文件系统)
主要区别就是uboot启动方式不同,其余的(linux内核,设备树,根文件系统) 没区别

5.交叉编译工具链

5.1ELF文件格式

5.1.1编译原理

 机器码(二进制)是处理器能直接识别的语言,不同的机器码代表不同的运算指令,处理器能够识别哪些机器码是由处理器的硬件设计所决定的,不同的处理器机器码不同,所以机器码不可移植

 汇编语言是机器码的符号化,即汇编就是用一个符号来代替一条机器码,所以不同的处理器汇编也不一样,即汇编语言也不可移植

 C语言在编译时我们可以使用不同的编译器将C源码编译成不同架构处理器的汇编,所以C语言可以移植

 5.1.2gcc编译过程

 5.1.3交叉编译

 简单来说:程序的编译和运行不在同一台机器上

  5.1.4交叉编译工具链

 交叉编译工具链的获取:
    1) 官网获取(不推荐,需要自己进行复杂配置与编译)
        http://ftp.gnu.org/gnu/gcc/
    2) BSP板级开发支持包(推荐)
        samsung、全志...
 交叉编译工具链的内容
    1) 交叉编译工具
        gcc/readelf/size/nm/strip/objcopy/objdump/addr2line
    2) 库
    ARM架构的库

5.2 ELF文件格式

 5.2.1 ELF文件相关命令

 file
    file + 文件名        查看文件的详细信息
    
 readelf
    readelf -h + 文件名     列出elf文件的头部信息
    readelf -a + 文件名     列出elf文件的所有信息

5.3 BIN文件格式

 5.4交叉编译工具链常用工具

 size           列出目标文件每一段的大小以及总体的大小
    size + 文件名        
    
 nm            列出目标文件中的符号表(标示符)
    nm + 文件名        

 strip        丢弃目标文件中的符号
    strip + 文件名        
    注:对于嵌入式开发,这个命令很重要


 objdump            从目标文件中显示信息    
    eg:        
        objdump -d + 文件名    将目标文件反汇编(机器码->汇编)
    
 objcopy            对目标文件进行复制和转换
    eg:
        objcopy --gap-fill=0xff -O binary a.out a.bin        
    将目标文件转换为bin格式

6.uboot移植

6.1 uboot源码获取

 uboot源码下载
    http://www.denx.de/wiki/U-Boot/(不使用)

    https://ftp.denx.de/pub/u-boot/

 uboot版本命名
    前期:uboot-1.2.3
    现在:uboot-2008.01

 uboot版本选择
    支持对应的硬件平台
    相对成熟的版本(资料多)

6.2 uboot特点

 代码结构清晰
 支持丰富的处理器与开发板,易于移植
 支持丰富的用户命令
 支持丰富的网络协议
 支持丰富的文件系统
 支持丰富的设备驱动
 更新活跃、用户较多、资料丰富
 开放源代码
 较高的稳定性
 不具有通用性(不同的处理器、开发板uboot不可通用)

6.3 uboot源码结构

 平台相关代码
    即与CPU架构或开发板硬件相关的源码,硬件的改动对应的代码也需要进行修改

    arch:与CPU架构相关的源代码
    board:与开发板相关的源代码,包含各种官方评估板对应的源码

 平台无关代码
    api:    应用接口
    common:    uboot命令源码
    disk:    对磁盘设备的支持
    drivers:    设备驱动源码
    fs:        对文件系统的支持    
    include:    头文件
    lib:    库
    net:    对网络协议的支持
    post:    上电自检程序
    ... ...

 配置文件、帮助文档、示例程序、工具等:
    README:    说明文档
    doc:    帮助文档
    Makefile:    编译管理
    CREDITS:    开发者
    COPYING:    版权
    examples:    示例程序
    tools:    工具
    ... ...

6.4 uboot配置

 1.指定当前使用的硬件平台
    make <board_name>_config
    注1:<board_name>为当前使用的开发板的名字
    注2:执行该命令的前提是uboot源码支持该开发板
    注3:该命令必须在uboot源码的顶层目录下执行
    
 2.指定编译uboot源码使用的编译器
    在uboot源码顶层目录下的Makefile中指定(CROSS_COMPILE变量)

6.5 uboo编译

 1.编译uboot
    make
    注1:该命令必须在uboot源码的顶层目录下执行
    注2:该命令执行后在uboot源码顶层目录下生成u-boot.bin
    
 2.清除编译过程中生成的中间文件
    make clean
    make distclean

    注1:该命令必须在uboot源码的顶层目录下执行

6.6 uboo移植

6.7 实验6 uboot移植

一般 制作开发板的公司会把适配好的uboot直接给出,可以直接使用,将uboot拷贝到SD卡或者硬盘即可。

7.Linux内核移植

7.1 Linux内核特点

 代码结构清晰、模块化设计
 支持丰富的硬件平台
 较高的稳定性
 轻量化及较强的裁剪性
 开放源代码
 更新活跃、用户较多、资料丰富
 支持丰富的网络协议
 ... ...

7.2 Linux内核源码下载

    https://www.kernel.org/

 Linux内核版本命名
    主版本号.次版本号.修订版本

 Linux内核版本选择
    支持对应的硬件平台
    相对成熟的版本(资料多)
    稳定版本(次版本号为偶数的版本一般都是稳定版)

7.3 Linux内核源码结构

平台相关代码
    arch:    与CPU架构相关的源代码

 平台无关代码
    block:磁盘设备的支持            crypto:加密相关
    drivers:设备驱动                firmware:固件
    fs:文件系统                include:头文件
    init:内核初始化                ipc:进程间通信
    kernel:内核核心调度机制等        lib:库
    mm:内存管理                net:网络协议
    scripts:工具、脚本等            security:安全
    usr:打包与压缩                virt:虚拟

 帮助文档、示例程序、工具等
    COPYING:        版权
    CREDITS:        内核贡献者
    README:        说明文档
    Documentation:    帮助文档
    Makefile:        编译管理
    samples:        示例
    tools:        工具
    ... ...

7.4Linux内核源码配置

 指定处理器架构及编译工具
    在Linux内核源码顶层目录下的Makefile中指定(ARCH、CROSS_COMPILE)
 导入当前处理器的默认配置
    make <soc_name>_defconfig
    注1:soc_name为当前使用的处理器的名字
    注2:内核源码的arch/arm/configs下对各个厂商的soc都有一个默认配置文件
    执行该命令后就会将对应的配置文件中的信息导入到源码顶层目录下的.config
    文件中CONFIG_xxx=y表示内核选中了该功能,内核编译时就会将该功能对应的
    代码编译,内核的体积也会增大。#CONFIG_xxx is not set表示内核没有选中
    该功能,内核编译时该功能对应的代码不会被编译,内核的体积也会减小。

 修改配置
    默认配置只能保证内核拥有最基本的功能,我们需要根据自己的实际需求对内核做进一步的配置

    方法1:
    直接修改.config文件(不推荐)
    方法2:
    make menuconfig

7.5 make menuconfig

    [ ] 有两种状态
        输入Y,显示“*”,内核中该功能被选中,相关代码会被编译进内核
    输入N,显示“ ”,内核中该功能不被选中,相关代码不会被编译进内核
    < > 有三种状态
        输入Y,显示“*”,内核中该功能被选中,相关代码会被编译进内核
    输入N,显示“ ”,内核中该功能不被选中,相关代码不会被编译进内核
       输入M,显示“M”,内核中该功能被选为模块(被编译为独立的模块)

    注:使用make menuconfig配置的本质还是修改.config文件

7.6 Linux内核源码编译

内核编译(以下命令均在内核源码的顶层目录下执行)
    make uImage    
    编译内核(编译选为“*”的选项到内核)
    make modules       
    编译内核模块(编译选为“M”的选项为独立模块)
    make dtbs          
    编译设备树(将设备树源文件dts编译为二进制文件dtb)
    make clean     
    删除编译过程中产生的中间文件

7.7 实验七 Linux 内核移植

【实验目的】
掌握 Linux 内核配置和编译的基本方法
【实验环境】
1 ubuntu 14.04 发行版
2 FS4412 实验平台
3 交叉编译工具: arm-none-linux-gnueabi-
【注意事项】
1 、实验步骤中以“ $ ”开头的命令表示在 ubuntu 环境下执行,以“
# ”开头的命令表
示在开发板下执行
【实验步骤】
1 、 在 Linux 官网下载 Linux 内核源码(这里我们下载 linux-3.14.tar.xz
https://mirrors.edge.kernel.org/pub/linux/kernel/v3.x/
2 、 拷贝内核源码包到 ubuntu 的家目录下,解压并进入其顶层目录
$ tar xvf linux-3.14.tar.xz
$ cd linux-3.14
3 、 源码并不知道我们的处理器架构及交叉编译工具是什么,我们自己在 Makefile 中指定
$ vi Makefile
ARCH
?= $(SUBARCH)
CROSS_COMPILE ?= $(CONFIG_CROSS_COMPILE:"%"=%)
修改为以下内容( 注意后边不要有多余空格 ),然后保存退出
ARCH
?= arm
CROSS_COMPILE ?= arm-none-linux-gnueabi-
4 、 指定使用的处理器
$ make exynos_defconfig 显示如下信息表示配置成功
5 、 进入内核配置界面
$ make menuconfig
弹出如下图形化配置界面,在该界面下我们可以对 linux 进行进一步的修改和配置
方向键可选择不同的选项,‘Enter ’键进入子菜单,‘ Y ’键选中某项功能,‘ N ’键 去除某项功能,‘ M ’键将该功能编译成内核模块,两次‘ Esc ’键退出界面,‘ ? ’键 为帮助选项,‘ / ’键为搜索选项
1 :若显示如下信息,是因为 ubuntu 上没有安装对应的图形库
执行如下命令安装对应的图形库,然后重新执行 make menuconfig 即可
$ sudo apt-get install libncurses5-dev
注2 :若显示如下信息,是因为终端窗口太小,需将终端最大化后再执行
6 、 配置内核
将‘System Type ’菜单下的‘ S3C UART... ’修改为 2 (即使用 UART2 System Type ---> ( 2 ) S3C UART to use for low-level messages 设置完成后通过方向键选择‘ Save ’保存即可,然后选择‘ Exit ’退出该配置界面
7 、 编译内核(该过程可能需要二十分钟左右)
$ make uImage
显示如下信息表示编译成功,即在源码的 arch/arm/boot/ 目录下生成了 uImage 镜像
注:如图所示,第一次在 ubuntu 上编译 Linux 内核会提示缺少一个 mkimage 命令
该命令可在 uboot 源码中 u-boot-2013.01/tools/ 目录下获取(必须是编译后的 uboot
将该命令拷贝到 ubuntu /usr/bin 目录下即可正确编译内核
$ sudo cp u-boot-2013.01/tools/mkimage /usr/bin/
给该命令添加可执行权限
$ sudo chmod 777 /usr/bin/mkimage
完成后回到内核的顶层目录下重新编译内核即可
8 、 编译设备树
内核源码中并没有 fs4412 平台的设备树文件,这里我们从源码支持的平台中找一个硬
件与我们最类似的,在其基础上进行修改,这里我们参考的是 samsung 公司的 origen 拷贝 origen 的设备树并将其重命名
$ cp arch/arm/boot/dts/exynos4412-origen.dts arch/arm/boot/dts/exynos4412-fs4412.dts
因为添加的设备树文件也要编译,所以对应的 Makefile 也要修改
$ vi arch/arm/boot/dts/Makefile
exynos4412-origen.dtb \
后添加如下内容,然后保存退出
exynos4412-fs4412.dtb \
回到源码的顶层目录下编译设备树
$ make dtbs
显示如下信息表示编译成功,即在 arch/arm/boot/dts/ 目录下生成了 exynos4412-fs4412.dtb
9 、 测试内核和设备树将编译生成的内核和设备树拷贝到 tftp 的工作目录
$ sudo cp arch/arm/boot/uImage /tftpboot
$ sudo cp arch/arm/boot/dts/exynos4412-fs4412.dtb /tftpboot/
$ sudo chmod 777 /tftpboot/*
设置 uboot 启动参数并保存
# setenv ipaddr ***.***.***.***
# setenv serverip xxx.xxx.xxx.xxx
# setenv bootcmd tftp 41000000 uImage\;tftp 42000000 exynos4412-fs4412.dtb\;bootm
41000000 - 42000000
# setenv bootargs root=/dev/nfs nfsroot=xxx.xxx.xxx.xxx:/opt/4412/rootfs/ rw
console=ttySAC2,115200 init=/linuxrc ip=***.***.***.***
# saveenv
1
xxx.xxx.xxx.xxx ubuntu 主机的 ip
***.***.***.*** 为开发板的 ip ,必须和 ubuntu
主机的 ip 在同一个网段(根据自己电脑情况进行设置)
2 :以上设置手动输入,命令粘贴可能会有中文符号
回到 ubuntu tftp nfs 服务器
$ sudo service tftpd-hpa restart
$ sudo service nfs-kernel-server restart
重启开发板查看现象,如图所示, 内核在启动到一半时会崩溃卡死 ,原因在于我们在该
实验中只是对 UART 进行了配置,而其他功能都保持默认选项,内核默认配置中没选
配我们使用的网卡驱动、 nfs 等功能,所以在挂载根文件系统时导致内核崩溃,所以后
续我们还需要配置网卡驱动、 nfs

8.Linux设备驱动移植

8.1设备树

 设备树
    设备树是一种描述硬件信息的数据结构,Linux内核运行时可以通过设备树将硬件信息直接传递给Linux内核,而不再需要在Linux内核中包含大量的冗余编码

8.2设备树语法概述

 设备树文件
    dts  设备树源文件
    dtsi 类似于头文件,包含一些公共的信息,可被其它设备树文件引用
    dtb  编译后的设备树文件

 设备树语法
    设备树的语法为树状结构,由一系列的节点和属性组成,根节点下包含子节点
    子节点下还可以包含子节点,节点内部包含了对应设备的属性

8.3linux内核驱动移植流程

    1.在make menuconfig界面中选中要安装的驱动
    2.在设备树中添加/修改相应的设备信息
    3.重新编译内核/设备树

8.4 实验八 网卡驱动移植

【实验目的】
掌握 Linux 内核配置的基本方法,完成对网卡驱动、 NFS 等相关功能的配置
【实验环境】
1 ubuntu 14.04 发行版
2 FS4412 实验平台
3 交叉编译工具: arm-none-linux-gnueabi-
【注意事项】
1 、实验步骤中以“ $ ”开头的命令表示在 ubuntu 环境下执行,以“
# ”开头的命令表
示在开发板下执行
【实验步骤】
1、 在内核源码的顶层目录下执行如下命令,修改内核配置
$ make menuconfig
给内核选配 DM9000 网卡驱动,然后选择“ Save ”保存
Device Drivers --->
[*] Network device support --->
[*]
Ethernet driver support --->
< * >
DM9000 support
因为内核要使用 NFS 去挂载根文件系统,而 NFS 是基于 TCP 协议实现的,所以这里需
要选配 TCP 相关的网络协议(部分功能默认已经选配),然后选择“ Save ”保存
[*] Networking support --->
Networking options --->
< * > Packet socket
< * > Unix domain sockets
[ * ] TCP/IP networking
[ * ]IP: kernel level autoconfiguration
因为内核要使用 NFS 去挂载根文件系统,所以需要给内核选配 NFS 客户端及相关功能
File systems --->
[*] Network File Systems --->
< * > NFS client support
< * >NFS client support for NFS version 3 (NEW)
[ * ]NFS client support for the NFSv3 ACL protocol extension
[ * ]Root file system on NFS
设置完成后通过方向键选择‘Save ’保存即可,然后选择‘ Exit ’退出该配置界面
2、 在设备树中添加网卡的硬件信息
$ vi arch/arm/boot/dts/exynos4412-fs4412.dts
在文件的末尾, 最后一个花括号前 添加如下内容(即要写在根节点之内)
srom-cs1@5000000 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x5000000 0x1000000>;
ranges;
ethernet@5000000 {
compatible = "davicom,dm9000";
reg = <0x5000000 0x2 0x5000004 0x2>;
interrupt-parent = <&gpx0>;
interrupts = <6 4>;
davicom,no-eeprom;
mac-address = [00 0a 2d a6 55 a2];
};
};
3修改时钟相关配置(忽略无用的时钟)
$ vi drivers/clk/clk.c
static bool clk_ignore_unused;
修改为以下内容,然后保存退出
static bool clk_ignore_unused=true;
4修改 EMMC 相关配置
$ vi drivers/mmc/core/mmc.c
if (card->ext_csd.rev > 7) {
pr_err("%s: unrecognised EXT_CSD revision %d\n",
mmc_hostname(card->host), card->ext_csd.rev);
err = -EINVAL;
goto out;
}
修改为以下内容,然后保存退出
#if 0
if (card->ext_csd.rev > 7) {
#else
if (card->ext_csd.rev > 8) {
#endif
pr_err("%s: unrecognised EXT_CSD revision %d\n",
mmc_hostname(card->host), card->ext_csd.rev);
err = -EINVAL;
goto out;
}
5、 编译内核和设备树
$ make uImage
$ make dtbs
6、 测试内核和设备树
将编译生成的内核和设备树拷贝到 tftp 的工作目录
$ sudo cp arch/arm/boot/uImage /tftpboot
$ sudo cp arch/arm/boot/dts/exynos4412-fs4412.dtb /tftpboot/
$ sudo chmod 777 /tftpboot/*
tftp nfs 服务器
$ sudo service tftpd-hpa restart
$ sudo service nfs-kernel-server restart
重启开发板查看现象,如图所示,此时 Linux 内核已经能通过 NFS 去挂载根文件系统
在终端下执行‘
ls ’命令我们就能看到根文件系统中的内容

 9.根文件系统

 9.1根文件系统

    根文件系统是内核启动后挂载的第一个文件系统系统引导程序会在根文件系统挂载后从中把一些基本的初始化脚本和服务等加载到内存中去运行

 9.2根文件系统内容

 bin        shell命令(elf格式)(通过busybox编译生成)
 dev        设备文件(内核启动后会将设备信息写入该目录)
 etc        内核配置文件
 lib        共享库(elf格式)(从交叉编译工具链中获取)
 linuxrc    内核运行的第一个应用程序(通过busybox编译生成)
 mnt        挂载目录(非必要)
 proc        进程相关文件(内核启动后会将进程信息写入该目录)
 root        超级用户家目录(非必要)
 sbin       系统管理shell命令(elf格式)(通过busybox编译生成)
 sys        驱动相关文件(内核启动后会将驱动信息写入该目录)
 usr        shell命令(elf格式)(通过busybox编译生成)

9.3BusyBox

    BusyBox将很多常用的工具集成到一个很小的可执行文件中,为普通用户提供大多数常用的命令,BusyBox实现的命令都是精简版的,很多扩展都不支持。BusyBox被称为Linux工具里的瑞士军刀

 BusyBox的获取
    https://busybox.net/downloads/

9.4 实验九 根文件系统移植

【实验目的】
熟悉根文件系统的目录结构,构建自己的根文件系统
【实验环境】
1 ubuntu 14.04 发行版
2 FS4412 实验平台
3 交叉编译工具: arm-none-linux-gnueabi-
【注意事项】
1 、实验步骤中以“ $ ”开头的命令表示在 ubuntu 环境下执行
【实验步骤】
一、构建自己的根文件系统
1 、 在 busybox 官网下载 busybox 源码(这里我们下载 busybox-1.22.1.tar.bz2
https://busybox.net/downloads/
2 、 拷贝 busybox 源码包到 ubuntu 的家目录下,解压并进入其顶层目录
$ tar xvf busybox-1.22.1.tar.bz2
$ cd busybox-1.22.1/
3 、 进入 busybox 配置界面(与 Linux 内核配置方法一样)
$ make menuconfig
4 、 参考如下信息配置 busybox
Busybox Settings --->
Build Options --->
[ * ] Build BusyBox as a static binary (no shared libs)
[ ] Build with Large File Support (for accessing files > 2 GB)
( arm-none-linux-gnueabi- ) Cross Compiler prefix
配置完成后通过方向键选择‘ Exit ’退出,并保存配置信息
5 、 编译 busybox
$ make
编译完成后在源码的顶层目录下会生成 busybox 文件
6 、 安装 busybox
$ make install
安装完成后在源码的顶层目录下会生成 _install 目录
7 、 进入到安装目录下查看生成的文件
$ cd _install/
$ ls
如下图所示,在安装目录下生成了根文件系统中所需的 shell 命令文件
8 、 将交叉编译工具链中的库文件拷贝到 _install 目录下
$ cp /home/linux/Linux_4412/toolchain/gcc-4.6.4/arm-arm1176jzfssf-linux-gnueabi/lib/ . -a
如下图所示,在安装目录下就有了根文件系统中所需的库文件
9 、 删除库文件中的静态库
$ sudo rm lib/*.a
10 、删除共享库中的符号表( 需要在 root 用户下操作
$ sudo su
$ /home/linux/Linux_4412/toolchain/gcc-4.6.4/bin/arm-none-linux-gnueabi-strip lib/*
$ exit
11 、将资料中“移植相关文件”下的 etc 目录(配置文件)拷贝到当前目录下
12 、给 etc/init.d/ 下的 rcS 脚本添加可执行权限
$ chmod +x etc/init.d/rcS
13 、创建其他目录
$ mkdir dev mnt proc root sys tmp var
如下图所示,至此我们就构建好了自己的根文件系统
14 、删除原来的根文件系统
$ sudo rm -rf /opt/4412/rootfs/*
15 、将自己制作的根文件系统拷贝到 NFS 的工作目录下测试
$ sudo cp -rf ./* /opt/4412/rootfs


总结

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值