一、前言
最近在ODYSSEY-STM32MP157C板子上移植arm-trusted-firmware、u-boot以及linux(其实这个开发板官方是有提供完整的系统镜像的,重新移植的原因主要是官方镜像没有使用TF-A,而是使用Uboot-SPL替代TF-A作为FSBL启动)。本以为之前在另一块stm32mp157板子上面移植过这些东西所以应该问题不大,但是由于硬件设计的差异仍然是遇到了一些问题。最后还是花费了些时间解决问题,故写这篇笔记用来记录各环节遇到的问题及解决过程。
二、Trusted Firmware A (TF-A)
版本:arm-trusted-firmware-2.2-stm32mp-r2.3
1、问题
ST官方的开发板都是使用芯片的I2C4驱动PMIC,而这块开发板是用的I2C2接口,本以为将设备树中驱动PMIC节点的i2c4部分改为i2c2,然后添加上i2c2的pinctrl信息就可以了。然而并非如此,会报如下错误:
PANIC at PC : 0x2ffeeab3
Exception mode=0x00000016 at: 0x2ffeeab3
2、原因
I2C4或I2C6被定义为安全外设,而I2C2为非安全外设。
在源码drivers/st/pmic/stm32mp_pmic.c中PMIC初始化函数调用如下:
void initialize_pmic(void)
--> initialize_pmic_i2c() //从设备树获取pmic的i2c节点信息并初始化
--> register_non_secure_pmic()
--> stm32mp_register_non_secure_periph_iomem(i2c_handle.i2c_base_addr)
--> register_periph_iomem(base, SHRES_NON_SECURE)
由于在函数register_periph_iomem中没有定义I2C_BASE导致进入panic()函数。
3、解决方法
在文件plat/st/stm32mp1/stm32mp1_def.h中定义I2C2_BASE:
#define I2C2_BASE U(0x40013000)
然后修改文件plat/st/stm32mp1/stm32mp1_shared_resources.c中的函数register_periph_iomem如下:
case UART8_BASE:
case IWDG2_BASE:
case I2C2_BASE: //添加非安全外设I2C2
/* Allow drivers to register some non-secure resources */
VERBOSE('IO for non-secure resource 0x%xn',
(unsigned int)base);
if (state != SHRES_NON_SECURE) {
panic();
}
return;
default:
panic();
break;
三、U-Boot
版本:u-boot-2020.01-stm32mp-r2.2
1、问题
移植完成第一次进入u-boot首先出现如下提示:
invalid MAC address in OTP 00:00:00:00:00:00
Net:
Error: ethernet@5800a000 address not set.
No ethernet found.
设置ethaddr环境变量即可:
env set ethaddr 14:16:0B:0B:11:31
上面这个倒是不算问题,重点是接下来遇到的问题。在执行dhcp命令时遇到如下错误:
STM32MP> dhcp
EQOS_DMA_MODE_SWR stuckFAILED: -110STM32MP>
这显然是网卡有问题。
2、原因
查看硬件原理图以太网部分发现和ST官方的DK2开发板有些不同。官方开发板的千兆以太网(RGMII)的125MHZ时钟来自PHY芯片,而我手上这块开发板的设计默认是需要由MPU内部RCC提供125MHZ时钟。除此之外,PHY地址硬件设计上也不相同,需要修改。


在STM32MP157参考手册(RM0436)中的Figure 83对以太网时钟有详细的描述

由上图可知若要使用RCC作为125MHZ时钟来源则需要配置SYSCFG寄存器的ETH_CLK_SEL字段,除此之外还需要选择使用RCC的pll4_p_ck或是pll3_q_ck作为具体时钟来源(我选择的是PLL4P)。既然知道了问题所在,接下来就是修改代码适配硬件。
3、解决方法
首先是时钟部分的改动。因为使用了TF-A所以U-Boot配置为trusted模式,修改u-boot源码中的时钟配置是无效的,需要修改TF-A中的时钟配置。主要就是配置PLL4P输出125MHZ时钟,关于PLL的详细信息需要查阅参考手册(RM0436)的第10章RCC(Reset and clock control)的PLL章节。

在TF-A源码设备树的rcc节点中添加如下代码配置PLL4时钟频率:
&rcc {
......
/* VCO = 750.0 MHz => P = 125, Q = 62.5, R = 62.5 */
pll4: st,pll@3 {
compatible = 'st,stm32mp1-pll';
reg = <3>;
cfg = < 3 124 5 11 11 PQR(1,1,1) >;
};
......
};
cfg中参数含义如下:
cfg = 因此按照上述参数计算各部分时钟频率结果如下: F(ref_ck) = HSE / (DIVM + 1) Using the PLLs in integer mode For the PLL3 and PLL4, the VCO frequency (FVCO) is given by the following expression: F(VCO) = F(ref_ck) x (DIVN + 1) And the frequency at the output of the post-dividers is given by with y = P, Q or R: F(pll_y_ck) = F(VCO) / (DIVy + 1) VCO = HSE / (DIVM + 1) * (DIVN + 1) = 24MHZ / (3 + 1) * (124 + 1) = 750MHZ PLL4P = P = VCO / (DIVP + 1) = 750MHZ / (5 + 1) = 125MHZ PLL4Q = VCO / (DIVQ + 1) = 750MHZ / (11 + 1) = 62.5MHZ PLL4R = VCO / (DIVR + 1) = 750MHZ / (11 + 1) = 62.5MHZ 这样就得到了期望的125MHZ时钟。接着还需要将Ethernet的时钟选为PLL4P,在rcc节点修改如下内容: &rcc { ...... st,pkcs = < ...... - CLK_ETH_DISABLED //删除这个 + CLK_ETH_PLL4P //添加这个 ...... >; ...... }; 至此,千兆以太网125MHZ时钟频率就配置好了。接下来需要修改的就是u-boot源码的设备树中ethernet0节点内容,主要是修改时钟选择部分的内容。根据手册可知选择RCC作为千兆以太网125 MHz时钟需要将寄存器SYSCFG_PMCSETR的ETH_CLK_SEL位配置为1: 在源码drivers/net/dwc_eth_qos.c文件中eqos_probe_resources_stm32函数会调用board_interface_eth_init函数(文件路径board/st/stm32mp1/stm32mp1.c)根据设备树内容配置该寄存器该位,如下: /* eth init function : weak called in eqos driver */ int board_interface_eth_init(struct udevice *dev, phy_interface_t interface_type) { u8 *syscfg; u32 value; bool eth_clk_sel_reg = false; ...... /* Gigabit Ethernet 125MHz clock selection. */ eth_clk_sel_reg = dev_read_bool(dev, 'st,eth_clk_sel'); ...... syscfg = (u8 *)syscon_get_first_range(STM32MP_SYSCON_SYSCFG); ...... switch (interface_type) { ...... case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: case PHY_INTERFACE_MODE_RGMII_RXID: case PHY_INTERFACE_MODE_RGMII_TXID: if (eth_clk_sel_reg) value = SYSCFG_PMCSETR_ETH_SEL_RGMII | SYSCFG_PMCSETR_ETH_CLK_SEL; else value = SYSCFG_PMCSETR_ETH_SEL_RGMII; debug('%s: PHY_INTERFACE_MODE_RGMIIn', __func__); break; ...... } /* clear and set ETH configuration bits */ writel(SYSCFG_PMCSETR_ETH_SEL_MASK | SYSCFG_PMCSETR_ETH_SELMII | SYSCFG_PMCSETR_ETH_REF_CLK_SEL | SYSCFG_PMCSETR_ETH_CLK_SEL, syscfg + SYSCFG_PMCCLRR); writel(value, syscfg + SYSCFG_PMCSETR); return 0; } 因此需要在设备树ethernet0节点下添加st,eth_clk_sel(文件路径arch/arm/dts/stm32mp151.dtsi)如下: ethernet0: ethernet@5800a000 { ...... st,eth_clk_sel; ...... }; 但是只是这么做还不够,进入u-boot会提示如下: Net: No phy clock provided -61eth0: ethernet@5800a000 根据提示可以定位到代码位置在drivers/net/dwc_eth_qos.c的eqos_probe_resources_stm32函数中: /* Get ETH_CLK clocks (optional) */ ret = clk_get_by_name(dev, 'eth-ck', &eqos->clk_ck); if (ret) pr_warn('No phy clock provided %d', ret); 因此在设备树ethernet0添加eth-ck如下: ethernet0: ethernet@5800a000 { ...... clock-names = 'stmmaceth', 'mac-clk-tx', 'mac-clk-rx', + 'eth-ck', //添加这行 'ethstp'; ...... st,eth_clk_sel; ...... }; 但是但是,这么做依旧不够,修改后u-boot执行dhcp命令报错如下: STM32MP> dhcp stm32mp1_clk_get_id: clk id 112 not found clk_enable(clk_ck) failed: -22eqos_start_clks() failed: -22FAILED: -22STM32MP> 因为添加了时钟名后还需要添加对应的时钟节点,因此在设备树ethernet0节点添加ETHCK_K如下: ethernet0: ethernet@5800a000 { ...... clock-names = 'stmmaceth', 'mac-clk-tx', 'mac-clk-rx', 'eth-ck', 'ethstp'; clocks = <&rcc ETHMAC>, <&rcc ETHTX>, <&rcc ETHRX>, + <&rcc ETHCK_K>, //添加这行 <&rcc ETHSTP>; st,eth_clk_sel; ...... }; 最后还得修改phy地址以及添加phy复位引脚(需和硬件设计一致),否则会有如下报错提示: 地址错误: STM32MP> dhcp Could not get PHY for ethernet@5800a000: addr 0 phy_connect() failedFAILED: 0 复位引脚缺失错误 Net: gpio_request_by_name(phy reset) not provided -2eth0: ethernet@5800a000 修改如下: ðernet0 { ...... mdio0 { ...... phy0: ethernet-phy@7 { reg = <7>; //phy地址 reset-gpios = <&gpiog 0 GPIO_ACTIVE_LOW>; //phy复位引脚 }; }; }; 复位操作在源码drivers/net/dwc_eth_qos.c函数eqos_probe_resources_stm32匹配设备树,函数eqos_start_resets_stm32执行。 以上修改完成后重新编译u-boot启动后执行网络操作命令就正常了: STM32MP> dhcp ethernet@5800a000 Waiting for PHY auto negotiation to complete........... done BOOTP broadcast 1 BOOTP broadcast 2 BOOTP broadcast 3 BOOTP broadcast 4 DHCP client bound to address 192.168.10.85 (2875 ms) STM32MP> 四、Linux Kernel 版本:linux-5.4-stm32mp-r2.4 1、问题 既然U-Boot部分网络有问题,那么在Linux中也会有同样的问题。但是在linux中只做u-boot中的改动网络仍然无法正常工作,会报如下错误: root@arm:~# [ 316.042400] stm32-dwmac 5800a000.ethernet eth0: no phy at addr -1 [ 316.047061] stm32-dwmac 5800a000.ethernet eth0: stmmac_open: Cannot attach to PHY (error: -19) [ 316.124044] stm32-dwmac 5800a000.ethernet eth0: no phy at addr -1 [ 316.128703] stm32-dwmac 5800a000.ethernet eth0: stmmac_open: Cannot attach to PHY (error: -19) [ 316.186944] stm32-dwmac 5800a000.ethernet eth0: no phy at addr -1 [ 316.191693] stm32-dwmac 5800a000.ethernet eth0: stmmac_open: Cannot attach to PHY (error: -19) [ 316.242397] stm32-dwmac 5800a000.ethernet eth0: no phy at addr -1 [ 316.247066] stm32-dwmac 5800a000.ethernet eth0: stmmac_open: Cannot attach to PHY (error: -19) 2、原因 在Linux设备树的ethernet0节点还需要添加一些phy芯片信息(这个板子是KSZ9031)并且要配置相关的驱动。 3、解决方法 make menuconfig Linux/arm 5.4.192 Kernel Configuration Device Drivers ---> [*] Network device support ---> -*- PHY Device support and infrastructure ---> <*> Micrel PHYs 完整的ethernet0设备树内容如下: ethernet0: ethernet@5800a000 { compatible = 'st,stm32mp1-dwmac', 'snps,dwmac-4.20a'; reg = <0x5800a000 0x2000>; reg-names = 'stmmaceth'; interrupts-extended = <&intc GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>, <&exti 70 IRQ_TYPE_LEVEL_HIGH>; interrupt-names = 'macirq', 'eth_wake_irq'; clock-names = 'stmmaceth', 'mac-clk-tx', 'mac-clk-rx', + 'eth-ck', //添加这行 'ethstp'; clocks = <&rcc ETHMAC>, <&rcc ETHTX>, <&rcc ETHRX>, + <&rcc ETHCK_K>, //添加这行 <&rcc ETHSTP>; + st,eth-clk-sel; //添加这行 st,syscon = <&syscfg 0x4>; snps,mixed-burst; snps,pbl = <2>; snps,en-tx-lpi-clockgating; snps,axi-config = <&stmmac_axi_config_0>; snps,tso; power-domains = <&pd_core>; status = 'disabled'; stmmac_axi_config_0: stmmac-axi-config { snps,wr_osr_lmt = <0x7>; snps,rd_osr_lmt = <0x7>; snps,blen = <0 0 0 0 16 8 4>; }; }; ðernet0 { status = 'okay'; pinctrl-0 = <ðernet0_rgmii_pins_a>; pinctrl-1 = <ðernet0_rgmii_pins_sleep_a>; pinctrl-names = 'default', 'sleep'; 
上一篇:STM32MP157移植Qt5.12.10
下一篇:ThreadX——IPC应用之消息队列
推荐阅读最新更新时间:2026-03-25 11:29
- 用于 7VIN 至 16VIN、1.5V 和 1.2V 输出的 LTM4628EV DC/DC 模块稳压器的典型应用电路
- 使用 Analog Devices 的 LTC3728LIGN 的参考设计
- DER-406 - 适用于 A19 灯的 5.76 W 高 PF 非隔离降压-升压型 TRIAC 调光 LED 驱动器
- ADR5045B 5V 输出精密微功率并联模式电压基准的典型应用
- LT3970EDDB-3.42 2.5V 降压转换器的典型应用
- MC78M08BDTG 8V 电流调节器的典型应用
- LT1021DCN8-5 精密电压基准的典型应用
- DER-282 - 100W, 扁平(11 mm), LLC DC-DC转换器
- REF193 低压差开尔文连接电压基准的典型应用电路
- LT3088EM 线性稳压器用于添加软启动的典型应用



【Follow me第三季第4期】CY8CPROTO-063-BLE开发任务汇总代码
英飞凌PSoC 6 电位器控制LED闪烁状态并水墨屏显示——源码
现代雷达系统的信号设计
5962-89541022A
BFR340T






京公网安备 11010802033920号