启动之OS_CPU_C

来源:互联网 发布:四六级模拟题软件 编辑:程序博客网 时间:2024/06/05 15:09

任务堆栈结构的初始化
在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                      */
}

原创粉丝点击