如何使用STM32CubeMX启动最小项目?

时间:2018-05-15 16:10:34

标签: embedded stm32 stm32f4discovery

我正在尝试学习嵌入式开发,目前我正在使用STM32F407G板。

到目前为止,我已经能够使用CubeMX提供的高级驱动程序API基于用户按钮切换LED。

但是,我现在想要在没有任何API帮助的情况下重新创建相同的功能。相反,使用参考手册中提供的基地址和寄存器,我想基本上重新创建API。

到目前为止,我已使用GUI禁用了所有外围设备:

enter image description here

但我觉得有更好的方法可以做到这一点。我不完全确定哪些外设我甚至需要调试板上的代码。

基本上,我需要足够的启动代码,以便能够将代码加载(闪存?)到微控制器中,并调试main()。其他一切(例如切换LED,检测用户按钮中断等)将是我想要处理的事情。

2 个答案:

答案 0 :(得分:3)

flash.s

.cpu cortex-m4
.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 PUT32
PUT32:
    str r1,[r0]
    bx lr

.thumb_func
.globl GET32
GET32:
    ldr r0,[r0]
    bx lr

.thumb_func
.globl dummy
dummy:
    bx lr

so.c

void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void dummy ( unsigned int );

int notmain ( void )
{
    unsigned int ra;

    for(ra=0;ra<1000;ra++) dummy(ra);

    return(0);
}

flash.ld

MEMORY
{
    rom : ORIGIN = 0x08000000, LENGTH = 0x1000
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}

SECTIONS
{
    .text : { *(.text*) } > rom
    .rodata : { *(.rodata*) } > rom
    .bss : { *(.bss*) } > ram
}

构建(不需要非eabi,使用此代码,您可以使用arm-linux-gnueabi或任何一个arm-whatever-gcc / as / ld你想要的(在合理范围内))

arm-none-eabi-gcc -Wall -Werror -O2 -nostdlib -nostartfiles -ffreestanding  -mthumb -mcpu=cortex-m4 -c so.c -o so.o
arm-none-eabi-ld -o so.elf -T flash.ld flash.o so.o
arm-none-eabi-objdump -D so.elf > so.list
arm-none-eabi-objcopy so.elf so.bin -O binary

从笔记中我花了一段时间后,您可以使用dfu-util来编写二进制文件

dfu-util -d 0483:df11 -c 1 -i 0 -a 0 -s 0x08000000 -D myprogram.bin

上面没什么用,但是是一个框架,你可以添加gpio块的启用,使led引脚成为输出,然后关闭并打开一些代码来消除循环中的时间。和/或轮询一个gpio引脚并驱动另一个匹配(使用按钮点亮或关闭LED)。

openocd用stlink连接到这个板/家庭......

你最初不需要中断或时钟配置(如果有的话)。

啊,对......无论你走哪条路,你都要检查二进制文件并确保它有机会工作。

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 f808   bl  8000054 <notmain>
 8000044:   e7ff        b.n 8000046 <hang>

08000046 <hang>:
 8000046:   e7fe        b.n 8000046 <hang>

使用堆栈指针前面的向量表,这很好,不必使用它,忽略stmdaeq反汇编,它只是试图反汇编向量条目,因为我使用objdump来检查二进制文件。向量表需要奇数,条目ORRED的地址为1。从技术上讲,如果足够小,你可以在这些部件上使用0x00000000,因为它实际上是在引导此代码时将被映射的地方,但因为它也映射到0x08000000,这些ST部件的全部闪存量通常会看到它像这个。如果您从另一个系列(NXP,Atmel / Microchip等)切换到另一个基于cortex-m的部件,那么您可能需要使用另一个地址,即0x00000000或该部分系列使用的其他地址。

如果您没有看到二进制文件的开头看起来像堆栈指针初始值和向量表,那么无论您采用什么库/软件路径,您都不太可能有很多运气。

请注意,对此问题的评论中给出了正确的答案。它主要是基于意见的。有多个库解决方案,随着时间的推移,供应商将不断改变它们的各种(通常是非技术性的)原因。从专业角度来说,你应该可以沿着任何一条路走下去,真正的裸机或沙箱或中间的某个地方。如果您没有编写所有代码并使用其他人,那么您仍然对该项目负责,因此您应该花时间深入研究它并检查该代码的质量和准确性。你应该对你发现的东西感到惊讶,你拥有它你应该修理它,如果你不喜欢和/或更换它。

这两条路径都不会自动更简单,也不会更快,也更可靠。没有正确答案,所以你需要灵活。

文档和库代码都是错误的,期待这一点,期望处理这个问题。

答案 1 :(得分:2)

您无需重新创建API。使用寄存器的Jest程序。我几乎在所有项目中都这样做(除非使用某种HAL是我的客户要求)

你需要:

  1. 使用向量表启动代码。
  2. CMSIS标题为方便起见。
  3. 如何使用CubeMx存档它。实际上很容易。

    1. 创建项目
    2. 导入您最喜欢的IDE。
    3. 在项目选项中删除USE_HAL_DRIVER定义
    4. 从构建(或删除)/驱动程序/ STMxxxxx_HAL_Driver
    5. 中排除所有文件
    6. 从main.c文件中删除所有内容
    7. 添加:

      #include "stm32f4xx.h" // CMSIS headers
      
      int main(void)
      {
      }
      

      并享受:)