目录

  • LibOpenCM3(一) Linux下命令行开发环境配置
  • LibOpenCM3(二) 项目模板 Makefile分析
  • LibOpenCM3(三) .ld文件(连接器脚本)和startup代码说明

本文默认使用 Linux 环境, 硬件为 STM32F103 系列开发板

LibOpenCM3 介绍

LibOpenCM3 是GPL协议(LGPL3)的Cortex-M系列的封装库, 支持stm32、atmel、nxp系列单片机. 这个固件库对标的是 CMSIS, 但是比 CMSIS 提供更多的方法接口, 实现度介于 CMSIS 和 SPL 之间. 对于常见的 STM32F1 系列, 代码已经基本稳定.

  • 项目地址
    https://github.com/libopencm3/libopencm3
  • 项目示例
    https://github.com/libopencm3/libopencm3-examples
  • WIKI
    https://github.com/libopencm3/libopencm3/wiki
  • API文档
    http://libopencm3.org/docs/latest/html/

开发环境

硬件部分

  • STM32F103 开发板
  • ST-Link V2

软件部分

  • LibOpenCM3
    https://github.com/libopencm3/libopencm3
  • LibOpenCM3项目模板
    https://github.com/libopencm3/libopencm3-template
  • GNU Arm Embedded Toolchain
    下载地址
  • stlink linux工具, 包含st-flash,st-info等命令
    https://github.com/stlink-org/stlink

环境配置

GNU Arm Embedded Toolchain 工具链

通过前面的地址下载最新版本, 根据自己的系统架构选择合适的架构版本

# 解压
tar xjf gcc-arm-none-eabi-10.3-2021.10-x86_64-linux.tar.bz2
# 放到/opt下并设置权限
sudo mv gcc-arm-none-eabi-10.3-2021.10 /opt/gcc-arm/
cd /opt/gcc-arm/
sudo chown -R root:root gcc-arm-none-eabi-10.3-2021.10/

加到PATH(可选)

export PATH="/opt/gcc-arm/gcc-arm-none-eabi-10.3-2021.10/bin:$PATH"

检查版本

$ arm-none-eabi-gcc --version
arm-none-eabi-gcc (GNU Arm Embedded Toolchain 10.3-2021.10) 10.3.1 20210824 (release)
Copyright (C) 2020 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

stlink,st-flash,st-info

需要先安装 libusb-1.0-0-dev

sudo apt install libusb-1.0-0-dev

编译安装

git clone https://github.com/stlink-org/stlink.git
cd stlink/
make
cd build/Release/
sudo make install

检查

$ st-flash  --version
v1.7.0-184-g468b1d2
$ st-info --version
Failed to parse flash type or unrecognized flash type
v1.7.0-184-g468b1d2

st-flash 使用说明 https://github.com/stlink-org/stlink/blob/develop/doc/tutorial.md

  • –flash=128k 参数可以指定flash大小, 例如覆盖 STM32F103C8T6 默认的 64k 大小设置. 取值可以使用 十进制(128k), 八进制 0200k, 或者十六进制 0x80k.
  • –reset 在写入结束后触发重置
  • –connect-under-reset 重置状态下连接. 使用这个选项可以在用户代码执行前连接MCU, 当目标MCU上的用户代码将MCU置于sleep状态, 或禁用了调试接口导致无法连接时特别有用.

LibOpenCM3

LibOpenCM3封装库文件结构

libopencm3
├── COPYING.GPL3
├── COPYING.LGPL3
├── doc
├── HACKING
├── HACKING_COMMON_DOC
├── include                  # 头文件目录
│     ├── libopencm3
│     │     ├── cm3
│     │     ├── dispatch
│     │     ├── docmain.dox
│     │     ├── efm32
│     │     ├── ethernet
│     │     ├── gd32
│     │     ├── license.dox
│     │     ├── lm3s
│     │     ├── lm4f
│     │     ├── lpc13xx
│     │     ├── lpc17xx
│     │     ├── lpc43xx
│     │     ├── msp432
│     │     ├── nrf
│     │     ├── pac55xx
│     │     ├── sam
│     │     ├── stm32       # 按不同的型号分组的头文件, 定义中断向量表的 irq.json
│     │     ├── swm050
│     │     ├── usb
│     │     └── vf6xx
│     └── libopencmsis
│         ├── core_cm3.h
│         └── dispatch
│             └── irqhandlers.h
├── ld
│     ├── devices.data      # 芯片数据库, 各个芯片型号对应的flash和ram尺寸
│     ├── linker.ld.S       # 连接器脚本模板, 不是汇编代码
│     ├── README
│     └── tests
├── lib                       # 链接库目录, 编译后生成的.a文件会放到对应芯片目录下
│     ├── cm3
│     │     ├── assert.c
│     │     ├── dwt.c
│     │     ├── nvic.c
│     │     ├── scb.c
│     │     ├── sync.c
│     │     ├── systick.c
│     │     └── vector.c      # startup代码
│     ├── cortex-m-generic.ld
│     ├── dispatch
│     │     ├── vector_chipset.c
│     │     └── vector_nvic.c
│     ├── efm32
│     ├── ethernet
│     ├── gd32
│     ├── lm3s
│     ├── lm4f
│     ├── lpc13xx
│     ├── lpc17xx
│     ├── lpc43xx
│     ├── Makefile.include
│     ├── msp432
│     ├── nrf
│     ├── pac55xx
│     ├── sam
│     ├── stm32
│     ├── swm050
│     ├── usb
│     └── vf6xx
├── locm3.sublime-project
├── Makefile
├── mk                    # make 规则目录
│     ├── gcc-config.mk
│     ├── gcc-rules.mk
│     ├── genlink-config.mk   # 用于配置生成ld需要的参数
│     ├── genlink-rules.mk    # 用于生成ld文件
│     └── README
├── README.md
├── scripts
│     ├── checkpatch.pl
│     ├── data
│     ├── gendoxylayout.py
│     ├── gendoxylist
│     ├── genlink.py          # 芯片数据库文件搜索脚本
│     ├── genlinktest.sh      # 芯片数据库文件搜索测试脚本
│     ├── irq2nvic_h          # 读取irq.json, 填充IRQ_HANDLERS变量, 这个变量会被vector.c 的 vector_table 引用,
│     └── lpcvtcksum
└── tests

LibOpenCM3 项目模板

导出 libopencm3 可以单独编译, 但是配置为完整的项目还需要添加用户代码和Makefile, 因为 LibOpenCM3 已经提供了立即可用的项目模板, 可以直接用模板提供的环境进行开发

导出模板

git clone --recurse-submodules https://github.com/libopencm3/libopencm3-template.git
cd libopencm3-template/
# 这一步需要前面的 arm-none-eabi-gcc 工具链已经配置到 PATH
# 编译
make -C libopencm3

这一步会编译 libopencm3

  • 在 libopencm3/lib 目录下生成全部型号的 .a 库文件
  • 在 libopencm3/lib/stm32 目录下, 对应 f0, f1, …, f7 等各个目录下生成对应型号的 ld 文件

如果前面没有将 arm-none-eabi-gcc 添加到PATH, 需要修改一下 libopencm3/Makefile, 将 PREFIX 修改为

PREFIX       ?= /opt/gcc-arm/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-

如果只想编译当前使用的设备(STM32F103), 可以指定设备, 这样比较节省时间

TARGETS=stm32/f1 make

如果要输出完整命令, 可以加上 V=1 参数

TARGETS=stm32/f1 make V=1

注: 在当前的模板项目中, libopencm3不是最新版本, 版本号 cb0661f81de5b1cae52ca99c7b5985b678176db7 对应的是2020-02-16的版本, 这个版本在lib/stm32/fx 目录下依然有各个型号的ld文件, 而这些文件实际上在 2020-11-29 的提交 BREAKING: drop all part specific ld files中已经删除了. 具体的说明可以点开查看. 当前模板的Makefile实际上使用的是后者的编译方式生成项目的ld文件.

编辑用户项目, 在编辑之前, 需要修改 my-project 目录下的 Makefile, 将 DEVICE 修改为自己的 STM32 型号

# TODO - you will need to edit these two lines!
DEVICE=stm32f103c6t6

填入的型号如果正确, 会在编译时生成对应的ld文件, 例如对应上面的就是 generated.stm32f103c6t6.ld

如果前面没有将 arm-none-eabi-gcc 添加到PATH, 需要修改一下 my-project/Makefile, 添加 PREFIX 定义

PREFIX       ?= /opt/gcc-arm/gcc-arm-none-eabi-10.3-2021.10/bin/arm-none-eabi-

编译

make -C my-project

这时候在 my-project 目录下会产生以下文件

total 172
-rwxrwxr-x 1 milton milton   1492 Feb 20 23:55 awesomesauce.bin*
-rwxrwxr-x 1 milton milton 276952 Feb 20 23:55 awesomesauce.elf*
drwxrwxr-x 2 milton milton   4096 Feb 20 23:55 bin/
-rw-rw-r-- 1 milton milton   1108 Feb 20 23:55 generated.stm32f103c6t6.ld
-rw-rw-r-- 1 milton milton    493 Feb 20 23:38 Makefile
-rw-rw-r-- 1 milton milton   2099 Feb 20 23:42 my-project.c

其中 awesomesauce.bin 是用于烧录的文件

通过 arm-none-eabi-size 查看编译结果的内存结构.

$ arm-none-eabi-size awesomesauce.elf text      data     bss     dec     hex filename1480       12         0      1492       5d4 awesomesauce.elf

其中

  • text 是占用的flash空间
  • data 初始化占用内存大小
  • bss 全局分配的内存大小
  • dec和hex 十进制和十六进制表示的总大小

演示示例

下面用一个闪灯的示例把开发环境跑一遍.

用户代码

将 my-project 目录下的 my-project.c 内容修改为

#include <libopencm3/cm3/nvic.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/timer.h>#ifndef ARRAY_LEN
#define ARRAY_LEN(array) (sizeof((array))/sizeof((array)[0]))
#endif#define LED1_PORT   GPIOC
#define LED1_PIN    GPIO13static void gpio_setup(void)
{/* Enable GPIO clock for leds. */rcc_periph_clock_enable(RCC_GPIOC);/* Enable led as output */gpio_set_mode(LED1_PORT,GPIO_MODE_OUTPUT_50_MHZ,GPIO_CNF_OUTPUT_PUSHPULL,LED1_PIN);gpio_set(LED1_PORT, LED1_PIN);
}static void tim_setup(void)
{/* Enable TIM2 clock. */rcc_periph_clock_enable(RCC_TIM2);/* Enable TIM2 interrupt. */nvic_enable_irq(NVIC_TIM2_IRQ);/* Reset TIM2 peripheral to defaults. */rcc_periph_reset_pulse(RST_TIM2);/* Timer global mode:* - No divider* - Alignment edge* - Direction up* (These are actually default values after reset above, so this call* is strictly unnecessary, but demos the api for alternative settings)*/timer_set_mode(TIM2, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP);/* Disable preload. */timer_disable_preload(TIM2);timer_continuous_mode(TIM2);timer_set_prescaler(TIM2, 36000); // Clock counts every 0.5 msectimer_set_period(TIM2, 2000); // 2000 * 0.5 msec => 1 sec/* Counter enable. */timer_enable_counter(TIM2);/* Enable Channel 1 compare interrupt to recalculate compare values */timer_enable_irq(TIM2, TIM_DIER_CC1IE);
}/*** ISR method defined in libopencm3/include/libopencm3/stm32/f1/nvic.h
*/
void tim2_isr(void)
{if (timer_get_flag(TIM2, TIM_SR_CC1IF)){/* Clear compare interrupt flag. */timer_clear_flag(TIM2, TIM_SR_CC1IF);/* Toggle LED to indicate compare event. */gpio_toggle(LED1_PORT, LED1_PIN);}
}int main(void)
{// Setup main clock, using external 8MHz crystalrcc_clock_setup_in_hse_8mhz_out_72mhz();// 如果用的libopencm3版本较高, 编译提示上面的函数已经废弃, 可以换成下面的代码//rcc_clock_setup_pll(&rcc_hse_configs[RCC_CLOCK_HSE8_72MHZ]);gpio_setup();tim_setup();while (1);return 0;
}

上面的代码, 用TIM2定时, 触发板载C13对应的LED每秒切换亮灭状态

编译

使用前面配置好的开发环境

make -C my-project

写入

将开发板接上ST-Link接上PC

写入, 0x800 0000 是 STM32F103 的Flash空间起始地址

st-flash write ./awesomesauce.bin 0x8000000
# 会看到包含如下文字的输出
2022-02-21T00:00:42 INFO common.c: STM32F1xx_LD: 10 KiB SRAM, 32 KiB flash in at least 1 KiB pages.
file ./awesomesauce.bin md5 checksum: 363668176fa21306a846725b7db2079, stlink checksum: 0x0001fe1e
2022-02-21T00:00:42 INFO common_flash.c: Attempting to write 1492 (0x5d4) bytes to stm32 address: 134217728 (0x8000000)
-> Flash page at 0x8000000 erased (size: 0x400)
-> Flash page at 0x8000400 erased (size: 0x400)2022-02-21T00:00:42 INFO flashloader.c: Starting Flash write for VL/F0/F3/F1_XL
2022-02-21T00:00:42 INFO flash_loader.c: Successfully loaded flash loader in sram
2022-02-21T00:00:42 INFO flash_loader.c: Clear DFSR
2022-02-21T00:00:42 INFO flash_loader.c: Clear CFSR
2022-02-21T00:00:42 INFO flash_loader.c: Clear HFSR2/  2 pages written
2022-02-21T00:00:42 INFO common_flash.c: Starting verification of write complete
2022-02-21T00:00:42 INFO common_flash.c: Flash written and verified! jolly good!

此时需要手动按一下开发板的 RESET 键, 程序才会开始执行, 如果需要自动重置, 使用下面的命令

st-flash --reset write ./awesomesauce.bin 0x8000000

其它命令

查看开发板信息

st-info --probe
# 会看到包含如下文字的输出(当前这块测试用的是 stm32f103c6t6)
Found 1 stlink programmersversion:    V2J37S7serial:     56FF6B064966485627461667flash:      32768 (pagesize: 1024)sram:       10240chipid:     0x412

擦除

st-flash erase
# 会看到包含如下文字的输出
2022-02-21T00:00:12 INFO common.c: STM32F1xx_LD: 10 KiB SRAM, 32 KiB flash in at least 1 KiB pages.
Mass erasing

参考

  • https://bdebyl.net/post/stm32-part0/
  • https://bdebyl.net/post/stm32-part1/
  • https://rhye.org/post/stm32-with-opencm3-0-compiling-and-uploading/
  • https://thomas.spurden.name/blog/stm-start/

LibOpenCM3(一) Linux下命令行开发环境配置相关推荐

  1. linux下Eclipse+CDT开发环境配置与使用

    1. 安装JDK. 在Ubuntu下安装软件就显得比较简单了,apt-get的功能实在强大,配以IPv6的更新源,下载的速度用飞快来形容一点也不为过.首先是安装jdk,在终端中输入 sudo apt- ...

  2. GCC编译器简明教程(Linux下C语言开发环境的搭建)

    GCC编译器简明教程(Linux下C语言开发环境的搭建) 市面上常见的Linux都是发行版本,典型的Linux发行版包含了Linux内核.桌面环境(例如GNOME.KDE.Unity等)和各种常用的必 ...

  3. 2021-01-13 Linux下安装lua开发环境 Ubuntu

    Linux下安装lua开发环境 Ubuntu 1.下载lua包并解压 wget -c http://www.lua.org/ftp/lua-5.3.5.tar.gz tar zxvf lua-5.3. ...

  4. linux 下51单片机开发环境搭建

    linux 下51单片机开发环境搭建(arch linux) 编译sdcc 软件: sdcc 命令:sdcc file.c 得到一堆文件需要( .inx) 命令: packihx file.inx & ...

  5. linux登陆ftp报错425,linux下命令行连接FTP是遇到的错误(425 Failed to establish connection)...

    linux下命令行连接FTP是遇到的错误(425 Failed to establish connection) 首先FTP的运行模式有主动模式和被动模式两种 然后笔者在工作中搭建了ftp,但是没有开 ...

  6. Linux下命令行压缩照片或图片的脚本 (ImageMagick使用心得,convert,import,display实例)

    from: Linux下命令行压缩照片或图片的脚本 (ImageMagick使用心得,convert,import,display实例) 在认识ImageMagick之前,我使用的图像浏览软件是Kui ...

  7. windows、linux下命令行登录oracle数据库方法,查询sga参数值sql语句

    windows 下 cmd 命令行登录 oracle 数据库方法.直接就登录进来了. C:\Users\Administrator>sqlplusSQL*Plus: Release 11.2.0 ...

  8. linux中C编译命令,linux下命令行下编译c程式

    linux下命令行下编译c程式 2008-02-23 05:41:36来源:互联网 阅读 () C 是任何版本的UNIX上的系统语言. C 在过去的二十年中有了很大的发展. 在80年代末期美国国家标准 ...

  9. Linux下命令行打开word、excel、pdf文件

    Linux下命令行打开word.excel.pdf文件 1.打开word文件 wps xxx.docx xdg-open xxx.docx 2.打开excel文件 et xxx.xlsx xdg-op ...

最新文章

  1. 阿里发布2019十大科技趋势:AI依然最热
  2. web开发中目录路径问题的解决
  3. android gradle proguard,Android Gradle插件2.2.0 ProGuard开始保留内部类
  4. 二改注册登录版素材代下载搜索引擎系统源码,自带火车头采集
  5. java start launcher_hmcl启动失败
  6. CentOS开启samba服(附smb.conf手册)
  7. Spark实例项目—每个域名下访问次数最多的URL
  8. linux emule 编译 wx-config --libs,Linux下的wxWidgets静态编译实现方法
  9. empire-CVE-2018-19462
  10. 手机投屏电视机的原理
  11. 【AE】【栅格操作】
  12. Ubuntu安装基础教程(No Zuo No Die)
  13. 什么样的领导者,更能赢得人心?
  14. unity投篮小游戏,原创,请勿转载。
  15. Groovy - GString String
  16. D.引水工程 【最小生成树+超级源点】
  17. 山西计算机等级考试科目一模拟试题,考驾照科目一试题100题,老司机教你两招,让你轻松考过!...
  18. C语言中的strtok函数用法
  19. 微信小程序 常用轮子
  20. python模拟ps中的素描工具

热门文章

  1. python爬虫初步学习
  2. 引擎Demo演示-算是一个转折点吧
  3. (1)一次意外的屠魔之旅
  4. 初中英语语法(016)-被动语态
  5. 【Linux】解决可恶的 “NIC Link is Down”
  6. for循环canvas渲染图片
  7. Android获取手机中的所有音乐地址
  8. 访问和更新Orkut数据
  9. Redis教程之基础-五种数据基本操作
  10. SAP 中利润中心 详细解析