一、创建任务核心
创建任务核心有三个:
①任务要执行的函数
②栈:函数运行过程的局部变量保存在哪,被切换的瞬间寄存器保存在哪
③TCP结构体:如何表示这个任务,如何找到保存的值
这是一个任务创建函数主要关注:
pxTaskCode
函数,usStackDepth
栈深度,uxPriority
优先级,pxCreatedTask
TBC结构体
BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
const configSTACK_DEPTH_TYPE usStackDepth,
void * const pvParameters,
UBaseType_t uxPriority,
TaskHandle_t * const pxCreatedTask )
我们描述一个任务会在内存中分配一个TCB结构体,里面包含了
pxTopOfStack
栈顶,xStateListItem
、xEventListItem
链表,uxPriority
优先级,pxStack
栈起始地址,pcTaskName
函数名字
typedef struct tskTaskControlBlock /* The old naming convention is used to prevent breaking kernel aware debuggers. */
{
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. */
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. */
} tskTCB;
在栈中保存了寄存器
R0-R15
,我们执行函数的时候,把函数地址赋值给PC(R15)
寄存器,参数保存在R0
。当我们想启动任务就需要把栈中寄存器数据写入CPU寄存器,这样就可以执行函数。
二、调度机制概述
2.1优先级与状态
优先级:高优先级任务优先执行,同优先级轮流执行(时间片轮转)
任务状态:假设有两个任务A、B
当正在运行A,那任务A就是运行态,另外一个任务是随时可以运行就是就绪态。当任务A在执行过程中要等待另一个事件一段时间才可以执行就变为阻塞态,而任务B直接休眠不知道什么时候才能启动就是暂停态
状态转换代码简单案例
void Task1Function(void * param)
{
TickType_t tstart = xTaskGetTickCount();
TickType_t t;
int flag =