最近一直埋頭于設計的撰寫當中,成天大眼對小眼地面對著word、viso和知網客戶端等等文字編輯工具真是有種麻木的趕腳,不寫不知道,一寫嚇一跳,感覺讓我寫上幾萬行代碼也比坐在電腦面前憋出幾萬字論文來的輕巧,“問君能有幾多愁,恰似一江春水向東流”,哎,突然間發現,人生最最痛苦的不是人死了錢沒花了,而是寫了十幾天的論文才發現,暈,還有一多半沒寫呢,不過木有辦法,只能硬著頭皮上了,再此之前還是更篇博客為好,不然該沉底落灰了(話說貌似斷更了好長時間了,不過幸好不是寫小說,不然該被拍磚了),哈哈~
閑話少說,下面進入正題。其實關于Flash調試和RAM調試的概念,我也是從調試Kinetis的時候才開始接觸,最初只是隨便用用,沒有深究,之后用的多了才開始深入研究兩者之間的區別,發現里面大有文章可作,這也是我為什么后來又把本文的前綴改成【原創精品】的緣故,翻看了網上的一些資料,大多是授人以魚的文章,所以覺著有必要在這里談談自己的一點看法,做個筆記:

上圖為在IAR環境下的Flash調試界面和RAM調試界面
首先說說什么是Flash調試和RAM調試,Flash調試就是通常意義下的普通調試,即將編譯鏈接之后的code下載到單片機的ROM區,數據放到RAM區,然后進行調試;而RAM調試則是將數據放到RAM區的同時再從RAM區中額外開辟出一段空間存放可執行code,這樣就是code和數據同時運行在RAM區里面。
至于為什么要刻意區分出這兩種調試方式,其實在低端MCU領域是沒有RAM調試這個概念的,其中很大一部分原因是它沒有足夠大的RAM空間在存放編譯后code代碼的同時仍然可以拿出額外的空間作為數據RAM的,而在高端MCU領域中,比如ARM,動輒幾十KB的RAM是很常見的,在不運行超大工程的情況下是完全可以拿出一部分空間運行代碼的,所以也就出現了RAM調試這種方法了。
相比于Flash調試,RAM調試則與生俱來的帶來兩個最大的先天優勢,一個是RAM的可擦寫的次數理論上是無限的,在調試代碼的期間我們往往是需要不斷下載更新的,而Flash的擦寫次數是有限的(一般幾萬次、幾十萬次不等,雖然看起來足夠多,但是也心疼的慌),因此在調試期間我們可以選擇RAM調試;另一個方面,則更是RAM調試的強項(Flash真夠悲催的),在RAM區的代碼執行速率和效率遠高于需要不斷地讀寫Flash區代碼的,這點毋庸置疑,所以在當今智能手機比拼硬件的時代,我們選擇一款強大的CPU是應該的,但是要想讓系統運行的更流暢,足夠大的機載RAM是必須的,呵呵。當然RAM調試的缺點是掉電丟失,在RAM區運行的代碼在掉電的情況下是不會被保存的,下次上電單片機仍然會執行Flash區內部的老的代碼,這點是需要注意的,很多人忘記考慮這點,在RAM調試功能完畢,等拿到現場單片機獨立運行的時候卻發現程序是不對的,咳咳,那當然不對啦。。。
理論部分介紹完畢,下面我們結合IAR開發環境來分析一下怎么實現Flash調試和RAM調試的。其實我們仔細研究發現,Flash調試和RAM調試在IAR下的區別只是.icf配置文件的不同罷了,其實很簡單很容易理解,也就是把單片機的內存映射改變了,下面單拿出兩者不同的部分曬出來(重要部分加了注釋,供參考):
flash調試的256KB_Pflash.icf文件:
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x00000000;/* 中斷向量的起始地址為ROM的首地址 */
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x0;
define symbol __ICFEDIT_region_ROM_end__ = 0x00040000;/* 256k ROM空間 */
define symbol __ICFEDIT_region_RAM_start__ = 0x1fff8410;
define symbol __ICFEDIT_region_RAM_end__ = 0x20000000;
…
define exported symbol __VECTOR_TABLE = 0x00000000;/* 中斷向量表放在ROM區0起始地址 */
define exported symbol __VECTOR_RAM = 0x1fff8000;
…
define symbol __code_start__ = 0x00000410;/* 代碼開始區地址在ROM區 */
…
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place at address mem:__code_start__ { readonly section .noinit };
place in ROM_region { readonly, block CodeRelocate}; /* 將只讀代碼放到ROM區 */
place in RAM_region { readwrite, block CodeRelocateRam,
block CSTACK, block HEAP };
RAM調試的64k_ram.icf文件:
/*-Specials-*/
define symbol __ICFEDIT_intvec_start__ = 0x1fff8000;/* 中斷向量的起始地址為RAM的首地址 */
/*-Memory Regions-*/
define symbol __ICFEDIT_region_ROM_start__ = 0x0;
define symbol __ICFEDIT_region_ROM_end__ = 0x0;/* 將ROM空間置0 */
define symbol __ICFEDIT_region_RAM_start__ = 0x1fff8000;
define symbol __ICFEDIT_region_RAM_end__ = 0x20000000;
…
define exported symbol __VECTOR_TABLE = 0x1fff8000;/* 中斷向量表放在RAM區首地址 */
define exported symbol __VECTOR_RAM = 0x1fff8000;
…
define symbol __code_start__ = 0x1fff8410;/* 將代碼開始區地址在RAM區 */
…
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
place at address mem:__code_start__ { readonly section .noinit };
place in RAM_region { readonly, block CodeRelocate }; /* 將只讀代碼放到RAM區 */
place in RAM_region { readwrite, block CodeRelocateRam,
block CSTACK, block HEAP };
上面的代碼我就不多做詳細解釋了,通過注釋和對比估計大多數博友應該會理解了,不明白的地方歡迎下面留言共同探討,當然,歡迎投票,呵呵。,轉載請注明出處和原作者jicheng0622信息,謝謝理解,再聊,未完待續~
|