Очень простой язык (чуть сложней ассемблера, зато писанины поменьше, но при этом остается понимание).
Сложный язык (сложней С, зато возможностей побольше, и при этом писанины поменьше). Смотри как лаконично записан цикл for по всему массиву. Просто взяли ссылку на каждый элемент массива и отпечатали по ней в терминал. А сортировка массива на этапе компиляции как тебе? И строка форматирования вывода (шаблон от строки на секундочку), держу пари, сильно оптимальней того что printf-ом бы получилось. Reflector столько плюшек в такой маленький пример засунул! Только жаль не все оценить могут.
Заголовок сообщения: Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
Добавлено: Вс дек 06, 2020 11:36:40
Нашел транзистор. Понюхал.
Зарегистрирован: Вс сен 06, 2020 16:06:10 Сообщений: 156
Рейтинг сообщения:0
Цитата:
C++ вариант ногодрыжной либы самый умный и эффективный, оптимизирует как на уровне пинов, так и на уровне работы с регистрами.
Там где мне вот именно перфоманс (а может и размер кода) важен, я вообще скажу reg32_write(reg, val) на какой-нибудь BSRR. И это будет чуть не 1 инструкция асма, без гребаных мегалиб и кучи кода. А, хотите сказать что это выглядит как кал? Согласен! Поэтому #define SOMETHING_ON ... вон то, с правильными параметрами. Выглядит лучше, понятно что и нафига. И по прежнему чуть не 1 команда асма. И те параметры конечно же символическими константами оформить, а не волшебными числами.
Цитата:
Можешь попытаться на его основании создать реверсный массив который также будет размещен во флеше.
А мне это нафига? Если мне что-то такое приспичит я подумаю о том чтобы хранить 1 массив а в месте где инверсный надо - индекс сделать не x а (arr_size - x). Вы там можете монстра с темплейтами воротить, а я пробурчу "оверинженерия сосет". К тому же в этом коде потом ардуинщик "типа знающий плюсы" дров наломает мама не горюй, потому что оказывается что C++ вовсе и не яваскрипт, а ардуинистый субдиалект далеко и не единственный вариант.
Цитата:
Какая разница менюшка или не менюшка, С++ умеет выполнять код на этапе компиляции,
И вот именно такие выкрутасы я абсолютно не желаю видеть, это порой делает происходящее чертовски неочевидным. И когда это прошивка МК это по мне довольно дерьмово. Есть шанс что код на этой почве поймут не так как это было задумано.
Цитата:
У gcc есть атрибут section(".init"), помечая им сишную функцию можно заставить ее вызываться в начале выполнения программы, для чего используется тот же механизм, что и для конструкторов, т.е. типичный gcc стартап для С и С++ ничем не отличается. Естественно атрибут эмуллирующий деструкторы имеется тоже.
Для сей я могу написать стартап сам. Для плюсов я это не сделать не возьмусь. А молиться на неведомы черные ящики делающие неведомо что лично мне в микроконтроллерах очень неохота. Хочу знать что и почему происходит, это дает мне плотный контроль над происходящим. Вот лично вы смогете накорябать плюсам стартап? А может еще и на плюсах?! А то сям на сях - можно. На кортексах без ассемблера вообще, что прикольно.
Цитата:
Насколько тривиально на С все размудрить для таких списков пинов?
Оно и на сях придет к чему-то весьма культурному, если не страдать фигней. Допустим вообще led7_out(digit). Внутри может быть по разному. И то что оно внутрях возьмет какой там еще SEVENSEG_PIN0 ... PIN7 из какого-нибудь board.h определяющего мой фактический борд, и перекраиваемый под новый за минуту - а оно при переделке борда проблемой уже не будет. И с новой бордой - ну переопределить пины, остальное и не заметит что что-то поменялось. А то что я не городил адские мегаструктуры - и чего?
Цитата:
В IAR и Keil стартап по ResetHandler передаёт управление стандартной библиотеке. Она сама знает есть ли конструкторы и вызывает их.
Вот именно это мне и не нравится. Есть какие-то волшебники, рангом покруче вас, которые вот так могут. А вот лично вы понятия не имеете что они делают, как это работает, но вы почему-то типа круче. Ага, конечно, размечтались. Вот чем мне ассемблерщики нравятся - не верят в черную магию черных ящиков. И знают что у них внутри.
Цитата:
Ничуть не больше чем на Си.
Не, вот пардон, когда вы запуск другой фирмари на чем-то сиобразном написали, вы таки чекали что в дампе. А я корябнув интринсик volatile asm так не развлекался, потому что вот он точно будет таким как надо, и компилер уже не имеет права там сумничать. У меня 0 раз, у вас 1.
Цитата:
А почему должно быть иначе, если вы не знаете язык?
У сей и тут есть преимущество: относительно простые. Да, есть премудрости и подводные камни. Но в плюсах этого счастья еще в цать раз больше - достаточно сравнить допустим правила MISRA для C и C++ - и подохренеть малость с того какой си++ простой и офигенный для писания программ без ошибок, что способов прострелить пятку в десяток раз больше. И интересно сколько упражнений местных вообще пройдут проверку такими тулзами без мата статического анализатора.
Там где мне вот именно перфоманс (а может и размер кода) важен, я вообще скажу reg32_write(reg, val) на какой-нибудь BSRR. И это будет чуть не 1 инструкция асма, без гребаных мегалиб и кучи кода.
Эта reg32_write начнет проигрывать С++ мегалибе уже на установке одного единственного бита и дальше будет только хуже:
PC15::set(); 5E 4B ldr r3, [pc, #376] 80 26 movs r6, #128 5E 76 strb r6, [r3, #25]
Цитата:
А мне это нафига?
Чтобы подтвердить свои слова о том, что на С наверно так тоже можно. Ну нельзя так нельзя
Цитата:
И вот именно такие выкрутасы я абсолютно не желаю видеть, это порой делает происходящее чертовски неочевидным. И когда это прошивка МК это по мне довольно дерьмово. Есть шанс что код на этой почве поймут не так как это было задумано.
Массив описывающий менюшку трансформируется на этапе компиляции и ложится во флеш, если компилятор так не сможет сделать, то код не скомпилируется, потому в принципе не может быть такого что пользователь сделал что-то не так и выполнение кода трансформации незаметно перешло в рантайм.
Цитата:
Для сей я могу написать стартап сам. Для плюсов я это не сделать не возьмусь. Вот лично вы смогете накорябать плюсам стартап? А может еще и на плюсах?! А то сям на сях - можно.
Стартап на C++ для целого STM32H7, вектора прерываний всегда в RAM, код в RAM или флеш: Спойлер
Код:
#include <stm32h7xx.h> #include "config.h"
extern void *_estack;
extern "C" void Reset_Handler(); extern "C" void Default_Handler(); int main();
Я его чуть обрезал, от сишного стартапа отличия минимальны, сделано на основе стандартного сишного стартапа из visualgdb.
Цитата:
Оно и на сях придет к чему-то весьма культурному, если не страдать фигней.
На С проблема даже просто весьма культурно передать 12 пинов с разных портов... Была относительно недавно тема про семисегментники, пишущие на С там перебирали пины из массива и выводили по одному биту
это не будет одна инструкция. Это будет загрузка адреса BSRR в РОН и загрузка val в другой РОН. С последующей командой STR. Это если reg32_write в той же единице трансляции находится. А то ещё ведь ещё и её вызов может произойти. А C++ метод на этапе компиляции сначала проверит, а не совпадает ли маска выводимых данных с 0xFF, 0xFFFF. Тогда И BSRR никакой не нужен, а можно командой STRB или STRH прямо байт или слово в ODR пульнуть. Но, допустим, счастья не случилось и надо писать в BSRR. Опять начинаем анализ записываемых данных с целью определить, нельзя ли обойтись командами STRB или STRH. Потому что, если вспомнить систему команд ARM (да, да, С++ программисты её знают), то константы меньшей разрядности загружаются в РОН проще, что приводит к более быстрому и компактному коду. А так как методы класса статические, описаны в заголовочном файле, то всё гарантировано заинлайнится. И вот тогда действительно будет всего несколько ассемблерных инструкций. Звучит сложно и как фантастика, но на деле все просто. Пример делает 10 импульсов на PA9.
Для сей я могу написать стартап сам. Для плюсов я это не сделать не возьмусь.
Ну, это лишь говорит о полном непонимании вопроса, который вы так многословно обсуждаете. К сообщению приложен стартап для GCC под С и С++. Какая из строчек вам непонятна?
Вот лично вы смогете накорябать плюсам стартап? А может еще и на плюсах?! А то сям на сях - можно. На кортексах без ассемблера вообще, что прикольно.
А думаете кто мне стартапы пишет? Если бы вы читали форум, а не только писали, то уже давно бы нашли мой иниверсальный стартап для Cortex-M, который совместим с GCC, IAR и Keil.
В IAR и Keil стартап по ResetHandler передаёт управление стандартной библиотеке. Она сама знает есть ли конструкторы и вызывает их.
Вот именно это мне и не нравится. Есть какие-то волшебники, рангом покруче вас, которые вот так могут. А вот лично вы понятия не имеете что они делают, как это работает, но вы почему-то типа круче.
Когда я лет 20 назад осваивал работу в IAR, то исследовал что делает стартовая библиотека. Смотрел исходники, щупал отладчиком. Пришел к выводу, что там нет ничего лишнего и писали её профи. Именно поэтому для IAR я смело ResetHandler перенаправляю на __cmain и знаю что всё будет Оk.
Вот чем мне ассемблерщики нравятся - не верят в черную магию черных ящиков. И знают что у них внутри.
Вера начинается там где заканчиваются знания. Знания С++ программиста обычно гораздо выше. По крайней мере, тех с кем я сталкивался по жизни. Им не надо верить в чёрную магию, они её сами делают.
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
GCC при сборке Си - закрывает глаза на границы массивов. Записать в массив 20 чисел, когда там всего 10 мест - код соберётся без предупреждений. Это долгоиграющий баг, который в той или иной степени наследуют все языки более сложного уровня. И да, в С++ оно тоже часто прокатывает.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
GCC при сборке Си - закрывает глаза на границы массивов.
Была одна тема, там ТС написал:
Код:
char s[5] = "Hello";
В С++ ошибка, как сишный код компилируется даже без предупреждения, по крайней мере если в gcc дополнительные ключи не указывать. Еще недавно столкнулся, в глобальном пространстве имен было типа такого:
Код:
foo();
Это объявление сишной функции для которого забыли в начале void написать, msvc никаких проблем тут не видит, в C++ это естественно ошибка.
Заголовок сообщения: Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
Добавлено: Вс дек 06, 2020 14:53:57
Нашел транзистор. Понюхал.
Зарегистрирован: Вс сен 06, 2020 16:06:10 Сообщений: 156
Рейтинг сообщения:0
Прошу прощения, подробное и нудное сообщение к сожалению просралось по техническим причинам, второй раз печатать лень, поэтому кратко: 1) Я не понимаю что люди делают с GCC и Си, чтобы "такой код" не генерился. С -O0 собирают? У меня gcc грузит в некий регистр "базу", чуть не 1 раз на всю фирмварь в лучшем случае, и танцует от нее, и не только BSRR но и много чего еще, что в кодирование смещения влезло. А обрашения делает компактно, кодируя в команду компилтайм константы + смещения относительно базы. Примерно это делает и STM'ский boot ROM кстати. Не знаю, си у них там такой аккуратный или таки асм (в F1xx бутром всего 2 кило, я его дизассемблировал более-менее по приколу посмотреть как профи флеш шьют). 2) Кстати в этом gcc легко даст мастеркласс ассемблерщикам, вспомнив через килобайт кода что удачная база в регистре уже была. Ассемблерщику через кило тяжко это трекать. 3) Да, асм не поддается статическому анализу. В нем недостаточно деклараций намерений. Именно поэтому я и сказал что минимум и тривиального, там я сам статический анализатор. И наверное когда альтернативой упование на конкретику оптимизаций как у того типа, что например обращений в стэк в процессе того трюка не будет (кто это обещал?) - ну, знаете... 4) И да, некоторые плюсовики - реально крутые господа. Именно некоторые. По моим наблюдениям, те которые из си и асма заппгрейдились. Но сериал.бегинщики им все же нагадили, смешав карты. И крутизна плюсов не помогает ардуине раскрыть потенциал атмег. Почему-то. А сишники и для аттиней с 2 кило флеша на все почему-то могут что-то осмысленное. 5) Да, у си есть дурацкие моменты. Но если посмотреть список правил мисры, можно заметить что у плюсов проблем не только есть - но и гораздо больше. И это работает по технологии одно лечим, другое калечим. 6) И таки я ну вот вообще совсем не уверен что желающие прогать на асме оценят плюсы. 7) У плюсов есть фирменный минус: код не реюзабелен. Именно плюсатый код невозможно оформить в нормальную либу и юзать из программ на си, или других ЯП. С другой стороны, сишный код можно довольно много куда прикручивать. У плюсов слишком крутые абстракции для этого. Конечно c GPIO это не такая уж и проблема, но вообще led7_out(digit) я могу запилить и для какого-нибудь Linux в допущении что на платформе GPIO есть и в принципе это может быть довольно абстрактный вызов, ничего не знающий о железе, платформе и реализации.
Ах да, минимальный стартап на си может быть и типа такого, что под кат прятать не обязательно:
Код:
len = (size_t) &__bss_end; len = len - (size_t) &__bss_start; memset(&__bss_start, 0, len);
len = (size_t) &__data_end; len = len - (size_t) &__data_start; memcpy(&__data_start, &__text_end, len);
board_init();
p.s. переменная чтобы статические анализаторы не воняли про математику над разными указателями (они правы, плохо, но в стартапе - надо). Реально gcc делает идентичный код и RAM на переменную не жрет. И ноль ассемблера - SP cortex M сам из vectors[0] возьмет. Вон те функции, кстати, можно и самому по минимуму написать, тогда кода совсем мизер. Да, с таким стартапом могут быть некоторые оговорки. Но так можно - и таки на самом си. Хочу посмотреть как плюсовики из именно плюсатого кода поднимут свою механику с конструкторами-деструкторами. А такой номер вообще возможен? То что ассемблерщики всегда могут и это и что угодно иное - кто бы сомневался, они всегда могут все что платформа технически может
p.p.s а с вьюжлстудии все знакомые сишники давно свалили на gcc и clang - потому что компилятор си в ней - никакой. Gcc на левую декларацию функции без прототипа бухтит варнингом.
1) Я не понимаю что люди делают с GCC и Си, чтобы "такой код" не генерился.
Ну ведь это же легко, используя вашу reg32_write(reg, val), сделать 10 импульсов на PA9 как в моём примере? Компилируете, показываете такой же код и расходимся.
Ну да, я 10 раз скопипастил on + off, это для светодиода было, если кто будет настаивать то на сях можно и макрос повтора сделать. Да, более костыльно, но от "стены кода" из копипасты избавит.
И между нами, LED1_ON как-то информативнее, чтоли, чем какое-то PC15::set которое вообще ни о чем не говорит. Так что сказ про крутой и читаемый код на плюсах, конечно, здорово, но... а вон то и правда менее читаемо вышло? Или более жирно по коду? Не? Тогда какого дьявола, господа?
И это тоже да. На одну команду загрузки адреса в РОН больше. Да и лишний РОН.
Добавлено after 12 minutes 54 seconds: Кстати, в моём примере вовсе не LED был. Какой смысл дергать его с частотой десяток МГц? Даже объявление LED на плюсах гораздо удобнее.
Код:
using LED1 = TLed<PC13>; // Анод на контроллер using LED2 = TLed<PC14, false>; // Катод на контроллер
И далее по коду методы On и Off будут бесплатно учитывать схему подключения. А ещё методы Toggle и ReadState. И при этом ему, по большому счёту, всё равно на STM32 он или вообще не на ARM вовсе.
Что я про глобальные оптимизации грил? Я пихнул это в проект под рукой, GCC+LTO реюзул r7 внаглую, раз он подходит. А вот на чистом асме так сумничать будет нелегко. Заодно showcase глобальной оптимизации попался.
Цитата:
Ну вообще да. 20 строк копипасты вместо указания повторить код 10 раз.
Так больше соответствует фактическому коду и его активности. Размер кода очевиднее. И если он не нравится, тогда, очевидно, надо пересмотреть подход и возможно циклом оформить, профукав скорость в пользу размера. А у вас что это unroll - на глаз не схватывается. И ощущение сгенеренного кода и эффективности пролюбливается. Оно так и мег кода воткнет, никто и не заметит, пока флеха не кончится.
Цитата:
И это тоже да. На одну команду загрузки адреса в РОН больше. Да и лишний РОН.
Не вы там возмущались что r7 непонятно откуда? В случае GCC+LTO оценка локального кода - не совсем полная картина мира. И как это глобально на оптимизации скажется - более интересный вопрос на самом деле.
А как насчет чуть хитрее? Что если мы хотим дергать сразу 1, 3, 5 и 7 пины порта, одновременно? В моем случае компилер скорее всего 1 константу поменяет. А у вас абстракция такой финт вообще позволит? И если да, что в коде будет? Мне в отличие от моего примера, где я с 90% вероятности угадаю что компилер выдаст - не очевидно вообще совсем нихрена.
Цитата:
Кстати, в моём примере вовсе не LED был. Какой смысл дергать его с частотой десяток МГц?
Он виноват только тем что под руку попался и был подходящим тестовым кроликом.
Цитата:
Даже объявление LED на плюсах гораздо удобнее.[code]using LED1 = TLed<PC13>; // Анод на контроллер
Зато я могу быстро заредефайнить LED1_ON так, что оно прокатит даже, блин, на моем десктопе, для вон того нумлока на клавиатуре (под линуксом). Ну да, код поменяется и будет сильно менее эффективным, но в конце концов - тоже LED и тоже ON. Хоть там и нет никакого port C и вообще, файловая система и файловые операции, в сторону usb-шной клавиатуры. А понятие LED1_ON все же применимо.
Цитата:
И далее по коду методы On и Off будут бесплатно учитывать схему подключения. А ещё методы Toggle и ReadState. И при этом ему, по большому счёту, всё равно на STM32 он или вообще не на ARM вовсе.
Ну, хорошо, и что такое PC13 в контексте моего пиюка с usb-клавиатурой и LED num lock'а на ней как LED1? Вот что такое LED1_ON - я могу в два счета оформить и для этой конфиги, хоть конечно за ним и будет вообще совсем другой код в случае писюка (или одноплатника) с Linux.
И между нами, LED1_ON как-то информативнее, чтоли, чем какое-то PC15::set которое вообще ни о чем не говорит.
LED1_ON/LED1_OFF/LED_PIN1 сначала нужно задефайнить, для каждого светодиода. А будут разные порты, то может добавиться LED_PORT, или нужен LED1_TOGGLE - будь добр добавь и его. Чтобы появились пины со всеми своими методами нужно лишь добавить хедер, а дальше будет максимум одно переопределение имени на диод.
Цитата:
А как насчет чуть хитрее? Что если мы хотим дергать сразу 1, 3, 5 и 7 пины порта, одновременно? В моем случае компилер скорее всего 1 константу поменяет. А у вас абстракция такой финт вообще позволит? И если да, что в коде будет?
Ну, хорошо, и что такое PC13 в контексте моего пиюка с usb-клавиатурой и LED num lock'а на ней как LED1? Вот что такое LED1_ON - я могу в два счета оформить и для этой конфиги, хоть конечно за ним и будет вообще совсем другой код в случае писюка (или одноплатника) с Linux.
Помнится кто-то ранее в этой теме говорил, что даже F4 - это слишком жирно и потому ему не нужно, а писюк или одноплатник на линуксе значит не жирно? Какое это имеет отношение к эмбедду?
Последний раз редактировалось Reflector Пн дек 07, 2020 11:41:14, всего редактировалось 1 раз.
А как насчет чуть хитрее? Что если мы хотим дергать сразу 1, 3, 5 и 7 пины порта, одновременно? В моем случае компилер скорее всего 1 константу поменяет. А у вас абстракция такой финт вообще позволит? И если да, что в коде будет?
Заголовок сообщения: Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
Добавлено: Пн дек 07, 2020 11:54:41
Нашел транзистор. Понюхал.
Зарегистрирован: Вс сен 06, 2020 16:06:10 Сообщений: 156
Рейтинг сообщения:0
Насколько я понимаю глобальный оптимизатор - так в том случае если ранее похожего не попадалось. Да, "без BSRR" является достаточно уникальной конструкцией, потому что слеплено специально для того теста. Однако если такого будет несколько, вероятно и реюз константы случится. Ну и кроме того сетап дергов случается до их начала - так что на скорость не влияет. Ну и без BSRR как я помню F0, чтоли. У них еще и набор команд - v6, он в целом похуже чем m3, на этом еще дополнительный слив бывает особенно в математике всякой.
А вот как в тех концепциях сразу несколько пинов с эффективным кодом - я не совсем догоняю. Я в вон тех терминах в принципе я могу описать манипуляцию сразу набором пинов, и на set, и на reset, и будет не сильно хуже по коду. Просто константа станет другой. А в ваших мегаконцепциях чего будет?
А теперь вставь этот код в прерывание, допустим, где содержимое регистров за тебя никто раньше не загрузил. А примени в другой единице трансляции, а... Да много ли ещё чего бывает. Компилятор не устаёт.
Просто константа станет другой. А в ваших мегаконцепциях чего будет?
Я же показал что будет. Указываем список пинов и погнали. Причем, пины могут быть из разных портов в любой последовательности. Всё сгруппируется как надо. Это могут быть не только set или reset, а write, read, toggle.
Я даже не буду просить повторить нижеследующий пример. Берём две группы пинов на разных портах. Читаем одну группу как байт, инвертируем и записываем во вторую группу.
Здесь структура - как символьный путь заполнения параметров. Если не всем видно - основной упор на AF функции контактов, они всегда уникальные. Своя уникальная огромная структура для каждого мк в уникальном корпусе. Потому как даже в одной серии могут быть незначительные различия в назначении ног. Ну есно структура заполняется не руками, но подбрасывать уголь в топку приходится, что немного утомительно. Если кому нужно под другой мк - могу сделать. https://github.com/AVI-crak/gpio_one
основное достоинство ассемблера это предсказуемый результат, вы получаете РОВНО ТО что написали, это надо четко понимать. все остальное это костыли которые призваны облегчить труд программиста (а равно и вхождение) и заработать бизнесу на нем синергия возможна лишь когда программист владеет и ассемблером и костылем в равной мере на высоком уровне, в противном случае одного знания костыля недостаточно чтобы писать хороший код
Инициализация десятка пинов с -O0 у меня 23КБ отожрала, потому что самая тяжелая функция принудительно инлайнится Если этот инлайн убрать, то в разы вырастает размер с включенной оптимизацией.
Плюсовой класс байт 20 выиграл. Но когда это на 20-100 ног умножится, то за гранью добра и зла получится. И во всех режимах все регистры задаются, что не всегда необходимо. Но тут С выше головы не прыгнет.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 25
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения