Linux 内核 Nios II 架构移植详解:在 Altera FPGA 上运行 Linux 的配置、编译与源码实现
2026/9/12 12:40:46 网站建设 项目流程

Linux 内核 Nios II 架构移植详解:在 Altera FPGA 上运行 Linux 的配置、编译与源码实现

【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux

导读

本文以 Documentation/arch/nios2/index.rst 及其核心文档 Documentation/arch/nios2/nios2.rst 为主体,系统讲解 Linux 内核如何移植到 Altera(现 Intel FPGA)的 Nios II 32 位嵌入式处理器上。你将掌握 Nios II 处理器为支持 Linux 所需的硬件前提(MMU 与硬件乘法器)、内核 Kconfig 中与 Nios II 相关的全部配置项及其含义、官方 defconfig 与设备树(Device Tree)的组织方式,以及从编译标志到启动镜像的完整构建流程,并深入理解 arch/nios2 目录下的源码实现细节。


一、Nios II 架构与 Linux 移植概述

Nios II 是 Altera 公司为自家 FPGA 产品线专门设计的 32 位嵌入式处理器架构。它属于软核处理器(soft-core processor),即处理器本身以可综合的硬件描述语言形式存在,开发者可以在 FPGA 中按需配置其功能,再通过 Quartus / QSYS 工具链生成对应硬件系统。

Linux 对 Nios II 的支持正是这样一个“将通用操作系统移植到可配置软核”的经典案例。根据 Documentation/arch/nios2/nios2.rst 的说明:

  • 这是一个专门针对 Nios II(arch 名nios2)处理器的 Linux 移植(port);
  • 要编译该移植版本的内核,需要一份支持通用系统调用 ABI(generic system call ABI)的 GCC 交叉编译器
  • 文档同时给出了编译与启动 Nios II 平台软件的官方参考指引,以及 Altera 官方 Nios II 处理器资料(Nios II Processor Reference Handbook)。

运行 Linux 的硬件前提:MMU 与硬件乘法器

原文档明确指出:为了支持 Linux,Nios II 处理器必须配置为启用 MMU 和硬件乘法器(hardware multiplier)

这一点在源码中得到了严格印证:

  • arch/nios2/Kconfig 中config MMU被硬编码为def_bool y,即 Nios II 移植强制启用 MMU,不可关闭;
  • arch/nios2/platform/Kconfig.platform 中的NIOS2_HW_MUL_SUPPORT等选项用于告知内核硬件是否实现了 MUL/DIV 等指令;
  • arch/nios2/kernel/cpuinfo.c 在启动早期会对设备树中的硬件能力与内核编译配置做一致性校验,若内核启用了CONFIG_NIOS2_HW_MUL_SUPPORT而设备树中altr,has-mul属性缺失,会直接打印ERROR: Nios II MUL different for kernel and DTS警告(对应源码中的err_cpu()宏)。

此外,Nios II 移植还具备以下架构级特征(来源于 arch/nios2/Kconfig 的select语句,可视为移植的“能力清单”):

特性说明
ARCH_NO_SWAP不支持交换分区(swap)
FPU默认def_bool n,无硬件浮点单元
HAVE_PAGE_SIZE_4KB仅支持 4KB 页大小
NR_CPUS默认 1,Nios II 为单核
MODULES_USE_ELF_RELA内核模块使用 RELA 重定位格式
OF/OF_EARLY_FLATTREE强制依赖扁平设备树(DTB)描述硬件
GENERIC_CSUM/GENERIC_HWEIGHT使用内核通用校验和与位计数实现
NO_IOPORT_MAP无传统 I/O 端口地址空间
TIMER_OF/COMMON_CLK/IRQ_DOMAIN/SPARSE_IRQ基于设备树的时钟、定时器与中断基础设施

二、Nios II ABI 与工具链要求

