injen-d 0 11 января, 2008 Опубликовано 11 января, 2008 · Жалоба Всем доброго времени суток. Помогите пожалуйста, может кто сталкивался с подобными непонятками, буду очень признателен. Не так давно AVRа стало маловато, решил переходить на ARM7, причем софт решил использовать свободный, чтоб так сказать все по честному. Выбор пал на YAGARTO Eclipse + GCC. До этого писал преимущественно на ассемблере, поэтому столкнулся с массой трудностей. Но постепенно все прояснялось, вот только со следующей проблемой борюсь уже 2 дня и ни сколько не продвинулся в ее решении. Даже появились грешные мысли воспользоваться ломаным иаром или кейлом :05: Проблема в следующем: решил я воспользоваться файлом "libAT91SAM7S256.h" (взял его где-то из примеров) и сразу после его подключения и последующей компиляции (ни одну из его функций я еще не использовал) размер генерируемого кода увеличился с 1К до 17К. Как выяснилось компилятся все функции независимо от того, вызывались они или нет. После "танцев с бубном, протирки монитора и постукивания по системнику" совершенно чудесным образом хидер начал компилиться как надо: только те функции которые были вызваны из main (или другой функции). :08: На радостях я решил сделать еще один хидер назвал его "icpsr.h" и вставил содержимое из файла "isrsupport.c" из примера demo_at91sam7_blink_flash. И тут опять старая проблема! Причем "libAT91SAM7S256.h" работает правильно, а "icpsr.h" компилится весь. Приведенные выше маневры не помогли. Подскажите, плиз проблема в компиляторе или в моей голове? Проэкт прилагается. NEW_workspace.rar ЗЫ: при установке компилятору уровня оптимизации отличного от -О0 размер кода заметно сокращается, но компилятор начинает полностью игнорировать конструкции типа: for (k = 600000; k != 0; k-- ); как будто их не существует! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 11 января, 2008 Опубликовано 11 января, 2008 · Жалоба решил я воспользоваться файлом "libAT91SAM7S256.h" (взял его где-то из примеров) и сразу после его подключения и последующей компиляции (ни одну из его функций я еще не использовал) размер генерируемого кода увеличился с 1К до 17К.Дело в том, что на уровне оптимизации -O0 выключено встраивание функций, и квалификатор __inline не работает. Поэтому включите оптимизацию хотя бы -O1, а лучше всего -Os. Чтобы любые неиспользуемые функции не подлинковывалисть в выходной файл, добавьте в makefileCFLAGS += -ffunction-sections -fdata-sections # to remove dead code, if any, at link time LDFLAGS += -Wl,--gc-sections #remove dead code ("garbage collection") ЗЫ: при установке компилятору уровня оптимизации отличного от -О0 размер кода заметно сокращается, но компилятор начинает полностью игнорировать конструкции типа: for (k = 600000; k != 0; k-- ); как будто их не существует! Правильно. Этот код ничего не делает, поэтому и выкидывается. Вы же хотели оптимизацию - вот компилятор и сократил и код, и время выполнения. Вам ведь не нравятся другие медленно работающие программы? ;) Чтобы этого не происходило, объявите k как volatile или вставьте в тело цикла что-нибудь типа asm(" nop"); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
injen-d 0 12 января, 2008 Опубликовано 12 января, 2008 · Жалоба Спасибо за разъяснение, но это проблему не решило. Я поправил Makefile, правда не совсем так, как вы указали: CFLAGS += -ffunction-sections -fdata-sections # to remove dead code, if any, at link time LDFLAGS += -Wl,--gc-sections #remove dead code ("garbage collection") я исправил на: CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections в соответствии с "GNAT User’s Guide For gcc version 4.2.2" 7.3.2 Compilation options The operation of eliminating the unused code and data from the final executable is directly performed by the linker. In order to do this, it has to work with objects compiled with the following options: ‘-ffunction-sections’ ‘-fdata-sections’. These options are usable with C and Ada files. They will place respectively each function or data in a separate section in the resulting object file. Once the objects and static libraries are created with these options, the linker can perform the dead code elimination. You can do this by setting the ‘-Wl,--gc-sections’ option to gcc command or in the ‘-largs’ section of gnatmake. This will create the final executable, without including the code and data determined as never accessed. Note that objects compiled without the ‘-ffunction-sections’ and ‘-fdata-sections’ options can still be linked with the executable. However, no dead code elimination will be performed on those objects (they will be linked as is). The GNAT static library is now compiled with -ffunction-sections and -fdata-sections. This allows you to eliminate the unused code of the GNAT library from your executable. После этого линкер начал требовать прописывания секции для каждой функции и глобальной переменной. После срочного изучения основ написания скриптов для линкера родились следующие строки: .text : /* collect all sections that should go into FLASH after startup */ { /* *(.text) /* all .text sections (code) */ *(.text.main) *(.text.USART0_setup) *(.text.uart0_putc) *(.text.Usart_c_irq_handler) *(.text.LowLevelInit) *(.text.blinker) ... Проэкт начал компилиться без ошибок. Но не все так хорошо: 1) "правильно" компилятся только __inline функции, остальные же по-прежнему компилятся всегда и при удалении их вызова сами они никуда из итогового кода не исчезают. 2) линкер требует прописывания секций так же для функций находящихся в хидере icpsr.h (кроме __inline функций), даже если они не вызывались. 3) а если у меня в проэкте около сотни различных функций наберется? Это ж сколько писанины в разных файлах. А еще глобальные переменные... Все вышеизложенное наталкивает на мысль, что решение должно быть гораздо проще. К тому же, в первоначальном варианте, до вышеописанной правки, для эксперемента я сделал __inline все функции в файле icpsr.h, таким образом получилось два почти одинаковых файла icpsr.h и libAT91SAM7S256.h. Различие было лишь в количестве содержащихся функций. Затем я подключал эти хидеры в соседних строках одного си-файла и вызывал по одной функции из каждого файла тоже в соседних строках, при этом из файла libAT91SAM7S256.h компилировалась только вызываемая функция, а из icpsr.h все по отдельности + еще раз вызываемая на этот раз в нужном месте. Глаза поломал, но разницу между файлами (кроме количества содержащихся функций) не увидел. :unsure: В чем может быть причина? Да и файл libAT91SAM7S256.h поначалу тоже компилился весь, но в какой-то момент во время танцев с бубном заработал как надо, и при последующей правке всяких мелочей содержимого и проб вариантов для поиска причины, работать не перестал. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 12 января, 2008 Опубликовано 12 января, 2008 · Жалоба Я поправил Makefile, правда не совсем так, как вы указали:Это не принципиально. После этого линкер начал требовать прописывания секции для каждой функции и глобальной переменной.Я тоже не большой специалист, но у меня получилось так: .text : { ....... *(.text) /* code */ *(.text.*) /* code */ ............. } > ROM Аналогично и для данных. Приведенные выше ключи компилятора заставляют выделять отдельную секцию для каждой функции и для каждой переменной (ибо линкер по --gc-sections умеет выкидывать только секции целиком). Все вышеизложенное наталкивает на мысль, что решение должно быть гораздо проще.Использование шаблонного символа '*' в скрипте.Затем я подключал эти хидеры в соседних строках одного си-файла и вызывал по одной функции из каждого файла тоже в соседних строках, при этом из файла libAT91SAM7S256.h компилировалась только вызываемая функция, а из icpsr.h все по отдельности + еще раз вызываемая на этот раз в нужном месте.Если до понедельника никто не ответит - покомпилирую приложенный вами выше проект, помедитирую. Пока не готов дать ответ. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 12 января, 2008 Опубликовано 12 января, 2008 · Жалоба 1) "правильно" компилятся только __inline функции, остальные же по-прежнему компилятся всегда и при удалении их вызова сами они никуда из итогового кода не исчезают. А с какого бодуна они должны исчезать :)? Объектные файлы линкуются целиком. Некоторые форматы объектников и соответственно поддерживающие их линкеры позволяют выборочную линковку, но это вымирающая (ARM IAR до перехода на elf умел ) редкость. Читайте про библиотеки, делайте их и пользуйтесь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
injen-d 0 12 января, 2008 Опубликовано 12 января, 2008 · Жалоба А с какого бодуна они должны исчезать :)? Объектные файлы линкуются целиком. Некоторые форматы объектников и соответственно поддерживающие их линкеры позволяют выборочную линковку, но это вымирающая (ARM IAR до перехода на elf умел ) редкость. Читайте про библиотеки, делайте их и пользуйтесь. Создать библиотеку? Это интересно :rolleyes: Вы, случайно ссылочкой не располагаете, где почитать про создание библиотек для ARM-GCC ? Буду очень признателен. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 12 января, 2008 Опубликовано 12 января, 2008 · Жалоба Вы, случайно ссылочкой не располагаете, где почитать про создание библиотек для ARM-GCC ? Дык, библиотекарь неотъемлимая часть набора инструментов. В GNU он, правда странновато называется ar (архивный библиотекарь). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
injen-d 0 12 января, 2008 Опубликовано 12 января, 2008 · Жалоба Дык, библиотекарь неотъемлимая часть набора инструментов. В GNU он, правда странновато называется ar (архивный библиотекарь). Спасибо zltigo, нагуглил простое описание для GCC. Щас как раз пытаюсь сделать статическую библиотеку из icpsr.h, напишу что получится. ;) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 12 января, 2008 Опубликовано 12 января, 2008 · Жалоба Щас как раз пытаюсь сделать статическую библиотеку из icpsr.h, напишу что получится. ;)Все же мне кажется, вы несколько не в ту сторону двигаетесь. Вы ведь не будете каждый файл компилировать в библиотеку. 1) нужно включить оптимизацию. В противном случае функции не будут инлайнится и если вы включите один заголовочник в несколько .c-файлов - получите несколько копий одной и той же функции в объектниках, с руганью на стадии линковки - линкер не знает, какую из копий использовать (он ведь не знает, что это копии) 2) все нестатические и невстраиваемые (не inline) функции из .c-файлов попадают в объектный файл при компиляции - ведь только на этапе линковки можно определить, какая функция потребуется, а какая нет. 3) линкер не знает, где начинается одна функция, а где заканчивается предыдущая, поэтому он может выкинуть только всю секцию целиком. Для этого компилятор помещает каждую функцию в отдельную секцию (-ffunction-sections). Тогда, если нет обращений к функции нет и обращений к этой секции и линкер может такую секцию выкинуть. Выкидывая секцию, линкер выкидывает функцию целиком, причем только одну. Поэтому, даже если будете пользоваться библиотеками, вам придется каждую функцию компилировать в библиотеку из отдельного исходного файла - иначе получите то же самое, что и сейчас. 4)-ffunction-sections прекрасно работает со скриптами, идущими в комплекте WinAVR. Пробовал и сборку Yagarto, тоже работает. Указание в скрипте линкера входных секций как *(.text.*) не помогло? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
injen-d 0 13 января, 2008 Опубликовано 13 января, 2008 · Жалоба Указание в скрипте линкера входных секций как *(.text.*) не помогло? Еще как помогло! :) Правда файл crt.s перестал линковаться (вместо ассемблерных команд непонятные значения, занимающие тот же объем в итоговом файле). Но после вставки скрипта из примеров для WinARM и небольших в нем исправлений, все заработало. В main.dmp вижу: 0010047c <EnableFIQ>: 10047c: e10f0000 mrs r0, CPSR 100480: e3c03040 bic r3, r0, #64; 0x40 100484: e129f003 msr CPSR_fc, r3 100488: e12fff1e bx lr Disassembly of section .text.EnableIRQ: 0010048c <EnableIRQ>: 10048c: e10f0000 mrs r0, CPSR 100490: e3c03080 bic r3, r0, #128; 0x80 100494: e129f003 msr CPSR_fc, r3 100498: e12fff1e bx lr Disassembly of section .text.RestoreIRQ: 0010049c <RestoreIRQ>: 10049c: e10f2000 mrs r2, CPSR 1004a0: e2000080 and r0, r0, #128; 0x80 1004a4: e3c23080 bic r3, r2, #128; 0x80 1004a8: e1833000 orr r3, r3, r0 1004ac: e129f003 msr CPSR_fc, r3 1004b0: e1a00002 mov r0, r2 1004b4: e12fff1e bx lr таким образом каждая функция расположена в своей секции, уровни оптимизации пробовал разные, в данном случае -Оs. Все функции на месте, хотя я вызываю только EnableIRQ() один раз в main.c. Пробовал комментировать вызовы функций, находящихся в USART_setup.c в частности USART0_setup(); Картина та же - исчезает только команда вызова. Может еще каких-нибудь флажков в мэйкфайле не хватает? :laughing: Поэтому, даже если будете пользоваться библиотеками, вам придется каждую функцию компилировать в библиотеку из отдельного исходного файла - иначе получите то же самое, что и сейчас. Вы, Сергей, абсолютно правы - уже убедился, так и есть: при вызове одной подключаются все. Слишком накладно получается каждую функцию из отдельного файла. :unsure: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 13 января, 2008 Опубликовано 13 января, 2008 · Жалоба Слишком накладно получается каждую функцию из отдельного файла. :unsure: Но, придется именно так, если пытаетесь делать абстрактную библиотеку. Практически для конкретной работы достаточно группы функций разбить по файлам и дополнительно добавить ключи условной трансляции для нескольких вариантов сборки. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
injen-d 0 13 января, 2008 Опубликовано 13 января, 2008 · Жалоба группы функций разбить по файлам Значит все таки можно для создания библиотеки несколько независимых функций в один файл? Или вы имели ввиду /основная функция + вызываемые из нее функции/ в одном файле? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 13 января, 2008 Опубликовано 13 января, 2008 · Жалоба Картина та же - исчезает только команда вызова. Может еще каких-нибудь флажков в мэйкфайле не хватает? :laughing: До меня только сегодня дошло - вы опцию, которая должны передаваться линкеру, -Wl,--gc-sections (это одна опция), поместили в CFLAGS и передаете компилятору. А ее надо поместить в LDFLAGS, ибо при линковке вы в качестве флагов используете именно ее (точнее, у вас она названа LFLAGS, но в документации на GNU make ее рекомендуется называть LDFLAGS):main.out: $(OBJECTS) test.cmd @ echo "..linking" $(LD) $(LFLAGS) -o main.out $(OBJECTS) libc.a libm.a libgcc.a чего-то я стормозил вчера в 21.35. У вас линкер не получает --gc-sections и поэтому не выкидывает неиспользуемые секции. Значит все таки можно для создания библиотеки несколько независимых функций в один файл?Можно. Указав при компиляции --ffunction-sections. Круг замкнулся :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
zltigo 0 13 января, 2008 Опубликовано 13 января, 2008 · Жалоба Значит все таки можно для создания библиотеки несколько независимых функций в один файл? Без труда - нет. Или вы имели ввиду /основная функция + вызываемые из нее функции/ в одном файле? Ну что-то приблизительно, как вариант. Я имел ввиду, что совсем-уж независимые функции бывают редко и можно объединять их в группы, даже если они друг из друга не вызываются. Ну а то, что много файлов, то в общем-то сильных неудобств при нормальном редакторе с проектом, тэгами.... это вызывать не должно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
injen-d 0 13 января, 2008 Опубликовано 13 января, 2008 · Жалоба До меня только сегодня дошло - вы опцию, которая должны передаваться линкеру, -Wl,--gc-sections (это одна опция), поместили в CFLAGS и передаете компилятору. А ее надо поместить в LDFLAGS, ибо при линковке вы в качестве флагов используете именно ее (точнее, у вас она названа LFLAGS, но в документации на GNU make ее рекомендуется называть LDFLAGS) Вобще-то, насколько я понял из документации (в школе учил французский ), -Wl, - означает "передать следующий флаг линкеру". Однако попробовал переименовать на LDFLAGS и т. д. В итоге: LDFLAGS = --gc-sections -Map main.map -T test.cmd после компиляции ошибок нет, но: TOTAL SIZE: arm-elf-size -t main.out text data bss dec hex filename 0 0 0 0 0 main.out 0 0 0 0 0 (TOTALS) Выходные файлы пусты, а объектные созданы правильно. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться