日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當(dāng)前位置:首頁(yè) > 單片機(jī) > 單片機(jī)
[導(dǎo)讀]嵌入式程序框架一般類(lèi)似于程序1所示結(jié)構(gòu):系統(tǒng)中有3個(gè)任務(wù)——TaskA、TaskB、TaskC,均放置于主循環(huán)內(nèi),在每一個(gè)循環(huán)周期內(nèi)都被執(zhí)行一次。在這種結(jié)構(gòu)中,能滿足系統(tǒng)實(shí)時(shí)性要求的條件是: (當(dāng)且僅當(dāng))Task

嵌入式程序框架一般類(lèi)似于程序1所示結(jié)構(gòu):系統(tǒng)中有3個(gè)任務(wù)——TaskA、TaskB、TaskC,均放置于主循環(huán)內(nèi),在每一個(gè)循環(huán)周期內(nèi)都被執(zhí)行一次。在這種結(jié)構(gòu)中,能滿足系統(tǒng)實(shí)時(shí)性要求的條件是: (當(dāng)且僅當(dāng))TaskA 、TaskB、TaskC三個(gè)任務(wù)的運(yùn)行時(shí)間之和要小于系統(tǒng)實(shí)時(shí)響應(yīng)的時(shí)間要求。在系統(tǒng)較為簡(jiǎn)單、任務(wù)運(yùn)行時(shí)間能滿足實(shí)時(shí)要求的情況下,可以采用這種最簡(jiǎn)單、最直接的順序執(zhí)行方式。但是更多的情形是,系統(tǒng)不僅要對(duì)一些事件做出實(shí)時(shí)響應(yīng),并且還要承擔(dān)很多其他的非實(shí)時(shí)任務(wù),并且這些非實(shí)時(shí)任務(wù)的運(yùn)行時(shí)間要遠(yuǎn)遠(yuǎn)超出了實(shí)時(shí)響應(yīng)時(shí)間的要求。傳統(tǒng)的這種程序結(jié)構(gòu)顯然不能滿足系統(tǒng)的實(shí)時(shí)性要求。通常的解決方案是,引入實(shí)時(shí)操作系統(tǒng),由操作系統(tǒng)進(jìn)行任務(wù)的調(diào)度,優(yōu)先執(zhí)行實(shí)時(shí)任務(wù),達(dá)到滿足系統(tǒng)實(shí)時(shí)性的要求。

程序1嵌入式程序框架
  void main(void) {
    Init();
    while(1) {
      TaskA();
      TaskB();
      TaskC();
    }
  }
  void Interrupt_1(void) interrupt 1 {
    …
  }
  void Interrupt_2(void) interrupt 2 {
    …
  }

一般來(lái)說(shuō),在嵌入式系統(tǒng)開(kāi)發(fā)中引入實(shí)時(shí)操作系統(tǒng)有諸多優(yōu)點(diǎn):
  ◆ 更好地支持多任務(wù),實(shí)時(shí)性要求能夠得以保障;
  ◆ 程序開(kāi)發(fā)更加容易,也更便于維護(hù);
  ◆ 有利于提高系統(tǒng)的穩(wěn)定性和可靠性。但是,操作系統(tǒng)的引入也將帶來(lái)較多的系統(tǒng)開(kāi)銷(xiāo):
  ◆ 實(shí)時(shí)操作系統(tǒng)往往使用定時(shí)器中斷來(lái)切換任務(wù),需要消耗不少的CPU處理時(shí)間;
  ◆ 實(shí)時(shí)操作系統(tǒng)在切換任務(wù)時(shí)需要保護(hù)當(dāng)前任務(wù)的執(zhí)行現(xiàn)場(chǎng),這就需要為每個(gè)任務(wù)準(zhǔn)備足夠多的RAM空間來(lái)實(shí)現(xiàn)任務(wù)切換;
  ◆ 實(shí)時(shí)操作系統(tǒng)的本身也需要占用相當(dāng)數(shù)量的Flash空間和RAM空間。
  如果這些系統(tǒng)開(kāi)銷(xiāo)都在可承受的范圍內(nèi),那么采用實(shí)時(shí)操作系統(tǒng)將是最佳的選擇。但是在很多應(yīng)用的場(chǎng)合,特別是系統(tǒng)的資源非常緊張的單片機(jī)應(yīng)用,實(shí)時(shí)操作系統(tǒng)帶來(lái)的系統(tǒng)開(kāi)銷(xiāo)往往是不可接受的。而更換速度更快、RAM更大、Flash更多的CPU意味著成本的增加,且會(huì)降低產(chǎn)品的競(jìng)爭(zhēng)力。當(dāng)系統(tǒng)中的任務(wù)不須進(jìn)行非常復(fù)雜的優(yōu)先級(jí)調(diào)度,而且其任務(wù)也相對(duì)簡(jiǎn)單時(shí),引入實(shí)時(shí)操作系統(tǒng)似有殺雞用牛刀之嫌。

1  Protothread的特點(diǎn)

Protothread是專(zhuān)為資源有限的系統(tǒng)設(shè)計(jì)的一種耗費(fèi)資源特別少并且不使用堆棧的線程模型,其特點(diǎn)是:
  ◆ 以純C語(yǔ)言實(shí)現(xiàn),無(wú)硬件依賴性;
  ◆ 極少的資源需求,每個(gè)Protothread僅需要2個(gè)額外的字節(jié);
  ◆ 可以用于有操作系統(tǒng)或無(wú)操作系統(tǒng)的場(chǎng)合;
  ◆ 支持阻塞操作且沒(méi)有棧的切換。

使用Protothread實(shí)現(xiàn)多任務(wù)的最主要的好處在于它的輕量級(jí)。每個(gè)Protothread不需要擁有自已的堆棧,所有的 Protothread共享同一個(gè)堆??臻g,這一點(diǎn)對(duì)于RAM資源有限的系統(tǒng)尤為有利。相對(duì)于操作系統(tǒng)下的多任務(wù)而言,每個(gè)任務(wù)都有自已的堆??臻g,這將消耗大量的RAM資源,而每個(gè)Protothread僅使用一個(gè)整型值保存當(dāng)前狀態(tài)。

2  Protothread的阻塞運(yùn)行機(jī)制

以下是一個(gè)典型的Protothread程序示例:

程序2Protothread程序示例
  PT_THREAD(radio_wake_thread(struct pt *pt)) {
    PT_BEGIN(pt);
    while(1) {
      radio_on();
      timer_set(&timer, T_AWAKE);
      PT_WAIT_UNTIL(pt, timer_expired(&timer));
      timer_set(&timer, T_SLEEP);
      if(!communication_complete()) {
        PT_WAIT_UNTIL(pt, communication_complete()‖timer_expired(&timer));
      }
      if(!timer_expired(&timer)) {
        radio_off();
        PT_WAIT_UNTIL(pt, timer_expired(&timer));
      }
    }
    PT_END(pt);
  }

這是一個(gè)非常簡(jiǎn)單的無(wú)線通信的狀態(tài)切換程序①,展開(kāi)Protothread的宏定義,便可以得到程序3所示的展開(kāi)代碼:

程序3Protothread宏展開(kāi)代碼
  void radio_wake_thread(struct pt *pt) {
    switch(pt﹥lc) {
      case 0:
      while(1) {
        radio_on();
        timer_set(&timer, T_AWAKE);
        pt﹥lc = 8;
        case 8:
          if(!timer_expired(&timer)) {
            return;
          }
          timer_set(&timer, T_SLEEP);
          if(!communication_complete()) {
            pt﹥lc = 13;
            case 13:
            if(!(communication_complete() ||timer_expired(&timer))) {
              return;
            }
          }
          if(!timer_expired(&timer)) {
            radio_off();
            pt﹥lc = 18;
            case 18:
            if(!timer_expired(&timer)) {
              return;
            }
          }
        }
      }
    }

當(dāng)Protothread程序運(yùn)行到PT_WAIT_UNTIL時(shí),判斷其運(yùn)行條件是否滿足,若不滿足,則阻塞。通過(guò)比對(duì)程序2和程序3的程序代碼可以得知,Protothread的阻塞其實(shí)質(zhì)就是函數(shù)返回,只不過(guò)在返回前保存了當(dāng)前的阻塞位置,待下一次Protothread被調(diào)用時(shí),直接跳到阻塞位置執(zhí)行,再次判斷運(yùn)行條件是否滿足,并執(zhí)行后續(xù)程序或繼續(xù)阻塞。

3  利用Protothread構(gòu)造實(shí)時(shí)多任務(wù)系統(tǒng)

與操作系統(tǒng)下的多任務(wù)不同,操作系統(tǒng)下的每個(gè)任務(wù)可在任意時(shí)刻被打斷并阻塞,Protothread僅能在程序員指定位置阻塞。用Protothread實(shí)現(xiàn)實(shí)時(shí)多任務(wù),正是利用了Protothread在指定位置阻塞的特點(diǎn),讓出執(zhí)行權(quán)限給更高優(yōu)先級(jí)的任務(wù)先運(yùn)行。

下面舉例說(shuō)明如何利用Protothread構(gòu)造實(shí)時(shí)多任務(wù)系統(tǒng)。

系統(tǒng)要求:
  TaskA實(shí)時(shí)任務(wù),30 ms內(nèi)響應(yīng),運(yùn)行時(shí)間<20 ms;
  TaskB實(shí)時(shí)任務(wù),200 ms內(nèi)響應(yīng),運(yùn)行時(shí)間<40 ms;
  TaskC非實(shí)時(shí)任務(wù),響應(yīng)時(shí)間無(wú)要求,運(yùn)行時(shí)間>30 ms。

設(shè)計(jì)思路:

將TaskB和TaskC分成若干步,每步運(yùn)行時(shí)間不超過(guò)10 ms(這個(gè)時(shí)間可視系統(tǒng)需求而定,例如TaskA若為40 ms內(nèi)響應(yīng),則每步可擴(kuò)至20 ms)。任務(wù)以3個(gè)Protothread的方式運(yùn)行。首先執(zhí)行TaskA,在TaskA執(zhí)行完成1次后,釋放執(zhí)行權(quán)限,讓TaskB和TaskC執(zhí)行。 TaskB或TaskC在每執(zhí)行1步之前檢查運(yùn)行時(shí)間,一旦發(fā)現(xiàn)30 ms內(nèi)不夠執(zhí)行1步時(shí),阻塞運(yùn)行,讓出執(zhí)行權(quán)限給TaskA。同樣,TaskB和TaskC的調(diào)度關(guān)系也類(lèi)似,先運(yùn)行TaskB,完成時(shí)釋放執(zhí)行權(quán)限,讓 TaskC執(zhí)行;TaskC在每執(zhí)行1步之前檢查運(yùn)行時(shí)間,若發(fā)現(xiàn)200 ms內(nèi)不夠執(zhí)行1步時(shí),阻塞運(yùn)行,讓出執(zhí)行權(quán)限重新交給TaskB。

源程序(Task0TimeCounter、Task1TimeCounter為計(jì)數(shù)器,每毫秒加1):
  #include "ptsem.h"
  #define TASKA_MAX_RUN_TIME20
  #define TASKA_CYCLE_TIME30
  #define TASKB_CYCLE_TIME200
  #define TASK_STEP_TIME10
  #define TASK0_VALID_TIME TASKA_CYCLE_TIME?TASK_STEP_TIME
  #define TASK1_VALID_TIME TASKB_CYCLE_TIME?TASK_STEP_TIME?TASKA_MAX_RUN_TIME *2
  /*按照PT_WAIT_UNTIL 的宏定義擴(kuò)展一個(gè)新宏:當(dāng)程序進(jìn)入阻塞時(shí)發(fā)送一信號(hào),告知高優(yōu)先級(jí)任務(wù)獲得執(zhí)行權(quán)限*/
  #define LC_STEP_SET(s,n) s = __LINE__ + n; case __LINE__ + n:
  #define PT_SEM_WAIT_UNTIL(pt, s, condition, n)\
    do {
      LC_STEP_SET((pt)﹥lc,n);
      if(!(condition)) {if((s)﹥count==0)
        PT_SEM_SIGNAL(pt,s);
        return PT_WAITING;
      }
    } while(0)
  struct pt TaskAPt;
  struct pt TaskBPt;
  struct pt TaskCPt;
  struct pt_sem SemRunTaskA;
  struct pt_sem SemRunTaskB;
  /*若30 ms內(nèi)已經(jīng)不夠時(shí)間執(zhí)行1步,則讓出TaskA的執(zhí)行權(quán)限*/
  #define TASKB_STEP(pt) \
    PR_SEM_WAIT_UNTIL(pt, & SemRunTaskA,TaskOTimeCounter<=TASKO_VALID_TIME,0)
  /*若200 ms內(nèi)已經(jīng)不夠時(shí)間執(zhí)行1步,則讓出TaskB的執(zhí)行權(quán)限*/
  /*若30 ms內(nèi)已經(jīng)不夠時(shí)間執(zhí)行1步,則讓出TaskA的執(zhí)行權(quán)限*/
  #define TASKC_STEP(pt) \
    PT_SEM_WAIT_UNTIL(pt, &SemRunTaskB,Task1TimeCounter<=TASK1_VALID_TIME,0);\
    PT_SEM_WAIT_UNTIL(pt, &SemRunTaskA,Task0TimeCounter<=TASK0_VALID_TIME,1)
  int ProtothreadTaskA(struct pt *pt) {
    PT_BEGIN(pt);
    PT_SEM_WAIT(pt, &SemRunTaskA);/*等待其他任務(wù)讓出執(zhí)行權(quán)限*/
    ResetTask0TimeCounter;/*對(duì)時(shí)間計(jì)數(shù)器置0*/
    TaskA();/*TaskA任務(wù)*/
    PT_END(pt);
  }
  int ProtothreadTaskB(struct pt *pt) {
    PT_BEGIN(pt);
    PT_SEM_WAIT(pt, &SemRunTaskB);/*等待TaskC讓出執(zhí)行權(quán)限*/
    ResetTask1TimeCounter;/*對(duì)時(shí)間計(jì)數(shù)器置0*/
    TASKB_STEP(pt);/*如果不夠1步執(zhí)行,則阻塞,讓出執(zhí)行權(quán)限*/
    TaskB_1();/*TaskB任務(wù)的第1步*/
    TASKB_STEP(pt);
    TaskB_2();/*TaskB任務(wù)的第2步*/
    TASKB_STEP(pt);
    TaskB_3();/*…*/
    PT_END(pt);
  }
  int ProtothreadTaskC(struct pt *pt) {
    PT_BEGIN(pt);
    TASKC_STEP(pt);/*如果不夠1步執(zhí)行,則阻塞,讓出執(zhí)行權(quán)限*/
    TaskC_1();/*TaskB任務(wù)的第1步*/
    TASKC_STEP(pt);
    TaskC_2();/*TaskB任務(wù)的第2步*/
    TASKC_STEP(pt);
    TaskC_3();/*…*/
    TASKC_STEP(pt);
    TaskC_4();
    PT_END(pt);
  }
  void main(void) {/*系統(tǒng)初始化*/?
    PT_INIT(&TaskAPt);
    PT_INIT(&TaskBPt);
    PT_INIT(&TaskCPt);
    PT_SEM_INIT(&SemRunTaskA,1);
    PT_SEM_INIT(&SemRunTaskB,1);/*運(yùn)行任務(wù)*/
    while(1) {
      ProtothreadTaskA(&TaskAPt);
      ProtothreadTaskB(&TaskBPt);
      ProtothreadTaskC(&TaskCPt);
    }
  }  

模擬運(yùn)行結(jié)果如表1所列。運(yùn)行結(jié)果顯示,3個(gè)任務(wù)的運(yùn)行情況完全滿足系統(tǒng)的設(shè)計(jì)要求。從資源需求來(lái)看,完成此例的系統(tǒng)設(shè)計(jì),共需要12個(gè)字節(jié)的RAM空間。筆者進(jìn)一步對(duì)Protothread定義文件做了少許修改和優(yōu)化,最終僅耗費(fèi)6個(gè)字節(jié)。

結(jié)語(yǔ)

本文旨在解決資源緊張型應(yīng)用的、多任務(wù)環(huán)境下的實(shí)時(shí)性問(wèn)題。 通過(guò)借助Protothread的阻塞運(yùn)行機(jī)制, 成功實(shí)現(xiàn)了低開(kāi)銷(xiāo)的實(shí)時(shí)多任務(wù)系統(tǒng)。
表1  模擬運(yùn)行結(jié)果運(yùn)行

參考文獻(xiàn)
[1]  Adam Dunkels, Oliver Schmidt, Thiemo Voigt. Using Protothreads for Sensor Node Programming[C]. REALWSN'05 Workshop on RealWorld Wireless Sensor Networks, Stockholm, Sweden, June 2005
[2]  Adam Dunkels, Oliver Schmidt, Thiemo Voigt, et al. Protothreads: Simplifying EventDriven Programming of MemoryConstrained Embedded Systems[C]. In Proceedings of the Fourth ACM Conference on Embedded Networked Sensor Systems (SenSys 2006), Boulder, Colorado, USA, November 2006.
[3]  Labrosse Jean J. MicroC/OSII The Real Time Kernel Second Edition[M]. CMP Books, CMP Media.
[4]  冉全. 單片機(jī)中基于多線程機(jī)制的實(shí)時(shí)多任務(wù)研究[J] .微型機(jī)與應(yīng)用,2003(8): 39-40.
 

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

在現(xiàn)代計(jì)算環(huán)境中,多任務(wù)系統(tǒng)已成為常態(tài)。無(wú)論是桌面操作系統(tǒng)、服務(wù)器系統(tǒng)還是嵌入式系統(tǒng),都需要同時(shí)處理多個(gè)任務(wù),以滿足用戶或系統(tǒng)的需求。在多任務(wù)系統(tǒng)中,CPU利用率是衡量系統(tǒng)性能的重要指標(biāo)之一。本文將探討如何統(tǒng)計(jì)CPU利用...

關(guān)鍵字: 多任務(wù)系統(tǒng) CPU

提供Zigbee兼容性平臺(tái)認(rèn)證、Matter 1.4認(rèn)證和Thread認(rèn)證相關(guān)服務(wù) 深圳2024年11月22日 /美通社/ -- 日前,國(guó)際獨(dú)立第三方檢測(cè)、檢驗(yàn)和認(rèn)證機(jī)構(gòu)德...

關(guān)鍵字: 物聯(lián)網(wǎng) 測(cè)試 Zigbee THREAD

本文轉(zhuǎn)載自公眾號(hào)Java技術(shù)棧我們都知道,Java目前最小的系統(tǒng)調(diào)度單元只支持線程,官方是不支持協(xié)程的,但可以通過(guò)第三方框架實(shí)現(xiàn),估計(jì)也很少有人會(huì)用吧,多線程就能滿足需求。好消息來(lái)了,不久的將來(lái),Java要開(kāi)始支持協(xié)程了...

關(guān)鍵字: JAVA THREAD VIRTUAL FACTORY

↓推薦關(guān)注↓前言堆內(nèi)存(HeapMemory)是一個(gè)很有意思的領(lǐng)域。你可能和我一樣,也困惑于下述問(wèn)題很久了:如何從內(nèi)核申請(qǐng)堆內(nèi)存?誰(shuí)管理它??jī)?nèi)核、庫(kù)函數(shù),還是應(yīng)用本身??jī)?nèi)存管理效率怎么這么高?!堆內(nèi)存的管理效率可以進(jìn)一步...

關(guān)鍵字: 分配器 內(nèi)存分配 BSP THREAD

synchronized簡(jiǎn)介 synchronized 是Java語(yǔ)言的一個(gè)關(guān)鍵字,它本身的意思為同步,是用來(lái)保證線程安全的,可用來(lái)給對(duì)象和方法或者代碼塊加鎖,當(dāng)它鎖定一個(gè)方法或者一個(gè)代碼塊的時(shí)候,同一時(shí)刻最多只有一個(gè)線...

關(guān)鍵字: SYNCHRONIZED 代碼 THREAD 內(nèi)存

不知道你是否遇到過(guò)面試官讓你手寫(xiě)生產(chǎn)者消費(fèi)者代碼。別說(shuō),前段時(shí)間有小伙伴還真的遇到了這種情況,當(dāng)時(shí)是一臉懵逼。 但是,俗話說(shuō),從哪里跌倒就要從哪里爬起來(lái)。既然這次被問(wèn)到了,那就回去好好研究一下,爭(zhēng)取下一次不再被虐唄。 于...

關(guān)鍵字: BSP QUEUE PUBLIC THREAD

Web3 Foundation 是 Polkadot 背后的主要組織機(jī)構(gòu),為多個(gè)客戶端的實(shí)現(xiàn)提供資金,并通過(guò)舉辦活動(dòng)和大使計(jì)劃來(lái)發(fā)展波卡社區(qū),同時(shí)與項(xiàng)目合作,以建立和擴(kuò)展 Polkadot。We

關(guān)鍵字: 智能合約 ADS THREAD AI

? 前言 最近和一個(gè)工作了7年的朋友聊天,他跟我說(shuō)起了他去XXX公司面試的情況,面試官的一個(gè)問(wèn)題把他打懵了!竟然問(wèn)他:你經(jīng)常使用Thread類(lèi)創(chuàng)建線程,那你看過(guò)Thread類(lèi)的源碼嗎?Thread類(lèi)創(chuàng)建線程的流程是什么?...

關(guān)鍵字: THREAD BSP 線程 PUBLIC

物聯(lián)網(wǎng)讓我們看到了一個(gè)更加美好的未來(lái):冰箱可以自動(dòng)訂購(gòu)食物、橋梁可以提醒汽車(chē)注意路面結(jié)冰,或者智能設(shè)備,可以監(jiān)測(cè)個(gè)人的健康狀況,并將實(shí)時(shí)數(shù)據(jù)發(fā)送到醫(yī)生手機(jī)上。盡管所有這些可能很快到來(lái),但我們?nèi)匀?/p> 關(guān)鍵字: 物聯(lián)網(wǎng) 物聯(lián)網(wǎng)技術(shù) SIGFOX THREAD

物聯(lián)網(wǎng)讓我們看到了一個(gè)更加美好的未來(lái):冰箱可以自動(dòng)訂購(gòu)食物、橋梁可以提醒汽車(chē)注意路面結(jié)冰,或者智能設(shè)備,可以監(jiān)測(cè)個(gè)人的健康狀況,并將實(shí)時(shí)數(shù)據(jù)發(fā)送到醫(yī)生手機(jī)上。盡管所有這些可能很快到來(lái),但我們?nèi)匀?/p> 關(guān)鍵字: 物聯(lián)網(wǎng)技術(shù) SIGFOX THREAD Zigbee

關(guān)閉