• 内存检测


    图示
    1.电路的制作工艺错误:在焊接电路的时候,可能会出现焊锡飞溅的情况,使得两个引脚短路,这样的后果是,当你对存储器进行操作的时候,就会数据重叠,甚至于说,出现无法读取的数据;焊接操作不当或者铜板刻制出错,出现开路的情况,可能会出现对存储器无法操作或者数据操作不成功的情况。
    2.电路的电容性:假设使用的芯片频率足够快,你进行一个写操作,为了检验,你再进行一个读操作,那么问题来了,如果电容性,虽然你可能检测到的数据是你想要的,但是这时这个数据是由于读写操作太快,而来不及反翻转,那么这样的芯片实际上是不能存储你检测到的那么多的数据的。
    3.存储芯片错误放置,其实这样的情况很容易避免的,这样的问题,进行检测的时候,都会自动的检测出来。

    现在介绍三种检测方法,数据总线检测,地址总线检测,设备检测。
    数据存取正常是在控制总线(地址总线)正常的情况下进行的,而设备检测需要确定地址总线和数据总线已经正常工作了。
    1.数据总线检测,通常采用的方法使用0~1对存储的每一个bit位进行遍历,
    每次的读写操作,每个数据位之间都是独立的。如图所示,好像“1”从右边走到了左边,所以这种方法也叫作“walking 1”.

    typedef unsigned char datum; /* 设置数据总线宽度为8bit */
    
    
    /**********************************************************************
    *
    * 函数名: memTestDataBus
    *
    * 函数内容: 在指定的地址下,用walking 1的方法对数据总线进行检测
    * 地址通过函数参数指定。
    *
    * 输入参数: address 需要检测的内存地址
    *
    * 返回值: 返回'0',则没有问题,如果返回其他值,
    * 则说明检测失败有数据位操作有问题
    *
    **********************************************************************/
    datum
    memTestDataBus(volatile datum * address)
    {
    datum pattern;
    
    
    /*
    * 在指定的地址下执行对数据线进行walking 1检测
    */
    for (pattern = 1; pattern != 0; pattern <<= 1)
    {
    /*
    * 写入检测数据
    */
    *address = pattern;
    
    /*
    * 读回数据
    */
    if (*address != pattern)
    {
    return (pattern);
    }
    }
    
    return (0);
    
    } /* memTestDataBus() */
    

    2.地址总线检测:对芯片的每一个地址进行写0和1,同时确定引脚之间相互独立。

    这个和数据总线检测的walking 1的方法是类似(对一个16bit的总线来说,地址可以是0000H,0001H,0002H,0004H,0008H,0010H,0020H,0080H等等),并且在你写入的同时,你需要检测其他的地址没有被重写。

    但是不是所有的地址线可以通过这样的方法检测,比如你的地址总线宽度是32bit,寻址空间是4GB,如果你要测试128K的内存块,那么其实只有17根总线用到了, 仍有15根总线没有用到。

    确定两个存储之间没有重叠

    /**********************************************************************
    *
    * 函数名:    memTestAddressBus()
    *
    * 函数描述:      这个测试可以找出某个bit位上的错误,比如,卡高,卡低
    *              短路。基础地址和区域大小可以由函数参数指定。
    * 输入参数:     基础地址,
    *
    * 返回值  :     如果地址总线没有,返回空值。
    *                    返回的非零的结果,是函数执行时遇见的第一个出现地址
    *                    重叠的。通过检查存储的内容,可以知道关于这个存储问
    *                    题是卡高,卡低,短路。
    *
    **********************************************************************/
    datum *
    memTestAddressBus(volatile datum * baseAddress, unsigned long nBytes)
    {
        unsigned long addressMask = (nBytes/sizeof(datum) - 1);
        unsigned long offset;
        unsigned long testOffset;
    
        datum pattern     = (datum) 0xAAAAAAAA;
        datum antipattern = (datum) 0x55555555;
    
    
        /*
         * 在每一个偏置电源下,对每一个地址位写初值操作
         */
        for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
        {
            baseAddress[offset] = pattern;
        }
    
        /*
         * 检查地址位卡低
         */
        testOffset = 0;
        baseAddress[testOffset] = antipattern;
    
        for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
        {
            if (baseAddress[offset] != pattern)
            {
                return ((datum *) &baseAddress[offset]);
            }
        }
    
        baseAddress[testOffset] = pattern;
    
        /*
         * 检查地址位卡高
         */
        for (testOffset = 1; (testOffset & addressMask) != 0; testOffset <<= 1)
        {
            baseAddress[testOffset] = antipattern;
    
              if (baseAddress[0] != pattern)
              {
                   return ((datum *) &baseAddress[testOffset]);
              }
    
            for (offset = 1; (offset & addressMask) != 0; offset <<= 1)
            {
                if ((baseAddress[offset] != pattern) && (offset != testOffset))
                {
                    return ((datum *) &baseAddress[testOffset]);
                }
            }
    
            baseAddress[testOffset] = pattern;
        }
    
        return (NULL);
    
    }   /* memTestAddressBus() */
    
    

    3.设备检测,存储器中每一位都可以存储0或1,虽然这句话很简单,很粗暴,但是所花的时间比前面两个多了不少。
    在设备检测过程中,你需要对所有的内存空间进行两次读写操作,第一次将一个随机数写读该地址,第二次将这个随机数取反再次写读。在检测中常用的方法是,随着地址的变化,存储的值逐渐增加。
    如下图所示:

    第一列和第二列是地址和数据的变化,第三列是数据取反之后的变化。取数值的方式有很多种,但是这种顺序变化的方式更加的容易计算。

    /**********************************************************************
    *
    * 函数名:    memTestDevice()
    *
    * 函数描述:    用数据递增/递减的方式检测整个物理存储区域。
    *                   在这个过程中设备里的每一个存储位用bit1或者bit0进行
    *                    检测。通过形参传递基础地址和检测区域大小。
    *输入参数:   基础地址 baseAddress,检测区域大小   
    *
    * 返回值:     如果检测成功,则返回空值。
    *                  如果检测失败,会返回一个第一次检测失败的内存地址。同时
    *                  检测内存内容,可以得到这个问题更多详细信息。
    *
    **********************************************************************/
    datum *
    memTestDevice(volatile datum * baseAddress, unsigned long nBytes)    
    {
        unsigned long offset;
        unsigned long nWords = nBytes / sizeof(datum);
    
        datum pattern;
        datum antipattern;
    
    
        /*
         * 用已知的数据
         */
        for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
        {
            baseAddress[offset] = pattern;
        }
    
        /*
         * 检测每一个存储位置,并进行每个bit位进行翻转
         */
        for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
        {
            if (baseAddress[offset] != pattern)
            {
                return ((datum *) &baseAddress[offset]);
            }
    
            antipattern = ~pattern;
            baseAddress[offset] = antipattern;
        }
    
        /*
         * 检测存储器中每个已经翻转的bit位,同时将所有内存置零
         */
        for (pattern = 1, offset = 0; offset < nWords; pattern++, offset++)
        {
            antipattern = ~pattern;
            if (baseAddress[offset] != antipattern)
            {
                return ((datum *) &baseAddress[offset]);
            }
        }
    
        return (NULL);
    
    }   /* memTestDevice() */
    
    

    好吧,到了三剑合一的时候了
    说了那么多,我们现在来讲点实际的。假设现在我们需要检测一个地址00000000H,大小是64K的内存块。我们现在以我们刚刚说的顺序对三个函数进行调用。对我们的内存进行检测,得到的代码如下。

    int
    memTest(void)
    {
    #define BASE_ADDRESS  (volatile datum *) 0x00000000
    #define NUM_BYTES     (64 * 1024)
    
        if ((memTestDataBus(BASE_ADDRESS) != 0) ||
            (memTestAddressBus(BASE_ADDRESS, NUM_BYTES) != NULL) ||
            (memTestDevice(BASE_ADDRESS, NUM_BYTES) != NULL))
        {
            return (-1);
        }
        else
        {
            return (0);
        }
             
    }   /* memTest() */
    

    在检测中,你可以用一个LED的亮灭来表示内存的检测的结果,如果返回值不为空,则亮起红灯。如果返回值为空,则亮起绿灯。

  • 相关阅读:
    课程设计-远程安防监控-个人报告
    实验八 Web基础 SQL注入原理
    实验七 网络欺骗
    实验六 信息搜集
    实验五---渗透测试实战
    实验四 系统监测和恶意代码分析 20155104 赵文昊
    实验三 免杀实践 赵文昊20155104
    给一寸照片换背景色
    Linux 流程控制语句 if else、for、while、until
    Linux 条件判断
  • 原文地址:https://www.cnblogs.com/JackFu/p/8070706.html
Copyright © 2020-2023  润新知