Mastering Embedded Linux Programming 学习 (五)在百问网157开发板上,解决网络配置问题

Mastering Embedded Linux Programming 学习 (五)在百问网157开发板上,解决网络配置问题

思考、参考

搜索发现,需要配置设备树,参考这个链接

修改设备树

找到百问网的补丁文件里面的ethernet0节点,内容如下所示

&ethernet0 {
        status = "okay";
        pinctrl-0 = <&ethernet0_rgmii_pins_a>;
        pinctrl-1 = <&ethernet0_rgmii_pins_sleep_a>;
        pinctrl-names = "default", "sleep";
        phy-mode = "rgmii";
        max-speed = <1000>;
        phy-handle = <&phy0>;

        mdio0 {
                #address-cells = <1>;
                #size-cells = <0>;
                compatible = "snps,dwmac-mdio";
                phy0: ethernet-phy@6 {
                        reg = <6>;
                };
        };
};

首先把它添加到u-boot的设备树文件里头
修改arch/arm/dts/stm32mp15xx-myboard.dtsi
将文件里的ethernet0节点,修改成上面的ethernet0节点

ethernet0的引脚

注意ethernet0_rgmii_pins_sleep_a,百问网的补丁文件重新定义了,不是简单的修改成原来的ethernet0_rgmii_sleep_pins_a就完事

修改arch/arm/dts/stm32mp15-pinctrl.dtsi
pinctrl节点下的ethernet0_rgmii_sleep_pins_a节点前面添加下面的两个节点
注意要把原来的ethernet0_rgmii_pins_a节点删掉


ethernet0_rgmii_pins_a: rgmii-0 {
	pins1 {
		pinmux = <STM32_PINMUX('G', 5, AF11)>, /* ETH_RGMII_CLK125 */
			 <STM32_PINMUX('G', 4, AF11)>, /* ETH_RGMII_GTX_CLK */
			 <STM32_PINMUX('G', 13, AF11)>, /* ETH_RGMII_TXD0 */
			 <STM32_PINMUX('G', 14, AF11)>, /* ETH_RGMII_TXD1 */
			 <STM32_PINMUX('C', 2, AF11)>, /* ETH_RGMII_TXD2 */
			 <STM32_PINMUX('E', 2, AF11)>, /* ETH_RGMII_TXD3 */
			 <STM32_PINMUX('B', 11, AF11)>, /* ETH_RGMII_TX_CTL */
			 <STM32_PINMUX('A', 2, AF11)>, /* ETH_MDIO */
			 <STM32_PINMUX('C', 1, AF11)>; /* ETH_MDC */
		bias-disable;
		drive-push-pull;
		slew-rate = <2>;
	};
	pins2 {
		pinmux = <STM32_PINMUX('C', 4, AF11)>, /* ETH_RGMII_RXD0 */
             <STM32_PINMUX('C', 4, AF11)>, /* ETH_RGMII_RXD0 */
			 <STM32_PINMUX('C', 5, AF11)>, /* ETH_RGMII_RXD1 */
			 <STM32_PINMUX('B', 0, AF11)>, /* ETH_RGMII_RXD2 */
			 <STM32_PINMUX('B', 1, AF11)>, /* ETH_RGMII_RXD3 */
			 <STM32_PINMUX('A', 1, AF11)>, /* ETH_RGMII_RX_CLK */
			 <STM32_PINMUX('A', 7, AF11)>; /* ETH_RGMII_RX_CTL */
		bias-disable;
	};
     
};


ethernet0_rgmii_pins_sleep_a: rgmii-sleep-0 {
	pins1 {
		pinmux = <STM32_PINMUX('G', 5, ANALOG)>, /* ETH_RGMII_CLK125 */
			 <STM32_PINMUX('G', 4, ANALOG)>, /* ETH_RGMII_GTX_CLK */
			 <STM32_PINMUX('G', 13, ANALOG)>, /* ETH_RGMII_TXD0 */
			 <STM32_PINMUX('G', 14, ANALOG)>, /* ETH_RGMII_TXD1 */
			 <STM32_PINMUX('C', 2, ANALOG)>, /* ETH_RGMII_TXD2 */
			 <STM32_PINMUX('E', 2, ANALOG)>, /* ETH_RGMII_TXD3 */
			 <STM32_PINMUX('B', 11, ANALOG)>, /* ETH_RGMII_TX_CTL */
			 <STM32_PINMUX('A', 2, ANALOG)>, /* ETH_MDIO */
			 <STM32_PINMUX('C', 1, ANALOG)>, /* ETH_MDC */
			 <STM32_PINMUX('C', 4, ANALOG)>, /* ETH_RGMII_RXD0 */
			 <STM32_PINMUX('C', 5, ANALOG)>, /* ETH_RGMII_RXD1 */
			 <STM32_PINMUX('B', 0, ANALOG)>, /* ETH_RGMII_RXD2 */
			 <STM32_PINMUX('B', 1, ANALOG)>, /* ETH_RGMII_RXD3 */
			 <STM32_PINMUX('A', 1, ANALOG)>, /* ETH_RGMII_RX_CLK */
			 <STM32_PINMUX('A', 7, ANALOG)>; /* ETH_RGMII_RX_CTL */
	};
};

修改arch/arm/dts/stm32mp15xx-myboard.dtsi
adc节点的status属性修改为disable

然后重新烧录编译

启动u-boot

设置网络参数

setenv ipaddr 192.168.123.18
setenv gatewayip 192.168.123.1
setenv netmask 255.255.255.0
setenv serverip 192.168.123.220
saveenv

修改ethernet0节点

备份arch/arm/dts/stm32mp151.dtsi
修改arch/arm/dts/stm32mp151.dtsi下的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",
                      "ethstp",
                      "ethstp";
        clocks = <&rcc ETHMAC>,
                 <&rcc ETHTX>,
                 <&rcc ETHRX>,
                 <&rcc ETHCK_K>,
                 <&rcc ETHSTP>;
        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";
};

重新编译烧录

pd_core不存在

提示pd_core不存在
在100ask的arch/arm/dts/stm32mp151.dtsi文件找到如下节点
在这里插入图片描述
编译成功

修改**arch/arm/dts/stm32mp15xx-myboard.dtsi **下的adc节点的adc1节点的status为disable

重新编译烧录
在这里插入图片描述
不报adc错误了,但是提示找不到adc设备
使用dhcp命令报错
在这里插入图片描述
搜索源码发现是在这个文件里
在这里插入图片描述
然后发现是这个玩意的驱动
在这里插入图片描述
发现是出错在这里
在这里插入图片描述

找到157相关的寄存器,发现有提示,难道是时钟没有配置好?
在这里插入图片描述

参考补丁开始修改

修改board/st/common/stusb160x.c

STUSB1600_CC_CONNECTION_STATUS修改为0x42
但是在board/st/stm32mp1/stm32mp1.c找不到这一个,不过发现下面这一行头文件
在这里插入图片描述
最后发现是在这个文件里面
board/st/common/stusb160x.c
而且变成了这个形式
在这里插入图片描述
修改这两个宏如下
在这里插入图片描述

修改board/st/stm32mp1/stm32mp1.c

继续修改stm32mp151.c,在最后一个endif下面添加下面的代码

static bool board_is_ya15xc_v2(void)
{
        if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) && of_machine_is_compatible("st,stm32mp157"))
                return true;

        return false;
}

static int phy_power(void)
{
	ofnode node1;
        struct gpio_desc phy;
        int ret = 0;

        node1 = ofnode_path("/wifi_bt_power/phy");
        if (!ofnode_valid(node1)) {
                printf("%s:  no phy-power?\n", __func__);
                return -ENOENT;
        }

	if (gpio_request_by_name_nodev(node1, "gpios", 0,
                                       &phy, GPIOD_IS_OUT)) {
                printf("%s: could not find reset-gpios1\n",
                         __func__);
                return -ENOENT;
        }

	ret = dm_gpio_set_value(&phy, 1);
        if (ret) {
                pr_err("%s: can't set_value for phy reset gpio", __func__);
                goto error;
        }

error:
        return ret;	
}



static bool board_is_ya15xc(void)
{
        if (CONFIG_IS_ENABLED(TARGET_ST_STM32MP15x) &&
            (of_machine_is_compatible("st,stm32mp157") ||
             of_machine_is_compatible("st,stm32mp157c-ya157c-v2")))
                return true;

        return false;
}

