配置clion用于stm32开发

配置clion用于stm32开发

以stm32f103ZET6为例

2022.4.8更新(解决了OCD无法调试的问题)

之前配置完环境后,就只是实验了一下烧录的功能,一直没有尝试使用ocd的调试功能。
后来有,有人私信我,询问我ocd能否进行调试,这才发现我的ocd没办法进行调试。起初以为是ocd的版本和clion的版本不匹配造成的,后来经过实验并不是这样。最后,发现是我的ocd的安装目录中存在空格,导致我的ocd无法调试。更改完安装目录(记得把环境变量也改掉哦),重启电脑后,调试功能就能正常使用了。

0.开始之前

从接触单片机开始,基本就一直用着keil在进行编程,中间又参加了智能车的比赛,了解到了IARAURIX-studio等IDE,但是始终没有开始学习C语言时,用的VS那种感觉。
之后,又尝试了一下VS+VisualGDB还有VScode上面的Keil Assistant的这款插件。
但是VScode上时不时仍需要打开keilVisualGDB用的破解版时不时出一些问题,正版太贵,属实买不起。

作为稚晖君的铁粉,自然知道dalao使用的是clion开发,正逢比赛延期,留出了些许空闲的时间,就基于稚晖君dalao的写的clion配置教程,折腾了一番。
虽说这篇文章可以说是保姆级教程了,可是我在配置过程中仍遇到了不少问题,花费了很多时间去查找解决方法,故特写此篇,以此记录。

1.配置前的准备

软件准备

  • Windows 10
  • STM32CubeMX
  • clion2021
  • MinGW
  • OpenOCD
  • arm-none-eabi-gcc

硬件准备

  • STM32F103ZET6
    • 正点原子的核心板
  • J-Link

软件安装

安装的时候,注意安装路径上不要出现中文

  1. STM32CubeMX
    这是st开发的代码生成器,基于hal库的。正常安装就行。

  2. OpenOCD
    这是一个对stm32的下载调试仿真的开源工具包,经常见到,之前使用VisualGDB时,也有见到过。下载好后,直接解压即可,无需安装。

  3. MinGW
    clion使用这个工具包的环境来配置工具链。安装完后,打开,进行组件的下载。右键单击选择Mark for Installation,将Basic Setup中的选项都勾选上。最后选择installation - Mark All Upgrades即可完成组件的安装。如下图:
    MinGW组件安装

  4. arm-none-eabi-gcc
    这是交叉工具链??相当于一个编译器,将C/C++翻译成arm架构的芯片能懂的语言的编译器??(大概是这个意思)下载压缩包即可。
    下载压缩包就行

也可以像我这样,把上面这个四个软件放在一个文件夹下

2022.2.18

不要和我一样把OpenOCD的文件夹放在文件夹“Program Files”中,理由前面说过了。

  1. clion
    这个的安装应该是没什么问题,当然clion是收费的,我们学生的话可以去学信网下载学籍在线验证报告,然后在clion官网上申请教育认证,一周左右应该就能申请下来,能免费使用一年。当然你也可以选择pojie版。
    选择官方文件认证

最后打开系统的环境变量(右击此电脑->属性->高级系统设置->环境变量),找到系统变量中的PATH变量,点击编辑,在当中新建三个路径,分别是OpenOCDMinGWarm-none-eabi-gcc三个软件安装目录下的bin文件夹的安装路径。

重启电脑,打开命令行(win+R后,输入cmd),分别输入一下三行代码:

  • gcc -v
  • arm-none-eabi-gcc -v
  • openocd -v

如果都有输出,那说明环境安装成功。

2.Clion的配置

打开Clion,选择Customize - All settings - Build,Execution,Deployment - Toolchains,选择一下MinGW环境,应该会自动帮你找到的,如果找不到的话,就手动添加一下。
大致是:

  • Environment:...\MinGW
  • Make:...\MinGW\bin\mingw32-make.exe
  • C Compiler:...\MinGW\bin\gcc.exe
  • C++ Compiler:...\MinGW\bin\g++.exe

Debugger的路径改成...\gcc-arm-none-eabi\bin\arm-none-eabi-gdb.exe

这里和稚晖君的配置有所出入,我按照稚晖君的设置反而无法使用,而我这个配置在我的电脑上是可以使用的。
具体什么原因我也不清楚,我对于编译器啊工具链啊之类的知之甚少。

这个选项卡的最终效果是这样

然后点击CMake,确认一下是否选择了刚才的配置

再选择Embedded Development选项卡,设置一下OpenOCDCubeMX的位置。一般为...\OpenOCD\bin\openocd.exe...\STM32CubeMX\STM32CubeMX.exe
点击一旁的Test按键,确认一下路径是否正确。
如果出现绿色的提示框,则说明路径正确。

出现绿色的提示框

配置完成,关闭设置。

3.新建工程

点击Projects - New Project - STM32CubeMX新建工程,例如:

点击create后会生成一个.ioc文件,这个文件跟使用STM32CubeMX直接创建的是一样的,点击图中的链接可以跳转到STM32CubeMX中打开这个ioc文件:

默认选中的芯片型号是STM32F030F4Px,我们可以在CubeMX中重新选择自己需要的芯片。
这次实验选择的是原子的开发板,故我配置了两个GPIO口PB5PE5用于流水灯,又配置了串口。相关参数见下图

需要注意的是,就是在下面的设置中项目名称和项目路径一定要和在Clion中建立的一致,这样生成的工程文件才会覆盖Clion中的文件,否则会另外生成一个文件夹,Clion就无法读取了。

还有生成的IDE类型选择是SW4STM32

每次修改完点Generate之后,弹窗直接点CloseClion里面会自动更新文件。

第一次设置完回到Clion会弹出一个板卡选择窗口:

国外的软件总喜欢选择开发板,这玩意儿不应该按芯片来选吗( ̄_, ̄ ),那个PlatformIO貌似也是这样的,这个配置先不选,直接点Cancel

4.编译工程

编写代码的时候,把自己的代码写在

/* USER CODE BEGIN N */
// 在此处添加你的代码
/* USER CODE END N */

这类注释的中间,这样之后用CubeMX重新生成文件时不会将你写的代码删除掉。

在IDE底栏的CMake选项卡中如果没有提示错误,说明工程配置就没问题了。

点击这个按钮可以更新CMake工程:

顶栏的三个图标分别是编译下载调试

随便写个流水灯的代码,点击编译,顺利的话,应该能看到下方命令行中编译的输出。
成功生成了用于烧录的hexbin文件。

5.烧录程序

之前使用的IDE有关烧录器的配置基本都是通过选项卡的形式配置的。而这里的配置需要依靠代码实现(貌似dalao们更钟爱使用代码来设置,VScode中都这样)。

点击编译按钮旁边的配置栏下拉,选择Edit Configurations,打开配置窗口。
可以看到没有设置板子的config文件所以出现警告错误,这个配置文件就是前面说的需要自己生成的文件。

因此,我们在工程根目录下新建一个configuration文件夹,在里面新建一个配置文件jlink.cfg,内容为

source [find interface/jlink.cfg]

transport select swd

source [find target/stm32f1x.cfg]

下面给出的是稚晖君给出的Dap-LinkST-Link的配置文件内容:

Dap-Link

# 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

ST-Link

# choose st-link/j-link/dap-link etc.
#adapter driver cmsis-dap
#transport select swd
source [find interface/stlink.cfg]
transport select hla_swd
source [find target/stm32f1x.cfg]
# download speed = 10MHz
adapter speed 10000

其他的芯片或者下载器的配置,可以参考OpenOCD自带的一系列配置文件,路径在OpenOCD安装目录的share\openocd\scripts下:

只需要关注这几个目录:

  • board:板卡配置,各种官方板卡
  • interface:仿真器类型配置,比如ST-Link、CMSIS-DAP等都在里面
  • target:芯片类型配置,STM32F1xx、STM32L0XX等等都在里面

设置好配置文件之后,就可以点击下载或者调试按钮进行下载和在线调试了。

在配置文件中不要加reset_config srst_only这一句,会导致下载失败,这一句是指示系统重启的,删除不影响下载。

如果你使用的J-Link的话,正常情况下到了这一步,和我一样应该仍然无法下载,貌似是keil的原因,或者是J-Link本身的问题。需要先插上J-Link,然后用zadig这个软件,将J-Link重新设置为普通USB设备。

选择Options - List All Devices,选择J-Link后,按下Reinstall Driver即可。

只有就能正常使用了。(但这样Keil就识别不了这个jlink了,需要重新安装固件)

6.其他

关于CMake

CLion中组织编译规则都是基于CMakeLists.txt文件的,就是根据代码来配置工程,据说功能非常强大,用熟了之后应该还是非常方便的。不过那些个源代码目录和include文件夹路径的添加,简单看一下这个文件的内容还是很好辨认的。甚至,还有一份自动生成的CMakeLists_template.txt文件可供参考学习。

include_directories(
        Core/Inc
        UserApp
// 其他include目录
)


file(GLOB_RECURSE SOURCES
        "startup/*.*"
        "Drivers/*.*"
        "Core/*.*"
        "UserApp/*.*"
        "3rdParty/*.*"
// *.*表示通配符,也就是这个文件夹里的所有文件都会被编译
        )

关于编译错误

这部分问题,我暂时没有遇到过,故全部摘自稚晖君的文章

  1. 如果移动了工程文件夹的话,最好打开.ioc文件重新Generate一下再编译,可以解决很多错误。
  2. 遇到任何CMake相关的报错,一般是由于缓存没有更新引起的,可以在CLion中选Tools-CMake-Reset Cache and Reload Project即可解决。

关于printf的重定向

正点原子给出的参考例程中,有关printf的重定向是将fputc这个函数经行重定向,这个可以在正点原子的usart.c文件中看到,如下

// 加入以下代码,支持printf函数,而不需要选择use MicroLIB	  
#if 1
#pragma import(__use_no_semihosting)             
// 标准库需要的支持函数                 
struct __FILE 
{ 
    int handle; 
}; 

FILE __stdout;       
// 定义_sys_exit()以避免使用半主机模式    
void _sys_exit(int x) 
{ 
    x = x; 
} 

// 重定义fputc函数 
int fputc(int ch, FILE *f)
{      
    while((USART1->SR&0X40)==0);//循环发送,直到发送完毕   
    USART1->DR = (u8) ch;      
    return ch;
}
#endif 

但若直接移植,在clion中是无法使用的,稚晖君也解释了这一问题:

其中的FILE定义在stdio.h头文件中,所以需要在项目中包含这个头文件,但是经过测试发现,Keil里面包含的是MDK\ARM\ARMCC\include这个目录下的stdio.h,而在Clion中是不会链接到这个文件的。因此如果在Clion中也按之前的方法进行重定向,会发现printf没有任何输出。
Clion中链接的是GNU-Tools-ARM-Embedded\arm-none-eabi\include里面的stdio.h

于是,需要新建一个retarget.h文件,内容为:

#ifndef _RETARGET_H__
#define _RETARGET_H__#include "stm32f1xx_hal.h"
#include <sys/stat.h>
#include <stdio.h>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 <errno.h>
#include <sys/time.h>
#include <sys/times.h>
#include <retarget.h>
#include <stdint.h>#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)

添加这两个文件至工程,然后编译的时候会发现,几个函数在syscalls.c文件中被重复定义,将syscalls.c中的这几个函数删掉即可。

在main函数的初始化代码中添加对头文件的引用并注册重定向的串口号:

#include "retarget.h"RetargetInit(&huart1);

稚晖君的代码中貌似没有如原子那样配置避免使用半主机模式的函数,具体的也不是很清楚。

稚晖君的代码很完善的将串口读取的函数也重定向了一遍,意味着咱们也可以愉快的使用scanf了。
在使用scanf输入时要注意,向串口发送的数据必须包含空格等识别符,否则scanf不会执行。
当然在使用scanf时,会像命令行中一样,程序运行到scanf时,会卡死在这里,等待输入。如果想让程序正常运行的话还是需要使用中断来接收。

另外,稚晖君还提供了第二种方法,但是我没有成功,暂且先列出来:

直接修改CMakeList.txt,加入下述编译选项

set(COMMON_FLAGS "-specs=nosys.specs -specs=nano.specs -u _printf_float -u _scanf_float")

clion的一些设置

clion提供了一些有用的插件,其中就包括中文插件。

进入Settings - Plugins - Marketplace,在搜索框中搜索chinese
找到Chinese Language Pack,点击install即可。
如果下载速度极慢,导致安装不成功,可以在这里下载。
在设置里,点击Install Plugin from Disk,找到下载好的文件,安装即可

可以在外观-背景图像中设置clion的背景

效果如下:

7.结束

啊哈哈哈哈,这样就基本上完成了配置,可以希望在clion上开发能带来快乐,大致上把我在配置上遇到的问题都写明了,另外,关于软件的下载,俺全程架着梯子,不知道没梯子行不行 (*  ̄3)(ε ̄ *)

  • 50
    点赞
  • 175
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 24
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 24
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

弄曲幽篁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值