記錄一次因為stack_size太小引起的問題。


出問題的函數如下:

 1 char *calc_file_md5(const char* fw_name)
 2 {
 3     FRESULT result;
 4     FIL File;
 5     uint32_t BytesRead = 0,offset = 0,file_size = 0;
 6     MD5_CTX context;   //MD5
 7     unsigned char digest[16];
 8     uint8_t i = 0;
 9     
10     result = f_open(&File,fw_name,FA_OPEN_EXISTING|FA_READ);        //打開文件
11     if(FR_OK  != result)
12     {
13         DEBUG_LOG(DEBUG_FW,("Not Find %s\n",fw_name));
14         return 0;
15     }
16    file_size = File.obj.objsize;//結束地址為起始地址加上文件大小。
17    MD5Init(&context);
18    while(1)
19    {
20        f_lseek(&File,offset);
21        result = f_read(&File,file_buffer,2048,&BytesRead);
22        if(result || BytesRead==0)
23        {
24             DEBUG_LOG(DEBUG_FW,("read %s error!\n",fw_name));
25             return 0;
26        }
27        MD5Update(&context, file_buffer, BytesRead);
28        
29        offset+=BytesRead;
30        if(offset==file_size)
31              break;
32    }
33     
34     MD5Final(digest, &context);
35     f_close(&File);
36     for (i = 0; i < 16; i++)
37         rt_sprintf(cal_md5_str+(i*2),"%02X",digest[i]);
38     
39     DEBUG_LOG(DEBUG_FW,("cal_md5:%s\n",cal_md5_str));
40     
41     return cal_md5_str;
42 }
View Code

就計算個MD5值的代碼,計算不對。不知道問題出在哪里,MD5算法是之前移植好,實驗無誤的。就吧這個函數有關的,全部弄到我的另一個工程,實驗計算正確!這就納悶了呀。工程本身的問題?玄學?

於是,(我在這個函數,又添加了些代碼,試圖讀回讀出的文件。結果MD5計算值變了,但不對。——以上為胡亂嘗試,無頭蒼蠅,瞎試)。我把第4行 弄到外邊 讓File作為全局變量,竟然正確了。

再次弄進來讓它作為局部變量,還是錯誤。立刻認識到可能是Stack_size設置小了,導致File里的數據在入棧出棧的時候發生錯誤了。於是我把Statck_size由0x400改為0x800,於是就好了。

還有一次,同事調用了文件系統的API,導致莫名進入硬件錯誤中斷,查找一番,找不到哪里硬件操作不當,於是想到了可能stack不夠用,於是把stack_size調大后,就正常了。

這里引出幾個問題:

1 描述stm32的Stack_Mem,Heap_Mem的作用。

棧(stack)空間,用於局部變量,函數調時現場保護和返回地址,函數的形參等。
堆(heap)空間,主要用於動態內存分配,也就是說用 malloc,calloc, realloc 等函數分配的變量空間

2 怎么在早期意識到Stack_size可能不夠用,即怎么估計我最大要用到的Stacks_size的大小?
首先,使用GUI和文件系統的時候,是要調大stack_size的。這些是定性的經驗之談,那么怎么定量呢?

工程全編譯,且無誤后,到obj文件夾找到與工程同名的.htm文件。
開頭就有最大棧深度的大小

 

 繼續往下翻,還可以看到具體的每個函數用到的棧的大小。

3 用rtos加持的stm32的Stack_Mem,Heap_Size的作用。
RTOS有自己的任務棧,不再使用這里,僅RTOS啟動前和中斷以及中斷嵌套才使用這里,這里的棧被稱為系統棧,而uCOS又略有不同,uCOS把系統棧也接管了。
Heap_Size作為裸機時,malloc,calloc, realloc 等函數用於分配動態內存。如果RTOS有自己的一套動態內存機制,這不受這個Heap_Size限制,而由那套機制限定。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM