跳到主要内容

8.1 硬件、系统与环境配置

🔄 问题解决前请考虑更新到最新系统

许多问题可通过系统更新解决,相关下载资源请参考:下载资源汇总

认证配件及购买链接请参考RDK S100 认证配件清单

Q1: 什么是 D-Robotics RDK 套件?

A: D-Robotics Developer Kits,简称D-Robotics RDK套件,是基于 D-Robotics 智能芯片打造的机器人开发者套件。

Q2: 如何查看 RDK 板卡的系统版本号?

A: 登录到 RDK 板卡的系统后,您可以使用以下命令:

  1. 查看系统大版本号:

    cat /etc/version

    例如,输出可能是 2.0.0x3_ubuntu_v1.1.6

  2. 查看已安装的地瓜核心功能包版本:

    apt list --installed | grep hobot

    或者使用 rdkos_info 命令(适用于较新的系统版本,如2.1.0及以后):

    rdkos_info

    示例输出 (RDK OS 2.x 版本,如2.0.0):

    root@ubuntu:~# apt list --installed | grep hobot
    hobot-boot/unknown,now 2.0.0-20230530181103 arm64 [installed]
    hobot-bpu-drivers/unknown,now 2.0.0-20230530181103 arm64 [installed]
    # ... 其他 hobot-* 包
    root@ubuntu:~# cat /etc/version
    2.0.0

    示例输出 (RDK OS 1.x 版本,如1.1.6):

    root@ubuntu:~# apt list --installed | grep hobot
    hobot-arm64-boot/unknown,now 1.1.6 arm64 [installed]
    # ... 其他 hobot-arm64-* 包
    root@ubuntu:~# cat /etc/version
    x3_ubuntu_v1.1.6

Q3: 不同 RDK OS 系统版本和硬件平台之间有什么对应关系?

A:

  • RDK OS 2.x 及更新版本系统 (如2.0.0, 2.1.0, 3.0.x):
    • 基于 D-Robotics Linux 开源代码包制作。
    • 通常支持对应芯片的 RDK 系列硬件,请根据实际系统版本与板卡型号确认。
  • RDK OS 1.x 版本系统:
    • 基于闭源 Linux 系统制作,属于历史版本。
    • 主要支持早期 RDK 硬件,已不作为当前主线版本。

重要注意事项:

  • 版本升级: 1.x 版本系统无法通过apt命令直接升级到2.x 或更新版本的系统。如需升级,必须通过烧录新版本系统镜像的方式重新安装操作系统
  • TROS 兼容性: 不同大版本的 TROS(如基于 Foxy 的 TROS 和基于 Humble 的 TROS)通常与特定的 RDK OS 大版本绑定。例如,RDK OS 2.x 通常搭载基于 ROS2 Foxy 的 TROS,而 RDK OS 3.x 通常搭载基于 ROS2 Humble 的 TROS。

Q4: 摄像头插拔有什么注意事项?

A: 严禁在开发板未断电的情况下插拔摄像头,否则非常容易烧坏摄像头模组或主板接口。 请务必在断开开发板所有电源后,再进行摄像头的连接或移除操作。

Q5: 开发板启动异常、上电后无任何显示或反复重启,可能是什么原因?如何排查?

A: 这类问题通常与供电、启动介质(SD 卡/eMMC)或硬件连接有关。

  • 供电不足或不稳定:

    • 现象: 系统在 U-Boot 加载内核时或内核启动初期无明显错误日志就直接重启;状态灯异常或 HDMI 完全黑屏。

      Uboot引导内核时因供电不足重启日志示例 内核启动数秒后因供电不足重启日志示例
    • 排查与解决:

      • 确保使用符合开发板要求的电源适配器(建议使用支持 QC/PD 的5V/3A 或更高规格适配器)。
      • 禁止使用 PC 的 USB 接口为开发板供电。
      • 使用质量可靠的 USB Type-C 供电线。
      • 参考当前文档站内的基础配件清单,选择官方建议规格的电源适配器。
  • 启动介质问题 (Micro SD 卡/eMMC):

    • 现象: 串口日志提示无法挂载文件系统、找不到分区、MMC/SD 卡初始化错误或超时。

      SD卡镜像格式错误日志示例 SD卡物理损坏或接触不良日志示例1 SD卡物理损坏或接触不良日志示例2
    • 排查与解决:

      • 确认 SD 卡镜像是否已正确、完整地烧录。
      • 尝试重新烧录系统镜像。
      • 更换一张新的、质量可靠的高速 Micro SD 卡。
      • 清洁 SD 卡槽和 SD 卡金手指。
  • 串口误触进入 U-Boot:

    • 现象: 系统启动后停留在 U-Boot 命令行界面(如 hobot>)。
    • 排查与解决: 可能是上电时调试串口有非预期输入。尝试拔掉串口线后重新给设备上电。如果在 U-Boot 命令行,可以尝试输入 boot 命令并回车。
  • 其他硬件问题或外设冲突:

    • 如果以上都已排除,移除所有非必要外设(USB 设备、扩展板等)再尝试启动。
    • 极端情况下可能存在板卡本身硬件故障。
  • 详细排查指南: 请参考官方论坛的板卡无法启动问题定位指南。连接调试串口并记录完整的启动日志对于问题定位至关重要。

Q6: apt update 命令执行失败或报错如何处理?

常见报错类型

  • 密钥验证失败或过期
  • 软件源域名无法解析
  • 锁文件被占用
  • 网络连接问题

问题排查与解决

1. 软件源域名变更或 GPG 密钥问题

典型报错信息:

  • Clearsigned file isn't valid, got 'NOSPLIT'
  • The repository '...' is no longer signed.
  • Could not resolve 'archive.sunrisepi.tech' (或其他旧域名)
  • The following signatures couldn't be verified because the public key is not available: NO_PUBKEY ...

原因分析: 地瓜机器人官方软件源域名或 GPG 签名密钥发生变更,导致本地配置过期。

解决步骤:

  1. 检查当前源配置

    cat /etc/apt/sources.list.d/sunrise.list

    正确的配置应类似:

    deb [signed-by=/usr/share/keyrings/sunrise.gpg] http://archive.d-robotics.cc/ubuntu-rdk-s100 jammy main #RDK S100
  2. 更新域名配置

    如果发现旧域名(如 archive.sunrisepi.techsunrise.horizon.cc等),需要更新:

    # 替换旧域名为新域名
    sudo sed -i 's/archive.sunrisepi.tech/archive.d-robotics.cc/g' /etc/apt/sources.list.d/sunrise.list
    sudo sed -i 's/旧域名/archive.d-robotics.cc/g' /etc/apt/sources.list.d/sunrise.list
  3. 切换测试版到正式版 截至 25-7-14,RDK S100 的正式版源尚未发布。

    如果使用测试版源(包含 -beta 后缀),需要切换到正式版:

    sudo sed -i 's/ubuntu-rdk-s100-beta/ubuntu-rdk-s100/g' /etc/apt/sources.list.d/sunrise.list
  4. 更新 GPG 密钥

    sudo wget -O /usr/share/keyrings/sunrise.gpg http://archive.d-robotics.cc/keys/sunrise.gpg
  5. 重新更新软件包列表

    sudo apt update
2. APT 锁文件被占用
  • 报错示例:
    E: Could not get lock /var/lib/apt/lists/lock. It is held by process XXXX (apt-get)
    N: Be aware that removing the lock file is not a solution and may break your system.
    E: Unable to lock directory /var/lib/apt/lists/
  • 原因: 系统可能正在后台自动运行更新检查或安装任务,或者上一次 apt 操作未正常结束导致锁文件未被释放。
  • 解决方法:
    1. 等待: 有时后台进程会自动完成,请稍等片刻再试。
    2. 杀死占用进程: 如果长时间被占用,可以尝试杀死持有锁的进程(报错信息中通常会提示进程 ID,如示例中的 XXXX):
      sudo kill XXXX
    3. 清理锁文件(⚠️ 谨慎操作): 在确认没有 apt 或 dpkg 进程正在运行后,可以尝试移除相关的锁文件。此操作有一定风险,可能破坏您的包管理系统,请务必谨慎。
      sudo rm /var/lib/apt/lists/lock
      sudo rm /var/cache/apt/archives/lock
      sudo rm /var/lib/dpkg/lock
      sudo rm /var/lib/dpkg/lock-frontend
      sudo dpkg --configure -a # 尝试修复任何未完成的包配置
    4. 再次尝试 sudo apt update
3. ROS2 GPG 密钥问题

典型报错信息:

W: GPG error: http://packages.ros.org/ros2/ubuntu jammy InReleaase: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY F42ED6FBAB17C654
E: The repository 'http://packages.ros.org/ros2/ubuntu jammy InRelease' is not signed.
N: Updating from such a repository can't be done securely, and is therefore disabled by default.
N: See apt-secure(8) manpage for repository creation and user configuration details.

原因分析: ROS2官方软件源 GPG 签名密钥更新,导致本地配置过期。

解决步骤:

  1. 更新 GPG 密钥

    curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key | sudo tee /usr/share/keyrings/ros-archive-keyring.gpg > /dev/null
  2. 重新更新软件包列表

    sudo apt update

Q7: 如何为 RDK 应用设置开机自启动?

A: 主要有两种方式:

  1. 通过 /etc/rc.local 文件 (传统方式): 编辑该文件 (如果不存在,可能需要手动创建或从模板配置并启用 rc-local.service),在 exit 0 语句之前加入您要执行的命令。确保脚本具有可执行权限。

    #!/bin/bash -e
    #
    # rc.local
    #
    # This script is executed at the end of each multiuser runlevel.
    # Make sure that the script will "exit 0" on success or any other
    # value on error.
    #
    # In order to enable or disable this script just change the execution
    # bits.
    #
    # By default this script does nothing.

    # Example: Start your application in the background
    # /usr/bin/python3 /home/sunrise/my_app.py &

    # Insert what you need before this line
    exit 0

    参考:RDK 文档 - rc.local 自启动

  2. 通过 systemd 服务(现代、推荐方式): 创建一个 .service 配置文件(例如 /etc/systemd/system/myapp.service),定义服务的启动命令、依赖关系、运行用户、重启策略等。 示例 myapp.service 文件:

    [Unit]
    Description=My Application Service
    After=network.target multi-user.target

    [Service]
    User=sunrise
    ExecStart=/usr/bin/python3 /home/sunrise/my_app.py
    Restart=on-failure
    # StandardOutput=append:/var/log/myapp_stdout.log
    # StandardError=append:/var/log/myapp_stderr.log

    [Install]
    WantedBy=multi-user.target

    然后使用以下命令启用并启动服务:

    sudo systemctl daemon-reload  # 如果新建或修改了service文件
    sudo systemctl enable myapp.service
    sudo systemctl start myapp.service
    # 查看服务状态: sudo systemctl status myapp.service
    # 查看服务日志 (如果配置了): journalctl -u myapp.service

    参考:RDK社区帖子 - systemd自启动

自启动注意事项:

  • 确保脚本或程序的路径正确,并且具有执行权限。
  • 处理好依赖项(如网络、特定硬件初始化完成)和环境变量。
  • 如果应用需要图形界面,确保 DISPLAY 环境变量已正确设置,并且 X Server 已运行。
  • 建议将应用的输出重定向到日志文件,以便排查自启动失败的原因。

Q8: 开发板的默认登录账户和密码是什么?

A: 开发板通常默认支持以下两种账户:

  • 普通用户: 用户名 sunrise,密码 sunrise
  • 超级用户 (root): 用户名 root,密码 root (请注意,具体默认账户和密码可能因您烧录的系统镜像版本和来源略有不同,建议查阅该镜像的发行说明。)

Q9: 如何在 RDK 板卡上挂载 NTFS 文件系统的 U 盘或硬盘并支持读写?

A: Ubuntu 系统默认对 NTFS 文件系统的写入支持可能不完整或仅为只读。为了获得完整的 NTFS 读写支持,需要安装 ntfs-3g 软件包:

  1. 安装 ntfs-3g
    sudo apt update
    sudo apt -y install ntfs-3g
  2. 挂载 NTFS 分区: 安装完成后,再使用 mount 命令挂载 NTFS 分区。通常,系统会自动使用 ntfs-3g 驱动进行挂载,从而支持读写。
    • 首先,创建一个挂载点目录(如果尚未创建):
      sudo mkdir /mnt/my_ntfs_disk
    • 然后挂载设备(假设 NTFS 分区是 /dev/sda1,请根据实际情况替换):
      sudo mount /dev/sda1 /mnt/my_ntfs_disk
      # 或者显式指定类型 (通常不需要,系统会自动识别)
      # sudo mount -t ntfs-3g /dev/sda1 /mnt/my_ntfs_disk
    现在,您应该可以在 /mnt/my_ntfs_disk 目录下对 NTFS 分区进行读写操作了。

Q10: RDK 开发板是否支持本地安装 VS Code?如何在 PC 上使用 VS Code 远程连接开发板?

A:

  • 本地安装 VS Code: RDK 开发板作为嵌入式 ARM 架构设备,通常不直接支持在其上本地安装并运行完整版的 VS Code 桌面应用程序。VS Code 官方主要提供 x86_64架构的桌面版。
  • 远程开发 (推荐方式): 强烈推荐在您的 PC(Windows, macOS, 或 Linux)上安装 VS Code,并利用其强大的 Remote - SSH 扩展插件来远程连接到 RDK 开发板。通过这种方式,您可以在 PC 上享受完整的 VS Code 体验(包括代码编辑、智能提示、调试器前端等),而实际的代码编译、运行和调试则在 RDK 板卡上执行。 步骤概述:
    1. 在 PC 上的 VS Code 中安装 "Remote - SSH" 扩展。
    2. 确保您的 PC 和 RDK 板卡在同一局域网内,并且 RDK 板卡上的 SSH 服务已启动且网络可达。
    3. 在 VS Code 中配置 SSH 连接到 RDK 板卡(通常是 ssh 用户名@板卡IP地址)。
    4. 连接成功后,您可以直接在 VS Code 中打开 RDK 板卡上的文件夹进行开发。

Q11: RDK 开发板如何启用和使用 ADB (Android Debug Bridge) 调试功能?

A: RDK 的 Ubuntu 系统中通常默认已经编译并可能启动了 adbd (ADB 守护进程) 服务,但其默认配置和 USB 接口的功能模式可能需要调整才能用于 ADB 连接。

  1. 确认adbd服务: 检查服务是否运行,或是否有启动脚本。
  2. USB 接口模式: RDK 板卡的 USB Type-C 口或特定的 Micro USB 口(通常标有 OTG 或 Device 功能)可能需要被配置为 USB Device 模式(而不是 Host 模式)才能被 PC 识别为 ADB 设备。这有时可以通过 srpi-config 工具或修改设备树/内核参数来配置。
  3. PC 端准备: 在您的电脑上安装 ADB 工具包(通常作为 Android SDK Platform Tools 的一部分提供)。
  4. 连接: 使用 USB 线将 PC 与 RDK 板卡上配置为 Device 模式的 USB 口连接。
  5. 验证: 在 PC 的命令行/终端中执行 adb devices。如果一切配置正确,您应该能看到列出的 RDK 设备。
  6. 使用: 一旦连接成功,您就可以使用 adb shell 访问板卡终端,adb push <本地文件> <板卡路径> 上传文件,adb pull <板卡文件> <本地路径> 下载文件等。

注意: 具体的启用步骤可能因 RDK 型号和系统版本而异。请务必查阅对应板卡和系统版本的官方文档中关于 ADB 功能配置的详细说明。有时,官方提供的 bootloader 更新教程中也可能包含 ADB 的配置或使用前提。 参考 (来自原始文档,可能主要关于 bootloader 更新,但可间接涉及 ADB 环境):bootloader镜像更新 (建议查找更专注于 ADB 配置的官方文档或社区帖子)。

Q12: 开发板和电脑之间的文件传输有哪些常用方式?

A: 有多种方式可以在 RDK 开发板和电脑之间传输文件:

  1. SCP (Secure Copy Protocol) - 基于 SSH:

    • 从电脑拷贝文件到开发板:
      # 拷贝单个文件
      scp /path/to/local_file sunrise@<开发板IP地址>:/path/on/rdk/
      # 拷贝整个文件夹 (使用 -r 选项)
      scp -r /path/to/local_folder sunrise@<开发板IP地址>:/path/on/rdk/
    • 从开发板拷贝文件到电脑:
      scp sunrise@<开发板IP地址>:/path/on/rdk/remote_file /path/to/local_destination/
      scp -r sunrise@<开发板IP地址>:/path/on/rdk/remote_folder /path/to/local_destination/

    需要电脑端有 SCP 客户端(Linux/macOS 自带,Windows 可用 WinSCP、MobaXterm 或 Git Bash 中的 scp)。

  2. SFTP (SSH File Transfer Protocol) - 基于 SSH: 许多 FTP 客户端软件(如 FileZilla, WinSCP)支持 SFTP 协议,可以提供图形化的文件传输界面。连接时选择 SFTP 协议,并使用 SSH 的用户名、密码和 IP 地址。

  3. USB 存储设备 (U 盘/移动硬盘):

    • 将 U 盘等格式化为开发板支持的文件系统(如 FAT32, exFAT, 或安装了ntfs-3g后的 NTFS)。
    • 在电脑上存入文件,然后将 U 盘插入开发板的 USB Host 口。
    • 在开发板上挂载 U 盘 (sudo mount /dev/sda1 /mnt/usb_disk - 设备节点可能变化),然后进行文件操作。
  4. ADB (Android Debug Bridge) - 如果已配置并连接:

    • 从电脑推送文件到开发板:
      adb push C:\local\path\file.txt /remote/path/on/rdk/
    • 从开发板拉取文件到电脑:
      adb pull /remote/path/on/rdk/file.txt C:\local\path\
  5. 网络共享服务 (如 Samba, NFS): 可以在开发板上配置 Samba 或 NFS 服务,将特定目录共享到局域网,然后在电脑上像访问网络驱动器一样访问这些文件。配置相对复杂一些。

  6. Python HTTP 服务器 (临时小文件共享): 如果在开发板的某个目录下有想让电脑下载的文件,可以在该目录下快速启动一个 HTTP 服务器:

    # 在开发板上,进入要共享的目录
    cd /path/to/share
    python3 -m http.server 8000

    然后在电脑的浏览器中访问 http://<开发板IP地址>:8000 即可看到文件列表并下载。

选择哪种方式取决于文件大小、传输频率、网络环境以及个人偏好。对于开发过程中的代码和配置文件同步,SCP/SFTP 或 VS Code 的 Remote-SSH 内置的文件同步功能通常最为便捷。

Q13: 系统执行 apt upgrade 时桌面环境黑屏怎么办?

A: 建议通过串口终端或 SSH 远程登录后,在纯字符界面的终端中执行系统更新命令(如 sudo apt update && sudo apt upgrade)。直接在图形桌面的终端中更新,有时在升级桌面自身相关的包时可能会导致显示中断或 X Server 重启,从而造成黑屏现象。

Q14: 为什么 SD 卡插上去能启动,但是拔下来后下次就启动不了了?

A: 这取决于您的 RDK 板卡型号和启动方式:

请确认您的板卡型号和当前的启动介质设置。

Q15: RDK OS 的 Server 版能直接升级为 Desktop 版吗?

A: RDK OS 的 Server 版和 Desktop 版在预装的软件包上存在显著差异,最主要的是 Desktop 版包含了图形用户界面(如 XFCE 桌面环境)及其相关组件,而 Server 版通常不包含这些,以节省资源。

  • 理论上: 您可以通过在 Server 版系统上手动安装所有 Desktop 版所需的软件包(如xserver-xorg, xfce4, lightdm等以及它们的依赖)来将其“升级”为一个具有图形界面的系统。
  • 官方支持与稳定性: 官方通常不提供或不推荐这种手动升级路径,并且不对通过此方式构建的 Desktop 系统的稳定性和完整性进行保证或测试。手动安装过程复杂,容易遗漏依赖或产生配置冲突。
  • 推荐做法: 如果您需要 Desktop 版的完整功能和最佳体验,强烈建议直接下载并烧录官方发布的Desktop 版本系统镜像。这是确保系统稳定性和功能完整的最佳途径。

Q16: 为什么连接 HDMI 显示器后没有画面显示,或者显示异常?

A: HDMI 显示问题可能由多种原因造成:

  1. 显示器兼容性:
    • 部分显示器可能与 RDK 板卡输出的特定分辨率或刷新率不完全兼容。
    • RDK OS 2.1.0及以上版本引入了更多的 HDMI 分辨率支持,但也可能导致与某些旧显示器的兼容性问题。
    • 通常情况下,标准的1080p (1920x1080) 分辨率的显示器在板卡启动时直接连接,兼容性会比较好。
  2. 线缆问题: 确保使用的 HDMI 线缆质量良好且连接牢固。尝试更换一条 HDMI 线。
  3. RDK 系统配置:
    • 对于 Desktop 版本的系统,确保图形界面服务(如 LightDM)正常启动。
    • 对于 Server 版本的系统,默认情况下 HDMI 可能只输出启动 LOGO 或控制台信息,不会有图形桌面。
    • 在 RDK OS 2.1.0及以上版本,如果遇到显示不兼容,可以尝试先通过 VNC 连接到板卡(如果已开启),然后在系统中手动调整 HDMI 的输出分辨率。参考:HDMI显示问题及分辨率调整
  4. 供电问题: 虽然不直接,但严重的供电不足可能导致系统无法正常初始化显示子系统。
  5. 硬件问题: 极少数情况下,可能是板卡的 HDMI 接口或显示器本身的硬件故障。

Q17: 连接的 HDMI 显示器不被支持,如何抓取 EDID 信息以供技术支持分析?

A: 如果您的 HDMI 显示器无法正常显示或显示异常,技术支持人员可能需要您提供该显示器的 EDID (Extended Display Identification Data) 信息来帮助诊断问题或添加兼容性支持。EDID 包含了显示器的特性、支持的分辨率和时序等信息。 获取 EDID 信息的方法通常有:

  1. 通过 Linux 命令行工具(如果板卡能部分启动或通过其他方式访问):
    • 可以使用如 read-edid 包中的 get-edidparse-edid 工具。首先需要安装这些工具:sudo apt install read-edid
    • 然后尝试读取连接的显示器的 EDID。
  2. 使用专门的 EDID 读取硬件/软件: 有些显示器测试工具或专用的 EDID 编程器可以直接读取和保存 EDID 信息。
  3. 在 PC 上读取: 如果该显示器连接到一台装有 Linux 或 Windows 的 PC 上可以正常工作,也可以尝试在 PC 上读取其 EDID 信息。
    • Linux 下可以使用 xrandr --props 查看连接显示器的属性,其中可能包含 EDID 信息,或使用 get-edid | parse-edid
    • Windows 下可以使用如 MonitorInfoView (NirSoft) 或 Phoenix EDID Designer 等工具。

获取到 EDID 数据(通常是一个二进制文件或十六进制文本)后,可以将其提供给技术支持。 具体在地瓜机器人 RDK 平台抓取 EDID 的方法,请参考官方论坛的指导帖子:如何提供不支持显示器的EDID信息

Q18: SD 卡有时不识别或识别不稳定怎么办?

A: SD 卡不识别或识别不稳定的问题,可以从以下几个方面排查:

  1. SD 卡本身质量:
    • 使用劣质、老化或损坏的 SD 卡是常见原因。请尝试更换一张新的、质量可靠的品牌高速 Micro SD 卡(如 Class 10, U1/U3级别)。
  2. SD 卡与卡槽接触:
    • 确保 SD 卡已完全插入卡槽且接触良好。可以尝试取出 SD 卡,用橡皮擦清洁金手指,并检查卡槽内是否有异物。
  3. SD 卡兼容性:
    • 虽然新版系统对 SD 卡兼容性已明显改善,但极少数 SD 卡仍可能存在兼容性问题。
    • 如果遇到 SD 卡兼容性问题,建议优先使用官方推荐镜像和可靠存储介质。 参考教程:SD卡兼容性问题及miniboot更新
  4. 系统镜像或烧录问题:
    • 确保系统镜像文件本身没有损坏,并且烧录过程正确无误。可以尝试重新下载镜像并使用推荐的烧录工具(如 balenaEtcher, Rufus)重新烧录。
  5. 供电问题:
    • 不稳定的供电有时也可能间接影响 SD 卡的识别和读写稳定性。
  6. 板卡硬件问题:
    • 极少数情况下,可能是板卡的 SD 卡控制器或卡槽硬件故障。

如果在串口日志中看到类似 "mmc0: error -110 whilst initialising SD card" 或 "Card did not respond to voltage select" 等信息,通常指向 SD 卡识别或初始化失败。

Q19: 系统启动的时候卡在 hobot> U-Boot 命令行界面怎么办?

A: 当系统启动时停留在 hobot> 提示符,这表示板卡已进入 U-Boot (Universal Boot Loader) 的命令行模式,而没有继续引导加载 Linux 内核。可能的原因有:

  1. 串口干扰: 在板卡上电启动的最初几秒内,如果调试串口接收到了某些非预期的字符或电平信号(例如,键盘误触、串口终端软件自动发送的某些控制字符),可能会中断 U-Boot 的自动引导流程,使其停在命令行。
  2. 引导顺序配置: U-Boot 内部有引导顺序的配置(如先尝试 SD 卡,再尝试 eMMC 或网络引导)。如果配置被意外更改,或者首选的引导介质上没有有效的系统,也可能停在命令行。
  3. 引导脚本问题: U-Boot 执行的引导脚本(boot script)如果存在错误或被中断。
  4. 按键中断: 某些板卡设计中,如果在启动时按下了特定的按键,也可能进入 U-Boot 命令行。

解决方法:

  • 简单尝试:hobot> 提示符下,直接输入 boot 命令并按回车。这会尝试执行默认的引导命令,通常能继续引导进入 Linux 系统。
  • 检查串口连接: 确保调试串口连接稳定,没有不必要的信号干扰。可以尝试断开串口线后重新给板卡上电,看是否能正常启动。
  • 检查启动介质: 确认 SD 卡或 eMMC 中的系统镜像是否完好且可引导。
  • 复位 U-Boot 环境变量(谨慎操作): 如果怀疑 U-Boot 环境变量被错误修改,可以尝试恢复到默认设置(具体命令需查阅对应 U-Boot 版本的文档,如 env default -a; saveenv; reset)。此操作会清除所有自定义环境变量,请谨慎。

Q20: 镜像烧录失败的常见原因有哪些?

A: 使用烧录工具(如 balenaEtcher, Rufus)向 SD 卡烧录系统镜像时失败,可能的原因包括:

  1. 镜像文件问题:
    • 未完全解压: 确保您烧录的是从压缩包(如 .zip, .gz, .xz)中完全解压出来的 .img 后缀的原始镜像文件,而不是直接烧录压缩包。
    • 镜像下载不完整或损坏: 尝试重新下载镜像文件,并校验其 MD5/SHA256值(如果官方提供)以确保文件完整性。
  2. SD 卡问题:
    • SD 卡损坏或质量差: 尝试更换一张新的、质量可靠的 SD 卡。
    • SD 卡写保护: 确保 SD 卡的物理写保护开关(如果有)未开启。
    • SD 卡容量不足: 确保 SD 卡容量大于镜像文件解压后的大小。
  3. 读卡器问题:
    • 读卡器损坏或与 SD 卡/电脑不兼容。尝试更换读卡器。
    • 部分高速 SD 卡在老旧或质量不佳的读卡器上可能出现问题。
  4. 烧录工具或电脑环境问题:
    • 烧录软件版本: 尝试更新或更换其他版本的烧录软件。
    • USB 接口或驱动: 尝试更换电脑的 USB 接口;确保 USB 驱动正常。
    • 操作系统权限: 在 Windows 下,以管理员权限运行烧录工具。
    • 杀毒软件或防火墙干扰: 临时禁用可能干扰磁盘写入操作的安全软件。
    • Windows 弹出格式化提示: 在烧录过程中,Windows 系统可能会因为无法识别 SD 卡上的 Linux 分区而弹出“是否需要格式化”的对话框。请务必选择“否”或直接关闭该对话框,不要进行格式化操作,否则会中断烧录。
  5. 交叉验证: 如果条件允许,尝试在另一台电脑上使用同一个 SD 卡和读卡器进行烧录,或者在同一台电脑上使用不同的 SD 卡/读卡器组合,以帮助定位问题环节。

Q21: TF 卡(Micro SD 卡)接触不良或损坏时,可能会在内核日志中看到哪些典型错误信息?

A: 如果 Micro SD 卡接触不良、损坏或不兼容,您可能会在系统启动的串口日志或通过dmesg命令查看到的内核日志中观察到类似以下的错误信息,这些信息通常与 MMC (MultiMediaCard) 控制器无法正确初始化或与 SD 卡通信有关:

mmc0: card never left busy state
mmc0: error -110 whilst initialising SD card
mmc_rescan_try_freq: send_status error -110
Card did not respond to voltage select! : -110
mmc0: unrecognised CSD structure version x
mmc0: error -22 whilst initialising SD card
eMMC or SD Card not detected on mmchost 0 (mmchost X 可能指代不同的MMC控制器)
MMC Device X not found
no mmc device at slot X

出现这类日志通常意味着需要检查 SD 卡是否插好、更换 SD 卡或检查 SD 卡槽。

Q22: 板卡在高负载运行时感觉温度过高,应该如何处理?

A: 板卡温度过高会影响性能稳定性,甚至可能损坏硬件。处理方法如下:

  1. 检查并改善散热方式:
    • 被动散热 vs. 主动散热: 确认板卡当前的散热方案。对于需要长时间高负载运行(如持续 AI 推理、视频处理)的场景,仅靠小面积的被动散热片可能不足。强烈建议使用主动散热方案,例如带有风扇的散热片,或者将板卡安装在有良好空气流通的机箱内。
    • 散热片安装: 确保散热片与芯片(CPU/SoC)接触良好,导热硅脂或导热垫片已正确涂抹/放置。
  2. 确保空气流通: 避免将板卡放置在密闭或通风不良的环境中。
  3. 监控温度:
    • 使用系统命令(如 hrut_somstatus,或读取 /sys/class/thermal/thermal_zoneX/temp 文件内容)来实时监控芯片温度。
    • 了解板卡芯片的安全工作温度范围,避免长时间超出上限。
  4. 优化应用负载:
    • 如果可能,优化您的应用程序,减少不必要的计算,降低 CPU/BPU 的持续高负载。
    • 考虑是否可以通过算法优化、模型轻量化等方式降低功耗和发热。
  5. 检查供电: 虽然不直接导致发热,但不稳定的供电可能导致芯片工作异常,间接影响温度。

重要提示: “发热量小不代表温度会低”。即使芯片本身设计功耗不高,如果散热不良,热量积聚仍然会导致表面温度快速升高。良好的散热设计是保证嵌入式系统稳定运行的关键。

Q23: 如何在 Conda 虚拟环境中获取和使用地瓜机器人 RDK 特定的 Python 包(如 hobot.GPIO, hobot_dnn 等)?

A: 地瓜机器人官方提供的 hobot.GPIOhobot_dnn 等 Python 包通常是为 RDK 的系统 Python 环境预编译和优化的,它们可能依赖于系统底层的特定库文件和驱动程序。在 Conda 等 Python 虚拟环境中使用这些包可能会遇到一些挑战,因为虚拟环境旨在隔离依赖。

以下是一些可能的方法和注意事项:

  1. 官方是否提供 Conda 支持或 .whl 文件:
    • 首先,查阅最新的地瓜机器人官方文档、开发者社区或 GitHub 仓库,看官方是否提供了针对 Conda 环境的安装说明,或者是否直接发布了可以在 Conda 环境中通过 pip 安装的 .whl 格式的这些包。这是最理想的情况。
  2. 尝试在 Conda 环境中通过 pip 安装系统路径下的包(如果 .whl 不可用):
    • 如果这些包已经安装在 RDK 的系统 Python 环境中(例如在 /usr/lib/python3/dist-packages/ 或类似路径下),并且您的 Conda 环境使用的 Python 版本与系统 Python 及这些包编译时所用的 Python 版本兼容,有时可以直接在激活 Conda 环境后,尝试用 pip 指向这些包的路径进行安装,但这通常不被推荐,且成功率不高,因为 pip 主要用于从 PyPI 或本地.whl/源码包安装。
  3. 修改 PYTHONPATHsys.path (不推荐,易出错):
    • 一种不规范的方法是,在激活 Conda 环境后,手动将系统 Python 环境中这些特定包的路径添加到 Conda 环境的 PYTHONPATH 环境变量中,或者在 Python 脚本中动态修改 sys.path
    • 风险: 这种方法非常容易导致依赖冲突、版本不匹配以及难以追踪的运行时错误,因为 Conda 环境的隔离性被破坏了。强烈不推荐用于生产或复杂项目。
  4. 使用系统 Python 环境:
    • 如果您的项目对 Python 环境隔离的要求不是非常严格,或者主要就是围绕这些 RDK 特定包进行开发,最简单直接的方法可能就是直接使用 RDK 系统自带的 Python 环境,而不是 Conda。这些包在系统环境中通常是配置好的。
  5. 容器化方案 (Docker):
    • 如果地瓜机器人官方提供了包含这些包和完整依赖的 Docker 镜像,那么在 Docker 容器中使用这些功能是更可靠的隔离和部署方案。
  6. 从源码编译(如果官方提供源码且允许):
    • 如果这些特定包的源码是开放的,并且有针对 ARM 架构的编译指南,理论上您可以尝试在您的 Conda 环境中从源码编译和安装这些包。但这通常需要较高的技术能力和时间投入。

总结: 优先查找官方对 Conda 环境的支持。如果官方不支持,直接使用系统 Python 环境可能是最稳妥的方案。避免通过修改PYTHONPATH等方式强行混合不同环境的包,除非您非常清楚潜在的风险和如何解决冲突。

Q24: 编译自己开发的 Linux 内核模块(.ko文件)后,加载时遇到“驱动签名报错”或“Required key not available”等问题怎么办?

A: 较新版本的 Linux 内核,尤其是在启用了 Secure Boot 的系统上,或者某些发行版的默认安全策略,会要求加载到内核中的模块(.ko文件)必须具有有效的数字签名。如果您自行编译了一个内核模块但没有对其进行签名,在尝试使用 insmodmodprobe 加载时就可能遇到此类错误。

解决方法通常涉及以下步骤:

  1. 生成签名密钥对: 您需要一对公钥和私钥用于签名。可以使用 openssl 工具生成。

    openssl req -new -x509 -newkey rsa:2048 -keyout MOK.priv -outform DER -out MOK.der -nodes -days 36500 -subj "/CN=My Module Signing Key/"

    这会生成私钥 MOK.priv 和公钥 MOK.der

  2. 对内核模块进行签名: Linux 内核源码树中通常包含一个签名脚本 scripts/sign-file。您需要使用这个脚本、您的私钥以及刚生成的公钥(或者内核信任的某个公钥)来对编译好的 .ko 文件进行签名。

    # 假设您在内核源码目录下,并且 MOK.priv 和 MOK.der 在当前目录
    # KBUILD_SIGN_PIN 环境变量可能需要设置,用于自动签名过程中的密码交互(如果密钥有密码)
    sudo /usr/src/linux-headers-$(uname -r)/scripts/sign-file sha256 ./MOK.priv ./MOK.der /path/to/your/module.ko

    路径和具体参数可能需要根据您的内核版本和环境进行调整。

  3. 将签名公钥注册到系统的 MOK (Machine Owner Key) 列表中: 为了让内核信任您的签名,需要将签名时使用的公钥(MOK.der)导入到系统的 MOK 列表中。这通常通过 mokutil 工具完成。

    sudo mokutil --import MOK.der

    执行此命令后,系统会提示您设置一个临时密码。请记住这个密码。

  4. 重启系统并在 MOK Manager 中确认导入: 重启计算机。在启动过程中(通常在 UEFI/BIOS 之后,操作系统加载之前),系统会进入一个蓝色的 MOK Manager 界面(Shim)。您需要选择 "Enroll MOK" 或类似选项,然后输入之前设置的临时密码,来确认导入新的公钥。

  5. 加载已签名的模块: 完成以上步骤后,您的内核模块应该已经被有效签名,并且内核会信任这个签名。此时再尝试加载 .ko 文件应该就不会再报签名错误了。

