• 新唐NUC980使用记录:U-Boot & Linux 编译与烧录(基于SPI NAND)


    目的

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

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

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

    开始前请将将开发板的USB0和UART0都接到Windows电脑上,电脑上使用终端工具连接UART0。

    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/
    
    • 1
    • 2

    修改配置文件:

    # cp include/configs/nuc980_evb.h include/configs/nuc980_evb.h.original
    gedit include/configs/nuc980_evb.h
    
    • 1
    • 2

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

    #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的分区设置等,可以按照需求调整
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    修改配置选项:

    # make distclean
    make nuc980_defconfig
    make menuconfig
    
    • 1
    • 2
    • 3

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

    进行编译:

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

    编译完成后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/
    
    • 1
    • 2
    • 3

    拨动拨动开关将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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    上面环境变量中使用 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/
    
    • 1
    • 2

    套用配置:

    # make distclean
    make nuc980_defconfig
    
    • 1
    • 2

    进行编译:

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

    注意默认配置下编译时会将 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/
    
    • 1
    • 2

    拨动拨动开关将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
    
    • 1
    • 2

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

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

    找到对应位置进行修改:

    // 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
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    修改配置选项:

    # make distclean
    make nuc980_defconfig
    make menuconfig
    
    • 1
    • 2
    • 3

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

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

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

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

    在这里插入图片描述

    使用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/
    
    • 1
    • 2
    • 3

    要使用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/
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

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

    打包镜像

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

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

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

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

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

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

    总结

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

  • 相关阅读:
    篮球竞赛预约平台设计与实现的源码+文档
    13.Mybatis之动态sql查询(面试)
    leetcode 739. 每日温度、496. 下一个更大元素 I
    JavaScript常用知识点
    2024年第十五届蓝桥杯第三期(校内)模拟赛题解
    linux 安装配置github
    vs2022中使用gridview显示sqlserver中的数据时只显示了列而没有显示表中的数据
    React源码分析3-render阶段(穿插scheduler和reconciler)
    Java1.8+ JUC包的ConcurrentHashMap源码分析
    RabbitMQ进阶技术回顾
  • 原文地址:https://blog.csdn.net/Naisu_kun/article/details/125371531