//reset the wifi-bt
static int wifi_bt_power(void)
{
        ofnode node1, node2;
        struct gpio_desc wifi, bt;
        int ret = 0;

        node1 = ofnode_path("/wifi_bt_power/wifi");
        if (!ofnode_valid(node1)) {
                printf("%s:  no wifi-power?\n", __func__);
                return -ENOENT;
        }
        node2 = ofnode_path("/wifi_bt_power/bt");
        if (!ofnode_valid(node2)) {
                printf("%s:  no bt-power?\n", __func__);
                return -ENOENT;
        }

        if (gpio_request_by_name_nodev(node1, "gpios", 0,
                                       &wifi, GPIOD_IS_OUT)) {
                printf("%s: could not find reset-gpios1\n",
                         __func__);
                return -ENOENT;
        }
        if (gpio_request_by_name_nodev(node2, "gpios", 0,
                                       &bt, GPIOD_IS_OUT)) {
                printf("%s: could not find reset-gpios2\n",
                         __func__);
                return -ENOENT;
        }

        ret = dm_gpio_set_value(&wifi, 0);
        if (ret) {
                pr_err("%s: can't set_value for wifi reset gpio", __func__);
                goto error;
        }
        ret = dm_gpio_set_value(&bt, 0);
        if (ret) {
                pr_err("%s: can't set_value for bt reset gpio", __func__);
                goto error;
        }
        mdelay(100);//delay

	ret = dm_gpio_set_value(&wifi, 1);
        if (ret) {
                pr_err("%s: can't set_value for wifi reset gpio", __func__);
                goto error;
        }
        ret = dm_gpio_set_value(&bt, 1);
        if (ret) {
                pr_err("%s: can't set_value for bt reset gpio", __func__);
                goto error;
        }

error:
        return ret;

}

搜索board_key_check,在board_init()函数调用board_key_check函数的后面添加如下代码


if (board_is_ya15xc())
{
	
	wifi_bt_power();
	dk2_i2c1_fix();
}

if (board_is_ya15xc_v2())
{
	phy_power();
	
}

考虑到把函数定义放在了后面,需要在board_init函数前放我们上面的函数声明

static bool board_is_ya15xc_v2(void);
static int phy_power(void);
static bool board_is_ya15xc(void);
static int wifi_bt_power(void);

/* board dependent setup after realloc */
int board_init(void)
...

修改drivers/clk/clk_stm32mp1.c

在这里插入图片描述

修改drivers/dfu/dfu.c

做如下修改
在这里插入图片描述

修改drivers/net/dwc_eth_qos.c

在这里插入图片描述

修改drivers/net/phy/atheros.c

在int ret 下添加下面的内容

u16 val;
/*----------------------------------------------*/
/* Ar803x phy SmartEEE feature cause link status generates glitch,
* which cause ethernet link down/up issue, so disable SmartEEE
*/
phy_write(phydev,MDIO_DEVAD_NONE, 0xd, 0x3);
phy_write(phydev,MDIO_DEVAD_NONE, 0xe, 0x805d);
phy_write(phydev,MDIO_DEVAD_NONE, 0xd, 0x4003);

val = phy_read(phydev,MDIO_DEVAD_NONE, 0xe);
phy_write(phydev,MDIO_DEVAD_NONE, 0xe, val & ~(1 << 8));

/* To enable AR8031 output a 125MHz clk from CLK_25M */
phy_write(phydev,MDIO_DEVAD_NONE, 0xd, 0x7);
phy_write(phydev,MDIO_DEVAD_NONE, 0xe, 0x8016);
phy_write(phydev,MDIO_DEVAD_NONE, 0xd, 0x4007);

val = phy_read(phydev,MDIO_DEVAD_NONE, 0xe);
val &= 0xffe3;
val |= 0x18;
phy_write(phydev,MDIO_DEVAD_NONE, 0xe, val);

phy_write(phydev,MDIO_DEVAD_NONE, 0x1d, 0x5);
val = phy_read(phydev,MDIO_DEVAD_NONE, 0x1e);
val |= 0x0100;
phy_write(phydev,MDIO_DEVAD_NONE, 0x1e, val);
printf("test ar8035 !!!");
/*------------------------------------------*/

修改drivers/net/phy/phy.c

在phy_probe函数下添加如下内容


phydev->supported = phydev->drv->features;

phydev->mmds = phydev->drv->mmds;

