FreeRTOS

发布时间 2023-06-06 20:14:52作者: 耿通宇

一、简介 、特点

  FreeRTOS (Free 免费的  Real  Time  Operate  System 实时操作系统)。文件数量比UCOS少(4-9K字节)。特点:可裁剪(通过配置文件里的宏定义),任务数量、优先级不限,支持低功耗的Tickless模式,堆栈溢出检测。

二、源码获取   (官网: www.freertos.org)

  

  1、提取文件

      

  2、实现串口收发(printf重定向,调试)和系统嘀嗒定时器(涉及RTOS的系统时钟)如果实现了timer2定时器先注释,笔者发现两个都初始化后任务创建不成功(timer2定时器中断优先级比较高的原因,调低就可以了

      systic.c文件里初始化完后要实现中断服务函数,实现delay_us(u32 us) 和 delay_xms(u32 ms) 延时函数,初始化和中断这里跟我们平时写的有差异,只因他是专门服务于FreeRTOS,文件放到博客园下了。

       

      FreeRTOS 心跳由滴答定时器产生,根据 FreeRTOS 的系统时钟节拍设置好滴答定时器的周期,这样就会周期触发滴答定时器中断了。在滴答定时器中断服务函数中调用FreeRTOS 的 API 函数 xPortSysTickHandler()。      

      如上1、2做完,工程添加完毕后编译:除图二错误可能还有中断函数重复定义等,因为RTOS里又定义了一次,把stm32f10x_it.c里的注释掉。

三、配置FreeRTOSConfig.h

  实际使用中通过该文件完成裁剪和配置:INCLUDE 开头的宏表示使能或不使用对应的API函数。如图所示(部分):具体文件已保存到博客园文件下了,F1和F4均通用。

      

四、任务基础   (创建、删除、挂起、恢复)

  1、简介:任何一个时间点只能有一个任务运行,由调度器决定,其职责是保证任务执行时的上下文环境 (寄存器值、堆栈内容等)和任务上一次退出时相同。为此,任务必须有其堆栈(保存上下文环境)。

  2、特性:无限制、支持抢占、优先级,任务都有堆栈导致RAM增大,使用抢占须考虑重入问题。

  3、状态:运行态、就绪态、阻塞态、挂起态。(由图可知,挂起态任务恢复后不是直接进到运行态,而是进到就绪态,阻塞态同理)

        

  4、优先级:每个任务都能分配0~(configMAX_PRIORITIES-1)的优先级,共32级,0-31,数值越低优先级越低(与单片机中断优先级和UCOS相反),空闲任务优先级最低,为0。同一个优先级时通过时间片轮转调度器获取运行时间。

    5、任务创建: xTaskCreate() 动态创建:任务所需RAM从RTOS堆中分配,需提供heap_4.c内存管理文件,宏 configSUPPORT_DYNAMIC_ALLOCATION 须为 1; xTaskCreateStatic() ;静态创建:RAM需用户提供。

         创建的任务是就绪态,若没有比它高优先级的任务运行则立即进入运行态。不管调度器是否启用。

    int main(void)

    TaskHandle_t StartTask_Handler;     //任务句柄  ----堆栈大小,优先级等也可以使用宏定义 ,如果没有其它API使用任务句柄也可以为NULL。任务创建定义在主函数最后面,则main.c不需要while(1)。

    BaseType_t xTaskCreate( (TaskFunction_t )pxTaskCode,                 //任务函数   (动态创建)                                                                                                                           (实际参数如:stat_task)

                (const char * )const pcName,                   //任务名字,一般用于追踪和调试,长度不超过configMAX_TASK_NAME_LEN                                         (如:"stat_task")

                (const uint16_t) usStackDepth,                 //堆栈大小,申请的实际字节为传入数据的4倍。空闲任务堆栈大小为:configMINIMAL_STACK_SIZE      (如:128)

                (void *) const pvParameters,                     //传递给任务函数的参数                                   (如:NULL)

                (UBaseType_t) uxPriority,                          //任务优先级, 0~ configMAX_PRIORITIES-1 值越大优先级越高                 (如:3)

                (TaskHandle_t *) const pxCreatedTask   ) // 成功返回句柄, 其实就是任务堆栈,堆栈就是保存任务句柄,其它API操作这个任务就是使用任务句柄  (如:&StartTask_Handler)

                pdPASS :创建成功返回    errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY: 创建失败,堆内存不足(太大空间不够,太小任务创建失败)  ,如下,除头文件外一个完整的main.c函数            

#include "stm32f10x.h"
#include "led.h"
#include "usart.h"
#include "delay.h"
#include "FreeRTOS.h"
#include "task.h"
TaskHandle_t StartTask_Handler;
void start_task(void *pvParameters);
int main (void){
    usart1_init(115200);        
    led2_init ();
    delay_init();
    xTaskCreate((TaskFunction_t )start_task,         //创建开始任务 任务函数
                (const char*    )"start_task",       //任务名称
                (uint16_t       )128,                //任务堆栈大小 可使用宏
                (void*          )NULL,               //传递给任务函数的参数
                (UBaseType_t    )1,                  //任务优先级 可使用宏
                (TaskHandle_t*  )&StartTask_Handler);//任务句柄              
    vTaskStartScheduler();          //开启任务调度
}
void start_task(void *pvParameters){//开始任务任务函数
    taskENTER_CRITICAL();           //进入临界区
    //创建TASK1任务
    xTaskCreate((TaskFunction_t )task1_task,             
                (const char*    )"task1_task",           
                (uint16_t       )128,        
                (void*          )NULL,                  
                (UBaseType_t    )2,        
                (TaskHandle_t*  )&Task1Task_Handler);   
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}
void task1_task(void *pvParameters){
    while(1){
        LED2_ON;
        delay_ms(1000);
        LED2_OFF;
        vTaskDelay(1000);   
    }
}              

 

    TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,      //任务函数   (静态创建)

                const char * const pcName,                     //任务名字

                const uint32_t ulStackDepth,                   //任务堆栈大小,静态创建由用户给,一般是个数组,传入的参数就是数组大小

                void * const pvParameters,                      //传递给任务函数的参数

                UBaseType_t uxPriority,                           //任务优先级, 0~ configMAX_PRIORITIES-1

                StackType_t * const puxStackBuffer,       //任务堆栈,一般为数组,数组类型: StackType_t 

                StaticTask_t * const pxTaskBuffer    )       //任务控制块

                NULL:创建失败,puxStackBuffer 或 pxTaskBuffer 为 NULL时        其它值:任务创建成功,返回任务句柄

    xTaskCreateRestricted()  :此函数创建的任务会受到MPU的保护,要求MCU有MPU(内存保护单元),其它功能和 xTaskCreate() 一致。

                

 

  6、任务删除:删除后不会进入运行态,也不能再使用任务句柄,动态创建的任务删除后空间被释放,但如果任务中调用 pvPortMalloc()分配的则删除任务后调用vPortFree()释放,否则内存泄漏。

        vTaskDelete( TaskHandle_t xTaskToDelete )     参数:要删除的任务句柄   

  7、任务挂起和恢复

        a、挂起:void vTaskSuspend( TaskHandle_t xTaskToSuspend)  参数:要挂起的任务句柄   参数为NULL表示挂起任务自己。特性:恢复后任务中变量保存的值不变。

        b、恢复:void vTaskResume( TaskHandle_t xTaskToResume)   参数:要恢复的任务句柄

        c、恢复(中断版本):BaseType_t xTaskResumeFromISR( TaskHandle_t xTaskToResume)   用于在中断服务函数中恢复一个任务。

                   返回值pdTRUE:优先级 >= 正在运行的任务,退出中断函数后必须进行一次上下文切换。pdFALSE:优先级 < 正在运行的任务,退出中断函数后不用进行上下文切换。  

五、任务查询、统计相关API(调试用)

  1、