Привет народ. Как вы могли заметить (наверное 😁) - сайт затих. Причина - на работе я сменил отдел. Плюсы - там уже нормальная ембеддед разработка. Минусы - у меня теперь вообще нет свободного времени (эта статья появилась благодаря моему отпуску).
За время отсутствия здесь - я успел забросить под диван несколько купленных девайсов под новые статьи (которые уже вряд ли когда-нибудь выйдут). И вообще уже рассчитывал надолго забросить сайт, но не тут то было - нашелся кандидат, достойный новой статьи. Так что вот и она - с кучей текста, частыми отступлениями, водой, и субъективщиной - все как обычно😄.
А начиналось все так:
Теща попросила меня купить ей сбер колонку с гигачатом, и все не могла нарадоваться, что он "как живой, и даже понимает и отвечает". Жена глядя на это - тоже захотела колонку. Да и мне чуток захотелось😊. Но вопрос - какую брать? И моё субъективное мнение - не русскую, ибо:
1) Сидение под колпаком:
Шпионят все, это понятно. Но западу без разницы на меня, а нашим - нет. Соответственно, не хотелось бы сесть за неудачную шутку о политике рядом с колонкой. Сбер и яндекс имеют опции типа "слушать всё всегда, чтобы вы потом могли посмотреть о чем говорили" - мда, "удобно". Это конечно же "можно выключить", но что-то мне слабо верится, что оно полностью отключаемо. Ведь так называемая кнопка "отключение микрофона" на этих колонках - просто gpio button, которая просит систему не слушать (а могли бы поставить кнопку с фиксацией нажатия, разрывающую питание цифровых микрофонов).
В добавок учитываем нездоровую любовь наших сервисов к сбору всех данных обо всех + их плотное сотрудничество с властями = получаем довольно опасное сочетание. И опять же, я не занимаюсь чем-то нелегальным, но чую иногда товарищу майору этого факта может не потребоваться.
2) Скудное зацензуренное общение:
Сказал лишнее слово, пошутил немного не так, задел "чувствительную тему" - и гигачат/алиса сразу же прерывают разговор сухими отмазками. Оно понятно, что разработчики не хотят сесть тюрьму, но мне с моей любовью к trash-talk это не подходит.
3) Качество ответов:
Русский ИИ все еще слабый. И это не моё субъективное мнение "так как я поболтал с чатгпт и алисой - и знаю разницу", а реальные тесты на русской арене (на мировую наших не пускают) - яндекс и гигачат разделили 33 место. И вот еще реальные тесты на мере - наши модели на уровне позапозапрошлых моделей от запада (Claude Opus 4.6 порвал всех).
Также нашел slava бенчмарк, но не нашёл первичного лидерборда бенчмарка + вторичные источники противоречат друг другу даже в расшифровке названия slava - так что лесом такие тесты.
Ну и немного отвлекусь на коддиг - с агентным режимом у наших моделей все плохо - его нет. Может быть тогда покодим по старинке без агентного? Тоже мимо - нет никаких тулз для этого, или хотя бы голого api - так что нормального кодинга не будет. А если вы настырный извращенец и готовы к запиливанию велосипеда для ненормального кодинга - то полученное будет кодить на уровне GPT-3.5 - GPT-4o (исходя из этой же ссылки). И коддинг в браузере - все тот же уровень, но еще и годится только для мелочей (ибо модель не может бегать по всему проекту когда захочет).
По итогу:
Нужна альтернатива - колонка с ИИ, который как минимум:
-умный,
-не против поболтать на (почти) любые темы,
-не отправит мои разговоры товарищу майору.
А значит - целимся на западные и китайские ИИ (включая опенсорсные).
Обзор русских ИИ
Но давайте в начале мельком посмотрим на наши ИИ более пристально (нишевое и старое - не рассматриваем). Скипайте раздел если не интересно.
Яндекс (YandexGPT - Алиса) - запилили свою модель на основе весов Qwen (китайская модель от Alibaba), что позволило Грефу потролить яндекс в совете федераций. Яндекс в ответ заявил, что "мы использовали веса Qwen для модели YandexGPT, после чего провели собственный полный цикл обучения на русскоязычных и других данных.". Интересное конечно опровержение - сказать "нет", и тут же подтвердить, что основой реально был qwen, но "обучали мы её сами" - а значит модель наша. Слово "обучали" тут кстати не подходит, ибо они её дообучали (post-training).
Сбер (Гигачат) - изначально пилился на основе ru-GPT3.5, что пилилась на основе весов GPT-3. Далее gigachat стал иметь тесную связь с deepseek, а теперь - заявляют, что практически полностью ушли от связей с deepseek. На huggingface веса кстати выкладывают.
VK (Маруся) - не ИИ, голосовой помощник. По сути свои колонки уже забросили (работают, но обновлений нет).
Кратко про наши ИИ в бизнесе:
VK (Discovery AI) - поисковый ИИ в VK. Честное "на основе LLaMA".
WB (BerryLM) - ИИ WB под их внутрянку. В карточке меры видим честное указание post-training, но не видим на основе чего. Подозреваю что на основе GLM-4.7.
Ибо у BerryLM-XL указано 357-358B, MoE, контекст 202k + chat template который WB отправила в MERA начинается с характерного для GLM [gMASK] и использует <|system|>, <|user|>, <|assistant|>, <|observation|> и тот же формат tool calls - у GLM-4.7 шаблон имеет те же конструкции.
МТС (Cotype) - про позапрошлую Cotype Nano 1.5B честное "на основе Qwen 2.5", про прошлую Cotype PRO честное post-training без указания основы. Про текущую Cotype Light 3/Pro 3 - осторожное "обучаем сами" без упоминания post-training (хотя явно его подразумевают).
Подозреваю, что новая - на Qwen3.5-27B. Ибо Pro 3 вышла 15 июля 2026 года и имеет: 27B + мультимодальность + 262K контекст + MTP. И Qwen3.5-27B имеет: 27B + Vision Encoder + 262,144 context + MTP. Причём даже архитектурные размеры указаны: 64 слоя, hidden size 5120, гибрид Gated DeltaNet/Gated Attention. Соответствие практически зеркальное. 21 апреля 2026 вышел еще и Qwen3.6-27B (тоже 27B, мультимодальная, с тем же 262K-контекстом и той же базовой архитектурой), но я склоняюсь к Qwen3.5-27B, потому что Light 3 вышла 2 апреля, за 19 дней до Qwen3.6-27B.
Т-Технологии (T-pro/T-lite) - честно признают, что на основе Qwen3-8B-Base.
Авито (A-Vibe/A-Vision) - на huggingface признают, что на основе Qwen3-32B.
Альтернатива русским ИИ колонкам
Выделим 4 варианта получения мирового ИИ в колонке (по нарастанию сложности):
1) Китайские колонки с Deepseek и Qwen
Довольно простые мелкие пищалки на ESP с глуховатыми микрофонами. Тем не менее своё дело делают - бесплатный qwen/deepseek (с китайской музыкой) - дают. Речь про самые зрелые и популярные на ESP32-S3/ESP32-C3 девайсы c прошивкой XiaoZhi (прошивки выходят постоянно, есть практически для всех комбинаций девайсов и даже для голых плат). По бюджету - от 1к до 5к:




