任务堆栈结构的初始化

在uC/OS-II中,任务是一个无限循环,任务之间也不会互相调用,但是uC/OS-II总是执行优先级最高的任务,假定当前有一个更高优先级的任务进入就绪状态,为了保证原来低优先级任务的完整性,uC/OS-II为每个任务建立了任务堆栈,就相当于函数调用时保存返回地址和参数一样,用来保存当前任务的状态,保证任务切换能和函数调用一样正确.只不过函数调用时函数堆栈的操作过程是编译器自动完成的,而任务切换时需要模拟一个和编译器类似的任务堆栈的操作过程.
OS_STK  *OSTaskStkInit (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT16U opt)
{
    INT16U *stk;

opt    = opt;                           /* 'opt' is not used, prevent warning                      */

//堆栈栈顶指针
    stk    = (INT16U *)ptos;                /* Load stack pointer                                      */

//堆栈有高地址往低地址增长,故使用*stk--
//pada参数
//假定pdata会被编译器保存到堆栈中,OSTaskStkInit()就会模仿编译器的这种行为,将pdata保存到堆栈中.
    *stk-- = (INT16U)FP_SEG(pdata);         /* Simulate call to function with argument                 */
    *stk-- = (INT16U)FP_OFF(pdata);

//任务起始地址.理论上,此处应该为任务的返回地址,但在uC/OS-II中,任务函数必须为无限循环结构,不能有返回点         
    *stk-- = (INT16U)FP_SEG(task);
    *stk-- = (INT16U)FP_OFF(task);

/*
PC:是你退出的当时执行程序时program counter,相当于你放下手中的事A去进行另一庄事情B,你得记住之前A事情已经做到什么阶段了,也许B事情你得花上1年2年

PSW:是program status word.同样道理,你开始做B事情的时候必须记住A事情的大致情况status.

堆栈:stack memory就像是一本旧的笔记本,记下A事情的各种问题,以便以后再做A事情,如果又有一个C事情,那B事情也得记到stack memory中

psw指程序状态字(program status word的缩写),是用来控制指令执行顺序并且保留和指示与程序相关的系统状态.
一般说来,程序状态字包含程序基本状态、中断码、中断屏蔽位三部分内容.

基本状态包括:指令地址,条件码,目态管态,等待计算

中断码:保存程序执行时当前发生的中断事件,以便操作系统进行分析处理

中断屏蔽位:用来指出不要响应出现的中断事件,若设置了中断屏蔽位,则即使出现了中断事件也不中止程序的执行,就像没有发生中断事件一样

*/
//中断使能-PSW状态字-0000 0010 0000 0010即
//堆栈中的SW初始化为0x0202,这将使任务启动后允许中断发生;如果设为0x0002,则任务启动后将禁止中断
    *stk-- = (INT16U)0x0202;                /* SW = Interrupts enabled                                 */

//堆栈顶端放置指向任务代码的指针
    *stk-- = (INT16U)FP_SEG(task);          /* Put pointer to task on top of stack                   */
    *stk-- = (INT16U)FP_OFF(task);

//注意寄存器在堆栈中的位置要和运行指令PUSHA,PUSH ES,和PUSH DS和压入堆栈的次序相同
//AX,BX,CX,DX,SP,BP,SI,和DI的次序是和指令PUSHA的压栈次序相同的.如果使用没有PUSHA指令的8086处理器,就要使用多个PUSH指令压入上述寄存器,且顺序要与PUSHA相同
//AX……的值在任务运行前无所谓的,因为在任务运行后在这些寄存器会有新的需要的值,写0xAAAA……是为了堆栈的这个位置是AX……,其实用其他的值也行
    *stk-- = (INT16U)0xAAAA;                /* AX = 0xAAAA                                             */
    *stk-- = (INT16U)0xCCCC;               /* CX = 0xCCCC                                            */
    *stk-- = (INT16U)0xDDDD;               /* DX = 0xDDDD                                            */
    *stk-- = (INT16U)0xBBBB;                /* BX = 0xBBBB                                             */
    *stk-- = (INT16U)0x0000;                 /* SP = 0x0000                                               */
    *stk-- = (INT16U)0x1111;                 /* BP = 0x1111                                               */
    *stk-- = (INT16U)0x2222;                 /* SI = 0x2222                                                */
    *stk-- = (INT16U)0x3333;                 /* DI = 0x3333                                                */
    *stk-- = (INT16U)0x4444;                 /* ES = 0x4444                                               */
    *stk   = _DS;                           /* DS = Current value of DS                                     */
    return ((OS_STK *)stk);
}


//浮点仿真任务栈初始化函数 OSTaskStkInit_FPE_x86(),其中将分段寻址的地址转换为线性地址
void  OSTaskStkInit_FPE_x86 (OS_STK **pptos, OS_STK **ppbos, INT32U *psize)
{
    INT32U   lin_tos;                                 /* 'Linear' version of top-of-stack    address   */
    INT32U   lin_bos;                                 /* 'Linear' version of bottom-of-stack address   */
    INT16U   seg;
    INT16U   off;
    INT32U   bytes;

seg      = FP_SEG(*pptos);                        /* Decompose top-of-stack pointer into seg:off   */
    off      = FP_OFF(*pptos);
    lin_tos  = ((INT32U)seg << 4) + (INT32U)off;      /* Convert seg:off to linear address             */
    bytes    = *psize * sizeof(OS_STK);               /* Determine how many bytes for the stack        */
    lin_bos  = (lin_tos - bytes + 15) & 0xFFFFFFF0L;  /* Ensure paragraph alignment for BOS            */
    
    seg      = (INT16U)(lin_bos >> 4);                /* Get new 'normalized' segment                  */
    *ppbos   = (OS_STK *)MK_FP(seg, 0x0000);          /* Create 'normalized' BOS pointer               */
    memcpy(*ppbos, MK_FP(_SS, 0), 384);               /* Copy FP emulation memory to task's stack      */
    bytes    = bytes - 16;                            /* Loose 16 bytes because of alignment           */
    *pptos   = (OS_STK *)MK_FP(seg, (INT16U)bytes);   /* Determine new top-of-stack                    */
    *ppbos   = (OS_STK *)MK_FP(seg, 384);             /* Determine new bottom-of-stack                 */
    bytes    = bytes - 384;
    *psize   = bytes / sizeof(OS_STK);                /* Determine new stack size                      */
}

