Skip to content

Wiki

Linux

About 50 min read

Existing English translations were reused. 9 current source blocks remain in Simplified Chinese, without triggering paid translation.

1.Environment Introduction

Introduction to the tutorial environment:

  1. System: Fedora 42 KDE Edition Linux

  2. System Kernel: Linux 6.15.6-200.fc42.x86_64

  3. Architecture: X86_64

Other Linux environments are also acceptable.

2.Install various environments

2.1.Install C/C++ environment


# debian系
sudo apt-get install gcc g++ gdb cmake-gui make

# rhel系
sudo dnf install gcc g++ gdb cmake-gui make

Check whether the environment was installed successfully

gcc -v
g++ -v
gdb -v
cmake --version

Next, test whether C/C++ can be compiled normally. Find a folder that stores C++ code, then cd into it in the terminal.

Then create a .cpp file and edit it with vim

vim hello.cpp

Copy the following code into this file

#include <iostream> 
int main(int argc,char **argv) 
{ 
    std::cout << "你好,机电创新学会!" << std::endl; 
    return 0; 
}

Then compile

g++ -o hello hello.cpp
ls

Run

./hello

This indicates that the environment has already been configured.

2.2.Install CubeMX

Download address:

https://www.st.com.cn/zh/development-tools/stm32cubemx.html

It is recommended to download version 6.14.1 (do not download 6.15.0; this version has bugs, and it is unknown when they will be fixed later).

Extract it

Open this software with root privileges.SetupSTM32CubeMX-6.15.0

sudo ./SetupSTM32CubeMX-6.15.0

In the newly popped-up interface, just keep clicking Next. After the installation is complete, if the screen shown below appears, it has succeeded.

/usr/local/STMicroelectronics/STM32Cube/STM32CubeMXEnter this folder, then open a terminal and input

./STM32CubeMX

Click Help

Select Manage embedded software packages, and check the first latest firmware for STM32F1, F4, and H7.

Click install

Log in to the account

Then wait for the download and installation to complete

Just finish downloading it and you're good.

Next, you can configure the CubeMX application to create a desktop shortcut for quick access. For detailed instructions, see the Appimage section of theVinci Robot Team Linux Introductory Tutorial; you can use ctrl+F to quickly locate this section.

The desktop shortcut is as follows:

[Desktop Entry]
Name=STM32CubeMX
Exec=/usr/local/STMicroelectronics/STM32Cube/STM32CubeMX/STM32CubeMX
Icon=/usr/local/STMicroelectronics/STM32Cube/STM32CubeMX/help/STM32CubeMX.png
Type=Application
Categories=Development;Electronics;Embedded;
Comment=STM32CubeMX configuration and code generation tool
Terminal=false

Follow the tutorial, and you can achieve this effect.

2.3.Install VSCode

https://code.visualstudio.com/Download

If it is a Debian-based system, download the deb; if it is an RHEL-based system, download the rpm.

After downloading, click the browser, find the folder containing this installation package, and open a terminal at that path.

Debian-based: entersudo apt install ./codeThen press thetabkey to complete the filename, and press Enter.

RHEL-based: entersudo dnf install ./codethen presstabkey to complete the filename, and press Enter.

For example, after completion:

sudo dnf install ./code-1.102.1-1752598767.el8.x86_64.rpm

Then open VSCode and enter the following command in the terminal.

code

Then install some plugins

All of the following need to be installed.

2.4.Install the ARM GNU toolchain

Comparison of compilation tools:

特性 ARM GCC (GNU 工具链) Keil AC5 (ARM Compiler 5) Keil AC6 (ARM Compiler 6)
核心身份 基于GNU GPL的开源编译器 ARM自家的传统编译器 基于LLVM/Clang的现代编译器
许可模式 免费、开源 商业收费(包含在MDK中) 商业收费(包含在MDK中)
代码生成/优化 良好,持续改进 优秀(尤其在小代码尺寸上) 极佳,在性能与尺寸间有最佳平衡
标准兼容性 紧跟最新C/C++标准(如C17,C++17/20) 主要支持C++98,较陈旧 支持现代C++(C++11/14/17),兼容性更好
错误/警告信息 比较清晰易懂 相对晦涩 非常清晰和友好,类似GCC/Clang
与Keil MDK集成 需要手动配置或通过CubeIDE 原生、无缝集成 原生、无缝集成,是ARM推荐选择
链接脚本 使用自有的链接脚本语法(.ld文件) 使用ARM自家的分散加载文件语法(.sct) 使用ARM自家的分散加载文件语法(.sct)
汇编语法 使用GNU汇编语法(.S文件) 使用ARM汇编语法(.s) 使用ARM汇编语法(.s),但AC6更严格
生态与未来 生态强大,是很多开源项目(如Zephyr,ESP-IDF)和IDE(CubeIDE,VS Code)的首选 处于维护模式,ARM不再增加新功能,不推荐新项目使用 是ARM的未来和主力,持续更新和优化

2.4.1.Install

It is recommended to install using theofficial method.

2.4.1.1.Method 1 (official website method)

https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads

Enter the download directory and open a terminal

Enter the following command in the terminal to copy the compiler tar archive to the folder where you store your programs (you decide this folder yourself; it is recommended to put it in the home partition, just don't delete it later).

The specific command iscp ./arm-gnuthen presstabto complete it, then a space, followed by the path of the folder you want to copy to.

For example, the following command:

cp ./arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi.tar.xz ~/UserFolder/Applications/

Then enter the copied folder:

cd ~/UserFolder/Applications/

Enter in the terminaltar -xvf ./arm-gnuand presstabto complete.

For example, after I complete it:

 tar -xvf ./arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi.tar.xz

Then enter this decompressed folder

cd ./arm-gnuaccording totabcomplete.

cd ./arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/
cd ./bin

View folder path

pwd

Copy it/home/tungchiahui/UserFolder/Applications/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/bin

Then the environment needs to be configured.

vim ~/.bashrc

At the end, enter the following command, replacing the following~/UserFolder/Applications/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/binwith the path you just copied;/home/用户名you can use~instead.

export PATH=/home/tungchiahui/UserFolder/Applications/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/bin:$PATH

Load Environment

source ~/.bashrc
2.4.1.2.Method 2 (System Repository Method)

This method is not recommended


# Debian系
sudo apt install arm-none-eabi-gcc

# Rhel系
sudo dnf install arm-none-eabi-gcc

2.4.2.Test

Check version

arm-none-eabi-gcc -v

2.5.Install JLink driver

2.5.1.Install the libreadline library.

For flashing, we use the JLinkExe command, and JLinkExe uses the libreadline library, so we need to install the libreadline library. Run the following command to install it:


# debian系
sudo apt-get install libreadline-dev

# rhel系
sudo dnf install readline-devel

2.5.2.Install JLink Driver

https://www.segger.com/downloads/jlink/

It is Debian-based; download the 64-bit DEB

For RHEL-based systems, download the 64-bit RPM.

(The 64-bit here refers to amd64 and X86_64. If you are on ARM64, please download the 64-bit version under Linux ARM below.)

Open the downloaded folder and open a terminal

Thensudo apt install ./JLinkThen press Tab to complete.

Thensudo dnf install ./JLinkThen press Tab to complete.

sudo dnf install ./JLink_Linux_V852_x86_64.rpm

Check whether the installation was successful

JLinkExe

We click No, and then we enter Commander interactive mode. In this mode, we can execute various J-Link commands provided by Commander to connect, configure the debugger, download programs or files to the target device, and so on. Interested readers can learn about it on their own.

Execute the "q" command to exit this mode.

2.5.3.Download and install Ozone

https://www.segger.com/products/development-tools/ozone-j-link-debugger/

It is Debian-based; download the 64-bit DEB

For RHEL-based systems, download the 64-bit RPM.

(The 64-bit here refers to amd64 and X86_64. If you are on ARM64, please download the 64-bit version under Linux ARM below.)

Thensudo apt install ./OzoneThen press Tab to complete.

Thensudo dnf install ./OzoneThen press Tab to complete.

sudo dnf install ./Ozone_Linux_V338g_x86_64.rpm

2.5.4.Test

Open the terminal and enter

ozone

2.6.Download SVD

https://www.st.com.cn/content/st_com/zh.html

Search for the chip model in the search, such as stm32f103c8t6.

Point CAD resource

Download SVD; just click the area in the red box with the mouse to download it.

After decompression, the SVD files for the F1 series can be obtained.

Then download and extract F4 and H7 as well, and you're done. (They can be extracted into the same folder.)

Then open a terminal in the above folder

Copy all these folders to Ozone's Config/Peripherals/directory. (You need to confirm in advance whether Ozone's configuration uses this path before copying.)

sudo cp ./*.svd /opt/SEGGER/Ozone_V338g/Config/Peripherals/

3.Project Creation and Testing

3.1.Create a project using CubeMX

Click to enter the microcontroller selection button

Search for the corresponding chip and double-click the corresponding chip option.

Do some configuration. The following are all very basic things that you definitely already know before watching this video.

Just open any IO for testing, such as the GPIO of an LED.

FreeRTOS also needs to be configured.

These folders also need to be configured properly. Finally, select CMake for Toolchain and GCC for the compiler (it is normal that there is no compiler selection option in versions 6.14.1 and earlier).

(However, CubeMX6.15.0 there is a bug: selecting the GCC compiler here has no effect, and you still need to manually select the compiler later. This bug may be fixed in the future.)

3.2.Configure and compile the project

Open a terminal in the project folder

Then open vscode

code .

After entering VSCode, click CMakeLists.txt in the directory.

Check whether the following line exists around line 25. If not, you need to manually add these two lines for it. (Version 6.14.1 does not have this bug.)

tips1: This is the bug in the CubeMX6.15.0 version mentioned above. Because this version added support for the Clang compiler, CubeMX also supports the operation of selecting a compiler, but this option was probably not written well by the engineer. No matter which compiler is selected, it will not select the compiler we chose, so we need to select it manually.

tips2:这CubeMX6.15.0有第二个bug,这个工作区根CMakeLists.txt他说了只会生成一次,后续不会再重新覆盖生成,但是发现每次在CubeMX修改配置后,然后重新生成代码,其他命令都被保留了,就这个命令不会被保留。不知道后续会不会被修复,或者直接修复上面tips1的bug.所以每次重新配置CubeMX后,需要再把这句加上。


# Include toolchain file
include("cmake/gcc-arm-none-eabi.cmake")

Press Ctrl+~ to open the built-in terminal.

Use the command below to create and enter the build folder

mkdir build
cd build

Next, use the cmake command to generate the makefile.

cmake ..

Check whether ARM's C/C++ and the assembler compiler have been found (if not, please check whether there are any mistakes in the tutorial above)

Then use the make command to compile, the command ismakeormake -jxx, here xx is the number of CPU threads you want to use for compilation. For example, my computer has 8 cores and 16 threads, so I can set xx to a number lower than 16. Andmakeuses one thread by default. If you do not know how many threads your CPU has, then just honestly use themakecommand, and do not use themake -jxxcommand.

make -j16

This means the compilation was successful.

3.3.Configure code hints

In VSCode press Ctrl+Shift+P, search for clangd, and select download language service.

Select Install in the lower right corner, and after installation is complete, the prompt shown in the figure below will appear.

Next, disable the code hinting feature of the C/C++ plugin (if this interface is not available, please continue reading below).

如果没有上图的弹窗,可以进行手动关闭,依然是ctrl shift P,输入settings然后找到如下图的选项

Find the option shown in the figure below and change it to disabled.

"C_Cpp.intelliSenseEngine": "disabled"

In VSCode, press Ctrl+Shift+P again, search for clangd, and select restart clangd language service (the code must have been compiled once before restarting the clangd language service).

At this point, you can see that the header files in the code are all recognized correctly, and code suggestions also work properly.

⚠️注意:Clangd 默认找的是 本机系统的 libc/include 路径(比如 x86_64 的 /usr/include) ,而我们工程里面实际使用的是 ARM 工具链的头文件路径 ,这就有概率导致包含C/C++库函数的头文件报错

For example:

Here, #include <math.h> shows that the header file cannot be found, but when we compile, no error is reported, indicating that there is a problem with the clangd configuration. The following introduces a solution:

  1. Run the following command to obtain the standard include paths used by ARM GCC:
arm-none-eabi-gcc -x c -E -v - </dev/null

  1. Create a .clangd file in the project root directory and include your header file paths in it (replace the content inside the quotation marks with your own ARM GCC header file path).
CompileFlags:
  Add: [
    "-isystem", "/home/xiaofang/Applications/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/14.3.1/include",
    "-isystem", "/home/xiaofang/Applications/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/lib/gcc/arm-none-eabi/14.3.1/include-fixed",
    "-isystem", "/home/xiaofang/Applications/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/arm-none-eabi/include"
  ]

Save; then refresh clangd, and the header file prompts will be normal.

3.4.Port the standard C/C++ engineering template of the Vinci robot team

Clone the repository using the git clone command:https://github.com/tungchiahui/CubeMX_MDK5to6_Template

git clone https://github.com/tungchiahui/CubeMX_MDK5to6_Template.git

把仓库里的“工程文件移植”文件夹里的 所有内容 复制到我们CMake工程的目录里。

Then open the applications folder, and in the Src and Inc folders create led_task.cpp and led_task.h respectively, with the contents as follows:

led_task.cpp:

#include "led_task.h"
#include "cmsis_os.h"
#include "stm32f1xx_hal.h" 

GPIO_PinState pinstate = GPIO_PIN_RESET;

extern "C"
void StartDefaultTask(void *argument)
{
  for(;;)
  {
    HAL_GPIO_WritePin(GPIOC,GPIO_PIN_13,pinstate);
    pinstate = (pinstate == GPIO_PIN_RESET) ? GPIO_PIN_SET : GPIO_PIN_RESET;
    osDelay(500);
  }
}

led_task.h:

#ifndef __LED_TASK_H_
#define __LED_TASK_H_

#ifdef __cplusplus
extern "C"
{
#endif

#include "cpp_interface.h"

#ifdef __cplusplus
}
#endif

#endif

然后打开cmake/user文件夹下的CMakeLists.txt,把刚才新建的led_task.cpp添加上去。

详细介绍(可以不看):这里的cmake/stm32cubemx下的CMakeLists.txt是被CubeMX管理的,你重新用CubeMX生成新代码后,这个文件里的东西会被覆盖。而工作区根目录下的CMakeLists.txt是不会被重新覆盖的,而且给我们留了一些区域加源文件和头文件,但是这样会让这个文件太过于嘈杂。所以我们选择新建一个user文件夹,然后在这里面弄一个CMakeLists.txt,再用顶层CMakeLists.txt去加载这个子CMakeLists.txt,这个子CMakeLists.txt方便咱们修改,文件结构也更加明显。(这些都不需要咱们自己创建,我已经给创建到 工程文件移植 里了,你在上面复制的时候已经复制过来了)

Then go to the top-level CMakeLists.txt and add this statement to reference our own CMakeLists.txt.


# Add USER generated sources
add_subdirectory(cmake/user)

The great task is accomplished; let's try compiling once. As shown in the figure below, all the newly added files have been compiled.

cmake ..
make

Then reference the main.c header file in cpp_interface.h, and call the cpp_main() function at this location in the main function. (In my case, RTOS is enabled, so the cpp_main function needs to be called before starting the RTOS. If you are using a bare-metal program without an RTOS, simply call cpp_main above while (1).)

Then modify the isRTOS macro in cpp_interface.h to let the program know whether you have enabled the RTOS. If it is enabled, the macro should be 1; for bare metal, set it to 0.

For other, more detailed information about the STM32 C/C++ project, please see Vinci Robotics Team Microcontroller Tutorial.

At this point, compiling the program in the build folder is found to be successful!

cmake ..
make

3.5.Download the program to the board

3.5.1.Configure CMake to generate .bin and .hex files

Before downloading the program to the board, we need to take a look at what files were actually generated by our previous compilation.

From the figure below, it can be seen that only the .elf file was generated, and not the .bin and .hex files that we commonly see.

We need to modify CMakeLists.txt in the workspace again so that .hex and .bin are generated during compilation (no way around it—it has to be this troublesome; I don't know why CubeMX doesn't do it all properly).


# 生成 .bin 和 .hex 文件
find_program(OBJCOPY arm-none-eabi-objcopy REQUIRED)

add_custom_command(TARGET ${CMAKE_PROJECT_NAME} POST_BUILD
    COMMAND ${OBJCOPY} -O binary ${CMAKE_PROJECT_NAME}.elf ${CMAKE_PROJECT_NAME}.bin
    COMMAND ${OBJCOPY} -O ihex   ${CMAKE_PROJECT_NAME}.elf ${CMAKE_PROJECT_NAME}.hex
    COMMENT "Generating ${CMAKE_PROJECT_NAME}.bin and ${CMAKE_PROJECT_NAME}.hex from ${CMAKE_PROJECT_NAME}.elf"
)

I have written all these commands that need to be added in the workspace main CMakeLists.txt in this notepad; every time a new project is generated, you can just copy them directly.

Then compile again

cmake ..
make

Now look at the build directory again: the .hex or .bin we need has been generated

3.5.2.Connect the device to JLink and flash the program
3.5.2.1.Graphical interface flashing
#打开终端输入
JFlashLite

Select the corresponding chip model and speed

Add hex file

Click flash and complete:

Successfully lit the LED:

3.5.2.2.Terminal flashing

Forget it, forget it, it's too much trouble.

3.6.Configure VSCode Tasks

When compiling above, we always need to enter the following command

cd build
cmake ..
make

Compiling this way every time is too cumbersome, so we use the powerful VSCode for one-click compilation.

First create the.vscodefolder andtasks.jsonfile

The following is the content of tasks.json:

{
    "version": "2.0.0",
    "options": {
        "cwd": "${workspaceFolder}/build"    //需要进入到我们执行tasks任务的文件夹中
    },
    "tasks": [    //tasks包含4个任务
        {
            "type": "shell",
            "label": "stm32-cmake",    //第一个任务的名字叫cmake
            "command": "bash",
            "args": [
                "-c",
                "mkdir -p ../log && echo \"===== CMake started at: $(date) =====\" | tee -a ../log/cmake.log && cmake .. 2>&1 | tee -a ../log/cmake.log"
            ],
            "problemMatcher": []    //这里需要添加一个空的问题匹配器,否则会报错
        },
        {
            "label": "stm32-make",    //第二个任务的名字叫make
            "command": "bash",
            "args": [
                "-c",
                "mkdir -p ../log && echo \"===== Make started at: $(date) =====\" | tee -a ../log/make.log && make -j$(grep -c ^processor /proc/cpuinfo) 2>&1 | tee -a ../log/make.log"
            ],
            "problemMatcher": []    //这里也需要添加一个空的问题匹配器,否则会报错
        },
        {
            "label": "stm32-Build",    //第3个任务的名字叫Build
            "group": {               //默认是build任务
                "kind": "build",
                "isDefault": true
            },
            "dependsOrder": "sequence",    //顺序执行依赖项
            "dependsOn":[    //依赖的2个项为cmake、make
                "stm32-cmake",    //即第一个任务的label
                "stm32-make"      //即第二个任务的label
            ]
        },
        {
            "type": "shell",
            "label": "stm32-clean",    //第四个任务:清理 build 文件夹
            "command": "bash",
            "args": [
                "-c",
                "echo \"===== Clean started at: $(date) =====\" && rm -rf * && echo \"Build folder cleaned.\""
            ],
            "options": {
                "cwd": "${workspaceFolder}/build"    //只清理build目录下的文件
            },
            "problemMatcher": []    //不需要问题匹配器
        }

    ]
}

Method 1:

In the VS Code title bar, locate终端and then select运行构建任务The shortcut key isCtrl+Shift+B.

It can be seen that the task has already been run.

Method 2:

On the VSCode title bar, find终端and then select运行任务.

Below are 4 STM32 tasks. The first is thestm32-Buildtask. After running, the effect is the same as Method 1 just now. The运行构建任务button in Method 1 is thisstm32-Buildtask that is run.

Thisstm32-Buildtask contains stm32-cmake and stm32-make tasks.

Thenstm32-cleanthe task is to clear all files under the build folder.

You can try it.stm32-cleanTask.

It can be seen that all have been deleted.

You do not need to worry about having to configure so many things every time you create a new project.

以上大多数配置文件全部都已经包含在https://github.com/tungchiahui/CubeMX_MDK5to6_Template仓库下的***`工程文件移植(创建新模板请看这里)`***文件夹了,到时候新建一个工程后,直接把这个文件夹下的所有文件全部复制过来即可。

3.7.Use ozone for Flash programming and Debug debugging

3.7.1.Basic configuration

Open a terminal and enter ozone to launch the software, or directly find the application icon to open ozone

First select the device, for example, mine is STM32F407VET6

Select Peripherals:

Click Next

If you are using SWD, fill in SWD; if it is JTAG, fill in JTAG

Select ELF

elf, hex, and bin can all be selected; generally, selecting elf is sufficient.

This step can be left at the default.

If you have enabled the RTOS, you may encounter this issue.

warning (138): The target application seems to be using FreeRTOS, but FreeRTOS-awareness is not enabled.

This means your target application appears to be using FreeRTOS, but debug support for FreeRTOS is currently not enabled (RTOS-awareness).

Simply apply the fix according to the prompt below it.

Just click Continue.

3.7.2.Programming and Debugging

You can watch the video below, it explains it quite well.(Start watching from 30:10)

https://www.bilibili.com/video/BV1yrLHzZEoE

Click File to have it sort by filename.

找到led_task.cpp点击就可以打开这个源文件啦。