內存檢測

圖示
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,同時肯定引腳之間相互獨立。code

這個和數據總線檢測的walking 1的方法是相似(對一個16bit的總線來講,地址能夠是0000H,0001H,0002H,0004H,0008H,0010H,0020H,0080H等等),而且在你寫入的同時,你須要檢測其餘的地址沒有被重寫。blog

可是不是全部的地址線能夠經過這樣的方法檢測,好比你的地址總線寬度是32bit,尋址空間是4GB,若是你要測試128K的內存塊,那麼其實只有17根總線用到了, 仍有15根總線沒有用到。ip

肯定兩個存儲之間沒有重疊內存

/**********************************************************************
*
* 函數名:    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,雖然這句話很簡單,很粗暴,可是所花的時間比前面兩個多了很多。
在設備檢測過程當中,你須要對全部的內存空間進行兩次讀寫操做,第一次將一個隨機數寫讀該地址,第二次將這個隨機數取反再次寫讀。在檢測中經常使用的方法是,隨着地址的變化,存儲的值逐漸增長。
以下圖所示:it

第一列和第二列是地址和數據的變化,第三列是數據取反以後的變化。取數值的方式有不少種,可是這種順序變化的方式更加的容易計算。class

/**********************************************************************
*
* 函數名:    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的內存塊。咱們如今以咱們剛剛說的順序對三個函數進行調用。對咱們的內存進行檢測,獲得的代碼以下。test

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的亮滅來表示內存的檢測的結果,若是返回值不爲空,則亮起紅燈。若是返回值爲空,則亮起綠燈。基礎

相關文章
相關標籤/搜索