您现在的位置是:首页 >技术教程 >新唐NUC980使用记录(5.10.y内核):u-boot & linux & rootfs 编译与烧录测试(基于SD1位置SD卡)网站首页技术教程

新唐NUC980使用记录(5.10.y内核):u-boot & linux & rootfs 编译与烧录测试(基于SD1位置SD卡)

Naisu Xu 2024-05-30 13:36:12
简介新唐NUC980使用记录(5.10.y内核):u-boot & linux & rootfs 编译与烧录测试(基于SD1位置SD卡)

目的

从去年(2022)开始新塘官方的NUC980 5.10.y内核的项目开始展开,这篇文章将测试在NUC980上使用5.10.y内核。

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

对于NUC980芯片本身的一些内容可以参考:
《新唐NUC980使用记录:基础说明与资料索引》

基础准备

烧录环境

烧录这里在Windows上进行,准备工作的话就是安装下设备驱动,准备烧录软件,相关内容仓库地址如下:
https://github.com/OpenNuvoton/NUC980_NuWriter

电脑上安装了 Git 的话可以 git clone 来下载,没有的话也可以直接在网页上下载。

在这里插入图片描述

如果是Linux平台,相关内容仓库地址为:
https://github.com/OpenNuvoton/NUC980_NuWriter_CMD

开发编译环境

下载安装Ubuntu Desktop(这里使用版本为22.04.2):
https://ubuntu.com/download/desktop

我这里使用VirtualBox(本文中版本为7.0.8)虚拟机安装Ubuntu,相关使用说明见下文:
《免费虚拟机软件VirtualBox快速入门》

安装完成后进行基础环境安装与设置:

sudo apt update
sudo apt install -y build-essential

# 下面两行内容是我个人习惯设置
# 在虚拟机中:安装增强功能、设置分辨率、初次软件更新&关闭更新检查、关闭熄屏
# 在VirtualBox对虚拟机进行设置:共享粘贴板、共享文件夹设置网卡2为桥接网卡

以下根据需求安装:

# 安装SSH服务
sudo apt install -y openssh-server

# 安装编辑器 VS Code
# 从官网中下载 .deb 格式安装包: https://code.visualstudio.com/
# 通过内置浏览器下载的话默认会下载到 ~/Downloads/ 目录下
sudo apt install ~/Downloads/code_1.78.0-1683145611_amd64.deb 
# 安装完成后可以使用 code 命令打开编辑器
# VS Code中可以安装Embedded Linux Kernel Dev扩展,方便开发

因为需要从GitHub下载项目所以还要安装git:

sudo apt install -y git-all
# git使用时可能需要设置用户名和邮箱
# git config --global user.name "naisu"
# git config --global user.email naisu@example.com

下面是 u-boot & linux & rootfs 配置编译过程中可能需要用到的各种库(不一定全部需要或是完全够,先装一些是一些):

sudo apt install -y libusb-1.0-0-dev zlib1g-dev
sudo apt install -y pkg-config
sudo apt install -y python2-dev python3-dev
sudo apt install -y swig
sudo apt install -y libncurses-dev libncurses5-dev
sudo apt install -y libssl-dev
sudo apt install -y libc6:i386 lib32stdc++6 lib32z1
sudo apt install -y u-boot-tools
sudo apt install -y flex

建立工作目录:

# 本文将工作目录设置在用户目录($HOME)下的nuc980-sdk文件夹中
cd ~
mkdir nuc980-sdk 

SD卡分区

嵌入式Liunx系统通常分为Bootloader、Linux Kernel、RootFS三个部分,三个部分分别存储在三个位置中。具体对于SD卡而言存储分布如下:

  • Bootloader放在开头1M以内位置上(这部分空间通常分区工具分区时会自动跳过);
    通常还需跳过开头至少512Bytes,这部分用于保存SD卡分区信息;
  • Linux Kernel放在第一个分区上,通常使用FAT32(vfat)格式分区,通常不需要太大;
  • RootFS放在第二个分区上,分区文件系统可以根据需求选择,这个可以大点,甚至分配剩下所有的空间;

SD卡可以通过读卡器在电脑上进行分区。Ubuntu上可以使用 GParted 工具进行分区:
安装方式: sudo apt install gparted
在这里插入图片描述
上面分区中唯一需要注意的是必须有一个fat32格式的分区(通常是第一个分区),用来存放内核和设备树等,不需要很大。

当然Ubuntu上也可以选择使用命令行方式进行分区:

# 先将SD卡插入Ubuntu中
# 使用 lsblk 查看SD卡设备号sdX
# 我这里显示为sdb,下面均以此进行说明

# 如果已经分过区了那么Ubuntu可能会自动挂载
# 逐条使用 sudo umount /dev/sdbn 进行卸载

# 对SD(TF)卡进行分区
sudo fdisk /dev/sdb
# 如果有分区的话可以输入 d 回车依次删除
# 输入 n 新建分区,分区大小根据需要设置即可
# 下面是我新建的两个分区的输入情况
# n回车  回车(p)  回车(1)  回车(2048)  +32M回车  (如果有额外提示则Y回车)
# n回车  回车(p)  回车(2)  回车(67584) +200M回车  (如果有额外提示则Y回车)
# 输入 w 回车保存退出,输入使用 lsblk 查看分区情况

# 格式化分区建立文件系统
sudo mkfs.vfat /dev/sdb1
sudo mkfs.ext4 /dev/sdb2

制作和设置编译工具链

制作toolchain和rootfs

这里使用buildroot来制作rootfs,先制作rootfs是打算后面用的交叉编译工具链也通过这里生成。

下载、配置与编译 buildroot:
buildroot下载地址从官网获取 https://buildroot.org/ ,这里使用版本为 2023.02 。

cd ~/nuc980-sdk/
wget https://buildroot.org/downloads/buildroot-2023.02.tar.xz
tar -xJf buildroot-2023.02.tar.xz

# 进入buildroot目录
cd buildroot-2023.02/
 
# 进行配置
# 这里做测试使用,只要配置下目标平台和工具链即可,详见后面截图
make menuconfig

# 编译
make

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

编译完成后 output 目录下的 host 目录中就是交叉编译工具链(toolchain); output 目录下的 images 目录中的 rootfs.tar 就是生成的根文件系统。

拷贝rootfs内容到SD卡

因为最终测试时是需要用到rootfs的,所以这里直接先进行拷贝。

将SD卡接入到Ubuntu中,使用 lsblk 查看挂载情况:
在这里插入图片描述

使用下面命令拷贝rootfs内容到SD卡:

# cd ~/nuc980-sdk/buildroot-2023.02/
# sudo rm -rf /media/nx/rootfs/*
sudo tar -xf output/images/rootfs.tar -C /media/nx/rootfs/

设置编译工具链

注意PATH使用自己的路径,每次打开终端都需要重新设置:

export ARCH=arm
export CROSS_COMPILE=arm-buildroot-linux-gnueabi-
export PATH=$PATH:/home/nx/nuc980-sdk/buildroot-2023.02/output/host/bin

u-boot编译与测试

下载、配置与编译

下载 u-boot:

cd ~/nuc980-sdk/

git clone --depth=1 https://github.com/OpenNuvoton/NUC970_U-Boot_v2016.11.git
# 得到的NUC970_U-Boot_v2016.11文件夹就是uboot项目了,这个是NUC970和NUC980共用的
# 当前版本由cwweng-nuvoton在2022-12-06最后提交,hash为d4ba46e
# 可以打包备份下:tar -cJf NUC970_U-Boot_v2016.11.tar.xz NUC970_U-Boot_v2016.11/

# 进入u-boot目录
cd NUC970_U-Boot_v2016.11/

修改源码以支持SD卡:

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

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

/*#define CONFIG_SYS_USE_SPIFLASH */
/*#define CONFIG_SYS_USE_NANDFLASH */ // 屏蔽
/*#define CONFIG_ENV_IS_IN_NAND */ // 屏蔽
/*#define CONFIG_ENV_IS_IN_SPI_FLASH */
#define CONFIG_ENV_IS_IN_MMC // 51行 启用MMC

// include/configs/nuc980_evb.h 这个文件中还定义了很多位置和大小的参数

配置 u-boot:

# cd ~/nuc980-sdk/NUC970_U-Boot_v2016.11
# make distclean
# 加载默认配置
make nuc980_defconfig

# 进行针对性配置
# 这里主要配置启用SD1
make menuconfig

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

需要注意的是下面的内核默认是启用了设备树支持的,而这个u-boot早先版本是没有启用设备树的,如果使用的是2022.08.19以前的版本的话需要启用 Library routines -> Enable the FDT library 。

