Keil环境下使用Jlink仿真器实现printf输出

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之后推出的新一代调试机制。现在我们来尝试一下这种方式调试。

2. 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+4*n)))  
#define ITM_Port16(n)   (*((volatile unsigned short*)(0xE0000000+4*n)))  
#define ITM_Port32(n)   (*((volatile unsigned long *)(0xE0000000+4*n)))  
#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.3 配置JLINK的初始化配置文件

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

/******************************************************************************/  
/* retarget.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机制,必须要打开BIT5。

2.4 打开MDK工程,按照下图修改。

选择上文添加的jlink初始化文件retarget.ini
在这里插入图片描述
ITM输出模式必须配置为SWD接口输出
在这里插入图片描述
注意:
1). 这里的CoreClock是72M,因为笔者使用的是stm32F103这款芯片,并且时钟配置为72M,所以这里填入72M,需要跟实际情况保持一致。
2). 最后一定要将 0处打勾,并将其他bit位上的勾去掉,最好与此图保持一致,除CoreClock外
在这里插入图片描述

2.5 烧录程序,并启动调试。

可以看到,笔者在程序源码中插入了一句printf语句输出,然后就可以在Debug (printf)Viewer 窗口看到程序的输出了
在这里插入图片描述

3. 总结

通过上述配置即可在keil环境中通过Jlink实现通过串口打印/终端输出一样的效果,非常便于没有预留串口的设备进行程序调试。

<think>好的,用户想了解Keil使用盗版JLink的后果以及合法的替代方案。首先,我需要回忆之前提供的引用内容,看看有哪些相关信息。引用[1]提到盗版JLink可能无法使用新版本软件,需要安装旧版驱动。引用[2]则说明高版本Keil(如5.40)可能因为JLink驱动导致闪退,需要替换旧版驱动。引用[3]涉及使用JLink时的硬件连接和设置。 接下来,用户关心的是使用盗版JLink的后果。根据常见情况,盗版硬件可能被软件检测到,导致功能限制或无法使用。比如,新版的JLink软件可能拒绝连接盗版设备,或者弹出警告信息,影响开发效率。此外,盗版产品可能存在稳定性问题,比如连接不稳定、下载失败等,甚至可能损坏目标设备。 然后是合法替代方案。正版JLink价格较高,但用户可能有预算限制。所以需要推荐一些低成本或免费的方案。比如,使用开源的ST-Link或DAPLink仿真器,这些通常价格较低且兼容性较好。另外,某些MCU厂商提供的专用工具,如ST的ST-Link,也可以作为替代。此外,使用旧版JLink驱动可能是一个临时解决方案,但需要确保来源可靠,避免安全风险。 还要考虑用户可能遇到的问题,比如如何在Keil中配置替代仿真器,是否需要修改项目设置,或者是否需要更新固件等。根据引用[3],使用SWD接口和正确连接SWO线可能影响功能,比如printf输出,需要确保硬件连接正确。 最后,用户可能需要步骤指导,例如如何安装旧版驱动,替换文件的具体操作,或者如何设置其他仿真器。需要将这些信息整理成清晰的步骤,并注意提醒用户注意法律风险,推荐合法工具。</think>### Keil使用盗版JLink的后果及解决方案 #### 一、使用盗版JLink的潜在风险 1. **功能限制**: 盗版JLink可能无法支持新版软件(如JLink V7以上版本),导致Keil调试时闪退或连接失败[^1]。部分功能(如高速下载、SWO跟踪)可能受限,且无法通过官方固件升级。 2. **稳定性问题**: 盗版硬件可能因驱动不匹配导致调试过程中断,例如Keil 5.40版本因JLink驱动冲突引发闪退[^2]。 3. **法律风险**: 商业项目中使用盗版工具可能面临法律追责,尤其是涉及产品认证时。 #### 二、临时解决方案(针对已有盗版设备) 1. **降级JLink驱动**: 从Segger官网下载旧版驱动(如V6.48b),替换Keil安装目录下的驱动文件(路径:`ARM\Segger`),并禁用自动更新[^1]。 2. **修改接口模式**: 在Keil中强制使用SWD接口(而非JTAG),可减少部分兼容性问题[^3]。需确保硬件连接包含SWO线(若需ITM调试输出)。 #### 三、合法替代方案 1. **开源调试器** - **DAPLink/CMSIS-DAP**: 支持SWD协议,价格低廉(约10-30元),兼容Keil且无版权风险。 - **ST-Link/V2**: 适用于ST系列芯片,支持SWD/JTAG,官方提供免费固件升级。 2. **正版JLink EDU** Segger提供教育版JLink(价格约$60),功能与商业版相同,仅限非商业用途。 3. **厂商专用工具** - **NXP的LPC-Link** - **Raspberry Pi Picoprobe**(需自行搭建) #### 四、操作示例(替换旧版驱动) ```plaintext 步骤: 1. 下载旧版JLink驱动:https://www.segger.com/downloads/jlink 2. 解压后替换Keil安装目录下`ARM\Segger`中的文件 3. 重启Keil,在Debug设置中选择"J-Link/J-Trace"并切换为SWD模式 ``` #### 五、注意事项 - 使用盗版工具可能导致长期维护成本增加(如调试时间浪费)。 - 开源工具需检查目标芯片支持情况,例如DAPLink对部分厂商MCU需手动配置。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值