TencentOS_Tiny 任務棧使用率(檢測任務棧最大使用深度)

来源:https://www.cnblogs.com/pimpernelLJX/archive/2022/04/14/16143746.html
-Advertisement-
Play Games

bat文件是dos下的批處理文件。批處理文件是無格式的文本文件,它包含一條或多條命令。它的文件擴展名為 .bat 或 .cmd。 ...


目錄

TencentOS_Tiny 任務棧使用率

在使用rtos時需要給任務分配合適大小的任務棧,任務運行時所占用的任務棧大小由整個任務所使用的臨時變數多少決定,當任務不複雜且調用子函數不多時,可以通過簡單的計算來判斷需要給任務分配多大的任務棧。當任務比較複雜,調用函數比較多時,計算起來比較麻煩。TencentOS Tiny提供了API可以檢測任務最多使用了任務棧多少位元組,在使用最多位元組的基礎上多分配一部分空間,就是一個合適的任務棧大小。

API調用

在CONFIG.h中使能

TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN     1U

在任務中調用

int depth;
tos_task_stack_draught_depth(&task1, &depth);
printf("%d", depth);

源碼分析

任務創建時對任務棧進行了初始化

tos_task_creat()中使用了cpu_task_stk_init()函數對任務棧進行處理


__API__ k_err_t tos_task_create(k_task_t *task,char *name,
                                            k_task_entry_t entry,
                                            void *arg,
                                            k_prio_t prio,
                                            k_stack_t *stk_base,
                                            size_t stk_size,
                                            k_timeslice_t timeslice)
{
    .......
    .......
    /* task_exist是提前聲明的私有函數,用於銷毀任務
     *   __STATIC__ void task_exit(void)
     *  {
     *       tos_task_destroy(K_NULL);
     *  }
     */
    task->sp        = cpu_task_stk_init((void *)entry, arg, (void *)task_exit, stk_base, stk_size);
    task->entry     = entry;
    task->arg       = arg;
    task->prio      = prio;
    task->stk_base  = stk_base;
    task->stk_size  = stk_size;
    strncpy(task->name, name, K_TASK_NAME_LEN_MAX);
    
    ......
    ......

    return K_ERR_NONE;
}

cpu_task_stk_init()函數在使能了TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN後會給任務棧的所有位元組初始化為0xCC,並將寄存器壓棧

__KNL__ k_stack_t *cpu_task_stk_init(void *entry,
                                              void *arg,
                                              void *exit,
                                              k_stack_t *stk_base,
                                              size_t stk_size)
{
    cpu_data_t *sp;
    

    // 棧頂做4位元組對齊

    sp = (cpu_data_t *)&stk_base[stk_size];
    sp = (cpu_data_t *)((cpu_addr_t)sp & 0xFFFFFFF8);

#if TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN > 0u

    // 從棧底到棧頂所有位元組初始化為0xCC
    uint8_t *slot = (uint8_t *)&stk_base[0];
    for (; slot < (uint8_t *)sp; ++slot) {
        *slot = 0xCC;
    }
#endif

    // 按順序將寄存器壓入任務棧
     
    /* auto-saved on exception(pendSV) by hardware */
    *--sp = (cpu_data_t)0x01000000u;    /* xPSR     */
    *--sp = (cpu_data_t)entry;          /* entry    */
    *--sp = (cpu_data_t)exit;           /* R14 (LR) */
    *--sp = (cpu_data_t)0x12121212u;    /* R12      */
    *--sp = (cpu_data_t)0x03030303u;    /* R3       */
    *--sp = (cpu_data_t)0x02020202u;    /* R2       */
    *--sp = (cpu_data_t)0x01010101u;    /* R1       */
    *--sp = (cpu_data_t)arg;            /* R0: arg  */

    /* Remaining registers saved on process stack */
    /* EXC_RETURN = 0xFFFFFFFDL
       Initial state: Thread mode +  non-floating-point state + PSP
       31 - 28 : EXC_RETURN flag, 0xF
       27 -  5 : reserved, 0xFFFFFE
       4       : 1, basic stack frame; 0, extended stack frame
       3       : 1, return to Thread mode; 0, return to Handler mode
       2       : 1, return to PSP; 0, return to MSP
       1       : reserved, 0
       0       : reserved, 1
     */
#if defined (TOS_CFG_CPU_ARM_FPU_EN) && (TOS_CFG_CPU_ARM_FPU_EN == 1U)
    *--sp = (cpu_data_t)0xFFFFFFFDL;
#endif

    *--sp = (cpu_data_t)0x11111111u;    /* R11      */
    *--sp = (cpu_data_t)0x10101010u;    /* R10      */
    *--sp = (cpu_data_t)0x09090909u;    /* R9       */
    *--sp = (cpu_data_t)0x08080808u;    /* R8       */
    *--sp = (cpu_data_t)0x07070707u;    /* R7       */
    *--sp = (cpu_data_t)0x06060606u;    /* R6       */
    *--sp = (cpu_data_t)0x05050505u;    /* R5       */
    *--sp = (cpu_data_t)0x04040404u;    /* R4       */

    return (k_stack_t *)sp;
}

