博客專欄

        EEPW首頁 > 博客 > 一個半小時,遠程解決一個 APP跳轉 BUG

        一個半小時,遠程解決一個 APP跳轉 BUG

        發布人:魚鷹談單片機 時間:2022-03-19 來源:工程師 發布文章

        昨天有一位讀者剛關注魚鷹,并且很快加了魚鷹微信,描述了以下問題:

        圖片

        圖片

        當時也沒有細看問題,只是大概看了一下,然后簡單的提供了一個思路給對方,畢竟魚鷹也比較忙,不可能花太多時間在別人的問題上。


        而且也是看對方的問題描述比較清楚,比較有誠意,所以才會提供一個思路,否則可能懶得回復了。所以大家問問題的時候一定要直接詳細描述,否則沒人不愿意回答。畢竟很多人問完并回復之后,可能一句謝謝都沒有就沒有下文了,這種事情見多了。好像別人幫助你是理所應當的。


        只是沒想到,對方會提出給報酬,所以看他挺有誠意的,就開玩笑的問問多少錢。然后開始報價,并且對方也同意我的報價,并愿意多給一倍。

        圖片


        既然他那么有誠意,晚上也沒啥事情,所以還是按自己的報價(有原則的魚鷹)確定下來 20 點左右開始遠程解決問題。


        8 點半左右開始正式遠程解決,原本以為半小時能搞定,實際上花了一個半小時。這里稍微總結一下。


        首先是讓對方復現問題,然后和正常的情況一并復現,這里花了幾分鐘,確定了好的代碼與不好的代碼不同現象。


        這里可能有點奇怪,為啥有好的代碼(boot 能正常跳轉到 APP),還要找魚鷹解決,魚鷹開始也有點納悶,后來才知道,原來好的代碼只要稍微改點代碼,就不能正常跳轉了,這肯定是不行的,因此找上了魚鷹(其實描述也說了,只是魚鷹沒太在意)。


        根據目前了解的情況來看,怎么說也是 APP 的問題,畢竟 Boot 有成功跳轉的情況。


        開始的時候,魚鷹的方向確實在 APP 上,還仔細的看了看 APP 的編譯警告問題(很多人不注意警告,總是在工程里面遺留很多警告,雖然很多情況下,這些警告不會有問題,但是萬一呢。所以建議大家盡量解決工程的警告, 0 error 0 warning還是相當舒服的),這里也花了幾分鐘確認,發現確實無關大雅。

        圖片


        之后又是嘗試了幾次好代碼與壞代碼的差別,發現在跳轉代碼部分,沒有任何區別,跳轉地址: 0x00010000 棧頂地址: 0xE000ED08(通過匯編代碼分析)。


        但這個反常的現象卻引起了魚鷹的警惕, 因為據魚鷹了解到的 Cortex-M3  內核知識《STM32固件升級之基礎知識(一)》,兩個不同的 APP 這兩個地址大概率是不同的。


        雖然它是 M33 的內核,但也不應該差別那么大。


        而且內存地址也不應該是 0xE000 開頭的,所以又是查 map 文件,又是看鏈接文件,又是上網(魚鷹對 M33 的跳轉不熟悉,所以需要了解情況,否則解決時間可以縮短不少),又是和提問者溝通,最終得到以下信息:


        1、兩個代碼確實不同(這個可以確定編譯沒有問題),通過 map 可以分析出來,但為什么一份可以,一份不可以?boot的跳轉地址和棧頂地址還一樣?不符合常理!


        2、調試過程中發現跳轉時不會運行到啟動文件(*.s),這有悖常理!


        3、內存地址實際從 0x20000000 開始;


        4、APP 鏈接文件修改的地方由 NXP 的 FAE 告知,跳轉到 APP 部分的代碼也是 FAE 提供的(一開始就了解了這個情況,所以沒有一開始就懷疑這部分代碼)。


        5、通過查看 flash 0x0001 0000 地址處的內容,發現兩份代碼有不同,確定下載沒有問題。


        結合上面的兩個地址(跳轉地址和棧頂地址(先假設是這樣,因為 M3 內核就是這樣,M33 內核估計差不了多少)),魚鷹開始重點查看這個跳轉代碼(NXP FAE 提供)




















        #define ApplicationAddress    0x10000
        void JumpToUserApplication(unsigned long userSP, unsigned long userStartup){ // set up stack pointer  __asm("msr msp, r0");  __asm("msr psp, r0");
         // Jump to PC (r1)  __asm("mov pc, r1"); }
        void StartUp(void){ // relocate vector table SCB->VTOR = ApplicationAddress;   // Jump to user application JumpToUserApplication(*((unsigned long*)ApplicationAddress), *((unsigned long*)(ApplicationAddress+4)));    }


        乍看,和魚鷹理解的 M3 類似,都是在跳轉時取出 APP 首地址處的 8 個字節作為 棧頂指針 和 PC 指針


        但是從 C 語言的角度,你看不出任何毛病,很正常,但是它最終到 JumpToUserApplication 時卻是 0x0001 0000 和 0xE000ED08,這個和前面的分析完全不符。


        沒辦法,只能拿出魚鷹的殺手锏,匯編


        之后就發現,這個嵌入式匯編在跳轉時,并沒有取出 0x0001 0000 地址的 8個數據,而是直接沿用前面的 SCB->VTOR = ApplicationAddress;  運行后的 R0、 R1作為參數傳遞進去,最終導致跳轉失敗。


        也就是說,問題出在 BOOT 上,而不是 APP 里面,所謂的好代碼只是湊巧趕上了,這也就能解釋為什么跳轉時不會運行到啟動文件了。


        找到問題,但因為對匯編不熟,又是一頓改寫,測試,總算成功跳轉了。也算是完成了任務。

        圖片

        從這次解決 BUG 的經歷中,各位道友可以發現,這里運用了非常多的基礎知識(內存分配、向量表、map文件、鏈接文件、匯編等等),正因為有這些知識的積累,此案才能順利告破。


        解 BUG,就像一個破案的警察,不僅需要從蛛絲馬跡中尋找線索,還需要很多理論基礎支撐,足夠敏感,才能順利解決,否則只能干瞪眼了。


        但個人覺得,自己的行為像一個殺手,你出錢,我辦事,各取所需。


        這次是魚鷹第一次有償且親自遠程解決疑難問題,覺得挺有意義的,故此記錄。


        另外如果其他道友有難解的 BUG,同時又愿意付費解決的話,歡迎咨詢魚鷹,魚鷹視情況收費(可能不低,但可以節省時間,項目緊急的話歡迎找魚鷹),當然也可以雇傭魚鷹作為 MCU 技術顧問,幫助公司解決一些難解問題。


        在此感謝大家對魚鷹的關注與支持!


        *博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。



        關鍵詞: 單片機

        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 新郑市| 北票市| 余干县| 江永县| 彝良县| 蓬安县| 万载县| 二手房| 康定县| 乐亭县| 榆社县| 资中县| 合江县| 石屏县| 东方市| 潢川县| 阜宁县| 丹江口市| 台山市| 肥城市| 郓城县| 勃利县| 永登县| 宝丰县| 彩票| 阿图什市| 荆门市| 藁城市| 巴青县| 唐河县| 措勤县| 阿尔山市| 南丹县| 马公市| 嘉荫县| 乐昌市| 贺州市| 曲靖市| 五原县| 普兰店市| 鸡西市|