Liteos-A任务调度之OsTaskStackInit函数
之前看过Liteos-a任务调度部分源码,本来想系统的记录一下学习的结果,但是奈何能力不足,又不甘心啥都不写,所以决定碎片化的记录一下学习到的东西。liteos-a是一个操作系统,所以看源码也需要了解基本的操作系统知识,本文不对这些基本知识进行多余的解释。如:
什么是任务?任务和线程有什么区别?任务或线程都有哪些状态?
而任务调度这部分也涉及汇编语言,liteos-a是基于arm架构,所以用的是arm汇编,需要各位了解arm架构和汇编的一些知识。
任务调度包含了任务的初始化,任务的切换,而任务切换包括保存当前任务,加载新任务,当新任务运行完或运行时被更高的任务打断时,就会再次进行任务切换,即保存当前任务,加载新任务。。。这都是后话,本文讲的是任务调度之前的任务栈的初始化,具体函数是OsTaskStackInit函数。
一、代码简单注释
参数:
UINT32 taskID —— 任务ID
UINT32 stackSize —— 任务栈大小
VOID *topStack —— 任务栈顶
BOOL initFlag —— 初始化标志位,用来判断是否需要栈的初始化
返回值:
(VOID *)taskContext —— 任务上下文指针
LITE_OS_SEC_TEXT_INIT VOID *OsTaskStackInit(UINT32 taskID, UINT32 stackSize, VOID *topStack, BOOL initFlag)
{if (initFlag == TRUE) { //判断是否进行栈的初始化OsStackInit(topStack, stackSize); //任务栈的初始化}TaskContext *taskContext = (TaskContext *)(((UINTPTR)topStack + stackSize) - sizeof(TaskContext)); //声明任务上下文结构体指针,同时定位指针的位置/* initialize the task context */
#ifdef LOSCFG_GDB //LOSCFG_GDB宏未定义,执行elsetaskContext->PC = (UINTPTR)OsTaskEntrySetupLoopFrame;
#elsetaskContext->PC = (UINTPTR)OsTaskEntry; //任务切换时新任务的入口函数
#endiftaskContext->LR = (UINTPTR)OsTaskExit; /* LR should be kept, to distinguish it's THUMB or ARM instruction */taskContext->R0 = taskID; /* R0 */#ifdef LOSCFG_THUMB //LOSCFG_THUMB宏未定义,执行elsetaskContext->regCPSR = PSR_MODE_SVC_THUMB; /* CPSR (Enable IRQ and FIQ interrupts, THUMNB-mode) */
#elsetaskContext->regCPSR = PSR_MODE_SVC_ARM; /* CPSR (Enable IRQ and FIQ interrupts, ARM-mode) */
#endif//FPU(浮点单元初始化)
#if !defined(LOSCFG_ARCH_FPU_DISABLE)/* 0xAAA0000000000000LL : float reg initialed magic word */for (UINT32 index = 0; index < FP_REGS_NUM; index++) {taskContext->D[index] = 0xAAA0000000000000LL + index; /* D0 - D31 */}taskContext->regFPSCR = 0;taskContext->regFPEXC = FP_EN;
#endifreturn (VOID *)taskContext;
}
二、任务栈和任务上下文的初始化
上面的代码总共做了两件事,一个是任务栈的初始化,一个是任务上下文结构体的初始化,其中任务栈是包含任务上下文结构体的。
1.任务栈的初始化
任务栈的初始化代码是:
VOID OsStackInit(VOID *stacktop, UINT32 stacksize)
{/* initialize the task stack, write magic num to stack top */(VOID)memset_s(stacktop, stacksize, (INT32)OS_STACK_INIT, stacksize); //用OS_STACK_INIT(0xCACACACA)初始化栈空间*((UINTPTR *)stacktop) = OS_STACK_MAGIC_WORD; //用OS_STACK_MAGIC_WORD(0xCCCCCCCC)初始化栈顶指针
}
任务栈初始化完成后会有一行代码:
TaskContext *taskContext = (TaskContext *)(((UINTPTR)topStack + stackSize) - sizeof(TaskContext));
声明一个任务上下文结构体,并指向任务栈中的某一位置,空间分布大概是这样:
这个栈空间我是以栈底作为高地址,栈顶作为低地址,栈空间初始化完成了,下面就该初始化任务上下文结构体了。
2.任务上下文结构体初始化
首先是任务上下文结构体代码:
/* The size of this structure must be smaller than or equal to the size specified by OS_TSK_STACK_ALIGN (16 bytes). */
typedef struct {#if !defined(LOSCFG_ARCH_FPU_DISABLE)UINT64 D[FP_REGS_NUM]; /* D0-D31 */UINT32 regFPSCR; /* FPSCR */UINT32 regFPEXC; /* FPEXC */
#endifUINT32 R4;UINT32 R5;UINT32 R6;UINT32 R7;UINT32 R8;UINT32 R9;UINT32 R10;UINT32 R11;/* It has the same structure as IrqContext */UINT32 reserved2; /**< Multiplexing registers, used in interrupts and system calls but with different meanings */UINT32 reserved1; /**< Multiplexing registers, used in interrupts and system calls but with different meanings */UINT32 USP; /**< User mode sp register */UINT32 ULR; /**< User mode lr register */UINT32 R0;UINT32 R1;UINT32 R2;UINT32 R3;UINT32 R12;UINT32 LR;UINT32 PC;UINT32 regCPSR;
} TaskContext;
结构体中包括ARM的R0~R12通用寄存器,PC、LR、CPSR以及32个64位浮点寄存器,还有FPSCR和FPEXC寄存器,这些都是ARM硬件上结构,还有reserved1、reserved2,这两个成员是保留的,USP和ULR是任务调度时非特权模式下要用到,这是后话。
根据OsTaskStackInit函数的代码,在任务栈初始化时主要初始化了PC、LR、R0、CPSR、32个64位浮点寄存器、FPSR和FPEXC这几个任务上下文结构体成员,这是加载任务并成功运行所必须的,所以必须初始化。
一个任务被创建并初始化后就可以参加调度了,创建任务和任务调度部分有机会的话会继续写,而任务栈的初始化现在就到此为止了,再写就不礼貌了。。
Liteos-A任务调度之OsTaskStackInit函数相关推荐
- Liteos-A任务调度之任务上下文切换
任务调度要调度的就是任务所拥有的CPU资源,其中最主要的就是寄存器,包括通用寄存器和状态寄存器,操作系统刚开始启动时任务调度的代码主要是加载第一个任务,然后随着操作系统的运行需求开始运行不同的任务,即 ...
- LiteOS内核源码分析:消息队列Queue
本文分享自华为云社区<LiteOS内核源码分析系列十 消息队列Queue>,原文作者:zhushy . 队列(Queue)是一种常用于任务间通信的数据结构.任务能够从队列里面读取消息,当队 ...
- LiteOS内核源码分析:任务栈信息
本文分享自华为云社区<LiteOS内核源码分析系列六 -任务及调度(2)-任务LOS_Task>,原文作者:zhushy . 我们介绍下LiteOS任务栈的基础概念.LiteOS任务栈是高 ...
- LiteOS内核开发(一)
之前学习LiteOS内核的基本结构和应用的时候,我们通过一张LiteOS内核系统的结构图了解到其基本结构. 其中,Huawei LiteOS基础内核包括不可裁剪的极小内核和可裁剪的其他模块.极小内核包 ...
- 从零开始的ESP8266探索(11)-定时任务调度器Ticker使用演示
文章目录 目的 使用演示 基本使用1 基本使用2 动态设置和参数传递 停止和重启任务 注意事项 总结 目的 Arduino for esp8266属于无操作系统环境,对于开发多任务的复杂应用还是比较麻 ...
- 【编写自己的RTOS】搞定任务调度
回顾: Q3:关于RTOS编写,要解决哪些核心问题 A3: a. 系统心跳:SysTick初始化 b. SysTick和PendSV的优先级设置 c. 任务控制块TCB结构与堆栈初始化 d. ...
- LiteOS通信模组教程04-深度剖析LiteOS的AT框架
1. AT客户端框架 在之前的三篇教程中,我们都是直接使用串口助手发送AT指令与模组通信,本篇教程就来探索一下如何使用 MCU 中的串口模组交互. 什么是AT客户端 在使用AT指令的时候,直接发送AT ...
- linux双系统怎么进tty,HI3556V200 Linux+Liteos双系统学习(4)----双系统通信 IPCM/virt_tty/sharefs...
文章目录 1 IPCM 1.1 IPCMSG 1.1.1 Linux端示例代码 1.1.2 Liteos端示例代码 1.2 DATAFIFO 1.2.1 Linux端示例代码 1.2.2 Liteos ...
- OS_Sched 函数
//任务调度 //uCOS-II总是运行进入就绪态任务中优先级最高的那一个.确定哪个任务优先级最高,下面该哪个任务运行了的工作是 //由调度器(Scheduler)完成的.任务级的调度是由函数OSSc ...
最新文章
- spring-boot项目优雅的http客户端工具,太香了!
- Tomcat-公布WEB应用
- 事务管理最佳实践全面解析
- 【MSTR产品】获取当前登陆用户的login_id
- Bootstrap学习笔记01
- 5shift shell
- python中代理模式分为几种_通俗 Python 设计模式——代理模式
- 3.2 Zabbix企业级分布式监控系统 --- zabbix-agent, zabbix-get 安装
- java 代码段 执行超时 抛异常_深入理解Java线程状态
- oracle数据库创建检查点,Oracle数据库通过检查点和RBA信息确定恢复范围
- H264码流中SPS PPS详解
- 签到活动 测试要点分析
- 图灵革命如何颠覆我们对世界的认知?
- 金融危机对中国IT产业四大深层影响
- LeetCode 罗马数字
- 计算机无法更改开机密码,不能修改win7电脑开机密码是怎么回事
- JS手写面试题 --- 数组扁平化
- 我爱赚钱吧:你知道自己建网站可以赚钱吗?①
- 工作展望简短_工作展望简短_时间2017工作展望
- 开源棋牌框架creator+skynet:牛牛+五子棋