Ассемблер для STM32. Сложно ли, стоит ли пытаться?
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
[uquote="Eddy_Em",url="/forum/viewtopic.php?p=3936170#p3936170"]Очень простой язык (чуть сложней ассемблера, зато писанины поменьше, но при этом остается понимание).[/uquote]Сложный язык (сложней С, зато возможностей побольше, и при этом писанины поменьше). Смотри как лаконично записан цикл for по всему массиву. Просто взяли ссылку на каждый элемент массива и отпечатали по ней в терминал. А сортировка массива на этапе компиляции как тебе? И строка форматирования вывода (шаблон от строки на секундочку), держу пари, сильно оптимальней того что printf-ом бы получилось. Reflector столько плюшек в такой маленький пример засунул! Только жаль не все оценить могут.
- Реклама
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
Там где мне вот именно перфоманс (а может и размер кода) важен, я вообще скажу 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++ - и подохренеть малость с того какой си++ простой и офигенный для писания программ без ошибок, что способов прострелить пятку в десяток раз больше. И интересно сколько упражнений местных вообще пройдут проверку такими тулзами без мата статического анализатора.А почему должно быть иначе, если вы не знаете язык?
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
[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 пинов с разных портов... Была относительно недавно тема про семисегментники, пишущие на С там перебирали пины из массива и выводили по одному битуОно и на сях придет к чему-то весьма культурному, если не страдать фигней.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
[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]Покажите мне как ассемблерные вставки его проходят. Ага.
- AVI-crak
- Прорезались зубы
- Сообщения: 202
- Зарегистрирован: Сб янв 09, 2016 15:51:17
- Контактная информация:
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
GCC при сборке Си - закрывает глаза на границы массивов. Записать в массив 20 чисел, когда там всего 10 мест - код соберётся без предупреждений. Это долгоиграющий баг, который в той или иной степени наследуют все языки более сложного уровня. И да, в С++ оно тоже часто прокатывает.
- Реклама
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
[uquote="AVI-crak",url="/forum/viewtopic.php?p=3937249#p3937249"]GCC при сборке Си - закрывает глаза на границы массивов.[/uquote]
Была одна тема, там ТС написал:
В С++ ошибка, как сишный код компилируется даже без предупреждения, по крайней мере если в gcc дополнительные ключи не указывать. Еще недавно столкнулся, в глобальном пространстве имен было типа такого:
Это объявление сишной функции для которого забыли в начале void написать, msvc никаких проблем тут не видит, в C++ это естественно ошибка.
Была одна тема, там ТС написал:
Код: Выделить всё
char s[5] = "Hello";Код: Выделить всё
foo();Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
Прошу прощения, подробное и нудное сообщение к сожалению просралось по техническим причинам, второй раз печатать лень, поэтому кратко:
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 на левую декларацию функции без прототипа бухтит варнингом.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
[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++)());Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
Если вы настаиваете, ок, быренько слепил из того что под рукой, и вышло как-то так:
Ну да, я 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))
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
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>; // Катод на контроллер
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
[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.
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
[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 раз.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
[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 тоже очевидно. А то что вам неочевидно, так ваши проблемы.
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
Насколько я понимаю глобальный оптимизатор - так в том случае если ранее похожего не попадалось. Да, "без BSRR" является достаточно уникальной конструкцией, потому что слеплено специально для того теста. Однако если такого будет несколько, вероятно и реюз константы случится. Ну и кроме того сетап дергов случается до их начала - так что на скорость не влияет. Ну и без BSRR как я помню F0, чтоли. У них еще и набор команд - v6, он в целом похуже чем m3, на этом еще дополнительный слив бывает особенно в математике всякой.
А вот как в тех концепциях сразу несколько пинов с эффективным кодом - я не совсем догоняю. Я в вон тех терминах в принципе я могу описать манипуляцию сразу набором пинов, и на set, и на reset, и будет не сильно хуже по коду. Просто константа станет другой. А в ваших мегаконцепциях чего будет?
А вот как в тех концепциях сразу несколько пинов с эффективным кодом - я не совсем догоняю. Я в вон тех терминах в принципе я могу описать манипуляцию сразу набором пинов, и на set, и на reset, и будет не сильно хуже по коду. Просто константа станет другой. А в ваших мегаконцепциях чего будет?
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
[uquote="iddqd",url="/forum/viewtopic.php?p=3937803#p3937803"]А вот как в тех концепциях сразу несколько пинов с эффективным кодом - я не совсем догоняю.[/uquote]
Может это поможет что-то прояснить.
Может это поможет что-то прояснить.
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
[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]
- AVI-crak
- Прорезались зубы
- Сообщения: 202
- Зарегистрирован: Сб янв 09, 2016 15:51:17
- Контактная информация:
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
Как вам такая запись?
Здесь структура - как символьный путь заполнения параметров. Если не всем видно - основной упор на 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
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
основное достоинство ассемблера это предсказуемый результат, вы получаете РОВНО ТО что написали, это надо четко понимать. все остальное это костыли которые призваны облегчить труд программиста (а равно и вхождение) и заработать бизнесу на нем
синергия возможна лишь когда программист владеет и ассемблером и костылем в равной мере на высоком уровне, в противном случае одного знания костыля недостаточно чтобы писать хороший код
синергия возможна лишь когда программист владеет и ассемблером и костылем в равной мере на высоком уровне, в противном случае одного знания костыля недостаточно чтобы писать хороший код
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
[uquote="AVI-crak",url="/forum/viewtopic.php?p=3937846#p3937846"]Как вам такая запись?[/uquote]
Инициализация десятка пинов с -O0 у меня 23КБ отожрала, потому что самая тяжелая функция принудительно инлайнится
Если этот инлайн убрать, то в разы вырастает размер с включенной оптимизацией.
Инициализация десятка пинов с -O0 у меня 23КБ отожрала, потому что самая тяжелая функция принудительно инлайнится
- VladislavS
- Собутыльник Кота
- Сообщения: 2562
- Зарегистрирован: Вт май 01, 2018 19:44:47
Re: Ассемблер для STM32. Сложно ли, стоит ли пытаться?
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 ???


