⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cc2420receivep.nc

📁 tinyos2.0版本驱动
💻 NC
字号:
/* * Copyright (c) 2005-2006 Arch Rock Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * - Redistributions of source code must retain the above copyright *   notice, this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright *   notice, this list of conditions and the following disclaimer in the *   documentation and/or other materials provided with the *   distribution. * - Neither the name of the Arch Rock Corporation nor the names of *   its contributors may be used to endorse or promote products derived *   from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE * ARCHED ROCK OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE *//** * @author Jonathan Hui <jhui@archrock.com> * @author David Moss * @author Jung Il Choi * @version $Revision: 1.11 $ $Date: 2008/06/04 05:36:21 $ */#include "IEEE802154.h"#include "message.h"#include "AM.h"module CC2420ReceiveP {  provides interface Init;  provides interface StdControl;  provides interface CC2420Receive;  provides interface Receive;  provides interface ReceiveIndicator as PacketIndicator;  uses interface GeneralIO as CSN;  uses interface GeneralIO as FIFO;  uses interface GeneralIO as FIFOP;  uses interface GpioInterrupt as InterruptFIFOP;  uses interface Resource as SpiResource;  uses interface CC2420Fifo as RXFIFO;  uses interface CC2420Strobe as SACK;  uses interface CC2420Strobe as SFLUSHRX;  uses interface CC2420Packet;  uses interface CC2420PacketBody;  uses interface CC2420Config;    uses interface Leds;}implementation {  typedef enum {    S_STOPPED,    S_STARTED,    S_RX_LENGTH,    S_RX_FCF,    S_RX_PAYLOAD,  } cc2420_receive_state_t;  enum {    RXFIFO_SIZE = 128,    TIMESTAMP_QUEUE_SIZE = 8,    SACK_HEADER_LENGTH = 7,  };  uint16_t m_timestamp_queue[ TIMESTAMP_QUEUE_SIZE ];    uint8_t m_timestamp_head;    uint8_t m_timestamp_size;    /** Number of packets we missed because we were doing something else */  uint8_t m_missed_packets;    /** TRUE if we are receiving a valid packet into the stack */  bool receivingPacket;    /** The length of the frame we're currently receiving */  norace uint8_t rxFrameLength;    norace uint8_t m_bytes_left;    norace message_t* ONE_NOK m_p_rx_buf;  message_t m_rx_buf;    cc2420_receive_state_t m_state;    /***************** Prototypes ****************/  void reset_state();  void beginReceive();  void receive();  void waitForNextPacket();  void flush();  bool passesAddressCheck(message_t * ONE msg);    task void receiveDone_task();    /***************** Init Commands ****************/  command error_t Init.init() {    m_p_rx_buf = &m_rx_buf;    return SUCCESS;  }  /***************** StdControl ****************/  command error_t StdControl.start() {    atomic {      reset_state();      m_state = S_STARTED;      atomic receivingPacket = FALSE;      call InterruptFIFOP.enableFallingEdge();    }    return SUCCESS;  }    command error_t StdControl.stop() {    atomic {      m_state = S_STOPPED;      reset_state();      call CSN.set();      call InterruptFIFOP.disable();    }    return SUCCESS;  }  /***************** CC2420Receive Commands ****************/  /**   * Start frame delimiter signifies the beginning/end of a packet   * See the CC2420 datasheet for details.   */  async command void CC2420Receive.sfd( uint16_t time ) {    if ( m_timestamp_size < TIMESTAMP_QUEUE_SIZE ) {      uint8_t tail =  ( ( m_timestamp_head + m_timestamp_size ) %                         TIMESTAMP_QUEUE_SIZE );      m_timestamp_queue[ tail ] = time;      m_timestamp_size++;    }  }  async command void CC2420Receive.sfd_dropped() {    if ( m_timestamp_size ) {      m_timestamp_size--;    }  }  /***************** PacketIndicator Commands ****************/  command bool PacketIndicator.isReceiving() {    bool receiving;    atomic {      receiving = receivingPacket;    }    return receiving;  }      /***************** InterruptFIFOP Events ****************/  async event void InterruptFIFOP.fired() {    if ( m_state == S_STARTED ) {      beginReceive();          } else {      m_missed_packets++;    }  }      /***************** SpiResource Events ****************/  event void SpiResource.granted() {    receive();  }    /***************** RXFIFO Events ****************/  /**   * We received some bytes from the SPI bus.  Process them in the context   * of the state we're in.  Remember the length byte is not part of the length   */  async event void RXFIFO.readDone( uint8_t* rx_buf, uint8_t rx_len,                                    error_t error ) {    cc2420_header_t* header = call CC2420PacketBody.getHeader( m_p_rx_buf );    cc2420_metadata_t* metadata = call CC2420PacketBody.getMetadata( m_p_rx_buf );    uint8_t tmpLen __DEPUTY_UNUSED__ = sizeof(message_t) - (offsetof(message_t, data) - sizeof(cc2420_header_t));    uint8_t* COUNT(tmpLen) buf = TCAST(uint8_t* COUNT(tmpLen), header);    rxFrameLength = buf[ 0 ];    switch( m_state ) {    case S_RX_LENGTH:      m_state = S_RX_FCF;      if ( rxFrameLength + 1 > m_bytes_left ) {        // Length of this packet is bigger than the RXFIFO, flush it out.        flush();              } else {        if ( !call FIFO.get() && !call FIFOP.get() ) {          m_bytes_left -= rxFrameLength + 1;        }                if(rxFrameLength <= MAC_PACKET_SIZE) {          if(rxFrameLength > 0) {            if(rxFrameLength > SACK_HEADER_LENGTH) {              // This packet has an FCF byte plus at least one more byte to read              call RXFIFO.continueRead(buf + 1, SACK_HEADER_LENGTH);                          } else {              // This is really a bad packet, skip FCF and get it out of here.              m_state = S_RX_PAYLOAD;              call RXFIFO.continueRead(buf + 1, rxFrameLength);            }                                      } else {            // Length == 0; start reading the next packet            atomic receivingPacket = FALSE;            call CSN.set();            call SpiResource.release();            waitForNextPacket();          }                  } else {          // Length is too large; we have to flush the entire Rx FIFO          flush();        }      }      break;          case S_RX_FCF:      m_state = S_RX_PAYLOAD;            /*       * The destination address check here is not completely optimized. If you        * are seeing issues with dropped acknowledgements, try removing       * the address check and decreasing SACK_HEADER_LENGTH to 2.       * The length byte and the FCF byte are the only two bytes required       * to know that the packet is valid and requested an ack.  The destination       * address is useful when we want to sniff packets from other transmitters       * while acknowledging packets that were destined for our local address.       */      if(call CC2420Config.isAutoAckEnabled() && !call CC2420Config.isHwAutoAckDefault()) {        if (((( header->fcf >> IEEE154_FCF_ACK_REQ ) & 0x01) == 1)            && ((header->dest == call CC2420Config.getShortAddr())                || (header->dest == AM_BROADCAST_ADDR))            && ((( header->fcf >> IEEE154_FCF_FRAME_TYPE ) & 7) == IEEE154_TYPE_DATA)) {          // CSn flippage cuts off our FIFO; SACK and begin reading again          call CSN.set();          call CSN.clr();          call SACK.strobe();          call CSN.set();          call CSN.clr();          call RXFIFO.beginRead(buf + 1 + SACK_HEADER_LENGTH,               rxFrameLength - SACK_HEADER_LENGTH);          return;        }      }            // Didn't flip CSn, we're ok to continue reading.      call RXFIFO.continueRead(buf + 1 + SACK_HEADER_LENGTH,           rxFrameLength - SACK_HEADER_LENGTH);      break;        case S_RX_PAYLOAD:      call CSN.set();            if(!m_missed_packets) {        // Release the SPI only if there are no more frames to download        call SpiResource.release();      }            if ( m_timestamp_size ) {        if ( rxFrameLength > 10 ) {          metadata->time = m_timestamp_queue[ m_timestamp_head ];          m_timestamp_head = ( m_timestamp_head + 1 ) % TIMESTAMP_QUEUE_SIZE;          m_timestamp_size--;        }      } else {        metadata->time = 0xffff;      }            // We may have received an ack that should be processed by Transmit      // buf[rxFrameLength] >> 7 checks the CRC      if ( ( buf[ rxFrameLength ] >> 7 ) && rx_buf ) {        uint8_t type = ( header->fcf >> IEEE154_FCF_FRAME_TYPE ) & 7;        signal CC2420Receive.receive( type, m_p_rx_buf );        if ( type == IEEE154_TYPE_DATA ) {          post receiveDone_task();          return;        }      }            waitForNextPacket();      break;    default:      atomic receivingPacket = FALSE;      call CSN.set();      call SpiResource.release();      break;          }      }  async event void RXFIFO.writeDone( uint8_t* tx_buf, uint8_t tx_len, error_t error ) {  }      /***************** Tasks *****************/  /**   * Fill in metadata details, pass the packet up the stack, and   * get the next packet.   */  task void receiveDone_task() {    cc2420_metadata_t* metadata = call CC2420PacketBody.getMetadata( m_p_rx_buf );    cc2420_header_t* header = call CC2420PacketBody.getHeader( m_p_rx_buf);    uint8_t tmpLen __DEPUTY_UNUSED__ = sizeof(message_t) - (offsetof(message_t, data) - sizeof(cc2420_header_t));    uint8_t* COUNT(tmpLen) buf = TCAST(uint8_t* COUNT(tmpLen), header);        metadata->crc = buf[ rxFrameLength ] >> 7;    metadata->lqi = buf[ rxFrameLength ] & 0x7f;    metadata->rssi = buf[ rxFrameLength - 1 ];        if(passesAddressCheck(m_p_rx_buf)) {      m_p_rx_buf = signal Receive.receive( m_p_rx_buf, m_p_rx_buf->data,           rxFrameLength );    }        atomic receivingPacket = FALSE;    waitForNextPacket();  }    /****************** CC2420Config Events ****************/  event void CC2420Config.syncDone( error_t error ) {  }    /****************** Functions ****************/  /**   * Attempt to acquire the SPI bus to receive a packet.   */  void beginReceive() {     m_state = S_RX_LENGTH;        atomic receivingPacket = TRUE;    if(call SpiResource.isOwner()) {      receive();          } else if (call SpiResource.immediateRequest() == SUCCESS) {      receive();          } else {      call SpiResource.request();    }  }    /**   * Flush out the Rx FIFO   */  void flush() {    reset_state();    call CSN.set();    call CSN.clr();    call SFLUSHRX.strobe();    call SFLUSHRX.strobe();    call CSN.set();    call SpiResource.release();    waitForNextPacket();  }    /**   * The first byte of each packet is the length byte.  Read in that single   * byte, and then read in the rest of the packet.  The CC2420 could contain   * multiple packets that have been buffered up, so if something goes wrong,    * we necessarily want to flush out the FIFO unless we have to.   */  void receive() {    call CSN.clr();    call RXFIFO.beginRead( (uint8_t*)(call CC2420PacketBody.getHeader( m_p_rx_buf )), 1 );  }  /**   * Determine if there's a packet ready to go, or if we should do nothing   * until the next packet arrives   */  void waitForNextPacket() {    atomic {      if ( m_state == S_STOPPED ) {        call SpiResource.release();        return;      }            atomic receivingPacket = FALSE;            /*       * The FIFOP pin here is high when there are 0 bytes in the RX FIFO       * and goes low as soon as there are bytes in the RX FIFO.  The pin       * is inverted from what the datasheet says, and its threshold is 127.       * Whenever the FIFOP line goes low, as you can see from the interrupt       * handler elsewhere in this module, it means we received a new packet.       * If the line stays low without generating an interrupt, that means       * there's still more data to be received.       */      if ( ( m_missed_packets && call FIFO.get() ) || !call FIFOP.get() ) {        // A new packet is buffered up and ready to go        if ( m_missed_packets ) {          m_missed_packets--;        }                beginReceive();              } else {        // Wait for the next packet to arrive        m_state = S_STARTED;        m_missed_packets = 0;        call SpiResource.release();      }    }  }    /**   * Reset this component   */  void reset_state() {    m_bytes_left = RXFIFO_SIZE;    atomic receivingPacket = FALSE;    m_timestamp_head = 0;    m_timestamp_size = 0;    m_missed_packets = 0;  }  /**   * @return TRUE if the given message passes address recognition   */  bool passesAddressCheck(message_t *msg) {    cc2420_header_t *header = call CC2420PacketBody.getHeader( msg );        if(!(call CC2420Config.isAddressRecognitionEnabled())) {      return TRUE;    }        return (header->dest == call CC2420Config.getShortAddr()        || header->dest == AM_BROADCAST_ADDR);  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -