記憶體檢測及C程式碼解釋
為什麼要進行記憶體檢測
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的亮滅來表示記憶體的檢測的結果,如果返回值不為空,則亮起紅燈。如果返回值為空,則亮起綠燈。
鵬@惠祥和
相關推薦
記憶體檢測及C程式碼解釋
為什麼要進行記憶體檢測 1.電路的製作工藝錯誤:在焊接電路的時候,可能會出現焊錫飛濺的情況,使得兩個引腳短路,這樣的後果是,當你對儲存器進行操作的時候,就會資料重疊,甚至於說,出現無法讀取的資料;焊接操作不當或者銅板刻製出錯,出現開路的情況,可能會出現對儲
Hough檢測直線原理及c++程式碼
函式功能:檢測影象中的線段 函式原型: CvSeq* cvHoughLines2( CvArr* image, void* line_storage, int method, double rho, double theta, int threshold, double param
引導濾波原理及C++程式碼實現
前置內容 在學習引導濾波,最好對高斯濾波和雙邊濾波有過理解,對於高斯濾波: W i
結構體中指標賦值問題的分析及C程式碼示例
問題描述 某結構體的定義如下: typedef struct { int iAge; // 年齡 char szAddr1[100]; // 地址1 char *psz
用Tensorflow實現CNN文字分類(詳細解釋及TextCNN程式碼解釋)
Ox00: Motivation最近在研究Yoon Kim的一篇經典之作Convolutional Neural Networks for Sentence Classification,這篇文章可以說是cnn模型用於文字分類的開山之作(其實第一個用的不是他,但是Ki
BP神經網路原理分析及c++程式碼實現(上)
本部落格所述BP神經網路,是本人研究總結的結果,希望對您有所幫助,當然,如果有需要,大家可以互相交流。 設計一個BP神經網路類,來實現一個BP神經網路。要求輸入層節點數、隱層數、隱層節點數、輸出層節點數、傳遞函式、演算法等等可以由使用者自主設定。 神經網路
YUV 格式與 RGB 格式的相互轉換公式及C++ 程式碼
YUV 格式與 RGB 格式的相互轉換公式 最近在用的一個工業相機,輸出的影象格式是 YUY2 格式。而在電腦上顯示時需要 RGB 格式,所以就花了些時間在網上查了些相關的資料。說實話,網上關於 YUV 與 RGB 格式變換的文章挺多的,本來不需要我再多寫這麼
執行緒池淺析及C++程式碼實現
(1)什麼是執行緒池 執行緒池是一種多執行緒處理技術。執行緒池先建立好若干執行緒,並管理這些執行緒。當有新的任務到來時,將任務新增到一個已建立的空閒執行緒中執行。執行緒池所建立的執行緒優先順序都是一樣的,所以需要使用特定執行緒優先順序的任務不宜使用執行緒池。 (2)
各種排序演算法總結及C#程式碼實現
排序是計算機內經常進行的一種操作,其目的是將一組“無序”的記錄序列調整為“有序”的記錄序列。分內部排序和外部排序。若整個排序過程不需要訪問外存便能完成,則稱此類排序問題為內部排序。反之,若參加排序的記錄數量很大,整個序列的排序過程不可能在記憶體中完成,則稱此類排序問
BP神經網路原理分析及c++程式碼實現(下)
為了方便廣大使用者的使用,本人將BP神經網路寫成了一個BPNNS類,這樣使用者們可以很方便的將此類潛入到自己的工程當中,此類的具體的使用規則,下面會介紹。 /*********************************************************
01揹包問題 及c++ 程式碼實現
今天在看july的部落格之時,看到其中一道題目的原理為01揹包問題,就自己溫習了下,寫下今天的學習體會。 本文理論分析參考部落格:http://www.cnblogs.com/qinyg/archive/2012/04/26/2471829.html 問題描述:
影象去霧之何凱明暗通道先驗去霧演算法原理及c++程式碼實現
http://blog.csdn.net/s12244315/article/details/50292049 何凱明博士,2007年清華大學畢業,2011年香港中文大學博士畢業,可謂是功力深厚,感嘆於國內一些所謂博士的水平,何這樣的博士才可以真正叫做
組合模式及C++程式碼實現
理論學習: 在開發中,我們經常可能要遞迴構建樹狀的組合結構,組合模式則提供了很好的解決方案! 組合模式的標準定義:將物件組合成樹形結構以表示“部分整體”的層次結構。組合模式使得使用者對單個物件和組合物件的使用具有一致性!組合模式解耦了客戶程式與
頁面排程演算法 FIFO,LRU,OPT,及C++程式碼
頁面排程演算法 FIFO,LRU,OPT 介紹了三種頁面排程演算法,給出了C++程式碼 1.FIFO 先來先去演算法這個非常好理解,給出分析圖 可以看出,缺頁次數為8次,缺頁中斷率為8/12=66.7%,依次置換的頁面為:1,2,5,3,4 C
[技術棧]CRC校驗原理及C#程式碼實現CRC16、CRC32計算FCS校驗碼
1.CRC、FCS是什麼 CRC,全稱Cyclic Redundancy Check,中文名稱為迴圈冗餘校驗,是一種根據網路資料包或計算機檔案等資料產生簡短固定位數校驗碼的一種通道編碼技術,主要用來檢測或校驗資料傳輸或者儲存後可能出現的錯誤。它是利用除法及餘數的原理來作錯誤偵測的。 FCS,全稱Frame C
【工具】valgrind檢測C++程式碼記憶體洩漏
一、valgrind介紹: valgrind是Linux下的一個開源工具,該工具用來檢測c++程式是否有非法使用記憶體的問題,例如訪問了未初始化的記憶體、訪問陣列時越界、忘記釋放動態記憶體等問題。Lin
如何檢測及預防C++記憶體洩漏
“該死系統存在記憶體洩漏問題”,專案中由於各方面因素,總是有人抱怨存在記憶體洩漏,系統長時間執行之後,可用記憶體越來越少,甚至導致了某些服務失敗。記憶體洩漏是最難發現的常見錯誤之一,因為除非用完記憶體或呼叫malloc失敗,否則都不會導致任何問題。實際上,使用C/C++這類
Opencv檢測交通中紅色標識輪廓c++程式碼例項及執行結果
環境vs2013+opencv2.4.9 c++程式碼 #include<opencv2/opencv.hpp> #include<iostream> #define PI 3.1415926 using namespace std; using
交通標識牌檢測及識別c++程式碼例項及執行結果 (可自行在網上下載圖片測試)
執行環境:vs2013+opencv2.4.9+win10 資料來源於GTSRB 效果不是很理想(預處理方法、檢測用的rgb2hsv、圓度檢測,、引數,總之改變程式中很多東西可以嘗試提高準確率),但檢測及識別的道路是打通了 c++程式碼 #include<iostr
C/C++程式設計知識:記憶體洩漏及檢測
“該死系統存在記憶體洩漏問題”,專案中由於各方面因素,總是有人抱怨存在記憶體洩漏,系統長時間執行之後,可用記憶體越來越少,甚至導致了某些服務失敗。記憶體洩漏是最難發現的常見錯誤之一,因為除非用完記憶體或呼叫malloc失敗,否則都不會導致任何問題。實際上,使用C/C++這類沒有垃圾回收機制的語言時,