前面一个帖子介绍了使用eclipse来开发STM32的固件,但有的时候使用Eclipse的GDB调试器会崩溃掉,反复这样造成我们开发的效率降低,信心也会受一打击。
最近接触到的许多源码,就是在linux下编译开发的,源码中显示他们并没有使用任何的IDE。
实际上在Linux中的开源软件,很可能几乎不会使用IDE环境,他们都很“原始”地采用文本的方式进行编写。可能,在Linux环境中,这才叫做原生态。
在此我打算不依赖于Eclipse等IDE工具去开始嵌入式开发,并将这些过程详尽地纪录下来。
主机系统:Ubuntu 12.04 LTS 32bit
交叉编译器:CodeSourcery
目标机:stm32w108
1 启动openocd
我使用的调试器为st-linkV2,与st-linkv2配套的软件在Ubuntu下没有的官方的支持,有爱好者开发了一个st-linkv2的调试服务器。在我这里使用于STM32F407时很不错,但用于我这块新的stm32w芯片时表现出一些问题来,估计是尚未支持到。所以我转而使用openocd(需要0.7版本)这个非常流行也是多数在Linux下做嵌入式开发人员的调试软件。
openocd在启动时需要指定使用哪一个调试接口(stlinkv2),再指定目标的MCU名(stm32w),这些输入每次都是一样的。为了方便,我做了一个sh文件,将启动命令复制进去。这样每次开始调试的时候执行一次这个脚本就可以了。
新建一个start_debug_stm32w108_with_stlinkv2.sh在openocd/share/openocd/scripts下面,然后使用
chmod +x start_debug_stm32w108_with_stlinkv2.sh
让该文件具有执行属性。
start_debug_stm32w108_with_stlinkv2.sh内容
openocd -f interface/stlink-v2.cfg -f target/stm32w108_stlink.cfg -c "init" -c "halt" -c "reset halt"
2 gdb自动执行初始化文件
想要gdb在启动时执行自己当前elf文件夹下的.gdbinit文件,还需要在~文件中有一个.gdbinit文件,里面的内容是:
add-auto-load-safe-path /home/merlin/projects/eclipseCppJuno/stm32w_gpio/Debug/.gdbinit
然后在自己的elf文件目录下面添加另外一个.gdbinit文件,里面写上自己想要在程序启动时的初始化命令即可,如:
target extended localhost:
load
set $pc = Reset_Handler
#break pre_main
break main
含义很明显
先连接到gdb服务器,openocd的正常使用服务器端口为3333(如果使用telnet测试的话是4444端口)
然后load加载程序到flash中
再把pc设置到Reset_Handler,这就是程序的开头(如果没有这个常常飞到不知所云的地方去,下图显示它到了0x08000088地址上了,而我的Reset_Handler是在0x08000199地址的)
最后在main开始的地方加一个断点
之后你应该看到这样的输出了:
使用backtrace命令(缩写bt)可以看到当前运行地址已经在了Reset_Handler上了。
1. 如何查看程序运行到哪一行了
bt命令可以看到当前线程已经运行到何处了
2. 多线程程序(fork分支程序)
info threads用于查看有多个线程在运行
thread x用于将线程切换到x号去
3. 从某函数中跳出来
使用finish命令
4 打印变量的值
打印为10进制数:
(gdb) p realAddress
$4 = 134481884
打印为16进制数:
(gdb) p/x realAddress
$5 = 0x80407dc
5 查看断点与删除断点
使用info breakpoints查看地断点
删除时使用delete n(n为查看地断点时GDB所打印出来的标记)
6 查看某地址上的数据(FLASH或者内存都可以)
x address