文章参考自:Embedded Linux Beginners Guide
硬件设计
本指南采用的硬件设计为自定制硬件设计:My_GHRD。关于该自定制硬件设计:My_GHRD的设计过程详见:《HPS SoC和FPGA联合使用例程》的My_GHRD工程部分。
生成对FPGA进行编程所需的原始二进制文件
- 如果您要进行自定义设计,并且想知道如何生成.rbf文件,请按照以下步骤操作:
- 在Quartus中,打开 “Convert Programming Files” 窗口(File→Convert Programming Files)。
- 在“Programming file type”中,选择“Raw Binary File (.rbf)”
在“Mode”中,选择“Passive Parallel x16”(这是从Linux进行硬件编程的默认模式)。 - 在“File name”栏为生成的文件选择一个名称(我命名为:soc_system.rbf)。
- 单击“Input files to convert”部分中的“SOF Data”,然后单击“Add File…”按钮,并浏览以找到需要转换的.sof文件。
- 选中刚添加的.sof文件所在行,点击右侧的“Properties”按钮“。
您的窗口应如下所示:
-
在“Sof File Properties”窗口勾选“Compression”。点击“OK”退出。
-
返回“Convert Programming Files”窗口后,单击“Generate”,然后软件将会在My_GHRD工程目录下将创建您的.rbf文件:soc_system.rbf,最后点击“Close”。
生成预加载器Preloader
启动BSP编辑器
打开“SoC EDS Command Shell”。进入My_GHRD工程目录。
cd /cygdrive/e/Work/Quartus/My_GHRD
启动BSP编辑器
bsp-editor &
在“ BSP Editor”窗口中,选择“File→New HPS BSP…”,为开发板的预加载器创建一个新的BSP项目。
单击“Preloader settings directory”旁边的“…”按钮,浏览至“ My_GHRD\hps_isw_handoff\soc_system_hps_0”,然后单击“Open”。其他选项选择默认,点击:OK。
配置预加载器
在“Settings”下的左侧树视图中,单击“Common”。这将为您显示最重要的设置:boot 选项,告诉预加载器在哪里可以找到bootloader。就像我们必须通过BSEL引脚告诉Boot ROM在哪里找到预加载器一样,这些选项也告诉预加载器在哪里找到bootloader。可以看出,您可以将引导加载程序放置在QSPI Flash,NAND Flash,RAM或SD卡中。确保将BOOT_FROM_SDMMC启用,因为我们会将U-Boot放入SD卡中。
我们还将U-Boot放在上述SD卡的FAT分区上,因此请确保启用FAT_SUPPORT并将FAT_BOOT_PARTITION设置为“ 1”(在格式化SD卡时,我们将确保分区位于放入U-Boot,将在分区1)。最后,确保FAT_LOAD_PAYLOAD_NAME设置为“ u-boot.img”。可以推断,这是预加载程序将查找的U-Boot映像的名称。
(注意:如果未启用FAT_SUPPORT,则必须将引导加载程序放置在SD卡上的地址0x40000处,以使系统成功找到引导加载程序。)
其他选项可以选择默认配置,然后点击:Generate。最后点击:Exit退出。
此时My_GHRD工程目录下将会生成“software”文件夹,里面包含制作预加载器Preloader的相关文件。
编译预加载器
回到“SoC EDS Command Shell”并进入到新的“software/ spl_bsp”目录下,ls可以看到新的文件。
cd software/spl_bsp/
ls
接下来,我们需要通过设置CROSS_COMPILE环境变量来告诉preloader(和其他makefile)使用此工具链进行编译。(在每次关闭shell后,请记住重新导入此变量。)
export CROSS_COMPILE=/cygdrive/e/Work/Quartus/My_GHRD/software/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
使用“make clean”命令,来清除之前的编译结果。
make clean
输入:make命令进行编译。
make
编译之后,您将找到一个新的“ uboot-socfpga”目录,该目录包含一个名为“ spl”的子文件夹,该子文件夹包含用于合并生成的代码的辅助程序加载器的代码。还有一个新的“ preloader-mkpimage.bin”文件,其中包含预加载器映像和“引导ROM标头”,引导ROM将其识别为实际的预加载器映像是必需的。稍后,我们会将该文件刻录到SD卡。
(注意:Windows10系统下进行编译时,会产生报错:
tar zxf /cygdrive/c/intelFPGA/18.0/embedded/host_tools/altera/preloader/uboot-socfpga.tar.gz
tar: Error opening archive: Failed to open '/cygdrive/c/intelFPGA/18.0/embedded/host_tools/altera/preloader/uboot-socfpga.tar.gz'
make: *** [uboot-socfpga/.untar] Error 1
根据Unable to make preloader in Windows 10中提供的解决方案需要对软件进行如下修改:
-
替换下面目录中的Makefile.template文件
C:<installation_directory>\embedded\ip\altera\preloader\src\Makefile.template
下载Makefile.template文件(将原来的Makefile.template文件增加后缀保留,然后解压并替换原来的Makefile.template) -
更改下面目录中内容
C:<installation_directory>\embedded\host_tools\cygwin\etc\fstab
使用“#”注释掉原来的命令:#non /cygdrive cygdrive binary,posix=0,user 0 0
然后添加下述命令:none /cygdrive cygdrive binary,posix=0,user,noacl 0 0 -
如果做完上述更改后,使用
make
命令仍然无法编译的话,可以把原来生成的software文件夹删除,然后重新启动BSP编辑器bsp-editor.exe生成software文件夹,最后执行make
命令编译预加载器。)
配置和编译U-Boot
编译U-Boot
在前面编译生成预加载器映像preloader-mkpimage.bin文件的同时,spl文件夹下也生成了一个新的“ uboot-socfpga”目录。
在spl文件夹目录下,运行make uboot
命令。
make uboot
这时可以在uboot-socfpga目录中可以看到生成的U-Boot的镜像文件u-boot.img,稍后,我们会将该文件刻录到SD卡。
编写启动脚本
如前所述,启动脚本是U-Boot命令的列表,每当设备启动时,U-Boot命令都会自动运行(并且您无需敲击任何键即可进入命令外壳)。该脚本将对FPGA进行编程,加载设备树,加载内核,并使用一组启动参数运行内核。
在软件目录中创建一个名为“ boot.script”的新文件,并复制以下内容:
echo -- Programming FPGA --
fatload mmc 0:1 $fpgadata soc_system.rbf;
fpga load 0 $fpgadata $filesize;
run bridge_enable_handoff;
echo -- Setting Env Variables --
setenv fdtimage soc_system.dtb;
setenv mmcroot /dev/mmcblk0p2;
setenv mmcload 'mmc rescan;${mmcloadcmd} mmc 0:${mmcloadpart} ${loadaddr} ${bootimage};${mmcloadcmd} mmc 0:${mmcloadpart} ${fdtaddr} ${fdtimage};';
setenv mmcboot 'setenv bootargs console=ttyS0,115200 root=${mmcroot} rw rootwait; bootz ${loadaddr} - ${fdtaddr}';
run mmcload;
run mmcboot;
具体的解释可以参考文首链接的英文网站。
编译启动脚本
U-Boot要求将启动脚本编译为二进制文件。运行以下命令以编译启动脚本。
mkimage -A arm -O linux -T script -C none -a 0 -e 0 -n "Boot Script Name" -d boot.script u-boot.scr
这样,U-Boot就完成编译并准备就绪了!后面我们会把得到的uboot启动脚本文件u-boot.scr和uboot映像文件u-boot.img一起刻录到SD卡。
生成和编译设备树
使用cd命令返回My_GHRD工程目录下(假设当前目录为:“ spl_bsp”子目录中)。
cd ../
cd ../
运行以下命令以创建设备树源文件soc_system.dts。
sopc2dts.exe --input soc_system.sopcinfo --output soc_system.dts --type dts --board soc_system_board_info.xml --board hps_common_board_info.xml --bridge-removal all --clocks
生成设备树二进制文件soc_system.dtb。
dtc -I dts -O dtb -o soc_system.dtb soc_system.dts
此时,My_GHRD工程目录下创建了一个名为“ soc_system.dtb”的设备树二进制文件。稍后,我们会将该文件刻录到SD卡。
配置和编译内核
现在,我们将获得linux-socfpga-socfpga-4.5.zip的源代码压缩文件,然后进行解压、配置和编译。
源代码准备
打开虚拟机,创建并进入“~/resource/de10-std
”(若已有该目录便不用创建)。
sking@ubuntu:~$ mkdir -p resource/de10-std
sking@ubuntu:~$ cd resource/de10-std
然后将我们需要的linux-socfpga-socfpga-4.5.zip的源代码压缩文件放到“~/resource/de10-std
”目录下并解压。
sking@ubuntu:~/resource/de10-std$ unzip linux-socfpga-socfpga-4.5.zip
为了避免损坏所用的各种资源文件,接下来创建一个工作目录“~/work/de10-std
”(若已有该目录便不用创建),然后将解压后的linux-socfpga-socfpga-4.5.zip的源代码linux-socfpga-socfpga-4.5放到“~/work/de10-std
”目录下。
sking@ubuntu:~/resource/de10-std$ mkdir ~/work/de10-std
sking@ubuntu:~/resource/de10-std$ mv linux-socfpga-socfpga-4.5 ~/work/de10-std/
进入源代码linux-socfpga-socfpga-4.5目录下。
sking@ubuntu:~/resource/de10-std$ cd ~/work/de10-std/linux-socfpga-socfpga-4.5/
编译配置
因为官方映像内核版本号为:4.5.0-00198-g6b20a29,官方指定的内核源码编译出的内核映像版本号为:4.5.0。默认配置在进行编译配置之前,为了保证编译出的内核映像文件zImage文件版本与官方的内核映像文件版本一致,需要在内核源码根目录的Makefile文件中对文件开头部分的内核版本信息进行修改。修改部分如下:
VERSION = 4
PATCHLEVEL = 5
SUBLEVEL = 0
EXTRAVERSION = -00198-g6b20a29
设置交叉编译环境。
sking@ubuntu:~/work/de10-std/linux-socfpga-socfpga-4.5$ export CROSS_COMPILE=~/work/de10-std/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf-
运行以下命令来设置默认配置。这将创建一个“ .config”文件,其设置与默认配置文件中的设置相同。
sking@ubuntu:~/work/de10-std/linux-socfpga-socfpga-4.5$ sudo make ARCH=arm socfpga_defconfig
为了打开GUI界面对内核编译进行配置,需要安装ncurses库。
sking@ubuntu:~/work/de10-std/linux-socfpga-socfpga-4.5$ sudo apt install libncurses5-dev
然后打开内核配置工具:
sking@ubuntu:~/work/de10-std/linux-socfpga-socfpga-4.5$ sudo make ARCH=arm menuconfig
内核配置具体内容如下:
- 取消选中:General Setup→Automatically append version information to the version string。防止内核向内核添加额外的“版本”信息,避免内核检查驱动程序是否使用与自身相同的源代码版本构建,以便更轻松地测试不同版本的驱动程序;
- 启用:General Setup→Embedded System选项;
- 启用:Enable the block layer→Support for large (2TB+) block devices and files选项,使用的是EXT4文件系统,则必须启用此选项(我们是);
- 启用:System Type→Altera SOCFPGA family→Suspend to RAM on SOCFPGA;
- 启用Kernel Features下的:Symmetric Multi-Processingh、Memory split、High Memory Support;
- 启用:Device Drivers→FPGA devices→FPGA Framework和Device Drivers→MMC / SD / SDIO;
- 启用:File systems→The Extended 4 (ext4) filesystem
- 启用:Kernel Hacking→Compile-time checks and compiler options→Compile the kernel with debug info;
设置完可用选项后,按右箭头键选择窗口底部的“Save”选项,然后按Enter。当要求输入文件名时,将其保留为默认名称(“ .config”),然后按Enter键。再次按下Enter键,然后退出配置工具。
编译内核
完成了内核的配置后,对Linux内核进行编译。
sudo make ARCH=arm CROSS_COMPILE=~/work/de10-std/gcc-linaro-6.2.1-2016.11-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- LOCALVERSION= zImage
(注意:“LOCALVERSION=”与“zImage”之间有空格)
内核编译完成后,生成的zImage映像文件将位于“ arch / arm / boot”中。稍后,我们会将该文件刻录到SD卡。
根文件系统
根文件系统可以按照Embedded Linux Beginners Guide自己制作,也可以使用现有的根文件系统。由于本人制作的根文件系统文件结构感觉不是很完整,且 抬头内容过于简介,本人使用起来很不自然,所以我这里暂时采用DE10 Standard开发板官方自带的映像文件中的根文件系统。
首先,在window系统下将官方映像文件烧录到SD卡中。
打开SD卡烧录软件Win32DiskImager,在弹出的Win32 Disk Imager窗口下,确认SD卡的盘符,点击文件夹图标,选择要烧录到SD卡上的系统映像文件,点击:打开。在返回的Win32 Disk Imager窗口中点击:Write按钮。然后在弹出的窗口下点击:确定。等烧录完成后,点击Win32 Disk Imager窗口下的:Exit按钮退出软件。
打开虚拟机,进入Ubuntu的终端中,在把SD卡连接到虚拟机的前后分别使用命令:lsblk
来确认SD卡的设备名称。最后,我们会发现在SD卡连接到虚拟机后,Linux系统中多了一段设备信息:
sdb 8:16 1 14.9G 0 disk
├─sdb1 8:17 1 500M 0 part /media/sking/2AF6-4A6D
├─sdb2 8:18 1 3G 0 part /media/sking/5393f0e0-63b6-4706-a4b7-432d36
└─sdb3 8:19 1 1M 0 part
所以我们的设备名称为:sdb,其中sdb2上存放着我们所需的根文件系统,它对应的路径为:/media/sking/5393f0e0-63b6-4706-a4b7-432d36。现在我们将sdb2上的根文件系统拷贝下来留以后面制作系统映像文件使用。
建立文件夹:~/resource/mksdimg/rootf来存放根文件系统。然后,拷贝sdb2上的根文件系统到该文件夹下。
sking@ubuntu:~$ mkdir resource/mksdimg/rootf
sking@ubuntu:~$ sudo cp -r /media/sking/5393f0e0-63b6-4706-a4b7-432d3673e8f4/. resource/mksdimg/rootf
SD卡系统映像制作
现在我们已经得到了制作系统映像文件所需的文件,我们只要创建一个空白的SD卡映像文件并对SD卡进行分区,然后再把我们制作系统映像文件所需的文件放置到这个SD卡映像文件中就会得到我们想要的制作系统映像文件。
我们首先需要为SD卡创建一个空白图像文件,并创建所有生成的文件将被放置在的分区。下图描述了如何对我们的设备进行分区。
第一个分区是FAT分区,它将保存我们的FPGA配置文件soc_system.dtb、U-Boot引导脚本u-boot.scr、设备树二进制文件soc_system.dtb和内核映像zImage。分区2将保存我们的根文件系统(所有文件和程序)。我们将分别在这两个分区上创建FAT和EXT4文件系统。最后一个分区是原始分区(无文件系统),它将包含预加载程序映像preloader-mkpimage.bin。扫描SD卡时,Boot ROM将寻找“ A2”类型的分区。找到后,它将运行位于其上的预加载器映像preloader-mkpimage.bin。
SD卡映像创建与分区
选择一张SD卡用作DE10 Standard开发板的启动卡,并使用格式化软件:SDFormatter.exe对其进行格式化。
将SD卡通过读卡器连接到电脑上。打开软件SDFormatter,在弹出的SDFormatter V4.0窗口中,确认SD卡的盘符,依次点击:更新→格式化。在接下来弹出的各个窗口下均点击:确定。在格式化完成后,将会返回SDFormatter V4.0窗口,最后点击:完成,退出该软件。
打开虚拟机,进入Ubuntu的终端中,在把SD卡连接到虚拟机的前后分别使用命令:df
来确认SD卡的设备名称。最后,我们会发现在SD卡连接到虚拟机后,Linux系统中多了一行设备信息:
sking@ubuntu:~$ lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sdb 8:16 1 14.9G 0 disk
└─sdb1 8:17 1 14.9G 0 part /media/sking/57F8-0F8C
sking@ubuntu:~$ df
文件系统 1K-块 已用 可用 已用% 挂载点
/dev/sdb1 15549952 32 15549920 1% /media/sking/3A2D-4EB1
可以看出,我们的SD卡设备名为:/dev/sdb 。它上面只有一个主分区:/dev/sdb1,空间大小为:15549952K,可用空间大小为:15549920K。
接下来,在当前目录下创建一个SD卡映像文件:sdcard.img,文件大小为上述SD卡的主分区可用空间大小,并初始化文件数据为:0。
sking@ubuntu:~$ sudo dd if=/dev/zero of=sdcard.img bs=1K count=15549920
现在,可以看到用户主目录下新创建了一个文件:sdcard.img,大小为:15.9G(15549952K)。
我们将使用回环设备来操作SD卡映像文件:sdcard.img,就好像它是磁盘一样。以下命令将返回与映像文件关联的回环设备的名称(在本例中为/ dev / loop11)。记住该设备名称以备后用。
sking@ubuntu:~$ sudo losetup --show -f sdcard.img
/dev/loop11
接下来,我们需要创建三个前面提到的分区。因为即将要创建的三个分区中,分区1和分区3所放的文件是确定的,所以其分区的大小也可以固定下来。但是分区2中将会存放根文件系统,然而根文件系统的大小会随着之后对操作系统中添加驱动程序、应用程序和数据文件而变得越来越大,所以我们需要尽可能地把更多的空间留给分区2。因此,我们先进行分区1和分区3的创建,最后把剩余的空间全部分配给分区3。
现在,我们将使用fdisk实用程序执行此操作(请记住系统分配给我们的回环设备为:/ dev / loop11)。
sking@ubuntu:~$ sudo fdisk /dev/loop11
欢迎使用 fdisk (util-linux 2.34)。
更改将停留在内存中,直到您决定将更改写入磁盘。
使用写入命令前请三思。
设备不包含可识别的分区表。
创建了一个磁盘标识符为 0xac71da67 的新 DOS 磁盘标签。
命令(输入 m 获取帮助):
使用p
命令查看当前分区情况,确认当前回环设备上没有分区。
命令(输入 m 获取帮助): p
Disk /dev/loop11:14.85 GiB,15923118080 字节,31099840 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0xac71da67
使用n
命令创建用于存储预加载器文件的分区3,分区类型:主分区(未知类型),扇区:默认,大小:1MiB。然后,使用t
命令设置分区3文件系统类型:A2。
命令(输入 m 获取帮助): n
分区类型
p 主分区 (0个主分区,0个扩展分区,4空闲)
e 扩展分区 (逻辑分区容器)
选择 (默认 p): p
分区号 (1-4, 默认 1): 3
第一个扇区 (2048-31099839, 默认 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-31099839, 默认 31099839): +1M
创建了一个新分区 3,类型为“Linux”,大小为 1 MiB。
命令(输入 m 获取帮助): t
已选择分区 3
Hex 代码(输入 L 列出所有代码): a2
已将分区“Linux”的类型更改为“未知”。
使用n
命令创建用于存储启动配置文件的分区1,分区类型:主分区(FAT类型),扇区:默认,大小:25MiB。然后,使用t
命令设置分区3文件系统类型:FAT32。当然,一旦知道启动配置文件将占用多少空间,我们也可以减小该分区的大小并增加根文件系统分区(分区2)的大小。
命令(输入 m 获取帮助): n
分区类型
p 主分区 (1个主分区,0个扩展分区,3空闲)
e 扩展分区 (逻辑分区容器)
选择 (默认 p): p
分区号 (1,2,4, 默认 1): 1
第一个扇区 (4096-31099839, 默认 4096):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (4096-31099839, 默认 31099839): +25M
创建了一个新分区 1,类型为“Linux”,大小为 25 MiB。
命令(输入 m 获取帮助): t
分区号 (1,3, 默认 3): 1
Hex 代码(输入 L 列出所有代码): b
已将分区“Linux”的类型更改为“W95 FAT32”。
使用n
命令创建用于存储根文件系统的分区2,分区类型:主分区(FAT类型),扇区:默认,大小:默认(使用剩余全部空间)。由于默认的分区类型为:Linux类型,所以此分区不用更改分区类型。
命令(输入 m 获取帮助): n
分区类型
p 主分区 (2个主分区,0个扩展分区,2空闲)
e 扩展分区 (逻辑分区容器)
选择 (默认 p): p
分区号 (2,4, 默认 2): 2
第一个扇区 (55296-31099839, 默认 55296):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (55296-31099839, 默认 31099839):
创建了一个新分区 2,类型为“Linux”,大小为 14.8 GiB。
使用p
命令打印出分区表,确认分区情况。
命令(输入 m 获取帮助): p
Disk /dev/loop11:14.85 GiB,15923118080 字节,31099840 个扇区
单元:扇区 / 1 * 512 = 512 字节
扇区大小(逻辑/物理):512 字节 / 512 字节
I/O 大小(最小/最佳):512 字节 / 512 字节
磁盘标签类型:dos
磁盘标识符:0xac71da67
设备 启动 起点 末尾 扇区 大小 Id 类型
/dev/loop11p1 4096 55295 51200 25M b W95 FAT32
/dev/loop11p2 55296 31099839 31044544 14.8G 83 Linux
/dev/loop11p3 2048 4095 2048 1M a2 未知
分区表记录没有按磁盘顺序。
使用w
命令将对SD卡映像的分区表信息进行写入。
命令(输入 m 获取帮助): w
分区表已调整。
将调用 ioctl() 来重新读分区表。
重新读取分区表失败。: 无效的参数
内核仍在使用旧分区表。新分区表将在下次重启或运行 partprobe(8) 或 kpartx(8) 后生效。
上述输出信息看似出现了某种错误,但是我们不用担心,因为这是提示我们内核还不知道我们分区信息有了更改。现在我们需要使用partprobe
命令让内核知道发生的变化。
sking@ubuntu:~$ sudo partprobe /dev/loop11
创建系统映像
上面我们已经成功创建了SD卡映像并对其进行了分区,现在我们可以创建文件系统并开始复制所需的文件进入到SD卡映像文件的相应分区。
在Ubuntu的~/resource/mksdimg
目录下来存放我们前面生成的预加载器文件:preloader-mkpimage.bin、FPGA配置文件soc_system.rbf、U-Boot引导脚本u-boot.scr、设备树二进制文件soc_system.dtb和内核映像zImage 。然后,进入该文件夹内。
sking@ubuntu:~$ cd resource/mksdimg/
分别找到上述所需文件,将它们放到文件夹:~/resource/mksdimg内。
我们将从将预加载器映像复制到A2分区(分区3)开始。
sking@ubuntu:~/resource/mksdimg$ sudo dd if=preloader-mkpimage.bin of=/dev/loop11p3 bs=64k seek=0
记录了4+0 的读入
记录了4+0 的写出
262144 bytes (262 kB, 256 KiB) copied, 0.00642017 s, 40.8 MB/s
接下来,在分区1(我们将分区设置为“ FAT”类型)上创建FAT文件系统。
sking@ubuntu:~/resource/mksdimg$ sudo mkfs -t vfat /dev/loop11p1
mkfs.fat 4.1 (2017-01-24)
在我们创建的Linux分区上创建EXT4文件系统。稍后将其用作我们的根文件系统。
sking@ubuntu:~/resource/mksdimg$ sudo mkfs.ext4 /dev/loop11p2
mke2fs 1.45.5 (07-Jan-2020)
丢弃设备块: 完成
创建含有 3880568 个块(每块 4k)和 971040 个inode的文件系统
文件系统UUID:bfaebc6b-d513-449a-9123-2a4880cf2e6e
超级块的备份存储于下列块:
32768, 98304, 163840, 229376, 294912, 819200, 884736, 1605632, 2654208
正在分配组表: 完成
正在写入inode表: 完成
创建日志(16384 个块) 完成
写入超级块和文件系统账户统计信息: 已完成
现在,我们将挂载FAT分区并复制所有启动文件。首先创建一个临时目录:temp_mount,然后将文件系统挂载到该目录。
sking@ubuntu:~/resource/mksdimg$ mkdir temp_mount
sking@ubuntu:~/resource/mksdimg$ sudo mount /dev/loop11p1 ./temp_mount/
复制所有启动文件到临时目录:temp_mount。
sking@ubuntu:~/resource/mksdimg$ sudo cp u-boot.img u-boot.scr soc_system.dtb soc_system.rbf zImage temp_mount/
复制完启动文件后,进行同步(确保将文件写入映像)并卸载FAT分区。
sking@ubuntu:~/resource/mksdimg$ sync
sking@ubuntu:~/resource/mksdimg$ sudo umount temp_mount
现在,我们将挂载Linux分区并复制根文件系统文件。首先创建一个临时目录:temp_mount,然后将文件系统挂载到该目录。
sking@ubuntu:~/resource/mksdimg$ sudo mount /dev/loop11p2 ./temp_mount
sking@ubuntu:~/resource/mksdimg$ sudo cp rootf/. temp_mount
复制完根文件系统文件后,进行同步(确保将文件写入映像)并卸载Linux分区。
sking@ubuntu:~/resource/mksdimg$ sync
sking@ubuntu:~/resource/mksdimg$ sudo umount temp_mount
最后,我们需要将刚刚创建的映像文件sdcard.img烧录到SD卡上。从前面可以知道,我们的SD卡设备名称是:/dev/sdb (lsblk命令也可以查看设备信息)。请运行以下命令烧录映像文件:
sking@ubuntu:~/resource/mksdimg$ cd ~
sking@ubuntu:~$ sudo dd if=sdcard.img of=/dev/sdb bs=2048
sking@ubuntu:~$ sync
至此,我们就完成了SD卡系统映像文件的烧录。我们也可以把它从虚拟机中拷贝出来,放到Windows系统下,使用SD卡烧录软件Win32DiskImager进行烧录。
写在后面
这里主要是想谈一谈SD卡烧录系统映像文件的一些相关问题。
为什么自己制作系统映像文件
SD卡系统映像文件制作这一部分主要是考虑到对SD卡内存空间的充分利用以及项目存储数据需要更大用户空间的嵌入式Linux系统。官方自带的系统映像文件的大小大约也就是4G。这个大小其实就是制作系统映像文件的时候建立的空白映像文件的大小,这个是可以通过自己制作系统映像文件来设定的。
哪些情况下不建议制作系统映像文件
其实只要你有了用户空间能够满足需要的系统映像文件,你就不用制作系统映像文件了。最核心的关注点——用户空间。
- 学习&测试
如果只是在嵌入式Linux系统上做一些练习、测试的话,那就用不了特别大的空间。这时官方自带的4G的系统映像文件就够用,没必要这么麻烦地自己制作系统映像文件。 - 启动文件功能不满足
如果已经有了一张用户空间满足需要的SD卡,但是因为上面的硬件逻辑配置文件、内核映像文件、设备树文件等启动文件不能满足我们需要的时候,我们只要在Windows系统下把相应文件替换为我们需要的文件即可,注意替换前后相应文件名保持一致。 - 驱动或应用程序功能不满足
如果是驱动程序或者是应用程序不满足我们的需要时,我们只需要将所需的驱动程序或应用程序传输到我们开发板上的嵌入式Linux系统中即可。要实现这一项操作方法有很多,可以通过网线和串口线,也可以直接将SD卡连接到Ubuntu上直接替换根文件系统中相应的文件。
总之,我们一定要怀着尽可能不自己重新制作系统映像文件的心理来解决问题,甚至怀着尽可能不烧录根文件系统的心理,因为如果更大的系统映像文件烧录的时间会非常的长。