用GDB动态打印快速实现嵌入式系统的调试输出

用GDB动态打印快速实现嵌入式系统的调试输出

print是最常用的调试手段之一。嵌入式系统通常使用串口来输出print消息,而且通常需要开发人员自行实现。这里介绍一种使用GDB动态打印命令dprintf来实现print消息的输出,这种方法非常便捷,不需要编写串口驱动就可以print消息到宿主机。

http://blog.csdn.net/zoomdy/article/details/50622698
mingdu.zheng at gmail dot com

dprintf使用示例

以FreeRTOS的一个示例程序作为示范。

#include <FreeRTOS.h>
#include <task.h>

void vPrintString(const char *str) {
	(void) str;
}

void vTaskFunction(void *pvParameters) {
	char *pcTaskName = (char *) pvParameters;

	for (;;) {
		vPrintString(pcTaskName);
		vTaskDelay(250 / portTICK_RATE_MS);
	}
}

static const char * const pcTextForTask1 = "Task 1 is running\r\n";
static const char * const pcTextForTask2 = "Task 2 is running\t\n";

int main(void) __attribute__((noreturn));
int main(void) {
	xTaskCreate(vTaskFunction, "Task 1", 1000, (void* )pcTextForTask1, 1, NULL);
	xTaskCreate(vTaskFunction, "Task 2", 1000, (void* )pcTextForTask2, 2, NULL);
	vTaskStartScheduler();

	for (;;);
}

这是《Using The FreeRTOS Real Time Kernel》这本书的Example4示例程序。程序功能很简单,创建两个相同的任务,每隔250ms打印一条消息。程序使用vPrintString函数来打印输出。按惯例,应当将vPrintString实现为对串口驱动的调用,通过串口来发送需要print的消息。但是这里的vPrintString函数实现是空的。通过GDB加载执行这个程序,在执行到main后,输入

dprintf vPrintString,"%s",str

然后继续执行程序,就可以在GDB窗口中看到目标程序打印的消息

Task 2 is running	
Task 1 is running
Task 2 is running	
Task 1 is running
Task 2 is running	
Task 1 is running
Task 2 is running	
Task 1 is running

dprintf用法

dprintf location,template,expression [,expression ...]

location:为需要打印消息的位置,可以是函数名、行号、文件名:行号等。
template:打印的格式,相当于printf函数的第一个参数。
expression:格式化消息的数据源。
举几个例子

dprintf main.c:4,"%s print %s\n",pxCurrentTCB->pcTaskName,str
dprintf xTaskIncrementTick,"xTickCount=%d\n",xTickCount

更详细的用法请参考Dynamic Printf

dprintf原理

dprintf命令会设置一个特殊的断点,这可以通过info break查看

info break
Num     Type           Disp Enb Address    What
1       dprintf        keep y   0x08000a76 in xTaskIncrementTick at tasks.c:1942
        printf "xTickCount=%d\n",xTickCount
2       dprintf        keep y   0x08000f54 in vPrintString at main.c:4
        printf "%s print %s\n",pxCurrentTCB->pcTaskName,str

dprintf设置了类型为dprintf的特殊断点,当程序执行到该断点时,GDB将按照template和expression打印消息,打印完成后继续执行程序。这个过程非常短暂(和仿真器的速度有关),人是感觉不出程序停顿的,所以看起来就跟是目标程序在打印消息一样。

dprintf局限性

dprintf的本质是断点,因此目标程序并不是持续执行的,目标程序因为断点而暂停执行,等dprintf打印消息后再继续,在实时系统中这或许是不可接受的。特别是当打印的频率比较高时,目标程序会被频繁地进入断点暂停执行。目标程序停顿的时间则跟仿真器的速度有关,速度越慢的仿真器,其停顿时间越长。因此dprintf仅可以作为权宜之计来使用,例如在实现串口驱动之前、临时需要打印某些消息时。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值