6.4 U-boot 移植

2023-11-08

一、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 的话就需要设置此选项,指定根文件系统的类型。 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

6.4 U-boot 移植 的相关文章

  • LINUX:如何锁定内存中进程的页面

    我有一个 LINUX 服务器 运行一个具有大量内存占用的进程 某种数据库引擎 该进程分配的内存太大 需要将其中一部分换出 换出 我想做的是将所有其他进程 或正在运行的进程的子集 的内存页面锁定在内存中 以便只有数据库进程的页面被换出 例如
  • 嵌入清单文件以要求具有 mingw32 的管理员执行级别

    我正在 ubuntu 下使用 i586 mingw32msvc 交叉编译应用程序 我很难理解如何嵌入清单文件以要求 mingw32 具有管理员执行级别 对于我的例子 我使用了这个hello c int main return 0 这个资源文
  • Linux无法删除文件

    当我找到文件时 我在删除它们时遇到问题 任务 必须找到带有空格的文件并将其删除 我的尝试 rm find L root grep i 但我有错误 rm cannot remove root test No such file or dire
  • 如何在 Linux 上通过 FTP 递归下载文件夹 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 Locked 这个问题及其答案是locked help locked posts因为这个问题是题外话 但却具有历史意义 目前不接受新的答案
  • awk 在循环中使用时不打印任何内容[重复]

    这个问题在这里已经有答案了 我有一堆使用 file 1 a 1 txt 格式的文件 如下所示 A 1 B 2 C 3 D 4 并使用以下命令添加包含每个文件名称的新列 awk print FILENAME NF t 0 file 1 a 1
  • ioctl 命令的用户权限检查

    我正在实现 char 驱动程序 Linux 并且我的驱动程序中有某些 IOCTL 命令仅需要由 ADMIN 执行 我的问题是如何在 ioctl 命令实现下检查用户权限并限制非特权用户访问 IOCTL 您可以使用bool capable in
  • 找不到包“gdk-pixbuf-2.0”

    我正在尝试在 Amazon Linux 发行版实例上构建 librsvg 我已经通过 yum 安装了大部分依赖项 其中一些在实例上启用的默认 yum 存储库中不可用 因此必须从头开始构建它们 我已经走了很远 但还停留在最后一点 跑步时sud
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • python获取上传/下载速度

    我想在我的计算机上监控上传和下载速度 一个名为 conky 的程序已经在 conky conf 中执行了以下操作 Connection quality alignr wireless link qual perc wlan0 downspe
  • 就分页分段内存而言的程序寿命

    我对 x86 Linux 机器中的分段和分页过程有一个令人困惑的概念 如果有人能澄清从开始到结束所涉及的所有步骤 我们将很高兴 x86 使用分页分段内存技术进行内存管理 任何人都可以解释一下从可执行的 elf 格式文件从硬盘加载到主内存到它
  • 执行“minikube start”命令时出现问题

    malik malik minikube start minikube v1 12 0 on Ubuntu 18 04 Using the docker driver based on existing profile Starting c
  • Linux 上的 Pervasive ODBC 错误 [01000][unixODBC][驱动程序管理器]无法打开 lib '/usr/local/psql/lib/odbcci.so':找不到文件

    我正在尝试让 Pervasive v10 客户端 ODBC 在 Centos 6 上运行 据我所知 没有 64 位 ODBC 客户端 因此我必须使用 32 位客户端 我终于成功安装了它 但尝试使用时出现以下错误 isql v mydsn 0
  • 如何获取 (Linux) 机器的 IP 地址?

    这个问题和之前问的几乎一样如何获取本地计算机的IP地址 https stackoverflow com questions 122208 get the ip address of local computer 问题 但是我需要找到一个的I
  • 在 Mono 上运行 .Net MVC5 应用程序

    我正在 Windows 上的 Visual Studio 2013 中开发 Net 4 5 1 MVC5 应用程序 现在我想知道 是否可以在Linux Ubuntu 12 04 上运行这个应用程序 可以使用OWIN吗 Owin 可以自托管运
  • .net-core:ILDASM / ILASM 的等效项

    net core 是否有相当于 ILDASM ILASM 的功能 具体来说 我正在寻找在 Linux 上运行的东西 因此为什么是 net core ildasm 和 ilasm 工具都是使用此存储库中的 CoreCLR 构建的 https
  • Bash - 在与当前终端分开的另一个终端中启动命令的新实例

    我有一个简单的 bash 脚本 test sh 设置如下 bin bash args if args 0 check capture then watch n 1 ls lag home user capture0 watch n 1 ls
  • 如何使用waf构建共享库?

    我想使用构建一个共享库waf http code google com p waf 因为它看起来比 GNU 自动工具更容易 更简洁 到目前为止 我实际上有几个与我开始编写的 wscript 有关的问题 VERSION 0 0 1 APPNA
  • Mac OS X 上的 /proc/self/cmdline / GetCommandLine 等效项是什么?

    如何在不使用 argc argv 的情况下访问 Mac OS X 上的命令行 在 Linux 上 我会简单地阅读 proc self cmdline or use GetCommandLine在 Windows 上 但我找不到 Mac OS
  • 在生产服务器上使用 Subversion 使文件生效的最佳方法是什么?

    目前我已经设置了 subversion 这样当我在 Eclipse PDT 中进行更改时 我可以提交更改 它们将保存在 home administrator 中项目文件 该文件具有 subversion 推荐的 branches tags
  • Linux 为一组进程保留一个处理器(动态)

    有没有办法将处理器排除在正常调度之外 也就是说 使用sched setaffinity我可以指示线程应该在哪个处理器上运行 但我正在寻找相反的情况 也就是说 我想从正常调度中排除给定的处理器 以便只有已明确调度的进程才能在那里运行 我还知道

随机推荐

  • Windows 8 Metro Stype App 学习笔记(五)--文件操作

    Windows 8 Metro Style App中文件操作都包含在Windows Storage命名空间中 其中包括StorageFolder StorageFile FileIO等类库 文件对象用StorageFile实现 文件头用St
  • 001 Python数据可视化之折线图

    话说 人是视觉的动物 本文从可视化入手来展现数据 试想一场景 某制造业工厂的CEO想了解两种成品的次品数及次品率 进而进行下一步决策 对于应用 excel在一定程度上可满足 如下图 对于开发 Python 1 2 作为受众度高的语言 3 在
  • AI实战:docker中用TensorBroad可视化模型训练过程

    前言 TensorBoard是TensorFlow自带的一个强大的可视化工具 目前支持7种可视化 Scalars Images Audio Graphs Distributions Histograms 和 Embeddings 主要功能如
  • 在C++中 char 到底是什么类型?

    在C 中 char 是一个用来表示字符的整数数据类型 它通常占据一个字节 8位 用于存储单个字符的ASCII码或其他字符编码的值 char 类型可以用于表示字符 比如字母 数字 标点符号等 每个字符在计算机内部都有一个对应的整数值 这个值可
  • 机器学习--使用朴素贝叶斯进行垃圾邮件分类

    一 学习背景 垃圾邮件的问题一直困扰着人们 传统的垃圾邮件分类的方法主要有 关键词法 和 校验码法 等 然而这两种方法效果并不理想 其中 如果使用的是 关键词 法 垃圾邮件中如果这个关键词被拆开则可能识别不了 比如 中奖 如果被拆成 中 奖
  • 学习Vue3第一天

    一 Vue简介 Vue是一款用于构建用户界面的 JavaScript 框架 它基于标准 HTML CSS 和 JavaScript 构建 并提供了一套声明式的 组件化的编程模型 帮助你高效地开发用户界面 无论是简单还是复杂的界面 Vue 都
  • Linux中的NFS共享

    1 NFS服务介绍 1 1什么是NFS服务 一 NFS工作原理 1 什么是NFS服务器 NFS就是Network File System的缩写 它最大的功能就是可以通过网络 让不同的机器 不同的操作系统可以共享彼此的文件 NFS服务器可以让
  • tr linux中文,linux中的tr用法详解

    tr命令可以对来自标准输入的字符进行替换 压缩和删除 它可以将一组字符成另一组字符 经常用来编写优美的单行命令 作用很强大 tr 选项 参数 c或 complerment 取代所有不属于第一字符集的字符 d或 delete 删除所有属于第一
  • Vysor 1.7.6 chrome 插件破解

    在你的Chrome扩展文件里面 找到 名为uglify js的文件 我的文件地址 C Users jin AppData Local Google Chrome User Data Default Extensions gidgenkbba
  • 数据库------DML操作

    DML的操作 数据操纵语言 指的是对表中的数据的增 删和改操作 添加数据 insert into 不推荐 方式一 insert into
  • python文字游戏源代码求年纪_Python实现猜年龄游戏代码实例

    1 在猜年龄的基础上编写登录 注册方法 并且把猜年龄游戏分函数处理 如 2 登录函数 3 注册函数 4 猜年龄函数 5 选择奖品函数 代码如下 import json real age 18 prize list 好迪洗发水 绿箭侠 小猪佩
  • 数据挖掘简介及模型介绍(一)

    1 简介 大数据时代正在唤醒企业通过利用客户数据获得竞争优势的机会 数据的广泛使用性和高度复杂性让仅使用传统决策技术来盈利变成不可能 这些传统方法主要使用电子表格 数据库查询和其它商业智能工具 另外 人们对从大数据中提取的有用信息和知识方法
  • CDH 是什么

    CDH 是由 Cloudera 公司构建 的Hadoop 稳定发行版 一 痛点 一个产品的出现肯定是为了解决用户的痛点 在大数据领域 我们这些使用Hadoop Hive Hbase等的开发者来说就是其用户 如果使用原生的ApacheHado
  • 【vue】安装vue3.X版本脚手架(图形化界面版)

    安装脚手架之前需要电脑已安装node与npm 首先按住 shift 鼠标右键 按下 在此处打开命令行窗口 进入命令行窗口 或者 win R 键 输入cmd 进入命令行窗口 输入 node v 与 npm v 查看有无安装node与npm 没
  • java JDK 环境配置教程

    最近在学习java 下面将window10系统为例配置Java JDK环境 1 右键单击此电脑进入属性 2 在打开的界面中选择高级系统设置 3 在系统属性中选中高级 之后点击环境变量 4 将安装的jdk路径复制 5 点击新建系统变量 6 将
  • 两个变量数据交换的方法

    这里给出了3个方法用来交换两个变量数据 1 最常见的创建一个临时变量来交换两个变量的数据 int a 1 b 2 int temp temp a a b b temp 这样就能通过创建的临时变量temp将变量a和b中的值进行交换 2 要是觉
  • node 报错 throw er; // Unhandled 'error' event 解决办法

    node 报错 Starting child process with node web js events js 183 throw er Unhandled error event Error listen EADDRINUSE 800
  • Android最强进程保活黑科技实现原理解密及方法

    启动Service mRemote transact transactCode mServiceData null 1 在 native 层进行 binder 通信 在Java层做进程复活的工作 这个方式是比较低效的 最好的方式是在 nat
  • 69.x的平方根(c++实现)

    给你一个非负整数 x 计算并返回 x 的 算术平方根 由于返回类型是整数 结果只保留 整数部分 小数部分将被 舍去 注意 不允许使用任何内置指数函数和算符 例如 pow x 0 5 或者 x 0 5 初看题目时 我 只觉得是一头雾水 不过这
  • 6.4 U-boot 移植

    一 ST 官方 U boot 编译测试 1 ST 官方 uboot 源码打补丁 1 1 获得 ST 官方的 uboot 源码 https www cnblogs com toutiegongzhu p 17578847 html 这里可以看