0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

任务堆栈的检测方法

汽车电子技术 来源:嵌入式之入坑笔记 作者:嵌入式之入坑笔记 2023-02-10 14:11 次阅读

使用freeRTOS时,创建的每一个任务都需要分配任务的堆栈空间,这些堆栈空间一般都是使用者根据任务的情况大致分配的。使用者往往不能直接知道分配的任务堆栈空间是否足够任务运行使用,有时候可能会不够,在运行过程中就出现了堆栈溢出,导致程序出现各种各样的奇怪问题,出现问题之后可能一时半会还难以找出来。

这种情况如果能有一种检测手段能够知道任务在运行过程中堆栈的使用情况或者剩余情况,那就可以很好的把握任务堆栈的情况,也可以在一开始就避免堆栈溢出这样的问题发生,将来项目产品上线了也避免了这样的风险存在!

值得开心的是,freeRTOS真的有提供这样的检测堆栈剩余量的功能。下面介绍怎么使用freeRTOS的任务堆栈的剩余量的方法。

1、允许堆栈检测 API 的使用

freeRTOS中堆栈使用剩余量的检测使用的是 uxTaskGetStackHighWaterMark ,使用这个函数需要先将一个宏定义为 1 才能使用堆栈检测功能。

打开 FreeRTOSConfig.h 文件,找到宏

INCLUDE_uxTaskGetStackHighWaterMark 并将其值定为 1,如下:

#define INCLUDE_uxTaskGetStackHighWaterMark     1

这个宏定义为 1 之后再文件 task.c 中就可以看到函数 uxTaskGetStackHighWaterMark 生效了,说明这个函数已经是可以使用的状态了。

2、uxTaskGetStackHighWaterMark 函数的说明

freeRTOS 中任务堆栈的检测函数的函数原型如下:

UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask )
    {
        TCB_t * pxTCB;
        uint8_t * pucEndOfStack;
        UBaseType_t uxReturn;


        pxTCB = prvGetTCBFromHandle( xTask );


        #if portSTACK_GROWTH < 0
            {
                pucEndOfStack = ( uint8_t * ) pxTCB->pxStack;
            }
        #else
            {
                pucEndOfStack = ( uint8_t * ) pxTCB->pxEndOfStack;
            }
        #endif


        uxReturn = ( UBaseType_t ) prvTaskCheckFreeStackSpace( pucEndOfStack );


        return uxReturn;
    }

函数描述:

函数参数:

xTask:需要检查的堆栈情况的任务句柄。这个句柄在创建任务时就可以知道的。

注意:将 xTask 设置为 NULL 的话检测的就是调用这个函数的任务堆栈情况。

函数返回值:

自创建 xTask 这个任务以来,已存在的最小可用堆栈空间量(以字为单位)。即返回的值是以字为单位的堆栈剩余量(例如,在 32 位机器上,返回值 1 表示任务堆栈中未使用的堆栈还剩余 4 个字节)。如果返回值为零,则该任务可能堆栈已经溢出。如果返回值接近零,则任务接近堆栈溢出。

特别注意:

freeRTOS中还有一个 uxTaskGetStackHighWaterMark2() ,这个是 uxTaskGetStackHighWaterMark() 的另外一个版本,它返回一个用户可定义的类型,主要用在一些 8 位架构上数据类型宽度有限制的MCU中。

3、堆栈剩余量检测的使用方法

3.1、任务自己检测自己的堆栈情况

如果 UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) 的参数 xTask 设置为NULL,则哪个任务调用这个函数检测的就是哪个任务的堆栈情况,如下:

void vTask1( void * pvParameters )
{
    UBaseType_t uxHighWaterMark;

   // 检测任务使用前的堆栈情况
    uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );

    for( ;; )
     {
         ...    // 其他代码
         ...
         ...
         vTaskDelay( 1000 );

         // 检测任务运行之后的堆栈剩余情况
         uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
     }
 }

3.2、使用任务单独检测任务的堆栈情况

可以使用一个任务单独进行项目中的任务堆栈的情况进行检测,如下:

void TaskStackDetect_Task1( void * pvParameters )
{
    UBaseType_t uxHighWaterMark;

    for( ;; )
     {
         uxHighWaterMark = uxTaskGetStackHighWaterMark( 任务句柄1 );
         print(uxHighWaterMark);

         uxHighWaterMark = uxTaskGetStackHighWaterMark( 任务句柄2 );
         print(uxHighWaterMark);

         uxHighWaterMark = uxTaskGetStackHighWaterMark( 任务句柄3 );
         print(uxHighWaterMark);

         ......

         uxHighWaterMark = uxTaskGetStackHighWaterMark( 任务句柄n );
         print(uxHighWaterMark);

         vTaskDelay( 1000 );
     }
 }

3.3、使用软件定时器检测任务堆栈的情况

检测堆栈的剩余情况也可以使用freeRTOS中提供的软件定时器服务,创建一个软件定时器,然后在软件定时器的回调函数里面定时进行检测即可,原理和使用一个任务检测是一样的。如下:

