摘 要:介紹μC/OS-Ⅱ操作系統(tǒng)的特點(diǎn)、內(nèi)核結(jié)構(gòu)和工作原理,并通過對(duì)NXP公司LPC2378及ARM7TDMI-S內(nèi)核體系結(jié)構(gòu)及內(nèi)部寄存器工作原理的分析,討論了μC/OS-Ⅱ移植過程中的重難點(diǎn)問題及解決方法,重點(diǎn)闡述移植代碼中堆棧初始化、任務(wù)切換、時(shí)鐘中斷服務(wù)程序的編寫過程,并對(duì)調(diào)試中出現(xiàn)的程序跑飛和堆棧空間不夠的問題進(jìn)行了解決和修改,最后通過設(shè)計(jì)多任務(wù)應(yīng)用程序證明了該移植是成功的。
關(guān)鍵詞: μC/OS-Ⅱ; LPC2378; 實(shí)時(shí)操作系統(tǒng); 移植
中圖分類號(hào):TP316.2 文獻(xiàn)標(biāo)識(shí)碼:B
文章編號(hào):1004-373X(2010)12-0033-04
Transplant and Application of the Embedded Real-time OS μC/OS-Ⅱ on LPC2378
SUN Ji-ru, GUO Min, ZHANG Yu-xiang, WANG Ming-li
(Physics and Engineering Department, Zhengzhou University, Zhengzhou 450001, China)
Abstract:The characteristics, kernel structure and the operating principle of the real-time embedded operating system μC/OS-Ⅱ are introduced. Besides, the key problem and the resolution appeared in the μC/OS-Ⅱ transplant are discussed through analyzing the ARM7TDMI-S and the kernel of LPC2378 produced by NXP Company. The process of preparing of Stack initialization, task switch and the clock interrupt service routine are expatiated. The problems of running fly and less of stack space during the debugging program are resolved, the success of transplant is proved by designing the multi-task application on the LPC2378.
Keywords: μC/OS-Ⅱ; LPC2378; real-time operating system; transplant
0 引 言
目前,市場(chǎng)以及院校科研用嵌入式系統(tǒng)產(chǎn)品,如Vxworks,Linux和Windows CE等都已經(jīng)相當(dāng)成熟,提供了有力的開發(fā)和調(diào)試工具,但有些開發(fā)成本昂貴,周期較長(zhǎng),而μC/OS-Ⅱ是一種多任務(wù)實(shí)時(shí)源代碼的公開操作系統(tǒng),內(nèi)核精簡(jiǎn),移植性較強(qiáng),非常適合用于一些小型控制和實(shí)驗(yàn)系統(tǒng)的開發(fā)。
1 操作系統(tǒng)及CPU介紹
μC/OS-Ⅱ是基于優(yōu)先級(jí)的占先式實(shí)時(shí)多任務(wù)操作系統(tǒng),包含有任務(wù)管理、時(shí)間管理、任務(wù)間同步通信(信號(hào)量,郵箱,消息隊(duì)列)和內(nèi)存管理等功能。絕大部分代碼用C語(yǔ)言寫成,極少部分與處理器密切相關(guān)的代碼用匯編語(yǔ)言編寫,便于移植。作為一個(gè)源代碼公開的實(shí)時(shí)操作系統(tǒng),最多可以管理64個(gè)任務(wù),并支持信號(hào)量、郵箱、消息隊(duì)列等多種進(jìn)程間的通信機(jī)制,同時(shí)用戶可以根據(jù)需求對(duì)內(nèi)核中的功能模塊進(jìn)行裁剪[1-3] 。
LPC2378是一款基于ARM7TDMI-S內(nèi)核的嵌入式精簡(jiǎn)指令集微控制器,包含了1個(gè)支持仿真的ARM7TDMI-S CPU,適用于為了各種目的而需要進(jìn)行串行通信的應(yīng)用。該體系機(jī)構(gòu)支持用戶、軟中斷、中斷、管理、中止、未定義、系統(tǒng)等7種處理器模式,ARM7 TDMI-S處理器內(nèi)部有31個(gè)通用32位寄存器,6個(gè)狀態(tài)寄存器。LPC2378包含了1個(gè)10/100 Ethernet MAC,USB 2.0全速接口,4個(gè)UART接口,2路CAN通道,1個(gè)SPI接口,2個(gè)同步串行端口(SSP),3個(gè)I2C接口,1個(gè)I2S接口和MiniBus(MiniBus僅用于LPC2378,它是8位數(shù)據(jù)/16位地址并行的總線)。下面以μC/OS-Ⅱ在工業(yè)級(jí)芯片LPC2378上的移植為例,通過分析操作系統(tǒng)內(nèi)核來(lái)介紹μC/OS-Ⅱ操作系統(tǒng)移植的一般方法和過程及相關(guān)問題的解決[4-5] 。
2 μC/OS-Ⅱ內(nèi)核結(jié)構(gòu)及工作原理
2.1 內(nèi)核基本結(jié)構(gòu)
圖1是接近μC/OS-Ⅱ的簡(jiǎn)單內(nèi)核體系結(jié)構(gòu)圖,內(nèi)核保留給上層應(yīng)用的接口有3個(gè),分別是軟保護(hù)、ITC和DSR[6] 。由于μC/OS-Ⅱ操作系統(tǒng)內(nèi)核是可剝奪型實(shí)時(shí)多任務(wù)內(nèi)核,因此最高優(yōu)先級(jí)的任務(wù)一旦就緒,總能得到CPU的使用權(quán)。如果是中斷服務(wù)子程序使一個(gè)高優(yōu)先級(jí)的任務(wù)進(jìn)入就緒態(tài),則中斷完成時(shí),中斷了的任務(wù)被掛起,優(yōu)先級(jí)高的任務(wù)開始運(yùn)行。
2.2 μC/OS-Ⅱ內(nèi)核基本工作原理
多任務(wù)系統(tǒng)中,操作系統(tǒng)內(nèi)核負(fù)責(zé)管理各個(gè)任務(wù),或者說(shuō)為每個(gè)任務(wù)分配CPU,并且負(fù)責(zé)各任務(wù)之間的通信和協(xié)同,任務(wù)切換是內(nèi)核提供的基本服務(wù)。μC/OS-Ⅱ多任務(wù)操作系統(tǒng)的基本工作原理[7] 如下:
(1) 在使用μC/OS-Ⅱ的所有服務(wù)之前,必須調(diào)用初始化函數(shù)OSInit(),初始化所有的變量和數(shù)據(jù)結(jié)構(gòu),同時(shí)創(chuàng)建空閑任務(wù)OSTaskIdle(),并賦予最低的優(yōu)先級(jí)別和永遠(yuǎn)的就緒態(tài),同時(shí)完成任務(wù)控制塊(TCB)的初始化、TCB優(yōu)先級(jí)表的初始化、TCB鏈表的初始化和事件控制塊(ECB)鏈表的初始化。
(2) 調(diào)用OSTaskCreate()或OSTaskCreateExt()創(chuàng)建至少一個(gè)新任務(wù),并給任務(wù)賦予一定的優(yōu)先級(jí),而且它們有各自的一套CPU寄存器和自己的棧空間。
(3) 調(diào)用OSSTART()函數(shù),通過從任務(wù)就緒表中找出用戶建立的優(yōu)先級(jí)別最高的任務(wù)控制塊,然后開始多任務(wù)調(diào)度。
圖1 簡(jiǎn)單內(nèi)核體系結(jié)構(gòu)
3μC/OS-Ⅱ在LPC2378上的移植過程及相關(guān)問題分析 [8-10]
現(xiàn)以LPC2378微控制器上的移植為例,分析μC/OS-Ⅱ操作系統(tǒng)移植的一般方法,所采用的開發(fā)環(huán)境為ARM公司的集成開發(fā)環(huán)境ADS 1.2。
3.1 移植代碼
(1) μC/OS-Ⅱ與CPU類型無(wú)關(guān)的代碼有μC/OS-Ⅱ.H,μC/OS-Ⅱ.C,OS CORE.C,OS TASK.C,OS TIME.C,OS SEM.C,OS MBOX.C,OS MUTEX.C,OS FLAG.C,也就是說(shuō)這些文件可以不用修改就直接添加。
(2) μC/OS-Ⅱ與CPU類型有關(guān)的代碼有OS CPU.H,OS CPU A.ASM,OS CPU C.C,也就是說(shuō)用戶需要根據(jù)所選CPU的類型將這些函數(shù)進(jìn)行修改后才能添加入內(nèi)核。
3.2 OS CPU.H文件的定義與修改
OS CPU.H文件定義了與編譯器及CPU相關(guān)的數(shù)據(jù)類型、堆棧的寬度和增長(zhǎng)方式以及開關(guān)中斷的宏定義。由于微處理器和微控制器所支持的堆棧增長(zhǎng)方式不同,這里需要根據(jù)所選芯片LPC2378支持的類型對(duì)宏OS STK GRWOTH進(jìn)行定義,由于ARM7 TDMI-S內(nèi)核堆棧支持從上往下的生長(zhǎng)方式,所以應(yīng)做如下定義:
#define OS STK GROWTH 1 //堆棧是從上往下長(zhǎng)的
OS CPU.H文件中另外3個(gè)宏OS CRITICAL METHOD,OS ENTER CRITICAL(),OS EXIT CRITICAL()用于定義開關(guān)中斷的方式及開關(guān)中斷的實(shí)現(xiàn)。通過調(diào)用開關(guān)中斷2個(gè)宏來(lái)保護(hù)臨界代碼如下:
#define OS CRITICAL METHOD 3
OS CPU SR os cpu sr;
/*選擇開、關(guān)中斷的方式 ,OS CPU SR 是μC/OS-Ⅱ的一種數(shù)據(jù)類型,在與處理器有關(guān)的頭文件OS CPU.H中定義,選用這種方式,開關(guān)中斷函數(shù)就認(rèn)為有了OS CPU SR這個(gè)局部變量*/
3.3OS CPU C.C文件中主要函數(shù)的定義及編寫
OS CPU C.C中要求用戶編寫10個(gè)簡(jiǎn)單的函數(shù):OSTaskStkInit(),OSTaskCreateHook(),OSTaskDel-Hook(),OSTaskSwHook(),OSTaskIdleHook(),OSTaskStatHook(),OSTi meTickHook(),OSInitHookBegin(),OSInitHookEnd(),OSTCBInitInitHook()。結(jié)合要移植的CPU內(nèi)核的硬件和寄存器特性,簡(jiǎn)要對(duì)任務(wù)堆棧初始化函數(shù)進(jìn)行分析和創(chuàng)建:
OS STK *OSTaskStkInit (void (*task)(void *p arg),void *p arg,OS STK *ptos,INT16U opt)
{
OS STK *stk;
INT32U task addr;
Opt=opt; //opt 沒有被使用,這里避免警告
Stk=ptos; //裝入堆棧指針
task addr=(INT32U)task ~1;
*(stk)=(INT32U)task addr;
…
if((INT32U)task 0x01)
{ *(--stk)=(INT32U)ARM SVC MODE THUMB; //CPSR同時(shí)使能IRQ和FIQ中斷,Thumb指令集模式}
else { *(--stk)=(INT32U)ARM SVC MODE ARM; //同時(shí)使能IRQ和FIQ中斷,ARM指令集模式
}
return (stk);}
其他9個(gè)函數(shù)必須聲明,但并不一定包含任務(wù)代碼。
3.4 μC/OS-Ⅱ的移植
μC/OS-Ⅱ的移植,還要求編寫4個(gè)簡(jiǎn)單的匯編語(yǔ)言函數(shù);即OSStartHighRdy(),OSIntCtxSw(),OSTickISR(),OSCtxSw()。
3.4.1 函數(shù)OSStart()調(diào)用OSStartHighRdy()
函數(shù)OSStart()用于調(diào)用OSStartHighRdy(),以使使就緒態(tài)任務(wù)中優(yōu)先級(jí)最高的任務(wù)開始運(yùn)行:
OSStartHighRdy
MSR CPSR c,#(OS CPU ARM CONTROL INT DIS|OS CPU ARM MODE SVC) ;轉(zhuǎn)換到SVC模式
LDR R0,OS TaskSwHook ;調(diào)用用戶定義的OSTaskSwHook()
MOV LR,PC
BXR0
LDRR0,?OS Running ; OSRunning = TRUE;
MOV R1,#1
STRBR1,[R0]
LDRR0,OS TCBHighRdy ;得到最高優(yōu)先級(jí)任務(wù)的任務(wù)控制塊地址
LDR R0,[R0] ;得到堆棧指針
LDR SP,[R0] ;跳轉(zhuǎn)到新堆棧
LDR R0,[SP],#4
MSR SPSR cxsf,R0
LDMFD SP!,{R0-R12,LR,PC}^
3.4.2 時(shí)鐘節(jié)拍中斷服務(wù)程序
μC/OS-Ⅱ要求用戶提供一個(gè)周期性的時(shí)鐘源,以實(shí)現(xiàn)時(shí)間延遲和超時(shí)確認(rèn)功能,時(shí)鐘節(jié)拍每秒發(fā)生10~100次。必須在開始多任務(wù)后,啟動(dòng)時(shí)鐘節(jié)拍中斷,但由于OSStart()函數(shù)不會(huì)返回,用戶無(wú)法實(shí)現(xiàn)這一操作,所以可以在OSStart()運(yùn)行之后,μC/OS啟動(dòng)的第1個(gè)任務(wù)中初始化節(jié)拍中斷。基于LPC2378移植下OSTickISR()的簡(jiǎn)易代碼編寫如下:
Void OSTickISR(void)
{
asm{d
ppage; //將每個(gè)任務(wù)的存儲(chǔ)頁(yè)面寄存器推人堆棧
psha
}
OSIntEnter(); //μC/OS-Ⅱ進(jìn)人時(shí)鐘節(jié)拍中斷服務(wù)子程序
OS SAVE SP();
CRGFLG=0Xef; //清中斷標(biāo)志
OSTimeTick(); //給每個(gè)用戶任務(wù)控制塊OS TCB中的時(shí)間延時(shí)項(xiàng)
OSTCBDly; //減1
OSIntExit(); //通知μC/OS-Ⅱ時(shí)鐘節(jié)拍服務(wù)子程序結(jié)束
asm {pula
st
ppage; //恢復(fù)頁(yè)面寄存器
nop
rti; //中斷返回
}
}
當(dāng)時(shí)鐘節(jié)拍中斷發(fā)生時(shí),CPU會(huì)自動(dòng)把CPU寄存器推人堆棧,但并不包括存儲(chǔ)頁(yè)面寄存器PPAGE,如果單片機(jī)系統(tǒng)的尋址范圍超過64 KB,則需要通過給PPAGE賦值來(lái)區(qū)分不同的16 KB地址,需要把PPAGE也推入堆棧。當(dāng)某任務(wù)的任務(wù)控制塊中時(shí)間延時(shí)項(xiàng)OSTCBDly減到了零,OSTimtick()就進(jìn)入了就緒態(tài)。OSIntExit()會(huì)調(diào)用中斷級(jí)的任務(wù)切換函數(shù)OSIntCtxSw執(zhí)行任務(wù)切換,而不再執(zhí)行后面的指令。如果沒有更高優(yōu)先級(jí)的任務(wù)進(jìn)人就緒態(tài),則CPU會(huì)返回中斷前狀態(tài)。
3.4.3 任務(wù)級(jí)任務(wù)切換
實(shí)際上任務(wù)級(jí)的切換就是通過執(zhí)行軟中斷指令,或者根據(jù)處理器的不同,執(zhí)行TRAP指令來(lái)實(shí)現(xiàn)。中斷服務(wù)子程序、TRAP或者異常處理的向量地址必須指向OSCtxsw(),利用系統(tǒng)在跳轉(zhuǎn)到中斷服務(wù)程序時(shí)會(huì)自動(dòng)把斷點(diǎn)指針壓入堆棧的功能,把斷點(diǎn)指針存入堆棧,而利用中斷返回指令I(lǐng)RET,能把斷點(diǎn)指針推入CPU的PC寄存器功能,恢復(fù)待運(yùn)行任務(wù)的斷點(diǎn),這樣就可以實(shí)現(xiàn)斷點(diǎn)的保存和恢復(fù)。
OSIntCtxSw
STMFD SP!,{LR} ;保存返回地址
STMFD SP!,{LR}
STMFD SP!,{R0-R12} ;當(dāng)前寄存器入棧
MRS R0,CPSR ; 當(dāng)前CPRS入棧
TST LR,#1 ;判斷指令集模式是否為Thumb
ORRNE R0,R0,#OS CPU ARM CONTROL THUMB;
STMFD SP!,{R0}
LDR R0,?OS TCBCur ;OSTCBCur->OSTCBStkPtr = SP;
LDR R1,[R0]
STR SP,[R1]
LDR R0,?OS TaskSwHook ;OSTaskSwHook();
MOV LR,PC
BX R0
LDR R0,?OS PrioCur ;OSPrioCur = OSPrioHighRdy;
LDR R1,?OS PrioHighRdy
LDRB R2,[R1]
STRB R2,[R0]
LDR R0,?OS TCBCur ;OSTCBCur = OSTCBHighRdy;
LDR R1,?OS TCBHighRdy
LDR R2,[R1]
STR R2,[R0]
LDR SP,[R2]
LDMFD SP!,{R0}
MSR SPSR cxsf,R0
LDMFD SP!,{R0-R12,LR,PC}^
3.4.4 中斷級(jí)任務(wù)切換
OSIntExit()通過調(diào)用OSIntSw(),在ISR中執(zhí)行任務(wù)切換函數(shù)。因?yàn)镺SIntCtxSw()是在ISR中被調(diào)用的,所以假定所有的處理器寄存器都被正確地保存到了被中斷任務(wù)的堆棧中。OSIntSw()函數(shù)的絕大多數(shù)代碼與OSCtxSw()函數(shù)是一樣的,區(qū)別只是:因?yàn)镮SR已經(jīng)保存了CPU的寄存器,而不再需要在OSIntSw()函數(shù)中保存CPU的寄存器。在進(jìn)行操作系統(tǒng)移植時(shí),該段程序的代碼如下:
OSIntCtxSw
LDR R0,?OS TaskSwHook
MOV LR,PC
BX R0
LDR R0,?OS PrioCur ;OSPrioCur=OSPrioHighRdy;
LDR R1,?OS PrioHighRdy
LDRB R2,[R1]
STRB R2,[R0]
LDR R0,?OS TCBCur ;OSTCBCur=OSTCBHighRdy;
LDR R1,?OS TCBHighRdy
LDR R2,[R1]
STR R2,[R0]
LDR SP,[R2]
LDMFD SP!,{R0}
LDMFD SP!,{R0-R12,LR,PC}^
3.5 移植中的問題
ARM處理器的軟件調(diào)試通過JTAG口直接在系統(tǒng)的外部SRAM運(yùn)行,因此在程序調(diào)試之前,ARM處理器的開發(fā)環(huán)境軟件首先調(diào)用初始化文件(*.ini),用戶可以根據(jù)自己系統(tǒng)的外部存儲(chǔ)器和設(shè)備的地址來(lái)修改文件。如果該文件有誤,開發(fā)環(huán)境軟件將無(wú)法通過JTAG與處理器通信。系統(tǒng)調(diào)試過程中,經(jīng)常會(huì)出現(xiàn)程序跑飛的現(xiàn)象,經(jīng)過測(cè)試與分析,主要有4個(gè)方面原因:
(1) 中斷處理程序的中斷矢量地址沒有正確賦值,從而導(dǎo)致發(fā)生中斷后CPU無(wú)法運(yùn)行到中斷處理程序位置;
(2) 在OSCtxSw和OSIntCtxSw中的任務(wù)切換語(yǔ)句后加人幾條NOP空語(yǔ)句,確保任務(wù)切換的相應(yīng)指令執(zhí)行結(jié)束,如果在這些位置沒有加相應(yīng)的空操作指令,也會(huì)導(dǎo)致程序跑飛;
(3) 由于堆棧的空間分配不夠,以及沒有給CPU的各個(gè)工作模式分配空間,導(dǎo)致任務(wù)切換時(shí),堆棧溢出;
(4)μC/OS-Ⅱ要求用戶提供一個(gè)時(shí)鐘資源來(lái)實(shí)現(xiàn)時(shí)鐘節(jié)拍,時(shí)鐘節(jié)拍應(yīng)該每秒鐘發(fā)生10~100次,用戶必須在開始多任務(wù)調(diào)度后(即調(diào)用OSStart后)允許時(shí)鐘節(jié)拍中斷。通常的錯(cuò)誤是在調(diào)用OSInit()和OSStart()之間允許時(shí)鐘節(jié)拍中斷,同時(shí)用戶不要單純地追求實(shí)時(shí)性,而將系統(tǒng)的時(shí)鐘節(jié)拍頻率增加太高。以上幾個(gè)方面的問題解決后,系統(tǒng)的工作非常穩(wěn)定。
4 系統(tǒng)測(cè)試
移植完成后的系統(tǒng)包括4個(gè)部分:自啟動(dòng)程序、μC/OS-Ⅱ系統(tǒng)文件、移植代碼、應(yīng)用程序。開發(fā)環(huán)境是ARM公司提供的ADS1.2 (ARM Developer Suite)。該系統(tǒng)創(chuàng)建了以下3個(gè)任務(wù)來(lái)驗(yàn)證μC/OS-Ⅱ的移植成功:
OSTaskCreate(Taskl,(void*),0,(void*)Stackl[TASK STK SIZE一1],1);
OSTaskCreate(Task2,(void*),1,(void*)Stack2[TASK STK SIZE一1],2);
OSTaskCreate(Task3,(void*),2,(void*)Stack3[TASK STK SIZE一1],3);
在為自己的微處理器做完μC/OS-Ⅱ的移植后,首先建立3個(gè)任務(wù),之后不加任何其他應(yīng)用代碼來(lái)測(cè)試移植好的μC/OS-Ⅱ,也就是說(shuō)應(yīng)該先測(cè)試內(nèi)核自身的運(yùn)行狀況。這樣做有2個(gè)原因:不希望將事情復(fù)雜化;如果有些地方?jīng)]有工作可以明白是移植本身的問題,而不是應(yīng)用代碼產(chǎn)生的問題。經(jīng)過測(cè)試和修改,無(wú)相關(guān)錯(cuò)誤產(chǎn)生,說(shuō)明移植成功。
5 結(jié) 語(yǔ)
μC/OS-Ⅱ具有很強(qiáng)的移植性,具有多任務(wù)實(shí)時(shí)可剝奪型內(nèi)核,而且代碼量較小,源代碼開放,可被廣泛移植到8位、16位等許多微處理器上。國(guó)外諸如APC,ROTEK等企業(yè)都在產(chǎn)品中成功地使用了μC/OS-Ⅱ內(nèi)核,不僅開發(fā)成本低,而且系統(tǒng)精簡(jiǎn),因此將μC/OS-Ⅱ移植到LPC2378這種工業(yè)級(jí)的芯片上,具有相當(dāng)?shù)纳虡I(yè)價(jià)值。
參考文獻(xiàn)
[1][ 美]JEAN J LABROSSE.嵌入式實(shí)時(shí)操作系統(tǒng)μC/OS-Ⅱ[ M] .卲貝貝,譯.2版.北京:北京航空航天大學(xué)出版社,2003.
[2]姚旭影.μC/OS-Ⅱ操作系統(tǒng)在AVR單片機(jī)上的移植[ J] .現(xiàn)代電子技術(shù),2006,29(12):53-55.
[3]趙偉國(guó),李文軍,梁國(guó)偉.實(shí)時(shí)嵌入式操作系統(tǒng)μC/OS-Ⅱ在AT91上的移植[ J] .中國(guó)計(jì)量學(xué)院學(xué)報(bào),2005,16(2):137-139.
[4]周立功.深入淺出ARM7-LPC2300[ M] .廣州:廣州致遠(yuǎn)電子有限公司,2004.
[5]周立功.ARM微控制器基礎(chǔ)與實(shí)戰(zhàn)[ M] .北京:北京航空航天大學(xué)出版社,2003.
[6]黃燕平.μC/OS ARM移植要點(diǎn)詳解[ M] .北京:北京航空航天大學(xué)出版社,2005.
[7]任哲.嵌入式實(shí)時(shí)操作系統(tǒng)μC/OS-Ⅱ原理及應(yīng)用[ M] .北京:北京航空航天大學(xué)出版社,2005.
[8]陳是知.μC/OS-Ⅱ內(nèi)核分析、移植與驅(qū)動(dòng)程序開發(fā)[ M] .北京:人民郵電出版社,2007.
[9]沈春,許峰.μC/OS-Ⅱ在OSP2407上若干移植問題的研究[ J] .中國(guó)水運(yùn),2007(5):175-176.
[10]寇鵬.實(shí)時(shí)操作系統(tǒng)μC/OS-Ⅱ在MCF5307處理器上的移植[ J] .現(xiàn)代電子技術(shù),2007,30(6):70-72.