打印

一个和指针有关的很无奈的怪问题!请大侠们帮我猜猜问题

[复制链接]
3560|25
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
alphal|  楼主 | 2007-11-15 15:50 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
请教一个非常奇怪的问题:程序中定义了一个数组mempool,指向该数组的指针MpIsrOut和结构体MInfo及指向该结构体的指针MpIsrInfo,这个结构体和数字都在xdata空间。程序在一个函数中是以该数组指针和结构体指针来访问这两个实体的,在这个函数里,出现了一个非常奇怪的现象:该函数内有以下语句:
   unsigned char nbytes;
   unsigned char cnt;

        for (cnt = 0; cnt < nbytes; cnt++)
        {
    _WriteRawRC2(RegFIFOData, MpIsrOut[MInfo.nBytesSent]);    //写数到片外一个地址
    MInfo.nBytesSent++;        //why????
        }
当“MInfo.nBytesSent”用结构体进行访问的时候程序运行正常。
但如果:
        for (cnt = 0; cnt < nbytes; cnt++)
        {
    _WriteRawRC2(RegFIFOData, MpIsrOut[MpIsrInfo->nBytesSent]);    //写数到片外一个地址
    MpIsrInfo->nBytesSent++;        //why????
        }
就运行异常,得不到正确结果。其中MpIsrInfo就是指向MInfo的,设断点观察,指针取值没错,取出的数也没有错,但结果却是失败。
奇怪点如下:
1、该函数中其它的地方是用指针,没有问题,只要把这里改成下一方式就出错,改成上一方式就正确。
2、在这个地方就是使用该指针进行一个无关的操作也会带来错误的结果。
3、这里cnt和nbytes指定到xdata空间,前一种方式,也会出错。
4、指针的赋值和其指向确认是没有错的,这里操作不会数组溢出。
5、仿真,烧片结果都是这样。

真的不是我忽悠大家,情况确实如此,不知道我讲清楚没有,我们经理听我的讲述后第一反应是:不可能!我说我也觉得不可能,你去看看吧,然后

来琢磨了半个下午后,很苦恼的说:我也不知道是为什么。。。。
本人已经无奈了,确实看不出来是什么问题,烦请各位高人帮我猜一猜,问题可能出现在那里。

如果搞过mfrc500的人应该能看出这个代码是philip的rc500源码里的,这个语句在那个中断服务函数里,只不过我把它改成查询了,发送一个命令之后不是等待中断的发生,而是不停查询该函数。用上面的语句读卡器能正常寻卡、反碰撞、选卡、读、写,如果后一种方式寻卡都寻不到,该函数中每次都是超时退出,一个字都收不到。这里我单步跟踪了,直到_WriteRawRC2函数内的数都是正确的。

相关帖子

沙发
alphal|  楼主 | 2007-11-15 22:46 | 只看该作者

连猜猜都没兴趣?更无奈了。。。。

使用特权

评论回复
板凳
农民讲习所| | 2007-11-15 22:53 | 只看该作者

信息不够

如果能贴出更多的更好
估摸着是编译有警告信息被忽略?

使用特权

评论回复
地板
孤星119| | 2007-11-16 08:54 | 只看该作者

猜猜.

其实程序的BUG,没有"不可能"这个说法的.只是你暂时没看出来罢了.会不会读写时序上出现问题了.结构体可以放在DATA里么?

使用特权

评论回复
5
alphal|  楼主 | 2007-11-16 09:28 | 只看该作者

再贴一个

void v_WriteRawRC2(u1_t addr, u1_t value)
{
    bool_t    __bea ;
//     data volatile u1_t __addrTemp, __valueTemp;//试图用data区中转一下

    __bea = _testbit_(EA) ;

    tstBuf[cursor] = addr ;
    MODINC(cursor, 20)    ;
    tstBuf[cursor] = value ;
    MODINC(cursor, 20)    ;//保存写到片外去的地址和数值

    MF_CS_IO = 0 ;//使能rc500芯片
  _nop_() ;
    _nop_() ;
    _nop_() ;
  AUXR = 2;//关芯片的片外ram
  _nop_();
    _nop_() ;
//  WriteRawRC1(__addrTemp, __valueTemp);
  WriteRawRC1(addr, value);
    _nop_();
    _nop_() ;
    _nop_() ;
  AUXR = 0;;//开芯片的片外ram
    _nop_();
    _nop_() ;
    _nop_() ;
    MF_CS_IO = 1 ;//禁能rc500
    _nop_() ;
    _nop_() ;
    _nop_() ;


    EA = __bea ;
}

rc500的地址和mcu(89e564,片内有728byte的xdata)的片内xdata空间地址是重合的,所以写数的时候需要开关该空间。
RegFIFOData是rc500的寄存器地址。

使用特权

评论回复
6
alphal|  楼主 | 2007-11-16 09:40 | 只看该作者

re:

编译器的警告已经设为2级了,最高也就2级。

这个结构体放在片内结果也是一样的。




真巴不得带上我的程序和系统出去求助高人。。。。

使用特权

评论回复
7
alphal|  楼主 | 2007-11-16 10:12 | 只看该作者

感觉好像是内存上面的问题,好像一不小心就乱了。。。

因为
1、该函数中其它的地方是用指针,没有问题,只要把这里改成下一方式就出错,改成上一方式就正确。
2、在这个地方就是使用该指针进行一个无关的操作也会带来错误的结果。
3、这里cnt和nbytes指定到xdata空间,前一种方式,也会出错。

但编译结果data = 100.4,xdata = 351,code=17380,没有溢出。
看不出问题。

使用特权

评论回复
8
农民讲习所| | 2007-11-16 10:35 | 只看该作者

如果是内存切换问题,要关中断

void v_WriteRawRC2(u1_t addr, u1_t value)
{
    bool_t    __bea ;
//     data volatile u1_t __addrTemp, __valueTemp;//试图用data区中转一下

    __bea = EA ;

    tstBuf[cursor] = addr ;
    MODINC(cursor, 20)    ;
    tstBuf[cursor] = value ;
    MODINC(cursor, 20)    ;//保存写到片外去的地址和数值

    MF_CS_IO = 0 ;//使能rc500芯片
  _nop_() ;
    _nop_() ;
    _nop_() ;
  EA=0;                      //这个一定要加 
  AUXR = 2;//关芯片的片外ram
//  WriteRawRC1(__addrTemp, __valueTemp);
  WriteRawRC1(addr, value);
  AUXR = 0;;//开芯片的片外ram
   EA = __bea ;

    _nop_();
    _nop_() ;
    _nop_() ;
    MF_CS_IO = 1 ;//禁能rc500
    _nop_() ;
    _nop_() ;
    _nop_() ;


使用特权

评论回复
9
alphal|  楼主 | 2007-11-16 11:17 | 只看该作者

程序中有__bea = _testbit_(EA) ;

已经关中断了。

我跟踪到v_WriteRawRC2里面,数据都还没有出错的。。。

使用特权

评论回复
10
农民讲习所| | 2007-11-16 11:21 | 只看该作者

关早了。

    tstBuf[cursor] = addr ;
    MODINC(cursor, 20)    ;
    tstBuf[cursor] = value ;
    MODINC(cursor, 20) 

不知道是否有XDATA操作。原则是只在操作外部XDATA瞬间关-读/写-开,这样系统内存不会错

使用特权

评论回复
11
alphal|  楼主 | 2007-11-16 11:33 | 只看该作者

tstBuf是片内的

另外,下面这句没有问题吧。
//#define WriteRawRC1(addr,value) (PBYTE[addr]=value)
#define WriteRawRC1(addr,value) ((*((unsigned char volatile pdata *)(addr))) = value)

使用特权

评论回复
12
alphal|  楼主 | 2007-11-16 11:36 | 只看该作者

关中断要在MF_CS_IO = 0 之前吧

使用特权

评论回复
13
农民讲习所| | 2007-11-16 11:39 | 只看该作者

不要使用pdata!绝对会犯错误的,特别是又用到xdata

MF_CS_IO操作并没有读写总线,所以在之后。

使用特权

评论回复
14
农民讲习所| | 2007-11-16 11:47 | 只看该作者

如果没用到外部总线,且内部RAM<=256,才可以使用pdata

否则,等着出错吧。
教科书害人的地方,pdata算一个。

使用特权

评论回复
15
alphal|  楼主 | 2007-11-16 11:50 | 只看该作者

pdata,pbyte有问题吗?

不要使用pdata!绝对会犯错误的,特别是又用到xdata??????

为何????


MF_CS_IO = 0;
后已经使能了芯片,不关掉的话,定时器中断中如果有操作xdata变量的数据岂不都进rc500芯片去了?


有个惊人的发现,我把数组mempool和结构体MInfo都定义到片内idata空间就没这些问题了。看来是xdata开关的问题???


谢谢所长的指点,不胜感激!

使用特权

评论回复
16
农民讲习所| | 2007-11-16 11:54 | 只看该作者

不会,AUXR没打开

关于pdata,可以专门开个话题,谨用pdata。

使用特权

评论回复
17
现实主义| | 2007-11-16 12:41 | 只看该作者

从最简单做起

从最简单做起。

新建一个工程,只加入你关心的代码,一点一点试。

如果两者一样,那程序别的地方,一定有问题。
先定位错误所在再说.

使用特权

评论回复
18
alphal|  楼主 | 2007-11-16 12:52 | 只看该作者

我现在定位的错误就在这个地方啊

使用特权

评论回复
19
现实主义| | 2007-11-16 13:08 | 只看该作者

是在一个简单工程里发现不一样吗?

是在一个简单工程模型里发现两者不一样吗?

本人C51不熟,不然试试看,要真是这样还真奇怪?
编译器有bug?不大可能吧?

使用特权

评论回复
20
alphal|  楼主 | 2007-11-16 13:22 | 只看该作者

re

to:现实主义
你说的简单工程多简单?

我这个工程也只是专门测试这个程序的。

我也不认为是编译器的bug的,不会那么好彩的吧。

似乎是内外存储器之间的问题,我把这个数组和结构体都放在data区就没有这些问题了,可是在xdata的时候,这个切换有什么问题呢???


to 所长:
关中断这个地方改成你原则上的那样了,pdata也改了,问题依然存在,这个程序的内存切换有漏洞吗???
另外可不可以简单的介绍一下pdata的使用规则。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

112

主题

473

帖子

1

粉丝