LuckFox FAQ Печать
Добавил(а) microsin   

Решения различных вопросов, возникающих при работе с аппаратной платформой LuckFox (серия плат для разработки на основе процессоров Rockchip RV1103 и RV1106).

Инструкция [1], под Ubuntu 24.04.3 LTS:

1. Установка зависимостей:

$ sudo apt update
$ sudo apt-get install -y git ssh make gcc gcc-multilib g++-multilib module-assistant expect g++ gawk \
 texinfo libssl-v bison flex fakeroot cmake unzip gperf autoconf device-tree-compiler libncurses5-dev \
 pkg-config bc python-is-python3 passwd openssl openssh-server openssh-client vim file cpio rsync

2. Клонирование последнего SDK:

$ git clone https://gitee.com/LuckfoxTECH/luckfox-pico.git

[Структура каталога SDK (luckfox-pico)]

├── build.sh -> project/build.sh ---- скрипт компиляции SDK
├── media --------------------------- Multimedia encoding/decoding, ISP, etc.(1)
├── sysdrv -------------------------- U-Boot, kernel, rootfs(1)
├── project ------------------------- Образцовые приложения, конфигурации компиляции, директория scripts
├── output -------------------------- Для сохранения файлов образа после компиляции SDK
└── tools --------------------------- прошивка образа и утилиты прошивки

Примечание (1): можно компилировать независимо.

Директория хранилища образа:

output/
├── image
│   ├── download.bin ---------------- Программа на стороне устройства для обновления коммуникации
|   |                                 с утилитами прошивки, загружается только в память платы
│   ├── env.img --------------------- Таблица разделов (partition table) и параметры загрузки
|   |                                 (boot parameters)
│   ├── uboot.img ------------------- U-Boot image
│   ├── idblock.img ----------------- Loader image
│   ├── boot.img -------------------- Kernel image
│   ├── rootfs.img ------------------ Kernel image
│   └── userdata.img ---------------- Userdata image
└── out
    ├── app_out --------------------- Файлы, компилируемые после компиляции reference application
    ├── media_out ------------------- Файлы, компилируемые после media-related компиляции
    ├── rootfs_xxx ------------------ File system packaging directory
    ├── S20linkmount ---------------- Partition mounting script
    ├── sysdrv_out ------------------ Файлы, компилируемые после sysdrv компиляции
    └── userdata -------------------- Userdata

[Файл конфигурации SDK]

1. Файлы конфигурации Luckfox-Pico series SDK находятся в папке project/cfg/BoardConfig_IPC.

luckfox-pico$ ls project/cfg/BoardConfig_IPC -1BoardConfig-EMMC-Buildroot-RV1106_Luckfox_Pico_86Panel-IPC.mk
BoardConfig-EMMC-Buildroot-RV1106_Luckfox_Pico_86Panel_W-IPC.mk
BoardConfig-EMMC-Buildroot-RV1106_Luckfox_Pico_Pi-IPC.mk
BoardConfig-EMMC-Buildroot-RV1106_Luckfox_Pico_Pi_W-IPC.mk
BoardConfig-EMMC-Buildroot-RV1106_Luckfox_Pico_Ultra-IPC.mk
BoardConfig-EMMC-Buildroot-RV1106_Luckfox_Pico_Ultra_W-IPC.mk
BoardConfig-EMMC-Buildroot-RV1106_Luckfox_Pico_Zero-IPC.mk
BoardConfig-EMMC-Busybox-RV1106_Luckfox_Pico_Ultra-IPC_FASTBOOT.mk
BoardConfig-SD_CARD-Buildroot-RV1103_Luckfox_Pico-IPC.mk
BoardConfig-SD_CARD-Buildroot-RV1103_Luckfox_Pico_Mini-IPC.mk
BoardConfig-SD_CARD-Buildroot-RV1103_Luckfox_Pico_Plus-IPC.mk
BoardConfig-SD_CARD-Buildroot-RV1103_Luckfox_Pico_WebBee-IPC.mk
BoardConfig-SD_CARD-Buildroot-RV1106_Luckfox_Pico_Pro_Max-IPC.mk
BoardConfig-SPI_NAND-Buildroot-RV1103_Luckfox_Pico_Mini-IPC.mk
BoardConfig-SPI_NAND-Buildroot-RV1103_Luckfox_Pico_Plus-IPC.mk
BoardConfig-SPI_NAND-Buildroot-RV1103_Luckfox_Pico_WebBee-IPC.mk
BoardConfig-SPI_NAND-Buildroot-RV1106_Luckfox_Pico_Pro_Max-IPC.mk
BoardConfig-SPI_NAND-Busybox-RV1106_Luckfox_Pico_Pro_Max-IPC_FASTBOOT.mk
luckfox-buildroot-nocsi-oem-pre.sh
luckfox-buildroot-oem-pre.sh
luckfox-glibc-oem-pre.sh
luckfox-rv1106-tb-emmc-post.sh
luckfox-rv1106-tb-spi_nand-post.sh
luckfox-systemd-off-modem-post.sh
luckfox-userdata-pre.sh
overlay

2. Если взять в качестве примера конфиг BoardConfig-SD_CARD-Buildroot-RV1106_Luckfox_Pico_Pro_Max-IPC.mk, то можно рассмотреть его основные ключи.

# Размер CMA в окружении
export RK_BOOTARGS_CMA_SIZE="66M"

# Kernel dts
export RK_KERNEL_DTS=rv1106g-luckfox-pico-pro-max.dts

# Откуда загружаться (target boot medium)
export RK_BOOT_MEDIUM=sd_card

# Конфигурация раздела в окружении
# Формат RK_PARTITION_CMD_IN_ENV:
# < partdef>[,< partdef>]
# < partdef> := < size>[@< offset>](part-name)
# Примечание: если смещение первого раздела не 0x0, то это должно быть добавлено.
# Иначе добавлять не нужно.
export RK_PARTITION_CMD_IN_ENV="32K(env),512K@32K(idblock),256K(uboot),32M(boot),512M(oem),256M(userdata),6G(rootfs)"

# Target rootfs
export LF_TARGET_ROOTFS=buildroot

# SUBMODULES : gitee/gitee
export LF_SUBMODULES_BY=gitee

# Buildroot defconfig
export RK_BUILDROOT_DEFCONFIG=luckfox_pico_defconfig

Здесь:

RK_BOOTARGS_CMA_SIZE: выделение памяти для камеры; если камера не используется, измените это значение на 1M.

RK_KERNEL_DTS: указывает файл дерева устройств (device tree file, DTS).

RK_BOOT_MEDIUM: указывает носитель загрузки (target boot medium), который может быть emmc (карта SD), sd_card (карта SD), spi_nor (SPI NOR Flash) или spi_nand (SPI NAND Flash).

RK_PARTITION_CMD_IN_ENV: эта информация используется для конфигурирования таблицы разделов. Если вам нужно сопоставить дисковое пространство с SD-картой, то вы можете изменить раздел rootfs.

LF_TARGET_ROOTFS: указывается корневая файловая система target (Root File System).

LF_SUBMODULES_BY: указывается источник субмодулей.

RK_BUILDROOT_DEFCONFIG: указывается конфигурационный файл Buildroot.

[Компиляция образов]

Из описания в предыдущем разделе можно увидеть, что образ Ubuntu поддерживает загрузку только с SD-карточки (SD card boot), в то время как образ Buildroot поддерживает как загрузку с TF-карты (TransFlash), так и загрузку из микросхемы памяти (SPI NAND FLASH boot).

1. Если вам нужно компилировать образ для системы Ubuntu и использовать gitee, то измените соответствующий mk-файл, задающий тип платы, чтобы отредактировать LF_SUBMODULES_BY для gitee, примерно так:

LF_SUBMODULES_BY=gitee

2. Если вы хотите компилировать образ Buildroot для загрузки TF card boot, то измените соответствующий файл BoardConfig-EMMC-Ubuntu-xxx.mk, чтобы поменять LF_TARGET_ROOTFS на buildroot, примерно так:

export LF_TARGET_ROOTFS=buildroot

3. Установите cross-compilation toolchain:

$ cd {SDK_PATH}/tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/
$ source env_install_toolchain.sh

4. Скомпилируйте все образы:

$ cd luckfox-pico
# Компиляция busybox/buildroot $ ./build.sh lunch $ ./build.sh
# Компиляция ubuntu $ sudo ./build.sh lunch $ sudo ./build.sh

Примечание: когда компилируется Ubuntu, используйте sudo, чтобы избежать файловых ошибок системы. Следующие инструкции не делают различий между этими двумя вариантами компиляции, но вы действуйте в соответствии с вашей ситуацией.

[Компиляция по частям]

Отдельная компиляция загрузчика U-Boot:

$ ./build.sh clean uboot
$ ./build.sh uboot

Сгенерированные файлы образа: output/image/MiniLoaderAll.bin и output/image/uboot.img

Отдельная компиляция ядра:

$ ./build.sh clean kernel
$ ./build.sh kernel

Сгенерированный файл образа: output/image/boot.img

Отдельная компиляция корневой файловой системы:

$ ./build.sh clean rootfs
$ ./build.sh rootfs

Примечание: после компиляции используйте команду ./build.sh firmware для переупаковки.

Отдельная компиляция media:

$ ./build.sh clean media
$ ./build.sh media

Файлы сохраняются в директории: output/out/media_out. После компиляции используйте команду ./build.sh firmware для переупаковки.

Отдельная компиляция образцовых приложений:

$ ./build.sh clean app
$ ./build.sh app

Примечания: app зависит от media. После компиляции используйте команду ./build.sh firmware для переупаковки.

Упаковка прошивки (firmware packaging):

$ ./build.sh firmware

Компиляция busybox/buildroot:

$ ./build.sh lunch
$ ./build.sh

Компиляция Ubuntu:

$ sudo ./build.sh lunch
$ sudo ./build.sh

Это принципиально разные подходы к сборке операционной системы для вашего Luckfox Pico. Сравнительная таблица:

ХарактеристикаBusybox / BuildrootUbuntu
Суть Минималистичная встроенная система (Embedded) Полноценная настольная ОС (Desktop)
Процесс сборки ./build.sh lunch -> Выбрать config -> ./build.sh sudo ./build.sh lunch -> Выбрать config -> sudo ./build.sh
Размер системы Маленький (десятки МБ) Очень большой (сотни МБ - ГБ)
Время сборки Минуты Десятки минут - часы
Количество пакетов Ограниченный, предустановленный набор Огромный репозиторий (apt), тысячи пакетов
Гибкость Вы компилируете только то, что нужно Вы получаете готовую систему со всем софтом
Использование Промышленные устройства, IoT, дроны, где важны размер и скорость Разработка, прототипирование, когда нужен привычный Linux-инструментарий
Управление пакетами Нет менеджера пакетов. Софт добавляется на этапе сборки. Есть apt — можно ставить/удалять что угодно.
Init система Обычно простой init или busybox init systemd
Требования к правам Обычные права пользователя (./build.sh) Требуются права root (sudo ./build.sh)

[Подробное объяснение]

1. Compile busybox/buildroot

Это стандартный способ для embedded-устройств. Buildroot — это инструмент для сборки, который:

  • Берет ядро Linux (kernel).
  • Компилирует минимальный набор системных библиотек (например, uClibc или glibc).
  • Использует Busybox — "швейцарский нож", который заменяет собой сотни стандартных UNIX-утилит (ls, cp, mvvi, ifconfig и т.д.) одним бинарным файлом, экономя огромное количество места.
  • Собирает всё это в компактный образ rootfs (корневой файловой системы).
  • Результат: Вы получаете минимальную, быструю и экономичную систему, идеально подходящую для финального продукта. Но установить новые программы "на лету" не получится — для этого нужно пересобирать весь образ.
  • Когда использовать: для готовых устройств, где важны размер, скорость загрузки и безопасность.

    2. Compile ubuntu

    Это способ для тех, кому нужна полноценная и привычная среда. Здесь скрипты не собирают систему с нуля, а кастомизируют и адаптируют готовые образы Ubuntu (чаще всего Ubuntu Base или Core) под архитектуру Luckfox Pico. В результате вы получаете почти ту же Ubuntu, что и на ПК, но собранную для ARM-процессора. В ней есть менеджер пакетов apt, вы можете легко установить python3, gcc, vim или любой другой пакет из репозиториев Ubuntu.

    Почему нужен sudo? Процесс адаптации образа часто involves mounting образы файловых систем и выполнение операций, требующих прав суперпользователя (например, chroot для установки пакетов или настройки).

    Когда использовать: Для разработки и отладки, когда вам нужен доступ к большому количеству инструментов и библиотек без необходимости их самостоятельной кросс-компиляции.

    [Итог: Какой вариант выбрать?]

    Если вы разработчик и хотите быстро протестировать код, использовать привычные инструменты (apt, systemd)? Тогда выбирайте Ubuntu. Если же вы создаете устройство для продажи или развертывания, где критически важен минимальный размер образа и максимальная скорость? Выбирайте Buildroot/Busybox.

    На практике часто начинают с Ubuntu для удобства прототипирования, а для финальной версии продукта переходят на Buildroot, чтобы оптимизировать образ.

    Gitee Source (или Gitee источник) — это серверы-зеркала (репозитории) на платформе Gitee.com, которые хранят копии исходного кода и пакетов с других открытых платформ (в первую очередь — GitHub). Их основная цель — ускорение доступа к этим ресурсам для разработчиков внутри Китая.

    Если говорить проще, Gitee Source — это "зеркало" или "кэш" для исходного кода.

    Детальное объяснение:

    Для чего это нужно?

    • Обход ограничений: прямой доступ к международным платформам, like GitHub, из Китая может быть медленным, нестабильным или вовсе ограниченным (из-за Великого файервола).

    • Высокая скорость: Gitee-зеркала расположены на территории Китая, поэтому местные разработчики и системы CI/CD (как в вашем случае со сборкой Luckfox Pico) могут скачивать код и пакеты с огромной скоростью.

    • Национальная безопасность: создание локальных копий критически важного opensource-кода является элементом технологического суверенитета.

    Как это работает?

    • Платформа Gitee автоматически или вручную периодически синхронизируется (копирует) популярные репозитории с GitHub и других платформ.

    • Когда вы в процессе сборки (как примере с ./build.sh) указываете использовать gitee source, система не идет на GitHub за исходным кодом ядра Linux, тулчейна (toolchain) или библиотек, а скачивает их с быстрого локального зеркала на Gitee.

    Где вы с этим сталкиваетесь?

    Именно в сценариях, подобных вашему — при сборке прошивок для embedded-устройств (Luckfox Pico, Raspberry Pi, Orange Pi и т.д.) с помощью скриптов вроде build.sh. Внутри таких скриптов часто есть выбор source (источника для загрузки). Обычно это выглядит так:

    • github (оригинальный, медленный для Китая)
    • gitee (зеркало, быстрое для Китая)
    Иногда gitlab или другие.

    Пример из практики: допустим, скрипту сборки нужен исходный код ядра Linux (linux.git). Вместо того чтобы клонировать его с https://github.com/torvalds/linux, что будет медленно, он клонирует его с https://gitee.com/mirrors/linux.git, что происходит почти мгновенно.

    Итог:

    Gitee Source — это техническое решение для ускорения и стабилизации разработки внутри Китая путем создания локальных копий международных opensource-репозиториев. Когда вы в процессе сборки видите упоминание gitee, это означает, что инструменты будут качать код не с медленного GitHub, а с его быстрого китайского зеркала.

    В вашем случае, при выполнении ./build.sh lunch, вам, скорее всего, предложат выбрать платформу (например, luckfox_pico) и, возможно, источник для загрузки (github или gitee). Выбор gitee значительно ускорит процесс, если вы находитесь в Китае или используете китайское железо/провайдера.

    TF card — это старое название карт microSD. По современным стандартам это одно и то же. Подробности см. в Википедии.

    В контексте одноплатных компьютеров LuckFox (и других подобных плат на процессорах Rockchip), термин `media` имеет очень конкретное и важное значение.

    `Media` здесь — это сокращение от "Multimedia" и относится к подсистеме обработки мультимедиа внутри процессора (SoC). Это целый набор аппаратных блоков (IP-ядер) и программного обеспечения, отвечающих за работу с видео и изображениями.

    Если говорить просто, `media` в LuckFox — это всё, что позволяет плате "видеть" и "показывать".

    [Что входит в подсистему Media?]

    Эта подсистема включает в себя два основных направления:

    1. Видеозахват (Video Input - VI). Это аппаратные блоки и драйверы, отвечающие за приём видео от камер.

    ISP (Image Signal Processor): "Мозги" обработки изображения. Он преобразует сырые данные (raw data) с матрицы камеры в привычное нам изображение, выполняя:

           Дебейеризацию (Demosaic) — преобразование сырых данных с Bayer-фильтра в цветное изображение.
           Коррекцию белого (AWB)
           Автоэкспозицию (AE)
           • Подавление шумов (3DNR)
           Резкость (Sharpness)
           Коррекцию линз (LSC)

    MIPI CSI (Camera Serial Interface): hardware-интерфейс, к которому физически подключаются современные камерные модули (например, ваши камеры LuckFox).

    VIPP (Video Input Post Processor): блок для дальнейшей обработки уже сформированного изображения (масштабирование, обрезка).

    2. Видеовывод и Кодирование/Декодирование (Video Output & Codec). Это аппаратные блоки, отвечающие за сжатие, распаковку и вывод видео.

    VPU (Video Processing Unit): hardware-энкодер и декодер. Именно он позволяет кодировать (сжимать) видео с камеры в форматы **H.264** или **H.265 (HEVC)** с очень малым потреблением энергии процессора. Это критически важно для видеорегистраторов, камер наблюдения.

    VOP (Video Output Processor): блок, управляющий выводом изображения на дисплей (например, по HDMI или через LVDS-интерфейс).

    [Где вы встречаетесь с термином "media" в LuckFox?]

    1. В Device Tree (`*.dts`): конфигурация всей подсистемы `media` (какие камеры подключены, их разрешение, режимы работы ISP) прописывается в файле дерева устройств.

    2. В ядре Linux (`kernel/`): драйверы, находящиеся в разделах типа `drivers/media/platform/rockchip/isp/`, `.../mipi-csi/`, `.../rkcif/`.

    3. В пользовательском пространстве:

        • Утилита `rkisp_demo`: позволяет тестировать и настраивать работу ISP (задавать параметры цветокоррекции, резкости и т.д.).
        Утилита `v4l2-ctl`: стандартная Linux-утилита для работы с видеоустройствами (Video4Linux2). Через неё можно посмотреть список доступных камер (`v4l2-ctl --list-devices`), получить формат изображения с камеры и т.д.
        Утилита `rkmpp`: набор утилит для работы с hardware-кодеком (VPU) — кодирование, декодирование видео.

    Пример рабочего потока (pipeline) `media`:

    Камера (Sensor)

        -> MIPI CSI-2 Interface 
        -> CIF (Capture Input Frame) 
        -> ISP (Image Signal Processor) 
        -> RGA (для rotation/scaling) 
        -> VPU (для кодирования в H.264) 
        -> Файл или сеть (RTSP-поток).

    Итог:

    В контексте LuckFox термин `media` — это не абстрактное "медиа", а конкретное название мощной аппаратно-программной подсистемы, которая отвечает за:

    * Захват видео с камеры
    * Обработку изображения (улучшение качества)
    * Кодирование и декодирование видео
    * Вывод видео на дисплей

    Именно эта подсистема является ключевым преимуществом процессоров Rockchip и делает платы LuckFox такими популярными для проектов компьютерного зрения, видеонаблюдения и потокового вещания.

    Buildroot — это не дистрибутив Linux (как Ubuntu или Debian), а система автоматизации сборки. Её главная задача — собрать всё необходимое для работы встроенной системы (embedded Linux) из исходного кода с помощью инструмента make.

    Представьте себе конструктор или конвейер, который по вашему заказу:

    • Скачивает исходные коды нужной версии ядра Linux, библиотек и программ.
    • Настраивает и компилирует их друг за другом, учитывая все зависимости.
    • На выходе выдает готовые образы: ядро (kernel.img), Device Tree (dtb) и, самое главное, корневую файловую систему (rootfs) — то есть набор всех библиотек, системных утилит и ваших программ, упакованный в один файл.

    Главная философия Buildroot — создавать минималистичные и эффективные системы без лишнего софта, что идеально для устройств с ограниченными ресурсами, наподобие плат разработчика Luckfox Pico Mini.

    Buildroot предоставляется производителем (Luckfox) в составе Software Development Kit (SDK), и внутри этого SDK Buildroot является основным движком для сборки всей операционной системы.

    Когда вы скачиваете официальный SDK для Luckfox Pico, его структура обычно включает:

    buildroot/ — Сама система Buildroot с конфигурациями и настройками от Luckfox.
    linux/ — Исходный код ядра Linux, патченного для поддержки чипа RV1103.
    uboot/ — Исходный код загрузчика U-Boot.
    output/ — Директория, куда помещаются готовые образы после сборки.

    Процесс разработки выглядит так:

    1. Вы входите в директорию SDK.

    2. Запускаете команду ./build.sh (это скрипт-обертка от Luckfox). Он скрипт запускает Buildroot, который, в свою очередь:

    - Компилирует кросс-компилятор (gcc) для архитектуры ARM.
    - Конфигурирует и компилирует ядро Linux.
    - Компилирует загрузчик U-Boot.
    - Собирает корневую файловую систему: берет базовый набор утилит (BusyBox), добавляет именно те библиотеки и программы, которые указаны в конфигурации (например, поддержку Wi-Fi, инструменты для работы с GPIO, примеры кода для работы с камерой и NPU).

    3. В результате в папке output/ вы получаете файлы rootfs.img, kernel.img и другие, которые можно прошить на вашу плату с помощью инструмента RKDevTool.

    Buildroot для Luckfox Pico Mini используется по следующим соображениям:

    • Легковесность: итоговая система получается очень маленькой. Образ rootfs.img может весить всего несколько десятков мегабайт, что идеально для встроенных устройств.
    • Простота и скорость: процесс сборки полностью автоматизирован одной командой. Не нужно вручную собирать каждую библиотеку.
    • Полный контроль: вы можете тонко настроить систему через конфигурационное меню (make menuconfig), чтобы включить или выключить тысячи опций, добавить конкретные библиотеки или свои приложения. Это избавляет систему от любого "мусора".
    • Повторяемость: процесс сборки детерминирован. Вы можете быть уверены, что соберете абсолютно идентичную систему на другой машине, что критически важно для разработки и промышленного применения.

    [Альтернативы Buildroot]

    Часто Buildroot сравнивают с Yocto Project. Оба решают одну задачу, но по-разному:

    Buildroot: Проще в освоении, быстрее собирает систему, идеален для относительно простых устройств и быстрого прототипирования (как в случае с Luckfox Pico).

    Yocto: Более мощный, гибкий и сложный инструмент, предназначенный для создания промышленных дистрибутивов с поддержкой множества пакетов и архитектур. Его кривая обучения значительно круче.

    Итог:

    Buildroot в контексте Luckfox Pico Mini — это "сердце" процесса сборки прошивки. Это инструмент, который превращает исходные коды ядра Linux, загрузчика U-Boot и сотен отдельных программ в единый, готовый к прошивке, минималистичный и оптимизированный образ операционной системы, который превращает голое "железо" Luckfox Pico в работающий мини-компьютер с Linux, способный выполнять ваши задачи.

    Без Buildroot вам пришлось бы вручную компилировать и компоновать все части ОС, что является невероятно сложной и трудоемкой задачей. Buildroot автоматизирует этот процесс до одной команды.

    Определить модель платы LuckFox Pico можно несколькими способами, от самого простого (визуальный осмотр) до более сложных (программных).

    [Способ 1: визуальный осмотр (cамый быстрый и простой)]

    Это первый и часто самый эффективный шаг. Посмотрите на вашу плату и найдите ключевые отличия. Ниже перечислены ключевые признаки для идентификации.

    1. Размер и форма платы:

    LuckFox Pico: самая маленькая плата (примерно 20x20 мм), квадратной формы. Выглядит как "голый" модуль без портов.
    LuckFox Pico Plus: чуть больше (примерно 30x30 мм), тоже квадратной формы. Часто на модуле есть металлическая крышка-радиатор.
    LuckFox Pico Mini: имеет вытянутую прямоугольную форму (примерно 56x26 мм). Все компоненты распаяны прямо на плате, модульной конструкции нет. На нижней стороне платы (противоположной кнопке BOOT) шелкографией нанесена надпись "Luckfox Pico Mini".
    LuckFox Pico Pro: cамая большая плата (примерно 56x56 мм), имеет прямоугольную форму с множеством разъемов.

    2. Наличие и тип интерфейсов:

    Ethernet (Сетевой порт RJ45): есть только у LuckFox Pico Mini A и LuckFox Pico Mini B. У модели "A" один порт, у модели "B" два порта.
    USB Type-C (для питания и данных): есть у всех моделей Mini, Plus и Pro. У базового Pico его нет (присутствуют только контакты для пайки).
    Разъем для камеры (MIPI CSI): есть у Mini B, Plus и Pro. У Mini A и базового Pico его нет.
    Разъем для дисплея (MIPI DSI): есть только у LuckFox Pico Pro.

    3. Количество и расположение контактов GPIO:

    LuckFox Pico: 24 контакта (2 ряда по 12 с каждой стороны).
    LuckFox Pico Mini: 22 контакта (2 ряда по 11 вдоль длинной стороны).
    LuckFox Pico Plus: 38 контактов.
    LuckFox Pico Pro: 48 контактов.

    LuckFox Pico:

    Pico pinout

    LuckFox Pico Mini A/B:

    Pico Mini AB pinout

    B-версия LuckFox Pico Mini отличается от A-версии только наличием распаянной на плате Flash памяти на 128 Мб. На Flash можно поставить операционную систему, но объема 128 Мб довольно мало (хотя в варианте сборки Buildroot для многих задач может хватить). Если использовать загрузку с карты SD, где памяти может быть намного больше, то Flash на плате можно использовать в качестве резервного хранилища важных данных, например, логов.

    LuckFox Pico Plus:

    Pico Plus pinout

    LuckFox Pico Pro/Max:

    Pico Pro Max pinout

    LuckFox Pico Ultra/Ultra W:

    Pico Ultra Ultra W pinout

    [Способ 2: определение через Linux (если плата уже прошита)]

    Если плата запускается, и у вас есть доступ к её командной строке (через UART, SSH или ADB [4]), то вы можете использовать несколько команд.

    1. Посмотреть модель в `proc/device-tree/` (самый точный способ). Проприетарные параметры платы хранятся в Device Tree. Выполните команду:

    # cat /proc/device-tree/model
    

    Результат будет прямо указывать на модель, например:

    `luckfox,pico` → LuckFox Pico
    `luckfox,pico-mini` → LuckFox Pico Mini
    `luckfox,pico-plus` → LuckFox Pico Plus
    `luckfox,pico-pro` → LuckFox Pico Pro

    2. Посмотреть информацию о процессоре. Следующая команда покажет не модель платы, а модель чипа, это тоже может быть полезно.

    [root@luckfox ]# cat /proc/cpuinfo
    processor	: 0
    model name	: ARMv7 Processor rev 5 (v7l)
    BogoMIPS	: 26.08
    Features	: half thumb fastmult vfp edsp neon vfpv3 tls vfpv4 idiva idivt vfpd32 lpae 
    CPU implementer	: 0x41
    CPU architecture: 7
    CPU variant	: 0x0
    CPU part	: 0xc07
    CPU revision	: 5
    Hardware : Rockchip (Device Tree) Revision : 0000 Serial : 359238bf91d2b5a8

    3. Проверить наличие определенных устройств (косвенный метод). Проверить сетевые интерфейсы позволяет команда `ifconfig -a` или `ip addr`:

    [root@luckfox ]# ifconfig -a
    lo        Link encap:Local Loopback  
              inet addr:127.0.0.1  Mask:255.0.0.0
              UP LOOPBACK RUNNING  MTU:65536  Metric:1
              RX packets:11948 errors:0 dropped:0 overruns:0 frame:0
              TX packets:11948 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000 
              RX bytes:884044 (863.3 KiB)  TX bytes:884044 (863.3 KiB)
    usb0      Link encap:Ethernet  HWaddr 06:2C:70:05:43:2B  
              inet addr:172.32.0.93  Bcast:172.32.255.255  Mask:255.255.0.0
              UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
              RX packets:2043 errors:0 dropped:1563 overruns:0 frame:0
              TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:1000 
              RX bytes:334536 (326.6 KiB)  TX bytes:0 (0.0 B)
    [root@luckfox ]# ip addr 1: lo: < LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever 2: usb0: < BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast qlen 1000 link/ether 06:2c:70:05:43:2b brd ff:ff:ff:ff:ff:ff inet 172.32.0.93/16 brd 172.32.255.255 scope global usb0 valid_lft forever preferred_lft forever

    Если видите `eth0` и `eth1`, то скорее всего это Pico Mini B. Если видите только `eth0`, то скорее всего это Pico Mini A. Если Ethernet-интерфейсов нет вообще, то это базовая Pico (без Ethernet).

    Проверить наличие аудиоустройства: команда `ls /dev/snd/`.

    [root@luckfox ]# ls /dev/snd/
    by-path controlC0 pcmC0D0c pcmC0D0p

    Наличие звуковых устройств характерно для моделей Plus и Pro.

    [Способ 3: по надписям на упаковке или плате]

    Производитель часто наносит шелкографию с названием модели на саму плату. Ищите надписи типа "Pico", "Pico Mini", "Pico Plus" или "Pico Pro".

    Коробка или антистатический пакет, в котором пришла плата, почти всегда имеют наклейку с точным указанием модели (например, "LuckFox Pico Mini B").

    BusyBox — это единственный исполняемый файл, который заменяет собой сотни маленьких стандартных UNIX-утилит (команд), таких как:

    `ls`, `cp`, `mv`, `mkdir`, `rm` (команды работы с файлами)
    `sh`, `bash` (командная оболочка)
    `grep`, `awk`, `sed` (поиск, обработка текста)
    `ping`, `ifconfig`, `netstat` (для работы с сетью)
    `vi` (простой текстовый редактор)

    И также многие другие команды. Это видно по множеству символических ссылок с команд на единственный исполняемый файл busybox:

    [root@luckfox ]# ls -la /bin
    total 5936
    drwxrwxr-x    2 1000     1000          5768 Sep 16  2025 .
    drwxr-xr-x   20 1000     1000          1584 Sep 16  2025 ..
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 arch -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 ash -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 base32 -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 base64 -> busybox
    -rwxr-xr-x    1 1000     1000        990960 Sep 16  2025 bash
    -rwxr-xr-x    1 1000     1000        857296 Sep 16  2025 busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 cat -> busybox
    -rwxr-xr-x    1 1000     1000          9304 Sep 16  2025 chattr
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 chgrp -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 chmod -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 chown -> busybox
    -rwxr-xr-x    1 1000     1000          1342 Sep 16  2025 compile_et
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 cp -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 cpio -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 date -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 dd -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 df -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 dmesg -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 dnsdomainname -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 dumpkmap -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 echo -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 egrep -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 false -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 fdflush -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 fgrep -> busybox
    -rwxr-xr-x    1 1000     1000          3477 Sep 16  2025 gcore
    -rwxr-xr-x    1 1000     1000       3486000 Sep 16  2025 gdb
    -rwxr-xr-x    1 1000     1000          4045 Sep 16  2025 gdb-add-index
    -rwxr-xr-x    1 1000     1000        253404 Sep 16  2025 gdbserver
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 getopt -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 grep -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 gunzip -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 gzip -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 hostname -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 kill -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 link -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 linux32 -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 linux64 -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 ln -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 login -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 ls -> busybox
    -rwxr-xr-x    1 1000     1000          9304 Sep 16  2025 lsattr
    -rwxrwxr-x    1 1000     1000         17900 Sep 16  2025 memtester
    -rwxr-xr-x    1 1000     1000          1102 Sep 16  2025 mk_cmds
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 mkdir -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 mknod -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 mktemp -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 more -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 mount -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 mountpoint -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 mt -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 mv -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 netstat -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 nice -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 nuke -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 pidof -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 ping -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 pipe_progress -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 printenv -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 ps -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 pwd -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 resume -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 rm -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 rmdir -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 run-parts -> busybox
    -rwxrwxr-x    1 1000     1000            88 Sep 16  2025 sdkinfo
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 sed -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 setarch -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 setpriv -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 setserial -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 sh -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 sleep -> busybox
    -rwxr-xr-x    1 1000     1000        236644 Sep 16  2025 stressapptest
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 stty -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 su -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 sync -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 tar -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 touch -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 true -> busybox
    -rwxr-xr-x    1 1000     1000        178592 Sep 16  2025 udevadm
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 umount -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 uname -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 usleep -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 vi -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 watch -> busybox
    lrwxrwxrwx    1 1000     1000             7 Sep 16  2025 zcat -> busybox
    

    Таким образом, каждая из этих команд представлена не отдельной программой, а всего лишь "ссылкой" на главный исполняемый файл `busybox`. Например, когда вы вызываете команду `ls`, на самом деле система запускает `busybox ls`, и BusyBox "понимает", что нужно выполнить функцию `ls`.

    Почему BusyBox КРИТИЧЕСКИ важен для LuckFox Pico Mini? Именно здесь преимущества BusyBox раскрываются в полной мере:

    1. Экономия места файловой системы (что крайне важно!):

    - LuckFox Pico Mini имеет ограниченный объем флеш-памяти (обычно 4GB или 16GB eMMC), часть которой занята ядром Linux и вашими приложениями.
    - Если бы все утилиты (`ls`, `cp`, `ping` и т.д.) были полноценными отдельными бинарными файлами (как в Ubuntu), они заняли бы десятки мегабайт.
    - BusyBox упаковывает все эти функции в один исполняемый файл размером всего 1-2 мегабайта. Это огромная экономия драгоценного пространства.

    2. Экономия оперативной памяти: запущенные программы занимают оперативную память (RAM). Так как BusyBox — это одна программа, а не множество, она использует меньше RAM при выполнении различных задач.

    3. Упрощение сборки и управления: разработчикам встраиваемых устройств проще управлять одним пакетом (BusyBox), который предоставляет весь базовый функционал, вместо того чтобы отслеживать сотни отдельных мелких утилит. При сборке прошивки с помощью Buildroot (см. Q002) просто выбирается конфигурация BusyBox с нужным набором функций.

    4. Скорость и эффективность: BusyBox оптимизирован для работы на системах с ограниченными ресурсами, таких как LuckFox Pico Mini. Его код написан с упором на минимализм и скорость.

    Итак, когда вы подключаетесь к своей плате через UART, SSH или ADB и попадаете в командную строку встраиваемой системы, практически с каждым вашим действием происходит взаимодействие с BusyBox.

    Проверка, что вы используете BusyBox: введите любую команду с ключом --help, и вы увидите сигнатуру BusyBox. Например:

    .[root@luckfox ]# ls --help
    BusyBox v1.36.1 (2025-09-16 13:42:36 MSK) multi-call binary.
    Usage: ls [-1AaCxdLHRFplinshrSXvctu] [-w WIDTH] [FILE]...
    List directory contents -1 One column output -a Include names starting with . -A Like -a, but exclude . and .. -x List by lines -d List directory names, not contents -L Follow symlinks -H Follow symlinks on command line
    ...

    Первая строка четко указывает, что это BusyBox.

    Можно посмотреть, какие функции встроены в BusyBox. Для этого выполните команду `busybox` без аргументов, и она выведет большой список всех поддерживаемых applets (маленьких приложений-функций).

    Таким образом, BusyBox в контексте LuckFox — это фундаментальный строительный блок встраиваемой операционной системы. Это минималистичная, невероятно эффективная и универсальная замена всем стандартным UNIX-инструментам, которая позволяет уместить мощную и функциональную командную среду Linux в несколько мегабайт, что идеально соответствует ограниченным ресурсам платы. Без BusyBox встроенные Linux-системы like LuckFox Pico Mini были бы гораздо больше, дороже и менее эффективны.

    На самой плате поддерживаются busybox, buildroot и Ubuntu 22.04. На машине разработчика для кросс-компиляции может использоваться Ubuntu 24.04 или Docker.

    Запустите SocToolKit с правами администратора, и затем установите TF-карту. Если она все еще не распознается, закройте ПО антивируса. Попробуйте также загрузить новую версию SocToolKit.

    Емкость TF-карты слишком маленькая; рекомендуется использовать 8GB или больше.

    При использовании SocToolKit для прошивки firmware платы Luckfox Pico, утилита показывает, что файл luckfox pico\image\media.img не существует.

    Причина в том, что Luckfox Pico поддерживает только лишь загрузку с TF-карты (TF card boot), и она должна быть записана с помощью картридера.

    Облачный диск не предоставляет образ системы buildroot, подходящий для загрузки с карты SD. Вам нужно самостоятельно скомпилировать его в соответствии с секцией SDK. Поскольку емкость SD-карт может быть разной, вам необходимо вручную подстроить емкость раздела.

    При установке TF-карты в плату Luckfox Pico и подключении к компьютеру SocToolKit показывает режим Maskrom, и программа не может быть прошита.

    Причина в том, что Luckfox Pico поддерживает только лишь загрузку с TF-карты (TF card boot). Используйте картридер для записи карты, после чего установите карту в слот платы для запуска системы.

    Попытка подключения не удается с сообщением, что подключенная сторона не ответила должным образом через определенный промежуток времени, или из-за того, что подключенный узел не ответил.

    Для решения проблемы сконфигурируйте виртуальный сетевой интерфейс RNDIS.

    Проверьте совместимость уровней логики последовательного интерфейса, и не перепутаны ли прием с передачей (сигналы RX и TX). Luckfox-Pico работает с сигналами уровня логики 3.3V, и требует соответствующей установки уровней на модуле переходника USB - TTL UART.

    На официальном сайте заявлено, что у Luckfox-Pico и Luckfox-Pico-Mini/Plus установлено 64MB памяти, но фактический объем памяти около 34 MB.

    Вероятно проблема в том, что память выделена системой и работающим программным обеспечением. Пример вывода:

    [ 0.000000] Memory: 34328K/65536K available (3452K kernel code, 283K rwdata, 1644K rodata,
     144K init, 127K bss, 6632K reserved, 24576K cma-reserved)
    

    Для Luckfox-Pico-Pro/Max фактический размер памяти меньше 128MB и 256MB. Если камера не используется, то вы можете освободить память модификацией переменной RK_BOOTARGS_CMA_SIZE, изменив значение 66M на 1M.

    FAQ Luckfox Pico Pro nocam

    Если взять в качестве примера Luckfox-Pico-Pro, то модификация выглядит следующим образом:

    FAQ Luckfox Pico Pro nocam free

    После подключения Luckfox-Pico-Plus/Pro/Max через последовательный порт устройство все время посылает сообщение "udhcpc: sending discover".

    Если сетевой кабель не подключен, то в лог будет выводиться сообщение "udhcpc: sending discover". Подключите сетевой кабель, или используйте команду kill для остановки процесса udhcpc.

    # ps | grep udhcpc
      248 root      1196 S    udhcpc -i eth0
      311 root      1192 S    grep udhcpc
    # kill 248
    udhcpc: received SIGTERM
    

    Причина в том, что factory image предназначен главным образом для тестирования функционала GPIO. Вам необходимо самостоятельно прошить образ из онлайн-репозитория.

    Вы должны использовать инструментарий кросс-компиляции из SDK. После кросс-компиляции на хосте Ubuntu или виртуальной машине выгрузите результат компиляции на плату.

    При загрузке виртуальной машины VirtualBox появляется ошибка "VT-x is disabled in the BIOS for both all CPU modes (VERR_VMX_MSR_ALL_VMX_DI)".

    Причина ошибки в том, что не разрешена технология виртуализации CPU на материнской плате хоста. Выполните следующие шаги, основываясь на модели вашей материнской платы для доступа к BIOS компьютера:

    1. Например, материнские платы ASUS для входа в BIOS используют клавишу F2 во время запуска.
    2. Выберите Advanced settings.
    3. Найдите раздел CPU Configuration и установите разрешенной опцию Intel Virtualization Technology.
    4. В завершение нажмите F10 для сохранения изменений и перезапуска компьютера.

    Программа VLC по умолчанию использует видеобуфер размером в 1 секунду (1000ms = 1s). Можно умеренно сократить время буферизации для улучшения real-time производительности, но слишком низкая задержка может привести к потере пакетов и заиканию. Не рекомендуется устанавливать размер буфера меньше 300ms.

    FAQ Luckfox Pico VLC options

    VBUS подключен ко входному напряжению интерфейса Type-C; VSYS это входное напряжение основной системы, с напряжением в диапазоне от 4.5V до 5.5V.

    Плата распознается, но во время программирования происходит ошибка: "Error: Write LBA failed, can't read flash id from device".

    FAQ Luckfox Pico RKSOC Toolkit failed

    Решение: удалите USB HUB и подключите кабель платы напрямую к компьютеру.

    $ sudo cp -r luckfox-pico/ ~/Luckfox-test/
    $ cd ~/Luckfox-test/luckfox-pico/
    $ ./build.sh lunch
    ls: cannot access 'BoardConfig*.mk': No such file or directory
    You're building on Linux Lunch menu... pick a combo: ... показываются варианты для выбора платы ... Which would you like? [0]: 2 ln: failed to create symbolic link '/home/luckfox/Luckfox-test/luckfox-pico/.BoardConfig.mk': Permission denied
    [build.sh:error] Running build_select_board failed! [build.sh:error] exit code 1 from line 191:
    [build.sh:info] ln -rfs $TARGET_PRODUCT_DIR/$RK_BUILD_TARGET_BOARD $BOARD_CONFIG

    Возможная причина ошибки в том, что используется команда sudo в процессе копирования, поэтому могут быть измерены права доступа к файлам в SDK. Удалите и заново выполните копирование с правами обычного пользователя.

    При компиляции происходит ошибка загрузки модуля драйвера Linux, SDK не компилируется после clean.

    Случай 1:

    FAQ Luckfox Pico error 1

    Решение: используйте ./build.sh для полной перекомпиляции.

    Случай 2:

    FAQ Luckfox Pico error 2

    Решение: выполните команду:

    $ make ARCH=arm CROSS_COMPILE=/home/luckfox/Luckfox-Pico/luckfox-pico/tools/linux/toolchain/\
    arm-rockchip830-linux-uclibcgnueabihf/bin/arm-rockchip830-linux-uclibcgnueabihf-
    

    На платах LuckFox, включая Pico Mini, нет единой универсальной команды, которая бы просто вывела "список разрешенных периферийных устройств". Вместо этого используется комбинация команд для анализа Device Tree (дерева устройств) и состояния ядра Linux.

    Вот как это правильно сделать:

    1. Основной способ: анализ Device Tree

    Device Tree (DT) — это структура данных, которая описывает аппаратное обеспечение платы ядру Linux. Именно в ней "разрешаются" или "запрещаются" периферийные устройства.

    Самая важная команда:

    # cat /sys/firmware/devicetree/base/compatible
    

    Эта команда покажет модель вашей платы, которую ядро использует для загрузки правильной конфигурации. Для LuckFox Pico Mini вы увидите что-то вроде:

    $ adb shell
    [root@luckfox ]# cat /sys/firmware/devicetree/base/compatible
    rockchip,rv1103g-38x38-ipc-v10rockchip,rv1103
    

    Чтобы посмотреть, какие устройства "включены" в текущей Device Tree, используйте:

    a) Просмотр всех узлов (devices) в дереве:

    [root@luckfox ]# ls /proc/device-tree/
    #address-cells                 pwm@ff350010
    #size-cells                    pwm@ff350020
    acodec-sound                   pwm@ff350030
    acodec@ff480000                pwm@ff360000
    adc-keys                       pwm@ff360010
    aliases                        pwm@ff360020
    arm-debug@ff200000             pwm@ff360030
    arm-pmu                        pwm@ff490000
    chosen                         pwm@ff490010
    clock-controller@ff3a0000      pwm@ff490020
    clocks                         pwm@ff490030
    compatible                     restart-poweroff
    cpu0-opp-table                 rga@ff980000
    cpuinfo                        rkcif-dvp
    cpus                           rkcif-mipi-lvds
    csi2-dphy-hw@ff3e8000          rkcif-mipi-lvds-sditf
    csi2-dphy0                     rkcif-mipi-lvds1
    csi2-dphy1                     rkcif@ffa10000
    csi2-dphy2                     rkdvbm@ffa70000
    dht11_sensor                   rkisp-vir0
    dma-controller@ff420000        rkisp@ffa00000
    ethernet@ffa80000              rkvenc-pp@ffa60000
    fiq-debugger                   rkvenc@ffa50000
    i2c@ff310000                   rng@ff448000
    i2c@ff320000                   rockchip-amp
    i2c@ff450000                   rockchip-suspend
    i2c@ff460000                   rockchip-system-monitor
    i2c@ff470000                   rve@ffad0000
    i2s@ffae0000                   saradc@ff3c0000
    interrupt-controller@ff1f0000  serial-number
    interrupt-parent               serial@ff4a0000
    leds                           serial@ff4b0000
    memory                         serial@ff4c0000
    mipi-csi2-hw@ffa20000          serial@ff4d0000
    mipi-csi2-hw@ffa30000          serial@ff4e0000
    mipi0-csi2                     serial@ff4f0000
    mmc@ff9a0000                   spi@ff500000
    mmc@ffa90000                   spi@ff510000
    mmc@ffaa0000                   spi@ffac0000
    model                          sram@ff6c0000
    mpp-srv                        syscon@ff000000
    mpp-vcodec                     syscon@ff388000
    name                           syscon@ff538000
    npu@ff660000                   thermal-zones
    otp@ff3d0000                   timer
    pinctrl                        tsadc@ff3c8000
    power-management@ff300000      usb2-phy@ff3e0000
    psci                           usbdrd
    pvtm@ff240000                  vcc-1v8
    pvtm@ff390000                  vcc-3v3
    pwm@ff350000                   vdd-arm
    

    Это покажет список всех узлов высокого уровня (например, `gpio@fdd60000`, `serial@ff9c0000`). Это не названия периферии в привычном виде, а технические имена.

    b) Поиск по ключевым словам (самый практичный метод). Используйте `grep` для поиска упоминаний конкретных интерфейсов в смонтированном дереве устройств.

    Для UART (последовательный порт):

    # find /proc/device-tree/ -name "*uart*" | head -5
    

    Для I2C:

    # find /proc/device-tree/ -name "*i2c*" | head -5
    

    Для SPI:

    # find /proc/device-tree/ -name "*spi*" | head -5
    

    Для PWM:

    # find /proc/device-tree/ -name "*pwm*" | head -5
    

    Если команда возвращает пути к файлам (например, `/proc/device-tree/pwm@fdd70000`), значит, этот контроллер активирован в Device Tree.

    2. Проверка, загрузились ли драйверы устройств. Даже если устройство разрешено в DT, стоит проверить, увидело ли его ядро и загрузило ли драйвер.

    a) Просмотр списка зарегистрированных устройств:

    # ls /sys/devices/platform/
    

    Здесь вы увидите список платформенных устройств, которые были обнаружены ядром.

    b) Проверка конкретных интерфейсов.

    I2C: посмотреть, какие I2C адаптеры (шины) доступны в системе.

    # i2cdetect -l
    

    SPI: проверить, есть ли устройства SPI.

    # ls /dev/spidev*
    

    PWM: посмотреть, экспортированы ли каналы PWM.

    # ls /sys/class/pwm/
    

    GPIO: управление GPIO происходит через sysfs.

    # ls /sys/class/gpio/
    

    UART: последовательные порты.

    # ls /dev/ttyS*
    

    3. Прямой просмотр исходного файла Device Tree (если есть доступ). Самый полный, но и самый сложный способ — посмотреть исходный файл *.dts. Его обычно нет на самой плате, но он есть в SDK на вашем компьютере.

    Путь в SDK, на примере платы LuckFox Pico Mini:

    $ find . -name rv1103g-luckfox-pico-mini.dts
    ./sysdrv/source/kernel/arch/arm/boot/dts/rv1103g-luckfox-pico-mini.dts
    

    В этом файле вы можете найти все блоки вида:

    &pwm0 {
    status = "okay"; };

    Строка `status = "okay";` означает, что устройство разрешено. Если стоит `status = "disabled";` — устройство отключено.

    Краткий итог для быстрой проверки на плате LuckFox Pico Mini:

    1. UART: `ls /dev/ttyS*` (должен быть `ttyS0` и другие).
    2. I2C: `i2cdetect -l` (должна быть как минимум одна шина, например `i2c0`).
    3. SPI: `ls /dev/spidev*` (часто по умолчанию отключен для экономии энергии).
    4. PWM: `ls /sys/class/pwm/` (должны быть видны `pwmchip0`, `pwmchip4` и т.д.).

    Вывод: не существует команды наподобие `list-peripherals`. Чтобы узнать список разрешенных устройств, нужно анализировать дерево устройств через `/proc/device-tree/` и проверять состояние драйверов в `/sys/` и `/dev/`.

    Предположим, что на плате LuckFox Pico Mini есть директория /oem/spitest, и в ней вы тестируете программу в исполняемом файл spi, который для обновления нужно каждый раз перезаписывать. Тогда скрипт компиляции может выглядеть примерно так:

    #!/bin/bash

    # Удалим предыдущий результат компиляции: rm spi
    # Компиляция spi.c в исполняемый файл spi: arm-rockchip830-linux-uclibcgnueabihf-gcc spi.c -o spi
    # Удалить файл spi на целевом устройстве LuckFox Pico Mini: adb shell "rm /oem/spitest/spi"
    # Записать в то же место обновленную версию файла: adb push ./spi /oem/spitest

    В этом примере команда adb shell "rm /oem/spitest/spi" удалит исполняемый файл на плате LuckFox Pico Mini, а команда adb push ./spi /oem/spitest запишет его обновленную версию.

    Можно посмотреть и отфильтровать лог компиляции, но ИМХО самый простой и надежный способ - внести в файл *.dts намеренную ошибку. Можно временно переименовать измененный вами файл, либо вставить в него что-то недопустимое, например:

    ...
    /**********USB**********/
    &usbdrd_dwc3 {
    status = "okay";
    dr_mode = "peripheral"; };

    // Мне надо проверить, компилируется ли это место в файле DTS:
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa

    /**********SPI**********/
    /* SPI0_M0 */
    &spi0 {
    status = "okay";
    spidev@0 {
    spi-max-frequency = < 50000000>;
    }; }; ...

    Выполните команду ./build.sh, и если этот исправленный файл компилируется, то скрипт выдаст ошибку:

    ...
    Error: /home/user/luckfox-pico/sysdrv/source/kernel/arch/arm/boot/dts/rv1103g-luckfox-pico-mini.dts:
     61.1-45 syntax error
    FATAL ERROR: Unable to parse input tree
    make[4]: *** [scripts/Makefile.lib:381: arch/arm/boot/dts/rv1103g-luckfox-pico-mini.dtb] Error 1
    make[3]: *** [/home/user/luckfox-pico/sysdrv/source/kernel/Makefile:1464: rv1103g-luckfox-pico-mini.dtb]
     Error 2
    make[3]: *** Waiting for unfinished jobs....
      CALL    /home/user/luckfox-pico/sysdrv/source/kernel/scripts/atomic/check-atomics.sh
      CALL    /home/user/luckfox-pico/sysdrv/source/kernel/scripts/checksyscalls.sh
    make[2]: *** [arch/arm/Makefile:375: rv1103g-luckfox-pico-mini.img] Error 2
    make[2]: Leaving directory '/home/user/luckfox-pico/sysdrv/source/objs_kernel'
    make[1]: *** [Makefile:185: __sub-make] Error 2
    make[1]: Leaving directory '/home/user/luckfox-pico/sysdrv/source/kernel'
    make: *** [Makefile:486: kernel] Error 1
    make: Leaving directory '/home/user/luckfox-pico/sysdrv'
    [build.sh:error] Running build_kernel failed! [build.sh:error] exit code 2 from line 847:
    [build.sh:info] make kernel -C ${SDK_SYSDRV_DIR} $kernel_build_options KERNEL_DTS=${RK_KERNEL_DTS} KERNEL_CFG=${RK_KERNEL_DEFCONFIG} KERNEL_CFG_FRAGMENT=${RK_KERNEL_DEFCONFIG_FRAGMENT}

    При попытке перепрошить образ утилита upgrade_tool выдает сообщение, что не подключено устройство rockusb:

    $ upgrade_tool uf output/image/update.imgNo found any rockusb device,please plug device in!
    

    Проблема в том, что платка LuckFox Pico не введена в режим программирования. Для входа в режим программирования отключите кабель USB (тем самым обесточите плату), нажмите и удерживайте кнопку BOOT, и снова подключите кабель USB. После этого отпустите кнопку BOOT. Устройство готово к прошивке утилитой upgrade_tool.

    $ upgrade_tool uf output/image/update.img
    Loading firmware...
    Support Type:1106 FW Ver:0.0.00 FW Time:2025-09-23 15:00:24
    Loader ver:1.01 Loader Time:2025-09-23 14:56:47
    Start to upgrade firmware...
    Download Boot Start
    Download Boot Success
    Wait For Maskrom Start
    Wait For Maskrom Success
    Test Device Start
    Test Device Success
    Check Chip Start
    Check Chip Success
    Get FlashInfo Start
    Get FlashInfo Success
    Prepare IDB Start
    Prepare IDB Success
    Download IDB Start
    Download IDB Success
    Download Firmware Start
    Download Image... (100%)
    Download Firmware Success
    Upgrade firmware ok.
    

    Откройте файл luckfox-pico/config/dts_config (это символическая ссылка), отредактируйте:

    ...
    /**********ETH**********/
    &gmac {
    //status = "disabled";
    status = "okay"; }; ...

    После этого осталось перекомпилировать и перепрошить:

    $ ./build.sh
    $ upgrade_tool uf output/image/update.img
    

    [Временная настройка статического адреса (до перезагрузки)]

    С помощью команд ifconfig и route:

    # ifconfig eth0 192.168.1.100 netmask 255.255.255.0 up
    # route add default gw 192.168.1.1
    

    Или используя команду ip:

    # ip addr add 192.168.1.100/24 dev eth0
    # ip link set eth0 up
    # ip route add default via 192.168.1.1
    

    [Настройка через DHCP]

    Запуск DHCP клиента:

    # udhcpc -i eth0
    

    Или используя systemd (если доступен):

    # systemctl restart networking
    

    [Постоянная настройка]

    1. Добавьте в конфигурационный файл сетевых интерфейсов /etc/network/interfaces:

    # Для DHCP:
    iface eth0 inet dhcp

    # Или для статического IP: iface eth0 inet static
    address 192.168.1.100
    netmask 255.255.255.0
    gateway 192.168.1.1
    dns-nameservers 8.8.8.8 8.8.4.4

    Если выполнить следующую команду, то настройки применятся:

    # ifdown eth0 && ifup eth0
    

    Однако для того, чтобы эти настройки применялись при перезагрузке, сделайте следующее:

    2. Создайте файл S40eth0config в папке /etc/init.d:

    # touch /etc/init.d/S40eth0config
    

    3. Добавьте в него следующий текст:

    #!/bin/sh
    ### BEGIN INIT INFO
    # Provides: eth0config
    # Required-Start: networking
    # Required-Stop: networking
    # Default-Start: 2 3 4 5
    # Default-Stop: 0 1 6
    # Description: Ethernet configuration for LuckFox Pico
    ### END INIT INFO

    case "$1" in
    start)
    echo "Configuring eth0..."
    ifdown eth0
    sleep 2
    ifup eth0
    ;;
    stop)
    echo "Stopping eth0..."
    ifdown eth0
    ;;
    restart)
    $0 stop
    sleep 2
    $0 start
    ;;
    *)
    echo "Usage: $0 {start|stop|restart}"
    exit 1
    ;;
    esac

    exit 0

    4. Сделайте этот файл исполняемым:

    # chmod +x /etc/init.d/S40eth0config
    

    Теперь после перезагрузки будет запускаться скрипт S40eth0config, и настройки будут применяться.

    5. Настройте систему разрешения имен DNS:

    # echo "nameserver 8.8.8.8" > /etc/resolv.conf
    # echo "nameserver 1.1.1.1" >> /etc/resolv.conf
    # echo "nameserver 192.168.1.1" >> /etc/resolv.conf
    

    [Проверка конфигурации]

    Проверка IP адреса:

    # ip addr show eth0
    # ifconfig eth0
    

    Проверка маршрутизации:

    # ip route
    # route -n
    

    Проверка разрешения имен DNS:

    # ping 8.8.8.8
    # ping google.com
    

    См. также совет Q082 [2].

    Если вам нужно просто выполнить команды при загрузке, используйте /etc/rc.local.

    1. Создайте или отредактируйте файл:

    # vi /etc/rc.local
    

    2. Добавьте в него содержимое:

    #!/bin/sh
    sleep 10 # Ждем загрузки системы ifdown eth0 ifup eth0
    exit 0

    3. Сделайте /etc/rc.local исполняемым:

    # chmod +x /etc/rc.local
    

    В последней версии плат Luckfox Pico сервис SSH по умолчанию разрешен.

    [Buildroot]

    Login: root
    Password: luckfox
    Static IP: 172.32.0.93

    [Ubuntu]

    Login: pico
    Password: luckfox
    Static IP: 172.32.0.70

    Для подключения выполните команду ssh root@IP_адрес, например:

    $ ssh root@172.32.0.93
    

    После чего введите пароль luckfox.

    Подключение по Ethernet — это очень удобный способ работы с LuckFox Pico Mini, так как он обеспечивает стабильное и быстрое соединение.

    Вот пошаговая инструкция, как это сделать.

    [Предварительные требования]

    Сетевая инфраструктура: Ваш компьютер и плата LuckFox Pico Mini должны быть подключены к одной локальной сети (к одному маршрутизатору/свитчу).
    USB-C кабель (только для начальной настройки): Вам понадобится его для первоначальной настройки сети на плате.
    ADB и драйвера: На вашем компьютере должен быть установлен Android Debug Bridge (ADB). Обычно он идет в составе Android SDK Platform-Tools. Скачайте с официального сайта: https://developer.android.com/tools/releases/platform-tools
    Распакуйте архив и желательно добавьте путь к папке в переменную окружения PATH вашей системы.

    [Пошаговая инструкция]

    Шаг 1: Первоначальная настройка платы через USB

    Подключите плату LuckFox Pico Mini к компьютеру с помощью кабеля USB-C (подключите его к порту OTG на плате).
    Определите COM-порт (Windows) или устройство (Linux/macOS), к которому подключилась плата.
    Используйте терминальную программу (например, PuTTY на Windows, screen или minicom на Linux/macOS) для подключения к последовательному порту платы. Скорость соединения (Baud Rate): 1500000
    Войдите в систему. Логин по умолчанию: root, пароль обычно не требуется.

    Шаг 2: Настройка сети на плате LuckFox Pico Mini

    Теперь нужно настроить плату на получение IP-адреса по DHCP от вашего роутера или задать статический IP-адрес.

    Способ А: Настройка DHCP (рекомендуется для большинства случаев)

    Отредактируйте файл конфигурации сети. Часто для этого используется файл /etc/network/interfaces или команда udhcpc. Для LuckFox часто используется следующий метод:

    # Проверьте имя сетевого интерфейса. Обычно это eth0 или end0.
    ifconfig -a

    # Запустите DHCP-клиент для получения IP-адреса автоматически.
    # Если интерфейс eth0: udhcpc -i eth0

    # Или можно настроить автоматический запуск при загрузке, отредактировав файл: vi /etc/init.d/S99luckfox
    # Добавьте в него строку (перед exit 0): udhcpc -i eth0 &

    Способ Б: Настройка статического IP-адреса

    Если вы хотите задать фиксированный IP-адрес, отредактируйте файл конфигурации.

    # Пример редактирования файла /etc/network/interfaces
    vi /etc/network/interfaces
    # Добавьте или измените строки для интерфейса eth0: auto eth0 iface eth0 inet static address 192.168.1.100 # Желаемый IP-адрес netmask 255.255.255.0 # Маска подсети gateway 192.168.1.1 # IP-адрес вашего роутера dns-nameservers 8.8.8.8

    # После сохранения файла перезапустите сетевой сервис или плату. /etc/init.d/S40network restart
    # или reboot

    Шаг 3: Определение IP-адреса платы

    После настройки сети вам нужно узнать, какой IP-адрес получила плата.

    На плате выполните команду:

    ifconfig eth0

    Найдите строку inet addr:. Например, inet addr:192.168.1.50. Это IP-адрес вашей платы. Запишите этот адрес, он понадобится на следующем шаге.

    Шаг 4: Подключение ADB по TCP/IP

    Подключитесь к плате по USB и убедитесь, что ADB видит устройство через USB. На компьютере выполните в командной строке (или PowerShell/Terminal):

    adb devices

    Должен появиться список устройств. Если ваша плата подключена по USB, она там будет (возможно, с статусом unauthorized — нужно подтвердить разрешение на отладку на плате, если есть экран).

    Переведите ADB в режим TCP/IP на указанный порт (по умолчанию 5555):

    Выполните команду, где — это адрес, который вы узнали на Шаге 3.

    adb tcpip 5555

    В ответ вы должны увидеть сообщение: restarting in TCP mode port: 5555.
    Отключите USB-кабель от платы. Теперь связь будет осуществляться только по сети.

    Подключитесь к плате по сети с помощью ADB:

    adb connect :5555
    

    Например: adb connect 192.168.1.50:5555
    В случае успеха вы увидите: connected to 192.168.1.50:5555.

    Проверьте соединение:

    adb devices
    

    Теперь в списке должно отображаться ваше устройство по сетевому адресу, например: 192.168.1.50:5555 device

    Готово! Теперь вы можете использовать все стандартные команды ADB (adb shell, adb push, adb pull и т.д.), и они будут выполняться по Ethernet.

    [Важные замечания и советы]

    Автозапуск ADBD по сети: Чтобы не выполнять adb tcpip 5555 после каждой перезагрузки, вы можете настроить демон ADB (adbd) на плате на автоматический запуск в TCP-режиме. Для этого нужно от редактировать файл /init.usb.rc или аналогичный в прошивке и изменить строку запуска adbd на: start adbd --tcpip=5555 (внесение таких изменений может потребовать пересборки прошивки).
    Безопасность: Помните, что открытие порта 5555 для ADB делает ваше устройство доступным для подключения из локальной сети. Не делайте это в публичных или недоверенных сетях.
    Файерволл: Убедитесь, что на вашем компьютере брандмауэр не блокирует исходящие соединения на порт 5555.
    Если соединение не удается: Проверьте, можете ли вы "пропинговать" плату с компьютера: ping . Если пинг не проходит, проблема в сетевом подключении, а не в ADB.

    Теперь вы можете удобно работать с вашей LuckFox Pico Mini по быстрому и надежному Ethernet-соединению.

    Когда у вас подключено несколько устройств, нужно явно указывать, к какому из них обращаться. Вот как это делается.

    [Проверка списка подключенных устройств]

    Сначала всегда смотрите, какие устройства доступны:

    adb devices
    

    Пример вывода:

    List of devices attached
    192.168.1.50:5555    device
    emulator-5554 device
    ABCDEF012345 device

    [Способы указания устройства для adb shell]

    Способ А: Использование параметра -s (serial)

    Указываете серийный номер или IP-адрес устройства:

    # Для устройства с IP-адресом
    adb -s 192.168.1.50:5555 shell
    # Для USB-устройства по серийному номеру adb -s ABCDEF012345 shell
    # Для эмулятора adb -s emulator-5554 shell

    Способ Б: Использование параметра -d (device) / -e (emulator)

    Если у вас подключено только одно физическое устройство и один эмулятор:

    # Для единственного физического устройства
    adb -d shell
    # Для единственного эмулятора adb -e shell

    Способ В: Установка переменной окружения ANDROID_SERIAL

    Можно задать устройство по умолчанию на время сессии:

    # Windows (CMD)
    set ANDROID_SERIAL=192.168.1.50:5555 adb shell

    # Windows (PowerShell) $env:ANDROID_SERIAL="192.168.1.50:5555" adb shell

    # Linux/macOS export ANDROID_SERIAL=192.168.1.50:5555 adb shell

    [Практические примеры для LuckFox Pico Mini]

    Допустим, у вас подключены несколько устройств:

    # Проверяем устройства
    adb devices
    # List of devices attached
    # 192.168.1.50:5555 device # LuckFox Pico Mini
    # emulator-5554 device # Android Emulator
    # ABCDEF012345 device # Телефон по USB

    # Подключаемся к LuckFox Pico Mini по сети
    adb -s 192.168.1.50:5555 shell
    # Или если это единственное сетевое устройство adb -d shell
    # Выполняем команды на конкретном устройстве adb -s 192.168.1.50:5555 shell ls -la adb -s 192.168.1.50:5555 shell cat /proc/version

    [Полезные команды с указанием устройства]

    # Копирование файлов
    adb -s 192.168.1.50:5555 push local_file.txt /sdcard/
    adb -s 192.168.1.50:5555 pull /sdcard/file.txt ./
    # Установка приложения
    adb -s 192.168.1.50:5555 install app.apk
    # Просмотр логов
    adb -s 192.168.1.50:5555 logcat
    # Перезагрузка
    adb -s 192.168.1.50:5555 reboot
    

    [Создание алиасов для удобства (Linux/macOS)]

    Добавьте в ~/.bashrc или ~/.zshrc:

    # Алиас для быстрого подключения к LuckFox
    alias adb-luckfox='adb -s 192.168.1.50:5555'
    alias luckfox-shell='adb -s 192.168.1.50:5555 shell'

    # Использование: adb-luckfox shell luckfox-shell

    [Для Windows - создание пакетных файлов]

    Создайте файл luckfox-shell.bat:

    @echo off
    adb -s 192.168.1.50:5555 shell
    

    [Важные моменты]

    Порт обязателен: для сетевых устройств всегда указывайте порт (:5555).
    Регистр важен: серийные номера обычно чувствительны к регистру.
    Авторизация: убедитесь, что устройство авторизовано для отладки.
    Стабильность соединения: для сетевых устройств проверяйте, что соединение активно.

    Теперь вы можете легко работать с конкретным устройством, даже когда подключено несколько устройств одновременно!

    В этом примере будем управлять ножкой 34 платы LuckFox Pico Mini, которая подключена к светодиоду пользователя:

    LuckFox Pico Mini B user LED

    1. Экспорт вывода GPIO 34 в файловую систему sysfs:

    # echo 34 > /sys/class/gpio/export
    

    2. Настройка GPIO 34 на выход:

    # echo out > /sys/class/gpio/gpio34/direction
    

    3. Установим лог. 1 на выходе порта GPIO 34:

    # echo 1 > /sys/class/gpio/gpio34/value
    

    После этой команды пользовательский светодиод загорится.

    4. Установим лог. 1 на выходе порта GPIO 34:

    # echo 0 > /sys/class/gpio/gpio34/value
    

    После этой команды пользовательский светодиод погаснет.

    5. Если вывод GPIO 34 больше не нужен, то отмените его экспорт:

    # echo 34 > /sys/class/gpio/unexport
    

    Обратите внимание, что после отмены экспорта настройка вывода сохранится, т. е. вывод 34 останется выходом, просто вывод 34 больше не будет представлен в файловой системе sysfs.

    В menuconfig (как в Buildroot, так и в конфигурации ядра Linux) символы < >, < *> и < M> имеют специальное значение:

    [1. Значения символов в menuconfig]

    < > (пусто) - пакет/модуль не выбран для сборки
    < *> (звездочка) - пакет/модуль будет встроен в основную систему (statically linked)
    < M> (буква M) - пакет/модуль будет собран как отдельный загружаемый модуль (loadable module)

    [2. Разница между < *> и < M>]

    < *> - Статическая сборка:

    Пакет/модуль включается непосредственно в:

    - Ядро Linux (для драйверов)
    - Root filesystem (для приложений)
    - Не может быть выгружен во время работы
    - Занимает память постоянно

    < M> - Сборка как модуль:

    Пакет/модуль собирается отдельно:

    - Создается файл .ko (для ядра) или отдельный бинарник
    - Может быть загружен/выгружен во время работы (insmod/rmmod)
    - Экономит память, если модуль не используется постоянно

    [3. Примеры в контексте LuckFox Pico]

    Для драйверов ядра:

    Device Drivers -->
      Character devices -->
        [*] Serial drivers  ← Встроено в ядро
        < M> USB Serial Converter support  ← Собрано как модуль

    Для пакетов Buildroot:

    Target packages -->
      Hardware handling -->
        [*] i2c-tools  ← Встроено в rootfs
        < M> spidev-test  ← Собрано как отдельный пакет

    [4. Практическое применение для LuckFox Pico]

    Когда использовать < *>:

    # Критически важные драйверы
    [*] GPIO support
    [*] I2C support
    [*] SPI support

    # Базовые утилиты
    [*] busybox
    [*] base-files

    Когда использовать < M>:

    # Специфичные или редко используемые драйверы
    < M> USB WiFi drivers
    < M> Bluetooth support
    < M> Video4Linux drivers

    # Дополнительные утилиты
    < M> iperf3
    < M> tcpdump

    [5. Работа с модулями после сборки]

    Если вы собрали что-то как < M>:

    Загрузка модуля:

    # На устройстве LuckFox Pico
    insmod /lib/modules/5.10.110/extra/wifi_driver.ko

    Добавьте в /etc/modules:

    usbserial
    ftdi_sio

    Просмотр загруженных модулей:

    [root@luckfox ]# lsmod
    Module                  Size  Used by    Tainted: G  
    rve                    23436  0 
    rockit                225880  0 
    rknpu                  27019  0 
    mpp_vcodec            414257  1 rockit
    rga3                   90762  1 rockit
    phy_rockchip_csi2_dphy     9338  0 
    phy_rockchip_csi2_dphy_hw    10066  0 
    video_rkisp           171902  1 rockit
    video_rkcif           162117  1 rockit
    rk_dvbm                 5941  2 mpp_vcodec,video_rkisp
    

    [6. Особенности для Buildroot в сравнении с ядром Linux]

    В конфигурации ядра Linux:

    • < M> создает .ko файлы в /lib/modules/
    • Модули должны быть совместимы с версией ядра

    В конфигурации Buildroot:

    • < M> может создавать отдельные пакеты .ipk
    • Пакеты можно устанавливать/удалять отдельно

    [7. Рекомендации для LuckFox Pico Mini]

    Для экономии памяти (256MB):

    Используйте < M> для:

    - Дополнительных сетевых драйверов
    - Специализированных устройств
    - Отладочных утилит

    Используйте < *> для:

    - Базовых системных компонентов
    - Драйверов основной периферии
    - Часто используемых утилит

    [8. Как переключать между режимами]

    В menuconfig: пробел циклически переключает между < >, < *> и < M>

    Y - выбрать как < *>
    M - выбрать как < M>
    N - не выбирать < >

    [9. Пример конфигурации для LuckFox Pico]

    # Критически важное - всегда < *>
    [*] GPIO support
    [*] I2C support  
    [*] PWM support
    [*] Serial console

    # Периферия - можно как < M>
    < M> USB gadget support
    < M> WiFi support
    < M> Bluetooth

    # Файловые системы
    [*] EXT4 support
    < M> NTFS support
    < M> F2FS support

    [10. Проверка конфигурации]

    После сохранения конфигурации:

    # Просмотр выбранных опций
    grep "=y" .config     # Статические компоненты
    grep "=m" .config    # Модули

    # В ядре Linux
    make kernelrelease
    ls -la output/build/linux-*/modules.order

    Вывод: < M> позволяет экономить ресурсы на мини-платах типа LuckFox Pico, загружая дополнительные функции только когда они нужны.

    RKNN в контексте LuckFox Pico Mini — это ключевая технология для работы с искусственным интеллектом на этом устройстве.

    [Что такое RKNN?]

    RKNN (Rockchip Neural Network) — это программный стек и формат моделей ИИ, разработанный компанией Rockchip для своих процессоров. Это аналог Google Coral (.tflite) или NVIDIA TensorRT, но для чипов Rockchip.

    Архитектура RKNN:

    ┌─────────────────┐
    │   AI-модель     │  # TensorFlow, PyTorch, ONNX
    │   (исходная)    │
    └─────────────────┘
             ↓
    ┌─────────────────┐
    │   RKNN Toolkit  │  # Конвертация и оптимизация
    │   (на ПК)       │
    └─────────────────┘
             ↓
    ┌─────────────────┐
    │   RKNN-модель   │  # .rknn файл
    │   (.rknn)       │
    └─────────────────┘
             ↓
    ┌─────────────────┐
    │  LuckFox Pico   │  # Выполнение на NPU
    │   с RKNN API    │
    └─────────────────┘

    Компоненты RKNN экосистемы:

    1. RKNN Toolkit (на ПК)

    - Конвертирует модели в формат .rknn
    - Оптимизация для NPU Rockchip
    - Квантизация (снижение точности для ускорения)
    - Отладка и профилирование

    2. RKNN Runtime (на LuckFox Pico)

    - Библиотека для выполнения моделей
    - API для C, C++, Python
    - Управление памятью и ресурсами NPU

    3. RKNN Model (.rknn файл)

    - Оптимизированный формат модели
    - Содержит веса и граф вычислений
    - Готов к выполнению на NPU

    [Практическое использование на LuckFox Pico Mini]

    Типичный workflow (на языке Python):

    from rknnlite.api import RKNNLite

    # Загрузка модели: rknn = RKNNLite() ret = rknn.load_rknn('model.rknn') ret = rknn.init_runtime()

    # Выполнение inference: inputs = [...] # входные данные outputs = rknn.inference(inputs=[inputs])

    Поддерживаемые операции:

    - Свёртки (Convolutions)
    - Пулинг (Pooling)
    - Активации (ReLU, Sigmoid, etc.)
    - Полносвязные слои (Fully Connected)

    Преимущества RKNN на LuckFox Pico:

    1. Высокая производительность
    - Использование **NPU** (Neural Processing Unit)
    - До 0.5 TOPS на некоторых моделях Rockchip
    - Энергоэффективное выполнение

    2. Низкая задержка

    - Оптимизировано для embedded-устройств
    - Минимальное использование CPU

    3. Поддержка популярных фреймворков

    - TensorFlow (.pb, .tflite)
    - PyTorch (.pt через ONNX)
    - ONNX (.onnx)
    - Caffe (.caffemodel)

    Примеры применений на LuckFox Pico Mini:

    # Распознавание объектов
    ./object_detection model.rknn image.jpg

    # Классификация изображений
    ./classification model.rknn image.jpg

    # Сегментация
    ./segmentation model.rknn image.jpg

    Ограничения:

    - Поддержка не всех операторов нейросетей
    - Квантизация может снижать точность
    - Память ограничена размерами NPU
    - Тепловыделение при интенсивной работе

    Типичный процесс разработки:

    1. Обучение модели на ПК (TensorFlow/PyTorch)
    2. Конвертация в RKNN через RKNN Toolkit
    3. Развертывание на LuckFox Pico
    4. Интеграция в приложение через RKNN API

    Полезные команды:

    # Проверка поддержки NPU
    cat /proc/device-tree/model

    # Загрузка драйверов RKNN
    modprobe rknpu

    # Примеры из репозитория LuckFox
    git clone https://github.com/LuckfoxTech/luckfox-pico

    В итоге: RKNN — это мост между стандартными фреймворками машинного обучения и аппаратным ускорением на чипах Rockchip, что делает LuckFox Pico Mini мощным устройством для embedded AI приложений.

    См. также:

    RKNN Model Inference Test site:wiki.luckfox.com.
    Guide to Using RKNN Instances site:wiki.luckfox.com.
    Q041. Что такое RKMPI?

    RKMPI в контексте LuckFox Pico Mini — это мультимедийный программный интерфейс (Media Process Interface) от Rockchip для работы с аппаратными блоками медиасистемы.

    [Что такое RKMPI?]

    RKMPI (Rockchip Media Process Interface) — это программный SDK, предоставляющий API для доступа к аппаратным мультимедийным возможностям процессоров Rockchip, включая:

    - Видео кодирование/декодирование (VPU - Video Processing Unit)
    - Обработка изображений (ISP - Image Signal Processor)
    - Аудио обработка
    - Вывод на экран
    - Работа с памятью

    Архитектура RKMPI:

    ┌────────────────────────────────────┐
    │       Приложение пользователя      │
    ├────────────────────────────────────┤
    │             RKMPI API              │
    ├────────────────────────────────────┤
    │   Драйверы аппаратных блоков:      │
    │  • VPU (кодирование/декодирование) │
    │  • ISP (обработка изображений)     │
    │  • VOP (дисплей)                   │
    │  • RGA (графический ускоритель)    │
    ├────────────────────────────────────┤
    │        Аппаратное обеспечение      │
    └────────────────────────────────────┘

    [Основные компоненты RKMPI]

    1. Видео кодирование/декодирование (VPU)

    - H.264/H.265 кодирование до 1080p@30fps
    - H.264/H.265 декодирование
    - MJPEG кодирование/декодирование
    - Низкая задержка обработки

    2. Обработка изображений (ISP)

    - Дебейеризация RAW-данных с камеры
    - Коррекция цвета, контраста, резкости
    - Шумоподавление (2D/3D NR)
    - Автоматические настройки (AWB, AE, AF)

    3. Графический ускоритель (RGA)

    - Масштабирование изображений
    - Поворот и отражение
    - Конвертация цветовых пространств
    - Наложение (blending) изображений

    4. Дисплейный вывод (VOP)

    - Вывод на HDMI/LCD
    - Композиция слоев
    - Гамма-коррекция

    [Практическое использование на LuckFox Pico Mini]

    Пример инициализации VPU (язык C):

    #include < rockchip/rk_mpi.h>

    // Инициализация системы RK_MPI_SYS_Init();

    // Создание VPU для кодирования VENC_CHN_ATTR_S venc_attr; venc_attr.stVencAttr.enType = RK_VIDEO_ID_AVC; // H.264 RK_MPI_VENC_CreateChn(0, &venc_attr);

    Пример работы с камерой через ISP:

    // Настройка ISP
    ISP_DEV isp_dev = 0;
    RK_MPI_ISP_SetContrast(isp_dev, 50);
    RK_MPI_ISP_SetSharpness(isp_dev, 60);

    // Захват кадра VIDEO_FRAME_INFO_S stFrame; RK_MPI_VI_GetChnFrame(0, 0, &stFrame, -1);

    Пример работы с RGA:

    // Масштабирование изображения
    RGA_ATTR_S stRgaAttr;
    stRgaAttr.bEnBufPool = RK_TRUE;
    stRgaAttr.stImgIn.u32X = 1920;
    stRgaAttr.stImgIn.u32Y = 1080;
    stRgaAttr.stImgOut.u32X = 640;
    stRgaAttr.stImgOut.u32Y = 360;
    RK_MPI_RGA_CreateChn(0, &stRgaAttr);
    

    [Типовые сценарии использования]

    1. Видеонаблюдение

    Захват с камеры → ISP обработка → H.264 кодирование → Сетевая передача:
    VI → ISP → VPU (Encoder) → Network

    2. Видеопроигрыватель

    Сетевая передача → H.264 декодирование → Вывод на дисплей:
    Network → VPU (Decoder) → VOP → HDMI/LCD

    3. Компьютерное зрение

    Захват с камеры → ISP → RGA (масштабирование) → AI обработка:
    VI → ISP → RGA → RKNN (AI inference)

    [Преимущества RKMPI]

    1. Аппаратное ускорение:

    - Низкое энергопотребление
    - Высокая производительность
    - Минимальная загрузка CPU

    2. Низкая задержка

    - Обработка в реальном времени
    - Прямая передача между блоками (zero-copy)

    3. Полный контроль

    - Тонкая настройка параметров
    - Доступ к RAW данным

    Ограничения:

    - Сложность программирования
    - Документация преимущественно на китайском
    - Требует глубокого понимания media pipeline

    [Полезные утилиты]

    Тест кодирования:

    # rkmpp_venc_test

    Тест декодирования:

    # rkmpp_vdec_test

    Информация о системе:

    # cat /proc/rk_camship

    Проверка аппаратных блоков:

    # ls /dev/ | grep -E "vpu|rga|isp"

    [Сравнение с другими технологиями]

    ТехнологияНазначениеУровень
    RKMPI Мультимедиа (видео/аудио) Низкоуровневый
    RKNN Нейронные сети (AI) Высокоуровневый
    GStreamer Мультимедиа пайплайны Прикладной
    OpenCV Компьютерное зрение Библиотека

    В итоге: RKMPI — это фундаментальный инструмент для создания высокопроизводительных мультимедийных приложений на LuckFox Pico Mini, обеспечивающий прямой доступ к аппаратным возможностям чипа Rockchip.

    См. также:

    Q040. Что такое RKNN?
    RKMPI Instance User Guide site:wiki.luckfox.com.

    OpenCV (Open Source Computer Vision Library) — это открытая библиотека компьютерного зрения, одна из самых популярных и мощных в своей области.

    [Что такое OpenCV?]

    OpenCV — это кроссплатформенная библиотека, содержащая более 2500 оптимизированных алгоритмов для:

    - Компьютерного зрения
    - Обработки изображений
    - Машинного обучения
    - Анализа видео

    Основные возможности OpenCV:

    1. Обработка изображений

    # python
    import cv2
    import numpy as np

    # Загрузка изображения img = cv2.imread('image.jpg')

    # Изменение размера resized = cv2.resize(img, (640, 480))

    # Размытие blurred = cv2.GaussianBlur(img, (5, 5), 0)

    # Обнаружение краев edges = cv2.Canny(img, 100, 200)

    # Пороговая обработка gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) _, threshold = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)

    2. Работа с видеопотоком и камерами

    # python
    # Захват видео с камеры cap = cv2.VideoCapture(0)

    while True: ret, frame = cap.read() if not ret: break # Обработка кадра gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) cv2.imshow('Camera', gray_frame) if cv2.waitKey(1) & 0xFF == ord('q'): break
    cap.release() cv2.destroyAllWindows()

    3. Обнаружение объектов и лиц

    # python
    # Загрузка классификатора для лиц face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

    # Обнаружение лиц faces = face_cascade.detectMultiScale(gray, 1.1, 4)

    # Рисование прямоугольников вокруг лиц
    for (x, y, w, h) in faces: cv2.rectangle(img, (x, y), (x+w, y+h), (255, 0, 0), 2)

    4. Машинное обучение

    # python
    # K-mean кластеризация criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) _, labels, centers = cv2.kmeans(data, 3, None, criteria, 10, cv2.KMEANS_RANDOM_CENTERS)

    # SVM классификатор svm = cv2.ml.SVM_create() svm.setType(cv2.ml.SVM_C_SVC) svm.setKernel(cv2.ml.SVM_LINEAR) svm.train(training_data, cv2.ml.ROW_SAMPLE, labels)

    Ключевые модули OpenCV:

    МодульНазначение
    core Основные структуры данных и функции
    imgproc Обработка изображений
    video Анализ видео и трекинг
    calib3d Калибровка камер и 3D реконструкция
    features2d Детекторы и дескрипторы признаков
    objdetect Обнаружение объектов
    ml Машинное обучение
    dnn Глубокие нейронные сети

    [Установка OpenCV]

    Для Python:

    # Базовая установка
    $ pip install opencv-python
    # Полная установка (с contrib модулями) $ pip install opencv-contrib-python

    Для Ubuntu:

    # Установка из репозитория
    $ sudo apt update
    $ sudo apt install python3-opencv
    # Или компиляция из исходников
    $ sudo apt install build-essential cmake git libgtk2.0-dev pkg-config \
     libavcodec-dev libavformat-dev libswscale-dev
    $ git clone https://github.com/opencv/opencv.git
    $ cd opencv && mkdir build && cd build
    $ cmake .. && make -j4 && sudo make install
    

    [Практические примеры использования]

    1. Распознавание QR-кодов:

    # python
    detector = cv2.QRCodeDetector()
    data, bbox, _ = detector.detectAndDecode(img)
    if data: print("QR Code data:", data)

    2. Детектирование движения:

    # python
    # Фоновая субтракция fgbg = cv2.createBackgroundSubtractorMOG2()

    while True: ret, frame = cap.read() fgmask = fgbg.apply(frame) # Анализ маски движения

    3. Калибровка камеры:

    # python
    # Поиск шахматной доски ret, corners = cv2.findChessboardCorners(gray, (9, 6), None)
    if ret: cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1], None, None)

    [Преимущества OpenCV]

    1. Кроссплатформенность

    - Windows, Linux, macOS, Android, iOS
    - Embedded системы (Raspberry Pi, LuckFox Pico)

    2. Поддержка многих языков программирования

    - C++, Python, Java, JavaScript
    - Интерфейсы для MATLAB, Ruby

    3. Высокая производительность

    - Оптимизированные алгоритмы
    - Поддержка GPU (CUDA, OpenCL)
    - Векторизация инструкций

    4. Активное сообщество

    - Регулярные обновления
    - Большая база примеров
    - Подробная документация

    [OpenCV в embedded-системах (например, LuckFox Pico)]

    # python
    # Пример для embedded устройства
    import cv2

    # Использование аппаратного ускорения cv2.setUseOptimized(True)

    # Работа с камерой MIPI cap = cv2.VideoCapture(0) # CSI камера

    # Экономная обработка для маломощных устройств small_frame = cv2.resize(frame, (320, 240)) gray = cv2.cvtColor(small_frame, cv2.COLOR_BGR2GRAY)

    Типовые области применения:

    - Робототехника (навигация, SLAM)
    - Медицина (анализ снимков)
    - Безопасность (распознавание лиц, детектирование движения)
    - Автомобильная промышленность (ADAS)
    - Дополненная реальность
    - Промышленный контроль качества

    В итоге: OpenCV — это "швейцарский нож" для разработчиков в области компьютерного зрения, предоставляющий готовые, оптимизированные алгоритмы для самых разнообразных задач обработки изображений и видео.

    Например:

    $ adb devices
    List of devices attached
    359238bf91d2b5a8     device
    192.168.1.100:5555   device
    

    Чтобы подключиться к нужному устройству из этого списка, используйте опцию -s, например:

    $ adb -s 192.168.1.100:5555 shell
    [root@luckfox ]#
    

    Чтобы отключить устройство, используйте adb disconnect:

    $ adb disconnect 192.168.1.100:5555
    disconnected 192.168.1.100:5555
    $ adb devices
    List of devices attached
    359238bf91d2b5a8     device
    

    Чтобы снова подключить устройство, используйте команду adb connect:

    $ adb connect 192.168.1.100:5555
    connected to 192.168.1.100:5555
    $ adb devices
    List of devices attached
    359238bf91d2b5a8     device
    192.168.1.100:5555   device
    

    Отключение всех сетевых устройств, используется adb disconnect без параметров (отключатся только сетевые устройства, USB-устройство останется подключенным):

    $ adb disconnect
    disconnected everything
    $ adb devices
    List of devices attached
    359238bf91d2b5a8     device
    

    Полная перезагрузка ADB сервера (если нужно):

    $ adb kill-server
    $ adb start-server
    

    Такая необходимость может возникнуть, если по какой-то причине подключиться через USB/ADB или Ethernet/SSH не представляется возможным. Например, вы собираетесь пересобрать Buildroot в конфигурации, когда порт USB будет использоваться как хост USB.

    [Что понадобится]

    1. Переходничок USB - TTL UART с уровнями логики 3.3V (на чипе CP2102, CH340, FT232 и т. п.).
    2. Программа терминала на компьютере хоста - putty или minicom, или что-то подобное.
    3. Плата LuckFox Pico.

    [Как определить сигналы RX и TX]

    1. Просмотрите список портов tty командой:

    [root@luckfox ]# ls -1 /dev | grep tty
    

    Выведется примерно вот такой список:

    tty
    tty0
    tty1
    tty10
    tty11
    ..
    tty8
    tty9
    ttyFIQ0
    

    Ищите в этом списке устройства ttyS*, ttyAMA*, ttyFIQ*. Обычно для подключения к консоли используют ttyS0 и ttyFIQ0.

    Также можно просмотреть список загрузочных сообщений командой:

    [root@luckfox ]# cat /proc/cmdline
    user_debug=31
    storagemedia=mtd
    androidboot.storagemedia=mtd
    androidboot.mode=normal  rootwait
    earlycon=uart8250,mmio32,0xff4c0000
    console=ttyFIQ0
    root=ubi0:rootfs
    snd_soc_core.prealloc_buffer_size_kbytes=16
    coherent_pool=0
    mtdparts=spi-nand0:256K(env),256K@256K(idblock),512K(uboot),4M(boot),
     30M(oem),6M(userdata),85M(rootfs)
    ubi.mtd=6 rootfstype=ubifs
    rk_dma_heap_cma=24M
    androidboot.fwver=uboot-09/23/2025
    

    В этом примере видно, что для консоли используется ttyFIQ0.

    2. Запустите в терминале команду:

    [root@luckfox ]# echo "hello" > /dev/ttyFIQ0
    

    И с помощью осциллографа смотрите, на каком выводе появится сигнал передачи UART. На моей платке LuckFox Pico Mini B это оказался контакт 4 (порт 42, GPIO1_B2_d, UART2_TX_M1).

    UART2 TX M1 signal

    Это и будет сигнал TX. По длительности минимального бита видно, что это скорость 115200 бод. Соответственно сигнал RX будет на контакте 5 (порт 43, GPIO1_B3_u, UART2_RX_M1).

    3. С помощью программы luckfox-config можно ознакомиться с текущей настройкой выводов:

    [root@luckfox root]# luckfox-config show
                                    Luckfox_Pico_MiniA/B
                                         + -USB- +
              -               -     VBUS |       | 1V8      -             -
              -               -      GND |       | GND      -             -
              -               -      3V3 |       | GPIO4_C1 - SARADC_M1   -
              - FIQtty_TX     - GPIO1_B2 |       | GPIO4_C0 - SARADC_M0   -
              - FIQtty_RX     - GPIO1_B3 |       | GPIO0_A4 -             - PWM1_M0
     PWM2_M2  - SPI0_M0_CS0   - GPIO1_C0 |       | GPIO1_C7 -             - PWM11_M1
     PWM4_M2  - SPI0_M0_CLK   - GPIO1_C1 |       | GPIO1_C6 -             - PWM10_M1
     PWM5_M2  - SPI0_M0_MOSI  - GPIO1_C2 |       | GPIO1_D3 - I2C3_M1_SCL - PWM11_M2
     PWM6_M2  - SPI0_M0_MISO  - GPIO1_C3 |       | GPIO1_D2 - I2C3_M1_SDA - PWM0_M1
     PWM8_M1  - UART4_M1_RX   - GPIO1_C4 |       | GPIO1_D1 - UART3_M1_RX - PWM10_M2
     PWM9_M1  - UART4_M1_TX   - GPIO1_C5 |       | GPIO1_D0 - UART3_M1_TX - PWM3_M2
                                         + - + - +
    

    [Подключение к консоли]

    Подключите переходничок адаптера USB - TTL UART к сигналам TX и RX платы:

    LuckFox Pico Mini B    USB-UART адаптер
    UART2_TX_M1         →  RX
    UART2_RX_M1         ←  TX
    GND                    GND

    Настройте подключение к порту адаптера USB - TTL UART с помощью программы терминала на скорости 115200, 8 бит данных, 1 стоп-бит, без контроля четности. Можно использовать различные программы терминала.

    Windows:

    Putty
    Tera Term
    SecureCRT 

    Linux/macOS:

    Minicom
    Screen
    Picocom
    Putty

    Пример подключения с помощью minicom (логин root, пароль luckfox):

    $ minicom -D /dev/ttyUSB1
    Welcome to minicom 2.9
    OPTIONS: I18n Port /dev/ttyUSB1, 09:40:33
    Press CTRL-A Z for help on special keys

    Welcome to luckfox pico luckfox login: root Password: [root@luckfox root]#

    ~/luckfox-pico$ upgrade_tool ul output/image/update.img 
    Loading loader...
    Support Type:RK1106 Loader ver:1.01 Loader Time:2025-09-30 13:58:34
    Start to upgrade loader...
    Download Boot Start
    Download Boot Success
    Wait For Maskrom Start
    Wait For Maskrom Success
    Test Device Start
    Test Device Success
    Check Chip Start
    Check Chip Success
    Get FlashInfo Start
    Get FlashInfo Success
    Prepare IDB Start
    Prepare IDB Success
    Download IDB Start
    Download IDB Success
    Upgrade loader ok.
    

    Проблема в том, что upgrade_tool загрузил только загрузчик (loader), но не саму прошивку.

    Что произошло:

    Загрузчик успешно загружен в RAM.
    Утилита перевела устройство в режим Maskrom.
    Утилита проверила чип и информацию о flash-памяти.
    Но не записала основную прошивку.

    Проблема в том, что была ошибочно указана опция ul (upgrade loader) вместо uf (upgrade firmware).

    Решения:

    1. Используйте параметр uf для полной прошивки:

    $ upgrade_tool uf output/image/update.img
    

    2. Или используйте для принудительной записи:

    $ upgrade_tool uf output/image/update.img
    

    3. Проверьте режим устройства:

    $ upgrade_tool pl
    

    Убедитесь, что устройство в режиме Loader или Maskrom.

    4. Альтернативные команды: используйте RKDevTool (графическая утилита) или rkdeveloptool.

    $ rkdeveloptool db output/image/update.img
    $ rkdeveloptool wl 0 output/image/update.img
    $ rkdeveloptool rd
    

    Порядок действий:

    - Переведите устройство в режим Maskrom (зажать кнопку Boot и нажать Reset или выдернуть и снова вставить кабель).
    - Выполните: upgrade_tool uf output/image/update.img.
    - Дождитесь полного завершения процесса.

    Ключевое отличие: ul загружает только loader, uf прошивает всю систему.

    [Начальная компиляция по умолчанию]

    Перейдите в каталог SDK:

    $ cd ~/luckfox-pico
    

    Начинать надо с выбора платы:

    $ ./build.sh lunch
    

    Теперь можно компилировать:

    $ ./build.sh
    

    После этого можно прошить память SPI FLASH командой:

    $ upgrade_tool uf output/image/update.img
    

    [Конфигурирование пакетов и ядра Buildroot]

    Сборка пакетов и приложений конфигурируется командой:

    $ ./build.sh buildrootconfig
    

    Сборка ядра конфигурируется командой:

    $ ./build.sh kernelconfig
    

    Подсказка по командам:

    $ ./build.sh --help
    Usage: build.sh [OPTIONS]
    Available options:
    lunch              -Select Board Configure
    env                -build env
    meta               -build meta (optional)
    uboot              -build uboot
    kernel             -build kernel
    rootfs             -build rootfs
    driver             -build kernel's drivers
    sysdrv             -build uboot, kernel, rootfs
    media              -build rockchip media libraries
    app                -build app
    recovery           -build recovery
    tool               -build tool
    updateimg          -build update image
    unpackimg          -unpack update image
    factory            -build factory image
    all                -build uboot, kernel, rootfs, recovery image
    allsave            -build all & firmware & save
    clean -clean all clean uboot -clean uboot clean kernel -clean kernel clean driver -clean driver clean rootfs -clean rootfs clean sysdrv -clean uboot/kernel/rootfs clean media -clean rockchip media libraries clean app -clean app clean recovery -clean recovery
    firmware -pack all the image we need to boot up system ota -pack update_ota.tar save -save images, patches, commands used to debug check -check the environment of building info -see the current board building information
    buildrootconfig -config b # EMMCuildroot and save defconfig kernelconfig -config kernel and save defconfig
    Default option is 'allsave'.

    По умолчанию интерфейс USB платки LuckFox Pico в сборке Buildroot работает в режиме устройства USB. Это сделано, в частности, чтобы при подключении через USB к компьютеру можно было подключиться к LuckFox Pico командой adb shell.

    $ adb devices
    * daemon not running; starting now at tcp:5037
    * daemon started successfully
    List of devices attached
    359238bf91d2b5a8 device
    

    Переконфигурировать USB на работу в режиме хоста можно с помощью команды luckfox-config в терминале Buildroot и последующей перезагрузкой.

    Примечание: если вы запустите Buildroot, когда USB работает в режиме хоста, нельзя будет подключаться через adb к плате. Восстановить работу adb можно через подключение Ethernet, если оно у вас настроено, см. Q036. Также можно получить доступ к консоли терминала через UART, см. Q044.

    Итак, как переконфигурировать сборку Buildroot, чтобы интерфейс USB работал в режиме хоста. Подключитесь к терминалу Buildroot, и введите команду:

    [root@luckfox root]# luckfox-config
    

    Откроется меню конфигурации, войдите в раздел Advanced Options -> USB.

    luckfox config USB host

    Выберите вариант 2 host, нажмите пробел, это соответствует нажатию кнопки OK для подтверждения выбора. Появится окно о необходимости перезагрузки для того, чтобы изменения вступили в силу.

    Нажмите еще раз пробел (OK), и несколько раз Esc для выхода из меню конфигурации. Выполните команду перезагрузки:

    [root@luckfox root]# reboot
    

    Чтоб можно было подключать устройства USB, необходимо подать питание +5V на контакт 1 (VBUS) платки LuckFox Pico:

    Pico Mini VBUS

    Теперь платка LuckFox Pico будет обнаруживать подключаемые к ней устройства. Вам понадобится USB-хаб с коннектором USB Type-C, например T-809A, T-809B, или любой другой:

    T 809A USB hub

    При подключении хаба T-809A в консоли Buildroot появится сообщение:

    [root@luckfox root]# [  187.785069] usb 1-1: new high-speed USB device
     number 2 using xhci-hcd                                                    
    [  187.990667] hub 1-1:1.0: USB hub found                                
    [  187.991568] hub 1-1:1.0: 4 ports detected
    

    v4l_id - это вспомогательная утилита в Linux-системах, которая играет важную роль в автоматическом определении и настройке видеоустройств, которая:

    - Принадлежит пакету udev (система управления устройствами).
    - Специализируется на идентификации Video4Linux (V4L/V4L2) устройств.
    - Вызывается автоматически демоном udevd при обнаружении нового видеоустройства.

    [Основные функции v4l_id]

    1. Сбор информации о видеоустройстве:

    - Определяет возможности устройства (форматы, разрешения)
    - Читает технические характеристики через V4L2 API
    - Получает идентификаторы устройства (модель, производитель)

    2. Создание симлинков в /dev/v4l/:

       /dev/v4l/by-id/usb-VIDEO_DEVICE_NAME-video-index0
       /dev/v4l/by-path/platform-xxxx.usb-usb-0:1.2:1.0-video-index0

    Это позволяет обращаться к устройствам по постоянным именам, а не по меняющимся /dev/video0, /dev/video1 и т.д.

    Почему v4l_id отсутствует в вашей Buildroot?

    В конфигурации Buildroot для LuckFox Pico Mini B часто включают только минимальный набор компонентов для экономии места. Утилита v4l_id может быть исключена как "необязательная".

    Как добавить v4l_id в Buildroot?

    Способ 1: Через menuconfig или buildrootconfig.

    $ cd ~/luckfox-pico/sysdrv/source/buildroot/buildroot-2023.02.6
    $ make menuconfig
    

    Или:

    $ cd ~/luckfox-pico
    $ ./build.sh buildrootconfig
    

    Перейдите в разделы:

    Target packages 
      → Hardware handling 
        → udev 
          → [*] Enable udev support
          → [*] Install udev rules for V4L devices

    Способ 2: Проверка существующих пакетов

    Некоторые пакеты автоматически включают v4l_id:

    $ make menuconfig
    

    И проверьте:

    Target packages 
      → Multimedia 
        → [*] v4l2-utils

    Что происходит без v4l_id?

    - Устройства создаются: /dev/video0, /dev/video1 и т. д.
    - Работоспособность: jсновные функции видео работают нормально
    - Недостатки:
      - Нет удобных симлинков в `/dev/v4l/by-*`
      - В логах появляются ошибки `failed to execute '/lib/udev/v4l_id'`
      - Автоматическая классификация устройств не работает

    Проверка наличия v4l_id, установлена ли утилита:

    # which v4l_id
    # ls -la /lib/udev/v4l_id
    

    Проверить наличие симлинков (которые создает v4l_id):

    # ls -la /dev/v4l/by-id/
    # ls -la /dev/v4l/by-path/
    

    Практическое значение для LuckFox Pico. На платах типа LuckFox Pico, где часто подключаются USB-камеры и устройства видеозахвата, наличие v4l_id полезно для:

    1. Стабильности имен - если у вас несколько камер, их порядок в /dev/video* может меняться при перезагрузке.
    2. Автоматизации - скрипты могут надежно обращаться к устройствам по постоянным именам.
    3. Отладки - проще идентифицировать конкретное устройство в системе.

    v4l_id - это не критически важный компонент, но очень полезная утилита для правильной организации видеоустройств в системе. Ее отсутствие не мешает базовой работе с камерами, но создает неудобства и сообщения об ошибках в логах.

    eudev - это реализация системы udev (userspace device manager), специально разработанная для встраиваемых систем и дистрибутивов вроде Buildroot. Утилита eudev (Embedded udev) заменяет оригинальную утилиту systemd-udev от Red Hat, которая:

    - Работает независимо от systemd
    - Оптимизирована для встраиваемых систем с ограниченными ресурсами
    - Обеспечивает динамическое управление устройствами в `/dev`

    [Основные функции eudev в Buildroot]

    1. Динамическое создание узлов устройств в /dev. Без eudev пришлось бы создавать все устройства статически (через `mknod`), что неэффективно для систем с подключаемыми устройствами.

    2. Автоматическая загрузка драйверов. При подключении устройства eudev определяет, какой драйвер нужен, и загружает его.

    3. Создание симлинков и персистентных имен. Пример того, что создает eudev:

    /dev/disk/by-id/usb-SanDisk_Cruzer_Blade_000000000000-0:0
    /dev/serial/by-id/usb-FTDI_FT232R_USB_UART_A900cePY-if00-port0
    /dev/v4l/by-id/usb-VIDEO_DEVICE_NAME-video-index0

    4. Запуск скриптов при обнаружении устройств. Eudev выполняет правила из `/etc/udev/rules.d/` при подключении/отключении устройств.

    [Конфигурация eudev в Buildroot для LuckFox Pico]

    Включение eudev:

    $ make menuconfig
    

    System configuration 
      → /dev management (Dynamic using eudev) 
      → [*] eudev (Dynamic using eudev)

    Дополнительные опции:

    Target packages 
      → Hardware handling 
        → [*] eudev
        → [*] Enable udev support
        → [*] Install udev rules for V4L devices    # включает v4l_id
        → [*] Install udev rules for devpts

    Почему eudev важен для LuckFox Pico?

    Для USB-устройств (камеры, флешки, последовательные порты):

    - Автоматическое создание /dev/video0, /dev/sda1, /dev/ttyUSB0
    - Стабильные имена через симлинки в /dev/disk/by-id/, /de/serial/by-id/

    Для встроенных периферийных устройств:

    - GPIO, I2C, SPI устройства
    - Аудиоустройства
    - Сетевые интерфейсы

    Что происходит без eudev? Без eudev в Buildroot обычно используются:

    1. Статический /dev - все устройства создаются при компиляции
    2. mdev - более легковесная альтернатива (устаревшая)
    3. devtmpfs - базовая функциональность без сложных правил

    [Практический пример с USB-камерой]

     С eudev при подключении камеры автоматически:

    [  561.687738] uvcvideo: Found UVC 1.00 device AV TO USB2.0

    - Создается /dev/video0
    - Создаются симлинки: /dev/v4l/by-id/usb-AV_TO_USB2.0-video-index0
    - Загружается драйвер uvcvideo

    Без eudev:

    - Устройство появится в /dev/videoX (если драйвер загружен)
    - Но не будет симлинков и дополнительной метаинформации
    - Могут отсутствовать автоматические действия при подключении

    Структура каталогов eudev

    /etc/udev/rules.d/          # Пользовательские правила
    /lib/udev/rules.d/          # Системные правила
    /lib/udev/                  # Вспомогательные утилиты
    ├── v4l_id                  # Для видеоустройств
    ├── ata_id                  # Для ATA устройств
    └── scsi_id                 # Для SCSI устройств

    [Отладка eudev]

    Просмотр событий eudev в реальном времени:

    [root@luckfox root]# udevadm monitor
    

    Информация об устройстве:

    [root@luckfox root]# udevadm info /dev/video0
    P: /devices/platform/usbdrd/ffb00000.usb/xhci-hcd.0.auto/usb1/1-1/1-1.4/
     1-1.4:1.0/video4linux/video21
    N: video21
    S: v4l/by-id/usb-MACROSILICON_AV_TO_USB2.0_20200909-video-index0
    S: v4l/by-path/platform-xhci-hcd.0.auto-usb-0:1.4:1.0-video-index0
    E: DEVLINKS=/dev/v4l/by-id/usb-MACROSILICON_AV_TO_USB2.0_20200909-video-index0
    /dev/v4l/by-path/platform-xhci-hcd.0.auto-usb-0:1.4:1.0-video-index0 E: DEVNAME=/dev/video21 E: DEVPATH=/devices/platform/usbdrd/ffb00000.usb/xhci-hcd.0.auto/usb1/ 1-1/1-1.4/1-1.4:1.0/video4linux/video21 E: ID_BUS=usb E: ID_MODEL=AV_TO_USB2.0 E: ID_MODEL_ENC=AV\x20TO\x20USB2.0 E: ID_MODEL_ID=0021 E: ID_PATH=platform-xhci-hcd.0.auto-usb-0:1.4:1.0 E: ID_PATH_TAG=platform-xhci-hcd_0_auto-usb-0_1_4_1_0 E: ID_REVISION=0121 E: ID_SERIAL=MACROSILICON_AV_TO_USB2.0_20200909 E: ID_SERIAL_SHORT=20200909 E: ID_TYPE=video E: ID_USB_DRIVER=uvcvideo E: ID_USB_INTERFACES=:0e0100:0e0200:030000: E: ID_USB_INTERFACE_NUM=00 E: ID_VENDOR=MACROSILICON E: ID_VENDOR_ENC=MACROSILICON E: ID_VENDOR_ID=534d E: MAJOR=81 E: MINOR=24 E: SUBSYSTEM=video4linux E: USEC_INITIALIZED=7594482747

    Тестирование правил:

    [root@luckfox root]# udevadm test /sys/class/video4linux/video0
    

    Выводы. eudev в контексте LuckFox Pico с Buildroot - это система, которая:

    - ✅ Обеспечивает автоматическое управление устройствами
    - ✅ Создает персистентные имена для USB-устройств
    - ✅ Загружает драйверы при подключении оборудования
    - ✅ Выполняет пользовательские скрипты через правила udev

    Для плат разработки с частым подключением различных USB-устройств (камер, флешек, последовательных адаптеров) eudev практически необходим для удобной работы.

    Я добавил в Lunux Buildroot настройку статического адреса для eth0 в файл /etc/network/interfaces:

    [root@luckfox root]# cat /etc/network/interfaces
    auto lo
    iface lo inet loopback
    auto eth0 iface eth0 inet static address 192.168.1.100 netmask 255.255.255.0 gateway 192.168.1.1 dns-nameservers 8.8.8.8

    Однако после перезагрузки системы интерфейс eth0 не работает. Чтобы он заработал необходимо вручную запускать команду:

    [root@luckfox root]# /etc/init.d/S40network restart
    

    Почему настройка eth0 не применяется автоматически?

    Проблема связана с порядком инициализации служб в Buildroot. Сеть поднимается до того, как все необходимые компоненты системы готовы.

    [Причина проблемы]

    В Buildroot существует несколько систем инициализации, и порядок запуска служб может отличаться:

    1. Скрипт S40network запускается слишком рано (до полной инициализации драйверов).
    2. Драйвер Ethernet может загружаться позже, чем пытается подняться сеть.
    3. udev/eudev может не успеть проинициализировать сетевые интерфейсы.

    Почему ручной перезапуск работает?

    Команда `/etc/init.d/S40network restart` работает, потому что к моменту ее выполнения:

    - Драйверы Ethernet уже загружены
    - Система полностью проинициализирована
    - Все аппаратные ресурсы готовы

    Проблема именно в временном соотношении между загрузкой драйверов и запуском сетевого сервиса при старте системы.

    [Решение 1: Ручная инициализация скриптами автозагрузки]

    Если вы не используете скрипт rc.local, то просто добавьте строчку /etc/init.d/S40network restart в конец файла /etc/init.d/rcS. Мне как раз помог именно этот простой метод.

    Если вы хотите использовать скрипт /etc/rc.local, и его запуск настроен в /etc/init.d/rcS, то добавьте в /etc/rc.local:

    echo "Sleeping for network initialization..."
    sleep 5
    /etc/init.d/S40network restart
    

    Сделайте файл /etc/rc.local исполняемым:

    # chmod +x /etc/rc.local
    

    Перезагрузите систему:

    # sync
    # reboot
    

    [Решение 2: Проверка и изменение порядка запуска]

    Посмотрите порядок служб в /etc/init.d/:

    # ls -la /etc/init.d/S*
    

    Сетевой сервис должен запускаться после основных системных сервисов. Попробуйте переименовать S40network в более поздний номер:

    # mv /etc/init.d/S40network /etc/init.d/S45network
    

    [Решение 3: Добавление задержки в сетевой сервис]

    1. Отредактируйте /etc/init.d/S40network и добавьте задержку перед поднятием интерфейсов:

    # vi /etc/init.d/S40network
    

    Добавьте в начало функции `start()`:

    start() {
    # Добавить задержку для инициализации системы
    sleep 3

    echo "Starting network..."
    # остальной код
    }

    [Решение 4: Использование системы инициализации BusyBox]

    Если вы используете BusyBox init, проверьте /etc/inittab:

    # cat /etc/inittab
    

    Убедитесь, что есть строка для сетевой инициализации:

    ::sysinit:/etc/init.d/rcS
    

    [Решение 5: Альтернативный подход - использование dhcpcd]

    Если статический IP не критичен, можно использовать DHCP. Измените настройку eth0 в файле /etc/network/interfaces:

    auto eth0
    iface eth0 inet dhcp
    

    [Решение 6: Использование systemd (если доступно)]

    Если в вашей сборке Buildroot используется systemd:

    # systemctl enable network
    # systemctl start network
    

    [Диагностика]

    Чтобы понять, в чем именно проблема, выполните диагностику.

    1. Убедитесь, что драйвер Ethernet загружается. Проверить загруженные модули:

    # lsmod | grep eth
    

    Или:

    # dmesg | grep eth
    

    2. Проверить логи загрузки:

    # dmesg | grep -i eth
    # dmesg | grep -i network
    

    3. Проверить статус интерфейса:

    # ip link show eth0
    

    4. Проверить, когда поднимается интерфейс:

    # ip addr show eth0
    

    5. Проверить наличие драйвера:

    # lsmod | grep gmac  # для LuckFox обычно gmac или подобный
    

    [Рекомендуемое решение]

    Мне помог вариант из Решения 1: просто добавил команду /etc/init.d/S40network restart в конец файла /etc/init.d/rcS. Скорее всего это поможет. Как вариант, попробуйте также Решение 2 и Решение 3.

    Я создаю этот файл командой:

    [root@luckfox root]# echo "nameserver 8.8.8.8" > /etc/resolv.conf
    

    Этот файл нормально создается и участвует в распознавании DNS-имен, но после перезагрузки оказывается пустым. Почему?

    Проблема с сохранением /etc/resolv.conf после перезагрузки связана с тем, как Buildroot управляет этим файлом. Вот основные причины и решения:

    Причина 1. Файл /etc/resolv.conf на самом деле это символическая ссылка на временный файл:

    Проверить, является ли resolv.conf симлинком:

    [root@luckfox root]# ls -la /etc/resolv.conf
    lrwxrwxrwx 1 1000 1000 18 Oct 16 2023 /etc/resolv.conf -> ../tmp/resolv.conf
    [root@luckfox root]# ls -la /tmp/resolv.conf
    -rw-r--r-- 1 root root 0  Jan 1 00:00 /tmp/resolv.conf
    

    Причина 2. tmpfs очищается при перезагрузке. Файл в /tmp/ создается заново при каждой загрузке. Таким образом, Причина 1 и Причина 2 могут быть взаимосвязаны, и дополнить друг друга, что как раз был мой случай.

    Причина 3. Сетевые скрипты перезаписывают файл. Сетевые демоны (наподобие connman, dhcpcd, network manager) могут перезаписывать resolv.conf.

    Скорее для Linux Buildroot на плате LuckFox Pico скорее всего причина проблемы это комбинация Причины 1 и Причины 2. Решить проблему можно, если заменить символическую ссылку реальным файлом. Как это сделать, по шагам:

    1. Удалите символическую ссылку:

    [root@luckfox root]# rm -f /etc/resolv.conf
    

    2. Создайте файл /etc/resolv.conf:

    [root@luckfox root]# echo "nameserver 8.8.8.8" > /etc/resolv.conf
    [root@luckfox root]# echo "nameserver 1.1.1.1" >> /etc/resolv.conf
    

    3. Заблокируйте этот файл от изменений (необязательный шаг):

    [root@luckfox root]# chattr +i /etc/resolv.conf 2>/dev/null || echo "chattr not available"
    

    4. Перезагрузите систему:

    [root@luckfox root]# sync
    [root@luckfox root]# reboot
    

    [Другие способы решения проблемы]

    Решение 2: Изменить точку назначения симлинка.

    Можно сохранить симлинк, но изменить его назначение. Создайте постоянный файл, на который будет ссылаться симлинк:

    [root@luckfox root]# mkdir -p /etc/resolv
    [root@luckfox root]# echo "nameserver 8.8.8.8" > /etc/resolv/resolv.conf.perm
    [root@luckfox root]# echo "nameserver 1.1.1.1" >> /etc/resolv/resolv.conf.perm
    

    Измените симлинк:

    [root@luckfox root]# rm -f /etc/resolv.conf
    [root@luckfox root]# ln -s /etc/resolv/resolv.conf.perm /etc/resolv.conf
    

    Решение 3: Добавить в создание /etc/resolv.conf автозагрузку.

    Добавьте в конец файла /etc/init.d/rcS строчки:

    echo "nameserver 8.8.8.8" > /etc/resolv.conf
    echo "nameserver 1.1.1.1" >> /etc/resolv.conf

    Перечисленные здесь команды использовались для взаимодействия хоста разработчика на Ubuntu 24.04.3 LTS через сеть Ethernet с Linux Buildroot на платке LuckFox Pico Mini B. На Ubuntu IP-адрес 192.168.1.1, на Buildroot 192.168.1.100.

    Запуск подключения к устройству LuckFox Pico Mini B:

    $ adb connect 192.168.1.100:5555
    connected to 192.168.1.100:5555
    

    Передача файла скрипта videotest.sh из локального каталога хоста в домашний каталог пользователя root на платке LuckFox (почему-то домашнему каталогу root соответствует папка /oem):

    $ adb -s 192.168.1.100:5555 push ./videotest.sh /oem
    

    Запуск команды на платке LuckFox:

    $ adb -s 192.168.1.100:5555 shell "ls ~"
    usr videotest.sh

    Описание проблемы. Вывод потока в файл работает, тестовый видеофайл /tmp/test.raw нормально создается:

    [root@luckfox root]# v4l2-ctl -d /dev/video0 --stream-mmap --stream-count=10 \
    --stream-to=/tmp/test.raw
    

    Но запуск потока на 192.168.1.1:5000 приводит к ошибке, несмотря на то, что связь с хостом 192.168.1.1 есть (ping проходит), на принимающей стороне запущена команда ffplay udp://192.168.1.100:5000.

    [root@luckfox root]# v4l2-ctl -d /dev/video0 --stream-mmap --stream-count=10 \
    --stream-to=192.168.1.1:5000
    could not open 192.168.1.1:5000 for writing
    

    Почему --stream-to=192.168.1.1:5000 приводит к ошибке?

    Дело в том, что v4l2-ctl --stream-to не поддерживает сетевые адреса с портами напрямую. Эта опция ожидает только путь к файлу или хост без указания порта. Таким образом, v4l2-ctl --stream-to интерпретирует 192.168.1.1:5000 как имя файла, а не сетевой адрес.

    [Решение 1: Использование netcat (nc)]

    На отправляющей стороне (luckfox):

    # v4l2-ctl -d /dev/video0 --stream-mmap --stream-to=- | nc -u 192.168.1.1 5000
    

    На принимающей стороне (192.168.1.1):

    $ nc -ul -p 5000 | ffplay -f rawvideo -pixel_format yuyv422 -video_size 640x480 -i -
    

    [Решение 2: Использование socat]

    На отправляющей стороне:

    # v4l2-ctl -d /dev/video0 --stream-mmap --stream-to=- | socat - udp-sendto:192.168.1.1:5000
    

    На принимающей стороне:

    $ ffplay -i udp://0.0.0.0:5000
    

    [Решение 3: использование ffmpeg для потоковой передачи]

    Примечание: этот вариант у меня не заработал на Buildroot, утилита ffmpeg постоянно приводила к критическому сбою.

    На отправляющей стороне:

    # ffmpeg -f v4l2 -input_format yuyv422 -video_size 640x480 -i /dev/video0 \
     -c copy -f mpegts udp://192.168.1.1:5000
    

    На принимающей стороне:

    $ ffplay udp://192.168.1.1:5000
    

    [Определение параметров видео]

    Для оптимального использования узнайте точные параметры вашего видео. На стороне вывода:

    [root@luckfox root]# v4l2-ctl -d /dev/video0 --get-fmt-video
    Format Video Capture:
            Width/Height      : 640/480
            Pixel Format      : 'MJPG' (Motion-JPEG)
            Field             : None
            Bytes per Line    : 0
            Size Image        : 614400
            Colorspace        : sRGB
            Transfer Function : Rec. 709
            YCbCr/HSV Encoding: ITU-R 601
            Quantization      : Default (maps to Full Range)
            Flags             : 
    

    Пример вывода:

    [root@luckfox root]# v4l2-ctl -d /dev/video0 --stream-mmap --stream-to=- \
     | socat - udp-sendto:192.168.1.1:5000
    <<<<<<<<<<<<<<<<<<<<<<<<< 25.00 fps, dropped buffers: 1
    <<<<<<<<<<<<<<<<<<<<<<<<< 25.00 fps
    <<<<<<<<<<<<<<<<<<<<<<<<< 25.00 fps
    <<<<<<<<<<<<<<<<<<<<<<<<< 25.00 fps
    <<<<<<<<<<<<<<<<<<<<<<<<< 25.00 fps
    <<<<<<<<<<<<<<<<<<<<<<<<< 25.00 fps
    ...
    

    Как подавить вывод, возможные варианты ниже.

    [1. Перенаправление stderr в /dev/null]

    Полностью подавить вывод сообщений с fps можно, если добавить 2>/dev/null к командной строке v4l2-ctl:

    [root@luckfox root]# v4l2-ctl -d /dev/video0 --stream-mmap --stream-to=- \
     2>/dev/null | socat - udp-sendto:192.168.1.1:5000
    

    Мне подошел этот вариант. Его достоинство: он скрывает только информационные сообщения, но оставляет возможность видеть критические ошибки в консоли.

    [2. Более точное подавление только FPS вывода]

    # v4l2-ctl -d /dev/video0 --stream-mmap --stream-to=- 2>&1 | grep -v "fps" \
     | socat - udp-sendto:192.168.1.1:5000
    

    [3. Использование --silent опции (если доступно)]

    Этот вариант у меня не заработал.

    # v4l2-ctl -d /dev/video0 --stream-mmap --stream-to=- --silent 2>/dev/null \
     | socat - udp-sendto:192.168.1.1:5000
    

    [4. Фильтрация только ошибок]

    # v4l2-ctl -d /dev/video0 --stream-mmap --stream-to=- 2>&1 >/dev/null \
     | socat - udp-sendto:192.168.1.1:5000
    

    [5. Полностью тихий режим]

    # v4l2-ctl -d /dev/video0 --stream-mmap --stream-to=- >/dev/null 2>&1 \
     | socat - udp-sendto:192.168.1.1:5000
    

    Но будьте осторожны - это также скроет возможные ошибки!

    Предположим, что вам нужно подключиться к платке LuckFox Pico Mini через Ethernet, платка видна по IP 192.168.1.100 (на ней работает сервер SSH).

    1. Добавьте хост 192.168.1.100 список доверенных хостов SSH:

    $ ssh-keygen -f '/home/имя_пользователя/.ssh/known_hosts' -R '192.168.1.100'
    

    Здесь имя_пользователя это логин пользователя на локальной машине, 192.168.1.100 это IP удаленного сервера SSH (на платке LuckFox Pico Mini).

    2. Пример выполнения команды pwd на удаленном хосте 192.168.1.100:

    $ ssh root@192.168.1.100 "pwd"
    root@192.168.1.100's password: 
    

    В ответ на запрос пароля введите luckfox, и команда выполнится:

    /root
    

    [sshpass]

    Чтобы не надо было каждый раз вводить пароль, необходимо либо сгенерировать ключи SSH, либо воспользоваться утилитой sshpass.

    Если утилита sshpass не установлена, установите её:

    $ sudo apt install sshpass
    

    Подключение с автоматическим вводом пароля:

    $ sshpass -p 'luckfox' ssh user@192.168.1.1 "команда"
    

    Недостаток использования sshpass очевиден, что её область применения пожалуй только в скриптах, потому что пароль в командной строке все равно присутствует, да еще и в открытом виде. Поэтому лучше настроить беспарольный доступ лучше с помощью обмена ключами шифрования SSH.

    [Настройка доступа по ключу SSH]

    1. На локальной машине выполните генерацию публичного и приватного ключей:

    $ ssh-keygen -t rsa -b 4096
    Generating public/private rsa key pair.
    Enter file in which to save the key (/home/имя_пользователя/.ssh/id_rsa): 251007luckfox
    Enter passphrase (empty for no passphrase): 
    Enter same passphrase again: 
    Your identification has been saved in 251007luckfox
    Your public key has been saved in 251007luckfox.pub
    The key fingerprint is:
    SHA256:eUJ6GQ+W2BComCfkuoF7aysNhFkYBf6SG8fJGtOeW0U имя_пользователя@TAG-5779
    The key's randomart image is:
    +---[RSA 4096]----+
    |o=.  .o.         |
    |o.. .  + .       |
    |+* .  .EB        |
    |*oO . .+ *       |
    |+O B  ..S o      |
    |= X . .. o       |
    | O o .           |
    |+ + o            |
    | +o+             |
    +----[SHA256]-----+
    

    Здесь имя_пользователя это логин локального пользователя, 251007luckfox имя файла для генерируемого ключа. После этой команды в локальном каталоге пользователя ~ будут сгенерированы два файла:

    $ ls -1 ~ | grep luckfox
    251007luckfox # приватный ключ
    251007luckfox.pub # публичный ключ

    2. Добавьте текст сгенерированного публичного ключа в файл /root/.ssh/authorized_keys на сервере SSH. Дальнейшие действия происходят на сервере SSH платки LuckFox под пользователем root:

    # mkdir -p /root/.ssh
    # touch /root/.ssh/authorized_keys
    # nano /root/.ssh/authorized_keys
    

    Вставьте текст из файла 251007luckfox.pub и сохраните файл /root/.ssh/authorized_keys. Это можно сделать с помощью текстового редактора nano или vi. Проверьте, что публичный ключ сохранился:

    # cat /root/.ssh/authorized_keys
    ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDJdUdHXUwguO8FH0WkSPnts8fauiop
    ...
    k6x+3hwVdJSKEmzIfGAnH6/7qsB1tPewQ8DQOFuk0NCCxUREQEfi3VXVizhvswpngrga
    pa7xnuioQZsy88acuiWBfMqffZan6Vdsdq/Q== имя_пользователя@TAG-5779
    

    3. Исправьте конфигурацию сервера SSH, чтобы там правильно был указан путь до файла authorized_keys:

    # nano /etc/ssh/sshd_config
    

    Проверьте строчку AuthorizedKeysFile, исправьте её, если она неправильная:

    AuthorizedKeysFile /root/.ssh/authorized_keys
    

    4. Проверьте права доступа и владельца на каталоги /root, /root/.ssh и файл /root/.ssh/authorized_keys с помощью команды ls -la:

    # ls -la /root
    # ls -la /root/.ssh
    # ls -la /root/.ssh/authorized_keys
    

    Везде владелец должен быть root:root, права доступа на каталогах /root и /root/.ssh должны быть drwx------, а на файл authorized_keys должны быть права доступа -rw-------.

    Доступ Владелец Группа Файл или папка
    drwx------ root root /root
    drwx------ root root /root/.ssh
    -rw------- root root /root/.ssh/authorized_keys

    Если это не так, то исправьте командами:

    # chown -R root:root /root
    # chown -R root:root /root/.ssh
    # chown -R root:root /root/.ssh/authorized_keys
    # chmod 700 /root
    # chmod 700 /root/.ssh
    # chmod 600 /root/.ssh/authorized_keys
    

    5. Перезапустите сервер ssh:

    # ps | grep ssh
     1349 root     sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups
     1380 root     grep ssh
    # kill 1349
    # /usr/sbin/sshd
    

    После этого вы сможете подключаться к серверу SSH платки LuckFox без пароля.

    [Полезные команды для диагностики]

    Подсказка по опциям (только на полноценном хосте доступна команда man sshd):

    $ ssh root@192.168.1.100 "sshd --help"
    unknown option -- -
    OpenSSH_9.3p2, OpenSSL 1.1.1v  1 Aug 2023
    usage: sshd [-46DdeGiqTtV] [-C connection_spec] [-c host_cert_file]
                [-E log_file] [-f config_file] [-g login_grace_time]
                [-h host_key_file] [-o option] [-p port] [-u len]
    

    Следующая команда запускает сервер SSH в режиме вывода лога отладки в консоль (опция -d), с использованием конфигурационного файла /etc/ssh/sshd_config (опция -f):

    # /usr/sbin/sshd -d -f /etc/ssh/sshd_config
    

    В частности, это помогло мне обнаружить проблему прав доступа к каталогу /root со стороны сервера sshd. Он упорно запрашивал пароль пользователя, несмотря на настроенный доступ по ключу (см. Q055).

    См. также:

    Q032. Как разрешить Ethernet на плате LuckFox Pico Mini
    Q033. Настроить IP интерфейса Ethernet на плате LuckFox Pico Mini
    Q035. Как подключиться по SSH?

    Наблюдается проблема: несмотря на то, что правильно настроен доступ по паре ключей SSH (см. Q054), сервер все равно запрашивает пароль при попытке подключения.

    Запуск сервера SSH в режиме отладки (опция -d) позволил понять, в чем проблема:

    # ps | grep ssh
     1349 root     sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups
     1380 root     grep ssh
    # kill 1349
    # /usr/sbin/sshd -d -f /etc/ssh/sshd_config
    debug1: sshd version OpenSSH_9.3, OpenSSL 1.1.1v  1 Aug 2023
    debug1: private host key #0: ssh-rsa SHA256:TUf2NU/xAfSS8UXJjyrxTkdLbIlYxBe2ZnxgXe9
    debug1: private host key #1: ecdsa-sha2-nistp256 SHA256:9wWC2XW74wk5uc4OrrFVyaZAX1+
    debug1: private host key #2: ssh-ed25519 SHA256:5b8Z6u5uCWhu0AhfsQTkrRwiyTtBidfSUcm
    debug1: rexec_argv[0]='/usr/sbin/sshd'
    debug1: rexec_argv[1]='-d'
    debug1: rexec_argv[2]='-f'
    debug1: rexec_argv[3]='/etc/ssh/sshd_config'
    debug1: Set /proc/self/oom_score_adj from 0 to -1000
    socket: Address family not supported by protocol
    debug1: Bind to port 22 on 0.0.0.0.
    Server listening on 0.0.0.0 port 22.
    ...
    

    Попытка подключения клиента SSH:

    ...
    debug1: rekey in after 134217728 blocks [preauth]
    debug1: KEX done [preauth]
    debug1: userauth-request for user root service ssh-connection method none [preauth]
    debug1: attempt 0 failures 0 [preauth]
    debug1: userauth-request for user root service ssh-connection method publickey [preauth]
    debug1: attempt 1 failures 0 [preauth]
    debug1: userauth_pubkey: publickey test pkalg ssh-ed25519 pkblob ED25519 SHA256:o2n
    9di8eVNIKkVNRHUrWpD8yWsnnYhFietm7q2tgOxE [preauth]
    debug1: temporarily_use_uid: 0/0 (e=0/0)
    debug1: trying public key file /root/.ssh/authorized_keys
    debug1: fd 4 clearing O_NONBLOCK
    Authentication refused: bad ownership or modes for directory /root
    debug1: restore_uid: 0/0
    ...
    

    Из лога видно, что отказано в попытке доступа к файлу /root/.ssh/authorized_keys (bad ownership or modes for directory /root).

    Проблему решила настройка владельца и прав доступа на каталог /root:

    # chown -R root:root /root
    # chmod 700 /root
    

    Проверьте также права доступа (командой ls -la) на каталог /root/.ssh/ и файл authorized_keys:

    Доступ Владелец Группа Файл или папка
    drwx------ root root /root
    drwx------ root root /root/.ssh
    -rw------- root root /root/.ssh/authorized_keys

    Перезагрузите сервер командами sync и reboot:

    # sync
    # reboot
    

    Для копирования файлов на сервер по SSH существует несколько основных способов:

    [1. SCP (Secure Copy)]

    Утилита scp это наиболее простой и распространенный способ. Общий синтаксис копирования одного файла:

    scp источник назначение

    Под источником и назначением могут быть как локальный файл, так и подключение к удаленному серверу SSH:

    scp localfile remoteuser@IP:/путь/на/сервере
    scp remoteuser@IP:/путь/на/сервере localfile

    Копирование директории рекурсивно:

    scp -r localdir remoteuser@IP:/путь/на/сервере

    Здесь localfile это файл, localdir директория на машине, откуда происходит копирование, remoteuser это пользователь на удаленном сервере SSH, IP это адрес сервера SSH (который может быть представлен DNS-именем), /путь/на/сервере это путь в файловой системе сервера SSH.

    Пример копирования файла hello.txt на SSH-сервер платки LuckFox, которая подключена через Ethernet. IP-адрес сервера SSH 192.168.1.100:

    $ touch hello.txt
    $ echo "hi!" > hello.txt
    $ scp hello.txt root@192.168.1.100:/oem
    hello.txt                                     100%    4     1.9KB/s   00:00
    

    Здесь каталог /oem это каталог на Linux Buildroot платки LuckFox, соответствующий домашнему каталогу пользователя root. Проверка, что файл успешно скопировался:

    $ ssh root@192.168.1.100 "cat /oem/hello.txt"
    hi!
    

    Важное замечание: /путь/на/сервере должен быть абсолютным, т. е. нельзя использовать относительные пути и пути, содержащие ~. Иначе это может привести к путанице.

    [2. SFTP (SSH File Transfer Protocol)]

    С помощью sftp можно организовать интерактивную работу с файловой системой SSH-сервера. Общий синтаксис показан ниже.

    Подключение к серверу:

    sftp remoteuser@IP

    Команды в SFTP:

    put локальный_файл          # Загрузить файл
    get удаленный_файл          # Скачать файл
    ls                          # Просмотр файлов
    cd папка                    # Смена директории

    [3. Rsync через SSH]

    Утилиту rsync часто используют для синхронизации файлов и директорий на сетевых хостах. Например, для зеркалирования каталогов web-сервера на другой web-сервер. При этом копируются только измененные или новые файлы [5]. Ниже показан общий синтаксис использования утилиты rsync.

    Синхронизация с прогрессом:

    rsync -avz -e ssh localdir/ remoteuser@IP:/remotedir/

    Синхронизация с удалением лишних файлов на сервере:

    rsync -avz --delete -e ssh localdir/ remoteuser@IP:/remotedir/

    [Параметры аутентификации scp]

    С паролем, будет запрошен пароль, если не настроена аутентификация по ключу (см. Q054):

    scp localfile remoteuser@IP:/путь/на/сервере

    С SSH-ключом, использование конкретного ключа:

    scp -i ~/.ssh/ключ localfile remoteuser@IP:/путь/на/сервере

    [Дополнительные опции scp]

    Указание порта подключения(нестандартного):

    scp -P 2222 localfile remoteuser@IP:/путь/на/сервере

    Сжатие данных при передаче:

    scp -C localfile remoteuser@IP:/путь/на/сервере

    Сохранение атрибутов файлов:

    scp -p localfile remoteuser@IP:/путь/на/сервере

    Ограничение скорости передачи 1000 килобит/сек:

    scp -l 1000 localfile remoteuser@IP:/путь/на/сервере

    Практические примеры. Копирование веб-сайта:

    $ scp -r /var/www/mysite/* user@webserver:/var/www/html/
    

    Копирование с прогрессом (rsync):

    $ rsync -avz --progress -e ssh backup.tar.gz user@server:/backups/
    

    Копирование через нестандартный порт SSH, с использованием конфигурационного файла config.conf для SSH (напрямую передается в утилиту ssh):

    $ scp -P 2022 -F config.conf admin@server:/etc/app/
    

    Советы:

    - Используйте SSH-ключи для автоматизации.
    - Rsync предпочтительнее для больших файлов/директорий.
    - Для частого использования настройте конфигурационный файл для ssh.

    Для остановки процесса по имени с помощью kill есть несколько способов:

    [С помощью скрипта]

    Создайте вот такой скрипт (например, k.sh):

    #!/bin/bash

    if [ $# -eq 0 ]; then
    echo "Использование: $0 < имя_процесса>"
    exit 1
    fi

    PIDS=$(pgrep "$1")

    if [ -z "$PIDS" ]; then
    echo "Процесс '$1' не найден"
    exit 1
    fi

    echo "Останавливаем процессы: $PIDS"
    kill $PIDS 2>/dev/null

    # Принудительное завершение, если процессы не отвечают sleep 2
    REMAINING=$(pgrep "$1")
    if [ -n "$REMAINING" ]; then
    echo "Принудительно завершаем: $REMAINING"
    kill -9 $REMAINING 2>/dev/null
    fi

    echo "Готово"

    Пример использования:

    $ gedit &
    [1] 277402
    $ ./k.sh gedit
    Останавливаем процессы: 277402
    Готово
    [1]+  Terminated              gedit
    

    [killall]

    Остановить все процессы с указанным именем:

    killall process_name

    Принудительная остановка:

    killall -9 process_name

    Примеры:

    $ killall nginx
    $ killall -9 python
    

    Пример запуска и остановки видеопотока MPEG с помощью утилиты v4l2-ctl:

    $ v4l2-ctl -d0 --stream-mmap --stream-to=- | socat - udp-sendto:192.168.1.1:5000 &
    [1] 277805
    $ ps | grep v4l2-ctl
     277804 pts/1    00:00:00 v4l2-ctl
    $ killall v4l2-ctl
    $ ps | grep v4l2-ctl
    [1]+ Stopped v4l2-ctl -d0 --stream-mmap --stream-to=- | socat - udp-sendto:192.168.1.1:5000
    

    [pkill (самый простой способ)]

    Этот способ не подойдет для Linux Buildroot, поскольку по умолчанию в сборке Buildroot нет утилиты pkill.

    Остановить процесс по имени (отправляет SIGTERM):

    pkill process_name

    Принудительная остановка (SIGKILL):

    pkill -9 process_name

    Примеры использования:

    $ pkill firefox
    $ pkill -9 chrome
    

    [Комбинация pgrep + kill]

    Этот способ не подойдет для Linux Buildroot, поскольку по умолчанию в сборке Buildroot нет утилиты pgrep.

    Найти PID и остановить:

    kill $(pgrep process_name)

    Или с принудительным завершением:

    kill -9 $(pgrep process_name)

    Пример:

    $ kill $(pgrep firefox)
    

    Безопасный способ с проверками (скрипт):

    # Проверка существования процесса перед остановкой
    PROCESS="firefox"
    PID=$(pgrep "$PROCESS")

    if [ -n "$PID" ]; then
    echo "Останавливаем процесс $PROCESS (PID: $PID)"
    kill $PID
    else
    echo "Процесс $PROCESS не найден"
    fi

    Для нескольких процессов с одним именем (скрипт):

    # Остановить все процессы с указанным именем
    PROCESS="python"
    PIDS=$(pgrep "$PROCESS")

    if [ -n "$PIDS" ]; then
    echo "Найдены процессы: $PIDS"
    kill $PIDS
    else
    echo "Процессы $PROCESS не найдены"
    fi

    Постепенное завершение (скрипт):

    # Сначала вежливая остановка, затем принудительная
    PROCESS="myapp"
    PID=$(pgrep "$PROCESS")

    if [ -n "$PID" ]; then
    echo "Отправляем SIGTERM процессу $PID"
    kill $PID

    # Ждем 5 секунд
    sleep 5

    # Проверяем, жив ли еще процесс
    if kill -0 $PID 2>/dev/null; then
    echo "Процесс не ответил, отправляем SIGKILL"
    kill -9 $PID
    fi
    fi

    [Универсальная функция для .bashrc]

    Добавьте в ~/.bashrc:

    killp() {
    if [ $# -eq 0 ]; then
    echo "Использование: killp < имя_процесса>"
    return 1
    fi

    local PIDS=$(pgrep "$1")

    if [ -z "$PIDS" ]; then
    echo "Процесс '$1' не найден"
    return 1
    fi

    echo "Останавливаем процессы '$1': $PIDS"
    kill $PIDS
    }

    После добавления в .bashrc:

    $ source ~/.bashrc
    $ killp firefox  # Использование функции
    

    [Сигналы для kill]

    Вежливое завершение (по умолчанию):

    kill -TERM $(pgrep process_name)

    Принудительное завершение:

    kill -KILL $(pgrep process_name)

    Перезапуск процесса:

    kill -HUP $(pgrep process_name)

    [Практические примеры]

    Остановить веб-сервер nginx:

    $ sudo pkill nginx
    

    Остановить все Python скрипты:

    $ pkill python
    

    Остановить процесс с подтверждением:

    $ read -p "Остановить Firefox? (y/n): " ans
    [[ $ans == "y" ]] && pkill firefox
    

    Остановить процесс, если он использует много памяти:

    if ps aux | grep firefox | grep -v grep | awk '{if ($4 > 50) print $2}' | xargs kill; then
    echo "Процессы Firefox с >50% памяти остановлены"
    fi

    Рекомендации:

    - Используйте pkill для простых случаев.
    - Используйте pgrep + kill когда нужен больший контроль.
    - Сначала пробуйте SIGTERM, и только потом SIGKILL.
    - Будьте осторожны с sudo и системными процессами.

    Для сохранения кадра в формате BMP с помощью v4l2-ctl есть несколько способов:

    [1. Прямое сохранение в BMP через --stream-to]

    Сохранение одного кадра:

    v4l2-ctl -d0 --stream-mmap --stream-to=frame.bmp --stream-count=1

    В этом примере кадр сохраняется как растровая картинка в формате MJPEG.

    [2. Сохранение RAW данных и конвертация]

    Сохраняем RAW данные (YUV или MJPEG):

    v4l2-ctl -d0 --set-fmt-video=width=1920,height=1080,pixelformat=YUYV
    v4l2-ctl -d0 --stream-mmap --stream-to=frame.raw --stream-count=1

    Затем конвертируем в BMP (требуются дополнительные утилиты). Использование ffmpeg для конвертации:

    ffmpeg -f rawvideo -pixel_format yuyv422 -video_size 640x480 -i frame.raw frame.bmp

    [Полный скрипт для сохранения BMP]

    #!/bin/bash

    # Параметры по умолчанию
    DEVICE="${1:-0}"
    WIDTH="${2:-640}"
    HEIGHT="${3:-480}"
    PIXELFORMAT="${4:-YUYV}"
    OUTPUT="${5:-frame.bmp}"

    echo "Захват кадра с /dev/video$DEVICE..."
    echo "Разрешение: ${WIDTH}x${HEIGHT}"
    echo "Формат: $PIXELFORMAT"

    # Устанавливаем формат v4l2-ctl -d$DEVICE --set-fmt-video=width=$WIDTH,height=$HEIGHT,pixelformat=$PIXELFORMAT

    # Сохраняем RAW данные
    RAW_FILE="${OUTPUT%.*}.raw" v4l2-ctl -d$DEVICE --stream-mmap --stream-to="$RAW_FILE" --stream-count=1

    # Конвертируем в BMP используя ffmpeg
    if command -v ffmpeg &> /dev/null; then
    case $PIXELFORMAT in
    YUYV|YUYV422)
    ffmpeg -f rawvideo -pixel_format yuyv422 -video_size ${WIDTH}x${HEIGHT} \
    -i "$RAW_FILE" "$OUTPUT" -y
    ;;
    MJPG)
    ffmpeg -f mjpeg -i "$RAW_FILE" "$OUTPUT" -y
    ;;
    RGB24)
    ffmpeg -f rawvideo -pixel_format rgb24 -video_size ${WIDTH}x${HEIGHT} \
    -i "$RAW_FILE" "$OUTPUT" -y
    ;;
    *)
    echo "Формат $PIXELFORMAT не поддерживается для автоматической конвертации"
    echo "RAW данные сохранены в: $RAW_FILE"
    exit 1
    ;;
    esac

    # Удаляем временный RAW файл
    rm "$RAW_FILE"
    echo "Кадр сохранен как: $OUTPUT"
    else
    echo "ffmpeg не найден. RAW данные сохранены в: $RAW_FILE"
    echo "Установите ffmpeg для конвертации в BMP: sudo apt install ffmpeg"
    fi

    [Скрипт с определением доступных форматов]

    #!/bin/bash
    capture_bmp() {
    local device="${1:-0}"
    local output="${2:-frame_$(date +%Y%m%d_%H%M%S).bmp}"

    # Получаем информацию о поддерживаемых форматах
    echo "=== Проверка поддерживаемых форматов ==="
    v4l2-ctl -d$device --list-formats-ext

    # Запрашиваем параметры у пользователя
    read -p "Ширина кадра [640]: " width
    width=${width:-640}

    read -p "Высота кадра [480]: " height
    height=${height:-480}

    read -p "Формат пикселей [YUYV]: " pixelformat
    pixelformat=${pixelformat:-YUYV}

    # Устанавливаем формат
    echo "Установка формата: ${width}x${height} $pixelformat"
    v4l2-ctl -d$device --set-fmt-video=width=$width,height=$height,pixelformat=$pixelformat

    # Захватываем кадр
    echo "Захват кадра..."
    temp_raw=$(mktemp)
    v4l2-ctl -d$device --stream-mmap --stream-to="$temp_raw" --stream-count=1

    # Конвертируем в BMP
    if command -v ffmpeg &> /dev/null; then
    echo "Конвертация в BMP..."
    ffmpeg -f rawvideo -pixel_format yuyv422 -video_size ${width}x${height} \
    -i "$temp_raw" "$output" -y -loglevel quiet
    rm "$temp_raw"
    echo "✅ Кадр сохранен: $output"
    else
    mv "$temp_raw" "${output%.*}.raw"
    echo "⚠️ ffmpeg не найден. RAW данные сохранены: ${output%.*}.raw"
    fi
    }

    Использование:

    capture_bmp "$@"

    [Простая однострочная команда с конвертацией]

    Однострочная команда для быстрого сохранения BMP:

    v4l2-ctl -d0 --set-fmt-video=width=640,height=480,pixelformat=YUYV --stream-mmap \
     --stream-to=/tmp/frame.raw --stream-count=1 && ffmpeg -f rawvideo -pixel_format \
     yuyv422 -video_size 640x480 -i /tmp/frame.raw frame.bmp -y && rm /tmp/frame.raw

    [Скрипт для периодического сохранения кадров]

    #!/bin/bash

    # Параметры
    DEVICE=0
    INTERVAL=5 # секунд между кадрами
    COUNT=10 # количество кадров

    for i in $(seq 1 $COUNT); do
    output="frame_$(printf "%03d" $i)_$(date +%H%M%S).bmp"
    echo "Захват кадра $i/$COUNT: $output"

    v4l2-ctl -d$DEVICE --stream-mmap --stream-to=/tmp/temp.raw --stream-count=1
    ffmpeg -f rawvideo -pixel_format yuyv422 -video_size 640x480 \
    -i /tmp/temp.raw "$output" -y -loglevel quiet
    rm /tmp/temp.raw

    sleep $INTERVAL
    done

    Как использовать:

    1. Сохраните скрипт как capture_bmp.sh.
    2. Сделайте исполняемым: chmod +x capture_bmp.sh.
    3. Запустите:

    $ ./capture_bmp.sh               # Использовать значения по умолчанию
    $ ./capture_bmp.sh 0 frame1.bmp  # Указать устройство и имя файла
    

    Примечания:

    - v4l2-ctl сам по себе не умеет сохранять прямо в BMP, только RAW данные
    - ffmpeg требуется для конвертации RAW в BMP
    - Формат YUYV наиболее распространен для веб-камер
    - Для MJPEG камер используйте `pixelformat=MJPG`

    Самый простой способ - использовать "3. Полный скрипт для сохранения BMP", который автоматически выполнит все необходимые шаги.

    Утилита v4l2-ctl работает на хосте с IP-адресом 192.168.1.100, и передает видеопоток от аналоговой камеры на хост с IP-адресом 192.168.1.1.

    [Через UDP]

    На передающей стороне:

    v4l2-ctl -d0 --stream-mmap --stream-to=- | socat - udp-sendto:192.168.1.1:5000

    На принимающей стороне видеопоток можно просмотреть командой:

    ffplay -f mjpeg udp://192.168.1.100:5000

    Проблема в том, что наблюдается большая задержка между событиями реального времени перед камерой и их появлением на принимающей стороне. Задержка может быть случайная, визуально от 0.2 до 3 секунд. При этом видно, что проигрывание картинки ffplay как раз происходит с этой задержкой.

    Причина проблемы заключалась в буферах UDP на стороне приема. Минимизировать эту задержку и сделать её постоянной можно с помощью следующей команды на стороне приема:

    ffplay -f mjpeg -fflags nobuffer -flags low_delay -framedrop -analyzeduration 1 \
     -probesize 32 -buffer_size 16384 udp://192.168.1.100:5000

    [Через TCP]

    На передающей стороне:

    v4l2-ctl -d0 --stream-mmap --stream-to-host 192.168.1.1:5000

    На принимающей стороне:

    ffplay -f mjpeg -fflags nobuffer -flags low_delay -framedrop -analyzeduration 1 \
     -probesize 32 tcp://0.0.0.0:5000?listen

    [Ссылки]

    1. SDK Environment Deployment(on the PC) site:wiki.luckfox.com.
    2. Ubuntu FAQ.
    3. Запускаем Yolo на пятирублёвой монете или Luckfox Pico Mini site:habr.com.
    4. man adb.
    5. rsync: синтаксис, примеры использования.