重要提示:

  • 上述步骤是一个通用流程,具体命令和细节可能因您的 Linux 发行版、内核版本以及 Secure Boot 的配置状态而有所不同。

  • 请务必参考您所使用的 Linux 发行版和内核版本的官方文档中关于“内核模块签名 (Kernel Module Signing)”的详细指南。

  • 地瓜机器人官方 RDK 文档中关于“Linux 开发”或“驱动开发”的章节,也可能包含针对 RDK 平台的具体模块签名指导:

    内核头文件与模块编译 (请查找此文档中关于模块签名的具体章节)。

Q25: 在编译大型项目(如使用 gcc/make/cmake/colcon 构建 ROS2工作空间)或运行内存消耗较大的工具(如hb_mapper模型转换)时,遇到内存不足的错误怎么办?

A: 内存不足(Out of Memory, OOM)是嵌入式设备或资源受限的开发机上编译大型项目或运行内存密集型应用时常见的问题。以下是一些解决方法:

  1. 增加 Swap 交换空间: 当物理内存(RAM)不足时,系统可以使用硬盘上的一部分空间作为虚拟内存(Swap)。这可以缓解 OOM 问题,但性能会比物理内存慢很多。

    • 创建并启用 Swap 文件(示例为创建4GB Swap,大小可根据需求调整):
      # 1. 创建一个指定大小的空文件
      sudo fallocate -l 4G /swapfile
      # 2. 设置文件权限
      sudo chmod 600 /swapfile
      # 3. 将该文件设置为Swap区域
      sudo mkswap /swapfile
      # 4. 启用Swap文件
      sudo swapon /swapfile
      # 5. (可选) 验证Swap是否已激活
      swapon --show
      free -h
    • 使其开机自动挂载: 编辑 /etc/fstab 文件,在末尾添加一行:
      /swapfile none swap sw 0 0
    • 关闭 Swap(如果需要):
      sudo swapoff /swapfile
      sudo rm /swapfile # 如果不再需要,可以删除文件
      # 同时记得从 /etc/fstab 中移除对应行
  2. 减少编译并行度/线程数: 编译过程(尤其是 C++项目)通常会启动多个并行的编译任务以加快速度,但这也会消耗大量内存。

    • make 命令: 使用 -j 参数指定并行任务数。例如,单线程编译:
      make -j1
      可以尝试 -j2, -jN (N 为 CPU 核心数的一半或更少)。
    • colcon build (ROS2):
      • 限制并行包编译数量:
        colcon build --parallel-workers 1
      • 禁用并行包编译,改为串行编译(更慢但内存占用更低):
        colcon build --executor sequential
      • 结合使用:
        colcon build --executor sequential --parallel-workers 1
    • cmake CMake 本身不直接控制 make 的并行度,但最终还是通过 make 执行。可以在调用 make 时传递 -j 参数。
    • 设置 MAKEFLAGS 环境变量(临时):
      export MAKEFLAGS="-j1"
      # 然后执行 colcon build 或其他编译命令
  3. 针对 hb_mapper (地平线模型转换工具):

    • 在模型转换的 yaml 配置文件中,查找是否有类似 compiler_parameters -> jobs: 1 的选项,用以限制模型编译(例如 ONNX 到 BIN 模型过程中某些阶段)的并行进程数。具体参数名请查阅最新的算法工具链文档。
  4. 关闭不必要的后台服务和应用程序: 在进行编译或运行内存密集型任务前,关闭其他占用内存的程序(如图形界面、浏览器、其他服务等),以释放更多物理内存。

  5. 使用更高配置的开发机/服务器进行编译: 如果是在 x86开发机上为 RDK 进行交叉编译,而开发机本身内存也有限,可以考虑使用内存配置更高的机器。对于板端编译,如果资源实在不足,交叉编译是更好的选择。

  6. 分步编译/模块化编译: 对于非常大的项目,如果构建系统支持,可以尝试只编译项目的一部分,或者将项目分解为更小的模块独立编译。

选择哪种方法或组合取决于具体的错误信息、可用资源以及对编译时间的要求。增加 Swap 通常是比较通用的缓解方法。

Q26: RDK 相关问题进行预排查的通用建议有哪些?

A: 在遇到 RDK 相关问题并寻求帮助前,建议进行以下预排查:

  1. 查阅最新官方手册: 确保您参考的是官方最新版本的用户手册、开发文档和发行说明。官方文档通常会包含最新的信息和已知问题的解决方案。您可以从地瓜机器人开发者社区获取最新文档:RDK资料中心
  2. 更新系统及相关软件包: 许多问题可能在较新的软件版本中得到修复。请确保您的 RDK 板卡上的操作系统以及所有hobot-*tros-*等关键软件包都已更新到最新稳定版本。通常可以通过以下命令进行更新:
    sudo apt update && sudo apt upgrade
    在提问时,请一并提供通过 rdkos_infoapt list --installed | grep hobot 等命令获取的当前系统和软件包版本信息。
  3. 仔细检查硬件连接: 确保所有硬件连接都牢固可靠,包括电源线、SD 卡、调试串口线、摄像头排线、网络线以及其他外设连接。接触不良是许多问题的根源。
  4. 提供完整的问题复现信息: 当您向社区或技术支持提问时,请尽可能提供以下信息:
    • 清晰的问题描述: 遇到了什么问题?期望的结果是什么?实际观察到的现象是什么?
    • RDK 硬件型号和系统版本: 例如 RDK S100, RDK OS 4.x。
    • 相关的软件包版本。
    • 详细的复现步骤: 一步一步说明如何操作才能触发问题。
    • 完整的错误日志或截图: 包括串口打印、dmesg 信息、应用程序的报错输出等。
    • 您已尝试过的解决方法及其结果。 提供充分的信息有助于他人更快地理解和定位您的问题。

Q27: Docker 镜像、OE 包或嵌入式开发 Samples 包下载失败或速度慢怎么办?

A:

  1. Docker 镜像(例如用于算法工具链、交叉编译环境):
    • 官方来源: Docker 镜像通常首发于 Docker Hub。地瓜机器人官方也可能在自己的服务器或特定的开发者社区资源帖中提供部分关键镜像的下载链接或拉取方式。
    • 网络问题: 如果从 Docker Hub 拉取速度慢或失败,可能是由于网络限制或国际带宽问题。可以尝试配置 Docker 使用国内的镜像加速器服务(如阿里云、DaoCloud、网易蜂巢等都提供此类服务)。
    • 社区资源: 关注地瓜机器人开发者社区的公告或资源下载区,有时会提供针对国内用户的镜像获取方案。例如,此帖曾提供过相关资源:地瓜机器人开发者社区论坛相关帖子 (请确认链接及内容的最新有效性)。
  2. OE (OpenEmbedded) 包 / BSP (Board Support Package):
    • OE 编译环境相关的包或完整的 BSP(包含内核源码、驱动、文件系统构建脚本等)通常体积较大。如果官方提供直接下载,请确保您的网络连接稳定且具有足够的带宽。
    • 这些资源一般会在开发者社区的“资源中心”板块或对应 RDK 型号的产品文档页提供下载链接。
  3. 嵌入式开发 Samples 包(示例代码):
    • 示例代码包可能作为 BSP 的一部分提供(例如在 BSP 解压后的 bsp/samples/ 或类似目录下)。
    • 也可能作为独立的 SDK、代码仓库(如 GitHub 上的 D-Robotics 组织)或压缩包提供。
    • 请仔细查阅对应 RDK 型号和版本的官方文档或快速入门指南,以找到获取官方示例代码的正确途径。
  4. 通用下载建议:
    • 使用下载工具: 对于较大的文件,建议使用支持断点续传的下载工具。
    • 检查网络环境: 如果您在公司或机构网络下,确认是否有防火墙、代理服务器或网络策略限制了大文件的下载或访问特定域名。
    • 错峰下载: 尝试在网络负载较低的时段进行下载。
    • 官方渠道优先: 始终优先从地瓜机器人官方开发者社区、官方文档中提供的链接或官方 GitHub 仓库获取各类开发资源,以确保文件的正确性、完整性和安全性。

Q28: 为 RDK 进行交叉编译的环境应该如何配置?

A: 为 RDK 板卡(通常是 ARM 架构)上的应用程序进行交叉编译,一般需要在 x86架构的 Linux 开发主机(推荐使用 Ubuntu LTS 版本,如 Ubuntu 20.04或22.04)上配置交叉编译工具链和相应的目标系统 SDK(Sysroot)。具体配置步骤会因您要编译的程序类型(例如,普通的 Linux C/C++程序、ROS/TROS 功能包)以及目标 RDK 的型号和系统版本而有所不同。

  1. 编译普通 Linux C/C++应用程序:

    • 获取交叉编译工具链: 地瓜机器人官方会为 RDK 系列平台提供相应的交叉编译工具链(例如,包含aarch64-linux-gnu-gcc, aarch64-linux-gnu-g++等工具)。这个工具链可能作为 SDK 的一部分提供,或者需要从开发者社区单独下载。
    • 安装与配置工具链: 按照官方文档的指引,将下载的工具链压缩包解压到您开发主机上的一个合适路径(例如 /opt/toolchains/)。然后,需要将工具链的 bin 目录(包含编译器等可执行文件)添加到您开发主机的 PATH 环境变量中,这样系统才能找到这些交叉编译命令。
    • 准备 Sysroot: 交叉编译不仅需要编译器,还需要目标板卡系统环境中的库文件(如 glibc, libstdc++, 以及其他依赖库)和头文件。这部分内容集合称为 Sysroot。Sysroot 可以从官方提供的 RDK SDK 中提取,或者从一个已经烧录好系统的 RDK 板卡的根文件系统中复制得到。在编译时,需要通过编译器的 --sysroot=<path_to_sysroot> 参数来指定 Sysroot 的路径。
    • 使用 CMake 进行交叉编译: 如果您的项目使用 CMake 作为构建系统,推荐创建一个 CMake 工具链配置文件(toolchain file,例如 aarch64-rdk.cmake)。在这个文件中,您需要指定:
      • 目标系统名称 (CMAKE_SYSTEM_NAME 通常设为 Linux)。
      • 目标处理器架构 (CMAKE_SYSTEM_PROCESSOR 通常设为 aarch64)。
      • C 交叉编译器 (CMAKE_C_COMPILER) 和 C++交叉编译器 (CMAKE_CXX_COMPILER) 的完整路径。
      • Sysroot 路径 (CMAKE_SYSROOT)。
      • 查找库和头文件的相关路径设置 (CMAKE_FIND_ROOT_PATH)。 然后在运行 CMake 配置项目时,通过 -DCMAKE_TOOLCHAIN_FILE=/path/to/your/aarch64-rdk.cmake 参数来指定使用这个工具链文件。
    • 参考官方手册: 详细的交叉编译环境搭建步骤、工具链文件示例以及编译参数,请务必参考您所使用的 RDK 型号和版本的官方《用户手册》或《SDK 开发指南》中关于“Linux 应用开发”或“交叉编译环境搭建”的章节。
  2. 编译 ROS/TROS 功能包:

    • 使用官方提供的 Docker 交叉编译环境(强烈推荐): 这是为 TROS 功能包进行交叉编译最推荐且最便捷的方式。地瓜机器人官方通常会提供预配置好的 Docker 镜像,这些镜像中已经集成了:
      • 特定 TROS 版本(如 Foxy, Humble)所需的交叉编译工具链。
      • Ament/Colcon 等 ROS 构建工具。
      • 目标板卡 TROS 环境对应的所有基础 ROS 库和依赖项的交叉编译版本。
      • 操作流程:
        1. 从官方渠道(如 Docker Hub 或地瓜机器人官方服务器)拉取对应 TROS 版本的交叉编译 Docker 镜像。
        2. 按照官方文档的指引启动 Docker 容器,并将您的 ROS 工作区源代码目录挂载到容器内部。
        3. 在 Docker 容器的终端内,使用 colcon build 配合适当的交叉编译参数(通常 Docker 环境已预设好)来编译您的工作区。
      • 参考官方手册: TROS 用户手册中关于“源码安装”、“开发者指南”或“交叉编译”的章节通常会有详细的 Docker 使用方法和命令示例。例如,此链接可能包含相关信息:TROS 手册
    • 手动配置 ROS/TROS 交叉编译环境 (极不推荐,非常复杂且极易出错): 如果不使用官方提供的 Docker 环境,手动从零开始搭建一个完整的 ROS/TROS 交叉编译环境是一项非常复杂和耗时的工作。您需要自行交叉编译 ROS 的所有核心组件、消息类型、依赖库,并为 Colcon 等构建工具配置大量的交叉编译参数和环境变量。这通常只适用于有深厚交叉编译和 ROS 构建系统经验的开发者。

通用交叉编译建议:

  • 仔细阅读官方文档: 针对您使用的 RDK 型号和目标系统版本,务必以官方最新发布的开发文档、SDK 说明和移植指南为准。
  • 保持环境一致性: 交叉编译环境中所使用的库(尤其是系统库和核心依赖库)的版本,应尽可能与目标 RDK 板卡上实际运行的库版本保持一致或兼容,以避免运行时出现链接错误或行为不一致的问题。
  • Sysroot 的正确配置至关重要: 无论是编译普通 Linux 程序还是 ROS 包,正确配置和使用 Sysroot 是交叉编译成功的关键环节。

Q29: IMX219等 MIPI 摄像头如何连接到 RDK S100? 连接后如何验证?

A: IMX219这类 MIPI 摄像头模组通常通过24pin FPC(柔性扁平电缆)与开发板连接。 连接注意: FPC 排线的两端通常有蓝色或黑色加强筋,请确保加强筋的一面朝上(或朝向连接器卡扣的扳手面,具体取决于连接器类型)插入到开发板和摄像头模组的连接器中,并锁紧卡扣。

IMX219摄像头连接示意图:

IMX219摄像头连接到RDK S100示意图

连接后验证:

  1. 确保摄像头已正确连接且开发板已上电。

  2. 运行 MIPI 摄像头示例程序 (以 RDK S100为例):

    cd /app/pydev_demo/10_mipi_camera_sample # 路径可能因系统版本而异
    python3 01_mipi_camera_yolov5x.py

    如果一切正常,您应该能通过 HDMI 输出或其他指定方式看到摄像头捕捉的画面以及可能的 AI 算法处理结果 示例算法渲染结果 HDMI 输出(检测到teddy bearcupvase):

    MIPI摄像头算法渲染结果示例
  3. 通过 i2cdetect 命令检查 I2C 通信:

    MIPI 摄像头通常通过 I2C 总线与主控芯片通信以进行配置。您可以使用 i2cdetect 命令来扫描连接到特定 I2C 总线上的设备。RDK S100上 MIPI 摄像头常用的 I2C 总线可能是 i2c-1i2c-2 (具体请查

    sudo i2cdetect -y -r 1  # 扫描 i2c-1 总线
    # 或 sudo i2cdetect -y -r 2 # 扫描 i2c-2 总线

    预期输出示例:

    • IMX219 (通常地址为 0x10):
        0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
    00: -- -- -- -- -- -- -- --
    10: 10 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- (0x10为IMX219地址)
    20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
    30: -- -- -- -- -- -- -- -- -- -- -- UU -- -- -- -- (UU可能表示内核驱动已占用)
    ...

    如果i2cdetect能够扫描到摄像头的 I2C 地址,说明摄像头至少在 I2C 通信层面被识别了。

Q30:RDK S100 Docker 安装后服务启动失败

docker 需要使用 iptables 的 legacy 模式,用户可以使用以下命令修复 docker 运行:

sudo update-alternatives --set iptables /usr/sbin/iptables-legacy
sudo update-alternatives --set ip6tables /usr/sbin/ip6tables-legacy
sudo systemctl restart docker

Q31:RDK S100 时区设置

RDK S100系统默认使用上海时区(UTC+8),该配置通过/etc/systemd/system.conf文件中的以下参数实现:

DefaultEnvironment="TZ=CST-08:00"

如果需要手动配置,请注释掉DefaultEnvironment="TZ=CST-08:00",然后reboot重启设备使配置生效。

Q32: RDKS100 桌面应用Power Statistics 应用设备节点显示不全问题

RDKS100默认不支持,未提供相应的驱动。如用户需要支持显示适配器信息和电池信息,请用户自行联系电源管理芯片供应商提供驱动。

下面内容对电源统计驱动做的简单介绍,Power Statistics 应用的信息是根据显示/sys/class/power_supply/下的节点信息进行显示的

  • sys/class/power_supply/ac 外部充电器充电相关
  • sys/class/power_supply/usb usb 充电相关
  • sys/class/power_supply/battery 电池状态相关

以下以内核自带的测试驱动 test_power.c 为例,做一下简单介绍

  1. 驱动代码存放位置:kernel/drivers/power/supply
    kernel/drivers/power/supply/
├── 88pm860x_battery.c
├── 88pm860x_charger.c
├── ab8500_bmdata.c
├── test_power.c # 内核自带测试驱动
├── Kconfig # 给内核添加编译选项
├── Makefile # 将test_power.c编译进内核
  1. Kconfig 文件
    config TEST_POWER
tristate "Test power driver"
help
This driver is used for testing. It's safe to say M here.
  1. Makefile 文件
    obj-$(CONFIG_TEST_POWER) += test_power.o
  1. test_power.c 主要接口:
    power_supply_register()接口介绍

功能:用于注册一个电源设备(如 AC、Battery、USB 等),让内核和用户空间可以统一访问和管理电源信息。

设备原型:
struct power_supply *power_supply_register(
struct device *parent,
const struct power_supply_desc *desc,
const struct power_supply_config *cfg
);

参数:
parent :父设备指针,一般传 NULL,表示没有父设备
desc :指向 struct power_supply_desc,描述电源设备属性、类型、回调函数等
cfg :电源配置结构体,提供 of_node、supplied_to、num_supplicants 等信息

主要部分如下(详细内容可查看 test_power.c 文件):

    #include <linux/kernel.h>
#include <linux/module.h>
#include <linux/power_supply.h>
#include <linux/errno.h>
#include <linux/delay.h>
#include <generated/utsrelease.h>

enum test_power_id {
TEST_AC,
TEST_BATTERY,
TEST_USB,
TEST_POWER_NUM,
};

static int ac_online = 1;
static int usb_online = 1;
static int battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
static int battery_health = POWER_SUPPLY_HEALTH_GOOD;
static int battery_present = 1; /* true */
static int battery_technology = POWER_SUPPLY_TECHNOLOGY_LION;
static int battery_capacity = 50;
static int battery_voltage = 3300;
static int battery_charge_counter = -1000;
static int battery_current = -1600;

static bool module_initialized;

/* -------------------------
* AC 电源属性获取函数
* ------------------------- */

static int test_power_get_ac_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
switch (psp) {
case POWER_SUPPLY_PROP_ONLINE:
val->intval = ac_online;
break;
default:
return -EINVAL;
}
return 0;
}

/* -------------------------
* USB 电源属性获取函数
* ------------------------- */

static int test_power_get_usb_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
switch (psp) {
case POWER_SUPPLY_PROP_ONLINE:
val->intval = usb_online;
break;
default:
return -EINVAL;
}
return 0;
}

/* -------------------------
* 电池属性获取函数
* ------------------------- */

static int test_power_get_battery_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
switch (psp) {
case POWER_SUPPLY_PROP_MODEL_NAME:
val->strval = "Test battery";
break;
case POWER_SUPPLY_PROP_MANUFACTURER:
val->strval = "Linux";
break;
.
.
.
default:
pr_info("%s: some properties deliberately report errors.\n",
__func__);
return -EINVAL;
}
return 0;
}
.
.
.
static int __init test_power_init(void)
{
int i;
int ret;

BUILD_BUG_ON(TEST_POWER_NUM != ARRAY_SIZE(test_power_supplies));
BUILD_BUG_ON(TEST_POWER_NUM != ARRAY_SIZE(test_power_configs));

for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++) {
test_power_supplies[i] = power_supply_register(NULL,
&test_power_desc[i],
&test_power_configs[i]);
if (IS_ERR(test_power_supplies[i])) {
pr_err("%s: failed to register %s\n", __func__,
test_power_desc[i].name);
ret = PTR_ERR(test_power_supplies[i]);
goto failed;
}
}

module_initialized = true;
return 0;
failed:
while (--i >= 0)
power_supply_unregister(test_power_supplies[i]);
return ret;
}
module_init(test_power_init); // 驱动注册阶段

static void __exit test_power_exit(void)
{
int i;

/* Let's see how we handle changes... */
ac_online = 0;
usb_online = 0;
battery_status = POWER_SUPPLY_STATUS_DISCHARGING;
for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++)
power_supply_changed(test_power_supplies[i]);
pr_info("%s: 'changed' event sent, sleeping for 10 seconds...\n",
__func__);
ssleep(10);

for (i = 0; i < ARRAY_SIZE(test_power_supplies); i++)
power_supply_unregister(test_power_supplies[i]);

module_initialized = false;
}
module_exit(test_power_exit); // 驱动卸载阶段