Placing Data into ROM

幾乎每個(gè)嵌入式程序都需要處理一些不變的數(shù)據(jù)量魔策;也就是在程序運(yùn)行的時(shí)候這些量的值不會(huì)發(fā)生改變氓皱。舉個(gè)例子滞造,我認(rèn)為大多數(shù)人會(huì)覺得相當(dāng)吃驚续室,當(dāng)調(diào)用:

                                 printf("Hello");

后輸出的不是Hello字符串。很明顯谒养,像"Hello"這樣的字符串應(yīng)該是不變的量挺狰。除了文字常量,許多程序還需要配置數(shù)據(jù)买窟,狀態(tài)轉(zhuǎn)換表丰泊,或者常數(shù)系數(shù),這些都應(yīng)該是不變的始绍。我們通常將不變的量稱為只讀的瞳购,與之相反的是可以讀寫的變量。

在許多桌面應(yīng)用中亏推,只是邏輯上而不是物理上區(qū)分只讀和讀寫学赛。鏈接器可能將所有的只讀數(shù)據(jù)放在一個(gè)數(shù)據(jù)段中來(lái)給促進(jìn)程序加載到內(nèi)存中去。

在許多嵌入式系統(tǒng)中吞杭,只讀和讀寫不僅僅只是邏輯上的區(qū)別了盏浇。大多數(shù)嵌入式系統(tǒng)程序不像桌面應(yīng)用程序那樣從磁盤中加載數(shù)據(jù)。嵌入式系統(tǒng)中芽狗,只讀數(shù)據(jù)將永久保存在ROM中绢掰。很明顯,讀寫數(shù)據(jù)不能放在ROM中童擎;它們必須放在RAM里面滴劲。因此,編譯器必須要能夠區(qū)分讀寫數(shù)據(jù)和只讀數(shù)據(jù)顾复,這樣它才有辦法將只讀數(shù)據(jù)放入ROM中班挖,將讀寫數(shù)據(jù)放入RAM里。

事實(shí)上捕透,就ROM和RAM而言聪姿,在嵌入式系統(tǒng)中都是很缺乏的碴萧。例如乙嘀,一些系統(tǒng)在生產(chǎn)線上讓所有的model使用同一個(gè)控制程序末购,并且為每個(gè)根據(jù)每個(gè)model的需求來(lái)配置相應(yīng)的數(shù)據(jù)。這些系統(tǒng)將二進(jìn)制代碼和只讀數(shù)據(jù)分別放在不同的存儲(chǔ)段中虎谢,以便將數(shù)據(jù)放在ROM中和代碼區(qū)分開來(lái)盟榴。因此,雖然每個(gè)model使用不同的ROM來(lái)存儲(chǔ)配置數(shù)據(jù)婴噩,但是在生產(chǎn)線上每個(gè)model都可以使用相同ROM來(lái)存儲(chǔ)二進(jìn)制代碼擎场。

典型的C/C++嵌入式系統(tǒng)編譯器根據(jù)這些需求,它們將代碼和數(shù)據(jù)映射到以下幾個(gè)不同的邏輯段:

O 代碼(Code)段(也叫<i>text</i>段):只讀段几莽,包含程序代碼
O 文字(Literal)段:只讀段迅办,包含初始化數(shù)據(jù)
O 初始化數(shù)據(jù)(也叫<i>plain data</i>):讀寫段,包含用于程序啟動(dòng)的初始化數(shù)據(jù)
O 未初始化數(shù)據(jù)(也叫<i>bss</i>):讀寫段章蚣,包含一些未初始化的數(shù)據(jù)站欺,直到程序使用到书妻。

編譯器和鏈接器也可以提供一種像#pragma一樣的開關(guān)或者命令使得你可以將一些邏輯段放入一個(gè)物理段中挠说。例如碧囊,你可以將文字常量和代碼固化到ROM中迫肖,也可以和初始化的數(shù)據(jù)一起放入RAM史侣。在這個(gè)段模型下跌造,將文字常量放到ROM中是相當(dāng)容易的足绅。編譯器會(huì)將所有的文字常量收集到文字常量段中析既。鏈接器和其他的后端工具會(huì)確保將文字常量段放入ROM中吼鱼。

將非文字常量放入到ROM中是一個(gè)比較復(fù)雜點(diǎn)的問(wèn)題蓬豁。編譯器必需將初始化的只讀數(shù)據(jù)和初始化的讀寫數(shù)據(jù)區(qū)分開來(lái)。很明顯菇肃,未初始化的數(shù)據(jù)不能是只讀的庆尘,如果這樣的化那么就是沒(méi)用的量,所以它必需放在RAM中巷送。然而驶忌,區(qū)分初始化的數(shù)據(jù)的方法并不是很明顯。

例如笑跛,當(dāng)一個(gè)編譯器遇到如下聲明:

                              unsigned char two_to_the[]
                                = { 1, 2, 4, 8, 16, 32, 128, 256 };

編譯器是將其放入到文字常量段付魔,還是初始化數(shù)據(jù)段中呢?

即使two_to_the是放在RAM中的讀寫數(shù)據(jù)飞蹂,初始化數(shù)據(jù)的復(fù)制本可能出現(xiàn)在ROM中几苍。在程序啟動(dòng)的時(shí)候?qū)⒊跏蓟闹祻腞OM中復(fù)制到RAM。

大多數(shù)嵌入式開發(fā)工具支持將初始化的數(shù)據(jù)放到ROM中陈哑,當(dāng)編譯一個(gè)源文件的時(shí)候妻坝,編譯器將所有初始化的數(shù)據(jù)放到一個(gè)段中伸眶。默認(rèn)情況下這個(gè)段就是初始化數(shù)據(jù)段。然而刽宪,你可以使用一個(gè)編譯器開關(guān)告訴編譯器將初始化的數(shù)據(jù)復(fù)制到文字常量段中厘贼。因此,你可以將所有需要設(shè)置為只讀的數(shù)據(jù)集中到一個(gè)源文件中并使用相應(yīng)的開關(guān)來(lái)將他們放入文字常量段圣拄。這個(gè)方法有一個(gè)要注意的就是你需要根據(jù)你物理上的需求來(lái)整理某些部分嘴秸,而不是邏輯上的。由此你可能會(huì)想將一些只讀量和讀寫數(shù)據(jù)放在使用它們的同一個(gè)源文件中去庇谆,但是不能這樣干岳掐。你必需將只讀數(shù)據(jù)放在一個(gè)單獨(dú)的源文件中,程序需要做出更多的努力來(lái)讀取它們 [1]饭耳。

許多編譯器提供pragmas這樣的開關(guān)串述。它可以在一個(gè)相同文件中將數(shù)據(jù)放到一個(gè)不同的段中。舉個(gè)例子:

                             #pragma data(“l(fā)iteral”)
                             unsigned char two_to_the[]
                               = { 1, 2, 4, 8, 16, 32, 64, 128 };
                             #pragma data()

第一個(gè)pragma告訴編譯器將以下的定義放入到文字常量段中去寞肖。第二個(gè)pragma告訴編譯器返回到之前的段中去纲酗。

不幸的是,編譯器們?cè)趐ragma語(yǔ)法上都不太一樣逝淹,有時(shí)顯得很戲劇性耕姊。C和C++標(biāo)準(zhǔn)都說(shuō)明了pragma語(yǔ)法的存在性,但是沒(méi)有強(qiáng)制編譯器們要支持某種特定的pragma語(yǔ)法栅葡。以此茉兰,使用到pragma的代碼移植性很差。

以上的方法都有一個(gè)問(wèn)題欣簇,就是沒(méi)有提供一種防止對(duì)只讀變量寫操作的方法规脸。一個(gè)編譯器應(yīng)該為以下這種操作報(bào)錯(cuò):

                             two_to_the[i] = 0;

但是不幸的是卻不可以。你可能都不會(huì)注意到這個(gè)錯(cuò)誤直到你運(yùn)行程序熊咽。

接下來(lái)進(jìn)入const修飾符莫鸭。const修飾符可以使得編譯器檢測(cè)到對(duì)只讀數(shù)據(jù)的寫操作。例如:

                             const unsigned char two_to_the[]
                               = { 1, 2, 4, 8, 16, 32, 64, 128 };

將two_to_the定義為“包含只讀數(shù)據(jù)的字符型數(shù)組”横殴。const是two_to_the類型符的一部分被因,編譯器用它來(lái)核實(shí)以后對(duì)two_to_the的操作的合法性。舉個(gè)例子衫仑,在上面的聲明后梨与,下面這樣一個(gè)復(fù)制語(yǔ)句:

                             two_to_the[i] = 0;

是一個(gè)編譯錯(cuò)誤。

僅僅使用const修飾符是不足以將其放入到ROM中去的文狱。你同樣需要使用鏈接器和后端工具將其放入到你想放的位置中去粥鞋。const修飾符只是提供了一個(gè)開始而已。

將數(shù)據(jù)放到ROM僅僅只是const修飾符幾個(gè)用法中的一個(gè)瞄崇。還有呻粹,盡管使用了后端工具相應(yīng)的支持壕曼,在聲明的時(shí)候時(shí)候const修飾符也不一定能確保將數(shù)據(jù)放到ROM中去。因?yàn)槁暶鞅匦铦M足其他的語(yǔ)法限制等浊。在未來(lái)的幾個(gè)月腮郊,我將細(xì)說(shuō)這些限制并且講述const的其他用法。<small>[ESP]</small>

本文是翻譯自: Dan Saks 的 Placing Data into ROM


  1. 此句翻譯可能有誤,如果你發(fā)現(xiàn)有其他錯(cuò)誤凿掂,如有錯(cuò)誤及其它錯(cuò)誤請(qǐng)聯(lián)系我伴榔!gilarus ?

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末纹蝴,一起剝皮案震驚了整個(gè)濱河市庄萎,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌塘安,老刑警劉巖糠涛,帶你破解...
    沈念sama閱讀 222,807評(píng)論 6 518
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異兼犯,居然都是意外死亡忍捡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,284評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門切黔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)砸脊,“玉大人,你說(shuō)我怎么就攤上這事纬霞×韫。” “怎么了?”我有些...
    開封第一講書人閱讀 169,589評(píng)論 0 363
  • 文/不壞的土叔 我叫張陵诗芜,是天一觀的道長(zhǎng)瞳抓。 經(jīng)常有香客問(wèn)我,道長(zhǎng)伏恐,這世上最難降的妖魔是什么孩哑? 我笑而不...
    開封第一講書人閱讀 60,188評(píng)論 1 300
  • 正文 為了忘掉前任,我火速辦了婚禮翠桦,結(jié)果婚禮上横蜒,老公的妹妹穿的比我還像新娘。我一直安慰自己销凑,他們只是感情好丛晌,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,185評(píng)論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著闻鉴,像睡著了一般茵乱。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上孟岛,一...
    開封第一講書人閱讀 52,785評(píng)論 1 314
  • 那天瓶竭,我揣著相機(jī)與錄音督勺,去河邊找鬼。 笑死斤贰,一個(gè)胖子當(dāng)著我的面吹牛智哀,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播荧恍,決...
    沈念sama閱讀 41,220評(píng)論 3 423
  • 文/蒼蘭香墨 我猛地睜開眼瓷叫,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了送巡?” 一聲冷哼從身側(cè)響起摹菠,我...
    開封第一講書人閱讀 40,167評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎骗爆,沒(méi)想到半個(gè)月后次氨,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,698評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡摘投,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,767評(píng)論 3 343
  • 正文 我和宋清朗相戀三年煮寡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片犀呼。...
    茶點(diǎn)故事閱讀 40,912評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡幸撕,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出外臂,到底是詐尸還是另有隱情坐儿,我是刑警寧澤,帶...
    沈念sama閱讀 36,572評(píng)論 5 351
  • 正文 年R本政府宣布专钉,位于F島的核電站挑童,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏跃须。R本人自食惡果不足惜站叼,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,254評(píng)論 3 336
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望菇民。 院中可真熱鬧尽楔,春花似錦、人聲如沸第练。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,746評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)娇掏。三九已至呕寝,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間婴梧,已是汗流浹背下梢。 一陣腳步聲響...
    開封第一講書人閱讀 33,859評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工客蹋, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人孽江。 一個(gè)月前我還...
    沈念sama閱讀 49,359評(píng)論 3 379
  • 正文 我出身青樓讶坯,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親岗屏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子辆琅,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,922評(píng)論 2 361

推薦閱讀更多精彩內(nèi)容