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