版權(quán)說(shuō)明:本文檔由用戶(hù)提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、目錄1系統(tǒng)定義與需求分析31.1系統(tǒng)定義31.1.1任務(wù)功能描述31.1.2 任務(wù)的優(yōu)先級(jí)分配41.1.3 任務(wù)間同步與通信的規(guī)則41.2 系統(tǒng)配置42詳細(xì)設(shè)計(jì)62.1 系統(tǒng)移植62.1.1移植os_cpu.h62.1.2 移植os_cpu_c.c72.2 最小系統(tǒng)的運(yùn)行調(diào)試102.2.1 保證編譯正確,系統(tǒng)啟動(dòng)正確112.2.2調(diào)試os_enter_critical()112.2.3 調(diào)試osstarthighrdy()122.2.4 調(diào)試osctxsw()122.2.5 調(diào)節(jié)時(shí)鐘節(jié)拍132.2.6 調(diào)試osintctxsw()和ostickisr()143 驅(qū)動(dòng)程序的設(shè)計(jì)與調(diào)試153.1
2、基于c/os-ii的中斷設(shè)計(jì)153.2 基于c/os-ii的設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)153.3 基于c/os-ii的設(shè)備驅(qū)動(dòng)程序測(cè)試164 系統(tǒng)集成與功能測(cè)試174.1 初始化任務(wù)174.2 鍵盤(pán)處理任務(wù)184.3 觸摸屏處理任務(wù)234.4 系統(tǒng)集成測(cè)試355參考文獻(xiàn)381系統(tǒng)定義與需求分析1.1系統(tǒng)定義電子詞典是一個(gè)典型的由外部輸入驅(qū)動(dòng)的開(kāi)環(huán)系統(tǒng),由鍵盤(pán)或觸摸屏輸入信息,處理器根據(jù)輸入的信息在lcd顯示屏上顯示相應(yīng)的內(nèi)容,顯示完成之后系統(tǒng)進(jìn)入空閑狀態(tài)等待下一次輸入。根據(jù)這一處理過(guò)程,講電子詞典應(yīng)用分為3個(gè)主任務(wù)主執(zhí)行任務(wù),鍵盤(pán)任務(wù),觸摸屏任務(wù)。系統(tǒng)的總體設(shè)計(jì)如圖1-1所示。main()函數(shù)初始化任務(wù)
3、鍵盤(pán)任務(wù)主執(zhí)行任務(wù)觸摸屏任務(wù)光標(biāo)任務(wù)鍵盤(pán)isr觸摸屏isr時(shí)鐘節(jié)拍 圖1-1 c/os-ii系統(tǒng)總是從main()函數(shù)開(kāi)始,通常在main()函數(shù)中指創(chuàng)建一個(gè)用戶(hù)任務(wù),即初始化任務(wù),這樣設(shè)計(jì)有利于系統(tǒng)管理,而且結(jié)構(gòu)也會(huì)更清晰。在初始化任務(wù)中啟動(dòng)時(shí)鐘節(jié)拍,創(chuàng)建各個(gè)任務(wù)以及要用到的信號(hào)量或消息。1.1.1任務(wù)功能描述在電子詞典設(shè)計(jì)中,鍵盤(pán)任務(wù)和觸摸屏任務(wù)負(fù)責(zé)采集輸入信號(hào),并將其轉(zhuǎn)換為鍵值告知主處理任務(wù)。主處理任務(wù)負(fù)責(zé)根據(jù)讀到的鍵值啟動(dòng)相應(yīng)功能。而光標(biāo)任務(wù)則是用來(lái)展現(xiàn)時(shí)鐘節(jié)拍,讓目標(biāo)板上的led燈以指定的時(shí)間間隔進(jìn)行閃爍。1.1.2 任務(wù)的優(yōu)先級(jí)分配系統(tǒng)中的優(yōu)先級(jí)分配按照最經(jīng)常發(fā)生的優(yōu)先級(jí)最高這一原
4、則進(jìn)行,具體分配如下:優(yōu)先級(jí)03:分配優(yōu)先級(jí)時(shí)將最高的4個(gè)優(yōu)先級(jí)留給系統(tǒng)用戶(hù);優(yōu)先級(jí)5:主處理任務(wù)優(yōu)先級(jí)最高為5級(jí);優(yōu)先級(jí)6:鍵盤(pán)的使用概率大于觸摸屏,其優(yōu)先級(jí)定為6級(jí);優(yōu)先級(jí)7:觸摸屏的優(yōu)先級(jí)為7級(jí);優(yōu)先級(jí)8:光標(biāo)每隔一個(gè)固定的時(shí)間閃爍一次,這個(gè)時(shí)間可以由用戶(hù)自定義,優(yōu)先級(jí)為8級(jí);最低優(yōu)先級(jí)-1:系統(tǒng)統(tǒng)計(jì)任務(wù)(可選);最低優(yōu)先級(jí):系統(tǒng)空閑任務(wù)。1.1.3 任務(wù)間同步與通信的規(guī)則需要傳遞消息的任務(wù)是鍵盤(pán)與主執(zhí)行任務(wù)。觸摸屏與主執(zhí)行任務(wù)之間傳遞的都是按鍵值,且鍵值不用區(qū)分來(lái)源,所以使用一個(gè)消息郵箱即可。由于任務(wù)間不存在共享互斥資源的問(wèn)題,所以不需要進(jìn)行任務(wù)間的同步。鍵盤(pán)與觸摸屏都是由外界時(shí)間觸發(fā)
5、的,可以使用中斷機(jī)制設(shè)計(jì)驅(qū)動(dòng)程序。在驅(qū)動(dòng)程序的設(shè)計(jì)中,遵循中斷中處理的時(shí)間盡量短,講更多的事情交給任務(wù)區(qū)完成這一原則。1.2 系統(tǒng)配置c/os-ii并不提供列斯linux那樣的命令行形式的配置方法,而是通過(guò)對(duì)配置的內(nèi)容進(jìn)行條件編譯來(lái)實(shí)現(xiàn)的。這是由于c/os-ii提供開(kāi)放的源代碼,用戶(hù)可以直接使用#define constants語(yǔ)句來(lái)更改內(nèi)核的很多參數(shù)。系統(tǒng)中提供了以下配置項(xiàng):事件標(biāo)志:包括使能或禁止事件標(biāo)志及其相關(guān)功能,通常以os_flag_為前綴;消息郵箱:包括使能或禁止消息郵箱及其相關(guān)功能,通常以os_mbox_為前綴;內(nèi)存管理:包括使能或禁止內(nèi)存管理及其相關(guān)功能,目前版本中只有兩個(gè)可配
6、置項(xiàng)os_mem_en和os_mem_query_en;互斥型信號(hào)量:包括使能或禁止互斥型信號(hào)量及其相關(guān)功能,通常以os_mutex_為前綴;消息隊(duì)列:包括使能或禁止消息隊(duì)列及其相關(guān)功能,通常以os_q_為前綴;信號(hào)量:包括使能或禁止信號(hào)量及其相關(guān)功能,通常以os_sem_為前綴;任務(wù)管理:系統(tǒng)提供兩個(gè)任務(wù)創(chuàng)建函數(shù),在配置文件中至少要對(duì)其中一個(gè)進(jìn)行使能,另外還包括一些對(duì)任務(wù)其他相關(guān)屬性的配置,通常以os_task_為前綴;時(shí)鐘管理:c/os-ii中用戶(hù)可以使用操作系統(tǒng)的時(shí)鐘作為演示的基準(zhǔn),這里包括使能或禁止使用系統(tǒng)時(shí)鐘及其相關(guān)功能,通常以os_time_為前綴;雜項(xiàng):包括配置任務(wù),事件,消息隊(duì)
7、列的最大個(gè)數(shù),任務(wù)堆棧的容量等。c/os-ii內(nèi)核默認(rèn)的是將系統(tǒng)配置為最大系統(tǒng),即使能所有功能,并且將認(rèn)為尿素時(shí)間按等設(shè)置為最大。在電子詞典的應(yīng)用中,只有13個(gè)任務(wù)(5個(gè)用戶(hù)任務(wù),8個(gè)系統(tǒng)預(yù)留任務(wù))、兩個(gè)事件標(biāo)志、一個(gè)消息郵箱,所以需要對(duì)默認(rèn)系統(tǒng)進(jìn)行重新配置。需要更改的主要參數(shù)如下:os_max_events:最大可申請(qǐng)的事件控制塊數(shù)。系統(tǒng)中每個(gè)消息和信號(hào)量都需要一個(gè)事件控制塊。電子詞典中只用到一個(gè)消息郵箱,該值大于1即可。為了便于本系統(tǒng)擴(kuò)展,將其設(shè)為5。os_max_flags:最大可申請(qǐng)的事件標(biāo)志數(shù)。當(dāng)前使用了倆各個(gè)事件標(biāo)志,該值大于2即可。為了便于本系統(tǒng)擴(kuò)展將其設(shè)為5。os_max_ta
8、sks:最大可申請(qǐng)的用戶(hù)任務(wù)書(shū)。電子詞典中共定義了5個(gè)用戶(hù)任務(wù),該值大于5即可。為了便于本系統(tǒng)擴(kuò)展將其設(shè)為10。os_lowest_prio:系統(tǒng)可分配的最低優(yōu)先級(jí)。系統(tǒng)根據(jù)該參數(shù)初始化任務(wù)控制塊,所以這個(gè)參數(shù)會(huì)影響系統(tǒng)對(duì)ram的占用 。電子詞典將此參數(shù)定義為15,其中5個(gè)用戶(hù)任務(wù)、8個(gè)系統(tǒng)任務(wù)、2個(gè)余量任務(wù)。各個(gè)功能的使能/禁止參數(shù)通常以_en為后綴,1為使能,0為禁止。在電子詞典中要使能消息郵箱(os_mbox_en)和信號(hào)量(os_sem_en),將其對(duì)應(yīng)的參數(shù)設(shè)為1,其余使能參數(shù)設(shè)為0,其他參數(shù)均使用默認(rèn)值即可。2詳細(xì)設(shè)計(jì)2.1 系統(tǒng)移植在移植c/os-ii之前,要確保目標(biāo)系統(tǒng)(主要是
9、處理器及其編譯環(huán)境)滿足如下要求:(1) 目標(biāo)系統(tǒng)所使用的編譯環(huán)境要包括標(biāo)準(zhǔn)的c交叉編譯器。(2) 目標(biāo)系統(tǒng)所使用的c編譯器支持在c程序中對(duì)中斷進(jìn)行操作。(3) 處理器必須可以產(chǎn)生定時(shí)器中斷。(4) 處理器必須可容納一定數(shù)據(jù)存儲(chǔ)硬件堆棧。(5) 處理器中的寄存器與內(nèi)存之間可以相互讀/寫(xiě)。2.1.1移植os_cpu.h在os_cpu.h里主要包括與處理器有關(guān)的數(shù)據(jù)類(lèi)型、常量以及宏的定義。定義常量so_stk_growth。這個(gè)常量表示了棧的增長(zhǎng)方向。1為向上遞減,棧底高地址入棧時(shí)指針減,出棧時(shí)指針加;0為向下遞增,棧底低地入棧時(shí)指針加,出棧時(shí)減。定義宏os_enter_critical()和os
10、_exit_critical()。這兩個(gè)宏是用來(lái)打開(kāi)和關(guān)閉中斷的。當(dāng)c/os-ii需要處理不能被中斷打斷的段時(shí),就要用到這兩個(gè)宏對(duì)其進(jìn)行保護(hù)。由于不同的處理器對(duì)中斷的操作不盡相同,所以在這里對(duì)這兩個(gè)操作進(jìn)行定義。關(guān)中斷宏代碼如下:#define os_enter_critical() _ _asmbl armdisableint 開(kāi)中斷宏代碼如下:#define os_exit_critical() _ _asmbl armenableint 具體功能在os_cpu_a.s實(shí)現(xiàn),代碼如下:armdisableintmrsr0,cpsrstmfd sp!,r0 ;保存當(dāng)前處理器狀態(tài)orrr0,r
11、0,#0x80msrcpsr_c,r0 ;禁止中斷movpc,lrarmenableintldmfdsp!,r0 ;從棧中彈出處理器的狀態(tài)值msrcpsr_c,r0 ;恢復(fù)原始的處理器狀態(tài)movpc,lr2.1.2 移植os_cpu_c.cos_cpu_c.c包括10個(gè)簡(jiǎn)單的c函數(shù)。與移植相關(guān)的只有ostaskstkinit()函數(shù),該函數(shù)負(fù)責(zé)對(duì)任務(wù)棧進(jìn)行初始化。另外9個(gè)都是對(duì)各種任務(wù)進(jìn)行擴(kuò)展時(shí)用的,雖然必須定義,但可以不用包含任何代碼。這10個(gè)函數(shù)分別是:ostaskstkinit()、ostaskcreatehook()、ostaskdelhook()、ostaskswhook()、ost
12、askidlehook()、ostaskstathook()、ostimetickhook()、osinithookbegin()、osinithookend()和ostcbinithook()。ostaskstkinit()函數(shù)在創(chuàng)建任務(wù)時(shí)被ostaskcreate()或ostaskcreateexit()調(diào)用,以初始化任務(wù)棧結(jié)構(gòu),將所有的寄存器像剛發(fā)生中斷一樣保存在棧里。雖然arm對(duì)棧的方向并沒(méi)有特殊要求,但是由于ads編譯器僅支持滿減棧fd(full descending),即高地址為棧底,入棧時(shí)指針減1,棧指針指向最后一個(gè)入棧的數(shù)據(jù)元素,所以需要在os_cpu.h中將任務(wù)棧定義為減棧:
13、#define os_stk_growth 1/*內(nèi)存中棧的增長(zhǎng)方向?yàn)閺母叩降?/其實(shí)際結(jié)構(gòu)如圖2-1所示。pdata是在人物創(chuàng)建時(shí)傳遞給任務(wù)的一個(gè)參數(shù)。代碼如下:os_stk*ostaskstkinit(viod(*task)(void*pd),void*pdata,os_stk*ptos,int16u opt)unsigned int * stk;opt=opt; stk=(unsigned int *)ptos; /*當(dāng)前棧指針*/*對(duì)新任務(wù)建立上下文環(huán)境*/*_ _stk=(unsigned int) task; /* pc*/*_ _stk=(unsigned int) task;
14、/* lr*/*_ _stk=0; /* r12*/*_ _stk=0; /* r11*/*_ _stk=0; /* r10*/*_ _stk=0; /* r9*/*_ _stk=0; /* r8*/*_ _stk=0; /* r7*/*_ _stk=0; /* r6*/*_ _stk=0; /* r5*/*_ _stk=0; /* r4*/*_ _stk=0; /* r3*/*_ _stk=0; /* r2*/*_ _stk=0;/* r1*/*_ _stk=(unsigned int)pdata;/* r0*/*_ _stk=(svc32mode|0x0;/* 禁用cpsr中的irq,fi
15、q*/*_ _stk=(svc32mode|0x0);/* 禁用spsr中的irq,fiq*/return(void*)stk;c/os-iic/os-ii中有4個(gè)與處理器相關(guān)的函數(shù)要用匯編語(yǔ)言實(shí)現(xiàn),這4個(gè)函數(shù)分別是:oostarthighrdy( )、osctxsw( )、osintctxsw( )和ostickisr( )。oostarthighrdy( )oostarthighrdy( )僅在osstart()函數(shù)中被調(diào)用。具體實(shí)現(xiàn)代碼如下: osstarthighrdybl ostaskswhookldrr4,=osrunningmovr5,#1strbr5,r4ldrr4,=osrc
16、bhighrdyldrr4,r4ldrsp,r4ldmfdsp!,r4msrspsr_c,r4ldmfdsp!,r4msr cpsr_c,r4ldmedsp!,r0-r12,lr,pc這段代碼中ostaskswhook()在文件os_cpu_c.c中定義,通過(guò)它用戶(hù)可以擴(kuò)展任務(wù)切換代碼的功能。osctxsw( )osctxsw( )用來(lái)實(shí)現(xiàn)任務(wù)級(jí)的任務(wù)切換。具體實(shí)現(xiàn)代碼如下: osctxswstmfdsp!,lrstmfdsp!,r0-r12,lrmrsr4,cpsrstmfdsp!,r4mrsr4,spsrstmfdsp!,r4_osctxswbl ostaskswhookldrr4,=os
17、priocurldrr5,=ospriohighrdyldrbr6,r5strbr6,r4ldrr4,=ostcbcurldrr5,r4strsp,r5ldrr6,= ospriohighrdyldrr6,r6ldrsp,r6strr6,r4ldmfdsp!,r4msrspsr_cxsf,r4ldmfdsp!,r4msrcpsr_cxsf,r4ldmfdsp!,r0-r12,lr,pcosintctxsw( )osintctxsw( )由osintexit( )調(diào)用,在isr中實(shí)現(xiàn)任務(wù)切換功能。通常使用如下形式的代碼實(shí)現(xiàn)中斷級(jí)的任務(wù)切換: osintctxswldrr0,=osintctxsw
18、flagmovr1,#1strr1,r0movpc,lr以上這段代碼值設(shè)置了一個(gè)用以表示是否需要進(jìn)行任務(wù)切換的標(biāo)志osintctxswflag,在中斷后的第一個(gè)時(shí)鐘節(jié)拍內(nèi)對(duì)此標(biāo)志進(jìn)行判斷,根據(jù)判斷結(jié)果決定是都需要進(jìn)行中斷級(jí)任務(wù)切換。ostixkisr( )ostixkisr( )時(shí)鐘節(jié)拍中斷的isr。在之前提到過(guò)的c/os-ii要求用戶(hù)提供一個(gè)稱(chēng)為時(shí)鐘節(jié)拍的定時(shí)中斷,以實(shí)現(xiàn)延時(shí)與超時(shí)控制等功能。這個(gè)中斷頻率一般是10100hz。具體實(shí)現(xiàn)代碼如下:nointequ0xc0i_ispcequ0x1e00024timer0equ0x1ostickisrstmfdsp!,r0-r3,r12,lrblo
19、sintenterldrr0,=i_ispcmovr2,#timer0ldrr1,r0orrr1,r1,r2,lsl #13strr1,r0blostimetickblosintexitldrr0,=osintctxswflagldrr1,r0cmpr1,#1beq_intctxswidmfdsp!,r0-r3,r12,lrsubspc,lr,#4/*-以下代碼用于任務(wù)切換-*/_intctxswldrr0,=osintctxswflagmovr1,#0str r1,r0idmfdsp!,r0-r3,r12,lrstmfdsp!,r0-r3movr1,spaddspsubr2,lr,#4mrs
20、r3,spsrorrr0,r3,#nointmsrspsr_c,r0idrr0,=.+8movspc,r0stmfdsp!,r2stmfdsp!,r4-r12,lrmovr4,r1movr5,r3idmfdr4!,r0-r3stmfdsp!,r0-r3stmfdsp!,r5mrsr4,spsrstmfdsp!,r4b_osctxsw2.2 最小系統(tǒng)的運(yùn)行調(diào)試最小系統(tǒng)主要是指如處理器、存儲(chǔ)器這些最基本的元素所組成的可運(yùn)行的最小系統(tǒng),在增加了操作系統(tǒng)之后,可以認(rèn)為最小系統(tǒng)等于硬件最小能運(yùn)行系統(tǒng)加上可運(yùn)行的操作系統(tǒng)內(nèi)核。只有當(dāng)最小系統(tǒng)運(yùn)行起來(lái)以后,才能進(jìn)一步開(kāi)發(fā)應(yīng)用程序。系統(tǒng)測(cè)試的過(guò)程要與系統(tǒng)運(yùn)行過(guò)
21、程一致。系統(tǒng)上電后調(diào)用的啟動(dòng)程序?qū)μ幚砥饕约按鎯?chǔ)器這些硬件進(jìn)行初始化,初始化完成之后跳轉(zhuǎn)至main()函數(shù),在此之前的工作基本與c/os-ii內(nèi)核無(wú)關(guān),所以對(duì)內(nèi)核的測(cè)試從main()函數(shù)開(kāi)始。在main()函數(shù)中系統(tǒng)調(diào)用osinit()初始化c/os-ii中所有的變量和數(shù)據(jù)結(jié)構(gòu),為了使測(cè)試更加簡(jiǎn)單,可以在系統(tǒng)配置中禁止系統(tǒng) 統(tǒng)計(jì)任務(wù)(#define os_task_stat_en 0)。于是,系統(tǒng)在初始化時(shí)至創(chuàng)建一個(gè)空閑任務(wù),并將其優(yōu)先級(jí)設(shè)置為最低,讓其永遠(yuǎn)處于就緒狀態(tài)。測(cè)試之前建立的main()函數(shù)代碼如下:void main(void)target_init();osinit();osta
22、skcreate(starttask,(void*)0,&starttaskstktasksize-1,pro);osstart();代碼含義如下:初始化目標(biāo)板上載調(diào)試時(shí)要用到的基本硬件,如led;調(diào)用osinit(),初始化c/os-ii系統(tǒng)內(nèi)核;創(chuàng)建一個(gè)用戶(hù)任務(wù),用來(lái)測(cè)試多任務(wù)調(diào)度是否成功;調(diào)用osstart(),開(kāi)始多任務(wù)調(diào)度。這里用到的與系統(tǒng)相關(guān)的函數(shù)有osinit()、ostaskcreate()、osstart(),只要這3個(gè)函數(shù)運(yùn)行正常系統(tǒng)就算移植成功。下面開(kāi)始測(cè)試代碼。2.2.1 保證編譯正確,系統(tǒng)啟動(dòng)正確從最簡(jiǎn)單的開(kāi)始 ,這一步只要保證代碼沒(méi)有語(yǔ)法錯(cuò)誤并且系統(tǒng)可正確啟動(dòng)即可。
23、將main()函數(shù)進(jìn)行如下改動(dòng):#include”includes.h”void main(void)target_init( );led_on( );在ads下編譯并運(yùn)行這段代碼。如果指示燈被成功點(diǎn)亮,就說(shuō)明沒(méi)有語(yǔ)法問(wèn)題,而且硬件也已經(jīng)啟動(dòng)完成了。這是一段用來(lái)驗(yàn)證是否存在語(yǔ)法錯(cuò)誤并且編譯、鏈接器以及匯編器是否配置正確的代碼。2.2.2調(diào)試os_enter_critical()講之前的測(cè)試程序進(jìn)行如下更改,在之前的main()函數(shù)中加入osinit()函數(shù),即#include”includes.h”void main(void)target_init( );osinit( );led_on(
24、);系統(tǒng)函數(shù)osinit()用于初始化c/os-ii系統(tǒng),使用系統(tǒng)函數(shù)osinit()時(shí)不需要輸入?yún)?shù),直接調(diào)用即可。osinit()函數(shù)設(shè)計(jì)的移植代碼包括os_enter_critical( )、os_exit_critical()、ostaskstkinit()。在ads下編譯完成,啟動(dòng)axd進(jìn)行調(diào)試。以上3個(gè)函數(shù)都是在osinit()內(nèi)部創(chuàng)建系統(tǒng)空閑任務(wù)時(shí)被調(diào)用的。對(duì)這些函數(shù)分別使用單步雕飾的發(fā)那個(gè)發(fā),觀察寄存器中的值是否與設(shè)計(jì)一致。2.2.3 調(diào)試osstarthighrdy()在之前的main()函數(shù)中加入osstart()函數(shù),即#include”includes.h”void m
25、ain(void)target_init( );osinit( );led_on( );osstart( );系統(tǒng)函數(shù)osstart()用于啟動(dòng)多任務(wù),使用時(shí)不需要輸入?yún)?shù),直接調(diào)用即可。進(jìn)入調(diào)試器開(kāi)始調(diào)試,執(zhí)行main()函數(shù)。如果移植正確,程序會(huì)從osstarthighrdy()運(yùn)行至os_taskidle()。整個(gè)運(yùn)行過(guò)程中需要關(guān)注的是移植中重寫(xiě)的函數(shù)osstarthighrdy()。這里可以通過(guò)調(diào)試器觀察是否將優(yōu)先級(jí)最高的任務(wù)控制塊交付給當(dāng)前處理器,也就是os_taskidle( )任務(wù),并且將新任務(wù)的所有寄存器按與入棧相反的順序出棧。如果這里出現(xiàn)問(wèn)題那么棧指針就會(huì)出錯(cuò),這是就要對(duì)os
26、starthighrdy()進(jìn)行修改。從osstarthighrdy()中返回時(shí)應(yīng)該直接跳轉(zhuǎn)至os_taskidle(),如果沒(méi)有這樣,那么有可能是在初始化時(shí)系統(tǒng)調(diào)用的ostaskstkinit()沒(méi)能正確創(chuàng)建任務(wù)堆棧,這是只要檢查并改正就可以 。在ostaskidlehook()將指示燈的狀態(tài)取反,并在其后加上適當(dāng)延時(shí)。具體如下:void ostaskidlehook(void)led_turn( );delay(10);這樣如果指示燈能夠閃爍,那么就說(shuō)明系統(tǒng)運(yùn)行正常,osstarthighrdy()的移植是成功的。2.2.4 調(diào)試osctxsw()通過(guò)上面幾步可知ostaskstkinit
27、()對(duì)任務(wù)棧的初始化操作是正確的,下來(lái)就可以創(chuàng)建一個(gè)用戶(hù)任務(wù),并且通過(guò)osctxsw()使其被切換至os_taskidle(),以此驗(yàn)證osctxsw()正確與否。首先更改主程序,即#include”include.h”os_stk taskstk100;void main(void)char idl=1;osinit( );led_on( );ostaskcreate(starttask,&idl,&taskstk99,4);osstart( ); void starttask(void* pdata)pdata=pdata;while(1)led_off( );ostimedly(1);系
28、統(tǒng)函數(shù)ostaskcreate()用于創(chuàng)建用戶(hù)任務(wù),有4個(gè)輸入?yún)?shù),它們分別是:第1個(gè)參數(shù):task指向任務(wù)代碼的指針,即在定義任務(wù)時(shí)使用的任務(wù)名;第2個(gè)參數(shù):pdata任務(wù)開(kāi)始時(shí)傳遞給任務(wù)的參數(shù)指針;第3個(gè)參數(shù):ptos分配給任務(wù)棧的棧頂指針,任務(wù)棧需要提前聲明為os_stk類(lèi)型的數(shù)組,這里的任務(wù)棧是容量為100的減棧。第4個(gè)參數(shù):prio任務(wù)優(yōu)先級(jí),任務(wù)就是在這里獲得最初優(yōu)先級(jí)。系統(tǒng)函數(shù)ostimedly()用于系統(tǒng)延時(shí)時(shí),有一個(gè)輸入?yún)?shù),int16u類(lèi)型的ticks,用以表示要延時(shí)多少個(gè)時(shí)鐘節(jié)拍后再重新返回該任務(wù)。但是由于此時(shí)還沒(méi)有啟動(dòng)時(shí)鐘節(jié)拍,所以系統(tǒng)無(wú)法從os_taskidle(0中
29、返回到startask()任務(wù)。編譯通過(guò)即可調(diào)試運(yùn)行,同第3步一樣單步運(yùn)行osstart()會(huì)發(fā)現(xiàn),程序會(huì)跳轉(zhuǎn)至新建立的任務(wù),這是因?yàn)樾陆⒌娜蝿?wù)優(yōu)先級(jí)高于os_taskidle();繼續(xù)單步運(yùn)行starttask()至ostimedly(1),系統(tǒng)在ostimedly()的最后調(diào)用了任務(wù)調(diào)度器os_sched(),在調(diào)度器的最后用osctxsw()實(shí)現(xiàn)了任務(wù)級(jí)的任務(wù)切換;單步執(zhí)行至osctxsw(),在osctxsw()中可以看到當(dāng)前任務(wù)starttask()中所有寄存器已經(jīng)保存到它自己的任務(wù)棧中,os_taskidle()任務(wù)棧中的寄存器則被調(diào)入當(dāng)前處理器,從osctxsw()返回到so_
30、taskidle()。如果沒(méi)能運(yùn)行到os_taskidle(),則需在osctxsw(0中查找原因并改正錯(cuò)誤。當(dāng)全速欲行程序時(shí),如果結(jié)果正確則可以看到指示燈先閃滅一次,然后開(kāi)始以一個(gè)固定的頻率閃動(dòng)。2.2.5 調(diào)節(jié)時(shí)鐘節(jié)拍由前面可知,任務(wù)棧的建立和初始化,以及任務(wù)級(jí)的任務(wù)調(diào)度都是正確的,還剩下系統(tǒng)時(shí)鐘ostickisr()和中斷級(jí)任務(wù)調(diào)度osintctxsw()這兩個(gè)移植項(xiàng)需要測(cè)試。在測(cè)試這兩個(gè)函數(shù)之前,首先要保證系統(tǒng)的時(shí)鐘節(jié)拍(定時(shí)器中斷)是否可以正常運(yùn)行,對(duì)starttask()任務(wù)進(jìn)行如下改正:void starttask(void*pdata)pdata=pdata;timer_ini
31、t( );while(1);將ostimetick()中調(diào)用的ostimetickhook()更改如下:void ostimetickhook(void)led_turn( );編譯通過(guò)后開(kāi)始調(diào)試,全速運(yùn)行。如果看到指示燈閃爍說(shuō)明時(shí)鐘節(jié)拍沒(méi)有問(wèn)題,否則要對(duì)ostickisr()進(jìn)行單步調(diào)試。2.2.6 調(diào)試osintctxsw()和ostickisr()首先刪除ostimetickhook()和ostaskidlehook()中對(duì)指示燈的操作。其次對(duì)starttask()任務(wù)進(jìn)行如下更改:void starttask(void*pdata)pdata = pdata;timer_init( )
32、;for(;)ostimedly(1);編譯通過(guò)后可以開(kāi)始調(diào)試。如果osintctxsw()移植正確,全速運(yùn)行指示燈閃爍,并且閃爍頻率與ostimedly(x)中的x成正比關(guān)系。否則就要針對(duì)osintctxsw()移植代碼進(jìn)行調(diào)試更改。調(diào)試時(shí)仍用外部中斷代替定時(shí)器中斷。至此所有與移植相關(guān)的文件都已經(jīng)調(diào)試完成,移植的c/os-ii意見(jiàn)可以正常工作,下面將在這個(gè)移植好的操作系統(tǒng)上,重新實(shí)現(xiàn)之前的電子詞典應(yīng)用實(shí)例。3 驅(qū)動(dòng)程序的設(shè)計(jì)與調(diào)試3.1 基于c/os-ii的中斷設(shè)計(jì)中斷使得處理器可以在事件發(fā)生時(shí)才予以處理,而不必連續(xù)不斷地查詢(xún)是否有事件發(fā)生,所以是設(shè)計(jì)驅(qū)動(dòng)時(shí)一個(gè)很重要的方法。在實(shí)時(shí)環(huán)境中,關(guān)
33、中斷的事件應(yīng)盡量短。關(guān)中斷影響中斷響應(yīng)時(shí)間,關(guān)中斷時(shí)間太長(zhǎng)可能會(huì)引起中斷丟失。中斷服務(wù)的處理時(shí)間應(yīng)該盡可能短,中斷服務(wù)所做的事情應(yīng)該盡可能少,應(yīng)該把大部分工作留給任務(wù)去做。c/os-ii系統(tǒng)內(nèi)核通過(guò)特殊函數(shù)os_enter_critical( )和os_exit_critical( )來(lái)開(kāi)/關(guān)中斷,讓用戶(hù)決定什么情況下需要響應(yīng)中斷,什么情況下不需要。本設(shè)計(jì)中涉及到的中斷分為兩大類(lèi):定時(shí)器中斷和用戶(hù)中斷。定時(shí)器中斷:它作為系統(tǒng)的時(shí)鐘節(jié)拍為系統(tǒng)提供特定的周期性中斷,是系統(tǒng)任務(wù)調(diào)度的基礎(chǔ)。使得系統(tǒng)內(nèi)核可以將任務(wù)延時(shí)若干個(gè)時(shí)鐘節(jié)拍,以及當(dāng)任務(wù)要求等待時(shí)提供超時(shí)依據(jù)。用戶(hù)中斷:鍵盤(pán)中斷以及觸摸屏中斷。所
34、有基于c/os-ii的isr需要調(diào)用osintenter()和osintexit()使內(nèi)核進(jìn)入/退出中斷處理狀態(tài)。3.2 基于c/os-ii的設(shè)備驅(qū)動(dòng)程序設(shè)計(jì)將硬件分為主動(dòng)式硬件和被動(dòng)式硬件兩類(lèi)。主動(dòng)式硬件指可以接受外部信息要求軟件作出響應(yīng)的軟件,如本系統(tǒng)的鍵盤(pán)和觸摸屏。主動(dòng)式硬件驅(qū)動(dòng)設(shè)計(jì)可分為初始化、中斷服務(wù)以及請(qǐng)求處理3類(lèi)。在中斷服務(wù)中使用信號(hào)量通知任務(wù)有事情發(fā)生,根據(jù)信號(hào)量的不同啟動(dòng)相應(yīng)的任務(wù),在該任務(wù)中對(duì)發(fā)出信號(hào)的硬件進(jìn)行處理。因此,在初始化具體硬件時(shí)需要?jiǎng)?chuàng)建用于通知系統(tǒng)的信號(hào)量。下面是相應(yīng)代碼:os_event *f_key;os_event *f_touch;os_event *k
35、ey_value;void device_drever_init(void)int8u err;f_key=ossemcreate(0);f_touch=ossemcreate(0);key_value=osmboxcreate(void*)0);gui_init( );keyboard_init( );touchscreen_init( );系統(tǒng)函數(shù)ossemcreate()用于創(chuàng)建信號(hào)量,只有一個(gè)int16u型的參數(shù)cnt用于表示該信號(hào)量的初始計(jì)數(shù)值,范圍是065535。信號(hào)量f_key和f_touch,分別用于表示鍵盤(pán)和觸摸屏。這兩個(gè)信號(hào)量都是用于表示有一個(gè)硬件輸入時(shí)間按發(fā)生所以在創(chuàng)建時(shí)
36、將cnt的初始值賦為0。系統(tǒng)函數(shù)osmboxcreate()用于創(chuàng)建消息郵箱,唯一的輸入?yún)?shù)msg是一個(gè)可以指向任意類(lèi)型值的指針,這個(gè)指針?biāo)赶虻木褪青]箱的內(nèi)容。在調(diào)用此函數(shù)創(chuàng)建郵箱時(shí)必須定義指針的初始值。通常用null將這個(gè)郵箱初始化為空,也可以在初始化時(shí)就給郵箱中放入消息。該函數(shù)返回一個(gè)指向事件控制塊ebc的指針,相當(dāng)于這個(gè)郵箱的名字。觸摸屏中斷服務(wù)代碼如下:void_ _irq touchscreen_int (void)osintenter( );rintmsk|=bit_eint0;ri_ispc=bit_einto;ossempost(f_touch);osintexit( );3
37、.3 基于c/os-ii的設(shè)備驅(qū)動(dòng)程序測(cè)試在開(kāi)始設(shè)計(jì)任務(wù)之前,可借鑒調(diào)試最小系統(tǒng)的方法對(duì)完成的設(shè)備驅(qū)動(dòng)進(jìn)行測(cè)試,測(cè)試仍遵循由簡(jiǎn)到繁的原則,先測(cè)試被動(dòng)式硬件,再測(cè)試主動(dòng)式硬件。將做好的驅(qū)動(dòng)代碼加入之前的測(cè)試工程,在創(chuàng)建的starttask中加入要測(cè)試硬件的初始化代碼。代碼在pc機(jī)上啟動(dòng)串口調(diào)試工具,設(shè)置參數(shù)。編譯并運(yùn)行測(cè)試代碼,如果測(cè)試成功則會(huì)通過(guò)串口每隔一個(gè)固定時(shí)間間隔打印一條提示信息。在timer_init( )內(nèi)將時(shí)鐘節(jié)拍設(shè)置為100hz,ostimedly(100)就會(huì)使starttask任務(wù)每秒啟動(dòng)一次,則打印的時(shí)間間隔應(yīng)該大約是1s。測(cè)試主動(dòng)式硬件與此過(guò)程稍有不同,需要在任務(wù)中等待系
38、統(tǒng)發(fā)來(lái)的相應(yīng)信號(hào),以鍵盤(pán)為例,仍然使用starttask任務(wù),代碼如下:代碼系統(tǒng)函數(shù)ossempend用于等待信號(hào)量。有3個(gè)輸入?yún)?shù)分別是:第1個(gè)參數(shù)為指向要等待的信號(hào)量對(duì)應(yīng)的事件控制塊的指針;第2個(gè)參數(shù)為int16u類(lèi)型的timeout,代表等待超時(shí)的時(shí)間,以時(shí)鐘節(jié)拍為單位,如果設(shè)置為0,表示無(wú)限期等待;第3特參數(shù)認(rèn)為返回的err錯(cuò)誤狀態(tài)。4 系統(tǒng)集成與功能測(cè)試4.1 初始化任務(wù)系統(tǒng)初始化任務(wù)通常在main()函數(shù)中創(chuàng)建,分配的優(yōu)先級(jí)可以是允許的優(yōu)先級(jí)中的任意一個(gè),因?yàn)槌跏蓟蝿?wù)通常只運(yùn)行一次,運(yùn)行完成后可以將其刪除,不會(huì)對(duì)其他任務(wù)優(yōu)先級(jí)分配造成影響。在main()函數(shù)中要對(duì)目標(biāo)板上的基本硬
39、件做初始化工作,如串口的初始化、中斷控制的初始化、s3c44b0x內(nèi)部緩存的初始化等。main()函數(shù)的代碼如下:void main(void)char idl=1;target_init( );uart_printf(0,”*=start test=*n);osinit( );ostaskcreate(inittask,&idl,&taskstk1taskstacksize-1,4);osstart( );硬件初始化:如lcd、鍵盤(pán)和觸摸屏。軟件初始化:創(chuàng)建所需的信號(hào)量、事件標(biāo)志組、消息郵箱、消息隊(duì)列中的一個(gè)或多個(gè);創(chuàng)建用戶(hù)任務(wù),但可以不是所有的任務(wù),根據(jù)系統(tǒng)的需要而定。由于初始化任務(wù)并不需
40、要重復(fù)進(jìn)行,所以在最后調(diào)用ostaskdel(so_prio_self)將其自身刪除即可。其代碼如下:/定義每個(gè)任務(wù)所要用到的棧os_stktaskstk1taskstacksize;os_stktaskstk2mintaskstacksize;os_stktaskstk3maxtaskstacksize;os_stktaskstk4taskstacksize;os_stktaskstk5taskstacksize;void inittask(void* pdata)char id2=2;char id3=3;char id4=4;char id5=5;ostaskcreate(coursor
41、task,&id2,&taskstk2mintaskstacksize-1,7); ostaskcreate(executtask,&id5,&taskstk3maxtaskstacksize-1,8);ostaskcreate(kbrecievetask,&id4,&taskstk4 taskstacksize-1,9);ostaskcreate(adconvertask,&id3,&taskstk5 taskstacksize-1,6);target_start( );ostaskdel(os_prio_self); 4.2 鍵盤(pán)處理任務(wù)對(duì)鍵盤(pán)的處理首先需要能對(duì)鍵盤(pán)動(dòng)作做出響應(yīng),因此鍵盤(pán)處
42、理函數(shù)必須能夠響應(yīng)鍵盤(pán)中斷,并通過(guò)系統(tǒng)總線讀取鍵盤(pán)相應(yīng)信息,并將其打印出來(lái)。代碼如下:/鍵盤(pán)測(cè)試函數(shù):void keyboard_test(void)int i, j, k;uint8t ucchar, t;iic_init();/ set eint2 interrupt handler pisr_eint2 = (int)keyboard_int;for(;) f_nkeypress = 0;rintmsk = rintmsk & (bit_global|bit_eint2);/ enable eint2 intwhile(f_nkeypress = 0);iic_read(0x70, 0x
43、1, &ucchar);if(ucchar !=0)ucchar = key_set(ucchar);if(ucchar 10) ucchar += 0x30;else if(ucchar 16) ucchar += 0x37;if(ucchar 255)uart_printf(press key %cn, ucchar);if(ucchar = 0xff)uart_printf( press key fun (exit now)nr);return; while(1);其中f_nkeypress為全局變量,含義是是否有鍵盤(pán)中斷發(fā)生(0代表有,1代表沒(méi)有)。鍵盤(pán)中斷函數(shù)如下:void keyb
44、oard_int(void)uint8t ucchar; delay(1000);rintmsk = rintmsk | bit_eint2;/ disable eint2 int ri_ispc = bit_eint2; f_nkeypress = 1;對(duì)鍵盤(pán)數(shù)值進(jìn)行轉(zhuǎn)換代碼如下:uint8t key_set(uint8t ucchar)switch(ucchar)case 1:case 2:case 3:case 4:case 5:ucchar-=1; break;case 9:case 10:case 11:case 12:case 13:ucchar-=4; break;case 17
45、:case 18:case 19:case 20:case 21:ucchar-=7; break;case 25: ucchar = 0xf; break;case 26: ucchar = +; break;case 27: ucchar = -; break;case 28: ucchar = *; break;case 29: ucchar = 0xff; break;default: ucchar = 0xfe;return ucchar;iic頭文件代碼:/* file:iic.h* author:embest* desc:iic header file* history:*/#i
46、fndef _iic_h_#define _iic_h_#endif /*_iic_h_*/系統(tǒng)總線iic的初始化函數(shù)如下:void iic_init(void)f_ngetack = 0; / enable interruptrintmod = 0x0;rintcon = 0x1;rintmsk = rintmsk & (bit_global|bit_iic); pisr_iic= (unsigned)iic_int;/ initialize iicriicadd = 0x10;/ s3c44b0x slave address riiccon = 0xe5;/ enable ack, int
47、errupt, iicclk=mclk/512, enable ack/64mhz/512/(15+1) = 8khz riicstat= 0x10;/ enable tx/rx iic的寫(xiě)操作代碼如下:/* name:iic_write* func:write data to iic* para:unslaveaddr - input, chip slave address*unaddr- input, data address*ucdata - input, data value* ret:none* modify:* comment:*/void iic_write(uint32t un
48、slaveaddr,uint32t unaddr,uint8t ucdata)f_ngetack = 0; / send control byte riicds = unslaveaddr;/ 0xa0 riicstat = 0xf0; / master tx,start while(f_ngetack = 0);/ wait ack f_ngetack = 0; / send address riicds = unaddr; riiccon = 0xe5; / resumes iic operation.while(f_ngetack = 0);/ wait ack f_ngetack = 0; / send data riicds = ucdata; riiccon = 0xe5; / resumes iic operation. while(f_ngetack = 0);/ wait ack f_ngetack = 0; / end send riicstat = 0xd0;/ stop master tx condition riiccon = 0xe5;/ resumes iic operation.while(ri
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶(hù)所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶(hù)上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶(hù)上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶(hù)因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 貨幣資金報(bào)表范例
- Windows Server網(wǎng)絡(luò)管理項(xiàng)目教程(Windows Server 2022)(微課版)10.3 任務(wù)2 DNS中繼代理
- 大型機(jī)械設(shè)備管理制度與安全操作規(guī)程(修改版1)
- 煤化工藝學(xué)煤低溫干餾
- 幼兒園安全教育教案18篇
- 小學(xué)安全教育主題班會(huì)教案
- 高三烴含氧衍生物歸納
- 全省小學(xué)數(shù)學(xué)教師賽課一等獎(jiǎng)數(shù)學(xué)一年級(jí)上冊(cè)(人教2024年新編)《10的認(rèn)識(shí) 》課件
- 生命在你手中主題班會(huì)
- 病歷書(shū)寫(xiě)規(guī)范
- 句子成分及句子基本結(jié)構(gòu)(共32張PPT)
- 醫(yī)院輸血管理委員會(huì)人員組成和工作職責(zé)制度及辦公室職責(zé)
- 數(shù)據(jù)安全治理白皮書(shū)5.0-行業(yè)數(shù)據(jù)安全治理實(shí)踐集-2023.05月
- 四年級(jí)下冊(cè)英語(yǔ)說(shuō)課稿-Lesson 22 My Favourite Subject-冀教版
- 企業(yè)國(guó)有資產(chǎn)法解讀課件講義
- 大眾標(biāo)準(zhǔn)目錄(中文)
- 善于休息增進(jìn)健康
- 全國(guó)中學(xué)生英語(yǔ)能力測(cè)試高三初評(píng)英語(yǔ)試題
- 《汽車(chē)專(zhuān)業(yè)英語(yǔ)》課程教學(xué)大綱
- 自己設(shè)計(jì)的花鍵跨棒距的計(jì)算-2
- 雷電的監(jiān)測(cè)和預(yù)警
評(píng)論
0/150
提交評(píng)論