启动之OS_CPU_C相关推荐

  1. os_cpu_c.c

      定位到源码的uCOS-II/Ports/ARM-Cortex-M3/Generic/IAR/os_cpu_c.c:   os_cpu_c.c定义了9个钩子(Hook)函数和一个堆栈初始化函数.   ...

  2. 启动ucosii之四OSTaskCreate()

    函数原型来自OS_TASK.C /*********************************************************************************** ...

  3. linux环境下nacos的安装+启动,阿里云服务器安装nacos

    nacos安装+启动(linux环境): 基础:安装java环境 官网下载压缩包:如 nacos-server-1.2.1.tar.gz 放在自定义目录下 # 解压 tar -xvf nacos-se ...

  4. 两步完成项目定时启动,java项目定时启动

    两步完成项目定时设置: 在需要定时启动或运行的方法上面加上注解@Scheduled //当天只跑一次 @Scheduled(cron = "0 40 21 * * ?") 在启动类 ...

  5. Solr部署如何启动

    Solr部署如何启动 Posted on 一月 10, 2013 in: Solr入门|评论关闭 我刚接触solr,我要怎么启动,这是群里的朋友问得比较多的问题, solr最新版本下载地址: http ...

  6. Python 多进程笔记 — 启动进程的方式、守护进程、进程间通信、进程池、进程池之间通信、多进程生产消费模型

    1 面向过程启动多进程 Python 操作进程的类都定义在 multiprocessing 模块,该模块提供了一个 Process 类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另 ...

  7. RabbitMQ 入门系列(4)— RabbitMQ 启动、停止节点和应用程序、用户管理、权限配置

    1. 服务器管理 我们使用 "节点" 来指代 RabbitMQ 实例,当我们谈到 RabbitMQ 节点时指的是 RabbitMQ 应用程序和其所在的 Erlang 节点. 1.1 ...

  8. Redis 笔记(01)— 安装、启动配置、开启远程连接、设置密码、远程连接

    1. Redis 简介 1月份将 <Redis入门指南>过了一遍,现将 Redis 五大类型的常用命令做一总结,留着后续备用. Redis 是 RemoteDictionary Serve ...

  9. Docker 入门系列(3)- Docker 容器(创建、启动、终止、进入、删除、导入、导出容器、容器和镜像转化)

    Docker 容器 简单来说,容器是镜像的一个运行实例.所不同的是,镜像是静态的只读文件,而容器带有运行时需要的可写文件层. 如果认为虚拟机是模拟运行的一整套操作系统(包括内核.应用运行态环境和其他系 ...

最新文章

  1. java成绩管理系统论文总结,JAVA论文成绩管理系统课程设计
  2. TensorFlow搭建简易Wide and Deep 模型
  3. Spring Transaction 使用入门 (转)
  4. Ubuntu8.10安装小记
  5. UVALive2245 POJ1131 HDU1376 ZOJ1086 Octal Fractions【进制】
  6. js焦点图片层叠轮播切换滚动
  7. epoll LT/ET 深度剖析
  8. js 获取浏览器高度、浏览器宽度
  9. CentOS7.9 查询内网ip
  10. 局域网聊天软件源代码(包括语音聊天)
  11. UNLIMITED TABLESPACE权限
  12. 照片太大了怎么改小kb?图片压缩在线处理方法
  13. html button 点击无效,HTML button点击不了
  14. 嵌入式Linux--Lichee Pi Zero原理图分析
  15. 邻接矩阵无向图的介绍
  16. Win10系统安装tensorflow-cpu和gpu版本(按照步骤一次成功)
  17. 面试”作弊“,不看绝对会后悔!
  18. 顶级技术公司的CEO是如何看待AI的?
  19. 发光二极管pcb封装图画法_LM2596电源模块原理图及PCB分享
  20. 小学妹问我【CodeBlocks提示no such file or directory】怎么解决【巧妙篇】

热门文章

  1. 【题解】 [HEOI2016]排序题解 (二分答案,线段树)
  2. DAL,IDAL,BLL,Factory作用
  3. Photoshop脚本指南——Hello World
  4. 关于HTML5中的video和audio元素
  5. [网络安全提高篇] 一〇八.Powershell和PowerSploit脚本渗透详解 (1)
  6. C# 系统应用之通过注册表获取USB使用记录(一)
  7. 【数据结构与算法】之深入解析“分割数组的最大值”的求解思路与算法示例
  8. iOS之深入解析CFRunloop的多线程隐患
  9. Swift之深入解析“属性”的底层原理
  10. iOS之深入解析数组遍历的底层原理和性能分析