当前位置:网站首页>J-link v9 使用技巧之虚拟串口功能
J-link v9 使用技巧之虚拟串口功能
2022-04-23 01:43:00 【无痕幽雨】
使用ITM机制实现调试contex-M系列,实现printf与scanf。
1. ITM简介
ITM机制是一种调试机制,是新一代调试方式,
ITM是ARM Cortex-M系列内核芯片中的一种全新的调试功能,可以方便的通过调试器来实现printf调试功能。来自STM32中文参考手册的介绍:
ITM ( 指令跟踪微单元 instrumentation trace macrocell):ITM是一应用驱动的跟踪源,它支持printf类的调试手段来跟踪操作系统(OS)和应用事件,并发布判定的系统信息。ITM以包的形式发布跟踪信息,它由以下部分组成:
- 软件跟踪:软件可以通过直接写ITM激发寄存器来发布包信息。
- 硬件跟踪:ITM会发布由DWT产生的信息包。
- 时间戳:时间戳被发布到相应的包上。ITM包含一个21位的计数器以产生时间戳。Cortex-M3的时钟或串行线观测器(Serial Wire Viewer)的位时钟率给计数器提供时钟。由ITM发送的信息包输出到TPIU(Trace Port Interface Unit),TPIU再添加一些额外的包(参考TPIU),然后输出完整的包序列给调试器。用户在设置或使用ITM之前,必需先使能异常调试和监视控制寄存器(Debug Exception and Monitor Control Register)的TRCEN位。
在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之后推出的新一代调试机制。现在我们来尝试一下这种方式调试。
2. stm32使用ITM调试
2.1 硬件连接
ITM机制要求使用SWD方式接口
1>一般的四线SWD方式(VCC SDCLK,SDIO,GND)是不行的。需要多连接SWO线,
2>标准的20针JTAG接口是可以的,只需要在MDK里设置使用SWD接口即可。
2.2 添加重定向文件
将下面的文件保存成retarget.c文件,并添加到工程中。这里对这个文件简单说明一下,要知道我们的程序是在MCU上运行的,为什么printf可以输出到MDK窗口里去呢?这是因为 标准库中的printf实际上调用 fputc实现输出,所以我们需要自己编写一个fputc函数,这个函数会借助ITM(类似于USART)提供的寄存器,实现数据的发送,仿真器会收到这些数据,并发往PC机。
-
#include <stdio.h>
-
#include <stdint.h>
-
#include "stm32f4xx.h"
-
#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 */
-
}
这里对retarget.c文件做几点说明.
1). 上面的代码实际是在X:\Keil\ARM\Startup\Retarget.c上修改而成的,scanf依赖的函数共有两个,fgetc和__backspace都需要实现,如果缺少__backespace函数,则scanf胡无法从Debug Viewer Dialog 窗口获取输入。
2). 函数ITM_SendChar,ITM_CheckChar,ITM_ReceiveChar在库文件CMSIS\Include\core_cm3.h中。
2.3 添加重定向文件的另一种方法
µVision User's Guide: Debug (printf) Viewer
2.4 配置J-Link的初始化配置文件
将下面文件放置在你的工程下,并取任意名称,这里笔者取名为 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 (c) 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) {
-
// <h> Debug MCU Configuration
-
// <o1.0> DBG_SLEEP <i> Debug Sleep Mode
-
// <o1.1> DBG_STOP <i> Debug Stop Mode
-
// <o1.2> DBG_STANDBY <i> Debug Standby Mode
-
// <o1.5> TRACE_IOEN <i> Trace I/O Enable
-
// <o1.6..7> TRACE_MODE <i> Trace Mode
-
// <0=> Asynchronous
-
// <1=> Synchronous: TRACEDATA Size 1
-
// <2=> Synchronous: TRACEDATA Size 2
-
// <3=> Synchronous: TRACEDATA Size 4
-
// <o1.8> DBG_IWDG_STOP <i> Independant Watchdog Stopped when Core is halted
-
// <o1.9> DBG_WWDG_STOP <i> Window Watchdog Stopped when Core is halted
-
// <o1.10> DBG_TIM1_STOP <i> Timer 1 Stopped when Core is halted
-
// <o1.11> DBG_TIM2_STOP <i> Timer 2 Stopped when Core is halted
-
// <o1.12> DBG_TIM3_STOP <i> Timer 3 Stopped when Core is halted
-
// <o1.13> DBG_TIM4_STOP <i> Timer 4 Stopped when Core is halted
-
// <o1.14> DBG_CAN_STOP <i> CAN Stopped when Core is halted
-
// </h>
-
_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机制,必须要打开BIT0。
打开MDK工程,按照下图修改。
![]() |
2.5MDK中对J-Link的配置
![]() |
下图中注意两点
1). 这里的CoreClock是120M,因为使用的是stm32F207VG这款芯片,并且时钟配置为120M,所以这里填入120M,如果你使用stm32F10x,时钟配置成72M,那么这里需要填入72M。即需要跟实际情况保持一致。
2). 最后一定要将 0处打勾,并将其他bit位上的勾去掉,最好与此图保持一致,除CoreClock外。
![]() |
2.6 烧录程序,并启动调试。可以看到,笔者在程序源码中插入了一句printf语句输出,然后按照下图,就可以看到程序的输出了。
![]() |
3. 编译运行
编译,烧录,运行,打开Debug (printf) viewer,就可以看到输入,参看下图
![]() |
4.虚拟串口功能配置
J-link的虚拟串口功能默认是关闭的,可以在J-link Commander下打开。
如果是V9以上,输入vcom enable。 如果出现以下提示,说明配置成功,直接将Jlink重新上电即可。
如果出现以下提示:The connected probe does not support VCOM functionality,重新输入以下指令:
power on
power off
vcom enable
如果不成功就重新上电多试几次,J-link Commander也要重新打开 。
没有提示错误则说明一切正常,将J-link重新上电,可以看到驱动会重新加载,设备管理器里多出了一个串口设备,说明设置成功。 该串口可以直接当做USB转串口设备使用,不影响J-link调试程序。
若需要关闭该功能,输入 vcom disable即可。
版权声明
本文为[无痕幽雨]所创,转载请带上原文链接,感谢
https://blog.csdn.net/wuhenyouyuyouyu/article/details/121414885
边栏推荐
- 力扣(LeetCode)112. 路径总和(2022.04.22)
- Technology cloud report: cloud computing has entered the "second half". Where is the way out for domestic cloud?
- Itextsharp displays Chinese fonts
- 什么时候应该编写单元测试?什么是TDD?
- 哪些代码需要做单元测试?
- 《维C中国》乡村助农暖人心第三站嘉宝果农场
- VSCODE + PHP Debug + 名字空间指引
- Unity结合iTextSharp生成PDF 准备dll
- Counting garlic guest: the solution of the equation
- 学习方法与职业发展指南(2022年版)
猜你喜欢
计蒜客:数独(DFS)
Full Permutation (DFS and next_permutation solution)
力扣(LeetCode)112. 路径总和(2022.04.22)
Redis implements distributed locks
最长公共子序列(记录路径版)
关于C4D动画如何导入Lumion
安装mysql出问题求解决
Self taught programming, don't read theory books foolishly, programmer: it's all left over by others
客户端项目管理经常面临的挑战
JSP basic knowledge summary
随机推荐
Counting garlic customers: Sudoku (DFS)
Gbase 8s存儲結構簡介及空間管理
Is the stable currency a super opportunity to accelerate the death of the public chain or replace BTC?
找数字(DFS)
Blocking type of gbase 8s concurrency control
[course summary] Hello harmonyos series of courses, take you to zero foundation introduction
什么是布尔类型?
Realize the function of progress bar through layerdrawable
Gbase 8s数据库日志简介及管理
Redis实现分布式锁
Planning garlic guest (outing) (DFS and BFS solution of dyeing block problem)
Introduction to gbase 8s shared memory buffer pool
. net (c) MySQL conn.open() reports an error: solution to SSL connection error
VSCODE + PHP Debug + 名字空间指引
Custom numeric input control
Full Permutation (DFS and next_permutation solution)
计蒜客:数独(DFS)
LSF的常用使用命令总结
Jerry's factors that usually affect CPU performance test results are: [article]
Gbase 8s fragment table management operation