I2C로 DDM 폴링 스크립트 짜기: A2h의 어느 바이트가 실시간 값이고 어느 게 임계값인가요
화이트박스 장비의 모듈에서 온도, 전압, 바이어스, 광파워를 바로 뽑아내는 작은 폴러를 만들고 있습니다. 누가 이미 에러 나기 시작한 링크를 눈으로 보는 대신 트렌드 라인을 얻으려고요. NOS는 보기 좋은 값을 출력해주는데, 저는 벤더 임계값을 옆에 붙인 raw 숫자를 원합니다. 모델마다 손으로 알람 레벨을 적지 않고 섞인 옵틱들 사이에서 일관되게 가려고요.
환경:
- Linux 호스트, 일반 I2C mux 뒤의 모듈 케이지, bus 1
- 세 벤더에서 나온 SFP, SFP+, SFP28 옵틱이 섞여 있음
- i2c-tools만으로 읽음, 벤더 SDK 없음
진단 페이지는 이렇게 읽습니다.
# i2cdump -y 1 0x51
그리고 이게 제 초안 파서인데, 여기가 확신이 안 서는 부분입니다.
temp = s16(a2[96:98]) / 256.0
vcc = u16(a2[98:100]) * 100e-6
bias = u16(a2[100:102]) * 2e-6
이미 해본 것:
- 제가 계산한 값을 NOS가 출력하는 것과 비교, 일부 모듈에서는 가깝고 다른 모듈에서는 확실히 어긋남
- SFF-8472를 읽어봤는데, 임계값 블록이 어디서 끝나고 calibration 영역이 어디서 시작하는지 자신 있게 말을 못 하겠음
- 같은 모듈을 직결 버스에서 덤프해서 mux는 배제함, 숫자 동일
그래서, A2h의 실제 맵이 어떻게 되나요? 임계값은 어디에 있고, 실시간 값은 어디서 시작하나요? 그리고 그 raw word들을 믿기 전에 뭔가 처리를 해야 한다고 알려주는 플래그가 어딘가에 있나요?
Comments 7
확실히 어긋나는 값이 뭔가요, 넷 다인가요 아니면 bias랑 power들만인가요? 보통 이게 답 전체를 결정합니다. 하는 김에 A0h도 덤프해서 바이트 92를 보세요. 모듈이 진단 정보를 아예 보고하는지, internal 캘리브레이션인지 external 캘리브레이션인지를 알려줍니다. 보유하신 장비 일부가 external 캘리브레이션인데 파서가 전부 똑같이 취급하고 있다면, 그 불일치는 버그가 아니라 예상된 동작입니다.
트레이 전체에서 A0h 바이트 92를 뽑아봤는데 일관되지 않습니다. 어떤 모듈은 external 캘리브레이션이라고 표시하고 어떤 건 아니고, NOS 출력이랑 안 맞는 게 정확히 external인 것들입니다. 온도랑 전압은 전부 노이즈 범위 안이고, 어긋나는 건 bias랑 두 power입니다. 그러니 오프셋을 잘못 읽는 게 아니라 단계 하나를 놓친 것 같네요. 그 서브셋의 raw word들에 실제로 뭘 해줘야 하나요?
0x51의 A2h는 관심 있으실 네 덩어리로 나뉩니다.
실시간 블록의 단위: 온도는 부호 있음, LSB당 1/256도. 전압은 LSB당 100uV. bias는 2uA. TX와 RX power는 0.1uW. 올려주신 코드는 이미 그 스케일을 정확히 적용하고 있어서, 오프셋은 문제가 아닙니다.
빠진 조각은 방금 찾으신 그 플래그입니다. external 캘리브레이션 모듈에서는 96-105의 word들이 raw ADC 출력이고, 의미를 가지려면 56-95의 상수를 적용해야 합니다. internal 캘리브레이션 모듈은 그 작업을 이미 대신 해준 상태고요. 그 분기가 두 그룹의 차이입니다.
제 말만 믿지 말고 대조할 레이아웃을 원하시면, FreeBSD의 sff8472.h 헤더랑 py-sfp-eeprom 둘 다 필드별로 오프셋을 다 적어놨습니다. 그래도 알람을 걸기 전에 벤더당 모듈 하나씩은 믿을 수 있는 값이랑 대조해서 검증하시길 권합니다.
임계값 블록이 왜 흥미로운 절반인지 덧붙일 만합니다. 0-55의 값들은 실시간 블록이랑 같은 단위라서, 스케일링만 맞으면 벤더 고유의 alarm이랑 warning 포인트를 공짜로 얻고 모델별로 한계값을 지어낼 필요가 없습니다. 그것만으로도 누군가의 예쁜 출력기를 파싱하는 대신 A2h를 직접 읽을 이유가 됩니다.
섞인 트레이에서 이걸 돌려본 실전 팁 하나. 폴링 간격을 적당히 유지하세요. 그 페이지는 평범한 I2C read고 모듈 컨트롤러는 빠르지 않습니다. mux 뒤에 있는 버스에서 모든 모듈을 매초 두드리면, 그래프에서 딱 옵틱이 흔들리는 것처럼 보이는 짧은 read들을 모으게 되기 딱 좋습니다.
그 표현은 조심해서 쓰세요. 사람들이 "항상 상수를 적용해라"로 읽고서 왜 숫자가 더 나빠졌는지 의아해하거든요. 56-95의 상수는 A0h의 바이트 92가 external 캘리브레이션이라고 말할 때만 적용됩니다. internal 캘리브레이션 모듈에 그걸 돌리면 멀쩡한 값을 엉터리로 만들어버립니다. 모듈이 그 작업을 이미 해놨으니까요. 플래그를 먼저 읽고, 그걸로 분기하고, 파서에 두 경로를 다 남겨두고, 특정 모듈이 어느 경로를 탔는지 로그로 남겨서 나중에 두 실패 모드를 구분할 수 있게 하세요.
온도도 같은 부류의 함정이 있습니다. 부호가 있는 값이거든요. unsigned로 파싱하면 0보다 낮은 건 뭐든 터무니없이 높은 숫자로 돌아오는데, 처음으로 추운 아침에 호출당하면 아주 재밌습니다.
제 쪽 업데이트입니다. A0h 바이트 92로 분기해서 모듈이 external이라고 할 때만 상수를 적용합니다. bias랑 두 power 다 이제 대조 가능했던 모든 모듈에서 NOS 출력이랑 일치하고, 온도랑 전압은 애초에 문제였던 적이 없습니다. 모듈 두 개는 여전히 진단 정보는 있다고 하는데 못 믿을 임계값을 돌려줘서, 그건 제 자체 한계값으로 폴백하고 모른 척하는 대신 인벤토리에 표시해두고 있습니다. 완전히 끝났다고는 안 하겠지만, 위의 맵이 정확히 제가 놓치고 있던 부분이었습니다.
이게 프로덕션에 들어가기 전에 하나만 더. 바이트 110은 같은 페이지에 있고 상태와 제어를 담고 있는데, 제어 쪽 절반에 TX disable이 포함됩니다. 폴러는 애초에 A2h에 쓸 일이 없어야 하는데, 라이브러리가 어딘가에서 read-modify-write를 하거나 운영 중인 박스에서 테스트하다 i2cset을 잘못 치면 유저스페이스에서 고객 링크를 떨어뜨릴 수 있습니다. 폴러에서는 버스를 read-only로 열고, 쓰기 경로는 일부러 실행해야 하는 별도 도구에 남겨두세요.
같은 바이트가 TX fault랑 RX LOS도 주는데, 둘 다 아날로그 값 옆에 내보낼 만합니다. RX power는 정상인데 LOS가 assert된 모듈은 그냥 낮게 읽히는 모듈이랑은 완전히 다른 이야기를 하고 있는 겁니다.