我试图为STM32F030F4制作一个简单的闪烁程序(对于整个STM32F0系列来说,它可能是相同的)。我尽量避免使用HAL和设置任何不必要的东西,但我无法让它发挥作用。
硬件和工具链运行良好,问题似乎出在程序本身。
这是代码:
/*Include definitions for core and peripheral registers*/
#include <core_cm0.h>
#include <stm32f030x6.h>
/*This function launches first after reset*/
void SystemInit (void)
{
RCC -> AHBENR |= RCC_AHBENR_GPIOAEN; //Enable clock for IO port A
GPIOA -> MODER |= GPIO_MODER_MODER4_0; //A4 to Push-Pull
}
/*Simple delay procedure*/
void wait (int x)
{
while (x--); //Delay by wasting cycles
}
/*Launches right after SystemInit()*/
int main (void)
{
while (1) //Repeat forever
{
GPIOA -> BSRR = GPIO_BSRR_BS_4; //Set A4 to HIGH
wait(10000); //Waste 1e4 cycles
GPIOA -> BSRR = GPIO_BSRR_BR_4; //Set A4 to LOW
wait(10000); //Waste again.
}
}
我可能错过了什么?
也许这里的一些东西会有所帮助,裸金属根本不使用他们的工具,任何(很多/大多数?)gnu-arm工具链都应该工作。
反汇编程序是你的朋友,你想赤手空拳,不使用他们的沙箱或工具,然后要启动它,你需要进行反汇编,以节省调试时间。
这会闪烁pa4和5,您可以根据需要进行调整。
闪烁器01.c
void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void dummy ( unsigned int );
#define GPIOABASE 0x48000000
#define RCCBASE 0x40021000
int notmain ( void )
{
unsigned int ra;
unsigned int rx;
ra=GET32(RCCBASE+0x14);
ra|=1<<17; //enable port a
PUT32(RCCBASE+0x14,ra);
//moder
ra=GET32(GPIOABASE+0x00);
ra&=~(3<<8); //PA4
ra&=~(3<<10); //PA5
ra|=1<<8; //PA4
ra|=1<<10; //PA5
PUT32(GPIOABASE+0x00,ra);
//OTYPER
ra=GET32(GPIOABASE+0x04);
ra&=~(1<<4); //PA4
ra&=~(1<<5); //PA5
PUT32(GPIOABASE+0x04,ra);
//ospeedr
ra=GET32(GPIOABASE+0x08);
ra|=3<<8; //PA4
ra|=3<<10; //PA5
PUT32(GPIOABASE+0x08,ra);
//pupdr
ra=GET32(GPIOABASE+0x0C);
ra&=~(3<<8); //PA4
ra&=~(3<<10); //PA5
PUT32(GPIOABASE+0x0C,ra);
for(rx=0;;rx++)
{
PUT32(GPIOABASE+0x18,(1<<5)|(1<<4));
for(ra=0;ra<200000;ra++) dummy(ra);
PUT32(GPIOABASE+0x18,(1<<(5+16))|(1<<(4+16)));
for(ra=0;ra<200000;ra++) dummy(ra);
}
return(0);
}
flash的
;@-----------------------
.cpu cortex-m0
.thumb
;@-----------------------
.thumb_func
.global _start
_start:
stacktop: .word 0x20001000
.word reset
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.word hang
.thumb_func
reset:
bl notmain
b hang
.thumb_func
hang: b .
;@-----------------------
.align
;@-----------------------
.thumb_func
.globl PUT16
PUT16:
strh r1,[r0]
bx lr
;@-----------------------
.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
;@-----------------------
.end
;@-----------------------
sram的
;@-----------------------
.cpu cortex-m0
.thumb
;@-----------------------
.thumb_func
.global _start
_start:
ldr r0,stacktop
mov sp,r0
bl notmain
b hang
.thumb_func
hang: b .
;@-----------------------
.align
stacktop: .word 0x20001000
;@-----------------------
.thumb_func
.globl PUT16
PUT16:
strh r1,[r0]
bx lr
;@-----------------------
.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
;@-----------------------
.end
;@-----------------------
flash.ld
MEMORY
{
ram : ORIGIN = 0x08000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > ram
.rodata : { *(.rodata*) } > ram
.bss : { *(.bss*) } > ram
}
sram.ld
MEMORY
{
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > ram
.rodata : { *(.rodata*) } > ram
.bss : { *(.bss*) } > ram
}
制作gnu工具或clang+llvm+gnu-ld文件。
用任何交叉编译器替换ARMGNU。
ARMGNU = arm-none-eabi
#ARMGNU = arm-linux-gnueabi
AOPS = --warn --fatal-warnings -mcpu=cortex-m0
COPS = -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mcpu=cortex-m0
LOPS = -Wall -m32 -emit-llvm -target arm-none-eabi -mcpu=cortex-m0 -mthumb
LLCOPS = -march=thumb -mcpu=cortex-m0
#LLCOPS = -mcpu=cortex-m0
COPS = -Wall -O2 -nostdlib -nostartfiles -ffreestanding
OOPS = -std-compile-opts
gcc : blinker01.gcc.thumb.flash.bin blinker01.gcc.thumb.sram.bin
all : gcc clang
clang : blinker01.clang.thumb.norm.flash.bin blinker01.clang.thumb.opt.flash.bin blinker01.clang.thumb.norm.sram.bin blinker01.clang.thumb.opt.sram.bin
clean:
rm -f *.bin
rm -f *.o
rm -f *.elf
rm -f *.list
rm -f *.bc
rm -f *.opt.s
rm -f *.norm.s
#---------------------------------
flash.o : flash.s
$(ARMGNU)-as $(AOPS) flash.s -o flash.o
sram.o : sram.s
$(ARMGNU)-as $(AOPS) sram.s -o sram.o
blinker01.gcc.thumb.o : blinker01.c
$(ARMGNU)-gcc $(COPS) -mthumb -c blinker01.c -o blinker01.gcc.thumb.o
blinker01.gcc.thumb.flash.bin : flash.ld flash.o blinker01.gcc.thumb.o
$(ARMGNU)-ld -o blinker01.gcc.thumb.flash.elf -T flash.ld flash.o blinker01.gcc.thumb.o
$(ARMGNU)-objdump -D blinker01.gcc.thumb.flash.elf > blinker01.gcc.thumb.flash.list
$(ARMGNU)-objcopy blinker01.gcc.thumb.flash.elf blinker01.gcc.thumb.flash.bin -O binary
blinker01.gcc.thumb.sram.bin : sram.ld sram.o blinker01.gcc.thumb.o
$(ARMGNU)-ld -o blinker01.gcc.thumb.sram.elf -T sram.ld sram.o blinker01.gcc.thumb.o
$(ARMGNU)-objdump -D blinker01.gcc.thumb.sram.elf > blinker01.gcc.thumb.sram.list
$(ARMGNU)-objcopy blinker01.gcc.thumb.sram.elf blinker01.gcc.thumb.sram.bin -O binary
#---------------------------------
blinker01.clang.bc : blinker01.c
clang $(LOPS) -c blinker01.c -o blinker01.clang.bc
blinker01.clang.thumb.norm.flash.bin : flash.ld flash.o blinker01.clang.bc
#llc $(LLCOPS) blinker01.clang.bc -o blinker01.clang.thumb.norm.s
#$(ARMGNU)-as $(AOPS) blinker01.clang.thumb.norm.s -o blinker01.clang.thumb.norm.o
llc $(LLCOPS) blinker01.clang.bc -filetype=obj -o blinker01.clang.thumb.norm.o
$(ARMGNU)-ld -o blinker01.clang.thumb.norm.flash.elf -T flash.ld flash.o blinker01.clang.thumb.norm.o
$(ARMGNU)-objdump -D blinker01.clang.thumb.norm.flash.elf > blinker01.clang.thumb.norm.flash.list
$(ARMGNU)-objcopy blinker01.clang.thumb.norm.flash.elf blinker01.clang.thumb.norm.flash.bin -O binary
blinker01.clang.thumb.opt.flash.bin : flash.ld flash.o blinker01.clang.bc
opt $(OOPS) blinker01.clang.bc -o blinker01.clang.thumb.opt.bc
#llc $(LLCOPS) blinker01.clang.thumb.opt.bc -o blinker01.clang.thumb.opt.s
#$(ARMGNU)-as $(AOPS) blinker01.clang.thumb.opt.s -o blinker01.clang.thumb.opt.o
llc $(LLCOPS) blinker01.clang.thumb.opt.bc -filetype=obj -o blinker01.clang.thumb.opt.o
$(ARMGNU)-ld -o blinker01.clang.thumb.opt.flash.elf -T flash.ld flash.o blinker01.clang.thumb.opt.o
$(ARMGNU)-objdump -D blinker01.clang.thumb.opt.flash.elf > blinker01.clang.thumb.opt.flash.list
$(ARMGNU)-objcopy blinker01.clang.thumb.opt.flash.elf blinker01.clang.thumb.opt.flash.bin -O binary
blinker01.clang.thumb.norm.sram.bin : sram.ld sram.o blinker01.clang.bc
#llc $(LLCOPS) blinker01.clang.bc -o blinker01.clang.thumb.norm.s
#$(ARMGNU)-as $(AOPS) blinker01.clang.thumb.norm.s -o blinker01.clang.thumb.norm.o
llc $(LLCOPS) blinker01.clang.bc -filetype=obj -o blinker01.clang.thumb.norm.o
$(ARMGNU)-ld -o blinker01.clang.thumb.norm.sram.elf -T sram.ld sram.o blinker01.clang.thumb.norm.o
$(ARMGNU)-objdump -D blinker01.clang.thumb.norm.sram.elf > blinker01.clang.thumb.norm.sram.list
$(ARMGNU)-objcopy blinker01.clang.thumb.norm.sram.elf blinker01.clang.thumb.norm.sram.bin -O binary
blinker01.clang.thumb.opt.sram.bin : sram.ld sram.o blinker01.clang.bc
opt $(OOPS) blinker01.clang.bc -o blinker01.clang.thumb.opt.bc
#llc $(LLCOPS) blinker01.clang.thumb.opt.bc -o blinker01.clang.thumb.opt.s
#$(ARMGNU)-as $(AOPS) blinker01.clang.thumb.opt.s -o blinker01.clang.thumb.opt.o
llc $(LLCOPS) blinker01.clang.thumb.opt.bc -filetype=obj -o blinker01.clang.thumb.opt.o
$(ARMGNU)-ld -o blinker01.clang.thumb.opt.sram.elf -T sram.ld sram.o blinker01.clang.thumb.opt.o
$(ARMGNU)-objdump -D blinker01.clang.thumb.opt.sram.elf > blinker01.clang.thumb.opt.sram.list
$(ARMGNU)-objcopy blinker01.clang.thumb.opt.sram.elf blinker01.clang.thumb.opt.sram.bin -O binary
在stm32f0上闪烁pa4和5。由于不同的启动条件,我有不同的引导程序代码,可以说你可以使用相同的代码,然后从一个偏移量恢复从sram(jtag)运行。
flash版本的反汇编在这里仔细检查第一项是堆栈指针加载值,然后我认为地址必须是奇数(拇指模式),但不确定,可以很容易地测试。lsbit在使用时被剥离,因此0x08000040是重置向量,这就是我们在反汇编中看到的,sp是由逻辑加载的,所以我们可以直接转到notmain(这只是旧工具链的一个习惯,如果它看到一个名为main的函数,就会添加垃圾)
08000000 <_start>:
8000000: 20001000 andcs r1, r0, r0
8000004: 08000041 stmdaeq r0, {r0, r6}
8000008: 08000047 stmdaeq r0, {r0, r1, r2, r6}
800000c: 08000047 stmdaeq r0, {r0, r1, r2, r6}
8000010: 08000047 stmdaeq r0, {r0, r1, r2, r6}
8000014: 08000047 stmdaeq r0, {r0, r1, r2, r6}
8000018: 08000047 stmdaeq r0, {r0, r1, r2, r6}
800001c: 08000047 stmdaeq r0, {r0, r1, r2, r6}
8000020: 08000047 stmdaeq r0, {r0, r1, r2, r6}
8000024: 08000047 stmdaeq r0, {r0, r1, r2, r6}
8000028: 08000047 stmdaeq r0, {r0, r1, r2, r6}
800002c: 08000047 stmdaeq r0, {r0, r1, r2, r6}
8000030: 08000047 stmdaeq r0, {r0, r1, r2, r6}
8000034: 08000047 stmdaeq r0, {r0, r1, r2, r6}
8000038: 08000047 stmdaeq r0, {r0, r1, r2, r6}
800003c: 08000047 stmdaeq r0, {r0, r1, r2, r6}
08000040 <reset>:
8000040: f000 f80a bl 8000058 <notmain>
8000044: e7ff b.n 8000046 <hang>
08000046 <hang>:
8000046: e7fe b.n 8000046 <hang>
08000048 <PUT16>:
8000048: 8001 strh r1, [r0, #0]
800004a: 4770 bx lr
0800004c <PUT32>:
800004c: 6001 str r1, [r0, #0]
800004e: 4770 bx lr
08000050 <GET32>:
8000050: 6800 ldr r0, [r0, #0]
8000052: 4770 bx lr
08000054 <dummy>:
8000054: 4770 bx lr
8000056: 46c0 nop ; (mov r8, r8)
08000058 <notmain>:
8000058: b570 push {r4, r5, r6, lr}
800005a: 4824 ldr r0, [pc, #144] ; (80000ec <notmain+0x94>)
800005c: f7ff fff8 bl 8000050 <GET32>
8000060: 2180 movs r1, #128 ; 0x80
8000062: 0289 lsls r1, r1, #10
8000064: 4301 orrs r1, r0
8000066: 4821 ldr r0, [pc, #132] ; (80000ec <notmain+0x94>)
8000068: f7ff fff0 bl 800004c <PUT32>
800006c: 2090 movs r0, #144 ; 0x90
800006e: 05c0 lsls r0, r0, #23
8000070: f7ff ffee bl 8000050 <GET32>
8000074: 21a0 movs r1, #160 ; 0xa0
8000076: 4c1e ldr r4, [pc, #120] ; (80000f0 <notmain+0x98>)
8000078: 00c9 lsls r1, r1, #3
800007a: 4020 ands r0, r4
800007c: 4301 orrs r1, r0
800007e: 2090 movs r0, #144 ; 0x90
8000080: 05c0 lsls r0, r0, #23
8000082: f7ff ffe3 bl 800004c <PUT32>
8000086: 481b ldr r0, [pc, #108] ; (80000f4 <notmain+0x9c>)
8000088: f7ff ffe2 bl 8000050 <GET32>
800008c: 2330 movs r3, #48 ; 0x30
800008e: 0001 movs r1, r0
8000090: 4818 ldr r0, [pc, #96] ; (80000f4 <notmain+0x9c>)
8000092: 4399 bics r1, r3
8000094: f7ff ffda bl 800004c <PUT32>
8000098: 4817 ldr r0, [pc, #92] ; (80000f8 <notmain+0xa0>)
800009a: f7ff ffd9 bl 8000050 <GET32>
800009e: 21f0 movs r1, #240 ; 0xf0
80000a0: 0109 lsls r1, r1, #4
80000a2: 4301 orrs r1, r0
80000a4: 4814 ldr r0, [pc, #80] ; (80000f8 <notmain+0xa0>)
80000a6: f7ff ffd1 bl 800004c <PUT32>
80000aa: 4814 ldr r0, [pc, #80] ; (80000fc <notmain+0xa4>)
80000ac: f7ff ffd0 bl 8000050 <GET32>
80000b0: 0001 movs r1, r0
80000b2: 4812 ldr r0, [pc, #72] ; (80000fc <notmain+0xa4>)
80000b4: 4021 ands r1, r4
80000b6: f7ff ffc9 bl 800004c <PUT32>
80000ba: 4d11 ldr r5, [pc, #68] ; (8000100 <notmain+0xa8>)
80000bc: 2130 movs r1, #48 ; 0x30
80000be: 4811 ldr r0, [pc, #68] ; (8000104 <notmain+0xac>)
80000c0: f7ff ffc4 bl 800004c <PUT32>
80000c4: 2400 movs r4, #0
80000c6: 0020 movs r0, r4
80000c8: 3401 adds r4, #1
80000ca: f7ff ffc3 bl 8000054 <dummy>
80000ce: 42ac cmp r4, r5
80000d0: d1f9 bne.n 80000c6 <notmain+0x6e>
80000d2: 21c0 movs r1, #192 ; 0xc0
80000d4: 480b ldr r0, [pc, #44] ; (8000104 <notmain+0xac>)
80000d6: 0389 lsls r1, r1, #14
80000d8: f7ff ffb8 bl 800004c <PUT32>
80000dc: 2400 movs r4, #0
80000de: 0020 movs r0, r4
80000e0: 3401 adds r4, #1
80000e2: f7ff ffb7 bl 8000054 <dummy>
80000e6: 42ac cmp r4, r5
80000e8: d1f9 bne.n 80000de <notmain+0x86>
80000ea: e7e7 b.n 80000bc <notmain+0x64>
80000ec: 40021014 andmi r1, r2, r4, lsl r0
80000f0: fffff0ff ; <UNDEFINED> instruction: 0xfffff0ff
80000f4: 48000004 stmdami r0, {r2}
80000f8: 48000008 stmdami r0, {r3}
80000fc: 4800000c stmdami r0, {r2, r3}
8000100: 00030d40 andeq r0, r3, r0, asr #26
8000104: 48000018 stmdami r0, {r3, r4}