天天看點

如何禁止KEIL初始化RAM為零& 如何判斷是軟複位還是上電複位[轉載]黑-月

http://www.csdn123.com/itweb.php?url=aHR0cDovL3d3dy5jbmJsb2dzLmNvbS9oZWl5dWUvYXJjaGl2ZS8yMDEzLzA4LzA5LzMyNDg3MTcuaHRtbA==

一篇非常棒的文章:

作者非常厲害!!!很沉穩!!!

細心嚴謹!!

黑-月

人在江湖!

如何禁止KEIL初始化RAM為零& 如何判斷是軟複位還是上電複位

(1)如何禁止KEIL初始化RAM為零?

1. 在KEIL Noinit 打鈎

2. <1> 另須對需要熱啟動保持的變量用 _at_ 關鍵字指定某個區域,否則還是沒用

    <2>或者__attribute__((zero_init)) 關鍵字

(2) 對STM32如何判斷是軟複位還是上電複位?

如何禁止KEIL初始化RAM為零&amp; 如何判斷是軟複位還是上電複位[轉載]黑-月
flag = RCC_GetFlagStatus(RCC_FLAG_SFTRST); //上電複位flag=0, 軟體複位flag=1

void RestStm32Cpu(void)
{ 
  __set_FAULTMASK(1); // 關閉所有中端
  NVIC_SystemReset(); // 複位
}      
如何禁止KEIL初始化RAM為零&amp; 如何判斷是軟複位還是上電複位[轉載]黑-月

  常把單片機系統的複位分為冷啟動和熱啟動。所謂冷啟動,也就是一般所說的上電複位,冷啟動後片内外RAM的内容是随機的,通常是0x00或0xFF;單片機的熱啟動是通過外部電路給運作中的單片機的複位端一複位電平而實作的,也就是所說的按鍵複位或看門狗複位。複位後,RAM的内容都沒有改變。在某些場合,必須區分出裝置的重新開機是熱重新開機還是冷重新開機。常用的方法是:确定某記憶體機關為标志位(如0x40003FF4~0x40003FF7 RAM單元),啟動時首先讀該記憶體單元的内容,如果它等于一個特定的值(例如為0xAA55AA55),就認為是熱啟動,否則就是冷啟動。

根據以上的設計思路思路定義一個變量:

  uint32 unStartFlag;

  在程式啟動時判斷:

如何禁止KEIL初始化RAM為零&amp; 如何判斷是軟複位還是上電複位[轉載]黑-月
if(unStartFlag==0xAA55AA55)
{
    //熱啟動處理
}
else
{
    //冷啟動處理
    unStartFlag=0xAA55AA55;
}      
如何禁止KEIL初始化RAM為零&amp; 如何判斷是軟複位還是上電複位[轉載]黑-月

  然而實際調試中發現,無論是熱啟動還是冷啟動,開機後所有記憶體單元的值都被複位為0,當然也實作不了熱啟動的要求。通過看keil MDK自帶的啟動代碼Startup.s,在這個啟動代碼中也并沒有發現将整個RAM區域清零的語句。反彙程式設計式,發現從啟動代碼執行結束到跳轉到main函數過程中,編譯器還執行了很多庫函數,其中__scatterload_zeroinit函數将所有W/R RAM都初始化為0(預設設定下)。為了判斷冷、熱啟動,必須人為控制某些特定RAM在複位時不被編譯器初始化為0。通過查找編譯器手冊,為處理器的RAM中分出一塊小片RAM,設定為NoInit格式(不對其初始化為0),如下圖:

如何禁止KEIL初始化RAM為零&amp; 如何判斷是軟複位還是上電複位[轉載]黑-月

然後使用__at關鍵字将冷、熱啟動标志位定位到這個NoInit區域:

uint32 unStartFlag __at (0x40003FF4);

這樣,當熱啟動時,變量unStartFlag所在的記憶體區域就不會被初始化為0,也實作了冷熱啟動的判斷。

定義鐵電0xFF7~0xFF8區域存儲冷啟動次數

0xFF9~0xFFA區域存儲熱啟動次數

0xFFB~0xFFC區域存儲總啟動次數

另一種方法:

如何禁止KEIL初始化RAM為零&amp; 如何判斷是軟複位還是上電複位[轉載]黑-月

繼續閱讀