檢測任務棧最多使用位元組數

tos_task.c 文件中提供了 API:tos_task_stack_draught_depth(k_task_t *task, int *depth)

__API__ k_err_t tos_task_stack_draught_depth(k_task_t *task, int *depth)
{
    TOS_CPU_CPSR_ALLOC();
    k_err_t rc;

    // 判斷傳入的參數depth是否合法,不合法直接return
    TOS_PTR_SANITY_CHECK(depth);
    

    // 判斷傳入的參數task是否合法,不合法則使用當前的運行的任務task
    if (unlikely(!task)) {
        task = k_curr_task;
    }

    TOS_OBJ_VERIFY(task, KNL_OBJ_TYPE_TASK);
    
    // 關中斷
    TOS_CPU_INT_DISABLE();
    
    // 實際用於檢測任務棧最大深度的函數
    rc = cpu_task_stack_draught_depth(task->stk_base, task->stk_size, depth);
    
    // 開中斷
    TOS_CPU_INT_ENABLE();

    return rc;
}

可以看到實際檢測任務棧最大深度的函數是 cpu_task_stack_draught_depth(k_stack_t *stk_base, size_t stk_size, int *depth)

__KNL__ k_err_t cpu_task_stack_draught_depth(k_stack_t *stk_base, size_t stk_size, int *depth)
{
    uint8_t *slot;
    uint8_t *sp, *bp;
    int the_depth = 0;

    // 棧底
    bp = (uint8_t *)&stk_base[0];

    // 棧頂4位元組對齊
    sp = &stk_base[stk_size];
    sp = (uint8_t *)((cpu_addr_t)sp & 0xFFFFFFF8);

    /*
     * 從棧頂開始遍歷到棧底,
     * 由於在初始化時將任務棧的每個位元組初始化為了0xCC,
     * 如果當前位置的值不為0xCC則是被任務使用了,
     * 棧頂的地址與當前位置的地址的差值為此時任務使用的深度,
     * 當遍歷到最後一個不為0xCC的地址時,
     * 差值為任務棧使用的最大深度
    */
    for (slot = sp - 1; slot >= bp; --slot) {
        if (*slot != 0xCC) {
            the_depth = sp - slot;
        }
    }

    *depth = the_depth;
    if (the_depth == stk_size) {
        return K_ERR_TASK_STK_OVERFLOW;
    }

    return K_ERR_NONE;
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 1、導航查詢特點 作用:主要處理主對象裡面有子對象這種層級關係查詢 1.1 無外鍵開箱就用 其它ORM導航查詢 需要 各種配置或者外鍵,而SqlSugar則開箱就用,無外鍵,只需配置特性和主鍵就能使用 1.2 高性能優 查詢 性能非常強悍 支持大數據分頁導航查詢 3.3 語法超級爽 註意:多級查詢時 ...
  • 前言 在Web 應用程式中,我們經常會遇到這樣的場景,如用戶信息,租戶信息本次的請求過程中都是固定的,我們希望是這種信息在本次請求內,一次賦值,到處使用。本文就來探討一下,如何在.NET Core 下去利用AsyncLocal 實現全局共用變數。 簡介 我們如果需要整個程式共用一個變數,我們僅需將該 ...
  • 此次,iNeuOS工業互聯網操作系統升級主要針對三維(3D)模型線上編輯與應用、數據實時統計。用戶有現成的3D模型可以導入到平臺中,模型部件與數據點進行綁定,實時反饋狀態信息到3D模型中。數據實時統計主要後期應用到線上Excel報表中,快速開發和生成時表報、日報表、月報表和年報表等應用。 ...
  • 從編程開發的角度來簡單來說,CLR就相當於“執行/運行”我們所編寫程式的“環境/服務”。這就好比如我們組裝了一個賽車,我們的賽車需要依賴“跑道”作為一個環境,賽車才能進行飛馳。而這個“跑道”就類似於CLR。在Java平臺中程式員要向一臺電腦部署軟體時,要確保軟體運行,電腦上就要按照JVM(Java虛 ...
  • 本文介紹,如何使用Metalama庫對.NET項目添加自定義的代碼分析,即自定義的編譯時警告、錯誤 ...
  • 有沒有想過如果我們自己要設計一門編程語言,要做到什麼樣的標準才能符合在.Net平臺下運行的條件呢?.Net在官方描述過一段話,大體的意思變成白話是:只要你的語言在編譯後能夠轉換成CIL代碼,那麼你的語言就可以在.Net平臺下進行開發和運行。 CIL語言之所以能夠在.Net平臺下運行,實際上它是符合了 ...
  • 介紹指令集的指令格式、定址方式、指令類型,介紹了一些著名的指令集。 ...
  • 佈置的Linux作業裡面有個配置yum和安裝telnet和嘗試命令:telnet 127.0.0.1,並記錄結果,寫作業中間一直報錯,搞了五六個小時才完成。分享一下安裝telnet過程。 虛擬機VMware16 光碟 CentOS 7 阿裡鏡像:阿裡雲開源鏡像站資源目錄 下載DVD-2009.iso ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...