cc2420receivep.nc

来自「tinyos-2.x.rar」· NC 代码 · 共 831 行 · 第 1/2 页

NC
831
字号
/*
 * 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
 * @author JeongGil Ko
 * @author Razvan Musaloiu-E
 * @version $Revision: 1.22 $ $Date: 2009/10/28 21:09:52 $
 */

#include "IEEE802154.h"
#include "message.h"
#include "AM.h"

module CC2420ReceiveP @safe() {

  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 PacketTimeStamp<T32khz,uint32_t>;

  uses interface CC2420Strobe as SRXDEC;
  uses interface CC2420Register as SECCTRL0;
  uses interface CC2420Register as SECCTRL1;
  uses interface CC2420Ram as KEY0;
  uses interface CC2420Ram as KEY1;
  uses interface CC2420Ram as RXNONCE;
  uses interface CC2420Ram as RXFIFO_RAM;
  uses interface CC2420Strobe as SNOP;

  uses interface Leds;
}

implementation {

  typedef enum {
    S_STOPPED,
    S_STARTED,
    S_RX_LENGTH,
    S_RX_DEC,
    S_RX_DEC_WAIT,
    S_RX_FCF,
    S_RX_PAYLOAD,
  } cc2420_receive_state_t;

  enum {
    RXFIFO_SIZE = 128,
    TIMESTAMP_QUEUE_SIZE = 8,
    SACK_HEADER_LENGTH = 7,
  };

  uint32_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 */
#ifdef CC2420_HW_SECURITY
  norace uint8_t m_missed_packets;
#else
  uint8_t m_missed_packets;
#endif

  /** 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;
#ifdef CC2420_HW_SECURITY
  norace cc2420_receive_state_t m_state;
  norace uint8_t packetLength = 0;
  norace uint8_t pos = 0;
  norace uint8_t secHdrPos = 0;
  uint8_t nonceValue[16] = {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01};
  norace uint8_t skip;
  norace uint8_t securityOn = 0;
  norace uint8_t authentication = 0;
  norace uint8_t micLength = 0;
  uint8_t flush_flag = 0;
  uint16_t startTime = 0;

  void beginDec();
  void dec();
#else
  cc2420_receive_state_t m_state;
#endif

  /***************** 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;
      /* Note:
         We use the falling edge because the FIFOP polarity is reversed. 
         This is done in CC2420Power.startOscillator from CC2420ControlP.nc.
       */
      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( uint32_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 ) {
#ifndef CC2420_HW_SECURITY
      m_state = S_RX_LENGTH;
      beginReceive();
#else
      m_state = S_RX_DEC;
      atomic receivingPacket = TRUE;
      beginDec();
#endif
    } else {
      m_missed_packets++;
    }
  }

  /*****************Decryption Options*********************/
#ifdef CC2420_HW_SECURITY
  task void waitTask(){

    if(SECURITYLOCK == 1){
      post waitTask();
    }else{
      m_state = S_RX_DEC;
      beginDec();
    }
  }

  void beginDec(){
    if(call SpiResource.isOwner()) {
      dec();
    } else if (call SpiResource.immediateRequest() == SUCCESS) {
      dec();
    } else {
      call SpiResource.request();
    }
  }

  norace uint8_t decLoopCount = 0;

  task void waitDecTask(){

    cc2420_status_t status;

    call CSN.clr();
    status = call SNOP.strobe();
    call CSN.set();

    atomic decLoopCount ++;

    if(decLoopCount > 10){
      call CSN.clr();
      atomic call SECCTRL0.write((0 << CC2420_SECCTRL0_SEC_MODE) |
				 (0 << CC2420_SECCTRL0_SEC_M) |
				 (0 << CC2420_SECCTRL0_SEC_RXKEYSEL) |
				 (1 << CC2420_SECCTRL0_SEC_CBC_HEAD) |
				 (1 << CC2420_SECCTRL0_RXFIFO_PROTECTION)) ;
      call CSN.set();
      SECURITYLOCK = 0;
      call SpiResource.release();
      atomic flush_flag = 1;
      beginReceive();
    }else if(status & CC2420_STATUS_ENC_BUSY){
      post waitDecTask();
    }else{
      call CSN.clr();
      atomic call SECCTRL0.write((0 << CC2420_SECCTRL0_SEC_MODE) |
				 (0 << CC2420_SECCTRL0_SEC_M) |
				 (0 << CC2420_SECCTRL0_SEC_RXKEYSEL) |
				 (1 << CC2420_SECCTRL0_SEC_CBC_HEAD) |
				 (1 << CC2420_SECCTRL0_RXFIFO_PROTECTION)) ;
      call CSN.set();
      SECURITYLOCK = 0;
      call SpiResource.release();
      beginReceive();
    }

  }

  void waitDec(){
    cc2420_status_t status;
    call CSN.clr();
    status = call SNOP.strobe();
    call CSN.set();

    if(status & CC2420_STATUS_ENC_BUSY){
      atomic decLoopCount = 1;
      post waitDecTask();
    }else{
      call CSN.clr();
      atomic call SECCTRL0.write((0 << CC2420_SECCTRL0_SEC_MODE) |
				 (0 << CC2420_SECCTRL0_SEC_M) |
				 (0 << CC2420_SECCTRL0_SEC_RXKEYSEL) |
				 (1 << CC2420_SECCTRL0_SEC_CBC_HEAD) |
				 (1 << CC2420_SECCTRL0_RXFIFO_PROTECTION)) ;
      call CSN.set();
      SECURITYLOCK = 0;
      call SpiResource.release();
      beginReceive();
    }
  }

  void dec(){
    cc2420_header_t header;
    security_header_t secHdr;
    uint8_t mode, key, temp, crc;

    atomic pos = (packetLength+pos)%RXFIFO_SIZE;
    atomic secHdrPos = (pos+10)%RXFIFO_SIZE;

    if (pos + 3 > RXFIFO_SIZE){
      temp = RXFIFO_SIZE - pos;
      call CSN.clr();
      atomic call RXFIFO_RAM.read(pos,(uint8_t*)&header, temp);
      call CSN.set();
      call CSN.clr();
      atomic call RXFIFO_RAM.read(0,(uint8_t*)&header+temp, 3-temp);
      call CSN.set();
    }else{
      call CSN.clr();
      atomic call RXFIFO_RAM.read(pos,(uint8_t*)&header, 3);
      call CSN.set();
    }

    packetLength = header.length+1;

    if(packetLength == 6){ // ACK packet
      m_state = S_RX_LENGTH;
      call SpiResource.release();
      beginReceive();
      return;
    }

    if (pos + sizeof(cc2420_header_t) > RXFIFO_SIZE){
      temp = RXFIFO_SIZE - pos;
      call CSN.clr();
      atomic call RXFIFO_RAM.read(pos,(uint8_t*)&header, temp);
      call CSN.set();
      call CSN.clr();
      atomic call RXFIFO_RAM.read(0,(uint8_t*)&header+temp, sizeof(cc2420_header_t)-temp);
      call CSN.set();
    }else{
      call CSN.clr();
      atomic call RXFIFO_RAM.read(pos,(uint8_t*)&header, sizeof(cc2420_header_t));
      call CSN.set();
    }

    if (pos+header.length+1 > RXFIFO_SIZE){
      temp = header.length - (RXFIFO_SIZE - pos);
      call CSN.clr();
      atomic call RXFIFO_RAM.read(temp,&crc, 1);
      call CSN.set();
    }else{
      call CSN.clr();
      atomic call RXFIFO_RAM.read(pos+header.length,&crc, 1);
      call CSN.set();
    }

    if(header.length+1 > RXFIFO_SIZE || !(crc << 7)){
      atomic flush_flag = 1;
      m_state = S_RX_LENGTH;
      call SpiResource.release();
      beginReceive();
      return;
    }
    if( (header.fcf & (1 << IEEE154_FCF_SECURITY_ENABLED)) && (crc << 7) ){
      if(call CC2420Config.isAddressRecognitionEnabled()){
	if(!(header.dest==call CC2420Config.getShortAddr() || header.dest==AM_BROADCAST_ADDR)){
	  packetLength = header.length + 1;
	  m_state = S_RX_LENGTH;
	  call SpiResource.release();
	  beginReceive();
	  return;
	}
      }
      if(SECURITYLOCK == 1){
	call SpiResource.release();
	post waitTask();
	return;
      }else{
	//We are going to decrypt so lock the registers
	atomic SECURITYLOCK = 1;

	if (secHdrPos + sizeof(security_header_t) > RXFIFO_SIZE){
	  temp = RXFIFO_SIZE - secHdrPos;
	  call CSN.clr();
	  atomic call RXFIFO_RAM.read(secHdrPos,(uint8_t*)&secHdr, temp);
	  call CSN.set();
	  call CSN.clr();
	  atomic call RXFIFO_RAM.read(0,(uint8_t*)&secHdr+temp, sizeof(security_header_t) - temp);
	  call CSN.set();
	} else {
	  call CSN.clr();
	  atomic call RXFIFO_RAM.read(secHdrPos,(uint8_t*)&secHdr, sizeof(security_header_t));
	  call CSN.set();
	}

	key = secHdr.keyID[0];

	if (secHdr.secLevel == NO_SEC){
	  mode = CC2420_NO_SEC;
	  micLength = 0;
	}else if (secHdr.secLevel == CBC_MAC_4){
	  mode = CC2420_CBC_MAC;
	  micLength = 4;
	}else if (secHdr.secLevel == CBC_MAC_8){

⌨️ 快捷键说明

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