当前位置: 首页 > news >正文

STM32最小CLion开发环境

文章目录

    • 1 必须文件
    • 2 工具链
    • 3 CLion 全局配置
    • 4 CLion 新项目配置
      • ST-Link 调试
    • 5 点亮 LED
    • 6 分析 elf 文件
    • 7 项目模板

1 必须文件

ST 提供的头文件支持 MDK-ARM, GCC, IAR 3种编译器, 下面采用 GCC

编译器 Arm GNU Toolchain Downloads – Arm Developer 或 安装包版
调试器服务端 OpenOCD
基础头文件仓库 STMicroelectronics/cmsis-core
F1头文件仓库 STMicroelectronics/cmsis-device-f1
F1头文件仓库 STMicroelectronics/stm32f1xx-hal-driver
外设 SVD 文件 stm32 svd

上述所有项目拉取/解压/解包后各自一个文件夹放在 stm32kits 中

2 工具链

新建 stm32kits/cmake/startup.bat, 内容如下

set CMAKE_TOOLCHAIN_FILE=%~dp0arm.toolchain.cmake

新建 stm32kits/cmake/arm.toolchain.cmake, 内容如下

set(CMAKE_SYSTEM_NAME               Generic)
set(CMAKE_SYSTEM_PROCESSOR          arm)set(CMAKE_C_COMPILER_ID GNU)
set(CMAKE_CXX_COMPILER_ID GNU)set(CMAKE_EXECUTABLE_SUFFIX_ASM     ".elf")
set(CMAKE_EXECUTABLE_SUFFIX_C       ".elf")
set(CMAKE_EXECUTABLE_SUFFIX_CXX     ".elf")set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)set(STM32_KITS_DIR "${CMAKE_CURRENT_LIST_DIR}/..")
set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH};${CMAKE_CURRENT_LIST_DIR}")# MCU specific flags
set(TARGET_FLAGS "-mcpu=cortex-m3 ")set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_FLAGS}")
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -MMD -MP")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wpedantic -fdata-sections -ffunction-sections -Wl,--no-warn-rwx-segments")set(CMAKE_C_FLAGS_DEBUG "-O0 -g3")
set(CMAKE_C_FLAGS_RELEASE "-Os -g0")
set(CMAKE_CXX_FLAGS_DEBUG "-O0 -g3")
set(CMAKE_CXX_FLAGS_RELEASE "-Os -g0")set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions -fno-threadsafe-statics")set(CMAKE_C_LINK_FLAGS "${TARGET_FLAGS}")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} --specs=nano.specs")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,-Map=${CMAKE_PROJECT_NAME}.map -Wl,--gc-sections")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--start-group -lc -lm -Wl,--end-group")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--print-memory-usage")set(CMAKE_CXX_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -Wl,--start-group -lstdc++ -lsupc++ -Wl,--end-group")

新建 stm32kits/cmake/FindSTM32Driver.cmake, 内容如下

function(stm32_parse_mcu_name MCU_NAME)string(TOUPPER "${MCU_NAME}" MCU_NAME_UPPER)if(NOT MCU_NAME_UPPER MATCHES "^STM32([C|F|G|H|L|M|N|U|W][A-Z0-9][A-Z0-9]?[A-Z0-9]?)([0-9][0-9])([A-Z])([0-9A-IZ])([BDG-KMPQTUVY]?)([6A7B3CD]?)$")set(STM32Driver_FOUND PARENT_SCOPE)return()endif()string(TOLOWER "${CMAKE_MATCH_1}" MATCH_1_LOWER)SET(MCU_SERIES_VARIANT_LOWER "${MATCH_1_LOWER}" PARENT_SCOPE)SET(MCU_SERIES_VARIANT "${CMAKE_MATCH_1}" PARENT_SCOPE)SET(MCU_VARIANT "${CMAKE_MATCH_2}" PARENT_SCOPE)SET(MCU_PIN_COUNT "${CMAKE_MATCH_3}" PARENT_SCOPE)string(TOLOWER "${CMAKE_MATCH_4}" CMAKE_MATCH_4_LOWER)SET(MCU_FLASH_LOWER "${CMAKE_MATCH_4_LOWER}" PARENT_SCOPE)SET(MCU_FLASH "${CMAKE_MATCH_4}" PARENT_SCOPE)SET(MCU_PACKAGE "${CMAKE_MATCH_5}" PARENT_SCOPE)SET(MCU_TEMP_RANGE "${CMAKE_MATCH_6}" PARENT_SCOPE)set(STM32Driver_FOUND TRUE PARENT_SCOPE)
endfunction()if(NOT DEFINED MCU_NAME)list(POP_FRONT STM32Driver_FIND_COMPONENTS MCU_NAME)
endif()
if(NOT DEFINED MCU_NAME)message(FATAL_ERROR "MCU_NAME variable must be defined before calling find_package(STM32Driver)")
endif()stm32_parse_mcu_name("${MCU_NAME}")
if(NOT STM32Driver_FOUND)message(WARNING "Invalid STM32 MCU name: ${MCU_NAME}")return()
endif()set(STM32Driver_FOUND)
foreach(flash_fit IN ITEMS 0 1 2 3 4 5 6 7 8 9 A B Z C D E F G H I)if(${flash_fit} STRGREATER_EQUAL ${MCU_FLASH})string(TOLOWER "${flash_fit}" MCU_FLASH_FIT_LOWER)if(EXISTS "${STM32_KITS_DIR}/cmsis-device-${MCU_SERIES_VARIANT_LOWER}/Source/Templates/gcc/startup_stm32${MCU_SERIES_VARIANT_LOWER}${MCU_VARIANT}x${MCU_FLASH_FIT_LOWER}.s")set(STM32Driver_FOUND TRUE)set(MCU_FLASH_FIT "${flash_fit}")break()endif()endif()
endforeach()
if(NOT STM32Driver_FOUND)message(WARNING "Invalid STM32 MCU Flash: ${MCU_FLASH}")return()
endif()enable_language(C ASM)
set(STM32Driver_FOUND TRUE)
add_library(STM32Driver STATIC"${STM32_KITS_DIR}/cmsis-device-${MCU_SERIES_VARIANT_LOWER}/Source/Templates/gcc/startup_stm32${MCU_SERIES_VARIANT_LOWER}${MCU_VARIANT}x${MCU_FLASH_FIT_LOWER}.s""${STM32_KITS_DIR}/cmsis-device-${MCU_SERIES_VARIANT_LOWER}/Source/Templates/system_stm32${MCU_SERIES_VARIANT_LOWER}xx.c""${STM32_KITS_DIR}/stm32${MCU_SERIES_VARIANT_LOWER}xx-hal-driver/Src/stm32${MCU_SERIES_VARIANT_LOWER}xx_hal.c""${STM32_KITS_DIR}/stm32${MCU_SERIES_VARIANT_LOWER}xx-hal-driver/Src/stm32${MCU_SERIES_VARIANT_LOWER}xx_hal_cortex.c"
)
foreach(feature IN LISTS STM32Driver_FIND_COMPONENTS)target_sources(STM32Driver PRIVATE"${STM32_KITS_DIR}/stm32${MCU_SERIES_VARIANT_LOWER}xx-hal-driver/Src/stm32${MCU_SERIES_VARIANT_LOWER}xx_hal_${feature}.c")
endforeach()
target_include_directories(STM32Driver PUBLIC"${STM32_KITS_DIR}/cmsis-core/Include""${STM32_KITS_DIR}/cmsis-device-${MCU_SERIES_VARIANT_LOWER}/Include""${STM32_KITS_DIR}/stm32${MCU_SERIES_VARIANT_LOWER}xx-hal-driver/Inc""${STM32_KITS_DIR}/easyheader"
)
target_compile_definitions(STM32Driver PUBLIC "STM32${MCU_SERIES_VARIANT}${MCU_VARIANT}x${MCU_FLASH_FIT}")
target_link_options(STM32Driver PUBLIC"SHELL:-T\"${STM32_KITS_DIR}/cmsis-device-${MCU_SERIES_VARIANT_LOWER}/Source/Templates/gcc/linker/STM32${MCU_SERIES_VARIANT}${MCU_VARIANT}X${MCU_FLASH_FIT}_FLASH.ld\""
)

新建 stm32kits/easyheader/stm32f1xx_hal_conf.h, 内容如下

#include <stm32f1xx_hal_conf_template.h>

至此 stm32kits 已手工创建完成

3 CLion 全局配置

设置→构建、执行、部署→工具链→"+"→系统
环境文件: stm32kits\cmake\startup.bat
C 编译器: arm-none-eabi-gcc.exe
C++ 编译器: arm-none-eabi-g++.exe
调试器: arm-none-eabi-gdb.exe

上述全局配置实际保存在 %APPDATA%\JetBrains\CLion2025.1\options\windows\toolchains.xml

      <toolchainname="ArmMinGW"toolSetKind="SYSTEM_WINDOWS_TOOLSET"customCCompilerPath="stm32kits\arm-gnu-toolchain-14.2.rel1-mingw-w64-x86_64-arm-none-eabi\bin\arm-none-eabi-gcc.exe"customCXXCompilerPath="stm32kits\arm-gnu-toolchain-14.2.rel1-mingw-w64-x86_64-arm-none-eabi\bin\arm-none-eabi-g++.exe"debuggerKind="CUSTOM_GDB"customGDBPath="stm32kits\arm-gnu-toolchain-14.2.rel1-mingw-w64-x86_64-arm-none-eabi\bin\arm-none-eabi-gdb.exe"environment="stm32kits\startup.bat" />

4 CLion 新项目配置

任意创建一个 C++ 项目后, 进行如下配置
设置→构建、执行、部署→CMake→配置文件
工具链: ArmMinGW

CMakeLists.txt 添加:

find_package(STM32Driver COMPONENTS STM32F103C8T6 gpio spi)
target_link_libraries(<项目名> PRIVATE STM32Driver)

之后程序就可编译了

ST-Link 调试

下面配置嵌入式 GDB 调试服务端, 需安装 Embedded Development Support 插件
设置→构建、执行、部署→调试器→调试服务器→"+"→泛型→GDB 服务器
可执行文件: stm32kits/OpenOCD/bin/openocd.exe
实参: -f interface\stlink.cfg -f target\stm32f1x.cfg
在这里插入图片描述
下面配置调试客户端
设置→构建、执行、部署→调试器→调试服务器→调试器
调试器: stm32kits\arm-gnu-toolchain\bin\arm-none-eabi-gdb.exe
连接/实参: tcp:localhost:3333 (用于启动客户端后连接服务端)

上述配置将在 ${CMAKE_CURRENT_SOURCE_DIR}/.idea/debugServers 生成 OpenOCD.xml, 该文件以后可直接复制使用, 其内容如下

<component name="DebugServers"><generic-debug-target name="OpenOCD" uniqueID="c136ea77-b81f-463e-8e9b-ef6a84b56628" selected="true"><debugger version="1"><debugger toolchainName="ArmMinGW" /><env /></debugger><gdbserver exe="C:/program/stm32kits/OpenOCD-20240916-0.12.0/bin/openocd.exe" args="-f interface\stlink.cfg -f target\stm32f1x.cfg"><env /></gdbserver><console enabled="true" port="4444" /><target reset-before="false" /><connection remote-string="tcp:localhost:3333" custom-script="echo Connecting to target...\n&#10;$GDBTargetCommand$&#10;echo Connected to target!\n" warmup-ms="500" /></generic-debug-target>
</component>

最后再设置一下当前调试服务器, 之后可通过 ST-Link 走 SWD 接口 下载程序和调试

ST-Link 也要装好驱动, OpenOCD已内置了ST-Link的驱动, 位置在 stm32kits/OpenOCD/drivers/ST-Link/dpinst_amd64.exe

在运行被中断时, 可以用调试浮窗的内存视图直接查看 SRAM 内存
而功能寄存器需要在调试浮窗可找到外设页(需安装 Embedded Development Support 插件), 加载 svd 文件来读取


调试时会出现 info pretty-printer 执行失败的错误, 原因是 arm-none-eabi-gdb 编译时移除了 python 支持, 否则通常可以在 gdb 隔壁 ../share/gdb/python/gdb/command/pretty_printers.py 找到该命令

5 点亮 LED

以tb上常见的STM32F103C8T6最小系统板为例, 一个 LED 负极接在 PC13 的位置

下面闪烁该 LED

#include <stm32f1xx_hal.h>
#include <stm32f1xx_hal_rcc.h>
#include <stm32f1xx_hal_gpio.h>extern "C" void SysTick_Handler() {HAL_IncTick();
}int main() {HAL_Init();__HAL_RCC_GPIOC_CLK_ENABLE();GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.Pin = GPIO_PIN_13;GPIO_InitStructure.Speed = GPIO_SPEED_FREQ_LOW;GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;GPIO_InitStructure.Pull = GPIO_NOPULL;HAL_GPIO_Init(GPIOC, &GPIO_InitStructure);while (true) {HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_SET);HAL_Delay(100);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);HAL_Delay(100);}
}

6 分析 elf 文件

IDA 加载 elf 文件后, Processor type 选 ARM Little-endian [ARM], Processor options→Edit ARM architecture options 选 ARMv7-M

可以看到08000000开始是向量表, 第2个是程序入口 Reset_Handler, 在0x0800021C

7 项目模板

CLion 暂不支持将项目保存为项目模板 (详见 Save project as template in CLion. How? ), 只有 Idea 其他 IDE 支持, 新项目都要手动重新配置 工具链,调试服务器

相关文章:

  • MYSQL之表的内连和外连
  • ABP-Book Store Application中文讲解 - Part 9: Authors: User Interface
  • 3D旋转动态爱心 - Python创意代码
  • 缓存控制HTTP标头设置为“无缓存、无存储、必须重新验证”
  • AtCoder-abc407_e解析
  • Nginx+Tomcat负载均衡与动静分离架构
  • 13、企业应付管理(AP)全流程解析:从发票登记到付款完成
  • 【定时器】定时器存在的内存泄露问题
  • 机器学习14-迁移学习
  • HDFS分布式存储 zookeeper
  • 半导体制冷片(Thermoelectric Cooler,TEC)
  • C++查找算法全解析:从基础到高级应用
  • CppCon 2015 学习:Bridging Languages Cross-Platform
  • 每日八股文6.4补
  • Fluence推出“Pointless计划”:五种方式参与RWA算力资产新时代
  • 更新 Docker 容器中的某一个文件
  • spring-ai入门
  • springboot ErrorController getErrorPath() 版本变迁
  • 【Spark征服之路-2.1-安装部署Spark(一)】
  • 电力系统时间同步系统之二
  • 网站页脚信息/模板下载网站
  • 网站投放广告多少钱/bt种子磁力搜索引擎
  • 网站做301还是302/爱站网关键词查询网站的工具
  • wordpress 定时发送/河北seo推广公司
  • 郑州网站建设培训班/seo的课谁讲的好
  • 京东不让卖网站制作么/上海网络营销seo