FreeRTOS之调试与优化

调试

1.打印

printf:FreeRTOS 工程里使用了 microlib,里面实现了 printf 函数。
我们只需实现一下函数即可使用printf:

int fputc( int ch, FILE *f );

2.断言

  • 断言用于检查程序中的某些条件是否为真。当断言条件为假时,程序会触发断言失败,通常会进入一个预先定义的错误处理流程,例如停止程序运行、输出错误信息等
#include "FreeRTOS.h"
#include "task.h"

void vTaskFunction( void *pvParameters )
{
    // 任务函数的具体实现
    for( ;; )
    {
        // 任务循环
    }
}

int main( void )
{
    TaskHandle_t xTaskHandle;
    BaseType_t xReturned;

    // 创建任务
    xReturned = xTaskCreate( vTaskFunction, "TaskName", 100, NULL, 1, &xTaskHandle );

    // 使用断言检查任务创建是否成功
    configASSERT( xReturned == pdPASS );

    // 启动调度器
    vTaskStartScheduler();

    for( ;; );
}
  • 在调用 xTaskCreate() 函数创建任务后,使用 configASSERT() 宏检查任务创建是否成功。如果任务创建失败(xReturned 不等于 pdPASS),则触发断言失败
  • 若失败,会进入一个预先定义的错误处理流程,如
#include <stdio.h>

#define configASSERT( x ) if( ( x ) == 0 ) { \
    printf("Assertion failed at file %s, line %d\n", __FILE__, __LINE__); \
    taskDISABLE_INTERRUPTS(); \
    for( ;; ); \
}
  • 如果断言失败发生在 main.c 文件的第 20 行,会输出类似 Assertion failed at file main.c, line 20 的信息
  • 接着调用 taskDISABLE_INTERRUPTS() 函数禁用所有中断,使系统进入无中断响应状态。

3.Malloc Hook 函数

编程时,一般的逻辑错误都容易解决。难以处理的是内存越界、栈溢出等。
内存越界经常发生在堆的使用过程中,堆,就是使用malloc得到的内存。并没有很好的方法检测内存越界,但是可以提供一些回调函数
使用 pvPortMalloc 失败时,如果在 FreeRTOSConfig.h 里配置configUSE_MALLOC_FAILED_HOOK 为 1,会调用:

void vApplicationMallocFailedHook( void );

4.栈溢出 Hook 函数

当 FreeRTOS 检测到栈溢出时,会自动调用这个函数。开发者可以在这个函数中实现一些处理逻辑
要启用栈溢出检测功能,需要在 FreeRTOSConfig.h 文件中进行相应的配置:

#define configCHECK_FOR_STACK_OVERFLOW 2

0:禁用栈溢出检测功能。
1:使用简单的栈边界检查方法。(多用)
2:使用简单的栈边界检查方法,并且在任务切换时也进行检查,检测更频繁
函数

void vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName );

参数说明:
xTask:指向发生栈溢出的任务句柄。
pcTaskName:指向发生栈溢出的任务名称的字符串指针。
简单示例

#include "FreeRTOS.h"
#include "task.h"
#include <stdio.h>

void vApplicationStackOverflowHook( TaskHandle_t xTask, signed char *pcTaskName )
{
    printf("Stack overflow detected in task: %s\n", pcTaskName);

    // 可以在这里添加更多的处理逻辑,例如重启系统
    // NVIC_SystemReset();
}

优化

1.栈使用情况

可以使用以下函数查看是还有多少空余的栈空间

UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask );
#include "FreeRTOS.h"
#include "task.h"
#include <stdio.h>

// 任务函数
void vTaskFunction( void *pvParameters )
{
    UBaseType_t uxHighWaterMark;

    for( ;; )
    {
        // 模拟任务的一些工作
        for( int i = 0; i < 1000; i++ )
        {
            // 这里可以添加更复杂的任务逻辑
        }

        // 获取当前任务的栈高水位线
        uxHighWaterMark = uxTaskGetStackHighWaterMark( NULL );
        printf("Stack high water mark of current task: %lu\n", (unsigned long)uxHighWaterMark);

        // 任务延时
        vTaskDelay( pdMS_TO_TICKS( 1000 ) );
    }
}

int main( void )
{
    // 创建任务
    xTaskCreate( vTaskFunction, "TaskName", 1000, NULL, 1, NULL );

    // 启动调度器
    vTaskStartScheduler();

    // 如果调度器启动失败,程序会执行到这里
    for( ;; );
}

vTaskList :获得任务的统计信息,形式为可读的字符串。注意,pcWriteBuffer必须足够大。

void vTaskList( signed char *pcWriteBuffer );

可读信息格式如下在这里插入图片描述

2.任务运行时间统计

配置(可在cubemx中配置)
#define configGENERATE_RUN_TIME_STATS 1
#define configUSE_TRACE_FACILITY 1
#define configUSE_STATS_FORMATTING_FUNCTIONS 1

在vTaskSwitchContext()函数中在这里插入图片描述
接着利用vTaskGetRunTimeStats:获得任务的运行信息,形式为可读的字符串。注意,pcWriteBuffer 必须足够大。

void vTaskGetRunTimeStats( signed char *pcWriteBuffer );

可读信息格式如下:在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值