📄 physical.c
字号:
/*
****************************************************************************
*
* 宁波中科集成电路设计中心 版权所有 Copyright 2005
*
*文件名: Physical.c
*程序员:
*主要内容:物理层调度控制
*完成日期:2005.5.25
****************************************************************************
*/
#include "physical.h"
#include "message.h"
#include "radiocontrol.h"
#include "os.h"
#include "mac.h"
#include "led.h"
extern uint8_t OS_BCAST_ADDR;
// 物理层状态值
enum {
IDLE,
RECEIVING,
TRANSMITTING,
TRANSMITTING_LAST,
TRANSMITTING_DONE
};
enum {FREE, BUSY}; // 缓存状态
static char state; // 物理层状态变量
uint8_t pktLength; // 包括包头的包长度
OSMACMsg buffer1; // 用于接收和处理的缓存空间
OSMACMsg buffer2;
char recvBufState; // 接收缓存状态
char procBufState; // 处理缓存状态
char* procBufPtr; // 处理缓存地址,用于接收和处理缓存地址交换
char* sendPtr; // 指向发送缓存,由上层分配
char* recvPtr; // 指向接收缓存
char* procPtr; // 指向处理缓存
static uint8_t txCount; // 发送字节计数变量
uint8_t recvCount; // 接收字节计数变量
int16_t crcRx; // 接收数据包CRC计算结果
int16_t crcTx; // 发送数据包CRC计算结果
/*************************************************************************
*功能描述:16位CRC计算
*参数说明:待计算的八位数据,上一次计算的CRC结果
*返回值: CRC计算一次后的结果
**************************************************************************/
int16_t update_crc(char data, int16_t crc)
{
char i;
int16_t tmp;
tmp = (int16_t)(data);
crc = crc ^ (tmp << 8);
for (i = 0; i < 8; i++) {
if (crc & 0x8000)
crc = (crc << 1) ^ 0x1021; // << is done before ^
else
crc = crc << 1;
}
return crc;
}
/*************************************************************************
*功能描述:数据包接收完成任务函数,通知MAC接收处理缓存中的包,并清空处理缓存
* 和接收缓存
*参数说明:无
*返回值: 无
**************************************************************************/
void packet_received(void)
{
void* tmp;
char error, intEnabled;
uint8_t len;
len = (uint8_t)procPtr[0];
if (crcRx != *(int16_t*)(procPtr + len - 2)) {
error = 1;
} else {
error = 0;
}
tmp = MACPhysicalRxPktDone(procPtr, error); // 通知MAC对接收到的数据包进行处理
if (tmp) {
intEnabled = (* (volatile unsigned char *) (0x3F + 0x20)) & 0x80;
* (volatile unsigned char *) (0x3F + 0x20) &= ~0x80; // 关中断
if (recvBufState == BUSY) { // 接收缓冲中有数据待处理
procPtr = recvPtr; // 处理缓冲获得待处理数据地址
recvPtr = (char*)tmp; // 接收缓冲置空闲,可用于接收
recvBufState = FREE;
} else {
procPtr = 0; // 接收缓冲中无数据
procBufPtr = (char *)tmp;
procBufState = FREE; // 处理缓冲可用
}
if (intEnabled)
* (volatile unsigned char *) (0x3F + 0x20) |= 0x80; // 开中断
if (procPtr) { // 处理从接收缓冲得到的数据
if ( !OSPostTask(packet_received) ) { // 任务队列满,丢弃数据包
procBufPtr = procPtr;
procBufState = FREE;
MACPhysicalRxPktDone((void *) 0, 1); // 通知MAC
}
}
}
}
/*************************************************************************
*功能描述:数据包发送完成任务函数,通知MAC数据包已经发送
*参数说明:无
*返回值: 无
**************************************************************************/
void packet_sent(void)
{
MACPhysicalTxPktDone(sendPtr);
}
/*************************************************************************
*功能描述:物理层初始化
*参数说明:无
*返回值: 无
**************************************************************************/
result_t PhysicalInit(void)
{
state = IDLE;
recvPtr = (char*)&buffer1;
procBufPtr = (char*)&buffer2;
recvBufState = FREE;
procBufState = FREE;
RadiocontrolInit();
return SUCCESS;
}
/*************************************************************************
*功能描述:物理层进入空闲状态
*参数说明:无
*返回值: 无
**************************************************************************/
result_t PhysicalIdle(void)
{
RadiocontrolIdle();
state = IDLE;
return SUCCESS;
}
/*************************************************************************
*功能描述:物理层进入睡眠状态
*参数说明:无
*返回值: 无
**************************************************************************/
result_t PhysicalSleep(void)
{
RadiocontrolSleep();
state = IDLE;
return SUCCESS;
}
/*************************************************************************
*功能描述:物理层发送数据包接口函数,进入发送状态,启动整个发送流程
*参数说明:packet:数据包地址 length:物理层要发送的字节数
*返回值: 无
**************************************************************************/
result_t PhysicalTxPkt(void* packet, uint8_t length)
{
if (length > MAX_PKT_LEN || length < MIN_PKT_LEN)
return FAIL;
if (state != IDLE && state != RECEIVING)
return FAIL;
state = TRANSMITTING;
RadiocontrolStartTx();
sendPtr = (char*)packet;
((OSMACMsgPtr)sendPtr)->length = length;
pktLength = length;
txCount = 0;
crcTx=update_crc(sendPtr[0], 0);
return SUCCESS;
}
/*************************************************************************
*功能描述:发送未完成时,准备下一个要发送的字节,发送完成时进入空闲状态并通知上层
*参数说明:无
*返回值: 无
**************************************************************************/
result_t PhysicalTxByteReady(void)
{ // 射频控制模块获得数据包下一个字节
if(state == TRANSMITTING) {
RadiocontrolTxNextByte(sendPtr[txCount]);
txCount++;
if (txCount < pktLength) { // 不是最后一个字节
if(txCount < pktLength - 2){ // 是否要计算CRC
crcTx=update_crc(sendPtr[txCount], crcTx);
}
if(txCount == pktLength - 2){ // 存入CRC结果
*(int16_t *)(sendPtr + pktLength - 2) = crcTx;
}
} else {
if (txCount == pktLength) { // 发送最后字节
state = TRANSMITTING_LAST;
}
}
} else if (state == TRANSMITTING_LAST) {
state = TRANSMITTING_DONE;
} else if (state == TRANSMITTING_DONE) {
RadiocontrolIdle(); // 射频控制转入空闲
state = IDLE;
OSPostTask(packet_sent); // 通知上层发送完成
}
return SUCCESS;
}
/*************************************************************************
*功能描述:检测到起始符号,通知MAC,准备接收数据,将缓存地址传给MAC
*参数说明:无
*返回值: 无
**************************************************************************/
result_t PhysicalStartSymDetected(void)
{
// 物理层处于空闲状态时
if (state == IDLE && recvBufState == FREE) {
state = RECEIVING;
recvCount = 0;
// MAC层可通过此调用对接收缓存中的字段打时间戳
MACStartSymDetected(recvPtr);
return SUCCESS;
}
return FAIL;
}
/*************************************************************************
*功能描述:将收到的字节打包成数据包,并发出包处理任务
*参数说明:收到的字节
*返回值: 执行结果
**************************************************************************/
result_t PhysicalRxByteDone(char data)
{
if (state != RECEIVING)
return FAIL;
if (recvCount == 0) { // 第一个字节为包长度
if ((uint8_t)data > MAX_PKT_LEN
|| (uint8_t)data < MIN_PKT_LEN) { // 包太长或太短,不能正确接收
RadiocontrolIdle();
state = IDLE;
// 通知上层接收包出错
MACPhysicalRxPktDone((void *) 0, 1);
return FAIL;
}
pktLength = (uint8_t)data; // 得到包长度
crcRx = 0;
}
recvPtr[recvCount] = data;
recvCount++;
if (recvCount < pktLength - 1) {
crcRx=update_crc(data, crcRx);
} else if (recvCount == pktLength) { // 接收完成
if (procBufState == FREE) { // 处理缓存区可用
procPtr = recvPtr; // 数据包存入处理缓存区
recvPtr = procBufPtr; // 接收缓存与处理缓存交换地址
recvBufState = FREE; // 接收缓存可用
if (OSPostTask(packet_received) ) { // 发出接收处理任务
procBufState = BUSY;
} else { // 任务队列满
procBufPtr = procPtr; // 丢包
MACPhysicalRxPktDone((void *) 0, 1); // 通知MAC已丢包
}
} else { // 处理缓存不可用时不能再接收数据
recvBufState = BUSY;
}
RadiocontrolIdle(); // 转入空闲状态
state = IDLE;
}
return SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -