Сегодняшняя статья – не восклицание: «Смотрите, какой мне красивый проц попался». Это скорее просто упорядочивание накопленных сведений о конкретном процессоре CH579. Вдруг кому пригодится. Ну, и, если через годы мне потребуется, я сам буду восстанавливать знания по этой статье. Просто так получилось, что по проекту Заказчик велел освоить его… Это недорогой микроконтроллер на базе ядра Cortex M0. После освоения Заказчик же и сказал, что мы всё будем делать на китайском клоне STM32. Характеристики же самобытного CH579 он признал недостаточными.
Но с другой стороны… Сегодня эта микросхема стоит 120-150 рублей за штуку на Ali Express. А у неё имеется не только встроенный PHY для десятимегабитного Ethernet, но и всё для работы по BLE. По-моему, не самая плохая цена. Кажется, для Интернета вещей может пригодиться. Но это цены за микросхему. Макетки безобразно дороги.
Ещё на многих форумах народ возмущается, что сетевая библиотека для этого контроллера поставляется не в виде исходных кодов. Китайцы отвечают, что они не собираются ничего менять. Наш Заказчик тоже возмущался. Поэтому в статье я покажу, каким путём мы шли, чтобы сделать исходный код. Любой сможет повторить этот путь буквально за пару дней. Там скорее обидно, чем сложно.
В общем, сегодня мы пробежимся по работе с китайским контроллером CH579. Будет немного практических сведений и немного мемуаров, как пришлось вскрывать библиотеки.
1. Включаем JTAG
Я не люблю современные процессоры, которые невозможно интерактивно отлаживать. Был у меня цикл статей, в которых я рассматривал просто обалденную макетную плату… Но в итоге, я её забраковал именно за то, что разработчик принципиально не вывел разъём JTAG. Мало того, он сделал всё, чтобы никто к этому каналу не подключился. Ну и как хочет! Хоть процессор и сверхмощный, а библиотеки там – очень вкусные, но без интерактивной отладки работа превращается в мучение. Ссылки на тот цикл – под катом.
Подключив макетку с CH579, я очень испугался, что меня ждёт что-то такое. Причём отладочный порт-то на ней имеется. Но он не работал. Порывшись по форумам, я узнал, что китайские производители очень переживают, как бы мы, пользователи не убили контроллер, именно поэтому они отключили потенциально опасный порт… Но дали возможность включить его.
Самый простой путь – найти программу WCHISPTool и всё сделать в ней… Правда, самый-то он самый, но помучиться всё равно придётся. Не знаю, как сейчас, а осенью, когда я вёл работы… Заходим на страничку, посвящённую контроллеру CH579, скачиваем оттуда WCHISPTool… И получаем старую версию, у которой нужный нам пункт меню всегда отключён. К счастью, программа универсальна, поэтому её можно скачать и со страниц других контроллеров той же фирмы. Точно работает версия 3.3.
Подключаем макетку через имеющийся на ней порт USB при зажатой кнопке Program (только так, нажать Program и стукнуть по Reset, как это сделано у большинства производителей, тут не сработает). Программа сразу определяет, что появилось устройство, готовое к прошиванию. Никаких действий для этого от нас не требуется.
Чтобы включить JTAG, надо взвести флажок Enable Sumilat Interface (орфография оригинала сохранена). В старых версиях программы этот флажок всегда серый, взвести его было нельзя. В версии 3.3, он активен.
Взвели – появилась новая кнопка. В ней уже орфография более привычная.
Нажимаем её, даём согласие на выполнение действий… Всё! Теперь можно прошивать и отлаживать кристалл через отладчик SWD. Ура! Но работа через ISP (In System Programming, то есть, через разъём USB на макетке) не пропадает. Конкретно сейчас мы с коллегой осваиваем работу с BLE, и заливаем скачанные с GitHub готовые HEX файлы именно силами ISP. То есть, наличие SWD не запрещает работу через ISP. Больше вариантов, хороших и разных!
2. Выбор отладочного адаптера
Сами китайцы поставляют готовые примеры, которые могут быть собраны и отлажены в среде Keil через любой адаптер. Вот тут я работаю через старый добрый ST LINK:
Отладка первого попавшегося китайского примера прекрасно идёт:
Всё здорово, кроме одного. Наш Заказчик любит Linux. А Keil может работать только под Windows. Ну, и открытый исходный код наш Заказчик любит. Поэтому пришлось искать другую конфигурацию. К слову, мне самому Keil вполне нравится, но китайские примеры, работающие с Bluetooth, в разы превышают бесплатный размер 32К кода. Так что даже в этом случае будет нужно что-то бесплатное.
При поиске альтернативного решения в голове надо держать две независимые задачи. Отладка – ну, у нас ядро Cortex M0. Отлаживать можно через тот же OpenOCD и любой поддерживаемый им адаптер. Но беда в том, что перед отладкой, код надо «прошить» во флэш. А процесс прошивки хоть и хорошо документирован, но совершенно не совместим с прочими контроллерами. То есть, близок локоть, да не укусишь. Нет в том же OpenOCD готового загрузчика, который бы залил код во флэшку. По крайней мере, на момент работ (осень 2022) не было.
Большинство форумов пестрит идеей: «Напишите свой загрузчик за пару дней, да внедрите в OpenOCD». Идея абсолютно верная и стопроцентно выигрышная, но Заказчик часы на эти работы не одобрил (пара дней-то — пара дней, но это при наличии опыта написания загрузчиков, так что с учётом накопления опыта, вышло бы чуть больше). Поэтому вычёркиваем.
В целом, производитель предлагает среду разработки MounRiver Studio, которая является доработкой Eclipse и позволяет вести отладку через тот же адаптер WCH-Link. Но так получилось, что никто не подумал, что без этого адаптера не обойтись, поэтому он не был заказан ни нами, ни Заказчиком, а сроки поджимали.
Оказалось, что OpenOCD внутри этой среды модифицирована. И если найти её исходники, то выяснится, что при работе с CH579 там жёстко вбиты USB-команды именно от адаптера WCH-Link. Менять нельзя. По крайней мере, осенью было так. Если что – исходники живут тут, все желающие могут перепроверить мои слова: GitHub — kprasadvnsi/riscv-openocd-wch: OpenOCD source code for CH32V series MCUs released by Mounriver IDE.
Можно было взять готовый загрузчик флэша из этого кода, но модифицировать его так, чтобы он попадал в контроллер через любой JTAG/SWD адаптер. Если бы Заказчик одобрил часы, разумеется… Но был найден более интересный вариант. В целом, его суть описана тут: iot-fan_at_cnblogs: iot-fan 在cnblogs 的档案仓库 — Gitee.com.
Там рассказывается, как модифицировать конфигурационные файлы программной поддержки адаптера JLINK. Там же странице есть готовые двоичные файлы загрузчиков, на которые ссылаются модифицированные конфигурационные файлы. После того, как файлы на диске модифицированы, JLINK начинает работать с контроллером CH579 без каких-либо проблем. Вот при такой конфигурации, обычная Eclipse начинает процесс прошивки и отладки:
А так как JLINK – универсальный отладчик, проблему можно объявить решённой. У меня этих адаптеров три штуки, разных версий. У Заказчика он тоже имеется.
Итак, кроме весьма специфичного WCH-Link, отлаживать можно или в Keil через любой адаптер, или через JLINK, немного модифицировав ему конфигурационные файлы. Ну, а JLINK понимают многие среды разработки. На всякий случай, полный архив с необходимыми файлами и подробной документацией, можно скачать здесь.
3. Библиотеки
Ну, ладно. Мы теперь уверены, что сможем загрузить и отладить «прошивку». А раз так, то можно начинать её делать. Если использовать Keil, то просто ставим в него пакет для поддержки нашей системы да начинаем открывать примеры. Это не тема для статьи на Хабре. В статье на Хабре должно быть что-то этакое. Вот наш Заказчик хотел кроссплатформенную работу, о ней и поговорим. В целом, процессорное ядро там Cortex M0, так что подойдёт любая среда разработки, которая умеет собирать код под него. Скажем, Eclipse.
Интереснее, как подключить заголовочные файлы, описывающие оборудование. Есть такой репозиторий на GitHub: GitHub — SoCXin/CH579: S4 L2 R3: WCH Cortex-M0 ETH/BLE SoC(CH579/CH578/CH577). Всё можно добыть на нём. В частности, код для работы с аппаратурой живёт тут.
Рядом есть также startup код, скрипт компоновщика и другие полезные вещи:
Startup файл там специфически, от Кейла, но они все похожи. Отличие обычно состоит в перечне векторов прерываний, можно просто скопировать их отсюда в любой другой типовой от вашей любимой среды, оставив остальное прежним. В качестве основы, подойдёт любой Startup от процессора на базе Cortex M0.
Мы с некоторых пор вообще заменяем все ассемблерные startup файлы сишным вариантом. Дело в том, что при включённой опции Link Time Optimization (LTO) вектора прерываний, описанные в ассемблерном Startup файле, плохо перекрываются нашими собственными версиями.
Добавляешь свой – не забудь закомментировать исходный. Неудобно. Пробовал искать решения – все про проблему пишут, но никто не говорит, как её решить. А кто говорит — те решения не помогают. Weak-функции же, написанные на чистых Сях прекрасно перекрываются хоть при отключённой, хоть при включённой опции LTO. В этом случае даже тип процессора не важен. Только специфичные вектора прерываний помещаем (как я уже сказал, их мы берём из того Кейловского startup кода), а остальное компилятор подгонит по месту сам.
4. Работа с Ethernet
4.1 Общие сведения
Ну всё. Хоть через Keil, хоть через иную среду разработки, совместимую с OpenOCD или JLINK, мы можем работать. Пора приступать к поставленным задачам. А задача была простая – освоить работу с протоколом UDP, причём всенепременно так, чтобы всё было с исходным кодом. Прекрасно! Вернее, не совсем прекрасно. Возвращаемся к рисунку с перечнем выданных нам аппаратных библиотек и не видим там ничего, связанного с сетью. В заголовочных файлах тоже ничего не встречаем. Но вот же целый каталог сетевых примеров!
Как же они работают с сетью? А вот так:
Все сетевые функции поставляются в виде закрытой библиотеки! Заглянем внутрь:
Добрые китайцы собрали для нас библиотеку lwIP… Библиотека, конечно, мощная и надёжная. Но обратной стороной универсальности получаем хорошую среднюю оптимизацию, но не пиковую. Чтобы выжать все соки, библиотека обычно конфигурируется на уровне исходного кода, который нам не выдан.
Ну, а для нашего семейства проектов, для повышения эффективности даже была разработана собственная UDP-библиотека, работающая с нулевыми копированиями. Именно её адаптация и является конечной целью работы.
В общем, если выше я жаловался на то, что Заказчик не согласовывал часы на разработку собственных загрузчиков, так как считал, что надо найти готовое решение, то вот тут – наоборот. Готовые решения совершенно неприемлемы для него. Отлично! Лезем смотреть, что к чему.
4.2 Где черпаем вдохновение
Документация на Ethernet у STM32 занимает много страниц. Вот я сейчас проверил. Для STM32F4 – целых 118 листов. Число регистров там просто зашкаливает. Число возможных комбинаций настроек – просто запредельное. При этом, там совершенно ничего не говорится про микросхему PHY. Её документацию надо изучать отдельно. Чтобы неподготовленному человеку всё понять, нужно потратить много времени и провести массу экспериментов.
Для CH579 же картина совершенно другая. Весь уровень Ethernet, включая работу с PHY, описан на семи листах. Обладая сегодняшними знаниями, я скажу, что описание там вполне себе достаточное. Но на поиск некоторых вещей ушло бы достаточно много времени, поэтому было решено осмотреть фирменную библиотеку изнутри.
В быту я люблю дизассемблер IDA, но тут не быт, а работа. В общем, чего-то захотелось поиграть в Гидру. Во-первых, она официально бесплатная, а во-вторых, на выходе там можно получить набор Сишных функций, так как у неё первичен не дизассемблер, а декомпилятор. Отчего бы не попробовать? В целом, кто хочет сделать быстрый старт, я нашёл очень полезное видео, которое показывает, как же эту Гидру установить и запустить: https://www.youtube.com/watch?v=Vm_VDJ5nxDk
4.3 Осмотр библиотеки
Как оказалось, библиотека внутри имеет многоуровневую структуру. Есть уровень, обслуживающий работу с железом, есть промежуточный уровень, а уже lwIP находится поверх него. Ну и замечательно! Нам надо только подглядеть инициализацию, да приём с передачей. Это всё живёт тут:
Остальные объектные файлы находятся на более высоком уровне и обращаются к функциям из модуля eth.o. Ну и замечательно! Смотрим его!
Там сразу видны функции, которые нам предстоит разобрать:
Код каждой функции занимает экран-другой. И сравнивая их с документацией, мы сразу видим, что именно авторы документации нам недосказали.
4.4 Очередь приёма
Кто работал с Ethernet в STM32, тот знает, что там как передача, так и приём могут обслуживаться в режиме очереди. Причём на передачу я не видел, чтобы кто-то её использовал, а вот на приём – да. Выделяется память, адреса буферов кладутся в дескрипторы, дальше прикладной уровень потихонечку входящие данные обрабатывает, а аппаратура в это время ведёт приём следующих пакетов. Красота!
В CH579 такой красоты нет. Давайте посмотрим на примере приёмного буфера. Он один, и всё тут!
Заглянув в библиотеку, мы выясним, что очередь организуется чисто программно. Внутри обработчика события «пришёл пакет» (а это событие вызывается из обработчика прерывания) мы видим такой код:
void CH57xMACRxSuccHandle(void)
{
int iVar1;
uint uVar2;
*(undefined4 *)(RxCtrl + RxCtrl._184_4_ * 4) = 2;
/* Receive Length Register */
*(uint *)(RxCtrl + RxCtrl._184_4_ * 4 + 0x3c) = (uint)_R16_ETH_ERXLN;
iVar1 = CH57xCfg;
*(undefined **)(RxCtrl + RxCtrl._184_4_ * 4 + 0x78) = &CH57xMACRxBuf + CH57xCfg * RxCtrl._184_4_;
RxCtrl._188_4_ = RxCtrl._188_4_ + 1;
RxCtrl._184_4_ = RxCtrl._184_4_ + 1;
uVar2 = (uint)(byte)RxQueueEntries;
if (uVar2 <= RxCtrl._184_4_) {
RxCtrl._184_4_ = 0;
}
*(undefined4 *)(RxCtrl + RxCtrl._184_4_ * 4) = 1;
if (uVar2 * 3 < RxCtrl._188_4_) {
RxCtrl._188_4_ = uVar2;
}
RxCtrl._192_4_ = 1;
_R16_ETH_ERXST__R32_ETH_RX = (short)iVar1 * (short)RxCtrl._184_4_ + 0x1008;
return;
}
В течение функции вычисляется адрес нового приёмного буфера, а последняя строка – настраивает аппаратуру на новый адрес. Проблемы «Не успеем настроиться, а новый пакет уже поедет» не возникает. Сеть десятимегабитная, времени на переключение у нас достаточно. Кстати, обратите внимание, адрес – шестнадцатиразрядный! Так что буфер может располагаться только в ОЗУ. То же касается и буфера на передачу, так что константы из области кода посылать нельзя.
4.5 Больно умный декомпилятор
Будьте осторожны. Гидра будет что-то додумывать за вас. Взял я, не глядя, код инициализации. Собрал, запустил – не работает. Полдня пробился, пока заметил. Вот так выглядит код, полученный от Гидры с настройками по умолчанию:
А вот так – дизассемблированный код, из которого он получился:
И только сильно ниже имеется:
movs r3,#0x0
strb r3,[r1,#0x0]=>R8_SAFE_ACCESS_SIG
Перед нами ни что иное, как выдача в аппаратуру хитрого пароля, открывающего на некоторое время особо критичные порты на запись. Надо послать именно последовательность 0x57, 0xa8. Тогда ряд портов откроется. А закроются они хоть после записи любого другого значения в порт R8_SAFE_ACCESS_SIG, хоть по прошествии скольки-то там тактов. А наш код сразу туда кладёт ноль. Нет пароля – нет настройки ряда портов. Вот ничего и не работает! Почему так вышло?
Этот больно умный декомпилятор понимает, что первые два занесения констант 0x57 и 0xa8 не нужны. Он считает, что нужна только последняя запись в переменную. Я бы ещё понял, если бы мне это сказал компилятор, да и то при ненулевом уровне оптимизации… Но тут… Тут декомпилятор! Какое твоё декомпиляторово дело? Восстанавливай мне логику программы и не выделывайся! Но нет.
В общем, пришлось области портов присвоить дополнительный атрибут volatile. Выкидывать строки Гидра перестала, но зато восстановленный код стал выглядеть вот так:
Читаемость просто нулевая! Ну, да ладно! Для случая, когда у нас функции занимают один-два экрана, можно потерпеть. Но в целом – я возмущён. Только кто меня спрашивает?
Собственно, после того, как функции инициализации, чтения и записи (а функция чтения частично живёт в обработчике прерывания, так как именно там переключаются буфера входной очереди) готовы, можно применять любую готовую сетевую библиотеку. Из опыта, на подготовку достаточно пары дней.
4.6 Пара слов о заголовочных файлах
Хоть для контроллера не прилагается никаких заголовочных файлов для работы с Ethernet, базовые порты описаны в файле CH579-master\src\EXAM\SRC\StdPeriphDriver\inc\CH579SFR.h.
Для комфортного написания своей библиотеки, этого более-менее достаточно. Хотелось бы большего, но будем довольствоваться тем, что есть… Для BLE, кстати, и такого нет.
5. Горе от выравнивания
Кто работает с STM32F1XX или STM32F4, тот про проблему выравнивания наверняка и не слышал. Нет там такой проблемы, так как ядра Cortex M3 и Cortex M4, если нужно, автоматически заменят одну транзакцию шины на несколько.
Когда мы осваивали контроллер CH32V307 с ядром RISC-V, нам пришлось поправить несколько мест, где разработчик нашей UDP-библиотеки весьма вольно берёт 32-битные значения из полей, адреса которых не выровнены на 32 бита. Он писал её для STM32F4, ему было проще. Но в целом, у CH32V307 Ethernet контроллер совместим с STM32, поэтому глобальной проблемы выравнивания тоже не возникает. Только мелочи со служебной частью сетевого пакета.
В CH579 эта проблема вылезает в полный рост. Дело в том, что сеть проектировалась во времена 16-битных ЭВМ. Поэтому у UDP-пакетов блок Payload (данные пользователя) смещён на 42 байта от его начала. Ну, то есть, на 0x2A. То есть, если пакет принят в память с выравниванием на 32 бита, блок данных пользователя гарантированно не будет выровнен на 32 бита.
Ну, скажем… Приняли мы пакет на адрес 0x1234. Тогда с 0x1234 по 0x125D будут идти служебные поля, а с адреса 0x125E (ну, то есть, 0x1234 + 0x2A) пойдут пользовательские данные. Этот адрес выровнен на 16 бит, но не выровнен на 32.
Чтобы избежать такой проблемы, в STM32 можно было выделить буфер вот так:
uint8_t tx_buf_aligned[1524 + 2] __attribute__((aligned(4)));
uint8_t *tx_buf = tx_buf_aligned + 2; // Aligns Ethernet frame payload at 4 bytes
И тогда служебные поля окажутся сдвинуты относительно 32-битных слов… Но многие из них – вполне себе 16-битные, так что это не страшно. Зато все данные пользователя будут выровнены именно на 32 бита. Красота!
В CH579 так делать нельзя. Особенности DMA таковы, что все Ethernet пакеты должны быть выровнены на 32 бита. Это явно прописано в документации. А процессорное ядро там Cortex M0. У него проблемы с выравниванием точно такие же, как и у RISC-V. Хочешь считать 32-битное слово – обращайся к адресам, которые делятся нацело на 4! А блок данных пользователя точно будет сдвинут…
В общем, всё грустно. Если используется какой-то свой протокол, то можно выкрутиться, учтя данную особенность. Размещать данные со сдвигом относительно блока Payload. Но это же костыль! Привязка к конкретной архитектуре!
Ну, и можно просто не выделываться, а копировать данные пользователя в другой буфер, уже обеспечивая выравнивание. Только в этом случае, обычный Loopback тест даёт скорость около трёх мегабит в секунду. С особыми ухищрениями, нам удалось поднять скорость до восьми-девяти мегабит в секунду, но не для любого случая, и всё равно даже не до десяти. Это связано с тем, что копирование буфера занимает достаточно много времени. А он копируется и после приёма, и перед передачей.
Вот так выглядит на осциллографе процесс передачи одного пакета от ПК в устройство и отправки его назад в режиме «запрос-ответ».
0,108 мс – это задержка на стороне ПК (работа тестовой программы). Жёлтый луч – сигнал на линии Rx устройства (по ней данные бегут от ПК к устройству). 1,36 мс – задержка внутри нашего устройства. Ну, и голубой луч – линия Tx (данные от устройства к ПК). При такой схеме (отсутствие конвейеризации), конечно, производительность выше пяти мегабит не получим даже без задержек. При нулевых задержках половину времени данные бегут туда, половину – обратно.
Но как видим, больше трети времени занимает не просто обработка, а банальное копирование данных. Это было выявлено в результате детального профилирования всех участков «прошивки». И наши «не более пяти» превращаются в «не более 10/3 = 3.3». Увы.
Конвейеризация улучшает работу, но не всегда допустима протоколом. И всё равно не позволяет занулить просадку скорости даже при десятимегабитной сети. Опять же, даже если снаружи всё красиво, то пока идёт копирование, прошивка не может заниматься полезными делами. Она занята копированием!
Хотя… Это нашему Заказчику была нужна производительность. Скажем, умной розетке она нужна не сильно, а вот каждые 100 рублей цены – критичны (десять розеток – уже тысяча рублей, а разница может оказаться и больше). В общем, не всегда описанная проблема является таковой, но мы теперь знаем, для каких задач контроллер рассматривать точно нельзя.
6. Требуемая периферия
6.1 Для Ethernet
Давайте рассмотрим, что надо докупить, чтобы подключить контроллер к Ethernet.
Достаточно разъёма со встроенными трансформаторами и двух токоограничивающих резисторов, если мы соберёмся использовать светодиоды. Ну, на схеме ещё конденсатор по питанию стоит. Всё!
6.2 Для Bluetooth и прочих радиозадач
Антенна (в том числе, печатная) подключается напрямую к выводу микросхемы.
6.3 Для подсистемы питания
Встроенные в микросхему стабилизаторы требуют обязательного наличия некоторых элементов в обвязке. Вот так это выглядит на схеме:
А вот так – выглядят требования в документе:
На этом какие-то специфичные требования заканчиваются. Я до сих пор не могу понять, почему макетки на базе CH579 стоят так дорого. Ну, кроме банального «халява кончилась». Я помню времена, когда все макетки стоили безумных денег. Потом на рынок вышли наши китайские друзья, и стало хорошо. Похоже, ситуация меняется. Здесь микросхема стоит от 120 до 150 рублей, а простейшая макетка – от полутора до трёх тысяч. Не подходит ситуация под привычные каноны! Обвязки для контроллера надо минимум! В общем, когда увидите такие цены — вы уже будете готовы… Не надо пугаться. Но надо ли брать — вопрос открытый.
7. Заключение
Из статьи видно, что рассмотренный контроллер не предназначен для весьма производительной работы. Поэтому дальше проектные работы с ним были свёрнуты. На новогодних праздниках я поиграл на нём в BLE… Может быть, когда-нибудь сделаю статью, но она будет сильно не хвалебная. Весь стек там спрятан в библиотеку, причём в той же библиотеке закопана и RTOS. А знаем мы, какая оптимальность у RTOS, которая поставляется не в исходниках.
Но так или иначе. Мне довелось пощупать (не по своей инициативе) этот контроллер, я описал результаты. Может, кому-то они пригодятся при выборе аппаратуры. А кому-то, кто тоже получает оборудование не по своей воле, может, будет легче начать с этим контроллером работу. Опять же, теперь все знают, как отказаться от закрытой библиотеки Ethernet и перейти на что-то своё.
Что до меня, то и тут труды не пропали даром. Я подзавёлся на изучение стандарта BLE. Но, поиграв на праздниках в CH579, теперь хочу попробовать осваивать всё на контроллерах других производителей. Если раскопаю что-то интересное – обязательно напишу. Например, уже нашёл интересное решение, где взять сниффер, не покупая дополнительного оборудования (Microsoft Bluetooth Test Platform — BTVS — Windows drivers | Microsoft Learn). Просто в большинстве случаев, все советуют купить специальную плату от Nordic Semiconductor. А с btvs.exe – всё на штатном работает.
Комментарии (26)
Javian
13.01.2023 14:26off Может быть мимо будут проходить специалисты, которые знают, чем можно дизассемблировать код Mediatek mt7681 (AndeStar™ patented 32-bit RISC-style CPU architecture).
Через этот soc с wifi умный кондиционер общается с облаком. Интересно бы узнать протокол общения.PS прошивка на отдельной 25q80dv, дамп которой слил.
osmanpasha
13.01.2023 17:50Может, проще интернет-трафик анализировать? Или он нечитабельно зашифрован?
Javian
13.01.2023 19:05Основное уже любителями сделано blog.instalator.ru/archives/433 Но остаются некоторые вопросы, которые не удается отреверсить. Официальное ПО умеет несколько больше, чем удалось понять в протоколе.
jaha33
13.01.2023 14:52А у BLE там прям RTOS или какой то свой планировщик? Задачи с приоритетами можно делать?
EasyLy Автор
13.01.2023 15:20Похоже, без приоритетов
extern bStatus_t tmos_start_task( tmosTaskID taskID, tmosEvents event, tmosTimer time );
Там есть события (event), сообщения (msg), таймеры. Из того, что вижу - в целом, всё.
Нам доступен только заголовочный файл, так что менять нельзя. Весь стек на это дело сильно завязан. Пользовательский код тоже на taskах построен. Как именно - я глубоко не погружался. Мне показалось, что это - не самый полезный контроллер для BLE, я решил другие поизучать, когда будет время свободное.
WicRus
13.01.2023 14:54+1Рассматривали QT-creator + qbs для работы с мк?
Выложить наработки в открытый доступ возможности нет, правильно понимаю?
Поделюсь опытом. С эклипсом не заладилось, уж очень хорошо падал, медленно запускался, ломал весь рабочий процесс. По возможности пытаюсь использовать qt+qbs. Разработчики qbs вроде даже читают/пишут на хабре.
Если делаю шаблонный проект пытаюсь выкладывать. Может кому будет полезен, может разработчики железок заметят и тоже будут выкладывать шаблоны под qbs. Эх мечты.EasyLy Автор
13.01.2023 15:32+2К сожалению, добра Заказчик на публикацию материалов не дал. К счастью, не так этих материалов и много. Самое главное я на словах изложил.
QT Creator для работы с Cortex M мы рассматривали, когда от нас потребовали проверить, что можно работать через CMake. Попробовали, всё получилось. Тот путь, что мы использовали, требовал слишком много подготовительных действий. Целую инструкцию на экран или два текста выполнить. Может быть, какие-то действия можно было и автоматизировать, не могу точно сказать.
Но каждый использует то, что ему нравится. Всё равно все среды разработки так или иначе завязываются на GDB или LLDB. Они, в свою очередь, могут опираться среди прочего на OpenOCD или J-Link. Поэтому на что опереться - тут показано (скачать китайский OpenOCD и работать через wch-link, либо взять JLINK и поправить ему конфиг). А дальше - всё, что сверху - заработает, кому бы что бы ни нравилось.
Лично мне очень нравится Эклипса. Ко мне она почему-то весьма дружелюбно относится. И в ней максимум всего автоматизировано. Напарник мой всё больше к VS Code тяготеет. Вам, вон Qt Creator нравится, но вот у меня к нему при отладке Виндушных приложений вопросики есть, поэтому я его не жалую и в других местах. Это же замечательно, когда каждый может выбирать что-то своё!
WicRus
13.01.2023 16:08+1Простите за нескромный вопрос, а зачем CMake в работе с CortexM?
Согласен наличие выбора сред разработок радует. Каждый может выбрать по вкусу и возможностям.
Я пытался продвигать qbs. Статейку даже тут писал, интереса особо не вызывала, железячники народ консервативный. Зато разработчик qbs объяснил мне, что же я сделал в своём проекте)EasyLy Автор
13.01.2023 16:34+1Да там проект разросся на кучу разных китайских процессоров, даже с разными ядрами (M3 и M4). Плюс кучка прочих опций. Заказчик сказал, что надо делать на CMake. Но я там только сбоку смотрел и при затыках идеи кидал. Делал напарник. Решили, что Qt Creator с этим лучше всего справляется. Он действительно справился на ура.
WicRus
13.01.2023 16:59+1Разные процессора + разные ядра, я вот про подобное же статейку писал. Там даже можно было компилировать через командную строку с указанием под какое железо собрать проект (это как раз разработчик qbs в коменте писал). Qt creator хорошая софтина, не пойму почему под него разработчики микросхем не делают шаблоны.
EasyLy Автор
13.01.2023 17:18+1Ну, начнём с того, что чисто официально этот Qt в России сегодня не скачать
Продолжим вопросом лицензии на использование Qt Creator (хоть и не фреймворка) для коммерческих проектов.
Но повторю... Вот у меня в Qt Creator при отладке под Windows иногда совершенно рабочие функции просто вылетают, если в них поставить точку останова. Пробегаем мимо этой функции - всё работает. Каждый раз приходится с бубном плясать, чтобы найти проблемное место. Причём суть проблемы обычно не ясна. Просто ушаманивать приходится. Чуть иначе проблемную строку перепишешь - начинает работать. Не любит меня Qt Creator, хотя под Windows я в последнее время им часто пользуюсь.
Но на самом деле... Каждый любитель той или иной среды разработки почти всегда может сконвертить в неё проект из другой среды. Производители CH579 любят Кейл, но мы под Эклипсу его быстро преекинули.
EasyLy Автор
13.01.2023 17:32+2не пойму почему под него разработчики микросхем не делают шаблоны.
К слову... Вот я - фанат библиотеки Константина Чижова mcucpp. Ну, и её наследницы Zhele. А вокруг почти никто не может прочувствовать их круть. Я, конечно, удивлён, что никто не хочет их использовать... Но это не мешает мне совать их во все более-менее серьёзные собственные проекты. Мне нравится - я пользуюсь. Другим продвигаю, но к тому, что мало кто фанатеет, отношусь философски. Их проблемы. Я-то пользуюсь...
WicRus
13.01.2023 18:58+1Если правильно помню qt creator можно из исходников собрать. Даже если всё там закроют, на форке можно пару десятков лет просидеть, особенно в не очень быстро меняющейся индустрии встраиваемого ПО. Могут быть юридические нюансы, но тут не силён. Хотя как можно запретить выкладывать на сайте шаблонный проект и ссылку на IDE, я плохо представляю)
С окнами давно не имею дела, 10ка была настолько ужасной, что перейти на линукс было проще. Однако у программистов не помню подобных проблем с отладкой под виндой. Под мк всё равно используется связка гдб+опеносд.
Обычно любят то, с чем умеют работать или то с чем умеют работать специалисты, которых смогли нанять. Обращаю внимание, во что вкладывает производитель, в квалификацию сотрудников или в покупку готовых решений. А то был случай, когда пришлось драйвер допиливать, чтобы он стал работать. В том случае была тотальная экономия и на сотрудниках, и на готовых решениях.
Пробежал глазами по Zhele. На вид довольно интересно. Спрошу наверное самый стандартный вопрос, какая разница в ресурсах/производительности относительно реализации на Си?
Попробую предположить, почему подобное мало используют. Железячники очень консервативный народ. Ресурсов на вхождение и освоение нужно в разы больше, чем в голом софте. Переучиваться на плюсы, когда работает на Си, не все хотят (некоторых индивидов приходилось выгонять с ассемблера на си). Ещё любят считать, что разработчик должен сделать схему, плату, написать прошивку и отладить железо, а учиться в свободное от работы время и желательно за свой счёт. Сверху заливаем этокомпаундомпрекрасными зарплатами, относительно более востребованных разработчиков, и в этой ситуации удивляться уже нечему.EasyLy Автор
13.01.2023 21:59+3Пробежал глазами по Zhele. На вид довольно интересно. Спрошу наверное самый стандартный вопрос, какая разница в ресурсах/производительности относительно реализации на Си?
Когда я начинал изучать mcucpp, проводил ряд тестов. Во всех случаях, даже при работе с группами битов, разбросанных по разным портам, компиляторы той поры (кажется, дело в 2017-м было, плюс-минус) оптимизировали всё так, лучше чего я бы на ассемблере не сделал. Ну, а драйверы аппаратных блоков там исходно оптимально спроектированы.
Там главная прелесть в шаблонах. Этот шаблон один раз объявил, у тебя появляется имя, к которому можно ссылаться. На чистых сях это можно сделать только через макросы. Но макросы второго или большего уровня - совершенно нечитаемы. И абсолютно не типизированы. Запутаться легко. Шаблоны - и легко понять, и предупредят, если неверно используешь.
Можно строить целые цепочки драйверов. Скажем, ножки GPIO, над ними SPI, над ними - экран, над ним - графическая библиотека. Любой кирпичик можно заменить. Ноги другие выбрать у того же SPI, выбрать другой SPI, заменить SPI на I2C с его ногами и т.п. Цепочки получаются - прелесть. Оптимизация - высшая! Прозрачность кода - все связи в одном месте через typedef прописаны, дальше - по именам внутренним обращения. Все замены - внутри этого заголовочного файла.
Если же хранить какой-то дескриптор в ОЗУ, а не через макросы/шаблоны делать - там процессор каждый раз цепочку от этого дескриптора должен раскручивать, тратя такты. В случае макросов или шаблонов, всё оптимизируется на этапе сборки. Ассемблерные команды сразу к портам лезут, так как их адреса заранее известны, даже через цепочку.
В наше время оптимизаторы в режиме LTO творят чудеса. Можно будет перепроверить, не будет ли всё так же красиво разрулено при вызове цепочки функций, где первая вызвана с константным аргументом. Но как Вы верно заметили, инертность... Когда-то потратил почти месяц, чтобы найти хорошее решение, теперь тратить ещё на перепроверку - лень. Всё ведь и так работает! Но факт того, что оптимизаторы ушли вперёд - я заметил.
Что касается Zhele - я помогал автору оптимизировать работу с USB. Он там в итоге добился двухбуферной схемы, что позволило выжать из USB все соки, но вылезли проблемы, которые мы ловили совместно. Фирменная библиотека от ST этого не позволяет. Причины тут (а тут - продолжение неожиданное). И вообще, работа с USB там классная. А дескрипторы строятся - вообще автоматически. Не то, что в Сишных реализациях. Поправить на Сях - целый процесс. Поменяй данные, поменяй длину. Тьфу!
kuzulis
15.01.2023 11:39+1Да, Qbs замечательная и интересная штукенция, но из за политики Qt в связи с сами знаете какими событиями, много русскоязычных разработчиков приостановили свою работу.
Например, и меня постигла та же идея, и к сожалению, сейчас в Qbs наблюдается застой, коммиты перестали поступать. По факту там остался один Кристиан из Qt Company.
Вот, так не дальновидная политика компании убивает хорошие проекты. У меня сейчас желания нет что то добавлять в Qbs, увы.
А те, кому не нравится QtCreator, могут попробовать VSCode, для которой я написал расширение и пока планирую его поддерживать. ))
В общем, вот такие вот дела, ребятушки.
SIWRX
15.01.2023 13:41Простите, а что не так с CMake для работы с микроконтроллерами? Это такой же инструмент для работы как и QBS, который позволяет делать довольно гибкие сборки.
kuzulis
15.01.2023 21:44Наврятли CMake лекго заработает, к примеру, с 8051 контроллерами, например тот же Keil, IAR И прочие. Придется писать свой синтаксис для таких тулчейнов. И CMake не предоставит нормальную подсветку заголовков и прочих вещей для таких компиляторов.
Хотя в Qbs это все есть из "коробки".
Кроме того, CMake ничего сам не собирает, ему нужны или Ninja Или Make, но Qbs не требует ничего лишнего и собирает сам. Кроме того, декларативный синтаксис самого Qbs гораздо лучше ложится на любые требования.
axe_chita
13.01.2023 19:13+1Спасибо за статью, читалось на одном дыхании. В закладки, плюс, и хабр торт!
acc0unt
14.01.2023 09:15Классическая работа с китайскими МК - разработка плавно перетекает в реверс и обратно. Классная статья.
А про цену макеток - ну так это тоже классика жанра. У многих производителей чипов девборды и по сей день часто стоят весьма приличных денег. Это же B2B - деньги компании, кто их считает. Три тысячи рублей за плату и столько же за родной прогер - это ещё по-божески.
Самые дешёвые и доступные девборды почти всегда сделаны не производителем, а третьей стороной - как те же Arduino Nano, или Blue Pill и Black Pill. И только увидев эти решения сам производитель начинает думать о уменьшении цены. Так что если хочется для какого-нибудь странного чипа дешёвую борду, то тут только самому делать. Производитель о популяризации своих изделий среди мелких разрабочиков, для которых между ценой в $20 и $120 есть разница, почти всегда думает в последнюю очередь.
Вообще в китайских железках приятнее всего именно степень интеграции. В одной банке BLE и Ethernet прям с PHY встречается нечасто. Много железок, которые могли бы тягаться на международном уровне - если бы не были сделаны китайцами в Китае.
DungeonLords
14.01.2023 14:31очень интересно было читать, спасибо. Пока читал постоянно свербила мысль
-Почему такой гениальный ум @EasyLy должен копаться в этом убожестве?Очень надеюсь, что в прекрасной России будущего миллиарды минпромторга будут идти на проекты российских талантливых инженеров и изобретателей. А дело Валерия Пшеничного будет расследовано.
EasyLy Автор
14.01.2023 14:35+1Всё в порядке, разбирались по заказу от товарища не из нашего ВУЗа, от товарища из Америки (слегка переделанная цитата из фильма "Дежа вю").
Но там была целая цепочка разных контроллеров. Вот тут, например, я описывал, как мы нашли в одном из них аппаратный баг. В другом (GD32F107) нашёлся баг поинтереснее. Его сетевая аппаратура зависает, если длина Ethernet пакета кратна четырём, а используется кольцевой буфер DMA. В фирменных примерах буфер используется связный, с ним такой проблемы не возникает. Но там материалов не на целую статью, поэтому я пока не стал писать, надо с чем-то объединить. В общем, если смотреть на весь объём работ, то там много интересного было. CH579 был быстро обследован, выводы сделаны, быстро Заказчиком отброшен.
sergopl
15.01.2023 02:44+1Отличная статья, но почему я все время представляю в голове мышей и кактус?
perfect_genius
15.01.2023 19:23Этот больно умный декомпилятор понимает, что первые два занесения констант 0x57 и 0xa8 не нужны.
Может, у Гидры есть включённая опция антиобфускации?
COKPOWEHEU
А возможно ли подключить через JTAG (SWD) на основе FT4232? А то нашел интересный контроллер CH32V307, и та же беда — какие-то идиоты решили, что прошивать его надо исключительно через wch-link либо мега-кривую софтину по UART. Хотя UART бы тоже устроил, если бы хоть протокол обмена известен был.
EasyLy Автор
Всё та же проблема. Вот прямо взять готовое - скорее всего, нельзя. Сделать поддержку в OpenOCD - можно, только надо время потратить (унифицировать китайский вариант или скопировать загрузчик оттуда в основной, творчески переработав обращения к нему). В коммерческих проектах после фразы про время обычно сразу всё заканчивается. Не любят Заказчики за такое платить. Особенно если находится готовое решение.
А любым монитором порта если поглядеть? Вдруг там будет видно, что к чему?
COKPOWEHEU
Пробовал. Похоже, прошивку на время передачи шифруют или что-то в этом роде. Ни одна последовательность исходной прошивки с потоком байтов не совпадает. Впрочем, какие-то открытые прошивальщики я видел, может и получится оттуда выкусить алгоритм.
Понятно. Моих познаний openocd на такое не хватит точно. Значит, буду извращаться другими способами.