系统移植-STM32MP1_Linux内核移植

张开发
2026/4/5 21:47:09 15 分钟阅读

分享文章

系统移植-STM32MP1_Linux内核移植
文章目录1 说明及源码获取1.1 源码获取1.2 安装依赖包1.3 Linux内核源码打补丁1.4 生成默认配置文件1.5 修改编译配置2 注意事项3 Linux内核移植3.1 创建默认配置设备树3.2 修改设备树Makefile配置项3.3 网络驱动修改3.3.1 驱动源文件替换3.3.2 Makefile文件修改3.3.3 Kconfig文件修改3.3.4 使能YT8511网络驱动3.4 更新stm32mp157d-da.dtsi文件3.4.1 删除3.4.2 添加3.4.3 修改3.4.4 stm32mp157d-da.dtsi文件最终内容3.5 关闭内核模块验证3.6 关闭内核log信息时间戳4 备份.config文件5 编译及烧录5.1 编译5.2 网络加载5.2.1 准备加载文件5.2.2 Linux内核运行5.2.3 uboot设置linux内核网络加载5.3 EMMC加载5.3.1.1 bootfs.ext4文件制作5.3.1.2 Linux内核烧录5.3.1.2.1 文件准备5.3.1.2.2 使用USB烧写bootfs.ext45.3.1.3 Linux内核运行5.3.1.4 uboot设置Linux内核从EMMC启动6 Linux内核移植结果验证7 根文件系统缺失Linux内核移植教程资源1 说明及源码获取1.1 源码获取使用正点原子提供的en.SOURCES-stm32mp1-openstlinux-5-4-dunfell-mp1-20-06-24.tar.xz。使用如下命令解压文件tar-xvfen.SOURCES-stm32mp1-openstlinux-5-4-dunfell-mp1-20-06-24.tar.xz目录下包含了如下文件夹文件夹描述linux-stm32mp-5.4.31-r0linux源码版本号为5.4.31optee-os-stm32mp-3.9.0.r1-r0optee系统源码版本为3.9.0tf-a-stm32mp-2.2.r1-r0tf-a源码版本号为2.2tf-a-stm32mp-ssp-2.2.r1-r0tf-a源码ssp全称为secure secert provisioning安全相关的内容u-boot-stm32mp-2020.01-r0uboot源码版本号为2020.01linux内核使用linux-stm32mp-5.4.31-r0文件夹内容。1.2 安装依赖包sudoaptupdatesudoaptinstalllzopsudoaptinstalllibssl-devsudoaptinstallu-boot-toolsSTM32MP1编译出来的Linux内核镜像文件为uImage这是uboot所使用的内核镜像格式通过在zImage镜像的前面添加0X40个字节的头部来得到uImage这个需要mkimage工具来完成此工作。使用sudo apt install u-boot-tools命令在Ubuntu下安装mkimage工具。1.3 Linux内核源码打补丁将linux-stm32mp-5.4.31-r0文件夹内容重新拷贝到一个新的文件夹中例如/home/alientek/linux/da-mp1/da/kernel在新的文件夹中使用如下命令打补丁# 在 /home/alientek/linux/da-mp1/da/kernel 文件夹下打开一个终端执行如下命令tar-vxflinux-5.4.31.tar.xzcdlinux-5.4.31/forpinls-1../*.patch;dopatch-p1$p;done# 打补丁1.4 生成默认配置文件编译linux内核的时候也需要使用make xxx_defconfig来对其进行默认配置ST官方原厂Linux内核需要先生成默认配置文件并且对其进行打补丁命令如下cdlinux-5.4.31/makeARCHarm multi_v7_defconfigfragment*.config# 生成默认配置文件# 如下两条命令将 fragment config补丁文件打入 .config 文件中forfinls-1../fragment*.config;doscripts/kconfig/merge_config.sh-m-r.config$f;doneyes|makeARCHarm oldconfig# 命令中的 为两个 经过上述命令生成了默认的.config文件。建议在自行调整了kernel的配置参数后将新的配置文件.config拷贝一份到./arch/arm/configs/xxx_defconfig避免执行make distclean将新配置文件.config删除。使用以下命令备份.config文件cdlinux-5.4.31/cp.config ./arch/arm/configs/stm32mp1_da_defconfig1.5 修改编译配置主要修改Makefile文件添加ARCH变量添加CROSS_COMPILE变量。在linux-5.4.31/Makefile中修改在文件的第361行添加如下代码ARCH arm CROSS_COMPILE arm-none-linux-gnueabihf-添加前内容添加后内容2 注意事项内核移植涉及修改内容较多为避免最后结果不符合预期建议可以在有效修改后分步骤编译运行查看结果可以提高最后结果的正确性。3 Linux内核移植3.1 创建默认配置设备树cdlinux-5.4.31/cdarch/arm/boot/dts/cpstm32mp15xx-edx.dtsi stm32mp157d-da.dtsicpstm32mp157d-ed1.dts stm32mp157d-da.dts打开stm32mp157d-da.dts文件修改如下内容修改#include stm32mp15xx-edx.dtsi头文件引用为#include stm32mp157d-da.dtsi修改/节点下的compatible属性值为st,stm32mp157d-da, st,stm32mp157。打开stm32mp157d-da.dtsi文件修改如下内容添加#include stm32mp157-m4-srm.dtsi头文件引用添加#include stm32mp157-m4-srm-pinctrl.dtsi头文件引用3.2 修改设备树Makefile配置项修改arch/arm/boot/dts/Makefile修改内容如下在dtb-$(CONFIG_ARCH_STM32)配置项中添加stm32mp157d-da.dtb。修改后内容如下dtb-$(CONFIG_ARCH_STM32) \ stm32f429-disco.dtb \ stm32f469-disco.dtb \ stm32f746-disco.dtb \ stm32f769-disco.dtb \ stm32429i-eval.dtb \ stm32746g-eval.dtb \ stm32h743i-eval.dtb \ stm32h743i-disco.dtb \ stm32mp157a-avenger96.dtb \ stm32mp157a-dk1.dtb \ stm32mp157d-dk1.dtb \ stm32mp157c-dk2.dtb \ stm32mp157f-dk2.dtb \ stm32mp157c-dk2-a7-examples.dtb \ stm32mp157c-dk2-m4-examples.dtb \ stm32mp157f-dk2-a7-examples.dtb \ stm32mp157f-dk2-m4-examples.dtb \ stm32mp157a-ed1.dtb \ stm32mp157c-ed1.dtb \ stm32mp157d-ed1.dtb \ stm32mp157f-ed1.dtb \ stm32mp157a-ev1.dtb \ stm32mp157c-ev1.dtb \ stm32mp157d-ev1.dtb \ stm32mp157f-ev1.dtb \ stm32mp157c-ev1-a7-examples.dtb \ stm32mp157c-ev1-m4-examples.dtb \ stm32mp157f-ev1-a7-examples.dtb \ stm32mp157f-ev1-m4-examples.dtb \ stm32mp157d-da.dtb3.3 网络驱动修改3.3.1 驱动源文件替换正点原子V1.3及以后版本的核心板开始将网络PHY芯片更换为了国产裕太电子的YT8511所以需要修改一下驱动。使用提供的资源目录/yt8511/motorcomm.c拷贝到linux-5.4.31/drivers/net/phy/文件夹中使用提供的资源目录/yt8511/motorcomm_phy.h拷贝到linux-5.4.31/include/linux/文件夹中。3.3.2 Makefile文件修改打开linux-5.4.31/drivers/net/phy/Makefile文件修改内容如下添加obj-$(CONFIG_MOTORCOMM_PHY) motorcomm.o到文件中修改后文件内容如下3.3.3 Kconfig文件修改打开linux-5.4.31/drivers/net/phy/Kconfig文件修改内容如下添加下面内容到文件中config MOTORCOMM_PHY tristate Motorcomm PHYs ---help--- Supports the YT8010, YT8510, YT8511, YT8512 PHYs.修改后文件内容如下3.3.4 使能YT8511网络驱动cdlinux-5.4.31/makemenuconfig按照下图修改修改完成之后退出保存。并执行如下命令保存最新配置到arch/arm/configs/stm32mp1_da_defconfig文件cdlinux-5.4.31/cp.config ./arch/arm/configs/stm32mp1_da_defconfig3.4 更新stm32mp157d-da.dtsi文件3.4.1 删除打开stm32mp157d-da.dtsi文件删除如下内容删除/节点下的sd_switch节点、vin节点和led节点删除dac节点删除adc节点删除i2c4节点;删除m4_rproc节点删除pwr_regulators节点删除timers6节点删除usbotg_hs节点删除usbphyc_port0节点删除usbphyc_port1节点。3.4.2 添加打开stm32mp157d-da.dtsi文件添加如下内容在/下添加vddcore节点和v3v3节点添加ethernet0节点。3.4.3 修改打开stm32mp157d-da.dtsi文件修改如下内容修改sdmmc1节点修改sdmmc2节点。3.4.4 stm32mp157d-da.dtsi文件最终内容// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) /* * Copyright (C) STMicroelectronics 2017 - All Rights Reserved * Author: Ludovic Barre ludovic.barrest.com for STMicroelectronics. */ #include stm32mp157-m4-srm.dtsi #include stm32mp157-m4-srm-pinctrl.dtsi #include dt-bindings/gpio/gpio.h #include dt-bindings/mfd/st,stpmic1.h / { memoryc0000000 { device_type memory; reg 0xC0000000 0x40000000; }; reserved-memory { #address-cells 1; #size-cells 1; ranges; mcuram2: mcuram210000000 { compatible shared-dma-pool; reg 0x10000000 0x40000; no-map; }; vdev0vring0: vdev0vring010040000 { compatible shared-dma-pool; reg 0x10040000 0x1000; no-map; }; vdev0vring1: vdev0vring110041000 { compatible shared-dma-pool; reg 0x10041000 0x1000; no-map; }; vdev0buffer: vdev0buffer10042000 { compatible shared-dma-pool; reg 0x10042000 0x4000; no-map; }; mcuram: mcuram30000000 { compatible shared-dma-pool; reg 0x30000000 0x40000; no-map; }; retram: retram38000000 { compatible shared-dma-pool; reg 0x38000000 0x10000; no-map; }; }; vddcore: buck1 { compatible regulator-fixed; regulator-name vddcore; regulator-min-microvolt 1200000; regulator-max-microvolt 1350000; regulator-always-on; regulator-boot-on; }; v3v3: regulator-3p3v { compatible regulator-fixed; regulator-name v3v3; regulator-min-microvolt 3300000; regulator-max-microvolt 3300000; regulator-always-on; regulator-boot-on; }; }; cpu0{ cpu-supply vddcore; }; crc1 { status okay; }; dma1 { sram dma_pool; }; dma2 { sram dma_pool; }; dts { status okay; }; ethernet0 { status okay; pinctrl-0 ethernet0_rgmii_pins_a; pinctrl-1 ethernet0_rgmii_pins_sleep_a; pinctrl-names default, sleep; phy-mode rgmii-id; max-speed 1000; phy-handle phy0; mdio0 { #address-cells 1; #size-cells 0; compatible snps,dwmac-mdio; phy0: ethernet-phy0 { reg 0; }; }; }; hash1 { status okay; }; ipcc { status okay; }; iwdg2 { timeout-sec 32; status okay; }; rng1 { status okay; }; rtc { status okay; }; sdmmc1 { pinctrl-names default, opendrain, sleep; pinctrl-0 sdmmc1_b4_pins_a; pinctrl-1 sdmmc1_b4_od_pins_a; pinctrl-2 sdmmc1_b4_sleep_pins_a; broken-cd; st,neg-edge; bus-width 4; vmmc-supply v3v3; status okay; }; sdmmc2 { pinctrl-names default, opendrain, sleep; pinctrl-0 sdmmc2_b4_pins_a; pinctrl-1 sdmmc2_b4_od_pins_a; pinctrl-2 sdmmc2_b4_sleep_pins_a; non-removable; st,neg-edge; bus-width 8; vmmc-supply v3v3; keep-power-in-suspend; status okay; }; sram { dma_pool: dma_pool0 { reg 0x50000 0x10000; pool; }; }; uart4 { pinctrl-names default, sleep, idle; pinctrl-0 uart4_pins_a; pinctrl-1 uart4_sleep_pins_a; pinctrl-2 uart4_idle_pins_a; pinctrl-3 uart4_pins_a; /delete-property/dmas; /delete-property/dma-names; status okay; };3.5 关闭内核模块验证Linux驱动的时候都是编译驱动模块然后在系统里面加载加载的时候系统会验证模块有时候会验证出错。比如板子运行的系统和编译驱动模块所用的系统不一致的时候。为了方便开发我们可以关闭内核模块验证。cdlinux-5.4.31/makemenuconfig按照下图修改修改完成之后退出保存。并执行如下命令保存最新配置到arch/arm/configs/stm32mp1_da_defconfig文件cdlinux-5.4.31/cp.config ./arch/arm/configs/stm32mp1_da_defconfig3.6 关闭内核log信息时间戳cdlinux-5.4.31/makemenuconfig按照下图修改修改完成之后退出保存。并执行如下命令保存最新配置到arch/arm/configs/stm32mp1_da_defconfig文件cdlinux-5.4.31/cp.config ./arch/arm/configs/stm32mp1_da_defconfig4 备份.config文件针对有效修改Linux内核配置项后使用以下命令备份cdlinux-5.4.31/cp.config ./arch/arm/configs/stm32mp1_da_defconfig这样做的目的就是为了防止在make distclen时将配置文件删除也可以使用如下命令加载配置cdlinux-5.4.31/makestm32mp1_da_defconfig5 编译及烧录5.1 编译使用如下命令编译cdlinux-5.4.31/makeuImage dtbsLOADADDR0XC2000040-j8# 可单独编译设备树 或者 内核镜像makedtbs-j8# 单独编译设备树makeuImageLOADADDR0XC2000040-j8# 单独编译内核镜像编译成功后会在linux-5.4.31/arch/arm/boot/目录下生成uImage内核镜像文件在linux-5.4.31/arch/arm/boot/dts目录下生成stm32mp157d-da.dtb文件。Linux内核加载有两种方式网络加载EMMC加载。5.2 网络加载5.2.1 准备加载文件将编译生成的uImage和stm32mp157d-da.dtb文件拷贝到tftp服务端设置的文件夹中笔者的tftp服务根目录为/home/alientek/linux/tftpboot/可以使用如下命令拷贝文件cdlinux-5.4.31/cp./arch/arm/boot/uImage ./arch/arm/boot/dts/stm32mp157d-da.dtb /home/alientek/linux/tftpboot/5.2.2 Linux内核运行打开MobaXterm软件设置好与开发板连接的串口波特率选择115200。设置开发板拨码开关为010也就是从EMMC启动然后复位开发板在串口中观察启动过程。5.2.3 uboot设置linux内核网络加载在系统启动的uboot阶段进入uboot命令行可以通过如下命令进行Linux内核网络加载(每次都需要进入uboot执行命令)tftp c2000000 uImage tftp c4000000 stm32mp157d-da.dtb bootm c2000000 - c4000000也可以将上述命令设置到bootcmd环境变量中只设置一次就可以setenv bootcmdtftp c2000000 uImage;tftp c4000000 stm32mp157d-da.dtb;bootm c2000000 - c4000000saveenv boot5.3 EMMC加载5.3.1.1 bootfs.ext4文件制作# 第一步在家目录中选择合适位置创建 bootfs 文件夹并进入mkdirbootfscdbootfs# 第二步将生成的 uImage 和 stm32mp157d-da.dtb 文件拷贝到 bootfs 文件夹目录中# 第三步新建 ext4 格式磁盘# of为名称bs为块大小count为块数量所以 bootfs.ext4 文件大小为10MB,如果空间不够则调整 countddif/dev/zeroofbootfs.ext4bs1Mcount10# -L bootfs 为卷名使用 mkfs.ext4 将 bootfs.ext4 文件格式化为 ext4 格式且指定卷名为 bootfsmkfs.ext4-Lbootfs bootfs.ext4# 第四步将系统镜像拷贝到 ext4 磁盘中sudomkdir/mnt/bootfssudomountbootfs.ext4 /mnt/bootfs/sudocpuImage stm32mp157d-da.dtb /mnt/bootfs/# 第五步卸载 /mnt/bootfssudoumount/mnt/bootfs将生成的bootfs.ext4文件拷贝到win系统中便于后续烧录。5.3.1.2 Linux内核烧录5.3.1.2.1 文件准备将制作好的的bootfs.ext4、tf-a-stm32mp157d-da-trusted.stm32和tf-a-stm32mp157d-da-serialboot.stm32、u-boot.stm32文件其中u-boot.stm32、tf-a-stm32mp157d-da-trusted.stm32和tf-a-stm32mp157d-da-serialboot.stm32使用已经编译好的统一放入文件夹中例如da-images文件夹。在da-images文件夹中添加da.tsv文件文件内容如下所示#Opt Id Name Type Device Offset Binary - 0x01 fsbl1-boot Binary none 0x0 tf-a-stm32mp157d-da-serialboot.stm32 - 0x03 ssbl-boot Binary none 0x0 u-boot.stm32 P 0x04 fsbl1 Binary mmc1 boot1 tf-a-stm32mp157d-da-trusted.stm32 P 0x05 fsbl2 Binary mmc1 boot2 tf-a-stm32mp157d-da-trusted.stm32 P 0x06 ssbl Binary mmc1 0x00080000 u-boot.stm32 P 0x21 boot System mmc1 0x00280000 bootfs.ext4文件内容格式要严格遵循下图tsv语法要求只能用TAB键不能用空格以#开头为注释。最终da-images文件夹中的内容如下使用STM32CubeProgrammer采用USB的方式烧写至开发板中也就是USB_OTG口来烧写系统。5.3.1.2.2 使用USB烧写bootfs.ext4通过USBType-C线将开发板的USB_OTG和USB_TTL连接到电脑上。设置开发板拨码开关设置为000也就是从USB启动然后复位开发板。打开STM32CubeProgrammer选择USB连接方式Port选择USB1。USB设置好以后点击右上角的“Connect”来连接开发板连接成功以后左下角的log区域就会输出一些信息右侧中间的数据区域也会显示开发板默认的分区情况右下角会显示目标板信息如图所示STM32CubeProgrammer要使用FlashLayout文件来烧写系统也就是da-images文件夹下的da.tsv。点击界面上的Open File打开da.tsv如下图所示烧写完成后会有如下提示5.3.1.3 Linux内核运行打开MobaXterm软件设置好与开发板连接的串口波特率选择115200。设置开发板拨码开关为010也就是从EMMC启动然后复位开发板在串口中观察启动过程。5.3.1.4 uboot设置Linux内核从EMMC启动setenv bootcmdext4load mmc 1:2 c2000000 uImage;ext4load mmc 1:2 c4000000 stm32mp157d-da.dtb;bootm c2000000 - c4000000saveenv boot6 Linux内核移植结果验证下面图片有内核的时间信息。7 根文件系统缺失---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,19) ]---内核崩溃崩溃原因是VFS(虚拟文件系统)不能挂载根文件系统。在Linux内核启动后是正常的因为还没有设置根文件系统。

更多文章