当前位置: 首页 > news >正文

(四)正点原子STM32MP135移植——u-boot移植

一、概述

        u-boot概述就不概述了,u-boot、kernel、dtb三件套,dddd

        

        经过国庆艰苦奋战,已经成功把所有功能移植好了

二、编译官方代码

        进入u-boot的目录

2.1 解压源码、打补丁

/* 解压源码 */
tar xf u-boot-stm32mp-v2022.10-stm32mp-r1-r0.tar.xz /* 进入源码目录 */
cd u-boot-stm32mp-v2022.10-stm32mp-r1//* 打补丁 */
for p in `ls -1 ../*.patch`; do patch -p1 < $p; done

2.2 修改Makefile.sdk

        打开Makefile.sdk,把DEPLOYDIR目录改成这个:

DEPLOYDIR ?= $(SRC_PATH)/../../FIP_artifacts/u-boot

         然后第12行开始,我们把157的屏蔽掉,留下135

# Init default config settings
# UBOOT_CONFIGS += trusted
# UBOOT_DEFCONFIG_trusted += stm32mp15_defconfig
# UBOOT_BINARY_stm32mp15_defconfig ?= u-boot.dtb
# UBOOT_DEVICETREE_stm32mp15_defconfig ?=  stm32mp157c-ed1 stm32mp157f-ed1 stm32mp157a-ev1 stm32mp157c-ev1 stm32mp157d-ev1 stm32mp157f-ev1 stm32mp157a-dk1 stm32mp157d-dk1 stm32mp157c-dk2 stm32mp157f-dk2
# Init default config settings
UBOOT_CONFIGS += trusted
UBOOT_DEFCONFIG_trusted += stm32mp13_defconfig
UBOOT_BINARY_stm32mp13_defconfig ?= u-boot.dtb
UBOOT_DEVICETREE_stm32mp13_defconfig ?=  stm32mp135f-dk
DEVICETREE ?= stm32mp135f-dk

2.3 配置编译环境

/* 加载环境 */
source /opt/st/stm32mp1/4.2.1-openstlinux-6.1-yocto-mickledore-mp1-v23.06.21/environment-setup-cortexa7t2hf-neon-vfpv4-ostl-linux-gnueabi/* 配置环境变量 */
export FIP_DEPLOYDIR_ROOT=$PWD/../../FIP_artifacts

不要关了这个终端,它已经配置好了,关于这部分的配置,可以看上一篇关于TF-A的解释比较详细。

2.4 编译

make -f ../Makefile.sdk all

由于之前我们编译过了stm32mp135f-dk的TF-A和optee,这里编译完成之后,会直接调用fiptool工具给我们打包生成fip-stm32mp135-atk-optee.bin到FIP文件夹里。

[fiptool] Create fip-stm32mp135f-dk-optee.bin fip binary into 'FIP_DEPLOYDIR_FIP' folder...
[fiptool] Done

三、移植

3.1 复制官方文件

/* 进入设备树目录 */
cd arch/arm/dts/cp stm32mp135f-dk.dts stm32mp135-atk.dts
cp stm32mp13-pinctrl.dtsi stm32mp13-pinctrl-atk.dtsi
cp stm32mp135f-dk-u-boot.dtsi stm32mp135-atk-u-boot.dtsi/* 回到源码根目录 */
cd ../../../

3.2 修改头文件

        打开stm32mp135-atk.dts,把引脚头文件改成我们的

// #include "stm32mp13-pinctrl.dtsi"
#include "stm32mp13-pinctrl-atk.dtsi"

3.3 修改电源

        首先找到scmi_regu节点,把里面的内容删,但是节点别删,还得留下一个scmi_v1v8_periph

&scmi_regu {scmi_vddcpu: voltd-vddcpu {reg = <VOLTD_SCMI_STPMIC1_BUCK1>;regulator-name = "vddcpu";};scmi_vdd: voltd-vdd {reg = <VOLTD_SCMI_STPMIC1_BUCK3>;regulator-name = "vdd";};scmi_vddcore: voltd-vddcore {reg = <VOLTD_SCMI_STPMIC1_BUCK4>;regulator-name = "vddcore";};scmi_vdd_adc: voltd-vdd-adc {reg = <VOLTD_SCMI_STPMIC1_LDO1>;regulator-name = "vdd_adc";};scmi_vdd_usb: voltd-vdd-usb {reg = <VOLTD_SCMI_STPMIC1_LDO4>;regulator-name = "vdd_usb";};scmi_vdd_sd: voltd-vdd-sd {reg = <VOLTD_SCMI_STPMIC1_LDO5>;regulator-name = "vdd_sd";};scmi_v1v8_periph: voltd-v1v8-periph {reg = <VOLTD_SCMI_STPMIC1_LDO6>;regulator-name = "v1v8_periph";};scmi_v3v3_sw: voltd-v3v3-sw {reg = <VOLTD_SCMI_STPMIC1_PWR_SW2>;regulator-name = "v3v3_sw";};
};

修改过后如下:如果有大佬知道怎么解决麻烦底下留言帮帮忙

/* 这一段不知道怎么解决,不能删
删除之后,烧写到u-boot阶段,会被强行复位,但是使用分立电源又不行
*/
&scmi_regu {scmi_v1v8_periph: voltd-v1v8-periph {reg = <VOLTD_SCMI_STPMIC1_LDO6>;regulator-name = "v1v8_periph";};
};

笔者尝试过在根节点下加入对1.8V电源的描述,但是并不行,烧录的时候会直接被迫重启,刚学linux不久,大佬带带

/* 想用分立电源代替掉scmi_v1v8_periph,但是没有实现 */// v1v8: v1v8 {//     compatible = "regulator-fixed";// 	regulator-name = "v1v8_periph";//     regulator-min-microvolt = <1800000>;//     regulator-max-microvolt = <1800000>;//     regulator-off-in-suspend;//     regulator-always-on;// };

删除scmi电源之后,在根节点下面加入我们的电源描述,和之前的一样

vddcore: vddcore {compatible = "regulator-fixed";regulator-name = "vddcore";regulator-min-microvolt = <1200000>;regulator-max-microvolt = <1350000>;regulator-off-in-suspend;regulator-always-on;};vddcpu: vddcpu {compatible = "regulator-fixed";regulator-name = "vddcpu";regulator-min-microvolt = <1350000>;regulator-max-microvolt = <1350000>;regulator-off-in-suspend;regulator-always-on;};v3v3: v3v3 {compatible = "regulator-fixed";regulator-name = "v3v3";regulator-min-microvolt = <3300000>;regulator-max-microvolt = <3300000>;regulator-off-in-suspend;regulator-always-on;};vbus_otg: vbus_otg {compatible = "regulator-fixed";regulator-name = "vbus_otg";regulator-min-microvolt = <5000000>;regulator-max-microvolt = <5000000>;regulator-off-in-suspend;regulator-always-on;};vdd: vdd {compatible = "regulator-fixed";regulator-name = "vdd";regulator-min-microvolt = <3300000>;regulator-max-microvolt = <3300000>;regulator-off-in-suspend;regulator-always-on;};vdd_usb: vdd_usb {compatible = "regulator-fixed";regulator-name = "vdd_usb";regulator-min-microvolt = <3300000>;regulator-max-microvolt = <3300000>;regulator-off-in-suspend;regulator-always-on;};

3.4 删除无关节点

        可以删除(建议删除)的节点如下

1.        &i2c5全部

2.        &uart8 &usart1 &usart2三个串口

3.        根节点下的gpio-keys

4.        根节点下aliases里的几个串口,只留下串口4

5.        &dcmipp节点

6.        &spi5  &timer3  &timer4  &timer8  &timer14这几个都可以删了

3.5 修改USB OTG

        正点原子的OTG使用的是usbphyc_port1,而usbphyc_port0是host,找到&usbphyc_port1节点,只需要修改该它的电源即可。

&usbphyc_port1 {// phy-supply = <&scmi_vdd_usb>;    /* 删了原来的 */phy-supply = <&vdd_usb>;st,current-boost-microamp = <1000>;st,decrease-hs-slew-rate;st,tune-hs-dc-level = <2>;st,enable-hs-rftime-reduction;st,trim-hs-current = <11>;st,trim-hs-impedance = <2>;st,tune-squelch-level = <1>;st,enable-hs-rx-gain-eq;st,no-hs-ftime-ctrl;st,no-lsfs-sc;
};

 修改&usbotg_hs

&usbotg_hs {phys = <&usbphyc_port1 0>;phy-names = "usb2-phy";usb-role-switch;dr_mode = "otg";pinctrl-0 = <&usbotg_hs_pins_a>;pinctrl-names = "default";vbus-supply = <&vbus_otg>;status = "okay";
};

3.6 修改USB节点

        同OTG,先把电源改了,下面那个connector好像不要也行

&usbphyc_port0 {// phy-supply = <&scmi_vdd_usb>;    /* 删了原来的 */phy-supply = <&vdd_usb>;st,current-boost-microamp = <1000>;st,decrease-hs-slew-rate;st,tune-hs-dc-level = <2>;st,enable-hs-rftime-reduction;st,trim-hs-current = <11>;st,trim-hs-impedance = <2>;st,tune-squelch-level = <1>;st,enable-hs-rx-gain-eq;st,no-hs-ftime-ctrl;st,no-lsfs-sc;/** Hack to keep hub active if wakeup source is enabled* otherwise the hub will wakeup the port0 as soon as the v3v3_sw is disabled*/connector {compatible = "usb-a-connector";vbus-supply = <&v3v3>;};
};

修改usbh_ehci节点:

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

3.7 修改TF卡和emmc节点

这里,偷个懒,直接把原子的复制过来了,直接替换掉

&sdmmc1 {pinctrl-names = "default", "opendrain", "sleep";pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_clk_pins_a>;pinctrl-1 = <&sdmmc1_b4_od_pins_a &sdmmc1_clk_pins_a>;pinctrl-2 = <&sdmmc1_b4_sleep_pins_a>;cd-gpios = <&gpiof 15 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;disable-wp;st,neg-edge;no-1-8-v;bus-width = <4>;vmmc-supply = <&v3v3>;status = "okay";
};/* EMMC */
&sdmmc2 {pinctrl-names = "default", "opendrain", "sleep";pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_b4_b7_pins_a &sdmmc2_clk_pins_a>;pinctrl-1 = <&sdmmc2_b4_od_pins_a &sdmmc2_b4_b7_od_pins_a &sdmmc2_clk_pins_a>;pinctrl-2 = <&sdmmc2_b4_sleep_pins_a &sdmmc2_b4_b7_sleep_pins_a>;non-removable;st,neg-edge;mmc-ddr-3_3v;no-1-8-v;bus-width = <8>;vmmc-supply = <&v3v3>;#address-cells = <1>;#size-cells = <0>;status = "okay";
};

3.8 修改ltdc

        在根节点下添加:

atk_pinctrl_lcd {gpior = <&gpioe 9 GPIO_ACTIVE_LOW>;gpiog = <&gpioa 15 GPIO_ACTIVE_LOW>;gpiob = <&gpioe 15 GPIO_ACTIVE_LOW>;};

        修改panel_rgb:panel-rgb,这里继续偷懒,直接复制粘贴了

panel_rgb: panel-rgb {compatible = "simple-panel";backlight = <&panel_backlight>;power-supply = <&v3v3>;status = "okay";port {panel_in_rgb: endpoint {remote-endpoint = <&ltdc_out_rgb>;};};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 参数 */};};};

        修改panel_backlight,ST用的是PE 12,正点原子用的是PD 13

