嵌入式设备有调试不方便的麻烦,这包括软件、硬件、环境部署上的困难。
如无特殊说明,下文描述的仅是嵌入式linux程序,而不是单片机或FPGA程序,它们有自己独特的调试手段,请知悉!
软件开发时,因gdb是命令行调试工具,我们不能像vs2015那样GUI方式下断点进行调试;硬件出问题时,因拆除外壳进行示波器测量困难,尤其是测试点在pcb板背面时,需断电、拆后盖测量,恐怕问题又不复现了;产品部署后因flash容量有限,无法很方便将log日志或者core dump文件保存下来。
本文不是试图去改变该现状,而是列出产品出厂后的调试手段。
一、gdb调试
因出厂程序是release版本,即去掉调试信息和符号表,在linux上是strip工具:
arm-hisiv400-linux-strip demo
如果使用去掉符号表的程序进行gdb调试则看到的只是汇编或者指针。
但如果在strip之前先把symbol保存下来,则方便日后调试,类似于vs的pdb文件:
CFLAGS += -g3
arm-hisiv400-linux-objcopy --only-keep-debug demo demo.symbol
arm-hisiv400-linux-strip demo
使用方法:
1,段错误排查:
ulimit -c unlimited
产生core文件
# arm-hisiv400-linux-gdb demo core
# (gdb) file ./demo.symbol
# (gdb) bt
2,调试正在运行的进程
hi3536-gdb attach [pid] gdb调试pid号的进程,其中hi3536-gdb为板内运行的gdb或者使用“板内运行的gdbserver+pc运行的arm-hisiv400-linux-gdb”
info threads 查看当前进程的线程
thread
thread apply all bt 对所有线程发送bt命令查看堆栈信息
二、使用glibc的backtrace接口跟踪函数调用栈
CFLAGS+= -g -funwind-tables -rdynamic
此时,可以使用类似linux内核的dump_stack(),当然肯定没有内核的强大!
参考:http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
#include
#include
#include
/* Obtain a backtrace and print it to stdout. */
void
print_trace (void)
{
void *array[10];
size_t size;
char **strings;
size_t i;
size = backtrace (array, 10);
strings = backtrace_symbols (array, size);
printf ("Obtained %zd stack frames.\n", size);
for (i = 0; i < size; i++)
printf ("%s\n", strings[i]);
free (strings);
}
/* A dummy function to make the backtrace more interesting. */
void
dummy_function (void)
{
print_trace ();
}
int
main (void)
{
dummy_function ();
return 0;
}
三、使用syslog或者编写DebugView服务器
这两个都可以通过tcp通信,将日志传至服务器,而服务器一般都部署在pc上,这时就可以将嵌入式设备的log日志发送到pc上阅读。为什么我们要使用这种“多此一举”的方法,其根本原因是嵌入式系统flash容量有限,而且NAND FLASH经常读写很容易产生坏块,把日志传到pc上阅读可以避免这些情况。
1,syslog使用方法
IP地址为192.168.100.110的PC上使用tftpd64.exe或tftpd32.exe部署好“Syslog server”后,如若应用程序使用下面封装的打印接口:
/* 日志等级:
* LOG_EMERG 0
* LOG_ALERT 1
* LOG_CRIT 2
* LOG_ERR 3
* LOG_WARNING 4
* LOG_NOTICE 5
* LOG_INFO 6
* LOG_DEBUG 7
*/
#include
#define LOG_PREFIX " TID[%ld] [%s:%d] "
#define NCSLOG(ilevel,sLog,...)\
do\
{\
syslog((ilevel),(LOG_PREFIX sLog),syscall(224),__FILE__, __LINE__,##__VA_ARGS__);\
}while(0)
//可以这样使用
//NCSLOG(LOG_ERR, "Error!\n");
//NCSLOG(LOG_INFO, "Info!\n");
//NCSLOG(LOG_DEBUG, "Debug\n");
//syslogd -s 10240 -l 8 打印到/var/log/message文件,文件大小为10MB 打印等级为8
则当使用syslogd指定服务器IP地址后(如syslogd -R 192.168.100.110 -l 8),log可传输到pc上。
2,使用DebugView接收日志
板卡需要运行服务程序。暂不作介绍。
以上仅供参考!