Хорошо, так что, может быть, это то, что я могу ответить, не понял ваш вопрос в комментарии другого вопроса.
Процессор загружается, ища векторную таблицу по адресу 0x00000000 в адресном пространстве оружия. ST реализовал свою часть так, что приложение fla sh находится по адресу 0x08000000 в адресном пространстве оружия.
В зависимости от режима загрузки ST может, если вы будете зеркалировать либо встроенную программу начального загрузчика на адрес 0x00000000, либо приложение. Таким образом, доступ к руке по адресу 0x00000000 будет возвращаться со значениями, найденными в fla sh Если зеркалировать приложение, то и 0x00000000, и 0x08000000 будут считывать значения с одного и того же физического устройства fla sh и возвращать их. Здесь нет magi c, шина ARM имеет адрес и объем данных, которые она хочет прочитать, logi c имеет маски и совпадения, чтобы определить, какое это адресное пространство, то если от 0x00000000 до некоторого количества Кбайт, тогда, если ремешок читается одним способом из одного флага sh, другой считывается из другого. Аналогично с write.
Поиск BOOT0 в справочном руководстве для детали.
В идеале вы хотите связать для 0x08000000 (или 0x00200000 для некоторых деталей, но не для всех), чтобы вектор записи таблицы, прочитанные по адресу 0x00000004, 0x00000008 и т. д., возвращают адреса 0x0800xxxx, таким образом, только таблица векторов фактически считывается из 0x00000000, а затем остальная часть программы в адресном пространстве приложения. В документации вы увидите, что адресное пространство 0x00000000 для деталей с большим количеством fla sh не поддерживает весь размер fla sh, поэтому вы не можете использовать все fla sh, если вы ссылаетесь на 0x00000000
теперь эти сценарии компоновщика интересны, прежде всего, если вы видите это в таблице векторов для cortex-m
.word _start + 1
.word _nmi_handler + 1
.word _hard_fault + 1
, найдите другой пример.
.thumb
.section isr_vector
.word 0x20001000
.word one
.word two
.text
.thumb_func
one:
b one
.thumb_func
two:
b two
.thumb_func
сначала скрипт компоновщика
Disassembly of section .text:
00000000 <one-0xc>:
0: 20001000 andcs r1, r0, r0
4: 0000000d andeq r0, r0, sp
8: 0000000f andeq r0, r0, pc
0000000c <one>:
c: e7fe b.n c <one>
0000000e <two>:
e: e7fe b.n e <two>
в этом случае, когда рычаг выполняет чтение таблицы векторов, чтобы найти вектор сброса по адресу 0x00000004, часть ST вернет значение во втором слове приложения fla sh (думаю, адрес 0x08000004)
, в этом случае он обнаруживает 0000000d, что означает начало выборки инструкций по адресу 0x0000000 c.
со вторым сценарием компоновщика
.thumb
.section .isr_vector
.globl _isr_vector
_isr_vector:
.word 0x20001000
.word Reset_Handler
.text
.globl Reset_Handler
.thumb_func
Reset_Handler:
b .
Disassembly of section .text:
08000000 <_isr_vector>:
8000000: 20001000 andcs r1, r0, r0
8000004: 08000009 stmdaeq r0, {r0, r3}
08000008 <Reset_Handler>:
8000008: e7fe b.n 8000008 <Reset_Handler>
в в этом случае, когда рука ищет вектор сброса в 0x00000004, он получит 0x08000009, что означает выбор первых инструкций по адресу 0x08000008, который находится в адресном пространстве для пар t для приложения fla sh, это предпочтительно.
У некоторых деталей ST есть небольшое окно с размером 0x00200000, которое может читать некоторые из этих флагов sh быстрее (это дело рук ITCM против AXIM, читайте документы cortex-m7).
По msp432, и я думаю, что fla приложения sh - это 0x01000000, то же самое, что и зеркалирование, просто другой адрес.
.thumb_func
.align 2
.global Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
Обратите внимание, что во втором примере у автора есть дополнительный код, оба .thumb_fun c и .type помечают эту метку как функцию (которая делает ORR с 1, чтобы установить lsbit адреса, чтобы вам не нужно было иметь уродливую векторную таблицу, используйте инструменты)
Например:
.thumb
.section .isr_vector
.globl _isr_vector
_isr_vector:
.word 0x20001000
.word Reset_Handler
.word Something_Else
.text
.globl Reset_Handler
.thumb_func
Reset_Handler:
b .
.type Something_Else, %function
Something_Else:
b .
Disassembly of section .text:
08000000 <_isr_vector>:
8000000: 20001000 andcs r1, r0, r0
8000004: 0800000d stmdaeq r0, {r0, r2, r3}
8000008: 0800000f stmdaeq r0, {r0, r1, r2, r3}
0800000c <Reset_Handler>:
800000c: e7fe b.n 800000c <Reset_Handler>
0800000e <Something_Else>:
800000e: e7fe b.n 800000e <Something_Else>
оба сработали, какой вы используете, это ваше личное предпочтение
.thumb_func
чисто и просто и не требует соответствия метке, но это зависит от позиции, следующая метка является той это помечено как функция. Также нет .arm_fun c
.type labelname, %function
работает как для кода руки, так и для большого пальца, это, возможно, немного больше печатать, и вы должны соответствовать названию этикетки, но есть плюсы в этом, как вы ясно обозначают метку, которую вы хотите идентифицировать как адрес функции, и эта привычка работает как в режиме «рука», так и в режиме «большой палец».
Оба автора (или это один и тот же человек дважды?) создали ненужную работу.
Рассмотрим эти
so.s
.thumb
.word 0x20001000
.word one
.word two
.thumb_func
one:
b .
.thumb_func
two:
b .
next.s
add r1,r2,r3
add r2,r3,r4
add r3,r4,r5
so.ld
MEMORY
{
xyz : ORIGIN = 0x08000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > xyz
}
arm-none-eabi-as so.s -o so.o
arm-none-eabi-as next.s -o next.o
arm-none-eabi-ld -T so.ld so.o next.o -o so.elf
arm-none-eabi-objdump -D so.elf
so.elf: file format elf32-littlearm
Disassembly of section .text:
08000000 <one-0xc>:
8000000: 20001000 andcs r1, r0, r0
8000004: 0800000d stmdaeq r0, {r0, r2, r3}
8000008: 0800000f stmdaeq r0, {r0, r1, r2, r3}
0800000c <one>:
800000c: e7fe b.n 800000c <one>
0800000e <two>:
800000e: e7fe b.n 800000e <two>
8000010: e0821003 add r1, r2, r3
8000014: e0832004 add r2, r3, r4
8000018: e0843005 add r3, r4, r5
это хорошо
но если вы
arm-none-eabi-ld -T so.ld next.o so.o -o so.elf
arm-none-eabi-objdump -D so.elf
so.elf: file format elf32-littlearm
Disassembly of section .text:
08000000 <one-0x18>:
8000000: e0821003 add r1, r2, r3
8000004: e0832004 add r2, r3, r4
8000008: e0843005 add r3, r4, r5
800000c: 20001000 andcs r1, r0, r0
8000010: 08000019 stmdaeq r0, {r0, r3, r4}
8000014: 0800001b stmdaeq r0, {r0, r1, r3, r4}
08000018 <one>:
8000018: e7fe b.n 8000018 <one>
0800001a <two>:
800001a: e7fe b.n 800001a <two>
это плохо.
если не вызывается в сценарии компоновщика, то позиция ссылки в командной строке определяет порядок элементов .text в файле. При предоставлении примера или создании проекта у вас не должно быть make-файла или инструкций по сборке для go с кодом? Вы действительно должны выполнить дополнительную работу в скрипте компоновщика? YMMV
Также обратите внимание, что метки памяти в скрипте компоновщика являются просто метками для соединения точек между MEMORY и SECTIONS. Вы можете использовать любые строки, которые вы хотите, в определенных пределах и с некоторыми исключениями.
Я использовал (rw), но это стало проблематично c пришлось перестроить мой скрипт компоновщика между двумя версиями бинутилс. (мне кажется, что в этом примере есть ошибка) Если компоновщик жалуется на отсутствующий раздел (.rodata), просто добавьте его, ничего не значит.
Красота чистого металла в том, что вы можете выбирать как вы хотите это сделать, если вы не используете библиотеки, то вы должны играть в их песочнице. И часто вы найдете более сложные скриптовые компоновщики и бутстрапы, которые пытаются охватить все возможные варианты использования и функции. Просто создайте тот, который соответствует вашему варианту использования.
Вы можете написать свой код так, чтобы вам не приходилось обнулять .bss или копировать .data, или вы можете выбрать поддержку .data, но не .bss, или вы можете полностью поддерживает как относительно простой скрипт компоновщика, так и bootstrap. У вас есть место на этом mcu, вам действительно нужно спроектировать стек в скрипт компоновщика? Вы знаете, насколько велика эта часть, просто сделайте стек сверху вниз. (если вам нужно набрать размер только один раз, если вы сделаете компоновщик волхвов c) На ваш выбор. Если по какой-то причине вы хотите поддерживать кучу (почему у вас когда-нибудь будет куча на mcu? Не очень хорошая вещь), вы можете добавить это и в скрипт компоновщика.
Опять красота голого металла, если он работает, вы можете делать все, что захотите. Я рекомендую выйти за рамки того, что сделали эти люди, и немного лучше изучить инструменты (в первую очередь на языке ассемблера), чтобы у вас было больше выбора относительно того, как вы это делаете.
Почему обе работы заключаются в том, что часть зеркально отображает часть / все адресное пространство 0x08000000 в 0x00000000. поэтому связь с любым из них будет работать в пределах окна.
Вы можете выбрать, что пометить этим, я использую термин адресное пространство руки, я бы также использовал термин физический адрес, немногие, если какое-либо из этих ядер имеет пространство виртуальной памяти , так что это не имеет смысла. Шина ARM от ARM IP (рука не производит микросхемы, она заставляет ядра, которые такие компании, как ST, покупать и выкладывать свои собственные или другие логики c, чтобы сделать чип), будет отправлять чтение с одним из этих физических адресов на То, как реагирует чип, зависит от того, как они его разработали. Записи в таблице векторов находятся по известным адресам, что означает, что logi c будет использовать известный адрес для чтения каждого элемента, а чип и программист должны ответить, если существует MMU, который может изменить адресное пространство, вектор таблица по-прежнему должна находиться по одному из этих физических адресов, если бы обработчик logi c проходил через mmu.
Поэтому, учитывая тест с множественным выбором, я бы сказал, логический адрес памяти, LMA.
Следующая вещь здесь - openocd поддерживает запись в 0x00000000. openocd, поддерживающий fla sh пишет вообще, является бонусом, так как это спецификация чипа c, и кто-то должен положить время. Из-за природы 0x00000000 для этих частей и того, как вы включили его (контакты-ремешки), вы можете неправильно связать его, и / или в реализации openocd есть предположение или определение, которое всегда превращает 0x00000000 в 0x08000000 или что-то подобное, может находиться в самом файле .cfg, который я недавно просматривал для вас, но не искал эту деталь.