Так что это вдохновило меня попробовать clang / llvm после нескольких лет перерыва ...
Теперь я на linux не windows, но вы должны быть в состоянии адаптироваться к windows ( или, конечно, двойную загрузку linux или поместите linux в виртуальную машину или что-то еще.
, полученное из инструкций по сборке на сайтах clang / llvm
rm -rf /opt/llvmv6m
rm -rf llvm-project
git clone https://github.com/llvm/llvm-project.git
cd llvm-project
mkdir build
cd build
cmake -DLLVM_ENABLE_PROJECTS=clang -DCMAKE_CROSSCOMPILING=True -DCMAKE_INSTALL_PREFIX=/opt/llvmv6m -DLLVM_DEFAULT_TARGET_TRIPLE=armv6m-none-eabi -DLLVM_TARGET_ARCH=ARM -DLLVM_TARGETS_TO_BUILD=ARM -G "Unix Makefiles" ../llvm
make
sudo make install
Это как Я построил это. Да, я знаю, что ваш cortex-m4 поддерживает все cortex-ms (пока что) armv6-m, вы можете легко сделать это armv7m. Был эксперимент, основанный на этих веб-страницах, и, что интересно, теперь мне не нужно указывать какие-либо вещи в командной строке, чтобы указать архитектуру или процессор, любопытно узнать, по-прежнему ли это универсальный кросс-компилятор c clang, а armv6m - просто по умолчанию. Во всяком случае ...
Это немного сложнее, чем простой бесконечный l oop, но играть с функциями llvm, которые вы не получаете в GNU.
start.s
.thumb
.cpu cortex-m0
.globl _start
_start:
.word 0x20001000
.word reset
.word loop
.word loop
.thumb_func
reset:
bl notmain
.thumb_func
loop:
b .
notmain. c
unsigned int fun ( void );
unsigned int notmain ( void )
{
return(fun());
}
fun. c
unsigned int fun ( void )
{
return(5);
}
memmap
MEMORY
{
rom : ORIGIN = 0x08000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
}
Makefile
all :
arm-none-eabi-as start.s -o start.o
clang -O2 -fomit-frame-pointer -c notmain.c -o notmain.o
clang -O2 -fomit-frame-pointer -c fun.c -o fun.o
arm-none-eabi-ld -T memmap start.o notmain.o fun.o -o basic.elf
arm-none-eabi-objdump -D basic.elf > basic.list
clang -fomit-frame-pointer -c -emit-llvm notmain.c -o notmain.bc
clang -fomit-frame-pointer -c -emit-llvm fun.c -o fun.bc
llc $(LLCOPS) notmain.bc -filetype=obj -o notmain.not.o
llc $(LLCOPS) fun.bc -filetype=obj -o fun.not.o
arm-none-eabi-ld -T memmap start.o notmain.not.o fun.not.o -o not.elf
arm-none-eabi-objdump -D not.elf > not.list
llvm-link notmain.bc fun.bc -o notmain.not.bc
opt -O2 notmain.not.bc -o notmain.opt.bc
llc $(LLCOPS) notmain.opt.bc -filetype=obj -o notmain.opt.o
arm-none-eabi-ld -T memmap start.o notmain.opt.o -o opt.elf
arm-none-eabi-objdump -D opt.elf > opt.list
clean:
rm -f *.S
rm -f *.o
rm -f *.list
rm -f *.elf
rm -f *.bc
basi c .list
Disassembly of section .text:
08000000 <_start>:
8000000: 20001000 andcs r1, r0, r0
8000004: 08000011 stmdaeq r0, {r0, r4}
8000008: 08000015 stmdaeq r0, {r0, r2, r4}
800000c: 08000015 stmdaeq r0, {r0, r2, r4}
08000010 <reset>:
8000010: f000 f802 bl 8000018 <notmain>
08000014 <loop>:
8000014: e7fe b.n 8000014 <loop>
...
08000018 <notmain>:
8000018: b580 push {r7, lr}
800001a: f000 f801 bl 8000020 <fun>
800001e: bd80 pop {r7, pc}
08000020 <fun>:
8000020: 2005 movs r0, #5
8000022: 4770 bx lr
not.list
Disassembly of section .text:
08000000 <_start>:
8000000: 20001000 andcs r1, r0, r0
8000004: 08000011 stmdaeq r0, {r0, r4}
8000008: 08000015 stmdaeq r0, {r0, r2, r4}
800000c: 08000015 stmdaeq r0, {r0, r2, r4}
08000010 <reset>:
8000010: f000 f802 bl 8000018 <notmain>
08000014 <loop>:
8000014: e7fe b.n 8000014 <loop>
...
08000018 <notmain>:
8000018: b580 push {r7, lr}
800001a: f000 f801 bl 8000020 <fun>
800001e: bd80 pop {r7, pc}
08000020 <fun>:
8000020: 2005 movs r0, #5
8000022: 4770 bx lr
opt.list
Disassembly of section .text:
08000000 <_start>:
8000000: 20001000 andcs r1, r0, r0
8000004: 08000011 stmdaeq r0, {r0, r4}
8000008: 08000015 stmdaeq r0, {r0, r2, r4}
800000c: 08000015 stmdaeq r0, {r0, r2, r4}
08000010 <reset>:
8000010: f000 f802 bl 8000018 <notmain>
08000014 <loop>:
8000014: e7fe b.n 8000014 <loop>
...
08000018 <notmain>:
8000018: b580 push {r7, lr}
800001a: f000 f802 bl 8000022 <fun>
800001e: 2005 movs r0, #5
8000020: bd80 pop {r7, pc}
08000022 <fun>:
8000022: 2005 movs r0, #5
8000024: 4770 bx lr
Самое интересное, что вы можете оптимизировать файлы / объекты, которые вы не можете сделать с помощью инструментов gnu AFAIK. Вау, на самом деле LLVM проделал очень плохую работу, и там пришлось разобраться с этим.
Теперь я использовал компоновщик и ассемблер gnus, все еще не зная, как обойти это, я получаю ошибку при попытке собрать только с clang.
все они достаточно c достаточно для запуска на вашем процессоре, как показано здесь, ключевые ловушки для поиска с новым проектом или инструментом.
08000000 <_start>:
8000000: 20001000
8000004: 08000011
8000008: 08000015
800000c: 08000015
08000010 <reset>:
08000014 <loop>:
для кортекса- Для правильной загрузки и немедленного сбоя в работе, в векторной таблице должен быть установлен lsbit для векторов, начиная с сброса, в этом случае значение сброса равно 0x08000010, поэтому запись в векторной таблице должна быть 0x08000011 для запуска этого кода. и это то, что мы видим здесь, поэтому мы не будем терпеть неудачу из-за этого.
, в то время как у некоторых mcus нет 0x1000 байтов, я полагаю, что у вас их есть, поэтому 0x20001000 является хорошим начальным местом для указателя стека. * Оттуда это снова не просто бесконечное l oop, это более сложно, но это должно работать на вашем процессоре и не давать сбой. Если вы измените его следующим образом:
.thumb
.cpu cortex-m0
.globl _start
_start:
.word 0x20001000
.word reset
.word loop
.word loop
.thumb_func
reset:
mov r0,#0
b reset
.thumb_func
loop:
b .
(если это станет проектом инструмента gnu, а не llvm / clang, какой ассемблер вы используете и какой компоновщик?)
, затем с отладчиком (stlink плюс openocd плюс te lnet) вы можете остановиться, возобновить и исследовать r0, чтобы увидеть, что он работает.
.thumb
.cpu cortex-m0
.globl _start
_start:
.word 0x20001000
.word reset
.word loop
.word loop
.thumb_func
reset:
bl notmain
.thumb_func
loop:
b .
.thumb_func
bounce:
bx lr
void bounce ( unsigned int );
unsigned int notmain ( void )
{
for(ra=0;;ra++) bounce(ra);
return(0);
}
, который добавляет к нему небольшой лязг / llvm и видит, что r0 меняется, если вы остановитесь /resume.
некоторые микросхемы будут проверять наличие векторов, если он видит 0xFFs, а затем может go войти в загрузчик, поэтому с помощью отладчика вы также можете проверить 0x00000000 и 0x08000000, попробуйте сбросить остановку на Командная строка telnet / openocd, а затем mdw 0 20, чтобы увидеть, что процессор увидит по адресу ноль, чтобы увидеть, является ли это вашей векторной таблицей.
Если вы преодолеете эти очень простые, но очень фатальные общие проблемы, тогда Вы можете иметь дело с чем-то еще, например, clang не любит циклы while (1), возможно, они, наконец, исправили эту ошибку, но когда я ее подал, они отказались, так что если есть код, ожидающий выполнения Чтобы изменить это, используется while (1), тогда, возможно, в этом и проблема. После описанного выше, я бы предпринял шаги, добавив одну вещь к основной, так как вы уже пробовали часы, возможно, у вас есть бесконечная функция l oop ((asm)), которую вы вызываете после инициализации часов, и смотрите, работает ли инициализация часов до завершения и возврата к main ().
Используете ли вы clang / llvm для сборки библиотек, которые вы используете, или они предварительно созданы для использования с clang / llvm?
РЕДАКТИРОВАТЬ
Сделано больше, если вышеизложенное относится к кому-либо и не удаляется.
изменить на
-DLLVM_ENABLE_PROJECTS = 'clang; lld'
MEMORY
{
rom : ORIGIN = 0x08000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
/DISCARD/ : {
*(.ARM.exidx*)
}
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
}
и, может быть, еще пара вещей. и теперь разборка похожа на вашу с данными в отдельных байтах с прямым порядком байтов.
Disassembly of section .text:
08000000 _start:
8000000: 00 10 asrs r0, r0, #32
8000002: 00 20 movs r0, #0
8000004: 11 00 movs r1, r2
8000006: 00 08 lsrs r0, r0, #32
8000008: 15 00 movs r5, r2
800000a: 00 08 lsrs r0, r0, #32
800000c: 15 00 movs r5, r2
800000e: 00 08 lsrs r0, r0, #32
08000010 reset:
8000010: 00 f0 02 f8 bl #4
08000014 loop:
8000014: fe e7 b #-4 <loop>
8000016: d4 d4 bmi #-88 <start.c+0x7ffffc2>
08000018 notmain:
8000018: 80 b5 push {r7, lr}
800001a: 00 f0 02 f8 bl #4
800001e: 05 20 movs r0, #5
8000020: 80 bd pop {r7, pc}
08000022 fun:
8000022: 05 20 movs r0, #5
8000024: 70 47 bx lr
Теперь к вашему комментарию о 400 МБ.
0x20000000 - 0x08000000 = 0x18000000 = 402653184.
И это, вероятно, ваша проблема, так что, похоже, у вас есть некоторые данные. .
Позвольте мне начать новый:
start.s
.text
/*.syntax unified*/
.cpu cortex-m0
.code 16
.globl _start
_start:
.word 0x20001000
.word reset
.word loop
.word loop
.thumb_func
reset:
bl notmain
.thumb_func
loop:
b .
notmain. c
unsigned int notmain ( void )
{
return(7);
}
Makefile
all :
clang -c start.s -o start.o
clang -O2 -fomit-frame-pointer -c notmain.c -o notmain.o
ld.lld -T memmap start.o notmain.o -o basic.elf
llvm-objdump -D basic.elf > basic.list
llvm-objcopy -O binary basic.elf basic.bin
clean:
rm -f *.o
rm -f *.list
rm -f *.elf
memmap
MEMORY
{
rom : ORIGIN = 0x08000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
/DISCARD/ : {
*(.ARM.exidx*)
}
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
.data : { *(.data*) } > ram
}
и получается 28-байтовый файл c .bin
08000000 _start:
8000000: 00 10 asrs r0, r0, #32
8000002: 00 20 movs r0, #0
8000004: 11 00 movs r1, r2
8000006: 00 08 lsrs r0, r0, #32
8000008: 15 00 movs r5, r2
800000a: 00 08 lsrs r0, r0, #32
800000c: 15 00 movs r5, r2
800000e: 00 08 lsrs r0, r0, #32
08000010 reset:
8000010: 00 f0 02 f8 bl #4
08000014 loop:
8000014: fe e7 b #-4 <loop>
8000016: d4 d4 bmi #-88 <start.c+0x7ffffc2>
08000018 notmain:
8000018: 07 20 movs r0, #7
800001a: 70 47 bx lr
Теперь давайте добавим .data
unsigned int x = 5;
unsigned int notmain ( void )
{
return(7);
}
теперь моя база c .bin имеет размер 402653188 байт.
В данный момент objcopy создает образ двоичной памяти, который начинается с первого загружаемого или соответствующего пространства и заканчивается последним, поэтому
Disassembly of section .text:
08000000 _start:
8000000: 00 10 asrs r0, r0, #32
8000002: 00 20 movs r0, #0
8000004: 11 00 movs r1, r2
8000006: 00 08 lsrs r0, r0, #32
8000008: 15 00 movs r5, r2
800000a: 00 08 lsrs r0, r0, #32
800000c: 15 00 movs r5, r2
800000e: 00 08 lsrs r0, r0, #32
08000010 reset:
8000010: 00 f0 02 f8 bl #4
08000014 loop:
8000014: fe e7 b #-4 <loop>
8000016: d4 d4 bmi #-88 <start.c+0x7ffffc2>
08000018 notmain:
8000018: 07 20 movs r0, #7
800001a: 70 47 bx lr
Disassembly of section .data:
20000000 x:
20000000: 05 00 movs r5, r0
20000002: 00 00 movs r0, r0
от 0x08000000 до 0x20000002 включительно
0x20000003 - 0x08000000 = 402653187, поэтому они дополняют его до ближайшего слова (или полуслово).
вы не можете загрузить это в свой микроконтроллер, оно не будет работать в любом случае, ваша программа должна находиться в энергонезависимой памяти ... fla sh ...
первый шаг:
MEMORY
{
rom : ORIGIN = 0x08000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
/DISCARD/ : {
*(.ARM.exidx*)
}
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
.data : { *(.data*) } > ram AT > rom
}
изменив его на ram AT rom.
файл basi c .bin теперь составляет 32 байта.
00000000 00 10 00 20 11 00 00 08 15 00 00 08 15 00 00 08 |... ............|
00000010 00 f0 02 f8 fe e7 d4 d4 07 20 70 47 05 00 00 00 |......... pG....|
00000020
Disassembly of section .text:
08000000 _start:
8000000: 00 10 asrs r0, r0, #32
8000002: 00 20 movs r0, #0
8000004: 11 00 movs r1, r2
8000006: 00 08 lsrs r0, r0, #32
8000008: 15 00 movs r5, r2
800000a: 00 08 lsrs r0, r0, #32
800000c: 15 00 movs r5, r2
800000e: 00 08 lsrs r0, r0, #32
08000010 reset:
8000010: 00 f0 02 f8 bl #4
08000014 loop:
8000014: fe e7 b #-4 <loop>
8000016: d4 d4 bmi #-88 <start.c+0x7ffffc2>
08000018 notmain:
8000018: 07 20 movs r0, #7
800001a: 70 47 bx lr
Disassembly of section .data:
20000000 x:
20000000: 05 00 movs r5, r0
20000002: 00 00 movs r0, r0
обратите внимание на конец двоичного файла:
70 47 05 00 00 00
у него есть последний элемент .text 70 47, а затем элемент .data.
и пусть инструменты сделают всю работу за вас
MEMORY
{
rom : ORIGIN = 0x08000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
/DISCARD/ : {
*(.ARM.exidx*)
}
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
__data_rom_start__ = .;
.data : {
__data_start__ = .;
*(.data*)
} > ram AT > rom
__data_end__ = .;
__data_size__ = __data_end__ - __data_start__;
}
basi c .bin все еще в настоящее время 32 байта, но
llvm-nm basic.elf
20000004 D __data_end__
0800001c T __data_rom_start__
00000004 A __data_size__
20000000 D __data_start__
08000000 T _start
08000014 t loop
08000018 T notmain
08000010 t reset
20000000 D x
теперь мы знаем, что в fla sh по адресу 0x0800001 c начинается встроенный .data, его размер составляет 4 байта, а его назначение в оперативной памяти равно 0x20000000, поэтому теперь код bootstrap может скопировать .data из fla sh в оперативную память перед вызовом C точка входа.
Теперь вы уже сделали все это, и я предполагаю, что знали все это относительно сценариев компоновщика и bootstrap, но вы получаете тот двоичный файл 400 МБ, который указывает, что что-то есть еще утечка в адресное пространство оперативной памяти.
Изучите выходные данные дизассемблирования (objdump -D) и .or readelf и / или nm, чтобы выяснить, что там, и добавьте его в скрипт компоновщика вместе с bootstrap код для его копирования.
добавление .bss
unsigned int x = 5;
unsigned int y;
unsigned int notmain ( void )
{
return(7);
}
из objdump
Disassembly of section .bss:
20000000 y:
...
Disassembly of section .data:
20000004 x:
20000004: 05 00 movs r5, r0
20000006: 00 00 movs r0, r0
из readelf
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x001000 0x08000000 0x08000000 0x0001c 0x0001c R E 0x1000
LOAD 0x002000 0x20000000 0x20000000 0x00000 0x00004 RW 0x1000
LOAD 0x002004 0x20000004 0x0800001c 0x00004 0x00004 RW 0x1000
.bss one выглядит немного страшно, но это не заканчивается в двоичном файле, который снова 32 б ytes. Но мы видим здесь, что .data физически находится во флаге sh, но хочет быть в оперативной памяти, что мы и хотим для этого типа платформы. Возможно, из readelf вы можете найти утечку в оперативную память.
Ваш двоичный вывод objcopy -O должен соответствовать fla sh и содержать 100% вашей программы и данных, иначе он не будет работать, если вы извлечете только fla sh часть этого 400-мегабайтного файла будет или может быть какие-то элементы данных, которых там не должно быть, и ожидается, что программное обеспечение будет там работать. Или, может быть, это какая-то глупая строковая таблица или какой-то другой элемент, который на самом деле не предназначен для двоичного файла, но в нем есть имя раздела, которое пока не обрабатывается в сценарии компоновщика.
Извините, 400 МБ должно было быть очевидно для я с самого начала, еще одна распространенная ловушка сценария компоновщика при подготовке нового проекта. Лично я никогда не использую .data и не полагаюсь на .bss, поэтому у меня нет этих проблем, кроме YMMV, но я все еще об этом знаю. (веселее, когда у вас .text на 0 и ram на 0x80000000 или даже выше, вы получаете файлы размером в гигабайт)