<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

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

3天內不再提示

Freertos棧檢測

嵌入式USB開發 ? 來源:嵌入式USB開發 ? 作者:嵌入式USB開發 ? 2023-09-19 14:03 ? 次閱讀

本文轉自公眾號,歡迎關注
https://mp.weixin.qq.com/s/uzaGLFTDBAn8wyR84yaiIw

1. 前言

RTOS的環境開發中,棧的溢出檢測是一個重要的工作。棧溢出檢測我們可以借助硬件的MPU等實現,也可以使用軟件檢測。這里分享Freertos中的實現。這里基于Cortex-M4硬件平臺,一些具體的代碼就未貼出了,順便介紹了一下Cortex-M4棧相關的基礎知識。

2. 棧初始化

2.1任務啟動前棧

復位后匯編代碼

IMPORT  __main


LDR     R0, =SystemInit


BLX     R0


LDR     R0, =__main


BX      R0


ENDP

會進入__main將棧內容寫為0。該部分由編譯器產生代碼實現。

棧的位置是鏈接腳本中指定。

2.2任務棧

xTaskCreate -> prvInitialiseNewTask將任務棧填充為tskSTACK_FILL_BYTE = ( 0xa5U )

然后調用pxPortInitialiseStack初始化任務棧上下文

任務初始化時
高地址
->任務切出時棧指針
低地址
任務運行一段時間后
高地址
已使用部分
->任務切出時棧指針
未使用部分
低地址

對應實際中斷后的棧如下:

3.任務切換

vPortSVCHandler函數模擬中斷返回

__asm void vPortSVCHandler( void )


{


PRESERVE8


/* Get the location of the current TCB. */


ldr r3, =pxCurrentTCB


ldr r1, [r3]


ldr r0, [r1]


/* Pop the core registers. */


ldmia r0!, {r4-r11, r14}


msr psp, r0


isb


mov r0, #0


msr basepri, r0


bx r14


}

其中

ldr r3, =pxCurrentTCB


ldr r1, [r3]


ldr r0, [r1]

是獲取棧指針r0即指向任務棧表中R4位置

ldmia r0!, {r4-r11, r14}是恢復R4-R11和portINITIAL_EXC_RETURN

msr psp, r0,更新棧指針,指向指向任務棧表中R0位置

bx r14模擬中斷返回 恢復R0-R3 R12 PC xPSR(硬件實現)。

由于R14=portINITIAL_EXC_RETURN=0xfffffffd

根據手冊描述

圖片

返回時使用PSP棧,返回后使用PSP棧。與初始化對應。

4.任務return

棧初始化時LR = prvTaskExitError 進入子函數時LR會入棧,退出子函數時LR出棧。

所以如果任務不是while(1)形式而是在最后return則最終會進入

prvTaskExitError執行。一般rtos的任務都是while(1)結構 不return。

5.棧指針

復位后使用MSP,任務根據返回時的LR值portINITIAL_EXC_RETURN使用PSP見“2.任務切換”。

中斷中固定使用MSP。

圖片

6.棧使用

中斷函數和mian使用中斷向量第一個字指向的棧區域。

任務使用任務棧。

在os啟動前默認時使用msp,根據中斷向量的第一個字加載msp

硬件實現,或者bootloader跳轉到應用時配置。

啟動os時prvStartFirstTask,又重新將中斷向量第一個字加載到msp。

今后中斷就使用msp對應的棧,即os啟動前main使用的棧。

因為main一去不復返,所以這里覆蓋使用main時的棧,這樣可以節約內存。

/* Use the NVIC offset register to locate the stack. */


ldr r0, =0xE000ED08


ldr r0, [r0]


ldr r0, [r0]


/* Set the msp back to the start of the stack. */


msr msp, r0

7棧檢測

7.1任務棧檢測

棧初始化時全部初始化為0xA5,運行一段時間后棧頂部分使用變為其他值。

檢查棧底有多少連續的0xA5即可知道棧剩余多少。

圖片

Freertos提供接口函數uxTaskGetSystemState獲取棧信息。

Shell中輸入ps查看(具體代碼未貼出)。

圖片

7.2中斷棧/main函數棧檢測

根據4.和5.的分析,中斷和main函數棧使用中斷向量第一個字對應的棧區域。

由于__main.c會將棧內容清除為0.所以在啟動第一個任務前將棧重新填充為0xa5。

有__main.c之前將棧填充為0xa5又會被清除為0,將填充代碼放在了任務啟動前prvStartFirstTask函數中。這樣main函數到prvStartFirstTask之前的棧使用大小不可監控。

只能監控后續中斷使用的棧大小。如果要檢測main函數棧使用則要將填充代碼放在main函數執行的第一條代碼后,需要嵌入匯編影響代碼閱讀和可移植性,所以不按這種方式。

實際上main函數棧溢出也沒關系 ,但是編程必須要求提供手動初始化變量的代碼,而不是依賴于編譯器的初始化。

比如有一個變量static int i =0;

編譯器提供代碼在__main中會對該變量初始化,如果main函數棧溢出覆蓋了這個變量的值。

那么在任務函數執行時提供 void mode_init(void)函數

手動再次初始化該變量i=0.

就可以避免問題。

建議在模塊任務啟動時對屬于模塊的全局變量再次提供”構造函數”手動初始化。

修改freertos底層移植代碼

__asm void prvStartFirstTask( void )


{


PRESERVE8


/* Use the NVIC offset register to locate the stack. */


ldr r0, =0xE000ED08


ldr r0, [r0]


ldr r0, [r0]


/* Set the msp back to the start of the stack. */


msr msp, r0


//;初始化棧為0xA5A5A5A5  


MOV     R2,#0xA5A5A5A5


LDR     R0, =0x4000


MRS     R1, MSP


 SUBS    R1,R1,#4


LOOP STR R2,[R1,#0x00]


SUBS    R0,R0,#4


 SUBS    R1,R1,#4


CMP     R0,#0x00


BNE     LOOP

增加檢測代碼

其中0x4000需要根據實際設置的棧大小修改。0xE000ED08為中斷向量表地址。

/*****************************************************************************


* fn          uint32_t bsp_sys_getstack(void)


* brief       獲取棧大小.


* note        .


* return      剩余棧字節數


*****************************************************************************


*/


uint32_t bsp_sys_getstack(void)


{


uint32_t size = 0;


uint32_t* p = (uint32_t*)(*(uint32_t*)(*(uint32_t*)0xE000ED08) - 0x4000);


while(*p == (uint32_t)0xA5A5A5A5)


{


size += 4;


p++;


}


return size;


}

Shell中輸入stack命令查看(具體代碼未貼出)

圖片

8. 總結

簡單來說軟件實現棧檢測,就是將棧初始化為固定值。如果棧有使用則初始化值會變化,軟件從棧底開始查找看剩余多少內容沒有被改寫就是剩余多少棧未使用。軟件檢測不是可靠的,因為溢出可能是跳躍的,即棧底一部分實際未用指針直接跳到了更后面的溢出位置,軟件檢測還存在延遲,所以軟件檢測一般可用于評估棧使用大小。使用硬件MPU更可靠,設置只有本任務只能訪問本任務棧對應的空間,一旦訪問其他空間就可以觸發MPU中斷這樣更及時可靠檢測。

審核編輯:湯梓紅

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

    關注

    5006

    文章

    18440

    瀏覽量

    292141
  • MPU
    MPU
    +關注

    關注

    0

    文章

    305

    瀏覽量

    48459
  • 函數
    +關注

    關注

    3

    文章

    4117

    瀏覽量

    61507
  • 代碼
    +關注

    關注

    30

    文章

    4586

    瀏覽量

    67219
  • FreeRTOS
    +關注

    關注

    12

    文章

    474

    瀏覽量

    61475
收藏 人收藏

    評論

    相關推薦

    轉:第11章 FreeRTOS任務大小確定及其溢出檢測

    本章節為大家講解FreeRTOS任務大小的確定方法以及溢出檢測方法。給任務分配多大的空間,一直是初學者比較頭疼的問題,本章就主要為大家
    發表于 08-28 15:21

    第10章 RL-TCPnet網絡協議移植(FreeRTOS

    轉最新教程本章教程為大家講解RL-TCPnet網絡協議FreeRTOS操作系統移植方式,學習了第6章講解的底層驅動接口函數之后,移植就比較容易了,主要是添加庫文件、配置文件和驅動文件即可。另外
    發表于 10-25 11:39

    freertos 堆棧問題

    公司有個項目,使用freertos系統,別人做的項目,我看他配置的系統只有1K,明顯太小,但能夠正常使用。使用系統時,只要任務夠用就行,不用管系統大小嗎?
    發表于 05-27 11:24

    請問在IAR中如何直接查看任務使用多少空間?

    在使用IAR調試freertos任務中,IAR自帶了一個調試插件,啟用這個插件會得到任務名、優先級、起始空間和頂位置,但是如何計算出每個任務具體使用了多少堆??臻g呢?還有就是在freert
    發表于 06-10 09:25

    FreeRTOS任務與系統的關系?

    在使用FreeRTOS時一直存在對設置的疑問,見以下三點疑問:1、Starup_stm32f40_41xxx.s中的“Stack_SizeEQU0x00001000”這里的設置的作用?2、在工程
    發表于 07-15 00:17

    freertos與STM32如何分配堆??臻g

    freertos與STM32分析、堆、全局區、常量區、代碼區、RAM、ROM,及如何分配堆??臻g基于STM32分析、堆、全局區、常量區、代碼區、RAM、ROM FreeRTOS任務
    發表于 08-03 06:36

    ThreadX任務大小的確定方法以及溢出檢測方法

    第10章 ThreadX任務大小確定及其溢出檢測本章節為大家講解ThreadX任務大小的確定方法以及溢出檢測方法。給任務分配多大的
    發表于 08-04 08:59

    講解ThreadX任務大小的確定方法以及溢出檢測方法

    第10章 ThreadX任務大小確定及其溢出檢測本章節為大家講解ThreadX任務大小的確定方法以及溢出檢測方法。給任務分配多大的
    發表于 08-09 06:30

    RL-TCPnet網絡協議FreeRTOS版本移植方式

    第8章 RL-TCPnet網絡協議移植(FreeRTOS)本章教程為大家講解RL-TCPnet網絡協議FreeRTOS版本移植方式。目錄第8章 RL-TCPnet網絡協議
    發表于 08-11 08:25

    FreeRTOS中的任務堆棧溢出檢測機制

    合理的任務堆棧大小,并實際運行程序進行測試,來確保系統運行過程中不會發生堆棧溢出。FreeRTOS中的任務堆棧溢出檢測機制:在FreeRTOS中,也提供了一些API函數用來檢測任務堆棧
    發表于 10-15 13:51

    怎樣將LWIP協議移植到FreeRTOS上呢

    怎樣將LWIP協議移植到FreeRTOS上呢?需要修改的文件有哪些呢?
    發表于 10-27 07:37

    SC0082 AT32在FreeRTOS上運行LwIP協議

    示例目的演示在FreeRTOS上運行LwIP協議,并搭建一個UDP echo server支持型號列表:支持型號AT32F407xxAT32F437xx主要使用外設列表:主要使用外設
    發表于 08-23 21:01

    從0到1學習FreeRTOSFreeRTOS 內核應用開發:(一)移植FreeRTOS到STM32第一部分

    從0到1學習FreeRTOSFreeRTOS 內核應用開發:(一)移植FreeRTOS到STM32第一部分
    發表于 12-04 12:51 ?21次下載
    從0到1學習<b class='flag-5'>FreeRTOS</b>:<b class='flag-5'>FreeRTOS</b> 內核應用開發:(一)移植<b class='flag-5'>FreeRTOS</b>到STM32第一部分

    初入FreeRTOS

    目錄一、FreeRTOS介紹1、初識FreeRTOS,什么是 FreeRTOS2、FreeRTOS的特點二、FreeRTOS移植1、
    發表于 12-06 21:06 ?37次下載
    初入<b class='flag-5'>FreeRTOS</b>

    FreeRTOS系列第8篇---FreeRTOS內存管理

    本文介紹內存管理的基礎知識,詳細源碼分析見《 FreeRTOS高級篇7---FreeRTOS內存管理分析》
    發表于 01-26 17:56 ?17次下載
    <b class='flag-5'>FreeRTOS</b>系列第8篇---<b class='flag-5'>FreeRTOS</b>內存管理
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>