A0500 Eclipse GNU工具链STM32开发 - matianfu/arabesque GitHub Wiki

在安装了Cygwin环境,熟悉了Eclipse基本使用之后,可以开始搭建STM32开发的交叉编译工具链、编译项目和调试。

安装

软件清单

  1. GNU Make和GNU CoreUtils

  2. GNU交叉编译工具链ARM版

  3. OpenOCD

  4. stlink V2驱动

  5. Eclipse

  6. EmbSysRegView,一个Eclipse插件

  7. STM32CubeMX和STM32F4Cube Firmware 1.3.0

GNU Make和GNU CoreUtils

Eclipse的Builder,设置为CDT Internal Builder,至少需要make, rm, echo命令才能工作;make命令来自GNU Make工具,rm和echo可由GNU CoreUtils包提供;

如果按照前面的文档安装了Cygwin,GCC和Make,则无须新安装软件;在安装GCC时Cygwin会自动安装GNU CoreUtils;可以在Cygwin Shell里输入rm和echo命令验证;

如果不安装Cygwin,替代的办法是安装GNU Make for Windows和GNU CoreUtils for Windows的独立发行版,下载链接如下:

http://gnuwin32.sourceforge.net/packages/make.htm

http://gnuwin32.sourceforge.net/packages/coreutils.htm

下载安装之后需要把二进制文件路径加入Windows系统路径中(环境变量Path);

GNU交叉编译工具链ARM版

官方的名称是:GNU Tools for ARM Embedded Processors,网站是:

https://launchpad.net/gcc-arm-embedded

下载页面是:

https://launchpad.net/gcc-arm-embedded/+download

本文档使用的版本是exe安装文件,版本4.9 2014q4:

gcc-arm-none-eabi-4_9-2014q4-20141203-win32.exe (md5)

下载之后安装,安装完成的界面上,如下图所示,不建议勾选Add path to environment variable选项;Eclipse能处理交叉编译工具链路径。

alt text

可执行文件默认安装位置在:

C:\Program Files\GNU Tools ARM Embedded\4.9 2014q4\bin

目录下是很多arm-none-eabi-前缀的exe文件,这些程序就是编译器,连接器和二进制工具(GNU Binutils)。

文档

C:\Program Files\GNU Tools ARM Embedded\4.9 2014q4\share\doc\gcc-arm-none-eabi

这个目录下是随程序一起发布的文档,应该作为该工具链的最权威文档;GNU工具链的版本很多,支持的平台也很多,第三方修改过的版本也很多;网上搜到的文档不一定适用于你在使用的工具链;

OpenOCD

如前面文档所述,可以选择文档介绍的方式在Cygwin里编译OpenOCD 0.8.0版本;

也可以下载预编译的二进制发行包,解压之后直接可以运行,无须安装;但我遇到的问题是预编译的二进制版和stlink v2配合不能实现semihosting功能,其他的debug功能一切正常;

stlink V2驱动

见前面文档

Eclipse

见前面文档

EmbSysRegView

后述

STM32CubeMX和STM32F4Cube Firmware 1.3.0

STM32CubeMX是一个代码生成工具,提供图形化的pinmux工具,时钟配置,提供项目代码框架,初始化代码,以及把Firmware包中的startup文件、HAL驱动、第三方库等代码复制到项目中;生成的项目支持IAR,Keil/MDK-ARM,和TrueStudio。

下载地址:

http://www.st.com/web/en/catalog/tools/PF259242

STM32F4Cube,可以和CubeMX工具搭配使用的STM32F4的Firmware,本文档使用版本1.3.0;下载地址:

http://www.st.com/web/en/catalog/tools/PF259243

安装STM32CubeMX,全部选择默认选项即可。

首次启动STM32CubeMX,首先应安装Firmware;

菜单Help -> Install New Libraries,在弹出的窗口中,底部,如果点击Check按钮程序将自动从网上下载Firmware安装,但速度非常慢;点击From Loc...按钮,在文件对话框中选择下载好的STM32F4Cube.zip文件,可直接从本地安装Firmware。

成功安装后,如下图所示。

alt text

关闭该窗口。

安装结束后,CubeMX把展开的固件库放在如下目录中:

C:\Users\<username>\STM32Cube\Repository\STM32Cube_FW_F4_V1.3.0

包含Firmware代码、文档和大量例子代码,在Projects子目录下;

用CubeMX生成代码

点击New Project创建一个新的代码生成项目;

alt text

在下拉列表中选择正确的MCU型号,Board Selector Tab页可以不选,点击OK;

alt text

Pinout Tab,在左侧找到RCC,在High Speed Clock下拉菜单中选择Crystal/Ceramic Resonator;

alt text

在Clock Configuration Tab,按照下图配置好时钟;

Main PLL的分频M选择和时钟频率一样的数值;倍频N选择336;路径选择HSE和PLLCLK,设置好APB1和APB2的Prescaler;

alt text

Configuration Tab和Power Consumption Calculator Tab不用配置;

菜单Project -> Settings,填入项目名称,选择项目文件目录,在Toolchain/IDE中选择TrueSTUDIO;TrueSTUDIO同样是基于GNU交叉编译工具链和Eclipse开发环境的IDE;代码兼容性会更好(Supposedly);

alt text

Code Generator Tab,选择Copy only the necessary library files,选择这个选项,CubeMX只把需要用到的Firmware文件复制到生成的项目中;

选择Copy All选项会把所有Firmware文件复制到生成的项目中,除非是打算把整个Firmware编译成库文件使用,否则不建议这么做,会大大增加编译时间;

alt text

点击OK关闭对话框;

菜单Project -> Generate Code,CubeMX开始在指定目录下生成代码和项目文件。

第一个Eclipse/Cross GCC项目

打开Eclipse;

如果缺省打开的workspace是前述文档中建议的Cygwin home目录下的文件夹;建议为stm32的Eclipse项目新建一个workspace;这样两类开发项目不会混在一起;

菜单File -> Switch Workspace -> Other...,选择一个新的路径,本文档示例使用的workspace路径是:

C:\stm32\workspace

这里不要求workspace路径中不包含空格和中文字符,建议使用易于访问的Windows路径;当然放在Cygwin Home里也是可以的,如果你打算使用Makefile和使用命令行编译的话;

新建Cross GCC项目

菜单File -> New -> C Project,项目名称minimal,选择Empty Projects,Toolchain选择Cross GCC,Next;

alt text

Next;

alt text

输入交叉编译器前缀和路径,注意路径是bin目录的路径,不是软件包的安装目录路径;

prefix和binpath是常见的设置交叉工具链的方法,如果不是使用Eclipse,通常这两个参数是设置在环境变量里或者通过命令行设置为Make的变量;

点击Finish;

alt text

和之前文档的Eclipse+Cygwin GCC类似,Eclipse CDT自动设置好了include的目录;

因为stm32的开发没有基于任何操作系统,所以这里的路径只有Toolchain提供的C语言标准库(实际上还有很多GNU扩展库)的路径,没有Cygwin/Unix系统的lib库路径;

Eclipse能找到这些路径,是因为Toolchain的目录结构有固定的约定;设置给Eclipse的只有binpath;Eclipse根据Toolchain的目录结构自动找到include path和lib path;

alt text

新建的Cross GCC缺省使用External Builder(GNU Make Builder)加自动生成Makefile方式Build;可以在导入源码之前先修改为(CDT)Internal builder,如果不喜欢在目标文件目录下有Makefile的话。

alt text

导入源码

菜单File -> Import,选择File System,Next;

alt text

Browser,选择刚刚CubeMX生成项目的目录,minimal;

先在左侧选中minimal,选择所有文件夹和文件,然后去掉左侧Projects文件夹的勾选,和右侧.mxproject和minial.ico两个文件的勾选;

Projects文件夹中是TrueSTUDIO的项目文件,.mxproject和.ioc文件是CubeMX的(代码生成项目)的项目文件,这些文件是不需要的;

点击Finish

alt text

可以在项目中看到导入的目录;

alt text

Eclipse的文件类型BUG

Eclipse CDT有个愚蠢的bug,只把.S文件(大写S)和.asm预定义为汇编源文件,用户可以自己添加文件扩展名但是无法添加.s。

这个设置在菜单Windows -> PreferenceC/C++ -> File Types里,如果发现某些扩展名文件没有被编译,首先检查该设置;

alt text

Workaround Solution是把汇编文件的扩展名改为.S或者.asm,好在一般项目里只有startup文件是汇编的,在导入的源文件中这个文件位于下图所示的目录中;

alt text

选中该文件,F2,或者鼠标右键菜单选择rename,将文件的扩展名修改为.S;

选中该文件,鼠标右键菜单PropertiesC/C++ Build -> Toolchain Editor,确认CDT已经自动为该文件选择了Cross GCC Assembler,表明它正确的识别此文件为汇编文件,会调用工具链的汇编工具编译;如果这里显示的是No Tool,意味着CDT没有把此文件当作汇编文件;

alt text

Paths and Symbols

导入源码之后首先要做的是设置include path;

请仔细注意操作过程;

进入设置界面,先选中Languages栏的GNU C,点击Add按钮;

alt text

在弹出的对话框里,Eclipse提供了多种选择路径的方式;

alt text

我们导入了全部的文件,所以选择Workspace;如果是导入外部的include文件,和预编译库文件一起工作的,选择File system更方便;

Variables提供Eclipse内置的以及用户自定义的(Build Variables)变量名称;如果你仔细观察Firmware库里的文件路径,会发现项目文件单独放在一个目录里,这样做的好处是可以让很多项目共享源文件,那么include path可以这样书写:

${ProjDirPath}\..\..\Libs\FatFS\Include

其中${ProjDirPath}是Eclipse CDT的Build Variable,Eclipse CDT会在开始编译之前把字符串中的这些变量全部展开成真正的路径字符串,然后再送给make等编译工具编译;

事实上在复杂项目中这是推荐的方式,但是在本文档中我们不把简单问题复杂化,示例的项目是自包含的,没有引用任何外部文件;

点击Workspace;在弹出的文件对话框中,找到第一个要加入的路径,OK;

alt text

结果如下:

alt text

做下图所示的更改;

alt text

首先删除/minimal/前缀,去掉Is a workspace path勾选;这样得到的路径是当前项目的相对路径;这样做的好处是你可以把整个项目copy到其他地方,然后用Eclipse导入;如果不做此修改,该路径是一个相对于Workspace文件夹的路径,这种方式通常用于一个Workspace里多个项目协同开发,例如其中一个项目是sd/mmc驱动,另一个项目是应用,那么互相引用路径的时候一般使用Workspace路路径;

然后勾选Add to all configurations,意思是这个include path加入所有的Build Configuration,包括Debug和Release;一般这就是我们需要的,除非你希望在不同的Build Configuration里使用不同的头文件;

在这个项目里不需要勾选Add too all languages,即该路径仅仅是GNU C语言的路径,而不是汇编语言文件的路径;因为这个项目里只有一个startup汇编文件,它不需要include任何其他文件;当然如果勾选了也没有副作用;

如果是C/C++混合语言项目,你很可能需要选择该选项,即无论C还是C++文件都需要有这个include path。

实际上,在编译过程中,每个源文件都是独立编译的;例如有三个文件,分别是:

a.s b.c c.cpp

在编译.s文件时,CDT只把对应汇编语言的include path参数传递给编译器;

在编译.c文件时,CDT只把对应C语言的include path参数传递给编译器;

在编译.cpp文件时,CDT只把对应C++语言的include path参数传递给编译器;

他们都可以是不同的设置;

同时还有Debug Configuration和Release Configuraton,所以实际上你看到的Path and Symbol的界面里,Include directories的列表实际上有4个:

Debug Configuration, Assembly Language Debug Configuration, GNU C Language Release Configuration, Assembly Language Release Configuration, GNU C Language

如果有更多的语言和更多的Build Configuration,这个列表的数量还会更多,一个一个的设置将会非常繁琐和容易出错;所以要非常理解这里的设置的含义,恰当的勾选Add to all configuration和Add to all languages选项;

点击OK,结果如下;

alt text

  • 如果发现添加的路径不正确,不要使用Edit修改,因为你只能修改当前Configuration和当前语言的设置,另外还有三个语言和配置组合的列表不会同时被修改;应该使用Delete删除错误路径,重新添加;

重复上述过程,加入其他三个include path;同时检查一下Relase Configuration,确认路径设置也是正确的;

alt text

在这个项目中,没有第三方的预编译库文件,所以Libraries和Library Paths都不用设置;大部分STM32的项目也都是如此;

Source Location里,因为创建时是空项目,CDT自动包含了项目根目录,下面的子目录里的源文件都会被选中编译;

最后来设置Symbols;

alt text

只有C/C++语言有Symbols设置,汇编语言编译器不接受Symbol;STM32F4Cube Firmware要求定义两个Symbols:

  • MCU型号,对这个项目而言是STM32F407xx

  • USE_HAL_DRIVER

如果不清楚对应的MCU型号的Symbol,可以在这个文件的代码里找找:

