之前看过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函数相关推荐

  1. Liteos-A任务调度之任务上下文切换

    任务调度要调度的就是任务所拥有的CPU资源,其中最主要的就是寄存器,包括通用寄存器和状态寄存器,操作系统刚开始启动时任务调度的代码主要是加载第一个任务,然后随着操作系统的运行需求开始运行不同的任务,即 ...

  2. LiteOS内核源码分析:消息队列Queue

    本文分享自华为云社区<LiteOS内核源码分析系列十 消息队列Queue>,原文作者:zhushy . 队列(Queue)是一种常用于任务间通信的数据结构.任务能够从队列里面读取消息,当队 ...

  3. LiteOS内核源码分析:任务栈信息

    本文分享自华为云社区<LiteOS内核源码分析系列六 -任务及调度(2)-任务LOS_Task>,原文作者:zhushy . 我们介绍下LiteOS任务栈的基础概念.LiteOS任务栈是高 ...

  4. LiteOS内核开发(一)

    之前学习LiteOS内核的基本结构和应用的时候,我们通过一张LiteOS内核系统的结构图了解到其基本结构. 其中,Huawei LiteOS基础内核包括不可裁剪的极小内核和可裁剪的其他模块.极小内核包 ...

  5. 从零开始的ESP8266探索(11)-定时任务调度器Ticker使用演示

    文章目录 目的 使用演示 基本使用1 基本使用2 动态设置和参数传递 停止和重启任务 注意事项 总结 目的 Arduino for esp8266属于无操作系统环境,对于开发多任务的复杂应用还是比较麻 ...

  6. 【编写自己的RTOS】搞定任务调度

    回顾: Q3:关于RTOS编写,要解决哪些核心问题 A3:  a. 系统心跳:SysTick初始化  b. SysTick和PendSV的优先级设置  c. 任务控制块TCB结构与堆栈初始化  d. ...

  7. LiteOS通信模组教程04-深度剖析LiteOS的AT框架

    1. AT客户端框架 在之前的三篇教程中,我们都是直接使用串口助手发送AT指令与模组通信,本篇教程就来探索一下如何使用 MCU 中的串口模组交互. 什么是AT客户端 在使用AT指令的时候,直接发送AT ...

  8. 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 ...

  9. OS_Sched 函数

    //任务调度 //uCOS-II总是运行进入就绪态任务中优先级最高的那一个.确定哪个任务优先级最高,下面该哪个任务运行了的工作是 //由调度器(Scheduler)完成的.任务级的调度是由函数OSSc ...

最新文章

  1. spring-boot项目优雅的http客户端工具,太香了!
  2. Tomcat-公布WEB应用
  3. 事务管理最佳实践全面解析
  4. 【MSTR产品】获取当前登陆用户的login_id
  5. Bootstrap学习笔记01
  6. 5shift shell
  7. python中代理模式分为几种_通俗 Python 设计模式——代理模式
  8. 3.2 Zabbix企业级分布式监控系统 --- zabbix-agent, zabbix-get 安装
  9. java 代码段 执行超时 抛异常_深入理解Java线程状态
  10. oracle数据库创建检查点,Oracle数据库通过检查点和RBA信息确定恢复范围
  11. H264码流中SPS PPS详解
  12. 签到活动 测试要点分析
  13. 图灵革命如何颠覆我们对世界的认知?
  14. 金融危机对中国IT产业四大深层影响
  15. LeetCode 罗马数字
  16. 计算机无法更改开机密码,不能修改win7电脑开机密码是怎么回事
  17. JS手写面试题 --- 数组扁平化
  18. 我爱赚钱吧:你知道自己建网站可以赚钱吗?①
  19. 工作展望简短_工作展望简短_时间2017工作展望
  20. 开源棋牌框架creator+skynet:牛牛+五子棋

热门文章

  1. 多种温湿度传感器外壳的简单介绍
  2. [二十六]JavaIO之再回首恍然(如梦? 大悟?)
  3. 区块链(二、智能合约的开发)
  4. 基于Android的游戏资讯APP设计
  5. ⭐还记得10年前的微信小游戏【打飞机】吗?C语言实现!
  6. 1 spss基本使用
  7. springboot+jsp基于javaweb房地产销售系统
  8. linux在线聊天报告,linux聊天室报告.doc
  9. 杂念参加完了广东互联网大会的一些感想
  10. taro + taro ui + dva 微信小程序实践