【ARM】内核移植(编译)

内核移植(编译)

  • 职责拆解与交付物梳理
  • [一. 内核移植(编译)](#一. 内核移植(编译))
    • [1. 获取内核源码](#1. 获取内核源码)
    • [2. 移植linux源码](#2. 移植linux源码)
      • [2.1. 将内核源码拷贝到ubuntu中,并解压](#2.1. 将内核源码拷贝到ubuntu中,并解压)
      • [2.2. 打补丁](#2.2. 打补丁)
      • [2.3. 生成标准板配置文件](#2.3. 生成标准板配置文件)
      • [2.4. 安装相关的工具(库)](#2.4. 安装相关的工具(库))
      • [2.5. 增加配置内核](#2.5. 增加配置内核)
      • [2.6. 编译linux内核源码](#2.6. 编译linux内核源码)
  • [二. 编译设备树文件](#二. 编译设备树文件)
    • [1. 将fsmp157的设备树文件拷贝到linux内核源码中](#1. 将fsmp157的设备树文件拷贝到linux内核源码中)
    • [2. 修改 `arch/arm/boot/dts/Makefile`](#2. 修改 arch/arm/boot/dts/Makefile)
    • [3. 编译设备树文件](#3. 编译设备树文件)
    • [4. 更新`/tftpboot`中的设备树文件](#4. 更新/tftpboot中的设备树文件)
  • [三. 根文件系统制作---buildroot](#三. 根文件系统制作---buildroot)
    • [1. 概念及获取](#1. 概念及获取)
    • [2. 将buildroot和交叉编译器拷贝到ubuntu的tools,并解压](#2. 将buildroot和交叉编译器拷贝到ubuntu的tools,并解压)
    • [3. 配置 buildroot](#3. 配置 buildroot)
    • [4. 编译buildroot](#4. 编译buildroot)
  • [四. 在开发板中测试新创建的文件系统](#四. 在开发板中测试新创建的文件系统)
    • [1. 将文件系统路径配置到nfs中](#1. 将文件系统路径配置到nfs中)
    • [2. 修改uboot参数](#2. 修改uboot参数)
    • [3. 取消rootfs登录账号和密码](#3. 取消rootfs登录账号和密码)
    • [4. 设置用户名和主机名](#4. 设置用户名和主机名)

本文档详细介绍了 Linux内核移植与编译流程 。主要内容包括:获取内核源码(官方镜像或芯片原厂BSP包)、解压标准内核并打补丁、生成配置文件(multi_v7_defconfig)、安装必要工具库、通过menuconfig配置内核选项(支持eMMC和网卡驱动)、编译生成uImage内核镜像等关键步骤。文档特别强调了交叉编译环境配置验证、补丁管理建议以及版本控制注意事项,为嵌入式Linux开发人员提供了从源码获取到镜像生成的全流程指导。编译完成后,将生成的uImage内核镜像拷贝至/tftpboot目录即完成移植工作。

职责拆解与交付物梳理

角色 主要任务 关键交付物 核心依赖
硬件工程师 需求评审、原理图、PCB、BOM、 硬件调试 硬件母板/子板、调试手册 芯片原厂参考设计、器件文档
Linux 系统工程师 Bootloader/Kernel 移植、根文件系统制作、系统裁剪 U‑Boot、Linux 内核、根文件系统镜像 (rootfs.ext4、rootfs.tar) SoC BSP、交叉工具链、Buildroot
Linux 驱动工程师 片上/板级驱动开发与调试 Kernel patch、Device Tree 更新、驱动说明 内核源码、目标板硬件资料
Linux 应用工程师 产品功能模块实现、上层应用 应用程序、启动脚本、配置文件 系统工程师提供的 rootfs & SDK
测试/运维支持 烧录脚本、工装、量产流程 自动化脚本、测试报告 系统镜像、测试工具

推荐学习路径:

  • 熟悉 gitmake、交叉编译基础。
  • 掌握内核配置、Device Tree、常见总线驱动。
  • 跟随真实项目完成一次从 BSP 到 rootfs 的端到端交付。
  • 了解 BuildrootYocto,以适应不同客户需求。
  • 加强调试工具链:gdbserverperftrace-cmdftraceethtool 等等...

一. 内核移植(编译)

1. 获取内核源码

bash 复制代码
1》从官网获取
   https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/   -----原厂工程师
   
2》从芯片原厂
   三星,高通,MTK,海思,RK,全志,ST等    ------产品工程师

linux内核源码如下:
en.SOURCES-stm32mp1-openstlinux-5-4-dunfell-mp1-20-06-24.tar.xz
bash 复制代码
源码获取渠道:
	官方镜像站
	此处提供的链接(https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/)是 Linux Kernel 官方镜像。针对 STM32MP1 BSP 使用的 linux-5.4.31.tar.xz,可直接从该站点获取,保证源码完整性与 PGP 签名验证。  

SoC原厂BSP包
	ST的 en.SOURCES-stm32mp1-openstlinux-5-4-dunfell-mp1-20-06-24.tar.xz 集成了标准内核、patch 以及 fragment 配置,便于快速组装官方配置。  

2. 移植linux源码

2.1. 将内核源码拷贝到ubuntu中,并解压

bash 复制代码
1》解压
tar -xvf en.SOURCES-stm32mp1-openstlinux-5-4-dunfell-mp1-20-06-24.tar.xz

2》进入linux-stm32mp-5.4.31-r0,解压标准的内核源码
   cd stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24/sources/arm-ostl-linux-gnueabi/linux-stm32mp-5.4.31-r0
   tar -xvf linux-5.4.31.tar.xz     //解压标准内核源码

2.2. 打补丁

bash 复制代码
1》进入内核源码目录
   cd linux-5.4.31/
2》打补丁
   for p in `ls -1 ../*.patch`; do patch -p1 < $p; done

解压与打补丁建议:

建议在 for 循环前加入 set -e 并记录日志,方便回滚:
for p in ../*.patch; do echo "Applying $p" | tee -a ../patch.log; patch -p1 < "$p"; done

2.3. 生成标准板配置文件

bash 复制代码
先导入交叉工具链
   source /opt/sdk/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi

1》  生成 multi_v7_defconfig 默认配置
   make ARCH=arm multi_v7_defconfig "fragment*.config"
       
2》在默认 multi_v7_defconfig 配置中加入 ST 官方提供的 fragment config
   for f in `ls -1 ../fragment*.config`; do scripts/kconfig/merge_config.sh -m -r .config $f; done
   yes '' | make ARCH=arm oldconfig
       
3》 生成自己的默认配置文件
   cp .config arch/arm/configs/stm32_fsmp1a_defconfig
       
4》取消 git 中的 SHA1
   echo "" > .scmversion   


//标准版基本配置已经配置好,在编译前如果需要编译额外的功能或者驱动,可以使用 meunconfig 来对内核进行配置

5》将配置好的内核源码拷贝到 ~/mp157/kernel
   cp -af linux-5.4.31  ~/mp157/kernel/

7》返回到内核目录 ~/mp157/kernel/ ,并删除其他文件
   cd ~/mp157/kernel/
   rm -r en.SOURCES-stm32mp1-openstlinux-5-4-dunfell-mp1-20-06-24.tar.xz  stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24/

2.4. 安装相关的工具(库)

bash 复制代码
sudo apt-get install -y gawk wget git-core diffstat unzip texinfo gcc-multilib build-essential chrpath socat cpio python python3 python3-pip python3-pexpect xz-utils debianutils iputils-ping

sudo apt-get install  -y libsdl1.2-dev xterm  make xsltproc docbook-utils fop dblatex xmlto python-git-doc ncurses-dev libncurses5-dev libncursesw5-dev lib32ncurses5 libssl-dev linux-headers-generic u-boot-tools device-tree-compiler bison flex g++ libyaml-dev

sudo apt-get install  -y coreutils bsdmainutils sed curl bc lrzsz corkscrew cvs subversion mercurial nfs-common nfs-kernel-server libarchive-zip-perl dos2unix texi2html diffstat libxml2-utils

2.5. 增加配置内核

bash 复制代码
在内核源码目录下执行下面的命令:
make ARCH=arm menuconfig
由于内核源码默认配置已经支持 eMMC和网卡,在此列出主要选项,如下:
Device Drivers --->
   Generic Driver Options  ---> 
      [*] Support for uevent helper         //支持热插拔,在/proc下生成/proc/sys/kernel/hotplug
Device Drivers --->
   <*> MMC/SD/SDIO card support --->
      [*] STMicroelectronics STM32 SDMMC Controller

Device Drivers --->
[*] Network device support --->
   [*] Ethernet driver support --->
       <*> STMicroelectronics Multi-Gigabit Ethernet driver
       <*> STMMAC Platform bus support
       <*> Support for snps,dwc-qos-ethernet.txt DT binding.
       <*> Generic driver for DWMAC
       <*> STM32 DWMAC support

2.6. 编译linux内核源码

bash 复制代码
1》编译内核源码
make ARCH=arm -j4 uImage LOADADDR=0xC2000040

//编译后生成文件uImage,如下:
LD      arch/arm/boot/compressed/vmlinux
 OBJCOPY arch/arm/boot/zImage
 Kernel: arch/arm/boot/zImage is ready
 UIMAGE  arch/arm/boot/uImage
Image Name:   Linux-5.4.31
Created:      Tue Sep 19 03:15:30 2023
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    7312584 Bytes = 7141.20 KiB = 6.97 MiB
Load Address: c2000040
Entry Point:  c2000040
 Kernel: arch/arm/boot/uImage is ready
 
2》将uImage 拷贝到/tftpboot/
   cp arch/arm/boot/uImage /tftpboot/   //将新编译的uImage拷贝到/tftpboot中

配置与版本管理注意点:

  • 环境变量
    source /opt/sdk/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi 后建议执行 echo $CCecho $ARCH 确认交叉链已生效,避免与主机 GCC 混用。
    merge_config.sh
    scripts/kconfig/merge_config.sh 默认输出 .config,你已通过 yes '' | make oldconfig 消除交互式提示,推荐改用 make ARCH=arm olddefconfig(非交互)以减少疏漏。
    ● 配置固化
    cp .config arch/arm/configs/stm32_fsmp1a_defconfig 后,可在版本库中保留该 defconfig,方便同事复现环境。
    ● Git 版本提示
    echo "" > .scmversion 可以关闭 -dirty 字样;若打算长期维护建议保留 Git repo,在 .gitignore 中添加中间文件即可。

二. 编译设备树文件

在linux内核源码中,设备树文件一般在: arch/arm/boot/dts/

1. 将fsmp157的设备树文件拷贝到linux内核源码中

bash 复制代码
将 D:\peter\ARM体系结构与系统移植\源码\设备树文件  目录中下面的所有文件 
stm32mp151.dtsi  
stm32mp157a-fsmp1a.dts  
stm32mp15-pinctrl.dtsi  
stm32mp15xx-dkx.dtsi  
stm32mp15xx-fsmp1x.dtsi

拷贝到: linux内核源码的 arch/arm/boot/dts/ 目录中

2. 修改 arch/arm/boot/dts/Makefile

bash 复制代码
1》打开Makefile
vim arch/arm/boot/dts/Makefile

2>添加下面一行
992         stm32mp157a-fsmp1a.dtb\

3. 编译设备树文件

bash 复制代码
1》指定编译某个设备树文件:
	make ARCH=arm -j4  stm32mp157a-fsmp1a.dtb LOADADDR=0xC2000040
或
2》编译 arch/arm/boot/dts/中所有的设备树文件
	make ARCH=arm -j4  dtbs LOADADDR=0xC2000040

4. 更新/tftpboot中的设备树文件

bash 复制代码
cp arch/arm/boot/dts/stm32mp157a-fsmp1a.dtb /tftpboot/  //将新编译的设备树文件拷贝到/tftpboot中
  • **编译与产物管理:
    • 编译命令与输出已验证。建议统一产物目录,避免误传:**
bash 复制代码
mkdir -p ~/mp157/kernel/build
make ARCH=arm O=build multi_v7_defconfig
make ARCH=arm O=build -j$(nproc) uImage LOADADDR=0xC2000040
cp build/arch/arm/boot/uImage /tftpboot/ 

LOADADDR 要与板级 u-boot 配置保持一致,建议写入 Makefile.kernel 或文档中,减少手动输入错误。


设备树配置要点:

  • 文件同步
    • 将自定义 DTS/DTSI 拷贝进 arch/arm/boot/dts/,同时修改 Makefile。可以在 arch/arm/boot/dts/Makefile 中使用模块化插入或 stm32mp157*.dtb 分组,方便未来维护。
  • 编译器选项
    • 单独编译:make ARCH=arm O=build stm32mp157a-fsmp1a.dtb
    • 全量编译:make ARCH=arm O=build dtbs
    • 产物统一输出 build/arch/arm/boot/dts/
  • 版本控制
    • 可以建立 board/stm32mp157a/ 目录存放自定义 DTS & fragment,避免直接覆盖官方文件,便于差异管理。

三. 根文件系统制作---buildroot

1. 概念及获取

bash 复制代码
在linux文件系统制作中,使用busybox可以生成linux的系统命令,但是系统需要的c库和第三方库,需要自己单独获取,这种原始的制作根文件系统的方法比较麻烦,而且制作的根文件系统默认是没有账号和密码

buildroot 工具集成了busybox,而且还集成各种常见的软件和第三方库,在制作根文件系统时,就不需要自己在单独获取其他库,为制作根文件系统带来了很大的方便。
获取buildroot ----官网: https://buildroot.org/download.html

//使用buildroot制作根文件系统需要用到:
buildroot-2021.02.1.tar.xz              //源码
arm-fsmp1x-linux-gnueabihf_sdk-buildroot.tar.gz   //交叉工具链

2. 将buildroot和交叉编译器拷贝到ubuntu的tools,并解压

bash 复制代码
1》创建文件系统的目录
	farsight@ubuntu:~$ mkdir mp157/rootfs
1》解压buildroot源码
farsight@ubuntu:~/mp157/rootfs$ tar xvf buildroot-2021.02.1.tar.xz

2》解压交叉工具链
farsight@ubuntu:~/mp157/rootfs$ tar -xvf arm-fsmp1x-linux-gnueabihf_sdk-buildroot.tar.gz

3. 配置 buildroot

bash 复制代码
//导入交叉工具链
source /opt/sdk/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi

//进入到buildroot源码目录下,
  cd buildroot-2021.02.1/
//执行: make menuconfig
1》配置目标选项
  Target options  ---> 
      Target Architecture (ARM (little endian))  ---> 
      Target Binary Format (ELF)  --->
      Target Architecture Variant (cortex-A7)  --->
      Target ABI (EABIhf)  ---> 
      Floating point strategy (NEON/VFPv4)  ---> 
      ARM instruction set (ARM)  ---> 
2》配置交叉工具链
 Toolchain  --->
  Toolchain type (External toolchain)  --->
  Toolchain (Custom toolchain)  --->           //使用自己的交叉编译器
  Toolchain origin (Pre-installed toolchain)  --->    //预装的编译器
  (/home/farsight/mp157/rootfs/arm-fsmp1x-linux-gnueabihf_sdk-buildroot) Toolchain path
  ($(ARCH)-fsmp1x-linux-gnueabihf) Toolchain prefix     //交叉编译器的前缀
      External toolchain gcc version (9.x)  --->
      External toolchain kernel headers series (5.4.x)  --->  //交叉编译器Linux版本号
      External toolchain C library (glibc/eglibc)  --->  
      [*] Toolchain has SSP support?
      [ ] Toolchain has RPC support?     //取消勾选
      [*] Toolchain has C++ support?
      [*] Enable MMU support 
  
3》系统配置
 System configuration  --->
  (farsight) System hostname   		//主机名,自定义
  (Welcome to farsight STM32MP157a) System banner    //欢迎语
  Init system (BusyBox)  --->
      /dev management (Dynamic using devtmpfs + mdev)  --->
      [*] Enable root login with password    //使能登录密码
      (123) Root password        //设置登录密码

4》 配置文件系统镜像 ---filesystem image
  Filesystem images  --->
    [*] ext2/3/4 root filesystem
      ext2/3/4 variant (ext4)  ---> 
    (1G)  exact size     //ext4 根文件系统 
5》禁止内核和u-boot编译
Kernel  --->
   [ ] Linux Kernel       //不能选择该选项
Bootloaders  --->
   [ ] U-Boot   			//不能选择该选项

6》配置目标包
 Target packages  --->
  System tools  --->
     [*] kmod  					//使能内核模块相关命令
  Libraries  ---> 
     Graphics  ---> 
       [*] libdrm  --->
        [*]   Install test programs
  Networking applications  --->
    [*] openssh          //使能openssh
          
 
sudo make busybox-menuconfig
 Linux Module Utilities  --->
   [*] depmod (27 kb)     //使能depmod

4. 编译buildroot

bash 复制代码
sudo make 

//生成文件:ls output/images/
rootfs.ext2  rootfs.ext4  rootfs.tar

//在/opt中创建根文件系统目录rootfs,将生成的根文件系统解包到:myrootfs
mkdir /opt/myrootfs
tar -xvf output/images/rootfs.tar -C /opt/myrootfs

Buildroot 根文件系统制作:

官方最新版本对比: 根据 Buildroot 官方下载页(https://buildroot.org/download.html):

发布线 当前版本 发布日期 状态
2025.11.x 2025.11-rc2 2025-11-20 最新 RC(预期 2026 年 3 月成为稳定版)
2025.08.x 2025.08.2 2025-11-20 稳定 LTS 替换(维护到 2025 年 12 月)
2025.02.x 2025.02.8 2025-11-20 长期维护版(LTS,支持到 2028 年 3 月)

此处使用的 buildroot-2021.02.1 较老,若无兼容性限制,你也可以升级到 2025.02.x LTS,可获得新包 与 安全维护。下载链接可从页面提供的 .tar.gz / .tar.xz 获取,对应 PGP 签名亦可校验。


工具链与配置建议:

  • source /opt/sdk/... 是 ST 官方 SDK 的环境;若升级 Buildroot,需确认交叉链与 External toolchain 版本号匹配。kernel headersgcc version 应与交叉链实际匹配。
  • Toolchain prefix 中可使用 $(ARCH)-fsmp1x-linux-gnueabihf,但需确认 ARCH 在环境变量中正确(多数情况下 ARCH=arm,也可以直接写 arm-fsmp1x-linux-gnueabihf,避免变量为空)。
  • Filesystem images
    • 若 NFS 开发,rootfs.tar 足够;若需要烧写 eMMC/SD 卡,可保留 rootfs.ext4 或使用 tar + mkfs.ext4 自行生成。
    • exact size (1G) 会生成固定大小镜像;如果后期需要压缩或缩小镜像,可以改用 Auto 或脚本后处理。

四. 在开发板中测试新创建的文件系统

1. 将文件系统路径配置到nfs中

bash 复制代码
1》打开nfs配置文件
	sudo vim /etc/exports
2》在文件末尾添加下面一行
	/opt/myrootfs    *(rw,sync,no_root_squash,no_subtree_check)
3》重启nfs服务
	sudo /etc/init.d/nfs-kernel-server restart

2. 修改uboot参数

bash 复制代码
重启开发板,进入uboot命令行
STM32MP> setenv bootargs root=/dev/nfs nfsroot=192.168.30.5:/opt/myrootfs ip=192.168.60.7 rootwait rw earlyprintk console=ttySTM0,115200 init=/linuxrc
STM32MP> saveenv
重启开发板,观察结果:
[    6.479696]      bootserver=255.255.255.255, rootserver=192.168.30.5, rootpath=
[    6.488237] ALSA device list:
[    6.489890]   #0: STM32MP1-FSMP1A
[    6.557474] VFS: Mounted root (nfs filesystem) on device 0:17.
[    6.562685] devtmpfs: mounted
[    6.567262] Freeing unused kernel memory: 1024K
[    6.606957] Run /linuxrc as init process
Starting syslogd: OK
Starting klogd: OK
Running sysctl: OK
Saving random seed: OK
Starting network: ip: RTNETLINK answers: File exists
FAIL
ssh-keygen: generating new host keys: RSA DSA ECDSA ED25519
Starting sshd: /var/empty must be owned by root and not group or world-writable.
OK

Welcome to Haha
HQYJ login: root
Password:
# ls
# ls /
bin      lib      media    proc     sbin     usr
dev      lib32    mnt      root     sys      var
etc      linuxrc  opt      run      tmp

3. 取消rootfs登录账号和密码

bash 复制代码
1》打开文件系统myrootfs中的配置文件etc/inittab
	vim /opt/myrootfs/etc/inittab
2》修改下面一行	
	注释下面一行:
	#console::respawn:/sbin/getty -L  console 0 vt100 # GENERIC_SERIAL
	添加下面一行:
	console::respawn:-/bin/sh
3》重启开发板,观察:、
[    7.554619] VFS: Mounted root (nfs filesystem) on device 0:17.
[    7.560099] devtmpfs: mounted
[    7.564284] Freeing unused kernel memory: 1024K
[    7.606728] Run /linuxrc as init process
Starting syslogd: OK
Starting klogd: OK
Running sysctl: OK
Initializing random number generator: OK
Saving random seed: OK
Starting network: ip: RTNETLINK answers: File exists
FAIL
Starting sshd: /var/empty must be owned by root and not group or world-writable.
OK
#
#
#
# ls
bin      lib      media    proc     sbin     usr
dev      lib32    mnt      root     sys      var
etc      linuxrc  opt      run      tmp

4. 设置用户名和主机名

bash 复制代码
1》打开文件系统myrootfs中的配置文件etc/profile
	
2》在文件末尾添加下面内容:
	export HOSTNAME=HQYJ         //主机名
    export USER=root				//用户名
    export HOME=root				//用户家目录名
    export PS1="[$USER@$HOSTNAME \w]\# "    //命令提示符格式
    PATH=/bin:/sbin:/usr/bin:/usr/sbin
    LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
    export PATH  LD_LIBRARY_PATH
3》重启开发板,观察:
[    6.516506] devtmpfs: mounted
[    6.520478] Freeing unused kernel memory: 1024K
[    6.566750] Run /linuxrc as init process
Starting syslogd: OK
Starting klogd: OK
Running sysctl: OK
Initializing random number generator: OK
Saving random seed: OK
Starting network: ip: RTNETLINK answers: File exists
FAIL
Starting sshd: /var/empty must be owned by root and not group or world-writable.
OK
[root@HQYJ /]#
[root@HQYJ /]#

以上,欢迎有从事同行业的电子信息工程、互联网通信、嵌入式开发的朋友共同探讨与提问,我可以提供实战演示或模板库。希望内容能够对你产生帮助!

相关推荐
fruge2 小时前
SIMD 编程实践:在 openEuler 上 x86 AVX 与 ARM Neon 性能探索
arm开发
chalmers_152 小时前
require 根据工程目录的相对路径-require新文件实现简单的热更新
linux·前端·javascript
天向上2 小时前
ubuntu系统adb shell报错 ADB server didn‘t ACK
android·linux·ubuntu·adb
智算菩萨2 小时前
深度剖析U盘启动WINPE技术体系:从底层原理到企业级应用实践
arm开发·系统安全·系统维护
阿猿收手吧!2 小时前
【Linux】Ubuntu配置开发环境合集
linux·ubuntu·bootstrap
某林2122 小时前
STM32 底层固件架构与驱动设计
stm32·单片机·嵌入式硬件
某林2122 小时前
集成式人机交互与底层驱动系统设计说明书
人工智能·stm32·嵌入式硬件·算法·机器学习·人机交互
Forest_HAHA2 小时前
<14>_Linux高级IO
linux·服务器
python百炼成钢2 小时前
解决——linux通过网络挂载tftp无法下载
linux·运维·网络