一、Makefile
1、语法
目标…… : 依赖文件集合……
命令 1
命令 2
……
例子:
生成main可执行文件需要main.o input.o calcu.o,命令是gcc -o main main.o input.o calcu.o
main: main.o input.o calcu.o
gcc -o main main.o input.o calcu.o
main.o: main.c
gcc -c main.c
input.o: input.c
gcc -c input.c
calcu.o: calcu.c
gcc -c calcu.c
clean:
rm *.o
rm main
2、变量
Makefile中的变量只能是字符串
例 :将object赋值 main.o input.o calcu.o,变量引用的时候要加$()
objects = main.o input.o calcu.o
main: $(objects)
gcc -o main $(objects)
3、几种赋值运算符
“=” :不一定要用定义好的值也可以用后面的值,与c语言赋值很像
“:=” :只使用定义的值后面的赋值不起作用
“?=”:如果没有赋值则赋值
“+=”:在后面附加
4、当“%”出现在目标中的时候,目标中“%”所代表的值决定了依赖中的“%”值
(泛化了),使用方法如下:
%.o : %.c
命令
5、自动化变量(常用的三种:$ @、$ <和$ ^)
例
objects = main.o input.o calcu.o
main: $(objects)
gcc -o main $(objects)
%.o : %.c
gcc -c $<
clean:
rm *.o
rm main
二、系统移植
1、何为uboot?
1、uboot是一个裸机程序,比较复杂。
2、uboot就是一个bootloader,作用就是用于启动Linux或其他系统。Uboot最主要的工作就是初始化DDR。因为Linux是运行在DDR里面的。一般Linux镜像zImage(uImage)+设备树(.dtb)存放在SD、EMMC、NAND、SPI FLASH等等外置存储区域。
这里就牵扯到一个问题,需要将Linux镜像从外置flash拷贝到DDR中,再去启动。
Uboot的主要目的就是为系统的启动做准备。
Uboot不仅仅能启动Linux,也可以启动其他系统,比如vxworks。
Linux不仅仅能通过uboot启动。
Uboot是个通用的bootloader,他支持多种架构。
2、Uboot获取
1、首先就是uboot官网。缺点就是支持少,比如某一款具体芯片驱动等不完善。
2、SOC厂商会从uboot官网下载某一个版本的uboot,然后在这个版本的uboot上加入相应的SOC以及驱动。这就是SOC厂商定制版的uboot。NXP官方的I.MX6ULL EVK板子
3、做开发板的厂商,开发板会参考SOC厂商的板子。开发板必然会和官方的板子不一样。因此开发板厂商又会去修改SOC厂商做好的uboot,以适应自己的板子。
3、uboot编译
首先在 Ubuntu 中安装 ncurses 库,否则编译会报错,安装命令如下:
sudo apt-get install libncurses5-dev
新建一个 shell 脚本文件,每次只需要执行 shell 脚本即可完成编译工作(这个脚本会清除之前的配置)。如下:
#!/bin/bash
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_ddr512_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j12
使用 chmod 命令给予 mx6ull_alientek_emmc.sh 文件可执行权限,然后就可以使用这个 shell
脚本文件来重新编译 uboot,命令如下:
./mx6ull_alientek_emmc.sh
在Makefile 254行加入这两条可以不用运行脚本 make就可以编译
4、uboot烧写与启动
1、我们要将 imxdownload (开发板光盘->5、开发工具->2、
Ubuntu 下裸机烧写软件->imxdownload)拷贝到工程根目录下。
2、ls /dev/sd*`看看烧写到那个sd卡
3、chmod 777 imxdownload //给予 imxdownload 可执行权限,一次即可
4、./imxdownload u-boot.bin /dev/sdd //烧写到 SD 卡,不能烧写到/dev/sda 或 sda1 设备里面!
5、uboot命令的使用
1、基础命令
help:查看所有命令
? (要查找命令):查看某一个命令信息
printenv:查看当前板子的环境变量
setenv:设置环境变量,也可以自定义环境变量,也可以删除环境变量(设置为空值就可以删除)
setenv author hsd 创建一个author环境变量赋值为hsd
saveenv:保存环境变量
md[.b, .w, .l] address [# of objects] :内存读写指令,要注意uboot中命令的数字都是16进制
比如你想查看以 0X80000000 开始的 20 个字节的内存值,显示格式为.b 的话,应该使用
如下所示命令:
md.b 80000000 14
而不是:
md.b 80000000 20
.b 格式显示,长度为 0x10,也就是 16 个字节;.w 格式显示,长度为 0x10,也就是 16*2=32
个字节;.l 格式显示,长度也是 0x10,也就是 16*4=64 个字节。
nm [.b, .w, .l] address 用于修改指定地址的内存值,输入q结束
mw [.b, .w, .l] address value [count] 用于使用一个指定的数据填充一段内存
例
mw.l 80000000 0A0A0A0A 10
将以 0X80000000 为起始地址的 0x10 个内存块(0x10 * 4=64 字节)填充为 0X0A0A0A0A
cp [.b, .w, .l] source target count 数据拷贝命令
cp.l 80000000 80000100 10 将 0x80000000 处的地址拷贝到 0X80000100 处,长度为 0x10 个
内存块(0x10 * 4=64 个字节)
cmp [.b, .w, .l] addr1 addr2 count
cmp.l 80000000 80000100 10 来比较 0x80000000 和 0X80000100 这
两个地址数据是否相等,比较长度为 0x10 个内存块(16 * 4=64 个字节)
2、网络相关的命令
ping主机之前一定要改下面这个配置,而且还要先ping一下要开发板设置的ip地址检查是否被占用。
setenv ipaddr 192.168.1.50
setenv ethaddr b8:ae:1d:01:00:00
setenv gatewayip 192.168.1.1
setenv netmask 255.255.255.0
setenv serverip 192.168.1.253
saveenv
1、nfs命令
安装nfs
sudo apt-get install nfs-kernel-server rpcbind
等待安装完成,安装完成以后在用户根目录下创建一个名为“linux”的文件夹,以后所有
的东西都放到这个“linux”文件夹里面,在“linux”文件夹里面新建一个名为“nfs”的文件夹。
配置 nfs
sudo vi /etc/exports
打开/etc/exports 以后在后面添加如下所示内容:
/home/zuozhongkai/linux/nfs *(rw,sync,no_root_squash)
重启 NFS 服务,使用命令如下:
sudo /etc/init.d/nfs-kernel-server restart
nfs(Network File System)网络文件系统,通过 nfs 可以在计算机之间通过网络来分享资源,比如我们将 linux 镜像和设备树文件放到 Ubuntu 中,然后在 uboot 中使用 nfs 命令将 Ubuntu 中的 linux 镜像和设备树下载到开发板的 DRAM 中。
nfs [loadAddress] [[hostIPaddr:]bootfilename]
例:
nfs 80800000 192.168.1.253:/home/zuozhongkai/linux/nfs/zImage
命令中的“ 80800000 ” 表 示 zImage 保 存 地 址 ,
“192.168.1.253:/home/zuozhongkai/linux/nfs/zImage”表示 zImage 在 192.168.1.253 这个主机中,路径为/home/zuozhongkai/linux/nfs/zImage。
2、tftp 命令
执行下面两条安装TFTP
sudo apt-get install tftp-hpa tftpd-hpa
sudo apt-get install xinetd
创建一个tftp根目录(要给权限),此目录文件可以下载到开发板(与nfs一样)
mkdir /home/zuozhongkai/linux/tftpboot
chmod 777 /home/zuozhongkai/linux/tftpboot
最后配置 tftp,安装完成以后新建文件/etc/xinetd.d/tftp,输入以下内容
server tftp
{
socket_type = dgram
protocol = udp
wait = yes
user = root
server = /usr/sbin/in.tftpd
server_args = -s /home/hsd/linux/tftpboot/
disable = no
per_source = 11
cps = 100 2
flags = IPv4
}
启动tftp
sudo service tftpd-hpa start
打开/etc/default/tftpd-hpa 文件,将其修改为如下所示内容:
# /etc/default/tftpd-hpa
TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/home/hsd/linux/tftpboot"
TFTP_ADDRESS=":69"
TFTP_OPTIONS="-l -c -s"
重启tftp服务器
sudo service tftpd-hpa restart
指令格式
tftpboot [loadAddress] [[hostIPaddr:]bootfilename]
loadAddress 是文件在 DRAM 中 的存 放 地 址 ,[[hostIPaddr:]bootfilename]是要从 Ubuntu 中下载的文件。但是和 nfs 命令的区别在于,只需要输入文件名即可。
例:
tftp 80800000 zImage
看到“TFTP error: ‘Permission denied’ (0)”这样的错误提示,提示没有权限,出现这个错误一般有两个原因:
①、在 Ubuntu 中创建 tftpboot 目录的时候没有给予 tftboot 相应的权限。
②、tftpboot 目录中要下载的文件没有给予相应的权限。
针对上述两个问题,使用命令“chmod 777 xxx”来给予权限,其中“xxx”就是要给予权限的文件或文件夹。
3、EMMC和SD卡
1、mmc read 命令
格式
mmc read addr blk# cnt
addr 是数据读取到 DRAM 中的地址,blk 是要读取的块起始地址(十六进制),一个块是 512字节,这里的块和扇区是一个意思,在 MMC 设备中我们通常说扇区,cnt 是要读取的块数量(十六进制)。比如从 EMMC 的第 1536(0x600)个块开始,读取 16(0x10)个块的数据到 DRAM 的0X80800000 地址处,命令如下:
mmc dev 1 0 //切换到 MMC 分区 0
mmc read 80800000 600 10 //读取数据
2、mmc list 命令
mmc list 命令用于来查看当前开发板一共有几个 MMC 设备
mmc dev 0 //切换到 SD 卡,0 为 SD 卡,1 为
有时候 SD 卡或者 EMMC 会有多个分区,可以使用命令“mmc part”来查看其分区
mmc dev 1 //切换到 EMMC
//查看 EMMC 分区
如果要将 EMMC 的分区 2 设置为当前 MMC 设备,可以使用如下命令:
mmc dev 1 2
3、mmc write 命令
要将数据写到 MMC 设备里面,可以使用命令“mmc write”,格式如下:
mmc write addr blk# cnt
addr 是要写入 MMC 中的数据在 DRAM 中的起始地址,blk 是要写入 MMC 的块起始地址
(十六进制),cnt 是要写入的块大小,一个块为 512 字节。
例:
如果要在 uboot 中更新 EMMC 对应的 uboot,可以使用如下所示命令:
mmc dev 1 0 //切换到 EMMC 分区 0
tftp 80800000 u-boot.imx //下载 u-boot.imx 到 DRAM
mmc write 80800000 2 32E //烧写 u-boot.imx 到 EMMC 中
mmc partconf 1 1 0 0 //分区配置,EMMC 需要这一步!
千万不要写 SD 卡或者 EMMC 的前两个块(扇区),里面保存着分区表!
4、FAT 格式文件系统操作命令
对于I.MX6U来说,SD/EMMC分为三个分区:
第一个:存放uboot
第二个:存放Linux zImage,.dtb。FAT
第三个:系统的根文件系统,EXT4
1、fatinfo 命令
用于查询指定 MMC 设备分区的文件系统信息,格式如下:
fatinfo <interface> [<dev[:part]>]
interface 表示接口,比如 mmc,dev 是查询的设备号,part 是要查询的分区。比如我们要查
询 EMMC 分区 1 的文件系统信息,命令如下:
fatinfo mmc 1:1
2、fatls 命令
用于查询 FAT 格式设备的目录和文件信息,命令格式如下:
fatls <interface> [<dev[:part]>] [directory]
interface 是要查询的接口,比如 mmc,dev 是要查询的设备号,part 是要查询的分区,directory
是要查询的目录。比如查询 EMMC 分区 1 中的所有的目录和文件,输入命令:
fatls mmc 1:1
3、fstype 命令
用于查看 MMC 设备某个分区的文件系统格式,命令格式如下:
fstype <interface> <dev>:<part>
例
fstype mmc 1:0
fstype mmc 1:1
fstype mmc 1:2
从上图可以看出,分区 0 格式未知,因为分区 0 存放的 uboot,并且分区 0 没有格式化,所
以文件系统格式未知。分区 1 的格式为 fat,分区 1 用于存放 linux 镜像和设备树。分区 2 的格
式为 ext4,用于存放 Linux 的根文件系统(rootfs)。
4、fatload 命令(重要)
用于将指定的文件读取到 DRAM 中,命令格式如下:
fatload <interface> [<dev[:part]> [<addr> [<filename> [bytes [pos]]]]]
interface 为接口,比如 mmc,dev 是设备号,part 是分区,addr 是保存在 DRAM 中的起始地址,filename 是要读取的文件名字。bytes 表示读取多少字节的数据,如果 bytes 为 0 或者省略的话表示读取整个文件。pos 是要读的文件相对于文件首地址的偏移,如果为 0 或者省略的话表示从文件首地址开始读取。我们将 EMMC 分区 1 中的 zImage 文件读取到 DRAM 中的0X80800000 地址处,命令如下:
fatload mmc 1:1 80800000 zImage
5、BOOT操作指令
1、bootz 命令(启动zImage命令)
要启动 Linux,可从 EMMC 或者 NAND 也可通过 nfs 或者 tftp 将 Linux 镜像文件和设备树文件下载到 DRAM 中,然后使用 bootz 命令来启动,bootz 命令格式如下:
bootz [addr [initrd[:size]] [fdt]]
addr 是 Linux 镜像文件在 DRAM 中的位置。
initrd 是 initrd 文件在DRAM 中的地址,如果不使用 initrd 的话使用‘-’代替即可。
fdt 就是设备树文件在 DRAM 中的地址。
例(tftp启动):
tftp 80800000 zImage
tftp 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb
bootz 80800000 - 83000000
例(emmc启动):
fatload mmc 1:1 80800000 zImage
fatload mmc 1:1 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb
bootz 80800000 - 83000000
2、bootm 命令(启动uImage命令,其余与bootz一致)
3、boot 命令
boot 会读取环境变量 bootcmd 来启动 Linux 系统,这个环境变量保存着引导命令,其实就是启动的命令集合,具体的引导命令内容是可以修改的。命令如下:
setenv bootcmd 'tftp 80800000 zImage;tftp 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb;bootz 80800000 - 83000000'
saveenv
boot
倒计时结束以后就会启动 Linux 系统,其实就是执行的 bootcmd 中的启动命令。
6、其他指令
1、reset 命令
复位
2、go 命令
跳到指定的地址处执行应用
tftp 87800000 printf.bin
go 87800000
3、run 命令
用于运行环境变量中定义的命令,比如可以通过“run bootcmd”来运行 bootcmd 中的启动命令,但是 run 命令最大的作用在于运行我们自定义的环境变量。
例:
创建环境变量 mybootemmc、mybootnet 和 mybootnand,命令如下:
setenv mybootemmc 'fatload mmc 1:1 80800000 zImage; fatload mmc 1:1 83000000 imx6ull-14x14-emmc-7-1024x600-c.dtb;bootz 80800000 - 83000000'
setenv mybootnand 'nand read 80800000 4000000 800000;nand read 83000000 6000000 100000;bootz 80800000 - 83000000'
setenv mybootnet 'tftp 80800000 zImage; tftp 83000000imx6ull-14x14-emmc-7-1024x600-c.dtb;bootz 80800000 - 83000000'
saveenv
通过下面方式运行
run mybootemmc
run mytoobnand
run mybootnet
6、U-Boot 移植源码目录分析
1、因为uboot会使用到一些经过编译才会生成的文件,因此我们在分析uboot的时候,需要先编译一下uboot。
2、arch\arm\cpu\u-boot.lds就是整个UBOOT的连接脚本
3、board\freescale\mx6ullevk。重点。
4、configs目录是uboot的默认配置文件目录。此目录下都是以_defconfig结尾的。这些配置文件对应不同的板子。
5、我们移植uboot的时候重点要关注。board\freescale \configs,主要是_defconfig
6、当我们执行make xxx_defconfig以后就会生成.config文件,此文件保存了详细的uboot配置信息。
7、顶层README,非常重要,建议大家阅读,介绍uboot。
8、u-boot。这个就是编译出来带ELF信息的uboot可执行文件。
7、U-Boot 移植
在工作中如果不是在芯片原厂一般都是对uboot进行二次开发,下面我将用NXP提供的u-boot进行移植
1、将NXP提供的uboot复制到我们的虚拟机文件夹对应的目录中
2、在uboot顶层目录编写Makefile
#!/bin/bash
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- mx6ull_14x14_evk_emmc_defconfig
make V=1 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -j16
3、./mx6ull_14x14_evk_emmc.sh 运行shell脚本进行编译
4、从其他裸机程序里拷贝一份imxdownload。然后将u盘插入ubantu
5、sudo fdisk -l //查看刚插入的u盘
6、烧
chmod 777 imxdownload //给予 imxdownload 可执行权限
./imxdownload u-boot.bin /dev/sdd //烧写到 SD 卡中,不能烧写到/dev/sda 或 sda1 里面
7.1 uboot图形化配置
1、进入到uboot源码目录下,输入 make xxx_defconfig
恢复默认设置。
2、通过make menuconfig
命令来打开图形界面,打开界面前要安装以下几个库。
sudo apt-get install build-essential
sudo apt-get install libncurses5-dev
简单总结一下 uboot 移植的过程:
①、不管是购买的开发板还是自己做的开发板,基本都是参考半导体厂商的 dmeo 板,而半导体厂商会在他们自己的开发板上移植好 uboot、linux kernel 和 rootfs 等,最终制作好 BSP包提供给用户。我们可以在官方提供的 BSP 包的基础上添加我们的板子,也就是俗称的移植。
②、我们购买的开发板或者自己做的板子一般都不会原封不动的照抄半导体厂商的 demo板,都会根据实际的情况来做修改,既然有修改就必然涉及到 uboot 下驱动的移植。
③、一般 uboot 中需要解决串口、NAND、EMMC 或 SD 卡、网络和 LCD 驱动,因为 uboot的主要目的就是启动 Linux 内核,所以不需要考虑太多的外设驱动。
④、在 uboot 中添加自己的板子信息,根据自己板子的实际情况来修改 uboot 中的驱动。
8、Linux内核
8.1内核编译
#!/bin/sh
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v7_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16
编译完成生成以下文件
zImage存放在./arch/arm/boot/zImage
.dtb存放在: ./arch/arm/boot/dts/xxx.dtb
8.2内核移植
1、arch/arm/configs 目 录 下 的 imx_v7_mfg_defconfig 重 新 复 制 一 份 , 命 名 为
imx_alientek_emmc_defconfig为emmc启动文件。
2、arch/arm/boot/dts 中,复制一份 imx6ull-14x14-evk.dts,然后将其重命名为 imx6ull-alientek-emmc.dts。
3、修 改 文 件 arch/arm/boot/dts/Makefile , 找 到 “ dtb-$(CONFIG_SOC_IMX6ULL)”配置项,在此配置项中加入“imx6ull-alientek-emmc.dtb”。
4、编译
5、使能8线EMMC
修改设备树,imx6ull-alientek-emmc.dts。节点usdhc2。
6、网络驱动修改
为何要一开始就修改网络驱动??在做Linux驱动开发的时候一般都是通过网络调试的。修改网络复位IO和PHY ID以后,Linux内核内部通用PHY驱动已经正常工作。LAN8720的生产厂家是SMSC。使能SMSC驱动,然后重新编译Linux内核,并启动,tftp启动。
7、在Linux中添加自己的开发板
(1)一个就是imx6_alientek_emmc_defconfig默认配置文件。
(2)imx6ull-alientek-emmc.dts编译出来就是.dtb文件。
复制arch/arm/configs/imx_v7_mfg_defconfig文件为imx_alientek_emmc_defconfig。
复制arch/arm/boot/dts/imx6ull-14x14-evk.dts文件为imx6ull-alientek-emmc.dts
修改arch/arm/boot/dts/Makefile,
8、CPU主频和网络驱动修改
1、修改驱动之前,要先保证板子能够正常启动。
2、根文件系统处理好,使用现成根文件系统。保证EMMC烧写了系统,设置bootcmd和bootargs。
Bootcmd设置默认从网络启动,通过TFTP。
Setenv bootcmd ‘tftp 80800000 zImage;tftp 83000000 imx6ull-alientek-emmc.dtb;bootz 80800000 - 83000000;’
Bootargs设置,根文件系统存放在EMMC的分区2里面,命令如下:
Setenv bootargs ‘console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw’
现在的问题就是EMMC驱动有问题,在imx6ull-alientek-emmc.dts中找到usdhc2节点。将usdhc2改为:
&usdhc2 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc2_8bit>;
pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
bus-width = <8>;
non-removable;
status = "okay";
};
完了以后编译设备树。使用如下命令:
Make dtbs。
通过图形界面保存配置文件
在图形界面中保存配置文件,在图形界面中会有“< Save >”选项,
通过键盘的“→”键,移动到“< Save >”选项,然后按下回车键,打开文件名输入对话框,
这样保存就不会被编译删掉了。
简单总结一下移植步骤:
①、在 Linux 内核中查找可以参考的板子,一般都是半导体厂商自己做的开发板。
②、编译出参考板子对应的zImage和.dtb文件。
③、使用参考板子的zImage文件和.dtb文件在我们所使用的板子上启动 Linux 内核,看能
否启动。
④、如果能启动的话就万事大吉,如果不能启动那就悲剧了,需要调试 Linux 内核。不过一般都会参考半导体官方的开发板设计自己的硬件,所以大部分情况下都会启动起来。启动Linux 内核用到的外设不多,一般就 DRAM(Uboot 都初始化好的)和串口。作为终端使用的串口一般都会参考半导体厂商的 Demo 板。
⑤、修改相应的驱动,像 NAND Flash、EMMC、SD 卡等驱动官方的 Linux 内核都是已经提供好了,基本不会出问题。重点是网络驱动,因为 Linux 驱动开发一般都要通过网络调试代码,所以一定要确保网络驱动工作正常。如果是处理器内部 MAC+外部 PHY 这种网络方案的话,一般网络驱动都很好处理,因为在 Linux 内核中是有外部 PHY 通用驱动的。只要设置好复位引脚、PHY 地址信息基本上都可以驱动起来。
⑥、Linux 内核启动以后需要根文件系统,如果没有根文件系统的话肯定会崩溃,所以确定 Linux
内核移植成功以后就要开始根文件系统的构建。
9、根文件系统
9.1根文件系统概念
根文件系统就是一个“文件夹”,此“文件夹”有很多个文件,这些文件是linux运行所必须的,但是无法放到内核里面去的。比如命令、库、配置文件等等。所有这些软件需要我们自己构建。
/就是Linux根文件系统。
9.2根文件系统移植
构建根文件系统,busybox。还有很多成熟化的根文件系统构建方式,buildroot,yocto。构建的根文件系统调试我们通过nfs网络挂载,也就是跟文件系统存放到ubuntu下,开发板启动以后通过nfs服务使用ubuntu下的跟文件系统。
1、修改makefile,添加交叉编译器修改ARCH和CROSS_COMPILE。
2、busybox支持中文字符
3、配置busybox
make defconfig。
make menuconfig打开图形化配置界面
4、编译busybox
5、拷贝库文件。
库文件就是交叉编译器的库文件。
先是rootfs/lib目录,然后是rootfs/usr/lib目录。
6、创建其他文件夹文章来源:https://www.toymoban.com/news/detail-500696.html
nfs挂载出错时有可能是ubantu nfs版本过高。
设置软件后台运行 xxx &
杀掉软件:ps查看pid,kill -9 pid文章来源地址https://www.toymoban.com/news/detail-500696.html
到了这里,关于IMX6ULL 自学笔记(Makefile 以及 系统移植)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!