STM32MP157A之Linux内核与根文件系统

(一)Linux内核移植步骤

Linux 内核源代码非常庞大,随着版本的发展不断增加。它使用目录树结构,并且使用Makefile 组织配置编译

3.1》导入源码

1)打开系统源码,进入linux的源码目录下,该目录下以 patch 结尾的文件为 ST 官方提供的补丁文件;linux-5.4.31.tar.xz为标准linux源码包。
/home/linux/fs_mp157a/kernel/stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24/sources/arm-ostl-linux-gnueabi/linux-stm32mp-5.4.31-r0
在这里插入图片描述
2)解压linux内核源码,并且进入解压后的源码目录下
tar -xvf linux-5.4.31.tar.xz
cd linux-5.4.31/
(********注意:接下来所有的操作都将在此目录下,不要走错了地方。)

3.2》添加 STMicroelectronics 官方补丁

1)解压 linux 内核源码后得到的是 Linux 社区的标准内核源码,接下来需要将 ST 官方提供的源码补丁添加到标准内核中。
for p in ls -1 ../*.patch; do patch -p1 < $p; done

3.3》生成标准板配置文件

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 /* echo命令的功能是写内容到标准输出。SHA1—哈希算法功能 */

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

3.4》生成设备树文件

1)以参考板 DK1 设备树文件 stm32mp15xx-dkx.dtsi 和 stm32mp157a-dk1.dts 为参考,增加 stm32mp15xx-fsmp1x.dtsi 和 stm32mp157a-fsmp1a.dts:
在 arch/arm/boot/dts/ 目录下新建 stm32mp15xx-fsmp1x.dtsi:
vim arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi
增加以下内容:
#include “stm32mp157-m4-srm.dtsi”
#include “stm32mp157-m4-srm-pinctrl.dtsi”
#include <dt-bindings/mfd/st,stpmic1.h>

/ {
memory@c0000000 {
device_type = “memory”;
reg = <0xc0000000 0x20000000>;
};

reserved-memory {
 #address-cells = <1>;
 #size-cells = <1>;
 ranges;

 mcuram2: mcuram2@10000000 {
 compatible = "shared-dma-pool";
 reg = <0x10000000 0x40000>;
 no-map;
 };

 vdev0vring0: vdev0vring0@10040000 {
 compatible = "shared-dma-pool";
 reg = <0x10040000 0x1000>;
 no-map;
 };

 vdev0vring1: vdev0vring1@10041000 {
 compatible = "shared-dma-pool";
 reg = <0x10041000 0x1000>;
 no-map;
 };

 vdev0buffer: vdev0buffer@10042000 {
 compatible = "shared-dma-pool";
 reg = <0x10042000 0x4000>;
 no-map;
 };
 mcuram: mcuram@30000000 {
 compatible = "shared-dma-pool";
 reg = <0x30000000 0x40000>;
 no-map;
 };

 retram: retram@38000000 {
 compatible = "shared-dma-pool";
 reg = <0x38000000 0x10000>;
 no-map;
 };

};
vin: vin {
compatible = “regulator-fixed”;
regulator-name = “vin”;
regulator-min-microvolt = <5000000>;
regulator-max-microvolt = <5000000>;
regulator-always-on;
};
v3v3: regulator-3p3v {
compatible = “regulator-fixed”;
regulator-name = “v3v3”;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
vdd: regulator-vdd {
compatible = “regulator-fixed”;
regulator-name = “vdd”;
regulator-min-microvolt = <3300000>;
regulator-max-microvolt = <3300000>;
regulator-always-on;
regulator-boot-on;
};
};
/HDMI CEC 控制器/
&cec {
pinctrl-names = “default”, “sleep”;
pinctrl-0 = <&cec_pins_b>;
pinctrl-1 = <&cec_pins_sleep_b>;
status = “okay”;
};
/循环冗余校验计算单元/
&crc1 {
status = “okay”;
};
&dma1 {
sram = <&dma_pool>;
};
&dma2 {
sram = <&dma_pool>;
};
/数字钟温度传感器/
&dts {
status = “okay”;
};
/图像处理单元/
&gpu {
contiguous-area = <&gpu_reserved>;
status = “okay”;
};
/哈希处理器/
&hash1 {
status = “okay”;
};
/处理器间通信控制器/
&ipcc {
status = “okay”;
};
/看门狗/
&iwdg2 {
timeout-sec = <32>;
status = “okay”;
};
/随机数发生器/
&rng1 {
status = “okay”;
};
/实时时钟/
&rtc {
status = “okay”;
};
/sdmmc1 TF 卡/
&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>;
cd-gpios = <&gpioh 3 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;
disable-wp;
st,neg-edge;
bus-width = <4>;
vmmc-supply = <&v3v3>;
status = “okay”;
};

&sram {
dma_pool: dma_pool@0 {
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”;
};
/电源基准缓冲器/
&vrefbuf {
regulator-min-microvolt = <2500000>;
regulator-max-microvolt = <2500000>;
vdda-supply = <&vdd>;
status = “okay”;
};
2)在 arch/arm/boot/dts/ 目录下新建 stm32mp157a-fsmp1a.dts:
vim arch/arm/boot/dts/stm32mp157a-fsmp1a.dts
增加以下内容:
/dts-v1/;
#include “stm32mp157.dtsi”
#include “stm32mp15xa.dtsi”
#include “stm32mp15-pinctrl.dtsi”
#include “stm32mp15xxaa-pinctrl.dtsi”
#include “stm32mp15xx-fsmp1x.dtsi”
/ {
model = “HQYJ STM32MP157 FSMP1A Discovery Board”;
compatible = “st,stm32mp157a-dk1”, “st,stm32mp157”;
aliases {
serial0 = &uart4;
};
chosen {
stdout-path = “serial0:115200n8”;
};
reserved-memory {
gpu_reserved: gpu@da000000 {
reg = <0xda000000 0x4000000>;
no-map;
};
optee_memory: optee@0xde000000 {
reg = <0xde000000 0x02000000>;
no-map;
};
};
};
&optee {
status = “okay”;
};
3)由于添加了新文件需修改 Makefile 才能编译,修改 arch/arm/boot/dts/Makefile,添加 stm32mp157a-fsmp1a.dts 的编译选项(红色字体部分为添加内容)
vim arch/arm/boot/dts/Makefile
4)在Makefile中增加红色内容
stm32mp157a-dk1.dtb \
stm32mp157a-fsmp1a.dtb \
stm32mp157d-dk1.dtb \

3.5》编译内核及设备树

1)导入交叉编译器
source /opt/st/stm32mp1/3.1-openstlinux-5.4-dunfell-mp1-20-06-24/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi

2)编译内核及设备树
make -j4 uImage dtbs LOADADDR=0xC2000040
在这里插入图片描述

内核文件在arch/arm/boot/ 目录下
设备树文件在arch/arm/boot/ dts 目录下
在这里插入图片描述

3)编译内核模块-----这一步暂时可以不做,时间太久了,暂时还不会使用模块,等需要再编译
make ARCH=arm modules
该操作会将内核中配置为模块的源码进行编译,最终得到 ko 文件。
在这里插入图片描述

4)将编译好的设备树文件与内核的 uImage文件,复制到 ubuntu 主机的/tftpboot 文件夹下,
当使用 tftp 方式下载内核与设备树文件时会用到。
cp arch/arm/boot/uImage /tftpboot/
cp arch/arm/boot/dts/stm32mp157a-fsmp1a.dtb /tftpboot/

3.6》通过TFTP下载内核

在 linux 系统移植中,我们使用 tftp 下载的方式来验证结果。为什么使用TFTP下载内核?因为Linux系统非常庞大,如果直接去构建系统,可能需要5个小时的时间,而在开发阶段,我们通常使用TFTP下载的方式,因为内核配置经常需要更改,不可能改一下,去构建一次系统。所以用TFTP下载内核。
使用 tftp 下载需要构建 pxelinux 相关的目录。
1)需要将 ubuntu 主机中的/tftpboot/pxelinux.cfg/01-00-80-e1-42-60-17 文件内容,暂时替换为如下内容,在后续的移植过程中会根据不同的需求进行修改。
sudo mkdir /tftpboot/pxelinux.cfg
sudo vim /tftpboot/pxelinux.cfg/01-00-80-e1-42-60-17
添加的内容如下:

Generic Distro Configuration file generated by OpenEmbedded

menu title Select the boot mode
TIMEOUT 20
DEFAULT stm32mp157a-fsmp1a-emmc
LABEL stm32mp157a-fsmp1a-emmc
KERNEL /uImage
FDT /stm32mp157a-fsmp1a.dtb
APPEND root=/dev/mmcblk1p4 rootwait rw console=ttySTM0,115200

2)打开开发板
下面这种方式:是电脑和开发板接同一个交换机的方式
在uboot中设置以下内容
env set -f ethaddr 00:80:E1:42:60:17 //这就是MAC
env set serverip 192.168.20.100 //Ubuntu的IP
env save //保存
下面这种方式:是电脑和开发板直连的方式(就是电脑的网口和开发板的网口用一根网线连接)
在uboot中设置以下内容
env set -f ethaddr 00:80:E1:42:60:17 //这就是MAC
env set serverip 192.168.20.100 //Ubuntu的IP
env set gatewayip 192.168.20.1 //网关
env set ipaddr 192.168.20.120 //给板子设置的IP
env save //保存
(注意如果使用直连方式,需要做以下步骤:
1)打开ubuntu,点击编辑------>虚拟网络编辑器
在这里插入图片描述

2)选择你的网卡,将网卡切换到ubuntu,让ubuntu使用你的网卡
在这里插入图片描述

3)将电脑和开发板之间的网线连接好

3)启动
静态IP启动或者电脑和开发板直连的方式
if pxe get; then pxe boot; fi
自动获取IP启动
run bootcmd_pxe
在这里插入图片描述

由于目前还未对源码进行任何修改,在内核启动过程中会停留在如下地方。

3.7》Linux 内核 eMMC 驱动移植

参考原理图可知 eMMC 使用的是 sdmmc2 总线,当前所使用的设备树文件中没有 sdmmc2 的支持,所以需要增加相关内容才能正常驱动 eMMC。
注意:还是在linux的内核源码下。
1)导入交叉编译器
source /opt/st/stm32mp1/3.1-openstlinux-5.4-dunfell-mp1-20-06-24/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
2)添加 eMMC 设备树配置,修改 arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi 文件
vim arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi
添加以下内容:
&sdmmc2 {
pinctrl-names = “default”, “opendrain”, “sleep”;
pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>;
pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_d47_pins_a>;
pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_d47_sleep_pins_a>;
non-removable;
no-sd;
no-sdio;
st,neg-edge;
bus-width = <8>;
vmmc-supply = <&v3v3>;
vqmmc-supply = <&vdd>;
mmc-ddr-3_3v;
status = “okay”;
};
3)配置内核,由于内核源码默认配置已经支持 eMMC,本节列出主要选项,如下
make menuconfig
Device Drivers —>
<> MMC/SD/SDIO card support —>
[
] STMicroelectronics STM32 SDMMC Controller
4)编译内核级设备树
make -j4 uImage dtbs LOADADDR=0xC2000040
5)将编译好的设备树文件与内核的 uImage文件,复制到 ubuntu 主机的/tftpboot 文件夹下, 当使用 tftp 方式下载内核与设备树文件时会用到。
cp arch/arm/boot/uImage /tftpboot/
cp arch/arm/boot/dts/stm32mp157a-fsmp1a.dtb /tftpboot/
6)重新启动开发板
在这里插入图片描述

3.8》Linux 内核网卡驱动移植

还是在linux的内核源码下。
1)导入交叉编译工具链
source /opt/st/stm32mp1/3.1-openstlinux-5.4-dunfell-mp1-20-06-24/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi
2)添加网卡设备树配置。
修改 arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi 文件
vim arch/arm/boot/dts/stm32mp15xx-fsmp1x.dtsi
在文件末尾添加如下内容:
&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-phy@0 {
reg = <0>;
};
};
};
3)编译内核及设备树
make -j16 uImage dtbs LOADADDR=0xC2000040

4)将编译好的设备树文件与内核的 uImage文件,复制到 ubuntu 主机的/tftpboot 文件夹下, 当使用 tftp 方式下载内核与设备树文件时会用到。
cp arch/arm/boot/uImage /tftpboot/
cp arch/arm/boot/dts/stm32mp157a-fsmp1a.dtb /tftpboot/
4)重新启动开发板
在这里插入图片描述

可以ping通主机就行,说明网络是通的。

(二)根文件系统的制作与挂载

4.1》配置制作文件系统的交叉编译工具链。

1)安装交叉编译器,自己的arm-none-linux-gnueabihf-
linux@ubuntu:$ sudo apt-get install gcc-arm-linux-gnueabihf
linux@ubuntu:$ sudo apt-get install g+±arm-linux-gnueabihf

2)验证开发工具是否安装正确,显示版本信息如下图所示
linux@ubuntu:$ arm-linux-gnueabihf-gcc -v
在这里插入图片描述

4.2》导入busybox源码

1)拷贝制作文件系统的工具源码:源码:E:\春\系统移植\系统移植工具\制作文件系统的源码\busybox-1.29.3.tar.bz2
拷贝到Ubuntu中的/home/linux/fs_mp157a/kernel/下
2)解压源码:busybox-1.29.3.tar.bz2 ,进入源码目录
tar -xvf busybox-1.29.3.tar.bz2
cd busybox-1.29.3
*******注意:后面的操作均在这个目录下。
3)配置 busybox 源码:
将顶层目录下的 Makefile 文件中的 CROSS_COMPILE 后增加 “arm-linux-gnueabihf-” ,后面不要有空格哟,否则编译有问题
vim Makefile
在这里插入图片描述

4)可以使用如下命令配置源码:
make menuconfig
必须执行,可以不改变任何内容,并且要保存,才会生成 .config的配置文件

4.3》创建文件系统

1)编译busybox源码
make
在这里插入图片描述

2)安装: busybox 默认安装路径为源码目录下的_install
make install
在这里插入图片描述

3)进入安装目录
cd _install
4)创建其他需要的目录
mkdir dev etc mnt proc var tmp sys root

5)添加库: 将工具链中的库拷贝到_install 目录下:看自己的交叉编译工具arm-none-linux-gnueabihf-
cp /usr/arm-linux-gnueabihf/lib/ . -a
6)删除静态库:
rm lib/*.a
7)添加系统启动文件: 在 etc 下添加文件 inittab,文件内容如下: 注意:修改文件均为_install 目录下
vim etc/inittab
增加以下内容:
#this is run first except when booting in single-user mode.
::sysinit:/etc/init.d/rcS

/bin/sh invocations on selected ttys

start an “askfirst” shell on the console (whatever that may be)

::askfirst:-/bin/sh

stuff to do when restarting the init process

::restart:/sbin/init

stuff to do before rebooting

::ctrlaltdel:/sbin/reboot

7)在 etc 下添加文件 fstab,文件内容如下:
vim etc/fstab
添加以下内容:
#device mount-point type options dump fsck order
proc /proc proc defaults 0 0
tmpfs /tmp tmpfs defaults 0 0
sysfs /sys sysfs defaults 0 0
tmpfs /dev tmpfs defaults 0 0
8)在 etc 下创建 init.d 目录,并在 init.d 下创建 rcS 文件,rcS 文件内容为:
mkdir etc/init.d
vim etc/init.d/rcS
添加以下内容:
#!/bin/sh

This is the first script called by init process

/bin/mount -a
/sbin/mdev -s
9)为 rcS 添加可执行权限:
chmod a+x etc/init.d/rcS
10)在 etc 下添加 profile 文件,文件内容为:
vim etc/profile
添加以下内容:
#!/bin/sh
export HOSTNAME=fsmp1a
export USER=root
export HOME=root
export PS1="[ U S E R @ USER@ USER@HOSTNAME \W]# "
PATH=/bin:/sbin:/usr/bin:/usr/sbin
LD_LIBRARY_PATH=/lib:/usr/lib:$LD_LIBRARY_PATH
export PATH LD_LIBRARY_PATH

4.3》测试------这里用NFS挂载的方式

1)删除原先的/opt/rootfs:
sudo rm -rf /opt/rootfs

2)将我们新建的根文件系统拷贝到/opt/rootfs 目录下
sudo mkdir /opt/rootfs
sudo cp ./* /opt/rootfs -a
3)修改 ubuntu 主机中的/tftpboot/pxelinux.cfg/01-00-80-e1-42-60-17 文件添加 nfs 启动选项
sudo vim /tftpboot/pxelinux.cfg/01-00-80-e1-42-60-17
替换成以下内容:nfsroot是ubantu的ip,开发板的ip
# Generic Distro Configuration file generated by OpenEmbedded
menu title Select the boot mode
MENU BACKGROUND /splash.bmp
TIMEOUT 20
DEFAULT stm32mp157a-fsmp1a-emmc
LABEL stm32mp157a-fsmp1a-emmc
KERNEL /uImage
FDT /stm32mp157a-fsmp1a.dtb
APPEND root=/dev/mmcblk1p4 rootwait rw console=ttySTM0,115200

	LABEL stm32mp157a-fsmp1a-nfs
	 KERNEL /uImage
	 FDT /stm32mp157a-fsmp1a.dtb
	 APPEND root=/dev/nfs nfsroot=192.168.20.100:/opt/rootfs ip=192.168.20.120 rootwait rw earlyprintk console=ttySTM0,115200

4)打开开发板
静态IP启动或者电脑和开发板直连的方式
if pxe get; then pxe boot; fi
回车输入启动指令 run bootcmd_pxe
在这里插入图片描述

选择nfs挂载方式启动 输入2
在这里插入图片描述

可以用ls查看一下是否进入开发板成功
在这里插入图片描述

注意:

在这里插入图片描述
如果出现这个错误,说明根文件系统制作有问题,重新操作一遍。就可以进来了。博主也在这卡了很久,一直以为自己做的没有问题,在别人的电脑上能进去,自己的电脑上就卡死在这了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值