用NFSRoot和TFTP启动你的嵌入式设备
介绍
最近在学习嵌入式Linux设备驱动开发。在刚开始学习的时候,一个比较大的痛点是总是需要把编译好的二进制文件想方法搬到设备上。对于比较小的文件比如内核驱动或者Userland程序,总是可以用scp之类的工具解决。但到了学习后期涉及到更改内核源代码,以至于要更改SDCard上的内核镜像后,可以使用的工具就比较有限了。除非你可以忍受每次更改源代码都把内核搬到SDCard或者其他储存介质上。
在经过一番搜索后,发现了一个嵌入式设备可以使用的启动模式,就是用NFSRoot和TFTP加载根文件系统(ROOTFS)和内核,而且这种启动方法对于节约将二进制文件拷贝到储存介质的次数很有帮助。
比如我在家中的网络(配置如下)使用笔记本进行开发,同时网络上还有嵌入式开发板和另外一个服务器。服务网络因为使用有线连接比较稳定。使用NFSRoot和TFTP让我可以将开发板的RootFS,内核镜像和dtb等文件放在服务器上。开发版启动时,会当即读取服务器上的内核到内存中的指定地址,然后用其启动设备。开发板启动后,在内核加载时会读取服务器上的RootFS作为根目录并启动系统。
这样子的设置意味着开发板启动后的“硬盘”已经已经不再开发板上,而是在服务器上了!如果用终端或SSH连接开发板并更改储存一些文件,这些改动会直接反映在服务器上。更重要的是,你直接连接服务器对RootFS的改动开发板能实时接收到。

步骤:
安装和设置TFTP服务器
很多嵌入式bootloader支持通过TFTP加载内核镜像和设备树,这对于系统开发、驱动开发人员是非常方便的。这让开发人员可以在开发电脑上编译内核和设备树,把编译好的内核与设备树放在TFTP上。然后,在嵌入式设备上,只需重新启动系统并在BootLoader中通过TFTP就可以加载新的内核,而无需拔下scdard烧录文件系统和新内核。那么具体怎么使用TFTP呢?
接下来的步骤假设你使用Linux作为你的操作系统。首先要安装TFTP服务器,对于基于Debian的系统,可以使用如下命令:
apt-get install tftpd-hpa # 安装完成后启动tftp服务器 service tftpd-hpa start
根据操作系统的不同,默认TFTP的根目录也不一样。若要查看TFTP的根目录可以到/etc/default/tftpd-hpa件里找到如下行:
TFTP_DIRECTORY="/srv/tftp"
在TFTP根目录下我们可以创建一个目录如下并放入我们为嵌入式设备编译好的内核与设备树:
/svr/tftp
test_new_kernel
devicetree.dtb
uImage
想要设备加载这个内核,我们需要提供一个启动脚本,假设其名为bootscript_new_kernel,我们可以将它放在/svr/tftp目录下:
/svr/tftp
test_new_kernel/
devicetree.dtb
uImage
bootscript_new_kernel
bootscript_new_kernel的具体内容我们一会儿再细讲。
这下我们把TFTP就大致设置好了。要知道,仅仅是有内核的嵌入式设备是没有办法启动的,我们还需要提供根文件系统并提供启动程序(init)才能让嵌入式设备成功启动。接下来我们讲讲怎么用NFSRoot来作为设备的跟文件系统。