打印
[资源分享]

【杰发科技AC7802x测评】2 MDK里隐藏的万能printf方法

[复制链接]
462|22
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 6552918 于 2023-6-30 17:23 编辑

#申请原创# #技术资源#   @21小跑堂

我们平时调试时都会用到printf输出调试信息,使用printf有很多种重定向的实现方法,用的最多的是串口的,有用SWO的,还有用JLINK RTT的,但上述几种方法都是有限制的,串口用于调试就不能被应用占用,SWO需要内核支持才行,JLINK RTT必须使用JLINK工具才能使用,有没有其他方式呢?
下面为大家介绍一种MDK赠送的万能printf输出调试的方法,不再受上述条件限制,这种方法有如下特点:
支持所有的调试仿真器,哪怕自己手搓的CMSIS-DAP都行;
MDK原生功能,连CMSIS-Pack都不用安装;
点几下鼠标就可以通过RTE完成部署;
除了简单的初始化函数外,无需手动插入代码;
可以将你的printf输出直接打印在MDK的Debug (printf) View窗口中。
接下来我在AC7802上展示实现过程,让我们发车。
首先找一个基础例程,我用的是01_GPIO_Basic

打开工程后 打开RTE配置

因为例程里使用了串口重用映射的printf,我们需要先关掉原工程内的串口printf映射。操作如下


找到并展开Compiler选项卡,勾选Event Recorder,并确保Variant下拉列表选中的是默认的DAP。

展开 Compiler 下的 I/O ,勾选STDOUT,并在 Variant 下拉列表中选择 EVR——这里 EVR 是 Event Recorder 的缩写。单击确定后,我们会在工程管理器中看到以下的内容:

至此,所需的工具都已经成功地加入到工程中了。
虽然这里EventRecorderConf.h 是一个可以编辑的状态,但实践中,我们基本不用去碰他——使用默认配置即可。其中相关配置好后可实现简单的程序运行时长的测量,但不是本贴的主要内容,在此不详细介绍。

然后 勾选使用微库选项

接着我们再程序中添加相关的初始化操作
在包含 main() 函数的C代码文件中,按照如下的格式添加对头文件的包含:
#include <RTE_Components.h>
#if defined(RTE_Compiler_EventRecorder)
#   include <EventRecorder.h>
#endif
在 main() 函数中添加对EventRecorder服务的初始化:
#if defined(RTE_Compiler_EventRecorder) \
&& defined(RTE_Compiler_IO_STDOUT_EVR)
EventRecorderInitialize(0, 1);
#endif

运行后,可以在 Debug (printf) View窗口中看到如下的结果:

但在进入仿真时,有个警告提示

并且 printf 输出似乎不是很稳定——时有时无,别慌,这个问题接着盘它!
打开工程配置窗口“Options for Target”,切换到“Linker”选项卡:
首先,一定要确保你勾选了图中的“Use Memory Layout from Target Dialog”选项。在这一前提下,再次取消对它的勾选:

我们会看到,MDK基于当前的Memory Layout,为我们在Out目录下生成了一个与工程同名的链接脚本(比如图中的工程名叫Demo,因此生成的链接脚本为 Demo.sct)。

“Linker”选项卡,单击 Edit 按钮,可以看到脚本的内容:

该文件是系统自动生成的,如果我们不移动它的位置,那么只要哪次手抖勾选了“Use Memory Layout from Target Dialog”,它的内容就会立即被覆盖掉——意味着我们在后续步骤中所做的修改就会付诸东流。
为了避免该问题,应该将它从 Object 目录中移动到工程目录下。
这样在勾选Use Memory Layout from Target Dialog”选项时,Scatter File使用的是Objects目录下的.sct文件


在不勾选Use Memory Layout from Target Dialog”选项时,Scatter File使用的是工程目录下的.sct文件


在不勾选Use Memory Layout from Target Dialog”选项时,“Linker”选项卡,单击 Edit 按钮在 RW_IRAM1 后面追加如下的代码:  ZI_RAM_UNINIT +0 UNINIT {
.ANY (.bss.noinit)
  }

保存后重新编译,再次进入 Debug 模式,问题就应该解决了。
这里步骤的核心思想是在 scatter script 内紧接着为 RW和ZI的 execution region为 .bss.noinit 提供一个属性为UNINIT的专属execution region。
MDK 通过 EventRecorder 为我们提供了一个通用便捷的方式来重定向 printf——无论你使用什么调试仿真器。使用该方法后将不再限制用户必须使用 J-Link 之类的工具,和其他限制。
最后强调一下,EventRecorder只在调试阶段有意义,产品发布时,就不要使用了。




