目录
以太网PHY硬件连接
MAC与PHY之间的接口标准MII/GMII
以太网PHY寄存器分析
以太网PHY驱动软件配置
其它
我们对g_ethercat_ssc_port0_ext_cfg这个全局变量深入追踪,其成员变量 g_ether_PHY0,正好是一个PHY实例的详细描述体。
左右滑动查看完整内容
/* Instance structure to use this module. */
const ether_PHY_instance_t g_ether_PHY0 =
{
.p_ctrl = &g_ether_PHY0_ctrl,
.p_cfg = &g_ether_PHY0_cfg,
.p_api = &g_ether_PHY_on_ether_PHY
};
其中g_ether_PHY0_cfg是pyh实例的配置结构体:
左右滑动查看完整内容
const ether_PHY_cfg_t g_ether_PHY0_cfg =
{
.channel = 0,
.PHY_lsi_address = 0,
.PHY_reset_wait_time = 0x00020000,
.mii_bit_access_wait_time = 0, // Unused
.flow_control = ETHER_PHY_FLOW_CONTROL_DISABLE,
.mii_type = (ether_PHY_mii_type_t) 0, // Unused
.p_context = NULL,
.p_extend = &g_ether_PHY0_extend
};
这里又通过p_extend 做了扩展配置(其实可以合并在一起)如下所示:
左右滑动查看完整内容
const ether_PHY_extend_cfg_t g_ether_PHY0_extend =
{
.port_type = ETHER_PHY_PORT_TYPE_ETHER_CAT,
.PHY_chip = (ether_PHY_chip_t) ETHER_PHY_CHIP_VSC8541,
.mdio_type = ETHER_PHY_MDIO_GMAC,
.bps = ETHER_PHY_SPEED_100,
.duplex = ETHER_PHY_DUPLEX_FULL,
.auto_negotiation = ETHER_PHY_AUTO_NEGOTIATION_ON,
.PHY_reset_pin = BSP_IO_PORT_20_PIN_7,
.PHY_reset_time = 15000,
.p_selector_instance = (ether_selector_instance_t *)&g_ether_selector0,
};
可以看到上面的扩展配置当中,PHY的具体硬件型号都已经列出,如PHY_chip = (ether_PHY_chip_t) ETHER_PHY_CHIP_;
可以看到在示例代码当中已经支持的PHY如下所示:
左右滑动查看完整内容
/** Identify PHY-LSI */
typedef enum e_ether_PHY_chip
{
ETHER_PHY_CHIP_VSC8541 = (1 << 0), ///< VSC8541
ETHER_PHY_CHIP_KSZ9131 = (1 << 1), ///< KSZ9131
ETHER_PHY_CHIP_KSZ9031 = (1 << 2), ///< KSZ9031
ETHER_PHY_CHIP_KSZ8081 = (1 << 3), ///< KSZ8081
ETHER_PHY_CHIP_KSZ8041 = (1 << 4) ///< KSZ8041
} ether_PHY_chip_t;
这里具体看一下 g_ether_selector0 这个 ether_selector_instance_t 类型的全局指针,指向 selector driver实例的成员变量:
左右滑动查看完整内容
typedef struct st_ether_selector_instance
{
ether_selector_ctrl_t * p_ctrl; ///< Pointer to the control structure for this instance
ether_selector_cfg_t const * p_cfg; ///< Pointer to the configuration structure for this instance
ether_selector_api_t const * p_api; ///< Pointer to the API structure for this instance
} ether_selector_instance_t;
这又是一个类似的结构体,通过三个指针来分别指向结构本身,selector的具体配置,和配置selector过程中所需要用的的成员方法api.
看一下selector的具体配置信息:
左右滑动查看完整内容
typedef struct st_ether_selector_cfg
{
uint8_t port; ///< Port number
ether_selector_PHYlink_polarity_t PHYlink; ///< PHY link signal polarity
ether_selector_interface_t interface; ///< Converter mode
ether_selector_speed_t speed; ///< Converter Speed
ether_selector_duplex_t duplex; ///< Converter Duplex
ether_selector_ref_clock_t ref_clock; ///< Converter REF_CLK
void const * p_extend; ///< Placeholder for user extension.
} ether_selector_cfg_t;
可以看到selector 对应的端口号,PHY连接信号对应的极性,接口模式,速率,全双工,以及外部时钟输入。再看一下配置selector的过程中所需要用到的API函数:
左右滑动查看完整内容
const ether_selector_api_t g_ether_selector_on_ether_selector =
{
.open = R_ETHER_SELECTOR_Open,
.converterSet = R_ETHER_SELECTOR_ConverterSet,
.close = R_ETHER_SELECTOR_Close,
.versionGet = R_ETHER_SELECTOR_VersionGet
};
其最主要的成员方法就是R_ETHER_SELECTOR_Open做了些什么:
先初始化ETHER_SELECTOR
左右滑动查看完整内容
/* One time initialization for all ETHER_SELECTOR instances. */
r_ether_selector_state_initialize();
/* Unlock write access protection for Ethernet subsystem registers */
r_ether_selector_reg_protection_disable(p_reg_ethss);
/* Set the function of Ethernet ports. */
sw_mode = ETHER_SELECTOR_CFG_MODE;
p_reg_ethss->MODCTRL_b.SW_MODE = sw_mode & ETHER_SELECTOR_MODCTRL_BIT_SWMODE_MASK;
/* Set the MAC of all port for half-duplex. */
p_reg_ethss->SWDUPC_b.PHY_DUPLEX = 0;
/* Set all Ethernet switch port to select not use 10Mbps. */
p_reg_ethss->SWCTRL_b.SET10 = 0;
根据端口号来选择对应控制寄存器
左右滑动查看完整内容
/* Set RGMII/RMII Converter configuration */
switch (port)
{
case 0:
{
p_reg_convctrl = (uint32_t *) &p_reg_ethss->CONVCTRL[0];
break;
}
case 1:
{
p_reg_convctrl = (uint32_t *) &p_reg_ethss->CONVCTRL[1];
break;
}
case 2:
default:
{
p_reg_convctrl = (uint32_t *) &p_reg_ethss->CONVCTRL[2];
break;
}
}
根据指向selector的配置信息:
左右滑动查看完整内容
const ether_selector_cfg_t g_ether_selector0_cfg =
{
.port = 0,
.PHYlink = ETHER_SELECTOR_PHYLINK_POLARITY_LOW,
.interface = ETHER_SELECTOR_INTERFACE_RGMII,
.speed = ETHER_SELECTOR_SPEED_100MBPS,
.duplex = ETHER_SELECTOR_DUPLEX_FULL,
.ref_clock = ETHER_SELECTOR_REF_CLOCK_INPUT,
.p_extend = NULL,
};
来对CONVCTRL[port_number]寄存器做相应的配置
点击可查看大图
这里结合RZ/T2M的用户手册,很容易理解其中的意思:
点击可查看大图
结合代码来看,总体ETHER_SELECTOR 的驱动的配置流程图台下所示:
点击可查看大图
在对ETHER_SELECTOR驱动做完配置后,下面具体看一下对ETHER_PHY_CHIP这个PHY,代码具体做了哪些操作:
首先是做初始化:
点击可查看大图
左右滑动查看完整内容
oid ether_PHY_targets_initialize_vsc8541 (ether_PHY_instance_ctrl_t * p_instance_ctrl)
{
/* Vendor Specific PHY Registers */
...
这个初始化函数,并没有对IEEE 标准规定的16个寄存器做读写操作,只对厂商自定义的寄存器做了配置。初始化完成之后,对是否打开自动协商的功能对PHY进行了读写:
点击可查看大图
点击可查看大图
这里可以看到对PHY芯生来说,需要配置的寄存器并不是很多,大多数情况下,把自动协商寄存器配置好,就可以了。除此之后就是厂商自定义的寄存器的一些自定义的功能。这部分功能需要结合用户手册来理解和使用,大部分也是用来调试和指示的作用以及一些IEEE基本标准之外的特色功能,比如节能标准之类的。
对于用户说来,搞清楚数据结构之间的关联,剩下的就是驱动代码的执行逻辑,考虑到执行逻辑并不复杂,这里不展开来说。用户可以参考录屏材料进一步深入了解。
其它
经过验证的PHY芯片列表:
您可复制下方网址到浏览器中打开进入瑞萨中文论坛查看:
https://community-ja.renesas.com/zh/forums-groups/mcu-mpu/
1
END
1
推荐阅读
工业以太网PHY驱动适配参考文档(1)
工业以太网PHY驱动适配参考文档(2)
工业以太网PHY驱动适配参考文档(3)