用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仅可以作为权宜之计来使用,例如在实现串口驱动之前、临时需要打印某些消息时。相关文章推荐
- 【官方】Android Studio中使用Git托管到GitHub
- 怎么用CIFilter给图片加上各种各样的滤镜_1
- 主动对象
- 使用 ACE 库框架在 UNIX 中开发高性能并发应用
- iOS bitcode实战
- 句柄
- 事务隔离级别
- 改进版的冒泡排序(双向冒泡算法)
- 【Android开发小记--4】动画--线性布局动画
- intent广播
- 数据源(Data Source
- 【CODEVS1380】没有上司的舞会
- 【hdu1573-X问题】拓展欧几里得-同余方程组
- 范式理论
- swoole(一)
- 深入 char
- Python 利用PIL将图片转为字符
- 引用计数
- java标识接口
- Adobe 官方公布的RTMP规范