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