XBOOT尺寸裁剪
介紹
- 硬體平臺:全志F1C100s
- 系統:ofollow,noindex" target="_blank">XBOOT (是個集成了驅動和庫的bootloader,沒有OS)
- 工具鏈:gcc-arm-none-eabi
XBOOT預設的配置帶了很多功能,編譯後的尺寸頗大,影響啟動時間。因為XBOOT啟動過程的大部分時間是花在從Flash拷貝程式碼到RAM,所以只要能把編譯結果的尺寸降下來,就可以成比例地加快啟動速度。
在對XBOOT做裁剪優化後,編譯後的尺寸從預設的4MB降至<170kB(不帶圖形系統和Lua),啟動速度完全滿足要求。
裁剪
未優化前,預設編譯結果xboot.bin
尺寸為4MB。
以下的裁剪措施分若干個步驟,可根據自己的需要的功能,只採取部分步驟。
-
去除不用的資原始檔,尺寸減到3.3MB。XBOOT帶了字型、圖片、示例Lua指令碼等資原始檔,如果完全用不著圖形介面,直接刪掉。(如果應用中確實需要用到大量資源,參見本文最後給出的優化方法。)
步驟:
-
刪除
src/romdisk
目錄; -
修改
src/Makefile
,去除$(CP) romdisk .obj
這行,但是保留arch/
下的romdisk
。
-
刪除
-
去除Lua框架,尺寸減到3MB。快速開發點簡單的東西用Lua比較方便,由於我們的產品是用C/C++開發,所以Lua完全用不著。
步驟:
-
修改
src/Makefile
,去除所有lua
、framework
相關的行; - 編譯一下,根據編譯錯誤,刪除程式碼裡相關的引用。
-
修改
-
去除圖形庫,尺寸減到403kB。圖形影象相關的庫比較多,可根據需要裁剪。很多應用場景不需要向量圖形、向量字型,只需要libpng再加上點陣圖字型檔就夠用。
步驟:
-
修改
src/Makefile
,去除zlib
、libpng
、pixman
、cairo
、freetype
、chipmunk
相關的行; -
編譯一下,根據編譯錯誤刪除程式碼裡引用到圖形庫的地方(比如
do_showlogo
)。
-
修改
-
去除shell、command功能,尺寸減到371kB。開發、除錯時可以用用shell,正式產品不需要保留。
步驟:
-
修改
src/Makefile
,去除shell
、command
相關的行; -
刪除
src/arch/arm32/lib/cpu/cmd-*.c
,或移到另外的目錄裡; -
刪除掉
main()
中的do_showlogo
、do_autoboot
、run_shell
呼叫,改為直接呼叫實際的應用程式碼入口; -
編譯一下,根據編譯錯誤刪除程式碼裡幾處引用到
system()
的地方。
-
修改
-
去除不用的驅動,尺寸減到308kB。根據自己的應用需求,刪除不必要的驅動。
步驟:
-
修改
src/Makefile
,去除用不到的driver/xxx
,我這裡只保留了block
、時鐘、console
、dma
、gpio
、i2c
、interrupt
、pwm
、reset
、spi
、uart
、watchdog
等常用外設驅動; -
刪除
mach-f1c100s/driver
裡不用的驅動,或移到單獨的目錄裡。
-
修改
-
去除不用的庫,尺寸減到277kB。
步驟:
-
修改
src/Makefile
,去除libc/charset
、libc/crypto
、fs/xfs
(視自己的需要刪除); 刪除程式碼裡引用到的地方。
-
修改
-
連結時去除未用到的符號,尺寸減到170kB。XBOOT自帶的
libc
和libm
函式都通過EXPORT_SYMBOL
巨集加到了.ksymtab.text
段,所以即使在程式碼中沒有呼叫到,連結時也無法優化掉,白白佔用空間。這個設計本意是為了編譯動態連結庫,不過在當前的XBOOT中並沒有使用。步驟:
-
修改
module.h
,把EXPORT_SYMBOL
巨集定義為空,即:#define EXPORT_SYMBOL(symbol)
; -
修改
mach-f1c100s/xboot.mk
,給LDFLAGS
增加-Wl,--gc-sections
,給MCFLAGS
增加-ffunction-sections -fdata-sections
,讓連結器刪除未用到的符號。
-
修改
-
去除檔案系統。鑑於這個改動涉及很多零散的點,且大多數應用都會需要檔案系統,所以不建議這樣改。如果實在有必要,可以把所有的
fs
和block
驅動去掉,尺寸減到131kB。
以上為功能裁剪和連結優化方法。
資源打包
如果程式中需要用到大量資源,資原始檔預設是放在romdisk中,會增加啟動時間。一個可採取的優化措施是,把非必要的資源單獨放在另一個romdisk中,在啟動後非同步載入。(還未實際驗證過)
先分析XBOOT的程式碼,和romdisk相關的有如下幾處:
-
src/Makefile
最後,sinclude
這句,把原始碼的某個目錄拷貝到.obj
目錄中,用cpio
命令把目錄打包成單個檔案; -
driver/block/romdisk/data.S
和mach-f1c100s/xboot.ld
,把打包後的romdisk檔案連結到單獨的.romdisk
段; -
啟動時,
sys_copyself
中把__image_start
和__image_end
兩個符號之間的內容拷貝到RAM,如上所說.romdisk
段也在此範圍內; -
subsys_init_romdisk
中,用__romdisk_start
和__romdisk_end
符號之間的記憶體建立romdisk,並在subsys_init_rootfs
中掛載到/
。
因此,優化方法是,將非必須(啟動不需要)的資原始檔打包到另一個romdisk,掛載到單獨的目錄下使用。大致做法如下:
- 啟動過程中必須的資源仍然放在預設romdisk中;
-
啟動非必須的資源單獨放到一個原始碼目錄,通過
Makefile
cpio打包成單個檔案; -
xboot.ld
中新增.dataromdisk
段,參照XBOOT的做法,用一個.S
檔案把上一步的打包檔案連結到.dataromdisk
段;該段定義在.data
段之後,因此啟動的時候不會被sys_copyself
拷貝; -
系統啟動之後,參照
sys_copyself
的方法,把.dataromdisk
段拷到RAM; -
按照
subsys_init_romdisk
和subsys_init_rootfs
的做法,初始化另一個romdisk,掛載到/data
。