STM32高级开发(9)-学习与编译libopencm3-example

本文介绍如何使用Libopencm3库简化STM32开发流程,通过下载官方示例工程、编译库文件及样例代码,帮助读者快速上手。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在前面的几篇中我们为大家介绍了在Linux下stm32开发环境的新特性和使用方式,可能大家觉得,我怎么写一个工程还要自己写链接文件和启动文件,是不是太不方便了点。那么这篇中我会告诉大家其实并不是这样的。在我们日常的一些小规模工程下我们是可以使用一个叫做libopencm3的cortexM核的通用驱动库来配置我们的工程。那么大型的工程呢?有童鞋还会问道。对于大型的工程,我想:自己去改写链接文件和启动文件,使得你对整个系统的启动及运行流程更好的把控绝对是物有所值的,在这两个文件上付出的短短的时间绝对会为我们带来超出他们花费的价值。


Libopencm3简介

libopencm3项目(以前称为libopenstm32)旨在创建一个适用于ARM Cortex-M0(+)/M3/M4内核单片机的免费、自由与开源(LGPL v3或更新)的固件库,其支持的单片机包括ST STM32, Ti Tiva and Stellaris, NXP LPC 11xx, 13xx, 15xx, 17xx parts, Atmel SAM3, Energy Micro EFM32等。

以上内容翻译自libopencm3在GitHub上的官方wiki中的介绍(请不要嘲笑我的翻译啦,大家明白意思就好,我就不费劲的去整理更好的语言描述了):
https://github.com/libopencm3/libopencm3/wiki

从Status的页面中我们可以查询到libopencm3目前所支持的单片机类型,其中由于该项目起初是为stm32而开发的,所以固件库对stm32的支持性是最好的,其次是TI和NXP的单片机,其他公司的MCU则要差许多,对支持性的描述大家可以在Status页面中自行阅读查找。

  • ST:STM32F0, F1, F2, F3, F4, F7, L0, L1, L4
  • TI: MSP432 nee LM4F nee TM4C
  • NXP:LPC13xx, LPC15xx and LPC17xx
  • NXP:LPC43xx
  • EFM32:Tiny Gecko, Gecko, Leopard Gecko and Giant Gecko
  • Atmel:SAM 3a, 3n, 3s, 3x, 3u
  • Freescale:Vybrid VF6xx

下载Libopencm3及其例程

在我们学习一个固件库的过程中最重要的显然是找到一个我们可以参考的样例工程,所以在我们此处选择下载Libopencm3的官方样例工程。

首先cd到我们之前创建的workspace目录下

$ cd ~/workspace

然后使用git指令克隆https://github.com/libopencm3/libopencm3-examples地址上的工程

$ git clone https://github.com/libopencm3/libopencm3-examples.git

这里写图片描述

我们点开克隆下来的工程进入其中的libopencm3固件库,会发现在文件夹下并不存在任何的文件,这是由于在样例工程中,配置引用了一个libopencm3固件库模块,这个submodule在我gitclone的过程中并不会被一起下载,所以我们需要cd进入工程使用git submodule init和update来更新注册并下载它。

$ cd ./libopencm3-examples
$ git submodule init
$ git submodule update

这里写图片描述

这里写图片描述

到此我们就已经成功的将样例工程下载下来了。


编译Libopencm3的样例


编译Libopencm3固件库

在我们编译样例工程之前我们首先要编译Libopencm3固件库从而生成库文件 .a,得以被样例工程调用。所以我们cd进入Libopencm3的目录并使用make编译。

这里写图片描述

这里写图片描述

这里再次讲一下这里生成的.a文件,.a文件是一种Linux下的静态链接库文件,而在我们的应用中我们可以把它理解为是一种由固件库中的.c.h文件编译生成的集成库,就像keil下的 .lib 是一样的。


样例工程的文件结构

在刚刚下载下来样例工程的时候我想大家想我一样,对它两眼一摸黑,甚至连样例工程的下各个例子在哪都找不到。所以在下面我们首先为大家来介绍一下我们下载下来的样例工程结构,来为大家分析一下它的用法。

首先我们要明白,我们下载下来的是一个完整的样例工程即就像st官方的固件库资料一样,里面包含了很多小的工程,如流水灯,LCD显示,ADC等等,但他们都是引用文件结构下的一个库文件进行编译,这点是和国内stm32开发板(如:原子、野火等)的教程不大一样的。在了解这点后,我们来看下文件夹下的内容。

-libopencm3-examples
|-examples\
|-libopencm3\
|-scripts\
|-Makefile
|-README.md

在 examples 存放的是样例的源代码,在其目录下以芯片型号分类成不同的文件夹。在libopencm3下,是libopencm3固件库的本体。scripts下存放的是libopencm3项目推荐的一个叫black_magic的调试器的启动文件,我们不需理会,README.md则是项目的说明文件,使用markdown语言编写,会在GitHub中的项目文件列表下自动显示。在此处顶层文件夹中的makefile中,它的功能是编译所有的样例文件下的子工程,我们不理会它,因为我们不会使用这个文件来编译。

下面我们进入 examples/stm32/f4的目录,由于我使用的是一块官方的F429DISCO开发板,所以在这个文件夹下是可以直接找到给这块开发板使用的子工程的,如果大家使用的是其他牌子或自行设计的开发板,大家可以选择一个与开发板上芯片主型号相同的官方开发板打开,因为除却外设接驳的端口等,实际上它们都是一样的。在板子的目录下我们可以看到不同功能的子工程,如 ADC、blink、button等。

这里写图片描述

我们进入最简单的例程:miniblink同时将终端cd进入该文件夹,输入make+空格,而后双击Tab,看看可以执行的目标:

$ make 

这里写图片描述

由于我们没有在makefile中配置好调试器,所以这里我们先选择编译.hex来编译。对于开发板上LED端口不对应的童鞋,在make前,可以先打开目录下miniblink.c的源代码修改其中的端口,及时我们之前没有接触过libopencm3的固件库,但我相信大家都是能够理解里面的内容的。

这里写图片描述

在修改完成后,我们使用make执行。

$ make hex

很快编译就会完成,并在子工程目录下生成一个.hex文件,我们将hex文件移出,下载进入单片机,看~是不是LED开始闪烁了?

这里写图片描述

由此我想大家就明白这个样例工程该怎么使用了,但是进一步的,大家肯定会产生疑问,这个样例工程下,makefile是怎样产生功能的,它是怎么配置的,么下下面我们就来深入的分析一下这个问题。


样例工程的makefile

我们来看看子工程目录下的make 也就是我们在该文件夹下执行make指令时首先调用的makefile文件。

BINARY = miniblink

LDSCRIPT = ../stm32f429i-discovery.ld

include ../../Makefile.include

除去文件头部的版权声明的注释,一共只有3行,第一行定义了一个变量BINARY ,这是我们在编译后生产工程执行文件的名称,此处为miniblink。然后为LDSCRIPT 变量赋值,设定了工程ld即链接文件件,其在当前目录的上方,最后include引用了一个在上上层的makefile。我们先来看看在这个文件的设定的ld文件,随后在来分析它引用的makefile。

MEMORY
{
    rom (rx) : ORIGIN = 0x08000000, LENGTH = 2048K
    ram (rwx) : ORIGIN = 0x20000000, LENGTH = 128K /* (esden) This should be 256 but I get segfault. :( */
}

/* Include the common ld script. */
INCLUDE libopencm3_stm32f4.ld

我们打开上层目录的ld文件stm32f429i-discovery.ld,发现它定义了板子上STM32F429ZIT6的ROM、RAM大小并引用了libopencm3固件库下的libopencm3_stm32f4.ld文件,再打开libopencm3_stm32f4.ld文件,我们发现其中只定义了除ROM、RAM大小的所有链接规则。至此我们就明白了ld文件的设置及引用结构。接下来再来看看被子工程引用的makefile:Makefile.include

ifeq ($(DEVICE),)
LIBNAME     = opencm3_stm32f4
DEFS        += -DSTM32F4

FP_FLAGS    ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16
ARCH_FLAGS  = -mthumb -mcpu=cortex-m4 $(FP_FLAGS)
endif

################################################################################
# OpenOCD specific variables

OOCD        ?= openocd
OOCD_INTERFACE  ?= stlink-v2
OOCD_TARGET ?= stm32f4x

################################################################################
# Black Magic Probe specific variables
# Set the BMP_PORT to a serial port and then BMP is used for flashing
BMP_PORT    ?=

################################################################################
# texane/stlink specific variables
#STLINK_PORT    ?= :4242


include ../../../../rules.mk

第一行,如果DEVICE变量为空,就执行下面的赋值,我们之前并未定义DEVICE所以下面的赋值会被执行。这里我们看到他定义了固件库的名称、芯片的型号和编译的参数。下面则定义了各种调试器的参数。并在最后再一次引用了一个makefile:rules.mk。而这一次我们先不打开这个makefile,在下面一个阶段里我们再来分析。

这里首先我们先讲讲,这里makefile和ld文件问什么分了这么多,搞得这么麻烦,其中最大的原因就是层次性和通用性,在我翻看其他的子工程源代码的情况下,我们会发现除了子工程目录下的makefile文件,其他的makefile文件和ld文件都被不同的子工程调用的多次,而到了rules.mk的文件,所有的不同型号芯片和板子的子工程都调用了这个makefile。以这种分层次分结构的的方式编写,显然的可以极大地方便最终子工程的设置修改和快速配置。

呃,是不是有点没大说清楚,我们举个具体的例子;就如在miniblink子工程文件夹下的makefile中,定义了子工程的设置。在开发板型号的目录下定义了,开发板和编译参数的具体设置,在最后的mk.rule中,则定义了所有样例工程的makefile设置。同理,ld文件的结构也是这样。

到这里我们对libopencm3工程的介绍就告一段落了,想来大家也对样例工程的结构有了一定的了解,从而可以自己去学习官方的样例工程了,在这里我还是建议大家先尝试的去更改官方样例工程的源代码,和makefile来试着编译自己的一个blink程序,来借此学习一下样例工程,从而为我们接下来的内容奠定一个基础。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值