您的位置:首页 > 其它

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

2016-02-02 20:39 495 查看

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

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

/article/8120137.html

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仅可以作为权宜之计来使用,例如在实现串口驱动之前、临时需要打印某些消息时。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: