Необъяснимый пустой адрес памяти перед разделом .data - PullRequest
0 голосов
/ 12 февраля 2019

В настоящее время я пишу программу на STM32, которая использует простой загрузчик и два подпрограммы.Подпрограммы расположены во флэш-памяти, и загрузчик загружает одну из них (и код, и данные) в память RAM, а затем начинает ее выполнение.Копирование выполняется просто путем перебора адресов во флэш-памяти и копирования данных с этих адресов в ОЗУ.

Недавно я столкнулся с какой-то странной ошибкой.Я пытался прочитать некоторые данные из глобально определенного массива.Я получал неправильные значения, например, когда я пытался прочитать array[0], я возвращал значение array[1].

Я сделал некоторую отладку и разборку файлов .elf и .hex, и я думаю,Я нашел причину этой ошибки.Оказалось, что между разделом .ARM файла .elf этого проекта есть пустое пространство.
Удивительно, но этого пустого пространства нет в файле .hex (который я использую для перепрошивки платы STM32).
Это то, о чем я говорю:

  • .elf файл:
2000ee70:   469e        mov lr, r3
2000ee72:   4770        bx  lr

Disassembly of section .ARM:

2000ee74 <__exidx_start>:
2000ee74:   7fff267c    svcvc   0x00ff267c
2000ee78:   00000001    andeq   r0, r0, r1

Disassembly of section .data:

2000ee80 <evnames.5255>:
2000ee80:   00000000    andeq   r0, r0, r0
2000ee84:   08030104    stmdaeq r3, {r2, r8}
  • .hex файл:
 802de70:   4770469e    
 802de74:   7fff267c    svcvc   0x00ff267c
 802de78:   00000001    andeq   r0, r0, r1
 802de7c:   00000000    andeq   r0, r0, r0
 802de80:   08030104    stmdaeq r3, {r2, r8}

Очевидно, что адреса разные, потому что адреса в файле .elf - это VMA, а адреса в файле .hex - это LMA.
Здесь я заметил, что после раздела .ARMследующий адрес памяти должен быть 2000ee7C, но по неизвестным причинам раздел .data начинается с 2000ee80.Так что между ними есть одно необъяснимое, пустое слово.Но этого пустого слова нет в файле .hex.За 00000001 сразу же следует 00000000.
Так что, в принципе, я думаю, что разборка файла .hex должна вывести следующий результат:

 802de70:   4770469e    
 802de74:   7fff267c    svcvc   0x00ff267c
 802de78:   00000001    andeq   r0, r0, r1
 802de7c:       <something here>
 802de80:   00000000    andeq   r0, r0, r0
 802de84:   08030104    stmdaeq r3, {r2, r8}

Из-за этого пустого пространства памяти, котороеисчезает в файле .hex, когда мой загрузчик загружает данные в ОЗУ, array[0], который LMA равен 2000eec8, оказывается по адресу 2000eec4.

Это тревожный фрагмент компоновщикаскрипт, который я использую:

  /* ARM specific sections, they also go to FLASH and are copied to RAM */
  .ARM.extab : { 
      *(.ARM.extab* .gnu.linkonce.armextab.*) 
  } > RAMAPP AT> FLASH_APP
  .ARM : {
      __exidx_start = .;
      *(.ARM.exidx*)
      __exidx_end = .;
  } > RAMAPP AT> FLASH_APP

  /* Initialized data sections - variables etc.  */
  .data :
  {
      . = ALIGN(4);
      *(.data)           /* .data sections */
      *(.data*)          /* .data* sections */
      . = ALIGN(4);    
  } >RAMAPP AT> FLASH_APP /* Data section is placed in FLASH_APP but its Virtual Memory Address is in RAM_APP */

Я использую следующую команду, чтобы связать файлы .o в один файл .elf:

arm-none-eabi-gcc -Wl,--gc-sections -mthumb -mthumb-interwork -mcpu=cortex-m4 --specs=nosys.specs -L[path_to_library_files] -T[path_to_ld_file] [long_list_of_object_files] -o [output_elf_file]

Я использую следующую команду для преобразования .elfфайл в файл .hex:

arm-none-eabi-objcopy -O ihex [elf_file] [output_hex_file]

Я пытался поэкспериментировать с параметрами, которые я даю arm-none-eabi-objcopy и arm-none-eabi-gcc, чтобы избавиться от этого отступа, например --file-alignment или --gap-fill но пока безуспешно.

Кто-нибудь имеет представление о том, откуда взялась эта пустая область и как от нее избавиться (или включить ее в файл .hex)?

РЕДАКТИРОВАТЬ: В соответствии с предложениями первых двух комНет, я пытался:
* используя новейшие версии arm-none-eabi-gcc и arm-none-eabi-objcopy в моей цепочке инструментов,
* ALIGN(4) раздела .ARM,
* не копировать .ARM раздел с RAM.
К сожалению, ни одно из этих решений не устранило эту проблему.

Недавно я заметил, что иногда данные правильно выровнены в файле .elf (первый адрес раздела .data - это адрес, который следует сразу за концом раздела .ARM).Это зависит от адреса, на котором заканчивается раздел .ARM.Я могу манипулировать этим, добавляя некоторые дополнительные вызовы функций в коде (что приводит к увеличению .text области), например:

2000ee84:   469e        mov lr, r3
2000ee86:   4770        bx  lr

Disassembly of section .ARM:

2000ee88 <__exidx_start>:
2000ee88:   7fff2668    svcvc   0x00ff2668
2000ee8c:   00000001    andeq   r0, r0, r1

Disassembly of section .data:

2000ee90 <evnames.5255>:
2000ee90:   00000000    andeq   r0, r0, r0
2000ee94:   2001111c    andcs   r1, r1, ip, lsl r1

Таким образом, я установил, что:
* когдаСекция .ARM заканчивается по адресу 0x*******0 Секция .data неправильно начинается в 0x*******8 (должно быть 0x*******4)
*, когда секция .ARM заканчивается по адресу 0x*******8 Секция .data неправильно начинаетсяв 0x*******0 (должно быть 0x*******C)
* когда секция .ARM заканчивается по адресу 0x*******4 секция .data ПРАВИЛЬНО начинается в 0x*******8
* когда секция .ARM заканчивается по адресу 0x*******C секция .data ПРАВИЛЬНО начинается с 0x*******0

1 Ответ

0 голосов
/ 17 февраля 2019

Хорошо, оказалось, что мне пришлось добавить ALIGN_WITH_INPUT в раздел .data в скрипте компоновщика.Например:

  .data : ALIGN_WITH_INPUT
  {
    . = ALIGN(4);
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
    . = ALIGN(4);    

  } >RAMAPP AT> FLASH_APP

Этот параметр вызывает выравнивание LMA секции таким же образом, как и VMA.Теперь выравнивание в .hex-файле идентично выравниванию в .elf-файле.
Приветствуйте reddit пользователя FreddieChopin, который помог мне решить эту проблему.

...