EVM3588-B开发板+NPU+Qwen2.5-3B-Instruct(一)
一、RK3588整体架构概览

| 项目 | 类型 | 型号参数 | 说明 | |
| 核心配置 | 处理器 | RK3588 | CPU |
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

七、其他优化配置及问题
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)