目录

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

LibOpenCM3 介绍

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

开发环境

硬件部分

  • STM32F103 开发板
  • ST-Link V2

软件部分

环境配置

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 可以单独编译, 但是配置为完整的项目还需要添加用户代码和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 文件

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

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

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

编译

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 filename
1480 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 GPIO13 static 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 msec
timer_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 crystal
rcc_clock_setup_in_hse_8mhz_out_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 HFSR
2/ 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 programmers
version: V2J37S7
serial: 56FF6B064966485627461667
flash: 32768 (pagesize: 1024)
sram: 10240
chipid: 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

参考

LibOpenCM3(一) Linux下命令行开发环境配置的更多相关文章

  1. C++14系列(1):Linux下C++14开发环境配置

    g++安装 參考地址: http://sysads.co.uk/2014/07/install-gcc-gnu-4-9-1-on-ubuntu-14-04/ 当前Ubuntu的LTS版本号为14.04 ...

  2. Linux学习心得之 Linux下命令行Android开发环境的搭建

    作者:枫雪庭 出处:http://www.cnblogs.com/FengXueTing-px/ 欢迎转载 Linux学习心得之 Linux下命令行Android开发环境的搭建 1. 前言2. Jav ...

  3. Windows10下配置Linux下C语言开发环境

    今天为大家介绍如在Windows10下配置Linux下C语言开发环境,首先安装linux子系统:启用开发者模式 1.打开设置 2.点击更新和安全3.点击开发者选项 4.启用开发人员模式 5.更改系统功 ...

  4. Linux下命令行安装weblogic10.3.6

    Linux下命令行安装weblogic10.3.6 一.安装前准备工作: 1.创建用户useradd weblogic;创建用户成功linux系统会自动创建一个和用户名相同的分组,并将该用户分到改组中 ...

  5. php 运行linux命令 与 linux下命令行执行php

    1.php运行linux命令 exec函数:string exec(string command, string [array], int [return_var]);  执行函数后不输出结果,返回最 ...

  6. Xshell下漂亮的开发环境配置

    今天折腾了一天Xshell配置Linux命令行开发环境. 总结几点: 1.Xshell配色方案,这是我自己调的个人使用版,网上比较好的版本有Solarized Dark,可以下载到. [ColorFo ...

  7. Linux下命令行cURL的10种常见用法示例

    curl的命令行工具功能非常强大,这些数据交互的功能基本上都是通过URL方式进行的,下面这篇文章主要给大家分享了在Linux中命令行cURL的10种常见用法示例,通过示例代码介绍的非常详细,需要的朋友 ...

  8. Fedora和Ubuntu下安装OpenGL开发环境配置

    Fedora下OpenGl开发环境配置 开发OpenGL工程需要3个库文件和对应的头文件: libglut.so,libGLU.so,libGL.so, gl.h ,glu.h, glut.h 这些库 ...

  9. WIN10下java8的开发环境配置与第一个java程序

    一.开发环境配置 1.在官网上下载jdk-8u111-windows-x64.exe 2.运行安装包,可以自定义安装路径 3.进入环境变量设置: 计算机右键-->属性-->高级系统设置-- ...

随机推荐

  1. Maven+ajax+SSM实现编辑修改

    转载自:https://www.cnblogs.com/kebibuluan/p/9017754.html 3.尚硅谷_SSM高级整合_使用ajax操作实现修改员工的功能 当我们点击编辑案例的时候,我 ...

  2. elasticsearch在linux上的安装,Centos7.X elasticsearch 7.6.2安装

    本文环境:Elasticsearch7.6.2目前最先版本   centos7.X     JDK1.8 elasticsearch介绍 官网:https://www.elastic.co/cn/pr ...

  3. 我的2021年度总结-回忆录|附旅行Vlog

    今天是农历腊月初十,还有20天就是2022年了.这一年,些许遗憾,些许期盼.时间久了,很多事已经慢慢模糊了,只记得,这最后几个月的闲碎小事. 不止多久,很久没有码字了.有些事,记不清,忆不得.时至今年 ...

  4. Android-ViewPager中调用notifyDataSetChanged失效问题--setItemPosition--POSITION_NONE

    最基本的方法: 针对于child view比较简单的情况(例如仅有TextView.ImageView等,没有ListView等展示数据的情况),可以在自己的Adapter中加入代码: @Overri ...

  5. spring拦截机制中Filter(过滤器)、interceptor(拦截器)和Aspect(切面)的使用及区别

    Spring中的拦截机制,如果出现异常的话,异常的顺序是从里面到外面一步一步的进行处理,如果到了最外层都没有进行处理的话,就会由tomcat容器抛出异常. 1.过滤器:Filter :可以获得Http ...

  6. tep0.9.5支持自定义扩展request

    tep0.9.5更新了以下内容: 自定义request请求日志 Allure报告添加request描述 猴子补丁扩展request fixtures支持多层级目录 FastAPI替代Flask 升级t ...

  7. java单例模式(饿汉式和懒汉式)

    1 /* 2 * 设计模式:对问题行之有效的解决方式.其实它是一种思想. 3 * 4 * 1,单例设计模式 5 * 解决的问题:就是可以保证一个类在内容中的对象唯一性. 6 * 7 * 必须对于多个程 ...

  8. 项目管理软件jira安装

    JIRA是Atlassian公司出品的项目与事务跟踪工具,被广泛应用于缺陷跟踪.客户服务.需求收集.流程审批.任务跟踪.项目跟踪和敏捷管理等工作领域. 官方文档https://confluence.a ...

  9. JavaWeb后端工程师技能图

  10. 前端基础之CSS(浮动-解决溢出-实现个人头像框)

    目录 一:浮动float 1.什么是浮动? 2.浮动的作用 3.浮动有两个特点 4.float格式 二:代码实现左右浮动边框 三:浮动造成父标签塌陷问题(清除浮动) 1.浮动会造成父标签的影响 三:清 ...