在线时间7 小时
UID2113301
注册时间2015-5-13
NXP金币0
该用户从未签到
注册会员

- 积分
- 100
- 最后登录
- 2018-4-11
|
来源:https://www.eefocus.com/constyu/blog
在嵌入式调试中,使用串口打印调试信息是一种十分常用的调试手段,但是在很多应用中,如果板子上串口引脚没有引出或者IO资源紧张时,该如何实现信息的打印呢?
在PC端编写C语言时,printf可以向控制台输出,scanf可以从控制台获取输入,这里的printf/scanf都是标准库函数,利用操作系统的这些函数,我们可以很方便的调试程序。在嵌入式设备开发时上,IAR/MDK等开发工具也都提供了printf/scanf标准库函数,那么这些函数是否可以直接使用呢? 那么问题来了,printf输出到哪里呢?并且大部分情况下,MCU系统也没有键盘,又如何使用scanf实现输入呢?
于是著名的Semi-Hosting(半主机调试机制)就诞生了,其原理是:通过借助J-link/U-Link等仿真器,使得单片机可以借助PC机的屏幕以及PC机的键盘实现printf的输出和scanf的按键获取。如下的hello world程序。
- #include <stdio.h>
- int main()
- {
- //硬件初始化
- //....
- printf("hello, world");
- for(;;);
- }
复制代码
将该程序烧录到单片机中后,仿真器连接接单片机与PC,开始在线调试后,那么这个程序会将"Hello, world"输出到PC机上,对于IAR开发工具,默认会输出到其Terminal IO窗口中显示。这就相当于,单片机借助了PC机的显示/输入设备实现了自己的输出/输入。这种方式无疑可以方便程序开发者调试。
在网上能搜索***“printf terminal IO”,可以看到很多基于STM32的应用,那在Kinetis 的SDK中如何实现呢?尽管IAR、Keil等IDE中标准库stdio.h的printf默认都是输出到Terminal IO,但事实上在SDK的例程代码中往往都把printf默认重定向到了硬件的UART串口。
所以如果想使能Semi-Hosting半自主调试功能,就需要disable SDK中的printf重定向,使之恢复默认打印到Terminal IO。那问题来了,SDK中究竟是在哪里重写的printf呢?很自然的想法是找到Printf的实现,但遗憾的是printf的实现是放在lib库中的,无法找到其实现细节,也有网友指出重写fputc,但是SDK中实现的机制并非是这样。于是经过一番求证,找到解决办法:
找到fsl_debug_console.c 的line323,使用#if 0 #endif或者其他方法注释掉line324-line374行,如下:
- #if 0
- #pragma weak __write
- size_t __write(int handle, const unsigned char * buffer, size_t size)
- ………….
- #pragma weak __read
- size_t __read(int handle, unsigned char * buffer, size_t size)
- /* Receive data.*/
- s_debugConsole.ops.rx_union.Receive(s_debugConsole.base, buffer, size);
- return size;
- }
- #endif
复制代码
在IAR中保存修改,然后重新编译下载到MCU,打开View->Terminal IO,如下图运行程序可以看到printf打印的内容输出到IAR的Terminal IO,而且可以借助电脑的键盘得到输入信息。从而实现在不占用硬件串口的基础上,灵活的输出调试信息,并实现人机交互,大大提高调试的效率。

|
|