目的

这篇文章中将测试在 NUC980 中运行Linux系统(基于SPI NAND)。

本文相关的开发环境准备请查看下面这篇文章:
《新唐NUC980使用记录:开发环境准备与编译配置基础说明》

这篇文章中内容均在下面的开发板上进行测试(理论上也可以在新唐官方NUMAKER NUC980 IIOT开发板中进行测试):
《新唐NUC980使用记录:自制开发板(基于NUC980DK61YC)》

开发板上在QSPI上接了型号为W25N01GVZEIG的SPI NAND。

开始前请将将开发板的USB0和UART0都接到Windows电脑上,电脑上使用终端工具连接UART0。另外拨动拨动开关将PG[9:8]设置为01,以使用SPI NAND 4-bit模式。

U-Boot编译

NUC980 U-Boot针对不同启动源的修改调整具体参考BSP包中的文档《NUC980 U-Boot v2016_11 User Manual》。

我这里使用自制的开发板所以从nuc980_evb.h和nuc980_defconfig这对最基础的配置上进行修改:

cd ~/nuc980-sdk/ 
cd NUC970_U-Boot_v2016.11/

修改配置文件:

# cp include/configs/nuc980_evb.h include/configs/nuc980_evb.h.original
gedit include/configs/nuc980_evb.h

配置文件中找到对应位置进行修改:

#define CONFIG_SYS_USE_SPIFLASH // 47行 启用SPI FLASH
#define CONFIG_SYS_USE_NANDFLASH
#define CONFIG_ENV_IS_IN_NAND
/*#define CONFIG_ENV_IS_IN_SPI_FLASH */
/*#define CONFIG_ENV_IS_IN_MMC */

/****************************************/

#ifdef CONFIG_ENV_IS_IN_NAND
#define CONFIG_ENV_OFFSET       0x80000
#define CONFIG_ENV_SIZE         0x20000 // 129行 调整uboot环境变量存储区域大小

// include/configs/nuc980_evb.h 这个文件中还定义了很多位置和大小的参数
// 比如bootm命令启动的内核最大尺寸、NAND的分区设置等,可以按照需求调整

修改配置选项:

# make distclean
make nuc980_defconfig
make menuconfig

配置选项中找到对应位置进行设置:
在这里插入图片描述
在这里插入图片描述

进行编译:

export PATH=$PATH:/home/nx/nuc980-sdk/arm_linux_4.8/bin
make

编译完成后u-boot.bin位于当前目录下,对于NAND而言还需要spl目录下的u-boot-spl.bin。将其拷贝至Windows中进行烧录。比如我的 /media/sf_common/ 是和Windows共享的目录,拷贝到这里即可:

# 拷贝至Windows电脑上
# sudo cp u-boot.bin /media/sf_common/
# sudo cp spl/u-boot-spl.bin /media/sf_common/

拨动拨动开关将PG[1:0]设置为00,按下复位键。在Windows中使用NuWriter进行烧录:
在这里插入图片描述
在这里插入图片描述

烧录完成后拨动拨动开关将PG[1:0]设置为11,按下复位键。可以在终端界面中看到启动信息:
在这里插入图片描述

U-Boot环境变量

U-Boot最重要的是用来启动 Linux Kernel 的,比较常用的做法是使用U-Boot环境变量中设置的参数来读取内核镜像,然后启动内核。

环境变量可以写死在U-Boot程序中,可以使用U-Boot命令来设置,也可以通过烧录工具烧录到保存环境变量的存储区域。下面是最后一种方式的演示:

拨动拨动开关将PG[1:0]设置为00,按下复位键。在Windows中使用NuWriter进行烧录(如果选择时看不到文件,弹窗右下角选择All Files):
在这里插入图片描述
烧录完成后拨动拨动开关将PG[1:0]设置为11,按下复位键。可以在终端界面中看到启动信息:
在这里插入图片描述

上面烧录的环境变量如下:

bootdelay=3
baudrate=115200
stderr=serial
stdin=serial
stdout=serial
loadkernel=nand read 0x7fc0 0x200000 0x1000000
bootcmd=run loadkernel;bootm 0x7fc0

上面环境变量中使用 nand 命令从nand的0x200000位置读取0x1000000大小(16M)的数据到内存0x7fc0位置;然后启动位于内存0x7fc0开始的程序。当然因为现在还没有烧录内核所以启动会失败。

Linux编译

默认设置

NUC980 U-Boot针对不同启动源的修改调整具体参考BSP包中的文档《NUC980 Linux 4.4 BSP User Manual》。

我这里使用自制的开发板所以以nuc980_defconfig这个最基础的配置进行使用:

cd ~/nuc980-sdk/ 
cd NUC980-linux-4.4.y/

套用配置:

# make distclean
make nuc980_defconfig

进行编译:

export PATH=$PATH:/home/nx/nuc980-sdk/arm_linux_4.8/bin
make uImage

注意默认配置下编译时会将 NUC980-linux-4.4.y 同级的 rootfs 目录打包进内核(作为ramfs启动),同时会将编译出的镜像 980uimage 放到 NUC980-linux-4.4.y 同级的 image 目录中。

将其拷贝至Windows中进行烧录。比如我的 /media/sf_common/ 是和Windows共享的目录,拷贝到这里即可:

# 拷贝至Windows电脑上
# sudo cp ../image/980uimage /media/sf_common/

拨动拨动开关将PG[1:0]设置为00,按下复位键。在Windows中使用NuWriter进行烧录(如果选择时看不到文件,弹窗右下角选择All Files):
在这里插入图片描述
烧录完成后拨动拨动开关将PG[1:0]设置为11,按下复位键。可以在终端界面中看到启动信息:
在这里插入图片描述

使用SPI NAND剩余分区

前面U-Boot配置文件中对NAND的分区设置中除去U-Boot、环境变量、内核等需要的空间,剩余空间都被分配为user分区。但是上面默认编译出来的内核并没有把这个分区用起来,如果想用的话需要进行调整。

首先内核要支持对应的 SPI NAND 芯片型号:

# 我这里使用的W25N01GV已经默认包含了,所以不需要调整
# gedit drivers/mtd/nand/nand_ids.c

接着要确保相关芯片驱动:

gedit arch/arm/mach-nuc980/dev.c

找到对应位置进行修改:

// SPI NAND使用驱动为mt29f

static struct flash_platform_data nuc980_qspi0_flash_data = {
// 下面838行加上默认配置中对应开发板CONFIG_BOARD_NUC980
#if defined(CONFIG_BOARD_IOT) || defined(CONFIG_BOARD_ETH2UART) || defined(CONFIG_BOARD_LORAG) || defined(CONFIG_BOARD_NUC980)
	.name = "mt29f",
#else
	.name = "m25p80",
#endif
	.parts = nuc980_qspi0_flash_partitions,
	.nr_parts = ARRAY_SIZE(nuc980_qspi0_flash_partitions),
	.type = "mx66l51235l",

};

/****************************************/

// 下面854行加上默认配置中对应开发板CONFIG_BOARD_NUC980
#if defined(CONFIG_BOARD_IOT) || defined(CONFIG_BOARD_ETH2UART) || defined(CONFIG_BOARD_LORAG) || defined(CONFIG_BOARD_NUC980)
		.modalias = "mt29f",
#else
		.modalias = "m25p80",
#endif

修改配置选项:

# make distclean
make nuc980_defconfig
make menuconfig

配置选项中找到对应位置进行设置:
在这里插入图片描述
上面mode也可以设置为 Quad mode ,使用时读写速度会更快些。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

重新编译烧录内核就可以看到效果了:

# export PATH=$PATH:/home/nx/nuc980-sdk/arm_linux_4.8/bin
# make uImage
# sudo cp ../image/980uimage /media/sf_common/

在这里插入图片描述

使用SPI NAND YAFFS2作为rootfs

前面的使用中根据默认配置,用的是ramfs,这个对嵌入式设备来说是挺不错的,可以有效防止断电引起的文件系统出错的问题,缺点就是无法在烧录后运行时对rootfs修改保存。通常直接使用flash上多余的分区存放rootfs是更加常见的做法。

在上节的基础上取消ramfs,然后设置从flash分区启动rootfs:
在这里插入图片描述
在这里插入图片描述
上面启动命令如下:
noinitrd root=/dev/mtdblock2 rootfstype=yaffs2 rootflags=inband-tags console=ttyS0,115200n8 rdinit=/sbin/init mem=64M

修改后重新编译内核并烧录:

# export PATH=$PATH:/home/nx/nuc980-sdk/arm_linux_4.8/bin
# make uImage
# sudo cp ../image/980uimage /media/sf_common/

要使用SPI NAND YAFFS2作为rootfs,还需要制作可供烧录到flash中的rootfs数据。新唐的NUC980_Linux_Applications项目中的yaffs2utils套件工具可以将rootfs目录转化为可供烧录的数据。

cd ~/nuc980-sdk/ 
cd NUC980_Linux_Applications/yaffs2utils/

make
# 编译生成的 mkyaffs2 就是我们需要的工具了
# 把工具临时添加到环境变量
export PATH=$PATH:/home/nx/nuc980-sdk/NUC980_Linux_Applications/yaffs2utils

cd ~/nuc980-sdk/ 
# 将当前目录下的rootfs目录打包成数据文件
mkyaffs2 --inband-tags -p 2048 rootfs rootfs_yaffs2.img
# --inband-tags:yaffs2的tag儲存在DATA區塊 / -p:設定NAND Flash頁的大小(Page Size)
# 当前目录下的 rootfs_yaffs2.img 就是需要的数据了
# sudo cp rootfs_yaffs2.img /media/sf_common/

在这里插入图片描述
修改后的内核和文件系统烧录完成后就可以测试了:
在这里插入图片描述

打包镜像

上面烧录过程都是分块一个个进行的,烧录不同的内容还需要设置不同的参数,开发中这样没问题,但是批量烧录时这样并不方便。使用NuWriter工具可以将所有需要的内容打包成一个镜像,烧录时也只要烧录这一个镜像即可。

下面是打包生成镜像演示:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

镜像使用非常方便,并不需要关系地址参数等:
在这里插入图片描述

如果觉得镜像文件存放占空间的话可以镜像压缩(使用前需要解压):
在这里插入图片描述

更多内容可以参考BSP包中的文档《NUC980 NuWriter User Manual》。

总结

根据上面的内容基本可以基于SPI NAND在NUC980上运行起系统来了。接下来使用中更多的是根据需求对kernel、rootfs、application的调整编写等。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