[学习资料] 【凌鸥创芯电机开发板LKS32MC071CBT8评测报告】2 例程补全之MDK下printf的实现

[复制链接]
1392|0
 楼主| 6552918 发表于 2023-7-30 21:29 | 显示全部楼层 |阅读模式
本帖最后由 6552918 于 2023-7-30 21:33 编辑

#申请原创# #技术资源#[url=home.php?mod=space&uid=760190]@21小跑堂 [/url]
在测评芯片时,使用例程测试了下芯片,发现原厂提供的例程库是在有点太简陋了,很对基础功能都不全,无奈只好针对例程库的不足现先来个基础功能补全,首先将调试时最常用的调试输出printf给实现了,相关实现过程如下
添加实现源码,在工程目录下添加printf.c文件和printf.h文件
9fa410df808bdf21b4338c7793291a44
5cc929067cc09cf71ad27d340e6cf30f
在工程内添加源码,头文件路径工程已经添加完就不用再添加了
63453e703b922c8c3f314978c4825644
源码文件支持几种使用情况,分为 使用微库 和 不使用微库;使用 编译器器5 和 使用编译器6
这两类的组合,一共可以有4种不同的使用组合方式
相关的组合使用说明如下:
微库的使用不和不使用由开发环境UseMicroLIB决定,勾选此项为使用微库,不勾选此项为不使用微库时,同时printf内的#define NOT_USE_Microlib要使能定义
2bbb22316199258a179ae3240e907266
91474a0a43fa40d6f3132ed187173114
使用微库时,同时printf内的#define NOT_USE_Microlib要取消定义
1da3b486b15338987eb6d05a7e8ae6a0
a8eb1d8193e946097bb89952db57ea8d
使用编译器5时,选择如下:
bff83ed338fc689013816d7882a92a43
使用编译器6时,选择如下:
bcbae68959f3d17d7b18541d786af8ff
根据上述2类的不同组合方式,可以灵活的根据实际情况进行使用
上诉方式是采用串口来实现printf的
使用了串口初始化和先关的IO初始化
a29cc2565dee30e1a23969c928dbdce0
和相关中断初始化处理
b1be15f0bf18a8f1328bc30424164674
完成上述初始化后就可以使用printf了,先关测试代码如下
6da1cab8a7080f81ffd570afe41b85eb
输出效果如下
ca21f10cae0653426811363195a73373
在MDK下还有一种万能printf的实现方法,不占用串口,不挑仿真器,这种方法有如下特点:
支持所有的调试仿真器,哪怕自己手搓的CMSIS-DAP都行;
MDK
原生功能,连CMSIS-Pack都不用安装;
点几下鼠标就可以通过RTE完成部署;
除了简单的初始化函数外,无需手动插入代码;
可以将你的printf输出直接打印在MDK的Debug (printf) View窗口中。
首先我们准备正常的工程
打开工程后 打开RTE配置
5ce9367ffc3844fb6d3a0fd66888e375
找到并展开Compiler选项卡,勾选Event Recorder,并确保Variant下拉列表选中的是默认的DAP。
bc5ea558b2633ce5227f87f3cf5e2923
展开 Compiler 下的 I/O ,勾选STDOUT,并在 Variant 下拉列表中选择 EVR——这里 EVR 是 Event Recorder 的缩写。单击确定后,我们会在工程管理器中看到以下的内容:
167a23da180299d2d746c49d9d5e7b79
至此,所需的工具都已经成功地加入到工程中了。
虽然这里EventRecorderConf.h 是一个可以编辑的状态,但实践中,我们基本不用去碰他——使用默认配置即可。其中相关配置好后可实现简单的程序运行时长的测量,但不是本贴的主要内容,在此不详细介绍。
76ddcdf74645d72a1a1fbe21179df1ce
然后 勾选使用微库选项
5e0838ca716c6270083ff2d387090f0f
接着我们再程序中添加相关的初始化操作
在包含 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
6817ffcf0c53e329809474fac45e485d
运行后,可以在 Debug (printf) View窗口中看到如下的结果:
aeffc6460e9b233c8cfcba75f1ec156e
但在进入仿真时,有个警告提示
7eb081fb880c8b798cc86378c5ca7eb5
并且 printf 输出似乎不是很稳定——时有时无,别慌,这个问题接着盘它!
打开工程配置窗口“Options for Target”,切换到“Linker”选项卡:
首先,一定要确保你勾选了图中的“Use Memory Layout from Target Dialog”选项。在这一前提下,再次取消对它的勾选:
ffca7fc8cf467cd0b0574ddca81cbb1e
f7c55d1c74892a0f3daa6fae24e2925b
我们会看到,MDK基于当前的Memory Layout,为我们在Objects目录下生成了一个与工程同名的链接脚本(比如图中的工程名叫LK_StdPeriph,因此生成的链接脚本为 LK_StdPeriph.sct)。
46ace59a2153388ed17a4f0bf1f85ed0
“Linker”选项卡,单击 Edit 按钮,可以看到脚本的内容:
33da5d97a309657fdf53c7279e80da90
该文件是系统自动生成的,如果我们不移动它的位置,那么只要哪次手抖勾选了“Use Memory Layout from Target Dialog”,它的内容就会立即被覆盖掉——意味着我们在后续步骤中所做的修改就会付诸东流。
为了避免该问题,应该将它从 Object 目录中移动到工程目录下。 1cc2e3757c5e1943d25045e3231a2eb2
这样在勾选Use Memory Layout from Target Dialog”选项时,Scatter File使用的是Objects目录下的.sct文件
4fb36be2b1ee0f1c56e3b945ddc924c5
272469c30411b53a6829c09a329e5ea6
在不勾选Use Memory Layout from Target Dialog”选项时,Scatter File使用的是工程目录下的.sct文件
73b57ace40c23140d3a17c3a6eb5e959
15a45e0d372585753088b4f3c9b01e7f
在不勾选Use Memory Layout from Target Dialog”选项时,“Linker”选项卡,单击 Edit 按钮在 RW_IRAM1 后面追加如下的代码:  ZI_RAM_UNINIT +0 UNINIT {
        .ANY (.bss.noinit)
  }
92a6d1ff51777d5c65856ef8711fc44a
保存后重新编译,再次进入 Debug 模式,问题就应该解决了。
这里步骤的核心思想是在 scatter script 内紧接着为 RW和ZI的 execution region为 .bss.noinit 提供一个属性为UNINIT的专属execution region。
MDK 通过 EventRecorder 为我们提供了一个通用便捷的方式来重定向 printf——无论你使用什么调试仿真器。使用该方法后将不再限制用户必须使用 J-Link 之类的工具,和其他限制。
最后强调一下,EventRecorder只在调试阶段有意义,产品发布时,就不要使用了。
至此,在MDK上实现了printf的通用串口输出和不依赖硬件资源的printf方法,**对大家有所帮助。
例程源码如下: Demo27_printf(RTE).zip (2.06 MB, 下载次数: 5) Demo26_printf.zip (1.37 MB, 下载次数: 5)

您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

102

主题

1290

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部