历史上的今天
返回首页

历史上的今天

今天是:2024年08月27日(星期二)

正在发生

2019年08月27日 | 【STM32H7教程】第8章 STM32H7的终极调试组件Event Recorder

2019-08-27 来源:eefocus

8.1   重要提示(必读)

只要是MDK支持的调试下载器,基本都支持Event Recorder,本教程测试了JLINK,STLINK和CMSIS-DAP。


务必使用MDK5.25及其以上版本。


使用ARM_Compiler 软件包V1.4.0及其以上版本。详情看此贴:http://forum.armfly.com/forum.php?mod=viewthread&tid=87175 。


CMSIS软件包 要是使用V5.3.0及其以上版本,详情本教程8.3小节末尾的说明。


如果大家的MDK5.X应用不是很熟练的话,可以看论坛网友翻译的MDK5.X入门手册:http://forum.armfly.com/forum.php?mod=viewthread&tid=31288。如果觉得看手册上手慢的话,可以直接看KEIL官方做的MDK入门系列视频,带中文字幕:http://forum.armfly.com/forum.php?mod=viewthread&tid=82667 。


为了实现Event Recorder组件的最高性能,最好将下载器的时钟速度设置到所支持的最大值,另外,根据需要加大EventRecorderConf.h文件中的缓冲大小,默认可以缓冲64个消息(动态更新的FIFO空间)。


此调试组件不需要用到SWO引脚,使用标准的下载接口即可。以我们的开发板为例,用到VCC,GND,SWDIO,SWCLK和NRST。大家使用三线JLINK-OB也是没问题的,仅需用到GND,SWDIO和SWCLK。


8.2   Event Recorder简介


前面的专题教程中为大家讲解了使用SEGGER的RTT功能来替代串口打印,比较方便。只是这种方法限制用户必须使用JLINK才可以。而使用Event Recorder的话,无此限制,各种LINK通吃。只要是MDK支持的即可。


Event Recorder是MDK在5.22版本的时增加的功能,到了5.25版本后,这个功能就更加完善了,增加了时间测量和功耗测量的功能。


此调试组件不需要用到SWO引脚,使用标准的下载接口即可。以我们的开发板为例,用到VCC,GND,SWDIO,SWCLK和NRST。大家使用三线JLINK-OB也是没问题的,仅需用到GND,SWDIO和SWCLK。


JTAG接口和SWD接口区别


下图分别是20pin的标准JTAG引脚和SWD( Serial Wire Debug)引脚,一般SWD接口仅需要Vref,SWDIO,SWCLK,RESET和GND五个引脚即可,SWO(Serial Wire Output)引脚是可选的。有了SWO引脚才可以实现数据从芯片到电脑端的数据发送。

词条 SWV(Serial Wire Viewer)


SWV是由仪器化跟踪宏单元ITM(Instrumentation Trace Macrocell)和SWO构成的。SWV实现了一种从MCU内部获取信息的低成本方案,SWO接口支持输出两种格式的跟踪数据,但是任意时刻只能使用一种。两种格式的数据编码分别是UART(串行)和Manchester(曼彻斯特)。当前JLINK仅支持UART编码,SWO引脚可以根据不同的信息发送不同的数据包。当前M3/M4可以通过SWO引脚输出以下三种信息:


ITM支持printf函数的debug调用(工程需要做一下接口重定向即可)。ITM有32个通道,如果使用MDK的话,通道0用于输出调试字符或者实现printf函数,通道31用于Event Viewer,这就是为什么实现Event Viewer需要配置SWV的原因。


数据观察点和跟踪DWT(Data Watchpoint and Trace)可用于变量的实时监测和PC程序计数器采样。


ITM 还附带了一个时间戳的功能:当一个新的跟踪数据包进入了ITM的FIFO 时,ITM 就会把一个差分的时间戳数据包插入到跟踪数据流中。跟踪捕获设备在得到了这些时间戳后,就可以找出各跟踪数据之间的时间相关信息。另外,在时间戳计数器溢出时也会发送时间戳数据包。


8.2.1 Event Recorder的特色

Event Recorder的特色主要有以下几点:


提升应用程序动态执行期间的检测能力。


支持的事件类型滤除机制,比如运行错误、API调用、内部操作和操作信息的区分。

可以在任务中、RTOS内核中和中断服务程序中任意调用。


对于带ITM功能的Cortex-M3/M4/M7/M33内核芯片,执行记录期间,全程无需开关中断操作。对于不带ITM功能的Cortex-M0/M0+/M23,是需要开关中断的。

支持printf重定向。


各种link通吃,支持SWD接口或者JTAG接口方式的JLINK、STLINK、ULINK和CMSIS-DAP。


对于带DWT时钟周期计数器功能的Cortex-M3/M4/M7/M33内核芯片,创建时间戳时,可以有效降低系统负担,无需专用定时器来实现。


Event Recorder执行时间具有时间确定性,即执行的时间是确定的,而且执行速度超快,因此,实际产品中的代码依然可以带有这部分,无需创建debug和release两种版本。

RTX5及其所有中间件都支持Event Recorder调试。


8.2.2  Event Recorder是如何工作的

首先来看下面这张图:


在截图的左下角有个Memory内存区,在这个内存区里面有一个缓冲Event Buffer,其实就是一个大数组。MDK通过访问这个数组实现消息的图形化展示。为了正确的图形化展示,数组缓冲里面的数据就得有一定的数据格式。而这个数据格式就是通过左侧截图里面的Event Recorder和Event Filter来实现的。Event Recorder的API实现数据记录和整理,Event Filter的API实现数据的筛选,从而可以选择哪些数据可以在MDK的Event Recorder调试组件里面展示出来。


这就是Event Recorder的基本工作流程。


8.2.3  Event Statistics时间测量功能

Event Statistics提供的时间测量功能简单易用,在测试代码前后加上测量函数即可:


在本章教程程的8.6小节为大家详细进行了讲解。通过这个时间测量功能,用户可以方便测试代码的执行时间,从而根据需要,进行合理的优化,提高代码执行效率。


8.2.4  Event Statistics功耗测量功能

Event Statistics提供的功耗测量功能,当前只有KEIL的ULINKplus支持此功能,由于ULINKplus价格不便宜,一套5000多,大家作为了解即可,实际效果如下:

8.2.5  Event Recorder的实现原理

每条Event Recorder消息是由16字节的数据组成,32位的ID,32位的时间戳,两个32位的数据,共计16个字节。其中32位ID最重要,格式如下: 

Level指定消息分类,主要用于消息筛选: 

Component number指定事件消息所属的软件组件,也可用于过滤: 

看了下Event Recorder的源码,每条消息大体是一样的:


typedef struct {

  uint32_t ts;                  // Timestamp (32-bit, Toggle bit instead of MSB)

  uint32_t val1;                // Value 1   (32-bit, Toggle bit instead of MSB)

  uint32_t val2;                // Value 2   (32-bit, Toggle bit instead of MSB)

  uint32_t info;                // Record Information

                                //  [ 7.. 0]: Message ID (8-bit)

                                //  [15.. 8]: Component ID (8-bit)

                                //  [18..16]: Data Length (1..8) / Event Context

                                //      [19]: IRQ Flag

                                //  [23..20]: Sequence Number

                                //      [24]: First Record

                                //      [25]: Last Record

                                //      [26]: Locked Record

                                //      [27]: Valid Record

                                //      [28]: Timestamp MSB

                                //      [29]: Value 1 MSB

                                //      [30]: Value 2 MSB

                                //      [31]: Toggle bit

} EventRecord_t;

其中参数成员info最重要,也就是前面说的32位ID,这里的说明与前面的说明稍有不同。这里是经过处理后,实际存储到Event Recorder缓冲里面的数据。


对于Event Recorder,大家了解了这些知识点基本就够用了。


8.3   创建工程模板和注意事项

Event Recorder工程的创建比较简单,这里分步为大家做个介绍。


  第1步:准备好一个使用MDK5.25或以上版本创建的工程模板。


  第2步:安装ARM_Compiler V1.4.0或以上版本(如果有最新版,直接安装最新的),详情见帖子:


http://forum.armfly.com/forum.php?mod=viewthread&tid=87175 。


  第3步:打开MDK5.25或以上版本创建的RTE环境。


  第4步:通过RTE环境,为工程添加Event Recorder功能。


  第5步:为了实现printf重定向,我们需要将STDOUT的输出方式改为Event Recorder,即选项里面的EVR。


  第6步:打开通过RTE环境为工程添加的文件EventRecorderConf.h,配置如下:


这里主要设置方框里面的两个参数。


Number of Records:表示Event Recorder缓冲可以记录的消息条数。


Time Stamp Source:表示时间戳来源,有如下四种可以选择,我们这里使用DWT时钟周期计数器。


由于选择的是DWT,因此EventRecorderCong.h文件中的Systick Configuration配置就不用管了。


==========================


通过上面的6步就完成了Event Recorder功能的添加,效果如下:


添加完成后,还有非常重要的两点要特别注意:


  第1点:一定要使用当前最新的CMSIS软件包,当前是V5.4.0(随着时间的推移,如果升级了新版本,直接使用新版即可)。大家可以从这里下载:http://www.keil.com/dd2/pack/ 。

下载并导入到MDK后,需要大家更新自己现有工程CMSIS文件里面的头文件,可以直接将CMSIS文件夹中Include文件里面的所有文件全部删掉,替换为MDK安装目录如下路径里面的所有头文件:


ARMPACKARMCMSIS5.4.0CMSISInclude。保证头文件都是最新的5.4.0版本。


 第2点:由于使能了printf重定向,大家的工程里面一定不要再做重定向了,比如fpuc,fgetc。另外当前选择了微库MicroLib:

注意这两点后,就可以使用Event Recorder的功能了。


8.4   Event Recorder事件记录的实现

Event Recorder的使用也比较省事,这里也分步为大家进行说明:


  第1步:初始化,仅需添加如下两行代码即可。


/* 初始化EventRecorder并开启 */ 

EventRecorderInitialize(EventRecordAll, 1U); 

EventRecorderStart();

  第2步:调用Event Recorder的API就可以使用了,主要有以下三个API:


EventRecord2:可以发送两个32位数据。


EventRecord4:可以发送四个32位数据。


EventRecordData:可以发送字符串。


显然这三个函数没有printf使用方便,所以对于这三个函数,大家做个简单的了解即可。教程配套例子里面有调用到这三个函数,可以操作熟悉下。这三个API的说明是在对应的help文档中,即MDK安装目录路径:/ARM/PACK/Keil/ARM_Compiler/1.6.0/Doc/General/html/index.html。

  第3步:进入调试状态,选上周期更新:


点击全速运行:


然后将Event Recorder调试组件展示出来:


效果如下:


另外,这里有个知识点需要大家了解下,如果程序里面也调用了Event Statistics时间测量函数,那么也会在这个界面里面展示消息的,如何才能仅展示大家想看的功能呢?这就需要用到Event Recorder支持的筛选功能。使用这个功能需要大家先暂停全速运行,然后点击下面这个选项:


弹出的界面里面可以设置哪些选项显示,哪些选项不显示(勾上表示显示),我们这里取消Event Statistics的显示,设置完毕后记得点击OK按钮。


这就不展示Event Statistics的内容了。再次启动全速运行前,下面这个选项的对勾别忘了勾上。


8.5   Event Recorder实现printf重定向

实现printf输出需要用到MDK调试组件中的Debug(printf) Viewer,输出效果就跟大家使用串口调试软件一样,可以输出中文和英文。


MDK的printf调试组件使用方法跟本章8.4小节中的说明一样,点击调试,选中周期运行,然后显示Debug(printf) Viewer调试组件:


效果如下:


另外,还有一个知识点需要给大家做个补充,使用SWD接口的SWO引脚也是可以做串口打印的,并且也是通过这个调试组件Debug(printf) Viewer进行输出。只是这种方式的性能没有Event Viewer强,而且要多占用一个SWO引脚。


关于SWO输出方式可以看此贴:http://forum.armfly.com/forum.php?mod=viewthread&tid=526 。


8.6   Event Statistics 时间测量功能的实现

时间测量功能简单易用,仅需一个起始函数,一个停止函数即可。当前支持4组,每组支持16路测量,也就是可以同时测量64路。


时间测量的API函数支持多任务和中断里面随意调用。


1、  测量起始函数:EventStartG (slot) 或者EventStartGv (slot, val1, val2)


 函数中的字母G是表示分组A,B,C,D,即实际调用函数为EventStartA,EventStartB,EventStartC和EventStartD。

  函数的第一个形参slot的范围是0-15,也就是每个分组可以测试16路。

  函数后面的两个形象val1和val2是32位变量,用户可以用这两个形参来传递变量数值给Event Statistics调试组件里面,方便图形化展示。简单的说,这两个变量仅仅起到一个传递变量数值的作用。

