?? spp.c
字號(hào):
/******************************************************************************
Filename: spp.c
Target: cc2430
Revised: 16/12-2005
Revision: 1.0
******************************************************************************/
#include <string.h>
#include "cul.h"
#include <stdio.h>
// protos
void rxCallBack(void);
void ackTimeout(void);
BOOL ackReceived(BYTE sourceAddress);
void sendAck(SPP_RX_STRUCT* receivedPacket);
void waitForAck(void);
static DMA_DESC* dmaTx; // pointer to the DMA descriptor for transmit.
static DMA_DESC* dmaRx; // pointer to the DMA descriptor for receive.
static BYTE dmaNumberTx = 0; // number indicating which DMA channel is used for transmit.
static BYTE dmaNumberRx = 0; // number indicating which DMA channel is used for receive.
static BYTE myAddress;
volatile BYTE sppRxStatus = 0;
volatile BYTE sppTxStatus = 0;
static BYTE pAckBuffer[7];
static SPP_TX_STRUCT* pAckData;
static volatile UINT8 retransmissionCounter;
static UINT8 ackTimerNumber;
static FUNCTION* rxCallBackFunction;
//-----------------------------------------------------------------------------
// See cul.h for a description of this function.
//-----------------------------------------------------------------------------
//設(shè)置用戶(hù)指定的回調(diào)函數(shù),在接收到一個(gè)正確的數(shù)據(jù)包死運(yùn)行
//通過(guò)這個(gè)函數(shù)可以用程序來(lái)改變正確接收數(shù)據(jù)包后的動(dòng)作。
//callBackFunction 用戶(hù)指定的函數(shù)
//rxCallBackFunction 指向 FUNCTION 的全局變量指針變量
void sppSetRxCallBackFunction(FUNCTION* callBackFunction)
{
rxCallBackFunction = callBackFunction;
} // Ends sppSetRxCallBackFunction()
//發(fā)送應(yīng)答
//SPP_RX_STRUCT 定義在 cul.h
//SFR( RFD , 0xD9 ) // RF Data 定義在ioCC2430.h
// myAddress 全局變量
// ACK cul.h 中宏定義
// ISTXON hal.h 中宏定義
// srcAddress 源地址
void sendAck(SPP_RX_STRUCT* receivedPacket)
{
RFD = SPP_HEADER_AND_FOOTER_LENGTH + SPP_ACK_LENGTH;
RFD = receivedPacket->srcAddress;
RFD = myAddress;
RFD = ACK;
RFD = 0;
RFIF &= ~IRQ_TXDONE;
ISTXON;
while(!(RFIF & IRQ_TXDONE));
return;
}
//------------------------------------------------------------------------------------------------------
// void rxCallBack(...)
//
// Description:
// This function is called by the interrupt routine when the Rx DMA channel
// finishes the data transfer. The received packet's destination address
// is checked. If not addressed to this node, or if the CRC value is not
// correct, the packet is erased. An ACK is sent if the packet
// tells to. A user defined callback function may is run if set (set
// with setRxCallBackFunction())
//在Rx DAM 通道完成數(shù)據(jù)傳輸后由中斷程序調(diào)用。檢查接收包掉的目的地址,如果地址不是
//這個(gè)節(jié)點(diǎn)的,或CRC值是錯(cuò)誤的,包裝將被擦除。如果數(shù)據(jù)包被告知將發(fā)送一個(gè)應(yīng)答。一個(gè)用戶(hù)定義的回調(diào)函數(shù)可以運(yùn)行如果定義了的話(huà)。
// Arguments:
// void
//
// Return value:
// void
//-----------------------------------------------------------------------------
//#define RXFIFOCNT XREG( 0xDF53 ) /* Receive FIFO Count 定義在ioCC2430.h
// ISFLUSHRX 清 RX FIFO 命令濾波. hal.h 命令濾波中定義
// GET_DMA_DEST(dmaRx) hal.h 中的宏定義,取得一個(gè) DMA 通道的目標(biāo)地址
// static DMA_DESC* dmaRx 指向設(shè)備 DMA 描述符的指針,全局變量.DMA_DESC DMA 配置結(jié)構(gòu)。
//
void rxCallBack(void)
{
SPP_RX_STRUCT __xdata* receivedPacket;
BYTE res = FALSE;
if(RXFIFOCNT > 0)
{
ISFLUSHRX;
ISFLUSHRX;
}
// Investigating the received packet.
// Checking the destination address and that the CRC is OK.
// The message is ACK'ed if it tells to.
receivedPacket = (SPP_RX_STRUCT __xdata*) GET_DMA_DEST(dmaRx);
receivedPacket->payloadLength = receivedPacket->payloadLength-SPP_HEADER_AND_FOOTER_LENGTH; //減去頭和尾長(zhǎng)度
if((receivedPacket->destAddress == myAddress) || (receivedPacket->destAddress == BROADCAST_ADDRESS)) //包目的地是本節(jié)點(diǎn)地址或廣播地址
{
if(receivedPacket->payload[receivedPacket->payloadLength+1] & 0x80) //CRC正確
{
if(receivedPacket->flags == ACK) //收到了應(yīng)答包
{
res = ackReceived(receivedPacket->srcAddress);
}
else //收到普通數(shù)據(jù)包
{
sppRxStatus = PACKET_RECEIVED; //ssp接收狀態(tài)-收到數(shù)據(jù)包
res = TRUE;
if(receivedPacket->flags & DO_ACK) //要求收到后發(fā)應(yīng)答
{
sendAck(receivedPacket); //發(fā)應(yīng)答
}
sppRxStatus = RX_COMPLETE; //ssp接收狀態(tài)-接收完成
if(rxCallBackFunction)
{
rxCallBackFunction(); //調(diào)用用戶(hù)指定回調(diào)函數(shù)
}
}
}
}
if(res == FALSE)
{
ISFLUSHRX; //清RX FIFO
ISFLUSHRX;
// rearming DMA channel
DMA_ARM_CHANNEL(dmaNumberRx);
RFIM |= IRQ_SFD;
sppRxStatus = RX_WAIT;
}
return;
} // ends rxCallBack
//-----------------------------------------------------------------------------
// void ackTimeout(...)
//
// Description:
// This function resends a packet if it is not ACK'ed by the recipient
// within _ACK_TIMEOUT_ m-seconds. The message is resent _ACK_RETRIES_ times.
// If the message remains un-ACK'ed, transmission is aborted and spp TX
// status is set to DEST_UNREACHABLE.
//如果沒(méi)有收到接收器返回的應(yīng)答,將重新發(fā)送數(shù)據(jù)包
// Arguments:
// void
//
// Return value:
// void
//-----------------------------------------------------------------------------
// TIMER4_RUN() 宏函數(shù)在 hal.h 中定義
// #define ACK_RETRIES 3 在 hal.h 中的宏定義常數(shù)
void ackTimeout(void){
culTimer4AdmClear(ackTimerNumber);
if(pAckData != NULL)
{
if(retransmissionCounter < ACK_RETRIES) //重發(fā)次數(shù)小于嘗試接收應(yīng)答次數(shù)
{
// Resending the message.
pAckData->flags |= RETRANSMISSION; //數(shù)據(jù)包標(biāo)志-重發(fā)
TIMER4_RUN(FALSE); //停止定時(shí)器4
sppSend(pAckData); //發(fā)送數(shù)據(jù)包
T4CNT = 0; //定時(shí)器4計(jì)數(shù)清零
TIMER4_RUN(TRUE); //定時(shí)器4開(kāi)始運(yùn)行
retransmissionCounter++;
}
else
{
// The packet has been resent too many times. Assuming that the node is unreacheble.
pAckData = 0;
retransmissionCounter = 0;
sppTxStatus = DEST_UNREACHABLE; //ssp發(fā)送狀態(tài)-不能完成
RFIM &= ~IRQ_FIFOP;
}
}
return;
} // ends ackTimeout
//-----------------------------------------------------------------------------
// See cul.h for a description of this function.
// 初始化簡(jiǎn)單的數(shù)據(jù)包裝協(xié)議Simple Packet Protocol (SPP)
// 從 DMA 管理器申請(qǐng)兩個(gè) DMA 通道,用于分別從 Rx FIFO 和 Tx FIFO 傳輸數(shù)據(jù)。定時(shí)器4
// 管理器同樣被設(shè)置,這個(gè)單元用于在數(shù)據(jù)包發(fā)送后接收器在一定時(shí)間內(nèi)沒(méi)有返回應(yīng)答時(shí)
// 產(chǎn)生中斷。無(wú)線(xiàn)部分配置為發(fā)送,工作在特定的頻率,在發(fā)送時(shí)自動(dòng)計(jì)算和插入和檢查CRC值。
//-----------------------------------------------------------------------------
BOOL sppInit(UINT32 frequency, BYTE address){
BYTE res = 0;
BOOL status = TRUE;
sppSetAddress(address);
// Clearing the states of the spp.
sppTxStatus = TX_IDLE; //在 cul.h TX 和 RX 狀態(tài)標(biāo)志部分宏定義
sppRxStatus = RX_IDLE; //同上
retransmissionCounter = 0;
ackTimerNumber = 0;
pAckData = 0;
// Clearing the RF interrupt flags and enable mask and enabling RF interrupts
RFIF = 0;
RFIM = 0;
INT_SETFLAG(INUM_RF,INT_CLR);
INT_ENABLE(INUM_RF,INT_ON);
// Setting the frequency and initialising the radio
res = halRfConfig(frequency); //在rfconfig.c
if(res == FALSE){
status = FALSE;
}
// Setting the number of bytes to assert the FIFOP flag
IOCFG0 = 7;
INT_SETFLAG(INUM_RFERR, INT_CLR);
INT_ENABLE(INUM_RFERR, INT_ON);
// Flushing both Tx and Rx FiFo. The flush-Rx is issued twice to reset the SFD.
// Calibrating the radio and turning on Rx to evaluate the CCA.
// SFD 開(kāi)始幀定界符
SRXON;
SFLUSHTX;
SFLUSHRX;
SFLUSHRX;
STXCALN;
ISSTART;
// Using the timer 4 administrator to generate interrupt to check if a message is unacked...
culTimer4AdmInit();
// Initialising the DMA administrator
culDmaInit();
// Requesting a DMA channel for transmit data. No callback function is used. Instead the TX_DONE
// interrupt is used to determine when a transfer is finished. Configuring the DMA channel for
// transmit. The data address and length will be set prior to each specific transmission.
dmaTx = culDmaAllocChannel(&dmaNumberTx, 0);
if((dmaNumberTx == 0) || (dmaNumberTx > 4)){
status = FALSE;
}
culDmaToRadio(dmaTx, 0, 0, FALSE);
// Requesting a DMA channel for receiving data. Giving the address of the callback function.
// Configuring the DMA channel for receive. The data address will be set prior to each specific
// reception.
dmaRx = culDmaAllocChannel(&dmaNumberRx, &rxCallBack);
if((dmaNumberRx == 0) || (dmaNumberRx > 4)){
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -