基于ARM Cortex-M和Eclipse的SWO单总线输出

最近在MCU on Eclipse网站上看到Erich Styger所写的一篇有关通过SWD的跟踪接口SWO获取ARM Cortex-M相关信息的文章,文章结构明晰,讲解透彻,本人深受启发,特意将其翻译过来供各位同仁参考。当然限于个人水平,有不当之处恳请指正。原文网址:https://mcuoneclipse.com/2016/10/17/tutorial-using-single-wire-output-swo-with-arm-cortex-m-and-eclipse/

作为一个标准过程,我将一些控制台功能添加到我的嵌入式应用程序中。这样我就有了一个命令行接口,可以检查和修改目标系统。ARM Cortex-M的一个有趣的硬件特性是单线输出(SWO) ,它允许通过一根线路将数据(例如字符串)发送到32个不同的激励端口。

ARM调试器接头上的SWO引脚

调试跟踪输出?SWO

我使用普通的UART/SCI作为标准的文本和命令行与目标板的接口。然而,在许多板上,UART被应用程序使用。

有一个Semihosting(半托管),但是速度非常慢,而且取决于调试器和工具链/库,加上需要消耗FLASH和RAM,所以我不建议在任何情况下使用Semihosting。

【注】Semihosting是针对ARM目标机的一种机制,它能够根据应用程序代码的输入/输出请求,与运行有调试功能的主机通讯。这种技术允许主机为通常没有输入和输出功能的目标硬件提供主机资源。

也有一个USB CDC,但这需要一个USB接口,一个USB栈和一个具有USB功能的微控制器。不适用于所有情况。

还有一个Segger RTT,它很小,速度快,最好的是不需要任何特殊的引脚。但只能工作于Segger的调试探测器。

ARM SWO

但还有另一件事:ARM SWO跟踪端口是由ARM为Cortexm-M定义的。从技术上讲,SWO是一个单一的跟踪引脚,它被用来以从CPU核心时钟中提取一个特定的时钟频率发送数据包。您可以将SWO看作是一种使用特殊格式发送数据包的UART TX引脚。可以使用多达32种包类型(或激励)。发送什么样的数据取决于应用程序,并且只需要很少的CPU处理或代码。

常见SWO用法是:

  • 按字符串发送调试信息
  • 记录中断的进入与退出
  • 记录函数的进入与退出
  • 周期性的PC值采样
  • 事件提示
  • 变量或内存单元修改超时

最常见的用法之一就是第一种:使用SWO以UART样式打印来自目标的调试消息。并且这也正是我再这篇文章中将要表达的。还有另一种编码(曼彻斯特编码),这里不做介绍。

ARM CoreSight

SWO是ARM CoreSight调试功能块的一部分,而ARM CoreSight则通常是Cortex-M3,M4,M7的一部分:

CoreSight功能块(来自:http://www.arm.com/files/pdf/AT_-_Advanced_Debug_of_Cortex-M_Systems.pdf

如上图所示,通过SWO(或SWV)ITM和DWT跟踪消息可以发送。对于指令跟踪需要4个额外的跟踪引脚

SWO引脚

使用SWO的前提条件是这个引脚可以在调试头中使用。这是我的TWR-K64F120M板的情况:

trace swo引脚(来自:TWR-K64F120M原理图)

如上图所示,SWO跟踪引脚是与JTAG TDO引脚共享的。所以这就意味着SWO不能在JTAG中使用,而只能在SWD中使用。

所以仔细检查你板子的原理图确定他是否支持SWO。例如FRDM-K64F(是TWR-K64F120M上一个版本),它的SWO是没有被引到调试头的:

FRDM-K64F上没有SWO

调试探针与SWO

为了能够使用SWO,我需要一个能够读取SWO引脚的调试探测器。例如,Freescale/NXP OpenSDA在Freedom和Tower模块板载调试接口硬件就不支持SWO。

然而,外部的Segger J-Link却支持SWO引脚。下面我有一个J-Link EDU连接到TWR-K64F120M板的调试和跟踪端口:

j-link edu连接到跟踪端口

通过SWO引脚发送调试信息的源码

为了通过SWO写调试消息到主机,需要一小段代码。在Github上有一个可用的完整代码的例子项目:

https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/KDS/TWR-K64F120M/TWR-K64F120M_Demo/Sources

外部工具(比如Segger RTT查看器)可以在硬件中设置SWO。我的建议是从应用程序初始化它。因为SWO跟踪输出时钟是从CPU时钟派生而来的,所以初始化函数需要这个时钟加上SWO端口号来初始化。下面是我用来初始化SWO输出的代码,默认为64k波特率:

/*!

* \brief Initialize the SWO trace port for debug message printing

* \param portBits Port bit mask to be configured

* \param cpuCoreFreqHz CPU core clock frequency in Hz

*/

void SWO_Init(uint32_t portBits, uint32_t cpuCoreFreqHz) {

uint32_t SWOSpeed = 64000; /* default 64k baud rate */

uint32_t SWOPrescaler = (cpuCoreFreqHz / SWOSpeed) - 1; /* SWOSpeed in Hz, note that cpuCoreFreqHz is expected to be match the CPU core clock */

CoreDebug->DEMCR = CoreDebug_DEMCR_TRCENA_Msk; /* enable trace in core debug */

*((volatile unsigned *)(ITM_BASE + 0x400F0)) = 0x00000002; /* "Selected PIN Protocol Register": Select which protocol to use for trace output (2: SWO NRZ, 1: SWO Manchester encoding) */

*((volatile unsigned *)(ITM_BASE + 0x40010)) = SWOPrescaler; /* "Async Clock Prescaler Register". Scale the baud rate of the asynchronous output */

*((volatile unsigned *)(ITM_BASE + 0x00FB0)) = 0xC5ACCE55; /* ITM Lock Access Register, C5ACCE55 enables more write access to Control Register 0xE00 :: 0xFFC */

ITM->TCR = ITM_TCR_TraceBusID_Msk | ITM_TCR_SWOENA_Msk | ITM_TCR_SYNCENA_Msk | ITM_TCR_ITMENA_Msk; /* ITM Trace Control Register */

ITM->TPR = ITM_TPR_PRIVMASK_Msk; /* ITM Trace Privilege Register */

ITM->TER = portBits; /* ITM Trace Enable Register. Enabled tracing on stimulus ports. One bit per stimulus port. */

*((volatile unsigned *)(ITM_BASE + 0x01000)) = 0x400003FE; /* DWT_CTRL */

*((volatile unsigned *)(ITM_BASE + 0x40304)) = 0x00000100; /* Formatter and Flush Control Register */

}

在我的主应用程序中,我像这样初始化它(对于一个有24MHz核心时钟的系统):

#define CPU_CORE_FREQUENCY_HZ 120000000 /* CPU core frequency in Hz */

SWO_Init(0x1, CPU_CORE_FREQUENCY_HZ);

在SWO_PrintChar()函数中完成打印:

/*!

* \brief Sends a character over the SWO channel

* \param c Character to be sent

* \param portNo SWO channel number, value in the range of 0 to 31

*/

void SWO_PrintChar(char c, uint8_t portNo) {

volatile int timeout;

/* Check if Trace Control Register (ITM->TCR at 0xE0000E80) is set */

if ((ITM->TCR&ITM_TCR_ITMENA_Msk) == 0) { /* check Trace Control Register if ITM trace is enabled*/

return; /* not enabled? */

}

/* Check if the requested channel stimulus port (ITM->TER at 0xE0000E00) is enabled */

if ((ITM->TER & (1ul<<portNo))==0) { /* check Trace Enable Register if requested port is enabled */

return; /* requested port not enabled? */

}

timeout = 5000; /* arbitrary timeout value */

while (ITM->PORT[0].u32 == 0) {

/* Wait until STIMx is ready, then send data */

timeout--;

if (timeout==0) {

return; /* not able to send */

}

}

ITM->PORT[0].u16 = 0x08 | (c<<8);

}

上面的代码使用了一个非常简单的超时机制:重要的一点是,如果SWO没有启用或者SWO端口没有准备好,那么应用程序就会被阻塞。

为了更方便地打印字符串,我使用以下函数:

/*!

* \brief Sends a string over SWO to the host

* \param s String to send

* \param portNumber Port number, 0-31, use 0 for normal debug strings

*/

void SWO_PrintString(const char *s, uint8_t portNumber) {

while (*s!=‘\0‘) {

SWO_PrintChar(*s++, portNumber);

}

}

要通过SWO发送一个“hello”,它就像这样简单:

SWO_PrintString("hello world with SWO\r\n", 0);

第一个参数是要发送的字符串,第二个是SWO跟踪通道号。

GNU ARM Eclipse查看器

要接收主机上的SWO跟踪输出,GNU ARM Eclipse插件内置了Segger J-Link探测器的SWO支持。

SWO仅支持SWD(单线调试)模式,不支持JTAG模式。所以确保SWD被选为调试协议:

SWD调试

在GNU ARM Eclipse调试配置中,启用SWO并指定CPU频率和SWO频率(请参见http://gnuarmeclipse.github.io/debug/jlink/上的有关频率的文档)。我必须提供CPU频率(在我的情况下为120 MHz),并且可以将SWO频率设置为0,以便J-Link自动确定速度)。在端口掩码中指定使用的端口(作为位掩码),因此0x1用于使用端口0:

SWO的设置

这样,在目标板上运行应用程序就会在Eclipse控制台视图中显示输出:

Eclipse控制台视图

Segger SWO Viewer

Segger有一个特殊的SWO Viewer(命令行和GUI版本)。

在GUI版本中,我指定使用的设备,它可以感测跟踪时钟:

segger gui swo viewer

在查看器中,我可以打开/关闭端口,并查看收到的数据:

segger j-link swo viewer

Telnet: Putty

但是,没有需要查看SWO数据的花哨的查看器或Eclipse。Segger默认使用端口2332:

SEGGER SWO端口

我可以配置任何telnet客户端(例如PuTTY)在端口2332上打开会话:

putty telnet会话设置

我在PuTTY中得到的输出:

SWO在PuTTY中的输出

综述

ARM SWO跟踪引脚允许向主机发送跟踪消息。一个常见的用法是向主机发送调试或其他消息。SWO只需要一个引脚,仅适用于SWD(而不是JTAG),并且在目标上需要很少的代码和资源。不幸的是,许多电路板没有将SWO跟踪引脚路由到调试头,因此如果您正在进行自己的设计,则至少应考虑将SWO路由到调试头。

虽然SWO跟踪输出很大,但是限于高端Cortex-M,我没有在Cortex-M0(+)中找到它,它只是输出,需要一个支持它的调试探针/接口。至少与Eclipse和GNU ARM Eclipse插件结合Segger J-Link探针SWO输出对我来说非常棒。

另一方面,Segger RTT的功能更加多样化,也非常快。它适用于所有ARM Cortex,最重要的是不需要额外的引脚。然而,它在目标系统上需要更多的开销和RAM资源。此外,它允许发送和接收数据。所以对于串行调试消息打印,Segger RTT对我来说听起来更好的解决方案。

接下来就是快乐SWO中了!

相关链接

  • SWO on Kinetis:https://community.nxp.com/thread/318058
  • SWO与GNU ARM Eclipse插件:http : //gnuarmeclipse.github.io/debug/jlink/
  • Segger SWO Viewer:https : //www.segger.com/j-link-swo-viewer.html
  • GNU ARM Eclipse插件:http : //gnuarmeclipse.github.io/debug/
  • Eclipse RxTx插件,用于解析SWO数据:http : //forum.segger.com/index.php? page=Thread&threadID=1010
  • ARM CoreSight概述:http : //www.arm.com/files/pdf/AT_-_Advanced_Debug_of_Cortex-M_Systems.pdf
  • GitHub上的示例代码:https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/KDS/TWR-K64F120M/TWR-K64F120M_Demo/Sources

欢迎关注:

时间: 2024-08-29 10:03:07

基于ARM Cortex-M和Eclipse的SWO单总线输出的相关文章

基于ARM Cortex-A8和Android 4.x的联动报警系统视频教程

基于ARM Cortex-A8和Android 4.x的联动报警系统 (Android .A8.Linux.驱动.NDK)课程讲师:老夫子 课程分类:Android适合人群:高级课时数量:38(70节)课时更新程度:完毕用到技术:Android.A8.210.Linux.驱动.NDK.报警涉及项目:联动报警系统 联系QQ:1609173918链接:http://down.51cto.com/data/2037421 1.课程研发环境 本课程包括JAVA应用.C语言驱动.NDK(应用调用驱动)等方

基于ARM Cortex-A8和Android 4.x的联动报警系统 (Android 、A8、Linux、驱动、NDK)

· 课程讲师:老夫子 · 课程分类:Android · 适合人群:高级 · 课时数量:38(70节)课时 · 更新程度:完毕 · 服务类型:C类(普通服务类课程) · 用到技术:Android.A8.210.Linux.驱动.NDK.报警 · 涉及项目:联动报警系统 对这个课程有兴趣的可以加我qq2748165793 1.课程研发环境 本课程包括JAVA应用.C语言驱动.NDK(应用调用驱动)等方面内容,课程涉及主要工具如下: 开发工具:Eclipse.Source Insight 交叉编译工具

ARM Cortex M0权威指南_PDF电子书下载 带书签目录 高清完整版 http://pan.baidu.com/s/1jGKQSwY MariaDB入门很简单_PDF电子书下载 带

ARM  Cortex  M0权威指南_PDF电子书下载 带书签目录 高清完整版   http://pan.baidu.com/s/1jGKQSwY MariaDB入门很简单_PDF电子书下载 带书签目录 高清完整版  http://pan.baidu.com/s/1hqpgV20 管理就是走流程__没有规范流程,管理一切为零_PDF电子书下载 带书签目录 高清完整版  http://pan.baidu.com/s/1bntuLyf 搜索引擎优化  SEO  方法与技巧  第5版_PDF电子书下

ARM7与ARM Cortex比较

ARM7与ARM Cortex比较  1.ARM实现方法 ARM Cortex是一种基于ARM7v架构的最新ARM嵌入式内核,它采用哈佛结构,使用分离的指令和数据总线(冯诺伊曼结构下,数据和指令共用一条总 线).从本质上来说,哈佛结构在物理上更为复杂,但是处理速度明显加快.根据摩尔定理,复杂性并不是一件非常重要的事,而吞吐量的增加却极具价值. ARM公司对Cortex的定位是:向专业嵌入式市场提供低成本.低功耗的芯片.在成本和功耗方面,Cortex具有相当好的性能,ARM公司认为它特别适用于汽车

ARM cortex a 之时钟系统1

ARM cortex a系列的时钟系统是一个非常复杂而且麻烦的东西,下面我们首先明确一些概念和东西. 本部分主要介绍一下时钟系统的初始化工作,以及里面的一些原理. S5PV210的时钟系统是一个非常麻烦的东西,首先需要时钟信号的产生,时钟发生器只有和晶振一起工作才能产生时钟信号,这两个单独使用的话是没有任何作用的. 时钟系统分为三个大域:即主系统(MSYS),显示系统(DSYS),和外围系统(PSYS). (1)MSYS域包括cortexA8处理器,DRAM内存控制器(DMC0和DMC1),3D

课程设计个人报告——基于ARM实验箱的捕鱼游戏的设计与实现

课程设计个人报告--基于ARM实验箱的捕鱼游戏的设计与实现 个人贡献 实验环境的搭建 代码调试 在电脑上成功运行 在ARM实验箱上成功实现 给程序增加功能(没成功) 研究程序代码撰写小组报告 一.实验环境 Eclipse软件开发环境: ARM实验箱(HonyaS5PC100): windows操作系统. 二.实践内容 Windows环境下ARM集成开发环境的搭建与使用: 安装软件到模拟器: 连接ARM实验箱与PC机: 将工程代码在ARM实验箱上实现: 给程序增加新的功能. 三.实践步骤 3.1

基于ARM处理器的反汇编器软件简单设计及实现

写在前面 2012年写的,仅供参考 反汇编的目的 缺乏某些必要的说明资料的情况下, 想获得某些软件系统的源代码.设计思想及理念, 以便复制, 改造.移植和发展: 从源码上对软件的可靠性和安全性进行验证,对那些直接与CPU 相关的目标代码进行安全性分析: 涉及的主要内容 分析ARM处理器指令的特点,以及编译以后可执行的二进制文件代码的特征: 将二进制机器代码经过指令和数据分开模块的加工处理: 分解标识出指令代码和数据代码: 然后将指令代码反汇编并加工成易于阅读的汇编指令形式的文件: 下面给出个示例

DreamHouse项目(基于ARM与ZIGBEE技术的智能家居)之项目展示

这是本人做的一次有关智能家居的项目,仅是用来参加比赛的!或者是我用来练手的吧!大概花费了我近2个月的时间来完成他,平台是建立在博创S3C2410的嵌入式的箱子上的,我觉得我唯一没有足够自信说是自己写的代码的话就是驱动部分了,毕竟当时的状态也是刚刚把单片机的知识全部学会罢了,因为这是基础中的基础,对于C语言,在校的学生普遍是没有完全掌握的,对于开发真的知识储备确实不够!好吧废话我不多说了,先讲讲我自己做的项目吧!学生的练手项目,大家应该不会来喷我吧! 上图先! 通用模块 我本人真的是没有做出来,但

基于ARM的车牌识别技术研究与实现

在云盘里包含了我本科毕业设计的全部资料和代码.主要涉及下面摘要中的几个部分.虽然系统无法实用,但是适合机器视觉和嵌入式方向的入门.希望能对有志从事相关方向的朋友有所帮助.本人现在在深圳从事机器视觉算法工程师职业.现在做人脸识别相关系统.希望能和网络上的有志之士一起在相关方向上学习和进步. 本文首先介绍了课题背景和研究现状,然后介绍了方案选择和设计过程.设计过程包括车牌识别程序设计,引导程序设计,内核驱动设计和文件系统设计.车牌识别程序设计中的车牌定位采用边缘检测和支持向量机相结合的定位算法,字符