📄 cc2420radiom.nc
字号:
// $Id: CC2420RadioM.nc,v 1.42 2005/08/15 18:04:55 jpolastre Exp $/* tab:4 * "Copyright (c) 2000-2003 The Regents of the University of California. * All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice, the following * two paragraphs and the author appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." * * Copyright (c) 2002-2003 Intel Corporation * All rights reserved. * * This file is distributed under the terms in the attached INTEL-LICENSE * file. If you do not find these files, copies can be found by writing to * Intel Research Berkeley, 2150 Shattuck Avenue, Suite 1300, Berkeley, CA, * 94704. Attention: Intel License Inquiry. *//* * Authors: Joe Polastre * Date last modified: $Revision: 1.42 $ * * This module provides the layer2 functionality for the mica2 radio. * While the internal architecture of this module is not CC2420 specific, * It does make some CC2420 specific calls via CC2420Control. * * $Id: CC2420RadioM.nc,v 1.42 2005/08/15 18:04:55 jpolastre Exp $ *//** * @author Joe Polastre * @author Alan Broad, Crossbow */includes byteorder;module CC2420RadioM { provides { interface StdControl; interface SplitControl; interface BareSendMsg as Send; interface ReceiveMsg as Receive; interface RadioCoordinator as RadioSendCoordinator; interface RadioCoordinator as RadioReceiveCoordinator; interface MacControl; interface MacBackoff; } uses { interface SplitControl as CC2420SplitControl; interface CC2420Control; interface HPLCC2420 as HPLChipcon; interface HPLCC2420FIFO as HPLChipconFIFO; interface HPLCC2420Interrupt as FIFOP; interface HPLCC2420Capture as SFD; interface StdControl as TimerControl; interface TimerJiffyAsync as BackoffTimerJiffy; interface Random; interface Leds; }}implementation { enum { DISABLED_STATE = 0, DISABLED_STATE_STARTTASK, IDLE_STATE, TX_STATE, TX_WAIT, PRE_TX_STATE, POST_TX_STATE, POST_TX_ACK_STATE, RX_STATE, POWER_DOWN_STATE, WARMUP_STATE, TIMER_INITIAL = 0, TIMER_BACKOFF, TIMER_ACK };#define MAX_SEND_TRIES 8 norace uint8_t countRetry; uint8_t stateRadio; norace uint8_t stateTimer; norace uint8_t currentDSN; norace bool bAckEnable; bool bPacketReceiving; uint8_t txlength; norace TOS_MsgPtr txbufptr; // pointer to transmit buffer norace TOS_MsgPtr rxbufptr; // pointer to receive buffer TOS_Msg RxBuf; // save received messages volatile uint16_t LocalAddr; ///********************************************************** //* local function definitions //**********************************************************/ void sendFailed() { atomic stateRadio = IDLE_STATE; txbufptr->length = txbufptr->length - MSG_HEADER_SIZE - MSG_FOOTER_SIZE; signal Send.sendDone(txbufptr, FAIL); } void flushRXFIFO() { call FIFOP.disable(); call HPLChipcon.read(CC2420_RXFIFO); //flush Rx fifo call HPLChipcon.cmd(CC2420_SFLUSHRX); call HPLChipcon.cmd(CC2420_SFLUSHRX); atomic bPacketReceiving = FALSE; call FIFOP.startWait(FALSE); } inline result_t setInitialTimer( uint16_t jiffy ) { stateTimer = TIMER_INITIAL; if (jiffy == 0) // set the minimum timer time return call BackoffTimerJiffy.setOneShot(2); return call BackoffTimerJiffy.setOneShot(jiffy); } inline result_t setBackoffTimer( uint16_t jiffy ) { stateTimer = TIMER_BACKOFF; if (jiffy == 0) // set the minimum timer time return call BackoffTimerJiffy.setOneShot(2); return call BackoffTimerJiffy.setOneShot(jiffy); } inline result_t setAckTimer( uint16_t jiffy ) { stateTimer = TIMER_ACK; return call BackoffTimerJiffy.setOneShot(jiffy); } /*************************************************************************** * PacketRcvd * - Radio packet rcvd, signal ***************************************************************************/ task void PacketRcvd() { TOS_MsgPtr pBuf; atomic { pBuf = rxbufptr; } pBuf = signal Receive.receive((TOS_MsgPtr)pBuf); atomic { if (pBuf) rxbufptr = pBuf; rxbufptr->length = 0; bPacketReceiving = FALSE; } } task void PacketSent() { TOS_MsgPtr pBuf; //store buf on stack atomic { stateRadio = IDLE_STATE; pBuf = txbufptr; pBuf->length = pBuf->length - MSG_HEADER_SIZE - MSG_FOOTER_SIZE; } signal Send.sendDone(pBuf,SUCCESS); } //********************************************************** //* Exported interface functions for Std/SplitControl //* StdControl is deprecated, use SplitControl //**********************************************************/ // This interface is depricated, please use SplitControl instead command result_t StdControl.init() { return call SplitControl.init(); } // Split-phase initialization of the radio command result_t SplitControl.init() { atomic { stateRadio = DISABLED_STATE; currentDSN = 0; bAckEnable = FALSE; bPacketReceiving = FALSE; rxbufptr = &RxBuf; rxbufptr->length = 0; } call TimerControl.init(); call Random.init(); LocalAddr = TOS_LOCAL_ADDRESS; return call CC2420SplitControl.init(); } event result_t CC2420SplitControl.initDone() { return signal SplitControl.initDone(); } default event result_t SplitControl.initDone() { return SUCCESS; } // This interface is depricated, please use SplitControl instead command result_t StdControl.stop() { return call SplitControl.stop(); } // split phase stop of the radio stack command result_t SplitControl.stop() { atomic stateRadio = DISABLED_STATE; call SFD.disable(); call FIFOP.disable(); call TimerControl.stop(); return call CC2420SplitControl.stop(); } event result_t CC2420SplitControl.stopDone() { return signal SplitControl.stopDone(); } default event result_t SplitControl.stopDone() { return SUCCESS; } task void startRadio() { result_t success = FAIL; atomic { if (stateRadio == DISABLED_STATE_STARTTASK) { stateRadio = DISABLED_STATE; success = SUCCESS; } } if (success == SUCCESS) call SplitControl.start(); } // This interface is depricated, please use SplitControl instead command result_t StdControl.start() { // if we put starting the radio from StdControl in a task, then it // delays executing until the other "start" functions are done. // the bug occurs when other components use the underlying bus in their // start() functions. since the radio is split phase, it acquires // the bus during SplitControl.start() but doesn't release it until // SplitControl.startDone(). Ideally, Main would be changed to // understand SplitControl and run each SplitControl serially. result_t success = FAIL; atomic { if (stateRadio == DISABLED_STATE) { // only allow the task to be posted once. if (post startRadio()) { success = SUCCESS; stateRadio = DISABLED_STATE_STARTTASK; } } } return success; } // split phase start of the radio stack (wait for oscillator to start) command result_t SplitControl.start() { uint8_t chkstateRadio; atomic chkstateRadio = stateRadio; if (chkstateRadio == DISABLED_STATE) { atomic { stateRadio = WARMUP_STATE; countRetry = 0; rxbufptr->length = 0; } call TimerControl.start(); return call CC2420SplitControl.start(); } return FAIL; } event result_t CC2420SplitControl.startDone() { uint8_t chkstateRadio; atomic chkstateRadio = stateRadio; if (chkstateRadio == WARMUP_STATE) { call CC2420Control.RxMode(); //enable interrupt when pkt rcvd call FIFOP.startWait(FALSE); // enable start of frame delimiter timer capture (timestamping) call SFD.enableCapture(TRUE); atomic stateRadio = IDLE_STATE; } signal SplitControl.startDone(); return SUCCESS; } default event result_t SplitControl.startDone() { return SUCCESS; } /************* END OF STDCONTROL/SPLITCONTROL INIT FUNCITONS **********/ /** * Try to send a packet. If unsuccessful, backoff again **/ void sendPacket() { uint8_t status; call HPLChipcon.cmd(CC2420_STXONCCA); status = call HPLChipcon.cmd(CC2420_SNOP); if ((status >> CC2420_TX_ACTIVE) & 0x01) { // wait for the SFD to go high for the transmit SFD call SFD.enableCapture(TRUE); } else { // try again to send the packet atomic stateRadio = PRE_TX_STATE; if (!(setBackoffTimer(signal MacBackoff.congestionBackoff(txbufptr) * CC2420_SYMBOL_UNIT))) { sendFailed(); } } } /** * Captured an edge transition on the SFD pin * Useful for time synchronization as well as determining * when a packet has finished transmission */ async event result_t SFD.captured(uint16_t time) { switch (stateRadio) { case TX_STATE: // wait for SFD to fall--indicates end of packet call SFD.enableCapture(FALSE); // if the pin already fell, disable the capture and let the next // state enable the cpature (bug fix from Phil Buonadonna) if (!TOSH_READ_CC_SFD_PIN()) { call SFD.disable(); } else { stateRadio = TX_WAIT; } // fire TX SFD event txbufptr->time = time; signal RadioSendCoordinator.startSymbol(8,0,txbufptr); // if the pin hasn't fallen, break out and wait for the interrupt // if it fell, continue on the to the TX_WAIT state if (stateRadio == TX_WAIT) { break; } case TX_WAIT: // end of packet reached stateRadio = POST_TX_STATE; call SFD.disable(); // revert to receive SFD capture call SFD.enableCapture(TRUE); // if acks are enabled and it is a unicast packet, wait for the ack if ((bAckEnable) && (txbufptr->addr != TOS_BCAST_ADDR)) { if (!(setAckTimer(CC2420_ACK_DELAY))) sendFailed(); } // if no acks or broadcast, post packet send done event else { if (!post PacketSent()) sendFailed(); } break; default: // fire RX SFD handler
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -