Comments 25
Студент привел, по-моему около 20 или 30 способовприписывают физику по имени Нильс Бор
Эм. "Экзотерично" это как? Экзотично? Эзотерично? Шестнадцатирично? :-)
А вообще конечно странно, что до сих пор не написали каноничный код для работы с регистрами мк. На хабре статей 5 уже видел...
Нафига вам работать с регистрами из C++ напрямую?
Вы пишите BSP так что потом вас долго вспоминали тихим добрым словом, те кому придётся всё переделывать?
Что мешает работать с готовой HAL отделанной от регистров, и реализованной на обычном C или даже ассемблере где не надо бороться с проблемами вызванными улучшениями, призванными бороться с этими самыми проблемами но в общем виде?
Так вот кроме этого, я считаю, что его можно использовать только в устройствах, которые поработал быстро и выключил, типа CAN сканера для считывания ошибок в автомобиле, или управление геликоптером, или блутуз чайник (хотя спорный вопрос, но знаю, что Редмонд его и использует), где риск отказа вообще не высокий. Ведь не беда, что устройство работает час, а потом перестает отвечать через USB(баг в USB там жесткий был)… или вытыкаешь на живую, а windows с синим экраном падает, ну ничего пользователь просто переткнул устройство, перегрузил компьютер и все…
А если вы делаете медицинское оборудования, где от такого зависания зависит жизнь человека? А если на атомной станции стоит?
Я бы даже в умной розетке его бы не использовал, потому, что опасно это.
Ответ на стековрелфлоу, мне кажется очень разумным:
It gives pseudo developers false feeling that they do not have to know how their hardware works.
Time spent learning HAL may be longer (and usually is) than needed to understand how the hardware works.
Horrible overhead
Many errors.
А переделывать все равно придется рано или поздно, ведь Общедоступные библиотеки же появляются уже тот Kvasir, modm. А закрытых еще больше… и все уже написано и ethernet и usb и стеки все и оно не жрет столько ресурсов, как HAL и код даже компактнее, чем на ассемблере.
Я вот помню, как примерно в таком же стиле переходили в 90х с ассемблера на Си. Ну тоже самое все было… и библиотеки и программисты только на ассемблере писали для 6800, 51 и PIC, но ведь перешли, ничего, сейчас кто ассемблер вспоминает?
Даже ARM это понял что люди переходят на С++ и выпустил вот это для генерации нормальных регистров на С++.
digitalWrite(led1Pin, HIGH);
или так
analogWrite(led2Pin, level);
Led1::Set();
А теперь представьте, что вам надо переключить сразу несколько ножек на разных портах… на Си это во сколько на ассемблере выльется?
А на С++ в 5-7 команд. Смотрите Reflector показал, как это реализовано easyelectronics.ru/rabota-s-portami-vvoda-vyvoda-mikrokontrollerov-na-si.html
А код будет выглядеть, примерно так
LedList<<Led1, Led2, Led4, Led3>::Toggle();
И всего то, и выродится это может в что-то типа
GpioA->Odr ^= (1 <<1) | (1<<2);
GpioC->Odr ^= (1 <<4) | (1<<3);
У него даже еще лучше через BSRR регистры
В статье довольно простой поиск групп пинов, там ищутся только идущие подряд, только в одном направлении и не должно быть других пинов относящихся к тому-же порту, т.е. список из PA8, PA7, PA6, PA3 — это 4 отдельных пина, из-за последнего. У меня ищутся цепочки в обоих направлениях и порядок не имеет значения, для списка PA8, PA7, PA3, PA5 будет найдена цепочка PA8, PA7, PA5, потому что если биты 3, 2 и 0 входных данных сдвинуть на 5 влево, то они станут как раз битами 8, 7 и 5. И в статье старенькая Loki используется, я брал за основу списки типов от Олега Фатхиева, на вариадиках, есть видео на youtube .
Есть у меня класс для работы с дисплеями, дисплеи могут быть с разными контролерами и работает это все через SPI, FMC или ногодрыг. В последнем случае я передают в шаблон отдельные управляющие пины(RS, WR...) и список пинов для данных, там они могут идти в любом порядке. Можно взять плату на которой дисплей с 16-ти битной шиной подключен к FMC и заставить ее работать через ногодрыг задав для данных такой список пинов:
PinList<PD10, PD9, PD8, PE15, PE14, PE13, PE12, PE11, PE10, PE9, PE8, PE7, PD1, PD0, PD15, PD14> LcdData;
Все, теперь внутри либы будет вызваться LcdData::write(...) и все разлирутся самом собой, пины автоматически разобьются на 4 группы и данные будут записаны в 2 порта, причем так же работает чтение, установка режима, быстрая смена направления и т.д… С точки зрения пользователя все предельно просто, эффективность на самом высоком уровне… С семисегментником будет то же самое, не важно к каким ногам он подключен, достаточно в списке расставить пины в правильном порядке.
А то что там на задворках для компилятора написано, в это вникать не надо… Это не для микроконтроллера, это для компилятора.
Кстати насчет ошибки… вы же вот тут написали Унифицированная обработка ошибок (C++ вариант для микроконтроллеров)
пример на Си — но это же столько ненужной работы надо сделать, и как его вообще переиспользовать, если у меня новые коды ошибок появляются? А на С++ ничего делать не надо… только список определи и все…
using CategoryErrorsList = EnumTypeRegister<Cpu_Error, Measure_Error, My_Error>;
И самое главное, в итоге по ресурсам процессора меньше. Зачем эти ненужные траты времени на написание скрипта? считайте что, аналог этого скрипта на С++ это как раз реализация класса метапрограммированием. Еще раз повторяюсь, все что там на шаблонах написано, это и есть скрипт-код не для микроконтроллера, а для того, чтобы компилятор этот код (скрипт) выполнил во время компиляции.
По поводу скриптов, вот у вас есть десяток вариантов плат. Где вы их конфигурации храните, даташиты и схемы по разводке? В шаблонах. Нет вы их храните в системе контроля версий в субмодуле платы. А на шаблонах там сделано или на дефайнах это дело десятое. Просто скриптом вытягиваете нужную ревизию и собираете. Причем заставляете это делать какой-нибудь jenkins.
…
«И самое главное, в итоге по ресурсам процессора меньше» — это не главное.
Напоминаю главное чтобы работало здесь и сечас. Поэтому переписывать так чтобы было офигенно со всех сторон как правило экономически не выгодно.
В общем я не хотел сказать, что Си плохой и на нем не надо писать, я к нему отношусь нейтрально, как к любому другому языку, который не очень знаю. Я больше хочу сказать, что С++ хороший и на нем можно писать эффективно на микроконтроллерах, но не обязательно нужно.
Думаю, что если надо быстро выпустить продукт на рынок широкого потребления, то да, взял Cube, HAL, быстро накидал логику — выпустил и собираешь прибыль, то альтернативе Си сейчас нет.
Но вот если продукт для атомной станции, который делается годами, то можно и потратить время на изучение более безопасного подхода, в том числе и на С++
но разница в сложности между си и асмом не такой большой была,
а учитывая сколько видов не совместимых с собой асмов на одну и ту же архитектуру было я бы за засомневался была ли сложность асма ниже чем у си, особенно у асмов с макросами и метапрограммингом, особенно у дсп от AD и техасов в конце 90ых — вот там творился вообще адский ад, пример попроще — турбоассемблер и макроассемблер под ДОС.
Пюсы дают проблемы компиляции на ровном месте из за более строгой типизации, зато огромный плюс плюсов в том что не перепутаешь xxxAPHxxxx и xxxAPBxxxx константные энумы инициализации и прочие плюшки строгой типизации и более развитый язык за который нужно платить в разы возрастающим временем проектирования, например генерики функций на шаблонах — такое порой проще препроцессором си написать (самое главное чтоб этот АД не пришлось потом через год поправить — никакая даже самая подробная дока не спасёт от траты минимум дня на разбор что это за ужас) — я про то что случае си читать потом неудобно, а в случае плюсов проектировать такое гораздо дольше — существенного преимущества нет.
Именно поэтому, я сомневаюсь, что плюсы полностью си вытеснят.
Скорее кончатся программисты которые на голом си умеют писать.
И да, так и будет — программисты кончатся, как кончились программисты на чистом ассемблере. По-крайней мере, так как я преподаю в университете, а там только С++ дают, в том числе и мой курс для микроконтроллеров. Про указатели многие студенты, приходя ко мне на курс даже и не знают, про ссылки знают, про ссылки на rvalue знают. А указатель это новость для них. Может это и правильно, не будут не безопасный код писать.
Тип доступа RO/WO/RW должен отностится не к регистру, а строго к каждому биту в отдельности
Дело в том, что во многих регистрах соседствуют биты rw и ro, некоторые биты сбрасываются записью 1, а не 0. Отсюда минус «можно сделать глупость» никуда не уходит.
В заголовочниках от производителя нет описания типов доступа для отдельных бит, а значит автоматически пересобрать заголовок с регистрами через python не получится. Теоретически это может делать производитель путем обработки исходных hdl-кодов (собственно, стандартные cmsis-заголовочники так и делаются), но вряд ли они будут делать это в сколь-нибудь обозримом будущем.
Там идея в том, в том, что генерация описания классов и регистров будет из SVD файлов, а код обращения к регистрам уже не сложный.
Если время будет, я попытаюсь это описать и выложить на хабр.
10++ способов работать с аппаратными регистрами на С++ (на примере IAR и Cortex M)