祝各位道友念头通达
GitHub Gitee 语雀 打赏

arm 实现mdio 读写 88X5113 寄存器

88X5113 芯片说明

该芯片和平常的phy芯片不同, 以下为芯片采用 MDIO 接口实现读写寄存器的说明
image

配置说明

  1. 寄存器分为基地址和扩展地址, 每次读写扩展地址的数据, 需要先将扩展地址 使用 op=00 写进基地址中, 然后在进行读写该基地址, 就会将所需的扩展地址的数据读出来
  2. 我调试的芯片有个问题: 就是mdio读数据的时候,时钟应该时32个和写进去的一样,但实际调试过程中在TA转向的时候, 会少一个时钟周期,导致读出来的数据总是末尾多一个 1

代码实现

IIC_88X5113.h

#ifndef   __IIC_88X5113_h__
#define  __IIC_88X5113_h__
#include "sys.h"
#include "stm32f10x_gpio.h"
#include "delay.h"

#define     RT_OK       0
#define     MODEL_WIRE_ADDR         0x00
#define     MODEL_WIRE_DATA         0x01
#define     MODEL_READ_DATA         0x02
#define     MODEL_READ_INCR         0x03
#endif

IIC_88X5113.c

#include    "IIC_88X5113.h"

#define MCU_4T4R_1_SDA_MDIO         GPIO_Pin_0
#define MCU_4T4R_1_SCL_MDC          GPIO_Pin_1

// #define SET_INPUT 		{GPIOA->CRL &= ~(0xf);GPIOA->CRL |= (0xa);}
#define IIC_DEBUG(...)              printf(__VA_ARGS__)

#define WRITE_MDC(VAL)              GPIO_WriteBit(GPIOA, MCU_4T4R_1_SCL_MDC, VAL)
#define WRITE_MDIO(VAL)             GPIO_WriteBit(GPIOA, MCU_4T4R_1_SDA_MDIO, VAL)
#define READ_MDIO()                 GPIO_ReadInputDataBit(GPIOA, MCU_4T4R_1_SDA_MDIO)
// #define READ_MDIO()                 GPIO_ReadOutputDataBit(GPIOA, MCU_4T4R_1_SDA_MDIO);

#define HIG_SET                     1
#define LOW_SET                     0
void IIC_GPIO_INIT() {
    GPIO_InitTypeDef  GPIO_InitStructure;
    // RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	        //使能PA端口时钟
    GPIO_InitStructure.GPIO_Pin =  MCU_4T4R_1_SCL_MDC;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;    
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = MCU_4T4R_1_SDA_MDIO;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    
    GPIO_WriteBit(GPIOA, MCU_4T4R_1_SCL_MDC, 0);
    GPIO_WriteBit(GPIOA, MCU_4T4R_1_SDA_MDIO, 0);
    
//    IIC_DEBUG("\r\n#INFO: init MDIO GPIO is PA0");
//    IIC_DEBUG("\r\n#INFO: init MDC  GPIO is PA1");
}
void SET_MDIO_ZZZ(){
    GPIOA->CRL = (GPIOA->CRL & 0xFFFFFFF0) | 0x00000008;
    // GPIO_InitTypeDef  GPIO_InitStructure;
    // GPIO_InitStructure.GPIO_Pin =  MCU_4T4R_1_SDA_MDIO;
    // GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    // GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    // GPIO_Init(GPIOA, &GPIO_InitStructure);
    // IIC_DEBUG("\r\n#INFO: set MDIO ZZZ");
}
void SET_MDIO_AFP(){
    GPIO_InitTypeDef  GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin =  MCU_4T4R_1_SDA_MDIO;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_WriteBit(GPIOA, MCU_4T4R_1_SDA_MDIO, 0);
    // IIC_DEBUG("\r\n#INFO: set MDIO AF_PP");
}

void MDC_CLOCK(u32 delay_time, u16 offset_time) {
    delay_us(delay_time - offset_time);
    WRITE_MDC(HIG_SET);
    delay_us(delay_time);
    WRITE_MDC(LOW_SET);
    delay_us(offset_time);
}

void IIC_WIRE(u32 cmd, u32 delay_time, u32 offset_time) {
    int count = 0;
    int cnt = 0;
    u8 bit = 0;
    SET_MDIO_AFP();
    while (1)
    {
        MDC_CLOCK(delay_time, offset_time);
        count++;
        if(count > 31) {
            bit = (cmd>>(31-cnt)) & 0x01;
            if(bit) {   
                WRITE_MDIO(1);  
            } else {  
                WRITE_MDIO(0);  
            }
            // IIC_DEBUG("\r\n#INFO cnt is %d, binary: %d", cnt, bit);
            cnt++;
            if(cnt > 31) {
                break;
            };
        } else {
            WRITE_MDIO(HIG_SET);        //持续拉高
            // IIC_DEBUG("\r\n 测试循环");
        }
    }
    MDC_CLOCK(delay_time, offset_time);
    SET_MDIO_AFP();
}

u16 IIC_READ(u32 cmd, u32 delay_time, u32 offset_time) {
    int count = 0;
    int cnt = 0;
    unsigned char bit = 0;
    unsigned short res = 0;
    unsigned short temp = 0;
    SET_MDIO_AFP();
    while (1)
    {
        MDC_CLOCK(delay_time, offset_time);
        count++;
        if(count > 31) {
            bit = (cmd>>(31-cnt)) & 0x01;
            if(bit) {   
                WRITE_MDIO(1);
            } else {  
                WRITE_MDIO(0);
            }
            // IIC_DEBUG("\r\n#INFO: cnt is %d, binary: %d", cnt, bit);
            cnt++;
            if(cnt > 13) break;
        } else {
            WRITE_MDIO(HIG_SET);        //持续拉高
            // IIC_DEBUG("\r\n 测试循环");
        }
    }
    MDC_CLOCK(delay_time, offset_time);
    SET_MDIO_ZZZ();
    MDC_CLOCK(delay_time, offset_time);
    cnt = 0;
    bit = 0;
    while (1) {
        MDC_CLOCK(delay_time, offset_time);
        cnt++;
        if(cnt <= 16) {
            bit = READ_MDIO();
            temp = ((bit & 0x0001) << (16 - cnt));
            res = res | temp;
            // IIC_DEBUG("\r\n#INFO: cnt is %d, read bit is %d, temp is %04x, res is 0x%04x, res | temp: %04x", cnt, bit, temp, res, res | temp);
        } else {
            break;
        }
    }
    // MDC_CLOCK(delay_time, offset_time);
    SET_MDIO_AFP();
    return res;    
}

int _88X5113_OPER(u32 delay_time, u32 offset_time, u8 opr_addr, u8 model, u16 cdata) {
    u8  phy_addr    =   0x08;                           // 0b00001000 
    u16 res         =   0;
    int cmd         =   0x00000000;
    u16 cdata_temp  =   cdata; 
    u8  cnt         =   0;
    u8  bit         =   0;
    
    // if(model == MODEL_WIRE_DATA) {
    //     cdata = 0x0000;
    //     while (cnt++ < 16) {
    //         bit = (cdata_temp >> (16 - cnt)) & 0x0001;
    //         cdata = cdata | (bit << cnt - 1);
    //         // IIC_DEBUG("\r\n==> cnt: %d, bit: %0x cdata: %4x", cnt, bit, cdata);
    //     }
    // }

    cmd |=  ((model    | 0x00000000)   <<    (28));     //设置 OP|ST
    cmd |=  ((phy_addr | 0x00000000)   <<    (20));     //设置 phyaddr
    cmd |=  ((opr_addr | 0x00000000)   <<    (18));     //设置 DEVADR
    cmd |=  ((0x02     | 0x00000000)   <<    (16));     //设置 TA
    cmd |=  ((cdata    | 0x00000000)   <<    (0	));     //设置 数据位

    // IIC_DEBUG("\r\nOPER_CMD is 0x%08x ", cmd);

    if(model == MODEL_READ_DATA || model == MODEL_READ_INCR) {
        res = IIC_READ(cmd, delay_time, offset_time);
    }

    if(model == MODEL_WIRE_ADDR || model == MODEL_WIRE_DATA) {
        IIC_WIRE(cmd, delay_time, offset_time);
    }
    return res;
}
// u32 delay_time = 500;   //半个时钟周期的时长,单位us
// u32 offset_time = 200;  //时钟延时,必须小于 delay_time
u32 delay_time = 10;   //半个时钟周期的时长,单位us
u32 offset_time = 2;  //时钟延时,必须小于 delay_time
#define OPER_INTERVAL   10
u16 read_REG(u8 opr_addr, u16 opr_regi) {
    u16 res = 0x0000;
    res = _88X5113_OPER(delay_time, offset_time, opr_addr, MODEL_WIRE_ADDR, opr_regi); //00 00 00001 00011 10, 0x008E_0010, 00 00 10000 00011 10, 0x080E_0010 
    delay_ms(OPER_INTERVAL);
    res = _88X5113_OPER(delay_time, offset_time, opr_addr, MODEL_READ_INCR, 0);        //00 1
    delay_ms(OPER_INTERVAL);
    IIC_DEBUG("\r\n#INFO: -read_REG- %2d.%04x=0x%04x", opr_addr, opr_regi, res);
    return res;
}

void wire_REG(u8 opr_addr, u16 opr_regi, u16 conf_dat) {
    _88X5113_OPER(delay_time, offset_time, opr_addr, MODEL_WIRE_ADDR, opr_regi); //00 00 00001 00011 10, 0x008E_0010, 00 00 10000 00011 10, 0x080E_0010 
    delay_ms(OPER_INTERVAL);
    _88X5113_OPER(delay_time, offset_time, opr_addr, MODEL_WIRE_DATA, conf_dat); //00 01 00001 00011 10, 0x108E_0010, 00 01 10000 00011 10, 0x180E_0010 
    delay_ms(OPER_INTERVAL);
}

void IIC_88X5113() {
    u16 res = 0;
    u8  opr_addr = 0x07;    //操作寄存器 基地址
    u16 opr_regi = 0x0000;  //操作寄存器地址
    u16 conf_dat = 0x0010;  //需要写入的数据
    // IIC_DEBUG("1");
    // delay_ms(2000);         //延迟         
    // IIC_DEBUG("2");
    wire_REG(31, 0xF404,0x4000);    //15=1 软复位, 14=1 硬复位,, 先硬复位
    delay_ms(5000);         //延迟

    IIC_DEBUG("\r\n==============   IIC_GPIO_INIT   =================");
    IIC_GPIO_INIT();
    // wire_REG(0x07, 0x0000, conf_dat);

    // wire_REG(7, 0x0000, 0x1000);     //自动协商 line
    // wire_REG(7, 0x1000, 0x1000);     //自动协商 host

    // wire_REG(3, 0xF000, 0x0025);      //line, SR4_P40LN, 31.F00n  1XXX_XXX0_0010_0101
    wire_REG(3, 0xF000, 0x0035);      //line, CR4_P40CN, 31.F00n  1XXX_XX00_0011_0101
    wire_REG(4, 0xF000, 0x0235);      //host, KR4_P40KN, 31.F00n  1XXX_XX10_0011_0101

    wire_REG(31, 0xF437, 0x8000);     //LED1  host side
    wire_REG(31, 0xF438, 0x1160);     //LED1  0001_0110_0110_0000
    wire_REG(31, 0xF439, 0x8000);     //LED2  host side
    wire_REG(31, 0xF43A, 0x1660);     //LED2  0001_0110_0110_0000
    wire_REG(31, 0xF43B, 0x8000);     //LED3  line side
    wire_REG(31, 0xF43C, 0x1660);     //LED3  0000_0110_0110_0000
    wire_REG(31, 0xF43D, 0x8000);     //LED4  line side
    wire_REG(31, 0xF43E, 0x1660);     //LED4  0000_0110_0110_0000

    // res = read_REG(3, 0x1000);        //数据复位
    // wire_REG(3, 0x1000, (0x8000 | res));     //line 复位
    // res = read_REG(4, 0x1000);
    // wire_REG(4, 0x1000, (0x8000 | res));     //host 复位

    // res = read_REG(3, 0x3000);
    // wire_REG(3, 0x3000, (0x1040 | res));     //line 
    // res = read_REG(3, 0xB000);
    // wire_REG(3, 0xB000, (0x2000 | res));     //host 复位

    // wire_REG(31, 0xF404,0x8000);          //15=1 软复位, 14=1 硬复位,  设置之后软复位
    delay_ms(1000);
    while(1) {
        IIC_DEBUG("\r\n=========================================>");
        read_REG(3, 0x9003);   //40G/50G link status 11-10, Local Fault Transmitted, Local Fault Received
        read_REG(4, 0x9003);   //40G/50G link status 11-10, Local Fault Transmitted, Local Fault Received

        read_REG(3, 0xF000);
        read_REG(4, 0xF000);
        read_REG(3, 0x3004);
        read_REG(7, 0x0000);    //自动协商
        read_REG(7, 0x1000);    //自动协商

        //L0 rv_cnt
        // read_REG(3, 0xF104);
        // read_REG(3, 0xF105);
        // read_REG(3, 0xF106);

        //h0 rv_cnt
        // read_REG(4, 0xF104);
        // read_REG(4, 0xF105);
        // read_REG(4, 0xF106);

        // read_REG(3, 0x1000);
        // read_REG(4, 0x1000);   //284c 0010_1000_0100_1101

        delay_ms(1000);
        //led1 灯闪烁
        // delay_ms(500);
        // wire_REG(0x1f, 0xF439, 0x8000);
        // delay_ms(500);
        // wire_REG(0x1f, 0xF439, 0x0000);

    }
}
posted @ 2022-11-10 14:24  韩若明瞳  阅读(629)  评论(0编辑  收藏  举报