丁香婷婷网,黄色av网站裸体无码www,亚洲午夜无码精品一级毛片,国产一区二区免费播放

現(xiàn)在位置:范文先生網(wǎng)>理工論文>電子通信論文>μC/OS-II的多任務(wù)信息流與CAN總線驅(qū)動(dòng)

μC/OS-II的多任務(wù)信息流與CAN總線驅(qū)動(dòng)

時(shí)間:2023-02-21 00:12:04 電子通信論文 我要投稿
  • 相關(guān)推薦

μC/OS-II的多任務(wù)信息流與CAN總線驅(qū)動(dòng)

  摘要:闡述μC/OS-II多任務(wù)信息流關(guān)鍵技術(shù)與中斷處理的一般方法和PC體系中斷的基本概念;以CAN總線為例,詳細(xì)分析在x86實(shí)模式下基于μC/OS-II的CAN總線驅(qū)動(dòng)的實(shí)現(xiàn)過(guò)程。
  關(guān)鍵詞:μC/OS-IIRTOS嵌入式系統(tǒng)設(shè)備驅(qū)動(dòng)中斷處理程序(ISR)進(jìn)程調(diào)度
  
  μC/OS-II是美國(guó)人JeanLabrosse編寫的一個(gè)免費(fèi)的、源碼公開的嵌入式實(shí)時(shí)內(nèi)核。對(duì)于開發(fā)計(jì)算機(jī)嵌入式應(yīng)用產(chǎn)品的技術(shù)人員來(lái)說(shuō)是一個(gè)實(shí)用價(jià)值很高的實(shí)時(shí)嵌入式操作系統(tǒng)ERTOS(EmbeddedRealTimeOperationSystem)。
  
  要開發(fā)出完善的ERTOS,就要在多任務(wù)的調(diào)度和對(duì)I/O設(shè)備操作的穩(wěn)定性、協(xié)調(diào)性方面做出大量的工作,這也是我在開發(fā)ERTOS過(guò)程中深深體會(huì)到的重點(diǎn)所在。希望本文能對(duì)開發(fā)ERTOS的技術(shù)人員在多任務(wù)信息流和I/O驅(qū)動(dòng)方面有所啟迪。
  
  1多任務(wù)信息流關(guān)鍵技術(shù)
  
  在討論多任務(wù)信息流之前,先討論一下多任務(wù)的工作狀態(tài)。在μC/OS中,每個(gè)任務(wù)都是無(wú)限循環(huán)的,每個(gè)任務(wù)都處在以下五種狀態(tài)之一:休眠態(tài)、就緒態(tài)、運(yùn)行態(tài)、掛起態(tài)和中斷態(tài),如圖1所示。
  
  在多任務(wù)的調(diào)度和驅(qū)動(dòng)程序的編寫過(guò)程中,必然要涉及到公用代碼段和共享存儲(chǔ)區(qū)的保護(hù)問(wèn)題。即使是原有的C函數(shù),可重用性方面在沒(méi)有得到理論和實(shí)踐的驗(yàn)證情況下也需要對(duì)其進(jìn)行保護(hù)。這樣就需要合理的算法對(duì)公用代碼段、共享存儲(chǔ)區(qū)進(jìn)行保護(hù),避免操作系統(tǒng)在運(yùn)行過(guò)程中產(chǎn)生重用性問(wèn)題而導(dǎo)致運(yùn)行結(jié)果不可預(yù)測(cè)。
  
  系統(tǒng)在開發(fā)過(guò)程中,既要考慮到減少系統(tǒng)的復(fù)雜程度,也要兼顧其穩(wěn)定性與運(yùn)行效率的要求。這就需要我們對(duì)各種算法進(jìn)行合理的選擇:在穩(wěn)定性可以保障的情況下,選擇相對(duì)簡(jiǎn)單,占用CPU時(shí)間少的算法;在穩(wěn)定性不能保障的情況下,考慮選擇周全的算法。只有這樣才能使操作系統(tǒng)在一定的配置環(huán)境下達(dá)到最高的運(yùn)行效率。
  
  接下來(lái)分別用voidCanSendMessageProcess(void*data)、voidCanSendMessage(void*data)、voidCanReceiveMessageProcess(void*data)和voidCanReceiveMessage(void*data)這四個(gè)任務(wù)來(lái)描述在采用消息隊(duì)列、郵箱和信號(hào)量通信機(jī)制時(shí)的信息流的傳遞過(guò)程。
  
 。1)消息隊(duì)列通信機(jī)制
  
  消息隊(duì)列在初始化的時(shí)候,建立一個(gè)指定空間大小的數(shù)組,這個(gè)數(shù)組在使用的時(shí)候取得了環(huán)形緩沖區(qū)的概念。這個(gè)數(shù)組在運(yùn)行期間不會(huì)被消除,這樣就避免了重復(fù)建立數(shù)組的時(shí)候內(nèi)存空間的泄漏問(wèn)題。當(dāng)一個(gè)任務(wù)向消息隊(duì)列發(fā)送一個(gè)信息的時(shí)候,相應(yīng)的指針加1(OSQIn+1),隊(duì)列滿時(shí)(OSQEntries=OSQSize),OSQIn則與OSQOut指向同一單元。如果在OSQIn指向的單元內(nèi)插入新的指向消息的指針,就構(gòu)成FIFO(First-In-First-Out)隊(duì)列。相反,如果在OSQOut指向單元的下一個(gè)單元插入新的指針,就構(gòu)成LIFO隊(duì)列(Last-In-First-Out)。在本實(shí)例中,我們定義FIFO隊(duì)列。消息指針總是從OSQOut指向的單元取出。OSQStart和OSQEnd定義了消息指針數(shù)組的頭和尾,以便在OSQIn和OSQOut到達(dá)隊(duì)列的邊緣時(shí),進(jìn)行邊界檢查和必要的指針調(diào)整,實(shí)現(xiàn)其循環(huán)功能。
  
  消息隊(duì)列數(shù)據(jù)結(jié)構(gòu)如下:
  
  typedefstructos_q{
  
  structos_q*OSQPtr;/*在空閑隊(duì)列控制塊中鏈接所有的隊(duì)列控制塊*/
  
  void*OSQStart;/*指向消息隊(duì)列的指針數(shù)組的起始地址的指針*/
  
  void*OSQEnd;/*指向消息隊(duì)列結(jié)束單元的下一個(gè)地址的指針*/
  
  void*OSQIn;/*指向消息隊(duì)列中插入下一條信息位置的指針*/
  
  void*OSQOut;/*指向消息隊(duì)列中下一個(gè)取出消息位置的指針*/
  
  INT16UOSQSize;/*消息隊(duì)列中總的單元數(shù)*/
  
  
  
  
  INT16UOSQEntries;/*消息隊(duì)列中總的消息數(shù)量*/
  
  }OS_Q;
  
  圖2為消息隊(duì)列信息流的演示說(shuō)明。
  
  ①CanSendMessageProcess任務(wù)完成信息的計(jì)算工作以后,將要發(fā)送的信息送進(jìn)消息隊(duì)列1。
  
 、贑anSendMessage任務(wù)負(fù)責(zé)取得消息隊(duì)列1里面的信息。
  
 、弁ㄟ^(guò)CAN總線I/O端口將數(shù)據(jù)發(fā)送到總線上去。如果消息隊(duì)列中沒(méi)有信息,則該任務(wù)由運(yùn)行狀態(tài)進(jìn)入等待狀態(tài),直到從消息隊(duì)列中接收到信息為止。
  
 、蹸anReceiveMessage任務(wù)負(fù)責(zé)讀取總線上面的信息。
  
  ⑤CanReceiveMessage任務(wù)將讀取到的信息送入消息隊(duì)列2。
  
 、轈anReceiveMessageProcess任務(wù)是從消息隊(duì)列2中取出信息開始計(jì)算工作,如果消息隊(duì)列為空的話,該任務(wù)進(jìn)入等待狀態(tài)。
  
  消息隊(duì)列適用于一對(duì)一、一對(duì)多、多對(duì)多和多對(duì)一的關(guān)系。也就是說(shuō),消息隊(duì)列可以作為一塊共享的公共區(qū)域,為實(shí)施互斥,任務(wù)間需要同步;為了合作,進(jìn)程間需要交換信息,這樣也就實(shí)現(xiàn)了同步和通信。
  
 。2)郵箱通信機(jī)制
  
  郵箱的概念和管道(管線)有相似的定義,一個(gè)任務(wù)或者中斷服務(wù)子程序向另一個(gè)任務(wù)發(fā)送一個(gè)指針型的變量,該指針指向一個(gè)包含了特定“消息”的數(shù)據(jù)結(jié)構(gòu)。在源端的任務(wù)只能向郵箱寫,在目的端的任務(wù)只能從郵箱讀。郵箱傳輸流數(shù)據(jù),即連續(xù)的字節(jié)串或流。因此,訪問(wèn)一個(gè)郵箱就像是訪問(wèn)一個(gè)順序文件。郵箱可以用來(lái)通知一個(gè)事件的發(fā)生(發(fā)送一條信息),也可以用來(lái)共享某些資源,這樣郵箱就被當(dāng)成一個(gè)二值信號(hào)量。
  
  圖3為郵箱信息流的演示說(shuō)明。
  
 、貱anSendMessageProcess任務(wù)將計(jì)算好的數(shù)據(jù)發(fā)送給CanSendMessage任務(wù),然后進(jìn)入就緒態(tài)等待應(yīng)答信號(hào)。CanSendMessage在接收的同時(shí)發(fā)送應(yīng)答握手信號(hào)給CanSendMessageProcess,確認(rèn)信息接收完畢。
  
  ②CanSendMessage任務(wù)將CanSendMessageProcess任務(wù)發(fā)送來(lái)的信息發(fā)送到CAN總線,發(fā)送結(jié)束后進(jìn)入就緒態(tài)等待下一次傳輸工作。
  
 、跜anReceiveMessage任務(wù)接收來(lái)自總線的信息流,將接收到的信息發(fā)送到CanReceiveMessageProcess任務(wù),進(jìn)入就緒態(tài)等待應(yīng)答信號(hào)。
  
 、蹸anReceiveMessageProcess任務(wù)收到信息后發(fā)送應(yīng)答握手信號(hào)。
  
 。3)信號(hào)量通信機(jī)制
  
  信號(hào)量(semaphore)是一種約定機(jī)制:兩個(gè)或多個(gè)任務(wù)通過(guò)簡(jiǎn)單的信號(hào)進(jìn)行合作,一個(gè)任務(wù)可以被迫在某一位置停止,直到它接收到一個(gè)特定的信號(hào)。在多任務(wù)內(nèi)核中普遍將信號(hào)量用于:
  
  ◇標(biāo)志某事件的發(fā)生;
  
  ◇控制共享資源的使用權(quán)(滿足互斥條件);
  
  ◇使兩個(gè)任務(wù)的行為同步。
  
  信號(hào)量主要實(shí)施三種操作:
  
  ◇一個(gè)信號(hào)量可以初始化為非負(fù)數(shù);
  
  ◇等待(wait)操作使信號(hào)量減1。如果值變成負(fù)數(shù),則執(zhí)行等待的任務(wù)被阻塞。
  
  ◇得到CPU使用權(quán)的任務(wù)singal操作使信號(hào)量加1。如果值不是正數(shù),則被等待操作阻塞的任務(wù)被解除阻塞。
  
  為了滿足信息傳遞過(guò)程中實(shí)時(shí)高效的原則,在消息隊(duì)列中部分地引入信號(hào)量的概念。也就是CanSendMessageProcess任務(wù),把若干個(gè)字節(jié)的信息一次性地發(fā)送到消息隊(duì)列,令信號(hào)量加1并由運(yùn)行態(tài)進(jìn)入等待掛起狀態(tài)。在CanSendMessage任務(wù)獲得信號(hào)量后進(jìn)入就緒態(tài),等待CPU的使用權(quán)進(jìn)入運(yùn)行態(tài)。進(jìn)入運(yùn)行態(tài)后,該任務(wù)使信號(hào)量減1并從消息隊(duì)列中取出信息后通過(guò)I/O端口發(fā)送到CAN總線。CanReceiveMessage任務(wù)和CanReceiveMessageProcess任務(wù)執(zhí)行與上面相反的操作。這個(gè)實(shí)例說(shuō)明了信號(hào)量用于標(biāo)志某事件的發(fā)生。(見圖2。)
  
  
  
  
  
  2μC/OS-II的中斷處理
  
  μC/OS-II中,中斷服務(wù)程序一般用匯編語(yǔ)言來(lái)寫。以下是中斷服務(wù)程序的示意代碼。
  
  用戶中斷服務(wù)程序:
  
  保存全部CPU寄存器;
  
  調(diào)用OSIntEnter或OSIntNesting直接加1;
  
  執(zhí)行用戶代碼做中斷服務(wù);
  
  調(diào)用OSIntExit;
  
  恢復(fù)所有CPU寄存器;
  
  執(zhí)行中斷返回指令;
  
  這里μC/OS-II提供了兩個(gè)ISR與內(nèi)核的接口函數(shù):OSIntEnter和OSIntExit。OSIntEnter通知μC/OS-II內(nèi)核,中斷服務(wù)程序開始運(yùn)行了。實(shí)際上,此函數(shù)做的工作是把一個(gè)全局變量OSIntNesting加1。在x86等有累加指令的CPU中,可以用指令代替OSIntEnter:
  
  INCBYTEPTROSIntNesting
  
  此中斷嵌套計(jì)數(shù)器可以確保所有中斷處理完成后再作任務(wù)調(diào)度。另一個(gè)接口函數(shù)OSIntExit則通知內(nèi)核,中斷服務(wù)已結(jié)束。根據(jù)相應(yīng)情況,返回被中斷點(diǎn)(可能是一個(gè)任務(wù)或者被嵌套的中斷服務(wù)程序)或由內(nèi)核作任務(wù)調(diào)度。
  
  用戶編寫的ISR必須被安裝到某一位置,以便中斷發(fā)生后,CPU根據(jù)相應(yīng)的中斷號(hào)運(yùn)行準(zhǔn)確的服務(wù)程序。許多實(shí)時(shí)操作系統(tǒng)都提供了安裝、卸載中斷服務(wù)程序的API接口函數(shù),有些成熟的RTOS甚至對(duì)中斷控制器的管理都有相應(yīng)的API函數(shù)。但μC/OS-II內(nèi)核沒(méi)有提供類似的接口函數(shù),需要用戶在對(duì)應(yīng)的CPU移植中自己實(shí)現(xiàn)。這些接口函數(shù)與具體的硬件環(huán)境有關(guān),接下來(lái)PC體系下的中斷處理對(duì)此有詳細(xì)的說(shuō)明。
  
  3PC體系下的中斷
  
  X86系列的處理器可支持256個(gè)中斷,并用向量表的方法來(lái)關(guān)聯(lián)每個(gè)中斷和相應(yīng)ISR的位置。在實(shí)模式下,中斷向量表(IVT)存于內(nèi)存的低端1K。每個(gè)向量表?xiàng)l目占4字節(jié),保存一個(gè)ISR的段地址和偏移信息。PC系統(tǒng)使用兩個(gè)級(jí)聯(lián)的可編程中斷控制器82C59A。一個(gè)82C59A能連接8個(gè)硬件中斷,編號(hào)為IRQ0~IRQ7。PC總共可管理15個(gè)外部中斷源,PC的中斷控制器如圖4所示。(關(guān)于82C59A的詳細(xì)使用可參見有關(guān)資料。)
  
  在μC/OS下,CAN總線I/O端口中斷向量設(shè)置偽代碼:
  
  voidCanInitHW(UIsegment,BYTEIrq0,BYTEIrq1){
  
  保存原有的中斷向量
  
  保存掩碼寄存器的值
  
  使82C59A的掩碼寄存器(0x21)各位置1,關(guān)閉中斷輸入
  
  關(guān)閉CPU中斷
  
  設(shè)置新的中斷向量
  
  正在服務(wù)的中斷禁止再次響應(yīng)服務(wù)(假定當(dāng)前服務(wù)中斷是IRQ5)
  
  開CPU中斷
  
  清除82C59A的掩碼寄存器(0X21、0XA1)各位,開啟中斷輸入
  
  }
  
  4信號(hào)量與緩沖隊(duì)列支持下的CAN總線驅(qū)動(dòng)
  
  前面介紹了μC/OS-II內(nèi)核下多任務(wù)調(diào)度的關(guān)鍵技術(shù)、中斷與PC體系下中斷的一般方法。又以82C59A的中斷5(IRQ5)、0x0D中斷向量為例,介紹了中斷服務(wù)子程序的重新分配和響應(yīng)SJA1000控制器收發(fā)的中斷服務(wù)子程序。
  
  下面介紹信號(hào)量配合下的環(huán)形緩沖隊(duì)列與中斷處理程序之間
  
  
  
  的關(guān)系問(wèn)題,這也是設(shè)備驅(qū)動(dòng)部分的核心內(nèi)容。
  
  ERTOS的驅(qū)動(dòng)程序與其它操作系統(tǒng)有所不同。比如Windows、Unix、Solaris、Linux等操作系統(tǒng)弱化了設(shè)備的概念,用戶進(jìn)程對(duì)設(shè)備的使用可以通過(guò)文件系統(tǒng)來(lái)完成。然而,在μC/OS-II上開發(fā)CAN總線驅(qū)動(dòng)程序沒(méi)有那么嚴(yán)格,只要滿足設(shè)備在連續(xù)的CPU時(shí)間上使用時(shí)不發(fā)生時(shí)間重疊就可以了。
  
  串行設(shè)備或者其它字符型設(shè)備都存在外設(shè)處理速度和CPU速度不匹配的問(wèn)題,所以需要建立相應(yīng)的緩沖區(qū)。向CAN口發(fā)送數(shù)據(jù)時(shí),只要把數(shù)據(jù)寫到緩沖區(qū),然后由SJA1000控制器逐個(gè)取出往外發(fā)。從CAN口接收數(shù)據(jù)時(shí),往往等收到若干個(gè)字節(jié)后才需要CPU進(jìn)行處理,所以這些預(yù)收的數(shù)據(jù)可以先存于緩沖區(qū)。緩沖區(qū)可以設(shè)置收到若干個(gè)字節(jié)后再中斷CPU,這樣避免了因?yàn)镃PU的頻繁中斷而降低系統(tǒng)的實(shí)時(shí)性。
  
  在對(duì)緩沖區(qū)讀寫的過(guò)程中,經(jīng)常會(huì)遇到想發(fā)送數(shù)據(jù)時(shí),發(fā)送緩沖已滿;想去讀時(shí),接收緩沖卻是空的。對(duì)于用戶程序端,可以采用查詢工作方式,即放棄無(wú)法讀寫的操作,然后再頻繁地去嘗試這個(gè)操作直到成功,這樣程序效率顯然降低。如果引入讀、寫兩個(gè)信號(hào)量分別對(duì)緩沖區(qū)兩端的操作進(jìn)行同步,問(wèn)題將迎刃而解。用戶任務(wù)想寫但緩沖區(qū)滿時(shí),在信號(hào)量上睡眠,讓CPU運(yùn)行別的任務(wù),待ISR從緩沖區(qū)讀走數(shù)據(jù)后喚醒此睡眠的任務(wù);類似地,用戶任務(wù)想讀但緩沖區(qū)空時(shí),也可以在信號(hào)量上睡眠,待外部設(shè)備有數(shù)據(jù)來(lái)了再喚醒。由于μC/OS-II的信號(hào)量提供了超時(shí)等待機(jī)制,CAN口當(dāng)然也具有超時(shí)讀寫能力。
  
  帶緩沖和信號(hào)量的CAN口接收和發(fā)送部分見本刊網(wǎng)絡(luò)補(bǔ)充版。
  
  接口函數(shù)總結(jié)如下。
  
  voidCanInitHW(UIsegment,BYTEirq0,BYTEIRQ1)
  
  /*設(shè)置SJA1000控制器端口中斷向量*/
  
  intcanReleaseHW()/*清除SJA1000控制器端口中斷向量*/
  
  intcanSendMsg(CANBYTEport,MSG_STRUCTmsg)
  
  /*向定制SJA1000控制器端口發(fā)送數(shù)據(jù)*/
  
  intcanReceiveMsg(CANBYTEport,MSG_STRUCTmsg_ptr)
  
  /*從定制SJA1000控制器端口接收數(shù)據(jù)
  
  intcanConfig(CANBYTEport,CAN_STRUCTcan)
  
  /*初始化和配置SJA1000控制器*/
  
  intcanNormalRun(CANBYTEport)
  
  /*設(shè)置SJA1000正常(Normal)運(yùn)行模式*/
  
  intcanReset(CANBYTEport)
  
  /*SJA1000控制器端口重新設(shè)置,緩沖區(qū)置位0xff*/
  
  CANBYTEcan0r(CANBYTEaddr)
  
  /*讀取SJA1000控制器端口0的定制寄存器的值*/
  
  CANBYTEcan1r(CANBYTEaddr)
  
  /*讀取SJA1000控制器端口1的定制寄存器的值*/
  
  接收和發(fā)送數(shù)據(jù)緩沖區(qū)數(shù)據(jù)結(jié)構(gòu)定義:
  
  
  
  
  >typedefstruct{
  
  INT16URingBufRxCtr;/*接收緩沖中字符數(shù)目*/
  
  OS_EVENTRingBufRxSem;/*接收信號(hào)量*/
  
  INT8URingBufRxInPtr;/*接收緩沖中下一字符的寫入位置*/
  
  INT8URingBufRxOutPtr;/*接收緩沖中下一待讀出字符的位置*/
  
  INT8URingBufRx[CAN_RX_BUF_SIZE];/*接收環(huán)形緩沖區(qū)*/
  
  INT16URingBufTxCtr;
  
  /*發(fā)送緩沖中字符數(shù)目*/
  
  OS_EVENT*RingBufTxSem;/*發(fā)送信號(hào)量*/
  
  INT8U*RingBufTxInPtr;
  
  /*發(fā)送緩沖中下一字符的寫入位置*/
  
  INT8U*RingBufTxOutPtr;
  
  /*發(fā)送緩沖中下一待讀出字符的位置*/
  
  INT8URingBufTx[CAN_TX_BUF_SIZE];/*發(fā)送環(huán)形緩沖區(qū)*/
  
  }CAN_RING_BUF;
  
  結(jié)語(yǔ)
  
  本文是在嵌入式計(jì)算機(jī)技術(shù)領(lǐng)域的應(yīng)用背景下提出的,整個(gè)工程開發(fā)結(jié)束以后,系統(tǒng)正常運(yùn)作時(shí)間超過(guò)27天。希望本文的提出對(duì)開發(fā)嵌入式操作系統(tǒng)的技術(shù)人員能有所幫助,同時(shí)也希望同一領(lǐng)域的開發(fā)人員共同探討、共同發(fā)展。
  
  
  
  

【μC/OS-II的多任務(wù)信息流與CAN總線驅(qū)動(dòng)】相關(guān)文章:

基于ADμC812的CAN總線智能節(jié)點(diǎn)的設(shè)計(jì)08-06

μC/OS-II實(shí)時(shí)內(nèi)核下的A/D驅(qū)動(dòng)程序設(shè)計(jì)08-06

CAN總線中位定時(shí)的設(shè)定方法08-06

CAN總線中位定時(shí)的設(shè)定方法08-06

CAN總線控制器與DSP的接口08-06

基于PCI總線的CAN卡的設(shè)計(jì)與實(shí)現(xiàn)08-06

光纖CAN總線自愈環(huán)網(wǎng)的研究08-06

CAN總線位定時(shí)參數(shù)的確定08-06

P80C592芯片在基于CAN總線顯示通信模塊中應(yīng)用08-06