Пролог

Каких только микроконтроллеров мне не приходилось программировать за 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

 https://github.com/aabzel/proxy_mcal

2

Что Должно Быть в Каждом FirmWare Pепозитории

https://habr.com/ru/articles/689542/

3

Архитектура Хорошо Поддерживаемого Программного Компонента

https://habr.com/ru/articles/683762/

4

Атрибуты Хорошего С-кода (Хартия Си Программистов)

https://habr.com/ru/articles/679256/

5

Примеры абстракций в технике и повседневности

https://habr.com/ru/articles/715146/

6

Архитектура Xорошего Кода Прошивки (Массив-Наше Всё)

https://habr.com/ru/articles/816589/

7

Диспетчер Задач для Микроконтроллера

https://habr.com/ru/articles/757000/

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


  1. acc0unt
    22.05.2025 19:48

    Вы изобрели "толстую" RTOS вроде Zephyr.


    1. aabzel Автор
      22.05.2025 19:48

      Zephyr пере усложнен наличием device tree и механизмом kconfig .
      Я же предлагаю взять от zephyr только методологию proxy Hal. И больше ничего.


      1. beefdeadbeef
        22.05.2025 19:48

        device tree там не от сырости завёлся, но от того факта, что заметное количество блоков (IP) в контроллерах существует в двух-трёх вариантах на всех -- приходят на ум контроллеры DMA, EMAC, тот же USB в вариантах fs/hs/otg.

        Собственно, на идее драйвера, привязанного к DT'шному compatible, весь arm'овый, да и не только, линукс построен.


  1. Goron_Dekar
    22.05.2025 19:48

    В C++ для решения этой проблемы есть концепция zero-cost abdtractions. В 2025 писать на МК без современных плюсов как-то странно.

    ну и mbed, как неплохой пример реализации этой идеи, пусть и не использующий всей новизны.

    У нас, когда ещё писали мк, было принято выносить аппаратно-зависимый код в отдельную часть проекта, а в логике стоял неявный запрет на инклюды хедеров HALа.

    однако, всякая тонкая оптимизация, свойственная мк проектам, быстро разрушала эту стену: тонкости dma, usb, lan-mac и can настолько отличались от мк к мк, что если мы экономили каждую мс без сна (а это важно при питании от батареи), то код всё равно был сильно привязан к архитектуре.

    конечно, если питание от сети, то можно взять малину и писать на питоне. Выйдет даже дешевле.


    1. Koyanisqatsi
      22.05.2025 19:48

      Согласен, когда в примерах указывают функцию переключения типа gpio_pin_write(), то всё прекрасно выглядит, но модули покрупнее и посложнее, внутреннее поведение которых разнится от МК к МК только усложнят жизнь по крайней мере разработчику такого MCAL.


  1. BelerafonL
    22.05.2025 19:48

    Читал-читал и думал - ну вот сейчас автор покажет реализацию своего MCAL на гитхабе, ну или хотя бы примеры, как может быть красиво и абстрактно реализован тот же доступ к GPIO при таком зоопарке подходов. Не говоря уже о каком-нибудь CAN - там даже философия аппаратных модулей внутри микроконтроллеров разная, у кого-то есть куча ящиков, у кого-то fifo сложные и фильтры, у кого-то свой CAN-подпроцессор со своим набором команд.

    Не понимаю, как можно тут придумать что-то универсальное и гибкое не получив спагетти-код или не получив ограничение функционала, где через MCAL пролезет 5% от того что умеет аппаратная часть микроконтроллера. Думал, может хоть этот момент автор рассмотрит на каком-то сложном примере, но нет... О чём тогда статья, непонятно. Я как считал что сферический в вакууме MCAL не реализуем, так и считаю.


    1. randomsimplenumber
      22.05.2025 19:48

      Arduino core :)


    1. aabzel Автор
      22.05.2025 19:48

      " автор покажет реализацию своего MCAL на гитхабе,"
      https://github.com/aabzel/proxy_mcal

      (для опровержения)


      1. Indemsys
        22.05.2025 19:48

        Вот что сказал об этом ChatGPT o3

        Короткий вывод

        В репозитории фактически лежит лишь набор «заготовок» для системы MCAL-драйверов: несколько Makefile/CMake-скриптов и пустой read_me.txt. Исходников, которые можно прямо собрать и запустить, там нет — большинство файлов, на которые ссылаются скрипты, отсутствуют. То есть «из коробки» использовать ничего не получится: придётся либо дописывать недостающие модули, либо подключать внешний MCAL-код.

        Это что-то новое - выкладывать шлак и по его мотивам писать статьи по теме микрокнтроллеров.

        Откуда тогда столько файлов?

        MCAL-слой часто собирают скриптом-генератором, читающим YAML/Kconfig с конфигурацией проекта. Такой скрипт:

        1. делает копии общих template-файлов в каталог проекта;

        2. проставляет нужные #define и CMake/Make-флаги;

        3. генерирует _commands.c для CLI-оболочки, _diag.c для диагностики и т. д.

        В коммите как раз видны одинаково оформленные пары файлов («general», «diag», «commands») для каждого переферийного блока — это типичный вывод такого инструмента.

        Да, нынче трудно стало водить за нос.


        1. 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-пути.

          Что придётся дописать

          1. Нижний уровень для каждого семейства МК.
            Создаёте папку mcal_<chip> и реализуете функции *_ll() (low level), структуру ComponentDriver_t, ISR, карту прерываний. Это 70-80 % работы.

          2. Генератор конфигурации.
            Скрипт (часто на Python) читает YAML/Excel со схемой платы и штампует code_generator.h + *_config.c. Без него даже общая часть не соберётся: массивы AdcNode[], GpioPad[], ClockDomain[] просто не объявлены.

          3. Сторонние заголовки.
            Упоминаются, но отсутствуют: convert.h, time_mcal.h, none_blocking_pause.h и др. Их нужно либо написать, либо убрать зависимости.

          Сгенерировано или вручную?

          • Файлы .c / .h внутри mcal_common — рукописные. Есть авторские комментарии, LOG_INFO() расставлены выборочно, стилистика единообразна.

          • Автоген требуются только для структур данных (константные таблицы и массивы), на что прямо указывают закомментированные строки #include "c_defines_generated.h".

          Итого

          • Репозиторий даёт полноценный «бизнес-слой» периферии (state-машины, очереди, CLI, диагностика).

          • Без собственных драйверов и конфигуратора он нерабочий — это половина конструкции.

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


          1. aabzel Автор
            22.05.2025 19:48

            Вы что купили подписку на chatGpt?


            1. BelerafonL
              22.05.2025 19:48

              Да а как нынче жить-то без этого... это же как вторая голова. Вот пока это пишу, оно мне рассказывает как с помощью Вашего MCAL выглядел бы мой драйвер J1939. Но вообще надо клод брать, вчера вот 4й вышел.


              1. aabzel Автор
                22.05.2025 19:48

                И сколько стоит тариф?


                1. BelerafonL
                  22.05.2025 19:48

                  2000-2500р в месяц примерно в зависимости через какие сервисы платить.


              1. 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.


          1. randomsimplenumber
            22.05.2025 19:48

            Хм. У вас тот же chatgpt,но совершенно другой вывод. Как так?


            1. BelerafonL
              22.05.2025 19:48

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


          1. 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

            Но только потом он исходники еще сильно кастрировал.


            1. BelerafonL
              22.05.2025 19:48

              У меня давече с другим проектом gpt o3 имел проблемы с ориентацией по гитхабу, а zip файл он разархивировал внутри и сразу все прочитал. Да и в plus подписке ограничивается число вызовов в неделю, и там и там один - что ссылку дать, что архив. Ну да лирика все это, и так понятно.


            1. aabzel Автор
              22.05.2025 19:48

              " Vector DaVinci Configurator Classic / Pro, EB tresos Studio, ETAS ISOLAR-A, Mentor VSTAR, Artop"
              Впервые узнаю, что есть такие утилиты.


          1. aabzel Автор
            22.05.2025 19:48

            Я согласен с тем, что ChatGPT написал про мой код. По сути он перефразировал заметку на habr .


        1. aabzel Автор
          22.05.2025 19:48

          Как говорил мой начальник- схемотехник
          "Не нужны нам программисты микроконтроллеров, ChatGPT сам напишет нам hex файл прошивки"


          1. randomsimplenumber
            22.05.2025 19:48

            ChatGPT сам напишет нам hex файл прошивки

            И схему тоже нарисует. Хочешь в стиле Сальвадора Дали, хочешь под стимпанк. Схемотехники, готовьтесь :)


    1. 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 для всех используемых платформ и даже существующий в одной единственноверной версии с которой собираются все проекты.

      Лютый героизм поддерживать такое, не могу сказать что в моих проектах есть нечто подобное.


  1. x89377
    22.05.2025 19:48

    Каждый начинает со своего MCAL. А получается просто CAL


  1. DrZliden
    22.05.2025 19:48

    -Сегодня первое, что делают люди, когда атакуют твою Темную Башню Зла - это заваливают тоннель для побега, - сказал Злобный Гарри.
    -Ублюдки! - сказал Коэн. - Ты должен позволить Темному Повелителю скрыться. Все это знают.
    -Это точно, - сказал Калеб. - Нужно оставлять себе немного работы на завтра.* ("Последний Герой")

    Так вот надо всегда оставлять немного работы на завтра. А переписать всё под новый контроллер это замечательная работа. Если не оставить её себе, то тебе поручат другую работу, которая может быть уже далеко не такой хорошей.
    С третьей стороны, переписывать каждый раз MCAL на другой контроллер тоже работа....


  1. SIISII
    22.05.2025 19:48

    А я вот никогда не использую "HAL от вендора" -- у меня самописное всё, от GPIO до USB. Ну, это если про нижний уровень, работающий прямо с железом, говорить. На среднем уже возможны варианты (скажем, использую LVGL, а если потребуется прикрутить сеть, возьму lwIP).


    1. aabzel Автор
      22.05.2025 19:48

      Аналог FatFs тоже сами написали?


      1. SIISII
        22.05.2025 19:48

        Да. Полностью асинхронный (а не чисто синхронный, как FatFs -- собсно, потому и написал свой). Причём использовал сопрограммы C++20 -- собсно, потренировался на кошечках :) Правда, сейчас перепишу на обычные процедуры обратного вызова, поскольку Кейловскому отладчику наличие сопрограмм начисто срывает крышу -- отлаживать можно только на уровне дизассемблера, причём не только сами сопрограммы, но и код более высокого уровня.


        1. rukhi7
          22.05.2025 19:48

          вот это не фига себе признание! Я тоже думаю что всегда лучше писать в рамках С++11 максимум. Кроме того что можно нормально отлаживаться, переносимость повышается туда куда последние достижения еще не завезли.


    1. aabzel Автор
      22.05.2025 19:48

      Вендор вендору рознь. Вот у stm плохой Hal . Хуже st Hal ни у кого в мире нет. А у китайцев artery, yuntu , flagchip - великолепный hal.


      1. aabzel Автор
        22.05.2025 19:48

        Издевка судьбы в том, что Mik32 слепо выбрали копировать именно самый галимый STшный HAL.
        https://github.com/MikronMIK32/mik32-hal/tree/main/peripherals/Source
        буквально прототип в прототип


      1. rukhi7
        22.05.2025 19:48

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

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


  1. NutsUnderline
    22.05.2025 19:48

    Это другая сторона большой legacy. Есть же вариант когда как бы наоборот: сделали один раз (на 8051) и отказаться никак не могут, допиливают, и даже эмулируют старое, т.е. как бы даже не переписывают. потому что где то была очень тонкая фишка которой потом нигде просто нет.

    В psoc сypress например много встроенного аналога, в новых attiny всякие lut элементы, ну шины событий - как раз то изза чего можно упростить и схему и код