После покупки - начальные Deepseek и Qwen через китайские сервера доступны сразу. Если хочется подключить нейронку поумнее - поднимай свой сервер-последник, настраивай на нем желаемый API (на OpenRouter например) на выбранные LLM/ASR(SST)/TTS модели (можно еще и CommandLLM/Intent для переключения моделей на лету) - и натравливай свою колонку на свой сервер.
Вопрос - почему просто нельзя этим колонкам скормить OpenAI compatible API например, а приходится сношать себе мозг каким-то промежуточным своим сервером? Ответ - эти ESP32 довольно слабые, так что их максимум - закодировать твой голос в opus, послать его на сервер (твой или китайцев) - и в ответ принять голос модели от сервера, и воспроизвести его.
И на вопрос "зачем тогда эти слабые чипы берут под такое?" ответ: дешевизна, да и в sdk этих ESPшек для ИИ ассистентов довольно многое сделано (аудиофреймворки, wake-word/командное распознавание, примеры подключения к облачным сервисам, большой выбор middleware).
Итог:
Не рекомендую эти игрушки на постоянку, но как дешевая и быстрая замена русских ИИ - вариант. Ну и музычку без своего сервера и колдовства они вам не включат.
Я например для теста взял себе такую с али за 2.5к с сенсорным экраном и батарейкой, и как по мне - оно того не стоит.
2) Западные колонки: Google Nest с Gemini, или Amazon с Alexa.
На авито их немного, но есть. Прайс от 2к до 5к. Но вариант не для всех, и дело даже не в играх с квн и регионами аккаунтов. Дело в языке - на русском гемини говорить отказывается (несмотря на то, что в браузере и на смартфоне на русском разговаривает). В инете можно найти 101 метод русификации, половина из них уже неактуальна, а вторая половина дает частичную и корявую русификацию, слетающую практически при каждом апдейте. Так что для общения на русском - точно плохой выбор.
3) Своя DIY колонка с нуля
Да, своя DIY колонка на ембеддед линукс идет пунктом 3, а не 4. Ибо как по мне - сделать свою сильно проще, чем реверсить и допиливать залоченную чужую без схемы и с экзотической периферией. При создании своей ты сам выбираешь устраивающий тебя SoC, сам собираешь/настраиваешь загрузчики, ядро, рутфс (на основе Buildroot например, или берешь какой-нить дистр), и вендорлоков сам себе не ставишь само собой. И красота - разработка становится разработкой (а не долбежкой с реверсом и костылями).
Про софтовую часть - нормальный совет не дам, ибо ИИ колонки еще не делал, но думал попробовать поиграться с Pipecat, LiveKit Agents, OpenVoiceOS...
Про плату - никто не мешает взять готовую типа апельсинки/малинки/прочее подобное - главное чтоб было аудио, и желательно цифровое (I2S + PDM например). Но я люблю делать платы сам (в KiСad) - это не сложно, не долго, и гораздо компактнее и красивее. И даже если верх твоего мастерства - трассировки плат с простым AVR + мысли о расчете DDR трасс и пайке BGA тебя пугают - это все равно не проблема. Есть чипы со встроенной RAM и не BGA, например - Allwinner T113-s4/T113-s3 (ARMv7/2хA7/1.2 GHz, 256 MB/128MB RAM), или более старые варианты с 64 MB RAM - Allwinner F1C200s (ARMv5) и Allwinner V3s (ARMv7/1хA7/1.2 GHz). Ну или есть вариант посерединке - core плату (с SoC и RAM) берем готовую, но распаиваем её на свою.
Про корпус - тоже можно не рассчитывать/проектировать/печатать самому, а купить с алиэкспресса корпус по запросу типа "DIY Bluetooth Speaker", после чего выкинуть из комплекта штатную bluetooth плату. Например:


4) Хак рандомной колонки с запихиванием любого ИИ
Но все-таки вариант хака рандомной колонки меня привлекает куда больше:
Во-первых: хороший объемный звук (так как за нас уже просчитали корпус с резонансами + выбрали хороший динамик/динамики + может быть даже поставили пассивный диффузор);
Во-вторых: хорошие микрофоны (чаще всего массив цифровых микрофонов);
В-третьих: отсутствие корпусной возни (моё нелюбимое)
В-четвертых: оно и внешне приятней.
Но этот вариант хака я назвал последним не просто так - такого рода девайсы всегда имеют защиты/секурбуты + экзотику в периферии. Так что даже если мы найдем колонку с SoC с хорошим майлайном (или со слитым SDK), то как минимум готовимся к борьбе с secureboot (и без гарантий) и пердолингом при заводе экзотической периферии (тоже без гарантий - на что-то драйвера будут кастрированные и придется допиливать, на что-то придется портировать старые вендорские или вообще портировать хрен пойми откуда, а на что-то их может не найтись и вовсе - и повезет, если в сети окажется слитый даташит, по которому сможем написать хоть какой-то драйвер).
Тем не менее, кто не рискует, тот не пьет шампанское - так что выбираем вариант 4😁.
Хак рандомной колонки
Колонок на авито много - какую покупать под хак?
1) Которую можно хакнуть
Не, я не рофлю😁. Звучит тупо, но это будет главной проблемой на девайсах подобного типа, ибо secureboot и прочие палки в колёса здесь в порядке вещей. Где найти инфу об этом по конкретной колонке? Почти всегда нигде. Максимум - нагуглишь редкий обзор начинки колонки, а далее уже прикидывай сам - что вендор закрыл, как хакать, часто ли вендоры конкретно на этом чипе кладут болт на secureboot, есть ли слабые места в этом secureboot, и так далее.
Так что не купишь - не узнаешь. Но можем сразу отсеять совсем жесткие варианты по secureboot, которые люди уже пытались хакать (и ничего полноценного не вышло) - это колонки от Google и Amazon.
2) Массовую
Есть отличные варианты от xiaomi, но их найти нереально - так что эти единичные экземпляры не считаем.
3) Дешевую
На этом пункте отбрасываем большие колонки от яндекс - за 20к тебе дают дохлый Amlogic 905X2 (что в тв боксы за 2к пихают). Но и совсем шлак на MCU тоже не принимаем - нам нужен linux.
4) С поддерживаемым SoC в майнлайн (или в слитых sdk) + без солянки между моделями
Мы уже ожидаем увидеть солянку китайца-шизофреника из периферии в подобного рода девайсах и готовы к пляскам с драйверами. Но увидеть SoC который не знает майнлайн + на который добрые китайцы не слили SDK - мы не готовы. Так что поиск обзоров с фоточками - обязателен.
Также мы не готовы терпеть кучу моделей под одним именем, иначе офигеем запоминать весь это зоопарк. Так что почти все xiaomi идут в лес.
В остатке имеем - колонки от сбера, от вк, и мини версии яндекс. Рассмотрим линейки, чтобы сделать выбор. Для этого придется побегать по обзорам с разборками колонок, и я это сделаю за вас.
СБЕР
Смотрим:

SberBoom Micro
Amlogic A113L, 128 MB RAM, 128 MB NAND, 2 W speaker, 2.4/5 GHz WIFI + BT 5.
один микрофон, питание 5 В/1 А по USB-C.

SberBoom Mini
Amlogic A113L, 128 MB RAM, 128 MB NAND, 5 W speaker, 2.4/5 GHz WIFI + BT 5.
два микрофона.

SberBoom Mini 2
Amlogic A113L?, 128 MB RAM, 128 MB NAND, 5 W speaker, 2.4/5 GHz WIFI + BT 5.
два микрофона, новый неодимовый динамик.

SberBoom Home
Amlogic A113L, 256 MB RAM, 256 MB NAND, 5 W speaker, 2.4/5 GHz WIFI + BT 5, Zigbee 3.0.
LED-матрица 5×17

SberBoom
Amlogic A113X, 256 MB RAM, 256 MB NAND, 40 W speaker, 2.4/5 GHz WIFI + BT 5.
I2S NTP8835C для НЧ/СЧ и I2S NTP8918 для ВЧ

SberBox Time
Amlogic S905D3, 2 GB RAM, 16 GB NAND, 15 W speaker, 2.4/5 GHz WIFI + BT 5, HDMI 2.0, LAN
тв приставка с механическими часами спереди, не рассматриваем
Видим везде классический для аудио девайсов Amlogic A113L/A113X SoC.
Amlogic A113L - SoC есть в майнлайн, но у него там нет поддержки никакого аудио - ни аналогового в самом SoC, ни интерфейсов для внешнего цифрового (PDM и I2S). Не шибкро проблема, ибо оно есть в виде сорцов вендора в CoreELEC, и портануть в майнлайн более чем реально, хоть и займет время.
Amlogic A113X - в майнлайн все есть, в том числе и аудио. Поэтому в теории, если сбер - то большую 40 ваттную, для более быстрого старта. Но ключевое тут "в теории".
Мне как эмбедеру не нравится сам факт наличия чужого amlogic в девайсе, в том числе и из-за моих субьективных наблюдений по secure boot. Но об этом ниже, а пока что - давайте подробнее про секурити на арм (чтоб в нем не путаться + интересно же):
TrustZone/Secure World появился во времена ARMv6. В чем его суть: есть Normal World - это Linux/U-Boot (UEFI)/обычные приложения, и есть Secure World - это secure monitor/TEE (Trusted Execution Environment)/trusted applications/ключи/secure storage services/DRM/crypto services.
И работает механизм runtime-изоляции: SoC помечает выполнение/транзакции как Secure или Non-secure, и для Secure World может выделить память, периферию и firmware, недоступные из Normal World. Соответственно, скомпрометированный Linux не получает доступ к тому, что есть в Secure World.
Как вы поняли - Secure World не равно Secure Boot - на практике одно может работать без другого, да и цели у них разные: Secure World - не позволяет вещам из Normal World лезть куда не надо, а Secure boot - проверяет подлинность загружаемых компонентов (с помощью публичного ключа/его хеша в OTP в SoC) и не позволяет грузить неподписанный вендором девайса код.
В описываемых выше ARMv8 Secure World и Secure Boot, конечно же, тоже остаются независимыми, но хорошо дополняют друг друга: TrustZone предоставляет аппаратную изоляцию Secure/Non-secure, а TF-A - типовую инфраструктуру для trusted boot/runtime firmware - поэтому secure boot удобно встраивать в эту же boot chain (но корень доверия начинается раньше - с BootROM и с публичного ключа/его хеша из OTP).
Ну и вы наверное заметили, что во времена ARMv7 девайсов с secure boot было мало, а начиная примерно с ARMv8 secureboot стали пихать практически в каждый SoC? Почему так, если Secure World был и там и там? Хочется ответить, что мир стал требовать verified boot, TEE, DRM, key protection... Это конечно же так, но еще одна весомая причина - secure firmware ecosystem раньше была менее унифицированной, а начиная примерно с ARMv8 arm хорошо стандартизировала firmware side - arm trusted firmware стал open-source в 2013, и дал разработчикам SoC типовую reference implementation Secure World + стандартные интерфейсы вроде PSCI, SMCCC а также референсную реализацию Trusted Board Boot. В том числе поэтому на ARMv8 secure boot стал типовым инженерным решением (в отличие от времен разрозненных ARMv7 с вендор BSP) - вот и пихают его почти в каждый ARMv8 SoC.
Эталонный бут TF-A на ARMv8 выглядит так: BL1 > BL2 > BL31 (EL3 runtime firmware) > optional BL32 (Secure payload/TEE) > BL33 (U-Boot/UEFI). При активном secure boot - компоненты проходят дополнительную проверку и неподписанное не запускается. Общий порядок проверки такой: BL1 загружает BL2, BL2 загружает BL31, BL32, BL33 и передаёт BL31 информацию об их entry points > BL31 инициализирует EL3/secure runtime и при наличии BL32 передаёт ему управление, затем передаёт управление BL33. Важная оговорка - verified boot может тянуться так далеко, как решил вендор девайса (хоть до BL2, хоть до linux kernel).
Какие цепочки используют типичные вендоры SoC? Да без особых извращений.
Например Allwinner: BootROM > SPL + ddr init > FIT (BL31 и U-boot + DT (может быть несколько dt и/или uboot)) > Linux.
Или Rockchip: BootROM > idbloader.img (DDR binary + miniloader) > trust.img > U-Boot > Linux. Или опенсорс Rockchip: BootROM > TPL > SPL > BL31 > U-Boot > Linux.
А теперь типичные Amlogic - который переняли многое необязательное из TF-A + еще и добавили свои стадии:
-BL1 (аппаратный бутлоадер в SoC)
-BL2 + ACS и BL21 + ddr firmware - специфичный ранний инит платы + инит памяти
-BL30 (SCP firmware) - прошивка SCP/system-control processor (MCU внутри SoC)
-BL301 (board SCP parameters)
-BL31 (secure monitor) - runtime firmware/secure monitor
-BL32 (optional TEE) -
-BL33 (U-Boot)
-Linux.
(тут BL30/BL301/ACS - не стандартные ступени TF-A).
Нет, Amlogic не сделал 100 стадий secure boot. Причина зоопарка - их любовь разносить SoC init, board-specific параметры и system-management firmware по отдельным бинарникам.
"Историческая справка" закончилась, продолжаем.
Мы обсудили наличие secureboot в каких-либо SoC. Но главный вопрос - об его активации на конкретных девайсах вендором девайса. Выпустил девайс на ARMv8 SoC с фичей secureboot'а, но не захотел её активировать? Окей, можно (привет Xiaomi AX3000T). Но делает так меньшинство вендоров. И, я может быть конечно не прав, но у меня сложилось впечатление, что secureboot на amlogic врубают все кому не лень, даже когда на девайсе secureboot нафиг не уперся, ибо традиция. Почему я так думаю? Потому что даже на китайских подвальных NONAME тв боксах на amlogic я всегда вижу secureboot активированным. Может быть китайцы не хотят чтобы мы ставили кастомы? Нет, им пофиг - они и файл пароля от bl1 скинут при просьбе (если его задавали), и u-boot всегда оставляют с незалоченным шелом и открытым bootloader usb mode, и даже ключ иногда могут скинуть (поэтому проблем со всякими кастомами и с armbian/debian на Vontar'ах у нас и нет). Зачем тогда они включили secureboot? А хрен их знает.
Так что про сбер - гуглим внимательнее. И да, видим, что скорее всего сбер мы не хакнем:
-сбер прямым текстом хвастается про активный секурбут;
-сбер хвастается "защищённой версией прошивки с проверкой целостности исполняемого кода и закрытыми отладочными интерфейсами" + домашними пентестами от своих сотрудников своих девайсов;
-тут народ проверил некоторые колонки - и нашел пароль на аппаратный загрузик в SoC (BL1) только на девайсах сбера (в отличие от девайсов яндекса или вк). Это показательно, и поясняю подробнее почему (для тех, кому лень читать статью по ссылке выше): Amlogic со своим A113X неплохо так обосрался (уж простите), выпилив из sdk фичу задания пароля BL1 + на вопли заказчиков по этому поводу Amlogic отвечал всем что-то типа "в этом SoC пароль на BL1 не задается". Тролли, ведь для A113X он задается - и его можно задать, сделав небольшой реверс + написав немного кода для этого. Как видим из статьи выше - до этого дошел только сбер (в отличие от яндекс и вк) - которые забили болт на отсутствие пароля на BL1 + на дыру в BL1, которая при отсутствии пароля позволяет запустить даже неподписанный код.
В оправдание яндекс и вк - их можно понять - они не посчитали серьезной уязвимостью то, что для дропа в режим BL1 бутлаудера на надо разобрать девайс, замкнуть контакты NAND, подать питание, разомкнуть NAND, подключиться по USB, залить начальные лоадеры в RAM через aml тулы для инициализации RAM/NAND, и только потом бросать свой код в RAM и запускать его. И даже если прошить свой код в NAND - при обычном старте из-за secureboot он не запустится (и при каждом ребуте придется снова руками все запускать через BL1 лаудер по USB). А сбер зачем-то запарился и закрыл даже такую мелочь.
Так что по итогу - думаю что сберу не пофиг, они шарят, и при покупки колонки сбера - я наверное словлю локи везде где только можно. Опять же, пока что ничего не утверждаю на 100%, но при наличии текущих вводных - сбер стоит отложить в самый конец и поискать что-то более лайтовое.
Мелкие колонки яндекса
По ним инфы сильно меньше и нормального списка не сделать. Все что я находил где-либо на редких фото - было на Amlogic A113X, с 256 MB RAM и 256 MB NAND. Так что просто оставлю здесь полный список их колонок, и вернусь к ним потом, если другого улова не будет.


VK
Тут уже зоопарка нет, да и инфа ищется лучше:

VK Капсула Нео
BES2300 (Cortex-M4F 300 МГц), 992 КБ SRAM, 4 МБ встроенной flash, 5 W, 2.4 GHz WIFI + BT
это mcu, а я хочу полноценный linux - так что в лес

VK Капсула Мини
Rockchip RK3308B, 256 МБ, 256 МБ SPI NAND, 5 W, 2.4/5 GHz Wi-Fi + BT 5 (6222B-SRC)
USB-C 9 В, 4 цифровых (PDM) микрофона, динамик на I2S NTP8910A, 7 сегментный экран для часов

VK Капсула
Rockchip RK3308, 256 МБ RAM, 256 МБ TSOP48 NAND (в статье 2 ГБ, но это ошибка), 25 W НЧ/СЧ и 5 W ВЧ, 2.4/5 GHz Wi-Fi + BT 5 (AP6256), RFID
6 микрофонов, звук по ADAC из SoC с аналоговым усилком TPA3116

VK Капсула Про
Инфы нет, но за 10к не очень то и хотелось
65 W, 2.4/5 GHz WIFI, Zigbee, круглый сенсорный IPS экран 480×480, температура/влажность/движение/свет.
Капсулу на MCU не рассматриваем, как и дорогую неизвестную прошку.
А вот мини и обычная большая привлекли моё внимание из-за любимца Rockcip - в большой видим Rockchip RK3308, а в мелкой Rockchip RK3308B. Опять же, моё субъективное наблюдение - многие вендоры на rockchip секурбут обычно не включают😁 (противоположность amlogic получается какая-то, но опять же - эти совпадения ничего не значат).
Чипы RK3308x тоже относится к классу аудио-чипов (со всякими там PDM и I2S). RK3308 имеет хорошую майнлайн поддержку, а у RK3308B в майнайне нет поддержки встроенного в SoC звука, но оно и не надо - в мини звуковая часть на цифре, правда кодек/усилок NTP8910A в майнлайн тоже не поддерживается, но как уже писал ранее - еще и не такую экзотику встретим в девайсах такого класса, и это скорее всего будет не самой большой проблемой.
В общем, не вижу особой разницы между большой и мелкой. По цене на авито разница тоже не шибко большая: 1-2к за мини, против 3-4к за обычную. А значит беру ту, что больше нравится - мини с экранчиком. Она компактная и влезет куда угодно + её звук в сети хвалят.
Осмотр, вскрытие, установка альпайна
Заказал, приехала. Осматриваем:




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


Amlogic A113X?😄 Прикольно, гугл вообще не знает что в капсуле мини он может встречаться (хотя в статье по ссылке выше про отсутствие пароля на BL1 - слова "ВК" и "Amlogic" в одном предложении встречались, так что не прямо так очень сильно удивлен). И NAND видим не SPI, а ONFI TSOP48. Разгадка всего этого в том, что в статье на плате с RK3308B указана ревизия CapsulaDot_Main_V1.0, а на моей c A113X указана ревизия MRC02B_Main_V0.5r1. Также видим плату с type-c и джеком 3.5 - на ней только QC контроллер.


Ну а коль уж колонка уже у меня - давайте её прощупаем:
На плате между SoC и WIFI видим два пятака + слева третий на мелком отдалении - UART? Замер мультиметром показал, что левый - земля. Давайте пока что без всяких анализаторов уровней протестируем в лоб на удачу - берем USB-UART, паяем землю на землю, RX адаптера на второй пятак платы, и на штатных для A113X (да и самых популярных) параметрах 115200n8 врубаем девайс и попробуем увидеть лог старта - и сразу бинго - видим лог старта загрузчиков, u-boot 2015, и стоковую прошивку с вендорским ядром 4.9. Теперь попробуем подпаять TX от USB-UART адаптера на оставшийся пятак и дропнуться хоть куда-то - но фиаско - u-boot не прерывается никакими клавишами, и в стоковой прошивке ввода с serial тоже нет. Окей, давайте попробуем оценить масштаб катастрофы. Анализируем полный лог старта - и видим активный secure boot вплоть до linux ядра включительно. Хорошее начало😅.
С надеждой читаем лог внимательнее, и видим, что при старте u-boot на 450 мс на USB порту поднимает режим бутлаудера. Хм, похоже вендор оставил это для фабричной заливки прошивки и тестирования уже собранных девайсов. Так что ожидаю на type-c увидеть заведенный загрузочный USB из SoC с запароленным режимом бутлаудера. Для проверки этого качаем утилиты общения с загрузчиком A113X - они не опенсорс, а часть вендор sdk, так что в инете видим только слитые бинари (ну и не под любой Amlogic подходит любая - нам нужна умеющая наш axg). Проверяем - и ой, вендор не запаролил режим бутлаудера в u-boot😄. А значит я могу отсылать команды в u-boot по USB. Их вывода я правда не вижу, но вендор же на плате оставил serial + не отключил на него вывод - а значит нам этого хватит - шлем команды по usb, а их вывод видим на serial. Давайте теперь попробуем добиться шелла в u-boot - bootdelay тут не задан, а мы зададим его секунду и сделаем saveenvs - вау, envs сохранились, так как их зачем-то положили на свой nand раздел (вместо захардкоривания в u-boot). Ребут - и нам предлагают тыкнуть space или enter, тыкаем - ой, мы дропнулись в u-boot шел, в котором ввод прекрасно работает по serial😄. Спасибо, так удобнее.
Теперь давайте бекапним сток перед сносом - нам из него потребуется декомпилированный dtb как минимум в качестве "документации" по девайсу. В режиме бутлаудера мы можем на комп дампить участки ram, а содержимое nand через u-boot тоже не проблема кинуть в ram - так что с бекапом проблем не возникло. Осматриваем бекапы: видим разделы со служебной инфой и загрузчиками, два kernel + две rootfs (от слотов a и b), и также раздел data. Видим что вендор не стал шифровать rootfs и data - это ubi контейнеры. Распаковываем data - и видим папку telemetry с архивами dmesg и logread, а также json файлы, а в них - id и api токен от вк бывшего владельца, с точными координатами его дома, и SSID + PSK от его роутера😶. Ребят - вы бы не забывали перед продажей девайсов их в дефолт сбрасывать (включить, после зажигания кольца белым зажать + и - до сигнала), а то на вендора как видим не всегда надежда есть, а значит есть мелкий шанс, что после продажи вашей колонки - к вашему падику прибежит рандомный социопат (по координатам), подключится к вашему роутеру, и устроит треш в вашей локалке с походами на запрещенные сайты с вашего ip. Ладно, сам я эти данные нигде не опубликую (и вообще удалю), и инструкции по их добыче тоже не опубликую (ибо они даже не требуют разборки колонки). Так что забыли короче, идем дальше.
Рутфс у нас тоже есть и это конечно хорошо, только вот dtb лежит в шифрованном кернел разделе, а он для нас как документация по девасу - его нужно расшифровать и декомпилировать. Да и расшифрованное ядро на будущее пригодится, ведь судя по всему - как минимиум в нем лежит карта начальных регистров от кодека-усилка NTP8910A (без которой будет непросто получить звук как на стоковой прошивке). Поразмышляем о расшифровке ядра. При старте ядро прыгает в ОЗУ, расшифровывается, и запускается уже расшифрованным. Все это делается внутри команды bootm. В этом u-boot bootm собрана с максимальным набором параметров, выполняющих разные стадии этой команды (start, loados, prep, go...). Попробуем их по очереди, и проверим - окажется ли на каком-то этапе ядро уже расшифрованным, но еще не запущенным. Если окажется - вытаскиваем. Проверил - расшифровывание идет при bootm go, но так как сразу после этого идет и запуск - способ не рабочий. Окей, значит надо понять что происходит в u-boot в этот момент - так что нам нужны хоть какие-то сливы сорцов. В инете есть какое-то количество сливов, но нет гарантий что они полностью соответствуют нашим. Но мы попробуем, и видим по сорцам, что расшифровка действительно выполняется при bootm go ассемблерной вставкой, и за ней же запуск. Так что берем эту вставку, компилим, кидаем по USB в ОЗУ, закидываем ядро в ОЗУ, запускаем нашу вставку по закинутому адресу - и ой, ядро расшифровано😄. Дампим на комп, и получаем Android boot image (в котором kernel, initrd, и dtb).
Это конечно все хорошо, но как помните - я выше писал, что secure boot на девайсе включен до ядра linux включительно. Да, рутфс тут не шифрован и не подписан, так что рутфс своего дистра мы подсунем и не все потеряно - но получается что мы теперь прибиты к старому вендор ядру с полутора модулями из-за secure boot? У меня закрались сомнения на этот счет, ибо как минимум залитая ассеблерная вставка выше отработала - а значит неподписанный код тут все-таки местами запускаем. Глянем мельком сорцы u-boot чтобы понять, как так вышло - и видим, что подпись проверяется только при старте через команду boom. А вот через booti (которую в этом u-boot тоже оставили) - подпись не сверяется. Проверим - для теста наспех состряпаем майнлайн 6.18 ядро "лишь бы грузилось" с типовым dts для этого soc и минимальной rootfs от alpine в initrd, тестируем - и вуаля, booti запустило наше ядро, и видим на сериал ash шелл от нашего альпайна.
Круто, по сути способ заливки своего дистра со своим ядром найден. Но не без мелких нюансов конечно. Например, booti в этом u-boot не умеет компрессию ядра, а под arm64 как мы помним уже не собираются самораспаковывающиеся zImage (исключение - ARM64 EFI), так что ожидаем вес кастомного ядра в ~15 МБ вместо ~5 МБ. Или еще - наш u-boot старше поля флагов ядра и в него не заглядывает - он считает адрес назначения ядра как SDRAM_BASE + text_offset, а новое майнлайн ядро при сборке пишет в свой заголовок text_offset = 0 и взводит бит 3 (отдавая размещение u-bootу), а так как на этой плате SDRAM_BASE=0, то u-boot пытается перенести ядро в физический ноль (где вместо памяти сидит hwrom), и портит запуск. Решение - в заголовок ядра пишем 0x01080000 адрес, по которому ядро уже и так лежит (тогда арифметика загрузчика попадает в текущее расположение ядра, и "переносом" становится копирование на себя).
Но это все мелочи, которые почти ни на что не влияют. Главное, что пациента все-таки можно исцелить от заброшенной/платной вендорской прошивки, и теперь дело за нами - выбрать дистр и завести всё оборудование колонки. Сначала про дистр: Debian на 256/256 точно не варант - будем ловить нехватку места даже при apt update (256/512 или 512/512 еще куда ни шло). OpenWRT - тоже не вариант, ибо SoC A113X в OpenWRTшных таргетах не значится, а значит поддержку придется пилить самому, что чревато тем, что мне придется держать/обновлять репы с kmod пакетами (а времени и так ни на что нет). Кто у нас там еще из мелких и фичастых дистров есть под многие архитектуры? Альпайн конечно же. Вот его и возьмем.
Теперь про железо - я уже расковырял девайс и готов предоставить нормальный отчет об оборудовании.
VK Capsula Mini:
SoC: Amlogic A113X (ARMv8, 4x Cortex-A53);
RAM: 256 MB DDR3 (ESMT M15T2G16128A-DEB);
NAND: 256 MB TSOP48 (Kioxia (Toshiba) TC58NVG1S3HTA00);
WIFI: Fn-Link K255B-SR SDIO module (Amlogic W1 W155S1 chip);
Звук: NeoFidelity NTP8910A (I2C/I2S, Class-D) с 5 Вт динамиком;
Микрофоны: Массив из 4х штук PDM (идут в SoC);
Экран: На ISSI IS31FL3236A, 4 разряда по 7 сегментов + 2 точки (в dts вендора также видим еще один возможный вариант экрана - на AW21036);
Датчик освещения: ROHM BH1730FVC - измеряет степень видимого и ИК спектра (вендор на основе его данных регулирует яркость экрана);
Сенсорные кнопки: Hynitron CSK05T (4 шт + центр = 5 шт);
LED кольцо под кнопками: 12 адресных светодиодов WS2812B на SPI у SoC;
Jack 3.5: Тоже от канала NTP8910A;
USB type-c: Порт питания, но USB 2.0 в нем тоже разведен;
Питание: 9 V в USB type-c на QC/PD контроллере LDR6328S (но колонка работает и от 5 V компа - правда звук при этом лучше громко не врубать).
Заводим железки:
NAND: Казалось бы, что тут заводить? Майнлайн и контроллер NAND и саму NAND умеет, так что просто собери и зашей ubi контейнер (с ядром и rootfs) с параметрами NAND из лога старта стока (128K/2048/64OOB) + c таким же алгоритмом ECC (мы так делали на девайсах из прошлых статей - и проблем не было). Но нет - записанное из u-boot не понимает собранный майнлайн, и наоборот. Стал копать, и выяснилось, что в майнлайн nand_toshiba.c для этих чипов удваивает OOB - в ID зашито 16 байт на 512, а драйвер делает 32, по итогу майнлайн считает, что запасной области 128 байт вместо 64, и каждый ECC-блок после этого ищется не там, где лежит.
Вторая проблема была уже в майнлайн meson_nand.c: в командное слово контроллера для обычных страниц лезет размер укороченного ECC-блока - это регрессия из-за коммита 04a81b4f9ba1, где перевод в восьмибайтные единицы применили заодно и к этой ветке.
Ну и шаг ECC 512, а не 1024 (хотя режим у вендора назывался bch8_1k).
Итого - u-boot и майнлайн одинаково работают с NAND, и больше нет необходимости для шитья своей ubi rootfs грузить майнлайн с rootfs в initrd.
А ядро с dtb я оставил в raw - в ubi не запихнул, в вендорском u-boot не включили ubi.
WIFI: Драйвера для Amlogic W1 (W155S1) в майнлайн нет, зато есть его сорцы от старого вендор ядра в проекте CoreELEC, но нам его портировать на майнлайн не придется, ибо народ уже это сделал - вот патч, который накладывается на project_w1 - и получаем драйвер для 6.18 майнлайна. Мелочи, что всплыли:
1 - Порядок линковки (aml_sdio перед vlsicomm, иначе "Driver 'aml_w1_sdio' is already registered")
2 - USE_SDIO_IRQ=1 и USE_GPIO_IRQ=0 надо определить оба, потому что выбор идёт через #if/#elif, и без них не компилируется ни одна ветка (драйвер грузится глухим), + CONFIG_HAS_WAKELOCK без которого макросы блокировок не определены вообще (и вызовы превращаются в неразрешённые символы)
3 - MAC. Его вендор берёт из efuse, но #ifdef CONFIG_MAC_SUPPORT включать нельзя: под ним лежит вендорская ветка через wifi_get_mac(), которая только объявлена + WIFIMAC_PATH. Само чтение efuse делает функция efuse_manual_read() - она вне ifdef и работает всегда - её и хватило: те же регистры, соседние слова.
Звук: Для NTP8910 драйвера в майнлане нет, зато есть для NTP8918. Найдя даташит на NTP8910 понял, что отличия между ними минимальны, и можно натянуть драйвер от NTP8918. Так что главной задачей было - выдрать начальную карту регистров из расшифрованного вендор ядра, которая рассчитана под наш динамик/девайс. Нашел, выдрал. Далее словил несколько косяков:
1 - Усилок не отвечает, пока GPIOA_18 не поднят. В стоке оно называется fault-gpios, но вендор делает на него GPIOD_OUT_HIGH и отпускает через 500 мкс после сброса. То есть оно гейтит, а не рапортует о неисправности.
2 - Подтяжки. На i2c3 у платы нет подтяжек, а в dtsi у всех шин стоит bias-disable, поэтому SDA после отпускания не поднимается (и любой адрес читается как неотвеченный).
3 - Ширина слота 32 бита - не для прикола. Уберёшь - axg-card передаст ноль, интерфейс возьмёт ширину сэмпла, 16 бит дадут 1.536 МГц, а усилитель принимает только 2.048, 2.8224, 3.072, 6.144, так что hw_params возвращает -EINVAL. Поэтому задаем 48к * 32 * 2 = и будет 3.072.
4 - Детект наушников. В стоковом dts висит linedet-gpios GPIOAO_4. Перенёс его в драйвер: джек вставлен - динамик глушим софт-мьютом 0x33. Но IRQ_TYPE_EDGE_BOTH этот контроллер не умеет, в INIT_MESON8_COMMON_DATA нет .support_edge_both - поэтому сток и слушает только спад. Сделал как на стоке - после каждого срабатывания разворачиваю триггер на встречный фронт, а фоном идёт медленный опрос для подстраховки на тот фронт, что проскочит в момент разворота.
5 - Громкости. Регистр 0x0C - байт с двойной ролью: 0x00-0x03 команды силовому каскаду, всё выше - громкость, причём у команды b'11 в даташите написано "softmute off", поэтому любая запись громкости прогоняет ту же последовательность и обнуляет 0x33, 0x34, 0x35. Дальше: regmap с кэшем - кодек почистил регистр мимо него, кэш по-прежнему считает что там мьют, и update_bits не шлёт на шину ничего. Итог - двигаешь громкость при вставленном джеке, и динамик оживает - фиксится безусловной snd_soc_component_write. Кстати, 0x35 это ещё и микшерный Playback Switch - и та же последовательность гасит и его - то есть громкость молча снимала мьют, так что еще и возвращаем значение из кэша после записи.
6 - Громкость джека. Разъём 3.5 имеет свой преобразователь с линий I2S, поэтому ни один регистр усилителя до него не достаёт - 0x0C = 0x00 его не глушит, на шине кроме 0x2a вообще никого. Единственное общее место - ослабление до выхода из SoC. Сделал softvol Master над hw:0,0, от -60 до 0 дБ, 101 шаг (всё как у стока). Он двигает динамик и джек разом. Громкость усилителя оставил разовой калибровкой: у стока инициализация ставит туда 0xFF.
7 - Петля для эхоподавления. Оказалось, axg-card создаёт её линк сам и дает ей внутренний сигнал воспроизведения. Маршрут: TDMIN_LB SRC SEL = IN 2, TODDR_B SRC SEL = IN 6, захват на hw:0,2. И приятное: дрейфа между микрофонами и опорой не будет, обе ветки висят на одном hifi_pll от единственного кварца 24 МГц и обе выходят на 3.072 МГц, так что сдвиг между потоками - константа.
Микрофоны: Массив из 4-х PDM цифровых микрофонов подключен к SoC. В майнайн оно уже работает (так что просто включим в dts). Получается один такт pdm_dclk_a14 на две линии данных (на одной линии сидят два микрофона, один отдаёт бит по фронту, другой по спаду - отсюда din0 + din1 = четыре канала).
Кодек dmic-codec в dts - заглушка (у PDM-микрофона нет регистров и шины управления - он просто сыплет поток, но ALSA требует чем-то замкнуть тракт).
Ну и про захват в 16 бит - axg-pdm.c объявлял только S24 и S32. Железо при этом 16 умеет, и помогло case 16: рядом с case 24: и SNDRV_PCM_FMTBIT_S16_LE в маску. Сток кстати писал с микрофонов в 4 канала/16 кГц/S16.
Экран: Судя по dts вендора - в колонке может оказаться как IS31FL3236A, как и AW21036 контроллер экрана. Мой случай - IS31FL3236A, и его поддержка есть в майнлайн. Косяки что словил:
1 - В стоке видим issi,is31fl3236 без "a", но также видим, что он пишет единицу в регистр 0x4B (которого у обычной версии нет). А значит мой вариант все-таки "а". Разница есть: с обычным compatible драйвер молча игнорирует issi,22khz-pwm и оставляет несущую на 3 кГц.
2 - Карту каналов снимал руками - жал по одному каналу и смотрел на панель (она нигде не закодирована, у вендора все метки называются clock-ledN).
Ну и еще по приколу написал драйвер, который одалживает эти каналы у контроллера и дает панель как символьный дисплей. Пишешь строку в message - зажигаются сегменты, заливаешь свою таблицу в map_seg7 - переопределяешь как выглядит любой символ (но точки оставлены светодиодами - они не часть символьной строки).
3 - Яркость. Потолок у стока задан током 10 мА, это поле - SL в регистрах управления 0x26..0x49, у него четыре ступени - IMAX, IMAX/2, IMAX/3, IMAX/4. SL - аналоговый, он задаёт высоту импульса, а ШИМ поверх - режет ширину, так что внутри каждой ступени остаются свои 256 градаций. Сам IMAX задаётся внешним резистором (по формуле 76.05 / R). Так вот, майнлайновый драйвер SL не читает: из дерева он берёт только reg каждого канала и issi,22khz-pwm, а в описании чипа у него enable_bits_per_led_control_register = 1, то есть в регистр уходит один бит разрешения и SL остаётся в 0 (то есть IMAX - максимум). Пришлось немного допилить драйвер, чтобы яркость регулировалась (сделал как у вендора) (дефолт тоже как у вендора - на второй ступени без ШИМа = половинная яркость).
И пару слов про AW21036 - в майнлайн его нет, да и в моей колонке тоже - так что заводить его не стал (но если нужно - можете сами, сорцы от андройда гуглятся).
Датчик освещения: В майнлайн драйвера BH1730FVC нет, но драйвер нагуглился в составе zephyr (rtos) - портанул и завел его. Внутри датчика два фотодиода: DATA0 - видит видимый свет плюс ИК, DATA1 - только ИК. Ни один сам по себе не освещённость - люксы получаются вычитанием взвешенного DATA1 из DATA0, причём вес выбирается по их отношению (так компенсируется тип источника - лампа накаливания даёт большой ИК-хвост при мелком видимом свете, люминесцентная и светодиодная почти не даёт, а солнце посередине). Так то без второго диода лампа бы читалась ярче, чем воспринимает глаз. Также:
В таблице коэффициентов при малой доле ИК множитель у DATA1 больше двух (вычитается больше, чем измерено) - не ошибка, а подгонка под кривую чувствительности глаза.
Ну и в zephyr драйвере член времени интегрирования перевёрнут (на настройках по умолчанию ошибка невидима - вылезает когда кто-то трогает время интегрирования).
По итогу - наружу драйвер отдает три величины: обработанные люксы и оба сырых канала.
Сенсорные кнопки: Вот это реально треш - драйвера под CSK05T нет нигде вообще, и единственное что удалось найти - статью на китайском, где автор ноет, что чип фуфло и он слил месяц, чтобы заставить его работать. По итогу в статье он дает страницы даташита с картой регистров + сорцы с примерами. Для написания драйвера этого хватило. И так как всю грязную работу делал он - перечислю косяки которые он словил:
1 - Чтение регистра - не комбинированная транзакция - пишешь адрес, отпускаешь шину со STOP, ждёшь 30 мкс и только потом читаешь. По итогу repeated START не работает вообще, и это вычёркивает regmap-i2c (он генерит ту транзакцию, которую чип не переваривает). Так что в драйвере голые i2c_master_send и i2c_master_recv.
2 - Чип может подняться несконфигурированным, теряет настройки на любой помехе, и после этого молча отвечает "ничего не нажато". Лечится так - каждую запись конфига читаешь обратно и сверяешь, весь init повторяешь с растущей паузой, а регистр управления сканированием проверяешь на каждом опросе - если обнулился, переконфигурируешь на ходу. Ну и прерывание не используешь, хотя пин INT есть, регистры под него есть - но автор пишет, что ничего с него так и не дождался.
В общем, спасибо китайцу. Ну а карту каналов по классике снял руками - жал кнопки поочереди и смотрел, какой бит шевельнулся.
LED кольцо под кнопками: Это классические адресные светодиоды WS2812B, что висят на SPI у SoC - 12 штук змейкой по кольцу. Так что в теории - изи - просто пиши нужные байтики в /dev/spi*, и кольцо раскрасится (SPI у SoC поддерживается в майнлайне). Но на практике - всплыли косяки:
1 - Первый кадр доезжает, все следующие уходят в никуда: кольцо держит первую "картинку" до снятия питания. Причина - в делителе частоты SPI. Он живёт в регистре ENH_CTL0, который контроллер забывает при выключении, а unprepare_transfer() выключает его после каждого сообщения. Ядро clk об этом не знает: частота у него закэширована, поэтому clk_set_rate() в подготовке следующей передачи решает, что менять нечего, и регистр больше никогда не пишется. Итог - один кадр после привязки уходит на 3.34 МГц, а всё остальное летит на том, что даёт обнулённый делитель. Лечится ребайндом драйвера перед кадром + короткой затравочной транзакцией на другой частоте: она ломает кэш, рабочий кадр видит изменение, и перепрограммирует делитель (короче обход бага драйвера, не решение).
2 - Обычный write() в spidev рвёт кадр каждые 16 байт. Он уходит с bits_per_word = 8, а spi-meson-spicc шлёт такое PIO-бурстами по одному FIFO - 16 слов, то есть 16 байт. Между бурстами тактирование останавливается, и драйвер сам закладывает на паузу до 10 мкс. Этого мало, ибо до 50 мкс не дотягивает (которые чип считает концом кадра), поэтому перезапуска не происходит - просто теряется бит, который был в полёте (и всё после него съезжает). Безразрывный путь один: bits_per_word == 64 включает DMA и отдаёт кадр железу одним куском. Достучаться туда можно только через SPI_IOC_MESSAGE (отсюда и необходимость писать утилиту на C, вместо башовских echo > /dev/spidev0.0).
3 - На простаивание линии между кадрами полагаться нельзя, но при конец кадра - должна быть тишина на линии. Что делает MOSI после конца транзакции - из userspace не видно - выходом пада распоряжается драйвер SPI. Поэтому нули надо слать явно и внутри той же транзакции: 128 байт до данных и столько же после. Почему 128, а не "столько, чтобы получилось 50 мкс"? Потому что оригинал WS2812B просит 50, V5 и клоны просят 280, а что в кольце по факту - фиг его знает. Так что шлем 128 нулей на 3.34 МГц - это 306 мкс.
4 - Порядок байт. В PIO драйвер кладёт первый байт буфера в младший байт слова FIFO, а сдвиговый регистр гонит со старшего бита, так что слово вылетает задом наперёд. В DMA такой упаковки нет: память течёт в 32-битный FIFO, а сдвигатель берёт 64-битными кусками, и какая половина уходит первой - по коду не видно. Выяснилось визуально: переворот целыми 64-битными словами зажигает верный цвет и верный диод.
5 - Кодирование. На 3.34 МГц (частота из стока) один бит SPI - 299 нс, четыре складываются в 1.20 мкс при требуемых 1.25. Ноль это 1000, единица 1110. Два бита данных ложатся в один байт SPI, так что кодировщик - таблица на четыре записи, и ничего не съезжает через границу байта.
Ну и про яркость. Сток выставляет всем 36 каналам яркость наполовину (0x7f ) - это же по умолчанию и я выставил в утилите. Но ограничения тока нет ни в стоке, ни у меня. Двенадцать диодов при белом свете на полной тянут 700 мА.
USB type-c: Объявил его в dts как peripheral + завел на нем CDC-ACM гаджет для serial консоли + CDC-ECM гаджет для usb-сетевой (для аварийной связи с компом). Оно уже из коробки в майнлайн, надо просто включить.
По итогу:
Имеем полностью работающий Alpine 3.24.1 с майнлайн ядром 6.18.44.
Образ, флешер, и мануал - скачать можно тут (или из меню сайта).
А сорцы ядра с описанными выше наработками выложил на гитхабе тут.
А на сегодня пожалуй все.
Что делаем во второй части? Очевидно то, ради чего все и затевалось - свою прошивку c веб интерфейсом для колонки, которая позволит добавить свой API токен от OpenRouter и получить в колонке любой мировой ИИ с возможностью горячего переключения (ChatGPT, Claude, Gemini, Grok, Deepseek, Kimi, Qwen, GLM...), + также запилим включение радио через Radio Browser, включение своей музыки с локальной шары, и генерацию музыки через suno api. И может что-нибудь еще. Ну и проверим адекватность/допилим AEC (акустического эхоподавление) - чтобы даже во время музыки колонка хорошо слышала наш голос.
Не знаю когда будет вторая часть, может быть в следующий отпуск... Когда следующий отпуск пока что тоже не знаю 😄. Так что пока что можете сделать как я - запилите несколько простых скриптов для одной любимой ИИшки и купите парочку LLM/SST/TTS API. Ну или можете сделать WIFI радио/сетевой плеер, повесив на кнопки управление через triggerhappy.
Ну и по традиции напоследок,
Мини FAQ:
Q: Хочу купить такую же колонку - как понять что колонка на Amlogic, а не на Rockchp?
A: Только покупкой и проверкой.
Q: А что по поводу колонки на Rockchip?
A: У меня меня её нет (и не было), и смысла её брать второй особо не вижу. Кастомов в инете под нее тоже не вижу. Сам вряд ли буду её покупать и что-то под нее пилить.
Q: Из-за чего установка альпайна на такой закрытый девайс с secureboot стала возможна?
A: Из-за того, что в ВК не очень внимательно настроили u-boot + не внесли в него пару мелких фиксов.
Q: Может ли ВК выпустить апдейт прошивки, в котором u-boot пофикшен?
A: Может.
Q: Выпустит?
A: Вряд ли, ВК капсулы заброшены.
Q: А если все-таки выпустит - то все, прощай альпайн?
A: Нет, как помните из ссылки на статью с хабра про A113X выше - ВК не поставили пароль на USB лаудер в BL1, + в A113X BL1 есть баг, который позволяет запускать неподписанное = такая комбинация позволит запустить что угодно неподписанное в любом случае.
Q: А если с новым апдейтом этот пароль они поставят?
A: Не поставят - он пишется amlogic утилитой по USB в OTP SoC. Не поставили до продажи = не поставят уже никогда.
Q: То есть при выходе "теоретического будущего апдейта с фиксом" - альпайн в любом случае можно будет запускать, но делать это придется с USB?
A: Можно будет запускать не только с USB - его можно будет прошить на NAND как и раньше. Ведь ничего не мешает через BL1 USB бутлаудер прошить прошлый дырявый u-boot в NAND.
Q: А запретить старт более старого u-boot они могут?
A: Не могут. Ибо ключи secureboot уже прошиты в OTP SoC - а значит подписать новый u-boot новым ключом + отозвать ключ старый - они не смогут = работать будут оба u-boot в любом случае (и фикшенный, и дырявый старый).
Q: Коль уж задание пароля на лаудер в BL1 ВК уже проморгали - может быть они выпустят апдейт BL1, который закроет дыру amlogic с запуском неподписанного?
A: Не выпустят, ибо BL1 - аппаратный загрузчик в SoC, и он необновляем. Но даже если бы в теории этой дыры с запуском неподписанного не было (а был бы только отсутствующий пароль) - нам бы это все равно не помешало. Мы бы подсунули в BL1 USB лаудер - лаудеры + старый дырявый u-boot - и оно бы стартануло (так как фиг подписано), а далее мы бы дропнулись в шел этого u-boot, и снова бы прошили его в NAND (с другими старыми лаудерами).
PS: Купил по приколу вторую ВК капсулу мини на авито - железо оказалось один в один.
