當(dāng)前位置:首頁(yè) > 嵌入式 > 嵌入式教程
[導(dǎo)讀]一個(gè)搶先式“裸奔"系統(tǒng)的設(shè)計(jì)

摘要:在一些資源比較緊張的嵌入式系統(tǒng)中,使用RTOS有時(shí)未必能夠較好地滿足系統(tǒng)較高的實(shí)時(shí)性要求。在軟件設(shè)計(jì)時(shí),可以借鑒搶先式RTOS實(shí)時(shí)調(diào)度內(nèi)核的方法,實(shí)現(xiàn)更為高效的任務(wù)調(diào)度算法,從而實(shí)現(xiàn)系統(tǒng)更高的實(shí)時(shí)性要求。
關(guān)鍵詞:嵌入式系統(tǒng);搶先式調(diào)度;實(shí)時(shí)操作系統(tǒng);STC12C5410

引言
   
這是2007年筆者在基于STC12C5410的工控系統(tǒng)里采用的軟件技術(shù)。系統(tǒng)中有兩個(gè)以主從方式通過I2C總線進(jìn)行數(shù)據(jù)通信的節(jié)點(diǎn),作為I2C總線的從機(jī)節(jié)點(diǎn),因MCU性能限制了數(shù)據(jù)傳輸速率,因而每次通過總線傳輸30個(gè)字節(jié)的數(shù)據(jù)需要持續(xù)占用幾十ms的時(shí)間。由于在進(jìn)行I2C總線通信的這段時(shí)間里,系統(tǒng)將不能響應(yīng)輸入和改變輸出(類似系統(tǒng)停頓),這么長(zhǎng)的時(shí)間延遲對(duì)于有較高實(shí)時(shí)要求的工控系統(tǒng)顯得難于容忍。
    為此,最初考慮解決問題的辦法有3個(gè):
    ①打斷和拆分?jǐn)?shù)據(jù)包,采用多次傳輸?shù)霓k法。這樣做不但需要修改從機(jī)的軟件,多個(gè)數(shù)據(jù)包的連接又讓軟件變得復(fù)雜起來,所以這不是個(gè)很好的辦法。
    ②由于I2C總線在進(jìn)行數(shù)據(jù)傳輸中,波特率較低,存在大量短時(shí)delay(),可以采用定時(shí)中斷,在定時(shí)中斷中只變換一次電平后就返回,從而在后臺(tái)完成數(shù)據(jù)發(fā)送。但這樣就導(dǎo)致中斷服務(wù)中必須執(zhí)行一個(gè)很龐大的狀態(tài)機(jī)判斷,中斷服務(wù)中大量的判斷也非常耗時(shí)耗力,且調(diào)試也不方便。
    ③采用RTOS技術(shù),但在80C51系統(tǒng)上使用RTOS,再精練的實(shí)時(shí)調(diào)度,每個(gè)tick的時(shí)間都很難低于1 ms。經(jīng)測(cè)試,I2C總線傳輸中途遇到1 ms以上的傳輸中斷,會(huì)產(chǎn)生總線超時(shí)錯(cuò)誤,因而在本系統(tǒng)中即使采用RTOS也未必能很好地解決問題。
    通過一段時(shí)間對(duì)RTOS的分析和研究,最后在80C51的裸奔系統(tǒng)中嵌入特別定制的精練的搶先式調(diào)度來完成主要任務(wù)和I2C總線任務(wù)的并行執(zhí)行,最終獲得了很好的效果。
    下面就來詳細(xì)地講述這個(gè)定制的搶先式調(diào)度的編程技巧。

1 I2C總線通信子程序
   
對(duì)I2C總線的時(shí)序在此就不作介紹了,下面是部分基于Keil C51模擬主I2C總線的通信子程序代碼如下:
   
   
    上面是基于80C51模擬I2C總線的通信程序,其中的HIGH、LOW是1、0的宏定義,idelay()提供時(shí)序要求的一段時(shí)間的延時(shí)。
    不難看出,這和通常的模擬I2C總線的通信子程序完全一樣。事實(shí)上,我也是直接使用了以前的子程序。[!--empirenews.page--]

2 程序主執(zhí)行函數(shù)main()函數(shù)
   
   
   
main()函數(shù)也非常簡(jiǎn)單。首先,調(diào)用Sys_init()完成單片機(jī)硬件系統(tǒng)的初始化;然后調(diào)用I2c_svr(),完成I2C總線通信系統(tǒng)的初始化,并執(zhí)行數(shù)據(jù)傳輸,本函數(shù)稍后將作詳細(xì)的介紹;接下來是一個(gè)while(1)主循環(huán),其中的mainfunc()是執(zhí)行主要任務(wù)的函數(shù),完成系統(tǒng)的主要功能,并返回一個(gè)bool變量,這個(gè)變量用于I2C總線數(shù)據(jù)傳輸?shù)恼?qǐng)求;
    這里定義了一個(gè)bool型變量bi2csvr。作用:由mainfunc()執(zhí)行結(jié)果來置位,系統(tǒng)根據(jù)此標(biāo)志,啟動(dòng)數(shù)據(jù)通信,并在數(shù)據(jù)傳輸完成后清零這個(gè)標(biāo)志。

3 I2C總線通信服務(wù)程序
   
通信服務(wù)程序I2c_svr()函數(shù)代碼如下:
   
    這個(gè)函數(shù)看起來也不復(fù)雜,但是需要讀者用RTOS任務(wù)的概念來理解這個(gè)函數(shù)。
    首先,關(guān)于寄存器組,這里的I2C服務(wù)程序I2c_svr()使用了單獨(dú)的寄存器組(寄存器組1),由于#pragmarb(1)編譯指令并不會(huì)讓編譯器自動(dòng)生成切換寄存器組的指令,所以I2c_svr()中又通過修改PSW特殊寄存器來切換到工作寄存器組1。當(dāng)然,要切換寄存器組,還需要確認(rèn)在切換前,本函數(shù)沒有使用工作寄存器。
    同時(shí),I2c_svr()的初始化部分還執(zhí)行了特殊功能寄存器壓棧保存和切換堆棧指針SP,這些本是實(shí)時(shí)內(nèi)核調(diào)度器里要完成的任務(wù),在這里的出現(xiàn)相當(dāng)于建立了新的任務(wù)。
    接下來的while(1)表明,這里相當(dāng)于實(shí)時(shí)系統(tǒng)里的一個(gè)任務(wù)了。
    這個(gè)任務(wù)很簡(jiǎn)單,i2write()的功能就是通過I2C總線,發(fā)送數(shù)據(jù)緩沖區(qū)里所有的數(shù)據(jù),在這里就不做詳細(xì)介紹了。在發(fā)送完成后,清零數(shù)據(jù)發(fā)送請(qǐng)求標(biāo)志位bi2csvr,然后執(zhí)行延時(shí)等待。

4 定時(shí)中斷和延時(shí)函數(shù)
   
搶先系統(tǒng)的關(guān)鍵部分是定時(shí)中斷timer1()和延時(shí)函數(shù)idelay(),代碼如下:
   
    首先看tsksw()宏,它的作用是保存堆棧指針并切換堆棧。這等同于RTOS里任務(wù)的上下文切換,但這里僅切換一下堆棧指針即可。
    接下來看這個(gè)定時(shí)中斷服務(wù)函數(shù)timer1(),其中systern_tmr()是個(gè)修改定時(shí)器TH0的函數(shù),這里不作介紹了。隨后,約束判斷(后面再作詳細(xì)介紹)再通過tsksw()函數(shù)進(jìn)行任務(wù)間的切換。
    接下來看延時(shí)函數(shù)idelay(),它提供I2C總線時(shí)序里要求的延時(shí)函數(shù)。注意:我們通常都是使用若干nop或者類似“for(x=LOOP;x>0;x——);”的延時(shí)來完成的,但這里一改這類傳統(tǒng)的方式,而是通過“任務(wù)切換”將CPU控制權(quán)交給另外一個(gè)任務(wù)main來實(shí)現(xiàn)的。需要特別指出,idelay()里的關(guān)中斷很重要,學(xué)習(xí)過RTOS的讀者應(yīng)該都記得RTOS里面的“臨界段代碼”的概念。
    最后,介紹上面未詳細(xì)說明的定時(shí)中斷服務(wù)函數(shù)timer1()中任務(wù)切換的約束判斷。bi2csvr是I2C總線請(qǐng)求標(biāo)志,如果這個(gè)標(biāo)志為零,則表示不需要I2C總線的通信服務(wù),定時(shí)中斷里也就不需要做任務(wù)切換;此外,bi2cdly也是個(gè)控制切換的小技巧,該標(biāo)志在idelay()中置位,在定時(shí)中斷服務(wù)中判斷并清零。也就是在執(zhí)行idelay()后發(fā)生的第一次定時(shí)中斷里只清除這個(gè)標(biāo)志,而在第二次定時(shí)中斷中才可能發(fā)生任務(wù)切換,以此保證idelay()的延時(shí)時(shí)間一定不少于一個(gè)定時(shí)器的溢出周期。
[!--empirenews.page--]
5 程序運(yùn)行流程
   
程序初始化流程圖如圖1所示。


    首先,main()在完成硬件初始化Sys_init()后,調(diào)用I2c_svr()總線通信服務(wù)程序。
    I2c_svr()服務(wù)程序里,首先完成類似通用RTOS的任務(wù)現(xiàn)場(chǎng)保護(hù)的過程。再通過切換堆棧指針,完成了新任務(wù)堆棧的初始化過程。然后進(jìn)入I2C總線通信模塊主循環(huán)(類似創(chuàng)建任務(wù)的操作),再通過調(diào)用idelay(),將CPU的控制權(quán)交還給main()。奧妙就在于idelay()首先保存通信程序的寄存器現(xiàn)場(chǎng)(ACC和PSW),然后轉(zhuǎn)換到main()的堆??臻g,并恢復(fù)剛才被I2c_svr()保存的寄存器現(xiàn)場(chǎng)(ACC和PSW)。所以;i2c_svr()里的idelay()函數(shù)返回后將不執(zhí)行其下面的i2write(),而是執(zhí)行main()里的while(1)。
    i2write()又如何能得到執(zhí)行呢?它是通過定時(shí)中斷服務(wù)程序timer1()再次獲得CPU控制權(quán)的。如果在main()的執(zhí)行中發(fā)生timer1()中斷,因?yàn)閠imer1()里也進(jìn)行與idelay()類似的任務(wù)切換操作,這時(shí)候?qū)⑶袚Q到I2c_svr()的堆棧和寄存器(現(xiàn)場(chǎng))。此時(shí)timer1()中斷返回時(shí),不會(huì)返回到main()里,而是執(zhí)行i2write()。
    另外,函數(shù)i2write()內(nèi)部執(zhí)行中也會(huì)調(diào)用idelay(),在I2c_svr()中的每次調(diào)用idelay()都會(huì)將CPU控制權(quán)交給main()的切換。main()和I2c_svr()的切換關(guān)系如圖2所示。


    當(dāng)然,timer1()并不總是引起任務(wù)的切換,通過判斷bi2csvr標(biāo)志可以避免(在不需要數(shù)據(jù)傳輸時(shí))不必要的任務(wù)切換。另外,timer1()也可能進(jìn)行從I2c_svr()到main()的切換。所以即使I2c_svr()里很長(zhǎng)時(shí)間沒有調(diào)用idelay(),也不會(huì)阻塞main()的執(zhí)行。
    切換現(xiàn)場(chǎng)一般基于80C51的RTOS,通常要保存所有的CPU寄存器(包括8個(gè)工作寄存器、ACC、PSW、B、DPTR等),而這里與它們不同,因?yàn)樵诠P者的通信服務(wù)模塊I2c_svr()中使用了另外的寄存器組,且未使用B和DPTR,因此不需要保存8個(gè)工作寄存器及B和DPTR,僅保存和恢復(fù)PSW和ACC這兩個(gè)寄存器就可以了,大大提高了切換效率。
    本系統(tǒng)里僅有兩個(gè)“任務(wù)”,即main()和I2c_svr(),也沒有固定優(yōu)先級(jí),處于“等待”狀態(tài)任務(wù)的優(yōu)先級(jí)總比當(dāng)前運(yùn)行中的任務(wù)高,所以相當(dāng)于同優(yōu)先級(jí)時(shí)間片輪轉(zhuǎn)調(diào)度方式。但相對(duì)于RTOS,這里還缺少操作系統(tǒng)必須管理的與任務(wù)相關(guān)的狀態(tài)和數(shù)據(jù)結(jié)構(gòu),所以筆者還將其稱做“裸奔”系統(tǒng)。

6 現(xiàn)場(chǎng)保護(hù)的補(bǔ)充說明
   
任務(wù)切換中的寄存器現(xiàn)場(chǎng)保護(hù)代碼如下:
   
   
    上面是Keil C51對(duì)定時(shí)中斷服務(wù)函數(shù)timer1()編譯生成的LST文件。編譯器在中斷服務(wù)里自動(dòng)生成壓棧和出棧寄存器的指令,所以在寫idelay()函數(shù)的寄存器現(xiàn)場(chǎng)切換的時(shí)候,必須完全遵守這個(gè)寄存器壓棧和出棧順序規(guī)則才能正常工作。

結(jié)語
   
通過學(xué)習(xí)和借鑒RTOS的CPU時(shí)間搶先調(diào)度和分配方法,可以將本系統(tǒng)中總線時(shí)序里許多很短的延時(shí)都交給主程序使用,最大程度利用CPU時(shí)間,實(shí)現(xiàn)主程序和通信服務(wù)程序的并行執(zhí)行,從而讓主程序和通信服務(wù)程序均達(dá)到系統(tǒng)要求的實(shí)時(shí)性能。
    本文為時(shí)間緊張的系統(tǒng)設(shè)計(jì)提供了一個(gè)新的解決思路。應(yīng)該有助于初學(xué)操作系統(tǒng)的讀者理解操作系統(tǒng)任務(wù)切換的工作機(jī)理。

本站聲明: 本文章由作者或相關(guān)機(jī)構(gòu)授權(quán)發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點(diǎn),本站亦不保證或承諾內(nèi)容真實(shí)性等。需要轉(zhuǎn)載請(qǐng)聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權(quán)益,請(qǐng)及時(shí)聯(lián)系本站刪除。
換一批
延伸閱讀

9月2日消息,不造車的華為或?qū)⒋呱龈蟮莫?dú)角獸公司,隨著阿維塔和賽力斯的入局,華為引望愈發(fā)顯得引人矚目。

關(guān)鍵字: 阿維塔 塞力斯 華為

倫敦2024年8月29日 /美通社/ -- 英國(guó)汽車技術(shù)公司SODA.Auto推出其旗艦產(chǎn)品SODA V,這是全球首款涵蓋汽車工程師從創(chuàng)意到認(rèn)證的所有需求的工具,可用于創(chuàng)建軟件定義汽車。 SODA V工具的開發(fā)耗時(shí)1.5...

關(guān)鍵字: 汽車 人工智能 智能驅(qū)動(dòng) BSP

北京2024年8月28日 /美通社/ -- 越來越多用戶希望企業(yè)業(yè)務(wù)能7×24不間斷運(yùn)行,同時(shí)企業(yè)卻面臨越來越多業(yè)務(wù)中斷的風(fēng)險(xiǎn),如企業(yè)系統(tǒng)復(fù)雜性的增加,頻繁的功能更新和發(fā)布等。如何確保業(yè)務(wù)連續(xù)性,提升韌性,成...

關(guān)鍵字: 亞馬遜 解密 控制平面 BSP

8月30日消息,據(jù)媒體報(bào)道,騰訊和網(wǎng)易近期正在縮減他們對(duì)日本游戲市場(chǎng)的投資。

關(guān)鍵字: 騰訊 編碼器 CPU

8月28日消息,今天上午,2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)開幕式在貴陽(yáng)舉行,華為董事、質(zhì)量流程IT總裁陶景文發(fā)表了演講。

關(guān)鍵字: 華為 12nm EDA 半導(dǎo)體

8月28日消息,在2024中國(guó)國(guó)際大數(shù)據(jù)產(chǎn)業(yè)博覽會(huì)上,華為常務(wù)董事、華為云CEO張平安發(fā)表演講稱,數(shù)字世界的話語權(quán)最終是由生態(tài)的繁榮決定的。

關(guān)鍵字: 華為 12nm 手機(jī) 衛(wèi)星通信

要點(diǎn): 有效應(yīng)對(duì)環(huán)境變化,經(jīng)營(yíng)業(yè)績(jī)穩(wěn)中有升 落實(shí)提質(zhì)增效舉措,毛利潤(rùn)率延續(xù)升勢(shì) 戰(zhàn)略布局成效顯著,戰(zhàn)新業(yè)務(wù)引領(lǐng)增長(zhǎng) 以科技創(chuàng)新為引領(lǐng),提升企業(yè)核心競(jìng)爭(zhēng)力 堅(jiān)持高質(zhì)量發(fā)展策略,塑強(qiáng)核心競(jìng)爭(zhēng)優(yōu)勢(shì)...

關(guān)鍵字: 通信 BSP 電信運(yùn)營(yíng)商 數(shù)字經(jīng)濟(jì)

北京2024年8月27日 /美通社/ -- 8月21日,由中央廣播電視總臺(tái)與中國(guó)電影電視技術(shù)學(xué)會(huì)聯(lián)合牽頭組建的NVI技術(shù)創(chuàng)新聯(lián)盟在BIRTV2024超高清全產(chǎn)業(yè)鏈發(fā)展研討會(huì)上宣布正式成立。 活動(dòng)現(xiàn)場(chǎng) NVI技術(shù)創(chuàng)新聯(lián)...

關(guān)鍵字: VI 傳輸協(xié)議 音頻 BSP

北京2024年8月27日 /美通社/ -- 在8月23日舉辦的2024年長(zhǎng)三角生態(tài)綠色一體化發(fā)展示范區(qū)聯(lián)合招商會(huì)上,軟通動(dòng)力信息技術(shù)(集團(tuán))股份有限公司(以下簡(jiǎn)稱"軟通動(dòng)力")與長(zhǎng)三角投資(上海)有限...

關(guān)鍵字: BSP 信息技術(shù)
關(guān)閉
關(guān)閉