В настоящее время я пишу программу на STM32, которая использует простой загрузчик и два подпрограммы.Подпрограммы расположены во флэш-памяти, и загрузчик загружает одну из них (и код, и данные) в память RAM, а затем начинает ее выполнение.Копирование выполняется просто путем перебора адресов во флэш-памяти и копирования данных с этих адресов в ОЗУ.
Недавно я столкнулся с какой-то странной ошибкой.Я пытался прочитать некоторые данные из глобально определенного массива.Я получал неправильные значения, например, когда я пытался прочитать array[0]
, я возвращал значение array[1]
.
Я сделал некоторую отладку и разборку файлов .elf и .hex, и я думаю,Я нашел причину этой ошибки.Оказалось, что между разделом .ARM
файла .elf этого проекта есть пустое пространство.
Удивительно, но этого пустого пространства нет в файле .hex (который я использую для перепрошивки платы STM32).
Это то, о чем я говорю:
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}
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