NXP / fsl_phy_mcr20a

Fork of fsl_phy_mcr20a by Freescale

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MPM.c Source File

MPM.c

Go to the documentation of this file.
00001 /*!
00002 * Copyright (c) 2015, Freescale Semiconductor, Inc.
00003 * All rights reserved.
00004 *
00005 * \file MPM.c
00006 * This is the source file for the Multiple PAN Manager.
00007 *
00008 * Redistribution and use in source and binary forms, with or without modification,
00009 * are permitted provided that the following conditions are met:
00010 *
00011 * o Redistributions of source code must retain the above copyright notice, this list
00012 *   of conditions and the following disclaimer.
00013 *
00014 * o Redistributions in binary form must reproduce the above copyright notice, this
00015 *   list of conditions and the following disclaimer in the documentation and/or
00016 *   other materials provided with the distribution.
00017 *
00018 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
00019 *   contributors may be used to endorse or promote products derived from this
00020 *   software without specific prior written permission.
00021 *
00022 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00023 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00024 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00025 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00026 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00027 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00029 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00030 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00031 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032 */
00033 
00034 /************************************************************************************
00035 *************************************************************************************
00036 * Include
00037 *************************************************************************************
00038 ************************************************************************************/
00039 
00040 #include "EmbeddedTypes.h "
00041 #include "MpmInterface.h "
00042 #include "Phy.h "
00043 
00044 #if 0
00045 #include "FunctionLib.h "
00046 #include "MemManager.h "
00047 #include "Panic.h"
00048 #endif
00049 
00050 #if gMpmIncluded_d
00051 
00052 /************************************************************************************
00053 *************************************************************************************
00054 * Public macros
00055 *************************************************************************************
00056 ************************************************************************************/
00057 
00058 /************************************************************************************
00059 *************************************************************************************
00060 * Public type definitions
00061 *************************************************************************************
00062 ************************************************************************************/
00063 
00064 /************************************************************************************
00065 *************************************************************************************
00066 * Private memory declarations
00067 *************************************************************************************
00068 ************************************************************************************/
00069 uint8_t        mRegisteredPANs;
00070 bool_t         mMpmExclusiveAccess;
00071 panInfo_t      mPanInfo[gMpmMaxPANs_c];
00072 panInfo_t     *pActivePANs[gMpmPhyPanRegSets_c];
00073 
00074 /************************************************************************************
00075 *************************************************************************************
00076 * Private functions prototypes
00077 *************************************************************************************
00078 ************************************************************************************/
00079 static void MPM_SetPanSettingsInPhy( uint8_t panIndex );
00080 static uint8_t MPM_AllocateResource( bool_t force, uint8_t panIdx );
00081 
00082 /************************************************************************************
00083 *************************************************************************************
00084 * Public functions
00085 *************************************************************************************
00086 ************************************************************************************/
00087 
00088 /*! *********************************************************************************
00089 * \brief  This function determines the instance of the MAC associated with a PHY regSet
00090 *
00091 * \param[in]  regSet The PHY registry set
00092 *
00093 * \return  The instance of the MAC associated with a PHY registry set.
00094 *
00095 ********************************************************************************** */
00096 uint32_t MPM_GetMacInstanceFromRegSet(uint32_t regSet)
00097 {
00098     if( pActivePANs[regSet] )
00099         return pActivePANs[regSet]->macInstance;
00100 
00101     return 0;
00102 }
00103 
00104 /*! *********************************************************************************
00105 * \brief  This function determines the PHY regSet for the specified panIndex
00106 *
00107 * \param[in]  panIdx The index in mPanInfo[] table
00108 *
00109 * \return  The PHY registry set.
00110 *
00111 ********************************************************************************** */
00112 uint32_t MPM_GetRegSet( uint8_t panIdx )
00113 {
00114     return mPanInfo[panIdx].phyRegSet;
00115 }
00116 
00117 /*! *********************************************************************************
00118 * \brief  This function determines the PHY regSet for the specified panIndex
00119 *
00120 * \param[in]  pibId The id of the PHY PIB
00121 * \param[in]  pValue The value of the PHY PIB
00122 * \param[in]  panIdx The index in mPanInfo[] table
00123 *
00124 * \return  The status of the operation.
00125 *
00126 ********************************************************************************** */
00127 phyStatus_t MPM_SetPIB(phyPibId_t pibId, void* pValue, uint8_t panIdx)
00128 {
00129     switch(pibId)
00130     {
00131 #if gMpmUseDifferentTxPwrLevel_c
00132     case gPhyPibTransmitPower_c:
00133         if( (*(uint8_t*)pValue < 3) || (*(uint8_t*)pValue > 31) )
00134         {
00135             return gPhyInvalidParameter_c;
00136         }
00137         mPanInfo[panIdx].pwrLevel = *(uint8_t*)pValue;
00138         break;
00139 #endif
00140 #if (gMpmMaxPANs_c > gMpmPhyPanRegSets_c)
00141     case gPhyPibCurrentChannel_c:
00142         if( (*(uint8_t*)pValue < 11) || (*(uint8_t*)pValue > 26) )
00143         {
00144             return gPhyInvalidParameter_c;
00145         }
00146         mPanInfo[panIdx].channel = *(uint8_t*)pValue;
00147         break;
00148     case gPhyPibLongAddress_c:
00149         mPanInfo[panIdx].longAddr = *(uint64_t*)pValue;
00150         break;
00151     case gPhyPibShortAddress_c:
00152         mPanInfo[panIdx].shortAddr = *(uint16_t*)pValue;
00153         break;
00154     case gPhyPibPanId_c:
00155         mPanInfo[panIdx].panId = *(uint16_t*)pValue;
00156         break;
00157     case gPhyPibPanCoordinator_c:
00158         if( *(bool_t*)pValue )
00159             mPanInfo[panIdx].flags |= gMpmFlagPanCoord_c;
00160         else
00161             mPanInfo[panIdx].flags &= ~gMpmFlagPanCoord_c;
00162         break;
00163 #endif
00164     case gPhyPibRxOnWhenIdle:
00165         if( *(bool_t*)pValue )
00166             mPanInfo[panIdx].flags |= gMpmFlagRxOnWhenIdle_c;
00167         else
00168             mPanInfo[panIdx].flags &= ~gMpmFlagRxOnWhenIdle_c;
00169         break;
00170     case gPhyPibPromiscuousMode_c:
00171         if( *(bool_t*)pValue )
00172             mPanInfo[panIdx].flags |= gMpmFlagPromiscuous_c;
00173         else
00174             mPanInfo[panIdx].flags &= ~gMpmFlagPromiscuous_c;
00175         break;
00176     default:
00177         return gPhyUnsupportedAttribute_c;
00178     }
00179 
00180     return gPhySuccess_c;
00181 }
00182 
00183 phyStatus_t MPM_GetPIB(phyPibId_t pibId, void *pValue, uint8_t panIdx)
00184 {
00185     switch(pibId)
00186     {
00187 #if gMpmUseDifferentTxPwrLevel_c
00188     case gPhyPibTransmitPower_c:
00189         *(uint8_t*)pValue = mPanInfo[panIdx].pwrLevel;
00190         break;
00191 #endif
00192 #if (gMpmMaxPANs_c > gMpmPhyPanRegSets_c)
00193     case gPhyPibCurrentChannel_c:
00194         *(uint8_t*)pValue = mPanInfo[panIdx].channel;
00195         break;
00196     case gPhyPibLongAddress_c:
00197         *(uint64_t*)pValue = mPanInfo[panIdx].longAddr;
00198         break;
00199     case gPhyPibShortAddress_c:
00200         *(uint16_t*)pValue = mPanInfo[panIdx].shortAddr;
00201         break;
00202     case gPhyPibPanId_c:
00203         *(uint16_t*)pValue = mPanInfo[panIdx].panId;
00204         break;
00205     case gPhyPibPanCoordinator_c:
00206         *(uint8_t*)pValue = !!(mPanInfo[panIdx].flags & gMpmFlagPanCoord_c);
00207         break;
00208 #endif
00209     case gPhyPibRxOnWhenIdle:
00210         *(uint8_t*)pValue = !!(mPanInfo[panIdx].flags & gMpmFlagRxOnWhenIdle_c);
00211         break;
00212     case gPhyPibPromiscuousMode_c:
00213         *(uint8_t*)pValue = !!(mPanInfo[panIdx].flags & gMpmFlagPromiscuous_c);
00214         break;
00215     default:
00216         return gPhyUnsupportedAttribute_c;
00217     }
00218 
00219     return gPhySuccess_c;
00220 }
00221 
00222 
00223 /*! *********************************************************************************
00224 * \brief  This function initializes the MPM module.
00225 *
00226 * \param[in]  None.
00227 *
00228 * \return  None
00229 *
00230 ********************************************************************************** */
00231 void MPM_Init( void )
00232 {
00233     uint32_t i;
00234 
00235     mRegisteredPANs = 0;
00236     mMpmExclusiveAccess = FALSE;
00237     FLib_MemSet( mPanInfo, 0x00, sizeof(mPanInfo) );
00238     FLib_MemSet( pActivePANs, 0x00, sizeof(pActivePANs) );
00239 
00240     for(i=0; i<gMpmMaxPANs_c; i++)
00241       mPanInfo[i].phyRegSet = gMpmInvalidRegSet_c;
00242 
00243     PhyPpSetDualPanDwell( ((mDefaultDualPanDwellPrescaller_c << mDualPanDwellPrescallerShift_c) & mDualPanDwellPrescallerMask_c) |
00244                           ((mDefaultDualPanDwellTime_c       << mDualPanDwellTimeShift_c      ) & mDualPanDwellTimeMask_c) );
00245 }
00246 
00247 /*! *********************************************************************************
00248 * \brief  This function prepare the Radio for a TX/CCA/ED operation
00249 *
00250 * \param[in]  macInstance The instance of the MAC
00251 *
00252 * \return  The status of the Operation
00253 *
00254 ********************************************************************************** */
00255 phyStatus_t MPM_PrepareForTx( instanceId_t macInstance )
00256 {
00257     uint8_t panIdx = MPM_GetPanIndex(macInstance);
00258 
00259     if( TRUE == mMpmExclusiveAccess && mPanInfo[panIdx].locked <= 0 )
00260         return gPhyChannelBusy_c;
00261 
00262     /* Allocate HW Resources if necessary */
00263     if( mPanInfo[panIdx].phyRegSet == gMpmInvalidRegSet_c )
00264     {
00265         if( gMpmInvalidRegSet_c == MPM_AllocateResource( TRUE, panIdx ) )
00266             return gPhyChannelBusy_c;
00267 
00268         MPM_SetPanSettingsInPhy( panIdx );
00269     }
00270 
00271     /* Disable DualPan Auto Mode, and select the Active PAN */
00272     PhyPpSetDualPanAuto( FALSE );
00273     PhyPpSetDualPanActiveNwk( mPanInfo[panIdx].phyRegSet );
00274     return gPhySuccess_c;
00275 }
00276 
00277 /*! *********************************************************************************
00278 * \brief  This function checks if a PAN has the RxOnWhenIdle PIB set.
00279 *         If an Rx needs to be started, it makes the propper settings in PHY.
00280 *
00281 * \param[in]  None.
00282 *
00283 * \return  phyStatus
00284 *
00285 ********************************************************************************** */
00286 phyStatus_t MPM_PrepareForRx( instanceId_t macInstance )
00287 {
00288     uint32_t i, count = 0;
00289     uint32_t activePan;
00290 
00291     if( gInvalidInstanceId_c != macInstance ) //Rx
00292     {
00293         i = MPM_GetPanIndex(macInstance);
00294 
00295         if( !mMpmExclusiveAccess || mPanInfo[i].locked )
00296         {
00297             /* Allocate HW Resources if necessary */
00298             if( mPanInfo[i].phyRegSet == gMpmInvalidRegSet_c )
00299             {
00300                 if( gMpmInvalidRegSet_c == MPM_AllocateResource( TRUE, i ) )
00301                     return gPhyChannelBusy_c;
00302 
00303                 MPM_SetPanSettingsInPhy( i );
00304             }
00305 
00306             count++;
00307             activePan = mPanInfo[i].phyRegSet;
00308         }
00309     }
00310     else //RxOnWhenIdle
00311     {
00312         for( i=0; i<gMpmPhyPanRegSets_c; i++)
00313         {
00314             if( (NULL != pActivePANs[i]) &&
00315                 (pActivePANs[i]->flags & gMpmFlagRxOnWhenIdle_c) &&
00316                 ( !mMpmExclusiveAccess || pActivePANs[i]->locked ) )
00317             {
00318                 activePan = i;
00319                 count++;
00320             }
00321         }
00322     }
00323 
00324     if( !count )
00325         return gPhyChannelBusy_c;
00326 
00327     /* Set the Active PAN and DualPan Auto mode if needed*/
00328     PhyPpSetDualPanActiveNwk( activePan );
00329     PhyPpSetDualPanAuto( count > 1 );
00330     return gPhySuccess_c;
00331 }
00332 
00333 /*! *********************************************************************************
00334 * \brief  This function returns the PAN index for a MAC instance
00335 *
00336 * \param[in]  macInstance The instance of the MAC
00337 *
00338 * \return  The PAN index or -1 if it was not found
00339 *
00340 ********************************************************************************** */
00341 int32_t  MPM_GetPanIndex( instanceId_t macInstance )
00342 {
00343     uint32_t i;
00344 
00345     /* Get PAN Index for the macInstance */
00346     for( i=0; i<mRegisteredPANs; i++ )
00347     {
00348         if( mPanInfo[i].macInstance == macInstance )
00349             return i;
00350     }
00351 
00352     /* The instance of the MAC is not registered!
00353      * Register the current MAC instance if there is enough space.
00354      */
00355     if( mRegisteredPANs < gMpmMaxPANs_c )
00356     {
00357         mPanInfo[mRegisteredPANs].macInstance = macInstance;
00358 
00359         /* Try to allocate HW resource */
00360         mPanInfo[mRegisteredPANs].phyRegSet = MPM_AllocateResource( FALSE, i );
00361         mRegisteredPANs++;
00362     }
00363     else
00364     {
00365         i = -1;
00366     }
00367 
00368     return i;
00369 }
00370 
00371 
00372 /*! *********************************************************************************
00373 * \brief  This function configures the MPM module
00374 *
00375 * \param[in]  pCfg pointer to a configuration structure
00376 *
00377 * \remarks
00378 * The Dual PAN dwell time prescaller values: 0-3
00379 * The Dual PAN dwell time values 0-63.
00380 * The (dwellTime+1) represents multiples of the prescaller time base.
00381 *
00382 ********************************************************************************** */
00383 void MPM_SetConfig( mpmConfig_t *pCfg )
00384 {
00385     PhyPpSetDualPanAuto ( FALSE );
00386     PhyPpSetDualPanDwell( pCfg->dwellTime );
00387     MPM_AllocateResource( TRUE, MPM_GetPanIndex(pCfg->activeMAC) );
00388     PhyPpSetDualPanAuto ( pCfg->autoMode );
00389     if( PhyIsIdleRx(0) )
00390     {
00391         PhyPlmeForceTrxOffRequest();
00392         Radio_Phy_TimeRxTimeoutIndication(0);
00393     }
00394 }
00395 
00396 /*! *********************************************************************************
00397 * \brief  This function returns the MPM configuration
00398 *
00399 * \param[in]  pCfg pointer to a configuration structure
00400 *
00401 * \return  None.
00402 *
00403 ********************************************************************************** */
00404 void MPM_GetConfig( mpmConfig_t *pCfg )
00405 {
00406     pCfg->dwellTime  = PhyPpGetDualPanDwell();
00407     pCfg->activeMAC  = MPM_GetMacInstanceFromRegSet( PhyPpGetDualPanActiveNwk() );
00408     pCfg->autoMode   = PhyPpGetDualPanAuto();
00409 }
00410 #endif /* #if gMpmIncluded_d */
00411 
00412 /*! *********************************************************************************
00413 * \brief  This function Acquires a PAN for exclusive access.
00414 *
00415 * \param[in]  macInstance The instance of the MAC
00416 *
00417 * \return  The status of the operation
00418 *
00419 ********************************************************************************** */
00420 phyStatus_t MPM_AcquirePAN( instanceId_t macInstance )
00421 {
00422 #if gMpmIncluded_d
00423     int32_t panIndex = MPM_GetPanIndex(macInstance);
00424 
00425     /* Check if another PAN is acquired */
00426     if( TRUE == mMpmExclusiveAccess &&
00427         mPanInfo[panIndex].locked <= 0 )
00428     {
00429         return gPhyBusy_c;
00430     }
00431 
00432     if( mPanInfo[panIndex].locked == 0 )
00433     {
00434         mMpmExclusiveAccess = TRUE;
00435         if( PhyIsIdleRx(0) )
00436         {
00437             PhyPlmeForceTrxOffRequest();
00438             Radio_Phy_TimeRxTimeoutIndication(0);
00439         }
00440     }
00441 
00442     mPanInfo[panIndex].locked++;
00443 #endif
00444     return gPhySuccess_c;
00445 }
00446 
00447 /*! *********************************************************************************
00448 * \brief  This function Releases a PAN that was Acquired
00449 *
00450 * \param[in]  macInstance The instance of the MAC
00451 *
00452 * \return  The status of the operation
00453 *
00454 ********************************************************************************** */
00455 phyStatus_t MPM_ReleasePAN( instanceId_t macInstance )
00456 {
00457 #if gMpmIncluded_d
00458     uint8_t panIndex = MPM_GetPanIndex(macInstance);
00459 
00460     mPanInfo[panIndex].locked--;
00461     if( mPanInfo[panIndex].locked == 0 )
00462     {
00463         mMpmExclusiveAccess = FALSE;
00464         if( PhyIsIdleRx(0) )
00465         {
00466             PhyPlmeForceTrxOffRequest();
00467             Radio_Phy_TimeRxTimeoutIndication(0);
00468         }
00469     }
00470 #endif
00471     return gPhySuccess_c;
00472 }
00473 
00474 /************************************************************************************
00475 *************************************************************************************
00476 * Private functions
00477 *************************************************************************************
00478 ************************************************************************************/
00479 #if gMpmIncluded_d
00480 /*! *********************************************************************************
00481 * \brief  This function alocates a registry set to a PAN.
00482 *
00483 * \param[in]  force If this parameter is TRUE, then another PAN can be preempted.
00484 * \param[in]  panIdx The index into the MPM database
00485 *
00486 * \return  The register set allocated for the specified PAN.
00487 *
00488 ********************************************************************************** */
00489 static uint8_t MPM_AllocateResource( bool_t force, uint8_t panIdx )
00490 {
00491     uint32_t i, regSet = gMpmInvalidRegSet_c;
00492 
00493     if( mPanInfo[panIdx].phyRegSet != gMpmInvalidRegSet_c )
00494       return mPanInfo[panIdx].phyRegSet;
00495 
00496     for( i=0; i<gMpmPhyPanRegSets_c; i++ )
00497     {
00498         if( NULL == pActivePANs[i] )
00499         {
00500             regSet = i;
00501             break;
00502         }
00503         else if( (force) &&
00504                  (pActivePANs[i]->flags == 0) &&
00505                  (pActivePANs[i]->locked <= 0) )
00506         {
00507             regSet = i;
00508         }
00509     }
00510 
00511     if( regSet != gMpmInvalidRegSet_c )
00512     {
00513         if( NULL != pActivePANs[regSet] )
00514         {
00515             pActivePANs[regSet]->phyRegSet = gMpmInvalidRegSet_c;
00516         }
00517 
00518         pActivePANs[regSet] = &mPanInfo[panIdx];
00519         pActivePANs[regSet]->phyRegSet = regSet;
00520     }
00521 
00522     return regSet;
00523 }
00524 
00525 /*! *********************************************************************************
00526 * \brief  This function will store PAN settings in PHY.
00527 *
00528 * \param[in]  panIdx The index into the MPM database
00529 *
00530 * \return  None.
00531 *
00532 * \remarks Function assumes that the PAN is active!
00533 *
00534 ********************************************************************************** */
00535 static void MPM_SetPanSettingsInPhy( uint8_t panIndex )
00536 {
00537     panInfo_t *pPAN = &mPanInfo[panIndex];
00538 
00539 #if gMpmUseDifferentTxPwrLevel_c
00540     PhyPlmeSetPIBRequest(gPhyPibTransmitPower_c,   pPAN->pwrLevel,            pPAN->phyRegSet, 0 );
00541 #endif
00542 
00543 #if (gMpmMaxPANs_c > gMpmPhyPanRegSets_c)
00544     PhyPlmeSetPIBRequest(gPhyPibPromiscuousMode_c, !!(pPAN->flags & gMpmFlagPromiscuous_c),  pPAN->phyRegSet, 0 );
00545     PhyPlmeSetPIBRequest(gPhyPibRxOnWhenIdle,      !!(pPAN->flags & gMpmFlagRxOnWhenIdle_c), pPAN->phyRegSet, 0 );
00546     PhyPlmeSetPIBRequest(gPhyPibPanCoordinator_c,  !!(pPAN->flags & gMpmFlagPanCoord_c),     pPAN->phyRegSet, 0 );
00547     PhyPlmeSetPIBRequest(gPhyPibPanId_c,           pPAN->panId,     pPAN->phyRegSet, 0 );
00548     PhyPlmeSetPIBRequest(gPhyPibShortAddress_c,    pPAN->shortAddr, pPAN->phyRegSet, 0 );
00549     PhyPlmeSetPIBRequest(gPhyPibLongAddress_c,     pPAN->longAddr,  pPAN->phyRegSet, 0 );
00550     PhyPlmeSetPIBRequest(gPhyPibCurrentChannel_c,  pPAN->channel,   pPAN->phyRegSet, 0 );
00551 #else
00552     (void)pPAN;
00553 #endif
00554 }
00555 #endif /* gMpmIncluded_d */