一、内核源码
1、首先,源码可以从官网进行下载,官网地址是
本教程使用的是5.7.1,也可以从如下网址直接下载
https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.7.1.tar.gz
将下载好的压缩包放在提前准备好的路径/usr/local/f1c200s/kernel下面
2、如同u-boot,kernel也需要进行配置,且内核源码里面也有全志官方的配置文件sunxi_defconfig。但是若要适配f1c200s,仍需要修改很多其他的参数,所以我们使用比较完备的licheepi的配置文件。
配置文件下载地址
链接:https://pan.baidu.com/s/1VCKU3mChoZ2fUkkayI6WkQ?pwd=k7d6
下载之后将配置文件放置在内核同样的位置,/usr/local/f1c200s/kernel
二、源码配置
1、首先进入目录/usr/local/f1c200s/kernel,对源码进行解压缩
#进行内核源码解压缩
tar -vxf linux-5.7.1.tar.gz
#然后进入解压出来的目录
cd linux-5.7.1
2、解压缩之后,配置架构和交叉编译器。这里同样可以使用grep命令,查看CROSS_COMPILE的位置(但是实际上源代码里面并没有定义,需要手动添加)
#首先执行vim命令,打开Makefile文件
vim Makefile
#然后在Makefile文件的开头位置,添加如下代码,用来指定架构和编译器
ARCH ?= arm
CROSS_COMPILE ?= arm-linux-gnueabi-
3、修改完Makefile之后,再对设备树进行修改。linux设备相关模型大致为 总线->>驱动->>设备。
a、总线比如说iic总线,spi总线,是一大类的统称,其中有一个比较特殊的是platform总线,表示的是没有明确归类的虚拟的总线,比如要控制一个io口可能就需要用到它。我们平时用的最多的就是虚拟总线。
b、驱动,自然就是控制设备运行的驱动程序,它和设备相互组合。
c、linux中,设备和驱动的组合,是内核自动匹配的。所以呢,假如我们要实现一个设备的功能,我们就需要注册设备和驱动,并指出设备所需要的驱动名称,内核匹配完成,就可以正常驱动设备了。
d、为了方便归纳设备,linux把原本需要从代码中添加设备的方式,变更为设备树文件的方式,这样,添加设备的时候就不需要修改代码,只需要在设备树文件.dts里面添加,在内核编译的过程中,设备树文件会被编译成dtb,被内核直接调用。
4、设备树文件之所以叫树,就是因为设备之间存在着关系,就像树一样,有主干有枝干。一个设备就是一个节点,所有的节点都挂在根节点下,f1c200s根节点以下有三个重要的节点,分别是clocks,cpus,soc。意如其名。
#include "suniv-f1c100s.dtsi" //设备树文件也可以像c语言一样加载其他的设备文件
/{ //根节点
...
clocks{ //时钟节点
... //每个节点下都会有对应的配置信息
}
cpus{
... //子节点下还可以有自己的子节点
}
...
}
5、博主使用的硬件,是用TF卡启动的,而官方配置里面是用spiflash启动的,所以呢,就需要在设备树文件里面添加mmc设备(TF卡)
a、首先进入目录/usr/local/f1c200s/kernel/linux-5.7.1/arch/arm/boot/dts,打开文件suniv-f1c100s.dtsi,在节点soc->pio下添加如下内容,进行引脚申请。
mmc0_pins: mmc0-pins { //分号之前是给节点起的名字
pins = "PF0", "PF1", "PF2", "PF3", "PF4", "PF5"; //申请引脚
function = "mmc0"; //指定设备
};
b、依然是文件suniv-f1c100s.dtsi,在soc节点下,添加mmc0设备
mmc0: mmc@1c0f000 { //@后面是设备的地址
compatible = "allwinner,suniv-f1c100s-mmc", //这里是指定厂商和驱动,有两个参数,表示
"allwinner,sun7i-a20-mmc"; //此设备支持这两种驱动,内核会依次查找匹配
reg = <0x01c0f000 0x1000>; //这里是从芯片手册得到的寄存器地址和长度
clocks = <&ccu CLK_BUS_MMC0>, //这里是此设备需要用到的时钟
<&ccu CLK_MMC0>,
<&ccu CLK_MMC0_OUTPUT>,
<&ccu CLK_MMC0_SAMPLE>;
clock-names = "ahb", //给时钟起的名字
"mmc",
"output",
"sample";
resets = <&ccu RST_BUS_MMC0>; //指定复位单元
reset-names = "ahb";
interrupts = <23>; //中断号,和芯片手册相对应
pinctrl-names = "default"; //引脚名称
pinctrl-0 = <&mmc0_pins>; //引脚列表,就是在soc->pio内定义的节点
status = "disabled"; //状态设为关闭
#address-cells = <1>; //设置子节点的地址占用大小
#size-cells = <0>; //设置子节点寄存器尺寸描述占用大小
};
c、当然不能忘了,在文件suniv-f1c100s.dtsi的开头位置,添加两个头文件,不然设备节点上面调用的时钟就找不到定义的位置了。
#include <dt-bindings/clock/suniv-ccu-f1c100s.h>
#include <dt-bindings/reset/suniv-ccu-f1c100s.h>
d、再接下来,就需要修改suniv-f1c100s-licheepi-nano.dts了,同样是在路径/usr/local/f1c200s/kernel/linux-5.7.1/arch/arm/boot/dts下,打开文件suniv-f1c100s-licheepi-nano.dts。细心的读者就会发现,在文件的开头,已经把suniv-f1c100s.dtsi加载进来了。
两个文件的两个根节点,其实就是同一个根节点。在根节点下添加3.3v设备。在根节点之外,启动mmc设备。
reg_vcc3v3: vcc3v3 {
compatible = "regulator-fixed";
regulator-name = "vcc3v3";
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
};
&mmc0 {
vmmc-supply = <®_vcc3v3>;
bus-width = <4>;
broken-cd;
status = "okay";
};
e、做完上面的操作,设备树就已经配置完成啦。
6、配置完设备树,然后就可以进行菜单配置了。
#首先进入目录
cd /usr/local/f1c200s/kernel
#解压缩licheepi的官方配置
unzip linux-licheepi_nano_defconfig.zip
#将配置文件复制到指定目录
cp linux-licheepi_nano_defconfig linux-5.7.1/arch/arm/configs/
#进入内核源码目录
cd linux-5.7.1
#在进行最终配置的时候,先安装一些必须的插件
sudo apt-get install flex
sudo apt-get install bison
sudo apt-get install openssl
sudo apt-get install libssl-dev
sudo apt-get install bc
#将licheepi官方配置套用到源码
make linux-licheepi_nano_defconfig
如果还需要配置其他的参数,还可以通过执行make menuconfig进行菜单配置。最后,执行make命令,进行编译
7、编译完成之后,会在路径/usr/local/f1c200s/kernel/linux-5.7.1/arch/arm/boot下,生成zImage,会在路径/usr/local/f1c200s/kernel/linux-5.7.1/arch/arm/boot/dts下,生成文件suniv-f1c100s-licheepi-nano.dtb。这两个文件就分别是内核和设备树。
三、TF卡分区
1、u-boot那一篇讲过,在芯片启动的时候,soc会自动的从启动位置(TF卡)读取4k内容,而这4k内容,在tf卡上就是开头的绝对物理地址。
2、上一篇也讲过,u-boot启动以后,会从mmc读取内核和设备树到内存。所以tf卡是需要我们提前分区处理好,并且要提前把内核和设备树文件放入到指定位置。
3、ubuntu下有gparted软件,可以很方便的对TF卡进行分区,而且是界面操作。
4、首先把TF卡的开头2M预留出来,用作u-boot的存储。
5、接着2M的空间,设置32M大小的区域,并且设置文件系统为fat16格式。u-boot配置时有命令load mmc 0:1 0x80008000 zImage;等,就是从这个空间复制文件到内存,因为u-boot只能识别fat16格式,所以格式设置为fat16,名称设置为boot。
6、在之后的TF卡剩余空间,可以根据需求设置大小,但是最小不能小于100M,因为这里是放根文件系统的地方。把这个区域设置为ext4文件系统,设置名称为roots。
7、接下来,就可以使用mount命令挂载磁盘了。使用cp命令,将文件zImage和suniv-f1c100s-licheepi-nano.dtb复制到boot内。完成后记得使用umount卸载磁盘。
8、最后,将TF卡插入到开发板上,上电,就可以看到加载内核的打印信息。