Zephyr配置使用w5500

Creative Commons
本作品采用知识共享署名

本文演示如何配置使用w5500.

Zephyr中含有大量的外设驱动,根据实际的硬件经过简单的配置就可以轻松的使用外设驱动,从而避免繁重的驱动开发和调试工作。本文基于mm_feather开发板演示如何配置使用w5500。

设备树

增加一个w5500

W5500是一款高性价比的以太网芯片,通过SPI接口和MCU进行高速通信,MCU作为SPI主机,W5500作为SPI从机。MCU和W5500通信的硬件连接引脚如下:

W5500 PIN MCU LPSPI PIN 连接/作用
SCK LPSPI4 SCK MCU SPI时钟/输出到W5500
MOSI LPSPI4 MOSI MCU SPI数据/输出到W5500
MISO LPSPI4 MISO MCU SPI数据输入/从W5500读数据
CS GPIO1.26 MCU SPI片选/输出信号选择W5500的SPI
INT GPIO1.28 MCU 中断输入引脚/接收W5500的中断
RST GPIO2.18 MCU GPIO/输出复位信号复位W5500

得益于Zephyr的设备树,再根据上面的硬件连接添加一个外设十分方便,在mm_feather.dts中原本有使能lpspi4

1
2
3
4
5
6
&lpspi4 {
status = "okay";
pcs-sck-delay = <2>;
sck-pcs-delay = <2>;
transfer-delay = <2>;
};

现在我们要将w5500做为device挂在lpspi4的总线下,devicetree写为

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
&lpspi4 {
status = "okay";
pcs-sck-delay = <2>;
sck-pcs-delay = <2>;
transfer-delay = <2>;

cs-gpios = <&gpio1 26 GPIO_ACTIVE_LOW>;

w5500: w5500@0 {
compatible = "wiznet,w5500";
label = "w5500";
reg = <0>;
spi-max-frequency = <49000000>;
int-gpios = <&gpio1 28 GPIO_ACTIVE_LOW>;
reset-gpios = <&gpio2 18 GPIO_ACTIVE_LOW>;
};
};
  • cs-gpios 这里将lpspi使用的片选指定为GPIO控制

  • w5500@0 表示lpspi4下面挂的第一个device

  • compatible 指定了w5500的绑定文件,对应到绑定文件就是dts/bindings/ethernet/wiznet,w5500.yaml

  • wizent,w5500.yaml中包含了spi-device.yaml,提供了

    • label是所有节点都含有的,代码中访问驱动名由lable指定的w5500

    • reg指定该spi device的寄存器序号,当有多个device时要和cs-gpios来对应

    • spi-max-frequency 指定device的spi通信最大速率

  • int-gpios w5500的中断输出引脚

  • reset-gpios w5500的复位输入引脚

增加多个设备

这里简单示例一下,一个spi下挂多个device的写法,例如在lpspi4下除了w5500外又加挂了一个enc28j60作为双网卡通信

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
&lpspi4 {
status = "okay";
pcs-sck-delay = <2>;
sck-pcs-delay = <2>;
transfer-delay = <2>;

cs-gpios = <&gpio1 26 GPIO_ACTIVE_LOW>,
<&gpio1 27 GPIO_ACTIVE_LOW>;

w5500: w5500@0 {
compatible = "wiznet,w5500";
label = "w5500";
reg = <0>;
spi-max-frequency = <49000000>;
int-gpios = <&gpio1 28 GPIO_ACTIVE_LOW>;
reset-gpios = <&gpio2 18 GPIO_ACTIVE_LOW>;
};

enc28j60: enc28j60@1 {
compatible = "microchip,enc28j60";
label = "ENC28J60";
reg = <0x1>;
spi-max-frequency = <10000000>;
int-gpios = <&gpio2 12 0>;
};
};

这里就可以很清晰的看到cs-gpio是这一组gpio,其顺序对应于后面spi device节点的reg序号,也就是gpio1.26为w5500的片选,gpio1.27为enc28j60的片选。

配置

在设备树中将w5500添加好后,也就为驱动提供了必要的硬件信息,最后就只用在配置选项中开启编译选项,就可能使用W5500了,配置选项的说明如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#启用zephyr网络
CONFIG_NETWORKING=y
# w5500是从L2 ethernet接入,配置L2
CONFIG_NET_L2_ETHERNET=y
# 配置启用w5500
CONFIG_ETH_W5500=y

#以下配置是纯TCP/IP协议栈的,可以按需增加和减少
CONFIG_NET_IPV4=y
CONFIG_NET_DHCPV4=n
CONFIG_NET_UDP=y
CONFIG_NET_TCP=y
CONFIG_NET_ARP=y
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_MY_IPV4_ADDR="192.168.101.33"

PinMux

现代的MCU大多数都支持pinmux,目前zephyr对rt系列芯片的Pinmux支持不全,因此还需要添加引脚功能的初始化。这步对于其它soc并不是必须,例如nrf的直接在设备树中就可以指定。
/boards/arm/mm_feather/pinmux.c中增加如下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#if DT_NODE_HAS_STATUS(DT_NODELABEL(lpspi4), okay) && CONFIG_ETH_W5500
// 配置spi4的引脚功能
IOMUXC_SetPinMux(IOMUXC_GPIO_B0_01_LPSPI4_SDI, 0U);
IOMUXC_SetPinMux(IOMUXC_GPIO_B0_02_LPSPI4_SDO, 0U);
IOMUXC_SetPinMux(IOMUXC_GPIO_B0_03_LPSPI4_SCK, 0U);

IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_01_LPSPI4_SDI, 0x10B0u);
IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_02_LPSPI4_SDO, 0x10B0u);
IOMUXC_SetPinConfig(IOMUXC_GPIO_B0_03_LPSPI4_SCK, 0x10B0u);


// 配置reset的引脚功能
IOMUXC_SetPinMux(IOMUXC_GPIO_B1_02_GPIO2_IO18, 0U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_B1_02_GPIO2_IO18, IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2) |
IOMUXC_SW_PAD_CTL_PAD_DSE(6));

// 配置cs的引脚功能
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_10_GPIO1_IO26, 0U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_10_GPIO1_IO26, IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2) |
IOMUXC_SW_PAD_CTL_PAD_DSE(6));

// 配置INT的引脚功能
IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B1_12_GPIO1_IO28, 0U);
IOMUXC_SetPinConfig(IOMUXC_GPIO_AD_B1_12_GPIO1_IO28, IOMUXC_SW_PAD_CTL_PAD_PKE_MASK |
IOMUXC_SW_PAD_CTL_PAD_SPEED(2) |
IOMUXC_SW_PAD_CTL_PAD_DSE(6));
#endif