嵌入式應用程式設計經驗之談-區域性變數造成的宕機
阿新 • • 發佈:2019-02-17
環境介紹:
開發軟體:keil4
硬體:STM32F107
開篇雜談:
寫下這篇文章,已經有段時間沒有來自己的部落格分享自己在工作中遇到的問題了。每當自己想寫分享的時候,都是自己再專案中遇到了困擾自己的問題,最後解決問題後的分享之 談。對於一個還未畢業的實習嵌入式開發的我來說,自己的知識面也有限。自己在分享的過程中有什麼錯誤的地方,希望大家予以指正。自己每篇文章,哪怕對大家有一點點幫助,對於自己來說都是莫大的推動力。自己也始終相信,互相分享交流大家才會一起進步。
問題描述:
這幾天開始了公司的一個新專案,自己在組建專案底層驅動寫到falsh晶片的資料儲存的時候出現了問題。這裡自己寫了一個讀寫falsh晶片一個扇區的測試程式碼。這裡列印除錯發現讀寫都成功了,但是程式碼跑到後面就跑飛了(也就是宕機了)。程式碼當時跑飛在測試段程式碼後面的Lwip初始化的程式碼段裡。奇怪的是,當我把這個測試的位置放在Lwip初始化程式碼後面,程式會跑起來,但是過了十幾秒還是會出現跑飛的現象。對於這種現象自己的心情是崩潰的,下面這張圖片來表達下自己的心情,相信每個程式 員碰到這樣的問題時內心都是拒絕的。雖然內心是拒絕的,但是還是得拿起傢伙衝進BUG堆中奮戰。圖片引用於網路
問題發現:
通過不斷的除錯自己發現問題出現在了下面這段程式碼中,程式碼當時不是死在這個地方也讓我找了很久,其實最後問題解決了自己也感嘆自己C語言的功底還是不夠啊!自己還是要加強C語言的學習啊!騷年革命尚未成功,同志仍需努力啊!自己早些時候在看C語言的書籍的時候就看到這樣一句話“作為一個嵌入式開發人員,如果沒有記憶體分配的概念,而只會C語言永遠只是一個普通的 程式設計師”,這次遇到這個問題,對這句話現在是深有體會啊!下面直接給出我的問題程式碼:#define MEM_SECTOR_SIZE 4096
u8 MX25_TEST(void) { u16 i; u8 tmp_buf[MEM_SECTOR_SIZE]; app_trace_log("Read Sector\r\n"); Mem_Sector_Read(1, tmp_buf); app_trace_dump(tmp_buf,5); app_trace_log("Write Sector\r\n"); for(i=0;i<MEM_SECTOR_SIZE;i++) tmp_buf[i] = i%256; Mem_Sector_Write(1, tmp_buf); memset(tmp_buf, 0x55, MEM_SECTOR_SIZE); app_trace_log("Read Sector\r\n"); Mem_Sector_Read(1, tmp_buf); app_trace_dump(tmp_buf,5); for(i=0;i<MEM_SECTOR_SIZE;i++) { if(tmp_buf[i] != (i%256)) break; } if(i<MEM_SECTOR_SIZE) {app_trace_log("Sector OP ERR"); return 1; } else { app_trace_log("Sector OP OK"); return 0; } }
問題解決:
這裡最後發現是由於區域性變數帶來的問題,區域性變數當我在函式中定義使用這個變數的時候系統分配了一個臨時的記憶體,當函式 執行完這個變數的記憶體就會被釋放掉。這裡我們都知道這樣一個原理,但是需要大家注意的是。當我們開發的微控制器的記憶體有限 的時候,用來分配這個臨時記憶體更是有限的。當我們這個時候定義了一個很大的臨時變數,這個時候我們的系統就崩潰了。這裡值 得結合微控制器的記憶體分配的機制多加揣摩,相信會學到很多。大家這裡在以後開發的時候,一定要注意這個不起眼的區域性變數 了。下面直接給出解決程式碼段。解決辦法一: 使用static關鍵字定義大陣列的區域性變數
解決辦法二:將陣列的區域性變數放在函式外定義
其實這兩種方法的最後的底層操作效果,都是讓這個變數的記憶體分配發生了變化,變數不會在使用之前有限的臨時記憶體段。這裡自己也在不斷的查閱書籍,不斷學習這裡關於底層詳細的知識點,自己後續也會不斷的更新和加強。這裡也希望對這一塊很是瞭解的朋友可以再微博評論欄寫寫你的分享,讓我們也跟著學習學習。當然您也可以加入這個嵌入式交流群469602418,和同行更多的朋友一起交流。#define MEM_SECTOR_SIZE 4096
//u8 tmp_buf[MEM_SECTOR_SIZE]; //解決辦法二
u8 MX25_TEST(void)
{
u16 i;
static u8 tmp_buf[MEM_SECTOR_SIZE]; //解決辦法一
app_trace_log("Read Sector\r\n");
Mem_Sector_Read(1, tmp_buf);
app_trace_dump(tmp_buf,5);
app_trace_log("Write Sector\r\n");
for(i=0;i<MEM_SECTOR_SIZE;i++)
tmp_buf[i] = i%256;
Mem_Sector_Write(1, tmp_buf);
memset(tmp_buf, 0x55, MEM_SECTOR_SIZE);
app_trace_log("Read Sector\r\n");
Mem_Sector_Read(1, tmp_buf);
app_trace_dump(tmp_buf,5);
for(i=0;i<MEM_SECTOR_SIZE;i++)
{
if(tmp_buf[i] != (i%256))
break;
}
if(i<MEM_SECTOR_SIZE)
{app_trace_log("Sector OP ERR");
return 1;
}
else
{ app_trace_log("Sector OP OK");
return 0;
}
}