Compare commits
61
Commits
9d61b1aa43
..
V1.2.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a1967bc9a | ||
|
|
496e3ab650 | ||
|
|
29ec4c2239 | ||
|
|
d73b119dc3 | ||
|
|
79a3604ac4 | ||
|
|
b84188322d | ||
|
|
b4148c9571 | ||
|
|
eacb218da8 | ||
|
|
4648f936c7 | ||
|
|
9cdd651d79 | ||
|
|
4f2f9ed090 | ||
|
|
1a06367ade | ||
|
|
1fbdcc23d6 | ||
|
|
0d2faef565 | ||
|
|
a9c56ee1d4 | ||
|
|
78a8f641c9 | ||
|
|
25e1ce0068 | ||
|
|
215fed6e95 | ||
|
|
db44f72352 | ||
|
|
9cc41f6fbd | ||
|
|
bc2b529c3a | ||
|
|
c3b0d49145 | ||
|
|
59861cf953 | ||
|
|
43314444e9 | ||
|
|
4854da8518 | ||
|
|
15ea776b82 | ||
|
|
03d609cc1f | ||
|
|
5e1e4a6a8f | ||
|
|
a31c186142 | ||
|
|
1b8d5a8e91 | ||
|
|
cac37583e7 | ||
|
|
802ee4d467 | ||
|
|
166b53983f | ||
|
|
ef7cbdffd4 | ||
|
|
ae8941a844 | ||
|
|
a6a12cdf2c | ||
|
|
e38d24c775 | ||
|
|
9a11c1d5bb | ||
|
|
cbef5865ec | ||
|
|
8714bbb773 | ||
|
|
d8bf1f7a41 | ||
|
|
da39122c43 | ||
|
|
b66ae47a58 | ||
|
|
d065db7d71 | ||
|
|
419b680980 | ||
|
|
4ed283d0ca | ||
|
|
491e807cf8 | ||
|
|
18ce7a1a73 | ||
|
|
d1b5cfea0b | ||
|
|
5e63e3da6b | ||
|
|
855b7a6e30 | ||
|
|
310f897067 | ||
|
|
fedf697977 | ||
|
|
ababb2c3d1 | ||
|
|
a9c3dafc22 | ||
|
|
4088a828c6 | ||
|
|
afb7b1e283 | ||
|
|
fd35857d80 | ||
|
|
cdf38a09ae | ||
|
|
8aa5c90166 | ||
|
|
224ddbd21c |
@@ -0,0 +1,29 @@
|
||||
# =============================================================================
|
||||
# 換行符政策
|
||||
# -----------------------------------------------------------------------------
|
||||
# 這個 repo 同時被 Windows(Tera Term 端編輯)與 SONiC/Linux(DUT 端執行)使用,
|
||||
# 所以必須明確指定,不能靠各機器的 core.autocrlf。
|
||||
#
|
||||
# 踩過的坑:margin.sh 帶著 CRLF 進 repo,scp 到 DUT 後 bash 直接掛:
|
||||
# -bash: $'\r': command not found
|
||||
# syntax error near unexpected token `$'{\r''
|
||||
# settings/*.conf 同樣危險 —— margin_init 是用 source 讀它們的,未加引號的
|
||||
# 賦值(例如 CB_I2C_CH=6)會變成 "6\r",SWB transport 會拿著壞掉的通道號去打 I2C。
|
||||
# =============================================================================
|
||||
|
||||
# 在 DUT / Linux 上執行或被 source 的,一律 LF
|
||||
*.sh text eol=lf
|
||||
*.conf text eol=lf
|
||||
*.py text eol=lf
|
||||
*.txt text eol=lf
|
||||
*.md text eol=lf
|
||||
|
||||
# Tera Term macro 只在 Windows 上跑,維持 CRLF;標成 -text 讓 git 原樣保存,
|
||||
# 避免對既有檔案產生大量純換行符的假 diff
|
||||
*.ttl -text
|
||||
|
||||
# 二進位,不要做任何轉換
|
||||
*.xlsx binary
|
||||
*.docx binary
|
||||
*.pdf binary
|
||||
*.h5 binary
|
||||
+13
-1
@@ -12,9 +12,15 @@ For_AI/
|
||||
!**/logs/.gitkeep
|
||||
!**/Logs/.gitkeep
|
||||
|
||||
# 打包輸出
|
||||
# monitor 腳本的執行期產物(原始擷取、pid、狀態)
|
||||
*.raw
|
||||
*.pid
|
||||
*.state
|
||||
|
||||
# 打包輸出:產出不進 git,打包工具本身要進
|
||||
publish/*
|
||||
!publish/.gitkeep
|
||||
!publish/publish.sh
|
||||
|
||||
# Office 暫存檔
|
||||
~$*
|
||||
@@ -22,3 +28,9 @@ publish/*
|
||||
# 客戶板 schematic 原始檔(機密,勿入 repo)
|
||||
*.DSN
|
||||
*.dsn
|
||||
|
||||
# 尚未上機驗證的腳本暫存區(不入 repo,測過再搬進 src/)
|
||||
tmp/
|
||||
|
||||
# mlucas 的 ELF binary(~99 MB),DUT image 已內含,不入 repo
|
||||
src/Script_ABC_Blanton/hammer/
|
||||
|
||||
+474
-80
@@ -11,8 +11,8 @@
|
||||
| Script | 階段 | 做什麼 |
|
||||
|--------|------|--------|
|
||||
| `1_Blanton_Script_A.ttl` | **Pre-test / Baseline** | 登入、對時、載入 shell 工具、清 PCIe AER、抓 PCIe tree / margin / PMON / dmesg 基線 |
|
||||
| `2_Blanton_Script_B.ttl` | **Stress / Soak** | 開 CPU / DDR / SSD / USB / PCIe / I2C 壓力程序,之後進無限迴圈每輪抓 fan / temp / margin |
|
||||
| `3_Blanton_Script_C.ttl` | **Post-test / Verdict** | 殺掉壓力程序、再抓一次 PMON / dmesg / PCIe AER,比對 stress log 判定 |
|
||||
| `2_Blanton_Script_B.ttl` | **Stress / Soak** | 開 CPU / DDR / SSD / USB 壓力程序 + 啟動 SWB loopback 線速流量,之後進無限迴圈每輪抓完整 PMON / margin |
|
||||
| `3_Blanton_Script_C.ttl` | **Post-test / Verdict** | 殺掉壓力程序、停流量並出 per-pair TX/RX 報表、再抓一次 PMON / dmesg / PCIe AER,比對 stress log 判定 |
|
||||
|
||||
DUT 端的實際取數能力則來自一組 **bash 工具庫**(`Blanton_Script/`),這一層才是真正碰硬體的地方:
|
||||
CB FPGA 的 PCIe BAR(`pcimem`)→ FPGA 內建 I2C / VI2C master → 板上 VRM、溫度感測器、
|
||||
@@ -36,8 +36,16 @@ LTC2980 margin 控制器。TTL 只負責「按順序 `sendln` 並把畫面收進
|
||||
| I2C / PMBus 路徑 | CB FPGA F3 OpenCores I2C master、CB FPGA F3 VI2C proxy、CPU 原生 bus(`i2cset`/`i2cget`) |
|
||||
| 電源 margin | LTC2980(= 2 × LTC2977)over PMBus,LINEAR16 編碼 |
|
||||
| 錯誤計數來源 | Linux PCIe AER sysfs(`aer_dev_*`)、EDAC sysfs(`dimm_ce/ue_count`) |
|
||||
| 平台監控 | SONiC `show platform *`(pmon container) |
|
||||
| 壓力測試 | `mlucas-avx2`(AMD CPU)、`~/hammer/tools/stress_*.py`(DDR / SSD / USB / PCIe / I2C) |
|
||||
| 平台監控 | SONiC `show platform *`(pmon container,含 `leak status` / `leak channels`) |
|
||||
| BMC 存取 | host 端 `bmc-manager run "<cmd>"`(不需對 BMC 開 SSH,繞開其 busybox 工具鏈);`bmc-first-enroll` / `bmc-manager version\|status` |
|
||||
| 背景工作管理 | `bgctl run/list/stop --all/reset`(平台工具);長時間 ping 用 `systemd-run --unit=` 掛成 transient unit |
|
||||
| 管理網路 | iproute2(`ip link set` / `ip address replace` / `ip route replace ... metric`)+ `ping -I` |
|
||||
| 測試 session | `hw-test-session start\|log\|status\|finish`;job log 收在 `/host/hw-eval/jobs/` |
|
||||
| 風扇控制 | max31790 driver rebind(`/sys/bus/i2c/drivers/max31790/{bind,unbind}`)+ `fan-speed-control.sh <%>` |
|
||||
| 100G PRBS | `bcmcmd -n <unit> -c 'dsh -c "phy diag <phy> prbs …"'`(set / prbsstat STArt / get / Ber / STOp / clear) |
|
||||
| 壓力測試 | `mlucas-avx2`(AMD CPU)、`bgctl run` 排程的 `memtester` / `qfx5252-stress-ssd` / `qfx5252-stress-usb` |
|
||||
| 資料面流量 | `bcmcmd`(Broadcom drivshell)VLAN loopback + `tx` burst,switch unit 0 / 1 |
|
||||
| 流量報表 | DUT 上 awk(`blanton_traffic_linespeed report`);離線 `python3 tools/bcm_mibpair_report_V1.1.0.py` |
|
||||
| 版本控制 | Git(NAS + Gitea 私有 remote;**不推 GitHub,含客戶 NDA 資料**) |
|
||||
|
||||
> ⚠️ **無編譯步驟。** TTL 與 bash 都是直譯執行,「build」等同「把 `src/Script_ABC_Blanton/` 複製到
|
||||
@@ -70,16 +78,19 @@ LTC2980 margin 控制器。TTL 只負責「按順序 `sendln` 並把畫面收進
|
||||
│ ├ blanton_icb_vi2c.sh vi2c_* (ICB/PDB proxy) │
|
||||
│ ├ blanton_temp_sensor.sh temp_cb / temp_icb / temp_all │
|
||||
│ ├ blanton_pwr_data.sh pwr_data / pwr_data_pdb │
|
||||
│ ├ blanton_traffic_linespeed.sh │
|
||||
│ │ init/clear/show/start/stop/ps/report (bcmcmd) │
|
||||
│ └ LTC2980_Margin_Script/ margin_init / margin_status ... │
|
||||
│ │
|
||||
│ ~/hammer/tools/ 壓力程序(mlucas-avx2, stress_*.py) │
|
||||
│ SONiC CLI show platform fan/temperature/... │
|
||||
│ bcmcmd -n 0|1 Broadcom drivshell(VLAN loopback / tx) │
|
||||
│ SONiC CLI show platform fan/temperature/leak/... │
|
||||
│ Linux sysfs aer_dev_* / edac mc0/rank* │
|
||||
└───────────────────────┬──────────────────────────────────────┘
|
||||
│ pcimem /sys/bus/pci/devices/0000:03:00.<fn>/resource0
|
||||
▼
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ CB FPGA (PCIe EP,4 個 Function) │
|
||||
│ CB FPGA (PCIe EP,4 個 Function;BDF 於 source 時自動偵測) │
|
||||
│ F0 local regs:RST_CAUSE_REG 0xD90 / SWB 0xD94,0xD98 │
|
||||
│ F3 I2C master Ch0..Ch17 (base 0x300, stride 0x20) │
|
||||
│ F3 VI2C→ICB Ch0..Ch4 (base 0x780, stride 0x20) │
|
||||
@@ -101,16 +112,35 @@ Blanton_TTL_Script/
|
||||
│
|
||||
├── CLAUDE.md # 專案記憶 & 給 Claude 的指令
|
||||
├── ARCHITECTURE.md # 本架構文件
|
||||
├── .gitignore # secret/ + For_AI/ + logs 規則
|
||||
├── .gitignore # secret/ + For_AI/ + tmp/ + hammer/ + logs + publish 產出
|
||||
├── .gitattributes # 換行符政策:.sh/.conf 釘 LF、.ttl 保持 CRLF
|
||||
│
|
||||
├── docs/ # 規格與狀態文件(客戶提供 / 專案產出)
|
||||
│ ├── Blantons_FPGA_Registers.md # FPGA 暫存器規格(markdown 正本,查 offset 用)
|
||||
│ ├── Blantons_FPGA_Registers_draft.docx # 同上,客戶原始 docx
|
||||
│ ├── Blantons_FPGA_Registers_Map_draft.xlsx
|
||||
│ ├── Blantons_PCIe_AER_and_DDR_EDAC_checks.pdf # AER / EDAC 檢查點依據
|
||||
│ └── TTL_Script_Blanton_Status_20260814.xlsx # ⭐ 三支腳本逐項 Status(OK / On-Going + Owner)
|
||||
│ ├── ADPM12200CMLZxx_DS_Datasheet_*.pdf # PDB brick 手冊(PAGE 與 DIRECT 係數的來源)
|
||||
│ ├── Blanton_Test_Flow.drawio # A/B/C + 熱安規四支的測試流程圖(draw.io)
|
||||
│ ├── LTC2980_channel_map.csv # 9 個 settings/*.conf 合併:Board,CONN,Ch,NetName,Vnom(144 列)
|
||||
│ ├── TTL_Script_Blanton_Status_20260814.xlsx
|
||||
│ └── TTL_Script_Blanton_Status_20260817.xlsx # ⭐ 最新:三支腳本逐項 Status(OK / On-Going + Owner)
|
||||
│
|
||||
├── tools/ # Host 端輔助腳本(log 解析、報表產生)
|
||||
├── tools/ # Host / 離線端輔助腳本
|
||||
│ ├── bcm_mibpair_report_V1.1.0.py # 離線解析 drivshell log → per-pair TX/RX + PASS/FAIL
|
||||
│ ├── traffic_loopback_vlan_setting.txt # bcmcmd VLAN 30..137 建立 + 成對 pbm(cdN <-> cdN+32)
|
||||
│ ├── traffic_loopback_start.txt # bcmcmd tx 100 length=512 VLantag=<vid>
|
||||
│ ├── traffic_loopback_vlan_remove.txt # bcmcmd vlan remove <vid> pbm=...
|
||||
│ │ # ↑ 三份為手動貼上用的原始指令表,
|
||||
│ │ # blanton_traffic_linespeed.sh 是其 bash 版
|
||||
│ ├── 100G_PRBS.txt # 100G PRBS 原始指令(port_prbs_monitor.sh 的來源)
|
||||
│ ├── TR518.txt # 內建封包測試 tr 518 → blanton_tr518.sh
|
||||
│ ├── BER_Test.txt # 全機 PRBS BER 指令 → blanton_ber.sh
|
||||
│ ├── Multiphase_{high3,low3,comboA,comboB,Save}.txt # → blanton_multiphase_margin.sh
|
||||
│ ├── Multiphase_Netname # 38 條軌的 net 名稱(區塊順序對應)
|
||||
│ ├── 100G_Traffic.txt # ce0 VLAN 138 打流 → blanton_traffic_linespeed.sh
|
||||
│ ├── fan_ctrl.txt # MAX31790 unbind/bind + fan-speed-control.sh 30
|
||||
│ └── gen_channel_map.sh # settings/*.conf → docs/LTC2980_channel_map.csv(需 gawk)
|
||||
│
|
||||
├── secret/ # 🚫 gitignored — DUT 密碼、per-unit BDF、COM 設定
|
||||
│ ├── README.md # ✅ committed — 用途索引
|
||||
@@ -119,22 +149,34 @@ Blanton_TTL_Script/
|
||||
│
|
||||
├── For_AI/ # 🚫 gitignored — AI 協作素材(波形截圖、草稿)
|
||||
│
|
||||
├── publish/ # 可交付的打包輸出(Blanton_Script_ABC_v<ver>_<date>/ + zip)
|
||||
├── publish/
|
||||
│ ├── publish.sh # ✅ committed — 打包工具(版號讀 Script A 檔頭)
|
||||
│ └── Script_ABC_Blanton_<Ver>/ # 🚫 產出,gitignored(-z 另出同名 .zip)
|
||||
│
|
||||
├── tmp/ # 🚫 gitignored — 尚未上機驗證的腳本暫存區
|
||||
│ └── blanton_reboottest.sh # 5_..._Reboot_Cycle.ttl 的 bash 版,測過再搬進 Blanton_Script/
|
||||
│
|
||||
└── src/
|
||||
└── Script_ABC_Blanton/ # ← Tera Term 的工作目錄(整包給測試員)
|
||||
│
|
||||
├── config.ttl # 全域設定:testcase 名、EN_Margin / EN_log、三個 prompt 字串
|
||||
├── 4_Blanton_Script_thermal_safety.ttl # 熱 / 安規:獨立跑,不接 A→B→C
|
||||
├── 5_Blanton_Script_Reboot_Cycle.ttl # 重開機循環:獨立跑,while 1 無止境(未上機驗證)
|
||||
├── config.ttl # 全域設定:testcase 名、EN_Margin / EN_TX_FIR / EN_log / EN_timestamp、
|
||||
│ # 風扇與 SWB 宣告、SSD/USB/BMC_USB 壓力秒數、三個 prompt 字串
|
||||
├── hammer/ # 🚫 gitignored — mlucas ELF binary(~99 MB),DUT image 自帶,
|
||||
│ # publish.sh 也排除;Script B / Script 4 只負責 chmod +x 後執行
|
||||
├── 1_Blanton_Script_A.ttl # Pre-test:登入 → 對時 → source 工具 → 清 AER → 抓基線
|
||||
├── 2_Blanton_Script_B.ttl # Stress:開壓力程序 → while 1 每輪抓 fan/temp/margin
|
||||
├── 3_Blanton_Script_C.ttl # Post-test:kill → 再抓一次 → 比對 stress log
|
||||
│
|
||||
├── utils/ # 可 include 的取數片段(TTL,無狀態、只 wait+sendln)
|
||||
│ ├── pcie_bus.ttl # lspci -tvvv / -vv
|
||||
│ ├── setup_pmon.ttl # show platform summary/fan/temperature/psu/voltage/current/ssd
|
||||
│ ├── show_dmesg.ttl # date + dmesg grep error/fail/warning
|
||||
│ ├── setup_pmon.ttl # show platform summary/fan/temperature/psustatus/voltage/
|
||||
│ │ # current/ssdhealth/leak status/leak channels + TPM(11 項)
|
||||
│ ├── show_dmesg.ttl # dmesg -T 合併 error 正則 + i2c 過濾 + dmesg -C 清空
|
||||
│ ├── show_margin_status.ttl # source margin_status_all.sh(掃 9 顆 LTC2980)
|
||||
│ ├── kill_all_process.ttl # kill $(jobs -p)
|
||||
│ ├── wait_init.ttl # 輪詢 show platform temperature 直到 pmon 起來
|
||||
│ ├── show_pcie_error_reg.ttl # 舊的合併版(已被下列 per-device 版取代)
|
||||
│ ├── show_pcie_error_reg_TH6_SWB0.ttl # EP 01:00.0 + RP 00:01.1
|
||||
│ ├── show_pcie_error_reg_TH6_SWB1.ttl # EP 02:00.0 + RP 00:01.2
|
||||
@@ -152,12 +194,41 @@ Blanton_TTL_Script/
|
||||
├── blanton_icb_vi2c.sh # CB F3 VI2C proxy → ICB/PDB(Ch0~Ch4)
|
||||
├── blanton_temp_sensor.sh # TMP75 / TMP432 讀溫(CB Ch10 mux + ICB VI2C Ch2)
|
||||
├── blanton_pwr_data.sh # SWB VRM + PDB brick 的 Vin/Vout/Iout/Temp 表
|
||||
├── blanton_traffic_linespeed.sh # SWB loopback 線速流量(bcmcmd unit 0/1)
|
||||
│ # init/clear/show/start/stop/ps/report/run
|
||||
├── mgmt_ping_monitor.sh # 10G/1G 管理網路 ping 監控(iproute2)
|
||||
│ # eth0→TARGET_10G、eth1→TARGET_1G,兩張卡同時持續 ping
|
||||
├── port_prbs_monitor.sh # 100G uplink PRBS 測試(bcmcmd phy diag)
|
||||
│ # ⚠️ V1.1.9 起 A/B/C 內註解掉的呼叫已整段刪除,只剩手動執行
|
||||
├── blanton_ber.sh # 全機 SerDes BER 掃描(phydiag prbs / prbsstat)
|
||||
├── bcm_dsc_scan.sh # 全機 SerDes DSC dump(phydiag <port> dsc,~445 port × 2 unit)
|
||||
│ # 由 EN_TX_FIR 控制,A 與 C 各掃一次;單次約 10 分鐘
|
||||
├── bcm_dsc_parse.sh # DSC raw log → <prefix>_lane.csv / _pm.csv(純 sh + awk)
|
||||
├── blanton_multiphase_margin.sh # 多相 VRM margin(原生 i2c,38 條軌)
|
||||
├── pwr_brick.sh # PDB / CPB power brick 讀值(VI2C ch4)
|
||||
├── nfc_polling.sh # NFC tag 背景輪詢 + PASS/FAIL 統計
|
||||
├── blantons_nfc_validate.py # NFC/NCI 驗證工具(廠商提供,未修改)
|
||||
├── blanton_tr518.sh # TR518 封包測試,量功耗前的負載來源
|
||||
├── TH6_SWB0_power_readback.sh # SWB0 19 條軌 V×I + 總功耗
|
||||
├── TH6_SWB1_power_readback.sh # SWB1 同上
|
||||
│ # ⚠️ 已納入交付,但 A/B/C 的呼叫仍註解掉(bring-up 中)
|
||||
├── usb_target.sh # 偵測 USB 裝置節點/掛載點(排除系統碟)
|
||||
├── bmc_monitor.sh # BMC 監控:free -m + I2C 寫入/讀回圖樣測試
|
||||
├── bmc_monitor_ddr.sh # ⚠️ 已停用:V1.1.9 起 B/C 內的註解區塊已刪除,DDR 壓力走 bgctl + bmc-manager
|
||||
│ # ↑ 三支都要 chmod +x 才能跑(見 Key Constraints)
|
||||
└── LTC2980_Margin_Script/ # 電壓 margin 子專案(另有獨立 repo)
|
||||
├── margin.sh # margin_init/status/set/apply_profile/save
|
||||
# # v2.7.0:margin_save all / margin_save blanton
|
||||
├── settings/*.conf # 一個 .conf = 一顆 LTC2980(CB + SWB0/1 × CONN13~16)
|
||||
├── profiles/*.conf # 16-ch 批次組合(comboA/B、high3/5、low3/5、normal、off)
|
||||
├── profiles/*.conf # 16-ch 批次組合。SWB 為 per-CONN:
|
||||
# # combo_SWB_CONN13~16_{high,low}(百分比對應該片的軌)
|
||||
# # comboA/comboB_{CB,SWB_CONN13~16}(互補棋盤配對)
|
||||
# # 通用:high3/5、low3/5、normal、all_off
|
||||
├── script/*_all.sh # 跨 9 顆 LTC2980 的批次 status / apply / save
|
||||
├── Ref/margin_command_trace.md # 指令追蹤參考(SWB 章節已標過期,見文件內警告)
|
||||
└── logs/ # margin 操作 log
|
||||
# 註:v2.6.0 起不再內含 blanton_cb_i2c.sh / blanton_fpga_pcimem.sh 的複本,
|
||||
# 改由 _swb_find_backend 往上層 Blanton_Script/ 找共用版
|
||||
```
|
||||
|
||||
---
|
||||
@@ -169,15 +240,20 @@ Blanton_TTL_Script/
|
||||
### 1. `config.ttl` — 全域測試參數(TTL 變數)
|
||||
|
||||
```ini
|
||||
strTestcase = "Margin" ; 測項名,進 log 檔名
|
||||
project_name = "Blanton" ; 專案名,進 log 檔名
|
||||
EN_Margin = 1 ; 1=跑 margin 掃描, 0=跳過
|
||||
strTestcase = "ENV" ; 測項名(ENV/EMC/Margin...),進 log 檔名
|
||||
EN_Margin = 0 ; 1=跑 margin 掃描, 0=跳過
|
||||
EN_log = 1 ; 1=logopen 存檔, 0=不存
|
||||
FAN_SPEED = 100 ; 傳給 fan-speed-control.sh 的風扇轉速 (%),預設全速
|
||||
SWB_UNIT0 = 1 ; 這台有 switch unit 0(流量與 wait_init 都依此)
|
||||
SWB_UNIT1 = 1 ; 這台有 switch unit 1
|
||||
prompt_login = "sonic login:"
|
||||
prompt_sonic = "admin@sonic:~$"
|
||||
prompt_sonic_root = "root@sonic:~#"
|
||||
```
|
||||
|
||||
> `SWB_UNIT0` / `SWB_UNIT1` 兩個都是 0 時,`wait_init.ttl` 直接 bypass、A/B/C 的流量段整段跳過。
|
||||
|
||||
Log 檔名規則:`<mdir>\Logs\<project_name>_<strTestcase>_<YYYYmmdd-HHMMSS>.log`
|
||||
|
||||
### 2. `settings/<board>.conf` — 一顆 LTC2980(16 channel)
|
||||
@@ -188,11 +264,57 @@ Log 檔名規則:`<mdir>\Logs\<project_name>_<strTestcase>_<YYYYmmdd-HHMMSS>.l
|
||||
| `CB_I2C_CH` | int | `TRANSPORT="swb"` 時的 FPGA I2C 通道(6/7/8/9) |
|
||||
| `CHIPS[]` | string[2] | `"bus:addr"`,index 0 → CH0~7、index 1 → CH8~15 |
|
||||
| `CHIP_PRE_CMD[]` / `CHIP_POST_CMD[]` | string[1] | mux 切換等前後置指令,`;` 分隔多筆 |
|
||||
| `CH<n>_VNOM` | string | 標稱電壓(`"-"` = 未使用 / NC) |
|
||||
| `CH<n>_VNOM` | string | 這條軌的**基準電壓**(`"-"` = 未使用 / NC) |
|
||||
| `CH<n>_NET` | string | 電路 net name(對照 schematic) |
|
||||
|
||||
Channel 定址:`ch / 8` → `CHIPS[]` index,`ch % 8` → LTC2977 PMBus PAGE(0x00~0x07)。
|
||||
|
||||
**`VNOM` 自 2026-08-30 起是「Blanton 實測中位數」,不是規格標稱值。** 144 條軌裡有 86 條
|
||||
被改上去 +0.8% ~ +2.5%(例:`PVDD3_3V_SYNTH_LDO_*` 3.3 → 3.38、`P0V9_AVDD_*` 0.9 → 0.915、
|
||||
`PVDD0_8V_T3` 0.8 → 0.82)。這件事影響兩處,**不是只有顯示**:
|
||||
|
||||
- `margin_status` 的偏差 % 是對 `VNOM` 算的 —— 以前一條穩定在 0.756 V 的軌顯示 `+0.80%`,
|
||||
現在顯示 `0.00%`。**舊 log 的偏差 % 不能跟新 log 直接比。**
|
||||
- `margin_set` 的 high / low / OV / UV **全部由 `VNOM` 推算**(`VNOM × (1 ± change%)`),
|
||||
所以整個 margin 視窗跟著平移。同樣下 `+3%`,實際打到的絕對電壓比以前高。
|
||||
|
||||
**SWB 通道與位址對應(2026-08-19 上機驗證,`ababb2c`):**
|
||||
|
||||
| FPGA I2C 通道 | 板 / 接頭 | LTC2977 位址(lo / hi) |
|
||||
|---|---|---|
|
||||
| Ch6 | SWB0 CONN14 / CONN16 | CONN14 `0x5C`,`0x5E` ; CONN16 `0x62`,`0x64` |
|
||||
| Ch8 | SWB0 CONN13 / CONN15 | CONN13 `0x5C`,`0x5E` ; CONN15 `0x62`,`0x64` |
|
||||
| Ch7 | SWB1 CONN14 / CONN16 | CONN14 `0x5C`,`0x5E` ; CONN16 `0x62`,`0x64` |
|
||||
| Ch9 | SWB1 CONN13 / CONN15 | CONN13 `0x5C`,`0x5E` ; CONN15 `0x62`,`0x64` |
|
||||
|
||||
> 同一顆 LTC2980 的兩個位址**相差 2**(7-bit,由規格書 8-bit 配對除以 2 而來),不是 1。
|
||||
> 兩張板共用一條通道,所以同通道上的位址必須互斥 —— 上表兩組(`0x5C/0x5E` 與 `0x62/0x64`)不重疊。
|
||||
|
||||
**同一批 LTC2977 也掛在原生 i2c bus 上**(2026-08-27 上機驗證):Blanton 的 SONiC 把 CB FPGA F3
|
||||
的這四條 I2C 通道同時註冊成 kernel i2c adapter,因此除了 `cb_pmbus_*` → pcimem 這條路,
|
||||
還可以用 `i2cset -f -y <bus>` 直接打到同一顆晶片:
|
||||
|
||||
| FPGA F3 通道 | Linux bus | CB FPGA 路徑 | 原生 i2c 路徑 |
|
||||
|---|---|---|---|
|
||||
| Ch6 | 13 | `cb_pmbus_write 6 <addr> …` | `i2cset -f -y 13 <addr> …` |
|
||||
| Ch7 | 14 | `cb_pmbus_write 7 <addr> …` | `i2cset -f -y 14 <addr> …` |
|
||||
| Ch8 | 15 | `cb_pmbus_write 8 <addr> …` | `i2cset -f -y 15 <addr> …` |
|
||||
| Ch9 | 16 | `cb_pmbus_write 9 <addr> …` | `i2cset -f -y 16 <addr> …` |
|
||||
|
||||
`margin.sh` 的 `margin_save blanton` 走原生路徑(`MARGIN_BLANTON_STORE` 表),
|
||||
其餘功能仍走 `TRANSPORT="swb"` 的 FPGA 路徑。兩條路到的是同一顆 LTC2977,
|
||||
**不要同時用**(同一條匯流排上兩個 master 語意的存取)。
|
||||
|
||||
**全通道 net / 電壓對照:`docs/LTC2980_channel_map.csv`**(9 個 `.conf` × 16ch = 144 列,
|
||||
欄位 `Board,CONN,Ch,NetName,Vnom`)。查「某個 net 在哪片哪個 channel」比翻 9 個 `.conf` 快。
|
||||
CSV 是產出物,不是正本 —— 改完 `.conf` 用 `./tools/gen_channel_map.sh` 重產,別手改 CSV。
|
||||
兩件從表上看得出來、改 `.conf` 時要記得的事:
|
||||
|
||||
- **SWB0 與 SWB1 的 net / 電壓完全相同**,差別只在 `CHIPS[]` 的 bus(`0:` vs `1:`)與 `CB_I2C_CH`。
|
||||
也就是說有兩份會各自漂移的重複資料 —— 改了 SWB0 沒改 SWB1,不會有任何東西擋你。
|
||||
- **8 個 NC 通道**(SWB0/1 CONN14 的 CH10/CH11/CH13、CONN15 的 CH10)在 CSV 裡以
|
||||
`NC` / `-` 原樣保留,不是漏掉;濾掉它們會讓 page 編號對不上。
|
||||
|
||||
### 3. `profiles/*.conf` — 16-ch 批次 margin 組合
|
||||
|
||||
```bash
|
||||
@@ -235,9 +357,16 @@ PROFILE_CHANNELS=( "0:high:8" "1:low:8" ... ) # "channel:operation:change_perc
|
||||
| I210 1G NIC | `0000:07:00.0` | `0000:00:02.4` |
|
||||
| NVMe SSD | `0000:06:00.0` | `0000:00:02.1` |
|
||||
|
||||
> ⚠️ **BDF 是 per-unit 的**。`blanton_fpga_pcimem.sh` 的 `FUNCT0..3_RES` 已經改過三次
|
||||
> (04:00.x → 03:00.x → 05:00.x → 03:00.x)。換 DUT 一定要先 `lspci -Dnn | grep -i fpga` 重新確認,
|
||||
> 同理 `show_pcie_error_reg_*.ttl` 裡的 BDF 也要跟著校。
|
||||
> ⚠️ **BDF 是 per-unit 的,而且只解決了一半。**
|
||||
> `blanton_fpga_pcimem.sh`(V1.5.0 起)**已改為 source 時自動偵測**,不再需要每台改檔:
|
||||
> 掃 sysfs 找 `vendor == 0x1590`(HPE)且 `.0`~`.3` 四個 function 都有 `resource0` 的裝置 →
|
||||
> 退回 `lspci -Dnn` 名稱比對 → 再退回 `FPGA_BDF_FALLBACK`(`0000:03:00`)。
|
||||
> 偵測結果會印一行 `[INFO] CB FPGA BDF = ...`,並存在 `FPGA_BDF_ACTIVE`。
|
||||
> 換 DUT 後可用 `fpga_rescan` 重測,或 `FPGA_BDF=0000:05:00 fpga_rescan` 手動釘住。
|
||||
>
|
||||
> **但 `utils/show_pcie_error_reg_*.ttl` 裡的 BDF 仍然是寫死的**(上表那 7 組),
|
||||
> 自動偵測完全沒有涵蓋到它們。換 DUT 時這些 TTL 還是要人工校對,否則 AER 會讀到錯誤的裝置
|
||||
> ——甚至讀到不存在的路徑而整段 `No such file or directory`。
|
||||
|
||||
---
|
||||
|
||||
@@ -245,15 +374,32 @@ PROFILE_CHANNELS=( "0:high:8" "1:low:8" ... ) # "channel:operation:change_perc
|
||||
|
||||
| 模組 | 進入點 | 功能 |
|
||||
|------|--------|------|
|
||||
| **Script A(Pre-test)** | `1_Blanton_Script_A.ttl` | root 登入 → `mkdir ./logs` → `date -s` 對時 → source 五個 bash 工具 → 清/讀 7 組 PCIe AER → `lspci -tvvv/-vv` → margin 全掃 → PMON 七項 → dmesg 三 grep → `messagebox` 提示接 Script B |
|
||||
| **Script B(Stress)** | `2_Blanton_Script_B.ttl` | `mlucas-avx2 -cpu 0:15` + 5 份 `stress_mem.py` + `stress_hhmd/ssd/pcie/usb.py` 全部背景執行 → `jobs` 確認 → `while 1` 每輪 `show platform fan` / `temperature` / margin |
|
||||
| **Script C(Post-test)** | `3_Blanton_Script_C.ttl` | `kill $(jobs -p)` → PMON + dmesg 再抓一次 → 7 組 AER 再抓一次 → `cat` mlucas / stress_ssd log → 完成 messagebox |
|
||||
| **FPGA 暫存器存取** | `cb_fpga <fn> <addr> [data]` | pcimem 打 `resource0` + BAR 相對 offset,32-bit word;`pmc/icb/swb0/swb1_fpga` 走 VSPI 窗口 |
|
||||
| **Script A(Pre-test)** | `1_Blanton_Script_A.ttl` V1.2.1 | root 登入 → `date -s` 對時 → 清 job log → **收掉前一輪殘留**(`hw-test-session finish` → `bgctl reset --yes` → `bgctl stop --all` → `bgctl list` 確認清空)→ `hw-test-session start` → **設定風扇轉速** → **等資料面就緒**(`wait_init.ttl`)→ DUT 清單(boot/version/fwutil/syseeprom/ssdhealth/TPM/NVMe)→ BMC enroll + version/status → source bash 工具 → 清/讀 7 組 PCIe AER + `ras-mc-ctl --summary` → `lspci` → margin → PMON → dmesg → **10G/1G 管理網路 ping** → **NFC 基線**(start → 30s → stop → report)→ 100G uplink 設定與狀態 → **BER 基線掃描**(依 `SWB_UNIT`,V1.2.1 新增)→ **一輪流量基線** → **SerDes DSC 基線**(`EN_TX_FIR`)→ `show uptime` |
|
||||
| **Script B(Stress)** | `2_Blanton_Script_B.ttl` | **V1.1.8 起 `mlucas-avx2 -cpu 0:15` 由 `systemd-run --unit=mlucas-amm`(`Type=exec`、`Restart=always`)啟動,不再是 shell 的 `&` 背景 job** + `bgctl run` 的 `memtester` / SSD / USB 壓力(v1.1.7 起 SSD/USB 的 `--runtime`/`--passes` 讀 `config.ttl` 的 `SSD_RUNTIME`/`SSD_COUNT`、`USB_RUNTIME`/`USB_COUNT`;BMC memtester 不帶次數 = 跑到被停) + BMC DDR(`bmc-manager run memtester`)→ BMC USB net test(探測 cdc_ncm 介面,`systemd-run` 掛 `BMC_USB_RUNTIME` 秒的 ping,V1.1.8 前寫死 4 小時)→ 啟動 mgmt ping 監控 → **啟動 NFC 輪詢** → `jobs` / `systemctl is-active mlucas-amm` / `bgctl list` → traffic(依 `SWB_UNIT`)→ `while 1` 每輪 PMON + `bgctl list`/`jobs`/`systemctl is-active mlucas-amm` + `sleep 60`(**V1.1.4 起 margin 不在迴圈內**;V1.2.0 起等待走 DUT 端 `sleep` 而非 macro 端 `pause`)|
|
||||
| **Script C(Post-test)** | `3_Blanton_Script_C.ttl` | `kill $(jobs -p)` + **`systemctl stop mlucas-amm`**(systemd unit 不是 shell job,`jobs -p` 抓不到)+ `bgctl stop --all` / `reset` + 停 BMC USB unit、mgmt ping 與 **NFC 輪詢** → PMON + dmesg → 7 組 AER + `ras-mc-ctl` → BMC USB `journalctl` **寫進 `log/bmc_usb_net.log`**(不再印在 console) → `ip -s link show eth0/eth1` → `cat` mlucas log(並 `cp` 進 job 目錄一起帶走)→ **NFC `report`** → traffic `stop` + `report` → **SerDes DSC 收尾**(`EN_TX_FIR`)→ **BER 掃描**(依 `SWB_UNIT`)→ NVMe 健康 → `show reboot-cause` → **margin 掃描**(`EN_Margin`,V1.1.4 由 Script B 移來)→ `uptime` → **job log 複製到 USB(帶時戳)** → `exit` + wait『Script done』→ `hw-test-session finish` |
|
||||
| **Script 4(Thermal / Safety)** | `4_Blanton_Script_thermal_safety.ttl` | **獨立腳本,不接 A→B→C。** Script A 式的環境建立(登入 / session / 風扇 / `wait_init` / DUT 清單 / BMC / PCIe 清除 / `pcie_bus` / PMON / dmesg)→ **滿載**(`mlucas-avx2 -cpu 0:15`,V1.1.8 起與 Script B 同樣掛成 `mlucas-amm` systemd unit + `blanton_tr518.sh start`)→ `while 1`:PMON + `TH6_SWB0/1_power_readback.sh` + `bgctl list` / `jobs` / `systemctl is-active mlucas-amm`,`pause 60`。**沒有收尾段** —— 中斷後 DUT 仍在 `port cd lb=mac` / `l2 learn off` / `test mode nr=yes`,且 CPU 仍滿載,要手動 `blanton_tr518.sh stop` + `systemctl stop mlucas-amm` |
|
||||
| **Script 5(Reboot Cycle)** | `5_Blanton_Script_Reboot_Cycle.ttl` | **獨立腳本,不接 A→B→C。** `while 1`:登入 → `sudo -i` → 對時 → 風扇 → **Check Pt1~Pt13**(DUT/BMC info、mgmt ping、NFC、SSD、USB、BMC USB、port status + 15s traffic、BER、NVMe、platform data、dmesg i2c、PCIe error counters)→ `show uptime` → `reboot` → `wait "Booting in blind mode"`。`cnt_cycle` 每輪 +1 印在標頭。**沒有結束條件** —— 要停就關掉 Tera Term 的 macro。**尚未上機驗證** |
|
||||
| **SWB loopback 流量** | `blanton_traffic_linespeed <sub> [-u 0\|1\|all]` | `init`(VLAN 30..137,成對 `cdN`/`cdN+32`)→ `clear` → `start`(`tx 200 length=324 PatternRandom=yes`,v0.7.0 起)→ `stop` → `report`(per-pair TX/RX 交叉比對 PASS/FAIL);另有 `ps`(link/speed)與 `run`(一條龍)。**V0.6.0 起含 100G uplink `ce0`**(VLAN 138):它沒有 loopback 對象,靠 **ingress mirror 打回自己**維持循環,`report` 最後一列就是它,底下再接一份跨 unit summary |
|
||||
| **FPGA 暫存器存取** | `cb_fpga <fn> <addr> [data]`、`fpga_rescan` | pcimem 打 `resource0` + BAR 相對 offset,32-bit word;BDF 於 source 時自動偵測;`pmc/icb/swb0/swb1_fpga` 走 VSPI 窗口 |
|
||||
| **CB I2C / PMBus** | `cb_i2c_init/scan/read/write`、`cb_pmbus_read/write/linear16` | FPGA F3 OpenCores master,**讀用 Repeated START**(SMBus/PMBus 裝置必需) |
|
||||
| **ICB / PDB 存取** | `vi2c_init/scan/read/write`、`vi2c_scan_all` | CB F3 VI2C proxy,~3.3 ms/reg,取代 VSPI 的 ~18 ms/reg(後者會踩 SMBus 25–35 ms timeout) |
|
||||
| **溫度** | `temp_cb` / `temp_icb` / `temp_all` | TMP75(12-bit 左靠齊 ×0.0625)、TMP432(含 RANGE bit 的 −64 偏移、remote1/2) |
|
||||
| **電源資料** | `pwr_data` / `pwr_data_pdb` / `pwr_pdb_id` | SWB VRM 全軌 Vin/Vout/Iout/Temp 對齊表;MP29816 解析度**執行期從 `MFR_VOUT_SCALE_LOOP` 讀**,不寫死 |
|
||||
| **電壓 Margin** | `margin_init/status/set/apply_profile/save` + `*_all.sh` | 9 顆 LTC2980(CB CONN13、SWB0/1 CONN13~16)批次 high/low margin 與狀態掃描 |
|
||||
| **電壓 Margin** | `margin_init/status/set/apply_profile/save` + `*_all.sh` | 9 顆 LTC2980(CB CONN13、SWB0/1 CONN13~16)批次 high/low margin 與狀態掃描。`VNOM` 為 Blanton 實測中位數(2026-08-30);SWB 的 profile 是 per-CONN,套錯 CONN 會 margin 到錯的軌且不報錯。v2.6.0 起 SWB 路徑真正接上共用 cb_i2c 後端,並有 `margin_swb_info/probe/scan/reset/sem` 除錯包裝 |
|
||||
| **Multiphase VRM margin** | `blanton_multiphase_margin.sh {high3\|low3\|comboA\|comboB\|save} [-u 0\|1\|all]` | 兩片 SWB 的多相控制器(**不是** `margin.sh` 管的 LTC2980),走原生 i2c bus:SWB0 = `/dev/i2c-13`+`-15`、SWB1 = `-14`+`-16`。每片 19 條軌、共 38 條,逐條印 `SWB0_0V9_ANLG0 - 0.930V Configure Done`。`save` 沒有 per-rail 對應,只印 `Multiphase Save All`。⚠️ `save` 是 `STORE_USER_ALL`(0x15,TH6 core 用 0x17)**永久寫 NVM**;⚠️ 與 `margin.sh` 從兩側摸同一批軌,**不可同時用** |
|
||||
| **Margin 寫 NVM** | `margin_save` / `margin_save all` / `margin_save blanton` | ⚠️ 永久寫入。`0x15` 送 PMBus **send-byte**(不帶 data byte)。`all` = 依 `settings/` 走 9 顆、跑完還原原本載入的板子;`blanton` = 本平台捷徑,18 顆全走原生 i2c bus(`MARGIN_BLANTON_STORE` 表),不需 `margin_init`。每筆之間 `MARGIN_STORE_SETTLE`(0.5s),工具**不 poll busy bit** |
|
||||
| **管理網路 ping** | `mgmt_ping_monitor.sh {start\|stop\|status\|fg\|tail\|clear\|summary}` | 一輪 = 10G leg + 1G leg,各自 `ip address/route replace` 後 `ping -I <if>` 打自己的對端;兩張卡都保持 up。每 leg 記 `ip -s link show` 與該卡的 TX/RX packet delta,另出一行可 grep 的 `RESULT` |
|
||||
| **BMC 監控** | `bmc_monitor.sh {start\|stop\|status\|fg\|tail\|clear}` | 由 host 端 `bmc-manager run` 週期取樣 `free -m`,另加一組 **I2C 寫入/讀回圖樣測試**(bus 1、addr 0x41、offset 0x00C0,寫 `55AA55AA` 讀回、再寫 `AA55AA55` 讀回)。B 啟動、C 停止並 `cat log/bmc_poll.log` |
|
||||
| **BMC DDR 壓力** | `bmc_monitor_ddr.sh` | ⚠️ **已停用** —— V1.1.9 起 B/C 內的註解區塊已刪除,改由 `bgctl run bmc-manager run memtester` 取代。檔案保留未刪 |
|
||||
| **SerDes DSC 擷取** | `bcm_dsc_scan.sh [-u 0\|1] [-f <name>] [-F] [-n] [-C]` + `bcm_dsc_parse.sh -i <log> -o <prefix>` | `bcmcmd -n <unit> -c "dsh -c 'phydiag <port> dsc'"` 掃全清單(1 個 100G + 445 個 200G port)× 2 unit,raw log 寫進 `<script_dir>/log` 再 `cp` 到 `/host/hw-eval/jobs`。`-f` 支援 `%u` / `%t`;沒帶 `%u` 時自動插 `_u0`/`_u1`。成功與否**不看 `bcmcmd` 的 exit code**,改比對 `SERDES DISPLAY DIAG DATA END` 數量 + 實際迭代筆數,結尾印 `### DSC_SCAN_DONE rc=<n>`。parse 端輸出 `_lane.csv`(每 lane:TXEQ/RXFFE/DFE/EYE/SNR)與 `_pm.csv`(每 pm_id:溫度/PLL/lane 數/統計)。**由 `EN_TX_FIR` 控制,預設關** |
|
||||
| **100G PRBS** | `port_prbs_monitor.sh {start [both\|a\|b]\|stop\|status\|report\|clear}` | 兩個 uplink 各一個 worker,可同時或單獨跑。setup(`lpmode off` → `prbs set` → `prbsstat STArt`)→ 週期 `prbs get`(判定)+ `prbsstat Ber`(只記錄)→ teardown(`STOp` + `prbs clear`)。輸出含 `PRBS OK!` 才算 PASS。**⚠️ V1.1.9 起 A/B/C 內的註解呼叫已刪除,只能手動跑** |
|
||||
| **SerDes BER 掃描** | `blanton_ber.sh {init\|clear\|start\|stop\|report} [-u 0\|1\|all]` | 全機每個對接 port 的 PRBS BER:`prbs set p=3` + `prbs get`(確認每條 lane 都鎖上)→ `prbsstat STArt Interval=30` →(等一個 interval)→ `prbsstat Ber` → `STOp` → `prbs clear`。`report` 一列一條 lane,**BER < 1e-6 才 PASS**,最後跨 unit 的 summary 帶最差 lane。⚠️ PRBS 期間 link 顯示 DOWN、不過流量。V1.2.1 起 Script A 與 Script C 各跑一次(A 在流量之前、C 在流量報表之後),夾住 soak |
|
||||
| **TR518 負載** | `blanton_tr518.sh {start\|stop} [-u 0\|1\|all]` | `port cd lb=mac` → `l2 learn off` → `test mode nr=yes` → `tr 518 ... testphase=1`,然後 settle `TR_SETTLE_SEC`(120s)再讓人量功耗。`stop` 只送 `port cd lb=none`(照 `TR518.txt`),L2 學習與 test mode **不會還原**,`TR_RESTORE_*=1` 才會 |
|
||||
| **PDB / CPB brick** | `pwr_brick.sh show [-r]` | 5 顆 brick 的 Vin / Iin / Vout / Iout / Temp(SWB0 `0x62`/`0x63`、SWB1 `0x60`/`0x61`、CPB `0x26`)。四顆 ADPM12200 **每個量各自一個 PMBus PAGE**(Vin 9、Iin 10、Vout 2、Iout 14、Temp 18),讀之前一定要先寫 PAGE —— `blanton_pwr_data.sh` 完全沒寫,所以整張 PDB 表都是 NA。換算用手冊 DIRECT 公式 `X=(1/m)(Y×10⁻ᴿ−b)`。每個值重讀到通過三道檢查為止(非 `0xFFFF`、非 `0x0000`、落在合理範圍)—— 這條匯流排**只壞高位元組**,`11.98 V` 會變成 `32.00 V`,全一過濾擋不住 |
|
||||
| **SWB 軌功耗** | `TH6_SWB{0,1}_power_readback.sh` | 讀 `show platform voltage/current` **各一次**,19 條軌 V×I 與總功耗。舊版每軌各讀一次(38 次呼叫、每軌不同時刻),總和是不同瞬間的加總 |
|
||||
| **NFC 讀取輪詢** | `nfc_polling.sh {start\|stop\|status\|tail\|report\|clear\|fg}` | 背景重複跑 `blantons_nfc_validate.py`,每輪追加一行機器可讀的 `RESULT=`(PASS/FAIL 取自工具自己的摘要行,兩者皆無則 **ERROR**,與 FAIL 分開計數)。`start` 會先清空 log;`report` **只讀 log,polling 中隨時可跑**,並標示 `RUNNING` 免得快照被當最終結果。`tail` **不 follow** |
|
||||
| **USB 目標偵測** | `usb_target.sh [-o dev\|mnt\|both\|id] [-n] [-r sec]` | 找出插入的 USB 儲存裝置,排除 `/` 與 `/host` 的底層碟(本平台可能從 USB DOM 開機),多顆時拒絕猜;掛載時會驗證真的可寫 |
|
||||
| **打包交付** | `publish/publish.sh [-v Ver] [-f] [-z] [-n]` | 版號讀 Script A 檔頭,複製成 `publish/Script_ABC_Blanton_<Ver>/`,排除 `*.log`,可另出 zip |
|
||||
|
||||
---
|
||||
|
||||
@@ -268,31 +414,55 @@ PROFILE_CHANNELS=( "0:high:8" "1:low:8" ... ) # "channel:operation:change_perc
|
||||
Script A ── logopen Logs/Blanton_Margin_<ts>.log ──┐ (之後所有畫面都進這個檔)
|
||||
│ │
|
||||
├─ 登入 admin → sudo -i → root@sonic:~# │
|
||||
├─ date -s "<host 時間>" ← 讓 DUT 時戳可對照 │
|
||||
├─ source 5 個 bash 工具(函數進 shell) │
|
||||
├─ date -s "<host 時間>" ← 讓 DUT 時戳可對照
|
||||
├─ rm /host/hw-eval/jobs/* ← 清掉上一輪的 job log
|
||||
├─ hw-test-session finish / bgctl reset / stop --all / list (收前一輪)
|
||||
├─ hw-test-session start / log / status
|
||||
├─ 風扇:max31790 unbind→sleep→bind(18-0020 與 25-0020 各一次)
|
||||
│ → fan-speed-control.sh <FAN_SPEED> → 回答 y 確認 │
|
||||
├─ source 6 個 bash 工具(函數進 shell) │
|
||||
│ └ 此時 blanton_fpga_pcimem.sh 印出 [INFO] CB FPGA BDF = ...(自動偵測結果)
|
||||
├─ AER 基線:7 組 EP+RP 的 correctable/nonfatal/fatal
|
||||
├─ lspci -tvvv / -vv ← 拓樸 + link speed/width
|
||||
├─ margin_status_all ← 9 顆 LTC2980 × 16ch 的 Vout 與偏差%
|
||||
├─ show platform × 7 ← fan/temp/psu/voltage/current/ssdhealth
|
||||
└─ dmesg | grep error/fail/warning
|
||||
├─ show platform × 9 ← fan/temp/psu/voltage/current/ssdhealth/leak status/leak channels
|
||||
├─ dmesg -T(合併 error 正則 + i2c 過濾)→ dmesg -C 清空 ← C 只會看到 soak 期間新產生的
|
||||
├─ mgmt ping:start → pause 45 → stop → cat log ← 10G/1G 各一輪
|
||||
├─ 100G uplink:lpmode off → 兩埠 startup → config save → show interfaces status
|
||||
├─ 一輪流量基線:ps → init → clear → show → start → stop → report
|
||||
└─ show uptime
|
||||
(最前面還有 wait_init.ttl:輪詢 show platform temperature 直到不再回報
|
||||
"Thermal Not detected",避免 pmon 還沒起來就抓基線)
|
||||
▼
|
||||
[messagebox "Start Script B"] ← 人工確認後手動跑 B
|
||||
│
|
||||
▼
|
||||
Script B ── 同一個 log 檔續寫(logwrite 分隔線)
|
||||
├─ 背景程序:mlucas-avx2(CPU) ×1, stress_mem ×5,
|
||||
│ stress_hhmd(I2C/LSB/PCIe), stress_ssd, stress_pcie, stress_usb
|
||||
├─ jobs ← 確認全部起來了
|
||||
└─ while 1: fan → temperature → margin_status_all (soak 期間持續取樣)
|
||||
├─ 背景程序:mlucas-avx2(CPU) ×1, stress_mem ×5, stress_ssd, stress_usb → 共 8 個 job
|
||||
│ (stress_hhmd / stress_pcie 已於 2026-08-17 移除,見 Status 表 ScriptB #5/#7 "KC Remove")
|
||||
├─ bgctl run: memtester 1G / qfx5252-stress-ssd / qfx5252-stress-usb
|
||||
├─ BMC: bmc-manager run memtester(DDR)、cdc_ncm 介面探測 + systemd-run 4hr ping(USB)
|
||||
├─ mgmt_ping_monitor.sh start
|
||||
├─ jobs / bgctl list ← 確認全部起來了
|
||||
├─ traffic: ps → init → clear → (pause 15) → show → start (unit 0 與 1,VLAN 30..137 loopback)
|
||||
└─ while 1: setup_pmon(9 項)→ margin_status_all (soak 期間持續取樣)
|
||||
▼
|
||||
[測試員 Ctrl-C / 停止 macro,接著跑 C]
|
||||
│
|
||||
▼
|
||||
Script C
|
||||
├─ kill $(jobs -p) ← 收掉所有背景壓力
|
||||
├─ show platform × 7 + dmesg ← 收工快照
|
||||
├─ show platform × 9 + dmesg ← 收工快照
|
||||
├─ AER 再抓一次 ← 與 Script A 基線相減 = 本輪新增錯誤
|
||||
└─ cat mlucas_amm_log / log.stress_ssd ← 壓力程式自身的 pass/fail
|
||||
├─ bgctl stop --all / reset、systemctl stop BMC USB unit、mgmt ping stop
|
||||
├─ journalctl BMC USB unit、ip -s link show eth0/eth1、ras-mc-ctl --summary
|
||||
├─ cat mlucas_amm_log ← CPU 壓力程式自身的 pass/fail
|
||||
├─ nvme smart-log / smartctl -x /dev/nvme0
|
||||
├─ traffic: stop → report ← per-pair TX/RX 交叉比對,PASS/FAIL/NA(exit 2 = 有 FAIL/NA)
|
||||
├─ show reboot-cause / show uptime ← soak 期間有沒有意外重開,一眼看得到
|
||||
├─ usb_target.sh -o dev → sync → mount <dev> /mnt/usb
|
||||
├─ cp bmc_poll.log / mgmt_ping.log → jobs/,再 cp -r jobs/ /mnt/usb/jobs-<YYYYmmdd>_<HHMM>
|
||||
└─ hw-test-session finish
|
||||
▼
|
||||
[messagebox "GOOD JOB! Test Case DONE"] → 人工檢查 log
|
||||
```
|
||||
@@ -317,27 +487,90 @@ pwr_data
|
||||
|
||||
1. **A → B → C 必須依序跑,且 B 之後才能跑 C。** Script B 的背景 job 只存在於那個 shell session,
|
||||
Script C 的 `kill $(jobs -p)` 依賴同一個 session;中途斷線就得手動收程序。
|
||||
V1.1.8 起 `mlucas-amm` 例外 —— 它是 systemd transient unit,**跨 session 存活**,
|
||||
所以 Script C 必須另外 `systemctl stop mlucas-amm`(見第 17 條)。
|
||||
2. **A / B / C 共用同一個 log 檔**:只有 Script A `logopen`,B / C 用 `logwrite` 續寫分隔線。
|
||||
跑 B/C 前若關掉了 Tera Term,log 就斷了。
|
||||
3. **PCIe AER 的判定是「差值」不是「絕對值」**:Script A 抓基線、Script C 抓結果,
|
||||
兩者相減才是本輪產生的錯誤。EP 與上游 Root Port **兩邊都要看**(錯誤可能只記在 RP)。
|
||||
4. **BDF 是 per-unit 的**,換 DUT 必須重新確認並改 `blanton_fpga_pcimem.sh` 的 `FUNCT0..3_RES`
|
||||
與 `utils/show_pcie_error_reg_*.ttl`(見 Data Models §5 註)。
|
||||
4. **BDF 是 per-unit 的,bash 端已自動偵測、TTL 端仍寫死**:`blanton_fpga_pcimem.sh` V1.5.0 起
|
||||
於 source 時自掃(vendor `0x1590` → `lspci` → fallback),但 `utils/show_pcie_error_reg_*.ttl`
|
||||
的 7 組 BDF 還是硬編碼,換 DUT 仍需人工校對(見 Data Models §5 註)。
|
||||
5. **ICB / PDB 一律走 VI2C,不走 VSPI**:VSPI ~18 ms/reg 會讓 I2C byte 相之間拉到 ~50 ms,
|
||||
踩中 SMBus 25–35 ms timeout,裝置會 NACK register pointer。實測全 5 通道掃描 9.4 s vs 34.0 s。
|
||||
6. **I2C 讀一律用 Repeated START**(不是 STOP + START):PMBus / SMBus 裝置(VRM、EFUSE)
|
||||
只吃 Sr;只有純暫存器裝置兩種都行。
|
||||
7. **`margin_save`(`STORE_USER_ALL`)會永久寫進 NVM**,斷電保留。測試流程中**絕不執行**,
|
||||
以免覆蓋客戶出廠 config。`margin.sh` 的 auto-enable 只改 RAM(`ON_OFF_CONFIG`),斷電復原。
|
||||
`margin_save all` / `margin_save blanton`(v2.7.0)一次對 9 顆 LTC2980(18 個 LTC2977)
|
||||
下同一道命令,風險同性質但範圍是全機;命令本身是 PMBus send-byte(`0x15`,不帶 data byte)。
|
||||
8. **操作硬體電壓有損壞 DUT 的風險**:套 profile 前先確認該軌 OV/UV limit 與 servo DAC 注入電阻
|
||||
有 populate(本板部分 margin 電阻標 PROTO,沒 populate 的軌電壓不會動)。
|
||||
9. **`ARB_LOST` 不等於裝置存在**:`vi2c_scan` 只看 `RX_ACK`,仲裁失敗會被誤報成「有裝置」。
|
||||
`blanton_pwr_data.sh` 因此加了 ARB_LOST-aware retry 與 plausibility window
|
||||
(`0xFFFF` 或超出範圍一律回 `NA`)——**寧可 NA 也不要印出一個看起來像數據的錯值**。
|
||||
10. **DUT 密碼不得進 git**:`1_Blanton_Script_A.ttl` 目前的 `sendln "YourPaSsWoRd"` 是 placeholder,
|
||||
10. **`bcmcmd` 成功退出不代表指令成功**:BCM shell 拒絕指令(`VLAN: ERROR: Entry exists` /
|
||||
`Failed to execute the diagnostic command`)時 `bcmcmd` 仍 exit 0。
|
||||
`blanton_traffic_linespeed.sh` 因此改用輸出比對(`$TL_ERR_PAT`),並把
|
||||
`vlan create` 的 `Entry exists`(重跑 init)與 `vlan remove` 的 `not found`(init 前先 stop)
|
||||
當良性情況分開計數。另外 `bcmcmd` 一律以 `</dev/null` 執行 ——
|
||||
否則它會吃掉 while 迴圈的 stdin,導致**只有第一個 VLAN 被設定**(V0.3.1 修的 bug)。
|
||||
**2026-09-07 `bcm_dsc_scan.sh` 又踩了同一個坑**(port 清單走 stdin,445 個 port 只掃了 1 個),
|
||||
而且因為 `### PORT` marker 與 dsc 區塊數量一起變少,原本的比對檢查完全看不出來、`rc=0`。
|
||||
修法:迴圈改讀 fd 3(`done 3< "$PORTFILE"`)+ `bcmcmd ... < /dev/null`,再加一道
|
||||
「實際迭代筆數 == 清單筆數」的獨立檢查。**寫任何餵檔案給 `while` 又在裡面呼叫 `bcmcmd` 的迴圈,
|
||||
都要假設它會讀 stdin;而且完整性檢查不能只比對兩個會一起變少的數字。**
|
||||
11. **DUT 密碼不得進 git**:`1_Blanton_Script_A.ttl` 目前的 `sendln "YourPaSsWoRd"` 是 placeholder,
|
||||
實際帳密必須放 `secret/config_secret.ttl`(gitignored)並由 `config.ttl` include。
|
||||
11. **客戶 NDA**:`docs/` 內含客戶 FPGA 規格與 schematic 衍生資訊,**本 repo 只推 NAS + Gitea,
|
||||
12. **`.sh` / `.conf` 必須是 LF**:CRLF 的 shell script 在 SONiC 上直接掛
|
||||
(`-bash: $'\r': command not found` + `syntax error near unexpected token`),
|
||||
`settings/*.conf` 則因為是被 `source` 的,未加引號的賦值會變成 `"6\r"`(安靜地壞掉)。
|
||||
`.gitattributes` 已把 `*.sh` `*.conf` `*.py` `*.txt` `*.md` 釘成 LF、`*.ttl` 維持 CRLF。
|
||||
⚠️ 但 `.gitattributes` **不會回頭重寫既有工作區檔案** —— 早於它 clone 出來的目錄,
|
||||
需 `git rm --cached -r . && git reset --hard` 或刪掉目錄重新 checkout 才會生效,
|
||||
而且 `git status` 乾淨**不代表**磁碟上是 LF(`--renormalize` 只在進 index 的路上轉換)。
|
||||
13. **`bmc_monitor*.sh` / `mgmt_ping_monitor.sh` 需要執行權**:它們是本專案「被執行」而非被 `source` 的腳本,
|
||||
而 `do_start` 內部是 `setsid "$SCRIPT_PATH" __daemon`,**即使用 `bash x.sh start` 呼叫
|
||||
也仍需 exec bit**。git 記錄為 `100644`,且 Windows → 隨身碟 → DUT 的路徑無法攜帶權限位元,
|
||||
所以佈署後要先 `chmod +x ~/Blanton_Script/bmc_monitor*.sh`,否則 Script B 的 start 會
|
||||
`Permission denied`、Script C 的 `cat` 撲空(BMC 段全空但不會報錯)。
|
||||
14. **TTL 的 `timeout` 是全域的,設了就要還原**:`timeout = N` 之後**每一個** `wait` 都被限制在 N 秒,
|
||||
逾時的 `wait` 會直接返回而沒吃到 prompt,於是下一個指令在前一個還沒跑完就送出,之後整輪錯開一拍。
|
||||
`wait_init.ttl` 設 60 後還原 0;Script B 的 cdc_ncm 探測設 15,成功路徑在 `endif` 之後還原、
|
||||
跳過路徑在 `:skip_ping` 還原(兩處各一次)。
|
||||
Script 5 抄了同一段,但它的 ping 區塊要 `wait` 一個 `sleep 10` —— DUT 一忙就逼近 15 s 上限,
|
||||
所以**還原點提前到 `if` 之前**:分支之前還原,一行就涵蓋兩條路徑,`:skip_ping` 的那行留作備援。
|
||||
加新的 `timeout` 時務必配一個 `timeout = 0`;**抄有 `goto` 的段落時連 `:label` 一起抄** ——
|
||||
標籤沒定義 Tera Term 不會在載入時報錯,要真的跳進那條分支才會彈錯誤視窗停住整輪
|
||||
(Script 5 原本就漏了 `:skip_ping`,只有抓不到 NCM 介面時才會發作,已補)。
|
||||
15. **兩張管理網卡同網段時會 ARP flux**:`mgmt_ping_monitor.sh` 讓 eth0/eth1 同時 up,若兩者在同一個
|
||||
/24(本專案預設 `192.168.1.99` / `.101`),對端 ARP 可能由任一張卡回應,回包落在沒送封包的那張,
|
||||
量到的數字不能歸屬。`ARP_STRICT=1` 會設 `arp_ignore=1` / `arp_announce=2` 擋掉;
|
||||
另外每個 leg 的 `RESULT` 行帶 `nic_tx` / `nic_rx`(該卡自己的 packet delta),
|
||||
**ping 成功但 `nic_tx` 接近 0 就代表封包從另一張卡出去了**。兩張卡在不同網段時可設 0。
|
||||
16. **客戶 NDA**:`docs/` 內含客戶 FPGA 規格與 schematic 衍生資訊,**本 repo 只推 NAS + Gitea,
|
||||
絕不推 GitHub**。
|
||||
17. **改用 `systemd-run` 起壓力工作,就要自己補停的那一行。** `utils/kill_all_process.ttl` 的內容
|
||||
只有 `kill $(jobs -p)`,而 systemd unit 不是 shell job,它抓不到。V1.1.8 把 `mlucas-avx2`
|
||||
搬到 `mlucas-amm` unit(好處:掉線不會停、`jobs` 看不見的問題消失、`Restart=always` 會自動拉回),
|
||||
代價是 Script C 少了那行 `systemctl stop` 就會讓 CPU 滿載燒進收工量測與下一輪測試 ——
|
||||
而 `show interfaces status` 之類的檢查完全看不出來。目前 `mlucas-amm` 與
|
||||
`qfx5252-bmc-usb-net-test` 兩個 unit 都已在 Script C 收掉。
|
||||
⚠️ **`4_Blanton_Script_thermal_safety.ttl` 用同一個 `mlucas-amm` unit,但它沒有收尾段**,
|
||||
所以那行 `systemctl stop mlucas-amm` 必須由測試員手動下 —— 這是 Script 4 目前
|
||||
唯一一個「不下就會延續到下一輪」的負載。
|
||||
18. **`pause` 停的是 macro,`sleep` 停的是 DUT。** V1.2.0 起 A/B/C 的等待一律改成
|
||||
`sendln "sleep N"` + `wait prompt_sonic_root`。`pause N` 期間 macro 不理會 DUT,shell 是閒著的,
|
||||
等於用猜的估上一個指令要跑多久 —— DUT 一忙就會提早往下送指令;改成 DUT 端 `sleep` 之後,
|
||||
prompt 回來才繼續,兩邊不可能走散,而且這段等待會帶時戳進 log,事後看得出哪一輪跑久了。
|
||||
⚠️ **Script 4 與 Script 5 尚未轉換,仍在用 `pause`**;B/C 開頭的 `pause 1` 也保留
|
||||
(它在登入前執行,沒有 prompt 可等)。
|
||||
19. **`config.ttl` 少一個變數會讓 macro 當場中止**,不是當成 0。V1.1.8 新增 `EN_timestamp`
|
||||
(Script A `logopen` 的第 5 個參數)與 `BMC_USB_RUNTIME`(Script B 的 ping unit);
|
||||
V1.2.0 再加 `EN_TX_FIR`(A/C 的 DSC 掃描與 C 的四行 `cp`,預設 0)。
|
||||
只更新 `.ttl` 卻沿用舊的 `config.ttl`,Script A 會停在 `logopen` 那一行。
|
||||
另外 **時間戳的「格式」不在 macro 裡** —— 它在 Tera Term 的
|
||||
Setup → Additional settings → Log,存在那台電腦的 `TERATERM.INI`,會跟著 PC 而不是跟著腳本走。
|
||||
|
||||
---
|
||||
|
||||
@@ -350,7 +583,7 @@ pwr_data
|
||||
| **客戶機密文件** | `docs/` 內 FPGA 規格(docx/xlsx/md)屬客戶 NDA 範圍;schematic 原始檔(`*.DSN`)一律 gitignore,不進 repo |
|
||||
| **Remote 限制** | 只推私有 remote:`nas`(`git.et-wen.com:51222`)+ `gitea`(`etgit.et-wen.com`)。**不設 GitHub `origin`** |
|
||||
| **測試 log** | `logs/*.log` 含 DUT 序號、MAC、韌體版本等可識別資訊 → gitignore,只保留目錄結構(`.gitkeep`) |
|
||||
| **破壞性硬體指令** | `margin_save` / `STORE_USER_ALL` 為永久 NVM 寫入,工具預設不呼叫;批次腳本 `margin_save_all.sh` 在 README 與腳本頂端都有警語 |
|
||||
| **破壞性硬體指令** | `margin_save` / `margin_save all` / `margin_save blanton` / `STORE_USER_ALL` 為永久 NVM 寫入,工具預設不呼叫;`margin_save all` 與批次腳本 `margin_save_all.sh` 在 README 與程式頂端都有警語 |
|
||||
| **root 權限** | 全流程在 `root@sonic:~#` 下執行(pcimem / i2c 需要);腳本不留任何 `chmod 777` 或放寬權限的動作 |
|
||||
| **For_AI/** | AI 協作素材(截圖、草稿筆記)整個資料夾 gitignore,避免不小心把客戶圖面帶進 repo |
|
||||
|
||||
@@ -371,22 +604,29 @@ cp secret/config_secret.ttl.example secret/config_secret.ttl
|
||||
|
||||
# ── 2. DUT 端:部署 bash 工具庫 ─────────────────────────────
|
||||
scp -r src/Script_ABC_Blanton/Blanton_Script admin@<DUT_IP>:~/
|
||||
# 佈署後務必補執行權(Windows/隨身碟路徑帶不動 exec bit):
|
||||
ssh admin@<DUT_IP> 'chmod +x ~/Blanton_Script/bmc_monitor*.sh'
|
||||
# 若曾在舊工作區編輯過,先確認沒有 CRLF:grep -rlU $'\r' ~/Blanton_Script
|
||||
ssh admin@<DUT_IP> 'sudo -i'
|
||||
# (現場無網路時改用 USB 隨身碟複製到 ~/Blanton_Script)
|
||||
|
||||
# ── 3. DUT 端:確認 FPGA BDF(每台不同!)────────────────────
|
||||
lspci -Dnn | grep -i fpga # 例:0000:03:00.0
|
||||
ls -d /sys/bus/pci/devices/0000:*:00.3
|
||||
# 若不是 0000:03:00.x,改 ~/Blanton_Script/blanton_fpga_pcimem.sh 的 FUNCT0..3_RES
|
||||
# 以及 src/Script_ABC_Blanton/utils/show_pcie_error_reg_*.ttl 內的 BDF
|
||||
|
||||
# ── 4. DUT 端:煙霧測試(跑 Script A 之前先手動確認)──────────
|
||||
# ── 3. DUT 端:煙霧測試(跑 Script A 之前先手動確認)──────────
|
||||
source ~/Blanton_Script/blanton_fpga_pcimem.sh
|
||||
# → 會印 [INFO] CB FPGA BDF = 0000:0X:00.0-.3 (resource0) ← BDF 自動偵測,不用改檔
|
||||
# 偵測錯或多顆候選時:FPGA_BDF=0000:05:00 fpga_rescan
|
||||
cb_fpga 0 0xD90 # RST_CAUSE_REG,讀得到值 = BAR 通了
|
||||
source ~/Blanton_Script/blanton_cb_i2c.sh
|
||||
cb_i2c_init 11 && cb_i2c_scan 11 # Ch11 風扇控制器,應看到 0x20
|
||||
source ~/Blanton_Script/LTC2980_Margin_Script/margin.sh
|
||||
margin_init Blanton_CB_CONN13 && margin_status
|
||||
source ~/Blanton_Script/blanton_traffic_linespeed.sh
|
||||
blanton_traffic_linespeed ps -u 0 # 對照線的 link/speed
|
||||
blanton_traffic_linespeed init -u 0 -n # -n = dry-run,先看要下哪些 bcmcmd
|
||||
|
||||
# ── 4. DUT 端:校對 AER 的 BDF(自動偵測沒涵蓋這裡!)─────────
|
||||
lspci -Dnn # 對照 ARCHITECTURE.md 的 PCIe 拓樸表
|
||||
# 與 src/Script_ABC_Blanton/utils/show_pcie_error_reg_*.ttl 內寫死的 7 組 BDF 比對,
|
||||
# 不符就改 TTL——否則 AER 會讀到別的裝置或不存在的路徑
|
||||
```
|
||||
|
||||
**Host(Windows)端:**
|
||||
@@ -402,6 +642,19 @@ margin_init Blanton_CB_CONN13 && margin_status
|
||||
8. 檢查 Logs\Blanton_Margin_<ts>.log
|
||||
```
|
||||
|
||||
**打包交付:**
|
||||
|
||||
```bash
|
||||
./publish/publish.sh # 版號讀 Script A 檔頭 → publish/Script_ABC_Blanton_V1.0.3/
|
||||
./publish/publish.sh -z # 另外產出同名 .zip
|
||||
./publish/publish.sh -n # dry run,只印會做什麼
|
||||
./publish/publish.sh -f # 覆蓋既有輸出資料夾
|
||||
```
|
||||
|
||||
版號**不是參數而是從 Script A 的 `; Version : Vx.y.z` 讀出來的**,所以資料夾名不可能跟
|
||||
測試員打開 macro 看到的版本不一致。要出新版就先改 Script A 檔頭再跑。
|
||||
輸出會排除 `*.log`(測試 log 含 DUT 序號,不隨交付外流),但保留空的 `logs/` 供 `logopen` 寫入。
|
||||
|
||||
> 註:本專案非 .NET / Blazor / EC2 架構,`aws-ec2-deploy` 與 `vbox-run-deploy` 兩份部署指南不適用,已跳過。
|
||||
|
||||
---
|
||||
@@ -416,12 +669,13 @@ margin_init Blanton_CB_CONN13 && margin_status
|
||||
**目標:** 專案進 git(NAS + Gitea),帳密不再躺在腳本裡,任何人 clone 下來照文件就能跑。
|
||||
|
||||
**包含:**
|
||||
- [ ] `git init` + `.gitignore`(`secret/*`、`For_AI/`、`logs/*.log`、`~$*`、`*.DSN`)
|
||||
- [ ] 建 `secret/README.md` + `secret/config_secret.ttl.example`(`__CHANGE_ME__` placeholder)
|
||||
- [x] `git init` + `.gitignore`(`secret/*`、`For_AI/`、`logs/*.log`、`~$*`、`*.DSN`)
|
||||
- [x] 建 `secret/README.md` + `secret/config_secret.ttl.example`(`__CHANGE_ME__` placeholder)
|
||||
- [ ] `config.ttl` 改為 `include "..\..\secret\config_secret.ttl"`(或現場放同層),
|
||||
把 `1_Blanton_Script_A.ttl` 的 `sendln "YourPaSsWoRd"` 換成 `sendln dut_password`
|
||||
- [ ] `src/Script_ABC_Blanton/logs/.gitkeep`,既有 `Blanton_Margin_20260814-164122.log` 移出 repo
|
||||
- [ ] `CLAUDE.md` + `ARCHITECTURE.md` 進 repo,push `nas` + `gitea`(**不推 GitHub**)
|
||||
**← 唯一未完成項;密碼目前仍寫在腳本裡**
|
||||
- [x] `src/Script_ABC_Blanton/logs/.gitkeep`,既有 `Blanton_Margin_20260814-164122.log` 移出 repo
|
||||
- [x] `CLAUDE.md` + `ARCHITECTURE.md` 進 repo,push `nas` + `gitea`(**不推 GitHub**)
|
||||
|
||||
**驗收條件:** 在另一台機器 `git clone` → 填 `secret/config_secret.ttl` → Script A 能完整登入並產生 log;
|
||||
`git log -p` 中搜不到任何實際密碼。
|
||||
@@ -442,7 +696,8 @@ margin_init Blanton_CB_CONN13 && margin_status
|
||||
- [ ] 新增 `utils/show_pwr_data.ttl`(`pwr_data` + `pwr_data_pdb`)與
|
||||
`utils/show_temp_sensor.ttl`(`temp_all`),把 `blanton_pwr_data.sh` /
|
||||
`blanton_temp_sensor.sh` 真正接進流程(目前 Script A 只 source 沒用)
|
||||
- [ ] Script A 開頭加 BDF 自檢:`lspci -Dnn | grep -i fpga`,log 裡看得到本台的實際 BDF
|
||||
- [x] Script A 開頭加 BDF 自檢 —— 由 `blanton_fpga_pcimem.sh` V1.5.0 的 source 時自動偵測達成,
|
||||
log 內會出現 `[INFO] CB FPGA BDF = ...`(比原本規劃的 `lspci` 一行更完整)
|
||||
|
||||
**驗收條件:** 跑一次 Script A,log 內同時含 reset cause 三個暫存器值、9 顆 LTC2980 × 16ch 的
|
||||
margin status、全部 VRM 軌的 Vin/Vout/Iout/Temp、CB + ICB 溫感讀值,且無 `ERR` / `NA` 以外的異常。
|
||||
@@ -454,18 +709,26 @@ margin status、全部 VRM 軌的 Vin/Vout/Iout/Temp、CB + ICB 溫感讀值,
|
||||
**目標:** 壓力程序起得來、起不來看得出來,soak 迴圈有時戳、可控週期。
|
||||
|
||||
**包含:**
|
||||
- [ ] 部署 `~/hammer/tools/` 前置檢查:新增 `utils/check_hammer_tools.ttl`
|
||||
(`ls -l ~/hammer/tools/` + `ls ~/hammer/tools/amd/mlucas-avx2`),缺檔就別往下跑
|
||||
- [ ] 前置檢查:`~/hammer/tools/amd/mlucas-avx2` 仍是唯一還依賴 hammer 的項目,缺檔就別往下跑
|
||||
- [ ] 壓力程序 log 加時戳,避免多輪覆蓋:
|
||||
`mlucas_amm_log` → `~/logs/mlucas_amm_log_$(date +%Y%m%d-%H%M%S).log`(Status 表 ScriptB #2 的既定寫法)
|
||||
- [ ] `jobs` 之後加驗證:期望 10 個背景 job(1 mlucas + 5 mem + hhmd/ssd/pcie/usb),
|
||||
數量不符時 `messagebox` 提示
|
||||
- [x] 壓力層改用平台的 `bgctl`(`memtester` / `qfx5252-stress-ssd` / `qfx5252-stress-usb`),
|
||||
取代 `~/hammer/tools/stress_*.py`;Script B 以 `jobs` + `bgctl list` 兩者並列確認
|
||||
- [ ] `bgctl list` 之後加數量驗證,不符時 `messagebox` 提示(目前只印出來給人看)
|
||||
**← V1.0.10 起 `bgctl list` + `jobs` 改為每輪都印,中途死掉的 job 看得到,但仍要靠人眼比對**
|
||||
- [ ] soak 迴圈改為「每輪先 `date`、跑完 `pause <間隔>`」,
|
||||
把 `EN_LoopInterval`(預設 600 秒 = 10 min)放進 `config.ttl`,兌現 Status 表的「Get data every 10mins」
|
||||
- [ ] soak 每輪補 `show platform psustatus` / `voltage` / `current`(目前只有 fan + temperature)
|
||||
**← V1.0.10 已補上 `pause 60`(迴圈不再全速空轉),但 60 秒是寫死的、也還沒有每輪 `date`;
|
||||
距 Status 表的 10 分鐘仍有差距,故本項未結**
|
||||
- [x] soak 每輪補 `show platform psustatus` / `voltage` / `current`
|
||||
—— 迴圈已改為 `include "utils/setup_pmon.ttl"`,九項全收
|
||||
- [ ] 補 `; ========== CLEAR EVENT ==========`(Status 表 ScriptB #1,Owner: Alan)
|
||||
- [x] BMC 納入 soak:`bmc_monitor.sh`(`free -m` 取樣)與 `bmc_monitor_ddr.sh`(`memtester`)
|
||||
由 Script B 啟動、Script C 停止並把 log 併進 master log
|
||||
- [x] Script A 加開機資訊與就緒等待:`show boot`、BMC `/etc/issue`、`wait_init.ttl`
|
||||
- [x] Script C 加 `show reboot-cause` / `show uptime`,soak 期間意外重開看得見
|
||||
|
||||
**驗收條件:** Script B 啟動後 `jobs` 顯示 10 個 job;連續跑 3 輪,log 內三段各自帶正確時戳且間隔 ≈10 min;
|
||||
**驗收條件:** Script B 啟動後 `jobs` 顯示 8 個 job;連續跑 3 輪,log 內三段各自帶正確時戳且間隔 ≈10 min;
|
||||
故意把 `~/hammer` 改名,Script B 會在前置檢查就停下並提示。
|
||||
|
||||
---
|
||||
@@ -474,19 +737,32 @@ margin status、全部 VRM 軌的 Vin/Vout/Iout/Temp、CB + ICB 溫感讀值,
|
||||
|
||||
**目標:** 補齊 Status 表中 Owner=Alan 的三個 traffic 項目,讓測試涵蓋交換晶片的資料面。
|
||||
|
||||
**包含:**
|
||||
- [ ] `utils/traffic_setup.ttl`:Blanton/SONiC 版的 port 起始設定與 counter 清零
|
||||
(對照 Carlsbad 的 `clear int stat global`,改用 SONiC `sonic-clear counters`)
|
||||
- [ ] `utils/show_traffic_counters.ttl`:`show interface counters`、
|
||||
`show interface counters errors`、`show interface status`
|
||||
- [ ] `utils/show_interface_detail.ttl`:`show interface transceiver eeprom/dom`、
|
||||
`show interface link-training`(對照 Carlsbad `sho int transceiver detail`)
|
||||
- [ ] `utils/show_tech.ttl`:`show techsupport`(Script C 收工快照,Status 表 ScriptC #4)
|
||||
- [ ] Script A 的 TRAFFIC-SETUP-STAGE 與 Script C 的 CHECK Traffic counters 接上這些片段
|
||||
- [ ] `config.ttl` 加 `EN_Traffic` 旗標,未接線的站點可整段跳過
|
||||
> 📌 **實作路線與原規劃不同**:原本設想用 SONiC CLI(`sonic-clear counters` / `show interface counters`),
|
||||
> 實際落地的是**更底層的 `bcmcmd` drivshell 路線** —— SWB 實體 loopback 線 + VLAN 成對配置 + `tx` burst,
|
||||
> 直接讀 ASIC 的 `MIB_TPOK`/`MIB_RPOK`。好處是能做 per-pair 雙向交叉比對(`cdA.TX == cdB.RX`),
|
||||
> 比 SONiC CLI 的單向 counter 強得多;代價是綁定 Broadcom SDK 與那條 loopback 線。
|
||||
|
||||
**驗收條件:** `EN_Traffic=1` 時,Script A log 有清零後的 counter 基線、Script C log 有結束時的
|
||||
counter 與 error-counter,兩者可直接相減;`EN_Traffic=0` 時整段不執行且不報錯。
|
||||
**包含:**
|
||||
- [x] `blanton_traffic_linespeed.sh`(V0.4.0):`init` / `clear` / `show` / `start` / `stop` /
|
||||
`ps` / `report` / `run`,unit 0 與 1,VLAN 30..137 對應 `cdN` ↔ `cdN+32`
|
||||
(取代原規劃的 `utils/traffic_setup.ttl`)
|
||||
- [x] per-pair TX/RX 報表與 PASS/FAIL 判定:DUT 上 awk(`report`)+ 離線
|
||||
`tools/bcm_mibpair_report_V1.1.0.py`,同版面同判定規則
|
||||
(取代原規劃的 `utils/show_traffic_counters.ttl`)
|
||||
- [x] Script B 接上 `ps → init → clear → show → start`、Script C 接上 `stop → report`
|
||||
- [x] 原始 bcmcmd 指令表留檔:`tools/traffic_loopback_{vlan_setting,start,vlan_remove}.txt`
|
||||
- [x] **Script A 的流量基線** —— 原本的空區塊已改成完整一輪
|
||||
(`ps → init → clear → show → start → stop → report`,含 15 秒沉澱)
|
||||
- [ ] `utils/show_interface_detail.ttl`:`show interface transceiver eeprom/dom`、
|
||||
`show interface link-training`(Status 表 ScriptC #4,仍 On-Going)
|
||||
- [ ] `utils/show_tech.ttl`:`show techsupport`(Script C 收工快照,Status 表 ScriptC #4)
|
||||
- [ ] `config.ttl` 加 `EN_Traffic` 旗標,未接 loopback 線的站點可整段跳過
|
||||
(現在 B/C 是無條件執行,沒接線會整批 bcmcmd 失敗)
|
||||
- [x] `-u 0` 已從三支腳本移除,全部沿用工具預設 `TL_UNITS="0 1"`,兩塊 switch board 都測到
|
||||
- [x] 100G uplink 狀態:`show interfaces status Ethernet513,Ethernet514`(A 與 B 各一次)
|
||||
|
||||
**驗收條件:** `EN_Traffic=1` 時,Script C 的 `report` 印出 108 對的 TX/RX 表且全 PASS;
|
||||
拔掉一條 loopback 線重跑,該對顯示 FAIL 或 NA 且 exit code 為 2;`EN_Traffic=0` 時整段不執行且不報錯。
|
||||
|
||||
---
|
||||
|
||||
@@ -501,7 +777,13 @@ counter 與 error-counter,兩者可直接相減;`EN_Traffic=0` 時整段不
|
||||
UE > 0 或 fatal/nonfatal > 0 直接標 FAIL
|
||||
- [ ] Margin 表解析:把 9 顆 × 16ch 的 Vout / 偏差% 收成 CSV,標出超出 ±(profile 設定值 + 容差) 的軌
|
||||
- [ ] 溫度 / 風扇 / 電源趨勢:soak 期間逐輪取樣 → CSV(可直接畫圖)
|
||||
- [ ] Stress 判定:`mlucas_amm_log` 與 `log.stress_ssd` 的錯誤關鍵字掃描
|
||||
- [ ] Stress 判定:`mlucas_amm_log` 與 `bgctl` 各工作的 log
|
||||
(`/host/hw-eval/.../qfx5252-stress-{ssd,usb}.log`)的錯誤關鍵字掃描
|
||||
- [ ] Traffic 判定:**直接複用 `tools/bcm_mibpair_report_V1.1.0.py`**(它已能吃 console log 的
|
||||
`show c` 段落並輸出 PASS/FAIL),不要重寫一套解析
|
||||
- [ ] 管理網路判定:抓 `mgmt_ping_monitor.sh` 的 `RESULT` 行(已是單行可 grep 格式),
|
||||
並檢查 `nic_tx`/`nic_rx` 不為 0 —— 否則 PASS 也不能歸屬到那張卡
|
||||
- [ ] NVMe / EDAC:`nvme smart-log`、`smartctl -x`、`ras-mc-ctl --summary` 的前後差值
|
||||
- [ ] 產出 `Logs/<run>_summary.md`:一頁 PASS/FAIL + 每個子系統一行結論
|
||||
|
||||
**驗收條件:** 拿一份既有 log(如 `Blanton_Margin_20260814-164122.log`)跑解析器,
|
||||
@@ -514,15 +796,15 @@ counter 與 error-counter,兩者可直接相減;`EN_Traffic=0` 時整段不
|
||||
**目標:** 產出可直接交給現場測試員(或客戶)的一包,含操作手冊,不需要看原始碼。
|
||||
|
||||
**包含:**
|
||||
- [ ] `tools/publish.sh`:把 `src/Script_ABC_Blanton/` + 空 `Logs/` + `secret/*.example`
|
||||
打包成 `publish/Blanton_Script_ABC_v<ver>_<YYYYMMDD>/` 與同名 zip(比照
|
||||
既有的 `Blanton_Script_ABC_v1.0_20251229` 命名)
|
||||
- [x] `publish/publish.sh`:把 `src/Script_ABC_Blanton/` 打包成
|
||||
`publish/Script_ABC_Blanton_<Ver>/`(`-z` 另出 zip)。版號讀 Script A 檔頭,
|
||||
排除 `*.log` 但保留空的 `logs/`。工具本身進 git,產出被 gitignore
|
||||
- [ ] `README.md`(現場用):Tera Term 設定、A→B→C 操作順序、常見錯誤(BDF 不符、
|
||||
margin 掃不到、hammer 工具缺檔)與對應處理
|
||||
- [ ] `CHANGELOG.md`:延續三支腳本頂端的 Version History,集中成一份
|
||||
- [ ] 三支腳本的 header 版號與 `CHANGELOG.md` 對齊,`config.ttl` 加 `script_version` 並寫進 log 開頭
|
||||
- [ ] `docs/TTL_Script_Blanton_Status_*.xlsx` 更新為全 OK,或把剩餘項目移進 Future Extensions
|
||||
- [ ] 打 git tag `v1.1.0`,push `nas` + `gitea`
|
||||
- [x] 打 git tag,push `nas` + `gitea`(已至 `V1.2.1`;`publish/` 依 Script A 檔頭版號打包)
|
||||
|
||||
**驗收條件:** 從 zip 解壓到一台乾淨的測試 NB,照 README 操作,不看原始碼就能完成一輪 A→B→C
|
||||
並產出 summary;`publish/` 內容與 git tag 一致。
|
||||
@@ -537,12 +819,124 @@ counter 與 error-counter,兩者可直接相減;`EN_Traffic=0` 時整段不
|
||||
COM36 才拿到部分結果;`READ_VIN` 已知不是真的輸入電壓(跟隨 `READ_VOUT`)。待拿到 brick 的
|
||||
`MFR_ID`/`MFR_MODEL` 後對照 datasheet 定案。
|
||||
- **`show_pcie_error_reg.ttl` 淘汰**:舊的合併版已被 7 支 per-device 版取代,確認無人引用後刪除。
|
||||
- **BDF 自動偵測**:把 `blanton_fpga_pcimem.sh` 註解中的 auto-detect 片段轉正,
|
||||
用 `lspci -Dnn | grep -i fpga` 動態填 `FUNCT0..3_RES`,讓換 DUT 不用改檔。
|
||||
- ✅ **BDF 自動偵測** —— 已於 `blanton_fpga_pcimem.sh` V1.5.0(2026-08-17)完成。
|
||||
下一步是把同樣的偵測結果餵給 `utils/show_pcie_error_reg_*.ttl`,
|
||||
讓 AER 那 7 組 BDF 也不用手改(目前仍是硬編碼)。
|
||||
- **`stress_hhmd` / `stress_pcie` 的替代**:兩者已於 2026-08-17 移除,I2C/PCIe 的持續讀取壓力
|
||||
目前沒有替代品。若仍需覆蓋這塊,可考慮用 `blanton_cb_i2c.sh` / `cb_fpga` 寫一支輕量 loop。
|
||||
- **SSH / 網路模式**:目前全走 COM console。若 DUT 管理網路可用,可改用 `plink`/`ssh` 執行同一組
|
||||
bash 工具,速度與可靠度都比 serial 好,TTL 只保留開機階段。
|
||||
- **多 DUT 併行**:多台 DUT 同時 soak 時,Tera Term 每台開一個 macro window;
|
||||
可考慮改成 Python(`pyserial`)統一排程與集中收 log。
|
||||
- **與 `LTC2980_Margin_Script` 獨立 repo 的同步機制**:目前 `Blanton_Script/LTC2980_Margin_Script/`
|
||||
是該 repo 的複本(少了 `ARCHITECTURE.md`/`CLAUDE.md`/`Reference/`,多了兩支 `blanton_*` 後端)。
|
||||
待評估改用 git submodule 或明確的 vendored 同步腳本。
|
||||
- ✅ **margin 子專案的重複檔** —— v2.6.0 已移除內含的 `blanton_cb_i2c.sh` /
|
||||
`blanton_fpga_pcimem.sh` 複本,改由 `_swb_find_backend` 往上層找共用版,漂移風險解除。
|
||||
與獨立 repo `LTC2980_Margin_Script` 的同步機制(submodule 或 vendored 腳本)仍待評估。
|
||||
- **`Ref/margin_command_trace.md` 需重新產生**:SWB 章節的 1223 條 `cb_pmbus_*` 指令是依
|
||||
修正前的通道/位址展開的(其中 487 條用到已不存在的 `0x5D`/`0x5F`/`0x63`/`0x65`),
|
||||
文件已加過期警告但內文未動。第 1~4 章不受影響。
|
||||
- **`wait_init.ttl` 沒有逾時出口**:若 pmon 一直起不來,`result` 既非 1 也非 2,迴圈會無限重試,
|
||||
Script A 既不往下走也不報錯。可加最大重試次數 + `messagebox` 提示。
|
||||
- **腳本的執行權**:`mgmt_ping_monitor.sh` 與 `bmc_monitor.sh`(以及已停用的 `bmc_monitor_ddr.sh`)需人工 `chmod +x`。
|
||||
可在 Script B 起它之前補一行(比照既有的 `chmod +x ~/hammer/tools/amd/mlucas-avx2`),或在 publish 時處理。
|
||||
- **`bmc_monitor_ddr.sh` 已停用**:V1.1.9 起 B/C 內那段註解掉的呼叫已刪除,DDR 壓力由
|
||||
`bgctl run bmc-manager run memtester` 取代。檔案還留在 repo,待確認不再需要後刪除,或在檔頭標註停用。
|
||||
(`bmc_monitor.sh` 已於 2026-08-25 重新啟用,並加上 I2C 寫入/讀回圖樣測試。)
|
||||
- **`rm /host/hw-eval/jobs/*` 清不掉子目錄**:Script A 用的是不帶 `-r` 的 `rm`,但 Script C
|
||||
是 `cp -r` 那個目錄,代表裡面可能有子目錄。清不乾淨的話,上一輪的 job log 會被當成這輪的一起
|
||||
複製到 USB。要確認 `bgctl` 的產出結構,必要時改成 `rm -rf .../jobs/*`。
|
||||
- **100G PRBS 已從 A/B/C 移除**:`port_prbs_monitor.sh` 仍隨包交付、仍可手動執行,但 V1.1.9 起
|
||||
三支腳本裡那些註解掉的呼叫已整段刪除(連同 Script C 的 `bmc_monitor_ddr.sh` 區塊)。
|
||||
要接回去得重寫,不是把註解拿掉。啟用時記得 PRBS 期間 link 會顯示 down,`stop` 之後才會回來。
|
||||
- **DSC 擷取預設是關的**:`EN_TX_FIR = 0`,所以出貨設定不會跑 `bcm_dsc_scan.sh`。
|
||||
開啟後 Script A 與 Script C 各掃一次、整輪多約 20 分鐘;只要單邊資料可以在腳本裡改成 `-u 0`。
|
||||
掃描本身是唯讀(`phydiag ... dsc` 不改 SerDes 設定),但**它與 `blanton_ber.sh` /
|
||||
`blanton_traffic_linespeed` / `blanton_tr518.sh` 一樣都在動同一批 port,不要同時跑**。
|
||||
- **Script 5(Reboot Cycle)尚未上機驗證**:`5_Blanton_Script_Reboot_Cycle.ttl` 隨 V1.1.7 交付,
|
||||
但還沒在真 DUT 上跑過一輪完整循環。兩個要現場確認的點:`wait "Booting in blind mode"` 是否
|
||||
真的在每一版開機訊息裡出現(沒出現就會永遠等下去,而且沒有 `timeout` 保護);以及每輪重跑
|
||||
`bmc-first-enroll` 是否安全。**沒有結束條件**,測夠了要自己關掉 macro。
|
||||
- **`tmp/blanton_reboottest.sh`(bash 版重開循環)也未上機驗證**:不用 Tera Term、由 systemd 在
|
||||
每次開機跑一輪並自動 `reboot`,登入下 `stop` 才停。整個 `tmp/` 是 gitignored,**不會進交付包** ——
|
||||
驗證過再搬進 `Blanton_Script/`。未驗證的腳本混進 `Blanton_Script/` 之後,測試員分不出哪支能信。
|
||||
- **交付包不含 `hammer/`,但 Script B 與 Script 4 都要用它**:V1.1.8 起 `hammer/` 是 gitignored
|
||||
且被 `publish.sh` 排除(~99 MB 的 mlucas binary,進 git 就永久留在 history)。這是刻意的 ——
|
||||
binary 由 DUT image 帶 —— 但代表**測試員解開交付包後 `~/hammer` 必須已經在 DUT 上**,
|
||||
否則 Script B 會在 `chmod +x ~/hammer/tools/amd/mlucas-avx2` 那一行失敗,而且 macro 不會停,
|
||||
接著的 `systemd-run` 只是起一個立刻失敗又被 `Restart=always` 反覆重拉的 unit。
|
||||
上機前先 `ls ~/hammer/tools/amd/mlucas-avx2` 確認一次。
|
||||
- **`mlucas-amm` 的 `~` 依賴 systemd 的環境**:unit 是
|
||||
`/bin/bash -c '~/hammer/... >> ~/hammer/mlucas_amm_log'`,system service 沒有 `User=` 時 systemd
|
||||
**不會設 `HOME`**,bash 才退回 passwd 的家目錄(root → `/root`)解出同一條路徑。目前會通,
|
||||
但那是剛好對上而不是保證;改成絕對路徑 `/root/hammer/...` 就不用賭。**尚未上機驗證。**
|
||||
- **Script C 的 USB 掛載走 `mount` 而非 `usb_target.sh -o mnt`**:目前是 `-o dev` 取節點再自己
|
||||
`mount <dev> /mnt/usb`,繞過了工具內建的 `mkdir -p`、exfat/ntfs `modprobe` 與可寫性驗證。
|
||||
掛載點不存在、檔案系統模組沒載、或媒體唯讀時只會失敗一行,job log 就沒帶出來。
|
||||
- **風扇確認提示是無限等待**:`wait "Set all configured fan channels to"` 之後才 `sendln "y"`;
|
||||
若該版 `fan-speed-control.sh` 不再詢問(或字串改了),這個 `wait` 會永遠等下去,Script A 停在那裡
|
||||
且不報錯。加個 `timeout` + 分支會比較保險(記得還原 `timeout = 0`)。
|
||||
- ✅ **TR518 已腳本化** —— `blanton_tr518.sh` V1.0.1(2026-08-28)。仍與 `blanton_traffic_linespeed`
|
||||
互斥(兩者都會動 `port cd` loopback 與 L2 學習),檔頭與 help 都標了。剩下三件事:
|
||||
`stop` 沒把 `l2 learn` / `test mode` 放回去(照 `TR518.txt` 的定義,旗標可開);
|
||||
**`sleep 120` 的方向還沒驗證** —— 若 `tr 518` 的流量是有時限的(參數含 `runtime=1`、
|
||||
`CheckDataTime=200`),等 120 秒可能量到已經降下來的值,要上機比對 0s / 30s / 120s 三次;
|
||||
TTL 尚未呼叫它。
|
||||
- **`--runtime` 是整個 job 的總時限,不是每個 pass 的**:V1.1.7 起由 `config.ttl` 宣告
|
||||
(`SSD_RUNTIME`/`SSD_COUNT`、`USB_RUNTIME`/`USB_COUNT`,COUNT 直接對應 `--passes`)。
|
||||
`qfx5252-stress-*` 跑滿 RUNTIME 秒就結束,**`--passes` 不會把它延長**,所以
|
||||
`RUNTIME=600, COUNT=720` 是 10 分鐘的壓力而不是 120 小時。要跑滿一天就把 RUNTIME 填 `86400`。
|
||||
**V1.1.8 起出貨預設是 `RUNTIME=3600`(1 小時)**,`BMC_USB_RUNTIME` 則是 `172800`(2 天)——
|
||||
三個壓力源的長度目前刻意不一致,開跑前要照當次 soak 的時間各自對一次。
|
||||
壓力提早結束時 Script B 每輪的 `bgctl list` 數量會變少,但**沒有任何東西會主動報警**;
|
||||
要比 24 小時更久則得加一段重啟 job 的邏輯。
|
||||
- **BMC USB 的 service log 只剩隨身碟一份**:Script C 把 `journalctl` 導進
|
||||
`log/bmc_usb_net.log` 再 `cp` 到 job 目錄,**不再印在 master console log**。
|
||||
那個 `cp` 沒有檢查回傳值(`nfc_polling.log` 檔名打錯那次就是這樣安靜失敗的),
|
||||
失敗的話這份 log 就完全消失。要嘛在 `cp` 之後補一次 `ls` 驗證,要嘛保留一份
|
||||
`cat` 到 console。
|
||||
- **`READ_VIN` / `READ_IIN` 不在 ADPM12200 手冊的 Table 3 裡**:`pwr_brick.sh` 讓它們沿用
|
||||
Voltage / Current 那兩組係數。50 V 輸入算得出來、數量級也對,但**手冊沒有明說**。要定案
|
||||
得找 ADI 確認,或找一個能獨立比對輸入電壓的量測點(`READ_VOUT` 就是靠 `show platform
|
||||
voltage` 的 `PDB_IBC_*` 對上的)。
|
||||
- **VI2C 沒有硬體號誌**(`vi2c_muxsel` 的 help 自己寫了「VI2C has no SEM_REG」),而平台的
|
||||
sensor 驅動會週期性讀同一批 PDB 裝置。`pwr_brick.sh` 用「重讀到合理為止」繞過去,但根本
|
||||
問題沒解:`_vrd` 裡的 `_vwait` 逾時後仍然回傳半成品,呼叫端也沒檢查它的回傳值。修
|
||||
`blanton_icb_vi2c.sh` 會影響所有走 VI2C 的工具(ICB 溫感、風扇、EEPROM),值得先確認
|
||||
是不是跟 pmon 競爭再動。
|
||||
- **`blanton_multiphase_margin.sh` 與 `margin.sh` 沒有互斥機制**:兩支從不同側(原生 i2c vs
|
||||
LTC2980 PMBus)摸同一批軌,各自都假設自己是唯一的寫入者。目前只靠文件與 help 提醒,
|
||||
沒有任何執行期檢查。
|
||||
- **Script 4 沒有收尾段**:`while 1` 之後就是檔案結尾,中斷時 DUT 停在 `port cd lb=mac` /
|
||||
`l2 learn off` / `test mode nr=yes`,而且 CPU 壓力還在跑。要手動
|
||||
`blanton_tr518.sh stop` + `systemctl stop mlucas-amm`(V1.1.8 起它是 systemd unit,
|
||||
關掉 Tera Term 或 `kill $(jobs -p)` 都收不掉),否則下一輪任何測試都在被污染的狀態上開始
|
||||
(Script A 的 `bgctl reset/stop --all` 收得掉 job,但收不掉 bcm 的 loopback 設定)。
|
||||
可考慮加一支對應的收尾腳本,或在檔尾用 `messagebox` 提示要下哪些指令。
|
||||
- **margin 在 soak 期間不再取樣**(V1.1.4):只剩 Script A 的起始值與 Script C 的結束值。
|
||||
漂移發生在中間就看不到了。若要恢復,比較好的做法是在 B 的迴圈內每 N 輪才掃一次,
|
||||
而不是每輪都掃。
|
||||
- **`blanton_ber.sh` 的 `sleep 30` 與 `BER_INTERVAL` 是兩處要同步改的數字**:Script A(V1.2.1 起)
|
||||
與 Script C 都寫死 `sendln "sleep 30"`,腳本預設 `BER_INTERVAL=30`。改一邊沒改另一邊,report 會
|
||||
讀到還沒累積完一個 interval 的數字,而且不會有任何警告。現在有**三處**要一起改。
|
||||
- **Script A 的 BER `clear` 與第一輪流量之間沒有 settle**:V1.2.1 把 BER 掃描放在流量**之前**,
|
||||
而 PRBS 是把 lane 拉出正常運作、`clear` 才放回去的。Script A 的 `blanton_ber.sh clear` 之後
|
||||
緊接著就是 `blanton_traffic_linespeed ps` / `init`,中間沒有等待;Script C 的 BER 在流量報表
|
||||
之後,沒有這個順序。上機時比對兩份 traffic report —— Script A 有 NA/FAIL 而 Script C 沒有,
|
||||
就是 lane 尚未回穩,在 `clear` 後加一個 `sleep` 即可。**尚未上機驗證。**
|
||||
- **`ce0` 的 ingress mirror 尚未上機驗證**:`mirror port ce0 Mode=Ingress DestPort=ce0` 這條路是
|
||||
推論出來的(鏡像複本不受 egress filter 的 source-port knockout 限制),語法取自 DUT 的
|
||||
`help mirror`,但**還沒證明硬體真的接受 destport == srcport**。驗證方式是隔 10 秒看兩次
|
||||
`show c | grep POK.ce0`,數字有沒有繼續長 —— 光看 report 的 PASS 分不出來,因為一次性 burst
|
||||
也是 TX==RX。不通的話備案是 `tr 518 PortList=268`。
|
||||
- **SWB 的 LTC2977 有兩條路可以到,目前工具兩條都在用**:`cb_pmbus_*`(CB FPGA F3 → pcimem)
|
||||
是 `margin_init` / `margin_status` / `margin_set` 走的路;原生 i2c bus(Ch+7 = bus 13/14/15/16)
|
||||
是 `margin_save blanton` 走的路。後者短很多 —— 不需要通道初始化、不需要 pcimem,
|
||||
單一 `i2cset` 就到。若原生 bus 在這平台夠穩,整個 `TRANSPORT="swb"` 層其實可以退成
|
||||
「bus 號不同的 i2c 路徑」,`_swb_*`、probe、semaphore、prescale 那整套都能拿掉。
|
||||
要動之前得先確認:讀取(`margin_status` 的 LINEAR16 word read)是否也同樣可靠,
|
||||
以及 kernel driver 有沒有搶著存取(`margin_save blanton` 帶 `-f` 就是為了繞過這件事)。
|
||||
- **`settings/` 裡 SWB0 與 SWB1 是兩份相同的資料**:8 個 `.conf` 中,SWB1 的四個除了 `CHIPS[]` 的
|
||||
bus 與 `CB_I2C_CH` 之外,net name 與 `VNOM` 與 SWB0 逐欄相同(見 `docs/LTC2980_channel_map.csv`)。
|
||||
改一邊忘了改另一邊不會有任何警告。可考慮改成「共用 net 定義 + 各自的 transport 覆寫」兩層檔案。
|
||||
- **Script C 沒有倒出 `mgmt_ping.log`**:C 會 `stop` 管理網路監控並印 `ip -s link show`,
|
||||
但沒有 `cat ~/Blanton_Script/log/mgmt_ping.log`,所以整個 soak 期間累積的 per-leg `RESULT`
|
||||
留在 DUT 上、沒進 master log。Script A 那輪基線有 `cat`。
|
||||
|
||||
@@ -9,6 +9,38 @@ DUT 端的取數能力由一組 **bash 工具庫** 提供(CB FPGA `pcimem` →
|
||||
|
||||
完整架構見 [ARCHITECTURE.md](ARCHITECTURE.md)。
|
||||
|
||||
**目前狀態(2026-09-08)**:Script A 為 **V1.2.1**(A 集中記錄所有 TTL 的變更)。涵蓋
|
||||
PCIe AER / DDR EDAC / PMON+TPM / 電壓 margin(9 顆 LTC2980)/ SWB loopback 線速流量 /
|
||||
10G+1G 管理網路 ping / BMC DDR 與 USB / NVMe 健康,壓力層走平台的 `bgctl`。
|
||||
switch unit 數量由 `config.ttl` 的 `SWB_UNIT0` / `SWB_UNIT1` 宣告,風扇轉速由 `FAN_SPEED` 指定
|
||||
(預設 100 = 全速;soak 是熱測試,散熱不該是變因)。
|
||||
測試 job log 收在 DUT 的 `/host/hw-eval/jobs/`,Script C 結束時掛好 USB 再帶時戳複製到 `/mnt/usb/`。
|
||||
100G PRBS(`port_prbs_monitor.sh`)已隨包交付、可手動執行,但 **V1.1.9 起 A/B/C 裡註解掉的呼叫已整段刪除**,
|
||||
要接回去得重寫(`bmc_monitor_ddr.sh` 在 Script C 的註解區塊同時移除)。
|
||||
V1.1.9 新增 **SerDes DSC 擷取**:`bcm_dsc_scan.sh`(DUT 端,`phydiag <port> dsc` 掃全機 ~445 port × 2 unit,
|
||||
約 10 分鐘)由 Script A 與 Script C 各跑一次夾住 soak,`bcm_dsc_parse.sh`(Host 端)把 raw log 轉成
|
||||
`_lane.csv` / `_pm.csv`。**由 `config.ttl` 的 `EN_TX_FIR` 控制,預設 0(關)** —— 開了整輪測試多 ~20 分鐘。
|
||||
Script B 的 soak 迴圈每輪印 `bgctl list` + `jobs` + `systemctl is-active mlucas-amm`,並 `sendln "sleep 60"`
|
||||
(V1.0.10 之前完全沒有間隔;V1.2.0 起 A/B/C 的等待一律改成 DUT 端 `sleep` 而非 macro 端 `pause`)。V1.1.8 起 AMD CPU 壓力(`mlucas-avx2`)由 `systemd-run` 掛成
|
||||
`mlucas-amm` transient unit(`Restart=always`),不再是 shell 的 `&` 背景 job —— 掉線也不會停,
|
||||
Script C 用 `systemctl stop mlucas-amm` 收掉並把 log 複製到隨身碟。
|
||||
V1.1.0 新增全機 SerDes BER 掃描(`blanton_ber.sh`,依 `SWB_UNIT` 分支);**V1.2.1 起 Script A 也接了一次**,
|
||||
在第一輪流量之前取基線,與 Script C 流量報表之後的收尾掃描一起夾住 soak(同 DSC 的做法)。另有
|
||||
TR518 負載(`blanton_tr518.sh`,**TTL 尚未接**)、SWB 軌功耗(`TH6_SWB{0,1}_power_readback.sh`),
|
||||
線速流量也納入 100G `ce0`(VLAN 138,靠 ingress mirror 維持循環)。
|
||||
Script A 開頭會先收掉前一輪殘留(`hw-test-session finish` + `bgctl reset/stop --all`),
|
||||
再 `bgctl list` 確認沒有 job 留著佔資源。
|
||||
NFC tag 讀取由 `nfc_polling.sh` 背景輪詢(A 做基線、B 起、C 停並 report)。
|
||||
另有 **`4_Blanton_Script_thermal_safety.ttl`**(熱 / 安規,**獨立跑不接 A→B→C**,滿載後每分鐘
|
||||
取 PMON + 兩片 SWB 的軌功耗;**沒有收尾段**,中斷後要手動 `blanton_tr518.sh stop`)。
|
||||
以及 **`5_Blanton_Script_Reboot_Cycle.ttl`**(重開機循環,**獨立跑不接 A→B→C**:登入 → 風扇 →
|
||||
Check Pt1~Pt13 → `reboot` → `wait "Booting in blind mode"`,`cnt_cycle` 每輪遞增,`while 1` 無止境,
|
||||
要停就關 Tera Term 的 macro)。**尚未上機驗證**。
|
||||
流程圖:`docs/Blanton_Test_Flow.drawio`。
|
||||
最後一次發布是 **V1.1.5**;SWB 的 I2C 通道與位址已於 2026-08-19 上機驗證。
|
||||
margin 的 `VNOM` 已於 2026-08-30 改為 Blanton 實測中位數(144 條軌中 86 條上調 0.8~2.5%)。
|
||||
交付用 `./publish/publish.sh` 打包。
|
||||
|
||||
## 技術棧
|
||||
|
||||
- **Host**:Tera Term 5.x TTL macro(`.ttl`),Windows
|
||||
@@ -17,6 +49,12 @@ DUT 端的取數能力由一組 **bash 工具庫** 提供(CB FPGA `pcimem` →
|
||||
- **I2C/PMBus**:CB FPGA F3 I2C master(Ch0~Ch17,base 0x300 stride 0x20)、
|
||||
CB F3 VI2C proxy → ICB/PDB(Ch0~Ch4,base 0x780)、CPU 原生 bus(`i2cset`/`i2cget`)
|
||||
- **Margin**:LTC2980(= 2 × LTC2977)over PMBus,LINEAR16
|
||||
- **資料面流量**:`bcmcmd`(Broadcom drivshell)SWB loopback,VLAN 30..137 成對 `cdN`/`cdN+32`,
|
||||
`tx 100 length=512`;判定讀 ASIC `MIB_TPOK`/`MIB_RPOK` 做 per-pair 雙向交叉比對
|
||||
- **BMC**:host 端 `bmc-manager run "<cmd>"`,不需對 BMC 開 SSH(繞開其 busybox 工具鏈)
|
||||
- **背景工作**:平台的 `bgctl run/list/stop --all/reset`;長時間 ping 用 `systemd-run --unit=` 掛 transient unit
|
||||
- **管理網路**:iproute2(`ip link set` / `address replace` / `route replace ... metric`)+ `ping -I`
|
||||
- **風扇**:max31790 driver rebind + `fan-speed-control.sh <%>`(轉速讀 `config.ttl` 的 `FAN_SPEED`)
|
||||
- **判定資料源**:PCIe AER sysfs(`aer_dev_*`)、EDAC sysfs(`dimm_{ce,ue}_count`)、SONiC `show platform *`
|
||||
- **無編譯步驟**:TTL 與 bash 都直譯執行
|
||||
|
||||
@@ -26,17 +64,19 @@ DUT 端的取數能力由一組 **bash 工具庫** 提供(CB FPGA `pcimem` →
|
||||
# ── 部署 bash 工具庫到 DUT ──────────────────────────
|
||||
scp -r src/Script_ABC_Blanton/Blanton_Script admin@<DUT_IP>:~/
|
||||
|
||||
# ── DUT 上先確認 FPGA BDF(每台不同!)───────────────
|
||||
lspci -Dnn | grep -i fpga
|
||||
ls -d /sys/bus/pci/devices/0000:*:00.3
|
||||
|
||||
# ── DUT 上載入工具(Script A 也是做這五件事)─────────
|
||||
source ~/Blanton_Script/blanton_fpga_pcimem.sh
|
||||
# ── DUT 上載入工具(Script A 也是做這六件事)─────────
|
||||
source ~/Blanton_Script/blanton_fpga_pcimem.sh # ← 會自己印出偵測到的 CB FPGA BDF
|
||||
source ~/Blanton_Script/blanton_cb_i2c.sh
|
||||
source ~/Blanton_Script/blanton_icb_vi2c.sh
|
||||
source ~/Blanton_Script/blanton_pwr_data.sh
|
||||
source ~/Blanton_Script/blanton_traffic_linespeed.sh
|
||||
source ~/Blanton_Script/LTC2980_Margin_Script/margin.sh
|
||||
|
||||
# ── FPGA BDF:自動偵測,不用改檔;必要時手動釘 ───────
|
||||
fpga_rescan # 換 DUT / 重新列舉後重測
|
||||
FPGA_BDF=0000:05:00 fpga_rescan # 偵測到多顆或選錯時,指定 domain:bus:dev(不含 .fn)
|
||||
echo $FPGA_BDF_ACTIVE # 目前生效的 BDF
|
||||
|
||||
# ── 煙霧測試 ────────────────────────────────────────
|
||||
cb_fpga 0 0xD90 # RST_CAUSE_REG,讀得到 = BAR 通了
|
||||
cb_i2c_init 11 && cb_i2c_scan 11 # Ch11 風扇控制器,應看到 0x20
|
||||
@@ -45,11 +85,138 @@ temp_all # CB + ICB 溫感
|
||||
pwr_data # SWB VRM 全軌
|
||||
margin_init Blanton_CB_CONN13 && margin_status
|
||||
|
||||
# ── 電壓 margin 寫 NVM(⚠️ 永久,測試中絕不執行)─────
|
||||
margin_save # 只寫當前 margin_init 載入的那顆(2 個 LTC2977)
|
||||
margin_save all # settings/ 全部 9 顆;跑完自動切回原本載入的那顆
|
||||
margin_save blanton # Blanton SONiC 捷徑:18 顆全走原生 i2c,不用 margin_init
|
||||
# 0x15 是 send-byte,不帶 data byte:i2cset -f -y <bus> <addr> 0x15
|
||||
# bus = FPGA F3 通道 + 7 → Ch6=13, Ch7=14, Ch8=15, Ch9=16(CB 本來就是 bus 4)
|
||||
# ⚠️ 沒裝滿的機器:改 margin.sh 頂端的 MARGIN_BLANTON_STORE,把沒有的板子註解掉
|
||||
|
||||
# ── SWB loopback 流量(bcmcmd,unit 0/1)─────────────
|
||||
# 不帶 -u 就是預設 TL_UNITS="0 1",兩塊 switch board 都做(TTL 三支腳本即如此)
|
||||
blanton_traffic_linespeed ps # 對照線的 link/speed
|
||||
blanton_traffic_linespeed init # VLAN 30..137,cdN <-> cdN+32
|
||||
blanton_traffic_linespeed clear # clear c
|
||||
blanton_traffic_linespeed start -tx 100 -length 512
|
||||
blanton_traffic_linespeed stop # 移除 VLAN 成員(--destroy 連 VLAN 一起砍)
|
||||
blanton_traffic_linespeed report # per-pair TX/RX + PASS/FAIL(exit 2 = 有 FAIL/NA)
|
||||
blanton_traffic_linespeed run # ps → init → clear → start → report 一條龍
|
||||
blanton_traffic_linespeed init -u 0 # 只做單一 unit 時才需要 -u
|
||||
blanton_traffic_linespeed init -n # -n dry-run:只印要下的 bcmcmd,不碰 DUT
|
||||
blanton_traffic_linespeed report -f <log> # 離線重解一份存下來的 console log
|
||||
|
||||
# 離線版報表(開發機上跑,選項更多)
|
||||
python3 tools/bcm_mibpair_report_V1.1.0.py <drivshell.log> -a
|
||||
|
||||
# ── 管理網路 ping 監控(需先 chmod +x!)──────────────
|
||||
chmod +x ~/Blanton_Script/*.sh # 佈署後必做一次
|
||||
~/Blanton_Script/mgmt_ping_monitor.sh fg # 前景試一輪(約 30 秒),確認 IP/對端/網卡
|
||||
~/Blanton_Script/mgmt_ping_monitor.sh start # 背景,log/mgmt_ping.log(start 會先清空)
|
||||
~/Blanton_Script/mgmt_ping_monitor.sh status
|
||||
~/Blanton_Script/mgmt_ping_monitor.sh stop
|
||||
~/Blanton_Script/mgmt_ping_monitor.sh summary # 只看每段的 RESULT 行
|
||||
# ⚠️ tail 子命令是 tail -f,會卡住不返回;TTL 裡要倒 log 請用 cat
|
||||
# bmc_monitor.sh start/stop # free -m + BMC I2C 寫入/讀回圖樣測試,log/bmc_poll.log
|
||||
# ⚠️ bmc_monitor_ddr.sh 已停用(DDR 壓力改走 bgctl + bmc-manager),檔案仍在
|
||||
|
||||
# ── 100G PRBS(目前 TTL 未啟用,手動測用)────────────
|
||||
bash ~/Blanton_Script/port_prbs_monitor.sh start # 兩個 port 同時
|
||||
bash ~/Blanton_Script/port_prbs_monitor.sh start a # 只跑 Ethernet513
|
||||
bash ~/Blanton_Script/port_prbs_monitor.sh start b # 只跑 Ethernet514
|
||||
bash ~/Blanton_Script/port_prbs_monitor.sh report # PASS/FAIL 統計(沒跑的顯示 SKIP)
|
||||
bash ~/Blanton_Script/port_prbs_monitor.sh stop # 收尾會跑 prbsstat STOp + prbs clear
|
||||
# ⚠️ PRBS 打起來時 link 會顯示 down,這是正常的 —— 所以 start 刻意不印 port status
|
||||
|
||||
# ── PDB / CPB power brick 讀值 ──────────────────────
|
||||
./Blanton_Script/pwr_brick.sh show # Vin/Iin/Vout/Iout/Temp × 5 顆
|
||||
./Blanton_Script/pwr_brick.sh show -r # 多印 raw word
|
||||
# 四顆 ADPM12200 每個量各一個 PMBus PAGE:Vin 9 / Iin 10 / Vout 2 / Iout 14 / Temp 18
|
||||
# CPB.PU37 (0x26) 是不同零件:不寫 PAGE,自己一套換算
|
||||
# PB_TRIES=1 ... show -r 可看未經重試的原始行為
|
||||
|
||||
# ── 多相 VRM margin(原生 i2c,38 條軌)──────────────
|
||||
./Blanton_Script/blanton_multiphase_margin.sh high3 # 全部 +3%
|
||||
./Blanton_Script/blanton_multiphase_margin.sh low3 # 全部 -3%
|
||||
./Blanton_Script/blanton_multiphase_margin.sh comboA # 混合,組合 A
|
||||
./Blanton_Script/blanton_multiphase_margin.sh comboB # 混合,組合 B
|
||||
./Blanton_Script/blanton_multiphase_margin.sh save # ⚠️ 永久寫 NVM
|
||||
# -u 0 / -u 1 單邊(SWB0=i2c-13/15,SWB1=i2c-14/16);-n 只印指令
|
||||
# 逐條印 SWB0_0V9_ANLG0 - 0.930V Configure Done;save 只印 Multiphase Save All
|
||||
# ⚠️ 這不是 margin.sh 管的 LTC2980,兩支摸同一批軌,不要同時用
|
||||
|
||||
# ── 全機 SerDes BER(PRBS,期間 link 會顯示 DOWN)────
|
||||
./Blanton_Script/blanton_ber.sh init # prbs set p=3 + prbs get(檢查每條 lane 鎖定)
|
||||
./Blanton_Script/blanton_ber.sh start # prbsstat STArt Interval=30
|
||||
sleep 30 # 至少等一個 interval 再 report
|
||||
./Blanton_Script/blanton_ber.sh report # 每 lane 一列,BER < 1e-6 才 PASS,最後 summary
|
||||
./Blanton_Script/blanton_ber.sh stop # prbsstat STOp
|
||||
./Blanton_Script/blanton_ber.sh clear # prbs clear(會解除 PRBS,要重測得再 init)
|
||||
# -u 0 / -u 1 單邊;-c 1e-9 換門檻;-F 只列失敗;-f <log> 離線重解
|
||||
# ⚠️ 不能跟 blanton_traffic_linespeed / blanton_tr518 同時跑(都會接管同一批 port)
|
||||
|
||||
# ── SerDes DSC 擷取(TX_FIR / RXFFE / DFE / EYE / SNR)──
|
||||
./Blanton_Script/bcm_dsc_scan.sh # unit 0+1 全掃,約 10 分鐘
|
||||
./Blanton_Script/bcm_dsc_scan.sh -u 0 # 只掃一個 unit(時間減半)
|
||||
./Blanton_Script/bcm_dsc_scan.sh -f my.log -F # 自訂檔名 + 覆蓋
|
||||
./Blanton_Script/bcm_dsc_scan.sh -n # dry-run,只列要掃的 port
|
||||
# log: ~/Blanton_Script/log/,掃完自動 cp 到 /host/hw-eval/jobs(-C 可關)
|
||||
# 檔名沒帶 %u 時會自動插 _u0 / _u1,所以兩個 unit 不會互相覆蓋
|
||||
# 結尾固定印 "### DSC_SCAN_DONE rc=<n>";rc=0 才是全部 port 都拿到完整 dump
|
||||
# ⚠️ 由 TTL 的 EN_TX_FIR 控制,預設 0(關)—— A 與 C 各掃一次,開了整輪多 ~20 分鐘
|
||||
|
||||
# ── DSC raw log → CSV(離線解,Host 或 DUT 都可)──────
|
||||
sh ~/Blanton_Script/bcm_dsc_parse.sh -i blanton_dsc_ScriptA_u0.log -o u0
|
||||
# 產出 u0_lane.csv(每 lane 一列)+ u0_pm.csv(每 pm_id 一列)
|
||||
# 純 sh + awk(mawk 相容),欄位靠括號群組順序抓,SDK 改排版不會壞;
|
||||
# 群組數 != 9 的列標成 UNPARSED 印到 stderr,不會安靜解錯
|
||||
|
||||
# ── TR518 負載 + 量功耗(TTL 尚未接)─────────────────
|
||||
./Blanton_Script/blanton_tr518.sh start # 兩 unit,跑完 settle 120s
|
||||
./Blanton_Script/TH6_SWB0_power_readback.sh # 19 條軌 V×I + TOTAL POWER
|
||||
./Blanton_Script/TH6_SWB1_power_readback.sh
|
||||
./Blanton_Script/blanton_tr518.sh stop # 只送 port cd lb=none
|
||||
# ⚠️ stop 不還原 l2 learn / test mode(TR_RESTORE_LEARN=1 / _TESTMODE=1 才會)
|
||||
|
||||
# ── NFC tag 輪詢 ────────────────────────────────────
|
||||
~/Blanton_Script/nfc_polling.sh start # 背景,start 會先清空 log
|
||||
~/Blanton_Script/nfc_polling.sh status # pid、已跑幾輪、最後一筆結果
|
||||
~/Blanton_Script/nfc_polling.sh report # PASS/FAIL/ERROR 統計,polling 中也能跑
|
||||
~/Blanton_Script/nfc_polling.sh tail 50 # 最後 50 行(不 follow,不會卡住)
|
||||
~/Blanton_Script/nfc_polling.sh stop
|
||||
# log: ~/Blanton_Script/log/nfc_poll.log
|
||||
# ERROR = 工具沒印出 [PASS]/[FAIL](或逾時),跟「tag 讀不到」分開算
|
||||
# NFC_INTERVAL_SEC / NFC_TIMEOUT_SEC / NFC_ARGS 可調(要每個子指令都帶)
|
||||
|
||||
# ── USB 目標偵測 ────────────────────────────────────
|
||||
bash ~/Blanton_Script/usb_target.sh -o dev # /dev/sdX1
|
||||
bash ~/Blanton_Script/usb_target.sh -o mnt # 掛好並回傳掛載點
|
||||
|
||||
# ── 背景壓力(平台工具)──────────────────────────────
|
||||
bgctl run /usr/sbin/memtester 1G 100
|
||||
bgctl list
|
||||
bgctl stop --all ; bgctl reset --yes
|
||||
|
||||
# ── 通道對照表(開發機上跑,改完 settings/*.conf 一定要重產)──
|
||||
./tools/gen_channel_map.sh # → docs/LTC2980_channel_map.csv(144 列)
|
||||
./tools/gen_channel_map.sh - # 只印到 stdout
|
||||
# ⚠️ 需要 gawk(用到 3 參數的 match());mawk 會直接擋下並提示
|
||||
|
||||
# ── 各工具的 help ───────────────────────────────────
|
||||
blanton_fpga_help ; blanton_cb_i2c_help ; vi2c_help
|
||||
temp_sensor_help ; pwr_data_help
|
||||
temp_sensor_help ; pwr_data_help ; blanton_traffic_linespeed_help
|
||||
```
|
||||
|
||||
**打包交付(在開發機上):**
|
||||
|
||||
```bash
|
||||
./publish/publish.sh # 版號讀 Script A 檔頭 → publish/Script_ABC_Blanton_V1.0.3/
|
||||
./publish/publish.sh -z # 另出 zip
|
||||
./publish/publish.sh -n # dry run
|
||||
```
|
||||
|
||||
要出新版**先改 Script A 檔頭的 `; Version :`**,publish 才會用新版號建資料夾。
|
||||
|
||||
**Host 端跑一輪測試:**
|
||||
|
||||
```
|
||||
@@ -69,10 +236,17 @@ Tera Term 連 COM port (115200-8-N-1)
|
||||
- **新增取數項目** = 新增一支 `utils/show_xxx.ttl`,再在主腳本 `include`,不要往主腳本塞指令
|
||||
- **bash 命名**:公開函數 `cb_i2c_* / vi2c_* / temp_* / pwr_* / margin_*`,內部 helper 一律底線開頭
|
||||
(`_cbi2c_* / _vr / _ts_* / _pwr_*`)
|
||||
- **版本紀錄**:每支 `.ttl` 與 `.sh` 檔頭都有 `Version History` 區塊,改動時**在檔頭補一行**
|
||||
(`V1.0.2 YYYY-MM-DD <做了什麼>`),不要只改版號
|
||||
- **版本紀錄**:`.sh` 每支檔頭都有 `Version History` 區塊,改動時**在檔頭補一行**
|
||||
(`V1.0.2 YYYY-MM-DD <做了什麼>`),不要只改版號。
|
||||
TTL 這邊 **2026-08-17 起改為集中制**:`1_Blanton_Script_A.ttl` 的 History 記錄 A/B/C 三支的
|
||||
所有變更,B 與 C 的檔頭版本區塊已移除。⚠️ 這是待確認的慣例變更 ——
|
||||
若要回到「每支各自記錄」,B/C 的 History 需要補回去
|
||||
- **Commit**:Conventional Commits,**英文**。scope 用 `ttl` / `fpga` / `i2c` / `vi2c` /
|
||||
`margin` / `pwr` / `temp` / `docs`
|
||||
- **換行符**:由 `.gitattributes` 管理 —— `*.sh` `*.conf` `*.py` `*.txt` `*.md` 釘 **LF**
|
||||
(要在 SONiC 上跑/被 source),`*.ttl` 維持 **CRLF**(Tera Term 只在 Windows 跑)。
|
||||
編輯 `.ttl` 時要保留 CRLF,別讓整檔變成 LF 產生假 diff
|
||||
- **打包**:`./publish/publish.sh`,版號**讀 Script A 檔頭**不是參數 —— 先改檔頭再打包
|
||||
- **Status 表**:`docs/TTL_Script_Blanton_Status_*.xlsx` 是逐項進度的正本(OK / On-Going + Owner),
|
||||
完成一項就同步更新,別讓文件跟腳本脫節
|
||||
|
||||
@@ -81,16 +255,64 @@ Tera Term 連 COM port (115200-8-N-1)
|
||||
- 🔒 **NDA:本 repo 只推 `nas` + `gitea`,絕不推 GitHub。** `docs/` 內含客戶 FPGA 規格。
|
||||
- 🔒 **DUT 帳密不進 git**。`1_Blanton_Script_A.ttl` 的 `sendln "YourPaSsWoRd"` 是 placeholder,
|
||||
實際值放 `secret/config_secret.ttl`(gitignored)。**任何 commit 前先 grep 一次確認沒帶到真密碼。**
|
||||
- ⚠️ **PCIe BDF 是 per-unit 的**。`blanton_fpga_pcimem.sh` 的 `FUNCT0..3_RES` 已經改過三次
|
||||
(04:00.x → 03:00.x → 05:00.x → 03:00.x)。換 DUT 一定先 `lspci -Dnn | grep -i fpga`,
|
||||
`utils/show_pcie_error_reg_*.ttl` 內的 BDF 也要一起校。
|
||||
- ⚠️ **PCIe BDF 是 per-unit 的 —— bash 端已自動化,TTL 端還沒**。
|
||||
`blanton_fpga_pcimem.sh` V1.5.0(2026-08-17)起 source 時自動偵測(sysfs vendor `0x1590` →
|
||||
`lspci` → `FPGA_BDF_FALLBACK`),**不用再每台改檔**;印一行 `[INFO] CB FPGA BDF = ...`,
|
||||
可用 `fpga_rescan` 重測、`FPGA_BDF=... fpga_rescan` 手動釘住。
|
||||
**但 `utils/show_pcie_error_reg_*.ttl` 裡的 7 組 BDF 仍是寫死的**,換 DUT 還是要人工校對 ——
|
||||
不校就會讀到別的裝置,或整段 `No such file or directory`。
|
||||
- ⚠️ **AER 判定看差值不看絕對值**:Script A 抓基線、Script C 抓結果,相減才是本輪錯誤。
|
||||
**Endpoint 與上游 Root Port 兩邊都要讀**,錯誤可能只記在 RP。
|
||||
- ⚠️ **ICB/PDB 一律走 VI2C(`blanton_icb_vi2c.sh`),不要走 VSPI**:VSPI ~18 ms/reg 會讓 I2C
|
||||
byte 相間隔拉到 ~50 ms,踩中 SMBus 25–35 ms timeout,裝置直接 NACK。實測全掃 9.4 s vs 34.0 s。
|
||||
- ⚠️ **I2C 讀一律 Repeated START**(不是 STOP + START),否則 PMBus/SMBus 裝置(VRM、EFUSE)不理。
|
||||
- ⚠️ **Script C 的 BMC USB service log 不進 master log**:改成
|
||||
`journalctl ... > log/bmc_usb_net.log` 再複製到隨身碟,**那是唯一一份**。
|
||||
收工後翻不到就先確認 job 目錄裡有沒有這個檔
|
||||
- ⚠️ **VI2C 這條路的壞法是「只壞高位元組」**,不是整包壞掉。`11.98 V` 會變成 `32.00 V`
|
||||
—— 正的、數量級也不誇張,**擋全一/全零的過濾完全攔不到**。寫任何 VI2C 讀值工具都要有
|
||||
合理範圍檢查 + 重讀,光靠 `PDB_REJECT_FFFF` 那種是不夠的(`pwr_brick.sh` 的教訓)
|
||||
- ⚠️ **PMBus 的 PAGE 不是只有 VRM 通道在用**:ADPM12200 把每個量測放在不同 PAGE
|
||||
(Vin 9 / Iin 10 / Vout 2 / Iout 14 / Temp 18),沒寫 PAGE 就讀,回的是 `0xFFFF` 或
|
||||
`0x0000`。`blanton_pwr_data.sh` 的 PDB 表 page 是 `-`,這就是它整張表 NA 的原因
|
||||
- ⚠️ **`--runtime` 是整個 job 的總時限,不是每個 pass 的**:V1.1.7 起由 `config.ttl` 的
|
||||
`SSD_RUNTIME`/`SSD_COUNT`、`USB_RUNTIME`/`USB_COUNT` 指定(COUNT 就是 `--passes`)。
|
||||
`qfx5252-stress-*` 跑滿 RUNTIME 秒就停,**`--passes` 不會把它延長** —— `RUNTIME=600` 就是
|
||||
10 分鐘,不是 600×COUNT。要 24 小時就填 `86400`。壓力提早結束時 `bgctl list` 數量變少是
|
||||
唯一線索,**不會報警**。V1.1.8 起出貨預設改為 `RUNTIME=3600`(1 小時),2 天 soak 要填 `172800`
|
||||
- ⚠️ **`utils/kill_all_process.ttl` 只有 `kill $(jobs -p)`,抓不到 systemd unit**:把壓力工作改成
|
||||
`systemd-run` 之後,Script C 一定要補對應的 `systemctl stop <unit>`,否則它會活過 Script C 燒進
|
||||
下一輪,**收工的溫度/功耗全部是在滿載下量的**。V1.1.8 已為 `mlucas-amm` 補上。
|
||||
Script 4 也改用同一個 unit,但它**沒有收尾段**,所以那行 `systemctl stop` 得由人手動下
|
||||
- ⚠️ **`config.ttl` 少一個變數會讓 macro 當場中止,不是當成 0**:`EN_timestamp`(V1.1.8 新增,
|
||||
餵 Script A `logopen` 的第 5 個參數)、`BMC_USB_RUNTIME` 都是必要項。只更新 `.ttl` 卻沿用舊的
|
||||
`config.ttl`,Script A 會停在 `logopen` 那一行
|
||||
- ⚠️ **log 時間戳的「格式」不在腳本裡**:`EN_timestamp` 只決定開不開,格式在 Tera Term 的
|
||||
Setup → Additional settings → Log,存在**那台電腦的 `TERATERM.INI`**。同一份 macro 在兩台機器上
|
||||
可以產生不同格式的 log,跨機比對前先確認
|
||||
- ⚠️ **多相 VRM 與 LTC2980 是同一批軌的兩條路**:`blanton_multiphase_margin.sh`(原生 i2c)
|
||||
和 `margin.sh`(LTC2980 PMBus)都假設自己是唯一寫入者,**沒有互斥檢查**,只靠人記得
|
||||
- ⚠️ **traffic 的計數器基準在 v0.7.0 變了**:`tx 100 length=512` → `tx 200 length=324`,
|
||||
每 burst 的位元組數 +27%。PASS/FAIL 是成對交叉比對不受影響,但**絕對值不能跟舊 log 比**
|
||||
- ⚠️ **Script 4(thermal/safety)沒有收尾**:`while 1` 之後就是檔尾。中斷後 DUT 停在
|
||||
`port cd lb=mac` / `l2 learn off` / `test mode nr=yes`,`mlucas-avx2` 也還在背景。
|
||||
下一個測試會在被污染的狀態上開始,而且 **`show interfaces status` 看不出來**。
|
||||
收尾:`blanton_tr518.sh stop` + `kill $(jobs -p)` + **`systemctl stop mlucas-amm`**
|
||||
(V1.1.8 起 CPU 壓力是 systemd unit,`kill $(jobs -p)` 收不掉,少這一行 CPU 會一直滿載)
|
||||
- ⚠️ **Script 4 與 Script B 不能共用同一台 DUT**:兩者都會接管 `port cd` 的 loopback
|
||||
- ⚠️ **`settings/*.conf` 的 `VNOM` 是實測中位數,不是規格值**(2026-08-30 起)。它同時是
|
||||
`margin_status` 偏差 % 的分母、也是 `margin_set` 推算 high/low/OV/UV 的基準,所以改它會
|
||||
同時移動「看到的數字」和「實際打出去的電壓」。**跨這個日期的 margin log 不能直接互比。**
|
||||
- ⚠️ **SWB 的 margin profile 是 per-CONN 的**:`combo_SWB_CONN13~16_{high,low}` 各自的百分比
|
||||
對應該片板子的軌。套到別的 CONN 會 margin 到錯的軌,而且**不會報錯**。CB 沒有專屬 profile,
|
||||
用通用的 `combo_high3` / `combo_low3`
|
||||
- ⚠️ **`margin_save` / `STORE_USER_ALL` 會永久寫 NVM**,斷電保留 → **測試流程中絕不執行**,
|
||||
以免覆蓋客戶出廠 config。`margin.sh` 的 auto-enable(`ON_OFF_CONFIG=0x1a`)只改 RAM,斷電復原。
|
||||
v2.7.0 新增的 **`margin_save all` / `margin_save blanton` 一次寫 18 個 LTC2977**,
|
||||
同一個警告放大 9 倍;另外 `0x15` 現在送 send-byte,不再帶多餘的 `0x00` data byte。
|
||||
- ⚠️ **SWB 的 LTC2977 有兩條路可以到**:`cb_pmbus_*`(CB FPGA F3 Ch6/7/8/9 → pcimem)與
|
||||
原生 i2c bus(`i2cset -f -y 13/14/15/16`,Ch+7 = bus)。`margin_save blanton` 走後者,
|
||||
其餘功能走前者。同一顆晶片,**不要同時用兩條路**。
|
||||
- ⚠️ **改電壓會弄壞 DUT**:套 profile 前確認該軌 OV/UV limit,且 servo DAC 注入電阻有 populate
|
||||
(本板部分 margin 電阻標 PROTO,沒 populate 的軌電壓不會動,不是腳本壞掉)。
|
||||
- ⚠️ **`ARB_LOST` ≠ 有裝置**:`vi2c_scan` 只看 `RX_ACK`,仲裁失敗會被誤報成裝置存在。
|
||||
@@ -99,12 +321,90 @@ Tera Term 連 COM port (115200-8-N-1)
|
||||
shell;log 也只有 A 會 `logopen`,B/C 是續寫。中途關掉 window 就得手動收程序、log 也斷了。
|
||||
- ⚠️ **MP29816 的 Vout 解析度不是固定值**,由 `MFR_VOUT_SCALE_LOOP(0x29)` bit[12:10] 決定,
|
||||
`blanton_pwr_data.sh` 執行期從晶片讀;xlsx 上寫的 `/5mV` 與 MP2985B 的 `+49` offset **都是錯的**。
|
||||
- ⚠️ **`bcmcmd` 就算失敗也 exit 0**(`VLAN: ERROR: Entry exists` /
|
||||
`Failed to execute the diagnostic command` 都照樣回 0),所以 `blanton_traffic_linespeed.sh`
|
||||
是**比對輸出**而非看 exit code。另外 `bcmcmd` 一律要 `</dev/null` ——
|
||||
否則它會吃掉 while 迴圈的 stdin,**只有第一個 VLAN 被設定**(V0.3.1 修過的 bug,很難看出來)。
|
||||
**2026-09-07 `bcm_dsc_scan.sh` 又踩了同一個坑**:port 清單走 stdin,第一次 `bcmcmd` 就把剩下的吃光,
|
||||
445 個 port 只掃了 1 個,而且 marker 與 dump 數量一起變少 → 比對通過、exit 0、log 看起來正常。
|
||||
修法是迴圈改讀 fd 3(`done 3< "$PORTFILE"`)+ `bcmcmd ... < /dev/null`,並加一道
|
||||
「實際迭代筆數 == 清單筆數」的檢查。**任何 `while ... done < file` 裡呼叫 `bcmcmd` 都要當它會讀 stdin。**
|
||||
- ⚠️ **`stress_hhmd.py` / `stress_pcie.py` 已於 2026-08-17 由 KC 移除**(Status 表 ScriptB #5/#7)。
|
||||
Script B 現在是 **8 個背景 job**(1 mlucas + 5 mem + ssd + usb),不是 10 個。
|
||||
I2C/PCIe 的持續讀取壓力目前沒有替代品。
|
||||
- ⚠️ **`pause` 是停 macro,`sleep` 是停 DUT**(V1.2.0 起 A/B/C 一律用後者):`pause N` 期間 macro 不理會
|
||||
DUT,shell 是閒著的,等於用猜的估上一個指令跑多久;`sendln "sleep N"` + `wait prompt_sonic_root`
|
||||
把等待放到 DUT 上,prompt 回來才繼續,兩邊不會走散,而且這一段會帶時戳進 log。
|
||||
**Script 4 / Script 5 尚未轉換,仍在用 `pause`**;B/C 開頭那個 `pause 1` 也保留(登入前沒有 prompt 可等)
|
||||
- ⚠️ **soak 迴圈沒有 `pause`**:取樣間隔不是 Status 表寫的 10 分鐘,而是取決於指令執行時間。
|
||||
(`-u 0` 已於 `491e807` 移除,A/B/C 現在都跑兩個 switch unit。)
|
||||
- 🔒 **`.sh` / `.conf` 一定要 LF**。CRLF 的 shell script 在 SONiC 上直接掛(`$'\r': command not found`);
|
||||
`settings/*.conf` 更陰險 —— 它們是被 `source` 的,`CB_I2C_CH=6` 會變成 `"6\r"`,安靜地壞掉。
|
||||
`.gitattributes` 已擋住 git 這條路徑,但**不會回頭重寫既有工作區檔案**:早於它 clone 的目錄要
|
||||
`git rm --cached -r . && git reset --hard` 才會生效,而且 **`git status` 乾淨不代表磁碟上是 LF**
|
||||
(`--renormalize` 只在進 index 的路上轉換)。驗證要看 byte:`grep -rlU $'\r' <dir>`
|
||||
- ⚠️ **TTL 的 `timeout` 是全域的**:`timeout = N` 之後**每一個** `wait` 都被限制在 N 秒。逾時的 `wait`
|
||||
直接返回而沒吃到 prompt,下一個指令就在前一個還沒跑完時送出,之後整輪錯開一拍。**設了一定要
|
||||
配一個 `timeout = 0` 還原**(`wait_init.ttl` 60→0;Script B 的 cdc_ncm 探測 15→0 兩處各還原一次
|
||||
—— `endif` 之後走成功路徑、`:skip_ping` 走跳過路徑;Script 5 同一段**直接還原在 `if` 之前**,
|
||||
一行涵蓋兩條路徑,因為它的 ping 區塊要 `wait` 一個 `sleep 10`,DUT 一忙就逼近 15 s 上限)
|
||||
- ⚠️ **`goto` 的標籤沒定義,Tera Term 是執行到才報錯**:Script 5 從 Script B 抄 cdc_ncm 探測時
|
||||
只帶走 `goto skip_ping` 沒帶 `:skip_ping`,平常測不出來 —— 只有真的抓不到 NCM 介面走進那條分支
|
||||
才會跳錯誤視窗停住整個循環(已補)。抄段落過去時**連標籤一起抄**
|
||||
- ⚠️ **兩張管理網卡同網段會 ARP flux**:`mgmt_ping_monitor.sh` 讓 eth0/eth1 同時 up,同一個 /24 下
|
||||
對端 ARP 可能由任一張卡回應,回包落在沒送封包的那張。`ARP_STRICT=1` 擋掉;判讀時看 `RESULT` 行的
|
||||
`nic_tx`/`nic_rx`(該卡自己的 packet delta)—— **ping 成功但 `nic_tx` 接近 0 = 封包從另一張卡出去的**
|
||||
- ⚠️ **BER 的 `clear` 才是把 lane 放回正常運作的動作**:V1.2.1 起 Script A 在第一輪流量**之前**跑 BER,
|
||||
而 `blanton_ber.sh clear` 與緊接著的 `blanton_traffic_linespeed ps` 之間**沒有任何 settle**。
|
||||
Script C 是流量報表之後才跑 BER,沒有這個順序問題。第一次上機時比對兩邊的 traffic report ——
|
||||
**Script A 有 NA/FAIL 而 Script C 沒有,就是 lane 還沒回穩**,在 `clear` 後補一個 `sleep` 即可
|
||||
- ⚠️ **PRBS 跑起來時 `show interfaces status` 會顯示 DOWN**,那是 link 離開正常運作模式,不是故障。
|
||||
`port_prbs_monitor.sh` 的 `start` 因此刻意不印 port status(避免測試員誤判),只在 `prbs clear` 之後的報表裡印
|
||||
- ⚠️ **`ip -s link` 的欄位順序是 `bytes packets errors ...`**,要 packet 數取的是**第 2 欄**不是第 1 欄
|
||||
- ⚠️ **`mgmt_ping_monitor.sh` / `bmc_monitor*.sh` 需要 exec bit**,且**不是改用 `bash x.sh start` 就能繞過** ——
|
||||
`do_start` 內部是 `setsid "$SCRIPT_PATH" __daemon`,直接執行該路徑。git 記錄是 `100644`,
|
||||
Windows → 隨身碟 → DUT 也帶不動權限位元,所以佈署後要 `chmod +x ~/Blanton_Script/bmc_monitor*.sh`。
|
||||
沒做的話 start 會 Permission denied、後面的 `cat` 撲空,而且**不會報錯**,只會得到一份全空的 log
|
||||
- ⚠️ **這幾支 monitor 的 `tail` 子命令是 `tail -n 50 -f`,永遠不返回**。TTL 裡絕對不要呼叫它
|
||||
(Script C 曾因此卡死,`18ce7a1` 改成直接 `cat log/*.log`)
|
||||
- ⚠️ **背景 monitor 的 `start` 只等 1 秒就返回**,不是跑完一輪。Script A 要做一輪基線的話,
|
||||
`start` 和 `stop` 中間必須 `pause`(目前是 45 秒,一輪約 30 秒)—— 少了它 log 只會有 START banner
|
||||
- ⚠️ **風扇那段設完會 `wait "Set all configured fan channels to"` 等確認提示再送 `y`**。該提示沒出現
|
||||
(版本改了、字串換了)就會永遠卡住且不報錯 —— 現場看起來像 Script A 當掉
|
||||
- ⚠️ **`show_dmesg.ttl` 結尾會 `dmesg -C` 清空 kernel ring buffer**。這是刻意的(讓 Script C 只看到
|
||||
soak 期間新產生的訊息),但代表事後在 DUT 上 `dmesg` 撈不到舊訊息 —— 內容只存在 master log 裡
|
||||
- ⚠️ **`bcmcmd` 的輸出是 CRLF**。`show c` 的計數器後面還跟著 delta,所以「砍掉第一個空白之後」
|
||||
順便把 CR 砍掉了;但 `prbsstat Ber` 的 BER 是**整行最後一個 token**,CR 直接黏在數字上 ——
|
||||
數字驗證會失敗(全變 NA),而且印出來時 CR 把游標拉回行首,後面的欄位會**覆蓋掉前面的欄位**。
|
||||
寫新的 awk 解析器時,第一件事就是 `{ gsub(/\r/, "") }`(`blanton_ber.sh` V1.0.1 的教訓)
|
||||
- ⚠️ **`bcmcmd` 的 exit code 兩邊都不能信**:BCM shell 拒絕指令時它回 **0**
|
||||
(`blanton_traffic_linespeed.sh` V0.3.1),而 `tr 518` 這種跑很久的指令會讓它 poll 逾時而回
|
||||
**非 0**,但指令其實已經在跑(`polling socket timeout: Success`)。可靠的作法是**找成功的證據**
|
||||
——例如 `tr 518` 印出 `TR 518 TEST PARAMETERS` 才算收下(`blanton_tr518.sh` V1.0.1)
|
||||
- ⚠️ **交換晶片不會把封包從進來的那個 port 送回去**(source-port knockout)。所以單一 port 的
|
||||
VLAN 打不出持續流量:`tx 100` 就是一趟來回然後結束。`ce0` 靠 **ingress mirror 打回自己**繞過
|
||||
這個限制(鏡像複本不經過 egress filter),**且不 stop 就不會自己停**
|
||||
- ⚠️ **DUT 的 awk 對 `%d` 會夾到 INT32**(2147483647)。線速流量的計數器是 ~10¹² 量級,
|
||||
所以 awk 裡輸出大數一律用 `%.0f`(double 域,精確到 2⁵³)。`blanton_traffic_linespeed.sh`
|
||||
V0.4.1 已修;寫新的 awk 報表時要記得同一件事
|
||||
|
||||
## 資料夾說明
|
||||
|
||||
- `src/Script_ABC_Blanton/` — 可執行內容(Tera Term 工作目錄;內含要 scp 到 DUT 的 `Blanton_Script/`)
|
||||
- `docs/` — 客戶 FPGA 規格、AER/EDAC 檢查依據、逐項 Status 表
|
||||
- `tools/` — Host 端輔助腳本(log 解析、報表產生、打包)
|
||||
- `publish/` — 交付用打包輸出(`Blanton_Script_ABC_v<ver>_<date>/` + zip)
|
||||
- `docs/` — 客戶 FPGA 規格、AER/EDAC 檢查依據、逐項 Status 表(最新為 `*_20260817.xlsx`)、
|
||||
`LTC2980_channel_map.csv`(9 個 `settings/*.conf` 合併成 Board,CONN,Ch,NetName,Vnom 144 列,
|
||||
查 net 對應哪片哪個 channel 用;**改 `.conf` 後要重跑產生**)
|
||||
- `tools/` — Host / 離線端:`bcm_mibpair_report_V1.1.0.py`(drivshell log → per-pair 報表)、
|
||||
`traffic_loopback_*.txt`(bcmcmd 原始指令表,`blanton_traffic_linespeed.sh` 是其 bash 版,
|
||||
**改 loopback 線路時兩邊要同步**)、`100G_PRBS.txt` / `TR518.txt` / `fan_ctrl.txt`
|
||||
(上機手貼用的原始指令;PRBS / TR518 / 100G traffic / multiphase normal 都已有對應 `.sh`)
|
||||
- `publish/` — `publish.sh`(打包工具,**進 git**)+ `Script_ABC_Blanton_<Ver>/` 產出(**gitignored**)
|
||||
- `tmp/` — 🚫 gitignored:**還沒上機驗證**的腳本暫存區(目前 `blanton_reboottest.sh`)。
|
||||
上機測過才搬進 `src/Script_ABC_Blanton/Blanton_Script/` 並進 git —— 未驗證的東西不該混在
|
||||
交付包裡,publish 時測試員分不出哪支能信
|
||||
- `src/Script_ABC_Blanton/hammer/` — 🚫 gitignored:mlucas 的 ELF binary(~99 MB,avx512 / avx2 /
|
||||
avx / sse2 / generic-c)。Script B 與 Script 4 會 `chmod +x` 後執行,但**它由 DUT image 帶**,
|
||||
不從這個 repo 發 —— binary 一旦進 git 就永久留在 history,每個 clone 都要付這個代價。
|
||||
`publish.sh` 也把它排除,所以打包結果不會因為誰的工作目錄有沒有 binary 而變成 100 MB
|
||||
- `secret/` — 🚫 gitignored(除 `README.md` 與 `*.example`):DUT 帳密、per-unit BDF 覆寫、COM 設定
|
||||
- `For_AI/` — 🚫 gitignored:AI 協作素材(波形截圖、草稿筆記)
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,172 @@
|
||||
<mxfile host="app.diagrams.net" agent="Blanton_TTL_Script/tools" version="24.7.17">
|
||||
<diagram id="blanton-test-flow" name="Blanton Test Flow">
|
||||
<mxGraphModel dx="1400" dy="900" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1670" pageHeight="1785" math="0" shadow="0">
|
||||
<root>
|
||||
<mxCell id="0"/>
|
||||
<mxCell id="1" parent="0"/>
|
||||
<mxCell id="n11" value="Blanton (Project Helios) — 測試流程" style="text;html=1;align=center;verticalAlign=middle;fontSize=20;fontStyle=1;" vertex="1" parent="1"><mxGeometry x="30" y="20" width="1610" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="n12" value="來源:src/Script_ABC_Blanton/{1,2,3}_Blanton_Script_*.ttl(Script A V1.1.3) · ⟨…⟩ = 由 config.ttl 的旗標決定" style="text;html=1;align=center;verticalAlign=middle;fontSize=11;fontColor=#666666;" vertex="1" parent="1"><mxGeometry x="30" y="54" width="1610" height="20" as="geometry"/></mxCell>
|
||||
<mxCell id="n13" value="Script A — Pre-test(基線 / 環境建立)" style="swimlane;html=1;startSize=34;fillColor=#ffffff;strokeColor=#4d4d4d;fontSize=14;fontStyle=1;horizontal=1;" vertex="1" parent="1"><mxGeometry x="30" y="96" width="380" height="1459" as="geometry"/></mxCell>
|
||||
<mxCell id="n14" value="<b>include config.ttl</b><br>project_name, strTestcase, EN_Margin,<br>EN_log, FAN_SPEED, SWB_UNIT0/1" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="44" width="344" height="64" as="geometry"/></mxCell>
|
||||
<mxCell id="n15" value="<b>logopen</b> Logs/&lt;proj&gt;_&lt;case&gt;_&lt;ts&gt;.log<br><i>⟨EN_log = 1⟩</i>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="124" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e16" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n14" target="n15"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n17" value="<b>Root Login</b><br>login → sudo -i → root@sonic:~#" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="189" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e18" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n15" target="n17"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n19" value="<b>Pre Setting</b><br>date -s 對時 · rm /host/hw-eval/jobs/*" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="254" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e20" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n17" target="n19"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n21" value="<b>HW Test Session — 收前一輪</b><br>hw-test-session finish · bgctl reset --yes<br>bgctl stop --all · <b>bgctl list 必須空</b>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="319" width="344" height="64" as="geometry"/></mxCell>
|
||||
<mxCell id="e22" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n19" target="n21"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n23" value="<b>hw-test-session start</b>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="399" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e24" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n21" target="n23"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n25" value="<b>FAN SPEED</b><br>max31790 rebind ×2 → fan-speed-control.sh $FAN_SPEED" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="449" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e26" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n23" target="n25"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n27" value="<b>Wait DUT Init</b> utils/wait_init.ttl<br>輪詢 bcmcmd ps,兩 unit link up ≥ 216<br><i>⟨SWB_UNIT0 / SWB_UNIT1⟩ · 無逾時出口</i>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="514" width="344" height="64" as="geometry"/></mxCell>
|
||||
<mxCell id="e28" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n25" target="n27"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n29" value="<b>DUT Info</b><br>show boot/version/platform · fwutil · syseeprom<br>ssdhealth · TPM · NVMe" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="594" width="344" height="64" as="geometry"/></mxCell>
|
||||
<mxCell id="e30" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n27" target="n29"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n31" value="<b>BMC</b> bmc-first-enroll · version · status" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="674" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e32" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n29" target="n31"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n33" value="<b>Load Shell Script</b><br>source blanton_fpga_pcimem / cb_i2c / icb_vi2c /<br>temp_sensor / pwr_data / traffic_linespeed / margin" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="724" width="344" height="64" as="geometry"/></mxCell>
|
||||
<mxCell id="e34" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n31" target="n33"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n35" value="<b>CLEAR PCIe Error</b> ×7<br>TH6_SWB0 · TH6_SWB1 · FPGA · BMC · DDR · I210 · SSD" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="804" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e36" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n33" target="n35"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n37" value="<b>PCIe tree / link / bandwidth</b> utils/pcie_bus.ttl" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="869" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e38" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n35" target="n37"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n39" value="<b>Check Margin</b> margin_status_all.sh(9 顆 LTC2980)<br><i>⟨EN_Margin = 1⟩</i>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="919" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e40" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n37" target="n39"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n41" value="<b>TAKE DATA</b> setup_pmon.ttl(9 項)+ show_dmesg.ttl" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="984" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e42" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n39" target="n41"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n43" value="<b>10G/1G MGMT Ping</b><br>start → 30s → report → clear" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="1034" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e44" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n41" target="n43"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n45" value="<b>NFC Test</b><br>start → status → 30s → stop → report" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="1099" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e46" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n43" target="n45"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n47" value="<b>100G Port Status</b> Ethernet513 / 514" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="1164" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e48" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n45" target="n47"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n49" value="<b>100G PRBS</b> port_prbs_monitor.sh<br><i>整段註解 — bring-up 中</i>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#999999;dashed=1;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;fontColor=#808080;" vertex="1" parent="n13"><mxGeometry x="18" y="1214" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e50" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n47" target="n49"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n51" value="<b>First Traffic Test(基線)</b><br>ps → init → clear → 15s → show → start → 15s → report<br><i>⟨SWB_UNIT⟩ 兩邊 / -u 0 / -u 1 / skip</i>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="1279" width="344" height="64" as="geometry"/></mxCell>
|
||||
<mxCell id="e52" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n49" target="n51"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n53" value="<b>Show power-on uptime</b>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n13"><mxGeometry x="18" y="1359" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e54" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n51" target="n53"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n55" value="messagebox 『Script A DONE / Start Script B』" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;align=center;verticalAlign=middle;fontSize=11;fontStyle=1;" vertex="1" parent="n13"><mxGeometry x="18" y="1409" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e56" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n53" target="n55"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n57" value="Script B — Stress(壓力 soak,人為中斷才結束)" style="swimlane;html=1;startSize=34;fillColor=#ffffff;strokeColor=#4d4d4d;fontSize=14;fontStyle=1;horizontal=1;" vertex="1" parent="1"><mxGeometry x="440" y="96" width="380" height="1014" as="geometry"/></mxCell>
|
||||
<mxCell id="n58" value="<b>include config.ttl</b>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="44" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="n59" value="<b>CLEAR EVENT</b>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="94" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e60" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n58" target="n59"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n61" value="<b>AMD CPU Stress</b> mlucas-avx2 -cpu 0:15" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="144" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e62" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n59" target="n61"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n63" value="<b>BMC DDR Stress</b> bgctl run bmc-manager memtester" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="194" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e64" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n61" target="n63"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n65" value="<b>BMC Monitor</b> bmc_monitor.sh start<br>free -m + I2C 寫入/讀回圖樣測試" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="244" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e66" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n63" target="n65"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n67" value="<b>DDR Memory Stress</b> bgctl run memtester" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="309" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e68" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n65" target="n67"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n69" value="<b>SSD read/write</b> bgctl run qfx5252-stress-ssd" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="359" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e70" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n67" target="n69"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n71" value="<b>USB read/write</b> usb_target.sh -o dev → bgctl run<br>qfx5252-stress-usb" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="409" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e72" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n69" target="n71"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n73" value="<b>SHOW Background job</b> bgctl list" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="474" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e74" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n71" target="n73"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n75" value="<b>BMC USB Test</b> 偵測 cdc_ncm 介面" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="524" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e76" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n73" target="n75"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n77" value="<b>:skip_ping</b> <b>timeout = 0</b>(還原全域逾時)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="574" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e78" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n75" target="n77"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n79" value="<b>10G/1G MGMT Ping</b> start → status" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="624" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e80" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n77" target="n79"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n81" value="<b>NFC Test</b> start → status" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="674" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e82" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n79" target="n81"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n83" value="<b>100G Port</b> lpmode off · config interface startup" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="724" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e84" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n81" target="n83"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n85" value="<b>100G PRBS</b> <i>整段註解 — bring-up 中</i>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#999999;dashed=1;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;fontColor=#808080;" vertex="1" parent="n57"><mxGeometry x="18" y="774" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e86" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n83" target="n85"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n87" value="<b>Traffic START</b><br>ps → init → clear → 15s → show → start<br><i>⟨SWB_UNIT⟩ 兩邊 / -u 0 / -u 1 / skip</i>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="824" width="344" height="64" as="geometry"/></mxCell>
|
||||
<mxCell id="e88" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n85" target="n87"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n89" value="<b>while 1 — soak 監控迴圈</b><br>setup_pmon.ttl(9 項)<br>bgctl list + jobs<br><b>pause 60</b><br><i>V1.1.4 起 margin 移到 Script C</i>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n57"><mxGeometry x="18" y="904" width="344" height="94" as="geometry"/></mxCell>
|
||||
<mxCell id="e90" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n87" target="n89"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n91" value="Script C — Post-test(收尾 / 判定 / 收 log)" style="swimlane;html=1;startSize=34;fillColor=#ffffff;strokeColor=#4d4d4d;fontSize=14;fontStyle=1;horizontal=1;" vertex="1" parent="1"><mxGeometry x="850" y="96" width="380" height="1259" as="geometry"/></mxCell>
|
||||
<mxCell id="n92" value="<b>include config.ttl</b>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="44" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="n93" value="<b>Kill Process</b> utils/kill_all_process.ttl<br>kill $(jobs -p) · bgctl stop --all ×2<br>停 BMC USB service · mgmt_ping stop · <b>nfc stop</b>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="94" width="344" height="64" as="geometry"/></mxCell>
|
||||
<mxCell id="e94" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n92" target="n93"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n95" value="<b>100G PRBS STOP</b> <i>整段註解</i>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#999999;dashed=1;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;fontColor=#808080;" vertex="1" parent="n91"><mxGeometry x="18" y="174" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e96" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n93" target="n95"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n97" value="<b>TAKE DATA</b> setup_pmon.ttl + show_dmesg.ttl" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="224" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e98" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n95" target="n97"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n99" value="<b>Check PCIe error counters</b> ×7(同 Script A)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="274" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e100" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n97" target="n99"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n101" value="<b>BMC DDR / BMC Monitor 取值</b> cat bmc_ddr.log · bmc_poll.log" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="324" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e102" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n99" target="n101"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n103" value="<b>BMC USB Test result</b> journalctl" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="374" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e104" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n101" target="n103"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n105" value="<b>CHECK Stress results</b><br>cat mlucas / memtester / ssd / usb log" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="424" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e106" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n103" target="n105"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n107" value="<b>10G/1G MGMT result</b> ip -s link show eth0/eth1 · cat log" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="489" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e108" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n105" target="n107"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n109" value="<b>NFC Test result</b> nfc_polling.sh report" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="539" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e110" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n107" target="n109"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n111" value="<b>100G Port</b> show interfaces status" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="589" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e112" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n109" target="n111"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n113" value="<b>CHECK Traffic counters</b><br>stop → report(per-pair TX/RX + ce0)<br><i>⟨SWB_UNIT⟩ 兩邊 / -u 0 / -u 1 / skip</i>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="639" width="344" height="64" as="geometry"/></mxCell>
|
||||
<mxCell id="e114" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n111" target="n113"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n115" value="<b>BER 掃描</b> blanton_ber.sh<br>init → start → <b>sleep 30</b> → report → stop → clear<br><i>⟨SWB_UNIT⟩ · sleep 30 要與 BER_INTERVAL 同步</i>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="719" width="344" height="64" as="geometry"/></mxCell>
|
||||
<mxCell id="e116" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n113" target="n115"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n117" value="<b>NVMe Err Info</b> nvme smart-log · smartctl -x" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="799" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e118" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n115" target="n117"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n119" value="<b>show reboot-cause</b>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="849" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e120" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n117" target="n119"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n121" value="<b>Check Margin</b> margin_status_all.sh(9 顆)<br><i>⟨EN_Margin = 1⟩ · V1.1.4 從 Script B 移來</i>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="899" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e122" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n119" target="n121"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n123" value="<b>show uptime</b>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="964" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e124" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n121" target="n123"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n125" value="<b>Copy Stress Log to USB</b><br>usb_target.sh → mount → cp 各 log 進 jobs/<br>→ 帶時戳複製到 /mnt/usb/" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="1014" width="344" height="64" as="geometry"/></mxCell>
|
||||
<mxCell id="e126" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n123" target="n125"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n127" value="<b>exit</b> → wait 『Script done』<br>離開 hw-test-session 的 shell" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="1094" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e128" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n125" target="n127"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n129" value="<b>hw-test-session finish</b> · bgctl reset --yes" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n91"><mxGeometry x="18" y="1159" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e130" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n127" target="n129"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n131" value="messagebox 『GOOD JOB! Test Case DONE』" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;align=center;verticalAlign=middle;fontSize=11;fontStyle=1;" vertex="1" parent="n91"><mxGeometry x="18" y="1209" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e132" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n129" target="n131"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n133" value="Script 4 — Thermal &amp; Safety(獨立跑,不接 A/B/C)" style="swimlane;html=1;startSize=34;fillColor=#ffffff;strokeColor=#4d4d4d;fontSize=14;fontStyle=1;horizontal=1;" vertex="1" parent="1"><mxGeometry x="1260" y="96" width="380" height="929" as="geometry"/></mxCell>
|
||||
<mxCell id="n134" value="<b>include config.ttl</b>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="44" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="n135" value="<b>logopen</b> <i>⟨EN_log = 1⟩</i>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="94" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e136" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n134" target="n135"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n137" value="<b>Root Login</b> → sudo -i" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="144" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e138" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n135" target="n137"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n139" value="<b>Pre Setting</b> mkdir ./logs · date -s · rm jobs/*" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="194" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e140" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n137" target="n139"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n141" value="<b>HW Test Session</b> finish → bgctl reset/stop --all → list<br>→ start → log → status" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="244" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e142" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n139" target="n141"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n143" value="<b>FAN SPEED</b> max31790 rebind ×2 → fan-speed-control.sh" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="309" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e144" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n141" target="n143"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n145" value="<b>Wait DUT Init</b> utils/wait_init.ttl<br><i>無逾時出口</i>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="359" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e146" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n143" target="n145"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n147" value="<b>DUT Info</b> boot/version/fwutil/system-memory/service<br>syseeprom · ssdhealth · TPM · NVMe" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="424" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e148" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n145" target="n147"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n149" value="<b>BMC</b> enroll · version · status" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="489" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e150" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n147" target="n149"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n151" value="<b>CLEAR PCIe Error</b> ×7 + ras-mc-ctl --summary" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="539" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e152" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n149" target="n151"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n153" value="<b>PCIe tree / link / bandwidth</b>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="589" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e154" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n151" target="n153"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n155" value="<b>TAKE DATA</b> setup_pmon.ttl + show_dmesg.ttl" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="639" width="344" height="34" as="geometry"/></mxCell>
|
||||
<mxCell id="e156" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n153" target="n155"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n157" value="<b>Full Load — CPU</b><br>chmod +x → mlucas-avx2 -s l -cpu 0:15 &amp;" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="689" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e158" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n155" target="n157"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n159" value="<b>Full Load — 資料面</b><br>blanton_tr518.sh start(含 120s settle)" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="754" width="344" height="49" as="geometry"/></mxCell>
|
||||
<mxCell id="e160" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n157" target="n159"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n161" value="<b>while 1 — 熱 / 安規監控迴圈</b><br>setup_pmon.ttl(9 項)<br>TH6_SWB0 / SWB1_power_readback.sh<br>bgctl list + jobs<br><b>pause 60</b>" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="n133"><mxGeometry x="18" y="819" width="344" height="94" as="geometry"/></mxCell>
|
||||
<mxCell id="e162" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#4d4d4d;" edge="1" parent="1" source="n159" target="n161"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="e163" value="人工啟動 Script B" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#d79b00;strokeWidth=2;dashed=1;fontSize=10;fontColor=#d79b00;" edge="1" parent="1" source="n55" target="n58"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="e164" value="soak 結束後人工中斷,啟動 Script C" style="edgeStyle=orthogonalEdgeStyle;rounded=1;html=1;strokeColor=#d79b00;strokeWidth=2;dashed=1;fontSize=10;fontColor=#d79b00;" edge="1" parent="1" source="n89" target="n92"><mxGeometry relative="1" as="geometry"/></mxCell>
|
||||
<mxCell id="n165" value="圖例" style="text;html=1;align=left;verticalAlign=middle;fontSize=13;fontStyle=1;" vertex="1" parent="1"><mxGeometry x="30" y="1585" width="200" height="24" as="geometry"/></mxCell>
|
||||
<mxCell id="n166" value="一般步驟" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="1"><mxGeometry x="30" y="1613" width="230" height="32" as="geometry"/></mxCell>
|
||||
<mxCell id="n167" value="受 config.ttl 旗標影響" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#fff2cc;strokeColor=#d6b656;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="1"><mxGeometry x="280" y="1613" width="230" height="32" as="geometry"/></mxCell>
|
||||
<mxCell id="n168" value="迴圈 / 持續執行" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#d5e8d4;strokeColor=#82b366;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="1"><mxGeometry x="530" y="1613" width="230" height="32" as="geometry"/></mxCell>
|
||||
<mxCell id="n169" value="目前註解停用" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f5f5f5;strokeColor=#999999;dashed=1;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;fontColor=#808080;" vertex="1" parent="1"><mxGeometry x="30" y="1655" width="230" height="32" as="geometry"/></mxCell>
|
||||
<mxCell id="n170" value="狀態變更 / 需留意" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;align=left;spacingLeft=8;verticalAlign=middle;fontSize=11;" vertex="1" parent="1"><mxGeometry x="280" y="1655" width="230" height="32" as="geometry"/></mxCell>
|
||||
<mxCell id="n171" value="人工交接點" style="rounded=1;whiteSpace=wrap;html=1;fillColor=#ffe6cc;strokeColor=#d79b00;align=center;verticalAlign=middle;fontSize=11;fontStyle=1;" vertex="1" parent="1"><mxGeometry x="530" y="1655" width="230" height="32" as="geometry"/></mxCell>
|
||||
<mxCell id="n172" value="⚠️ 已知待辦:① 100G PRBS 三支腳本內呼叫仍註解(bring-up 中) ② wait_init.ttl 與風扇確認 wait 沒有逾時出口,起不來會無限等待 ③ Script C 的 sleep 30 需與 blanton_ber.sh 的 BER_INTERVAL 同步 ④ Script 4 沒有收尾段:中斷後 tr518 留下 port cd lb=mac / l2 learn off / test mode nr=yes,需手動 blanton_tr518.sh stop" style="text;html=1;align=left;verticalAlign=top;fontSize=11;fontColor=#b85450;" vertex="1" parent="1"><mxGeometry x="30" y="1703" width="1610" height="46" as="geometry"/></mxCell>
|
||||
</root>
|
||||
</mxGraphModel>
|
||||
</diagram>
|
||||
</mxfile>
|
||||
@@ -0,0 +1,145 @@
|
||||
Board,CONN,Ch,NetName,Vnom
|
||||
CB,CONN13,CH0,V5P0_ALW,5.0
|
||||
CB,CONN13,CH1,V3P3_ALW,3.3
|
||||
CB,CONN13,CH2,PWR_VDD_MISC_ALW,0.75
|
||||
CB,CONN13,CH3,V1P8_ALW,1.8
|
||||
CB,CONN13,CH4,PWR_APU_VDDIO_SUS,1.1
|
||||
CB,CONN13,CH5,PWR_VDD_MISC_RUN,0.75
|
||||
CB,CONN13,CH6,PWR_APU_VDD_MEM_RUN,0.78
|
||||
CB,CONN13,CH7,V0P8_PHY2_DVDD,0.816
|
||||
CB,CONN13,CH8,V0P8_AVDD,0.8
|
||||
CB,CONN13,CH9,V0P8_PHY,0.8
|
||||
CB,CONN13,CH10,V1P8_FPGA,1.8
|
||||
CB,CONN13,CH11,V2P5_FPGA,2.5
|
||||
CB,CONN13,CH12,V1P1_FPGA,1.1
|
||||
CB,CONN13,CH13,P5V_STBY,5.0
|
||||
CB,CONN13,CH14,P3V3_STBY,3.3
|
||||
CB,CONN13,CH15,V0P8_PHY2_AVDD,0.816
|
||||
SWB0,CONN13,CH0,P0V75_DVDD_47,0.75
|
||||
SWB0,CONN13,CH1,P0V75_AVDD_47,0.756
|
||||
SWB0,CONN13,CH2,P1V5_AVDD_47,1.524
|
||||
SWB0,CONN13,CH3,P0V9_AVDD_47,0.915
|
||||
SWB0,CONN13,CH4,P1V8_1,1.816
|
||||
SWB0,CONN13,CH5,PVDD3_3V_SYNTH_LDO_A3,3.38
|
||||
SWB0,CONN13,CH6,PVDD3_3V_SYNTH_LDO_B1,3.38
|
||||
SWB0,CONN13,CH7,P1V8_3,1.816
|
||||
SWB0,CONN13,CH8,P1V8_DVDDIO_3,1.8
|
||||
SWB0,CONN13,CH9,P0V75_DVDD_39,0.75
|
||||
SWB0,CONN13,CH10,P0V75_AVDD_39,0.756
|
||||
SWB0,CONN13,CH11,P1V5_AVDD_39,1.524
|
||||
SWB0,CONN13,CH12,P0V9_AVDD_39,0.915
|
||||
SWB0,CONN13,CH13,PVDD1V5_2,1.5
|
||||
SWB0,CONN13,CH14,PVDD1V8_DUT,1.8
|
||||
SWB0,CONN13,CH15,PVDD_MDIO,1.2
|
||||
SWB0,CONN14,CH0,P0V75_AVDD_7,0.756
|
||||
SWB0,CONN14,CH1,P1V5_AVDD_7,1.524
|
||||
SWB0,CONN14,CH2,P0V9_AVDD_7,0.915
|
||||
SWB0,CONN14,CH3,P1V8_5,1.816
|
||||
SWB0,CONN14,CH4,P1V8_2,1.816
|
||||
SWB0,CONN14,CH5,PVDD3_3V_SYNTH_LDO_B2,3.38
|
||||
SWB0,CONN14,CH6,PVDD3_3V_SYNTH_LDO_A2,3.38
|
||||
SWB0,CONN14,CH7,PVDD3_3V_SYNTH_LDO_A1,3.38
|
||||
SWB0,CONN14,CH8,PVDD1V5_TSC,1.516
|
||||
SWB0,CONN14,CH9,PVDD1V5_ANLG,1.516
|
||||
SWB0,CONN14,CH10,NC,-
|
||||
SWB0,CONN14,CH11,NC,-
|
||||
SWB0,CONN14,CH12,PVDD1V5_1,1.5
|
||||
SWB0,CONN14,CH13,NC,-
|
||||
SWB0,CONN14,CH14,P1V8_DVDDIO_1,1.8
|
||||
SWB0,CONN14,CH15,P0V75_DVDD_7,0.75
|
||||
SWB0,CONN15,CH0,P1V5_AVDD_55,1.524
|
||||
SWB0,CONN15,CH1,P0V9_AVDD_55,0.915
|
||||
SWB0,CONN15,CH2,P0V75_DVDD_63,0.75
|
||||
SWB0,CONN15,CH3,P0V75_AVDD_63,0.756
|
||||
SWB0,CONN15,CH4,P1V5_AVDD_63,1.524
|
||||
SWB0,CONN15,CH5,P0V9_AVDD_63,0.915
|
||||
SWB0,CONN15,CH6,PVDD3_3V_SYNTH_LDO_B3,3.38
|
||||
SWB0,CONN15,CH7,PVDD1V5_3,1.5
|
||||
SWB0,CONN15,CH8,P0V85_STBY,0.85
|
||||
SWB0,CONN15,CH9,P1V8_STBY,1.8
|
||||
SWB0,CONN15,CH10,NC,-
|
||||
SWB0,CONN15,CH11,P3V3_STBY,3.3
|
||||
SWB0,CONN15,CH12,PVDD0V9_2,0.91
|
||||
SWB0,CONN15,CH13,P0V75_DVDD_55,0.75
|
||||
SWB0,CONN15,CH14,P0V75_AVDD_55,0.756
|
||||
SWB0,CONN15,CH15,P1V8_DVDDIO_4,1.8
|
||||
SWB0,CONN16,CH0,PVDD1V5_0,1.5
|
||||
SWB0,CONN16,CH1,P1V8_4,1.816
|
||||
SWB0,CONN16,CH2,PVDD3_3V_SYNTH_LDO_B5,3.38
|
||||
SWB0,CONN16,CH3,PVDD3_3V_SYNTH_LDO_A5,3.38
|
||||
SWB0,CONN16,CH4,PVDD3_3V_SYNTH_LDO_B4,3.38
|
||||
SWB0,CONN16,CH5,PVDD3_3V_SYNTH_LDO_A4,3.38
|
||||
SWB0,CONN16,CH6,P3V3,3.327
|
||||
SWB0,CONN16,CH7,PVDD0_8V_T3,0.82
|
||||
SWB0,CONN16,CH8,P0V75_DVDD_1,0.75
|
||||
SWB0,CONN16,CH9,P0V75_AVDD_1,0.756
|
||||
SWB0,CONN16,CH10,P1V5_AVDD_1,1.524
|
||||
SWB0,CONN16,CH11,P0V9_AVDD_1,0.915
|
||||
SWB0,CONN16,CH12,PVDD0V9_0,0.915
|
||||
SWB0,CONN16,CH13,PVDD0V9_1,0.91
|
||||
SWB0,CONN16,CH14,PVDD0V9_3,0.915
|
||||
SWB0,CONN16,CH15,PVDD1V2_T3,1.224
|
||||
SWB1,CONN13,CH0,P0V75_DVDD_47,0.75
|
||||
SWB1,CONN13,CH1,P0V75_AVDD_47,0.756
|
||||
SWB1,CONN13,CH2,P1V5_AVDD_47,1.524
|
||||
SWB1,CONN13,CH3,P0V9_AVDD_47,0.915
|
||||
SWB1,CONN13,CH4,P1V8_1,1.816
|
||||
SWB1,CONN13,CH5,PVDD3_3V_SYNTH_LDO_A3,3.38
|
||||
SWB1,CONN13,CH6,PVDD3_3V_SYNTH_LDO_B1,3.38
|
||||
SWB1,CONN13,CH7,P1V8_3,1.816
|
||||
SWB1,CONN13,CH8,P1V8_DVDDIO_3,1.8
|
||||
SWB1,CONN13,CH9,P0V75_DVDD_39,0.75
|
||||
SWB1,CONN13,CH10,P0V75_AVDD_39,0.756
|
||||
SWB1,CONN13,CH11,P1V5_AVDD_39,1.524
|
||||
SWB1,CONN13,CH12,P0V9_AVDD_39,0.915
|
||||
SWB1,CONN13,CH13,PVDD1V5_2,1.5
|
||||
SWB1,CONN13,CH14,PVDD1V8_DUT,1.8
|
||||
SWB1,CONN13,CH15,PVDD_MDIO,1.2
|
||||
SWB1,CONN14,CH0,P0V75_AVDD_7,0.756
|
||||
SWB1,CONN14,CH1,P1V5_AVDD_7,1.524
|
||||
SWB1,CONN14,CH2,P0V9_AVDD_7,0.915
|
||||
SWB1,CONN14,CH3,P1V8_5,1.816
|
||||
SWB1,CONN14,CH4,P1V8_2,1.816
|
||||
SWB1,CONN14,CH5,PVDD3_3V_SYNTH_LDO_B2,3.38
|
||||
SWB1,CONN14,CH6,PVDD3_3V_SYNTH_LDO_A2,3.38
|
||||
SWB1,CONN14,CH7,PVDD3_3V_SYNTH_LDO_A1,3.38
|
||||
SWB1,CONN14,CH8,PVDD1V5_TSC,1.516
|
||||
SWB1,CONN14,CH9,PVDD1V5_ANLG,1.516
|
||||
SWB1,CONN14,CH10,NC,-
|
||||
SWB1,CONN14,CH11,NC,-
|
||||
SWB1,CONN14,CH12,PVDD1V5_1,1.5
|
||||
SWB1,CONN14,CH13,NC,-
|
||||
SWB1,CONN14,CH14,P1V8_DVDDIO_1,1.8
|
||||
SWB1,CONN14,CH15,P0V75_DVDD_7,0.75
|
||||
SWB1,CONN15,CH0,P1V5_AVDD_55,1.524
|
||||
SWB1,CONN15,CH1,P0V9_AVDD_55,0.915
|
||||
SWB1,CONN15,CH2,P0V75_DVDD_63,0.75
|
||||
SWB1,CONN15,CH3,P0V75_AVDD_63,0.756
|
||||
SWB1,CONN15,CH4,P1V5_AVDD_63,1.524
|
||||
SWB1,CONN15,CH5,P0V9_AVDD_63,0.915
|
||||
SWB1,CONN15,CH6,PVDD3_3V_SYNTH_LDO_B3,3.38
|
||||
SWB1,CONN15,CH7,PVDD1V5_3,1.5
|
||||
SWB1,CONN15,CH8,P0V85_STBY,0.85
|
||||
SWB1,CONN15,CH9,P1V8_STBY,1.8
|
||||
SWB1,CONN15,CH10,NC,-
|
||||
SWB1,CONN15,CH11,P3V3_STBY,3.3
|
||||
SWB1,CONN15,CH12,PVDD0V9_2,0.91
|
||||
SWB1,CONN15,CH13,P0V75_DVDD_55,0.75
|
||||
SWB1,CONN15,CH14,P0V75_AVDD_55,0.756
|
||||
SWB1,CONN15,CH15,P1V8_DVDDIO_4,1.8
|
||||
SWB1,CONN16,CH0,PVDD1V5_0,1.5
|
||||
SWB1,CONN16,CH1,P1V8_4,1.816
|
||||
SWB1,CONN16,CH2,PVDD3_3V_SYNTH_LDO_B5,3.38
|
||||
SWB1,CONN16,CH3,PVDD3_3V_SYNTH_LDO_A5,3.38
|
||||
SWB1,CONN16,CH4,PVDD3_3V_SYNTH_LDO_B4,3.38
|
||||
SWB1,CONN16,CH5,PVDD3_3V_SYNTH_LDO_A4,3.38
|
||||
SWB1,CONN16,CH6,P3V3,3.327
|
||||
SWB1,CONN16,CH7,PVDD0_8V_T3,0.82
|
||||
SWB1,CONN16,CH8,P0V75_DVDD_1,0.75
|
||||
SWB1,CONN16,CH9,P0V75_AVDD_1,0.756
|
||||
SWB1,CONN16,CH10,P1V5_AVDD_1,1.524
|
||||
SWB1,CONN16,CH11,P0V9_AVDD_1,0.915
|
||||
SWB1,CONN16,CH12,PVDD0V9_0,0.915
|
||||
SWB1,CONN16,CH13,PVDD0V9_1,0.91
|
||||
SWB1,CONN16,CH14,PVDD0V9_3,0.915
|
||||
SWB1,CONN16,CH15,PVDD1V2_T3,1.224
|
||||
|
@@ -0,0 +1,56 @@
|
||||
# v1.0.10 — The soak loop stops spinning flat out, and shows you what is still running
|
||||
|
||||
## ✨ New features
|
||||
|
||||
**Every soak round now reports the background jobs**
|
||||
* Script B's monitoring loop prints `bgctl list` (platform jobs) and `jobs` (the login shell's own background jobs) on every pass, right after the platform data. A stress job that dies three hours into an overnight soak now shows up as a shorter list on the next round, instead of only being noticed at the end — or not at all.
|
||||
* The two lists answer different questions and are both worth having: `bgctl` knows about the platform's job runner, `jobs` knows about anything the macro backgrounded in that shell.
|
||||
|
||||
**A single table for all 144 margin channels**
|
||||
* `docs/LTC2980_channel_map.csv` flattens the nine `settings/*.conf` files into one sheet — `Board,CONN,Ch,NetName,Vnom` — so "which board and channel is `PVDD1V5_TSC` on?" is one search instead of opening nine files.
|
||||
* `tools/gen_channel_map.sh` regenerates it. **The CSV is output, not source**: edit the `.conf` files and re-run the script, never the other way round.
|
||||
* Unused channels stay in the table as `NC` / `-` rather than being dropped, because the channel number is also the PMBus page (`ch / 8` picks the chip, `ch % 8` picks the page) — filtering the gaps out would shift everything after them.
|
||||
|
||||
**The bench command lists that these scripts came from**
|
||||
* `tools/100G_PRBS.txt`, `tools/TR518.txt` and `tools/fan_ctrl.txt` join the existing `traffic_loopback_*.txt` set: the raw `bcmcmd` / sysfs sequences, kept in the form you can paste into a console when a script is misbehaving and you want to drive the hardware directly.
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**The soak loop ran as fast as the DUT could answer**
|
||||
* `while 1` had no pause at all, so each round started the moment the previous one finished. Over a long soak that means constant console traffic and a log full of near-identical samples taken seconds apart. The loop now ends each round with `pause 60`.
|
||||
* Note the gap this leaves: the Status sheet asks for a 10-minute sampling interval, and 60 seconds is still hard-coded rather than configurable. This makes the loop sane, it does not finish the job.
|
||||
|
||||
**A comment promised a cadence the code never had**
|
||||
* The loop was labelled `Get data every 10mins` while running with no delay whatsoever. It now says what it does.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.0.10.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
**After copying to the DUT:**
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh # see below
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
```
|
||||
|
||||
`mgmt_ping_monitor.sh` and `port_prbs_monitor.sh` launch their workers through `bash`, so those two run without the execute bit. `bmc_monitor.sh` and `usb_target.sh` still need it, and neither git (mode 100644) nor a Windows/USB copy carries it. Without the `chmod`, `start` fails with `Permission denied` and the later `cat` finds nothing: **the section ends up empty and nothing reports an error.**
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **Declare the switch population.** `SWB_UNIT0` / `SWB_UNIT1` in `config.ttl` say which switch units this DUT has; traffic and the readiness gate both follow them.
|
||||
* **Set `FAN_SPEED`.** It is applied at the start of every run.
|
||||
* **Management connectivity is in use, not preserved.** Both management NICs are up and pinging — drive the run from the serial console.
|
||||
* **PRBS is still not wired into the macros.** Run `port_prbs_monitor.sh` by hand if you want it; the calls in A/B/C remain commented out, unchanged from v1.0.9.
|
||||
* **TR518 and the loopback traffic test cannot both run.** `tools/TR518.txt` sets `port all lb=mac` and `l2 learn off` across the whole unit, which is the same hardware `blanton_traffic_linespeed` is using. Pick one.
|
||||
* **Two settings persist to `config_db.json`** and survive a reboot: LLDP is left disabled and the 100G uplinks are left configured. Restore them before the DUT moves on.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
* [LTC2980_channel_map.csv](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/docs/LTC2980_channel_map.csv) — all 144 margin channels
|
||||
|
||||
**Full changelog:** [V1.0.9...V1.0.10](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.0.9...V1.0.10)
|
||||
@@ -0,0 +1,59 @@
|
||||
# v1.0.11 — Saving the margin settings to NVM is now one command, and the command is correct
|
||||
|
||||
## ✨ New features
|
||||
|
||||
**`margin_save blanton` — all 18 LTC2977 in one go**
|
||||
* On this platform the CB FPGA's I2C channels are also exposed as ordinary Linux i2c buses, so every margin controller on the box — CB and both switch boards — can be reached with plain `i2cset`. `margin_save blanton` walks all 18 of them from one flat list: no `margin_init`, no FPGA channel setup, no `pcimem`.
|
||||
* The channel-to-bus mapping it relies on (F3 Ch6 → bus 13, Ch7 → 14, Ch8 → 15, Ch9 → 16; CB is bus 4 as before) is now written down in `ARCHITECTURE.md` and the margin README, not just known at the bench.
|
||||
* **A partly-populated DUT is a normal build.** Comment out the lines you do not have in `MARGIN_BLANTON_STORE` at the top of `margin.sh` rather than letting the tool talk to boards that are not there.
|
||||
* Missing bus and unresponsive chip are reported as two different failures. `/dev/i2c-16 does not exist` means the FPGA's i2c adapters did not enumerate; `i2cset failed (NACK/busy)` means the board is absent or the address is wrong. Chasing the second when you have the first wastes an afternoon.
|
||||
|
||||
**`margin_save all` — every board in `settings/`**
|
||||
* Runs `margin_init` + `margin_save` across all nine boards, then puts back whichever board you had loaded, so a following `margin_status` still reports the board you were looking at.
|
||||
* It does not stop at the first failure: a half-saved set is harder to reason about than a fully-attempted one. The summary names the boards that failed.
|
||||
|
||||
Both print a per-chip line and a `N saved, M failed` tally, and both return a non-zero exit code when anything failed.
|
||||
|
||||
**The fans now default to full speed**
|
||||
* `FAN_SPEED` in `config.ttl` is 100 instead of 30. A soak is a thermal test of everything *except* the cooling, so the cooling should not be a variable in it — and a DUT that throttles halfway through a run produces results that look like a different fault. Lower it deliberately if quiet operation is what you are measuring.
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**A failed NVM write still reported success**
|
||||
* `margin_save` discarded the result of every write, so a NACK printed `Change Saved` exactly like a successful store. For the one operation in this tool that is permanent, that is the worst place to stay quiet. Each store is now checked and named if it fails.
|
||||
|
||||
**`STORE_USER_ALL` was sent with a data byte it should not have**
|
||||
* The command went out as `0x15` followed by a dummy `0x00` — an SMBus write-byte, where `STORE_USER_ALL` is a send-byte. The LTC2977 tolerated it, but tolerance is not correctness. It is now `i2cset ... 0x15 c` on the native path and a no-data `cb_pmbus_write` on the FPGA path.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.0.11.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
**After copying to the DUT:**
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh # see below
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
```
|
||||
|
||||
`mgmt_ping_monitor.sh` and `port_prbs_monitor.sh` launch their workers through `bash`, so those two run without the execute bit. `bmc_monitor.sh` and `usb_target.sh` still need it, and neither git (mode 100644) nor a Windows/USB copy carries it. Without the `chmod`, `start` fails with `Permission denied` and the later `cat` finds nothing: **the section ends up empty and nothing reports an error.**
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **`margin_save` in any form writes NVM permanently.** A power cycle does not undo it. `margin_save all` and `margin_save blanton` do it to all 18 controllers at once. Run `margin_status_all.sh` first and never call any of them during a test run — the macros do not, and should not be made to.
|
||||
* **The 18 raw commands were verified on the DUT; the wrapper was not.** `margin_save blanton` issues exactly the sequence that was run by hand at the bench, and the packaging was tested against stubbed hardware, but the function itself has not been run on a DUT yet. Watch the per-chip lines the first time.
|
||||
* **Declare the switch population.** `SWB_UNIT0` / `SWB_UNIT1` in `config.ttl` say which switch units this DUT has; traffic and the readiness gate both follow them.
|
||||
* **`FAN_SPEED` is now 100.** It is applied at the start of every run, so this build runs the fans flat out unless you change `config.ttl`. Expect the noise.
|
||||
* **Management connectivity is in use, not preserved.** Both management NICs are up and pinging — drive the run from the serial console.
|
||||
* **PRBS is still not wired into the macros.** Run `port_prbs_monitor.sh` by hand if you want it; the calls in A/B/C remain commented out.
|
||||
* **Two settings persist to `config_db.json`** and survive a reboot: LLDP is left disabled and the 100G uplinks are left configured. Restore them before the DUT moves on.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
* [LTC2980_Margin_Script/README.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/src/Script_ABC_Blanton/Blanton_Script/LTC2980_Margin_Script/README.md) — the three `margin_save` variants and what each one sends
|
||||
|
||||
**Full changelog:** [V1.0.10...V1.0.11](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.0.10...V1.0.11)
|
||||
@@ -0,0 +1,65 @@
|
||||
# v1.0.7 — Management-link ping test, and the fans start where you set them
|
||||
|
||||
## ✨ New features
|
||||
|
||||
**10G / 1G management port ping test**
|
||||
* New `mgmt_ping_monitor.sh` exercises both management NICs in one loop: it brings each up with iproute2, waits for the link to settle, then pings that NIC's own target — `eth0` → `192.168.1.30`, `eth1` → `192.168.1.31`.
|
||||
* Runs detached like the other monitors: `start` / `stop` / `status` / `fg` / `summary`. `start` clears the previous log, so one run means one log.
|
||||
* Every leg writes a single greppable line — `RESULT 10G eth0 -> 192.168.1.30 tx=10 rx=10 loss=0% rtt_avg=1.743ms nic_tx=10 nic_rx=10 PASS` — so a whole soak can be read with `summary` instead of scrolling.
|
||||
* `nic_tx` / `nic_rx` are that interface's own counter delta across the burst. If a ping passes but they stay near zero, the traffic left on the *other* NIC and the number does not belong to this one.
|
||||
* Script A runs one round as a baseline; Script B leaves it running through the soak.
|
||||
|
||||
**Fan speed is set at the start of every run**
|
||||
* `FAN_SPEED` in `config.ttl` (default 30) is applied by Script A, so a run no longer inherits whatever the previous test left the fans doing.
|
||||
* Both MAX31790 controllers are rebound first, which clears a controller left in an odd state.
|
||||
|
||||
**Stress load moved onto the platform's own job runner**
|
||||
* CPU, DDR, SSD and USB stress now go through `bgctl`, replacing the `~/hammer/tools/stress_*.py` scripts. `bgctl list` shows what is running; Script C stops everything with `bgctl stop --all`.
|
||||
* BMC DDR stress runs through `bmc-manager`, and a new BMC USB test discovers the `cdc_ncm` interface and pings across it for four hours under `systemd-run`.
|
||||
|
||||
**More of the DUT on record**
|
||||
* Script A now captures the boot image, `show version`, firmware status, system EEPROM, SSD health, TPM version and NVMe SMART data before the test starts.
|
||||
* PCIe AER now sits next to `ras-mc-ctl --summary`, and Script C closes with NVMe health so a disk that degraded during the soak is visible.
|
||||
* `dmesg` capture uses human-readable timestamps and one combined error pattern, then clears the ring buffer — so Script C's dmesg shows only what the soak produced, not everything since boot.
|
||||
* Each run opens with `hw-test-session start` and closes with `finish`; Script C copies the job logs to `/mnt/usb/jobs-<date>_<time>` so they leave the DUT with the run they belong to.
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**Script A no longer hangs waiting for ports that are already up**
|
||||
* The readiness gate required *more than* 216 ports up, but a fully cabled unit reports exactly 216 — 108 loopback pairs times two. Script A sat in the poll loop forever on the very state it was waiting for. It now proceeds at 216.
|
||||
* The comments in `wait_init.ttl` still described the old "more than" rule; they now match the code, so the off-by-one cannot be reintroduced by reading the wrong line.
|
||||
|
||||
**The macro no longer runs ahead of the DUT during the soak**
|
||||
* Script B set a 15-second wait cap for the `cdc_ncm` probe and never restored it. In Tera Term that cap is global, so it stayed in force for everything after — including the traffic setup, which walks 108 VLANs per switch unit and takes far longer. A timed-out wait returns without the prompt, leaving every later command issued a step early.
|
||||
|
||||
**Fan controller is no longer bound twice**
|
||||
* One of the two MAX31790 controllers received a second `bind` immediately after the first, which could only fail because the driver was already attached.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.0.7.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
**After copying to the DUT:**
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh # required -- see below
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
```
|
||||
|
||||
The `chmod +x` is not optional. `mgmt_ping_monitor.sh` is executed rather than sourced and re-execs its own path to daemonise, and neither git (mode 100644) nor a Windows/USB copy carries the execute bit. Without it `start` fails with `Permission denied` and the later `cat` finds nothing — **the section ends up empty and nothing reports an error**.
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **Declare the switch population.** `SWB_UNIT0` / `SWB_UNIT1` in `config.ttl` say which switch units this DUT has. Traffic and the readiness gate both follow them: a single unit gets `-u 0` or `-u 1`, and with neither set the traffic stage is skipped instead of failing against hardware that is not there.
|
||||
* **Both management NICs stay up.** If they share a subnet, keep `ARP_STRICT=1` — otherwise the target's ARP can be answered by either NIC and a reply may arrive on the one that did not send.
|
||||
* **Management connectivity is exercised, not preserved.** Drive the run from the serial console.
|
||||
* **Two settings persist to `config_db.json`** and survive a reboot: LLDP is left disabled, and the 100G uplinks are left configured. Restore them before the DUT moves on.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
|
||||
**Full changelog:** [V1.0.5...V1.0.7](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.0.5...V1.0.7)
|
||||
@@ -0,0 +1,61 @@
|
||||
# v1.0.8 — Both management links tested at once, and ARP stops looking like packet loss
|
||||
|
||||
## ✨ New features
|
||||
|
||||
**Both management NICs are pinged simultaneously and continuously**
|
||||
* `mgmt_ping_monitor.sh` no longer alternates fixed bursts. `start` configures both NICs, then pings from each at the same time and keeps accumulating until stopped — so a soak-long run is one continuous measurement rather than a series of snapshots.
|
||||
* `stop` renders a report into the log: the last 20 entries per NIC, each one's ping statistics and PASS/FAIL, then `ip -s link show` for both interfaces.
|
||||
* Every line is timestamped, and a request that got no reply prints a marker instead of merely being absent — a drop is visible in the tail, not inferred from a gap in the sequence numbers.
|
||||
* `status` shows both pids and how many replies each NIC has received so far, which is the quick way to see one side is dead without waiting for the report.
|
||||
|
||||
**The USB stress target is detected, not assumed**
|
||||
* New `usb_target.sh` reports an inserted USB device's node, mount point or by-id path. Script B asks it for the node and builds the stress command from the answer, so a stick that enumerates as `sdb` no longer sends a write test at whatever `/dev/sda1` happens to be.
|
||||
* It excludes whatever disk backs `/` and `/host` — this platform can boot from a USB DOM, which also reports as USB — refuses to guess when several USB disks are present, and when it mounts, verifies the result is actually writable rather than trusting that `mount` succeeded.
|
||||
|
||||
**BMC I2C integrity is exercised through the soak**
|
||||
* `bmc_monitor.sh` is back in the run and now writes two complementary patterns to a BMC scratch register and reads each back. One pattern alone cannot catch a bit stuck the same way it was written; repeating the pair through the soak turns an intermittent I2C fault into something the log records rather than something the tester has to witness.
|
||||
|
||||
**Test artefacts leave the DUT with the run**
|
||||
* Script C copies `bmc_poll.log` and `mgmt_ping.log` into the job directory before it is archived to USB, so the monitors' output travels with the `bgctl` job logs.
|
||||
* DDR stress now runs continuously instead of stopping after 100 passes, matching the other soak loads.
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**Three FAILs that were not link faults**
|
||||
* A bench run reported `FAIL=3` with zero NIC errors, zero drops and sub-millisecond replies. Every failure was missing exactly `icmp_seq=1` and nothing else: once the neighbour entry for the target expires, the first echo request is spent resolving ARP and `ping` counts it as loss. A discarded warm-up ping per NIC now absorbs that, which is what lets the loss threshold stay at zero and still mean something. Raising the threshold instead would have hidden genuine single-packet loss.
|
||||
|
||||
**Job logs were being cleared before they were collected**
|
||||
* Script C ran `bgctl reset --yes` while killing processes — before the job directory is copied to USB. Moved to after the archive, so a run's own logs are collected before anything clears them.
|
||||
|
||||
**The fan controller was bound twice**
|
||||
* One of the two MAX31790 controllers received a second `bind` immediately after the first, which could only fail because the driver was already attached.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.0.8.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
**After copying to the DUT:**
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh # see below
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
```
|
||||
|
||||
`mgmt_ping_monitor.sh` no longer re-execs itself, so `bash mgmt_ping_monitor.sh start` works without the execute bit. `bmc_monitor.sh` and `usb_target.sh` still need it — and neither git (mode 100644) nor a Windows/USB copy carries it. Without the `chmod`, `start` fails with `Permission denied` and the later `cat` finds nothing: **the section ends up empty and nothing reports an error.**
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **Declare the switch population.** `SWB_UNIT0` / `SWB_UNIT1` in `config.ttl` say which switch units this DUT has. Traffic and the readiness gate both follow them; with neither set the traffic stage is skipped rather than failing against hardware that is not there.
|
||||
* **Set the fan speed you want.** `FAN_SPEED` in `config.ttl` is applied at the start of every run.
|
||||
* **Management connectivity is in use, not preserved.** Both NICs are up and pinging — drive the run from the serial console.
|
||||
* **If the two management NICs share a subnet, keep `ARP_STRICT=1`.** Otherwise the target's ARP can be answered by either NIC and a reply may arrive on the one that did not send. Check `nic_tx` / `nic_rx` on the RESULT line: they are that interface's own counter delta.
|
||||
* **Two settings persist to `config_db.json`** and survive a reboot: LLDP is left disabled and the 100G uplinks are left configured. Restore them before the DUT moves on.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
|
||||
**Full changelog:** [V1.0.7...V1.0.8](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.0.7...V1.0.8)
|
||||
@@ -0,0 +1,63 @@
|
||||
# v1.0.9 — 100G PRBS testing, and the job logs actually reach the USB stick
|
||||
|
||||
## ✨ New features
|
||||
|
||||
**100G uplink PRBS test**
|
||||
* New `port_prbs_monitor.sh` drives a PRBS test on both 100G uplinks: it clears low-power mode, arms the pattern, then polls `phy diag <phy> prbs get` in the background until stopped. A poll counts as PASS only when the output says `PRBS OK!`; `prbsstat Ber` is captured alongside every poll for the record.
|
||||
* `stop` runs `prbsstat STOp` and `prbs clear` on each port before rendering the report, so the test does not leave PRBS armed behind it.
|
||||
* `report` gives the tally the bench actually wants:
|
||||
|
||||
```
|
||||
PORT POLLS PASS FAIL RESULT
|
||||
Ethernet513 42 42 0 PASS
|
||||
Ethernet514 42 40 2 FAIL
|
||||
```
|
||||
* **One port at a time is a first-class mode.** `start a` or `start b` runs a single uplink, which is how you separate a genuine port fault from the DUT not coping with two PRBS streams at once. A port that was not run reports `SKIP`, not `FAIL`.
|
||||
* Every command and its full output — setup, each poll, teardown — goes to that port's raw log.
|
||||
|
||||
> ⚠️ The script ships in this build and can be run by hand, but **the calls in Script A, B and C are commented out**: PRBS is still under bring-up on this platform.
|
||||
|
||||
**USB target detection**
|
||||
* `usb_target.sh` reports an inserted USB device's node, mount point or by-id path. It excludes whatever disk backs `/` and `/host` — this platform can boot from a USB DOM, which also reports as USB — refuses to guess when several USB disks are present, and when mounting, verifies the result is writable rather than trusting that `mount` succeeded.
|
||||
* Script B builds the USB stress command from the detected node instead of a hard-coded `/dev/sda1`.
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**The job logs were being written to a path nobody collected**
|
||||
* Stress output, the monitors' logs and the USB archive disagreed about where the job directory lives. Everything now uses `/host/hw-eval/jobs/`, so what Script B writes is what Script C copies out.
|
||||
|
||||
**Script C copied to a USB that was never mounted**
|
||||
* The archive step assumed `/mnt/usb` was ready. Script C now finds the device and mounts it first, so a run's logs leave the DUT instead of being written into an empty mount point.
|
||||
|
||||
**`show interfaces status` right after starting PRBS reads as a failure**
|
||||
* With PRBS armed the link is out of normal operation and reports DOWN. `port_prbs_monitor.sh` deliberately does not print the port status at `start` — it appears in the report instead, after `prbs clear`, labelled as the recovered state.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.0.9.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
**After copying to the DUT:**
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh # see below
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
```
|
||||
|
||||
`mgmt_ping_monitor.sh` and `port_prbs_monitor.sh` launch their workers through `bash`, so those two run without the execute bit. `bmc_monitor.sh` and `usb_target.sh` still need it, and neither git (mode 100644) nor a Windows/USB copy carries it. Without the `chmod`, `start` fails with `Permission denied` and the later `cat` finds nothing: **the section ends up empty and nothing reports an error.**
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **Declare the switch population.** `SWB_UNIT0` / `SWB_UNIT1` in `config.ttl` say which switch units this DUT has; traffic and the readiness gate both follow them.
|
||||
* **Set `FAN_SPEED`.** It is applied at the start of every run.
|
||||
* **Management connectivity is in use, not preserved.** Both management NICs are up and pinging — drive the run from the serial console.
|
||||
* **PRBS is not wired into the macros yet.** Run `port_prbs_monitor.sh` by hand if you want it; uncommenting the calls in A/B/C is not supported in this build.
|
||||
* **Two settings persist to `config_db.json`** and survive a reboot: LLDP is left disabled and the 100G uplinks are left configured. Restore them before the DUT moves on.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
|
||||
**Full changelog:** [V1.0.8...V1.0.9](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.0.8...V1.0.9)
|
||||
@@ -0,0 +1,81 @@
|
||||
# v1.1.0 — BER, power under load, and a 100G port that actually keeps sending
|
||||
|
||||
## ✨ New features
|
||||
|
||||
**Whole-switch SerDes BER sweep**
|
||||
* New `blanton_ber.sh` runs PRBS across every cabled port and reports the bit error rate lane by lane. `init` → `start` → wait → `report` → `stop` → `clear`, with `-u 0` / `-u 1` for a single switch unit.
|
||||
* **A lane passes only when its BER is below 1e-6.** Equal to the threshold is a FAIL, not a pass. `-c <ber>` sets a different bar.
|
||||
* `report` ends with a summary across both units, and each unit's row carries its **worst lane** — so a run where everything passes still tells you how much margin there was:
|
||||
|
||||
```
|
||||
Unit LANES PASS FAIL NA WORST BER WORST LANE RESULT
|
||||
unit 0 432 432 0 0 1.98e-08 203[0] PASS
|
||||
unit 1 432 432 0 0 6.34e-10 366[1] PASS
|
||||
```
|
||||
* `init` also checks that every lane locked. This matters: an unlocked lane still reports a BER later, and it is a meaningless one. Without the check, a dead lane can report a beautiful number and pass.
|
||||
* A lane whose reading is not a number is `NA` — counted separately from `FAIL`, because "not measured" and "measured and bad" are different problems.
|
||||
* Script C runs the sweep after the traffic report, following `SWB_UNIT0` / `SWB_UNIT1` the same way the traffic block does.
|
||||
|
||||
**TR518 load test, for measuring power under traffic**
|
||||
* New `blanton_tr518.sh` puts the cd ports in loopback and runs the built-in `tr 518` packet test, then waits `TR_SETTLE_SEC` (120s by default) before handing back — so the power figures you take afterwards are loaded and settled, not caught mid-ramp.
|
||||
* `-u 0` / `-u 1` for one unit; no flag runs both.
|
||||
* `stop` sends `port cd lb=none` and nothing else, which is exactly what the bench procedure does. **L2 learning and test mode are left as `start` set them** — the tool says so on every `stop` rather than quietly leaving the box in a state you did not ask about. `TR_RESTORE_LEARN=1` / `TR_RESTORE_TESTMODE=1` if you want a true inverse.
|
||||
|
||||
**Per-rail power readback for both switch boards**
|
||||
* `TH6_SWB0_power_readback.sh` / `TH6_SWB1_power_readback.sh` report V × I and total power for the 19 rails on each board.
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**The power readback measured every rail at a different moment**
|
||||
* It ran `show platform voltage` and `show platform current` once *per rail* — 38 invocations of a slow CLI, and 38 different instants. Under load the currents move a lot (`TH6_CORE` was seen going from 186 A to 636 A), so the "total" was a sum of readings taken seconds apart. Both tables are now read once, up front. Same output, one moment.
|
||||
* A rail missing from the sensor table used to contribute a silent `0.000 V / 0.00 W` to the total. It now says so on stderr; the printed report format is unchanged.
|
||||
|
||||
**The 100G port stopped sending after one round trip**
|
||||
* `ce0` has no loopback partner, and a switch never forwards a frame back out the port it arrived on — so a `tx` burst went out, came back, and was dropped. TX 100, RX 100, silence. That measures the link; it does not exercise it.
|
||||
* `init` now sets an ingress mirror of `ce0` back to itself. The mirrored copy is not egress-filtered, so each packet keeps lapping and the load is set by how much you inject (`-tx`). **`stop` is what ends it** — removing the VLAN membership does not, because the mirrored copy never consulted the VLAN.
|
||||
|
||||
**The 100G verdict was being decided the wrong way**
|
||||
* `ce0` was treated as a cross-unit check. The bench says otherwise: there is one `ce0` per unit and a burst sent on unit 0 alone came back on unit 0. It is now judged within its own unit. The distinction is invisible while everything works and decisive when it does not — read as cross-unit, *both* links dying still leaves `unit0.TX == unit1.RX` (0 == 0) and reports PASS.
|
||||
|
||||
**Every BER lane reported `NA`, and the Port column printed `NA` too**
|
||||
* `bcmcmd` returns CRLF, and the BER is the last token on its line, so the carriage return stayed glued to the number: it failed the numeric check, and printing it sent the cursor back to column 1 so the RESULT column overwrote the start of the row. Both symptoms, one stray `\r`.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.1.0.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
**After copying to the DUT:**
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh # see below
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
```
|
||||
|
||||
`blanton_ber.sh` is invoked by Script C as `./Blanton_Script/blanton_ber.sh`, so it joins `bmc_monitor.sh` and `usb_target.sh` in needing the execute bit — and neither git nor a Windows/USB copy carries it reliably. Without the `chmod` the BER section fails with `Permission denied` and the log simply has no BER in it.
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **These three tests cannot share the switch.** `blanton_ber.sh`, `blanton_tr518.sh` and `blanton_traffic_linespeed` all take over port loopback and L2 learning. Run one at a time; Script C already orders BER after the traffic report.
|
||||
* **PRBS takes the links down.** While `blanton_ber.sh` is armed the ports report DOWN and no traffic passes. That is the test working, not a fault. `clear` releases them.
|
||||
* **`ce0` keeps running until you stop it.** If a run is interrupted between `start` and `stop`, the 100G port stays saturated with nothing in `show interfaces status` to hint at it. `blanton_traffic_linespeed stop` (or `bcmcmd -n <u> -c 'mirror port ce0 Mode=Off'`) ends it.
|
||||
* **Two numbers must stay in step**: Script C's `sleep 30` and `blanton_ber.sh`'s `BER_INTERVAL`. Change one without the other and `report` reads an interval that has not finished accumulating — with no warning.
|
||||
* **`FAN_SPEED` is 100.** This build runs the fans flat out unless you change `config.ttl`.
|
||||
* **Declare the switch population** with `SWB_UNIT0` / `SWB_UNIT1`; traffic, the readiness gate and now the BER sweep all follow it.
|
||||
* **PRBS on the two 100G uplinks (`port_prbs_monitor.sh`) is still not wired into the macros.** Unchanged from v1.0.9.
|
||||
|
||||
## 🔬 Not yet verified on hardware
|
||||
|
||||
Three things in this build were reasoned out rather than measured, and each has a one-command check:
|
||||
|
||||
* **The `ce0` ingress mirror.** `mirror port ce0 Mode=Ingress DestPort=ce0` should make the port circulate, but the hardware may refuse a mirror destination equal to its source. Check `show c | grep POK.ce0` twice ten seconds apart — the number must climb. The report cannot tell you: a one-shot burst is also `TX == RX` and also says PASS. Fallback is `tr 518 PortList=268`.
|
||||
* **The 120s settle in `blanton_tr518.sh`.** If `tr 518`'s traffic is time-limited (its parameters include `runtime=1`, `CheckDataTime=200`), waiting 120s could mean measuring after the load has already dropped. Compare a power readback at 0s, 30s and 120s.
|
||||
* **`test mode nr=no`** in `blanton_tr518.sh` is the derived inverse of the `nr=yes` that `start` sends; it is not part of the bench-verified sequence, and is off by default.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
|
||||
**Full changelog:** [V1.0.11...V1.1.0](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.0.11...V1.1.0)
|
||||
@@ -0,0 +1,42 @@
|
||||
# v1.1.1 — A run no longer inherits the last one's leftovers
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**A previous run's jobs and session survived into the next one**
|
||||
* Script A now clears the box before it starts: `hw-test-session finish`, `bgctl reset --yes`, `bgctl stop --all`, then `bgctl list` so you can see it came back empty.
|
||||
* This matters after a run that ended badly — a closed Tera Term window, a DUT reboot mid-soak, a macro stopped by hand. The stress jobs kept running and the session stayed open, so the next run started on a box that was already loaded. Nothing failed; the numbers were just quietly wrong, and the only hint was a `bgctl list` nobody was reading.
|
||||
* The `bgctl list` at the end is the point of the sequence, not decoration: it is the one line in the log that proves the DUT was idle when the run began.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.1.1.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
**After copying to the DUT:**
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh # see below
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
```
|
||||
|
||||
`blanton_ber.sh` is invoked by Script C as `./Blanton_Script/blanton_ber.sh`, so it needs the execute bit along with `bmc_monitor.sh` and `usb_target.sh` — and neither git nor a Windows/USB copy carries it reliably. Without the `chmod` the BER section fails with `Permission denied` and the log simply has no BER in it.
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **`hw-test-session finish` at the start will complain if no session is open.** That is expected on a fresh DUT and does not stop the run.
|
||||
* **These three tests cannot share the switch.** `blanton_ber.sh`, `blanton_tr518.sh` and `blanton_traffic_linespeed` all take over port loopback and L2 learning. Script C already orders BER after the traffic report.
|
||||
* **PRBS takes the links down** while `blanton_ber.sh` is armed. That is the test working, not a fault.
|
||||
* **`ce0` keeps running until you stop it.** If a run is interrupted between `start` and `stop`, the 100G port stays saturated with nothing in `show interfaces status` to hint at it.
|
||||
* **Two numbers must stay in step**: Script C's `sleep 30` and `blanton_ber.sh`'s `BER_INTERVAL`.
|
||||
* **`FAN_SPEED` is 100** — the fans run flat out unless you change `config.ttl`.
|
||||
* **Declare the switch population** with `SWB_UNIT0` / `SWB_UNIT1`.
|
||||
* **PRBS on the two 100G uplinks (`port_prbs_monitor.sh`) is still not wired into the macros.**
|
||||
* **The three items listed as unverified in v1.1.0 are still unverified**: the `ce0` ingress mirror, the 120s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop. See [v1.1.0](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/releases/tag/V1.1.0) for the one-command check on each.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
|
||||
**Full changelog:** [V1.1.0...V1.1.1](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.0...V1.1.1)
|
||||
@@ -0,0 +1,63 @@
|
||||
# v1.1.2 — NFC tag reads are now watched for the whole soak, not sampled once
|
||||
|
||||
## ✨ New features
|
||||
|
||||
**Background NFC polling**
|
||||
* New `nfc_polling.sh` runs `blantons_nfc_validate.py` over and over in the background and keeps score. `start` / `stop` / `status` / `tail` / `report` / `clear` / `fg`.
|
||||
* **`report` works while the poll is still running.** It only reads the log, so it never disturbs the run — and it labels itself `RUNNING` so a mid-soak snapshot is not mistaken for the final answer:
|
||||
|
||||
```
|
||||
state : RUNNING (pid=2240323) -- this is a snapshot, the count is still moving
|
||||
rounds : 240
|
||||
PASS : 238
|
||||
FAIL : 2
|
||||
ERROR : 0 (tool did not produce a verdict)
|
||||
RESULT : FAIL
|
||||
|
||||
--- tags seen ---
|
||||
046F7BD2142290 238
|
||||
```
|
||||
* **`ERROR` is counted apart from `FAIL`.** A round where the tool printed neither `[PASS]` nor `[FAIL]` — it crashed, the file was missing, it hung past the timeout — did not measure anything. That is a different problem from a tag that would not read, and rolling the two together hides whichever one you are not looking for.
|
||||
* `report` also lists which NFCID1s were seen and how often, and the last ten failures with their timestamps and reasons.
|
||||
* `start` clears the log first, so a report always describes the run you just did rather than everything since the DUT was built.
|
||||
* Script A takes a 30-second NFC baseline, Script B starts the poll for the soak, Script C stops it with the other monitors and reports.
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**The NFC log never reached the USB stick**
|
||||
* Script C copied `nfc_polling.log`; the file is `nfc_poll.log`. The `cp` failed, nothing checked it, and the run finished looking fine — you would only notice back at the desk with a job archive that had no NFC log in it.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.1.2.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
**After copying to the DUT:**
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh # see below
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
```
|
||||
|
||||
`blanton_ber.sh` and `nfc_polling.sh` are invoked by the macros through `./` or `~/`, so they need the execute bit along with `bmc_monitor.sh` and `usb_target.sh` — neither git nor a Windows/USB copy carries it reliably. `blantons_nfc_validate.py` does **not** need it: `nfc_polling.sh` calls it through `python3` precisely so one more `chmod` cannot be forgotten.
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **`nfc_polling.sh start` clears the log.** Script B starts a fresh poll for the soak, which wipes Script A's baseline log — the baseline numbers are already in the master console log by then, but the file is gone.
|
||||
* **NFC log path is `~/Blanton_Script/log/nfc_poll.log`** and it is copied into the job directory by Script C for the USB archive.
|
||||
* **These three tests cannot share the switch.** `blanton_ber.sh`, `blanton_tr518.sh` and `blanton_traffic_linespeed` all take over port loopback and L2 learning. Script C already orders BER after the traffic report.
|
||||
* **PRBS takes the links down** while `blanton_ber.sh` is armed. That is the test working, not a fault.
|
||||
* **`ce0` keeps running until you stop it.** An interrupted run leaves the 100G port saturated with nothing in `show interfaces status` to hint at it.
|
||||
* **Two numbers must stay in step**: Script C's `sleep 30` and `blanton_ber.sh`'s `BER_INTERVAL`.
|
||||
* **`FAN_SPEED` is 100** — the fans run flat out unless you change `config.ttl`.
|
||||
* **Declare the switch population** with `SWB_UNIT0` / `SWB_UNIT1`.
|
||||
* **PRBS on the two 100G uplinks (`port_prbs_monitor.sh`) is still not wired into the macros.**
|
||||
* **The three items listed as unverified in v1.1.0 are still unverified**: the `ce0` ingress mirror, the 120s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop. See [v1.1.0](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/releases/tag/V1.1.0) for the one-command check on each.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
|
||||
**Full changelog:** [V1.1.1...V1.1.2](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.1...V1.1.2)
|
||||
@@ -0,0 +1,59 @@
|
||||
# v1.1.3 — Margin now measures against what this platform actually runs at
|
||||
|
||||
## ✨ New features
|
||||
|
||||
**Per-CONN margin profiles for the switch boards**
|
||||
* `combo_SWB_CONN13_high` / `_low` through `combo_SWB_CONN16_high` / `_low` replace the old `comboA` / `comboB` pair. Each file's per-channel percentages follow the rails on *that* board, so a CONN13 profile is no longer a rough fit for CONN16.
|
||||
* SWB0 and SWB1 share a profile per CONN — the two boards carry identical rails and differ only by I2C bus.
|
||||
* A high pass and a low pass are now the same run with `_high` swapped for `_low`.
|
||||
* **A profile applied to the wrong CONN margins the wrong rails and says nothing.** The percentages are positional, so nothing detects the mismatch. `margin_apply_profile_all.sh` now names the right profile per board instead of one name for all nine.
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**`VNOM` was the spec value, not what the rails actually sit at**
|
||||
* 86 of the 144 channels moved up between +0.8% and +2.5% to the measured median for this platform — `PVDD3_3V_SYNTH_LDO_*` 3.3 → 3.38, `P0V9_AVDD_*` 0.9 → 0.915, `PVDD0_8V_T3` 0.8 → 0.82, and so on.
|
||||
* **This is not a display change.** `VNOM` is the denominator of `margin_status`'s deviation %, *and* the basis `margin_set` derives high / low / OV / UV from. A rail sitting steady at 0.756 V used to read `+0.80%` against a nominal 0.75 and now reads `0.00%`; and asking for `+3%` now lands on a different absolute voltage than it did last week.
|
||||
* **Margin logs from before and after this build cannot be compared directly.** The numbers moved because the reference moved, not because the hardware did.
|
||||
|
||||
**The batch profile script pointed at files that no longer exist**
|
||||
* `margin_apply_profile_all.sh` still named `comboA` for all nine boards. With `comboA.conf` removed, every board would have stopped at `Profile not found` — a nine-line wall of errors on a script that is normally left to run.
|
||||
|
||||
**The channel map CSV was stale**
|
||||
* `docs/LTC2980_channel_map.csv` is generated from `settings/*.conf`, so all 86 changed rails were wrong in it. Regenerated with `tools/gen_channel_map.sh`. It is output, not source — regenerate it, never hand-edit it.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.1.3.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
**After copying to the DUT:**
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh # see below
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
```
|
||||
|
||||
`blanton_ber.sh` and `nfc_polling.sh` are invoked by the macros through `./` or `~/`, so they need the execute bit along with `bmc_monitor.sh` and `usb_target.sh` — neither git nor a Windows/USB copy carries it reliably.
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **Re-baseline your margin expectations.** Any pass/fail limits or golden logs derived from the old `VNOM` values need redoing against this build.
|
||||
* **`margin_save` in any form writes NVM permanently** and now writes margin windows derived from the new reference. Run `margin_status_all.sh` first and never call it during a test.
|
||||
* **SWB profiles are per-CONN.** Applying `combo_SWB_CONN13_high` to a CONN16 board is silently wrong.
|
||||
* **These three tests cannot share the switch**: `blanton_ber.sh`, `blanton_tr518.sh` and `blanton_traffic_linespeed`.
|
||||
* **PRBS takes the links down** while `blanton_ber.sh` is armed.
|
||||
* **`ce0` keeps running until you stop it.**
|
||||
* **Two numbers must stay in step**: Script C's `sleep 30` and `blanton_ber.sh`'s `BER_INTERVAL`.
|
||||
* **`FAN_SPEED` is 100** — the fans run flat out unless you change `config.ttl`.
|
||||
* **`nfc_polling.sh start` clears the log**, so Script B wipes Script A's NFC baseline file (the numbers are already in the console log).
|
||||
* **The NFC tool is written for the customer's tag.** It polls Type A / B / F only and parses Type A strictly; a tag of another technology is never discovered and fails as `no RF interface activation notification received`. Without `--expected-id` it does not check identity, so a different tag of the same type still passes.
|
||||
* **The three items listed as unverified in v1.1.0 are still unverified**: the `ce0` ingress mirror, the 120s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
* [LTC2980_channel_map.csv](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/docs/LTC2980_channel_map.csv) — all 144 margin channels with the new `VNOM`
|
||||
|
||||
**Full changelog:** [V1.1.2...V1.1.3](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.2...V1.1.3)
|
||||
@@ -0,0 +1,61 @@
|
||||
# v1.1.4 — A thermal and safety run that loads the box and watches the rails
|
||||
|
||||
## ✨ New features
|
||||
|
||||
**`4_Blanton_Script_thermal_safety.ttl`**
|
||||
* A **standalone** script — it is not part of the A → B → C chain and is not started by any of them. Run it on its own when the question is thermal or safety rather than functional.
|
||||
* Brings the DUT up the same way Script A does (login, session reset, fan speed, `wait_init`, DUT inventory, BMC, PCIe error clear, `pcie_bus`, PMON, dmesg), then loads it: `mlucas-avx2 -cpu 0:15` in the background and `blanton_tr518.sh start` on the data plane.
|
||||
* Then loops every minute: platform data, **both switch boards' rail power** via `TH6_SWB0/1_power_readback.sh`, and `bgctl list` / `jobs`. That is the point of the script — power per rail under sustained full load, sampled over hours.
|
||||
* **It has no teardown.** When you interrupt it the DUT is still in `port cd lb=mac`, `l2 learn off` and `test mode nr=yes`, and `mlucas-avx2` is still running. Run `blanton_tr518.sh stop` and `kill $(jobs -p)` before anything else uses the box — nothing in `show interfaces status` reveals the leftover state.
|
||||
* **It cannot share a DUT with Script B.** Both take over the `cd` ports.
|
||||
|
||||
**Test flow diagram**
|
||||
* `docs/Blanton_Test_Flow.drawio` draws all four scripts side by side, with the config flags that change each step marked, the one real `goto` in Script B drawn, and the manual handoffs between A → B → C shown as such.
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**The soak loop spent most of its minute reading margin**
|
||||
* Script B's per-round loop is meant to be a quick sample. `margin_status_all.sh` walks nine LTC2980s over I2C and dominated the round. The scan moved to Script C, which takes it once before `show uptime`.
|
||||
* **The trade-off is real and worth knowing**: margin is now only measured at the start (Script A) and the end (Script C). Drift that happens *during* the soak is no longer visible.
|
||||
|
||||
**`hw-test-session finish` ran from inside the session's own shell**
|
||||
* Script C now sends `exit` and waits for `Script done` first, so `finish` runs in the login shell that opened the session.
|
||||
|
||||
**The new script arrived with LF line endings**
|
||||
* Every other `.ttl` in the repo is CRLF, and `.gitattributes` marks `*.ttl` as `-text` — whatever is committed is exactly what Tera Term gets. Converted to CRLF to match.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.1.4.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
**After copying to the DUT:**
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh # see below
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
```
|
||||
|
||||
`blanton_ber.sh`, `nfc_polling.sh`, `blanton_tr518.sh` and the two `TH6_SWB*_power_readback.sh` are invoked through `./` or `~/`, so they need the execute bit along with `bmc_monitor.sh` and `usb_target.sh` — neither git nor a Windows/USB copy carries it reliably.
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **Script 4 leaves the switch loaded and looped back.** Always finish with `blanton_tr518.sh stop`. If the next test starts without it, traffic and BER results are meaningless and nothing warns you.
|
||||
* **Do not run Script 4 and Script B on the same DUT.** Same ports, same L2 settings.
|
||||
* **Margin is no longer sampled during the soak** — only Script A (start) and Script C (end).
|
||||
* **Re-baseline your margin limits if you have not already**: `VNOM` became the measured median in v1.1.3, which moved both the deviation % and the margin window.
|
||||
* **These three cannot share the switch**: `blanton_ber.sh`, `blanton_tr518.sh`, `blanton_traffic_linespeed`.
|
||||
* **PRBS takes the links down** while `blanton_ber.sh` is armed.
|
||||
* **`ce0` keeps circulating until you stop it.**
|
||||
* **Two numbers must stay in step**: Script C's `sleep 30` and `blanton_ber.sh`'s `BER_INTERVAL`.
|
||||
* **`FAN_SPEED` is 100** — relevant here more than anywhere: a thermal run at full fan is not the same test as one at 30%.
|
||||
* **The three items listed as unverified in v1.1.0 are still unverified**: the `ce0` ingress mirror, the 120s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop. The settle matters most for this release — Script 4 depends on `tr 518` still driving traffic minutes after it was started.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [Blanton_Test_Flow.drawio](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/docs/Blanton_Test_Flow.drawio) — the four scripts side by side
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
|
||||
**Full changelog:** [V1.1.3...V1.1.4](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.3...V1.1.4)
|
||||
@@ -0,0 +1,67 @@
|
||||
# v1.1.5 — The stress jobs now last the whole soak
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**USB stress ran for sixty seconds of an overnight soak**
|
||||
* `qfx5252-stress-usb` was started with `--runtime 60`. It finished a minute in and the USB path sat idle for the rest of the night. Nothing failed, nothing said so, and the run looked complete.
|
||||
* SSD stress had the same shape at `--runtime 3600` — one hour of a soak that usually runs far longer.
|
||||
* Both are now `--runtime 86400`, and the BMC DDR memtester lost its loop count (`64M 1` → `64M`) so it runs until it is stopped rather than finishing one pass.
|
||||
* **86400 is 24 hours, not "forever".** A soak longer than a day leaves SSD and USB dead for the remainder. Script B prints `bgctl list` every round (since v1.0.10), so the shorter list is visible there — but nothing raises an alarm.
|
||||
|
||||
## ✨ New features
|
||||
|
||||
**Multiphase VRM margin**
|
||||
* New `blanton_multiphase_margin.sh` drives the multiphase controllers on both switch boards over the native i2c buses — SWB0 on `/dev/i2c-13` and `-15`, SWB1 on `-14` and `-16`. 19 rails per board, 38 in all.
|
||||
* `high3` / `low3` / `comboA` / `comboB` set the voltages and report one line per rail:
|
||||
|
||||
```
|
||||
SWB0_0V9_ANLG0 - 0.930V Configure Done
|
||||
SWB0_0V75_ANLG0 - 0.775V Configure Done
|
||||
...
|
||||
[ OK ] high3: 38 rail(s) configured
|
||||
```
|
||||
* `save` commits them. It has no per-rail mapping, so it reports as one operation: `Multiphase Save All`.
|
||||
* `-u 0` / `-u 1` for a single board; rails belonging to the other board are skipped and counted separately, not failed.
|
||||
* **`save` writes NVM permanently** (PMBus `STORE_USER_ALL`, and `0x17` on the TH6 core rail). A power cycle does not undo it.
|
||||
* **These are not the LTC2980s that `margin.sh` drives.** The two tools reach the same rails from different sides and each assumes it is the only writer. There is no interlock — do not run both.
|
||||
|
||||
**Traffic bursts carry a random pattern**
|
||||
* `blanton_traffic_linespeed` v0.7.0 appends `PatternRandom=yes` to every `tx`, `ce0` included. A fixed pattern can sit on a benign bit sequence for an entire run; a changing one is what makes a weak lane show itself.
|
||||
* `-r no` forces the fixed pattern; `-r ""` leaves the argument off entirely, which is the pre-v0.7.0 wire format if a future SDK rejects it.
|
||||
* Defaults change from `tx 100 length=512` to `tx 200 length=324`.
|
||||
* **Counter totals are not comparable across this build**: 64800 bytes per burst instead of 51200, about 27% more. The PASS/FAIL cross-check compares a pair against each other and is unaffected — only absolute figures moved.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.1.5.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
**After copying to the DUT:**
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh # see below
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
```
|
||||
|
||||
`blanton_ber.sh`, `nfc_polling.sh`, `blanton_tr518.sh`, `blanton_multiphase_margin.sh` and the two `TH6_SWB*_power_readback.sh` are invoked through `./` or `~/`, so they need the execute bit along with `bmc_monitor.sh` and `usb_target.sh` — neither git nor a Windows/USB copy carries it reliably.
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **A soak longer than 24 hours needs the runtimes raised.** `--runtime 86400` is a ceiling; past it, SSD and USB are idle and only a shorter `bgctl list` hints at it.
|
||||
* **`blanton_multiphase_margin.sh save` is permanent.** Read the rails back before committing, and never run it during a test.
|
||||
* **Do not mix `blanton_multiphase_margin.sh` and `margin.sh`** — same rails, two different access paths, no interlock.
|
||||
* **Traffic counters changed scale.** Any absolute thresholds taken from earlier logs need redoing.
|
||||
* **Script 4 (thermal/safety) has no teardown** — finish with `blanton_tr518.sh stop` and `kill $(jobs -p)`.
|
||||
* **These three cannot share the switch**: `blanton_ber.sh`, `blanton_tr518.sh`, `blanton_traffic_linespeed`.
|
||||
* **Margin is only sampled at the start and end of a soak** (since v1.1.4), not during it.
|
||||
* **`FAN_SPEED` is 100** — the fans run flat out unless you change `config.ttl`.
|
||||
* **The three items listed as unverified in v1.1.0 are still unverified**: the `ce0` ingress mirror, the 120s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [Blanton_Test_Flow.drawio](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/docs/Blanton_Test_Flow.drawio) — the four scripts side by side
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
|
||||
**Full changelog:** [V1.1.4...V1.1.5](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.4...V1.1.5)
|
||||
@@ -0,0 +1,74 @@
|
||||
# v1.1.6 — The PDB bricks were never being asked the right question
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**Every PDB reading was `NA`, and the cause was a page number written in the wrong base**
|
||||
* The four ADPM12200 bricks put each measurement on its own PMBus PAGE, and the page has to be written before every read. The bring-up spreadsheet listed those page numbers in decimal but with an `0x` prefix, so four of the five selected the wrong page:
|
||||
|
||||
| Reading | Datasheet PAGE | Should send | Spreadsheet said |
|
||||
|---|---|---|---|
|
||||
| Vin | 9 | `0x09` | `0x00` |
|
||||
| Iin | 10 | `0x0A` | `0x10` |
|
||||
| Vout | 2 | `0x02` | `0x02` ✅ |
|
||||
| Iout | 14 | `0x0E` | `0x14` |
|
||||
| Temp | 18 | `0x12` | `0x18` |
|
||||
|
||||
* Only Vout worked — because 2 reads the same in either base. That is why Iin and Iout answered `0xFFFF` and the temperature answered `0x0000`, and why a Vin scaling had to be invented to make 50 V appear.
|
||||
* `blanton_pwr_data.sh` sends no page at all (its PDB table has `page "-"`), which is the reason it reports the whole PDB section as `NA`.
|
||||
|
||||
## ✨ New features
|
||||
|
||||
**`pwr_brick.sh` — the five power bricks, read properly**
|
||||
* `show` prints Vin / Iin / Vout / Iout / Temp for all five: `SWB0.PU207` (0x62), `SWB0.PU13` (0x63), `SWB1.PU332` (0x60), `SWB1.PU85` (0x61) and `CPB.PU37` (0x26). `-r` adds the raw words.
|
||||
* Conversions come from the datasheet's DIRECT equation, `X = (1/m)(Y × 10⁻ᴿ − b)`, with Table 3's coefficients: voltage `Y × 8 mV`, current `Y × 0.04 A`, temperature `Y × 0.01 °C`.
|
||||
* **Cross-checked, not assumed**: `READ_VOUT` returns `0x05D4` → 1492 × 8 = 11936 mV, which is exactly the figure `show platform voltage` reports for that rail from a completely separate sensor path.
|
||||
* `CPB.PU37` is a different part — no page writes and its own scaling — and is handled separately.
|
||||
* The datasheet is now in the repo (`docs/ADPM12200CMLZxx_DS_*.pdf`) so the pages and coefficients can be checked without hunting for it.
|
||||
|
||||
**Every value is validated before it is printed**
|
||||
* This bus corrupts the **high byte only**. That turns `11.98 V` into `32.00 V` — positive, plausible in magnitude, and invisible to any "reject 0xFFFF" filter. Each value is re-read (up to `PB_TRIES`, default 8) until it is not `0xFFFF`, not `0x0000`, and lands inside a plausibility window.
|
||||
* `0x0000` is rejected as a raw word for the same reason: on the temperature register it decodes to a perfectly believable 0 °C.
|
||||
|
||||
**Complementary margin profiles per board**
|
||||
* `comboA` / `comboB` for CB and each SWB CONN. `comboB` is `comboA` with every direction flipped, so running both covers each rail high and low while its neighbours sit the other way.
|
||||
* NC channels stay at `nominal` in both — there is nothing to margin on an unused rail (CONN14 CH10/11/13, CONN15 CH10).
|
||||
|
||||
**The BMC USB service log is captured again — to a file**
|
||||
* Script C's `journalctl` dump had been commented out, so that service log reached nothing at all. It now runs with `-o short-iso` into `log/bmc_usb_net.log` and is copied into the job directory for the USB archive. The ISO timestamps line up with the other monitor logs, and `rm -f` first keeps the file to one run.
|
||||
* **It is no longer printed to the console**, so the USB copy is the only copy. If that `cp` fails — and nothing checks it — the service log is gone. Check the job directory before packing up.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.1.6.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
**After copying to the DUT:**
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh # see below
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
```
|
||||
|
||||
`blanton_ber.sh`, `nfc_polling.sh`, `blanton_tr518.sh`, `blanton_multiphase_margin.sh`, `pwr_brick.sh` and the two `TH6_SWB*_power_readback.sh` are invoked through `./` or `~/`, so they need the execute bit along with `bmc_monitor.sh` and `usb_target.sh` — neither git nor a Windows/USB copy carries it reliably.
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **`READ_VIN` and `READ_IIN` are not in the datasheet's coefficient table.** They are decoded here with the voltage and current coefficients — consistent with a ~50 V input, but not stated by the datasheet. Anything quoting brick Vin should have that confirmed first. `PB_VIN_M` / `PB_IIN_M` are where to change it.
|
||||
* **The BMC USB service log only exists on the USB stick.** It is not in the master console log any more.
|
||||
* **`NA` has two meanings**: nothing readable, or read but outside its plausibility window. Use `PB_TRIES=1 ./Blanton_Script/pwr_brick.sh show -r` to see the unretried raw words and tell them apart.
|
||||
* **Margin profiles are positional.** `comboA_SWB_CONN13` applied to a CONN16 board margins the wrong rails and nothing detects it.
|
||||
* **`blanton_multiphase_margin.sh save` is permanent**, and it must not be mixed with `margin.sh` — same rails, two access paths, no interlock.
|
||||
* **A soak longer than 24 hours needs the stress runtimes raised** — `--runtime 86400` is a ceiling.
|
||||
* **Script 4 (thermal/safety) has no teardown** — finish with `blanton_tr518.sh stop` and `kill $(jobs -p)`.
|
||||
* **These three cannot share the switch**: `blanton_ber.sh`, `blanton_tr518.sh`, `blanton_traffic_linespeed`.
|
||||
* **`FAN_SPEED` is 100.**
|
||||
* **The three items listed as unverified in v1.1.0 are still unverified**: the `ce0` ingress mirror, the 120s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
* [Blanton_Test_Flow.drawio](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/docs/Blanton_Test_Flow.drawio) — the four scripts side by side
|
||||
|
||||
**Full changelog:** [V1.1.5...V1.1.6](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.5...V1.1.6)
|
||||
@@ -0,0 +1,73 @@
|
||||
# v1.1.7 — A way back from a margin, and a reboot cycle that runs itself
|
||||
|
||||
## ✨ New features
|
||||
|
||||
**`blanton_multiphase_margin.sh normal` — put the rails back without a power cycle**
|
||||
* `normal` returns all 38 multiphase rails to their nominal set point, with the same per-rail reporting as the margin profiles (`SWB0_0V9_ANLG0 - 0.930V Configure Done`). `-u 0|1|all` as usual.
|
||||
* Until now the only way out of a margin was to power-cycle the DUT. That mattered more than it sounds: `save` run while the board was still margined would have written the offsets into NVM, where a power cycle does not help either.
|
||||
* The commands it sends are in `tools/Multiphase_Normal.txt` for anyone driving the bench by hand.
|
||||
|
||||
> ⚠️ `TH6_CORE` is 0.8 V nominal but settles near **0.8591 V** once the load line is active. Reading back 0.859 after `normal` is the load line doing its job, not a failed write.
|
||||
|
||||
**`5_Blanton_Script_Reboot_Cycle.ttl` — an unattended reboot-cycle run**
|
||||
* A standalone macro, like Script 4: it does **not** chain to A → B → C and does not use `hw-test-session`. Every cycle is a fresh boot, so there is nothing to carry over and nothing to tear down.
|
||||
* Each round: login → `sudo -i` → `date -s` → fan speed → `wait_init` → **Check Pt1 … Pt13** → `show uptime` → `reboot` → wait for the next boot. The cycle number is printed in the banner of every round.
|
||||
|
||||
| | | | |
|
||||
|---|---|---|---|
|
||||
| **Pt1** DUT info | **Pt2** BMC info + tools | **Pt3** mgmt ping | **Pt4** NFC poll |
|
||||
| **Pt5** SSD stress | **Pt6** USB stress | **Pt7** BMC USB net | **Pt8** port status + 15 s traffic |
|
||||
| **Pt9** BER sweep | **Pt10** NVMe errors | **Pt11** platform data | **Pt12** dmesg i2c |
|
||||
| **Pt13** PCIe error counters | | | |
|
||||
|
||||
* The USB step takes its device node from `usb_target.sh`, not a hard-coded `/dev/sda1`.
|
||||
|
||||
**The SSD and USB stress durations are declared in `config.ttl`**
|
||||
* `SSD_RUNTIME` / `SSD_COUNT` and `USB_RUNTIME` / `USB_COUNT` replace the values that were hard-coded in Script B, so a site changes them in one place. `COUNT` is passed straight through as `--passes`.
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**Script B left the global `timeout` at 15 s for the rest of the cdc_ncm section**
|
||||
* The NCM probe sets `timeout = 15` and restored it only at `:skip_ping` — which the *success* path reaches several `wait`s later. Until then every `wait` gave up after 15 s instead of blocking, and a `wait` that returns without eating the prompt puts the whole macro a beat ahead of the DUT. It is now restored on the success path too.
|
||||
|
||||
**`goto skip_ping` in the reboot-cycle macro had no label to jump to**
|
||||
* The probe was copied out of Script B without its `:skip_ping` label. Tera Term does not check labels when it loads a macro — it raises the error only when it actually jumps, which here means only when the NCM interface is missing. The failure mode was an error dialog stopping the whole cycle, on the one run where something was already wrong. The label is there now, and the `timeout` is restored **before** the branch so one line covers both paths.
|
||||
|
||||
**Two check points both numbered 12**
|
||||
* `Dmesg_i2c` and `PCIE Error Counters` both announced themselves as `Check Pt12`. The second is now `Pt13`; Pt1 … Pt13 are unique.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.1.7.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
**After copying to the DUT:**
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh # see below
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
```
|
||||
|
||||
`blanton_ber.sh`, `nfc_polling.sh`, `blanton_tr518.sh`, `blanton_multiphase_margin.sh`, `pwr_brick.sh` and the two `TH6_SWB*_power_readback.sh` are invoked through `./` or `~/`, so they need the execute bit along with `bmc_monitor.sh` and `usb_target.sh` — neither git nor a Windows/USB copy carries it reliably.
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **`--runtime` is the job's overall limit, not a per-pass one.** `qfx5252-stress-*` stops after `RUNTIME` seconds whatever `--passes` says, so `SSD_RUNTIME=600` is a **10 minute** stress, not 600 × `SSD_COUNT`. For a 24 hour soak set `RUNTIME` to `86400`. The shipped defaults are 600.
|
||||
* **Script 5 has not been run on hardware yet.** Two things to confirm on the bench: that `wait "Booting in blind mode"` really appears in this build's boot output — it has no `timeout` guard, so a changed string waits forever — and that re-running `bmc-first-enroll` every cycle is safe.
|
||||
* **Script 5 has no exit condition.** `while 1` with a `reboot` at the end of each round; stop it by closing the Tera Term macro.
|
||||
* **`blanton_multiphase_margin.sh save` is permanent**, and must not be mixed with `margin.sh` — same rails, two access paths, no interlock. Never run it while the board is margined.
|
||||
* **`READ_VIN` and `READ_IIN` are still not in the ADPM12200 coefficient table** — `pwr_brick.sh` decodes them with the voltage and current coefficients. Confirm before quoting brick Vin.
|
||||
* **The BMC USB service log only exists on the USB stick.**
|
||||
* **Script 4 (thermal/safety) has no teardown** — finish with `blanton_tr518.sh stop` and `kill $(jobs -p)`.
|
||||
* **These three cannot share the switch**: `blanton_ber.sh`, `blanton_tr518.sh`, `blanton_traffic_linespeed`.
|
||||
* **`FAN_SPEED` is 100.**
|
||||
* **Still unverified from v1.1.0**: the `ce0` ingress mirror, the 120 s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
* [Blanton_Test_Flow.drawio](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/docs/Blanton_Test_Flow.drawio) — the scripts side by side
|
||||
|
||||
**Full changelog:** [V1.1.6...V1.1.7](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.6...V1.1.7)
|
||||
@@ -0,0 +1,71 @@
|
||||
# v1.1.8 — The CPU stress no longer dies with your terminal
|
||||
|
||||
## ✨ New features
|
||||
|
||||
**`mlucas` now runs as a systemd unit, so it survives a lost session**
|
||||
* The AMD CPU load is started as `systemd-run --unit=mlucas-amm --property=Type=exec --property=Restart=always --property=RestartSec=2`, instead of being backgrounded with `&` in the login shell. Script B and the thermal/safety macro (Script 4) both use it.
|
||||
* As a shell job it belonged to that one terminal: close Tera Term, drop the console, reconnect on a different session, and the load was gone — while `jobs` from the new session showed nothing to tell you. A multi-day soak could spend most of its length with an idle CPU and produce thermal numbers that looked fine because nothing was loading the part.
|
||||
* `Restart=always` brings it back if it exits on its own, and the log is appended (`>>`) inside the unit while being truncated (`>`) once before the unit starts, so a restart adds to the run rather than erasing it.
|
||||
* Script B now prints `systemctl is-active mlucas-amm` beside `jobs`, both in the one-shot check and in every pass of the monitor loop. One word — `active` — tells you the CPU is still loaded.
|
||||
|
||||
> The old `&` line is kept commented out directly above the new one, to fall back to if `systemd-run` is not available on a build.
|
||||
|
||||
**Script C stops the unit and brings its log home**
|
||||
* `systemctl stop mlucas-amm` was added next to the existing `kill $(jobs -p)`, and `mlucas_amm_log` is copied into `/host/hw-eval/jobs/` with the other stress logs.
|
||||
* `kill $(jobs -p)` cannot reach a systemd unit, so without this the load would have run straight through the post-test snapshot and into the next test — every temperature and power reading taken at full load, with nothing in `show interfaces status` to reveal it.
|
||||
|
||||
**`EN_timestamp` — turn the per-line log timestamp on or off from `config.ttl`**
|
||||
* Script A's `logopen` takes its 5th argument from the new flag: `logopen filename 0 1 1 EN_timestamp`. The argument order (`<file> <binary> <append> <PlainText> <timestamp>`) is now spelled out above the call.
|
||||
|
||||
**`BMC_USB_RUNTIME` — the BMC USB ping duration is a knob, not a constant**
|
||||
* It was hard-coded to `-w 14400` (4 hours), which no longer matched the soak lengths the SSD and USB knobs were being set to. The shipped default is `172800` (2 days).
|
||||
|
||||
**The shipped stress defaults are now one hour**
|
||||
* `SSD_RUNTIME` and `USB_RUNTIME` go from 600 to `3600`. v1.1.7 shipped a 10 minute stress by default.
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**`publish.sh` produced a different bundle depending on whose machine it ran on**
|
||||
* `rsync` copied whatever sat in `src/Script_ABC_Blanton/`, so a developer with the `hammer/` mlucas binaries in their working tree shipped a ~100 MB zip while a fresh clone shipped ~200 KB. `hammer/` is now excluded from the bundle and ignored by git.
|
||||
* `publish.sh -h` also printed the first lines of code along with the usage text, and would have truncated the usage block as the header grew. It now reads the header up to the first line of code.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.1.8.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
**After copying to the DUT:**
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh # see below
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
ls ~/hammer/tools/amd/mlucas-avx2 # must already be there - see below
|
||||
```
|
||||
|
||||
`blanton_ber.sh`, `nfc_polling.sh`, `blanton_tr518.sh`, `blanton_multiphase_margin.sh`, `pwr_brick.sh` and the two `TH6_SWB*_power_readback.sh` are invoked through `./` or `~/`, so they need the execute bit along with `bmc_monitor.sh` and `usb_target.sh` — neither git nor a Windows/USB copy carries it reliably.
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **Replace `config.ttl` along with the macros.** `EN_timestamp` and `BMC_USB_RUNTIME` are new, and Tera Term aborts the macro on an undefined variable rather than treating it as 0 — keeping an old `config.ttl` stops Script A at the `logopen` line.
|
||||
* **`hammer/` is not in the bundle.** The ~99 MB of mlucas binaries comes with the DUT image, not from this repo. If `~/hammer/tools/amd/mlucas-avx2` is missing, Script B does not stop — it starts a unit that fails and is restarted every 2 seconds. Check for the file before you start.
|
||||
* **The timestamp format is not in the macro.** `EN_timestamp` only decides whether there is one; the format lives in Tera Term's Setup → Additional settings → Log, stored in that PC's `TERATERM.INI`. Two benches running the same macro can produce differently stamped logs.
|
||||
* **The three stress durations are deliberately different**: SSD and USB at 1 hour, the BMC USB ping at 2 days. Set each to match the soak you are actually running.
|
||||
* **`--runtime` is the job's overall limit, not a per-pass one.** `qfx5252-stress-*` stops after `RUNTIME` seconds whatever `--passes` says. For a 24 hour soak set `RUNTIME` to `86400`.
|
||||
* **`mlucas-amm` has not been run on hardware yet.** The unit resolves `~` through bash's fallback to the passwd entry, because systemd does not set `HOME` for a system service without `User=`. It should land on `/root/hammer`, the same path the interactive shell uses — confirm it on the bench, or change both paths to an absolute `/root/hammer/...`.
|
||||
* **Script 4 uses the same unit but has no teardown.** The thermal/safety macro now starts `mlucas-amm` the same way Script B does, and it still ends at `while 1` — so stopping it means `blanton_tr518.sh stop` **and** `systemctl stop mlucas-amm`. Closing Tera Term does not stop the CPU load any more.
|
||||
* **Script 5 (reboot cycle) is still unverified on hardware**, still has no exit condition, and `wait "Booting in blind mode"` still has no `timeout` guard.
|
||||
* **`blanton_multiphase_margin.sh save` is permanent**, and must not be mixed with `margin.sh` — same rails, two access paths, no interlock.
|
||||
* **`READ_VIN` and `READ_IIN` are still not in the ADPM12200 coefficient table.**
|
||||
* **The BMC USB service log only exists on the USB stick.**
|
||||
* **These three cannot share the switch**: `blanton_ber.sh`, `blanton_tr518.sh`, `blanton_traffic_linespeed`.
|
||||
* **`FAN_SPEED` is 100.**
|
||||
* **Still unverified from v1.1.0**: the `ce0` ingress mirror, the 120 s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
* [Blanton_Test_Flow.drawio](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/docs/Blanton_Test_Flow.drawio) — the scripts side by side
|
||||
|
||||
**Full changelog:** [V1.1.7...V1.1.8](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.7...V1.1.8)
|
||||
@@ -0,0 +1,76 @@
|
||||
# v1.2.0 — SerDes DSC capture, and the macro now waits on the DUT
|
||||
|
||||
## ✨ New features
|
||||
|
||||
**Full-machine SerDes DSC capture, before and after the soak**
|
||||
* `bcm_dsc_scan.sh` runs `phydiag <port> dsc` through the Broadcom diag shell across the whole port list — one 100G port plus the 200G ranges, about 445 per unit, on both units — and writes the raw log under `Blanton_Script/log/`, then copies it to `/host/hw-eval/jobs/`.
|
||||
* Script A takes a baseline and Script C takes a closing dump, so the pair brackets the stress run and the two are directly comparable.
|
||||
* `-u 0` scans one unit, `-f <name>` names the log (`%u` → `u0`/`u1`, `%t` → timestamp), `-F` overwrites, `-n` dry runs, `-C` skips the copy. A name without `%u` gets `_u0` / `_u1` inserted automatically, so unit 1 can never overwrite unit 0.
|
||||
* Every run ends with `### DSC_SCAN_DONE rc=<n>`. `rc=0` means every port returned a complete dump.
|
||||
* `phydiag ... dsc` is read-only — it does not change any SerDes setting.
|
||||
|
||||
**`bcm_dsc_parse.sh` turns a raw DSC log into two CSVs**
|
||||
* `<prefix>_lane.csv` — one row per lane: TXEQ, RXFFE, DFE, EYE, SNR and the rest.
|
||||
* `<prefix>_pm.csv` — one row per `pm_id`: temperature, PLL, lane count, SNR/EYE statistics.
|
||||
* POSIX `sh` + `awk`, no Python, so it runs on the DUT as happily as on a laptop. Lane rows are read by the order of their bracket groups rather than by fixed column positions, so the SDK re-spacing its output does not break parsing; a row that does not yield 9 groups is reported as `UNPARSED` on stderr instead of being parsed wrongly.
|
||||
|
||||
**`EN_TX_FIR` in `config.ttl` — the DSC scan is off by default**
|
||||
* A full scan is about 10 minutes and both Script A and Script C do one, so the shipped default (`0`) keeps ~20 minutes out of a routine run. Set it to `1` when the SerDes data is what you are after.
|
||||
|
||||
**The macro now waits on the DUT instead of on itself**
|
||||
* Every `pause N` in Scripts A, B and C became `sendln "sleep N"` followed by `wait prompt_sonic_root`.
|
||||
* `pause` stopped the macro for N seconds without touching the DUT — the shell sat idle and the macro was guessing how long the previous command would take. On a loaded DUT the guess ran short and the next command went out before the previous one had finished, putting the whole run a beat ahead of the switch. Now the wait happens on the DUT and the macro resumes when the prompt actually comes back.
|
||||
* It also means the wait appears in the console log with a timestamp, so a round that ran long is visible afterwards.
|
||||
* Timings changed with it: the management-ping sample in Script A is 15 s (was 30), the settle after each traffic `clear` is 5 s (was 15). The traffic run itself stays 15 s and Script B's monitor loop stays 60 s.
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**The DSC scan only ever scanned one port — and reported success**
|
||||
* The scan loop read its port list on stdin, and `bcmcmd` reads stdin too, so the first call swallowed the rest of the file and the loop ended after a single port.
|
||||
* Nothing looked wrong. The log held one port marker and one dsc block, the marker-to-dump comparison passed because both numbers shrank together, the exit code was 0, and a 445-port scan simply finished in seconds.
|
||||
* The loop now reads on file descriptor 3 and `bcmcmd` is given `< /dev/null`, and there is a new check that the number of iterations matches the number of ports in the list — a check that cannot be fooled by the loop ending early.
|
||||
|
||||
**Dead call sites removed from Scripts A, B and C**
|
||||
* The commented-out 100G PRBS calls, a duplicated commented 100G port-status block in Script A, and the stale `bmc_monitor_ddr.sh` block in Script C have been deleted. They had been dead since bring-up.
|
||||
* `port_prbs_monitor.sh` still ships and still runs by hand — but re-enabling it means writing the calls again, not un-commenting them.
|
||||
|
||||
## 🔧 Changes
|
||||
|
||||
* **Script C no longer prints the BMC poll log or the mlucas log to the console.** Both files are still copied to `/host/hw-eval/jobs/` and out to the USB stick with everything else; only the master log got shorter.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.2.0.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
**After copying to the DUT:**
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh # bcm_dsc_scan.sh is invoked as ./Blanton_Script/... and needs it
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
ls ~/hammer/tools/amd/mlucas-avx2 # must already be there
|
||||
```
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **Replace `config.ttl` along with the macros.** `EN_TX_FIR` is new, and Tera Term aborts on an undefined variable rather than treating it as 0.
|
||||
* **`bcm_dsc_scan.sh` needs the execute bit.** Script A and Script C invoke it as `./Blanton_Script/bcm_dsc_scan.sh`. Without `chmod +x` it fails with `Permission denied`, the macro walks straight past it, and Script C's four `cp` lines then each report a missing file.
|
||||
* **The DSC scan shares the ports with `blanton_ber.sh`, `blanton_traffic_linespeed` and `blanton_tr518.sh`** — do not run it alongside any of them.
|
||||
* **Script 4 and Script 5 still use `pause`.** Only A, B and C were converted.
|
||||
* **`--runtime` is the job's overall limit, not a per-pass one.** `--passes` does not extend it; for a 24 hour soak set `RUNTIME` to `86400`.
|
||||
* **Script 4 has no teardown**: finish it with `blanton_tr518.sh stop` **and** `systemctl stop mlucas-amm`.
|
||||
* **Script 5 (reboot cycle) is still unverified on hardware**, has no exit condition, and its `wait "Booting in blind mode"` has no `timeout` guard.
|
||||
* **`blanton_multiphase_margin.sh save` is permanent**, and must not be mixed with `margin.sh`.
|
||||
* **`READ_VIN` and `READ_IIN` are still not in the ADPM12200 coefficient table.**
|
||||
* **The BMC USB service log only exists on the USB stick.**
|
||||
* **`FAN_SPEED` is 100.**
|
||||
* **Still unverified from v1.1.0**: the `ce0` ingress mirror, the 120 s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop.
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
* [Blanton_Test_Flow.drawio](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/docs/Blanton_Test_Flow.drawio) — the scripts side by side
|
||||
|
||||
**Full changelog:** [V1.1.8...V1.2.0](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.1.8...V1.2.0)
|
||||
@@ -0,0 +1,49 @@
|
||||
# v1.2.1 — A BER baseline, so the SerDes numbers have something to be compared against
|
||||
|
||||
## ✨ New features
|
||||
|
||||
**Script A now takes a SerDes BER sweep before the first traffic run**
|
||||
* `blanton_ber.sh init → start → sleep 30 → report → stop → clear`, branched on `SWB_UNIT0` / `SWB_UNIT1` exactly like the traffic block beside it.
|
||||
* Script C already ran the closing sweep after its traffic report. With this one at the front, the pair brackets the soak — the same shape as the DSC scans added in v1.2.0, and the same reason: a BER figure on its own says very little, a *change* in it says a lot.
|
||||
* The `sleep 30` matches `blanton_ber.sh`'s `BER_INTERVAL`. Reporting before one full interval has accumulated reads a window that has not finished, and nothing warns you about it.
|
||||
|
||||
## 🐛 Bug fixes
|
||||
|
||||
**The new block's comment described the wrong position**
|
||||
* It was copied out of Script C, which runs BER *after* the traffic report, and the comment came with it and still said "after". In Script A the block runs *before* traffic. The comment now says what the code does and why the ordering is what it is.
|
||||
|
||||
## ⚠️ Before you run
|
||||
|
||||
* **Watch Script A's first traffic report on the first run.** PRBS holds the lanes out of normal operation and `blanton_ber.sh clear` is what releases them — and in Script A nothing settles between that `clear` and the `blanton_traffic_linespeed ps` / `init` that follows. Script C does not have this ordering, so the two reports are a built-in comparison: **if Script A shows NA or FAIL pairs that Script C does not, the lanes had not come back yet**, and a `sleep` after `clear` is the fix. This has not been run on hardware yet.
|
||||
* **`sleep 30` and `BER_INTERVAL` now live in three places** — Script A, Script C, and `blanton_ber.sh` itself. Changing one without the others silently reports a partial interval.
|
||||
* **BER, `blanton_traffic_linespeed` and `blanton_tr518.sh` cannot overlap.** They all take over the same ports. Script A now touches those ports twice before the soak even starts.
|
||||
* **`EN_TX_FIR` is still 0 by default**, so the DSC scans do not run unless you turn them on; a full scan is ~10 min in each of Script A and Script C.
|
||||
* **Replace `config.ttl` along with the macros.** Tera Term aborts the macro on an undefined variable rather than treating it as 0.
|
||||
* **`bcm_dsc_scan.sh` needs the execute bit**: `chmod +x ~/Blanton_Script/*.sh` after copying.
|
||||
* **`--runtime` is the job's overall limit, not a per-pass one.** `--passes` does not extend it.
|
||||
* **Script 4 has no teardown**: finish it with `blanton_tr518.sh stop` **and** `systemctl stop mlucas-amm`.
|
||||
* **Script 5 (reboot cycle) has no exit condition.** A 199-cycle / 60-hour run has now been analysed: PCIe AER stayed at 0, all 218 traffic pairs and all 864 lanes passed every cycle, and the BMC never reset. Two things it did surface — `bmc-first-enroll` does not exist on that BMC build, and NFC returned FAIL on every cycle.
|
||||
* **`blanton_multiphase_margin.sh save` is permanent**, and must not be mixed with `margin.sh`.
|
||||
* **`READ_VIN` and `READ_IIN` are still not in the ADPM12200 coefficient table.**
|
||||
* **The BMC USB service log only exists on the USB stick.**
|
||||
* **`FAN_SPEED` is 100.**
|
||||
* **Still unverified from v1.1.0**: the `ce0` ingress mirror, the 120 s settle in `blanton_tr518.sh`, and `test mode nr=no` on stop.
|
||||
|
||||
## 📦 Downloads
|
||||
|
||||
| File | Contents |
|
||||
|---|---|
|
||||
| `Script_ABC_Blanton_V1.2.1.zip` | The full Tera Term working directory, including `Blanton_Script/` to copy onto the DUT |
|
||||
|
||||
```bash
|
||||
chmod +x ~/Blanton_Script/*.sh
|
||||
grep -rlU $'\r' ~/Blanton_Script # expect no output
|
||||
ls ~/hammer/tools/amd/mlucas-avx2 # must already be there
|
||||
```
|
||||
|
||||
## 🔗 Links
|
||||
|
||||
* [ARCHITECTURE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/ARCHITECTURE.md) — test flow, data models, constraints
|
||||
* [CLAUDE.md](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/src/branch/main/CLAUDE.md) — commands and the bench gotchas
|
||||
|
||||
**Full changelog:** [V1.2.0...V1.2.1](https://etgit.et-wen.com/etwen/Blanton_TTL_Script/compare/V1.2.0...V1.2.1)
|
||||
@@ -0,0 +1,120 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# publish.sh -- package src/Script_ABC_Blanton for delivery
|
||||
# =============================================================================
|
||||
# Version History:
|
||||
# V1.0.0 2026-08-21 Initial. Copies src/Script_ABC_Blanton to
|
||||
# publish/Script_ABC_Blanton_<Version>, taking <Version>
|
||||
# from the "; Version : Vx.y.z" header of
|
||||
# 1_Blanton_Script_A.ttl.
|
||||
# V1.0.1 2026-09-06 Exclude hammer/ (the mlucas binaries) from the bundle,
|
||||
# so the output no longer depends on whether the developer
|
||||
# has them in their working tree.
|
||||
# =============================================================================
|
||||
#
|
||||
# The version is READ FROM Script A rather than passed in, so the folder name
|
||||
# can never disagree with the header the tester sees when they open the macro.
|
||||
# Bump Script A's header first, then run this.
|
||||
#
|
||||
# Usage:
|
||||
# ./publish/publish.sh # publish at Script A's version
|
||||
# ./publish/publish.sh -v V1.0.4 # override the version
|
||||
# ./publish/publish.sh -f # overwrite an existing output folder
|
||||
# ./publish/publish.sh -z # also produce a .zip next to it
|
||||
# ./publish/publish.sh -n # dry run: print what would happen
|
||||
# =============================================================================
|
||||
set -u
|
||||
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd -- "${SCRIPT_DIR}/.." && pwd)"
|
||||
SRC_DIR="${REPO_ROOT}/src/Script_ABC_Blanton"
|
||||
OUT_ROOT="${SCRIPT_DIR}"
|
||||
NAME="Script_ABC_Blanton"
|
||||
VER=""; FORCE=0; ZIP=0; DRY=0
|
||||
|
||||
info() { printf '[\033[34mINFO\033[0m] %s\n' "$*"; }
|
||||
ok() { printf '[\033[32m OK \033[0m] %s\n' "$*"; }
|
||||
die() { printf '[\033[31mERR \033[0m] %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
# Print the header block above, up to (but not including) the first line of
|
||||
# code, so adding a Version History entry never truncates the usage text.
|
||||
usage() { sed -n '2,/^set -u/p' "${BASH_SOURCE[0]}" | sed '$d' | sed 's/^# \{0,1\}//'; exit 0; }
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-v|--version) VER="${2:-}"; shift 2 ;;
|
||||
-f|--force) FORCE=1; shift ;;
|
||||
-z|--zip) ZIP=1; shift ;;
|
||||
-n|--dry-run) DRY=1; shift ;;
|
||||
-h|--help) usage ;;
|
||||
*) die "unknown option '$1' (try -h)" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ -d "${SRC_DIR}" ] || die "source not found: ${SRC_DIR}"
|
||||
|
||||
# --- version from Script A's header ------------------------------------------
|
||||
# The .ttl files are CRLF, so strip the carriage return or it lands in the
|
||||
# folder name and produces a directory no one can cd into.
|
||||
if [ -z "${VER}" ]; then
|
||||
A_TTL="${SRC_DIR}/1_Blanton_Script_A.ttl"
|
||||
[ -f "${A_TTL}" ] || die "cannot read version: ${A_TTL} missing"
|
||||
VER=$(grep -m1 -E '^;[[:space:]]*Version[[:space:]]*:' "${A_TTL}" \
|
||||
| tr -d '\r' | sed -E 's/.*:[[:space:]]*//; s/[[:space:]]+$//')
|
||||
[ -n "${VER}" ] || die "no '; Version : Vx.y.z' header in $(basename "${A_TTL}")"
|
||||
info "version from $(basename "${A_TTL}") : ${VER}"
|
||||
else
|
||||
info "version (overridden) : ${VER}"
|
||||
fi
|
||||
|
||||
case "${VER}" in
|
||||
V[0-9]*) ;;
|
||||
*) die "version '${VER}' does not look like Vx.y.z" ;;
|
||||
esac
|
||||
|
||||
DEST="${OUT_ROOT}/${NAME}_${VER}"
|
||||
info "source : ${SRC_DIR#${REPO_ROOT}/}"
|
||||
info "destination : ${DEST#${REPO_ROOT}/}"
|
||||
|
||||
if [ -e "${DEST}" ]; then
|
||||
[ "${FORCE}" = "1" ] || die "${DEST##*/} already exists (use -f to overwrite)"
|
||||
[ "${DRY}" = "1" ] || rm -rf -- "${DEST}"
|
||||
info "existing folder removed (-f)"
|
||||
fi
|
||||
|
||||
if [ "${DRY}" = "1" ]; then
|
||||
info "dry run: nothing copied"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- copy ---------------------------------------------------------------------
|
||||
# Captured console logs are per-run and often carry DUT serials, so they are
|
||||
# never shipped; the empty logs/ directory itself is kept because Script A's
|
||||
# logopen writes into it.
|
||||
#
|
||||
# hammer/ is excluded as well: it is ~99 MB of mlucas ELF binaries that the DUT
|
||||
# image already carries, and it is gitignored. Without this exclude the bundle
|
||||
# would depend on whether the developer happened to have the binaries sitting in
|
||||
# src/ - 100 MB from one machine, 200 KB from a fresh clone.
|
||||
mkdir -p -- "${DEST}" || die "cannot create ${DEST}"
|
||||
if command -v rsync >/dev/null 2>&1; then
|
||||
rsync -a --exclude='*.log' --exclude='hammer/' "${SRC_DIR}/" "${DEST}/" \
|
||||
|| die "rsync failed"
|
||||
else
|
||||
cp -a -- "${SRC_DIR}/." "${DEST}/" || die "cp failed"
|
||||
find "${DEST}" -type f -name '*.log' -delete
|
||||
rm -rf -- "${DEST}/hammer"
|
||||
fi
|
||||
|
||||
# Tera Term's logopen target, in case the source tree never had one
|
||||
mkdir -p -- "${DEST}/logs"
|
||||
|
||||
n_files=$(find "${DEST}" -type f | wc -l)
|
||||
ok "${n_files} files -> ${DEST##*/}"
|
||||
|
||||
if [ "${ZIP}" = "1" ]; then
|
||||
command -v zip >/dev/null 2>&1 || die "zip not installed"
|
||||
( cd -- "${OUT_ROOT}" && rm -f -- "${NAME}_${VER}.zip" \
|
||||
&& zip -qr "${NAME}_${VER}.zip" "${NAME}_${VER}" ) || die "zip failed"
|
||||
ok "$(du -h "${OUT_ROOT}/${NAME}_${VER}.zip" | cut -f1) -> ${NAME}_${VER}.zip"
|
||||
fi
|
||||
@@ -1,7 +1,7 @@
|
||||
; =============================================================================
|
||||
; Script A for Blanton
|
||||
; Version : V1.0.2
|
||||
; Date : 2026-08-17
|
||||
; Version : V1.2.1
|
||||
; Date : 2026-09-08
|
||||
; Author : ETWen
|
||||
; =============================================================================
|
||||
; Version History:
|
||||
@@ -14,7 +14,554 @@
|
||||
; ScriptB Remove stress_hhmd, stress_pcie
|
||||
; Blanton_Script Add blanton_traffic_linespeed.sh
|
||||
; ScriptB/C Add Traffic Test
|
||||
;
|
||||
; V1.0.3 2026-08-21 utils/wait_init.ttl Created
|
||||
; ScriptA Add Wait DUT Ready
|
||||
; V1.0.4 2026-08-21 utils/wait_init.ttl Wait on bcmcmd port-up, count (both units > 216)
|
||||
; utils/wait_init.ttl Add WT_UNIT0/WT_UNIT1, skip absent units
|
||||
; ScriptA Add EEPROM info (hpe-eeprom-tlv --bus 4 --addr 0x50)
|
||||
; ScriptA Remove empty Check History block
|
||||
; ScriptA/B Disable lldp + config save before traffic (silent MAC)
|
||||
; ScriptB Add sfputil lpmode off Ethernet513/514
|
||||
; V1.0.5 2026-08-21 config.ttl Add SWB_UNIT0/SWB_UNIT1
|
||||
; utils/wait_init.ttl Follow config.ttl SWB_UNIT0/SWB_UNIT1
|
||||
; ScriptA/B/C Traffic follows SWB_UNIT: -u 0 / -u 1 / skip
|
||||
; V1.0.6 2026-08-24 utils/show_dmesg.ttl Edited dmesg grep i2c & clear event
|
||||
; ScriptA HW Test Session
|
||||
; ScriptC HW Test Session Finish
|
||||
; ScriptA bmc-first-enroll, bmc version/status
|
||||
; ScriptB Stress test DDR, SSD, USB, BMC DDR, BMC USB Stress test
|
||||
; ScriptC BMC USB Stress test result
|
||||
; ScriptA DUT Info
|
||||
; ScriptAC 10G/1G MGMT ping
|
||||
; ScriptA Edited 100G Port Status
|
||||
; ScriptA, utils/setup_pmon.ttl Add TPM
|
||||
; ScriptAC NVME Error Info
|
||||
; ScriptAC Add PCIe Summary
|
||||
; V1.0.7 2026-08-25 config.ttl Add FAN_SPEED
|
||||
; ScriptA Add Fan Ctrl (max31790 rebind + fan-speed-control.sh)
|
||||
; ScriptA Clear /host/hw-eval/current/jobs before the run
|
||||
; ScriptC Copy stress jobs log to USB, timestamped
|
||||
; utils/wait_init.ttl WT_INTERVAL 10 -> 60, fix WT_MIN comments
|
||||
; ScriptC Disable BMC USB journalctl dump
|
||||
; V1.0.8 2026-08-25 Blanton_Script/bmc_monitor.sh Add BMC I2C write/read-back pattern test
|
||||
; ScriptB Re-enable bmc_monitor.sh start
|
||||
; ScriptC Re-enable bmc_monitor.sh stop + cat bmc_poll.log
|
||||
; ScriptC Copy bmc_poll.log + mgmt_ping.log into jobs/ before the USB archive
|
||||
; Blanton_Script/usb_target.sh Created - auto-detect USB device node / mount point
|
||||
; ScriptB USB stress uses the detected node, not a hard-coded /dev/sda1
|
||||
; ScriptB DDR memtester runs continuously (drop the 100-pass limit)
|
||||
; ScriptC Move bgctl reset --yes after the USB archive
|
||||
; Blanton_Script/mgmt_ping_monitor.sh V3.0.0 - both NICs ping simultaneously, accumulating
|
||||
; + ARP warm-up so a stale neighbour entry is not counted as loss
|
||||
; + stop renders last-N per NIC, stats, and both ip -s link show
|
||||
; .gitignore Ignore monitor *.raw / *.pid / *.state
|
||||
; ScriptA MGMT ping baseline 45s -> 30s, clear the log afterwards
|
||||
; ScriptB Show mgmt_ping status after start
|
||||
; ScriptC Show mgmt_ping status before stop, cat the report after
|
||||
; V1.0.9 2026-08-26 Blanton_Script/port_prbs_monitor.sh Add 100G Port PRBS test
|
||||
; start [both|a|b] - single port isolates a port fault from
|
||||
; the DUT not coping with two PRBS streams at once
|
||||
; !! TTL calls are commented out in A/B/C - still under bring-up
|
||||
; ScriptA/B/C Job log path /host/hw-eval/current/jobs -> /host/hw-eval/jobs
|
||||
; ScriptC Mount the USB (usb_target.sh) before copying the job logs
|
||||
; ScriptC Reorder results: stress logs, then MGMT ping, then 100G status
|
||||
; V1.0.10 2026-08-27 ScriptB Monitor loop lists the background jobs every round
|
||||
; + bgctl list - platform jobs
|
||||
; + jobs - shell jobs of the login shell
|
||||
; + pause 60 - the loop used to run with no pause at all
|
||||
; docs/LTC2980_channel_map.csv Channel / net / Vnom map built from settings/*.conf
|
||||
; tools/gen_channel_map.sh Regenerates that CSV - the CSV is output, not source
|
||||
; tools/100G_PRBS.txt Bench command references, kept for hand-run debug
|
||||
; tools/TR518.txt TR518 = built-in packet test (swutil / bcmcmd tr 518)
|
||||
; tools/fan_ctrl.txt MAX31790 rebind + fan-speed-control.sh
|
||||
; V1.0.11 2026-08-28 LTC2980_Margin_Script/margin.sh v2.7.0 - margin_save fixes + two new subcommands
|
||||
; STORE_USER_ALL (0x15) is now a PMBus send-byte, not
|
||||
; 0x15 followed by a dummy 0x00 data byte. The LTC2977
|
||||
; tolerated the old form, but it was the wrong protocol
|
||||
; i2c: i2cset .. 0x15 c swb: cb_pmbus_write <ch> <addr> 0x15
|
||||
; + margin_save all - every board in settings/ (9 boards,
|
||||
; 18 chips), then re-init the one loaded beforehand
|
||||
; + margin_save blanton - Blanton SONiC shortcut: all 18
|
||||
; LTC2977 straight over the native i2c buses - no
|
||||
; margin_init, no FPGA channel setup, no pcimem
|
||||
; F3 Ch6->bus 13, Ch7->14, Ch8->15, Ch9->16
|
||||
; board list = MARGIN_BLANTON_STORE at the top of margin.sh
|
||||
; The store result is now checked - a NACK used to still
|
||||
; print "Change Saved"
|
||||
; MARGIN_STORE_SETTLE (0.5s) between stores; nothing in this
|
||||
; tool polls the part's busy bit
|
||||
; LTC2980_Margin_Script/README.md What each margin_save variant sends, and the
|
||||
; FPGA-channel -> i2c-bus map
|
||||
; LTC2980_Margin_Script/Ref/*.md 0x15 trace note corrected to send-byte
|
||||
; LTC2980_Margin_Script/script/margin_save_all.sh Point at margin_save all; keep it for subsets
|
||||
; config.ttl FAN_SPEED 30 -> 100 (full speed by default)
|
||||
; V1.1.0 2026-08-28 Blanton_Script/blanton_ber.sh Add whole-switch SerDes BER test (PRBS via phydiag)
|
||||
; init / start / report / stop / clear, -u 0|1|all
|
||||
; report: one row per lane, PASS when BER < 1e-6, then
|
||||
; a summary across units carrying the worst lane
|
||||
; init also checks every lane locked - an unlocked lane
|
||||
; still reports a BER, and it is a meaningless one
|
||||
; !! PRBS takes the SerDes out of normal operation:
|
||||
; links show DOWN, no traffic passes while it runs
|
||||
; Blanton_Script/blanton_tr518.sh Add TR518 packet test - loads the switch so the rails
|
||||
; can be measured under traffic
|
||||
; start [-u 0|1] then settles 120s (TR_SETTLE_SEC), so
|
||||
; the power read afterwards is loaded, not ramping
|
||||
; stop = port cd lb=none, exactly what TR518.txt does;
|
||||
; l2 learn / test mode are NOT put back - stop says so
|
||||
; Blanton_Script/TH6_SWB{0,1}_power_readback.sh Read the sensor tables ONCE, not once per rail
|
||||
; 38 'show platform' calls -> 2. The old loop sampled
|
||||
; each rail at a different instant, so the total was a
|
||||
; sum of readings seconds apart. Output format unchanged
|
||||
; A rail missing from the table now warns on stderr
|
||||
; instead of silently counting as 0 W
|
||||
; Blanton_Script/blanton_traffic_linespeed.sh Add the 100G uplink (ce0, VLAN 138) to the test
|
||||
; ce0 has no loopback partner and a switch will not send
|
||||
; a frame back out its ingress port, so a tx burst was
|
||||
; one round trip. An INGRESS MIRROR of ce0 back to ce0
|
||||
; keeps it circulating until stop turns the mirror off
|
||||
; !! stop MUST run - the loop does not end on its own
|
||||
; report: ce0 is the last row; a summary at the bottom
|
||||
; carries every unit's PASS / FAIL / NA totals
|
||||
; ScriptC Run the BER sweep, after the traffic report so the
|
||||
; two do not fight over the same ports
|
||||
; Follows SWB_UNIT0/SWB_UNIT1 like the traffic block:
|
||||
; -u 0 / -u 1 / skip, so a single-unit DUT is not asked
|
||||
; for counters from a board it does not have
|
||||
; tools/BER_Test.txt Bench command references for the two new scripts
|
||||
; tools/100G_Traffic.txt
|
||||
; tools/TR518.txt Corrected on the bench: port cd (not *:port all),
|
||||
; testphase=1, and an explicit stop
|
||||
; V1.1.1 2026-08-28 ScriptA Clear a leftover session before starting a new run
|
||||
; hw-test-session finish -> bgctl reset --yes ->
|
||||
; bgctl stop --all -> bgctl list (must come back empty)
|
||||
; A run that ended badly leaves jobs holding CPU and a
|
||||
; session open; the next run used to inherit both, and
|
||||
; the stress numbers were quietly wrong because of it
|
||||
; V1.1.2 2026-08-28 Blanton_Script/nfc_polling.sh Add background NFC tag polling
|
||||
; start / stop / status / tail / report / clear / fg
|
||||
; wraps blantons_nfc_validate.py; start clears the log
|
||||
; first, so a report covers this run only
|
||||
; report works WHILE polling - it only reads the log,
|
||||
; and says RUNNING so a snapshot is not read as final
|
||||
; Each round appends a machine-readable RESULT line, so
|
||||
; the tally never depends on the tool's wording
|
||||
; PASS / FAIL come from the tool's own summary; ERROR
|
||||
; means it produced neither, which is a different fault
|
||||
; from a tag that would not read - counted separately
|
||||
; tail does NOT follow (tail -f never returns, and a
|
||||
; macro waiting on the prompt would hang there)
|
||||
; Runs the .py through python3, not ./ - the file is
|
||||
; mode 100644 and a USB copy carries no execute bit
|
||||
; Blanton_Script/blantons_nfc_validate.py Vendor NFC/NCI validation tool (unmodified)
|
||||
; ScriptA NFC baseline: start -> status -> 30s -> stop -> report
|
||||
; ScriptB Start NFC polling for the soak, then status
|
||||
; ScriptC Stop NFC polling with the other monitors, report it
|
||||
; next to the mgmt ping log, and copy nfc_poll.log to
|
||||
; the job dir for the USB archive
|
||||
; Fix: that cp said nfc_polling.log - the file is
|
||||
; nfc_poll.log, so the NFC log never reached the USB
|
||||
; V1.1.3 2026-08-30 LTC2980_Margin_Script/settings/*.conf VNOM is now the measured median, not the spec value
|
||||
; 86 of 144 rails moved up +0.8% .. +2.5%
|
||||
; (3.3 -> 3.38, 0.9 -> 0.915, 0.8 -> 0.82, ...)
|
||||
; This is NOT display-only: VNOM is the denominator of
|
||||
; margin_status deviation % AND the basis margin_set
|
||||
; derives high/low/OV/UV from, so the whole margin
|
||||
; window shifts with it
|
||||
; !! margin logs from before/after cannot be compared
|
||||
; LTC2980_Margin_Script/profiles/ Add per-CONN SWB profiles, drop comboA/comboB
|
||||
; combo_SWB_CONN13..16_{high,low} - the percentages
|
||||
; follow that board rails, so applying one to a
|
||||
; different CONN margins the wrong things, silently
|
||||
; SWB0 and SWB1 share a profile per CONN (same rails)
|
||||
; LTC2980_Margin_Script/script/*.sh Fix: margin_apply_profile_all.sh still pointed every
|
||||
; board at comboA, which this change deleted - all 9
|
||||
; boards would have failed with "Profile not found"
|
||||
; docs/LTC2980_channel_map.csv Regenerated (tools/gen_channel_map.sh) - it is output
|
||||
; V1.1.4 2026-08-31 4_Blanton_Script_thermal_safety.ttl Add the thermal / safety run - a STANDALONE script,
|
||||
; not part of the A -> B -> C chain
|
||||
; Script A style setup (login, session, fan, wait_init,
|
||||
; DUT info, BMC, PCIe clear, pcie_bus, pmon, dmesg)
|
||||
; then FULL LOAD: mlucas-avx2 -cpu 0:15 in the
|
||||
; background + blanton_tr518.sh start
|
||||
; then while 1: setup_pmon + TH6_SWB0/SWB1 power
|
||||
; readback + bgctl list + jobs, pause 60
|
||||
; !! no teardown section: after you interrupt it the
|
||||
; unit is still on port cd lb=mac / l2 learn off /
|
||||
; test mode nr=yes - run blanton_tr518.sh stop
|
||||
; !! it drives the same ports as traffic and BER, so it
|
||||
; cannot share a DUT with Script B
|
||||
; ScriptB Drop the margin scan from the soak loop
|
||||
; The loop is a fast per-minute sample; margin_status
|
||||
; walks 9 LTC2980 over I2C and dominated the round
|
||||
; ScriptC Take the margin scan instead, once, before uptime
|
||||
; Trade-off: no margin drift DURING the soak any more,
|
||||
; only a start (Script A) and end (Script C) reading
|
||||
; ScriptC exit + wait "Script done" before hw-test-session
|
||||
; finish - leaves the session shell first, so finish
|
||||
; runs in the login shell that opened it
|
||||
; docs/Blanton_Test_Flow.drawio Add the A/B/C + thermal flow diagram
|
||||
; V1.1.5 2026-09-01 ScriptB Stress jobs now last the whole soak
|
||||
; BMC DDR memtester 64M 1 -> 64M (loop count
|
||||
; dropped = runs until stopped)
|
||||
; SSD --runtime 3600 -> 86400
|
||||
; USB --runtime 60 -> 86400
|
||||
; The USB one finished after 60 SECONDS, so an
|
||||
; overnight run had USB idle for all but the first
|
||||
; minute and nothing said so
|
||||
; !! 86400 is 24h: a soak longer than that leaves SSD
|
||||
; and USB dead for the remainder - the per-round
|
||||
; bgctl list (V1.0.10) is where that shows up
|
||||
; Blanton_Script/blanton_multiphase_margin.sh Add multiphase VRM margin over the native i2c buses
|
||||
; high3 / low3 / comboA / comboB / save, -u 0|1|all
|
||||
; 38 rails (19 per SWB), one line each:
|
||||
; SWB0_0V9_ANLG0 - 0.930V Configure Done
|
||||
; save has no per-rail map, prints Multiphase Save All
|
||||
; !! save is STORE_USER_ALL - permanent, survives a
|
||||
; power cycle
|
||||
; !! these are NOT the LTC2980s margin.sh drives; the
|
||||
; two tools reach the same rails from different
|
||||
; sides - do not run both
|
||||
; Blanton_Script/blanton_traffic_linespeed.sh v0.7.0 tx gains PatternRandom, defaults change
|
||||
; tx 100 length=512 -> tx 200 length=324
|
||||
; every burst now ends PatternRandom=yes, ce0 included
|
||||
; A fixed pattern can sit on a benign bit sequence for
|
||||
; a whole run; random is what exposes a weak lane
|
||||
; -r no forces the fixed pattern, -r "" omits the
|
||||
; argument entirely (pre-v0.7.0 wire format)
|
||||
; !! bytes per burst went 51200 -> 64800 (+27%), so
|
||||
; counter totals are not comparable across this
|
||||
; build - the PASS/FAIL cross-check is unaffected
|
||||
; tools/Multiphase_*.txt Bench command references for the new script
|
||||
; V1.1.6 2026-09-02 Blanton_Script/pwr_brick.sh Add PDB / CPB power brick readings
|
||||
; 5 devices, Vin / Iin / Vout / Iout / Temp:
|
||||
; SWB0.PU207 0x62 SWB0.PU13 0x63
|
||||
; SWB1.PU332 0x60 SWB1.PU85 0x61
|
||||
; CPB.PU37 0x26
|
||||
; The four ADPM12200 put each measurement on its own
|
||||
; PMBus PAGE, so a PAGE write has to precede every
|
||||
; read - blanton_pwr_data.sh sends none, which is why
|
||||
; it reports the whole PDB table as NA
|
||||
; Vin PAGE 9 Iin PAGE 10 Vout PAGE 2
|
||||
; Iout PAGE 14 Temp PAGE 18
|
||||
; !! the bring-up spreadsheet wrote those page numbers
|
||||
; in decimal but with an 0x prefix (10 -> 0x10,
|
||||
; 14 -> 0x14, 18 -> 0x18). Only Vout worked,
|
||||
; because 2 reads the same either way
|
||||
; Conversions are the datasheet DIRECT equation
|
||||
; X = (1/m)(Y x 10^-R - b), Table 3: voltage Y x 8mV,
|
||||
; current Y x 0.04A, temperature Y x 0.01C
|
||||
; Checked: READ_VOUT 0x05D4 -> 11936 mV, the same
|
||||
; figure show platform reports for that rail
|
||||
; !! Table 3 does NOT list READ_VIN / READ_IIN; they
|
||||
; borrow the voltage / current coefficients here
|
||||
; Each value is re-read until it passes: not 0xFFFF,
|
||||
; not 0x0000, and inside a plausibility window. This
|
||||
; bus corrupts the HIGH BYTE only, which turns 11.98 V
|
||||
; into 32.00 V - a value no all-ones filter catches
|
||||
; docs/ADPM12200..._Datasheet_2025_12_19.pdf The brick datasheet the pages and coefficients above
|
||||
; came from
|
||||
; ScriptC Re-enable the BMC USB service log, and send it to
|
||||
; a file instead of the console
|
||||
; journalctl ... -o short-iso > log/bmc_usb_net.log
|
||||
; then cp it into the job dir for the USB archive
|
||||
; rm -f first, so the file is this run only
|
||||
; -o short-iso gives it timestamps that line up with
|
||||
; the other monitor logs
|
||||
; !! it no longer appears in the master console log,
|
||||
; so the USB copy is now the ONLY copy - if that
|
||||
; cp fails the service log is gone
|
||||
; LTC2980_Margin_Script/profiles/ Add comboA / comboB per board (CB + SWB CONN13..16)
|
||||
; Checkerboard pair: comboB is comboA with every
|
||||
; direction flipped, so running both covers each rail
|
||||
; high and low while its neighbours sit the other way
|
||||
; NC channels stay nominal in both (CONN14 CH10/11/13,
|
||||
; CONN15 CH10) - nothing to margin on an unused rail
|
||||
; V1.1.7 2026-09-04 Blanton_Script/blanton_multiphase_margin.sh v1.1.0 Add the 'normal' sub-command
|
||||
; Puts all 38 rails back to their nominal set point,
|
||||
; from tools/Multiphase_Normal.txt - same rails and the
|
||||
; same per-rail reporting as the margin profiles
|
||||
; Until now the only way back from a margin was a power
|
||||
; cycle, and 'save' run while margined would have
|
||||
; committed the offsets to NVM, where a power cycle does
|
||||
; not help either
|
||||
; !! TH6_CORE is 0.8 V nominal but settles near 0.8591 V
|
||||
; once the load line is active - reading back 0.859
|
||||
; after 'normal' is the load line, not a failed write
|
||||
; tools/Multiphase_Normal.txt Bench command reference for the above
|
||||
; 5_Blanton_Script_Reboot_Cycle.ttl Created Reboot-cycle run - a STANDALONE script, not
|
||||
; chained to A -> B -> C and not using hw-test-session:
|
||||
; every cycle is a fresh boot, so there is nothing to
|
||||
; carry over and nothing to tear down
|
||||
; while 1: login -> sudo -i -> date -s -> fans -> wait_init
|
||||
; -> Check Pt1..Pt13 -> show uptime -> reboot ->
|
||||
; wait 'Booting in blind mode'
|
||||
; cnt_cycle is printed in the banner of every round
|
||||
; Pt1 DUT info (boot/version/fwutil/syseeprom/ssdhealth/
|
||||
; TPM/NVMe) Pt2 BMC info + source the bash tools
|
||||
; Pt3 mgmt ping Pt4 NFC poll (20 s)
|
||||
; Pt5 SSD stress Pt6 USB stress (node from
|
||||
; usb_target.sh, not a fixed sda1)
|
||||
; Pt7 BMC USB net Pt8 100G port status + 15 s traffic
|
||||
; Pt9 BER sweep Pt10 NVMe error info
|
||||
; Pt11 platform data Pt12 dmesg i2c
|
||||
; Pt13 PCIe error counters + ras-mc-ctl
|
||||
; !! there is NO exit condition - the only way to stop it
|
||||
; is to close the Tera Term macro
|
||||
; !! NOT verified on hardware yet
|
||||
; The cdc_ncm probe sets timeout = 15 and restores it to 0
|
||||
; BEFORE the if, so both branches are covered in one line -
|
||||
; the ping block below it waits on a 'sleep 10', which is
|
||||
; already two thirds of the cap on a loaded DUT
|
||||
; The probe was copied from Script B without its :skip_ping
|
||||
; label, so 'goto skip_ping' had no target. Tera Term only
|
||||
; raises that when it actually jumps, i.e. only when the
|
||||
; NCM interface is missing - the label is now there
|
||||
; Renumbered the second 'Check Pt12' (PCIe error counters)
|
||||
; to Pt13; Pt1..Pt13 are now unique
|
||||
; ScriptB Restore timeout = 0 on the cdc_ncm success path too
|
||||
; It was only restored at :skip_ping, which the success
|
||||
; path reaches several waits later - until then every wait
|
||||
; was capped at 15 s instead of blocking
|
||||
; .gitignore Ignore tmp/ - scripts not yet verified on hardware
|
||||
; blanton_reboottest.sh (the bash port of the reboot cycle,
|
||||
; for running without Tera Term) lives there until it has
|
||||
; been run on a DUT. Unverified scripts must not reach the
|
||||
; publish bundle: the tester cannot tell which ones to
|
||||
; trust once they are side by side in Blanton_Script/
|
||||
; config.ttl Add SSD_RUNTIME / SSD_COUNT / USB_RUNTIME / USB_COUNT
|
||||
; The SSD and USB stress durations were hard-coded in
|
||||
; ScriptB (--runtime 86400 --passes 5 / 1); they are now
|
||||
; declared in one place per site
|
||||
; !! --runtime is the job's OVERALL limit, not per pass:
|
||||
; qfx5252-stress-* stops at RUNTIME seconds whatever
|
||||
; --passes says. RUNTIME 600 = a 10 minute stress,
|
||||
; not 600 x COUNT. For a 24 h soak set RUNTIME 86400
|
||||
; ScriptB Build the SSD / USB stress commands from those knobs
|
||||
; sprintf2 cmd_ssd ... SSD_RUNTIME SSD_COUNT, and the same
|
||||
; for USB; the old hard-coded lines are left commented out
|
||||
; next to them
|
||||
; V1.1.8 2026-09-06
|
||||
; ScriptA Drive logopen's timestamp flag from EN_timestamp
|
||||
; logopen filename 0 1 1 EN_timestamp, with the argument
|
||||
; order spelled out above the call: <file> <binary>
|
||||
; <append> <PlainText> <timestamp>
|
||||
; binary must stay 0. In binary mode Tera Term writes the
|
||||
; raw stream and both PlainText and the timestamp are
|
||||
; ignored
|
||||
; !! EN_timestamp has to exist in config.ttl. An undefined
|
||||
; variable aborts the macro at logopen, it is not read
|
||||
; as 0
|
||||
; !! the timestamp FORMAT lives in TERATERM.INI (Setup >
|
||||
; Additional settings > Log), so it follows the PC and
|
||||
; not this script. Two testers can produce differently
|
||||
; stamped logs from one macro
|
||||
; ScriptB Run mlucas as a systemd unit, not a shell background job
|
||||
; systemd-run --unit=mlucas-amm --property=Type=exec
|
||||
; --property=Restart=always --property=RestartSec=2
|
||||
; The '&' job belonged to the interactive shell: it died
|
||||
; with the session, and 'jobs' could not see it from a
|
||||
; reconnected one, so a soak that lost its terminal quietly
|
||||
; stopped loading the CPU
|
||||
; The log is truncated with '>' before the unit starts and
|
||||
; appended with '>>' inside it, so a restart adds to the
|
||||
; run instead of erasing it
|
||||
; 'systemctl is-active mlucas-amm' now sits beside 'jobs',
|
||||
; both in the one-shot check and in the monitor loop at the
|
||||
; end
|
||||
; !! the old '&' line is kept commented out directly above
|
||||
; it, to fall back to if systemd-run is unavailable
|
||||
; ScriptB Take the BMC USB ping duration from BMC_USB_RUNTIME
|
||||
; sprintf2 cmd '... -w %d ...' ncm_if BMC_USB_RUNTIME. It
|
||||
; was hard-coded to 14400 (4 h), which no longer matched
|
||||
; the soak the SSD and USB knobs were set for
|
||||
; ScriptC Stop mlucas-amm and copy its log to the USB stick
|
||||
; utils/kill_all_process.ttl is only "kill $(jobs -p)", and
|
||||
; a systemd unit is not a shell job
|
||||
; ScriptB's change on its own would have left mlucas
|
||||
; loading all 16 cores through ScriptC and into the next
|
||||
; run, so every temperature and power reading after it
|
||||
; would have been taken under load
|
||||
; cp ~/hammer/tools/amd/mlucas_amm_log /host/hw-eval/jobs/
|
||||
; joins the other stress logs
|
||||
; !! ScriptB and ScriptC change together. Whoever moves a
|
||||
; stress job to systemd owns the matching stop in
|
||||
; ScriptC
|
||||
; Script4 Use the same mlucas-amm systemd unit as ScriptB
|
||||
; The thermal / safety macro started mlucas the same way
|
||||
; ScriptB used to, with '&', so it had the same failure:
|
||||
; the load quietly ended when the console went away, in the
|
||||
; one test where a long steady full load is the whole point
|
||||
; 'systemctl is-active mlucas-amm' joins 'bgctl list' and
|
||||
; 'jobs' in the monitor loop
|
||||
; !! Script4 still has no teardown section, so the matching
|
||||
; stop is manual: blanton_tr518.sh stop AND systemctl
|
||||
; stop mlucas-amm. Closing Tera Term no longer stops the
|
||||
; CPU load, and 'kill $(jobs -p)' never reached a unit
|
||||
; config.ttl Add EN_timestamp and BMC_USB_RUNTIME, raise stress runtimes
|
||||
; EN_timestamp = 1 feeds ScriptA's logopen; BMC_USB_RUNTIME
|
||||
; = 172800 feeds ScriptB's ping unit
|
||||
; SSD_RUNTIME and USB_RUNTIME 600 -> 3600, so the shipped
|
||||
; default is a one hour stress rather than the ten minutes
|
||||
; V1.1.7 went out with
|
||||
; !! --runtime is still the job's OVERALL limit. RUNTIME
|
||||
; 3600 = one hour of stress; COUNT does not multiply it.
|
||||
; For a 2 day soak set RUNTIME 172800
|
||||
; .gitignore Ignore src/Script_ABC_Blanton/hammer/
|
||||
; ~99 MB of unstripped mlucas ELF binaries (avx512 / avx2 /
|
||||
; avx / sse2 / generic-c) that ScriptB and the thermal
|
||||
; macro chmod and run on the DUT
|
||||
; !! they are deliberately NOT in git. A binary tree that
|
||||
; large is permanent once committed and every clone pays
|
||||
; for it forever; the DUT image already carries hammer/
|
||||
; publish/publish.sh Exclude hammer/ from the delivery bundle
|
||||
; rsync copies whatever sits in src/, so a developer who
|
||||
; happened to have the binaries locally would have shipped
|
||||
; a 100 MB zip while a clone shipped 200 KB. The bundle is
|
||||
; now the same either way
|
||||
; V1.1.9 2026-09-07
|
||||
; Blanton_Script/bcm_dsc_scan.sh Created V1.2.0 - batch SerDes DSC dump
|
||||
; Runs bcmcmd -n <unit> -c "dsh -c 'phydiag <port> dsc'"
|
||||
; over the whole port list (1 x 100G + 445 x 200G ranges),
|
||||
; both units, and leaves the raw log in <script_dir>/log
|
||||
; before copying it to /host/hw-eval/jobs
|
||||
; -f names the log (%u -> u0/u1, %t -> timestamp), -F
|
||||
; overwrites, -u picks one unit, -n dry runs, -C skips the
|
||||
; copy. -f takes a filename only; the directory comes from
|
||||
; -o
|
||||
; bcmcmd exits 0 even when the diag shell rejects a
|
||||
; command, so success is judged by counting 'SERDES DISPLAY
|
||||
; DIAG DATA END' markers, not by the exit code - the same
|
||||
; trap blanton_traffic_linespeed.sh hit
|
||||
; Paths come from $0, not $HOME, because Script A runs it
|
||||
; after sudo -i and a literal ~ would depend on the
|
||||
; environment. Ends with '### DSC_SCAN_DONE rc=<n>' for a
|
||||
; TTL wait to key on
|
||||
; Non-tty output is one line per port instead of a progress
|
||||
; bar, so it does not flood the Tera Term log
|
||||
; !! phydiag dsc is read-only and does not change any
|
||||
; SerDes setting, but a full scan is ~10 min per run.
|
||||
; ScriptA and ScriptC each do one, so the test is ~20
|
||||
; min longer than before. Do not set DELAY to 0
|
||||
; Blanton_Script/bcm_dsc_parse.sh Created V1.0.0 - offline DSC log to CSV
|
||||
; Host side. -i <raw log> -o <prefix> produces
|
||||
; <prefix>_lane.csv (one row per lane: TXEQ / RXFFE / DFE /
|
||||
; EYE / SNR) and <prefix>_pm.csv (one row per pm_id:
|
||||
; temperature / PLL / lane count / SNR-EYE stats)
|
||||
; POSIX sh + awk, mawk compatible, no Python. Lane rows are
|
||||
; read by the order of their bracket groups rather than
|
||||
; fixed columns, so re-spacing by the SDK does not break
|
||||
; it; a row whose group count is not 9 is marked UNPARSED
|
||||
; on stderr instead of being parsed wrongly
|
||||
; SD / LCK sticky '*' flags are kept as separate columns
|
||||
; and not interpreted; a BER field of '!chk_en' means the
|
||||
; checker was off and is passed through unchanged
|
||||
; ScriptA Collect the SerDes DSC baseline before 'show uptime'
|
||||
; ./Blanton_Script/bcm_dsc_scan.sh -f
|
||||
; blanton_dsc_ScriptA.log -F
|
||||
; The name has no %u, so the script inserts _u0 / _u1
|
||||
; itself and unit 1 cannot overwrite unit 0 - that is where
|
||||
; the file names ScriptC copies come from
|
||||
; ScriptA / ScriptB / ScriptC Remove the commented-out 100G PRBS blocks
|
||||
; The port_prbs_monitor.sh calls had been commented out in
|
||||
; all three since bring-up, together with a second copy of
|
||||
; the 100G port status block in ScriptA and the stale
|
||||
; bmc_monitor_ddr.sh block in ScriptC
|
||||
; port_prbs_monitor.sh still ships and still runs by hand;
|
||||
; only the dead call sites are gone
|
||||
; ScriptC Collect the closing DSC dump and carry the four logs out
|
||||
; ./Blanton_Script/bcm_dsc_scan.sh -f
|
||||
; blanton_dsc_ScriptC.log -F, then cp of
|
||||
; blanton_dsc_Script{A,C}_u{0,1}.log into
|
||||
; /host/hw-eval/jobs/
|
||||
; The scan already copies its own output there; these four
|
||||
; are a second pass so a failed copy inside the scan still
|
||||
; leaves the data on the USB stick
|
||||
; Blanton_Script Both new scripts need the execute bit on the DUT
|
||||
; !! git records them 100644 like every other .sh here, and
|
||||
; ScriptA / ScriptC invoke them as
|
||||
; ./Blanton_Script/bcm_dsc_scan.sh, so they join
|
||||
; bmc_monitor.sh and friends in the chmod +x line after
|
||||
; deployment. Without it both scans fail with Permission
|
||||
; denied and the macro walks straight past it
|
||||
; V1.2.0 2026-09-07
|
||||
; Blanton_Script/bcm_dsc_scan.sh v1.3.0 bcmcmd was eating the port list
|
||||
; The scan loop read the port file on stdin, and bcmcmd
|
||||
; reads stdin too, so the first call swallowed the rest of
|
||||
; the file and the loop ended after ONE port
|
||||
; Nothing looked wrong: the log held one PORT marker and
|
||||
; one dsc block, markers == dumps, exit code 0. A 445 port
|
||||
; scan finished in seconds and reported success
|
||||
; Fixed by reading the loop on fd 3 (done 3< "$PORTFILE")
|
||||
; and giving bcmcmd < /dev/null
|
||||
; Added a check that the iteration count equals the port
|
||||
; list count. The marker / dump comparison cannot catch a
|
||||
; loop that ends early, because both numbers shrink
|
||||
; together; the Saved: line now reports dumps out of TOTAL,
|
||||
; not out of markers
|
||||
; !! this is the same bcmcmd trap
|
||||
; blanton_traffic_linespeed.sh hit at v0.3.1, where only
|
||||
; the first VLAN was configured. Every while ... done <
|
||||
; file loop that calls bcmcmd needs < /dev/null - assume
|
||||
; it will read stdin unless proven otherwise
|
||||
; ScriptA / ScriptB / ScriptC Wait on the DUT with 'sleep', not on the macro with 'pause'
|
||||
; pause N stops the macro for N seconds without touching
|
||||
; the DUT: the shell sits idle and the macro is guessing
|
||||
; how long the last command took. sendln "sleep N" + wait
|
||||
; prompt_sonic_root moves the wait onto the DUT, so the
|
||||
; macro resumes when the prompt actually comes back and the
|
||||
; two cannot drift apart
|
||||
; It also lands in the console log with a timestamp, so a
|
||||
; round that ran long is visible afterwards instead of
|
||||
; invisible
|
||||
; Durations changed with it: ScriptA mgmt ping 30 -> 15 s;
|
||||
; the settle after every traffic 'clear' 15 -> 5 s; the
|
||||
; traffic run itself stays 15 s; ScriptB's monitor loop
|
||||
; stays 60 s
|
||||
; !! Script4 and Script5 were NOT converted and still use
|
||||
; pause. The 'pause 1' at the top of ScriptB / ScriptC
|
||||
; also stays - it only spaces the log header and runs
|
||||
; before there is a prompt to wait for
|
||||
; config.ttl Add EN_TX_FIR to gate the SerDes DSC scan
|
||||
; EN_TX_FIR = 1 enables bcm_dsc_scan.sh in ScriptA and
|
||||
; ScriptC, and the four cp lines that carry
|
||||
; blanton_dsc_Script{A,C}_u{0,1}.log to /host/hw-eval/jobs.
|
||||
; Default is 0
|
||||
; A full scan is ~10 min and both scripts do one, so
|
||||
; leaving it off keeps ~20 min out of a routine run. Turn
|
||||
; it on when the SerDes data is what you are after
|
||||
; ScriptC Stop printing the BMC poll and mlucas logs to the console
|
||||
; cat bmc_poll.log and cat mlucas_amm_log are commented
|
||||
; out. Both files are still copied to /host/hw-eval/jobs
|
||||
; and out to the USB stick with everything else, so no data
|
||||
; is lost - the master log is just shorter
|
||||
; V1.2.1 2026-09-08
|
||||
; ScriptA Add a BER baseline sweep before the traffic run
|
||||
; blanton_ber.sh init / start / sleep 30 / report / stop /
|
||||
; clear, branched on SWB_UNIT0 and SWB_UNIT1 the same way
|
||||
; the traffic block is. ScriptC already took the closing
|
||||
; sweep after its traffic report, so the two now bracket
|
||||
; the soak the way the DSC scans do
|
||||
; sleep 30 is not arbitrary: it is blanton_ber.sh's
|
||||
; BER_INTERVAL. 'report' before one full interval has
|
||||
; accumulated reads a window that has not finished
|
||||
; The block was copied from ScriptC, which runs it AFTER
|
||||
; traffic, and its comment said so. In ScriptA it runs
|
||||
; BEFORE traffic, so the comment was rewritten to match
|
||||
; where the code actually is
|
||||
; !! nothing settles between 'blanton_ber.sh clear' and
|
||||
; 'blanton_traffic_linespeed ps' that follows it. PRBS
|
||||
; holds the lanes out of normal operation and 'clear' is
|
||||
; what releases them, so the first traffic run of
|
||||
; ScriptA now starts on lanes that have just been
|
||||
; released. ScriptC does not have this ordering. Watch
|
||||
; ScriptA's first traffic report for NA or FAIL pairs
|
||||
; that ScriptC's does not show - if they appear, a sleep
|
||||
; after 'clear' is the fix
|
||||
; !! ScriptA now runs BER twice as far as the switch is
|
||||
; concerned: once here and once inside ScriptC. Neither
|
||||
; can overlap blanton_traffic_linespeed or
|
||||
; blanton_tr518.sh - they all take over the same ports
|
||||
; =============================================================================
|
||||
include "config.ttl"
|
||||
|
||||
@@ -27,7 +574,11 @@ getdir mdir
|
||||
|
||||
if EN_log = 1 then
|
||||
sprintf2 filename '%s\Logs\%s_%s_%s.log' mdir project_name strTestcase str_starttime
|
||||
logopen filename 0 1 1 1
|
||||
; logopen <file> <binary> <append> <PlainText> <timestamp>
|
||||
; binary=0 text mode, so PlainText / timestamp are honoured
|
||||
; append=1 keep earlier cycles, do not overwrite
|
||||
; PlainText=1 strip the ANSI colour codes SONiC emits
|
||||
logopen filename 0 1 1 EN_timestamp
|
||||
endif
|
||||
|
||||
; ========== Root Login ==========
|
||||
@@ -49,6 +600,86 @@ gettime timestr
|
||||
sprintf2 cmd 'sudo date -s "%s %s"' datestr timestr
|
||||
sendln cmd
|
||||
|
||||
;Stress log clear
|
||||
wait prompt_sonic_root
|
||||
sendln "rm /host/hw-eval/jobs/*"
|
||||
|
||||
; ========== HW Test Session ==========
|
||||
; Clear session
|
||||
wait prompt_sonic_root
|
||||
sendln "hw-test-session finish"
|
||||
wait prompt_sonic_root
|
||||
sendln "bgctl reset --yes"
|
||||
wait prompt_sonic_root
|
||||
sendln "bgctl stop --all"
|
||||
wait prompt_sonic_root
|
||||
sendln "bgctl list"
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "hw-test-session start"
|
||||
wait prompt_sonic_root
|
||||
sendln "hw-test-session log"
|
||||
wait prompt_sonic_root
|
||||
sendln "hw-test-session status"
|
||||
|
||||
; ========== FAN SPEED ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "echo 18-0020 > /sys/bus/i2c/drivers/max31790/unbind"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep .5"
|
||||
wait prompt_sonic_root
|
||||
sendln "echo 18-0020 > /sys/bus/i2c/drivers/max31790/bind"
|
||||
wait prompt_sonic_root
|
||||
sendln "echo 25-0020 > /sys/bus/i2c/drivers/max31790/unbind"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep .5"
|
||||
wait prompt_sonic_root
|
||||
sendln "echo 25-0020 > /sys/bus/i2c/drivers/max31790/bind"
|
||||
|
||||
wait prompt_sonic_root
|
||||
sprintf2 fan_ctrl_cmd 'fan-speed-control.sh %d' FAN_SPEED
|
||||
sendln fan_ctrl_cmd
|
||||
|
||||
wait "Set all configured fan channels to"
|
||||
sendln "y"
|
||||
|
||||
|
||||
; ========== Wait DUT Init ==========
|
||||
include "utils/wait_init.ttl"
|
||||
|
||||
; ========== DUT Info ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "show boot"
|
||||
wait prompt_sonic_root
|
||||
sendln "show version"
|
||||
wait prompt_sonic_root
|
||||
sendln "fwutil show status"
|
||||
wait prompt_sonic_root
|
||||
sendln "show system-memory"
|
||||
wait prompt_sonic_root
|
||||
sendln "show service"
|
||||
wait prompt_sonic_root
|
||||
sendln "show platform syseeprom"
|
||||
wait prompt_sonic_root
|
||||
sendln "show platform ssdhealth"
|
||||
wait prompt_sonic_root
|
||||
sendln "qfx5252-tpm-version"
|
||||
wait prompt_sonic_root
|
||||
sendln "/usr/sbin/nvme smart-log -H /dev/nvme0"
|
||||
wait prompt_sonic_root
|
||||
sendln "/usr/sbin/smartctl -x /dev/nvme0"
|
||||
|
||||
; ========== BMC version ==========
|
||||
;wait prompt_sonic_root
|
||||
;sendln "bmc-manager run 'cat /etc/issue'"
|
||||
wait prompt_sonic_root
|
||||
sendln "bmc-first-enroll"
|
||||
wait prompt_sonic_root
|
||||
sendln "bmc-manager version"
|
||||
wait prompt_sonic_root
|
||||
sendln "bmc-manager status"
|
||||
|
||||
|
||||
; ========== Load Shell Script ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "source ~/Blanton_Script/blanton_fpga_pcimem.sh"
|
||||
@@ -72,14 +703,13 @@ include "utils/show_pcie_error_reg_DDR.ttl"
|
||||
include "utils/show_pcie_error_reg_I210.ttl"
|
||||
include "utils/show_pcie_error_reg_SSD.ttl"
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "/usr/sbin/ras-mc-ctl --summary"
|
||||
|
||||
|
||||
; ========== Check PCIE tree + PCIE link status + GET PCIE bandwidth Test ==========
|
||||
include "utils/pcie_bus.ttl"
|
||||
|
||||
; ========== Check History ==========
|
||||
;wait prompt_sonic_root
|
||||
;sendln "command"
|
||||
|
||||
; ========== Check Margin ==========
|
||||
if EN_Margin = 1 then
|
||||
include "utils/show_margin_status.ttl"
|
||||
@@ -88,16 +718,180 @@ endif
|
||||
; ========== TAKE DATA ==========
|
||||
include "utils/setup_pmon.ttl"
|
||||
include "utils/show_dmesg.ttl"
|
||||
wait prompt_sonic_root
|
||||
|
||||
;include "utils/xxx.ttl"
|
||||
;wait prompt_sonic_root
|
||||
;flushrecv
|
||||
|
||||
; ========== TRAFFIC-SETUP-STAGE ==========
|
||||
;sendln "command"
|
||||
; ========== 10G/1G MGMT Ping Test ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/mgmt_ping_monitor.sh start"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 15"
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/mgmt_ping_monitor.sh stop"
|
||||
wait prompt_sonic_root
|
||||
sendln "cat ~/Blanton_Script/log/mgmt_ping.log"
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/mgmt_ping_monitor.sh clear"
|
||||
|
||||
; ========== NFC Test ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/nfc_polling.sh start"
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/nfc_polling.sh status"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 30"
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/nfc_polling.sh stop"
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/nfc_polling.sh report"
|
||||
|
||||
|
||||
; ========== 100G Port Status ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "sudo sfputil lpmode off Ethernet513"
|
||||
wait prompt_sonic_root
|
||||
sendln "sudo sfputil lpmode off Ethernet514"
|
||||
wait prompt_sonic_root
|
||||
sendln "config interface -n asic0 startup Ethernet513"
|
||||
wait prompt_sonic_root
|
||||
sendln "config interface -n asic1 startup Ethernet514"
|
||||
wait prompt_sonic_root
|
||||
sendln "config save -y"
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "show interfaces status Ethernet513,Ethernet514"
|
||||
|
||||
|
||||
; ========== First Traffic Test ==========
|
||||
; Silent MAC
|
||||
wait prompt_sonic_root
|
||||
sendln "config feature state lldp disabled"
|
||||
wait prompt_sonic_root
|
||||
sendln "config save -y"
|
||||
|
||||
; ========== BER ==========
|
||||
; Baseline sweep, taken BEFORE the traffic run - ScriptC takes the closing
|
||||
; one after its traffic report, so the pair brackets the soak.
|
||||
; PRBS takes the SerDes out of normal operation; 'clear' is what puts the
|
||||
; lanes back, so it has to run before the traffic block below.
|
||||
; sleep 30 matches blanton_ber.sh BER_INTERVAL - reporting earlier reads an
|
||||
; interval that has not finished accumulating.
|
||||
if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh init"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh start"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 30"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh report"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh stop"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh clear"
|
||||
elseif SWB_UNIT0 = 1 && SWB_UNIT1 = 0 then
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh init -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh start -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 30"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh report -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh stop -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh clear -u 0"
|
||||
elseif SWB_UNIT0 = 0 && SWB_UNIT1 = 1 then
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh init -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh start -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 30"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh report -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh stop -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh clear -u 1"
|
||||
else
|
||||
|
||||
endif
|
||||
|
||||
if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed ps"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed init"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed clear"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 5"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed show"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed start"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 15"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed stop"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed report"
|
||||
elseif SWB_UNIT0 = 1 && SWB_UNIT1 = 0 then
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed ps -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed init -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed clear -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 5"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed show -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed start -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 15"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed stop -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed report -u 0"
|
||||
elseif SWB_UNIT0 = 0 && SWB_UNIT1 = 1 then
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed ps -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed init -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed clear -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 5"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed show -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed start -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 15"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed stop -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed report -u 1"
|
||||
else
|
||||
|
||||
endif
|
||||
|
||||
if EN_TX_FIR = 1 then
|
||||
; ========== Collect bcm dsc data ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/bcm_dsc_scan.sh -f blanton_dsc_ScriptA.log -F"
|
||||
endif
|
||||
|
||||
; ========== Show Power on uptime ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "show uptime"
|
||||
|
||||
|
||||
sendln ""
|
||||
wait prompt_sonic_root
|
||||
messagebox 'Start Script B' 'Script A DONE'
|
||||
@@ -15,57 +15,177 @@ pause 1
|
||||
;sendln "command"
|
||||
|
||||
; ========== AMD CPU STRESS TEST ==========
|
||||
; Clear the log file first
|
||||
wait prompt_sonic_root
|
||||
sendln "> ~/hammer/tools/amd/mlucas_amm_log"
|
||||
wait prompt_sonic_root
|
||||
sendln 'chmod +x ~/hammer/tools/amd/mlucas-avx2'
|
||||
wait prompt_sonic_root
|
||||
sendln "~/hammer/tools/amd/mlucas-avx2 -s l -cpu 0:15 > ~/hammer/tools/amd/mlucas_amm_log 2>&1 &"
|
||||
;sendln "~/hammer/tools/amd/mlucas-avx2 -s l -cpu 0:15 > ~/hammer/tools/amd/mlucas_amm_log 2>&1 &"
|
||||
sendln "systemd-run --unit=mlucas-amm --property=Type=exec --property=Restart=always --property=RestartSec=2 /bin/bash -c '~/hammer/tools/amd/mlucas-avx2 -s l -cpu 0:15 >> ~/hammer/tools/amd/mlucas_amm_log 2>&1'"
|
||||
|
||||
|
||||
; ========== BMC DDR Stress Test ==========
|
||||
;wait prompt_sonic_root
|
||||
;sendln "./Blanton_Script/bmc_monitor_ddr.sh start"
|
||||
;wait prompt_sonic_root
|
||||
;sendln "./Blanton_Script/bmc_monitor.sh start"
|
||||
wait prompt_sonic_root
|
||||
;sendln "bgctl run bmc-manager run '/usr/bin/memtester 64M 1'"
|
||||
sendln "bgctl run bmc-manager run '/usr/bin/memtester 64M'" ; Continue Execture
|
||||
|
||||
; ========== BMC Monitor Test ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/bmc_monitor.sh start"
|
||||
|
||||
; ========== DDR MEMORY STRESS TEST ==========
|
||||
;wait prompt_sonic_root
|
||||
;sendln "bgctl run /usr/sbin/memtester 1G 100"
|
||||
wait prompt_sonic_root
|
||||
sendln "python ~/hammer/tools/stress_mem.py &"
|
||||
wait prompt_sonic_root
|
||||
sendln "python ~/hammer/tools/stress_mem.py &"
|
||||
wait prompt_sonic_root
|
||||
sendln "python ~/hammer/tools/stress_mem.py &"
|
||||
wait prompt_sonic_root
|
||||
sendln "python ~/hammer/tools/stress_mem.py &"
|
||||
wait prompt_sonic_root
|
||||
sendln "python ~/hammer/tools/stress_mem.py &"
|
||||
sendln "bgctl run /usr/sbin/memtester 1G" ; Continue Execture
|
||||
|
||||
; ========== SSD read/write ==========
|
||||
sprintf2 cmd_ssd "bgctl run qfx5252-stress-ssd 1G --runtime %d --passes %d --write --force --log /host/hw-eval/jobs/qfx5252-stress-ssd.log" SSD_RUNTIME SSD_COUNT
|
||||
wait prompt_sonic_root
|
||||
sendln "python ~/hammer/tools/stress_ssd.py &"
|
||||
;sendln "bgctl run qfx5252-stress-ssd 1G --runtime 86400 --passes 5 --write --force --log /host/hw-eval/jobs/qfx5252-stress-ssd.log"
|
||||
sendln cmd_ssd
|
||||
|
||||
; ========== USB read/write ==========
|
||||
; ---- Get USB partition node -> usb_dev ----
|
||||
usb_dev = ''
|
||||
wait prompt_sonic_root
|
||||
sendln "python ~/hammer/tools/stress_usb.py &"
|
||||
sendln 'D=$(bash ~/Blanton_Script/usb_target.sh -o dev 2>/dev/null); echo "<<D""EV=${D:-NONE}>>"'
|
||||
waitregex '<<DEV=([^>]*)>>'
|
||||
usb_dev = groupmatchstr1
|
||||
|
||||
wait prompt_sonic_root
|
||||
;sprintf2 cmd "bgctl run qfx5252-stress-usb %s 256M --runtime 86400 --passes 1 --write --log /host/hw-eval/jobs/qfx5252-stress-usb.log" usb_dev
|
||||
sprintf2 cmd "bgctl run qfx5252-stress-usb %s 256M --runtime %d --passes %d --write --log /host/hw-eval/jobs/qfx5252-stress-usb.log" usb_dev USB_RUNTIME USB_COUNT
|
||||
sendln cmd
|
||||
|
||||
;wait prompt_sonic_root
|
||||
;sendln "bgctl run qfx5252-stress-usb /dev/sda1 256M --runtime 60 --passes 1 --write --log /host/hw-eval/qfx5252-stress-usb.log"
|
||||
|
||||
; ========== SHOW Background job ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "jobs"
|
||||
wait prompt_sonic_root
|
||||
sendln "systemctl is-active mlucas-amm"
|
||||
wait prompt_sonic_root
|
||||
sendln "bgctl list"
|
||||
|
||||
; ========== BMC USB Test ==========
|
||||
wait prompt_sonic_root
|
||||
sendln 'echo "NCMIF=$(ls -d /sys/bus/usb/drivers/cdc_ncm/*/net/* 2>/dev/null | head -n 1 | xargs -r basename)"'
|
||||
timeout = 15
|
||||
waitregex 'NCMIF=[A-Za-z0-9_-]+'
|
||||
if result = 0 then
|
||||
messagebox 'cdc_ncm interface not found. Ping test skipped.' 'ERROR'
|
||||
goto skip_ping
|
||||
endif
|
||||
timeout = 0
|
||||
strlen matchstr
|
||||
cut_len = result - 6 ; 'NCMIF=' = 6 chars
|
||||
strcopy matchstr 7 cut_len ncm_if ; -> ncm_if = "eth2" / "eth3"
|
||||
|
||||
sprintf2 cmd 'ip -br link show %s' ncm_if
|
||||
wait prompt_sonic_root
|
||||
sendln cmd
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln 'systemctl stop qfx5252-bmc-usb-net-test.service 2>/dev/null || true'
|
||||
wait prompt_sonic_root
|
||||
sendln 'systemctl reset-failed qfx5252-bmc-usb-net-test.service 2>/dev/null || true'
|
||||
sprintf2 cmd 'systemd-run --unit=qfx5252-bmc-usb-net-test --property=Type=exec /usr/bin/ping -I %s -i 1 -W 2 -w %d 192.168.200.200' ncm_if BMC_USB_RUNTIME
|
||||
wait prompt_sonic_root
|
||||
sendln cmd
|
||||
|
||||
:skip_ping
|
||||
; restore the default (no cap): the traffic init below walks 108 VLANs per
|
||||
; unit and takes far longer than the 15 s set for the NCM probe above.
|
||||
timeout = 0
|
||||
|
||||
; ========== 10G/1G MGMT Ping Test ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/mgmt_ping_monitor.sh start"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 3"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/mgmt_ping_monitor.sh status"
|
||||
|
||||
; ========== NFC Test ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/nfc_polling.sh start"
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/nfc_polling.sh status"
|
||||
|
||||
|
||||
; ========== 100G Port ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "show interfaces status Ethernet513,Ethernet514"
|
||||
|
||||
; ========== Take one round of eye measurement on uplink ports ==========
|
||||
|
||||
; ========== Traffic START ==========
|
||||
; Silent MAC
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed ps -u 0"
|
||||
sendln "config feature state lldp disabled"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed init -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed clear -u 0"
|
||||
wait prompt_sonic_root
|
||||
pause 3
|
||||
sendln "blanton_traffic_linespeed show -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed start -u 0"
|
||||
sendln "config save -y"
|
||||
|
||||
if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed ps"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed init"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed clear"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 5"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed show"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed start"
|
||||
elseif SWB_UNIT0 = 1 && SWB_UNIT1 = 0 then
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed ps -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed init -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed clear -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 5"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed show -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed start -u 0"
|
||||
elseif SWB_UNIT0 = 0 && SWB_UNIT1 = 1 then
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed ps -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed init -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed clear -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 5"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed show -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed start -u 1"
|
||||
else
|
||||
|
||||
endif
|
||||
|
||||
|
||||
|
||||
; ========== Get data every 10mins ==========
|
||||
; ========== Monitor loop: platform data + background jobs (sleep 60s per round) ==========
|
||||
while 1
|
||||
include "utils/setup_pmon.ttl"
|
||||
; ========== Check Margin ==========
|
||||
if EN_Margin = 1 then
|
||||
include "utils/show_margin_status.ttl"
|
||||
endif
|
||||
endwhile
|
||||
wait prompt_sonic_root
|
||||
sendln "bgctl list"
|
||||
wait prompt_sonic_root
|
||||
sendln "jobs"
|
||||
wait prompt_sonic_root
|
||||
sendln "systemctl is-active mlucas-amm"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 60"
|
||||
endwhile
|
||||
|
||||
@@ -12,6 +12,27 @@ pause 1
|
||||
|
||||
; ========== Kill Process ==========
|
||||
include "utils/kill_all_process.ttl"
|
||||
wait prompt_sonic_root
|
||||
sendln "systemctl is-active mlucas-amm"
|
||||
wait prompt_sonic_root
|
||||
sendln "systemctl stop mlucas-amm"
|
||||
|
||||
; bgctrl all stop
|
||||
wait prompt_sonic_root
|
||||
sendln "bgctl stop --all"
|
||||
wait prompt_sonic_root
|
||||
sendln "bgctl stop --all"
|
||||
; BMC USB Test STOP
|
||||
wait prompt_sonic_root
|
||||
sendln "systemctl stop qfx5252-bmc-usb-net-test.service"
|
||||
; 10G/1G MGMT Test STOP
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/mgmt_ping_monitor.sh status"
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/mgmt_ping_monitor.sh stop"
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/nfc_polling.sh stop"
|
||||
|
||||
; ========== TAKE DATA ==========
|
||||
include "utils/setup_pmon.ttl"
|
||||
include "utils/show_dmesg.ttl"
|
||||
@@ -25,17 +46,186 @@ include "utils/show_pcie_error_reg_DDR.ttl"
|
||||
include "utils/show_pcie_error_reg_I210.ttl"
|
||||
include "utils/show_pcie_error_reg_SSD.ttl"
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "/usr/sbin/ras-mc-ctl --summary"
|
||||
|
||||
|
||||
; ========== BMC Monitor TAKE DATA ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/bmc_monitor.sh stop"
|
||||
; wait prompt_sonic_root
|
||||
; sendln "cat ./Blanton_Script/log/bmc_poll.log"
|
||||
|
||||
; ========== BMC USB Test result ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "rm -f ~/Blanton_Script/log/bmc_usb_net.log"
|
||||
wait prompt_sonic_root
|
||||
sendln "journalctl -u qfx5252-bmc-usb-net-test.service --no-pager -o short-iso > ~/Blanton_Script/log/bmc_usb_net.log"
|
||||
|
||||
|
||||
; ========== CHECK Stress results ==========
|
||||
; wait prompt_sonic_root
|
||||
; sendln "cat ~/hammer/tools/amd/mlucas_amm_log"
|
||||
wait prompt_sonic_root
|
||||
sendln "cat ~/hammer/tools/amd/mlucas_amm_log"
|
||||
sendln "cat /host/hw-eval/jobs/qfx5252-stress-ssd.log"
|
||||
wait prompt_sonic_root
|
||||
sendln "cat ~/hammer/tools/log.stress_ssd"
|
||||
sendln "cat /host/hw-eval/jobs/qfx5252-stress-usb.log"
|
||||
|
||||
; ========== 10G/1G MGMT Test result ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "cat ~/Blanton_Script/log/mgmt_ping.log"
|
||||
|
||||
; ========== NFC Test result ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/nfc_polling.sh report"
|
||||
|
||||
; ========== 100G Port ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "show interfaces status Ethernet513,Ethernet514"
|
||||
|
||||
; ========== CHECK Traffic counters ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed stop -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed report -u 0"
|
||||
if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed stop"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed report"
|
||||
elseif SWB_UNIT0 = 1 && SWB_UNIT1 = 0 then
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed stop -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed report -u 0"
|
||||
elseif SWB_UNIT0 = 0 && SWB_UNIT1 = 1 then
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed stop -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed report -u 1"
|
||||
else
|
||||
|
||||
endif
|
||||
|
||||
; ========== BER ==========
|
||||
; PRBS takes the SerDes out of normal operation, so this runs AFTER the
|
||||
; traffic report. sleep 30 matches blanton_ber.sh BER_INTERVAL - reporting
|
||||
; earlier reads an interval that has not finished accumulating.
|
||||
if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh init"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh start"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 30"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh report"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh stop"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh clear"
|
||||
elseif SWB_UNIT0 = 1 && SWB_UNIT1 = 0 then
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh init -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh start -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 30"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh report -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh stop -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh clear -u 0"
|
||||
elseif SWB_UNIT0 = 0 && SWB_UNIT1 = 1 then
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh init -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh start -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 30"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh report -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh stop -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh clear -u 1"
|
||||
else
|
||||
|
||||
endif
|
||||
|
||||
if EN_TX_FIR = 1 then
|
||||
; ========== Collect bcm dsc data ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/bcm_dsc_scan.sh -f blanton_dsc_ScriptC.log -F"
|
||||
endif
|
||||
|
||||
; ========== NVME Err Info ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "/usr/sbin/nvme smart-log -H /dev/nvme0"
|
||||
wait prompt_sonic_root
|
||||
sendln "/usr/sbin/smartctl -x /dev/nvme0"
|
||||
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "show reboot-cause"
|
||||
|
||||
; ========== Check Margin ==========
|
||||
if EN_Margin = 1 then
|
||||
include "utils/show_margin_status.ttl"
|
||||
endif
|
||||
|
||||
; ========== Show Power on uptime ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "show uptime"
|
||||
|
||||
|
||||
; ---- Get USB partition node -> usb_dev ----
|
||||
usb_dev = ''
|
||||
wait prompt_sonic_root
|
||||
sendln 'D=$(bash ~/Blanton_Script/usb_target.sh -o dev 2>/dev/null); echo "<<D""EV=${D:-NONE}>>"'
|
||||
waitregex '<<DEV=([^>]*)>>'
|
||||
usb_dev = groupmatchstr1
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "sync"
|
||||
wait prompt_sonic_root
|
||||
sprintf2 cmd "mount %s /mnt/usb" usb_dev
|
||||
sendln cmd
|
||||
|
||||
; ========== Copy Stress Log to USB ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "cp ~/hammer/tools/amd/mlucas_amm_log /host/hw-eval/jobs/"
|
||||
wait prompt_sonic_root
|
||||
sendln "cp ./Blanton_Script/log/bmc_usb_net.log /host/hw-eval/jobs/"
|
||||
wait prompt_sonic_root
|
||||
sendln "cp ./Blanton_Script/log/bmc_poll.log /host/hw-eval/jobs/"
|
||||
wait prompt_sonic_root
|
||||
sendln "cp ./Blanton_Script/log/mgmt_ping.log /host/hw-eval/jobs/"
|
||||
wait prompt_sonic_root
|
||||
sendln "cp ./Blanton_Script/log/nfc_poll.log /host/hw-eval/jobs/"
|
||||
|
||||
if EN_TX_FIR = 1 then
|
||||
wait prompt_sonic_root
|
||||
sendln "cp ./Blanton_Script/log/blanton_dsc_ScriptA_u0.log /host/hw-eval/jobs/"
|
||||
wait prompt_sonic_root
|
||||
sendln "cp ./Blanton_Script/log/blanton_dsc_ScriptA_u1.log /host/hw-eval/jobs/"
|
||||
wait prompt_sonic_root
|
||||
sendln "cp ./Blanton_Script/log/blanton_dsc_ScriptC_u0.log /host/hw-eval/jobs/"
|
||||
wait prompt_sonic_root
|
||||
sendln "cp ./Blanton_Script/log/blanton_dsc_ScriptC_u1.log /host/hw-eval/jobs/"
|
||||
endif
|
||||
|
||||
wait prompt_sonic_root
|
||||
getdate ts_date "%Y%m%d"
|
||||
gettime ts_time "%H%M"
|
||||
sprintf2 usb_dst "/mnt/usb/jobs-%s_%s" ts_date ts_time
|
||||
sprintf2 cmd "cp -r /host/hw-eval/jobs/ %s" usb_dst
|
||||
sendln cmd
|
||||
|
||||
; ========== HW Test Session ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "exit"
|
||||
wait "Script done"
|
||||
wait prompt_sonic_root
|
||||
sendln "hw-test-session finish"
|
||||
wait prompt_sonic_root
|
||||
sendln "bgctl reset --yes"
|
||||
|
||||
messagebox 'GOOD JOB! Test Case DONE' 'teraterm'
|
||||
@@ -0,0 +1,164 @@
|
||||
include "config.ttl"
|
||||
|
||||
flushrecv
|
||||
;================================================================
|
||||
; Log File Creation
|
||||
;================================================================
|
||||
gettime str_starttime "%Y%m%d-%H%M%S"
|
||||
getdir mdir
|
||||
|
||||
if EN_log = 1 then
|
||||
sprintf2 filename '%s\Logs\%s_%s_%s.log' mdir project_name strTestcase str_starttime
|
||||
logopen filename 0 1 1 1
|
||||
endif
|
||||
|
||||
; ========== Root Login ==========
|
||||
wait prompt_login
|
||||
sendln "admin"
|
||||
wait "Password:"
|
||||
sendln "YourPaSsWoRd"
|
||||
wait prompt_sonic
|
||||
sendln "sudo -i"
|
||||
|
||||
; ========== Pre Setting ==========
|
||||
; Make log directory
|
||||
wait prompt_sonic_root
|
||||
sendln "mkdir ./logs"
|
||||
|
||||
; Setting System Time
|
||||
getdate datestr
|
||||
gettime timestr
|
||||
sprintf2 cmd 'sudo date -s "%s %s"' datestr timestr
|
||||
sendln cmd
|
||||
|
||||
;Stress log clear
|
||||
wait prompt_sonic_root
|
||||
sendln "rm /host/hw-eval/jobs/*"
|
||||
|
||||
; ========== HW Test Session ==========
|
||||
; Clear session
|
||||
wait prompt_sonic_root
|
||||
sendln "hw-test-session finish"
|
||||
wait prompt_sonic_root
|
||||
sendln "bgctl reset --yes"
|
||||
wait prompt_sonic_root
|
||||
sendln "bgctl stop --all"
|
||||
wait prompt_sonic_root
|
||||
sendln "bgctl list"
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "hw-test-session start"
|
||||
wait prompt_sonic_root
|
||||
sendln "hw-test-session log"
|
||||
wait prompt_sonic_root
|
||||
sendln "hw-test-session status"
|
||||
|
||||
; ========== FAN SPEED ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "echo 18-0020 > /sys/bus/i2c/drivers/max31790/unbind"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep .5"
|
||||
wait prompt_sonic_root
|
||||
sendln "echo 18-0020 > /sys/bus/i2c/drivers/max31790/bind"
|
||||
wait prompt_sonic_root
|
||||
sendln "echo 25-0020 > /sys/bus/i2c/drivers/max31790/unbind"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep .5"
|
||||
wait prompt_sonic_root
|
||||
sendln "echo 25-0020 > /sys/bus/i2c/drivers/max31790/bind"
|
||||
|
||||
wait prompt_sonic_root
|
||||
sprintf2 fan_ctrl_cmd 'fan-speed-control.sh %d' FAN_SPEED
|
||||
sendln fan_ctrl_cmd
|
||||
|
||||
wait "Set all configured fan channels to"
|
||||
sendln "y"
|
||||
|
||||
; ========== Wait DUT Init ==========
|
||||
include "utils/wait_init.ttl"
|
||||
|
||||
; ========== DUT Info ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "show boot"
|
||||
wait prompt_sonic_root
|
||||
sendln "show version"
|
||||
wait prompt_sonic_root
|
||||
sendln "fwutil show status"
|
||||
wait prompt_sonic_root
|
||||
sendln "show system-memory"
|
||||
wait prompt_sonic_root
|
||||
sendln "show service"
|
||||
wait prompt_sonic_root
|
||||
sendln "show platform syseeprom"
|
||||
wait prompt_sonic_root
|
||||
sendln "show platform ssdhealth"
|
||||
wait prompt_sonic_root
|
||||
sendln "qfx5252-tpm-version"
|
||||
wait prompt_sonic_root
|
||||
sendln "/usr/sbin/nvme smart-log -H /dev/nvme0"
|
||||
wait prompt_sonic_root
|
||||
sendln "/usr/sbin/smartctl -x /dev/nvme0"
|
||||
|
||||
; ========== BMC version ==========
|
||||
;wait prompt_sonic_root
|
||||
;sendln "bmc-manager run 'cat /etc/issue'"
|
||||
wait prompt_sonic_root
|
||||
sendln "bmc-first-enroll"
|
||||
wait prompt_sonic_root
|
||||
sendln "bmc-manager version"
|
||||
wait prompt_sonic_root
|
||||
sendln "bmc-manager status"
|
||||
|
||||
; ========== CLEAR PCIE Error ==========
|
||||
include "utils/show_pcie_error_reg_TH6_SWB0.ttl"
|
||||
include "utils/show_pcie_error_reg_TH6_SWB1.ttl"
|
||||
include "utils/show_pcie_error_reg_FPGA.ttl"
|
||||
include "utils/show_pcie_error_reg_BMC.ttl"
|
||||
include "utils/show_pcie_error_reg_DDR.ttl"
|
||||
include "utils/show_pcie_error_reg_I210.ttl"
|
||||
include "utils/show_pcie_error_reg_SSD.ttl"
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "/usr/sbin/ras-mc-ctl --summary"
|
||||
|
||||
; ========== Check PCIE tree + PCIE link status + GET PCIE bandwidth Test ==========
|
||||
include "utils/pcie_bus.ttl"
|
||||
|
||||
; ========== TAKE DATA ==========
|
||||
include "utils/setup_pmon.ttl"
|
||||
include "utils/show_dmesg.ttl"
|
||||
|
||||
; ========== Full Load ==========
|
||||
; AMD CPU STRESS TEST
|
||||
; Clear the log file first
|
||||
wait prompt_sonic_root
|
||||
sendln "> ~/hammer/tools/amd/mlucas_amm_log"
|
||||
wait prompt_sonic_root
|
||||
sendln 'chmod +x ~/hammer/tools/amd/mlucas-avx2'
|
||||
wait prompt_sonic_root
|
||||
;sendln "~/hammer/tools/amd/mlucas-avx2 -s l -cpu 0:15 > ~/hammer/tools/amd/mlucas_amm_log 2>&1 &"
|
||||
sendln "systemd-run --unit=mlucas-amm --property=Type=exec --property=Restart=always --property=RestartSec=2 /bin/bash -c '~/hammer/tools/amd/mlucas-avx2 -s l -cpu 0:15 >> ~/hammer/tools/amd/mlucas_amm_log 2>&1'"
|
||||
|
||||
; TR518 TEST
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/blanton_tr518.sh start"
|
||||
|
||||
while 1
|
||||
; Base info polling
|
||||
include "utils/setup_pmon.ttl"
|
||||
|
||||
; TH6 Power Polling
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/TH6_SWB0_power_readback.sh"
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/TH6_SWB1_power_readback.sh"
|
||||
|
||||
; Background jobs Check
|
||||
wait prompt_sonic_root
|
||||
sendln "bgctl list"
|
||||
wait prompt_sonic_root
|
||||
sendln "jobs"
|
||||
wait prompt_sonic_root
|
||||
sendln "systemctl is-active mlucas-amm"
|
||||
pause 60
|
||||
endwhile
|
||||
@@ -0,0 +1,419 @@
|
||||
include "config.ttl"
|
||||
|
||||
flushrecv
|
||||
;================================================================
|
||||
; Log File Creation
|
||||
;================================================================
|
||||
gettime str_starttime "%Y%m%d-%H%M%S"
|
||||
getdir mdir
|
||||
|
||||
if EN_log = 1 then
|
||||
sprintf2 filename '%s\Logs\%s_%s_%s.log' mdir project_name "Reboot_Cycle" str_starttime
|
||||
logopen filename 0 1 1 1
|
||||
endif
|
||||
|
||||
cnt_cycle = 0
|
||||
|
||||
while 1
|
||||
cnt_cycle = cnt_cycle + 1
|
||||
; ========== Root Login ==========
|
||||
wait prompt_login
|
||||
sendln "admin"
|
||||
wait "Password:"
|
||||
sendln "YourPaSsWoRd"
|
||||
wait prompt_sonic
|
||||
sendln "sudo -i"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 10"
|
||||
|
||||
wait prompt_sonic_root
|
||||
sprintf2 strTitle "echo -e '\033[1;32mReboot Cycle : %d \033[0m'" cnt_cycle
|
||||
sendln strTitle
|
||||
|
||||
; ========== Pre Setting ==========
|
||||
; Make log directory
|
||||
wait prompt_sonic_root
|
||||
sendln "mkdir ./logs"
|
||||
|
||||
; Setting System Time
|
||||
getdate datestr
|
||||
gettime timestr
|
||||
sprintf2 cmd 'sudo date -s "%s %s"' datestr timestr
|
||||
sendln cmd
|
||||
|
||||
; ========== FAN SPEED ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "echo 18-0020 > /sys/bus/i2c/drivers/max31790/unbind"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep .5"
|
||||
wait prompt_sonic_root
|
||||
sendln "echo 18-0020 > /sys/bus/i2c/drivers/max31790/bind"
|
||||
wait prompt_sonic_root
|
||||
sendln "echo 25-0020 > /sys/bus/i2c/drivers/max31790/unbind"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep .5"
|
||||
wait prompt_sonic_root
|
||||
sendln "echo 25-0020 > /sys/bus/i2c/drivers/max31790/bind"
|
||||
|
||||
wait prompt_sonic_root
|
||||
sprintf2 fan_ctrl_cmd 'fan-speed-control.sh %d' FAN_SPEED
|
||||
sendln fan_ctrl_cmd
|
||||
|
||||
wait "Set all configured fan channels to"
|
||||
sendln "y"
|
||||
|
||||
; ========== Wait DUT Init ==========
|
||||
include "utils/wait_init.ttl"
|
||||
|
||||
; ========== DUT Info ==========
|
||||
wait prompt_sonic_root
|
||||
sprintf2 strCKPt1 "echo -e '\033[36mCheck Pt1 : DUT Info\033[0m'"
|
||||
sendln strCKPt1
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "show boot"
|
||||
wait prompt_sonic_root
|
||||
sendln "show version"
|
||||
wait prompt_sonic_root
|
||||
sendln "fwutil show status"
|
||||
wait prompt_sonic_root
|
||||
sendln "show system-memory"
|
||||
wait prompt_sonic_root
|
||||
sendln "show service"
|
||||
wait prompt_sonic_root
|
||||
sendln "show platform syseeprom"
|
||||
wait prompt_sonic_root
|
||||
sendln "show platform ssdhealth"
|
||||
wait prompt_sonic_root
|
||||
sendln "qfx5252-tpm-version"
|
||||
wait prompt_sonic_root
|
||||
sendln "/usr/sbin/nvme smart-log -H /dev/nvme0"
|
||||
wait prompt_sonic_root
|
||||
sendln "/usr/sbin/smartctl -x /dev/nvme0"
|
||||
|
||||
; ========== BMC version ==========
|
||||
wait prompt_sonic_root
|
||||
sprintf2 strCKPt2 "echo -e '\033[36mCheck Pt2 : BMC Info\033[0m'"
|
||||
sendln strCKPt2
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "bmc-first-enroll"
|
||||
wait prompt_sonic_root
|
||||
sendln "bmc-manager version"
|
||||
wait prompt_sonic_root
|
||||
sendln "bmc-manager status"
|
||||
|
||||
; ========== Load Shell Script ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "source ~/Blanton_Script/blanton_fpga_pcimem.sh"
|
||||
wait prompt_sonic_root
|
||||
sendln "source ~/Blanton_Script/blanton_cb_i2c.sh"
|
||||
wait prompt_sonic_root
|
||||
sendln "source ~/Blanton_Script/blanton_icb_vi2c.sh"
|
||||
wait prompt_sonic_root
|
||||
sendln "source ~/Blanton_Script/blanton_pwr_data.sh"
|
||||
wait prompt_sonic_root
|
||||
sendln "source ~/Blanton_Script/blanton_traffic_linespeed.sh"
|
||||
wait prompt_sonic_root
|
||||
sendln "source ~/Blanton_Script/LTC2980_Margin_Script/margin.sh"
|
||||
|
||||
; ========== CLEAR PCIE Error ==========
|
||||
include "utils/show_pcie_error_reg_TH6_SWB0.ttl"
|
||||
include "utils/show_pcie_error_reg_TH6_SWB1.ttl"
|
||||
include "utils/show_pcie_error_reg_FPGA.ttl"
|
||||
include "utils/show_pcie_error_reg_BMC.ttl"
|
||||
include "utils/show_pcie_error_reg_DDR.ttl"
|
||||
include "utils/show_pcie_error_reg_I210.ttl"
|
||||
include "utils/show_pcie_error_reg_SSD.ttl"
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "/usr/sbin/ras-mc-ctl --summary"
|
||||
|
||||
; ========== Check PCIE tree + PCIE link status + GET PCIE bandwidth Test ==========
|
||||
include "utils/pcie_bus.ttl"
|
||||
|
||||
; ========== TAKE DATA ==========
|
||||
include "utils/setup_pmon.ttl"
|
||||
include "utils/show_dmesg.ttl"
|
||||
|
||||
; ========== 10G/1G MGMT Ping Test ==========
|
||||
wait prompt_sonic_root
|
||||
sprintf2 strCKPt3 "echo -e '\033[36mCheck Pt3 : Mgmt Ping Test\033[0m'"
|
||||
sendln strCKPt3
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/mgmt_ping_monitor.sh start"
|
||||
wait prompt_sonic_root
|
||||
pause 30
|
||||
sendln "~/Blanton_Script/mgmt_ping_monitor.sh stop"
|
||||
wait prompt_sonic_root
|
||||
sendln "cat ~/Blanton_Script/log/mgmt_ping.log"
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/mgmt_ping_monitor.sh clear"
|
||||
|
||||
; ========== NFC Test ==========
|
||||
wait prompt_sonic_root
|
||||
sprintf2 strCKPt4 "echo -e '\033[36mCheck Pt4 : NFC Test\033[0m'"
|
||||
sendln strCKPt4
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/nfc_polling.sh start"
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/nfc_polling.sh status"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 20"
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/nfc_polling.sh stop"
|
||||
wait prompt_sonic_root
|
||||
sendln "~/Blanton_Script/nfc_polling.sh report"
|
||||
|
||||
; ========== SSD read/write ==========
|
||||
wait prompt_sonic_root
|
||||
sprintf2 strCKPt5 "echo -e '\033[36mCheck Pt5 : SSD Test\033[0m'"
|
||||
sendln strCKPt5
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "qfx5252-stress-ssd 1G --runtime 30 --passes 2 --write --force --log /host/hw-eval/jobs/qfx5252-stress-ssd.log"
|
||||
wait prompt_sonic_root
|
||||
sendln "cat /host/hw-eval/jobs/qfx5252-stress-ssd.log"
|
||||
|
||||
; ========== USB read/write ==========
|
||||
wait prompt_sonic_root
|
||||
sprintf2 strCKPt6 "echo -e '\033[36mCheck Pt6 : USB Test\033[0m'"
|
||||
sendln strCKPt6
|
||||
|
||||
; ---- Get USB partition node -> usb_dev ----
|
||||
usb_dev = ''
|
||||
wait prompt_sonic_root
|
||||
sendln 'D=$(bash ~/Blanton_Script/usb_target.sh -o dev 2>/dev/null); echo "<<D""EV=${D:-NONE}>>"'
|
||||
waitregex '<<DEV=([^>]*)>>'
|
||||
usb_dev = groupmatchstr1
|
||||
|
||||
wait prompt_sonic_root
|
||||
sprintf2 cmd "qfx5252-stress-usb %s 256M --runtime 30 --passes 2 --write --log /host/hw-eval/jobs/qfx5252-stress-usb.log" usb_dev
|
||||
sendln cmd
|
||||
wait prompt_sonic_root
|
||||
sendln "cat /host/hw-eval/jobs/qfx5252-stress-usb.log"
|
||||
|
||||
; ========== BMC USB Test ==========
|
||||
wait prompt_sonic_root
|
||||
sprintf2 strCKPt7 "echo -e '\033[36mCheck Pt7 : BMC USB Test\033[0m'"
|
||||
sendln strCKPt7
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln 'echo "NCMIF=$(ls -d /sys/bus/usb/drivers/cdc_ncm/*/net/* 2>/dev/null | head -n 1 | xargs -r basename)"'
|
||||
; timeout is GLOBAL and sticky: left at 15, every 'wait' below gives up after
|
||||
; 15 s instead of blocking, the macro runs ahead of the DUT and the whole
|
||||
; cycle desynchronises. Restore it BEFORE the branch so both paths are
|
||||
; covered - the ping block below waits on 'sleep 10', which is already two
|
||||
; thirds of the 15 s cap on a loaded DUT.
|
||||
timeout = 15
|
||||
waitregex 'NCMIF=[A-Za-z0-9_-]+'
|
||||
ncm_found = result ; hold it: 'result' is reused below
|
||||
timeout = 0 ; restore, both paths
|
||||
if ncm_found = 0 then
|
||||
messagebox 'cdc_ncm interface not found. Ping test skipped.' 'ERROR'
|
||||
goto skip_ping
|
||||
endif
|
||||
strlen matchstr
|
||||
cut_len = result - 6 ; 'NCMIF=' = 6 chars
|
||||
strcopy matchstr 7 cut_len ncm_if ; -> ncm_if = "eth2" / "eth3"
|
||||
|
||||
sprintf2 cmd 'ip -br link show %s' ncm_if
|
||||
wait prompt_sonic_root
|
||||
sendln cmd
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln 'systemctl stop qfx5252-bmc-usb-net-test.service 2>/dev/null || true'
|
||||
wait prompt_sonic_root
|
||||
sendln 'systemctl reset-failed qfx5252-bmc-usb-net-test.service 2>/dev/null || true'
|
||||
sprintf2 cmd 'systemd-run --unit=qfx5252-bmc-usb-net-test --property=Type=exec /usr/bin/ping -I %s -i 1 -W 2 -w 14400 192.168.200.200' ncm_if
|
||||
wait prompt_sonic_root
|
||||
sendln cmd
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 10"
|
||||
wait prompt_sonic_root
|
||||
sendln "systemctl stop qfx5252-bmc-usb-net-test.service"
|
||||
wait prompt_sonic_root
|
||||
sendln "journalctl -u qfx5252-bmc-usb-net-test.service --no-pager"
|
||||
|
||||
:skip_ping
|
||||
timeout = 0 ; backstop, same as Script B
|
||||
|
||||
; ========== 100G Port Setting ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "sudo sfputil lpmode off Ethernet513"
|
||||
wait prompt_sonic_root
|
||||
sendln "sudo sfputil lpmode off Ethernet514"
|
||||
wait prompt_sonic_root
|
||||
sendln "config interface -n asic0 startup Ethernet513"
|
||||
wait prompt_sonic_root
|
||||
sendln "config interface -n asic1 startup Ethernet514"
|
||||
wait prompt_sonic_root
|
||||
sendln "config save -y"
|
||||
|
||||
; ========== First Traffic Test ==========
|
||||
; Silent MAC
|
||||
wait prompt_sonic_root
|
||||
sendln "config feature state lldp disabled"
|
||||
wait prompt_sonic_root
|
||||
sendln "config save -y"
|
||||
|
||||
; ========== 100G Port Status ==========
|
||||
wait prompt_sonic_root
|
||||
sprintf2 strCKPt8 "echo -e '\033[36mCheck Pt8 : Port Status and 15sec Traffic \033[0m'"
|
||||
sendln strCKPt8
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "show interfaces status Ethernet513,Ethernet514"
|
||||
|
||||
; ========== Traffic Test ==========
|
||||
if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed ps"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed init"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed clear"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed show"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed start"
|
||||
wait prompt_sonic_root
|
||||
pause 15
|
||||
sendln "blanton_traffic_linespeed stop"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed report"
|
||||
elseif SWB_UNIT0 = 1 && SWB_UNIT1 = 0 then
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed ps -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed init -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed clear -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed show -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed start -u 0"
|
||||
wait prompt_sonic_root
|
||||
pause 15
|
||||
sendln "blanton_traffic_linespeed stop -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed report -u 0"
|
||||
elseif SWB_UNIT0 = 0 && SWB_UNIT1 = 1 then
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed ps -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed init -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed clear -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed show -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed start -u 1"
|
||||
wait prompt_sonic_root
|
||||
pause 15
|
||||
sendln "blanton_traffic_linespeed stop -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "blanton_traffic_linespeed report -u 1"
|
||||
else
|
||||
|
||||
endif
|
||||
|
||||
; ========== BER ==========
|
||||
; PRBS takes the SerDes out of normal operation, so this runs AFTER the
|
||||
; traffic report. sleep 30 matches blanton_ber.sh BER_INTERVAL - reporting
|
||||
; earlier reads an interval that has not finished accumulating.
|
||||
wait prompt_sonic_root
|
||||
sprintf2 strCKPt8 "echo -e '\033[36mCheck Pt9 : BER Test \033[0m'"
|
||||
sendln strCKPt8
|
||||
|
||||
if SWB_UNIT0 = 1 && SWB_UNIT1 = 1 then
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh init"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh start"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 30"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh report"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh stop"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh clear"
|
||||
elseif SWB_UNIT0 = 1 && SWB_UNIT1 = 0 then
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh init -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh start -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 30"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh report -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh stop -u 0"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh clear -u 0"
|
||||
elseif SWB_UNIT0 = 0 && SWB_UNIT1 = 1 then
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh init -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh start -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "sleep 30"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh report -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh stop -u 1"
|
||||
wait prompt_sonic_root
|
||||
sendln "./Blanton_Script/blanton_ber.sh clear -u 1"
|
||||
else
|
||||
|
||||
endif
|
||||
|
||||
; ========== NVME Err Info ==========
|
||||
wait prompt_sonic_root
|
||||
sprintf2 strCKPt9 "echo -e '\033[36mCheck Pt10 : NVME Err Info \033[0m'"
|
||||
sendln strCKPt9
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "/usr/sbin/nvme smart-log -H /dev/nvme0"
|
||||
wait prompt_sonic_root
|
||||
sendln "/usr/sbin/smartctl -x /dev/nvme0"
|
||||
|
||||
; ========== TAKE DATA ==========
|
||||
wait prompt_sonic_root
|
||||
sprintf2 strCKPt10 "echo -e '\033[36mCheck Pt11 : Platform Data \033[0m'"
|
||||
sendln strCKPt10
|
||||
include "utils/setup_pmon.ttl"
|
||||
|
||||
wait prompt_sonic_root
|
||||
sprintf2 strCKPt12 "echo -e '\033[36mCheck Pt12 : Dmesg_i2c \033[0m'"
|
||||
sendln strCKPt12
|
||||
include "utils/show_dmesg.ttl"
|
||||
|
||||
; ========== Check PCIE error counters ==========
|
||||
wait prompt_sonic_root
|
||||
sprintf2 strCKPt13 "echo -e '\033[36mCheck Pt13 : PCIE Error Counters \033[0m'"
|
||||
sendln strCKPt13
|
||||
include "utils/show_pcie_error_reg_TH6_SWB0.ttl"
|
||||
include "utils/show_pcie_error_reg_TH6_SWB1.ttl"
|
||||
include "utils/show_pcie_error_reg_FPGA.ttl"
|
||||
include "utils/show_pcie_error_reg_BMC.ttl"
|
||||
include "utils/show_pcie_error_reg_DDR.ttl"
|
||||
include "utils/show_pcie_error_reg_I210.ttl"
|
||||
include "utils/show_pcie_error_reg_SSD.ttl"
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "/usr/sbin/ras-mc-ctl --summary"
|
||||
|
||||
; ========== Show Power on uptime ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "show uptime"
|
||||
|
||||
; ========== Show Power on uptime ==========
|
||||
wait prompt_sonic_root
|
||||
sendln "reboot"
|
||||
|
||||
wait "Booting in blind mode"
|
||||
endwhile
|
||||
@@ -14,6 +14,8 @@
|
||||
| `margin_operation <ch> <op>` | 只切 OPERATION register |
|
||||
| `margin_apply_profile <file>` | 批次套用 profile(套用在當前載入的 LTC2980) |
|
||||
| `margin_save` | 寫入 NVM(當前 LTC2980 的兩個 LTC2977 都寫) |
|
||||
| `margin_save all` | 對 `settings/` 底下**全部** LTC2980 寫入 NVM,結束後回到原本載入的那顆 |
|
||||
| `margin_save blanton` | **Blanton SONiC 專用**:18 顆 LTC2977 全部走原生 i2c bus 寫入,不需要 `margin_init` |
|
||||
| `margin_debug [on\|off]` | 開關 debug 模式(不帶參數則 toggle) |
|
||||
| `margin_log [on\|off]` | 開關 log 記錄(不帶參數則 toggle,預設開啟) |
|
||||
|
||||
@@ -70,16 +72,18 @@ margin_operation 0 high
|
||||
margin_operation 0 nominal
|
||||
|
||||
# 批次套用 profile(套在當前載入的 LTC2980)
|
||||
margin_apply_profile profiles/comboA.conf
|
||||
margin_apply_profile profiles/comboB.conf
|
||||
margin_apply_profile profiles/combo_SWB_CONN13_high.conf
|
||||
margin_apply_profile profiles/combo_SWB_CONN13_low.conf
|
||||
margin_apply_profile profiles/all_off.conf
|
||||
|
||||
# 切換到另一顆 LTC2980
|
||||
margin_init Blanton_SWB1_CONN16
|
||||
margin_apply_profile profiles/comboA.conf
|
||||
margin_apply_profile profiles/combo_SWB_CONN16_high.conf
|
||||
|
||||
# 儲存到 NVM(斷電後保留)
|
||||
margin_save
|
||||
margin_save # 只寫當前載入的那顆
|
||||
margin_save all # settings/ 底下 9 顆全部寫,最後自動切回原本那顆
|
||||
margin_save blanton # Blanton SONiC 專用捷徑,18 顆一次寫完(見下)
|
||||
```
|
||||
|
||||
## 一次掃所有 LTC2980
|
||||
@@ -104,7 +108,7 @@ BOARDS=(
|
||||
## 一次套 profile 到所有 LTC2980
|
||||
|
||||
`script/margin_apply_profile_all.sh` 對多顆 LTC2980 依 `BOARDS[i]` 配對
|
||||
`PROFILES[i]` 套用 profile(預設全部 `comboA`)。
|
||||
`PROFILES[i]` 套用 profile(預設 SWB 各用自己 CONN 的 `_high`,CB 用 `combo_high3`)。
|
||||
|
||||
```bash
|
||||
source script/margin_apply_profile_all.sh
|
||||
@@ -120,8 +124,8 @@ BOARDS=(
|
||||
)
|
||||
|
||||
PROFILES=(
|
||||
"comboA" # Blanton_CB_CONN13
|
||||
"comboB" # Blanton_SWB0_CONN13 ← 改成 comboB
|
||||
"combo_high3" # Blanton_CB_CONN13
|
||||
"combo_SWB_CONN13_high" # Blanton_SWB0_CONN13
|
||||
...
|
||||
)
|
||||
```
|
||||
@@ -129,18 +133,109 @@ PROFILES=(
|
||||
`PROFILES` 寫名字即可(不含路徑跟 `.conf`),script 會自動展開成
|
||||
`profiles/<name>.conf`。兩個陣列長度不一致會直接報錯。
|
||||
|
||||
## 一次把所有 LTC2980 寫入 NVM
|
||||
> ⚠️ **SWB 的 profile 是 per-CONN 的**:每個檔的百分比對應該片板子的軌,
|
||||
> 套到別的 CONN 會 margin 到錯的東西(而且不會報錯)。這裡不能全部填同一個名字。
|
||||
> HIGH / LOW 兩輪就是把 `_high` 全換成 `_low` 再跑一次。
|
||||
|
||||
`script/margin_save_all.sh` 對 `BOARDS` 列出的每顆 LTC2980 跑 `margin_save`。
|
||||
## 一次把所有 LTC2980 寫入 NVM
|
||||
|
||||
> ⚠️ `margin_save` 會把當前 margin / OV / UV 設定**永久寫入 NVM**,
|
||||
> 斷電後保留。執行前先用 `margin_status_all.sh` 確認狀態正確。
|
||||
|
||||
**全部 9 顆**直接用內建的:
|
||||
|
||||
```bash
|
||||
margin_save all
|
||||
```
|
||||
|
||||
依 `settings/*.conf` 的檔名順序跑,中途某顆失敗**不會停**(半套完成的狀態比全部試完更難查),
|
||||
最後印出「幾顆成功 / 哪幾顆失敗」的總結,並把 `margin_init` 切回你呼叫前載入的那顆。
|
||||
|
||||
**只寫其中幾顆**才需要 `script/margin_save_all.sh`,編 script 頂端的 `BOARDS` 陣列:
|
||||
|
||||
```bash
|
||||
source script/margin_save_all.sh
|
||||
```
|
||||
|
||||
要改寫哪幾顆,編 script 頂端的 `BOARDS` 陣列即可(同前述)。
|
||||
### 送出去的是什麼
|
||||
|
||||
`margin_save` 對每顆 LTC2977 送一次 `STORE_USER_ALL`(PMBus command `0x15`),
|
||||
**不分 page**(這是整顆晶片的命令),也**不帶 data byte** —— 它是 SMBus send-byte:
|
||||
|
||||
```bash
|
||||
i2cset -y 4 0x5C 0x15 c # CB CONN13(原生 bus 4)
|
||||
cb_pmbus_write 8 0x5C 0x15 # SWB0 CONN13(CB FPGA F3 Ch8)
|
||||
```
|
||||
|
||||
> v2.7.0 之前送的是 `0x15 0x00`(write-byte)。LTC2977 在 CB 上吃得下去,但那是零件寬容,
|
||||
> 不是規範。同時 v2.7.0 起會檢查回傳值 —— 以前 NACK 了還是印 `Change Saved`。
|
||||
|
||||
每顆之間會 `sleep $MARGIN_STORE_SETTLE`(預設 0.5 秒)。這不是量測值,是保守的保護:
|
||||
NVM 寫入需要時間,而這支工具**沒有**去 poll 零件的 busy bit。`margin_save all` 連續送 18 次,
|
||||
這個間隔就是唯一的緩衝。要關掉設成空字串即可。
|
||||
|
||||
## `margin_save blanton` — Blanton SONiC 專用
|
||||
|
||||
Blanton 這台把 CB FPGA F3 的 I2C 通道**同時掛成了原生 Linux i2c adapter**,
|
||||
所以 SWB 上的 LTC2977 不必走 `cb_pmbus_*` / pcimem,用 `i2cset` 直接打得到:
|
||||
|
||||
| FPGA F3 通道 | Linux bus | 板 / 接頭 |
|
||||
|---|---|---|
|
||||
| Ch6 | 13 | SWB0 CONN14 / CONN16 |
|
||||
| Ch8 | 15 | SWB0 CONN13 / CONN15 |
|
||||
| Ch7 | 14 | SWB1 CONN14 / CONN16 |
|
||||
| Ch9 | 16 | SWB1 CONN13 / CONN15 |
|
||||
| —(原生) | 4 | CB CONN13 |
|
||||
|
||||
因此 `margin_save blanton` 就是一張平表跑完 18 顆,**不需要 `margin_init`**、
|
||||
不做 FPGA 通道初始化、不做 probe,也不會動到你當前載入的那顆板子:
|
||||
|
||||
```bash
|
||||
margin_save blanton
|
||||
```
|
||||
|
||||
```
|
||||
CB CONN13 bus 4 0x5C : saved
|
||||
SWB0 CONN13 bus 15 0x5C : saved
|
||||
...
|
||||
margin_save blanton: 18 saved, 0 failed
|
||||
```
|
||||
|
||||
送出去的就是這 18 行(2026-08-27 上機驗證):
|
||||
|
||||
```bash
|
||||
i2cset -f -y 4 0x5C 0x15 ; i2cset -f -y 4 0x5E 0x15 # CB CONN13
|
||||
i2cset -f -y 15 0x5C 0x15 ; i2cset -f -y 15 0x5E 0x15 # SWB0 CONN13
|
||||
i2cset -f -y 13 0x5C 0x15 ; i2cset -f -y 13 0x5E 0x15 # SWB0 CONN14
|
||||
i2cset -f -y 15 0x62 0x15 ; i2cset -f -y 15 0x64 0x15 # SWB0 CONN15
|
||||
i2cset -f -y 13 0x62 0x15 ; i2cset -f -y 13 0x64 0x15 # SWB0 CONN16
|
||||
i2cset -f -y 16 0x5C 0x15 ; i2cset -f -y 16 0x5E 0x15 # SWB1 CONN13
|
||||
i2cset -f -y 14 0x5C 0x15 ; i2cset -f -y 14 0x5E 0x15 # SWB1 CONN14
|
||||
i2cset -f -y 16 0x62 0x15 ; i2cset -f -y 16 0x64 0x15 # SWB1 CONN15
|
||||
i2cset -f -y 14 0x62 0x15 ; i2cset -f -y 14 0x64 0x15 # SWB1 CONN16
|
||||
```
|
||||
|
||||
`-f` 是因為這些 bus 上的 LTC2977 可能已被 kernel driver 認走;上機驗證過的指令帶 `-f`,就照原樣保留。
|
||||
|
||||
**這台沒裝滿的話**,把 `margin.sh` 頂端 `MARGIN_BLANTON_STORE` 陣列裡對應的行註解掉即可,
|
||||
不要讓它去打不存在的板子。bus 節點不存在(`/dev/i2c-N` 沒有)與晶片不回應(NACK)
|
||||
會分別報不同訊息 —— 前者代表 FPGA 的 i2c adapter 根本沒 enumerate,後者才是板子的問題。
|
||||
|
||||
## Profile 一覽
|
||||
|
||||
| Profile | 適用 | 說明 |
|
||||
|---|---|---|
|
||||
| `combo_SWB_CONN13_high` / `_low` | **SWB CONN13 專用** | 每個 channel 依該板的軌給 3% 或 5% |
|
||||
| `combo_SWB_CONN14_high` / `_low` | **SWB CONN14 專用** | 同上 |
|
||||
| `combo_SWB_CONN15_high` / `_low` | **SWB CONN15 專用** | 同上 |
|
||||
| `combo_SWB_CONN16_high` / `_low` | **SWB CONN16 專用** | 同上 |
|
||||
| `combo_high3` / `combo_low3` | 通用 | 全部 channel ±3% |
|
||||
| `combo_high5` / `combo_low5` | 通用 | 全部 channel ±5% |
|
||||
| `combo_normal` | 通用 | 全部回 nominal |
|
||||
| `all_off` | 通用 | 全部 OPERATION off |
|
||||
|
||||
SWB0 和 SWB1 的同號 CONN 共用同一個 profile(兩片板的軌完全相同,
|
||||
只差 I2C bus)。CB CONN13 沒有專屬 profile,用通用的 `combo_high3` / `combo_low3`。
|
||||
|
||||
## Operation 對應
|
||||
|
||||
|
||||
+2456
File diff suppressed because it is too large
Load Diff
@@ -1,444 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# blanton_cb_i2c.sh -- CB FPGA (F3) I2C / PMBus over the OpenCores I2C master
|
||||
# =============================================================================
|
||||
# Version History:
|
||||
# V0.1.0 2026-06-16 CB sibling of blanton_icb_i2c.sh. Same OpenCores I2C
|
||||
# handshake, but the I2C block lives in CB FPGA *Function 3*
|
||||
# register space (base 0x300, stride 0x20, Ch0..Ch17), and
|
||||
# is reached via cb_fpga 3 <off> (direct PCIe BAR -> .3/resource0).
|
||||
# =============================================================================
|
||||
#
|
||||
# IMPORTANT (vs the hand-written cb_fpga.md pcimem commands):
|
||||
# * The CB I2C channels are on PCI **Function 3**, so the sysfs file is
|
||||
# .../0000:02:00.3/resource0 (NOT .0). cb_fpga 3 uses FUNCT3_RES for this.
|
||||
# * This tool uses **Repeated START** for reads (write reg pointer with WR only,
|
||||
# no STOP, then Sr + slave|R) so it works for the SMBus/PMBus parts (VRM,
|
||||
# EFUSE) as well as plain register parts. STOP+START only works for the latter.
|
||||
# * Slave addresses are 7-bit here. The spec lists 8-bit pairs (e.g. MAX31790
|
||||
# "0x40/0x41" -> 7-bit 0x20; TCA9546 "0xE8/0xE9" -> 7-bit 0x74). Divide by 2.
|
||||
#
|
||||
# CB FPGA F3 I2C channels (base 0x300, stride 0x20) -- 7-bit addrs in (...):
|
||||
# Ch0 0x300 SWB_0: TCA9546 mux (0x74), M0.C0 temp sensor, ...
|
||||
# Ch1 0x320 SWB_1: TCA9546 mux (0x74), ...
|
||||
# Ch2 0x340 SWB_0: SWB_FPGA (0x40), IO Exp PCA9555 (0x24), ...
|
||||
# Ch3 0x360 SWB_1: SWB_FPGA (0x40), PCA9555 (0x24), ...
|
||||
# Ch4 0x380 SWB_0: M1 TCA9546 mux (0x74), Clk Gen SI5..., ...
|
||||
# Ch5 0x3A0 SWB_1: M1 TCA9546 mux (0x74), ...
|
||||
# Ch6 0x3C0 SWB_0: VRM M29816 (0x20), VRM M2985B (0x21), ... [PMBus]
|
||||
# Ch7 0x3E0 SWB_1: VRM M29816 (0x20), VRM M2985B (0x21), ... [PMBus]
|
||||
# Ch8 0x400 SWB_0: VRM M2985B (0x25), M2985B (0x26), ... [PMBus]
|
||||
# Ch9 0x420 SWB_1: VRM M2985B (0x25), M2985B (0x26), ... [PMBus]
|
||||
# Ch10 0x440 M0 TCA9543 mux (0x70), M0.C0 Clk Buf 9DBL0452, ...
|
||||
# Ch11 0x460 Fan Ctrl MAX31790 (0x20)
|
||||
# Ch12 0x480 ADC leakage ADC128D818 (0x1F)
|
||||
# Ch13 0x4A0 NFC SM-MFAD4-C02 (0x28)
|
||||
# Ch14 0x4C0 M1 TCA9543 mux (0x70), M1.C0 QSFP28.P1 xcvr, ...
|
||||
# Ch15 0x4E0 Fan1/2 EFUSE STEF48H28 (0x10/0x11), ... [PMBus-ish]
|
||||
# Ch16 0x500 1G PHY I210 Ethernet ctrlr (0x49)
|
||||
# Ch17 0x520 Chassis EEPROM (0x28..0x29), Diag EEPROM (0x2B), ...
|
||||
# (slave 7-bit addrs derived from the 8-bit pairs in the register map; verify
|
||||
# against the device datasheet / your board before driving writes.)
|
||||
#
|
||||
# Per-channel register layout (offset from channel base):
|
||||
# +0x00 I2C_PRSCL_LO +0x04 I2C_PRSCL_HI +0x08 I2C_CTRL (bit7 MOD_EN)
|
||||
# +0x0C I2C_TX(W)/I2C_RX(R) +0x10 I2C_CMD(W)/I2C_STAT(R)
|
||||
# +0x14 I2C_MUX_SEL +0x18 I2C_RST (0xD) +0x1C SEM
|
||||
# CMD : STA=0x80 STO=0x40 RD=0x20 WR=0x10 ACK=0x08(1=NACK) IACK=0x01
|
||||
# STAT: RX_ACK=0x80(1=NACK) BUSY=0x40 ARB_LOST=0x20 TIP=0x02 INT_FLAG=0x01
|
||||
# Prescale = (in_clk/(5*scl))-1 @75MHz: 0x88=100kHz, 0x24=400kHz
|
||||
#
|
||||
# Usage:
|
||||
# source blanton_fpga_pcimem.sh # provides cb_fpga / fpga_debug
|
||||
# source blanton_cb_i2c.sh
|
||||
# cb_i2c_init 11 # Ch11 (Fan Ctrl) @100kHz
|
||||
# cb_i2c_scan 11
|
||||
# cb_i2c_read 11 0x20 0x01 1 # MAX31790 (7-bit 0x20) reg 0x01
|
||||
# cb_pmbus_read 6 0x20 0x8B 2 # Ch6 VRM READ_VOUT
|
||||
# =============================================================================
|
||||
|
||||
# --- Pull in the register-access backend (cb_fpga) if not present -----------
|
||||
if ! declare -F cb_fpga >/dev/null 2>&1; then
|
||||
_CBI2C_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
|
||||
if [ -n "$_CBI2C_DIR" ] && [ -f "$_CBI2C_DIR/blanton_fpga_pcimem.sh" ]; then
|
||||
# shellcheck source=/dev/null
|
||||
source "$_CBI2C_DIR/blanton_fpga_pcimem.sh"
|
||||
else
|
||||
echo -e "[\033[33mWARN\033[0m] blanton_cb_i2c.sh: cb_fpga() not found." >&2
|
||||
echo " source blanton_fpga_pcimem.sh first (provides cb_fpga)." >&2
|
||||
fi
|
||||
fi
|
||||
|
||||
# === CB I2C geometry =========================================================
|
||||
CBI2C_FN=3 # CB PCI Function hosting the I2C block
|
||||
CBI2C_BASE=0x300 # channel 0 base offset (relative to F3 resource0)
|
||||
CBI2C_CH_STRIDE=0x20
|
||||
CBI2C_CH_MAX=17
|
||||
|
||||
# Per-channel register offsets
|
||||
_CBI2C_PRSCL_LO=0x00
|
||||
_CBI2C_PRSCL_HI=0x04
|
||||
_CBI2C_CTRL=0x08
|
||||
_CBI2C_TX=0x0C
|
||||
_CBI2C_RX=0x0C
|
||||
_CBI2C_CMD=0x10
|
||||
_CBI2C_STAT=0x10
|
||||
_CBI2C_MUX_SEL=0x14
|
||||
_CBI2C_RST=0x18
|
||||
_CBI2C_SEM=0x1C
|
||||
|
||||
# I2C_CTRL_REG / CMD / STAT bits
|
||||
_CBI2C_EN=0x80
|
||||
_CBI2C_STA=0x80
|
||||
_CBI2C_STO=0x40
|
||||
_CBI2C_RD=0x20
|
||||
_CBI2C_WR=0x10
|
||||
_CBI2C_NACK=0x08
|
||||
_CBI2C_RXACK=0x80
|
||||
_CBI2C_TIP=0x02
|
||||
_CBI2C_RST_VAL=0xD
|
||||
|
||||
# Defaults
|
||||
CB_I2C_PRESCALE_LO="${CB_I2C_PRESCALE_LO:-0x88}" # 100 kHz @ 75 MHz
|
||||
CB_I2C_PRESCALE_HI="${CB_I2C_PRESCALE_HI:-0x00}"
|
||||
CB_I2C_AUTO_INIT="${CB_I2C_AUTO_INIT:-1}"
|
||||
CB_I2C_TIP_POLL_MAX="${CB_I2C_TIP_POLL_MAX:-100}"
|
||||
|
||||
# --- External I2C-mux RESET control (verified on COM34, 2026-06-16) ----------
|
||||
# The TCA9543 muxes on CH10 (M0) and CH14 (M1) have an FPGA-driven, active-low
|
||||
# RESET line. On power-up / FPGA reload the FPGA holds them in reset, so 0x70
|
||||
# does NOT ACK on the root bus and all downstream legs are unreachable.
|
||||
#
|
||||
# The control is a GLOBAL register in CB FPGA *Function 0*, offset 0x7D4
|
||||
# (I2C_MUX_RST_REG) -- NOT the per-channel I2C_MUX_SEL_REG (+0x14) which is a
|
||||
# device-select and does nothing to the RESET pin. Per bit: 1 = release,
|
||||
# 0 = hold-in-reset. Observed default 0xDD (bit1=CH10 mux, bit5=CH14 mux held).
|
||||
# Writing 0xFF releases all external muxes (normal operating state). This value
|
||||
# is volatile and is lost on the next power cycle / FPGA reload.
|
||||
CBI2C_MUX_RST_FN="${CBI2C_MUX_RST_FN:-0}"
|
||||
CBI2C_MUX_RST_OFF="${CBI2C_MUX_RST_OFF:-0x7D4}"
|
||||
|
||||
# Channels whose root bus carries an external mux that hangs off the RESET reg.
|
||||
# CH10/CH14 = TCA9543; CH0/1/4/5 = TCA9546 (SWB/M1) per the channel map above.
|
||||
CBI2C_MUX_CHANNELS="${CBI2C_MUX_CHANNELS:-0 1 4 5 10 14}"
|
||||
|
||||
# Auto-release external mux RESET before scanning / mux-writing a mux channel.
|
||||
CB_I2C_AUTO_MUX_RST="${CB_I2C_AUTO_MUX_RST:-1}"
|
||||
|
||||
# --- Single FPGA register read/write via cb_fpga <fn> <off> [data] ----------
|
||||
# _cbi2c_reg <abs_offset> [data] data present = write, absent = read (echo hex)
|
||||
_cbi2c_reg() {
|
||||
local off="$1" data="${2:-}"
|
||||
if [ -n "$data" ]; then cb_fpga "$CBI2C_FN" "$off" "$data"; else cb_fpga "$CBI2C_FN" "$off"; fi
|
||||
}
|
||||
|
||||
# Channel base absolute offset
|
||||
_cbi2c_chan_base() {
|
||||
local ch="$1"
|
||||
if (( ch < 0 || ch > CBI2C_CH_MAX )); then
|
||||
echo "blanton_cb_i2c: ch must be 0..$CBI2C_CH_MAX" >&2; return 1
|
||||
fi
|
||||
printf '0x%X' $(( CBI2C_BASE + ch * CBI2C_CH_STRIDE ))
|
||||
}
|
||||
|
||||
# Normalize a register read-back to a number string ("0x...." -> 0x....)
|
||||
_cbi2c_num() { local v="$1"; [[ "$v" =~ (0[xX][0-9a-fA-F]+) ]] && echo "${BASH_REMATCH[1]}" || echo "0"; }
|
||||
|
||||
# Write CMD then poll STAT (same offset) until TIP clears; echo final status hex
|
||||
_cbi2c_cmd_wait() {
|
||||
local cmd_off="$1" cmd_val="$2" i status
|
||||
_cbi2c_reg "$cmd_off" "$cmd_val" >/dev/null
|
||||
for (( i=0; i<CB_I2C_TIP_POLL_MAX; i++ )); do
|
||||
status=$(_cbi2c_num "$(_cbi2c_reg "$cmd_off")")
|
||||
if (( (status & _CBI2C_TIP) == 0 )); then
|
||||
printf '0x%X' "$status"; return 0
|
||||
fi
|
||||
done
|
||||
echo -e "[\033[31mERR\033[0m] CB I2C TIP timeout (status=$status)" >&2
|
||||
printf '0x%X' "${status:-0}"; return 1
|
||||
}
|
||||
|
||||
# Check RX_ACK in status (bit7). 0 = ACK, 1 = NACK -> return 1
|
||||
_cbi2c_check_ack() {
|
||||
local status; status=$(_cbi2c_num "$1")
|
||||
(( (status & _CBI2C_RXACK) != 0 )) && return 1 || return 0
|
||||
}
|
||||
|
||||
# === Public: init / reset / semaphore / mux-sel =============================
|
||||
|
||||
# cb_i2c_init <ch> [prescale_lo] [prescale_hi]
|
||||
cb_i2c_init() {
|
||||
[[ $# -lt 1 ]] && { echo "Usage: cb_i2c_init <ch> [prescale_lo] [prescale_hi]"; return 1; }
|
||||
local ch="$1" lo="${2:-$CB_I2C_PRESCALE_LO}" hi="${3:-$CB_I2C_PRESCALE_HI}" base
|
||||
base=$(_cbi2c_chan_base "$ch") || return 1
|
||||
_cbi2c_reg "$(printf '0x%X' $((base + _CBI2C_CTRL)))" 0x00 >/dev/null # disable
|
||||
_cbi2c_reg "$(printf '0x%X' $((base + _CBI2C_PRSCL_LO)))" "$lo" >/dev/null
|
||||
_cbi2c_reg "$(printf '0x%X' $((base + _CBI2C_PRSCL_HI)))" "$hi" >/dev/null
|
||||
_cbi2c_reg "$(printf '0x%X' $((base + _CBI2C_CTRL)))" "$_CBI2C_EN" >/dev/null # enable
|
||||
return 0
|
||||
}
|
||||
|
||||
# cb_i2c_reset <ch>
|
||||
cb_i2c_reset() {
|
||||
[[ $# -lt 1 ]] && { echo "Usage: cb_i2c_reset <ch>"; return 1; }
|
||||
local ch="$1" base; base=$(_cbi2c_chan_base "$ch") || return 1
|
||||
_cbi2c_reg "$(printf '0x%X' $((base + _CBI2C_RST)))" "$_CBI2C_RST_VAL" >/dev/null
|
||||
echo " [RST] ch=$ch local I2C controller reset (0xD)"
|
||||
}
|
||||
|
||||
# cb_i2c_sem <ch> [status|acquire [val]|release]
|
||||
cb_i2c_sem() {
|
||||
[[ $# -lt 1 ]] && { echo "Usage: cb_i2c_sem <ch> [status|acquire [val]|release]"; return 1; }
|
||||
local ch="$1" act="${2:-status}" base off cur
|
||||
base=$(_cbi2c_chan_base "$ch") || return 1
|
||||
off=$(printf '0x%X' $((base + _CBI2C_SEM)))
|
||||
case "$act" in
|
||||
status)
|
||||
cur=$(_cbi2c_num "$(_cbi2c_reg "$off")")
|
||||
(( (cur & 0xFF) == 0 )) && echo " [SEM] ch=$ch free (0x00)" \
|
||||
|| printf ' [SEM] ch=%s held (0x%02X)\n' "$ch" $((cur & 0xFF)) ;;
|
||||
acquire)
|
||||
local val="${3:-0x01}"
|
||||
cur=$(_cbi2c_num "$(_cbi2c_reg "$off")")
|
||||
if (( (cur & 0xFF) != 0 )); then
|
||||
printf ' [SEM] ch=%s already held (0x%02X) -- not acquired\n' "$ch" $((cur & 0xFF)); return 1
|
||||
fi
|
||||
_cbi2c_reg "$off" "$val" >/dev/null
|
||||
cur=$(_cbi2c_num "$(_cbi2c_reg "$off")")
|
||||
(( (cur & 0xFF) != 0 )) && printf ' [SEM] ch=%s acquired (0x%02X)\n' "$ch" $((cur & 0xFF)) \
|
||||
|| { echo " [SEM] ch=$ch acquire failed"; return 1; } ;;
|
||||
release)
|
||||
_cbi2c_reg "$off" 0x00 >/dev/null; echo " [SEM] ch=$ch released (0x00)" ;;
|
||||
*) echo "Usage: cb_i2c_sem <ch> [status|acquire [val]|release]"; return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# cb_i2c_muxsel <ch> <dev_sel> -- write I2C_MUX_SEL_REG (FPGA drives ext mux pins)
|
||||
cb_i2c_muxsel() {
|
||||
[[ $# -lt 2 ]] && { echo "Usage: cb_i2c_muxsel <ch> <dev_sel>"; return 1; }
|
||||
local ch="$1" sel="$2" base; base=$(_cbi2c_chan_base "$ch") || return 1
|
||||
_cbi2c_reg "$(printf '0x%X' $((base + _CBI2C_MUX_SEL)))" "$sel" >/dev/null
|
||||
printf ' [MUXSEL] ch=%s DEV_SEL <= 0x%02X\n' "$ch" $((sel & 0xFF))
|
||||
}
|
||||
|
||||
# cb_i2c_mux_reset_release -- de-assert ALL external mux RESET lines (F0 0x7D4 <= 0xFF)
|
||||
# Global, not per-channel. Volatile: lost on power cycle / FPGA reload.
|
||||
cb_i2c_mux_reset_release() {
|
||||
cb_fpga "$CBI2C_MUX_RST_FN" "$CBI2C_MUX_RST_OFF" 0xFF >/dev/null
|
||||
local rb; rb=$(_cbi2c_num "$(cb_fpga "$CBI2C_MUX_RST_FN" "$CBI2C_MUX_RST_OFF")")
|
||||
printf ' [MUX-RST] I2C_MUX_RST_REG (F%s %s) <= 0xFF (all external muxes released, readback %s)\n' \
|
||||
"$CBI2C_MUX_RST_FN" "$CBI2C_MUX_RST_OFF" "$rb"
|
||||
}
|
||||
|
||||
# _cbi2c_is_mux_channel <ch> -- 0 (true) if ch is in CBI2C_MUX_CHANNELS
|
||||
_cbi2c_is_mux_channel() {
|
||||
local ch="$1" c
|
||||
for c in $CBI2C_MUX_CHANNELS; do [[ "$c" == "$ch" ]] && return 0; done
|
||||
return 1
|
||||
}
|
||||
|
||||
# _cbi2c_auto_mux_rst <ch> -- release external mux RESET if ch is a mux channel
|
||||
_cbi2c_auto_mux_rst() {
|
||||
[[ "$CB_I2C_AUTO_MUX_RST" == "1" ]] || return 0
|
||||
_cbi2c_is_mux_channel "$1" || return 0
|
||||
cb_i2c_mux_reset_release
|
||||
}
|
||||
|
||||
# === Core transfers (Repeated START, SMBus/PMBus compatible) =================
|
||||
|
||||
# _cbi2c_xfer_read <ch> <slave7> <reg> <nbytes> echoes space-separated hex bytes
|
||||
_cbi2c_xfer_read() {
|
||||
local ch="$1" slave="$2" reg="$3" n="$4" base tx cmd rx status i last cmdv val out=""
|
||||
base=$(_cbi2c_chan_base "$ch") || return 1
|
||||
tx=$(printf '0x%X' $((base + _CBI2C_TX)))
|
||||
cmd=$(printf '0x%X' $((base + _CBI2C_CMD)))
|
||||
rx=$(printf '0x%X' $((base + _CBI2C_RX)))
|
||||
[[ "$CB_I2C_AUTO_INIT" == "1" ]] && cb_i2c_init "$ch" >/dev/null
|
||||
|
||||
_cbi2c_reg "$tx" "$(printf '0x%X' $(( (slave << 1) & 0xFF )))" >/dev/null
|
||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_STA | _CBI2C_WR)))")
|
||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on slave addr (W) 0x$(printf %02X "$slave")" >&2; return 1; }
|
||||
|
||||
_cbi2c_reg "$tx" "$(printf '0x%X' $((reg & 0xFF)))" >/dev/null
|
||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_WR)))") # WR only, no STOP
|
||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on reg 0x$(printf %02X "$reg")" >&2; return 1; }
|
||||
|
||||
_cbi2c_reg "$tx" "$(printf '0x%X' $(( ((slave << 1) | 1) & 0xFF )))" >/dev/null
|
||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_STA | _CBI2C_WR)))") # Repeated START
|
||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on slave addr (R) 0x$(printf %02X "$slave")" >&2; return 1; }
|
||||
|
||||
for (( i=0; i<n; i++ )); do
|
||||
last=$(( i == n-1 ))
|
||||
if (( last )); then cmdv=$(( _CBI2C_RD | _CBI2C_NACK | _CBI2C_STO )); else cmdv=$(( _CBI2C_RD )); fi
|
||||
_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' "$cmdv")" >/dev/null
|
||||
val=$(_cbi2c_num "$(_cbi2c_reg "$rx")")
|
||||
out+="$(printf '0x%02X ' $((val & 0xFF)))"
|
||||
done
|
||||
echo "${out% }"
|
||||
}
|
||||
|
||||
# _cbi2c_xfer_write <ch> <slave7> <reg> <byte> [byte...]
|
||||
_cbi2c_xfer_write() {
|
||||
local ch="$1" slave="$2" reg="$3"; shift 3
|
||||
local base tx cmd status b last cmdv n=$# idx=0
|
||||
[[ $n -lt 1 ]] && { echo "ERR: no data bytes" >&2; return 1; }
|
||||
base=$(_cbi2c_chan_base "$ch") || return 1
|
||||
tx=$(printf '0x%X' $((base + _CBI2C_TX)))
|
||||
cmd=$(printf '0x%X' $((base + _CBI2C_CMD)))
|
||||
[[ "$CB_I2C_AUTO_INIT" == "1" ]] && cb_i2c_init "$ch" >/dev/null
|
||||
|
||||
_cbi2c_reg "$tx" "$(printf '0x%X' $(( (slave << 1) & 0xFF )))" >/dev/null
|
||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_STA | _CBI2C_WR)))")
|
||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on slave addr (W) 0x$(printf %02X "$slave")" >&2; return 1; }
|
||||
|
||||
_cbi2c_reg "$tx" "$(printf '0x%X' $((reg & 0xFF)))" >/dev/null
|
||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_WR)))")
|
||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on reg 0x$(printf %02X "$reg")" >&2; return 1; }
|
||||
|
||||
for b in "$@"; do
|
||||
idx=$((idx+1)); last=$(( idx == n ))
|
||||
_cbi2c_reg "$tx" "$(printf '0x%X' $(( $((b)) & 0xFF )))" >/dev/null
|
||||
if (( last )); then cmdv=$(( _CBI2C_WR | _CBI2C_STO )); else cmdv=$(( _CBI2C_WR )); fi
|
||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' "$cmdv")")
|
||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on data byte #$idx" >&2; return 1; }
|
||||
done
|
||||
return 0
|
||||
}
|
||||
|
||||
# _cbi2c_xfer_cmd_only <ch> <slave7> <cmd> -- START+W, cmd byte, STOP (no data)
|
||||
_cbi2c_xfer_cmd_only() {
|
||||
local ch="$1" slave="$2" cc="$3" base tx cmd status
|
||||
base=$(_cbi2c_chan_base "$ch") || return 1
|
||||
tx=$(printf '0x%X' $((base + _CBI2C_TX)))
|
||||
cmd=$(printf '0x%X' $((base + _CBI2C_CMD)))
|
||||
[[ "$CB_I2C_AUTO_INIT" == "1" ]] && cb_i2c_init "$ch" >/dev/null
|
||||
_cbi2c_reg "$tx" "$(printf '0x%X' $(( (slave << 1) & 0xFF )))" >/dev/null
|
||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_STA | _CBI2C_WR)))")
|
||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on slave addr (W) 0x$(printf %02X "$slave")" >&2; return 1; }
|
||||
_cbi2c_reg "$tx" "$(printf '0x%X' $((cc & 0xFF)))" >/dev/null
|
||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_WR | _CBI2C_STO)))")
|
||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on cmd 0x$(printf %02X "$cc")" >&2; return 1; }
|
||||
return 0
|
||||
}
|
||||
|
||||
# === Public: generic I2C =====================================================
|
||||
|
||||
# cb_i2c_read <ch> <slave> <reg> [nbytes]
|
||||
cb_i2c_read() {
|
||||
[[ $# -lt 3 ]] && { echo "Usage: cb_i2c_read <ch> <slave> <reg> [nbytes]"; return 1; }
|
||||
local ch="$1" slave=$(( $2 )) reg=$(( $3 )) n="${4:-1}" bytes
|
||||
bytes=$(_cbi2c_xfer_read "$ch" "$slave" "$reg" "$n") || return 1
|
||||
printf ' [I2C-R] ch=%s slave=0x%02X reg=0x%02X => [%s]\n' "$ch" "$slave" "$reg" "$bytes"
|
||||
}
|
||||
|
||||
# cb_i2c_write <ch> <slave> <reg> <byte> [byte...]
|
||||
cb_i2c_write() {
|
||||
[[ $# -lt 4 ]] && { echo "Usage: cb_i2c_write <ch> <slave> <reg> <byte> [byte...]"; return 1; }
|
||||
local ch="$1" slave=$(( $2 )) reg=$(( $3 )); shift 3
|
||||
_cbi2c_xfer_write "$ch" "$slave" "$reg" "$@" || return 1
|
||||
printf ' [I2C-W] ch=%s slave=0x%02X reg=0x%02X <= [%s]\n' "$ch" "$slave" "$reg" "$*"
|
||||
}
|
||||
|
||||
# cb_i2c_muxwrite <ch> <mux_slave> <ctrl_byte> -- raw 1-byte write, no reg (TCA954x)
|
||||
cb_i2c_muxwrite() {
|
||||
[[ $# -lt 3 ]] && { echo "Usage: cb_i2c_muxwrite <ch> <mux_slave> <ctrl_byte>"; return 1; }
|
||||
local ch="$1" slave=$(( $2 )) val=$(( $3 )) base tx cmd status
|
||||
base=$(_cbi2c_chan_base "$ch") || return 1
|
||||
tx=$(printf '0x%X' $((base + _CBI2C_TX)))
|
||||
cmd=$(printf '0x%X' $((base + _CBI2C_CMD)))
|
||||
[[ "$CB_I2C_AUTO_INIT" == "1" ]] && cb_i2c_init "$ch" >/dev/null
|
||||
_cbi2c_auto_mux_rst "$ch"
|
||||
_cbi2c_reg "$tx" "$(printf '0x%X' $(( (slave << 1) & 0xFF )))" >/dev/null
|
||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_STA | _CBI2C_WR)))")
|
||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on mux addr 0x$(printf %02X "$slave")" >&2; return 1; }
|
||||
_cbi2c_reg "$tx" "$(printf '0x%X' $((val & 0xFF)))" >/dev/null
|
||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_WR | _CBI2C_STO)))")
|
||||
_cbi2c_check_ack "$status" || { echo "ERR: NACK on mux ctrl byte" >&2; return 1; }
|
||||
printf ' [MUX-W] ch=%s mux=0x%02X <= 0x%02X\n' "$ch" "$slave" "$val"
|
||||
}
|
||||
|
||||
# cb_i2c_scan <ch> -- probe 0x08..0x77, report slaves that ACK
|
||||
cb_i2c_scan() {
|
||||
[[ $# -lt 1 ]] && { echo "Usage: cb_i2c_scan <ch>"; return 1; }
|
||||
local ch="$1" base tx cmd a status found=""
|
||||
base=$(_cbi2c_chan_base "$ch") || return 1
|
||||
tx=$(printf '0x%X' $((base + _CBI2C_TX)))
|
||||
cmd=$(printf '0x%X' $((base + _CBI2C_CMD)))
|
||||
cb_i2c_init "$ch" >/dev/null
|
||||
_cbi2c_auto_mux_rst "$ch"
|
||||
for (( a=0x08; a<=0x77; a++ )); do
|
||||
_cbi2c_reg "$tx" "$(printf '0x%X' $(( (a << 1) & 0xFF )))" >/dev/null
|
||||
status=$(_cbi2c_cmd_wait "$cmd" "$(printf '0x%X' $((_CBI2C_STA | _CBI2C_WR | _CBI2C_STO)))")
|
||||
_cbi2c_check_ack "$status" && found+="$(printf '0x%02X ' "$a")"
|
||||
done
|
||||
[[ -n "$found" ]] && echo " [SCAN] ch=$ch found: ${found% }" || echo " [SCAN] ch=$ch no devices"
|
||||
}
|
||||
|
||||
# === Public: PMBus (== SMBus; command code + Repeated START read) ============
|
||||
|
||||
# cb_pmbus_read <ch> <slave> <cmd> [nbytes] (default 2 bytes, LSB first)
|
||||
cb_pmbus_read() {
|
||||
[[ $# -lt 3 ]] && { echo "Usage: cb_pmbus_read <ch> <slave> <cmd> [nbytes]"; return 1; }
|
||||
local ch="$1" slave=$(( $2 )) cc=$(( $3 )) n="${4:-2}" bytes
|
||||
bytes=$(_cbi2c_xfer_read "$ch" "$slave" "$cc" "$n") || return 1
|
||||
if [[ "$n" == "2" ]]; then
|
||||
local b0 b1 word; b0=$(( $(echo "$bytes" | awk '{print $1}') )); b1=$(( $(echo "$bytes" | awk '{print $2}') ))
|
||||
word=$(( b0 | (b1 << 8) ))
|
||||
printf ' [PMB-R] ch=%s slave=0x%02X cmd=0x%02X => 0x%04X raw=[%s] linear16=%s\n' \
|
||||
"$ch" "$slave" "$cc" "$word" "$bytes" "$(cb_pmbus_linear16 "$word")"
|
||||
else
|
||||
printf ' [PMB-R] ch=%s slave=0x%02X cmd=0x%02X => [%s]\n' "$ch" "$slave" "$cc" "$bytes"
|
||||
fi
|
||||
}
|
||||
|
||||
# cb_pmbus_write <ch> <slave> <cmd> [data byte...] (no byte = send-byte)
|
||||
cb_pmbus_write() {
|
||||
[[ $# -lt 3 ]] && { echo "Usage: cb_pmbus_write <ch> <slave> <cmd> [data byte...]"; return 1; }
|
||||
local ch="$1" slave=$(( $2 )) cc=$(( $3 )); shift 3
|
||||
if [[ $# -eq 0 ]]; then
|
||||
_cbi2c_xfer_cmd_only "$ch" "$slave" "$cc" || return 1
|
||||
printf ' [PMB-W] ch=%s slave=0x%02X cmd=0x%02X <= (send-byte)\n' "$ch" "$slave" "$cc"; return 0
|
||||
fi
|
||||
_cbi2c_xfer_write "$ch" "$slave" "$cc" "$@" || return 1
|
||||
printf ' [PMB-W] ch=%s slave=0x%02X cmd=0x%02X <= [%s]\n' "$ch" "$slave" "$cc" "$*"
|
||||
}
|
||||
|
||||
# cb_pmbus_linear16 <word>
|
||||
cb_pmbus_linear16() {
|
||||
local word=$(( $1 & 0xFFFF ))
|
||||
awk -v w="$word" 'BEGIN{
|
||||
e=int(w/2048)%32; if(e>15)e-=32;
|
||||
m=w%2048; if(m>1023)m-=2048;
|
||||
printf "%.4f", m * (2.0 ^ e);
|
||||
}'
|
||||
}
|
||||
|
||||
# === Help ====================================================================
|
||||
blanton_cb_i2c_help() {
|
||||
echo -e "\033[1mblanton_cb_i2c.sh - CB FPGA (F3) I2C / PMBus over OpenCores I2C master\033[0m"
|
||||
echo ""
|
||||
echo -e " Backend: \033[36mcb_fpga $CBI2C_FN\033[0m (direct PCIe BAR -> .3/resource0), base 0x300, Ch0..$CBI2C_CH_MAX"
|
||||
echo ""
|
||||
echo -e "\033[1mSetup\033[0m"
|
||||
echo -e " \033[33mcb_i2c_init\033[0m <ch> [pre_lo] [pre_hi] prescale + enable (def 0x88/0x00 = 100kHz)"
|
||||
echo -e " \033[33mcb_i2c_reset\033[0m <ch> LCL_RST=0xD"
|
||||
echo -e " \033[33mcb_i2c_sem\033[0m <ch> [status|acquire [v]|release]"
|
||||
echo -e " \033[33mcb_i2c_muxsel\033[0m <ch> <dev_sel> write I2C_MUX_SEL_REG"
|
||||
echo -e " \033[33mcb_i2c_mux_reset_release\033[0m de-assert ALL ext mux RESET (F0 0x7D4<=0xFF)"
|
||||
echo ""
|
||||
echo -e "\033[1mGeneric I2C\033[0m"
|
||||
echo -e " \033[33mcb_i2c_scan\033[0m <ch>"
|
||||
echo -e " \033[33mcb_i2c_read\033[0m <ch> <slave> <reg> [nbytes]"
|
||||
echo -e " \033[33mcb_i2c_write\033[0m <ch> <slave> <reg> <byte> [byte...]"
|
||||
echo -e " \033[33mcb_i2c_muxwrite\033[0m <ch> <mux_slave> <ctrl_byte> raw 1-byte (TCA954x)"
|
||||
echo ""
|
||||
echo -e "\033[1mPMBus / SMBus\033[0m"
|
||||
echo -e " \033[33mcb_pmbus_read\033[0m <ch> <slave> <cmd> [nbytes] (def 2, LE word + linear16)"
|
||||
echo -e " \033[33mcb_pmbus_write\033[0m <ch> <slave> <cmd> [byte...]"
|
||||
echo -e " \033[33mcb_pmbus_linear16\033[0m <word>"
|
||||
echo ""
|
||||
echo -e " Slave = 7-bit (tool shifts). Spec lists 8-bit pairs -> divide by 2."
|
||||
echo -e " \033[33mfpga_debug on\033[0m to see every underlying pcimem command."
|
||||
}
|
||||
|
||||
blanton_cb_i2c_help
|
||||
@@ -1,270 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# blanton_fpga_pcimem.sh -- pcimem backend, sysfs resource file + relative offset
|
||||
# =============================================================================
|
||||
# Version History:
|
||||
# V1.3.0 2026-06-12 pcimem variant (SONiC hardware). memtool variant: blanton_fpga_memtool.sh
|
||||
# Version number kept in sync with blanton_fpga_memtool.sh
|
||||
# V1.4.0 2026-06-15 Fix: VSPI window bases pointed at the VSPI-Flash block
|
||||
# (0x340/0x380/0x3C0/0x400, config-flash channel) so register
|
||||
# reads returned 0; corrected to the VSPI register block
|
||||
# (PMC 0x640 / ICB 0x680 / SWB0 0x6C0 / SWB1 0x700)
|
||||
# Add: _vspi_fnwarn guard - warns when PMC/ICB/SWB are called with
|
||||
# cb_fpga-style "<fn> <addr>" (a read turning into a write)
|
||||
# Change: suppress pcimem write stdout noise (mmap/Written lines)
|
||||
# Docs: comments/help translated to English (ASCII-only for SONiC console)
|
||||
# V1.4.1 2026-06-23 Fix: BDF in example auto-detect was wrong (02:00 vs 04:00); corrected to match the lspci example.
|
||||
# =============================================================================
|
||||
#
|
||||
# SONiC hardware has no memtool / devmem, but it has pcimem. pcimem mmaps the PCI
|
||||
# sysfs resource file directly and takes "resource file + offset relative to BAR
|
||||
# start", not an absolute physical address.
|
||||
#
|
||||
# pcimem { sysfile } { offset } [ type*count [ data ] ]
|
||||
# sysfile : sysfs file for the pci resource (e.g. .../resource0)
|
||||
# offset : offset into pci memory region
|
||||
# type : [b]yte, [h]alfword, [w]ord, [d]ouble-word
|
||||
# *count : number of items (w*100 dump 100 words)
|
||||
# data : data to be written
|
||||
#
|
||||
# This tool always accesses as word (w, 32-bit).
|
||||
#
|
||||
# After sourcing this file the following functions are available:
|
||||
# cb_fpga <fn:0-3> <addr> [data]
|
||||
# pmc_fpga <addr> [data]
|
||||
# icb_fpga <addr> [data]
|
||||
# swb0_fpga <addr> [data]
|
||||
# swb1_fpga <addr> [data]
|
||||
#
|
||||
# data present = write, absent = read.
|
||||
# Usage: source blanton_fpga_pcimem.sh
|
||||
|
||||
# === CB FPGA PCIe resource file (sysfs) ===
|
||||
# Use lspci -D to find the BDF (domain:bus:dev.fn); resource0 is the sysfs mapping of BAR0.
|
||||
# e.g. lspci -Dnn | grep -i fpga -> 0000:02:00.0 ...
|
||||
# memtool variant fills in the BAR value; pcimem variant fills in the resource file
|
||||
# path instead (offset becomes relative to BAR).
|
||||
FUNCT0_RES=/sys/bus/pci/devices/0000:04:00.0/resource0
|
||||
FUNCT1_RES=/sys/bus/pci/devices/0000:04:00.1/resource0
|
||||
FUNCT2_RES=/sys/bus/pci/devices/0000:04:00.2/resource0
|
||||
FUNCT3_RES=/sys/bus/pci/devices/0000:04:00.3/resource0
|
||||
|
||||
# Auto-detect example (uncomment to use; needs the FPGA's BDF prefix):
|
||||
# _BDF=0000:02:00
|
||||
# FUNCT0_RES=/sys/bus/pci/devices/${_BDF}.0/resource0
|
||||
# FUNCT1_RES=/sys/bus/pci/devices/${_BDF}.1/resource0
|
||||
# FUNCT2_RES=/sys/bus/pci/devices/${_BDF}.2/resource0
|
||||
# FUNCT3_RES=/sys/bus/pci/devices/${_BDF}.3/resource0
|
||||
|
||||
# === VSPI window base offset (relative to CB Function 2 resource0 start) ===
|
||||
# NOTE: CB.F2 has TWO near-identical VSPI register blocks (see spec register map):
|
||||
# - VSPI-Flash-* @ 0x340/0x380/0x3C0/0x400 -> accesses the remote FPGA's CONFIG FLASH
|
||||
# - VSPI-* @ 0x640/0x680/0x6C0/0x700 -> accesses the remote FPGA's REGISTERS
|
||||
# This tool reads/writes remote registers, so it uses the VSPI-* block (0x640+).
|
||||
# The VSPI-Flash bases are kept below (commented) in case flash access is needed later.
|
||||
VSPI_PMC_BASE=0x640
|
||||
VSPI_ICB_BASE=0x680
|
||||
VSPI_SWB0_BASE=0x6C0
|
||||
VSPI_SWB1_BASE=0x700
|
||||
|
||||
# VSPI-Flash window bases (config-flash access, not register access):
|
||||
# VSPI_FLASH_PMC_BASE=0x340
|
||||
# VSPI_FLASH_ICB_BASE=0x380
|
||||
# VSPI_FLASH_SWB0_BASE=0x3C0
|
||||
# VSPI_FLASH_SWB1_BASE=0x400
|
||||
|
||||
# === VSPI protocol constants ===
|
||||
_VSPI_CMD_STAT=0x00
|
||||
_VSPI_ADDR=0x04
|
||||
_VSPI_WR_DATA=0x08
|
||||
_VSPI_RD_DATA=0x0C
|
||||
_VSPI_NEW_CMD=0x01
|
||||
_VSPI_READ_W=0x02
|
||||
_VSPI_WRITE_W=0x04
|
||||
_VSPI_READY_MASK=0x100
|
||||
_VSPI_POLL_MAX=200
|
||||
|
||||
# === pcimem command ===
|
||||
PCIMEM_CMD="${PCIMEM_CMD:-pcimem}"
|
||||
|
||||
# === Debug mode (1=print commands AND execute, 0=execute only) ===
|
||||
DEBUG_MODE=${DEBUG_MODE:-0}
|
||||
|
||||
fpga_debug() {
|
||||
if [ "${1:-}" = "on" ]; then DEBUG_MODE=1
|
||||
elif [ "${1:-}" = "off" ]; then DEBUG_MODE=0
|
||||
else [ "$DEBUG_MODE" = "0" ] && DEBUG_MODE=1 || DEBUG_MODE=0; fi
|
||||
echo -e "[\033[34mINFO\033[0m] DEBUG_MODE=$DEBUG_MODE"
|
||||
}
|
||||
|
||||
# Wrapper: debug mode prints command (to stderr) AND executes, normal mode executes only.
|
||||
# On read, returns the parsed hex value (stripping pcimem's mmap noise).
|
||||
# Usage: _pcimem <sysfile> <offset> [data] (data present = write, absent = read)
|
||||
_pcimem() {
|
||||
local sysfile="$1" offset="$2" data="${3:-}"
|
||||
if [[ -n "$data" ]]; then
|
||||
[ "$DEBUG_MODE" = "1" ] && \
|
||||
echo -e "\033[90m[DEBG] $PCIMEM_CMD $sysfile $offset w $data\033[0m" >&2
|
||||
# Write output (opened / Target offset / mmap / Written...readback) is never
|
||||
# parsed -> drop stdout noise; keep stderr so real errors still surface.
|
||||
$PCIMEM_CMD "$sysfile" "$offset" w "$data" >/dev/null
|
||||
else
|
||||
[ "$DEBUG_MODE" = "1" ] && \
|
||||
echo -e "\033[90m[DEBG] $PCIMEM_CMD $sysfile $offset w\033[0m" >&2
|
||||
# pcimem read prints mmap info + "Value at offset ...: 0xXXXX";
|
||||
# take the last 0x... token as the actual read-back value.
|
||||
$PCIMEM_CMD "$sysfile" "$offset" w | grep -oiE '0x[0-9a-f]+' | tail -1
|
||||
fi
|
||||
}
|
||||
|
||||
# --- Internal VSPI helpers (all hang off CB Function 2's resource0) ---
|
||||
|
||||
_vspi_read() {
|
||||
local win_off="$1" remote_offset="$2"
|
||||
local cmd_off add_off rd_off addr_val status i
|
||||
|
||||
cmd_off=$(printf '0x%X' $(( win_off + _VSPI_CMD_STAT )))
|
||||
add_off=$(printf '0x%X' $(( win_off + _VSPI_ADDR )))
|
||||
rd_off=$(printf '0x%X' $(( win_off + _VSPI_RD_DATA )))
|
||||
addr_val=$(printf '0x%08X' $(( (0x0 << 20) | (remote_offset & 0xFFFFF) )))
|
||||
|
||||
_pcimem "$FUNCT2_RES" "$add_off" "$addr_val"
|
||||
_pcimem "$FUNCT2_RES" "$cmd_off" $(printf '0x%X' $(( _VSPI_NEW_CMD | _VSPI_READ_W )))
|
||||
|
||||
for (( i=0; i<_VSPI_POLL_MAX; i++ )); do
|
||||
status=$(_pcimem "$FUNCT2_RES" "$cmd_off")
|
||||
if (( ( ${status:-0} & _VSPI_READY_MASK) != 0 )); then
|
||||
_pcimem "$FUNCT2_RES" "$rd_off"
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
echo "ERROR: VSPI read timeout @ offset $remote_offset" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
_vspi_write() {
|
||||
local win_off="$1" remote_offset="$2" data="$3"
|
||||
local cmd_off add_off wr_off addr_val status i
|
||||
|
||||
cmd_off=$(printf '0x%X' $(( win_off + _VSPI_CMD_STAT )))
|
||||
add_off=$(printf '0x%X' $(( win_off + _VSPI_ADDR )))
|
||||
wr_off=$(printf '0x%X' $(( win_off + _VSPI_WR_DATA )))
|
||||
addr_val=$(printf '0x%08X' $(( (0x0 << 20) | (remote_offset & 0xFFFFF) )))
|
||||
|
||||
_pcimem "$FUNCT2_RES" "$wr_off" "$data"
|
||||
_pcimem "$FUNCT2_RES" "$add_off" "$addr_val"
|
||||
_pcimem "$FUNCT2_RES" "$cmd_off" $(printf '0x%X' $(( _VSPI_NEW_CMD | _VSPI_WRITE_W )))
|
||||
|
||||
for (( i=0; i<_VSPI_POLL_MAX; i++ )); do
|
||||
status=$(_pcimem "$FUNCT2_RES" "$cmd_off")
|
||||
if (( ( ${status:-0} & _VSPI_READY_MASK) != 0 )); then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
echo "ERROR: VSPI write timeout @ offset $remote_offset" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
# Guard: PMC/ICB/SWB are single-function; signature is <addr> [data], NO fn arg.
|
||||
# Common pitfall: using cb_fpga's "<fn> <addr>" form -> 2nd arg becomes data, a read
|
||||
# turns into a write. If addr is 0~3 (looks like fn) AND data is given, warn and
|
||||
# confirm; on a non-tty (script) just warn, don't block.
|
||||
# Usage: _vspi_fnwarn <name> <addr> <data> non-zero return = cancel
|
||||
_vspi_fnwarn() {
|
||||
local name="$1" addr="$2" data="$3"
|
||||
[[ -z "$data" ]] && return 0 # read, nothing to warn
|
||||
case "$addr" in
|
||||
0|1|2|3|0x0|0x1|0x2|0x3|0x00|0x01|0x02|0x03) ;; # looks like fn, warn below
|
||||
*) return 0 ;; # normal offset, allow
|
||||
esac
|
||||
echo -e "[\033[33mWARN\033[0m] $name has no fn arg; signature is <addr> [data] (NOT cb_fpga's <fn> <addr>)." >&2
|
||||
echo -e " This will WRITE $data to PMC/ICB/SWB offset $addr." >&2
|
||||
echo -e " To READ offset $addr, pass a single arg: $name $addr" >&2
|
||||
if [ -t 0 ]; then
|
||||
local ans
|
||||
read -r -p " Proceed with write anyway? [y/N] " ans
|
||||
case "$ans" in
|
||||
y|Y|yes|YES) return 0 ;;
|
||||
*) echo " Cancelled." >&2; return 1 ;;
|
||||
esac
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# === Public functions ===
|
||||
|
||||
cb_fpga() {
|
||||
if [[ $# -lt 2 ]]; then
|
||||
echo "Usage: cb_fpga <fn:0-3> <addr> [data]"; return 1
|
||||
fi
|
||||
local fn="$1" addr="$2" data="${3:-}" res
|
||||
case "$fn" in
|
||||
0) res=$FUNCT0_RES ;; 1) res=$FUNCT1_RES ;;
|
||||
2) res=$FUNCT2_RES ;; 3) res=$FUNCT3_RES ;;
|
||||
*) echo "cb_fpga: fn must be 0-3" >&2; return 1 ;;
|
||||
esac
|
||||
# pcimem offset is relative to BAR start; do not add BAR.
|
||||
if [[ -z "$data" ]]; then
|
||||
_pcimem "$res" "$addr"
|
||||
else
|
||||
_pcimem "$res" "$addr" "$data"
|
||||
fi
|
||||
}
|
||||
|
||||
pmc_fpga() {
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Usage: pmc_fpga <addr> [data]"; return 1
|
||||
fi
|
||||
local addr="$1" data="${2:-}"
|
||||
_vspi_fnwarn pmc_fpga "$addr" "$data" || return 1
|
||||
if [[ -z "$data" ]]; then _vspi_read "$VSPI_PMC_BASE" "$addr"
|
||||
else _vspi_write "$VSPI_PMC_BASE" "$addr" "$data"; fi
|
||||
}
|
||||
|
||||
icb_fpga() {
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Usage: icb_fpga <addr> [data]"; return 1
|
||||
fi
|
||||
local addr="$1" data="${2:-}"
|
||||
_vspi_fnwarn icb_fpga "$addr" "$data" || return 1
|
||||
if [[ -z "$data" ]]; then _vspi_read "$VSPI_ICB_BASE" "$addr"
|
||||
else _vspi_write "$VSPI_ICB_BASE" "$addr" "$data"; fi
|
||||
}
|
||||
|
||||
swb0_fpga() {
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Usage: swb0_fpga <addr> [data]"; return 1
|
||||
fi
|
||||
local addr="$1" data="${2:-}"
|
||||
_vspi_fnwarn swb0_fpga "$addr" "$data" || return 1
|
||||
if [[ -z "$data" ]]; then _vspi_read "$VSPI_SWB0_BASE" "$addr"
|
||||
else _vspi_write "$VSPI_SWB0_BASE" "$addr" "$data"; fi
|
||||
}
|
||||
|
||||
swb1_fpga() {
|
||||
if [[ $# -lt 1 ]]; then
|
||||
echo "Usage: swb1_fpga <addr> [data]"; return 1
|
||||
fi
|
||||
local addr="$1" data="${2:-}"
|
||||
_vspi_fnwarn swb1_fpga "$addr" "$data" || return 1
|
||||
if [[ -z "$data" ]]; then _vspi_read "$VSPI_SWB1_BASE" "$addr"
|
||||
else _vspi_write "$VSPI_SWB1_BASE" "$addr" "$data"; fi
|
||||
}
|
||||
|
||||
blanton_fpga_help() {
|
||||
echo -e "\033[1mblanton_fpga (pcimem) - FPGA Register Access Tool\033[0m"
|
||||
echo ""
|
||||
echo -e "\033[1mUsage:\033[0m"
|
||||
echo -e " \033[33mcb_fpga\033[0m <fn:0-3> <addr> [data] CB FPGA direct (sysfs resource0)"
|
||||
echo -e " \033[33mpmc_fpga\033[0m <addr> [data] PMC FPGA via VSPI"
|
||||
echo -e " \033[33micb_fpga\033[0m <addr> [data] ICB FPGA via VSPI"
|
||||
echo -e " \033[33mswb0_fpga\033[0m <addr> [data] SWB0 FPGA via VSPI"
|
||||
echo -e " \033[33mswb1_fpga\033[0m <addr> [data] SWB1 FPGA via VSPI"
|
||||
echo -e " \033[33mfpga_debug\033[0m on|off Toggle debug mode (print commands and execute)"
|
||||
echo ""
|
||||
echo -e " Omit [data] to \033[32mread\033[0m, provide [data] to \033[31mwrite\033[0m."
|
||||
echo -e " Backend: \033[36mpcimem\033[0m (sysfs resource file + relative offset)."
|
||||
echo -e " Run \033[33mblanton_fpga_help\033[0m to show this message again."
|
||||
}
|
||||
|
||||
blanton_fpga_help
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,22 +0,0 @@
|
||||
# Profile: comboA - alternating high/low (even=high, odd=low)
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:high:8"
|
||||
"1:low:8"
|
||||
"2:high:8"
|
||||
"3:low:8"
|
||||
"4:high:8"
|
||||
"5:low:8"
|
||||
"6:high:8"
|
||||
"7:low:8"
|
||||
"8:high:8"
|
||||
"9:low:8"
|
||||
"10:high:8"
|
||||
"11:low:8"
|
||||
"12:high:8"
|
||||
"13:low:8"
|
||||
"14:high:8"
|
||||
"15:low:8"
|
||||
)
|
||||
@@ -0,0 +1,26 @@
|
||||
# Profile: comboA_CB - checkerboard, the complement of comboB_CB
|
||||
# Board: CB only. The channel list is positional, so applying this to a
|
||||
# different board margins the wrong rails and nothing detects it.
|
||||
# Run comboA then comboB to cover every rail in both directions while its
|
||||
# neighbours sit the other way.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:low:5"
|
||||
"1:low:5"
|
||||
"2:high:5"
|
||||
"3:low:5"
|
||||
"4:high:5"
|
||||
"5:high:5"
|
||||
"6:high:5"
|
||||
"7:high:5"
|
||||
"8:low:5"
|
||||
"9:high:5"
|
||||
"10:high:5"
|
||||
"11:high:5"
|
||||
"12:low:5"
|
||||
"13:high:5"
|
||||
"14:high:5"
|
||||
"15:low:5"
|
||||
)
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
# Profile: comboA_SWB_CONN13 - checkerboard, the complement of comboB_SWB_CONN13
|
||||
# Board: SWB_CONN13 only. The channel list is positional, so applying this to a
|
||||
# different board margins the wrong rails and nothing detects it.
|
||||
# Run comboA then comboB to cover every rail in both directions while its
|
||||
# neighbours sit the other way.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:high:3"
|
||||
"1:high:3"
|
||||
"2:low:3"
|
||||
"3:low:3"
|
||||
"4:high:5"
|
||||
"5:low:5"
|
||||
"6:high:5"
|
||||
"7:high:5"
|
||||
"8:high:5"
|
||||
"9:high:3"
|
||||
"10:high:3"
|
||||
"11:low:3"
|
||||
"12:low:3"
|
||||
"13:high:3"
|
||||
"14:high:3"
|
||||
"15:low:5"
|
||||
)
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
# Profile: comboA_SWB_CONN14 - checkerboard, the complement of comboB_SWB_CONN14
|
||||
# Board: SWB_CONN14 only. The channel list is positional, so applying this to a
|
||||
# different board margins the wrong rails and nothing detects it.
|
||||
# Run comboA then comboB to cover every rail in both directions while its
|
||||
# neighbours sit the other way.
|
||||
# CH 10, 11, 13 stay nominal: they are NC on this board, so there is
|
||||
# nothing to margin.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:high:3"
|
||||
"1:low:3"
|
||||
"2:low:3"
|
||||
"3:high:5"
|
||||
"4:high:5"
|
||||
"5:high:5"
|
||||
"6:low:5"
|
||||
"7:low:5"
|
||||
"8:low:3"
|
||||
"9:low:3"
|
||||
"10:nominal:5"
|
||||
"11:nominal:5"
|
||||
"12:high:3"
|
||||
"13:nominal:5"
|
||||
"14:high:5"
|
||||
"15:high:3"
|
||||
)
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
# Profile: comboA_SWB_CONN15 - checkerboard, the complement of comboB_SWB_CONN15
|
||||
# Board: SWB_CONN15 only. The channel list is positional, so applying this to a
|
||||
# different board margins the wrong rails and nothing detects it.
|
||||
# Run comboA then comboB to cover every rail in both directions while its
|
||||
# neighbours sit the other way.
|
||||
# CH 10 stay nominal: they are NC on this board, so there is
|
||||
# nothing to margin.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:low:3"
|
||||
"1:low:3"
|
||||
"2:high:3"
|
||||
"3:high:3"
|
||||
"4:low:3"
|
||||
"5:low:3"
|
||||
"6:high:5"
|
||||
"7:high:3"
|
||||
"8:high:5"
|
||||
"9:low:5"
|
||||
"10:nominal:5"
|
||||
"11:low:5"
|
||||
"12:low:3"
|
||||
"13:high:3"
|
||||
"14:high:3"
|
||||
"15:high:5"
|
||||
)
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
# Profile: comboA_SWB_CONN16 - checkerboard, the complement of comboB_SWB_CONN16
|
||||
# Board: SWB_CONN16 only. The channel list is positional, so applying this to a
|
||||
# different board margins the wrong rails and nothing detects it.
|
||||
# Run comboA then comboB to cover every rail in both directions while its
|
||||
# neighbours sit the other way.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:high:3"
|
||||
"1:high:5"
|
||||
"2:high:5"
|
||||
"3:low:5"
|
||||
"4:high:5"
|
||||
"5:low:5"
|
||||
"6:high:5"
|
||||
"7:high:3"
|
||||
"8:high:3"
|
||||
"9:high:3"
|
||||
"10:low:3"
|
||||
"11:low:3"
|
||||
"12:low:3"
|
||||
"13:low:3"
|
||||
"14:low:3"
|
||||
"15:high:3"
|
||||
)
|
||||
@@ -1,22 +0,0 @@
|
||||
# Profile: comboB - inverse of comboA (even=low, odd=high)
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:low:8"
|
||||
"1:high:8"
|
||||
"2:low:8"
|
||||
"3:high:8"
|
||||
"4:low:8"
|
||||
"5:high:8"
|
||||
"6:low:8"
|
||||
"7:high:8"
|
||||
"8:low:8"
|
||||
"9:high:8"
|
||||
"10:low:8"
|
||||
"11:high:8"
|
||||
"12:low:8"
|
||||
"13:high:8"
|
||||
"14:low:8"
|
||||
"15:high:8"
|
||||
)
|
||||
@@ -0,0 +1,26 @@
|
||||
# Profile: comboB_CB - checkerboard, the complement of comboA_CB
|
||||
# Board: CB only. The channel list is positional, so applying this to a
|
||||
# different board margins the wrong rails and nothing detects it.
|
||||
# Run comboB then comboA to cover every rail in both directions while its
|
||||
# neighbours sit the other way.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:high:5"
|
||||
"1:high:5"
|
||||
"2:low:5"
|
||||
"3:high:5"
|
||||
"4:low:5"
|
||||
"5:low:5"
|
||||
"6:low:5"
|
||||
"7:low:5"
|
||||
"8:high:5"
|
||||
"9:low:5"
|
||||
"10:low:5"
|
||||
"11:low:5"
|
||||
"12:high:5"
|
||||
"13:low:5"
|
||||
"14:low:5"
|
||||
"15:high:5"
|
||||
)
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
# Profile: comboB_SWB_CONN13 - checkerboard, the complement of comboA_SWB_CONN13
|
||||
# Board: SWB_CONN13 only. The channel list is positional, so applying this to a
|
||||
# different board margins the wrong rails and nothing detects it.
|
||||
# Run comboB then comboA to cover every rail in both directions while its
|
||||
# neighbours sit the other way.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:low:3"
|
||||
"1:low:3"
|
||||
"2:high:3"
|
||||
"3:high:3"
|
||||
"4:low:5"
|
||||
"5:high:5"
|
||||
"6:low:5"
|
||||
"7:low:5"
|
||||
"8:low:5"
|
||||
"9:low:3"
|
||||
"10:low:3"
|
||||
"11:high:3"
|
||||
"12:high:3"
|
||||
"13:low:3"
|
||||
"14:low:3"
|
||||
"15:high:5"
|
||||
)
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
# Profile: comboB_SWB_CONN14 - checkerboard, the complement of comboA_SWB_CONN14
|
||||
# Board: SWB_CONN14 only. The channel list is positional, so applying this to a
|
||||
# different board margins the wrong rails and nothing detects it.
|
||||
# Run comboB then comboA to cover every rail in both directions while its
|
||||
# neighbours sit the other way.
|
||||
# CH 10, 11, 13 stay nominal: they are NC on this board, so there is
|
||||
# nothing to margin.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:low:3"
|
||||
"1:high:3"
|
||||
"2:high:3"
|
||||
"3:low:5"
|
||||
"4:low:5"
|
||||
"5:low:5"
|
||||
"6:high:5"
|
||||
"7:high:5"
|
||||
"8:high:3"
|
||||
"9:high:3"
|
||||
"10:nominal:5"
|
||||
"11:nominal:5"
|
||||
"12:low:3"
|
||||
"13:nominal:5"
|
||||
"14:low:5"
|
||||
"15:low:3"
|
||||
)
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
# Profile: comboB_SWB_CONN15 - checkerboard, the complement of comboA_SWB_CONN15
|
||||
# Board: SWB_CONN15 only. The channel list is positional, so applying this to a
|
||||
# different board margins the wrong rails and nothing detects it.
|
||||
# Run comboB then comboA to cover every rail in both directions while its
|
||||
# neighbours sit the other way.
|
||||
# CH 10 stay nominal: they are NC on this board, so there is
|
||||
# nothing to margin.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:high:3"
|
||||
"1:high:3"
|
||||
"2:low:3"
|
||||
"3:low:3"
|
||||
"4:high:3"
|
||||
"5:high:3"
|
||||
"6:low:5"
|
||||
"7:low:3"
|
||||
"8:low:5"
|
||||
"9:high:5"
|
||||
"10:nominal:5"
|
||||
"11:high:5"
|
||||
"12:high:3"
|
||||
"13:low:3"
|
||||
"14:low:3"
|
||||
"15:low:5"
|
||||
)
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
# Profile: comboB_SWB_CONN16 - checkerboard, the complement of comboA_SWB_CONN16
|
||||
# Board: SWB_CONN16 only. The channel list is positional, so applying this to a
|
||||
# different board margins the wrong rails and nothing detects it.
|
||||
# Run comboB then comboA to cover every rail in both directions while its
|
||||
# neighbours sit the other way.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:low:3"
|
||||
"1:low:5"
|
||||
"2:low:5"
|
||||
"3:high:5"
|
||||
"4:low:5"
|
||||
"5:high:5"
|
||||
"6:low:5"
|
||||
"7:low:3"
|
||||
"8:low:3"
|
||||
"9:low:3"
|
||||
"10:high:3"
|
||||
"11:high:3"
|
||||
"12:high:3"
|
||||
"13:high:3"
|
||||
"14:high:3"
|
||||
"15:low:3"
|
||||
)
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
# Profile: combo_SWB_CONN13_high - every channel margin HIGH, per-channel percentage
|
||||
# For the SWB CONN13 board only: the percentages follow that board's
|
||||
# rails, so applying it to a different CONN margins the wrong things.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:high:3"
|
||||
"1:high:3"
|
||||
"2:high:3"
|
||||
"3:high:3"
|
||||
"4:high:5"
|
||||
"5:high:5"
|
||||
"6:high:5"
|
||||
"7:high:5"
|
||||
"8:high:5"
|
||||
"9:high:3"
|
||||
"10:high:3"
|
||||
"11:high:3"
|
||||
"12:high:3"
|
||||
"13:high:3"
|
||||
"14:high:3"
|
||||
"15:high:5"
|
||||
)
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
# Profile: combo_SWB_CONN13_low - every channel margin LOW, per-channel percentage
|
||||
# For the SWB CONN13 board only: the percentages follow that board's
|
||||
# rails, so applying it to a different CONN margins the wrong things.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:low:3"
|
||||
"1:low:3"
|
||||
"2:low:3"
|
||||
"3:low:3"
|
||||
"4:low:5"
|
||||
"5:low:5"
|
||||
"6:low:5"
|
||||
"7:low:5"
|
||||
"8:low:5"
|
||||
"9:low:3"
|
||||
"10:low:3"
|
||||
"11:low:3"
|
||||
"12:low:3"
|
||||
"13:low:3"
|
||||
"14:low:3"
|
||||
"15:low:5"
|
||||
)
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
# Profile: combo_SWB_CONN14_high - every channel margin HIGH, per-channel percentage
|
||||
# For the SWB CONN14 board only: the percentages follow that board's
|
||||
# rails, so applying it to a different CONN margins the wrong things.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:high:3"
|
||||
"1:high:3"
|
||||
"2:high:3"
|
||||
"3:high:5"
|
||||
"4:high:5"
|
||||
"5:high:5"
|
||||
"6:high:5"
|
||||
"7:high:5"
|
||||
"8:high:3"
|
||||
"9:high:3"
|
||||
"10:nominal:5"
|
||||
"11:nominal:5"
|
||||
"12:high:3"
|
||||
"13:nominal:5"
|
||||
"14:high:5"
|
||||
"15:high:3"
|
||||
)
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
# Profile: combo_SWB_CONN14_low - every channel margin LOW, per-channel percentage
|
||||
# For the SWB CONN14 board only: the percentages follow that board's
|
||||
# rails, so applying it to a different CONN margins the wrong things.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:low:3"
|
||||
"1:low:3"
|
||||
"2:low:3"
|
||||
"3:low:5"
|
||||
"4:low:5"
|
||||
"5:low:5"
|
||||
"6:low:5"
|
||||
"7:low:5"
|
||||
"8:low:3"
|
||||
"9:low:3"
|
||||
"10:nominal:5"
|
||||
"11:nominal:5"
|
||||
"12:low:3"
|
||||
"13:nominal:5"
|
||||
"14:low:5"
|
||||
"15:low:3"
|
||||
)
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
# Profile: combo_SWB_CONN15_high - every channel margin HIGH, per-channel percentage
|
||||
# For the SWB CONN15 board only: the percentages follow that board's
|
||||
# rails, so applying it to a different CONN margins the wrong things.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:high:3"
|
||||
"1:high:3"
|
||||
"2:high:3"
|
||||
"3:high:3"
|
||||
"4:high:3"
|
||||
"5:high:3"
|
||||
"6:high:5"
|
||||
"7:high:3"
|
||||
"8:high:5"
|
||||
"9:high:5"
|
||||
"10:nominal:5"
|
||||
"11:high:5"
|
||||
"12:high:3"
|
||||
"13:high:3"
|
||||
"14:high:3"
|
||||
"15:high:5"
|
||||
)
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
# Profile: combo_SWB_CONN15_low - every channel margin LOW, per-channel percentage
|
||||
# For the SWB CONN15 board only: the percentages follow that board's
|
||||
# rails, so applying it to a different CONN margins the wrong things.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:low:3"
|
||||
"1:low:3"
|
||||
"2:low:3"
|
||||
"3:low:3"
|
||||
"4:low:3"
|
||||
"5:low:3"
|
||||
"6:low:5"
|
||||
"7:low:3"
|
||||
"8:low:5"
|
||||
"9:low:5"
|
||||
"10:nominal:5"
|
||||
"11:low:5"
|
||||
"12:low:3"
|
||||
"13:low:3"
|
||||
"14:low:3"
|
||||
"15:low:5"
|
||||
)
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
# Profile: combo_SWB_CONN16_high - every channel margin HIGH, per-channel percentage
|
||||
# For the SWB CONN16 board only: the percentages follow that board's
|
||||
# rails, so applying it to a different CONN margins the wrong things.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:high:3"
|
||||
"1:high:5"
|
||||
"2:high:5"
|
||||
"3:high:5"
|
||||
"4:high:5"
|
||||
"5:high:5"
|
||||
"6:high:5"
|
||||
"7:high:3"
|
||||
"8:high:3"
|
||||
"9:high:3"
|
||||
"10:high:3"
|
||||
"11:high:3"
|
||||
"12:high:3"
|
||||
"13:high:3"
|
||||
"14:high:3"
|
||||
"15:high:3"
|
||||
)
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
# Profile: combo_SWB_CONN16_low - every channel margin LOW, per-channel percentage
|
||||
# For the SWB CONN16 board only: the percentages follow that board's
|
||||
# rails, so applying it to a different CONN margins the wrong things.
|
||||
# Applied to whichever LTC2980 is currently loaded via margin_init
|
||||
# Format: "channel:operation:change_percent"
|
||||
|
||||
PROFILE_CHANNELS=(
|
||||
"0:low:3"
|
||||
"1:low:5"
|
||||
"2:low:5"
|
||||
"3:low:5"
|
||||
"4:low:5"
|
||||
"5:low:5"
|
||||
"6:low:5"
|
||||
"7:low:3"
|
||||
"8:low:3"
|
||||
"9:low:3"
|
||||
"10:low:3"
|
||||
"11:low:3"
|
||||
"12:low:3"
|
||||
"13:low:3"
|
||||
"14:low:3"
|
||||
"15:low:3"
|
||||
)
|
||||
+17
-10
@@ -17,17 +17,24 @@ BOARDS=(
|
||||
"Blanton_SWB1_CONN16"
|
||||
)
|
||||
|
||||
# 對應的 profile 名稱(不含路徑與 .conf 副檔名),預設全部 comboA
|
||||
# 對應的 profile 名稱(不含路徑與 .conf 副檔名)。
|
||||
#
|
||||
# SWB 的 profile 是 per-CONN 的:百分比對應該片板子的軌,套到別的 CONN 會 margin
|
||||
# 到錯的東西,所以這裡不能全部填同一個名字。
|
||||
#
|
||||
# 這份預設是 HIGH 那一輪;LOW 那一輪把下面的 _high 全換成 _low 再跑一次
|
||||
# (或 sed -i 's/_high/_low/' 這個檔)。
|
||||
# CB 沒有 per-CONN profile,沿用通用的 combo_high3 / combo_low3。
|
||||
PROFILES=(
|
||||
"comboA" # Blanton_CB_CONN13
|
||||
"comboA" # Blanton_SWB0_CONN13
|
||||
"comboA" # Blanton_SWB0_CONN14
|
||||
"comboA" # Blanton_SWB0_CONN15
|
||||
"comboA" # Blanton_SWB0_CONN16
|
||||
"comboA" # Blanton_SWB1_CONN13
|
||||
"comboA" # Blanton_SWB1_CONN14
|
||||
"comboA" # Blanton_SWB1_CONN15
|
||||
"comboA" # Blanton_SWB1_CONN16
|
||||
"combo_high3" # Blanton_CB_CONN13 (低壓軌多,用通用 +3%)
|
||||
"combo_SWB_CONN13_high" # Blanton_SWB0_CONN13
|
||||
"combo_SWB_CONN14_high" # Blanton_SWB0_CONN14
|
||||
"combo_SWB_CONN15_high" # Blanton_SWB0_CONN15
|
||||
"combo_SWB_CONN16_high" # Blanton_SWB0_CONN16
|
||||
"combo_SWB_CONN13_high" # Blanton_SWB1_CONN13
|
||||
"combo_SWB_CONN14_high" # Blanton_SWB1_CONN14
|
||||
"combo_SWB_CONN15_high" # Blanton_SWB1_CONN15
|
||||
"combo_SWB_CONN16_high" # Blanton_SWB1_CONN16
|
||||
)
|
||||
|
||||
# --- Source margin.sh if not already loaded ---
|
||||
|
||||
@@ -4,6 +4,10 @@
|
||||
# ⚠️ margin_save 會把目前的 margin / OV / UV 設定**永久寫入 NVM**,
|
||||
# 斷電後仍保留。執行前請務必先 margin_status 確認各 channel 狀態正確。
|
||||
#
|
||||
# 全部 9 顆請直接用 margin.sh v2.7.0 內建的 `margin_save all` —— 它有成功/失敗總結,
|
||||
# 跑完還會把 margin_init 切回你原本載入的那顆。這支只在「只想寫其中幾顆」時才需要,
|
||||
# 編下面的 BOARDS 陣列。
|
||||
#
|
||||
# Usage:
|
||||
# source script/margin_save_all.sh
|
||||
|
||||
|
||||
+52
-52
@@ -1,52 +1,52 @@
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- Transport (blank = i2c): CB's LTC2980 is on the native I2C bus, driven by
|
||||
# i2cset/i2cget. Only SWB boards set TRANSPORT="swb" + CB_I2C_CH=<6|7|8|9>. ---
|
||||
TRANSPORT=""
|
||||
CB_I2C_CH=
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: CB (CONN13)
|
||||
"4:0x5C" # CH0 ~ CH7
|
||||
"4:0x5E" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # CB CONN13 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # CB CONN13 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: CB (CONN13)
|
||||
# ============================================================
|
||||
CH0_VNOM="5.0"; CH0_NET="V5P0_ALW"
|
||||
CH1_VNOM="3.3"; CH1_NET="V3P3_ALW"
|
||||
CH2_VNOM="0.75"; CH2_NET="PWR_VDD_MISC_ALW"
|
||||
CH3_VNOM="1.8"; CH3_NET="V1P8_ALW"
|
||||
CH4_VNOM="1.1"; CH4_NET="PWR_APU_VDDIO_SUS"
|
||||
CH5_VNOM="0.75"; CH5_NET="PWR_VDD_MISC_RUN"
|
||||
CH6_VNOM="0.78"; CH6_NET="PWR_APU_VDD_MEM_RUN"
|
||||
CH7_VNOM="0.8"; CH7_NET="V0P8_PHY2_DVDD"
|
||||
CH8_VNOM="0.8"; CH8_NET="V0P8_AVDD"
|
||||
CH9_VNOM="0.8"; CH9_NET="V0P8_PHY"
|
||||
CH10_VNOM="1.8"; CH10_NET="V1P8_FPGA"
|
||||
CH11_VNOM="2.5"; CH11_NET="V2P5_FPGA"
|
||||
CH12_VNOM="1.1"; CH12_NET="V1P1_FPGA"
|
||||
CH13_VNOM="5.0"; CH13_NET="P5V_STBY"
|
||||
CH14_VNOM="3.3"; CH14_NET="P3V3_STBY"
|
||||
CH15_VNOM="0.8"; CH15_NET="V0P8_PHY2_AVDD"
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- Transport (blank = i2c): CB's LTC2980 is on the native I2C bus, driven by
|
||||
# i2cset/i2cget. Only SWB boards set TRANSPORT="swb" + CB_I2C_CH=<6|7|8|9>. ---
|
||||
TRANSPORT=""
|
||||
CB_I2C_CH=
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: CB (CONN13)
|
||||
"4:0x5C" # CH0 ~ CH7
|
||||
"4:0x5E" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # CB CONN13 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # CB CONN13 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: CB (CONN13)
|
||||
# ============================================================
|
||||
CH0_VNOM="5.0"; CH0_NET="V5P0_ALW"
|
||||
CH1_VNOM="3.3"; CH1_NET="V3P3_ALW"
|
||||
CH2_VNOM="0.75"; CH2_NET="PWR_VDD_MISC_ALW"
|
||||
CH3_VNOM="1.8"; CH3_NET="V1P8_ALW"
|
||||
CH4_VNOM="1.1"; CH4_NET="PWR_APU_VDDIO_SUS"
|
||||
CH5_VNOM="0.75"; CH5_NET="PWR_VDD_MISC_RUN"
|
||||
CH6_VNOM="0.78"; CH6_NET="PWR_APU_VDD_MEM_RUN"
|
||||
CH7_VNOM="0.816"; CH7_NET="V0P8_PHY2_DVDD"
|
||||
CH8_VNOM="0.8"; CH8_NET="V0P8_AVDD"
|
||||
CH9_VNOM="0.8"; CH9_NET="V0P8_PHY"
|
||||
CH10_VNOM="1.8"; CH10_NET="V1P8_FPGA"
|
||||
CH11_VNOM="2.5"; CH11_NET="V2P5_FPGA"
|
||||
CH12_VNOM="1.1"; CH12_NET="V1P1_FPGA"
|
||||
CH13_VNOM="5.0"; CH13_NET="P5V_STBY"
|
||||
CH14_VNOM="3.3"; CH14_NET="P3V3_STBY"
|
||||
CH15_VNOM="0.816"; CH15_NET="V0P8_PHY2_AVDD"
|
||||
|
||||
+52
-52
@@ -1,52 +1,52 @@
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=6
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB0 (CONN13)
|
||||
"0:0x5C" # CH0 ~ CH7
|
||||
"0:0x5E" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB0 CONN13 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB0 CONN13 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB0 (CONN13)
|
||||
# ============================================================
|
||||
CH0_VNOM="0.75"; CH0_NET="P0V75_DVDD_47"
|
||||
CH1_VNOM="0.75"; CH1_NET="P0V75_AVDD_47"
|
||||
CH2_VNOM="1.5"; CH2_NET="P1V5_AVDD_47"
|
||||
CH3_VNOM="0.9"; CH3_NET="P0V9_AVDD_47"
|
||||
CH4_VNOM="1.8"; CH4_NET="P1V8_1"
|
||||
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A3"
|
||||
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B1"
|
||||
CH7_VNOM="1.8"; CH7_NET="P1V8_3"
|
||||
CH8_VNOM="1.8"; CH8_NET="P1V8_DVDDIO_3"
|
||||
CH9_VNOM="0.75"; CH9_NET="P0V75_DVDD_39"
|
||||
CH10_VNOM="0.75"; CH10_NET="P0V75_AVDD_39"
|
||||
CH11_VNOM="1.5"; CH11_NET="P1V5_AVDD_39"
|
||||
CH12_VNOM="0.9"; CH12_NET="P0V9_AVDD_39"
|
||||
CH13_VNOM="1.5"; CH13_NET="PVDD1V5_2"
|
||||
CH14_VNOM="1.8"; CH14_NET="PVDD1V8_DUT"
|
||||
CH15_VNOM="1.2"; CH15_NET="PVDD_MDIO"
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=8 # CB F3 Ch8 = SWB0 CONN13/CONN15 (shared with CONN15, addr must differ)
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB0 (CONN13)
|
||||
"0:0x5C" # CH0 ~ CH7
|
||||
"0:0x5E" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB0 CONN13 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB0 CONN13 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB0 (CONN13)
|
||||
# ============================================================
|
||||
CH0_VNOM="0.75"; CH0_NET="P0V75_DVDD_47"
|
||||
CH1_VNOM="0.756"; CH1_NET="P0V75_AVDD_47"
|
||||
CH2_VNOM="1.524"; CH2_NET="P1V5_AVDD_47"
|
||||
CH3_VNOM="0.915"; CH3_NET="P0V9_AVDD_47"
|
||||
CH4_VNOM="1.816"; CH4_NET="P1V8_1"
|
||||
CH5_VNOM="3.38"; CH5_NET="PVDD3_3V_SYNTH_LDO_A3"
|
||||
CH6_VNOM="3.38"; CH6_NET="PVDD3_3V_SYNTH_LDO_B1"
|
||||
CH7_VNOM="1.816"; CH7_NET="P1V8_3"
|
||||
CH8_VNOM="1.8"; CH8_NET="P1V8_DVDDIO_3"
|
||||
CH9_VNOM="0.75"; CH9_NET="P0V75_DVDD_39"
|
||||
CH10_VNOM="0.756"; CH10_NET="P0V75_AVDD_39"
|
||||
CH11_VNOM="1.524"; CH11_NET="P1V5_AVDD_39"
|
||||
CH12_VNOM="0.915"; CH12_NET="P0V9_AVDD_39"
|
||||
CH13_VNOM="1.5"; CH13_NET="PVDD1V5_2"
|
||||
CH14_VNOM="1.8"; CH14_NET="PVDD1V8_DUT"
|
||||
CH15_VNOM="1.2"; CH15_NET="PVDD_MDIO"
|
||||
|
||||
+52
-52
@@ -1,52 +1,52 @@
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=8
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB0 (CONN14)
|
||||
"0:0x5E" # CH0 ~ CH7
|
||||
"0:0x5F" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB0 CONN14 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB0 CONN14 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB0 (CONN14)
|
||||
# ============================================================
|
||||
CH0_VNOM="0.75"; CH0_NET="P0V75_AVDD_7"
|
||||
CH1_VNOM="1.5"; CH1_NET="P1V5_AVDD_7"
|
||||
CH2_VNOM="0.9"; CH2_NET="P0V9_AVDD_7"
|
||||
CH3_VNOM="1.8"; CH3_NET="P1V8_5"
|
||||
CH4_VNOM="1.8"; CH4_NET="P1V8_2"
|
||||
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_B2"
|
||||
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_A2"
|
||||
CH7_VNOM="3.3"; CH7_NET="PVDD3_3V_SYNTH_LDO_A1"
|
||||
CH8_VNOM="1.5"; CH8_NET="PVDD1V5_TSC"
|
||||
CH9_VNOM="1.5"; CH9_NET="PVDD1V5_ANLG"
|
||||
CH10_VNOM="-"; CH10_NET="NC"
|
||||
CH11_VNOM="-"; CH11_NET="NC"
|
||||
CH12_VNOM="1.5"; CH12_NET="PVDD1V5_1"
|
||||
CH13_VNOM="-"; CH13_NET="NC"
|
||||
CH14_VNOM="1.8"; CH14_NET="P1V8_DVDDIO_1"
|
||||
CH15_VNOM="0.75"; CH15_NET="P0V75_DVDD_7"
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=6 # CB F3 Ch6 = SWB0 CONN14/CONN16 (shared with CONN16, addr must differ)
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB0 (CONN14)
|
||||
"0:0x5C" # CH0 ~ CH7
|
||||
"0:0x5E" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB0 CONN14 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB0 CONN14 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB0 (CONN14)
|
||||
# ============================================================
|
||||
CH0_VNOM="0.756"; CH0_NET="P0V75_AVDD_7"
|
||||
CH1_VNOM="1.524"; CH1_NET="P1V5_AVDD_7"
|
||||
CH2_VNOM="0.915"; CH2_NET="P0V9_AVDD_7"
|
||||
CH3_VNOM="1.816"; CH3_NET="P1V8_5"
|
||||
CH4_VNOM="1.816"; CH4_NET="P1V8_2"
|
||||
CH5_VNOM="3.38"; CH5_NET="PVDD3_3V_SYNTH_LDO_B2"
|
||||
CH6_VNOM="3.38"; CH6_NET="PVDD3_3V_SYNTH_LDO_A2"
|
||||
CH7_VNOM="3.38"; CH7_NET="PVDD3_3V_SYNTH_LDO_A1"
|
||||
CH8_VNOM="1.516"; CH8_NET="PVDD1V5_TSC"
|
||||
CH9_VNOM="1.516"; CH9_NET="PVDD1V5_ANLG"
|
||||
CH10_VNOM="-"; CH10_NET="NC"
|
||||
CH11_VNOM="-"; CH11_NET="NC"
|
||||
CH12_VNOM="1.5"; CH12_NET="PVDD1V5_1"
|
||||
CH13_VNOM="-"; CH13_NET="NC"
|
||||
CH14_VNOM="1.8"; CH14_NET="P1V8_DVDDIO_1"
|
||||
CH15_VNOM="0.75"; CH15_NET="P0V75_DVDD_7"
|
||||
|
||||
+52
-52
@@ -1,52 +1,52 @@
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=6
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB0 (CONN15)
|
||||
"0:0x62" # CH0 ~ CH7
|
||||
"0:0x63" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB0 CONN15 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB0 CONN15 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB0 (CONN15)
|
||||
# ============================================================
|
||||
CH0_VNOM="1.5"; CH0_NET="P1V5_AVDD_55"
|
||||
CH1_VNOM="0.9"; CH1_NET="P0V9_AVDD_55"
|
||||
CH2_VNOM="0.75"; CH2_NET="P0V75_DVDD_63"
|
||||
CH3_VNOM="0.75"; CH3_NET="P0V75_AVDD_63"
|
||||
CH4_VNOM="1.5"; CH4_NET="P1V5_AVDD_63"
|
||||
CH5_VNOM="0.9"; CH5_NET="P0V9_AVDD_63"
|
||||
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B3"
|
||||
CH7_VNOM="1.5"; CH7_NET="PVDD1V5_3"
|
||||
CH8_VNOM="0.85"; CH8_NET="P0V85_STBY"
|
||||
CH9_VNOM="1.8"; CH9_NET="P1V8_STBY"
|
||||
CH10_VNOM="-"; CH10_NET="NC"
|
||||
CH11_VNOM="3.3"; CH11_NET="P3V3_STBY"
|
||||
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_2"
|
||||
CH13_VNOM="0.75"; CH13_NET="P0V75_DVDD_55"
|
||||
CH14_VNOM="0.75"; CH14_NET="P0V75_AVDD_55"
|
||||
CH15_VNOM="1.8"; CH15_NET="P1V8_DVDDIO_4"
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=8 # CB F3 Ch8 = SWB0 CONN13/CONN15 (shared with CONN13, addr must differ)
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB0 (CONN15)
|
||||
"0:0x62" # CH0 ~ CH7
|
||||
"0:0x64" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB0 CONN15 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB0 CONN15 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB0 (CONN15)
|
||||
# ============================================================
|
||||
CH0_VNOM="1.524"; CH0_NET="P1V5_AVDD_55"
|
||||
CH1_VNOM="0.915"; CH1_NET="P0V9_AVDD_55"
|
||||
CH2_VNOM="0.75"; CH2_NET="P0V75_DVDD_63"
|
||||
CH3_VNOM="0.756"; CH3_NET="P0V75_AVDD_63"
|
||||
CH4_VNOM="1.524"; CH4_NET="P1V5_AVDD_63"
|
||||
CH5_VNOM="0.915"; CH5_NET="P0V9_AVDD_63"
|
||||
CH6_VNOM="3.38"; CH6_NET="PVDD3_3V_SYNTH_LDO_B3"
|
||||
CH7_VNOM="1.5"; CH7_NET="PVDD1V5_3"
|
||||
CH8_VNOM="0.85"; CH8_NET="P0V85_STBY"
|
||||
CH9_VNOM="1.8"; CH9_NET="P1V8_STBY"
|
||||
CH10_VNOM="-"; CH10_NET="NC"
|
||||
CH11_VNOM="3.3"; CH11_NET="P3V3_STBY"
|
||||
CH12_VNOM="0.91"; CH12_NET="PVDD0V9_2"
|
||||
CH13_VNOM="0.75"; CH13_NET="P0V75_DVDD_55"
|
||||
CH14_VNOM="0.756"; CH14_NET="P0V75_AVDD_55"
|
||||
CH15_VNOM="1.8"; CH15_NET="P1V8_DVDDIO_4"
|
||||
|
||||
+52
-52
@@ -1,52 +1,52 @@
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=8
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB0 (CONN16)
|
||||
"0:0x64" # CH0 ~ CH7
|
||||
"0:0x65" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB0 CONN16 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB0 CONN16 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB0 (CONN16)
|
||||
# ============================================================
|
||||
CH0_VNOM="1.5"; CH0_NET="PVDD1V5_0"
|
||||
CH1_VNOM="1.8"; CH1_NET="P1V8_4"
|
||||
CH2_VNOM="3.3"; CH2_NET="PVDD3_3V_SYNTH_LDO_B5"
|
||||
CH3_VNOM="3.3"; CH3_NET="PVDD3_3V_SYNTH_LDO_A5"
|
||||
CH4_VNOM="3.3"; CH4_NET="PVDD3_3V_SYNTH_LDO_B4"
|
||||
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A4"
|
||||
CH6_VNOM="3.3"; CH6_NET="P3V3"
|
||||
CH7_VNOM="0.8"; CH7_NET="PVDD0_8V_T3"
|
||||
CH8_VNOM="0.75"; CH8_NET="P0V75_DVDD_1"
|
||||
CH9_VNOM="0.75"; CH9_NET="P0V75_AVDD_1"
|
||||
CH10_VNOM="1.5"; CH10_NET="P1V5_AVDD_1"
|
||||
CH11_VNOM="0.9"; CH11_NET="P0V9_AVDD_1"
|
||||
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_0"
|
||||
CH13_VNOM="0.9"; CH13_NET="PVDD0V9_1"
|
||||
CH14_VNOM="0.9"; CH14_NET="PVDD0V9_3"
|
||||
CH15_VNOM="1.2"; CH15_NET="PVDD1V2_T3"
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=6 # CB F3 Ch6 = SWB0 CONN14/CONN16 (shared with CONN14, addr must differ)
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB0 (CONN16)
|
||||
"0:0x62" # CH0 ~ CH7
|
||||
"0:0x64" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB0 CONN16 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB0 CONN16 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB0 (CONN16)
|
||||
# ============================================================
|
||||
CH0_VNOM="1.5"; CH0_NET="PVDD1V5_0"
|
||||
CH1_VNOM="1.816"; CH1_NET="P1V8_4"
|
||||
CH2_VNOM="3.38"; CH2_NET="PVDD3_3V_SYNTH_LDO_B5"
|
||||
CH3_VNOM="3.38"; CH3_NET="PVDD3_3V_SYNTH_LDO_A5"
|
||||
CH4_VNOM="3.38"; CH4_NET="PVDD3_3V_SYNTH_LDO_B4"
|
||||
CH5_VNOM="3.38"; CH5_NET="PVDD3_3V_SYNTH_LDO_A4"
|
||||
CH6_VNOM="3.327"; CH6_NET="P3V3"
|
||||
CH7_VNOM="0.82"; CH7_NET="PVDD0_8V_T3"
|
||||
CH8_VNOM="0.75"; CH8_NET="P0V75_DVDD_1"
|
||||
CH9_VNOM="0.756"; CH9_NET="P0V75_AVDD_1"
|
||||
CH10_VNOM="1.524"; CH10_NET="P1V5_AVDD_1"
|
||||
CH11_VNOM="0.915"; CH11_NET="P0V9_AVDD_1"
|
||||
CH12_VNOM="0.915"; CH12_NET="PVDD0V9_0"
|
||||
CH13_VNOM="0.91"; CH13_NET="PVDD0V9_1"
|
||||
CH14_VNOM="0.915"; CH14_NET="PVDD0V9_3"
|
||||
CH15_VNOM="1.224"; CH15_NET="PVDD1V2_T3"
|
||||
|
||||
+52
-52
@@ -1,52 +1,52 @@
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=7
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB1 (CONN13)
|
||||
"1:0x5C" # CH0 ~ CH7
|
||||
"1:0x5D" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB1 CONN13 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB1 CONN13 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB1 (CONN13)
|
||||
# ============================================================
|
||||
CH0_VNOM="0.75"; CH0_NET="P0V75_DVDD_47"
|
||||
CH1_VNOM="0.75"; CH1_NET="P0V75_AVDD_47"
|
||||
CH2_VNOM="1.5"; CH2_NET="P1V5_AVDD_47"
|
||||
CH3_VNOM="0.9"; CH3_NET="P0V9_AVDD_47"
|
||||
CH4_VNOM="1.8"; CH4_NET="P1V8_1"
|
||||
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A3"
|
||||
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B1"
|
||||
CH7_VNOM="1.8"; CH7_NET="P1V8_3"
|
||||
CH8_VNOM="1.8"; CH8_NET="P1V8_DVDDIO_3"
|
||||
CH9_VNOM="0.75"; CH9_NET="P0V75_DVDD_39"
|
||||
CH10_VNOM="0.75"; CH10_NET="P0V75_AVDD_39"
|
||||
CH11_VNOM="1.5"; CH11_NET="P1V5_AVDD_39"
|
||||
CH12_VNOM="0.9"; CH12_NET="P0V9_AVDD_39"
|
||||
CH13_VNOM="1.5"; CH13_NET="PVDD1V5_2"
|
||||
CH14_VNOM="1.8"; CH14_NET="PVDD1V8_DUT"
|
||||
CH15_VNOM="1.2"; CH15_NET="PVDD_MDIO"
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=9 # CB F3 Ch9 = SWB1 CONN13/CONN15 (shared with CONN15, addr must differ)
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB1 (CONN13)
|
||||
"1:0x5C" # CH0 ~ CH7
|
||||
"1:0x5E" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB1 CONN13 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB1 CONN13 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB1 (CONN13)
|
||||
# ============================================================
|
||||
CH0_VNOM="0.75"; CH0_NET="P0V75_DVDD_47"
|
||||
CH1_VNOM="0.756"; CH1_NET="P0V75_AVDD_47"
|
||||
CH2_VNOM="1.524"; CH2_NET="P1V5_AVDD_47"
|
||||
CH3_VNOM="0.915"; CH3_NET="P0V9_AVDD_47"
|
||||
CH4_VNOM="1.816"; CH4_NET="P1V8_1"
|
||||
CH5_VNOM="3.38"; CH5_NET="PVDD3_3V_SYNTH_LDO_A3"
|
||||
CH6_VNOM="3.38"; CH6_NET="PVDD3_3V_SYNTH_LDO_B1"
|
||||
CH7_VNOM="1.816"; CH7_NET="P1V8_3"
|
||||
CH8_VNOM="1.8"; CH8_NET="P1V8_DVDDIO_3"
|
||||
CH9_VNOM="0.75"; CH9_NET="P0V75_DVDD_39"
|
||||
CH10_VNOM="0.756"; CH10_NET="P0V75_AVDD_39"
|
||||
CH11_VNOM="1.524"; CH11_NET="P1V5_AVDD_39"
|
||||
CH12_VNOM="0.915"; CH12_NET="P0V9_AVDD_39"
|
||||
CH13_VNOM="1.5"; CH13_NET="PVDD1V5_2"
|
||||
CH14_VNOM="1.8"; CH14_NET="PVDD1V8_DUT"
|
||||
CH15_VNOM="1.2"; CH15_NET="PVDD_MDIO"
|
||||
|
||||
+52
-52
@@ -1,52 +1,52 @@
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=9
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB1 (CONN14)
|
||||
"1:0x5E" # CH0 ~ CH7
|
||||
"1:0x5F" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB1 CONN14 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB1 CONN14 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB1 (CONN14)
|
||||
# ============================================================
|
||||
CH0_VNOM="0.75"; CH0_NET="P0V75_AVDD_7"
|
||||
CH1_VNOM="1.5"; CH1_NET="P1V5_AVDD_7"
|
||||
CH2_VNOM="0.9"; CH2_NET="P0V9_AVDD_7"
|
||||
CH3_VNOM="1.8"; CH3_NET="P1V8_5"
|
||||
CH4_VNOM="1.8"; CH4_NET="P1V8_2"
|
||||
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_B2"
|
||||
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_A2"
|
||||
CH7_VNOM="3.3"; CH7_NET="PVDD3_3V_SYNTH_LDO_A1"
|
||||
CH8_VNOM="1.5"; CH8_NET="PVDD1V5_TSC"
|
||||
CH9_VNOM="1.5"; CH9_NET="PVDD1V5_ANLG"
|
||||
CH10_VNOM="-"; CH10_NET="NC"
|
||||
CH11_VNOM="-"; CH11_NET="NC"
|
||||
CH12_VNOM="1.5"; CH12_NET="PVDD1V5_1"
|
||||
CH13_VNOM="-"; CH13_NET="NC"
|
||||
CH14_VNOM="1.8"; CH14_NET="P1V8_DVDDIO_1"
|
||||
CH15_VNOM="0.75"; CH15_NET="P0V75_DVDD_7"
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=7 # CB F3 Ch7 = SWB1 CONN14/CONN16 (shared with CONN16, addr must differ)
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB1 (CONN14)
|
||||
"1:0x5C" # CH0 ~ CH7
|
||||
"1:0x5E" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB1 CONN14 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB1 CONN14 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB1 (CONN14)
|
||||
# ============================================================
|
||||
CH0_VNOM="0.756"; CH0_NET="P0V75_AVDD_7"
|
||||
CH1_VNOM="1.524"; CH1_NET="P1V5_AVDD_7"
|
||||
CH2_VNOM="0.915"; CH2_NET="P0V9_AVDD_7"
|
||||
CH3_VNOM="1.816"; CH3_NET="P1V8_5"
|
||||
CH4_VNOM="1.816"; CH4_NET="P1V8_2"
|
||||
CH5_VNOM="3.38"; CH5_NET="PVDD3_3V_SYNTH_LDO_B2"
|
||||
CH6_VNOM="3.38"; CH6_NET="PVDD3_3V_SYNTH_LDO_A2"
|
||||
CH7_VNOM="3.38"; CH7_NET="PVDD3_3V_SYNTH_LDO_A1"
|
||||
CH8_VNOM="1.516"; CH8_NET="PVDD1V5_TSC"
|
||||
CH9_VNOM="1.516"; CH9_NET="PVDD1V5_ANLG"
|
||||
CH10_VNOM="-"; CH10_NET="NC"
|
||||
CH11_VNOM="-"; CH11_NET="NC"
|
||||
CH12_VNOM="1.5"; CH12_NET="PVDD1V5_1"
|
||||
CH13_VNOM="-"; CH13_NET="NC"
|
||||
CH14_VNOM="1.8"; CH14_NET="P1V8_DVDDIO_1"
|
||||
CH15_VNOM="0.75"; CH15_NET="P0V75_DVDD_7"
|
||||
|
||||
+52
-52
@@ -1,52 +1,52 @@
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=7
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB1 (CONN15)
|
||||
"1:0x62" # CH0 ~ CH7
|
||||
"1:0x63" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB1 CONN15 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB1 CONN15 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB1 (CONN15)
|
||||
# ============================================================
|
||||
CH0_VNOM="1.5"; CH0_NET="P1V5_AVDD_55"
|
||||
CH1_VNOM="0.9"; CH1_NET="P0V9_AVDD_55"
|
||||
CH2_VNOM="0.75"; CH2_NET="P0V75_DVDD_63"
|
||||
CH3_VNOM="0.75"; CH3_NET="P0V75_AVDD_63"
|
||||
CH4_VNOM="1.5"; CH4_NET="P1V5_AVDD_63"
|
||||
CH5_VNOM="0.9"; CH5_NET="P0V9_AVDD_63"
|
||||
CH6_VNOM="3.3"; CH6_NET="PVDD3_3V_SYNTH_LDO_B3"
|
||||
CH7_VNOM="1.5"; CH7_NET="PVDD1V5_3"
|
||||
CH8_VNOM="0.85"; CH8_NET="P0V85_STBY"
|
||||
CH9_VNOM="1.8"; CH9_NET="P1V8_STBY"
|
||||
CH10_VNOM="-"; CH10_NET="NC"
|
||||
CH11_VNOM="3.3"; CH11_NET="P3V3_STBY"
|
||||
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_2"
|
||||
CH13_VNOM="0.75"; CH13_NET="P0V75_DVDD_55"
|
||||
CH14_VNOM="0.75"; CH14_NET="P0V75_AVDD_55"
|
||||
CH15_VNOM="1.8"; CH15_NET="P1V8_DVDDIO_4"
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=9 # CB F3 Ch9 = SWB1 CONN13/CONN15 (shared with CONN13, addr must differ)
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB1 (CONN15)
|
||||
"1:0x62" # CH0 ~ CH7
|
||||
"1:0x64" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB1 CONN15 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB1 CONN15 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB1 (CONN15)
|
||||
# ============================================================
|
||||
CH0_VNOM="1.524"; CH0_NET="P1V5_AVDD_55"
|
||||
CH1_VNOM="0.915"; CH1_NET="P0V9_AVDD_55"
|
||||
CH2_VNOM="0.75"; CH2_NET="P0V75_DVDD_63"
|
||||
CH3_VNOM="0.756"; CH3_NET="P0V75_AVDD_63"
|
||||
CH4_VNOM="1.524"; CH4_NET="P1V5_AVDD_63"
|
||||
CH5_VNOM="0.915"; CH5_NET="P0V9_AVDD_63"
|
||||
CH6_VNOM="3.38"; CH6_NET="PVDD3_3V_SYNTH_LDO_B3"
|
||||
CH7_VNOM="1.5"; CH7_NET="PVDD1V5_3"
|
||||
CH8_VNOM="0.85"; CH8_NET="P0V85_STBY"
|
||||
CH9_VNOM="1.8"; CH9_NET="P1V8_STBY"
|
||||
CH10_VNOM="-"; CH10_NET="NC"
|
||||
CH11_VNOM="3.3"; CH11_NET="P3V3_STBY"
|
||||
CH12_VNOM="0.91"; CH12_NET="PVDD0V9_2"
|
||||
CH13_VNOM="0.75"; CH13_NET="P0V75_DVDD_55"
|
||||
CH14_VNOM="0.756"; CH14_NET="P0V75_AVDD_55"
|
||||
CH15_VNOM="1.8"; CH15_NET="P1V8_DVDDIO_4"
|
||||
|
||||
+52
-52
@@ -1,52 +1,52 @@
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=9
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB1 (CONN16)
|
||||
"1:0x64" # CH0 ~ CH7
|
||||
"1:0x65" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB1 CONN16 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB1 CONN16 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB1 (CONN16)
|
||||
# ============================================================
|
||||
CH0_VNOM="1.5"; CH0_NET="PVDD1V5_0"
|
||||
CH1_VNOM="1.8"; CH1_NET="P1V8_4"
|
||||
CH2_VNOM="3.3"; CH2_NET="PVDD3_3V_SYNTH_LDO_B5"
|
||||
CH3_VNOM="3.3"; CH3_NET="PVDD3_3V_SYNTH_LDO_A5"
|
||||
CH4_VNOM="3.3"; CH4_NET="PVDD3_3V_SYNTH_LDO_B4"
|
||||
CH5_VNOM="3.3"; CH5_NET="PVDD3_3V_SYNTH_LDO_A4"
|
||||
CH6_VNOM="3.3"; CH6_NET="P3V3"
|
||||
CH7_VNOM="0.8"; CH7_NET="PVDD0_8V_T3"
|
||||
CH8_VNOM="0.75"; CH8_NET="P0V75_DVDD_1"
|
||||
CH9_VNOM="0.75"; CH9_NET="P0V75_AVDD_1"
|
||||
CH10_VNOM="1.5"; CH10_NET="P1V5_AVDD_1"
|
||||
CH11_VNOM="0.9"; CH11_NET="P0V9_AVDD_1"
|
||||
CH12_VNOM="0.9"; CH12_NET="PVDD0V9_0"
|
||||
CH13_VNOM="0.9"; CH13_NET="PVDD0V9_1"
|
||||
CH14_VNOM="0.9"; CH14_NET="PVDD0V9_3"
|
||||
CH15_VNOM="1.2"; CH15_NET="PVDD1V2_T3"
|
||||
# Blanton Channel Settings
|
||||
# Format: CH<n>_VNOM=voltage CH<n>_NET=net_name
|
||||
#
|
||||
# Channel numbering (Script Channel, per Blanton_Margin_List):
|
||||
# ch_global / 8 -> CHIPS index (0~17)
|
||||
# ch_global % 8 -> page within LTC2977 (0~7)
|
||||
# One LTC2980 = two LTC2977 (8ch each), controlled via 2 I2C addresses.
|
||||
|
||||
# --- SWB transport (added): this LTC2980 sits behind the CB FPGA F3 I2C; reach
|
||||
# it with cb_pmbus, not i2cset. CB_I2C_CH = FPGA I2C channel for this CONN. ---
|
||||
TRANSPORT="swb"
|
||||
CB_I2C_CH=7 # CB F3 Ch7 = SWB1 CONN14/CONN16 (shared with CONN14, addr must differ)
|
||||
|
||||
# --- I2C Configuration ---
|
||||
|
||||
# Format: "bus:address" (8 channels per entry / per LTC2977)
|
||||
CHIPS=(
|
||||
# chip1: SWB1 (CONN16)
|
||||
"1:0x62" # CH0 ~ CH7
|
||||
"1:0x64" # CH8 ~ CH15
|
||||
)
|
||||
|
||||
# Pre-commands to run before accessing each chip (empty = none)
|
||||
# Multiple commands separated by ;
|
||||
CHIP_PRE_CMD=(
|
||||
"" # SWB1 CONN16 (lo)
|
||||
)
|
||||
|
||||
# Post-commands to run after accessing each chip (optional, empty = none)
|
||||
CHIP_POST_CMD=(
|
||||
"" # SWB1 CONN16 (lo)
|
||||
)
|
||||
|
||||
# ============================================================
|
||||
# chip1: SWB1 (CONN16)
|
||||
# ============================================================
|
||||
CH0_VNOM="1.5"; CH0_NET="PVDD1V5_0"
|
||||
CH1_VNOM="1.816"; CH1_NET="P1V8_4"
|
||||
CH2_VNOM="3.38"; CH2_NET="PVDD3_3V_SYNTH_LDO_B5"
|
||||
CH3_VNOM="3.38"; CH3_NET="PVDD3_3V_SYNTH_LDO_A5"
|
||||
CH4_VNOM="3.38"; CH4_NET="PVDD3_3V_SYNTH_LDO_B4"
|
||||
CH5_VNOM="3.38"; CH5_NET="PVDD3_3V_SYNTH_LDO_A4"
|
||||
CH6_VNOM="3.327"; CH6_NET="P3V3"
|
||||
CH7_VNOM="0.82"; CH7_NET="PVDD0_8V_T3"
|
||||
CH8_VNOM="0.75"; CH8_NET="P0V75_DVDD_1"
|
||||
CH9_VNOM="0.756"; CH9_NET="P0V75_AVDD_1"
|
||||
CH10_VNOM="1.524"; CH10_NET="P1V5_AVDD_1"
|
||||
CH11_VNOM="0.915"; CH11_NET="P0V9_AVDD_1"
|
||||
CH12_VNOM="0.915"; CH12_NET="PVDD0V9_0"
|
||||
CH13_VNOM="0.91"; CH13_NET="PVDD0V9_1"
|
||||
CH14_VNOM="0.915"; CH14_NET="PVDD0V9_3"
|
||||
CH15_VNOM="1.224"; CH15_NET="PVDD1V2_T3"
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# TH6_SWB0_power_readback.sh -- SWB0 rail power from the platform sensors
|
||||
# =============================================================================
|
||||
# Version History:
|
||||
# V1.1.0 2026-08-28 'show platform voltage' and 'show platform current' are
|
||||
# now read ONCE each instead of once per rail. The old
|
||||
# loop ran them 19 times apiece (38 invocations of a slow
|
||||
# Python CLI) and every sample came from a different
|
||||
# instant, so the rails were never actually measured
|
||||
# together. Output format is unchanged.
|
||||
# Rails missing from the tables are reported on stderr
|
||||
# instead of silently contributing 0.000 V / 0.00 W.
|
||||
# V1.0.0 2026-08-28 First version.
|
||||
# =============================================================================
|
||||
#
|
||||
# Reads the two platform sensor tables:
|
||||
# 'show platform voltage' -> <RAIL> in mV
|
||||
# 'show platform current' -> <RAIL>_CURRENT in mA
|
||||
# and reports V x I per rail plus the total.
|
||||
#
|
||||
# For a loaded reading, start traffic first: blanton_tr518.sh start
|
||||
# =============================================================================
|
||||
|
||||
# --- Rails to report, in output order (edit this list) ---
|
||||
rails=(
|
||||
"SWB0_0V9_ANLG0"
|
||||
"SWB0_0V9_ANLG1"
|
||||
"SWB0_0V75_ANLG0"
|
||||
"SWB0_0V75_ANLG1"
|
||||
"SWB0_PHYTILE_P0"
|
||||
"SWB0_PHYTILE_P1"
|
||||
"SWB0_PHYTILE_P2"
|
||||
"SWB0_PHYTILE_P3"
|
||||
"SWB0_PHYTILE_P4"
|
||||
"SWB0_PHYTILE_P5"
|
||||
"SWB0_PHYTILE_P6"
|
||||
"SWB0_PHYTILE_P7"
|
||||
"SWB0_PVDD1V5_CNDR0"
|
||||
"SWB0_PVDD1V5_CNDR1"
|
||||
"SWB0_PVDDA_PHYT0"
|
||||
"SWB0_PVDDA_PHYT1"
|
||||
"SWB0_PVDDA_PHYT2"
|
||||
"SWB0_PVDDA_PHYT3"
|
||||
"SWB0_TH6_CORE"
|
||||
)
|
||||
|
||||
# --- One snapshot of each table ---------------------------------------------
|
||||
# Both are taken up front, back to back, so every rail below comes from the same
|
||||
# moment. Under tr 518 the currents move a lot; re-reading per rail meant the
|
||||
# total was a sum of readings taken seconds apart.
|
||||
V_TABLE="$(show platform voltage 2>/dev/null)"
|
||||
C_TABLE="$(show platform current 2>/dev/null)"
|
||||
|
||||
if [ -z "$V_TABLE" ] || [ -z "$C_TABLE" ]; then
|
||||
echo "ERROR: 'show platform voltage/current' returned nothing" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Join and report ---------------------------------------------------------
|
||||
# Sensor name is field 1 and the value field 2 in both tables; header and rule
|
||||
# lines drop out because their field 2 is not numeric.
|
||||
{
|
||||
printf '%s\n' "$V_TABLE"
|
||||
echo "@@@SPLIT@@@"
|
||||
printf '%s\n' "$C_TABLE"
|
||||
} | awk -v rails="${rails[*]}" '
|
||||
BEGIN { n = split(rails, R, " "); sec = 1 }
|
||||
/^@@@SPLIT@@@$/ { sec = 2; next }
|
||||
{
|
||||
if (NF < 2) next
|
||||
name = $1; val = $2
|
||||
if (val !~ /^[0-9]+(\.[0-9]+)?$/) next # header / ---- / blank
|
||||
if (sec == 2) CUR[name] = val + 0
|
||||
else VOLT[name] = val + 0
|
||||
}
|
||||
END {
|
||||
total = 0
|
||||
for (i = 1; i <= n; i++) {
|
||||
rail = R[i]; cname = rail "_CURRENT"
|
||||
haveV = (rail in VOLT); haveC = (cname in CUR)
|
||||
if (!haveV || !haveC)
|
||||
printf "WARN: %s missing from the sensor table (%s%s%s) -- counted as 0 W\n", \
|
||||
rail, (haveV ? "" : "no voltage"), \
|
||||
((!haveV && !haveC) ? ", " : ""), \
|
||||
(haveC ? "" : "no current") > "/dev/stderr"
|
||||
v = haveV ? VOLT[rail] : 0
|
||||
c = haveC ? CUR[cname] : 0
|
||||
p = sprintf("%.2f", (v/1000)*(c/1000))
|
||||
printf "%s: Voltage=%.3f V, Current=%.3f A, Power=%.2f W\n", rail, v/1000, c/1000, p
|
||||
total = sprintf("%.2f", total + p)
|
||||
}
|
||||
print "----------------------------------------"
|
||||
printf "TOTAL POWER: %.2f W\n", total
|
||||
}'
|
||||
@@ -0,0 +1,95 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# TH6_SWB1_power_readback.sh -- SWB1 rail power from the platform sensors
|
||||
# =============================================================================
|
||||
# Version History:
|
||||
# V1.1.0 2026-08-28 'show platform voltage' and 'show platform current' are
|
||||
# now read ONCE each instead of once per rail. The old
|
||||
# loop ran them 19 times apiece (38 invocations of a slow
|
||||
# Python CLI) and every sample came from a different
|
||||
# instant, so the rails were never actually measured
|
||||
# together. Output format is unchanged.
|
||||
# Rails missing from the tables are reported on stderr
|
||||
# instead of silently contributing 0.000 V / 0.00 W.
|
||||
# V1.0.0 2026-08-28 First version.
|
||||
# =============================================================================
|
||||
#
|
||||
# Reads the two platform sensor tables:
|
||||
# 'show platform voltage' -> <RAIL> in mV
|
||||
# 'show platform current' -> <RAIL>_CURRENT in mA
|
||||
# and reports V x I per rail plus the total.
|
||||
#
|
||||
# For a loaded reading, start traffic first: blanton_tr518.sh start
|
||||
# =============================================================================
|
||||
|
||||
# --- Rails to report, in output order (edit this list) ---
|
||||
rails=(
|
||||
"SWB1_0V9_ANLG0"
|
||||
"SWB1_0V9_ANLG1"
|
||||
"SWB1_0V75_ANLG0"
|
||||
"SWB1_0V75_ANLG1"
|
||||
"SWB1_PHYTILE_P0"
|
||||
"SWB1_PHYTILE_P1"
|
||||
"SWB1_PHYTILE_P2"
|
||||
"SWB1_PHYTILE_P3"
|
||||
"SWB1_PHYTILE_P4"
|
||||
"SWB1_PHYTILE_P5"
|
||||
"SWB1_PHYTILE_P6"
|
||||
"SWB1_PHYTILE_P7"
|
||||
"SWB1_PVDD1V5_CNDR0"
|
||||
"SWB1_PVDD1V5_CNDR1"
|
||||
"SWB1_PVDDA_PHYT0"
|
||||
"SWB1_PVDDA_PHYT1"
|
||||
"SWB1_PVDDA_PHYT2"
|
||||
"SWB1_PVDDA_PHYT3"
|
||||
"SWB1_TH6_CORE"
|
||||
)
|
||||
|
||||
# --- One snapshot of each table ---------------------------------------------
|
||||
# Both are taken up front, back to back, so every rail below comes from the same
|
||||
# moment. Under tr 518 the currents move a lot; re-reading per rail meant the
|
||||
# total was a sum of readings taken seconds apart.
|
||||
V_TABLE="$(show platform voltage 2>/dev/null)"
|
||||
C_TABLE="$(show platform current 2>/dev/null)"
|
||||
|
||||
if [ -z "$V_TABLE" ] || [ -z "$C_TABLE" ]; then
|
||||
echo "ERROR: 'show platform voltage/current' returned nothing" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- Join and report ---------------------------------------------------------
|
||||
# Sensor name is field 1 and the value field 2 in both tables; header and rule
|
||||
# lines drop out because their field 2 is not numeric.
|
||||
{
|
||||
printf '%s\n' "$V_TABLE"
|
||||
echo "@@@SPLIT@@@"
|
||||
printf '%s\n' "$C_TABLE"
|
||||
} | awk -v rails="${rails[*]}" '
|
||||
BEGIN { n = split(rails, R, " "); sec = 1 }
|
||||
/^@@@SPLIT@@@$/ { sec = 2; next }
|
||||
{
|
||||
if (NF < 2) next
|
||||
name = $1; val = $2
|
||||
if (val !~ /^[0-9]+(\.[0-9]+)?$/) next # header / ---- / blank
|
||||
if (sec == 2) CUR[name] = val + 0
|
||||
else VOLT[name] = val + 0
|
||||
}
|
||||
END {
|
||||
total = 0
|
||||
for (i = 1; i <= n; i++) {
|
||||
rail = R[i]; cname = rail "_CURRENT"
|
||||
haveV = (rail in VOLT); haveC = (cname in CUR)
|
||||
if (!haveV || !haveC)
|
||||
printf "WARN: %s missing from the sensor table (%s%s%s) -- counted as 0 W\n", \
|
||||
rail, (haveV ? "" : "no voltage"), \
|
||||
((!haveV && !haveC) ? ", " : ""), \
|
||||
(haveC ? "" : "no current") > "/dev/stderr"
|
||||
v = haveV ? VOLT[rail] : 0
|
||||
c = haveC ? CUR[cname] : 0
|
||||
p = sprintf("%.2f", (v/1000)*(c/1000))
|
||||
printf "%s: Voltage=%.3f V, Current=%.3f A, Power=%.2f W\n", rail, v/1000, c/1000, p
|
||||
total = sprintf("%.2f", total + p)
|
||||
}
|
||||
print "----------------------------------------"
|
||||
printf "TOTAL POWER: %.2f W\n", total
|
||||
}'
|
||||
@@ -0,0 +1,204 @@
|
||||
#!/bin/sh
|
||||
# =============================================================================
|
||||
# bcm_dsc_parse_V1.0.0.sh
|
||||
#
|
||||
# Author : ETWen
|
||||
# Date : 20260906
|
||||
#
|
||||
# Version History
|
||||
# V1.0.0 20260906 Initial Version
|
||||
#
|
||||
# Description:
|
||||
# Parse Broadcom diag shell "phydiag <pm_id> dsc" raw log into CSV.
|
||||
# 支援多個 pm_id 串接在同一份 log,以 "pm_id =" 當 record separator。
|
||||
#
|
||||
# Output:
|
||||
# <prefix>_lane.csv : 每個 lane 一列(TXEQ / RXFFE / DFE / EYE / SNR ...)
|
||||
# <prefix>_pm.csv : 每個 pm_id 一列(溫度 / PLL / lane 數 / SNR-EYE 統計)
|
||||
#
|
||||
# Usage:
|
||||
# ./bcm_dsc_parse_V1.0.0.sh -i dsc_raw.log [-o out_prefix]
|
||||
#
|
||||
# Design notes:
|
||||
# - 純 POSIX sh + awk(mawk 相容),不依賴 Python。
|
||||
# - Lane row 採「括號群組出現順序」抽取,而非固定欄位位置,對排版空白
|
||||
# 變動免疫。SDK 若增減欄位,群組數不等於 9,該列會被標記 UNPARSED
|
||||
# 並輸出到 stderr,不會靜默解析錯誤。
|
||||
# - 已知 header 名稱數與資料欄數不一致之處:
|
||||
# * (P RX, CDRxN, UC_CFG, UC_STS, RST, STP) 6 個名字 / 7 個值
|
||||
# (RST 實際是 "0,0" 兩欄)
|
||||
# * TXEQ 尾端多一個逗號
|
||||
# * AVG_TMON 顯示為 "(11) 66C" 兩個 token
|
||||
# - SD / LCK 的 "*" 為 sticky 旗標,本版拆成獨立欄位保留,不做判讀。
|
||||
# - BER 欄若為 "!chk_en" 表示 checker 未開啟,值無效,原樣保留。
|
||||
# =============================================================================
|
||||
|
||||
set -e
|
||||
|
||||
IN=""
|
||||
PREFIX="dsc"
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 -i <raw_log> [-o <out_prefix>]" >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
while getopts "i:o:h" opt; do
|
||||
case "$opt" in
|
||||
i) IN="$OPTARG" ;;
|
||||
o) PREFIX="$OPTARG" ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
[ -n "$IN" ] || usage
|
||||
[ -f "$IN" ] || { echo "ERROR: input not found: $IN" >&2; exit 2; }
|
||||
|
||||
LANE_CSV="${PREFIX}_lane.csv"
|
||||
PM_CSV="${PREFIX}_pm.csv"
|
||||
|
||||
# 先去掉 CR(console / telnet log 常帶),再交給 awk
|
||||
tr -d '\r' < "$IN" | awk -v LANE_CSV="$LANE_CSV" -v PM_CSV="$PM_CSV" '
|
||||
function trim(s) { sub(/^[ \t]+/, "", s); sub(/[ \t]+$/, "", s); return s }
|
||||
|
||||
# 掃描一列,取出所有頂層括號群組到 G[],群組前的英數 prefix 到 P[],
|
||||
# 其餘純量文字留在 REST。回傳群組數。
|
||||
function split_groups(line, i, ch, d, buf, ng, rest, prefix) {
|
||||
split("", G, ":"); split("", P, ":")
|
||||
ng = 0; d = 0; buf = ""; rest = ""; prefix = ""
|
||||
for (i = 1; i <= length(line); i++) {
|
||||
ch = substr(line, i, 1)
|
||||
if (ch == "(") {
|
||||
d++
|
||||
if (d == 1) {
|
||||
buf = ""; prefix = ""
|
||||
if (match(rest, /[A-Za-z_]+$/)) {
|
||||
prefix = substr(rest, RSTART, RLENGTH)
|
||||
rest = substr(rest, 1, RSTART - 1)
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
if (ch == ")") {
|
||||
d--
|
||||
if (d == 0) { ng++; G[ng] = buf; P[ng] = prefix; rest = rest " "; continue }
|
||||
}
|
||||
if (d > 0) { buf = buf ch; continue }
|
||||
rest = rest ch
|
||||
}
|
||||
REST = rest
|
||||
return ng
|
||||
}
|
||||
|
||||
# 取括號群組的第 n 個子欄位(以逗號分隔)
|
||||
function gf(idx, n, a, c) {
|
||||
c = split(G[idx], a, ",")
|
||||
if (n > c) return ""
|
||||
return trim(a[n])
|
||||
}
|
||||
|
||||
function is_num(s) { return (s ~ /^[+-]?[0-9]+(\.[0-9]+)?$/) }
|
||||
|
||||
function reset_pm() {
|
||||
core = ""; sdtype = ""; hw_lanes = ""; lane_sel = ""
|
||||
live_temp = ""; avg_tmon = ""; pll_lock = ""
|
||||
n_lane = 0; snr_min = ""; snr_max = ""; eye_min = ""; all_lck = 1
|
||||
}
|
||||
|
||||
function flush_pm() {
|
||||
if (pm == "") return
|
||||
printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n",
|
||||
pm, core, sdtype, hw_lanes, lane_sel, n_lane,
|
||||
live_temp, avg_tmon, pll_lock,
|
||||
(snr_min == "" ? "NA" : snr_min),
|
||||
(eye_min == "" ? "NA" : eye_min),
|
||||
(n_lane == 0 ? "NA" : (all_lck ? "PASS" : "FAIL")) > PM_CSV
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
pm = ""; in_lane = 0; core_row = 0; bad = 0
|
||||
print "pm_id,core,lane,serdes_type,sd,sd_sticky,lck,lck_sticky,rxppm,txppm," \
|
||||
"txeq_n3,txeq_n2,txeq_n1,txeq_m,txeq_p1,txeq_p2,txeq_sum," \
|
||||
"rxffe_n3,rxffe_n2,rxffe_n1,rxffe_m,rxffe_p1,rxffe_p2," \
|
||||
"dfe1,dfe2,pf_m,pf_l,pf_h,vga,dco,tp0,tp1,tp2,flt_m,flt_s," \
|
||||
"nlc_u,nlc_l,eye_u,eye_m,eye_l,link_time,snr,ber," \
|
||||
"live_temp,avg_tmon,pll_lock,rx_pol,cdr,uc_cfg,uc_sts,rst,stp" > LANE_CSV
|
||||
print "pm_id,core,serdes_type,hw_lanes,lane_select,active_lanes," \
|
||||
"live_temp,avg_tmon,pll_lock,snr_min,eye_min,lck_all" > PM_CSV
|
||||
}
|
||||
|
||||
/^pm_id[ \t]*=/ { flush_pm(); pm = $NF; reset_pm(); in_lane = 0; next }
|
||||
/^Core[ \t]*=/ { if (match($0, /Core[ \t]*=[ \t]*[0-9]+/)) { core = $0; sub(/.*Core[ \t]*=[ \t]*/, "", core); sub(/[^0-9].*/, "", core) } next }
|
||||
/^SerDes type[ \t]*=/ { sdtype = $NF; next }
|
||||
/^Rev ID # Lanes/ { hw_lanes = $NF; next }
|
||||
/^lane_select[ \t]*=/ { lane_sel = $NF; next }
|
||||
|
||||
/^CORE[ \t]+RST_ST/ { core_row = 1; next }
|
||||
core_row == 1 {
|
||||
line = $0
|
||||
gsub(/\([^)]*\)[ \t]*/, "", line) # 去掉 AVG_TMON 的 "(11)"
|
||||
n = split(trim(line), c, /[ \t]+/)
|
||||
if (n >= 15) { live_temp = c[9]; avg_tmon = c[10]; pll_lock = c[15] }
|
||||
core_row = 0
|
||||
next
|
||||
}
|
||||
|
||||
/^LN[ \t]*\(/ { in_lane = 1; next }
|
||||
/SERDES DISPLAY DIAG DATA END/ { in_lane = 0; next }
|
||||
|
||||
in_lane && /^[0-9]+[ \t]*\(/ {
|
||||
ng = split_groups($0)
|
||||
if (ng != 9) {
|
||||
printf "UNPARSED (groups=%d) pm_id=%s: %s\n", ng, pm, $0 > "/dev/stderr"
|
||||
bad++
|
||||
next
|
||||
}
|
||||
nr = split(trim(REST), r, /[ \t]+/)
|
||||
if (nr != 10) {
|
||||
printf "UNPARSED (scalars=%d) pm_id=%s: %s\n", nr, pm, $0 > "/dev/stderr"
|
||||
bad++
|
||||
next
|
||||
}
|
||||
|
||||
lane = r[1]
|
||||
sd = r[2]; sd_st = (sd ~ /\*/) ? 1 : 0; gsub(/\*/, "", sd)
|
||||
lck = r[3]; lck_st = (lck ~ /\*/) ? 1 : 0; gsub(/\*/, "", lck)
|
||||
rxppm = r[4]; vga = r[5]; dco = r[6]; txppm = r[7]
|
||||
link_time = r[8]; snr = r[9]; ber = r[10]
|
||||
|
||||
# TXEQ 六個 tap 與總和(僅在全為數值時計算)
|
||||
tsum = 0; tok = 1
|
||||
for (i = 1; i <= 6; i++) {
|
||||
tq[i] = gf(7, i)
|
||||
if (is_num(tq[i])) tsum += tq[i]; else tok = 0
|
||||
}
|
||||
|
||||
printf "%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,", pm, core, lane, sdtype, sd, sd_st, lck, lck_st, rxppm, txppm > LANE_CSV
|
||||
printf "%s,%s,%s,%s,%s,%s,%s,", tq[1], tq[2], tq[3], tq[4], tq[5], tq[6], (tok ? tsum : "NA") > LANE_CSV
|
||||
printf "%s,%s,%s,%s,%s,%s,", gf(4,1), gf(4,2), gf(4,3), gf(4,4), gf(4,5), gf(4,6) > LANE_CSV
|
||||
printf "%s,%s,", gf(5,1), gf(5,2) > LANE_CSV
|
||||
printf "%s,%s,%s,%s,%s,", gf(2,1), gf(2,2), gf(2,3), vga, dco > LANE_CSV
|
||||
printf "%s,%s,%s,%s,%s,", gf(3,1), gf(3,2), gf(3,3), gf(6,1), gf(6,2) > LANE_CSV
|
||||
printf "%s,%s,%s,%s,%s,", gf(8,1), gf(8,2), gf(9,1), gf(9,2), gf(9,3) > LANE_CSV
|
||||
printf "%s,%s,%s,", link_time, snr, ber > LANE_CSV
|
||||
printf "%s,%s,%s,", live_temp, avg_tmon, pll_lock > LANE_CSV
|
||||
printf "%s,%s,%s,%s,%s/%s,%s\n", gf(1,1), gf(1,2), gf(1,3), gf(1,4), gf(1,5), gf(1,6), gf(1,7) > LANE_CSV
|
||||
|
||||
# per-PM 統計
|
||||
n_lane++
|
||||
if (lck != "1" || sd != "1") all_lck = 0
|
||||
if (is_num(snr)) { if (snr_min == "" || snr + 0 < snr_min + 0) snr_min = snr }
|
||||
for (i = 1; i <= 3; i++) {
|
||||
e = gf(9, i)
|
||||
if (is_num(e)) { if (eye_min == "" || e + 0 < eye_min + 0) eye_min = e }
|
||||
}
|
||||
next
|
||||
}
|
||||
|
||||
END {
|
||||
flush_pm()
|
||||
if (bad > 0) printf "WARN: %d lane row(s) unparsed\n", bad > "/dev/stderr"
|
||||
}
|
||||
'
|
||||
|
||||
echo "OK: ${LANE_CSV}, ${PM_CSV}"
|
||||
@@ -0,0 +1,347 @@
|
||||
#!/bin/sh
|
||||
# =============================================================================
|
||||
# bcm_dsc_scan.sh
|
||||
#
|
||||
# Author : ETWen
|
||||
# Date : 20260906
|
||||
#
|
||||
# Version History
|
||||
# V1.0.0 20260906 Initial Version
|
||||
# V1.1.0 20260906 Log 預設輸出至 <script_dir>/log,掃描後自動複製到
|
||||
# /host/hw-eval/jobs/;非 tty 環境改用逐行進度輸出,
|
||||
# 避免灌爆 Tera Term logopen 的 log
|
||||
# V1.2.0 20260906 新增 -f 自訂 log 檔名(支援 %u / %t 佔位符)與
|
||||
# -F 強制覆蓋;預設不覆蓋既有檔案,自動加序號
|
||||
# V1.3.0 20260907 修正 bcmcmd 讀取 stdin 導致掃描迴圈在第一筆之後
|
||||
# 提前結束的問題(迴圈改用 fd 3,bcmcmd 導向
|
||||
# /dev/null);新增實際迭代筆數與清單筆數的檢查
|
||||
#
|
||||
# Description:
|
||||
# 在 Blanton SONiC DUT 上批次執行 Broadcom diag shell 的
|
||||
# "phydiag <port> dsc",收集 raw log 供離線解析。
|
||||
#
|
||||
# 實際下的指令為:
|
||||
# bcmcmd -n <unit> -c "dsh -c 'phydiag <port> dsc'"
|
||||
#
|
||||
# Deployment:
|
||||
# Script : /root/Blanton_Script/bcm_dsc_scan.sh
|
||||
# Log : /root/Blanton_Script/log/dsc_raw_u<unit>_<YYYYmmdd_HHMMSS>.log
|
||||
# Copy : /host/hw-eval/jobs/
|
||||
#
|
||||
# Log 檔名可用 -f 覆寫,支援兩個佔位符:
|
||||
# %u -> u0 / u1
|
||||
# %t -> YYYYmmdd_HHMMSS
|
||||
# -f 只接受檔名,不接受路徑;目錄一律由 -o 決定。
|
||||
# 同時掃兩個 unit 但檔名未含 %u 時,會自動在副檔名前插入 _u<unit>,
|
||||
# 避免第二個 unit 覆蓋掉第一個。
|
||||
#
|
||||
# 路徑由 $0 推導,不依賴 $HOME。Script A 以 sudo -i 執行時 ~ 為 /root,
|
||||
# 直接寫死 ~ 會有風險,故一律使用絕對路徑。
|
||||
#
|
||||
# Usage:
|
||||
# ./bcm_dsc_scan.sh # unit 0 與 1 都掃,掃完自動複製
|
||||
# ./bcm_dsc_scan.sh -u 0 # 只掃 unit 0
|
||||
# ./bcm_dsc_scan.sh -n # dry-run,只列出要掃的 port
|
||||
# ./bcm_dsc_scan.sh -C # 不複製到 /host/hw-eval/jobs
|
||||
# ./bcm_dsc_scan.sh -c /other/dir # 指定複製目的地
|
||||
# ./bcm_dsc_scan.sh -u 0 -f dsc_before_reboot.log
|
||||
# ./bcm_dsc_scan.sh -f blanton_dsc_%u_%t.log
|
||||
#
|
||||
# Exit code:
|
||||
# 0 = 全部 port 皆取得完整 dump
|
||||
# 1 = 有 port 未取得完整 dump,或複製失敗
|
||||
# 2 = 參數 / 路徑錯誤
|
||||
# 3 = 找不到 bcmcmd
|
||||
#
|
||||
# 結束時固定輸出一行 "### DSC_SCAN_DONE rc=<n>",供 TTL 端 wait 判斷。
|
||||
#
|
||||
# Design notes:
|
||||
# - 純 POSIX sh,不依賴 bash / Python。
|
||||
# - Port 清單以「範圍字串」定義在下方 PORTS_* 變數,展開後去重。
|
||||
# 100G 清單先展開,故重複的 port 會被判定為 100G(目前僅 port 268)。
|
||||
# - bcmcmd 即使指令失敗通常仍回傳 0,因此不以 exit code 判斷成功與否;
|
||||
# 改由 marker 行 + "SERDES DISPLAY DIAG DATA END" 數量比對。
|
||||
# - 先寫入本機 log 目錄再複製,而非直接寫遠端,避免中途失敗遺失整份資料。
|
||||
#
|
||||
# Assumptions:
|
||||
# - unit 0 與 unit 1 使用相同的 port 清單。
|
||||
# - phydiag 的參數為此清單中的 port 編號(非 port name)。
|
||||
# - 由 root 執行(Script A 的 sudo -i 之後),故不呼叫 sudo。
|
||||
#
|
||||
# Cautions:
|
||||
# - 全清單約 445 port x 2 unit,估計 10 分鐘,請勿把 DELAY 設為 0。
|
||||
# - phydiag ... dsc 為唯讀操作,不會變更 SerDes 設定。
|
||||
# =============================================================================
|
||||
|
||||
set -u
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Port list (以空白分隔的範圍或單一值)
|
||||
# ----------------------------------------------------------------------------
|
||||
PORTS_100G="268"
|
||||
PORTS_200G="1-24 40-96 112-168 184-240 256-308 310-327 342-380 382-399 414-452 454-471 486-524 526-543 558-565"
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Paths / defaults
|
||||
# ----------------------------------------------------------------------------
|
||||
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) || exit 2
|
||||
|
||||
UNITS="0 1"
|
||||
OUTDIR="${SCRIPT_DIR}/log"
|
||||
COPYDIR="/host/hw-eval/jobs"
|
||||
DELAY="0.2"
|
||||
DRYRUN=0
|
||||
DOCOPY=1
|
||||
LOGNAME="" # -f 指定的 log 檔名,空字串表示使用預設命名
|
||||
FORCE=0 # -F 允許覆蓋既有檔案
|
||||
PROGRESS_EVERY=50 # 非 tty 環境每 N 筆印一行進度
|
||||
|
||||
usage() {
|
||||
cat >&2 << 'USAGE'
|
||||
Usage: bcm_dsc_scan.sh [-u <0|1>] [-o <outdir>] [-f <logname>] [-F]
|
||||
[-c <copydir>] [-C] [-d <sec>] [-n] [-h]
|
||||
|
||||
-u <unit> 只掃指定 unit。省略則 unit 0 與 1 都掃。
|
||||
-o <dir> log 輸出目錄 (default: <script_dir>/log)
|
||||
-f <name> 自訂 log 檔名(僅檔名,不含路徑)
|
||||
佔位符: %u -> u0/u1 , %t -> YYYYmmdd_HHMMSS
|
||||
default: dsc_raw_%u_%t.log
|
||||
-F 允許覆蓋既有同名檔案 (default: 自動加序號 _1 / _2 ...)
|
||||
-c <dir> 掃描後複製目的地 (default: /host/hw-eval/jobs)
|
||||
-C 不複製
|
||||
-d <sec> 每筆 phydiag 之間的間隔 (default: 0.2)
|
||||
-n dry-run,列出展開後的 port 清單與指令,不實際執行
|
||||
-h 顯示此說明
|
||||
USAGE
|
||||
exit 1
|
||||
}
|
||||
|
||||
while getopts "u:o:f:Fc:Cd:nh" opt; do
|
||||
case "$opt" in
|
||||
u)
|
||||
case "$OPTARG" in
|
||||
0|1) UNITS="$OPTARG" ;;
|
||||
*) echo "ERROR: -u 只接受 0 或 1 (got: $OPTARG)" >&2; exit 2 ;;
|
||||
esac
|
||||
;;
|
||||
o) OUTDIR="$OPTARG" ;;
|
||||
f)
|
||||
case "$OPTARG" in
|
||||
"") echo "ERROR: -f 不可為空" >&2; exit 2 ;;
|
||||
*/*) echo "ERROR: -f 只接受檔名,路徑請用 -o (got: $OPTARG)" >&2; exit 2 ;;
|
||||
*) LOGNAME="$OPTARG" ;;
|
||||
esac
|
||||
;;
|
||||
F) FORCE=1 ;;
|
||||
c) COPYDIR="$OPTARG" ;;
|
||||
C) DOCOPY=0 ;;
|
||||
d) DELAY="$OPTARG" ;;
|
||||
n) DRYRUN=1 ;;
|
||||
*) usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
mkdir -p "$OUTDIR" 2>/dev/null || { echo "ERROR: cannot create outdir: $OUTDIR" >&2; exit 2; }
|
||||
[ -w "$OUTDIR" ] || { echo "ERROR: outdir not writable: $OUTDIR" >&2; exit 2; }
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# sleep 是否支援小數秒(busybox sleep 可能只吃整數)
|
||||
# ----------------------------------------------------------------------------
|
||||
if ! sleep "$DELAY" 2>/dev/null; then
|
||||
echo "WARN: sleep '$DELAY' 不支援,改用 sleep 1" >&2
|
||||
DELAY="1"
|
||||
fi
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# 展開 port 清單。100G 先展開,重複者以 100G 為準。
|
||||
# 輸出格式: "<port>,<speed>",依 port 數值排序。
|
||||
# ----------------------------------------------------------------------------
|
||||
PORTFILE=$(mktemp) || { echo "ERROR: mktemp failed" >&2; exit 2; }
|
||||
trap 'rm -f "$PORTFILE"' EXIT
|
||||
trap 'echo "" >&2; echo "### DSC_SCAN_DONE rc=130 (INTERRUPTED)" >&2; rm -f "$PORTFILE"; exit 130' INT TERM
|
||||
|
||||
awk -v a="$PORTS_100G" -v b="$PORTS_200G" '
|
||||
function expand(s, spd, n, i, j, p, k, lo, hi) {
|
||||
n = split(s, p, /[ \t]+/)
|
||||
for (i = 1; i <= n; i++) {
|
||||
if (p[i] == "") continue
|
||||
if (split(p[i], k, "-") == 2) { lo = k[1] + 0; hi = k[2] + 0 }
|
||||
else { lo = p[i] + 0; hi = lo }
|
||||
if (hi < lo) { printf "ERROR: bad range %s\n", p[i] > "/dev/stderr"; continue }
|
||||
for (j = lo; j <= hi; j++) if (!(j in SPD)) SPD[j] = spd
|
||||
}
|
||||
}
|
||||
BEGIN {
|
||||
expand(a, "100G") # 先展開 100G,重複的 port 由 100G 取得
|
||||
expand(b, "200G")
|
||||
for (p in SPD) print p "," SPD[p]
|
||||
}' | sort -t, -k1,1n > "$PORTFILE"
|
||||
|
||||
TOTAL=$(wc -l < "$PORTFILE" | tr -d ' ')
|
||||
[ "$TOTAL" -gt 0 ] || { echo "ERROR: port list is empty" >&2; exit 2; }
|
||||
|
||||
N100=$(grep -c ',100G$' "$PORTFILE" || true)
|
||||
N200=$(grep -c ',200G$' "$PORTFILE" || true)
|
||||
|
||||
echo "Script dir : $SCRIPT_DIR" >&2
|
||||
echo "Log dir : $OUTDIR" >&2
|
||||
echo "Port list : $TOTAL ports (200G x2: $N200, 100G: $N100)" >&2
|
||||
echo "Units : $UNITS" >&2
|
||||
echo "Delay : ${DELAY}s" >&2
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Dry-run
|
||||
# ----------------------------------------------------------------------------
|
||||
if [ "$DRYRUN" -eq 1 ]; then
|
||||
for U in $UNITS; do
|
||||
echo "--- unit $U ---"
|
||||
while IFS=, read -r P SPD; do
|
||||
printf 'bcmcmd -n %s -c "dsh -c '\''phydiag %s dsc'\''" # %s\n' "$U" "$P" "$SPD"
|
||||
done < "$PORTFILE"
|
||||
done
|
||||
echo "### DSC_SCAN_DONE rc=0 (dry-run)" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
command -v bcmcmd > /dev/null 2>&1 || {
|
||||
echo "ERROR: bcmcmd not found in PATH" >&2
|
||||
echo "### DSC_SCAN_DONE rc=3" >&2
|
||||
exit 3
|
||||
}
|
||||
|
||||
# stderr 是 tty 才用 \r 進度條;被導向檔案(Tera Term logopen)時改逐行輸出
|
||||
if [ -t 2 ]; then TTY=1; else TTY=0; fi
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Log 檔名處理
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# 純 POSIX 的字串取代,避免 sed 對檔名中的特殊字元誤判
|
||||
replace_all() { # $1=haystack $2=needle $3=replacement
|
||||
_s=$1; _n=$2; _r=$3; _out=""
|
||||
while :; do
|
||||
case "$_s" in
|
||||
*"$_n"*)
|
||||
_out="${_out}${_s%%"$_n"*}${_r}"
|
||||
_s=${_s#*"$_n"}
|
||||
;;
|
||||
*) _out="${_out}${_s}"; break ;;
|
||||
esac
|
||||
done
|
||||
printf '%s' "$_out"
|
||||
}
|
||||
|
||||
# 依 unit 組出 log 檔名。未指定 -f 時使用預設命名。
|
||||
build_logname() { # $1=unit
|
||||
_u=$1
|
||||
_n=${LOGNAME:-dsc_raw_%u_%t.log}
|
||||
case "$_n" in *%u*) _has_u=1 ;; *) _has_u=0 ;; esac
|
||||
_n=$(replace_all "$_n" '%u' "u${_u}")
|
||||
_n=$(replace_all "$_n" '%t' "$TS")
|
||||
# 掃兩個 unit 但檔名沒有 %u,第二個 unit 會覆蓋第一個,故自動加上 _u<unit>
|
||||
if [ "$_has_u" -eq 0 ] && [ "$MULTI" -eq 1 ]; then
|
||||
case "$_n" in
|
||||
*.*) _n="${_n%.*}_u${_u}.${_n##*.}" ;;
|
||||
*) _n="${_n}_u${_u}" ;;
|
||||
esac
|
||||
fi
|
||||
printf '%s' "$_n"
|
||||
}
|
||||
|
||||
# 檔案已存在時自動加序號,避免覆蓋掉先前的掃描結果(-F 可強制覆蓋)
|
||||
uniquify() { # $1=filename
|
||||
_f=$1
|
||||
[ -e "${OUTDIR}/${_f}" ] || { printf '%s' "$_f"; return; }
|
||||
if [ "$FORCE" -eq 1 ]; then
|
||||
echo "WARN: 覆蓋既有檔案 ${OUTDIR}/${_f}" >&2
|
||||
printf '%s' "$_f"; return
|
||||
fi
|
||||
case "$_f" in
|
||||
*.*) _b=${_f%.*}; _e=".${_f##*.}" ;;
|
||||
*) _b=$_f; _e="" ;;
|
||||
esac
|
||||
_i=1
|
||||
while [ -e "${OUTDIR}/${_b}_${_i}${_e}" ]; do _i=$((_i + 1)); done
|
||||
echo "WARN: ${_f} 已存在,改用 ${_b}_${_i}${_e}(-F 可強制覆蓋)" >&2
|
||||
printf '%s' "${_b}_${_i}${_e}"
|
||||
}
|
||||
|
||||
MULTI=0
|
||||
[ "$(echo "$UNITS" | wc -w | tr -d ' ')" -gt 1 ] && MULTI=1
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Scan
|
||||
# ----------------------------------------------------------------------------
|
||||
TS=$(date +%Y%m%d_%H%M%S)
|
||||
RC=0
|
||||
LOGS=""
|
||||
|
||||
for U in $UNITS; do
|
||||
LOG="${OUTDIR}/$(uniquify "$(build_logname "$U")")"
|
||||
: > "$LOG" || { echo "ERROR: cannot write $LOG" >&2; exit 2; }
|
||||
LOGS="$LOGS $LOG"
|
||||
|
||||
printf '### SCAN_BEGIN unit=%s time=%s total=%s script=bcm_dsc_scan_V1.3.0\n' \
|
||||
"$U" "$(date '+%Y-%m-%d %H:%M:%S')" "$TOTAL" >> "$LOG"
|
||||
|
||||
echo "[unit $U] scanning $TOTAL ports -> $LOG" >&2
|
||||
|
||||
SEQ=0
|
||||
while IFS=, read -r P SPD <&3; do
|
||||
SEQ=$((SEQ + 1))
|
||||
printf '### PORT unit=%s port=%s speed=%s seq=%s/%s\n' "$U" "$P" "$SPD" "$SEQ" "$TOTAL" >> "$LOG"
|
||||
# bcmcmd 會讀取 stdin,若不導成 /dev/null 會把 PORTFILE 剩餘內容吸走,
|
||||
# 導致迴圈在第一筆之後就讀到 EOF 而提前結束。
|
||||
bcmcmd -n "$U" -c "dsh -c 'phydiag $P dsc'" >> "$LOG" 2>&1 < /dev/null || RC=1
|
||||
|
||||
if [ "$TTY" -eq 1 ]; then
|
||||
printf '\r[unit %s] %s/%s port=%-5s' "$U" "$SEQ" "$TOTAL" "$P" >&2
|
||||
elif [ $((SEQ % PROGRESS_EVERY)) -eq 0 ] || [ "$SEQ" -eq "$TOTAL" ]; then
|
||||
printf '[unit %s] %s/%s port=%s\n' "$U" "$SEQ" "$TOTAL" "$P" >&2
|
||||
fi
|
||||
|
||||
sleep "$DELAY"
|
||||
done 3< "$PORTFILE"
|
||||
|
||||
[ "$TTY" -eq 1 ] && printf '\n' >&2
|
||||
printf '### SCAN_END unit=%s time=%s\n' "$U" "$(date '+%Y-%m-%d %H:%M:%S')" >> "$LOG"
|
||||
|
||||
# 檢查 1:實際迭代筆數是否等於 port 清單筆數。
|
||||
# 迴圈若因 stdin 被子程序吸走而提前結束,只靠下面的 marker/dump 比對抓不到。
|
||||
if [ "$SEQ" -ne "$TOTAL" ]; then
|
||||
echo "ERROR: unit $U 只跑了 $SEQ/$TOTAL 筆,迴圈提前結束" >&2
|
||||
RC=1
|
||||
fi
|
||||
|
||||
# 檢查 2:每筆 PORT marker 應對應一個 dsc 區塊
|
||||
MARK=$(grep -c '^### PORT ' "$LOG" || true)
|
||||
DUMP=$(grep -c 'SERDES DISPLAY DIAG DATA END' "$LOG" || true)
|
||||
if [ "$MARK" -ne "$DUMP" ]; then
|
||||
echo "WARN: unit $U markers=$MARK dsc_blocks=$DUMP (有 port 未取得完整 dump)" >&2
|
||||
RC=1
|
||||
fi
|
||||
echo "Saved: $LOG (${DUMP}/${TOTAL} dumps)" >&2
|
||||
done
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Copy to job directory
|
||||
# ----------------------------------------------------------------------------
|
||||
if [ "$DOCOPY" -eq 1 ]; then
|
||||
if mkdir -p "$COPYDIR" 2>/dev/null && [ -w "$COPYDIR" ]; then
|
||||
for L in $LOGS; do
|
||||
if cp -p "$L" "$COPYDIR/"; then
|
||||
echo "Copied: $COPYDIR/$(basename "$L")" >&2
|
||||
else
|
||||
echo "ERROR: copy failed: $L -> $COPYDIR" >&2
|
||||
RC=1
|
||||
fi
|
||||
done
|
||||
sync
|
||||
else
|
||||
echo "ERROR: copydir not writable: $COPYDIR (log 仍保留在 $OUTDIR)" >&2
|
||||
RC=1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "### DSC_SCAN_DONE rc=${RC}" >&2
|
||||
exit "$RC"
|
||||
@@ -0,0 +1,495 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# blanton_ber.sh -- SerDes BER test over every cabled port (PRBS via phydiag)
|
||||
# =============================================================================
|
||||
# Version History:
|
||||
# V1.0.1 2026-08-28 Fix: every lane reported NA and the Port column showed
|
||||
# "NA". bcmcmd returns CRLF, and the BER is the last token
|
||||
# on its line, so the CR stayed glued to the number: it
|
||||
# failed the numeric test (-> NA) and printing it sent the
|
||||
# cursor back to column 1, so the RESULT column overwrote
|
||||
# the start of the row. The parser now strips CR first.
|
||||
# (The traffic report never hit this -- there the counter
|
||||
# is followed by a delta, so the CR was trimmed with it.)
|
||||
# V1.0.0 2026-08-28 First version. Bash port of tools/BER_Test.txt.
|
||||
# init/clear/start/stop/report, -u 0|1|all (default both).
|
||||
# report parses 'prbsstat Ber' into a per-lane table with a
|
||||
# PASS/FAIL against BER_MAX (default 1e-6) and a summary
|
||||
# across units at the very bottom.
|
||||
# =============================================================================
|
||||
#
|
||||
# This is the WHOLE-SWITCH BER sweep: every cabled port, both lanes, PRBS-31
|
||||
# through the SerDes. Not to be confused with port_prbs_monitor.sh, which drives
|
||||
# the two 100G uplinks only and polls them continuously.
|
||||
#
|
||||
# Order of operations (matches tools/BER_Test.txt):
|
||||
# init phydiag <ports> prbs set p=3 arm PRBS on every lane
|
||||
# phydiag <ports> prbs get confirm every lane locked
|
||||
# start phydiag <ports> prbsstat STArt Interval=<n>
|
||||
# ...wait at least one Interval...
|
||||
# report phydiag <ports> prbsstat Ber read + judge
|
||||
# stop phydiag <ports> prbsstat STOp
|
||||
# clear phydiag <ports> prbs clear disarm, release the lanes
|
||||
#
|
||||
# ⚠️ 'clear' disarms PRBS -- run 'init' again before another measurement.
|
||||
# ⚠️ PRBS takes the SerDes out of normal operation: the links report DOWN and no
|
||||
# traffic passes while it is armed. Do not run this alongside
|
||||
# blanton_traffic_linespeed or blanton_tr518.
|
||||
#
|
||||
# Usage (run directly):
|
||||
# ./blanton_ber.sh init # both units
|
||||
# ./blanton_ber.sh start -u 0 # unit 0 only
|
||||
# ./blanton_ber.sh report
|
||||
# ./blanton_ber.sh stop
|
||||
# ./blanton_ber.sh clear
|
||||
#
|
||||
# Usage (sourced, like the other blanton_*.sh tools):
|
||||
# source blanton_ber.sh
|
||||
# blanton_ber report -u 1
|
||||
#
|
||||
# Options:
|
||||
# -u|--unit <0|1|all|0,1> bcmcmd unit(s). Default: $BER_UNITS ("0 1")
|
||||
# -c|--criteria <ber> report: PASS threshold (default $BER_MAX)
|
||||
# -i|--interval <sec> start: prbsstat Interval (default $BER_INTERVAL)
|
||||
# -p|--ports <list> override the port list
|
||||
# -F|--fail-only report: list only the lanes that FAIL
|
||||
# --tsv report: tab-separated (paste into Excel)
|
||||
# --raw report: also print the raw 'prbsstat Ber' output
|
||||
# --color|--no-color report: force / disable colours
|
||||
# -f|--file <log> report: parse a saved console log, do not touch DUT
|
||||
# -d|--debug print every bcmcmd before running it
|
||||
# -n|--dry-run print commands only, do not touch the DUT
|
||||
# -h|--help help
|
||||
#
|
||||
# Environment overrides:
|
||||
# BCMCMD_CMD=bcmcmd BER_UNITS="0 1" BER_MAX=1e-6 BER_INTERVAL=30
|
||||
# BER_PORTS="1-24,..." BER_POLY=p=3 BER_LOG_DIR=/tmp DEBUG_MODE=1
|
||||
# =============================================================================
|
||||
|
||||
# === Config ==================================================================
|
||||
BCMCMD_CMD="${BCMCMD_CMD:-bcmcmd}"
|
||||
BER_UNITS="${BER_UNITS:-0 1}" # one DUT = two switch boards (0 and 1)
|
||||
|
||||
# The cabled ports, in bcm logical-port numbering. Same list as
|
||||
# blanton_traffic_linespeed.sh's TL_PS_PORTS -- kept as one string so it can be
|
||||
# pasted straight from/into a manual phydiag command.
|
||||
BER_PORTS="${BER_PORTS:-1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565}"
|
||||
|
||||
BER_POLY="${BER_POLY:-p=3}" # passed to 'prbs set'
|
||||
BER_INTERVAL="${BER_INTERVAL:-30}" # passed to 'prbsstat STArt Interval='
|
||||
|
||||
# PASS threshold. A lane PASSES when its BER is strictly BELOW this.
|
||||
# 1e-6 is the acceptance figure for this project; the measured lanes sit around
|
||||
# 1e-13..1e-8, so anything near the threshold is already a real finding.
|
||||
BER_MAX="${BER_MAX:-1e-6}"
|
||||
|
||||
BER_LOG_DIR="${BER_LOG_DIR:-/tmp}" # where the raw 'prbsstat Ber' capture goes
|
||||
BER_FAIL_ONLY=${BER_FAIL_ONLY:-0}
|
||||
BER_TSV=${BER_TSV:-0}
|
||||
BER_RAW=${BER_RAW:-0}
|
||||
BER_REPORT_FILE="" # -f <log>: parse this instead of the DUT
|
||||
BER_COLOR="${BER_COLOR:-auto}" # auto|always|never
|
||||
|
||||
DEBUG_MODE=${DEBUG_MODE:-0}
|
||||
BER_DRY_RUN=${BER_DRY_RUN:-0}
|
||||
|
||||
# === Logging =================================================================
|
||||
_ber_info() { echo -e "[\033[34mINFO\033[0m] $*"; }
|
||||
_ber_ok() { echo -e "[\033[32m OK \033[0m] $*"; }
|
||||
_ber_warn() { echo -e "[\033[33mWARN\033[0m] $*" >&2; }
|
||||
_ber_err() { echo -e "[\033[31mERR \033[0m] $*" >&2; }
|
||||
_ber_dbg() { [ "$DEBUG_MODE" = "1" ] && echo -e "\033[90m[DEBG] $*\033[0m" >&2; return 0; }
|
||||
|
||||
# === bcmcmd wrapper ==========================================================
|
||||
# stdin closed for the same reason as blanton_traffic_linespeed.sh: bcmcmd
|
||||
# otherwise inherits the caller's stdin and eats what a surrounding loop reads.
|
||||
#
|
||||
# bcmcmd exits 0 even when the BCM shell refused the command, so the output is
|
||||
# pattern-matched as well. And it exits NON-zero on long-running commands whose
|
||||
# response poll times out while the command is in fact fine -- that one is
|
||||
# tolerated (the blanton_tr518.sh lesson).
|
||||
BER_ERR_PAT="${BER_ERR_PAT:-ERROR|Failed to execute|Invalid|Syntax error|Unavailable|Unknown command}"
|
||||
BER_BENIGN_PAT="${BER_BENIGN_PAT:-polling socket timeout}"
|
||||
|
||||
# _ber_bcm <unit> <phydiag args...> -- wraps in dsh -c 'phydiag <ports> ...'
|
||||
# echoes the DUT output on stdout, returns 0 ok / 1 failed
|
||||
_ber_bcm() {
|
||||
local unit="$1"; shift
|
||||
local inner="phydiag ${BER_PORTS} $*"
|
||||
local cmd="dsh -c '${inner}'"
|
||||
_ber_dbg "$BCMCMD_CMD -n $unit -c \"${cmd}\""
|
||||
if [ "$BER_DRY_RUN" = "1" ]; then
|
||||
echo "[DRY ] $BCMCMD_CMD -n $unit -c \" ${cmd} \"" >&2
|
||||
return 0
|
||||
fi
|
||||
local out rc
|
||||
out=$("$BCMCMD_CMD" -n "$unit" -c "$cmd" </dev/null 2>&1); rc=$?
|
||||
printf '%s\n' "$out"
|
||||
if echo "$out" | grep -qiE "$BER_ERR_PAT"; then
|
||||
_ber_err "unit $unit: the BCM shell rejected 'phydiag ... $*'"
|
||||
return 1
|
||||
fi
|
||||
if [ "$rc" -ne 0 ] && ! echo "$out" | grep -qiE "$BER_BENIGN_PAT"; then
|
||||
_ber_err "unit $unit: bcmcmd exited $rc on 'phydiag ... $*'"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
_ber_units_check() {
|
||||
local u ok=""
|
||||
for u in $BER_UNITS; do
|
||||
case "$u" in
|
||||
0|1) ok="$ok $u" ;;
|
||||
*) _ber_err "invalid unit '$u' (use 0, 1 or all)"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
[ -n "$ok" ] || { _ber_err "no unit selected"; return 1; }
|
||||
BER_UNITS="${ok# }"
|
||||
return 0
|
||||
}
|
||||
|
||||
_ber_use_color() {
|
||||
case "$BER_COLOR" in
|
||||
always|1|yes) return 0 ;;
|
||||
never|0|no) return 1 ;;
|
||||
*) [ -t 1 ] && [ "$BER_TSV" != "1" ] ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# === init ====================================================================
|
||||
# prbs set + prbs get. The 'get' is not decoration: a lane that did not lock
|
||||
# still reports a BER later, and it is a meaningless one.
|
||||
blanton_ber_init() {
|
||||
_ber_units_check || return 1
|
||||
local unit out total ok rc=0
|
||||
for unit in $BER_UNITS; do
|
||||
_ber_info "unit $unit: prbs set ${BER_POLY} on ${BER_PORTS}"
|
||||
_ber_bcm "$unit" "prbs set ${BER_POLY}" >/dev/null || { rc=1; continue; }
|
||||
|
||||
out=$(_ber_bcm "$unit" "prbs get") || { rc=1; continue; }
|
||||
[ "$BER_DRY_RUN" = "1" ] && continue
|
||||
# lines look like: " 185 : PRBS OK!has been unlocked since last call"
|
||||
total=$(printf '%s\n' "$out" | grep -cE '^[ \t]*[0-9]+[ \t]*:')
|
||||
ok=$(printf '%s\n' "$out" | grep -cE '^[ \t]*[0-9]+[ \t]*:.*PRBS OK')
|
||||
if [ "$total" -eq 0 ]; then
|
||||
_ber_err "unit $unit: 'prbs get' reported no lanes at all"
|
||||
rc=1
|
||||
elif [ "$ok" -eq "$total" ]; then
|
||||
_ber_ok "unit $unit: $ok/$total ports locked"
|
||||
else
|
||||
_ber_warn "unit $unit: only $ok/$total ports locked -- the rest will report a meaningless BER:"
|
||||
printf '%s\n' "$out" | grep -E '^[ \t]*[0-9]+[ \t]*:' | grep -v 'PRBS OK' >&2
|
||||
rc=2
|
||||
fi
|
||||
done
|
||||
return $rc
|
||||
}
|
||||
|
||||
# === clear ===================================================================
|
||||
blanton_ber_clear() {
|
||||
_ber_units_check || return 1
|
||||
local unit rc=0
|
||||
for unit in $BER_UNITS; do
|
||||
_ber_info "unit $unit: prbs clear"
|
||||
_ber_bcm "$unit" "prbs clear" >/dev/null || rc=1
|
||||
done
|
||||
[ "$rc" -eq 0 ] && _ber_ok "PRBS disarmed on unit(s): $BER_UNITS -- run 'init' before measuring again"
|
||||
return $rc
|
||||
}
|
||||
|
||||
# === start ===================================================================
|
||||
blanton_ber_start() {
|
||||
_ber_units_check || return 1
|
||||
local unit rc=0
|
||||
for unit in $BER_UNITS; do
|
||||
_ber_info "unit $unit: prbsstat STArt Interval=${BER_INTERVAL}"
|
||||
_ber_bcm "$unit" "prbsstat STArt Interval=${BER_INTERVAL}" >/dev/null || rc=1
|
||||
done
|
||||
if [ "$rc" -eq 0 ]; then
|
||||
_ber_ok "BER accumulation running on unit(s): $BER_UNITS"
|
||||
_ber_info "wait at least ${BER_INTERVAL}s before 'report' -- a shorter run has not accumulated a full interval"
|
||||
fi
|
||||
return $rc
|
||||
}
|
||||
|
||||
# === stop ====================================================================
|
||||
blanton_ber_stop() {
|
||||
_ber_units_check || return 1
|
||||
local unit rc=0
|
||||
for unit in $BER_UNITS; do
|
||||
_ber_info "unit $unit: prbsstat STOp"
|
||||
_ber_bcm "$unit" "prbsstat STOp" >/dev/null || rc=1
|
||||
done
|
||||
if [ "$rc" -eq 0 ]; then
|
||||
_ber_ok "BER accumulation stopped on unit(s): $BER_UNITS"
|
||||
_ber_info "PRBS is still armed -- 'clear' releases the lanes and restores normal operation"
|
||||
fi
|
||||
return $rc
|
||||
}
|
||||
|
||||
# === report ==================================================================
|
||||
# Parses 'prbsstat Ber' output:
|
||||
# port BER
|
||||
# ====
|
||||
# 1[0] : 3.53e-11
|
||||
# 1[1] : 4.00e-11
|
||||
# into <port> <lane> <ber> <verdict>, PASS when ber < BER_MAX.
|
||||
# _ber_render <logfile> [side_file] -> 0 all PASS, 2 any FAIL/NA, 1 parse error
|
||||
_ber_render() {
|
||||
local log="$1" side="${2:-/dev/null}" color=0
|
||||
_ber_use_color && color=1
|
||||
awk -v MAXBER="$BER_MAX" \
|
||||
-v FAILONLY="$BER_FAIL_ONLY" \
|
||||
-v TSV="$BER_TSV" \
|
||||
-v COLOR="$color" \
|
||||
-v SIDE="$side" '
|
||||
function vc(v) {
|
||||
if (!COLOR) return v
|
||||
if (v == "PASS") return "\033[32m" v "\033[0m"
|
||||
if (v == "FAIL") return "\033[31m" v "\033[0m"
|
||||
return "\033[33m" v "\033[0m"
|
||||
}
|
||||
BEGIN {
|
||||
LIM = MAXBER + 0
|
||||
NC = 4
|
||||
HDR[1] = "Port"; AL[1] = 1
|
||||
HDR[2] = "Lane"; AL[2] = 1
|
||||
HDR[3] = "BER"; AL[3] = 1
|
||||
HDR[4] = "RESULT"; AL[4] = 1
|
||||
worst = -1; worstlane = "-"
|
||||
}
|
||||
# bcmcmd hands back CRLF. On the cd/traffic report the counter is followed by
|
||||
# a delta, so the CR got trimmed with the rest of the line; here the BER is
|
||||
# the LAST token, so the CR sticks to the number -- it failed the numeric
|
||||
# test (every lane NA) and, worse, printing it moved the cursor back to
|
||||
# column 1 so the RESULT column overwrote the start of the row.
|
||||
{ gsub(/\r/, "") }
|
||||
|
||||
{
|
||||
# " 203[1] : 5.05e-09" (leading spaces vary, "====" separators ignored)
|
||||
if ($0 !~ /^[ \t]*[0-9]+\[[0-9]+\][ \t]*:/) next
|
||||
line = $0
|
||||
sub(/^[ \t]+/, "", line)
|
||||
p = index(line, "[")
|
||||
q = index(line, "]")
|
||||
c = index(line, ":")
|
||||
port = substr(line, 1, p - 1)
|
||||
lane = substr(line, p + 1, q - p - 1)
|
||||
ber = substr(line, c + 1)
|
||||
gsub(/^[ \t\r]+|[ \t\r]+$/, "", ber)
|
||||
sub(/[ \t\r].*$/, "", ber)
|
||||
seen++
|
||||
n++
|
||||
PORT[n] = port; LANE[n] = lane; BERS[n] = ber
|
||||
# a lane that reported something non-numeric has no usable measurement
|
||||
if (ber ~ /^[0-9]+(\.[0-9]+)?([eE][-+]?[0-9]+)?$/) {
|
||||
v = ber + 0
|
||||
if (v < LIM) { V[n] = "PASS"; npass++ }
|
||||
else { V[n] = "FAIL"; nfail++ }
|
||||
if (v > worst) { worst = v; worstlane = port "[" lane "]"; worststr = ber }
|
||||
} else {
|
||||
V[n] = "NA"; nna++
|
||||
}
|
||||
}
|
||||
END {
|
||||
if (seen == 0) {
|
||||
print "error: no \"<port>[<lane>] : <ber>\" line found in the log" > "/dev/stderr"
|
||||
exit 1
|
||||
}
|
||||
# column widths over the rows that will actually be printed
|
||||
for (c2 = 1; c2 <= NC; c2++) w[c2] = length(HDR[c2])
|
||||
for (i = 1; i <= n; i++) {
|
||||
if (FAILONLY && V[i] == "PASS") continue
|
||||
if (length(PORT[i]) > w[1]) w[1] = length(PORT[i])
|
||||
if (length(LANE[i]) > w[2]) w[2] = length(LANE[i])
|
||||
if (length(BERS[i]) > w[3]) w[3] = length(BERS[i])
|
||||
if (length(V[i]) > w[4]) w[4] = length(V[i])
|
||||
}
|
||||
for (c2 = 1; c2 <= NC; c2++) w[c2] += 2
|
||||
|
||||
if (TSV) {
|
||||
print HDR[1] "\t" HDR[2] "\t" HDR[3] "\t" HDR[4]
|
||||
for (i = 1; i <= n; i++) {
|
||||
if (FAILONLY && V[i] == "PASS") continue
|
||||
print PORT[i] "\t" LANE[i] "\t" BERS[i] "\t" V[i]
|
||||
}
|
||||
} else {
|
||||
printf "%*s%*s%*s%*s\n", w[1], HDR[1], w[2], HDR[2], w[3], HDR[3], w[4], HDR[4]
|
||||
for (i = 1; i <= n; i++) {
|
||||
if (FAILONLY && V[i] == "PASS") continue
|
||||
printf "%*s%*s%*s", w[1], PORT[i], w[2], LANE[i], w[3], BERS[i]
|
||||
# pad on the plain text, then colour, so the columns stay aligned
|
||||
printf "%*s%s\n", w[4] - length(V[i]), "", vc(V[i])
|
||||
}
|
||||
if (FAILONLY && nfail == 0 && nna == 0)
|
||||
print " (no failing lane)"
|
||||
}
|
||||
|
||||
print ""
|
||||
printf "# lanes measured : %d\n", n
|
||||
printf "# %s %d %s %d %s %d (criteria BER < %s)\n", \
|
||||
vc("PASS"), npass + 0, vc("FAIL"), nfail + 0, vc("NA"), nna + 0, MAXBER
|
||||
if (worst >= 0)
|
||||
printf "# worst lane : %s %s\n", worstlane, worststr
|
||||
if (SIDE != "" && SIDE != "/dev/null")
|
||||
printf "SUM %d %d %d %d %s %s\n", n, npass + 0, nfail + 0, nna + 0, \
|
||||
(worst >= 0 ? worststr : "-"), worstlane > SIDE
|
||||
exit (nfail || nna) ? 2 : 0
|
||||
}' "$log"
|
||||
}
|
||||
|
||||
# _ber_summary <stamp> -- one table for every unit, printed last
|
||||
_ber_summary() {
|
||||
local stamp="$1" unit side g r y n worst=0
|
||||
g=$'\033[32m'; r=$'\033[31m'; y=$'\033[33m'; n=$'\033[0m'
|
||||
_ber_use_color || { g=""; r=""; y=""; n=""; }
|
||||
|
||||
echo ""
|
||||
echo "===== summary : all units ====="
|
||||
printf '%-8s %8s %8s %8s %8s %-12s %-10s %s\n' \
|
||||
"Unit" "LANES" "PASS" "FAIL" "NA" "WORST BER" "WORST LANE" "RESULT"
|
||||
|
||||
local tag lanes pass fail na wber wlane v any=0
|
||||
for unit in $BER_UNITS; do
|
||||
side="$BER_LOG_DIR/berside_unit${unit}_${stamp}"
|
||||
[ -r "$side" ] || continue
|
||||
read -r tag lanes pass fail na wber wlane < "$side" 2>/dev/null
|
||||
[ "$tag" = "SUM" ] || continue
|
||||
any=1
|
||||
if [ "${fail:-0}" -gt 0 ] || [ "${na:-0}" -gt 0 ]; then
|
||||
v="${r}FAIL${n}"; worst=2
|
||||
else
|
||||
v="${g}PASS${n}"
|
||||
fi
|
||||
printf '%-8s %8s %8s %8s %8s %-12s %-10s %b\n' \
|
||||
"unit $unit" "$lanes" "$pass" "$fail" "$na" "$wber" "$wlane" "$v"
|
||||
done
|
||||
[ "$any" = "1" ] || echo " (no unit produced a result)"
|
||||
echo ""
|
||||
printf 'criteria: BER < %s\n' "$BER_MAX"
|
||||
echo ""
|
||||
return "$worst"
|
||||
}
|
||||
|
||||
blanton_ber_report() {
|
||||
local unit log side rc worst=0 stamp
|
||||
|
||||
# -f <log>: offline, no DUT access, no unit loop -> no cross-unit summary
|
||||
if [ -n "$BER_REPORT_FILE" ]; then
|
||||
[ -r "$BER_REPORT_FILE" ] || { _ber_err "cannot read log '$BER_REPORT_FILE'"; return 1; }
|
||||
_ber_info "report from log: $BER_REPORT_FILE (criteria BER < $BER_MAX)" >&2
|
||||
_ber_render "$BER_REPORT_FILE"; return $?
|
||||
fi
|
||||
|
||||
_ber_units_check || return 1
|
||||
if [ "$BER_DRY_RUN" = "1" ]; then
|
||||
for unit in $BER_UNITS; do _ber_bcm "$unit" "prbsstat Ber" >/dev/null; done
|
||||
return 0
|
||||
fi
|
||||
|
||||
stamp=$(date +%Y%m%d_%H%M%S 2>/dev/null || echo now)
|
||||
for unit in $BER_UNITS; do
|
||||
log="$BER_LOG_DIR/prbsber_unit${unit}_${stamp}.log"
|
||||
side="$BER_LOG_DIR/berside_unit${unit}_${stamp}"
|
||||
: > "$side"
|
||||
if ! _ber_bcm "$unit" "prbsstat Ber" > "$log" 2>&1; then
|
||||
_ber_err "unit $unit: 'prbsstat Ber' failed (see $log)"; worst=1; continue
|
||||
fi
|
||||
[ "$BER_RAW" = "1" ] && { echo "----- unit $unit : raw prbsstat Ber -----"; cat "$log"; }
|
||||
echo "===== unit $unit : PRBS BER report (raw: $log) ====="
|
||||
_ber_render "$log" "$side"; rc=$?
|
||||
[ "$rc" -gt "$worst" ] && worst=$rc
|
||||
case "$rc" in
|
||||
0) _ber_ok "unit $unit: every lane below $BER_MAX" ;;
|
||||
2) _ber_warn "unit $unit: at least one lane FAIL/NA" ;;
|
||||
*) _ber_err "unit $unit: report parse error" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
_ber_summary "$stamp"; rc=$?
|
||||
[ "$rc" -gt "$worst" ] && worst=$rc
|
||||
rm -f "$BER_LOG_DIR"/berside_unit*_"${stamp}"
|
||||
return "$worst"
|
||||
}
|
||||
|
||||
# === Help ====================================================================
|
||||
blanton_ber_help() {
|
||||
echo -e "\033[1mblanton_ber.sh - SerDes BER test over every cabled port (PRBS via phydiag)\033[0m"
|
||||
echo ""
|
||||
echo -e " Units : \033[36m$BER_UNITS\033[0m poly: \033[36m$BER_POLY\033[0m interval: \033[36m${BER_INTERVAL}s\033[0m"
|
||||
echo -e " Criteria : BER < \033[36m$BER_MAX\033[0m"
|
||||
echo -e " Ports : \033[36m$BER_PORTS\033[0m"
|
||||
echo ""
|
||||
echo -e "\033[1mSubcommands\033[0m"
|
||||
echo -e " \033[33minit\033[0m prbs set $BER_POLY + prbs get (checks every lane locked)"
|
||||
echo -e " \033[33mstart\033[0m prbsstat STArt Interval=$BER_INTERVAL"
|
||||
echo -e " \033[33mreport\033[0m prbsstat Ber -> per-lane table + PASS/FAIL + summary"
|
||||
echo -e " \033[33mstop\033[0m prbsstat STOp"
|
||||
echo -e " \033[33mclear\033[0m prbs clear (disarms PRBS -- 'init' again before measuring)"
|
||||
echo -e " \033[33mhelp\033[0m"
|
||||
echo ""
|
||||
echo -e "\033[1mOptions\033[0m"
|
||||
echo -e " \033[33m-u|--unit\033[0m <0|1|all> bcmcmd unit(s); 'all' = 0 1 (default: $BER_UNITS)"
|
||||
echo -e " \033[33m-c|--criteria\033[0m <ber> PASS threshold (default $BER_MAX)"
|
||||
echo -e " \033[33m-i|--interval\033[0m <sec> prbsstat Interval (default $BER_INTERVAL)"
|
||||
echo -e " \033[33m-p|--ports\033[0m <list> override the port list"
|
||||
echo -e " \033[33m-F|--fail-only\033[0m report: list only failing lanes"
|
||||
echo -e " \033[33m--tsv\033[0m report: tab-separated"
|
||||
echo -e " \033[33m--raw\033[0m report: also print the raw output"
|
||||
echo -e " \033[33m-f|--file\033[0m <log> report: parse a saved log, do not touch the DUT"
|
||||
echo -e " \033[33m-d|--debug\033[0m print every bcmcmd"
|
||||
echo -e " \033[33m-n|--dry-run\033[0m print commands only"
|
||||
echo ""
|
||||
echo -e "\033[1mTypical run\033[0m"
|
||||
echo -e " ./blanton_ber.sh init && ./blanton_ber.sh start"
|
||||
echo -e " sleep $BER_INTERVAL"
|
||||
echo -e " ./blanton_ber.sh report"
|
||||
echo -e " ./blanton_ber.sh stop && ./blanton_ber.sh clear"
|
||||
echo ""
|
||||
echo -e "\033[33m PRBS takes the SerDes out of normal operation: links show DOWN and no\033[0m"
|
||||
echo -e "\033[33m traffic passes. Do not run alongside blanton_traffic_linespeed / blanton_tr518.\033[0m"
|
||||
}
|
||||
|
||||
# === Argument parsing ========================================================
|
||||
blanton_ber() {
|
||||
local sub="${1:-help}"; shift 2>/dev/null
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-u|--unit)
|
||||
case "$2" in
|
||||
all|ALL) BER_UNITS="0 1" ;;
|
||||
*) BER_UNITS="$(echo "$2" | tr ',' ' ')" ;;
|
||||
esac
|
||||
shift 2 ;;
|
||||
-c|--criteria) BER_MAX="$2"; shift 2 ;;
|
||||
-i|--interval) BER_INTERVAL="$2"; shift 2 ;;
|
||||
-p|--ports) BER_PORTS="$2"; shift 2 ;;
|
||||
-f|--file) BER_REPORT_FILE="$2"; shift 2 ;;
|
||||
-F|--fail-only) BER_FAIL_ONLY=1; shift ;;
|
||||
--tsv) BER_TSV=1; shift ;;
|
||||
--raw) BER_RAW=1; shift ;;
|
||||
--color) BER_COLOR=always; shift ;;
|
||||
--no-color) BER_COLOR=never; shift ;;
|
||||
-d|--debug) DEBUG_MODE=1; shift ;;
|
||||
-n|--dry-run) BER_DRY_RUN=1; shift ;;
|
||||
-h|--help) blanton_ber_help; return 0 ;;
|
||||
*) _ber_err "unknown option '$1'"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$sub" in
|
||||
init) blanton_ber_init ;;
|
||||
clear) blanton_ber_clear ;;
|
||||
start) blanton_ber_start ;;
|
||||
stop) blanton_ber_stop ;;
|
||||
report) blanton_ber_report ;;
|
||||
help|-h|--help) blanton_ber_help ;;
|
||||
*) _ber_err "unknown subcommand '$sub'"; blanton_ber_help; return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Run when executed, define-only when sourced (same as the other blanton_*.sh).
|
||||
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
|
||||
blanton_ber "$@"
|
||||
fi
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,326 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# blanton_tr518.sh -- TH6 built-in packet test (tr 518) via bcmcmd
|
||||
# =============================================================================
|
||||
# Version History:
|
||||
# V1.0.1 2026-08-28 Fix: start reported ERR on a run that was actually fine.
|
||||
# bcmcmd exits NON-zero on 'tr 518' because the test
|
||||
# outlives its response poll ("polling socket timeout:
|
||||
# Success") -- the command had been accepted and was
|
||||
# running. The tr 518 step is now judged on a POSITIVE
|
||||
# marker in the output ("TR 518 TEST PARAMETERS", which
|
||||
# the shell prints only after it starts the test) instead
|
||||
# of on bcmcmd's exit status, and "polling socket timeout"
|
||||
# is tolerated generally. Failures now also say WHICH
|
||||
# check tripped (shell rejected it / bcmcmd exited N).
|
||||
# V1.0.0 2026-08-28 First version. Bash port of tools/TR518.txt, command for
|
||||
# command. start = port cd lb=mac, l2 learn off,
|
||||
# test mode nr=yes, tr 518 ... testphase=1, then a settle
|
||||
# wait so a power reading taken afterwards is a loaded and
|
||||
# stable one rather than a ramping one.
|
||||
# stop = port cd lb=none (exactly what TR518.txt does).
|
||||
# -u 0 | -u 1 | -u all (default both).
|
||||
# =============================================================================
|
||||
#
|
||||
# What this is for: tr 518 loads the switch so the power rails can be measured
|
||||
# under traffic. The usual sequence is
|
||||
#
|
||||
# blanton_tr518.sh start # loads both units, waits to settle
|
||||
# TH6_SWB0_power_readback.sh # now the numbers mean something
|
||||
# TH6_SWB1_power_readback.sh
|
||||
# blanton_tr518.sh stop
|
||||
#
|
||||
# ⚠️ tr 518 and blanton_traffic_linespeed CANNOT run at the same time. Both take
|
||||
# over the cd ports and L2 learning; running one while the other is set up
|
||||
# gives numbers from neither test. Stop one before the other starts.
|
||||
#
|
||||
# ⚠️ stop only undoes the loopback -- see TR_RESTORE_* below.
|
||||
#
|
||||
# Usage (run directly):
|
||||
# ./blanton_tr518.sh start # both units
|
||||
# ./blanton_tr518.sh start -u 0 # unit 0 only
|
||||
# ./blanton_tr518.sh start -u 1 # unit 1 only
|
||||
# ./blanton_tr518.sh stop [-u 0|1]
|
||||
# ./blanton_tr518.sh help
|
||||
#
|
||||
# Usage (sourced, like the other blanton_*.sh tools):
|
||||
# source blanton_tr518.sh
|
||||
# blanton_tr518 start -u 0
|
||||
#
|
||||
# Options:
|
||||
# -u|--unit <0|1|all|0,1> bcmcmd unit(s). Default: $TR_UNITS ("0 1")
|
||||
# -w|--wait <sec> start: settle wait after tr 518 (default $TR_SETTLE_SEC)
|
||||
# --no-wait start: skip the settle wait entirely
|
||||
# -d|--debug print every bcmcmd and its output
|
||||
# -n|--dry-run print commands only, do not touch the DUT
|
||||
# -h|--help help
|
||||
#
|
||||
# Environment overrides:
|
||||
# BCMCMD_CMD=bcmcmd TR_UNITS="0 1" TR_SETTLE_SEC=120 TR_UNIT_GAP_SEC=1
|
||||
# TR_TEST_ARGS="..." TR_LB_PORTS=cd TR_RESTORE_LEARN=0 TR_RESTORE_TESTMODE=0
|
||||
# DEBUG_MODE=1
|
||||
# =============================================================================
|
||||
|
||||
# === Config ==================================================================
|
||||
BCMCMD_CMD="${BCMCMD_CMD:-bcmcmd}"
|
||||
TR_UNITS="${TR_UNITS:-0 1}" # one DUT = two switch boards (0 and 1)
|
||||
|
||||
# Settle wait after tr 518 is issued. The point is NOT the test itself -- it is
|
||||
# to stop someone reading power while traffic is still ramping and reporting a
|
||||
# number that is neither idle nor loaded. Lower it only if you know the rails
|
||||
# have already settled.
|
||||
TR_SETTLE_SEC="${TR_SETTLE_SEC:-120}"
|
||||
|
||||
# Gap between unit 0 and unit 1 (each unit is set up as a complete block, the
|
||||
# way TR518.txt does it -- the cd ports are in MAC loopback, so a unit does not
|
||||
# depend on the other one being ready).
|
||||
TR_UNIT_GAP_SEC="${TR_UNIT_GAP_SEC:-1}"
|
||||
|
||||
# Ports put into MAC loopback. 'cd' = the cd port group, per TR518.txt.
|
||||
TR_LB_PORTS="${TR_LB_PORTS:-cd}"
|
||||
|
||||
# The tr 518 argument string, verbatim from tools/TR518.txt. One editable line
|
||||
# so it can be pasted straight from / into a manual bcmcmd.
|
||||
# Printed by the BCM shell only after tr 518 has accepted its arguments and
|
||||
# started. Used as the success marker, because bcmcmd's own exit status is not
|
||||
# trustworthy for a command that runs longer than its response poll.
|
||||
TR_TEST_OK_PAT="${TR_TEST_OK_PAT:-TR 518 TEST PARAMETERS}"
|
||||
|
||||
TR_TEST_ARGS="${TR_TEST_ARGS:-Scenario=6 Profile=2 Count=260 PktSize=324 PortList=1-259,270-565 rm=ext CheckLinkTime=20 CheckDataTime=200 testphase=1}"
|
||||
|
||||
# TR518.txt stops with 'port cd lb=none' and nothing else, so that is the
|
||||
# default here too. But note what start changed and stop does NOT put back:
|
||||
# l2 learn off -> the unit keeps learning disabled
|
||||
# test mode nr=yes -> the unit stays in test mode
|
||||
# Both persist until something else changes them or the box reboots. Set these
|
||||
# to 1 if you want stop to be a true inverse; they are off by default because
|
||||
# they are not in the bench-verified list.
|
||||
TR_RESTORE_LEARN="${TR_RESTORE_LEARN:-0}"
|
||||
TR_RESTORE_TESTMODE="${TR_RESTORE_TESTMODE:-0}"
|
||||
|
||||
DEBUG_MODE=${DEBUG_MODE:-0}
|
||||
TR_DRY_RUN=${TR_DRY_RUN:-0}
|
||||
TR_NO_WAIT=${TR_NO_WAIT:-0}
|
||||
|
||||
# === Logging =================================================================
|
||||
_tr_info() { echo -e "[\033[34mINFO\033[0m] $*"; }
|
||||
_tr_ok() { echo -e "[\033[32m OK \033[0m] $*"; }
|
||||
_tr_warn() { echo -e "[\033[33mWARN\033[0m] $*" >&2; }
|
||||
_tr_err() { echo -e "[\033[31mERR \033[0m] $*" >&2; }
|
||||
_tr_dbg() { [ "$DEBUG_MODE" = "1" ] && echo -e "\033[90m[DEBG] $*\033[0m" >&2; return 0; }
|
||||
|
||||
# === bcmcmd wrapper ==========================================================
|
||||
# stdin is closed for the same reason as in blanton_traffic_linespeed.sh:
|
||||
# bcmcmd otherwise inherits the caller's stdin and eats whatever a surrounding
|
||||
# loop was reading.
|
||||
#
|
||||
# bcmcmd exits 0 even when the BCM shell refused the command, so the output is
|
||||
# pattern-matched as well (the V0.3.1 lesson from blanton_traffic_linespeed.sh).
|
||||
TR_ERR_PAT="${TR_ERR_PAT:-ERROR|Failed to execute|Invalid|Syntax error|Unavailable|Unknown command}"
|
||||
|
||||
# ...and the reverse also happens: bcmcmd exits NON-zero on a command that was
|
||||
# accepted and is running. 'tr 518' outlives bcmcmd's response poll, so bcmcmd
|
||||
# gives up with "polling socket timeout: Success" and a non-zero status while
|
||||
# the test carries on inside the BCM shell. Treating that as a failure is what
|
||||
# made V1.0.0 report ERR on a run that was actually fine.
|
||||
TR_BENIGN_PAT="${TR_BENIGN_PAT:-polling socket timeout}"
|
||||
|
||||
# _tr_bcm <unit> <cmd> -> 0 ok, 1 failed
|
||||
# _tr_bcm_ok <unit> <ok_marker> <cmd> -> as above, but if the output contains
|
||||
# <ok_marker> the command is a success
|
||||
# regardless of exit status.
|
||||
#
|
||||
# The marker is a POSITIVE proof of success ("the shell printed the thing it
|
||||
# only prints when it accepted this command"), which is far more reliable than
|
||||
# trying to enumerate every way bcmcmd can look unhappy.
|
||||
_tr_bcm() { _tr_bcm_ok "$1" "" "${@:2}"; }
|
||||
|
||||
_tr_bcm_ok() {
|
||||
local unit="$1" okpat="$2"; shift 2
|
||||
local cmd="$*" out rc why=""
|
||||
_tr_dbg "$BCMCMD_CMD -n $unit -c '$cmd'"
|
||||
if [ "$TR_DRY_RUN" = "1" ]; then
|
||||
echo "[DRY ] $BCMCMD_CMD -n $unit -c '$cmd'"
|
||||
return 0
|
||||
fi
|
||||
out=$("$BCMCMD_CMD" -n "$unit" -c "$cmd" </dev/null 2>&1); rc=$?
|
||||
[ "$DEBUG_MODE" = "1" ] && [ -n "$out" ] && echo "$out"
|
||||
|
||||
# 1. positive proof wins over everything else
|
||||
if [ -n "$okpat" ] && echo "$out" | grep -qF "$okpat"; then
|
||||
[ "$rc" -ne 0 ] && _tr_dbg "unit $unit: bcmcmd rc=$rc but '$okpat' seen -> accepted"
|
||||
return 0
|
||||
fi
|
||||
# 2. the BCM shell said no
|
||||
if echo "$out" | grep -qiE "$TR_ERR_PAT"; then
|
||||
why="the BCM shell rejected it"
|
||||
# 3. bcmcmd itself was unhappy -- unless it is the known transport artifact
|
||||
elif [ "$rc" -ne 0 ]; then
|
||||
if echo "$out" | grep -qiE "$TR_BENIGN_PAT"; then
|
||||
_tr_dbg "unit $unit: bcmcmd rc=$rc (${TR_BENIGN_PAT}) -> tolerated"
|
||||
return 0
|
||||
fi
|
||||
why="bcmcmd exited $rc"
|
||||
else
|
||||
return 0
|
||||
fi
|
||||
|
||||
_tr_err "unit $unit: $why -- '$cmd'"
|
||||
[ "$DEBUG_MODE" = "1" ] || { [ -n "$out" ] && echo "$out" >&2; }
|
||||
return 1
|
||||
}
|
||||
|
||||
_tr_units_check() {
|
||||
local u ok=""
|
||||
for u in $TR_UNITS; do
|
||||
case "$u" in
|
||||
0|1) ok="$ok $u" ;;
|
||||
*) _tr_err "invalid unit '$u' (use 0, 1 or all)"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
[ -n "$ok" ] || { _tr_err "no unit selected"; return 1; }
|
||||
TR_UNITS="${ok# }"
|
||||
return 0
|
||||
}
|
||||
|
||||
_tr_is_uint() { case "$1" in ''|*[!0-9]*) return 1 ;; *) return 0 ;; esac; }
|
||||
|
||||
_tr_gap() {
|
||||
[ "$TR_DRY_RUN" = "1" ] && return 0
|
||||
[ "$TR_UNIT_GAP_SEC" = "0" ] && return 0
|
||||
sleep "$TR_UNIT_GAP_SEC"
|
||||
}
|
||||
|
||||
# === start ===================================================================
|
||||
# One complete block per unit, exactly the order in tools/TR518.txt.
|
||||
blanton_tr518_start() {
|
||||
_tr_units_check || return 1
|
||||
_tr_is_uint "$TR_SETTLE_SEC" || { _tr_err "settle wait '$TR_SETTLE_SEC' is not an integer (-w <sec>)"; return 1; }
|
||||
|
||||
local unit fail=0 first=1
|
||||
_tr_info "TR518 start on unit(s): $TR_UNITS"
|
||||
for unit in $TR_UNITS; do
|
||||
[ "$first" = "0" ] && _tr_gap
|
||||
first=0
|
||||
_tr_info "unit $unit: port $TR_LB_PORTS lb=mac -> l2 learn off -> test mode nr=yes -> tr 518"
|
||||
_tr_bcm "$unit" "port $TR_LB_PORTS lb=mac" || fail=$((fail+1))
|
||||
_tr_bcm "$unit" "l2 learn off" || fail=$((fail+1))
|
||||
_tr_bcm "$unit" 'dsh -c "test mode nr=yes"' || fail=$((fail+1))
|
||||
# "TR 518 TEST PARAMETERS" is printed only once the shell has parsed the
|
||||
# arguments and started the test -- that is the proof we check for.
|
||||
_tr_bcm_ok "$unit" "$TR_TEST_OK_PAT" "dsh -c \"tr 518 $TR_TEST_ARGS\"" || fail=$((fail+1))
|
||||
done
|
||||
|
||||
if [ "$fail" -ne 0 ]; then
|
||||
_tr_err "$fail command(s) failed -- traffic may not be running, not waiting"
|
||||
_tr_warn "the unit(s) may still be in loopback: blanton_tr518.sh stop"
|
||||
return 1
|
||||
fi
|
||||
|
||||
if [ "$TR_NO_WAIT" = "1" ] || [ "$TR_SETTLE_SEC" = "0" ]; then
|
||||
_tr_ok "TR518 running on unit(s): $TR_UNITS (settle wait skipped)"
|
||||
_tr_warn "rails may still be ramping -- a power reading taken now is not a settled one"
|
||||
return 0
|
||||
fi
|
||||
|
||||
_tr_info "settling ${TR_SETTLE_SEC}s before the rails are worth reading ..."
|
||||
[ "$TR_DRY_RUN" = "1" ] || sleep "$TR_SETTLE_SEC"
|
||||
_tr_ok "TR518 running and settled on unit(s): $TR_UNITS"
|
||||
_tr_info "read power now: TH6_SWB0_power_readback.sh / TH6_SWB1_power_readback.sh"
|
||||
_tr_info "when finished: blanton_tr518.sh stop"
|
||||
return 0
|
||||
}
|
||||
|
||||
# === stop ====================================================================
|
||||
# TR518.txt stops with 'port cd lb=none' only. l2 learning and test mode are
|
||||
# left as start set them unless TR_RESTORE_* is turned on.
|
||||
blanton_tr518_stop() {
|
||||
_tr_units_check || return 1
|
||||
local unit fail=0 first=1
|
||||
_tr_info "TR518 stop on unit(s): $TR_UNITS"
|
||||
for unit in $TR_UNITS; do
|
||||
[ "$first" = "0" ] && _tr_gap
|
||||
first=0
|
||||
_tr_bcm "$unit" "port $TR_LB_PORTS lb=none" || fail=$((fail+1))
|
||||
[ "$TR_RESTORE_LEARN" = "1" ] && { _tr_bcm "$unit" "l2 learn on" || fail=$((fail+1)); }
|
||||
[ "$TR_RESTORE_TESTMODE" = "1" ] && { _tr_bcm "$unit" 'dsh -c "test mode nr=no"' || fail=$((fail+1)); }
|
||||
done
|
||||
|
||||
if [ "$fail" -eq 0 ]; then
|
||||
_tr_ok "unit(s) $TR_UNITS: port $TR_LB_PORTS lb=none"
|
||||
[ "$TR_RESTORE_LEARN" = "1" ] || \
|
||||
_tr_info "l2 learning is still off (TR_RESTORE_LEARN=1 to put it back)"
|
||||
[ "$TR_RESTORE_TESTMODE" = "1" ] || \
|
||||
_tr_info "test mode is still nr=yes (TR_RESTORE_TESTMODE=1 to put it back)"
|
||||
else
|
||||
_tr_warn "$fail command(s) failed -- check the unit is not still in loopback:"
|
||||
_tr_warn " bcmcmd -n <u> -c 'port $TR_LB_PORTS' | head"
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# === Help ====================================================================
|
||||
blanton_tr518_help() {
|
||||
echo -e "\033[1mblanton_tr518.sh - TH6 built-in packet test (tr 518) for power loading\033[0m"
|
||||
echo ""
|
||||
echo -e " Units : \033[36m$TR_UNITS\033[0m"
|
||||
echo -e " Settle wait : \033[36m${TR_SETTLE_SEC}s\033[0m after tr 518 (so power is read loaded, not ramping)"
|
||||
echo -e " Loopback : \033[36mport $TR_LB_PORTS lb=mac\033[0m"
|
||||
echo -e " tr 518 args : \033[36m$TR_TEST_ARGS\033[0m"
|
||||
echo ""
|
||||
echo -e "\033[1mSubcommands\033[0m"
|
||||
echo -e " \033[33mstart\033[0m per unit: port $TR_LB_PORTS lb=mac -> l2 learn off -> test mode nr=yes -> tr 518 -> wait"
|
||||
echo -e " \033[33mstop\033[0m per unit: port $TR_LB_PORTS lb=none"
|
||||
echo -e " \033[33mhelp\033[0m"
|
||||
echo ""
|
||||
echo -e "\033[1mOptions\033[0m"
|
||||
echo -e " \033[33m-u|--unit\033[0m <0|1|all> bcmcmd unit(s); 'all' = 0 1 (default: $TR_UNITS)"
|
||||
echo -e " \033[33m-w|--wait\033[0m <sec> start: settle wait (default $TR_SETTLE_SEC)"
|
||||
echo -e " \033[33m--no-wait\033[0m start: skip the settle wait"
|
||||
echo -e " \033[33m-d|--debug\033[0m print every bcmcmd and its output"
|
||||
echo -e " \033[33m-n|--dry-run\033[0m print commands only, do not touch the DUT"
|
||||
echo ""
|
||||
echo -e "\033[1mExamples\033[0m"
|
||||
echo -e " ./blanton_tr518.sh start # both units, then wait ${TR_SETTLE_SEC}s"
|
||||
echo -e " ./blanton_tr518.sh start -u 0 # unit 0 only"
|
||||
echo -e " ./blanton_tr518.sh stop -u 1 # release unit 1"
|
||||
echo -e " ./blanton_tr518.sh start -n # show the bcmcmds, touch nothing"
|
||||
echo ""
|
||||
echo -e "\033[33m stop only sends 'port $TR_LB_PORTS lb=none'. l2 learning stays off and test mode\033[0m"
|
||||
echo -e "\033[33m stays nr=yes -- TR_RESTORE_LEARN=1 / TR_RESTORE_TESTMODE=1 to put them back.\033[0m"
|
||||
echo -e "\033[33m tr 518 and blanton_traffic_linespeed cannot run together.\033[0m"
|
||||
}
|
||||
|
||||
# === Argument parsing ========================================================
|
||||
blanton_tr518() {
|
||||
local sub="${1:-help}"; shift 2>/dev/null
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
-u|--unit)
|
||||
case "$2" in
|
||||
all|ALL) TR_UNITS="0 1" ;;
|
||||
*) TR_UNITS="$(echo "$2" | tr ',' ' ')" ;;
|
||||
esac
|
||||
shift 2 ;;
|
||||
-w|--wait) TR_SETTLE_SEC="$2"; shift 2 ;;
|
||||
--no-wait) TR_NO_WAIT=1; shift ;;
|
||||
-d|--debug) DEBUG_MODE=1; shift ;;
|
||||
-n|--dry-run) TR_DRY_RUN=1; shift ;;
|
||||
-h|--help) blanton_tr518_help; return 0 ;;
|
||||
*) _tr_err "unknown option '$1'"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
case "$sub" in
|
||||
start) blanton_tr518_start ;;
|
||||
stop) blanton_tr518_stop ;;
|
||||
help|-h|--help) blanton_tr518_help ;;
|
||||
*) _tr_err "unknown subcommand '$sub'"; blanton_tr518_help; return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Run when executed, define-only when sourced (same as the other blanton_*.sh).
|
||||
if [ "${BASH_SOURCE[0]}" = "$0" ]; then
|
||||
blanton_tr518 "$@"
|
||||
fi
|
||||
@@ -6,7 +6,7 @@
|
||||
# V0.1.0 2026-08-17 First version. Bash port of the three Tera Term macros
|
||||
# utils/traffic_loopback_vlan_setting.ttl (VLAN 30..137,
|
||||
# port pair cdN <-> cdN+32), utils/traffic_loopback_start.ttl
|
||||
# (tx 100 length=512 VLantag=<vid>) and
|
||||
# (tx <count> length=<len> VLantag=<vid>) and
|
||||
# utils/traffic_loopback_vlan_remove.ttl.
|
||||
# One DUT = two switch boards -> bcmcmd unit 0 and 1
|
||||
# (bcmcmd -n <unit>), default both.
|
||||
@@ -40,6 +40,88 @@
|
||||
# to the plain text before colouring so the columns stay
|
||||
# aligned. Auto-disabled when stdout is not a terminal or
|
||||
# with --tsv; --color / --no-color / TL_COLOR force it.
|
||||
# V0.3.3 2026-08-17 Add: -tx / -length aliases for -c / -l so the tx burst can
|
||||
# be written the way the bcm command reads
|
||||
# ("start -u 0 -tx 100 -length 512"). Values are validated
|
||||
# as positive integers; omitted = defaults 100 / 512.
|
||||
# Fix: --dry-run printed nothing for init/start/stop/report
|
||||
# since V0.3.1 (the new wrapper discarded the "[DRY ]"
|
||||
# lines); the commands are listed again.
|
||||
# V0.4.0 2026-08-17 Change: report now lists ALL 108 pairs, PASS / FAIL / NA
|
||||
# alike, keeping one line per port (two lines per pair):
|
||||
# Port TX RX PASS/FAIL
|
||||
# cd0 4 4 PASS
|
||||
# cd32 4 4 PASS
|
||||
# cd204 - - NA
|
||||
# cd236 - - NA
|
||||
# Missing counters show '-'. -a is therefore the default
|
||||
# (the flag is still accepted), and the long
|
||||
# "# NA (no counters): ..." summary line is dropped because
|
||||
# every NA pair is now a visible row. This is the only
|
||||
# intentional difference from
|
||||
# tools/bcm_mibpair_report_V1.1.0.py, which hides NA pairs
|
||||
# unless -a is given.
|
||||
# V0.4.1 2026-08-19 Fix: report printed every counter as 2147483647 (INT32_MAX).
|
||||
# grp() rendered values with sprintf("%d", v); the DUT's awk
|
||||
# casts to a 32-bit int for %d, so any counter above 2^31-1
|
||||
# -- i.e. every real line-speed run -- saturated. Values are
|
||||
# now formatted with %.0f, which stays in awk's double domain
|
||||
# (exact to 2^53, far above any MIB counter).
|
||||
# NOTE: the PASS/FAIL verdicts were NEVER affected -- the
|
||||
# cross-check compares TX[]/RX[] doubles directly and only
|
||||
# the display path went through grp(). Past reports that said
|
||||
# PASS were right; only the numbers shown were wrong.
|
||||
# Same fix applied to the "# FAIL ..." delta line (%+d ->
|
||||
# %+.0f), which would otherwise saturate when a dead port
|
||||
# makes the delta the size of the whole counter.
|
||||
# V0.5.0 2026-08-28 Add: the 100G uplink (ce0, VLAN 138) joins init / start /
|
||||
# stop / report, from tools/100G_Traffic.txt.
|
||||
# ce0 is NOT a loopback pair: there is one per unit and the
|
||||
# two are cabled to each other, so its verdict is a
|
||||
# CROSS-UNIT check and cannot be decided from one unit's
|
||||
# counters. It therefore appears as the LAST row of each
|
||||
# unit table with the verdict DEFER, and is judged in a new
|
||||
# summary printed once at the very bottom, after every
|
||||
# unit -- which also carries the per-unit PASS/FAIL/NA
|
||||
# totals ("all Results" in one place).
|
||||
# TL_CE_MODE=cross (default) | self picks the topology;
|
||||
# it is a plain editable flag, NOT auto-detected, because
|
||||
# a non-zero RX cannot tell the two cablings apart.
|
||||
# With only one unit selected the summary reports
|
||||
# UNDECIDED (exit 3) instead of guessing.
|
||||
# TL_CE_ENABLE=0 restores the old cd-pairs-only behaviour.
|
||||
# V0.7.0 2026-09-01 Change: tx bursts carry PatternRandom=yes and the defaults
|
||||
# become tx 200 length=324 (were 100 / 512).
|
||||
# Random payload keeps the bit pattern changing instead of
|
||||
# repeating, which is what makes a marginal lane show up;
|
||||
# a fixed pattern can sit on a benign sequence all run.
|
||||
# TL_TX_RANDOM=no forces the fixed pattern, "" leaves the
|
||||
# argument off entirely (pre-V0.7.0 wire format).
|
||||
# NOTE: counters scale with count x length, so totals from
|
||||
# before this build are not comparable - 200x324 moves
|
||||
# about 27% more bytes per burst than 100x512.
|
||||
# V0.6.0 2026-08-28 Add: ce0 traffic is now SUSTAINED, not a single burst.
|
||||
# A cd pair keeps its packets circulating because they
|
||||
# flood to the partner port; ce0 has no partner and a
|
||||
# switch will not send a frame back out its ingress port,
|
||||
# so 'tx 100' was exactly one round trip (TX 100/RX 100)
|
||||
# and then silence. init now sets an INGRESS MIRROR of ce0
|
||||
# back to ce0 -- the mirrored copy is not egress-filtered,
|
||||
# so each packet keeps lapping until stop turns it off.
|
||||
# init : mirror init; mirror port ce0 Mode=Ingress
|
||||
# DestPort=ce0; vlan create/add
|
||||
# stop : mirror port ce0 Mode=Off (FIRST -- this is what
|
||||
# breaks the loop), then vlan remove
|
||||
# Bench-verified command set. TL_CE_MIRROR=0 goes back to
|
||||
# the one-shot burst.
|
||||
# Change: TL_CE_MODE now defaults to 'self'. 'ps ce' shows
|
||||
# one ce port per unit and a unit-0-only burst returned on
|
||||
# unit 0, so the cross-unit reading was wrong.
|
||||
# V0.5.1 2026-08-28 Add: TL_CE_COUNTER selects which counter judges the ce
|
||||
# port -- packets (MIB_TPOK/MIB_RPOK, default, same as the
|
||||
# cd rows) or bytes (MIB_TBYT/MIB_RBYT). The report prints
|
||||
# which one it used under the table, so a byte figure is
|
||||
# never mistaken for a packet count next to the cd rows.
|
||||
# =============================================================================
|
||||
#
|
||||
# The VLAN/port table below is copied verbatim from
|
||||
@@ -67,11 +149,16 @@
|
||||
# Options (any order, after the subcommand):
|
||||
# -u|--unit <0|1|all|0,1> bcmcmd unit(s). Default: $TL_UNITS ("0 1")
|
||||
# -c|--count <n> tx packet count (default $TL_TX_COUNT)
|
||||
# aliases: -tx | --tx
|
||||
# -l|--length <n> tx packet length (default $TL_TX_LENGTH)
|
||||
# aliases: -length | --len
|
||||
# -r|--random <yes|no> tx PatternRandom (default $TL_TX_RANDOM;
|
||||
# empty string omits the argument)
|
||||
# -p|--ports <list|all> ps: port list ('all' = plain 'ps', every port)
|
||||
# -T|--tolerance <n> report: allowed |delta| in packets (default 0;
|
||||
# -T 1 absorbs the normal snapshot skew)
|
||||
# -a|--all report: also list pairs that have no counters
|
||||
# -a|--all report: accepted for compatibility -- every pair is
|
||||
# listed by default, NA included
|
||||
# -g|--grouped report: comma-group the values (1,234,567)
|
||||
# -P|--with-port report: render cd1(2) instead of cd1
|
||||
# -q|--quiet report: drop the trailing summary comments
|
||||
@@ -86,7 +173,8 @@
|
||||
# -h|--help help
|
||||
#
|
||||
# Environment overrides:
|
||||
# BCMCMD_CMD=bcmcmd TL_UNITS="0 1" TL_TX_COUNT=100 TL_TX_LENGTH=512
|
||||
# BCMCMD_CMD=bcmcmd TL_UNITS="0 1" TL_TX_COUNT=200 TL_TX_LENGTH=324
|
||||
# TL_TX_RANDOM=yes
|
||||
# TL_PS_PORTS="1-24,40-96,..." TL_TOLERANCE=0 TL_LOG_DIR=/tmp
|
||||
# DEBUG_MODE=1
|
||||
#
|
||||
@@ -98,8 +186,14 @@
|
||||
# === Config ==================================================================
|
||||
BCMCMD_CMD="${BCMCMD_CMD:-bcmcmd}"
|
||||
TL_UNITS="${TL_UNITS:-0 1}" # one DUT = two switch boards (0 and 1)
|
||||
TL_TX_COUNT="${TL_TX_COUNT:-100}"
|
||||
TL_TX_LENGTH="${TL_TX_LENGTH:-512}"
|
||||
TL_TX_COUNT="${TL_TX_COUNT:-200}"
|
||||
TL_TX_LENGTH="${TL_TX_LENGTH:-324}"
|
||||
|
||||
# PatternRandom=yes|no is appended to every tx burst. Random payload exercises
|
||||
# the SerDes with changing bit patterns instead of the repeating one a fixed
|
||||
# pattern produces, which is what makes a marginal lane show up.
|
||||
# Set to "" to leave the argument off entirely (pre-V0.7.0 behaviour).
|
||||
TL_TX_RANDOM="${TL_TX_RANDOM:-yes}"
|
||||
TL_DEFAULT_VLAN="${TL_DEFAULT_VLAN:-1}"
|
||||
TL_DEFAULT_VLAN_PBM="${TL_DEFAULT_VLAN_PBM:-cd}"
|
||||
|
||||
@@ -108,6 +202,56 @@ TL_DEFAULT_VLAN_PBM="${TL_DEFAULT_VLAN_PBM:-cd}"
|
||||
# pasted straight from/into a manual "bcmcmd -n 0 -c 'ps <list>'".
|
||||
TL_PS_PORTS="${TL_PS_PORTS:-1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565}"
|
||||
|
||||
# --- 100G uplink (ce0) ------------------------------------------------------
|
||||
# The cd pairs above are loopback pairs WITHIN one switch unit (cdN <-> cdN+32).
|
||||
# ce0 is not a pair: 'ps ce' shows exactly one ce port per unit, and it is looped
|
||||
# back on itself. Bench-confirmed 2026-08-28 -- a tx burst on unit 0 alone came
|
||||
# back on unit 0 (TPOK +100 AND RPOK +100), which only happens on a self loop.
|
||||
#
|
||||
# TL_CE_MODE=self ce0 loops back on itself (default, matches bench)
|
||||
# verdict: TX == RX within the unit, decided in its own table
|
||||
# TL_CE_MODE=cross unit0.ce0 <-> unit1.ce0 cabled together
|
||||
# verdict: unit0.TX == unit1.RX and unit0.RX == unit1.TX,
|
||||
# decided in the summary; needs BOTH units
|
||||
#
|
||||
# If the bench cabling changes, edit TL_CE_MODE -- it is not auto-detected,
|
||||
# because "RX happens to be non-zero" cannot tell the two topologies apart.
|
||||
# Note the two modes agree whenever both units send the same amount, so a wrong
|
||||
# setting looks fine until something actually breaks: with a self loop read as
|
||||
# cross, BOTH links dying still leaves unit0.TX == unit1.RX (0 == 0) -> PASS.
|
||||
TL_CE_ENABLE=${TL_CE_ENABLE:-1} # 0 = skip ce0 entirely (cd pairs only)
|
||||
TL_CE_VLAN="${TL_CE_VLAN:-138}" # one past the cd range (30..137)
|
||||
TL_CE_PORT="${TL_CE_PORT:-ce0}" # bcm port name, same on both units
|
||||
TL_CE_MODE="${TL_CE_MODE:-self}" # cross | self -- see above
|
||||
|
||||
# --- Why ce0 needs an ingress mirror -----------------------------------------
|
||||
# A cd pair sustains itself: the packet floods to the OTHER member, goes out the
|
||||
# cable, comes back on the partner, floods to the other member again -- forever.
|
||||
# ce0 has no partner. A switch never forwards a frame back out the port it
|
||||
# arrived on (source-port knockout), so with ce0 as the only VLAN member the
|
||||
# returning packet is dropped and one 'tx' burst is exactly one round trip:
|
||||
# TX 100, RX 100, done. That measures the link, it does not load it.
|
||||
#
|
||||
# An INGRESS MIRROR of ce0 back to ce0 is the way round it: the mirrored copy is
|
||||
# not subject to the egress filter, so it does leave the port it came in on.
|
||||
# Each circulating packet makes exactly one copy per lap -- 1:1, not amplifying,
|
||||
# so the load is set by how many packets 'start' injects, and it runs until
|
||||
# 'stop' turns the mirror off.
|
||||
#
|
||||
# ⚠️ The loop does NOT stop on its own. Unlike the cd pairs, removing the VLAN
|
||||
# membership is not enough -- 'stop' must set Mode=Off, or the port keeps
|
||||
# running flat out with nothing in 'show interfaces status' to hint at it.
|
||||
# ⚠️ 'mirror init' resets the mirror module. Anything else using mirroring on
|
||||
# this box (ERSPAN, monitoring) is cleared. Set TL_CE_MIRROR=0 to skip it.
|
||||
TL_CE_MIRROR=${TL_CE_MIRROR:-1} # 0 = no mirror (one-shot burst, as before)
|
||||
|
||||
# Which counter the ce port is judged on. Packets by default, the same counter
|
||||
# as the cd pairs, so every row of the table is in the same unit.
|
||||
# packets -> MIB_TPOK / MIB_RPOK (default, same as the cd rows)
|
||||
# bytes -> MIB_TBYT / MIB_RBYT
|
||||
# Either way the report prints which one it used under the table.
|
||||
TL_CE_COUNTER="${TL_CE_COUNTER:-packets}"
|
||||
|
||||
# --- report (pair cross-check) defaults -------------------------------------
|
||||
TL_TOLERANCE="${TL_TOLERANCE:-0}" # allowed |delta| in packets before FAIL
|
||||
TL_LOG_DIR="${TL_LOG_DIR:-/tmp}" # where the raw 'show c' capture is kept
|
||||
@@ -283,7 +427,8 @@ TL_BENIGN_REMOVE="${TL_BENIGN_REMOVE:-Entry not found|not found|does not exist|n
|
||||
_tl_bcm_run() {
|
||||
local unit="$1" benign="$2"; shift 2
|
||||
local cmd="$*" out rc
|
||||
if [ "$TL_DRY_RUN" = "1" ]; then _tl_bcm "$unit" "$cmd" >/dev/null; return 0; fi
|
||||
# dry-run: let _tl_bcm print the "[DRY ] bcmcmd ..." line, run nothing
|
||||
if [ "$TL_DRY_RUN" = "1" ]; then _tl_bcm "$unit" "$cmd"; return 0; fi
|
||||
_tl_dbg "$BCMCMD_CMD -n $unit -c '$cmd'"
|
||||
out=$("$BCMCMD_CMD" -n "$unit" -c "$cmd" </dev/null 2>&1); rc=$?
|
||||
[ "$DEBUG_MODE" = "1" ] && [ -n "$out" ] && echo "$out"
|
||||
@@ -319,6 +464,9 @@ _tl_units_check() {
|
||||
|
||||
_tl_pair_count() { echo "$TL_PAIRS" | grep -c . ; }
|
||||
|
||||
# positive integer? (tx count / length come straight from the command line)
|
||||
_tl_is_uint() { case "$1" in ''|*[!0-9]*) return 1 ;; 0) return 1 ;; *) return 0 ;; esac; }
|
||||
|
||||
# === Step 1: VLAN loopback setup (traffic_loopback_vlan_setting.ttl) =========
|
||||
traffic_linespeed_init() {
|
||||
_tl_units_check || return 1
|
||||
@@ -337,6 +485,21 @@ traffic_linespeed_init() {
|
||||
_tl_bcm_q "$unit" "vlan add $vid pbm=$pa,$pb" || fail=$((fail+1))
|
||||
n=$((n+1))
|
||||
done 3<<< "$TL_PAIRS"
|
||||
# 100G uplink: one port, its own VLAN, added last so it is easy to skip.
|
||||
# The mirror goes up BEFORE the VLAN so the loop is armed the moment the
|
||||
# first packet is injected.
|
||||
if [ "$TL_CE_ENABLE" = "1" ]; then
|
||||
if [ "$TL_CE_MIRROR" = "1" ]; then
|
||||
_tl_bcm_q "$unit" "mirror init" || fail=$((fail+1))
|
||||
_tl_bcm_q "$unit" "mirror port $TL_CE_PORT Mode=Ingress DestPort=$TL_CE_PORT" \
|
||||
|| fail=$((fail+1))
|
||||
fi
|
||||
_tl_bcm_run "$unit" "$TL_BENIGN_CREATE" "vlan create $TL_CE_VLAN"; rc=$?
|
||||
[ "$rc" = "1" ] && fail=$((fail+1))
|
||||
[ "$rc" = "2" ] && exist=$((exist+1))
|
||||
_tl_bcm_q "$unit" "vlan add $TL_CE_VLAN pbm=$TL_CE_PORT" || fail=$((fail+1))
|
||||
n=$((n+1))
|
||||
fi
|
||||
if [ "$fail" -eq 0 ]; then
|
||||
_tl_ok "unit $unit: $n VLANs configured$([ "$exist" -gt 0 ] && echo " ($exist already existed)"), port pairs added"
|
||||
else
|
||||
@@ -369,17 +532,31 @@ traffic_linespeed_show() {
|
||||
# === Step 4: start traffic (traffic_loopback_start.ttl) =====================
|
||||
traffic_linespeed_start() {
|
||||
_tl_units_check || return 1
|
||||
_tl_is_uint "$TL_TX_COUNT" || { _tl_err "tx count '$TL_TX_COUNT' is not a positive integer (-tx|-c <n>)"; return 1; }
|
||||
_tl_is_uint "$TL_TX_LENGTH" || { _tl_err "tx length '$TL_TX_LENGTH' is not a positive integer (-length|-l <n>)"; return 1; }
|
||||
local rnd=""
|
||||
case "$TL_TX_RANDOM" in
|
||||
yes|no) rnd=" PatternRandom=$TL_TX_RANDOM" ;;
|
||||
"") rnd="" ;;
|
||||
*) _tl_err "PatternRandom '$TL_TX_RANDOM' must be yes, no or empty (-r|--random)"; return 1 ;;
|
||||
esac
|
||||
local unit vid pa pb n fail
|
||||
for unit in $TL_UNITS; do
|
||||
n=0; fail=0
|
||||
_tl_info "unit $unit: tx $TL_TX_COUNT length=$TL_TX_LENGTH per VLAN 30..137"
|
||||
_tl_info "unit $unit: tx $TL_TX_COUNT length=$TL_TX_LENGTH${rnd} per VLAN 30..137"
|
||||
while read -r vid pa pb <&3; do
|
||||
[ -z "$vid" ] && continue
|
||||
_tl_bcm_q "$unit" "tx $TL_TX_COUNT length=$TL_TX_LENGTH VLantag=$vid" || fail=$((fail+1))
|
||||
_tl_bcm_q "$unit" "tx $TL_TX_COUNT length=$TL_TX_LENGTH VLantag=$vid${rnd}" || fail=$((fail+1))
|
||||
n=$((n+1))
|
||||
done 3<<< "$TL_PAIRS"
|
||||
if [ "$TL_CE_ENABLE" = "1" ]; then
|
||||
_tl_bcm_q "$unit" "tx $TL_TX_COUNT length=$TL_TX_LENGTH VLantag=$TL_CE_VLAN${rnd}" || fail=$((fail+1))
|
||||
n=$((n+1))
|
||||
fi
|
||||
if [ "$fail" -eq 0 ]; then
|
||||
_tl_ok "unit $unit: $n bursts sent ($((n * TL_TX_COUNT)) packets, ${TL_TX_LENGTH}B each)"
|
||||
[ "$TL_CE_ENABLE" = "1" ] && [ "$TL_CE_MIRROR" = "1" ] && \
|
||||
_tl_info "unit $unit: ${TL_CE_PORT} is now circulating and will keep running until 'stop'"
|
||||
else
|
||||
_tl_warn "unit $unit: $n bursts attempted, $fail failed"
|
||||
fi
|
||||
@@ -403,6 +580,25 @@ traffic_linespeed_stop() {
|
||||
fi
|
||||
n=$((n+1))
|
||||
done 3<<< "$TL_PAIRS"
|
||||
if [ "$TL_CE_ENABLE" = "1" ]; then
|
||||
# Mirror OFF first: that is what actually breaks the loop. Removing
|
||||
# the VLAN membership does not -- the mirrored copy never consulted
|
||||
# the VLAN in the first place.
|
||||
if [ "$TL_CE_MIRROR" = "1" ]; then
|
||||
_tl_bcm_q "$unit" "mirror port $TL_CE_PORT Mode=Off" || {
|
||||
fail=$((fail+1))
|
||||
_tl_err "unit $unit: ${TL_CE_PORT} mirror still ON -- the loop is STILL RUNNING"
|
||||
_tl_err " stop it by hand: ${BCMCMD_CMD} -n $unit -c 'mirror port $TL_CE_PORT Mode=Off'"
|
||||
}
|
||||
fi
|
||||
_tl_bcm_run "$unit" "$TL_BENIGN_REMOVE" "vlan remove $TL_CE_VLAN pbm=$TL_CE_PORT"
|
||||
[ "$?" = "1" ] && fail=$((fail+1))
|
||||
if [ "$TL_DESTROY" = "1" ]; then
|
||||
_tl_bcm_run "$unit" "$TL_BENIGN_REMOVE" "vlan destroy $TL_CE_VLAN"
|
||||
[ "$?" = "1" ] && fail=$((fail+1))
|
||||
fi
|
||||
n=$((n+1))
|
||||
fi
|
||||
if [ "$fail" -eq 0 ]; then
|
||||
_tl_ok "unit $unit: $n VLANs cleaned$([ "$TL_DESTROY" = "1" ] && echo " and destroyed")"
|
||||
else
|
||||
@@ -437,8 +633,11 @@ traffic_linespeed_ps() {
|
||||
# (a cd port absent from 'show c' means the counter is zero or the
|
||||
# console scrolled -- cross-check with 'ps' before blaming the port).
|
||||
# _tl_pair_report <logfile> -> 0 all PASS, 2 any FAIL/NA, 1 parse error
|
||||
# _tl_pair_report <logfile> [side_file]
|
||||
# side_file (optional) receives machine-readable lines for the cross-unit
|
||||
# summary: SUM <npass> <nfail> <nna> CE <tx> <rx> (CE omitted if absent)
|
||||
_tl_pair_report() {
|
||||
local log="$1" color=0
|
||||
local log="$1" side="${2:-/dev/null}" color=0
|
||||
# PASS green / FAIL red / NA yellow. auto = only when stdout is a terminal,
|
||||
# so redirecting to a file or piping into grep/diff stays plain text.
|
||||
case "$TL_COLOR" in
|
||||
@@ -454,9 +653,13 @@ _tl_pair_report() {
|
||||
-v WITHPORT="$TL_REPORT_WITHPORT" \
|
||||
-v QUIET="$TL_REPORT_QUIET" \
|
||||
-v TSV="$TL_REPORT_TSV" \
|
||||
-v COLOR="$color" '
|
||||
-v COLOR="$color" \
|
||||
-v CEPORT="$([ "$TL_CE_ENABLE" = "1" ] && echo "$TL_CE_PORT")" \
|
||||
-v CEMODE="$TL_CE_MODE" \
|
||||
-v CECOUNTER="$TL_CE_COUNTER" \
|
||||
-v SIDE="$side" '
|
||||
function grp(v, s,out,l,i) {
|
||||
s = sprintf("%d", v)
|
||||
s = sprintf("%.0f", v)
|
||||
if (!GROUPED) return s
|
||||
out = ""; l = length(s)
|
||||
for (i = 1; i <= l; i++) {
|
||||
@@ -470,8 +673,9 @@ _tl_pair_report() {
|
||||
# colour the verdict token: PASS green, FAIL red, NA yellow
|
||||
function vc(v) {
|
||||
if (!COLOR) return v
|
||||
if (v == "PASS") return "\033[32m" v "\033[0m"
|
||||
if (v == "FAIL") return "\033[31m" v "\033[0m"
|
||||
if (v == "PASS") return "\033[32m" v "\033[0m"
|
||||
if (v == "FAIL") return "\033[31m" v "\033[0m"
|
||||
if (v == "DEFER") return "\033[36m" v "\033[0m" # cyan: judged in the summary
|
||||
return "\033[33m" v "\033[0m"
|
||||
}
|
||||
function redl(s) { return COLOR ? "\033[31m" s "\033[0m" : s }
|
||||
@@ -480,17 +684,24 @@ _tl_pair_report() {
|
||||
NP = split(PAIRS, L, "\n")
|
||||
for (i = 1; i <= NP; i++) { split(L[i], f, " "); VID[i] = f[1]; A[i] = f[2]; B[i] = f[3] }
|
||||
MISSING = "-"
|
||||
NC = 4
|
||||
HDR[1] = "Port"; AL[1] = 0
|
||||
HDR[2] = "TX"; AL[2] = 1
|
||||
HDR[3] = "RX"; AL[3] = 1
|
||||
HDR[4] = "PASS/FAIL"; AL[4] = 1
|
||||
VCOL = NC # the verdict is always the last column
|
||||
}
|
||||
{
|
||||
idx = index($0, "MIB_")
|
||||
if (idx == 0) next
|
||||
s = substr($0, idx)
|
||||
kind = substr(s, 5, 4)
|
||||
if (kind != "TPOK" && kind != "RPOK") next
|
||||
# POK = packets (the cd pairs), BYT = bytes (used for the ce port)
|
||||
if (kind != "TPOK" && kind != "RPOK" && kind != "TBYT" && kind != "RBYT") next
|
||||
p1 = index(s, "."); p2 = index(s, "("); p3 = index(s, ")"); p4 = index(s, ":")
|
||||
if (p1 == 0 || p2 == 0 || p3 == 0 || p4 == 0 || p2 < p1 || p4 < p3) next
|
||||
cd = substr(s, p1 + 1, p2 - p1 - 1)
|
||||
if (cd !~ /^cd[0-9]+$/) next
|
||||
if (cd !~ /^(cd|ce)[0-9]+$/) next
|
||||
lp = substr(s, p2 + 1, p3 - p2 - 1)
|
||||
val = substr(s, p4 + 1)
|
||||
sub(/^[ \t]+/, "", val)
|
||||
@@ -498,7 +709,10 @@ _tl_pair_report() {
|
||||
sub(/[ \t].*$/, "", val)
|
||||
gsub(/,/, "", val)
|
||||
LP[cd] = lp
|
||||
if (kind == "TPOK") { TX[cd] = val + 0; HTX[cd] = 1 } else { RX[cd] = val + 0; HRX[cd] = 1 }
|
||||
if (kind == "TPOK") { TX[cd] = val + 0; HTX[cd] = 1 }
|
||||
else if (kind == "RPOK") { RX[cd] = val + 0; HRX[cd] = 1 }
|
||||
else if (kind == "TBYT") { TXB[cd] = val + 0; HTXB[cd] = 1 }
|
||||
else { RXB[cd] = val + 0; HRXB[cd] = 1 }
|
||||
seen++
|
||||
}
|
||||
END {
|
||||
@@ -512,44 +726,87 @@ _tl_pair_report() {
|
||||
oka = (a in HTX) && (a in HRX); okb = (b in HTX) && (b in HRX)
|
||||
if (!(oka && okb)) {
|
||||
v = "NA"; nna++
|
||||
miss = miss (miss == "" ? "" : " ") a "/" b
|
||||
if (!ALL) continue
|
||||
ta = oka ? grp(TX[a]) : MISSING; ra = oka ? grp(RX[a]) : MISSING
|
||||
tb = okb ? grp(TX[b]) : MISSING; rb = okb ? grp(RX[b]) : MISSING
|
||||
# every pair is listed, NA included; absent counters show '-'
|
||||
ta = (a in HTX) ? grp(TX[a]) : MISSING; ra = (a in HRX) ? grp(RX[a]) : MISSING
|
||||
tb = (b in HTX) ? grp(TX[b]) : MISSING; rb = (b in HRX) ? grp(RX[b]) : MISSING
|
||||
} else {
|
||||
dtx = TX[a] - RX[b]; drx = RX[a] - TX[b]
|
||||
d = absd(dtx); if (absd(drx) > d) d = absd(drx)
|
||||
if (d <= TOL + 0) { v = "PASS"; npass++ }
|
||||
else {
|
||||
v = "FAIL"; nfail++
|
||||
FL[++nf] = sprintf("# FAIL %s/%s: %s.TX-%s.RX=%+d %s.RX-%s.TX=%+d", \
|
||||
FL[++nf] = sprintf("# FAIL %s/%s: %s.TX-%s.RX=%+.0f %s.RX-%s.TX=%+.0f", \
|
||||
a, b, a, b, dtx, a, b, drx)
|
||||
}
|
||||
ta = grp(TX[a]); ra = grp(RX[a]); tb = grp(TX[b]); rb = grp(RX[b])
|
||||
}
|
||||
nrep++
|
||||
nrow++; C0[nrow] = pname(a); C1[nrow] = ta; C2[nrow] = ra; C3[nrow] = v
|
||||
nrow++; C0[nrow] = pname(b); C1[nrow] = tb; C2[nrow] = rb; C3[nrow] = v
|
||||
nrow++; CELL[nrow,1] = pname(a); CELL[nrow,2] = ta; CELL[nrow,3] = ra; CELL[nrow,4] = v
|
||||
nrow++; CELL[nrow,1] = pname(b); CELL[nrow,2] = tb; CELL[nrow,3] = rb; CELL[nrow,4] = v
|
||||
}
|
||||
|
||||
H0 = "Port"; H1 = "TX"; H2 = "RX"; H3 = "PASS/FAIL"
|
||||
if (TSV) {
|
||||
print H0 "\t" H1 "\t" H2 "\t" H3
|
||||
for (r = 1; r <= nrow; r++) print C0[r] "\t" C1[r] "\t" C2[r] "\t" C3[r]
|
||||
} else {
|
||||
w0 = length(H0); w1 = length(H1); w2 = length(H2); w3 = length(H3)
|
||||
for (r = 1; r <= nrow; r++) {
|
||||
if (length(C0[r]) > w0) w0 = length(C0[r])
|
||||
if (length(C1[r]) > w1) w1 = length(C1[r])
|
||||
if (length(C2[r]) > w2) w2 = length(C2[r])
|
||||
if (length(C3[r]) > w3) w3 = length(C3[r])
|
||||
# --- 100G uplink, appended LAST so it sits at the bottom of the table ---
|
||||
# It is a single port, not a pair, so it gets one row. In cross mode the
|
||||
# verdict needs the OTHER unit counters and is decided in the summary;
|
||||
# DEFER says "not judged here", which is not the same as NA ("no data").
|
||||
cev = ""; ceunit = ""
|
||||
if (CEPORT != "") {
|
||||
if (CECOUNTER == "packets") {
|
||||
ceunit = "packets"
|
||||
haveT = (CEPORT in HTX); haveR = (CEPORT in HRX)
|
||||
cetv = TX[CEPORT]; cerv = RX[CEPORT]
|
||||
} else {
|
||||
ceunit = "bytes"
|
||||
haveT = (CEPORT in HTXB); haveR = (CEPORT in HRXB)
|
||||
cetv = TXB[CEPORT]; cerv = RXB[CEPORT]
|
||||
}
|
||||
w0 += 2; w1 += 2; w2 += 2; w3 += 2
|
||||
printf "%-*s%*s%*s%*s\n", w0, H0, w1, H1, w2, H2, w3, H3
|
||||
cet = haveT ? grp(cetv) : MISSING
|
||||
cer = haveR ? grp(cerv) : MISSING
|
||||
if (!(haveT && haveR)) {
|
||||
cev = "NA"; nna++
|
||||
} else if (CEMODE == "self") {
|
||||
if (absd(cetv - cerv) <= TOL + 0) { cev = "PASS"; npass++ }
|
||||
else {
|
||||
cev = "FAIL"; nfail++
|
||||
FL[++nf] = sprintf("# FAIL %s: TX-RX=%+.0f %s (self loopback)", \
|
||||
CEPORT, cetv - cerv, ceunit)
|
||||
}
|
||||
} else {
|
||||
cev = "DEFER"
|
||||
}
|
||||
nrep++
|
||||
nrow++; CELL[nrow,1] = pname(CEPORT); CELL[nrow,2] = cet; CELL[nrow,3] = cer; CELL[nrow,4] = cev
|
||||
if (SIDE != "" && SIDE != "/dev/null" && haveT && haveR)
|
||||
printf "CE %.0f %.0f\n", cetv, cerv > SIDE
|
||||
}
|
||||
|
||||
if (TSV) {
|
||||
line = HDR[1]
|
||||
for (c = 2; c <= NC; c++) line = line "\t" HDR[c]
|
||||
print line
|
||||
for (r = 1; r <= nrow; r++) {
|
||||
# pad on the plain text, then colour, so the columns stay aligned
|
||||
printf "%-*s%*s%*s", w0, C0[r], w1, C1[r], w2, C2[r]
|
||||
printf "%*s%s\n", w3 - length(C3[r]), "", vc(C3[r])
|
||||
line = CELL[r, 1]
|
||||
for (c = 2; c <= NC; c++) line = line "\t" CELL[r, c]
|
||||
print line
|
||||
}
|
||||
} else {
|
||||
for (c = 1; c <= NC; c++) {
|
||||
w[c] = length(HDR[c])
|
||||
for (r = 1; r <= nrow; r++) if (length(CELL[r, c]) > w[c]) w[c] = length(CELL[r, c])
|
||||
w[c] += 2
|
||||
}
|
||||
for (c = 1; c <= NC; c++) printf(AL[c] ? "%*s" : "%-*s", w[c], HDR[c])
|
||||
printf "\n"
|
||||
for (r = 1; r <= nrow; r++) {
|
||||
for (c = 1; c <= NC; c++) {
|
||||
if (c == VCOL) {
|
||||
# pad on the plain text, then colour, so columns stay aligned
|
||||
printf "%*s%s", w[c] - length(CELL[r, c]), "", vc(CELL[r, c])
|
||||
} else {
|
||||
printf(AL[c] ? "%*s" : "%-*s", w[c], CELL[r, c])
|
||||
}
|
||||
}
|
||||
printf "\n"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,38 +816,132 @@ _tl_pair_report() {
|
||||
printf "# pairs reported : %d\n", nrep
|
||||
printf "# %s %d %s %d %s %d (tolerance %d)\n", \
|
||||
vc("PASS"), npass, vc("FAIL"), nfail, vc("NA"), nna, TOL + 0
|
||||
if (miss != "") printf "# %s (no counters): %s\n", vc("NA"), miss
|
||||
if (CEPORT != "" && ceunit != "")
|
||||
printf "# %s TX/RX are %s (MIB_%s/MIB_%s); the cd rows are packets\n", \
|
||||
CEPORT, ceunit, \
|
||||
(ceunit == "bytes" ? "TBYT" : "TPOK"), \
|
||||
(ceunit == "bytes" ? "RBYT" : "RPOK")
|
||||
if (cev == "DEFER")
|
||||
printf "# %s is judged across units -- see the summary at the end\n", CEPORT
|
||||
# every NA pair is a visible row -> no long "no counters" list needed
|
||||
for (i = 1; i <= nf; i++) print redl(FL[i])
|
||||
}
|
||||
if (SIDE != "" && SIDE != "/dev/null")
|
||||
printf "SUM %d %d %d\n", npass, nfail, nna > SIDE
|
||||
exit (nfail || nna) ? 2 : 0
|
||||
}' "$log"
|
||||
}
|
||||
|
||||
# _tl_ce_summary -- the cross-unit ce0 verdict + the per-unit totals.
|
||||
# Printed once, at the very bottom, after every unit's table.
|
||||
# Args: <stamp> (side files are $TL_LOG_DIR/tlside_unit<N>_<stamp>)
|
||||
# Returns 0 all PASS, 2 any FAIL/NA, 3 could not be decided.
|
||||
_tl_ce_summary() {
|
||||
local stamp="$1" unit side c g y n r
|
||||
c=$'\033[36m'; g=$'\033[32m'; y=$'\033[33m'; r=$'\033[31m'; n=$'\033[0m'
|
||||
case "$TL_COLOR" in
|
||||
never|0|no) c=""; g=""; y=""; r=""; n="" ;;
|
||||
always|1|yes) ;;
|
||||
*) [ -t 1 ] || { c=""; g=""; y=""; r=""; n=""; } ;;
|
||||
esac
|
||||
|
||||
local u tx rx pass fail na have=""
|
||||
local -A CETX CERX UPASS UFAIL UNA
|
||||
for unit in $TL_UNITS; do
|
||||
side="$TL_LOG_DIR/tlside_unit${unit}_${stamp}"
|
||||
[ -r "$side" ] || continue
|
||||
while read -r tag a b cc; do
|
||||
case "$tag" in
|
||||
CE) CETX[$unit]="$a"; CERX[$unit]="$b" ;;
|
||||
SUM) UPASS[$unit]="$a"; UFAIL[$unit]="$b"; UNA[$unit]="$cc" ;;
|
||||
esac
|
||||
done < "$side"
|
||||
have="$have $unit"
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "===== summary : all units ====="
|
||||
printf '%-8s %8s %8s %8s %s\n' "Unit" "PASS" "FAIL" "NA" "RESULT"
|
||||
local worst=0 v
|
||||
for unit in $have; do
|
||||
pass="${UPASS[$unit]:-0}"; fail="${UFAIL[$unit]:-0}"; na="${UNA[$unit]:-0}"
|
||||
if [ "$fail" -gt 0 ] || [ "$na" -gt 0 ]; then v="${r}FAIL${n}"; worst=2
|
||||
else v="${g}PASS${n}"; fi
|
||||
printf '%-8s %8s %8s %8s %b\n' "unit $unit" "$pass" "$fail" "$na" "$v"
|
||||
done
|
||||
|
||||
[ "$TL_CE_ENABLE" = "1" ] || { echo ""; return "$worst"; }
|
||||
|
||||
echo ""
|
||||
echo "----- ${TL_CE_PORT} (100G uplink, VLAN ${TL_CE_VLAN}, mode=${TL_CE_MODE}, counter=${TL_CE_COUNTER}) -----"
|
||||
if [ "$TL_CE_MODE" != "cross" ]; then
|
||||
echo "# mode=self: the verdict is in each unit's table above"
|
||||
echo ""
|
||||
return "$worst"
|
||||
fi
|
||||
|
||||
# cross mode needs both units' counters
|
||||
if [ -z "${CETX[0]}" ] || [ -z "${CETX[1]}" ]; then
|
||||
printf '%b\n' "${y}UNDECIDED${n} ${TL_CE_PORT} is a cross-unit check and needs unit 0 AND unit 1;"
|
||||
echo " this run had TL_UNITS=\"$TL_UNITS\" (counters seen for:${have:-none})."
|
||||
echo " Re-run with -u all, or set TL_CE_MODE=self if the cabling is a self loopback."
|
||||
echo ""
|
||||
[ "$worst" -lt 3 ] && worst=3
|
||||
return "$worst"
|
||||
fi
|
||||
|
||||
local cu="bytes"; [ "$TL_CE_COUNTER" = "packets" ] && cu="packets"
|
||||
printf '%-22s %18s %18s\n' "Direction" "TX ($cu)" "RX ($cu)"
|
||||
printf '%-22s %18s %18s\n' "unit0.${TL_CE_PORT}" "${CETX[0]}" "${CERX[0]}"
|
||||
printf '%-22s %18s %18s\n' "unit1.${TL_CE_PORT}" "${CETX[1]}" "${CERX[1]}"
|
||||
|
||||
local d1 d2 v1 v2
|
||||
d1=$(awk -v a="${CETX[0]}" -v b="${CERX[1]}" 'BEGIN{printf "%.0f", a-b}')
|
||||
d2=$(awk -v a="${CETX[1]}" -v b="${CERX[0]}" 'BEGIN{printf "%.0f", a-b}')
|
||||
v1=$(awk -v d="$d1" -v t="$TL_TOLERANCE" 'BEGIN{print (d<0?-d:d)<=t ? "PASS" : "FAIL"}')
|
||||
v2=$(awk -v d="$d2" -v t="$TL_TOLERANCE" 'BEGIN{print (d<0?-d:d)<=t ? "PASS" : "FAIL"}')
|
||||
echo ""
|
||||
printf 'unit0.TX -> unit1.RX delta %+d %b\n' "$d1" "$([ "$v1" = PASS ] && echo "${g}PASS${n}" || echo "${r}FAIL${n}")"
|
||||
printf 'unit1.TX -> unit0.RX delta %+d %b\n' "$d2" "$([ "$v2" = PASS ] && echo "${g}PASS${n}" || echo "${r}FAIL${n}")"
|
||||
if [ "$v1" = PASS ] && [ "$v2" = PASS ]; then
|
||||
printf '%-22s %b\n' "${TL_CE_PORT} RESULT" "${g}PASS${n}"
|
||||
else
|
||||
printf '%-22s %b\n' "${TL_CE_PORT} RESULT" "${r}FAIL${n}"
|
||||
worst=2
|
||||
fi
|
||||
echo ""
|
||||
return "$worst"
|
||||
}
|
||||
|
||||
# traffic_linespeed_report -- 'show c' per unit, keep the raw log, render the table
|
||||
traffic_linespeed_report() {
|
||||
local unit log rc worst=0 stamp
|
||||
# -f <log>: offline mode, no DUT access, no unit loop
|
||||
if [ -n "$TL_REPORT_FILE" ]; then
|
||||
[ -r "$TL_REPORT_FILE" ] || { _tl_err "cannot read log '$TL_REPORT_FILE'"; return 1; }
|
||||
_tl_info "report from log: $TL_REPORT_FILE (tolerance $TL_TOLERANCE)"
|
||||
# note on stderr so the table on stdout stays pipe/diff clean
|
||||
_tl_info "report from log: $TL_REPORT_FILE (tolerance $TL_TOLERANCE)" >&2
|
||||
_tl_pair_report "$TL_REPORT_FILE"; return $?
|
||||
fi
|
||||
|
||||
_tl_units_check || return 1
|
||||
if [ "$TL_DRY_RUN" = "1" ]; then
|
||||
for unit in $TL_UNITS; do _tl_bcm "$unit" "show c" >/dev/null; done
|
||||
for unit in $TL_UNITS; do _tl_bcm "$unit" "show c"; done
|
||||
return 0
|
||||
fi
|
||||
|
||||
stamp=$(date +%Y%m%d_%H%M%S 2>/dev/null || echo now)
|
||||
local side
|
||||
for unit in $TL_UNITS; do
|
||||
log="$TL_LOG_DIR/showc_unit${unit}_${stamp}.log"
|
||||
side="$TL_LOG_DIR/tlside_unit${unit}_${stamp}"
|
||||
: > "$side"
|
||||
if ! _tl_bcm "$unit" "show c" > "$log" 2>&1; then
|
||||
_tl_err "unit $unit: show c failed (see $log)"; return 1
|
||||
fi
|
||||
[ "$TL_REPORT_RAW" = "1" ] && { echo "----- unit $unit : raw show c -----"; cat "$log"; }
|
||||
echo "===== unit $unit : loopback pair counter report (raw: $log) ====="
|
||||
_tl_pair_report "$log"; rc=$?
|
||||
_tl_pair_report "$log" "$side"; rc=$?
|
||||
[ "$rc" -gt "$worst" ] && worst=$rc
|
||||
case "$rc" in
|
||||
0) _tl_ok "unit $unit: all pairs PASS" ;;
|
||||
@@ -598,6 +949,12 @@ traffic_linespeed_report() {
|
||||
*) _tl_err "unit $unit: report parse error" ;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Summary last, after every unit's table -- this is where the cross-unit
|
||||
# ce0 verdict can finally be decided.
|
||||
_tl_ce_summary "$stamp"; rc=$?
|
||||
[ "$rc" -gt "$worst" ] && worst=$rc
|
||||
rm -f "$TL_LOG_DIR"/tlside_unit*_"${stamp}"
|
||||
return "$worst"
|
||||
}
|
||||
|
||||
@@ -617,27 +974,33 @@ traffic_linespeed_run() {
|
||||
blanton_traffic_linespeed_help() {
|
||||
echo -e "\033[1mblanton_traffic_linespeed.sh - SWB loopback line-speed traffic (bcmcmd)\033[0m"
|
||||
echo ""
|
||||
echo -e " Units: \033[36m$TL_UNITS\033[0m tx: \033[36m$TL_TX_COUNT pkt x ${TL_TX_LENGTH}B\033[0m"
|
||||
echo -e " Units: \033[36m$TL_UNITS\033[0m tx: \033[36m$TL_TX_COUNT pkt x ${TL_TX_LENGTH}B\033[0m PatternRandom: \033[36m${TL_TX_RANDOM:-(不加)}\033[0m"
|
||||
echo -e " VLANs: 30..137 ($(_tl_pair_count) loopback pairs, cdN <-> cdN+32)"
|
||||
[ "$TL_CE_ENABLE" = "1" ] && \
|
||||
echo -e " 100G : VLAN \033[36m$TL_CE_VLAN\033[0m port \033[36m$TL_CE_PORT\033[0m mode=\033[36m$TL_CE_MODE\033[0m (cross = unit0.$TL_CE_PORT <-> unit1.$TL_CE_PORT cabled)"
|
||||
echo ""
|
||||
echo -e "\033[1mSubcommands\033[0m"
|
||||
echo -e " \033[33minit\033[0m step 1 vlan remove 1 pbm=cd, vlan create/add each pair"
|
||||
echo -e " \033[33mclear\033[0m step 2 clear c"
|
||||
echo -e " \033[33mshow\033[0m step 3/6 show c (run before and after traffic)"
|
||||
echo -e " \033[33mstart\033[0m step 4 tx <count> length=<len> VLantag=<vid> per VLAN"
|
||||
echo -e " \033[33mstart\033[0m step 4 tx <count> length=<len> VLantag=<vid> [PatternRandom=<yes|no>] per VLAN"
|
||||
echo -e " \033[33mstop\033[0m step 5 vlan remove <vid> pbm=<pair> [--destroy also destroys]"
|
||||
[ "$TL_CE_ENABLE" = "1" ] && [ "$TL_CE_MIRROR" = "1" ] && \
|
||||
echo -e " \033[33m^ also turns the $TL_CE_PORT mirror off -- without it the 100G loop keeps running\033[0m"
|
||||
echo -e " \033[33mps\033[0m ps <portlist> port status (link/speed) of the cabled ports"
|
||||
echo -e " \033[33mreport\033[0m show c -> per-pair TX/RX table + PASS/FAIL cross-check"
|
||||
echo -e " \033[33mreport\033[0m show c -> per-port TX/RX per pair + PASS/FAIL/NA cross-check"
|
||||
echo -e " ${TL_CE_PORT} is the last row (DEFER), judged in the summary at the bottom"
|
||||
echo -e " \033[33mrun\033[0m ps -> init -> clear -> start -> report"
|
||||
echo -e " \033[33mhelp\033[0m"
|
||||
echo ""
|
||||
echo -e "\033[1mOptions\033[0m"
|
||||
echo -e " \033[33m-u|--unit\033[0m <0|1|all> bcmcmd unit(s); 'all' = 0 1 (default: $TL_UNITS)"
|
||||
echo -e " \033[33m-c|--count\033[0m <n> tx packet count (default $TL_TX_COUNT)"
|
||||
echo -e " \033[33m-l|--length\033[0m <n> tx packet length (default $TL_TX_LENGTH)"
|
||||
echo -e " \033[33m-c|--count|-tx\033[0m <n> tx packet count (default $TL_TX_COUNT)"
|
||||
echo -e " \033[33m-l|--length|-length\033[0m <n> tx packet length (default $TL_TX_LENGTH)"
|
||||
echo -e " \033[33m-r|--random\033[0m <yes|no> tx PatternRandom (default $TL_TX_RANDOM; \"\" 完全不加)"
|
||||
echo -e " \033[33m-p|--ports\033[0m <list> ps port list, or 'all' for every port"
|
||||
echo -e " \033[33m-T|--tolerance\033[0m <n> report: allowed |delta| pkts (default $TL_TOLERANCE; -T 1 = snapshot skew)"
|
||||
echo -e " \033[33m-a|--all\033[0m report: also list pairs with no counters"
|
||||
echo -e " \033[33m-a|--all\033[0m report: kept for compatibility (all pairs are listed)"
|
||||
echo -e " \033[33m-g|--grouped\033[0m report: comma-group values"
|
||||
echo -e " \033[33m-P|--with-port\033[0m report: render cd1(2) instead of cd1"
|
||||
echo -e " \033[33m-q|--quiet\033[0m report: no trailing summary"
|
||||
@@ -658,7 +1021,9 @@ blanton_traffic_linespeed_help() {
|
||||
echo -e " blanton_traffic_linespeed report -u 1 -q | grep -v PASS"
|
||||
echo -e " blanton_traffic_linespeed report -f /tmp/showc_unit1_*.log -a"
|
||||
echo -e " blanton_traffic_linespeed show -u 1 | grep -iE 'error|discard|drop'"
|
||||
echo -e " blanton_traffic_linespeed start -c 1000 -l 9216 -d"
|
||||
echo -e " blanton_traffic_linespeed start -u 0 -tx 200 -length 324"
|
||||
echo -e " blanton_traffic_linespeed start -r no # 固定樣式,不隨機"
|
||||
echo -e " blanton_traffic_linespeed start -tx 100000 -length 9216 -d"
|
||||
echo -e " blanton_traffic_linespeed stop --destroy"
|
||||
echo ""
|
||||
echo -e " report exit code: 0 = all pairs PASS, 2 = any FAIL/NA, 1 = parse error"
|
||||
@@ -679,8 +1044,9 @@ blanton_traffic_linespeed() {
|
||||
*) TL_UNITS="$2" ;;
|
||||
esac
|
||||
shift 2 ;;
|
||||
-c|--count) TL_TX_COUNT="$2"; shift 2 ;;
|
||||
-l|--length) TL_TX_LENGTH="$2"; shift 2 ;;
|
||||
-c|--count|-tx|--tx) TL_TX_COUNT="$2"; shift 2 ;;
|
||||
-l|-length|--length|--len) TL_TX_LENGTH="$2"; shift 2 ;;
|
||||
-r|--random|-PatternRandom|--pattern-random) TL_TX_RANDOM="$2"; shift 2 ;;
|
||||
-p|--ports) TL_PS_PORTS="$2"; shift 2 ;;
|
||||
-T|--tolerance) TL_TOLERANCE="$2"; shift 2 ;;
|
||||
-f|--file) TL_REPORT_FILE="$2"; shift 2 ;;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,344 @@
|
||||
#!/bin/bash
|
||||
###############################################################################
|
||||
# bmc_monitor.sh
|
||||
#
|
||||
# Version : V1.1.0
|
||||
# Author : ETWen
|
||||
# Date : 20260820
|
||||
#
|
||||
# Purpose : Periodically execute a list of commands on the BMC through
|
||||
# `bmc-manager run "<cmd>"` from the SONiC host side, and append all
|
||||
# output to a rotating log file. Designed to run detached in the
|
||||
# background so no interactive SSH session to the BMC is required.
|
||||
#
|
||||
# Notes : - Everything runs on the HOST. Nothing is deployed to the BMC, so
|
||||
# the BMC busybox toolchain (no base64 / no setsid ...) is a
|
||||
# non-issue.
|
||||
# - `bmc-manager run` prints the remote command output on stdout and
|
||||
# its own banner on stderr; the two streams are captured separately
|
||||
# so the log stays clean.
|
||||
#
|
||||
# Version History
|
||||
# V1.0.0 20260820 Initial Version
|
||||
# V1.1.0 20260820 `start` clears the previous log by default
|
||||
# (START_LOG_MODE: new / archive / append)
|
||||
###############################################################################
|
||||
|
||||
set -u
|
||||
|
||||
###############################################################################
|
||||
# User Configurable Section -- normally this is the only part you need to edit
|
||||
###############################################################################
|
||||
|
||||
# Commands executed on the BMC, one per line, in this order.
|
||||
# Add a line to add a command; comment it out to disable it.
|
||||
COMMANDS=(
|
||||
"free -m"
|
||||
"i2ctransfer -f -y 1 w6@0x41 0x00 0xC0 0x55 0xAA 0x55 0xAA"
|
||||
"i2ctransfer -f -y 1 w2@0x41 0x00 0xC0 r4"
|
||||
"i2ctransfer -f -y 1 w6@0x41 0x00 0xC0 0xAA 0x55 0xAA 0x55"
|
||||
"i2ctransfer -f -y 1 w2@0x41 0x00 0xC0 r4"
|
||||
#"uptime"
|
||||
#"cat /proc/loadavg"
|
||||
#"cat /proc/meminfo"
|
||||
#"df -h /tmp"
|
||||
#"dmesg | tail -n 30"
|
||||
)
|
||||
|
||||
# Seconds to wait after a full round (all COMMANDS executed) before the next one
|
||||
INTERVAL_SEC=10
|
||||
|
||||
# Seconds to wait between two commands inside the same round (0 = no wait)
|
||||
INTER_CMD_DELAY_SEC=0
|
||||
|
||||
# Per-command timeout in seconds; prevents a hung bmc-manager from freezing the
|
||||
# whole loop. Set to 0 to disable.
|
||||
CMD_TIMEOUT_SEC=30
|
||||
|
||||
# Stop after this many rounds. 0 = run until stopped manually.
|
||||
MAX_ROUNDS=0
|
||||
|
||||
# Command runner. Final invocation is:
|
||||
# "$RUNNER_BIN" "${RUNNER_ARGS[@]}" "<command string>"
|
||||
# BMC side : RUNNER_BIN="bmc-manager" ; RUNNER_ARGS=(run)
|
||||
# BMC by IP : RUNNER_BIN="bmc-manager" ; RUNNER_ARGS=(--ip 192.168.200.200 run)
|
||||
# Host side : RUNNER_BIN="bash" ; RUNNER_ARGS=(-c)
|
||||
RUNNER_BIN="bmc-manager"
|
||||
RUNNER_ARGS=(run)
|
||||
|
||||
# stderr handling of the runner (bmc-manager banner lives here)
|
||||
# 0 = log stderr only when the command fails (recommended, keeps log clean)
|
||||
# 1 = always log stderr
|
||||
LOG_STDERR=0
|
||||
|
||||
# Logging
|
||||
LOG_DIR="" # empty = <script directory>/log
|
||||
LOG_NAME="bmc_poll.log"
|
||||
MAX_LOG_SIZE_MB=100 # rotate above this size; 0 = never rotate
|
||||
MAX_LOG_KEEP=5 # keep .1 .. .N
|
||||
|
||||
# What `start` does with the log left behind by the previous run:
|
||||
# new = begin with an empty log; previous content and rotated copies are
|
||||
# discarded (default -- one run, one log)
|
||||
# archive = rename the previous log to <log>.YYYYmmdd-HHMMSS, then begin empty
|
||||
# append = keep appending to the existing log
|
||||
START_LOG_MODE="new"
|
||||
|
||||
###############################################################################
|
||||
# Internal
|
||||
###############################################################################
|
||||
SCRIPT_NAME="$(basename -- "${BASH_SOURCE[0]}")"
|
||||
SCRIPT_PATH="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/${SCRIPT_NAME}"
|
||||
[ -n "${LOG_DIR}" ] || LOG_DIR="$(dirname -- "${SCRIPT_PATH}")/log"
|
||||
LOG_FILE="${LOG_DIR}/${LOG_NAME}"
|
||||
PID_FILE="${LOG_DIR}/${LOG_NAME%.log}.pid"
|
||||
|
||||
LOG_TO_FILE=0
|
||||
STOP=0
|
||||
SLEEP_PID=""
|
||||
|
||||
ts() { date '+%Y-%m-%d %H:%M:%S'; }
|
||||
die() { printf '[ERROR] %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
on_signal() {
|
||||
STOP=1
|
||||
[ -n "${SLEEP_PID}" ] && kill "${SLEEP_PID}" 2>/dev/null
|
||||
}
|
||||
|
||||
# sleep that can be aborted immediately by SIGTERM/SIGINT
|
||||
interruptible_sleep() {
|
||||
local sec="$1"
|
||||
[ "${sec}" -gt 0 ] 2>/dev/null || return 0
|
||||
sleep "${sec}" &
|
||||
SLEEP_PID=$!
|
||||
wait "${SLEEP_PID}" 2>/dev/null
|
||||
SLEEP_PID=""
|
||||
}
|
||||
|
||||
# echo the pid and return 0 when a live instance is found
|
||||
is_running() {
|
||||
local pid
|
||||
[ -f "${PID_FILE}" ] || return 1
|
||||
pid="$(cat "${PID_FILE}" 2>/dev/null)"
|
||||
[[ "${pid}" =~ ^[0-9]+$ ]] || return 1
|
||||
kill -0 "${pid}" 2>/dev/null || return 1
|
||||
grep -qa "${SCRIPT_NAME}" "/proc/${pid}/cmdline" 2>/dev/null || return 1
|
||||
printf '%s' "${pid}"
|
||||
return 0
|
||||
}
|
||||
|
||||
rotate_log_if_needed() {
|
||||
local max_bytes size i
|
||||
[ "${LOG_TO_FILE}" -eq 1 ] || return 0
|
||||
[ "${MAX_LOG_SIZE_MB}" -gt 0 ] || return 0
|
||||
[ -f "${LOG_FILE}" ] || return 0
|
||||
|
||||
max_bytes=$(( MAX_LOG_SIZE_MB * 1024 * 1024 ))
|
||||
size="$(stat -c %s "${LOG_FILE}" 2>/dev/null || echo 0)"
|
||||
[ "${size}" -ge "${max_bytes}" ] || return 0
|
||||
|
||||
for (( i = MAX_LOG_KEEP - 1; i >= 1; i-- )); do
|
||||
[ -f "${LOG_FILE}.${i}" ] && mv -f "${LOG_FILE}.${i}" "${LOG_FILE}.$(( i + 1 ))"
|
||||
done
|
||||
mv -f "${LOG_FILE}" "${LOG_FILE}.1"
|
||||
exec >>"${LOG_FILE}" 2>&1 # re-bind stdout/stderr to the new file
|
||||
printf '[%s] INFO : log rotated at %s MB\n' "$(ts)" "${MAX_LOG_SIZE_MB}"
|
||||
}
|
||||
|
||||
# Remove the rotated copies (.1 .. .N) only. Timestamped archives are kept.
|
||||
remove_rotated_logs() {
|
||||
local i
|
||||
for (( i = 1; i <= MAX_LOG_KEEP + 1; i++ )); do
|
||||
rm -f "${LOG_FILE}.${i}"
|
||||
done
|
||||
}
|
||||
|
||||
# Apply START_LOG_MODE just before a background run is launched.
|
||||
prepare_log_on_start() {
|
||||
local stamp
|
||||
case "${START_LOG_MODE}" in
|
||||
append)
|
||||
return 0
|
||||
;;
|
||||
archive)
|
||||
if [ -s "${LOG_FILE}" ]; then
|
||||
stamp="$(date '+%Y%m%d-%H%M%S')"
|
||||
mv -f "${LOG_FILE}" "${LOG_FILE}.${stamp}" \
|
||||
|| die "cannot archive ${LOG_FILE}"
|
||||
printf 'previous log archived: %s.%s\n' "${LOG_FILE}" "${stamp}"
|
||||
fi
|
||||
remove_rotated_logs
|
||||
;;
|
||||
new)
|
||||
# Truncate rather than unlink: the inode is preserved, so a `tail -f`
|
||||
# that is already attached keeps following the new run.
|
||||
if [ -f "${LOG_FILE}" ]; then
|
||||
: > "${LOG_FILE}" || die "cannot truncate ${LOG_FILE}"
|
||||
fi
|
||||
remove_rotated_logs
|
||||
;;
|
||||
*)
|
||||
die "invalid START_LOG_MODE: ${START_LOG_MODE}"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
run_one_command() {
|
||||
local cmd="$1"
|
||||
local out err rc t0 elapsed err_file
|
||||
|
||||
err_file="$(mktemp)"
|
||||
t0=${SECONDS}
|
||||
if [ "${CMD_TIMEOUT_SEC}" -gt 0 ]; then
|
||||
out="$(timeout "${CMD_TIMEOUT_SEC}" \
|
||||
"${RUNNER_BIN}" "${RUNNER_ARGS[@]}" "${cmd}" 2>"${err_file}")"
|
||||
else
|
||||
out="$("${RUNNER_BIN}" "${RUNNER_ARGS[@]}" "${cmd}" 2>"${err_file}")"
|
||||
fi
|
||||
rc=$?
|
||||
elapsed=$(( SECONDS - t0 ))
|
||||
err="$(cat "${err_file}" 2>/dev/null)"
|
||||
rm -f "${err_file}"
|
||||
|
||||
printf '===== [%s] CMD: %s | rc=%d | %ds =====\n' "$(ts)" "${cmd}" "${rc}" "${elapsed}"
|
||||
printf '%s\n' "${out}"
|
||||
if [ "${rc}" -eq 124 ]; then
|
||||
printf '[%s] WARN : timeout after %ds\n' "$(ts)" "${CMD_TIMEOUT_SEC}"
|
||||
fi
|
||||
if [ -n "${err}" ] && { [ "${LOG_STDERR}" -eq 1 ] || [ "${rc}" -ne 0 ]; }; then
|
||||
printf -- '--- stderr ---\n%s\n' "${err}"
|
||||
fi
|
||||
printf '\n'
|
||||
}
|
||||
|
||||
main_loop() {
|
||||
local round=0 cmd
|
||||
|
||||
[ "${#COMMANDS[@]}" -gt 0 ] || die "COMMANDS is empty"
|
||||
command -v "${RUNNER_BIN}" >/dev/null 2>&1 || die "runner not found: ${RUNNER_BIN}"
|
||||
|
||||
trap on_signal INT TERM
|
||||
|
||||
printf '#############################################################\n'
|
||||
printf '[%s] START: pid=%d interval=%ds timeout=%ds cmds=%d\n' \
|
||||
"$(ts)" "$$" "${INTERVAL_SEC}" "${CMD_TIMEOUT_SEC}" "${#COMMANDS[@]}"
|
||||
printf '#############################################################\n'
|
||||
|
||||
while [ "${STOP}" -eq 0 ]; do
|
||||
round=$(( round + 1 ))
|
||||
printf -- '---------- ROUND %d @ %s ----------\n' "${round}" "$(ts)"
|
||||
|
||||
for cmd in "${COMMANDS[@]}"; do
|
||||
[ "${STOP}" -eq 0 ] || break
|
||||
run_one_command "${cmd}"
|
||||
[ "${INTER_CMD_DELAY_SEC}" -gt 0 ] && interruptible_sleep "${INTER_CMD_DELAY_SEC}"
|
||||
done
|
||||
|
||||
rotate_log_if_needed
|
||||
|
||||
if [ "${MAX_ROUNDS}" -gt 0 ] && [ "${round}" -ge "${MAX_ROUNDS}" ]; then
|
||||
break
|
||||
fi
|
||||
# Fixed gap between rounds. For a fixed cadence instead, replace with:
|
||||
# interruptible_sleep $(( INTERVAL_SEC - round_elapsed ))
|
||||
[ "${STOP}" -eq 0 ] && interruptible_sleep "${INTERVAL_SEC}"
|
||||
done
|
||||
|
||||
printf '[%s] STOP : pid=%d after %d round(s)\n' "$(ts)" "$$" "${round}"
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Sub-commands
|
||||
###############################################################################
|
||||
do_start() {
|
||||
local pid
|
||||
pid="$(is_running)" && die "already running (pid=${pid})"
|
||||
mkdir -p "${LOG_DIR}" || die "cannot create ${LOG_DIR}"
|
||||
prepare_log_on_start
|
||||
|
||||
if command -v setsid >/dev/null 2>&1; then
|
||||
setsid "${SCRIPT_PATH}" __daemon >/dev/null 2>&1 &
|
||||
else
|
||||
nohup "${SCRIPT_PATH}" __daemon >/dev/null 2>&1 &
|
||||
disown 2>/dev/null
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
pid="$(is_running)" || die "start failed, check ${LOG_FILE}"
|
||||
printf 'started (pid=%s)\nlog: %s\n' "${pid}" "${LOG_FILE}"
|
||||
}
|
||||
|
||||
do_daemon() {
|
||||
mkdir -p "${LOG_DIR}" || die "cannot create ${LOG_DIR}"
|
||||
LOG_TO_FILE=1
|
||||
exec >>"${LOG_FILE}" 2>&1
|
||||
printf '%d\n' "$$" > "${PID_FILE}"
|
||||
trap 'rm -f "${PID_FILE}"' EXIT
|
||||
main_loop
|
||||
}
|
||||
|
||||
do_stop() {
|
||||
local pid i
|
||||
pid="$(is_running)" || { printf 'not running\n'; rm -f "${PID_FILE}"; return 0; }
|
||||
|
||||
kill -TERM -"${pid}" 2>/dev/null || kill -TERM "${pid}" 2>/dev/null
|
||||
for (( i = 0; i < 20; i++ )); do
|
||||
kill -0 "${pid}" 2>/dev/null || break
|
||||
sleep 0.5
|
||||
done
|
||||
if kill -0 "${pid}" 2>/dev/null; then
|
||||
printf 'SIGTERM ignored, sending SIGKILL\n'
|
||||
kill -KILL -"${pid}" 2>/dev/null || kill -KILL "${pid}" 2>/dev/null
|
||||
fi
|
||||
rm -f "${PID_FILE}"
|
||||
printf 'stopped (pid=%s)\n' "${pid}"
|
||||
}
|
||||
|
||||
do_status() {
|
||||
local pid
|
||||
if pid="$(is_running)"; then
|
||||
printf 'status : running (pid=%s)\n' "${pid}"
|
||||
else
|
||||
printf 'status : stopped\n'
|
||||
fi
|
||||
printf 'log : %s\n' "${LOG_FILE}"
|
||||
[ -f "${LOG_FILE}" ] && printf 'size : %s\n' "$(du -h "${LOG_FILE}" | cut -f1)"
|
||||
printf 'cmds : %d, interval=%ds\n' "${#COMMANDS[@]}" "${INTERVAL_SEC}"
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: ${SCRIPT_NAME} {start|stop|status|fg|tail|clear}
|
||||
|
||||
start Run detached in the background; the previous log is discarded first
|
||||
(see START_LOG_MODE)
|
||||
stop Stop the background instance
|
||||
status Show pid / log path / log size
|
||||
fg Run in the foreground, output to the terminal (for a quick check)
|
||||
tail tail -f the log file
|
||||
clear Remove the log file and all rotated copies (must be stopped first)
|
||||
|
||||
Log file : ${LOG_FILE}
|
||||
|
||||
To add a command, edit the COMMANDS array at the top of this script.
|
||||
EOF
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Entry point
|
||||
###############################################################################
|
||||
case "${1:-}" in
|
||||
start) do_start ;;
|
||||
stop) do_stop ;;
|
||||
status) do_status ;;
|
||||
fg) LOG_TO_FILE=0; main_loop ;;
|
||||
tail) tail -n 50 -f "${LOG_FILE}" ;;
|
||||
clear)
|
||||
is_running >/dev/null && die "still running, stop it first"
|
||||
rm -f "${LOG_FILE}" "${LOG_FILE}".[0-9]*
|
||||
printf 'log cleared\n'
|
||||
;;
|
||||
__daemon) do_daemon ;;
|
||||
-h|--help|"") usage ;;
|
||||
*) printf '[ERROR] unknown sub-command: %s\n\n' "$1" >&2; usage; exit 1 ;;
|
||||
esac
|
||||
@@ -0,0 +1,340 @@
|
||||
#!/bin/bash
|
||||
###############################################################################
|
||||
# bmc_monitor_ddr.sh
|
||||
#
|
||||
# Version : V1.1.0
|
||||
# Author : ETWen
|
||||
# Date : 20260820
|
||||
#
|
||||
# Purpose : Periodically execute a list of commands on the BMC through
|
||||
# `bmc-manager run "<cmd>"` from the SONiC host side, and append all
|
||||
# output to a rotating log file. Designed to run detached in the
|
||||
# background so no interactive SSH session to the BMC is required.
|
||||
#
|
||||
# Notes : - Everything runs on the HOST. Nothing is deployed to the BMC, so
|
||||
# the BMC busybox toolchain (no base64 / no setsid ...) is a
|
||||
# non-issue.
|
||||
# - `bmc-manager run` prints the remote command output on stdout and
|
||||
# its own banner on stderr; the two streams are captured separately
|
||||
# so the log stays clean.
|
||||
#
|
||||
# Version History
|
||||
# V1.0.0 20260820 Initial Version
|
||||
# V1.1.0 20260820 `start` clears the previous log by default
|
||||
# (START_LOG_MODE: new / archive / append)
|
||||
###############################################################################
|
||||
|
||||
set -u
|
||||
|
||||
###############################################################################
|
||||
# User Configurable Section -- normally this is the only part you need to edit
|
||||
###############################################################################
|
||||
|
||||
# Commands executed on the BMC, one per line, in this order.
|
||||
# Add a line to add a command; comment it out to disable it.
|
||||
COMMANDS=(
|
||||
"memtester 500M 1"
|
||||
#"uptime"
|
||||
#"cat /proc/loadavg"
|
||||
#"cat /proc/meminfo"
|
||||
#"df -h /tmp"
|
||||
#"dmesg | tail -n 30"
|
||||
)
|
||||
|
||||
# Seconds to wait after a full round (all COMMANDS executed) before the next one
|
||||
INTERVAL_SEC=5
|
||||
|
||||
# Seconds to wait between two commands inside the same round (0 = no wait)
|
||||
INTER_CMD_DELAY_SEC=0
|
||||
|
||||
# Per-command timeout in seconds; prevents a hung bmc-manager from freezing the
|
||||
# whole loop. Set to 0 to disable.
|
||||
CMD_TIMEOUT_SEC=3600
|
||||
|
||||
# Stop after this many rounds. 0 = run until stopped manually.
|
||||
MAX_ROUNDS=0
|
||||
|
||||
# Command runner. Final invocation is:
|
||||
# "$RUNNER_BIN" "${RUNNER_ARGS[@]}" "<command string>"
|
||||
# BMC side : RUNNER_BIN="bmc-manager" ; RUNNER_ARGS=(run)
|
||||
# BMC by IP : RUNNER_BIN="bmc-manager" ; RUNNER_ARGS=(--ip 192.168.200.200 run)
|
||||
# Host side : RUNNER_BIN="bash" ; RUNNER_ARGS=(-c)
|
||||
RUNNER_BIN="bmc-manager"
|
||||
RUNNER_ARGS=(run)
|
||||
|
||||
# stderr handling of the runner (bmc-manager banner lives here)
|
||||
# 0 = log stderr only when the command fails (recommended, keeps log clean)
|
||||
# 1 = always log stderr
|
||||
LOG_STDERR=0
|
||||
|
||||
# Logging
|
||||
LOG_DIR="" # empty = <script directory>/log
|
||||
LOG_NAME="bmc_ddr.log"
|
||||
MAX_LOG_SIZE_MB=100 # rotate above this size; 0 = never rotate
|
||||
MAX_LOG_KEEP=5 # keep .1 .. .N
|
||||
|
||||
# What `start` does with the log left behind by the previous run:
|
||||
# new = begin with an empty log; previous content and rotated copies are
|
||||
# discarded (default -- one run, one log)
|
||||
# archive = rename the previous log to <log>.YYYYmmdd-HHMMSS, then begin empty
|
||||
# append = keep appending to the existing log
|
||||
START_LOG_MODE="new"
|
||||
|
||||
###############################################################################
|
||||
# Internal
|
||||
###############################################################################
|
||||
SCRIPT_NAME="$(basename -- "${BASH_SOURCE[0]}")"
|
||||
SCRIPT_PATH="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)/${SCRIPT_NAME}"
|
||||
[ -n "${LOG_DIR}" ] || LOG_DIR="$(dirname -- "${SCRIPT_PATH}")/log"
|
||||
LOG_FILE="${LOG_DIR}/${LOG_NAME}"
|
||||
PID_FILE="${LOG_DIR}/${LOG_NAME%.log}.pid"
|
||||
|
||||
LOG_TO_FILE=0
|
||||
STOP=0
|
||||
SLEEP_PID=""
|
||||
|
||||
ts() { date '+%Y-%m-%d %H:%M:%S'; }
|
||||
die() { printf '[ERROR] %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
on_signal() {
|
||||
STOP=1
|
||||
[ -n "${SLEEP_PID}" ] && kill "${SLEEP_PID}" 2>/dev/null
|
||||
}
|
||||
|
||||
# sleep that can be aborted immediately by SIGTERM/SIGINT
|
||||
interruptible_sleep() {
|
||||
local sec="$1"
|
||||
[ "${sec}" -gt 0 ] 2>/dev/null || return 0
|
||||
sleep "${sec}" &
|
||||
SLEEP_PID=$!
|
||||
wait "${SLEEP_PID}" 2>/dev/null
|
||||
SLEEP_PID=""
|
||||
}
|
||||
|
||||
# echo the pid and return 0 when a live instance is found
|
||||
is_running() {
|
||||
local pid
|
||||
[ -f "${PID_FILE}" ] || return 1
|
||||
pid="$(cat "${PID_FILE}" 2>/dev/null)"
|
||||
[[ "${pid}" =~ ^[0-9]+$ ]] || return 1
|
||||
kill -0 "${pid}" 2>/dev/null || return 1
|
||||
grep -qa "${SCRIPT_NAME}" "/proc/${pid}/cmdline" 2>/dev/null || return 1
|
||||
printf '%s' "${pid}"
|
||||
return 0
|
||||
}
|
||||
|
||||
rotate_log_if_needed() {
|
||||
local max_bytes size i
|
||||
[ "${LOG_TO_FILE}" -eq 1 ] || return 0
|
||||
[ "${MAX_LOG_SIZE_MB}" -gt 0 ] || return 0
|
||||
[ -f "${LOG_FILE}" ] || return 0
|
||||
|
||||
max_bytes=$(( MAX_LOG_SIZE_MB * 1024 * 1024 ))
|
||||
size="$(stat -c %s "${LOG_FILE}" 2>/dev/null || echo 0)"
|
||||
[ "${size}" -ge "${max_bytes}" ] || return 0
|
||||
|
||||
for (( i = MAX_LOG_KEEP - 1; i >= 1; i-- )); do
|
||||
[ -f "${LOG_FILE}.${i}" ] && mv -f "${LOG_FILE}.${i}" "${LOG_FILE}.$(( i + 1 ))"
|
||||
done
|
||||
mv -f "${LOG_FILE}" "${LOG_FILE}.1"
|
||||
exec >>"${LOG_FILE}" 2>&1 # re-bind stdout/stderr to the new file
|
||||
printf '[%s] INFO : log rotated at %s MB\n' "$(ts)" "${MAX_LOG_SIZE_MB}"
|
||||
}
|
||||
|
||||
# Remove the rotated copies (.1 .. .N) only. Timestamped archives are kept.
|
||||
remove_rotated_logs() {
|
||||
local i
|
||||
for (( i = 1; i <= MAX_LOG_KEEP + 1; i++ )); do
|
||||
rm -f "${LOG_FILE}.${i}"
|
||||
done
|
||||
}
|
||||
|
||||
# Apply START_LOG_MODE just before a background run is launched.
|
||||
prepare_log_on_start() {
|
||||
local stamp
|
||||
case "${START_LOG_MODE}" in
|
||||
append)
|
||||
return 0
|
||||
;;
|
||||
archive)
|
||||
if [ -s "${LOG_FILE}" ]; then
|
||||
stamp="$(date '+%Y%m%d-%H%M%S')"
|
||||
mv -f "${LOG_FILE}" "${LOG_FILE}.${stamp}" \
|
||||
|| die "cannot archive ${LOG_FILE}"
|
||||
printf 'previous log archived: %s.%s\n' "${LOG_FILE}" "${stamp}"
|
||||
fi
|
||||
remove_rotated_logs
|
||||
;;
|
||||
new)
|
||||
# Truncate rather than unlink: the inode is preserved, so a `tail -f`
|
||||
# that is already attached keeps following the new run.
|
||||
if [ -f "${LOG_FILE}" ]; then
|
||||
: > "${LOG_FILE}" || die "cannot truncate ${LOG_FILE}"
|
||||
fi
|
||||
remove_rotated_logs
|
||||
;;
|
||||
*)
|
||||
die "invalid START_LOG_MODE: ${START_LOG_MODE}"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
run_one_command() {
|
||||
local cmd="$1"
|
||||
local out err rc t0 elapsed err_file
|
||||
|
||||
err_file="$(mktemp)"
|
||||
t0=${SECONDS}
|
||||
if [ "${CMD_TIMEOUT_SEC}" -gt 0 ]; then
|
||||
out="$(timeout "${CMD_TIMEOUT_SEC}" \
|
||||
"${RUNNER_BIN}" "${RUNNER_ARGS[@]}" "${cmd}" 2>"${err_file}")"
|
||||
else
|
||||
out="$("${RUNNER_BIN}" "${RUNNER_ARGS[@]}" "${cmd}" 2>"${err_file}")"
|
||||
fi
|
||||
rc=$?
|
||||
elapsed=$(( SECONDS - t0 ))
|
||||
err="$(cat "${err_file}" 2>/dev/null)"
|
||||
rm -f "${err_file}"
|
||||
|
||||
printf '===== [%s] CMD: %s | rc=%d | %ds =====\n' "$(ts)" "${cmd}" "${rc}" "${elapsed}"
|
||||
printf '%s\n' "${out}"
|
||||
if [ "${rc}" -eq 124 ]; then
|
||||
printf '[%s] WARN : timeout after %ds\n' "$(ts)" "${CMD_TIMEOUT_SEC}"
|
||||
fi
|
||||
if [ -n "${err}" ] && { [ "${LOG_STDERR}" -eq 1 ] || [ "${rc}" -ne 0 ]; }; then
|
||||
printf -- '--- stderr ---\n%s\n' "${err}"
|
||||
fi
|
||||
printf '\n'
|
||||
}
|
||||
|
||||
main_loop() {
|
||||
local round=0 cmd
|
||||
|
||||
[ "${#COMMANDS[@]}" -gt 0 ] || die "COMMANDS is empty"
|
||||
command -v "${RUNNER_BIN}" >/dev/null 2>&1 || die "runner not found: ${RUNNER_BIN}"
|
||||
|
||||
trap on_signal INT TERM
|
||||
|
||||
printf '#############################################################\n'
|
||||
printf '[%s] START: pid=%d interval=%ds timeout=%ds cmds=%d\n' \
|
||||
"$(ts)" "$$" "${INTERVAL_SEC}" "${CMD_TIMEOUT_SEC}" "${#COMMANDS[@]}"
|
||||
printf '#############################################################\n'
|
||||
|
||||
while [ "${STOP}" -eq 0 ]; do
|
||||
round=$(( round + 1 ))
|
||||
printf -- '---------- ROUND %d @ %s ----------\n' "${round}" "$(ts)"
|
||||
|
||||
for cmd in "${COMMANDS[@]}"; do
|
||||
[ "${STOP}" -eq 0 ] || break
|
||||
run_one_command "${cmd}"
|
||||
[ "${INTER_CMD_DELAY_SEC}" -gt 0 ] && interruptible_sleep "${INTER_CMD_DELAY_SEC}"
|
||||
done
|
||||
|
||||
rotate_log_if_needed
|
||||
|
||||
if [ "${MAX_ROUNDS}" -gt 0 ] && [ "${round}" -ge "${MAX_ROUNDS}" ]; then
|
||||
break
|
||||
fi
|
||||
# Fixed gap between rounds. For a fixed cadence instead, replace with:
|
||||
# interruptible_sleep $(( INTERVAL_SEC - round_elapsed ))
|
||||
[ "${STOP}" -eq 0 ] && interruptible_sleep "${INTERVAL_SEC}"
|
||||
done
|
||||
|
||||
printf '[%s] STOP : pid=%d after %d round(s)\n' "$(ts)" "$$" "${round}"
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Sub-commands
|
||||
###############################################################################
|
||||
do_start() {
|
||||
local pid
|
||||
pid="$(is_running)" && die "already running (pid=${pid})"
|
||||
mkdir -p "${LOG_DIR}" || die "cannot create ${LOG_DIR}"
|
||||
prepare_log_on_start
|
||||
|
||||
if command -v setsid >/dev/null 2>&1; then
|
||||
setsid "${SCRIPT_PATH}" __daemon >/dev/null 2>&1 &
|
||||
else
|
||||
nohup "${SCRIPT_PATH}" __daemon >/dev/null 2>&1 &
|
||||
disown 2>/dev/null
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
pid="$(is_running)" || die "start failed, check ${LOG_FILE}"
|
||||
printf 'started (pid=%s)\nlog: %s\n' "${pid}" "${LOG_FILE}"
|
||||
}
|
||||
|
||||
do_daemon() {
|
||||
mkdir -p "${LOG_DIR}" || die "cannot create ${LOG_DIR}"
|
||||
LOG_TO_FILE=1
|
||||
exec >>"${LOG_FILE}" 2>&1
|
||||
printf '%d\n' "$$" > "${PID_FILE}"
|
||||
trap 'rm -f "${PID_FILE}"' EXIT
|
||||
main_loop
|
||||
}
|
||||
|
||||
do_stop() {
|
||||
local pid i
|
||||
pid="$(is_running)" || { printf 'not running\n'; rm -f "${PID_FILE}"; return 0; }
|
||||
|
||||
kill -TERM -"${pid}" 2>/dev/null || kill -TERM "${pid}" 2>/dev/null
|
||||
for (( i = 0; i < 20; i++ )); do
|
||||
kill -0 "${pid}" 2>/dev/null || break
|
||||
sleep 0.5
|
||||
done
|
||||
if kill -0 "${pid}" 2>/dev/null; then
|
||||
printf 'SIGTERM ignored, sending SIGKILL\n'
|
||||
kill -KILL -"${pid}" 2>/dev/null || kill -KILL "${pid}" 2>/dev/null
|
||||
fi
|
||||
rm -f "${PID_FILE}"
|
||||
printf 'stopped (pid=%s)\n' "${pid}"
|
||||
}
|
||||
|
||||
do_status() {
|
||||
local pid
|
||||
if pid="$(is_running)"; then
|
||||
printf 'status : running (pid=%s)\n' "${pid}"
|
||||
else
|
||||
printf 'status : stopped\n'
|
||||
fi
|
||||
printf 'log : %s\n' "${LOG_FILE}"
|
||||
[ -f "${LOG_FILE}" ] && printf 'size : %s\n' "$(du -h "${LOG_FILE}" | cut -f1)"
|
||||
printf 'cmds : %d, interval=%ds\n' "${#COMMANDS[@]}" "${INTERVAL_SEC}"
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: ${SCRIPT_NAME} {start|stop|status|fg|tail|clear}
|
||||
|
||||
start Run detached in the background; the previous log is discarded first
|
||||
(see START_LOG_MODE)
|
||||
stop Stop the background instance
|
||||
status Show pid / log path / log size
|
||||
fg Run in the foreground, output to the terminal (for a quick check)
|
||||
tail tail -f the log file
|
||||
clear Remove the log file and all rotated copies (must be stopped first)
|
||||
|
||||
Log file : ${LOG_FILE}
|
||||
|
||||
To add a command, edit the COMMANDS array at the top of this script.
|
||||
EOF
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Entry point
|
||||
###############################################################################
|
||||
case "${1:-}" in
|
||||
start) do_start ;;
|
||||
stop) do_stop ;;
|
||||
status) do_status ;;
|
||||
fg) LOG_TO_FILE=0; main_loop ;;
|
||||
tail) tail -n 50 -f "${LOG_FILE}" ;;
|
||||
clear)
|
||||
is_running >/dev/null && die "still running, stop it first"
|
||||
rm -f "${LOG_FILE}" "${LOG_FILE}".[0-9]*
|
||||
printf 'log cleared\n'
|
||||
;;
|
||||
__daemon) do_daemon ;;
|
||||
-h|--help|"") usage ;;
|
||||
*) printf '[ERROR] unknown sub-command: %s\n\n' "$1" >&2; usage; exit 1 ;;
|
||||
esac
|
||||
@@ -0,0 +1,403 @@
|
||||
#!/bin/bash
|
||||
###############################################################################
|
||||
# mgmt_ping_monitor.sh
|
||||
#
|
||||
# Version : V3.0.0
|
||||
# Author : ETWen
|
||||
# Date : 20260826
|
||||
#
|
||||
# Purpose : Ping from BOTH management NICs at the same time, continuously, and
|
||||
# keep accumulating until stopped:
|
||||
#
|
||||
# 10G (eth0) -> TARGET_10G
|
||||
# 1G (eth1) -> TARGET_1G
|
||||
#
|
||||
# `stop` renders a report into the log: the last TAIL_LINES entries
|
||||
# per NIC, each one's ping statistics and verdict, then
|
||||
# `ip -s link show` for both interfaces.
|
||||
#
|
||||
# Notes : - Both NICs are configured with iproute2 `replace`, which is
|
||||
# idempotent, and both are left up. On a shared subnet the target's
|
||||
# ARP can be answered by either NIC, so ARP_STRICT keeps each one
|
||||
# to its own address.
|
||||
# - ARP WARM-UP: the first packet after a neighbour entry expires is
|
||||
# spent resolving ARP and is counted as loss. On the bench this
|
||||
# produced three FAILs whose only missing packet was icmp_seq=1,
|
||||
# every time, with zero NIC errors or drops. One discarded ping
|
||||
# before the measured run removes that artefact, which is what lets
|
||||
# MAX_LOSS_PCT stay at 0 and still mean something.
|
||||
# - MANAGEMENT CONNECTIVITY IS IN USE while this runs. Drive it from
|
||||
# the serial console.
|
||||
#
|
||||
# Version History
|
||||
# V1.0.0 20260824 Initial Version (ifconfig, one NIC at a time)
|
||||
# V2.0.0 20260824 iproute2; both NICs stay up; per-NIC target;
|
||||
# ip -s link show + TX/RX delta per leg
|
||||
# V3.0.0 20260826 Both NICs ping SIMULTANEOUSLY and continuously instead
|
||||
# of alternating fixed bursts. Add the ARP warm-up.
|
||||
# `stop` renders last-N per NIC + statistics + both
|
||||
# ip -s link outputs into the log.
|
||||
###############################################################################
|
||||
|
||||
set -u
|
||||
|
||||
###############################################################################
|
||||
# User Configurable Section -- normally this is the only part you need to edit
|
||||
###############################################################################
|
||||
|
||||
# --- 10G management port ---
|
||||
IF_10G="eth0"
|
||||
IP_10G="192.168.1.99"
|
||||
TARGET_10G="192.168.1.30" # host this NIC pings
|
||||
PLEN_10G=24 # prefix length, e.g. 24 = /24
|
||||
GW_10G="" # default gateway; empty = do not touch routing
|
||||
METRIC_10G=100 # lower metric wins for off-subnet traffic
|
||||
|
||||
# --- 1G management port ---
|
||||
IF_1G="eth1"
|
||||
IP_1G="192.168.1.101"
|
||||
TARGET_1G="192.168.1.31"
|
||||
PLEN_1G=24
|
||||
GW_1G=""
|
||||
METRIC_1G=200
|
||||
|
||||
# --- ping ---
|
||||
PING_INTERVAL_SEC=1 # seconds between echo requests (ping -i)
|
||||
MAX_LOSS_PCT=0 # loss above this marks the NIC FAIL
|
||||
TAIL_LINES=20 # how many recent entries per NIC the report shows
|
||||
|
||||
# Extra ping flags. -D timestamps every line, -O prints a marker for a request
|
||||
# that got no reply, so a drop is visible in the tail instead of just missing.
|
||||
# Clear this if the platform's ping does not accept them.
|
||||
PING_EXTRA_OPTS="-D -O"
|
||||
|
||||
# One discarded ping per NIC before the measured run, to resolve ARP. Without
|
||||
# it the first packet of the run is lost to neighbour resolution and looks
|
||||
# exactly like a link fault. 0 disables.
|
||||
ARP_WARMUP=1
|
||||
ARP_WARMUP_TIMEOUT=2 # seconds to wait for the warm-up reply
|
||||
|
||||
# Both NICs stay up. If they share a subnet the target's ARP can be answered by
|
||||
# either one, so a reply may arrive on the NIC that did not send. This applies
|
||||
# arp_ignore=1 / arp_announce=2 to both. RAM only -- reverts on reboot.
|
||||
ARP_STRICT=1
|
||||
|
||||
# Prefix for the ip commands; empty because this already runs as root.
|
||||
SUDO=""
|
||||
|
||||
# Seconds to wait after bringing a link up before pinging.
|
||||
LINK_SETTLE_SEC=5
|
||||
|
||||
# Logging
|
||||
LOG_DIR="" # empty = <script directory>/log
|
||||
LOG_NAME="mgmt_ping.log"
|
||||
|
||||
# What `start` does with the log left behind by the previous run:
|
||||
# new = discard it (default -- one run, one log)
|
||||
# archive = rename it to <log>.YYYYmmdd-HHMMSS first
|
||||
# append = keep it
|
||||
START_LOG_MODE="new"
|
||||
|
||||
###############################################################################
|
||||
# Internal
|
||||
###############################################################################
|
||||
SCRIPT_NAME="$(basename -- "${BASH_SOURCE[0]}")"
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
[ -n "${LOG_DIR}" ] || LOG_DIR="${SCRIPT_DIR}/log"
|
||||
|
||||
LOG_FILE="${LOG_DIR}/${LOG_NAME}"
|
||||
BASE="${LOG_DIR}/${LOG_NAME%.log}"
|
||||
PID_FILE="${BASE}.pid"
|
||||
STATE_FILE="${BASE}.state"
|
||||
RAW_10G="${BASE}_${IF_10G}.raw"
|
||||
RAW_1G="${BASE}_${IF_1G}.raw"
|
||||
|
||||
ts() { date '+%Y-%m-%d %H:%M:%S'; }
|
||||
die() { printf '[ERROR] %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
# "<rx_packets> <tx_packets>" for an interface. ip -s link orders the columns
|
||||
# "bytes packets errors ...", so packets is $2, not $1.
|
||||
if_counters() {
|
||||
${SUDO} ip -s link show "$1" 2>/dev/null | awk '
|
||||
/RX:/ { getline; rx = $2 }
|
||||
/TX:/ { getline; tx = $2 }
|
||||
END { printf "%s %s", (rx == "" ? 0 : rx), (tx == "" ? 0 : tx) }'
|
||||
}
|
||||
|
||||
# Bring the NIC up and (re)apply its address and default route.
|
||||
setup_iface() {
|
||||
local iface="$1" ipaddr="$2" plen="$3" gw="$4" metric="$5"
|
||||
${SUDO} ip link set "${iface}" up 2>&1 || return 1
|
||||
${SUDO} ip address replace "${ipaddr}/${plen}" dev "${iface}" 2>&1 || return 1
|
||||
if [ -n "${gw}" ]; then
|
||||
${SUDO} ip route replace default via "${gw}" dev "${iface}" \
|
||||
metric "${metric}" 2>&1 || return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
apply_arp_strict() {
|
||||
local i
|
||||
[ "${ARP_STRICT}" -eq 1 ] || return 0
|
||||
for i in "${IF_10G}" "${IF_1G}"; do
|
||||
${SUDO} sysctl -qw "net.ipv4.conf.${i}.arp_ignore=1" 2>/dev/null
|
||||
${SUDO} sysctl -qw "net.ipv4.conf.${i}.arp_announce=2" 2>/dev/null
|
||||
done
|
||||
}
|
||||
|
||||
# Resolve the neighbour so the measured run does not spend its first packet on
|
||||
# ARP. Result is deliberately discarded.
|
||||
arp_warmup() {
|
||||
local iface="$1" target="$2"
|
||||
[ "${ARP_WARMUP}" -eq 1 ] || return 0
|
||||
ping -I "${iface}" -c 1 -W "${ARP_WARMUP_TIMEOUT}" "${target}" >/dev/null 2>&1
|
||||
return 0
|
||||
}
|
||||
|
||||
# echo "pid_10g pid_1g" and return 0 when both are alive
|
||||
is_running() {
|
||||
local p0 p1
|
||||
[ -f "${PID_FILE}" ] || return 1
|
||||
p0="$(sed -n '1p' "${PID_FILE}" 2>/dev/null)"
|
||||
p1="$(sed -n '2p' "${PID_FILE}" 2>/dev/null)"
|
||||
[[ "${p0}" =~ ^[0-9]+$ ]] || return 1
|
||||
[[ "${p1}" =~ ^[0-9]+$ ]] || return 1
|
||||
kill -0 "${p0}" 2>/dev/null || kill -0 "${p1}" 2>/dev/null || return 1
|
||||
printf '%s %s' "${p0}" "${p1}"
|
||||
return 0
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Report
|
||||
###############################################################################
|
||||
|
||||
# The recent entries for one NIC: replies and, thanks to -O, the requests that
|
||||
# got none.
|
||||
tail_entries() {
|
||||
grep -aE 'bytes from|no answer|Unreachable|Time to live' "$1" 2>/dev/null \
|
||||
| tail -n "${TAIL_LINES}"
|
||||
}
|
||||
|
||||
# The trailing "--- x ping statistics ---" block.
|
||||
stats_block() {
|
||||
sed -n '/ping statistics ---/,$p' "$1" 2>/dev/null
|
||||
}
|
||||
|
||||
# render_leg <label> <iface> <target> <raw> <rx0> <tx0>
|
||||
render_leg() {
|
||||
local label="$1" iface="$2" target="$3" raw="$4" rx0="$5" tx0="$6"
|
||||
local st tx rx loss avg verdict c1 rx1 tx1 drx dtx
|
||||
|
||||
printf -- '----- %s : %s -> %s : last %s entries -----\n' \
|
||||
"${label}" "${iface}" "${target}" "${TAIL_LINES}"
|
||||
tail_entries "${raw}"
|
||||
printf '\n'
|
||||
st="$(stats_block "${raw}")"
|
||||
printf '%s\n' "${st}"
|
||||
|
||||
tx="$(printf '%s' "${st}" | sed -n 's/^\([0-9]\+\) packets transmitted.*/\1/p' | tail -1)"
|
||||
rx="$(printf '%s' "${st}" | sed -n 's/.*[, ]\([0-9]\+\) received.*/\1/p' | tail -1)"
|
||||
loss="$(printf '%s' "${st}" | sed -n 's/.*[, ]\([0-9]\+\)% packet loss.*/\1/p' | tail -1)"
|
||||
avg="$(printf '%s' "${st}" | sed -n 's|.*= [0-9.]*/\([0-9.]*\)/.*|\1|p' | tail -1)"
|
||||
[ -n "${tx}" ] || tx=0
|
||||
[ -n "${rx}" ] || rx=0
|
||||
[ -n "${loss}" ] || loss=100
|
||||
[ -n "${avg}" ] || avg="-"
|
||||
|
||||
c1="$(if_counters "${iface}")"; rx1="${c1% *}"; tx1="${c1#* }"
|
||||
drx=$(( rx1 - rx0 )); dtx=$(( tx1 - tx0 ))
|
||||
|
||||
if [ "${loss}" -le "${MAX_LOSS_PCT}" ] && [ "${tx}" -gt 0 ]; then
|
||||
verdict="PASS"
|
||||
else
|
||||
verdict="FAIL"
|
||||
fi
|
||||
|
||||
# nic_tx/nic_rx are this interface's own counter delta over the whole run.
|
||||
# A pass with nic_tx near zero means the traffic left on the other NIC.
|
||||
printf '[%s] RESULT %-3s %-6s -> %-15s tx=%s rx=%s loss=%s%% rtt_avg=%sms nic_tx=%s nic_rx=%s %s\n\n' \
|
||||
"$(ts)" "${label}" "${iface}" "${target}" "${tx}" "${rx}" "${loss}" "${avg}" \
|
||||
"${dtx}" "${drx}" "${verdict}"
|
||||
}
|
||||
|
||||
write_report() {
|
||||
local rx0_10g tx0_10g rx0_1g tx0_1g started
|
||||
started="$(sed -n '1p' "${STATE_FILE}" 2>/dev/null)"
|
||||
rx0_10g="$(sed -n '2p' "${STATE_FILE}" 2>/dev/null)"; rx0_10g="${rx0_10g:-0}"
|
||||
tx0_10g="$(sed -n '3p' "${STATE_FILE}" 2>/dev/null)"; tx0_10g="${tx0_10g:-0}"
|
||||
rx0_1g="$(sed -n '4p' "${STATE_FILE}" 2>/dev/null)"; rx0_1g="${rx0_1g:-0}"
|
||||
tx0_1g="$(sed -n '5p' "${STATE_FILE}" 2>/dev/null)"; tx0_1g="${tx0_1g:-0}"
|
||||
|
||||
{
|
||||
printf '#############################################################\n'
|
||||
printf '[%s] mgmt ping report\n' "$(ts)"
|
||||
printf ' started : %s\n' "${started:-unknown}"
|
||||
printf ' stopped : %s\n' "$(ts)"
|
||||
printf ' 10G : %s %s/%s -> %s (metric %s)\n' \
|
||||
"${IF_10G}" "${IP_10G}" "${PLEN_10G}" "${TARGET_10G}" "${METRIC_10G}"
|
||||
printf ' 1G : %s %s/%s -> %s (metric %s)\n' \
|
||||
"${IF_1G}" "${IP_1G}" "${PLEN_1G}" "${TARGET_1G}" "${METRIC_1G}"
|
||||
printf ' ping : -i %s %s, max loss %s%%\n' \
|
||||
"${PING_INTERVAL_SEC}" "${PING_EXTRA_OPTS}" "${MAX_LOSS_PCT}"
|
||||
printf '#############################################################\n\n'
|
||||
|
||||
render_leg "10G" "${IF_10G}" "${TARGET_10G}" "${RAW_10G}" "${rx0_10g}" "${tx0_10g}"
|
||||
render_leg "1G" "${IF_1G}" "${TARGET_1G}" "${RAW_1G}" "${rx0_1g}" "${tx0_1g}"
|
||||
|
||||
printf -- '--- ip -s link show %s ---\n' "${IF_10G}"
|
||||
${SUDO} ip -s link show "${IF_10G}" 2>&1
|
||||
printf '\n'
|
||||
printf -- '--- ip -s link show %s ---\n' "${IF_1G}"
|
||||
${SUDO} ip -s link show "${IF_1G}" 2>&1
|
||||
} >> "${LOG_FILE}"
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Sub-commands
|
||||
###############################################################################
|
||||
prepare_log_on_start() {
|
||||
local stamp
|
||||
case "${START_LOG_MODE}" in
|
||||
append) return 0 ;;
|
||||
archive)
|
||||
if [ -s "${LOG_FILE}" ]; then
|
||||
stamp="$(date '+%Y%m%d-%H%M%S')"
|
||||
mv -f "${LOG_FILE}" "${LOG_FILE}.${stamp}" || die "cannot archive ${LOG_FILE}"
|
||||
printf 'previous log archived: %s.%s\n' "${LOG_FILE}" "${stamp}"
|
||||
fi
|
||||
;;
|
||||
new)
|
||||
# Truncate rather than unlink, so a tail -f already attached keeps
|
||||
# following the new run.
|
||||
[ -f "${LOG_FILE}" ] && { : > "${LOG_FILE}" || die "cannot truncate ${LOG_FILE}"; }
|
||||
;;
|
||||
*) die "invalid START_LOG_MODE: ${START_LOG_MODE}" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
do_start() {
|
||||
local pids p0 p1 c
|
||||
|
||||
pids="$(is_running)" && die "already running (pids=${pids})"
|
||||
|
||||
command -v ip >/dev/null 2>&1 || die "ip (iproute2) not found"
|
||||
command -v ping >/dev/null 2>&1 || die "ping not found"
|
||||
|
||||
mkdir -p "${LOG_DIR}" || die "cannot create ${LOG_DIR}"
|
||||
prepare_log_on_start
|
||||
: > "${RAW_10G}"
|
||||
: > "${RAW_1G}"
|
||||
|
||||
setup_iface "${IF_10G}" "${IP_10G}" "${PLEN_10G}" "${GW_10G}" "${METRIC_10G}" \
|
||||
|| die "cannot configure ${IF_10G}"
|
||||
setup_iface "${IF_1G}" "${IP_1G}" "${PLEN_1G}" "${GW_1G}" "${METRIC_1G}" \
|
||||
|| die "cannot configure ${IF_1G}"
|
||||
apply_arp_strict
|
||||
sleep "${LINK_SETTLE_SEC}"
|
||||
|
||||
# Spend the ARP resolution here, not on the first measured packet.
|
||||
arp_warmup "${IF_10G}" "${TARGET_10G}"
|
||||
arp_warmup "${IF_1G}" "${TARGET_1G}"
|
||||
|
||||
# Counter baseline, taken after the warm-up so its packets are excluded.
|
||||
{ c="$(if_counters "${IF_10G}")"
|
||||
printf '%s\n%s\n%s\n' "$(ts)" "${c% *}" "${c#* }"
|
||||
c="$(if_counters "${IF_1G}")"
|
||||
printf '%s\n%s\n' "${c% *}" "${c#* }"
|
||||
} > "${STATE_FILE}"
|
||||
|
||||
# Both NICs ping at the same time and keep accumulating until stopped.
|
||||
nohup ping -I "${IF_10G}" -i "${PING_INTERVAL_SEC}" ${PING_EXTRA_OPTS} \
|
||||
"${TARGET_10G}" >> "${RAW_10G}" 2>&1 &
|
||||
p0=$!
|
||||
nohup ping -I "${IF_1G}" -i "${PING_INTERVAL_SEC}" ${PING_EXTRA_OPTS} \
|
||||
"${TARGET_1G}" >> "${RAW_1G}" 2>&1 &
|
||||
p1=$!
|
||||
disown "${p0}" 2>/dev/null
|
||||
disown "${p1}" 2>/dev/null
|
||||
printf '%s\n%s\n' "${p0}" "${p1}" > "${PID_FILE}"
|
||||
|
||||
sleep 1
|
||||
kill -0 "${p0}" 2>/dev/null || die "10G ping failed to start, see ${RAW_10G}"
|
||||
kill -0 "${p1}" 2>/dev/null || die "1G ping failed to start, see ${RAW_1G}"
|
||||
printf 'started (10G pid=%s, 1G pid=%s)\nlog: %s\n' "${p0}" "${p1}" "${LOG_FILE}"
|
||||
}
|
||||
|
||||
do_stop() {
|
||||
local pids p0 p1 i
|
||||
|
||||
pids="$(is_running)" || {
|
||||
printf 'not running\n'
|
||||
rm -f "${PID_FILE}"
|
||||
return 0
|
||||
}
|
||||
p0="${pids% *}"; p1="${pids#* }"
|
||||
|
||||
# SIGINT, not SIGTERM: ping prints its statistics block on interrupt, and
|
||||
# that block is what the report parses.
|
||||
kill -INT "${p0}" 2>/dev/null
|
||||
kill -INT "${p1}" 2>/dev/null
|
||||
for (( i = 0; i < 20; i++ )); do
|
||||
kill -0 "${p0}" 2>/dev/null || kill -0 "${p1}" 2>/dev/null || break
|
||||
sleep 0.5
|
||||
done
|
||||
kill -KILL "${p0}" 2>/dev/null
|
||||
kill -KILL "${p1}" 2>/dev/null
|
||||
|
||||
write_report
|
||||
rm -f "${PID_FILE}"
|
||||
printf 'stopped (10G pid=%s, 1G pid=%s)\nreport: %s\n' "${p0}" "${p1}" "${LOG_FILE}"
|
||||
}
|
||||
|
||||
do_status() {
|
||||
local pids
|
||||
if pids="$(is_running)"; then
|
||||
printf 'status : running (10G pid=%s, 1G pid=%s)\n' "${pids% *}" "${pids#* }"
|
||||
else
|
||||
printf 'status : stopped\n'
|
||||
fi
|
||||
printf 'log : %s\n' "${LOG_FILE}"
|
||||
printf '10G : %s %s/%s -> %s\n' "${IF_10G}" "${IP_10G}" "${PLEN_10G}" "${TARGET_10G}"
|
||||
printf '1G : %s %s/%s -> %s\n' "${IF_1G}" "${IP_1G}" "${PLEN_1G}" "${TARGET_1G}"
|
||||
[ -f "${RAW_10G}" ] && printf '10G recv: %s\n' "$(grep -ac 'bytes from' "${RAW_10G}")"
|
||||
[ -f "${RAW_1G}" ] && printf '1G recv: %s\n' "$(grep -ac 'bytes from' "${RAW_1G}")"
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: ${SCRIPT_NAME} {start|stop|status|summary|clear}
|
||||
|
||||
start Configure both NICs, warm up ARP, then ping from BOTH at the same
|
||||
time and keep accumulating. The previous log is discarded first.
|
||||
stop Stop both pings and render the report into the log
|
||||
status Show pids, configured NICs and replies received so far
|
||||
summary Print just the RESULT lines from the log
|
||||
clear Remove the log and the raw captures (must be stopped first)
|
||||
|
||||
Log file : ${LOG_FILE}
|
||||
|
||||
The report holds, per NIC, the last ${TAIL_LINES} entries and the ping
|
||||
statistics, then "ip -s link show" for both interfaces.
|
||||
|
||||
Both NICs are used at once, so management connectivity is in play -- drive
|
||||
this from the serial console. Edit the User Configurable Section at the top
|
||||
to change interfaces, addresses, targets or the ping options.
|
||||
EOF
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Entry point
|
||||
###############################################################################
|
||||
case "${1:-}" in
|
||||
start) do_start ;;
|
||||
stop) do_stop ;;
|
||||
status) do_status ;;
|
||||
summary) grep -a 'RESULT' "${LOG_FILE}" 2>/dev/null || printf 'no results in %s\n' "${LOG_FILE}" ;;
|
||||
clear)
|
||||
is_running >/dev/null && die "still running, stop it first"
|
||||
rm -f "${LOG_FILE}" "${LOG_FILE}".[0-9]* "${RAW_10G}" "${RAW_1G}" "${STATE_FILE}"
|
||||
printf 'log cleared\n'
|
||||
;;
|
||||
-h|--help|"") usage ;;
|
||||
*) printf '[ERROR] unknown sub-command: %s\n\n' "$1" >&2; usage; exit 1 ;;
|
||||
esac
|
||||
@@ -0,0 +1,314 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# nfc_polling.sh -- keep reading the NFC tag in the background, and tally it
|
||||
# =============================================================================
|
||||
# Version History:
|
||||
# V1.0.0 2026-08-28 First version. start/stop/status/tail/report/clear/fg,
|
||||
# wraps blantons_nfc_validate.py. 'report' works while the
|
||||
# poll is still running.
|
||||
# =============================================================================
|
||||
#
|
||||
# Each round runs blantons_nfc_validate.py once and appends a machine-readable
|
||||
# verdict line, so 'report' never has to parse the tool's prose:
|
||||
#
|
||||
# [2026-08-28 15:04:11] NFC poll #000001 START
|
||||
# ... the tool's own output ...
|
||||
# [2026-08-28 15:04:14] NFC poll #000001 RESULT=PASS tag=046F7BD2142290
|
||||
#
|
||||
# The verdict comes from the tool's own [PASS] / [FAIL] summary line. If neither
|
||||
# appears the round is ERROR, not FAIL -- "the tool did not run" and "the tag was
|
||||
# not read" are different problems and get counted separately.
|
||||
#
|
||||
# Usage:
|
||||
# ./nfc_polling.sh start # background, CLEARS the log first
|
||||
# ./nfc_polling.sh status # running? pid, rounds so far, log size
|
||||
# ./nfc_polling.sh tail [n] # last n lines (default 50) -- does NOT follow
|
||||
# ./nfc_polling.sh report # PASS/FAIL tally; safe to run WHILE polling
|
||||
# ./nfc_polling.sh stop
|
||||
# ./nfc_polling.sh clear # delete the log (must be stopped)
|
||||
# ./nfc_polling.sh fg # run in the foreground, Ctrl-C to stop
|
||||
#
|
||||
# Environment overrides:
|
||||
# NFC_INTERVAL_SEC=10 NFC_TIMEOUT_SEC=60 NFC_MAX_ROUNDS=0 (0 = forever)
|
||||
# NFC_ARGS="test --debug" NFC_LOG_DIR=<dir> NFC_BIN=<python3>
|
||||
# =============================================================================
|
||||
|
||||
# --- User Configurable Section ----------------------------------------------
|
||||
NFC_INTERVAL_SEC="${NFC_INTERVAL_SEC:-10}" # gap between rounds
|
||||
NFC_TIMEOUT_SEC="${NFC_TIMEOUT_SEC:-60}" # kill a round that hangs (0 = never)
|
||||
NFC_MAX_ROUNDS="${NFC_MAX_ROUNDS:-0}" # 0 = until 'stop'
|
||||
|
||||
# Called through python3 on purpose: blantons_nfc_validate.py arrives from git
|
||||
# (mode 100644) and a Windows/USB copy does not carry the execute bit either, so
|
||||
# "./blantons_nfc_validate.py" would fail with Permission denied on a fresh DUT.
|
||||
NFC_PY="${NFC_PY:-python3}"
|
||||
NFC_SCRIPT_NAME="${NFC_SCRIPT_NAME:-blantons_nfc_validate.py}"
|
||||
|
||||
# --debug is kept because that is the output that has been seen on the bench.
|
||||
# It costs ~1.5 KB per round (~13 MB/day at a 10s interval), which is fine for a
|
||||
# soak; drop it to "test" if you want a smaller log.
|
||||
NFC_ARGS="${NFC_ARGS:-test --debug}"
|
||||
|
||||
NFC_LOG_DIR="${NFC_LOG_DIR:-}" # empty = <script dir>/log
|
||||
NFC_LOG_NAME="${NFC_LOG_NAME:-nfc_poll.log}"
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
SCRIPT_NAME="$(basename -- "${BASH_SOURCE[0]}")"
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SCRIPT_PATH="${SCRIPT_DIR}/${SCRIPT_NAME}"
|
||||
NFC_SCRIPT="${NFC_SCRIPT:-${SCRIPT_DIR}/${NFC_SCRIPT_NAME}}"
|
||||
[ -n "${NFC_LOG_DIR}" ] || NFC_LOG_DIR="${SCRIPT_DIR}/log"
|
||||
LOG_FILE="${NFC_LOG_DIR}/${NFC_LOG_NAME}"
|
||||
PID_FILE="${NFC_LOG_DIR}/${NFC_LOG_NAME%.log}.pid"
|
||||
|
||||
STOP=0
|
||||
SLEEP_PID=""
|
||||
|
||||
ts() { date '+%Y-%m-%d %H:%M:%S'; }
|
||||
die() { printf '[ERROR] %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
on_signal() {
|
||||
STOP=1
|
||||
[ -n "${SLEEP_PID}" ] && kill "${SLEEP_PID}" 2>/dev/null
|
||||
return 0
|
||||
}
|
||||
|
||||
# sleep that a signal can cut short, so 'stop' does not wait out the interval
|
||||
interruptible_sleep() {
|
||||
local sec="$1"
|
||||
[ "${sec}" -le 0 ] 2>/dev/null && return 0
|
||||
sleep "${sec}" &
|
||||
SLEEP_PID=$!
|
||||
wait "${SLEEP_PID}" 2>/dev/null
|
||||
SLEEP_PID=""
|
||||
return 0
|
||||
}
|
||||
|
||||
is_running() {
|
||||
local pid
|
||||
[ -f "${PID_FILE}" ] || return 1
|
||||
pid="$(cat "${PID_FILE}" 2>/dev/null)"
|
||||
[ -n "${pid}" ] || return 1
|
||||
kill -0 "${pid}" 2>/dev/null || return 1
|
||||
printf '%s' "${pid}"
|
||||
return 0
|
||||
}
|
||||
|
||||
# --- one round ---------------------------------------------------------------
|
||||
# Appends START, the tool output, then a RESULT line. Everything about a round
|
||||
# lands in the log even when the tool dies, so 'report' can still account for it.
|
||||
run_one_round() {
|
||||
local n="$1" out rc verdict tag reason
|
||||
printf '[%s] NFC poll #%06d START\n' "$(ts)" "${n}"
|
||||
|
||||
if [ -n "${NFC_TIMEOUT_SEC}" ] && [ "${NFC_TIMEOUT_SEC}" -gt 0 ] 2>/dev/null \
|
||||
&& command -v timeout >/dev/null 2>&1; then
|
||||
out="$(timeout "${NFC_TIMEOUT_SEC}" "${NFC_PY}" "${NFC_SCRIPT}" ${NFC_ARGS} 2>&1)"; rc=$?
|
||||
else
|
||||
out="$("${NFC_PY}" "${NFC_SCRIPT}" ${NFC_ARGS} 2>&1)"; rc=$?
|
||||
fi
|
||||
printf '%s\n' "${out}"
|
||||
|
||||
# The tool's own summary decides. Exit status is only the fallback, because
|
||||
# a tool that never printed a summary did not measure anything.
|
||||
if printf '%s\n' "${out}" | grep -q '^\[PASS\]'; then
|
||||
verdict="PASS"
|
||||
elif printf '%s\n' "${out}" | grep -q '^\[FAIL\]'; then
|
||||
verdict="FAIL"
|
||||
elif [ "${rc}" -eq 124 ]; then
|
||||
verdict="ERROR"; reason="round exceeded NFC_TIMEOUT_SEC=${NFC_TIMEOUT_SEC}s"
|
||||
else
|
||||
verdict="ERROR"; reason="no [PASS]/[FAIL] summary, exit=${rc}"
|
||||
fi
|
||||
|
||||
tag="$(printf '%s\n' "${out}" | sed -n 's/.*NFCID1=\([0-9A-Fa-f]*\).*/\1/p' | tail -1)"
|
||||
[ -n "${reason}" ] || reason="$(printf '%s\n' "${out}" | grep -m1 '^\[\(PASS\|FAIL\)\]' | cut -c8-)"
|
||||
|
||||
printf '[%s] NFC poll #%06d RESULT=%s tag=%s reason=%s\n' \
|
||||
"$(ts)" "${n}" "${verdict}" "${tag:--}" "${reason:--}"
|
||||
}
|
||||
|
||||
main_loop() {
|
||||
local n=0
|
||||
trap on_signal INT TERM
|
||||
printf '[%s] ===== nfc_polling start : %s %s (interval %ss) =====\n' \
|
||||
"$(ts)" "${NFC_PY}" "${NFC_SCRIPT}" "${NFC_INTERVAL_SEC}"
|
||||
while [ "${STOP}" -eq 0 ]; do
|
||||
n=$(( n + 1 ))
|
||||
run_one_round "${n}"
|
||||
if [ "${NFC_MAX_ROUNDS}" -gt 0 ] 2>/dev/null && [ "${n}" -ge "${NFC_MAX_ROUNDS}" ]; then
|
||||
break
|
||||
fi
|
||||
[ "${STOP}" -eq 0 ] && interruptible_sleep "${NFC_INTERVAL_SEC}"
|
||||
done
|
||||
printf '[%s] ===== nfc_polling stop : %d round(s) =====\n' "$(ts)" "${n}"
|
||||
}
|
||||
|
||||
# --- sub-commands ------------------------------------------------------------
|
||||
do_start() {
|
||||
local pid
|
||||
pid="$(is_running)" && die "already running (pid=${pid})"
|
||||
[ -r "${NFC_SCRIPT}" ] || die "cannot read ${NFC_SCRIPT}"
|
||||
command -v "${NFC_PY}" >/dev/null 2>&1 || die "${NFC_PY} not found"
|
||||
mkdir -p "${NFC_LOG_DIR}" || die "cannot create ${NFC_LOG_DIR}"
|
||||
|
||||
# start always begins a fresh log, so a report is about THIS run only
|
||||
: > "${LOG_FILE}" || die "cannot write ${LOG_FILE}"
|
||||
|
||||
if command -v setsid >/dev/null 2>&1; then
|
||||
setsid "${SCRIPT_PATH}" __daemon >/dev/null 2>&1 &
|
||||
else
|
||||
nohup "${SCRIPT_PATH}" __daemon >/dev/null 2>&1 &
|
||||
disown 2>/dev/null
|
||||
fi
|
||||
|
||||
sleep 1
|
||||
pid="$(is_running)" || die "start failed, check ${LOG_FILE}"
|
||||
printf 'started (pid=%s)\nlog: %s\n' "${pid}" "${LOG_FILE}"
|
||||
}
|
||||
|
||||
do_daemon() {
|
||||
mkdir -p "${NFC_LOG_DIR}" || die "cannot create ${NFC_LOG_DIR}"
|
||||
exec >>"${LOG_FILE}" 2>&1
|
||||
printf '%d\n' "$$" > "${PID_FILE}"
|
||||
trap 'rm -f "${PID_FILE}"' EXIT
|
||||
main_loop
|
||||
}
|
||||
|
||||
do_stop() {
|
||||
local pid i
|
||||
pid="$(is_running)" || { printf 'not running\n'; rm -f "${PID_FILE}"; return 0; }
|
||||
kill -TERM -"${pid}" 2>/dev/null || kill -TERM "${pid}" 2>/dev/null
|
||||
for (( i = 0; i < 20; i++ )); do
|
||||
kill -0 "${pid}" 2>/dev/null || break
|
||||
sleep 0.5
|
||||
done
|
||||
if kill -0 "${pid}" 2>/dev/null; then
|
||||
printf 'SIGTERM ignored, sending SIGKILL\n'
|
||||
kill -KILL -"${pid}" 2>/dev/null || kill -KILL "${pid}" 2>/dev/null
|
||||
fi
|
||||
rm -f "${PID_FILE}"
|
||||
printf 'stopped (pid=%s)\n' "${pid}"
|
||||
}
|
||||
|
||||
# counts straight out of the log, so it is the same answer running or stopped
|
||||
_tally() {
|
||||
local f="$1"
|
||||
[ -r "${f}" ] || { printf '0 0 0 0\n'; return; }
|
||||
awk '
|
||||
/RESULT=PASS/ { p++ }
|
||||
/RESULT=FAIL/ { f++ }
|
||||
/RESULT=ERROR/ { e++ }
|
||||
/ START$/ { s++ }
|
||||
END { printf "%d %d %d %d\n", s+0, p+0, f+0, e+0 }
|
||||
' "${f}"
|
||||
}
|
||||
|
||||
do_status() {
|
||||
local pid started passed failed errored size
|
||||
if pid="$(is_running)"; then
|
||||
printf 'status : running (pid=%s)\n' "${pid}"
|
||||
else
|
||||
printf 'status : stopped\n'
|
||||
fi
|
||||
printf 'log : %s\n' "${LOG_FILE}"
|
||||
if [ -r "${LOG_FILE}" ]; then
|
||||
size="$(du -h "${LOG_FILE}" 2>/dev/null | cut -f1)"
|
||||
read -r started passed failed errored <<< "$(_tally "${LOG_FILE}")"
|
||||
printf 'size : %s\n' "${size:-?}"
|
||||
printf 'rounds : %s started (PASS %s / FAIL %s / ERROR %s)\n' \
|
||||
"${started}" "${passed}" "${failed}" "${errored}"
|
||||
printf 'last : %s\n' "$(grep -a 'RESULT=' "${LOG_FILE}" | tail -1)"
|
||||
else
|
||||
printf 'size : (no log yet)\n'
|
||||
fi
|
||||
}
|
||||
|
||||
do_report() {
|
||||
local pid started passed failed errored inflight verdict first last
|
||||
[ -r "${LOG_FILE}" ] || die "no log at ${LOG_FILE} -- has it been started?"
|
||||
read -r started passed failed errored <<< "$(_tally "${LOG_FILE}")"
|
||||
inflight=$(( started - passed - failed - errored ))
|
||||
|
||||
echo "===== NFC polling report ====="
|
||||
printf 'log : %s\n' "${LOG_FILE}"
|
||||
if pid="$(is_running)"; then
|
||||
printf 'state : RUNNING (pid=%s) -- this is a snapshot, the count is still moving\n' "${pid}"
|
||||
else
|
||||
printf 'state : stopped\n'
|
||||
fi
|
||||
first="$(grep -a -m1 ' START$' "${LOG_FILE}" | sed -n 's/^\[\([^]]*\)\].*/\1/p')"
|
||||
last="$(grep -a 'RESULT=' "${LOG_FILE}" | tail -1 | sed -n 's/^\[\([^]]*\)\].*/\1/p')"
|
||||
printf 'window : %s -> %s\n' "${first:-?}" "${last:-?}"
|
||||
echo ""
|
||||
printf 'rounds : %d\n' "${started}"
|
||||
printf 'PASS : %d\n' "${passed}"
|
||||
printf 'FAIL : %d\n' "${failed}"
|
||||
printf 'ERROR : %d (tool did not produce a verdict)\n' "${errored}"
|
||||
[ "${inflight}" -gt 0 ] && printf 'in flight: %d (round started, no result yet)\n' "${inflight}"
|
||||
|
||||
if [ "${started}" -eq 0 ]; then
|
||||
verdict="NO DATA"
|
||||
elif [ "${failed}" -gt 0 ] || [ "${errored}" -gt 0 ]; then
|
||||
verdict="FAIL"
|
||||
else
|
||||
verdict="PASS"
|
||||
fi
|
||||
printf 'RESULT : %s\n' "${verdict}"
|
||||
|
||||
echo ""
|
||||
echo "--- tags seen ---"
|
||||
grep -a 'RESULT=PASS' "${LOG_FILE}" \
|
||||
| sed -n 's/.* tag=\([0-9A-Fa-f]*\) .*/\1/p' \
|
||||
| sort | uniq -c | sort -rn | awk '{printf " %-20s %s\n", $2, $1}'
|
||||
grep -aq 'RESULT=PASS.* tag=[0-9A-Fa-f]' "${LOG_FILE}" || echo " (none)"
|
||||
|
||||
if [ "$(( failed + errored ))" -gt 0 ]; then
|
||||
echo ""
|
||||
echo "--- last 10 FAIL / ERROR ---"
|
||||
grep -aE 'RESULT=(FAIL|ERROR)' "${LOG_FILE}" | tail -10 | sed 's/^/ /'
|
||||
fi
|
||||
echo ""
|
||||
[ "${verdict}" = "FAIL" ] && return 2
|
||||
return 0
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<USAGE
|
||||
${SCRIPT_NAME} - background NFC tag polling (wraps ${NFC_SCRIPT_NAME})
|
||||
|
||||
start run in the background; CLEARS the log first
|
||||
stop stop it
|
||||
status running? pid, rounds so far, last result
|
||||
tail [n] last n lines of the log (default 50) -- does NOT follow
|
||||
report PASS/FAIL tally -- safe to run WHILE polling
|
||||
clear delete the log (must be stopped)
|
||||
fg run in the foreground, Ctrl-C to stop
|
||||
|
||||
interval ${NFC_INTERVAL_SEC}s per-round timeout ${NFC_TIMEOUT_SEC}s rounds ${NFC_MAX_ROUNDS} (0 = forever)
|
||||
log ${LOG_FILE}
|
||||
|
||||
A round is PASS or FAIL from the tool's own summary line; ERROR means it
|
||||
produced neither, which is a different problem from a tag that would not read.
|
||||
USAGE
|
||||
}
|
||||
|
||||
case "${1:-}" in
|
||||
start) do_start ;;
|
||||
stop) do_stop ;;
|
||||
status) do_status ;;
|
||||
report) do_report ;;
|
||||
# deliberately NOT 'tail -f': that never returns, and a TTL macro waiting on
|
||||
# the prompt would hang there forever.
|
||||
tail) [ -r "${LOG_FILE}" ] || die "no log at ${LOG_FILE}"
|
||||
tail -n "${2:-50}" "${LOG_FILE}" ;;
|
||||
clear)
|
||||
is_running >/dev/null && die "still running, stop it first"
|
||||
rm -f "${LOG_FILE}"
|
||||
printf 'log cleared\n'
|
||||
;;
|
||||
fg) main_loop ;;
|
||||
__daemon) do_daemon ;;
|
||||
-h|--help|"") usage ;;
|
||||
*) printf '[ERROR] unknown sub-command: %s\n\n' "$1" >&2; usage; exit 1 ;;
|
||||
esac
|
||||
@@ -0,0 +1,431 @@
|
||||
#!/bin/bash
|
||||
###############################################################################
|
||||
# port_prbs_monitor.sh
|
||||
#
|
||||
# Version : V1.0.0
|
||||
# Author : ETWen
|
||||
# Date : 20260826
|
||||
#
|
||||
# Purpose : Run a PRBS test on the two 100G uplinks AT THE SAME TIME and keep
|
||||
# polling until stopped. Each port gets its own background worker:
|
||||
#
|
||||
# setup : sfputil lpmode off <port>
|
||||
# phy diag <phy> prbs set <poly>
|
||||
# phy diag <phy> prbsstat STArt Interval=<n>
|
||||
# poll : phy diag <phy> prbs get <- PASS/FAIL comes from here
|
||||
# phydiag <phy> prbsstat Ber <- recorded only
|
||||
# stop : phydiag <phy> prbsstat STOp
|
||||
# phydiag <phy> prbs clear
|
||||
#
|
||||
# Every command and its full output goes to that port's raw log.
|
||||
# `stop` tears the test down and renders the report; `report`
|
||||
# prints the PASS/FAIL tally per port.
|
||||
#
|
||||
# Notes : - A poll counts as PASS only when the output contains "PRBS OK!".
|
||||
# bcmcmd exits 0 even when the BCM shell rejects a command, so the
|
||||
# exit status cannot be used -- only the output can.
|
||||
# - bcmcmd is always run with </dev/null. Without it, it inherits the
|
||||
# polling loop's stdin and eats it, and the loop runs once.
|
||||
#
|
||||
# Version History
|
||||
# V1.0.0 20260826 Initial Version
|
||||
###############################################################################
|
||||
|
||||
set -u
|
||||
|
||||
###############################################################################
|
||||
# User Configurable Section -- normally this is the only part you need to edit
|
||||
###############################################################################
|
||||
|
||||
# --- port A ---
|
||||
PORT_A_NAME="Ethernet513"
|
||||
PORT_A_UNIT=0 # bcmcmd -n <unit>
|
||||
PORT_A_PHY=268 # phy diag <phy>
|
||||
|
||||
# --- port B ---
|
||||
PORT_B_NAME="Ethernet514"
|
||||
PORT_B_UNIT=1
|
||||
PORT_B_PHY=268
|
||||
|
||||
# Which ports `start` runs when no argument is given: both | a | b
|
||||
# Override per run: start a / start b / start both
|
||||
# Running one at a time is how you tell a genuine port fault from the DUT not
|
||||
# coping with two PRBS streams at once.
|
||||
PORTS="both"
|
||||
|
||||
# --- PRBS ---
|
||||
PRBS_POLY="p=3" # passed to "prbs set"
|
||||
PRBS_STAT_INTERVAL=5 # passed to "prbsstat STArt Interval="
|
||||
POLL_INTERVAL_SEC=10 # seconds between polls
|
||||
PASS_PATTERN="PRBS OK!" # a poll is PASS only if the output contains this
|
||||
|
||||
# Seconds to wait after the setup commands before the first poll, so the link
|
||||
# has settled and the counters mean something.
|
||||
SETTLE_SEC=10
|
||||
|
||||
|
||||
# Stop after this many polls per port. 0 = run until stopped manually.
|
||||
MAX_POLLS=0
|
||||
|
||||
# How many recent poll blocks the report shows per port.
|
||||
TAIL_ENTRIES=20
|
||||
|
||||
# Prefix for privileged commands; empty because this already runs as root.
|
||||
SUDO=""
|
||||
BCMCMD="bcmcmd"
|
||||
|
||||
# Logging
|
||||
LOG_DIR="" # empty = <script directory>/log
|
||||
LOG_NAME="port_prbs.log"
|
||||
|
||||
# What `start` does with the log left behind by the previous run:
|
||||
# new | archive | append
|
||||
START_LOG_MODE="new"
|
||||
|
||||
###############################################################################
|
||||
# Internal
|
||||
###############################################################################
|
||||
SCRIPT_NAME="$(basename -- "${BASH_SOURCE[0]}")"
|
||||
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
||||
SCRIPT_PATH="${SCRIPT_DIR}/${SCRIPT_NAME}"
|
||||
[ -n "${LOG_DIR}" ] || LOG_DIR="${SCRIPT_DIR}/log"
|
||||
|
||||
LOG_FILE="${LOG_DIR}/${LOG_NAME}"
|
||||
BASE="${LOG_DIR}/${LOG_NAME%.log}"
|
||||
PID_FILE="${BASE}.pid"
|
||||
STATE_FILE="${BASE}.state"
|
||||
RAW_A="${BASE}_${PORT_A_NAME}.raw"
|
||||
RAW_B="${BASE}_${PORT_B_NAME}.raw"
|
||||
|
||||
ts() { date '+%Y-%m-%d %H:%M:%S'; }
|
||||
|
||||
# port_tally <name> <raw> -> "<polls> <pass> <fail> <verdict>"
|
||||
# A raw without a "PRBS START" line means the port was not run this session,
|
||||
# which is SKIP -- reporting it as FAIL would make a deliberate single-port
|
||||
# run look like half the hardware is broken.
|
||||
port_tally() {
|
||||
local name="$1" raw="$2" pass fail polls verdict
|
||||
if [ ! -s "${raw}" ] || ! grep -aq "PRBS START ${name}" "${raw}" 2>/dev/null; then
|
||||
printf '0 0 0 SKIP'; return 0
|
||||
fi
|
||||
pass=$(grep -ac "PRBS ${name} poll=[0-9]* PASS" "${raw}" 2>/dev/null); pass=${pass:-0}
|
||||
fail=$(grep -ac "PRBS ${name} poll=[0-9]* FAIL" "${raw}" 2>/dev/null); fail=${fail:-0}
|
||||
polls=$(( pass + fail ))
|
||||
if [ "${polls}" -gt 0 ] && [ "${fail}" -eq 0 ]; then verdict=PASS; else verdict=FAIL; fi
|
||||
printf '%s %s %s %s' "${polls}" "${pass}" "${fail}" "${verdict}"
|
||||
}
|
||||
die() { printf '[ERROR] %s\n' "$*" >&2; exit 1; }
|
||||
|
||||
# bcm <unit> <dsh command> -- output on stdout, never trusts the exit status.
|
||||
# </dev/null so it cannot consume the caller's stdin.
|
||||
bcm() {
|
||||
local unit="$1" cmd="$2"
|
||||
${SUDO} "${BCMCMD}" -n "${unit}" -c "dsh -c \"${cmd}\"" </dev/null 2>&1
|
||||
}
|
||||
|
||||
# run_step <unit> <dsh command>
|
||||
# The command and its full output are written to the LOG via stderr, because
|
||||
# the worker has stderr pointed at the raw file. Only the output itself goes to
|
||||
# stdout, so `out="$(run_step ...)"` captures the output without swallowing the
|
||||
# log lines -- writing both to stdout would have put the whole record inside
|
||||
# the variable and left the log with nothing but the poll verdicts.
|
||||
run_step() {
|
||||
local unit="$1" cmd="$2" out
|
||||
out="$(bcm "${unit}" "${cmd}")"
|
||||
{
|
||||
printf '[%s] CMD : bcmcmd -n %s -c '\''dsh -c "%s"'\''\n' "$(ts)" "${unit}" "${cmd}"
|
||||
printf '%s\n' "${out}"
|
||||
} >&2
|
||||
printf '%s' "${out}"
|
||||
}
|
||||
|
||||
# Echo "<pid_a> <pid_b>" and return 0 while at least one worker is alive. A
|
||||
# port that was not started this run is recorded as "-", so a single-port run
|
||||
# is a first-class case rather than a half-broken two-port one.
|
||||
is_running() {
|
||||
local pa pb alive=0
|
||||
[ -f "${PID_FILE}" ] || return 1
|
||||
pa="$(sed -n '1p' "${PID_FILE}" 2>/dev/null)"; pa="${pa:--}"
|
||||
pb="$(sed -n '2p' "${PID_FILE}" 2>/dev/null)"; pb="${pb:--}"
|
||||
[[ "${pa}" =~ ^[0-9]+$ ]] && kill -0 "${pa}" 2>/dev/null && alive=1
|
||||
[[ "${pb}" =~ ^[0-9]+$ ]] && kill -0 "${pb}" 2>/dev/null && alive=1
|
||||
[ "${alive}" -eq 1 ] || return 1
|
||||
printf '%s %s' "${pa}" "${pb}"
|
||||
return 0
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Worker -- one per port, launched by `start`
|
||||
###############################################################################
|
||||
WORKER_STOP=0
|
||||
worker_on_signal() { WORKER_STOP=1; }
|
||||
|
||||
# __worker <name> <unit> <phy> <rawfile>
|
||||
do_worker() {
|
||||
local name="$1" unit="$2" phy="$3" raw="$4"
|
||||
local n=0 pass=0 fail=0 out
|
||||
|
||||
exec >>"${raw}" 2>&1
|
||||
trap worker_on_signal INT TERM
|
||||
|
||||
printf '#############################################################\n'
|
||||
printf '[%s] PRBS START %s (unit %s, phy %s) poly=%s interval=%ss poll=%ss\n' \
|
||||
"$(ts)" "${name}" "${unit}" "${phy}" "${PRBS_POLY}" \
|
||||
"${PRBS_STAT_INTERVAL}" "${POLL_INTERVAL_SEC}"
|
||||
printf '#############################################################\n'
|
||||
|
||||
# --- setup ---
|
||||
printf '[%s] CMD : sfputil lpmode off %s\n' "$(ts)" "${name}"
|
||||
${SUDO} sfputil lpmode off "${name}" </dev/null 2>&1
|
||||
run_step "${unit}" "phy diag ${phy} prbs set ${PRBS_POLY}" >/dev/null
|
||||
run_step "${unit}" "phy diag ${phy} prbsstat STArt Interval=${PRBS_STAT_INTERVAL}" >/dev/null
|
||||
|
||||
sleep "${SETTLE_SEC}"
|
||||
|
||||
# --- poll ---
|
||||
while [ "${WORKER_STOP}" -eq 0 ]; do
|
||||
n=$(( n + 1 ))
|
||||
printf -- '---------- %s POLL %d @ %s ----------\n' "${name}" "${n}" "$(ts)"
|
||||
|
||||
out="$(run_step "${unit}" "phy diag ${phy} prbs get")"
|
||||
# Ber is recorded for the log only; it does not decide the verdict.
|
||||
run_step "${unit}" "phydiag ${phy} prbsstat Ber" >/dev/null
|
||||
|
||||
if printf '%s' "${out}" | grep -qF "${PASS_PATTERN}"; then
|
||||
pass=$(( pass + 1 ))
|
||||
printf '[%s] PRBS %s poll=%d PASS\n' "$(ts)" "${name}" "${n}"
|
||||
else
|
||||
fail=$(( fail + 1 ))
|
||||
printf '[%s] PRBS %s poll=%d FAIL\n' "$(ts)" "${name}" "${n}"
|
||||
fi
|
||||
|
||||
[ "${MAX_POLLS}" -gt 0 ] && [ "${n}" -ge "${MAX_POLLS}" ] && break
|
||||
[ "${WORKER_STOP}" -eq 0 ] || break
|
||||
sleep "${POLL_INTERVAL_SEC}"
|
||||
done
|
||||
|
||||
# --- teardown ---
|
||||
run_step "${unit}" "phydiag ${phy} prbsstat STOp" >/dev/null
|
||||
run_step "${unit}" "phydiag ${phy} prbs clear" >/dev/null
|
||||
printf '[%s] PRBS STOP %s polls=%d PASS=%d FAIL=%d\n' \
|
||||
"$(ts)" "${name}" "${n}" "${pass}" "${fail}"
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Report
|
||||
###############################################################################
|
||||
# render_port <name> <unit> <phy> <raw>
|
||||
render_port() {
|
||||
local name="$1" unit="$2" phy="$3" raw="$4"
|
||||
local t polls pass fail verdict
|
||||
|
||||
t="$(port_tally "${name}" "${raw}")"
|
||||
polls="$(printf '%s' "${t}" | awk '{print $1}')"
|
||||
pass="$(printf '%s' "${t}" | awk '{print $2}')"
|
||||
fail="$(printf '%s' "${t}" | awk '{print $3}')"
|
||||
verdict="$(printf '%s' "${t}" | awk '{print $4}')"
|
||||
|
||||
if [ "${verdict}" = "SKIP" ]; then
|
||||
printf -- '----- %s (unit %s, phy %s) : not run this session -----\n\n' \
|
||||
"${name}" "${unit}" "${phy}"
|
||||
printf '[%s] RESULT %-12s polls=%-4s PASS=%-4s FAIL=%-4s %s\n\n' \
|
||||
"$(ts)" "${name}" "${polls}" "${pass}" "${fail}" "${verdict}"
|
||||
return 0
|
||||
fi
|
||||
|
||||
printf -- '----- %s (unit %s, phy %s) : last %s poll blocks -----\n' \
|
||||
"${name}" "${unit}" "${phy}" "${TAIL_ENTRIES}"
|
||||
grep -aE "^-{10} ${name} POLL|PRBS ${name} poll=|prbsstat Ber|^ *[0-9]+ *: " "${raw}" 2>/dev/null \
|
||||
| tail -n $(( TAIL_ENTRIES * 3 ))
|
||||
printf '\n'
|
||||
printf '[%s] RESULT %-12s polls=%-4s PASS=%-4s FAIL=%-4s %s\n\n' \
|
||||
"$(ts)" "${name}" "${polls}" "${pass}" "${fail}" "${verdict}"
|
||||
}
|
||||
|
||||
write_report() {
|
||||
local started
|
||||
started="$(sed -n '1p' "${STATE_FILE}" 2>/dev/null)"
|
||||
{
|
||||
printf '#############################################################\n'
|
||||
printf '[%s] 100G PRBS report\n' "$(ts)"
|
||||
printf ' started : %s\n' "${started:-unknown}"
|
||||
printf ' stopped : %s\n' "$(ts)"
|
||||
printf ' %s : unit %s, phy %s\n' "${PORT_A_NAME}" "${PORT_A_UNIT}" "${PORT_A_PHY}"
|
||||
printf ' %s : unit %s, phy %s\n' "${PORT_B_NAME}" "${PORT_B_UNIT}" "${PORT_B_PHY}"
|
||||
printf ' poly=%s prbsstat Interval=%s poll every %ss\n' \
|
||||
"${PRBS_POLY}" "${PRBS_STAT_INTERVAL}" "${POLL_INTERVAL_SEC}"
|
||||
printf ' a poll is PASS only when the output contains "%s"\n' "${PASS_PATTERN}"
|
||||
printf '#############################################################\n\n'
|
||||
|
||||
render_port "${PORT_A_NAME}" "${PORT_A_UNIT}" "${PORT_A_PHY}" "${RAW_A}"
|
||||
render_port "${PORT_B_NAME}" "${PORT_B_UNIT}" "${PORT_B_PHY}" "${RAW_B}"
|
||||
|
||||
# Taken after prbsstat STOp + prbs clear, so this is the recovered
|
||||
# state. During the test the same command would have reported DOWN.
|
||||
printf -- '--- show interfaces status %s,%s (after prbsstat STOp + prbs clear) ---\n' \
|
||||
"${PORT_A_NAME}" "${PORT_B_NAME}"
|
||||
${SUDO} show interfaces status "${PORT_A_NAME},${PORT_B_NAME}" </dev/null 2>&1
|
||||
} >> "${LOG_FILE}"
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Sub-commands
|
||||
###############################################################################
|
||||
prepare_log_on_start() {
|
||||
local stamp
|
||||
case "${START_LOG_MODE}" in
|
||||
append) return 0 ;;
|
||||
archive)
|
||||
if [ -s "${LOG_FILE}" ]; then
|
||||
stamp="$(date '+%Y%m%d-%H%M%S')"
|
||||
mv -f "${LOG_FILE}" "${LOG_FILE}.${stamp}" || die "cannot archive ${LOG_FILE}"
|
||||
fi ;;
|
||||
new)
|
||||
[ -f "${LOG_FILE}" ] && { : > "${LOG_FILE}" || die "cannot truncate ${LOG_FILE}"; } ;;
|
||||
*) die "invalid START_LOG_MODE: ${START_LOG_MODE}" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# do_start [both|a|b|<port name>]
|
||||
do_start() {
|
||||
local which="${1:-${PORTS}}" pids pa="-" pb="-" run_a=0 run_b=0
|
||||
|
||||
case "${which}" in
|
||||
both|BOTH|all) run_a=1; run_b=1 ;;
|
||||
a|A|"${PORT_A_NAME}") run_a=1 ;;
|
||||
b|B|"${PORT_B_NAME}") run_b=1 ;;
|
||||
*) die "unknown port selector '${which}' (use: both | a | b | ${PORT_A_NAME} | ${PORT_B_NAME})" ;;
|
||||
esac
|
||||
|
||||
pids="$(is_running)" && die "already running (pids=${pids})"
|
||||
command -v "${BCMCMD}" >/dev/null 2>&1 || die "${BCMCMD} not found"
|
||||
|
||||
mkdir -p "${LOG_DIR}" || die "cannot create ${LOG_DIR}"
|
||||
prepare_log_on_start
|
||||
# Only the selected ports are truncated. A raw with no "PRBS START" line is
|
||||
# what the report uses to tell "not run this session" from "ran and failed".
|
||||
[ "${run_a}" -eq 1 ] && : > "${RAW_A}"
|
||||
[ "${run_b}" -eq 1 ] && : > "${RAW_B}"
|
||||
printf '%s\n' "$(ts)" > "${STATE_FILE}"
|
||||
|
||||
# One worker per selected port; with both, they run at the same time.
|
||||
# Invoked through bash so the file does not need the execute bit.
|
||||
if [ "${run_a}" -eq 1 ]; then
|
||||
setsid bash "${SCRIPT_PATH}" __worker \
|
||||
"${PORT_A_NAME}" "${PORT_A_UNIT}" "${PORT_A_PHY}" "${RAW_A}" >/dev/null 2>&1 &
|
||||
pa=$!
|
||||
disown "${pa}" 2>/dev/null
|
||||
fi
|
||||
if [ "${run_b}" -eq 1 ]; then
|
||||
setsid bash "${SCRIPT_PATH}" __worker \
|
||||
"${PORT_B_NAME}" "${PORT_B_UNIT}" "${PORT_B_PHY}" "${RAW_B}" >/dev/null 2>&1 &
|
||||
pb=$!
|
||||
disown "${pb}" 2>/dev/null
|
||||
fi
|
||||
printf '%s\n%s\n' "${pa}" "${pb}" > "${PID_FILE}"
|
||||
|
||||
sleep 1
|
||||
[ "${run_a}" -eq 1 ] && { kill -0 "${pa}" 2>/dev/null || die "${PORT_A_NAME} worker failed, see ${RAW_A}"; }
|
||||
[ "${run_b}" -eq 1 ] && { kill -0 "${pb}" 2>/dev/null || die "${PORT_B_NAME} worker failed, see ${RAW_B}"; }
|
||||
printf 'started (%s pid=%s, %s pid=%s)\nlog: %s\n' \
|
||||
"${PORT_A_NAME}" "${pa}" "${PORT_B_NAME}" "${pb}" "${LOG_FILE}"
|
||||
|
||||
# Deliberately NOT printing "show interfaces status" here. With PRBS armed
|
||||
# the link is out of normal operation and reports DOWN, which reads as a
|
||||
# failure to anyone glancing at the console. The status is shown in the
|
||||
# report instead, once PRBS has been cleared.
|
||||
}
|
||||
|
||||
do_stop() {
|
||||
local pids pa pb i
|
||||
pids="$(is_running)" || { printf 'not running\n'; rm -f "${PID_FILE}"; return 0; }
|
||||
pa="${pids% *}"; pb="${pids#* }"
|
||||
|
||||
# TERM lets each worker finish its poll and run prbsstat STOp / prbs clear.
|
||||
[[ "${pa}" =~ ^[0-9]+$ ]] && kill -TERM "${pa}" 2>/dev/null
|
||||
[[ "${pb}" =~ ^[0-9]+$ ]] && kill -TERM "${pb}" 2>/dev/null
|
||||
for (( i = 0; i < 120; i++ )); do
|
||||
kill -0 "${pa}" 2>/dev/null || kill -0 "${pb}" 2>/dev/null || break
|
||||
sleep 0.5
|
||||
done
|
||||
if kill -0 "${pa}" 2>/dev/null || kill -0 "${pb}" 2>/dev/null; then
|
||||
printf 'workers did not exit in time, sending SIGKILL (PRBS may be left running)\n' >&2
|
||||
kill -KILL "${pa}" 2>/dev/null
|
||||
kill -KILL "${pb}" 2>/dev/null
|
||||
fi
|
||||
|
||||
write_report
|
||||
rm -f "${PID_FILE}"
|
||||
printf 'stopped\nreport: %s\n' "${LOG_FILE}"
|
||||
}
|
||||
|
||||
do_report() {
|
||||
local name raw pass fail polls verdict
|
||||
printf '%-14s %-8s %-8s %-8s %s\n' PORT POLLS PASS FAIL RESULT
|
||||
printf '%-14s %-8s %-8s %-8s %s\n' -------------- -------- -------- -------- ------
|
||||
for spec in "${PORT_A_NAME}:${RAW_A}" "${PORT_B_NAME}:${RAW_B}"; do
|
||||
name="${spec%%:*}"; raw="${spec#*:}"
|
||||
set -- $(port_tally "${name}" "${raw}")
|
||||
printf '%-14s %-8s %-8s %-8s %s\n' "${name}" "$1" "$2" "$3" "$4"
|
||||
done
|
||||
}
|
||||
|
||||
do_status() {
|
||||
local pids
|
||||
if pids="$(is_running)"; then
|
||||
printf 'status : running (%s pid=%s, %s pid=%s)\n' \
|
||||
"${PORT_A_NAME}" "${pids% *}" "${PORT_B_NAME}" "${pids#* }"
|
||||
else
|
||||
printf 'status : stopped\n'
|
||||
fi
|
||||
printf 'log : %s\n' "${LOG_FILE}"
|
||||
do_report
|
||||
}
|
||||
|
||||
usage() {
|
||||
cat <<EOF
|
||||
Usage: ${SCRIPT_NAME} {start [both|a|b]|stop|status|report|clear}
|
||||
|
||||
start Set up PRBS and poll in the background. With no argument it runs
|
||||
\$PORTS (currently "${PORTS}"); "a" or "b" runs that port alone,
|
||||
which is how you tell a genuine port fault from the DUT not coping
|
||||
with two PRBS streams at once.
|
||||
start both ports at the same time
|
||||
start a ${PORT_A_NAME} only
|
||||
start b ${PORT_B_NAME} only
|
||||
Port status is NOT shown here: with PRBS armed the link reports
|
||||
DOWN, which looks like a failure. See the report instead.
|
||||
stop Stop polling, run prbsstat STOp + prbs clear on both ports, and
|
||||
render the report into the log
|
||||
report Print the PASS/FAIL tally per port
|
||||
status Show worker pids plus the current tally
|
||||
clear Remove the log and raw captures (must be stopped first)
|
||||
|
||||
Log file : ${LOG_FILE}
|
||||
Raw : ${RAW_A}
|
||||
${RAW_B}
|
||||
|
||||
A poll is PASS only when "phy diag <phy> prbs get" reports "${PASS_PATTERN}".
|
||||
prbsstat Ber is captured alongside every poll but does not decide the verdict.
|
||||
A port that was not run in this session reports SKIP, not FAIL.
|
||||
EOF
|
||||
}
|
||||
|
||||
###############################################################################
|
||||
# Entry point
|
||||
###############################################################################
|
||||
case "${1:-}" in
|
||||
start) shift; do_start "${1:-${PORTS}}" ;;
|
||||
stop) do_stop ;;
|
||||
status) do_status ;;
|
||||
report) do_report ;;
|
||||
clear)
|
||||
is_running >/dev/null && die "still running, stop it first"
|
||||
rm -f "${LOG_FILE}" "${LOG_FILE}".[0-9]* "${RAW_A}" "${RAW_B}" "${STATE_FILE}"
|
||||
printf 'log cleared\n' ;;
|
||||
__worker)
|
||||
shift
|
||||
do_worker "$1" "$2" "$3" "$4" ;;
|
||||
-h|--help|"") usage ;;
|
||||
*) printf '[ERROR] unknown sub-command: %s\n\n' "$1" >&2; usage; exit 1 ;;
|
||||
esac
|
||||
@@ -0,0 +1,241 @@
|
||||
#!/usr/bin/env bash
|
||||
# =============================================================================
|
||||
# pwr_brick.sh -- PDB / CPB power brick Vin / Iin / Vout / Iout / Temp
|
||||
# =============================================================================
|
||||
# Version History:
|
||||
# V1.1.0 2026-09-02 PAGE values and conversions taken from the ADPM12200
|
||||
# datasheet instead of the bring-up spreadsheet.
|
||||
# The spreadsheet wrote every PAGE in decimal but with an
|
||||
# 0x prefix, so four of the five selected the wrong page:
|
||||
# Vin PAGE 9 -> it said 0x00 (should be 0x09)
|
||||
# Iin PAGE 10 -> it said 0x10 (should be 0x0A)
|
||||
# Vout PAGE 2 -> it said 0x02 correct by luck
|
||||
# Iout PAGE 14 -> it said 0x14 (should be 0x0E)
|
||||
# Temp PAGE 18 -> it said 0x18 (should be 0x12)
|
||||
# Only Vout worked, because 2 reads the same either way.
|
||||
# That is why Iin/Iout answered 0xFFFF and Temp 0x0000.
|
||||
# Conversions now use the datasheet DIRECT equation; the
|
||||
# reverse-engineered BRICK_VIN_LSB is gone.
|
||||
# V1.0.0 2026-09-02 First version.
|
||||
# =============================================================================
|
||||
#
|
||||
# Path: CB FPGA F3 VI2C ch4 -> TCA954x mux 0x72 ch0 -> the bricks
|
||||
#
|
||||
# The four ADPM12200 modules put each measurement on its own PMBus PAGE, so a
|
||||
# PAGE write has to precede every read. blanton_pwr_data.sh does not send one
|
||||
# at all (its PDB table has page "-"), which is why it reports them as NA.
|
||||
#
|
||||
# READ_VIN 0x88 PAGE 9
|
||||
# READ_IIN 0x89 PAGE 10
|
||||
# READ_VOUT 0x8B PAGE 2
|
||||
# READ_IOUT 0x8C PAGE 14
|
||||
# READ_TEMPERATURE_1 0x8D PAGE 18
|
||||
#
|
||||
# DIRECT format, datasheet Table 3 ("PMBus Command Code Coefficients"):
|
||||
#
|
||||
# X = (1/m) x (Y x 10^-R - b) Y = the 2-byte two's complement word
|
||||
#
|
||||
# Voltage m=0.125 b=0 R=0 units mV -> X = Y x 8 mV
|
||||
# Current m=0.25 b=0 R=2 units A -> X = Y x 0.04 A
|
||||
# Temperature m=1 b=0 R=2 units degC -> X = Y x 0.01 degC
|
||||
#
|
||||
# Sanity check: READ_VOUT 0x05D4 = 1492 -> 1492 x 8 = 11936 mV, which is exactly
|
||||
# what PDB_IBC_SWB1_A_VOUT reports in 'show platform voltage'.
|
||||
#
|
||||
# ⚠️ Table 3 does not list READ_VIN or READ_IIN. They are decoded here with the
|
||||
# Voltage and Current coefficients respectively - reasonable, and consistent
|
||||
# with a ~50 V input, but not stated by the datasheet. PB_VIN_M / PB_IIN_M
|
||||
# below are where to change that if the part turns out to differ.
|
||||
#
|
||||
# ⚠️ CPB.PU37 (0x26) is a DIFFERENT part: no PAGE writes, and its own scaling
|
||||
# (Vin 0.25 V, Vout 2^-11 V, Iout 0.5 A per count of the mantissa). Those
|
||||
# three were confirmed against words this DUT returns.
|
||||
#
|
||||
# Usage:
|
||||
# ./pwr_brick.sh show # the table
|
||||
# ./pwr_brick.sh show -r # add the raw words
|
||||
# ./pwr_brick.sh help
|
||||
# =============================================================================
|
||||
|
||||
# --- User Configurable Section ----------------------------------------------
|
||||
PB_CH="${PB_CH:-4}" # ICB VI2C channel
|
||||
PB_MUX="${PB_MUX:-0x72}" # TCA954x address
|
||||
PB_MUX_SEL="${PB_MUX_SEL:-0x01}" # control byte: bit0 = channel 0
|
||||
PB_TRIES="${PB_TRIES:-8}" # reads per value before giving up
|
||||
|
||||
# PMBus PAGE per measurement (ADPM12200). Decimal page numbers written in hex.
|
||||
PB_PAGE_VIN="${PB_PAGE_VIN:-0x09}" # 9
|
||||
PB_PAGE_IIN="${PB_PAGE_IIN:-0x0A}" # 10
|
||||
PB_PAGE_VOUT="${PB_PAGE_VOUT:-0x02}" # 2
|
||||
PB_PAGE_IOUT="${PB_PAGE_IOUT:-0x0E}" # 14
|
||||
PB_PAGE_TEMP="${PB_PAGE_TEMP:-0x12}" # 18
|
||||
|
||||
# DIRECT coefficients: m, R, and the divisor that takes the datasheet unit to
|
||||
# the displayed unit (mV -> V is 1000; A and degC are already right).
|
||||
PB_VOUT_M="${PB_VOUT_M:-0.125}"; PB_VOUT_R="${PB_VOUT_R:-0}"; PB_VOUT_DIV="${PB_VOUT_DIV:-1000}"
|
||||
PB_VIN_M="${PB_VIN_M:-0.125}"; PB_VIN_R="${PB_VIN_R:-0}"; PB_VIN_DIV="${PB_VIN_DIV:-1000}"
|
||||
PB_IOUT_M="${PB_IOUT_M:-0.25}"; PB_IOUT_R="${PB_IOUT_R:-2}"; PB_IOUT_DIV="${PB_IOUT_DIV:-1}"
|
||||
PB_IIN_M="${PB_IIN_M:-0.25}"; PB_IIN_R="${PB_IIN_R:-2}"; PB_IIN_DIV="${PB_IIN_DIV:-1}"
|
||||
PB_TEMP_M="${PB_TEMP_M:-1}"; PB_TEMP_R="${PB_TEMP_R:-2}"; PB_TEMP_DIV="${PB_TEMP_DIV:-1}"
|
||||
|
||||
# CPB.PU37 only (different part, no PAGE, mantissa-based)
|
||||
CPB_VIN_LSB="${CPB_VIN_LSB:-0.25}" # V per count of the mantissa
|
||||
CPB_IOUT_LSB="${CPB_IOUT_LSB:-0.5}" # A per count of the mantissa
|
||||
|
||||
# Plausibility windows. A decoded value outside its window is discarded and the
|
||||
# read retried; this is what rejects the corrupted words this bus produces - a
|
||||
# bad high byte turns 11.98 V into 32.00 V, which "reject 0xFFFF" never catches.
|
||||
PB_VIN_LO="${PB_VIN_LO:-30}"; PB_VIN_HI="${PB_VIN_HI:-70}"
|
||||
PB_VOUT_LO="${PB_VOUT_LO:-8}"; PB_VOUT_HI="${PB_VOUT_HI:-14}"
|
||||
PB_IIN_LO="${PB_IIN_LO:-0}"; PB_IIN_HI="${PB_IIN_HI:-100}"
|
||||
PB_IOUT_LO="${PB_IOUT_LO:-0}"; PB_IOUT_HI="${PB_IOUT_HI:-300}"
|
||||
PB_TEMP_LO="${PB_TEMP_LO:-0}"; PB_TEMP_HI="${PB_TEMP_HI:-125}"
|
||||
|
||||
# All-ones and all-zeros are the two ways this bus says "nobody answered", and
|
||||
# both can decode into a value that sits inside its window - 0x0000 on the
|
||||
# temperature register reads as a perfectly plausible 0 C. Rejected as raw
|
||||
# words, before any conversion, so no window has to be bent to catch them.
|
||||
PB_REJECT_FFFF="${PB_REJECT_FFFF:-1}"
|
||||
PB_REJECT_0000="${PB_REJECT_0000:-1}"
|
||||
|
||||
# "location:bricks:slave:netname:kind" kind = adpm (PAGE per read) | cpb
|
||||
PB_DEVS=(
|
||||
"SWB0.PU207:BRICKS1:0x62:P12V_SWB0_L:adpm"
|
||||
"SWB0.PU13:BRICKS2:0x63:P12V_SWB0_L:adpm"
|
||||
"SWB1.PU332:BRICKS1:0x60:P12V_SWB1_R:adpm"
|
||||
"SWB1.PU85:BRICKS2:0x61:P12V_SWB1_R:adpm"
|
||||
"CPB.PU37:BRICK:0x26:P12V_STBY:cpb"
|
||||
)
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
PB_NA="NA"
|
||||
PB_RAW=0
|
||||
PB_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" 2>/dev/null && pwd)"
|
||||
|
||||
_pb_err() { echo -e "[\033[31mERR \033[0m] $*" >&2; }
|
||||
|
||||
# --- backend -----------------------------------------------------------------
|
||||
if ! declare -F vi2c_read >/dev/null 2>&1; then
|
||||
if [ -r "$PB_DIR/blanton_icb_vi2c.sh" ]; then
|
||||
# shellcheck source=/dev/null
|
||||
source "$PB_DIR/blanton_icb_vi2c.sh" >/dev/null 2>&1
|
||||
else
|
||||
_pb_err "blanton_icb_vi2c.sh not found next to this script"; exit 1
|
||||
fi
|
||||
fi
|
||||
declare -F vi2c_read >/dev/null 2>&1 || { _pb_err "vi2c_read() still undefined"; exit 1; }
|
||||
|
||||
# --- decoders ----------------------------------------------------------------
|
||||
# DIRECT: X = (1/m) x (Y x 10^-R - b), b = 0. Y is two's complement, so a word
|
||||
# above 0x7FFF is negative - that matters for temperature, not for the rails.
|
||||
_pb_direct() {
|
||||
awk -v w=$(( $1 )) -v m="$2" -v r="$3" -v d="$4" 'BEGIN{
|
||||
if (w > 32767) w -= 65536
|
||||
printf "%.3f", ((w * (10 ^ -r)) / m) / d
|
||||
}'
|
||||
}
|
||||
# SLINEAR11 mantissa only (bits[10:0], two's complement) - CPB.PU37 path.
|
||||
_pb_mant() { awk -v w=$(( $1 )) 'BEGIN{ m = w % 2048; if (m > 1023) m -= 2048; print m }'; }
|
||||
_pb_mul() { awk -v a="$1" -v b="$2" 'BEGIN{ printf "%.3f", a * b }'; }
|
||||
_pb_lin11() { awk -v w=$(( $1 )) 'BEGIN{ printf "%.4f", w * (2.0 ^ -11) }'; }
|
||||
_pb_in() { awk -v x="$1" -v lo="$2" -v hi="$3" 'BEGIN{ exit !(x >= lo && x <= hi) }'; }
|
||||
|
||||
# _pb_word <slave> <page|-> <reg> -> "0xWWWW"
|
||||
_pb_word() {
|
||||
local slave="$1" page="$2" reg="$3" out
|
||||
[ "$page" != "-" ] && vi2c_write "$PB_CH" "$slave" 0x00 "$page" >/dev/null 2>&1
|
||||
out=$(vi2c_read "$PB_CH" "$slave" "$reg" 2 2>/dev/null \
|
||||
| sed -n 's/.*\[0x\(..\) 0x\(..\)\].*/0x\2\1/p')
|
||||
[ -n "$out" ] && echo "$out"
|
||||
}
|
||||
|
||||
# _pb_val <slave> <page|-> <reg> <decoder> <a1> <a2> <a3> <lo> <hi>
|
||||
# Retries until the decoded value lands inside the window; echoes "value raw".
|
||||
_pb_val() {
|
||||
local slave="$1" page="$2" reg="$3" dec="$4" a1="$5" a2="$6" a3="$7" lo="$8" hi="$9"
|
||||
local i w v
|
||||
for (( i = 0; i < PB_TRIES; i++ )); do
|
||||
w=$(_pb_word "$slave" "$page" "$reg") || continue
|
||||
[ -z "$w" ] && continue
|
||||
[ "$PB_REJECT_FFFF" = "1" ] && [ "$(( w ))" -eq 65535 ] && continue
|
||||
[ "$PB_REJECT_0000" = "1" ] && [ "$(( w ))" -eq 0 ] && continue
|
||||
case "$dec" in
|
||||
direct) v=$(_pb_direct "$w" "$a1" "$a2" "$a3") ;;
|
||||
mant) v=$(_pb_mul "$(_pb_mant "$w")" "$a1") ;;
|
||||
lin11) v=$(_pb_lin11 "$w") ;;
|
||||
esac
|
||||
_pb_in "$v" "$lo" "$hi" || continue
|
||||
echo "$v $w"; return 0
|
||||
done
|
||||
echo "$PB_NA -"; return 1
|
||||
}
|
||||
|
||||
_pb_mux_open() {
|
||||
# The mux takes a bare control byte and vi2c_write always sends a register
|
||||
# first, so passing 0x01 as both makes the part latch 0x01 either way.
|
||||
vi2c_init "$PB_CH" >/dev/null 2>&1
|
||||
vi2c_write "$PB_CH" "$PB_MUX" "$PB_MUX_SEL" "$PB_MUX_SEL" >/dev/null 2>&1
|
||||
return 0
|
||||
}
|
||||
|
||||
# --- show --------------------------------------------------------------------
|
||||
pwr_brick_show() {
|
||||
_pb_mux_open
|
||||
echo "==== PDB / CPB power bricks (VI2C ch${PB_CH} -> mux ${PB_MUX} ch0) ===="
|
||||
printf '%-3s %-12s %-8s %-7s %-14s %10s %10s %10s %10s %9s\n' \
|
||||
"No." "Location" "Bricks" "SlaveID" "Netname" \
|
||||
"Vin(V)" "Iin(A)" "Vout(V)" "Iout(A)" "Temp(C)"
|
||||
printf '%s\n' "--------------------------------------------------------------------------------------------------------------"
|
||||
|
||||
local n=0 entry loc bk slave net kind vi ii vo io tp
|
||||
for entry in "${PB_DEVS[@]}"; do
|
||||
IFS=':' read -r loc bk slave net kind <<< "$entry"
|
||||
n=$(( n + 1 ))
|
||||
if [ "$kind" = "cpb" ]; then
|
||||
vi=$(_pb_val "$slave" - 0x88 mant "$CPB_VIN_LSB" "" "" "$PB_VIN_LO" "$PB_VIN_HI")
|
||||
ii="$PB_NA -" # no input current on this part
|
||||
vo=$(_pb_val "$slave" - 0x8B lin11 "" "" "" "$PB_VOUT_LO" "$PB_VOUT_HI")
|
||||
io=$(_pb_val "$slave" - 0x8C mant "$CPB_IOUT_LSB" "" "" "$PB_IOUT_LO" "$PB_IOUT_HI")
|
||||
tp=$(_pb_val "$slave" - 0x8D direct 1 2 1 "$PB_TEMP_LO" "$PB_TEMP_HI")
|
||||
else
|
||||
vi=$(_pb_val "$slave" "$PB_PAGE_VIN" 0x88 direct "$PB_VIN_M" "$PB_VIN_R" "$PB_VIN_DIV" "$PB_VIN_LO" "$PB_VIN_HI")
|
||||
ii=$(_pb_val "$slave" "$PB_PAGE_IIN" 0x89 direct "$PB_IIN_M" "$PB_IIN_R" "$PB_IIN_DIV" "$PB_IIN_LO" "$PB_IIN_HI")
|
||||
vo=$(_pb_val "$slave" "$PB_PAGE_VOUT" 0x8B direct "$PB_VOUT_M" "$PB_VOUT_R" "$PB_VOUT_DIV" "$PB_VOUT_LO" "$PB_VOUT_HI")
|
||||
io=$(_pb_val "$slave" "$PB_PAGE_IOUT" 0x8C direct "$PB_IOUT_M" "$PB_IOUT_R" "$PB_IOUT_DIV" "$PB_IOUT_LO" "$PB_IOUT_HI")
|
||||
tp=$(_pb_val "$slave" "$PB_PAGE_TEMP" 0x8D direct "$PB_TEMP_M" "$PB_TEMP_R" "$PB_TEMP_DIV" "$PB_TEMP_LO" "$PB_TEMP_HI")
|
||||
fi
|
||||
printf '%-3s %-12s %-8s %-7s %-14s %10s %10s %10s %10s %9s\n' \
|
||||
"$n" "$loc" "$bk" "$slave" "$net" \
|
||||
"${vi%% *}" "${ii%% *}" "${vo%% *}" "${io%% *}" "${tp%% *}"
|
||||
[ "$PB_RAW" = "1" ] && printf '%-3s %-12s %-8s %-7s %-14s %10s %10s %10s %10s %9s\n' \
|
||||
"" "" "" "" "raw" "${vi##* }" "${ii##* }" "${vo##* }" "${io##* }" "${tp##* }"
|
||||
done
|
||||
# No trailing notes on stdout: this table gets pasted into reports and
|
||||
# captured into the master console log, and a caveat printed every run stops
|
||||
# being read after the second time. The caveats live in the file header -
|
||||
# the one that still matters is that READ_VIN / READ_IIN are not in the
|
||||
# datasheet coefficient table and borrow the Voltage / Current sets.
|
||||
}
|
||||
|
||||
pwr_brick_help() {
|
||||
echo -e "\033[1mpwr_brick.sh - PDB / CPB power brick readings\033[0m"
|
||||
echo ""
|
||||
echo -e " \033[33mshow\033[0m [-r] Vin / Iin / Vout / Iout / Temp for all 5 bricks (-r adds raw)"
|
||||
echo -e " \033[33mhelp\033[0m"
|
||||
echo ""
|
||||
echo -e " Path : VI2C ch$PB_CH -> mux $PB_MUX ch0"
|
||||
echo -e " The four ADPM12200 modules need a PMBus PAGE per measurement:"
|
||||
echo -e " Vin $PB_PAGE_VIN(9) Iin $PB_PAGE_IIN(10) Vout $PB_PAGE_VOUT(2) Iout $PB_PAGE_IOUT(14) Temp $PB_PAGE_TEMP(18)"
|
||||
echo -e " DIRECT format, datasheet Table 3: X = (1/m) x (Y x 10^-R - b)"
|
||||
echo -e " CPB.PU37 (0x26) is a different part - no PAGE, its own scaling."
|
||||
echo -e " \033[33mREAD_VIN / READ_IIN are not in Table 3; they borrow Voltage / Current.\033[0m"
|
||||
}
|
||||
|
||||
case "${1:-help}" in
|
||||
show)
|
||||
shift 2>/dev/null
|
||||
[ "${1:-}" = "-r" ] && PB_RAW=1
|
||||
pwr_brick_show ;;
|
||||
help|-h|--help) pwr_brick_help ;;
|
||||
*) _pb_err "unknown sub-command: $1"; pwr_brick_help; exit 1 ;;
|
||||
esac
|
||||
@@ -0,0 +1,203 @@
|
||||
#!/bin/bash
|
||||
###############################################################################
|
||||
# usb_target.sh
|
||||
#
|
||||
# Version : V1.1.0
|
||||
# Author : ETWen
|
||||
# Date : 20260825
|
||||
# Purpose : Auto-detect an inserted USB mass-storage device and report either
|
||||
# its device node, its mount point, or both.
|
||||
#
|
||||
# stdout : requested value(s) only, for $(...) capture
|
||||
# stderr : diagnostic messages
|
||||
#
|
||||
# Usage : usb_target.sh [-o dev|mnt|both|id] [-n] [-r seconds]
|
||||
#
|
||||
# -o dev print partition device node (e.g. /dev/sda1)
|
||||
# -o mnt print mount point (e.g. /mnt/usb) [default]
|
||||
# -o both print "<dev> <mnt>" on one line
|
||||
# -o id print stable by-id path (/dev/disk/by-id/...)
|
||||
# -n detect only, do not mount
|
||||
# -r sec udev enumeration wait, default 15
|
||||
#
|
||||
# Exit : 0 success
|
||||
# 1 no USB mass-storage found
|
||||
# 2 multiple USB disks detected (refuse to guess)
|
||||
# 3 no usable filesystem on the device
|
||||
# 4 mount failed
|
||||
# 5 mounted but not writable
|
||||
#
|
||||
# Version History
|
||||
# V1.0.0 20260825 Initial Version
|
||||
# V1.1.0 20260825 Add -o/-n/-r options; expose device node and by-id path
|
||||
###############################################################################
|
||||
set -u
|
||||
|
||||
MNT_BASE="/mnt/usb"
|
||||
RETRY=15
|
||||
OUTPUT="mnt"
|
||||
DO_MOUNT=1
|
||||
|
||||
log() { echo "[usb] $*" >&2; } # diagnostics go to stderr; stdout stays clean
|
||||
|
||||
while getopts "o:nr:h" opt; do
|
||||
case "$opt" in
|
||||
o) OUTPUT="$OPTARG" ;;
|
||||
n) DO_MOUNT=0 ;;
|
||||
r) RETRY="$OPTARG" ;;
|
||||
h) sed -n '3,30p' "$0" >&2; exit 0 ;;
|
||||
*) log "invalid option"; exit 1 ;;
|
||||
esac
|
||||
done
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
case "$OUTPUT" in
|
||||
dev|mnt|both|id) ;;
|
||||
*) log "invalid -o value: $OUTPUT"; exit 1 ;;
|
||||
esac
|
||||
|
||||
# "-o dev" / "-o id" alone does not require mounting.
|
||||
[ "$OUTPUT" = "dev" ] && [ "$DO_MOUNT" = "1" ] && DO_MOUNT=0
|
||||
[ "$OUTPUT" = "id" ] && [ "$DO_MOUNT" = "1" ] && DO_MOUNT=0
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Identify the physical disk(s) backing rootfs / /host so they can be excluded.
|
||||
# Needed because some platforms boot from a USB DOM, which also reports TRAN=usb.
|
||||
#------------------------------------------------------------------------------
|
||||
get_system_disk() {
|
||||
local src
|
||||
for mp in /host / ; do
|
||||
src=$(findmnt -no SOURCE "$mp" 2>/dev/null) || continue
|
||||
lsblk -no PKNAME "$src" 2>/dev/null | head -1
|
||||
done | sort -u
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# List candidate USB disks (whole devices, not partitions).
|
||||
#------------------------------------------------------------------------------
|
||||
find_usb_disks() {
|
||||
local sysdisks; sysdisks=$(get_system_disk)
|
||||
lsblk -dn -o NAME,TYPE,TRAN,RM 2>/dev/null | while read -r name type tran rm; do
|
||||
[ "$type" = "disk" ] || continue
|
||||
case "$name" in loop*|ram*|dm-*|sr*|zram*) continue ;; esac
|
||||
|
||||
# Older util-linux may not expose the TRAN column; fall back to sysfs.
|
||||
if [ "$tran" != "usb" ]; then
|
||||
readlink -f "/sys/block/$name/device" 2>/dev/null | grep -q '/usb[0-9]' || continue
|
||||
[ "$rm" = "1" ] || continue
|
||||
fi
|
||||
|
||||
echo "$sysdisks" | grep -qx "$name" && { log "skip $name (system disk)"; continue; }
|
||||
echo "/dev/$name"
|
||||
done
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Pick a mountable partition from a disk; fall back to the whole device for
|
||||
# superfloppy layouts (filesystem written directly, no partition table).
|
||||
#------------------------------------------------------------------------------
|
||||
pick_partition() {
|
||||
local disk="$1" p
|
||||
p=$(lsblk -ln -o NAME,TYPE,FSTYPE "$disk" | \
|
||||
awk '$2=="part" && $3!="" {print "/dev/"$1; exit}')
|
||||
[ -n "$p" ] && { echo "$p"; return; }
|
||||
[ -n "$(lsblk -dn -o FSTYPE "$disk")" ] && echo "$disk"
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Resolve a device node to a stable /dev/disk/by-id path, if one exists.
|
||||
#------------------------------------------------------------------------------
|
||||
resolve_by_id() {
|
||||
local dev="$1" real link
|
||||
real=$(readlink -f "$dev")
|
||||
for link in /dev/disk/by-id/*; do
|
||||
[ -e "$link" ] || continue
|
||||
case "$link" in *-part*|*) ;; esac
|
||||
[ "$(readlink -f "$link")" = "$real" ] && { echo "$link"; return 0; }
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Main
|
||||
#------------------------------------------------------------------------------
|
||||
disks=""
|
||||
for i in $(seq 1 "$RETRY"); do
|
||||
disks=$(find_usb_disks)
|
||||
[ -n "$disks" ] && break
|
||||
sleep 1
|
||||
done
|
||||
|
||||
[ -z "$disks" ] && { log "no USB mass-storage found"; exit 1; }
|
||||
|
||||
n=$(echo "$disks" | wc -l)
|
||||
if [ "$n" -gt 1 ]; then
|
||||
log "multiple USB disks detected, refuse to guess:"
|
||||
log "$disks"
|
||||
exit 2
|
||||
fi
|
||||
disk="$disks"
|
||||
|
||||
part=$(pick_partition "$disk")
|
||||
[ -z "$part" ] && { log "$disk has no usable filesystem"; exit 3; }
|
||||
|
||||
fstype=$(lsblk -no FSTYPE "$part")
|
||||
log "found $part (disk=$disk fstype=$fstype)"
|
||||
|
||||
# --- device-node only: no mount needed ---------------------------------------
|
||||
if [ "$OUTPUT" = "dev" ]; then
|
||||
echo "$part"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "$OUTPUT" = "id" ]; then
|
||||
if byid=$(resolve_by_id "$part"); then
|
||||
echo "$byid"
|
||||
exit 0
|
||||
fi
|
||||
log "no by-id path for $part, falling back to device node"
|
||||
echo "$part"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- mount point required ----------------------------------------------------
|
||||
mp=$(lsblk -no MOUNTPOINT "$part" | head -1)
|
||||
|
||||
if [ -z "$mp" ] && [ "$DO_MOUNT" = "0" ]; then
|
||||
log "$part is not mounted and -n was given"
|
||||
exit 4
|
||||
fi
|
||||
|
||||
if [ -z "$mp" ]; then
|
||||
log "mounting $part -> $MNT_BASE"
|
||||
mkdir -p "$MNT_BASE"
|
||||
|
||||
# exfat/ntfs are not always built into the platform kernel.
|
||||
case "$fstype" in
|
||||
exfat) grep -qw exfat /proc/filesystems || modprobe exfat 2>/dev/null ;;
|
||||
ntfs) grep -qw ntfs3 /proc/filesystems || modprobe ntfs3 2>/dev/null ;;
|
||||
esac
|
||||
|
||||
if ! mount -o rw,noatime "$part" "$MNT_BASE" 2>/dev/null; then
|
||||
log "mount failed (fstype=$fstype)"
|
||||
exit 4
|
||||
fi
|
||||
mp="$MNT_BASE"
|
||||
|
||||
# Verify it is actually writable (read-only media, dirty FAT, or full device).
|
||||
if ! touch "$mp/.wtest" 2>/dev/null; then
|
||||
log "mounted read-only or no space left"
|
||||
umount "$mp"
|
||||
exit 5
|
||||
fi
|
||||
rm -f "$mp/.wtest"
|
||||
else
|
||||
log "$part already mounted at $mp"
|
||||
fi
|
||||
|
||||
if [ "$OUTPUT" = "both" ]; then
|
||||
echo "$part $mp"
|
||||
else
|
||||
echo "$mp"
|
||||
fi
|
||||
exit 0
|
||||
@@ -1,12 +1,34 @@
|
||||
;================================================================
|
||||
; User Configuration
|
||||
;================================================================
|
||||
strTestcase="Margin"
|
||||
project_name = "Blanton"
|
||||
strTestcase="ENV" ;ENV,EMC,Margin...etc
|
||||
|
||||
EN_Margin = 1 ; 1: Enable Margin Test, 0: Disable Margin Test
|
||||
EN_Margin = 0 ; 1: Enable Margin Test, 0: Disable Margin Test
|
||||
EN_TX_FIR = 0 ; 1: Enable bcm_dsc_scan.sh collect port TX_FIR, 0: Disable (saves ~20 min: ScriptA and ScriptC each scan for ~10 min)
|
||||
|
||||
EN_log = 1 ; 1: Enable log, 0: Disable log
|
||||
EN_timestamp = 1 ; 1: Enable timestamp in log, 0: Disable timestamp in log
|
||||
|
||||
;================================================================
|
||||
; FAN_SPEED
|
||||
;================================================================
|
||||
FAN_SPEED = 100
|
||||
;================================================================
|
||||
; Switch Unit Population
|
||||
;================================================================
|
||||
SWB_UNIT0 = 1 ; 1 = this DUT has switch unit 0, wait for it ; 0 = skip
|
||||
SWB_UNIT1 = 1 ; 1 = this DUT has switch unit 1, wait for it ; 0 = skip
|
||||
|
||||
;================================================================
|
||||
; Stress_Test
|
||||
;================================================================
|
||||
SSD_RUNTIME = 3600 ; Unit seconds, 3600 = 1 hour
|
||||
SSD_COUNT = 240 ; Total time = SSD_RUNTIME * SSD_COUNT
|
||||
USB_RUNTIME = 3600 ; Unit seconds, 3600 = 1 hour
|
||||
USB_COUNT = 240 ; Total time = USB_RUNTIME * USB_COUNT
|
||||
BMC_USB_RUNTIME = 172800 ; Unit seconds, 172800 = 2 days
|
||||
|
||||
;================================================================
|
||||
; Prompt Definitions
|
||||
;================================================================
|
||||
|
||||
@@ -15,4 +15,9 @@ sendln "show platform ssdhealth"
|
||||
wait prompt_sonic_root
|
||||
sendln "show platform leak status"
|
||||
wait prompt_sonic_root
|
||||
sendln "show platform leak channels"
|
||||
sendln "show platform leak channels"
|
||||
|
||||
wait prompt_sonic_root
|
||||
sendln "tpm-dut-test fru"
|
||||
wait prompt_sonic_root
|
||||
sendln "tpm-dut-test tpm-read"
|
||||
@@ -1,8 +1,11 @@
|
||||
; All Event
|
||||
wait prompt_sonic_root
|
||||
sendln "date"
|
||||
sendln "dmesg -T | grep -Ei 'error|fail(ed|ure)?|fault|critical|panic|timeout'"
|
||||
|
||||
; i2c event
|
||||
wait prompt_sonic_root
|
||||
sendln "dmesg | grep -i error"
|
||||
sendln "dmesg -T | grep -Ei 'error|fail(ed|ure)?|fault|critical|panic|timeout' | grep -i i2c"
|
||||
|
||||
; Clear Event
|
||||
wait prompt_sonic_root
|
||||
sendln "dmesg | grep -i fail"
|
||||
wait prompt_sonic_root
|
||||
sendln "dmesg | grep -i warning"
|
||||
sendln "dmesg -C"
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
; =============================================================================
|
||||
; File : utils/wait_init.ttl
|
||||
; Version : V3.0.0
|
||||
; Date : 2026-08-21
|
||||
; Author : ETWen
|
||||
; =============================================================================
|
||||
; Wait until every switch unit ENABLED below reports at least WT_MIN ports up:
|
||||
; bcmcmd -n <u> -c ps | grep -w up | wc -l
|
||||
;
|
||||
; The DUT is not always fully populated. Which units exist is declared ONCE in
|
||||
; config.ttl, so the traffic blocks in Script A/B/C and this wait agree:
|
||||
; both units -> SWB_UNIT0 = 1 , SWB_UNIT1 = 1
|
||||
; unit 0 only -> SWB_UNIT0 = 1 , SWB_UNIT1 = 0
|
||||
; unit 1 only -> SWB_UNIT0 = 0 , SWB_UNIT1 = 1
|
||||
; no unit -> SWB_UNIT0 = 0 , SWB_UNIT1 = 0 (bypass, returns immediately)
|
||||
;
|
||||
; Enter : prompt of the previous command is NOT consumed.
|
||||
; Exit : a command has been sent, prompt NOT consumed (caller does the wait).
|
||||
;
|
||||
; Why the "PORTS0=" marker: TTL can only test for a string, so reading a count
|
||||
; means capturing it. Wrapping the number in an echo gives waitregex a unique
|
||||
; anchor, and the ECHO of the command cannot false-match -- it reads
|
||||
; "PORTS0=$(bcmcmd ..." and the pattern requires a digit right after the "=".
|
||||
;
|
||||
; Version History:
|
||||
; V1.0.0 2026-08-21 Initial Version (waited on "show platform temperature"
|
||||
; until it stopped reporting "Thermal Not detected")
|
||||
; V2.0.0 2026-08-21 Wait on the bcmcmd port-up count of BOTH switch units
|
||||
; instead of the thermal sensors; proceed only when both
|
||||
; are greater than WT_MIN (216).
|
||||
; V3.0.0 2026-08-21 Add WT_UNIT0 / WT_UNIT1 so a partly populated DUT can
|
||||
; be declared: wait on the enabled units only, and bypass
|
||||
; entirely when neither is set.
|
||||
; V3.1.0 2026-08-21 Take the population from SWB_UNIT0 / SWB_UNIT1 in
|
||||
; config.ttl instead of local copies, so this wait and the
|
||||
; traffic blocks cannot drift apart.
|
||||
; V3.1.1 2026-08-25 WT_INTERVAL 10 -> 60. Fix the WT_MIN comments: the test
|
||||
; has been `< WT_MIN` (at least) since the threshold was
|
||||
; corrected, but the text still said "more than", which is
|
||||
; the off-by-one that once hung Script A.
|
||||
; =============================================================================
|
||||
; ---- which units to wait for: SWB_UNIT0 / SWB_UNIT1, set in config.ttl ------
|
||||
WT_MIN = 216 ; an enabled unit must report AT LEAST this many ports up
|
||||
; (216 = 108 loopback pairs x 2, i.e. every cabled port)
|
||||
WT_INTERVAL = 60 ; seconds between polls
|
||||
; -----------------------------------------------------------------------------
|
||||
|
||||
timeout = 60 ; per-wait cap; bcmcmd ps is not instant
|
||||
wait prompt_sonic_root
|
||||
|
||||
; nothing declared -> bypass
|
||||
if SWB_UNIT0 = 0 then
|
||||
if SWB_UNIT1 = 0 then
|
||||
goto NO_UNITS
|
||||
endif
|
||||
endif
|
||||
|
||||
:WAIT_PORTS
|
||||
wt_ok = 1
|
||||
|
||||
if SWB_UNIT0 = 1 then
|
||||
wt_up0 = 0
|
||||
sendln "echo PORTS0=$(bcmcmd -n 0 -c ps | grep -w up | wc -l)"
|
||||
waitregex "PORTS0=[ ]*([0-9]+)"
|
||||
if result = 1 then
|
||||
str2int wt_up0 groupmatchstr1
|
||||
endif
|
||||
wait prompt_sonic_root
|
||||
if wt_up0 < WT_MIN then
|
||||
wt_ok = 0
|
||||
endif
|
||||
endif
|
||||
|
||||
if SWB_UNIT1 = 1 then
|
||||
wt_up1 = 0
|
||||
sendln "echo PORTS1=$(bcmcmd -n 1 -c ps | grep -w up | wc -l)"
|
||||
waitregex "PORTS1=[ ]*([0-9]+)"
|
||||
if result = 1 then
|
||||
str2int wt_up1 groupmatchstr1
|
||||
endif
|
||||
wait prompt_sonic_root
|
||||
if wt_up1 < WT_MIN then
|
||||
wt_ok = 0
|
||||
endif
|
||||
endif
|
||||
|
||||
if wt_ok = 1 then
|
||||
goto PORTS_OK
|
||||
endif
|
||||
|
||||
pause WT_INTERVAL
|
||||
goto WAIT_PORTS
|
||||
|
||||
; ---- exits ------------------------------------------------------------------
|
||||
; Both leave exactly one prompt unconsumed, so the caller's next
|
||||
; "wait prompt_sonic_root" has something to match.
|
||||
:NO_UNITS
|
||||
sendln "echo wait_init:no-switch-unit-declared,bypassing-port-wait"
|
||||
goto DONE
|
||||
|
||||
:PORTS_OK
|
||||
sendln ""
|
||||
|
||||
:DONE
|
||||
timeout = 0
|
||||
@@ -0,0 +1,63 @@
|
||||
|
||||
|
||||
echo PORTS0=$(bcmcmd -n 0 -c ps | grep -w up | wc -l)
|
||||
echo PORTS0=$(bcmcmd -n 1 -c ps | grep -w up | wc -l)
|
||||
|
||||
show interfaces status Ethernet513,Ethernet514
|
||||
|
||||
|
||||
//100G Port 513
|
||||
sudo sfputil lpmode off Ethernet513
|
||||
bcmcmd -n 0 -c 'dsh -c "phy diag 268 prbs set p=3"'
|
||||
bcmcmd -n 0 -c 'dsh -c "phy diag 268 prbsstat STArt Interval=5"'
|
||||
|
||||
bcmcmd -n 0 -c 'dsh -c "phy diag 268 prbs get"'
|
||||
bcmcmd -n 0 -c 'dsh -c "phydiag 268 prbsstat Ber"'
|
||||
|
||||
bcmcmd -n 0 -c 'dsh -c "phydiag 268 prbsstat STOp"'
|
||||
bcmcmd -n 0 -c 'dsh -c "phydiag 268 prbs clear"'
|
||||
|
||||
|
||||
//100G Port 514
|
||||
sudo sfputil lpmode off Ethernet514
|
||||
bcmcmd -n 1 -c 'dsh -c "phy diag 268 prbs set p=3"'
|
||||
bcmcmd -n 1 -c 'dsh -c "phy diag 268 prbsstat STArt Interval=5"'
|
||||
bcmcmd -n 1 -c 'dsh -c "phy diag 268 prbs get"'
|
||||
bcmcmd -n 1 -c 'dsh -c "phydiag 268 prbsstat Ber"'
|
||||
bcmcmd -n 1 -c 'dsh -c "phydiag 268 prbsstat STOp"'
|
||||
bcmcmd -n 1 -c 'dsh -c "phydiag 268 prbs clear"'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//100G Port 513
|
||||
sudo sfputil lpmode off Ethernet513
|
||||
sudo sfputil lpmode off Ethernet514
|
||||
|
||||
bcmcmd -n 0 -c 'dsh -c "phy diag 268 prbs set p=3"'
|
||||
sleep 1
|
||||
bcmcmd -n 1 -c 'dsh -c "phy diag 268 prbs set p=3"'
|
||||
|
||||
bcmcmd -n 0 -c 'dsh -c "phy diag 268 prbsstat STArt Interval=5"'
|
||||
sleep 1
|
||||
bcmcmd -n 1 -c 'dsh -c "phy diag 268 prbsstat STArt Interval=5"'
|
||||
|
||||
bcmcmd -n 0 -c 'dsh -c "phy diag 268 prbs get"'
|
||||
sleep 1
|
||||
bcmcmd -n 1 -c 'dsh -c "phy diag 268 prbs get"'
|
||||
|
||||
bcmcmd -n 0 -c 'dsh -c "phydiag 268 prbsstat Ber"'
|
||||
sleep 1
|
||||
bcmcmd -n 1 -c 'dsh -c "phydiag 268 prbsstat Ber"'
|
||||
|
||||
bcmcmd -n 0 -c 'dsh -c "phydiag 268 prbsstat STOp"'
|
||||
sleep 1
|
||||
bcmcmd -n 1 -c 'dsh -c "phydiag 268 prbsstat STOp"'
|
||||
|
||||
bcmcmd -n 0 -c 'dsh -c "phydiag 268 prbs clear"'
|
||||
sleep 1
|
||||
bcmcmd -n 1 -c 'dsh -c "phydiag 268 prbs clear"'
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
//Init
|
||||
bcmcmd -n 0 -c 'mirror init'
|
||||
bcmcmd -n 0 -c 'mirror port ce0 Mode=Ingress DestPort=ce0'
|
||||
bcmcmd -n 0 -c 'vlan create 138'
|
||||
bcmcmd -n 0 -c 'vlan add 138 pbm=ce0'
|
||||
|
||||
//Start
|
||||
bcmcmd -n 0 -c 'tx 100 length=512 VLantag=138'
|
||||
|
||||
//stop
|
||||
bcmcmd -n 0 -c 'mirror port ce0 Mode=Off'
|
||||
bcmcmd -n 0 -c 'vlan remove 138 pbm=ce0'
|
||||
@@ -0,0 +1,900 @@
|
||||
bcmcmd -n 0 -c " dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbs set p=3' "
|
||||
bcmcmd -n 0 -c " dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbs get' "
|
||||
|
||||
bcmcmd -n 0 -c " dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbsstat STArt Interval=30' "
|
||||
bcmcmd -n 0 -c " dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbsstat Ber' "
|
||||
|
||||
bcmcmd -n 0 -c " dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbsstat STOp' "
|
||||
bcmcmd -n 0 -c " dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbs clear' "
|
||||
|
||||
root@sonic:~# bcmcmd -n 0 -c " dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbs set p=3' "
|
||||
dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbs set p=3'
|
||||
drivshell>
|
||||
root@sonic:~# bcmcmd -n 0 -c " dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbs get' "
|
||||
dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbs get'
|
||||
1 : PRBS OK!has been unlocked since last call
|
||||
2 : PRBS OK!has been unlocked since last call
|
||||
3 : PRBS OK!has been unlocked since last call
|
||||
4 : PRBS OK!has been unlocked since last call
|
||||
5 : PRBS OK!has been unlocked since last call
|
||||
6 : PRBS OK!has been unlocked since last call
|
||||
7 : PRBS OK!has been unlocked since last call
|
||||
8 : PRBS OK!has been unlocked since last call
|
||||
18 : PRBS OK!has been unlocked since last call
|
||||
19 : PRBS OK!has been unlocked since last call
|
||||
20 : PRBS OK!has been unlocked since last call
|
||||
21 : PRBS OK!has been unlocked since last call
|
||||
22 : PRBS OK!has been unlocked since last call
|
||||
23 : PRBS OK!has been unlocked since last call
|
||||
24 : PRBS OK!has been unlocked since last call
|
||||
40 : PRBS OK!has been unlocked since last call
|
||||
41 : PRBS OK!has been unlocked since last call
|
||||
42 : PRBS OK!has been unlocked since last call
|
||||
43 : PRBS OK!has been unlocked since last call
|
||||
54 : PRBS OK!has been unlocked since last call
|
||||
55 : PRBS OK!has been unlocked since last call
|
||||
56 : PRBS OK!has been unlocked since last call
|
||||
57 : PRBS OK!has been unlocked since last call
|
||||
58 : PRBS OK!has been unlocked since last call
|
||||
59 : PRBS OK!has been unlocked since last call
|
||||
60 : PRBS OK!has been unlocked since last call
|
||||
61 : PRBS OK!has been unlocked since last call
|
||||
72 : PRBS OK!has been unlocked since last call
|
||||
73 : PRBS OK!has been unlocked since last call
|
||||
74 : PRBS OK!has been unlocked since last call
|
||||
75 : PRBS OK!has been unlocked since last call
|
||||
76 : PRBS OK!has been unlocked since last call
|
||||
77 : PRBS OK!has been unlocked since last call
|
||||
78 : PRBS OK!has been unlocked since last call
|
||||
79 : PRBS OK!has been unlocked since last call
|
||||
90 : PRBS OK!has been unlocked since last call
|
||||
91 : PRBS OK!has been unlocked since last call
|
||||
92 : PRBS OK!has been unlocked since last call
|
||||
93 : PRBS OK!has been unlocked since last call
|
||||
94 : PRBS OK!has been unlocked since last call
|
||||
95 : PRBS OK!has been unlocked since last call
|
||||
96 : PRBS OK!has been unlocked since last call
|
||||
112 : PRBS OK!has been unlocked since last call
|
||||
113 : PRBS OK!has been unlocked since last call
|
||||
114 : PRBS OK!has been unlocked since last call
|
||||
115 : PRBS OK!has been unlocked since last call
|
||||
126 : PRBS OK!has been unlocked since last call
|
||||
127 : PRBS OK!has been unlocked since last call
|
||||
128 : PRBS OK!has been unlocked since last call
|
||||
129 : PRBS OK!has been unlocked since last call
|
||||
130 : PRBS OK!has been unlocked since last call
|
||||
131 : PRBS OK!has been unlocked since last call
|
||||
132 : PRBS OK!has been unlocked since last call
|
||||
133 : PRBS OK!has been unlocked since last call
|
||||
144 : PRBS OK!has been unlocked since last call
|
||||
145 : PRBS OK!has been unlocked since last call
|
||||
146 : PRBS OK!has been unlocked since last call
|
||||
147 : PRBS OK!has been unlocked since last call
|
||||
148 : PRBS OK!has been unlocked since last call
|
||||
149 : PRBS OK!has been unlocked since last call
|
||||
150 : PRBS OK!has been unlocked since last call
|
||||
151 : PRBS OK!has been unlocked since last call
|
||||
162 : PRBS OK!has been unlocked since last call
|
||||
163 : PRBS OK!has been unlocked since last call
|
||||
164 : PRBS OK!has been unlocked since last call
|
||||
165 : PRBS OK!has been unlocked since last call
|
||||
166 : PRBS OK!has been unlocked since last call
|
||||
167 : PRBS OK!has been unlocked since last call
|
||||
168 : PRBS OK!has been unlocked since last call
|
||||
184 : PRBS OK!has been unlocked since last call
|
||||
185 : PRBS OK!has been unlocked since last call
|
||||
186 : PRBS OK!has been unlocked since last call
|
||||
187 : PRBS OK!has been unlocked since last call
|
||||
198 : PRBS OK!has been unlocked since last call
|
||||
199 : PRBS OK!has been unlocked since last call
|
||||
200 : PRBS OK!has been unlocked since last call
|
||||
201 : PRBS OK!has been unlocked since last call
|
||||
202 : PRBS OK!has been unlocked since last call
|
||||
203 : PRBS OK!has been unlocked since last call
|
||||
204 : PRBS OK!has been unlocked since last call
|
||||
205 : PRBS OK!has been unlocked since last call
|
||||
216 : PRBS OK!has been unlocked since last call
|
||||
217 : PRBS OK!has been unlocked since last call
|
||||
218 : PRBS OK!has been unlocked since last call
|
||||
219 : PRBS OK!has been unlocked since last call
|
||||
220 : PRBS OK!has been unlocked since last call
|
||||
221 : PRBS OK!has been unlocked since last call
|
||||
222 : PRBS OK!has been unlocked since last call
|
||||
223 : PRBS OK!has been unlocked since last call
|
||||
234 : PRBS OK!has been unlocked since last call
|
||||
235 : PRBS OK!has been unlocked since last call
|
||||
236 : PRBS OK!has been unlocked since last call
|
||||
237 : PRBS OK!has been unlocked since last call
|
||||
238 : PRBS OK!has been unlocked since last call
|
||||
239 : PRBS OK!has been unlocked since last call
|
||||
240 : PRBS OK!has been unlocked since last call
|
||||
256 : PRBS OK!has been unlocked since last call
|
||||
257 : PRBS OK!has been unlocked since last call
|
||||
258 : PRBS OK!has been unlocked since last call
|
||||
259 : PRBS OK!has been unlocked since last call
|
||||
270 : PRBS OK!has been unlocked since last call
|
||||
271 : PRBS OK!has been unlocked since last call
|
||||
272 : PRBS OK!has been unlocked since last call
|
||||
273 : PRBS OK!has been unlocked since last call
|
||||
274 : PRBS OK!has been unlocked since last call
|
||||
275 : PRBS OK!has been unlocked since last call
|
||||
276 : PRBS OK!has been unlocked since last call
|
||||
277 : PRBS OK!has been unlocked since last call
|
||||
288 : PRBS OK!has been unlocked since last call
|
||||
289 : PRBS OK!has been unlocked since last call
|
||||
290 : PRBS OK!has been unlocked since last call
|
||||
291 : PRBS OK!has been unlocked since last call
|
||||
292 : PRBS OK!has been unlocked since last call
|
||||
293 : PRBS OK!has been unlocked since last call
|
||||
294 : PRBS OK!has been unlocked since last call
|
||||
295 : PRBS OK!has been unlocked since last call
|
||||
306 : PRBS OK!has been unlocked since last call
|
||||
307 : PRBS OK!has been unlocked since last call
|
||||
308 : PRBS OK!has been unlocked since last call
|
||||
310 : PRBS OK!has been unlocked since last call
|
||||
311 : PRBS OK!has been unlocked since last call
|
||||
312 : PRBS OK!has been unlocked since last call
|
||||
313 : PRBS OK!has been unlocked since last call
|
||||
324 : PRBS OK!has been unlocked since last call
|
||||
325 : PRBS OK!has been unlocked since last call
|
||||
326 : PRBS OK!has been unlocked since last call
|
||||
327 : PRBS OK!has been unlocked since last call
|
||||
342 : PRBS OK!has been unlocked since last call
|
||||
343 : PRBS OK!has been unlocked since last call
|
||||
344 : PRBS OK!has been unlocked since last call
|
||||
345 : PRBS OK!has been unlocked since last call
|
||||
346 : PRBS OK!has been unlocked since last call
|
||||
347 : PRBS OK!has been unlocked since last call
|
||||
348 : PRBS OK!has been unlocked since last call
|
||||
349 : PRBS OK!has been unlocked since last call
|
||||
360 : PRBS OK!has been unlocked since last call
|
||||
361 : PRBS OK!has been unlocked since last call
|
||||
362 : PRBS OK!has been unlocked since last call
|
||||
363 : PRBS OK!has been unlocked since last call
|
||||
364 : PRBS OK!has been unlocked since last call
|
||||
365 : PRBS OK!has been unlocked since last call
|
||||
366 : PRBS OK!has been unlocked since last call
|
||||
367 : PRBS OK!has been unlocked since last call
|
||||
378 : PRBS OK!has been unlocked since last call
|
||||
379 : PRBS OK!has been unlocked since last call
|
||||
380 : PRBS OK!has been unlocked since last call
|
||||
382 : PRBS OK!has been unlocked since last call
|
||||
383 : PRBS OK!has been unlocked since last call
|
||||
384 : PRBS OK!has been unlocked since last call
|
||||
385 : PRBS OK!has been unlocked since last call
|
||||
396 : PRBS OK!has been unlocked since last call
|
||||
397 : PRBS OK!has been unlocked since last call
|
||||
398 : PRBS OK!has been unlocked since last call
|
||||
399 : PRBS OK!has been unlocked since last call
|
||||
414 : PRBS OK!has been unlocked since last call
|
||||
415 : PRBS OK!has been unlocked since last call
|
||||
416 : PRBS OK!has been unlocked since last call
|
||||
417 : PRBS OK!has been unlocked since last call
|
||||
418 : PRBS OK!has been unlocked since last call
|
||||
419 : PRBS OK!has been unlocked since last call
|
||||
420 : PRBS OK!has been unlocked since last call
|
||||
421 : PRBS OK!has been unlocked since last call
|
||||
432 : PRBS OK!has been unlocked since last call
|
||||
433 : PRBS OK!has been unlocked since last call
|
||||
434 : PRBS OK!has been unlocked since last call
|
||||
435 : PRBS OK!has been unlocked since last call
|
||||
436 : PRBS OK!has been unlocked since last call
|
||||
437 : PRBS OK!has been unlocked since last call
|
||||
438 : PRBS OK!has been unlocked since last call
|
||||
439 : PRBS OK!has been unlocked since last call
|
||||
450 : PRBS OK!has been unlocked since last call
|
||||
451 : PRBS OK!has been unlocked since last call
|
||||
452 : PRBS OK!has been unlocked since last call
|
||||
454 : PRBS OK!has been unlocked since last call
|
||||
455 : PRBS OK!has been unlocked since last call
|
||||
456 : PRBS OK!has been unlocked since last call
|
||||
457 : PRBS OK!has been unlocked since last call
|
||||
468 : PRBS OK!has been unlocked since last call
|
||||
469 : PRBS OK!has been unlocked since last call
|
||||
470 : PRBS OK!has been unlocked since last call
|
||||
471 : PRBS OK!has been unlocked since last call
|
||||
486 : PRBS OK!has been unlocked since last call
|
||||
487 : PRBS OK!has been unlocked since last call
|
||||
488 : PRBS OK!has been unlocked since last call
|
||||
489 : PRBS OK!has been unlocked since last call
|
||||
490 : PRBS OK!has been unlocked since last call
|
||||
491 : PRBS OK!has been unlocked since last call
|
||||
492 : PRBS OK!has been unlocked since last call
|
||||
493 : PRBS OK!has been unlocked since last call
|
||||
504 : PRBS OK!has been unlocked since last call
|
||||
505 : PRBS OK!has been unlocked since last call
|
||||
506 : PRBS OK!has been unlocked since last call
|
||||
507 : PRBS OK!has been unlocked since last call
|
||||
508 : PRBS OK!has been unlocked since last call
|
||||
509 : PRBS OK!has been unlocked since last call
|
||||
510 : PRBS OK!has been unlocked since last call
|
||||
511 : PRBS OK!has been unlocked since last call
|
||||
522 : PRBS OK!has been unlocked since last call
|
||||
523 : PRBS OK!has been unlocked since last call
|
||||
524 : PRBS OK!has been unlocked since last call
|
||||
526 : PRBS OK!has been unlocked since last call
|
||||
527 : PRBS OK!has been unlocked since last call
|
||||
528 : PRBS OK!has been unlocked since last call
|
||||
529 : PRBS OK!has been unlocked since last call
|
||||
540 : PRBS OK!has been unlocked since last call
|
||||
541 : PRBS OK!has been unlocked since last call
|
||||
542 : PRBS OK!has been unlocked since last call
|
||||
543 : PRBS OK!has been unlocked since last call
|
||||
558 : PRBS OK!has been unlocked since last call
|
||||
559 : PRBS OK!has been unlocked since last call
|
||||
560 : PRBS OK!has been unlocked since last call
|
||||
561 : PRBS OK!has been unlocked since last call
|
||||
562 : PRBS OK!has been unlocked since last call
|
||||
563 : PRBS OK!has been unlocked since last call
|
||||
564 : PRBS OK!has been unlocked since last call
|
||||
565 : PRBS OK!has been unlocked since last call
|
||||
drivshell>
|
||||
root@sonic:~#
|
||||
root@sonic:~#
|
||||
root@sonic:~#
|
||||
root@sonic:~# bcmcmd -n 0 -c " dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbssat STArt Interval=30' "
|
||||
dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbsstat STArt Interval=30'
|
||||
PRBSStat thread started ...
|
||||
drivshell>
|
||||
root@sonic:~# sleep 30
|
||||
root@sonic:~# bcmcmd -n 0 -c " dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbsstat Ber' "
|
||||
dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbsstat Ber'
|
||||
port BER
|
||||
====
|
||||
1[0] : 3.53e-11
|
||||
1[1] : 4.00e-11
|
||||
====
|
||||
2[0] : 1.64e-10
|
||||
2[1] : 8.80e-11
|
||||
====
|
||||
3[0] : 6.01e-11
|
||||
3[1] : 3.45e-12
|
||||
====
|
||||
4[0] : 7.69e-11
|
||||
4[1] : 2.60e-11
|
||||
====
|
||||
5[0] : 9.41e-13
|
||||
5[1] : 6.27e-13
|
||||
====
|
||||
6[0] : 3.14e-13
|
||||
6[1] : 6.27e-13
|
||||
====
|
||||
7[0] : 2.98e-12
|
||||
7[1] : 2.20e-12
|
||||
====
|
||||
8[0] : 4.24e-12
|
||||
8[1] : 9.41e-13
|
||||
====
|
||||
18[0] : 7.84e-13
|
||||
18[1] : 2.04e-12
|
||||
====
|
||||
19[0] : 1.57e-13
|
||||
19[1] : 1.73e-12
|
||||
====
|
||||
20[0] : 1.19e-11
|
||||
20[1] : 1.41e-12
|
||||
====
|
||||
21[0] : 5.65e-12
|
||||
21[1] : 7.69e-12
|
||||
====
|
||||
22[0] : 1.54e-11
|
||||
22[1] : 7.84e-13
|
||||
====
|
||||
23[0] : 1.10e-12
|
||||
23[1] : 2.35e-12
|
||||
====
|
||||
24[0] : 2.51e-12
|
||||
24[1] : 1.41e-12
|
||||
====
|
||||
40[0] : 2.23e-11
|
||||
40[1] : 2.35e-11
|
||||
====
|
||||
41[0] : 3.76e-12
|
||||
41[1] : 4.55e-12
|
||||
====
|
||||
42[0] : 7.84e-12
|
||||
42[1] : 3.76e-12
|
||||
====
|
||||
43[0] : 5.02e-12
|
||||
43[1] : 1.35e-11
|
||||
====
|
||||
54[0] : 7.84e-13
|
||||
54[1] : 6.27e-13
|
||||
====
|
||||
55[0] : 1.57e-13
|
||||
55[1] : 1.57e-13
|
||||
====
|
||||
56[0] : 3.14e-13
|
||||
56[1] : 4.71e-13
|
||||
====
|
||||
57[0] : 4.71e-12
|
||||
57[1] : 6.27e-13
|
||||
====
|
||||
58[0] : 5.80e-12
|
||||
58[1] : 4.24e-11
|
||||
====
|
||||
59[0] : 6.90e-12
|
||||
59[1] : 7.84e-13
|
||||
====
|
||||
60[0] : 1.13e-11
|
||||
60[1] : 1.10e-12
|
||||
====
|
||||
61[0] : 2.35e-12
|
||||
61[1] : 5.49e-12
|
||||
====
|
||||
72[0] : 4.39e-11
|
||||
72[1] : 5.49e-12
|
||||
====
|
||||
73[0] : 7.22e-12
|
||||
73[1] : 8.00e-12
|
||||
====
|
||||
74[0] : 3.29e-12
|
||||
74[1] : 1.25e-12
|
||||
====
|
||||
75[0] : 5.96e-12
|
||||
75[1] : 3.45e-12
|
||||
====
|
||||
76[0] : 1.57e-13
|
||||
76[1] : 1.41e-12
|
||||
====
|
||||
77[0] : 2.20e-12
|
||||
77[1] : 1.57e-13
|
||||
====
|
||||
78[0] : 2.67e-12
|
||||
78[1] : 1.41e-12
|
||||
====
|
||||
79[0] : 6.27e-13
|
||||
79[1] : 3.14e-13
|
||||
====
|
||||
90[0] : 3.61e-12
|
||||
90[1] : 1.91e-11
|
||||
====
|
||||
91[0] : 1.88e-12
|
||||
91[1] : 4.24e-12
|
||||
====
|
||||
92[0] : 8.47e-12
|
||||
92[1] : 4.08e-12
|
||||
====
|
||||
93[0] : 3.92e-12
|
||||
93[1] : 1.82e-11
|
||||
====
|
||||
94[0] : 1.57e-13
|
||||
94[1] : 1.41e-12
|
||||
====
|
||||
95[0] : 1.57e-13
|
||||
95[1] : 1.57e-13
|
||||
====
|
||||
96[0] : 1.57e-13
|
||||
96[1] : 4.71e-13
|
||||
====
|
||||
112[0] : 4.08e-12
|
||||
112[1] : 2.04e-12
|
||||
====
|
||||
113[0] : 4.08e-12
|
||||
113[1] : 3.29e-12
|
||||
====
|
||||
114[0] : 7.84e-13
|
||||
114[1] : 9.41e-13
|
||||
====
|
||||
115[0] : 6.27e-13
|
||||
115[1] : 1.88e-12
|
||||
====
|
||||
126[0] : 2.82e-12
|
||||
126[1] : 1.57e-13
|
||||
====
|
||||
127[0] : 1.57e-13
|
||||
127[1] : 4.71e-13
|
||||
====
|
||||
128[0] : 3.45e-12
|
||||
128[1] : 3.14e-13
|
||||
====
|
||||
129[0] : 4.71e-13
|
||||
129[1] : 6.27e-13
|
||||
====
|
||||
130[0] : 2.67e-12
|
||||
130[1] : 1.57e-12
|
||||
====
|
||||
131[0] : 2.35e-12
|
||||
131[1] : 6.12e-12
|
||||
====
|
||||
132[0] : 3.33e-11
|
||||
132[1] : 5.02e-12
|
||||
====
|
||||
133[0] : 9.88e-12
|
||||
133[1] : 6.90e-12
|
||||
====
|
||||
144[0] : 7.84e-13
|
||||
144[1] : 7.22e-12
|
||||
====
|
||||
145[0] : 3.29e-12
|
||||
145[1] : 6.12e-12
|
||||
====
|
||||
146[0] : 1.02e-11
|
||||
146[1] : 1.57e-12
|
||||
====
|
||||
147[0] : 1.57e-12
|
||||
147[1] : 3.92e-12
|
||||
====
|
||||
148[0] : 1.57e-13
|
||||
148[1] : 1.25e-12
|
||||
====
|
||||
149[0] : 1.57e-13
|
||||
149[1] : 1.57e-13
|
||||
====
|
||||
150[0] : 6.27e-13
|
||||
150[1] : 1.57e-13
|
||||
====
|
||||
151[0] : 6.27e-13
|
||||
151[1] : 3.14e-13
|
||||
====
|
||||
162[0] : 1.57e-13
|
||||
162[1] : 6.27e-13
|
||||
====
|
||||
163[0] : 3.14e-13
|
||||
163[1] : 1.57e-12
|
||||
====
|
||||
164[0] : 1.25e-12
|
||||
164[1] : 2.20e-12
|
||||
====
|
||||
165[0] : 4.71e-13
|
||||
165[1] : 2.67e-12
|
||||
====
|
||||
166[0] : 1.57e-13
|
||||
166[1] : 3.14e-13
|
||||
====
|
||||
167[0] : 1.57e-13
|
||||
167[1] : 1.57e-12
|
||||
====
|
||||
168[0] : 4.71e-13
|
||||
168[1] : 1.57e-13
|
||||
====
|
||||
184[0] : 4.11e-10
|
||||
184[1] : 3.12e-10
|
||||
====
|
||||
185[0] : 1.71e-08
|
||||
185[1] : 3.13e-09
|
||||
====
|
||||
186[0] : 2.05e-10
|
||||
186[1] : 2.27e-09
|
||||
====
|
||||
187[0] : 3.94e-11
|
||||
187[1] : 2.97e-09
|
||||
====
|
||||
198[0] : 3.44e-11
|
||||
198[1] : 3.29e-11
|
||||
====
|
||||
199[0] : 7.53e-10
|
||||
199[1] : 1.66e-10
|
||||
====
|
||||
200[0] : 4.38e-11
|
||||
200[1] : 3.81e-11
|
||||
====
|
||||
201[0] : 5.43e-11
|
||||
201[1] : 1.95e-11
|
||||
====
|
||||
202[0] : 1.82e-10
|
||||
202[1] : 5.74e-09
|
||||
====
|
||||
203[0] : 1.98e-08
|
||||
203[1] : 5.05e-09
|
||||
====
|
||||
204[0] : 2.09e-10
|
||||
204[1] : 5.71e-11
|
||||
====
|
||||
205[0] : 6.59e-11
|
||||
205[1] : 5.21e-11
|
||||
====
|
||||
216[0] : 4.71e-13
|
||||
216[1] : 6.27e-13
|
||||
====
|
||||
217[0] : 1.57e-12
|
||||
217[1] : 6.27e-13
|
||||
====
|
||||
218[0] : 3.14e-13
|
||||
218[1] : 1.57e-13
|
||||
====
|
||||
219[0] : 1.41e-12
|
||||
219[1] : 1.41e-12
|
||||
====
|
||||
220[0] : 1.57e-13
|
||||
220[1] : 1.57e-13
|
||||
====
|
||||
221[0] : 1.57e-13
|
||||
221[1] : 1.57e-13
|
||||
====
|
||||
222[0] : 1.57e-13
|
||||
222[1] : 3.14e-13
|
||||
====
|
||||
223[0] : 9.41e-13
|
||||
223[1] : 1.57e-13
|
||||
====
|
||||
234[0] : 1.57e-13
|
||||
234[1] : 4.71e-13
|
||||
====
|
||||
235[0] : 3.14e-13
|
||||
235[1] : 1.25e-12
|
||||
====
|
||||
236[0] : 4.71e-13
|
||||
236[1] : 1.57e-13
|
||||
====
|
||||
237[0] : 3.14e-13
|
||||
237[1] : 1.57e-13
|
||||
====
|
||||
238[0] : 1.57e-13
|
||||
238[1] : 1.57e-13
|
||||
====
|
||||
239[0] : 3.14e-13
|
||||
239[1] : 3.14e-13
|
||||
====
|
||||
240[0] : 2.35e-12
|
||||
240[1] : 1.57e-13
|
||||
====
|
||||
256[0] : 4.24e-12
|
||||
256[1] : 7.37e-12
|
||||
====
|
||||
257[0] : 4.71e-13
|
||||
257[1] : 7.69e-12
|
||||
====
|
||||
258[0] : 1.09e-09
|
||||
258[1] : 6.25e-09
|
||||
====
|
||||
259[0] : 1.66e-11
|
||||
259[1] : 1.02e-10
|
||||
====
|
||||
270[0] : 1.10e-12
|
||||
270[1] : 9.25e-12
|
||||
====
|
||||
271[0] : 5.33e-12
|
||||
271[1] : 1.62e-11
|
||||
====
|
||||
272[0] : 1.37e-10
|
||||
272[1] : 9.15e-10
|
||||
====
|
||||
273[0] : 9.41e-12
|
||||
273[1] : 1.90e-11
|
||||
====
|
||||
274[0] : 1.57e-13
|
||||
274[1] : 2.04e-12
|
||||
====
|
||||
275[0] : 1.73e-12
|
||||
275[1] : 2.20e-12
|
||||
====
|
||||
276[0] : 1.30e-10
|
||||
276[1] : 1.36e-10
|
||||
====
|
||||
277[0] : 1.41e-12
|
||||
277[1] : 2.04e-12
|
||||
====
|
||||
288[0] : 4.71e-13
|
||||
288[1] : 4.71e-13
|
||||
====
|
||||
289[0] : 3.14e-13
|
||||
289[1] : 2.20e-12
|
||||
====
|
||||
290[0] : 3.14e-13
|
||||
290[1] : 1.57e-13
|
||||
====
|
||||
291[0] : 3.29e-11
|
||||
291[1] : 1.08e-11
|
||||
====
|
||||
292[0] : 3.14e-13
|
||||
292[1] : 6.27e-13
|
||||
====
|
||||
293[0] : 1.57e-13
|
||||
293[1] : 5.80e-12
|
||||
====
|
||||
294[0] : 5.96e-12
|
||||
294[1] : 1.88e-12
|
||||
====
|
||||
295[0] : 1.27e-11
|
||||
295[1] : 1.21e-11
|
||||
====
|
||||
306[0] : 4.71e-13
|
||||
306[1] : 1.10e-12
|
||||
====
|
||||
307[0] : 7.84e-13
|
||||
307[1] : 5.02e-12
|
||||
====
|
||||
308[0] : 3.92e-12
|
||||
308[1] : 2.67e-12
|
||||
====
|
||||
310[0] : 3.92e-12
|
||||
310[1] : 1.25e-12
|
||||
====
|
||||
311[0] : 2.51e-12
|
||||
311[1] : 6.27e-13
|
||||
====
|
||||
312[0] : 2.20e-12
|
||||
312[1] : 6.75e-12
|
||||
====
|
||||
313[0] : 5.43e-11
|
||||
313[1] : 2.18e-10
|
||||
====
|
||||
324[0] : 1.46e-11
|
||||
324[1] : 1.27e-11
|
||||
====
|
||||
325[0] : 2.67e-12
|
||||
325[1] : 7.94e-11
|
||||
====
|
||||
326[0] : 5.35e-11
|
||||
326[1] : 2.35e-12
|
||||
====
|
||||
327[0] : 7.15e-11
|
||||
327[1] : 1.11e-11
|
||||
====
|
||||
342[0] : 2.04e-12
|
||||
342[1] : 1.41e-12
|
||||
====
|
||||
343[0] : 3.14e-13
|
||||
343[1] : 3.61e-12
|
||||
====
|
||||
344[0] : 1.41e-12
|
||||
344[1] : 1.57e-13
|
||||
====
|
||||
345[0] : 1.25e-12
|
||||
345[1] : 1.41e-12
|
||||
====
|
||||
346[0] : 3.14e-13
|
||||
346[1] : 1.57e-13
|
||||
====
|
||||
347[0] : 1.57e-13
|
||||
347[1] : 3.14e-13
|
||||
====
|
||||
348[0] : 1.57e-13
|
||||
348[1] : 3.14e-13
|
||||
====
|
||||
349[0] : 1.73e-12
|
||||
349[1] : 2.21e-11
|
||||
====
|
||||
360[0] : 8.78e-12
|
||||
360[1] : 1.24e-11
|
||||
====
|
||||
361[0] : 7.22e-12
|
||||
361[1] : 1.87e-11
|
||||
====
|
||||
362[0] : 1.30e-11
|
||||
362[1] : 1.74e-11
|
||||
====
|
||||
363[0] : 1.51e-10
|
||||
363[1] : 2.85e-11
|
||||
====
|
||||
364[0] : 1.38e-11
|
||||
364[1] : 1.17e-10
|
||||
====
|
||||
365[0] : 3.95e-11
|
||||
365[1] : 2.67e-12
|
||||
====
|
||||
366[0] : 4.24e-12
|
||||
366[1] : 5.49e-12
|
||||
====
|
||||
367[0] : 1.71e-10
|
||||
367[1] : 1.40e-11
|
||||
====
|
||||
378[0] : 1.41e-11
|
||||
378[1] : 3.50e-11
|
||||
====
|
||||
379[0] : 7.67e-11
|
||||
379[1] : 1.03e-09
|
||||
====
|
||||
380[0] : 2.16e-11
|
||||
380[1] : 1.62e-11
|
||||
====
|
||||
382[0] : 4.35e-11
|
||||
382[1] : 1.81e-10
|
||||
====
|
||||
383[0] : 2.28e-10
|
||||
383[1] : 1.41e-10
|
||||
====
|
||||
384[0] : 7.22e-12
|
||||
384[1] : 5.71e-11
|
||||
====
|
||||
385[0] : 3.36e-11
|
||||
385[1] : 2.16e-11
|
||||
====
|
||||
396[0] : 2.82e-12
|
||||
396[1] : 4.55e-12
|
||||
====
|
||||
397[0] : 1.27e-11
|
||||
397[1] : 1.41e-11
|
||||
====
|
||||
398[0] : 2.99e-10
|
||||
398[1] : 5.80e-11
|
||||
====
|
||||
399[0] : 2.51e-11
|
||||
399[1] : 1.11e-11
|
||||
====
|
||||
414[0] : 4.55e-12
|
||||
414[1] : 8.31e-12
|
||||
====
|
||||
415[0] : 1.57e-13
|
||||
415[1] : 9.41e-13
|
||||
====
|
||||
416[0] : 6.27e-12
|
||||
416[1] : 5.96e-12
|
||||
====
|
||||
417[0] : 2.20e-12
|
||||
417[1] : 1.88e-12
|
||||
====
|
||||
418[0] : 6.27e-13
|
||||
418[1] : 1.25e-12
|
||||
====
|
||||
419[0] : 1.57e-13
|
||||
419[1] : 1.41e-12
|
||||
====
|
||||
420[0] : 3.14e-13
|
||||
420[1] : 2.82e-12
|
||||
====
|
||||
421[0] : 4.39e-12
|
||||
421[1] : 1.16e-11
|
||||
====
|
||||
432[0] : 4.71e-13
|
||||
432[1] : 6.27e-13
|
||||
====
|
||||
433[0] : 4.71e-13
|
||||
433[1] : 1.57e-12
|
||||
====
|
||||
434[0] : 4.71e-13
|
||||
434[1] : 1.57e-13
|
||||
====
|
||||
435[0] : 1.25e-12
|
||||
435[1] : 1.57e-13
|
||||
====
|
||||
436[0] : 1.57e-13
|
||||
436[1] : 1.57e-13
|
||||
====
|
||||
437[0] : 1.57e-13
|
||||
437[1] : 4.71e-13
|
||||
====
|
||||
438[0] : 7.84e-13
|
||||
438[1] : 1.41e-12
|
||||
====
|
||||
439[0] : 1.41e-12
|
||||
439[1] : 1.10e-12
|
||||
====
|
||||
450[0] : 6.27e-13
|
||||
450[1] : 4.71e-13
|
||||
====
|
||||
451[0] : 1.57e-13
|
||||
451[1] : 1.25e-12
|
||||
====
|
||||
452[0] : 1.10e-12
|
||||
452[1] : 7.84e-13
|
||||
====
|
||||
454[0] : 1.10e-12
|
||||
454[1] : 1.88e-12
|
||||
====
|
||||
455[0] : 6.27e-13
|
||||
455[1] : 1.57e-12
|
||||
====
|
||||
456[0] : 1.88e-12
|
||||
456[1] : 9.41e-13
|
||||
====
|
||||
457[0] : 7.84e-13
|
||||
457[1] : 4.71e-13
|
||||
====
|
||||
468[0] : 6.27e-13
|
||||
468[1] : 9.41e-13
|
||||
====
|
||||
469[0] : 2.67e-12
|
||||
469[1] : 4.08e-12
|
||||
====
|
||||
470[0] : 3.14e-13
|
||||
470[1] : 4.71e-13
|
||||
====
|
||||
471[0] : 3.14e-13
|
||||
471[1] : 7.84e-13
|
||||
====
|
||||
486[0] : 1.73e-12
|
||||
486[1] : 1.57e-12
|
||||
====
|
||||
487[0] : 1.10e-12
|
||||
487[1] : 2.82e-12
|
||||
====
|
||||
488[0] : 4.71e-13
|
||||
488[1] : 4.71e-13
|
||||
====
|
||||
489[0] : 9.41e-13
|
||||
489[1] : 3.14e-13
|
||||
====
|
||||
490[0] : 1.57e-13
|
||||
490[1] : 3.14e-13
|
||||
====
|
||||
491[0] : 3.14e-13
|
||||
491[1] : 1.57e-13
|
||||
====
|
||||
492[0] : 9.41e-13
|
||||
492[1] : 1.10e-12
|
||||
====
|
||||
493[0] : 7.84e-13
|
||||
493[1] : 2.98e-12
|
||||
====
|
||||
504[0] : 4.71e-13
|
||||
504[1] : 3.14e-13
|
||||
====
|
||||
505[0] : 1.57e-13
|
||||
505[1] : 7.84e-13
|
||||
====
|
||||
506[0] : 4.71e-13
|
||||
506[1] : 1.57e-13
|
||||
====
|
||||
507[0] : 3.14e-13
|
||||
507[1] : 1.57e-13
|
||||
====
|
||||
508[0] : 2.04e-12
|
||||
508[1] : 1.41e-12
|
||||
====
|
||||
509[0] : 9.41e-13
|
||||
509[1] : 7.84e-13
|
||||
====
|
||||
510[0] : 1.57e-13
|
||||
510[1] : 6.27e-13
|
||||
====
|
||||
511[0] : 6.27e-13
|
||||
511[1] : 4.71e-13
|
||||
====
|
||||
522[0] : 2.35e-12
|
||||
522[1] : 1.57e-13
|
||||
====
|
||||
523[0] : 3.14e-13
|
||||
523[1] : 6.27e-13
|
||||
====
|
||||
524[0] : 7.84e-13
|
||||
524[1] : 1.57e-13
|
||||
====
|
||||
526[0] : 7.84e-13
|
||||
526[1] : 3.14e-13
|
||||
====
|
||||
527[0] : 1.41e-12
|
||||
527[1] : 4.71e-13
|
||||
====
|
||||
528[0] : 3.14e-13
|
||||
528[1] : 9.41e-13
|
||||
====
|
||||
529[0] : 4.71e-13
|
||||
529[1] : 1.57e-13
|
||||
====
|
||||
540[0] : 6.27e-13
|
||||
540[1] : 1.25e-12
|
||||
====
|
||||
541[0] : 3.14e-13
|
||||
541[1] : 1.10e-12
|
||||
====
|
||||
542[0] : 2.98e-12
|
||||
542[1] : 6.27e-13
|
||||
====
|
||||
543[0] : 2.98e-12
|
||||
543[1] : 3.14e-13
|
||||
====
|
||||
558[0] : 9.41e-13
|
||||
558[1] : 1.10e-12
|
||||
====
|
||||
559[0] : 3.29e-12
|
||||
559[1] : 2.04e-12
|
||||
====
|
||||
560[0] : 1.57e-13
|
||||
560[1] : 1.57e-13
|
||||
====
|
||||
561[0] : 2.35e-12
|
||||
561[1] : 4.71e-13
|
||||
====
|
||||
562[0] : 1.57e-13
|
||||
562[1] : 1.57e-13
|
||||
====
|
||||
563[0] : 1.57e-13
|
||||
563[1] : 4.71e-13
|
||||
====
|
||||
564[0] : 1.41e-12
|
||||
564[1] : 7.84e-13
|
||||
====
|
||||
565[0] : 4.55e-12
|
||||
565[1] : 1.57e-13
|
||||
====
|
||||
drivshell>
|
||||
root@sonic:~# bcmcmd -n 0 -c " dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbssat STOp' "
|
||||
dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbsstat STOp'
|
||||
Stopping PRBSStat thread
|
||||
drivshell>
|
||||
root@sonic:~# bcmcmd -n 0 -c " dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbs clear' "
|
||||
dsh -c 'phydiag 1-24,40-96,112-168,184-240,256-259,270-308,310-327,342-380,382-399,414-452,454-471,486-524,526-543,558-565 prbs clear'
|
||||
drivshell>
|
||||
root@sonic:~#
|
||||
@@ -0,0 +1,40 @@
|
||||
SWB0_0V9_ANLG0
|
||||
SWB0_0V9_ANLG1
|
||||
SWB0_0V75_ANLG0
|
||||
SWB0_0V75_ANLG1
|
||||
SWB0_PHYTILE_P0
|
||||
SWB0_PHYTILE_P1
|
||||
SWB0_PHYTILE_P2
|
||||
SWB0_PHYTILE_P3
|
||||
SWB0_PHYTILE_P4
|
||||
SWB0_PHYTILE_P5
|
||||
SWB0_PHYTILE_P6
|
||||
SWB0_PHYTILE_P7
|
||||
SWB0_PVDD1V5_CNDR0
|
||||
SWB0_PVDD1V5_CNDR1
|
||||
SWB0_PVDDA_PHYT0
|
||||
SWB0_PVDDA_PHYT1
|
||||
SWB0_PVDDA_PHYT2
|
||||
SWB0_PVDDA_PHYT3
|
||||
SWB0_TH6_CORE
|
||||
|
||||
|
||||
SWB1_0V9_ANLG0
|
||||
SWB1_0V9_ANLG1
|
||||
SWB1_0V75_ANLG0
|
||||
SWB1_0V75_ANLG1
|
||||
SWB1_PHYTILE_P0
|
||||
SWB1_PHYTILE_P1
|
||||
SWB1_PHYTILE_P2
|
||||
SWB1_PHYTILE_P3
|
||||
SWB1_PHYTILE_P4
|
||||
SWB1_PHYTILE_P5
|
||||
SWB1_PHYTILE_P6
|
||||
SWB1_PHYTILE_P7
|
||||
SWB1_PVDD1V5_CNDR0
|
||||
SWB1_PVDD1V5_CNDR1
|
||||
SWB1_PVDDA_PHYT0
|
||||
SWB1_PVDDA_PHYT1
|
||||
SWB1_PVDDA_PHYT2
|
||||
SWB1_PVDDA_PHYT3
|
||||
SWB1_TH6_CORE
|
||||
@@ -0,0 +1,188 @@
|
||||
//0.900V (nominal)
|
||||
i2cset -f -y 13 0x25 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x25 0x21 0x83 0x00
|
||||
i2cset -f -y 13 0x25 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x25 0x0D 0x74 0x10
|
||||
//0.900V (nominal)
|
||||
i2cset -f -y 15 0x26 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x26 0x21 0x83 0x00
|
||||
i2cset -f -y 15 0x26 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x26 0x0D 0x74 0x10
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 13 0x25 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x25 0x21 0x65 0x00
|
||||
i2cset -f -y 13 0x25 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x25 0x1D 0x5A 0x06
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 15 0x26 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x26 0x21 0x65 0x00
|
||||
i2cset -f -y 15 0x26 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x26 0x1D 0x5A 0x06
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 13 0x21 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x21 0x21 0x65 0x00
|
||||
i2cset -f -y 13 0x21 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x21 0x0D 0xB2 0x0C
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 13 0x21 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x21 0x21 0x65 0x00
|
||||
i2cset -f -y 13 0x21 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x21 0x1D 0x5A 0x06
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 13 0x22 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x22 0x21 0x65 0x00
|
||||
i2cset -f -y 13 0x22 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x22 0x0D 0xB2 0x0C
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 13 0x22 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x22 0x21 0x65 0x00
|
||||
i2cset -f -y 13 0x22 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x22 0x1D 0x5A 0x06
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 15 0x23 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x23 0x21 0x65 0x00
|
||||
i2cset -f -y 15 0x23 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x23 0x0D 0xB2 0x0C
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 15 0x23 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x23 0x21 0x65 0x00
|
||||
i2cset -f -y 15 0x23 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x23 0x1D 0x5A 0x06
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 15 0x24 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x24 0x21 0x65 0x00
|
||||
i2cset -f -y 15 0x24 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x24 0x0D 0xB2 0x0C
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 15 0x24 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x24 0x21 0x65 0x00
|
||||
i2cset -f -y 15 0x24 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x24 0x1D 0x5A 0x06
|
||||
//1.5V (nominal)
|
||||
i2cset -f -y 13 0x29 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x29 0x21 0xFB 0x00
|
||||
i2cset -f -y 13 0x29 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x29 0x0D 0x71 0x1F
|
||||
//1.5V (nominal)
|
||||
i2cset -f -y 13 0x29 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x29 0x21 0xFB 0x00
|
||||
i2cset -f -y 13 0x29 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x29 0x1D 0xB9 0x0F
|
||||
//0.720V
|
||||
i2cset -f -y 13 0x27 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x27 0x21 0x5F 0x00
|
||||
i2cset -f -y 13 0x27 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x27 0x0D 0xF4 0x0B
|
||||
//0.720V
|
||||
i2cset -f -y 13 0x27 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x27 0x21 0x5F 0x00
|
||||
i2cset -f -y 13 0x27 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x27 0x1D 0xFC 0x05
|
||||
//0.720V
|
||||
i2cset -f -y 15 0x28 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x28 0x21 0x5F 0x00
|
||||
i2cset -f -y 15 0x28 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x28 0x0D 0xF4 0x0B
|
||||
//0.720V
|
||||
i2cset -f -y 15 0x28 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x28 0x21 0x5F 0x00
|
||||
i2cset -f -y 15 0x28 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x28 0x1D 0xFC 0x05
|
||||
//0.8V(nominal) , 0.8591V with load line
|
||||
i2cset -f -y 13 0x20 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x20 0x21 0x57 0x01
|
||||
|
||||
|
||||
//0.900V (nominal)
|
||||
i2cset -f -y 14 0x25 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x25 0x21 0x83 0x00
|
||||
i2cset -f -y 14 0x25 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x25 0x0D 0x74 0x10
|
||||
//0.900V (nominal)
|
||||
i2cset -f -y 16 0x26 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x26 0x21 0x83 0x00
|
||||
i2cset -f -y 16 0x26 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x26 0x0D 0x74 0x10
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 14 0x25 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x25 0x21 0x65 0x00
|
||||
i2cset -f -y 14 0x25 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x25 0x1D 0x5A 0x06
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 16 0x26 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x26 0x21 0x65 0x00
|
||||
i2cset -f -y 16 0x26 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x26 0x1D 0x5A 0x06
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 14 0x21 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x21 0x21 0x65 0x00
|
||||
i2cset -f -y 14 0x21 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x21 0x0D 0xB2 0x0C
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 14 0x21 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x21 0x21 0x65 0x00
|
||||
i2cset -f -y 14 0x21 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x21 0x1D 0x5A 0x06
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 14 0x22 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x22 0x21 0x65 0x00
|
||||
i2cset -f -y 14 0x22 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x22 0x0D 0xB2 0x0C
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 14 0x22 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x22 0x21 0x65 0x00
|
||||
i2cset -f -y 14 0x22 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x22 0x1D 0x5A 0x06
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 16 0x23 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x23 0x21 0x65 0x00
|
||||
i2cset -f -y 16 0x23 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x23 0x0D 0xB2 0x0C
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 16 0x23 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x23 0x21 0x65 0x00
|
||||
i2cset -f -y 16 0x23 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x23 0x1D 0x5A 0x06
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 16 0x24 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x24 0x21 0x65 0x00
|
||||
i2cset -f -y 16 0x24 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x24 0x0D 0xB2 0x0C
|
||||
//0.75V (nominal)
|
||||
i2cset -f -y 16 0x24 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x24 0x21 0x65 0x00
|
||||
i2cset -f -y 16 0x24 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x24 0x1D 0x5A 0x06
|
||||
//1.5V (nominal)
|
||||
i2cset -f -y 14 0x29 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x29 0x21 0xFB 0x00
|
||||
i2cset -f -y 14 0x29 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x29 0x0D 0x71 0x1F
|
||||
//1.5V (nominal)
|
||||
i2cset -f -y 14 0x29 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x29 0x21 0xFB 0x00
|
||||
i2cset -f -y 14 0x29 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x29 0x1D 0xB9 0x0F
|
||||
//0.720V (nominal)
|
||||
i2cset -f -y 14 0x27 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x27 0x21 0x5F 0x00
|
||||
i2cset -f -y 14 0x27 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x27 0x0D 0xF4 0x0B
|
||||
//0.720V (nominal)
|
||||
i2cset -f -y 14 0x27 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x27 0x21 0x5F 0x00
|
||||
i2cset -f -y 14 0x27 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x27 0x1D 0xFC 0x05
|
||||
//0.720V (nominal)
|
||||
i2cset -f -y 16 0x28 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x28 0x21 0x5F 0x00
|
||||
i2cset -f -y 16 0x28 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x28 0x0D 0xF4 0x0B
|
||||
//0.720V (nominal)
|
||||
i2cset -f -y 16 0x28 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x28 0x21 0x5F 0x00
|
||||
i2cset -f -y 16 0x28 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x28 0x1D 0xFC 0x05
|
||||
//0.8V(nominal) , 0.8591V with load line
|
||||
i2cset -f -y 14 0x20 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x20 0x21 0x57 0x01
|
||||
@@ -0,0 +1,48 @@
|
||||
i2cset -f -y 13 0x25 0x00 0
|
||||
i2cset -f -y 13 0x25 0x15
|
||||
i2cset -f -y 15 0x26 0x00 0
|
||||
i2cset -f -y 15 0x26 0x15
|
||||
i2cset -f -y 13 0x25 0x00 0
|
||||
i2cset -f -y 13 0x25 0x15
|
||||
i2cset -f -y 15 0x26 0x00 0
|
||||
i2cset -f -y 15 0x26 0x15
|
||||
i2cset -f -y 13 0x21 0x00 0
|
||||
i2cset -f -y 13 0x21 0x15
|
||||
i2cset -f -y 13 0x22 0x00 0
|
||||
i2cset -f -y 13 0x22 0x15
|
||||
i2cset -f -y 15 0x23 0x00 0
|
||||
i2cset -f -y 15 0x23 0x15
|
||||
i2cset -f -y 15 0x24 0x00 0
|
||||
i2cset -f -y 15 0x24 0x15
|
||||
i2cset -f -y 13 0x29 0x00 0
|
||||
i2cset -f -y 13 0x29 0x15
|
||||
i2cset -f -y 13 0x27 0x00 0
|
||||
i2cset -f -y 13 0x27 0x15
|
||||
i2cset -f -y 15 0x28 0x00 0
|
||||
i2cset -f -y 15 0x28 0x15
|
||||
i2cset -f -y 13 0x20 0x00 0
|
||||
i2cset -f -y 13 0x20 0x17
|
||||
i2cset -f -y 14 0x25 0x00 0
|
||||
i2cset -f -y 14 0x25 0x15
|
||||
i2cset -f -y 16 0x26 0x00 0
|
||||
i2cset -f -y 16 0x26 0x15
|
||||
i2cset -f -y 14 0x25 0x00 0
|
||||
i2cset -f -y 14 0x25 0x15
|
||||
i2cset -f -y 16 0x26 0x00 0
|
||||
i2cset -f -y 16 0x26 0x15
|
||||
i2cset -f -y 14 0x21 0x00 0
|
||||
i2cset -f -y 14 0x21 0x15
|
||||
i2cset -f -y 14 0x22 0x00 0
|
||||
i2cset -f -y 14 0x22 0x15
|
||||
i2cset -f -y 16 0x23 0x00 0
|
||||
i2cset -f -y 16 0x23 0x15
|
||||
i2cset -f -y 16 0x24 0x00 0
|
||||
i2cset -f -y 16 0x24 0x15
|
||||
i2cset -f -y 14 0x29 0x00 0
|
||||
i2cset -f -y 14 0x29 0x15
|
||||
i2cset -f -y 14 0x27 0x00 0
|
||||
i2cset -f -y 14 0x27 0x15
|
||||
i2cset -f -y 16 0x28 0x00 0
|
||||
i2cset -f -y 16 0x28 0x15
|
||||
i2cset -f -y 14 0x20 0x00 0
|
||||
i2cset -f -y 14 0x20 0x17
|
||||
@@ -0,0 +1,188 @@
|
||||
//0.930V
|
||||
i2cset -f -y 13 0x25 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x25 0x21 0x89 0x00
|
||||
i2cset -f -y 13 0x25 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x25 0x0D 0x34 0x11
|
||||
//0.930V
|
||||
i2cset -f -y 15 0x26 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x26 0x21 0x89 0x00
|
||||
i2cset -f -y 15 0x26 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x26 0x0D 0x34 0x11
|
||||
//0.725V
|
||||
i2cset -f -y 13 0x25 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x25 0x21 0x60 0x00
|
||||
i2cset -f -y 13 0x25 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x25 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 15 0x26 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x26 0x21 0x60 0x00
|
||||
i2cset -f -y 15 0x26 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x26 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 13 0x21 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x21 0x21 0x60 0x00
|
||||
i2cset -f -y 13 0x21 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x21 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 13 0x21 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x21 0x21 0x60 0x00
|
||||
i2cset -f -y 13 0x21 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x21 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 13 0x22 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x22 0x21 0x60 0x00
|
||||
i2cset -f -y 13 0x22 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x22 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 13 0x22 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x22 0x21 0x60 0x00
|
||||
i2cset -f -y 13 0x22 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x22 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 15 0x23 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x23 0x21 0x60 0x00
|
||||
i2cset -f -y 15 0x23 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x23 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 15 0x23 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x23 0x21 0x60 0x00
|
||||
i2cset -f -y 15 0x23 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x23 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 15 0x24 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x24 0x21 0x60 0x00
|
||||
i2cset -f -y 15 0x24 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x24 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 15 0x24 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x24 0x21 0x60 0x00
|
||||
i2cset -f -y 15 0x24 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x24 0x1D 0x0A 0x06
|
||||
//1.545V
|
||||
i2cset -f -y 13 0x29 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x29 0x21 0x04 0x01
|
||||
i2cset -f -y 13 0x29 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x29 0x0D 0x91 0x20
|
||||
//1.545V
|
||||
i2cset -f -y 13 0x29 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x29 0x21 0x04 0x01
|
||||
i2cset -f -y 13 0x29 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x29 0x1D 0x49 0x10
|
||||
//0.745V
|
||||
i2cset -f -y 13 0x27 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x27 0x21 0x64 0x00
|
||||
i2cset -f -y 13 0x27 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x27 0x0D 0x94 0x0C
|
||||
//0.745V
|
||||
i2cset -f -y 13 0x27 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x27 0x21 0x64 0x00
|
||||
i2cset -f -y 13 0x27 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x27 0x1D 0x4C 0x06
|
||||
//0.745V
|
||||
i2cset -f -y 15 0x28 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x28 0x21 0x64 0x00
|
||||
i2cset -f -y 15 0x28 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x28 0x0D 0x94 0x0C
|
||||
//0.745V
|
||||
i2cset -f -y 15 0x28 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x28 0x21 0x64 0x00
|
||||
i2cset -f -y 15 0x28 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x28 0x1D 0x4C 0x06
|
||||
//0.885V
|
||||
i2cset -f -y 13 0x20 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x20 0x21 0x62 0x01
|
||||
|
||||
|
||||
//0.930V
|
||||
i2cset -f -y 14 0x25 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x25 0x21 0x89 0x00
|
||||
i2cset -f -y 14 0x25 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x25 0x0D 0x34 0x11
|
||||
//0.930V
|
||||
i2cset -f -y 16 0x26 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x26 0x21 0x89 0x00
|
||||
i2cset -f -y 16 0x26 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x26 0x0D 0x34 0x11
|
||||
//0.725V
|
||||
i2cset -f -y 14 0x25 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x25 0x21 0x60 0x00
|
||||
i2cset -f -y 14 0x25 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x25 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 16 0x26 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x26 0x21 0x60 0x00
|
||||
i2cset -f -y 16 0x26 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x26 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 14 0x21 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x21 0x21 0x60 0x00
|
||||
i2cset -f -y 14 0x21 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x21 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 14 0x21 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x21 0x21 0x60 0x00
|
||||
i2cset -f -y 14 0x21 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x21 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 14 0x22 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x22 0x21 0x60 0x00
|
||||
i2cset -f -y 14 0x22 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x22 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 14 0x22 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x22 0x21 0x60 0x00
|
||||
i2cset -f -y 14 0x22 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x22 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 16 0x23 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x23 0x21 0x60 0x00
|
||||
i2cset -f -y 16 0x23 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x23 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 16 0x23 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x23 0x21 0x60 0x00
|
||||
i2cset -f -y 16 0x23 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x23 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 16 0x24 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x24 0x21 0x60 0x00
|
||||
i2cset -f -y 16 0x24 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x24 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 16 0x24 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x24 0x21 0x60 0x00
|
||||
i2cset -f -y 16 0x24 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x24 0x1D 0x0A 0x06
|
||||
//1.545V
|
||||
i2cset -f -y 14 0x29 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x29 0x21 0x04 0x01
|
||||
i2cset -f -y 14 0x29 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x29 0x0D 0x91 0x20
|
||||
//1.545V
|
||||
i2cset -f -y 14 0x29 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x29 0x21 0x04 0x01
|
||||
i2cset -f -y 14 0x29 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x29 0x1D 0x49 0x10
|
||||
//0.745V
|
||||
i2cset -f -y 14 0x27 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x27 0x21 0x64 0x00
|
||||
i2cset -f -y 14 0x27 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x27 0x0D 0x94 0x0C
|
||||
//0.745V
|
||||
i2cset -f -y 14 0x27 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x27 0x21 0x64 0x00
|
||||
i2cset -f -y 14 0x27 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x27 0x1D 0x4C 0x06
|
||||
//0.745V
|
||||
i2cset -f -y 16 0x28 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x28 0x21 0x64 0x00
|
||||
i2cset -f -y 16 0x28 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x28 0x0D 0x94 0x0C
|
||||
//0.745V
|
||||
i2cset -f -y 16 0x28 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x28 0x21 0x64 0x00
|
||||
i2cset -f -y 16 0x28 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x28 0x1D 0x4C 0x06
|
||||
//0.885V
|
||||
i2cset -f -y 14 0x20 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x20 0x21 0x62 0x01
|
||||
@@ -0,0 +1,188 @@
|
||||
//0.870V
|
||||
i2cset -f -y 13 0x25 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x25 0x21 0x7D 0x00
|
||||
i2cset -f -y 13 0x25 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x25 0x0D 0xB4 0x0F
|
||||
//0.870V
|
||||
i2cset -f -y 15 0x26 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x26 0x21 0x7D 0x00
|
||||
i2cset -f -y 15 0x26 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x26 0x0D 0xB4 0x0F
|
||||
//0.775V
|
||||
i2cset -f -y 13 0x25 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x25 0x21 0x6A 0x00
|
||||
i2cset -f -y 13 0x25 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x25 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 15 0x26 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x26 0x21 0x6A 0x00
|
||||
i2cset -f -y 15 0x26 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x26 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 13 0x21 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x21 0x21 0x6A 0x00
|
||||
i2cset -f -y 13 0x21 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x21 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 13 0x21 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x21 0x21 0x6A 0x00
|
||||
i2cset -f -y 13 0x21 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x21 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 13 0x22 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x22 0x21 0x6A 0x00
|
||||
i2cset -f -y 13 0x22 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x22 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 13 0x22 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x22 0x21 0x6A 0x00
|
||||
i2cset -f -y 13 0x22 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x22 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 15 0x23 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x23 0x21 0x6A 0x00
|
||||
i2cset -f -y 15 0x23 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x23 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 15 0x23 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x23 0x21 0x6A 0x00
|
||||
i2cset -f -y 15 0x23 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x23 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 15 0x24 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x24 0x21 0x6A 0x00
|
||||
i2cset -f -y 15 0x24 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x24 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 15 0x24 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x24 0x21 0x6A 0x00
|
||||
i2cset -f -y 15 0x24 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x24 0x1D 0xAA 0x06
|
||||
//1.455V
|
||||
i2cset -f -y 13 0x29 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x29 0x21 0xF2 0x00
|
||||
i2cset -f -y 13 0x29 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x29 0x0D 0x51 0x1E
|
||||
//1.455V
|
||||
i2cset -f -y 13 0x29 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x29 0x21 0xF2 0x00
|
||||
i2cset -f -y 13 0x29 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x29 0x1D 0x29 0x0F
|
||||
//0.695V
|
||||
i2cset -f -y 13 0x27 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x27 0x21 0x5A 0x00
|
||||
i2cset -f -y 13 0x27 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x27 0x0D 0x54 0x0B
|
||||
//0.695V
|
||||
i2cset -f -y 13 0x27 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x27 0x21 0x5A 0x00
|
||||
i2cset -f -y 13 0x27 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x27 0x1D 0xAC 0x05
|
||||
//0.695V
|
||||
i2cset -f -y 15 0x28 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x28 0x21 0x5A 0x00
|
||||
i2cset -f -y 15 0x28 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x28 0x0D 0x54 0x0B
|
||||
//0.695V
|
||||
i2cset -f -y 15 0x28 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x28 0x21 0x5A 0x00
|
||||
i2cset -f -y 15 0x28 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x28 0x1D 0xAC 0x05
|
||||
//0.753V
|
||||
i2cset -f -y 13 0x20 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x20 0x21 0x2D 0x01
|
||||
|
||||
|
||||
//0.870V
|
||||
i2cset -f -y 14 0x25 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x25 0x21 0x7D 0x00
|
||||
i2cset -f -y 14 0x25 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x25 0x0D 0xB4 0x0F
|
||||
//0.870V
|
||||
i2cset -f -y 16 0x26 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x26 0x21 0x7D 0x00
|
||||
i2cset -f -y 16 0x26 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x26 0x0D 0xB4 0x0F
|
||||
//0.775V
|
||||
i2cset -f -y 14 0x25 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x25 0x21 0x6A 0x00
|
||||
i2cset -f -y 14 0x25 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x25 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 16 0x26 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x26 0x21 0x6A 0x00
|
||||
i2cset -f -y 16 0x26 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x26 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 14 0x21 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x21 0x21 0x6A 0x00
|
||||
i2cset -f -y 14 0x21 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x21 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 14 0x21 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x21 0x21 0x6A 0x00
|
||||
i2cset -f -y 14 0x21 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x21 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 14 0x22 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x22 0x21 0x6A 0x00
|
||||
i2cset -f -y 14 0x22 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x22 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 14 0x22 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x22 0x21 0x6A 0x00
|
||||
i2cset -f -y 14 0x22 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x22 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 16 0x23 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x23 0x21 0x6A 0x00
|
||||
i2cset -f -y 16 0x23 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x23 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 16 0x23 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x23 0x21 0x6A 0x00
|
||||
i2cset -f -y 16 0x23 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x23 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 16 0x24 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x24 0x21 0x6A 0x00
|
||||
i2cset -f -y 16 0x24 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x24 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 16 0x24 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x24 0x21 0x6A 0x00
|
||||
i2cset -f -y 16 0x24 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x24 0x1D 0xAA 0x06
|
||||
//1.455V
|
||||
i2cset -f -y 14 0x29 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x29 0x21 0xF2 0x00
|
||||
i2cset -f -y 14 0x29 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x29 0x0D 0x51 0x1E
|
||||
//1.455V
|
||||
i2cset -f -y 14 0x29 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x29 0x21 0xF2 0x00
|
||||
i2cset -f -y 14 0x29 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x29 0x1D 0x29 0x0F
|
||||
//0.695V
|
||||
i2cset -f -y 14 0x27 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x27 0x21 0x5A 0x00
|
||||
i2cset -f -y 14 0x27 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x27 0x0D 0x54 0x0B
|
||||
//0.695V
|
||||
i2cset -f -y 14 0x27 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x27 0x21 0x5A 0x00
|
||||
i2cset -f -y 14 0x27 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x27 0x1D 0xAC 0x05
|
||||
//0.695V
|
||||
i2cset -f -y 16 0x28 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x28 0x21 0x5A 0x00
|
||||
i2cset -f -y 16 0x28 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x28 0x0D 0x54 0x0B
|
||||
//0.695V
|
||||
i2cset -f -y 16 0x28 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x28 0x21 0x5A 0x00
|
||||
i2cset -f -y 16 0x28 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x28 0x1D 0xAC 0x05
|
||||
//0.753V
|
||||
i2cset -f -y 14 0x20 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x20 0x21 0x2D 0x01
|
||||
@@ -0,0 +1,188 @@
|
||||
//0.930V
|
||||
i2cset -f -y 13 0x25 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x25 0x21 0x89 0x00
|
||||
i2cset -f -y 13 0x25 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x25 0x0D 0x34 0x11
|
||||
//0.930V
|
||||
i2cset -f -y 15 0x26 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x26 0x21 0x89 0x00
|
||||
i2cset -f -y 15 0x26 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x26 0x0D 0x34 0x11
|
||||
//0.775V
|
||||
i2cset -f -y 13 0x25 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x25 0x21 0x6A 0x00
|
||||
i2cset -f -y 13 0x25 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x25 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 15 0x26 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x26 0x21 0x6A 0x00
|
||||
i2cset -f -y 15 0x26 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x26 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 13 0x21 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x21 0x21 0x6A 0x00
|
||||
i2cset -f -y 13 0x21 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x21 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 13 0x21 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x21 0x21 0x6A 0x00
|
||||
i2cset -f -y 13 0x21 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x21 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 13 0x22 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x22 0x21 0x6A 0x00
|
||||
i2cset -f -y 13 0x22 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x22 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 13 0x22 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x22 0x21 0x6A 0x00
|
||||
i2cset -f -y 13 0x22 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x22 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 15 0x23 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x23 0x21 0x6A 0x00
|
||||
i2cset -f -y 15 0x23 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x23 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 15 0x23 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x23 0x21 0x6A 0x00
|
||||
i2cset -f -y 15 0x23 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x23 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 15 0x24 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x24 0x21 0x6A 0x00
|
||||
i2cset -f -y 15 0x24 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x24 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 15 0x24 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x24 0x21 0x6A 0x00
|
||||
i2cset -f -y 15 0x24 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x24 0x1D 0xAA 0x06
|
||||
//1.545V
|
||||
i2cset -f -y 13 0x29 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x29 0x21 0x04 0x01
|
||||
i2cset -f -y 13 0x29 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x29 0x0D 0x91 0x20
|
||||
//1.545V
|
||||
i2cset -f -y 13 0x29 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x29 0x21 0x04 0x01
|
||||
i2cset -f -y 13 0x29 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x29 0x1D 0x49 0x10
|
||||
//0.745V
|
||||
i2cset -f -y 13 0x27 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x27 0x21 0x64 0x00
|
||||
i2cset -f -y 13 0x27 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x27 0x0D 0x94 0x0C
|
||||
//0.745V
|
||||
i2cset -f -y 13 0x27 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x27 0x21 0x64 0x00
|
||||
i2cset -f -y 13 0x27 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x27 0x1D 0x4C 0x06
|
||||
//0.745V
|
||||
i2cset -f -y 15 0x28 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x28 0x21 0x64 0x00
|
||||
i2cset -f -y 15 0x28 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x28 0x0D 0x94 0x0C
|
||||
//0.745V
|
||||
i2cset -f -y 15 0x28 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x28 0x21 0x64 0x00
|
||||
i2cset -f -y 15 0x28 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x28 0x1D 0x4C 0x06
|
||||
//0.885V
|
||||
i2cset -f -y 13 0x20 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x20 0x21 0x62 0x01
|
||||
|
||||
|
||||
//0.930V
|
||||
i2cset -f -y 14 0x25 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x25 0x21 0x89 0x00
|
||||
i2cset -f -y 14 0x25 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x25 0x0D 0x34 0x11
|
||||
//0.930V
|
||||
i2cset -f -y 16 0x26 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x26 0x21 0x89 0x00
|
||||
i2cset -f -y 16 0x26 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x26 0x0D 0x34 0x11
|
||||
//0.775V
|
||||
i2cset -f -y 14 0x25 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x25 0x21 0x6A 0x00
|
||||
i2cset -f -y 14 0x25 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x25 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 16 0x26 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x26 0x21 0x6A 0x00
|
||||
i2cset -f -y 16 0x26 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x26 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 14 0x21 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x21 0x21 0x6A 0x00
|
||||
i2cset -f -y 14 0x21 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x21 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 14 0x21 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x21 0x21 0x6A 0x00
|
||||
i2cset -f -y 14 0x21 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x21 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 14 0x22 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x22 0x21 0x6A 0x00
|
||||
i2cset -f -y 14 0x22 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x22 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 14 0x22 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x22 0x21 0x6A 0x00
|
||||
i2cset -f -y 14 0x22 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x22 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 16 0x23 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x23 0x21 0x6A 0x00
|
||||
i2cset -f -y 16 0x23 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x23 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 16 0x23 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x23 0x21 0x6A 0x00
|
||||
i2cset -f -y 16 0x23 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x23 0x1D 0xAA 0x06
|
||||
//0.775V
|
||||
i2cset -f -y 16 0x24 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x24 0x21 0x6A 0x00
|
||||
i2cset -f -y 16 0x24 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x24 0x0D 0x52 0x0D
|
||||
//0.775V
|
||||
i2cset -f -y 16 0x24 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x24 0x21 0x6A 0x00
|
||||
i2cset -f -y 16 0x24 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x24 0x1D 0xAA 0x06
|
||||
//1.545V
|
||||
i2cset -f -y 14 0x29 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x29 0x21 0x04 0x01
|
||||
i2cset -f -y 14 0x29 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x29 0x0D 0x91 0x20
|
||||
//1.545V
|
||||
i2cset -f -y 14 0x29 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x29 0x21 0x04 0x01
|
||||
i2cset -f -y 14 0x29 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x29 0x1D 0x49 0x10
|
||||
//0.745V
|
||||
i2cset -f -y 14 0x27 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x27 0x21 0x64 0x00
|
||||
i2cset -f -y 14 0x27 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x27 0x0D 0x94 0x0C
|
||||
//0.745V
|
||||
i2cset -f -y 14 0x27 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x27 0x21 0x64 0x00
|
||||
i2cset -f -y 14 0x27 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x27 0x1D 0x4C 0x06
|
||||
//0.745V
|
||||
i2cset -f -y 16 0x28 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x28 0x21 0x64 0x00
|
||||
i2cset -f -y 16 0x28 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x28 0x0D 0x94 0x0C
|
||||
//0.745V
|
||||
i2cset -f -y 16 0x28 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x28 0x21 0x64 0x00
|
||||
i2cset -f -y 16 0x28 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x28 0x1D 0x4C 0x06
|
||||
//0.885V
|
||||
i2cset -f -y 14 0x20 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x20 0x21 0x62 0x01
|
||||
@@ -0,0 +1,188 @@
|
||||
//0.870V
|
||||
i2cset -f -y 13 0x25 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x25 0x21 0x7D 0x00
|
||||
i2cset -f -y 13 0x25 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x25 0x0D 0xB4 0x0F
|
||||
//0.870V
|
||||
i2cset -f -y 15 0x26 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x26 0x21 0x7D 0x00
|
||||
i2cset -f -y 15 0x26 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x26 0x0D 0xB4 0x0F
|
||||
//0.725V
|
||||
i2cset -f -y 13 0x25 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x25 0x21 0x60 0x00
|
||||
i2cset -f -y 13 0x25 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x25 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 15 0x26 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x26 0x21 0x60 0x00
|
||||
i2cset -f -y 15 0x26 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x26 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 13 0x21 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x21 0x21 0x60 0x00
|
||||
i2cset -f -y 13 0x21 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x21 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 13 0x21 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x21 0x21 0x60 0x00
|
||||
i2cset -f -y 13 0x21 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x21 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 13 0x22 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x22 0x21 0x60 0x00
|
||||
i2cset -f -y 13 0x22 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x22 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 13 0x22 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x22 0x21 0x60 0x00
|
||||
i2cset -f -y 13 0x22 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x22 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 15 0x23 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x23 0x21 0x60 0x00
|
||||
i2cset -f -y 15 0x23 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x23 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 15 0x23 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x23 0x21 0x60 0x00
|
||||
i2cset -f -y 15 0x23 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x23 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 15 0x24 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x24 0x21 0x60 0x00
|
||||
i2cset -f -y 15 0x24 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x24 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 15 0x24 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x24 0x21 0x60 0x00
|
||||
i2cset -f -y 15 0x24 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x24 0x1D 0x0A 0x06
|
||||
//1.455V
|
||||
i2cset -f -y 13 0x29 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x29 0x21 0xF2 0x00
|
||||
i2cset -f -y 13 0x29 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x29 0x0D 0x51 0x1E
|
||||
//1.455V
|
||||
i2cset -f -y 13 0x29 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x29 0x21 0xF2 0x00
|
||||
i2cset -f -y 13 0x29 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x29 0x1D 0x29 0x0F
|
||||
//0.695V
|
||||
i2cset -f -y 13 0x27 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x27 0x21 0x5A 0x00
|
||||
i2cset -f -y 13 0x27 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x27 0x0D 0x54 0x0B
|
||||
//0.695V
|
||||
i2cset -f -y 13 0x27 0x00 1
|
||||
i2ctransfer -f -y 13 w3@0x27 0x21 0x5A 0x00
|
||||
i2cset -f -y 13 0x27 0x00 2
|
||||
i2ctransfer -f -y 13 w3@0x27 0x1D 0xAC 0x05
|
||||
//0.695V
|
||||
i2cset -f -y 15 0x28 0x00 0
|
||||
i2ctransfer -f -y 15 w3@0x28 0x21 0x5A 0x00
|
||||
i2cset -f -y 15 0x28 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x28 0x0D 0x54 0x0B
|
||||
//0.695V
|
||||
i2cset -f -y 15 0x28 0x00 1
|
||||
i2ctransfer -f -y 15 w3@0x28 0x21 0x5A 0x00
|
||||
i2cset -f -y 15 0x28 0x00 2
|
||||
i2ctransfer -f -y 15 w3@0x28 0x1D 0xAC 0x05
|
||||
//0.753V
|
||||
i2cset -f -y 13 0x20 0x00 0
|
||||
i2ctransfer -f -y 13 w3@0x20 0x21 0x2D 0x01
|
||||
|
||||
|
||||
//0.870V
|
||||
i2cset -f -y 14 0x25 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x25 0x21 0x7D 0x00
|
||||
i2cset -f -y 14 0x25 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x25 0x0D 0xB4 0x0F
|
||||
//0.870V
|
||||
i2cset -f -y 16 0x26 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x26 0x21 0x7D 0x00
|
||||
i2cset -f -y 16 0x26 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x26 0x0D 0xB4 0x0F
|
||||
//0.725V
|
||||
i2cset -f -y 14 0x25 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x25 0x21 0x60 0x00
|
||||
i2cset -f -y 14 0x25 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x25 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 16 0x26 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x26 0x21 0x60 0x00
|
||||
i2cset -f -y 16 0x26 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x26 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 14 0x21 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x21 0x21 0x60 0x00
|
||||
i2cset -f -y 14 0x21 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x21 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 14 0x21 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x21 0x21 0x60 0x00
|
||||
i2cset -f -y 14 0x21 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x21 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 14 0x22 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x22 0x21 0x60 0x00
|
||||
i2cset -f -y 14 0x22 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x22 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 14 0x22 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x22 0x21 0x60 0x00
|
||||
i2cset -f -y 14 0x22 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x22 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 16 0x23 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x23 0x21 0x60 0x00
|
||||
i2cset -f -y 16 0x23 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x23 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 16 0x23 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x23 0x21 0x60 0x00
|
||||
i2cset -f -y 16 0x23 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x23 0x1D 0x0A 0x06
|
||||
//0.725V
|
||||
i2cset -f -y 16 0x24 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x24 0x21 0x60 0x00
|
||||
i2cset -f -y 16 0x24 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x24 0x0D 0x12 0x0C
|
||||
//0.725V
|
||||
i2cset -f -y 16 0x24 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x24 0x21 0x60 0x00
|
||||
i2cset -f -y 16 0x24 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x24 0x1D 0x0A 0x06
|
||||
//1.455V
|
||||
i2cset -f -y 14 0x29 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x29 0x21 0xF2 0x00
|
||||
i2cset -f -y 14 0x29 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x29 0x0D 0x51 0x1E
|
||||
//1.455V
|
||||
i2cset -f -y 14 0x29 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x29 0x21 0xF2 0x00
|
||||
i2cset -f -y 14 0x29 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x29 0x1D 0x29 0x0F
|
||||
//0.695V
|
||||
i2cset -f -y 14 0x27 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x27 0x21 0x5A 0x00
|
||||
i2cset -f -y 14 0x27 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x27 0x0D 0x54 0x0B
|
||||
//0.695V
|
||||
i2cset -f -y 14 0x27 0x00 1
|
||||
i2ctransfer -f -y 14 w3@0x27 0x21 0x5A 0x00
|
||||
i2cset -f -y 14 0x27 0x00 2
|
||||
i2ctransfer -f -y 14 w3@0x27 0x1D 0xAC 0x05
|
||||
//0.695V
|
||||
i2cset -f -y 16 0x28 0x00 0
|
||||
i2ctransfer -f -y 16 w3@0x28 0x21 0x5A 0x00
|
||||
i2cset -f -y 16 0x28 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x28 0x0D 0x54 0x0B
|
||||
//0.695V
|
||||
i2cset -f -y 16 0x28 0x00 1
|
||||
i2ctransfer -f -y 16 w3@0x28 0x21 0x5A 0x00
|
||||
i2cset -f -y 16 0x28 0x00 2
|
||||
i2ctransfer -f -y 16 w3@0x28 0x1D 0xAC 0x05
|
||||
//0.753V
|
||||
i2cset -f -y 14 0x20 0x00 0
|
||||
i2ctransfer -f -y 14 w3@0x20 0x21 0x2D 0x01
|
||||
@@ -0,0 +1,17 @@
|
||||
//Start Unit0 Tr518
|
||||
bcmcmd -n 0 -c 'port cd lb=mac'
|
||||
bcmcmd -n 0 -c 'l2 learn off'
|
||||
bcmcmd -n 0 -c 'dsh -c "test mode nr=yes"'
|
||||
bcmcmd -n 0 -c 'dsh -c "tr 518 Scenario=6 Profile=2 Count=260 PktSize=324 PortList=1-259,270-565 rm=ext CheckLinkTime=20 CheckDataTime=200 testphase=1"'
|
||||
|
||||
//Stop Unit0 Tr518
|
||||
bcmcmd -n 0 -c 'port cd lb=none'
|
||||
|
||||
//Start Unit1 Tr518
|
||||
bcmcmd -n 1 -c 'port cd lb=mac'
|
||||
bcmcmd -n 1 -c 'l2 learn off'
|
||||
bcmcmd -n 1 -c 'dsh -c "test mode nr=yes"'
|
||||
bcmcmd -n 1 -c 'dsh -c "tr 518 Scenario=6 Profile=2 Count=260 PktSize=324 PortList=1-259,270-565 rm=ext CheckLinkTime=20 CheckDataTime=200 testphase=1"'
|
||||
|
||||
//Stop Unit1 Tr518
|
||||
bcmcmd -n 1 -c 'port cd lb=none'
|
||||
@@ -0,0 +1,7 @@
|
||||
echo 18-0020 > /sys/bus/i2c/drivers/max31790/unbind
|
||||
sleep .5
|
||||
echo 18-0020 > /sys/bus/i2c/drivers/max31790/bind
|
||||
echo 25-0020 > /sys/bus/i2c/drivers/max31790/unbind
|
||||
sleep .5
|
||||
echo 25-0020 > /sys/bus/i2c/drivers/max31790/bind
|
||||
fan-speed-control.sh 30
|
||||
@@ -0,0 +1,59 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# gen_channel_map.sh - Build docs/LTC2980_channel_map.csv from settings/*.conf
|
||||
# Version : V1.0.0
|
||||
# Date : 2026-08-27
|
||||
# Author : ETWen
|
||||
# =============================================================================
|
||||
# Runs on the DEV machine, not the DUT. Reads every LTC2980 margin settings
|
||||
# file and flattens CH<n>_VNOM / CH<n>_NET into one CSV:
|
||||
#
|
||||
# Board,CONN,Ch,NetName,Vnom
|
||||
# CB,CONN13,CH0,V5P0_ALW,5.0
|
||||
#
|
||||
# NC channels keep their literal NC / "-" so the page numbering still lines up
|
||||
# (ch/8 -> CHIPS[] index, ch%8 -> LTC2977 PAGE). Do not filter them out.
|
||||
#
|
||||
# Usage:
|
||||
# tools/gen_channel_map.sh # write docs/LTC2980_channel_map.csv
|
||||
# tools/gen_channel_map.sh - # write to stdout
|
||||
# =============================================================================
|
||||
set -eu
|
||||
|
||||
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
SET_DIR="${REPO_ROOT}/src/Script_ABC_Blanton/Blanton_Script/LTC2980_Margin_Script/settings"
|
||||
OUT="${1:-${REPO_ROOT}/docs/LTC2980_channel_map.csv}"
|
||||
|
||||
[ -d "${SET_DIR}" ] || { echo "settings dir not found: ${SET_DIR}" >&2; exit 1; }
|
||||
|
||||
# 3-argument match(str, regex, array) is a gawk extension. Under mawk it is a
|
||||
# syntax error at best and an empty CSV at worst - fail loudly instead.
|
||||
awk 'BEGIN { if (match("a", /a/, m) != 1) exit 1 }' 2>/dev/null \
|
||||
|| { echo "need gawk (3-arg match); this awk is: $(awk --version 2>&1 | head -1)" >&2; exit 1; }
|
||||
|
||||
gen() {
|
||||
printf 'Board,CONN,Ch,NetName,Vnom\n'
|
||||
# CB first, then SWB0/SWB1 CONN13..CONN16 - matches the physical walk order.
|
||||
for f in "${SET_DIR}"/Blanton_CB_CONN*.conf \
|
||||
"${SET_DIR}"/Blanton_SWB0_CONN*.conf \
|
||||
"${SET_DIR}"/Blanton_SWB1_CONN*.conf ; do
|
||||
[ -f "${f}" ] || continue
|
||||
base="$(basename "${f}" .conf)" # Blanton_SWB0_CONN13
|
||||
board="$(echo "${base}" | cut -d_ -f2)" # SWB0
|
||||
conn="$(echo "${base}" | cut -d_ -f3)" # CONN13
|
||||
|
||||
# .conf files are LF per .gitattributes, but strip CR anyway - a stray
|
||||
# CR would land inside the net name and travel into the CSV unseen.
|
||||
sed 's/\r$//' "${f}" | awk -v b="${board}" -v c="${conn}" '
|
||||
match($0, /^CH([0-9]+)_VNOM="([^"]*)"[^"]*CH[0-9]+_NET="([^"]*)"/, m) {
|
||||
printf "%s,%s,CH%s,%s,%s\n", b, c, m[1], m[3], m[2]
|
||||
}'
|
||||
done
|
||||
}
|
||||
|
||||
if [ "${OUT}" = "-" ]; then
|
||||
gen
|
||||
else
|
||||
gen > "${OUT}"
|
||||
echo "wrote ${OUT} ($(($(wc -l < "${OUT}") - 1)) channels)"
|
||||
fi
|
||||
Reference in New Issue
Block a user