"); //-->
工欲善其事必先利其器之二(MPLAB IDE中使用DBPRINTF()函数打印debug信息)
现在很多嵌入式MCU开发软件都具有直接在IDE的控制台console中实时打印调试信息和实时采集数据的功能,这对我们这些MCU程序设计和开发者来说,无疑是十分有用的。MPLAB IDE中也当仁不让的集成并支持这一功能,这主要得益于它使用了gcc编译器和gdb调试器以及Microchip公司的32位高性能MPIS核MCU——PIC32XX。
但是我最开始拿到Cerebot 32MX4™™ Board时,使用MPLAB 8.6.0使用例程中的DBPRINTF()函数打印调试信息时却未成功,经过最近两天的探索,今天下午终于把问题解决了,而且这个问题的解决居然是如此的简单~!
在main.c的最前面,即代码首行对PIC32_STARTER_KIT进行定义如下所示:
#define PIC32_STARTER_KIT 1
下面讲一下其中的原因:
我首先在google寻找答案,搜到一篇名为《Hello from PIC32》的外语文章,其链接为:http://www.johnloomis.org/microchip/pic32/hello/hello1.html
按照这边文章所说的,我下载了其提供的工程,下载到Cerebot 32MX4™™ Board上,运行,确实成功的使用DBPRINTF()函数打印出了Hello from PIC32,窃以为只要按照这种方法把下载到的db_utils.h头文件和db_utils.a库文件加到自己的工程中,并在main.c的开头加入#include "db_utils.h"就可以在自己的工程中正常的使用DBPRINTF()函数呢,结果不是。
当我把下载到的db_utils.h头文件和db_utils.a库文件拷贝到i2c工程中,并添加到该工程里面时,一编译就冒出类似如下警告来:
Executing: "C:\Study\Microchip\MPLAB C32 Suite\bin\pic32-gcc.exe" -mprocessor=32MX360F512L -x c -c "source\i2c_master.c" -o".\objects\i2c_master.o" -MMD -MF".\objects\i2c_master.d" -I"C:\Projects\Peripheral Libs\Trunk\pic32-libs\include" -I".\source" -D__DEBUG -D__MPLAB_DEBUGGER_PIC32MXSK=1 -g -DSYS_CLOCK=80000000 -Wall
In file included from source\i2c_master.c:50:
source\/db_utils.h:49:1: warning: "DBINIT" redefined
In file included from C:/Study/Microchip/MPLAB C32 Suite/bin/../lib/gcc/pic32mx/3.4.4/../../../../pic32mx/include/p32xxxx.h:396,from C:/Study/Microchip/MPLAB C32 Suite/bin/../lib/gcc/pic32mx/3.4.4/../../../../pic32mx/include/peripheral/adc10.h:44,from C:/Study/Microchip/MPLAB C32 Suite/bin/../lib/gcc/pic32mx/3.4.4/../../../../pic32mx/include/plib.h:41,from source\i2c_master.c:48:
提示BDXXXX相关的调试函数全部重定义了。
我以为警告没有什么问题,下载到板子上进行调试,结果发现程序可以正常运行,但是还是不能打印调试信息,最后单步调试才发现,程序根本不执行DBXX类的函数,包括DBINIT();DBPRINTF();DBPUTS()等(单步是,程序直接跳过有DBXX函数的行,继续往下执行)。
最后,功夫不负有心人,提供最终编译日志,查到了原因所在:
原因其实不不在于工程没有包含db_utils.a这个包含调试函数的库,在IDE的gcc工具设置中已经包含了相关函数定义及头文件了的。我追踪到我的MPLAB安装目录C:\Study\Microchip\MPLAB C32 Suite\pic32mx\include\sys下一个叫appio.h的头文件:
在其101行至129行有如下内容:
#if defined(PIC32_STARTER_KIT) && defined(__DEBUG)
#define DBINIT() _pic32mxsk_init()
#define DBPUTC(c) db_puts(c,1)
#define DBPUTS(s) db_puts(s, strlen(s))
#define DBPRINTF printf
#define DBSCANF ((void)0) /* scanf not supported in SK */
#define DBGETS(s,len) db_gets(s, len)
#define DBGETC(c) db_gets(c,1)
/* Debug function prototypes */
extern void _pic32mxsk_init (void);
extern void __attribute__ ((noinline,nomips16,weak)) db_puts (const unsigned char *s, int len);
extern void __attribute__ ((noinline,nomips16,weak)) db_gets (unsigned char *s, int len);
extern void __attribute__ ((weak)) _mon_write (const char * s, unsigned int count) __attribute__((alias("_p32mxsk_write")));
extern void __attribute__ ((weak)) _mon_putc (char c) __attribute__((alias("_p32mxsk_putc")));
extern void __attribute__ ((weak)) _mon_getc (int canblock) __attribute__((alias("_p32mxsk_getc")));
#else /* !(defined(PIC32_STARTER_KIT) && defined(__DEBUG)) */
#define DBINIT() ((void)0)
#define DBPUTC(ignore) ((void)0)
#define DBPUTS(ignore) ((void)0)
#define DBPRINTF(ignore,...) ((void)0)
#define DBSCANF(ignore,...) ((void)0)
#define DBGETC(ignore) ((void)0)
#define DBGETS(ignore,ignore2) ((void)0)
#define DBAPPIO_INIT(ignore) ((void)0)
#define DBGETWORD(ignore) ((void)0)
#define DBPUTWORD(ignore) ((void)0)
#endif
从以上条件编译可以看到,只有当PIC32_STARTER_KIT和__DEBUG两个预编译控制变量都为1(或者非0)时,才真正对DBXX类调试函数进行定义,否则定义为((void)0)即空函数,怪说不得,之前的程序执行到DBXX函数时就直接跳过了。呵呵,真正的原因也句找到了~!
接下来解决的办法就是让编译器在编译我们的工程时真正定义这些DBxx类函数,当我们将工程属性配置为debug而非release时(配置方法为①新建工程时选择为debug,②通过IDE的菜单栏Project->Build Configuration->Debug),IDE就会自动的为我们定义__DEBUG,而PIC32_STARTER_KIT则需要我们自己进行定义,系统不会自动定义。
另外,由于在p32xxxx.h,dc10.h以及很多头文件中有用到appio.h文件,所以必须在main.c的首行就用#define PIC32_STARTER_KIT 1 对PIC32_STARTER_KIT进行定义才能让软件在编译你的工程时真正的定义DBXX类调试函数。
胡恩伟
2011年1月16日
于重庆大学A区一舍
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。
eleaction01 阅读:2939