第四章 STM32CubeIDE的使用
本章将通过第一个工程实验,带领大家熟悉STM32CubeIDE的使用,同时会介绍软件的一些使用技巧,大家平时可以多操作,掌握软件的操作方法,为后面的实验打下基础。
本章将分为如下几个小节:
4.1、STM32CubeIDE第一个工程;
4.2、STM32CubeIDE使用技巧;
4.3、无线调试器和DAP仿真器的使用
4.1 STM32CubeIDE第一个工程
本实验配置好的实验工程已经放到了开发板光盘中,路径为:开发板光盘A-基础资料\1、程序源码\11、M4 CubeIDE裸机驱动例程\CubeIDE_project\1 HAL_LED。
下面,我们新建一个工程,实现LED灯闪烁,通过这个实验来熟悉STM32CubeIDE的基本操作流程,包括新建工程、配置工程、编译工程和下载验证。
4.1.1 创建工程
双击桌面STM32CubeIDE快捷键打开STM32CubeIDE,选择一个目录作为工作区,这里选择E:\STM32CubeIDE_Project作为工作区,注意路径中不要有中文,工作区的路径可以自己定,如果是第一次打开,最好联网,因为后面会在线下载相关固件。
图4.1.1. 1选择工作区
第一次启动STM32CubeIDE以后,会进入如图4.1.1.2界面:
图4.1.1. 3欢迎界面
①是主菜单栏;
②是快捷创建工程或者打开已有工程选项界面;
③是STM32CubeIDE的一些使用说明以及新增功能介绍;
④是一些社交和社区链接,是提供随时与世界各地志同道合的人会面的场所。例如Facebook(脸书)、Youtube(油管)和twitter(推特)等社交链接,ST Home是ST官网,ST Community是ST社区,点击STM32MPU Wiki可以访问Wiki网站。
我们可以点击②处的Start new STM32 project来创建一个新的工程,也可以点击菜单栏的FileàNewàSTM32 Project进行创建。
图4.1.1. 4新建一个ST32工程
如图4.1.1.5,我们进入了STM32CubeMX插件界面:
图4.1.1. 6插件界面
图中的红框部分内容介绍如表4.1.1. 1:
标号 | 选项 | 概要说明 |
① | MCU/MPU Selector | MCU/MPU芯片选择窗口,我们创建项目一般在此窗口进行 |
Board Selector | ST官方的一些开发板选择窗口 | |
Example Selector | 示例程序选择窗口,ST官方开发板的一些现有示例 | |
Cross Selector | 交叉引用工具窗口,在此窗口选择对应的CPU型号,则会弹出一个相同系列的CPU型号的资源对比界面 | |
② | Part Number | 芯片型号选择,输入芯片型号可以筛选出符合条件的芯片型号 |
Core | 内核类型选择,例如Cortex-M0、Cortex-M3、Cortex-M4、Cortex-M33和Arm Cortex-M7单核,还有Cortex-M7和Cortex-M4以及STM32MP1系列对应的Cortex-A7+Cortex-M4双核 | |
Series | STM芯片各个系列,包含ST的各个产品系列,从STM32F0系列到STM32MP1系列,以及STM32WB和STM32WL系列 | |
Line | STM芯片各个产品线,从STM32F0x0产品线到STM32MP151、STM32MP153、STM32MP157产品线,还有其他STM32WBxM模块 | |
Package | ST各个产品线的封装类型,例如目前STM32MP1系类的封装类型有LFBGA354、LFBGA448、TFBGA257和TFBGA361 | |
Other | 其它选项,例如价格范围、IO引脚数范围、Flash和Ram大小范围以及主频范围等,可以手动配置对应的范围来进行筛选 | |
Peripheral | 周边设备选项,例如可选有无ADC,有无FMC,有无TFT LCD等,勾选好以后会列出符合条件的产品型号 | |
③ | 匹配结果列表 | 显示我们根据②处筛选条件的匹配结果 |
④ | Features | 芯片特性介绍,详细介绍芯片有哪些资源 |
Block Diagram | CPU功能框图介绍,以框图的形式列出芯片的整体资源 | |
Docs &Resources | 文档资源浏览,可以下载和在线查看和芯片有关的手册,例如数据手册、参考手册、编程手册等 | |
Datasheet | 数据手册下载区,点击可以下载对应芯片的数据手册 | |
Buy | ST官方产品购买链接 |
表4.1.1. 2插件界面介绍
我们选择①处的MCU/MPU Selector,在②处输入STM32MP157D然后回车,如果输入有误或者输入法是中文,那么,Part Number处方框里会显示红色提示。然后在③处中选择STM32MP157DAAx这个型号的CPU,③处会显示该芯片的主要信息,例如芯片封装为LFBGA448,RAM大小是448 kBytes,总共176个IO,主频是800 MHz。操作如图4.1.1.5所示:
图4.1.1. 7芯片选择
点击Features可以看到STM32MP157D这颗芯片的特性介绍,我们还可以在数据手册下载下区下载此CPU的数据手册,如图4.1.1. 8:
图4.1.1. 9芯片介绍
我们选好芯片的型号以后,点击Nest,在图4.1.1.10界面中设置工程名称为HAL_LED,工程保存路径可以自己选择,此处选择前面工作区的路径,编程语言为C语言,这里目标文件类型我们选择是可执行文件,如果想在其它项目中用到这些静态库,也可以选择生成静态库文件。
图4.1.1. 11工程名字
点击Next,如图4.1.1.10是STM32MP157DAAx使用的HAL库固件版本信息,这里显示使用的是V1.2.0版本,并提示固件包默认存储的位置在C盘的用户路径下(以后我们想拷贝固件包也可以在这个C盘的路径下找到),当然,如果想将固件包保存在其它地方也可以,可以点击下方的Firmware Updater以后再按照提示选择固件包保存的位置,以后STM32CubeIDE会从对应的目录下找这个固件包。这里我们就不改了,选择默认的路径。
此外,Code Generator Options选项默认选择Copy only the necessary library files,即只需要从下载的固件包中拷贝需要的文件到工程中。如果选择Add necessary library files as reference in the toolchain project configuration file的话,表示从下载的固件包从添加必要的库文件,(经过测试,有些头文件是直接引用了固件包里的,不是从固件包里拷贝到工程中的,所以可能会导致不小心修改了固件包里的头文件)。两种方式的差异,我们以后再讲解。(具体说明我们在后面的工程模板分析第8.3小节有讲解。)
图4.1.1. 12库固件版本信息
点击Finish后弹出一个选择打开此透视图的界面(其实就是工程界面),我们选中Yes选择打开,可以勾选Remember my decision选项框,下次就不会再跳出此提示界面。
图4.1.1.13打开透视图界面
系统开始初始化设备配置,并在线下载V1.2.0版本固件库包,此固件包里包含我们实验中要是使用的HAL库,我们是基于HAL库来开发的。下载完以后软件会自动解压固件库压缩包,可以看到图中下载和解压的进度条(如果要在线下载固件包,需要联网),解压完成后,软件自动关联固件包。当然也可以不用在线下载固件包,我们可以手动设置关联已有的固件包,我们后面会讲解怎么关联,这里先讲解在线下载固件包的情况,如图4.1.1. 14所示。
图4.1.1. 15在线下载固件包
固件包下载完成后,弹出OpenSTLinux安装页面,我们选择No,因为我们是在Windows系统开发的,无需安装Linux相关的文件。
图4.1.1. 13 OpenSTLinux安装页面
大家可以打开前面C盘下的STM32Cube的用户路径,stm32cube_fw_mp1_v120.zip 是前面已经下载好的V1.2.0版本的固件包,STM32Cube_FW_MP1_V1.2.0是解压好的固件包,其它文件是我们在浏览的时候自动下载的,在后面的操作中,STM32CubeMX插件生成的初始化代码其实是通过拷贝这个固件包里的文件来生成的:
图4.1.1. 16下载好的固件包
如果我们已有固件包,可以不需要在线下载固件包,秩序设置关联即可,如下图,点击Help-->Manage embedded software packages:
图4.1.1.17管理固件包
然后弹出管理界面,在该窗口找到STMMP1列表选项,勾选1.2.0版本(目前最新版本是1.2.0版本,也可以选择自己需要的版本)。关联STM32Cube固件包有两个方法,如图4.1.1.18所示。
图4.1.1.18下载和关联STM32Cube固件包
如果选择方法二:软件会在线下载好固件包并解压之后,会自动关联,所以不需要多讲什么。如果前面我们已经在线下载了固件包,这步操作就不需要做了。
如果是方法一:点击后,弹出下面的窗口,然后选择光盘中的对应的固件包,注意这里是以压缩包的形式来选择的固件包版本,如下图所示。
图4.1.1.19关联本地STM32Cube固件包
选择好固件包后,点击打开选项,STM32CubeMX会自动将所选的固件包解压到一个目录下,如下是解压过程的进度条:
图4.1.1.20解压中,等待关联
解压完成后,则关联成功:
图4.1.1.21关联成功
关联好固件包后我们就可以开始配置工程了。以后生成的工程文件大多数都是从关联的固件包中拷贝过来的,如工程中用到的启动文件以及HAL库文件等,如果不小心删除了关联的固件包(解压出来的固件包),那么软件将无法正常生成工程,需要我们重新关联。当然,如果想更另一个版本的固件包,可以按照方法一来操作。
固件包关联成功后,在进入工程界面后,此时工程默认打开一个.ioc文件,这个是STM32CubeMX插件的配置界面,我们在此界面中配置外设以及时钟,配置生成的工程文件也都是从关联的固件包拷贝得来的。如果不小心关掉了.ioc文件,我们还可以在左边的项目浏览窗口双击HAL_LED.ioc再次打开STM32CubeMX插件界面。
图4.1.1.22插件界面
我们之前选择将工程默认保存在工作区路径下,进入工程路径可以看到如下工程文件:
图4.1.1.23工程目录
4.1.2 配置工程
1. CubeMX配置窗口介绍
在上面,我们已经进入了STM32CubeMX插件界面,如果之前有接触过STM32CubeMX工具,就会知道通过STM32CubeMX配置,可以生成工程的时钟系统初始化代码以及外设的初始化代码,这是非常方便的。下面我们先简单介绍一下这个界面相关的功能,具体配置方法我们在后面的实操中详细讲解。
如图4.1.2.1,此时默认进入的是Pinout & Configuration配置窗口,我们介绍一下这个窗口的配置项。
图4.1.2. 2配置窗口
如表4.1.2.1所示是配置功能选项介绍:
名称 | 说明 | 介绍 (点击跳转) |
Pinout &Configuration | 引脚配置窗口,包含外设配置、软件包管理、引脚排列视图、引脚操作模式、组件和外设配置状态以及引脚搜索框等 | (1) |
Clock Configuration | 时钟配置窗口,包含了STM32MP157的五个时钟源 | (2) |
Project Manager | 项目管理配置窗口,可以查看项目名称以及保存位置、使用的固件包版本、Linux内核和Uboot版本,可以配置是否生成初始化的.c和.h文件 | (3) |
Tool | 相关工具配置窗口,包含功率测试和DDR测试 | (4) |
表4.1.2. 1 Pinout & Configuration配置窗口配置项列表
下面我们简单介绍窗口的各个配置项。
(1)Pinout &Configuration窗口介绍
外设栏选项,可以按照AàZ的顺序来排列,也可以按照(Categories)分类目录来排列,默认是按照Categories来排列,我们简单介绍一下外设栏有什么配置。
名称 | 说明 |
System Core | 系统核心配置项,一般是必备的配置项,芯片的DDR、GPIO、看门狗、时钟、DMA、系统和中断等重要配置 |
Analog | 模拟量配置项,例如ADC、DAC和参考量 |
Timers | 定时器配置项,包括RTC和TIM1-TIM8,TIM12-TIM17以及低功耗的LPTIM定时器 |
Connectivity | 芯片的通信接口配置项,例如网络ETH、I2C和SPI总线、USB和UART接口等 |
Multimedia | 多媒体功能配置接口,例如音频相关的I2S和SAI,显示相关的GPU、HDMI、LTDC和DSI等 |
Security | 安全项配置项,例如可对随机数RNG、扩展的TrustZone保护控制器(ETZPC)进行设置 |
Computing | 校验类型配置项,例如CRC校验和DFSDM(数字滤波器模块)相关校验。 |
Middleware | 中间件的配置项,例如FREERTOS实时操作系统和OPENAMP系统 |
Trace and Debug | 跟踪和调试相关配置项 |
Power and Thermal | MCU功率模式配置 |
Utilities | 资源管理实用程序 |
表4.1.2. 2 外设栏介绍
图4.1.2. 3外设栏配置图
Software Packs软件包组件选项,可以选择组件安装、删除以及检查是否有新的嵌入式固件包发行版。
图4.1.2. 4软件包
点击Manage Software Packs可以选择对应的固件包,下图显示的是正在使用我们之前在线下载的V1.2.0版本固件包。
图4.1.2. 5固件包管理
Pinout是引脚操作工具项,常用的有:
选项 | 说明 | 快捷键 |
Undo Mode and pinout | 撤销操作 | Ctrl + Z |
Redo Mode and pinout | 恢复撤销 | Ctrl + Y |
Show User Label | 显示用户自定义标签 | |
Disable All Modes | 禁用所有外设和中间件 | Ctrl + D |
Clear Pinouts | 清除所有管脚配置 | Ctrl + P |
Clear Single Mapped Signals | 解除没有关联模式的信号 | Ctrl + M |
Reset used GPIOs | 重置部分或全部使用的GPIO | Alt + G |
表4.1.2. 3 Pinout引脚操作选项列表
图4.1.2. 6引脚操作选项
System view以图形化显示了系统资源的中间件的配置状态。通过选择Category view,然后勾选by Context Execution中的选项,可以列出它们的中间件。
图4.1.2. 7配置图
点击Context Execution view可以列出系统资源的所有中间件。
图4.1.2. 8配置图
(2)Clock Configuration窗口介绍
时钟配置窗口,主要完成STM32MP1的时钟树配置,我们配置好时钟来源以及分频和倍频系数,系统就会自动计算参数来生成所需频率,通过图形化动态配置时钟树,我们就不需要像以前一样再手动去计算时钟了。关于时钟的配置,我们后面会有专门的章节来讲解。
图4.1.2. 9时钟配置窗口
(3)Project Manager窗口介绍
Project Manager窗口是对工程进行配置,可以查看项目名称以及保存的位置、使用的固件包版本、设备树对应的Linux内核和Uboot版本,可以设置堆栈大小(一般不设置),可以配置代码生成的方式,还可以设置选择使用HAL库还是LL库等。
图4.1.2. 10窗口
(4)Tools窗口介绍
此窗口是工具选项,里边有芯片性能测试的工具配置,例如功耗测试、DDR测试等等,此项会在设计产品时会用到。
图4.1.2. 11窗口
STM32CubeMX插件的配置界面选项比较多,我们需要通过后期更多的实验操作来熟悉如何进行配置,这里,我们就不占用过多篇幅来讲解了。下面我们继续往下操作。
2. GPIO /功能引脚配置
我们以开发板的LED0(开发板底板上丝印DS0)配置为例,查看开发板光盘A-基础资料à2、开发板原理图àSTM32MP15x底板(底板原理图),LED0接在PI0上,且当GPIO输出低电平时LED0点亮,当GPIO输出高电平时LED0熄灭。
图4.1.2. 12原理图
在STM32CubeMX插件的引脚搜索框处输入PI0,在引脚排列视图处可以看到一个引脚在闪烁,这个就是我们要找的PI0。
图4.1.2. 13查找PI0
我们点击闪烁的引脚,在弹出的复用功能菜单中可以看到此IO口可以配置成多种功能模式,这里我们选择GPIO_Output,即作为GPIO输出。
图4.1.2. 14将GPIO设置为输出
配置完复用功能,我们还要配置Pin Reserved选项,即引脚保留,也就是将这个引脚给谁用。选中PI0,右键弹出设置项,我们选择Pin ReservedàCortex-M4,这里注意,如果不配置此项,在生成工程代码的时候将不会看到有关这个Pin的初始化代码。
图4.1.2. 15设置Pin给M4用
打开左边的System CoreàGPIO进入GPIO模式配置界面,在下方会列出该GPIO的配置项。下面我们依次来解释这些配置项的含义:
名称 | 说明 |
GPIO mode | 设置引脚输出模式,可选Output Push Pull(推挽)模式或者Output Open Drain(开漏)模式 |
GPIO Pull-up/Pull-down | 设置 引脚是上拉/下拉/没有上下拉 |
Mzximum ouput speed | 设置引脚输出速度,可选为低速(Low)/中速(Medium)/高速(Hign)/快速(Very High)模式 |
User Label | 设置引脚的标签名称 |
表4.1.2. 4 GPIO配置项
关于GPIO模式的配置,我们后面会有详细的章节讲解。本实验我们设置为推挽输出 Output Push Pull、上拉(Pull-up)、速度选择高速 High。选项 User Label 是用来设置初始化的引脚为我们自定义的宏,一般情况我们可以不用设置,这里我们填写为LED0。我们也可以在Pinout view视图里直接设置,选中PI0,右键弹出设置项,输入LED0后按下回车键完成设置,这样的设置效果也是一样的。有兴趣的同学可以在生成初始化代码以后,对比一下此项设置与不设置的差别。
图4.1.2. 16设置标签
按照如上操作,设置后的界面如下图4.1.2. 17:
图4.1.2. 18配置后的界面
3. 配置时钟
时钟是单片机运行的基础,是CPU的脉搏,它决定CPU以及外围设备工作在什么速率,就像是人的心脏一样,有心跳有脉搏才可以做其它事情。STM32MP157的时钟系统比较复杂,我们后期会专门讲解这部分,这里虽然不设置,但是系统采用了默认的时钟。
本节实验中我们操作的是GPIOI,查看参考手册其时钟来源为hclk4,如图4.1.2.19。而GPIOI挂在AHB4上,时钟配置界面中的To AHB1,2,3,4 Peripheral Clocks处是64MHz,如图4.1.2.20。那么GPIOI的时钟频率就是64MHz。关于时钟树我们后面会再详细讲解。
图4.1.2. 19参考手册部分截图
打开时钟配置选项,可以看到MCU采用默认内部时钟HSI(High Speed Internal oscillator),频率 64MHz,如图4.1.2.20所示:
图4.1.2. 20时钟树配置图
4. Project Manager配置
Project Manager的配置很重要,要注意的地方也比较多,下面我们分点来讲解:
(1)Project选项配置
Project选项配置我们一般可以不用管,可以大概浏览一下里边的内容。
①Projcet Settings
此项是工程基础设置,工程名字是HAL_LED,工程位置是E:\STM32CubeIDE_Project。Application Struture应用程序结构中有两种可选,一个是Basic,另一个是Advanced。一般来说,Basic是不包含中间件(RTOS、文件系统、USB设备等)的基础结构,Advanced的话,是结构中会包含中间件。Do not generate the main()就是是否要生成main函数,这项就不勾选了。Toolchain Folder Location是工程路径,Toolchain/IDE是选择生成的工程,这两项也是默认的。
②Linker Settings
此项是堆栈设置,主要就是设置堆和栈的大小,Heap堆默认设置为0x200,Stack栈默认设置为0x400,这两个我们一般也可以不用设置。
③Mcu and Firmware Package
此项是MCU和固件包信息,可以看到我们使用的MCU是STM32MP157DAAx,固件包版本是STM32Cube FW_MP1 V1.2.0。当然这两项也是不能改的,创建工程的时候就已经确定好了。
④OpenSTLinux Settings设置:
STM32MP1通用微处理器系列产品主要是基于Arm Cortex-A7核 和 Arm Cortex-M4核架构,而开源OpenSTLinux主要针对于Cortex-A7。openstlinux-5.4-dunfell-mp1-20-06-24是ST官方发布的Linux系统集成开发包,这个包里整合了Linux内核源码、uboot源码和TF-A源码,可以看出TF-A版本是2.2,内核版本是5.4,U-Boot版本是2020.01。STM32CubeMX可以为OpenSTLinux分发生成部分设备树,在后面我们生成的初始化代码里是可以看到设备树的。
关于Linux系统的知识部分,这里我们先不用理会,正点原子《STM32MP1嵌入式Linux驱动开发指南》对这部分会有一个详细的讲解。
图4.1.2. 21选项配置
(2)Code Generator选项配置
①STM32Cube MCU packages and embedded software packs
此项默认选择Copy only the necessary library files选项(在前面创建工程的时候我们就默认的采用这项),意思就是,工程会从STM32Cube MCU软件包中拷贝需要用到的HAL库文件,没用到的不会拷贝,这样生成的工程就比较精简和小巧。
②Generated files
此项主要是生成的文件配置项,其中:
Generate peripheral initialization as a pair of'.c/.h' files per peripheral 表示让每个外设生成独立的'.c/.h'文件,如果此项不勾选,那么外设相关的初始化代码将会生成在man.c中了,这样的话,如果外设一多,就不好调用了,还会造成main.c文件的臃肿(不过系统时钟初始化的代码默认生成在main.c文件中,勾选或者不勾选此项对系统时钟没有影响)。这里我们要勾选此项,STM32CubeMX插件就会为每个外设生成独立的.c和.h文件,例如本实验是GPIO相关的实验,后期生成的代码中会看到有gpio.h和gpio.c这两个文件。这点大家要注意,如果忘了勾选,可以再次打开.ioc文件来配置此项。
Backup previously generated files when re-generating表示在重新生成初始化代码的时候备份以前生成的文件,系统会在相关目录中生成一个Backup文件夹,并自动将之前源文件拷贝到其中,从而完成备份。本实验,我们选择此项。
Keep User Code when re-generating 表示在重新生成初始化代码时保留用户之前添加的代码,例如我之前在main.c中写了一串代码,我希望这串代码被保留,那么就要勾选此项。这里注意的是,所添加的代码一定要在成对出现的BEGIN和END之间,系统才会保留,在其它位置的话还是会被清除的,我们后面会讲解怎么添加。这里我们不希望每次改了.ioc以后把之前添加的代码清除,所以此项要选择。
Delete previously generated files when not re-generated 表示删除以前生成,但现在没有生成的文件,例如之前的工程中生成了UART.c文件,工程经过修改以后不会再生成UART.c文件,如果不想要之前生成的UART.c文件,就可以勾选此项让系统自动清掉这些文件。这里我们勾选此项。
③HAL Settings
此项涉及到HAL库设置,其中:
Set all free pins as analog (to optimize the power consumption)表示将所有空闲引脚设置为模拟模式,此项是在做产品的时候会用到的,目的是优化功耗。此项我们不选。
Enable Full Assert表示使能所有断言,Assert即断言,可以理解为功能函数中的一些布尔表达式,使用断言做一些假设,可以检查代码中隐藏的bug。在任何时候都可以启用和禁用断言验证,这里我们就不选了。关于断言,我们在后面会有对应的实验做讲解。
④Template Settings
此项是模板选择,Select a template to generate customized code 表示选择一个模板来生成自定义代码,这里我们可以不配置,系统会默认选择。
图4.1.2. 22选项配置
(3)Advanced Settings高级设置
①Driver Selector选项可以配置使用的是HAL库还是LL库,STM32CubeMX插件是以HAL库为基础的,且目前STM32CubeMX插件仅支持HAL库及LL库,我们这里选择默认的HAL库。
②Generated Function Calls(生成的函数调用)中,有如图4.1.2. 23两个可选栏:
Do Not Generate Function Call(不生成函数调用)栏,表示main.c代码不调用对应初始化函数。什么意思呢,比如在IP Instance Name中的GPIO选项,我们在Do Not Generate Function Call下勾选、保存,然后生成的初始化代码里,main.c函数中是没有调用MX_GPIO_Init这个函数的。
图4.1.2. 24配置项
如果GPIO选项没有勾选Do Not Generate Function Call,在保存修改生成初始化代码以后,可以在main.c中看到调用了MX_GPIO_Init函数。这里,有些选项是默认值,不能修改的,即使修改了也没有效果,例如SystemClock_Config这项。如下图,笔者没有勾选GPIO选项的Do Not Generate Function Call,生成的代码中可以看到main.c中调用了MX_GPIO_Init函数,大家可在后面生成代码的时候留意一下此项配置:
图4.1.2. 25中调用MX_GPIO_Init函数
Visibility (Static)栏就是配置初始化代码声明为static,不过有些选项是默认值,不能修改的,例如SystemClock_Config配置不声明为ststic。另外,如果Code Generator选项我们已经配置了生成.c .h独立文件了,那就不会生成static了。
如下图4.1.2.26,默认选择了MX_GPIO_Init和MX_ETZPC_Init两个函数,我们可以不用管,保持默认。
图4.1.2. 27高级设置
4.1.3 生成初始化代码
按下键盘的Ctrl+S组合键保存HAL_LED.ioc文件(修改的文件在未保存的时候,会显示*号,如果已经保存以后*号会消失。),在弹出的窗口中会提示Do you want generate Code?即是否要生成代码,如果勾选了Remember my decision,下次不会再弹出此提示窗口,点击Yes使系统自动产生初始化代码。
图4.1.3. 1选择产生代码
点击Yes选择切换至与与C / C ++透视图相关联的视图,也就是C/C++工程界面。
图4.1.3. 2选择打开工程界面
最后进入工程main.c界面,用过Eclipse的童鞋看到下面这个界面是不是很熟悉?
图4.1.3. 3文件界面
如果不小心点击了Do you want generate Code?界面的No选项,我们也可以在工程的菜单栏ProjectàGenerate Code来手动生成初始化代码。
图4.1.3. 4手动生成初始化代码
4.1.4 控制逻辑代码实现
在前面,我们使用STM32CubeMX插件生成了基于HAL库的GPIO初始化代码,还没有控制LED0点亮和熄灭的逻辑代码,接下来我们在这个工程的基础上去手动完成这部分内容。下面直接基于HAL库添加控制逻辑代码,先不分析工程,在后面章节我们会分析一下整个工程。
我们在main.c函数的while循环函数里添加如下代码,注意代码添加的位置,要添加在成对出现的BEGIN和END的区域之间,这样可以避免下次修改.ioc文件以后再重新生成初始化代码的时,自己额外添加的代码被清空了。
1 /* 设置GPIOI的GPIO_PIN_0为1 */
2 HAL_GPIO_WritePin(GPIOI,GPIO_PIN_0,GPIO_PIN_SET);
3 HAL_Delay(500); /* 延时500ms */
4 /* 设置GPIOI的GPIO_PIN_0为0 */
5 HAL_GPIO_WritePin(GPIOI,GPIO_PIN_0,GPIO_PIN_RESET);
6 HAL_Delay(500); /* 延时500ms */
也可以写成如下这种:
1 设置LED0_Pin为1 */
2 HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_SET);
3 HAL_Delay(500); /* 延时500ms */
4 /* 设置LED0_Pin为0 */
5 HAL_GPIO_WritePin(LED0_GPIO_Port,LED0_Pin,GPIO_PIN_RESET);
6 HAL_Delay(500); /* 延时500ms */
图4.1.3. 5未保存代码的函数界面
添加完代码,在还没有保存前,main.c文件旁边有一个*号,当我们我们按下键盘的Ctrl+S保存工程,或者点击菜单栏的FileàSave来保存修改以后,*号消失,代码保存成功。
4.1.5 编译工程
点击工具栏的小锤子
进行编译,编译过程将会在下方的Consle窗口输出:
图4.1.5. 1编译工程窗口
编译结束后提示Build Finished. 0 errors, 0 warnings,没有报错,这里我们解释一下,编译结果里面的几个数据的意义:
text是代码段,用来存放程序执行代码的一块内存区域。
data(data segment)段,是已经初始化的变量,属于静态内存分配。
bss(block started by symbol)段,是未初始化的全局变量,属于静态内存分配。
dec(decimal的缩写,即十进制数),是text,data和bss的算术和。
hex就是十六进制的意思,其对应的数值是dec的十六进制格式。
以上是在程序没有运行前(程序没有加载到内存前)的3段信息。
程序的大小就是text代码段的大小,filename是生成的文件名字,这里生成了HAL_LED_CM4.elf二进制文件,注意前面的dec和hex不是指HAL_LED_CM4.elf文件的大小,静态区由.bss段和.data段组成,栈、堆、静态区(.bss段、.data段)都是要存放在RAM中。成功编译后,在工程的Binaries下可以看到HAL_LED_CM4.elf文件:
图4.1.5. 2编译生成elf文件
同时,在工程存放路径CM4àDebug下也有HAL_LED_CM4.elf文件:
图4.1.5. 3工程存放目录
在前面编译工程中,也可以点击HAL_LED_CM4(in CM4)à然后右键选择Build Project来编译工程,或者按下Ctrl+B选择编译全部。
图4.1.5. 4编译工程选项
如果不小心关闭了Consle窗口,也可以通过点击WindowsàShow ViewàConsole来打开:
图4.1.5. 5打开Consle窗口
4.1.6 下载验证
注意的是,如果之前将ST-LINK在MDK下仿真后,当将此ST-Link放到STM32CubeIDE下仿真时,需要在STM32CubeIDE上重新更新ST-Link驱动才可以正常使用,否则无法正常仿真。在STM32CubeIDE更新ST-Link驱动,我们下面会讲到。
1. 调试配置
开发板通过JTAG线和转接板接上ST-Link,ST-Link一端接电脑的USB接口。插上配套电源线给开发板供电,拨码开关拨为001(开发板底板有丝印),如图4.1.6. 1所示。
图4.1.6. 1开发板和ST-Link连接图
①、ST LINK通过USB线连接电脑,且仿真器的红灯常亮(如果红灯闪烁,说明没有安装驱动,请参考3.3节安装仿真器驱动)。然后用10P的灰排线连接到开发板的JTAG座上。
②、确保开发板已经正常供电,蓝色电源灯亮起。
③、BOOT设置为001,设置为MCU启动,也就是M4内核启动。BOOT的拨码开关拨上去为1,拨下来为0。
硬件接好以后,开发板上电,点击STM32CubeIDE工具栏的下的Debug Configurations..选项进入调试配置界面。
图4.1.6. 2进入调试配置界面
也可以点击点击RunàDebug Configurations...进入调试配置界面。
图4.1.6. 3进入调试配置界面
进入的Debug Configurations...界面如下图。
图4.1.6. 4调试配置界面
下面,我们新增一个Debug配置项:
双击图4.1.6.5中①处的STM32 Cortex-M C/C++ Application就会自动创建和打开名为HAL_LED_CM4 Debug的配置项。②处会默认选择Debug下编译生成的HAL_LED_CM4.elf文件,如果没有自动选择对应的.elf文件,可以再点击右边选择框搜索对应文件,注意的是,此项不能空,因为我们调试的时候需要将对应的.elf文件下载到目标板卡的SRAM中运行。如果工程没有编译成功,将搜不到.elf文件。
图4.1.6. 6新增一个Debug配置项
或者选中下图4.1.6. 7中①处的STM32 Cortex-M C/C++ Application,然后点击②处的新建,就会自动新建一个名字为HAL_LED_CM4 Debug配置项。
图4.1.6. 7另一种方式新增一个Debug配置项
如果我们不想要这个配置项,也可以选中HAL_LED_CM4 Debug配置项,右键选择将其删除,如图4.1.6. 8:
图4.1.6. 9删除Debug配置项
在这个界面我们先配置一下调试选项,点击调试器,进行如下配置:
Load Mode选择thru JTAG/SWD link(Engineering mode),此项设置,一般是根据实际接线,如果用的是SWD接口,则选中SWD,若是JTAG,则选JTAG,调试探头选择ST-LINK(OpenOCD),我们用ST-Link来进行调试。其它选项保持默认不变,然后点击AplyàDebug开始调试。
图4.1.6. 10配置调试选项
2. 更新ST-LINK固件
第一次在STM32CubeIDE用ST-Link下载程序的话,系统会提示更新ST-LINK固件,点击Yes选择更新:
图4.1.6. 11系统提示更新ST-LINK固件
弹出如下STLinkUpgrade对话框(本实验用的是ST-Link,如果是J-Link的话会提示下载更新J-Link的的驱动):
图4.1.6. 12对话框
我们先拔掉然后再重新连上连接下载器的USB线,接着点击Open in update mode,弹出如下界面(如果不这样操作,点击Open in update mode以后可能提示ST-Link is not in the DFU mode.Please restart it,即要求复位一下下载器。):
图4.1.6. 13驱动更新操作顺序
点击Upgrade更新ST-Link固件,等待更新进度条加载完成就更新成功了。也可以直接在菜单栏的Help处进行更新,点击HelpàST-LINK更新同样也可以进入前面的STLinkUpgrade对话框,后续的操作和前面的一样。
图4.1.6. 14手动更新ST-Link固件
更新完ST-Link固件后,回到工程界面,点击RunàDebug ConfigurationsàDdebug进行调试,如下提示是否切换到Debug透视图,也就是调试的界面,点击Switch进行切换,勾选左边的Remember my decision,下次就不会再弹出此提示。
图4.1.6. 15切换到Debug透视图
3. 程序调试
进入调试界面,我们看到Console打印以下信息:
1 Info : SWD DPIDR 0x6ba02477
2 Info : Deferring arp_examine of STM32MP157DAAx.cm4
3 Info : Use arp_examine command to examine it manually!
4 Info : stlink_dap_op_connect(connect)
5 Info : stlink_dap_op_connect(reconnect)
6 Info : SWD DPIDR 0x6ba02477
7 Info : SWD DPIDR 0x6ba02477
8 Info : STM32MP157DAAx.cm4: hardware has 6 breakpoints, 4 watchpoints
9 Info : STM32MP157DAAx.cm4: external reset detected
10 target halted due to debug-request, current mode: Thread
11 xPSR: 0x01000000 pc: 0x00000008 msp: 0x00000100
调试界面如下,我们介绍界面上常用的一些功能:
图4.1.6. 16调试界面介绍
我们点击继续运行按钮
来运行调试,可以看到开发板底板的LED0在闪烁,点击
即可终止调试并退出调试界面。
图4.1.6. 17调试运行窗口
4.1.7 使用STM32CubeMX导出工程
1. 使用STM32CubeMX打开工程
如果想通过STM32CubeIDE配置工程,然后生成可以给MDK使用的初始化代码的话,可以按照本步骤来操作,注意,我们使用的MDK版本是5.31,如需要安装MDK,可以按照正点原子的《STM32MP1 M4裸机HAL库开发指南》来安装。如果不需要导出工程给MDK使用的,可以跳过这个步骤。
虽然STM32CubeIDE上已经集成了STM32CubeMX插件,但是其生成的初始化代码目前也只能给STM32CubeIDE使用(可能以后ST官方升级软件后可以支持导出MDK工程),如果想将上面配置的工程导出给MDK使用的话,则需独立安装一个STM32CubeMX软件,该软件安装包在开发板光盘A-基础资料\5、开发工具\2、ST官方开发工具\en.stm32cubemx_v6-0-1.zip下,软件安装步骤比较简单,也可以参考正点原子的《STM32MP1 M4裸机HAL库开发指南》第十章部分的操作步骤来安装。
2. 使用STM32CubeMX导出工程
导出工程的步骤请参考正点原子的《STM32MP1 M4裸机HAL库开发指南》第十章10.3.3节的第5小节的来操作,这里就不再画过多的篇幅来讲解了。
至此,使用STM32CubeMX生成MDK工程的步骤已经讲解完了,我们只是以一个最简单的GPIO配置为例子进行介绍,如果想用STM32CubeMX软件来配置其它的外设,如ADC、定时器、DMA等等,可以参考之后的实验配置,我们之后的实验都是在STM32CubeIDE集成的STM32CubeMX插件上完成的。
4.2 STM32CubeIDE使用技巧
在前面,我们通过第一个实验初步了解了STM32CubeIDE的开发步骤,下面我们对这个IDE的开发环境做一个简单的介绍。在以后的学习中,不能纸上谈兵,大家应结合实验多操作,积累更多的实战经验。
4.2.1 STM32CubeIDE窗口介绍
1. 菜单栏
图4.2.1. 1菜单栏
菜单栏功能简单说明如下表:
菜单 | 说明 |
File | 新建文件、工程,关闭文件、工程,导入文件、工程,保存、退出工程等操作 |
Edit | 撤销、复制、粘贴、选择、查找、智能能插入等操作 |
Source | 添加、删除代码块注释,代码左移、右移,代码对齐、缩进,格式化代码等操作 |
Refactor | 提取局部变量、常数、函数,构建工程历史记录 |
Navigate | 打开函数声明,查看函数调用关系,退回上一次浏览的位置等操作 |
Search | 查找功能 |
Project | 编译、清除、配置工程 |
Run | 运行、调试、配置工程,添加、取消断点等操作 |
Windows | 打开、隐藏菜单栏,打开某个窗口,窗口风格设置等操作 |
Help | 帮助窗口 |
表4.2.1. 1菜单栏功能介绍表
上面介绍的菜单栏我们在实践中会经常用到。如果是第一次使用STM32CubeIDE,也可以通过Help菜单获取更多的帮助信息。例如,通过Information Center可以后返回到Home界面,然后可以访问STM32CubeIDE入门指南,了解IDE的使用,访问ST支持和社区。此外,还可以通过Help菜单检查嵌入式软件包更新、管理嵌入式软件包、更新ST-LINK驱动等等。
图4.2.1. 2菜单
2. 工具栏
图4.2.1. 3工具栏
鼠标放到对应工具选项就会有英文提示,根据提示可以知道此工具的用途。其中,窗口切换工具可以进行窗口切换,例如此时在调试界面,如果想返回STM32CubeMX界面,点击MX窗口切换图标即可。
3. Debug窗口
在前面我们已经调试工程,调试窗口如下:
图4.2.1. 4调试窗口
4.2.1 窗口和文本调整
1. 修改函数窗口字体和大小
如果函数窗口显示的代码的字体太小,想调大一些,可以点击代码界面,然后按下键盘的Ctrl+“/”来减小字体,按Ctrl+Shift+“+”可以增大字体。也可以通过点击Windowàpreperencesà进入Preferences界面来修外观。
图4.2.1. 5选择工程属性
进入Preferences界面后,点击GeneralàAppearanceàColors and Fontsà进入Colors and Fonts 配置选项,里边主要是整个窗口的颜色和字体配置,在选项里的BasicàText FrontàEdità选择字体、字形、大小à点击确定à如果效果满意了再点击Apply 或者Apply and Close实现修改,窗口的代码发生变化。如果不想要设置的效果,可以再进入窗口,选择Restore Defaults恢复默认值,再点击Apply and Close使修改生效并退出。
图4.2.1. 6修改窗口字体
2. 修改函数窗口字体颜色和风格
进入Preferences以后,也可以直接在搜索框里输入color,在搜索到的选项里边选择C/C++àEditoràSyntax ColoringàCode,可以修改代码的风格,例如关键字、数字等等字体的颜色和风格,例如要修改代码中的数字显示红色,选择字体加粗,可以在Preview里查看效果,如果效果满意了再点击Apply and Close确认修改,如果要切换回默认设置,可以点击Restore Defaults恢复默认值,再点击Apply and Close确认修改。
图4.2.1. 7修改函数窗口字体颜色和风格
3. 修改调试窗口Console的字体和大小
如果只是想修改调试窗口Console的字体大小,可以修改Colors and Fonts选项里的DebugàConsole font (overrides default:Text Font)。
图4.2.1. 8修改Console的字体和大小
4. 修改调试窗口Console的字体颜色
如果不喜欢调试窗口的字体颜色,可以选择WindowàPreferencesàGeneralàAppearanceàRun/DebugàConsole来进行修改,也可以直接在Preferences里搜索Console找到设置的位置,或者可以在调试窗口Console右键选择Preferences,如图:
图4.2.1. 9选择Console的属性配置
进入Debug Console Settings设置界面,选择Standard Error text color进行修改,如果不喜欢修改的效果,可以点击Restore Defaults恢复默认值。
图4.2.1. 10修改Console字体颜色
5. 修改文字编码风格
如果要修改CM4工程的文字编码风格,可以选中CM4工程,再点击Project àPropertiesà进入CM4工程配置界面,选中Resourceà默认文件编码风格是UTF-8,我们也可以选择其它的编码风格,如图:
图4.2.1. 11修改文字编码风格
6. 修改界面背景颜色
如果要修改代码显示区域的背景颜色,可以在WindowsàPreferences中进行配置:
图4.2.1. 12选中界面属性
进入Preferences配置界面以后,依次选择GeneralàText EditorsàBackground colorà 在Color处选择一个背景颜色,然后点击Apply查看显示效果,如图:
图4.2.1. 13修改界面背景颜色
4.2.2 代码编辑技巧
1. 常用快捷键
先来看看STM32CubeIDE常用的快捷键,大家可以多操作,掌握常用的快捷键。
快捷键 | 快捷键说明 | 快捷键 | 快捷键说明 |
Ctrl+S | 保存 | Ctrl+C | 复制 |
Ctrl+V | 粘贴 | Ctrl+X | 剪切 |
Ctrl+“-” | 快速注释行 | Alt+“-” | 补全代码 |
Shift+Tab | 代码对齐 | Ctrl+D | 删除整行 |
Ctrl+“-” | 缩小字体 | Ctrl+ Shift +“+” | 放大字体 |
Ctrl+鼠标左键 | 跳转到声明处 | Ctrl+L | 跳转至某行 |
F3 | 跳转到声明处 | Shift+Enter | 在下一行新增空行 |
F2 | 展开详细信息 | ||
Ctrl+Tab | 源文件/头文件切换 | Ctrl+E | 快速选择已打开文件 |
Ctrl+Q | 跳回最新编辑点 | Alt+“←”/“→” | 前一个/后一个页面 |
Ctrl+鼠标滚轮 | 快速滑动 | Ctrl+F | 文件内内搜索 |
Ctrl+↑/↓ | 快速滑动 | Ctrl+H | 项目内搜索 |
Ctrl+M | 最大化/默认当前窗口 | Ctrl+O | 显示大纲(方便跳转) |
Ctrl+W | 关闭当前窗口 | Ctrl+B | 编译工程 |
F11 | 启动调试 | Ctrl+F2 | 终止运行 |
F5 | 单步跳入(调试时) | F6 | 单步跳过(调试时) |
F7 | 单步返回(调试时) | F8 | 继续运行(调试时) |
Ctrl+Z | 向后撤回 | Ctrl+Y | 向前撤回 |
表4.2.2. 1常用快捷键
文件中搜索
如果我们要在某个文件中搜索一个字符串,例如要在main.c文件中搜索是否有HAL_Init函数,先打开main.c文件,然后按下快捷键“Ctrl+F”打开搜索框,在搜索框中输入HAL_Init,然后按下回车开始搜索。
图4.2.2. 1在文件中搜索
工程中搜索
我们同样在工程中搜索HAL_Init函数,按下“Ctrl+H”快捷键,弹出的搜索框,如图:
图4.2.2. 2工程搜索界面
Remote Search搜索框可以搜索整个工作区或者电脑的其它盘的文件,即可以选择搜索的范围,不过一般不建议用此项来搜索,可能会报内存错误,也可能会导致软件崩溃。
图4.2.2. 3 Remote Search搜索框
File Search和C/C++ Search这两个是我们常用的搜索项。C/C++ Search是搜索整个工程的C/C++文件,并在右下角列出搜索到的文件。File Search搜索范围是整个工作区的每个文件,在右下角会列出包含HAL_Init字符串的文件名字,例如我们用File Search搜索结果:
图4.2.2. 4 File Search搜索框
当然,也可以直接点击菜单栏的搜索项搜索:
图4.2.2. 5菜单栏搜索
2. 自定义快捷键
在WindowàpreperencesàKeys下可以查看STM32CubeIDE的快捷键,也可以按照如下步骤自定义快捷键,例如自定义编译工程的快捷键,选中Command中的Build Project选项,然后鼠标点击Binding方框,按下键盘的“Shift+B”组合键,在Binding处会显示按下的组合键,点击Apply and Close实现修改,以后编译工程我们直接可以选中要编译的工程,再按下“Shift+B”组合键来实现。
图4.2.2. 6自定义快捷键
3. 快速注释行
选中要注释的代码,按下键盘的“Ctrl+/”(Shift旁边的)即可用“//”注释掉选中的代码,再次按下键盘的“Ctrl+ /”(Shift旁边的)即可取消注释。
图4.2.2. 7快速注释行
4. 代码对齐
选中要调整的代码,按下“Shift+Tab”组合键,代码可以整体往左边移动,按下Tab键,代码可以整体往右边移动。
5. 删除整行
光标放在要删除的行上,按下“Ctrl+D”组合键可以将光标所在的行删除。
6. 查看/跳转函数的声明
选中要查看的函数,按下F2可以显示函数的声明,或者直接按下F3跳转到函数的声明。
图4.2.2. 8查看函数声明
7. 代码格式化
选中WindowàpreperencesàCode StyleàFormatter按照如下配置,在③处选择自己喜欢的代码格式。
图4.2.2. 9代码格式化
8. 手动代码补全
按下“Alt+ /”组合键可以手动触发代码提示功能,当我们编辑代码的时候,可以按下“Alt+ /”组合键,然后从弹出的选项列表里边选择我们想要的函数,双击即可补全。
图4.2.2.10手动代码补全
9. 自动代码补全
以上是需要每次按下“Alt+ /”组合键才可以开启代码提示功能,如果我们想实现系统自动开启代码补全功能的话,需要在线安装一个Eclipse插件,安装完以后还需要配置和导出配置好的插件,因为操作过程复杂也很花时间,这里直接给出插件,大家直接用即可。
注:
此插件目前在STM32CubeIDE 1.4.0版本和STM32CubeIDE 1.3.0版本上测试过可用,其他版本没有做过测试。
先关闭STM32CubeIDE,找到STM32CubeIDE 的安装目录下的D:\ST\STM32CubeIDE_1.4.0\STM32CubeIDE\plugins路径,将org.eclipse.cdt.ui_6.6.0.201909091956.jar插件先重命名了以后作为备份(万一这次操作不成功还可以再替换回去),我们重命名为org.eclipse.cdt.ui_6.6.0.201909091956abc.jar,然后再将开发板光盘A-基础资料\3、软件下的org.eclipse.cdt.ui_6.6.0.201909091956.jar拷贝进去。
图4.2.2. 11 CubeIDE插件目录
拷贝完成,重启STM32CubeIDE,在窗口代码区输入代码,可以看到当我们输入代码的时候,不需要再按下“Alt+ /”组合键来手动触发代码补全功能,系统会自动补全。
10. 比较文件代码
如果要对比两个文件的代码,或者要对比这次修改的文件和上次修改的文件代码差异,可以先选中要对比的其中一个文件,右键后选择Compare With,如果选择Each Other,表示和其它文件进行对比,选中要对比的文件进行对比就可以了。如果选择Local History,则表示和此文件以前的版本进行对比。
图4.2.2. 12选择代码对比项
如下图,选择Local History,则和以前的修改版本进行对比,如下图。
图4.2.2. 13代码比对窗口
11. 查看修改历史
如果要查看某个文件的修改历史记录,可以选中文件,右键,在下拉选项中选中Team查看历史记录。
图4.2.2. 14显示修改历史
找到修改历史以后,可以选中某一项,右键,可以选择打开此历史记录或者和当前的文件对比:
图4.2.2. 15打开修改历史代码
4.2.3 添加自己的代码文件
在复杂的项目中,STM32CubeMX插件生成的工程目录是无法满足我们的需求的,很多时候我们需要在工程中新建一个一个文件夹,每个文件夹放置对应的文件,我们往新增的文件里添加我们的代码,实现控制逻辑,然后再在main.c函数里调用这些文件。这样做的好处是工程结构逻辑清晰,例如当我们的工程有很多的外设控制逻辑时,采用这样的添加方法一目了然,而且也不会因为修改.ioc文件不小心清除掉这些代码。下面我们介绍如何直接在工程界面新建这些文件夹/文件,或者直接在工程中导入已有的文件的文件夹。
1. 新建文件夹
选中CM4工程,右键,选择Properties,如图:
图4.2.3. 1工程属性选项
进入Properties for HAL LED_CM4配置项,依次按照如下操作顺序添加BSP文件夹:选择C/C++GeneralàPaths and SymbolsàIncludesàGNU CàAddà输入文件夹名字BSPàOKàApplyàApply and Close。
图4.2.3. 2工程文件夹配置步骤
在点击Apply以后,可以在Includes选项中多出BSP:
图4.2.3. 3添加好的工程文件夹
按照同样的操作方式再次进入Properties界面,依次按照如下操作顺序对添加的BSP文件夹进行链接,即链接到CM4工程中:选择C/C++GeneralàPaths and SymbolsàSource LocationàLink Folderà输入文件夹名字BSPàOKàApplyàApply and Close。
图4.2.3. 4对添加的文件夹进行关联
在点击Apply的时候,可以在Source Location选项中多出“/ HAL_LED_CM4/BSP”:
图4.2.3. 5显示添加的文件夹路径
回到工程界面,我们看到CM4工程下多出了一个文件夹BSP,注意此BSP文件夹的左上角多了一个“C”字眼的字符,表示这个文件夹和工程关联成功(即前面进行链接后的效果)。如果没有看到BSP文件夹,可以选中CM4工程,右键,选择Refresh更新一下工程。
图4.2.3. 6更新工程目录
2. 新建文件
添加完文件夹,我们在文件夹中添加自己的驱动文件。选中BSP文件夹,右键,选择New创建一个文件,我们先创建头文件,选择Header File(或者选择File选项也是可以的)。
图4.2.3. 7新建头文件
输入Header File的文件名,我们取名为LED.h。
图4.2.3. 8设置头文件名字
按照同样的方法来创建源文件:
图4.2.3. 9新建源文件
我们设置源文件的名字为LED.c:
图4.2.3. 10设置源文件名字
按照上述操作,我们添加了自己的驱动文件,我们在main.c文件中包含新建的LED.h文件,保存修改以后编译工程,在Console中编译成功。
1 /* USER CODE BEGIN Includes */
2 #include "LED.h"
3 /* USER CODE END Includes */
图4.2.3. 11添加头文件路径
3. 另一种新建文件的方法
按照上述添加自己的文件的好处是,在工程中包含文件不用写文件的绝对路径,在编译工程时不会找不到头文件,因为前面已经做好了关联。如果是采用下面的方式添加,在添加文件的时候必须要写出文件的绝对路径,否则编译的时候会提示找不到头文件。下面我们尝试这种操作。
选中CM4工程,选中New,选中Folder,即新建一个文件夹:
图4.2.3. 12在工程中新建文件夹
文件夹的名字命名为UART:
图4.2.3. 13给新建的文件夹命名
选中UART,右键,选择NewàFile来新建一个文件:
图4.2.3. 14在文件夹中新建一个文件
文件名字为UART.h:
图4.2.3. 15设置头文件名字
按照同样的方法新建文件UART.c文件。文件新建完成,我们在main.c中包含UART.h头文件。
1 /* USER CODE BEGIN Includes */
2 #include "LED.h"
3 #include "UART.h"
4 /* USER CODE END Includes */
保存修改后,编译后报错找不到UART.h文件:
图4.2.3. 16编译报错
我们注释掉前面添加的#include "UART.h"这段代码,修改成将UART.h的文件在工程中的绝对路径(这个路径是相对于main.c来说的)添加上去:
1 /* USER CODE BEGIN Includes */
2 #include "LED.h"
3 //#include "UART.h"
4 #include "../../UART/UART.h"
5 /* USER CODE END Includes */
修改保存,进行编译,编译不再报错了:
图4.2.3. 17编译成功
在以后添加文件的操作中,大家多注意这方面的操作,编译报错找不到头文件的话,可以写上文件路径的绝对地址。
4. 导入已有文件
前面是在工程中直接新建文件,如果想在工程中导入已有的文件,可以选中工程中要导入文件的文件夹,然后右键选择Import,例如要在前面新建的BSP文件夹中导入STM32CubeIDE工作目录下的TEST文件夹里的test.c和test.h两个文件(TEST文件夹的文件是笔者自己创建的)。
图4.2.3. 18笔者自己新建的文件
选中工程中BSP文件夹,右键选择Import:
图4.2.3. 19选择导入文件夹
选择GeneralàFile System,点击Next:
图4.2.3. 20选择File System
按照如下步骤选择TEST文件夹的两个文件:
图4.2.3. 21选中要导入的文件
点击Finish添加完成。这种添加的方式相当于拷贝文件,即将文件拷贝到CM4工程的BSP目录下:
图4.2.3. 22文件导入成功
采用这种方式导入头文件,可以直接在main.c函数中直接包含test.h文件,添加完然后保存修改了再编译,可以编译通过。
1 /* USER CODE BEGIN Includes */
2 #include "LED.h"
3 //#include "UART.h"
4 #include "../../UART/UART.h"
5 #include "test.h"
6 /* USER CODE END Includes */
如果添加的文件不想要,可以选中文件,然后右键选中Delete删除:
图4.2.3. 23删除选中的文件
也可以直接选中STM32CubeIDE工作目录下的TEST文件夹里的test.c和test.h两个文件,然后拖拽到工程中,例如直接将上述两个文件拖拽到工程的BSP目录下,然后弹出如下选项,如果选择Copy files的话,效果和前面的拷贝方式一样。
图4.2.3. 24拖拽文件到工程中
如果选择的是Link to files的话,在main.c中#include "test.h"以后编译会报错找不到test.h文件,需要在Paths and Symbols中导入头文件路径才可以编译通过:
图4.2.3. 25导入头文件路径
5. 导入已有文件的文件夹
如果已有一个包含源代码文件的文件夹,我们需要将其导入工程中,例如笔者已有的SYSTEM 文件夹。可以先将文件夹拷贝到CM4工程目录下。
图4.2.3. 26笔者的SYSTEM文件夹
拷贝好SYSTEM 文件夹后,刷新一下工程,可以看到在CM4工程下多了SYSTEM文件夹:
图4.2.3. 27工程中多了一个SYSTEM文件夹
选择CM4工程,右键选中Properties,进入Properties for HAL LED_CM4配置项,依次按照如下操作顺序添加SYSTEM文件夹中的delay文件夹和sys文件夹,这一步主要就是往工程中添加头文件:选择C/C++GeneralàPaths and SymbolsàIncludesàGNU CàAddàFile systemà选中delay文件夹à点击Apply。
图4.2.3. 28在工程中添加delay文件夹
接着按照同样的操作方法添加sysy文件夹:
图4.2.3. 29在工程中添加sysy文件夹
添加完成后,在Includes中看到前面添加的路径:
图4.2.3. 30已添加的文件夹路径
再次进入Properties for HAL LED_CM4配置项,依次按照如下操作顺序添加SYSTEM文件夹,这一步主要就是将SYSTEM文件夹和工程关联起来:选择C/C++GeneralàPaths and SymbolsàSource LocationàAdd Folderà选择SYSTEM文件夹àOKàApply and Close。
图4.2.3. 31文件夹和工程关联
回到工程窗口,我们发现SYSTEM文件夹左上角多了一个C符号,打开工程的Includes目录,发现多出了HAL_LED_CM4/SYSTEM/delay和HAL_LED_CM4/SYSTEM/sys两个路径,我们在main.c函数中包含delay.h和sys.h两个头文件:
1 /* USER CODE BEGIN Includes */
2 #include "delay.h"
3 #include "sys.h"
4 /* USER CODE END Includes */
修改完main.c代码,保存,并编译,如下图编译没有报错,添加成功。
图4.2.3. 32编译成功
4.2.4 编译生成BIN或HEX文件
如何让编译生成BIN或HEX文件?
默认情况下STM32CubeIDE编译后生成的是ELF文件,如果想要生成HEX或BIN文件的话需要按照如下配置。选中工程,然后右键选择Properties,或者点击菜单栏的FileàPropertiesàC/C++ BuildàSettingsàMCU Post build outputsà勾选Convert to binary file(-O binary)和Convert to Intel Hex file(-O ihex)。
图4.2.4 1设置编译生成BIN文件
配置好后,保存配置,重新编译工程,在CM4工程的Debug目录下生成bin文件、elf文件和hex文件。
图4.2.4 2编译生成的文件
4.2.5 调试技巧
下面,我们讲解一些基本的调试技巧,掌握这些调试技巧可以帮助我们进行快速地开发,在后面的实验中,我们还会结合实验来掌握一些调试的方法。
1. 启用断言
在项目开发阶段,我们可能会借助断言来判断某个参数是否符合要求,那么就会开启断言进行调试。什么是断言?关于断言我们后面的固件库分析和实验中会讲解到,下面我们先讲解怎么开启断言。
打开.ioc文件进入STM32CubeMX插件配置界面,在Project Manager配置界面的Code Generator处配置HAL库,勾选Enable Full Assert开启断言,按下“Ctrl+S”组合键保存修改,重新编译工程。
图4.2.5. 1开启断言
也可以通过手动添加宏定义USE_FULL_ASSERT的方式开启断言,至于为什么添加这个宏可以开启断言,涉及HAL库的stm32mp1xx_hal_conf.h文件分析,我们在后面的7.3.1小节会介绍到。
2. 添加宏定义
如果工程中要定义某一个宏,可以直接在STM32CubeIDE上添加。选中CM4工程àProjectàProperties进入工程属性设置:
图4.2.5. 2工程属性设置
在CM4工程属性设置界面,点击C/C++ GeneralàPaths and SymbolsàSymbolsàAddà添加自己要定义的宏,这里为了演示,填写FOR_TESTà点击OK确定添加àApply。
图4.2.5. 3定义一个宏
添加完成后,在Symbol处可以看到已经添加的宏定义,添加完宏定义以后,记得重新编译工程。
图4.2.5. 4已经添加的宏
3. Debug模式和Release模式切换
STM32CubeIDE默认采用Debug模式。
图4.2.5. 5默认采用Debug模式
Debug模式,称为调试版本,编译结果通常包含调试信息,而且不做任何优化,只有Debug模式下才能设置断点、进行单步调试。另一个是Release模式,Release 称为发布版本,它往往是进行了各种优化,使得程序在代码大小和运行速度上都是最优的,以便用户很好地使用,Release模式下,在线点击调试的时候,程序直接运行,但不能单步调试。如果要改为Release模式,可以按照如下步骤进行配置:
点击Manage Configurations处,在弹出的配置窗口选中Release,然后选择Set Active,表示默认激活点击Release模式,然后点击OK确认,修改完配置,记得点击Apply and Close使能配置:
图4.2.5. 6选择Release模式
配置完成后,再次进入M4工程的Properties配置界面,看到之前的DEBUG宏定义不见了:
图4.2.5. 7模式配置成功
配置完成后,重新编译工程。不管是Debug模式还是Release模式,在工程的目录下会单独生成一个文件夹来存放编译生成的工程文件,在编译之后,可以对比一下生成文件的大小,可见Release模式下编译生成的文件比Debug模式下编译生成的文件还要小:
图4.2.5. 8模式和Release模式编译生成的文件对比
以后,如果要编译工程,可以在小锤子
下面选择是编译Debug版本还是Release版本
图4.2.5. 9编译版本选择
或者可以直接在Project菜单栏选择设置激活Debug或者Release版本:
图4.2.5. 10在Project中选择编译的版本
同样的,如果要调试,也可以选择Debug版本或者Release版本,要注意的是,如果要进行单步调试的话,一定要选择Debug版本。
图4.2.5. 11调试版本选择
4. 关闭工程
如果STM32CubeIDE中打开了多个工程,可能会干扰我们对某个工程的操作,那么我们可以将其他不用的工程关闭。如下图,笔者打开了FOR_TEST工程和HAL_LED工程,如果要关闭FOR_TEST工程,先选择FOR_TEST工程,然后点击右键,再点击Close Project将其关闭,然后按照此方法依次把CA7和CM4工程给关闭:
图4.2.5. 12关闭工程
关闭后的效果如图:
图4.2.5. 13已经关闭工程
5. 打开观察窗口
STM32CubeIDE上集成了非常多的窗口,通过这些窗口我们可以获取一些信息。特别是在在Debug的时候,可以选择打开这些窗口:
图4.2.5. 14时可以打开的观察窗口
下面只是列举一部分常用的窗口,在后期,我们在实验调试中还会遇见一些窗口,结合实验来调试更容易理解。
(1)查看函数调用关系
如果想查看一个文件中有哪些函数,可以在项目浏览器那里打开此文件,如下图查看main.c文件中有哪些文件和函数:
图4.2.5. 15查看文件调用的函数
如果想看一个函数调用了那些函数,可以先选中此函数,然后右键,选中打开Open Call Hierarchy:
图4.2.5. 16查看main函数调用关系
如下图,打开了Open Call Hierarchy窗口以后,可以查看各个函数的具体调用关系,点开>括号还可以层层查看函数的调用层级关系。
图4.2.5. 17查看函数调用层级关系
(2)查看头文件调用关系
如果想查看一个文件调用了哪些头文件,以及这些头文件的调用关系,可以先选中此文件,右键,然后选择Show InàInclude Browser打开包含关系列表:
图4.2.5. 18选择头文件包含列表
如下图,可以查看头文件的调用关系:
图4.2.5. 19显示函数包含关系列表
(3)查找工程中某个文件
查找工程中某个文件,可以在项目离别里查询,如果工程中文件很多,也可以直接通过通 配符*来搜索。打开菜单栏Navigateàopen Resourceà:
图4.2.5. 20打开资源文件搜索窗口
例如搜索gpio相关的文件,可以在搜索框中输入*gpio,这样就会列出gpio相关的函数。
图4.2.5. 21查找文件
(4)打开Build Analyzer窗口
Build Analyzer窗口可以查看内存信息。点击菜单栏的WindowàShow ViewàBuild Analyzer可以打开Build Analyzer窗口。
图4.2.5. 22打开Build Analyzer窗口
在Memory Regions可以查看内存的分配区域,例如下图,内存地址0x00000000~0x00000298是中断向量表地址范围,m_text代码段内存地址范围是0x10000000~0x10020000,m_data数据段的范围是0x10020000~0x10040000,这些地址范围是可以修改的,在后面我们分析链接脚本的时候会对其进行讲解。
图4.2.5. 23列表
Memory Details下是具体的内存映射关系,其中VMA表示虚拟地址,一般是RAM位置,LMA一般是加载地址,因为CM4内核没有可用的Flash,所以LMA地址表示ROM位置:
图4.2.5. 24列表
(5)Memory 窗口
Memory 窗口和上面的Build Analyzer窗口的内存映射关系窗口不一样,Memory 窗口可以查看具体的某个地址的数据,此项是在调试的时候才可以用。例如我们进入Debug调试模式,然后点击菜单栏的WindowàShow Viewà:
图4.2.5. 25选择打开Memory 窗口
在Debug处打开的Memory窗口如下:
图4.2.5. 26已经打开的Memory 窗口
下面我们要观察某一段内存的数据,可以点击+号图标,然后再弹出的窗口写入地址,例如我写入前面提到的m_data数据段的地址0x10020000,然后点击OK:
图4.2.5. 27添加要观察的地址
在Memory窗口会列出从地址0x10020000开始以后的地址数据,是16进制的数据,且每4位为一个单元。
图4.2.5. 28每4位为一个单元显示
如果觉得这样看着不是很方便,也可以将4位为一个单元改成每1位为一个单元,先将鼠标放在旁边的空白处,然后右键点击,选择Format:
图4.2.5. 29每1位为一个单元显示
然后可以选择进制数,可以是8进制、16进制、2进制或者其他,可以选择多少位来显示,这里我们选择还是16进制,以1位单元来显示:
图4.2.5. 30配置显示方式
效果如图:
图4.2.5. 31每1位为一个单元显示
(6)Static Stack Analyzer窗口
Static Stack Analyzer是静态堆栈分析窗口,如果有必要,也可以打开此窗口进行分析。点击菜单栏WindowàShow ViewàStatic Stack Analyzer打开静态堆栈分析窗口:
图4.2.5. 32选择打开Static Stack Analyzer窗口
图4.2.5. 33列表
图4.2.5. 34列表
6. 单步调试
为了方便讲解调试部分内容,我们在main.c文件中添加如下代码,然后重新编译工程:
static uint32_t Freq= 0;
Freq = HAL_RCC_GetSystemCoreClockFreq();
这里定义一个静态局部变量Freq,初始值为0。HAL_RCC_GetSystemCoreClockFreq是HAL库的一个函数,表示获取系统时钟。这里表示将系统时钟的值赋值给Freq变量,然后我们通过后面的调试来观察此变量。(关于HAL_RCC_GetSystemCoreClockFreq函数我们后面会有专门的章节进行讲解。)
图4.2.5. 35添加代码
编译不报错以后,开发板通过转接板和ST-Link相连,ST-Link通过USB线接在电脑USB口上,具体操作请看第4.1.6小节。连接好硬件以后,打开开发板的开关,点击Debug Configurations..进入调试配置界面(如果之前在工程中已经配置过调试选项,可以直接点击
进行调试):
图4.2.5. 36配置调试
进入调试配置项以后,按照第4.1.6小节操作,最后进入Dubg界面。进入Debug界面以后,箭头默认指向HAL_Init();函数处,表示程序从此处开始执行,而且可以看到此时的Freq变量的值为0:
图4.2.5. 37进入Debug界面
按下F6键或者点击Step Over
符号(表示执行过去),箭头会跟着移动,继续点击Step Ove符号,待箭头到了代码第101行以后,发现Freq变量的值变成了64000000,此时开发板底板的DS0灯亮了。
图4.2.5. 38观察变量Freq的变化
再点一下Step Ove符号,箭头到了代码第102行以后,开发板底板的DS0灯灭了。继续点击Step Ove符号,箭头到了第104行代码以后DS0灭了,再继续点击,箭头到了第105行后DS0又亮了,如果此时继续点击Step Ove,箭头就又跳到代码第101行处,如果继续点击Step Ove,箭头在whlie函数里循环。
图4.2.5. 39执行Step Ove
如果在代码第101行,点击Step Into
符号,或者按下快捷键F5,表示执行进去,也就是进入HAL_GPIO_WritePin函数里边运行。
图4.2.5. 40执行Step Into
如果要跳出HAL_GPIO_WritePin函数,则按下快捷键F7,或者点击
Step Return返回符号。
7. 设置断点
调试过程中也可以通过设置断点来观察程序运行情况。在代码窗口行号的旁边,双击即可调价一个断点,再双击即可去掉一个断点。例如在MX_GPIO_Init();函数行号旁边双击,即可添加一个断点:
图4.2.5. 41添加一个断点
点击运行,程序运行到断点处:
图4.2.5. 42程序执行到断点处
当然,也可以在STM32CubeIDE中设置条件断点,即符合某个条件时才中断断点,不过要编写条件代码,这里就不列举了。
8. 使用J-Link进行调试
在前面我们使用ST官方的ST-Link工具进行了仿真,如果要用J-Link的朋友操作方法会有些不同,用J-Link进行仿真的时候需要选择器件,注意,我们要选Cortex-M4。
如下图,开发板先不要上电,拨码开关拨成001。J-Link的JTAG接口连接转接板,转接板通过J-TAG线和开发板相连,J-Link的另一端通过USB线接到电脑的USB接口:
图4.2.5. 43连接图
编译好工程、硬件接好以后,开发板上电,点击STM32CubeIDE工具栏的Debug图标
下的Debug Configurations..选项进入调试配置界面。
图4.2.5. 44进入调试配置界面
也可以点击点击RunàDebug Configurations...进入调试配置界面。
图4.2.5. 45进入调试配置界面
进入的Debug Configurations...界面如下图。
图4.2.5. 46调试配置界面
下面,我们新增一个Debug配置项(如果已经新增过配置项,可直接双击配置项来打开):
双击图中①处的STM32 Cortex-M C/C++ Application就会自动创建和打开名为HAL_LED_CM4 Debug的配置项。②处会默认选择Debug下编译生成的HAL_LED_CM4.elf文件,如果没有自动选择对应的.elf文件,可以再点击右边选择框搜索对应文件,注意的是,此项不能空,因为我们调试的时候需要将对应的.elf文件下载到目标板卡的SRAM中运行。如果工程没有编译成功,将搜不到.elf文件。
图4.2.5. 47新增一个Debug配置项
或者选中下图4.1.6. 7中①处的STM32 Cortex-M C/C++ Application,然后点击②处的新建,就会自动新建一个名字为HAL_LED_CM4 Debug配置项。
图4.2.5. 48另一种方式新增一个Debug配置项
如果我们不想要这个配置项,也可以选中HAL_LED_CM4 Debug配置项,右键选择将其删除,如图:
图4.2.5. 49删除Debug配置项
在这个界面我们先配置一下调试选项,点击调试器,按步骤进行如下配置:
Load Mode选择thru JTAG/SWD link(Engineering mode),调试探头选择SEGGER J-LINK,接口选择SWD,其它选项保持默认不变,然后点击AplyàDebug开始调试。
图4.2.5. 50配置调试选项
点击Debug以后弹出如下窗口,提示选择器件,我们点击OK:
图4.2.5. 51选择调试器件
先选择Cortex-M4,然后点击OK确定,然后进入了调试界面了,可以进行调试,调试步骤和前面的讲到的相同。
图4.2.5. 52选择Cortex-M4
4.3 无线调试器和DAP仿真器的使用
由于M4没有可以用的Flash,所以一般在M4代码调试阶段我们会采用在线仿真的方式,即将代码下载到M4可用的SRAM中,对STM32MP1的M4进行仿真,我们可以使用ST-Link、Jlink、正点原子的DAP仿真器或者无线调试器来进行仿真调试。
本节主要讲解如何使用正点原子的DAP仿真器以及无线调试器在STM32MP1上进行仿真,正点原子的DAP仿真器和无线调试器分为高速版和普速版,关于以上仿真器的用户手册等相关资料,大家可以到正点原子资料下载中心进行下载。注意,使用仿真器前一定要先认真阅读用户手册!用户手册中讲解了仿真器的基本使用方法。
资料链接:http://www.openedv.com/docs/tool/dap/index.html
4.3.1仿真器和调试器资料下载
4.3.1 DAP仿真器的使用
1. 开发板连接
图4.3.1.1开发板连接
正常的情况是:开发板上电以后,开发板核心板和底板的电源指示灯(蓝灯)正常亮,DAP仿真器的灯显示为蓝色,如果DAP仿真器的灯始终是红色或者不亮的话,说明仿真器没正常连接,请检查USB线是否已经接好,可以重新接好USB线。请注意,如果此前自己更新过DAP仿真器的固件的话,如果没有配置好,也可能会导致DAP仿真器的灯不亮,那么请参考正点原子的DAP用户使用手册进行操作。
2. 下载OpenOCD
进入网址https://gnutoolchains.com/arm-eabi/openocd/下下载OpenOCD,如下,我们下载当前最新版本:
图4.3.1.2下载OpenOCD
如下图,笔者下载并解压到了桌面,解压后进入openocd-20210625\OpenOCD-20210625-0.11.0\bin下(即bin目录下):
图4.3.1.3解压OpenOCD
在bin目录的页面,按下键盘的Shift键,然后打开Powershell,我们需要在Powershell下执行指令以启动OpenOCD服务:
图4.3.1.4打开Powershell
在openocd-20210625\OpenOCD-20210625-0.11.0\share\openocd\scripts\target下有stm32mp15x.cfg文件,说明OpenOCD是支持STM32MP1系列芯片的,我们在Powershell下输入以下指令后,按下回车键以执行该指令:
./openocd -f interface/cmsis-dap.cfg -f target/stm32mp15x.cfg
执行以下指令后,如下图,最后提示Cortex-CM4内核使用端口3334来进行仿真,而3333对应的是Cortex-A7内核,所以后面我们在CubeIDE下进行配置的时候,端口一定要写3334,请不要写错哦,否则无法进行仿真:
图4.3.1.5启动OpenOCD服务端口
成功启动OpenOCD以后,上面的Powershell界面不要关闭,请保持,如果关闭Powershell的话,则不能进行仿真,必须重新进入Powershell以后,再次执行上面的指令以重启服务以后才可以进行下一步的仿真操作。
如下图,出现如下的界面,提示Error且没有出现端口,说明OpenOCD服务未开启成功,请检查仿真器是否连接好了、开发板拨码开关是否设置正确了、电源是否已经开启等。
图4.3.1.6开启OpenOCD服务
3. STM32CubeIDE配置
本节实验使用了后面第十一章蜂鸣器实验为例子来进行仿真(实验前请打开此实验的代码,先成功编译,再进行以下操作),当然,大家可以直接使用第四章 的实验来进行仿真,都是可以的。
成功编译工程后,按照如下步骤进入工程的调试配置界面:
图4.3.1.7 进入Debug配置界面
进入工程调试配置界面后,选择要用到的编译生成的文件,如下:
图4.3.1.8 选择仿真的程序
进入调试器配置页面,按照如下配置,请注意,将端口号3333改为3334(端口号一定要修改正确):
图4.3.1.9选择OpenOCD服务端口
如果有弹出如下界面,请选择Switch:
图4.3.1.10选择打开调试界面
点击Debug后,进入仿真页面,点击运行按钮
即可运行仿真:
图4.3.1.11 进入Debug调试界面
4.3.2 无线调试器的使用
无线调试器的使用步骤大部分和DAP仿真器的使用类似,只不过硬件连接方式不一样。
开发板连接
如下图,无线调试器的发送端和接收端通过USB线和电脑进行通信,无线调试器的接收端通过JTAG接口和开发板连接,两个调试器的灯显示蓝色,说明连接正常。如调试器的灯是红色的或者灯不亮,说明连接不正常,请检查USB线是否接好,可以重新接好试试。请注意,如果此前自己更新过DAP仿真器的固件的话,如果没有配置好,也可能会导致DAP仿真器的灯不亮,那么请参考正点原子的DAP用户使用手册进行操作。
图4.3.2.1 无线调试器链接
仿真前配置
连接好硬件以后,剩下的操作和前面的4.3.1小节一样。