FreeRTOS任务基础

本文是《ALIENTEK STM32F429 FreeRTOS 开发教程》第五章学习笔记
第一章笔记–FreeRTOS简介与源码下载
第二章笔记–FreeRTOS在STM32F4上移植
第三章笔记-FreeRTOS系统配置
第四章笔记-FreeRTOS中断分析
第四章笔记补充-FreeRTOS临界段代码

1. 多任务系统

未加操作系统时,单片机跑裸板程序,一般是在main函数中用以个While(1)的大循环来完成所有操作。即应用程序是一个无限的循环,循环中调用相应的函数完成所需的操作。有时也需要中断中完成一些操作。

相对于多任务系统,这样的while(1)做一个大循环完成所有操作称为前后台系统(单任务系统),中断服务函数作为前台程序,大循环while(1)作为后台程序。

前后台系统实时性差。各个任务排队等待着轮流执行,但是前后台系统简单。消耗资源少,但在稍微大一些的嵌入式应用中前后台系统显得力不从心

多任务系统把一个大问题,划分成许多小问题,这些小问题单独作为一个小任务来处理。这些小任务是并发处理的,但并不是同一时刻一起执行很多任务,而是由于每个任务执行的时间很短,导致看起来同一时刻执行了很多任务。

多任务系统中的任务调度器,使操作系统永远执行高优先级的任务,高优先级的任务可以打断低优先级任务而取得CPU的使用权,高优先级的任务执行完成以后重新把CPU的使用权还给低优先级的任务。

2. 任务

2.1 任务特性

  1. 简单
  2. 没有使用限制
  3. 支持抢占(低优先级可以被高优先级打断)
  4. 支持优先级(CPU永远执行优先级最高的任务)
  5. 每个任务都拥有堆栈 (任务切换需要把上下文环境保存在堆栈中,这样当任务再次执行可以从堆栈中取出上下文环境,任务恢复运行)
  6. 如果使用抢占则必须仔细考虑充入的问题

2.2 任务状态

运行态

正在使用CPU的任务,即正在运行的任务,称这个任务处于运行态。如果是单核处理器,不论任何时刻,永远只有一个任务处于运行态

就绪态

当任务已经准备就绪(没有被阻塞或者挂起),可以运行的任务,但是还没有运行(因为有一个同优先级或者更高优先级任务正在运行)称为就绪态任务

阻塞态

如果一个任务当前正在等待某个外部事件则称为阻塞态任务,比如某个任务调用了函数vTaskDelay()便会进入阻塞态,直到延时周期完成

任务在等待队列、信号量、事件组、通知或互斥信号量时也会进入阻塞态。

任务进入阻塞态会有一个超时时间,当超过这个超时时间任务就会退出阻塞态,即使所等待的事件还没来临

挂起态

跟阻塞态一样,任务进入挂起态以后不能被任务调度器调用进入运行态,但是进入挂起态的任务没有超时时间。

任务进入和退出挂起态通过调用函数vTaskSuspend()和xTaskResume()

任务间的状态转换

这里写图片描述

2.3 任务优先级

每个任务都可以分配一个优先级,优先级可选范围是:从0~(configMAX_PRIORITIES-1)的

configMAX_PRIORITIES在FreeRTOSConfig.h中定义

#define configMAX_PRIORITIES (32)    //可使用的最大优先级

优先级数字越大表示优先级越高,0的优先级最低,configMAX_PRIORITIES-1优先级最高。空闲任务的优先级最低,为0。

2.4 任务控制块

FreeRTOS每个任务都有一些属性需要储存,FreeRTOS把这些属性集合到一起用一个结构体(TCB_t)来表示.

tasks.c里面有结构体源码:

typedef struct tskTaskControlBlock
{
    volatile StackType_t    *pxTopOfStack;  /*< Points to the location of the last item placed on the tasks stack.  THIS MUST BE THE FIRST MEMBER OF THE TCB STRUCT. */

    #if ( portUSING_MPU_WRAPPERS == 1 )
        xMPU_SETTINGS   xMPUSettings;       /*< The MPU settings are defined as part of the port layer.  THIS MUST BE THE SECOND MEMBER OF THE TCB STRUCT. */
    #endif

    ListItem_t          xStateListItem; /*< The list that the state list item of a task is reference from denotes the state of that task (Ready, Blocked, Suspended ). */
    ListItem_t          xEventListItem;     /*< Used to reference a task from an event list. */
    UBaseType_t         uxPriority;         /*< The priority of the task.  0 is the lowest priority. */
    StackType_t         *pxStack;           /*< Points to the start of the stack. */
    char                pcTaskName[ configMAX_TASK_NAME_LEN ];/*< Descriptive name given to the task when created.  Facilitates debugging only. */ /*lint !e971 Unqualified char types are allowed for strings and single characters only. */

    #if ( portSTACK_GROWTH > 0 )
        StackType_t     *pxEndOfStack;      /*< Points to the end of the stack on architectures where the stack grows up from low memory. */
    #endif

    #if ( portCRITICAL_NESTING_IN_TCB == 1 )
        UBaseType_t     uxCriticalNesting;  /*< Holds the critical section nesting depth for ports that do not maintain their own count in the port layer. */
    #endif

    #if ( configUSE_TRACE_FACILITY == 1 )
        UBaseType_t     uxTCBNumber;        /*< Stores a number that increments each time a TCB is created.  It allows debuggers to determine when a task has been deleted and then recreated. */
        UBaseType_t     uxTaskNumber;       /*< Stores a number specifically for use by third party trace code. */
    #endif

    #if ( configUSE_MUTEXES == 1 )
        UBaseType_t     uxBasePriority;     /*< The priority last assigned to the task - used by the priority inheritance mechanism. */
        UBaseType_t     uxMutexesHeld;
    #endif

    #if ( configUSE_APPLICATION_TASK_TAG == 1 )
        TaskHookFunction_t pxTaskTag;
    #endif

    #if( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 )
        void *pvThreadLocalStoragePointers[ configNUM_THREAD_LOCAL_STORAGE_POINTERS ];
    #endif

    #if( configGENERATE_RUN_TIME_STATS == 1 )
        uint32_t        ulRunTimeCounter;   /*< Stores the amount of time the task has spent in the Running state. */
    #endif

    #if ( configUSE_NEWLIB_REENTRANT == 1 )
        /* Allocate a Newlib reent structure that is specific to this task.
        Note Newlib support has been included by popular demand, but is not
        used by the FreeRTOS maintainers themselves.  FreeRTOS is not
        responsible for resulting newlib operation.  User must be familiar with
        newlib and must provide system-wide implementations of the necessary
        stubs. Be warned that (at the time of writing) the current newlib design
        implements a system-wide malloc() that must be provided with locks. */
        struct  _reent xNewLib_reent;
    #endif

    #if( configUSE_TASK_NOTIFICATIONS == 1 )
        volatile uint32_t ulNotifiedValue;
        volatile uint8_t ucNotifyState;
    #endif

    /* See the comments above the definition of
    tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE. */
    #if( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
        uint8_t ucStaticallyAllocated;      /*< Set to pdTRUE if the task is a statically allocated to ensure no attempt is made to free the memory. */
    #endif

    #if( INCLUDE_xTaskAbortDelay == 1 )
        uint8_t ucDelayAborted;
    #endif

} tskTCB;

/* The old tskTCB name is maintained above then typedefed to the new TCB_t name
below to enable the use of older kernel aware debuggers. */
typedef tskTCB TCB_t;

2.5 任务堆栈

FreeRTOS的任务调度器在进行任务切换的时候,会将当前任务的现场(CPU寄存器值等)保存在此任务的任务堆栈中,等到下次任务运行的时候先用堆栈中保存的值来恢复现场,恢复现场以后任务会接着从上次中断的地方开始运行

任务堆栈类型:

#define portSTACK_TYPE  uint32_t

typedef portSTACK_TYPE StackType_t;

因为是uint32_t类型,任务堆栈大小=(设置的值*4)B

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值