2、  测量停止函数:EventStopG (slot) 或者  EventStopGv (slot, val1, val2)


  函数中的字母G是表示分组A,B,C,D,即实际调用函数为EventStopA,EventStopB,EventStopC和EventStopD。

  函数的第一个形参slot的范围是0-15,也就是每个分组可以测试16路。

 函数后面的两个形象val1和val2是32位变量,用户可以用这两个形参来传递变量数值给Event Statistics调试组件里面,方便图形化展示。简单的说,这两个变量仅仅起到一个传递变量数值的作用。

 


这里也分步为大家说明Event Statistics时间测量功能的使用方法。


  第1步:初始化,仅需添加如下两行代码即可。


/* 初始化EventRecorder并开启 */ 

EventRecorderInitialize(EventRecordAll, 1U); 

EventRecorderStart();

  第2步:在要测量的代码前后加上起始和结束时间。


EventStartA(0); 

测量的代码部分 

EventStopA(0);

这里是用分组A的测量通道0。


  第3步:跟本章8.4小节讲解的一样,点击调试,选择周期更新选项,然后全速运行。


  第4步:全速运行后,显示Event Statistics调试组件。


比如我这里简单的测试了一个5ms的延迟函数,效果如下(测量时间是动态更新的):


另外要注意一点,微秒的时间单位us可能无法正常显示,这个是没有关系的:


8.7   Event Statistics 功耗测量功能的实现

当前仅KEIL自家的ULINKplus支持功耗测量功能,这款下载器不便宜,一套5000多,大家有个了解即可,我们这里就不做讲解了。


8.8   Event Recorder对RTX5及其所有中间件的支持

后面做RTX5及其所有中间件的教程时会为大家做讲解,这里让大家看下效果:


  RTX5组件和使用Event Recoder的效果:



  网络调试组件效果展示:


  文件系统和USB协议栈的效果展示:


8.9   JLINK配置说明

为了帮助大家更好的使用JLINK,这里将JLINK配置中关键的几个地方做个说明。


  下面这个地方最重要,一定要正确设置当前系统工作的主频,如果不正确,会导致Event Statistics的时间统计不正确(对于H7,Core部分要填400MHz)。

注:如果大家调试状态弹出SWD配置时钟超出范围的问题,可以考虑将上面截图中的Enable选项的对勾取消掉即可,但内核时钟一定要修改为芯片的主频。


另外,进入调试状态后,右下角的时间是否正常更新都没有关系:


  其它选项配置如下(只要大家的工程能够正常调试,配置就是没问题的):



8.10 STLINK配置说明

为了帮助大家更好的使用STLINK,这里将STLINK配置中关键的几个地方做个说明。


  下面这个地方最重要,一定要正确设置当前系统工作的主频,如果不正确,会导致Event Statistics的时间统计是不正确的(对于H7,Core部分要填400MHz)。

另外注意,进入调试状态后,右下角的时间是否正常更新都没有关系:

其它选项配置如下(只要大家的工程能够正常调试,配置就是没问题的):


8.11 CMSIS-DAP配置说明

为了帮助大家更好的使用CMSIS-DAP,这里将CMSIS-DAP配置中关键的几个地方做个说明。


  下面这个地方最重要,一定要正确设置当前系统工作的主频,如果不正确,会导致Event Statistics的时间统计不正确(对于H7,Core部分要填400MHz)。


另外注意,进入调试状态后,右下角的时间是否正常更新都没有关系:


  其它选项配置如下(只要大家的工程能够正常调试,配置就是没问题的):

推荐阅读

史海拾趣

Datakey Electronics公司的发展小趣事

在电子产品行业,产品质量是企业生存和发展的基石。Datakey Electronics始终坚守品质至上的原则,从原材料采购到生产流程控制,再到产品检验和售后服务,每一个环节都严格把关。正是这种对品质的执着追求,使Datakey Electronics的产品在市场上树立了良好的口碑,赢得了客户的信赖。

Heatron LED Integration公司的发展小趣事

Heatron LED Integration始终将客户需求放在首位,提供全方位的服务支持。公司建立了完善的售前咨询、售中指导和售后服务体系,确保客户在使用过程中能够得到及时、专业的帮助。此外,公司还根据客户需求提供定制化解决方案,满足不同场景下的照明需求。这种客户至上的服务理念,赢得了广大客户的信赖和好评。

FILTRONETICS Inc公司的发展小趣事

为了确保产品质量,FILTRONETICS始终将质量管理放在首位。公司建立了完善的质量管理体系,从原材料采购、生产制造到产品检测、售后服务等各个环节都严格把关。同时,公司还引入了先进的检测设备和技术手段,对产品进行全方位的质量检测和控制。这些措施不仅确保了产品的稳定性和可靠性,也提升了公司的品牌形象和市场声誉。

