A library implementing IEEE 802.15.4 PHY functionality for the MCR20A transceiver. The PHY sublayer provides two services: the PHY data service and the PHY management service interfacing to the PHY sublayer management entity (PLME) service access point (SAP) (known as PLME-SAP). The PHY data service enables the transmission and reception of PHY protocol data units (PSDUs) over the media (radio).
Fork of fsl_phy_mcr20a by
The Freescale PHY Layer deals with the physical burst which is to be sent and/or received. It performs modulation and demodulation, transmitter and receiver switching, fragmentation, scrambling, interleaving, and error correction coding. The communication to the upper protocol layers is carried out through the Layer 1 Interface.
The PHY Layer is capable of executing the following sequences:
- I (Idle)
- R (Receive Sequence conditionally followed by a TxAck)
- T (Transmit Sequence)
- C (Standalone CCA)
- CCCA (Continuous CCA)
- TR (Transmit/Receive Sequence - transmit unconditionally followed by either an R or RxAck)
In addition to these sequences the PHY Layer also integrates a packet processor which determines whether the packet is MAC-compliant, and if it is, whether it is addressed to the end device. Another feature of the packet processor is Source Address Matching which can be viewed as an extension of packet filtering; however its function is very specific to its intended application (data-polling and indirect queue management by a PAN Coordinator).
Documentation
PHY/MPM.c
- Committer:
- andreikovacs
- Date:
- 2015-08-18
- Revision:
- 0:764779eedf2d
File content as of revision 0:764779eedf2d:
/*! * Copyright (c) 2015, Freescale Semiconductor, Inc. * All rights reserved. * * \file MPM.c * This is the source file for the Multiple PAN Manager. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * o Redistributions of source code must retain the above copyright notice, this list * of conditions and the following disclaimer. * * o 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. * * o Neither the name of Freescale Semiconductor, Inc. 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 COPYRIGHT HOLDER OR 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. */ /************************************************************************************ ************************************************************************************* * Include ************************************************************************************* ************************************************************************************/ #include "EmbeddedTypes.h" #include "MpmInterface.h" #include "Phy.h" #if 0 #include "FunctionLib.h" #include "MemManager.h" #include "Panic.h" #endif #if gMpmIncluded_d /************************************************************************************ ************************************************************************************* * Public macros ************************************************************************************* ************************************************************************************/ /************************************************************************************ ************************************************************************************* * Public type definitions ************************************************************************************* ************************************************************************************/ /************************************************************************************ ************************************************************************************* * Private memory declarations ************************************************************************************* ************************************************************************************/ uint8_t mRegisteredPANs; bool_t mMpmExclusiveAccess; panInfo_t mPanInfo[gMpmMaxPANs_c]; panInfo_t *pActivePANs[gMpmPhyPanRegSets_c]; /************************************************************************************ ************************************************************************************* * Private functions prototypes ************************************************************************************* ************************************************************************************/ static void MPM_SetPanSettingsInPhy( uint8_t panIndex ); static uint8_t MPM_AllocateResource( bool_t force, uint8_t panIdx ); /************************************************************************************ ************************************************************************************* * Public functions ************************************************************************************* ************************************************************************************/ /*! ********************************************************************************* * \brief This function determines the instance of the MAC associated with a PHY regSet * * \param[in] regSet The PHY registry set * * \return The instance of the MAC associated with a PHY registry set. * ********************************************************************************** */ uint32_t MPM_GetMacInstanceFromRegSet(uint32_t regSet) { if( pActivePANs[regSet] ) return pActivePANs[regSet]->macInstance; return 0; } /*! ********************************************************************************* * \brief This function determines the PHY regSet for the specified panIndex * * \param[in] panIdx The index in mPanInfo[] table * * \return The PHY registry set. * ********************************************************************************** */ uint32_t MPM_GetRegSet( uint8_t panIdx ) { return mPanInfo[panIdx].phyRegSet; } /*! ********************************************************************************* * \brief This function determines the PHY regSet for the specified panIndex * * \param[in] pibId The id of the PHY PIB * \param[in] pValue The value of the PHY PIB * \param[in] panIdx The index in mPanInfo[] table * * \return The status of the operation. * ********************************************************************************** */ phyStatus_t MPM_SetPIB(phyPibId_t pibId, void* pValue, uint8_t panIdx) { switch(pibId) { #if gMpmUseDifferentTxPwrLevel_c case gPhyPibTransmitPower_c: if( (*(uint8_t*)pValue < 3) || (*(uint8_t*)pValue > 31) ) { return gPhyInvalidParameter_c; } mPanInfo[panIdx].pwrLevel = *(uint8_t*)pValue; break; #endif #if (gMpmMaxPANs_c > gMpmPhyPanRegSets_c) case gPhyPibCurrentChannel_c: if( (*(uint8_t*)pValue < 11) || (*(uint8_t*)pValue > 26) ) { return gPhyInvalidParameter_c; } mPanInfo[panIdx].channel = *(uint8_t*)pValue; break; case gPhyPibLongAddress_c: mPanInfo[panIdx].longAddr = *(uint64_t*)pValue; break; case gPhyPibShortAddress_c: mPanInfo[panIdx].shortAddr = *(uint16_t*)pValue; break; case gPhyPibPanId_c: mPanInfo[panIdx].panId = *(uint16_t*)pValue; break; case gPhyPibPanCoordinator_c: if( *(bool_t*)pValue ) mPanInfo[panIdx].flags |= gMpmFlagPanCoord_c; else mPanInfo[panIdx].flags &= ~gMpmFlagPanCoord_c; break; #endif case gPhyPibRxOnWhenIdle: if( *(bool_t*)pValue ) mPanInfo[panIdx].flags |= gMpmFlagRxOnWhenIdle_c; else mPanInfo[panIdx].flags &= ~gMpmFlagRxOnWhenIdle_c; break; case gPhyPibPromiscuousMode_c: if( *(bool_t*)pValue ) mPanInfo[panIdx].flags |= gMpmFlagPromiscuous_c; else mPanInfo[panIdx].flags &= ~gMpmFlagPromiscuous_c; break; default: return gPhyUnsupportedAttribute_c; } return gPhySuccess_c; } phyStatus_t MPM_GetPIB(phyPibId_t pibId, void *pValue, uint8_t panIdx) { switch(pibId) { #if gMpmUseDifferentTxPwrLevel_c case gPhyPibTransmitPower_c: *(uint8_t*)pValue = mPanInfo[panIdx].pwrLevel; break; #endif #if (gMpmMaxPANs_c > gMpmPhyPanRegSets_c) case gPhyPibCurrentChannel_c: *(uint8_t*)pValue = mPanInfo[panIdx].channel; break; case gPhyPibLongAddress_c: *(uint64_t*)pValue = mPanInfo[panIdx].longAddr; break; case gPhyPibShortAddress_c: *(uint16_t*)pValue = mPanInfo[panIdx].shortAddr; break; case gPhyPibPanId_c: *(uint16_t*)pValue = mPanInfo[panIdx].panId; break; case gPhyPibPanCoordinator_c: *(uint8_t*)pValue = !!(mPanInfo[panIdx].flags & gMpmFlagPanCoord_c); break; #endif case gPhyPibRxOnWhenIdle: *(uint8_t*)pValue = !!(mPanInfo[panIdx].flags & gMpmFlagRxOnWhenIdle_c); break; case gPhyPibPromiscuousMode_c: *(uint8_t*)pValue = !!(mPanInfo[panIdx].flags & gMpmFlagPromiscuous_c); break; default: return gPhyUnsupportedAttribute_c; } return gPhySuccess_c; } /*! ********************************************************************************* * \brief This function initializes the MPM module. * * \param[in] None. * * \return None * ********************************************************************************** */ void MPM_Init( void ) { uint32_t i; mRegisteredPANs = 0; mMpmExclusiveAccess = FALSE; FLib_MemSet( mPanInfo, 0x00, sizeof(mPanInfo) ); FLib_MemSet( pActivePANs, 0x00, sizeof(pActivePANs) ); for(i=0; i<gMpmMaxPANs_c; i++) mPanInfo[i].phyRegSet = gMpmInvalidRegSet_c; PhyPpSetDualPanDwell( ((mDefaultDualPanDwellPrescaller_c << mDualPanDwellPrescallerShift_c) & mDualPanDwellPrescallerMask_c) | ((mDefaultDualPanDwellTime_c << mDualPanDwellTimeShift_c ) & mDualPanDwellTimeMask_c) ); } /*! ********************************************************************************* * \brief This function prepare the Radio for a TX/CCA/ED operation * * \param[in] macInstance The instance of the MAC * * \return The status of the Operation * ********************************************************************************** */ phyStatus_t MPM_PrepareForTx( instanceId_t macInstance ) { uint8_t panIdx = MPM_GetPanIndex(macInstance); if( TRUE == mMpmExclusiveAccess && mPanInfo[panIdx].locked <= 0 ) return gPhyChannelBusy_c; /* Allocate HW Resources if necessary */ if( mPanInfo[panIdx].phyRegSet == gMpmInvalidRegSet_c ) { if( gMpmInvalidRegSet_c == MPM_AllocateResource( TRUE, panIdx ) ) return gPhyChannelBusy_c; MPM_SetPanSettingsInPhy( panIdx ); } /* Disable DualPan Auto Mode, and select the Active PAN */ PhyPpSetDualPanAuto( FALSE ); PhyPpSetDualPanActiveNwk( mPanInfo[panIdx].phyRegSet ); return gPhySuccess_c; } /*! ********************************************************************************* * \brief This function checks if a PAN has the RxOnWhenIdle PIB set. * If an Rx needs to be started, it makes the propper settings in PHY. * * \param[in] None. * * \return phyStatus * ********************************************************************************** */ phyStatus_t MPM_PrepareForRx( instanceId_t macInstance ) { uint32_t i, count = 0; uint32_t activePan; if( gInvalidInstanceId_c != macInstance ) //Rx { i = MPM_GetPanIndex(macInstance); if( !mMpmExclusiveAccess || mPanInfo[i].locked ) { /* Allocate HW Resources if necessary */ if( mPanInfo[i].phyRegSet == gMpmInvalidRegSet_c ) { if( gMpmInvalidRegSet_c == MPM_AllocateResource( TRUE, i ) ) return gPhyChannelBusy_c; MPM_SetPanSettingsInPhy( i ); } count++; activePan = mPanInfo[i].phyRegSet; } } else //RxOnWhenIdle { for( i=0; i<gMpmPhyPanRegSets_c; i++) { if( (NULL != pActivePANs[i]) && (pActivePANs[i]->flags & gMpmFlagRxOnWhenIdle_c) && ( !mMpmExclusiveAccess || pActivePANs[i]->locked ) ) { activePan = i; count++; } } } if( !count ) return gPhyChannelBusy_c; /* Set the Active PAN and DualPan Auto mode if needed*/ PhyPpSetDualPanActiveNwk( activePan ); PhyPpSetDualPanAuto( count > 1 ); return gPhySuccess_c; } /*! ********************************************************************************* * \brief This function returns the PAN index for a MAC instance * * \param[in] macInstance The instance of the MAC * * \return The PAN index or -1 if it was not found * ********************************************************************************** */ int32_t MPM_GetPanIndex( instanceId_t macInstance ) { uint32_t i; /* Get PAN Index for the macInstance */ for( i=0; i<mRegisteredPANs; i++ ) { if( mPanInfo[i].macInstance == macInstance ) return i; } /* The instance of the MAC is not registered! * Register the current MAC instance if there is enough space. */ if( mRegisteredPANs < gMpmMaxPANs_c ) { mPanInfo[mRegisteredPANs].macInstance = macInstance; /* Try to allocate HW resource */ mPanInfo[mRegisteredPANs].phyRegSet = MPM_AllocateResource( FALSE, i ); mRegisteredPANs++; } else { i = -1; } return i; } /*! ********************************************************************************* * \brief This function configures the MPM module * * \param[in] pCfg pointer to a configuration structure * * \remarks * The Dual PAN dwell time prescaller values: 0-3 * The Dual PAN dwell time values 0-63. * The (dwellTime+1) represents multiples of the prescaller time base. * ********************************************************************************** */ void MPM_SetConfig( mpmConfig_t *pCfg ) { PhyPpSetDualPanAuto ( FALSE ); PhyPpSetDualPanDwell( pCfg->dwellTime ); MPM_AllocateResource( TRUE, MPM_GetPanIndex(pCfg->activeMAC) ); PhyPpSetDualPanAuto ( pCfg->autoMode ); if( PhyIsIdleRx(0) ) { PhyPlmeForceTrxOffRequest(); Radio_Phy_TimeRxTimeoutIndication(0); } } /*! ********************************************************************************* * \brief This function returns the MPM configuration * * \param[in] pCfg pointer to a configuration structure * * \return None. * ********************************************************************************** */ void MPM_GetConfig( mpmConfig_t *pCfg ) { pCfg->dwellTime = PhyPpGetDualPanDwell(); pCfg->activeMAC = MPM_GetMacInstanceFromRegSet( PhyPpGetDualPanActiveNwk() ); pCfg->autoMode = PhyPpGetDualPanAuto(); } #endif /* #if gMpmIncluded_d */ /*! ********************************************************************************* * \brief This function Acquires a PAN for exclusive access. * * \param[in] macInstance The instance of the MAC * * \return The status of the operation * ********************************************************************************** */ phyStatus_t MPM_AcquirePAN( instanceId_t macInstance ) { #if gMpmIncluded_d int32_t panIndex = MPM_GetPanIndex(macInstance); /* Check if another PAN is acquired */ if( TRUE == mMpmExclusiveAccess && mPanInfo[panIndex].locked <= 0 ) { return gPhyBusy_c; } if( mPanInfo[panIndex].locked == 0 ) { mMpmExclusiveAccess = TRUE; if( PhyIsIdleRx(0) ) { PhyPlmeForceTrxOffRequest(); Radio_Phy_TimeRxTimeoutIndication(0); } } mPanInfo[panIndex].locked++; #endif return gPhySuccess_c; } /*! ********************************************************************************* * \brief This function Releases a PAN that was Acquired * * \param[in] macInstance The instance of the MAC * * \return The status of the operation * ********************************************************************************** */ phyStatus_t MPM_ReleasePAN( instanceId_t macInstance ) { #if gMpmIncluded_d uint8_t panIndex = MPM_GetPanIndex(macInstance); mPanInfo[panIndex].locked--; if( mPanInfo[panIndex].locked == 0 ) { mMpmExclusiveAccess = FALSE; if( PhyIsIdleRx(0) ) { PhyPlmeForceTrxOffRequest(); Radio_Phy_TimeRxTimeoutIndication(0); } } #endif return gPhySuccess_c; } /************************************************************************************ ************************************************************************************* * Private functions ************************************************************************************* ************************************************************************************/ #if gMpmIncluded_d /*! ********************************************************************************* * \brief This function alocates a registry set to a PAN. * * \param[in] force If this parameter is TRUE, then another PAN can be preempted. * \param[in] panIdx The index into the MPM database * * \return The register set allocated for the specified PAN. * ********************************************************************************** */ static uint8_t MPM_AllocateResource( bool_t force, uint8_t panIdx ) { uint32_t i, regSet = gMpmInvalidRegSet_c; if( mPanInfo[panIdx].phyRegSet != gMpmInvalidRegSet_c ) return mPanInfo[panIdx].phyRegSet; for( i=0; i<gMpmPhyPanRegSets_c; i++ ) { if( NULL == pActivePANs[i] ) { regSet = i; break; } else if( (force) && (pActivePANs[i]->flags == 0) && (pActivePANs[i]->locked <= 0) ) { regSet = i; } } if( regSet != gMpmInvalidRegSet_c ) { if( NULL != pActivePANs[regSet] ) { pActivePANs[regSet]->phyRegSet = gMpmInvalidRegSet_c; } pActivePANs[regSet] = &mPanInfo[panIdx]; pActivePANs[regSet]->phyRegSet = regSet; } return regSet; } /*! ********************************************************************************* * \brief This function will store PAN settings in PHY. * * \param[in] panIdx The index into the MPM database * * \return None. * * \remarks Function assumes that the PAN is active! * ********************************************************************************** */ static void MPM_SetPanSettingsInPhy( uint8_t panIndex ) { panInfo_t *pPAN = &mPanInfo[panIndex]; #if gMpmUseDifferentTxPwrLevel_c PhyPlmeSetPIBRequest(gPhyPibTransmitPower_c, pPAN->pwrLevel, pPAN->phyRegSet, 0 ); #endif #if (gMpmMaxPANs_c > gMpmPhyPanRegSets_c) PhyPlmeSetPIBRequest(gPhyPibPromiscuousMode_c, !!(pPAN->flags & gMpmFlagPromiscuous_c), pPAN->phyRegSet, 0 ); PhyPlmeSetPIBRequest(gPhyPibRxOnWhenIdle, !!(pPAN->flags & gMpmFlagRxOnWhenIdle_c), pPAN->phyRegSet, 0 ); PhyPlmeSetPIBRequest(gPhyPibPanCoordinator_c, !!(pPAN->flags & gMpmFlagPanCoord_c), pPAN->phyRegSet, 0 ); PhyPlmeSetPIBRequest(gPhyPibPanId_c, pPAN->panId, pPAN->phyRegSet, 0 ); PhyPlmeSetPIBRequest(gPhyPibShortAddress_c, pPAN->shortAddr, pPAN->phyRegSet, 0 ); PhyPlmeSetPIBRequest(gPhyPibLongAddress_c, pPAN->longAddr, pPAN->phyRegSet, 0 ); PhyPlmeSetPIBRequest(gPhyPibCurrentChannel_c, pPAN->channel, pPAN->phyRegSet, 0 ); #else (void)pPAN; #endif } #endif /* gMpmIncluded_d */