void TaskStackDetect_Callback(TimerHandle_t pxTimer)
{
    UBaseType_t uxHighWaterMark;

    uxHighWaterMark = uxTaskGetStackHighWaterMark( 任务句柄1 );
    print(uxHighWaterMark);

    uxHighWaterMark = uxTaskGetStackHighWaterMark( 任务句柄2 );
    print(uxHighWaterMark);

    uxHighWaterMark = uxTaskGetStackHighWaterMark( 任务句柄3 );
    print(uxHighWaterMark);

         ......

    uxHighWaterMark = uxTaskGetStackHighWaterMark( 任务句柄n );
    print(uxHighWaterMark);
}
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 堆栈
    +关注

    关注

    0

    文章

    171

    浏览量

    19522
  • FreeRTOS
    +关注

    关注

    12

    文章

    473

    浏览量

    61347
  • 空间
    +关注

    关注

    2

    文章

    48

    浏览量

    13539
收藏 人收藏

    评论

    相关推荐

    uCOS任务堆栈的深入分析

    在uCOS中,每一个任务都有一个独立的任务堆栈。为了深入理解任务堆栈的作用,不妨分析任务从“出生
    发表于 11-01 11:52 3104次阅读

    详解μC/OS-II如何检测任务堆栈实际使用情况——即如何设置ucosii任务堆栈大小

    :OSTaskStkChk()不错,检测任务堆栈实际使用情况正是用的这个函数,下面来本函数的接口原型:INT8U OSTaskStkChk(INT8U prio, //待测任务的优先级
    发表于 09-23 17:00

    任务控制块和任务堆栈的关系是什么?

    学完,发现自己最基本的概念都不清楚啊。任务控制块和任务堆栈在ram上是两个独立的区域对吗?所有的系统API函数的操作都是针对TCB的,或者通过TCB对堆栈进行控制?系统中那部分内容,是
    发表于 04-20 23:56

    ucosiii堆栈使用情况检测使用率100%?

    用OSTaskStkChk函数检测堆栈的使用情况,发现有两个任务使用情况为100%,堆栈设置为1024,增大堆栈到2048,依然使用率100
    发表于 04-20 22:56

    FreeRTOS中的任务堆栈溢出检测机制

    合理的任务堆栈大小,并实际运行程序进行测试,来确保系统运行过程中不会发生堆栈溢出。FreeRTOS中的任务堆栈溢出
    发表于 10-15 13:51

    堆栈的定义与任务

    任务堆栈堆栈定义:在存储器中按数据“后进先出(LIFO)”的原则组织的连续存储空间。堆栈大小计算: TASK_STK_SIZE * sizeof(OS_STK)
    发表于 12-16 07:45

    任务堆栈是什么意思

    店里的两个不同位置做,那么这个两个位置就比喻为每个任务的“工作场所”——即任务堆栈。在uC/OS-III中,每个任务都像我们以前写的函数类似,其结构为://
    发表于 12-16 06:12

    如何设置应用任务堆栈大小?

    想到的就是堆栈大小不足。但任务所需的堆栈大小与具体应用相关,如何确定任务堆栈的大小?●●●●●●● 通过分析
    发表于 06-08 15:11

    任务系统中的堆栈使用

    在使用μC/OS的多任务应用程序中,main()启动后首先使用系统C栈,在OS启动后使用任务栈。基于μC/OS-II或μC/OS-III编写应用代码时,用户必须为每个任务声明一个堆栈
    发表于 01-05 13:52

    freertos怎么查看任务堆栈的大小?

    要通过什么方法来获取当前任务堆栈大小
    发表于 10-12 08:01

    ucosiii堆栈检测函数运用的小疑问求解

    附上堆栈检测函数的代码 #defineUsage_STK_SIZE128u //统计任务 #defineIWDG_STK_SIZE64u//看门狗任务 m data-ke->
    发表于 10-19 06:47

    关于FreeRTOS创建任务时的堆栈问题

    usStackDepth指定堆栈大小。 请问,这个堆栈是用来干什么的? 是任务中分配的局部变量放在这个堆栈里吗? 或者是任务切换过程中保存局
    发表于 10-31 08:08

    深入分析uCOS的任务堆栈

    堆栈作用的就是用来保存局部变量,从本质上讲也就是将CPU寄存器的值保存到RAM中。在uCOS中,每一个任务都有一个独立的任务堆栈。为了深入理解任务
    发表于 12-01 01:25 574次阅读

    RTOS任务堆栈大小与代码量有啥关系吗?

    需要提前分配堆栈大小,也就是在创建任务的时候分配好堆栈的大小。 比如uCOS创建一个检测(Check)任务: //
    的头像 发表于 05-26 09:34 1888次阅读

    任务系统中的堆栈使用

    不同的微控制器栈的实现也不同,许多32位处理器支持多个栈。例如,ARM Cortex-M内核有两个栈指针,分别指向主栈和进程栈。在基于μC/OS-III的应用中,多任务开始前使用主堆栈,其空间为链接命令文件中定义的堆栈区域。
    的头像 发表于 12-02 11:15 576次阅读