linux - 如何在Ubuntu上编译STM32f103程序?

标签 linux cross-compiling stm32 cortex-m3

我有一些使用keil在windows上编程stm32 arm cortex m3微控制器的经验。我现在想转到linux环境,使用开源工具来编程stm32 cortex m3设备。
我研究了一下,发现我可以使用openocd或texane的st-link来闪存芯片。我还发现我需要一个交叉编译器来编译代码viz。gcc arm none eabi工具链。
我想知道需要什么基本的源文件和头文件?这是核心和系统文件需要作出一个简单的闪烁程序。
我现在不打算用哈尔图书馆。我用的是stm32f103zet6单片机(一个非常通用的板)。我去了http://regalis.com.pl/en/arm-cortex-stm32-gnulinux/,但无法准确定位文件。
如果有在Linux环境下启动stm32编程的教程,请告诉我。
如有任何帮助,我们将不胜感激。谢谢!

最佳答案

下面是一个非常简单的例子,它可以移植到stm32系列中。不做任何有用的事情,你必须填补空白闪烁一个LED或一些东西(阅读示意图,手册,使时钟到GPIO,按照指示,使其推/拉输出等,设置位或清除位等)。
我有自己的理由,别人也有自己的理由,我们都有多年或几十年的经验。但到了最后,他们的意见和许多不同的解决方案将工作。
在ubuntu的最后一个版本中,你可以简单地使用它来获得一个工具链:

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

或者你可以在这里为你的操作系统预先构建一个
https://launchpad.net/gcc-arm-embedded

闪光
.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

闪光.ld
MEMORY
{
    rom : ORIGIN = 0x08000000, LENGTH = 0x1000
    ram : ORIGIN = 0x20000000, LENGTH = 0x1000
}

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

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

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

诺特迈恩
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

如果您愿意,也可以尝试/使用这种方法。我有理由不这么做。
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为你发布衍生产品的arm文档之间(不是每个人都这么做,你还是应该去arm)。再加上ST医生。
有基于uart的bootloader内置(可能是usb等),很容易接口,让我们看看…我的主机代码下载程序是在数百行的代码,可能需要一个晚上或下午写。YMMV公司。如果你还没有,你可以得到一个发现板或核子板,我建议你无论如何,你可以使用它的调试端来编程其他stm32或甚至其他非st-arm芯片(不是全部,取决于openocd支持什么,等等,但有些)可以得到那些30%的便宜比专用stlink usb加密狗,你不需要一个扩展usb电缆等。当然可以与openocd或texane stlink一起使用stlink。
由于cortex-m的启动方式,我提供了两个例子,一个用于烧录flash,另一个用于通过openocd下载到ram并以这种方式运行,可以说也可以使用flash,但运行时必须调整开始地址。我更喜欢这种方法。YMMV公司。
这种方法是可移植的,完全不受hal限制或需求、构建环境等的限制,但我建议您尝试各种方法。像这样的裸金属,HAL类型的裸金属,有一个或多个ST解决方案和CMSIS方法。每年左右再试一次,看看你选的那个还是你喜欢的那个。
这个例子虽然不需要太多的时间,但却证明了这一点。我选择Cortex-M0只是为了避免ARMV7M拇指2的延长。没有这些扩展的thumb是最便携的arm指令集。同样的,代码基本上什么也不做,但是在任何带有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初始化,并且无法从reset函数返回,在实际实现中,如果没有演示测试,您可能无法返回(LED闪烁10次,然后程序完成)。
您的工具链可能有其他方法来实现这一点。因为所有的工具链都应该有一个汇编器,而且汇编器可以生成单词表,所以总是有这个选项,为这个创建另一个工具和语言是没有意义的,但是有些人觉得有必要。工具链可能不需要名为“u start”的入口点和/或它可能有不同的入口点名称要求。
即使你使用kiel,你也应该尝试gnu工具,比kiel更容易获得,在世界上有更多的支持和经验。可能不会产生像kiel、performance wise或其他代码那样“好”的代码,但是应该总是把它放在你的后口袋里,因为你总是能够找到gnu工具的帮助。

关于linux - 如何在Ubuntu上编译STM32f103程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38443734/

相关文章:

为 ARM11 交叉编译 GStreamer、Airstream

go - 如何使用github.com/mattn/go-sqlite3为Google Cloud VM交叉编译Go软件包?

c - 在STM32F3上用DMA生成正弦波-乱码输出

c++ - 使用 C++ 将半字写入闪存时的 ARM Cortex-M HardFault 异常

linux - CUDA C v. Thrust,我错过了什么吗?

python - 在 python 的子进程中调用 bash 时缺少别名设置

c - 在 Linux 中使用计时器记录指标

java - Selenium 服务器在被 SIGTERM 杀死后不绑定(bind)到套接字

c++ - 在多个平台和架构上部署?

c - 错误 : selected processor does not support ARM mode `wfi'