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

news2024/10/6 20:31:01
#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

对于RTL8305NB,要从电口模式切换为光口模式,主要操作涉及到PHY page的切换和特定寄存器的配置。以下是详细的操作步骤:

  1. PHY Page切换
    • 首先,需要访问PHY地址8的寄存器31。这个寄存器用于Page的切换。
    • 向PHY地址8的寄存器31写入值0x8000,这将使芯片切换到PHY page。
  2. 光口模式配置
    • 在切换到PHY page后,需要配置特定的寄存器以将端口设置为光口模式。
    • 根据参考文章提供的信息,通常需要修改PHY page下的某个寄存器的某个位来配置光口模式。具体而言,是将寄存器28的bit5置高(设置为1)。

// 假设有一个函数用于向PHY寄存器写入值  
void write_phy_register(uint8_t phy_address, uint8_t register_address, uint16_t value) {  
    // 实现向PHY寄存器写入的逻辑  
    // ...  
}  
  
// 切换到PHY Page  
write_phy_register(8, 31, 0x8000); // 切换到PHY Page

// 假设有一个函数用于读取PHY寄存器的值  
uint16_t read_phy_register(uint8_t phy_address, uint8_t register_address) {  
    // 实现从PHY寄存器读取值的逻辑  
    // ...  
    return value;  
}  
  
// 配置光口模式  
uint16_t register28_value = read_phy_register(8, 28); // 读取寄存器28的当前值  
register28_value |= (1 << 5); // 将bit5设置为1(光口模式)  
write_phy_register(8, 28, register28_value); // 将修改后的值写回寄存器28


void switch_fiber_port_init(void)
{
    unsigned short data = 0;
    write_phy_register(0x08, 0x1F, 0x8000);         // 切换Page至PHY page
    write_phy_register(PORT2_PHY_ADDR, 0x1F, 0x00); // 设置Port2为光口
    data = read_phy_register(PORT2_PHY_ADDR, 0x1C); // 读出寄存器28原始状态
    data |= (0x01 << 5);// 将bit5置高
    write_phy_register(PORT2_PHY_ADDR, 0x1C, data); // 将修改后的值写入寄存器
    write_phy_register(0x08, 0x1F, 0x0); // 切回MAC Page
}

总结

  • 访问PHY地址8的寄存器31,并写入0x8000以切换到PHY page。
  • 在PHY page下,将寄存器28的bit5置高,从而配置端口为光口模式。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1885394.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

秋招Java后端开发冲刺——基础篇5(String集合)

一、String String类是Java中字符串操作类&#xff0c;位于java.lang包下String类型对象的底层使用字符数组char[]存储字符串&#xff0c;由final修饰且没有提供公共的修改方法&#xff0c;因此String对象是不可变的。常见方法 方法名作用trim()去掉字符串首尾空字符split(分…

[AI Perplexica] AI驱动的开源搜索引擎

之前&#xff0c;我们有介绍过 Perplexcity 现在&#xff0c;开源市场上&#xff0c;也有一款对标产品 Perplexica &#xff0c;我们来看下 界面很像 介绍 Perplexica是一个开源的、由AI驱动的搜索工具或搜索引擎&#xff0c;它深入互联网寻找答案。受到Perplexity AI的启发…

警惕!帕金森老人身体恶化七大征兆,家有老人必看!

帕金森病&#xff0c;这个在老年人群中越来越常见的神经系统疾病&#xff0c;以其独特的“静止性震颤、运动迟缓、肌强直和姿势平衡障碍”等四大症状&#xff0c;成为许多家庭心中的痛。然而&#xff0c;帕金森病的进展并非一蹴而就&#xff0c;而是有着一系列的身体变坏征兆。…

vue3源码(六)渲染原理-runtime-dom

1、从入口文件看实现 项目入口文件 import { createApp } from vue import ./style.css import App from ./App.vuecreateApp(App).mount(#app)文件位置core\packages\runtime-dom\src\index.ts 保证了render的唯一性 // // rendererOptions 是patchProp 和nodeOps的合集&a…

材料科学SCI期刊,IF=6+,超高录用率,2个月录用

一、期刊名称 Advanced Electronic Materials 二、期刊简介概况 期刊类型&#xff1a;SCI 学科领域&#xff1a;材料科学 影响因子&#xff1a;5.3 中科院分区&#xff1a;2区 三、期刊简介 Advanced Electronic Materials 是一个跨学科论坛&#xff0c;旨在为材料科学、…

YOLOv8-对注意力机制模型进行通道剪枝-同时实现涨点和轻量化【附代码】

文章目录 前言视频效果文章概述必要环境一、训练自己的模型1、 训练命令2、 训练参数解析 二、模型剪枝1、 对训练好的模型将进行剪枝2、 剪枝代码详解1.解析命令行参数2. 定义剪枝函数3. 定义剪枝结构4. 更新注意力机制5. 保存更新后的模型6. 主函数 三、剪枝后的训练运行命令…

Windows 11 安装 安卓子系统 (WSA)

How to Install Windows Subsystem for Android (WSA) on Windows 11 新手教程&#xff1a;如何安装Windows 11 安卓子系统 说明 Windows Subsystem for Android 或 WSA 是由 Hyper-V 提供支持的虚拟机&#xff0c;可在 Windows 11 操作系统上运行 Android 应用程序。虽然它需…

c++读取文件时出现中文乱码

原因&#xff1a;UTF-8格式不支持汉字编码 解决&#xff1a;改成ANSI&#xff0c;因为ANSI编码支持汉字编码

生成式人工智能将如何改变网络可访问性

作者&#xff1a;Matthew Adams 受 Be My Eyes 和 OpenAI 启发的一项实验&#xff0c;尝试使用 ChatGPT 4o 实现网页无障碍 在 Elastic&#xff0c;我们肩负着一项使命&#xff0c;不仅要构建最佳的搜索驱动型 AI 平台&#xff0c;还要确保尽可能多的人喜欢使用该平台。我们相…

深入剖析vLLM:大模型计算加速系列之调度器策略探索

原文&#xff1a; 图解大模型计算加速系列&#xff1a;vLLM源码解析2&#xff0c;调度器策略(Scheduler) 目录 收起 前期提要与本期导览 一、入口函数 二、SequenceGroup 2.1 原生输入 2.2 SequenceGroup的作用 2.3 SequenceGroup的结构 三、add_request()&#xff1a…

[python][Anaconda]使用jupyter打开F盘或其他盘文件

jupyter有一个非常不好的体验&#xff0c;就是不能在界面切换到其他盘来打开文件。 使用它&#xff0c;比较死板的操作是要先进入文件目录&#xff0c;再运行jupyter。 以Windows的Anaconda安装了jupyter lab或jupyter notebook为例。 1&#xff0c;先运行Anaconda Prompt 2&…

儿童房间灯哪个牌子的好?几款儿童房间灯具品牌分享

对于视力正处于发育阶段的儿童而言&#xff0c;台灯已不仅仅是一个简单的照明工具。它不仅驱散夜幕下的阴霾&#xff0c;还能为儿童的眼部保驾护航。一款优质的护眼台灯更是不可或缺的守护者。然而&#xff0c;面对市场上琳琅满目的选择&#xff0c;怎样选出一款合适的护眼台灯…

​Stable Diffusion史上最全插件,已打包整理,12个常用插件你肯定用得上!

还在于有丰富的第三方插件&#xff0c;即我们在安装部署之后安装汉化插件的界面 插件安装方式可以是“可下载->加载扩展列表”&#xff0c;然后从列表选择或搜索插件下载&#xff0c;或直接选择“从网站安装”&#xff0c;填写插件的git仓库地址。一般我们从扩展列表搜索即可…

【Python】已解决:pymssql._pymssql.OperationalError 关于关键字‘distinct’的语法错误

文章目录 一、分析问题背景二、可能出错的原因三、错误代码示例四、正确代码示例五、注意事项 已解决&#xff1a;pymssql._pymssql.OperationalError 关于关键字‘distinct’的语法错误 一、分析问题背景 在使用pymssql库与SQL Server数据库进行交互时&#xff0c;有时会遇到…

WPF在.NET9中的重大更新:Windows 11 主题

在2023年的2月20日&#xff0c;在WPF的讨论区&#xff0c;WPF团队对路线的优先级发起了一次讨论。 对三个事项发起了投票。 第一个是Windows 11 主题 第二个是更新的控件 第三个是可空性注释 最终Windows 11 主题得票最高&#xff0c;WPF团队2023-2024的工作优先级就是Windows…

UE4_材质_水体的反射与折射制作_Ben教程

在这个教程中&#xff0c;将制作水的反射和折射&#xff0c;上个教程&#xff0c;我们主要讲了制作水涟漪&#xff08;水面波纹&#xff09;和水滴法线混合&#xff0c;水深计算&#xff0c;我们首先要谈的是反射和产生折射的问题。我们将所有从干扰从场景中分离出去&#xff0…

微信小程序 canvas 处理图片的缩放移动旋转问题

这里使用到了一个插件&#xff0c;canvas-drag&#xff0c;来实现大部分功能的 上效果 直接上代码吧~ wxml <div class"container"><canvas-drag id"canvas-drag" graph"{{graph}}" width"700" height"750" ena…

页面加载503 Service Temporarily Unavailable异常

最近发现网页刷新经常503&#xff0c;加载卡主&#xff0c;刷新页面就正常了。 研究之后发现是页面需要的js文件等加载失败了。 再研究之后发现是nginx配置的问题。 我之前为了解决一个漏洞检测到目标主机可能存在缓慢的HTTP拒绝服务攻击 把nginx的连接设置了很多限制&#…

JSONpath语法怎么用?

JSONPath 可以看作定位目标对象位置的语言&#xff0c;适用于 JSON 文档。 JSONPath 与 JSON 的 关系相当于 XPath 与 XML 的关系&#xff0c; JSONPath 参照 XPath 的路径表达式&#xff0c;提供了描述 JSON 文档层次结构的表达式&#xff0c;通过表达式对目标…

点云处理实操 点云平面拟合

目录 一、什么是平拟合 二、拟合步骤 三、数学原理 1、平面拟合 2、PCA过程 四、代码 一、什么是平拟合 平面拟合是指在三维空间中找到一个平面,使其尽可能接近给定的点云。最小二乘法是一种常用的拟合方法,通过最小化误差平方和来找到最优的拟合平面。 二、拟合步骤…