📄 dataqueue.c
字号:
/*
****************************************************************************
* 宁波中科集成电路设计中心 版权所有 Copyright 2005
* http:\\www.nbicc.com
*文件名: dataqueue.c
*程序员: 蒋文丰
*主要内容:数据包缓存的队列管理
*
*如有问题或BUG,请登录www.wsn.net.cn 提问或用邮件和作者联系
****************************************************************************
*/
/////
#include "led.h"
#include "type.h"
#include "message.h"
#include "mac.h"
#include "dataqueue.h"
#include "os.h"
#include "route.h"
#include "app.h"
#include "global.h"
static void routeSendTask(void);
static void routeSendBroadcast(void);
static void routeSendLocalMsg(void);
static uint8_t enqueue_next; //队列尾指针
static uint8_t dequeue_next; //队列头指针
static bool QueueIdle; //队列的互斥变量
static uint8_t FreeAreaInQueue;//队列中的可用的空间数目
extern uint8_t currentparent;
static uint8_t TimeMask;
static uint8_t nextAddr;
static uint8_t QueueBroadcastState;
static uint8_t QueueLocalMsgState;
enum {IDLE,WRITE,USEFULL};
void QueueInit(void){ //mac层的调用在mac.c中被调用
TimeMask = 0;
enqueue_next = 0;
for( ;enqueue_next < MESSAGE_QUEUE_SIZE ; enqueue_next ++ )
Queuemsgqueue[enqueue_next].length = 0 ;
enqueue_next = 0;
dequeue_next = 0;
FreeAreaInQueue = MESSAGE_QUEUE_SIZE;
QueueIdle = TRUE;
QueueBroadcastState = IDLE;
QueueLocalMsgState = IDLE;
}
/**************************************************************************
*功能描述:数据入缓冲队列
*参数说明:type 表示单播或广播,type由message.h中的enum定义,BROADCAST代表广播方式,SENSOR 代表单播方式
enum PACKETTYPE {
BROADCAST = 4,
SENSOR = 3
};
adress 表示下一调的地址还是广播地址,由type决定
length 数据包的长度
msg 数据包地址
*返回值:
**************************************************************************/
result_t InQueue(uint8_t type, uint8_t length, OSMACMsgPtr msg) {
if ((enqueue_next + 1) % MESSAGE_QUEUE_SIZE == dequeue_next) {
OSPostTask(routeSendTask); //队列满,调用任务,加快传输
return FAIL;
}
if(QueueIdle == TRUE) {
QueueIdle = FALSE;
//设置队列内容
Queuemsgqueue[enqueue_next].length = length;
Queuemsgqueue[enqueue_next].type = type;
Queuemsgqueue[enqueue_next].Msg = *msg;
enqueue_next++; //进入队列数目加1
enqueue_next %= MESSAGE_QUEUE_SIZE;
FreeAreaInQueue = FreeAreaInQueue - 1;
QueueIdle = TRUE;
}
return SUCCESS;
}
/**************************************************************************
*功能描述:广播包入缓冲区
*参数说明:type 表示单播或广播,type由message.h中的enum定义,BROADCAST代表广播方式,SENSOR 代表单播方式
enum PACKETTYPE {
BROADCAST = 4,
SENSOR = 3
};
adress 表示下一调的地址还是广播地址,由type决定
length 数据包的长度
msg 数据包地址
*返回值:
**************************************************************************/
result_t InBroadQueue(uint8_t type, uint8_t length, OSMACMsgPtr msg) {
if(QueueBroadcastState == IDLE){
QueueBroadcastState = WRITE;
QueueBroadcast.length = length;
QueueBroadcast.type = type;
QueueBroadcast.Msg = *msg;
QueueBroadcastState = USEFULL;
return 1;
}else{
return 0;
}
}
/**************************************************************************
*功能描述:本地数据包入缓冲区
*参数说明:type 表示单播或广播,type由message.h中的enum定义,BROADCAST代表广播方式,SENSOR 代表单播方式
enum PACKETTYPE {
BROADCAST = 4,
SENSOR = 3
};
adress 表示下一调的地址还是广播地址,由type决定
length 数据包的长度
msg 数据包地址
*返回值:
**************************************************************************/
result_t InLocalMsgQueue(uint8_t type, uint8_t length, OSMACMsgPtr msg){
if(QueueLocalMsgState == IDLE ) {
QueueLocalMsgState = WRITE;
QueueLocalMsg.length = length;
QueueLocalMsg.type = type;
QueueLocalMsg.Msg = *msg;
QueueLocalMsgState = USEFULL;
return 1;
}else{
return 0;
}
}
/**************************************************************************
*功能描述:定时调用发送任务
*参数说明:
*返回值:
**************************************************************************/
void MACTask(void){
if(currentparent != INVALID_NODE_ID) {
LedRedOn();
}else {
LedRedOff();
}
if(TimeMask == 0 ){
if(QueueBroadcastState == USEFULL) {
OSPostTask(routeSendBroadcast);
}else if(QueueLocalMsgState == USEFULL){
OSPostTask(routeSendLocalMsg);
}else{
if(QueueLocalMsgState == IDLE) LocalDataIn();
if( OS_LOCAL_ADDRESS != SINKNODE){
OSPostTask(routeSendTask); //调度发送任务,完成数据向MAC的传送
}
}
}else {
TimeMask--;
}
}
/**************************************************************************
*功能描述:调用MAC层函数实现广播包发送
*参数说明:
*返回值:
**************************************************************************/
static void routeSendBroadcast(void){
MACBroadcastMsg(&QueueBroadcast.Msg, QueueBroadcast.length);
}
/**************************************************************************
*功能描述:调用MAC层函数实现本地数据包发送
*参数说明:
*返回值:
**************************************************************************/
static void routeSendLocalMsg(void){
//本地的数据包直接以currentparent为下一跳地址
if(currentparent != INVALID_NODE_ID) {
MACUnicastMsg(&QueueLocalMsg.Msg, QueueLocalMsg.length,currentparent);
}
}
/**************************************************************************
*功能描述:调用MAC层函数实现发送
*参数说明:
*返回值:
**************************************************************************/
//读队列数据的时候可以写,但是写的时候不能读
static void routeSendTask(void) {
SHopMsgPtr sHopMsg;
if (QueueIdle == FALSE ) return ; //正在写队列
if (Queuemsgqueue[dequeue_next].length != 0) { //队列中还有消息存在 则
if(currentparent == INVALID_NODE_ID) return ;
nextAddr = CheckRoute(&Queuemsgqueue[dequeue_next].Msg);
if (nextAddr != INVALID_NODE_ID) {
MACUnicastMsg(&Queuemsgqueue[dequeue_next].Msg, Queuemsgqueue[dequeue_next].length,nextAddr);
} else{ //如果currentparent存在但是没有可以解决循环路由的合适的下一跳节点,drop该数据项
/*Queuemsgqueue[dequeue_next].length = 0;
dequeue_next++;
dequeue_next %= MESSAGE_QUEUE_SIZE;
FreeAreaInQueue = FreeAreaInQueue + 1;*/
sHopMsg = (SHopMsgPtr )Queuemsgqueue[dequeue_next].Msg.data;
if(sHopMsg->lifetime >= 1 ){
sHopMsg->lifetime = (sHopMsg->lifetime)|0xF0;
MACUnicastMsg(&Queuemsgqueue[dequeue_next].Msg, Queuemsgqueue[dequeue_next].length,currentparent);
}else{
Queuemsgqueue[dequeue_next].length = 0;
dequeue_next++;
dequeue_next %= MESSAGE_QUEUE_SIZE;
FreeAreaInQueue = FreeAreaInQueue + 1;
}
}
} else {
if( dequeue_next !=enqueue_next ) {
dequeue_next = (dequeue_next + 1)%MESSAGE_QUEUE_SIZE;
}
}
}
/**************************************************************************
*功能描述:数据包发送完成后的处理
*参数说明:发送出去的数据包地址
*返回值:
**************************************************************************/
result_t TransmitDone(OSMACMsgPtr msg) {
uint8_t type;
SHopMsgPtr sHopMsg;
sHopMsg = (SHopMsgPtr )msg->data;
type = sHopMsg->type;
switch (type) {
case BROADCAST: //发送广播包结束
if (msg != &QueueBroadcast.Msg) {
return FAIL;
}
QueueBroadcastState = IDLE;
routeBroadcastDone(msg);
break;
case SENSOR: //发送数据包结束
TimeMask = 4;//如果数据报发送成功,为了保证上层节点发送数据包时不冲突,尽量退避
if (msg == &Queuemsgqueue[dequeue_next].Msg) {
Queuemsgqueue[dequeue_next].length = 0;
dequeue_next++;
dequeue_next %= MESSAGE_QUEUE_SIZE;
FreeAreaInQueue = FreeAreaInQueue + 1;
}else if(msg == &QueueLocalMsg.Msg){
QueueLocalMsgState = IDLE;
}
routeSendSENSORDone(msg);
break;
}
return SUCCESS;
}
result_t GetFreeQueueLength(void){
return FreeAreaInQueue;
}
void SendFail(OSMACMsgPtr receivemsg){
RouteChangeP(receivemsg->toAddr);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -