目录
一、前言
二、F1C200s上电启动顺序
三、前期准备
四、新建用户
五、交叉编译环境配置
六、uboot简介
七、uboot移植
uboot下载
uboot默认配置
uboot图形界面配置
uboot编译
烧录bin文件
八、uboot启动测试
九、参考内容
在移植Linux之前我们需要先移植一个bootloader代码,这个bootloader代码用于启动Linux内核,bootloader有很多,常用的就是 uboot。移植好uboot以后再移植Linux内核,移植完Linux内核以后Linux还不能正常启动,还需要再移植一个根文件系统(rootfs),根文件系统里面包含了一些最常用的命令和文件。所以uboot、Linux kernel 和 rootfs 这三者一起构成了一个完整的Linux系统,一个可以正常使用、功能完善的 Linux 系统。
-- 来自正点原子嵌入式Linux驱动开发指南。
Linux系统要启动就必须需要一个bootloader程序,也就说芯片上电以后先运行一段bootloader程序。这段 bootloader 程序会先初始化DDR等外设,然后将 Linux 内核从 flash(NAND,NOR FLASH,SD,MMC等)拷贝到DDR中,最后启动Linux内核。下面我们首先进行uboot的移植,或者说适配。
在进行uboot移植之前,需要了解F1C200s芯片上电后启动的顺序,避免重复造轮子,我们直接根据F1C100s启动时搜索SPI Flash的顺序?了解到启动顺序如下,F1C200s同F1C100s。
1. 上电后, f1c100s内部 BROM (芯片内置,无法擦除) 启动,
2. 首先检查 SD0 有没有插卡, 如果有插卡就读卡 8k偏移数据,是否是合法的启动数据, 如果是BROM 引导结束, 否则进入下一步
3. 检测SPI0 NOR FLASH(W25QXXX, MX25LXXX) 是否存在, 是否有合法的启动数据, 如果是BROM 引导结束, 否则进入下一步
4. 检测SPI0 NAND FLASH 是否存在, 是否有合法的启动数据, 如果是BROM 引导结束, 否则进入下一步
5. 因为找不到任何可以引导的介质, 系统进入usb fel 模式, 可以用USB烧录了。
上电之后,F1C200s芯片内部的BROM启动检查到SD卡,读取8k偏移数据。
注意:这里的
bs=1024 seek=8
是添加了8192字节的偏移,之所以要加8K偏移是因为FSBL也就是bootROM里面硬写死了会从设备的8K地址处加载SPL,然后进入uboot。因此上面烧写的时候,指定的偏移地址一定是相对于储存设备硬件的偏移,而不是相对于分区的偏移!来自:peng-zhihui/Planck-Pi: Super TINY & Low-cost Linux Develop-Kit Based On F1C200s.
虚拟机VmwareWorkstation安装;
ubuntu16.04系统安装。
如果你已经再当前用户安装了一些其他的编译器,那么最好创建一个新的账户,避免一些命令可能出现干扰,或者说与其他项目隔离开,具体操作如下,比较简单,看图操作即可。
在路径 “ linaro release->compoments->toolchain->binaries->7.2-2017.11->arm-linux-gnueabi->gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi.tar.xz ” 中下载对应的交叉编译器,记住是release版本,不是snapshots版本。(Snapshot版本代表不稳定、尚处于开发中的版本,快照版本。Release版本则代表稳定的版本,发行版本。)具体链接如下:
Linaro Releaseshttps://releases.linaro.org/components/toolchain/binaries/7.2-2017.11/arm-linux-gnueabi/下载完成,使用如下面命令解压缩:
tar -vxf gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi.tar.xz
将解压的文件复制到/usr/local/arm/中,操作命令如下:
sudo cp -rf /home/project01/pro01/gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi ./
然后添加该交叉编译器的环境变量,只有这样编译器才能在任何目录或者任何位置打开的终端中执行,打开~/.bashrc文件 (修改.bashrc文件
,只是针对某一个特定的用户;修改/etc/profile文件
,它是针对于所有的用户),写入以下内容:
export PATH=$PATH:/usr/local/arm/gcc-linaro-7.2.1-2017.11-x86_64_arm-linux-gnueabi/bin
使环境变量生效:
source ~/.bashrc
验证是否成功:
arm-linux-gnueabi-gcc -v
bootloader主要的工作就是启动 Linux 内核,bootloader和 Linux内核的关系就跟PC上的BIOS和 Windows的关系一样,bootloader就相当于BIOS。常见的bootloader有 U-Boot、vivi、RedBoot 等等。
本文使用uboot作为系统的bootloader,它的全称是"Universal Boot Loader",意为"通用引导加载程序"。uboot是一种裸机程序,可以视为是一个汇集了多种裸机功能的综合示例。目前的uboot已经支持液晶显示屏、网络连接、USB等高级功能。
uboot官方会维护uboot源码,也是最原汁原味的源码,但是官方提供的代码是供半导体厂商,也就是生产F1C200s的厂商使用的,他们会维护一个定制版本的uboot,但是,很遗憾,全志并没有将资料公开。(注:后来发现,这里有全志的uboot,不知道这个是否是官方的网站,但已经好久没有更新)由于网上关于F1C200s的uboot从零开始的开发资料几乎没有,此处我们使用荔枝派的uboot启动Linux。(后面有时间再完善,欢迎大佬加群或评论区指导)
首先在github上下载Lichee-Pi提供的uboot,当然,前提是你的虚拟机能访问网络,如果不会配置,参看我左侧专栏虚拟机中的文章即可。或者直接在Windows中github上下载,然后传到ubuntu中解压。
uboot下载完成后,打开文件夹,uboot文件内容如下图所示:
对于同一款芯片,比如F1C200s,可能有不同的外设,uboot需要初始化的内容也不相同,因此需要选用uboot中的某些配置,去初始化各个外设,在uboot中的configs文件夹中存储着一些配置“套餐”,就是已经固定配置某些外设的默认配置文件,一旦进行编译,uboot会根据这个配置文件进行配置。
如上图所示,为uboot的configs目录下的两个荔枝派的配置文件,第一个licheepi_nono_defconfig 是针对TF卡的配置文件,第二个licheepi_nano_spiflash_defconfig是针对flash的启动文件,显然我们需要选择第一个配置文件编译uboot,因为我们只有TF卡一种存储介质,没有flash。下面是编译指令:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- licheepi_nano_defconfig
为了避免使用类似于上方的繁琐编译指令,在uboot根目录Makfile中加入如下内容:
这样我们可以通过以下简洁的代码进行uboot配置:
# 进入u-boot目录
cd u-boot/
# 加载配置文件
make licheepi_nano_defconfig
经过以上操作,默认配置文件licheepi_nano_deconfig已经写入到,/uboot/.config文件中,这是根据默认配置文件,生成的uboot的最终配置文件,这个配置文件记录了所有配置选项的宏开关,我们可以通过宏开关对其进行修改。
注意:硬件中USB T口连接uart0,而荔枝派默认初始化uart0,因此无需修改。
使用make menuconfig命令进行图形界面配置uboot。
Enable boot arguments 选项上点击空格,弹出Boot arguments选项,选中回车输入以下内容后回车保存。
console=ttyS0,115200 panic=5 rootwait root=/dev/mmcblk0p2 earlyprintk rw
同样的操作输入bootcmd的值,输入完成后如下图所示,有关bootargs和bootcmd值的含义,后序文章进行分析,这里不做解释。
load mmc 0:1 0x80008000 zImage;load mmc 0:1 0x80c08000 suniv-f1c100s-licheepi-nano.dtb;bootz 0x80008000 - 0x80c08000;
在进行编译之前需要在Ubuntu 中安装 ncurses 库,否则可能编译会报错,安装命令如下:
sudo apt-get install libncurses5-dev
使用make -j2进行编译,其中-j2代表处理器核心数。编译完成,在根目录下找到u-boot-sunxi-with-spl.bin文件,该文件为最终烧录文件。
只要将u-boot-sunxi-with-spl.bin烧录到tf卡的8k偏移地址处就可以了,至于为什么,上面的引用已经解释清楚了。将准备号的TF卡插入读卡器,使用如下块搬移命令进行烧写:
sudo dd if=u-boot-sunxi-with-spl.bin of=/dev/sdb bs=1024 seek=8
if 文件名:输入文件名,缺省为标准输入。即指定源文件。< if=input file >
of 文件名:输出文件名,缺省为标准输出。即指定目的文件。< of=output file >
bs bytes:同时设置读入/输出的块大小为bytes个字节。
seek blocks:从输出文件开头跳过blocks个块后再开始复制。
这里的输出文件(of)为主机电脑的/dev/sdb文件,也就是插入的读卡器代表的TF卡。
烧录完成,如下图所示,然后弹出读卡器之后再拔出,否则可能损坏读卡器。
将开发板使用数据线与电脑相连,打开串口调试工具,根据bootargs参数设置串口通信参数:
正常启动,窗串口调试工具为SecureCRT,选中端口后,波特率设置为115200:
墨云:
因为在你插入USB通电的时候开发板就已经启动了,所以当你打开串口连接的时候可能未必会看到信息,所以按一下重启键,就可以看到如下的输出信息了,这就是我们的u-boot,执行到u-boot计数完成后会产生错误,那是因为我们还没有进行系统内核的移植,所以默认就会进入u-boot命令模式。
点击复位按钮之后,在3秒之内(我设置的5秒)点击回车即可进入uboot命令模式,在 uboot命令模式输入“print”来查看环境变量 bootargs和bootcmd的值如下,和我们设置的相同,表示uboot启动成功!
至此,完成uboot移植全部内容,然而并没有像我想的那样,从零开始,按照官方的uboot一步一步自己移植,谁让我是个小白呢。
1. 墨云uboot移植;
2. 稚辉君github项目;
3. 正点原子《嵌入式Linux驱动开发指南》