當(dāng)前位置:首頁(yè) > 單片機(jī) > 單片機(jī)
[導(dǎo)讀] 一些產(chǎn)品,當(dāng)系統(tǒng)復(fù)位后(非上電復(fù)位),可能要求保持住復(fù)位前RAM中的數(shù)據(jù),用來(lái)快速恢復(fù)現(xiàn)場(chǎng),或者不至于因瞬間復(fù)位而重啟現(xiàn)場(chǎng)設(shè)備。而keil mdk在默認(rèn)情況下,任何形式的復(fù)位都會(huì)將RAM區(qū)的非初始化變量數(shù)據(jù)清零。

一些產(chǎn)品,當(dāng)系統(tǒng)復(fù)位后(非上電復(fù)位),可能要求保持住復(fù)位前RAM中的數(shù)據(jù),用來(lái)快速恢復(fù)現(xiàn)場(chǎng),或者不至于因瞬間復(fù)位而重啟現(xiàn)場(chǎng)設(shè)備。而keil mdk在默認(rèn)情況下,任何形式的復(fù)位都會(huì)將RAM區(qū)的非初始化變量數(shù)據(jù)清零。如何設(shè)置非初始化數(shù)據(jù)變量不被零初始化,這是本篇文章所要探討的。

在給出方法之前,先來(lái)了解一下代碼和數(shù)據(jù)的存放規(guī)則、屬性,以及復(fù)位后為何默認(rèn)非初始化變量所在RAM都被初始化為零了呢。

什么是初始化數(shù)據(jù)變量,什么又是非初始化數(shù)據(jù)變量?(因?yàn)槲业奈淖置枋霾灰欢?zhǔn)確,所以喜歡舉一些例子來(lái)輔助理解文字。)

定義一個(gè)變量:int nTimerCount=20;變量nTimerCount就是初始化變量,也就是已經(jīng)有初值;

如果定義變量:int nTimerCount;變量nTimerCount就是一個(gè)非賦值的變量,Keil MDK默認(rèn)將它放到屬性為ZI的輸入節(jié)。

那么,什么是“ZI”,什么又是“輸入節(jié)”呢?這要了解一下ARM映像文件(image)的組成了,這部分內(nèi)容略顯無(wú)聊,但我認(rèn)為這是非常有必要掌握的。

ARM映像文件的組成:

一個(gè)映像文件由一個(gè)或多個(gè)域(region,也有譯為“區(qū)”)組成

每個(gè)域包含一個(gè)或多個(gè)輸出段(section,也有譯為“節(jié)”)

每個(gè)輸出段包含一個(gè)或多個(gè)輸入段

各個(gè)輸入段包含了目標(biāo)文件中的代碼和數(shù)據(jù)

輸入段中包含了四類(lèi)內(nèi)容:代碼、已經(jīng)初始化的數(shù)據(jù)、未經(jīng)過(guò)初始化的存儲(chǔ)區(qū)域、內(nèi)容初始化為零的存儲(chǔ)區(qū)域。每個(gè)輸入段有相應(yīng)的屬性:只讀的(RO)、可讀寫(xiě)的(RW)以及初始化成零的(ZI)。

一個(gè)輸出段中包含了一些列具有相同的RO、RW和ZI屬性的輸入段。輸出段屬性與其中包含的輸入段屬性相同。

一個(gè)域包含一到三個(gè)輸出段,各個(gè)輸出段的屬性各不相同:RO屬性、RW屬性和ZI屬性

到這里我們就可以知道,一般情況下,代碼會(huì)被放到RO屬性的輸入節(jié),已經(jīng)初始化的變量會(huì)被分配到RW屬性輸入?yún)^(qū),而“ZI”屬性輸入節(jié)可以理解為是初始化成零變量的集合。

已經(jīng)初始化變量的初值,會(huì)被放到硬件的哪里呢?(比如定義int nTimerCount=20;那么初始值20被放到哪里呢?),我覺(jué)得這是個(gè)有趣的問(wèn)題,比如keil在編譯完成后,會(huì)給出編譯文件大小的信息,如下所示:

Total RO Size (Code + RO Data) 54520 ( 53.24kB)
Total RW Size (RW Data + ZI Data) 6088 ( 5.95kB)
Total ROM Size (Code + RO Data + RW Data) 54696 ( 53.41kB)

很多人不知道這是怎么計(jì)算的,也不知道究竟放入ROM/Flash中的代碼有多少。其實(shí),那些已經(jīng)初始化的變量,是被放入RW屬性的輸入節(jié)中,而這些變量的初值,是被放入ROM/Flash中的。有時(shí)候這些初值的量比較大,Keil還會(huì)將這些初值壓縮后再放入ROM/Flash以節(jié)省存儲(chǔ)空間。那這些初值是誰(shuí)在何時(shí)將它們恢復(fù)到RAM中的?ZI屬性輸入節(jié)中的變量所在RAM又是誰(shuí)在何時(shí)給用零初始化的呢?要了解這些東西,就要看默認(rèn)設(shè)置下,從系統(tǒng)復(fù)位,到執(zhí)行C代碼中你編寫(xiě)的main函數(shù),Keil幫你做了些什么。

硬件復(fù)位后,第一步是執(zhí)行復(fù)位處理程序,這個(gè)程序的入口在啟動(dòng)代碼里(默認(rèn)),摘錄一段cortex-m3的復(fù)位處理入口代碼:

1:Reset_HandlerPROC;PROC等同于FUNCTION,表示一個(gè)函數(shù)的開(kāi)始,與ENDP相對(duì)?
2:
3:EXPORTReset_Handler[WEAK]
4:IMPORTSystemInit
5:IMPORT__main
6:LDRR0,=SystemInit
7:BLXR0
8:LDRR0,=__main
9:BXR0
10:ENDP

初始化堆棧指針、執(zhí)行完用戶(hù)定義的底層初始化代碼(SystemInit函數(shù))后,接下來(lái)的代碼調(diào)用了__main函數(shù),這里__main函數(shù)會(huì)調(diào)用一些列的C庫(kù)函數(shù),完成代碼和數(shù)據(jù)的復(fù)制、解壓縮以及ZI數(shù)據(jù)的零初始化。數(shù)據(jù)的解壓縮和復(fù)制,其中就包括將儲(chǔ)存在ROM/Flash中的已初始化變量的初值復(fù)制到相應(yīng)的RAM中去。對(duì)于一個(gè)變量,它可能有三種屬性,用const修飾符修飾的變量最可能放在RO屬性區(qū),已經(jīng)初始化的變量會(huì)放在RW屬性區(qū),那么剩下的變量就要放到ZI屬性區(qū)了。默認(rèn)情況下,ZI數(shù)據(jù)的零初始化會(huì)將所有ZI數(shù)據(jù)區(qū)初始化為零,這是每次復(fù)位后程序執(zhí)行C代碼的main函數(shù)之前,由編譯器“自作主張”完成的。所以我們要在C代碼中設(shè)置一些變量在復(fù)位后不被零初始化,那一定不能任由編譯器“胡作非為”,我們要用一些規(guī)則,約束一下編譯器。

分散加載文件對(duì)于連接器來(lái)說(shuō)至關(guān)重要,在分散加載文件中,使用UNINIT來(lái)修飾一個(gè)執(zhí)行節(jié),可以避免__main對(duì)該區(qū)節(jié)的ZI數(shù)據(jù)進(jìn)行零初始化。這是要解決非零初始化變量的關(guān)鍵。因此我們可以定義一個(gè)UNINIT修飾的數(shù)據(jù)節(jié),然后將希望非零初始化的變量放入這個(gè)區(qū)域中。于是,就有了第一種方法:

1. 修改分散加載文件,增加一個(gè)名為MYRAM的執(zhí)行節(jié),該執(zhí)行節(jié)起始地址為0x1000A000,長(zhǎng)度為0x2000字節(jié)(8KB),由UNINIT修飾:

1:LR_IROM10x000000000x00080000{;loadregionsize_region
2:ER_IROM10x000000000x00080000{;loadaddress=executionaddress
3:*.o(RESET,+First)
4:*(InRoot$$Sections)
5:.ANY(+RO)
6:}
7:RW_IRAM10x100000000x0000A000{;RWdata
8:.ANY(+RW+ZI)
9:}
10:MYRAM0x1000A000UNINIT0x00002000{
11:.ANY(NO_INIT)
12:}
13:}

那么,如果在程序中有一個(gè)數(shù)組,你不想讓它復(fù)位后零初始化,就可以這樣來(lái)定義變量:

    
unsignedcharplc_eu_backup[PLC_EU_BACKUP_BUF/8]__attribute__((at(0x1000A000)));

變量屬性修飾符__attribute__((at(adder)))用來(lái)將變量強(qiáng)制定位到adder所在地址處。由于地址0x1000A000開(kāi)始的8KB區(qū)域ZI變量不會(huì)被零初始化,所以處在這一區(qū)域的數(shù)組plc_eu_backup也就不會(huì)被零初始化了。

這種方法的缺點(diǎn)是顯而易見(jiàn)的:要自己分配變量的地址,如果非零初始化數(shù)據(jù)比較多,這將是件難以想象的大工程(以后的維護(hù)、增加、修改代碼等等)。所以要找到一種辦法,讓編譯器去自動(dòng)分配這一區(qū)域的變量。

2. 分散加載文件同方法1,如果還是定義一個(gè)數(shù)組,可以用下面方法:

unsignedcharplc_eu_backup[PLC_EU_BACKUP_BUF/8]__attribute__((section("NO_INIT"),zero_init));

變量屬性修飾符__attribute__((section(“name”),zero_init))用于將變量強(qiáng)制定義到name屬性數(shù)據(jù)節(jié)中,zero_init表示將未初始化的變量放到ZI數(shù)據(jù)節(jié)中。因?yàn)椤癗O_INIT”這顯性命名的自定義節(jié),具有UNINIT屬性。(強(qiáng)烈推薦最簡(jiǎn)單的方法)

3. 如何將一個(gè)模塊內(nèi)的非初始化變量都非零初始化?

假如該模塊名字為test.c,修改分散加載文件如下所示:

1:LR_IROM10x000000000x00080000{;loadregionsize_region
2:ER_IROM10x000000000x00080000{;loadaddress=executionaddress
3:*.o(RESET,+First)
4:*(InRoot$$Sections)
5:.ANY(+RO)
6:}
7:RW_IRAM10x100000000x0000A000{;RWdata
8:.ANY(+RW+ZI)
9:}
10:RW_IRAM20x1000A000UNINIT0x00002000{
11:test.o(+ZI)
12:}
13:}

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專(zhuān)欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車(chē)的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車(chē)技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車(chē)工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車(chē)。 SODA V工具的開(kāi)發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車(chē) 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來(lái)越多用戶(hù)希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來(lái)越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開(kāi)幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱(chēng),數(shù)字世界的話語(yǔ)權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱(chēng)"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