⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 os_cpu_c.c

📁 ucos注解版 内容大都是从邵贝贝和网上摘取的 有参考价值
💻 C
📖 第 1 页 / 共 2 页
字号:
/*
*********************************************************************************************************
*                                               uC/OS-II
*                                         The Real-Time Kernel
*
*                         (c) Copyright 1992-2002, Jean J. Labrosse, Weston, FL
*                                          All Rights Reserved
*
*
*                                       80x86/80x88 Specific code
*                                          LARGE MEMORY MODEL
*
*                                          Borland C/C++ V4.51
*
* File         : OS_CPU_C.C
* By           : Jean J. Labrosse
*********************************************************************************************************
*/

#define  OS_CPU_GLOBALS
#include "includes.h"

/*
*********************************************************************************************************
*                                       OS INITIALIZATION HOOK
*                                            (BEGINNING)
*
* Description: This function is called by OSInit() at the beginning of OSInit().进入OSInit()函数后,OSInitHookBegin()就会
立即被调用。添加这个函数的原因在于,想把与OS有关的初始化代码也放在OSInit()函数中。这个函数使得用户可以将自己特定的代码也
放在OSInit()函数中。这样代码会简洁明了。
*
* Arguments  : none
*
* Note(s)    : 1) Interrupts should be disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
void  OSInitHookBegin (void)
{
}
#endif

/*
*********************************************************************************************************
*                                       OS INITIALIZATION HOOK
*                                               (END)
*
* Description: This function is called by OSInit() at the end of OSInit().OSInitHookEnd()与OSInitHookBegin()函数相似,只是
它在OSInit()函数返回之前被调用。添加这个函数的原因与添加OSInitHookBegin()的原因是相同的。可以在第15章看到OSInitHookEnd()的
例子。
*
* Arguments  : none
*
* Note(s)    : 1) Interrupts should be disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0 && OS_VERSION > 203
void  OSInitHookEnd (void)
{
}
#endif

/*$PAGE*/
/*
*********************************************************************************************************
*                                          TASK CREATION HOOK
*
* Description: This function is called when a task is created.每当添加任务时,OS_TCBInit()函数都会调用OSTaskCreateHook()函
数。该函数允许扩展UCOS的功能。当UCOS设置完任务控制块(OS_TCB)初始化的绝大部分工作后,但在任务控制块被链接到相应的任务链中之
前, 以及在该任务就绪运行之前,UCOS会调用OSTaskCreateHook()。该函数被调用时中断是开着的。
当OSTaskCreateHook()被调用时,它会收到指向刚刚建立任务的任务控制块的指针。这样,OSTaskCreateHook()就可访问任务控制块结构所
有的成员了。当用OSTaskCreate()建立任务时,OSTaskCreateHook()的功能是有限的;但当使用OSTaskCreateExt()建立任务时,会得到
OS_TCB中的扩展指针(OSTCBExtPtr)。该指针可用来访问任务的附加数据,如浮点寄存器,MMU寄存器,任务计数器以及调试信息。可以检查
OS_TCBInit(),看都做了哪些工作。
*
* Arguments  : ptcb   is a pointer to the task control block of the task being created.
*
* Note(s)    : 1) Interrupts are disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0                /*只有当OS_CFG.H中的OS_CPU_HOOKS_EN置一时,才会生成OS_CPU_C.C文件中的相应OS???Hook()
函数。这些在本节和以下各节描述的HOOK函数的代码中,OS???Hook()函数是始终需要的,'#define constant OS_CPU_HOOKS_EN'并不意味着
OS???Hook()是否被调用。OS_CPU_HOOKS_EN只是表明OS???Hook()函数是在OS_CPU_C.C文件中(OS_CPU_HOOKS_EN==1),还是在其他文件中
(OS_CPU_HOOKS_EN==0)。这个特点使得用户可以在自己的移植实例中,在OS_CPU_C.C文件之外定义自己的HOOK函数。显然,使用该移植范例
其他源文件的用户,应将OS_CPU_HOOKS_EN设置为0,以防止链接时出现重复定义错误。如果不需要使用HOOK函数这种机制来扩展UCOS的功能
,可以将这些HOOK函数写成空函数。需要再次强调的是,UCOS需要这些HOOK函数(这些函数必须在某处定义)。*/
void  OSTaskCreateHook (OS_TCB *ptcb)
{
    ptcb = ptcb;                       /* Prevent compiler warning                                     */
}
#endif


/*
*********************************************************************************************************
*                                           TASK DELETION HOOK
在任务从就绪态列表或等待列表(若任务在等待某事件发生)中被删除后,OSTaskDel()就会调用OSTaskDelHook()。该函数在将任务从UCOS
的内部有效任务链表中删除之前被调用。当调用OSTaskDelHook()时,它会收到一个指向正在被删除任务的任务控制块的指针,这样它就可
以访问该任务控制块所有的结构成员了。OSTaskDelHook()可以用来检验TCB扩展部分是否已建立了(一个非空的指针),并进行一些清0等操
作。OSTaskDelHook()被调用时,中断是关掉的,所以该函数的代码太长会影响中断响应时间。
*
* Description: This function is called when a task is deleted.
*
* Arguments  : ptcb   is a pointer to the task control block of the task being deleted.
*
* Note(s)    : 1) Interrupts are disabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0 
void  OSTaskDelHook (OS_TCB *ptcb)
{
    ptcb = ptcb;                       /* Prevent compiler warning                                     */
}
#endif

/*
*********************************************************************************************************
*                                             IDLE TASK HOOK
*
* Description: This function is called by the idle task.  This hook has been added to allow you to do  
*              such things as STOP the CPU to conserve power.很多处理器都允许执行相应的指令,将CPU置于低功耗模式。而当接受
到中断信号时,CPU就会退出低功耗模式。OSTaskIdle()函数可调用OSTaskIdleHook()函数,实现CPU的这种低功耗模式。详见邵贝贝UCOSII
*P300
* Arguments  : none
*
* Note(s)    : 1) Interrupts are enabled during this call.
*********************************************************************************************************
*/
#if OS_CPU_HOOKS_EN > 0 && OS_VERSION >= 251
void  OSTaskIdleHook (void)
{
}
#endif

/*
*********************************************************************************************************
*                                           STATISTIC TASK HOOK
*
* Description: This function is called every second by uC/OS-II's statistics task.  This allows your 
*              application to add functionality to the statistics task.OSTaskStatHook函数每秒都会被统计任务OSTaskStat()调用
一次。可以用OSTaskStatHook()扩展统计任务的功能。例如,可以跟踪并显示每个任务的执行时间,每个任务所用的CPU份额以及每个任务
执行的频率等等。
*
* Arguments  : none
*********************************************************************************************************
*/

#if OS_CPU_HOOKS_EN > 0 
void  OSTaskStatHook (void)
{
}
#endif

/*$PAGE*/
/*
*********************************************************************************************************
*                                        INITIALIZE A TASK'S STACK 
UCOS的移植范例要求用户编写10个简单的C函数。唯一必要的是OSTaskStkInit(),其他9个函数必须声明,但并不一定要包含任何代码。
在本移植中就是这么作的。用#define语句定义的常数OS_CPU_HOOKS_EN(见OS_CFG.H)应该置为1.该函数由OSTaskCreate()或
OSTaskCreateExt()调用,用来初始化任务堆栈。将堆栈的结构初始化成看起来好像刚刚发生过中断一样,处理器的所有寄存器被推入堆栈。
当调用OSTaskCreate()或OSTaskCreateExt()建立一个新任务时,须传递的参数是:任务代码的起始地址(task),参数指针(pdata),任务堆栈
顶端的地址(ptos)以及任务的优先级(prio).OSTaskCreateExt()还需要一些其他参数,但与OSTaskStkInit()没有关系。为了合理地初始化
堆栈结构,OSTaskStkInit()只需要以上提到的前三个参数(task,pdata,ptos)。关于opt是调用OSTaskStkInit()函数时须要传递过去的参数
。因为只有OSTaskCreate()函数不支持附加的opt选项,因此,当OSTaskCreate()调用OSTaskStkInit()时,将opt设置为0x0000.
*
* Description: This function is called by either OSTaskCreate() or OSTaskCreateExt() to initialize the
*              stack frame of the task being created.  This function is highly processor specific.
*
* Arguments  : task          is a pointer to the task code
*
*              pdata         is a pointer to a user supplied data area that will be passed to the task
*                            when the task first executes.
*
*              ptos          is a pointer to the top of stack.  It is assumed that 'ptos' points to
*                            a 'free' entry on the task stack.  If OS_STK_GROWTH is set to 1 then 
*                            'ptos' will contain the HIGHEST valid address of the stack.  Similarly, if
*                            OS_STK_GROWTH is set to 0, the 'ptos' will contains the LOWEST valid address
*                            of the stack.
*
*              opt           specifies options that can be used to alter the behavior of OSTaskStkInit().
*                            (see uCOS_II.H for OS_TASK_OPT_???).
*
* Returns    : Always returns the location of the new top-of-stack' once the processor registers have
*              been placed on the stack in the proper order.
*
* Note(s)    : Interrupts are enabled when your task starts executing. You can change this by setting the
*              PSW to 0x0002 instead.  In this case, interrupts would be disabled upon task startup.  The
*              application code would be responsible for enabling interrupts at the beginning of the task
*              code.  You will need to modify OSTaskIdle() and OSTaskStat() so that they enable 
*              interrupts.  Failure to do this will make your system crash!
*********************************************************************************************************
*/

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由于80x86堆栈是16位宽的(以字为单位),OSTaskStkInit()将建
    立并初始化一个局部指针变量。该指针变量指向以字为单位的内存区,同时UCOS要求指针ptos指向空堆栈的入口。*/
    *stk-- = (INT16U)FP_SEG(pdata);         /* Simulate call to function with argument;BorlandC编译器用堆栈而不是寄存器来
    传递参数pdata,此时从参数pdata得到的段地址和偏移量都将按次序保存在堆栈中。
                                             函数名: FP_SEG 
                                             功 能: 获取远地址段值 
                                             用 法: unsigned FP_SEG(void far *farptr); 
                                             函数名: FP_OFF 
                                             功 能: 获取远地址偏移量 
                                             用 法: unsigned FP_OFF(void far *farptr); 

*/
    *stk-- = (INT16U)FP_OFF(pdata);         
    *stk-- = (INT16U)FP_SEG(task);          /*堆栈中紧接着是任务函数的起始地址。理论上,此处应该为任务的返回地址;但在UCOS
    中,任务函数必须为无限循环结构,不能有返回点,所以这里保存的内容实际上无关紧要。*/
    *stk-- = (INT16U)FP_OFF(task);
    *stk-- = (INT16U)0x0202;                /* SW = Interrupts enabled返回地址下面是状态字SW,设置状态字也是为了模拟中断发
    生或的堆栈结构。堆栈中的SW初始化为0x0202,这将使任务启动后中断是开着的;如果设为0x0002,则任务启动后将关中断。UCOS不能
    设置成一些任务启动后中断是开着的,而另一些任务启动后中断是关掉的。也就是说,要么所有的任务启动时中断都是开着的,要么都
    是关掉的。如果确实要突破上述限制,则可以在用OSTaskCreateExt()函数建立任务时,通过参数pdata或者opt向任务传递启动时想要
    的中断状态。然而,目前没有这么作。如果选择任务启动后中断是关掉的,那么每个任务运行时都需要重新开中断。在这种情况下,还
    要修改OSTaskIdle()和OSTaskStat()函数,运行时开中断。如果以上任何一个环节出了问题,系统就会崩溃,所以推荐设置SW为0x0202
    ,在任务启动时开中断。*/
    *stk-- = (INT16U)FP_SEG(task);          /* Put pointer to task   on top of stack                   */
    *stk-- = (INT16U)FP_OFF(task);
    *stk-- = (INT16U)0xAAAA;                /* AX = 0xAAAA堆栈中还须留出各个寄存器的空间。注意寄存器在堆栈中的位置要和运行
    指令PUSHA,PUSH ES以及PUSH DS后压入堆栈的次序相同。AX,BX,CX,DX,SP,BP,SI,DI的次序是与指令PUSHA的压栈次序相同的。
    PUSHA和POPA能用一系列的push和pop指令来代替   
  在8086cpu下   
  pusha等价于   
  push   ax   
  push   bx   

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -