一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

如何在嵌入式中使用設(shè)計(jì)模式的思想?

STM32嵌入式開(kāi)發(fā) ? 來(lái)源:CSDN ? 2023-08-09 16:15 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

嵌入式

嵌入式的標(biāo)簽多為:低配,偏硬件,底層,資源緊張,代碼多以C語(yǔ)言,匯編為主,代碼應(yīng)用邏輯簡(jiǎn)單。但隨著AIOT時(shí)代的到來(lái),局面組件改變。芯片的性能資源逐漸提升,業(yè)務(wù)邏輯也逐漸變得復(fù)雜,相對(duì)于代碼的效率而言,代碼的復(fù)用可移植性要求越來(lái)越高,以獲得更短的項(xiàng)目周期 和更高的可維護(hù)性。下面是AIOT時(shí)代嵌入式設(shè)備的常見(jiàn)的軟件框架。72092d50-368b-11ee-9e74-dac502259ad0.png

設(shè)計(jì)模式

設(shè)計(jì)模式的標(biāo)簽:高級(jí)語(yǔ)言 ,高端,架構(gòu)等。在AIOT時(shí)代,設(shè)計(jì)模式與嵌入式能擦出怎樣的火花?設(shè)計(jì)模式可描述為:對(duì)于某類相似的問(wèn)題,經(jīng)過(guò)前人的不斷嘗試,總結(jié)出了處理此類問(wèn)題的公認(rèn)的有效解決辦法。嵌入式主要以C語(yǔ)言開(kāi)發(fā),且面向過(guò)程,而設(shè)計(jì)模式常見(jiàn)于高級(jí)語(yǔ)言(面向?qū)ο螅?,目前市面上描述設(shè)計(jì)模式的書(shū)籍多數(shù)使用JAVA 語(yǔ)言,C語(yǔ)言能實(shí)現(xiàn)設(shè)計(jì)模式嗎?設(shè)計(jì)模式與語(yǔ)言無(wú)關(guān),它是解決問(wèn)題的方法,JAVA可以實(shí)現(xiàn),C語(yǔ)言同樣可以實(shí)現(xiàn)。同樣的,JAVA程序員會(huì)遇到需要用模式來(lái)處理的問(wèn)題,C程序員也可能遇見(jiàn),因此設(shè)計(jì)模式是很有必要學(xué)習(xí)的。模式陷阱:設(shè)計(jì)模式是針對(duì)具體的某些類問(wèn)題的有效解決辦法,不是所有的問(wèn)題都能匹配到對(duì)應(yīng)的設(shè)計(jì)模式。因此,不能一味的追求設(shè)計(jì)模式,有時(shí)候簡(jiǎn)單直接的處理反而更有效。有的問(wèn)題沒(méi)有合適的模式,可以盡量滿足一些設(shè)計(jì)原則,如開(kāi)閉原則(對(duì)擴(kuò)展開(kāi)放,對(duì)修改關(guān)閉)
觀察者模式
情景在對(duì)象之間定義一個(gè)一對(duì)多的依賴,當(dāng)一個(gè)對(duì)象狀態(tài)改變的時(shí)候,所有依賴的對(duì)象都會(huì)自動(dòng)收到通知。7218cf44-368b-11ee-9e74-dac502259ad0.png實(shí)現(xiàn)

主題對(duì)象提供統(tǒng)一的注冊(cè)接口,以及注冊(cè)函數(shù) 。由觀察者本身實(shí)例化observer_intf 接口,然后使用注冊(cè)函數(shù),添加到對(duì)應(yīng)的主題列表中,主題狀態(tài)發(fā)生改變,依次通知列表中的所有對(duì)象。


	
 struct observer_ops
 {
     void*(handle)(uint8_t evt);  
 };
 struct observer_intf
 {
     struct observer_intf* next;
     const char* name;
     void* condition;
     const struct observer_ops *ops;
 }
intobserver_register(structtopical*top,structobserver_intf*observer);

	

當(dāng)主題狀態(tài)發(fā)生改變,將通知到所有觀察者,觀察者本身也可以設(shè)置條件,是否選擇接收通知。

 struct observer_intf observer_list;
     
 void XXXX_topical_evt(uint8_t evt)
{
      struct observer_intf* cur_observer = observer_list.next;
      uint8_t* condition = NULL;
      while(cur_observer != NULL)
      {
          condition = (uint8_t*)cur_observer->condition;
          if(NULL == condition || (condition && *condition))
          {
              if(cur_observer->ops->handle){
                  cur_observer->ops->handle(evt);
              }       
          }
          cur_observer = cur_observer->next;
      }
 }

	實(shí)例:嵌入式裸機(jī)低功耗框架
  • 設(shè)備功耗分布
723e857c-368b-11ee-9e74-dac502259ad0.png其中線路損耗,電源電路等軟件無(wú)法控制,故不討論。板載外設(shè),如傳感器可能通過(guò)某條命令配置進(jìn)入低功耗模式,又或者硬件上支持控制外設(shè)電源來(lái)控制功耗。片內(nèi)外設(shè),及芯片內(nèi)部的外設(shè),通過(guò)卸載相關(guān)驅(qū)動(dòng),關(guān)閉時(shí)鐘配置工作模式來(lái)控制功耗。
  • 設(shè)備喚醒方式當(dāng)系統(tǒng)某個(gè)定時(shí)事件到來(lái)時(shí),系統(tǒng)被主動(dòng)喚醒處理事件系統(tǒng)處于睡眠,被外部事件喚醒,如串口接收到一包數(shù)據(jù),傳感器檢測(cè)到變化,通過(guò)引腳通知芯片
    • 被動(dòng)喚醒
    • 主動(dòng)喚醒
  • 系統(tǒng)允許睡眠的條件
    • 外設(shè)無(wú)正在收發(fā)的數(shù)據(jù)
    • 緩存無(wú)需要處理的數(shù)據(jù)
    • 應(yīng)用層狀態(tài)處于空閑(無(wú)需要處理的事件)
  • 基于觀察者模式的PM框架實(shí)現(xiàn)

PM組件提供的接口:

struct pm
{
    struct pm* next;
    const char* name;
   void(*init)(void);
    void(*deinit(void);
    void* condition;
};
static struct pm pm_list;
static uint8_t pm_num;
static uint8_t pm_status;
         
int pm_register(const struct pm* pm , const char* name)
{
     struct pm* cur_pm =  &pm_list;
     while(cur_pm->next)
     {
         cur_pm = cur_pm->next;
     }
     cur_pm->next = pm;
     pm->next = NULL;
     pm->name = name;
     pm_num++;
}
 
void pm_loop(void)
{
    uint32_t pm_condition = 0;
    struct pm* cur_pm =  pm_list.next;
    static uint8_t cnt;
    
    /*check all condition*/
    while(cur_pm)
    {
        if(cur_pm->condition){
         pm_condition |=  *((uint32_t*)(cur_pm->condition));
        }
        cur_pm = cur_pm->next;
    }
    if(pm_condition == 0)
    {
      cnt++;
        if(cnt>=5)
        {
            pm_status = READY_SLEEP;
        }
    }
    else
    {
        cnt = 0;
    }
    if( pm_status == READY_SLEEP)
    {
         cur_pm =  pm_list.next;
         while(cur_pm)
         {
             if(cur_pm->deinit){
                cur_pm->deinit();
             }
             cur_pm = cur_pm->next;
         }
        pm_status = SLEEP;
        ENTER_SLEEP_MODE();
    }   
    /*sleep--->wakeup*/
    if(pm_status == SLEEP)
    {
         pm_status = NORMAL;
         cur_pm =  pm_list.next;
         while(cur_pm)
         {
             if(cur_pm->init){
                cur_pm->init();
             }
             cur_pm = cur_pm->next;
         }
    }
}

	

外設(shè)使用PM接口:


	
struct uart_dev
{
 ...
 struct pm pm;
    uint32_t pm_condition; 
};
struct uart_dev uart1;
 
void hal_uart1_init(void);
void hal_uart1_deinit(void);
    
void uart_init(void)
{
    uart1.pm.init =  hal_uart1_init;
    uart1.pm.deinit =  hal_uart1_deinit;
    uart1.pm.condition = &uart1.pm_condition;
    pm_register(&uart1.pm , "uart1");
}
/*接下來(lái)串口驅(qū)動(dòng)檢查緩存 , 發(fā)送 , 接收是否空閑或者忙碌 , 給uart1.pm_condition賦值*/



結(jié)論
  • PM 電源管理可以單獨(dú)形成模塊,當(dāng)功耗外設(shè)增加時(shí),只需實(shí)現(xiàn)接口,注冊(cè)即可
  • 通過(guò)定義段導(dǎo)出操作,可以更加簡(jiǎn)化應(yīng)用層或外設(shè)的注冊(cè)邏輯
  • 方便調(diào)試,可以很方便打印出系統(tǒng)當(dāng)前為滿足睡眠條件的模塊
  • 通過(guò)條件字段劃分,應(yīng)該可以實(shí)現(xiàn)系統(tǒng)部分睡眠
職責(zé)鏈模式
情景在現(xiàn)實(shí)生活中,一個(gè)事件(任務(wù))需要經(jīng)過(guò)多個(gè)對(duì)象處理是很常見(jiàn)的場(chǎng)景。如報(bào)銷流程,公司員工報(bào)銷, 首先員工整理報(bào)銷單,核對(duì)報(bào)銷金額,有誤則繼續(xù)核對(duì)整理,直到無(wú)誤,將報(bào)銷單遞交到財(cái)務(wù),財(cái)務(wù)部門(mén)進(jìn)行核對(duì),核對(duì)無(wú)誤后,判斷金額數(shù)量,若小于一定金額,則財(cái)務(wù)部門(mén)可直接審批,若金額超過(guò)范圍,則報(bào)銷單流傳到總經(jīng)理,得到批準(zhǔn)后,整個(gè)任務(wù)才算結(jié)束。類似的情景還有很多,如配置一個(gè)WIFI模塊,通過(guò)AT指令,要想模塊正確連入WIFI , 需要按一定的順序依次發(fā)送配置指令 , 如設(shè)置設(shè)置模式 ,設(shè)置 需要連接的WIFI名,密碼,每發(fā)送一條配置指令,模塊都將返回配置結(jié)果,而發(fā)送者需要判斷結(jié)果的正確性,再選擇是否發(fā)送下一條指令或者進(jìn)行重傳。總結(jié)起來(lái)是,一系列任務(wù)需要嚴(yán)格按照時(shí)間線依次處理的順序邏輯,如下圖所示:

7244a04c-368b-11ee-9e74-dac502259ad0.png

在存在系統(tǒng)的情況下,此類邏輯可以很容易的用阻塞延時(shí)來(lái)實(shí)現(xiàn),實(shí)現(xiàn)如下:

void process_task(void)
{
    task1_process();
    msleep(1000);
    
    task2_process();
    mq_recv(&param , 1000);
    
    task3_process();
    while(mq_recv(¶m , 1000) != OK)
    {
        if(retry)
        {
             task3_process();
             --try;
        }
    }
}

	

在裸機(jī)的情況下,為了保證系統(tǒng)的實(shí)時(shí)性,無(wú)法使用阻塞延時(shí),一般使用定時(shí)事件配合狀態(tài)機(jī)來(lái)實(shí)現(xiàn):

void process_task(void)
{
     switch(task_state)
     {
         case task1:
             task1_process();
             set_timeout(1000);break;
         case task2:
             task1_process();
             set_timeout(1000);break;
         case task3:
             task1_process();
             set_timeout(1000)break;
         default:break;
     }
}
/*定時(shí)器超時(shí)回調(diào)*/
void timeout_cb(void)
{
    if(task_state == task1)
    {
        task_state = task2;
        process_task();
    }
    else  //task2 and task3
    {
        if(retry)
        {
            retry--;
             process_task();
        }
    }
}
/*任務(wù)的應(yīng)答回調(diào)*/
void task_ans_cb(void* param)
{
    if(task==task2)
    {
        task_state = task3;
        process_task();
    }
}

	和系統(tǒng)實(shí)現(xiàn)相比,裸機(jī)的實(shí)現(xiàn)更加復(fù)雜,為了避免阻塞,只能通過(guò)狀態(tài)和定時(shí)器來(lái)實(shí)現(xiàn)順序延時(shí)的邏輯,可以看到,實(shí)現(xiàn)過(guò)程相當(dāng)分散,對(duì)于單個(gè)任務(wù)的處理分散到了3個(gè)函數(shù)中處理,這樣導(dǎo)致的后果是:修改,移植的不便。而實(shí)際的應(yīng)用中,類似的邏輯相當(dāng)多,如果按照上面的方法去實(shí)現(xiàn),將會(huì)導(dǎo)致應(yīng)用程序的強(qiáng)耦合實(shí)現(xiàn)可以發(fā)現(xiàn),上面的情景有以下特點(diǎn):
  • 任務(wù)按順序執(zhí)行,只有當(dāng)前任務(wù)執(zhí)行完了(有結(jié)論,成功或者失敗)才允許執(zhí)行下一個(gè)任務(wù)
  • 前一個(gè)任務(wù)的執(zhí)行結(jié)果會(huì)影響到下一個(gè)任務(wù)的執(zhí)行情況
  • 任務(wù)有一些特性,如超時(shí)時(shí)間,延時(shí)時(shí)間,重試次數(shù)
通過(guò)以上信息,我們可以抽象出這樣一個(gè)模型:任務(wù)作為節(jié)點(diǎn), 每一個(gè)任務(wù)節(jié)點(diǎn)有其屬性:如超時(shí),延時(shí),重試,參數(shù),處理方法,執(zhí)行結(jié)果。當(dāng)需要按照順序執(zhí)行一系列任務(wù)時(shí),依次將任務(wù)節(jié)點(diǎn)串成一條鏈,啟動(dòng)鏈運(yùn)行,則從任務(wù)鏈的第一個(gè)節(jié)點(diǎn)開(kāi)始運(yùn)行,運(yùn)行的結(jié)果可以是 OK , BUSY ,ERROR 。若是OK, 表示節(jié)點(diǎn)已處理,從任務(wù)鏈中刪除,ERROR 表示運(yùn)行出錯(cuò),任務(wù)鏈將停止運(yùn)行,進(jìn)行錯(cuò)誤回調(diào),可以有用戶決定是否繼續(xù)運(yùn)行下去。BUSY表示任務(wù)鏈處于等待應(yīng)答,或者等待延時(shí)的情況。當(dāng)整條任務(wù)鏈上的節(jié)點(diǎn)都執(zhí)行完,進(jìn)行成功回調(diào)。

725f54b4-368b-11ee-9e74-dac502259ad0.png

node數(shù)據(jù)結(jié)構(gòu)定義:

/*shadow node api type for req_chain src*/
typedef struct shadow_resp_chain_node
{
 uint16_t timeout;
 uint16_t duration;
 uint8_t init_retry;
 uint8_t param_type;
 uint16_t retry;
 /*used in mpool*/
   struct shadow_resp_chain_node* mp_prev;
 struct shadow_resp_chain_node* mp_next;
 
    /*used resp_chain*/
 struct shadow_resp_chain_node* next;
 
 node_resp_handle_fp handle;
 void* param;
}shadow_resp_chain_node_t;
node內(nèi)存池:使用內(nèi)存池的必要性:實(shí)際情況下,同一時(shí)間,責(zé)任鏈的條數(shù),以及單條鏈的節(jié)點(diǎn)數(shù)比較有限,但種類是相當(dāng)多的。比如一個(gè)支持AT指令的模塊,可能支持幾十條AT指令,但執(zhí)行一個(gè)配置操作,可能就只會(huì)使用3-5條指令,若全部靜態(tài)定義節(jié)點(diǎn),將會(huì)消耗大量?jī)?nèi)存資源。因此動(dòng)態(tài)分配是必要的。72821ab2-368b-11ee-9e74-dac502259ad0.png初始化node內(nèi)存池,內(nèi)存池內(nèi)所有節(jié)點(diǎn)都將添加到free_list。當(dāng)申請(qǐng)節(jié)點(diǎn)時(shí),會(huì)取出第一個(gè)空閑節(jié)點(diǎn),加入到used_list , 并且接入到責(zé)任鏈。當(dāng)責(zé)任鏈某一個(gè)節(jié)點(diǎn)執(zhí)行完,將會(huì)被自動(dòng)回收(從責(zé)任鏈中刪除,并從used_list中刪除,然后添加到free_list)

職責(zé)鏈數(shù)據(jù)結(jié)構(gòu)定義:

typedef struct resp_chain
{
   bool enable;               //enble == true 責(zé)任鏈啟動(dòng) 
 bool  is_ans;              //收到應(yīng)答,與void* param 共同組成應(yīng)答信號(hào)
 
 uint8_t state;            
 const char* name;
 void* param;
 TimerEvent_t timer;
 bool timer_is_running;
 shadow_resp_chain_node_t node;        //節(jié)點(diǎn)鏈
 void(*resp_done)(void* result);       //執(zhí)行結(jié)果回調(diào)
}resp_chain_t;

	

職責(zé)鏈初始化:

void resp_chain_init(resp_chain_t* chain ,  const char* name , 
                                            void(*callback)(void* result))                   
{
   RESP_ASSERT(chain);
 /*only init one time*/
 resp_chain_mpool_init();
 
   chain->enable = false;
 chain->is_ans = false;
 chain->resp_done = callback;
 chain->name = name;
 
 chain->state = RESP_STATUS_IDLE;
 chain->node.next = NULL;
 chain->param = NULL;
 
 TimerInit(&chain->timer,NULL);
}

	

職責(zé)鏈添加節(jié)點(diǎn):

int resp_chain_node_add(resp_chain_t* chain , 
                        node_resp_handle_fp handle , void* param)
{
   RESP_ASSERT(chain);
 BoardDisableIrq();  
 shadow_resp_chain_node_t* node = chain_node_malloc();
 if(node == NULL)
 {
    BoardEnableIrq();
    RESP_LOG("node malloc error ,no free node");
  return -2;
 }
 /*初始化節(jié)點(diǎn),并加入責(zé)任鏈*/
 shadow_resp_chain_node_t* l = &chain->node;
 while(l->next != NULL)
 {
  l = l->next;
 }
 l->next = node;
 node->next = NULL; 
 node->handle = handle;
 node->param = param;
 node->timeout = RESP_CHIAN_NODE_DEFAULT_TIMEOUT;
 node->duration = RESP_CHIAN_NODE_DEFAULT_DURATION;
 node->init_retry = RESP_CHIAN_NODE_DEFAULT_RETRY;
 node->retry = (node->init_retry == 0)? 0 :(node->init_retry-1);
 BoardEnableIrq();
 return 0;
}

	

職責(zé)鏈的啟動(dòng):

void resp_chain_start(resp_chain_t* chain)
{
   RESP_ASSERT(chain);
 chain->enable = true;
}

	

職責(zé)鏈的應(yīng)答:

void resp_chain_set_ans(resp_chain_t* chain , void* param)
{
 RESP_ASSERT(chain);
   if(chain->enable)
 {
  chain->is_ans = true;
  if(param != NULL)
     chain->param = param;
  else
  {
   chain->param = "NO PARAM";
  }
 }
}

	

職責(zé)鏈的運(yùn)行:

