RCray 0 26 марта, 2012 Опубликовано 26 марта, 2012 · Жалоба Коллеги, Часть глобальных данных хочу инициализировать ещё на этапе объявления. Ну там int32_t a[5] = {1, 2, 3, 4, 5}; А всю остальную часть глобальных данных хочу обнулить. Моя проблема в том, что секция с данными {1, 2, 3, 4, 5} и a[5] оказываются отдельно в разных секциях .rodata и .data соответсвенно. Существует ли какой-то способ сэкономить память и сразу их объеденить ещё на этапе линкования? Спасибо. Сейчас использую такое описание в *.ld файле для линкера: MEMORY { ... ... IntCodeRAM (rx) : ORIGIN = 0x00080000, LENGTH = 128k IntDataRAM (rw) : ORIGIN = 0x20000000, LENGTH = 112k ... ... } PROVIDE (initStart = _etext); /*******************************************/ /* .rodata section for read-only data (constants) */ .rodata . : { *(.rodata) *(.rodata.*) . = ALIGN(4); _etext = .; PROVIDE (etext = .); } >IntCodeRAM /*******************************************/ /* .data section for initialized data */ .data : AT (_etext) { /* used for initialized data */ dataStart = .; PROVIDE (dataStart = .); *(.data) *(.data.*) *(.gnu.linkonce.d*) SORT(CONSTRUCTORS) dataEnd = .; PROVIDE (dataEnd = .); } >IntDataRAM . = ALIGN(4); _edata = .; PROVIDE (edata = .); /*******************************************/ /* .bss section for uninitialized data */ .bss : { bssStart = .; bssStart = .; *(.bss) *(.gnu.linkonce.b*) . = ALIGN(4); bssEnd = .; } >IntDataRAM А потом для обнуления или инициализации глобальных данных константами использую в исходниках следующий код /* initialize .data segment */ src = &initStart; for(dst = &dataStart; dst < &dataEnd; ) { *dst++ = *src++; } /* Zero fill the .bss segment. */ for(dst = &bssStart; dst < &bssEnd; ) { *dst++ = 0; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 26 марта, 2012 Опубликовано 26 марта, 2012 · Жалоба Как-то у вас очень сложно. В .rodata идут константы, а ваши a[] и {1,2,3,4,5} должны попасть в .data. А начальные значения .data {1,2,3,4,5} линкер поместил во флеш надо использовать конструкцию > IntDataRAM AT > IntCodeRAM. И забудьте конструкцию .data : AT (_etext) как страшный сон и вредные советы. Вот такой кусочек прекрасно работает: MEMORY { ROM (rx) : ORIGIN = 0x08000000, LENGTH = 64K RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K } SECTIONS { ....... .data : { . = ALIGN(4); _sdata = .; /* start of .data label */ *(.data) *(.data.*) . = ALIGN(4); _edata = .; /* end of .data label */ } > RAM AT > ROM _sidata = LOADADDR(.data); /* start of initialized data label */ /* .bss section - uninitialized data */ .bss (NOLOAD): { . = ALIGN(4); _sbss = .; /* start of .bss label (for startup) */ *(.bss) *(.bss.*) *(COMMON) . = ALIGN(4); _ebss = .; /* end of .bss label (for startup) */ _end = .; /* end of used ram (start of free memory, for malloc) */ __end = .; /* the same */ } > RAM extern uint32_t _sidata[]; extern uint32_t _sdata[]; extern uint32_t _edata[]; extern uint32_t _sbss[]; extern uint32_t _ebss[]; static inline __attribute__((always_inline)) void __Init_Data(void) { uint32_t *pSrc = _sidata; for(uint32_t * pDst = _sdata; pDst < _edata; ) *pDst++ = *pSrc++; for(uint32_t * pDst = _sbss; pDst < _ebss; ) *pDst++ = 0; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
RCray 0 26 марта, 2012 Опубликовано 26 марта, 2012 · Жалоба Спасибо за совет. Так у вас тоже под константы место выделяется отдельно, а для данных которыми инициализируются этими константами отдельно. И если и вы, и я в итоге используем в любом случае строчки вида: for(uint32_t * pDst = _sdata; pDst < _edata; ) *pDst++ = *pSrc++; То почему бы не иметь опцию, которая бы сразу совмещала данные и их заполнение по одному адресу? Или такой опции не существует? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 26 марта, 2012 Опубликовано 26 марта, 2012 · Жалоба Так у вас тоже под константы место выделяется отдельно, а для данных которыми инициализируются этими константами отдельно.Да, все верно. А у вас что, и код и данные грузятся перед исполнением в ОЗУ какой-то сторонней запускалкой? Тогда просто убрать AT > ROM и данные будут расположены сразу по адресам .data, а копирование будет не нужно. Этот же скрипт полагает, что программа находится во флеше и исполняется после включения питания из флеша. А данные {1,2,3,4,5} в ОЗУ после включения питания должны откуда-то как-то появится, они ведь теряются после выключения питания, вот они и копируются этим циклом, а копироваться они должны из флеша, куда начальные значения и помещаются конструкцией AT > ROM. А если вы объявите данные как int32_t const a[5] = {1, 2, 3, 4, 5}; то они попадут в секцию .rodata и вот ее можно смело класть в выходную секцию .text, ибо компилятор будет следить за тем, чтобы вы использовали эти данные только для чтения и поэтому они могут лежать во флеше. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться