Привет, Хабр. Год назад я круто изменил направление своей деятельности с desktop разработчика на программиста микроконтроллеров. Хочу поговорить о том, как прошел этот год, поделиться своими наблюдениями, рассказать о чем никто не рассказывает. А, еще и RNDIS на stm32f103 поднимем.

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

GIT для микроконтроллерщика

Скажу сразу: я не специалист - я типичный самозванец. Мои познания в  схемотехнике ограничиваются законами Ома и Кирхгофа. Новая работа очень близка к железу, отладке плат и прочим электромагнитным экспериментам. Но вот вам обратное наблюдение (не только моё): люди, которые заняты программированием на микроконтроллерах зачастую далеки от программирования. Они запросто вам расскажут как подключить транзистор к ножке МК, но библиотеку к проекту будут подключать с горем пополам. Я это к чему. Я попал на пару десятков проектов на разных распространенных камнях STM32 (серия f103, f105, f407), с системой контроля версий в виде копирования папки проекта целиком и переименования в `_old_{дата}`, с проектами в просто морально устаревшей IDE (которую уже невозможно даже скачать), с файлами main.c в >5000 строк (и это без комментариев, просто спагетти, паста, код, в некоторые ветви которого никак попасть) и т.д. И все это работало, но работало только пока было под присмотром автора. Как только он ушел, и я остался с проектами один-на-один, а ко мне начали приходить с просьбами добавить/исправить фичу - я схватился за голову.

Система контроля версий одного из проектов
Система контроля версий одного из проектов

Первым делом, пока мы еще работали с прежним микроконтроллерщиком, я явил людям git. Для упрощения, в виде простой связки git + TortoiseGit с репозиторием в (хотя бы) локальной папке. Не нужно запоминать синтаксис команд, только понять что делает одна единственная операция: commit, - и вы на коне. Глаза моего коллеги, когда он увидел, как я в несколько кликов показал ему diff между двумя его папками, - не передать словами. Для каких-то проектов, которые уже не так активно велись мы просто сделали initial commit, для других я набросал скрипт, который пробегал по всем копиям папок и собирал историю изменений с комментариями в виде названий папок. Через несколько дней ко мне подошел человек из другого отдела и спросил, нет ли чего-нибудь похожего для его задач…

IDE

Мой опыт программирования МК все же был немного больше нуля (завершенный pet-проект датчика CO2 на attiny13 со стрелочным индикатором). Здесь же мне была вручена синяя таблетка - и с нее все началось. А с чего, собственно, начать? Я начал искать озвученную мне CooCox CoIDE. Чтобывыдумали? Нет уже ни сайта, ни разработчика, ни архивов. Где-то на просторах обучающих блогов еще можно найти установщики - но это никуда не годится. Поставить её я все равно был вынужден для поддержки старых проектов. Откуда мне было знать, сколько должен собираться проект под МК, мы просто беседовали обо всем, пока чего-то там крутилось и собиралось… и раз в пять минут писали код. Однако, я начал искать варианты по-современнее. Из рассмотренных вариантов: 

  • Visual Studio + VisualGDB - мощнейшая IDE, но платный аддон. Я пользовался этой связкой раньше при разработке под Embedded Linux, но со своим инструментарием в чужую избу не ходят. Большой и универсальный комбайн, к которому нужно привыкать, с избыточным набором инструментов под поставленные задачи.

  • VS Code + PlatformIO - еще вариант. Честно, не могу вспомнить что там было не так. (upd: да, там действительно в то время функция дебага была платной фичей только по подписке)

  • Keil uVision - нет темной темы - хаха!

  • STM32 CubeIDE - собственно IDE от производителя, на которой я и остановился. Современный Eclipse с поддержкой аддонов из Marketplace.

CubeIDE оказалась самой готовой к работе из всех. Плюс встроенная поддержка .ioc файлов, в которых можно разметить и настроить МК (об этом дальше). Очень быстро получилось разобраться где-чего-куда, перенести проекты из CoIDE в CubeIDE. И, о чудо или о горе, проекты почему-то стали собираться за несколько секунд. Магия, не иначе.

Перенос проекта из CoIDE в CubeIDE
  1. New -> STM32 Project

    1. Выбрать соответствующий микроконтроллер в MCU/MPU Selector. Next

    2. Ввести название проекта и выбрать для него папку. Target Language = C, Target Binary = Executable, Targeted Project = Empty. Finish

  2. Готовим файлы

    1. Удалить папки Inc, Src, Startup

    2. Скопировать файлы *.c *.h из проекта CoIDE

  3. Правой кнопкой мыши по проекту -> Properties

    1. C/C++ Build -> Settings -> Tool Settings -> 

      1. MCU GCC Compiler -> General -> Language standard = GCC default

      2. MCU GCC Compiler -> Include paths В таблицу Includes добавить папки из проекта, где находятся .h файлы. В том числе корневой, если в нем находится *.h

      3. MCU GCC Linker -> General -> поставить галочки если не стоят напротив:

        - Do not use standard start files, - отвечает за startup файл для мк
        - Do not use default libraries, No startup or default libs - отвечает за вызов выбранной syscalls.c имплементации (nosys и nano specs)

    2. C/C++ General -> Paths and Symbols

      1. В таблицу Symbols добавить дефайны из проекта CoIDE (Configuration -> Compile Defined Symbols) (например, STM32F103CB; STM32F10X_MD; USE_STDPERIPH_DRIVER;__ASSEMBLY__)

      2. В список Source Location добавить папки, где находятся .c файлы.

  4. Билд

  5. Если билд не удался, смотреть что к чему. Удалить файлы, которые не участвовали в компиляции в проекте CoIDE.

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

Меня ждал сюрприз, когда поехала кодировка немногочисленных комментариев в коде. Оказалось, что все файлы были в CR1251. Ох!

foreach($file in get-ChildItem *.c -Recurse) { (Get-Content -Path $file) | Set-Content -Encoding UTF8 -Path $file}

CMSIS SPL LL HAL

Во время поиска IDE я уже понимал, что встанет и другой вопрос. Легаси проекты были собраны из смеси прямых обращений к регистрам и SPL. Выбранная CubeIDE в первую очередь заточена на генерацию проектов из .ioc на HAL или частично LL. Но давайте по порядку про основные понятия:

  • CMSIS - и не библиотека вообще-то, это интерфейс, заголовочные файлы от разработчиков архитектуры ARM. Штука почти независимая от производителя МК, содержит адреса только основных регистров и прерываний. Это практически нижайший уровень доступа к МК. К нему прилагается файл от производителя МК с описанием регистров периферии, которую они запихнули в конкретную модель МК.

  • SPL - вот это уже библиотека под определенные семейства микропроцессоров от ST. Реализация того, что написано в Programming Manual для вашего МК. Она обращается по адресам указанным в CMSIS и реализует в себе функции для доступа, инициализации, управления периферией. С помощью нее можно выразить практически весь функционал МК. На мой взгляд, лучшая библиотека. Но, к сожалению, “старая”. ST решили прекратить поддержку и выдали нам…

  • LL - очень похожую библиотеку, но кастрированную. По сути брат близнец SPL, недоразвитый и неполноценный. Нет, например, поддержки CAN и некоторых других модулей (почему?), а еще какая-то странная политика именования функций и дефайнов. Какие-то начинаются с LL_*, какие-то нет; параметры у функций и принимаемые константы никаким смысловым наполнением не связаны. ST даже выкатили некий конвертер, но что-то серьезнее Blink, пережевывает он с трудом.

  • HAL - библиотека с более высоким заявленным уровнем абстракции. И тоже странная, отчасти. Некоторые модули зависят от LL, другие вполне самостоятельны. HAL подразумевает абстракцию над железом, легкий перенос с одного семейства на другое, но чуда не происходит, все равно приходится портировать код, а иногда еще и долго искать почему что-то перестало работать. Библиотека вроде бы много берет на себя, но не все, и после её инициализации, приходится еще самому “довызывать” функции, причем долго гадать, чего же не хватило. И к тому же из-за абстрагирования и оверхеда имеет больший отпечаток, т.е. занимает много места в памяти, по сравнению с SPL или LL.

  • libopencm3 - популярная open source библиотека для ARM Cortex-M3 (под который попадает и наш f103), можно найти много примеров как простых, так и сложных проектов. Не пользовался, ничего не могу сказать.

По поводу именования функций и дефайнов, о котором я выше упомянул: вот вам для сравнения простейший пример, GPIO в SPL и LL/HAL:

Автодополнение в SPL
Автодополнение в SPL
Автодополнение в LL/HAL
Автодополнение в LL/HAL

Та же беда и у HAL. Поле структуры называется TimeSeg1, а значение ему впиши CAN_BS1_1TQ. В противовес у SPL: поле CAN_BS1 и значение CAN_BS1_1tq (если забыл, что такое BS1, нажми на поле структуры, и тебе явится подсказка `Specifies the number of time quanta in Bit Segment 1`).

Бомбит меня от этих поделий. Да, такой код пишется единожды, но когда оно сплошь такое - бомбит. И это не автодополнение глупое, это я глупый, раз не могу запомнить как же называется нужный мне дефайн для данного поля структуры.

CubeIDE Configuration tool / CubeMX

Однако преимуществом LL / HAL является сопутствующая утилита по конфигурации микроконтроллера. Как ни крути, очень удобно визуально увидеть занятые ножки, выгнать эти значения и передать в отдел разработки плат, визуально сконфигурировать периферию, одно удовольствие настраивать тут таймеры и тайминги. Но, опять же, генерирует код она только в LL или HAL. И, опять же, какая-то периферия не имеет имплементации на LL, и если вы хотели бы написать что-то без HAL, то это ваши проблемы.

Настройка тактирования
Настройка тактирования

С помощью этой утилиты я проводил реверс-инжиниринг легаси проектов на SPL. Я собирал ioc и размечал те пины, которые были подведены на плате, дальше дело шло легче. В коде тут и там дергались модули, которые даже не были инициализированы, и я смело удалял эти куски. Главное не нажать случайно кнопку Generate Code.

Структура проекта

Сейчас новые проекты я стараюсь писать полностью на LL, хочется идти в ногу со временем, так сказать (пришлось переписать can и flash, чтобы не тянуть HAL). Однако большая часть легаси проектов на SPL, где не было генерации файлов и папок, и один несчастный main.c в over9000 строк кода - это неприемлемо, я начал искать в сети, как программисты МК организовывают структуру проекта. И я не нашел. Ладно, может что-то я нашел, но понял, что каждый делает так, как удобно себе. Так же сделал и я, собрал все полученные знания, волю в кулак и начал рефакторить. По итогу получилось придумать несколько логичную структуру проекта. Ничего не навязываю, просто даю пример, потому что хочется иногда найти в сети пример и использовать:

Структура проекта
Структура проекта

Папка device - индивидуальна для каждого проекта. В ней лежит device.h, который хранит мои описания пинов, имен, адресов и прочего, конкретно для этого проекта. Сюда же ложатся файлы реализующие конфигурацию и логику работы модулей конкретного девайса. В папку lib же ложатся переносимые из проекта в проект библиотеки, не только CMSIS и SPL, но и мои helper функции, модули для периферии, внешних датчиков и т.д.

Параллельно с ежедневным рефакторингом и рабочими задачами я продолжал знакомится с новой для меня областью программирования, что вылилось в серию проектов на github, ничем не примечательных, но связанных между собой одним шаблоном. Побольше бы таких шаблонов для типовых задач и IDE.

RNDIS

Как оказалось, ничего катастрофически сложного в программировании STM32 нет. Знай да всегда помни (если что-то вдруг не работает), включил ли ты тактирование, правильно ли выставил множители, да всю ли инициализацию провел. Даташит твой лучший друг, код SPL библиотеки прекрасно документирован и иногда даже позволяет к лучшему другу не обращаться. 

И вот, спустя почти год работы с камнями, я нашел свой макгаффин. Применить полученные знания и написать Ethernet поверх USB на той самой BluePill. Вообще-то что-то такое уже есть, в одном единственном экземпляре: @fse написал несколько статей на эту тему (upd: а с недавних пор есть и в TinyUSB). Титанический труд, без понятия чего это стоило и как получилось заставить работать. Проект Сергея послужил для меня отправной точкой.

USB

RNDIS начинается с USB: качаем USB full speed device library (UM0424). Библиотека делится условно на две части: USB Full Speed device driver и Application Interface layer. Первая часть - это внутренняя кухня протокола USB: прием прерываний, заполнение буферов и т.д. Эта часть остается неизменной. Вторая - это непосредственно то, что мы хотим изобразить - интерфейс, которым наш USB должен прикинуться. Здесь будут наши USB-дескрипторы, эндпоинты, логика работы и т.д. Нельзя не упомянуть USB in Nutshell, которая помогла с большего разобраться с USB стеком. Давайте немного посмотрим на интересные моменты либы.

В заголовочном hw_config.h есть такой интересный параметр: USB_DISCONNECT_PIN. На отладочных платах, по-хорошему, подразумевается транзистор, который электронно бы размыкал цепь между хостом и устройством. Что мы имеем на BluePill? Ничего. Однако на просторах интернета я отыскал хитрый прием: наличие устройства хост определяет по состоянию линии D+, стоит перевести пин в низкое состояние Out Push-Pull (высокого импеданса / HiZ) на >=5 мс - и хосту покажется, что мы отключили устройство. Поэтому мы назначаем этому USB_DISCONNECT_PIN наш пин PA12(USB D+). Для чего это всё? Теперь при программной перезагрузке камня (например вход в дебаг), устройство само “отключается” от ПК и “подключается” обратно, запуская со стороны хоста соответствующие процессы по установлению USB соединения.

GPIO_InitStructure.GPIO_Pin = USB_DISCONNECT_PIN; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 
GPIO_Init(USB_DISCONNECT, &GPIO_InitStructure); 
GPIO_ResetBits(USB_DISCONNECT, USB_DISCONNECT_PIN); 
DWT_Delay_ms(5); 
GPIO_InitStructure.GPIO_Pin = USB_DISCONNECT_PIN; 
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; 
GPIO_Init(USB_DISCONNECT, &GPIO_InitStructure);

Описание USB устройства находится в usb_desc.c. Официальная классификация USB устройств содержит такой класс, как RNDIS (0xEF 0x04), но почему-то наше устройство отказывается определяться с такими значениями, пришлось использовать подсмотренное значение, которое работает как Wireless Controller (0xE0 0x00). В этом же файле описание эндпоинтов, а также текстовое представление устройства (String Descriptors).

Вся непосредственная магия RNDIS пакетов находится в usb_prop.c и usb_endp.c. В основном большую часть времени я тут и провел. На просторах я даже нашел чей-то дневник попыток переписать RNDIS на HAL. Почерпнул оттуда идею использования USB анализатора, перепробовал разных (USBlyzer, USBTrace, бесплатный WireShark + USBPcap) - и каждый выдавал мне различные, но полезные данные. Помни, юный USB-падаван: USB хост-центричен - IN (up) всегда к хосту, OUT (down) всегда к девайсу.

Data Breakpoint

Кстати, во время отладки мне в один момент понадобилось знать кто-и-когда меняет мне значение в памяти. Но переменная глобальная, к ней обращений из всех уголков USB библиотеки. Так я наткнулся на Data Breakpoints. Такие точки останова, которые вызываются в момент записи/чтения указанной переменной.

В CubeIDE зовутся они Watchpoint и настраиваются на вкладках Variables, Expressions и даже Memory.

Настройка Data Breakpoint в CubeIDE
Настройка Data Breakpoint в CubeIDE

Включаем дебаг, отправляем интересующий запрос - срабатывает точка останова, виден stack trace, виден подлец, который пишет туда-куда-не-надо. Таким арсеналом и получилось завести RNDIS.

LwIP

Теперь давайте посмотрим на подключение (и портирование) библиотеки LwIP. Не будем брать какую-нибудь древнюю готовую реализацию, а сделаем все по-взрослому: добавим в наш git репозиторий подмодуль и напишем порт по их гайду, чтобы понимать что и откуда берется.

Я уже упоминал ToroiseGit, в нем все делается проще простого: заходим в файловом менеджере в папку lib нашего проекта и через контекстное меню выбираем TortoiseGit -> Submodule Add

Видим окно, в которое вводится адрес репозитория LwIP и опционально выбирается бранч (STABLE-2_1_x).

Добавления субмодуля git
Добавления субмодуля git

Библиотека LwIP построена таким образом, что нам не надо ничего менять в её исходных файлах. Все настраивается “снаружи” библиотеки. Единственные манипуляции, которые необходимы над папкой библиотеки - это исключить из сборки папки lwip\doc, lwip\test, lwip\apps\http\makefsdata (утилита для хоста, о ней позже)

Рядом с папкой lwip я создал lwip_port, где и располагается все касаемо нашего портирования. Согласно гайду, в arch/cc.h ложатся адаптированные под нашу архитектуру и компилятор базовые методы (например htons, htonl), реализации функций работы со строками (itoa, strcmp, strstr), типы переменных и т.д. Если этого не приложить, LwIP будет использовать собственные софтовые реализации, которые могут быть медленнее и больше.
В файле lwipopts.h перечислены настройки библиотеки. Среди важных MEM_SIZE, который определяет размер буфера под пакеты, и MEMP_NUM_PBUF, который отвечает за количество этих пакетов. Чем больше траффиков©, тем выше должны быть эти значения. Тут мы немного сэкономим, чтобы все поместилось в память МК.

Строка

#define LWIP_IP_ACCEPT_UDP_PORT(p)      ((p) == PP_NTOHS(67))

Необходима для работы DHCP сервера (он использует порт 67 для своих служебных коммуникаций).

Также на демо-странице я вставил картинку в формате .svg, но сам LwIP по умолчанию не знает о нем и воспринимает файл по умолчанию как "text/plain", исправляется путем добавления

#define HTTPD_ADDITIONAL_CONTENT_TYPES {"svg", HTTP_CONTENT_TYPE("image/svg+xml")}

Ту самую утилиту makefsdata, которую мы исключили из сборки, нужно собирать отдельно под вашу операционную систему уже после настройки lwipopts (он подтягивает некоторые настройки, например указанные нами Content types).

Связующим интерфейсом между USB-RNDIS и LwIP является rndisif.c (rndis interface). Здесь мы парсим RNDIS пакет и запаковываем в LwIP (rndisif_input()), и наоборот (linkoutput_fn()). Вся инициализация лежит в файле netconf.c, там же настраивается DHCP и DNS сервера (про них подробнее в статье у Сергея).

HTTPD

HTTPD одна из составляющих служб LwIP, отвечающая за работу с протоколом HTTP. Мы уже в настройках её включили, как и два механизма: SSI (Server Side Includes) и CGI (Common Gateway Interface). Пример использования лежит в device/httpd_cgi_ssi.c.

SSI позволяет нам на стороне сервера изменять представляемую пользователю страницу, выводя таким образом, например, значения переменных МК или состояние пинов. На стороне страницы мы помечаем тегом место, куда сервер должен будет вставить текст. Выглядит он так <!--#IsLED-->. На стороне сервера мы указываем список этих тегов и пишем обработчик, что подставить при встрече определенного тега в коде страницы. Так же в lwipopts есть настройка LWIP_HTTPD_SSI_INCLUDE_TAG, которая определяет, нужно ли вставлять ли в код страницы необработанный тег.

CGI дает возможность отправлять со стороны клиента на сервер информацию через url в виде пары param=value. На странице размещается форма с сабмитом, а в коде МК в обработчике выполняется действие при встрече данной пары.

<form method="get" action="/leds.cgi">
<input type="checkbox" id="ld1" name="led" value="1" <!--#IsLED--> />
<input value="OK" type="submit"/>
</form>
/* Check cgi parameter : example GET /leds.cgi?led=1 */
for (i = 0; i < iNumParams; i++)
{
	/* check parameter "led" */
	if (strcmp(pcParam[i], "led") == 0)
	{
		/* switch led1 ON if 1 */
		if (strcmp(pcValue[i], "1") == 0)
			GPIO_ResetBits(GPIOC, PIN_LED);
	}
}

Обработчики и теги упаковываются в структуры и скармливаются LwIP через http_set_ssi_handler() и http_set_cgi_handlers().

FS data

Уже к этому моменту память на моем BluePill начала трещать по швам, приходилось делать преждевременную оптимизацию, чтобы проект хотя бы собирался.

Прожорливость кода
Прожорливость кода

Для уменьшения отпечатка можно бы переписать USB стек (как это делают народные умельцы), или использовать другой TCP/IP стек, или даже включить -Os/-O3 оптимизацию.

В проекте на камне побольше у меня прикручена fatfs, а для LwIP стоит опция LWIP_HTTPD_CUSTOM_FILES с реализацией доступа к файлам через fs_open_custom(), что позволяет изменять html файлы без перепрошивки самого МК. В нашем же проекте вместо растровой картинки, я нарисовал пилюлю в svg, уложившись в 3 кБ.

Чтобы собрать “сайт” в файл fsdata_custom.c, нужно скомпилировать ту самую утилиту makefsdata из папки LwIP в своем любимом C компиляторе. 

По умолчанию утилита ищет папку ./fs и упаковывает всё, что найдет внутри. Либо можно указать ей путь к файлам самостоятельно. Подробнее можно посмотреть вывод --help.

Полученный файл fsdata.c, переименовываем в fsdata_custom.c (потому что в lwipopts мы указали HTTPD_USE_CUSTOM_FSDATA, что в свою очередь приводит в недрах к #define HTTPD_FSDATA_FILE "fsdata_custom.c"), кладем его в папку device и исключаем из билда. LwIP (в apps/httpd/fs.c) включит этот файла на этапе компиляции.

Итог

Вот и всё. Проект собираем, зашиваем, подключаем. В системе появляется новое сетевое устройство Remote NDIS Internet Sharing Device, в браузере можете вписать  http://192.168.7.1 (по умолчанию), а благодаря поднятому DNS серверу, можно даже написать http://run.stm и увидеть веб-интерфейс нашей BluePill, поморгать светодиодом.

Читатель спросит: что с этим делать? Я не знаю. Вот вам еще один user interface для ваших проектов. Поздравьте своих товарищей новогодней открыткой, принесенной на платке, удивите коллег `интернетом` на флешке. У кого-то есть идеи получше?

з.ы.

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

Теперь действительно в TinyUSB есть реализация этого же RNDIS, причем используется код @fse. Я сам поднаторел достаточно, чтобы с полузакрытыми глазами смотреть на данный проект. Я бы поменял некоторые вещи, но статья не об этом.

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

Комментарии (37)


  1. Kudesnick33
    22.12.2022 23:01
    +2

    Keil uVision - нет темной темы - хаха!

    https://github.com/Kudesnick/uVision-dark-theme


    1. viteo Автор
      23.12.2022 11:02
      +4

      ну, знаете ли...

      скажем так, тема "вечерняя"


      1. Kudesnick33
        23.12.2022 14:13

        Да, текстовый редактор - не сильная сторона Keil. Непонятный для меня феномен, кстати. IDE живая, постоянно апдейтится, но gui заморожен намертво.


        1. mctMaks
          23.12.2022 15:12
          +2

          почему же намертво, они в какой-то момент убрали обязательную пустую строку в конце файла, а иначе warning)) сделали таки усилие


  1. ripandtear
    22.12.2022 23:12
    +14

    Круто вы сразу обобщили всех программистов МК, как тех, кто в "нормальное" программирование никак не умеет.

    Вот это сейчас обидно было (с)


    1. viteo Автор
      23.12.2022 11:14
      +2

      да всё уже. я теперь один из нас)


  1. GennPen
    22.12.2022 23:28

    Уже к этому моменту память на моем BluePill начала трещать по швам, приходилось делать преждевременную оптимизацию, чтобы проект хотя бы собирался.

    STM32F103C8T6 прекрасно работает со 128 кБ флеш-памяти. По сути это и есть CBT6, только перемаркированный под младшую модель.


    1. viteo Автор
      23.12.2022 11:12
      +1

      известная фича.
      только в проде так делать не надо все же.
      и на клонов китайских тоже не надо надеяться.


    1. mctMaks
      23.12.2022 15:14
      +1

      скорее отбракованный по каким-то причинам или, возможно, проверить 64кБ Flash памяти сильно дешевле чем 128 кБ. вот и маркируют как младшую модель.


  1. andrey239
    22.12.2022 23:33
    +1

    Напоминаю про божественный ChibiOS - который RTOS+HAL с фокусом на stm32


  1. Indemsys
    23.12.2022 01:22
    +1

    Сделать на STM клиента RNDIS не представляет собой какой-либо задачи.
    Примеры RNDIS полностью готовые идут с STM почти под все оси.
    Вот, например, как он делается на Azure RTOS - https://habr.com/ru/post/582742/
    И он там еще одновременно с Mass Storage и Virtual COM работает.

    Но вот хост RNDIS это совсем другой уровень. И пока его никто осилить не может.
    А вот хост бывает очень нужен, когда требуется подключить мобильные модемы к устройству.


    1. fse
      23.12.2022 04:46
      +2

      Добрый вечер. Вероятно, было бы правильнее сказать, что не сложно на контроллере запустить уже готовую цепочку RNDIS+стек+ПО. Однако, как упомянутый выше автор, не могу согласиться, что сделать цепочку было просто. Замечу, что на момент написания (2015 год) альтернатив ещё не было (в том числе Azure RTOS USBX). И сейчас альтернатив почти нет (Azure, либо Azure+USBX+CubeMX, либо работы отдельных авторов на github-е: Lexatagan, oleg84, nicokorn, JonasHeim). Поэтому считаю, что даже на сегодняшний день наблюдается значительный недостаток выбора. Буду Вам признателен, если Вы подробнее поясните на счёт "идут с STM почти под все оси". В составе каких пакетов?
      По поводу подключения мобильных модемов, этого, действительно, не сделано. На текущий момент наиболее "тонкий" usb-хост с поддержкой RNDIS - это уже одноплатный ПК под управлением развитой ОС. Вероятно, производители МК решили, что отношение востребованность/затраты чересчур низкое для разработки, а необходимую долю рынка уже схватили такие известные производители, как SIMCom.



  1. pwl
    23.12.2022 03:59
    +2

    CubeIDE оказалась самой готовой к работе из всех.

    Хм. Для вас показателем готовности к работе является "нажал F7 и светодиодик замигал"? А как-же тогда ваше вступление "о настоящем программисте"? Cube может быть удобен для "попробовать", но он:

    • ужасно тормозной

    • по сути такой-же древний как и keil c iar-ом.

    Я для своих поделок пользуюсь vscode + gcc + openocd. К ним замечательно прикручиваются и логи, и визуальная отладка через swd.


    1. fse
      23.12.2022 05:15

      Как-то пробовал связку jlink_gdb_server + gdb + qtcreator, отлично работающую как в windows, так и в linux. Пикантности добавлял тот факт, что Cortex-M0 запускался на ресурсах программируемой логики.


      1. Sergey78
        23.12.2022 13:36

        К нему при этом, можно еще и удаленно по tcp подключаться :) Т.е. к целевому МК подключается условная "малина" по swd, а к ней по сети с рабочего места. И отладка, как будто МК подключен напрямую (ну по медленнее конечно).


        1. fse
          23.12.2022 14:29

          Да, это, бесспорно, очень удобно! Особенно, в упомянутом случае, когда место разработчика ПЛИС и место разработчика ПО находятся в удалении друг от друга. Справедливости ради, этим удобством также обладает openocd, поскольку реализует gdbserver.


  1. kh0
    23.12.2022 06:06
    +1

    Колоссально!
    Я не совсем понял, пролистал все еще раз и все равно не совсем понял:
    мы берм USB-сетевуху а ля китай, втыкаем в пилюлю в usb как раба и получаем в сети еще один хост который, получает по DHCP IP-адрес и начинает прикидываться веб-сервером с блекджеком и монтажницами?
    Еще интересует момент, насколько сложно теоретически забабахать всеуровневый IP-стек? Ну то есть вешаем на GPIO траснформаторы из сетевухи и поехали реализовывать все уровни...
    На FPGA это довольно старый баян, а вот на пилюле....
    Еще вопрос, ща народ активно топит за RISC-V, если только собираешься залезть на взрослые контроллеры, может стоит пропустить STM32 и сразу перескочить на RISC-V? тем более что есть уже от гигадевайса девборда с ними, и не оч дорого...


    1. Avsmirn0ov
      23.12.2022 07:30
      +1

      На gpio не выйдет, ни у одного stm32, насколько я помню, нет реализации физического уровня на чипе (у некоторых других компаний есть), следовательно, нужно поставить внешнюю микросхему PHY (например, какую нибудь ksz8081), и подключиться к ней по MII/RMII к MAC, который в контроллере уже, если такая переферия вообще есть в камне. И вот потом уже трансформатор, да.

      Если нету MII, то всё грустно, для ethernet придется ставить что то навроде w5500, а там большой скорости не видать, явно не 100Мб


    1. olartamonov
      23.12.2022 12:56
      +2

      Еще вопрос, ща народ активно топит за RISC-V, если только собираешься залезть на взрослые контроллеры, может стоит пропустить STM32 и сразу перескочить на RISC-V? тем более что есть уже от гигадевайса девборда с ними, и не оч дорого...

      Если для себя, то без большой разницы, с чего начинать. Если вы не пользуетесь хорошо проработанной ОС или хотя бы HAL с поддержкой разных производителей, где почти всё работает из коробки, то разница между ST и каким-нибудь NXP с точки зрения старта разработки для вас будет не меньше, чем между ARM и RISC-V. Периферия разная, подходы к работе с ней разные, к документации разные — всё едино садиться и неделю изучать, чего там наворочено, хотя формально вы вроде бы с одного Cortex-M3 на другой Cortex-M3 переходите.

      Поэтому если хочется новизны, в учебных целях можно брать RISC-V и играться с ним, общие навыки наработаются такие же, как на любом Cortex'е.

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


      1. Gryphon88
        23.12.2022 13:10

        Сейчас если новый проект, то я предпочту взять CH32 на ARM или RISC-V. Они банально доступнее.


        1. olartamonov
          23.12.2022 13:22
          +2

          У меня последний проект вообще на PIC10F200 был, и пользовался бурным успехом, а следующий намечается на ATtiny13A. А через один — скорее всего, на одном из клонов STM32F103C8T6, но и эта замена там уже с очевидностью будет не самым занятным кульбитом.

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


    1. Indemsys
      23.12.2022 13:17

      Нет, чтобы подключить USB-сетевуху нужна вот такая технология - https://habr.com/ru/post/676120/

      Ждать что-то конкурентное на RISC-V для малых встраиваемых систем я думаю надо не раньше чем лет через 5.

      Тогда кончатся гарантируемые сроки поставок большинства начатых малых SoC на ARM-ах, которые успели раскрутить до кризиса.

      А сейчас я бы ориентировался на ARM-Cortex M85


      1. Gryphon88
        23.12.2022 14:27

        Ждать что-то конкурентное на RISC-V для малых встраиваемых систем я думаю надо не раньше чем лет через 5.
        Esp не нравится?


  1. 8street
    23.12.2022 08:16
    -3

    Следующим открытием для автора, очевидно, будет какой-нибудь esp8266 с WiFi и кучей библиотек в разных средах.


  1. Koyanisqatsi
    23.12.2022 09:31
    +2

    Я бы посоветовал создавать проекты для микронтроллеров с помощью CMake, т.е. без привязки к какой-то определенной IDE или редактору. Отладка - OpenOCD. В VSCode, Eclipse всё это прекрасно работает, есть всякие удобные плагины. Может напишу как-нибудь небольшой туториал по связке CMake + VSCode + OpenOCD, так как я сам себе настроил.


    1. Sergey78
      23.12.2022 13:31

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

      Я использую jlink для подключения по swd, а для отладки Ozone. Запускается прямо из vscode. Отличный отладчик, очень удобно. Ну и все остальные преимущества jlink - RTT, SystemView, при необходимости прошивка флешек по spi и прочее. Вместо openocd использую или прошивку из Ozone или при помощи драйвера jlink (их утилита консольная умеет работать в "пакетном режиме", с параметрами из командной строки).

      У такого подхода, когда вместо комбайна IDE используется связка из нескольких инструментов, есть свой большой плюс - любой инструмент можно заменить. Не нравится vscode? Можно хоть vi использовать. Нужна другая версия компилятора? Без проблем. Для многих платформ есть toolchain со сборкой через makefile. Соответственно для того, чтобы попрограммировать под esp32, nfr52, avr или что-то ещё, не нужно менять удобную и привычную среду написания кода.


  1. rBo3Db
    23.12.2022 10:41
    +3

    какой смысл переходить с десктопа на мк? Там платят на 20-30% ниже, и ответственности куда больше(зависит конечно от области)


    1. select26
      23.12.2022 10:52
      +3

      Не всё в этом мире измеряется деньгами, коллега.


  1. igorking
    23.12.2022 11:24

    Пробовали подключить к linux машине? У меня почему-то на линуксе определяется как usb-com преобразователь. Пробовал подключить f4discovery с прошивкой от fetistova определился как rndis, но ip не получил.


    1. viteo Автор
      23.12.2022 11:53

      у меня на ubuntu запускается. смотрите, что у вас в dmesg

      ...


  1. xhd
    23.12.2022 12:41

    Из библиотек есть ещё stm32plus - с претензией, но слегка подзаброшенная.


  1. OldFashionedEngineer
    23.12.2022 17:03
    +3

    Не удивлюсь, если скоро на хабре появится статья о том, как в коллективе электронщиков появился программист, который, раздувая щеки, рассказывал про контроль версий и структуру проекта, а сам не понимал, как землю развести по схеме)))

    А если серьёзно, то конечно требования к прошивке МК сильно возрасли за последние десять - пятнадцать лет. И теперь целесообразно разделять работу над проектом на софт и хард.


  1. qoj
    23.12.2022 21:02
    +1

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

    Кмк решение почти как с версионированием кода копированием проекта. Лучше это делать в notion/obsidian.


  1. Rixty
    23.12.2022 22:12

    А подскажите, я с этой платой вообще не знаком, а есть ли возможность эмуляции вайфай флешки (устройство прикидывается флешкой, по факту же представляет доступ к первому диску)?

    Недавно был тут материал про есп32 в такой роли, но скорость там никакая. Да и автору не нужно было mtp или что то более современное. А у меня глупый телевизор lg, который умеет читать файлы с флешки, но не умеет больше ничего.

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


    1. kh0
      24.12.2022 03:24

      я так понял, вы хотите "пробросить" в телевизор сетевой диск. Готовых проектов под это наверное фиг найдешь, проще купить приставку на андроиде наверное. андроид будет заходить по сети к вам на комп и "показывать мультики".


  1. DungeonLords
    24.12.2022 10:42

    Автор пишет

    "Меня ждал сюрприз, когда поехала кодировка немногочисленных комментариев в коде. Оказалось, что все файлы были в CR1251."

    foreach($file in get-ChildItem *.c -Recurse) { (Get-Content -Path $file) | Set-Content -Encoding UTF8 -Path $file}

    Я не понимаю где и как запускать этот скрипт. И что скрипт сделает с файлом, который уже в UTF8? (грамотное поведение - не трогать) При попытке запустить код ожидаемо получил
    bash: syntax error near unexpected token `$file'

    Вот рабочее решение. Помогает перевести файлы проекта Microchip Studio/Atmel Studio в UTF8.

    Устанавливаем
    https://github.com/nijel/enca
    Заходим в папку с исходкиками
    cd ПутьКПапкеСИсходниками

    Запустим скрипт перевода всего, что в русских кодировках (russian: KOI8-R CP1251 ISO-8859-5 IBM866 maccyr) в UTF-8.
    find ./ -name ".c" -o -name ".h" -type f | while read file; do enca -L ru -x UTF-8 $file; done;