<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      自用純C語言實現裸機任務調度(可用于STM32、C51等單片機)

      前言

      ??這個任務調度模塊的實現是形成于畢設項目中的,用在STM32中,斷斷續續跨度2個月實現了一些基本功能,可能后面再做其他項目時會一點點完善起來,也會多學習相關知識來強化模塊的實用性和高效性,畢竟用自己自主實現出來的功能還是蠻舒心的。

      任務調度模式結構

      ??整體上的結構屬于線性結構,結合鏈表定時器來實現,我使用的是sysTick這個滴答時鐘,1ms的頻率,功能比較簡單,容易理解。

      分片

      ??分片的模式,主要體現在函數分片時間分片在我之前就有使用在函數中,主要的思路是,把函數功能切片,分為幾個小部分,每次執行時按次序執行小部分,對于沒有時序要求的函數來說,可以把一個占用CPU大的功能分攤開來實現,從而避免有些地方耗時長的問題。對于時間分片,其實就是定時器的一種應用,實際上,函數分片在執行的時候已經是一種時間分片了,不過現在加上人為的控制在里面了。
      ??下面是函數分片的一般結構:

      void func(char *fos,...){
          static char step=0;//順序控制變量,自由度比較高,可亂序,可循環,可延遲執行
          switch(step){
              case 0:{
                  //...
                  step++;
                  break;
              }
              case 1:{
                  //...
                  step++;
                  break;
              }
              //...
              default:{
                  //step++;//可以借助default實現延時的效果,即跳過幾次空白step
                  break;
              }
      
          }
          return;
      }
      

      其中添加的參數變量*fos必要的,因為就是通過傳入每個任務的這個標志位來判斷是否運行結束,而其他的參數,就得基于具體任務做不一樣的處理了。

      輪詢

      • 運行框圖

      ??可以看到這個框圖是一個頭尾相連閉環結構,從頭節點依次運行到尾節點后再從頭循環往復執行下去。

      • 輪詢函數
      void loop_task(void){
      	static Task_Obj *tasknode;
      	
      	tasknode=task_curnode->next;//repoint the curnode to the next
      	if(tasknode==NULL){//tasknode is null,only the headnode have the attr
      		return;//express the task space is none
      	}
      	else if(tasknode->task_type==TYPE_HEAD){//tasknode is headnode
      		task_curnode=tasknode;
      		return;
      	}
      	else{
      		if(tasknode->run_type == RUN_WAIT){
                  //等待型任務,通過ready標志來確定是否執行,否則就跳過
      			if(!tasknode->ready){
      				if(task_curnode->next !=NULL){
      					task_curnode=task_curnode->next;
      					return;
      				}
      			}
      		}
      		if(tasknode->task_status==STATUS_INIT){
      
      			tasknode->tickstart=HAL_GetTick();//獲取tick
      			tasknode->task_status=STATUS_RUN;
      
      		}
      		else if(tasknode->task_status==STATUS_RUN){
      			if((HAL_GetTick() - tasknode->tickstart) > (uint32_t)tasknode->task_tick){
      				tasknode->task_name(&(tasknode->task_fos));//run the step task,transfer the fos
      				tasknode->tickstart+=(uint32_t)tasknode->task_tick;//update the tickstart
      			}
      		}
      		
      	}
      	if(tasknode->task_fos==FOS_FLAG){
      		
      		tasknode->ready=0;
      		if(tasknode->waittask!=NULL){
                  //置位該任務綁定的等待的任務準備運行標志位,標識可以準備運行了
      			tasknode->waittask->ready=1;
      		}
              //運行結束就刪掉該任務
      		delete_task(tasknode);
      	}
      	else if(tasknode->task_fos==FOC_FLAG){
              //循環運行該任務
      		tasknode->task_status=STATUS_INIT;//continue running from start
      		tasknode->task_fos=0;//RESET fos
      		
      	}
      	if(task_curnode->next !=NULL){
      		if(task_curnode->next->run_type==RUN_FORCE) return;//force-type's task
      		
      		else task_curnode=task_curnode->next;
      		
      	}
      	
      
      }
      

      其中有幾個運行態和標志位

      #define FOS_FLAG 99//運行結束標志
      #define FOC_FLAG 100//運行結束后再次執行,相當于循環運行
      #define TYPE_NOMAL 0//標識一般任務類型
      #define TYPE_HEAD 1//標識頭任務類型
      #define TYPE_END 2//標識尾任務類型
      #define RUN_NORMAL 0//一般輪詢模式
      #define RUN_FORCE 1//強制運行該任務,運行結束才繼續下一個任務
      #define RUN_WAIT 2//等待指定的任務結束,才可以被運行
      #define STATUS_INIT 0//任務的準備階段,用于獲取起始時間
      #define STATUS_RUN 1//任務運行階段
      #define STATUS_UNVAILED 2//無效狀態
      

      運行時對時間間隔tick的把握還有點問題,這個等待后面有機會優化下。

      現添加如下代碼優化執行間隔的問題 @6.12

      void loop_add_tick(void){
      	char i;
      	Task_Obj *tasknode;
      	tasknode = &task_headnode;
      	for(i = 0;i<task_num;i++){
      		tasknode = tasknode->next;
      		if(tasknode->task_status == STATUS_RUN)
      			tasknode->tickcnt++;
      	}
      }
      

      把這段代碼放在Systick中斷函數中,然后修改循環調度函數中的判斷執行間隔的地方。這種方式的好處是可以精細化到每一個任務的執行間隔,而不是之前只在一條時間線上,進行多個任務的時間間隔的處理,并且由于是在中斷中同時在進行自增,所以減少了之前任務的額外時間消耗。

      調度實現

      • 任務鏈表結構
      typedef struct TASK_CLASS{
      	void (*task_name)(char *taskfos,...);//任務函數
      	int task_tick;//任務的時間分片間隔
      	uint32_t tickstart;//起始時間點,每次執行完須加上一個tick
      	char task_fos;//運行結束標志
      	char task_type;//任務類型變量
      	char task_status;//任務狀態
      	char run_type;//運行狀態
      	char ready;//準備運行標志位
      	struct TASK_CLASS *next;//下一任務
      	struct TASK_CLASS *waittask;//等待執行的任務
      } Task_Obj;
      
      • 添加任務

        • add_task
        void add_task(void (*taskname)(char *,...),int tasktick,int runtype){//可變參,這里未做處理
        Task_Obj *tasknode,*tmpnode;
        char i;
        
        tasknode = (Task_Obj*)malloc(sizeof(Task_Obj));
        
        tasknode->task_name=taskname;
        tasknode->task_tick=tasktick;
        tasknode->task_fos=0;
        tasknode->task_status=STATUS_INIT;//initial status
        tasknode->task_type=TYPE_END; //set the new node to endnode
        tasknode->run_type=runtype;
        tasknode->next=&task_headnode;//the endnode point to the headnode
        
        tmpnode=&task_headnode;
        if(task_num==0){
        	tmpnode->next=tasknode;
        	task_num++;
        	return;
        }
        for(i=0;i<task_num;i++){
        	tmpnode=tmpnode->next;//reach the endnode
        }
        tmpnode->task_type=TYPE_NOMAL;//turn the last endnode to the normal node
        tmpnode->next=tasknode;
        task_num++;
        }
        
        • add_wait_task
        void add_wait_task(void (*taskname)(char *),void (*waitname)(char *),int tasktick){
        Task_Obj *tmpnode,*tasknode;
        char i,pos;
        
        tmpnode=&task_headnode;
        for(i=0;i<task_num;i++){
        	tmpnode=tmpnode->next;//reach the endnode
        	if(tmpnode->task_name==taskname){
        		pos=i;//獲取要等待任務的位置
        		break;
        	}
        }
        
        tasknode = (Task_Obj*)malloc(sizeof(Task_Obj));
        
        tasknode->task_name=waitname;
        tasknode->task_tick=tasktick;
        tasknode->task_fos=0;
        tasknode->task_status=STATUS_INIT;//initial status
        tasknode->task_type=TYPE_END; //set the new node to endnode
        tasknode->run_type=RUN_WAIT;//任務為等待運行
        tasknode->ready=0;
        tasknode->next=&task_headnode;//the endnode point to the headnode
        
        tmpnode->waittask=tasknode;//獲取新建的等待執行的任務地址,在運行結束后把等待執行的任務的準備運行標志位置1
        
        tmpnode=&task_headnode;
        if(task_num==0){
        	tmpnode->next=tasknode;
        	task_num++;
        	return;
        }
        for(i=0;i<task_num;i++){
        	tmpnode=tmpnode->next;//reach the endnode
        }
        tmpnode->task_type=TYPE_NOMAL;//turn the last endnode to the normal node
        tmpnode->next=tasknode;
        task_num++;
        
        }
        
      • 刪除任務

        • delete_task(局限性大,只針對當前運行的任務而言)
        void delete_task(Task_Obj *taskobj){
        if(task_curnode->task_type==TYPE_HEAD && task_num < 2){//if curnode is headnode,and tasknum=1
        	task_curnode->next=NULL;
        }
        else{
        	task_curnode->next=taskobj->next;//repoint the curnode next
        }
        free(taskobj);//free the space of where the taskobj pointed
        
        task_num--;
        
        }
        
        • delete_task_withname(刪除指定任務名的任務)
        void delete_task_withname(void (*taskname)(char *)){
        Task_Obj *tmpnode,*tmpnode2;
        char i,pos;
        
        tmpnode=&task_headnode;
        for(i=0;i<task_num;i++){
        	tmpnode=tmpnode->next;//reach the endnode
        	if(tmpnode->task_name==taskname){
        		pos=i;
        		break;
        	}
        }
        if(i==task_num) return;
        tmpnode=&task_headnode;
        for(i=0;i<pos+1;i++){
        	tmpnode2=tmpnode;
        	tmpnode=tmpnode->next;
        }
        if(tmpnode->next==NULL){//if tmpnode is endnode
        	tmpnode2->next=&task_headnode;
        }
        else{
        	tmpnode2->next=tmpnode->next;//repoint the curnode next
        }
        task_num--;
        free(tmpnode);
        }
        
      • 初始化任務空間

      void non_task(char *taskfos){
      	return;
      }
      
      void init_taskspace(void){
      	task_headnode.task_name=non_task;
      	task_headnode.task_type=TYPE_HEAD;
      	task_headnode.task_status=STATUS_UNVAILED;
      	task_headnode.next=NULL;
      	task_curnode=&task_headnode;//頭節點是沒有任務需要執行的
      	task_num=0;
      }
      
      • 調用實例
      add_task(task1,500,RUN_NORMAL);//500ms執行一次task1任務
      add_wait_task(task1,task2,500);//task2等待task1結束才會執行,運行的時間間隔為500ms
      delete_task_withname(task1);//刪除task1任務
      
      while(1){
          //...
          loop_task();//任務輪詢
      }
      

      結語

      ??整體實現說難不難,說簡單不簡單,但也是我第一次嘗試這種偏向系統級應用的代碼,而且都沒有參照任何其他的資料和代碼,完全以自己的對任務的理解和具體項目的需求來一點點實現,希望后面會把這個調度的代碼進一步完善成一個通用型的調度方式,也方便后面項目的使用了。

      posted @ 2023-04-09 17:54  pie_thn  閱讀(3803)  評論(3)    收藏  舉報
      主站蜘蛛池模板: 国产av亚洲精品ai换脸电影| 国产亚洲中文字幕久久网| 国产羞羞的视频一区二区| 日韩一区二区在线看精品| 国产中文字幕日韩精品| 国产情侣激情在线对白| 免费一区二区无码东京热| 亚洲欧洲日韩国内高清| 极品无码国模国产在线观看| 国产亚洲精品AA片在线播放天| 国产综合精品91老熟女| 精品无码人妻| 中字幕人妻一区二区三区| 亚洲爆乳WWW无码专区| 亚洲色欲色欱WWW在线| 亚洲熟妇乱色一区二区三区| 人人干人人噪人人摸| 99RE6在线观看国产精品| a国产一区二区免费入口| 国产成人永久免费av在线| 国产在线午夜不卡精品影院| 陵川县| 永久免费无码av在线网站| 久久99精品久久久学生| 亚洲精品不卡av在线播放| 少妇人妻偷人偷人精品| 人妻丝袜AV中文系列先锋影音| 国产精品国产精品偷麻豆| 制服丝袜另类专区制服| 亚洲欧美电影在线一区二区| 久久精品免视看国产成人| 久热伊人精品国产中文| 精品亚洲国产成人性色av| 躁躁躁日日躁| 吉川爱美一区二区三区视频 | 色av专区无码影音先锋| 久久亚洲精品人成综合网| 欧美人人妻人人澡人人尤物 | 日本污视频在线观看| 日韩精品无码区免费专区| 亚洲欧洲日韩国内高清|