Drivers\CMSIS\Device\ST\STM32F4xx\Include\stm32f4xx.h

如果使用的不是STM32F4,可以去Firmware里找类似的头文件;

注意大小写;

点击Add

alt text

填写Symbol Name,Value可以为空;

勾选Add to all configurations,理由和前述include path一样;OK;结果如下:

alt text

重复这个操作,加入第二个Symbol,USE_HAL_DRIVER;然后检查一下Release Configuration是否设置一样;

alt text

Paths and Symbols设置是设置中最繁琐和需要耐心的地方;这一步设置正确后,编译器就不会海量的报错,易于检查分析出错原因;

编译和链接参数

设置完Paths and Symbols之后,可以进行一次编译;

在Console View里可以看到如下出错信息:

Error: selected processor does not support ARM mode 'dsb'

alt text

Cross Compiler缺省编译的是ARM指令,在编译C文件时不会报错(当然编译结果是错的),但是在编译汇编文件时(注意出错行中给出的文件是.s文件),会遇到指令集不兼容问题;Cortex M系列CPU只支持Thumb指令,不支持ARM指令,这是编译错误的原因。

开始设置编译链接参数。

首先查看Cross Settings,确认prefix和bin path设置正确;

alt text

然后尝试添加CPU类型选项;这组选项是编译器,汇编器,和链接器都需要的,所以我们先定义一个Build Variable,在Build Variable界面,点击Add

alt text

Variable Name命名为CPU_FLAGS

Type为String;

Value是:

-mthumb表示编译thumb指令;

-mcpu=cortex-m4指定ARM Core类型;

-mfloat-abi=hard表示使用硬件浮点单元;

-mfpu=fpv4-sp-d16指定硬件浮点单元的类型;

写在一起是:

-mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16

分割符是空格,顺序不重要;点击OK;

alt text

这里再强调一下Build Variable和Environment的区别:Build Variables只在CDT内生效,所有设置里的Build Variables都会在make开始之前被展开(字符串替换),结果交给make系统;Environment则是make时的环境变量;这里设置的CPU_FLAGS,如果在Environment里设置也是可以的,CDT不会展开,而是直接把字符串或字符串列表里出现的${CPU_FLAGS}远远本本交给make或者shell;make或者shell会自动展开,cdt、make、以及shell对字符串变量展开的语法是一样的;所以结果是一样的,但是机制不同;


回到Settings,选中Cross GCC Compiler,把command栏内容改为:

gcc -c ${CPU_FLAGS}

-c的意思是将源文件(.c)编译成Object文件(.o);CDT采用两步编译方式,先将全部.c和.s文件编译成.o,然后再调用Linker全部链接成可执行程序;

alt text

选择Miscellaneous,把原有的-c -fmessage-length=0选项删除;

alt text

选择Cross GCC Assembler,将Command域里原有的as替换成gcc -c ${CPU_FLAGS} -g

理论上gcc应该仅仅是编译c文件的编译器,as是用于编译汇编文件的编译器;但实际上gcc是个前端程序(Frontend),无论编译C还是汇编,以及链接,调用的都是gcc程序;它再把任务交给cpp(preprocessor)、ld(linker)或者as(assembler);这样做的好处是对于简单的程序编译,可以大大简化命令书写,让编译过程一次完成;

-g是添加Debug信息;

alt text

回到Cross GCC Compiler,逐一检查一下各种设置;

Dialect指的是C语言标准,这里没必要设置;

alt text

Preprocessor是预处理器,处理宏定义;这里的-E选项可以用于调试宏定义,它导致gcc不编译程序,而是把预处理器宏展开之后的C文件打印出来;

alt text

Symbols,是CDT根据Paths and Symbols设置自动填写的;最终送给编译器的参数,例如对应USE_HAL_DRIVer,是-DUSE_HAL_DRIVER-D表示定义(define)Symbol;

alt text

Include path,也是自动填写的;最终送给编译器的参数,例如对应../Inc,是-I../Inc,用..表示当前路径很重要,否则编译器会把这个路径理解为绝对路径;

alt text

Optimization,选择None即可,编译器参数是-O0,GCC的优化分为4级,0,1,2,3;3是最高优化;但是保险的做法是选择-O2,因为-O3不是在所有场合下都比-O2更好,有可能更差,和应用情况有关;

另外编译器还提供一个-Os选项,选择该选项获得的代码体积最小;

在Debug配置中基本上只选择-O0,复杂的优化有Code Motion,目标机器码的逻辑和源码是等价的但是工作流可能不一样,调试时和源码对不上;

alt text

Debugging,选择目标文件中Debugging信息的丰富程度;最多为-g3

在Other debugging flags,可以添加-ggdb选项,会为GDB Debugger提供一些额外的信息;

alt text

Warning,缺省的-Wall,打印所有Warning信息,是OK的;

缺省情况下,编译器遇到Warning只会打印信息,不会停止编译;-Werror选项会让编译器在遇到Warning的时候停下来;

一般不会在新项目中关闭任何Warning信息,需要这样做的原因可能是你拿到了一份第三方代码或者老代码,里面某些语法会产生大量的Warning,但你确信这些Warning不是代码逻辑问题,可以用选项选择性关闭;

alt text

Miscellaneous,目前不需要其他选项;-v可以打印非常详细的错误信息,帮助错误分析;

alt text

Debug Configuration的完整的编译选项(对每个C文件)是:

gcc -c -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 -DSTM32F407xx -DUSE_HAL_DRIVER -I../Drivers/CMSIS/Include -I../Drivers/CMSIS/Device/ST/STM32F4xx/Include -I../Drivers/STM32F4xx_HAL_Driver/Inc -I../Inc -O0 -g3 -Wall

这一步完成后如果迫不及待的编译一下,会看到所有的.o文件都正确生成,报错的是Linker;

alt text

Linker的Command还是gcc,同样需要cpu选项,但是没有-c,这个参数是编译参数,不是链接参数;

alt text

缺省的选项没问题,可以选择-static,TrueSTUDIO的一些例子使用了这个选项,但我不清楚这个选项在STM32上有什么意义,因为无OS裸跑是肯定不能链接动态链接库的,也许针对使用rtos的应用有意义;

alt text

链接库文件和库文件路径,C语言的内置库不用指定,gcc可以自动链接;如果链接第三方库(比如指纹算法解码库),需要指定;

alt text

Linker有很多其他选项可以指定,比如生成Linker.map文件(函数和源码的映射),清除未被调用的函数和未使用的数据等等;暂时不用;

alt text

最后一个设置和共享库有关,STM32的裸芯片开发不会用到;

OK,再编译一次,这次得到的错误是Linker抱怨很多符号没有定义;

alt text

这些符号对应的含义是代码段、数据段、栈等内存空间分配地址;需要提供这些定义给Linker;需要一个Linker脚本文件;

Linker脚本

可以在其他IDE中找到这个Linker脚本,我从TrueSTUDIO 5.2.1里拿到的Linker文件是:stm32f4_flash.ld

下载这个文件(右键,另存为),Eclipse File -> Import,导入到项目中,放在项目的根目录之下;

然后在Linker设置中,Command栏修改为:

gcc ${CPU_FLAGS} -T"../stm32f4_flash.ld"

-T参数表示传递Linker脚本给Linker;路径也可以写成项目的相对地址:

-T"${ProjDirPath}/stm32f4_flash.ld"

alt text

编译,还有一个错误:undefined reference to '_exit'

alt text

syscalls.c

这个错误的原因在第一篇文档中解释过;C语言标准里约定了libc中的一些函数留给了平台实现,而不包含在C语言标准库(libc)之内;这些函数都和Unix操作系统API有关,因此被称为syscall;因为这个例子程序太简单,只有_exit() syscall被使用(在程序退出时),如果程序内有代码使用了更多的Unix API,例如文件操作的open/read/write/close,或者使用了堆内存,malloc/free,Linker会报告更多的错误。

TrueSTUDIO里提供的syscalls.c文件是:

TrueSTUDIO syscalls.c

在STM32F4的Firmware例子工程里也有syscalls.c提供,在所有的TrueSTUDIO项目代码里都有,例如:

Projects/STM32F429I-Discovery/Examples/BSP/TrueSTUDIO/syscalls.c

可以下载上述链接版本导入,或者直接导入例子工程里的版本,将文件放在src目录下。

alt text

再次编译,终于成功了,Cheers!

alt text

小结

  1. (Optional)用STM32CubeMX和Firmware Library生成代码;

  2. 创建新的CROSS GCC项目;

  3. 选择编译方式为CDT Internal Builder;

  4. 设置include path;

  5. 设置Symbols;

  6. 设置Compiler,Assembler、Linker参数;

  7. 提供Linker Script文件

  8. 提供syscall实现(syscalls.c)

