GPIO模拟SMI[MDC/MDIO]协议

编程入门 行业动态 更新时间:2024-10-11 03:23:32

GPIO模拟SMI[MDC/MDIO]<a href=https://www.elefans.com/category/jswz/34/1771197.html style=协议"/>

GPIO模拟SMI[MDC/MDIO]协议

GPIO模拟SMI[MDC/MDIO]协议

  • 背景
  • 一、SMI概念
  • 二、MDIO数据传输协议
  • 三、实现代码示例


背景

在某些芯片上可能没有提供MDC/MDIO接口,可以通过GPIO(General Purpose Input/Output)来模拟,GPIO可实现串行输入输出,且一般CPU上会提供很多GPIO接口供用户自定义使用。

每组SMI需要两个GPIO口分别来模拟MDC和MDIO,首先需要保证这两个GPIO口不作其他用途,且相应的复用模式设置为GPIO模式。


一、SMI概念

SMI:串行管理接口(Serial Management Interface),通常直接被称为MDIO接口(Management Data Input/Output Interface)。MDIO最早在IEEE 802.3的第22卷定义,后来在第45卷又定义了增强版本的MDIO,其主要被应用于以太网的MAC和PHY层之间,用于MAC层器件通过读写寄存器来实现对PHY层器件的操作与管理。

MDIO主机(即产生MDC时钟的设备)通常被称为STA(Station Management Entity),而MDIO从机通常被称为MMD(MDIO Management Device)。通常STA都是MAC层器件的一部分,而MMD则是PHY层器件的一部分。

MDIO接口包括两条线,MDIO和MDC,其中MDIO是双向数据线,而MDC是由STA驱动的时钟线。MDC时钟的最高速率一般为2.5MHz,MDC也可以是非固定频率,甚至可以是非周期的。MDIO接口只是会在MDC时钟的上升沿进行采样,而并不在意MDC时钟的频率(类似于I2C接口)。MDIO是一个PHY的管理接口,用来读/写PHY的寄存器,以控制PHY的行为或获取PHY的状态,MDC为MDIO提供时钟。

MDIO原本是为MII总线接口定义的,MII用于连接MAC和PHY,包含两种信号接口:

  1. 一个数据接口用于MAC和PHY之间接收和发送以太网帧数据。

  2. 一个PHY管理接口,即MDIO,用于读写每个PHY的控制寄存器和状态寄存器,以达到控制PHY行为和监控PHY状态的目的。

MDIO是双向的,只支持一个MAC连接最多32个PHY的连接方式,且MAC作为master,PHY作为slave。在写PHY寄存器的时候,由MAC驱动MDIO向PHY写入数据;在读PHY寄存器时,前半段由MAC驱动发送寄存器地址,后半段由PHY驱动回复寄存器的值。

MDC要求由MAC输出,是非周期性的,即不要求提供固定频率的时钟,对于PHY芯片则作为输入,以在上升沿触发MDIO的读写。MDC的时钟频率可以是DC-2.5MHz,即最小的时钟周期为400ns。

MDIO接口有两个版本,通常被称为卷22版本和卷45版本。卷22版本的MDIO接口最多支持连接32个MMD(PHY层设备),每个设备最多支持32个寄存器。卷45版本的MDIO接口最多支持连接32个MMD,32个设备类型,每个设备最多支持64K个寄存器

二、MDIO数据传输协议

MDIO数据格式定义在IEEE 802.3以太网标准中,如下图所示(数据传输顺序为从左至右):

上图中*表示高阻态,这时MDIO的状态由一个外部的1.5KΩ电阻决定。
Preamble+Start:32bits的前导码以及2bit的开始位。
OP Code:2bits的操作码,10表示读,01表示写。
PHYAD:5bits的PHY地址,一般PHY地址从0开始顺序编号,例如6口switch中PHY地址为0-5。
REGAD:5bits的寄存器地址,即要读或写的寄存器。
Turn Around:2bits的TA,在读命令中,MDIO在此时由MAC驱动改为PHY驱动,并等待一个时钟周期准备发送数据。在写命令中,不需要MDIO方向发生变化,则只是等待两个时钟周期准备写入数据。
Data:16bits数据,在读命令中,PHY芯片将读到的对应PHYAD的REGAD寄存器的数据写到Data中,在写命令中,MAC将要写入对应PHYAD的REGAD寄存器的值写入Data中。
Idle:空闲状态,此时MDIO无源驱动,处高阻状态,但一般用上拉电阻使其处在高电平。

三、实现代码示例

代码如下(示例)通过chat-gpt搜索,这个是好东西:

#include "stm32f4xx.h"#define SMI_CLK_Pin GPIO_Pin_8 // SMI CLK 引脚
#define SMI_DATA_Pin GPIO_Pin_9 // SMI DATA 引脚void SMI_Init_GPIO(void) {GPIO_InitTypeDef GPIO_InitStruct;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // Enable GPIOA clockGPIO_InitStruct.GPIO_Pin = SMI_CLK_Pin | SMI_DATA_Pin;GPIO_InitStruct.GPIO_Mode = GPIO_Mode_OUT; // 配置为推挽输出模式GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_NOPULL;GPIO_InitStruct.GPIO_Speed = GPIO_Speed_100MHz;GPIO_Init(GPIOA, &GPIO_InitStruct);
}uint16_t SMI_ReadRegister(uint32_t phy_addr, uint16_t reg_addr) {uint16_t data = 0;uint16_t command = 0;uint8_t i;// 发送PRE数据for(i = 0; i < 32; i++) {GPIO_SetBits(GPIOA, SMI_CLK_Pin);GPIO_ResetBits(GPIOA, SMI_CLK_Pin);}// 发送ST数据GPIO_ResetBits(GPIOA, SMI_DATA_Pin);GPIO_SetBits(GPIOA, SMI_CLK_Pin);GPIO_ResetBits(GPIOA, SMI_CLK_Pin);GPIO_SetBits(GPIOA, SMI_DATA_Pin);// 发送OP数据command = ((phy_addr & 0x1F) << 5) | ((reg_addr & 0x1F) << 0);for(i = 0; i < 14; i++) {GPIO_WriteBit(GPIOA, SMI_DATA_Pin, (command >> (13-i)) & 0x01);GPIO_SetBits(GPIOA, SMI_CLK_Pin);GPIO_ResetBits(GPIOA, SMI_CLK_Pin);}// 接收数据GPIO_SetBits(GPIOA, SMI_DATA_Pin); // 配置DATA引脚为输入模式for(i = 0; i < 16; i++) {GPIO_SetBits(GPIOA, SMI_CLK_Pin);data |= GPIO_ReadInputDataBit(GPIOA, SMI_DATA_Pin) << (15 - i);GPIO_ResetBits(GPIOA, SMI_CLK_Pin);}return data;
}void SMI_WriteRegister(uint32_t phy_addr, uint16_t reg_addr, uint16_t data) {uint16_t command = 0;uint8_t i;// 发送PRE数据for(i = 0; i < 32; i++) {GPIO_SetBits(GPIOA, SMI_CLK_Pin);GPIO_ResetBits(GPIOA, SMI_CLK_Pin);}// 发送ST数据GPIO_ResetBits(GPIOA, SMI_DATA_Pin);GPIO_SetBits(GPIOA, SMI_CLK_Pin);GPIO_ResetBits(GPIOA, SMI_CLK_Pin);GPIO_SetBits(GPIOA, SMI_DATA_Pin);// 发送OP数据command = ((phy_addr & 0x1F) << 5) | ((reg_addr & 0x1F) << 0) | 0x4000;for(i = 0; i < 14; i++) {GPIO_WriteBit(GPIOA, SMI_DATA_Pin, (command >> (13-i)) & 0x01);GPIO_SetBits(GPIOA, SMI_CLK_Pin);GPIO_ResetBits(GPIOA, SMI_CLK_Pin);}// 发送DATA数据for(i = 0; i < 16; i++) {GPIO_WriteBit(GPIOA, SMI_DATA_Pin, (data >> (15-i)) & 0x01);GPIO_SetBits(GPIOA, SMI_CLK_Pin);GPIO_ResetBits(GPIOA, SMI_CLK_Pin);}
}

更多推荐

GPIO模拟SMI[MDC/MDIO]协议

本文发布于:2024-02-14 14:23:41,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1763753.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:协议   SMI   GPIO   MDIO   MDC

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!