寵物任務的詳細流程? 一直以來,我不斷的探索RTOS的使用方法,以UC/OS-II為基礎當然努力的結果是逐漸形成了一個可以使用的軟件平台但我意識到如果沒有相應文檔的支持或許這個東西也許隻有我自己能使用了另外提高的空間有限所以今天就從這個困擾我許久的問題入手,慢慢的介紹我這兩年來努力的成果,我來為大家科普一下關于寵物任務的詳細流程?以下内容希望對你有幫助!
一直以來,我不斷的探索RTOS的使用方法,以UC/OS-II為基礎。當然努力的結果是逐漸形成了一個可以使用的軟件平台。但我意識到如果沒有相應文檔的支持或許這個東西也許隻有我自己能使用了。另外提高的空間有限。所以今天就從這個困擾我許久的問題入手,慢慢的介紹我這兩年來努力的成果。
關于多任務下如何才能有效的使用看門狗這個問題其實也不是很難。關鍵是在于喂狗的策略。你沒辦法像以前一樣。在程序的開頭初始化看門狗,然後在程序中的某一點調用喂狗指令,清除看門狗計數器。因為你要明白,你想要清楚的知道每一個任務都必需有條不紊的工作的。任何一個任務死掉就得停止喂狗。這就是問題的關鍵了。所以你不可以在每個任務裡直接調用喂狗指令。那是混亂的沒有實際意義。
那麼不能直接喂狗,自然就想到間接喂狗的方式了。如何才能做到間接喂狗。我使用了軟件看門狗的方式。給每個任務一個軟件模拟出來的看門狗計數器。然後在适當的時候定時的查詢每一個軟件看門狗的喂狗情況,由此決定是否調用喂狗指令,清除看門狗計數器。如果發現有任何一個軟件看門狗溢出,就停止喂狗,讓系統複位。
如何定時查詢軟件看門狗的喂狗情況? UC/OS-II系統時間節拍鈎子函數是個不錯的選擇。随後再給出具有體的實現。
void OSTimeTickHook (void)
{ SoftWdtISR(); //定時查詢每一個軟件看門狗喂狗狀況。
}
軟件看門狗是一個什麼樣的東西??從數據結構上來說,它是這樣子的:
typedef struct soft_wach_dog_timer{
uint16 watchDogTimeOut; //看門狗計數超時初值
uint16 watchDogTime; //看門狗定時器
uint8 watchDogCountBack; //上一次看門喂狗計數器
uint8 watchDogCount; //看門狗喂狗計數器
SWDT_STAT watchDogState; //看門狗定時器狀态
uint8 NOUSE8;
}SOFT_WATCH_DOG_TIMER;
好吧,我來一個個介紹,才幾個變量而以,很容易的。先講第二個成員吧,uint16 watchDogTime; 這個就是軟件看門狗的定時器了,每當調用SoftWdtISR的時候如果相應看門狗沒有喂狗操作該值會被減去1,否則将從第一個成員uint16 watchDogTimeOut複制一份拷貝。所以第一個成員變量叫做看門狗計數超時初值。那麼第三個和第四個成員變量是幹嗎用的呢,這兩個就是用來判斷是否有喂狗操作。第五個成員是表示軟件看門狗狀态的。總共有三種狀态。
typedef enum{ SWDT_STAT_IDLE, //軟件看門狗空閑
SWDT_STAT_SUSPEN, //軟件看門狗挂起
SWDT_STAT_RUN //軟件看門狗運行
}SWDT_STAT; 接下來看看SoftWdtISR的實現吧。
void SoftWdtISR(void){
SOFT_WATCH_DOG_TIMER *SoftWatchDogTimerPtr = SoftWatchDogTimerList;
uint8 i = 0;
if(StopWDTFedMake == TRUE){
return;
}
for(i=0; i<MAX_SWDT_ID; i ){
//對挂起和空閑的看門狗定時器不進行檢查獲 if(SoftWatchDogTimerPtr->watchDogState == SWDT_STAT_RUN){
//軟件看門狗有喂食,重裝看門狗計數上限
if(SoftWatchDogTimerPtr->watchDogCount != SoftWatchDogTimerPtr->watchDogCountBack){
SoftWatchDogTimerPtr->watchDogCountBack = SoftWatchDogTimerPtr->watchDogCount;
SoftWatchDogTimerPtr->watchDogTime = SoftWatchDogTimerPtr->watchDogTimeOut;
}else if(--SoftWatchDogTimerPtr->watchDogTime == 0){ //沒有喂狗,看門狗計時器減一操作 //其中任一個運行着的看門狗超時停止喂硬件看門狗
StopWDTFedMake = TRUE;
return;
}
}
SoftWatchDogTimerPtr ;
}//調用硬件喂狗
FeedDog();
}
SoftWdtISR函數隻對狀态為運行的軟件看門狗定時器進行檢查,每次都要判斷watchDogCountBack 是否等于watchDogCount,相等就表示該軟件看門狗沒有調用喂狗操作,然後執行軟件看門狗計數watchDogTime值減一操作。如果不相等就把watchDogCount的值賦給watchDogCountBack,。并且把watchDogTimeOut的值賦給watchDogTime,清除看門狗計數器。
當watchDogTime值為0,表示軟件看門狗溢出,需要複位系統。這有些曲折和複雜了,以後會改進。到時會去掉watchDogCountBack 、watchDogCount,這兩個成員。那麼該如何使用看門狗呢,我們要知道總共有幾個任務,為每個任務分配一個軟件看門狗,為每個看門狗分配一個ID。然後要清空所有軟件看門狗和初始化硬件看門狗:
typedef enum{//往這裡添加軟件看門狗ID
KEY_TASK_SWDT_ID,
MP3_TASK_SWDT_ID,
MAX_SWDT_ID,
}SWDT_ID;
//軟件看門狗定時器數組
SOFT_WATCH_DOG_TIMER SoftWatchDogTimerList[MAX_SWDT_ID] = {0};
void SoftWDTInit(void){
OS_MEMSET(SoftWatchDogTimerList, 0, sizeof(SOFT_WATCH_DOG_TIMER)*MAX_SWDT_ID); StopWDTFedMake = 0; //初始化硬件看門狗
WatchDogInit(1000,1);
}
軟件看門狗的使用:
Void KeyBoardTask(void *pdata){
//任務開始的地方,初始化軟件看門狗
SoftWdtInit(KEY_TASK_SWDT_ID,2000);
While(1){
const DEV_FUN* Device = NULL;
HAL_ERR_CODE err;
uint8 key_value[2] = {0};
uint8 data_addr = 0; /* 讀取一按鍵 */
SoftWdtFed(KEY_TASK_SWDT_ID); //任務主循環中喂狗
Device = DeviceOpen(I2C0_ID,&err);
……………………………..//以下代碼省略。
DeviceClose(&Device);
}
}
首先就是在任務開始的地方調用SoftWdtInit(KEY_TASK_SWDT_ID,2000);設置軟件看門狗溢出時間,單位mS. 然後在任務的主循環中調用SoftWdtFed(KEY_TASK_SWDT_ID);喂狗.接下來看看軟件看門狗初始化,和喂狗的實現。軟件看門狗的初始化:
//初始化軟件看門狗
BOOL SoftWdtInit(SWDT_ID SwdtId, uint16 TimerTop){
SOFT_WATCH_DOG_TIMER *SoftWatchDogTimerPtr = SoftWatchDogTimerList;
uint16 osTick = 0;
if(SwdtId >= MAX_SWDT_ID){
return 0;
}
if(SoftWatchDogTimerPtr->watchDogState == SWDT_STAT_IDLE){
SoftWatchDogTimerPtr = SwdtId;
osTick = MsToOSTicks(TimerTop);//将mS時間換算成系統時鐘節拍
SoftWatchDogTimerPtr->watchDogTimeOut = osTick;
SoftWatchDogTimerPtr->watchDogTime = osTick;
SoftWatchDogTimerPtr->watchDogState = SWDT_STAT_RUN;
return 1;
}else{
return 0;
}
}
這裡就沒什麼好說的,從軟件看門狗定時器數組裡,根據ID找到相應的軟件看門狗,然後初始化watchDogTimeOut,置watchDogState狀态為運行。
喂狗: //軟件看門狗喂食
void SoftWdtFed(SWDT_ID SwdtId){
SOFT_WATCH_DOG_TIMER *SoftWatchDogTimerPtr = SoftWatchDogTimerList; if(SwdtId >= MAX_SWDT_ID){
return;
}
SoftWatchDogTimerPtr = SwdtId;
OS_ENTER_CRITICAL();
SoftWatchDogTimerPtr->watchDogCount ;
//保證這兩個值使終不相等 if(SoftWatchDogTimerPtr->watchDogCount == SoftWatchDogTimerPtr->watchDogCountBack){
SoftWatchDogTimerPtr->watchDogCount ;
}
OS_EXIT_CRITICAL();
}
這個也很簡單,根據ID找到相應的軟件看門狗,然後執行SoftWatchDogTimerPtr->watchDogCount ;并保證SoftWatchDogTimerPtr->watchDogCount 不等于SoftWatchDogTimerPtr->watchDogCountBack多餘的部分:
之前說過watchDogCount 、watchDogCountBack這兩個是多餘的所以将來會改成: void SoftWdtFed(SWDT_ID SwdtId){
SOFT_WATCH_DOG_TIMER *SoftWatchDogTimerPtr = SoftWatchDogTimerList;
if(SwdtId >= MAX_SWDT_ID){
return; }
SoftWatchDogTimerPtr = SwdtId;
OS_ENTER_CRITICAL();
SoftWatchDogTimerPtr->watchDogTime = SoftWatchDogTimerPtr->watchDogTimeOut;
OS_EXIT_CRITICAL();
}
相應的SoftWdtISR也需要簡化。
最後介紹兩個函數: void SuspenWdt(SWDT_ID SwdtId); //挂起軟件看門狗。void RunWdt(SWDT_ID SwdtId); //恢複運行軟件看門狗。
,更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!