首页 > 其他分享 >FreeRtos中任务的有关理解

FreeRtos中任务的有关理解

时间:2024-11-05 10:24:09浏览次数:2  
标签:const FreeRTOS FreeRtos void OLED 任务 理解 xTaskCreate

osThreadNew 和 xTaskCreate 都是用于创建任务(线程)的函数,但它们属于不同的接口和框架。

接口层级:

    • xTaskCreate: 是 FreeRTOS 的原生 API 直接用于创建任务,属于 FreeRTOS 的核心函数。这是一个更低级的接口,直接与 FreeRTOS 的调度器交互。
    • osThreadNew: 是根据 CMSIS-RTOS API 规范定义的接口,目的是提供一个更高层次的、硬件无关的 RTOS 接口。CMSIS-RTOS API 可以被视为在 FreeRTOS 之上提供了一层抽象,使得代码更具可移植性。
  • 使用 xTaskCreate 是一个针对 FreeRTOS 的直接接口,提供了更底层的控制。
  • 使用 osThreadNew 则是一个更加标准化和可移植的方式,适合需要与不同 RTOS 系统兼容的项目。

 创建任务时使用的函数:(静态和动态)

BaseType_t xTaskCreate( TaskFunction_t pxTaskCode, // 函数指针, 任务函数
                        const char * const pcName, // 任务的名字
                        const configSTACK_DEPTH_TYPE usStackDepth, // 栈大小,单位为word,10表示40字节
                        void * const pvParameters, // 调用任务函数时传入的参数
                        UBaseType_t uxPriority,    // 优先级
                        TaskHandle_t * const pxCreatedTask ); // 任务句柄, 以后使用它来操作这个任务

参数说明:

参数描述
pvTaskCode 函数指针,任务对应的 C 函数。任务应该永远不退出,或者在退出时调用 "vTaskDelete(NULL)"。
pcName 任务的名称,仅用于调试目的,FreeRTOS 内部不使用。pcName 的长度为 configMAX_TASK_NAME_LEN。
usStackDepth 每个任务都有自己的栈,usStackDepth 指定了栈的大小,单位为 word。例如,如果传入 100,表示栈的大小为 100 word,即 400 字节。最大值为 uint16_t 的最大值。确定栈的大小并不容易,通常是根据估计来设定。精确的办法是查看反汇编代码。
pvParameters 调用 pvTaskCode 函数指针时使用的参数:pvTaskCode(pvParameters)。
uxPriority 任务的优先级范围为 0~(configMAX_PRIORITIES – 1)。数值越小,优先级越低。如果传入的值过大,xTaskCreate 会将其调整为 (configMAX_PRIORITIES – 1)。
pxCreatedTask 用于保存 xTaskCreate 的输出结果,即任务的句柄(task handle)。如果以后需要对该任务进行操作,如修改优先级,则需要使用此句柄。如果不需要使用该句柄,可以传入 NULL。
返回值 成功时返回 pdPASS,失败时返回 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY(失败原因是内存不足)。请注意,文档中提到的失败返回值是 pdFAIL 是不正确的。pdFAIL 的值为 0,而 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY 的值为 -1。
TaskHandle_t xTaskCreateStatic ( 
    TaskFunction_t pxTaskCode,   // 函数指针, 任务函数
    const char * const pcName,   // 任务的名字
    const uint32_t ulStackDepth, // 栈大小,单位为word,10表示40字节
    void * const pvParameters,   // 调用任务函数时传入的参数
    UBaseType_t uxPriority,      // 优先级
    StackType_t * const puxStackBuffer, // 静态分配的栈,就是一个buffer
    StaticTask_t * const pxTaskBuffer // 静态分配的任务结构体的指针,用它来操作这个任务
);

相比于使用动态分配内存创建任务的函数,最后2个参数不一样:

参数描述
pvTaskCode 函数指针,可以简单地认为任务就是一个C函数。 它稍微特殊一点:永远不退出,或者退出时要调用"vTaskDelete(NULL)"
pcName 任务的名字,FreeRTOS内部不使用它,仅仅起调试作用。 长度为:configMAX_TASK_NAME_LEN
usStackDepth 每个任务都有自己的栈,这里指定栈大小。 单位是word,比如传入100,表示栈大小为100 word,也就是400字节。 最大值为uint16_t的最大值。 怎么确定栈的大小,并不容易,很多时候是估计。 精确的办法是看反汇编码。
pvParameters 调用pvTaskCode函数指针时用到:pvTaskCode(pvParameters)
uxPriority 优先级范围:0~(configMAX_PRIORITIES – 1) 数值越小优先级越低, 如果传入过大的值,xTaskCreate会把它调整为(configMAX_PRIORITIES – 1)
puxStackBuffer 静态分配的栈内存,比如可以传入一个数组, 它的大小是usStackDepth*4。
pxTaskBuffer 静态分配的StaticTask_t结构体的指针
返回值 成功:返回任务句柄; 失败:NULL

 

编程实例

在02_freertos_first_app中,默认任务运行LCD程序,显示字符,自己使用xTaskCreate函数创建的任务中运行LED闪烁程序。LCD程序和LED闪烁程序内部都是死循环实现,在裸机中是不可能同时运行的,但是在freertos中,通过任务调度,可以让用户看到两个程序同时运行的现象。(本质上是交替执行的)

