cc2420transmitp.nc
来自「tinyos-2.x.rar」· NC 代码 · 共 851 行 · 第 1/2 页
NC
851 行
/*
* 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 Initial SACK implementation
* @author JeongGil Ko
* @author Razvan Musaloiu-E
* @version $Revision: 1.16 $ $Date: 2009/10/28 21:09:52 $
*/
#include "CC2420.h"
#include "CC2420TimeSyncMessage.h"
#include "crc.h"
#include "message.h"
module CC2420TransmitP @safe() {
provides interface Init;
provides interface StdControl;
provides interface CC2420Transmit as Send;
provides interface RadioBackoff;
provides interface ReceiveIndicator as EnergyIndicator;
provides interface ReceiveIndicator as ByteIndicator;
uses interface Alarm<T32khz,uint32_t> as BackoffTimer;
uses interface CC2420Packet;
uses interface CC2420PacketBody;
uses interface PacketTimeStamp<T32khz,uint32_t>;
uses interface PacketTimeSyncOffset;
uses interface GpioCapture as CaptureSFD;
uses interface GeneralIO as CCA;
uses interface GeneralIO as CSN;
uses interface GeneralIO as SFD;
uses interface Resource as SpiResource;
uses interface ChipSpiResource;
uses interface CC2420Fifo as TXFIFO;
uses interface CC2420Ram as TXFIFO_RAM;
uses interface CC2420Register as TXCTRL;
uses interface CC2420Strobe as SNOP;
uses interface CC2420Strobe as STXON;
uses interface CC2420Strobe as STXONCCA;
uses interface CC2420Strobe as SFLUSHTX;
uses interface CC2420Register as MDMCTRL1;
uses interface CC2420Strobe as STXENC;
uses interface CC2420Register as SECCTRL0;
uses interface CC2420Register as SECCTRL1;
uses interface CC2420Ram as KEY0;
uses interface CC2420Ram as KEY1;
uses interface CC2420Ram as TXNONCE;
uses interface CC2420Receive;
uses interface Leds;
}
implementation {
typedef enum {
S_STOPPED,
S_STARTED,
S_LOAD,
S_SAMPLE_CCA,
S_BEGIN_TRANSMIT,
S_SFD,
S_EFD,
S_ACK_WAIT,
S_CANCEL,
} cc2420_transmit_state_t;
// This specifies how many jiffies the stack should wait after a
// TXACTIVE to receive an SFD interrupt before assuming something is
// wrong and aborting the send. There seems to be a condition
// on the micaZ where the SFD interrupt is never handled.
enum {
CC2420_ABORT_PERIOD = 320
};
#ifdef CC2420_HW_SECURITY
uint16_t startTime = 0;
norace uint8_t secCtrlMode = 0;
norace 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 uint16_t CTR_SECCTRL0, CTR_SECCTRL1;
uint8_t securityChecked = 0;
void securityCheck();
#endif
norace message_t * ONE_NOK m_msg;
norace bool m_cca;
norace uint8_t m_tx_power;
cc2420_transmit_state_t m_state = S_STOPPED;
bool m_receiving = FALSE;
uint16_t m_prev_time;
/** Byte reception/transmission indicator */
bool sfdHigh;
/** Let the CC2420 driver keep a lock on the SPI while waiting for an ack */
bool abortSpiRelease;
/** Total CCA checks that showed no activity before the NoAck LPL send */
norace int8_t totalCcaChecks;
/** The initial backoff period */
norace uint16_t myInitialBackoff;
/** The congestion backoff period */
norace uint16_t myCongestionBackoff;
/***************** Prototypes ****************/
error_t send( message_t * ONE p_msg, bool cca );
error_t resend( bool cca );
void loadTXFIFO();
void attemptSend();
void congestionBackoff();
error_t acquireSpiResource();
error_t releaseSpiResource();
void signalDone( error_t err );
/***************** Init Commands *****************/
command error_t Init.init() {
call CCA.makeInput();
call CSN.makeOutput();
call SFD.makeInput();
return SUCCESS;
}
/***************** StdControl Commands ****************/
command error_t StdControl.start() {
atomic {
call CaptureSFD.captureRisingEdge();
m_state = S_STARTED;
m_receiving = FALSE;
abortSpiRelease = FALSE;
m_tx_power = 0;
}
return SUCCESS;
}
command error_t StdControl.stop() {
atomic {
m_state = S_STOPPED;
call BackoffTimer.stop();
call CaptureSFD.disable();
call SpiResource.release(); // REMOVE
call CSN.set();
}
return SUCCESS;
}
/**************** Send Commands ****************/
async command error_t Send.send( message_t* ONE p_msg, bool useCca ) {
return send( p_msg, useCca );
}
async command error_t Send.resend(bool useCca) {
return resend( useCca );
}
async command error_t Send.cancel() {
atomic {
switch( m_state ) {
case S_LOAD:
case S_SAMPLE_CCA:
case S_BEGIN_TRANSMIT:
m_state = S_CANCEL;
break;
default:
// cancel not allowed while radio is busy transmitting
return FAIL;
}
}
return SUCCESS;
}
async command error_t Send.modify( uint8_t offset, uint8_t* buf,
uint8_t len ) {
call CSN.clr();
call TXFIFO_RAM.write( offset, buf, len );
call CSN.set();
return SUCCESS;
}
/***************** Indicator Commands ****************/
command bool EnergyIndicator.isReceiving() {
return !(call CCA.get());
}
command bool ByteIndicator.isReceiving() {
bool high;
atomic high = sfdHigh;
return high;
}
/***************** RadioBackoff Commands ****************/
/**
* Must be called within a requestInitialBackoff event
* @param backoffTime the amount of time in some unspecified units to backoff
*/
async command void RadioBackoff.setInitialBackoff(uint16_t backoffTime) {
myInitialBackoff = backoffTime + 1;
}
/**
* Must be called within a requestCongestionBackoff event
* @param backoffTime the amount of time in some unspecified units to backoff
*/
async command void RadioBackoff.setCongestionBackoff(uint16_t backoffTime) {
myCongestionBackoff = backoffTime + 1;
}
async command void RadioBackoff.setCca(bool useCca) {
}
inline uint32_t getTime32(uint16_t time)
{
uint32_t recent_time=call BackoffTimer.getNow();
return recent_time + (int16_t)(time - recent_time);
}
/**
* The CaptureSFD event is actually an interrupt from the capture pin
* which is connected to timing circuitry and timer modules. This
* type of interrupt allows us to see what time (being some relative value)
* the event occurred, and lets us accurately timestamp our packets. This
* allows higher levels in our system to synchronize with other nodes.
*
* Because the SFD events can occur so quickly, and the interrupts go
* in both directions, we set up the interrupt but check the SFD pin to
* determine if that interrupt condition has already been met - meaning,
* we should fall through and continue executing code where that interrupt
* would have picked up and executed had our microcontroller been fast enough.
*/
async event void CaptureSFD.captured( uint16_t time ) {
uint32_t time32;
uint8_t sfd_state = 0;
atomic {
time32 = getTime32(time);
switch( m_state ) {
case S_SFD:
m_state = S_EFD;
sfdHigh = TRUE;
// in case we got stuck in the receive SFD interrupts, we can reset
// the state here since we know that we are not receiving anymore
m_receiving = FALSE;
call CaptureSFD.captureFallingEdge();
call PacketTimeStamp.set(m_msg, time32);
if (call PacketTimeSyncOffset.isSet(m_msg)) {
uint8_t absOffset = sizeof(message_header_t)-sizeof(cc2420_header_t)+call PacketTimeSyncOffset.get(m_msg);
timesync_radio_t *timesync = (timesync_radio_t *)((nx_uint8_t*)m_msg+absOffset);
// set timesync event time as the offset between the event time and the SFD interrupt time (TEP 133)
*timesync -= time32;
call CSN.clr();
call TXFIFO_RAM.write( absOffset, (uint8_t*)timesync, sizeof(timesync_radio_t) );
call CSN.set();
//restoring the event time to the original value
*timesync += time32;
}
if ( (call CC2420PacketBody.getHeader( m_msg ))->fcf & ( 1 << IEEE154_FCF_ACK_REQ ) ) {
// This is an ack packet, don't release the chip's SPI bus lock.
abortSpiRelease = TRUE;
}
releaseSpiResource();
call BackoffTimer.stop();
if ( call SFD.get() ) {
break;
}
/** Fall Through because the next interrupt was already received */
case S_EFD:
sfdHigh = FALSE;
call CaptureSFD.captureRisingEdge();
if ( (call CC2420PacketBody.getHeader( m_msg ))->fcf & ( 1 << IEEE154_FCF_ACK_REQ ) ) {
m_state = S_ACK_WAIT;
call BackoffTimer.start( CC2420_ACK_WAIT_DELAY );
} else {
signalDone(SUCCESS);
}
if ( !call SFD.get() ) {
break;
}
/** Fall Through because the next interrupt was already received */
default:
/* this is the SFD for received messages */
if ( !m_receiving && sfdHigh == FALSE ) {
sfdHigh = TRUE;
call CaptureSFD.captureFallingEdge();
// safe the SFD pin status for later use
sfd_state = call SFD.get();
call CC2420Receive.sfd( time32 );
m_receiving = TRUE;
m_prev_time = time;
if ( call SFD.get() ) {
// wait for the next interrupt before moving on
return;
}
// if SFD.get() = 0, then an other interrupt happened since we
// reconfigured CaptureSFD! Fall through
}
if ( sfdHigh == TRUE ) {
sfdHigh = FALSE;
call CaptureSFD.captureRisingEdge();
m_receiving = FALSE;
/* if sfd_state is 1, then we fell through, but at the time of
* saving the time stamp the SFD was still high. Thus, the timestamp
* is valid.
* if the sfd_state is 0, then either we fell through and SFD
* was low while we safed the time stamp, or we didn't fall through.
* Thus, we check for the time between the two interrupts.
* FIXME: Why 10 tics? Seams like some magic number...
*/
if ((sfd_state == 0) && (time - m_prev_time < 10) ) {
call CC2420Receive.sfd_dropped();
if (m_msg)
call PacketTimeStamp.clear(m_msg);
}
break;
}
}
}
}
/***************** ChipSpiResource Events ****************/
async event void ChipSpiResource.releasing() {
if(abortSpiRelease) {
call ChipSpiResource.abortRelease();
}
}
/***************** CC2420Receive Events ****************/
/**
* If the packet we just received was an ack that we were expecting,
* our send is complete.
*/
async event void CC2420Receive.receive( uint8_t type, message_t* ack_msg ) {
cc2420_header_t* ack_header;
cc2420_header_t* msg_header;
cc2420_metadata_t* msg_metadata;
uint8_t* ack_buf;
uint8_t length;
if ( type == IEEE154_TYPE_ACK && m_msg) {
ack_header = call CC2420PacketBody.getHeader( ack_msg );
msg_header = call CC2420PacketBody.getHeader( m_msg );
if ( m_state == S_ACK_WAIT && msg_header->dsn == ack_header->dsn ) {
call BackoffTimer.stop();
msg_metadata = call CC2420PacketBody.getMetadata( m_msg );
ack_buf = (uint8_t *) ack_header;
length = ack_header->length;
msg_metadata->ack = TRUE;
msg_metadata->rssi = ack_buf[ length - 1 ];
msg_metadata->lqi = ack_buf[ length ] & 0x7f;
signalDone(SUCCESS);
}
}
}
/***************** SpiResource Events ****************/
event void SpiResource.granted() {
uint8_t cur_state;
atomic {
cur_state = m_state;
}
switch( cur_state ) {
case S_LOAD:
loadTXFIFO();
break;
case S_BEGIN_TRANSMIT:
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?