本文是《ALIENTEK STM32F429 FreeRTOS 开发教程》第五章学习笔记
第一章笔记–FreeRTOS简介与源码下载
第二章笔记–FreeRTOS在STM32F4上移植
第三章笔记-FreeRTOS系统配置
第四章笔记-FreeRTOS中断分析
第四章笔记补充-FreeRTOS临界段代码
未加操作系统时,单片机跑裸板程序,一般是在main函数中用以个While(1)的大循环来完成所有操作。即应用程序是一个无限的循环,循环中调用相应的函数完成所需的操作。有时也需要中断中完成一些操作。
相对于多任务系统,这样的while(1)做一个大循环完成所有操作称为前后台系统(单任务系统),中断服务函数作为前台程序,大循环while(1)作为后台程序。
前后台系统实时性差。各个任务排队等待着轮流执行,但是前后台系统简单。消耗资源少,但在稍微大一些的嵌入式应用中前后台系统显得力不从心
多任务系统把一个大问题,划分成许多小问题,这些小问题单独作为一个小任务来处理。这些小任务是并发处理的,但并不是同一时刻一起执行很多任务,而是由于每个任务执行的时间很短,导致看起来同一时刻执行了很多任务。
多任务系统中的任务调度器,使操作系统永远执行高优先级的任务,高优先级的任务可以打断低优先级任务而取得CPU的使用权,高优先级的任务执行完成以后重新把CPU的使用权还给低优先级的任务。
正在使用CPU的任务,即正在运行的任务,称这个任务处于运行态。如果是单核处理器,不论任何时刻,永远只有一个任务处于运行态
当任务已经准备就绪(没有被阻塞或者挂起),可以运行的任务,但是还没有运行(因为有一个同优先级或者更高优先级任务正在运行)称为就绪态任务
如果一个任务当前正在等待某个外部事件则称为阻塞态任务,比如某个任务调用了函数vTaskDelay()便会进入阻塞态,直到延时周期完成
任务在等待队列、信号量、事件组、通知或互斥信号量时也会进入阻塞态。
任务进入阻塞态会有一个超时时间,当超过这个超时时间任务就会退出阻塞态,即使所等待的事件还没来临
跟阻塞态一样,任务进入挂起态以后不能被任务调度器调用进入运行态,但是进入挂起态的任务没有超时时间。
任务进入和退出挂起态通过调用函数vTaskSuspend()和xTaskResume()
每个任务都可以分配一个优先级,优先级可选范围是:从0~(configMAX_PRIORITIES-1)的
configMAX_PRIORITIES在FreeRTOSConfig.h中定义
#define configMAX_PRIORITIES (32) //可使用的最大优先级
优先级数字越大表示优先级越高,0的优先级最低,configMAX_PRIORITIES-1优先级最高。空闲任务的优先级最低,为0。
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;
FreeRTOS的任务调度器在进行任务切换的时候,会将当前任务的现场(CPU寄存器值等)保存在此任务的任务堆栈中,等到下次任务运行的时候先用堆栈中保存的值来恢复现场,恢复现场以后任务会接着从上次中断的地方开始运行
任务堆栈类型:
#define portSTACK_TYPE uint32_t
typedef portSTACK_TYPE StackType_t;
因为是uint32_t类型,任务堆栈大小=(设置的值*4)B