void Led_Test(void)
{
    Led_Init();

    while (1)
    {
        Led_Control(LED_GREEN, 1);
        HAL_Delay(500);
        Led_Control(LED_GREEN, 0);
        HAL_Delay(500);
    }
}

void OLED_Test(void)
{
    uint16_t cnt=0;
    OLED_Init();
    // 清屏
    OLED_Clear();
    
    while (1)
    {
        // 在(0, 0)打印'A'
        OLED_PutChar(0, 0, 'A');
        // 在(1, 0)打印'Y'
        OLED_PutChar(1, 0, 'Y');
        // 在第0列第2页打印一个字符串"Hello World!"
        OLED_PrintString(0, 2, "Hello World!");
        OLED_PrintSignedVal(0, 4, cnt++);
    }
}

//默认任务
defaultTaskHandle = osThreadNew(StartDefaultTask, NULL, &defaultTask_attributes);

//led任务
xTaskCreate(MyTask,"myfirsttask",128,NULL,osPriorityNormal,NULL);

void StartDefaultTask(void *argument)
{
  /* USER CODE BEGIN StartDefaultTask */
  /* Infinite loop */
  for(;;)
  {
    //osDelay(1);
    //Led_Test();
    LCD_Test();
  }
}

void MyTask(void *argument)
{
    while(1)
    {
        Led_Test();
    }
}

在创建任务时,FreeRTOS会在堆中开辟出一块空间,用于存放任务的控制信息TCB块和栈区Stack用于储存任务相关的变量,每一个任务都有自己的栈。

在任务切换时,FreeRTOS 需要保存当前任务的上下文,以便将来能够恢复。而后,切换到新任务时,FreeRTOS 需要加载新的任务上下文。这一过程称为上下文切换。保存现场保存在哪里呢,就保存在栈里。保存的什么呢,包括寄存器的值,pc,sp等。

标签:const,FreeRTOS,FreeRtos,void,OLED,任务,理解,xTaskCreate
From: https://www.cnblogs.com/lichungang/p/18518912

相关文章

  • .net core 使用定时任务 quartz.net 实例
    项目是core3.1的 只用引用一个包就可以了引用配置Quartz首先创建一个任务工厂publicclassCronJobFactory:IJobFactory{privatereadonlyIServiceProvider_serviceProvider;publicCronJobFactory(IServiceProviderserviceProvider){_ser......
  • ArkTS 常用状态管理:深入理解与实践
    在HarmonyOS应用开发中,ArkTS作为开发语言,其状态管理机制是构建响应式应用的核心。本文将详细介绍ArkTS中的状态管理机制,包括@State、@Prop、@Link、@Provide和@Consume等装饰器的使用,以及它们在实际开发中的应用和最佳实践。状态管理的重要性状态管理是前端开发中的一个核心......
  • 基于springboot+vue实现的任务管理系统(源码+L文)4-103
      第4章系统设计4.1总体功能设计员工,经理,管理员都需要登录才能进入任务管理系统,使用者登录时会在后台判断使用的权限类型,包括一般使用者和管理者,一般使用者为员工和经理,对员工只能提供任务信息显示查询,对经理还有部分修改功能,而对管理者则能基本全部任务信息内容提供......
  • NeurIPS 2024 | 真实世界复杂任务,全新基准GTA助力大模型工具调用能力评测
     点击访问我的技术博客https://tmqcjr.com/利用语言模型调用工具,是实现通用目标智能体(general-purposeagents)的重要途径,对语言模型的工具调用能力提出了挑战。然而,现有的工具评测和真实世界场景存在很大差距,局限性主要体现在以下几个方面:评估问题通常是AI生成的,形式固......
  • NSET or MSET算法--原理解析
    1.背景NSET/MSET是一种非线性的多元预测诊断技术,广泛应用于系统状态估计、故障诊断和预测等领域;相比于传统的线性模型和方法,NSET/MSET能够更好地处理非线性系统,并提供更准确的预测和诊断能力。在早期,MSET融合了模式识别技术和序贯概率比检验方法,主要应用于核电厂信号验证、......
  • Linux配置定时任务,定时(每分钟)查看jar是否运行,没有运行则重新启动
    Linux配置定时任务,定时(每分钟)查看jar是否运行,没有运行则重新启动部署在Linux服务器上的服务,有时会因为其他原因(如内存溢出,误杀)导致服务被kill了,影响业务的正常运行。为避免这类问题发生,需要配置监控(定时查询服务是否还在运行中),当发现服务被kill掉了,则重新启动!1、准备工作Jav......
  • Java面试高频问题:深入理解 volatile 关键字的作用与实际应用
    在Java并发编程中,volatile是一个常见的关键字,尤其在多线程面试中经常被提及。很多开发者只了解volatile能“防止指令重排序”或者“保证可见性”,但真正理解其应用并正确使用的人并不多。这篇文章将详细介绍volatile的原理、使用场景、实际案例和面试常见问题,帮助你更......
  • 深入理解Java中的数组克隆:浅克隆与深克隆
    深入理解Java中的数组克隆:浅克隆与深克隆在Java编程中,数组的克隆是一个常见的需求,尤其是在处理复杂数据结构时。Java提供了数组的clone方法,但这个方法的行为在不同情况下有所不同。本文将通过一个具体的代码示例,深入探讨Java中数组的浅克隆和深克隆的概念,并解释它们之间的区别......