当前位置: 首页 > news >正文

EVM3588-B开发板+NPU+Qwen2.5-3B-Instruct(一)

一、RK3588整体架构概览

项目类型型号参数说明
核心配置处理器RK3588CPU

Quad-core ARM Cortex-A76@2.4GHz

Quad-core ARM Cortex-A55@1.8GH

GPU四核 ARM Mali-G610 MP4
NPU算力 6.0TOPs
内存LPDDR4默认配置8GByte
可选配置4GByte/16GByte
存储eMMC默认配置32GByte
可选配置64GByte

本机配置:RK3588/8GByte/64GByte

二、软件资源

2.1、英码科技官方SDK:

​​​​​​https://pan.baidu.com/s/1QsDRVisbcaC2X1sd54ac5A?pwd=wbdn 提取码:wbdn

链接失效了找英码官方要:https://www.ema-tech.com/technology

SDK:

出货镜像:

烧录工具:

2.2、rockchip_RKLLM_SDK

https://github.com/airockchip/rknn-llm

2.3、hf-mirror原版Qwen2.5-3B-Instruct

$:export HF_ENDPOINT=https://hf-mirror.com $:hf download Qwen/Qwen2-7B-Instruct --local-dir ./Qwen2.5-3B-Instruct

模型文件:

三、必备条件

3.1、RK3588 NPU驱动版本≥0.9.8,查看NPU驱动版本:

$cat /sys/kernel/debug/rknpu/version
RKNPU driver:v0.9.8

3.2、PC: Ubuntu 20.04 x86_64 / Ubuntu 22.04 x86_64, kernel 5.10/kernel 6.1,16~32G

3.3、板端 :Ubuntu 20.04/Ubuntu 22.04,kernel 5.10/kernel 6.1

#系统版本 uname -v #或 cat /etc/issue
#内核版本 uname -r #或 cat /proc/version

3.4、本机:PC(Ubuntu 22.04 x86_64, python3.10),板端(Ubuntu 20.04/kernel 5.10,python 3.8)

四、板端:系统烧录与镜像更新(驱动更新)

4.1、linux系统烧录镜像:

4.1.1、工具:Linux_Upgrade_Tool_v1.65.zip,下载后解压。

#解压 unzip Linux_Upgrade_Tool_v1.65.zip cd Linux_Upgrade_Tool_v1.65

解压后的文件:

安装到系统中:

#安装到系统中 sudo mv upgrade_tool /usr/local/bin sudo chown root:root /usr/local/bin/upgrade_tool sudo chmod a+x /usr/local/bin/upgrade_tool

检测是否识别:

#检测是否识别 sudo upgrade_tool ld

显示以下信息,说明安装成功。

$ sudo upgrade_tool ld Not found config.ini Program Data in /usr/local/bin List of rockusb connected(0)

4.1.2、烧录镜像:evm3588_ubuntu20.04_v1.0.3_ema_v1.2.1.6_240429.img

软件方式进入Loader模式:

adb reboot loader
* daemon not running; starting now at tcp:5037 * daemon started successfully

烧录固件:

#擦除flash 使用ef 参数 sudo upgrade_tool ef evm3588_ubuntu20.04_v1.0.3_ema_v1.2.1.6_240429.img #重新烧写 sudo upgrade_tool uf evm3588_ubuntu20.04_v1.0.3_ema_v1.2.1.6_240429.img

如果Linux_Upgrade_Tool安装到系统中失败,使用以下命令:

#镜像和工具放到同一目录下 cd Linux_Upgrade_Tool_v1.65 sudo ./upgrade_tool uf evm3588_ubuntu20.04_v1.0.3_ema_v1.2.1.6_240429.img

出现以下信息,烧写成功。

Linux_Upgrade_Tool_v1.65$ ./upgrade_tool uf evm3588_ubuntu20.04_v1.0.3_ema_v1.2.1.6_240429.img' Program Data in Loading firmware... Support Type:RK3588 FW Ver:1.0.00 FW Time:2024-04-29 15:25:51 Loader ver:1.0b Loader Time:2023-08-09 09:40:20 Upgrade firmware ok.

系统重启,板端查看NPU驱动版本:

$cat /sys/kernel/debug/rknpu/version RKNPU driver:v0.9.2

4.1.3、更新boot镜像(包含NPU驱动)

#进入loader模式 adb reboot loader #安装upgrade_tool工具成功就去掉 ./ sudo ./upgrade_tool di -boot evm3588_ab_boot-v0.9.8.img #或 sudo upgrade_tool di -boot evm3588_ab_boot-v0.9.8.img

出现以下信息,烧写成功。

Linux_Upgrade_Tool_v1.65$ sudo ./upgrade_tool di -boot evm3588_ab_boot-v0.9.8.img Program Data in directlba=1,first4access=1,gpt=1 Download boot start...(0x00008000) Download image ok.

系统重启,板端查看NPU驱动版本:

$sudo cat /sys/kernel/debug/rknpu/version RKNPU driver:v0.9.8

五、PC: X86 电脑|模型量化转换 HF 原生→.rkllm(ubuntu 22.04)

5.1、安装conda和rkllm-toolkit(rkllm_toolkit-1.2.3) 及依赖。

conda:

#创建虚拟环境: conda create --name rkllm310 python=3.10 #激活虚拟环境: conda activate rkllm310

安装对应python版本的rkllm_toolkit :

cd /rknn-llm-main/rkllm-toolkit/packages #虚拟环境安装: pip install rkllm_toolkit-1.2.3-cp310-cp310-linux_x86_64.whl #安装依赖 sudo apt install -y git build-essential cmake python3-pip libssl-dev gcc g++

版本检查:

python -c "from rkllm.api import RKLLM; print('✅ RKLLM 导入成功')"

强制安装对应版本核心包

pip install torch==2.6.0 transformers==4.55.2 numpy==1.26.4 accelerate==1.5.2 Jinja2==3.1.4 safetensors==0.5.3 sentencepiece==0.2.0 --force-reinstall
# 打印所有核心依赖的当前版本 pip list | grep -E "torch|transformers|numpy|accelerate|sentencepiece|safetensors|Jinja2"

5.2、下载hf-mirror原版Qwen2.5-3B-Instruct

#下载模型到文件夹./Qwen2.5-3B $:export HF_ENDPOINT=https://hf-mirror.com $:hf download Qwen/Qwen2.5-3B-Instruct --local-dir ./Qwen2.5-3B

5.3、模型量化转换(HF 原生→.rkllm,关键步骤)

rockchip_RKLLM_SDK / rknn-llm-main:

../rknn-llm-main/examples/rkllm_api_demo/export/export_rkllm.py

修改 modelpath = '../Qwen2.5-3B-Instruct' 为下载的原版Qwen2.5-3B-Instruct路径

from rkllm.api import RKLLM import os os.environ['CUDA_VISIBLE_DEVICES']='0' ''' https://huggingface.co/deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B Download the DeepSeek R1 model from the above url. ''' modelpath = '../Qwen2.5-3B-Instruct' llm = RKLLM() # Load model # Use 'export CUDA_VISIBLE_DEVICES=0' to specify GPU device # device options ['cpu', 'cuda'] # dtype options ['float32', 'float16', 'bfloat16'] # Using 'bfloat16' or 'float16' can significantly reduce memory consumption but at the cost of lower precision # compared to 'float32'. Choose the appropriate dtype based on your hardware and model requirements. ret = llm.load_huggingface(model=modelpath, model_lora = None, device='cuda', dtype="float32", custom_config=None, load_weight=True) # ret = llm.load_gguf(model = modelpath) if ret != 0: print('Load model failed!') exit(ret) # Build model dataset = "./data_quant.json" # Json file format, please note to add prompt in the input,like this: # [{"input":"Human: 你好!\nAssistant: ", "target": "你好!我是人工智能助手KK!"},...] # Different quantization methods are optimized for different algorithms: # w8a8/w8a8_gx is recommended to use the normal algorithm. # w4a16/w4a16_gx is recommended to use the grq algorithm. qparams = None # Use extra_qparams target_platform = "RK3588" optimization_level = 1 quantized_dtype = "W8A8" quantized_algorithm = "normal" num_npu_core = 3 ret = llm.build(do_quantization=True, optimization_level=optimization_level, quantized_dtype=quantized_dtype, quantized_algorithm=quantized_algorithm, target_platform=target_platform, num_npu_core=num_npu_core, extra_qparams=qparams, dataset=dataset, hybrid_rate=0, max_context=4096) if ret != 0: print('Build model failed!') exit(ret) # Export rkllm model ret = llm.export_rkllm(f"./{os.path.basename(modelpath)}_{quantized_dtype}_{target_platform}.rkllm") if ret != 0: print('Export model failed!') exit(ret)

canda环境运行python export_rkllm.py 开始转换模型:

(rkllm310) admain@D:/rockchip/jxby/Qwen2.5-3B$ python export_rkllm.py

出现以下信息,转换成功。

5.4、模型传输到板端

adb push Qwen2.5-3B-Instruct_w8a8_rk3588.rkllm /home/ema/3588/models

六、板端:rkllm-runtime配置及调用模型

6.1、开发板配置rkllm-runtime

(可选)放到系统路径: # 头文件 sudo cp -r rkllm-runtime/runtime/Linux/include /usr/include/ # 库文件 sudo cp rkllm-runtime/runtime/Linux/aarch64/librkllmrt.so /usr/lib/ # 刷新库缓存 sudo ldconfig

6.2、模型调用及demo

rockchip_RKLLM_SDK /rknn-llm-main:

../rknn-llm-main/examples/rkllm_api_demo/deploy/

编译:

#创建并进入编译文件夹 mkdir build && cd build cmake .. #编译 make -j4

运行:

# ./llm_demo + rkllm模型路径 + 单次最大 + 最大上下文窗口 ./llm_demo /home/ema/3588/models/Qwen2.5-3B-Instruct_w8a8_rk3588.rkllm 256 4096

出现以下信息运行成功:

ema@ema:~/3588/rockchip/rknn-llm-main/examples/rkllm_api_demo/deploy/build$ ./llm_demo /home/ema/3588/models/Qwen2.5-3B-Instruct_w8a8_rk3588.rkllm 256 4096 rkllm init start I rkllm: rkllm-runtime version: 1.2.3, rknpu driver version: 0.9.8, platform: RK3588 I rkllm: loading rkllm model from /home/ema/3588/models/Qwen2.5-3B-Instruct_W8A8_RK3588.rkllm I rkllm: rkllm-toolkit version: 1.2.3, max_context_limit: 4096, npu_core_num: 3, target_platform: RK3588, model_dtype: W8A8 I rkllm: Enabled cpus: [4, 5, 6, 7] I rkllm: Enabled cpus num: 4 rkllm init success

6.3、token/s 测试

RKLLM 的 llm_demo,不需要额外装工具,只要开一条环境变量,就能自动打印 token/s

export RKLLM_LOG_LEVEL=1

然后正常启动模型:

./llm_demo /home/ema/3588/models/Qwen2.5-3B-Instruct_w8a8_rk3588.rkllm 256 4096

每次对话结束,终端会自动输出类似下面的token/s 结果:

6.4、NPU 定频

1. NPU的节点路径

ema@ema:~/桌面$ ls /sys/class/devfreq/fdab0000.npu/ available_frequencies device max_freq polling_interval target_freq uevent available_governors governor min_freq power timer cur_freq load name subsystem trans_stat

2. 获取NPU支持的频点

ema@ema:~/桌面$ cat /sys/class/devfreq/fdab0000.npu/available_frequencies 300000000 400000000 500000000 600000000 700000000 800000000 900000000 1000000000

最高1GHZ

3. 获取NPU运行的模式

ema@ema:~/桌面$ cat /sys/class/devfreq/fdab0000.npu/available_governors rknpu_ondemand dmc_ondemand userspace powersave performance simple_ondemand

performance:性能模式,强制锁定 NPU 运行在最高主频(1GHz),无论负载高低都保持满频,不自动降频。

powersave:省电模式,强制锁定 NPU 运行在最低主频(300MHz),功耗和发热降到最低。

userspace:用户空间控频模式,将调频权限完全开放给用户层,由你手动指定具体运行频率(必须是支持的频点)。

simple_ondemand:简易按需调频模式,ux 通用的动态调速策略,根据 NPU 负载自动升降频。

dmc_ondemand:内存控制器联动调频,联动动态内存控制器(DMC),根据 NPU 计算负载 + 内存带宽需求联合调频,优化高带宽场景的访问效率。

4、查看当前模式频率

#模式 ema@ema:~/桌面$ cat /sys/class/devfreq/fdab0000.npu/governor performance #频率 ema@ema:~/桌面$ cat /sys/class/devfreq/fdab0000.npu/cur_freq 1000000000

5、模式配置&设置频率

#设置模式 ema@ema:~/桌面$ sudo echo userspace > /sys/class/devfreq/fdab0000.npu/governor #设置频率 echo 1000000000 > /sys/class/devfreq/fdab0000.npu/userspace/set_freq cat /sys/class/devfreq/fdab0000.npu/cur_freq #无权限使用以下命令 ema@ema:~/桌面$ echo userspace | sudo tee /sys/class/devfreq/fdab0000.npu/governor userspace ema@ema:~/桌面$ cat /sys/class/devfreq/fdab0000.npu/governor userspace ema@ema:~/桌面$ echo 800000000 | sudo tee /sys/class/devfreq/fdab0000.npu/userspace/set_freq 800000000 ema@ema:~/桌面$ cat /sys/class/devfreq/fdab0000.npu/cur_freq 800000000

6、负载&温度

#负载 三核 ema@ema:~/桌面$ sudo cat /sys/kernel/debug/rknpu/load NPU load: Core0: 78%, Core1: 80%, Core2: 79%, #温度: value/1000 ema@ema:~/桌面$ cat /sys/class/thermal/thermal_zone6/temp 46230

6.5、资源监控 ***.sh

#!/bin/bash # --- 配置路径 --- # NPU NPU_LOAD_FILE="/sys/kernel/debug/rknpu/load" NPU_FREQ_FILE="/sys/class/devfreq/fdab0000.npu/cur_freq" NPU_TEMP_FILE="/sys/class/thermal/thermal_zone6/temp" # GPU GPU_FILE="/sys/class/devfreq/fb000000.gpu/load" # RGA (视频处理) RGA_LOAD_FILE="/sys/kernel/debug/rkrga/load" CLK_SUMMARY_FILE="/sys/kernel/debug/clk/clk_summary" # CPU PROC_STAT_FILE="/proc/stat" CPU_FREQ_BASE_PATH="/sys/devices/system/cpu" # 内存/交换分区 MEM_INFO_FILE="/proc/meminfo" # 磁盘监控路径(默认监控根分区 /,可自行修改) DISK_MONITOR_PATH="/" # --- 全局变量定义 --- # NPU NPU_CORE0_LOAD=0 NPU_CORE1_LOAD=0 NPU_CORE2_LOAD=0 NPU_FREQ="N/A" NPU_TEMP=0 # GPU GPU_LOAD=0 GPU_FREQ="N/A" GPU_TEMP=0 # RGA RGA_LOAD0=0 RGA_LOAD1=0 RGA_LOAD2=0 RGA_FREQ0="N/A" RGA_FREQ1="N/A" RGA_FREQ2="N/A" # CPU declare -a CPU_LOAD declare -a CPU_FREQ declare -a CPU_PREV_TOTAL declare -a CPU_PREV_IDLE CPU_CORE_COUNT=0 CPU_FIRST_RUN=1 SOC_TEMP=0 LITTLE_CORE_TEMP=0 BIG_CORE0_TEMP=0 BIG_CORE1_TEMP=0 # 内存/交换分区 MEM_TOTAL=0 MEM_USED=0 MEM_USED_PERCENT=0 SWAP_TOTAL=0 SWAP_USED=0 SWAP_USED_PERCENT=0 # 磁盘存储(新增) DISK_TOTAL=0 DISK_USED=0 DISK_USED_PERCENT=0 # --- 权限检查与自动提权 --- if [ "$(id -u)" -ne 0 ]; then echo "此脚本需要 root 权限来读取 debugfs 信息。正在请求权限..." exec sudo "$0" "$@" fi # ---文件检查 --- [[ ! -f "$NPU_LOAD_FILE" ]] && echo "警告:找不到 NPU load 文件" [[ ! -f "$NPU_FREQ_FILE" ]] && echo "警告:找不到 NPU freq 文件" [[ ! -f "$GPU_FILE" ]] && echo "警告:找不到 GPU load 文件" [[ ! -f "$RGA_LOAD_FILE" ]] && echo "警告:找不到 RGA load 文件" [[ ! -f "$CLK_SUMMARY_FILE" ]] && echo "警告:找不到 RGA clk_summary 文件" [[ ! -f "$PROC_STAT_FILE" ]] && echo "警告:找不到 $PROC_STAT_FILE 文件" [[ ! -f "$MEM_INFO_FILE" ]] && echo "警告:找不到 $MEM_INFO_FILE 文件" # === 自适应配置 === BAR_WIDTH_BASE=5 BAR_WIDTH_MAX=40 LAYOUT_MARGIN=65 REFRESH_TIME=0.5 # 动态计算 BAR_WIDTH calc_bar_width() { local term_width=80 local cols if cols=$(tput cols 2>/dev/null); then term_width=$cols elif [[ -n "$COLUMNS" ]]; then term_width=$COLUMNS fi local available=$(( (term_width - LAYOUT_MARGIN) / 2 )) if (( available < BAR_WIDTH_BASE )); then BAR_WIDTH=$BAR_WIDTH_BASE elif (( available > BAR_WIDTH_MAX )); then BAR_WIDTH=$BAR_WIDTH_MAX else BAR_WIDTH=$available fi } # --- 绘制进度条函数 --- draw_bar() { local percent=$1 if ! [[ "$percent" =~ ^[0-9]+$ ]]; then percent=0; fi local filled=$((percent * BAR_WIDTH / 100)) if (( percent > 0 && filled == 0 )); then filled=1 fi local empty=$((BAR_WIDTH - filled)) local GREEN='\033[32m' local YELLOW='\033[33m' local RED='\033[31m' local CYAN='\033[36m' local NC='\033[0m' if (( percent > 80 )); then COLOR=$RED elif (( percent > 50 )); then COLOR=$YELLOW else COLOR=$GREEN fi local i printf "${CYAN}[${COLOR}" for ((i=0; i<filled; i++)); do printf "|"; done for ((i=0; i<empty; i++)); do printf " "; done printf "${CYAN}]${NC}" } # --- 设备查询函数 --- # 温度读取辅助函数(保留兼容,实际已通过循环直接赋值) get_thermal_temp() { local thermal_type="$1" for zone_path in /sys/class/thermal/thermal_zone*; do if [ -f "$zone_path/type" ] && [ "$(cat "$zone_path/type" 2>/dev/null)" = "$thermal_type" ]; then local temp_raw=$(cat "$zone_path/temp" 2>/dev/null) if [ -n "$temp_raw" ] && [[ "$temp_raw" =~ ^[0-9]+$ ]]; then awk -v t="$temp_raw" 'BEGIN {printf "%.1f°C", t / 1000}' return 0 fi fi done echo "N/A" } # 1. 查询 NPU 状态 query_npu_status() { if [[ -f "$NPU_LOAD_FILE" ]]; then read -r NPU_CORE0_LOAD NPU_CORE1_LOAD NPU_CORE2_LOAD <<< $(awk '{gsub(/%|,/,""); print $4, $6, $8}' "$NPU_LOAD_FILE" 2>/dev/null) else NPU_CORE0_LOAD=0; NPU_CORE1_LOAD=0; NPU_CORE2_LOAD=0 fi if [[ -f "$NPU_FREQ_FILE" ]]; then NPU_FREQ=$(awk '{printf "%.2f", $1/1000000000}' "$NPU_FREQ_FILE" 2>/dev/null) else NPU_FREQ="N/A" fi } # 2. 查询 GPU 状态 query_gpu_status() { if [[ -f "$GPU_FILE" ]]; then read -r GPU_LOAD GPU_FREQ <<< $(cat "$GPU_FILE" | awk -F'@' '{gsub(/Hz/, "", $2); printf "%d %.2f", $1, $2/1000000000}') else GPU_LOAD=0 GPU_FREQ="N/A" fi } # 3. 查询 RGA 状态 query_rga_status() { if [[ -f "$RGA_LOAD_FILE" ]]; then local rga_loads=( $(cat "$RGA_LOAD_FILE" | awk '/load = [0-9]/ {print $3}' | tr -d '%') ) RGA_LOAD0=${rga_loads[0]:-0} RGA_LOAD1=${rga_loads[1]:-0} RGA_LOAD2=${rga_loads[2]:-0} else RGA_LOAD0=0; RGA_LOAD1=0; RGA_LOAD2=0 fi [[ "$RGA_LOAD0" =~ ^[0-9]+$ ]] || RGA_LOAD0=0 [[ "$RGA_LOAD1" =~ ^[0-9]+$ ]] || RGA_LOAD1=0 [[ "$RGA_LOAD2" =~ ^[0-9]+$ ]] || RGA_LOAD2=0 local clk_data=$(cat /sys/kernel/debug/clk/clk_summary 2>/dev/null | grep rga) RGA_FREQ0=$(echo "$clk_data" | awk '$1 == "clk_rga3_0_core" {printf "%.2f", $5/1000000000}') RGA_FREQ1=$(echo "$clk_data" | awk '$1 == "clk_rga3_1_core" {printf "%.2f", $5/1000000000}') RGA_FREQ2=$(echo "$clk_data" | awk '$1 == "clk_rga2_core" {printf "%.2f", $5/1000000000}') } # 4. 查询 CPU 状态 query_cpu_status() { CPU_CORE_COUNT=$(grep -c "^cpu[0-9]" "$PROC_STAT_FILE") local idx=0 while read -r line; do if [[ "$line" =~ ^cpu[0-9]+ ]]; then read -r _ user nice system idle iowait irq softirq steal _ <<< "$line" local curr_total=$((user + nice + system + idle + iowait + irq + softirq + steal)) local curr_idle=$((idle + iowait)) if [[ $CPU_FIRST_RUN -eq 1 ]]; then CPU_LOAD[$idx]=0 else local diff_total=$((curr_total - CPU_PREV_TOTAL[$idx])) local diff_idle=$((curr_idle - CPU_PREV_IDLE[$idx])) if (( diff_total > 0 )); then CPU_LOAD[$idx]=$(( (diff_total - diff_idle) * 100 / diff_total )) else CPU_LOAD[$idx]=0 fi fi CPU_PREV_TOTAL[$idx]=$curr_total CPU_PREV_IDLE[$idx]=$curr_idle local freq_file="$CPU_FREQ_BASE_PATH/cpu${idx}/cpufreq/scaling_cur_freq" if [[ -f "$freq_file" ]]; then local freq_khz=$(cat "$freq_file" 2>/dev/null) CPU_FREQ[$idx]=$(awk "BEGIN {printf \"%.4f\", $freq_khz/1000000}") else CPU_FREQ[$idx]="N/A" fi ((idx++)) fi done < "$PROC_STAT_FILE" CPU_FIRST_RUN=0 } display_cpu_status() { if [[ $CPU_CORE_COUNT -gt 0 ]]; then half=$(( (CPU_CORE_COUNT + 1) / 2 )) for ((i=0; i<half; i++)); do left_idx=$i right_idx=$((i + half)) left_load=${CPU_LOAD[$left_idx]:-0} left_freq=${CPU_FREQ[$left_idx]:-"N/A"} printf " CPU%-2d: " "$left_idx" draw_bar "$left_load" printf " %3d%% @ %s GHz" "$left_load" "$left_freq" printf "\t" if [[ $right_idx -lt $CPU_CORE_COUNT ]]; then right_load=${CPU_LOAD[$right_idx]:-0} right_freq=${CPU_FREQ[$right_idx]:-"N/A"} printf "CPU%-2d: " "$right_idx" draw_bar "$right_load" printf " %3d%% @ %s GHz" "$right_load" "$right_freq" fi printf "\n" done fi } # 5. 查询温度 query_temperature() { #local sensors_output #sensors_output=$(sensors 2>/dev/null) #SOC_TEMP=$(echo "$sensors_output" | awk '/^soc_thermal/{getline; getline; print $2}') #LITTLE_CORE_TEMP=$(echo "$sensors_output" | awk '/^littlecore_thermal/{getline; getline; print $2}') #BIG_CORE0_TEMP=$(echo "$sensors_output" | awk '/^bigcore0_thermal/{getline; getline; print $2}') #BIG_CORE1_TEMP=$(echo "$sensors_output" | awk '/^bigcore1_thermal/{getline; getline; print $2}') #NPU_TEMP=$(echo "$sensors_output" | awk '/^npu_thermal/{getline; getline; print $2}') #GPU_TEMP=$(echo "$sensors_output" | awk '/^gpu_thermal/{getline; getline; print $2}') # 初始化所有温度变量为默认值 SOC_TEMP="N/A" LITTLE_CORE_TEMP="N/A" BIG_CORE0_TEMP="N/A" BIG_CORE1_TEMP="N/A" GPU_TEMP="N/A" # 一次遍历所有温度传感器,匹配名称后赋值给对应变量 for zone in /sys/class/thermal/thermal_zone*; do if [[ ! -f "$zone/type" || ! -f "$zone/temp" ]]; then continue fi local zone_type=$(cat "$zone/type" 2>/dev/null) local temp_raw=$(cat "$zone/temp" 2>/dev/null) if [[ "$temp_raw" =~ ^[0-9]+$ ]]; then local temp_str=$(awk -v t="$temp_raw" 'BEGIN {printf "%.1f°C", t / 1000}') case "$zone_type" in "soc-thermal") SOC_TEMP="$temp_str" ;; "littlecore-thermal") LITTLE_CORE_TEMP="$temp_str" ;; "bigcore0-thermal") BIG_CORE0_TEMP="$temp_str" ;; "bigcore1-thermal") BIG_CORE1_TEMP="$temp_str" ;; "gpu-thermal") GPU_TEMP="$temp_str" ;; esac fi done # NPU温度:直接读取指定的固定路径 if [[ -f "$NPU_TEMP_FILE" ]]; then local npu_temp_raw=$(cat "$NPU_TEMP_FILE" 2>/dev/null) if [[ "$npu_temp_raw" =~ ^[0-9]+$ ]]; then NPU_TEMP=$(awk -v t="$npu_temp_raw" 'BEGIN {printf "%.1f°C", t / 1000}') else NPU_TEMP="N/A" fi else NPU_TEMP="N/A" fi } # 6. 内存&交换分区查询 query_memory_status() { read -r mt mf mb mc st sf < <( awk ' /^MemTotal/ {mt=$2} /^MemFree/ {mf=$2} /^Buffers/ {mb=$2} /^Cached/ {mc=$2} /^SwapTotal/ {st=$2} /^SwapFree/ {sf=$2} END {print mt+0, mf+0, mb+0, mc+0, st+0, sf+0} ' "$MEM_INFO_FILE" ) # 内存计算 KB -> MB local mem_used_kb=$(( mt - mf - mb - mc )) MEM_TOTAL=$(( mt / 1024 )) MEM_USED=$(( mem_used_kb / 1024 )) if (( mt > 0 )); then MEM_USED_PERCENT=$(( mem_used_kb * 100 / mt )) else MEM_USED_PERCENT=0 fi # 交换分区计算 local swap_used_kb=$(( st - sf )) SWAP_TOTAL=$(( st / 1024 )) SWAP_USED=$(( swap_used_kb / 1024 )) if (( st > 0 )); then SWAP_USED_PERCENT=$(( swap_used_kb * 100 / st )) else SWAP_USED_PERCENT=0 fi } # 7. 【新增】磁盘存储空间查询 query_disk_status() { local disk_info disk_info=$(df -P "$DISK_MONITOR_PATH" 2>/dev/null | awk 'NR==2 {print $2, $3, $5}') read -r d_total_1k d_used_1k d_pct < <(echo "$disk_info") # 1K块 转为 MB DISK_TOTAL=$(( d_total_1k / 1024 )) DISK_USED=$(( d_used_1k / 1024 )) # 去除百分号 DISK_USED_PERCENT=${d_pct%\%} # 容错 [[ "$DISK_USED_PERCENT" =~ ^[0-9]+$ ]] || DISK_USED_PERCENT=0 } # 定义清屏重绘函数 redraw_screen() { clear tput cup 0 0 calc_bar_width } # 捕获窗口变化信号 trap redraw_screen SIGWINCH # 初始化终端,隐藏光标,退出恢复 tput civis trap 'tput cnorm; exit' INT EXIT # --- 主循环 --- redraw_screen while true; do tput cup 0 0 # 依次查询所有硬件状态 query_npu_status query_gpu_status query_rga_status query_cpu_status query_temperature query_memory_status query_disk_status # 新增磁盘查询 # 绘制界面头部 echo -e " Rockchip Monitor (Refresh: "$REFRESH_TIME"s)\t\tTime: $(date +"%H:%M:%S")" echo -e "--------------------" # --- 内存 & 交换分区区域 --- echo -e " Memory & Swap Status:" printf " Memory: "; draw_bar "$MEM_USED_PERCENT" printf " %3d%% | Used: %d MB / Total: %d MB\n" "$MEM_USED_PERCENT" "$MEM_USED" "$MEM_TOTAL" printf " Swap : "; draw_bar "$SWAP_USED_PERCENT" printf " %3d%% | Used: %d MB / Total: %d MB\n" "$SWAP_USED_PERCENT" "$SWAP_USED" "$SWAP_TOTAL" # --- 【新增】磁盘存储区域(Swap 下方)--- printf " Disk : "; draw_bar "$DISK_USED_PERCENT" printf " %3d%% | Used: %d MB / Total: %d MB\n" "$DISK_USED_PERCENT" "$DISK_USED" "$DISK_TOTAL" echo -e "" # --- CPU 区域 --- echo -e " CPU Status:" display_cpu_status printf " SOC temperature: %s \n" "$SOC_TEMP" printf " Little cores temperature: %s \n" "$LITTLE_CORE_TEMP" printf " Big core0 temperature: %s \n Big core1 temperature: %s \n" "$BIG_CORE0_TEMP" "$BIG_CORE1_TEMP" echo -e "" # --- NPU 区域 --- echo -e " ========================================" echo -e " NPU Status:" printf " Core0: "; draw_bar "$NPU_CORE0_LOAD"; printf " %3d%% @ %s GHz\n" "$NPU_CORE0_LOAD" "${NPU_FREQ}" printf " Core1: "; draw_bar "$NPU_CORE1_LOAD"; printf " %3d%% @ %s GHz\n" "$NPU_CORE1_LOAD" "${NPU_FREQ}" printf " Core2: "; draw_bar "$NPU_CORE2_LOAD"; printf " %3d%% @ %s GHz\n" "$NPU_CORE2_LOAD" "${NPU_FREQ}" printf " NPU temperature: %s \n" "$NPU_TEMP" echo -e " ========================================" echo -e "" # --- GPU 区域 --- echo -e " GPU Status:" printf " Util : "; draw_bar "$GPU_LOAD"; printf " %3d%% @ %s GHz\n" "$GPU_LOAD" "$GPU_FREQ" printf " GPU temperature: %s \n" "$GPU_TEMP" echo -e "" # --- RGA 区域 --- echo -e " RGA Status (Video Proc):" printf " RGA3_0: "; draw_bar "$RGA_LOAD0"; printf " %3d%% @ %s GHz\n" "$RGA_LOAD0" "${RGA_FREQ0:-N/A}" printf " RGA3_1: "; draw_bar "$RGA_LOAD1"; printf " %3d%% @ %s GHz\n" "$RGA_LOAD1" "${RGA_FREQ1:-N/A}" printf " RGA2 : "; draw_bar "$RGA_LOAD2"; printf " %3d%% @ %s GHz\n" "$RGA_LOAD2" "${RGA_FREQ2:-N/A}" # ========== 新增:所有温度传感器列表 ========== echo -e " \n All Thermal Sensors:" for zone in /sys/class/thermal/thermal_zone*; do printf " %-20s %s\n" "$(cat $zone/type):" "$(awk '{printf "%.1f°C", $1/1000}' $zone/temp)" done # ============================================== echo -e "--------------------" echo -e " Press Ctrl+C to exit..." sleep $REFRESH_TIME done

七、其他优化配置及问题

http://www.gsyq.cn/news/1537231.html

相关文章:

  • 2026上海名包回收门店汇总:5家甄选好评门店,各有千秋 - 奢侈品回收测评
  • 合肥南亚理工学校招生电话,热门专业,报名要求,收费标准,学校位置详情 - hflgzz
  • 佛山冰箱维修漏水怎么办?2026年专业检修方案与平台对比分析 - 简单到家
  • 武汉黄金回收避坑指南:四种套路一次拆穿,帮你少走很多弯路 - 奢侈品回收测评
  • go | 环境安装和快速入门
  • Nano Banana Pro:专业级AI图像生成的四大底层突破
  • 2026年宁波减肥训练营2026宁波封闭式减肥训练营深度实测:吃住全包 + 签约减重,东吴这家营地凭实力打破行业乱象 - 速递信息
  • 海口家电维修平台服务对比:2026年行业数据驱动的消费决策参考 - 简单到家
  • 无锡哪家宠舍靠谱 7家实地探访给出答案 - 园友3800037
  • OpenClaw本地AI工作流部署全解析:PowerShell、Ollama镜像与Qwen3.5:9b实战
  • 【问答】青岛防水维修一般质保多久?不同部位质保标准参考 - 青岛防水品牌推荐
  • Python 数据分析实战:Pandas+Matplotlib 从入门到可视化报表
  • 解锁AI写专著密码!AI专著撰写工具,20万字专著快速成型!
  • 2026实测推荐:小红书视频怎么去水印?复制链接就能解析保存的3个小程序 - 效率工具研究所
  • 20251202马思钊 2025-2026-2 实验四 Python综合实践
  • 新手在无锡买猫狗 哪家宠物门店值得信赖? - 园友3800037
  • BallonTranslator:让漫画翻译变得像聊天一样简单的AI工具
  • 2026 粘结钕铁硼厂家推荐|高精度异形磁体定制,新能源电机磁瓦生产厂商 - 商业新知
  • Steam Deck控制器Windows驱动完全指南:SWICD让你的游戏体验无缝衔接
  • 2026 好用的素颜霜早八通勤实测|100 人 28 天横评榜单 黄皮自然抗暗沉优选 - 速递信息
  • 2026银行秋招面试技巧班深度评测:4家头部机构对比,谁能帮你突破最后一关 - 互联网科技品牌测评
  • 杭州购宠避坑指南:4家靠谱实体门店实测推荐 - 园友3800037
  • 2026银行网申修改机构横向评测:精准适配不同考生,破解网申死难题 - 互联网科技品牌测评
  • 无锡购宠避坑指南 7家正规实体繁育门店实测推荐 - 园友3800037
  • 北京卖表必看!全网高口碑奢侈品名表回收门店测评|本地6大商家客观排名 - 名奢变现站
  • 长沙雨花区下水道疏通 2026 真实评测最新综合排行榜 - 居顺联家政疏通
  • 二手欧米茄出手别乱询价,2026南京正规回收门店报价透明实测 - 奢侈品回收评测
  • Rescuezilla终极指南:3个简单步骤实现系统备份与恢复
  • 2026济南黄金回收测评打分:添价收99分摘冠,七家品牌全维度评分 - 薛定谔的梨花猫
  • 解决macOS多设备滚动冲突的智能方案