原创 程序调试记录

2009-10-16 21:42 2921 6 6 分类: MCU/ 嵌入式

<?xml:namespace prefix = st1 ns = "urn:schemas-microsoft-com:office:smarttags" />20091016星期五19:44:43


程序调试


一、调试目的


在前两天编写的shell程序中,出了这么一个问题:shell程序从消息队列读取按键,当读取到enter键时,进入命令执行状态;命令执行完成后,回到输入态,继续读取按键。但是实际执行过程中发现,如果输入错误命令,程序正常执行;但是输入正确命令执行完成以后,会进入一个读取按键的死循环。通过简单调试发现,是消息队列那里出了问题,今天的调试就从消息队列开始。


<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 


二、ucos的消息队列


1、它是如何创建的?


   在操作系统初始化时,调用了OS_QInit(),该函数主要是初始化了OSQFreeList = &OSQTbl[0];并且把各个消息队列控制块链接起来。


   然后应用程序调用OS_QCreate()创建自己的消息队列,提供的参数两个:一个是事件控制块,事件控制块包括—类型、指针、等待任务列表等;一个是消息指针数组。创建的过程大概是这样:取出一个事件控制块,类型设置为消息队列,取出一个队列控制块,让事件控制块的指针指向它。然后队列控制块有读指针、写指针、消息数量、队列容量等参数进行初始化。      pq->OSQStart           = start;  /*  Initialize the queue     */


            pq->OSQEnd           = &start[size];


            pq->OSQIn             = start;


            pq->OSQOut             = start;


            pq->OSQSize            = size;


            pq->OSQEntries         = 0;


2、消息发到消息队列


   程序调用OS_QPost()函数将消息发送到队列,实际上消息内容需要程序自己提供内存,消息队列接受内容的指针,将它复制到消息指针数字里,同时调整写指针,指向下一个消息指针。    *pq->OSQIn++ = pmsg;  /* Insert message into queue   */


pq->OSQEntries++; 


3、从消息队列取数据


   程序调用OS_QPend()函数从消息队列取消息,实际上是得到一个指针,然后根据指针取到相应的内容,同时还要调整队列控制块的读指针和有效消息数。    pq = (OS_Q *)pevent->OSEventPtr; /* Point at queue control block   */


    if (pq->OSQEntries > 0) {  /* See if any messages in the queue                   */


        pmsg = *pq->OSQOut++;  /* Yes, extract oldest message from the queue         */


        pq->OSQEntries--;   


   当然,如果没有消息,那就在该队列上等待。


三、调试过程


1、观察事件控制块的参数变化


我定义的事件控制块为KeyValueOSQ,先把它加到观察列表。


在出问题的地方之前设置一个断点,起动调试。


输入一个正确的命令,程序执行输出:输入help,屏幕显示shell支持的其他三个命令。


最后观察KeyValueOSQ:它的队列控制块指针为0x2000,0df0.


同时把消息指针数组加到观察列表。


进入KB_GetChar()函数的内部,调用OS_QPend()从消息队列取数据,一进去,发现    if (perr == (INT8U *)0) {   /* Validate 'perr'                                    */


        return ((void *)0);


是由于这句话因此返回一个无效指针。Perr没有有效地址。


解决办法:将它设置为一个全局变量。


 


2、最终的解决方案


开始定义 u8 *perr,这个指针由于没有初始化,是一个随即的值。


改为u8 Err,然后在调用OS_QPend时采用参数,&Err,程序正常运行。


 


四、收获


1、调试过程中要做好计划,先确定故障的范围,一般来说,结合程序的输出表现、单步调试可以确定故障点。


2指针的使用一定要注意:使用之前必须先初始化,比如这个程序中我定义了u8* perr。然后在程序中直接调用KeyPtr=OS_QPend(KeyValueOSQ,0,perr);这是一个还未赋值和初始化的指针,它的值是随机的,当它变为0后,这个程序的运行就不正常了。


改为:u8 Err定义,然后这样调用KeyPtr=OS_QPend(KeyValueOSQ,0,&Err),程序的运行就恢复正常了。

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
6
关闭 站长推荐上一条 /3 下一条