int resp_chain_run(resp_chain_t* chain)
{ 
 RESP_ASSERT(chain);
 if(chain->enable)
 {
    shadow_resp_chain_node_t* cur_node = chain->node.next;
    /*maybe ans occur in handle,so cannot change state direct when ans comming*/
    if(chain->is_ans)
  {
   chain->is_ans = false;
   chain->state = RESP_STATUS_ANS;
  }  
   
  switch(chain->state)
  {
   case RESP_STATUS_IDLE:
   {
    if(cur_node)
    {
       uint16_t retry = cur_node->init_retry;
     if(cur_node->handle)
     {
        cur_node->param_type = RESP_PARAM_INPUT;
      chain->state = cur_node->handle((resp_chain_node_t*)cur_node                                                               ,cur_node->param);
     }
     else
     {
         RESP_LOG("node handle is null ,goto next node");
      chain->state = RESP_STATUS_OK;
     }
     if(retry != cur_node->init_retry)
     {
      cur_node->retry = cur_node->init_retry>0?(cur_node-                                                      >init_retry-1):0;                       
     }
    }
    else
    {
       if(chain->resp_done)
     {
      chain->resp_done((void*)RESP_RESULT_OK);
     }
     chain->enable = 0;
     chain->state = RESP_STATUS_IDLE;
     TimerStop(&chain->timer);
     chain->timer_is_running  = false;
    }
    break;
   }
   case RESP_STATUS_DELAY:
   {
    if(chain->timer_is_running == false)
    {
       chain->timer_is_running  = true;
     TimerSetValueStart(&chain->timer , cur_node->duration);
    }
    if(TimerGetFlag(&chain->timer) == true)
    {
     chain->state = RESP_STATUS_OK;
     chain->timer_is_running  = false;
    }
     break; 
   }
   case RESP_STATUS_BUSY:
   {
      /*waiting for ans or timeout*/
      if(chain->timer_is_running == false)
    {
       chain->timer_is_running  = true;
     TimerSetValueStart(&chain->timer , cur_node->timeout);
    }
    if(TimerGetFlag(&chain->timer) == true)
    {
     chain->state = RESP_STATUS_TIMEOUT;
     chain->timer_is_running  = false;
    }
    break;
      }
   case RESP_STATUS_ANS:
     {
      /*already got the ans,put the param back to the request handle*/
      TimerStop(&chain->timer);
    chain->timer_is_running  = false;
    if(cur_node->handle)
    {
     cur_node->param_type = RESP_PARAM_ANS;
     chain->state = cur_node->handle((resp_chain_node_t*)cur_node ,                                                                 chain->param);
    }
    else
    {
     RESP_LOG("node handle is null ,goto next node");
     chain->state = RESP_STATUS_OK;
    }
    break;
   }
   case RESP_STATUS_TIMEOUT:
   {
    if(cur_node->retry)
    {
     cur_node->retry--; 
     /*retry to request until cnt is 0*/
     chain->state = RESP_STATUS_IDLE;
    }
    else
    {
     chain->state = RESP_STATUS_ERROR;
    }
    break;
   }
   case RESP_STATUS_ERROR:
   {
      if(chain->resp_done)
    {
       chain->resp_done((void*)RESP_RESULT_ERROR);
    }
    chain->enable = 0;
    chain->state = RESP_STATUS_IDLE;
    TimerStop(&chain->timer);
    chain->timer_is_running  = false;
    cur_node->retry = cur_node->init_retry>0?(cur_node->init_retry-1):0;
    chain_node_free_all(chain);
    break;
   }
   case RESP_STATUS_OK:
   {
      /*get the next node*/
      cur_node->retry = cur_node->init_retry>0?(cur_node->init_retry-1):0;
    chain_node_free(cur_node);
    chain->node.next = chain->node.next->next;
    chain->state = RESP_STATUS_IDLE;
    break;
   }
      default:
     break;
  }
 }
 return chain->enable;
}

	

測(cè)試用例:

  • 定義并初始化責(zé)任鏈
void chain_test_init(void)
{
    resp_chain_init(&test_req_chain , "test request" , test_req_callback);
}

	
  • 定義運(yùn)行函數(shù),在主循環(huán)中調(diào)用
void chain_test_run(void)
{
    resp_chain_run(&test_req_chain);
}

	
  • 測(cè)試節(jié)點(diǎn)添加并啟動(dòng)觸發(fā)函數(shù)
void chain_test_tigger(void)
{
    resp_chain_node_add(&test_req_chain ,  node1_req ,NULL);
    resp_chain_node_add(&test_req_chain ,  node2_req,NULL);
    resp_chain_node_add(&test_req_chain ,  node3_req,NULL);
    resp_chain_start(&test_req_chain);
}

	
  • 分別實(shí)現(xiàn)節(jié)點(diǎn)請(qǐng)求函數(shù)
 /*延時(shí)1s 后執(zhí)行下一個(gè)節(jié)點(diǎn)*/
 int node1_req(resp_chain_node_t* cfg, void* param)
{
     cfg->duration = 1000;
     RESP_LOG("node1 send direct request: delay :%d ms" , cfg->duration);
     return RESP_STATUS_DELAY;
 }
 /*超時(shí)時(shí)間1S , 重傳次數(shù)5次*/ 
 int node2_req(resp_chain_node_t* cfg , void* param)
{
     static uint8_t cnt;
     if(param == NULL)
     {
         cfg->init_retry = 5;
         cfg->timeout  = 1000;
         RESP_LOG("node2 send request max retry:%d , waiting for ans...");
         return RESP_STATUS_BUSY;
     }
     RESP_LOG("node2 get ans: %d",(int)param);
     return RESP_STATUS_OK;
 }
 /*非異步請(qǐng)求*/  
 int node3_req(resp_chain_node_t* cfg , void* param)
{
     RESP_LOG("node4 send direct request");
     return RESP_STATUS_OK;
 }
 
 void ans_callback(void* param)
{
     resp_chain_set_ans(&test_req_chain , param);
 }

	結(jié)論
  • 實(shí)現(xiàn)了裸機(jī)處理 順序延時(shí)任務(wù)
  • 較大程度的簡(jiǎn)化了應(yīng)用程的實(shí)現(xiàn),用戶只需要實(shí)現(xiàn)響應(yīng)的處理函數(shù) , 調(diào)用接口添加,即可按時(shí)間要求執(zhí)行
  • 參數(shù)為空,表明為請(qǐng)求 ,否則為應(yīng)答。(在某些場(chǎng)合,請(qǐng)求可能也帶參數(shù),如接下來(lái)所說(shuō)的LAP協(xié)議,此時(shí)需要通過(guò)判斷參數(shù)的類型)
設(shè)計(jì)模式參考Head First 設(shè)計(jì)模式(中文版)人人都懂設(shè)計(jì)模式:從生活中領(lǐng)悟設(shè)計(jì)模式:Python實(shí)現(xiàn)設(shè)計(jì)模式之禪設(shè)計(jì)模式的C語(yǔ)言應(yīng)用.https://bbs.huaweicloud.com/blogs/113179適配器模式


聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 芯片
    +關(guān)注

    關(guān)注

    460

    文章

    52520

    瀏覽量

    441134
  • 嵌入式
    +關(guān)注

    關(guān)注

    5152

    文章

    19675

    瀏覽量

    317691
  • C語(yǔ)言
    +關(guān)注

    關(guān)注

    180

    文章

    7632

    瀏覽量

    141812

原文標(biāo)題:如何在嵌入式中使用設(shè)計(jì)模式的思想?

文章出處:【微信號(hào):c-stm32,微信公眾號(hào):STM32嵌入式開(kāi)發(fā)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    深入了解嵌入式編程

    能從PC機(jī)器編程去看嵌入式問(wèn)題,那是第一步;學(xué)會(huì)用嵌入式編程思想,那是第二步;用PC的思想嵌入式思想
    的頭像 發(fā)表于 10-18 09:56 ?3968次閱讀

    何在嵌入式系統(tǒng)設(shè)計(jì)中使用UML技術(shù)

    嵌入式系統(tǒng)設(shè)計(jì)是一個(gè)軟、硬件結(jié)合的協(xié)同設(shè)計(jì)(Hardware/Software Co-design),需要不同技術(shù)背景的人共同開(kāi)發(fā)。 本文將重點(diǎn)討論如何在嵌入式系統(tǒng)設(shè)計(jì)中使用 UML
    發(fā)表于 04-14 08:02 ?4168次閱讀
    如<b class='flag-5'>何在</b><b class='flag-5'>嵌入式</b>系統(tǒng)設(shè)計(jì)<b class='flag-5'>中使</b>用UML技術(shù)

    怎么利用分層思想進(jìn)行嵌入式項(xiàng)目設(shè)計(jì)

    利用分層思想進(jìn)行嵌入式項(xiàng)目設(shè)計(jì),你試過(guò)嗎?
    發(fā)表于 05-22 10:16

    嵌入式開(kāi)發(fā)必須掌握的設(shè)計(jì)思想?

    嵌入式開(kāi)發(fā)重要的2個(gè)設(shè)計(jì)思想
    發(fā)表于 03-09 07:02

    何在嵌入式系統(tǒng)設(shè)計(jì)中使用UML技術(shù)?

    統(tǒng)一建模語(yǔ)言UML及其特點(diǎn)UML在車載GPS終端設(shè)計(jì)中的應(yīng)用如何在嵌入式系統(tǒng)設(shè)計(jì)中使用UML技術(shù)
    發(fā)表于 04-23 06:26

    何在嵌入式系統(tǒng)設(shè)計(jì)中使用UML技術(shù)?

    何在嵌入式系統(tǒng)設(shè)計(jì)中使用UML技術(shù)?怎樣去設(shè)計(jì)嵌入式系統(tǒng)?
    發(fā)表于 04-26 07:14

    嵌入式系統(tǒng)硬件抽象層的設(shè)計(jì)思想簡(jiǎn)析

    嵌入式系統(tǒng)硬件抽象層(HAL & BSP)的設(shè)計(jì)思想1 前言1.1 層次化思想1.2 模塊化思想1.3 對(duì)象化思想2 板級(jí)支持包(BSP)3
    發(fā)表于 02-11 07:49

    何在嵌入式設(shè)備上運(yùn)行高性能Java

    何在嵌入式設(shè)備上運(yùn)行高性能Java
    發(fā)表于 03-28 09:43 ?16次下載

    嵌入式DHCP Server如何在vxWorks中

    嵌入式DHCP Server如何在vxWorks中的軟件實(shí)現(xiàn)
    發(fā)表于 03-29 12:27 ?23次下載

    基于AVR單片機(jī)的嵌入式“瘦服務(wù)器”系統(tǒng)設(shè)計(jì)思想

    基于AVR單片機(jī)的嵌入式“瘦服務(wù)器”系統(tǒng)設(shè)計(jì)思想 根據(jù)國(guó)內(nèi)嵌入式設(shè)備的研究形勢(shì)和產(chǎn)業(yè)發(fā)展規(guī)模,提出了基于AVR單片機(jī)(ATmega103)的嵌入式 “瘦
    發(fā)表于 05-04 22:10 ?974次閱讀
    基于AVR單片機(jī)的<b class='flag-5'>嵌入式</b>“瘦服務(wù)器”系統(tǒng)設(shè)計(jì)<b class='flag-5'>思想</b>

    嵌入式系統(tǒng)中使用FPGA時(shí)的常見(jiàn)問(wèn)題及對(duì)策

    電子發(fā)燒友網(wǎng)核心提示 :在嵌入式系統(tǒng)中使用FPGA時(shí)會(huì)經(jīng)常出現(xiàn)以下常見(jiàn)問(wèn)題,如在嵌入式設(shè)計(jì)中,怎樣使用FPGA、在嵌入式設(shè)計(jì)中,怎樣采用FPGA進(jìn)行設(shè)計(jì)來(lái)降低風(fēng)險(xiǎn)等。今天電子發(fā)燒友
    發(fā)表于 10-17 13:38 ?1175次閱讀

    何在嵌入式Linux中使用GPIO

    了解如何在嵌入式Linux中使用GPIO,特別強(qiáng)調(diào)Zynq-7000系列。 我們介紹了基本的用戶和內(nèi)核空間GPIO使用情況,以及GPIO,GPIO密鑰和GPIO LED上的bit-banged I / O.
    的頭像 發(fā)表于 11-26 07:02 ?4334次閱讀

    嵌入式系統(tǒng)系列叢書(shū)-時(shí)間觸發(fā)嵌入式系統(tǒng)設(shè)計(jì)模式

    嵌入式系統(tǒng)系列叢書(shū)-時(shí)間觸發(fā)嵌入式系統(tǒng)設(shè)計(jì)模式
    發(fā)表于 12-13 11:30 ?0次下載

    嵌入式中使用設(shè)計(jì)模式思想

    嵌入式的標(biāo)簽多為:低配,偏硬件,底層,資源緊張,代碼多以C語(yǔ)言,匯編為主,代碼應(yīng)用邏輯簡(jiǎn)單。
    的頭像 發(fā)表于 05-05 14:35 ?829次閱讀
    在<b class='flag-5'>嵌入式</b><b class='flag-5'>中使</b>用設(shè)計(jì)<b class='flag-5'>模式</b>的<b class='flag-5'>思想</b>

    嵌入式思想與PC思想結(jié)合

    能從PC機(jī)器編程去看嵌入式問(wèn)題,那是第一步。
    的頭像 發(fā)表于 05-10 10:42 ?808次閱讀
    <b class='flag-5'>嵌入式</b><b class='flag-5'>思想</b>與PC<b class='flag-5'>思想</b>結(jié)合