吴忠躺衫网络科技有限公司

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

本跳轉(zhuǎn)程序靠bug運(yùn)行,請不要優(yōu)化

魚鷹談單片機(jī) ? 來源:魚鷹談單片機(jī) ? 2023-07-11 14:59 ? 次閱讀

絕大多數(shù)產(chǎn)品開發(fā),軟件一般都會設(shè)計成 boot + app 的形式,這是方便后續(xù)軟件更新,否則更新會變成一個很麻煩的事情。

網(wǎng)上隨處可見的跳轉(zhuǎn)程序大概如下:

#define APP_START_ADDR          0x08040000 


voidjump2app()
{
typedefvoid(*func_app_start)(void);
   
__disable_irq();

func_app_start app_start=(func_app_start)(*(__IOuint32_t*)(APP_START_ADDR+4));
  
__set_MSP(*(__IOuint32_t*)(APP_START_ADDR));//設(shè)置棧頂?shù)刂?/span>


app_start();
}

大多數(shù)情況下,該程序跳轉(zhuǎn)正常,但當(dāng)你改變了編譯器優(yōu)化級別時,可能直接就 hardfault 了。

此時你會莫名其妙,為什么???

從魚鷹18接觸到 boot 知識以來,都覺得這樣的跳轉(zhuǎn)程序理所當(dāng)然,并且也沒出現(xiàn)過問題,直到最近修改了優(yōu)化級別,發(fā)現(xiàn)程序直接hardfault 了,根本沒跳轉(zhuǎn)到 app 中,才發(fā)現(xiàn)了這里隱藏的 bug。

調(diào)試發(fā)現(xiàn),app_start 這個函數(shù)指針變成了異常值,但魚鷹查看0x08040000 處的內(nèi)存空間值是正常的。那只能是代碼問題了。

因此結(jié)合匯編和在線調(diào)試,終于發(fā)現(xiàn),執(zhí)行__set_MSP 這條語句前app_start 的值是正常的,執(zhí)行后,這個值就異常了。

再結(jié)合 C 語言關(guān)于棧、局部變量的知識,立刻就知道是因?yàn)橹匦略O(shè)置棧頂?shù)刂罚珔R編代碼不變,但是從新棧位置偏移取函數(shù)地址,因此跳轉(zhuǎn)失敗。

如:

15bee072-1f9c-11ee-962d-dac502259ad0.png

新棧的位置,變量的值是未知的,用它進(jìn)行跳轉(zhuǎn),失敗是必然的。

但是為什么大部分情況下程序沒有問題呢?

這是因?yàn)樘D(zhuǎn)程序很簡單,局部變量少,那么這個app_start 局部變量編譯器可能就不會從棧中分配,而直接用一個寄存器存儲數(shù)據(jù),而寄存器是不受棧頂位置影響的,自然程序能跳轉(zhuǎn)了。

但我們不能讓程序運(yùn)行正常與否由編譯器隨機(jī)決定,因此我們要避免這個 bug,讓程序不管在何種優(yōu)化級別函數(shù)多復(fù)雜的情況下,依然可以正常運(yùn)行,因此還是有必要進(jìn)行優(yōu)化的。

最簡單的方法,就是把這個app_start 局部變量變成全局變量這樣變量就不會受到棧頂位置影響,自然可以避免了。

如:

#define APP_START_ADDR          0x08040000 


voidjump2app()
{
typedefvoid(*func_app_start)(void);
   
__disable_irq();

static func_app_start app_start=(func_app_start)(*(__IOuint32_t*)(APP_START_ADDR+4));
  
__set_MSP(*(__IOuint32_t*)(APP_START_ADDR));//設(shè)置棧頂?shù)刂?/span>


app_start();
}

如有更好的優(yōu)化方法,歡迎留言討論。




聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5363

    瀏覽量

    121178
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4346

    瀏覽量

    62977
  • 變量
    +關(guān)注

    關(guān)注

    0

    文章

    613

    瀏覽量

    28466

原文標(biāo)題:本跳轉(zhuǎn)程序靠bug運(yùn)行,請不要優(yōu)化

文章出處:【微信號:emOsprey,微信公眾號:魚鷹談單片機(jī)】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    西門子S7-1200 PLC程序控制指令:跳轉(zhuǎn)與標(biāo)簽指令

    在S7-1200PLC中,程序控制指令主要包含兩部分:一是改變程序執(zhí)行順序的的跳轉(zhuǎn)指令;二是程序運(yùn)行過程中用于控制的指令;本節(jié)主要分享
    發(fā)表于 03-07 10:25 ?8305次閱讀

    與單片機(jī)Bug戰(zhàn)斗的那些經(jīng)歷

    時我們可以知道是在哪一個地方。這點(diǎn)是相當(dāng)?shù)膶?shí)用,對于無法仿真的51單片機(jī),要了解程序內(nèi)部運(yùn)行的狀態(tài)和變量現(xiàn)在的值,就顯得很無語,簡直束手無策。那么就加入串口程序的代碼,利用串口將一些
    發(fā)表于 11-05 17:09

    與單片機(jī)Bug戰(zhàn)斗的那些經(jīng)歷

    可以知道是在哪一個地方。這點(diǎn)是相當(dāng)?shù)膶?shí)用,對于無法仿真的51單片機(jī),要了解程序內(nèi)部運(yùn)行的狀態(tài)和變量現(xiàn)在的值,就顯得很無語,簡直束手無策。那么就加入串口程序的代碼,利用串口將一些重要變
    發(fā)表于 12-20 17:15

    IAP程序跳轉(zhuǎn)到APP只能運(yùn)行大約2秒

    );} 問題:如果設(shè)置了" __MSR_MSP (AppSpInitVal);//設(shè)置SP.,則跳轉(zhuǎn)過去大約2秒就又回到IAP程序了;而不操作這個SP,則可以正常運(yùn)行,實(shí)際上就是在IAP與APP同時
    發(fā)表于 03-14 08:05

    關(guān)于程序跳轉(zhuǎn)的問題如何解決

    你好,我是一個初學(xué)者,有個問題想問一下就是關(guān)于DSP6747的在FLASH的0地址處加載一個AIS格式的bin文件,在這個程序讀到RAM中運(yùn)行的時候,我想讓DSP跳轉(zhuǎn)到另一個程序入口處
    發(fā)表于 05-22 14:49

    為了心愛的本本,不要吸煙

    為了心愛的本本,不要吸煙  問題:鍵盤里有很多煙灰,請問如何拆下,該如何清洗,工具哪有買,最好詳細(xì)點(diǎn),謝謝。我用的是COMPAQ的X1000   回答:
    發(fā)表于 01-25 13:04 ?396次閱讀

    ---GD32F450---bootloader跳轉(zhuǎn)到app無法運(yùn)行

    問題描述:bootloader和app程序都能單獨(dú)正常運(yùn)行,但是在使用bootloader進(jìn)行跳轉(zhuǎn)時,程序跑飛。原因:bootloader在運(yùn)行
    發(fā)表于 12-02 14:36 ?16次下載
    ---GD32F450---bootloader<b class='flag-5'>跳轉(zhuǎn)</b>到app無法<b class='flag-5'>運(yùn)行</b>

    KEIL上跳轉(zhuǎn)程序的起始地址(未完成)

    //有任何想法,務(wù)必評論,共同進(jìn)步一、keil設(shè)置二、程序設(shè)置內(nèi)存上面做跳轉(zhuǎn),定義一個在此地址之后的量(數(shù)組函數(shù)都可以)三、程序起始運(yùn)行
    發(fā)表于 12-03 09:06 ?12次下載
    KEIL上<b class='flag-5'>跳轉(zhuǎn)</b><b class='flag-5'>程序</b>的起始地址(未完成)

    STM32 IAP - Boot跳轉(zhuǎn)到APP

    簡單IAP設(shè)計思路:單片機(jī)上電首先運(yùn)行BootLoader程序; Bootloader如果檢測到需要更新APP,則首先進(jìn)行更新,更新完成后跳轉(zhuǎn)到APP并運(yùn)行; Bootloader如果
    發(fā)表于 12-03 14:21 ?12次下載
    STM32 IAP - Boot<b class='flag-5'>跳轉(zhuǎn)</b>到APP

    【單片機(jī)程序和RAM】程序在RAM中調(diào)試的運(yùn)行方式&程序固化后運(yùn)行方式

    程序固化后運(yùn)行方式: 程序開始運(yùn)行后需要將RW 和ZI段搬移到RAM中去,程序下載進(jìn)Flash中以后,上電后是怎樣將RW ZI斷搬移到RA
    發(fā)表于 12-03 15:21 ?4次下載
    【單片機(jī)<b class='flag-5'>程序</b>和RAM】<b class='flag-5'>程序</b>在RAM中調(diào)試的<b class='flag-5'>運(yùn)行</b>方式&<b class='flag-5'>程序</b>固化后<b class='flag-5'>運(yùn)行</b>方式

    BL(B)和LDR跳轉(zhuǎn)范圍是如何規(guī)定的

    ??LDR和BL在啟動程序中,都是可以負(fù)責(zé)pc跳轉(zhuǎn)的指令。 ??BL是地址無關(guān)指令,即和當(dāng)前的運(yùn)行地址無關(guān)。鏈接器腳本中標(biāo)明了一個運(yùn)行地址,但是arm中的代碼實(shí)際是從地址0開始
    的頭像 發(fā)表于 07-03 10:29 ?2477次閱讀

    PLC跳轉(zhuǎn)/標(biāo)號指令的工作原理及應(yīng)用舉例

    跳轉(zhuǎn)/標(biāo)號執(zhí)行是用來跳過部分程序使其不執(zhí)行必須用在同一程序塊內(nèi)部實(shí)現(xiàn)跳轉(zhuǎn)跳轉(zhuǎn)/標(biāo)號指令有兩條,分別為
    的頭像 發(fā)表于 10-08 09:59 ?6014次閱讀

    SCL用GOTO語句執(zhí)行程序跳轉(zhuǎn)

    用GOTO語句能夠執(zhí)行程序跳轉(zhuǎn)。此引起立即跳轉(zhuǎn)到指定標(biāo)號,為此而到同塊中不同的語句。
    的頭像 發(fā)表于 02-01 09:22 ?2727次閱讀

    AN040 IAP程序跳轉(zhuǎn)說明

    AN040 IAP程序跳轉(zhuǎn)說明
    發(fā)表于 02-23 19:11 ?0次下載
    AN040 IAP<b class='flag-5'>程序</b><b class='flag-5'>跳轉(zhuǎn)</b>說明

    PLC的條件跳轉(zhuǎn)、子程序調(diào)用等

    當(dāng)我們按下X000后,程序跳轉(zhuǎn)指令開始運(yùn)行程序跳轉(zhuǎn)的位置為程序指針?biāo)诘奈恢茫簿褪菢?biāo)號10
    的頭像 發(fā)表于 06-07 14:46 ?1352次閱讀
    PLC的條件<b class='flag-5'>跳轉(zhuǎn)</b>、子<b class='flag-5'>程序</b>調(diào)用等
    百家乐牌九| 3U百家乐官网的玩法技巧和规则| 致胜百家乐的玩法技巧和规则| 百家乐官网怎么才能包赢| 三公百家乐在哪里可以玩| 天博百家乐官网的玩法技巧和规则 | 百家乐官网网上真钱娱乐场开户注册 | 百家乐官网一直下注庄家| 大发888缺少casino组件common| 百家乐官网首页红利| 晴隆县| 娱乐百家乐的玩法技巧和规则 | 曲阳县| 百家乐之对子的技巧| 百家乐官网马渚| 澳门百家乐官网死局| 百家乐vshow| 百家乐官网不锈钢| 百家乐官网怎么玩呀| 大发888官方6222.co| 游戏百家乐的玩法技巧和规则 | 百家乐官网只打闲打法| 同乐城备用| E世博百家乐娱乐城| 百家乐官网游戏开发软件| 武夷山市| 老虎机价格| 百家乐现金网开户平台| 百家乐官网电影网| 属蛇和属猪做生意吗| 电玩百家乐官网游戏机路单| 网络百家乐官网软件真假| 百家乐官网下对子的概率| 澳门百家乐官网皇冠网| 百家乐官网哪家有优惠| 澳门百家乐官网玩法| bodog博狗| 永利高倒闭| 大发888娱乐城备用| 大发888娱乐新澳博| 大发888的比赛怎么报名|