Comments 16
Посидел сейчас, и получил размер программы 56 байт… меньше уже не знаю как сделать — мешает формат THUMB инструкций (требуется выравнивание к 4 байтам — и программа слишком маленькая чтобы было что менять) :-)
p.s. осталось только проверить на работоспособность (но это только дома)
p.s. осталось только проверить на работоспособность (но это только дома)
0
написал на gcc за 10 минут тоже самое и сразу влезло в 52 байта
версия GNU Tools ARM Embedded 4.6 2012q4
ключи компилирования:
arm-none-eabi-gcc -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -Wall -ffunction-sections -g -Os -c…
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -Wl -nostartfiles -g -Wl,-Map=Gate_Tester.map -Os -Wl,--gc-sections -LE:/gsm/src/Gate_Tester -Wl,-TE:/gsm/src/Gate_Tester/arm-gcc-link.ld -g -o Gate_Tester.elf ..\obj\stm32kiss_button.o
оптимизация по размеру -Os, LTO (оптимизация при линковке) нет в этой версии gcc
бинарник в хекс редакторе:
![image](https://habrastorage.org/r/w1560/getpro/habr/comment_images/c1f/987/58c/c1f98758c36b5eeb788b9ce4e1c1be7f.png)
Program Size:
text data bss dec hex filename
52 0 65536 65588 10034 Gate_Tester.elf
версия GNU Tools ARM Embedded 4.6 2012q4
ключи компилирования:
arm-none-eabi-gcc -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard -mthumb -Wall -ffunction-sections -g -Os -c…
arm-none-eabi-gcc -mcpu=cortex-m4 -mthumb -Wl -nostartfiles -g -Wl,-Map=Gate_Tester.map -Os -Wl,--gc-sections -LE:/gsm/src/Gate_Tester -Wl,-TE:/gsm/src/Gate_Tester/arm-gcc-link.ld -g -o Gate_Tester.elf ..\obj\stm32kiss_button.o
оптимизация по размеру -Os, LTO (оптимизация при линковке) нет в этой версии gcc
void min_Reset_Handler();
#define STACK_SIZE 0x00004000 /*!< Stack size (in Words) */
__attribute__ ((section(".co_stack"))) unsigned long minStack[STACK_SIZE];
__attribute__ ((section(".min_isr_vector"))) void (* const minVectors[])(void) =
{
(void *)&minStack[STACK_SIZE-1], /*!< The initial stack pointer*/
min_Reset_Handler, /*!< Reset Handler */
};
void min_Reset_Handler()
{
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
GPIOD->MODER |= GPIO_MODER_MODER15_0;
uint32_t counter;
volatile uint32_t *led = (*(volatile uint32_t *)(PERIPH_BB_BASE + ((((uint32_t)&GPIOD->ODR) - PERIPH_BASE)*32) + 15*4));
while (true)
{
(*led) = counter >> 31;
counter += 1024;
}
}
Disassembly of section .text:
08000000 <minVectors>:
8000000: fc ff 00 10 09 00 00 08 ........
08000008 <min_Reset_Handler>:
8000008: 4b08 ldr r3, [pc, #32] ; (800002c <min_Reset_Handler+0x24>)
;RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
800000a: 6b19 ldr r1, [r3, #48] ; 0x30
800000c: f041 0108 orr.w r1, r1, #8
8000010: 6319 str r1, [r3, #48] ; 0x30
;GPIOD->MODER |= GPIO_MODER_MODER15_0;
8000012: f5a3 5330 sub.w r3, r3, #11264 ; 0x2c00
8000016: 6819 ldr r1, [r3, #0]
8000018: f041 4180 orr.w r1, r1, #1073741824 ; 0x40000000
800001c: 6019 str r1, [r3, #0]
;volatile uint32_t *led = (*(volatile uint32_t *)(PERIPH_BB_BASE + ((((uint32_t)&GPIOD->ODR) - PERIPH_BASE)*32) + 15*4));
800001e: 4b04 ldr r3, [pc, #16] ; (8000030 <min_Reset_Handler+0x28>)
;uint32_t counter;
8000020: 681b ldr r3, [r3, #0]
<min_Reset_Handler_while>:
8000022: 0fd1 lsrs r1, r2, #31 ;
8000024: 6019 str r1, [r3, #0] ; (*led) = counter >> 31;
8000026: f502 6280 add.w r2, r2, #1024 ; counter += 1024;
800002a: e7fa b.n 8000022 <min_Reset_Handler_while>
800002c: 40023800 .word 0x40023800
8000030: 424182bc .word 0x424182bc
или в сыром виде без моих камментов:![image](https://habrastorage.org/r/w1560/getpro/habr/comment_images/274/ed8/60b/274ed860b3618e266d4a56974535b8de.png)
![image](https://habrastorage.org/getpro/habr/comment_images/274/ed8/60b/274ed860b3618e266d4a56974535b8de.png)
ld файл стандартный кокосовский
OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
/* Internal Memory Map*/
MEMORY
{
rom (rx) : ORIGIN = 0x08000000, LENGTH = 0x000F8000
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00020000
ccm (rwx) : ORIGIN = 0x10000000, LENGTH = 0x00010000
}
_eram = 0x20000000 + 0x00020000;
/* Section Definitions */
SECTIONS
{
.text :
{
. = 0x00000000;
/*KEEP(*(.isr_vector .isr_vector.*))*/
KEEP(*(.min_isr_vector .min_isr_vector.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
} > rom
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > rom
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
__exidx_end = .;
. = ALIGN(4);
_etext = .;
_sidata = .;
.data : AT (_etext)
{
_sdata = .;
*(.data .data.*)
. = ALIGN(4);
_edata = . ;
} > ram
/* .bss section which is used for uninitialized data */
.bss (NOLOAD) :
{
_sbss = . ;
*(.bss .bss.*)
*(COMMON)
. = ALIGN(4);
_ebss = . ;
} > ram
/* stack section */
.co_stack (NOLOAD):
{
. = ALIGN(8);
*(.co_stack .co_stack.*)
} > ccm
. = ALIGN(4);
_end = . ;
}
бинарник в хекс редакторе:
![image](https://habrastorage.org/getpro/habr/comment_images/c1f/987/58c/c1f98758c36b5eeb788b9ce4e1c1be7f.png)
+2
ну на счет 10 минут — что то «меня берут смутные сомнения» (с) Брилиантовая рука, но «ход» со сдвигом- однозначно интересен!!! я до такого простого и краткого решения не додумался…
тогда 38 байт! (только с позицией стека нужно уточнить, но помоему правильно)
Бинарник:
![](https://habrastorage.org/r/w780q1/files/529/a09/853/529a0985379e4820bc1829a6bbcfc878.jpg)
тогда 38 байт! (только с позицией стека нужно уточнить, но помоему правильно)
Disassembly of section .text:
00000000 <AB_STACK-0x8>:
0: 00000008 .word 0x00000008
4: 00000015 .word 0x00000015
00000008 <AB_STACK>:
8: 00000001 .word 0x00000001
c: 4247060c .word 0x4247060c
10: 42418038 .word 0x42418038
00000014 <Reset>:
14: bc0e pop {r1, r2, r3}
16: 6019 str r1, [r3, #0]
18: 6011 str r1, [r2, #0]
0000001a <BLINK_LOOP>:
1a: 0fe1 lsrs r1, r4, #31
1c: f8c3 1284 str.w r1, [r3, #644] ; 0x284
20: f504 6480 add.w r4, r4, #1024 ; 0x400
24: e7f9 b.n 1a <BLINK_LOOP>
Бинарник:
![](https://habrastorage.org/files/529/a09/853/529a0985379e4820bc1829a6bbcfc878.jpg)
0
помоему регистр перепутал на запись значения,… дома проверю :-)
0
браво, но смысла нет кроме рекорда длинны и образовательного смысла для тех кто слаб в асме.
я своим постом хотел сказать что даже на мелких и ничтожно мелких задачах Си в прямых руках по всем параметрам на уровне асма.
А по потреблению времени — реально 10 минут, я дольше ответ оформлял.
я своим постом хотел сказать что даже на мелких и ничтожно мелких задачах Си в прямых руках по всем параметрам на уровне асма.
А по потреблению времени — реально 10 минут, я дольше ответ оформлял.
0
ну все примеры смысла не имеют, но для понимания механизма очень полезны!
я вот про сдвиговую генерацию значения даже не додумался!!! более того — со сдвигами у меня туго — сидел и на бумажке рисовал сейчас :-))
в моем примере запись в R2 и в R3 местами поменять нужно!!!
кстати, на асме — на больших участках кода оптимизировать код проще — зачастую 5-10 строк асм-кода уже можно в подпрограммы выделять, да и частичное использование кода проще делать…
хотя конечно на асме тяжело писать — меня например сейчас напрягает то, что не знаю как делать изолированные метки :-(
в armasm метки кроме определенных директивами компилятора export/import видны только внутри файла исходника…
то есть шанса на пересечение в разных файлах нет…
а вот в GNU AS такой фичи не нашел :-((( вернее она там есть (по названию метки, не помню точно с «L» чтоли начинаться должны) — но указано (как я понял) как отмирающая что ли, и не во всех версиях реализована…
я вот про сдвиговую генерацию значения даже не додумался!!! более того — со сдвигами у меня туго — сидел и на бумажке рисовал сейчас :-))
в моем примере запись в R2 и в R3 местами поменять нужно!!!
кстати, на асме — на больших участках кода оптимизировать код проще — зачастую 5-10 строк асм-кода уже можно в подпрограммы выделять, да и частичное использование кода проще делать…
хотя конечно на асме тяжело писать — меня например сейчас напрягает то, что не знаю как делать изолированные метки :-(
в armasm метки кроме определенных директивами компилятора export/import видны только внутри файла исходника…
то есть шанса на пересечение в разных файлах нет…
а вот в GNU AS такой фичи не нашел :-((( вернее она там есть (по названию метки, не помню точно с «L» чтоли начинаться должны) — но указано (как я понял) как отмирающая что ли, и не во всех версиях реализована…
0
" на асме — на больших участках кода оптимизировать код проще" вот только человек с этим справляется хуже т.к. оптимизирует частности и не всегда и не везде, а компилятор всё и сразу, может быть в каких то мелочах похуже человека но в целом картина выглядит существенно более сбалансированной.
Как то надо было адаптировать gprs загрузчик с STM32F4xx на STM32F10x самый младший, при этом он был написан на Си и модульный, отдельно драйвер уарта, отдельно парсер команд, отдельно regexp для парсера, отдельно управлятор АТ командами и тд.
А надо было уменьшить в 2-3 раза размер флеша и озу.
При помощи простых операций не вмешиваясь в суть исходников на Си я это сделал вполне успешно, было потребление озу 24-30кбайт, стало 12кбайт. И вписался в 4к ОЗУ из первоначальных 12к.
А сколько времени займёт переписать на ассемблере около 10 тысяч строк Си кода? и точно результат влезет в 12к флеша? Не профукаем ли мы какие либо мелочи спустя лет десять?
Насчёт глобальных и локальных меток… помню лет 20 назад когда кодил на асме в турбоасме были директивы для этого, помоему это global и import если не ошибаюсь, попробуй поискать аналогичные.
Как то надо было адаптировать gprs загрузчик с STM32F4xx на STM32F10x самый младший, при этом он был написан на Си и модульный, отдельно драйвер уарта, отдельно парсер команд, отдельно regexp для парсера, отдельно управлятор АТ командами и тд.
А надо было уменьшить в 2-3 раза размер флеша и озу.
При помощи простых операций не вмешиваясь в суть исходников на Си я это сделал вполне успешно, было потребление озу 24-30кбайт, стало 12кбайт. И вписался в 4к ОЗУ из первоначальных 12к.
А сколько времени займёт переписать на ассемблере около 10 тысяч строк Си кода? и точно результат влезет в 12к флеша? Не профукаем ли мы какие либо мелочи спустя лет десять?
Насчёт глобальных и локальных меток… помню лет 20 назад когда кодил на асме в турбоасме были директивы для этого, помоему это global и import если не ошибаюсь, попробуй поискать аналогичные.
0
Насчёт глобальных и локальных меток… помню лет 20 назад когда кодил на асме в турбоасме были директивы для этого, помоему это global и import если не ошибаюсь, попробуй поискать аналогичные
нашел, но что то не соображу как теперь cmd файл поправить :-(
нужно в цикле организовать перебор каталогов и файлов в них, потом в этом же цикле создать в отдельном каталоге такую же структуру каталогов (вот тут я что то уже голову сломал как это сделать) и запустить для каждого файла .asm компилятор чтобы он сделал .o файл…
а потом все получившиеся .o файлы подсунуть компановщику…
p.s. у меня пока не получается создать структуру каталогов :-(
0
а разве этим не makefile или Autotools должен заниматься?
в том же эклипсе (работает на makefile) всё делается автоматом независимо от структуры директорий и не требуя от пользователя никаких действий
в том же эклипсе (работает на makefile) всё делается автоматом независимо от структуры директорий и не требуя от пользователя никаких действий
0
А зачем тут сдвиг, если значение всё равно берётся из младшего бита? Так?
1: str r4,[r3, #644]
adc r4,r4,#2048
b 1b
1: str r4,[r3, #644]
adc r4,r4,#2048
b 1b
0
Спасибо, очень интересный цикл статей, на таком уровне последний раз работал только с AVR.
Проверил на STM32F4-Discovery — все отлично работает.
Проверил на STM32F4-Discovery — все отлично работает.
+1
Sign up to leave a comment.
STM32F4: GNU AS: Мигаем светодиодом (Версия для STM32F4 Discovery, Оптимизация) (Часть 3)