work_sript/02.nicsensor/nicsensor.sh

1101 lines
34 KiB
Bash
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/sh
# script Version 1.1 20240912
# 支持测试的传感器芯片 emc1413 ina3221 adc128
# 支持通过 chip 参数直接做I2C命令透传来访问芯片寄存器
# 支持通过 fru 参数读取FRU十六进制内容
# ---------------------------------------------------------
# Project Feature Varible (按照项目需要修改)
# ---------------------------------------------------------
# ADC128 分压系数 (Ravel)
votage_division_factor_0="1"
votage_division_factor_1="1"
votage_division_factor_2="1"
votage_division_factor_3="0.8"
votage_division_factor_4="0.6"
votage_division_factor_5="0.6"
votage_division_factor_6="0.2326"
votage_division_factor_7="1"
# ADC128 channel名称定制(可更换为对应的 电压/电流/温度 的名称)
ADC128_Channel0_name="Channel 0"
ADC128_Channel1_name="Channel 1"
ADC128_Channel2_name="Channel 2"
ADC128_Channel3_name="Channel 3"
ADC128_Channel4_name="Channel 4"
ADC128_Channel5_name="Channel 5"
ADC128_Channel6_name="Channel 6"
ADC128_Channel7_name="Channel 7"
# INA3221 分流电阻, 单位(毫欧姆)(Ravel)
shunt_resistor_0="2"
shunt_resistor_1="2"
shunt_resistor_2="5"
# EMC1413 channel名称定制(可更换为对应的 电压/电流/温度 的名称)
EMC1413_Channel0_name="Channel 0"
EMC1413_Channel1_name="Channel 1"
EMC1413_Channel2_name="Channel 2"
# fru 烧录的起始地址
fru_offset="0x00 0x00"
# 应用的服务器产品,根据服务器产品手动修改这个变量
# 当前适配的服务器产品 5280m7 5468m7 donghu yichun
server_type="5280m7"
# ---------------------------------------------------------
# Common Varible (请勿随意修改)
# ---------------------------------------------------------
# Input Param
# Introduction of pcie_slot
# 1.脚本即将访问的网卡位于服务器上的PCIe插槽位置
pcie_slot=$1
# Introduction of sensor_type
# 1.脚本即将读取和处理的传感器名称
sensor_type=$2
# Introduction of chip_slave
# 1.chip i2c slave address(7bit)
chip_slave=$3
# Introduction of option_data
# 1.在FRU的处理过程中,使用option_data来区分是读操作还是写操作,将值设置为
# "read"或者"write"
# 2.在chip的处理过程中,使用option_data来代表一条完整的i2c命令,这条命令会
# 被发到chip上,一个例子:"i2ctransfer -y 12 w2@0x10 0x90 0x00 r9"
option_data=$4
# Introduction of option_data2
# 1.仅用于fru write操作代表即将写入的fru文件名
option_data2=$5
# CHIP REGISTER
REG_pca9641_controll="0x01"
REG_adc128_config="0x00"
REG_adc128_advance="0x0b"
REG_adc128_status="0x0c"
REG_adc128_ch0="0x20"
REG_adc128_ch1="0x21"
REG_adc128_ch2="0x22"
REG_adc128_ch3="0x23"
REG_adc128_ch4="0x24"
REG_adc128_ch5="0x25"
REG_adc128_ch6="0x26"
REG_adc128_ch7="0x27"
REG_emc1413_TD1_H="0x00"
REG_emc1413_TD1_L="0x29"
REG_emc1413_TD2_H="0x01"
REG_emc1413_TD2_L="0x10"
REG_emc1413_TD3_H="0x23"
REG_emc1413_TD3_L="0x24"
REG_ina3221_ch1="0x01"
REG_ina3221_ch2="0x03"
REG_ina3221_ch3="0x05"
REG_ina3221_bus1="0x02"
REG_ina3221_bus2="0x04"
REG_ina3221_bus3="0x06"
# ---------------------------------------------------------
# Global Varible (请勿随意修改)
# ---------------------------------------------------------
# DEBUG MODE=0 : Disable debug mode
# =1 : Enable debug mode
# 启用debug模式后需要手动配置 i2c_bus
DEBUG_MODE=0
# 选通网卡I2C通路的关键变量
i2c_bus=12
pca9641_slave=0x41
pca9548_channel=0x04
pca9548_slave=0x72
# 硬件上是否有PCA9641?
is_have_pca9641=1
log="/tmp/nicsensor_debug.log"
INA3221_SHUNT_VOLT=0
INA3221_BUS_VOLT=1
INA3221_POWER=2
INFO="Info"
WARNING="Warning"
ERROR="Error"
ina3221_ch0_volt="0"
ina3221_ch1_volt="0"
ina3221_ch2_volt="0"
ina3221_ch0_current="0"
ina3221_ch1_current="0"
ina3221_ch2_current="0"
SCRIPT_VRESION="1.2 InTest Rev3"
fru_file_name=$option_data2
fru_write_size=0
fru_write_data=""
# ---------------------------------------------------------
# Script Function Defination
# ---------------------------------------------------------
# script usage
print_usage(){
echo ""
echo "================>>> nicsensor script usage <<<================="
echo " Command Format : ./nicsensor.sh [slot] [sensor tpye] [slave]"
echo " Option Detail"
echo " [slot] : 0 1 2 3 4 5 ..."
echo " [sensor type] : emc1413, adc128, ina3221"
echo " [slave] : chip slave address , please provide 7 bit address"
echo " E.G. : ./nicsensor.sh 0 adc128 0x1f"
echo ""
echo " To Auto detect i2c slave on server, please use:"
echo " ./nicsensor.sh detect"
echo " This function now only support on server 5280m7, 5468m7, donghu"
echo ""
echo " If want to read/write chip register, use the below format"
echo " ./nicsensor.sh [slot] chip [slave] [i2c_command]"
echo " i2c_command : such as [i2ctransfer -y 13 w1@0x10 0x00 r2]"
echo ""
echo " If want to use debug mode, please modify the DEBUG_MODE to 1"
echo " now status : DEBUG_MODE = $DEBUG_MODE"
echo ""
}
print_chip_command_format(){
echo "Command Format : ./nicsensor.sh [slot] chip [slave] [i2c_command]"
}
print_fru_command_format(){
echo "Command Format : ./nicsensor.sh [slot] fru [slave] write [fru_file]"
}
# 格式化输出信息
# @Param1 信息等级 [Info/Warning/Error]
# @Param2 信息内容
format_print(){
echo ">>> [$1] $2"
}
# 格式化输出信息到日志文件
# @Param1 信息等级 [Info/Warning/Error]
# @Param2 信息内容
format_log_print(){
echo "[$1] $2" >> $log
}
# 自查一些脚本中的属性配置
conf_pre_check(){
# 校验debug mode的值
if [ $DEBUG_MODE -ne 0 && $DEBUG_MODE -ne 1 ];then
format_print $ERROR "Invalid conf value, DEBUG_MODE: $DEBUG_MODE"
exit 1
fi
}
# 根据5280m7 pcie slot 和 i2c 对对应关系调整变量
set_configuration_5280m7(){
is_have_pca9641=1
# set pca9641 address && I2C BUS
if [ $pcie_slot -le 2 ];then
pca9641_slave="0x41"
i2c_bus=12
else
pca9641_slave="0x42"
i2c_bus=13
fi
# set pca9548 switch channel
if [ $pcie_slot -eq 0 ];then
pca9548_channel="0x02"
elif [ $pcie_slot -eq 1 ];then
pca9548_channel="0x04"
elif [ $pcie_slot -eq 2 ];then
pca9548_channel="0x08"
elif [ $pcie_slot -eq 3 ];then
pca9548_channel="0x02"
elif [ $pcie_slot -eq 4 ];then
pca9548_channel="0x04"
elif [ $pcie_slot -eq 5 ];then
pca9548_channel="0x08"
fi
}
# 根据5468m7 pcie slot 和 i2c 对对应关系调整变量
set_configuration_5468m7(){
is_have_pca9641=1
# set pca9641 address && I2C BUS
if [ $pcie_slot -le 4 ];then
pca9641_slave="0x31"
pca9548_slave="0x70"
i2c_bus=13
else
pca9641_slave="0x42"
pca9548_slave="0x71"
i2c_bus=14
fi
# set pca9548 switch channel
if [ $pcie_slot -eq 0 ];then
pca9548_channel="0x01"
elif [ $pcie_slot -eq 1 ];then
pca9548_channel="0x02"
elif [ $pcie_slot -eq 2 ];then
pca9548_channel="0x04"
elif [ $pcie_slot -eq 3 ];then
pca9548_channel="0x08"
elif [ $pcie_slot -eq 4 ];then
pca9548_channel="0x10"
elif [ $pcie_slot -eq 5 ];then
pca9548_channel="0x01"
elif [ $pcie_slot -eq 6 ];then
pca9548_channel="0x02"
elif [ $pcie_slot -eq 7 ];then
pca9548_channel="0x04"
elif [ $pcie_slot -eq 8 ];then
pca9548_channel="0x08"
elif [ $pcie_slot -eq 9 ];then
pca9548_channel="0x10"
elif [ $pcie_slot -eq 10 ];then
pca9548_channel="0x20"
fi
}
# 根据donghu pcie slot 和 i2c 对对应关系调整变量
set_configuration_donghu(){
is_have_pca9641=0
i2c_bus=3
# set pca9548 switch channel
if [ $pcie_slot -eq 0 ];then
pca9548_channel="0x80"
elif [ $pcie_slot -eq 1 ];then
pca9548_channel="0x40"
elif [ $pcie_slot -eq 2 ];then
pca9548_channel="0x20"
elif [ $pcie_slot -eq 3 ];then
pca9548_channel="0x10"
elif [ $pcie_slot -eq 4 ];then
pca9548_channel="0x08"
elif [ $pcie_slot -eq 5 ];then
pca9548_channel="0x04"
elif [ $pcie_slot -eq 6 ];then
pca9548_channel="0x02"
elif [ $pcie_slot -eq 7 ];then
pca9548_channel="0x01"
fi
}
# 根据yichun pcie slot 和 i2c 对对应关系调整变量
set_configuration_yichun(){
is_have_pca9641=0
pca9548_slave="0x74"
# set pca9548 switch channel
if [ $pcie_slot -eq 0 ];then
i2c_bus=12
pca9548_channel="0x02"
elif [ $pcie_slot -eq 1 ];then
i2c_bus=13
pca9548_channel="0x02"
elif [ $pcie_slot -eq 2 ];then
i2c_bus=14
pca9548_channel="0x02"
fi
}
# 根据输入信息调整选通芯片的配置(PCA9641 PCA9548)
# 20240912 - 更新脚本:支持通过服务器型号进行配置
set_configuration(){
format_log_print $INFO "Server Type : $server_type"
# 根据服务器型号执行对应的配置策略
if [ $server_type == "5280m7" ];then
set_configuration_5280m7
elif [ $server_type == "5468m7" ];then
set_configuration_5468m7
elif [ $server_type == "donghu" ];then
set_configuration_donghu
elif [ $server_type == "yichun" ];then
set_configuration_yichun
else
format_print $ERROR "Error: Unsupport Server Type !!! - $server_type"
exit 1
fi
}
# 初始化调试日志
init_debuglog(){
# 只保留一次日志读取记录
if [ -e $log ];then
rm $log
fi
# print time header
res_date=`date`
format_log_print $INFO "=========================== $res_date"
format_log_print $INFO "Script Version : $SCRIPT_VERSION"
if [ $DEBUG_MODE -ne 0 ];then
format_log_print $WARNING "Enable debug mode : $DEBUG_MODE"
fi
}
# 记录配置信息日志
prepare_start_info(){
# 记录单次配置信息到调试日志中去
format_log_print $INFO "PCIE slot : $pcie_slot"
format_log_print $INFO "I2C Bus: $i2c_bus"
format_log_print $INFO "PCA9641 slave: $pca9641_slave"
format_log_print $INFO "PCA9548 slave: $pca9548_slave"
format_log_print $INFO "PCA9548 channel: $pca9548_channel"
# Record i2c device info to log
res_info=`i2cdetect -y $i2c_bus`
echo $res_info >> $log
}
# 获取PCA9641的控制权
get_pca9641_controll(){
# Request 9641 lock
res_lock=`i2ctransfer -y $i2c_bus w2@$pca9641_slave $REG_pca9641_controll 0x81 r1`
format_log_print $INFO "After request 9641 lock, The REG value is $res_lock"
# Build 9641 Connection
res_build=`i2ctransfer -y $i2c_bus w2@$pca9641_slave $REG_pca9641_controll 0x85 r1`
format_log_print $INFO "After Build 9641 connection, The REG value is $res_build"
# After get 9641 controll, Record i2c device info to log
res_after=`i2cdetect -y $i2c_bus`
echo $res_after >> $log
if [ "$res_build" != "0x87" ];then
format_print $ERROR "Cannot establish connection with pca9641 !!!"
exit 1
fi
}
# 选通PCA9548的channel
switch_pca9548_channel(){
# set 9548 channel
res_setchannel=`i2ctransfer -y $i2c_bus w1@$pca9548_slave $pca9548_channel`
format_log_print $INFO "After switch channel"
# After set 9548 channel , record i2c device info
res_after=`i2cdetect -y $i2c_bus`
echo $res_after >> $log
}
# ---------------------------------------------------------
# Chip EMC1413
# ---------------------------------------------------------
# 处理EMC1413读到的数据并输出结果
# @Param1 emc1413读取数据高位
# @Param2 emc1413读取数据低位
# @Param3 channel号/定制化名称
convert_emc1413_data(){
# 将读取到的两位数据去掉 0x 前缀
hex_value1=$(echo "$1" | awk '{sub(/^0x/,""); print}')
hex_value2=$(echo "$2" | awk '{sub(/^0x/,""); print}')
# 由于 bc 计算器只能识别大写的 十六进制数据,将小写的十六进制数据全部转化为大写的数据
upper_hex_value1=$(echo "$hex_value1" | awk '{
for(i=1; i<=length($0); i++){
if(tolower(substr($0,i,1)) ~ /^[a-f]$/)
printf toupper(substr($0,i,1));
else
printf substr($0,i,1);
}
print ""
}')
upper_hex_value2=$(echo "$hex_value2" | awk '{
for(i=1; i<=length($0); i++){
if(tolower(substr($0,i,1)) ~ /^[a-f]$/)
printf toupper(substr($0,i,1));
else
printf substr($0,i,1);
}
print ""
}')
# 转化为10进制数据
dec_value1=$(echo "ibase=16; $upper_hex_value1" | bc)
dec_value2=$(echo "ibase=16; $upper_hex_value2" | bc)
# 计算温度值
temp=$(echo "scale=4; $dec_value1 + ($dec_value2 / 32 * 0.125 )" | bc)
# 格式化输出数据
format_temp=$(echo "$temp" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }')
echo "$3 : $format_temp C, hex value : $hex_value1 $hex_value2"
}
# 读取EMC1413芯片每个通道的数据,随后调用数据处理函数进行数据解析并输出
read_emc1413_channel_value(){
format_log_print $INFO "Start EMC1413 channel data ..."
res_td1_h=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_emc1413_TD1_H r1`
res_td1_l=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_emc1413_TD1_L r1`
res_td2_h=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_emc1413_TD2_H r1`
res_td2_l=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_emc1413_TD2_L r1`
res_td3_h=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_emc1413_TD3_H r1`
res_td3_l=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_emc1413_TD3_L r1`
# 将 I2C 读取的 raw 数据记录到调试日志中
format_log_print $INFO "channel 1 : $res_td1_h $res_td1_l"
format_log_print $INFO "channel 2 : $res_td2_h $res_td2_l"
format_log_print $INFO "channel 3 : $res_td3_h $res_td3_l"
# start parse raw data
echo ">>> The emc1413 value is:"
convert_emc1413_data $res_td1_h $res_td1_l $EMC1413_Channel0_name
convert_emc1413_data $res_td2_h $res_td2_l $EMC1413_Channel1_name
convert_emc1413_data $res_td3_h $res_td3_l $EMC1413_Channel2_name
}
# EMC1413处理逻辑
process_emc1413(){
# emc1413 no need to init
# get chip emc1413 value
read_emc1413_channel_value
}
# ---------------------------------------------------------
# Chip ADC128
# ---------------------------------------------------------
# 进行ADC128芯片的初始化
check_adc128_init(){
# Get Reg 0x00 status
res_adc128_status=`i2cget -y $i2c_bus $chip_slave $REG_adc128_config`
format_log_print $INFO "REG adc128 STATUS : $res_adc128_status"
# if stauts is not 0x01 (Start Monitor) ,then do init
if [ "$res_adc128_status" != "0x01" ];then
format_log_print $INFO "Start Init ADC128 Chip"
# Init ADC128 work as mode 1 (0x02)
res_adc128_advance=`i2ctransfer -y $i2c_bus w2@$chip_slave $REG_adc128_advance 0x02`
# Set ADC128 on start (0x01)
res_adc128_setstart=`i2ctransfer -y $i2c_bus w2@$chip_slave $REG_adc128_config 0x01 r1`
format_log_print $INFO "After Set status, the REG 0x00 value is $res_adc128_setstart"
fi
}
# 处理ADC128读到的数据并输出结果
# @Param 1 ADC128读取数据高位
# @Param 2 ADC128读取数据低位
# @Param 3 channel号/定制化名称
# @Param 4 分压系数
convert_adc128_data(){
# 将读取到的两位数据拼接起来
hex_value1=$(echo "$1" | awk '{sub(/^0x/,""); print}')
hex_value2=$(echo "$2" | awk '{sub(/^0x/,""); print}')
merge_value="${hex_value1}${hex_value2}"
# 由于 bc 计算器只能识别大写的 十六进制数据,这里将小写的十六进制数据全部转化为大写的数据
upper_hex_value=$(echo "$merge_value" | awk '{
for(i=1; i<=length($0); i++){
if(tolower(substr($0,i,1)) ~ /^[a-f]$/)
printf toupper(substr($0,i,1));
else
printf substr($0,i,1);
}
print ""
}')
# 利用bc计算器进行运算并将返回值格式化后输出
dec_val=$(echo "ibase=16; $upper_hex_value" | bc)
volt=$(echo "scale=4; $dec_val / 16 / 4096 * 2.65 / $4" | bc)
format_volt=$(echo "$volt" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }')
echo "$3 : $format_volt v, hex value: $upper_hex_value"
}
# 读取ADC128芯片每个通道的数据,随后调用数据处理函数进行数据解析并输出
read_adc128_channel_value(){
format_log_print $INFO "Start Read ADC128 channel data ..."
res_ch0=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch0 r2`
res_ch1=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch1 r2`
res_ch2=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch2 r2`
res_ch3=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch3 r2`
res_ch4=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch4 r2`
res_ch5=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch5 r2`
res_ch6=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch6 r2`
res_ch7=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_adc128_ch7 r2`
# 将 I2C 读取的 raw 数据记录到调试日志中
format_log_print $INFO "channel0 : $res_ch0"
format_log_print $INFO "channel1 : $res_ch1"
format_log_print $INFO "channel2 : $res_ch2"
format_log_print $INFO "channel3 : $res_ch3"
format_log_print $INFO "channel4 : $res_ch4"
format_log_print $INFO "channel5 : $res_ch5"
format_log_print $INFO "channel6 : $res_ch6"
format_log_print $INFO "channel7 : $res_ch7"
# start parse raw data
echo ">>> The ADC128 value is :"
convert_adc128_data $res_ch0 $ADC128_Channel0_name $votage_division_factor_0
convert_adc128_data $res_ch1 $ADC128_Channel1_name $votage_division_factor_1
convert_adc128_data $res_ch2 $ADC128_Channel2_name $votage_division_factor_2
convert_adc128_data $res_ch3 $ADC128_Channel3_name $votage_division_factor_3
convert_adc128_data $res_ch4 $ADC128_Channel4_name $votage_division_factor_4
convert_adc128_data $res_ch5 $ADC128_Channel5_name $votage_division_factor_5
convert_adc128_data $res_ch6 $ADC128_Channel6_name $votage_division_factor_6
convert_adc128_data $res_ch7 $ADC128_Channel7_name $votage_division_factor_7
}
# ADC128处理逻辑
process_adc128(){
# check if chip adc128 need init
check_adc128_init
# get chip adc128 value
read_adc128_channel_value
}
# ---------------------------------------------------------
# Chip INA3221
# ---------------------------------------------------------
# 处理INA3221读到的电流数据并输出结果
# @Param1 ina3221读取数据高位
# @Param2 ina3221读取数据低位
# @Param3 channel号
# @Param4 0代表数据是shunt volt
# 1代表数据是bus volt
# @Param5 分流电阻 (仅在 Param4 是 shunt volt时有用)
convert_ina3221_data(){
# 将读取到的两位数据拼接起来
hex_value1=$(echo "$1" | awk '{sub(/^0x/,""); print}')
hex_value2=$(echo "$2" | awk '{sub(/^0x/,""); print}')
merge_value="${hex_value1}${hex_value2}"
# 由于 bc 计算器只能识别大写的 十六进制数据,这里将小写的十六进制数据全部转化为大写的数据
upper_hex_value=$(echo "$merge_value" | awk '{
for(i=1; i<=length($0); i++){
if(tolower(substr($0,i,1)) ~ /^[a-f]$/)
printf toupper(substr($0,i,1));
else
printf substr($0,i,1);
}
print ""
}')
# 将16进制数据转化为10进制
dec_val=$(echo "ibase=16; $upper_hex_value" | bc)
# todo 检查这个数据的最高位是否为1
# max_unsigned_32bit_half=$(echo "scale=0; 2^31 / 2" | bc)
# if [ $(echo "$dec_val >= $max_unsigned_32bit_half" | bc) -eq 1 ];then
# echo ""
# else
# echo ""
# fi
if [ $4 -eq $INA3221_BUS_VOLT ];then
# 计算每个通道上的电压
volt=$(echo "scale=4; $dec_val / 8 * 40 / 10000 * 2" | bc)
# 格式化输出数据
format_volt=$(echo "$volt" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }')
echo "channel $3 : $format_volt V, hex value: $upper_hex_value"
if [ $3 -eq 0 ];then
ina3221_ch0_volt=$format_volt
elif [ $3 -eq 1 ];then
ina3221_ch1_volt=$format_volt
else
ina3221_ch2_volt=$format_volt
fi
elif [ $4 -eq $INA3221_SHUNT_VOLT ];then
# 计算每个分流电阻上的电压,同时计算出电流
current_mv=$(echo "scale=4; $dec_val / 8 * 40 / 1000" | bc)
current=$(echo "scale=4; $current_mv / $5" | bc)
# 格式化输出数据
format_current=$(echo "$current" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }')
format_current_mv=$(echo "$current_mv" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }')
echo "channel $3 : $format_current A, shunt volt: $format_current_mv mV, shunt resistor: $5 mOhm, hex value: $upper_hex_value"
if [ $3 -eq 0 ];then
ina3221_ch0_current=$format_current
elif [ $3 -eq 1 ];then
ina3221_ch1_current=$format_current
else
ina3221_ch2_current=$format_current
fi
elif [ $4 -eq $INA3221_POWER ];then
# 计算每个通道上的功耗,并算总和
power_ch0=$(echo "scale=4; $ina3221_ch0_volt * $ina3221_ch0_current" | bc)
power_ch1=$(echo "scale=4; $ina3221_ch1_volt * $ina3221_ch1_current" | bc)
power_ch2=$(echo "scale=4; $ina3221_ch2_volt * $ina3221_ch2_current" | bc)
# 格式化输出数据
format_power_ch0=$(echo "$power_ch0" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }')
format_power_ch1=$(echo "$power_ch1" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }')
format_power_ch2=$(echo "$power_ch2" | awk '{ if ($0 ~ /^\./) print "0" $0; else print $0 }')
total_power=$(echo "scale=4; $power_ch0 + $power_ch1 + $power_ch2" | bc)
echo "channel 0 : $format_power_ch0 W"
echo "channel 1 : $format_power_ch1 W"
echo "channel 2 : $format_power_ch2 W"
echo "total power: $total_power W"
fi
}
# 读取INA3221芯片每个通道的数据,随后调用数据处理函数进行数据解析并输出
read_ina3221_channel_value(){
format_log_print $INFO "Start Read INA3221 channel data ..."
res_ch0=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_ina3221_ch1 r2`
res_ch1=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_ina3221_ch2 r2`
res_ch2=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_ina3221_ch3 r2`
res_bus0=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_ina3221_bus1 r2`
res_bus1=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_ina3221_bus2 r2`
res_bus2=`i2ctransfer -y $i2c_bus w1@$chip_slave $REG_ina3221_bus3 r2`
# 将 I2C 读取的 raw 数据记录到调试日志中
format_log_print $INFO "channel 0 shunt volt: $res_ch0"
format_log_print $INFO "channel 1 shunt volt: $res_ch1"
format_log_print $INFO "channel 2 shunt volt: $res_ch2"
format_log_print $INFO "Channel 0 bus volt : $res_bus0"
format_log_print $INFO "Channel 1 bus volt : $res_bus1"
format_log_print $INFO "Channel 2 bus volt : $res_bus2"
# start parse raw data
echo ">>> The INA3221 shunt value is :"
convert_ina3221_data $res_ch0 0 $INA3221_SHUNT_VOLT $shunt_resistor_0
convert_ina3221_data $res_ch1 1 $INA3221_SHUNT_VOLT $shunt_resistor_1
convert_ina3221_data $res_ch2 2 $INA3221_SHUNT_VOLT $shunt_resistor_2
echo ">>> The INA3221 bus value is :"
convert_ina3221_data $res_bus0 0 $INA3221_BUS_VOLT
convert_ina3221_data $res_bus1 1 $INA3221_BUS_VOLT
convert_ina3221_data $res_bus2 2 $INA3221_BUS_VOLT
echo ">>> The INA3221 bus power is :"
convert_ina3221_data 0 0 0 $INA3221_POWER
}
# INA3221处理逻辑
process_ina3221(){
# ina3221 no need to init first
# get chip ina3221 value
read_ina3221_channel_value
}
# ---------------------------------------------------------
# CHIP
# ---------------------------------------------------------
# 临时支持CHIP读取寄存器
write_read_chip(){
# Modify i2c cmd which write to cpld if need
cmd_wr=$option_data
res_wr=`$cmd_wr`
format_print $INFO ">>> Chip Command: $cmd_wr"
format_print $INFO ">>> The Result : $res_wr"
}
# chip处理逻辑
process_chip(){
# cpld no need to init first
# write and read cpld
write_read_chip
}
# ---------------------------------------------------------
# FRU
# ---------------------------------------------------------
# 将传入的fru文件解析为可被i2cransfer直接写入的数据
parse_fru_write_data(){
# 判断fru文件是否存在于当前目录
if [ -e $fru_file_name ];then
format_log_print $INFO "Fru file exist!"
else
format_log_print $ERROR "Fru file not exist!"
format_print $WARNING "Fru file not exist in current directory!"
format_print $ERROR "Operation Failed!"
exit 1
fi
# 计算需要写入的fru文件大小
fru_write_size=`ls -lht | grep $fru_file_name | awk '{print $5}'`
format_print $INFO "Fru File [$fru_file_name] size = $fru_write_size Bytes"
format_log_print $INFO "Fru File [$fru_file_name] size = $fru_write_size Bytes"
# 获取fru文件的 raw data
fru_raw_data=`hexdump -C $fru_file_name | awk '{
for(i=2;i<18;i++){
print $i
}
}'`
format_log_print $INFO "Fru Raw Data: $fru_raw_data"
# 将raw data解析为可被 i2ctransfer 写入的数据
fru_write_data=`echo $fru_raw_data | awk -v size=$fru_write_size '{
for(i=1;i<=size;i++){
printf "0x%s ",$i
}
}'`
}
# 支持FRU读取
read_fru(){
res_fru=`i2ctransfer -y $i2c_bus w2@$chip_slave $fru_offset r256`
# 将FRU数据按照每行16个字符输出
echo "The Fru Data :"
echo "$res_fru" | \
awk '{
line="";
count=0;
for(i=1; i<=NF; i++){
hex=substr($i, 3);
if(line != ""){
line = line " ";
}
line = line hex;
count++;
if (count == 16){
print line;
line = "";
count = 0;
}
}
if(line != ""){
print line;
}
}'
}
# 20240926 支持写板卡FRU
write_fru(){
i2c_write_byte=$(($fru_write_size+2))
# 组装command并发送
write_command="i2ctransfer -y $i2c_bus w$i2c_write_byte@$chip_slave $fru_offset $fru_write_data"
write_res=`$write_command`
format_log_print $INFO "Exec Command: $write_command"
}
# fru 处理逻辑
process_fru(){
# fru no need to init first
# write and read fru
if [ "$option_data" == "write" ];then
write_fru
else
# 默认为读取操作
read_fru
fi
}
# ---------------------------------------------------------
# END of CHIP Function
# ---------------------------------------------------------
# 读取sensor流程的起点
start_get_sensor(){
# 首先选通 PCA9641 和 PCA9548,构建I2C通路
# 如果使用了debug模式,那么将不执行选通9641和9548的操作
if [ $DEBUG_MODE -eq 0 ];then
# set global varible by server type
set_configuration
# 记录开始执行脚本前的I2C配置信息
prepare_start_info
# 从9641获取I2C控制权
if [ $is_have_pca9641 -eq 1 ];then
get_pca9641_controll
fi
# 选择9548 channel
switch_pca9548_channel
fi
# get sensor detail value
if [ "$sensor_type" == "emc1413" ];then
process_emc1413
elif [ "$sensor_type" == "adc128" ];then
process_adc128
elif [ "$sensor_type" == "ina3221" ];then
process_ina3221
elif [ "$sensor_type" == "chip" ];then
process_chip
elif [ "$sensor_type" == "fru" ];then
process_fru
else
format_print $ERROR "Unsupport Sensor Type !!!"
print_usage
fi
}
# 在 5280m7 上扫描每个pcie slot下的I2C设备
# 详细对应关系参阅 readme.txt 第二节
detect_on_5280m7(){
# 从9641获取I2C控制权
i2c_bus=12
pca9641_slave="0x41"
get_pca9641_controll
format_print $INFO "PCIe slot 0 : bus12 9548channel 1"
i2ctransfer -y $i2c_bus w1@0x72 0x02
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 1 : bus12 9548channel 2"
i2ctransfer -y $i2c_bus w1@0x72 0x04
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 2 : bus12 9548channel 3"
i2ctransfer -y $i2c_bus w1@0x72 0x08
i2cdetect -y $i2c_bus
i2c_bus=13
pca9641_slave="0x42"
get_pca9641_controll
format_print $INFO "PCIe slot 3 : bus13 9548channel 1"
i2ctransfer -y $i2c_bus w1@0x72 0x02
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 4 : bus13 9548channel 2"
i2ctransfer -y $i2c_bus w1@0x72 0x04
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 5 : bus13 9548channel 3"
i2ctransfer -y $i2c_bus w1@0x72 0x08
i2cdetect -y $i2c_bus
}
# 在 5468m7 上扫描每个pcie slot下的I2C设备
# 详细对应关系参阅 readme.txt 第二节
detect_on_5468m7(){
# 从9641获取I2C控制权
i2c_bus=13
pca9641_slave="0x31"
get_pca9641_controll
format_print $INFO "PCIe slot 0 : bus13 9548channel 0"
i2ctransfer -y $i2c_bus w1@0x70 0x01
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 1 : bus13 9548channel 1"
i2ctransfer -y $i2c_bus w1@0x70 0x02
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 2 : bus13 9548channel 2"
i2ctransfer -y $i2c_bus w1@0x70 0x04
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 3 : bus13 9548channel 3"
i2ctransfer -y $i2c_bus w1@0x70 0x08
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 4 : bus13 9548channel 4"
i2ctransfer -y $i2c_bus w1@0x70 0x10
i2cdetect -y $i2c_bus
i2c_bus=14
pca9641_slave="0x42"
get_pca9641_controll
format_print $INFO "PCIe slot 5 : bus14 9548channel 0"
i2ctransfer -y $i2c_bus w1@0x71 0x01
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 6 : bus14 9548channel 1"
i2ctransfer -y $i2c_bus w1@0x71 0x02
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 7 : bus14 9548channel 2"
i2ctransfer -y $i2c_bus w1@0x71 0x04
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 8 : bus14 9548channel 3"
i2ctransfer -y $i2c_bus w1@0x71 0x08
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 9 : bus14 9548channel 4"
i2ctransfer -y $i2c_bus w1@0x71 0x10
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 10 : bus14 9548channel 5"
i2ctransfer -y $i2c_bus w1@0x71 0x20
i2cdetect -y $i2c_bus
}
# 在 donghu 上扫描每个pcie slot下的I2C设备
detect_on_donghu(){
i2c_bus=3
format_print $INFO "PCIe slot 0 : bus3 9548channel 7"
i2ctransfer -y $i2c_bus w1@0x70 0x80
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 1 : bus3 9548channel 6"
i2ctransfer -y $i2c_bus w1@0x70 0x40
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 2 : bus3 9548channel 5"
i2ctransfer -y $i2c_bus w1@0x70 0x20
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 3 : bus3 9548channel 4"
i2ctransfer -y $i2c_bus w1@0x70 0x10
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 4 : bus3 9548channel 3"
i2ctransfer -y $i2c_bus w1@0x70 0x08
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 5 : bus3 9548channel 2"
i2ctransfer -y $i2c_bus w1@0x70 0x04
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 6 : bus3 9548channel 1"
i2ctransfer -y $i2c_bus w1@0x70 0x02
i2cdetect -y $i2c_bus
format_print $INFO "PCIe slot 7 : bus3 9548channel 0"
i2ctransfer -y $i2c_bus w1@0x70 0x01
i2cdetect -y $i2c_bus
}
# 在 yichun 上扫描每个pcie slot下的I2C设备
detect_on_yichun(){
i2c_bus=12
format_print $INFO "PCIe slot 0 : bus12 9546channel 2"
i2ctransfer -y $i2c_bus w1@0x74 0x02
i2cdetect -y $i2c_bus
i2c_bus=13
format_print $INFO "PCIe slot 1 : bus13 9546channel 2"
i2ctransfer -y $i2c_bus w1@0x74 0x02
i2cdetect -y $i2c_bus
i2c_bus=14
format_print $INFO "PCIe slot 2 : bus14 9546channel 2"
i2ctransfer -y $i2c_bus w1@0x74 0x02
i2cdetect -y $i2c_bus
}
# 搜索服务器所有PCIE插槽的I2C设备信息,当前仅支持特定Riser卡上的设备
# change list : 20240912-支持服务器器型号5280m7,5468m7
start_detect_device(){
# debug mode下进行detect操作仅对当前链路进行detect
if [ $DEBUG_MODE -ne 0 ];then
format_print $INFO "In debug mode now, only detect i2c_bus$i2c_bus:"
i2cdetect -y $i2c_bus
exit 0
fi
format_print $INFO "Detect on server : $server_type"
if [ $server_type == "5280m7" ];then
detect_on_5280m7
elif [ $server_type == "5468m7" ];then
detect_on_5468m7
elif [ $server_type == "donghu" ];then
detect_on_donghu
elif [ $server_type == "yichun" ];then
detect_on_yichun
else
format_print $ERROR "Unsupport Server Type !!!"
fi
}
# ---------------------------------------------------------
# Start Execute Script
# ---------------------------------------------------------
# 配置校验
conf_pre_check
# 参数合法校验
if [ "$sensor_type" == "chip" ];then
if [ $# -le 3 ];then
format_print $ERROR "Command Format illegal"
print_chip_command_format
exit 1
fi
fi
if [ "$1" == "detect" ];then
start_detect_device
exit 0
fi
# 在正式执行脚本之前初始化调试日志
init_debuglog
# 如果是fru write操作, 需要对即将写入的bin文件进行数据预处理
if [ "$sensor_type" == "fru" ];then
if [ "$option_data" == "write" ];then
format_log_print $INFO "Opreation FRU Write"
# 在fru write操作下要求必须有 option_data2, 做参数检查
if [ "$option_data2" == "" ];then
format_print $ERROR "Please provide fru file name"
print_fru_command_format
exit 1
fi
# 解析fru bin文件
parse_fru_write_data
fi
fi
if [ $# -le 2 ];then
print_usage
else
start_get_sensor
fi