MacOS Based STM32 Development

MacOS Based STM32 Development

Notice: This article is only available in Chinese. :(


使用过 Intellij 系列 IDE 的同学都知道使用其进行开发的流畅体验。最近几年 ST 公司大力推行 HAL 库及 Cube 工具(MacOS 上可直接使用基于 Eclipse 二次开发的 CubeIDE),也为 MacOS 上的嵌入式开发提供了非常大的便捷,而 Jetbrains 公司的 CLion 对 Cube 相关工具的整合与适配更是锦上添花。何乐而不为呢?

对我而言,CLion 拥有的非常实用的功能主要有以下这些:

  • 代码自动补全,以及无处不在、无微不致的提示(连调函数时都会体贴地提示你形参名,泪目)
  • 代码文档注释(只需鼠标移动至函数、变量等对象下,即可出现格式化的文档注释。我在习惯 HAL 库的注释风格后也逐渐地养成在我写的或是移植的库中写好这样的注释的习惯,便于下次开发时快速上手)
  • 舒适的调试过程(在项目中加载 SVD 描述文件后即可在需要查看或调整寄存器值的时候方便地找到该寄存器的作用,而不用频繁地在参考手册和 IDE 之间来回切换)
  • 静态检查(大赞 Clang-Tidy,编译前就能检查出因粗心等犯的低级错误,同时还能让你在做项目时不断地积累 Best Practices)
  • 非常便捷地重构,再也不用查找替换了
  • 强迫症必须的拼写检查
  • 集成 Git,也有内置的版本管理器,再也不怕写的东西突然消失了
  • ...

千言万语不如一张图,先给几张图片感受一下:

这篇文章将介绍为 MacOS 上的 CLion 配置开发环境以及创建 HAL 库项目的标准流程。在学校的课程设计中,因授课的要求需要使用标准库,在本文的最后也会进行介绍。

准备工具链

这一步应该是本文中最简单的环节,直接一个命令搞定:

brew install arm-none-eabi-gcc

这个是 ARM 官方为 GCC(GNU Compiler Collection) 提供的工具链。与 MDK 不同,这个工具链是完全免费的。
至于 ARM-GCC 与 MDK 两个工具链孰优孰劣,待我后来有了深入研究后再来写一篇。

为 STLink V3 准备支持版本的 OpenOCD

0.10.1版本的 openocd 不支持 stlink v3,后来在网上搜了搜,找到了这篇文章:https://mbd.kleier.net/integrating-st-link-v3.html
0.10.0-rc2版本的 openocd 便支持 stlink v3 了,只是因为是 rc 版本,还没有正式释出,故需要自己动手编译。

这个 rc 版本的 openocd 源在 sourceforge 上,可直接访问这个地址下载到本地:
https://sourceforge.net/p/openocd/code/ci/v0.10.0-rc2/tree/

编译前安装编译工具:brew install autoconf / automake / libtool。
另外,stlink 有依赖 libusb,故应先通过brew install libusb命令安装libusb库。(若有出现冲突,需先将原来的删除后再brew link libusb

然后进入到项目根目录,执行下面的命令来完成编译:

./configure --enable-stlink --enable-jlink
make
sudo make install

准备 CubeMX 工具

从 ST 官网下载安装 CubeMX。这是个用 Java 写的跨平台程序,不知道什么 bug 会导致有时双击打不开,这时可以右键进入包中,找到二进制文件后拖到终端中运行即可。

CLion HAL 库 项目创建与配置

  1. CLion 中新建项目,选项卡中选择嵌入式开发的 STM32CubeMX
  2. 双击 .ioc 配置文件,打开 STM32CubeMX 配置芯片(CLion 默认 F0 ,直接更换覆盖即可)
  3. 在 Project Manager/Project 选项卡中: Project Location 回退一层,再在 Project Name 中键入项目名,项目文件夹为目录上一级(同 CLion) Toolchain/IDE 选择 SW4STM32 ,勾选右边
    a. Project Manager/Code Generator 选项卡中:
    b. 选择 Copy only the necessary library files 勾选 Generate peripheral initialization as a pair of ‘.c/.h’ files per peripheral
    c. 完成芯片配置
  4. 点击 Generate code ,返回到 CLion
  5. CLion 已发现项目配置的更改,并识别到了芯片,在弹出的 Board Config Files 对话框中选择芯片对应官方开发体验板,例如 STM32F411 对应 STM32F4Discovery,点击复制
  6. 若提示未检测到 cmake 文件,文件->从源新建 CMake 项目,勾选包含 .ioc 配置文件的文件夹,自动生成 cmakelist 文件
  7. 打开 Preferences ,构建、执行、部署->工具链,调试器选择 Bundled GDB,平时在本地调试算法注意要调回 LLDB
  8. 尝试编译,若成功将会在 cmake-build-debug 文件夹下;若出现重复定义的错误提示,重新生成代码即可

CLion 标准外设库 项目创建与配置

  1. 在 CLion 中新建项目,选项卡中选择嵌入式开发的 STM32CubeMX
  2. 双击 .ioc 配置文件,打开 STM32CubeMX 配置芯片( CLion 默认 F0 ,直接覆盖保存即可)
  3. Project Manager/Project 选项卡中: Project Location 回退一层,再在Project Name中键入项目名,项目文件夹为目录上一级(同CLion) Toolchain/IDE 选择 SW4STM32 ,勾选右边
  4. 做完步骤三后直接点击 Generate code ,返回到 CLion
  5. CLion 已发现项目配置的更改,并识别到了芯片,在弹出的 Board Config Files 对话框中选择芯片对应官方开发体验板,例如 STM32F411对应 STM32F4Discovery,点击复制
    若提示未检测到cmake文件,文件->从源新建CMake项目,勾选包含 .ioc 配置文件的文件夹,自动生成cmakelist文件
  6. 打开 Preferences ,构建、执行、部署->工具链,调试器选择 Bundled GDB,平时调试算法注意要调回 LLDB
  7. 自动生成的项目文件夹仅保留 CmakeLists.txt、 cmake-build-debug 和 startup,其他可直接删除
  8. 复制 STM32F10x_FWLib 即标准外设库文件夹,CORE(删除 startup script)、HARDWARE、USER 等用户文件夹到项目中,并分别将其中的C语言头文件和源文件移动到各自的 Inc 和 Src 文件夹中
  9. 编辑 CMakeLists 文件:
    1. 更改 Inc Src 包含路径为
      include_directories(CORE/Inc HARDWARE/Inc STM32F10x_FWLib/Inc SYSTEM/Inc USER/Inc)
      file(GLOB_RECURSE SOURCES "startup/*.*" "CORE/*.*" "HARDWARE/*.*" "STM32F10x_FWLib/*.*" "SYSTEM/*.*" "USER/*.*")

      对应使用的单片机种类编辑并修改编译定义

      #add_definitions(-DUSE_HAL_DRIVER -DSTM32F103xB -DUSE_STDPERIPH_DRIVER -DSTM32F10x_HD) # successed trial
      #add_definitions(-DUSE_HAL_DRIVER -DSTM32F411xE) # F411 HAL Driver
      #add_definitions(-DUSE_HAL_DRIVER -DSTM32F103xE) # F103 HAL Driver
      add_definitions(-DUSE_STDPERIPH_DRIVER -DSTM32F10x_HD) # F10x STDPERIPH Driver
    2. 添加链接选项,解决链接出错和 printf 不能使用 float 的问题
      add_link_options(-specs=nano.specs -specs=nosys.specs -u _printf_float)
  10. 进入 USER/Inc/stm32f10x.h 文件,取消F10x产品线(STM32F10X_HD)对应注释:
     #define STM32F10X_HD    /*!< STM32F10X_HD: STM32 High density devices */

    进入 CORE/Src/core_cm3.c 文件,修改 第736行 和 第753行 的内联汇编指令:

    //736行
    __ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
    //753行
    __ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );

    改成

    //736行
    __ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
    //753行
    __ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );

    进入 SYSTEM/Src/sys.c 文件,注释掉下列的 设置栈顶地址的内联汇编指令:

    //设置栈顶地址
    //addr:栈顶地址
    __asm void MSR_MSP(u32 addr)
    {
        MSR MSP, r0 //set Main Stack value
        BX r14
    }
  11. 配置完成,测试是否能通过编译

在线调试配置:

  1. 第一次配置 debug 时需在 cubemx 中配置 jtag 口4pin或5pin调试接口,再使用 CubeProgrammer 下载至单片机中
  2. 在 CLion 中 Debug Profile 中编辑运行配置,profile 文件应按照下表对应选择:
    • stm32f103c8 → stm32f103c8_blue_pill.cfg
    • stm32f103rc/rb → st-nucleo_f103rb.cfg
    • stm32f401/411 → st_nucleo_f4.cfg
    • stm32f429 → stm32f429discovery.cfg
      若上表没有当前使用的芯片,则需从网上搜索使用该芯片的官方开发版型号并在列表中选择,或者尝试自己复制与修改相邻型号芯片的 Profile 文件。该文件定义了调试器配置、调试连接初始化、调试速率、target 复位方法等相关信息,若该文件不正确,点击调试按钮进入调试模式时 OpenOCD 即会报错。
  3. 点击 Debug,选择 外设 选项卡,从文件夹中找到单片机型号对应的 .swd 文件,便于查看寄存器作用及其当前值
  4. 下断点,点击重启 Debug 开始调试

参考

  1. 配置CLion用于STM32开发【优雅の嵌入式开发】