www.久久久久|狼友网站av天堂|精品国产无码a片|一级av色欲av|91在线播放视频|亚洲无码主播在线|国产精品草久在线|明星AV网站在线|污污内射久久一区|婷婷综合视频网站

當(dāng)前位置:首頁 > 公眾號精選 > 嵌入式微處理器
[導(dǎo)讀]之前做過一次 uboot的升級,當(dāng)時留下了一些記錄,本文摘錄其中比較有意思的兩個問題。

背景

之前做過一次 uboot的升級,當(dāng)時留下了一些記錄,本文摘錄其中比較有意思的兩個問題。

啟動失敗問題

問題簡述

uboot代碼中用到了一個庫,考慮到庫本身跟 uboot版本沒什么關(guān)系,就直接把舊的庫文件拷貝過來使用。結(jié)果編譯鏈接是沒問題,啟動卻會卡住。

消失的打印

為了明確卡住的位置,就去修改了庫的源碼,添加一些打?。ù藭r還是在舊版本 uboot下編譯的),結(jié)果發(fā)現(xiàn)卡住的位置或隨著添加打印的變化而變化,且有些打印語句,添加后未打印出來。
我決定先從這些神秘消失的打印入手。
分析下 uboot中的 printf實現(xiàn),最底層就是寫寄存器,是一個同步的函數(shù),也沒什么可疑的地方。
為了確認打印不出來的時候,到底有沒有調(diào)用到 printf,我決定給 printf增加一個計數(shù)器,在 gd結(jié)構(gòu)體中,增加一個 printf_count字段,初始化為 0,每次打印時執(zhí)行 printf_count++并打印出值。
設(shè)計這個試驗,本意是確認未打印出來時是否確實也調(diào)用到了 printf,但卻有了別的發(fā)現(xiàn),實驗結(jié)果中 printf_count值會異常變化,不是按打印順序遞增,而是會突變成很大的異常值。
printf_countgd結(jié)構(gòu)體的成員,那就是 gd的問題了。進一步將 uboot全局結(jié)構(gòu)體 gd的地址打印出來。確認了原因是 gd結(jié)構(gòu)體的指針變化了。
這也可以解釋部分打印消失的現(xiàn)象,原因是我們在 gd中有另一個字段,用于控制打印等級。當(dāng) gd被改動了, printf就可能解析出錯,誤以為打印等級為 0而提前返回。

gd的實現(xiàn)

那么好端端的, gd為什么會被改了呢?這就要先看看 gd到底是怎么實現(xiàn)的了。
uboot中維護了一個全局的結(jié)構(gòu)體 gd。在代碼中加入

    
DECLARE_GLOBAL_DATA_PTR;
即可使用 gd指針訪問這個全局結(jié)構(gòu)體,許多地方都會借助 gd來保存?zhèn)鬟f信息。
進一步看看這個宏的定義

    
舊版本uboot:
#define?DECLARE_GLOBAL_DATA_PTR????????register?volatile?gd_t?*gd?asm?("r8")

新版本uboot:
#define?DECLARE_GLOBAL_DATA_PTR????????register?volatile?gd_t?*gd?asm?("r9")
居然不一樣,一個是將 gd的值放到 r8寄存器,一個是放在 r9寄存器。
那么就可以猜測到,庫是在舊版本 uboot中編譯出來的,可能使用了 r9,那么放到新版本 uboot中去,就會破壞 r9寄存器中保存的 gd值,導(dǎo)致一系列依賴 gd的代碼不能正常工作。

驗證改動

