基于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
欢迎关注:
基于ARM Cortex-M和Eclipse的SWO单总线输出相关推荐
- 基于Arm Cortex内核的32位MCU和MPU(M0、M0+、M3、M4、M33、M7、A7)
基于Arm Cortex内核的32位MCU和MPU ST意法半导体产品矩阵 M3典型--STM32 F1系列Cortex-M3基础型MCU M4典型--带有DSP和FPU指令的STM32F4系列高性能 ...
- 基于ARM Cortex M0 核心的低功耗蓝牙BLE芯片
MS1793S 是一款基于ARM Cortex M0 核心的低功耗蓝牙芯片,射频采用2.4GHz ISM 频段的频率,2MHz 信道间隔,符合蓝牙规范.MS1793S使用高性能的ARM®Cortex® ...
- android平板开发板,基于ARM Cortex A9开发板平板电脑实战项目
Cortex A9处理器基于先进的推测型八级流水线,该流水线具有高效.动态长度.多发射超标量及无序完成特征,这款处理器的性能.功效和功能均达到了前所未有的水平,能够满足消费.网络.企业和移动应用等领域 ...
- 基于ARM Cortex M0国产32位单片机MM32SPIN220B
灵动MM32SPIN220B使用高性能的ARM®CortexTM-M0为内核的国产32位MCU,内嵌两组具备有自举二极管的N通道半桥栅极驱动器.MCU微控制器工作频率高达96兆赫兹,内置高速SRAM存 ...
- 东芝面向消费设备和工业设备推出基于Arm(R) Cortex(R)-M3且具备先进功能的低功耗微控制器
东京--(美国商业资讯)--东芝电子元件及存储装置株式会社("东芝")面向消费设备和工业设备推出"M3H族"微控制器,成功扩大其基于Arm® Cortex®-M ...
- 意法半导体STM32 ARM Cortex 32位微控制器
STM32系列32位微控制器基于Arm® Cortex®-M处理器,旨在为MCU用户提供新的开发自由度.它包括一系列产品,集高性能.实时功能.数字信号处理.低功耗/低电压操作.连接性等特性于一身,同时 ...
- ARM® Cortex®-M内核单片机STM32家族介绍,覆盖STM32F、STM32H、STM32L全系列
STM32是ARM®Cortex®-M内核单片机.目前提供10大产品线(F0, F1, F2, F3, F4, F7, H7, L0, L1, L4),超过700个型号.STM32产品广泛应用于 ...
- 「免费申请」基于Arm Cortex-M4的兆易创新GD32F427高性能开发板试用活动
申请链接:「免费申请」基于Arm Cortex-M4的兆易创新GD32F427高性能开发板试用活动 基于Arm® Cortex®-M4的兆易创新GD32F427开发板免费试用活动 近期兆易创新发布了全 ...
- 恩智浦arm芯片Linux,基于ARM处理器的工业控制系列【恩智浦】
中国上海,2011年2月22日 -- 恩智浦半导体(NXP Semiconductors N.V.)今天宣布推出其基于ARM? Cortex?-M0处理器的LPC1200工业控制系列.LPC1200进 ...
最新文章
- anaconda不同虚拟环境下使用jupyter的问题
- springboot使用原生servlet、filter、listener
- 七牛直播云服务技术揭秘
- 再谈csdn blog的bug
- list stream().forEach
- 陕西师范大学计算机专业排名,陕西师范大学优势专业排名,2021年陕西师范大学最好的专业排名...
- LoadRunner踩坑记录:服务器“127.0.0.1”在尝试协商 SSL 会话时关闭连接
- multisim变压器反馈式_【鼎阳硬件智库原创|高速总线】 以太网变压器反转问题技术分析...
- Java基础知识总结(一)创建和销毁对象
- Android 笔记 json GSON,Android中使用Gson解析JSON数据
- JS实现轮播图(一看就懂逻辑清晰)
- LUAT游戏第一弹---贪吃蛇
- Django admin修改app名称
- 云虚拟机和普通虚拟机有什么区别
- 机器学习和人工智能的关系是什么?
- Linux系统如何优化
- 人力资源行业拓客的10个经典方法
- 在IT行业中,程序员的学历重要吗?
- 数据结构 笔记:图的遍历(DFS)
- 计算机中的物理地址与内存
热门文章
- 使用memocache
- 20145324 《Java程序设计》第6周学习总结
- android studio升级时提示 Connection failed. Please check your network connection and try again
- c#自动更新+安装程序的制作
- 《那些年啊,那些事——一个程序员的奋斗史》——63
- AjaxPro.dll和AjaxPro.2.dll的web配置方法
- 计算机网络概述(一)
- springboot 添加拦截器之后中文乱码_spring boot 2.x 添加拦截器配置未生效的问题
- java单元格合并多列_ElementUI表格列相同值自动合并单元格( 多列 )
- dc持久内存与mysql_Calypso Systems推出测试软件和服务器测试傲腾数据中心级持久内存...