)
一、RK3588整体架构概览项目类型型号参数说明核心配置处理器RK3588CPUQuad-core ARM Cortex-A762.4GHzQuad-core ARM Cortex-A551.8GHGPU四核 ARM Mali-G610 MP4NPU算力 6.0TOPs内存LPDDR4默认配置8GByte可选配置4GByte/16GByte存储eMMC默认配置32GByte可选配置64GByte本机配置RK3588/8GByte/64GByte二、软件资源2.1、英码科技官方SDKhttps://pan.baidu.com/s/1QsDRVisbcaC2X1sd54ac5A?pwdwbdn 提取码wbdn链接失效了找英码官方要https://www.ema-tech.com/technologySDK出货镜像烧录工具2.2、rockchip_RKLLM_SDKhttps://github.com/airockchip/rknn-llm2.3、hf-mirror原版Qwen2.5-3B-Instruct$:export HF_ENDPOINThttps://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/versionRKNPU driver:v0.9.83.2、PC Ubuntu 20.04 x86_64 / Ubuntu 22.04 x86_64 kernel 5.10/kernel 6.11632G3.3、板端 Ubuntu 20.04/Ubuntu 22.04kernel 5.10/kernel 6.1#系统版本 uname -v #或 cat /etc/issue#内核版本 uname -r #或 cat /proc/version3.4、本机PCUbuntu 22.04 x86_64 python3.10板端Ubuntu 20.04/kernel 5.10python 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 ax /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.24.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 directlba1,first4access1,gpt1 Download boot start...(0x00008000) Download image ok.系统重启板端查看NPU驱动版本$sudo cat /sys/kernel/debug/rknpu/version RKNPU driver:v0.9.8五、PC: X86 电脑模型量化转换 HF 原生→.rkllmubuntu 22.045.1、安装conda和rkllm-toolkitrkllm_toolkit-1.2.3 及依赖。conda#创建虚拟环境 conda create --name rkllm310 python3.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 torch2.6.0 transformers4.55.2 numpy1.26.4 accelerate1.5.2 Jinja23.1.4 safetensors0.5.3 sentencepiece0.2.0 --force-reinstall# 打印所有核心依赖的当前版本 pip list | grep -E torch|transformers|numpy|accelerate|sentencepiece|safetensors|Jinja25.2、下载hf-mirror原版Qwen2.5-3B-Instruct#下载模型到文件夹./Qwen2.5-3B $:export HF_ENDPOINThttps://hf-mirror.com $:hf download Qwen/Qwen2.5-3B-Instruct --local-dir ./Qwen2.5-3B5.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_DEVICES0 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(modelmodelpath, model_lora None, devicecuda, dtypefloat32, custom_configNone, load_weightTrue) # 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 inputlike 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_quantizationTrue, optimization_leveloptimization_level, quantized_dtypequantized_dtype, quantized_algorithmquantized_algorithm, target_platformtarget_platform, num_npu_corenum_npu_core, extra_qparamsqparams, datasetdataset, hybrid_rate0, max_context4096) 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) admainD/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 ldconfig6.2、模型调用及demorockchip_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出现以下信息运行成功emaema:~/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 success6.3、token/s 测试RKLLM 的 llm_demo不需要额外装工具只要开一条环境变量就能自动打印 token/sexport RKLLM_LOG_LEVEL1然后正常启动模型./llm_demo /home/ema/3588/models/Qwen2.5-3B-Instruct_w8a8_rk3588.rkllm 256 4096每次对话结束终端会自动输出类似下面的token/s 结果6.4、NPU 定频1. NPU的节点路径emaema:~/桌面$ 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_stat2. 获取NPU支持的频点emaema:~/桌面$ cat /sys/class/devfreq/fdab0000.npu/available_frequencies 300000000 400000000 500000000 600000000 700000000 800000000 900000000 1000000000最高1GHZ3. 获取NPU运行的模式emaema:~/桌面$ cat /sys/class/devfreq/fdab0000.npu/available_governors rknpu_ondemand dmc_ondemand userspace powersave performance simple_ondemandperformance:性能模式强制锁定 NPU 运行在最高主频1GHz无论负载高低都保持满频不自动降频。powersave省电模式强制锁定 NPU 运行在最低主频300MHz功耗和发热降到最低。userspace用户空间控频模式将调频权限完全开放给用户层由你手动指定具体运行频率必须是支持的频点。simple_ondemand简易按需调频模式ux 通用的动态调速策略根据 NPU 负载自动升降频。dmc_ondemand内存控制器联动调频联动动态内存控制器DMC根据 NPU 计算负载 内存带宽需求联合调频优化高带宽场景的访问效率。4、查看当前模式频率#模式 emaema:~/桌面$ cat /sys/class/devfreq/fdab0000.npu/governor performance #频率 emaema:~/桌面$ cat /sys/class/devfreq/fdab0000.npu/cur_freq 10000000005、模式配置设置频率#设置模式 emaema:~/桌面$ 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 #无权限使用以下命令 emaema:~/桌面$ echo userspace | sudo tee /sys/class/devfreq/fdab0000.npu/governor userspace emaema:~/桌面$ cat /sys/class/devfreq/fdab0000.npu/governor userspace emaema:~/桌面$ echo 800000000 | sudo tee /sys/class/devfreq/fdab0000.npu/userspace/set_freq 800000000 emaema:~/桌面$ cat /sys/class/devfreq/fdab0000.npu/cur_freq 8000000006、负载温度#负载 三核 emaema:~/桌面$ sudo cat /sys/kernel/debug/rknpu/load NPU load: Core0: 78%, Core1: 80%, Core2: 79%, #温度 value/1000 emaema:~/桌面$ cat /sys/class/thermal/thermal_zone6/temp 462306.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_LOAD0 NPU_CORE1_LOAD0 NPU_CORE2_LOAD0 NPU_FREQN/A NPU_TEMP0 # GPU GPU_LOAD0 GPU_FREQN/A GPU_TEMP0 # RGA RGA_LOAD00 RGA_LOAD10 RGA_LOAD20 RGA_FREQ0N/A RGA_FREQ1N/A RGA_FREQ2N/A # CPU declare -a CPU_LOAD declare -a CPU_FREQ declare -a CPU_PREV_TOTAL declare -a CPU_PREV_IDLE CPU_CORE_COUNT0 CPU_FIRST_RUN1 SOC_TEMP0 LITTLE_CORE_TEMP0 BIG_CORE0_TEMP0 BIG_CORE1_TEMP0 # 内存/交换分区 MEM_TOTAL0 MEM_USED0 MEM_USED_PERCENT0 SWAP_TOTAL0 SWAP_USED0 SWAP_USED_PERCENT0 # 磁盘存储新增 DISK_TOTAL0 DISK_USED0 DISK_USED_PERCENT0 # --- 权限检查与自动提权 --- 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_BASE5 BAR_WIDTH_MAX40 LAYOUT_MARGIN65 REFRESH_TIME0.5 # 动态计算 BAR_WIDTH calc_bar_width() { local term_width80 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 percent0; fi local filled$((percent * BAR_WIDTH / 100)) if (( percent 0 filled 0 )); then filled1 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 ((i0; ifilled; i)); do printf |; done for ((i0; iempty; 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_LOAD0; NPU_CORE1_LOAD0; NPU_CORE2_LOAD0 fi if [[ -f $NPU_FREQ_FILE ]]; then NPU_FREQ$(awk {printf %.2f, $1/1000000000} $NPU_FREQ_FILE 2/dev/null) else NPU_FREQN/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_LOAD0 GPU_FREQN/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_LOAD00; RGA_LOAD10; RGA_LOAD20 fi [[ $RGA_LOAD0 ~ ^[0-9]$ ]] || RGA_LOAD00 [[ $RGA_LOAD1 ~ ^[0-9]$ ]] || RGA_LOAD10 [[ $RGA_LOAD2 ~ ^[0-9]$ ]] || RGA_LOAD20 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 idx0 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_RUN0 } display_cpu_status() { if [[ $CPU_CORE_COUNT -gt 0 ]]; then half$(( (CPU_CORE_COUNT 1) / 2 )) for ((i0; ihalf; 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_TEMPN/A LITTLE_CORE_TEMPN/A BIG_CORE0_TEMPN/A BIG_CORE1_TEMPN/A GPU_TEMPN/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_TEMPN/A fi else NPU_TEMPN/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 mt0, mf0, mb0, mc0, st0, sf0} $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_PERCENT0 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_PERCENT0 fi } # 7. 【新增】磁盘存储空间查询 query_disk_status() { local disk_info disk_info$(df -P $DISK_MONITOR_PATH 2/dev/null | awk NR2 {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_PERCENT0 } # 定义清屏重绘函数 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_TIMEs)\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 CtrlC to exit... sleep $REFRESH_TIME done七、其他优化配置及问题