⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 aps.c

📁 zigbee在cc2430下的演示程序。
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * "Copyright (c) 2006 Robert B. Reese ("AUTHOR")"
 * All rights reserved.
 * (R. Reese, reese@ece.msstate.edu, Mississippi State University)
 * IN NO EVENT SHALL THE "AUTHOR" BE LIABLE TO ANY PARTY FOR
 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
 * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHOR"
 * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * THE "AUTHOR" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
 * ON AN "AS IS" BASIS, AND THE "AUTHOR" HAS NO OBLIGATION TO
 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
 *
 *
 * This file makes use of Zigbee Alliance intellectual property in the
 * form of frame formats as specified in the Zigbee 1.0 standard.
 * The author consulted the
 * Zigbee standard when writing this file, and agreed to the terms
 * of conditions by the Zibee Alliance when downloading the standard.
 * As such, use of this file is governed by the Zigbee Trademarks,
 * Designations, and Logos policy. A paraphrase of this policy is
 * that free usage is granted for research, educational or personal
 * use. Commercial usage is restricted, see the policy for details.
 *
 * Please maintain this header in its entirety when copying/modifying
 * these files.
 *
 * Files in this software distribution may have different usage
 * permissions, see the header in each file. Some files have NO permission
 * headers since parts of the original sources in these files
 * came from vendor  sources with no usage restrictions.
 *
 */

/*
  V0.1 Initial Release   10/July/2006  RBR

*/



/*
APS Layer


*/

#include "compiler.h"
#include "lrwpan_config.h"         //user configurations
#include "lrwpan_common_types.h"   //types common acrosss most files
#include "ieee_lrwpan_defs.h"
#include "console.h"
#include "debug.h"
#include "memalloc.h"
#include "neighbor.h"
#include "hal.h"
#include "halstack.h"
#include "phy.h"
#include "mac.h"
#include "nwk.h"
#include "aps.h"
#include "zep.h"
#include "evboard.h"


#define apsTXIdle() (!aps_pib.flags.bits.TxInProgress)
#define apsTXBusy() (aps_pib.flags.bits.TxInProgress)
#define apsSetTxBusy() aps_pib.flags.bits.TxInProgress = 1
#define apsSetTxIdle() aps_pib.flags.bits.TxInProgress = 0


typedef enum _APS_RXSTATE_ENUM {
  APS_RXSTATE_IDLE,
  APS_RXSTATE_START,
  APS_RXSTATE_RESOLVE_INDIRECT,
  APS_RXSTATE_HANDLE_ZEROEP,
  APS_RXSTATE_ACK_SEND_WAIT
} APS_RXSTATE_ENUM;



APS_PIB aps_pib;
APS_SERVICE a_aps_service;
APS_STATE_ENUM apsState;

//there can only be one TX in progress at a time, so
//a_aps_tx_data contains the arguments for that TX on the APS layer.
APS_TX_DATA a_aps_tx_data;
APS_RX_DATA a_aps_rx_data;
APS_RX_DATA indirect_data;  //used for holding an indirect packet while being reflected.

void apsFSM(void);
void apsTxData(BOOL copy_payload);

//locals
static APS_RXSTATE_ENUM apsRxState;
static LRWPAN_STATUS_ENUM apsTxFSM_status;

static void apsParseHdr(BYTE *ptr);
static void apsRxFSM(void);
static BOOL apsCheckAck(void);
static void apsFormatAck(void);
static void apsTxFSM(void);

#ifdef LRWPAN_COORDINATOR
static void apsInjectIndirectPacket(void);
void apsRxBuffInit(void);
BOOL apsRxBuffFull(void);
BOOL apsRxBuffEmpty(void);
APS_RX_DATA *apsGetRxPacket(void);
void apsFreeRxPacket(BOOL freemem);
void apsRxBuffAdd (APS_RX_DATA *ptr);

#endif

//converts MAC TICKs to Microseconds
UINT32 aplMacTicksToUs(UINT32 ticks){

   return(halMacTicksToUs(ticks));
  
}

//this sleeps, then restarts the stack and the radio
void aplShutdown(void){
   //wait until stack is idle
   while(apsBusy()) apsFSM();
   DISABLE_GLOBAL_INTERRUPT();  //disable interrupts, if halSleep wants to reenable them, let it.
   halShutdown();
   a_aps_service.status = LRWPAN_STATUS_SUCCESS;
   
 }

void aplWarmstart(void){
   a_aps_service.status = macWarmStartRadio();
}



