本文在简书上(链接)写的比较完整了,搬过来论坛上,大家有什么问题和建议 一块讨论进步~一般我在简书上更新的比较快,因为其md在线编辑器比较好用。代码则在github上更新快。
简介实现了在CLion中编译、烧录、调试STM32。
主要参考了 在Mac下使用CLion做嵌入式开发和CLion for embedded development。
步骤简要是:建立Eclipse项目并转为CLion项目->在CLion中编译->在CLion中调用OpenOCD和Tcl expect脚本直接烧写程序->CLion gdb窗口中调试。
步骤操作比较多,也可直接安装配置环境后直接用我github上的项目pro_tmpl_stm32f10x,基于stm32f10x的,若其它芯片则可用Eclipse生成固件库然后代替项目中system文件夹并修改CMakelist编译参数就行。
若在linux或mac系统下用Clion,配置应该差不多,就expect脚本里声音提示函数部分要修改一下。
以下所有代码块推荐在github我的项目里拷贝,因为github里代码可能有所更新 PS:本人是刚入门STM32的菜鸡,由于之前写java和php、c++等用了Jetbrains系列的IDE后在其它方面用其它开发工具感觉体验差不少,于是打什么代码都想用Jetbrains系列的IDEs,比如去年的汇编就用CLion打(有时间另开篇写设置汇编代码高亮和代码提示等的相关方法)。由上述所以刚学STM32就不用MDK不用Keil,直接用CLion和Eclipse开搞了。
先放张CLion里写stm32的工作图:
更新进展
- 2017年9月24日 21:38:08 修改一些描述,不影响步骤。
- 2017年9月14日 11:20:52 教程基本完工。更新了github上的代码。更新参考资料链接。
- 2017年9月13日 22:57:09 expect脚本基本完工,继续更新本文。将更新github上本项目代码。明天再写。
2017年9月13日 22:01:56 实现各种常见下载时问题的报错红字提示。
2017年9月12日 20:24:06 实现下载过程error、warn、Succeed三种声音提示。优化代码快完成。
2017年9月11日 实现一键run/debug!,美滋滋。。run配置完成。速度 rebuild 2s~3s,少量改动再build则 5s,expect脚本约2s 496ms,总5s左右。 - 2017年9月10日 11:29:27更正文章部分描述错误。继续写CLion调试最后的步骤
- 2017年9月9日 22:27:23 写到三种调试方式,优化在CLion中的OpenOCD和WriteFlash配置。
- 2017年9月9日 11:25:05 实现在CLion中调用OpenOCD和ActiveTcl 的expect进行下载调试,速度20s左右比较慢(【更正】:其实烧录下载不慢,是timeout设置过长拖了10s才打开gdb)。继续写本教程。
- 2017年9月8日 19:53:22 教程写到创建eclipse项目。。
- 2017年9月1日 成功在CLion中编译STM32项目,未实现在CLion中直接调用OpenOCD进行调试。
环境截止至2017年9月7日 22:21:01,本文所使用的软硬件工具如下,都是尽量最新版: - 电脑系统:win7x64
- IDE:
- CLion 2017.xxx
- Eclipse Oxygen
- toolchain / 编译器:GNU GCC for ARM (gcc-arm-none-eabi)
- Debugger:OpenOCD-20170821、Ozone
- MinGW:装在C:MinGW
—————— - MCU:STM32F103RBT6,Alientek Mini v2.0开发板
- 仿真器:J-Link-ARM v8
基本环境搭建和配置安装CLion安装 MinGW:安装 GNU Tools for ARM Embedded Processors安装 Eclipse 及插件CDT GNU Cross Development Tools后面的调试部分有两个方案,各需下载不同工具,下载地址和配置见后面各方案。创建项目
其中SW4STM32是基于Eclipse的IDE,不建议用它,而用Eclipse OXYGEN原版+GNU 插件,因为相对于专版的SW4STM32,Eclipse里可以写更多东西,加其他通用插件。
扯回来,说到STM32CubeMx,试了下在CLion里编译老报各种错,所以先不用它了,它的好处是设计独立单板PCB时对引脚等繁琐配置的简化操作,修改更新配置也方便,但对于用开发板的就先用不着它,因为开发板一般都有配套相关模块配置代码库。等到设计单板时再用它生成配置代码(选用上图的Other Toolchains,代码最简,应该可配合在同一CLion项目目录下使用)。1.创建Eclipse项目
因为在Eclipse建立一个基于Stm32f10x的project以后的项目都可以直接复制这个项目文件夹修改成新名称的项目,所以我直接建个pro_tmpl_stm32f10x项目当模板,如下图名称和路径。
pro_tmpl_stm32f10x
Step2 接下来如图,我开发板芯片是stm32f103rbt,对应Chip family是Medium Density。Content选择Empty吧,blink a led示例代码没啥好参考。对于Trace output应该是初始给你生成trace_puts、trace_printf函数之类代码的c文件,好在Debug时电脑调试框能返回类似printf的打印信息。其他默认,我不认识。
Paste_Image.png
如果不知道Chip family选哪个可以打开STM32CubeMx,新建项目,找到自己芯片后看其英文介绍第一句就提示了其封装密度类型:
查找密度类型
Step3 一路Next,到这选如图配置,点Finish
step3
2.转为CLion项目,在CLion中编译CLion中打开文件夹C:CodeEmbeddedSTM32pro_tmplpro_tmpl_stm32f10x, 根目录下新建CMakeLists.txt,代码内容如下(自行修正路径) project(pro_tmpl_stm32f10x)cmake_minimum_required(VERSION 3.3)enable_language(ASM)set(BUILD_MODE DEBUG)#在Clion中Settings>Build>Cmake的Cmake options加入下面一行(自行修正路径),不包含#符号。#-DTOOLCHAIN_DIR="C:Program Files (x86)GNU Tools ARM Embedded6 2017-q2-update" -DCMAKE_TOOLCHAIN_FILE="toolchain-arm-eabi-gcc.cmake"set(USER_C_FLAGS "-mcpu=cortex-m3 -mthumb -fmessage-length=0 -fsigned-char -ffunction-sections -fdata-sections -ffreestanding -fno-move-loop-invariants -Wall")set(USER_CXX_FLAGS "-std=c++11 -fabi-version=0 -fno-exceptions -fno-rtti -fno-use-cxa-atexit -fno-threadsafe-statics")#下面可选 -DSTM32F10X_MD -DSTM32F10X_HD等。一般选高点的_HD也不影响运行。set(USER_C_DEFINES "-DARM_MATH_CM3 -DUSE_FULL_ASSERT -DTRACE -DOS_USE_TRACE_SEMIHOSTING_STDOUT -DSTM32F10X_MD -DUSE_STDPERIPH_DRIVER -DHSE_VALUE=8000000" )if (BUILD_MODE STREQUAL "DEBUG") set(USER_C_FLAGS "${USER_C_FLAGS} -Og -g3") set(USER_C_DEFINES "${USER_C_DEFINES} -DDEBUG")else () set(USER_C_FLAGS "${USER_C_FLAGS} -O3")endif ()set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${USER_C_FLAGS} ${USER_C_DEFINES}")set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${USER_C_FLAGS} ${USER_CXX_FLAGS} ${USER_C_DEFINES}")include_directories( ${TOOLCHAIN_DIR}/arm-none-eabi/include ${TOOLCHAIN_DIR}/arm-none-eabi/include/c++/6.3.1 ${TOOLCHAIN_DIR}/arm-none-eabi/include/c++/6.3.1/arm-none-eabi/thumb/v7-m ${TOOLCHAIN_DIR}/arm-none-eabi/include/c++/6.3.1/backward ${TOOLCHAIN_DIR}/lib/gcc/arm-none-eabi/6.3.1/include ${TOOLCHAIN_DIR}/lib/gcc/arm-none-eabi/6.3.1/include-fixed)include_directories( #STM32固件库 system/include system/include/cmsis system/include/stm32f1-stdperiph #ALIENTEK开发板的代码库 board/ALIENTEK/System/delay board/ALIENTEK/System/sys board/ALIENTEK/System/usart #ALIENTEK开发板的模块代码库 board/ALIENTEK/MiniSTM32Board/LED board/ALIENTEK/MiniSTM32Board/KEY #自己的include user/include)file(GLOB_RECURSE C_FILES #stm32固件库 system/*.c system/*.cpp #ALIENTEK开发板的代码库 board/*.c board/*.cpp #自己的 user/*.c user/*.cpp)set(SOURCE_FILES ${C_FILES})set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -L"${PROJECT_SOURCE_DIR}/ldscripts" -T libs.ld -T mem.ld -T sections.ld -fmessage-length=0 -fsigned-char -ffreestanding -nostartfiles -specs=nano.specs -Xlinker --gc-sections -Wl,-Map=${PROJECT_NAME}.map")add_executable(${PROJECT_NAME}.elf ${SOURCE_FILES})set(HEX_FILE ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.hex)set(BIN_FILE ${CMAKE_BINARY_DIR}/${PROJECT_NAME}.bin)add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD COMMAND ${CMAKE_OBJCOPY} -Oihex $ ${HEX_FILE} COMMAND ${CMAKE_OBJCOPY} -Obinary $ ${BIN_FILE} )项目根目录下新建toolchain-arm-eabi-gcc.cmake,代码内容如下 include(CMakeForceCompiler)set(CMAKE_SYSTEM_NAME Generic)set(CMAKE_SYSTEM_PROCESSOR cortex-m3)find_program(ARM_CC arm-none-eabi-gcc ${TOOLCHAIN_DIR}/bin)find_program(ARM_CXX arm-none-eabi-g++ ${TOOLCHAIN_DIR}/bin)find_program(ARM_OBJCOPY arm-none-eabi-objcopy ${TOOLCHAIN_DIR}/bin)find_program(ARM_SIZE_TOOL arm-none-eabi-size ${TOOLCHAIN_DIR}/bin)# specify the cross compiler指定交叉编译器CMAKE_FORCE_C_COMPILER(${ARM_CC} GNU)CMAKE_FORCE_CXX_COMPILER(${ARM_CXX} GNU)set(CMAKE_ARM_FLAGS "-mcpu=cortex-m3 -mthumb -fno-common -ffunction-sections -fdata-sections" )if (CMAKE_SYSTEM_PROCESSOR STREQUAL "cortex-m3") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${CMAKE_ARM_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${CMAKE_ARM_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${CMAKE_ARM_FLAGS}")else () message(WARNING "Processor not recognised in toolchain file, " "compiler flags not configured." )endif ()# fix long strings (CMake appends semicolons)string(REGEX REPLACE ";" " " CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS}" CACHE STRING "")set(BUILD_SHARED_LIBS OFF)在Clion菜单中File>Settings>Build....>Cmake的Cmake options加入下面一行(自行修正路径) -DTOOLCHAIN_DIR="C:Program Files (x86)GNU Tools ARM Embedded6 2017-q2-update" -DCMAKE_TOOLCHAIN_FILE="toolchain-arm-eabi-gcc.cmake"点击Tools>CMake>ResetCache and Reload Project,当你每次编译报错时,可以第一步用这命令重清下缓存再试。
打开View>ToolWindows>Cmake窗口,点击Tools>CMake>Reload CMake Project,一般会报一些warning,最后会提示 -- Configuring done
-- Generating done
CMake Warning:
Manually-specified variables were not used by the project:
CMAKE_TOOLCHAIN_FILE
-- Build files have been written to: C:/Code/Embedded/STM32/pro_tmpl/pro_tmpl_stm32f10x/cmake-build-debug
再Run>Build,第一次编译整个目录会比较久,后面编译就自动只编译修改过的文件。buil成功最后会提示: [100%] Built target pro_tmpl_stm32f10x.elf
然后查看cmake-build-debug下有.bin和.hex生成,就算build成功了。 我把根目录的include和src放新建的user文件夹了,以和system、board对立区分。放张目录图:
项目目录
根目录中board放的是开发板的库,如上图有ALIENTEK的Mini开发板提供的常用库System和模块或驱动:KEY、LED。至于user、board标蓝色,system标黄色,用右键就可以标。
注:不建议把Stm32核心库system文件夹和开发板模块文件等放在项目外部链接的方式。原因是1.我试过多种方法编译stm32库为静态库然后在项目里链接编译老是报各种错。2.system里放的是.c源代码不是预编译好的.s汇编文件或.a静态库文件,比较利于学习底层代码,代码调试时也容易定位深层代码查找bug原因。3.代码项目总量就10几20MB,不算大。 烧写和调试有两种方案,
方案一是Eclipse或Segger Ozone(旧名J-LinkDebugger)中调试,
方案二是CLion中调用OpenOCD和Tcl expect脚本直接烧写后启动内部gdb窗口进行调试,
但由于CLion IDE尚不完善,gdb不是IDE原生支持的,所以在调试过程中有些不便之处,比如调试不能查看内存、寄存器,不能查看汇编,但一般不需要用到。//TODO不知道新版本CLion有改进没,我再看看。
由于两种方案在win下所用的J-Link仿真器驱动不同,所以
方案一和二同时只能二选一!!。(//TODO我再找找有没其他兼容的方法。) 方案一中Eclipse调试方法:单击菜单栏中的 Run -> Debug Configurations… 在左侧的 GDB SEGGER J-Link Debugging下的xxxDebug右键Duplicate复制一个新的配置,修改如图红框:
然后Debug既可。 方案一中Segger Ozone调试方法:Ozone>File -> New -> New Project Wizard…
新建Ozone项目后File -> Save Project As…, 选择CLion项目根目录,保存名为 run.jdebug 。
在CLion>File>Settings>Tools>External Tools,右侧新建Tool,配置如图
以后在CLion中可以Tools>External Tools>Ozone Debugger,就能打开Ozone手动调试。 方案二:CLion中直接烧写调试安装Jlink仿真器驱动程序说的直白一些openOCD只把Jlink仿真器当作普通的USB设备来使用,不使用Jlink自带的仿真器驱动程序,如果已安装了Jlink仿真器驱动程序,这个过程就是把原先的驱动程序换掉。
直接引用文章步骤: - 插入Jlink仿真器(如果是第一次插入Jlink仿真器,系统会要求安装驱动程序,我们可以点击取消,不必理会),运行zadig软件。
- 选择Options-List All Devices。
- 在其下拉列表中选择J-Link。
- 选择WinUSB驱动程序,点击Reinstall Driver按钮或Replace Driver按钮,这样便完成了驱动程序的替换。
如下图:
Zadig
安装配置OpenOCD
其中-f interface/jlink.cfg -f target/stm32f1x.cfg,jlink.cfg表示使用jlink仿真器,stm32f1x.cfg表示下载到的系列MCU。在OpenOCDOpenOCD-20170821shareopenocdscripts目录可以找到各类cfg配置文件。
注:如果使用LCD等模块其引脚与jtag接口冲突,则需要在C:CodeCommonEnvironmentOpenOCDOpenOCD-20170821shareopenocdscriptsinterfacejlink.cfg脚本中的interface jlink这行下方加上一行:#transport select jtagtransport select swd 就把jlink的默认jtag模式改为swd模式,只占用2个IO引脚。 运行Run>Extral tools>OpenOCD,提示如下则成功连接了仿真器: ........Info : No device selected, using first device.Info : J-Link ARM V8 compiled Nov 28 2014 13:44:46Info : Hardware version: 8.00Info : VTarget = 3.319 VInfo : clock speed 1000 kHzInfo : JTAG tap: stm32f1x.cpu tap/device found: 0x3ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x3)Info : JTAG tap: stm32f1x.bs tap/device found: 0x16410041 (mfg: 0x020 (STMicroelectronics), part: 0x6410, ver: 0x1)Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints如提示如下连接失败,则关闭gdb等正在运行的项,再次运行OpenOcd。或Ctrl+Shift+Esc,关闭openocd进程。再不行,则win任务栏右下角那点弹出J-link, 重插USB线再试: Open On-Chip Debugger 0.10.0 (2017-08-21) [https://github.com/sysprogs/openocd]Licensed under GNU GPL v2For bug reports, read http://openocd.org/doc/doxygen/bugs.htmlInfo : auto-selecting first available session transport "jtag". To override use 'transport select '.adapter speed: 1000 kHzadapter_nsrst_delay: 100jtag_ntrst_delay: 100none separatecortex_m reset_config sysresetreqWarn : Failed to open device: LIBUSB_ERROR_ACCESS.Info : No device selected, using first device.Error: No J-Link device found.安装ActiveTcl的expect并配置成CLion外部工具#!/usr/bin/expect#author: @fightfa#2017年9月13日 22:01:56 实现各种常见下载时问题的报错红字提示。#2017年9月12日 20:24:06 声音提示实现。优化代码快完成。#2017年9月11日 实现一键run/debug,run配置完成。速度 rebuild 2s~3s,少量改动build则 5s,本脚本2s 496ms,总5s左右#必看说明:!!!#教程详见:http://www.jianshu.com/p/f8a939ad7efd#CLion中Run/Debug的romote debug和romote run互相切换时不能先自动关闭gbd窗口中原已运行的Tab,要手动关闭!# TODO 解决左边说的。#Run/debug Configuraton 中remote debug中必须手动指定Symbol file即elf文件路径,emote run中则Symbol file置空。#窗口输出文字都用了英文写。set now [clock clicks]set timeout 8#TODO * 传入elf路径参数给CLion中的gdb remote 再使CLion开gdb窗口。(难实现。)#TODO 优化参数传入格式#TODO 处理可能的因地址含有空格而须带双引号的参数处理的问题#注:将传入的地址中所有的左斜/替换为右斜,由于在win中地址是\左斜,linux mac中expect shell等只支持/右斜的地址,expectForWin也是set num [regsub -all "\\" [lindex $argv 0] "/" projectFileDir]set num [regsub -all "\\" [lindex $argv 1] "/" bin_path]#action:执行动作:-Run或 -Debugset action [string tolower [lindex $argv 2]]set bin_path $projectFileDir/$bin_path#必须是严格格式《空格{》《}空格》。。# 保持 } elseif 才能不报错。。if {$action=="-debug"} { send_user ">>Action is Debugn"} elseif {$action=="-run"} { send_user ">>Action is Runn"} else { set action "-debug" send_user "n>>warn: Unkown Action of '$action', now is default to DebugnYou can set argv[1] '-run' or '-debug' n"}global MessageBeepset MessageBeep $projectFileDir/MessageBeep.exeproc beepError {} { global MessageBeep exec $MessageBeep 16}proc beepSucceed {} { global MessageBeep exec $MessageBeep 64}#proc beepOk{} {# global MessageBeep## 0 这声音其实更常用在warn上。。# exec $MessageBeep 0#}#发出铛一声,提示build完成#beepOk#结束与openocd会话的函数:proc exitSession {code} { #结束会话,不结束会话可能会导致下次烧录时send出错吧#TODO 验证左边。 send "exitn" expect "Connection closed by foreign host" set timeout 0 exit $code}#TODO 不能是send_error $expect(0,string) 原因未知#TODO send_error 偶尔显示不出来就exit了 原因未知proc abort {str} { beepError send_error n$str global timeout exitSession 1}proc abortTimeout {} { global timeout beepError puts "n" send_error "n>>error:timeout ${timeout}s! please check the above, or:nyou may try extend the timeout value (or set -1 to be not timeout) and run again." exitSession 2}proc abortCatch {str} { beepError send_error "n>>error:process is interrupted because catch the follow from above :" send_user n$str global timeout exitSession 1}proc abortWithTips {} { abort "failed! please check the above, or:n1.Power on your board;n2.Rerun the tool OpenOCDn3.Modify or comment this line in expect.writeflash.sh and rerun"}#步骤1:登录建立与会话spawn telnet localhost 4444#不能如下行这样写,会卡上3、4秒。。。#expect { ">" {}expect { -re "ntelnet: Unable to connect to remote host.*n>" { abortWithTips } ">" {} timeout {abortTimeout}}#步骤2:复位板子send "reset initn"#send "resetn"#send "initn"#send "haltn"#timeout {abortTimeout} 这句放前面会慢4s。。。#不能用^或A匹配开头。。expect { -nocase -re "n(error|failed).*n>" { abortWithTips } ">" {} timeout {abortTimeout}}#步骤3:烧录bin文件到板子send "flash write_image erase $bin_path 0x8000000n"expect { -re "nwrote(.*)>" { #发出铛一声,提示烧写完成 beepSucceed } -re "n(error|failed|couldn't open.*)>" { abortCatch $expect_out(1,string) } timeout {abortTimeout}}#TODO 上一指令和下面几个指令偶尔运行会出现多一个 >字符。导致显示信息有时重复和乱了行顺序。。影响不大。#步骤4:烧录完发下面指令给板子if {$action=="-debug"} {#下载完断点调试: send "haltn" expect ">" #打开调试通信模式,可以CLion下方的OpenOCD窗口中看到接收trace_puts等的返回信息,这里必须加。 send "arm semihosting enablen" expect ">"} elseif {$action=="-run"} {#下载完直接运行,其中edit configurations->remote run 中 Symbol file必须保持为空#这两行可不加:# send "resetn"# expect ">"#打开调试通信模式,可以在CLion下方的OpenOCD窗口中看到接收trace_puts等的返回信息,若不用到则可关。 send "arm semihosting enablen"# send "arm semihosting disablen" expect ">"}#步骤5:计算本脚本运行时间,不包括Build时间 #TODO * 计入Build时间的方法set time [expr [clock clicks]-$now]set seconds [expr $time/1000]set millis [expr $time%1000]set now [clock format [clock seconds] -format {%H:%M:%S}]#send_user "n>>w 烧写成功!耗时 ${seconds}s ${millis}msn"send_user "n>>$now Write Flash finished in ${seconds}s ${millis}msn"#expect offexitSession 0其中发出声音提示是调用了Windows的API MessageBeep,由于MessageBeep函数参数不带句柄回调,所以直接在expect中写
exec "C:/windows/system32/cmd.exe" "/c rundll32 user32 MessageBeep "(最后有个空格)或在cmd中打rundll32 user32 MessageBeep
是可以直接发声,但发声随机,不能指定。所以我开CLion写了个简单的MessageBeep.exe程序,如下 #include /*expect脚本中使用方法示例: exec "MessageBeep.exe" 48 常见声音提示: #define MB_OK 0 #define MB_ICONWARNING 48 // ASTERISK :星号 #define MB_ICONASTERISK 64 #define MB_ICONERROR 16 */int main(int argc, char *argv[]) { UINT beep = MB_ICONERROR; if (argc > 1) beep = (UINT) atoi(argv[1]); MessageBeep(beep); return 0;}//expect脚本中直接运行:(只能发一种不确定声音)// exec "C:/windows/system32/cmd.exe" "/c rundll32 user32.dll MessageBeep "// 只能发一种不确定声音:// system("rundll32 user32.dll,MessageBeep ");编译成MessageBeep.exe后复制到stm32项目根目录下即可供expect脚本调用。也可直接在我github项目上复制。 个人啰嗦PS:
1.为了写set num [regsub -all "\\" $bin_path0 "/" bin_path]这一行实现替换字符串效果,我可瞎找了一个晚上试了近一百行代码啊。。最终在这找到解决思路: Tcl 编程简介。ActiveTcl expect和其他系统的expect在语法上还是有不少不同的。。。。
2.为实现expect中发出声音提示,尝试了不少思路,如运行bat、vbs、脚本等。
然后在CLion中File>Settings>Tools>External Tools,右侧新建Tool,命名为Write Flash & Run,配置如图:
writeflash tool
Parameters为$ProjectFileDir$expect.writeflash.sh $ProjectFileDir$ cmake-build-debug$ProjectName$.bin -run,
路径使用了CLion的$xx$参数(注意$xx$参数只有在Build运行后才能使用),比较通用,避免建了新项目又得改这里。
路径中尽量用右斜,windows里的路径左斜默认表示法真是坑人啊。
再选中Write Flash & Run,点击右上方复制图标,生成新tool,命名为Write Flash & Debug,配置同上,但Parameters为$ProjectFileDir$expect.writeflash.sh $ProjectFileDir$ cmake-build-debug$ProjectName$.bin -debug接下来是Run>Edit Configurations...中,添加gdb remote配置:
其中Symbol file必须置空,这样执行Run可烧录完直接让板子运行而忽略所有代码断点。记得勾选single instance only。下方添加的工具是点击绿色+号出现的前两项。
再复制remote run为remote debug,修改如下部分:
其中Symbol file是你生成的elf文件路径:C:/Code/Embedded/STM32/pro_tmpl/pro_tmpl_stm32f10x/cmake-build-debug/pro_tmpl_stm32f10x.elf好了,现在你打开OpenOCD tool,(打开一次且链接上仿真器了就行)
再运行 romote run:
如下,编译烧录成功,板子运行了!
OpenOCD显示了板子传回的“hello stm”的信息:
我在main.c中写的demo是:intmain(int argc, char *argv[]) { int i = 0; delay_init(); //延时函数初始化 LED_Init(); //初始化与LED连接的硬件接口 //CLion调试时在OpenOCD窗口console中有返回信息: trace_puts("hello stm32"); for (int i = 0; i < 5; i++) { LED0 = 0; LED1 = 0; delay_ms(300); //延时300ms LED0 = 1; LED1 = 1; delay_ms(300); //延时300ms } while (1) { i = ++i % 6; LED0 = 1; LED1 = 1; delay_ms(300); //延时300ms LED0 = 1; LED1 = 0; delay_ms(300); //延时300ms if (i == 3) { LED0 = 0; delay_ms(300); //延时300ms } }}切换到romote debug前,先将gdb的romote run进程结束掉,再选择remote debug,运行:
可以进行调试了,断点、跟踪变化等。但试了中途改变量值继续运行会没变化,可能clion gdb工具里还没实现直接修改寄存器的功能,也未有查看变量地址等功能。应该CLion以后版本会支持吧。 OpenOCD,remote run/debug等都可设置快捷键。推荐Shift+Alt+D打开openocd,Shift+Alt+X编译烧录,Alt+2为Cmake窗,Alt+3为Build窗,等等。 最后一步是把项目pro_tmpl_stm32f10x上传到github仓库了,点这里。 好了,现在终于可以愉快的敲C代码了! 相关资料//TODO 参考文章
|