為了求證,將庫反匯編出來,發(fā)現(xiàn)確實避開了 r8寄存器,但使用了 r9寄存器。
說明 uboot在指定 gd寄存器的同時,還有某種方法讓其他代碼不使用這個寄存器。
那是不是把舊 uboot中的這個 r8改成 r9,重新編譯庫就可以了呢?試一下,還是不行。
那么禁止其他代碼使用 r8寄存器肯定就是通過別的方式實現(xiàn)的了。簡單粗暴地在舊版本 uboot下搜索 r8,去掉 .c .h等類型后,很容易發(fā)現(xiàn)了

    
./arch/arm/cpu/armv7/config.mk:24:PLATFORM_RELFLAGS?+=?-fno-common?-ffixed-r8?-msoft-floa
-ffixed-r8修改為 -ffixed-r9,重新編譯出庫,這回就可以正常工作了,打印正常,啟動正常。反匯編出來也可以看到,新編譯出來的庫用了 r8沒有用 r9。
當(dāng)然更好的改法,是直接在新版本的 uboot中編譯,這是最可靠的。

追本溯源

話說回來,為什么兩個版本的 uboot,會使用不同的寄存器呢?難道有什么坑?
這就得去翻一下 git記錄了。

    
commit?fe1378a961e508b31b1f29a2bb08ba1dac063155
Author:?Jeroen?Hofstee?
Date:???Sat?Sep?21?14:04:41?2013?+0200

????ARM:?use?r9? for?gd
????
????To?be?more?EABI?compliant?and?as?a?preparation? for?building
????with?clang,?use?the?platform-specific?r9?register? for?gd
????instead?of?r8.
????
????note:?The?FIQ?is?not?updated?since?it?is?not?used? in?u-boot,
????and?under?discussion? for?the?time?being.
????
????The?following?checkpatch?warning?is?ignored:
????WARNING:?Use?of?volatile?is?usually?wrong:?see
????Documentation/volatile-considered-harmful.txt
????
????Signed-off-by:?Jeroen?Hofstee?
????cc:?Albert?ARIBAUD?
git記錄中,也可以確認完整地將 r8切換到 r9,都需要做哪些修改

    
diff?--git?a/arch/arm/config.mk?b/arch/arm/config.mk
index? 16c2e3d1e0..d0cf43ff41? 100644
---?a/arch/arm/config.mk
+++?b/arch/arm/config.mk
@@? -17, 7?+ 17, 7?@@?endif
?
?LDFLAGS_FINAL?+=?--gc-sections
?PLATFORM_RELFLAGS?+=?-ffunction-sections?-fdata-sections?\
-?????????????????????-fno-common?-ffixed-r8?-msoft- float
+?????????????????????-fno-common?-ffixed-r9?-msoft- float
?
?#?Support?generic?board?on?ARM
?__HAVE_ARCH_GENERIC_BOARD?:=?y
diff?--git?a/arch/arm/cpu/armv7/lowlevel_init.S?b/arch/arm/cpu/armv7/lowlevel_init.S
index? 82b2b86520. .69e3053a42? 100644
---?a/arch/arm/cpu/armv7/lowlevel_init.S
+++?b/arch/arm/cpu/armv7/lowlevel_init.S
@@? -22, 11?+ 22, 11?@@?ENTRY(lowlevel_init)
????????ldr?????sp,?=CONFIG_SYS_INIT_SP_ADDR
????????bic?????sp,?sp,?# 7? /*?8-byte?alignment?for?ABI?compliance?*/
?#ifdef?CONFIG_SPL_BUILD
-???????ldr?????r8,?=gdata
+???????ldr?????r9,?=gdata
?# else
????????sub?????sp,?#GD_SIZE
????????bic?????sp,?sp,?# 7
-???????mov?????r8,?sp
+???????mov?????r9,?sp
?#endif
???????? /*
?????????*?Save?the?old?lr(passed?in?ip)?and?the?current?lr?to?stack
diff?--git?a/arch/arm/include/asm/global_data.h?b/arch/arm/include/asm/global_data.h
index?79a9597419..e126436093?100644
---?a/arch/arm/include/asm/global_data.h
+++?b/arch/arm/include/asm/global_data.h
@@?-47,6?+47,6?@@?struct?arch_global_data?{
?
?#include?
?
-#define?DECLARE_GLOBAL_DATA_PTR?????register?volatile?gd_t?*gd?asm?("r8")
+#define?DECLARE_GLOBAL_DATA_PTR?????register?volatile?gd_t?*gd?asm?("r9")
?
?#endif?/*?__ASM_GBL_DATA_H?*/

diff?--git?a/arch/arm/lib/crt0.S?b/arch/arm/lib/crt0.S
index? 960d12e732..ac54b9359a? 100644
---?a/arch/arm/lib/crt0.S
+++?b/arch/arm/lib/crt0.S
@@? -69, 7?+ 69, 7?@@?ENTRY(_main)
????????bic?????sp,?sp,?# 7?????? /*?8-byte?alignment?for?ABI?compliance?*/
????????sub?????sp,?#GD_SIZE???? /*?allocate?one?GD?above?SP?*/
????????bic?????sp,?sp,?# 7?????? /*?8-byte?alignment?for?ABI?compliance?*/
-???????mov?????r8,?sp?????????? /*?GD?is?above?SP?*/
+???????mov?????r9,?sp?????????? /*?GD?is?above?SP?*/
????????mov?????r0,?# 0
????????bl??????board_init_f
?
@@? -81, 15?+ 81, 15?@@?ENTRY(_main)
??*? 'here'?but?relocated.
??*/
?
-???????ldr?????sp,?[r8,?#GD_START_ADDR_SP]????? /*?sp?=?gd->start_addr_sp?*/
+???????ldr?????sp,?[r9,?#GD_START_ADDR_SP]????? /*?sp?=?gd->start_addr_sp?*/
????????bic?????sp,?sp,?# 7?????? /*?8-byte?alignment?for?ABI?compliance?*/
-???????ldr?????r8,?[r8,?#GD_BD]???????????????? /*?r8?=?gd->bd?*/
-???????sub?????r8,?r8,?#GD_SIZE???????????????? /*?new?GD?is?below?bd?*/
+???????ldr?????r9,?[r9,?#GD_BD]???????????????? /*?r9?=?gd->bd?*/
+???????sub?????r9,?r9,?#GD_SIZE???????????????? /*?new?GD?is?below?bd?*/
?
????????adr?????lr,?here
-???????ldr?????r0,?[r8,?#GD_RELOC_OFF]????????? /*?r0?=?gd->reloc_off?*/
+???????ldr?????r0,?[r9,?#GD_RELOC_OFF]????????? /*?r0?=?gd->reloc_off?*/
????????add?????lr,?lr,?r0
-???????ldr?????r0,?[r8,?#GD_RELOCADDR]????????? /*?r0?=?gd->relocaddr?*/
+???????ldr?????r0,?[r9,?#GD_RELOCADDR]????????? /*?r0?=?gd->relocaddr?*/
????????b???????relocate_code
?here:
?
@@? -111, 8?+ 111, 8?@@?clbss_l:cmp?r0,?r1?????????????????? /*?while?not?at?end?of?BSS?*/
????????bl?red_led_on
?
???????? /*?call?board_init_r(gd_t?*id,?ulong?dest_addr)?*/
-???????mov?????r0,?r8?????????????????? /*?gd_t?*/
-???????ldr?????r1,?[r8,?#GD_RELOCADDR]? /*?dest_addr?*/
+???????mov?????r0,?r9?????????????????? /*?gd_t?*/
+???????ldr?????r1,?[r9,?#GD_RELOCADDR]? /*?dest_addr?*/
???????? /*?call?board_init_r?*/
????????ldr?????pc,?=board_init_r??????? /*?this?is?auto-relocated!?*/

啟動慢問題

問題簡述

填了幾個坑之后,新的 uboot可以啟動到內(nèi)核了,但發(fā)現(xiàn)啟動速度非常慢,內(nèi)核啟動速度慢了接近 10倍!明明是同一個內(nèi)核,為什么差異這么大。

排查寄存器

初步排查了下設(shè)備樹配置,以及 uboot跳轉(zhuǎn)內(nèi)核前的一些關(guān)鍵寄存器,確實在兩個版本的 uboot中有所不同,但具體去看這些不同,發(fā)現(xiàn)都不會影響速度,將一些驅(qū)動對齊之后寄存器差異基本就消失了。

差異的分界

那再細看, kernel的速度有差異, uboot呢?在哪個時間點之后,速度開始產(chǎn)生差異?
嘗試在兩個版本的 uboot中插入一些操作,對比時間戳,發(fā)現(xiàn)兩個 uboot在某個節(jié)點之后的速度確實有區(qū)別。
進一步排查,原來是在打開 cache操作之后,舊 uboot的速度就會比新 uboot快。嘗試將舊 ubootcache關(guān)掉,則二者基本一致。嘗試將舊 uboot操作 cache的代碼,移植到新 uboot,未發(fā)生改變。
此時可確認新 uboot的開 cache有問題。但覺得這個跟 kernel啟動慢沒關(guān)系。因為 uboot進入 kernel之前都會關(guān) cache,由 kernel自己去重新打開。
也就是不管是用哪份 uboot,也不管 uboot中是否開了 cache,對 kernel階段都應(yīng)該沒有影響才對。
于是記錄下來 uboot的這個問題,待后續(xù)修復(fù)。先繼續(xù)找 kernel啟動慢的原因。(注:現(xiàn)在看來當(dāng)時的做法是有問題的,這里的異常這么明顯,應(yīng)該設(shè)法追蹤下去找出原因才對)

鎖定uboot

uboot的嫌疑非常大,但還不能完全確認,因為 uboot之前還有一級 spl。是否會是 spl的問題呢?
嘗試改用 新spl+舊uboot,啟動速度正常。而新 spl+新uboot的啟動速度則很慢,其他因素都不變,說明問題確實出在 uboot階段。

多做or少做

當(dāng)時到這一步就卡住了,直接比較兩份 uboot的代碼不太現(xiàn)實,差異太大了。
后來我就給自己提了個問題,到底新 uboot是多做了某件事情,還是少做了某件事情?
換個說法,目前已知

    
spl?-->?舊uboot?-->?kernel(速度快)
spl?-->?新uboot?-->?kernel(速度快)
但到底是以下的情況 A還是情況 B呢?

    
A:?spl(速度慢)?-->?舊uboot(做了某個會提升速度的操作)?-->?kernel(速度快)
???spl(速度慢)?-->?新uboot(少做了某個會提升速度的操作)?-->?kernel(速度慢)

B:?spl(速度快)?-->?舊uboot(沒做特殊操作)?-->?kernel(速度快)
???spl(速度快)?-->?新uboot(多做了某個會限制速度的操作)?-->?kernel(速度慢)
為了驗證,我決定讓 spl直接啟動內(nèi)核,看看內(nèi)核到底是快是慢。
支持過程碰到了一些小問題
1. spl沒有能力加載這么大的 kernel
解決:此時不需要 kernel能完全啟動,只需要能加載啟動一段,足以體現(xiàn)出啟動速度是否正常即可,于是裁剪出一個非常小 kernel來輔助實驗。
2. kernel需要 dtb
解決:內(nèi)核有一個 CONFIG_BUILD_ARM_APPENDED_DTB_IMAGE選項。選上重新編譯。編譯后再用 ddkerneldtb拼接到一起,作為新的 kernel。這樣, spl就只需要加載一個文件并跳轉(zhuǎn)過去即可。
試驗結(jié)果, spl啟動的 kernel和使用新 uboot啟動的 kernel速度一致,均比舊 uboot啟動的 kernel慢。
說明,舊 uboot中做了某個關(guān)鍵操作,而新 uboot沒做。

找出關(guān)鍵操作

那接下來的任務(wù)就是,找出舊 uboot中的這個關(guān)鍵操作了。
怎么找呢?有了上一步的成果,我們可以使用以下方法來排查
  1. spl加載kernel和舊uboot

  2. spl跳轉(zhuǎn)到舊uboot,此時kernel其實已經(jīng)在dram中準(zhǔn)備好了,隨時可以啟動

  3. 在舊uboot的啟動流程各個階段,嘗試直接跳轉(zhuǎn)到kernel,觀察啟動速度

  4. 如果在舊ubootA點跳轉(zhuǎn)kernel啟動慢,B點跳轉(zhuǎn)啟動快,則說明關(guān)鍵操作位于AB點之間。

方法有了,很快就鎖定到 start.S,進一步在 start.S中揪出了這段代碼

    
#if?defined(CONFIG_ARM_A7)
@ set?SMP?bit
????mrc?????p15,? 0,?r0,?c1,?c0,? 1
????orr????????r0,?r0,?#( 1<< 6)
????mcr????????p15,? 0,?r0,?c1,?c0,? 1
#endif
ubootstart.S中沒有這段代碼,嘗試在新 ubootstart.S中添加此操作,速度立馬恢復(fù)正常了。
再全局搜索下,原來這個新版本 uboot中,套路是在 board_init中進行此項設(shè)置的,而這個平臺從舊版本移植過來,就沒有設(shè)置 SMP bit, 補上即可。

SMP bit是什么

SMP 是指對稱多處理器,看起來這個 bit 會影響多核的 cache一致性,此處沒有再深入研究。
但可以知道,對于單處理器的情況,也需要設(shè)置這個 bit才能正常使用 cache。
貼下 arm的圖和描述:

    
[6]?SMP?

Signals? if?the?Cortex-A9?processor?is?taking?part? in?coherency?or?not.

In?uniprocessor?configurations,? if?this?bit?is? set,? then?Inner?Cacheable?Shared?is?treated?as?Cacheable.?The?reset?value?is?zero.
搜下 kernel的代碼,發(fā)現(xiàn)也是有地方調(diào)用了的。不過這個芯片是單核的,根本就沒配置 CONFIG_SMP

    
#ifdef?CONFIG_SMP
?ALT_SMP(mrc?p15,? 0,?r0,?c1,?c0,? 1)
?ALT_UP(mov?r0,?#( 1?<6))??@?fake?it? for?UP
?tst?r0,?#( 1?<6)???@?SMP/nAMP?mode?enabled?
?orreq?r0,?r0,?#( 1?<6)??@?Enable?SMP/nAMP?mode
?orreq?r0,?r0,?r10???@?Enable?CPU-specific?SMP?bits
?mcreq?p15,? 0,?r0,?c1,?c0,? 1
#endif

總結(jié)

整理出來一方面是記錄這兩個 bug,另一方面也是想記錄下當(dāng)時的一些操作。
畢竟同樣的 bug可能以后都不會碰到了,但解 bug的方法和思路卻是可以積累復(fù)用的。

-END-


本文授權(quán)轉(zhuǎn)載自qb雜貨鋪,作者:瞎折騰的zqb




推薦閱讀



【01】C語言內(nèi)存泄露很嚴(yán)重,如何應(yīng)對?
【02】編譯C語言程序,使用 gcc 指令,而C++程序則推薦使用 g++指令!
【03】C語言:優(yōu)雅的字符串函數(shù)庫
【04】在C 語言中,請一定記得初始化局部變量!
【05】嵌入式編程是否應(yīng)該用C++替代C語言


免責(zé)聲明:整理文章為傳播相關(guān)技術(shù),版權(quán)歸原作者所有,如有侵權(quán),請聯(lián)系刪除

免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺僅提供信息存儲服務(wù)。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

嵌入式ARM

掃描二維碼,關(guān)注更多精彩內(nèi)容

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

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

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

加利福尼亞州圣克拉拉縣2024年8月30日 /美通社/ -- 數(shù)字化轉(zhuǎn)型技術(shù)解決方案公司Trianz今天宣布,該公司與Amazon Web Services (AWS)簽訂了...

關(guān)鍵字: AWS AN BSP 數(shù)字化

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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