惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Cisco Talos Blog
Cisco Talos Blog
V
V2EX
C
Check Point Blog
GbyAI
GbyAI
D
Docker
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog RSS Feed
H
Hackread – Cybersecurity News, Data Breaches, AI and More
N
Netflix TechBlog - Medium
T
Troy Hunt's Blog
博客园 - Franky
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Microsoft Security Blog
Microsoft Security Blog
P
Privacy & Cybersecurity Law Blog
WordPress大学
WordPress大学
The Cloudflare Blog
S
SegmentFault 最新的问题
Latest news
Latest news
Microsoft Azure Blog
Microsoft Azure Blog
P
Proofpoint News Feed
I
InfoQ
博客园 - 【当耐特】
NISL@THU
NISL@THU
A
About on SuperTechFans
T
Tailwind CSS Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
The Hacker News
The Hacker News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Scott Helme
Scott Helme
雷峰网
雷峰网
C
CXSECURITY Database RSS Feed - CXSecurity.com
Security Latest
Security Latest
V
Vulnerabilities – Threatpost
Security Archives - TechRepublic
Security Archives - TechRepublic
A
Arctic Wolf
Hacker News: Ask HN
Hacker News: Ask HN
N
News and Events Feed by Topic
IT之家
IT之家
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
aimingoo的专栏
aimingoo的专栏
T
Threat Research - Cisco Blogs
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
阮一峰的网络日志
阮一峰的网络日志
SecWiki News
SecWiki News
大猫的无限游戏
大猫的无限游戏
S
Security Affairs
The Register - Security
The Register - Security
www.infosecurity-magazine.com
www.infosecurity-magazine.com
L
LINUX DO - 热门话题
T
Tor Project blog

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Нестандартное решение для стандартных задач: пробуем вычислительный модуль Luckfox
CyberexTech · 2026-05-18 · via Все публикации подряд на Хабре

Уровень сложностиСредний

Время на прочтение23 мин

Охват и читатели131

Кейс

Luckfox

Luckfox

Привет, Хабр!

Глядя на то, как из-за кризиса производства оперативной памяти цены на одноплатные компьютеры улетают в космос, чувствуешь острую необходимость искать для своих проектов более бюджетные и порой нестандартные решения. Одним из таких решений, которое случайно попалось мне на глаза, стал вычислительный модуль от компании Luckfox. В данной статье мы посмотрим его характеристики, соберем операционную систему и запустим I2S-интерфейс для передачи цифрового аудио.

❯ Начало

Для своего проекта я искал решение со встроенной постоянной памятью EMMC, радио модулем Wi-Fi/BT, производительным SoC и в компактном форм-фактора а-ля вычислительный модуль. И кажется я его нашел, им стал вычислительный модуль Luckfox Core 1106 на базе SoC Rockchip RV1106G3.

❯ Технические характеристики модуля

Ниже в таблице представлены технические характеристики модулей:

Модель

Core11061408

CPU

RV1106G3

Processor

Cortex A7 @1.2GHz

NPU

1TOPS, supports int4, int8, int16

ISP

Supports input 5M@30fps

Аппаратное кодирование

Hardware encoding, supports MJPEG, H264, H265

Оперативная память

256MB DDR3L

Интерфейс дисплея

Parallel RGB 18-bit × 1

Интерфейс камеры

MIPI CSI 2-lane × 2 or MIPI CSI 4-lane × 1

Микрофон

Analog differential MIC interface × 2

Аналоговые аудио выходы

LINEOUT × 1

USB

USB 2.0 Host/Device

WIFI/Bluetooth

2.4 GHz WIFI 6 and Bluetooth 5.2/BLE

Ethernet порт

10/100M Ethernet controller and embedded PHY

Постоянная память

eMMC 5.1 (8GB)

Интерфейсы

I2S × 3, I2C × 5, SPI × 2, SDIO × 2, ADC × 2, UART × 6, PWM × 12

Размер

30 × 30 (mm)

Количество выводов

112 Pin

В моём случае используется модель модуля Core11061408. Особенностью используемого SoC является то, что оперативная память реализована на самом кристалле, а не отдельной микросхемой. Это значительно повышает скорость обмена с RAM и заметно уменьшает габариты платы. Габариты вычислительного модуля представлены на фото ниже.

Размеры вычислительного модуля

Размеры вычислительного модуля

Как вы могли заметить в техническом описании, используемый в модуле SoC также имеет на борту NPU-ускоритель на 1 TOPS и интерфейс для подключения камеры. Это намекает нам на то, что основной функционал модуля заточен под системы видеонаблюдения с локальной ИИ-обработкой видеопотока.

❯ Первый тестовый запуск

Так как данный модуль был куплен «как есть» — без платы разработчика, в которую его можно было бы вставить для прошивки, — мне пришлось самостоятельно разбираться со схемой подключения. Ниже представлен вариант распиновки, который получился в итоге.

Схема подключения модуля

Схема подключения модуля

Здесь стоит похвалить компанию Luckfox за подробную документацию. Они даже подготовили проект для KiCad с распиновкой модуля, что значительно упростило мне дальнейшую разработку.

А вот так выглядит моё тестовое подключение к модулю вживую:

Физическое подключение к модулю

Физическое подключение к модулю

Также будет нелишним привести нумерацию выводов самого модуля:

Распаковка модуля

Распаковка модуля

Теперь пришло время прошить модуль. Luckfox очень подробно описала этот процесс, поэтому я лишь продемонстрирую видео из их Wiki:

А если коротко, то прошивка модуля выполняется с помощью фирменного приложения SocToolKit flashing tool от компании Rockchip и скомпилированного образа. Удерживая кнопку BOOT, подключите плату к компьютеру. Отпустите кнопку BOOT, как только приложение для прошивки Rockchip отобразит устройство MaskRom. Далее в поле Search Path выбрать необходимый образ прошивки и нажать кнопку Download.

Для прошивки предлагается несколько готовых вариантов образов на базе Buildroot и Ubuntu:

Version

Description

Download

Buildroot

Standard models (A/B): Burn the Luckfox_Pico_Pi_EMMC_250313 firmware Wireless models (A/B W): Burn the Luckfox_Pico_Pi_W_EMMC_250313 firmware

Google Driver

Community-Supported Image Download

Version

Description

Download

Ubuntu22.04

Standard models (A/B): Burn the Ubuntu_Luckfox_Pico_Pi_EMMC_250313 firmware Wireless models (A/B W): Burn the Ubuntu_Luckfox_Pico_Pi_W_EMMC_250313 firmware

Google Driver

Для тестовой прошивки я выбрал образ на базе Ubuntu. Так как используется модуль со встроенной памятью и радиомодулем, необходимо выбирать версию с индексами W и EMMC. В моём случае корректно заработала прошивка с названием Ubuntu_Luckfox_Pico_Ultra_W_EMMC — на остальных вариантах радиомодуль не запускался.

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

  • ADB;

  • SSH (+RNDIS);

  • USB-to-TTL.

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

❯ Дайте мне звук!

А тут начинаются мои эксперименты! Данный модуль был выбран не просто так, а из-за хорошего набора интерфейсов (I2S × 3, I2C × 5, SPI × 2, SDIO × 2, ADC × 2, UART × 6, PWM × 12) при небольшой стоимости. А так как я планирую реализовать аудио приложение на данном модуле, то возникает задача запуска цифрового аудио интерфейса I2S.

Но, как всегда, все сладкие мечты разбиваются о жестокую действительность китайских SBC: ну не любят они интерфейс (I2S), и «из коробки» он не работает, хотя и отображается в списке звуковых устройств. Выполняя команду на модуле:

alsamixer

Мы видим следующее:

Конфигурация аудиоустройства. Взято из официального Wiki, свой забыл сделать :)

Конфигурация аудиоустройства. Взято из официального Wiki, свой забыл сделать :)

Есть упоминание об I2S-интерфейсе, но, к сожалению, потыкав осциллографом в шину при тестовом воспроизведении звука, понимаешь, что она мертва. Легкого пути, как всегда, не случилось, поэтому будем пересобирать систему с активированной шиной I2S.

❯ Пересобираем систему

И заодно избавляемся от лишнего. Для начала нам нужно разобраться с деревом устройств и посмотреть что там вообще происходит, активирован ли интерфейс I2S?

Кстати, процесс сборки образа прошивки детально описан здесь, поэтому в статье подробно раскрывать эту тему не стану. Вся компиляция образа выполняется на виртуальный машине с Ubuntu 22.04.

Для начала нам нужно скачать SDK с исходниками с помощью команды:

git clone -b 5.10.110 https://github.com/LuckfoxTECH/luckfox-pico.git

Пока я потренируюсь на кошках на старом ядре, а дальше посмотрим.

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

cd /luckfox-pico/project/cfg/BoardConfig_IPC

Ранее я уже упоминал, что наиболее рабочая конфигурация прошивки это Ubuntu Luckfox Pico Ultra W, поэтому будем использовать эту конфигурацию при сборке. Откроем файл и уберем лишнее оборудование:

nano BoardConfig-EMMC-Ubuntu-RV1106_Luckfox_Pico_Ultra_W-IPC.mk

Приведем файл к следующему содержанию:

Содержание файла
#!/bin/bash

#################################################
# 	Board Config
#################################################

# Target CHIP
export RK_CHIP=rv1106

# app config
# export RK_APP_TYPE=RKIPC_RV1106

# Config CMA size in environment
export RK_BOOTARGS_CMA_SIZE="1M"

# Kernel dts
export RK_KERNEL_DTS=rv1106g-luckfox-pico-ultra-w.dts

#################################################
#	BOOT_MEDIUM
#################################################

# Target boot medium: emmc/spi_nor/spi_nand
export RK_BOOT_MEDIUM=emmc

# Uboot defconfig fragment
export RK_UBOOT_DEFCONFIG_FRAGMENT=rk-emmc.config

# specify post.sh for delete/overlay files
# export RK_PRE_BUILD_OEM_SCRIPT=rv1103-spi_nor-post.sh

# config partition in environment
# RK_PARTITION_CMD_IN_ENV format:
#     <partdef>[,<partdef>]
#       <partdef> := <size>[@<offset>](part-name)
# Note:
#   If the first partition offset is not 0x0, it must be added. Otherwise, it needn't adding.
export RK_PARTITION_CMD_IN_ENV="32K(env),512K@32K(idblock),256K(uboot),32M(boot),512M(oem),256M(userdata),6G(rootfs)"

# config partition's filesystem type (squashfs is readonly)
# emmc:    squashfs/ext4
# nand:    squashfs/ubifs
# spi nor: squashfs/jffs2
# RK_PARTITION_FS_TYPE_CFG format:
#     AAAA:/BBBB/CCCC@ext4
#         AAAA ----------> partition name
#         /BBBB/CCCC ----> partition mount point
#         ext4 ----------> partition filesystem type
export RK_PARTITION_FS_TYPE_CFG=rootfs@IGNORE@ext4,userdata@/userdata@ext4,oem@/oem@ext4

# config filesystem compress (Just for squashfs or ubifs)
# squashfs: lz4/lzo/lzma/xz/gzip, default xz
# ubifs:    lzo/zlib, default lzo
# export RK_SQUASHFS_COMP=xz
# export RK_UBIFS_COMP=lzo

#################################################
#	TARGET_ROOTFS
#################################################

# Target rootfs : ubuntu(only emmc)/buildroot/busybox
export LF_TARGET_ROOTFS=ubuntu

# SUBMODULES : github/gitee
export LF_SUBMODULES_BY=github

# Buildroot defconfig
export RK_BUILDROOT_DEFCONFIG=luckfox_pico_w_defconfig

#################################################
# 	Defconfig
#################################################

# Target arch
export RK_ARCH=arm

# Target Toolchain Cross Compile
export RK_TOOLCHAIN_CROSS=arm-rockchip830-linux-uclibcgnueabihf

#misc image
export RK_MISC=wipe_all-misc.img

# Uboot defconfig
export RK_UBOOT_DEFCONFIG=luckfox_rv1106_uboot_defconfig


# Kernel defconfig
export RK_KERNEL_DEFCONFIG=luckfox_rv1106_linux_defconfig

# Kernel defconfig fragment
export RK_KERNEL_DEFCONFIG_FRAGMENT=rv1106-bt.config

# Config sensor IQ files
# RK_CAMERA_SENSOR_IQFILES format:
#     "iqfile1 iqfile2 iqfile3 ..."
# ./build.sh media and copy <SDK root dir>/output/out/media_out/isp_iqfiles/$RK_CAMERA_SENSOR_IQFILES
#export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json"
#export RK_CAMERA_SENSOR_IQFILES="sc4336_OT01_40IRC_F16.json sc3336_CMK-OT2119-PC1_30IRC-F16.json sc530ai_CMK-OT2115-PC1_30IRC-F16.json"

# Config sensor lens CAC calibrattion bin files
#export RK_CAMERA_SENSOR_CAC_BIN="CAC_sc4336_OT01_40IRC_F16"
#export RK_CAMERA_SENSOR_CAC_BIN="CAC_sc4336_OT01_40IRC_F16 CAC_sc530ai_CMK-OT2115-PC1_30IRC-F16"

# build ipc web backend
# export RK_APP_IPCWEB_BACKEND=y

# enable install app to oem partition
export RK_BUILD_APP_TO_OEM_PARTITION=y

# enable rockchip test
#export RK_ENABLE_ROCKCHIP_TEST=y

# enable rockchip wifi
export RK_ENABLE_WIFI=y
export RK_ENABLE_WIFI_CHIP=AIC8800DC

# config wifi ssid and passwd
export LF_WIFI_SSID="Your wifi ssid"
export LF_WIFI_PSK="Your wifi password"

В строках 97 и 101 закомментируем использование камеры, а для экономии места в строке 111 отключим тест железа.

С основным файлом конфигурации разобрались, идем дальше по следу. В строке 17 у нас указана ссылка файл конфигурации дерева устройств:

export RK_KERNEL_DTS=rv1106g-luckfox-pico-ultra-w.dts

Давайте и займемся им. Всё это добро у нас лежит по пути:

cd luckfox-pico/sysdrv/source/kernel/arch/arm/boot/dts

А теперь посмотрим содержание этого файла, нам нужно обратить внимание на импорты в начале файла:

nano rv1106g-luckfox-pico-ultra-w.dts

В импортах мы видим следующее:

#include "rv1106.dtsi"
#include "rv1106-luckfox-pico-ultra-ipc.dtsi"
#include "rv1106-thunder-boot-emmc.dtsi"
#include <dt-bindings/input/input.h>
#include <dt-bindings/display/media-bus-format.h>

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

Посмотрим на их содержание.

nano rv1106-luckfox-pico-ultra-ipc.dtsi
Содержание файла

// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
 * Copyright (c) 2022 Rockchip Electronics Co., Ltd.
 */
#include "rv1106-amp.dtsi"
#include "rv1106-evb.dtsi"
#include <dt-bindings/input/input.h>
#include <dt-bindings/display/media-bus-format.h>

/ {
	chosen {
		bootargs = "earlycon=uart8250,mmio32,0xff4c0000 console=ttyFIQ0 root=/dev/mmcblk0p7 rootwait snd_soc_core.prealloc_buffer_size_kbytes=16 coherent_pool=0";
	};

	backlight: backlight {
		status = "okay";
		compatible = "pwm-backlight";
		pwms = <&pwm1 0 25000 12500>;
		brightness-levels = <
			  0   1   2   3   4   5   6   7
			  8   9  10  11  12  13  14  15
			 16  17  18  19  20  21  22  23
			 24  25  26  27  28  29  30  31
			 32  33  34  35  36  37  38  39
			 40  41  42  43  44  45  46  47
			 48  49  50  51  52  53  54  55
			 56  57  58  59  60  61  62  63
			 64  65  66  67  68  69  70  71
			 72  73  74  75  76  77  78  79
			 80  81  82  83  84  85  86  87
			 88  89  90  91  92  93  94  95
			 96  97  98  99 100 101 102 103
			104 105 106 107 108 109 110 111
			112 113 114 115 116 117 118 119
			120 121 122 123 124 125 126 127
			128 129 130 131 132 133 134 135
			136 137 138 139 140 141 142 143
			144 145 146 147 148 149 150 151
			152 153 154 155 156 157 158 159
			160 161 162 163 164 165 166 167
			168 169 170 171 172 173 174 175
			176 177 178 179 180 181 182 183
			184 185 186 187 188 189 190 191
			192 193 194 195 196 197 198 199
			200 201 202 203 204 205 206 207
			208 209 210 211 212 213 214 215
			216 217 218 219 220 221 222 223
			224 225 226 227 228 229 230 231
			232 233 234 235 236 237 238 239
			240 241 242 243 244 245 246 247
			248 249 250 251 252 253 254 255>;
		default-brightness-level = <255>;
	};

	panel: panel {
		compatible = "simple-panel";
		backlight = <&backlight>;

		reset-gpios = <&gpio0 RK_PA1 GPIO_ACTIVE_LOW>;
		reset-delay-ms = <200>;
		status = "okay";

		bus-format = <MEDIA_BUS_FMT_RGB666_1X18>;
		width-mm = <85>;
		height-mm = <85>;

		display-timings {
			native-mode = <&timing0>;

			timing0: timing0 {
				clock-frequency = <30000000>;
				hactive = <720>;
				vactive = <720>;
				hback-porch = <44>;
				hfront-porch = <46>;
				vback-porch = <18>;
				vfront-porch = <16>;
				hsync-len = <2>;
				vsync-len = <2>;
				hsync-active = <0>;
				vsync-active = <0>;
				de-active = <0>;
				pixelclk-active = <0>;
			};
		};

		port {
			panel_in_rgb: endpoint {
				remote-endpoint = <&rgb_out_panel>;
			};
		};
	};

	reserved_memory: reserved-memory {
		status = "okay";
		#address-cells = <1>;
		#size-cells = <1>;
		ranges;
		drm_logo: drm-logo@00000000 {
			compatible = "rockchip,drm-logo";
			reg = <0x0 0x0>;
		};
		linux,cma {
			status = "okay";
			compatible = "shared-dma-pool";
			inactive;
			reusable;
			size = <0xA00000>; //10M
			linux,cma-default;
		};
	};

	acodec_sound: acodec-sound {
		compatible = "simple-audio-card";
		simple-audio-card,name = "rv1106-acodec";
		simple-audio-card,format = "i2s";
		simple-audio-card,mclk-fs = <256>;
		simple-audio-card,cpu {
			sound-dai = <&i2s0_8ch>;
		};
		simple-audio-card,codec {
			sound-dai = <&acodec>;
		};
	};

	dsm_sound: dsm-sound {
		status = "disabled";
		compatible = "simple-audio-card";
		simple-audio-card,format = "i2s";
		simple-audio-card,mclk-fs = <256>;
		simple-audio-card,name = "rockchip,dsm-sound";
		simple-audio-card,bitclock-master = <&sndcodec>;
		simple-audio-card,frame-master = <&sndcodec>;
		sndcpu: simple-audio-card,cpu {
			sound-dai = <&i2s0_8ch>;
		};
		sndcodec: simple-audio-card,codec {
			sound-dai = <&dsm>;
		};
	};

	vcc_1v8: vcc-1v8 {
		compatible = "regulator-fixed";
		regulator-name = "vcc_1v8";
		regulator-always-on;
		regulator-boot-on;
		regulator-min-microvolt = <1800000>;
		regulator-max-microvolt = <1800000>;
	};

	vcc_3v3: vcc-3v3 {
		compatible = "regulator-fixed";
		regulator-name = "vcc_3v3";
		regulator-always-on;
		regulator-boot-on;
		regulator-min-microvolt = <3300000>;
		regulator-max-microvolt = <3300000>;
	};

	vdd_arm: vdd-arm {
		compatible = "regulator-fixed";
		regulator-name = "vdd_arm";
		regulator-min-microvolt = <900000>;
		regulator-max-microvolt = <900000>;
		regulator-always-on;

		regulator-boot-on;
	};

	leds: leds {
		compatible = "gpio-leds";
		work_led: work{
			gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>;
			linux,default-trigger = "activity";
			default-state = "on";
		};
	};
};

/***************************** audio ********************************/
&i2s0_8ch {
	#sound-dai-cells = <0>;
	status = "okay";
};

&acodec {
	#sound-dai-cells = <0>;
	pa-ctl-gpios = <&gpio3 RK_PD3 GPIO_ACTIVE_HIGH &pcfg_pull_up>;
	status = "okay";
};

/************************* FIQ_DUBUGGER ****************************/
&fiq_debugger {
	rockchip,irq-mode-enable = <1>;
	status = "okay";
};

/***************************** USB *********************************/
&u2phy {
	status = "okay";
};

&u2phy_otg {
	status = "okay";
};

&usbdrd {
	status = "okay";
};

&usbdrd_dwc3 {
	extcon = <&u2phy>;
	status = "okay";
};

/***************************** DSM *********************************/
&dsm {
	status = "disabled";
};

&cpu0 {
	cpu-supply = <&vdd_arm>;
};

/*************************** CSI *********************************/
&csi2_dphy_hw {
	status = "okay";
};

&csi2_dphy0 {
	status = "okay";

	ports {
		#address-cells = <1>;
		#size-cells = <0>;

		port@0 {
			reg = <0>;
			#address-cells = <1>;
			#size-cells = <0>;

			csi_dphy_input0: endpoint@0 {
				reg = <0>;
				remote-endpoint = <&sc3336_out>;
				data-lanes = <1 2>;
			};

			csi_dphy_input1: endpoint@1 {
				reg = <1>;
				remote-endpoint = <&sc4336_out>;
				data-lanes = <1 2>;
			};

			csi_dphy_input2: endpoint@2 {
				reg = <2>;
				remote-endpoint = <&sc530ai_out>;
				data-lanes = <1 2>;
			};
		};

		port@1 {
			reg = <1>;
			#address-cells = <1>;
			#size-cells = <0>;

			csi_dphy_output: endpoint@0 {
				reg = <0>;
				remote-endpoint = <&mipi_csi2_input>;
			};
		};
	};
};

&i2c4 {
	status = "okay";
	clock-frequency = <400000>;
	//pinctrl-names = "default";
	//pinctrl-0 = <&i2c4m2_xfer>;

	sc3336: sc3336@30 {
		compatible = "smartsens,sc3336";
		status = "okay";
		reg = <0x30>;
		clocks = <&cru MCLK_REF_MIPI0>;
		clock-names = "xvclk";
		pwdn-gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;
		pinctrl-names = "default";
		pinctrl-0 = <&mipi_refclk_out0>;
		rockchip,camera-module-index = <0>;
		rockchip,camera-module-facing = "back";
		rockchip,camera-module-name = "CMK-OT2119-PC1";
		rockchip,camera-module-lens-name = "30IRC-F16";
		port {
			sc3336_out: endpoint {
				remote-endpoint = <&csi_dphy_input0>;
				data-lanes = <1 2>;
			};
		};
	};

	sc4336: sc4336@30 {
		compatible = "smartsens,sc4336";
		status = "okay";
		reg = <0x30>;
		clocks = <&cru MCLK_REF_MIPI0>;
		clock-names = "xvclk";
		pwdn-gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;
		pinctrl-names = "default";
		pinctrl-0 = <&mipi_refclk_out0>;
		rockchip,camera-module-index = <0>;
		rockchip,camera-module-facing = "back";
		rockchip,camera-module-name = "OT01";
		rockchip,camera-module-lens-name = "40IRC_F16";
		port {
			sc4336_out: endpoint {
				remote-endpoint = <&csi_dphy_input1>;
				data-lanes = <1 2>;
			};
		};
	};

	sc530ai: sc530ai@30 {
		compatible = "smartsens,sc530ai";
		status = "okay";
		reg = <0x30>;
		clocks = <&cru MCLK_REF_MIPI0>;
		clock-names = "xvclk";
		pwdn-gpios = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;
		pinctrl-names = "default";
		pinctrl-0 = <&mipi_refclk_out0>;
		rockchip,camera-module-index = <0>;
		rockchip,camera-module-facing = "back";
		rockchip,camera-module-name = "CMK-OT2115-PC1";
		rockchip,camera-module-lens-name = "30IRC-F16";
		port {
			sc530ai_out: endpoint {
				remote-endpoint = <&csi_dphy_input2>;
				data-lanes = <1 2>;
			};
		};
	};
};

&mipi0_csi2 {
	status = "okay";

	ports {
		#address-cells = <1>;
		#size-cells = <0>;

		port@0 {
			reg = <0>;
			#address-cells = <1>;
			#size-cells = <0>;

			mipi_csi2_input: endpoint@1 {
				reg = <1>;
				remote-endpoint = <&csi_dphy_output>;
			};
		};

		port@1 {
			reg = <1>;
			#address-cells = <1>;
			#size-cells = <0>;

			mipi_csi2_output: endpoint@0 {
				reg = <0>;
				remote-endpoint = <&cif_mipi_in>;
			};
		};
	};
};

&rkcif {
	status = "okay";
};

&rkcif_mipi_lvds {
	status = "okay";

	pinctrl-names = "default";
	pinctrl-0 = <&mipi_pins>;
	port {
		/* MIPI CSI-2 endpoint */
		cif_mipi_in: endpoint {
			remote-endpoint = <&mipi_csi2_output>;
		};
	};
};

&rkcif_mipi_lvds_sditf {
	status = "okay";

	port {
		/* MIPI CSI-2 endpoint */
		mipi_lvds_sditf: endpoint {
			remote-endpoint = <&isp_in>;
		};
	};
};

&rkisp {
	status = "okay";
};

&rkisp_vir0 {
	status = "okay";

	port@0 {
		isp_in: endpoint {
			remote-endpoint = <&mipi_lvds_sditf>;
		};
	};
};

/***************************** ADC ********************************/
&saradc {
	status = "okay";
	vref-supply = <&vcc_1v8>;
};

&tsadc {
	status = "okay";
};

/**************************** LCD/TP ******************************/
&pwm1 {
	status = "okay";
	pinctrl-names = "active";
	pinctrl-0 = <&pwm1m2_pins>;
};

&display_subsystem {
	status = "okay";
	logo-memory-region = <&drm_logo>;
};

&rgb {
	status = "okay";
	pinctrl-names = "default";
	pinctrl-0 = <&lcd_pins>;

	ports {
		rgb_out: port@1 {
			reg = <1>;
			#address-cells = <1>;
			#size-cells = <0>;

			rgb_out_panel: endpoint@0 {
				reg = <0>;
				remote-endpoint = <&panel_in_rgb>;
			};
		};
	};
};

&rgb_in_vop {
	status = "okay";
};

&route_rgb {
	status = "disabled";
};

&vop {
	status = "okay";
};

&i2c3 {
    clock-frequency = <100000>;
    GT911:touchscreen {
      compatible = "goodix,gt911";
      reg = <0x14>;

      interrupt-parent = <&gpio0>;
      interrupts = <RK_PA3 IRQ_TYPE_EDGE_FALLING>;

      reset-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_LOW>;
      pinctrl-names = "default";
    };
};

/**************************** PINCTRL ******************************/
// SPI
&spi0 {
	pinctrl-0 = <&spi0m0_clk &spi0m0_miso &spi0m0_mosi &spi0m0_cs0>;
	#address-cells = <1>;
	#size-cells = <0>;
	spidev@0 {
		compatible = "rockchip,spidev";
		spi-max-frequency = <50000000>;
		reg = <0>;
	};
};

// I2C
&i2c1 {
	pinctrl-0 = <&i2c1m1_xfer>;
};
&i2c2 {
	pinctrl-0 = <&i2c2m0_xfer>;
};
&i2c3 {
	pinctrl-0 = <&i2c3m0_xfer &i2c3m1_xfer &i2c3m2_xfer &tp_rst &tp_irq>;
};
&i2c4 {
	pinctrl-0 = <&i2c4m0_xfer &i2c4m1_xfer &i2c4m2_xfer>;
};

// UART
&uart0 {
	pinctrl-0 = <&uart0m0_xfer &uart0m1_xfer>;
};
&uart1 {
	pinctrl-0 = <&uart1m1_xfer>;
};
&uart3 {
	pinctrl-0 = <&uart3m0_xfer &uart3m1_xfer>;
};
&uart4 {
	pinctrl-0 = <&uart4m0_xfer>;
};
&uart5 {
	pinctrl-0 = <&uart5m1_xfer>;
};

// PWM
&pwm0 {
	pinctrl-0 = <&pwm0m1_pins>;
};
&pwm2 {
	pinctrl-0 = <&pwm2m1_pins &pwm2m2_pins>;
};
&pwm3 {
	pinctrl-0 = <&pwm3m2_pins>;
};
&pwm4 {
	pinctrl-0 = <&pwm4m0_pins &pwm4m1_pins &pwm4m2_pins>;
};
&pwm5 {
	pinctrl-0 = <&pwm5m1_pins &pwm5m2_pins>;
};
&pwm6 {
	pinctrl-0 = <&pwm6m1_pins &pwm6m2_pins>;
};
&pwm7 {
	pinctrl-0 = <&pwm7m0_pins &pwm7m1_pins>;
};
&pwm8 {
	pinctrl-0 = <&pwm8m1_pins>;
};
&pwm9 {
	pinctrl-0 = <&pwm9m1_pins>;
};
&pwm10 {
	pinctrl-0 = <&pwm10m1_pins &pwm10m2_pins>;
};
&pwm11 {
	pinctrl-0 = <&pwm11m1_pins &pwm11m2_pins>;
};

&pinctrl {
	spi0 {
		spi0m0_clk: spi0m0-clk {
			rockchip,pins = <1 RK_PC1 4 &pcfg_pull_none>;
		};
		spi0m0_mosi: spi0m0-mosi {
			rockchip,pins = <1 RK_PC2 6 &pcfg_pull_none>;
		};
		spi0m0_miso: spi0m0-miso {
			rockchip,pins = <1 RK_PC3 6 &pcfg_pull_none>;
		};
		spi0m0_cs0: spi0m0-cs0 {
			rockchip,pins = <1 RK_PC0 4 &pcfg_pull_none>;
		};
	};

	touchscreen {
		tp_rst:tp-rst {
			rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_up>;
		};

		tp_irq:tp-irq {
			rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
		};
	};
};

И тут мы видим, что в секции dsm_sound параметр status = "disabled". Это намекает нам на то, что с данной конфигурацией I2S у нас запустить не получится:

	dsm_sound: dsm-sound {
		status = "disabled";
		compatible = "simple-audio-card";
		simple-audio-card,format = "i2s";
		simple-audio-card,mclk-fs = <256>;
		simple-audio-card,name = "rockchip,dsm-sound";
		simple-audio-card,bitclock-master = <&sndcodec>;
		simple-audio-card,frame-master = <&sndcodec>;
		sndcpu: simple-audio-card,cpu {
			sound-dai = <&i2s0_8ch>;
		};
		sndcodec: simple-audio-card,codec {
			sound-dai = <&dsm>;
		};
	};

Чтобы решить проблему и запустить I2S, нам необходимо подкорректировать файл rv1106-luckfox-pico-ultra-ipc.dtsi, и заодно удалить лишние секции:

  • backlight;

  • panel;

  • reserved_memory;

  • acodec_sound;

  • dsm_sound.

А ещё на всякий случай запретим acodec (аналоговый выход), изменив статус на disable:

&acodec {
	#sound-dai-cells = <0>;
	pa-ctl-gpios = <&gpio1 RK_PA1 GPIO_ACTIVE_HIGH>;
	status = "disable";
};

И так как я провожу эксперименты с ЦАП PCM5102, то добавим в файл конфигурации новое аудиоустройство с именем «PCM5102 Audio»:

    pcm5102_codec: pcm5102-codec {
        compatible = "linux,spdif-dit";
        #sound-dai-cells = <0>;
        status = "okay";
    };

    sound {
        compatible = "simple-audio-card";
        simple-audio-card,name = "PCM5102 Audio";
        simple-audio-card,format = "i2s";
        simple-audio-card,mclk-fs = <256>; // Для внешнего тактирования

        simple-audio-card,cpu {
            sound-dai = <&i2s0_8ch>;
            bitclock-master;
            frame-master;
        };

        simple-audio-card,codec {
            sound-dai = <&pcm5102_codec>;
        };
    };

И заодно скорректируем узел i2s0_8ch, где жёстко пропишем пины I2S-интерфейса:

&i2s0_8ch {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&i2s0m0_sclk_tx>, <&i2s0m0_lrck_tx>, <&i2s0m0_sdo0>, <&i2s0m0_mclk_tx>;
    
    rockchip,clk-trcm = <1>; 
    #sound-dai-cells = <0>;
};

И после этого можно приступать к сборке прошивки модуля.

❯ Собираем прошивку

Данное действие, как я говорил ранее, выполняется на своей виртуальный машине с Ubuntu 22.04.

Настраиваем среду для компиляции с помощью скрипта, согласно Wiki:

