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 + -
显示快捷键?