Это обсуждение я, видимо, пропустил. Хотя stm32 ведь равнодушна к выравниванию, разве нет?
В линейке микроконтроллеров STM32 применяются ядра Cortex M0, M0+, M3, M4F, M7 - это из того что я знаю. Младшенькие из них невыровненый доступ не поддерживают вообще. И даже у тех которые поддерживают есть инструкции, которые не поддерживают (коряво сказано, но оно так и есть). Теперь накладываем на это дело разные компиляторы (GCC, IAR, ARMClang) и у каждого куча уровней оптимизации. Получается несчитанное количество комбинаций. Поверь, это не мои фантазии, я получал Hard Fault по невыровненому доступу на Cortex-M4F.
То есть подобная библиотека сама пишется в самом начале освоения. Жаль только, я не видел удачного интерфейса, под который можно было бы подгонять свою.
) И как раз в вашем случае из C++ взята только возможность прямой двоичной записи числа. То есть, вот я например на память не помню, как в F1 идут биты в CRL(H) регистре - сначала MODE, потом CNF или наоборот, хэзэ. Но зато я помню, что сброс обеих CNF и установка обеих MODE - это пин на выход в ПП-режиме. Так же я против дополнительных дефайнов, еще больше утяжеляющих текст по числу строк. Настройка ног в принципе то выполняется один раз. А если где и требуется переключение режимов по ходу дела, то логичнее тогда уж писать макросы в виде DATAPORT_OUTPUT() и DATAPORT_INPUT(), в которых в одном месте простым коротким текстом выполняется настройка режимов. То есть, принцип разумной достаточности и непложения (от слова "плодить") сущностей. Принцип "не плодите сущности" - один из основополагающих принципов программирования. То есть, не надо пересказывать своими словами уже ранее придуманную сущность. Это добавляет коду неочевидности, загромождает текст лишними сущностями, создает налет проприетарности, да и в целом уводит от принятого стандарта CMSIS в описании. А на стадии освоения вообще нужно избегать писать какие-либо долгосрочные библиотеки. По мере наработки опыта изменится взгляд на уже написанное. И вот такие "улучшения" будут просто слишком тяжеловесными. По мере освоения программист упрощает все эти тонны портянок и в конечном счете приходит к самой короткой записи, то есть к тому, что уже было предложено в сопроводительных документах. Там же люди тоже не дураки сидят, и если они разработали микроконтроллер, то именно они лучше всего и знают его работу.
Вы не представляете какой кайф при программировании ничего не знать о внутреннем устройство GPIO-порта, а просто оперировать стандартными методами и режимами. Особенно, когда в работе их целый зоопарк. Когда вижу на форуме примеры кода с MODER-ами, CNF-ами аж передёргивает.
Кайф "ничего не знать"? Хм. А я вот например предпочитаю знать даже то, какие транзисторы приводятся в работу в том или ином режиме работы порта. И это например помогло мне в свое время понять, почему в стоп-режиме потребление тока в несколько раз превышало документированные цифры. А всё потому, что не были выключены триггеры шмитта в режиме цифрового входа, и для их отключения нужен режим аналогового входа.
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Не надо передёргивать. "Ничего не знать, когда пользуешься". Пользуешься результатами своего труда. Когда сделано так, чтобы не думать о том что внутри когда тебе это не надо.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Немалым, но не возьмусь сказать, что он обязательно будет больше и сложнее, чем на Си
Меньше, в разы. Проверено на практике. Не забывай про наследование, которое уменьшает дублирование кода.
COKPOWEHEU писал(а):
Все-таки отсутствие мощного препроцессора вынуждает либо выдумывать хитрые извращения, либо плевать на эффективность и делать все в рантайме
Во-первых, препроцессор никуда в С++ не делся. А, во-вторых, он там и не нужен особо. Разве что имена циферкам задать и условную компиляцию выполнить. Есть инлайн-подстановка, есть шаблоны, есть вычисления на этапе компиляции. Так что на С++ без извращений получаются проги не больше и не медленней, чем на С.
VladislavS писал(а):
Вы не представляете какой кайф при программировании ничего не знать о внутреннем устройство GPIO-порта, а просто оперировать стандартными методами и режимами. Особенно, когда в работе их целый зоопарк
Точно.
НовыйДень писал(а):
не были выключены триггеры шмитта в режиме цифрового входа, и для их отключения нужен режим аналогового входа
Это, по-моему, в даташите в разделе условий измерений было указано. Оттуда, кстати, и идёт рекомендация переводить неиспользуемые выводы в режим аналогового ввода. Просто не заметил текст, набранный мелкими буковками. Бывает.
Теперь накладываем на это дело разные компиляторы (GCC, IAR, ARMClang) и у каждого куча уровней оптимизации.
Надо будет проверить. Хотя у меня сейчас только L151 под рукой. Но это же "младшее семейство"?
Цитата:
И как раз в вашем случае из C++ взята
Как раз в моем случае С++ нет вообще.
Цитата:
То есть, вот я например на память не помню, как в F1 идут биты в CRL(H) регистре - сначала MODE, потом CNF или наоборот, хэзэ. Но зато я помню, что сброс обеих CNF и установка обеих MODE - это пин на выход в ПП-режиме.
А в L1 деление не "вдоль", а "поперек", вместо разбиения по 8 ног на регистр делят на "режим" и "скорость", MODER и OSPEEDR. И лично я не помню какой режим за что отвечает. Лучше уж писать так, чтобы из текста было понятно, чего ты хочешь добиться, а не какие биты выставить.
Цитата:
А на стадии освоения вообще нужно избегать писать какие-либо долгосрочные библиотеки. По мере наработки опыта изменится взгляд на уже написанное. И вот такие "улучшения" будут просто слишком тяжеловесными. По мере освоения программист упрощает все эти тонны портянок и в конечном счете приходит к самой короткой записи, то есть к тому, что уже было предложено в сопроводительных документах. Там же люди тоже не дураки сидят, и если они разработали микроконтроллер, то именно они лучше всего и знают его работу.
Вот та библиотека, которая переживет два - три разных контроллера, уже и может использоваться как основная. Примерно поэтому же у меня до сих пор нет библиотек под АЦП или таймеры: не могу найти общий функционал, который бы стоило абстрагировать. А библиотеки вроде HAL выбывают из этого списка еще на предварительном этапе: слишком сложные.
Цитата:
Кайф "ничего не знать"?
Вероятнее всего, имелось в виду "не держать в голове подробностей". Знать-то, понятное дело, надо. Но если я хочу нарисовать на дисплее линию, я предпочту оперировать функциями рисования точек или областей, но не командами конкретного дисплея, регистрами SPI или поворотом плоскости поляризации жидкими кристаллами.
Цитата:
Меньше, в разы. Проверено на практике. Не забывай про наследование, которое уменьшает дублирование кода.
Не могу ни подтвердить, ни опровергнуть. Я под контроллеры на С++ не писал.
Цитата:
Во-первых, препроцессор никуда в С++ не делся. А, во-вторых, он там и не нужен особо.
Еще раз: в Си нет достаточно удобного препроцессора чтобы реализовывать компил-тайм алгоритмы по-человечески, поэтому приходится извращаться. В С++ такого тоже нет, зато есть constexpr'ы, которые решают ту же задачу, но другим способом. Насколько я понимаю, это позволяет на С++ при должном умении (которого у меня нет) писать более читаемый код, чем на Си. Быстродействия-то там примерно одинакового можно достичь.
Хотя у меня сейчас только L151 под рукой. Но это же "младшее семейство"?
Насколько помню, L1 это Cortex-M3, то есть "средненькие". На Cortex-M0(M0+) это L0, F0, G0. Но, как раз таки когда знаешь, что контроллер не поддерживает невыровненый доступ, то за такими моментами строже следишь. А тут расслабишься "типа М4F умеет невыровненый" и тут тебе плюха такая хлобысь!
Быстродействия-то там примерно одинакового можно достичь.
На каком-то небольшом участке кода да. Но в реальном проекте соревноваться с шаблонами и constexpr умумукаешься. Плюсовой код легко пишется в заголовочных файлах, а значит хорошо инлайнится и оптимизируется. Плюсовой код можно инстанцировать под конкретные данные, выбирая оптимальные алгоритмы под них на этапе компиляции. И это будет делать компилятор, а не программист. А компилятор не устаёт.
Вот чтобы далеко не ходить, у тебя есть макрос установки режимов пинов. Давай установим, к примеру, на каком-нибудь PA13 режим Analog для любого контроллера (за исключением F1 серии, там GPIO другой).
1. На православном С. (попросим форумчан поучаствовать в этом процессе). 2. Твоим макросом. 3. На С++. Тут я могу показать листинг от PA13<PinMode::Analog>::mode();
Дядьки из комитета по стандартизации давно провели сравнения большого количества кода, выполняющего одно и то же, но написанного на С и С++. Можете порыться в Инете, там все подробности есть. Результат таков: программы на С++, в среднем, на 10-20% короче, но расходуют на 10-20% больше ОЗУ. За счёт оптимизации кода под данные при использовании шаблонов разница в скорости лежит в диапазоне 10-150 раз. И вывод дядьки сделали такой, что нет объективных причин отказываться от использования С++ на МК с его ограниченными ресурсами.
На каком-то небольшом участке кода да. Но в реальном проекте соревноваться с шаблонами и constexpr умумукаешься.
Если пытаться адаптировать плюсовый код под Си - да. Но такой задачи ведь не стоит. Я не мыслю в терминах С++, соответственно и костылить тамошний подход нужды нет. А на Си подход другой, и описанных вами проблем не возникает.
Цитата:
Давай установим, к примеру, на каком-нибудь PA13 режим Analog для любого контроллера (за исключением F1 серии, там GPIO другой).
1. На православном С. (попросим форумчан поучаствовать в этом процессе). 2. Твоим макросом. 3. На С++. Тут я могу показать листинг от PA13<PinMode::Analog>::mode();
1. Лично в моем случае будет то же, что 2 - либо макросом, либо тем, во что он разворачивается. Я ведь его именно так и писал - сворачивал обычный код. 2.
#define GPIO_ADC 0b0000 #define mode GPIO_ADC do{ uint32_t temp = GPIO ## A -> CR ## H; //для тех, кто не знаком с препроцессором, ## это объединение строк, то есть GPIO ## A превращается в GPIOA temp &=~(0b1111<<(((13-8)&0x07)*4)); temp |= ( mode <<(((13-8)&0x07)*4)); GPIO ## A -> CR ## H = temp; }while(0);
Немного причесал код и выкинул лишние подстановки, но оставил общую суть. 3. Вам бы тоже не помешало показать во что разворачивается ваш шаблон. 4. Еще ждем от форумчан реализации на HAL, CMSIS и тот код, который из него получается - вызовы функций и т.п.
Цитата:
И вывод дядьки сделали такой, что нет объективных причин отказываться от использования С++ на МК с его ограниченными ресурсами.
Именно с этим никто не спорит, хотя бы потому, что на С++ почти всегда можно компилировать напрямую Си-шный код. То есть на С++ достичь ровной той же производительности, что на Си можно просто по определению. Но вот дальше начинаются сложности, поскольку фичи С++ могут упрощать код (constexpr), усложнять (полиморфизм), могут делать и то и другое одновременно (наследование, шаблоны). Соответственно, и знаний языка и специфики его применения в МК, требуется гораздо больше, чтобы хотя бы не навредить. Тут даже фанатичный Эдди признает, что С++ учить надо, там действительно есть фичи, упрощающие код. Вот только предпочитает оставить это дело молодым. Но, заметьте, таки пропагандирует, а не отговаривает. Ну а лично мне просто не нравится переусложненность С++. Туда напихали слишком много и бессистемно. Но, может, и придется его осваивать. Посмотрим.
Немного причесал код и выкинул лишние подстановки, но оставил общую суть. 3. Вам бы тоже не помешало показать во что разворачивается ваш шаблон.
Хоть это и не так просто, но могу немного причесать, выкинуть лишние инстанциации, но оставить общую суть и показать. Только чуть попозже, иначе это будет большой подсказкой.
А зачем этим всем многим пользоваться? Уже наследование и полиморфизм дают очень много для упрощения программирования больших проектов. Я до последнего года писал с оглядкой на возможность сборки проекта под х86-16 с помощью Борланд С++ 5.02, поэтому умышленно избегал использования современных фич С++. Похоже, что 80186/80188 окончательно уйдут от нас, поэтому буду осваивать новые фичи С++, так сказать, не обременённый оглядкой на совместимость со старыми компиляторами.
А я для удобства работы с GPIO простые макросы накатал. Скажем, для F303:
Код:
// clear MODER: ~GPIO_MODER_MODERXX_Msk, you should AND these #define MODER_CLR(n) (~(3<<(n*2))) // _AI - analog inpt, _O - general output, _AF - alternate function // these should be OR'ed #define MODER_I(n) (0) #define MODER_O(n) (1<<(n*2)) #define MODER_AF(n) (2<<(n*2)) #define MODER_AI(n) (3<<(n*2))
// Set led as opendrain output GPIOC->CRH |= CRH(13, CNF_ODOUTPUT | MODE_SLOW); // USB pullup (PA15) - pushpull output GPIOA->CRH = CRH(15, CNF_PPOUTPUT | MODE_SLOW);
У F0 все достаточно просто, так что я лишь сделал дополнительные макросы на флаги, чтобы более понятно было (MODER_AI, MODER_O и т.п.), но надо бы переделывать все так же, как под 303: более понятно.
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Блин, пасаны, ну вы зарубились с этими пинами, блин. Всё равно, быстрее, чем запись числового значения напрямую или в текстовом виде вы не сделаете. Пины - это не та тема, на которую следует защищать докторскую диссертацию.
Но они же не добавляют абстракции и не упрощают перенос с f0 на f1, f3 и т.д.
Вот-вот. А потом окажется, что для одного пина активный уровень "1", а для другого- "0". А в другом исполнении девайса они могут быть другими. И как вычислять большие логические выражения, когда то "1", то "0"? А ведение логов при изменении уровня на каком-то пине? И как контролировать, что по запарке ты не присваиваешь результат вычисления логического выражения входному сигналу? Я видел макросы на 5 экранов для подобных случаев, но как такое отлаживать и быть уверенным в правильности работы?
А я для удобства работы с GPIO простые макросы накатал. Скажем, для F303:
Код:
// clear MODER: ~GPIO_MODER_MODERXX_Msk, you should AND these #define MODER_CLR(n) (~(3<<(n*2))) // _AI - analog inpt, _O - general output, _AF - alternate function // these should be OR'ed #define MODER_I(n) (0) #define MODER_O(n) (1<<(n*2)) #define MODER_AF(n) (2<<(n*2)) #define MODER_AI(n) (3<<(n*2))
Скобки натыканы просто бездумно. Подумайте что будет с вашими макросами когда например: MODER_O(1 + 2) ? Правильно писать: #define MODER_O(n) (1<<(n)*2)
Но они же не добавляют абстракции и не упрощают перенос с f0 на f1, f3 и т.д.
Я не собираюсь очередное подобие кала писать. Мне нужно лишь упростить написание и чтение кода.
Цитата:
Подумайте что будет с вашими макросами когда например: MODER_O(1 + 2) ?
Скрипты для такого рукожопия не предназначены.
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 40
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения