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

 
 
 
Reply to this topicStart new topic
> GNU linker, .rodata and .data sections
RCray
сообщение Mar 26 2012, 16:20
Сообщение #1


Частый гость
**

Группа: Свой
Сообщений: 170
Регистрация: 14-09-05
Из: Suwon
Пользователь №: 8 548



Коллеги,

Часть глобальных данных хочу инициализировать ещё на этапе объявления. Ну там 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;
    }
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 26 2012, 18:28
Сообщение #2


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Как-то у вас очень сложно. В .rodata идут константы, а ваши a[] и {1,2,3,4,5} должны попасть в .data. А начальные значения .data {1,2,3,4,5} линкер поместил во флеш надо использовать конструкцию > IntDataRAM AT > IntCodeRAM. И забудьте конструкцию .data : AT (_etext) как страшный сон и вредные советы.
Вот такой кусочек прекрасно работает:
CODE
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;
}


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
RCray
сообщение Mar 26 2012, 18:44
Сообщение #3


Частый гость
**

Группа: Свой
Сообщений: 170
Регистрация: 14-09-05
Из: Suwon
Пользователь №: 8 548



Спасибо за совет.

Так у вас тоже под константы место выделяется отдельно, а для данных которыми инициализируются этими константами отдельно. И если и вы, и я в итоге используем в любом случае строчки вида:


for(uint32_t * pDst = _sdata; pDst < _edata; )
*pDst++ = *pSrc++;

То почему бы не иметь опцию, которая бы сразу совмещала данные и их заполнение по одному адресу? Или такой опции не существует?
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Mar 26 2012, 21:16
Сообщение #4


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (RCray @ Mar 26 2012, 21:44) *
Так у вас тоже под константы место выделяется отдельно, а для данных которыми инициализируются этими константами отдельно.
Да, все верно. А у вас что, и код и данные грузятся перед исполнением в ОЗУ какой-то сторонней запускалкой? Тогда просто убрать AT > ROM и данные будут расположены сразу по адресам .data, а копирование будет не нужно.

Этот же скрипт полагает, что программа находится во флеше и исполняется после включения питания из флеша. А данные {1,2,3,4,5} в ОЗУ после включения питания должны откуда-то как-то появится, они ведь теряются после выключения питания, вот они и копируются этим циклом, а копироваться они должны из флеша, куда начальные значения и помещаются конструкцией AT > ROM.

А если вы объявите данные как int32_t const a[5] = {1, 2, 3, 4, 5}; то они попадут в секцию .rodata и вот ее можно смело класть в выходную секцию .text, ибо компилятор будет следить за тем, чтобы вы использовали эти данные только для чтения и поэтому они могут лежать во флеше.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

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

 


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


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