最近將rt-thread移植到W806上,從stm32F103的rt-htread工程代碼移植到W806,基本的GPIO和UART修改後能通過,但運行出錯。經過排查,問題出現在函數rt_components_board_init()中的__rt_init_rti_board_start的宏定義INIT_EXPORT(fn,level),凡是用到了對宏定義INIT_EXPORT(fn,level)的變量調用,編譯後對結構體變量rt_object_container[]的內存空間都造成了破壞,而且內存破壞的結果很奇怪,原內存數據整體向後移動了若幹字節。相同的代碼在stm32F103下編譯後運行沒有問題。我已將該問題在聯盛德官方提供W806的DEMO工程代碼WM_SDK_W806上複現了,我已經檢查了startup.s和gcc_csky.ld,未發現什麼錯誤,目前懷疑可能是編譯工具鏈在編譯處理時有bug,編譯是在WIN下,編譯工具鏈是csky-elfabiv2-tools-mingw-minilibc-20210423.tar.gz(我查了下是最新版本,下載地址:https://occ.t-head.cn/community/download?id=3885366095506644992)。
問題描述如下:
正常編譯後rt_object_container指向的內存空間前4字節應該是01000000,但實際編譯後rt_object_container指向的內存空間前4字節是00000000,之前懷疑是startup.s啟動初始化到main函數這個階段對內存作了修改,但沒發現有內存拷貝的調用,故懷疑編譯工具鏈的bug。問題的重點是在宏定義INIT_EXPORT(fn,level)和這個宏定義所聲明的變量__rt_init_rti_board_start被調用了,這兩個關鍵點同時滿足,編譯後就會對內存造成破壞。
以下是WM_SDK_W806修改後複現該問題的工程代碼(主要是增加了main.h和修改了main.c部分代碼)。
WM_SDK_W806_DEBUG.zip
編譯WM_SDK_W806的步驟:
1. 需要下載編譯工具鏈解壓到適當的目錄,
2. 修改WM_SDK_W806代碼工程中的文件.config下的工具鏈路徑CONFIG_W800_TOOLCHAIN_PATH,
3. WM_SDK_W806目錄下直接直接執行make。
請官方技術支持或有餘力的同仁幫助分析下bug原因,是否有其他出錯可能。
下載了你的demo,關於你上述的問題暫時還沒有騰出來時間去驗證,但是發現了一個問題,感覺你沒有理解 INIT_EXPORT 宏的 作用是什麼,要想使用該宏 是需要更改鏈接腳本的,因為 INIT_EXPORT 宏的作用就是把函數的地址,按照順序放到 section 段內,你如果不指定的話,gcc 編譯在鏈接腳本裡找不到該section 的描述,就會忽略此限定詞,你可以參考RTthread 官方 BSP 中 CK802的鏈接腳本的寫法進行更改。這是我的一點拙見哈
RT_USED const init_fn_t __rt_init_##fn SECTION(".rti_fn." level) = &fn;
__rt_init_start = .;
KEEP(*(SORT(.rti_fn*)))
__rt_init_end = .;
非常感謝,已經驗證了,確實是鏈接腳本缺少對INIT_EXPORT宏的section 段指定。