cc2420transmitp.nc

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

NC
851
字号
      attemptSend();
      break;
      
    case S_CANCEL:
      call CSN.clr();
      call SFLUSHTX.strobe();
      call CSN.set();
      releaseSpiResource();
      atomic {
        m_state = S_STARTED;
      }
      signal Send.sendDone( m_msg, ECANCEL );
      break;
      
    default:
      releaseSpiResource();
      break;
    }
  }
  
  /***************** TXFIFO Events ****************/
  /**
   * The TXFIFO is used to load packets into the transmit buffer on the
   * chip
   */
  async event void TXFIFO.writeDone( uint8_t* tx_buf, uint8_t tx_len,
                                     error_t error ) {

    call CSN.set();
    if ( m_state == S_CANCEL ) {
      atomic {
        call CSN.clr();
        call SFLUSHTX.strobe();
        call CSN.set();
      }
      releaseSpiResource();
      m_state = S_STARTED;
      signal Send.sendDone( m_msg, ECANCEL );
      
    } else if ( !m_cca ) {
      atomic {
        m_state = S_BEGIN_TRANSMIT;
      }
      attemptSend();
      
    } else {
      releaseSpiResource();
      atomic {
        m_state = S_SAMPLE_CCA;
      }
      
      signal RadioBackoff.requestInitialBackoff(m_msg);
      call BackoffTimer.start(myInitialBackoff);
    }
  }

  
  async event void TXFIFO.readDone( uint8_t* tx_buf, uint8_t tx_len, 
      error_t error ) {
  }
  
  
  /***************** Timer Events ****************/
  /**
   * The backoff timer is mainly used to wait for a moment before trying
   * to send a packet again. But we also use it to timeout the wait for
   * an acknowledgement, and timeout the wait for an SFD interrupt when
   * we should have gotten one.
   */
  async event void BackoffTimer.fired() {
    atomic {
      switch( m_state ) {
        
      case S_SAMPLE_CCA : 
        // sample CCA and wait a little longer if free, just in case we
        // sampled during the ack turn-around window
        if ( call CCA.get() ) {
          m_state = S_BEGIN_TRANSMIT;
          call BackoffTimer.start( CC2420_TIME_ACK_TURNAROUND );
          
        } else {
          congestionBackoff();
        }
        break;
        
      case S_BEGIN_TRANSMIT:
      case S_CANCEL:
        if ( acquireSpiResource() == SUCCESS ) {
          attemptSend();
        }
        break;
        
      case S_ACK_WAIT:
        signalDone( SUCCESS );
        break;

      case S_SFD:
        // We didn't receive an SFD interrupt within CC2420_ABORT_PERIOD
        // jiffies. Assume something is wrong.
        call SFLUSHTX.strobe();
        call CaptureSFD.captureRisingEdge();
        releaseSpiResource();
        signalDone( ERETRY );
        break;

      default:
        break;
      }
    }
  }
      
  /***************** Functions ****************/
  /**
   * Set up a message to be sent. First load it into the outbound tx buffer
   * on the chip, then attempt to send it.
   * @param *p_msg Pointer to the message that needs to be sent
   * @param cca TRUE if this transmit should use clear channel assessment
   */
  error_t send( message_t* ONE p_msg, bool cca ) {
    atomic {
      if (m_state == S_CANCEL) {
        return ECANCEL;
      }
      
      if ( m_state != S_STARTED ) {
        return FAIL;
      }
      
#ifdef CC2420_HW_SECURITY
      securityChecked = 0;
#endif
      m_state = S_LOAD;
      m_cca = cca;
      m_msg = p_msg;
      totalCcaChecks = 0;
    }
    
    if ( acquireSpiResource() == SUCCESS ) {
      loadTXFIFO();
    }

    return SUCCESS;
  }
  
  /**
   * Resend a packet that already exists in the outbound tx buffer on the
   * chip
   * @param cca TRUE if this transmit should use clear channel assessment
   */
  error_t resend( bool cca ) {

    atomic {
      if (m_state == S_CANCEL) {
        return ECANCEL;
      }
      
      if ( m_state != S_STARTED ) {
        return FAIL;
      }
      
      m_cca = cca;
      m_state = cca ? S_SAMPLE_CCA : S_BEGIN_TRANSMIT;
      totalCcaChecks = 0;
    }
    
    if(m_cca) {
      signal RadioBackoff.requestInitialBackoff(m_msg);
      call BackoffTimer.start( myInitialBackoff );
      
    } else if ( acquireSpiResource() == SUCCESS ) {
      attemptSend();
    }
    
    return SUCCESS;
  }
#ifdef CC2420_HW_SECURITY

  task void waitTask(){
    call Leds.led2Toggle();
    if(SECURITYLOCK == 1){
      post waitTask();
    }else{
      securityCheck();
    }
  }

  void securityCheck(){

    cc2420_header_t* msg_header;
    cc2420_status_t status;
    security_header_t* secHdr;
    uint8_t mode;
    uint8_t key;
    uint8_t micLength;

    msg_header = call CC2420PacketBody.getHeader( m_msg );

    if(!(msg_header->fcf & (1 << IEEE154_FCF_SECURITY_ENABLED))){
      // Security is not used for this packet
      // Make sure to set mode to 0 and the others to the default values
      CTR_SECCTRL0 = ((0 << CC2420_SECCTRL0_SEC_MODE) |
		      (1 << CC2420_SECCTRL0_SEC_M) |
		      (1 << CC2420_SECCTRL0_SEC_TXKEYSEL) |
		      (1 << CC2420_SECCTRL0_SEC_CBC_HEAD)) ;
      
      call CSN.clr();
      call SECCTRL0.write(CTR_SECCTRL0);
      call CSN.set();

      return;
    }

    if(SECURITYLOCK == 1){
      post waitTask();
    }else {
      //Will perform encryption lock registers
      atomic SECURITYLOCK = 1;

      secHdr = (security_header_t*) &msg_header->secHdr;
      memcpy(&nonceValue[3], &(secHdr->frameCounter), 4);

      skip = secHdr->reserved;
      key = secHdr->keyID[0]; // For now this is the only key selection mode.

      if (secHdr->secLevel == NO_SEC){
	mode = CC2420_NO_SEC;
	micLength = 4;
      }else if (secHdr->secLevel == CBC_MAC_4){
	mode = CC2420_CBC_MAC;
	micLength = 4;
      }else if (secHdr->secLevel == CBC_MAC_8){
	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 = 4;
      }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{
	return;
      }

      CTR_SECCTRL0 = ((mode << CC2420_SECCTRL0_SEC_MODE) |
		      ((micLength-2)/2 << CC2420_SECCTRL0_SEC_M) |
		      (key << CC2420_SECCTRL0_SEC_TXKEYSEL) |
		      (1 << CC2420_SECCTRL0_SEC_CBC_HEAD)) ;
#ifndef TFRAMES_ENABLED
      CTR_SECCTRL1 = (skip+11+sizeof(security_header_t)+((skip+11+sizeof(security_header_t))<<8));
#else
      CTR_SECCTRL1 = (skip+10+sizeof(security_header_t)+((skip+10+sizeof(security_header_t))<<8));
#endif

      call CSN.clr();
      call SECCTRL0.write(CTR_SECCTRL0);
      call CSN.set();

      call CSN.clr();
      call SECCTRL1.write(CTR_SECCTRL1);
      call CSN.set();

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

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

      while(status & CC2420_STATUS_ENC_BUSY){
	call CSN.clr();
	status = call SNOP.strobe();
	call CSN.set();
      }
      
      // Inline security will be activated by STXON or STXONCCA strobes

      atomic SECURITYLOCK = 0;

    }
  }
#endif

  /**
   * Attempt to send the packet we have loaded into the tx buffer on 
   * the radio chip.  The STXONCCA will send the packet immediately if
   * the channel is clear.  If we're not concerned about whether or not
   * the channel is clear (i.e. m_cca == FALSE), then STXON will send the
   * packet without checking for a clear channel.
   *
   * If the packet didn't get sent, then congestion == TRUE.  In that case,
   * we reset the backoff timer and try again in a moment.
   *
   * If the packet got sent, we should expect an SFD interrupt to take
   * over, signifying the packet is getting sent.
   * 
   * If security is enabled, STXONCCA or STXON will perform inline security
   * options before transmitting the packet.
   */
  void attemptSend() {
    uint8_t status;
    bool congestion = TRUE;

    atomic {
      if (m_state == S_CANCEL) {
        call SFLUSHTX.strobe();
        releaseSpiResource();
        call CSN.set();
        m_state = S_STARTED;
        signal Send.sendDone( m_msg, ECANCEL );
        return;
      }
#ifdef CC2420_HW_SECURITY
      if(securityChecked != 1){
	securityCheck();
      }
      securityChecked = 1;
#endif
      call CSN.clr();
      status = m_cca ? call STXONCCA.strobe() : call STXON.strobe();
      if ( !( status & CC2420_STATUS_TX_ACTIVE ) ) {
        status = call SNOP.strobe();
        if ( status & CC2420_STATUS_TX_ACTIVE ) {
          congestion = FALSE;
        }
      }

      m_state = congestion ? S_SAMPLE_CCA : S_SFD;
      call CSN.set();
    }

    if ( congestion ) {
      totalCcaChecks = 0;
      releaseSpiResource();
      congestionBackoff();
    } else {
      call BackoffTimer.start(CC2420_ABORT_PERIOD);
    }
  }
  
  
  /**  
   * Congestion Backoff
   */
  void congestionBackoff() {
    atomic {
      signal RadioBackoff.requestCongestionBackoff(m_msg);
      call BackoffTimer.start(myCongestionBackoff);
    }
  }
  
  error_t acquireSpiResource() {
    error_t error = call SpiResource.immediateRequest();
    if ( error != SUCCESS ) {
      call SpiResource.request();
    }
    return error;
  }

  error_t releaseSpiResource() {
    call SpiResource.release();
    return SUCCESS;
  }


  /** 
   * Setup the packet transmission power and load the tx fifo buffer on
   * the chip with our outbound packet.  
   *
   * Warning: the tx_power metadata might not be initialized and
   * could be a value other than 0 on boot.  Verification is needed here
   * to make sure the value won't overstep its bounds in the TXCTRL register
   * and is transmitting at max power by default.
   *
   * It should be possible to manually calculate the packet's CRC here and
   * tack it onto the end of the header + payload when loading into the TXFIFO,
   * so the continuous modulation low power listening strategy will continually
   * deliver valid packets.  This would increase receive reliability for
   * mobile nodes and lossy connections.  The crcByte() function should use
   * the same CRC polynomial as the CC2420's AUTOCRC functionality.
   */
  void loadTXFIFO() {
    cc2420_header_t* header = call CC2420PacketBody.getHeader( m_msg );
    uint8_t tx_power = (call CC2420PacketBody.getMetadata( m_msg ))->tx_power;

    if ( !tx_power ) {
      tx_power = CC2420_DEF_RFPOWER;
    }
    
    call CSN.clr();
    
    if ( m_tx_power != tx_power ) {
      call TXCTRL.write( ( 2 << CC2420_TXCTRL_TXMIXBUF_CUR ) |
                         ( 3 << CC2420_TXCTRL_PA_CURRENT ) |
                         ( 1 << CC2420_TXCTRL_RESERVED ) |
                         ( (tx_power & 0x1F) << CC2420_TXCTRL_PA_LEVEL ) );
    }
    
    m_tx_power = tx_power;
    
    {
      uint8_t tmpLen __DEPUTY_UNUSED__ = header->length - 1;
      call TXFIFO.write(TCAST(uint8_t * COUNT(tmpLen), header), header->length - 1);
    }
  }
  
  void signalDone( error_t err ) {
    atomic m_state = S_STARTED;
    abortSpiRelease = FALSE;
    call ChipSpiResource.attemptRelease();
    signal Send.sendDone( m_msg, err );
  }

}

⌨️ 快捷键说明

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