⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 c06b_wdog.c

📁 Tornado的源代码资源包
💻 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 + -