L
我们做光接入设备,需要在主控Linux上实时采集板上光模块的DDM数据并上报网管。把驱动层到应用层的实现思路整理一下,供做类似产品的同行参考。
## 硬件链路
SFP/SFP+模块通过I2C总线挂在主控上:
- 地址0x50:只读EEPROM,存模块ID、厂商、波长、兼容性信息
- 地址0x51:DDM数字诊断,存收发光功率、偏置电流、温度、电压
## 内核侧:I2C读取
用Linux的i2c-dev字符设备,用户态直接读:
#include <linux/i2c.h>
#include <fcntl.h>
int fd = open("/dev/i2c-0", O_RDWR);
// 先写寄存器地址,再读DDM页
关键点:
1. 不同厂商模块的DDM寄存器偏移略有差异,要兼容处理
2. 光功率是16位定点数,高字节在前,按0.1dBm/LSB换算
3. 读不到要重试,I2C偶发毛刺不要直接判死
## 应用层:定时采集与阈值告警
每5秒读一次,存环形缓冲,对比模块自带的高低告警门限:
- TX/RX光功率越限 → 上报告警
- 温度超温 → 降额或告警
- 偏置电流异常 → 模块老化预警
## 实际踩的坑
**坑1:浮点换算精度**
光功率定点换算错一个字节,读数差十几dBm,务必用模块数据手册的公式核对。
**坑2:热插拔不重新枚举**
模块拔出再插,I2C设备节点不会自动重建,应用要监听热插拔事件后重新open。
**坑3:多模块总线冲突**
一条I2C挂多个模块,地址相同,需要用I2C mux通道切换,不能直接并发读。
## 选型配合
整机批量落地时,模块最好选出厂就带完整DDM校准、门限可读写的货源,省掉在驱动里补校准的工作量。我们配套用fiberuni的光模块,逐只带光功率测试报告,嵌入式侧采集上来的离散度小,网管侧告警基本不用人工复核。
## 小结
DDM监控本质就是I2C读EEPROM+定点换算+阈值判断,难点不在读数据,而在多厂商兼容、热插拔处理和异常重试。
有做过类似光模块网管采集的同行吗?你们门限告警是放设备端还是网管侧统一算?
## 硬件链路
SFP/SFP+模块通过I2C总线挂在主控上:
- 地址0x50:只读EEPROM,存模块ID、厂商、波长、兼容性信息
- 地址0x51:DDM数字诊断,存收发光功率、偏置电流、温度、电压
## 内核侧:I2C读取
用Linux的i2c-dev字符设备,用户态直接读:
#include <linux/i2c.h>
#include <fcntl.h>
int fd = open("/dev/i2c-0", O_RDWR);
// 先写寄存器地址,再读DDM页
关键点:
1. 不同厂商模块的DDM寄存器偏移略有差异,要兼容处理
2. 光功率是16位定点数,高字节在前,按0.1dBm/LSB换算
3. 读不到要重试,I2C偶发毛刺不要直接判死
## 应用层:定时采集与阈值告警
每5秒读一次,存环形缓冲,对比模块自带的高低告警门限:
- TX/RX光功率越限 → 上报告警
- 温度超温 → 降额或告警
- 偏置电流异常 → 模块老化预警
## 实际踩的坑
**坑1:浮点换算精度**
光功率定点换算错一个字节,读数差十几dBm,务必用模块数据手册的公式核对。
**坑2:热插拔不重新枚举**
模块拔出再插,I2C设备节点不会自动重建,应用要监听热插拔事件后重新open。
**坑3:多模块总线冲突**
一条I2C挂多个模块,地址相同,需要用I2C mux通道切换,不能直接并发读。
## 选型配合
整机批量落地时,模块最好选出厂就带完整DDM校准、门限可读写的货源,省掉在驱动里补校准的工作量。我们配套用fiberuni的光模块,逐只带光功率测试报告,嵌入式侧采集上来的离散度小,网管侧告警基本不用人工复核。
## 小结
DDM监控本质就是I2C读EEPROM+定点换算+阈值判断,难点不在读数据,而在多厂商兼容、热插拔处理和异常重试。
有做过类似光模块网管采集的同行吗?你们门限告警是放设备端还是网管侧统一算?

