一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

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

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

FreeRTOS中如何定位HardFault?

麥克泰技術 ? 來源:麥克泰技術 ? 作者:麥克泰技術 ? 2022-11-29 14:30 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

今天繼續(xù)聊聊開發(fā)中常見的 HardFault,這個問題應該從學習 STM32 開發(fā)以來就一直伴隨著我們,很多人遇到這種問題也是不知道該如何定位。

如果只是獨立開發(fā),遇到這種問題,一般都是看代碼、修改代碼等等這些常規(guī)手段,因為自己寫的代碼最熟悉,改動一般也不會太大,容易縮小范圍,也更容易定位。

但現(xiàn)在的產品越來越復雜,目前的開發(fā)模式都是合作開發(fā),每個人負責各自的模塊,這樣的項目代碼量大、復雜度高,也就更難定位問題。

而有的時候,剛入職一家公司,什么代碼都不熟悉,又出現(xiàn)了 HardFault,更是讓人崩潰,分分鐘有跑路的沖動(你和代碼,有一個能跑就行)。

此時,有一個能解決這種疑難雜癥的大牛是能大大節(jié)省時間的,而我在公司也解決不少類似的問題,所以經驗也算豐富,充當?shù)囊彩沁@一類角色。

而魚鷹定位 Hardfault 的方法一般是靠 KEIL在線調試+C語言+權威指南中的知識搞定。

目前魚鷹的解 BUG 差不多是這樣的:

1、必現(xiàn),代碼熟悉的情況下,幾個小時內搞定。

2、偶現(xiàn),根據出現(xiàn)情況決定解決問題的時間,一般出現(xiàn)個四五次,基本就能定位。

3、難現(xiàn)。這種一般要掛一個記錄儀實時記錄運行情況。

經歷了這么多,已經很少有能讓魚鷹需要花費幾天時間才能解決的 Hardfault 問題了(猶記得剛來深圳時,因為別人寫的一個 BUG 導致的 Hardfault,不得已加了幾天通宵,要不是偶然機會還不一定能搞定)。

這里打個小廣告,如果難解決,可以有償請魚鷹解決 Hardfault 問題哦。

不過最近工作上因為用了 C++,這個基礎不是很熟悉,解決 Hardfault 的速度又下降了。而工程編譯優(yōu)化等級 -O2 也加大了不少調試難度,因此掌握下面的方法是很重要的:

總結 MDK 幾種編譯優(yōu)化設置的方法

關于 Hardfault,魚鷹以前也是分享了不少筆記的,不知道有多少人認真看過。

HardFault 之 INVSTAE 錯誤定位(一)

見鬼,過年回來后板子就 hardfault 了?

今天,魚鷹繼續(xù)分享關于在 FreeRTOS 定位 Hardfault 方法。

這里需要一個大佬寫的組件 :CmBacktrace(事實上,如果能在線調試,魚鷹是不需要借助這個組件的,但是難復現(xiàn)的情況下用這個組件還是比較香的)。

gitee 倉庫https://gitee.com/Armink/CmBacktrace

這個組件估計很多道友都聽說過,也用過,但魚鷹想說的是,有些道友在用的組件可能比較老,沒有下面這種追蹤功能,建議大家更新一下。

61daf8a8-6fa0-11ed-8abf-dac502259ad0.png

上面可以看到出錯時,函數(shù)的調用棧(有時可能是錯誤的,需要實際分析,僅做參考)

_call_main ->  main -> fult_test_by_div0

相當實用。

同時,本篇筆記不僅適用于在 FreeRTOS 定位 Hardfault,實際上uCOS、rt-thread 等其它 RTOS 照樣可以修改后使用(裸機更不用說了)。

倉庫例子支持的平臺:裸機、rt-thread、ucoss-ii、freertos。

這里重點在如何移植這個組件到freertos 中(實際上,倉庫的說明文檔也非常詳細,可以參考)。由于freertos 也是不斷更新中,所以這個組件的例子不能完全適用于新版本,而魚鷹剛好移植好了,在此記錄一下,方便大家移植。

1、將倉庫中的 cm_backtrace(源碼文件)整個文件夾拷貝到自己的工程文件夾下。

61fddfee-6fa0-11ed-8abf-dac502259ad0.png

2、在自己的工程中添加這些文件(我們可以打開 demos -> os -> freertos 工程查看)

62210834-6fa0-11ed-8abf-dac502259ad0.png

只有兩個文件,相當簡單。

一個是核心源碼,另外一個則是匯編代碼,代碼執(zhí)行入口。

注意,根據 IDE 不同,選擇的匯編文件也不同:

623a3d72-6fa0-11ed-8abf-dac502259ad0.png

其實就是將 startup_stm32f10x_hd.s 中的hardfault 默認處理函數(shù)重定位到 cmb_fault.S 中了。

62595ff4-6fa0-11ed-8abf-dac502259ad0.png

注意這里有一個weak,這樣鏈接的時候就不會鏈接這個,而是cmb_fault.S這個:

62736502-6fa0-11ed-8abf-dac502259ad0.png

為了更方便的定位問題,我們后面還需要修改一下這個代碼才行。

注意,如果你的啟動文件內的 hardfault 代碼被修改了,而你不懂匯編,建議恢復成上面那種,不然可能運行不正常。

3、主函數(shù)中初始化代碼。

62941478-6fa0-11ed-8abf-dac502259ad0.png

這里的字符串需要和這個一樣(根據自己的工程名修改):

62a71672-6fa0-11ed-8abf-dac502259ad0.png

所以建議用英文建工程。這個在輸出錯誤信息的時候用的上,否則每次查看調用棧都需要修改一下,比較麻煩。

如果開啟了內部看門狗,建議關閉一下:

//HAL 庫
__HAL_DBGMCU_FREEZE_IWDG1();
//標準庫
DBGMCU_Config(DBGMCU_IWDG_STOP, ENABLE);

在斷言失敗的位置添加該函數(shù) cm_backtrace_assert:

62bb7928-6fa0-11ed-8abf-dac502259ad0.png

這樣斷言失敗了也能看到調用棧了。

4、FreeROTS內核文件修改(內核版本 V10.2.1)

為了分析出錯的代碼,必須知道每個任務的棧信息,而 FreeRTOS 可能沒有這些信息,因此,我們需要添加進去。

task.c

62db59be-6fa0-11ed-8abf-dac502259ad0.png

FreeRTOS.h

6303c084-6fa0-11ed-8abf-dac502259ad0.png

注意,老版本freertos 是只要修改一處的,但新版本需要修改兩處,否則會斷言失敗,運行不下去。

建議把注釋也一起添加進去。

UBaseType_t     uxSizeOfStack;      /*< Support For CmBacktrace >*/

相關函數(shù)修改 task.c prvInitialiseNewTask():

63324f08-6fa0-11ed-8abf-dac502259ad0.png

task.c 文件最后添加如下代碼用于獲取棧地址、大小、名字:

63585766-6fa0-11ed-8abf-dac502259ad0.png

為方便復制,在此貼代碼

/*-----------------------------------------------------------*/
/*< Support For CmBacktrace >*/
uint32_t * vTaskStackAddr()
{
    return pxCurrentTCB->pxStack;
}


uint32_t vTaskStackSize()
{
    #if ( portSTACK_GROWTH > 0 )
    
    return (pxNewTCB->pxEndOfStack - pxNewTCB->pxStack + 1);
    
    #else /* ( portSTACK_GROWTH > 0 )*/
    
    return pxCurrentTCB->uxSizeOfStack;
    
    #endif /* ( portSTACK_GROWTH > 0 )*/
}


char * vTaskName()
{
    return pxCurrentTCB->pcTaskName;
}
/*-----------------------------------------------------------*/

5、根據所屬 RTOS 平臺和芯片內核修改組件配置信息

cmb_cfg.h

6378da40-6fa0-11ed-8abf-dac502259ad0.png

1)需要定義打印輸出函數(shù),一般用 printf 打印,也可以用你自定義的一些打印函數(shù),功能和 printf 類似即可。

#define cmb_println(...)               printf(__VA_ARGS__);printf("
")

2)使能 RTOS 支持

#define CMB_USING_OS_PLATFORM

3)具體 RTOS 選擇FreeRTOS

#define CMB_OS_PLATFORM_TYPE           CMB_OS_PLATFORM_FREERTOS

4)芯片內核根據實際選擇,目前支持 M0、M3、M4、M7。

#define CMB_CPU_PLATFORM_TYPE          CMB_CPU_ARM_CORTEX_M3

5)打印虛擬棧,可以將出錯時的原始棧信息打印出來,可能對分析有些幫助

#define CMB_USING_DUMP_STACK_INFO

6)語言支持:英語。實際也支持中文,但建議使用英語(不配置,默認就是英語)

#define CMB_PRINT_LANGUAGE             CMB_PRINT_LANGUAGE_ENGLISH

7)如果是 C++ 編譯的,有可能出錯,可以在開頭定義這個:

#define__CLANG_ARM

7、根據需要修改組件,方便使用(這些看看能不能有機會合并到大佬的分支里面)

1)因為功能涉及范圍小,因此可以將相關頭文件包含形式改成這種,這樣就不需要改頭文件路徑了,移植更方便:

#include 
-->>
#include"./cm_backtrace.h"


#include 
-->>
#include "./cmb_cfg.h"


#include "cmb_def.h"
-->>
#include "./cmb_def.h"

main 中也不需要包含頭文件,而是在需要位置直接聲明這個函數(shù)即可,因為外部只需要調用這個函數(shù)

#include 
-->
void cm_backtrace_init(const char *firmware_name, const char *hardware_ver, const char *software_ver);

這樣一來,就不需要添加頭文件的路徑了。

或者使用相對路徑的方式添加頭文件:

#include "../../driver/cm_backtrace/cm_backtrace.h"

另外,我們可以讓程序進入 Hardfault 前,讓代碼自動停止,這樣我們能更好的利用在線調試代碼,《傳說中的軟件斷點到底是什么?。

