?? os_cpu_c.c
字號:
/*
*********************************************************************************************************
* 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()的原因是相同的??梢栽诘?5章看到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()調用
一次??梢杂肙STaskStatHook()擴展統計任務的功能。例如,可以跟蹤并顯示每個任務的執行時間,每個任務所用的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 + -