使用特权

评论回复

相关帖子

沙发
yangxiaor520| | 2023-7-1 11:58 | 只看该作者
学到一招,谢谢楼主分享。

使用特权

评论回复
板凳
modesty3jonah| | 2023-7-5 22:30 | 只看该作者
可能涉及到配置串口相关的参数(如波特率、数据位、停止位等),并使终端或串口能够接收和显示输出数据。

使用特权

评论回复
地板
6552918|  楼主 | 2023-7-5 22:32 | 只看该作者
modesty3jonah 发表于 2023-7-5 22:30
可能涉及到配置串口相关的参数(如波特率、数据位、停止位等),并使终端或串口能够接收和显示输出数据。 ...

和串口没关系

使用特权

评论回复
5
saservice| | 2023-7-6 12:28 | 只看该作者
在MDK(Keil MDK-ARM)中,使用printf函数进行调试输出是一种常见的方法。

使用特权

评论回复
6
6552918|  楼主 | 2023-7-6 12:37 | 只看该作者
saservice 发表于 2023-7-6 12:28
在MDK(Keil MDK-ARM)中,使用printf函数进行调试输出是一种常见的方法。

我的方法是不限制调试器的实现方法

使用特权

评论回复
7
pmp| | 2023-7-6 15:14 | 只看该作者
printf() 函数用于将格式化的数据打印到标准输出设备(通常是终端或串口),以便进行调试和输出显示。

使用特权

评论回复
8
burgessmaggie| | 2023-7-6 15:34 | 只看该作者
printf函数是一个标准C库函数,用于在控制台或终端上输出文本。

使用特权

评论回复
9
uiint| | 2023-7-6 15:53 | 只看该作者
在mdk 中用printf,需要同时重定义fputc函数

使用特权

评论回复
10
uptown| | 2023-7-6 16:11 | 只看该作者
在使用 MDK 的时候,可以使用标准的 C 语言函数 printf() 来进行调试和输出。

使用特权

评论回复
11
zerorobert| | 2023-7-6 16:38 | 只看该作者
在代码中添加stdio.h头文件,该头文件包含了printf函数的声明和其他标准输入输出函数的定义。

使用特权

评论回复
12
mikewalpole| | 2023-7-6 16:48 | 只看该作者
keil uvision 怎样查看printf结果

使用特权

评论回复
13
cashrwood| | 2023-7-6 16:58 | 只看该作者
如何在mdk中使用printf              

使用特权

评论回复
14
6552918|  楼主 | 2023-7-6 20:57 | 只看该作者
uiint 发表于 2023-7-6 15:53
在mdk 中用printf,需要同时重定义fputc函数

我的这种方法,重定义的操作,库文件已经完成了,不需要自己去实现。

使用特权

评论回复
15
6552918|  楼主 | 2023-7-6 20:58 | 只看该作者
mikewalpole 发表于 2023-7-6 16:48
keil uvision 怎样查看printf结果

debug viewer内查看输出

使用特权

评论回复
16
6552918|  楼主 | 2023-7-6 20:59 | 只看该作者
cashrwood 发表于 2023-7-6 16:58
如何在mdk中使用printf

本帖就是 在mdk中使用printf的一种方法   

使用特权

评论回复
17
tpgf| | 2023-7-7 11:31 | 只看该作者
请问楼主,万能printf方法指的是哪方面比较万能呢

使用特权

评论回复
18
wowu| | 2023-7-7 12:16 | 只看该作者
就是说这个printf函数的兼容性非常好 是吗  

使用特权

评论回复
19
paotangsan| | 2023-7-7 12:40 | 只看该作者
在使用这个方法的时候,我们如何定义是打印到哪里了呢

使用特权

评论回复
20
6552918|  楼主 | 2023-7-7 12:44 | 只看该作者
tpgf 发表于 2023-7-7 11:31
请问楼主,万能printf方法指的是哪方面比较万能呢

不限制任何调试器

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:北京汇冠触摸技术有限公司/电子工程师
简介:电子工程师,嵌入式应用爱好者。

100

主题

1186

帖子

5

粉丝