u16 val;
/*----------------------------------------------*/
/* Ar803x phy SmartEEE feature cause link status generates glitch,
* which cause ethernet link down/up issue, so disable SmartEEE
*/
phy_write(phydev,MDIO_DEVAD_NONE, 0xd, 0x3);
phy_write(phydev,MDIO_DEVAD_NONE, 0xe, 0x805d);
phy_write(phydev,MDIO_DEVAD_NONE, 0xd, 0x4003);

val = phy_read(phydev,MDIO_DEVAD_NONE, 0xe);
phy_write(phydev,MDIO_DEVAD_NONE, 0xe, val & ~(1 << 8));

/* To enable AR8031 output a 125MHz clk from CLK_25M */
phy_write(phydev,MDIO_DEVAD_NONE, 0xd, 0x7);
phy_write(phydev,MDIO_DEVAD_NONE, 0xe, 0x8016);
phy_write(phydev,MDIO_DEVAD_NONE, 0xd, 0x4007);

val = phy_read(phydev,MDIO_DEVAD_NONE, 0xe);
val &= 0xffe3;
val |= 0x18;
phy_write(phydev,MDIO_DEVAD_NONE, 0xe, val);

phy_write(phydev,MDIO_DEVAD_NONE, 0x1d, 0x5);
val = phy_read(phydev,MDIO_DEVAD_NONE, 0x1e);
val |= 0x0100;
phy_write(phydev,MDIO_DEVAD_NONE, 0x1e, val);
//--------------------------------------

编译成功,重新烧录
在这里插入图片描述
提示这个,需要继续修改设备树文件

修改arch/arm/dts/stm32mp157c-myboard.dts

在根节点下添加

wifi_bt_power:wifi_bt_power {
	compatible = "wifibt-rst";
	wifi {
		label = "wifi-rst";
		gpios = <&gpioi 3 GPIO_ACTIVE_HIGH>;
	};
	bt {
		label = "bt-rst";
		gpios = <&gpioa 15 GPIO_ACTIVE_HIGH>;
	};
	phy {
		label = "phy-rest";
		gpios = <&gpiog 0 GPIO_ACTIVE_HIGH>;
	};
};	

编译成功,重新烧录

在这里插入图片描述
成功搞定!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Key Features, Create efficient and secure embedded devices using LinuxMinimize project costs by using open source tools and programsExplore each component technology in depth, using sample implementations as a guide, Book Description, Mastering Embedded Linux Programming takes you through the product cycle and gives you an in-depth description of the components and options that are available at each stage. You will begin by learning about toolchains, bootloaders, the Linux kernel, and how to configure a root filesystem to create a basic working device. You will then learn how to use the two most commonly used build systems, Buildroot and Yocto, to speed up and simplify the development process. Building on this solid base, the next section considers how to make best use of raw NAND/NOR flash memory and managed flash eMMC chips, including mechanisms for increasing the lifetime of the devices and to perform reliable in-field updates. Next, you need to consider what techniques are best suited to writing applications for your device. We will then see how functions are split between processes and the usage of POSIX threads, which have a big impact on the responsiveness and performance of the final device The closing sections look at the techniques available to developers for profiling and tracing applications and kernel code using perf and ftrace., What you will learn, Understand the role of the Linux kernel and select an appropriate role for your applicationUse Buildroot and Yocto to create embedded Linux systems quickly and efficientlyCreate customized bootloaders using U-BootEmploy perf and ftrace to identify performance bottlenecksUnderstand device trees and make changes to accommodate new hardware on your deviceWrite applications that interact with Linux device driversDesign and write multi-threaded applications using POSIX threadsMeasure real-time latencies and tune the Linux kernel to minimize them, About the Author, Chris Simmonds is a software consultant and trainer who lives in southern England. He has been using Linux in embedded systems since the late 1990s, during which he has worked on many interesting projects, including a stereoscopic camera, intelligent weighing scales, various set-top boxes and home routers, and even a large walking robot., He is a frequent presenter at open source and embedded conferences, including the Embedded Linux Conference, Embedded World, and the Android Builders' Summit. He has been conducting training courses and workshops in embedded Linux since 2002 and in embedded Android since 2010. He has delivered hundreds of sessions to many well-known companies. You can see some of his work on the 'Inner Penguin' blog at www.2net.co.uk., Table of Contents, Starting OutLearning About ToolchainsAll About BootloadersPorting and Configuring the KernelBuilding a Root FilesystemSelecting a Build SystemCreating a Storage StrategyIntroducing Device DriversStarting up - the init ProgramLearning About Processes and ThreadsManaging MemoryDebugging with GDBProfiling and TracingReal-time Programming
### 回答1: 《嵌入式Linux编程的精髓-第二版》是一本涵盖嵌入式Linux编程相关知识的书籍。嵌入式系统是指嵌入到设备中,负责控制设备运行的计算机系统。Linux是一种自由、开放源代码的操作系统,广泛应用于嵌入式系统中。 在第二版中,这本书提供了嵌入式系统开发的最新趋势和技术。它讲解了嵌入式Linux系统的搭建和配置,包括交叉编译工具链的搭建、Linux内核的配置和裁剪,以及Bootloader的加载等。此外,书中还介绍了如何进行硬件与软件的交互,包括GPIO控制、设备驱动的开发与调试等。 本书还特别强调了实践与项目开发。作者通过编写一些实际案例来引导读者探索不同的嵌入式项目,包括网络应用、图形界面、多媒体处理、无线通信等。这有助于读者将所学知识应用到实际开发中,提高嵌入式系统的开发能力。 此外,本书还介绍了调试和优化嵌入式系统的方法。作者分享了一些调试工具和技巧,帮助读者解决开发中的常见问题。还介绍了优化嵌入式系统性能的方法,以提高系统的速度和响应能力。 总之,《嵌入式Linux编程的精髓-第二版》是一本全面而实践性强的嵌入式Linux编程学习指南。通过学习本书,读者将能够掌握Linux的基本原理和嵌入式系统的开发技巧,并能够应用于实际项目中,提高嵌入式系统的性能和稳定性。 ### 回答2: 《嵌入式Linux编程:第二版》是一本涵盖嵌入式Linux系统开发的重要概念和技术的书籍。本书旨在帮助读者掌握嵌入式Linux编程的各个方面,从而成为一名嵌入式系统开发专家。 第二版的《嵌入式Linux编程》与第一版相比,进行了更新和扩展。本书涵盖了Linux内核的最新版本,并介绍了最新的嵌入式Linux开发工具和技术。同时,本书还增加了对容器化和虚拟化技术在嵌入式Linux系统中的应用的讨论。 本书的内容涵盖了从基础知识到高级主题的嵌入式Linux系统开发。读者将学习如何搭建嵌入式Linux开发环境,了解Linux内核的基本概念和结构,并深入研究设备驱动程序和文件系统的开发。此外,本书还介绍了嵌入式系统的调试和性能优化技术,以及与硬件交互的通信协议和接口。 读者在阅读本书时,将通过实例和案例学习,结合实际应用场景,将理论知识应用到实际项目中。通过深入学习嵌入式Linux编程,读者将能够理解和掌握嵌入式Linux系统的架构和工作原理,能够编写高效、可靠的设备驱动程序和应用程序,并能够解决嵌入式系统开发中遇到的各种挑战和问题。 总之,通过阅读《嵌入式Linux编程:第二版》,读者将获得全面的嵌入式Linux编程知识和技能,并能够在实际项目中应用这些知识和技能,成为一名嵌入式系统开发专家。 ### 回答3: 《嵌入式Linux编程掌握-第二版》是一本深入了解嵌入式Linux编程的指南。这本书适合有一定编程基础的读者,他们有兴趣学习如何在嵌入式系统中使用Linux。它提供了关于嵌入式Linux的详细知识和实践经验,包括Linux内核和设备驱动程序的基础知识,以及如何将Linux运行在各种不同的嵌入式硬件上。 这本书的第二版提供了更加深入和全面的内容,与第一版相比进行了更新和扩充。它介绍了如何为嵌入式系统配置和编译Linux内核,以及如何开发和调试Linux设备驱动程序。此外,它还涵盖了嵌入式Linux系统的网络和存储管理,以及如何优化和调试系统性能。 书中还包含了大量的示例代码和实验项目,读者可以通过实践来加深对所学知识的理解和掌握。此外,该书还介绍了一些流行的嵌入式开发板和硬件平台,以及常用的开发工具和调试技术。 总的来说,通过阅读《嵌入式Linux编程掌握-第二版》,读者将获得深入了解嵌入式Linux系统开发的能力,并在实践中掌握如何在嵌入式系统中应用Linux的技术和工具。这对想要在嵌入式领域从事开发工作的人来说是一本很有价值的参考书。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值