编译 u-boot:

# export ARCH=arm; export CROSS_COMPILE=arm-buildroot-linux-gnueabi-
# export PATH=$PATH:/home/nx/nuc980-sdk/buildroot-2023.02/output/host/bin
make
# 可以根据电脑配置使用make -jx等加快编译速度

烧录u-boot与环境变量

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

# cd ~/nuc980-sdk/NUC970_U-Boot_v2016.11
# 拷贝至Windows电脑上
# sudo cp u-boot.bin /media/sf_common/

烧录U-Boot需要将SD卡插在开发板上。拨动拨动开关将 PG[1:0] 设置为 00,按下复位键。在Windows中使用NuWriter进行烧录(烧录通过USB0,调试交互默认通过UART0):
在这里插入图片描述

烧录u-boot环境变量:
在Windows中新建env.txt文件,写入下面内容:

bootdelay=3
baudrate=115200
stderr=serial
stdin=serial
stdout=serial
loadkernel=fatload mmc 0:1 0x7fc0 uImage
loaddtb=fatload mmc 0:1 0xc00000 nuc980-dev-v1.0.dtb
bootcmd=run loadkernel;run loaddtb;bootm 0x7fc0 - 0xc00000

烧录环境变量:
在这里插入图片描述

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

linux kernel编译与测试

下载、配置与编译

下载 linux kernel:

cd ~/nuc980-sdk/

# 默认情况下下面项目编译时会将生成的Image和dtb文件拷贝到项目目录同级的image目录中,所以需要创建该目录
# mkdir image
# 但是实际使用时需要用到uImage文件,但是该文件却没有拷贝出来,所以下面操作中干脆把拷贝这个操作注释掉了,这样也不用收到创建image目录了

git clone --depth=1 https://github.com/OpenNuvoton/NUC980-linux-5.10.y
# 得到的NUC980-linux-5.10.y文件夹就是linux kernel项目了
# 当前版本由yclu-ntc在2023-04-27最后提交,hash为74db56f
# 可以打包备份下:tar -cJf NUC980-linux-5.10.y.tar.xz NUC980-linux-5.10.y/

# 进入linux kernel目录
cd NUC980-linux-5.10.y/

配置 linux kernel:

# make distclean
make nuc980_defconfig

# 进行针对性配置
make menuconfig

默认使用ramfs,而本文使用sd卡分区上的fs,所以需要取消默认设置:
在这里插入图片描述

启用ext4文件系统支持:
在这里插入图片描述

修改设备树文件:

# cp arch/arm/boot/dts/nuc980-dev-v1.0.dts arch/arm/boot/dts/nuc980-dev-v1.0.dts.original
gedit arch/arm/boot/dts/nuc980-dev-v1.0.dts

设备树文件中主要就是要注意sd接口要启用,并且不和其它功能冲突,本文中设备树文件内容见文章结尾。

修改Makefile文件以取消编译时拷贝image和dtb文件操作:

# cp Makefile Makefile.original
# cp arch/arm/boot/Makefile arch/arm/boot/Makefile.original
gedit Makefile
gedit arch/arm/boot/Makefile
# 装了VS Code也可以用VS Code来修改
# code ...

在这里插入图片描述

编译 linux kernel:

# 设置编译工具链
# export ARCH=arm; export CROSS_COMPILE=arm-buildroot-linux-gnueabi-
# export PATH=$PATH:/home/nx/nuc980-sdk/buildroot-2023.02/output/host/bin

# 编译生成内核镜像
make uImage
# 可以根据电脑配置使用make -jx等加快编译速度

# 编译生成设备树文件
make dtbs

编译生成的系统镜像 uImagearch/arm/boot/ 目录下,设备树文件 nuc980-dev-v1.0.dtbarch/arm/boot/dts/ 目录下。

系统运行测试

拷贝文件到SD卡boot分区:

# 拷贝至Windows电脑上
# sudo cp arch/arm/boot/uImage /media/sf_common/
# sudo cp arch/arm/boot/dts/nuc980-dev-v1.0.dtb /media/sf_common/

# 在电脑上将两个文件拷贝到SD卡boot分区

拷贝完成后将SD开插回开发板,上电测试:
在这里插入图片描述

默认情况下登录用户名为 root ,没有密码。如果登录有问题的话检查buildroot相关配置:
在这里插入图片描述

如果启动有问题的话根据控制台输出来检查。比如内核和设备树加载有问题的话可以检查环境变量,检查内核镜像和设备树文件等;文件系统加载问题的话检查文件系统分区、文件系统内容等;如果init进程启动失败的话尝试重新编译拷贝根文件系统内容。具体情况具体分析处理。

总结

根据上面的内容基本可以基于SD1位置使用SD卡在NUC980上运行起系统来了。 5.10.y 内核和之前 4.4 内核相比最大的区别是默认就启用了设备树,这也是目前 arm linux 比较流行的方式。

设备树文件内容

/*
 * Device Tree Source for NUC980 DEV board
 *
 * Copyright (C) 2018 Nuvoton Technology Corp.
 *
 * The code contained herein is licensed under the GNU General Public
 * License. You may obtain a copy of the GNU General Public License
 * Version 2 or later at the following locations:
 *
 * http://www.opensource.org/licenses/gpl-license.html
 * http://www.gnu.org/copyleft/gpl.html
 */
/dts-v1/;

#include "nuc980.dtsi"

/ {
	model = "Nuvoton NUC980 DEV V1.0";
	compatible = "nuvoton,nuc980-dev-v1.0", "nuvoton,nuc980";

	chosen {
		bootargs = "console=ttyS0,115200n8 noinitrd rootfstype=ext4 root=/dev/mmcblk0p2 rw rootwait mem=64M";
	};

	apb {
		uart1: serial@b0071000 {
			status = "disabled";
		};

		uart2: serial@b0072000 {
			status = "disabled";
		};

		uart3: serial@b0073000 {
			status = "disabled";
		};

		uart4: serial@b0074000 {
			status = "disabled";
		};

		uart5: serial@b0075000 {
			status = "disabled";
		};

		uart6: serial@b0076000 {
			status = "disabled";
		};

		uart7: serial@b0077000 {
			status = "disabled";
		};

		uart8: serial@b0078000 {
			status = "disabled";
		};

		uart9: serial@b0079000 {
			status = "disabled";
		};

		can0: can@b00a0000 {
			status = "disabled";
		};

		can1: can@b00a1000 {
			status = "disabled";
		};

		rtc: rtc@b0041000 {
			status = "disabled";
		};

		nadc: nadc@b0043000 {
			status = "disabled";
		};

		pwm0: pwm@b0058000 {
			status = "disabled";
		};

		pwm1: pwm@b0059000 {
			status = "disabled";
		};


		etimer0: etimer0@b0050000 {
			status = "disabled";
		};

		etimer1: etimer1@b0050100 {
			status = "disabled";
		};

		etimer2: etimer2@b0051000 {
			status = "disabled";
		};

		etimer3: etimer3@b0051100 {
			status = "disabled";
		};

		i2c0: i2c0@b0080000 {
			status = "disabled";
		};

		i2c1: i2c1@b0081000 {
			status = "disabled";
			pinctrl-0 = <&pinctrl_i2c1_PB>;
		};


		i2c2: i2c2@b0082000 {
			status = "disabled";
			pinctrl-0 = <&pinctrl_i2c2_PB>;
		};

	};

	ahb {

		usbh_ehci@b0015000 {
			status = "okay";
		};
		usbh_ohci@b0017000{
			status = "okay";
		};

		usbdev@b0016000 {
			status = "okay";
		};

		fmi@b0019000 {
			status = "disabled";
		};

		sdh@b0018000 {
			status = "okay";
		};

		emac0@b0012000 {
			status = "disabled";
		};
		emac1@b0022000 {
			status = "disabled";
		};
		ccap0@b0024000 {
			status = "disabled";
		};
		i2c_gpio0: i2c-gpio-0 {
			status = "disabled";
		};
		ccap1@b0014000 {
			status = "disabled";
		};
		i2c_gpio1: i2c-gpio-1 {
			status = "disabled";
		};
		dma@b0008000 {
			status = "okay";
		};

		i2s: i2s@b0020000 {
			status = "disabled";
		};

		i2s_pcm: i2s_pcm {
			status = "disabled";
		};

		sound {
			compatible = "nuvoton,nuc980-audio";
			i2s-controller = <&i2s>;
			i2s-platform = <&i2s_pcm>;
			status = "disabled";
		};
		ebi: ebi@b0010000 {
			status = "disabled";
		};
	};
};
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。