Good Will Instrument Co., Ltd.公司的发展小趣事

为了确保产品质量,FILTRONETICS始终将质量管理放在首位。公司建立了完善的质量管理体系,从原材料采购、生产制造到产品检测、售后服务等各个环节都严格把关。同时,公司还引入了先进的检测设备和技术手段,对产品进行全方位的质量检测和控制。这些措施不仅确保了产品的稳定性和可靠性,也提升了公司的品牌形象和市场声誉。

BULGIN公司的发展小趣事

作为公认的环境密封连接器及元器件领先制造商,BULGIN公司一直专注于提升在环境密封、电源及防控产品领域的市场地位。公司凭借在极具挑战性的环境中提供可靠、坚固的电源、信号和数据连接的能力,赢得了客户的广泛赞誉。其中,备受欢迎的Buccaneer圆形连接器系列在业界享有出色的声誉,成为公司的一大亮点。

这五个故事展示了BULGIN公司在电子行业中的发展历程和关键里程碑。从创立初期到成为全球领先的电子零件制造商,再到战略性合并和业务扩展,BULGIN始终保持着创新精神和对优质产品的追求。如今,作为环境密封连接器及元器件的领先制造商,BULGIN将继续为客户提供卓越的产品和服务,推动电子行业的持续发展。

ARCOLECTRICSWITCHES公司的发展小趣事

在电子行业的初期,ARCOLECTRIC SWITCHES公司以其卓越的技术研发能力崭露头角。公司研发团队成功开发出一种新型开关技术,具有更高的稳定性和耐用性,迅速在市场上获得了广泛认可。这一技术突破不仅为公司带来了丰厚的利润,还奠定了其在电子行业的重要地位。随着技术的不断升级和完善,ARCOLECTRIC SWITCHES公司逐渐发展成为一家技术领先、市场影响力强大的企业。

问答坊 | AI 解惑

悬挂系统中的步进电机带动装置选择问题

本帖最后由 paulhyde 于 2014-9-15 09:25 编辑 步进电机带动滑轮,要用什么样的线比较好? 线要绕在步进电机上还是绕在哪里?绕在电机上的话线太长,步进电机齿轮太小,绕不上。 还有这些滑轮啦线啦齿轮啦要上哪买?五金店吗?  …

查看全部问答>

发个字符移动的程序(ZT)

本帖最后由 paulhyde 于 2014-9-15 09:38 编辑 前几天在公交站牌上看到那个led屏上字符移动的效果,看了之后回来想玩玩,就做了这个,发上来分享一下!!  …

查看全部问答>

请问无盘工作站是两个系统吗?

请问无盘工作站是两个系统吗?为什么有的是一个呢?它们有什么区别啊?》…

查看全部问答>

ADS下全局变量赋值无效的问题

我用ADS1.2+JTAG调试程序的时候,定义的全局变量在赋值的时候赋不进去。当在初始化汇编代码init.s中加入存储寄存器初始化的代码,就可以赋值进去,这是什么原因呢 ? 加入的存储寄存器初始化代码如下: SMRDATA DATA ; Memory configuration sho ...…

查看全部问答>

如何将笔记本usb口虚拟成串口

本人想进行串口编程,但笔记本上只有usb口,故想将其虚拟成串口,但不知怎么做。希望个位帮帮忙,给分绝不吝惜!!!…

查看全部问答>

M2M-DMA的问题

  DMA_InitStructure.DMA_PeripheralBaseAddr = (u32)SRC_Buffer;  DMA_InitStructure.DMA_MemoryBaseAddr = (u32)DST_Buffer;采用M2M模式,在本地RAM测试通过。即SRC_Buffer[x]={};  DST_ ...…

查看全部问答>

【转帖】MSP430是很有前途的单片机--转自老古论坛

对于ti推出的msp430低功耗的16位单片机,评论很多。在这个时候推出16位的单片机,是否能够占领市场? 我们知道8位单片机在中国是处于龙头地位的。要动摇51单片机的地位,确实在中国有一定的困难。在中国,特别要考虑的是中国的国情。 比 ...…

查看全部问答>

stm32的usart接收字符串问题:怎样接收字符串

如何让stm32的usart接收字符串啊,USART_ReceiveData函数仅仅接收的是最后一个字符…

查看全部问答>