第 2 節

Linux

0瀏覽次數0訪問次數--跳出率--平均停留

環境介紹

本教程環境介紹:

  1. 系統:Fedora 42 KDE Edition Linux
  2. 系統內核:Linux 6.15.6-200.fc42.x86_64
  3. 架構:X86_64

其他Linux環境也可以。

安裝各種環境

安裝C/C++環境


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

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

查看是否環境安裝成功

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

接下來測試是否能夠對C/C++正常編譯,請找一個存放C++代碼的文件夾,然後在終端中cd進去。

然後創建一個.cpp文件並用vim編輯

vim hello.cpp

複製以下代碼到該文件裡

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

然後編譯

g++ -o hello hello.cpp
ls

運行

./hello

說明環境已經配置好了

安裝CubeMX

下載地址:

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

推薦下載6.14.1版本(不要下載6.15.0,這個版本有bug,不知道後續何時會修復)

解壓出來

用root權限打開這個軟件SetupSTM32CubeMX-6.15.0

sudo ./SetupSTM32CubeMX-6.15.0

在新彈出的界面一直點下一步就行,安裝結束後出現如下圖就成功了。

/usr/local/STMicroelectronics/STM32Cube/STM32CubeMX進入這個文件夾,然後打開終端輸入

./STM32CubeMX

點擊Help

Manage embedded software packages,把STM32F1,F4,H7的第一個最新的固件勾上。

點install

登陸上賬號

然後等下載和安裝完

下載好就行了。

接下來可以把CubeMX應用配置一個桌面快捷方式等可以快速打開,教程詳見Vinci機器人隊Linux入門教程的Appimage章節,可以用ctrl+F快速定位該章節。

桌面快捷方式如下:

[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

根據教程做,就可以實現這種效果啦。

安裝VScode

https://code.visualstudio.com/Download

如果是debian系下載deb,如果是rhel系下載rpm.

下載完之後,點擊瀏覽器,找到這個安裝包的文件夾,並在該路徑打開終端。

Debian系:輸入sudo apt install ./code然後按tab按鍵補齊文件名,回車。

RHEL系:輸入sudo dnf install ./code然後按tab按鍵補齊文件名,回車。

例如補齊後的:

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

然後打開VScode,在終端輸入下面的命令

code

然後安裝一些插件

下面這些都要裝

安裝ARM GNU工具鏈

編譯工具比較:

特性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的未來和主力,持續更新和優化

安裝

建議都用官方法進行安裝。

方法一(官網法)

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

進入下載目錄並打開終端

在終端裡輸入下列命令,將編譯器文件tar壓縮包複製到你存放程序的文件夾(這個文件夾你自己定,建議在home分區,別以後刪了就行)。

具體命令為cp ./arm-gnu然後按tab補齊,然後空格,再跟上你要複製到的文件夾的路徑。

比如下面的命令:

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

然後進入複製到的文件夾:

cd ~/UserFolder/Applications/

在終端裡輸入tar -xvf ./arm-gnu並按tab補齊。

例如我補齊後的:

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

再進入這個解壓後的文件夾

cd ./arm-gnutab補齊。

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

查看文件夾路徑

pwd

複製一下/home/tungchiahui/UserFolder/Applications/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/bin

然後需要配置環境

vim ~/.bashrc

在末尾輸入下面的命令,把下面~/UserFolder/Applications/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/bin替換成你剛才複製的路徑,/home/用户名可以用~來代替。

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

加載環境

source ~/.bashrc
方法二(系統倉庫法)

不建議本法


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

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

測試

檢查版本

arm-none-eabi-gcc -v

安裝JLink驅動

安裝libreadline庫

我們燒錄會用到JLinkExe的命令,而JLinkExe會用到libreadline庫,所以要安裝libreadline庫,執行如下命令安裝:


# debian系
sudo apt-get install libreadline-dev

# rhel系
sudo dnf install readline-devel

安裝JLink驅動

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

是Debian系下載64位DEB

是RHEL系下載64位RPM

(這裡的64位指的是amd64和X86_64,如果你是ARM64請下載下方那個Linux ARM裡的64位)

打開下載到的文件夾,並打開終端

然後sudo apt install ./JLink然後tab補齊。

然後sudo dnf install ./JLink然後tab補齊。

sudo dnf install ./JLink_Linux_V852_x86_64.rpm

檢查是否安裝成功

JLinkExe

我們點擊No,然後會進入Commander交互模式,在這種模式下,我們可以執行各種 J-Link Commander 提供的命令來連接、配置調試器,下載程序或文件到目標設備等操作,感興趣的同學可自行學習。

執行“q”指令退出該模式。

下載並安裝Ozone

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

是Debian系下載64位DEB

是RHEL系下載64位RPM

(這裡的64位指的是amd64和X86_64,如果你是ARM64請下載下方那個Linux ARM裡的64位)

然後sudo apt install ./Ozone然後tab補齊。

然後sudo dnf install ./Ozone然後tab補齊。

sudo dnf install ./Ozone_Linux_V338g_x86_64.rpm

測試

打開終端輸入

ozone

下載SVD

https://www.st.com.cn/content/st\_com/zh.html

在搜索裡搜索芯片型號,如stm32f103c8t6

點CAD資源

下載SVD,鼠標點紅色框的區域就可以下載了

解壓後就可以獲得F1系列的SVD文件了

依次把F4和H7的也下載解壓了就可以了。(可以解壓到一個文件夾裡)

然後在上面的文件夾打開終端

將這些文件夾全部複製到Ozone的Config/Peripherals/目錄下。(你需要提前確定一下ozone的配置是否是這個路徑再複製)

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

工程創建與測試

使用CubeMX創建工程

點擊進入單片機挑選的按鈕

搜索對應芯片,並雙擊對應芯片選項。

進行一些配置,以下都是很基礎的東西,你在看這個視頻前肯定都會了

隨便開一個IO用來測試,比如LED的GPIO

FreeRTOS也要配置一下。

這些文件夾也要配置好,最後Toolchain選擇CMake,編譯器選擇GCC(6.14.1及之前沒有選擇編譯器這個選項很正常)

(但是CubeMX6.15.0有bug,這個選擇GCC編譯器並沒有用,還需要後續自己手動選擇編譯器,以後可能會修復這個bug.)

對工程進行配置與編譯

在工程文件夾打開終端

然後打開vscode

code .

進入vscode後,點擊目錄下的CMakeLists.txt

檢查第25行左右是否有下面這行,如果沒有,你需要手動給他加上這兩行。(6.14.1版本沒有這個bug)

tips1:這就是上面說的CubeMX6.15.0版本的bug,因為這個版本增加了對clang編譯器的支持,在CubeMX裡也支持了選擇編譯器的操作,但是這個選項估計是工程師沒寫好,選擇編譯器不管選哪個,他都不會選擇咱們選擇的編譯器,所以咱們需要手動選擇。

tips2:這CubeMX6.15.0有第二個bug,這個工作區根CMakeLists.txt他說了只會生成一次,後續不會再重新覆蓋生成,但是發現每次在CubeMX修改配置後,然後重新生成代碼,其他命令都被保留了,就這個命令不會被保留。不知道後續會不會被修復,或者直接修復上面tips1的bug.所以每次重新配置CubeMX後,需要再把這句加上。


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

按ctrl+~打開內置終端。

使用下方命令創建並進入build文件夾

mkdir build
cd build

接下來使用cmake命令生成makefile文件

cmake ..

檢查一下是否ARM的C/C++以及彙編編譯器都被找到了(如果沒有,請檢查上面的教程是否有做錯的地方)

然後使用make命令進行編譯,命令為make或者make -jxx,這裡的xx是你想使用CPU的幾個線程來進行編譯,比如我電腦是8核16線程,我就可以讓xx是比16低的數字。而make是默認用一個線程。如果你並不知道你CPU有幾個線程,那你就老老實實用make命令,別用make -jxx命令了。

make -j16

這樣就是編譯成功了。

對代碼提示進行配置

在VScode中按Ctrl+Shift+P,搜索clangd,並選擇下載語言服務

在右下角選擇安裝即可,安裝完就會出現下圖提示。

接著禁用C/C++插件的代碼提示功能(如果沒這個界面,請往下看)

如果沒有上圖的彈窗,可以進行手動關閉,依然是ctrl shift P,輸入settings然後找到如下圖的選項

找到下圖這個選項,改成disabled即可。

"C_Cpp.intelliSenseEngine": "disabled"

在VScode中再按Ctrl+Shift+P,搜索clangd,並選擇重啟clangd語言服務(重啟clangd語言服務之前必須編譯過一遍代碼了)

此時,可以看代碼裡頭文件都正常識別了,代碼提示也正常了。

⚠️注意:Clangd 默認找的是 本機系統的 libc/include 路徑(比如 x86_64 的 /usr/include ,而我們工程裡面實際使用的是 ARM 工具鏈的頭文件路徑 ,這就有概率導致包含C/C++庫函數的頭文件報錯

例如:

這裡的 #include <math.h>顯示找不到頭文件,但是我們進行編譯的時候卻沒有報錯,說明是clangd的配置有問題 。以下介紹一種解決方法:

  1. 運行以下命令,獲取 ARM GCC 使用的標準 include 路徑:
arm-none-eabi-gcc -x c -E -v - </dev/null

  1. 在工程根目錄下面創建 .clangd 文件 將自己的頭文件路徑包含進去(引號裡面替換成你自己的arm gcc頭文件路徑)
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"
  ]

保存,此時刷新一下clangd,頭文件提示正常

移植Vinci機器人隊標準C/C++工程模板

用git clone命令克隆倉庫:https://github.com/tungchiahui/CubeMX_MDK5to6_Template

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

把倉庫裡的“工程文件移植”文件夾裡的 所有內容 複製到我們CMake工程的目錄裡。

然後打開applications文件夾,在Src和Inc文件夾分別創建led_task.cpp和led_task.h,內容分別如下:

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方便咱們修改,文件結構也更加明顯。(這些都不需要咱們自己創建,我已經給創建到 工程文件移植 裡了,你在上面複製的時候已經複製過來了)

然後要去最頂層的CMakeLists.txt里加上這句話來引用我們自己的CMakeLists.txt。


# Add USER generated sources
add_subdirectory(cmake/user)

大功告成,編譯一次試試。可以看到下圖,那些新加的文件都編譯上了。

cmake ..
make

然後去main.c中引用cpp_interface.h頭文件,並將cpp_main()函數在main函數的這個地方調用。(我這裡是開RTOS了,所以需要在啟動RTOS之前調用cpp_main函數,如果你是沒有用RTOS的裸機程序,則在while (1)的上方調用cpp_main即可)

然後在cpp_interface.h裡修改isRTOS這個宏來讓程序知道你是否開啟了RTOS,如果開啟了,宏就為1,裸機就填0。

其他更加詳細的關於STM32的C/C++工程介紹請看Vinci機器人隊單片機教程

此時在build文件夾下進行編譯程序,發現成功!

cmake ..
make

下載程序到板子

配置CMake生成.bin和.hex文件

在下載程序到板子之前,我們需要去看看咱們之前編譯的到底生成了啥文件。

通過下圖可知,他只生成了.elf文件,並沒有咱們常見的.bin和.hex文件。

咱們需要再更改一下工作區下的CMakeLists.txt從而來讓編譯的時候生成.hex和.bin(沒辦法,就得這麼麻煩,我也不知道為啥CubeMX不給全乾好)


# 生成 .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"
)

