使用指南

本文档介绍Quectel Pi H1智能主控板的常用功能和使用方法,包括音频与多媒体、机器学习、系统配置与监控、40-pin与接口扩展、网络与通信、图形与显示、摄像头方案、存储设备、核心资源与性能、电源与功耗、USB与扩展外设等内容。

音频与多媒体

PulseAudio音频服务

PulseAudio是Linux环境下主流的音频服务系统,它介于应用程序和底层音频架构(TinyALSA)之间,负责管理音频流、混合多路音频以及路由到不同的输出设备。

PulseAudio概述

PulseAudio是一个跨平台的、可通过网络工作的声音服务,它从一个或多个音源(进程或输入设备)接受声音输入,然后重定向声音到一个或多个槽(声卡,远程网络PulseAudio服务,或其他进程)。它与最底层的ALSA(Advanced Linux Sound Architecture)交互,并为应用程序提供统一的接口,从而实现多路音频混合、音频转发等高级功能。

查看声卡信息

在终端中输入如下命令,查看声卡的挂载情况:

root@qcm6490-idp:/opt# cat /proc/asound/cards
 0 [qcm6490idpsndca]: qcm6490 - qcm6490-idp-snd-card
                      qcm6490-idp-snd-card

设备查看与管理

查看可用输出设备(Sinks)

如需查看系统当前可用的音频输出设备及其详细信息,可以使用以下命令,此命令会列出所有可用的sink(输出设备)的索引(index)和名称(name)。输出示例:

root@qcm6490-idp:/# pactl list short sinks
*       0       low-latency0    module-pal-card.c       s16le 1ch 16000Hz       SUSPENDED
1       deep-buffer0    module-pal-card.c       s16le 2ch 48000Hz       SUSPENDED
2       offload0        module-pal-card.c       s16le 2ch 48000Hz       SUSPENDED
3       voip-rx0        module-pal-card.c       s16le 2ch 48000Hz       SUSPENDED

其中,*号标记表示当前默认的输出设备。

如需获取更详细的设备信息,请使用:

root@qcm6490-idp:/# pactl list sinks
Sink #0
        State: SUSPENDED
        Name: low-latency0
        Description: pal sink to play via low-latency path
        Driver: module-pal-card.c
        Sample Specification: s16le 1ch 16000Hz
        Channel Map: mono
        Owner Module: 1
        Mute: no
        Volume: mono: 65536 / 100%
                balance 0.00
        Base Volume: 65536 / 100%
        Monitor Source: low-latency0.monitor
        Latency: 0 usec, configured 0 usec
        Flags: HARDWARE HW_VOLUME_CTRL LATENCY
        Properties:
                device.string = "low_latency"
                device.description = "pal sink to play via low-latency path"
                device.icon_name = "audio-card"
        Ports:
                speaker: speaker (type: Unknown, priority: 200, available)
                headset: headset (type: Unknown, priority: 100, available)
        Active Port: speaker
        Formats:
                pcm

Sink #1
        State: SUSPENDED
        Name: deep-buffer0
        Description: pal sink to play via deep buffer path
        Driver: module-pal-card.c
        Sample Specification: s16le 2ch 48000Hz
        Channel Map: front-left,front-right
        Owner Module: 1
        Mute: no
        Volume: front-left: 65536 / 100%,   front-right: 65536 / 100%
                balance 0.00
        Base Volume: 65536 / 100%
        Monitor Source: deep-buffer0.monitor
        Latency: 0 usec, configured 0 usec
        Flags: HARDWARE HW_VOLUME_CTRL LATENCY
        Properties:
                device.string = "deep_buffer"
                device.description = "pal sink to play via deep buffer path"
                device.icon_name = "audio-card"
        Ports:
                speaker: speaker (type: Unknown, priority: 200, available)
                headset: headset (type: Unknown, priority: 100, available)
                bta2dp-out: BT a2dp source port (type: Unknown, priority: 50, not available)
        Active Port: speaker
        Formats:
                pcm

Sink #2
        State: SUSPENDED
        Name: offload0
        Description: pal sink to play compressed via offload path
        Driver: module-pal-card.c
        Sample Specification: s16le 2ch 48000Hz
        Channel Map: front-left,front-right
        Owner Module: 1
        Mute: no
        Volume: front-left: 65536 / 100%,   front-right: 65536 / 100%
                balance 0.00
        Base Volume: 65536 / 100%
        Monitor Source: offload0.monitor
        Latency: 0 usec, configured 0 usec
        Flags: HARDWARE HW_VOLUME_CTRL LATENCY
        Properties:
                device.string = "offload"
                device.description = "pal sink to play compressed via offload path"
                device.icon_name = "audio-card"
        Ports:
                speaker: speaker (type: Unknown, priority: 200, available)
                headset: headset (type: Unknown, priority: 100, available)
                bta2dp-out: BT a2dp source port (type: Unknown, priority: 50, not available)
        Active Port: speaker
        Formats:
                mpeg
                aac

Sink #3
        State: SUSPENDED
        Name: voip-rx0
        Description: pal sink to play via voip rx path
        Driver: module-pal-card.c
        Sample Specification: s16le 2ch 48000Hz
        Channel Map: front-left,front-right
        Owner Module: 1
        Mute: no
        Volume: front-left: 65536 / 100%,   front-right: 65536 / 100%
                balance 0.00
        Base Volume: 65536 / 100%
        Monitor Source: voip-rx0.monitor
        Latency: 0 usec, configured 0 usec
        Flags: HARDWARE HW_VOLUME_CTRL LATENCY
        Properties:
                device.string = "voip_rx"
                device.description = "pal sink to play via voip rx path"
                device.icon_name = "audio-card"
        Ports:
                speaker: speaker (type: Unknown, priority: 200, available)
                headset: headset (type: Unknown, priority: 100, available)
                btsco-out: BT SCO sink port (type: Unknown, priority: 50, not available)
        Active Port: speaker
        Formats:
                pcm

查看输入设备(Sources)

类似地,可以查看音频输入设备(如麦克风):

root@qcm6490-idp:/# pactl list short sources
0       low-latency0.monitor    module-pal-card.c       s16le 1ch 16000Hz       SUSPENDED
1       deep-buffer0.monitor    module-pal-card.c       s16le 2ch 48000Hz       SUSPENDED
2       offload0.monitor        module-pal-card.c       s16le 2ch 48000Hz       SUSPENDED
3       voip-rx0.monitor        module-pal-card.c       s16le 2ch 48000Hz       SUSPENDED
4       regular0        module-pal-card.c       s16le 2ch 48000Hz       SUSPENDED
5       regular2        module-pal-card.c       s16le 2ch 48000Hz       SUSPENDED
6       voip-tx0        module-pal-card.c       s16le 1ch 48000Hz       SUSPENDED

录音

板载DMIC录音

root@qcm6490-idp:~# pactl set-source-port 5 speaker-mic
root@qcm6490-idp:~# parec -d 5 --file-format=wav output.wav

3.5 mm耳机录音

使用3.5 mm耳机录制前需将gpio8和gpio68电平置高。

root@qcm6490-idp:/opt# rgpiod &
root@qcm6490-idp:/opt# sleep 1
root@qcm6490-idp:/opt# rgs c 999 go 4
root@qcm6490-idp:/opt# rgs c 999 gso 0 8
root@qcm6490-idp:/opt# rgs c 999 gw 0 8 1
root@qcm6490-idp:/opt# rgs c 999 gso 0 68
root@qcm6490-idp:/opt# rgs c 999 gw 0 68 1
  • gpio8:耳机欧标/美标切换控制开关。0:欧标;1:美标
  • gpio68:耳机电源供电使能开关。0:禁用;1:使能
root@qcm6490-idp:~# pactl set-source-port 5 headset-mic
root@qcm6490-idp:~# parec -d 5 --file-format=wav output1.wav

播放

喇叭播放

GPIO控制PA的使能开关:

rgpiod &
sleep 1
rgs c 999 go 4
rgs c 999 gso 0 142
rgs c 999 gw 0 142 1
root@qcm6490-idp:~# pactl set-sink-port 0 speaker
root@qcm6490-idp:~# paplay output.wav

3.5 mm耳机播放

root@qcm6490-idp:~# pactl set-sink-port 0 headset
root@qcm6490-idp:~# paplay output1.wav

TinyALSA/AGM直连音频测试

Quectel Pi H1智能主控板支持外置MIC录制、3.5 mm耳机录制与播放等多种直连音频链路,以下示例基于TinyALSA/AGM工具链说明如何直接访问声卡。

查看声卡信息

  • 在终端中输入如下命令,查看声卡的挂载情况:
root@qcm6490-idp:/opt# cat /proc/asound/cards
 0 [qcm6490idpsndca]: qcm6490 - qcm6490-idp-snd-card
                      qcm6490-idp-snd-card
  • 在终端中输入如下命令,查看已分配的PCM流列表:
root@qcm6490-idp:/opt# cat /proc/asound/pcm
00-00: CODEC_DMA-LPAIF_RXTX-RX-0 multicodec-0 :  : playback 1
00-01: CODEC_DMA-LPAIF_RXTX-TX-3 multicodec-1 :  : capture 1
00-02: CODEC_DMA-LPAIF_VA-TX-0 va_macro_tx1-2 :  : capture 1

外置MIC录制

  1. 停止PulseAudio避免占用音频设备,并设置采集链路:
root@qcm6490-idp:/opt# systemctl stop pulseaudio
root@qcm6490-idp:/opt# tinymix set "VA DMIC MUX0" "DMIC0"
root@qcm6490-idp:/opt# tinymix set "VA_AIF1_CAP Mixer DEC0" "1"
root@qcm6490-idp:/opt# tinymix set "VA_DEC0 Volume" "100"
root@qcm6490-idp:/opt# agmcap test1.wav -D 100 -d 101 -c 1 -r 48000 -b 16 -i "CODEC_DMA-LPAIF_VA-TX-0"
  • -c 1:单声道录音
  • -r 48000:采样率48 kHz
  • -b 16:采样位深16-bit
  • -i "CODEC_DMA-LPAIF_VA-TX-0":指定输入设备接口
  1. Ctrl+C停止录制,当前目录生成test1.wav文件:
root@qcm6490-idp:/opt# ls
cni  containerd  test1.wav

3.5 mm耳机录制

  1. gpio8gpio68置高,打开耳机标准切换与电源:
root@qcm6490-idp:/opt# rgpiod &
root@qcm6490-idp:/opt# sleep 1
root@qcm6490-idp:/opt# rgs c 999 go 4
root@qcm6490-idp:/opt# rgs c 999 gso 0 8
root@qcm6490-idp:/opt# rgs c 999 gw 0 8 1
root@qcm6490-idp:/opt# rgs c 999 gso 0 68
root@qcm6490-idp:/opt# rgs c 999 gw 0 68 1
  1. 配置录制链路并开始采集:
root@qcm6490-idp:/opt# systemctl stop pulseaudio
root@qcm6490-idp:/opt# tinymix set "TX DEC0 MUX" "SWR_MIC" 
root@qcm6490-idp:/opt# tinymix set "TX SMIC MUX0" "ADC1" 
root@qcm6490-idp:/opt# tinymix set "TX_AIF1_CAP Mixer DEC0" "1" 
root@qcm6490-idp:/opt# tinymix set "ADC2 MUX" "INP2" 
root@qcm6490-idp:/opt# tinymix set "ADC2 Switch" "1" 
root@qcm6490-idp:/opt# tinymix set "ADC2_MIXER Switch" "1" 
root@qcm6490-idp:/opt# tinymix set "TX_DEC0 Volume" "80" 
root@qcm6490-idp:/opt# tinymix set "ADC2 Volume" "20" 
root@qcm6490-idp:/opt# agmcap test2.wav -D 100 -d 101 -c 1 -r 48000 -b 16 -i "CODEC_DMA-LPAIF_RXTX-TX-3"
  1. Ctrl+C停止录制,test2.wav文件生成在当前目录:
root@qcm6490-idp:/opt# ls
cni  containerd  test2.wav

3.5 mm耳机播放

  1. 同样先拉高gpio8gpio68以启用耳机:
root@qcm6490-idp:/opt# rgpiod &
root@qcm6490-idp:/opt# sleep 1
root@qcm6490-idp:/opt# rgs c 999 go 4
root@qcm6490-idp:/opt# rgs c 999 gso 0 8
root@qcm6490-idp:/opt# rgs c 999 gw 0 8 1
root@qcm6490-idp:/opt# rgs c 999 gso 0 68
root@qcm6490-idp:/opt# rgs c 999 gw 0 68 1
  1. 设置播放路径并使用agmplay输出音频:
root@qcm6490-idp:/opt# systemctl stop pulseaudio
root@qcm6490-idp:/opt# tinymix set "RX_MACRO RX0 MUX" "AIF1_PB" 
root@qcm6490-idp:/opt# tinymix set "RX_MACRO RX1 MUX" "AIF1_PB" 
root@qcm6490-idp:/opt# tinymix set "RX INT0_1 MIX1 INP0" "RX0" 
root@qcm6490-idp:/opt# tinymix set "RX INT1_1 MIX1 INP0" "RX1" 
root@qcm6490-idp:/opt# tinymix set "RX INT0 DEM MUX" "CLSH_DSM_OUT" 
root@qcm6490-idp:/opt# tinymix set "RX INT1 DEM MUX" "CLSH_DSM_OUT" 
root@qcm6490-idp:/opt# tinymix set "RX_COMP1 Switch" "1" 
root@qcm6490-idp:/opt# tinymix set "RX_COMP2 Switch" "1"
root@qcm6490-idp:/opt# tinymix set "HPHL Switch" "1" 
root@qcm6490-idp:/opt# tinymix set "HPHR Switch" "1" 
root@qcm6490-idp:/opt# tinymix set "HPHL_RDAC Switch" "1" 
root@qcm6490-idp:/opt# tinymix set "HPHR_RDAC Switch" "1" 
root@qcm6490-idp:/opt# agmplay test.wav -D 100 -d 100 -i "CODEC_DMA-LPAIF_RXTX-RX-0"
  • 音频播放完会自动停止,若想提前停止,可按Ctrl+C

机器学习

NPU应用场景

Quectel Pi H1智能主控板中,NPU资源应用场景包括:图像分类、目标检测、语义分割等。该章节以图像分类中的ResNeXt50机器学习模型为例,该模型可以对 Imagenet 数据集中的图像进行分类,也可以作为构建更复杂模型的主干,用于特定用例。

下载量化模型

部署模型

  1. 将模型和标签文件部署到Quectel Pi H1中,通过adb或者scp把这两个部署到 /opt目录下。

  2. 模型特性:

    • 模型检查点:Imagenet
    • 输入分辨率:224 x 224
    • 参数数量:88.7 M
    • 模型大小:87.3 MB

连接显示器

准备显示器,并连接显示器到Quectel Pi H1上。

运行命令

在设备终端运行如下命令以确保结果显示在连接的显示器上:

export XDG_RUNTIME_DIR=/dev/socket/weston && export WAYLAND_DISPLAY=wayland-1

在设备中运行以下命令:

gst-launch-1.0 -e --gst-debug=2 filesrc location=/opt/video11.mp4 ! qtdemux ! queue ! h264parse ! v4l2h264dec capture-io-mode=5 output-io-mode=5 ! queue ! tee name=split split. ! queue ! qtivcomposer name=mixer sink_1::position="<30, 30>" sink_1::dimensions="<640, 360>" ! queue ! waylandsink sync=true fullscreen=true split. ! queue ! qtimlvconverter ! queue ! qtimltflite delegate=external external-delegate-path=libQnnTFLiteDelegate.so external-delegate-options="QNNExternalDelegate,backend_type=htp;" model=/opt/resnext50_quantized.tflite ! queue ! qtimlvclassification threshold=35.0 results=5 module=mobilenet labels=/opt/imagenet_labels.txt extra-operation=softmax constants="Resnetnet,q-offsets=<30.0>,q-scales=<0.06314703077077866>;" ! video/x-raw,format=BGRA,width=256,height=144 ! queue ! mixer.

命令说明

  • gst-launch-1.0:这是GStreamer的命令行工具,用于启动一个GStreamer管道(pipeline)。其后的 -e参数表示在管道结束时退出,而不是继续运行。
  • --gst-debug=2:设置调试级别为2,显示调试信息。
  • filesrc location=/opt/video11.mp4:指定输入视频文件路径。
  • !:是一个连接符号,用于将前一个元素的输出连接到后一个元素的输入。
  • qtdemux:将输入视频文件解析为多个流。
  • queue:用于缓冲输入数据。
  • h264parse:将输入数据解析为H.264格式数据。
  • v4l2h264dec:将H.264格式的数据解码为YUV格式。
  • capture-io-mode=5:指定解码器输入端口(Capture Side)的内存访问模式。
  • output-io-mode=5:指定解码器输出端口(Output Side)的内存访问模式。
  • tee name=split:将输入数据分割为两个分支。
  • split.:第一个分支用于显示原始视频流。
  • qtivcomposer:用于组合多个视频流。
  • waylandsink:将组合后的视频流显示在屏幕上。
  • split.:第二个分支用于进行图像分类。
  • qtimlvconverter:用于将输入数据转换为模型输入格式。
  • qtimltflite:用于执行模型推理。
  • delegate=external:使用外部加速库(即非TFLite默认的CPU后端)来运行模型推理,通常用于调用硬件加速器。
  • external-delegate-path=libQnnTFLiteDelegate.so:指定TensorFlow Lite的外部加速库(Delegate)的路径。
  • external-delegate-options="QNNExternalDelegate,backend_type=htp;":指定外部加速库的选项,这里指定了后端类型为HTP(High-Throughput Processing)。
  • model=/opt/resnext50_quantized.tflite:指定模型路径。
  • qtimlvclassification:用于对模型输出进行分类。
  • video/x-raw,format=BGRA,width=256,height=144:指定输出视频格式和尺寸。
  • mixer:将两个分支的输出组合在一起。
  • threshold=35.0:设置置信度阈值,用于过滤低置信度的分类结果。
  • results=5:设置返回的分类结果数量。
  • module=mobilenet:指定使用的模型名称。
  • labels=/opt/imagenet_labels.txt:指定标签文件路径。
  • extra-operation=softmax:对模型输出进行Softmax操作,得到每个类别的概率。
  • constants="Resnetnet,q-offsets=<30.0>,q-scales=<0.06314703077077866>;":指定模型量化参数。

运行结果

运行命令后,显示器会显示视频流和图像分类结果。

TensorFlow Lite简介

TensorFlow Lite是一套工具,通过帮助开发人员在移动设备、嵌入式设备和边缘设备上运行模型,实现设备机器学习。下面以姿态估计中的posenet机器学习模型为例,演示实时推理与显示流程。

下载posenet模型

部署模型

  1. 将模型和标签文件部署到Quectel Pi H1中,通过adb或者scp把文件放在 /opt/目录。
  2. 模型特性:
    • 模型检查点:mobilenet_v1_101
    • 输入分辨率:513 x 257
    • 参数数量:3.31 M
    • 模型大小:12.7 MB

连接摄像头和显示器

  • 准备MIPI摄像头,并连接到第一个CSI插槽。
  • 准备HDMI显示器,并连接至开发板。

使用TFLite进行姿势估计和显示

  1. 设置Wayland环境变量:
export XDG_RUNTIME_DIR=/dev/socket/weston && export WAYLAND_DISPLAY=wayland-1
  1. 启动实时姿势估计:
setprop persist.overlay.use_c2d_blit 2

gst-launch-1.0 -e \
qtiqmmfsrc name=camsrc camera=0 ! video/x-raw\(memory:GBM\),format=NV12,width=1280,height=720,framerate=30/1,compression=ubwc ! queue ! tee name=split \
split. ! queue ! qtimetamux name=metamux ! queue ! qtioverlay ! queue ! waylandsink fullscreen=true sync=false \
split. ! queue ! qtimlvconverter ! queue ! qtimltflite delegate=external external-delegate-path=libQnnTFLiteDelegate.so external-delegate-options="QNNExternalDelegate,backend_type=htp;" model=/opt/posenet_mobilenet_v1.tflite ! queue ! qtimlvpose threshold=51.0 results=2 module=posenet labels=/opt/posenet_mobilenet_v1.labels constants="Posenet,q-offsets=<128.0,128.0,117.0>,q-scales=<0.0784313753247261,0.0784313753247261,1.3875764608383179>;" ! text/x-raw ! queue ! metamux.

关键命令说明

  • gst-launch-1.0:构建GStreamer pipeline,-e确保结束时释放资源。
  • qtiqmmfsrc:基于QMMF的摄像头源,camera=0选择第一个CSI接口。
  • tee name=split:复制原始视频流,分别用于显示与推理。
  • qtimlvconverter:将NV12视频帧转换成模型输入张量。
  • qtimltflite:调用TensorFlow Lite + QNN delegate,以HTP加速模型推理。
  • qtimlvpose:对推理结果做姿态解码并输出人体关键点。
  • qtioverlay/qtimetamux:将关键点叠加到视频帧并通过waylandsink输出。

运行结果

运行命令后,显示器会显示camera流和姿势估计结果。测试示例


系统配置与监控

qpi_config 是一个用于配置 Quectel Pi H1 的工具,提供下列功能:

  1. 配置板载LED工作模式和亮度;
  2. 配置风扇接口工作模式和风扇转速;
  3. 配置40-Pin接口工作模式;
  4. 查询系统各组件温度;
  5. 查询系统CPU、内存和存储状态;
  6. 配置Wi-Fi。

板载LED配置

配置工作模式

qpi-config led mode <blue|green|red> <heartbeat|none>

配置亮度

qpi-config led brightness <blue|green|red> <0-511>

风扇配置

配置风扇转速

qpi-config fan set speed <0-255>

40-Pin接口工作模式配置

先修改配置文件 /etc/qpi-config/qpi-config.ini,再运行以下命令进行配置:

qpi-config 40pin set

查询系统各组件温度

qpi-config dump temperature

查询系统CPU、内存和存储状态

qpi-config dump systemusage

配置Wi-Fi

扫描Wi-Fi

qpi-config wifi scan

查看已存在Wi-Fi连接

qpi-config wifi show

查看Wi-Fi连接状态

qpi-config wifi dump <connection uuid>

添加Wi-Fi连接

qpi-config wifi connect <ssid> <password>

删除Wi-Fi连接

qpi-config wifi delete <connection uuid>

40PIN 与接口扩展


40-Pin中部分低速接口(I2C9/SPI10/UART12_2w/I2C13/SPI14)配置文件位于/etc/qpi-config/qpi-config.ini,配置步骤为:

  1. 修改qpi-config.ini配置
  2. 应用配置
qpi-config 40pin set
  1. 重启生效

GPIO测试

选取一个40-pinGPIO引脚来测试GPIO功能,例如选取40-pinPin3引脚进行测试,pin3对应的gpio_num36。各引脚对应的gpio_num信息可以从引脚映射表中查找。

连接示意图如下,其中红色线接万用表正极,白色线接万用表负极:

使用SHELL命令控制

系统已默认启用lgpiod服务,依次执行如下命令来测试40-pinPin3引脚的GPIO功能:

  • rgs c 999 go 4 #使用go命令打开文件 /dev/gpiochip4
  • rgs c 999 gso 0 36 #使用gso命令设置GPIO36为输出模式,这条命令里的 0是上一条命令的返回内容,根据实际情况修改
  • rgs c 999 gw 0 36 0 #设置GPIO36为低电平,这个时候测试引脚电压值为0 V
  • rgs c 999 gw 0 36 1 #设置GPIO36为高电平,这个时候测试引脚电压值为3.3 V

使用C代码控制

  • 新建gpio.c文件,内容如下:

    #include <stdlib.h>
    #include <lgpio.h>
    
    int main(int argc, char **argv)
    {
        int gpio_num = atoi(argv[1]);
        int pin_level = atoi(argv[2]);
        int handle = lgGpiochipOpen(4);
    
        lgGpioClaimOutput(handle, 0, gpio_num, 0);
        lgGpioWrite(handle, gpio_num, pin_level);
    }
    
  • 编译:gcc -o gpio gpio.c -llgpio

  • 执行:./gpio 36 0 #设置GPIO36为低电平,这个时候测试引脚电压值为0 V

  • 执行:./gpio 36 1 #设置GPIO36为高电平,这个时候测试引脚电压值为3.3 V

I2C测试

40-PinPin3Pin5默认是I2Cdataclock引脚,对应设备节点 /dev/i2c9,若节点未出现,您可以先使用本章介绍的qpi_config进行配置和使能。

测试I2C接口需要外接一个I2C设备,这里选择微雪环境传感器扩展板,通过40-Pin接口进行连接。

连接示意图:

图片1

微雪环境传感器扩展板

图片2

Quectel Pi H1 40-PIN引脚

图片3

插上环境传感器扩展板的Quectel Pi H1

使用C代码测试

测试步骤:

  • 新建 envtest.c 文件,内容如下:

    #include <stdio.h>
    #include <lgpio.h>
    
    #define I2C_DEV_NUM 9
    #define BME280_ADDR 0x76
    
    int32_t digT[3],digP[9],digH[6];
    int32_t t_fine = 0.0;
    
    double compensate_P(int32_t adc_P)
    {
        double pressure = 0.0;
        double v1,v2;
        v1 = (t_fine / 2.0) - 64000.0;
        v2 = (((v1 / 4.0) * (v1 / 4.0)) / 2048) * digP[5];
        v2 = v2 + ((v1 * digP[4]) * 2.0);
        v2 = (v2 / 4.0) + (digP[3] * 65536.0);
        v1 = (((digP[2] * (((v1 / 4.0) * (v1 / 4.0)) / 8192)) / 8)  + ((digP[1] * v1) / 2.0)) / 262144;
        v1 = ((32768 + v1) * digP[0]) / 32768;
        if(v1 == 0)
            return 0;
        pressure = ((1048576 - adc_P) - (v2 / 4096)) * 3125;
        if (pressure < 0x80000000)
            pressure = (pressure * 2.0) / v1;
        else
            pressure = (pressure / v1) * 2;
        v1 = (digP[8] * (((pressure / 8.0) * (pressure / 8.0)) / 8192.0)) / 4096;
        v2 = ((pressure / 4.0) * digP[7]) / 8192.0;
        pressure = pressure + ((v1 + v2 + digP[6]) / 16.0) ;
        return (pressure/100);
    }
    
    double compensate_T(int32_t adc_T)
    {
        double temperature = 0.0;
        double v1,v2;
        v1 = (adc_T / 16384.0 - digT[0] / 1024.0) * digT[1];
        v2 = (adc_T / 131072.0 - digT[0] / 8192.0) * (adc_T / 131072.0 - digT[0] / 8192.0) * digT[2];
        t_fine = v1 + v2;
        temperature = t_fine / 5120.0;
        return temperature;
    }
    
    double compensate_H(int32_t adc_H)
    {       
        double var_h = t_fine - 76800.0;
        if (var_h == 0)
            return 0;
        var_h = (adc_H - (digH[3] * 64.0 + digH[4]/16384.0 * var_h)) *
            (digH[1] / 65536.0 * (1.0 + digH[5] / 67108864.0 * var_h * (1.0 + digH[2] / 67108864.0 * var_h)));
        var_h = var_h * (1.0 - digH[0] * var_h / 524288.0);
        if (var_h > 100.0)
            var_h = 100.0;
        else if (var_h < 0.0)
            var_h = 0.0;
        return var_h;
    } 
    
    void get_calib_param(int handle)
    {
        uint8_t calib[32];
        for(int i=0;i<24;i++) {   
            calib[i] = lgI2cReadByteData(handle, 0x88 + i); 
        }   
        calib[24] = lgI2cReadByteData(handle, 0xA1);
        for(int i=25,o=0;i<32;i++,o++) {   
            calib[i] = lgI2cReadByteData(handle, 0xE1 + o); 
        }   
        digT[0] = (calib[1] << 8) | calib[0];
        digT[1] = (calib[3] << 8) | calib[2];
        digT[2] = (calib[5] << 8) | calib[4];
        digP[0] = (calib[7] << 8) | calib[6];
        digP[1] = (calib[9] << 8) | calib[8];
        digP[2] = (calib[11] << 8) | calib[10];
        digP[3] = (calib[13] << 8) | calib[12];
        digP[4] = (calib[15] << 8) | calib[14];
        digP[5] = (calib[17] << 8) | calib[16];
        digP[6] = (calib[19] << 8) | calib[18];
        digP[7] = (calib[21] << 8) | calib[20];
        digP[8] = (calib[23] << 8) | calib[22];
        digH[0] = calib[24];
        digH[1] = (calib[26] << 8) | calib[25];
        digH[2] = calib[27];
        digH[3] = (calib[28] << 4) | (0x0f & calib[29]);
        digH[4] = (calib[30] << 4) | ((calib[29] >> 4) & 0x0f);
        digH[5] = calib[31];
        for(int i=1;i<2;i++)
            if((digT[i] & 0x8000) != 0) digT[i] = (-digT[i] ^ 0xFFFF) + 1;
        for(int i=1;i<8;i++)        
            if ((digP[i] & 0x8000) != 0)    digP[i]=(-digP[i] ^ 0xFFFF) + 1 ;    
        for(int i=0;i<6;i++)    
            if ((digH[i] & 0x8000) != 0) digH[i] = (-digH[i] ^ 0xFFFF) + 1;
    }
    
    int main(int argc, char **argv)
    {
        uint8_t data[8];
        double value[3];
        int handle = lgI2cOpen(I2C_DEV_NUM, BME280_ADDR, 0);
    
        lgI2cWriteByteData(handle, 0xF2, 0x01);
        lgI2cWriteByteData(handle, 0xF4, 0x27);
        lgI2cWriteByteData(handle, 0xF5, 0xA0);
        get_calib_param(handle);
    
        for(int i=0;i<8;i++) {
            data[i] = lgI2cReadByteData(handle, 0xF7 + i); 
        }
        value[0] = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4); 
        value[1] = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4); 
        value[2] = (data[6] << 8)  |  data[7];
        value[0] = compensate_P(value[0]);
        value[1] = compensate_T(value[1]);
        value[2] = compensate_H(value[2]);
    
        printf("pressure:    %7.2f hPa\n", value[0]);
        printf("temperature: %7.2f C\n"  , value[1]);
        printf("humidity:    %7.2f %\n"  , value[2]);
        lgI2cClose(handle);
    }
    
  • 编译:gcc -o envtest envtest.c -llgpio

  • 运行:./envtest #输出内容包含采集的气压、温度和湿度信息

SPI测试

使用微雪2.23OLED显示器测试40-Pin中的SPI功能,对应设备节点 /dev/spi10,若节点未显示,您可以先使用本章介绍的qpi_config进行配置和使能。

连接示意图:

图片1

微雪环境传感器扩展板

图片2

Quectel Pi H1 40PIN引脚

测试步骤:

  • wget http://www.waveshare.net/w/upload/c/c5/2.23inch-OLED-HAT-Code.7z #下载微雪提供的源码

  • 7z x 2.23inch-OLED-HAT-Code.7z #解压源码

  • cd 2.23inch-OLED-HAT-Code/Without\ scrolling/Raspberry\ Pi/SPI/c #切换到源码目录

  • 按照下列补丁的内容修改源码:

    diff -r -u "2.23inch-OLED-HAT-Code/Without scrolling/Raspberry Pi/c/examples/main.c" quectelpi/c/examples/main.c
    --- "2.23inch-OLED-HAT-Code/Without scrolling/Raspberry Pi/c/examples/main.c"	2023-12-20 03:19:38.000000000 +0000
    +++ quectelpi/c/examples/main.c	2025-08-15 07:34:39.959415415 +0000
    @@ -17,10 +17,13 @@
         char value[10]={'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
         time_t now;
         struct tm *timenow;
    -
    -    if(DEV_ModuleInit() != 0) {
    -		return -1;
    -	}
    +    extern int GPIO_Handle;
    +    extern int SPI_Handle;
    +    GPIO_Handle = lgGpiochipOpen(4); if (GPIO_Handle < 0) { printf( "gpiochip4 Export Failed\n"); return -1; }
    +    lgGpioClaimOutput(GPIO_Handle, 0, 119     , LG_LOW); //enable OLED_DC mode
    +    lgGpioClaimOutput(GPIO_Handle, 0, OLED_RST, LG_LOW);
    +    lgGpioClaimOutput(GPIO_Handle, 0, OLED_DC , LG_LOW);
    +    SPI_Handle = lgSpiOpen(10, 0, 10000000, 0);
         SSD1305_begin();
         SSD1305_bitmap(7, 0, waveshare_ch,112,32);
         SSD1305_display();
    Only in quectelpi/c/lib/Config: .DEV_Config.h.un~
    diff -r -u "2.23inch-OLED-HAT-Code/Without scrolling/Raspberry Pi/c/lib/Config/DEV_Config.h" quectelpi/c/lib/Config/DEV_Config.h
    --- "2.23inch-OLED-HAT-Code/Without scrolling/Raspberry Pi/c/lib/Config/DEV_Config.h"	2023-12-20 03:23:11.000000000 +0000
    +++ quectelpi/c/lib/Config/DEV_Config.h	2025-08-15 07:32:05.844626084 +0000
    @@ -41,8 +41,8 @@
    
     //OLED Define
     #define OLED_CS         8		
    -#define OLED_RST        25	
    -#define OLED_DC         24	
    +#define OLED_RST        19
    +#define OLED_DC         33
    
  • 编译:make

  • 运行:./main

  • 运行效果如下图:

UART测试

40-PinPin8Pin10默认配置为UART功能,对应设备节点 /dev/ttyHS2,若节点没出来可以先使用本章开头部分的qpi_config进行配置使能。

将电脑的USB转串口的RXpin8TXpin10


连接示意图: ![](./images/40pin-pin8.jpg)

使用C代码控制

  • 新建uart.c文件,内容如下:

    #include <stdio.h>
    #include <string.h>
    #include <lgpio.h>
    
    int strip_head_and_tail(char *data, int data_len)
    {
        int found_tail = 0;
        if (data_len > 0 && data[0] == '\r') {
            bcopy(data + 1, data, data_len-1);
            data_len--;
        }
        if (data_len > 0 && data[0] == '\n') {
            bcopy(data + 1, data, data_len-1);
            data_len--;
        }
        if (data_len > 0 && data[data_len - 1] == '\r') {
            data_len--;
            data[data_len] = 0;
            found_tail = 1;
        }
        if (data_len > 0 && data[data_len - 1] == '\n') {
            data_len--;
            data[data_len] = 0;
            found_tail = 1;
        }
        return found_tail;
    }
    
    int main(int argc, char **argv)
    {
        int handle = lgSerialOpen("/dev/ttyHS2", 115200, 0);
        char data[512];
        int data_len = 0;
        for (;;) {
            int read_len = lgSerialRead(handle,
                data + data_len, sizeof(data) - data_len);
            if (read_len > 0) {
                data_len += read_len;
            }
            if (strip_head_and_tail(data, data_len)) {
                printf("received: %s\n", data);
                lgSerialWrite(handle, "Received.\r\n", 11);
            }
            lguSleep(100);
        }
        lgSerialClose(handle);
    }
    
  • 编译:gcc -o uart uart.c -llgpio

  • 运行:./uart #此时USB转串口模块与PC连接,使用putty等支持串口通行的软件与该串口服务程序通行,putty等客户端输入内容并以回车键结尾,服务端程序会打印用户输入的内容并返回“Received.”给客户端。

使用Python脚本控制

  • 创建服务端程序uart.py,文件内容如下:

    import serial
    import threading
    
    PORT = '/dev/ttyHS2'
    BAUDRATE = 115200
    TIMEOUT = 1
    
    ser = serial.Serial(PORT, BAUDRATE, timeout=TIMEOUT)
    
    def read_and_echo(ser):
        while True:
            data = ser.readline()
            if data:
                print(f"Received: {data.decode().strip()}")
                ser.write(“Received.\r\n”)
    
    def main():
        if ser.is_open:
            print(f"Serial port {PORT} is open. Echo service started.")
            thread = threading.Thread(target=read_and_echo, args=(ser,))
            thread.daemon = True
            thread.start()
    
            try:
                while True:
                    pass
            except KeyboardInterrupt:
                print("Exiting program.")
        else:
            print(f"Failed to open serial port {PORT}.")
    
        ser.close()
        print(f"Serial port {PORT} is closed.")
    
    if __name__ == "__main__":
        main()
    
  • 运行:python test.py #此时USB转串口模块与PC连接,使用putty等支持串口通行的软件与该串口服务程序通行,putty等客户端输入内容并以回车键结尾,服务端程序会打印用户输入的内容并返回“Received.”给客户端。

PWM测试

40-PinPin33默认配置为PWM功能,这里选择微雪的4-Pin PWM协议的调速风扇做为测试设备。

使用C代码控制

  • 创建pwm.c文件,文件内容如下:

    #include <stdio.h>
    #include <lgpio.h>
    int main(int argc, char **argv)
    {
          int h;
          int gpio = 78; 
          float pwmFrequency = 1000;
          float pwmDutyCycle = 50; 
    
          h = lgGpiochipOpen(4);
          if (h < 0) {
              printf("ERROR: %s (%d)\n", lguErrorText(h), h); 
              return 1;
          }   
    
          int e = lgGpioClaimOutput(h, 0, gpio, 0); 
          if (e < 0) {
              printf("ERROR: %s (%d)\n", lguErrorText(e), e); 
              return 1;
          }   
    
          e = lgTxPwm(h, gpio, pwmFrequency, pwmDutyCycle, 0, 0); 
          if (e < 0) {
              printf("ERROR: %s (%d)\n", lguErrorText(e), e); 
              return 1;
          }   
    
          lguSleep(5);
          lgGpioFree(h, gpio);
          lgGpiochipClose(h);
          return 0;
    }
    
  • 编译:gcc pwm.c -o pwm -llgpio

  • 运行:./pwm #风扇会以中等转速运转,可以调整代码中的pwmDutyCycle值来调整风扇转速。

网络与通信

蓝牙测试

Quectel Pi H1智能主控板支持QCA1023 HCI UART蓝牙模块,可以连接常见蓝牙外设,以下流程演示与键鼠配对的方法。

蓝牙模块启动

蓝牙模块为HCI UART连接主控,通过HCI H4协议进行通信。
首先,通过设备节点执行如下命令给外设供电。若为echo 0时,则给蓝牙外设下电。

echo 1 > /sys/devices/platform/rfkill/bt_en

通过hciattach命令,通过串口初始化蓝牙模块。

hciattach /dev/ttyHS1 qca 3000000 flow

通过hciconfig命令,查询并且启用HCI蓝牙设备。

hciconfig hci0 up

通过hciconfig查询HCI设备状态。当状态为UP RUNNING时,说明HCI蓝牙设备已经启用。

root@qcm6490-idp:~# hciconfig 
hci0:	Type: Primary  Bus: UART
    BD Address: 00:00:00:00:5A:AD  ACL MTU: 1024:7  SCO MTU: 60:8
    UP RUNNING 
    RX bytes:783665 acl:1106 sco:0 events:18678 errors:0
    TX bytes:4072 acl:57 sco:0 commands:305 errors:0

连接蓝牙外设

执行bluetoothctl进入蓝牙配置工具。若命令提示符变成[bluetooth]#,表示已经进入蓝牙控制模式。

root@qcm6490-idp:~# bluetoothctl 
[bluetooth]# 

执行scan on开始扫描蓝牙设备,会显示周边蓝牙设备信息,此时需要打开蓝牙设备的配对模式,放在旁边。

[bluetooth]# scan on

扫描到一定时间后,执行scan off,停止扫描。

[bluetooth]# scan off

执行devices,列出扫描到的设备,找到你的蓝牙外设。此处以蓝牙鼠标为例。

[bluetooth]# devices
Device C3:3E:68:5E:E7:1F MX Master 2S

使用pair命令进行连接,地址为你的外设地址。

[bluetooth]# pair C3:3E:68:5E:E7:1F

当输出CHG的日志时,说明配对成功。此时可以发现,该鼠标被注册到input设备下,这里为input5(请以实际注册地址为准)。

[CHG] Device C3:3E:68:5E:E7:1F Modalias: usb:v046DpB019d0006
[MX Master 2S]# [ 1157.381232][ T1737] input: MX Master 2S Keyboard as /devices/virtual/misc/uhid/0005:046D:B019.0001/input/input4
[ 1157.392409][ T1737] input: MX Master 2S Mouse as /devices/virtual/misc/uhid/0005:046D:B019.0001/input/input5

将设备添加为trust并且连接(可选:如果设备自动连接则可跳过)。

[MX Master 2S]# trust C3:3E:68:5E:E7:1F
Changing C3:3E:68:5E:E7:1F trust succeeded
[MX Master 2S]# connect C3:3E:68:5E:E7:1F
Attempting to connect to C3:3E:68:5E:E7:1F
Connection successful

验证外设

此时,我们可以用evtest工具来验证外设是否可用。输入evtest会显示可使用的 event设备,这时选择鼠标对应的编号5。

root@qcm6490-idp:~# evtest 
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0:	pm8xxx_vib_ffmemless
/dev/input/event1:	gpio-keys
/dev/input/event2:	pmic_pwrkey
/dev/input/event3:	pmic_resin
/dev/input/event4:	MX Master 2S Keyboard
/dev/input/event5:	MX Master 2S Mouse
Select the device event number [0-5]: 

当出现如下日志,则大功告成,可以通过移动鼠标和按键来测试是否有事件上报。

Input driver version is 1.0.1
Input device ID: bus 0x5 vendor 0x46d product 0xb019 version 0x6
Input device name: "MX Master 2S Mouse"
Supported events:
  Event type 0 (EV_SYN)
  Event type 1 (EV_KEY)
    Event code 272 (BTN_LEFT)
    Event code 273 (BTN_RIGHT)
    Event code 274 (BTN_MIDDLE)
    Event code 275 (BTN_SIDE)
    Event code 276 (BTN_EXTRA)
    Event code 277 (BTN_FORWARD)
    Event code 278 (BTN_BACK)
    Event code 279 (BTN_TASK)
    Event code 280 (?)
    Event code 281 (?)
    Event code 282 (?)
    Event code 283 (?)
    Event code 284 (?)
    Event code 285 (?)
    Event code 286 (?)
    Event code 287 (?)
  Event type 2 (EV_REL)
    Event code 0 (REL_X)
    Event code 1 (REL_Y)
    Event code 6 (REL_HWHEEL)
    Event code 8 (REL_WHEEL)
    Event code 11 (REL_WHEEL_HI_RES)
    Event code 12 (REL_HWHEEL_HI_RES)
  Event type 4 (EV_MSC)
    Event code 4 (MSC_SCAN)
Properties:
Testing ... (interrupt to exit)
Event: time 2618.445029, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90001
Event: time 2618.445029, type 1 (EV_KEY), code 272 (BTN_LEFT), value 1
Event: time 2618.445029, -------------- SYN_REPORT ------------
Event: time 2618.610162, type 4 (EV_MSC), code 4 (MSC_SCAN), value 90001
Event: time 2618.610162, type 1 (EV_KEY), code 272 (BTN_LEFT), value 0
Event: time 2618.610162, -------------- SYN_REPORT ------------

有线网络(eth0)

Quectel Pi H1智能主控板支持1路自适应千兆以太网,以太网对网线的要求:仅支持直连网线,不支持交叉网线。

网络配置

系统默认开启NetworkManager服务来管理网络。

查看网络配置

使用ifconfig命令查看网络接口地址:

使用route -n命令查看网络路由信息,里面包含默认网关地址信息:

通过查看 /etc/resolv.conf文件内容检查DNS服务器地址:

自动获取网络配置

【如果是通过网络远程连接到设备中修改网络,会有风丢失网络连接的风险,请确保有方法(如通过调试串口或显示器)查看修改后的网络配置】

系统默认设置为自动获取网络配置。使用网线将设备接入局域网,设备会自动获取网络配置(前提条件:需要局域网中存在可用的DHCP服务)。
故障排除:

  • 查看连接信息:执行nmcli c,观察输出的结果中DEVICE列是否包含eth0,如果有,先删除再重建。
  • 删除旧的连接信息:执行nmcli c del 'Wired connection 1' #这里的 'Wired connection 1'是从上一步中查询出的连接的NAME。【删除后默认会自动创建一个NAMEeth0的连接,这个时候会自动获取网络配置】
  • 新建连接并使能:执行nmcli c add type ethernet con-name eth0 ifname eth0来创建连接。这里指定了连接名为eth0,使用的网络接口也是eth0;再执行nmcli connection up eth0以使名为eth0的连接生效。【一般上一步删除旧连接后,会自动创建一个NAMEeth0的连接。这时会自动获取网络配置,如果某些情况下新的连接迟迟没有自动创建,可以执行该步骤来创建和使能新的连接】
手动配置网络

【如果是通过网络远程连接到设备中修改网络,会有风丢失网络连接的风险,请确保有方法(如通过调试串口或显示器)查看修改后的网络配置】

  • 查看连接信息:执行nmcli c,观察输出的结果中DEVICE列是否包含eth0,若有,则需要记住其NAME值,后续步骤中需要用到。若无,则需要先创建一个eth0连接,执行nmcli c add type ethernet con-name 'Wired connection 1' ifname eth0
  • 执行如下命令手动配置网络:
    nmcli c modify 'Wired connection 1' \
    ipv4.addresses 192.168.1.100/24 \
    ipv4.gateway 192.168.1.1 \
    ipv4.dns 192.168.1.1 \
    ipv4.method manual
    
    修改完成后,执行nmcli c up 'Wired connection 1'使能连接【上述示例中的IP地址、网关地址和DNS地址根据实际需要修改】。

测试网络

执行ping命令测试网络连接:

  • 执行ping 192.168.1.1。如果ping通,则表示局域网网络连接正常【这里的IP地址需要修改为实际网络的网关地址】。
  • 执行ping 114.114.114.114。如果ping通,则表示外部网络连接正常。
  • 执行ping baidu.com。如果ping通,则表示外部网络连接正常且DNS解析功能正常。

Wi-Fi网络测试

使用nmcli快速连接Wi‑Fi:

  • 查看Wi‑Fi设备状态:nmcli dev status
  • 打开Wi‑Fi开关:nmcli radio wifi on
  • 扫描热点(指定Wi‑Fi设备):nmcli dev wifi list ifname wlan0
  • 连接热点:nmcli dev wifi connect "wifi名称" password "wifi密码"

执行连接命令后,若输出successfully activated即表示已成功联网。

PCIe 5G模块连接

Quectel Pi H1智能主控板可以通过PCIe接口,通过转接板连接5G网卡,本文介绍使用PCIe转接板连接RM520N-GL PCIe网卡的使用方法。

PCIe模块配置

使用PCIe转接板,需要将5G模块设置成PCIe-EP模式,这样才能和Quectel Pi H1的PCIe接口通信。安装5G模块驱动后,通过转接板的USB口将Quectel Pi H1连接到5G模块,输入AT命令,将其切换到PCIe-EP模式。

  1. 使用一根Type-C转USB线接入Windows电脑(此时您可能需要安装驱动,驱动文件由移远通信技术支持提供,请按照对应5G模块选择合适的驱动文件安装)。

  1. 使用串口工具,打开模块AT端口。

可以在主机的设备管理器上查看端口,找到“Quectel USB AT Port(COM***)”端口。

AT+QCFG="data_interface",1,0
AT+QCFG="pcie/mode",0
AT+QCFG="usbnet",2
AT+CFUN=1,1

执行完命令,拔掉电脑端口的USB,重新给Quectel Pi H1上电之后,通过shell口使用如下命令,判断5G模块是否被Quectel Pi H1正常识别并连接。

root@qcm6490-idp:~# lspci
0000:00:00.0 PCI bridge: Qualcomm Device 010b
0000:01:00.0 Ethernet controller: Device 1f0a:6801 (rev 01)
0001:00:00.0 PCI bridge: Qualcomm Device 010b
0001:01:00.0 Unassigned class [ff00]: Qualcomm Device 0308
root@qcm6490-idp:~# ls /dev/mhi*
/dev/mhi_BHI  /dev/mhi_DIAG  /dev/mhi_DUN  /dev/mhi_LOOPBACK  /dev/mhi_QMI0

如果设备均被识别出来,则可以正常进行拨号操作。

拨号上网

使用quectel-CM工具进行拨号上网,首先为5G模块连接天线,插入SIM卡,避免信号较差无法注网。

确认无误后,直接后台运行quectel-CM命令进行拨号。

root@qcm6490-idp:~# quectel-CM &
[2] 1303
root@qcm6490-idp:~# [01-01_00:07:55:168] QConnectManager_Linux_V1.6.7
[01-01_00:07:55:179] network interface '' or qmidev '' is not exist
[01-01_00:07:55:179] netcard driver = pcie_mhi, driver version = V1.3.7
[01-01_00:07:55:179] qmap_mode = 1, qmap_version = 9, qmap_size = 15360, muxid = 0x81, qmap_netcard = rmnet_mhi0.1
[01-01_00:07:55:179] Modem works in QMI mode
[01-01_00:07:55:193] /proc/1273/fd/7 -> /dev/mhi_QMI0
[01-01_00:07:55:193] /proc/1273/exe -> /usr/bin/quectel-CM
[01-01_00:07:55:193] requestDeactivateDefaultPDP WdsConnectionIPv4Handle
[01-01_00:07:55:424] ip link set dev rmnet_mhi0 down
[01-01_00:07:55:431] ip addr flush dev rmnet_mhi0.1
[01-01_00:07:55:436] ip link set dev rmnet_mhi0.1 down
[01-01_00:07:55:457] QmiWwanThread exit
[01-01_00:07:55:459] qmi_main exit
[01-01_00:07:57:196] cdc_wdm_fd = 7
[01-01_00:07:57:208] Get clientWDS = 15
[01-01_00:07:57:212] Get clientDMS = 1
[01-01_00:07:57:215] Get clientNAS = 4
[01-01_00:07:57:219] Get clientUIM = 3
[01-01_00:07:57:224] Get clientWDA = 1
[01-01_00:07:57:229] requestBaseBandVersion RM520NGLABR03A02M8G
[01-01_00:07:57:232] qmap_settings.rx_urb_size = 15360
[01-01_00:07:57:233] qmap_settings.ul_data_aggregation_max_datagrams  = 11
[01-01_00:07:57:233] qmap_settings.ul_data_aggregation_max_size       = 8192
[01-01_00:07:57:233] qmap_settings.dl_minimum_padding                 = 0
[01-01_00:07:57:248] requestGetSIMStatus SIMStatus: SIM_READY
[01-01_00:07:57:257] requestGetProfile[pdp:1 index:1] ctnet///0/IPV4V6
[01-01_00:07:57:261] requestRegistrationState2 MCC: 460, MNC: 11, PS: Attached, DataCap: 5G_SA
[01-01_00:07:57:265] requestQueryDataCall IPv4ConnectionStatus: DISCONNECTED
[01-01_00:07:57:265] ip link set dev rmnet_mhi0 down
[01-01_00:07:57:272] ip addr flush dev rmnet_mhi0.1
[01-01_00:07:57:277] ip link set dev rmnet_mhi0.1 down
[01-01_00:07:57:768] requestSetupDataCall WdsConnectionIPv4Handle: 0xe27891d0
[01-01_00:07:57:783] ip link set dev rmnet_mhi0 up
[  473.062494][ T1311] [I][mhi_netdev_open] Opened net dev interface
[01-01_00:07:57:797] ip link set dev rmnet_mhi0.1 up
[01-01_00:07:57:803] busybox udhcpc -f -n -q -t 5 -i rmnet_mhi0.1
udhcpc: started, v1.35.0
udhcpc: broadcasting discover
udhcpc: broadcasting select for 192.168.134.67, server 192.168.134.68
udhcpc: lease of 192.168.134.67 obtained from 192.168.134.68, lease time 7200
[01-01_00:07:57:883] /etc/udhcpc.d/50default: Adding DNS 8.8.8.8
[01-01_00:07:57:883] /etc/udhcpc.d/50default: Adding DNS 8.8.4.4

当最后两行udhcpc获取到IP地址后,说明已经可以正常获取到基站分配的IP,即表示可以上网。

使用ifconfig和ping命令验证网络:

root@qcm6490-idp:~# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:55:7B:B5:7D:F7  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:166 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:50 errors:0 dropped:0 overruns:0 frame:0
          TX packets:50 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:4632 (4.5 KiB)  TX bytes:4632 (4.5 KiB)

p2p0      Link encap:Ethernet  HWaddr 02:03:7F:D6:00:01  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

rmnet_mhi0 Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00  
          inet6 addr: fe80::6921:e40e:336d:a80e/64 Scope:Link
          UP RUNNING NOARP  MTU:1500  Metric:1
          RX packets:14 errors:0 dropped:0 overruns:0 frame:0
          TX packets:23 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:4464 (4.3 KiB)  TX bytes:5204 (5.0 KiB)

rmnet_mhi0.1 Link encap:Ethernet  HWaddr 02:50:F4:00:00:01  
          inet addr:192.168.134.67  Mask:255.255.255.248
          inet6 addr: fe80::50:f4ff:fe00:1/64 Scope:Link
          UP RUNNING NOARP  MTU:1500  Metric:1
          RX packets:14 errors:0 dropped:0 overruns:0 frame:0
          TX packets:23 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:4330 (4.2 KiB)  TX bytes:5334 (5.2 KiB)

wlan0     Link encap:Ethernet  HWaddr 00:03:7F:50:00:01  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

root@qcm6490-idp:~# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=113 time=5006.075 ms
64 bytes from 8.8.8.8: seq=5 ttl=113 time=485.806 ms
64 bytes from 8.8.8.8: seq=6 ttl=113 time=190.026 ms
64 bytes from 8.8.8.8: seq=13 ttl=113 time=628.962 ms
64 bytes from 8.8.8.8: seq=14 ttl=113 time=542.605 ms
64 bytes from 8.8.8.8: seq=15 ttl=113 time=585.632 ms
64 bytes from 8.8.8.8: seq=16 ttl=113 time=796.018 ms
64 bytes from 8.8.8.8: seq=17 ttl=113 time=95.139 ms
64 bytes from 8.8.8.8: seq=18 ttl=113 time=837.369 ms
64 bytes from 8.8.8.8: seq=19 ttl=113 time=41.186 ms

图形与显示

GPU性能测试

背景

在当今数字化时代,图形处理能力已成为衡量开发板性能的关键指标之一,Quectel Pi H1智能主控板,凭借其内置的高通Adreno 642L/643 GPU,在图形处理领域展现出了令人瞩目的实力,想象一下,在智慧交通场景中,Quectel Pi H1智能主控板能够凭借其强大的GPU性能,快速且精准地识别并标注车辆、车牌以及行人等目标物体,为交通管理提供实时且准确的数据支持。又或者在智能安全领域,面对复杂多变的监控画面,它能借助GPU卓越的运算能力,迅速完成图像识别与分析,及时发现潜在风险。这一切高效且精准的图形处理背后,正是 Quectel Pi H1 GPU性能的生动体现。它不仅能轻松应对日常的多媒体处理任务,更在对图形运算要求极高的复杂应用场景中,表现得游刃有余。以下通过glmark2基准测试工具,用于评估Quectel Pi H1的图形渲染性能。

glmark2是一款开源的OpenGL ESEGL基准测试工具,主要用于评估设备的图形渲染性能。它通过运行一系列标准化测试场景(如纹理填充、光照计算、像素处理等),量化GPU的帧率(FPS)、延迟(FrameTime)和稳定性,适用于嵌入式设备、手机、开发板等平台的图形性能分析和调优。

测试环境

glmark2默认已集成到系统镜像并安装。进入设备终端可直接测试性能。

  • 准备显示器,并连接显示器到Quectel Pi H1上。

运行命令

  • 在设备终端运行以下命令以确保结果显示在连接的显示器上:
export XDG_RUNTIME_DIR=/dev/socket/weston && export WAYLAND_DISPLAY=wayland-1
  • 运行glmark2命令以测试图形渲染性能:
glmark2-es2-wayland

测试结果

QUALCOMM build                   : a4d6ce04e1, I363e8f8d61
Build Config                     : G ESX_C_COMPILER_OPT 4.4.0 AArch64
Driver Path                      : /usr/lib/libGLESv2_adreno.so
Driver Version                   : 0808.0
Process Name                     : glmark2-es2-wayland
GBM_INFO::msmgbm_mapper(262)::gbm mapper instantiated

gbm_create_device(224): Info: backend name is: msm_drm
PFP: 0x016dc112, ME: 0x00000000
I/Adreno-UNKNOWN (1382,1382): <ReadGpuID:1042>: Reading chip ID through GSL
Pre-rotation disabled !!!

EGL updater thread started

=======================================================
    glmark2 2021.12
=======================================================
    OpenGL Information
    GL_VENDOR:     Qualcomm
    GL_RENDERER:   Adreno (TM) 643
    GL_VERSION:    OpenGL ES 3.2
=======================================================
[build] use-vbo=false: FPS: 516 FrameTime: 1.938 ms
[build] use-vbo=true: FPS: 679 FrameTime: 1.473 ms
[texture] texture-filter=nearest: FPS: 748 FrameTime: 1.337 ms
[texture] texture-filter=linear: FPS: 722 FrameTime: 1.385 ms
[texture] texture-filter=mipmap: FPS: 231 FrameTime: 4.329 ms
[shading] shading=gouraud: FPS: 220 FrameTime: 4.545 ms
[shading] shading=blinn-phong-inf: FPS: 679 FrameTime: 1.473 ms
[shading] shading=phong: FPS: 221 FrameTime: 4.525 ms
[shading] shading=cel: FPS: 688 FrameTime: 1.453 ms
[bump] bump-render=high-poly: FPS: 693 FrameTime: 1.443 ms
[bump] bump-render=normals:[  606.705365][  T943] smcinvoke: process_accept_req: Setting pid:943, server id : 23 state to defunct
[  606.714752][  T944] smcinvoke: process_accept_req: Setting pid:944, server id : 23 state to defunct
[  606.724315][  T945] smcinvoke: process_accept_req: Setting pid:945, server id : 23 state to defunct
[  606.734878][  T946] smcinvoke: process_accept_req: Setting pid:946, server id : 23 state to defunct
[  606.751381][  T943] smcinvoke: process_tzcb_req: server is defunct, state= 1 tzhandle = -2147483625
[  606.760794][  T943] smcinvoke: process_tzcb_req: server invalid, res: -90
 FPS: 714 FrameTime: 1.401 ms
[bump] bump-render=height: FPS: 674 FrameTime: 1.484 ms
[effect2d] kernel=0,1,0;1,-4,1;0,1,0;: FPS: 373 FrameTime: 2.681 ms
[effect2d] kernel=1,1,1,1,1;1,1,1,1,1;1,1,1,1,1;: FPS: 251 FrameTime: 3.984 ms
[pulsar] light=false:quads=5:texture=false: FPS: 213 FrameTime: 4.695 ms
[desktop] blur-radius=5:effect=blur:passes=1:separable=true:windows=4: FPS: 559 FrameTime: 1.789 ms
[desktop] effect=shadow:windows=4: FPS: 466 FrameTime: 2.146 ms
Error: Requested MapBuffer VBO update method but GL_OES_mapbuffer is not supported!
[buffer] columns=200:interleave=false:update-dispersion=0.9:update-fraction=0.5:update-method=map: Unsupported
[buffer] columns=200:interleave=false:update-dispersion=0.9:update-fraction=0.5:update-method=subdata: FPS: 238 FrameTime: 4.202 ms
Error: Requested MapBuffer VBO update method but GL_OES_mapbuffer is not supported!
[buffer] columns=200:interleave=true:update-dispersion=0.9:update-fraction=0.5:update-method=map: Unsupported
[ideas] speed=duration: FPS: 578 FrameTime: 1.730 ms
[jellyfish] <default>: FPS: 642 FrameTime: 1.558 ms
[terrain] <default>: FPS: 74 FrameTime: 13.514 ms
[shadow] <default>: FPS: 527 FrameTime: 1.898 ms
[refract] <default>: FPS: 418 FrameTime: 2.392 ms
[conditionals] fragment-steps=0:vertex-steps=0: FPS: 679 FrameTime: 1.473 ms
[conditionals] fragment-steps=5:vertex-steps=0: FPS: 686 FrameTime: 1.458 ms
[conditionals] fragment-steps=0:vertex-steps=5: FPS: 230 FrameTime: 4.348 ms
[function] fragment-complexity=low:fragment-steps=5: FPS: 680 FrameTime: 1.471 ms
[function] fragment-complexity=medium:fragment-steps=5: FPS: 693 FrameTime: 1.443 ms
[loop] fragment-loop=false:fragment-steps=5:vertex-steps=5: FPS: 691 FrameTime: 1.447 ms
[loop] fragment-steps=5:fragment-uniform=false:vertex-steps=5: FPS: 240 FrameTime: 4.167 ms
[loop] fragment-steps=5:fragment-uniform=true:vertex-steps=5: FPS: 685 FrameTime: 1.460 ms
=======================================================
                                  glmark2 Score: 506
=======================================================

EGL updater thread exited

性能分析

glmark2基准测试报告显示的Quectel Pi H1的OpenGL ES图形性能,最终得分为506,总体表现不错。主要性能表现如下:

VBO(顶点缓冲对象)优化

  • use-vbo=false → 516 FPS
  • use-vbo=true → 679 FPS(提升31.6%)

结论:启用VBO能显著提升渲染效率,减少CPU-GPU数据传输开销。

纹理过滤模式

  • nearest(最近邻)→ 748 FPS(最快)
  • linear(线性)→ 722 FPS(轻微性能损失)
  • mipmap(多级渐远)→ 231 FPS(性能下降69%)

结论:mipmap因额外计算开销导致帧率大幅下降,适合高质量纹理但代价高。

着色模型(Shading)

  • blinn-phong-inf(优化版布林-冯模型)→ 679 FPS
  • cel(卡通渲染)→ 688 FPS
  • phong/gouraud(传统光照模型)→ 220 FPS(性能极低)

结论:现代着色器(如 blinn-phong-inf)比传统模型(如 phong)更高效。

HDMI屏测试

Quectel Pi H1智能主控板支持HDMI接口显示屏。

HDMI屏连接

按照下图进行连接:

图片1

11.6寸HDMI显示屏

图片3

连接上HDMI显示屏后的Quectel Pi H1

HDMI屏显示Weston桌面

连接上HDMI显示器并上电开机后,启动显示服务:systemctl start init_displayHDMI屏会显示Weston桌面。


显示效果如下图:

利用HDMI屏播放视频

执行视频回放命令:

mount -o rw,remount /
export XDG_RUNTIME_DIR=/dev/socket/weston
export WAYLAND_DISPLAY=wayland-1
gst-launch-1.0 -e filesrc location=/root/quectel.mp4 ! qtdemux ! \
    queue ! h264parse ! v4l2h264dec capture-io-mode=5 output-io-mode=5 ! \
    waylandsink enable-last-sample=false fullscreen=true
    #其中location后的参数根据实际视频路径进行修改

命令说明:

  • gst-launch-1.0:这是GStreamer的命令行工具,用于启动一个GStreamer管道(pipeline)。-e参数表示在管道结束时退出,而不是继续运行。
  • filesrc location=/root/quectel.mp4filesrc用于从文件中读取数据, location=/root/quectel.mp4指定要读取的文件路径。
  • ! qtdemux!是一个连接符号,用于将前一个元素的输出连接到后一个元素的输入,qtdemux用于解复用MP4文件。MP4文件通常包含视频流和音频流,qtdemux 的作用是将这些流分离出来,以便后续处理。
  • ! queuequeue是一个缓冲队列元素,用于在管道中缓冲数据。它可以缓解数据处理速度不一致的问题,例如,当解码器处理速度较慢时,queue可以暂存数据,避免数据丢失。
  • ! h264parseh264parse用于解析H.264视频流。它会将H.264视频流中的数据重新组织成适合解码器处理的格式。
  • ! v4l2h264dec capture-io-mode=5 output-io-mode=5v4l2h264dec用于解码 H.264视频流,capture-io-mode=5:设置捕获输入模式为5,这通常与硬件加速有关,具体含义取决于硬件和驱动程序;output-io-mode=5 设置输出模式为 5,同样与硬件加速相关。
  • ! waylandsink enable-last-sample=false fullscreen=truewaylandsink用于将解码后的视频输出到Wayland显示服务器上,enable-last-sample=false禁用“最后样本”功能,这通常是用于优化性能或避免某些问题;fullscreen=true将视频以全屏模式显示。

视频回放效果如下图:

MIPI屏测试

Quectel Pi H1智能主控板支持MIPI接口显示屏,下面选取微雪的一款8DSI接口ISP电容触摸屏为例进行测试。

MIPI屏连接


按照下图进行连接:
注:此屏幕共有4处接口可供电,任选一处即可,示例选择“1”处供电。
  1. type-C接口
  2. I2C通讯与供电接口
  3. 5V输入输出接口
  4. I2C通讯与供电接口,需将螺丝孔对准Quectel Pi H1智能主控板拧紧,让顶针与 40-Pin连接牢固
图片1

微雪8寸MIPI显示屏背面

图片3

连接上MIPI显示屏后的Quectel Pi H1

MIPI屏显示Weston桌面

连接上MIPI显示器并上电开机后,启动显示服务:systemctl start init_displayMIPI屏会显示Weston桌面。


显示效果如下图:

利用MIPI屏播放视频

执行视频回放命令:

mount -o rw,remount /
export XDG_RUNTIME_DIR=/dev/socket/weston
export WAYLAND_DISPLAY=wayland-1
gst-launch-1.0 -e filesrc location=/root/quectel.mp4 ! qtdemux ! \
    queue ! h264parse ! v4l2h264dec capture-io-mode=5 output-io-mode=5 ! \
    waylandsink enable-last-sample=false fullscreen=true
    #其中location后的参数根据实际视频路径进行修改

命令说明:

  • gst-launch-1.0:这是GStreamer的命令行工具,用于启动一个GStreamer管道(pipeline)。-e参数表示在管道结束时退出,而不是继续运行。
  • filesrc location=/root/quectel.mp4filesrc用于从文件中读取数据, location=/root/quectel.mp4 指定要读取的文件路径。
  • ! qtdemux!是一个连接符号,用于将前一个元素的输出连接到后一个元素的输入,qtdemux用于解复用MP4文件。MP4文件通常包含视频流和音频流,qtdemux的作用是将这些流分离出来,以便后续处理。
  • ! queuequeue是一个缓冲队列元素,用于在管道中缓冲数据。它可以缓解数据处理速度不一致的问题,例如,当解码器处理速度较慢时,queue 可以暂存数据,避免数据丢失。
  • ! h264parseh264parse用于解析H.264视频流。它会将H.264视频流中的数据重新组织成适合解码器处理的格式。
  • ! v4l2h264dec capture-io-mode=5 output-io-mode=5v4l2h264dec用于解码H.264视频流,capture-io-mode=5:设置捕获输入模式为5,这通常与硬件加速有关,具体含义取决于硬件和驱动程序;output-io-mode=5设置输出模式为5,同样与硬件加速相关。
  • ! waylandsink enable-last-sample=false fullscreen=truewaylandsink用于将解码后的视频输出到Wayland显示服务器上,enable-last-sample=false禁用“最后样本”功能,这通常是用于优化性能或避免某些问题;fullscreen=true将视频以全屏模式显示。

视频回放效果如下图:

DP屏测试

Quectel Pi H1智能主控板支持通过Type-CDP接口的方法接显示屏。

DP屏连接

按照下图进行连接:

DP屏显示Weston桌面

连接上DP显示器并上电开机后,启动显示服务:systemctl start init_displayDP屏会显示Weston桌面。

显示效果如下图:

利用DP屏播放视频

执行视频回放命令:

mount -o rw,remount /
export XDG_RUNTIME_DIR=/dev/socket/weston
export WAYLAND_DISPLAY=wayland-1
gst-launch-1.0 -e filesrc location=/root/quectel.mp4 ! qtdemux ! \
    queue ! h264parse ! v4l2h264dec capture-io-mode=5 output-io-mode=5 ! \
    waylandsink enable-last-sample=false fullscreen=true
    #其中location后的参数根据实际视频路径进行修改

命令说明:

  • gst-launch-1.0:这是GStreamer的命令行工具,用于启动一个GStreamer管道(pipeline)。-e参数表示在管道结束时退出,而不是继续运行。
  • filesrc location=/root/quectel.mp4filesrc用于从文件中读取数据, location=/root/quectel.mp4 指定要读取的文件路径。
  • ! qtdemux! 是一个连接符号,用于将前一个元素的输出连接到后一个元素的输入,qtdemux用于解复用MP4文件。MP4文件通常包含视频流和音频流,qtdemux的作用是将这些流分离出来,以便后续处理。
  • ! queuequeue是一个缓冲队列元素,用于在管道中缓冲数据。它可以缓解数据处理速度不一致的问题,例如,当解码器处理速度较慢时,queue可以暂存数据,避免数据丢失。
  • ! h264parseh264parse用于解析H.264视频流。它会将H.264视频流中的数据重新组织成适合解码器处理的格式。
  • ! v4l2h264dec capture-io-mode=5 output-io-mode=5v4l2h264dec用于解码 H.264视频流,capture-io-mode=5:设置捕获输入模式为5,这通常与硬件加速有关,具体含义取决于硬件和驱动程序;output-io-mode=5设置输出模式为5,同样与硬件加速相关。
  • ! waylandsink enable-last-sample=false fullscreen=truewaylandsink用于将解码后的视频输出到Wayland显示服务器上,enable-last-sample=false禁用"最后样本"功能,这通常是用于优化性能或避免某些问题;fullscreen=true将视频以全屏模式显示。

视频回放效果如下图:

摄像头方案

MIPI摄像头(IMX219)测试

Quectel Pi H1智能主控板支持MIPI接口摄像头,下面选取微雪的一款imx219 CSI接口CMOS摄像头为例进行测试。

摄像头连接

按照下图进行连接,连接时向上拉开连接器的黑色锁扣部分,将 FPC 排线插入第一个 CSI 卡槽,注意金属接触面朝向板内金属接触面,按下锁扣,确认 FPC 排线稳定没有松动。

前提条件

SSH终端中运行以下命令:

mount -o rw,remount /
export XDG_RUNTIME_DIR=/dev/socket/weston
export WAYLAND_DISPLAY=wayland-1

单摄像头流启动

  1. device终端中运行如下命令。
gst-launch-1.0 -e qtiqmmfsrc name=camsrc ! 'video/x-raw(memory:GBM),format=NV12,width=1280,height=720,framerate=30/1' ! fakesink
  1. 此示例说明如何使用720p@30 FPS配置启动摄像头。该命令使用fakesink(虚拟接收器)作为输出,fakesink会接收来自摄像头传感器的帧数据但不做任何处理,直接丢弃,因此不会在设备上保存任何内容。此命令仅用于测试摄像头是否正常工作。如果gst pipeline状态更改为 “PLAYING”,如下所示,则表示摄像头正在运行。
gbm_create_device(187): Info: backend name is: msm_drm 
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Setting pipeline to PLAYING ... 
New clock: GstSystemClock
  1. 如果想实时显示摄像头捕捉的画面,需提前连接好HDMI屏幕,并执行以下命令:
gst-launch-1.0 -e qtiqmmfsrc name=camsrc camera=0 ! 'video/x-raw(memory:GBM),format=NV12,width=1280,height=720,framerate=30/1' ! waylandsink
  • camera=0表示使用第一个CSI接口摄像头,camera=1表示使用第二个CSI接口摄像头。
  • 如果想全屏显示,请在命令后面加上fullscreen=true
  • 如果要停止摄像头流,请按下CTRL+C

预览+视频录制

  1. device终端中运行以下命令:
gst-launch-1.0 -e qtiqmmfsrc name=camsrc camera=0 video_1::type=preview ! 'video/x-raw,format=NV12,width=1280,height=720,framerate=30/1',compression=ubwc,interlace-mode=progressive,colorimetry=bt601 ! tee name=t ! queue ! waylandsink fullscreen=true t. ! queue ! v4l2h264enc capture-io-mode=5 output-io-mode=5 extra-controls="controls,video_bitrate=6000000,video_bitrate_mode=0;" ! queue ! h264parse ! mp4mux ! filesink location=/opt/mux_avc.mp4
  1. 此命令以720p 30 FPS配置启动相机,并在h264视频编码后将其另存为视频文件。如果gst管道状态更改为 “PLAYING”,则表示摄像头正在运行。
  2. 如果要停止摄像头录制,请按下CTRL+C
  3. MP4文件保存在 /opt/目录。

命令说明:

  • ! 是一个连接符号,用于将前一个元素的输出连接到后一个元素的输入。

  • gst-launch-1.0:这是GStreamer的命令行工具,用于启动一个GStreamer管道(pipeline)。-e参数表示在管道结束时退出,而不是继续运行。

  • qtiqmmfsrc name=camsrc camera=0:高通平台专用的摄像头源插件,从设备 camera=0(主摄像头)采集视频。

  • video_1::type=preview:这是qtiqmmfsrc元素的属性配置,针对video_1流(不同摄像头可能输出多路流,比如预览流、抓拍流等 ),设置其类型为preview(预览流 ),表示后续处理的是用于实时预览场景的视频流,一般帧率、分辨率等参数会适配预览需求。

  • video/x-raw,format=NV12,width=1280,height=720,framerate=30/1video/x-raw(原始视频),NV12YUV 4:2:0,单平面格式,常见于视频编码),分辨率 1280×720(720p),帧率30fps

  • compression=ubwc,interlace-mode=progressive,colorimetry=bt601: 启用高通的UBWC(Ultra Bandwidth Compression)技术,通过硬件压缩减少内存带宽需求,逐行扫描(非隔行),色彩空间为ITU-R BT.601(适用于标清视频)。

  • tee name=t :分流器(tee)元素,作用是将一路输入数据复制成多路输出,方便对同一视频流进行多种不同处理(这里一路用于预览显示,一路用于编码存储 )。name=t给这个tee元素命名为t,后续其他分支通过名字引用它来获取视频流 。

  • queue ! waylandsink fullscreen=truequeue:队列元素,用于在 pipeline中创建一个缓冲队列,起到解耦上下游元素、异步处理的作用。可以缓解上下游处理速度不一致的问题,避免因一方处理慢导致另一方阻塞或丢帧。

waylandsink:输出sink元素,用于在Wayland显示服务器环境下,将视频画面渲染显示到屏幕上。
fullscreen=true:设置waylandsink以全屏模式显示视频画面。

  • t. ! queuet.:通过 . 语法引用之前命名为ttee元素,获取视频流进行后续处理。

queue:再次使用队列元素,缓冲数据,保证编码等环节的流畅性。

  • v4l2h264enc capture-io-mode=5 output-io-mode=5 extra-controls="controls,video_bitrate=6000000 video_bitrate_mode=0;":使用DMABUF(直接内存访问缓冲区)进行输入,优化数据传输效率,同样使用DMABUF输出编码后数据,目标比特率为6 Mbps,使用CBR(固定比特率) 模式,适合网络流媒体或需要稳定带宽的场景。

  • queue ! h264parse ! mp4mux ! filesink location=/opt/mux_avc.mp4queue:又一个队列元素,继续缓冲编码后的数据,协调后续处理速度。解析H.264 流,添加必要的NAL单元头部,使其符合MP4封装要求,将H.264视频流封装为MP4格式,将数据写入文件 /opt/mux_avc.mp4

预览+拍照

  1. device终端中运行以下命令:
 gst-pipeline-app -e qtiqmmfsrc name=camsrc camera=0 ! 'video/x-raw(memory:GBM),format=NV12,width=1280,height=720,framerate=30/1' ! waylandsink camsrc.image_1 ! "image/jpeg,width=1280,height=720,framerate=30/1" ! multifilesink location=/opt/frame%d.jpg async=false sync=true
  1. Enter键。此命令将打印以下菜单并等待用户输入。
##################################### MENU #####################################

============================== Pipeline Controls==============================
(0) NULL: Set the pipeline into NULL state
(1) READY: Set the pipeline into READY state
(2) PAUSED: Set the pipeline into PAUSED state
(3) PLAYING: Set the pipeline into PLAYING state

==================================== Other====================================
(p) Plugin Mode: Choose a plugin which to control
(q) Quit : Exit the application

Choose an option:
  1. 使用以下菜单步骤在预览时拍摄快照。
(1) ready -> (3) Playing -> (Enter)-> (p)Plugin Mode : Select (5)camerasrc ->(36) capture-image -> (1): still – Snapshot ->(1) Snapshot count ('guint' value for arg1)
  1. 要停止相机,请按Enter,按b(返回),然后按q(退出)。拍摄的快照图像保存在 /opt/中。通过在主机PC上运行以下scp命令,可以从设备中提取录制的内容:
scp -r root@[ip-addr]:/opt/<file name> .
  • 生成文件如下图所示:

MIPI摄像头(IMX477)测试

Quectel Pi H1智能主控板支持MIPI接口摄像头,下面选取微雪的一款imx477 CSI接口CMOS摄像头为例进行测试。

摄像头连接

按照下图进行连接,连接时向上拉开连接器的黑色锁扣部分,将FPC排线插入第二个CSI卡槽,注意金属接触面朝向板内金属接触面,按下锁扣,确认FPC排线稳定没有松动。

前提条件

SSH终端中运行以下命令:

mount -o rw,remount /
export XDG_RUNTIME_DIR=/dev/socket/weston
export WAYLAND_DISPLAY=wayland-1

单摄像头流启动

  1. device终端中运行以下命令。
gst-launch-1.0 -e qtiqmmfsrc name=camsrc camera=1 ! 'video/x-raw(memory:GBM),format=NV12,width=1280,height=720,framerate=30/1' ! fakesink
  1. 此示例说明如何使用720p@30 FPS配置启动摄像头。该命令使用 fakesink(虚拟接收器)作为输出,fakesink 会接收来自摄像头传感器的帧数据但不做任何处理,直接丢弃,因此不会在设备上保存任何内容。此命令仅用于测试摄像头是否正常工作。如果gst pipeline状态更改为 “PLAYING”,如下所示,则表示摄像头正在运行。
gbm_create_device(187): Info: backend name is: msm_drm 
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
Setting pipeline to PLAYING ... 
New clock: GstSystemClock
  1. 如果想实时显示摄像头捕捉的画面,需提前连接好HDMI屏幕,并执行以下命令:
gst-launch-1.0 -e qtiqmmfsrc name=camsrc camera=1 ! 'video/x-raw(memory:GBM),format=NV12,width=1280,height=720,framerate=30/1' ! waylandsink
  • camera=0表示使用第一个CSI接口摄像头,camera=1表示使用第二个 CSI 接口摄像头。
  • 如果想全屏显示,请在命令后面加上fullscreen=true
  • 如果要停止摄像头流,请按下CTRL+C

预览+视频录制

  1. device终端中运行以下命令:
gst-launch-1.0 -e qtiqmmfsrc name=camsrc camera=1 video_1::type=preview ! 'video/x-raw,format=NV12,width=1280,height=720,framerate=30/1',compression=ubwc,interlace-mode=progressive,colorimetry=bt601 ! tee name=t ! queue ! waylandsink fullscreen=true t. ! queue ! v4l2h264enc capture-io-mode=5 output-io-mode=5 extra-controls="controls,video_bitrate=6000000,video_bitrate_mode=0;" ! queue ! h264parse ! mp4mux ! filesink location=/opt/mux_avc.mp4
  1. 此命令以720p 30 FPS配置启动相机,并在h264视频编码后将其另存为视频文件。如果gst管道状态更改为 “PLAYING”,则表示摄像头正在运行。
  2. 如果要停止摄像头录制,请按下CTRL+C
  3. MP4文件保存在 /opt/目录。

命令说明:

  • !是一个连接符号,用于将前一个元素的输出连接到后一个元素的输入

  • gst-launch-1.0:这是GStreamer的命令行工具,用于启动一个GStreamer管道(pipeline)。-e参数表示在管道结束时退出,而不是继续运行。

  • qtiqmmfsrc name=camsrc camera=1:高通平台专用的摄像头源插件,从设备 camera=1(副摄像头)采集视频。

  • video_1::type=preview:这是qtiqmmfsrc元素的属性配置,针对video_1流(不同摄像头可能输出多路流,比如预览流、抓拍流等 ),设置其类型为preview(预览流 ),表示后续处理的是用于实时预览场景的视频流,一般帧率、分辨率等参数会适配预览需求。

  • video/x-raw,format=NV12,width=1280,height=720,framerate=30/1video/x-raw(原始视频),NV12YUV 4:2:0,单平面格式,常见于视频编码),分辨率1280×720(720p),帧率30fps

  • compression=ubwc,interlace-mode=progressive,colorimetry=bt601:启用高通的UBWC(Ultra Bandwidth Compression)技术,通过硬件压缩减少内存带宽需求,逐行扫描(非隔行),色彩空间为ITU-R BT.601(适用于标清视频)。

  • tee name=t:分流器(tee)元素,作用是将一路输入数据复制成多路输出,方便对同一视频流进行多种不同处理(这里一路用于预览显示,一路用于编码存储 )。name=t给这个tee元素命名为t,后续其他分支通过名字引用它来获取视频流 。

  • queue ! waylandsink fullscreen=truequeue:队列元素,用于在 pipeline中创建一个缓冲队列,起到解耦上下游元素、异步处理的作用。可以缓解上下游处理速度不一致的问题,避免因一方处理慢导致另一方阻塞或丢帧。

waylandsink:输出sink元素,用于在Wayland显示服务器环境下,将视频画面渲染显示到屏幕上。
fullscreen=true:设置waylandsink以全屏模式显示视频画面。

  • t. ! queuet.:通过 . 语法引用之前命名为ttee元素,获取视频流进行后续处理。

queue:再次使用队列元素,缓冲数据,保证编码等环节的流畅性。

  • v4l2h264enc capture-io-mode=5 output-io-mode=5 extra-controls="controls,video_bitrate=6000000 video_bitrate_mode=0;" 使用DMABUF(直接内存访问缓冲区)进行输入,优化数据传输效率,同样使用DMABUF输出编码后数据,目标比特率为6 Mbps,使用CBR(固定比特率) 模式,适合网络流媒体或需要稳定带宽的场景。

  • queue ! h264parse ! mp4mux ! filesink location=/opt/mux_avc.mp4queue:又一个队列元素,继续缓冲编码后的数据,协调后续处理速度。解析H.264流,添加必要的NAL单元头部,使其符合MP4封装要求,将H.264视频流封装为MP4格式,将数据写入文件 /opt/mux_avc.mp4

预览+拍照

  1. device终端中运行以下命令:
 gst-pipeline-app -e qtiqmmfsrc name=camsrc camera=1 ! 'video/x-raw(memory:GBM),format=NV12,width=1280,height=720,framerate=30/1' ! waylandsink camsrc.image_1 ! "image/jpeg,width=1280,height=720,framerate=30/1" ! multifilesink location=/opt/frame%d.jpg async=false sync=true
  1. Enter键。此命令将打印以下菜单并等待用户输入。
##################################### MENU #####################################

============================== Pipeline Controls==============================
(0) NULL: Set the pipeline into NULL state
(1) READY: Set the pipeline into READY state
(2) PAUSED: Set the pipeline into PAUSED state
(3) PLAYING: Set the pipeline into PLAYING state

==================================== Other====================================
(p) Plugin Mode: Choose a plugin which to control
(q) Quit : Exit the application

Choose an option:
  1. 使用以下菜单步骤在预览时拍摄快照。
(1) ready -> (3) Playing -> (Enter)-> (p)Plugin Mode : Select (5)camerasrc ->(36) capture-image -> (1): still – Snapshot ->(1) Snapshot count ('guint' value for arg1)
  1. 要停止相机,请按Enter,按b(返回),然后按q(退出)。拍摄的快照图像保存在 /opt/中。通过在主机PC上运行以下scp命令,可以从设备中提取录制的内容:
scp -r root@[ip-addr]:/opt/<file name> .
  • 生成文件如下图所示:

双摄像头流拼接显示

从主摄像头和辅助摄像头获取的两个流(均为720p)。两个流被发送以并排组合,然后显示。

gst-launch-1.0 -e qtivcomposer name=mixer sink_0::position="<0, 0>" sink_0::dimensions="<640, 360>" sink_1::position="<640, 0>" sink_1::dimensions="<640, 360>" mixer. ! queue ! waylandsink enable-last-sample=false fullscreen=true qtiqmmfsrc name=camsrc_0 camera=0 ! video/x-raw\(memory:GBM\), format=NV12, width=1280, height=720, framerate=30/1, compression=ubwc ! mixer. qtiqmmfsrc name=camsrc_1 camera=1 ! video/x-raw\(memory:GBM\), format=NV12, width=1280, height=720, framerate=30/1, compression=ubwc ! mixer.
  • 如果要停止摄像头流,请按下CTRL+C

USB摄像头测试

Quectel Pi H1智能主控板支持USB接口摄像头,下面选取微雪的一款OV5693 5MP USB 接口摄像头为例进行测试。

摄像头连接

USB摄像头的连接线插入Quectel Pi H1type-A接口。

查看相关信息

  1. SSH终端中运行以下命令,可查看系统识别到的USB设备信息:
dmesg | grep usb




  1. SSH终端中运行以下命令,可查看新增设备节点:
v4l2-ctl --list-devices

  • /dev/video2 —— 主视频节点,后面gst命令主要操作这个节点
  • /dev/video3 —— 元数据节点
  • /dev/media3 —— 硬件拓扑控制器,控制整个pipeline



  1. SSH终端中运行以下命令,可查看video节点支持的格式:
v4l2-ctl --list-formats-ext --device /dev/video2

  • 由图可知,该摄像头支持MJPGYUYV两种格式的图片输出。



前提条件

连接好HDMI屏幕,在SSH终端中运行以下命令:

mount -o rw,remount /
export XDG_RUNTIME_DIR=/dev/socket/weston
export WAYLAND_DISPLAY=wayland-1

实时预览

  1. device终端中运行以下命令:
  • MJPG格式(分辨率、帧率需符合摄像头支持的模式)
gst-launch-1.0 v4l2src device=/dev/video2 ! image/jpeg,width=1280,height=720,framerate=30/1 ! jpegdec ! videoconvert ! waylandsink fullscreen=true
  • YUYV格式(分辨率、帧率需符合摄像头支持的模式,GStreamer中使用YUY2表示此格式)
gst-launch-1.0 v4l2src device=/dev/video2 ! video/x-raw,format=YUY2,width=1280,height=720,framerate=10/1 ! videoconvert ! waylandsink fullscreen=true

命令说明:

  • gst-launch-1.0 -e


启动管线;-e保证按Ctrl+C停止时能正确收尾(EOS)。

  • v4l2src device=/dev/video2


V4L2设备/dev/video2采集数据。

  • image/jpeg,width=1280,height=720,framerate=30/1


要求摄像头输出1280×720@30 fpsMJPEG;若摄像头不支持,pipeline会直接报错。

  • jpegdec


MJPEG帧解码成原始YUV/RGB像素数据。

  • videoconvert


把像素格式转成waylandsink能接受的格式(通常是NV12/BGRx)。

  • waylandsink fullscreen=true


Wayland作为显示后端,并把窗口设置为全屏(无标题栏、铺满屏幕)。


预览+视频录制

  1. device终端中运行以下命令:
gst-launch-1.0 -e v4l2src device=/dev/video2 io-mode=2 ! \
  image/jpeg,width=1280,height=720,framerate=30/1 ! \
  jpegdec ! videoconvert ! tee name=t \
  t. ! queue ! v4l2h264enc ! h264parse ! mp4mux ! filesink location=/opt/out.mp4 \
  t. ! queue ! videoconvert ! waylandsink  fullscreen=true sync=false
  1. 此命令以720p 30 FPS配置启动相机,并在h264视频编码后将其另存为视频文件。如果gst管道状态更改为 "PLAYING",则表示摄像头正在运行。
  2. 如果要停止摄像头录制,请按下CTRL+C
  3. MP4文件保存在 /opt/目录。

命令说明:

  • v4l2src device=/dev/video2 io-mode=2


/dev/video2设备捕获视频流;io-mode=2表示使用内存映射(mmap)模式,提高性能。

  • image/jpeg,width=1280,height=720,framerate=30/1


指定捕获的视频流格式为MJPEG,分辨率为1280×720,帧率为30fps

  • jpegdec


解码MJPEG格式的视频流,将其转换为原始的RGB/YUV格式。

  • videoconvert


将解码后的视频格式转换为适合后续处理的格式(例如,从YUV转换为RGBA)。

  • tee name=t


将一路视频流分成两路,后续可以通过t.引用这两路流。

  • t. ! queue


tee元素中取出一路流,并通过queue元素进行缓冲。

  • v4l2h264enc


将视频流编码为H.264格式。

  • h264parse


解析H.264编码的视频流,使其符合MP4文件格式的要求。

  • mp4mux


H.264视频流封装为MP4文件格式。

  • filesink location=/opt/out.mp4:


将封装好的MP4文件保存到/opt/out.mp4

  • t. ! queue


tee元素中取出另一路流,并通过queue元素进行缓冲。

  • videoconvert


将视频格式转换为适合Wayland显示器显示的格式。

  • waylandsink fullscreen=true sync=false


将视频流输出到Wayland显示器,以全屏模式显示视频,禁用同步模式,避免Wayland显示器等待数据流,从而提高显示性能。

  1. 播放视频文件,请在device终端中运行以下命令:
gst-launch-1.0 -e filesrc location=/opt/out.mp4 ! qtdemux ! queue ! h264parse ! v4l2h264dec capture-io-mode=5 output-io-mode=5 !  videocrop top=0 bottom=40 left=0 right=0 ! videoconvert ! waylandsink  fullscreen=true enable-last-sample=false

命令说明:

  • filesrc location=/opt/out.mp4


/opt/out.mp4文件读取数据。

  • qtdemux


MP4文件中的视频和音频流分离出来。

  • queue


缓冲数据,避免处理过程中的数据丢失。

  • h264parse


解析视频流中的H.264编码数据。

  • v4l2h264dec capture-io-mode=5 output-io-mode=5


使用V4L2解码器解码H.264视频流,capture-io-mode=5output-io-mode=5是硬件加速相关的参数。

  • videocrop top=0 bottom=40 left=0 right=0


由于视频流自动对齐,填充额外的像素信息。导致视频底部有绿边,因此裁剪底部40像素。

  • videoconvert


格式转换元素,确保裁剪后的视频流格式适合Wayland显示器。

  • waylandsink fullscreen=true enable-last-sample=false


将解码后的视频输出到Wayland显示器上,并设置为全屏模式,同时禁用最后一帧显示。


预览+拍照

  1. device终端中运行以下命令:
gst-launch-1.0 -e v4l2src device=/dev/video2 io-mode=2 ! \
  image/jpeg,width=1280,height=720,framerate=30/1 ! \
  tee name=t \
  t. ! queue ! jpegdec ! videoconvert ! waylandsink sync=false \
  t. ! queue ! multifilesink location=/opt/shot-%05d.jpg max-files=5
  1. 按下CTRL+C,自动保存最后5张图片。

命令说明:

  • v4l2src device=/dev/video2 io-mode=2


USB摄像头采集MJPEG数据。

  • image/jpeg,width=1280,height=720,framerate=30/1


要求摄像头输出1280×720@30 fpsMJPEG流。

  • tee name=t


把同一路流一分为多,后面用t.引用。

  • t. ! queue ! jpegdec ! videoconvert ! waylandsink sync=false


预览分支:解码MJPEG → 转成RGB → 送到Wayland窗口实时显示。sync=false减少延迟。

  • t. ! queue ! multifilesink location=shot-%05d.jpg max-files=5


拍照分支:每一帧原封不动保存为JPG,文件名自动编号%05d5位数字)。max-files=5只保留最近5张,旧文件被自动删除。


  1. 查看照片请在device终端中输入以下命令:
gst-launch-1.0 filesrc location=/opt/shot-00036.jpg ! jpegdec ! imagefreeze ! waylandsink fullscreen=true
  1. 退出查看,请按下CTRL+C

命令说明:

  • filesrc location=/opt/shot-00036.jpg


从文件系统读取/opt/shot-00036.jpg

  • jpegdec


JPEG压缩数据解码成原始RGB/YUV像素帧。

  • imagefreeze


只保留第一帧,后续不断重复这一帧 → 实现“静止图片”效果。

  • waylandsink fullscreen=true


把图像送到Wayland合成器全屏显示。

存储设备

NVMe SSD分区、格式化与挂载

本文介绍如何在Linux系统中对NVMe固态硬盘(以/dev/nvme0n1为例)进行分区、格式化、挂载及性能测试的完整流程。

分区操作(使用fdisk)

通过fdisk工具对NVMe设备进行分区,步骤如下:

进入分区交互界面

执行以下命令,启动fdisk并指定目标NVMe设备:

fdisk /dev/nvme0n1
交互界面操作步骤

进入fdisk交互模式后,按以下顺序执行命令:

创建GPT分区表

输入g并回车,创建GUID分区表(GPT),适用于大容量设备(推荐):

Command (m for help): g
Created a new GPT disklabel (GUID: XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX)

新建分区

输入n并回车,创建一个新分区。后续参数(分区号、起始扇区、结束扇区)保持默认即可(默认会使用全部可用空间):

Command (m for help): n
Partition number (1-128, default 1): 
First sector (2048-xxxxxxxxx, default 2048): 
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-xxxxxxxxx, default xxxxxx): 
Created a new partition 1 of type 'Linux filesystem' and of size XX GiB.

写入分区表并退出

输入w并回车,将分区配置写入设备并退出fdisk:

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

操作完成后,系统会生成新分区/dev/nvme0n1p1(p1表示第一个分区)。

格式化分区(EXT4格式)

使用mkfs.ext4工具将新分区格式化为EXT4文件系统(适用于大多数Linux环境):

mkfs.ext4 /dev/nvme0n1p1

执行后会显示格式化进度,完成后输出类似信息:

mke2fs 1.46.5 (30-Dec-2021)
Creating filesystem with 12345678 4k blocks and 3456789 inodes
Filesystem UUID: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Superblock backups stored on blocks: 
  32768, 98304, 163840, ...
Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (65536 blocks): done
Writing superblocks and filesystem accounting information: done

手动挂载分区

创建挂载目录

使用mkdir命令创建一个用于挂载SSD的目录(示例路径为/mnt/myssd):

mkdir -p /mnt/myssd
挂载分区

将/dev/nvme0n1p1分区挂载到/mnt/myssd目录:

mount /dev/nvme0n1p1 /mnt/myssd

可通过df -h命令验证挂载是否成功,若输出中包含/dev/nvme0n1p1和/mnt/myssd则表示挂载正常:

df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p1  100G   5G   95G   5% /mnt/myssd

配置自动挂载(重启后生效)

通过修改/etc/fstab文件实现系统启动时自动挂载分区:

编辑fstab文件

使用编辑器打开/etc/fstab:

添加挂载配置

在文件末尾添加以下行,指定分区、挂载点、文件系统类型及挂载参数:

/dev/nvme0n1p1  /mnt/myssd  ext4  defaults  0  2

性能测试(读写速度验证)

使用dd命令测试SSD的读写性能(测试时确保分区已挂载):

读取速度测试

创建一个临时测试文件(若已存在),并通过读取该文件到空设备(/dev/null)测试读取速度:

dd if=/mnt/myssd/testfile of=/dev/null bs=1G iflag=direct

说明iflag=direct表示绕过系统缓存,测试真实读取速度。

输出示例:

1+0 records in
1+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 0.852345 s, 1.3 GB/s
写入速度测试

生成一个1 GB的空文件(/dev/zero为零数据来源),测试写入速度:

dd if=/dev/zero of=/mnt/myssd/testfile bs=1G count=1 oflag=direct

输出示例:

1+0 records in
1+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 1.245678 s, 862 MB/s

测试完成后可删除临时文件:

rm /mnt/myssd/testfile

UFS存储

Quectel Pi H1内嵌128 GB UFS存储芯片。相较于eMMC,其UFS读写速度更快、支持全双工通信和命令队列,性能更优。

查看容量

通过fdisk -l命令可以查询到UFS分区信息及容量。

root@qcm6490-idp:/opt/bc-1.08.1# fdisk -l
Disk /dev/sda: 116.09 GiB, 124646326272 bytes, 30431232 sectors
Disk model: C2G072
Units: sectors of 1 * 4096 = 4096 bytes
Sector size (logical/physical): 4096 bytes / 4096 bytes
I/O size (minimum/optimal): 4096 bytes / 4096 bytes
Disklabel type: gpt
Disk identifier: 49B3A77D-3D7D-22A5-0A10-6A2ECDDEA256

Device      Start      End  Sectors   Size Type
/dev/sda1       6   131077   131072   512M EFI System
/dev/sda2  131078   138757     7680    30M Linux filesystem
/dev/sda3  138758 30431226 30292469 115.6G Linux root (ARM-64)

查看分区信息

通过df命令可以查询到UFS分区信息,使用情况,挂载目录等信息。

root@qcm6490-idp:/opt/bc-1.08.1# df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda3       109G  3.3G  101G   4% /sysroot
devtmpfs        4.0M     0  4.0M   0% /dev
tmpfs           3.6G     0  3.6G   0% /dev/shm
tmpfs           1.5G   31M  1.5G   3% /run
tmpfs           4.0M     0  4.0M   0% /sys/fs/cgroup
tmpfs           3.6G   12K  3.6G   1% /tmp
tmpfs           3.6G     0  3.6G   0% /var/volatile
/dev/sda1       511M  136M  376M  27% /boot
/dev/sda2        25M  892K   22M   4% /var/persist
tmpfs           737M     0  737M   0% /run/user/0

性能测试

性能测试主要测试ufs在linux系统下对文件的读写速度,一般结合timedd双命令进行测试。

写文件测试

root@qcm6490-idp:/opt# time dd if=/dev/zero of=tempfile bs=1M count=100 conv=fdatasync
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 0.2874 s, 365 MB/s

real    0m0.316s
user    0m0.000s
sys     0m0.122s

使用dd命令写文件时,需要加conv=fdatasync参数,表示当dd完成写入操作后,会强制将缓存中的数据同步到磁盘。因为对磁盘的写操作一般是先写到内核缓存(page cache),系统调用就立即返回成功,但数据可能还没有真正写入物理磁盘。使用 conv=fdatasync可以确保数据真正写入磁盘后才返回,这样测试出的速度才是真实的磁盘写入速度。这里测试出写磁盘速度为365 MB/s。

读文件测试

在嵌入式系统中,经常需要测试系统文件读写性能。读文件时,系统默认会使用cache(缓存),这会导致测试结果不准确,因为从cache读取数据的速度远快于从磁盘读取。为了测试真实的磁盘读取速度,需要忽略cache的影响,可以指定参数iflag=direct,nonblock。

root@qcm6490-idp:/opt# time dd if=tempfile of=/dev/null bs=1M count=100 iflag=direct,nonblock
100+0 records in
100+0 records out
104857600 bytes (105 MB, 100 MiB) copied, 0.196993 s, 532 MB/s

real    0m0.201s
user    0m0.001s
sys     0m0.041s

可知,从磁盘直接读取读速度为532 MB/s。

核心资源与性能

CPU指标与测试

Quectel Pi H1智能主控板采用高通QCS6490作为核心处理器,基于Arm v8 Cortex,主频高达2.7 GHz。

  1. 查看CPU信息命令
root@qcm6490-idp:/# cat /proc/cpuinfo
processor       : 0
BogoMIPS        : 38.40
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x2
CPU part        : 0xd05
CPU revision    : 0

processor       : 1
BogoMIPS        : 38.40
Features        : fp asimd evtstrm aes pmull sha1 sha2 crc32 atomics fphp asimdhp cpuid asimdrdm lrcpc dcpop asimddp
CPU implementer : 0x41
CPU architecture: 8
CPU variant     : 0x2
CPU part        : 0xd05
CPU revision    : 0
  • processor:系统中逻辑处理核的编号,对于多核处理器则可以是物理核、或者使用超线程技术虚拟的逻辑核
  • BogoMIPS:在系统内核启动时粗略测算的CPU每秒运行百万条指令数(Million Instructions Per Second )
  1. 查看CPU使用率

执行top之后,按1显示各CPU核使用率

root@qcm6490-idp:/# top
top - 00:20:05 up 20 min,  1 user,  load average: 0.04, 0.07, 0.06
Tasks: 340 total,   1 running, 339 sleeping,   0 stopped,   0 zombie
%Cpu0  :  0.5 us,  1.6 sy,  0.0 ni, 97.3 id,  0.0 wa,  0.5 hi,  0.0 si,  0.0 st
%Cpu1  :  0.5 us,  0.0 sy,  0.0 ni, 98.9 id,  0.0 wa,  0.5 hi,  0.0 si,  0.0 st
%Cpu2  :  1.6 us,  0.0 sy,  0.0 ni, 97.3 id,  0.5 wa,  0.0 hi,  0.0 si,  0.5 st
%Cpu3  :  0.0 us,  0.5 sy,  0.0 ni, 98.4 id,  0.0 wa,  0.5 hi,  0.0 si,  0.5 st
%Cpu4  :  1.1 us,  0.0 sy,  0.0 ni, 98.4 id,  0.0 wa,  0.0 hi,  0.0 si,  0.5 st
%Cpu5  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu6  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu7  :  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   7366.7 total,   6386.2 free,    498.6 used,    481.9 buff/cache
MiB Swap:   5395.5 total,   5395.5 free,      0.0 used.   6698.9 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
      1 root      20   0  162028   9468   6524 S   1.1   0.1   0:07.64 systemd
    594 message+  20   0    6904   3712   3328 S   1.1   0.0   0:06.46 dbus-daemon
   1087 root      20   0 1794556  61472  30848 S   1.1   0.8   0:05.56 containerd
   1816 root      20   0    5768   2688   2048 R   1.1   0.0   0:00.04 top
     40 root      20   0       0      0      0 I   0.5   0.0   0:00.48 kworker/3:0-mm_percpu_wq
     50 root      20   0       0      0      0 S   0.5   0.0   0:00.55 rcuop/4
    127 root      20   0       0      0      0 I   0.5   0.0   0:00.47 kworker/u16:6-events_unbound
    280 root      20   0   34988  15176  14792 S   0.5   0.2   0:05.38 systemd-journal
    925 root      20   0  630136  72200  53256 S   0.5   1.0   0:06.65 weston

  • %us:表示用户空间程序的CPU使用率(没有通过nice调度)
  • %sy:表示系统空间的CPU使用率,主要是内核程序
  • %ni:表示通过nice调度过的用户空间程序的CPU使用率
  • %id:空闲CPU
  • %wa: 等待输入输出的CPU时间百分比
  • %hi: CPU处理硬中断的数量
  • %si: CPU处理软中断的数量
  • %st: 实时
  1. 获取CPU温度信息
root@qcm6490-idp:/# cat /sys/class/thermal/thermal_zone0/temp
37000
  • 上述显示数字为千分之一度,除以1000就是当前温度值(单位:摄氏度)。
  1. CPU压力测试

CPU压力的测试方式有很多,可通过bc命令来计算圆周率方法来测试CPU在运算过程中的稳定性。

root@qcm6490-idp:/# echo "scale=5000; 4*a(1)" | bc -l -q &
[1] 1592

上述命令将在后台计算PI,并精确到小数点后5000位,计算过程需要一段时间。
此时,我们可以通过top命令检查CPU利用率的变化,如下所示:

root@qcm6490-idp:/# top
top - 06:42:14 up 8 min,  1 user,  load average: 0.29, 0.16, 0.09
Tasks: 326 total,   3 running, 323 sleeping,   0 stopped,   0 zombie
%Cpu(s): 12.7 us,  0.2 sy,  0.0 ni, 86.8 id,  0.0 wa,  0.1 hi,  0.0 si,  0.2 st
MiB Mem :   7366.9 total,   6540.2 free,    439.5 used,    387.2 buff/cache
MiB Swap:   5395.7 total,   5395.7 free,      0.0 used.   6770.1 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   1592 root      20   0    3052   1792   1536 R  99.7   0.0   0:14.37 bc
    588 message+  20   0    6908   3584   3200 S   0.7   0.0   0:03.06 dbus-da+
      1 root      20   0  162064   9324   6380 S   0.3   0.1   0:04.26 systemd
...

约15秒后,PI结果被计算出来。在此期间CPU使用率达到100%,没有发生异常,说明CPU压力测试通过。还可以继续增加精确值,可进一步提高CPU压力测试强度。

root@qcm6490-idp:/# 3.141592653589793238462643383279502884197169399375105820974944592307\
81640628620899862803482534211706798214808651328230664709384460955058\
22317253594081284811174502841027019385211055596446229489549303819644\
...

Memory状态

  1. 查看内存信息
root@qcm6490-idp:/opt/bc-1.08.1# cat /proc/meminfo
MemTotal:        7543736 kB
MemFree:         6664720 kB
MemAvailable:    6928688 kB
Buffers:           19768 kB
Cached:           380520 kB
SwapCached:            0 kB
Active:            52044 kB
Inactive:         462332 kB
Active(anon):       3588 kB
Inactive(anon):   142568 kB
Active(file):      48456 kB
Inactive(file):   319764 kB
  • MemTotal:所有可用的RAM大小,物理内存减去预留位和内核使用
  • MemFree :LowFree + HighFree
  • Buffers:用来给块设备做缓存的大小
  • Cached:文件的缓冲区大小
  • SwapCached:已经被交换出来的内存。与I/O相关
  • Active:经常(最近)被使用的内存
  • Inactive:最近不常使用的内存
  1. 获取内存使用率
root@qcm6490-idp:/opt/bc-1.08.1# free -m
               total        used        free      shared  buff/cache   available
Mem:            7366         437        6504          31         424        6763
Swap:           5395           0        5395
  • total :内存总量
  • used :被使用的内存量
  • free :可使用的内存量
  1. 内存压力测试

通过给定测试内存的大小和次数, 可以对系统现有的内存进行压力上的测试。可使用系统工具 memtester进行测试,如指定内存大小300 MB ,测试次数为1,测试命令为"memtester 300M 1"。

下列以使用300 MB内存空间,单次测试为例:

root@qcm6490-idp:/# memtester 300M 1
memtester version 4.5.1 (64-bit)
Copyright (C) 2001-2020 Charles Cazabon.
Licensed under the GNU General Public License version 2 (only).

pagesize is 4096
pagesizemask is 0xfffffffffffff000
want 300MB (314572800 bytes)
got  300MB (314572800 bytes), trying mlock ...locked.
Loop 1/1:
  Stuck Address       : ok
  Random Value        : ok
  Compare XOR         : ok
  Compare SUB         : ok
  Compare MUL         : ok
  Compare DIV         : ok
  Compare OR          : ok
  Compare AND         : ok
  Sequential Increment: ok
  Solid Bits          : ok
  Block Sequential    : ok
  Checkerboard        : ok
  Bit Spread          : ok
  Bit Flip            : ok
  Walking Ones        : ok
  Walking Zeroes      : ok

Done.

电源与功耗

PMIC休眠唤醒

Linux内核一般提供了几种Suspend模式:Freeze(对应"freeze")、Standby(对应"standby")、STR(Suspend to RAM,对应"mem")和STD(Suspend to Disk,对应"disk")。在用户空间向/sys/power/state文件写入对应的字符串即可触发相应的休眠模式。Quectel Pi H1支持freeze和mem两种方式,standby和disk暂不支持。以下将以mem为例进行测试说明。

  • 查看当前Quectel Pi H1支持的模式
root@qcm6490-idp:/# cat /sys/power/state
freeze mem disk
  • 设置唤醒源

测试休眠唤醒需要先设置唤醒源,设置Debug串口(ttySC0)为唤醒源。

root@qcm6490-idp:/# echo enabled > /sys/devices/platform/soc@0/9c0000.geniqup/994000.serial/tty/ttyMSM0/power/wakeup
  • 休眠到内存

在用户空间向/sys/power/state写入字符串即进入相应的电源管理模式,休眠到内存的方式如下:

root@qcm6490-idp:/# echo mem > /sys/power/state
[15219.746797] PM: suspend entry (s2idle)
[15219.760424] Filesystems sync: 0.013 seconds
[15219.780574] Freezing user space processes
[15219.781589] process_accept_req: 22 callbacks suppressed
[15219.781600] smcinvoke: process_accept_req: Server id :17 interrupted probaby due to suspend, pid:897
[15219.791806] smcinvoke: process_accept_req: Server id :24 interrupted probaby due to suspend, pid:962
[15219.801969] smcinvoke: process_accept_req: Server id :18 interrupted probaby due to suspend, pid:903
[15219.812240] smcinvoke: process_accept_req: Server id :17 interrupted probaby due to suspend, pid:898
[15219.822590] smcinvoke: process_accept_req: Server id :18 interrupted probaby due to suspend, pid:902
[15219.832962] smcinvoke: process_accept_req: Server id :26 interrupted probaby due to suspend, pid:969
[15219.843391] smcinvoke: process_accept_req: Server id :21 interrupted probaby due to suspend, pid:929
[15219.853728] smcinvoke: process_accept_req: Server id :21 interrupted probaby due to suspend, pid:930
[15219.864031] smcinvoke: process_accept_req: Server id :17 interrupted probaby due to suspend, pid:899
[15219.874482] smcinvoke: process_accept_req: Server id :22 interrupted probaby due to suspend, pid:935
[15219.900228] Freezing user space processes completed (elapsed 0.119 seconds)

  • 通过Debug串口唤醒

输入休眠命令后Quectel Pi H1休眠,将运行状态数据存到内存,并关闭外设,进入等待模式,此时因为设置的是debug唤醒,键盘随意输入字符即能成功唤醒系统,如下:

[15221.270632] process_accept_req: 3 callbacks suppressed
[15221.270636] smcinvoke: process_accept_req: process_accept_req txn 4 either invalid or removed from Q
[15221.270655] smcinvoke: process_accept_req: process_accept_req txn 2 either invalid or removed from Q
[15221.270668] smcinvoke: process_accept_req: process_accept_req txn 3 either invalid or removed from Q
[15221.270742] smcinvoke: process_accept_req: process_accept_req txn 2 either invalid or removed from Q
[15221.270870] smcinvoke: process_accept_req: process_accept_req txn 1 either invalid or removed from Q
[15221.270924] smcinvoke: process_accept_req: process_accept_req txn 4 either invalid or removed from Q
[15221.270981] smcinvoke: process_accept_req: process_accept_req txn 3 either invalid or removed from Q
[15221.270982] done.
[15221.271044] smcinvoke: process_accept_req: process_accept_req txn 1 either invalid or removed from Q
[15221.271059] smcinvoke: process_accept_req: process_accept_req txn 3 either invalid or removed from Q
[15221.271078] smcinvoke: process_accept_req: process_accept_req txn 2 either invalid or removed from Q
[15221.371963] PM: suspend exit

USB与扩展外设

USB Host测试

USB Host是指能够控制和管理USB设备的系统或硬件,它负责为连接的USB设备(如U盘、键盘、鼠标等)提供电源、数据传输和管理功能。以下是一些常见的USB Host的功能和应用场景。

插入示例:

U盘挂载

当U盘插入到Quectel Pi H1上的USB Host上时,系统检测到一个USB闪存盘,并已成功初始化为存储设备。通过dmesg -n 8查看日志:

usb 1-1.2: new high-speed USB device number 7 using xhci-hcd
[  806.667878][  T162] usb-storage 1-1.2:1.0: USB Mass Storage device detected
[  806.676812][  T162] scsi host1: usb-storage 1-1.2:1.0
[  808.172742][  T162] scsi 1:0:0:0: Direct-Access     USB      Flash Disk       1100 PQ: 0 ANSI: 4
[  808.189763][   T74] sd 1:0:0:0: [sdg] 15730688 512-byte logical blocks: (8.05 GB/7.50 GiB)
[  808.200512][   T74] sd 1:0:0:0: [sdg] Write Protect is off
[  808.207624][   T74] sd 1:0:0:0: [sdg] Mode Sense: 43 00 00 00
[  808.216028][   T74] sd 1:0:0:0: [sdg] Write cache: enabled, read cache: enabled, doesn't support DPO or FUA
[  808.244091][   T74]  sdg: sdg1
  • 确认设备节点
lsblk

输出信息如下:

NAME    MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
sda       8:0    0 116.1G  0 disk
|-sda1    8:1    0   512M  0 part /boot
|-sda2    8:2    0    30M  0 part /var/persist
`-sda3    8:3    0 115.6G  0 part /var
                                  /usr
                                  /
                                  /sysroot
sdb       8:16   0     8M  0 disk
|-sdb1    8:17   0   3.5M  0 part
|-sdb2    8:18   0   512K  0 part
`-sdb3    8:19   0   3.5M  0 part
sdc       8:32   0     8M  0 disk
|-sdc1    8:33   0   3.5M  0 part
|-sdc2    8:34   0   512K  0 part
`-sdc3    8:35   0   3.5M  0 part
sdd       8:48   0    32M  0 disk
|-sdd1    8:49   0   104K  0 part
|-sdd2    8:50   0   128K  0 part
|-sdd3    8:51   0     1M  0 part
|-sdd4    8:52   0     1M  0 part
`-sdd5    8:53   0     1M  0 part
sde       8:64   0     3G  0 disk
|-sde1    8:65   0   512K  0 part
|-sde2    8:66   0    64M  0 part
|-sde3    8:67   0   256K  0 part
|-sde4    8:68   0     2M  0 part
|-sde5    8:69   0     5M  0 part
|-sde6    8:70   0     4M  0 part
|-sde7    8:71   0     8M  0 part
|-sde8    8:72   0     4M  0 part
|-sde9    8:73   0    32M  0 part
|-sde10   8:74   0   128K  0 part
|-sde11   8:75   0    80K  0 part
|-sde12   8:76   0     2M  0 part
|-sde13   8:77   0     2M  0 part
|-sde14   8:78   0   128K  0 part
|-sde15   8:79   0    32K  0 part
|-sde16 259:0    0     1M  0 part
|-sde17 259:1    0   256K  0 part
|-sde18 259:2    0   512K  0 part
|-sde19 259:3    0   256K  0 part
|-sde20 259:4    0    64M  0 part
|-sde21 259:5    0     2M  0 part
|-sde22 259:6    0     5M  0 part
|-sde23 259:7    0     4M  0 part
|-sde24 259:8    0     8M  0 part
|-sde25 259:9    0     4M  0 part
|-sde26 259:10   0    32M  0 part
|-sde27 259:11   0   128K  0 part
|-sde28 259:12   0    80K  0 part
|-sde29 259:13   0     2M  0 part
|-sde30 259:14   0     2M  0 part
|-sde31 259:15   0   128K  0 part
|-sde32 259:16   0    32K  0 part
|-sde33 259:17   0     1M  0 part
|-sde34 259:18   0   256K  0 part
|-sde35 259:19   0     4K  0 part
|-sde36 259:20   0     4K  0 part
|-sde37 259:21   0     4K  0 part
|-sde38 259:22   0    16M  0 part
|-sde39 259:23   0    30M  0 part
|-sde40 259:24   0     1M  0 part
|-sde41 259:25   0  32.6M  0 part
|-sde42 259:26   0     4K  0 part
|-sde43 259:27   0     4K  0 part
|-sde44 259:28   0     1M  0 part
|-sde45 259:29   0     8M  0 part
|-sde46 259:30   0    40M  0 part
|-sde47 259:31   0   512M  0 part
|-sde48 259:32   0    28K  0 part
|-sde49 259:33   0   512K  0 part
|-sde50 259:34   0     1M  0 part
`-sde51 259:35   0  32.6M  0 part
sdf       8:80   0    32M  0 disk
|-sdf1    8:81   0     3M  0 part
|-sdf2    8:82   0     3M  0 part
|-sdf3    8:83   0     3M  0 part
`-sdf4    8:84   0   128K  0 part
sdg       8:96   1   7.5G  0 disk
`-sdg1    8:97   1   7.5G  0 part
zram0   253:0    0   5.3G  0 disk [SWAP]
  • 创建挂载点
mkdir -p /mnt/usb
  • 挂载分区
mount /dev/sdg1 /mnt/usb
  • 验证挂载
df -h

输出信息如下:

Filesystem      Size  Used Avail Use% Mounted on
/dev/sda3       109G  3.3G  101G   4% /sysroot
devtmpfs        4.0M     0  4.0M   0% /dev
tmpfs           3.6G     0  3.6G   0% /dev/shm
tmpfs           1.5G   19M  1.5G   2% /run
tmpfs           4.0M     0  4.0M   0% /sys/fs/cgroup
tmpfs           3.6G   20K  3.6G   1% /tmp
tmpfs           3.6G     0  3.6G   0% /var/volatile
/dev/sda1       511M  136M  376M  27% /boot
/dev/sda2        25M   44K   22M   1% /var/persist
tmpfs           737M     0  737M   0% /run/user/0
/dev/sdg1       7.5G  1.9G  5.7G  25% /var/rootdirs/mnt/usb
  • 访问U盘内容
ls /mnt/usb
  • 卸载U盘
umount /mnt/usb

键盘、鼠标

当Logitech USB无线接收器插入到Quectel Pi H1上的USB Host上时,键盘鼠标可以正常使用。具体细节可以通过dmesg -n 8查看日志,显示了一个Logitech USB无线接收器(型号046D:C534,罗技键盘/鼠标套装)被Linux系统成功识别并初始化的过程。

usb 1-1.1: new full-speed USB device number 6 using xhci-hcd
[  478.273171][ T1373] input: Logitech USB Receiver as /devices/platform/soc@0/8c00000.usb/xhci-hcd.0.auto/usb1/1-1/1-1.1/1-1.1:1.0/0003:046D:C534.0003/input/input10
[  478.350114][ T1373] hid-generic 0003:046D:C534.0003: input: USB HID v1.11 Keyboard [Logitech USB Receiver] on usb-xhci-hcd.0.auto-1.1/input0
[  478.367447][ T1373] input: Logitech USB Receiver Mouse as /devices/platform/soc@0/8c00000.usb/xhci-hcd.0.auto/usb1/1-1/1-1.1/1-1.1:1.1/0003:046D:C534.0004/input/input11
[  478.383765][ T1373] input: Logitech USB Receiver Consumer Control as /devices/platform/soc@0/8c00000.usb/xhci-hcd.0.auto/usb1/1-1/1-1.1/1-1.1:1.1/0003:046D:C534.0004/input/input12
[  478.458989][ T1373] input: Logitech USB Receiver System Control as /devices/platform/soc@0/8c00000.usb/xhci-hcd.0.auto/usb1/1-1/1-1.1/1-1.1:1.1/0003:046D:C534.0004/input/input13
[  478.475639][ T1373] hid-generic 0003:046D:C534.0004: input,hiddev96: USB HID v1.11 Mouse [Logitech USB Receiver] on usb-xhci-hcd.0.auto-1.1/input1

USB OTG测试

利用qusb命令设置USB工作模式,qusb支持的参数如下:

init	初始化USB配置(挂载configfs,创建设备节点,加载默认PID)
bind	绑定USB设备到配置(激活当前配置)
unbind	解绑USB设备(停止当前配置)
setpid <PID>	切换到指定PID的USB组合模式(如setpid 901D启用DIAG+ADB)
setpid -p <PID>	 设置PID为默认模式(持久化到/etc/usb/usb_pid,重启后生效)
showpid	 显示所有支持的PID及其对应功能组合
persist <PID>	 仅持久化PID(不立即切换)

利用qusb测试USB口模拟网卡的功能

  • 查看usb支持的所有功能:
    root@qcm6490-idp:/# qusb showpid
    A4A1: NCM
    4EE7: ADB
    900E: DIAG
    901C: DIAG,UAC2
    901D: DIAG,ADB
    9015: MASS_STORAGE,ADB
    9024: RNDIS,ADB
    902A: RNDIS,MASS_STORAGE
    902B: RNDIS,ADB,MASS_STORAGE
    902C: RNDIS,DIAG
    902D: RNDIS,DIAG,ADB
    902F: RNDIS,DIAG,MASS_STORAGE
    908C: NCM,ADB
    90CA: DIAG,UAC2,ADB
    90CB: DIAG,UVC,ADB
    90CC: DIAG,UAC2,UVC,ADB
    90DF: DIAG,UVC
    90E0: DIAG,UAC2,UVC
    9135: DIAG,QDSS,ADB
    9136: DIAG,QDSS
    F000: MASS_STORAGE
    F00E: RNDIS
    
  • 切换USB模式:qusb setpid 908C # 启用NCM+ADB,此时在设备的shell里执行ifconfig -a可以查看到usb0接口
  • Quectel Pi H1Type-C口与PCUSB口连接[PC 的系统建议是linux]
  • Quectel Pi H1usb0接口设置IP地址:ip addr add dev usb0 192.168.0.5/24
  • PC上新识别出来的USB网卡设置地址:ip addr add dev enp0s20f0u13 192.168.0.6/24 # 这里的enp0s20f0u13需要根据实际情况进行修改
  • 测试网络:在PCSHELL中执行ping 192.168.0.5 #可以观察到能程序ping通目的地址

连接Wi-Fi的一般步骤及示例

打开Wi-Fi功能

使用命令来打开Wi-Fi功能,相当于桌面版的“打开Wi-Fi开关”。

nmcli radio wifi on

查看可用Wi-Fi列表

执行命令,扫描并列出当前无线网卡探测到的Wi-Fi网络。该命令会显示附近的Wi-Fi网络以及它们的名称(SSID)、信号强度、频道和加密方式等信息。

nmcli dev wifi list ifname wlan0  

返回如下,可以看到周围的热点信息。

root@qcm6490-idp:~# nmcli dev wifi list ifname wlan0 
IN-USE  BSSID              SSID                   MODE   CHAN  RATE        SIGNAL  BARS  SECURITY         
        64:09:80:76:42:BE  Xiaomi_42BD            Infra  11    130 Mbit/s  100     ▂▄▆█  WPA1 WPA2        
*       F8:5E:3C:01:F8:18  xiupax                 Infra  11    130 Mbit/s  100     ▂▄▆█  --               
        9C:9D:7E:F7:30:5E  tdz                    Infra  2     130 Mbit/s  97      ▂▄▆█  WPA1 WPA2        
        E2:F1:E1:57:D5:C6  gms-wifi               Infra  1     0 Mbit/s    95      ▂▄▆█  WPA1 WPA2        
        E2:F1:E1:57:D5:C8  cit-test-5g            Infra  1     0 Mbit/s    94      ▂▄▆█  WPA2             
        48:5F:08:BB:BA:41  TP-LINK_BA41           Infra  11    270 Mbit/s  87      ▂▄▆█  --               
        64:09:80:76:42:BF  Xiaomi_42BD_5G         Infra  157   270 Mbit/s  82      ▂▄▆█  WPA1 WPA2        
        B4:2F:03:DA:23:B5  5G_RRO_A23B5           Infra  157   135 Mbit/s  79      ▂▄▆_  WPA1 WPA2        
        A2:A7:90:A7:5B:A0  LSMate30               Infra  149   270 Mbit/s  77      ▂▄▆_  WPA2             
        A4:00:E2:EF:F7:83  Quectel-HF             Infra  1     260 Mbit/s  74      ▂▄▆_  WPA1 WPA2 802.1X 
        F0:2F:74:2A:41:78  odmtest                Infra  1     260 Mbit/s  74      ▂▄▆_  WPA3             
        2C:CF:67:6B:4A:86  HW-676B4A85            Infra  36    117 Mbit/s  74      ▂▄▆_  WPA1             
        A4:00:E2:EF:F7:82  Quectel-HF-2.4G        Infra  1     260 Mbit/s  72      ▂▄▆_  WPA1 WPA2 802.1X 
        A4:00:E2:EF:F7:80  Quectel-Customer-2.4G  Infra  1     260 Mbit/s  72      ▂▄▆_  WPA1 WPA2        
        66:D6:9A:C6:6D:21  PAXWIFIAP_2.4G         Infra  1     130 Mbit/s  72      ▂▄▆_  WPA2             
        A4:00:E2:EF:F7:90  Quectel-Customer       Infra  44    540 Mbit/s  72      ▂▄▆_  WPA1 WPA2        
        A4:00:E2:EF:F7:92  Quectel-HF             Infra  44    540 Mbit/s  72      ▂▄▆_  WPA1 WPA2 802.1X 
        9C:9D:7E:F7:30:5F  tdz                    Infra  149   270 Mbit/s  70      ▂▄▆_  WPA1 WPA2        
        34:CE:00:09:E5:A8  SW_test                Infra  6     130 Mbit/s  69      ▂▄▆_  WPA1 WPA2        
        E2:F1:E1:57:D5:CA  gms-wifi_5G            Infra  149   270 Mbit/s  69      ▂▄▆_  WPA1 WPA2        
        E2:F1:E1:57:D5:CE  cit-test-5g            Infra  149   270 Mbit/s  69      ▂▄▆_  WPA2             
        F0:2F:74:2A:41:7C  odmtest-5G             Infra  161   540 Mbit/s  65      ▂▄▆_  WPA2             
        A4:00:E2:EF:F8:52  Quectel-HF             Infra  36    540 Mbit/s  57      ▂▄▆_  WPA1 WPA2 802.1X 
        A4:00:E2:EF:F8:50  Quectel-Customer       Infra  36    540 Mbit/s  57      ▂▄▆_  WPA1 WPA2        
        3C:7C:3F:0B:94:FC  HWTEST                 Infra  161   540 Mbit/s  52      ▂▄__  WPA2             
        A4:00:E2:EF:F4:50  Quectel-Customer       Infra  149   540 Mbit/s  49      ▂▄__  WPA1 WPA2        
        A4:00:E2:EF:F4:52  Quectel-HF             Infra  149   540 Mbit/s  47      ▂▄__  WPA1 WPA2 802.1X 

连接Wi-Fi网络

选择要连接的Wi-Fi网络,并执行命令nmcli dev wifi connect "你的Wi-Fi名称" password "你的密码"来连接到该网络。例如,nmcli dev wifi connect "MyHomeWiFi" password "12345678"。如果网络没有密码,则不需要提供password参数。
连接加密热点:

root@qcm6490-idp:~# nmcli dev wifi connect "SSID" password "12345678" ifname wlan0 
Device 'wlan0' successfully activated with 'd0ef4183-ac40-41d5-8822-2cc174107c77'.

连接开放热点:

root@qcm6490-idp:~# nmcli dev wifi connect "SSID" ifname wlan0 
Device 'wlan0' successfully activated with 'd0ef4183-ac40-41d5-8822-2cc174107c77'.

使用ifconfig命令查看网络接口地址:

root@qcm6490-idp:~# ifconfig
eth0      Link encap:Ethernet  HWaddr 32:C0:A2:09:FE:40  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:167 Base address:0x1000 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:75 errors:0 dropped:0 overruns:0 frame:0
          TX packets:75 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:6301 (6.1 KiB)  TX bytes:6301 (6.1 KiB)

p2p0      Link encap:Ethernet  HWaddr 02:03:7F:D6:00:01  
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

wlan0     Link encap:Ethernet  HWaddr 00:03:7F:50:00:01  
          inet addr:192.168.253.211  Bcast:192.168.253.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:3421 errors:0 dropped:0 overruns:0 frame:0
          TX packets:61 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:3000 
          RX bytes:151273 (147.7 KiB)  TX bytes:7300 (7.1 KiB)

可以发现wlan0口已经获取 IP。

测试无线网络

执行ping命令测试网络连接:

  • 执行ping 192.168.1.1命令,如果ping通则表示局域网网络连接正常【这里的目的ip需要修改为实际网络的网关地址】。
  • 执行ping 114.114.114.114命令,如果ping通则表示外部网络连接正常。
  • 执行ping baidu.com命令,如果ping通则表示外部网络连接正常且DNS解析功能正常。