?? c06b_wdog.c
字號:
/******************************************************************
*
* tran_control.c - 使用看門狗定時器監視兩個任務之間的消息交互流程.
*
* Copy writes Oct, 2003
*
*/
/* 頭文件*/
#include "vxworks.h"
#include "logLib.h"
#include "taskLib.h"
#include "wdLib.h"
#include "msgQLib.h"
#include "sigLib.h"
#include "stdio.h"
/* 宏定義*/
#define SENDER_TASK_PRIORITY 100 /* 接受任務優先級 */
#define RECVER_TASK_PRIORITY 100 /* 發送任務優先級 */
#define TASK_STACK_SIZE 0x1000 /* 任務堆棧去大小 */
#define TIME_TO_DELAY 100 /* 任務時延 */
#define SENDER_SIG SIGRTMIN + 1 /* 與發送方task綁定的信號 */
#define RECVER_SIG SIGRTMIN + 2 /* 與接收方task綁定的信號 */
#define SEND_STR "REQ" /* 發送的消息 */
#define REPLY_STR "ACK" /* 應答的消息 */
#define RESEND_INTV 100 /* 重發消息的間隔 */
#define IDLE_INTV 300 /* 接收方空閑時間 */
#define NO_PARAMETER 0 /* 啟動看門狗定時器參數 */
#define NO_OPTION 0 /* 綁定信號處理程序的選項 */
#define MSG_MAX_QUEUE_NUM 10 /* 消息隊列中消息的最大個數 */
#define MSG_MAX_LEN 3 /* 消息接收區消息的最大長度 */
/* 全局變量 */
LOCAL int SendTask_ID = ERROR; /* 發送消息的task ID */
LOCAL int RecvTask_ID = ERROR; /* 接收消息的task ID */
LOCAL WDOG_ID ReSender_Wdog = NULL; /* 重發看門狗定時器的ID */
LOCAL WDOG_ID Idle_Wdog = NULL; /* 空閑看門狗定時器的ID */
LOCAL MSG_Q_ID SendMsgQ; /* 發送task的消息隊列ID */
LOCAL MSG_Q_ID RecvMsgQ; /* 接收task的消息隊列ID */
LOCAL UINT8 Send_Sequence = 0; /* 標記是否已經重發過 */
/* 綁定到信號SENDER_SIG的處理句柄 */
LOCAL struct sigvec newSigHandler_Sender;
/* 記錄原來綁定到信號SENDER_SIG的處理句柄 */
LOCAL struct sigvec oldSigHandler_Sender;
/* 綁定到信號RECVER_SIG的處理句柄 */
LOCAL struct sigvec newSigHandler_Recver;
/* 記錄原來綁定到信號RECVER_SIG的處理句柄 */
LOCAL struct sigvec oldSigHandler_Recver;
/* 函數說明 */
/* 重發定時器超時后的ISR */
void Resender_Wdog_Timeout_Handler(void);
/* 空閑定時器超時后的ISR */
void Idle_Wdog_Timeout_Handler(void);
/* 接收task收到信號SENDER_SIG后的信號服務程序 */
void Send_Sig_Handler(int sigNum);
/* 發送task收到信號RECVER_SIG后的信號服務程序 */
void Recv_Sig_Handler(int sigNum);
/*******************************************************************
* Sender_Task - 發送消息的task.
* 操作步驟如下:
* 1.初始化階段,首先創建重發看門狗定時器
* 2.綁定SENDER_SIG的信號服務程序
* 3.進入循環體開始每隔TIME_TO_DELAY發送一個消息,并且等待接收ACK
* 4.在接收到ACK后,停止看門狗定時器的計時,并開始下一輪的消息發送
* 5.如果在指定的時間內沒有收到ACK,則會收到信號SENDER_SIG,從而執行
* 指定的信號處理程序.
*/
LOCAL void Sender_Task(void)
{
char RecvBuffer[MSG_MAX_LEN];
/* 創建重發看門狗定時器,并且輸出ID信息 */
if ((ReSender_Wdog = wdCreate()) == NULL)
{
printf("\n[SEND] Create Watchdog Timer Fail!");
return;
}
printf("\n[SEND]ReSender_Wdog ID = %x",(int)ReSender_Wdog);
/* 綁定信號處理程序 */
if (sigvec(SENDER_SIG, &newSigHandler_Sender,
&oldSigHandler_Sender) == ERROR)
{
printf("\n[SEND] Bind Signal Service Routine Fail!");
wdDelete(ReSender_Wdog);
return;
}
/* 周期性發送消息并等待ACK */
FOREVER
{
taskDelay(TIME_TO_DELAY);
if (msgQSend(RecvMsgQ, SEND_STR, (int)strlen(SEND_STR),
NO_WAIT, MSG_PRI_NORMAL) == ERROR)
{
printf("\n[SEND] Send Msg Fail!");
wdDelete(ReSender_Wdog);
return;
}
if (wdStart(ReSender_Wdog, RESEND_INTV,
(FUNCPTR)Resender_Wdog_Timeout_Handler, NO_PARAMETER)
== ERROR)
{
printf("\n[SEND] Start Watchdog Timer Fail!");
wdDelete(ReSender_Wdog);
return;
};
if (msgQReceive(SendMsgQ, (char*)&RecvBuffer, MSG_MAX_LEN,
WAIT_FOREVER) == ERROR)
{
printf("\n[SEND] Receive Msg Fail!");
wdDelete(ReSender_Wdog);
return;
};
printf("\n[Send] REQ");
wdCancel(ReSender_Wdog);
Send_Sequence = 0;
}
}
/******************************************************************
* Recver_Task - 接收消息的task.
* 操作步驟如下:
* 1.初始化階段,首先創建空閑看門狗定時器
* 2.綁定RECVER_SIG的信號服務程序
* 3.進入循環體開始啟動定時器,并且等待接收REQ
* 4.在接收到REQ后,停止看門狗定時器的計時,并開始下一輪的等待
* 5.如果在定義的時長之內,沒有收到任何消息,那么就會收到信號RECVER_SIG
* 從而執行指定的信號處理程序。
*/
LOCAL void Recver_Task(void)
{
char RecvBuffer[MSG_MAX_LEN];
if ((Idle_Wdog = wdCreate()) == NULL)
{
printf("\n[RECV] Create Watchdog Timer Fail!");
return;
}
printf("\n[RECV]Idle_Wdog ID = %x",(int)Idle_Wdog);
if (sigvec(RECVER_SIG, &newSigHandler_Recver,
&oldSigHandler_Recver) == ERROR)
{
printf("\n[RECV] Bind Signal Service Routine Fail!");
wdDelete(Idle_Wdog);
return;
}
FOREVER
{
if (wdStart(Idle_Wdog, IDLE_INTV,
(FUNCPTR)Idle_Wdog_Timeout_Handler, NO_PARAMETER)
== ERROR)
{
printf("\n[RECV] Start Watchdog Timer Fail!");
wdDelete(Idle_Wdog);
return;
};
if (msgQReceive(RecvMsgQ, (char*)&RecvBuffer, MSG_MAX_LEN,
WAIT_FOREVER) == ERROR)
{
printf("\n[RECV] Receive Msg Fail!");
wdDelete(Idle_Wdog);
return;
};
printf("\n[RECV] ACK");
if (msgQSend(SendMsgQ, REPLY_STR, (int)strlen(REPLY_STR),
NO_WAIT, MSG_PRI_NORMAL) == ERROR)
{
printf("\n[RECV] Send Msg Fail!");
wdDelete(ReSender_Wdog);
return;
}
wdCancel(Idle_Wdog);
}
}
/******************************************************************
* Resender_Wdog_Timeout_Handler - 重發看門狗定時器超時中斷的處理程序
*/
void Resender_Wdog_Timeout_Handler(void)
{
/* 發送信號SENDER_SIG */
if (kill(SendTask_ID, SENDER_SIG) == ERROR)
{
logMsg("\n[Resender] Send Signal Fail!", 0, 0, 0, 0, 0, 0);
}
else
{
logMsg("\n[Resender] Send Signal!", 0, 0, 0, 0, 0, 0);
}
return;
}
/******************************************************************
* Idle_Wdog_Timeout_Handler - 空閑計時看門狗定時器超時中斷的處理程序
*/
void Idle_Wdog_Timeout_Handler(void)
{
/* 發送信號給接收task,并輸出信息 */
if (kill(RecvTask_ID, RECVER_SIG) == ERROR)
{
logMsg("\n[Idle] Send Signal Fail!", 0, 0, 0, 0, 0, 0);
}
else
{
logMsg("\n[Idle] Send Signal!", 0, 0, 0, 0, 0, 0);
}
return;
}
/******************************************************************
* Send_Sig_Handler - 發送task綁定的信號處理程序.
* 步驟如下:
* 1.判斷是否已經重發過.
* 2.如果沒有重發,則重發REQ,并且再次啟動重發定時器
* 3.否則,輸出信息好將當前的task置為掛起態.
*/
void Send_Sig_Handler(int sigNum)
{
if (Send_Sequence == 0)
{
Send_Sequence = 1;
if (msgQSend(RecvMsgQ, SEND_STR, (int)strlen(SEND_STR),
NO_WAIT, MSG_PRI_NORMAL) == ERROR)
{
printf("\n[SIGNAL_SEND] Send Msg Fail!");
return;
}
if (wdStart(ReSender_Wdog, RESEND_INTV,
(FUNCPTR)Resender_Wdog_Timeout_Handler, NO_PARAMETER)
== ERROR)
{
printf("\n[SIGNAL_SEND] Start Watchdog Timer Fail!");
return;
};
printf("\n[SIGNAL_SEND] Resend!");
}
else
{
Send_Sequence = 0;
printf("\n[SIGNAL_SEND] NO ACK! Suspend!");
taskSuspend(SendTask_ID);
}
return;
}
/******************************************************************
* Recv_Sig_Handler - 接收task綁定的信號處理程序.
* 步驟如下:
* 1.由于空閑時間過長,將接收task掛起
*/
void Recv_Sig_Handler(int sigNum)
{
printf("\n[SIGNAL_RECV] NO Message! Suspend!");
taskSuspend(RecvTask_ID);
return;
}
/******************************************************************
* WatchdogRoot - 根task,創建各個task,并初始化必備的設施:
* 步驟如下:
* 1.創建發送和接收task
* 2.創建發送和接收task的消息隊列
* 3.配置兩個信號的處理句柄
*/
void WatchdogRoot(void)
{
if ((SendTask_ID = taskSpawn("tSendtask", SENDER_TASK_PRIORITY,
VX_NO_STACK_FILL, TASK_STACK_SIZE,
(FUNCPTR)Sender_Task, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR)
{
printf("\n[ROOT]Task Spawn Fail!");
return;
}
if ((RecvTask_ID = taskSpawn("tRecvtask", RECVER_TASK_PRIORITY,
VX_NO_STACK_FILL, TASK_STACK_SIZE,
(FUNCPTR)Recver_Task, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) == ERROR)
{
printf("\n[ROOT]Task Spawn Fail!");
taskDelete(SendTask_ID);
return;
}
if ((SendMsgQ = msgQCreate(MSG_MAX_QUEUE_NUM, MSG_MAX_LEN,
MSG_Q_FIFO)) == NULL)
{
printf("\n[ROOT]Msg Queue Create Fail!");
taskDelete(SendTask_ID);
taskDelete(RecvTask_ID);
return;
}
if ((RecvMsgQ = msgQCreate(MSG_MAX_QUEUE_NUM, MSG_MAX_LEN,
MSG_Q_FIFO)) == NULL)
{
printf("\n[ROOT]Msg Queue Create Fail!");
msgQDelete(SendMsgQ);
taskDelete(SendTask_ID);
taskDelete(RecvTask_ID);
return;
}
newSigHandler_Sender.sv_handler = Send_Sig_Handler;
newSigHandler_Sender.sv_mask = SIGUSR2;
newSigHandler_Sender.sv_flags = NO_OPTION;
newSigHandler_Recver.sv_handler = Recv_Sig_Handler;
newSigHandler_Recver.sv_mask = SIGUSR2;
newSigHandler_Recver.sv_flags = NO_OPTION;
}
/******************************************************************
* TaskController - 依據參數的不同分別掛起發送或是發送task,從而觸發看門狗
* 定時器超時,進而執行響應的信號處理程序:
* 步驟如下:
* 1.判斷兩個task是否已經被創建
* 2.依據taskNum掛起響應的task
*/
void TaskController(UINT8 taskNum)
{
if ((SendTask_ID == ERROR) || (RecvTask_ID == ERROR))
{
printf("\n[CONTROLLER] Task Not Exist");
return;
}
switch (taskNum)
{
case 0:
taskSuspend(SendTask_ID);
break;
case 1:
taskSuspend(RecvTask_ID);
break;
default :
break;
}
return;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -