Arm 为什么是stm32f103';s elf文件运行良好,但二进制文件不行?
我正在尝试运行stm32f103内的固件。所以当我使用opencod+gdb上传和调试elf文件时,一切都很好,我的固件工作正常,我可以设置和删除断点 但是当我尝试使用st flash上传这个固件(与elf文件一起构建)并将其写入Arm 为什么是stm32f103';s elf文件运行良好,但二进制文件不行?,arm,gdb,stm32,firmware,openocd,Arm,Gdb,Stm32,Firmware,Openocd,我正在尝试运行stm32f103内的固件。所以当我使用opencod+gdb上传和调试elf文件时,一切都很好,我的固件工作正常,我可以设置和删除断点 但是当我尝试使用st flash上传这个固件(与elf文件一起构建)并将其写入0x8000000时,它不起作用。虽然我收到“固件已成功上载”的消息 当LED开始闪烁时,我可以查看代码是否运行 根据启用引导加载程序的数据表,BOOT0通过npn晶体管连接到cp2102的DTR引脚。我必须将BOOT0设置为高。但是当我通过st链接上传我的fw时,我的
0x8000000
时,它不起作用。虽然我收到“固件已成功上载”的消息
当LED开始闪烁时,我可以查看代码是否运行
根据启用引导加载程序的数据表,BOOT0通过npn晶体管连接到cp2102的DTR引脚。我必须将BOOT0设置为高。但是当我通过st链接上传我的fw时,我的串行(cp2102)没有连接。所以我认为DTR引脚是浮动的或向下拉的。我的错在哪里
我试图在上传之前批量擦除我的flash,它给出了相同的结果
这是我的链接器的ld文件:
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
CCMRAM (xrw) : ORIGIN = 0x00000000, LENGTH = 0
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 64K
FLASHB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB0 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB2 (rx) : ORIGIN = 0x00000000, LENGTH = 0
EXTMEMB3 (rx) : ORIGIN = 0x00000000, LENGTH = 0
MEMORY_ARRAY (xrw) : ORIGIN = 0x00000000, LENGTH = 0
}
和部分您是否尝试过使用
它允许您使用UART、SWD、JTAG和USB对固件进行编程。请先尝试SWD,然后再尝试UART模式,看看是ST错误还是您的UART接线。试试这个
.globl _start
_start:
.word 0x20001000
.word reset
.word loop
.word loop
.thumb_func
reset:
add r0,#1
b reset
.thumb_func
loop:
b loop
构建,可以使用arm任何东西(arm none eabi、arm linux gnueabi等)
眨眼器01.c
void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void dummy ( unsigned int );
#define GPIOCBASE 0x40011000
#define RCCBASE 0x40021000
int notmain ( void )
{
unsigned int ra;
unsigned int rx;
ra=GET32(RCCBASE+0x18);
ra|=1<<4; //enable port c
PUT32(RCCBASE+0x18,ra);
//config
ra=GET32(GPIOCBASE+0x04);
ra&=~(3<<20); //PC13
ra|=1<<20; //PC13
ra&=~(3<<22); //PC13
ra|=0<<22; //PC13
PUT32(GPIOCBASE+0x04,ra);
for(rx=0;;rx++)
{
PUT32(GPIOCBASE+0x10,1<<(13+0));
for(ra=0;ra<200000;ra++) dummy(ra);
PUT32(GPIOCBASE+0x10,1<<(13+16));
for(ra=0;ra<200000;ra++) dummy(ra);
}
return(0);
}
建造
检查向量表
Disassembly of section .text:
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>
两者应该有相同的数据。如果没有,那么您就有boot0问题
编辑
如果DTR高,则boot0为0/GND是吗?这就是正常启动所需的。开机时boot0处于低位,复位处于高位,或从低位到高位
您可以编写一个程序以某种方式强制DTR
int dtr_bit=TIOCM_DTR;
...
dtr_bit=TIOCM_DTR;
ioctl(ser_hand,TIOCMBIC,&dtr_bit);
...
dtr_bit=TIOCM_DTR;
ioctl(ser_hand,TIOCMBIS,&dtr_bit);
用通常的termios材料打开把手
或者假设您的哑终端(minicom等)支持DTR,连接uart,然后打开电源和/或重置电路板(回形针或任何您手边的东西)
由于我经常使用串行引导加载程序加载我的stm32部件,或者即使我使用SWD,我总是为自己提供一个控制boot0和复位的解决方案,无论是按钮、跳线、焊盘还是其他组合 @非常感谢您的详细回答。我发现问题在于固件过大。我的芯片只有64k的闪存,fw是68k,所以eclipse没有告诉我固件太大,并试图闪存它。另外,我基于项目的模板使用了newlib,其中startup.s被C文件替换,我想这是有问题的。因此,我从openstm32 tamplate创建了一个新项目(它从stdperiph lib、cmsis等+ld复制了所有必要的文件),之后我添加了我的文件,通过删除未使用的文件和set-Os标志优化了构建,它似乎对我有效,但固件大小几乎过大。我将尝试您的解释)我发现链接器和ld文件存在问题,但这是一个奇怪的问题。如果我从blink模板创建一个新项目,并将其上载到我的stm32,则一切正常,led闪烁。如果我用同一个ld文件上传我的fw,没有任何效果。如果我通过Keil uVision构建并上传它,那么一切都正常工作。你也应该能够使用openocd+telnet。通过telnet,您可以使用其他格式的文件。我怀疑这是因为elf文件包含大量关于二进制文件的位置等信息,而对于原始闪存图像,只有字节,你必须告诉工具更多,另一个可能的问题是二进制文件中的入口点错误,但是通过使用gdb,它在您定义的位置而不是应该在的位置启动程序,向量表的反汇编/转储是什么样子的?除此之外,还需要更多关于您尝试和/或尝试执行的操作、二进制文件的外观(至少在开始时)以及您尝试过的小型测试二进制文件的信息。gdb既有帮助又有伤害,所以使用gdb只能让你走到目前为止,要想在没有gdb的情况下运行,你必须弄清楚gdb为你做了什么,而不是为你做了什么。stlink与boot0无关,boot0让你进入片上引导加载程序,通常是uart,有时是其他,但不是swd/jtag——你可以随时使用它,除非你在挂起的芯片上放了一个二进制文件,否则可能无法通过swd进入(除非你使用boot0只是为了将它转换成无缺陷/挂起的代码)。如果你想在boot0中使用cp2102,你需要不同的软件,st网站上提供的信息非常容易编写你自己的程序员,而且还有很多。在尝试了其他方法后,你能回到使用openocd+gdb和elf文件吗?你有没有挂断芯片,或者能够通过这种组合重新获得成功?
MEMORY
{
rom : ORIGIN = 0x08000000, LENGTH = 0x1000
ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
.text : { *(.text*) } > rom
.rodata : { *(.rodata*) } > rom
.bss : { *(.bss*) } > ram
}
arm-none-eabi-as --warn --fatal-warnings flash.s -o flash.o
arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding -mthumb -c blinker01.c -o blinker01.o
arm-none-eabi-ld -o blinker01.elf -T flash.ld flash.o blinker01.o
arm-none-eabi-objdump -D blinker01.elf > blinker01.list
arm-none-eabi-objcopy blinker01.elf blinker01.bin -O binary
Disassembly of section .text:
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>
mdw 0x00000000 20
mdw 0x08000000 20
int dtr_bit=TIOCM_DTR;
...
dtr_bit=TIOCM_DTR;
ioctl(ser_hand,TIOCMBIC,&dtr_bit);
...
dtr_bit=TIOCM_DTR;
ioctl(ser_hand,TIOCMBIS,&dtr_bit);