Комментарии 33
Вы изобрели "толстую" RTOS вроде Zephyr.
Zephyr пере усложнен наличием device tree и механизмом kconfig .
Я же предлагаю взять от zephyr только методологию proxy Hal. И больше ничего.
device tree там не от сырости завёлся, но от того факта, что заметное количество блоков (IP) в контроллерах существует в двух-трёх вариантах на всех -- приходят на ум контроллеры DMA, EMAC, тот же USB в вариантах fs/hs/otg.
Собственно, на идее драйвера, привязанного к DT'шному compatible, весь arm'овый, да и не только, линукс построен.
В C++ для решения этой проблемы есть концепция zero-cost abdtractions. В 2025 писать на МК без современных плюсов как-то странно.
ну и mbed, как неплохой пример реализации этой идеи, пусть и не использующий всей новизны.
У нас, когда ещё писали мк, было принято выносить аппаратно-зависимый код в отдельную часть проекта, а в логике стоял неявный запрет на инклюды хедеров HALа.
однако, всякая тонкая оптимизация, свойственная мк проектам, быстро разрушала эту стену: тонкости dma, usb, lan-mac и can настолько отличались от мк к мк, что если мы экономили каждую мс без сна (а это важно при питании от батареи), то код всё равно был сильно привязан к архитектуре.
конечно, если питание от сети, то можно взять малину и писать на питоне. Выйдет даже дешевле.
Читал-читал и думал - ну вот сейчас автор покажет реализацию своего MCAL на гитхабе, ну или хотя бы примеры, как может быть красиво и абстрактно реализован тот же доступ к GPIO при таком зоопарке подходов. Не говоря уже о каком-нибудь CAN - там даже философия аппаратных модулей внутри микроконтроллеров разная, у кого-то есть куча ящиков, у кого-то fifo сложные и фильтры, у кого-то свой CAN-подпроцессор со своим набором команд.
Не понимаю, как можно тут придумать что-то универсальное и гибкое не получив спагетти-код или не получив ограничение функционала, где через MCAL пролезет 5% от того что умеет аппаратная часть микроконтроллера. Думал, может хоть этот момент автор рассмотрит на каком-то сложном примере, но нет... О чём тогда статья, непонятно. Я как считал что сферический в вакууме MCAL не реализуем, так и считаю.
Arduino core :)
" автор покажет реализацию своего MCAL на гитхабе,"
https://github.com/aabzel/proxy_mcal
(для опровержения)
Вот что сказал об этом ChatGPT o3
Короткий вывод
В репозитории фактически лежит лишь набор «заготовок» для системы MCAL-драйверов: несколько Makefile/CMake-скриптов и пустой
read_me.txt
. Исходников, которые можно прямо собрать и запустить, там нет — большинство файлов, на которые ссылаются скрипты, отсутствуют. То есть «из коробки» использовать ничего не получится: придётся либо дописывать недостающие модули, либо подключать внешний MCAL-код.
Это что-то новое - выкладывать шлак и по его мотивам писать статьи по теме микрокнтроллеров.
Откуда тогда столько файлов?
MCAL-слой часто собирают скриптом-генератором, читающим YAML/Kconfig с конфигурацией проекта. Такой скрипт:
делает копии общих template-файлов в каталог проекта;
проставляет нужные
#define
иCMake/Make
-флаги;генерирует
_commands.c
для CLI-оболочки,_diag.c
для диагностики и т. д.В коммите как раз видны одинаково оформленные пары файлов («general», «diag», «commands») для каждого переферийного блока — это типичный вывод такого инструмента.
Да, нынче трудно стало водить за нос.
Ну мой 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, диагностика).
Без собственных драйверов и конфигуратора он нерабочий — это половина конструкции.
Писать придётся много: низкоуровневые функции для каждой периферии, генератор таблиц и пару вспомогательных утилит.
Вы что купили подписку на chatGpt?
Да а как нынче жить-то без этого... это же как вторая голова. Вот пока это пишу, оно мне рассказывает как с помощью Вашего MCAL выглядел бы мой драйвер J1939. Но вообще надо клод брать, вчера вот 4й вышел.
И сколько стоит тариф?
Ну вот, говорит, вместо использования кучи аппаратных меилбоксов, как в моём оригинальном драйвере (каждый меилбокс со своим ID и приоритетом) мне придется самому программно засовывать все сообщения в единую свою FIFO очередь и вызывать ваш can_api_transmit_data - но который может ещё и не записать данные, и надо проверять что сообщение ушло через can_wait_tx_done_ll. А оно может не уйти, потому что, скажем, линия занята низкоприоритетными сообщениями, а мне надо отправить что-то срочное. И мне придется отменять отправку текущего сообщения (которое застряло и не уходит) и проталкивать более срочное. Притом что у вас CAN_abort пока и не предусмотрено.
Итого, придется работать с CAN "через одну дырку" делая программно свою приоритизированную очередь, вместо того, чтобы натолкать новых данных в десяток аппаратных мейлбоксов и забыть - сами отправятся по своим триггерам и приоритету (сейчас у меня так). В итоге накладные расходы использования вашего MCAL это не "10-20 тактов процессора" на вызов обертки MCAL, а существенное изменение архитектуры драйвера, который вместо полагания на аппаратные возможности микроконтроллера будет вынужден пользоваться кастрированным узким API MCAL, тратить кучу ресурсов на организацию своих приоритетов, FIFO и менеджера отправки данных в сеть CAN.
Хм. У вас тот же chatgpt,но совершенно другой вывод. Как так?
Ну почему другой - и тот и этот написали что больше части файлов нет, а именно привязки к микроконтроллерам. Разнится оценка вклада имеющегося кода: один раз он написал что это только скелет с обертками, другой раз решил что это уже половина дела уже. Ну а так-то да, gpt что дышло, как спроси так и вышло
Это довольно странно качать в Zip, а потом за свои же деньги заставлять GPT это распаковывать при этом потерять историю коммитов. Лучше смотреть прямо на GitHub-е. Там GPT дополнительно посмотрит как юзер активничал.
Но мой o3 пошел дальше и все же думает, что автор втихую использовал один из корпоративных генераторов сорсов:
- Vector DaVinci Configurator Classic / Pro
- EB tresos Studio
- ETAS ISOLAR-A, Mentor VSTAR, Artop
Но только потом он исходники еще сильно кастрировал.
У меня давече с другим проектом gpt o3 имел проблемы с ориентацией по гитхабу, а zip файл он разархивировал внутри и сразу все прочитал. Да и в plus подписке ограничивается число вызовов в неделю, и там и там один - что ссылку дать, что архив. Ну да лирика все это, и так понятно.
" Vector DaVinci Configurator Classic / Pro, EB tresos Studio, ETAS ISOLAR-A, Mentor VSTAR, Artop"
Впервые узнаю, что есть такие утилиты.
Как говорил мой начальник- схемотехник
"Не нужны нам программисты микроконтроллеров, ChatGPT сам напишет нам hex файл прошивки"
Нечто подобное есть Кристофера Корманиоса, автора кникги 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 для всех используемых платформ и даже существующий в одной единственноверной версии с которой собираются все проекты.
Лютый героизм поддерживать такое, не могу сказать что в моих проектах есть нечто подобное.
Каждый начинает со своего MCAL. А получается просто CAL
-Сегодня первое, что делают люди, когда атакуют твою Темную Башню Зла - это заваливают тоннель для побега, - сказал Злобный Гарри.
-Ублюдки! - сказал Коэн. - Ты должен позволить Темному Повелителю скрыться. Все это знают.
-Это точно, - сказал Калеб. - Нужно оставлять себе немного работы на завтра.* ("Последний Герой")
Так вот надо всегда оставлять немного работы на завтра. А переписать всё под новый контроллер это замечательная работа. Если не оставить её себе, то тебе поручат другую работу, которая может быть уже далеко не такой хорошей.
С третьей стороны, переписывать каждый раз MCAL на другой контроллер тоже работа....
А я вот никогда не использую "HAL от вендора" -- у меня самописное всё, от GPIO до USB. Ну, это если про нижний уровень, работающий прямо с железом, говорить. На среднем уже возможны варианты (скажем, использую LVGL, а если потребуется прикрутить сеть, возьму lwIP).
Аналог FatFs тоже сами написали?
Да. Полностью асинхронный (а не чисто синхронный, как FatFs -- собсно, потому и написал свой). Причём использовал сопрограммы C++20 -- собсно, потренировался на кошечках :) Правда, сейчас перепишу на обычные процедуры обратного вызова, поскольку Кейловскому отладчику наличие сопрограмм начисто срывает крышу -- отлаживать можно только на уровне дизассемблера, причём не только сами сопрограммы, но и код более высокого уровня.
Вендор вендору рознь. Вот у stm плохой Hal . Хуже st Hal ни у кого в мире нет. А у китайцев artery, yuntu , flagchip - великолепный hal.
Издевка судьбы в том, что Mik32 слепо выбрали копировать именно самый галимый STшный HAL.
https://github.com/MikronMIK32/mik32-hal/tree/main/peripherals/Source
буквально прототип в прототип
Hal пишется для примера, чтобы продемонстрировать только основные возможности железа. Эта цель обычно вступает в прямое противоречие с эффективностью, когда надо сделать что-то специальное самым оптимальным способом.
Чтобы обеспечить эффективность надо анализировать функции железа и их взаимодействие на уровне доступных регистров, и на уровне взаимодействия операций в железе, а не на уровне показушных функций.
Это другая сторона большой legacy. Есть же вариант когда как бы наоборот: сделали один раз (на 8051) и отказаться никак не могут, допиливают, и даже эмулируют старое, т.е. как бы даже не переписывают. потому что где то была очень тонкая фишка которой потом нигде просто нет.
В psoc сypress например много встроенного аналога, в новых attiny всякие lut элементы, ну шины событий - как раз то изза чего можно упростить и схему и код
Proxy MCAL для Микроконтроллера