目录:git
三、任务进入退出函数源码分析
四、小结post
继续分析鸿蒙轻内核源码,咱们本文开始要分析下任务及任务调度模块。首先,咱们介绍下任务栈的基础概念。任务栈是高地址向低地址生长的递减栈,栈指针指向即将入栈的元素位置。初始化后未使用过的栈空间初始化的内容为宏OS_TASK_STACK_INIT
表明的数值0xCACACACA
,栈顶初始化为宏OS_TASK_MAGIC_WORD
表明的数值0xCCCCCCCC
。一个任务栈的示意图以下,其中,栈底指针是栈的最大的内存地址,栈顶指针,是栈的最小的内存地址,栈指针从栈底向栈顶方向生长。学习
任务上下文(Task Context)是任务及任务调度模块的另一个重要的概念,它指的是任务运行的环境,例如包括程序计数器、堆栈指针、通用寄存器等内容。在多任务调度中,任务上下文切换(Task Context Switching)属于核心内容,是多个任务运行在同一CPU
核上的基础。在任务调度时,保存退出运行状态的任务使用的寄存器信息到任务栈,还会从进入运行状态的任务的栈中读取上下文信息,恢复寄存器信息。url
下面,咱们剖析下任务栈、任务栈初始化的源代码,若涉及开发板部分,以开发板工程targets\cortex-m7_nucleo_f767zi_gcc\
为例进行源码分析。首先,看下任务上下文结构体。spa
一、 TaskContext上下文结构体定义
在文件kernel\arch\arm\cortex-m7\gcc\los_arch_context.h
中,定义的上下文的结构体以下,主要是浮点寄存器,通用寄存器。.net
typedef struct TagTskContext { #if ((defined(__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ (defined(__FPU_USED) && (__FPU_USED == 1U))) UINT32 S16; UINT32 S17; UINT32 S18; UINT32 S19; UINT32 S20; UINT32 S21; UINT32 S22; UINT32 S23; UINT32 S24; UINT32 S25; UINT32 S26; UINT32 S27; UINT32 S28; UINT32 S29; UINT32 S30; UINT32 S31; #endif UINT32 uwR4; UINT32 uwR5; UINT32 uwR6; UINT32 uwR7; UINT32 uwR8; UINT32 uwR9; UINT32 uwR10; UINT32 uwR11; UINT32 uwPriMask; UINT32 uwR0; UINT32 uwR1; UINT32 uwR2; UINT32 uwR3; UINT32 uwR12; UINT32 uwLR; UINT32 uwPC; UINT32 uwxPSR; #if ((defined(__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ (defined(__FPU_USED) && (__FPU_USED == 1U))) UINT32 S0; UINT32 S1; UINT32 S2; UINT32 S3; UINT32 S4; UINT32 S5; UINT32 S6; UINT32 S7; UINT32 S8; UINT32 S9; UINT32 S10; UINT32 S11; UINT32 S12; UINT32 S13; UINT32 S14; UINT32 S15; UINT32 FPSCR; UINT32 NO_NAME; #endif } TaskContext;
二、 任务栈相关函数
2.1 任务栈初始化函数
在文件kernel\arch\arm\cortex-m7\gcc\los_context.c
中定义了任务栈初始化函数VOID *HalTskStackInit(t()
。该函数被文件kernel\src\los_task.c
中的函数UINT32 OsNewTaskInit()
调用完成任务初始化,并进一步在建立任务函数UINT32 LOS_TaskCreateOnly()
中调用,完成新建立任务的任务栈初始化。指针
该函数使用3个参数,一个是任务编号UINT32 taskID
,一个是初始化的栈的大小UINT32 stackSize
,第3个参数是栈顶指针VOID *topStack
。⑴处代码把栈内容初始化为OS_TASK_STACK_INIT
,⑵处把栈顶初始化为OS_TASK_MAGIC_WORD
。
⑶处代码获取任务上下文的指针地址TaskContext *context
。对于新建立任务,从栈的底部开始,大小为sizeof(TaskContext)
的栈空间存放上下文的数据。⑷处若是支持浮点数计算,须要初始化浮点数相关的寄存器。⑸初始化通用寄存器,其中.uwLR
初始化为(UINT32)(UINTPTR)HalSysExit
。.uwPC
初始化为(UINT32)(UINTPTR)OsTaskEntry
,这是CPU
首次执行该任务时运行的第一条指令的位置。这2个函数下文会分析。
⑹处返回值是指针(VOID *)taskContext
,这个就是任务初始化后的栈指针,注意不是从栈底开始了,栈底保存的是上下文,栈指针要减去上下文占用的栈大小。在栈中,从TaskContext *context
指针增长的方向,依次保存上下文结构体的第一个成员,第二个成员…另外,初始化栈的时候,除了特殊的几个寄存器,不一样寄存器的初始值虽然没有什么意义,也有些初始化的规律。好比R2
寄存器初始化为0x02020202L
,R12
寄存器初始化为0x12121212L
初始化的内容和寄存器编号有关联,其他相似。
LITE_OS_SEC_TEXT_INIT VOID *HalTskStackInit(UINT32 taskID, UINT32 stackSize, VOID *topStack) { TaskContext *context = NULL; errno_t result; /* initialize the task stack, write magic num to stack top */ ⑴ result = memset_s(topStack, stackSize, (INT32)(OS_TASK_STACK_INIT & 0xFF), stackSize); if (result != EOK) { printf("memset_s is failed:%s[%d]\r\n", __FUNCTION__, __LINE__); } ⑵ *((UINT32 *)(topStack)) = OS_TASK_MAGIC_WORD; ⑶ context = (TaskContext *)(((UINTPTR)topStack + stackSize) - sizeof(TaskContext)); #if ((defined(__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \ (defined(__FPU_USED) && (__FPU_USED == 1U))) ⑷ context->S16 = 0xAA000010; context->S17 = 0xAA000011; context->S18 = 0xAA000012; context->S19 = 0xAA000013; context->S20 = 0xAA000014; context->S21 = 0xAA000015; context->S22 = 0xAA000016; context->S23 = 0xAA000017; context->S24 = 0xAA000018; context->S25 = 0xAA000019; context->S26 = 0xAA00001A; context->S27 = 0xAA00001B; context->S28 = 0xAA00001C; context->S29 = 0xAA00001D; context->S30 = 0xAA00001E; context->S31 = 0xAA00001F; context->S0 = 0xAA000000; context->S1 = 0xAA000001; context->S2 = 0xAA000002; context->S3 = 0xAA000003; context->S4 = 0xAA000004; context->S5 = 0xAA000005; context->S6 = 0xAA000006; context->S7 = 0xAA000007; context->S8 = 0xAA000008; context->S9 = 0xAA000009; context->S10 = 0xAA00000A; context->S11 = 0xAA00000B; context->S12 = 0xAA00000C; context->S13 = 0xAA00000D; context->S14 = 0xAA00000E; context->S15 = 0xAA00000F; context->FPSCR = 0x00000000; context->NO_NAME = 0xAA000011; #endif ⑸ context->uwR4 = 0x04040404L; context->uwR5 = 0x05050505L; context->uwR6