📄 c06c_timer.c
字号:
/* 头文件*/
#include "vxWorks.h"
#include "stdio.h"
#include "stdlib.h"
#include "semLib.h"
#include "taskLib.h"
#include "sysLib.h"
#include "tickLib.h"
/* 宏定义 */
#define NUM_SAMPLE 10 /*组成一个样本的数据的个数*/
#define HOT 20 /* 输出HOT的临界值 */
#define SYSCLK_TICK 100 /* 系统时钟每秒的tick数 */
#define NO_ARG 0 /* 传递给函数的参数 */
#define STACK_SIZE 20000 /* 分配给每个任务的堆栈大小 */
/* 类型定义 */
typedef struct byLightning
{
int data;
int nodeNum;
struct byLightning *pPrevNode;
}LIST_NODE;
/* 全局变量 */
int tidSchlep; /* 任务ID */
int tidCrunch;
int tidMonitor;
int cosmicData = 0; /* 模拟产生的数据 */
int result = 0; /* 样本处理结果 */
int sysClkOringnalRate = 60; /* 系统时钟的原始ISR */
LIST_NODE * pCurrNode = NULL; /* 数据列表的头指针 */
SEM_ID dataSemId; /* 信号量ID,用于同步,数据可用时释放 */
SEM_ID syncSemId; /* 信号量ID,用于同步,样本可用时释放 */
SEM_ID nodeListGuardSemId; /* 信号量ID,用于互斥,保护数据列表 */
/* 函数申明 */
void cosmos(void);
void nodeAdd(int data, int nodeNum);
void schlep(void);
void nodeScrap(void);
void crunch(void);
void monitor(void);
void progStop(void);
extern void usrClock ();
/*******************************************************************
* progStart - 启动实例程序
*
* 负责创建信号量与任务
*
* RETURNS: OK
*/
STATUS progStart(void)
{
syncSemId = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
dataSemId = semBCreate(SEM_Q_FIFO, SEM_EMPTY);
nodeListGuardSemId = semMCreate(SEM_Q_PRIORITY
| SEM_INVERSION_SAFE
| SEM_DELETE_SAFE);
/* 初始化变量 */
pCurrNode = NULL;
/* 初始化系统时钟 */
sysClkOringnalRate = sysClkRateGet();
printf("\n system clock original rate = %d", sysClkOringnalRate);
if (sysClkRateSet(SYSCLK_TICK) == ERROR)
{
printf("\n System clock rate setting failure!");
return(ERROR);
}
if (sysClkConnect((FUNCPTR)cosmos, NO_ARG) == ERROR)
{
printf("\n System clock ISR connecting failure!");
return(ERROR);
}
sysClkEnable();
/* 创建任务 */
tidSchlep = taskSpawn("tSchlep", 220, 0, STACK_SIZE,
(FUNCPTR)schlep,0,0,0,0,0,0,0,0,0,0);
tidCrunch = taskSpawn("tCrunch", 240, 0, STACK_SIZE,
(FUNCPTR) crunch,0,0,0,0,0,0,0,0,0,0);
tidMonitor = taskSpawn("tMonitor", 250, 0, STACK_SIZE,
(FUNCPTR) monitor,0,0,0,0,0,0,0,0,0,0);
return (OK);
}
/******************************************************************
* cosmos - 系统时钟服务程序,每次释放一次信号量代表数据到来一次
*
* RETURNS: N/A
*/
void cosmos(void)
{
tickAnnounce();
cosmicData = rand();
semGive(dataSemId);
}
/******************************************************************
*
* nodeAdd - 将样本数据存储到数据链表
*
* 申请一个数据节点来保持样本数据,并将节点前插入数据链表中
*
* RETURNS: N/A
*/
void nodeAdd
(
int data, /* 需要存入的数据 */
int nodeNum /* 用于创建新的数据节点 */
)
{
LIST_NODE * node;
if ( (node = (LIST_NODE *) malloc(sizeof (LIST_NODE))) != NULL)
{
/* 保存样本数据 */
node->data = data;
node->nodeNum = nodeNum;
/* 将节点前插入数据链表中 */
semTake(nodeListGuardSemId, WAIT_FOREVER);
node->pPrevNode = pCurrNode;
pCurrNode = node;
semGive(nodeListGuardSemId);
}
else
{
printf ("cobble: Out of Memory.\n");
taskSuspend(0);
}
return;
}
/*******************************************************************
* schlep - 将采集到的数据组成一个样本
*
* 将采集到的数据,每NUM_SAMPLE个一组,组成一个样本,样本用全局的数据链表存储
* 每组成一个样本之后,利用二进制信号量的同步功能,唤醒(Unpend)样本处理任务
*
* RETURNS: N/A
*/
void schlep(void)
{
int nodeIdx;
FOREVER
{
for (nodeIdx = 0; nodeIdx < NUM_SAMPLE; nodeIdx++)
{
/* 等数据 */
semTake(dataSemId, WAIT_FOREVER);
/* 保存数据 */
nodeAdd(cosmicData, nodeIdx);
}
/* 将单个的样本发给tCrunch */
semGive(syncSemId);
}
}
/******************************************************************
*
* nodeScrap - 从数据链表中删除首个数据节点
*
* 互斥访问数据链表,完成从数据链表中删除首个数据节点的工作
*
* RETURNS: N/A
*/
void nodeScrap(void)
{
LIST_NODE *pTmpNode; /* 指向首个数据节点 */
/* 互斥访问数据链表 */
semTake(nodeListGuardSemId, WAIT_FOREVER);
if (pCurrNode != NULL)
{
pTmpNode = pCurrNode;
pCurrNode = pCurrNode->pPrevNode;
free(pTmpNode);
}
/* 互斥结束 */
semGive(nodeListGuardSemId);
return;
}
/******************************************************************
* crunch - 处理样本数据
*
* 利用二进制信号量的同步功能,等待tSchlep发送一个样本。
* 对收到的样本数据进行处理。
*
* RETURNS: N/A
*/
void crunch(void)
{
int sampleSum = 0; /* 保存样本数据之和 */
int div;
int *pDiv = ÷
FOREVER
{
semTake(syncSemId, WAIT_FOREVER);
semTake(nodeListGuardSemId, WAIT_FOREVER);
while (pCurrNode != NULL)
{
sampleSum += pCurrNode->data;
div = pCurrNode->data;
/* 递归访问,删除数据 */
nodeScrap();
}
semGive(nodeListGuardSemId);
if ((pDiv != NULL) && (*pDiv != 0))
{
result = sampleSum / (*pDiv);
}
sampleSum = 0;
}
}
/*****************************************************************
* monitor - 监视程序运行情况
*
* 监视程序运行情况,并显示结果
*
* RETURNS: N/A
*/
void monitor(void)
{
int isHot = FALSE; /* 标志:TRUE = 热;FALSE = 冷 */
FOREVER
{
if (!isHot && result >= HOT)
{
isHot = TRUE;
printf("WARNING: HOT!\n");
}
else if (isHot && result < HOT)
{
isHot = FALSE;
printf("cool\n");
}
}
}
/********************************************************************
* progStop - 停止实例程序
*
* 调用本函数来停止本实例程序,删除创建的任务并释放信号量资源。
*
* RETURNS: N/A
*/
void progStop(void)
{
/* 恢复对系统时钟的默认配置 */
sysClkDisable();
sysClkConnect ((FUNCPTR) usrClock, NO_ARG);
sysClkRateSet (sysClkOringnalRate);
sysClkEnable ();
/* 互斥信号量有删除保护功能,
* 必须成功获得之后再进行删除任务的工作
*
* nodeScrap()中需要使用互斥信号量
* 必须在删除互斥信号量调用
*/
taskDelete(tidSchlep);
taskDelete(tidCrunch);
taskDelete(tidMonitor);
semDelete(dataSemId);
semDelete(syncSemId);
semDelete(nodeListGuardSemId);
/* 清空数据链表 */
while (pCurrNode != NULL)
{
nodeScrap();
}
printf("BYE!TSCHUESS!ADIEU!\n");
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -