Добрый день.
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 = . ;
}
Пока хотел спросить и формулировал как спросить понял как найти и нашол в гугле и разобрался, понадобился день.
Решил уж опубликовать, раз текст почти подготовил
Интересно есть ли у данного способа недостатки?
Как проще решить данную проблему?