這些需要在工作區主CMakeLists.txt裡添加的命令我全都寫在這個記事本里了,每次生成新工程直接複製即可。

然後再次編譯

cmake ..
make

此時再看build目錄:咱們需要的.hex或者.bin就出來了

將設備連接到JLink並燒錄程序
圖形界面燒錄
#打开终端输入
JFlashLite

選擇對應的芯片型號和速度

添加hex文件

點擊燒錄並完成:

成功點亮led:

終端燒錄

算鳥算鳥,太麻煩了。

配置VScode任務

咱們在上面編譯,一直需要輸入以下命令

cd build
cmake ..
make

這樣每次編譯過於麻煩了,所以我們使用強大的VScode來一鍵編譯。

首先創建.vscode文件夾和tasks.json文件

以下是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": []    //不需要问题匹配器
        }

    ]
}

方法一:

在VScode標題欄上,找到终端,然後再選擇运行构建任务,快捷鍵是Ctrl+Shift+B

可見任務已經被運行了。

方法二:

在VScode標題欄上,找到终端,然後再選擇运行任务

下面有4個stm32的任務,第一個是stm32-Build任務,運行後的效果和剛才方法一是一樣的,方法一的那個运行构建任务的按鈕,就是運行的這個stm32-Build任務。

這個stm32-Build任務包含stm32-cmake和stm32-make任務。

然後stm32-clean任務就是清除build文件夾下的所有文件。

可以試一下stm32-clean任務。

可以發現都刪完了。

你不用擔心每次新建工程都需要配置那麼多東西。

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

使用ozone進行Flash燒錄和Debug調試

基礎配置

打開終端輸入ozone打開軟件或者直接找到應用圖標打開ozone

先選擇device,比如我是STM32F407VET6

選擇Peripherals:

點擊下一步

你用的SWD就填SWD,是JTAG就填JTAG

選擇ELF

elf,hex,bin都可以選,一般選elf就行。

這一步保持默認即可。

如果你開啟了RTOS可能會遇到這個問題。

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

意思是你的目標應用似乎使用了 FreeRTOS,但當前沒有啟用對 FreeRTOS 的調試支持(RTOS-awareness)。

直接按照他底下的提示應用修復即可。

點繼續就行。

燒錄與調試

可以看下面這個視頻,講的挺好的。(從30:10開始看)

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

點擊File讓他按文件名排序。

找到led_task.cpp點擊就可以打開這個源文件啦。

音乐页