panel_backlight: panel-backlight {compatible = "gpio-backlight";gpios = <&gpiod 13 GPIO_ACTIVE_HIGH>;default-on;status = "okay";};

        然后向pinctrl追加:

&pinctrl {gpio_r:gpio_r {pins {pinmux = <STM32_PINMUX('E', 9, GPIO)>; /* PE9.GPIO */bias-pull-up;drive-push-pull;};};gpio_g:gpio_g {pins {pinmux = <STM32_PINMUX('A', 15, GPIO)>; /* PA15.GPIO */bias-pull-up;drive-push-pull;};};gpio_b:gpio_b {pins {pinmux = <STM32_PINMUX('E', 15, GPIO)>; /* PE15.GPIO */bias-pull-up;drive-push-pull;};};
};

3.9 修改网络

        找到eth1和eth2两个节点,直接覆盖修改

&eth1 {status = "okay";pinctrl-0 = <&eth1_rgmii_pins_a>;pinctrl-1 = <&eth1_rgmii_sleep_pins_a>;pinctrl-names = "default", "sleep";phy-mode = "rgmii-id";max-speed = <1000>;phy-handle = <&phy0_eth1>;nvmem-cells = <&ethernet_mac1_address>;nvmem-cell-names = "mac-address";mdio1 {#address-cells = <1>;#size-cells = <0>;compatible = "snps,dwmac-mdio";phy0_eth1: ethernet-phy@1 {reg = <1>;};};
};/* 需要用eth2就取消注释即可 */
// &eth2 {
// 	status = "okay";
// 	pinctrl-0 = <&eth2_rgmii_pins_a>;
// 	pinctrl-1 = <&eth2_rgmii_sleep_pins_a>;
// 	pinctrl-names = "default", "sleep";
// 	phy-mode = "rgmii-id";
// 	max-speed = <1000>;
// 	phy-handle = <&phy0_eth2>;
// 	phy-supply = <&v3v3>;
// 	nvmem-cells = <&ethernet_mac2_address>;
// 	nvmem-cell-names = "mac-address";// 	mdio1 {
// 		#address-cells = <1>;
// 		#size-cells = <0>;
// 		compatible = "snps,dwmac-mdio";
// 		phy0_eth2: ethernet-phy@2 {
// 			reg = <2>;
// 		};
// 	};
// };

3.10 修改引脚

        偷个懒,直接照搬原子的引脚配置即可

// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
/** Copyright (C) STMicroelectronics 2021 - All Rights Reserved* Author: Alexandre Torgue <alexandre.torgue@foss.st.com>*/
#include <dt-bindings/pinctrl/stm32-pinfunc.h>&pinctrl {eth1_rgmii_pins_a: eth1-rgmii-1 {pins1 {pinmux = <STM32_PINMUX('F', 12, AF11)>, /* ETH1_RGMII_CLK125 */<STM32_PINMUX('C', 1, AF11)>, 	/* ETH1_RGMII_GTX_CLK */<STM32_PINMUX('G', 13, AF11)>, /* ETH1_RGMII_TXD0 */<STM32_PINMUX('G', 14, AF11)>, /* ETH1_RGMII_TXD1 */<STM32_PINMUX('C', 2, AF11)>, 	/* ETH1_RGMII_TXD2 */<STM32_PINMUX('E', 5, AF10)>, 	/* ETH1_RGMII_TXD3 */<STM32_PINMUX('B', 11, AF11)>, /* ETH1_RGMII_TX_CTL */<STM32_PINMUX('A', 2, AF11)>, 	/* ETH1_MDIO */<STM32_PINMUX('G', 2, AF11)>; 	/* ETH1_MDC */bias-disable;drive-push-pull;slew-rate = <2>;};pins2 {pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH1_RGMII_RXD0 */<STM32_PINMUX('C', 5, AF11)>, /* ETH1_RGMII_RXD1 */<STM32_PINMUX('B', 0, AF11)>, /* ETH1_RGMII_RXD2 */<STM32_PINMUX('B', 1, AF11)>, /* ETH1_RGMII_RXD3 */<STM32_PINMUX('A', 1, AF11)>, /* ETH1_RGMII_RX_CLK */<STM32_PINMUX('A', 7, AF11)>; /* ETH1_RGMII_RX_CTL */bias-disable;};};eth1_rgmii_sleep_pins_a: eth1-rgmii-sleep-1 {pins1 {pinmux = <STM32_PINMUX('F', 12, ANALOG)>, /* ETH1_RGMII_CLK125 */<STM32_PINMUX('C', 1, ANALOG)>, 	/* ETH1_RGMII_GTX_CLK */<STM32_PINMUX('G', 13, ANALOG)>, 	/* ETH1_RGMII_TXD0 */<STM32_PINMUX('G', 14, ANALOG)>, 	/* ETH1_RGMII_TXD1 */<STM32_PINMUX('C', 2, ANALOG)>, 	/* ETH1_RGMII_TXD2 */<STM32_PINMUX('E', 5, ANALOG)>, 	/* ETH1_RGMII_TXD3 */<STM32_PINMUX('B', 11, ANALOG)>, 	/* ETH1_RGMII_TX_CTL */<STM32_PINMUX('A', 2, ANALOG)>, 	/* ETH1_MDIO */<STM32_PINMUX('G', 2, ANALOG)>, 	/* ETH1_MDC */<STM32_PINMUX('C', 4, ANALOG)>, 	/* ETH1_RGMII_RXD0 */<STM32_PINMUX('C', 5, ANALOG)>, 	/* ETH1_RGMII_RXD1 */<STM32_PINMUX('B', 0, ANALOG)>, 	/* ETH1_RGMII_RXD2 */<STM32_PINMUX('B', 1, ANALOG)>, 	/* ETH1_RGMII_RXD3 */<STM32_PINMUX('A', 1, ANALOG)>, 	/* ETH1_RGMII_RX_CLK */<STM32_PINMUX('A', 7, ANALOG)>; 	/* ETH1_RGMII_RX_CTL */};};eth2_rgmii_pins_a: eth2-rgmii-2 {pins1 {pinmux = <STM32_PINMUX('H', 2, AF13)>, /* ETH2_RGMII_CLK125 */<STM32_PINMUX('F', 7, AF11)>, 	/* ETH2_RGMII_TXD0 */<STM32_PINMUX('G', 11, AF10)>, /* ETH2_RGMII_TXD1 */<STM32_PINMUX('G', 1, AF10)>, 	/* ETH2_RGMII_TXD2 */<STM32_PINMUX('E', 6, AF11)>, 	/* ETH2_RGMII_TXD3 */<STM32_PINMUX('G', 3, AF10)>, 	/* ETH2_RGMII_GTX_CLK */<STM32_PINMUX('F', 6, AF11)>, 	/* ETH2_RGMII_TX_CTL */<STM32_PINMUX('B', 2, AF11)>, 	/* ETH2_MDIO */<STM32_PINMUX('G', 5, AF10)>; 	/* ETH2_MDC */bias-disable;drive-push-pull;slew-rate = <2>;};pins2 {pinmux = <STM32_PINMUX('F', 4, AF11)>, /* ETH2_RGMII_RXD0 */<STM32_PINMUX('E', 2, AF10)>, 	/* ETH2_RGMII_RXD1 */<STM32_PINMUX('H', 6, AF12)>, 	/* ETH2_RGMII_RXD2 */<STM32_PINMUX('A', 8, AF11)>, 	/* ETH2_RGMII_RXD3 */<STM32_PINMUX('H', 11, AF11)>, /* ETH2_RGMII_RX_CLK */<STM32_PINMUX('G', 12, AF12)>; /* ETH2_RGMII_RX_CTL */bias-disable;};};eth2_rgmii_sleep_pins_a: eth2-rgmii-sleep-2 {pins1 {pinmux = <STM32_PINMUX('H', 2, ANALOG)>, /* ETH2_RGMII_CLK125 */<STM32_PINMUX('F', 7, ANALOG)>, 	/* ETH2_RGMII_TXD0 */<STM32_PINMUX('G', 11, ANALOG)>, 	/* ETH2_RGMII_TXD1 */<STM32_PINMUX('G', 1, ANALOG)>, 	/* ETH2_RGMII_TXD2 */<STM32_PINMUX('E', 6, ANALOG)>, 	/* ETH2_RGMII_TXD3 */<STM32_PINMUX('G', 3, ANALOG)>, 	/* ETH2_RGMII_GTX_CLK */<STM32_PINMUX('F', 6, ANALOG)>, 	/* ETH2_RGMII_TX_CTL */<STM32_PINMUX('B', 2, ANALOG)>, 	/* ETH2_MDIO */<STM32_PINMUX('G', 5, ANALOG)>, 	/* ETH2_MDC */<STM32_PINMUX('F', 4, ANALOG)>, 	/* ETH2_RGMII_RXD0 */<STM32_PINMUX('E', 2, ANALOG)>, 	/* ETH2_RGMII_RXD1 */<STM32_PINMUX('H', 6, ANALOG)>, 	/* ETH2_RGMII_RXD2 */<STM32_PINMUX('A', 8, ANALOG)>, 	/* ETH2_RGMII_RXD3 */<STM32_PINMUX('H', 11, ANALOG)>, 	/* ETH2_RGMII_RX_CLK */<STM32_PINMUX('G', 12, ANALOG)>; 	/* ETH2_RGMII_RX_CTL */};};ltdc_pins_a: ltdc-0 {pins {pinmux = <STM32_PINMUX('D',  9, AF13)>, /* LCD_CLK */<STM32_PINMUX('H',  10, AF13)>, /* LCD_HSYNC */<STM32_PINMUX('G',  4, AF11)>, /* LCD_VSYNC */ <STM32_PINMUX('H',  9, AF11)>, /* LCD_DE */<STM32_PINMUX('E', 11, AF9)>,  /* LCD_R0 */<STM32_PINMUX('D',  4, AF11)>, /* LCD_R1 */<STM32_PINMUX('G',  7, AF14)>, /* LCD_R2 */<STM32_PINMUX('B', 12, AF13)>, /* LCD_R3 */<STM32_PINMUX('D', 14, AF14)>, /* LCD_R4 */<STM32_PINMUX('E',  7, AF14)>, /* LCD_R5 */<STM32_PINMUX('E', 13, AF14)>, /* LCD_R6 */<STM32_PINMUX('E',  9, AF14)>, /* LCD_R7 */<STM32_PINMUX('F',  5, AF9)>,  /* LCD_G0 */<STM32_PINMUX('F',  1, AF14)>, /* LCD_G1 */<STM32_PINMUX('H', 13, AF14)>, /* LCD_G2 */<STM32_PINMUX('F',  3, AF14)>, /* LCD_G3 */<STM32_PINMUX('E', 12, AF11)>, /* LCD_G4 */<STM32_PINMUX('G',  0, AF14)>, /* LCD_G5 */<STM32_PINMUX('A', 12, AF14)>, /* LCD_G6 */<STM32_PINMUX('A', 15, AF11)>, /* LCD_G7 */<STM32_PINMUX('D',  5, AF13)>, /* LCD_B0 */<STM32_PINMUX('G',  8, AF7)>,  /* LCD_B1 */<STM32_PINMUX('D', 10, AF14)>, /* LCD_B2 */<STM32_PINMUX('F',  2, AF14)>, /* LCD_B3 */<STM32_PINMUX('G', 15, AF11)>, /* LCD_B4 */<STM32_PINMUX('D', 15, AF14)>, /* LCD_B5 */<STM32_PINMUX('D',  1, AF11)>, /* LCD_B6 */<STM32_PINMUX('E', 15, AF14)>; /* LCD_B7 */bias-disable;drive-push-pull;slew-rate = <1>;};};ltdc_sleep_pins_a: ltdc-sleep-0 {pins {pinmux = <STM32_PINMUX('D',  9, ANALOG)>, /* LCD_CLK */<STM32_PINMUX('H',  10, ANALOG)>, /* LCD_HSYNC */<STM32_PINMUX('G',  4, ANALOG)>, /* LCD_VSYNC */<STM32_PINMUX('H',  9, ANALOG)>, /* LCD_DE */<STM32_PINMUX('E', 11, ANALOG)>, /* LCD_R0 */<STM32_PINMUX('D',  4, ANALOG)>, /* LCD_R1 */				 <STM32_PINMUX('G',  7, ANALOG)>, /* LCD_R2 */<STM32_PINMUX('B', 12, ANALOG)>, /* LCD_R3 */<STM32_PINMUX('D', 14, ANALOG)>, /* LCD_R4 */<STM32_PINMUX('E',  7, ANALOG)>, /* LCD_R5 */<STM32_PINMUX('E', 13, ANALOG)>, /* LCD_R6 */<STM32_PINMUX('E',  9, ANALOG)>, /* LCD_R7 */<STM32_PINMUX('F',  5, ANALOG)>, /* LCD_G0 */<STM32_PINMUX('F',  1, ANALOG)>, /* LCD_G1 */				 <STM32_PINMUX('H', 13, ANALOG)>, /* LCD_G2 */<STM32_PINMUX('F',  3, ANALOG)>, /* LCD_G3 */<STM32_PINMUX('E', 12, ANALOG)>, /* LCD_G4 */<STM32_PINMUX('G',  0, ANALOG)>, /* LCD_G5 */<STM32_PINMUX('A', 12, ANALOG)>, /* LCD_G6 */<STM32_PINMUX('A', 15, ANALOG)>, /* LCD_G7 */<STM32_PINMUX('D',  5, ANALOG)>, /* LCD_B0 */<STM32_PINMUX('G',  8, ANALOG)>, /* LCD_B1 */				 <STM32_PINMUX('D', 10, ANALOG)>, /* LCD_B2 */<STM32_PINMUX('F',  2, ANALOG)>, /* LCD_B3 */<STM32_PINMUX('G', 15, ANALOG)>, /* LCD_B4 */<STM32_PINMUX('D', 15, ANALOG)>, /* LCD_B5 */<STM32_PINMUX('D',  1, ANALOG)>, /* LCD_B6 */<STM32_PINMUX('E', 15, ANALOG)>; /* LCD_B7 */};};sdmmc1_b4_pins_a: sdmmc1-b4-0 {pins {pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */<STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */<STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */<STM32_PINMUX('C', 11, AF12)>, /* SDMMC1_D3 */<STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */slew-rate = <1>;drive-push-pull;bias-disable;};};sdmmc1_b4_od_pins_a: sdmmc1-b4-od-0 {pins1 {pinmux = <STM32_PINMUX('C', 8, AF12)>, /* SDMMC1_D0 */<STM32_PINMUX('C', 9, AF12)>, /* SDMMC1_D1 */<STM32_PINMUX('C', 10, AF12)>, /* SDMMC1_D2 */<STM32_PINMUX('C', 11, AF12)>; /* SDMMC1_D3 */slew-rate = <1>;drive-push-pull;bias-disable;};pins2 {pinmux = <STM32_PINMUX('D', 2, AF12)>; /* SDMMC1_CMD */slew-rate = <1>;drive-open-drain;bias-disable;};};sdmmc1_b4_sleep_pins_a: sdmmc1-b4-sleep-0 {pins {pinmux = <STM32_PINMUX('C', 8, ANALOG)>, /* SDMMC1_D0 */<STM32_PINMUX('C', 9, ANALOG)>, /* SDMMC1_D1 */<STM32_PINMUX('C', 10, ANALOG)>, /* SDMMC1_D2 */<STM32_PINMUX('C', 11, ANALOG)>, /* SDMMC1_D3 */<STM32_PINMUX('C', 12, ANALOG)>, /* SDMMC1_CK */<STM32_PINMUX('D', 2, ANALOG)>; /* SDMMC1_CMD */};};sdmmc1_clk_pins_a: sdmmc1-clk-0 {pins {pinmux = <STM32_PINMUX('C', 12, AF12)>; /* SDMMC1_CK */slew-rate = <1>;drive-push-pull;bias-disable;};};sdmmc2_b4_pins_a: sdmmc2-b4-0 {pins {pinmux = <STM32_PINMUX('B', 14, AF10)>, /* SDMMC2_D0 */<STM32_PINMUX('B', 15, AF10)>, /* SDMMC2_D1 */<STM32_PINMUX('B', 3, AF10)>, /* SDMMC2_D2 */<STM32_PINMUX('B', 4, AF10)>, /* SDMMC2_D3 */<STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */slew-rate = <1>;drive-push-pull;bias-pull-up;};};sdmmc2_b4_b7_pins_a: sdmmc2-b4-b7-0 {pins {pinmux = <STM32_PINMUX('F', 0, AF10)>, /* SDMMC2_D4 */<STM32_PINMUX('B', 9, AF10)>, /* SDMMC2_D5 */<STM32_PINMUX('C', 6, AF10)>, /* SDMMC2_D6 */				 <STM32_PINMUX('C', 7, AF10)>; /* SDMMC2_D7 */slew-rate = <1>;drive-push-pull;bias-pull-up;};};sdmmc2_b4_od_pins_a: sdmmc2-b4-od-0 {pins1 {pinmux = <STM32_PINMUX('B', 14, AF10)>, /* SDMMC2_D0 */<STM32_PINMUX('B', 15, AF10)>, /* SDMMC2_D1 */<STM32_PINMUX('B', 3, AF10)>, /* SDMMC2_D2 */<STM32_PINMUX('B', 4, AF10)>; /* SDMMC2_D3 */slew-rate = <1>;drive-push-pull;bias-pull-up;};pins2 {pinmux = <STM32_PINMUX('G', 6, AF10)>; /* SDMMC2_CMD */slew-rate = <1>;drive-open-drain;bias-pull-up;};};sdmmc2_b4_b7_od_pins_a: sdmmc2-b4-b7-od-0 {pins {pinmux = <STM32_PINMUX('F', 0, AF10)>, /* SDMMC2_D4 */<STM32_PINMUX('B', 9, AF10)>, /* SDMMC2_D5 */<STM32_PINMUX('C', 6, AF10)>, /* SDMMC2_D6 */				 <STM32_PINMUX('C', 7, AF10)>; /* SDMMC2_D7 */slew-rate = <1>;drive-push-pull;bias-pull-up;};};	sdmmc2_b4_sleep_pins_a: sdmmc2-b4-sleep-0 {pins {pinmux = <STM32_PINMUX('B', 14, ANALOG)>, /* SDMMC2_D0 */<STM32_PINMUX('B', 15, ANALOG)>, /* SDMMC2_D1 */<STM32_PINMUX('B', 3, ANALOG)>, /* SDMMC2_D2 */<STM32_PINMUX('B', 4, ANALOG)>, /* SDMMC2_D3 */<STM32_PINMUX('E', 3, ANALOG)>, /* SDMMC2_CK */<STM32_PINMUX('G', 6, ANALOG)>; /* SDMMC2_CMD */};};sdmmc2_b4_b7_sleep_pins_a: sdmmc2-b4-b7-sleep-0 {pins {pinmux = <STM32_PINMUX('F', 0, ANALOG)>, /* SDMMC2_D4 */<STM32_PINMUX('B', 9, ANALOG)>, /* SDMMC2_D5 */<STM32_PINMUX('C', 6, ANALOG)>, /* SDMMC2_D6 */				 <STM32_PINMUX('C', 7, ANALOG)>; /* SDMMC2_D7 */};};sdmmc2_clk_pins_a: sdmmc2-clk-0 {pins {pinmux = <STM32_PINMUX('E', 3, AF10)>; /* SDMMC2_CK */slew-rate = <1>;drive-push-pull;bias-pull-up;};};uart4_pins_a: uart4-0 {pins1 {pinmux = <STM32_PINMUX('D', 6, AF8)>; /* UART4_TX */bias-disable;drive-push-pull;slew-rate = <0>;};pins2 {pinmux = <STM32_PINMUX('D', 8, AF8)>; /* UART4_RX */bias-pull-up;};};uart4_idle_pins_a: uart4-idle-0 {pins1 {pinmux = <STM32_PINMUX('D', 6, ANALOG)>; /* UART4_TX */};pins2 {pinmux = <STM32_PINMUX('D', 8, AF8)>; /* UART4_RX */bias-pull-up;};};uart4_sleep_pins_a: uart4-sleep-0 {pins {pinmux = <STM32_PINMUX('D', 6, ANALOG)>, /* UART4_TX */<STM32_PINMUX('D', 8, ANALOG)>; /* UART4_RX */};};usbotg_hs_pins_a: usbotg-hs-0 {pins {pinmux = <STM32_PINMUX('A', 10, ANALOG)>; /* OTG_ID */};};
};

3.11 其他

        在stm32mp135-atk-u-boot.dtsi里,关于adc那一行是检测usb电压的,把它注释掉,然后笔者把快速启动注释了,led灯也没有用到。

	config {// u-boot,boot-led = "led-blue";// u-boot,error-led = "led-red";u-boot,mmc-env-partition = "u-boot-env";// st,adc_usb_pd = <&adc1 6>, <&adc1 12>;// st,fastboot-gpios = <&gpioa 13 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;st,stm32prog-gpios = <&gpioa 14 (GPIO_ACTIVE_LOW | GPIO_PULL_UP)>;};

3.12 网络补充

        这里一点至关重要!!!!

        正点原子修改了phy的驱动,所以我们要找到drivers\net\phy\phy.c这个文件,在genphy_config_aneg(struct phy_device *phydev)这个函数后面插入

/***************alientek add****************/
#define YT8531_REG_DEBUG_ADDR_OFFSET		0x1e
#define YT8531_REG_DEBUG_DATA				0x1fstatic int yt8531_rd_ext(struct phy_device *phydev, u32 regnum)
{int val;phy_write(phydev, MDIO_DEVAD_NONE, YT8531_REG_DEBUG_ADDR_OFFSET, regnum);val = phy_read(phydev, MDIO_DEVAD_NONE, YT8531_REG_DEBUG_DATA);return val;
}static int yt8531_wr_ext(struct phy_device *phydev, u32 regnum, u16 val)
{int ret;ret = phy_write(phydev, MDIO_DEVAD_NONE, YT8531_REG_DEBUG_ADDR_OFFSET, regnum);ret = phy_write(phydev, MDIO_DEVAD_NONE, YT8531_REG_DEBUG_DATA, val);return ret;
}int yt8531_xtal_init(struct phy_device *phydev)
{int ret = 0;int val = 0;mdelay(50);do {ret = yt8531_wr_ext(phydev, 0xa012, 0x88);if (ret < 0)return ret;mdelay(100);val = yt8531_rd_ext(phydev, 0xa012);if (val < 0)return val;mdelay(20);} while (val != 0x88);ret = yt8531_wr_ext(phydev, 0xa012, 0xd0);if (ret < 0)return ret;return ret;
}void yt8531_led_init(struct phy_device *phydev)
{yt8531_wr_ext(phydev, 0xa00d, 0x2600);	//yellow led blinkyt8531_wr_ext(phydev, 0xa00c, 0x30);	//10_100M green led always lightyt8531_wr_ext(phydev, 0xa00e, 0x40);	//1000M green led always light	
}/*********************end add***************************/

然后修改 int genphy_update_link(struct phy_device *phydev)这个函数

/*** genphy_update_link - update link status in @phydev* @phydev: target phy_device struct** Description: Update the value in phydev->link to reflect the*   current link value.  In order to do this, we need to read*   the status register twice, keeping the second value.*/
int genphy_update_link(struct phy_device *phydev)
{unsigned int mii_reg;/************alientek add********/int ret = 0;unsigned int phyid1, phyid2;phyid1 = phy_read(phydev, MDIO_DEVAD_NONE, MII_PHYSID1);phyid2 = phy_read(phydev, MDIO_DEVAD_NONE, MII_PHYSID2);if((phyid1 == 0x4f51) && (phyid2 == 0xe91b)) { //YT8531 IDret = yt8531_xtal_init(phydev);if (ret < 0){printf("yt8531_xtal_init failed.\r\n");return ret;}yt8531_led_init(phydev);}/*********************end add***************************//** Wait if the link is up, and autonegotiation is in progress* (ie - we're capable and it's not done)*/mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);/** If we already saw the link up, and it hasn't gone down, then* we don't need to wait for autoneg again*/if (phydev->link && mii_reg & BMSR_LSTATUS)return 0;if ((phydev->autoneg == AUTONEG_ENABLE) &&!(mii_reg & BMSR_ANEGCOMPLETE)) {int i = 0;printf("%s Waiting for PHY auto negotiation to complete",phydev->dev->name);while (!(mii_reg & BMSR_ANEGCOMPLETE)) {/** Timeout reached ?*/if (i > (PHY_ANEG_TIMEOUT / 50)) {printf(" TIMEOUT !\n");phydev->link = 0;return -ETIMEDOUT;}if (ctrlc()) {puts("user interrupt!\n");phydev->link = 0;return -EINTR;}if ((i++ % 10) == 0)printf(".");mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);mdelay(50);	/* 50 ms */}printf(" done\n");phydev->link = 1;} else {/* Read the link a second time to clear the latched state */mii_reg = phy_read(phydev, MDIO_DEVAD_NONE, MII_BMSR);if (mii_reg & BMSR_LSTATUS)phydev->link = 1;elsephydev->link = 0;}return 0;
}

四、编译

make -f ../Makefile.sdk all

        由于我们前面已经编译好了TF-A和optee,在这里编译uboot的时候,会自动用fiptool给我们打包好,然后生成我们需要的fip-stm32mp135-atk-optee.bin文件

相关文章:

(四)正点原子STM32MP135移植——u-boot移植

一、概述 u-boot概述就不概述了&#xff0c;u-boot、kernel、dtb三件套&#xff0c;dddd 经过国庆艰苦奋战&#xff0c;已经成功把所有功能移植好了 二、编译官方代码 进入u-boot的目录 2.1 解压源码、打补丁 /* 解压源码 */ tar xf u-boot-stm32mp-v2022.10-stm32mp-r1-r0.…...

[计算机入门] 应用软件(办公类)

3.19 应用软件(办公类) 3.19.1 Microsoft office办公软件套件 Microsoft Office 是一套广泛使用的办公软件套件&#xff0c;由Microsoft公司开发和发布。它包含了多个应用程序&#xff0c;用于处理各种办公任务。以下是Office常见的几个应用程序&#xff1a; Microsoft Word…...

基于安卓android微信小程序音乐播放器

运行环境 小程序前端框架&#xff1a;uniapp 小程序运行软件&#xff1a;微信开发者 后端技术:javaSsm(SpringSpringMVCMyBatis)vue.js 后端开发环境:idea/eclipse 数据库:mysql 项目介绍 音乐播放器小程序的设计主要是对系统所要实现的功能进行详细考虑&#xff0c;确定所要…...

Java的指针、引用与C++的指针、引用的对比

笔者前两天在参加菜鸟面试的时候被面试官问到了这个问题&#xff0c;由于只在本科程序设计课上学过C&#xff0c;已经好久没有开发实际项目&#xff0c;所以对C相关的指针以及引用的记忆较为模糊&#xff0c;在此进行一定的知识汇总与梳理。 我们以面试中出现的问题为例来进行整…...

串级/级联控制知识点整理

串级控制系统是改善控制质量的有效方法之一&#xff0c;在过程控制中得到了广泛的应用。所谓串级控制&#xff0c;就是采用两个控制器串联工作&#xff0c;外环控制器的输出作为内环控制器的设定值&#xff0c;由内环控制器的输出去操纵控制阀&#xff0c;从而对外环被控量具有…...

数据产品读书笔记——认识数据产品经理

&#x1f33b;大家可能听说的更多是产品经理这个角色&#xff0c;对数据产品经理可能或多或少了解一些&#xff0c;但又不能准确的描述数据产品经理的主要职能和与其他产品的不同&#xff0c;因此通过读一些书来对数据产品经理有一个准确且全面的认知。 目录 1. 数据的产品分类…...

从 0 到 1 ,手把手教你编写《消息队列》项目(Java实现) —— 创建虚拟机

文章目录 一、虚拟机二、关于消息的API发布消息直接交换机 DIRECT 转发规则扇出交换机 FANOUT 转发规则主题交换机 TOPIC 转发规则匹配规则Router类 订阅消息消费者队列如何给订阅的消费者发送消息自动发送消息至订阅者 应答消息 三、代码编写 一、虚拟机 接下来要创建虚拟机,…...

GIT版本控制--前言

欢迎来到《GIT版本控制》专栏&#xff01;在当今软件开发和协作的世界中&#xff0c;版本控制是不可或缺的工具之一。无论您是一名初学者&#xff0c;一位经验丰富的开发者&#xff0c;还是一个项目团队的成员&#xff0c;都有可能会受益于对GIT的深入了解。 GIT是一个强大的分…...

由于 MAC 地址的问题,导致网络不通的原因和分析

由于 MAC 地址的问题&#xff0c;导致网络不通的原因和分析 将现象及原因分析发给大家&#xff0c;供大家参考&#xff0c;以后有类似问题时有个解决问题的参考开发板网络不通&#xff0c;也抓不到包&#xff0c;折腾了好久&#xff0c;将电脑和开发板用网线直连&#xff0c;结…...

游戏开发中的设计模式

单例模式 实例化单一对象&#xff0c;懒加载 //单例模式 class GameManagerSingleton {private constructor(){}private static instance:GameManagerSingleton;public static Instance(){if(!GameManagerSingleton.instance){this.instance new GameManagerSingleton();}re…...

React核心原理与实际开发

学习目标 React是啥&#xff1f; 官方定义&#xff1a;将前端请求获取到的数据渲染为HTML视图的JavaScript库。 一、React入门 1、React项目创建 直接创建react&#xff0c;使用初始化会创建package.json npm init -y再安装 2、React基本使用 使用纯JS创建ReactDOM&#…...

Springboot+vue的企业OA管理系统(有报告),Javaee项目,springboot vue前后端分离项目。

演示视频&#xff1a; Springbootvue的企业OA管理系统&#xff08;有报告&#xff09;&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目。 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的企业OA管理系统&#xff0c;采用M&#xff08;m…...

3、字符设备驱动框架和开发步骤

一、Linux内核对文件的分类 Linux的文件种类 1、-&#xff1a;普通文件2、d&#xff1a;目录文件3、p&#xff1a;管道文件4、s&#xff1a;本地socket文件5、l&#xff1a;链接文件6、c&#xff1a;字符设备7、b&#xff1a;块设备 Linux内核按驱动程序实现模型框架的不同&…...

[MySQL]基础篇

文章目录 1. MySQL基本使用1.1 MySQL的启动和登录1.1.1 MySQL的启动1.1.2 MySQL的客户端连接 1.2 数据模型 2. SQL2.1 SQL类型2.1.1 数值类型2.1.2 字符串类型2.1.3 日期类型 2.2 DDL2.2.1 数据库操作2.2.2 表操作 - 查询2.2.3 表操作 - 创建表2.2.4 表操作 - 修改 2.3 DML2.3.…...

Meta Semantic Template for Evaluation of Large Language Models

本文是LLM系列文章&#xff0c;针对《Meta Semantic Template for Evaluation of Large Language Models》的翻译。 大型语言模型评估的元语义模板 摘要1 引言2 相关工作3 方法4 实验5 结论 摘要 大型语言模型(llm)是否真正理解语言的语义&#xff0c;或者只是记住训练数据?…...

Git相关知识(1)

目录 1.初识Git 1.基础知识 2.centos中下载 2.基本操作 1.创建本地仓库 2.配置本地仓库 3.版本库、工作区、暂存区 4.添加文件 5.add和commit对git文件的作用 6.修改文件 7.版本回退 8.撤销修改 9.删除文件 3.分支操作 1.HEAD与分支 2.创建分支 3.删除分支 …...

pytorch中nn.DataParallel多次使用

pytorch中nn.DataParallel多次使用 import torch import torch.nn as nn import torch.optim as optim from torch.utils.data import DataLoader# 定义模型 class MyModel(nn.Module):def __init__(self):super(MyModel, self).__init__()self.fc nn.Linear(10, 1)def forwa…...

制作电商页面(Html)

任务 制作一个电商页面&#xff0c;要求所卖物品清晰&#xff0c;页面色调清晰&#xff0c;要有主页和详情页。 网站所买物品&#xff1a;书籍 色调&#xff1a;#FF2400 橙红色 代码 主页HTML代码&#xff1a; <html><head><meta charset"utf-8"…...

Android Sutdio依赖Snapshot版本,无法同步最新的包

起因 局域网中搭建了Nexus托管本地打包的aar&#xff0c;正常情况下&#xff0c;把修改完成的库推送到仓库后&#xff0c;其他项目引用Snapshot版本的依赖&#xff0c;同步后会马上下载最新的包&#xff0c;但是当第二次推送后&#xff0c;就没有重新下载最新的包&#xff0c;…...

Feign调用异常触发降级捕获异常

通过配置fallbackFactory来捕获异常信息&#xff0c;代码如下 FeignClient(name "user", fallbackFactory UserFallBackFactory.class) public interface UserFeign {PostMapping("/get/list")Map getList();}Component public class UserFallBackFacto…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

oracle与MySQL数据库之间数据同步的技术要点

Oracle与MySQL数据库之间的数据同步是一个涉及多个技术要点的复杂任务。由于Oracle和MySQL的架构差异&#xff0c;它们的数据同步要求既要保持数据的准确性和一致性&#xff0c;又要处理好性能问题。以下是一些主要的技术要点&#xff1a; 数据结构差异 数据类型差异&#xff…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

优选算法第十二讲:队列 + 宽搜 优先级队列

优选算法第十二讲&#xff1a;队列 宽搜 && 优先级队列 1.N叉树的层序遍历2.二叉树的锯齿型层序遍历3.二叉树最大宽度4.在每个树行中找最大值5.优先级队列 -- 最后一块石头的重量6.数据流中的第K大元素7.前K个高频单词8.数据流的中位数 1.N叉树的层序遍历 2.二叉树的锯…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...