稚晖君:配置CLion用于STM32开发

0.前言
最近在做一个开源个人项目有用到stm32这款mcu,好久没用keil感觉各种不适应,遂尝试能不能把stm32的开发环境部署到其他更强大的ide,结果很圆满,以下是配置clion用于stm32开发的过程记录,供大家参考~
做嵌入式开发的人对stm32这个平台应该都是非常熟悉的,在国内尤其流行,很多产品里面都是基于这个平台做的方案。多数人在开发stm32的时候用的都是keil这个老牌ide,很大一部分原因是因为大多数人最初是从51单片机学习过来的,51就是基于keil去开发的,然后迁移到stm32的时候也就沿用下来了。
keil开发环境界面
keil操作简单,容易上手,而且可以很方便地进行调试。但是对于以前不是做嵌入式开发的软件开发人员来说,面对keil这种上世纪风格的ide(不只是ui)肯定是不太有好感的。在尝试过stm32cubeide和truestudio等用eclipse修改的ide之后,总是觉得还是没内味儿。
我平时工作中最常用的是pycharm和android studio,都是jetbrains系的ide。用过jetbrains系ide的朋友肯定会被它强大的代码补全、界面风格、各种插件、流畅性等众多优点所吸引,毫无疑问这些是能够极大提高开发效率的。而其中有一款clion ide就是专门面向c/c++开发的,所以本篇文章会介绍如何把stm32的编译调试环境部署到clion中,过程还是有很多坑值得注意的。
代码的话大家以前用的基本上都是st的标准库,然后自己开发逻辑部分,或者在一些方便的地方直接操作寄存器。直接操作寄存器能提高代码的执行效率,但是很难移植,后来st开发了一款可以快速demo的平台cube mx,通过这个软件配合st的hal库,可以快速的搭建工程,并能生成跨芯片平台的工程。hal库更容易进行移植,而且应用起来也更加方便,st也正在加大对hal库的支持,并渐渐放弃标准库。
本篇介绍的内容也是以基于hal库开发为准的。
1.环境及所需工具
软件环境:
windows 10
stm32cubemx
clion-2019
mingw
openocd
arm-none-eabi-gcc
硬件环境:
stm32f103vet6
自制的daplink下载器(st-link/j-link也是可以的)
工具安装
stm32cubemx
这个正常去官网下载最新版的安装就行了:https://www.st.com/en/development-tools/stm32cubemx.html
openocd
openocd是用于对stm32进行下载仿真的工具,是一个开源软件包,windows版本下从这里下载,下载好解压到一个目录就行,后面会在clion中链接这个目录:
mingw
clion需要使用mingw环境来配置工具链,安装方法如下:
首先去mingw主页下载最新版本的mingw: minimalist gnu for windows,这是mingw的安装器:
打开exe进行安装,修改安装目录(最好不能有空格),安装完成后进行组件下载:
如上图中所示,把basic setup里面的组件全部勾选(也可也去掉不需要的语言编译器比如objective-c)。
配置系统的环境变量,在path环境变量里面添加一条,指向mingw的bin文件夹:
重启电脑,然后在命令窗口中输入下面的命令验证安装是否成功:
gcc -v
arm-none-eabi-gcc
windows到这里下载:https://developer.arm.com/open-source/gnu-toolchain/gnu-rm/downloads ,选择zip压缩包形式的:
解压到一个文件夹,并把安装目录下的bin文件夹添加到环境变量:
然后重启使得环境变量生效之后可以在命令行里用以下语句测试:
arm-none-eabi-gcc -v
如果有信息输出,那就是装好了。
clion配置
clion是基于cmake来管理项目的,所以首选我们需要配置好预设的mingw和cmake环境。
打开file-settings-build,execution,deployment选项卡,在toolchains下面添加一个mingw环境:
注意debugger不要改,否则断点调试的时候无法连接。
然后再cmake栏下确认一下工具链是否正确:
至此clion环境配置完成,可以创建stm32项目了。
2.在clion中创建stm32工程
创建cubemx工程
在clion中选择file-new project可以创建stm32cubemx的项目:
点击create后会生成一个.ioc文件,这个文件跟使用stm32cubemx直接创建的是一样的,点击图中的链接可以跳转到stm32cubemx中打开这个ioc文件:
默认选中的芯片型号是stm32f030f4px,我们可以在cubemx中重新选择自己需要的芯片,一切操作都和使用keil开发没有区别。
只有一个地方需要注意一下,就是在下面的设置中项目名称一定要和在clion中建立的一致,这样生成的工程文件才会覆盖clion中的文件,否则会另外生成一个文件夹,clion就无法读取了。
另外生成的ide类型选择是sw4stm32。
每次修改完点generate之后,弹窗直接点close,clion里面会自动更新文件。
第一次设置完回到clion会弹出一个板卡选择窗口:
这些配置文件是跟openocd下载程序有关的,里面的板子很可能是没有我们自己要用的型号的,后面会介绍怎么自己建立这个配置文件,这里先点取消。
编译工程
在ide底栏的cmake选项卡中如果没有提示错误,说明工程配置就没问题了。
点击这个按钮可以更新cmake工程:
顶栏的这三个图标分别是编译、下载、调试:
点击编译,可以看到编译输出:
可以看到成功生成了用于烧写的.bin和.hex文件。
烧录程序 & 在线调试
在keil里面我们烧录程序的时候要指定使用的下载器(j-link、st-link、cmsis-dap等),clion烧录程序之前通用需要进行一些设置。
点击编译按钮旁边的配置栏下拉,选edit configurations,打开配置窗口:
可以看到没有设置板子的config文件所以出现警告错误,这个配置文件就是前面说的需要自己生成的文件。
我们在工程根目录下新建一个文件夹config,在里面新建一个配置文件daplink.cfg(因为我这里使用的是自制daplink作为仿真器),文件的内容如下:
# choose st-link/j-link/dap-link etc.
adapter driver cmsis-dap
transport select swd
# 0x10000 = 64k flash size
set flash_size 0x20000
source [find target/stm32f1x.cfg]
# download speed = 10mhz
adapter speed 10000
前两行设置了仿真器的类型和接口,下面几行指定了flash大小、芯片类型、下载速度等。
如果对自己的芯片不知道怎么设置,可以参考openocd自带的一系列配置文件,路径在openocd安装目录的share\openocd\scripts下:
只需要关注这几个目录:
board:板卡配置,各种官方板卡
interface:仿真器类型配置,比如st-link、cmsis-dap等都在里面
target:芯片类型配置,stm32f1xx、stm32l0xx等等都在里面
设置好配置文件之后,就可以点击下载或者调试按钮进行下载和在线调试了。
在配置文件中不要加reset_config srst_only这一句,会导致下载失败,这一句是指示系统重启的,删除不影响下载。
clion里面是支持全功能的单步断点调试的,也能在代码里直接观察变量的值,非常舒服~
强大的代码补全功能
单步调试和变量观察功能
3.其他问题
编译错误问题
如果移动了工程文件夹的话,最好打开.ioc文件重新generate一下再编译,可以解决很多错误。
printf重定向问题
在keil里面为了使用printf函数我们需要重定向fputc函数:
int fputc (int ch, file *f)
{
(void)hal_uart_transmit(&huart1, (uint8_t *)&ch, 1, 1000);
return ch;
}
其中的file定义在stdio.h头文件中,所以需要在项目中包含这个头文件,但是经过测试发现,keil里面包含的是mdk\arm\armcc\include这个目录下的stdio.h,而在clion中是不会链接到这个文件的。因此如果在clion中也按之前的方法进行重定向,会发现printf没有任何输出。
在clion中链接的是gnu-tools-arm-embedded\arm-none-eabi\include里面的stdio.h,如果仍然想使用printf函数功能,则需要进行如下操作:
新建一个retarget.h文件内容如下:
#ifndef _retarget_h__
#define _retarget_h__
#include “stm32f1xx_hal.h”
#include
#include
void retargetinit(uart_handletypedef *huart);
int _isatty(int fd);
int _write(int fd, char *ptr, int len);
int _close(int fd);
int _lseek(int fd, int ptr, int dir);
int _read(int fd, char *ptr, int len);
int _fstat(int fd, struct stat *st);
#endif //#ifndef _retarget_h__
再新建一个retarget.c文件内容如下:
#include 《_ansi.h》
#include 《_syslist.h》
#include
#include
#include
#include
#include
#if !defined(os_use_semihosting)
#define stdin_fileno 0
#define stdout_fileno 1
#define stderr_fileno 2
uart_handletypedef *ghuart;
void retargetinit(uart_handletypedef *huart)
{
ghuart = huart;
/* disable i/o buffering for stdout stream, so that
* chars are sent out as soon as they are printed. */
setvbuf(stdout, null, _ionbf, 0);
}
int _isatty(int fd)
{
if (fd 》= stdin_fileno && fd 《= stderr_fileno)
return 1;
errno = ebadf;
return 0;
}
int _write(int fd, char *ptr, int len)
{
hal_statustypedef hstatus;
if (fd == stdout_fileno || fd == stderr_fileno)
{
hstatus = hal_uart_transmit(ghuart, (uint8_t *) ptr, len, hal_max_delay);
if (hstatus == hal_ok)
return len;
else
return eio;
}
errno = ebadf;
return -1;
}
int _close(int fd)
{
if (fd 》= stdin_fileno && fd 《= stderr_fileno)
return 0;
errno = ebadf;
return -1;
}
int _lseek(int fd, int ptr, int dir)
{
(void) fd;
(void) ptr;
(void) dir;
errno = ebadf;
return -1;
}
int _read(int fd, char *ptr, int len)
{
hal_statustypedef hstatus;
if (fd == stdin_fileno)
{
hstatus = hal_uart_receive(ghuart, (uint8_t *) ptr, 1, hal_max_delay);
if (hstatus == hal_ok)
return 1;
else
return eio;
}
errno = ebadf;
return -1;
}
int _fstat(int fd, struct stat *st)
{
if (fd 》= stdin_fileno && fd 《= stderr_fileno)
{
st-》st_mode = s_ifchr;
return 0;
}
errno = ebadf;
return 0;
}
#endif //#if !defined(os_use_semihosting)
添加这两个文件到工程,更新cmake,编译之后会发现,有几个系统函数重复定义了,被重复定义的函数位于src目录的syscalls.c文件中,我们把里面重复的几个函数删掉即可。
在main函数的初始化代码中添加对头文件的引用并注册重定向的串口号:
#include “retarget.h”
retargetinit(&huart1);
然后就可以愉快地使用printf和scanf啦:
char buf[100];
printf(“\r\nyour name: ”);
scanf(“%s”, buf);
printf(“\r\nhello, %s!\r\n”, buf);

消费者今年可以放心的使用5G吗
如何提前规避模块电源使用中的耐压测试风险
解析40G QSFP+ LR4光模块连接方案
榕树贷款探索智能金融服务新模式
智慧公安信息管理平台搭建情指一体化系统搭建
稚晖君:配置CLion用于STM32开发
PLC为何学以不能致用
华为Mate30 Pro相机得分更新,拍照得分加1分
一种高速ADC接口电路设计方案
魅族PRO5金色版高清图赏
超高频RFID射频接口电路设计
适合学生党的平价无线蓝牙耳机,好用便宜的蓝牙耳机推荐
电动汽车新快速充电标准下周公布
24多头点焊机控制原理图
【自适应计算在机器人领域的应用】连载一:什么是自适应机器人?
深天马与三安半导体签署战略合作协议 共同发力车载LED芯片领域
家庭影院屏幕选用技巧
智慧配电房数字化升级
决胜2024,欧美、日本电车市场发展放缓,中国车企开始登顶
AR增强现实技术以后会在哪一些领域发展