HardFault_Handler    PROC
    LDR     r0, =0xE000EDF0; DEMCR
    LDR     r0,[r0,#0x00]
    AND     r0,r0,#0x00000001
    CBZ     r0,not_in_debug
    BKPT    0
not_in_debug
    MOV     r0, lr                  ; get lr
    MOV     r1, sp                  ; get stack pointer (current is MSP)
    BL      cm_backtrace_fault

因為剛進入 Hardfault 時的信息最全,又不想每次打斷點,上面的代碼很好的實現(xiàn)了功能,同時也不會影響程序的正常運行(會自動判斷是否處于調試模式)。

8、實驗。

上面都搞定了,就可以驗證一下效果了。這里我們我們可以模擬仿真看看情況。(修改工程配置,這些內容魚鷹以前分享過,不多說)

639ec7f0-6fa0-11ed-8abf-dac502259ad0.png

運行倉庫例子后,應該能打印下面的信息,告訴我們出現(xiàn)了 div 0 錯誤

63cb7908-6fa0-11ed-8abf-dac502259ad0.png

而你移植好的工程也應該打印類似的信息(加入測試代碼 :fault_test_by_div0();)如果打印不出來,有兩種可能:

1、打印函數(shù)沒初始化好就進入了Hardfault

2、打印函數(shù)有問題。

63e46c9c-6fa0-11ed-8abf-dac502259ad0.png

之后我們復制最后一行,然后運行倉庫 tools 里面的 add2line 工具看看調用棧信息:

63fc89ee-6fa0-11ed-8abf-dac502259ad0.png

在 git bash 中可能會執(zhí)行失敗,可以加入程序路徑,當然也可以將該工具路徑加入到Windows 環(huán)境變量中。有可能提示找不到 axf 文件,把這個文件拷貝到工具下即可。

正確的做法是,將該工具放到 C 盤目錄下,同時添加環(huán)境變量,之后就可以在 axf 目錄下打開 gitbash 或者 cmd 窗口執(zhí)行命令即可。

這里只作為演示,就不多介紹這些了。

最后再簡單介紹一下這個組件的實現(xiàn)原理:

如果出現(xiàn)hardfault, 首先進入匯編文件的 HardFault_Handler處理,這里會得到當前的棧指針和 LR,并且根據 LR 確定出錯的棧是哪個《STM32 兩個棧,你用哪一個?》(這里是 PSP 棧)

根據錯誤寄存器信息,確定哪種錯誤(這里為除 0 錯誤。

然后對棧信息 和 LR 、PC 進行 FLASH 上的匯編代碼分析,找出可能的跳轉指令,這里找到的兩個跳轉地址為 0x08001f96 0x08000368,進而得到調用棧。

因此,要能準確的得到調用棧,有兩點重要前提條件(建議優(yōu)化等級 -O0):

1、棧未被破壞

2、芯片運行代碼和 axf 文件保持一致。

即使如此,你也不能保證找出的調用棧就是正確的,比如你使用 fault_test_by_unalign() 測試,得到的結果如下:

641fe20e-6fa0-11ed-8abf-dac502259ad0.png

中間多了一個 fputc。

因此,這些打印信息只能作為參考使用。

但在線調試不同,它更專業(yè),不容易出現(xiàn)錯誤調用關系。

6440fd2c-6fa0-11ed-8abf-dac502259ad0.png

魚鷹想分享的內容到此就結束了,下期再見!

審核編輯 :李倩


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

    關注

    180

    文章

    7632

    瀏覽量

    141739
  • FreeRTOS
    +關注

    關注

    12

    文章

    493

    瀏覽量

    64352

原文標題:FreeRTOS 中如何定位 HardFault?

文章出處:【微信號:麥克泰技術,微信公眾號:麥克泰技術】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    詳解FreeRTOS與SAFERTOS的區(qū)別

    開源免費的FreeRTOS由Richard Barry在WHIS工作時創(chuàng)建,WHIS基于FreeRTOS的功能模型,通過完整的HAZOP分析,確定了功能模型和API的所有的弱點,減輕所有薄弱環(huán)節(jié),并采用IEC 61508 SI
    的頭像 發(fā)表于 06-04 16:58 ?329次閱讀
    詳解<b class='flag-5'>FreeRTOS</b>與SAFERTOS的區(qū)別

    s32k324調試時出現(xiàn)MemManage和HardFault怎么解決?

    我目前正在使用 s32k324 板。 我正在運行一個簡單的示例代碼,但在調試時收到以下兩個錯誤 MemManage:處理器嘗試從不允許執(zhí)行的位置獲取指令。 HardFault:故障已升級為硬故障。 您能告訴我解決方案嗎?
    發(fā)表于 04-04 08:16

    STM32U5退出stop2模式后進入HardFault_Handler如何解決?

    HardFault_Handler,但是連接stlink開啟調試下,程序能連續(xù)進入和退出stop2模式,有無大佬了解該問題或者該如何定位問題?
    發(fā)表于 03-13 06:12

    stm32F407平臺上使用freertos,使用pvPortMalloc申請內存,發(fā)現(xiàn)內存的數(shù)據總被修改,怎么解決?

    如題,我現(xiàn)在在stm32F407平臺上打開FREERTOS,然后使用pvPortMalloc動態(tài)申請內存的時候,發(fā)現(xiàn)這塊內存的數(shù)據總是變化,后面改為malloc申請,內存的數(shù)據就符合預期了,我已經按照網上的流程配置了
    發(fā)表于 03-07 09:03

    STM32H7 0x00000000地址的內容引發(fā)hardfault怎么解決?

    ;Init.Request)時引發(fā)hardfault。具體原因是因為變量huart(對應類型UART_HandleTypeDef)未對hdmarx進行初始化,該指針變量指向0x00000000,但
    發(fā)表于 03-07 08:15

    STM32H743對關鍵中斷函數(shù),使用ITCM搬至RAM運行,仿真進入HardFault_Handler報錯怎么解決?

    ,CubeIDE編譯能正常通過,且map文件,對已搬至ITCM RAM區(qū)域運行的中斷函數(shù)的地址是OK的。只要上電一仿真運行就會進入HardFault_Handler函數(shù),MCU主頻是480MHz,不知是否主頻過高所致,請各位大神指點下。
    發(fā)表于 03-07 08:04

    定位信標在人員定位系統(tǒng)的作用

    這個系統(tǒng),定位信標則是不可或缺的一環(huán)。那么,定位信標在人員定位系統(tǒng)到底起著什么樣的作用呢?本文將為您揭開這一謎底。 首先,我們需要了解什
    的頭像 發(fā)表于 10-24 10:16 ?1103次閱讀
    <b class='flag-5'>定位</b>信標在人員<b class='flag-5'>定位</b>系統(tǒng)<b class='flag-5'>中</b>的作用

    freertos最多支持多少個任務

    FreeRTOS是一個輕量級的實時操作系統(tǒng)(RTOS),其設計初衷就是為了提供簡單、可靠且高效的實時任務管理。關于FreeRTOS最多支持多少個任務的問題,實際上并沒有一個固定的上限,這主要取決于
    的頭像 發(fā)表于 09-02 14:21 ?2267次閱讀

    freertos和rtos區(qū)別是什么

    FreeRTOS 和 RTOS(實時操作系統(tǒng))是兩個不同的概念,但它們之間有緊密的聯(lián)系。FreeRTOS 是一個特定的開源實時操作系統(tǒng),而 RTOS 是實時操作系統(tǒng)的一般概念。 概念定義 RTOS
    的頭像 發(fā)表于 09-02 14:18 ?3018次閱讀

    freertos中斷優(yōu)先級在哪設置

    FreeRTOS是一個流行的實時操作系統(tǒng),它廣泛應用于嵌入式系統(tǒng)開發(fā)。在FreeRTOS,中斷優(yōu)先級是一個重要的概念,因為它決定了中斷處理的順序和響應時間。 1. 理解中斷優(yōu)先級 在討論如何設置
    的頭像 發(fā)表于 09-02 14:17 ?1582次閱讀

    freertos和裸機有什么區(qū)別

    FreeRTOS 和裸機編程是兩種不同的嵌入式系統(tǒng)開發(fā)方法,它們在設計理念、資源使用、功能實現(xiàn)等方面有著顯著的差異。 1. 基本概念 1.1 FreeRTOS FreeRTOS 是一個小型的、可裁剪
    的頭像 發(fā)表于 09-02 14:13 ?3007次閱讀

    freertos和rtthread哪一個更好

    在嵌入式系統(tǒng)開發(fā),選擇合適的實時操作系統(tǒng)(RTOS)對于項目的成功至關重要。FreeRTOS和RT-Thread是兩個非常流行的開源RTOS,它們各自具有獨特的特點和優(yōu)勢。 1. 簡介
    的頭像 發(fā)表于 09-02 14:06 ?7132次閱讀

    STM32U5退出stop2模式后進入HardFault_Hand的原因?

    HardFault_Handler,但是連接stlink開啟調試下,程序能連續(xù)進入和退出stop2模式,有無大佬了解該問題或者該如何定位問題?
    發(fā)表于 07-24 06:25

    STM32G0 FLASH快速寫入發(fā)生HardFault的原因?

    3.HAL_FLASH_Program(FLASH_TYPEPROGRAM_FAST, address, FlashWrite[0]); 第3步,使用FASH模式進行寫入,返回Hardfault. 其中地址定義
    發(fā)表于 07-23 07:44

    服務提供商數(shù)據在精確定位的應用

    我們在網絡連接和數(shù)據傳輸時通過利用ISP提供的數(shù)據,可以實現(xiàn)對用戶和設備的精確定位。接下來我將就ISP數(shù)據在精確定位的應用進行闡述。 ISP數(shù)據的概述 互聯(lián)網服務提供商(ISP)在提供網絡連接服務
    的頭像 發(fā)表于 07-18 11:18 ?634次閱讀