cd tools/linux/toolchain/arm-rockchip830-linux-uclibcgnueabihf/
source env_install_toolchain.sh

Для компиляции образа прошивки с Ubuntu в корневом каталоге luckfox-pico выполняем следующие команды:

sudo ./build.sh lunch

Далее будет предложено выбрать версию аппаратной конфигурации — необходимо выбрать [7] custom.

Выбор аппаратной конфигурации

Выбор аппаратной конфигурации

После ввода нам будет предложено выбрать кастомный файл конфигурации. В нашем случае это профиль под номером 3:

Список профилей

Список профилей

После выбора мы получим следующее сообщение:

[build.sh:info] Lunching for Default BoardConfig_IPC/BoardConfig-EMMC-Ubuntu-RV1106_Luckfox_Pico_Ultra_W-IPC.mk boards...
[build.sh:info] Running build_select_board succeeded.

Теперь можно запустить полный процесс компиляции прошивки для нашего модуля:

sudo ./build.sh

После успешного завершения сборки в папке output/images будут доступны файлы образов для загрузки. Получить удалённый доступ к этой папке можно по протоколу SMB.

❯ Тестируем результат

Для тестов я подключил к модулю ЦАП PCM5102 и усилитель PAM8406, которые были записаны от пятивольтовой линии USB порта. И тестовый стенд у меня теперь выглядит так:

Паутина проводов

Паутина проводов

После загрузки модуля необходимо выполнить вход (логин по умолчанию: pico, пароль: Luckfox). Далее нам нужно убедиться в правильности назначения пинов. Для этого в режиме суперпользователя посмотрим содержание файла pinmux-pins:

sudo -i 
cat /sys/kernel/debug/pinctrl/pinctrl-rockchip-pinctrl/pinmux-pins

В моем случае вывод следующий:

Содержание файла pinmux-pins
Pinmux settings per pin
Format: pin (name): mux_owner gpio_owner hog?
pin 0 (gpio0-0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 1 (gpio0-1): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 2 (gpio0-2): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 3 (gpio0-3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 4 (gpio0-4): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 5 (gpio0-5): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 6 (gpio0-6): ff4b0000.serial (GPIO UNCLAIMED) function uart1 group uart1m0-ctsn
pin 7 (gpio0-7): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 8 (gpio0-8): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 9 (gpio0-9): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 10 (gpio0-10): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 11 (gpio0-11): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 12 (gpio0-12): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 13 (gpio0-13): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 14 (gpio0-14): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 15 (gpio0-15): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 16 (gpio0-16): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 17 (gpio0-17): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 18 (gpio0-18): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 19 (gpio0-19): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 20 (gpio0-20): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 21 (gpio0-21): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 22 (gpio0-22): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 23 (gpio0-23): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 24 (gpio0-24): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 25 (gpio0-25): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 26 (gpio0-26): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 27 (gpio0-27): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 28 (gpio0-28): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 29 (gpio0-29): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 30 (gpio0-30): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 31 (gpio0-31): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 32 (gpio1-0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 33 (gpio1-1): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 34 (gpio1-2): (MUX UNCLAIMED) gpio1:34
pin 35 (gpio1-3): ff4b0000.serial (GPIO UNCLAIMED) function uart1 group uart1m0-xfer
pin 36 (gpio1-4): ff4b0000.serial (GPIO UNCLAIMED) function uart1 group uart1m0-xfer
pin 37 (gpio1-5): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 38 (gpio1-6): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 39 (gpio1-7): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 40 (gpio1-8): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 41 (gpio1-9): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 42 (gpio1-10): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 43 (gpio1-11): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 44 (gpio1-12): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 45 (gpio1-13): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 46 (gpio1-14): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 47 (gpio1-15): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 48 (gpio1-16): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 49 (gpio1-17): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 50 (gpio1-18): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 51 (gpio1-19): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 52 (gpio1-20): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 53 (gpio1-21): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 54 (gpio1-22): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 55 (gpio1-23): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 56 (gpio1-24): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 57 (gpio1-25): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 58 (gpio1-26): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 59 (gpio1-27): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 60 (gpio1-28): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 61 (gpio1-29): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 62 (gpio1-30): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 63 (gpio1-31): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 64 (gpio2-0): ffae0000.i2s (GPIO UNCLAIMED) function i2s0_8ch group i2s0m0-sclk-tx
pin 65 (gpio2-1): ffae0000.i2s (GPIO UNCLAIMED) function i2s0_8ch group i2s0m0-lrck-tx
pin 66 (gpio2-2): ffae0000.i2s (GPIO UNCLAIMED) function i2s0_8ch group i2s0m0-mclk-tx
pin 67 (gpio2-3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 68 (gpio2-4): ffae0000.i2s (GPIO UNCLAIMED) function i2s0_8ch group i2s0m0-sdo0
pin 69 (gpio2-5): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 70 (gpio2-6): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 71 (gpio2-7): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 72 (gpio2-8): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 73 (gpio2-9): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 74 (gpio2-10): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 75 (gpio2-11): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 76 (gpio2-12): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 77 (gpio2-13): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 78 (gpio2-14): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 79 (gpio2-15): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 80 (gpio2-16): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 81 (gpio2-17): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 82 (gpio2-18): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 83 (gpio2-19): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 84 (gpio2-20): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 85 (gpio2-21): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 86 (gpio2-22): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 87 (gpio2-23): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 88 (gpio2-24): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 89 (gpio2-25): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 90 (gpio2-26): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 91 (gpio2-27): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 92 (gpio2-28): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 93 (gpio2-29): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 94 (gpio2-30): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 95 (gpio2-31): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 96 (gpio3-0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 97 (gpio3-1): ffaa0000.mmc (GPIO UNCLAIMED) function sdmmc0 group sdmmc0-det
pin 98 (gpio3-2): ffaa0000.mmc (GPIO UNCLAIMED) function sdmmc0 group sdmmc0-bus4
pin 99 (gpio3-3): ffaa0000.mmc (GPIO UNCLAIMED) function sdmmc0 group sdmmc0-bus4
pin 100 (gpio3-4): ffaa0000.mmc (GPIO UNCLAIMED) function sdmmc0 group sdmmc0-clk
pin 101 (gpio3-5): ffaa0000.mmc (GPIO UNCLAIMED) function sdmmc0 group sdmmc0-cmd
pin 102 (gpio3-6): ffaa0000.mmc (GPIO UNCLAIMED) function sdmmc0 group sdmmc0-bus4
pin 103 (gpio3-7): ffaa0000.mmc (GPIO UNCLAIMED) function sdmmc0 group sdmmc0-bus4
pin 104 (gpio3-8): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 105 (gpio3-9): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 106 (gpio3-10): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 107 (gpio3-11): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 108 (gpio3-12): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 109 (gpio3-13): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 110 (gpio3-14): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 111 (gpio3-15): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 112 (gpio3-16): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 113 (gpio3-17): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 114 (gpio3-18): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 115 (gpio3-19): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 116 (gpio3-20): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 117 (gpio3-21): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 118 (gpio3-22): (MUX UNCLAIMED) gpio3:118
pin 119 (gpio3-23): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 120 (gpio3-24): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 121 (gpio3-25): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 122 (gpio3-26): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 123 (gpio3-27): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 124 (gpio3-28): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 125 (gpio3-29): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 126 (gpio3-30): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 127 (gpio3-31): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 128 (gpio4-0): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 129 (gpio4-1): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 130 (gpio4-2): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 131 (gpio4-3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 132 (gpio4-4): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 133 (gpio4-5): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 134 (gpio4-6): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 135 (gpio4-7): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 136 (gpio4-8): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 137 (gpio4-9): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 138 (gpio4-10): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 139 (gpio4-11): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 140 (gpio4-12): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 141 (gpio4-13): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 142 (gpio4-14): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 143 (gpio4-15): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 144 (gpio4-16): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 145 (gpio4-17): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 146 (gpio4-18): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 147 (gpio4-19): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 148 (gpio4-20): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 149 (gpio4-21): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 150 (gpio4-22): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 151 (gpio4-23): (MUX UNCLAIMED) (GPIO UNCLAIMED)

Из вывода видно, что пины для I2S-интерфейса успешно задействованы:

pin 64 (gpio2-0): ffae0000.i2s (GPIO UNCLAIMED) function i2s0_8ch group i2s0m0-sclk-tx
pin 65 (gpio2-1): ffae0000.i2s (GPIO UNCLAIMED) function i2s0_8ch group i2s0m0-lrck-tx
pin 66 (gpio2-2): ffae0000.i2s (GPIO UNCLAIMED) function i2s0_8ch group i2s0m0-mclk-tx
pin 67 (gpio2-3): (MUX UNCLAIMED) (GPIO UNCLAIMED)
pin 68 (gpio2-4): ffae0000.i2s (GPIO UNCLAIMED) function i2s0_8ch group i2s0m0-sdo0

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

pin = bank * 32 + (group * 8 + X)

где значения bankgroup и X берутся из названия пина GPIO{bank}_{group}{X}. Для примера рассчитаем номер пина для GPIO2_A4_d (I2S_SDO):

bank = 2
group = 0 [A=0, B=1, C=2, D=3]
X = 4
pin = 2 * 32 + (0 * 8 + 4) = 68

Всё совпадает, мы получили номер пина, соответствующий значению в файле. Теперь мы можем проверить наличие нашего аудиоустройства с помощью команды:

aplay -L

И если всё удачно сложилось, то мы должны получить следующий вывод в консоль:

hw:CARD=Audio,DEV=0
    PCM5102 Audio, ffae0000.i2s-dit-hifi dit-hifi-0
    Direct hardware device without any conversions
plughw:CARD=Audio,DEV=0
    PCM5102 Audio, ffae0000.i2s-dit-hifi dit-hifi-0
    Hardware device with all software conversions
sysdefault:CARD=Audio
    PCM5102 Audio, ffae0000.i2s-dit-hifi dit-hifi-0
    Default Audio Device
dmix:CARD=Audio,DEV=0
    PCM5102 Audio, ffae0000.i2s-dit-hifi dit-hifi-0
    Direct sample mixing device

Наша звуковая карта успешно определилась. Теперь можно немного «попищать» в динамики, для этого выполним следующую команду:

speaker-test -D hw:0,0 -t sine -f 440 -c 2

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

Ну а чтобы было ещё интереснее, запустим немного кода из моего предыдущего проекта:

У кого нет доступа в YouTube

❯ Подведём итоги

Несмотря на моё желание, чтобы работало всё и сразу, мне понравилось работать с данным модулем — в частности, из-за полной и понятной документации, а также актуального SDK. Ещё один немаловажный момент — это форм-фактор модуля и экономическая составляющая, позволяющие с минимальными затратами интегрировать данную модель в свои проекты.

На этой позитивной ноте можно и закончить статью. Надеюсь, она будет кому-то полезна. Спасибо за уделенное время! Всем добра и успешных проектов! А если есть что добавить — добро пожаловать в комментарии.

Ссылки к статье:

Новости, обзоры продуктов и конкурсы от команды Timeweb.Cloud — в нашем Telegram-канале 

Перейти ↩

Перейти

Может быть интересно: