日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

【STM32F303開發(fā)】 關(guān)于連接寄存器LR的值

 刀首木 2019-02-10
昨天有位同學(xué)看了我之前的這個(gè)帖子:【STM32F303開發(fā)】+如何找到導(dǎo)致程序出現(xiàn)HardFault的代碼   后在社區(qū)群里說他也遇到了這個(gè)問題,但是他不太清楚那個(gè)帖子最后的那個(gè)圖片的中的有2個(gè)LR的值哪個(gè)才是有用的,該使用哪個(gè)LR的值去找跑飛的代碼。我告訴他是debug viewer中輸出的那個(gè),他好像還是不太明白,下面我們就簡(jiǎn)單的看下LR的變化過程。他說的那個(gè)圖片如下,其中包含了2個(gè)LR,左邊一個(gè)寄存器R14的值,右邊debug viewer輸出一個(gè)。
lr.jpg
我們通常說的LR寄存器就是寄存器R14,它常用于在調(diào)用子程序分支時(shí)存儲(chǔ)返回地址,調(diào)用完成后用于返回到調(diào)用之前的地方繼續(xù)執(zhí)行下面的代碼,
《Cortex-M3 權(quán)威指南》對(duì)LR的描述如下,其中提到了LR的地址等于當(dāng)前子程序分支的下一條指令的地址。
lr.jpg
我們知道當(dāng)程序發(fā)生異常或者中斷時(shí)會(huì)自動(dòng)保存現(xiàn)場(chǎng)將xPSR,PC,LR,以及R0-R3由硬件自動(dòng)壓入堆棧以及一些其他的處理,然后程序進(jìn)入異常或者中斷函數(shù),此時(shí)LR的值將會(huì)被自動(dòng)被更新為特殊的EXC_RETURN.《Cortex-M3 權(quán)威指南》里的詳細(xì)的介紹如下:
lr.jpg

下面我們根據(jù)上面的敘述結(jié)合實(shí)際的代碼看下LR的值的變化過程:
1)我們?cè)诋惓:瘮?shù)void HardFault_Handler(void)里面設(shè)置一個(gè)斷點(diǎn)后debug下全速運(yùn)行,這個(gè)函數(shù)是重載的系統(tǒng)的函數(shù),當(dāng)出現(xiàn)HardFault時(shí)會(huì)自動(dòng)進(jìn)入這個(gè)函數(shù),可以看到此時(shí)的LR=0XFFFFFFF9,且此時(shí)處于Handler模式,和上面的描述相符。在這個(gè)函數(shù)里面首先判斷是使用的MSP還是SPS,然后將這個(gè)SP的值保存到r0寄存器,然后調(diào)用函數(shù)void Hard_Fault_Handler(uint32_t stack[]),此時(shí)的r0,作為函數(shù)Hard_Fault_Handler的參數(shù)。
lr.jpg
下面我們進(jìn)入到void Hard_Fault_Handler(uint32_t stack[]),具體如下,主要是打印一些信息出來,我們?cè)谙旅娴暮瘮?shù)里設(shè)置一個(gè)斷點(diǎn),然后進(jìn)入到下面的函數(shù)中去
  1. void Hard_Fault_Handler(uint32_t stack[])

  2. {

  3. static char msg[80];

  4. printf('In Hard Fault Handler\n');

  5. sprintf(msg, 'SCB->HFSR = 0x%08x\n', SCB->HFSR);

  6. printf(msg);

  7. if ((SCB->HFSR & (1 << 30)) != 0)

  8. {

  9. printf('Forced Hard Fault\n');

  10. sprintf(msg, 'SCB->CFSR = 0x%08x\n', SCB->CFSR );

  11. printf(msg);

  12. if((SCB->CFSR & 0xFFFF0000) != 0) {

  13. printUsageErrorMsg(SCB->CFSR);

  14. }

  15. if((SCB->CFSR & 0xFF00) != 0) {

  16. printBusFaultErrorMsg(SCB->CFSR);

  17. }

  18. if((SCB->CFSR & 0xFF) != 0) {

  19. printMemoryManagementErrorMsg(SCB->CFSR);

  20. }      

  21. }  

  22. stackDump(stack);

  23. __ASM volatile('BKPT #01');

  24. while(1);

  25. }

在斷點(diǎn)暫停后我們發(fā)現(xiàn)LR的值還沒有發(fā)生變化,還是剛進(jìn)入中斷函數(shù)的0xFFFFFFF9,
lr.jpg
程序在進(jìn)入函數(shù)時(shí)把r0的值傳給了r4,用于保存參數(shù)的值,因?yàn)橄旅嬉玫絩0.
lr.jpg

繼續(xù)看下面的匯編。將要輸出的字符的地址傳到r0保存,我們可以在內(nèi)存中看到地址0x08000818中保存的就是要輸出的字符串'In Hard Fault Handler\n',同時(shí)也可以在我們上次得到的反匯編文件中看到這個(gè)FLASH地址保存的輸出字符。
lr.jpg
反匯編中得到保存的輸出字符的位置,具體參考:【STM32F303開發(fā)】+使用fromelf反匯編keil生成的AXF文件
lr.jpg
保存好參數(shù)r0后程序會(huì)跳轉(zhuǎn)到輸出函數(shù)的地址0x08002080繼續(xù)執(zhí)行,注意輸出字符串函數(shù)下面的一條語句的地址為0x080006c6,這個(gè)地址將會(huì)在程序跳轉(zhuǎn)到輸出函數(shù)時(shí)被保存在LR中,此時(shí)的LR的值將會(huì)發(fā)生變化。在0x08002080設(shè)置個(gè)斷點(diǎn),然后全速運(yùn)行程序,程序會(huì)暫停在輸出函數(shù)。
從下圖中可以看到LR的值從進(jìn)入中斷函數(shù)時(shí)的0xFFFFFFF9變成了0x080006c7(指令最低bit0必須為1),這個(gè)值正好是我們跳轉(zhuǎn)前的下一句代碼的地址0x080006c6.
lr.jpg

綜上,進(jìn)入中斷函數(shù)時(shí)的LR為特殊的EXC_RETURN,但是如果在中斷函數(shù)中有發(fā)生子程序分支調(diào)用時(shí),LR的值就會(huì)被壓棧,然后發(fā)生變化用于存儲(chǔ)子程序的返回地址。而我們用于保存跑飛代碼的LR的值一直在保存著并沒有發(fā)生變化,最后在debug viewer輸出的正是我們要找的LR的值。

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多