原文档的 "Nios II ABI" 一节明确指出,应用二进制接口(Application Binary Interface)的完整规范请参考Nios II Processor Reference Handbook中的 "Application Binary Interface" 章节。从内核源码可以补充以下几点实现层面的 ABI 事实:

  • 内核的KBUILD_CFLAGS会根据架构修订版本与指令集扩展生成对应的编译标志,详见 arch/nios2/Makefile:
    • -march=r$(CONFIG_NIOS2_ARCH_REVISION):指定 Nios II R1 或 R2 架构;
    • -mhw-mul/-mno-hw-mul-mhw-mulx/-mno-hw-mulx-mhw-div/-mno-hw-div:对应硬件乘/乘扩展/除指令;
    • -mbmx/-mno-bmx-mcdx/-mno-cdx:Nios II R2 的位操作扩展指令;
    • -mcustom-fpu-cfg=60-1:当启用NIOS2_FPU_SUPPORT时使用 Altera 自定义浮点指令配置;
    • 另有-fno-builtin-G 0(禁用小数据段聚合)等嵌入式优化标志。
  • 系统调用表位于 arch/nios2/kernel/syscall_table.c,对应的用户态头文件为 arch/nios2/include/uapi/asm/unistd.h,这正对应原文档所说的“generic system call ABI”——Nios II 使用 Linux 内核的通用系统调用编号方案,因此需要支持该 ABI 的 GCC 工具链。

注意:Nios II 的 R1 与 R2 两个架构修订版本是二进制不兼容的(Kconfig 帮助文本原文为 "The architectures are binary incompatible"),编译内核时必须通过CONFIG_NIOS2_ARCH_REVISION(取值范围 1~2,默认 1)明确指定目标架构。


三、Nios II 内核配置详解(Kconfig)

3.1 基础配置(arch/nios2/Kconfig)

打开 arch/nios2/Kconfig 可以看到 Nios II 移植的核心配置菜单,包括:

  • MMUdef_bool y,强制启用;
  • NR_CPUS:固定为 1;
  • NIOS2_ALIGNMENT_TRAP(Catch alignment trap,默认 y):Nios II CPU 无法执行总线非对齐访问(2/4 字节取数必须落在 2/4 字节对齐地址上)。开启该选项后,非对齐的 load/store 指令会被陷入并在软件中模拟执行,代价是性能下降;
  • Boot options(引导参数)
    • CMDLINE_BOOL/CMDLINE:在引导加载程序无法传递内核参数的平台上,编译期内置默认内核命令行;
    • CMDLINE_FORCE:强制内置命令行覆盖引导加载程序传入的参数;
    • NIOS2_CMDLINE_IGNORE_DTB(默认 y):忽略设备树chosen节点中的bootargs
    • NIOS2_PASS_CMDLINE:使用 U-Boot 环境变量bootargs作为内核命令行,会覆盖“默认内核命令字符串”;
    • NIOS2_BOOT_LINK_OFFSET(默认0x00500000):设置 zImage 的链接地址偏移,对内存较小的板卡可用。
  • Advanced setup(高级内存区域设置)
    • NIOS2_KERNEL_MMU_REGION_BASE(默认0x80000000):内核 MMU 区域的虚拟基址;
    • NIOS2_KERNEL_REGION_BASE(默认0xc0000000):内核区域虚拟基址(即 MMU 开启后内核线性映射的起始地址,cpuinfo与设备树相关代码均依赖该地址约定);
    • NIOS2_IO_REGION_BASE(默认0xe0000000):I/O 区域虚拟基址。

3.2 平台配置(arch/nios2/platform/Kconfig.platform)

arch/nios2/platform/Kconfig.platform 定义了与具体 FPGA 硬件系统强相关的选项,可归纳为四类:

内存设置

  • NIOS2_MEM_BASE(默认0x00000000):内核运行的物理内存基址,直接用于内核链接与初始内存管理;该地址是裸物理地址,若经过桥接(bridge)连接需要手工做地址转换。

设备树加载方式

  • NIOS2_DTB_AT_PHYS_ADDR+NIOS2_DTB_PHYS_ADDR(默认0xc0000000):从固定物理地址加载 DTB,可在没有引导加载程序的情况下直接使用设备树(例如把 DTB 存入 NOR Flash 或片上 ROM);使用 MMU 时地址需加上0xC0000000偏移;
  • BUILTIN_DTB+BUILTIN_DTB_NAME:将指定 DTS 编译并链接进内核镜像,实现“内置设备树”。

Nios II 指令集配置(决定编译标志与运行时一致性校验)

配置项对应编译器标志说明
NIOS2_ARCH_REVISION-march=rNNios II R1 或 R2,二者二进制不兼容,默认 R1
NIOS2_HW_MUL_SUPPORT-mhw-mul硬件乘法指令 MUL
NIOS2_HW_MULX_SUPPORT-mhw-mulx硬件乘扩展指令 MULX
NIOS2_HW_DIV_SUPPORT-mhw-div硬件除法指令 DIV
NIOS2_BMX_SUPPORT-mbmxR2 位操作扩展(仅 R2)
NIOS2_CDX_SUPPORT-mcdxR2 压缩指令扩展(仅 R2)
NIOS2_FPU_SUPPORT-mcustom-fpu-cfg=60-1Altera 自定义浮点指令
NIOS2_CI_SWAB_SUPPORTQSYS 中配置的字节交换(endian converter)自定义指令,加速内核ntohs等字节序转换

缓存设置

  • CUSTOM_CACHE_SETTINGS(默认关闭):仅当需要在设备树信息可用前的早期启动阶段调整缓存参数时开启。Kconfig 帮助文本明确建议“除非你清楚自己在做什么,否则选 N”,并说明即使 Nios II 配置了更小的缓存,Linux 也能正常工作;
  • NIOS2_DCACHE_SIZE(范围0x200~0x10000,默认0x800)、NIOS2_DCACHE_LINE_SIZE(范围0x10~0x20,默认0x20)、NIOS2_ICACHE_SIZE(范围0x200~0x10000,默认0x1000)。

3.3 官方 defconfig:两款参考板卡

仓库在 arch/nios2/configs 下提供了两款官方参考板卡的默认配置,且 arch/nios2/Makefile 将KBUILD_DEFCONFIG := 3c120_defconfig设为默认:

  • 10m50_defconfig:对应 MAX 10 FPGA 开发板(设备树见 10m50_devboard.dts),关键差异项为CONFIG_NIOS2_MEM_BASE=0x8000000
  • 3c120_defconfig:对应 Cyclone III 3C120 开发板,差异项为CONFIG_NIOS2_MEM_BASE=0x10000000CONFIG_NIOS2_PASS_CMDLINE=yCONFIG_NIOS2_BOOT_LINK_OFFSET=0x00800000

两者共同的基础配置包括:

CONFIG_NIOS2_HW_MUL_SUPPORT=y CONFIG_NIOS2_HW_DIV_SUPPORT=y CONFIG_CUSTOM_CACHE_SETTINGS=y CONFIG_NIOS2_DCACHE_SIZE=0x8000 CONFIG_NIOS2_ICACHE_SIZE=0x8000 # CONFIG_NIOS2_CMDLINE_IGNORE_DTB is not set CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y CONFIG_SERIAL_OF_PLATFORM=y CONFIG_SERIAL_ALTERA_JTAGUART=y CONFIG_MTD=y CONFIG_JFFS2_FS=y CONFIG_NFS_FS=y CONFIG_ROOT_NFS=y

从中可以看到 Nios II 板级 Linux 的典型形态:通过 8250 兼容 UART 或 Altera JTAG UART 作为控制台,MTD + JFFS2 承载根文件系统,NFS 作为网络启动(root on NFS)选项,网络驱动使用ALTERA_TSE(Triple-Speed Ethernet)+ Marvell PHY。

3.4 内核内存区域的虚拟地址布局

结合 Kconfig 默认值与 arch/nios2/kernel/cpuinfo.c 等实现,Nios II 移植的虚拟地址空间可归纳为:

区域虚拟地址用途
内核 MMU 区域0x80000000内核页表管理的 MMU 区域(NIOS2_KERNEL_MMU_REGION_BASE
内核区域0xc0000000内核线性映射(NIOS2_KERNEL_REGION_BASE),设备树地址换算中“加 0xC0000000”即指此
I/O 区域0xe0000000外设 I/O 映射(NIOS2_IO_REGION_BASE

四、设备树:硬件能力的唯一真相来源

Nios II 移植完全基于扁平设备树(FDT)描述硬件,这一点由 Kconfig 中强制select OFOF_EARLY_FLATTREE保证。以 10m50_devboard.dts 为例,CPU 节点完整描述了处理器能力:

cpu: cpu@0 { device_type = "cpu"; compatible = "altr,nios2-1.1"; reg = <0x00000000>; interrupt-controller; #interrupt-cells = <1>; altr,exception-addr = <0xc8000120>; altr,fast-tlb-miss-addr = <0xc0000100>; altr,has-div = <1>; altr,has-initda = <1>; altr,has-mmu = <1>; altr,has-mul = <1>; altr,implementation = "fast"; altr,pid-num-bits = <8>; altr,reset-addr = <0xd4000000>; altr,tlb-num-entries = <256>; altr,tlb-num-ways = <16>; altr,tlb-ptr-sz = <8>; clock-frequency = <75000000>; dcache-line-size = <32>; dcache-size = <32768>; icache-line-size = <32>; icache-size = <32768>; };

这些属性与 arch/nios2/kernel/cpuinfo.c 中的setup_cpuinfo()一一对应:内核启动早期读取altr,has-*系列属性判断硬件指令能力,读取 TLB 参数(altr,tlb-num-waysaltr,tlb-num-entriesaltr,pid-num-bits)计算tlb_num_lines等值,并将CONFIG_NIOS2_ICACHE_SIZE/CONFIG_NIOS2_DCACHE_SIZE/CONFIG_NIOS2_DCACHE_LINE_SIZE与设备树中的缓存参数比对,不一致时打印Warning: icache/dcache ... configuration mismatch

该文件同时揭示了几个启动早期的重要检查:

  1. 若设备树中找不到 CPU 节点,panic("%s: No CPU found in devicetree!")
  2. 若 CPU 未实现initda指令(altr,has-initda为假),说明数据缓存行小于 4 字节,直接panic要求更新硬件系统;
  3. altr,tlb-num-ways为 0,同样panic提示检查硬件系统。

设备树中的chosen节点还承担了命令行传递功能:

chosen { bootargs = "debug earlycon console=ttyS0,115200"; stdout-path = &a_16550_uart_0; };

这与前文 Kconfig 中的NIOS2_CMDLINE_IGNORE_DTB/NIOS2_PASS_CMDLINE选项直接相关:是否采用bootargs、是否由 U-Boot 覆盖,均由这三者协同决定。


五、编译与启动:从源码到 vmImage

5.1 构建目标

根据 arch/nios2/Makefile,Nios II 的默认构建产物为vmImageall: vmImage),同时支持zImage,二者均依赖vmlinux生成:

nios2-boot := arch/$(ARCH)/boot BOOT_TARGETS = vmImage zImage KBUILD_IMAGE := $(nios2-boot)/vmImage all: vmImage $(BOOT_TARGETS): vmlinux $(Q)$(MAKE) $(build)=$(nios2-boot) $(nios2-boot)/$@
  • vmImage:面向 U-Boot 的内核镜像(Kernel-only image for U-Boot);
  • zImage:压缩内核镜像,其链接偏移由CONFIG_NIOS2_BOOT_LINK_OFFSET控制;
  • install:调用 arch/nios2/boot/install.sh 安装内核,默认安装路径为INSTALL_PATH ?= /tftpboot(典型 TFTP 网络启动场景),脚本会将旧镜像备份为vmlinuz.old、写入vmlinuz并拷贝System.map

5.2 典型构建命令

# 使用默认 defconfig(3c120_defconfig)生成 .config make ARCH=nios2 CROSS_COMPILE=nios2-linux-gnu- defconfig # 或显式选用 MAX 10 板卡配置 make ARCH=nios2 CROSS_COMPILE=nios2-linux-gnu- 10m50_defconfig # 调整配置 make ARCH=nios2 CROSS_COMPILE=nios2-linux-gnu- menuconfig # 构建 vmImage(默认目标) make ARCH=nios2 CROSS_COMPILE=nios2-linux-gnu- # 构建 zImage / 安装到 /tftpboot make ARCH=nios2 CROSS_COMPILE=nios2-linux-gnu- zImage make ARCH=nios2 CROSS_COMPILE=nios2-linux-gnu- install

前置条件是交叉编译器支持generic system call ABI(原文档特别强调),且宿主机具备 GNU 工具链的-march=r1/r2-mhw-mul等 Nios II 特有标志能力。启动阶段由引导程序(典型为 U-Boot)加载 vmImage/zImage 与 DTB,内核依据前文所述三种方式(引导程序传递 / 固定物理地址 / 内置 DTB)获得设备树后完成初始化。

5.3 启动早期日志可观测性

在内核配置设备树后,可通过/proc/cpuinfo观察运行时能力(由 arch/nios2/kernel/cpuinfo.c 的show_cpuinfo()生成),输出格式包括:

CPU: Nios II/fast REV: 1 MMU: present FPU: none Clocking: 75.00 MHz BogoMips: ... MUL: yes / MULX: no / DIV: yes / BMX: no / CDX: no Icache: 32kB, line length: 32 Dcache: 32kB, line length: 32 TLB: 16 ways, 256 entries, 8 PID bits

这与设备树中的 CPU 属性严格对应,可作为硬件配置是否正确的快速验证手段。


六、源码结构导航

Nios II 移植的完整源码位于 arch/nios2 目录,结构清晰、职责分明,便于读者按需深入:

子目录/文件内容
arch/nios2/kernel启动入口(head.Sentry.S)、中断(irq.c)、异常/陷阱(traps.c)、信号(signal.c)、进程管理(process.c)、系统调用表、CPU 信息(cpuinfo.c)、KGDB 调试支持、非对齐访问模拟(misaligned.c)、指令集模拟(insnemu.S)等
arch/nios2/mm页表(pgtable.c)、TLB(tlb.c)、缺页处理(fault.c)、缓存刷新(cacheflush.c)、DMA 映射、ioremap、uaccess
arch/nios2/include/asm架构相关头文件:寄存器定义(registers.h)、MMU(mmu.h)、页表位(pgtable-bits.h)、系统调用等
arch/nios2/boot压缩启动(compressed/)、设备树源(dts/)、安装脚本(install.sh
arch/nios2/configs官方板卡 defconfig
arch/nios2/platform平台相关配置与platform.c
arch/nios2/lib架构优化的memcpymemmovememsetdelay
arch/nios2/Kconfig 与 arch/nios2/platform/Kconfig.platform全部架构级与平台级配置选项

七、总结

Linux 对 Nios II 的支持是一份典型的“面向可配置软核处理器”的架构移植:

  1. 硬件前提明确:必须启用 MMU 与硬件乘法器,内核侧强制CONFIG_MMU=y,并在启动早期通过设备树校验硬件能力与编译配置的一致性;
  2. 配置体系完整:从指令集扩展(MUL/MULX/DIV/BMX/CDX/FPU/自定义指令)、内存区域布局(0x80000000/0xc0000000/0xe0000000)、缓存参数到引导命令行策略,arch/nios2/Kconfig 与 arch/nios2/platform/Kconfig.platform 提供了细粒度的控制面;
  3. 设备树驱动一切:CPU 能力、TLB 结构、时钟、串口、以太网、GPIO、定时器全部由 DTB 描述,配合BUILTIN_DTB或固定地址 DTB 可在无引导程序场景下启动;
  4. 构建流程简单直接make ARCH=nios2 ... defconfig后构建默认产出面向 U-Boot 的vmImage,配合install目标可完成 TFTP 目录部署。

对于希望在 Altera/Intel FPGA 上运行 Linux 的开发者而言,理解 Documentation/arch/nios2/nios2.rst 中关于 MMU/硬件乘法器要求与通用系统调用 ABI 工具链的前提,再结合本文梳理的 Kconfig、defconfig 与设备树细节,即可快速完成从硬件配置到内核启动的完整链路搭建。

【免费下载链接】linuxLinux kernel source tree项目地址: https://gitcode.com/GitHub_Trending/li/linux

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询