6.4 U-boot 移植

news2024/11/26 2:55:46

一、ST 官方 U-boot 编译测试

1. ST 官方 uboot 源码打补丁

1.1 获得 ST 官方的 uboot 源码

https://www.cnblogs.com/toutiegongzhu/p/17578847.html 这里可以看如何下载uboot源码。解压完后输入以下命令:

cd stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24/sources/arm-ostl-linux-gnueabi/u-boot-stm32mp-2020.01-r0/

解压 u-boot-stm32mp-2020.01-r0.tar.gz ,命令如下:

tar -vxf u-boot-stm32mp-2020.01-r0.tar.gz

1.2 打补丁

输入以下命令:

cd u-boot-stm32mp-2020.01/     //进入 uboot 源码目录
for p in `ls -1 ../*.patch`;do patch -p1 < $p;done     //打补丁

# 解释一下打补丁这行代码。
ls -1 ../*.patch:使用 ls 命令列出指定目录上层目录中所有以 .patch 结尾的文件,并使用 -1 参数确保每个文件名只占一行。
for p in ...; do ...; done:对第一步列出的每个补丁文件执行循环操作。
patch -p1 < $p:对当前循环遍历到的补丁文件应用 patch 命令。-p1 参数用于在应用补丁之前去除文件路径中的前缀目录层级,保持与当前目录下的源码结构一致。< $p 用于将补丁文件作为输入传递给 patch 命令。
# 所以这行代码的作用是:循环遍历所有补丁文件,并依次应用到当前目录下的源码中

创建 my_uboot 来保存移植的uboot源码,输入以下命令:

cd ~
cd linux/atk-mpl/uboot/
mkdir my_uboot      
cd ~
cd linux/atk-mpl/stm32mp1-openstlinux-5.4-dunfell-mp1-20-06-24/sources/arm-ostl-linux-gnueabi/u-boot-stm32mp-2020.01-r0/u-boot-stm32mp-2020.01/
cp * /home/alientek/linux/atk-mpl/uboot/my_uboot/ -rf    
# * 代表通配符,表示匹配当前目录下的所有文件
# -r:递归复制子目录
# -f:强制覆盖已存在的文件

2.  编译 ST 官方 uboot 源码

2.1 修改Makefile

打开Makefile文件,增加以下代码:

  uboot的移植就是: 编译 EVK 开发板对应的 uboot,编译完成以后将得到的 uboot 可执行文件烧写到正点原子的 STM32MP1 开发板中,看看能不能运行,不能的话就要修改 uboot 相应的文件。命令如下:

make stm32mp15_trusted_defconfig        # 使用 make 工具来生成一个名为 stm32mp15_trusted_defconfig 的配置文件
make DEVICE_TREE=stm32mp157d-ev1 all -j8 # DEVICE_TREE=stm32mp157d-ev1 参数指定了使用的设备树文件(Device Tree File),这是描述硬件配置的文件
# -j8 参数表示使用 8 个并行任务进行编译,可以加快构建过程

   编译完成后就可以获得uboot可执行文件:

  u-boot.bin 包含了设备树(dtb),也就是将 uboot 镜像和设备树打包在了一起。其中 u-boot.stm32 是在 u-boot.bin前面添加了 256 字节头部信息的可执行文件,是要烧写到开发板里面的。 

2.2 烧写测试

  为什么不能用上一小节编译出来的u-boot.stm32,是因为必须要保证这个uboot是工作正常的,我们刚刚才编译出来的uboot肯定有问题,所以使用正点原子提供的uboot。下载到DDR是正点原子的,下载到EMMC是我们自己编译出来的。

  将上一小节编译出来的u-boot.stm32 重命名为 my-u-boot.stm32。然后将 my-u-boot.stm32 放在 images 目录下,并且还要修改Flashlayouts文件,修改烧写到EMMC里面的uboot名字。

首先拨片换到USB才检测得到USB。

  烧写完成后,换成EMMC,再重启。我们发现重启以后会一直进行重启,并发出警报声。

从上图可以看出:

1、uboot是能运行的,就是说ST官方的EVK开发板的uboot可以直接在正点原子 STM32Mp157上面运行,但是运行会出错。

2、uboot版本为2020.01,编译日期为2023.8.2,就是刚刚自己编译了uboot。

3、

,因为ST 的EVK开发板使用了电源管理芯片 STPMIC1A,所以uboot运行的时候会初始化PMIC芯片,但这个板子是没有这个芯片的,所以会报 STPMIC的错误。

一步步的修改 uboot,至到其正常工作,也就是所谓的 uboot 移植。

二、  在 U-boot 中添加开发板

1. 创建默认配置文件 

首先进入这个目录

其实开发板是参考了官方的 EVK 开发板,所以直接参考官方的板子即可,输入以下命令:

cd configs     //进入 uboot 的 configs 目录
cp stm32mp15_trusted_defconfig stm32mp15_atk_trusted_defconfig     // 拷贝并重命名

此时这里的 stm32mp15_atk_trusted_defconfig 文件就是开发板使用的默认配置文件。

2. 创建默认设备树 

直接复制ST官方的开发板的设备树,命令如下:

cd ..
cd arch/arm/dts/
cp stm32mp157d-ed1.dts stm32mp157d-atk.dts // 拷贝并重命名.dts
cp stm32mp15xx-edx.dtsi stm32mp157d-atk.dtsi // 拷贝并重命名.dtsi
cp stm32mp157a-ed1-u-boot.dtsi stm32mp157d-atk-u-boot.dtsi // 拷贝并重命名.dtsi

打开  stm32mp157d-atk.dts ,需要修改头文件引用:

#include "stm32mp157.dtsi"
#include "stm32mp15xd.dtsi"
#include "stm32mp15-pinctrl.dtsi"
#include "stm32mp15xxaa-pinctrl.dtsi"
#include "stm32mp157-m4-srm.dtsi"
#include "stm32mp157-m4-srm-pinctrl.dtsi"
// 原本是 #include "stm32mp15xx-edx.dtsi"
// 修改为:
stm32mp157d-atk.dtsi
// 因为需要修改成自己的头文件

3. 修改电源管理设置 

打开 stm32mp157d-atk-u-boot.dtsi ,代码如下:

/ SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause
/*
 * Copyright : STMicroelectronics 2018
 */

#include <dt-bindings/clock/stm32mp1-clksrc.h>
#include "stm32mp15-u-boot.dtsi"
#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi"

/ {
	aliases {
		i2c3 = &i2c4;
		mmc0 = &sdmmc1;
		mmc1 = &sdmmc2;
	};

	config {
		u-boot,boot-led = "heartbeat";
		u-boot,error-led = "error";
		u-boot,mmc-env-partition = "ssbl";
		// st,fastboot-gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;         删除
		// st,stm32prog-gpios = <&gpioa 14 GPIO_ACTIVE_LOW>;        删除
	};

	led {
		/* red {
			label = "error";
			gpios = <&gpioa 13 GPIO_ACTIVE_LOW>;        删除
			default-state = "off";
			status = "okay";
		};*/
	};
};

#ifndef CONFIG_STM32MP1_TRUSTED
&clk_hse {
	st,digbypass;
};

&i2c4 {
	u-boot,dm-pre-reloc;
};

&i2c4_pins_a {
	u-boot,dm-pre-reloc;
	pins {
		u-boot,dm-pre-reloc;
	};
};

/* &pmic {
	u-boot,dm-pre-reloc;    删除
}; */

接着修改 stm32mp157d-atk.dtsi :

// adc整段删除
&adc {
	/* ANA0, ANA1 are dedicated pins and don't need pinctrl: only in6. */
	pinctrl-0 = <&adc1_in6_pins_a>;
	pinctrl-names = "default";
	vdd-supply = <&vdd>;
	vdda-supply = <&vdda>;
	vref-supply = <&vdda>;
	status = "disabled";        
	adc1: adc@0 {
		st,adc-channels = <0 1 6>;
		/* 16.5 ck_cycles sampling time */
		st,min-sample-time-nsecs = <400>;
		status = "okay";
	};
};

&cpu0{
	cpu-supply = <&vddcore>;
};

&crc1 {
	status = "okay";
};

// dac整段删除
&dac {
	pinctrl-names = "default";
	pinctrl-0 = <&dac_ch1_pins_a &dac_ch2_pins_a>;
	vref-supply = <&vdda>;
	status = "disabled";
	dac1: dac@1 {
		status = "okay";
	};
	dac2: dac@2 {
		status = "okay";
	};
};

&dma1 {
	sram = <&dma_pool>;
};

&dma2 {
	sram = <&dma_pool>;
};

&dts {
	status = "okay";
};

&hash1 {
	status = "okay";
};

// i2c4整段删除
&i2c4 {
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&i2c4_pins_a>;
	pinctrl-1 = <&i2c4_pins_sleep_a>;
	i2c-scl-rising-time-ns = <185>;
	i2c-scl-falling-time-ns = <20>;
	clock-frequency = <400000>;
	status = "okay";
	/* spare dmas for other usage */
	/delete-property/dmas;
	/delete-property/dma-names;

	pmic: stpmic@33 {
		compatible = "st,stpmic1";
		reg = <0x33>;
		interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>;
		interrupt-controller;
		#interrupt-cells = <2>;
		status = "okay";

		regulators {
			compatible = "st,stpmic1-regulators";
			buck1-supply = <&vin>;
			buck2-supply = <&vin>;
			buck3-supply = <&vin>;
			buck4-supply = <&vin>;
			ldo1-supply = <&v3v3>;
			ldo2-supply = <&v3v3>;
			ldo3-supply = <&vdd_ddr>;
			ldo4-supply = <&vin>;
			ldo5-supply = <&v3v3>;
			ldo6-supply = <&v3v3>;
			vref_ddr-supply = <&vin>;
			boost-supply = <&vin>;
			pwr_sw1-supply = <&bst_out>;
			pwr_sw2-supply = <&bst_out>;

			vddcore: buck1 {
				regulator-name = "vddcore";
				regulator-min-microvolt = <1200000>;
				regulator-max-microvolt = <1350000>;
				regulator-always-on;
				regulator-initial-mode = <0>;
				regulator-over-current-protection;
			};
......
               vbus_sw: pwr_sw2 {
				regulator-name = "vbus_sw";
				interrupts = <IT_OCP_SWOUT 0>;
				regulator-active-discharge = <1>;
			 };
		};

		onkey {
			compatible = "st,stpmic1-onkey";
			interrupts = <IT_PONKEY_F 0>, <IT_PONKEY_R 0>;
			interrupt-names = "onkey-falling", "onkey-rising";
			power-off-time-sec = <10>;
			status = "okay";
		};

		watchdog {
			compatible = "st,stpmic1-wdt";
			status = "disabled";
		};
	};
};

 继续修改,将下面的代码都删除:

	led {
		compatible = "gpio-leds";
		blue {
			label = "heartbeat";
			gpios = <&gpiod 9 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "heartbeat";
			default-state = "off";
		};
	};

	sd_switch: regulator-sd_switch {
		compatible = "regulator-gpio";
		regulator-name = "sd_switch";
		regulator-min-microvolt = <1800000>;
		regulator-max-microvolt = <2900000>;
		regulator-type = "voltage";
		regulator-always-on;

		gpios = <&gpiof 14 GPIO_ACTIVE_HIGH>;
		gpios-states = <0>;
		states = <1800000 0x1 2900000 0x0>;
	};

  最后需要向 stm32mp157d-atk.dtsi 文件的根节点‘/’下添加自己的电源管理配置,将下面的代码添加到下方代码中间处:

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

// 此处添加代码
	vddcore: regulator-vddcore {
		compatible = "regulator-fixed";
		regulator-name = "vddcore";
		regulator-min-microvolt = <1200000>;     // 最小电压设定为 1.2V
		regulator-max-microvolt = <1350000>;     // 最大电压设定为 1.35V
		regulator-always-on;                     // 始终开启,不能被关闭
		regulator-boot-on;                       // 引导时开启
    };

	v3v3: regulator-3p3v {
		compatible = "regulator-fixed";
		regulator-name = "v3v3";
		regulator-min-microvolt = <3300000>;     // 最小电压设定为 3.3V
		regulator-max-microvolt = <3300000>;     // 最大电压设定为 3.3V
		regulator-always-on;                     // 始终开启,不能被关闭
		regulator-boot-on;                       // 引导时开启
	};

	v1v8_audio: regulator-v1v8-audio {
		compatible = "regulator-fixed";
		regulator-name = "v1v8_audio";
		regulator-min-microvolt = <1800000>;     // 最小电压设定为 1.8V
		regulator-max-microvolt = <1800000>;     // 最大电压设定为 1.8V
		regulator-always-on;                     // 始终开启,不能被关闭
		regulator-boot-on;                       // 引导时开启
	};

	vdd: regulator-vdd {
		compatible = "regulator-fixed";
		regulator-name = "vdd";
		regulator-min-microvolt = <3300000>;     // 最小电压设定为 3.3V
		regulator-max-microvolt = <3300000>;     // 最大电压设定为 3.3V
		regulator-always-on;                     // 始终开启,不能被关闭
		regulator-boot-on;                       // 引导时开启
	};

	vdd_usb: regulator-vdd-usb {
		compatible = "regulator-fixed";
		regulator-name = "vdd_usb";
		regulator-min-microvolt = <3300000>;     // 最小电压设定为 3.3V
		regulator-max-microvolt = <3300000>;     // 最大电压设定为 3.3V
		regulator-always-on;                     // 始终开启,不能被关闭
		regulator-boot-on;                       // 引导时开启
	};

	vin: vin {
		compatible = "regulator-fixed";
		regulator-name = "vin";
		regulator-min-microvolt = <5000000>;
		regulator-max-microvolt = <5000000>;
		regulator-always-on;
	};
};

4.  修改 TF 卡和 EMMC 配置 

  继续修改  stm32mp157d-atk.dtsi   找到 sdmmc1 和 sdmmc2 这两个节点,将这两个节点改为如下所示内容: 

&sdmmc1 {
	/* 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>;                 /* 休眠引脚控制器 */
	st,neg-edge;                                           /* 设置负边沿触发 */
	broken-cd;                                             /* CD引脚已损坏 */
	bus-width = <4>;                                       /* 总线宽度为4 */
	vmmc-supply = <&v3v3>;                                 /* VMMC供电引脚 */
	status = "okay";                                       /* 设备状态正常 */
};

&sdmmc2 {
	/* 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;                                         /* 不可移动设备 */
	st,neg-edge;                                           /* 设置负边沿触发 */
	bus-width = <8>;                                       /* 总线宽度为8 */
	vmmc-supply = <&v3v3>;                                 /* VMMC供电引脚 */
	keep-power-in-suspend;                                 /* 在挂起状态下保持电源 */
	status = "okay";                                       /* 设备状态正常 */
};

5.  编译uboot

  编译之前先在 stm32mp157d-atk.dtsi 文件中找到 usbotg_hs节点,此节点默认内容如下所示: 

// 定义USB_OTG电源配置
&usbotg_hs {
	vbus-supply = <&vbus_otg>;
};

  ST 官方开发板的 USB_OTG 电源也是通过 PMIC 配置的,所以 USB_OTG 电源配置也要修改,但在此之前需要先测试一下uboot能不能运行,把上方的代码给注释掉。

  打开 arch/arm/dts/Makefile 文件,找到“dtb-$(CONFIG_STM32MP15x)”配置项,然后在此配置项中加入“stm32mp157d-atk.dtb”:

  第 847 行里就是告诉“Makefile”把我们刚新建的 stm32mp157d-atk.bts 编译成对应的 dtb 文件。以前编译 uboot 都是自己输入一条一条命令编译,我们可以创建一个 shell 脚本,将所有的编译命令都写到这个 shell 脚本里面,然后每次的时候只需要执行一下这个 shell脚本即可。在 uboot 源码根目录下新建一个名为 stm32mp157d_alientek.sh 的 shell 脚本,在这个 shell 脚本里面输入如下内容: 

#!/bin/bash

make distclean                           # 清除之前的构建文件
make stm32mp15_atk_trusted_defconfig     # 使用 stm32mp15_atk_trusted_defconfig 进行配置
make DEVICE_TREE=stm32mp157d-atk all -j12 # 使用 stm32mp157d-atk 设备树进行构建,使用12个并发任务

  给予 stm32mp157d_alientek.sh 可执行权限,然后运行脚本来完成编译,命令如下: 

chmod 777 stm32mp157d_alientek.sh     # 给予可执行权限
./stm32mp157d_alientek.sh     # 运行脚本编译 uboot

  把 u-boot.stm32 重命名为 my-u-boot.stm32 ,跟上次一样的方法用 STM32CubeProgrammer 烧写进板子里,并用 MobaXterm 去查看板子信息:

  uboot 启动成功,并且进入了命令行模式,并且命令行也可以正常操作,那么是不是说明 uboot 已经移植成功了呢?不一定, uboot 有没有移植成功取决于当前uboot 能不能满足我们的要求,如果不满足就说明还没移植成功。

  当前 uboot 的网络、 USB_OTG 也不能正常工作,所以我们还需要接着修改。 

6. 网络驱动修改 

6.1 修改网络设备树

  

从这我们可以看出,并没有找到网络,说明uboot的网络驱动有问题。原因是当前设备树没有网络相关节点,只需要将网络相关的节点加入设备树即可。

  打开  stm32mp157d-atk.dtsi 文件,将如下所示的 ethernet0 节点加添加到最后面: 

&ethernet0 {
	status = "okay";
	pinctrl-0 = <&ethernet0_rgmii_pins_a>;  // 配置引脚控制器0为rgmii_pins_a
	pinctrl-1 = <&ethernet0_rgmii_pins_sleep_a>;  // 配置引脚控制器1为rgmii_pins_sleep_a
	pinctrl-names = "default", "sleep";  // 引脚控制器的命名,用于区分默认和睡眠状态
	phy-mode = "rgmii-id";  // 物理层模式设置为rgmii-id(双主机模式)
	max-speed = <1000>;  // 最大速度设置为1000Mbps
	phy-handle = <&phy0>;  // 物理设备的句柄引用

	mdio0 {
		#address-cells = <1>;  // MDIO地址单元的数量(在这种情况下为1)
		#size-cells = <0>;  // MDIO大小单元的数量(在这种情况下为0)
		compatible = "snps,dwmac-mdio";  // 兼容性标识,指定MDIO兼容性

		phy0: ethernet-phy@0 {  // 第一个以太网物理设备,地址为0
			reg = <0>;  // 注册地址设置为0
		};
	};
};

6.2  修改网络驱动

用正点原子提供的修改后的 phy.c 文件替换掉 uboot 下的/drivers/net/phy/phy.c 文件即可,设备树无需做任何修改,直接编译。 

设置网络相关命令:

setenv ipaddr 192.168.1.106     # 开发板 IP 地址
setenv ethaddr b8:ae:1d:01:01:00     # 开发板网卡 MAC 地址
setenv gatewayip 192.168.1.1     # 开发板默认网关
setenv netmask 255.255.255.0     # 开发板子网掩码
setenv serverip 192.168.1.105     # 服务器地址,也就是 Ubuntu 地址
saveenv

 测试一下:

ping 192.168.1.105

7. 修改 USB OTG 设备树

7.1 添加 usb_phy_tuning 子节点

  打开 stm32mp157d-atk.dtsi 这个文件,在根节点“/”下添加名为“usb_phy_tuning”的子节点,节点内容如下: 

	usb_phy_tuning: usb-phy-tuning {
		st,hs-dc-level = <2>;
		st,fs-rftime-tuning;
		st,hs-rftime-reduction;
		st,hs-current-trim = <15>;
		st,hs-impedance-trim = <1>;
		st,squelch-level = <3>;
		st,hs-rx-offset = <2>;
		st,no-lsfs-sc;
	};

7.2 添加 STUSB1600 I2C 子节点

  开发板上的 USB OTG 接口类型为 Type-C,使用 STUSB1600 芯片来实现此接口功能, STUSB1600 有一个 I2C 接口,此 I2C 接口用来配置芯片,因此我们还需要在设备树中添加 STUSB1600 相关的 I2C 节点内容。将如下内容添加到 stm32mp157d-atk.dtsi 的最后面: 

&i2c1 {
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&i2c1_pins_a>;
	pinctrl-1 = <&i2c1_pins_sleep_a>;
	i2c-scl-rising-time-ns = <100>;
	i2c-scl-falling-time-ns = <7>;
	status = "okay";
	/delete-property/dmas;
	/delete-property/dma-names;

	stusb1600@28 {
		compatible = "st,stusb1600";
		reg = <0x28>;
		interrupts = <2 IRQ_TYPE_EDGE_FALLING>;
		interrupt-parent = <&gpiog>;
		pinctrl-names = "default";
		pinctrl-0 = <&stusb1600_pins_a>;
		status = "okay";
		vdd-supply = <&vin>;

		connector {
			compatible = "usb-c-connector";
			label = "USB-C";
			power-role = "dual";
			power-opmode = "default";

			port {
				con_usbotg_hs_ep: endpoint {
					remote-endpoint = <&usbotg_hs_ep>;
				};
			};
		};
	};
};

7.3 添加 usb 接口相关节点

  继续向 stm32mp157d-atk.dtsi 添加 USB 接口代码,内容如下:

&usbh_ehci {
	phys = <&usbphyc_port0>;
	status = "okay";
};

&usbotg_hs {
	phys = <&usbphyc_port1 0>;
	phy-names = "usb2-phy";
	usb-role-switch;
	status = "okay";

	port {
		usbotg_hs_ep: endpoint {
			remote-endpoint = <&con_usbotg_hs_ep>;
		};
	};
};

&usbphyc {
	status = "okay";
};

7.4 在 stm32mp157d-atk-u-boot.dtsi 中添加 usbotg_hs 节点

&usbotg_hs {
	u-boot,force-b-session-valid;
	hnp-srp-disable;
	/* TEMP: force peripheral for USB OTG */
	dr_mode = "peripheral";
};

  重新编译 uboot 并烧写,然后使用 ums 命令测试,看看能不能将 EMMC 模拟成 U 盘,挂载到电脑上,命令如下: 

ums 0 mmc 1

8. 使能 boot 和 bootd 命令 

  ST 官方 uboot 默认并没有使能 boot 和 bootd 这两个命令,这两个命令的实现源文件为cmd/bootm.c, bootm.c 代码如下: 

/*******************************************************************/
/* bootd - boot default image */
/*******************************************************************/
#if defined(CONFIG_CMD_BOOTD)    // 要使能boot和bootd,必须定义CONFIG_CMD_BOOTD
int do_bootd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
	return run_command(env_get("bootcmd"), flag);
}

U_BOOT_CMD(
	boot,	1,	1,	do_bootd,
	"boot default, i.e., run 'bootcmd'",
	""
);

/* keep old command name "bootd" for backward compatibility */
U_BOOT_CMD(
	bootd, 1,	1,	do_bootd,
	"boot default, i.e., run 'bootcmd'",
	""
);

#endif

打开 include/configs/stm32mp1.h,然后在后面添加如下宏定义:

重新编译并烧写,并输入命令:

? boot
// 或
? bootd

9. LCD 驱动修改  

  uboot 也是支持 LCD 显示的,主要是设置屏幕背光、屏幕时序参数这些,这些直接在设备树里面修改即可。打开 stm32mp157d-atk.dts 文件,在里面添加 LCD 相关节点信息,首先在根节点“/”下添加 panel_backlight 和 panel_rgb 这两个节点,节点内容如下: 

/* panel_backlight 为 LCD 的背光控制节点,主要指定 LCD 背光 IO 所使用的引脚,正点原子的 STM32MP157 开发板 LCD 背光引脚为 PD13*/
panel_backlight: panel-backlight {
	compatible = "gpio-backlight";
	gpios = <&gpiod 13 GPIO_ACTIVE_HIGH>;
	default-on;
	status = "okay";
};

panel_rgb: panel-rgb {                // panel_rgb 为 RGB LCD 节点,指定了 LTDC 接口所使用的 IO、屏幕时序参数等
	compatible = "simple-panel";
	pinctrl-names = "default", "sleep";
	pinctrl-0 = <&ltdc_pins_b>;
	pinctrl-1 = <&ltdc_pins_sleep_b>;
	backlight = <&panel_backlight>;
	status = "okay";

	port {
		panel_in_rgb: endpoint {
			remote-endpoint = <&ltdc_ep0_out>;
		};
	};

	display-timings {
		native-mode = <&timing0>; /* 时序信息 */
		timing0: timing0 { /* 7 寸 1024*600 分辨率 */
			clock-frequency = <51200000>; /* LCD 像素时钟,单位 Hz */
			hactive = <1024>; /* LCD X 轴像素个数 */
			vactive = <600>; /* LCD Y 轴像素个数 */
			hfront-porch = <160>; /* LCD hfp 参数 */
			hback-porch = <140>; /* LCD hbp 参数 */
			hsync-len = <20>; /* LCD hspw 参数 */
			vback-porch = <20>; /* LCD vbp 参数 */
			vfront-porch = <12>; /* LCD vfp 参数 */
			vsync-len = <3>; /* LCD vspw 参数 */
		};
	};
};

 并且在这个文件下继续添加 ltdc 节点内容:

&ltdc {
	status = "okay";
	pinctrl-names = "default";
	port {
		#address-cells = <1>;
		#size-cells = <0>;

		ltdc_ep0_out: endpoint@0 {
			reg = <0>;
			remote-endpoint = <&panel_in_rgb>;
		};
	};
};

三、U-boot测试

3.1 自烧写测试

修改 FlashLayout 如下图所示:

用我们自己编译的 uboot 来烧写自身。检测方法很简单,看能不能正常烧写。

3.2 EMMC 启动 Linux

  从EMMC启动也就是将编译出来的Linux镜像文件uImage和.dtb设备树文件保存在EMMC中, uboot 从 EMMC 中读取这两个文件并启动,这个是我们产品最终的启动方式。首先 EMMC里面要先存放 Linux 镜像文件 uImage 和.dtb 设备树,但是我们前面新建的 FlashLayout 文件并没有烧写 uImage 和.dtb,所以我们需要修改一下 FlashLayout 文件,加入 uImage 和.dtb 烧写命令。由于我们还没有移植 Linux 系统,所以 uImage 和.dtb 就先使用正点原子出厂系统提供的。

  atk-image-bootfs.ext4 是 ext4 格式的打包文件,因为 STM32CubeProgrammer软件要求将 uImage 和.dtb 打包在一起,格式为 ext4。 把 atk-image-bootfs.ext4 复制到 image 文件夹下,并修改 FlashLayout:

  修改完成重新烧录并重启, 使用 ext4ls 命令查看一下 EMMC 的分区 2 里面有没有 uImage 和.dtb 文件,命令如下: 

ext4ls mmc 1:2

  这里我们只需要用到 uImage 和 stm32mp157d-atk.dtb 这两个文件,设置bootcmd 环境变量从 EMMC 里面读取系统文件,然后再启动,命令如下: 

setenv bootcmd 'ext4load mmc 1:2 c2000000 uImage;ext4load mmc 1:2 c4000000 stm32mp157datk.dtb;bootm c2000000 - c4000000'
saveenv
boot

# 挨个来解释
# ext4load mmc 1:2 c2000000 uImage:从MMC设备的第1个分区(mmc 1)的第2个文件系统分区(分区号2)中加载uImage文件到内存地址c2000000
# ext4load mmc 1:2 c4000000 stm32mp157datk.dtb:从MMC设备的第1个分区(mmc 1)的第2个文件系统分区(分区号2)中加载stm32mp157datk.dtb设备树文件到内存地址c4000000
# bootm c2000000 - c4000000:使用加载的内核映像和设备树进行引导,内核位于地址c2000000,设备树位于地址c4000000

  只要出现了 Booting Linux on physical CPU 0x0 即引导 Linux 内核成功。

3.3 从网络启动 Linux 系统 (测试)

  从网络启动 Linux 系统的唯一目的就是为了调试。如果每次修改 Linux 系统文件或者 Linux 下的某个驱动,以后都要烧写到 EMMC 去测试,太麻烦。 我们可以设置 Linux 从网络启动,也就是将 Linux 镜像文件和根文件系统都放到 Ubuntu 下某个指定的文件夹中,这样每次重新编译 Linux 内核或者某个 Linux 驱动以后只需要使用 cp 命令将其拷贝到这个指定的文件夹中即可,这样就不用需要频繁的烧写EMMC。

  可以通过 nfs 或者 tftp 从 Ubuntu 中下载 uImage 和设备树文件,根文件系统的话也可以通过 nfs 挂载,但这里我们使用 tftp 从 Ubuntu 中下载 uImage和设备树文件,前提是要将 uImage 和设备树文件放到 Ubuntu 下的 tftp 目录中。 

首先使用 FileZilla 把文件 传到 tftpboot 目录下:

之后用命令把这两个文件给予权限:

再在uboot里面输入以下命令:

setenv bootcmd 'tftp c2000000 uImage;tftp c4000000 stm32mp157d-atk.dtb;bootm c2000000 - c4000000'
saveenv
boot

四、bootcmd 和 bootargs 环境变量 

4.1 bootcmd 环境变量 

  bootcmd 保存着 uboot 默认命令, uboot 倒计时结束以后就会执行 bootcmd 中的命令。这些命令一般都是用来启动 Linux 内核的,比如读取 EMMC 或者 NAND Flash 中的 Linux 内核镜像文件和设备树文件到 DRAM 中,然后启动 Linux 内核。可以在 uboot 启动以后进入命令行设置 bootcmd 环境变量的值。如果 EMMC 或者 NAND 中没有保存 bootcmd 的值,那么 uboot 就会使用默认的值,板子第一次运行 uboot 的时候都会使用默认值来设置 bootcmd 环境变量。 

  bootcmd 的默认值就是 CONFIG_BOOTCOMMAND,bootargs 的默认值就是 CONFIG_BOOTARGS。我们可以直接在 stm32mp1.h 文件中通过设置宏CONFIG_BOOTCOMMAND 来设置 bootcmd 的默认值。 

4.2 bootargs 环境变量 

  bootargs 环境变量是用于设置 Linux 内核启动参数的变量。它定义了在引导 Linux 内核时传递给内核的命令行参数。 如下面 bootargs 环境变量值: 

console=ttySTM0,115200 root=/dev/mmcblk2p3 rootwait rw

① console

  console 用来设置 linux 终端(或者叫控制台),也就是通过什么设备来和 Linux 进行交互,是串口还是 LCD 屏幕?如果是串口的话应该是串口几等等。一般设置串口作为 Linux 终端,这样我们就可以在电脑上通过 MobaXterm 来和 linux 交互了。这里设置 console 为 ttySTM0,因为linux 启动以后 STM32MP1 的串口 4 在 linux 下的设备文件就是/dev/ttySTM0,在 Linux 下,一切皆文件。 

  ttySTM0 后面有个“,115200”,这是设置串口的波特率, console=ttySTM0,115200 综合起来就是设置 ttySTM0(也就是串口 4)作为 Linux 的终端,并且串口波特率设置为 115200。 

② root

  root 用来设置根文件系统的位置, root=/dev/mmcblk2p3 用于指明根文件系统存放在  mmcblk2 设备的分区3中。 其 中/dev/mmcblkx(x=0~n) 表 示 mmc 设 备 , 而/dev/mmcblkxpy(x=0~n,y=1~n)表示 mmc 设备 x 的分区 y。在 STM32MP1 开发板中/dev/mmcblk2表示 EMMC,而/dev/mmcblk2p3 表示 EMMC 的分区 3。 

  root 后面有“rootwait rw”, rootwait 表示等待 mmc 设备初始化完成以后再挂载,否则的话mmc 设备还没初始化完成就挂载根文件系统会出错的。 rw 表示根文件系统是可以读写的,不加rw 的话可能无法在根文件系统中进行写操作,只能进行读操作。 

③ rootfstype

  此选项一般配合 root 一起使用, rootfstype 用于指定根文件系统类型,如果根文件系统为ext 格式的话此选项可有可无。如果根文件系统是 yaffs、 jffs 或 ubifs 的话就需要设置此选项,指定根文件系统的类型。 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1301203.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

什么是图片懒加载(image lazy loading)?它的作用是什么?

聚沙成塔每天进步一点点 ⭐ 专栏简介 前端入门之旅&#xff1a;探索Web开发的奇妙世界 欢迎来到前端入门之旅&#xff01;感兴趣的可以订阅本专栏哦&#xff01;这个专栏是为那些对Web开发感兴趣、刚刚踏入前端领域的朋友们量身打造的。无论你是完全的新手还是有一些基础的开发…

区块链媒体宣发:揭示优势与趋势,引领信息传播新时代

在数字化潮流中&#xff0c;区块链技术正以惊人的速度改变着传媒行业的格局。从区块链媒体宣发中获得的种种优势和未来的趋势&#xff0c;不仅为企业带来了新的推广途径&#xff0c;也在信息传播领域掀起了一场革命。本文将深入探讨区块链媒体宣发的优势以及未来的发展趋势。 1…

一款基于ESP32的迷你四足机器人

一、软件介绍 增加自定义动作模式&#xff0c;可以在小程序中自定义一个最多10个步骤的动作。 附件中&#xff1a;带自定模式固件bin.zip esp32c3固件文件 烧录下图设置 无串口版本esp32c3开发板烧录前先按住BOOT键再插线进入烧录模式&#xff0c;LoadMode选择USB。 二、AP…

计算机毕业设计 SpringBoot的医院门诊在线挂号系统 Javaweb项目 Java实战项目 前后端分离 文档报告 代码讲解 安装调试

&#x1f34a;作者&#xff1a;计算机编程-吉哥 &#x1f34a;简介&#xff1a;专业从事JavaWeb程序开发&#xff0c;微信小程序开发&#xff0c;定制化项目、 源码、代码讲解、文档撰写、ppt制作。做自己喜欢的事&#xff0c;生活就是快乐的。 &#x1f34a;心愿&#xff1a;点…

shiro反序列化漏洞复现

shiro反序列化漏洞复现 文章目录 shiro反序列化漏洞复现版本安装环境漏洞利用流量分析 版本 550 仅需要一个url 721 需要一个账号 安装环境 先配置国内源 安装docker apt-get install docker 安装docker-compose apt-get install docker-compose 拉取镜像 docker pull …

二分查找|滑动窗口|前缀和|LeetCode209: 长度最小的子数组

长度最短的子数组 作者推荐 【动态规划】【广度优先】LeetCode2258:逃离火灾 本文涉及的基础知识点 二分查找算法合集 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 滑动窗口 题目 给定一个含有 n 个正整数的数组和一个正整数 target…

Python开发运维:Python项目发布到K8S集群

目录 一、实验 1.Python项目发布到K8S集群 一、实验 1.Python项目发布到K8S集群 &#xff08;1&#xff09;获取应用程序代码 #把hello-python.tar.gz压缩包上传到k8s控制节点master1的root下&#xff0c;手动解压 tar zxvf hello-python.tar.gz &#xff08;2&#xff0…

智能外呼有什么好处?

智能外呼是一种自动化的电话营销方式&#xff0c;利用AI智能外呼技术和大量数据分析&#xff0c;帮助企业实现与客户之间的高效、精准、个性化的客户沟通&#xff0c;还可以在客户服务、市场营销和销售等方面带来助力。那么&#xff0c;智能外呼有什么好处呢&#xff1f; 1. 提…

elasticsearch|大数据|elasticsearch低版本集群的部署安装和安全增强---密码设置问题

一&#xff0c; 版本问题 elasticsearch的高低版本划分标准为6.3&#xff0c;该版本之前的为低版本&#xff0c;6.3版本之后的包括6.3为高版本&#xff0c;这么划分主要是在安全性方面也就是x-pack插件的使用部署方面&#xff0c;低版本需要手动安装该安全插件&#xff0c;而…

【网络协议】LACP(Link Aggregation Control Protocol,链路聚合控制协议)

文章目录 LACP名词解释LACP工作原理互发LACPDU报文确定主动端确定活动链路链路切换 LACP和PAgP有什么区别&#xff1f;LACP与LAG的关系LACP模式更优于手动模式LACP模式对数据传输更加稳定和可靠LACP模式对聚合链路组的故障检测更加准确和有效 推荐阅读 LACP名词解释 LACP&…

同位素二氧化碳数据记录软件

同位素二氧化碳数据记录软件用于实现同位素二氧化碳分析仪数据的获取与存档&#xff0c;阀箱数据的获取、记录以及阀箱的远程操作&#xff0c;数据的FTP上传等功能。其主操作界面如下&#xff1a; 软件的左侧为操作目录区域&#xff0c;实现显示界面的切换和连接操作及其状态指…

GPIO的使用--USART串口通信--传感器控制数据

目录 一、串口通信 1、概念 2、原理图 3、使用步骤 &#xff08;1&#xff09;寻找串口位置 &#xff08;2&#xff09;确定引脚编号 &#xff08;3&#xff09;编写代码 4、实验结果 实验代码 main.c usart.c usart.h 一、串口通信 1、概念 串行接口是一种可以将…

Spring 面向切面编程(AOP)

一、aop介绍 &#xff08;一&#xff09;前言 一般的后端开发流程是纵向开发&#xff0c;就是controller&#xff08;控制层&#xff09;->service&#xff08;业务层&#xff09;->mapper&#xff08;数据持久层&#xff09;&#xff0c;Spring采用动态代理技术可以在…

flstudio21.3.2304高级版水果编曲音乐软件

flstudio高级版是一款适用于广泛领域的音频编辑软件。它支持多通道混音器和VST插件&#xff0c;包括数百种乐器和效果插件。它还为您提供了一个乐谱编辑器&#xff0c;需要对不同乐器的节奏进行必要的编辑。Flstudio具有许多内置电子合成声音&#xff0c;可提供更广泛的电子声音…

基于STM32的四位数码管计数器设计与实现

✅作者简介&#xff1a;热爱科研的嵌入式开发者&#xff0c;修心和技术同步精进&#xff0c; 代码获取、问题探讨及文章转载可私信。 ☁ 愿你的生命中有够多的云翳,来造就一个美丽的黄昏。 &#x1f34e;获取更多嵌入式资料可点击链接进群领取&#xff0c;谢谢支持&#xff01;…

2024年网络安全竞赛-数字取证调查attack817

​ 数字取证调查 (一)拓扑图 服务器场景:FTPServer20221010(关闭链接) 服务器场景操作系统:未知 FTP用户名:attack817密码:attack817 分析attack.pcapng数据包文件,通过分析数据包attack.pcapng找出恶意用户第一次访问HTTP服务的数据包是第几号,将该号数作为Flag值…

如何打印富文本控件中的内容?

出于某种原因&#xff0c;人们确实对打印富文本控件中的内容感到困惑。 我并非打印方面的专家&#xff0c;但是经过对资料的研究的&#xff0c;我也算弄明白了&#xff0c;今天在此记录一下。 解决问题的关键是这个消息&#xff1a;EM_FORMATRANGE。 每次发送这个消息的时候&a…

【论文极速读】LVM,视觉大模型的GPT时刻?

【论文极速读】LVM&#xff0c;视觉大模型的GPT时刻&#xff1f; FesianXu 20231210 at Baidu Search Team 前言 这一周&#xff0c;LVM在arxiv上刚挂出不久&#xff0c;就被众多自媒体宣传为『视觉大模型的GPT时刻』&#xff0c;笔者抱着强烈的好奇心&#xff0c;在繁忙工作之…

洛谷P4071 排列计数

传送门&#xff1a; P4071 [SDOI2016] 排列计数 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)https://www.luogu.com.cn/problem/P4071题干: 有多少个1到n的排列a&#xff0c;使得恰好有m个位置满足ai i &#xff0c; 回答T组询问&#xff0c;答案多 10^97取模 数据范围&am…

为什么需要 Kubernetes,它能做什么?

传统部署时代&#xff1a; 早期&#xff0c;各个组织是在物理服务器上运行应用程序。 由于无法限制在物理服务器中运行的应用程序资源使用&#xff0c;因此会导致资源分配问题。 例如&#xff0c;如果在同一台物理服务器上运行多个应用程序&#xff0c; 则可能会出现一个应用程…