文章目录
- 1. 编译环境搭建
- 1.1 交叉编译器下载
- 1.2 交叉编译器安装
- 2. 编译原厂uboot
- 3. 烧录开发板
- 3.1 烧录到SD卡
- 3.2 启动开发板
1. 编译环境搭建
1.1 交叉编译器下载
嵌入式Linux开发,程序编译通常在电脑端的Linux(如虚拟机中的Ubuntu)下进行编译,Ubuntu 自带gcc 编译器,但该编译器是针对 X86 架构的!而嵌入式Linux是ARM架构的, 所以需要一个在 X86 架构上可以编译 ARM 架构代码的 gcc编译器,即交叉编译器。
交叉编译器有很多,本实验使用 Linaro 出品的交叉编译器,下载地址:
https://releases.linaro.org/components/toolchain/binaries/4.9-2017.01/arm-linux-gnueabihf/
1.2 交叉编译器安装
在Ubuntu中创建目录:/home/kaka/IMX6ULL/gcc-linaro-4.9.4-2017.01-x86_64_arm
,并将下载的gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz
复制到此文件中,然后**「解压」**,解压命令如下:
sudo tar -vxf gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf.tar.xz
解压完成以后会生成一个名为“gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf
”的文件夹,这个文件夹里面就是交叉编译工具链。
然后,需要将该目录添加到环境变量中。打开/etc/profile 以后,在最后面输入如下所示内容:
临时有效:
export PATH=${PATH}:/home/kaka/IMX6ULL/gcc-linaro-4.9.4-2017.01-x86_64_arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin
长期有效:
sudo vi /etc/profile
使用交叉编译器之前还需要安装其它的库,命令如下:
sudo apt-get install lsb-core lib32stdc++6
sudo apt-get install libncurses5-dev
安装完之后,可以查看交叉编译工具的版本号,输入如下命令:
arm-linux-gnueabihf-gcc -v
可以看到类似如下打印
kaka@kaka-virtual-machine:~$ arm-linux-gnueabihf-gcc -v
Using built-in specs.
COLLECT_GCC=arm-linux-gnueabihf-gcc
COLLECT_LTO_WRAPPER=/home/kaka/IMX6ULL/gcc-linaro-4.9.4-2017.01-x86_64_arm/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/../libexec/gcc/arm-linux-gnueabihf/4.9.4/lto-wrapper
Target: arm-linux-gnueabihf
Configured with: /home/tcwg-buildslave/workspace/tcwg-make-release/label/docker-trusty-amd64-tcwg-build/target/arm-linux-gnueabihf/snapshots/gcc-linaro-4.9-2017.01/configure SHELL=/bin/bash --with-mpc=/home/tcwg-buildslave/workspace/tcwg-make-release/label/docker-trusty-amd64-tcwg-build/target/arm-linux-gnueabihf/_build/builds/destdir/x86_64-unknown-linux-gnu --with-mpfr=/home/tcwg-buildslave/workspace/tcwg-make-release/label/docker-trusty-amd64-tcwg-build/target/arm-linux-gnueabihf/_build/builds/destdir/x86_64-unknown-linux-gnu --with-gmp=/home/tcwg-buildslave/workspace/tcwg-make-release/label/docker-trusty-amd64-tcwg-build/target/arm-linux-gnueabihf/_build/builds/destdir/x86_64-unknown-linux-gnu --with-gnu-as --with-gnu-ld --disable-libmudflap --enable-lto --enable-objc-gc --enable-shared --without-included-gettext --enable-nls --disable-sjlj-exceptions --enable-gnu-unique-object --enable-linker-build-id --disable-libstdcxx-pch --enable-c99 --enable-clocale=gnu --enable-libstdcxx-debug --enable-long-long --with-cloog=no --with-ppl=no --with-isl=no --disable-multilib --with-float=hard --with-mode=thumb --with-tune=cortex-a9 --with-arch=armv7-a --with-fpu=vfpv3-d16 --enable-threads=posix --enable-multiarch --enable-libstdcxx-time=yes --with-build-sysroot=/home/tcwg-buildslave/workspace/tcwg-make-release/label/docker-trusty-amd64-tcwg-build/target/arm-linux-gnueabihf/_build/sysroots/arm-linux-gnueabihf --with-sysroot=/home/tcwg-buildslave/workspace/tcwg-make-release/label/docker-trusty-amd64-tcwg-build/target/arm-linux-gnueabihf/_build/builds/destdir/x86_64-unknown-linux-gnu/arm-linux-gnueabihf/libc --enable-checking=release --disable-bootstrap --enable-languages=c,c++,fortran,lto --build=x86_64-unknown-linux-gnu --host=x86_64-unknown-linux-gnu --target=arm-linux-gnueabihf --prefix=/home/tcwg-buildslave/workspace/tcwg-make-release/label/docker-trusty-amd64-tcwg-build/target/arm-linux-gnueabihf/_build/builds/destdir/x86_64-unknown-linux-gnu
Thread model: posix
gcc version 4.9.4 (Linaro GCC 4.9-2017.01)
以看出当前交叉编译器的版本号为 4.9.4,说明交叉编译工具链安装成功。
2. 编译原厂uboot
在Ubuntu中创建存放uboot的目录,如我的目录是:/home/kaka/IMX6ULL/u-boot
这里使用的是正点原子提供的NXP官方原版Uboot源码包( uboot-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2)
然后进行解压:
tar -vxjf uboot-imx-rel_imx_4.1.15_2.1.0_ga.tar.bz2
解压后的源码文件如下:
首先看下uboot的配置,configs 目录下有很多跟 I.MX6UL/6ULL 有关的配置,找到与mx6ull相同的,如下图。
因为这个开发板是emmc版本的,所有就使用这个mx6ull_14x14_evk_emmc_defconfig
。
编译uboot使用下面3条指令:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8
这3条命令中 :
ARCH=arm
设置目标为 arm 架构CROSS_COMPILE
指定所使用的交叉编译器。- 第1条命令相当于
make distclean
,目的是清除工程,一般在第一次编译的时候最好清理一下工程。 - 第2条指令相当于
make mx6ull_14x14_evk_emmc_defconfig
,用于配置 uboot,配置文件为 mx6ull_14x14_evk_emmc_defconfig。 - 第3条指令相当于
make -j8
,也就是使用8核来编译uboot。
为了方便的执行着3条指令,可以**「将这些指令写成shell脚本」**,比如在uboot源码目录下新建一个build.sh文件,写入如下内容:
#!/bin/bash
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j8
然后进行编译:
./build.sh
编译完成以后uboot 源码多了一些文件,其中u-boot.bin
就是编译出来的 uboot二进制文件。 uboot是个裸机程序, 因此需要在其前面
加上头部(IVT、 DCD等数据)才能在I.MX6U上执行,u-boot.imx
文件就是添加头部以后的 u-boot.bin。
u-boot.imx 就是我们最终要烧写到开发板中的 uboot 镜像文件。
3. 烧录开发板
烧录u-boot到开发板,实际是要烧录到SD卡中,然后将SD卡插入开发板,让开发板从SD卡启动(需要在开发板上设置拨码开关来选择启动方式)。
3.1 烧录到SD卡
正点原子专门编写了一个小软件用来将编译出来的.bin 文件烧写到 SD 卡中,这个软件叫做“imxdownload
”
将imxdownload
复制到 Ubuntu 中的uboot源码文件夹,再使用如下指令,给予 imxdownload 可执行权限:
chmod 777 imxdownload
然后电脑USB中插入SD卡(读卡器),并在虚拟机中设置usb加载(VMware或VirtualBox虚拟机需要先安装增强功能才能使用)
然后可以使用如下指令来查看SD卡的挂载标识符:
kaka@kaka-virtual-machine:~/IMX6ULL/u-boot$ ls /dev/sd
sda sda1 sda2 sda3 sdb sdb1
这里的/dev/sdb
就是我的SD卡
注:第一次使用SD卡烧录时,只多出了/dev/sdb,但不知什么情况,用了几次后,再插入SD卡,就会同时多出来/dev/sdb和/dev/sdb1,但实际测试,仍然把程序烧录到/dev/sdb也能用)。
imxdownload
向SD卡烧写led.bin文件,命令格式如下:
./imxdownload u-boot.bin /dev/sdb
注意不能烧写到/dev/sda
或sda1
设备里面!那是系统磁盘。
烧写过程会输入如下信息:
注意这个烧写速度,如果这个烧写速度在几百KB/s以下那么就是正常烧写。 如果这个烧写速度大于几十MB/s、甚至几百MB/s那么肯定是烧写失败了! 重新插拔/格式化SD卡或重启ubuntu再试。
烧写完成以后会在当前工程目录下生成一个load.imx
的文件,这个文件就是软件imxdownload
根据 NXP 官方启动方式介绍的内容, 在 bin 文件前面添加了一些数据头以后生成的。最终烧写到SD卡里面的就是这个imx文件。
3.2 启动开发板
烧录完之后,将SD卡插入开发板启动,使用串口连接电脑,查看uboot启动信息。 设置好串口参数(波特率115200)并打开,按键复位开发板。 当串口打印上出现Hit any key to stop autoboot
倒计时的时候按下 键盘上的回车键」,默认是 3 秒倒计时,在 3 秒倒计时结束以后如果没有按下回车键的话 uboot 就会使用默认参数来启动 Linux 内核了。
如果在 3 秒倒计时结束之前按下回车键,那么就会进入 uboot 的命令行模式:
解读一下这些信息的含义:
- 第1行是 uboot 「版本号和编译时间」:当前的 uboot 版本号是 2016.03,编译时间是 2023/6/15/23:01:07
- 第3、4 行是 「CPU 信息」:当前使用的 CPU 是飞思卡尔(属于NXP)的 I.MX6ULL (频率为 792MHz),此时运行在 396MHz。这颗芯片是工业级的,结温为-40°C~105°C
- 第 5 行是 「复位原因」:I.MX6ULL 芯片上有个 POR_B 引脚,将这个引脚拉低即可复位 I.MX6ULL。
- 第 6 行是 「板子名字」,“I.MX6U ALPHA|MINI”即开发板的名字 。
- 第 7 行提示 「I2C 准备就绪」。
- 第 8 行提示当前板子的 「DRAM(内存)」 为 512MB
- 第 9 行提示当前有 「两个MMC/SD 卡控制器」:FSL_SDHC(0)和 FSL_SDHC(1)。
I.MX6ULL支持两个 MMC/SD,正点原子的 I.MX6ULL EMMC 核心板上 FSL_SDHC(0)接的 SD(TF)卡,FSL_SDHC(1)接的 EMMC
。 - 第10行是一条警告信息,先忽略。
- 第 12、13 行是 「LCD 型号」,原厂默认的是TFT43AB (480x272)。
- 第 14~16 是 「标准输入、标准输出和标准错误」 所使用的终端,这里都使用串口(serial)作为终端。
- 第 17 、18行是 「切换到emmc的第0个分区上」,因为当前的 uboot 是 emmc 版本的,也就是从 emmc 启动的。我们只是为了方便将其烧写到了 SD 卡上,但是它的“内心”还是 EMMC的。所以 uboot 启动以后会将 emmc 作为默认存储器 。
- 第 19行是 「网口信息」,提示我们当前使用的 FEC1 这个网口,I.MX6ULL 支持两个网口。
- 第 20行提示 「FEC1网卡地址没有设置」(后面我们会讲解如何在uboot 里面设置网卡地址)。
- 第 22行提示 「正常启动」, 也就是说 uboot要从emmc里面读取环境变量和参数信息启动 Linux内核了。
- 第23行是 「倒计时提示」,默认倒计时 3 秒,倒计时结束之前按下回车键就会进入 Linux 命令行模式。如果在倒计时结束以后没有按下回车键,那么 Linux 内核就会启动,Linux 内核一旦启动,uboot 就运行结束了。
- 第23行是在倒计时 3 秒内按了回车键,符号
=>
表示可以继续与uboot进行 「命令交互」。