调试

安装

调试需要使用OpenOCD Debug Probe Software,它提供GDB Server;

调试程序(Debugger)是GNU交叉编译工具链中的arm-none-eabi-gdb.exe;

GDB是源码级(Source Level)调试器,需要解析Elf数据、Map目标内存的指令和数据到源文件的代码和变量中,所以它必须理解目标硬件的架构和指令集,不是硬件无关的;它是工具链中必要的组件,使用哪个工具链Build可执行程序,就需要使用相应的Debugger调试程序;

Eclipse以GDB前端的方式工作,用户不需要使用GDB的命令行界面,Eclipse会根据用户操作自动完成这些工作;

除了OpenOCD和GDB之外,调试工作还需要两个软件(Eclipse插件),和配置Debug Launch Configuration。

GDB Hardware Debugging插件是CDT的官方可选组件;针对硬件调试,提供Debug Launch Configuration设置模板;

EmbSysRegView是Eclipse Marketplace(插件市场)里的一个第三方插件,它提供STM32F4上的寄存器浏览,如果没有这类插件,用户只能浏览ARM Core里的CPU寄存器,其他的I/O寄存器只能通过原始的内存浏览功能,对照芯片手册,了解I/O寄存器的值;

安装GDB Hardware Debugger

Eclipse菜单,Help -> Install New Software

alt text

点击界面上的Available Software Sites链接;

alt text

在右侧列表中勾选CDT;

alt text

Works with:输入域中输入CDT,选中CDT软件池的网址链接,按回车键;等待Eclipse Install去服务器取包说明数据;结果如下图所示;

alt text

  • Eclipse的官方软件池在某些地区可能访问困难;Eclipse支持设置代理服务器,在主界面菜单Window -> Preferences,左侧栏General -> Network Connections,在Active Provider下拉列表里选择Manual,编辑http、https、socks代理服务器即可。

展开CDT Optional Features节点,勾选C/C++ GDB Hardware DebuggingNext

alt text

alt text

接受版权协议;

alt text

alt text

安装完成后会要求重启Eclipse,点击Yes

alt text

设置Debug (Launch) Configuration

在工程中选中项目名称,主界面菜单Run -> Debug Configuration

在左侧的GDB Hardware Debugging分类下新建Debug Configuration;

CDT会自动填写Main Tab页内容;

alt text

选择Debugger Tab页,GDB Command需要修改为交叉编译工具链提供的GDB程序,使用Browser浏览文件,找到arm-none-eabi-gdb.exe程序;

Remote Target栏内,Port Number修改为3333,这是OpenOCD缺省的GDB Server侦听端口;

alt text

alt text

Startup Tab页,设置gdb的启动选项;

在Intialization Commands栏内,加入command:

monitor reset halt

reset halt实际上是OpenOCD的命令,不是gdb的命令;monitor是GDB命令,它会把reset halt命令“透明的”发送给OpenOCD;

Reset and Delay可以修改为0;它是启动GDB后的等待时间,不需要等待3秒钟这么久;

alt text

把控件面板卷到最底部,勾选Set breakpoint at:,后面加入main;设置程序启动后,在C入口函数main()设置临时断点(是个一次性断点,hit之后自动从断点列表中删除);

点击控件面板底部的Select others...链接;

alt text

勾选Use configuration specific settings,然后在激活的列表中选择Legacy GDB Hardware Debugging Launcher;CDT缺省的DSF Launcher目前和GDB Hardware Debugging有冲突,所以使用旧的启动器;希望在未来版本的Eclipse中DSF可以支持;OK;

alt text

OK之后,界面底部显示的是Using Legacy GDB Hardware Debugging Launcher;先停在这个界面,不用关闭;

alt text

启动OpenOCD

和电脑连接好目标板,stlink v2硬件;

在Cygwin Shell中启动openocd,正常结果如下图所示;

alt text

如果你用的是二进制发行版,没有安装Cygwin,可以在DOS Shell下,进入OpenOCD的解压目录,使用同样的命令启动;

在我的实际使用过程中,OpenOCD的表现非常稳定(绝不比Keil/MDK差),只有在硬件拔出重新插入时有可能无法自动恢复连接,这是需要中止(Ctrl+C)和重新启动OpenOCD;

在其他的调试情况下,应该一直保持OpenOCD运行;在Eclipse内中止Debug实际上只中止了GDB程序,但不会中止OpenOCD/GDB Server,也没有这个必要;

Debug

回到Eclipse中,启动Debug;需要几秒钟时间,程序停在汇编入口Reset_Handler位置;

alt text

让程序恢复运行,ResumeF8,C程序入口的main断点生效;

alt text

请注意界面底部,右侧,有个计算机外形的图标,右侧有下拉箭头,下拉后可以看到有4个选项;这4个选项都是Console输出;

alt text

  1. CDT Global Build Console,如果是多个项目Build,这个窗口把所有的Build信息合并在一起输出;

  2. CDT Build Console (minimal),minimal项目的Build输出;

  3. ......arm-none-eabi-gdb.exe,这是GDB的窗口;

  4. ......minimal,这是我们正在调试的minimal程序的输出,当然,目前是没有输出,因为这个程序没有standard i/o。


GDB窗口里能看到所有Eclipse向GDB程序发送的命令和返回结果,例如下图中红色的tbreak main,就是在程序启动的时候在main()设置了临时断点(一次性);

通过GDB窗口直接向GDB程序写命令是可能的(而且在某些场合下非常有用);图中示例的绿色指令info breakpoints,是手工输入的,查询当前的所有断点;GDB返回结果:No breakpoints or watchpoints.

alt text

在调试时查看OpenOCD的窗口则可以看到OpenOCD的状态输出,但对开发者一般帮助不大;

alt text

在Eclipse调试结束后,OpenOCD窗口可以看到:

Info : dropped ‘gdb' connection’,表示GDB程序关闭,GDB和GDB Server之间的连接断开;

alt text

EmbSysRegView

这个冗长的名字的意思是:Embedded System Register View。

它不是CDT的官方组件,但在官方的Eclipse Marketplace发行,免费软件;

Eclipse主界面菜单,Help -> Eclipse Marketplace;基本上需要代理服务器才能访问;

alt text

Find:输入域内输入EmbSysRegView,回车,得到搜索结果;点击Install

alt text

alt text

同意版权协议;

alt text

确认安装未签名包:

alt text

安装完成后回到主界面,为EmbSysRegView配置处理器类型;

主界面菜单Windows -> Preferences,展开C/C++ -> Debug -> EmbSys Registers View

alt text

如下图所示设置:

Architecture: cortex-m4

Vendor: STMicro

Chip: stm32f40x

Board: none

alt text

点击OK关闭。


Debug时,在Debug Perspective下,菜单Windows -> Show View -> Other

alt text

选择Debug分类下的EmbSys Registers,点击OK;

alt text

在Debug Perspective界面下出现EmbSys Registers View;

alt text

展开RCC节点,找到和展开RCC_CR寄存器,双击寄存器名左侧三个圆点的图标,该操作使能RCC_CR寄存器的读取,在每次程序停下的时候,EmbSysRegView会读取相应的寄存器数据并显示;

alt text

单步执行一次,或者让程序停在断点上;即可看到寄存器的值;

alt text

读取寄存器的操作性能不快(和Debug Probe价格有关,高档货可以很快);所以Debug时应该只有在必要的情况下读取必要的寄存器值;不再需要的浏览的寄存器应该再次双击圆点图标,关闭读取;

小结

  1. 使用arm-none-eabi-gdb.exe作为Debugger;

  2. 使用OpenOCD(以及stlink v2驱动)作为GDB Server;

  3. 使用Eclipse作为Debugger FrontEnd;

  4. 需要安装GDB Hardware Debugging Plugin,为Debug Launch Configuration提供设置模板;

  5. Debug Launch Configuration的设置并不复杂,需注意设置Legacy Launcher,而不是使用DSF Launcher;

  6. OpenOCD的Shell输出可以看到OpenOCD/GDB Server的工作状态;

  7. Eclipse的Console列表里,arm-none-eabi-gdb.exe Console可以观察GDB命令和结果,可以手工输入GDB命令;

  8. EmbSysRegView Plugin提供观察寄存器信息的功能;但它支持的MCU种类并不多,只有最流行的型号;

未解决的问题

  1. 如果EmbSysRegView未提供我需要的MCU型号怎么办?(见总结部分)

  2. 一般商用IDE都提供一个restart功能,即无须重新下载程序,只是reset CPU,重置gdb,但不必重新烧录程序,在反复调试的时候很有用;目前没找到好办法实现这个功能,我会继续研究,有解决方案后会更新本文档;目前只能停止和重新启动Debug,大约有8秒左右的等待时间;

总结

至此,这个系列文档完成了基本的STM32F4开源开发工具套件搭建,介绍了Cygwin和Eclipse,给出了简单的例子;

对于个人项目,用STM32CubeMX生成的基础框架,然后用本文档介绍的方法基本不会遇到其他问题;在某些情况下Linker文件和syscalls.c可能需要有所调整;

开源开发工具为开发者展开了所有的细节,使用上它不完美,但足以完成有质量的开发工作而且不牺牲效率;

选择开源开发工具链的真正收益,不是为了节省正版软件的钱;而是因为两点:

第一,绝大多数嵌入式硬件平台,无论是MCU,还是嵌入式Linux,这套开源开发工具链介绍的概念都是通用的;开发者在使用过程中可以不断深入的学习到新的知识,无论平台、市场和厂商如何变换,这些基本的东西是不变的,在这样的工具链上积累的经验,可以使用和收益终身;

事实上,越来越多的厂商基于Eclipse平台推出集成开发工具,例如TI的Code Composer Studio,NXP的LPCxpresso等等;ST虽然没有官方的IDE推出,但是TrueSTUDIO,emIDE,emBlock,Coocox IDE,都是基于Eclipse的;它们能提供给开发者的功能,90%都在这个系列文档中涵盖了;

第二,工具链并不仅仅是一个完成工作的工具而已,它是可以富有创造性的;在商用IDE里,很多调试和测试方法,项目管理和代码版本管理工具的集成,都需要等待工具软件厂商提供;

但是使用开源工具链,你不需要等待,有很多开发者有过和你一样的好想法而且很可能早已付诸实施,在开源时代,广泛学习其他开发者的经验,利用他们的代码、产品、和工具,才是生产效率和产品质量的保证;象John Carmack那样,程序员如侠客一般单打独斗创出传奇的时代早已成为历史;在开源时代程序员如果希望创造出有影响力的产品或者项目,必须站在无数前辈程序员的肩膀上;


后面的文档会尽可能多的提供一些功能示例,包括:

  1. Eclipse EGit代码版本管理系统集成;

  2. Github工作流介绍和EGit集成;

  3. Semihosting设置(可提供standaard I/O能力);

  4. Profiling工具在STM32上的应用;

  5. STM32 + Eclipse的Makefile项目;

  6. C语言单元测试CMocka集成;

  7. C++语言单元测试框架Google C++ Test Framework;

如果精力允许可能还会简单研究一下:

  1. Eclipse Mylyn项目管理集成

  2. Doxygen文档


限于篇幅,Git和Unit Testing的基础概念不会做很详细的介绍,他们本身都值得写一本书,但是会对概念作出简介和给出一些高质量的阅读材料;


Alternative A

本文档采用了推荐的路线,使用Cygwin,并且编译OpenOCD;

不装Cygwin,分别安装GNU Make for Windows, GNU CoreUtils for Windows,OpenOCD 0.8.0二进制发行版也是可以的;

但后续的文档不提供对这种配置的支持保证;不是所有Cygwin里的功能都能找到独立的Windows版发行包;

Alternative B

有一个开源项目叫做GNU ARM Eclipse Plugin,在SourceForget上:

http://sourceforge.net/projects/gnuarmeclipse/

它提供了一个集成的插件,无须Cygwin,自己打包了一个Make+CoreUtils的安装包;

OpenOCD和GNU Toolchain仍然需要独立安装;

它提供足够的安装使用文档;

它提供创建项目的模板,避免了本文档前面编译和链接设置的繁琐过程,可能一些开发者会非常喜欢;

另外值得一提的是类似本文档介绍的EmbSysRegView功能,GNU ARM Eclipse Plugin提供了一个Packs Manager;

PACK是ARM官方支持的对ARM芯片的一种描述方式,使用XML格式和基于标准的描述语言;实际上所有的商用IDE都使用PACKS提供芯片信息;

GNU ARM Eclipse Plugin的Packs Manager可以从官方(ARM, Keil, etc)网站上下载Packs文件,用于代码模板和调试使用;Packs Manager目前处于Beta阶段,可用但有些Bug;

总的来说GNU ARM Eclipse Plugin非常值得推荐;如果遇到EmbSysRegView不支持的MCU型号,我推荐使用这个Plugin;在本文档基础上,参照GNU ARM Eclipse Plugin文档,理解和使用毫无问题。

最后,新年快乐!

⚠️ **GitHub.com Fallback** ⚠️