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

📄 mac_tx_engine.c

📁 ucos在NEC平台下的移植
💻 C
📖 第 1 页 / 共 3 页
字号:
//
//  DESCRIPTION:
//      Schedules the active packet for transmission ASAP. This function is only used in a beacon 
//      network. If the packet cannot be transmitted, a flag is set to indicate that the transmission 
//      should continue after the next receive beacon, or after the "locate beacon" timeout.
//-------------------------------------------------------------------------------------------------------
BYTE mtxSetStartupTime(void) {
    INT32 bosLeft;
    UINT8 randomBackoff;
    MAC_TX_PACKET *pPacket = mtxInfo.pPacket;

#if MAC_OPT_FFD
    // If this is an indirect packet, then make sure that it still is requested!
    if ((pPacket->txOptions & TX_OPT_INDIRECT) && !pPacket->requested) return MTX_SST_INDIRECT_PACKET_TOO_LATE;
#endif
        
    // Calculate the random backoff period
    if (pPacket->txMode & MTX_MODE_USE_CSMACA_BM) {
        randomBackoff = msupGetRandomByte() & (BM(mtxInfo.be) - 1);
    } else {
        randomBackoff = 0;
    }
    
    // Calculate the number of FULL backoff slots left in the CAP (including the two/three periods required to prepare for transmission
    if (mpib.macSuperframeOrder == 15) {
        bosLeft = 0;
    } else if (mbcnInfo.lastSfSpec.battLifeExt && pPacket->toCoord) {
        //        <----------------- The CAP duration ----------------->   <------- Used CAP ------>   < Delay + overhead + duration >                                                                                         
        bosLeft = (mbcnInfo.beaconDuration + mpib.macBattLifeExtPeriods) - (mtimInfo.bosCounter + 1) -     (randomBackoff + 2 + 1) - 5;
    } else {
        //        <- The CAP duration >   <------- Used CAP ------>   <-------- Delay + overhead + duration -------->   <-- Beacon margin -->                                                                  
        bosLeft = msupCalcCapDuration() - (mtimInfo.bosCounter + 1) - (randomBackoff + 2 + mtxInfo.pPacket->duration) - mbcnGetBeaconMargin() - 5; 
    }
    
    // Subtract an extra backoff period if slotted CSMA-CA is used (2 CCA checks instead of 1)
    if (pPacket->slotted) bosLeft--;

    // Default values...
    mtxInfo.searchForBeacon = FALSE;
    mtxInfo.waitForBeacon = FALSE;
    
    // Is there enough time to transmit in this CAP (are we really in the CAP)?
    if (bosLeft > 0) {
        if (!mtxStartAfterDelay(randomBackoff)) return MTX_SST_RESOURCE_SHORTAGE;
    } else {
        
        // CSMA-CA should not be resumed in the next superframe for indirect packets!
        if (pPacket->txOptions & TX_OPT_INDIRECT) {
            return MTX_SST_INDIRECT_PACKET_TOO_LATE;
        
        // For direct packets: Wait for the beacon, and search for it if beacon tracking is not enabled
        } else {
            if (!mtimSetCallback(mtxLocateBeaconTimeout, msupCalcBeaconInterval())) return MTX_SST_RESOURCE_SHORTAGE;
            mtxInfo.waitForBeacon = TRUE;
            mtxInfo.randomBackoff = randomBackoff;
            
            // If beacons are not being tracked, then try to locate one before transmitting
            // Note: If beacon tracking is stopped, but searchForBeacon = TRUE, then RX must not be turned off!
            if (!(mbcnInfo.trackBeacon || GET_MF(MF_TRANSMIT_BEACON))) {
                mrxIncrOnCounter();
                mtxInfo.searchForBeacon = TRUE;
            }
        }
    }
    return MTX_SST_SUCCESS;

} // csmaSetStartupTime




//-------------------------------------------------------------------------------------------------------
//  void mtxResumeAfterBeacon(void)
//
//  DESCRIPTION:
//      Resumes transmission after the beacon has been received, if there is a sufficient number of 
//      backoff slot left in the CAP.
//-------------------------------------------------------------------------------------------------------
void mtxResumeAfterBeaconCallback(void) {
    //MAC_TX_PACKET *pPacket = mbcnInfo.pTxPacket;
    //MAC_TX_PACKET *pPacket = mtxInfo.pPacket;
    
    mtimInfo.bosCounter = mbcnInfo.beaconDuration + 2;
    mschAddTask(mschReserveTask(), MAC_TASK_PRI_MEDIUM, mtxResumeAfterBeaconTask, 0); 
     
}



void mtxResumeAfterBeaconTask(MAC_TASK_INFO *pTask) { mtxResumeAfterBeacon(); mschRemoveTask(pTask->priority, MSCH_KEEP_TASK_IN_PROGRESS_BM); }
void mtxResumeAfterBeacon(void) {
    INT32 capLeft;
    INT32 capRequired;
    
    if (mtxInfo.waitForBeacon) {
        
        // Cancel the beacon location timeout
        mtimCancelCallback(mtxLocateBeaconTimeout);
        
        // Calculate the CAP duration (number of backoff slots)
        if (mbcnInfo.lastSfSpec.battLifeExt) {
            //        <----------------- The CAP duration ----------------->   <------ Used CAP ------->
            capLeft = (mbcnInfo.beaconDuration + mpib.macBattLifeExtPeriods) - (mtimInfo.bosCounter + 1);
            capRequired = mtxInfo.randomBackoff + 2 + 1 + !!mtxInfo.pPacket->slotted;
        } else {
            //        <- The CAP duration >   <------ Used CAP ------->   <-- Beacon margin -->
            capLeft = msupCalcCapDuration() - (mtimInfo.bosCounter + 1) - mbcnGetBeaconMargin(); 
            capRequired = mtxInfo.randomBackoff + 2 + mtxInfo.pPacket->duration + !!mtxInfo.pPacket->slotted;
        }

        // Enough time left in the CAP to transmit now?
        if (capLeft >= capRequired) {
            if (mtxInfo.searchForBeacon) {
                mtxInfo.searchForBeacon = FALSE;
                mrxDecrOnCounter();
            }
            mtxInfo.waitForBeacon = FALSE;
            mtxStartAfterDelay(msupGetRandomByte() & (BM(mtxInfo.be) - 1));
            //mtxCreateStartTask();
            
        // Or do we have to wait for another beacon?
        } else {
            // Subtract the number of backoff periods left in the CAP (we cannot subtract mpib.macBattLifeExtPeriods
            // and transmit when mtxInfo.randomBackoff became zero or negative!)
            if (capLeft > 0) {
                mtxInfo.randomBackoff = MAX(0, mtxInfo.randomBackoff - capLeft);
            }
        }
    }
} // mtxResumeAfterBeacon




//-------------------------------------------------------------------------------------------------------
//  void mtxPacketTimeout(void)
//
//  DESCRIPTION:
//      Transmission timeout:
//          Ack.req = TRUE: 
//-------------------------------------------------------------------------------------------------------
void mtxPacketTimeout(void) {
    
    // Turn off RX (turned on by mtxStartTransmission(...))
    mrxDecrOnCounter();
    
    // For packets transmitted using mtxScheduleTransmission(...)
    if (mtxInfo.status == MTX_STATUS_TRANSMISSION_STARTED) {
        if (mtxInfo.pPacket->txOptions & TX_OPT_ACK_REQ) {
            mtxInfo.status = MTX_STATUS_ACK_TIMEOUT;
        } else {
            mtxInfo.status = MTX_STATUS_TX_FINISHED;
        }
    }
    
} // mtxPacketTimeout




//-------------------------------------------------------------------------------------------------------
//  void mtxScheduleTransmission(MAC_TASK_INFO *pTask)
//
//  DESCRIPTION:
//      This task is created to start a transmission. The task is responsible for setting up the CSMA-CA
//      mechanism, scheduling the transmission, and handle the result when the packet timeout is trigged.
//      Note: Periodically transmitted beacons bypass this task and uses mtxStartTransmission directly.
//-------------------------------------------------------------------------------------------------------
void mtxScheduleTransmission(MAC_TASK_INFO *pTask) {
    MAC_TX_PACKET *pPacket = (MAC_TX_PACKET*) pTask->taskData;
    MAC_TX_PACKET *indirectpPacket;
    switch (pTask->state) {
    case MTX_STATE_INIT_TRANSMISSION:
        ENABLE_FIFOP_INT();
    
        // Reschedule this task if we're in scan mode and the "scan related" flag is not set on this packet
        if ((macInfo.state & MAC_STATE_SCAN_BM) && !(pPacket->txMode & MTX_MODE_SCAN_RELATED_BM)) {
            mschRescheduleTask(pTask, MTX_STATE_INIT_TRANSMISSION);
        }
    
        // Set the TX engine packet pointer
        mtxInfo.pPacket = pPacket;    
#if MAC_OPT_FFD
       //If data frame and packet in inderect quee set pending frame bit in outgoing frame.
       if (( (pPacket->pHeader[0] & FRAME_TYPE_BM)== FT_DATA) && (miqInfo.firstIndirectPacket != NO_PACKET))
       {
            //Find out if we have any inderect packets to in memmory to this node..
            if ((pPacket->pHeader[1] & DEST_ADDR_BM) == DEST_ADDR_EXT)
            {
                indirectpPacket = miqFindIndirectPacket((ADDRESS *) &pPacket->pHeader[5], TRUE);//(ADDRESS *pDestAddr, BOOL isExtAddr);                
            }
            else
            {
                indirectpPacket = miqFindIndirectPacket((ADDRESS *) &pPacket->pHeader[5], FALSE);//(ADDRESS *pDestAddr, BOOL isExtAddr);
            }
            if (indirectpPacket != NULL)
            {
                pPacket->pHeader[0] |= FRAME_PENDING_BM;
            }
        }
#endif        
        
        // No break here!
        
    case MTX_STATE_INIT_CSMACA:
    
        // Reset CSMA-CA parameters
        mtxInfo.nb = 0;
        mtxInfo.be = mpib.macMinBE;
        pPacket->slotted = !((mpib.macBeaconOrder == 15) || (pPacket->txMode & MTX_MODE_FORCE_UNSLOTTED_BM));
        if (pPacket->slotted && mpib.macBattLifeExt) {
            mtxInfo.be = MIN(2, mtxInfo.be);
        }
        pTask->state = MTX_STATE_SET_STARTUP_TIME;
        break;
        
    case MTX_STATE_SET_STARTUP_TIME:
    
        // In a non-beacon network: Start the transmission with or without a random delay (CSMA-CA)
        if (!pPacket->slotted) {
            if (pPacket->txMode & MTX_MODE_USE_CSMACA_BM) {
                mtxStartAfterDelay(msupGetRandomByte() & (BM(mtxInfo.be) - 1));
            } else {
                mtxCreateStartTask();
            }
            pTask->state = MTX_STATE_WAIT;
            mtxInfo.status = MTX_STATUS_WAITING;
        
        // In a beacon network: Calculate and set the startup time
        } else {
            switch (mtxSetStartupTime()) {
            case MTX_SST_SUCCESS:
            
                // The startup time has been set -> proceed to the next state
                pTask->state = MTX_STATE_WAIT;
                mtxInfo.status = MTX_STATUS_WAITING;
                break;
                
            case MTX_SST_RESOURCE_SHORTAGE:
                
                // Repeat this step if there's a temporary shortage on resources (timers and tasks)
                break;
                
            case MTX_SST_INDIRECT_PACKET_TOO_LATE:
#if MAC_OPT_FFD
                // We have not even tried to transmit the packet in this superframe -> no changes...
                if (!mtxInfo.nb) {
                    miqSetRequested(pPacket, FALSE);
                    pPacket->transmissionStarted = FALSE;
                    mschRemoveTask(pTask->priority, MSCH_KEEP_TASK_IN_PROGRESS_BM);
                    
                // We've had at least one channel access failure... (we don't get here because of NO_ACK)
                } else {
                    if (pPacket->retriesLeft) {
                        pTask->state = MTX_STATE_WAIT;
                        mtxInfo.status = MTX_STATUS_CHANNEL_ACCESS_FAILURE;
                    } else {
                        mtxFinishTransmission(CHANNEL_ACCESS_FAILURE, pPacket, pTask);
                    }
                }
#endif
                break;
            }
            break;
        }
        break;
    
    case MTX_STATE_WAIT:
        ENABLE_FIFOP_INT();
    
        switch (mtxInfo.status) {
        case MTX_STATUS_WAITING:
        case MTX_STATUS_TRANSMISSION_STARTED:

⌨️ 快捷键说明

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