RTL8305NB从电口模式切换为光口模式

#if 1//下面是参考案例  //RTL8305NB
 
 
#define PORT2_PHY_ADDR 0x05  // SFP Port2 PHY地址
#define STATUS_REG_ADDR 0x01 // 状态寄存器地址
 
#define MDC_PIN GPIO_Pin_13      //MDC (PC13)      
#define MDIO_PIN GPIO_Pin_6  //MDIO (PE6)
 
 
#define MDIO_DELAY 10      // us
#define MDIO_READ_DELAY 10 // us
 
 
void smi_init(void);
 
u16 smi_reg_read(u16 phy, u16 reg);
 
void smi_reg_write(u16 phy, u16 reg, u16 val);
 
static void MDC_OUT(void);
static void MDIO_OUT(void);
static void MDIO_IN(void);
static void MDC_H(void);
static void MDC_L(void);
static uint8_t GET_MDIO(void);
static void SET_MDIO(uint8_t val);
extern void delay_us(u32 nus);
 
void LOS_UDelay(u32 nus)
{
    delay_us(nus);    
}
 
 
/* 设置MDC为输出引脚,在MDC输出时钟之前设置 */
static void MDC_OUT(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; // 推挽输出,因为MDIO是双向的,但在这里我们先配置为输出  
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//GPIO_PuPd (Pull-Up/Pull-Down)设置 GPIO 引脚的内部上拉/下拉电阻
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//GPIO_OType (Output Type)用于设置 GPIO 引脚在输出模式下的类型。 
  
    // MDC (PC13) 配置为输出  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;  
    GPIO_Init(GPIOC, &GPIO_InitStructure); 
 
}
 
/* 设置MDIO的gpio引脚为输出引脚 */
static void MDIO_OUT(void)
{
 
    GPIO_InitTypeDef GPIO_InitStructure;
    // MDIO (PE6) 配置为输出  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; // 推挽输出,因为MDIO是双向的,但在这里我们先配置为输出  
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//GPIO_PuPd (Pull-Up/Pull-Down)设置 GPIO 引脚的内部上拉/下拉电阻
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//GPIO_OType (Output Type)用于设置 GPIO 引脚在输出模式下的类型。
    GPIO_Init(GPIOE, &GPIO_InitStructure);  
      
}
 
/* 设置MDIO的gpio引脚为输入引脚 */
static void MDIO_IN(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    // MDIO (PE6) 配置为输出  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;    
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;   
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//GPIO_PuPd (Pull-Up/Pull-Down)设置 GPIO 引脚的内部上拉/下拉电阻
    GPIO_Init(GPIOE, &GPIO_InitStructure); 
    
}
 
/* MDC输出高电平,在MDC设置为输出后调用 */
static void MDC_H(void)
{
    GPIO_SetBits(GPIOC, MDC_PIN); 
}
 
 
 
/* MDC输出低电平,在MDC设置为输出后调用 */
static void MDC_L(void)
{
    GPIO_ResetBits(GPIOC, MDC_PIN); 
}
 
/* 获得MDIO的数据,只获得一个bit */
static uint8_t GET_MDIO(void)
{
    return GPIO_ReadInputDataBit(GPIOE,MDIO_PIN);
}
 
/* 设置MDIO的数据,一个bit */
static void SET_MDIO(uint8_t val)
{
    if (val != 0) {
        GPIO_SetBits(GPIOE, MDIO_PIN);
    } else {
        GPIO_ResetBits(GPIOE, MDIO_PIN);
    }
}
 
/* MDIO发送一个bit的数据,MDIO必须已经被配置为输出 */
static void mdio_bb_send_bit(uint8_t val)
{
    MDC_OUT();
    SET_MDIO(val);
    LOS_UDelay(MDIO_DELAY);
    MDC_H();
    LOS_UDelay(MDIO_DELAY);
    MDC_L();
    // LOS_UDelay(MDIO_DELAY);
}
 
/*  MDIO 获取一个bit的数据,MDIO必须已经被配置为输入. */
static uint8_t mdio_bb_get_bit(void)
{
    uint8_t value;
 
    MDC_OUT();
    LOS_UDelay(MDIO_DELAY);
    MDC_H();
    LOS_UDelay(MDIO_READ_DELAY);
    value = GET_MDIO();
    //  LOS_UDelay(MDIO_DELAY);
    MDC_L();
    return value;
}
 
/*
 *  MDIO发送一个数据,MDIO 必须被配置为输出模式.
 *  value:要发送的数据
 *  bits:数据的位数
 *
 *  */
static void mdio_bb_send_num(u16 value, uint8_t bits)
{
    int i;
    MDIO_OUT();
    for (i = bits - 1; i >= 0; i--)
        mdio_bb_send_bit((value >> i) & 1);
}
 
/*
 *  MDIO获取一个数据,MDIO 必须被配置为输入模式.
 *  bits:获取数据的位数
 *
 *  */
static u16 mdio_bb_get_num(u8 bits)
{
    int i;
    u16 ret = 0;
    for (i = bits - 1; i >= 0; i--) {
        ret <<= 1;
        ret |= mdio_bb_get_bit();
    }
 
    return ret;
}
 
/*  Utility to send the preamble, address, and
 *   register (common to read and write).
 */
static void mdio_bb_cmd(uint8_t op, u16 phy, u16 reg)
{
    int i = 0;
    MDIO_OUT(); //设置MDIO引脚为输出引脚
 
    /*发送32bit的1,这个帧前缀域不是必须的,某些物理层芯片的MDIO操作就没有这个域*/
    for (i = 0; i < 32; i++)
        mdio_bb_send_bit(1);
 
 
    mdio_bb_send_bit(0);
    mdio_bb_send_bit(1);
 
    mdio_bb_send_bit((op >> 1) & 1);
    mdio_bb_send_bit((op >> 0) & 1);
 
    mdio_bb_send_num(phy, 5);
    mdio_bb_send_num(reg, 5);
}
 
 
void mdio_set_turnaround(void)
{
    int i = 0;
    MDIO_IN();
    MDC_OUT();
    for (i = 0; i < 1; i++) {
        LOS_UDelay(MDIO_DELAY);
        MDC_H();
        LOS_UDelay(MDIO_DELAY);
        MDC_L();
    }
}
 
u16 smi_reg_read(u16 phy, u16 reg)
{
    u16 ret, i;
 
    mdio_bb_cmd(MDIO_READ, phy, reg);
 
    MDIO_IN();
    // mdio_set_turnaround();
#if 1
    /*  check the turnaround bit: the PHY should be driving it to zero */
    if (mdio_bb_get_bit() != 0) {
        /* PHY didn\'t driver TA low -- flush any bits it may be trying to send*/
        for (i = 0; i < 32; i++)
            mdio_bb_get_bit();
        // bios_log("PHY didn\'t driver TA low! \r\n");
        return 0xFFFF;
    }
#endif
    ret = mdio_bb_get_num(16);
    mdio_bb_get_bit();
    return ret;
}
 
void smi_reg_write(u16 phy, u16 reg, u16 val)
{
 
    mdio_bb_cmd(MDIO_WRITE, phy, reg);
 
    /*  send the turnaround (10) */
    mdio_bb_send_bit(1);
    mdio_bb_send_bit(0);
 
    mdio_bb_send_num(val, 16);
 
    MDIO_IN();
    // mdio_bb_get_bit();
}
 
void smi_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;  
    // 使能GPIOE和GPIOC的时钟  
    RCC_APB2PeriphClockCmd(RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOC, ENABLE); 
    
    // MDIO (PE6) 配置为输出  
    GPIO_InitStructure.GPIO_Pin = MDIO_PIN;  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;  
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; // 推挽输出,因为MDIO是双向的,但在这里我们先配置为输出  
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//GPIO_PuPd (Pull-Up/Pull-Down)设置 GPIO 引脚的内部上拉/下拉电阻
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//GPIO_OType (Output Type)用于设置 GPIO 引脚在输出模式下的类型。
    GPIO_Init(GPIOE, &GPIO_InitStructure);  
  
    // MDC (PC13) 配置为输出  
    GPIO_InitStructure.GPIO_Pin = MDC_PIN;  
    GPIO_Init(GPIOC, &GPIO_InitStructure); 
 
}
  
 
void switch_fiber_port_init(void)
{
    u16 data = 0;
    smi_reg_write(0x08, 0x1F, 0x8000);         // 切换Page至PHY page
 
    smi_reg_write(PORT2_PHY_ADDR, 0x1F, 0x00); // 设置Port2为光口
    data = smi_reg_read(PORT2_PHY_ADDR, 0x1C); // 读出寄存器28原始状态
    data |= (0x01 << 5);// 将bit5置高
    smi_reg_write(PORT2_PHY_ADDR, 0x1C, data); // 将修改后的值写入寄存器
    smi_reg_write(0x08, 0x1F, 0x0); // 切回MAC Page
}
 
 
 
 
 
 
#endif

https://img-blog.csdnimg.cn/direct/ae20d440ec554692bd3b002938de43e2.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值