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

WinAVR - проблема с секциями в ld

Мега 8. WinAVR 20070525.

Потребовалось организовать в ОЗУ следующую карту памяти:

0x60-0x71 - зарезервировано

0x71-N - Массив (его размер определяется при объявлении в программе)

N-0x45F - данные программы, стеки, в общем как обычно.

 

Массив определяю в программе в отдельную секцию:

uint8_t Buffer[5] __attribute__((section("buffer"),used));

Скопировал в каталог проекта скрипт avr4.x, изменил в нем регионы, поставил выходную секцию .bss перед .data, добавил свою секцию в .bss:

MEMORY
{
  text   (rx)   : ORIGIN = 0, LENGTH = 0x17F4
  data   (rw!x) : ORIGIN = 0x800071, LENGTH = 1K
  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 512
}
....
  .bss :
  {
    *(buffer);    /* reserved for TxBuffer */
    KEEP (*(buffer))
     PROVIDE (__bss_start = .);
    *(.bss)
    *(.bss*)
    *(COMMON)
     PROVIDE (__bss_end = .);
  }  > data

  .data SIZEOF(.bss) + ADDR(.bss)  : AT (ADDR (.text) + SIZEOF (.text) )   /* load from (.text) + sizeof(.text) */
  {
     PROVIDE (__data_start = .);
    *(.data)
    *(.data*)
    *(.rodata)  /* We need to include .rodata here if gcc is used */
    *(.rodata*) /* with -fdata-sections.  */
    *(.gnu.linkonce.d*)
    . = ALIGN(2); 
     _edata = .;
     PROVIDE (__data_end = .);
  }  > data

При компиляции получаю предупреждение: ld.exe: Test.elf: warning: allocated section `.data' not in segment

При этом avr-objcopy при создании .hex добавляет в него данные по адресам __data_start (т.е. 0x8000XX). Начал урезать исходники и makefile, чтобы отыскать откуда ноги. Эффект нестабильный - при выкидывании одних кусков исходника пропадает, при выкидывании других - остается. Получил прилагаемый проект, в котором эффект еще повторяется. При дальнейшем уменьшении исходника эффект пропадает. Причем он пропадает даже при изменении той части исходника, код из которой не используется и выкидывается при линковке. Если убрать --gc-sections, эффект также пропадает. Если в линкерном скрипте убрать ". = ALIGN(2);" в .data (кстати, зачем он тут?) - тоже исчезает. Заметил, что одно из условий появления - если в результате сбора мусора линкером сегмент .data получается пустым, однако это не единственное условие, требуется что-то еще.

 

Пробовал версию 22071221 - поведение идентично. 20060421 - предупреждение не генерится, но в выходной .hex-файл все равно добавляется мусор.

 

Вопрос первый - что означает это предупреждение? Гугление не помогло.

Вопрос второй - что я делаю не так и как надо правильно добавлять свои секции?

Вопрос третий - пробовал создавать в линкерном скрипте отдельную выходную секцию для массива. В результате avr-objcopy -o ihex -R .eeprom Test.elf Test.hex помещает в .hex нули по VMA адресам этого массива. При указании -R <имя моей секции> она исчезает из выходного файла, но тогда возникет вопрос - почему в выходном файле не появляются секции .noinit, .bss и секции отладочной информации (перечислены в конце скрипта), хотя они и не были перечислены с ключем -R. Где об этом можно почитать? В документации к ld, avr-objcopy, objcopy, gcc ничего на эту тему не нашел.

ld_quest.zip

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


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

Провел дополнительные исследования. Выяснил, что появление лишней информации в .hex и это предупреждение не связаны (хотя вчера они появлялись и исчезали одновременно). С появлением лишней информации выяснил, что если мои секции описаны в .bss между строчками PROVIDE (__bss_start = .) и PROVIDE (__bss_end = .), то они не появляются в выходном файле, если же вне этих строчек - то появляются:

  .bss :  /* Так появляется */
  {
    *(buffer);    /* reserved for TxBuffer */
    KEEP (*(buffer))
     PROVIDE (__bss_start = .);
    *(.bss)
    *(.bss*)
    *(COMMON)
     PROVIDE (__bss_end = .);
  }  > data

  .bss :     /* a так - нет */
  {
     PROVIDE (__bss_start = .);
    *(buffer);    /* reserved for TxBuffer */
    KEEP (*(buffer))
    *(.bss)
    *(.bss*)
    *(COMMON)
     PROVIDE (__bss_end = .);
  }  > data

Таким образом обходное решение найдено, но остается третий вопрос - как avr-objcopy по умолчанию определяет, что включать в .hex, а что - нет.

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


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

При компиляции получаю предупреждение: ld.exe: Test.elf: warning: allocated section `.data' not in segment

Проблема (несоответствие) адресов/размеров переменных и Memory Region.

То есть попытка разместить символ по адресу, не попападающему в соответствующий регион памяти.

 

Провел дополнительные исследования. Выяснил, что появление лишней информации в .hex и это предупреждение не связаны (хотя вчера они появлялись и исчезали одновременно). С появлением лишней информации выяснил, что если мои секции описаны в .bss между строчками PROVIDE (__bss_start = .) и PROVIDE (__bss_end = .), то они не появляются в выходном файле, если же вне этих строчек - то появляются:
  .bss :  /* Так появляется */
  {
    *(buffer);    /* reserved for TxBuffer */
    KEEP (*(buffer))
     PROVIDE (__bss_start = .);
    *(.bss)
    *(.bss*)
    *(COMMON)
     PROVIDE (__bss_end = .);
  }  > data

  .bss :     /* a так - нет */
  {
     PROVIDE (__bss_start = .);
    *(buffer);    /* reserved for TxBuffer */
    KEEP (*(buffer))
    *(.bss)
    *(.bss*)
    *(COMMON)
     PROVIDE (__bss_end = .);
  }  > data

Таким образом обходное решение найдено, но остается третий вопрос - как avr-objcopy по умолчанию определяет, что включать в .hex, а что - нет.

Собственно __bss_start и __bss_end являются общепринятыми (в мире CGG) именами и должны обрамлять секцию. То-же касается и __data_start и прочих. Я не копал глубоко, но может эти имена анализируются линкером.

PROVIDE () больше предназначено для устранения дублирующих определений и их гарантированного появления чем для собственно определений. Что будет если PROVIDE (__bss_start = .) заменить на __bss_start = .? Сообщение останется?

objcopy по умолчанию копирует в HEX файл (как впрочем и в binary) выходные секции .text .data .rodata (полный список зависит от архитектуры).

Изменено пользователем amw

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


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

Проблема (несоответствие) адресов/размеров переменных и Memory Region.

То есть попытка разместить символ по адресу, не попападающему в соответствующий регион памяти.

Пппереведи! (с)"Москва слезам не верит". Какое мое действие приводит к возникновению этого предупреждения и почему оно то появляется, то исчезает в зависимости от седержимого кода, удаляемого сборщиком мусора линкера?

Я интуитивно понял, что при какой-то комбинации сборщик мусора линкера выкидывает все из секции .data, но оставляет там байт-заполнитель от инструкции скрипта . = ALIGN(2). Предполагаю, что для этого байта нет соответствующего значения в области AT (ADDR (.text) + SIZEOF (.text), о чем и ругается линкер. Но это только мое предположение.

Собственно __bss_start и __bss_end являются общепринятыми (в мире CGG) именами и должны обрамлять секцию. То-же касается и __data_start и прочих. Я не копал глубоко, но может эти имена анализируются линкером.
Вот где про это почитать, кроме исходников линкера? В описании линкера эти символы не упоминаются, в примерах скриптов в этом же описании не встречаются, и вдруг выясняется, что они имеют важное значение. Хотелось бы ознакомиться с документами, где это описано, чтобы не двигаться наощупь. И вдруг там описано еще что-то важное и интересное.

PROVIDE () больше предназначено для устранения дублирующих определений... Что будет если PROVIDE (__bss_start = .) заменить на __bss_start = .? Сообщение останется?
PROVIDE определяет символ, если такой символ не определен в объектных файлах. В данном конкретном случае не изменилось ничего, чего и следовало ожидать.

objcopy по умолчанию копирует в HEX файл (как впрочем и в binary) выходные секции .text .data .rodata (полный список зависит от архитектуры).
- А я Виндовс-2000 так до конца и не прошел :(

- Так это же не игра, а операционная система!

- Откуда инфа?!?!?

Откуда инфа? Где посмотреть этот полный список? .bss, .noinit, .stab, .comment, .debug, .line - тоже выходные секции. Причем как показал мой эксперимент с перемещением __bss_start = . он может копировать выходные секции не целиком, а частями.

Кто-нибудь знает, какой конкретно TFM мне надо R?

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


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

А почему не сделать просто в Makefile ? :

 

.....................
## Linker flags
LDFLAGS = $(COMMON)
LDFLAGS +=  -Wl,-Map=Pd105Gcc.map
LDFLAGS += -Wl,-section-start=.data=0x800070
LDFLAGS += -Wl,-section-start=buffer=0x800060

## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom -R buffer

HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0
............................

##Link
$(TARGET): $(OBJECTS)
     $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)

%.hex: $(TARGET)
    avr-objcopy -O ihex $(HEX_FLASH_FLAGS)  $< $@

%.eep: $(TARGET)
    avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@
.......................

 

в HEX_FLASH_FLAGS просто удаляем секцию buffer при создании hex

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


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

Пппереведи! (с)"Москва слезам не верит". Какое мое действие приводит к возникновению этого предупреждения и почему оно то появляется, то исчезает в зависимости от седержимого кода, удаляемого сборщиком мусора линкера?

Не могу :(. Примерно так же ковыряюсь наугад в скриптах. Более подробной инфы чем info ld не встречал.

Недавно было такое-же, когда я пытался зарезервировать область (читай секцию) в начале ОЗУ под векторы исключений для ARM.

Линкер то выкидывал нафиг эту секцию, то ругался как у Вас.

Методом тыка дошел до того, что в прилагаемом файле.

К стати у меня на Debian Ваш пример компилится/линкуется без ошибок и варнингов.

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

Я интуитивно понял, что при какой-то комбинации сборщик мусора линкера выкидывает все из секции .data, но оставляет там байт-заполнитель от инструкции скрипта . = ALIGN(2). Предполагаю, что для этого байта нет соответствующего значения в области AT (ADDR (.text) + SIZEOF (.text), о чем и ругается линкер. Но это только мое предположение.

Возможно.

Возможно C++ хочет что-то положить в начале памяти. Я собственно с C++ работаю очень редко, потому тут помочь не могу. Как вариант, попробуйте чистый C.

Собственно секции лучше всего располагать по выроненному адресу. Так более универсальнее. Для этого и стоит ALIGN().

Вот где про это почитать, кроме исходников линкера? В описании линкера эти символы не упоминаются, в примерах скриптов в этом же описании не встречаются, и вдруг выясняется, что они имеют важное значение. Хотелось бы ознакомиться с документами, где это описано, чтобы не двигаться наощупь. И вдруг там описано еще что-то важное и интересное.

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

Откуда инфа? Где посмотреть этот полный список? .bss, .noinit, .stab, .comment, .debug, .line - тоже выходные секции. Причем как показал мой эксперимент с перемещением __bss_start = . он может копировать выходные секции не целиком, а частями.

Кто-нибудь знает, какой конкретно TFM мне надо R?

Боюсь, что авторы binutils не смогут Вам ответить :( .

Список высмотрел когда-то в исходниках. Давно было дело, года 4 назад.

 

Вот результат компиляции, может поможет.

 

# avr-gcc -v
Using built-in specs.
Target: avr
Configured with: ../build-tree/gcc-4.1.0/configure -v --enable-languages=c,c++ --prefix=/usr --infodir=/usr/share/info --mandir=/usr/share/man --enable-shared --with-system-zlib --enable-long-long --enable-nls --without-included-gettext --disable-checking --disable-libssp --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=avr
Thread model: single
gcc version 4.1.0
# avr-ld -v
GNU ld (GNU Binutils) 2.18.20071027

lpc2378.lds.zip

ld_quest_lnx.zip

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


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

А почему не сделать просто в Makefile ?
Потому что буфер находится внутри выходной секции .bss, а ключ -R применяется к выходным, а не входным секциям.

В первом варианте, когда это у меня вылезло, у меня под буфер была выделена отдельная выходная секция и мне ReAl как раз такое решение и посоветовал. Но мое чувство прекрасного воспротивелось этому - если objcopy умеет по умолчанию выкидывать какие-то секции, то пусть и мой буфер выкинет заодно. Для этого я и поместил его в .bss. Вылез подводный камень. Хочу разобраться.

 

Методом тыка дошел до того, что в прилагаемом файле.
Спасибо, посмотрю.
К стати у меня на Debian Ваш пример компилится/линкуется без ошибок и варнингов.
Надо будет проверить. Как раз недавно поставил Кубунту дома, осваиваю.
Как вариант, попробуйте чистый C.
Нет, уж лучше вы к нам :)
Собственно секции лучше всего располагать по выроненному адресу. Так более универсальнее. Для этого и стоит ALIGN().
Я понимаю, что это необходимость для ARM. Но для AVR я вижу только расход и так маленькой памяти без необходимости. Поэтому и поднял вопрос - или я чего-то не понимаю, и тогда мне объяснят и я стану умнее, или это просто недоработка и заходящие сюда авторы libc обратят на нее внимание.
Боюсь, что авторы binutils не смогут Вам ответить :( .
Не уверен. diwil имеет (имел?) к binutils отношение (правда в контексте mspgcc), кое-кто из участников имеет отношение к WinAVR и avr-libc (возможно, при работе с ней приходится и в binutils ковыряться), да и вообще - предполагаю, что многие участники используют gcc в различных видах и, возможно, знают точный ответ на мои глупые вопросы. А может кто-нибудь из спецов покачает головой вот так: :( и скажет: "Э... да это бага!" и тогда мы смело будем писать письмо турецкому султану (баг-репорт).

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


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

Нет, уж лучше вы к нам

:) . Все может быть. Но я имел в виду потестить, а не полностью проект переписывать.

Я понимаю, что это необходимость для ARM. Но для AVR я вижу только расход и так маленькой памяти без необходимости. Поэтому и поднял вопрос - или я чего-то не понимаю, и тогда мне объяснят и я стану умнее, или это просто недоработка и заходящие сюда авторы libc обратят на нее внимание.

Я не в курсе AVR архитектуры, однако наводящий вопрос: могут ли быть какие нибудь команды (или ситуации), требующие четного адреса? Возможно. используя эти команды быстрее производится копирование блоков данных (типа копирование секции .data в ОЗУ). Ну или что-то в этом роде.

Не уверен. diwil имеет (имел?) к binutils отношение (правда в контексте mspgcc), кое-кто из участников имеет отношение к WinAVR и avr-libc (возможно, при работе с ней приходится и в binutils ковыряться), да и вообще - предполагаю, что многие участники используют gcc в различных видах и, возможно, знают точный ответ на мои глупые вопросы. А может кто-нибудь из спецов покачает головой вот так: :( и скажет: "Э... да это бага!" и тогда мы смело будем писать письмо турецкому султану (баг-репорт).

:)

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


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

я имел в виду потестить, а не полностью проект переписывать.
Боюсь, что мне не удастся повторить этот эффект. Я в этом исходнике его с трудом "удержал" в процессе обрезания. Это я про предупреждение линкера. Про вывод секции в .hex - проверю.
Я не в курсе AVR архитектуры, однако наводящий вопрос: могут ли быть какие нибудь команды (или ситуации), требующие четного адреса?
В том-то и дело, что нет. 8-битный проц, все чисто байтовое. Точнее есть, но только одно место - заполнение буфера флеш при самопрограммировании производится по 2 байта. Но это никак с .data не связано.

 

К стати у меня на Debian Ваш пример компилится/линкуется без ошибок и варнингов.
Но "огрызок" секции .data с моим буфером все равно в хексе присутствует:
:0200000400807A
:0600710000000000000089

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


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

amw, спасибо за толчок в новом направлении! Мысли упорядочиваются.

 

Поймал себя на логическом противоречии. Если мой буфер должен быть заполнен нулями (как и вся секция .bss), то его входная секция должна находиться между __bss_start = . и __bss_end = ., ведь по этим символам crt.s определяет обнуляемую область. Если же он не должен очищаться, то он и не должен находиться в выходной секции .bss. Значит ему место или в .noinit (проверил, эта секция появляется в хексе целиком и на варнинг это не влияет), но поскольку .noinit это скорее внешнее ОЗУ под батарейкой, то моему буферу место в отдельной выходной секции, про которую objcopy ничего заранее знать не может и, значит, про которую ему надо сообщать явно. Выходит, изначально ReAl был прав.

 

Теперь поймал на противоречии описание avr-libc. Там сказано, что .noinit является частью секции .bss, что противоречит и содержимому скриптов линкера из комплекта avr-libc и духу секции .bss (обнуленные при старте данные). Ведь в описании as ясно сказано:

4.5 bss Section

.....When your program starts running, all the contents of the bss section are zeroed bytes.

Кстати, вот где оно все должно было быть! avr-libc-user-manual:

9.3 Memory Sections

Remarks:

Need to list all the sections which are available to the avr.

Оно просто не дописано еще!

 

Тогда несколько изменил бы следующие два выражения оттуда:

9.3.2 The .data Section

This section contains static data which was defined in your code.

9.3.3 The .bss Section

Uninitialized global or static variables end up in the .bss section.

Все-таки uninitialized - это про .noinit. Я бы про .data написал This section contains static data which was explicitly initialized in your code. А про .bss: Global or static variables which are not explicitly initialized end up in the .bss section. Those variables are zeroed accordinary with C standart (ISO/IEC 9899:1999 6.7.8.10) И уже не поминал бы .bss в контексте .noinit.

 

И тут у меня появился следующий вопрос: почему в примерах WinAVR для получения .hex используется команда $(OBJCOPY) -R .eeprom , хотя более логичным было бы использование $(OBJCOPY) -j .text ? Ведь прошиваемой является только выходная секция .text! Рано радовался. Инициализирующие значения .data складываются после .text посредством : AT() в скрипте линкера. Надо подумать, нельзя ли их сложить внутрь .text, рядом с rodata - тогда бы все получилось красиво. А пока эти данные нельзя явно указать objcopy и приходится вместо этого указывать "все, кроме лишнего". И что-то из этого "лишнего" заботливо указано avr-objcopy авторами по-умолчанию (но вот в документации это не отражено или я не нашел). Остаются совсем маленькие вопросы - почему размер "обрезаемой" части .bss определяется по __bss_start и __bss_end, а не по размеру самой секции, ведь эта информация должна быть в объектном файле и objdump ее видит? И почему для avr-objcopy по-умолчанию не указана секция .init? На последнее могу предположить, что .noinit не бывает в больших процессорах, из которых выросли binutils, а список секций живет где-то в непортируемой части. Но это только предположение.

 

Итого, резюмируя, вопросов осталось три - откуда warning (таки баг сборщика мусора линкера?), почему в .data . = ALIGN(2) и почему в objcopy __bss_start/__bss_end.

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


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

очнее есть, но только одно место - заполнение буфера флеш при самопрограммировании производится по 2 байта. Но это никак с .data не связано.

Как это не связано!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

А как, по вашему производится копирование секции .data из флеш в ОЗУ?

Гляньте в дизассемблер.

 

Но "огрызок" секции .data с моим буфером все равно в хексе присутствует:
:0200000400807A
:0600710000000000000089

То есть буффер попал в .data а не в .bss

 

amw, спасибо за толчок в новом направлении! Мысли упорядочиваются.

 

Поймал себя на логическом противоречии. Если мой буфер должен быть заполнен нулями (как и вся секция .bss), то его входная секция должна находиться между __bss_start = . и __bss_end = ., ведь по этим символам crt.s определяет обнуляемую область. Если же он не должен очищаться, то он и не должен находиться в выходной секции .bss. Значит ему место или в .noinit (проверил, эта секция появляется в хексе целиком и на варнинг это не влияет), но поскольку .noinit это скорее внешнее ОЗУ под батарейкой, то моему буферу место в отдельной выходной секции, про которую objcopy ничего заранее знать не может и, значит, про которую ему надо сообщать явно. Выходит, изначально ReAl был прав.

Теперь поймал на противоречии описание avr-libc. Там сказано, что .noinit является частью секции .bss, что противоречит и содержимому скриптов линкера из комплекта avr-libc и духу секции .bss (обнуленные при старте данные). Ведь в описании as ясно сказано:

Кстати, вот где оно все должно было быть! avr-libc-user-manual:Оно просто не дописано еще!

 

Тогда несколько изменил бы следующие два выражения оттуда:

Все-таки uninitialized - это про .noinit. Я бы про .data написал This section contains static data which was explicitly initialized in your code. А про .bss: Global or static variables which are not explicitly initialized end up in the .bss section. Those variables are zeroed accordinary with C standart (ISO/IEC 9899:1999 6.7.8.10) И уже не поминал бы .bss в контексте .noinit.

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

int a = 0;

Это - инициализируемая переменная.

Если указано

int b;

Это - НЕинициализируемая переменная.

Инициализируемая переменная -> .data.

НЕинициализируемая переменная -> .bss.

И тут у меня появился следующий вопрос: почему в примерах WinAVR для получения .hex используется команда $(OBJCOPY) -R .eeprom , хотя более логичным было бы использование $(OBJCOPY) -j .text ? Ведь прошиваемой является только выходная секция .text! Рано радовался. Инициализирующие значения .data складываются после .text посредством : AT() в скрипте линкера. Надо подумать, нельзя ли их сложить внутрь .text, рядом с rodata - тогда бы все получилось красиво. А пока эти данные нельзя явно указать objcopy и приходится вместо этого указывать "все, кроме лишнего". И что-то из этого "лишнего" заботливо указано avr-objcopy авторами по-умолчанию (но вот в документации это не отражено или я не нашел). Остаются совсем маленькие вопросы - почему размер "обрезаемой" части .bss определяется по __bss_start и __bss_end, а не по размеру самой секции, ведь эта информация должна быть в объектном файле и objdump ее видит? И почему для avr-objcopy по-умолчанию не указана секция .init? На последнее могу предположить, что .noinit не бывает в больших процессорах, из которых выросли binutils, а список секций живет где-то в непортируемой части. Но это только предположение.

Инициализацию секции .data и обнуление .bss выполняет сама программа. Во время выполнения. А в crt0.S имеется код типа такого (прифожу C эквивалент)

for (i = __bss_start; i < __bss_end; i++)
    *((char *)i) = 0;

Ваша программа включая crt0.S оперирует символами а не секциями. О секциях знает только компилятор и binutils. __bss_start и _bss_end - это и есть символы, по которым производится очистка.

Итого, резюмируя, вопросов осталось три - откуда warning (таки баг сборщика мусора линкера?), почему в .data . = ALIGN(2) и почему в objcopy __bss_start/__bss_end.

1. хз.

2. Посмотрите в исходнике crt0.S или в дизассемблере, как производится копирование .data.

3. Не уверен, что в objcopy, но может зарезервированные имена. .noinit секция (если Вы правильно описали ее суть) вообще не должна трогаться. А .bss должна. Как их отличить если .noinit часть .bss? Похоже что по символам "почему в objcopy __bss_start/__bss_end."

 

Ваш Test.ld

  /* Global data not cleared after reset.  */
  .noinit  SIZEOF(.data) + ADDR(.data) :
  {
     PROVIDE (__noinit_start = .);
    *(.noinit*)
     PROVIDE (__noinit_end = .);
     _end = .;
     PROVIDE (__heap_start = .);
  }  > data

Информация к размышлению © "17 мгновений весны"

 

Дизассемблер (фрагмент) Вашего примера

00000032 <__do_copy_data>:
  32:    10 e0           ldi    r17, 0x00; 0
  34:    a7 e7           ldi    r26, 0x77; 119
  36:    b0 e0           ldi    r27, 0x00; 0
  38:    e4 e7           ldi    r30, 0x74; 116
  3a:    f0 e0           ldi    r31, 0x00; 0
  3c:    02 c0           rjmp    .+4      ; 0x42 <.do_copy_data_start>

0000003e <.do_copy_data_loop>:
  3e:    05 90           lpm    r0, Z+
  40:    0d 92           st    X+, r0

00000042 <.do_copy_data_start>:
  42:    a8 37           cpi    r26, 0x78; 120
  44:    b1 07           cpc    r27, r17
  46:    d9 f7           brne    .-10     ; 0x3e <__SP_H__>

Какая из комманд оперирует выровненым адресом?

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


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

Как это не связано!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

А как, по вашему производится копирование секции .data из флеш в ОЗУ?

Нееее :) Из флеш в ОЗУ можно копировать побайтно совершенно безболезненно. Ограничение только при записи в обратном направлении. При записи во флеш (бутлодырь) можно буфер флеша заполнять только по два байта. Но заполняется он из регистров, а читать в регистры можно из любого адреса. И это делается правильно специальными функциями из комплекта avr-libc на инлайн-асме. Так что тут все нормально.
То есть буффер попал в .data а не в .bss
Звучит правдоподобно, НО КАК? В скрипте-то он был указан быть положенным в .bss
Инициализируемые переменные - это те, которым Вы в программе явно указали, чему они должны быть равны при старте программы. Точное значение - не важно.Если написано

int a = 0;

Это - инициализируемая переменная.

Если указано

int b;

Это - НЕинициализируемая переменная.

Инициализируемая переменная -> .data.

НЕинициализируемая переменная -> .bss.

То есть вы хотите сказать, что значение b при старте программы не определено? Стандарт утверждает обратное:
10 If an object that has automatic storage duration is not initialized explicitly, its value is indeterminate. If an object that has static storage duration is not initialized explicitly, then:

— if it has pointer type, it is initialized to a null pointer;

— if it has arithmetic type, it is initialized to (positive or unsigned) zero;

— if it is an aggregate, every member is initialized (recursively) according to these rules;

— if it is a union, the first named member is initialized (recursively) according to these

rules.

в .bss попадают как раз an object that has static storage duration и которые при этом not initialized explicitly, т.е. не проинициализированны явно. Кстати, где-то встречал упоминание (кажется в каком-то из описаний GCC), что переменные, явно проинициализированные нулем тоже кладутся в .bss а не в .data
Инициализацию секции .data и обнуление .bss выполняет сама программа.
Ммм... в контексте простой embedded-системы - да. Когда crt0.s является частью программы. Если же в системе живет управляющая ОС, осуществляющая запуск приложений, то ОС, загружая программу, своими средствами выполняет те же действия что и crt0.s перед запуском программы. А именно - копирование секций из LMA в VMA, обнуление .bss, динамическую линковку библиотек, передачу управления на точку указанную через ENTRY() в скрипте линкера. Во всяком случае я пока так себе это представляю.
Ваша программа включая crt0.S оперирует символами а не секциями. О секциях знает только компилятор и binutils.
Я это понимаю и с этим и не спорил. Я писал об objcopy, которая есть часть binutils и которая оперирует с секциями.
.noinit секция (если Вы правильно описали ее суть) вообще не должна трогаться. А .bss должна. Как их отличить если .noinit часть .bss?
Вот и я о том же. Значит в описании avr-libc имеется ошибка и ее надо исправить.
Информация к размышлению © "17 мгновений весны"
Не понял. Эти символы я перемещал - они в моем случае на .hex не влияют.
Какая из комманд оперирует выровненым адресом?
Никакая. Выровненным во всей системе команд AVR должен быть только аргумент команды перехода или косвенного перехода (ну и упомянутый аргумент команды программирования флеши).

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


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

Нееее :) Из флеш в ОЗУ можно копировать побайтно совершенно безболезненно. Ограничение только при записи в обратном направлении. При записи во флеш (бутлодырь) можно буфер флеша заполнять только по два байта. Но заполняется он из регистров, а читать в регистры можно из любого адреса. И это делается правильно специальными функциями из комплекта avr-libc на инлайн-асме. Так что тут все нормально.

ОК. Убедили, но проверте все же как именно выполняется копирование. Выравние из ниоткуда? Должны же быть причины для такого выравнивания.

Звучит правдоподобно, НО КАК? В скрипте-то он был указан быть положенным в .bss То есть вы хотите сказать, что значение b при старте программы не определено? Стандарт утверждает обратное:в .bss попадают как раз an object that has static storage duration и которые при этом not initialized explicitly, т.е. не проинициализированны явно.

Определено. Секция .bss забивается нулями. Естественно я говорю о глобальных и/или статических переменных, а не о тех, что в стеке.

Кстати, где-то встречал упоминание (кажется в каком-то из описаний GCC), что переменные, явно проинициализированные нулем тоже кладутся в .bss а не в .data

Гм.. Да. Только что проверил.

Ммм... в контексте простой embedded-системы - да. Когда crt0.s является частью программы. Если же в системе живет управляющая ОС, осуществляющая запуск приложений, то ОС, загружая программу, своими средствами выполняет те же действия что и crt0.s перед запуском программы. А именно - копирование секций из LMA в VMA, обнуление .bss, передачу управления на точку указанную через ENTRY() в скрипте линкера.Я это понимаю и с этим и не сприл.

Да. Но! В любом случае, эта часть (копирование и обнуление секций) не есть часть компилятора.

В embedded-мире - это часть libc.

Я писал об objcopy, которая есть часть binutils и которая оперирует с секциями.Вот и я о том же. Значит в описании avr-libc имеется ошибка и ее надо исправить.Не понял. Эти символы я перемещал - они в моем случае на .hex не влияют.Никакая. Выровненным во всей системе команд AVR должен быть только аргумент команды перехода или косвенного перехода (ну и упомянутый аргумент команды программирования флеши).

Ага. А где гарантия, что за секция .data (LMA) идет после секции .text? Простейший пример:

text :
{
  (*crt0.o (.text))
}
.data :
{
  *(.data);
}
text :
{
  *(.text);
}

Что будет с переходом, если секция .data - 3 байта?

Думаю, что в виду специфики AVR (и не только) objcopy анализирует что-то, специфичное для конкретной архитектуры.

 

Щас попробую потасовать секции. Может что-нибудь прояню.

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


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

И тут у меня появился следующий вопрос: почему в примерах WinAVR для получения .hex используется команда $(OBJCOPY) -R .eeprom , хотя более логичным было бы использование $(OBJCOPY) -j .text ? Ведь прошиваемой является только выходная секция .text! Рано радовался. Инициализирующие значения .data складываются после .text посредством : AT() в скрипте линкера. Надо подумать, нельзя ли их сложить внутрь .text, рядом с rodata - тогда бы все получилось красиво.
Развил мысль, все получилось. Надо objcopy указывать не только -j .text, но и -j .data Итого: $(OBJCOPY) -O ihex -j .text -j .data $< $@ копирует в хекс-файл только исполняемый код и инициализирующие значения для .data. Все остальное не копирует.

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


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

Развил мысль, все получилось. Надо objcopy указывать не только -j .text, но и -j .data Итого: $(OBJCOPY) -O ihex -j .text -j .data $< $@ копирует в хекс-файл только исполняемый код и инициализирующие значения для .data. Все остальное не копирует.

А .rodata? Константы нужны? В том числе и те, которые есть в компиляторах и библиотеках.

 

Щас попробую потасовать секции. Может что-нибудь прояню.

Не могу добиться варнинга.

А сравните версии компиляторов. (Я свою приводил выше). Может и в правду какая бага. У Вас есть, а у меня уже (или еще) нет.

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


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

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

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

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

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

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

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

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

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

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