
Пролог
Каких только микроконтроллеров мне не приходилось программировать за 12 лет: AVR, STM8, MSP430x, STM32, NXP (LPC2148), Xilinx MicroBlaze, NIOS II, MDR32, ESP32, MIK32, SPC58NNx, сс26x2, NRF53, Artery AT32, YTM32, FlagChip FC7300x. В сумме 16 семейств микроконтроллеров. Все они разные, как снежинки.
Могу с уверенностью сказать, что любая прошивка для микроконтроллера зиждется на базовом системном коде. Это код настройки тактирования CLOCK, EEPROM, GPIO, I2S, NVS, PWM, SPI, TIMER, WATCHDOG, ADC, DAC, EXT_INT, I2C, INTERRUPT, PDM, RTC, SPIFI, UART, WDG, CAN, DMA, FLASH, I2S, PIN, SDIO, SWD, USB и прочего. Всё это называют разными словами: HAL, MCAL, EHAL, System Software, SPL и прочее. Чисто ради определенности выберем название MCAL (Microcontroller Abstraction Layer).
Любое приложение на микроконтроллере строится поверх MCAL.
При этом каждый производитель микроконтроллеров поставляет бесплатно свою открытую реализацию HAL, а иногда и сразу две (HAL или LL)
Vendor |
Название HAL |
язык реализации |
Artety |
AT32F435_437_Firmware_Library_EN_V2.1.5 |
C, ASM |
Nordoc |
nrfx-v2.1.0 |
С |
YunTu |
YTM32Bx_SDK |
C |
STm |
STM32F4xx_HAL_Driver |
С |
STm |
SPL |
C |
STm |
libopencm3 |
C |
TI |
simplelink_cc13x2_26x2_sdk |
С |
Espressiv |
ESP-IDF |
C |
Zephyr |
Zephyr HAL |
С |
Миландр |
Standard Peripherals Library |
C |
Mikron |
MIK32_HAL |
C |
Элвис |
ELIoT1_SDK |
.. |
и прочие |
... |
... |
Многие компании пишут реализацию HAL сами. Вплоть до регистров процессора. Каждый называет функции получившегося HAL как хочет.
В чем проблема?
Проблема в том, что при продолжительной разработке на одном семействе микроконтроллеров получается так, что приложение намертво привязано к конкретному семейству микроконтроллеров и его SDK, так как напрямую использует HAL от вендора.
Это особенно явно проявляется в таких случаях, когда надо переносить прошивку на другой микроконтроллер.
В таких случаях получается, что приходится заново писать всю прошивку, всё приложение, драйвера всех ASIC-ов. Переписывать каждый файл. Драйвер светодиодов, драйвер кнопок, драйвер ASICов c I2C SPI управлением. В общем всё переписывать. Поменяли MCU и пришлось переписать все файлы в репозитории. Нормально так да?
Определения
--Прототипом функции в языке Си называется объявление функции, не содержащее тела функции, но указывающее имя функции, типы аргументов и возвращаемый тип данных. В то время как определение функции описывает, что именно делает функция, прототип функции может восприниматься как описание её интерфейса (API).
--binding-и - это функции, которые просто вызывают другие функции. В переводе на кухонный язык - программный клей. Binding-и нужны только лишь для того, чтобы связать два совершенно разных API.
--proxy - уполномоченный, сделанный по доверенности, совершенный по доверенности, выданный по доверенности.
--лазанья-код – это идиоматическое выражение, используемое в IT-среде для обозначения кода, который имеет слишком много слоев абстракции, слои сильно взаимозависимы, и любое изменение в одном слое может негативно повлиять на весь проект.
--CLI - Интерфейс командной строки. Это способ взаимодействовать с программой обменом текстами по принципу запрос-ответ.
--ASIC- специализированная микросхема, которая выполняет только одну специфическую задачу аппаратно.
--SDK ( software development kit) — комплект для разработки программного обеспечения, набор инструментов для разработки программного обеспечения, объединённый в одной папке, обычно содержит комплект необходимых исходников, статических библиотек, компилятор, отладчик, иногда — интегрированную среду разработки.
По каким причинам обычно приходится переносить прошивку на совершенно другой микроконтроллер?
1--Прежний микроконтроллер морально устарел. Появились в продаже те, что производительнее, экономичнее и главное - дешевле.
2--Изначального микроконтроллера просто больше нет в продаже. Случился кризис полупроводников.
2--Прежний микроконтроллер невозможно больше купить в нужных количествах
3--Государство-производитель микроконтроллера наложило Санкции и Эмбарго на поставки своего микроконтроллера на Вашу территорию.
4--В новой версии продукта понадобился новый функционал (например Bluetooth 5.3), которого не было в предыдущем микроконтроллере на PCB. Всё. Меняем МК.
6--У вас в офисе может банально не хватить отладочных плат с вашим основным микроконтроллером и тут для отладки, условно, акселерометра подойдет какая-нибудь широко распространенная в продаже отладочная плата на основе другого уже микроконтроллера. И тут-то вы пожелаете переносимости прошивки на другое железо. Это чисто организационный момент.
7--Даже если Вы работаете только с одним семейством MCU, то рано или поздно Вы столкнётесь с багом, который захочется попробовать воспроизвести на другом микроконтроллере. И тут-то Вам понадобится собрать, то же приложение на , условно, STM32 или ESP32.
8--Менеджер проекта получил взятку (подарок) от производителя микроконтроллеров, чтобы в очередной версии серийного продукта компании был именно микроконтроллер от этого производителя (который дал взятку). Это не шутка, я такое видел.
Как видите, причин для миграции проекта на новое железо может быть сколько угодно. То есть существует электронный продукт (условно контроллер CNC станка или датчик дыма), а железо под ним меняется в зависимости от конъюнктуры. Товар пользуется спросом. Производство останавливать нельзя. Схемотехники ставят другой микроконтроллер, чтобы продолжать производство. Программистам надо приспосабливаться к программированию другой архитектуры.
Как решить проблему миграции FW на новое железо?
Очевидно, что нужен некоторый уровень абстракции для связи приложения и базового System Software. Нужен proxy MCAL, посредник для вызова API функций от того SDK, который поставляет данный конкретный вендор.

Переводя на кухонный язык, нужны одни и те же единообразные функции, которые будут по -своему реализованы для каждого отдельного микроконтроллера и семейства микроконтроллеров. Только и всего. Эти функции могут, как сами писать в регистры, так и вызывать готовый HAL от вендора. Это зависит лишь от того, сколько у Вас свободного времени.
Требования к MCAL?
1--Прежде всего proxy MCAL должен обладать таким свойством, как полнота. Должно быть много функций. Неприлично много функций. Функции на все случаи жизни. Если функция не нужна, то её просто надо делать weak функцией и компоновщик её сам выкинет из бинаря.
2--Принятие. MCAL должен признаваться коллегами. Все должны его дорабатывать. Повлиять на его создание.
3--Простота. Такой MCAL должен быть простым и интуитивно понятным. Все функции помещаются на одном экране. Там не надо очевидных комментариев. По модульным тестам и так будет понятно как им пользоваться. А модульные тесты будут найдены утилитой grep.
4--Масштабируемость.
5--Универсальность
6--Переносимость, независимость от платформы. Чтобы можно было даже на PC собирать код и, чтобы просто вызывались пустые функции.
7--MCAL должен управляться через UART-CLI. Чтобы можно было верифицировать каждую отдельную функцию в ручном режиме во время исполнения прошивки.
8--Для MCAL должны быть модульные тесты. Тесты нужны не только для испытаний проекта. Тесты служат, как документация к коду.
Вот пожалуй и всё.
Пример реализации MCAL
Рассмотрим на примере той функции которая точно есть в каждой прошивке: GPIO_Set. Это gpio_logic_level_set на stm32
bool gpio_logic_level_set(Pad_t pad, GpioLogicLevel_t logic_level) {
HAL_GPIO_WritePin(Port2PortPtr(pad.port), 1 << pad.pin,
(GPIO_PinState)logic_level);
return true;
}
Версия gpio_logic_level_set на nrf5340
bool gpio_logic_level_set(Pad_t Pad, GpioLogicLevel_t logic_level) {
bool res = false;
res = gpio_is_valid_pad(Pad);
if(res) {
nrf_gpio_pin_write((uint32_t)Pad.byte, (uint32_t)logic_level);
}
return res;
}
Версия gpio_logic_level_set на Artery AT32
/*can be called from isr*/
bool gpio_logic_level_set(Pad_t Pad, GpioLogicLevel_t logic_level) {
Pad_t pad = {0};
(void)pad;
pad.byte = pad_num;
gpio_type* GPIOx = Port2PortPtr(Pad.port);
if(GPIOx) {
switch((uint8_t)logic_level) {
case GPIO_LVL_HI: {
GPIOx->scr = 1 << Pad.pin;
} break;
case GPIO_LVL_LOW: {
GPIOx->clr = 1 << Pad.pin;
} break;
}
}
return true;
}
Как видите, название и аргументы у функции одни, а тело функции разное, в зависимости от микроконтроллера. Всё просто и лаконично. Это и есть binding-и.
Достоинства MCAL
Создание MCAL даст вам ряд очень важных достоинств:
1++Переносимость приложений. Вы пишите приложение под MCAL. Потом просто пишите binging-и под другой проц и получаете приложение на другом микроконтроллере. Красота!
2++Можно вызывать модульные тесты базового ПО через MCAL. Вы пишите модульные тесты только один раз для MCAL. Далее Вы тестируете HAL от вендора через готовые тесты для MCAL.
3++Управлять базовым ПО через CLI. Вы пишите CLI только один раз. Для MCAL. Вся остальная периферия уже запускается из CLI через binging-и на MCAL.
4++Вы можете разрабатывать и отлаживать драйвер SPI-Flash памяти вообще на любом микроконтроллере. Благодаря MCAL драйвер любого ASICа будет одинаковый для всех микроконтроллеров.
Недостатки Proxy MCAL
1--В каждом действии появляется ещё один вызов функции. Ваш код будет исполняться медленнее на 10-20 тактов процессора. Только и всего. Хотя непременно найдется кто-то кто назовет это "лазанья-код".
2--Надо очень осторожно подбирать имена для функций Proxy MCAL. Иной раз создашь функцию system_init(), а потом появится вендор, который в своем SDK тоже создал функцию system_init. Код SDK ты, естественно, менять не имеешь права. Это же чужой код. Поэтому приходится выпускать новый релиз proxy_mcal с переименованной функцией mcal_system_init. Та же история с названиями для перечислений.
Аналогии
На самом деле концепция proxy MCAL стара, как мир.
1-- Именно эту задачу решают Portable Operating System Interface (POSIX). Таким образом разные OS имеют один и тот же интерфейс.
2--Есть такой репозиторий Zephyr Project. У Zyphyr свой API для HAL. Поддержка огромного количества MCU. Zephyr весьма универсальный. Однако для пуска Zephyr вам придется переходить на CMake, Kconfig, DeviceTree, что не всегда возможно.
3--Существует AUTOSAR методология для создания переносимых прошивок. Там уже есть готовые названия эталонных функций для MCAL. Однако AUTOSAR подразумевает существенную оплату за присоединения к консорциуму и получение исходников. Коллега как-то отметил, что покупка универсального драйвера сторожевого таймера из AUTOSAR стоит 30k EUR. Это то, что любой русский программист МК пишет за три дня.
Вам не обязательно покупать исходники AUTOSAR, чтобы добиться переносимости. Вы можете сами внутри своей организации договориться о том как будет выглядеть ваш внутренний proxy MCAL. Хотя конечно было бы лучше, если был бы некоторый индустриальный стандарт для того, чтобы единообразно называть функции для HAL для доступа к GPIO UART SPI и прочее между всеми производителями микроконтроллеров в стране: Миландр, Микрон, ЭЛВИС, НИИЭТ, Байкал, ДЦ Союз, Цифровые решения, Ангстрем, НИИСИ РАН и прочие.
Если Вы получили сорцы от другой организации и там условно уже есть proxy_MCAL1, а у вас давно работает proxy_MCAL2, то это тоже не беда. Вы просто напишете binding-и c proxy_MCAL1 на proxy_MCAL2 или наоборот. И приложение заведется само собой.
Итоги
Задача переносимости прошивок с микроконтроллера на микроконтроллер полностью решается через создание уровня абстракции под названием proxy MCAL. Благодяря MCAL миграция на новый MCU станет простой задачей.
При переходе на новые микроконтроллер вам надо всего-навсего написать binding с MCAL на HAL от вендора. Это простая задача, которую можно получить даже студенту. И, таким образом, ваш прибор заработает, как и прежде на новом SoC-е, как ни в чем не бывало.
Вот моя реализация proxy_mcal https://github.com/aabzel/proxy_mcal . Специально выкладываю ее для опровержения.
Словарь
Акроним |
Расшифровка |
HAL |
Hardware Abstraction Layer |
MCAL |
Microcontroller Abstraction Layer |
POSIX |
Portable Operating System Interface |
SPL |
Standard Peripherals Library |
CLI |
command-line interface |
FW |
Firmware |
API |
application programming interface |
SoC |
System-on-a-Chip |
PCB |
Printed circuit board |
ASIC |
Application Specific Integrated Circuit |
ПО |
Программное обеспечение |
ASM |
Язык ассемблера |
Ссылки
№ |
название |
URL |
1 |
Моя версия proxy MCAL |
|
2 |
Что Должно Быть в Каждом FirmWare Pепозитории |
|
3 |
Архитектура Хорошо Поддерживаемого Программного Компонента |
|
4 |
Атрибуты Хорошего С-кода (Хартия Си Программистов) |
|
5 |
Примеры абстракций в технике и повседневности |
|
6 |
Архитектура Xорошего Кода Прошивки (Массив-Наше Всё) |
|
7 |
Диспетчер Задач для Микроконтроллера |
Комментарии (34)
Goron_Dekar
22.05.2025 19:48В C++ для решения этой проблемы есть концепция zero-cost abdtractions. В 2025 писать на МК без современных плюсов как-то странно.
ну и mbed, как неплохой пример реализации этой идеи, пусть и не использующий всей новизны.
У нас, когда ещё писали мк, было принято выносить аппаратно-зависимый код в отдельную часть проекта, а в логике стоял неявный запрет на инклюды хедеров HALа.
однако, всякая тонкая оптимизация, свойственная мк проектам, быстро разрушала эту стену: тонкости dma, usb, lan-mac и can настолько отличались от мк к мк, что если мы экономили каждую мс без сна (а это важно при питании от батареи), то код всё равно был сильно привязан к архитектуре.
конечно, если питание от сети, то можно взять малину и писать на питоне. Выйдет даже дешевле.
Koyanisqatsi
22.05.2025 19:48Согласен, когда в примерах указывают функцию переключения типа gpio_pin_write(), то всё прекрасно выглядит, но модули покрупнее и посложнее, внутреннее поведение которых разнится от МК к МК только усложнят жизнь по крайней мере разработчику такого MCAL.
BelerafonL
22.05.2025 19:48Читал-читал и думал - ну вот сейчас автор покажет реализацию своего MCAL на гитхабе, ну или хотя бы примеры, как может быть красиво и абстрактно реализован тот же доступ к GPIO при таком зоопарке подходов. Не говоря уже о каком-нибудь CAN - там даже философия аппаратных модулей внутри микроконтроллеров разная, у кого-то есть куча ящиков, у кого-то fifo сложные и фильтры, у кого-то свой CAN-подпроцессор со своим набором команд.
Не понимаю, как можно тут придумать что-то универсальное и гибкое не получив спагетти-код или не получив ограничение функционала, где через MCAL пролезет 5% от того что умеет аппаратная часть микроконтроллера. Думал, может хоть этот момент автор рассмотрит на каком-то сложном примере, но нет... О чём тогда статья, непонятно. Я как считал что сферический в вакууме MCAL не реализуем, так и считаю.
aabzel Автор
22.05.2025 19:48" автор покажет реализацию своего MCAL на гитхабе,"
https://github.com/aabzel/proxy_mcal(для опровержения)
Indemsys
22.05.2025 19:48Вот что сказал об этом ChatGPT o3
Короткий вывод
В репозитории фактически лежит лишь набор «заготовок» для системы MCAL-драйверов: несколько Makefile/CMake-скриптов и пустой
read_me.txt
. Исходников, которые можно прямо собрать и запустить, там нет — большинство файлов, на которые ссылаются скрипты, отсутствуют. То есть «из коробки» использовать ничего не получится: придётся либо дописывать недостающие модули, либо подключать внешний MCAL-код.Это что-то новое - выкладывать шлак и по его мотивам писать статьи по теме микрокнтроллеров.
Откуда тогда столько файлов?
MCAL-слой часто собирают скриптом-генератором, читающим YAML/Kconfig с конфигурацией проекта. Такой скрипт:
делает копии общих template-файлов в каталог проекта;
проставляет нужные
#define
иCMake/Make
-флаги;генерирует
_commands.c
для CLI-оболочки,_diag.c
для диагностики и т. д.
В коммите как раз видны одинаково оформленные пары файлов («general», «diag», «commands») для каждого переферийного блока — это типичный вывод такого инструмента.
Да, нынче трудно стало водить за нос.
BelerafonL
22.05.2025 19:48Ну мой o3 - я ему дал весь репозиторий в zip - говорит что всё настоящее, но только верхний слой абстракции, без слоёв микроконтроллеров. И частично рукописное. Цитирую o3:
-
В папке
mcal_common/
лежит ≈ 30 модулей (GPIO, UART, DMA, …).
Для каждого «живого» модуля присутствуют:_general
.c
— основная логика (state-машины, буферы, таймауты и т.п.);*_commands.c
— набор CLI-команд для отладочной консоли;*_diag.c
— обход регистров, self-test, счётчики ошибок.
Код этой части компилируемый и читабельный — он написан вручную (комментарии, осмыслённые имена, нет признаков автосгенерированного мусора).
Общие макросы
COMPONENT_GET_NODE/CONFIG
и ссылки наcode_generator.h
показывают, что к каждой сборке должен добавляться автоматически сгенерированный файл с описанием таблиц конфигурации (маску выводов, частоты, номера каналов…). Сам генератор (скрипт/утилита) в архив не положен.MCU-специфичного слоя нет вообще. Нет каталогов вида
mcal_stm32f4/
,mcal_esp32/
и даже простых «заглушек» с прямым доступом к периферии.
Поэтому все вызовы видаgpio_pin_set_ll()
,adc_start_ll()
и т.п. остаются «висящими».Отдельные модули действительно пока пустые: например,
mcal_common/wdg/
содержит толькоwdg_const.h
и.mk
— чистый каркас без строчки кода.
Чем уже можно пользоваться
Алгоритмическая «верхушка». Логика обмена по CAN (очереди, сортировка по приоритету, ожидание TX Ack), I²C-FSM, FSM для I²S full-duplex, универсальные таймерные обёртки, фоновые state-машины PWM/RTC — их можно подключить к своему проекту и «подшить» к собственным низкоуровневым вызовам.
CLI-команды и диагностика. Если заведёте свою систему логов (
log.h
) и консоль, уже готов базовый набор команд:adc_init
,gpio_toggle
,dma_stat
, …Make/CMake-инфраструктура. Файлы
mcal.mk
иmcal.cmake
умеют по флагам подключать нужные модули, размазывать#define HAS_<MODULE>
и добавлять include-пути.
Что придётся дописать
Нижний уровень для каждого семейства МК.
Создаёте папкуmcal_<chip>
и реализуете функции*_ll()
(low level), структуруComponentDriver_t
, ISR, карту прерываний. Это 70-80 % работы.Генератор конфигурации.
Скрипт (часто на Python) читает YAML/Excel со схемой платы и штампуетcode_generator.h
+*_config.c
. Без него даже общая часть не соберётся: массивыAdcNode[]
,GpioPad[]
,ClockDomain[]
просто не объявлены.Сторонние заголовки.
Упоминаются, но отсутствуют:convert.h
,time_mcal.h
,none_blocking_pause.h
и др. Их нужно либо написать, либо убрать зависимости.
Сгенерировано или вручную?
Файлы .c / .h внутри
mcal_common
— рукописные. Есть авторские комментарии,LOG_INFO()
расставлены выборочно, стилистика единообразна.Автоген требуются только для структур данных (константные таблицы и массивы), на что прямо указывают закомментированные строки
#include "c_defines_generated.h"
.
Итого
Репозиторий даёт полноценный «бизнес-слой» периферии (state-машины, очереди, CLI, диагностика).
Без собственных драйверов и конфигуратора он нерабочий — это половина конструкции.
Писать придётся много: низкоуровневые функции для каждой периферии, генератор таблиц и пару вспомогательных утилит.
aabzel Автор
22.05.2025 19:48Вы что купили подписку на chatGpt?
BelerafonL
22.05.2025 19:48Да а как нынче жить-то без этого... это же как вторая голова. Вот пока это пишу, оно мне рассказывает как с помощью Вашего MCAL выглядел бы мой драйвер J1939. Но вообще надо клод брать, вчера вот 4й вышел.
BelerafonL
22.05.2025 19:48Ну вот, говорит, вместо использования кучи аппаратных меилбоксов, как в моём оригинальном драйвере (каждый меилбокс со своим ID и приоритетом) мне придется самому программно засовывать все сообщения в единую свою FIFO очередь и вызывать ваш can_api_transmit_data - но который может ещё и не записать данные, и надо проверять что сообщение ушло через can_wait_tx_done_ll. А оно может не уйти, потому что, скажем, линия занята низкоприоритетными сообщениями, а мне надо отправить что-то срочное. И мне придется отменять отправку текущего сообщения (которое застряло и не уходит) и проталкивать более срочное. Притом что у вас CAN_abort пока и не предусмотрено.
Итого, придется работать с CAN "через одну дырку" делая программно свою приоритизированную очередь, вместо того, чтобы натолкать новых данных в десяток аппаратных мейлбоксов и забыть - сами отправятся по своим триггерам и приоритету (сейчас у меня так). В итоге накладные расходы использования вашего MCAL это не "10-20 тактов процессора" на вызов обертки MCAL, а существенное изменение архитектуры драйвера, который вместо полагания на аппаратные возможности микроконтроллера будет вынужден пользоваться кастрированным узким API MCAL, тратить кучу ресурсов на организацию своих приоритетов, FIFO и менеджера отправки данных в сеть CAN.
randomsimplenumber
22.05.2025 19:48Хм. У вас тот же chatgpt,но совершенно другой вывод. Как так?
BelerafonL
22.05.2025 19:48Ну почему другой - и тот и этот написали что больше части файлов нет, а именно привязки к микроконтроллерам. Разнится оценка вклада имеющегося кода: один раз он написал что это только скелет с обертками, другой раз решил что это уже половина дела уже. Ну а так-то да, gpt что дышло, как спроси так и вышло
Indemsys
22.05.2025 19:48Это довольно странно качать в Zip, а потом за свои же деньги заставлять GPT это распаковывать при этом потерять историю коммитов. Лучше смотреть прямо на GitHub-е. Там GPT дополнительно посмотрит как юзер активничал.
Но мой o3 пошел дальше и все же думает, что автор втихую использовал один из корпоративных генераторов сорсов:
- Vector DaVinci Configurator Classic / Pro
- EB tresos Studio
- ETAS ISOLAR-A, Mentor VSTAR, Artop
Но только потом он исходники еще сильно кастрировал.
BelerafonL
22.05.2025 19:48У меня давече с другим проектом gpt o3 имел проблемы с ориентацией по гитхабу, а zip файл он разархивировал внутри и сразу все прочитал. Да и в plus подписке ограничивается число вызовов в неделю, и там и там один - что ссылку дать, что архив. Ну да лирика все это, и так понятно.
aabzel Автор
22.05.2025 19:48" Vector DaVinci Configurator Classic / Pro, EB tresos Studio, ETAS ISOLAR-A, Mentor VSTAR, Artop"
Впервые узнаю, что есть такие утилиты.
aabzel Автор
22.05.2025 19:48Я согласен с тем, что ChatGPT написал про мой код. По сути он перефразировал заметку на habr .
-
aabzel Автор
22.05.2025 19:48Как говорил мой начальник- схемотехник
"Не нужны нам программисты микроконтроллеров, ChatGPT сам напишет нам hex файл прошивки"randomsimplenumber
22.05.2025 19:48ChatGPT сам напишет нам hex файл прошивки
И схему тоже нарисует. Хочешь в стиле Сальвадора Дали, хочешь под стимпанк. Схемотехники, готовьтесь :)
AlexGfr
22.05.2025 19:48Нечто подобное есть Кристофера Корманиоса, автора кникги Real-Time C++: Efficient Object-Oriented and Template Microcontroller Programming: GitHub - ckormanyos/real-time-cpp: Source code for the book Real-Time C++, by Christopher Kormanyos
И у коллеги по работе было - набор библиотек, обеспечивающий единое API для всех используемых платформ и даже существующий в одной единственноверной версии с которой собираются все проекты.
Лютый героизм поддерживать такое, не могу сказать что в моих проектах есть нечто подобное.
DrZliden
22.05.2025 19:48-Сегодня первое, что делают люди, когда атакуют твою Темную Башню Зла - это заваливают тоннель для побега, - сказал Злобный Гарри.
-Ублюдки! - сказал Коэн. - Ты должен позволить Темному Повелителю скрыться. Все это знают.
-Это точно, - сказал Калеб. - Нужно оставлять себе немного работы на завтра.* ("Последний Герой")Так вот надо всегда оставлять немного работы на завтра. А переписать всё под новый контроллер это замечательная работа. Если не оставить её себе, то тебе поручат другую работу, которая может быть уже далеко не такой хорошей.
С третьей стороны, переписывать каждый раз MCAL на другой контроллер тоже работа....
SIISII
22.05.2025 19:48А я вот никогда не использую "HAL от вендора" -- у меня самописное всё, от GPIO до USB. Ну, это если про нижний уровень, работающий прямо с железом, говорить. На среднем уже возможны варианты (скажем, использую LVGL, а если потребуется прикрутить сеть, возьму lwIP).
aabzel Автор
22.05.2025 19:48Аналог FatFs тоже сами написали?
SIISII
22.05.2025 19:48Да. Полностью асинхронный (а не чисто синхронный, как FatFs -- собсно, потому и написал свой). Причём использовал сопрограммы C++20 -- собсно, потренировался на кошечках :) Правда, сейчас перепишу на обычные процедуры обратного вызова, поскольку Кейловскому отладчику наличие сопрограмм начисто срывает крышу -- отлаживать можно только на уровне дизассемблера, причём не только сами сопрограммы, но и код более высокого уровня.
rukhi7
22.05.2025 19:48вот это не фига себе признание! Я тоже думаю что всегда лучше писать в рамках С++11 максимум. Кроме того что можно нормально отлаживаться, переносимость повышается туда куда последние достижения еще не завезли.
aabzel Автор
22.05.2025 19:48Вендор вендору рознь. Вот у stm плохой Hal . Хуже st Hal ни у кого в мире нет. А у китайцев artery, yuntu , flagchip - великолепный hal.
aabzel Автор
22.05.2025 19:48Издевка судьбы в том, что Mik32 слепо выбрали копировать именно самый галимый STшный HAL.
https://github.com/MikronMIK32/mik32-hal/tree/main/peripherals/Source
буквально прототип в прототип
rukhi7
22.05.2025 19:48Hal пишется для примера, чтобы продемонстрировать только основные возможности железа. Эта цель обычно вступает в прямое противоречие с эффективностью, когда надо сделать что-то специальное самым оптимальным способом.
Чтобы обеспечить эффективность надо анализировать функции железа и их взаимодействие на уровне доступных регистров, и на уровне взаимодействия операций в железе, а не на уровне показушных функций.
NutsUnderline
22.05.2025 19:48Это другая сторона большой legacy. Есть же вариант когда как бы наоборот: сделали один раз (на 8051) и отказаться никак не могут, допиливают, и даже эмулируют старое, т.е. как бы даже не переписывают. потому что где то была очень тонкая фишка которой потом нигде просто нет.
В psoc сypress например много встроенного аналога, в новых attiny всякие lut элементы, ну шины событий - как раз то изза чего можно упростить и схему и код
acc0unt
Вы изобрели "толстую" RTOS вроде Zephyr.
aabzel Автор
Zephyr пере усложнен наличием device tree и механизмом kconfig .
Я же предлагаю взять от zephyr только методологию proxy Hal. И больше ничего.
beefdeadbeef
device tree там не от сырости завёлся, но от того факта, что заметное количество блоков (IP) в контроллерах существует в двух-трёх вариантах на всех -- приходят на ум контроллеры DMA, EMAC, тот же USB в вариантах fs/hs/otg.
Собственно, на идее драйвера, привязанного к DT'шному compatible, весь arm'овый, да и не только, линукс построен.