Ассемблер для STM32. Сложно ли, стоит ли пытаться?
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
[uquote="Eddy_Em",url="/forum/viewtopic.php?p=3936170#p3936170"]Очень простой язык (чуть сложней ассемблера, зато писанины поменьше, но при этом остается понимание).[/uquote]Сложный язык (сложней С, зато возможностей побольше, и при этом писанины поменьше). Смотри как лаконично записан цикл for по всему массиву. Просто взяли ссылку на каждый элемент массива и отпечатали по ней в терминал. А сортировка массива на этапе компиляции как тебе? И строка форматирования вывода (шаблон от строки на секундочку), держу пари, сильно оптимальней того что printf-ом бы получилось. Reflector столько плюшек в такой маленький пример засунул! Только жаль не все оценить могут.
- Реклама
- Сообщения: 156
- Зарегистрирован: Вс сен 06, 2020 16:06:10
Там где мне вот именно перфоманс (а может и размер кода) важен, я вообще скажу reg32_write(reg, val) на какой-нибудь BSRR. И это будет чуть не 1 инструкция асма, без гребаных мегалиб и кучи кода. А, хотите сказать что это выглядит как кал? Согласен! Поэтому #define SOMETHING_ON ... вон то, с правильными параметрами. Выглядит лучше, понятно что и нафига. И по прежнему чуть не 1 команда асма. И те параметры конечно же символическими константами оформить, а не волшебными числами.C++ вариант ногодрыжной либы самый умный и эффективный, оптимизирует как на уровне пинов, так и на уровне работы с регистрами.
А мне это нафига? Если мне что-то такое приспичит я подумаю о том чтобы хранить 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++ - и подохренеть малость с того какой си++ простой и офигенный для писания программ без ошибок, что способов прострелить пятку в десяток раз больше. И интересно сколько упражнений местных вообще пройдут проверку такими тулзами без мата статического анализатора.А почему должно быть иначе, если вы не знаете язык?
- Сообщения: 2089
- Зарегистрирован: Вс июн 19, 2016 09:32:03
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]Там где мне вот именно перфоманс (а может и размер кода) важен, я вообще скажу reg32_write(reg, val) на какой-нибудь BSRR. И это будет чуть не 1 инструкция асма, без гребаных мегалиб и кучи кода.[/uquote]
Эта reg32_write начнет проигрывать С++ мегалибе уже на установке одного единственного бита и дальше будет только хуже:

Я его чуть обрезал, от сишного стартапа отличия минимальны, сделано на основе стандартного сишного стартапа из visualgdb.

Эта reg32_write начнет проигрывать С++ мегалибе уже на установке одного единственного бита и дальше будет только хуже:
Код: Выделить всё
GPIOC->BSRR = GPIO_BSRR_BS15;
5D 4B ldr r3, [pc, #372]
4F F4 00 42 mov.w r2, #32768
9A 61 str r2, [r3, #24]
Код: Выделить всё
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();
using FP = void(*)();
#ifdef sram_layout
FP isrVectors[166] __attribute__((section(".isr_vector_ram"), used))
{
(FP)&_estack,
&Reset_Handler
};
#else
FP isrVectors[166] __attribute__((section(".isr_vector_ram"), used));
FP fvectors[] __attribute__((section(".isr_vector"), used)) =
{
(FP)&_estack,
&Reset_Handler,
};
#endif
void setVectorTable(IRQn_Type irqn, FP fp)
{
isrVectors[int(irqn) + 16] = FP(fp);
__DSB();
__ISB();
}
extern uint8_t _data_load, _data, _data_size;
extern uint8_t _bss, _bss_size;
extern uint8_t _itcm_load, _itcm, _itcm_size;
extern uint8_t _itcm_bss, _itcm_bss_size;
extern uint8_t _dtcm_load, _dtcm, _dtcm_size;
extern uint8_t _dtcm_bss, _dtcm_bss_size;
extern uint8_t _sram123_load, _sram123, _sram123_size;
extern uint8_t _sram123_bss, _sram123_bss_size;
extern uint8_t _sram4_load, _sram4, _sram4_size;
extern uint8_t _sram4_bss, _sram4_bss_size;
void SystemInit()
{
SCB->CPACR = SCB->CPACR | (3 << 10 * 2) | (3 << 11 * 2); // set CP10 and CP11 Full Access
RCC->CR = RCC->CR | RCC_CR_HSION;
RCC->CFGR = 0;
RCC->CR = RCC->CR & ~(RCC_CR_HSEON | RCC_CR_CSSHSEON | RCC_CR_CSION | RCC_CR_HSI48ON | RCC_CR_CSIKERON | RCC_CR_PLL1ON | RCC_CR_PLL2ON | RCC_CR_PLL3ON);
RCC->D1CFGR = 0;
RCC->D2CFGR = 0;
RCC->D3CFGR = 0;
RCC->PLLCKSELR = 0;
RCC->PLLCFGR = 0;
RCC->PLL1DIVR = 0;
RCC->PLL1FRACR = 0;
RCC->PLL2DIVR = 0;
RCC->PLL2FRACR = 0;
RCC->PLL3DIVR = 0;
RCC->PLL3FRACR = 0;
RCC->CR = RCC->CR & ~RCC_CR_HSEBYP;
RCC->CIER = 0;
RCC->AHB2ENR = RCC->AHB2ENR | RCC_AHB2ENR_SRAM1EN | RCC_AHB2ENR_SRAM2EN | RCC_AHB2ENR_SRAM3EN;
RCC->AHB2ENR;
PWR->CR3 = PWR->CR3 & ~(PWR_CR3_SCUEN | PWR_CR3_BYPASS) | PWR_CR3_LDOEN;
while (!(PWR->CSR1 & PWR_CSR1_ACTVOSRDY)) {}
#ifndef sram_layout
memcpy(&_data, &_data_load, (size_t)&_data_size);
memcpy(&_itcm, &_itcm_load, (size_t)&_itcm_size);
memcpy(&_dtcm, &_dtcm_load, (size_t)&_dtcm_size);
memcpy(&_sram123, &_sram123_load, (size_t)&_sram123_size);
memcpy(&_sram4, &_sram4_load, (size_t)&_sram4_size);
#endif
memset(&_bss, 0, (size_t)&_bss_size);
memset(&_itcm_bss, 0, (size_t)&_itcm_bss_size);
memset(&_dtcm_bss, 0, (size_t)&_dtcm_bss_size);
memset(&_sram123_bss, 0, (size_t)&_sram123_bss_size);
memset(&_sram4_bss, 0, (size_t)&_sram4_bss_size);
SCB->VTOR = uint32_t(isrVectors);
for (int i = 2; i < 166; i++)
{
isrVectors[i] = FP(Default_Handler);
}
__DSB();
__ISB();
}
extern "C" void __libc_init_array();
void __attribute__((naked, noreturn)) Reset_Handler()
{
asm("ldr sp, =_estack");
__ISB();
SystemInit();
__libc_init_array();
main();
while (true) {}
}
void Default_Handler() { __BKPT(255); }
На С проблема даже просто весьма культурно передать 12 пинов с разных портов... Была относительно недавно тема про семисегментники, пишущие на С там перебирали пины из массива и выводили по одному битуОно и на сях придет к чему-то весьма культурному, если не страдать фигней.
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]Там где мне вот именно перфоманс (а может и размер кода) важен, я вообще скажу reg32_write(reg, val) на какой-нибудь BSRR.[/uquote]И получите неоптимальный код. Потому что
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]И это будет чуть не 1 инструкция асма,[/uquote]это не будет одна инструкция. Это будет загрузка адреса BSRR в РОН и загрузка val в другой РОН. С последующей командой STR. Это если reg32_write в той же единице трансляции находится. А то ещё ведь ещё и её вызов может произойти. А C++ метод на этапе компиляции сначала проверит, а не совпадает ли маска выводимых данных с 0xFF, 0xFFFF. Тогда И BSRR никакой не нужен, а можно командой STRB или STRH прямо байт или слово в ODR пульнуть. Но, допустим, счастья не случилось и надо писать в BSRR. Опять начинаем анализ записываемых данных с целью определить, нельзя ли обойтись командами STRB или STRH. Потому что, если вспомнить систему команд ARM (да, да, С++ программисты её знают), то константы меньшей разрядности загружаются в РОН проще, что приводит к более быстрому и компактному коду. А так как методы класса статические, описаны в заголовочном файле, то всё гарантировано заинлайнится. И вот тогда действительно будет всего несколько ассемблерных инструкций. Звучит сложно и как фантастика, но на деле все просто. Пример делает 10 импульсов на PA9.Хренушки твоя reg32_write(reg, val) вызванная 20 раз даст такой код!
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]А мне это нафига?[/uquote]Стандартный аргумент, когда не можешь. Знакомо.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]К тому же в этом коде потом ардуинщик "типа знающий плюсы" дров наломает мама не горюй,[/uquote]Наоборот. Он не полезет внутрь библиотек, а будет вызывать простые и понятные методе типа serial.begin.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]Есть шанс что код на этой почве поймут не так как это было задумано.[/uquote]Кто поймёт? Код компилятор должен понимать. Мнение безграмотных читателей в топку.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]Для сей я могу написать стартап сам. Для плюсов я это не сделать не возьмусь.[/uquote]Ну, это лишь говорит о полном непонимании вопроса, который вы так многословно обсуждаете. К сообщению приложен стартап для GCC под С и С++. Какая из строчек вам непонятна?
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]Вот лично вы смогете накорябать плюсам стартап? А может еще и на плюсах?! А то сям на сях - можно. На кортексах без ассемблера вообще, что прикольно.[/uquote]А думаете кто мне стартапы пишет? Если бы вы читали форум, а не только писали, то уже давно бы нашли мой иниверсальный стартап для Cortex-M, который совместим с GCC, IAR и Keil.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]Вот чем мне ассемблерщики нравятся - не верят в черную магию черных ящиков. И знают что у них внутри.[/uquote]Вера начинается там где заканчиваются знания. Знания С++ программиста обычно гораздо выше. По крайней мере, тех с кем я сталкивался по жизни. Им не надо верить в чёрную магию, они её сами делают.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]И интересно сколько упражнений местных вообще пройдут проверку такими тулзами без мата статического анализатора.[/uquote]Покажите мне как ассемблерные вставки его проходят. Ага.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]И это будет чуть не 1 инструкция асма,[/uquote]это не будет одна инструкция. Это будет загрузка адреса BSRR в РОН и загрузка val в другой РОН. С последующей командой STR. Это если reg32_write в той же единице трансляции находится. А то ещё ведь ещё и её вызов может произойти. А C++ метод на этапе компиляции сначала проверит, а не совпадает ли маска выводимых данных с 0xFF, 0xFFFF. Тогда И BSRR никакой не нужен, а можно командой STRB или STRH прямо байт или слово в ODR пульнуть. Но, допустим, счастья не случилось и надо писать в BSRR. Опять начинаем анализ записываемых данных с целью определить, нельзя ли обойтись командами STRB или STRH. Потому что, если вспомнить систему команд ARM (да, да, С++ программисты её знают), то константы меньшей разрядности загружаются в РОН проще, что приводит к более быстрому и компактному коду. А так как методы класса статические, описаны в заголовочном файле, то всё гарантировано заинлайнится. И вот тогда действительно будет всего несколько ассемблерных инструкций. Звучит сложно и как фантастика, но на деле все просто. Пример делает 10 импульсов на PA9.
Код: Выделить всё
//Repeat<10>([]{ PA_9::set(); PA_9::clear(); });
MOVS R0,#+2
LDR.N R1,??DataTable1_4 ;; 0x48000019
STRB R0,[R1, #+0]
STRB R0,[R1, #+2]
STRB R0,[R1, #+0]
STRB R0,[R1, #+2]
STRB R0,[R1, #+0]
STRB R0,[R1, #+2]
STRB R0,[R1, #+0]
STRB R0,[R1, #+2]
STRB R0,[R1, #+0]
STRB R0,[R1, #+2]
STRB R0,[R1, #+0]
STRB R0,[R1, #+2]
STRB R0,[R1, #+0]
STRB R0,[R1, #+2]
STRB R0,[R1, #+0]
STRB R0,[R1, #+2]
STRB R0,[R1, #+0]
STRB R0,[R1, #+2]
STRB R0,[R1, #+0]
STRB R0,[R1, #+2][uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]А мне это нафига?[/uquote]Стандартный аргумент, когда не можешь. Знакомо.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]К тому же в этом коде потом ардуинщик "типа знающий плюсы" дров наломает мама не горюй,[/uquote]Наоборот. Он не полезет внутрь библиотек, а будет вызывать простые и понятные методе типа serial.begin.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]Есть шанс что код на этой почве поймут не так как это было задумано.[/uquote]Кто поймёт? Код компилятор должен понимать. Мнение безграмотных читателей в топку.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]Для сей я могу написать стартап сам. Для плюсов я это не сделать не возьмусь.[/uquote]Ну, это лишь говорит о полном непонимании вопроса, который вы так многословно обсуждаете. К сообщению приложен стартап для GCC под С и С++. Какая из строчек вам непонятна?
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]Вот лично вы смогете накорябать плюсам стартап? А может еще и на плюсах?! А то сям на сях - можно. На кортексах без ассемблера вообще, что прикольно.[/uquote]А думаете кто мне стартапы пишет? Если бы вы читали форум, а не только писали, то уже давно бы нашли мой иниверсальный стартап для Cortex-M, который совместим с GCC, IAR и Keil.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]
Оно и на сях придет к чему-то весьма культурному, если не страдать фигней.[/uquote]Вы даже не поняли в чём подвох. Печально.Насколько тривиально на С все размудрить для таких списков пинов?
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]
Вот именно это мне и не нравится. Есть какие-то волшебники, рангом покруче вас, которые вот так могут. А вот лично вы понятия не имеете что они делают, как это работает, но вы почему-то типа круче.[/uquote]Когда я лет 20 назад осваивал работу в IAR, то исследовал что делает стартовая библиотека. Смотрел исходники, щупал отладчиком. Пришел к выводу, что там нет ничего лишнего и писали её профи. Именно поэтому для IAR я смело ResetHandler перенаправляю на __cmain и знаю что всё будет Оk.В IAR и Keil стартап по ResetHandler передаёт управление стандартной библиотеке. Она сама знает есть ли конструкторы и вызывает их.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]Вот чем мне ассемблерщики нравятся - не верят в черную магию черных ящиков. И знают что у них внутри.[/uquote]Вера начинается там где заканчиваются знания. Знания С++ программиста обычно гораздо выше. По крайней мере, тех с кем я сталкивался по жизни. Им не надо верить в чёрную магию, они её сами делают.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937124#p3937124"]И интересно сколько упражнений местных вообще пройдут проверку такими тулзами без мата статического анализатора.[/uquote]Покажите мне как ассемблерные вставки его проходят. Ага.
- Сообщения: 202
- Зарегистрирован: Сб янв 09, 2016 15:51:17
GCC при сборке Си - закрывает глаза на границы массивов. Записать в массив 20 чисел, когда там всего 10 мест - код соберётся без предупреждений. Это долгоиграющий баг, который в той или иной степени наследуют все языки более сложного уровня. И да, в С++ оно тоже часто прокатывает.
- Реклама
- Сообщения: 2089
- Зарегистрирован: Вс июн 19, 2016 09:32:03
[uquote="AVI-crak",url="/forum/viewtopic.php?p=3937249#p3937249"]GCC при сборке Си - закрывает глаза на границы массивов.[/uquote]
Была одна тема, там ТС написал:
В С++ ошибка, как сишный код компилируется даже без предупреждения, по крайней мере если в gcc дополнительные ключи не указывать. Еще недавно столкнулся, в глобальном пространстве имен было типа такого:
Это объявление сишной функции для которого забыли в начале void написать, msvc никаких проблем тут не видит, в C++ это естественно ошибка.
Была одна тема, там ТС написал:
Код: Выделить всё
char s[5] = "Hello";Код: Выделить всё
foo();- Сообщения: 156
- Зарегистрирован: Вс сен 06, 2020 16:06:10
Прошу прощения, подробное и нудное сообщение к сожалению просралось по техническим причинам, второй раз печатать лень, поэтому кратко:
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 есть и в принципе это может быть довольно абстрактный вызов, ничего не знающий о железе, платформе и реализации.
Ах да, минимальный стартап на си может быть и типа такого, что под кат прятать не обязательно:p.s. переменная чтобы статические анализаторы не воняли про математику над разными указателями (они правы, плохо, но в стартапе - надо). Реально gcc делает идентичный код и RAM на переменную не жрет. И ноль ассемблера - SP cortex M сам из vectors[0] возьмет. Вон те функции, кстати, можно и самому по минимуму написать, тогда кода совсем мизер. Да, с таким стартапом могут быть некоторые оговорки. Но так можно - и таки на самом си. Хочу посмотреть как плюсовики из именно плюсатого кода поднимут свою механику с конструкторами-деструкторами. А такой номер вообще возможен? То что ассемблерщики всегда могут и это и что угодно иное - кто бы сомневался, они всегда могут все что платформа технически может 
p.p.s а с вьюжлстудии все знакомые сишники давно свалили на gcc и clang - потому что компилятор си в ней - никакой. Gcc на левую декларацию функции без прототипа бухтит варнингом.
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.p.s а с вьюжлстудии все знакомые сишники давно свалили на gcc и clang - потому что компилятор си в ней - никакой. Gcc на левую декларацию функции без прототипа бухтит варнингом.
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
[uquote="iddqd",url="/forum/viewtopic.php?p=3937307#p3937307"]1) Я не понимаю что люди делают с GCC и Си, чтобы "такой код" не генерился.[/uquote]Ну ведь это же легко, используя вашу reg32_write(reg, val), сделать 10 импульсов на PA9 как в моём примере? Компилируете, показываете такой же код и расходимся.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937307#p3937307"]Ах да, минимальный стартап на си может быть и типа такого,[/uquote]А на С++ он не может быть типа такого?
[uquote="iddqd",url="/forum/viewtopic.php?p=3937307#p3937307"]Хочу посмотреть как плюсовики из именно плюсатого кода поднимут свою механику с конструкторами-деструкторами.[/uquote]Я же чуть выше выложил стартап. Все конструкторы вызываются двумя строками кода, повторю их тут.Причём, как заметил Reflector, они же и для Си нужны, по хорошему.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937307#p3937307"]Ах да, минимальный стартап на си может быть и типа такого,[/uquote]А на С++ он не может быть типа такого?
[uquote="iddqd",url="/forum/viewtopic.php?p=3937307#p3937307"]Хочу посмотреть как плюсовики из именно плюсатого кода поднимут свою механику с конструкторами-деструкторами.[/uquote]Я же чуть выше выложил стартап. Все конструкторы вызываются двумя строками кода, повторю их тут.
Код: Выделить всё
for(void(**fConstr)() = __preinit_array_start; fConstr < __preinit_array_end; (*fConstr++)());
for(void(**fConstr)() = __init_array_start; fConstr < __init_array_end; (*fConstr++)());- Сообщения: 156
- Зарегистрирован: Вс сен 06, 2020 16:06:10
Если вы настаиваете, ок, быренько слепил из того что под рукой, и вышло как-то так:
Ну да, я 10 раз скопипастил on + off, это для светодиода было, если кто будет настаивать то на сях можно и макрос повтора сделать. Да, более костыльно, но от "стены кода" из копипасты избавит.
А внутрях как раз вот так было:
И между нами, LED1_ON как-то информативнее, чтоли, чем какое-то PC15::set которое вообще ни о чем не говорит. Так что сказ про крутой и читаемый код на плюсах, конечно, здорово, но... а вон то и правда менее читаемо вышло? Или более жирно по коду? Не? Тогда какого дьявола, господа?
Код: Выделить всё
LED1_ON;
8000eec: 2310 movs r3, #16
8000eee: 4a0a ldr r2, [pc, #40] ; (8000f18 <reset_handler+0x748>)
8000ef0: 6013 str r3, [r2, #0]
LED1_OFF;
8000ef2: 603b str r3, [r7, #0]
LED1_ON;
8000ef4: 6013 str r3, [r2, #0]
LED1_OFF;
8000ef6: 603b str r3, [r7, #0]
LED1_ON;
8000ef8: 6013 str r3, [r2, #0]
LED1_OFF;
8000efa: 603b str r3, [r7, #0]
LED1_ON;
8000efc: 6013 str r3, [r2, #0]
LED1_OFF;
8000efe: 603b str r3, [r7, #0]
LED1_ON;
....
А внутрях как раз вот так было:
Код: Выделить всё
#define LED1_ON REG32_WRITE(GPIOA_BSRR, BIT(LED_PIN1))
#define LED1_OFF REG32_WRITE(GPIOA_BRR, BIT(LED_PIN1))
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
iddqd, а теперь то же самое на контроллере без BRR?
Э!!! А загрузку R7 куда дели?
Добавлено after 21 minute 49 seconds:
[uquote="iddqd",url="/forum/viewtopic.php?p=3937735#p3937735"]И между нами, LED1_ON как-то информативнее, чтоли, чем какое-то PC15::set которое вообще ни о чем не говорит.[/uquote]
[uquote="iddqd",url="/forum/viewtopic.php?p=3937735#p3937735"]Так что сказ про крутой и читаемый код на плюсах, конечно, здорово, но... а вон то и правда менее читаемо вышло?[/uquote]Ну вообще да. 20 строк копипасты вместо указания повторить код 10 раз.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937735#p3937735"]Или более жирно по коду?[/uquote]И это тоже да. На одну команду загрузки адреса в РОН больше. Да и лишний РОН.
Добавлено after 12 minutes 54 seconds:
Кстати, в моём примере вовсе не LED был. Какой смысл дергать его с частотой десяток МГц? Даже объявление LED на плюсах гораздо удобнее.И далее по коду методы On и Off будут бесплатно учитывать схему подключения. А ещё методы Toggle и ReadState. И при этом ему, по большому счёту, всё равно на STM32 он или вообще не на ARM вовсе.
Э!!! А загрузку R7 куда дели?
Добавлено after 21 minute 49 seconds:
[uquote="iddqd",url="/forum/viewtopic.php?p=3937735#p3937735"]И между нами, LED1_ON как-то информативнее, чтоли, чем какое-то PC15::set которое вообще ни о чем не говорит.[/uquote]
Код: Выделить всё
using LED1 = PC15;[uquote="iddqd",url="/forum/viewtopic.php?p=3937735#p3937735"]Или более жирно по коду?[/uquote]И это тоже да. На одну команду загрузки адреса в РОН больше. Да и лишний РОН.
Добавлено after 12 minutes 54 seconds:
Кстати, в моём примере вовсе не LED был. Какой смысл дергать его с частотой десяток МГц? Даже объявление LED на плюсах гораздо удобнее.
Код: Выделить всё
using LED1 = TLed<PC13>; // Анод на контроллер
using LED2 = TLed<PC14, false>; // Катод на контроллер
- Сообщения: 156
- Зарегистрирован: Вс сен 06, 2020 16:06:10
[uquote="VladislavS",url="/forum/viewtopic.php?p=3937740#p3937740"]iddqd, а теперь то же самое на контроллере без BRR?[/uquote]Ок, #define LED1_OFF REG32_WRITE(GPIOA_BSRR, BIT(LED_PIN1+16)). И получаем:
А как насчет чуть хитрее? Что если мы хотим дергать сразу 1, 3, 5 и 7 пины порта, одновременно? В моем случае компилер скорее всего 1 константу поменяет. А у вас абстракция такой финт вообще позволит? И если да, что в коде будет? Мне в отличие от моего примера, где я с 90% вероятности угадаю что компилер выдаст - не очевидно вообще совсем нихрена.
Код: Выделить всё
LED1_ON;
8000f04: 2110 movs r1, #16
LED1_OFF;
8000f06: f44f 1280 mov.w r2, #1048576 ; 0x100000
LED1_ON;
8000f0a: 4b0a ldr r3, [pc, #40] ; (8000f34 <reset_handler+0x764>)
8000f0c: 6019 str r1, [r3, #0]
LED1_OFF;
8000f0e: 601a str r2, [r3, #0]
LED1_ON;
8000f10: 6019 str r1, [r3, #0]
LED1_OFF;
8000f12: 601a str r2, [r3, #0]
...
Что я про глобальные оптимизации грил? Я пихнул это в проект под рукой, GCC+LTO реюзул r7 внаглую, раз он подходит. А вот на чистом асме так сумничать будет нелегко. Заодно showcase глобальной оптимизации попался.Э!!! А загрузку R7 куда дели?
Так больше соответствует фактическому коду и его активности. Размер кода очевиднее. И если он не нравится, тогда, очевидно, надо пересмотреть подход и возможно циклом оформить, профукав скорость в пользу размера. А у вас что это unroll - на глаз не схватывается. И ощущение сгенеренного кода и эффективности пролюбливается. Оно так и мег кода воткнет, никто и не заметит, пока флеха не кончится.Ну вообще да. 20 строк копипасты вместо указания повторить код 10 раз.
Не вы там возмущались что r7 непонятно откуда? В случае GCC+LTO оценка локального кода - не совсем полная картина мира. И как это глобально на оптимизации скажется - более интересный вопрос на самом деле.И это тоже да. На одну команду загрузки адреса в РОН больше. Да и лишний РОН.
А как насчет чуть хитрее? Что если мы хотим дергать сразу 1, 3, 5 и 7 пины порта, одновременно? В моем случае компилер скорее всего 1 константу поменяет. А у вас абстракция такой финт вообще позволит? И если да, что в коде будет? Мне в отличие от моего примера, где я с 90% вероятности угадаю что компилер выдаст - не очевидно вообще совсем нихрена.
Он виноват только тем что под руку попался и был подходящим тестовым кроликом.Кстати, в моём примере вовсе не LED был. Какой смысл дергать его с частотой десяток МГц?
Даже объявление LED на плюсах гораздо удобнее.Код: Выделить всё
using LED1 = TLed<PC13>; // Анод на контроллер[/quote] Зато я могу быстро заредефайнить LED1_ON так, что оно прокатит даже, блин, на моем десктопе, для вон того нумлока на клавиатуре (под линуксом). Ну да, код поменяется и будет сильно менее эффективным, но в конце концов - тоже LED и тоже ON. Хоть там и нет никакого port C и вообще, файловая система и файловые операции, в сторону usb-шной клавиатуры. А понятие LED1_ON все же применимо. [quote]И далее по коду методы On и Off будут бесплатно учитывать схему подключения. А ещё методы Toggle и ReadState. И при этом ему, по большому счёту, всё равно на STM32 он или вообще не на ARM вовсе.[/quote] Ну, хорошо, и что такое PC13 в контексте моего пиюка с usb-клавиатурой и LED num lock'а на ней как LED1? Вот что такое LED1_ON - я могу в два счета оформить и для этой конфиги, хоть конечно за ним и будет вообще совсем другой код в случае писюка (или одноплатника) с Linux.
- Сообщения: 2089
- Зарегистрирован: Вс июн 19, 2016 09:32:03
[uquote="iddqd",url="/forum/viewtopic.php?p=3937735#p3937735"]
И между нами, LED1_ON как-то информативнее, чтоли, чем какое-то PC15::set которое вообще ни о чем не говорит.[/uquote]
LED1_ON/LED1_OFF/LED_PIN1 сначала нужно задефайнить, для каждого светодиода. А будут разные порты, то может добавиться LED_PORT, или нужен LED1_TOGGLE - будь добр добавь и его. Чтобы появились пины со всеми своими методами нужно лишь добавить хедер, а дальше будет максимум одно переопределение имени на диод.
Добавлено after 27 minutes 25 seconds:
[uquote="iddqd",url="/forum/viewtopic.php?p=3937775#p3937775"]Ну, хорошо, и что такое PC13 в контексте моего пиюка с usb-клавиатурой и LED num lock'а на ней как LED1? Вот что такое LED1_ON - я могу в два счета оформить и для этой конфиги, хоть конечно за ним и будет вообще совсем другой код в случае писюка (или одноплатника) с Linux.[/uquote]
Помнится кто-то ранее в этой теме говорил, что даже F4 - это слишком жирно и потому ему не нужно, а писюк или одноплатник на линуксе значит не жирно?
Какое это имеет отношение к эмбедду?
Код: Выделить всё
#define LED1_ON REG32_WRITE(GPIOA_BSRR, BIT(LED_PIN1))
#define LED1_OFF REG32_WRITE(GPIOA_BRR, BIT(LED_PIN1))
LED1_ON/LED1_OFF/LED_PIN1 сначала нужно задефайнить, для каждого светодиода. А будут разные порты, то может добавиться LED_PORT, или нужен LED1_TOGGLE - будь добр добавь и его. Чтобы появились пины со всеми своими методами нужно лишь добавить хедер, а дальше будет максимум одно переопределение имени на диод.
А как насчет чуть хитрее? Что если мы хотим дергать сразу 1, 3, 5 и 7 пины порта, одновременно? В моем случае компилер скорее всего 1 константу поменяет. А у вас абстракция такой финт вообще позволит? И если да, что в коде будет?
Код: Выделить всё
PinList<PC7, PC3, PC5, PC1>::write(0b1010);
// ldr r2, [pc, #220]
// ldr r6, [pc, #224]
// str r6, [r2, #24]
[uquote="iddqd",url="/forum/viewtopic.php?p=3937775#p3937775"]Ну, хорошо, и что такое PC13 в контексте моего пиюка с usb-клавиатурой и LED num lock'а на ней как LED1? Вот что такое LED1_ON - я могу в два счета оформить и для этой конфиги, хоть конечно за ним и будет вообще совсем другой код в случае писюка (или одноплатника) с Linux.[/uquote]
Помнится кто-то ранее в этой теме говорил, что даже F4 - это слишком жирно и потому ему не нужно, а писюк или одноплатник на линуксе значит не жирно?
Последний раз редактировалось Reflector Пн дек 07, 2020 11:41:14, всего редактировалось 1 раз.
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
[uquote="iddqd",url="/forum/viewtopic.php?p=3937775#p3937775"]Ок, #define LED1_OFF REG32_WRITE(GPIOA_BSRR, BIT(LED_PIN1+16)). И получаем:
[/uquote]И получаем дополнительную ЖИРНУЮ команду загрузки константы, как ни крути.
Добавлено after 10 minutes 40 seconds:
[uquote="iddqd",url="/forum/viewtopic.php?p=3937775#p3937775"]А как насчет чуть хитрее? Что если мы хотим дергать сразу 1, 3, 5 и 7 пины порта, одновременно? В моем случае компилер скорее всего 1 константу поменяет. А у вас абстракция такой финт вообще позволит? И если да, что в коде будет?[/uquote]А если на разных портах, ась?
[uquote="iddqd",url="/forum/viewtopic.php?p=3937775#p3937775"]Мне в отличие от моего примера, где я с 90% вероятности угадаю что компилер выдаст - не очевидно вообще совсем нихрена.[/uquote]Мне очевидно. Очевидно, что для Reflector тоже очевидно. А то что вам неочевидно, так ваши проблемы.
Код: Выделить всё
LED1_ON;
8000f04: 2110 movs r1, #16
LED1_OFF;
8000f06: f44f 1280 mov.w r2, #1048576 ; 0x100000
LED1_ON;
8000f0a: 4b0a ldr r3, [pc, #40] ; (8000f34 <reset_handler+0x764>)
...
Добавлено after 10 minutes 40 seconds:
[uquote="iddqd",url="/forum/viewtopic.php?p=3937775#p3937775"]А как насчет чуть хитрее? Что если мы хотим дергать сразу 1, 3, 5 и 7 пины порта, одновременно? В моем случае компилер скорее всего 1 константу поменяет. А у вас абстракция такой финт вообще позволит? И если да, что в коде будет?[/uquote]
Код: Выделить всё
//using PINS = PinList<PC7, PC5, PC3, PC1>;
//Repeat<10>([]{ PINS::set(); PINS::clear(); } );
MOVS R0,#+170
LDR.N R1,??DataTable1_4 ;; 0x48000818
STR R0,[R1, #+0]
STRH R0,[R1, #+2]
STR R0,[R1, #+0]
STRH R0,[R1, #+2]
STR R0,[R1, #+0]
STRH R0,[R1, #+2]
STR R0,[R1, #+0]
STRH R0,[R1, #+2]
STR R0,[R1, #+0]
STRH R0,[R1, #+2]
STR R0,[R1, #+0]
STRH R0,[R1, #+2]
STR R0,[R1, #+0]
STRH R0,[R1, #+2]
STR R0,[R1, #+0]
STRH R0,[R1, #+2]
STR R0,[R1, #+0]
STRH R0,[R1, #+2]
STR R0,[R1, #+0]
STRH R0,[R1, #+2]
[uquote="iddqd",url="/forum/viewtopic.php?p=3937775#p3937775"]Мне в отличие от моего примера, где я с 90% вероятности угадаю что компилер выдаст - не очевидно вообще совсем нихрена.[/uquote]Мне очевидно. Очевидно, что для Reflector тоже очевидно. А то что вам неочевидно, так ваши проблемы.
- Сообщения: 156
- Зарегистрирован: Вс сен 06, 2020 16:06:10
Насколько я понимаю глобальный оптимизатор - так в том случае если ранее похожего не попадалось. Да, "без BSRR" является достаточно уникальной конструкцией, потому что слеплено специально для того теста. Однако если такого будет несколько, вероятно и реюз константы случится. Ну и кроме того сетап дергов случается до их начала - так что на скорость не влияет. Ну и без BSRR как я помню F0, чтоли. У них еще и набор команд - v6, он в целом похуже чем m3, на этом еще дополнительный слив бывает особенно в математике всякой.
А вот как в тех концепциях сразу несколько пинов с эффективным кодом - я не совсем догоняю. Я в вон тех терминах в принципе я могу описать манипуляцию сразу набором пинов, и на set, и на reset, и будет не сильно хуже по коду. Просто константа станет другой. А в ваших мегаконцепциях чего будет?
А вот как в тех концепциях сразу несколько пинов с эффективным кодом - я не совсем догоняю. Я в вон тех терминах в принципе я могу описать манипуляцию сразу набором пинов, и на set, и на reset, и будет не сильно хуже по коду. Просто константа станет другой. А в ваших мегаконцепциях чего будет?
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
[uquote="iddqd",url="/forum/viewtopic.php?p=3937803#p3937803"]Насколько я понимаю глобальный оптимизатор[/uquote]А теперь вставь этот код в прерывание, допустим, где содержимое регистров за тебя никто раньше не загрузил. А примени в другой единице трансляции, а... Да много ли ещё чего бывает. Компилятор не устаёт.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937803#p3937803"]А вот как в тех концепциях сразу несколько пинов с эффективным кодом - я не совсем догоняю.[/uquote]Не догоняю, но осуждаю. Тоже знакомо.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937803#p3937803"]Просто константа станет другой. А в ваших мегаконцепциях чего будет?[/uquote]Я же показал что будет. Указываем список пинов и погнали. Причем, пины могут быть из разных портов в любой последовательности. Всё сгруппируется как надо. Это могут быть не только set или reset, а write, read, toggle.
Я даже не буду просить повторить нижеследующий пример. Берём две группы пинов на разных портах. Читаем одну группу как байт, инвертируем и записываем во вторую группу.Сколько вы это будете руками ковырять... Компилятор делает за долю секунды.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937803#p3937803"]Ну и без BSRR как я помню F0, чтоли.[/uquote]Только без BRR. В F4 или H7, например. Мэинстрим, как ни крути, приходится учитывать.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937803#p3937803"]А вот как в тех концепциях сразу несколько пинов с эффективным кодом - я не совсем догоняю.[/uquote]Не догоняю, но осуждаю. Тоже знакомо.
[uquote="iddqd",url="/forum/viewtopic.php?p=3937803#p3937803"]Просто константа станет другой. А в ваших мегаконцепциях чего будет?[/uquote]Я же показал что будет. Указываем список пинов и погнали. Причем, пины могут быть из разных портов в любой последовательности. Всё сгруппируется как надо. Это могут быть не только set или reset, а write, read, toggle.
Я даже не буду просить повторить нижеследующий пример. Берём две группы пинов на разных портах. Читаем одну группу как байт, инвертируем и записываем во вторую группу.
Код: Выделить всё
PinList<PC7, PC6, PC5, PC4, PC3, PA0, PA1, PA5> pins1;
PinList<PB1, PB2, PB3, PB4, PB5, PD5, PD1, PD0> pins2;
pins2 = ~pins1;Спойлер
Код: Выделить всё
//pins2 = ~pins1;
LDR.N R1,??DataTable1_4 ;; 0x48000010
LDR R2,[R1, #+2048]
LDR R3,[R1, #+0]
AND R3,R3,#0x23
AND R2,R2,#0xF8
ORR R2,R2,R3, LSR #+5
AND R0,R3,#0x2
LSLS R3,R3,#+2
ORRS R2,R0,R2
AND R3,R3,#0x4
ORRS R2,R3,R2
MVNS R2,R2
AND R3,R2,#0xF8
RBIT R0,R3
LSRS R0,R0,#+23
AND R0,R0,#0x3E
ORR R0,R0,#0x3E0000
STR R0,[R1, #+1032]
AND R0,R2,#0x3
LSLS R2,R2,#+3
AND R2,R2,#0x20
ORRS R2,R2,R0
ORR R2,R2,#0x230000
STR R2,[R1, #+3080]
- Сообщения: 202
- Зарегистрирован: Сб янв 09, 2016 15:51:17
Как вам такая запись?
Здесь структура - как символьный путь заполнения параметров. Если не всем видно - основной упор на AF функции контактов, они всегда уникальные. Своя уникальная огромная структура для каждого мк в уникальном корпусе. Потому как даже в одной серии могут быть незначительные различия в назначении ног. Ну есно структура заполняется не руками, но подбрасывать уголь в топку приходится, что немного утомительно.
Если кому нужно под другой мк - могу сделать.
https://github.com/AVI-crak/gpio_one
Код: Выделить всё
gpio_one_pin(zap_gpio.H.pin05.v_af12_fmc_sdnwe.speed4.pull_up.lock_on); /// FMC_sdnweЕсли кому нужно под другой мк - могу сделать.
https://github.com/AVI-crak/gpio_one
- Сообщения: 8
- Зарегистрирован: Пн дек 07, 2020 14:44:59
основное достоинство ассемблера это предсказуемый результат, вы получаете РОВНО ТО что написали, это надо четко понимать. все остальное это костыли которые призваны облегчить труд программиста (а равно и вхождение) и заработать бизнесу на нем
синергия возможна лишь когда программист владеет и ассемблером и костылем в равной мере на высоком уровне, в противном случае одного знания костыля недостаточно чтобы писать хороший код
синергия возможна лишь когда программист владеет и ассемблером и костылем в равной мере на высоком уровне, в противном случае одного знания костыля недостаточно чтобы писать хороший код
- Сообщения: 2089
- Зарегистрирован: Вс июн 19, 2016 09:32:03
[uquote="AVI-crak",url="/forum/viewtopic.php?p=3937846#p3937846"]Как вам такая запись?[/uquote]
Инициализация десятка пинов с -O0 у меня 23КБ отожрала, потому что самая тяжелая функция принудительно инлайнится
Если этот инлайн убрать, то в разы вырастает размер с включенной оптимизацией.
Инициализация десятка пинов с -O0 у меня 23КБ отожрала, потому что самая тяжелая функция принудительно инлайнится
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
AVI-crak, как для одной ноги вполне нормально получается, если закрыт глаза на попранные стандарты.Плюсовой класс байт 20 выиграл. Но когда это на 20-100 ног умножится, то за гранью добра и зла получится. И во всех режимах все регистры задаются, что не всегда необходимо. Но тут С выше головы не прыгнет.
Добавлено after 53 seconds:
[uquote="Reflector",url="/forum/viewtopic.php?p=3937925#p3937925"]Инициализация десятка пинов с -O0 у меня 23КБ отожрала,[/uquote]Что такое -O0 ???
Спойлер
Код: Выделить всё
Disassembly of section .text.zap_gpio_one_pin.constprop.0:
00000000 <zap_gpio_one_pin.constprop.0>:
zap_in_TypeDef init;
init.data_s = s_gpio;
zap_GPIO_TypeDef* GPIOx = (zap_GPIO_TypeDef*)(0x40020000 + (uint32_t)init.port);
GPIOx->MODER = (GPIOx->MODER & (~(3 << (init.pin << 1)))) | (init.mode << (init.pin << 1));
0: 4b16 ldr r3, [pc, #88] ; (5c <zap_gpio_one_pin.constprop.0+0x5c>)
static void zap_gpio_one_pin (const uint32_t s_gpio)
2: b570 push {r4, r5, r6, lr}
GPIOx->MODER = (GPIOx->MODER & (~(3 << (init.pin << 1)))) | (init.mode << (init.pin << 1));
4: 2405 movs r4, #5
6: 681e ldr r6, [r3, #0]
8: 0060 lsls r0, r4, #1
a: 2203 movs r2, #3
c: fa02 f500 lsl.w r5, r2, r0
10: 2102 movs r1, #2
12: ea26 0605 bic.w r6, r6, r5
16: 4081 lsls r1, r0
18: 4331 orrs r1, r6
1a: 6019 str r1, [r3, #0]
GPIOx->PUPDR = (GPIOx->PUPDR & (~(3 << (init.pin << 1)))) | (init.pup << (init.pin << 1));
1c: 68de ldr r6, [r3, #12]
1e: 2101 movs r1, #1
20: 4081 lsls r1, r0
22: ea26 0605 bic.w r6, r6, r5
26: 4331 orrs r1, r6
28: 60d9 str r1, [r3, #12]
GPIOx->OSPEEDR = (GPIOx->OSPEEDR & (~(3 << (init.pin << 1)))) | (init.sped << (init.pin << 1));
2a: 6899 ldr r1, [r3, #8]
2c: 462a mov r2, r5
2e: ea21 0105 bic.w r1, r1, r5
32: 430a orrs r2, r1
34: 609a str r2, [r3, #8]
if (init.yper) GPIOx->OTYPER |= 1 << init.pin; else GPIOx->OTYPER &= ~(1 << init.pin);
36: 6859 ldr r1, [r3, #4]
38: 2201 movs r2, #1
3a: 40a2 lsls r2, r4
3c: ea21 0102 bic.w r1, r1, r2
40: 6059 str r1, [r3, #4]
if (init.mode == 2 )
{
GPIOx->AFR[init.pin_afa] = (GPIOx->AFR[init.pin_afa] &(~(15 << (init.pin_afd << 2)))) | (init.af << (init.pin_afd << 2));
42: 6a19 ldr r1, [r3, #32]
44: f421 0170 bic.w r1, r1, #15728640 ; 0xf00000
48: f441 0140 orr.w r1, r1, #12582912 ; 0xc00000
4c: 6219 str r1, [r3, #32]
};
if (init.lok)
{
GPIOx->LCKR = (1 << 16) | (1 << init.pin);
4e: f442 3180 orr.w r1, r2, #65536 ; 0x10000
52: 61d9 str r1, [r3, #28]
GPIOx->LCKR = 1 << init.pin;
54: 61da str r2, [r3, #28]
GPIOx->LCKR = (1 << 16) | (1 << init.pin);
56: 61d9 str r1, [r3, #28]
};
};
58: bd70 pop {r4, r5, r6, pc}
5a: bf00 nop
5c: 40021c00 .word 0x40021c00
Добавлено after 53 seconds:
[uquote="Reflector",url="/forum/viewtopic.php?p=3937925#p3937925"]Инициализация десятка пинов с -O0 у меня 23КБ отожрала,[/uquote]Что такое -O0 ???


