Modules SFP pour fibre optique : Communication avec l’EEPROM et lecture des paramètres de diagnostique (DDM – Digital Diagnostic Monitoring).
Montage et applications autour de la Raspberry Pi et de l’Arduino.
Les modules SFP correspondent à un standard de communication par fibre optique (Wikipedia/SFP).
Ils simplifient grandement l’utilisation de fibres optiques car ils sont standardisé. Il est possible de sélectionner un module SFP selon sa connectique avec la fibre optique, sa longueur d’onde, sa puissance, son débit, ses performances, sa robustesse, etc…
De plus, ils s’occupent de toutes la gestion analogique de l’électronique pour le laser et la photodiode, filtrage et remise en forme des signaux et présentent directement des signaux numériques sur paires différentielles pour le circuit qui les accueille.
[Eoin] a utilisé une Raspberry Pi et un Arduino pour communiquer avec des modules SFP via leur interface de communication I2C normalisée et je voulais vous partager ses conclusions.Connecteurs des modules SFP :
Toutes les pins VeeT ou VeeR sont à la masse.
Les Pin 15 et Pin 16 nécessitent du +3.3V.
Pin 4: MOD-Def(2) – ligne de données SDA de l’interface i2c.
Pin 5: MOD-Def(1) – ligne d’horloge SCL de l’interface i2c.
Pin 6: MOD-Def(0) correspond à un signal de présence du module dans le système (les modules SFP sont hot-pluggable). Ce signal est connecté à la masse en interne dans le module et doit être scruté par le circuit de gestion du module SFP§. Une résistance de pull-up est nécessaire.
Accès de l’EEPROM avec la Raspberry Pi
Selon les spécifications INF-8074, les modules SFP contiennent une EEPROM permettant de stocker diverses informations sur leurs caractéristiques techniques et peuvent présenter des paramètres de diagnostique si cette fonctionnalité est implémentée dans le module (SFF-8472). On accède donc à deux adresses de périphériques esclaves sur le bus I²C : l’adresse 0xA0, correspondant à l’EEPROM, qui contient les caractéristiques du module et du vendeur, et l’adresse 0xA2 qui permet d’accéder aux paramètres de diagnostiques.
[Eoin] a utilisé l’interface I2C d’une Raspberry Pi pour lire et écrire dans les paramètres de l’EEPROM des modules SFP. Il est ainsi en mesure de voir les caractéristiques du module ou de le personnaliser afin de le faire passer pour un autre module, par exemple pour rendre un module no name compatible avec un routeur Cisco. À condition que l’EEPROM ne soit pas verrouillée en écriture comme je l’ai déjà vu sur certains modules SFP.Lecture/écriture de l’EEPROM avec une Raspberry Pi
Il faut d’abord raccorder les lignes I2C du module SFP à la Raspberry Pi. Pour simplifier, [Eoin] a utilisé un circuit Cisco TwinGig acheté sur ebay. Il s’agit d’une carte fille permettant de raccorder 2 modules SFPs sur un appareil Cisco de type routeur. Ne reste plus qu’à repiquer les lignes I2C sur les résistances R57 (SDA) and R54(SCL), et à alimenter la carte en 3,3V.
Sur la Raspberry Pi, il a connecté les 4 fils suivants sur le port GPIO :
- GPIO Pin 1: 3.3V
- GPIO Pin 6: 0V
- GPIO Pin 3: SDA
- GPIO Pin 5: SCL
Ci-dessous, l’ensemble raccordé :
Tester le fonctionnement
Il faut maintenant configurer la Raspberry Pi pour être en mesure de dialoguer avec le module SFP via le port I²C.
1) Installer i2c-tools :
sudo apt-get install i2c-tools
2) Assurez-vous que le module soit bien installé et pas blacklisté :
pi@raspberrypi ~ $ cat /etc/modprobe.d/raspi-blacklist.conf
Si c’est le cas, supprimer le ‘#’ devant “blacklist i2c-bcm2708”
# blacklist spi and i2c by default (many users don't need them) blacklist spi-bcm2708 #blacklist i2c-bcm2708
3) Testez la connexion. Vous devez voir l’adresse du SFP (0x50) sur le bus I²C. Si vous ne voyez pas cette adresse, il doit y avoir un problème dans le câblage. Pourquoi l’adresse 0x50 sachant qu’on a parlé de 0xA0 juste avant ? Et bien parce-que ça dépends de si on tient compte ou pas du bit0 (RW) spécifiant un accès en lecture ou écriture. Si on décale les bits de 0xA0 d’un cran vers la droite, onn obtient bien 0x50. Normalement l’adresse devrait être sur 7 bits et donc bien 0x50, mais personnellement, je suis plus partisan de lire l’octet normalement avec le bit RW et donc dire 0xA0. Ça respecte la position des différents bits…
pi@raspberrypi ~ $ i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: 50 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- pi@raspberrypi ~ $
Si vous voyez l’adresse 0x51 (0xA2 décalé vers la droite comme précédemment), cela signifie que votre module SFP supporte aussi le diagnostique digitale (DOM-Digital Optical Monitoring).
4) Lecture de l’EEPROM à l’adresse 0x50 en utilisant I2Cdump.
pi@raspberrypi ~ $ i2cdump -y 1 0x50 No size specified (using byte-data access) 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef 00: 03 04 07 00 00 00 01 00 00 00 00 01 0d 00 00 00 ???...?....??... 10: 37 1b 00 00 52 61 73 70 62 65 72 72 79 20 50 69 7?..Raspberry Pi 20: 20 20 20 20 00 00 30 d3 51 46 42 52 2d 35 37 36 ..0?QFBR-576 30: 36 4c 50 20 20 20 20 20 20 20 20 20 03 52 00 c6 6LP ?R.? 40: 00 1a 00 00 31 32 33 34 35 36 37 38 39 4a 4b 20 .?..123456789JK 50: 20 20 20 20 30 35 30 33 31 30 20 20 00 00 00 95 050310 ...? 60: 00 00 02 ab 89 12 ea 3e 00 04 1c 5f 6a 0a de 10 ..?????>.??_j??? 70: 74 11 3b 00 00 00 00 00 00 00 00 00 ef 19 f8 08 t?;.........???? 80: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ 90: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ a0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ b0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ c0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ d0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ e0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ f0: ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ................ pi@raspberrypi ~ $
Pour comprendre le détail de l’EEPROM, il faut se référer aux dernières spécifications SFP MSA.To understand the details of the EEPROM refer to the latest SFP MSA.
Pour lire tous les octets de l’EEPROM et les stocker dans un tableau appelé A50 :
int xio; int fd1; unsigned char A50[128]; printf ("Read SFP EEPROM\n"); xio = wiringPiI2CSetup (0x50); if (xio < 0){ fprintf (stderr, "xio: Unable to initialise I2C: %s\n", strerror (errno)); return 1; } /*Read in the first 128 bytes 0 to 127*/ for(i=0; i <128; i++){ fd1 = wiringPiI2CReadReg8 (xio,i); A50[i] = fd1; } //print vendor id bytes 20 to 35 memcpy(&vendor, &A50[20],16); vendor[16] = '\0'; printf("\nVendor = %s",vendor);
Vous pouvez écrire un octet ou un tableau contenant les valeurs souhaitées en utilisant la fonction wiringPiI2CWriteReg8 :
unsigned char mybytes[] = {0xff}; wiringPiI2CWriteReg8(xio, counter, mybytes[0]);
Pour vérifier si le Cheksum correspond à celui écrit sur l’EEPROM :
sum = 0; for (counter = 0; counter <0x3f; counter++) sum = (A50[counter] + sum); sum = sum & 0xff; cc_base = A50[0x3f]; //sum stored in address 63. printf("value of cc_base = %x and sum= %x\n",cc_base,sum); printf ("\n");
Pour lire la valeur de la longueur d’onde du transceiver :
int wave; //3 bytes. 60 high order, 61 low order. 62 is the mantissa wave = ((int) A50[60]<<8) | ((int) A50[61]); printf("\nWavelength = %d.%d",wave,A50[62]);
Le dump de l’EEPROM du module SFP ci-dessous à le VendorID “Raspberry Pi”. Il est aisé de lire et afficher des valeurs. Par exemple :
Transceiver is 1000Base SX Wavelength = 850.0 Vendor = Raspberry Pi Serial = 123456789JK cc_base = c6 and cc_ext = 95
Pour rendre un moduel SFP compatible avec les systèmes Cisco, il faut rendre les deux Cheksums valides (cc_base et cc_ext), il faut également calculer des octets particuliers aux adresses 0x60 à 0x7F du champs Vendor Specific.
Vous pouvez trouver les détails ici : http://forum.nag.ru/
Le code développé par [Eoin]est disponible ici : https://github.com/sonicepk/sfppi
Accès aux informations de diagnostique
Maintenant que nous avons vu comment communiquer avec le module SFP, nous allons maintenant voir comment lire les données de diagnostique, à savoir la tension d’alimentation, de polarisation du laser, la température et les puissances optiques en émission et en réception.
[Eoin] a utilisé un Arduino pour lire les données de diagnostique du module SFP qui sont ensuite affichées sur un écran LCD, réalisant ainsi un puissance-mètre optique “low-cost”, simple à réaliser.#include <Wire.h> #include <math.h> #include <LiquidCrystal.h> // LCD interface pins LiquidCrystal lcd(12, 11, 5, 4, 3, 2); const byte EEPROM_ID = 0x51; int A51[128]; void setup() { Wire.begin(); Serial.begin(9600); // set up the LCD's number of columns and rows: lcd.begin(16, 2); } byte I2CEEPROM_Read (unsigned int address) { byte data; Wire.beginTransmission(EEPROM_ID); Wire.write(address); Wire.endTransmission(); Wire.requestFrom(EEPROM_ID,(byte)1); while(Wire.available() == 0); data = Wire.read(); return data; } void loop() { for (int i = 96; i <106; i++) { A51[i] = I2CEEPROM_Read(i); } float temp = A51[96] + (float) A51[97]/256; float optical_rx = 10 * log10((float)(A51[104]<<8 | A51[105]) * 0.0001); lcd.setCursor(0, 0); lcd.print ("Temp = "); lcd.print (temp); lcd.print ((char)223); //degree symbol lcd.print ("C");</div> <div> lcd.setCursor (0, 1); lcd.print ("RX = ");</div> <div> lcd.print (optical_rx); lcd.print (" dBm"); delay(1000); }
Code également disponible sur https://github.com/sonicepk/sfpduino
Sources :