Перейти к содержанию
    

Размер исполняемого файла не влез в отведённую память, что можно уменьшить?

Здравствуйте. Не уверен, что выбрал правильный раздел. Если что - поправьте пожалуйста. В этом разделе в основном обсуждаются аппаратные проблемы использования встраиваемых систем, чистых программистов там мало похоже, судя по отсутствию ответов на мои вопросы начинающего. А проблема у меня чисто програмерская, нужно глубоко понимать, как что компилится и линкуется.

Я новичок в программировании под Microblaze (ARM-ядро, если не путаю), работаю в SDK от Xilinx, это допиленный Eclipse, как я понимаю. Пользоваться толком не умею, поэтому, думаю, и проблемы.

Проблема такая. На этапе компиляции всего проекта вылазят такие ошибки:

 

fft_sp605.elf section `.text' will not fit in region `microblaze_0_i_bram_ctrl_microblaze_0_d_bram_ctrl'    fft_sp605             C/C++ Problem

region `microblaze_0_i_bram_ctrl_microblaze_0_d_bram_ctrl' overflowed by 63912 bytes    fft_sp605             C/C++ Problem

 

Всего мне отведено 8кБ памяти в ПЛИС. Моя программа небольшая реально, на пару страниц кода. Библиотеки почти не используются, ёмкие функции не вызываются. Почти уверен, что должна влезть в отведённую память. Ну хотя бы даже не влезть, но не в 8 же раз ей не хватает...

 

Начал лазить по файлам, смотреть, кто чего сколько потребил. Вот тут накопал:

 

файл main.o:

architecture: MicroBlaze, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
 0 .text         00000000  00000000  00000000  00000034  2**0
                 CONTENTS, ALLOC, LOAD, READONLY, CODE
 1 .data         00000000  00000000  00000000  00000034  2**0
                 CONTENTS, ALLOC, LOAD, DATA
 2 .bss          00000000  00000000  00000000  00000034  2**0
                 ALLOC
 3 .rodata       00000298  00000000  00000000  00000034  2**2
                 CONTENTS, ALLOC, LOAD, READONLY, DATA
 4 .text.main    00000f5c  00000000  00000000  000002cc  2**2
                 CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
 5 .debug_frame  00000040  00000000  00000000  00001228  2**2
                 CONTENTS, RELOC, READONLY, DEBUGGING
 6 .debug_info   0000054d  00000000  00000000  00001268  2**0
                 CONTENTS, RELOC, READONLY, DEBUGGING
 7 .debug_abbrev 00000130  00000000  00000000  000017b5  2**0
                 CONTENTS, READONLY, DEBUGGING
 8 .debug_loc    0000002e  00000000  00000000  000018e5  2**0
                 CONTENTS, RELOC, READONLY, DEBUGGING
 9 .debug_aranges 00000020  00000000  00000000  00001913  2**0
                 CONTENTS, RELOC, READONLY, DEBUGGING
10 .debug_ranges 00000010  00000000  00000000  00001933  2**0
                 CONTENTS, RELOC, READONLY, DEBUGGING
11 .debug_line   000006c4  00000000  00000000  00001943  2**0
                 CONTENTS, RELOC, READONLY, DEBUGGING
12 .debug_macinfo 0000eb39  00000000  00000000  00002007  2**0
                 CONTENTS, READONLY, DEBUGGING
13 .debug_str    00000428  00000000  00000000  00010b40  2**0

 

Файл platform.o

architecture: MicroBlaze, flags 0x00000011:
HAS_RELOC, HAS_SYMS
start address 0x00000000

Sections:
Idx Name          Size      VMA       LMA       File off  Algn
 0 .text         00000000  00000000  00000000  00000034  2**0
                 CONTENTS, ALLOC, LOAD, READONLY, CODE
 1 .data         00000000  00000000  00000000  00000034  2**0
                 CONTENTS, ALLOC, LOAD, DATA
 2 .bss          00000000  00000000  00000000  00000034  2**0
                 ALLOC
 3 .text.enable_caches 00000040  00000000  00000000  00000034  2**2
                 CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
 4 .text.disable_caches 00000040  00000000  00000000  00000074  2**2
                 CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
 5 .text.init_uart 00000020  00000000  00000000  000000b4  2**2
                 CONTENTS, ALLOC, LOAD, READONLY, CODE
 6 .text.init_platform 00000040  00000000  00000000  000000d4  2**2
                 CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
 7 .text.cleanup_platform 00000034  00000000  00000000  00000114  2**2
                 CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
 8 .debug_frame  0000009c  00000000  00000000  00000148  2**2
                 CONTENTS, RELOC, READONLY, DEBUGGING
 9 .debug_info   000000df  00000000  00000000  000001e4  2**0
                 CONTENTS, RELOC, READONLY, DEBUGGING
10 .debug_abbrev 00000041  00000000  00000000  000002c3  2**0
                 CONTENTS, READONLY, DEBUGGING
11 .debug_loc    000000dc  00000000  00000000  00000304  2**0
                 CONTENTS, RELOC, READONLY, DEBUGGING
12 .debug_aranges 00000040  00000000  00000000  000003e0  2**0
                 CONTENTS, RELOC, READONLY, DEBUGGING
13 .debug_ranges 00000030  00000000  00000000  00000420  2**0
                 CONTENTS, RELOC, READONLY, DEBUGGING
14 .debug_line   000000f3  00000000  00000000  00000450  2**0
                 CONTENTS, RELOC, READONLY, DEBUGGING
15 .debug_macinfo 000100c2  00000000  00000000  00000543  2**0
                 CONTENTS, READONLY, DEBUGGING
16 .debug_str    00000169  00000000  00000000  00010605  2**0
                 CONTENTS, READONLY, DEBUGGING

 

Тут видно, что секции debug слишком жирные.

 

Я честно говоря вообще толком не знаю, где что правильно посмотреть и как настроить какие размеры сегментов. Даже не знаю, как посмотреть, сколько моя программа занимает отдельно, а сколько переменные отдельно и т.п.

 

Логичным решением вроде является не использовать отладку, раз дебуг секция не лезет. Но, насколько я знаю, многие разработчики прекрасно отлаживаются с таким же объёмом памяти, так что проблема видимо, что я где-то что-то не так настроил.

 

Если нужны ещё какие-то файлы, что-то где-то глянуть - спросите, я посмотрю, просто сразу не знаю, что вам показать, чтобы было понятно, как мне можно помочь.

 

Заранее спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

вы небось где-то вызывали функцию печати на UART. Она сразу цепляет кучу sprintf и прочей байды, и сразу же падает std библиотека...

 

есть функции xil_printf - она поменьше. И чтобы все совсем стало хорошо, надо переписать и сделать свою функцию отладочного вывода информации....

 

 

разрастание секций простенькой программы - это 100% подтягивания стандартных библиотек, иногда вызов одной функции затягивает столько библиотек что пипец....

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Добавление:

методом дихотомии обнаружил, что проблему составляло одно-единственное деление в дабле, именно оно отъедало кучу памяти. Т.к. видимо подключалась вся библиотека для работы с флоатом.

Ещё printf очень прожорливый, вместо него надо xil_printf использовать, тогда потребление памяти в пределах разумного.

 

Теперь у меня превышение есть, ошибка остаётся. Но уже не в 8 раз, а на пару килобайтов. Так что вопросы в принципе в силе. Как куда смотреть, что крутить. Т.е. какие приёмы программисты используют, чтобы понять, что не влазит, чтобы оценить, что занимает слишком много, что не должно столько занимать и т.д...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Добавление:

методом дихотомии обнаружил, что проблему составляло одно-единственное деление в дабле, именно оно отъедало кучу памяти. Т.к. видимо подключалась вся библиотека для работы с флоатом.

Ещё printf очень прожорливый, вместо него надо xil_printf использовать, тогда потребление памяти в пределах разумного.

 

Теперь у меня превышение есть, ошибка остаётся. Но уже не в 8 раз, а на пару килобайтов. Так что вопросы в принципе в силе. Как куда смотреть, что крутить. Т.е. какие приёмы программисты используют, чтобы понять, что не влазит, чтобы оценить, что занимает слишком много, что не должно столько занимать и т.д...

1) Это не АРМ -Это Микроблаз

2) Для линковщика - потом смотреть содержимое map.lst

-Map $(OBJ_DIR)/map.lst --cref

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

наверное вы еще флот модуль не добавили в микроблайз и у вас вся математика на библиотеке...

 

я обычно делал систему микроблайз с 64 К памяти, если надо ужаться и брамы куда-то нужны (хотя по мне можно кеши срезать, если программа работает из брама, то нафига кеш), то я не использовал библиотек вообще и даже xil_print переписал на свою. Выкинул все драйвера, с их чудным и Чудным инитом, и переписал ручками, половина ну во всяком случае для простой периферии типа таймера, портов и так далее...

 

ну и конечно после того как все угук, смотрите карту памяти, и понимаете какой сегмент у вас сколько отожрал, там даже по функциям понятно какая сколько съела. Ну не забываем про всякие оптимизации и отрезания отладочных кусков вообще.

 

Хорошим тоном сделать

 

#ifdef DEBUG

#define my_debug_print (smb...) xil_printf (smb...)

#elseif

#define my_debug_print (smb...)

#endif

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

вы небось где-то вызывали функцию печати на UART. Она сразу цепляет кучу sprintf и прочей байды, и сразу же падает std библиотека...

 

есть функции xil_printf - она поменьше. И чтобы все совсем стало хорошо, надо переписать и сделать свою функцию отладочного вывода информации....

 

 

разрастание секций простенькой программы - это 100% подтягивания стандартных библиотек, иногда вызов одной функции затягивает столько библиотек что пипец....

Спасибо, я не сразу увидел Ваше сообщение, сначала своё успел написать. Но Вы вобщем-то всё наперёд предсказали и угадали ))

 

Накопал тут ещё тем касаемо моего вопроса

http://electronix.ru/forum/index.php?showtopic=117966

http://electronix.ru/forum/index.php?showt...p;#entry1244345

Многое прояснилось. В частности, хорошая подсказка использовать print() - самое низкое потребление памяти. К стати, а эти функции не инлайновые? Ну там print(), printf(), xil_printf()... Мне показалось, что при каждом новом вызове код разрастается не на размер команды вызова подпрограммы ))) Может, ошибаюсь.

 

1) Это не АРМ -Это Микроблаз

2) Для линковщика - потом смотреть содержимое map.lst

-Map $(OBJ_DIR)/map.lst --cref

1. Хорошо, ошибался.

2. А куда это вписывать? В XMD Console? Попробовал, вот что выдало:

can't read "(OBJ_DIR)": no such variable

В теме по последней ссылке предлагают такой ключик: -Wl.-Map=имя_файла

Я тоже не понял, куда его вписывать. Попробовал сюда:

 

post-13271-1418892419_thumb.png

 

Не помогло, после сборки не нашёл такого файла.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо, я не сразу увидел Ваше сообщение, сначала своё успел написать. Но Вы вобщем-то всё наперёд предсказали и угадали ))

 

Накопал тут ещё тем касаемо моего вопроса

http://electronix.ru/forum/index.php?showtopic=117966

http://electronix.ru/forum/index.php?showt...p;#entry1244345

Многое прояснилось. В частности, хорошая подсказка использовать print() - самое низкое потребление памяти. К стати, а эти функции не инлайновые? Ну там print(), printf(), xil_printf()... Мне показалось, что при каждом новом вызове код разрастается не на размер команды вызова подпрограммы ))) Может, ошибаюсь.

 

 

1. Хорошо, ошибался.

2. А куда это вписывать? В XMD Console? Попробовал, вот что выдало:

can't read "(OBJ_DIR)": no such variable

В теме по последней ссылке предлагают такой ключик: -Wl.-Map=имя_файла

Я тоже не понял, куда его вписывать. Попробовал сюда:

 

post-13271-1418892419_thumb.png

 

Не помогло, после сборки не нашёл такого файла.

Это опции линковщика -Map и --cref (читайте описание сих опций за подробност...)

Я пользую make по сему куда "сувать" в ide я не знаю.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

наверное вы еще флот модуль не добавили в микроблайз и у вас вся математика на библиотеке...
Golikov A., Вы опять всё полностью угадали )) У меня в железе только перемножитель. Но я подумал, что оттого, что я разделю один раз одно число на другое, много съесться не должно, т.к. чисто физически в делении нет ничего сложного, что бы занимало килобайты кода )) Но я ошибался ))) Ладно, сделаю самописное деление для такого случая.

 

 

хотя по мне можно кеши срезать, если программа работает из брама, то нафига кеш)
Как это сделать? Я бы с радостью )

 

 

Выкинул все драйвера, с их чудным и Чудным инитом, и переписал ручками, половина ну во всяком случае для простой периферии типа таймера, портов и так далее...
У меня та же проблема. Использую axi_timer, дак его библиотека xtmrctr.h съела 1,5 кБ кода, хотя там руками можно пару регистров прогрузить, чтобы всё заработало, и это займёт десятки байт максимум ))) Буду писать свою библиотечку для запуска и считывания таймера, зачем Xilinx стреляет из пушки по воробьям такими монструозными дровами для таких простых устройств - не понятно...

 

ну и конечно после того как все угук, смотрите карту памяти, и понимаете какой сегмент у вас сколько отожрал, там даже по функциям понятно какая сколько съела. Ну не забываем про всякие оптимизации и отрезания отладочных кусков вообще.
Так ещё и не понял, как это сделать...

 

 

Хорошим тоном сделать
Спасибо, нужная подсказка для новичка.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

и даже xil_print переписал на свою
К стати, если не связаны запретом на распространение трудов своего плода, не поделитесь исходником? )

А то чото жалко тратить 3кБ на xil_printf, а иногда хочется выводить не только строки, но и числа...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

хм... не поделюсь, не потому что жалко, а потому что проект уже погиб где-то, еще вечером погляжу но шансов найти мало.

как я говорил наш тот проект загнулся и мы перешли на внешний проц, а начала в контроле версий не сохранилось, потому что фактически начали новый проект.

 

но суть проста, все sprintf и прочее они использую кучу, динамически выделяют память, и какое-то расписание делают чтобы это все отправлялось - в общем мрак.

 

А тем временем UART - это фифо в которое надо попихать данные и они поедут на выход (вот я сейчас задумался а не рукописный ли у меня там был уарт, но вроде у корки тоже есть FIFO...). Ну так вот я и сделал простую функцию с блокировкой отправки, поскольку у меня это было только для отладки. На входе принимала строку и размер, и просто тупо в цикле все пихала в UART. Даже не проверяла есть ли место в FIFO, перепихав выходила из функции... Разбора строки и прочего не было, была еще маленькая функция перевода числа в HEX формат, чтобы константы передавать для отладки. И все.

Крайне аскетично....

 

 

Если у вас в проце есть езернет или модуль контроля прерываний поглядите как сделаны их инициализация и обработка, там пипец много текста который тоже имеет смысл переписать....

 

 

Кеши - это вы в настройках, когда создаете микроблайз, сам проц, то выбираете. Там как-то можно свойства проца вызвать, то ли правая кнопка, то ли двойной клик. И там есть ползунки размер кеша данных и размер кеша команд. Когда их тянете вперед он пишет что проц становиться быстрее, но на эти кеши жруться брамы. Это нужно при работе проги из ДДР, там без кешей ваще как будто проц стоит как все медленно. Но при работе из внутренней брамки, кеш инструкций 100% не нужен, а если вы в ДДР никакие константы-переменные проца не кладете, то и кеш данных так же не нужен. Проц и работает стабильнее и кучу брамов отдает...

 

 

карту памяти - это в свойствах проекта, уже в SDK, можно поставить галочку генерить карту памяти, файл с map (кажется) расширением, где точно это не подскажу, если не найдете пишите в личку, вечером погляжу. Так вот после того как галка стоит, после перебилда проекта у вас будет файл с тем где лежит каждая функция, сколько она ест памяти и так далее...

 

 

Библиотеки микроблайза сделаны либо как демонстрационно-учебные, либо уже берешь если сил нет разбираться как в случае с езернетом, зато они на все случаи жизни их меняющегося кода%). Если кристалл большой и практически весь функционал вынесен в ПЛИС часть, а проц только арбитр и не жмет производительность, то спокойно ляпаешь на библиотеках и не думаешь, удобно тем что можно будет перенести куда хочешь, даже проц пересоздать, оно должно само адреса найти. Другое дело что не находит, и работает медленно, потому я конечно много переписывал... И в целом оглядываясь назад я даже немного рад что теперь у меня внешний ARM%)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Спасибо. Где какие галочки поставить, чтобы был *.map, я не нашёл, но решил таким способом: http://electronix.ru/forum/index.php?s=&am...t&p=1300078

 

В принципе, если Вас не затруднит, киньте свой способ, чтобы так сказать народ знал.

 

По поводу функции печати: меня print() устраивает по размеру. Но она не умеет числа печатать (мне нужны десятичные правда). В принципе мне достаточно найти функцию типа dec2str(), чтобы была нересурсоёмкая. Может кто подскажет такую. Тогда я подготовлю из числа строку, а её пошлю через print().

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Чет я капитально все забыл что с микроблайзом связано, хотя это скорее к gcc

Галочки и правда нет,

Projecp propirties -> C/C++ Buil -> Settings - MicroBlaze gcc Linker

и там в секции

Miscellaneous -> Linker Flags, забил -Wl,-Map -Wl,"..путь..mem.map"

 

то есть фактически как вы сделал, только в другом месте флажок ставил... реальной галки нет

 

по поводу функции у меня была DecToHex

которая 32 битное число обрабатывала по 4 младших бита, кейзом выбирала символ от 0 до F, и сдвигало на 4 бита. Самый малая трата ресурсов, потому что иначе приходиться делить, целочисленно, но делить.

 

sym = Data % 10;

Data -= sym;

Data /= 10;

и кейзом выбираете символ от 0 до 9.

 

и таких итераций либо пока Data в 0 не уйдет либо фиксированное число. Но это по ресурсам сильно больше.

 

Опять же через хекс вы передаете бинарь. То есть фактически можете передать даже флоат и дабл. И можно сделать свой ком порт терминальчик который будет раскодировать числа. То есть в дебуг вывод добавляете что-то типа

#Df - дальше флотовское число

#Dd - дальше добловское

и прикладываете хекс. А ваш терминальчик парсит либо входной лог, либо сохранненый из обычного терминала и значения вида #Di0011, заменяет на 17 сразу сам. Но я обошелся без автопарсера, в отладке обычно редко надо прям следить за значениями, важно их сочетание и все... ИМХО

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...