feat(i2c): Add a Tray ID I2C stress and run it in Script A and B

tray_id_stress.sh writes 0xA5 and 0x5A to register 0x02 of device 0x70
on buses 34, 35, 38 and 39, reading each back and comparing. The two
patterns put every bit in both states. It prints one PASS / FAIL / ERROR
line per step and a per-bus Summary with a single RESULT line; exit 0 is
all PASS, 1 is any FAIL or I2C error, 2 is bad arguments. FAIL (wrong
value read) and ERROR (i2cset / i2cget failed) are counted apart.

The original value is read first and written back at the end, verified
by a read; -R skips that, -n N repeats the sequence. Buses, address,
register and patterns are editable at the top of the file.

Script A runs one pass after show_dmesg as the baseline. Script B runs
one pass in every soak round, before the sleep 60.

The script is called by path and needs the exec bit on the DUT.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UniUXkxgCG2Ty74advL8Pd
This commit is contained in:
2026-10-01 13:32:14 +08:00
co-authored by Claude Opus 5.5
parent 1d3fb4f929
commit ebb2260798
3 changed files with 164 additions and 0 deletions
@@ -897,6 +897,10 @@ endif
include "utils/setup_pmon.ttl" include "utils/setup_pmon.ttl"
include "utils/show_dmesg.ttl" include "utils/show_dmesg.ttl"
; ========== Tray ID Stress Test ==========
wait prompt_sonic_root
sendln "~/Blanton_Script/tray_id_stress.sh"
;include "utils/xxx.ttl" ;include "utils/xxx.ttl"
;wait prompt_sonic_root ;wait prompt_sonic_root
;flushrecv ;flushrecv
@@ -186,6 +186,11 @@ while 1
sendln "jobs" sendln "jobs"
wait prompt_sonic_root wait prompt_sonic_root
sendln "systemctl is-active mlucas-amm" sendln "systemctl is-active mlucas-amm"
; ========== Tray ID Stress Test ==========
wait prompt_sonic_root
sendln "~/Blanton_Script/tray_id_stress.sh"
wait prompt_sonic_root wait prompt_sonic_root
sendln "sleep 60" sendln "sleep 60"
endwhile endwhile
@@ -0,0 +1,155 @@
#!/bin/bash
#==============================================================================
# Author : ETWen
# Date : 20261001
# Purpose : Tray ID I2C stress - write a pattern to the Tray ID register on each
# bus, read it back and compare. Patterns 0xA5 and 0x5A exercise every
# bit in both states (1010_0101 / 0101_1010).
# Usage : ./tray_id_stress.sh [-n loops] [-R] [-h]
# -n N repeat the whole sequence N times (default 1)
# -R do NOT restore the original register value at the end
# -h help
# Buses / address / register / patterns are set in the block below.
#
# Exit : 0 = all PASS, 1 = any FAIL or I2C error, 2 = usage
#
# Version History:
# V1.0.0 20261001 Initial Version
#==============================================================================
#------------------------------------------------------------------------------
# Settings - edit here
#------------------------------------------------------------------------------
BUSES=(34 35 38 39) # i2c buses, one Tray ID device each
ADDR=0x70 # device address
REG=0x02 # Tray ID register
PATTERNS=(0xa5 0x5a) # written in this order, each read back and compared
RESTORE=1 # 1 = write the original value back when done
LOOPS=1
usage() {
sed -n '/^# Usage/,/^# Exit/p' "$0" | sed 's/^# \{0,1\}//'
}
while getopts ":n:Rh" opt; do
case "$opt" in
n) LOOPS="$OPTARG" ;;
R) RESTORE=0 ;;
h) usage; exit 0 ;;
:) echo "ERROR: -$OPTARG needs a value" >&2; usage >&2; exit 2 ;;
\?) echo "ERROR: unknown option -$OPTARG" >&2; usage >&2; exit 2 ;;
esac
done
if ! [[ "$LOOPS" =~ ^[1-9][0-9]*$ ]]; then
echo "ERROR: -n must be a positive integer (got '$LOOPS')" >&2; exit 2
fi
for t in i2cset i2cget; do
command -v "$t" >/dev/null 2>&1 || { echo "ERROR: $t not found" >&2; exit 2; }
done
# Counters per bus
declare -A N_PASS N_FAIL N_ERR ORIG
for b in "${BUSES[@]}"; do N_PASS[$b]=0; N_FAIL[$b]=0; N_ERR[$b]=0; ORIG[$b]=""; done
# Read one byte; prints the value (0xNN) on success, returns 1 on failure.
rd() {
local out
out=$(i2cget -f -y "$1" "$ADDR" "$REG" 2>&1)
if [[ $? -ne 0 || ! "$out" =~ ^0x[0-9a-fA-F]{1,2}$ ]]; then
echo "$out"; return 1
fi
echo "$out"
}
TS() { date '+%Y-%m-%d %H:%M:%S'; }
echo "=========================================================="
echo " Tray ID I2C stress $(TS)"
echo " buses: ${BUSES[*]} addr $ADDR reg $REG"
echo " patterns: ${PATTERNS[*]} loops: $LOOPS restore: $RESTORE"
echo "=========================================================="
#------------------------------------------------------------------------------
# Original values (so they can be put back)
#------------------------------------------------------------------------------
for b in "${BUSES[@]}"; do
if v=$(rd "$b"); then
ORIG[$b]="$v"
printf "[bus %-2s %s reg %s] original value: %s\n" "$b" "$ADDR" "$REG" "$v"
else
printf "[bus %-2s %s reg %s] original value: READ ERROR (%s)\n" "$b" "$ADDR" "$REG" "$v"
fi
done
echo "----------------------------------------------------------"
#------------------------------------------------------------------------------
# Write / read-back
#------------------------------------------------------------------------------
for (( loop = 1; loop <= LOOPS; loop++ )); do
(( LOOPS > 1 )) && echo "--- loop $loop / $LOOPS ---"
for b in "${BUSES[@]}"; do
for p in "${PATTERNS[@]}"; do
tag=$(printf "[bus %-2s %s reg %s]" "$b" "$ADDR" "$REG")
if ! werr=$(i2cset -f -y "$b" "$ADDR" "$REG" "$p" 2>&1); then
N_ERR[$b]=$(( N_ERR[$b] + 1 ))
echo "$tag write $p -> WRITE ERROR (${werr:-no message}) ERROR"
continue
fi
if ! got=$(rd "$b"); then
N_ERR[$b]=$(( N_ERR[$b] + 1 ))
echo "$tag write $p -> READ ERROR (${got:-no message}) ERROR"
continue
fi
if (( got == p )); then
N_PASS[$b]=$(( N_PASS[$b] + 1 ))
echo "$tag write $p -> read $got PASS"
else
N_FAIL[$b]=$(( N_FAIL[$b] + 1 ))
echo "$tag write $p -> read $got FAIL"
fi
done
done
done
#------------------------------------------------------------------------------
# Restore
#------------------------------------------------------------------------------
if (( RESTORE )); then
echo "----------------------------------------------------------"
for b in "${BUSES[@]}"; do
o=${ORIG[$b]}; v=""
if [[ -z "$o" ]]; then
printf "[bus %-2s] restore skipped: original value was not readable\n" "$b"
continue
fi
if i2cset -f -y "$b" "$ADDR" "$REG" "$o" >/dev/null 2>&1 && v=$(rd "$b") && (( v == o )); then
printf "[bus %-2s] restored %s\n" "$b" "$o"
else
printf "[bus %-2s] RESTORE FAILED: wanted %s, read %s\n" "$b" "$o" "${v:-?}"
N_ERR[$b]=$(( N_ERR[$b] + 1 ))
fi
done
fi
#------------------------------------------------------------------------------
# Summary
#------------------------------------------------------------------------------
per_bus=$(( LOOPS * ${#PATTERNS[@]} ))
tp=0; tf=0; te=0
echo
echo "=========================== Summary =========================="
printf "%-6s %-6s %-6s %8s %6s %6s %6s %s\n" "BUS" "ADDR" "REG" "CHECKS" "PASS" "FAIL" "ERROR" "RESULT"
for b in "${BUSES[@]}"; do
p=${N_PASS[$b]}; f=${N_FAIL[$b]}; e=${N_ERR[$b]}
tp=$(( tp + p )); tf=$(( tf + f )); te=$(( te + e ))
r=PASS; (( f > 0 || e > 0 || p != per_bus )) && r=FAIL
printf "%-6s %-6s %-6s %8s %6s %6s %6s %s\n" "$b" "$ADDR" "$REG" "$per_bus" "$p" "$f" "$e" "$r"
done
total=$(( per_bus * ${#BUSES[@]} ))
overall=PASS; (( tf > 0 || te > 0 || tp != total )) && overall=FAIL
printf "%-6s %-6s %-6s %8s %6s %6s %6s %s\n" "TOTAL" "" "" "$total" "$tp" "$tf" "$te" "$overall"
echo "=============================================================="
echo "Tray ID stress RESULT: $overall ($(TS))"
[[ "$overall" == PASS ]] && exit 0 || exit 1