Итак, что я выяснил у вас до сих пор, так это то, что вы купили / приобрели эту часть, положили ее на разделочную доску. Подайте питание и заземление, добавьте светодиод и резистор и подключите stlink. Могу использовать CubeMX и заставить его работать, используя Kiel.
Так что я сделал так, что многие разделительные доски поместили светодиоды и тому подобное на плату, потому что мне надоело подключать элементы отдельно. Части, которые я использовал, вам понадобились, чтобы убедиться, что VDD и VDDA были подключены, но у вас один и тот же контакт, проверьте. VDD и VSS без сомнения, если у вас это работает. NRST подтянулся для хорошей меры, хотя я думаю, что не требуется, поскольку есть внутреннее подтягивание, но BOOT0 действительно требовал понижения, но это STM32G, и вы указали, что SWCLK и BOOT0 имеют один и тот же вывод. ST, к сожалению, уходит от встроенного загрузчика чипа или, по крайней мере, отключен на заводе
ST. Производственное значение: 0xDFFF E1AA
Бит 24 nBOOT_SEL
0 : Сигнал BOOT0 определяется значением контакта BOOT0 (традиционный режим)
1: Сигнал BOOT0 определяется параметром nBOOT0, бит
Таким образом, при поставке новая деталь BOOT0 не является чем-то, что вы можете положитесь на загрузчик и используйте решение uart для загрузки кода во флаг sh, и при этом вы не можете использовать его для того, чтобы не быть лишенным кирпича при выполнении этого уровня работы.
Таким образом, stlink подключен к вам сказал, что Киль может поговорить с этой частью, так что в теории все в порядке, а не проблема.
У меня нет Киля под рукой, но каждый может получить кросс-компилятор GNU или собрать его из исходников.
apt-get install binutils-arm-linux-gnueabi gcc-arm-linux-gnueabi
Приведенный ниже код не заботится о вариациях arm-non-eabi- vs arm- linux -gnueabi- кросс-компилятора, он не зависит от этих различий, ему просто нужен компилятор компилятора и компоновщик . * 1 022 *
Теперь это, вероятно, снова приведет к личной битве с некоторыми другими пользователями SO. Работайте сквозь шум. Я специально избегаю CMSIS, я видел реализацию, и вы должны проверить ее, так как сейчас вы не хотите добавлять этот риск в свой код, удалите его и добавьте его позже по желанию. Это мой стиль, он специально контролирует инструкции, используемые для доступа, все основано на большом опыте, даже если вы этого не видите, и создан для того, чтобы читатель имел большие шансы на успех. Сделайте свой собственный, если / когда вы заставите это работать и / или побочные комментарии, которые являются моей настоящей целью, могут помочь вам изучить бинарный файл, который вы строите с помощью своего собственного инструмента, чтобы устранить распространенные ловушки.
Это не просто случай получения кода C в main () для правильного использования кода без кода, вам нужно, чтобы все было от перезагрузки до правого.
Fla sh основанная версия:
fla sh .s
.cpu cortex-m0
.thumb
.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.thumb_func
reset:
bl notmain
b hang
.thumb_func
hang: b .
.thumb_func
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.thumb_func
.globl GET32
GET32:
ldr r0,[r0]
bx lr
.thumb_func
.globl dummy
dummy:
bx lr
notmain. c
void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void dummy ( unsigned int );
#define RCC_BASE 0x40021000
#define RCC_IOPENR (RCC_BASE+0x34)
#define GPIOA_BASE 0x50000000
#define GPIOA_MODER (GPIOA_BASE+0x00)
#define GPIOA_OTYPER (GPIOA_BASE+0x04)
#define GPIOA_BSRR (GPIOA_BASE+0x18)
#define DCOUNT 2000000
int notmain ( void )
{
unsigned int ra;
unsigned int rx;
ra=GET32(RCC_IOPENR);
ra|=1<<0; //enable port a
PUT32(RCC_IOPENR,ra);
ra=GET32(GPIOA_MODER);
ra&=~(3<<(5<<1)); //clear bits 10,11
ra|= (1<<(5<<1)); //set bit 10
PUT32(GPIOA_MODER,ra);
ra=GET32(GPIOA_OTYPER);
ra&=~(1<<5); //clear bit 5
PUT32(GPIOA_OTYPER,ra);
for(rx=0;;rx++)
{
PUT32(GPIOA_BSRR, (1<<(5+ 0)) );
for(ra=0;ra<DCOUNT;ra++) dummy(ra);
PUT32(GPIOA_BSRR, (1<<(5+16)) );
for(ra=0;ra<DCOUNT;ra++) dummy(ra);
}
return(0);
}
fla sh .ld
MEMORY
{
rom : ORIGIN = 0x08000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
}
build
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m0 flash.s -o flash.o
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mcpu=cortex-m0 -mthumb -c notmain.c -o notmain.o
arm-none-eabi-ld -o notmain.elf -T flash.ld flash.o notmain.o
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy notmain.elf notmain.bin -O binary
Опять вы можете заменить arm-none-eabi на arm- linux -gnueabi, если это то, что у вас есть / найдено. Этот код не заботится о различиях.
Дело в том, что процессор загружается:
Disassembly of section .text:
08000000 <_start>:
8000000: 20001000 andcs r1, r0, r0
8000004: 08000011 stmdaeq r0, {r0, r4}
8000008: 08000017 stmdaeq r0, {r0, r1, r2, r4}
800000c: 08000017 stmdaeq r0, {r0, r1, r2, r4}
08000010 <reset>:
8000010: f000 f808 bl 8000024 <notmain>
8000014: e7ff b.n 8000016 <hang>
08000016 <hang>:
8000016: e7fe b.n 8000016 <hang>
Приложение fla sh начинается с 0x08000000 в области памяти ARM, называется Main Fla sh Memory в справочном руководстве. В зависимости от настроек загрузочного ремешка 0x08000000 будет зеркально отображаться в 0x00000000, как указано в руководствах по ARM, именно здесь находится таблица векторов. Первое слово - это значение, загружаемое в указатель стека при сбросе, слово по адресу 0x00000004 (которое будет зеркально отображено на 0x08000004) - это вектор сброса.
Выше использовался дизассемблер, поэтому он пытается разобрать те значения как инструкции они являются значениями / векторами игнорируют разборку для этой таблицы.
Если предположить, что мы можем получить инструменты для помещения этого двоичного файла во флаг sh в нужном месте, то
08000000 <_start>:
8000000: 20001000 value loaded into sp on reset
8000004: 08000011 reset vector
Вектор сброса - это адрес кода, который должен быть выполнен для этого исключения с lsbit, установленным для указания режима большого пальца, lsbit удаляется, он не go в p c. Таким образом, адрес вектора сброса здесь равен 0x08000010, что является правильным:
08000010 <reset>:
8000010: f000 f808 bl 8000024 <notmain>
8000014: e7ff b.n 8000016 <hang>
И может следовать за этим, чтобы не существовать, имя точки входа C не важно, и некоторые инструменты добавят дополнительный материал, который он видит label main (), не видел ни одного из них в течение многих лет, но продолжайте делать это, чтобы также доказать, что это не имеет значения.
Так что, если это помещено в main fla sh по адресу arm 0x08000000, тогда этот код будет загружаться и запускаться до кода C.
Примечание. Sram начинается с 0x20000000, а RM показывает, что эта часть имеет 32 МБайт sram, поэтому у него есть по крайней мере 0x1000 байт, чтобы покрыть этот проект большим количеством дополнительной комнаты.
8000026: 481b ldr r0, [pc, #108] ; (8000094 <notmain+0x70>)
8000028: f7ff fff8 bl 800001c <GET32>
800002c: 2101 movs r1, #1
800002e: 4301 orrs r1, r0
8000030: 4818 ldr r0, [pc, #96] ; (8000094 <notmain+0x70>)
8000032: f7ff fff1 bl 8000018 <PUT32>
...
8000094: 40021034 andmi r1, r2, r4, lsr r0
Будь то, как я запрограммировал или через вашу программу и заголовки CMSIS или HAL, вы должны увидеть, что 0x40021034 используется в той или иной форме. Обратите внимание, что эта ваша часть - cortex-m0 +, поэтому она имеет только ограниченное количество расширений thumb2. Обратите внимание, что bl - это две отдельные 16 инструкций, которые могут быть разнесены, но почти всегда находятся в паре, это две инструкции, Остальные инструкции должны быть 16-битными, если вы видите что-то .w в разборке или в инструкциях, отличных от bl 32 или 16 * 2 битами, то это может быть инструкция thumb2, которая не будет работать на этом процессоре и может быть некоторые настройки, которые вы использовали при создании этого кода, вы можете увидеть с помощью этой цепочки инструментов, которую я специально назвал m0, которая фактически совпадает с m0 + с точки зрения набора команд (архитектура armv6-m). Вам не нужен armv7-m для этого чипа, он не будет работать, в armv7-m примерно 100 инструкций, которые не будут работать на чипах на базе armv6-m.
Орринг бит в регистре разрешения ввода-вывода должен напоминать чтение (ldr) из 0x40021034, модификацию чтения значения и запись (str) по тому же адресу.
Ваш опубликованный код работал бы на других частях STM32, так как многие из них инициализируют регистр MODER (если эта часть использует этот тип периферийного устройства GPIO) для нулей для большинства выводов, которые вводятся. В этой части описывается, что большинство выводов сбрасываются на 0b11, что является аналоговым режимом, любопытно, почему, но не важно.
Сброс:
0xEBFF FFFF для порта A
0xFFFF FFFF для других портов
, поэтому вы не можете просто установить один из двух битов, чтобы изменить режим, если биты начинаются с 0b00, тогда можно установить его в 0b01, но для этой части вы можете либо просто сбросьте бит 11, либо лучше управляйте обоими битами и не полагайтесь на состояние сброса, поэтому очистите два бита и установите один из них или сбросьте один и установите другой
5 << 1 означает 5 смещенных влево на один 0b101 сдвиг нуля справа дает 0b1010, который является 0xA, который равен 10, это визуальный способ увидеть, что я связываюсь с PA5, и число 5 есть, но для этого регистра настройки режима вывода вывода 5 - это биты 10 и 11 . 3 << (5 << 1) означает 3 << 10, что является битами 10 и 11. Тильда означает инвертирование всего, поэтому 00000C00 - это инверсия 3 << 10, в результате которой вы получите FFFFF3FF, который с нулевым значением модера будет равен нулю. немного s 10 и 11. теперь orr с 00000400 1 << 10 для установки бита 10. </p>
Мы хотим, чтобы выход хотя бы на данный момент был пу sh -пулл не открытым стоком, так что даже при значении сброса это уже пу sh -пул, я проясняю это для хорошей меры. Теперь я обычно не беспокоюсь о подтягивании или другом регистре настройки gpio, я связываюсь с этими двумя MODER и OTYPER для частей STM32, которые используют это периферийное устройство GPIO (вы увидите, что не все части STM32 используют один и тот же IP, STM32F103 например, используйте другой.
Таким образом, каким-то образом убедитесь, что CMSIS или нет, что созданный код работает с этими регистрами. Из документации GPIOA начинается с 0x50000000, поэтому регистры 0x50000000 и 0x50000004.
Поскольку эта часть имеет регистр GPIO BSRR, это хорошая функция, просто используйте ее сейчас, чтобы случайно не связываться с другими выводами.
Пустышка l oop сжигает время, так что в этом случае светодиод мигает, и вы должны настроить DCOUNT на основе тактовых импульсов, используемых для процессора, когда вы работаете не слишком быстро, не слишком медленно, просто правильно. Делая это таким образом с внешней функцией, это уже не мертвый код (для (ra = 0; ra
Нет, код на самом деле не возвращает return (0); некоторые компиляторы не настолько умны и недовольны. (Некоторые настолько умны) и жалуйтесь, что вы не можете туда добраться, YMMV) * 1089 *
Все эти части должны быть на месте, чтобы иметь хотя бы половину шансов на эту работу. Это не просто несколько строк кода C.
С помощью stlink инструменты kiel в порядке, и я надеюсь, что есть способ проверить объем памяти, вы захотите изучить 0x08000000 и сравнить его с двоичным файлом, сгенерированным инструментом, и, надеюсь, есть способ проверить вывод инструмента, а также посмотреть, что он построил, это легко сделать с помощью gnu.
вы можете использовать openocd вместо kiel для загрузки и изучения вещей из командной строки, это будет что-то в форме
openocd -f stlink.cfg -f target.cfg
и затем в другом окне
telnet localhost 4444
GDB добавляет намного больше неизвестных ...
тогда вы можете использовать
mdw 0x08000000 40
В те lnet ветер Теперь мы увидим, что находится в этом главном флаге sh, а затем сравним его с загружаемой частью двоичного файла, чтобы увидеть, действительно ли ваша программа находится там, если вашей программы на самом деле нет, то независимо от того, что вы делаете с C код не заставит его мигать.
Есть способы использовать openocd для указания sh деталей, но это очень специфично для поставщика / детали c, так как они должны добавить эту возможность в openocd, и вы должны иметь правильную версию, из памяти это что-то вроде
flash write_image erase notmain.elf
, если используется «двоичный» с адресной информацией в нем, если вы используете образ памяти, то вам нужно поставить адрес на эта командная строка 0x08000000
Некоторые части заблокированы или, скажем, доски, такие как синие таблетки, где это не работает, девственные детали Я не знаю, видел ли я заблокированные, вы купили незакрепленные детали, так что они не должны быть заблокирован.
Если у вас работает openocd и gnu, вы также можете попробовать использовать sram, не имея изначально поддержки fla sh.
sram.s
.cpu cortex-m0
.thumb
.thumb_func
.global _start
_start:
ldr r0,=0x20001000
mov sp,r0
bl notmain
b .
.thumb_func
.globl PUT32
PUT32:
str r1,[r0]
bx lr
.thumb_func
.globl GET32
GET32:
ldr r0,[r0]
bx lr
.thumb_func
.globl dummy
dummy:
bx lr
sram.ld
MEMORY
{
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > ram
.rodata : { *(.rodata*) } > ram
.bss : { *(.bss*) } > ram
}
, так как эта часть использует таблицу векторов, и то, что собирается описать, использует отладчик для размещения и запустить программу в sram, volatile, поэтому при сбросе / перезагрузке она теряется, но она дает возможность экспериментировать без необходимости писать fla sh.
мы скажем отладчику начать выполнение в 0x20000000, поэтому мы хотим, чтобы там была инструкция, а не таблица векторов.
arm-none-eabi-as --warn --fatal-warnings -mcpu=cortex-m0 sram.s -o sram.o
arm-none-eabi-ld -o notmain.elf -T sram.ld sram.o notmain.o
arm-none-eabi-objdump -D notmain.elf > notmain.list
arm-none-eabi-objcopy notmain.elf notmain.bin -O binary
всегда проверяйте свой двоичный файл на новом проекте перед запуском
Disassembly of section .text:
20000000 <_start>:
20000000: 4804 ldr r0, [pc, #16] ; (20000014 <dummy+0x2>)
20000002: 4685 mov sp, r0
20000004: f000 f808 bl 20000018 <notmain>
20000008: e7fe b.n 20000008 <_start+0x8>
2000000a <PUT32>:
2000000a: 6001 str r1, [r0, #0]
2000000c: 4770 bx lr
2000000e <GET32>:
2000000e: 6800 ldr r0, [r0, #0]
20000010: 4770 bx lr
20000012 <dummy>:
20000012: 4770 bx lr
20000014: 20001000 andcs r1, r0, r0
20000018 <notmain>:
20000018: b570 push {r4, r5, r6, lr}
, и это выглядит хорошо.
с openocd теперь вы можете
сбросить остановку load_image notmain.elf резюме 0x20000000
для запуска программы (может потребоваться путь, если вы запустите openocd в каталоге, где находится elf файл и / или вы копируете файл elf в каталог, в котором вы запустили openocd (не te lnet, openocd), тогда вам обычно не нужно указывать путь.
это в sram, а не fla sh так может работать быстрее и может захотеть большее значение задержки l oop.
Если вы просто хотите сделать вывод высоким или низким, тогда просто используйте нужную строку bsrr и избавьтесь от циклов, этот код, как написано, помещает вас в безопасное бесконечное l oop, когда вы возвращаетесь из notmain тот, который не будет мешать работе порта gpio. В рамках вашего исследования бинарного файла, который вы строите с помощью своего инструмента, вам нужно подтвердить, что хотя размещенный вами l oop на самом деле не мертвый код и был реализован (clang имеет было известно, что это мертвый код, так что другие тоже могут это сделать), и некоторые песочницы отменяют вещи, когда вы возвращаетесь из main, поэтому может случиться так, что ваш код теперь в порядке, но выходит из main, и bootstrap отменяет то, что вы сделали с PA5 быстрее, чем Вы можете видеть это.
Это все, что я могу сделать до сих пор, у меня есть часть stm32 cortex-m0 + с работающей конфигурацией openocd, если это помогает, это другая часть, но ядро такое же, если нет другого касания, тогда он должен просто работать, но Вы никогда не знаете.
Может изменить этот ответ, основываясь на дополнительной информации от вас или результатах экспериментов.
Короткий ответ, ваш код модера не сработал бы, иначе он выглядел бы хорошо, но C Код это только часть истории, необходимой для успеха. В этом длинном ответе освещаются основные моменты, которые необходимо учитывать при загрузке и настройке светодиодов. Возможно, что мы оба пропустили дополнительное включение, у меня нет этой части специально, поэтому я не могу на самом деле вытащить один и запустить этот код на нем. Пу sh подходит, чтобы засунуть, я мог бы получить один и сделать доску, и т. Д. c, но это было бы через несколько недель ...