semihost/ITM机制浅析以及使用JLINK通过ITM调试stm32单片机

使用ITM机制实现调试stm32单片机,实现printf与scanf。

  1. ITM简介
    ITM机制是一种调试机制,是新一代调试方式,在这之前,有一种比较出名的调试方式,称为半主机(semihosting)方式。

在pc上编写过C语言的人都知道,printf可以向控制台输出,scanf可以从控制台获取输入,这里的printf/scanf都是标准库函数,利用操作系统的这些函数,我们可以很方便的调试程序。在嵌入式设备上(如stm32单片机平台上)开发工具(如MDK/IAR)也都提供了标准库函,自然也提供了printf/scanf函数,那么这些函数是否可以使用呢? 问题来了,printf向哪里输出呢?并且大部分情况下,也没有键盘,又如何使用scanf实现输入呢?

我们都知道,嵌入式设备一般的使用仿真器,如常见Jlink/ulink,可以实现烧录,单步,下断点,查看变量,等等。仿真器将PC机和单片机连接器来。聪明的设计者们就在考虑是否可以借助仿真器,使得单片机可以借助PC机的屏幕以及PC机的键盘实现printf的输出和scanf的按键获取。
也就是说,如下的hello,world程序
#include <stdio.h>
int main()
{
//硬件初始化
//…
printf(“hello, world”);
for(;😉;
}
这个程序烧录到单片机中后,仿真器连接接单片机与PC,开始在线调试后,那么这个程序会将"Hello, world"输出到PC机上,在开发工具(MDK/IAR等)的某个窗口中显示。

这就相当于,单片机借助了PC机的显示/输入设备实现了自己的输出/输入。这种方式无疑可以方便程序开发者调试。

这种机制有多种实现方式,比较著名的就是semihosting(半主机机制)和ITM机制。
ITM是ARM在推出semihosting之后推出的新一代调试机制。现在我们来尝试一下这种方式调试。

  1. stm32使用ITM调试
    MCU:stm32f207VG
    仿真器:Jlink V8
    IDE:MDK4.50

2.1 硬件连接
ITM机制要求使用SWD方式接口,并需要连接SWO线,一般的四线SWD方式(VCC SDCLK,SDIO,GND)是不行的。标准的20针JTAG接口是可以的,只需要在MDK里设置使用SWD接口即可。

2.2 添加重定向文件
将下面的文件保存成任意C文件,并添加到工程中。这里对这个文件简单说明一下,要知道我们的程序是在单片机上运行的,为什么printf可以输出到MDK窗口里去呢?这是因为 标准库中的printf实际上调用 fputc实现输出,所以我们需要自己编写一个fputc函数,这个函数会借助ITM(类似于USART)提供的寄存器,实现数据的发送,仿真器会收到这些数据,并发往PC机。

实际上,如果你的单片机和一块LCD连接,那么你只需要重新实现fputc函数,并向LCD上输出即可,那么你调用printf时就会输出到LCD上了。这中机制,就是所谓的重定向机制。

#include <stdio.h>

#define ITM_Port8(n) (((volatile unsigned char )(0xE0000000+4n)))
#define ITM_Port16(n) (
((volatile unsigned short*)(0xE0000000+4n)))
#define ITM_Port32(n) (
((volatile unsigned long )(0xE0000000+4n)))
#define DEMCR (*((volatile unsigned long *)(0xE000EDFC)))
#define TRCENA 0x01000000

struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;

int fputc(int ch, FILE *f)
{
if (DEMCR & TRCENA)
{
while (ITM_Port32(0) == 0);
ITM_Port8(0) = ch;
}
return(ch);
}

2.2 配置JLINK的初始化配置文件

将下面文件放置在你的工程下,并取任意名称,这里笔者取名为 STM32DBG.ini

/*****************************************************************************/
/
STM32DBG.INI: STM32 Debugger Initialization File /
/
*****************************************************************************/
// <<< Use Configuration Wizard in Context Menu >>> //
/*****************************************************************************/
/
This file is part of the uVision/ARM development tools. /
/
Copyright © 2005-2007 Keil Software. All rights reserved. /
/
This software may only be used under the terms of a valid, current, /
/
end user licence from KEIL for a compatible version of KEIL software /
/
development tools. Nothing else gives you the right to use this software. /
/
*****************************************************************************/

FUNC void DebugSetup (void) {
// Debug MCU Configuration
// <o1.0> DBG_SLEEP Debug Sleep Mode
// <o1.1> DBG_STOP Debug Stop Mode
// <o1.2> DBG_STANDBY Debug Standby Mode
// <o1.5> TRACE_IOEN Trace I/O Enable
// <o1.6…7> TRACE_MODE Trace Mode
// <0=> Asynchronous
// <1=> Synchronous: TRACEDATA Size 1
// <2=> Synchronous: TRACEDATA Size 2
// <3=> Synchronous: TRACEDATA Size 4
// <o1.8> DBG_IWDG_STOP Independant Watchdog Stopped when Core is halted
// <o1.9> DBG_WWDG_STOP Window Watchdog Stopped when Core is halted
// <o1.10> DBG_TIM1_STOP Timer 1 Stopped when Core is halted
// <o1.11> DBG_TIM2_STOP Timer 2 Stopped when Core is halted
// <o1.12> DBG_TIM3_STOP Timer 3 Stopped when Core is halted
// <o1.13> DBG_TIM4_STOP Timer 4 Stopped when Core is halted
// <o1.14> DBG_CAN_STOP CAN Stopped when Core is halted
//

_WDWORD(0xE0042004, 0x00000027); // DBGMCU_CR
_WDWORD(0xE000ED08, 0x20000000); // Setup Vector Table Offset Register
}

DebugSetup(); // Debugger Setup

这里对这个文件做简单的解释,
_WDWORD(0xE0042004, 0x00000027); // DBGMCU_CR
这一句表示想 0xE0042004地址处写入 0x000000027,这个寄存器是各个位表示的含义在注释中给出了详细的解释。 0x27即表示
BIT0 DBG_SLEEP
BIT1 DBG_STOP
BIT2 DBG_STANDBY
BIT5 TRACE_IOEN
注意,要使用ITM机制,必须要打开BIT5。

打开MDK工程,按照下图修改。
在这里插入图片描述

2.3 MDK中对JLINK的配置
在这里插入图片描述

下图中注意两点
1). 这里的CoreClock是120M,因为笔者使用的是stm32F207VG这款芯片,并且时钟配置为120M,所以这里填入120M,如果你使用stm32F10x,时钟配置成72M,那么这里需要填入72M。即需要跟实际情况保持一致。
2). 最后一定要将 0处打勾,并将其他bit位上的勾去掉,最好与此图保持一致,除CoreClock外。
在这里插入图片描述

2.4 烧录程序,并启动调试。可以看到,笔者在程序源码中插入了一句printf语句输出,然后按照下图,就可以看到程序的输出了。
在这里插入图片描述

  1. 综合版本使用scanf和printf
    3.1 添加retarget文件
    将如下代码保存成retarget.c,然后加入到工程中。
    #pragma import(__use_no_semihosting_swi)

struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;

int fputc(int ch, FILE *f)
{
return ITM_SendChar(ch);
}

volatile int32_t ITM_RxBuffer;
int fgetc(FILE *f)
{
while (ITM_CheckChar() != 1) __NOP();
return (ITM_ReceiveChar());
}

int ferror(FILE f)
{
/
Your implementation of ferror */
return EOF;
}

void _ttywrch(int c)
{
fputc(c, 0);
}

int __backspace()
{
return 0;
}
void _sys_exit(int return_code)
{
label:
goto label; /* endless loop */
}
3.2 编译运行
编译,烧录,运行,打开Debug (printf) viewer,就可以看到输入,参看下图
在这里插入图片描述

这里对retarget.c文件做几点说明.
1). 上面的代码实际是在X:\Keil\ARM\Startup\Retarget.c上修改而成的,scanf依赖的函数共有两个,fgetc和__backspace都需要实现,如果缺少__backespace函数,则scanf胡无法从Debug Viewer Dialog 窗口获取输入。另外上面提供的代码只是个demo,用于演示效果,用于生产时应该处理的更完善一些。见参考文献[1]

2). 函数ITM_SendChar,ITM_CheckChar,ITM_ReceiveChar在库文件CMSIS\Include\core_cm3.h中。

  1. 查看函数的符号引用关系,可以通过生成详细的map文件来查看。命令行增加 --verbose --list rtt.map选项即可生成名为rtt.map的文件。
  1. ITM与RTT结合(待实现)
    grissiom 写道:
    忽然想到,或许可以把这个半主机做成 device,然后 rt_console_set_device(“semi”) 就可以直接用半主机做 finsh/rt_kprintf 了…… 不知可行不可行……

prife: ITM的接收不知道是否支持中断,目前接收字符使用是轮询方式。如果是中断才有意义。这样可以把ITM设备做成一个 rtt 的device了,让finsh跑在 Debug printf Viewer窗口上。以后只要接一个jtag/SWD口就可以调试了,不用再接串口线了

参考文献
[1] MDK help. Indirect semihosting C library function dependencies
[2] MDK help ARM Development Tools.
Debugger Adapter User’s Guides
J-Link/J-Trace User’s Guide
Libraries and Floating Point Support Referencee
Libraries and Floating Point Support Guide
Linker Reference Guide

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/464990.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

5毛钱搞一个2.4GHz射频信号探测器

射频电子领域神秘而又朦胧&#xff0c;今天我们通过一个小小的射频检波电路来体验一下射频世界的魅力。实验目的制作一个 2.4 GHz 射频信号探测器&#xff0c;电路简单总成本不到 5 毛钱。该电路在靠近 2.4 GHz 无线信号时 LED 灯会闪烁。这是我用制作好的 2.4 GHz 射频信号靠近…

华为宣布:免费培养8000名嵌入式开发者!学习免费!实践免费!辅导免费!

真正的5G时代&#xff0c;万物互联各行各业都离不开智能物联网技术物联网 (IoT) 设备会生成海量数据通过分析这些数据可以提供业务洞察力优化业务决策&#xff0c;实现流程自动化也由于物联网的迅速兴起&#xff0c;专业性人才稀缺各阶层课程层出不穷&#xff0c;开发者眼花缭乱…

现在不要着急买房

我写这篇文章&#xff0c;是因为确实最近有人向我咨询买房的事&#xff0c;今天抽空想聊下这方面的事&#xff0c;如果观点不正确&#xff0c;欢迎评论说出你的想法。是前天&#xff0c;我一个同学咨询我买房的事情。我也直接说了&#xff0c;最近两年&#xff0c;把钱放在口袋…

解决vlc-android播放http视频退出问题

之前用vlc-android播放http视频,程序就自动退出了,尝试用ndk-gdb调试,但是一调试,就报 /home/administrator/code/vlc-android/extras/package/android/vlc-android/obj/local/armeabi/gdb.setup:4: Error in sourced command file:Remote communication error: Connection res…

受保护的属性无法直接读取

转载于:https://www.cnblogs.com/xiaobiaomei/p/9645795.html

MDK530编译出现ARM版本不符问题

1、用最新版的MDK530编译原来的代码出现问题&#xff1a;错误&#xff1a;“35; pragma import”是ARM编译器5的扩展&#xff0c;ARM编译器6不支持它[-Warmcc pragma import] 在仙女棒里面将ARM6修改为ARM5&#xff1a; 与此同时&#xff0c;在sys.c里面__asm void MSR_MSP(u3…

存储器Flash页、扇区、块的区别

作者 | strongerHuang微信公众号 | 嵌入式专栏大家都知道Flash是用于存储数据的存储器&#xff0c;但很多读者看到页(Page)、扇区(Sector)、块(Block)等这些单位时一脸懵逼&#xff0c;这到底是什么&#xff0c;有什么区别&#xff1f;下面就来讲讲关于Flash内部结构组织以及相…

volatile用法

许多程序员无法正确的理解C语言关键字volatile。这并不奇怪&#xff0c;大多数C原因书籍不过一两句一带而过。本文将告诉你如何正确使用它。 在C/C嵌入式代码中&#xff0c;你是否经历过下面的情况&#xff1a; ● 代码执行正常–直到你打开了编译器优化 ● 代码执行正常–直…

Linux 终端(TTY)

TTY 是 Teletype 或 Teletypewriter 的缩写&#xff0c;原来是指电传打字机&#xff0c;后来这种设备逐渐键盘和显示器取代。不管是电传打字机还是键盘显示器&#xff0c;都是作为计算机的终端设备存在的&#xff0c;所以 TTY 也泛指计算机的终端(terminal)设备。为了支持这些 …

印象笔记 MAC安装使用旧版本

印象笔记终于支持markdown了&#xff0c;赞&#xff01;第一个beta版用起来非常不错。提示更新安装新版本后保存markdown一直提示 “Note content is invalid.”&#xff0c;无法保存&#xff0c;无奈下只能安装旧版本印象笔记markdown 密码:wa23安装旧版本后&#xff0c;打开印…

你打开的那些网页,大概率是被监控了

你有没有这样的经历&#xff1a;当用手机搜索一件物品时&#xff0c;APP很快就会给你精准推荐这件物品。这并不是APP有多懂你&#xff0c;而是你的隐私已被APP监视了。哪怕你用的是“清理历史记录切换无痕模式”&#xff0c;后台依然可以记录你的搜索……还有&#xff0c;长夜漫…

操作系统常见面试题

1.进程的常见状态&#xff1f;以及各种状态之间的转换条件&#xff1f; 就绪&#xff1a;进程已处于准备好运行的状态&#xff0c;即进程已分配到除CPU外的所有必要资源后&#xff0c;只要再获得CPU&#xff0c;便可立即执行。执行&#xff1a;进程已经获得CPU&#xff0c;程序…

加强型的记录集权限(数据集权限、约束表达式设置功能)实现方法界面参考...

1。功能要求相对复杂的信息管理系统&#xff0c;有比较严格的权限管理设置的需求。例如业务管理系统中的一个角色只能查看金额小于500万的合同&#xff0c;而且只能看自己所在部门的合同&#xff0c;系统要求限制条件能灵活设置过滤所能看到的&#xff0c;所能操作的数据项&…

性能强悍的MCU,主频干到GHz

目前有两款高性能MCU印象深刻&#xff0c;不是多核心就是主频上1GHz。这也许是为了满足一些高数据吞吐量但仍需高实时性的需求吧。比如机械臂。一、第一款是来自于TI的Sitara AM2x&#xff0c;如型号为AM2434的单片机&#xff0c;拥有四个800MHz的核心&#xff0c;官方称为双核…

Unity3D_(游戏)控制物体的上、下、左、右移动

通过键盘上↑、↓、←、→实现对物体的控制 using System.Collections; using System.Collections.Generic; using UnityEngine;public class Gary_Text : MonoBehaviour {public Transform WuTi;public float speed 1;// Use this for initializationvoid Start () {}// Upda…

糟糕的C语言睡眠排序算法

不知道大家知道这个算法没有&#xff0c;就是靠睡觉完成排序的。比如数字1 4 3&#xff0c;第一个数字1的时候&#xff0c;创建一个线程&#xff0c;然后让线程休眠1个时间单位&#xff0c;依次是 4 和 3个单位。因为睡眠的时间不同&#xff0c;线程醒的时间也不同。3会比4先醒…

写给小白看的,逆向工程怎么上路?

什么是逆向工程大家好&#xff0c;我是写代码的篮球&#xff0c;这篇文章转自小白哥的文章。给大家出一道思考题&#xff1a;用C语言设计一个程序&#xff0c;验证输入的密码是否是“12345678”&#xff0c;如果验证成功&#xff0c;就输出“success”&#xff0c;如果验证失败…

线程、同步与锁——Mutex想说爱你不容易

除了Lock&#xff08;&#xff09;、Monitor之外&#xff0c;我们最长用的就是Mutex了&#xff0c;但是玩不好Mutex就总会造成死锁或者AbandonedMutexException&#xff08;我就玩的不怎么好&#xff0c;在并发性访问测试的时候总是遇到关于Mutex的问题&#xff0c;各位线虫见笑…

STM32F4 串口DMA

串口DMA方式收发 笔者使用的是STM32F407VET6&#xff0c;共包含6路串口&#xff0c;页尾处程序已将全部串口的DMA收发配置完成&#xff0c;本文仅以串口1为例进行讲解。&#xff08;查看代码可直接跳至第二节或页尾处下载&#xff09; 1 STM32F4 DMA 简介 DMA&#xff0c;全称为…

由马化腾谈“微博修改功能”,看什么是优秀的产品经理

我仔细阅读过马化腾的的简历&#xff0c;他是一位技术出身的企业家。也是腾讯最大的产品经理,大家都知道产品经理的对产品的重要性那是不言而喻的&#xff0c;而产品是公司的灵魂。 今天早上起床&#xff0c;看到马化腾先生更新的微博。有位网络公司的CTO建议腾讯微博加一个修改…