Настройка компиляции в Arduino IDE
- Войдите на сайт для отправки комментариев
Вс, 22/05/2016 - 20:15
Добрый всем вечер.
Собственно захотелось поиграться с настройкой компиляции. В частности с уровнями оптимизации (O1, Os) и вытащить ассемблерный листинг avr-objdump'ом из файла ELF.
Не нашел, где записана строка с параметрами вызова avr-gcc и можно ли добавить вызов avr-objdump (кроме avr-gcc ещё вызывается avr-objcopy). Пока приходится вручную запускать avr-objdump и скармливать ему ELF.
Может кто знает? Спасибо.
Такое ощущение, что это где-то захардкожено...
строка с параметрами вызова avr-gcc и
У меня
<корень IDE>\hardware\arduino\avr\platform.txt
можно ли добавить вызов avr-objdump
Не знаю, я отдельно запускал.
У меня
<корень IDE>\hardware\arduino\avr\platform.txt
Вот спасибо. Похоже эту возможность добавили в новых версиях, начиная с 1.5.*. В старых версиях 1.0.* такого нет.
С уровнем оптимизации разобрался, а вот вызов objdump пока не получилось добавить.
В общем разобрался со всем. Расскажу, может ещё кому пригодится. Как уже упоминалось, всё настраивается в файле <корень IDE>\hardware\arduino\avr\platform.txt
1) Уровень оптимизации меняется в строках compiler.c.flags, compiler.c.elf.flags, compiler.cpp.flags. По умолчанию стоит -Os
2) Автоматический вывод ассемблерного листинга в файл с помощью утилиты avr-objdump делается через хуки (hooks). В platform.txt в секции AVR compile variables добавляем новые строки:
compiler.objdump.cmd=avr-objdump.bat compiler.objdump.flags={compiler.path}, {build.path}\{build.project_name}.elf, {build.path}\{build.project_name}.lstВ секции AVR compile patterns, подсекции Create output files (.eep and .hex) добавляем строку:
recipe.hooks.objcopy.postobjcopy.1.pattern="{compiler.path}{compiler.objdump.cmd}" {compiler.objdump.flags}(Описание всех хуков ЗДЕСЬ)
Всё, теперь после компиляции во временной папке что-то типа C:\Users\User\AppData\Local\Temp\build28f38fc51e0bd2ba8c700ba028289fe6.tmp\ рядом с файлами *.hex и *.elf появится файл *.lst с ассемблерным листингом (обычный текстовый файл, кому не нравится расширение - можно поменять на *.txt в строке compiler.objdump.flags).
P.S. По поводу костыля с батником. Утилиту avr-objdump можно вызывать напрямую из среды и передавать её параметры. Но Arduino IDE не обрабатывает символ вывода в файл ">" (который работает в виндовой консоли) и тупо ругается на него. Поэтому пришлось вызывать батник, передавать ему параметры, а уже он вызывает утилиту и делает вывод в файл.
P.P.S. Проверял на Arduino IDE версии 1.6.6. Хуки добавили с версии 1.6.5. А на старых версиях меньше 1.5.* файла platform.txt вообще нет.
Прикладываю свои файлы platform.txt и avr-objdump.bat
Пасибки, полезно.
Жека, а чем objdump удобнее, чем если сразу компилятору сказать, чтобы ассемблерный код выдал?
Вы про опцию -Wa,-ahls=file.lst ? У меня почему-то не получилось, запутался в хитросплетениях формирования всей строки с параметрами для avr-gcc. Да и проверил эту опцию в Atmel Studio - не понравился вид представления информации и форматирование. В общем, вывод objdump мне понравился больше. Но это так, с моей "любительской" точки зрения :)
Для сравнения, objdump:
Sections: Idx Name Size VMA LMA File off Algn 0 .data 00000000 00800100 00800100 0000013c 2**0 CONTENTS, ALLOC, LOAD, DATA 1 .text 000000e8 00000000 00000000 00000054 2**1 CONTENTS, ALLOC, LOAD, READONLY, CODE 2 .comment 00000030 00000000 00000000 0000013c 2**0 CONTENTS, READONLY 3 .note.gnu.avr.deviceinfo 00000040 00000000 00000000 0000016c 2**2 CONTENTS, READONLY 4 .debug_aranges 00000028 00000000 00000000 000001ac 2**0 CONTENTS, READONLY, DEBUGGING 5 .debug_info 000001e8 00000000 00000000 000001d4 2**0 CONTENTS, READONLY, DEBUGGING 6 .debug_abbrev 000000e5 00000000 00000000 000003bc 2**0 CONTENTS, READONLY, DEBUGGING 7 .debug_line 000001b8 00000000 00000000 000004a1 2**0 CONTENTS, READONLY, DEBUGGING 8 .debug_frame 00000034 00000000 00000000 0000065c 2**2 CONTENTS, READONLY, DEBUGGING 9 .debug_str 000001a2 00000000 00000000 00000690 2**0 CONTENTS, READONLY, DEBUGGING 10 .debug_ranges 00000018 00000000 00000000 00000832 2**0 CONTENTS, READONLY, DEBUGGING Disassembly of section .text: 00000000 <__vectors>: 0: 0c 94 34 00 jmp 0x68 ; 0x68 <__ctors_end> 4: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 8: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 10: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 14: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 18: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 1c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 20: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 24: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 28: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 2c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 30: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 34: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 38: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 3c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 40: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 44: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 48: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 4c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 50: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 54: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 58: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 5c: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 60: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 64: 0c 94 3e 00 jmp 0x7c ; 0x7c <__bad_interrupt> 00000068 <__ctors_end>: 68: 11 24 eor r1, r1 6a: 1f be out 0x3f, r1 ; 63 6c: cf ef ldi r28, 0xFF ; 255 6e: d8 e0 ldi r29, 0x08 ; 8 70: de bf out 0x3e, r29 ; 62 72: cd bf out 0x3d, r28 ; 61 74: 0e 94 47 00 call 0x8e ; 0x8e <main> 78: 0c 94 72 00 jmp 0xe4 ; 0xe4 <_exit> 0000007c <__bad_interrupt>: 7c: 0c 94 00 00 jmp 0 ; 0x0 <__vectors> 00000080 <setup>: #include <avr/io.h> #include <util/delay.h> void setup() { DDRB |= ((1<<5)|(1<<4)); 80: 84 b1 in r24, 0x04 ; 4 82: 80 63 ori r24, 0x30 ; 48 84: 84 b9 out 0x04, r24 ; 4 PORTB &= ~((1<<5)|(1<<4)); 86: 85 b1 in r24, 0x05 ; 5 88: 8f 7c andi r24, 0xCF ; 207 8a: 85 b9 out 0x05, r24 ; 5 8c: 08 95 ret 0000008e <main>: } int main(void) { setup(); 8e: 0e 94 40 00 call 0x80 ; 0x80 <setup> while (1) { PORTB |= (1<<5); //PB5, D13 92: 2d 9a sbi 0x05, 5 ; 5 asm volatile("sbi %0, 4" :: "I" (_SFR_IO_ADDR(PORTB))); //PB4, D12 94: 2c 9a sbi 0x05, 4 ; 5 #else //round up by default __ticks_dc = (uint32_t)(ceil(fabs(__tmp))); #endif __builtin_avr_delay_cycles(__ticks_dc); 96: 8f e3 ldi r24, 0x3F ; 63 98: 9c e9 ldi r25, 0x9C ; 156 9a: 01 97 sbiw r24, 0x01 ; 1 9c: f1 f7 brne .-4 ; 0x9a <main+0xc> 9e: 00 c0 rjmp .+0 ; 0xa0 <main+0x12> a0: 00 00 nop _delay_ms(10); PORTB &= ~(1<<5); //PB5, D13 a2: 2d 98 cbi 0x05, 5 ; 5 asm volatile("cbi %0, 4" :: "I" (_SFR_IO_ADDR(PORTB))); //PB4, D12 a4: 2c 98 cbi 0x05, 4 ; 5 a6: 8f e3 ldi r24, 0x3F ; 63 a8: 9c e9 ldi r25, 0x9C ; 156 aa: 01 97 sbiw r24, 0x01 ; 1 ac: f1 f7 brne .-4 ; 0xaa <main+0x1c> ae: 00 c0 rjmp .+0 ; 0xb0 <main+0x22> b0: 00 00 nop _delay_ms(10); PORTB |= ((1<<5)|(1<<4)); //Set PB5, PB4 b2: 85 b1 in r24, 0x05 ; 5 b4: 80 63 ori r24, 0x30 ; 48 b6: 85 b9 out 0x05, r24 ; 5 asm volatile("in R24, %0 \n andi R24, 0b11001111 \n out %0, R24" :: "I" (_SFR_IO_ADDR(PORTB))); //Clear PB5, PB4 b8: 85 b1 in r24, 0x05 ; 5 ba: 8f 7c andi r24, 0xCF ; 207 bc: 85 b9 out 0x05, r24 ; 5 be: 8f e3 ldi r24, 0x3F ; 63 c0: 9c e9 ldi r25, 0x9C ; 156 c2: 01 97 sbiw r24, 0x01 ; 1 c4: f1 f7 brne .-4 ; 0xc2 <main+0x34> c6: 00 c0 rjmp .+0 ; 0xc8 <main+0x3a> c8: 00 00 nop _delay_ms(10); asm volatile("in R24, %0 \n ori R24, 0b00110000 \n out %0, R24" :: "I" (_SFR_IO_ADDR(PORTB))); //Set PB5, PB4 ca: 85 b1 in r24, 0x05 ; 5 cc: 80 63 ori r24, 0x30 ; 48 ce: 85 b9 out 0x05, r24 ; 5 PORTB &= ~((1<<5)|(1<<4)); //Clear PB5, PB4 d0: 85 b1 in r24, 0x05 ; 5 d2: 8f 7c andi r24, 0xCF ; 207 d4: 85 b9 out 0x05, r24 ; 5 d6: 8f e3 ldi r24, 0x3F ; 63 d8: 9c e9 ldi r25, 0x9C ; 156 da: 01 97 sbiw r24, 0x01 ; 1 dc: f1 f7 brne .-4 ; 0xda <main+0x4c> de: 00 c0 rjmp .+0 ; 0xe0 <main+0x52> e0: 00 00 nop e2: d7 cf rjmp .-82 ; 0x92 <main+0x4> 000000e4 <_exit>: e4: f8 94 cli 000000e6 <__stop_program>: e6: ff cf rjmp .-2 ; 0xe6 <__stop_program>avr-gcc:
Вы про опцию -Wa,-ahls=file.lst ?
я пишу вот так (в bat-айле):
-Wa,-a=C:\Arduino\build\%1.asm
Вроде, работает.
Сравнил Ваши листинги. objdump понравился больше. Попробую.
Лично мне objdump интересней тем, что его можно, когда нужно, запустить отдельным командником и получить асм листинг, а на постоянке оно нафиг не нужно. ИМХО, конечно же.
В принципе согласен. Но смысл был в том, чтобы один раз сделать и забыть. Если вдруг понадобился листинг - просто залез во временную папку и посмотрел. Оно же не хранится постоянно на ПК - после закрытия IDE временная папка со всеми файлами удаляется.
В принципе согласен. Но смысл был в том, чтобы один раз сделать и забыть. Если вдруг понадобился листинг - просто залез во временную папку и посмотрел. Оно же не хранится постоянно на ПК - после закрытия IDE временная папка со всеми файлами удаляется.
Да не вопрос, каждый волен поступать так, как ему хочется. Я же не осуждаю ;)
Вот только у меня большие сомнения, на счет фразы "один раз сделать и забыть", еще не факт, что в IDE что либо не поменяется, а командник он с IDE вообще не связан, он срабатывает на расширение файла и вызывает objdump. Разумеется, objdump могут переместить в другое место в IDE.
Уфф, кажется только отнимаю время у всех, я закончил. :)
А вот кусок листинга, сделанного IDA PRO 6.5
еще не факт, что в IDE что либо не поменяется
С этим согласен, в IDE периодически вносят довольно большие изменения.
а командник он с IDE вообще не связан, он срабатывает на расширение файла и вызывает objdump. Разумеется, objdump могут переместить в другое место в IDE.
Вот тут есть положительный момент: в platform.txt не используются абсолютные пути. Путь к objdump и *.elf подставляется автоматически: {compiler.path}, {build.path}. Название файла тоже: {build.project_name}. Хотя название можно и не использовать, а только путь к папке. А в батнике сделать срабатывание на расширение файла, как Вы и написали (но смысла в этом не вижу).
Objdump если и перенесут, то явно вместе с остальными утилитами и компиляторм, поэтому {compiler.path} будет всё так же работать.
P.S. я не ради спора, просто уточнил некоторые моменты.
На вкус и цвет все фломастеры разные ;) Думаю на том и сойдемся, я никогда не буду включать objdump в сборку, а Вы не будете писать командник, вот и все дела. И в этом нет ничего особенного, каждый прав по-своему.
Скажите как правильно в файл platform.txt добавить дефайн типа { #define NOMORE } , что бы он использовался только при компиляции .с файлов? Может быть куда то в строку compiler.c.flags ?
1. Скоро в Песочнице будет об этом материал.
2. НУ НУЖНО ничего менять в системных каталогах.
3. Ниже последовательность действий. Пример для Наны, есть токости, если у самого не получится со своей платой - пиши сюда - я помогу.
ИТАК (я описываю свой пример, который только что проверил):
1. в скетчбуке создаеи папку hardware, скорее всего она у тебя уже есть.
2. в ней папку wlad_nano;
3. в ней папку avr;
4. в ней файл boards.txt вот такой:
Это просто копия из системного про нано, ВАЖНЫЕ ДОБАВЛЕНИЯ:
а) "arduino:" - добавлено в трех местах, будь внимателен, это отсылка к общим настройкам.
б) ТО САМОЕ, ЧТО ТЫ ХОТЕЛ - последняя строчка определяет имя WLAD.
все это проверяем, выбирая при сборке плату: "Arduino Nano by Wlad".
вот проверочный скетч:
void setup() { Serial.begin(57600); while(!Serial); #ifdef WLAD Serial.println("WLAD defined!"); #endif } void loop() { }Если тебе нужны другие РЕЦЕПТЫ компиляции, то это сложнее, нужно создавать новую ПЛАТФОРМУ. Подожди тогда до статьи в Песочнице.
При выполнении сборки, порой требуется сначала выполнить дополнительные действия, например выполнить преобразования файлов перед сборкой.
В platform.local.txt добавляю
recipe.hooks.sketch.prebuild.0.pattern={runtime.platform.path}/prebuild.local {build.source.path} {build.path} {build.project_name}Рядышком с platform.local.txt положил тот самый prebuild.local, который выполнит prebuild в директории со скетчем если он там присутствует.
Здравствуйте. Сделал как написано в статье, но выскочила ошибка .... bin/avr-objdump.bat": file does not exist.
Подскажите как преодолеть эту проблему. у мене Aeduino IDE 1.8.12 версия.
Да, ярлык с админ правами не помог.
Написано же - Файл отсутствует.
Здравствуйте. Сделал как написано в статье, но выскочила ошибка .... bin/avr-objdump.bat": file does not exist.
Подскажите как преодолеть эту проблему. у мене Aeduino IDE 1.8.12 версия.
Так надо добавить путь к bin в PATH
Спасибо. Разобрался. .bat файл нужно разместить в папку bin: c:\Users\<your name>\AppData\Local\Arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino5\bin\.
Корень Arduino IDE это ведь в Programms Files(x86).