Linux下搭建STM32开发环境

方案

STM32开发一般使用官方的固件库,将MDK作为集成开发环境。MDK将代码编辑和工程构建全包了,这固然很方便,但是代码编辑功能较弱,而且MDK还是收费软件。于是便萌生了使用其他开发环境的想法。

果然,有免费的高质量方案:GNU Toolchain + STM32CubeMX + VSCode

  • GNU Toolchain:包括编译器、链接器、调试器和C语言标准库在内的一整套工具链
  • STM32CubeMX:图形化的软件配置工具,用来生成STM32初始化代码工程。ST官方已经停止更新固件库,STM32CubeMX是推荐的开发方式
  • VSCode:牛逼哄哄的代码编辑器,搭配强大的插件,从此忘记Vim和Emacs

上述的三个工具都是跨平台的,在Linux和Windows下都可以搭建,在Linux下搭建更方便。本文以Manjaro Linux为例,其他Linux发行版和Windows的搭建方法类似。

GNU Toolchain

GNU Arm Embedded Toolchain是目标平台为ARM嵌入式处理器的工具链软件。一般要安装编译器、调试器和函数库三个组件:

1
sudo pacman -S arm-none-eabi-gcc arm-none-eabi-gdb arm-none-eabi-newlib

arm-none-eabi-newlib是嵌入式平台下的C语言标准函数库,如果不安装可能会产生编译错误。Windows用户可以通过下载软件包来安装这套工具链,安装完后还需配置环境变量。

STM32CubeMX

ST官方的固件库已经停止更新,官方推荐用STM32CubeMX生成项目的初始化代码。STM32CubeMX是图形化界面,点击鼠标就能配置,比固件库方便很多。

STM32CubeMX依赖Java运行环境,要安装JRE 1.8:

1
sudo pacman -S jdk8-openjdk

在ST的官方网站上下载安装文件,我下载的是5.3.0版本。解压后有三个文件,Windows通过运行exe文件安装,Linux通过运行.linux后缀的文件安装:

1
sudo ./SetupSTM32CubeMX-5.3.0.linux

会跳出一个图形化安装界面,不停地点下一步就行。安装完成后,启动软件,点击File - New Project新建一个工程。此时会看到选择芯片型号的界面,可以通过勾选筛选条件过滤出目标芯片,我的芯片型号是STM32F103RCT6,ARM Cortex-M3架构。芯片型号选择好之后,点击Start Project,会有配置引脚的界面。在我的开发板上,PA8和PD2两个GPIO口驱动两个LED灯,点击对应的引脚,将它们配置为GPIO_Output

GPIO配置

接下来是时钟配置,暂时先保持默认的配置吧。

时钟配置

再接下来是项目配置,比较重要是的Toolchain/IDE那一项的选择。我选择的是Makefile,使用make来管理项目。点击右上方的GENERATE CODE按钮生成项目的代码。Windows用户还可以选择MDK-ARM,最后会生成代码以及MDK的项目文件,可以用MDK打开、编辑和构建工程。

项目配置

这里再插一句,上图最下方可以看到有个Firmware目录的设置,默认配置在用户的home目录下。如果嫌碍眼,可以打开Help - Updater Settings,修改成其它的目录。

工程的目录下生成了如下文件:

1
2
$ ls -F
Drivers/ Inc/ LedTest.ioc Makefile Src/ startup_stm32f103xe.s STM32F103RCTx_FLASH.ld

可以看到有个Makefile文件;startup_stm32f103xe.s是芯片的启动代码,是汇编语言;Drivers/文件夹中是自动生成的芯片底层代码,和固件库的组织很类似;Src/目录下有包括main.c在内的需要用户修改的源码文件。

VSCode

如果用VSCode做C/C++开发,推荐安装C/C++ Intelligence这个插件。用VSCode打开项目文件夹和Src/目录下的main.c文件,并在main函数的while循环中加入控制流水灯的代码:

VSCode

生成的代码都以HAL开头,函数名和固件库中的也很类似。可以看到,STM32CubeMX在main函数中自动添加了初始化的代码。打开MX_GPIO_Init函数还能看到将PA8和PD2两个GPIO口设置为输出的配置代码。

上图中有些宏定义下方有波浪线,将鼠标移动到附近还会提示「标识符未定义」。这时候按F1键,搜索Edit Configuration,打开json配置文件,添加一些信息帮助插件做代码检查和自动补全的工作。将Makefile中C_INCLUDESC_DEFS的内容添加到includePathdefines中。编译器的头文件目录也要添加到includePath中。修改后的配置文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"Inc",
"Drivers/STM32F1xx_HAL_Driver/Inc",
"Drivers/STM32F1xx_HAL_Driver/Inc/Legacy",
"Drivers/CMSIS/Device/ST/STM32F1xx/Include",
"Drivers/CMSIS/Include",
"/usr/arm-none-eabi/include",
"/usr/arm-none-eabi/include/c++/9.1.0",
"/usr/arm-none-eabi/include/c++/9.1.0/backward",
"/usr/lib/gcc/arm-none-eabi/9.1.0/include",
"/usr/lib/gcc/arm-none-eabi/9.1.0/include-fixed"
],
"defines": [
"USE_HAL_DRIVER",
"STM32F103xE"
],
"compilerPath": "/usr/bin/arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb",
"cStandard": "c99",
"cppStandard": "c++11",
"intelliSenseMode": "clang-x64"
}
],
"version": 4
}

现在就可以构建工程了,在项目的根目录下直接运行make命令,编译链接完成后,工程根目录下会多出一个build/目录,里面有我们需要的LedTest.bin文件。

stm32flash

最后将二进制文件烧写到芯片中。一般来说,用JLink是最方便的,不仅可以烧写软件还能够进行硬件调试。我没有JLink,手头只有一根可以供电和烧写软件的USB转串口线,所以我介绍另一款名为stm32flash的烧写软件。stm32flash需要自己下载源码后编译安装:

1
2
3
4
git clone https://github.com/stm32duino/stm32flash
cd stm32flash/
make
sudo make install

用跳线帽将板子的BOOT0引脚接3.3V,BOOT1引脚接地,用USB转串口线将板子和电脑连接,然后上电。我的Linux系统默认就有CH340芯片的驱动,上电后多了一个名为/dev/ttyUSB0的设备。可以用stm32flash查看串口的信息:

1
$ sudo stm32flash /dev/ttyUSB0

一切正常,然后用下面的命令将编译生成的二进制文件烧写入芯片中:

1
$ sudo stm32flash -w LedTest.bin -v -g 0x00 /dev/ttyUSB0

烧写完后就可以在板子上看到LED闪烁的效果。该软件更多的功能可以通过运行stm32flash -h命令查看。

参考

  1. 使用VSCode打造STM32开发环境