//this is top level init, does inits for other layers
void apsInit(void){

  debug_level = 0;
  apsState = APS_STATE_IDLE;
  apsRxState = APS_RXSTATE_IDLE;
#ifdef LRWPAN_COORDINATOR
  aps_pib.rxCnt = 0;
  aps_pib.rxTail = 0;
  aps_pib.rxHead = 0;
#endif

  aps_pib.apsTSN = 0;
  aps_pib.flags.val = 0;
  aps_pib.apscAckWaitDuration = MSECS_TO_MACTICKS(LRWPAN_APS_ACK_WAIT_DURATION) ; //convert to MAC Ticks
  aps_pib.apsAckWaitMultiplier = 1; //default value
  aps_pib.apscMaxFrameRetries = LRWPAN_APS_MAX_FRAME_RETRIES ;
  phyInit();
  macInit();
  nwkInit();
  zepInit();

}

//Formats a Send Message service
void aplFmtSendMSG (BYTE dstMode,
                    LADDR_UNION *dstADDR,
                    BYTE dstEP,
                    BYTE cluster,
                    BYTE srcEP,
                    BYTE* pload,
                    BYTE  plen,
                    BYTE  tsn,
                    BYTE  reqack) {

                      while(apsBusy()) apsFSM();
                      a_aps_service.cmd = LRWPAN_SVC_APS_GENERIC_TX;
                      a_aps_tx_data.srcEP = srcEP;	
                      a_aps_tx_data.usrPlen = plen;
                      a_aps_tx_data.usrPload = pload;
                      a_aps_tx_data.tsn = tsn;
                      a_aps_tx_data.cluster = cluster;
                      a_aps_tx_data.dstMode = dstMode;
                      a_aps_tx_data.dstEP = dstEP;
                      a_aps_tx_data.srcSADDR = macGetShortAddr();
                      a_aps_tx_data.af_fcf = (1 | AF_FRM_TYPE_MSG);


                      if (dstMode == APS_DSTMODE_NONE) {
                        a_aps_tx_data.aps_fcf = APS_FRM_TYPE_DATA | APS_FRM_DLVRMODE_INDIRECT;
                      }else  {
                        a_aps_tx_data.aps_fcf = APS_FRM_TYPE_DATA | APS_FRM_DLVRMODE_NORMAL;
                        if (a_aps_tx_data.dstMode == APS_DSTMODE_SHORT ){
                              a_aps_tx_data.dstSADDR = dstADDR->saddr;
                             }
                        else {
                          a_aps_tx_data.dstLADDR = &dstADDR->laddr.bytes[0];
                          a_aps_tx_data.dstSADDR = LRWPAN_SADDR_USE_LADDR;
                          /* APS acks to no make sense for LONG addressing, which is
                          being used to bypass routing. The MAC acks serve for APS acks
                          in this case. Also APS acks would be returned via routing,
                          negating the bypass of the routing in the first place.
                          */
                          reqack = 0;
                        }
                      }	
                      if (reqack) a_aps_tx_data.aps_fcf |= (APS_FRM_ACKREQ_MASK);

                    }

//TODO - add a pib flag that indicates when the User's TX
//buffer has been copied so that user can begin building a
//new TX packet while the old one is being TX'ed.



void apsFSM(void) {


#ifdef LRWPAN_COORDINATOR
  APS_RX_DATA *rxPtr;
#endif

  
  
  nwkFSM();
  //if TxFSM is busy we need to call it
  if (apsTXBusy()) apsTxFSM();
  apsRxFSM(); //check RX

apsFSM_start2:

  if (zepBusy()) zepFSM();

apsFSM_start:


  switch (apsState) {
	 case APS_STATE_IDLE:
           if (aps_pib.flags.bits.zepRxInProgress){
             //need to handle the zep RX, lock the APS state machine.
             apsState = APS_STATE_ZEP_WAIT_RXSTART;
             goto apsFSM_start;
           }

           //ackSendPending check must come before the indirect Pending check!
           if (aps_pib.flags.bits.ackSendPending) {
             apsState = APS_STATE_ACK_SEND_START;
             goto apsFSM_start;			
           }

#ifdef LRWPAN_COORDINATOR
           if (aps_pib.flags.bits.indirectPending) {
             //free up RX FSM so that we can receive possible APS acks for this packet.			
             aps_pib.flags.bits.indirectPending = 0;  //free up RX FSM
             // an indirect message needs resolving
             //initialize the binding table iterator
             //get pointer to current indirect packet
             rxPtr = &aps_pib.rxBuff[aps_pib.rxTail];
             if (!evbBindTableIterInit(rxPtr->srcEP, rxPtr->srcSADDR,rxPtr->cluster)){
               //a failure to initialize the iterator, give up.
               DEBUG_STRING(DBG_ERR,"APS: BindTable Iterator initialize failed. Discarding indirect msg.\n");
               apsState = APS_STATE_IDLE;
             }else {
               apsState = APS_STATE_INDIRECT_GETDST;
               goto apsFSM_start;
             }
           }
#endif


           break;
	 case APS_STATE_COMMAND_START:
           switch(a_aps_service.cmd) {
           case LRWPAN_SVC_APS_GENERIC_TX:
			 aps_pib.flags.bits.IsUsrBufferFree = 0;
#ifdef LRWPAN_COORDINATOR
             if (APS_GET_FRM_DLVRMODE(a_aps_tx_data.aps_fcf) == APS_FRM_DLVRMODE_INDIRECT){
               //this is a special case. A Coordinator endpoint is sending indirect.
               //we need to inject this into the stack as if it has been received
               apsState = APS_STATE_INJECT_INDIRECT;
               goto apsFSM_start;
             }
#endif
             //Indirect vs Direct is handled within the apsTxData() function				
             //at this point ready to begin formating packet.
             //do not exit this state until we can grab the TX buffer.
             if (phyTxUnLocked()) {
               phyGrabTxLock(); //prevents lower stack layers from grabbing TX buffer.
               phy_pib.currentTxFlen = 0;  //set frame length to zero, build from scratch
               apsTxData(TRUE);
			   aps_pib.flags.bits.IsUsrBufferFree = 1;
               apsState = APS_STATE_GENERIC_TX_WAIT;
             }
             break;

           case LRWPAN_SVC_APS_SEND_END_DEVICE_ANNOUNCE:
             if (phyTxUnLocked()) {
               phyGrabTxLock(); //prevents lower stack layers from grabbing TX buffer.
               zepFmtEndDeviceAnnounce();
               phy_pib.currentTxFlen = 0;  //set frame length to zero, build from scratch
               apsTxData(FALSE);           //payload already in TX buffer
               apsState = APS_STATE_GENERIC_TX_WAIT;
             }

             break;

			case LRWPAN_SVC_APS_PING_PARENT:
             if (phyTxUnLocked()) {
               phyGrabTxLock(); //prevents lower stack layers from grabbing TX buffer.
               zepFmtPing();
               phy_pib.currentTxFlen = 0;  //set frame length to zero, build from scratch
               apsTxData(FALSE);           //payload already in TX buffer
               apsState = APS_STATE_GENERIC_TX_WAIT;
             }

             break;

           case LRWPAN_SVC_APS_NWK_PASSTHRU:
             //for NWK calls that have to pass thru the APS layer
             //this just serves to lock the APS layer while the
             //the NWK layer is doing its thing
             if (nwkBusy()) break;  //wait until nwk is idle
             nwkDoService();
             apsState = APS_STATE_NWK_PASSTHRU_WAIT;
             break;

           default: break;
           }//end switch(a_aps_service.cmd)

           break;

	 case APS_STATE_ACK_SEND_START:
           if (phyTxLocked()) break;
           //send an ACK
           //lock the TX buffer
           phyGrabTxLock();
           //we are now ready
           apsFormatAck();
           phy_pib.currentTxFlen = 0;  //set frame length to zero, build from scratch
           apsTxData(TRUE);
           //data sent, release the RX buffer, will let RX FSM resume
           aps_pib.flags.bits.ackSendPending = 0;
           apsState = APS_STATE_GENERIC_TX_WAIT;

           break;

	 case APS_STATE_GENERIC_TX_WAIT:
           if (!apsTXIdle()) break;
           //TX is finished, copy status
           a_aps_service.status = apsTxFSM_status;
           //release the TX buffer lock before exiting.
           phyReleaseTxLock();
           apsState = APS_STATE_IDLE;
           if (aps_pib.flags.bits.indirectPending) {
             //have used this state to wait for finishing sending an
             //ACK back to the source of an indirect transmit. Now
             //finish resolving the indirect
             goto apsFSM_start;
           }


           break;

  case APS_STATE_NWK_PASSTHRU_WAIT:
    //for split-phase passthrus
    if (nwkBusy()) break;
    a_aps_service.status = a_nwk_service.status;
    apsState = APS_STATE_IDLE;
    break;

    //wait for the ZEP FSM to be idle so that it can start

⌨️ 快捷键说明

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