реклама на сайте
подробности

 
 
> GCC для ARM: Размещение неиспользуемой константы в прошивке., Для случая когда нужна оптимизация.
Porty
сообщение Feb 21 2012, 13:58
Сообщение #1


Местный
***

Группа: Свой
Сообщений: 246
Регистрация: 28-05-08
Из: г. Ижевск
Пользователь №: 37 893



Добрый день.
GCC для ARM: Размещение неиспользуемой константы в прошивке, для случая когда нужна оптимизация.

Условия:
Часто бывает необходимо какую либо служебную информацию включить внутрь прошивки такую какая будет использоваться например нестандартным прошивальшиком, или самим пользователем или ещё как, а не самой программой, т.е. внутри программы на этот блок данных ссылки нет и поэтому компилятор и компоновщик GCC их выкидывают если оптимизация включена например -О3 и включено убирание неиспользуемых данных и кода --gc-sections. Т.е. после сборки такая константа удаляются и их нет в файле прошивки. И желательно, чтоб эта константа включалась в прошивку, всего лишь включением в список компилированных си файлов дополнительного си файла. Т.е. чтобы ничего другого не писать и не дописывать уже имеющиеся исходники

Особенности - локальное отключение оптимизации не помогает, куча разных хаков описанных на stackoverfull тоже. volatile тоже не помогает. Всякие разные __attribute__ и их ухищрения тоже. Все способы не работают на АРМ, на других платформах многие работают. А так же нужна оптимизация и сборка мусора и неиспользуемых блоков кода и данных (иначе бинарник не уместится в памяти).

Решение
Почему удаляется неиспользуемая константа - всему виной --gc-sections - это ключ для компилятора который сборщику LD говорит чтоб не включал в сборку секции на которые нет ссылок из других секций. Под секцией подразумевается либо функции либо данные. Сборщик LD работает через имена секций и скрипт сборки с расширением *.ld. Через данный скрипт можно напрямую задать то как собирать и что сохранить, директива KEEP от оптимизации, т.е. те секции которые указаны в KEEP будут принудительно включены в сборку. Но данные компилятор добавляет все в одну секцию, для констант она именуется как .rodata. Для того чтоб каждая переменная/константа и тд клалась в свою секцию необходимо компилятору добавить ключ -fdata-sections
И далее добавить в *.ld файл в раздел секций инструкцию KEEP(*(.rd.const_name)) в блок .text :

Т.е. например имея необходимость принудительно невзирая на оптимизацию разместить константу const_name в флеш памяти
необходимо сделать следующее:
1. Добавить ключ -fdata-sections на стадию компиляции всего проекта или отдельному си файлу с описанием данной константы.
2. Внести в *.ld файл в раздел секций начинающийся с SECTIONS { в подраздел начинающийся с .text : { . Запись вида: KEEP(*(.rd.const_name)) в конец подсекции .text (ВАЖНО, порядок строк в данном файле задаёт порядок сборки бинарника)
3. Сделать ребилд всего проекта. Готово.

Пример:
CODE
OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
SEARCH_DIR(.)
INCLUDE "memory.ld"

/* Section Definitions */
SECTIONS
{
.text :
{
KEEP(*(.isr_vector .isr_vector.*))
*(.text .text.* .gnu.linkonce.t.*)
*(.glue_7t) *(.glue_7)
*(.rodata .rodata* .gnu.linkonce.r.*)
KEEP(*(.rodata.const_name)) /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*/
} > rom

.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > rom

.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom

. = 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.*)
} > ram

. = ALIGN(4);
_end = . ;
}


Пока хотел спросить и формулировал как спросить понял как найти и нашол в гугле и разобрался, понадобился день. laughing.gif
Решил уж опубликовать, раз текст почти подготовил biggrin.gif

Интересно есть ли у данного способа недостатки?
Как проще решить данную проблему?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
KnightIgor
сообщение Feb 21 2012, 14:07
Сообщение #2


Знающий
****

Группа: Участник
Сообщений: 643
Регистрация: 29-05-09
Из: Германия
Пользователь №: 49 725



const mytype name __attribute__((section("sectionname"), used)) = initial_value;

Сообщение отредактировал KnightIgor - Feb 21 2012, 14:08
Go to the top of the page
 
+Quote Post
Porty
сообщение Feb 21 2012, 14:40
Сообщение #3


Местный
***

Группа: Свой
Сообщений: 246
Регистрация: 28-05-08
Из: г. Ижевск
Пользователь №: 37 893



Цитата(KnightIgor @ Feb 21 2012, 18:07) *
const mytype name __attribute__((section("sectionname"), used)) = initial_value;

used не работает

что то меня не покидает ощущение что опять где то фразу в офф. документации пропустил и всё можно было бы сделать одной такой строкой как выше ... поэтому и спрашиваю, нормальное ли мое решение в начале темы и кто как делает?
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 24th July 2025 - 15:15
Рейтинг@Mail.ru


Страница сгенерированна за 0.01378 секунд с 7
ELECTRONIX ©2004-2016