如何在ubuntu上编译STM32f103程序?

时间:2016-07-18 18:32:58

标签: linux cross-compiling stm32 cortex-m3

我在使用Keil在Windows上编程stm32 arm cortex m3微控制器方面有一些经验。我现在想转移到linux环境并使用开源工具来编程STM32 cortex m3设备。

我进行了一些研究,发现我可以使用OpenOCD或Texane的ST Link来闪存芯片。我还发现我需要一个交叉编译器来编译代码。 gcc-arm-none-eabi工具链。

我想知道需要哪些基本的源文件和头文件?哪个是制作简单闪烁程序所需的核心和系统文件。

我现在不打算使用HAL库。我使用的是stm32f103zet6 mcu(非常通用的主板)。我去了http://regalis.com.pl/en/arm-cortex-stm32-gnulinux/,但无法精确定位文件。

如果有任何教程要在linux环境下启动stm32编程,请告诉我。

感谢任何帮助。谢谢!

3 个答案:

答案 0 :(得分:2)

这是一个非常简单的示例,它在stm32系列中相当便携。没有做任何有用的事情,你必须填写空白闪烁led或东西(阅读原理图,手册,启用时钟到gpio,按照说明使其成为推/拉输出等等,设置为位或清除位等。)

我有自己的理由,其他人有自己的理由,我们都有不同年数或数十年的经验。但在他们结束的那天,他们就是意见,许多不同的解决方案都会奏效。

在ubuntu的最后这么多版本中你可以简单地做到这一点来获得一个工具链:

apt-get install gcc-arm-linux-gnueabi binutils-arm-linux-gnueabi

或者您可以到这里为您的操作系统预先构建

https://launchpad.net/gcc-arm-embedded

flash.s

.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

flash.ld

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

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

sram.s

.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

sram.ld

MEMORY
{
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}
SECTIONS
{
    .text : { *(.text*) } > ram
    .rodata : { *(.rodata*) } > ram
    .data : { *(.data*) } > ram
    .bss : { *(.bss*) } > ram
}

notmain.c

void PUT32 ( unsigned int, unsigned int );
unsigned int GET32 ( unsigned int );
void dummy ( unsigned int );
#define STK_CSR 0xE000E010
#define STK_RVR 0xE000E014
#define STK_CVR 0xE000E018
#define STK_MASK 0x00FFFFFF
int delay ( unsigned int n )
{
    unsigned int ra;
    while(n--)
    {
        while(1)
        {
            ra=GET32(STK_CSR);
            if(ra&(1<<16)) break;
        }
    }
    return(0);
}
int notmain ( void )
{
    unsigned int rx;
    PUT32(STK_CSR,4);
    PUT32(STK_RVR,1000000-1);
    PUT32(STK_CVR,0x00000000);
    PUT32(STK_CSR,5);
    for(rx=0;;rx++)
    {
        dummy(rx);
        delay(50);
        dummy(rx);
        delay(50);
    }
    return(0);
}

生成文件

#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


all : notmain.gcc.thumb.flash.bin notmain.gcc.thumb.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
    rm -f *.hex

#---------------------------------

flash.o : flash.s
    $(ARMGNU)-as $(AOPS) flash.s -o flash.o

sram.o : sram.s
    $(ARMGNU)-as $(AOPS) sram.s -o sram.o

notmain.gcc.thumb.o : notmain.c
    $(ARMGNU)-gcc $(COPS) -mthumb -c notmain.c -o notmain.gcc.thumb.o

notmain.gcc.thumb.flash.bin : flash.ld flash.o notmain.gcc.thumb.o
    $(ARMGNU)-ld -o notmain.gcc.thumb.flash.elf -T flash.ld flash.o notmain.gcc.thumb.o
    $(ARMGNU)-objdump -D notmain.gcc.thumb.flash.elf > notmain.gcc.thumb.flash.list
    $(ARMGNU)-objcopy notmain.gcc.thumb.flash.elf notmain.gcc.thumb.flash.bin -O binary

notmain.gcc.thumb.sram.bin : sram.ld sram.o notmain.gcc.thumb.o
    $(ARMGNU)-ld -o notmain.gcc.thumb.sram.elf -T sram.ld sram.o notmain.gcc.thumb.o
    $(ARMGNU)-objdump -D notmain.gcc.thumb.sram.elf > notmain.gcc.thumb.sram.list
    $(ARMGNU)-objcopy notmain.gcc.thumb.sram.elf notmain.gcc.thumb.sram.hex -O ihex
    $(ARMGNU)-objcopy notmain.gcc.thumb.sram.elf notmain.gcc.thumb.sram.bin -O binary

如果您愿意,也可以尝试/使用此方法。我的理由不是,TL; DW。

void dummy ( unsigned int );
#define STK_MASK 0x00FFFFFF
#define STK_CSR (*((volatile unsigned int *)0xE000E010))
#define STK_RVR (*((volatile unsigned int *)0xE000E014))
#define STK_CVR (*((volatile unsigned int *)0xE000E018))
int delay ( unsigned int n )
{
    unsigned int ra;
    while(n--)
    {
        while(1)
        {
            ra=STK_CSR;
            if(ra&(1<<16)) break;
        }
    }
    return(0);
}
int notmain ( void )
{
    unsigned int rx;
    STK_CSR=4;
    STK_RVR=1000000-1;
    STK_CVR=0x00000000;
    STK_CSR=5;
    for(rx=0;;rx++)
    {
        dummy(rx);
        delay(50);
        dummy(rx);
        delay(50);
    }
    return(0);
}

在某种程度上ST为您发布衍生品的手臂文档之间(不是每个人都这样做,您仍然应该去武装)。加上st docs。

内置了基于uart的bootloader(可能是usb等),这很容易接口,让我们看看...我的主机代码下载程序是在几百行代码中,可能需要一个晚上或者写下午。因人而异。你可以得到,如果你没有,发现或核板之一,无论如何,我推荐那些,你可以使用它的调试结束编程其他stm32甚至其他非st arm芯片(不是全部,取决于openocd支持什么等等,但有些)可以获得比专用的stlink usb加密狗便宜30%的那些,你不需要扩展USB线缆等,YMMV。当然可以像你已经提到的那样使用带有openocd或texane stlink的stlink。

由于cortex-m靴子的方式,我提供了两个例子,一个用于刻录闪光另一个用于通过openocd下载到ram并以这种方式运行,可以说可以使用闪存但是你必须调整开始运行时的地址。我更喜欢这种方法。因人而异。

这种方法是可移植的,完全不受HAL限制或要求,构建环境等的影响。但我建议您尝试各种方法。像这样的裸金属HAL类型的裸金属与一个或多个st解决方案和cmsis方法。每年左右再试一次,看看你选择的那个是否仍然是你喜欢的那个。

这个例子说明了它并不需要很多。我选择了cortex-m0只是为了避免使用armv7m thumb2扩展。没有这些扩展的拇指是最便携的手臂指令集。所以代码几乎什么也没做,但是在任何带有systick定时器的stm32 cortex-m上什么也没做。

修改

这与您提供链接器所需的一切都是最小的非C代码。

.global _start
_start:
.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

这个缩写取决于芯片供应商和核心,每个小东西的每个小中断都可以有几十到几百个向量。在这种情况下,标签重置和挂起将是处理这些向量的C函数的名称(芯片和核心的文档确定什么向量处理什么)。第一个向量始终是堆栈指针的初始值。第二个是永远复位,接下来几个是常见的,之后它们是核心上的通用中断引脚,芯片供应商连线,所以你必须查看芯片供应商的文档。

核心设计是为您保留寄存器,因此您不需要一点装配。在没有任何引导程序的情况下,你假设没有.bss归零,也没有.data初始化,你不能从重置函数返回,在实际的实现中你不能但是对于演示测试,你可能(闪烁一个led 10次然后程序是完成)。

您的工具链可能还有其他一些方法可以做到这一点。由于所有工具链都应该有一个汇编程序,而汇编程序可以生成单词表,所以总有这个选项,为这个创建另一个工具和语言并没有真正意义,但有些人觉得有必要。您的工具链可能不需要名为_start的入口点和/或它可能有不同的入口点名称要求。

即使你使用基尔,你也应该尝试使用gnu工具,轻松(更容易)获得,在世界上比基尔更多的支持和经验。可能不会产生&#34;好&#34;代码作为基尔,性能明智或其他,但应始终在你的后袋中,因为你总是能够找到gnu工具的帮助。

答案 1 :(得分:-1)

http://gnuarmeclipse.github.io/

在那里你可以找到所有东西,包括IDE(Eclipse),工具链,调试器,标题。

答案 2 :(得分:-1)

看看这个package。这是IDE +工具链+调试器,可用于Linux平台。你可以研究它并获得任何你想做的想法。我希望大多数linux程序都有commnad线路接口。

此外,我可以向您建议:尝试使用LL api,如果它已经可用于您的mcu。