本文的主要内容是Linux下通过tftp烧写设备树文件并启动开发板,通过给设备树中添加自定义节点这个例子来学习这一整套流程,文中会涉及到设备树节点的添加与编译、开发板环境参数的设置与修改等内容。
连接好开发板后上电,打开开关,板子启动并打印如下信息。
上图中内核启动时打印的时间信息就是你烧写到内核中的内核映像压缩文件zImage最后的编译时间。(我们后续添加成功设备树节点后再次启动时,这个时间会变化)
仔细查看上面图中的这段信息,尤其是下面的几行。
CPU: Freescale i.MX6DL rev1.3 996 MHz (running at 792 MHz)
Board:MX6-SabreSD
reading imx6dl-c-sabresd.dtb
通过这些启动信息我们可以知道自己板子的型号信息,启动时要读取的设备树文件,这对后续给设备树中添加自定义节点至关重要,因为涉及到设备树文件的选择。
没有添加设备树节点之前先登录进去,看看开发板中已存在的节点,方便后续做对比。
我们发现此时还没有gpios这个设备树节点,我们接下来的例子就是添加名为gpios的节点。
通过板子的启动信息我们知道了要用到的设备树文件是imx6dl-c-sabresd.dtb(注意:开发板不同,这里的文件也不一样,一定要注意选择正确的设备树文件添加节点,这非常重要!!!否则在开发板启动时会遇到问题)。
在/linux-4.1.15/arch/arm/boot/dts/目录下找到设备树文件imx6dl-c-sabresd.dts并打开。
我们看到它包含了imx6dl.dtsi头文件,再找到imx6dl.dtsi打开,并添加如下代码。
gpio_user: gpios{
pinctrl-names = "default";
compatible = "gpio-user";
gpio0{
label = "D01";
gpios = <&gpio3 15 1>;
default-direction = "out";
};
gpio1{
label = "D02";
gpios = <&gpio2 21 1>;
default-direction = "out";
};
};
再打开文件imx6dl-c-sabresd.dts并添加如下代码。
&gpio_user{
pinctrl-names = "default";
fsl,user;
status = "okay";
test1:test{
#address-cells = <1>;
#size-cells = <1>;
compatible = "test";
reg = <0x20ac000 0x0000004>;
status = "okay";
};
};
&test1{
compatible = "test123"; //编译后,"test123"会替换上面定义中的"test"
};
上面添加成功了设备树节点,保存文件,然后打开WSL来编译我们刚才修改过的设备树文件。
先使能环境变量,命令如下。
. /opt/fsl-imx-x11/4.1.15-2.1.0/environment-setup-cortexa7hf-neon-poky-linux-gnueabi
接着编译设备树文件,使用命令如下。
make dtbs
上面的命令是编译所有的设备树文件,也可以使用下面的命令单独编译imx6dl-c-sabresd.dts文件。
make imx6dl-c-sabresd.dtb
如下图,由于我们上面已经编译过,所以再次编译没有什么改动。
有人可能会担心,咱们上面修改了两个设备树文件,这里编译一个可以吗?答案是肯定的,因为imx6dl-c-sabresd.dts文件中包含了imx6dl.dtsi头文件,所以在编译的时候,改动过的imx6dl.dtsi文件也会被一起编译。
当然你也可以使用make命令将内核映像文件和设备树一起编译。
如果你的驱动有修改,在make后,内核映像文件Image和内核映像压缩文件zImage都会进行更新。
到这里,我们的设备树文件就准备好了。
在根目录下新建一个tftp文件夹,将上面编译过的imx6dl-c-sabresd.dtb文件复制到该目录下。
同时将内核映像压缩文件zImage复制到该目录下。(注:这里不复制zImage文件也可以,如果你没有重新编译内核的话)
如果你的wsl文件夹没有添加到网络位置这里。
先在此电脑所在的文件夹下右键,选择添加一个网络位置按下图中设置(版本名称因人而异)进行添加。
打开MobaXterm工具,(非常好用的一款工具,点此下载)在Servers下使用TFTP功能,注意选择的根目录一定要正确,tftp这级目录就是刚刚新建的文件夹。
防火墙这里一定要允许访问。
这样就好了,在后面使用tftp命令时,回到这里打开tftp即可,由于tftp每次打开只有6分钟(360秒),倒计时完成后自动关闭,所以在后面传输时,遇到下面这种情况时,记得返回这里再次打开tftp即可。
在板子启动(或按复位键)时按Enter键进入到u-boot引导,相当于电脑开机时进入BIOS一个道理。
输入0后再输入help,重点关注下面这两个。
其中printenv是打印环境变量,setenv是设置环境变量。
未设置环境变量之前的信息,重点关注圈住的参数在环境变量设置前后的对比。
接着来设置环境变量,这是本文中的重中之重。
setenv serverip 192.168.0.2
//这是电脑的IP,这个IP因人而异,注意查看自己的
setenv ipaddr 192.168.0.232
//这是开发板的IP,可以通过ifconfig命令在开发板上查看
setenv image zImage
//内核镜像压缩文件
setenv fdt_file imx6dl-c-sabresd.dtb
//设备树文件,一定要和你开发板启动时读取的文件一致
setenv mmcboot 'echo Booting from mmc ...; run mmcargs; tftp ${loadaddr} zImage;tftp ${fdt_addr} imx6dl-c-sabresd.dtb; bootz ${loadaddr} - ${fdt_addr};'
//修改mmcboot属性值
saveenv
//保存环境变量的修改
设置环境变量的截图如下。
再次打印环境变量。
发现我们设置的环境变量已经生效了。
重启开发板之前先开启tftp,这很重要!!!否则在传输zImage和imx6dl-c-sabresd.dtb文件时会失败。
按下复位键,等待开发板重启。
打印信息如下图。
我们看到zImage和imx6dl-c-sabresd.dtb文件通过IP已经发送成功了。
再来看看内核启动时所打印的时间。
这里的时间和开始没有配置环境变量时相比较已经变化了。
这个时间正是/linux-4.1.15/arch/arm/boot/目录下zImage的最后编译时间。(注:如果你没有将zImage放进tftp文件夹,这里的时间不会改变,和没有设置环境变量时的时间相同,一般情况下,如果你没有重新编译内核,只是编译了设备树,tftp文件夹里复制进去imx6dl-c-sabresd.dtb这一个文件就行了,不会影响后面设备树节点的添加)
登录进去后来到/proc/device-tree/目录下,查看一下设备树节点,发现我们新添加的gpios节点已经添加进去了,这就说明我们通过tftp将zImage和dtb文件烧写到开发板并成功启动了。
下面的指令均可查看设备树节点,其功能是相同的。
cat /proc/device-tree
cat /sys/firmware/devicetree/base
进到gpios文件中,查看一下。
对比上文中的代码,这确实是通过代码添加进去的,而且compatible的属性"test123"确实替换了"test"。
如果我们不慎保存了不想要的环境变量,要回到最初默认的环境变量,那么就可以通过如下命令设置。
env default -a
saveenv
运行的截图如下。
再来看一次我们的环境变量。
和没有设置环境变量时的信息一致!
以上就是Linux下通过tftp烧写设备树文件并启动开发板的所有内容了,这里提醒大家一定要注意根据自己开发板的启动信息去修改设备树文件中对应的设备树文件,而且不要忘了在设置好环境变量重启开发板之前打开tftp,修改设备树并烧写到开发板在以后会经常用得到,所以熟练掌握这部分技能相当重要!
参考博文:Linux嵌入式uboot使用tftp网络启动加载zImage、dtb到内存,文件系统本地启动