cc2420receivep.nc

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

NC
831
字号
	  mode = CC2420_CBC_MAC;
	  micLength = 8;
	}else if (secHdr.secLevel == CBC_MAC_16){
	  mode = CC2420_CBC_MAC;
	  micLength = 16;
	}else if (secHdr.secLevel == CTR){
	  mode = CC2420_CTR;
	  micLength = 0;
	}else if (secHdr.secLevel == CCM_4){
	  mode = CC2420_CCM;
	  micLength = 4;
	}else if (secHdr.secLevel == CCM_8){
	  mode = CC2420_CCM;
	  micLength = 8;
	}else if (secHdr.secLevel == CCM_16){
	  mode = CC2420_CCM;
	  micLength = 16;
	}else{
	  atomic SECURITYLOCK = 0;
	  packetLength = header.length + 1;
	  m_state = S_RX_LENGTH;
	  call SpiResource.release();
	  beginReceive();
	  return;
	}

	if(mode < 4 && mode > 0) { // if mode is valid
  
	  securityOn = 1;

	  memcpy(&nonceValue[3], &(secHdr.frameCounter), 4);
	  skip = secHdr.reserved;

	  if(mode == CC2420_CBC_MAC || mode == CC2420_CCM){
	    authentication = 1;
	    call CSN.clr();
	    atomic call SECCTRL0.write((mode << CC2420_SECCTRL0_SEC_MODE) |
				       ((micLength-2)/2 << CC2420_SECCTRL0_SEC_M) |
				       (key << CC2420_SECCTRL0_SEC_RXKEYSEL) |
				       (1 << CC2420_SECCTRL0_SEC_CBC_HEAD) |
				       (1 << CC2420_SECCTRL0_RXFIFO_PROTECTION)) ;
	    call CSN.set();
	  }else{
	    call CSN.clr();
	    atomic call SECCTRL0.write((mode << CC2420_SECCTRL0_SEC_MODE) |
				       (1 << CC2420_SECCTRL0_SEC_M) |
				       (key << CC2420_SECCTRL0_SEC_RXKEYSEL) |
				       (1 << CC2420_SECCTRL0_SEC_CBC_HEAD) |
				       (1 << CC2420_SECCTRL0_RXFIFO_PROTECTION)) ;
	    call CSN.set();
	  }

	  call CSN.clr();
#ifndef TFRAMES_ENABLED
	  atomic call SECCTRL1.write(skip+11+sizeof(security_header_t)+((skip+11+sizeof(security_header_t))<<8));
#else
	  atomic call SECCTRL1.write(skip+10+sizeof(security_header_t)+((skip+10+sizeof(security_header_t))<<8));
#endif
	  call CSN.set();

	  call CSN.clr();
	  atomic call RXNONCE.write(0, nonceValue, 16);
	  call CSN.set();

	  call CSN.clr();
	  atomic call SRXDEC.strobe();
	  call CSN.set();

	  atomic decLoopCount = 0;
	  post waitDecTask();
	  return;

	}else{
	  atomic SECURITYLOCK = 0;
	  packetLength = header.length + 1;
	  m_state = S_RX_LENGTH;
	  call SpiResource.release();
	  beginReceive();
	  return;
	}
      }
    }else{
      packetLength = header.length + 1;
      m_state = S_RX_LENGTH;
      call SpiResource.release();
      beginReceive();
      return;
    }
  }
#endif
  /***************** SpiResource Events ****************/
  event void SpiResource.granted() {
#ifdef CC2420_HW_SECURITY
    if(m_state == S_RX_DEC){
      dec();
    }else{
      receive();
    }
#else
    receive();
#endif
  }
  
  /***************** 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 );
    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;
#ifdef CC2420_HW_SECURITY
      packetLength = rxFrameLength+1;
#endif
      if ( rxFrameLength + 1 > m_bytes_left
#ifdef CC2420_HW_SECURITY
           || flush_flag == 1
#endif
           ) {
        // 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();
      }
      
      //new packet is buffered up, or we don't have timestamp in fifo, or ack
      if ( ( m_missed_packets && call FIFO.get() ) || !call FIFOP.get()
            || !m_timestamp_size
            || rxFrameLength <= 10) {
        call PacketTimeStamp.clear(m_p_rx_buf);
      }
      else {
          if (m_timestamp_size==1)
            call PacketTimeStamp.set(m_p_rx_buf, m_timestamp_queue[ m_timestamp_head ]);
          m_timestamp_head = ( m_timestamp_head + 1 ) % TIMESTAMP_QUEUE_SIZE;
          m_timestamp_size--;

          if (m_timestamp_size>0) {
            call PacketTimeStamp.clear(m_p_rx_buf);
            m_timestamp_head = 0;
            m_timestamp_size = 0;
          }
      }

      // 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 length = header->length;
    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[ length ] >> 7;
    metadata->lqi = buf[ length ] & 0x7f;
    metadata->rssi = buf[ length - 1 ];

    if (passesAddressCheck(m_p_rx_buf) && length >= CC2420_SIZE) {
#ifdef CC2420_HW_SECURITY
      if(securityOn == 1){
	if(m_missed_packets > 0){
	  m_missed_packets --;
	}
	if(authentication){
	  length -= micLength;
	}
      }
      micLength = 0;
      securityOn = 0;
      authentication = 0;
#endif
      m_p_rx_buf = signal Receive.receive( m_p_rx_buf, m_p_rx_buf->data,
					   length - CC2420_SIZE);
    }
    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() {
#ifdef CC2420_HW_SECURITY
    flush_flag = 0;
    pos =0;
    packetLength =0;
    micLength = 0;
    securityOn = 0;
    authentication = 0;
#endif
    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--;
        }
#ifdef CC2420_HW_SECURITY
	call SpiResource.release();
	m_state = S_RX_DEC;
	beginDec();
#else
	beginReceive();
#endif

      } 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 + =
减小字号Ctrl + -
显示快捷键?