NXP / fsl_phy_mcr20a

Fork of fsl_phy_mcr20a by Freescale

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers PhyTime.c Source File

PhyTime.c

Go to the documentation of this file.
00001 /*!
00002 * Copyright (c) 2015, Freescale Semiconductor, Inc.
00003 * All rights reserved.
00004 *
00005 * \file PhyTime.c
00006 *
00007 * Redistribution and use in source and binary forms, with or without modification,
00008 * are permitted provided that the following conditions are met:
00009 *
00010 * o Redistributions of source code must retain the above copyright notice, this list
00011 *   of conditions and the following disclaimer.
00012 *
00013 * o Redistributions in binary form must reproduce the above copyright notice, this
00014 *   list of conditions and the following disclaimer in the documentation and/or
00015 *   other materials provided with the distribution.
00016 *
00017 * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
00018 *   contributors may be used to endorse or promote products derived from this
00019 *   software without specific prior written permission.
00020 *
00021 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00022 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00023 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00024 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
00025 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00026 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00028 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00029 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00030 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00031 */
00032 
00033 
00034 /************************************************************************************
00035 *************************************************************************************
00036 * Include
00037 *************************************************************************************
00038 ************************************************************************************/
00039 #include "EmbeddedTypes.h "
00040 //#include "fsl_os_abstraction.h"
00041 #include "MCR20Drv.h "
00042 #include "MCR20Reg.h"
00043 #include "Phy.h "
00044 
00045 #include "FunctionLib.h "
00046 
00047 /************************************************************************************
00048 *************************************************************************************
00049 * Private macros
00050 *************************************************************************************
00051 ************************************************************************************/
00052 #define gPhyTimeMinSetupTime_c (10) /* symbols */
00053 
00054 /************************************************************************************
00055 *************************************************************************************
00056 * Public memory declarations
00057 *************************************************************************************
00058 ************************************************************************************/
00059 void (*gpfPhyTimeNotify)(void) = NULL;
00060 
00061 /************************************************************************************
00062 *************************************************************************************
00063 * Private memory declarations
00064 *************************************************************************************
00065 ************************************************************************************/
00066 static phyTimeEvent_t  mPhyTimers[gMaxPhyTimers_c];
00067 static phyTimeEvent_t *pNextEvent;
00068 volatile uint32_t      mPhySeqTimeout;
00069 volatile uint64_t      gPhyTimerOverflow;
00070 
00071 /************************************************************************************
00072 *************************************************************************************
00073 * Private prototypes
00074 *************************************************************************************
00075 ************************************************************************************/
00076 static void PhyTime_OverflowCB( uint32_t param );
00077 static phyTimeEvent_t* PhyTime_GetNextEvent( void );
00078 
00079 /************************************************************************************
00080 *************************************************************************************
00081 * Public functions
00082 *************************************************************************************
00083 ************************************************************************************/
00084 
00085 /*! *********************************************************************************
00086 * \brief  Sets the start time of a sequence
00087 *
00088 * \param[in]  startTime  the start time for a sequence
00089 *
00090 ********************************************************************************** */
00091 void PhyTimeSetEventTrigger
00092 (
00093   uint32_t startTime
00094 )
00095 {
00096   uint8_t phyReg, phyCtrl3Reg;
00097 
00098   OSA_EnterCritical(kCriticalDisableInt);
00099 
00100   phyReg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL1);
00101   phyReg |= cPHY_CTRL1_TMRTRIGEN;    // enable autosequence start by TC2 match
00102   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL1, phyReg);
00103 
00104   phyCtrl3Reg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL3);
00105   phyCtrl3Reg &= ~(cPHY_CTRL3_TMR2CMP_EN);// disable TMR2 compare
00106   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL3, phyCtrl3Reg);
00107 
00108   MCR20Drv_DirectAccessSPIMultiByteWrite( (uint8_t) T2PRIMECMP_LSB, (uint8_t *) &startTime, 2);
00109 
00110   phyReg = MCR20Drv_DirectAccessSPIRead(IRQSTS3);
00111   phyReg &= 0xF0;                     // do not change other IRQs status
00112   phyReg &= ~(cIRQSTS3_TMR2MSK);      // unmask TMR2 interrupt
00113   phyReg |= (cIRQSTS3_TMR2IRQ);       // aknowledge TMR2 IRQ
00114   MCR20Drv_DirectAccessSPIWrite( (uint8_t) IRQSTS3, phyReg);
00115 
00116   // TC2PRIME_EN must be enabled in PHY_CTRL4 register
00117   phyCtrl3Reg |= cPHY_CTRL3_TMR2CMP_EN;   // enable TMR2 compare
00118   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL3, phyCtrl3Reg);
00119 
00120   OSA_ExitCritical(kCriticalDisableInt);
00121 }
00122 
00123 /*! *********************************************************************************
00124 * \brief  Disable the time trigger for a sequence.
00125 *
00126 * \remarks The sequence will start asap
00127 *
00128 ********************************************************************************** */
00129 void PhyTimeDisableEventTrigger
00130 (
00131   void
00132 )
00133 {
00134   uint8_t phyReg;
00135 
00136   OSA_EnterCritical(kCriticalDisableInt);
00137 
00138   phyReg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL1);
00139   phyReg &= ~(cPHY_CTRL1_TMRTRIGEN); // disable autosequence start by TC2 match
00140   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL1, phyReg);
00141 
00142   phyReg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL3);
00143   phyReg &= ~(cPHY_CTRL3_TMR2CMP_EN);// disable TMR2 compare
00144   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL3, phyReg);
00145 
00146   phyReg = MCR20Drv_DirectAccessSPIRead(IRQSTS3);
00147   phyReg &= 0xF0;                    // do not change other IRQs status
00148   phyReg |= (cIRQSTS3_TMR2MSK);      // mask TMR2 interrupt
00149   phyReg |= (cIRQSTS3_TMR2IRQ);      // aknowledge TMR2 IRQ
00150   MCR20Drv_DirectAccessSPIWrite( (uint8_t) IRQSTS3, phyReg);
00151 
00152   OSA_ExitCritical(kCriticalDisableInt);
00153 }
00154 
00155 /*! *********************************************************************************
00156 * \brief  Sets the timeout value for a sequence
00157 *
00158 * \param[in]  pEndTime the absolute time when a sequence should terminate
00159 *
00160 * \remarks If the sequence does not finish until the timeout, it will be aborted
00161 *
00162 ********************************************************************************** */
00163 void PhyTimeSetEventTimeout
00164 (
00165   uint32_t *pEndTime
00166 )
00167 {
00168   uint8_t phyReg, phyCtrl3Reg;
00169 
00170 #ifdef PHY_PARAMETERS_VALIDATION
00171   if(NULL == pEndTime)
00172   {
00173     return;
00174   }
00175 #endif // PHY_PARAMETERS_VALIDATION
00176 
00177   OSA_EnterCritical(kCriticalDisableInt);
00178 
00179   phyCtrl3Reg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL3);
00180   phyCtrl3Reg &= ~(cPHY_CTRL3_TMR3CMP_EN);// disable TMR3 compare
00181   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL3, phyCtrl3Reg);
00182 
00183   phyReg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL4);
00184   phyReg |= cPHY_CTRL4_TC3TMOUT;     // enable autosequence stop by TC3 match
00185   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL4, phyReg);
00186 
00187   mPhySeqTimeout = *pEndTime & 0x00FFFFFF;
00188   MCR20Drv_DirectAccessSPIMultiByteWrite( (uint8_t) T3CMP_LSB, (uint8_t *) pEndTime, 3);
00189 
00190   phyReg = MCR20Drv_DirectAccessSPIRead(IRQSTS3);
00191   phyReg &= 0xF0;                     // do not change IRQ status
00192 //  phyReg &= ~(cIRQSTS3_TMR3MSK);      // unmask TMR3 interrupt
00193   phyReg |= (cIRQSTS3_TMR3IRQ);       // aknowledge TMR3 IRQ
00194   MCR20Drv_DirectAccessSPIWrite( (uint8_t) IRQSTS3, phyReg);
00195 
00196   phyCtrl3Reg |= cPHY_CTRL3_TMR3CMP_EN;   // enable TMR3 compare
00197   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL3, phyCtrl3Reg);
00198 
00199   OSA_ExitCritical(kCriticalDisableInt);
00200 }
00201 
00202 /*! *********************************************************************************
00203 * \brief  Return the timeout value for the current sequence
00204 *
00205 * \return  uint32_t the timeout value
00206 *
00207 ********************************************************************************** */
00208 uint32_t PhyTimeGetEventTimeout( void )
00209 {
00210     return mPhySeqTimeout;
00211 }
00212 
00213 /*! *********************************************************************************
00214 * \brief  Disables the sequence timeout
00215 *
00216 ********************************************************************************** */
00217 void PhyTimeDisableEventTimeout
00218 (
00219   void
00220 )
00221 {
00222   uint8_t phyReg;
00223 
00224   OSA_EnterCritical(kCriticalDisableInt);
00225 
00226   phyReg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL4);
00227   phyReg &= ~(cPHY_CTRL4_TC3TMOUT);  // disable autosequence stop by TC3 match
00228   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL4, phyReg);
00229 
00230   phyReg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL3);
00231   phyReg &= ~(cPHY_CTRL3_TMR3CMP_EN);// disable TMR3 compare
00232   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL3, phyReg);
00233 
00234   phyReg = MCR20Drv_DirectAccessSPIRead(IRQSTS3);
00235   phyReg &= 0xF0;                     // do not change IRQ status
00236   phyReg |= cIRQSTS3_TMR3IRQ;         // aknowledge TMR3 IRQ
00237   MCR20Drv_DirectAccessSPIWrite( (uint8_t) IRQSTS3, phyReg);
00238 
00239   OSA_ExitCritical(kCriticalDisableInt);
00240 }
00241 
00242 /*! *********************************************************************************
00243 * \brief  Reads the absolute clock from the radio
00244 *
00245 * \param[out]  pRetClk pointer to a location where the current clock will be stored
00246 *
00247 ********************************************************************************** */
00248 void PhyTimeReadClock
00249 (
00250   uint32_t *pRetClk
00251 )
00252 {
00253 #ifdef PHY_PARAMETERS_VALIDATION
00254   if(NULL == pRetClk)
00255   {
00256     return;
00257   }
00258 #endif // PHY_PARAMETERS_VALIDATION
00259 
00260   OSA_EnterCritical(kCriticalDisableInt);
00261 
00262   MCR20Drv_DirectAccessSPIMultiByteRead( (uint8_t) EVENT_TMR_LSB, (uint8_t *) pRetClk, 3);
00263   *(((uint8_t *)pRetClk) + 3) = 0;
00264 
00265   OSA_ExitCritical(kCriticalDisableInt);
00266 
00267 }
00268 
00269 /*! *********************************************************************************
00270 * \brief  Initialize the Event Timer
00271 *
00272 * \param[in]  pAbsTime  pointer to the location where the new time is stored
00273 *
00274 ********************************************************************************** */
00275 void PhyTimeInitEventTimer
00276 (
00277   uint32_t *pAbsTime
00278 )
00279 {
00280   uint8_t phyCtrl4Reg;
00281 
00282 #ifdef PHY_PARAMETERS_VALIDATION
00283   if(NULL == pAbsTime)
00284   {
00285     return;
00286   }
00287 #endif // PHY_PARAMETERS_VALIDATION
00288 
00289   OSA_EnterCritical(kCriticalDisableInt);
00290 
00291   phyCtrl4Reg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL4);
00292   phyCtrl4Reg |= cPHY_CTRL4_TMRLOAD; // self clearing bit
00293 
00294   MCR20Drv_DirectAccessSPIMultiByteWrite( (uint8_t) T1CMP_LSB, (uint8_t *) pAbsTime, 3);
00295   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL4, phyCtrl4Reg);
00296 
00297   OSA_ExitCritical(kCriticalDisableInt);
00298 }
00299 
00300 /*! *********************************************************************************
00301 * \brief  Set TMR1 timeout value
00302 *
00303 * \param[in]  pWaitTimeout the timeout value
00304 *
00305 ********************************************************************************** */
00306 void PhyTimeSetWaitTimeout
00307 (
00308   uint32_t *pWaitTimeout
00309 )
00310 {
00311   uint8_t phyCtrl3Reg, irqSts3Reg;
00312 
00313   OSA_EnterCritical(kCriticalDisableInt);
00314 
00315   phyCtrl3Reg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL3);
00316   phyCtrl3Reg &= ~(cPHY_CTRL3_TMR1CMP_EN);// disable TMR1 compare
00317   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL3, phyCtrl3Reg);
00318 
00319   MCR20Drv_DirectAccessSPIMultiByteWrite( (uint8_t) T1CMP_LSB, (uint8_t *) pWaitTimeout, 3);
00320 
00321   irqSts3Reg = MCR20Drv_DirectAccessSPIRead(IRQSTS3);
00322   irqSts3Reg &= ~(cIRQSTS3_TMR1MSK);      // unmask TMR1 interrupt
00323   irqSts3Reg &= 0xF0;                     // do not change other IRQs status
00324   irqSts3Reg |= (cIRQSTS3_TMR1IRQ);       // aknowledge TMR1 IRQ
00325   MCR20Drv_DirectAccessSPIWrite( (uint8_t) IRQSTS3, irqSts3Reg);
00326 
00327   phyCtrl3Reg |= cPHY_CTRL3_TMR1CMP_EN;   // enable TMR1 compare
00328   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL3, phyCtrl3Reg);
00329 
00330   OSA_ExitCritical(kCriticalDisableInt);
00331 
00332 }
00333 
00334 /*! *********************************************************************************
00335 * \brief  Disable the TMR1 timeout
00336 *
00337 ********************************************************************************** */
00338 void PhyTimeDisableWaitTimeout
00339 (
00340   void
00341 )
00342 {
00343   uint8_t phyReg;
00344 
00345   OSA_EnterCritical(kCriticalDisableInt);
00346 
00347   phyReg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL3);
00348   phyReg &= ~(cPHY_CTRL3_TMR1CMP_EN);// disable TMR1 compare
00349   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL3, phyReg);
00350 
00351   phyReg = MCR20Drv_DirectAccessSPIRead(IRQSTS3);
00352   phyReg &= 0xF0;                     // do not change IRQ status
00353   phyReg |= cIRQSTS3_TMR1IRQ;         // aknowledge TMR1 IRQ
00354   MCR20Drv_DirectAccessSPIWrite( (uint8_t) IRQSTS3, phyReg);
00355 
00356   OSA_ExitCritical(kCriticalDisableInt);
00357 }
00358 
00359 /*! *********************************************************************************
00360 * \brief  Set TMR4 timeout value
00361 *
00362 * \param[in]  pWakeUpTime  absolute time
00363 *
00364 ********************************************************************************** */
00365 void PhyTimeSetWakeUpTime
00366 (
00367   uint32_t *pWakeUpTime
00368 )
00369 {
00370   uint8_t phyCtrl3Reg, irqSts3Reg;
00371 
00372   OSA_EnterCritical(kCriticalDisableInt);
00373 
00374   phyCtrl3Reg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL3);
00375 //  phyCtrl3Reg &= ~(cPHY_CTRL3_TMR4CMP_EN);// disable TMR4 compare
00376 //  MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL3, phyCtrl3Reg);
00377 
00378   MCR20Drv_DirectAccessSPIMultiByteWrite( (uint8_t) T4CMP_LSB, (uint8_t *) pWakeUpTime, 3);
00379 
00380   irqSts3Reg = MCR20Drv_DirectAccessSPIRead(IRQSTS3);
00381   irqSts3Reg &= ~(cIRQSTS3_TMR4MSK);      // unmask TMR4 interrupt
00382   irqSts3Reg &= 0xF0;                     // do not change other IRQs status
00383   irqSts3Reg |= (cIRQSTS3_TMR4IRQ);       // aknowledge TMR4 IRQ
00384   MCR20Drv_DirectAccessSPIWrite( (uint8_t) IRQSTS3, irqSts3Reg);
00385 
00386   phyCtrl3Reg |= cPHY_CTRL3_TMR4CMP_EN;   // enable TMR4 compare
00387   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL3, phyCtrl3Reg);
00388 
00389   OSA_ExitCritical(kCriticalDisableInt);
00390 }
00391 
00392 /*! *********************************************************************************
00393 * \brief  Check if TMR4 IRQ occured, and aknowledge it
00394 *
00395 * \return  TRUE if TMR4 IRQ occured
00396 *
00397 ********************************************************************************** */
00398 bool_t PhyTimeIsWakeUpTimeExpired
00399 (
00400   void
00401 )
00402 {
00403   bool_t wakeUpIrq = FALSE;
00404   uint8_t phyReg;
00405 
00406   OSA_EnterCritical(kCriticalDisableInt);
00407 
00408   phyReg = MCR20Drv_DirectAccessSPIRead(PHY_CTRL3);
00409   phyReg &= ~(cPHY_CTRL3_TMR4CMP_EN);// disable TMR4 compare
00410   MCR20Drv_DirectAccessSPIWrite( (uint8_t) PHY_CTRL3, phyReg);
00411 
00412   phyReg = MCR20Drv_DirectAccessSPIRead(IRQSTS3);
00413 
00414   if( (phyReg & cIRQSTS3_TMR4IRQ) == cIRQSTS3_TMR4IRQ )
00415   {
00416     wakeUpIrq = TRUE;
00417   }
00418 
00419   phyReg &= ~(cIRQSTS3_TMR4MSK);      // unmask TMR4 interrupt
00420   phyReg &= 0xF0;                     // do not change other IRQs status
00421   phyReg |= (cIRQSTS3_TMR4IRQ);       // aknowledge TMR2 IRQ
00422 
00423   MCR20Drv_DirectAccessSPIWrite( (uint8_t) IRQSTS3, phyReg);
00424 
00425   OSA_ExitCritical(kCriticalDisableInt);
00426 
00427   return wakeUpIrq;
00428 }
00429 
00430 
00431 /*! *********************************************************************************
00432 * \brief  PHY Timer Interrupt Service Routine
00433 *
00434 ********************************************************************************** */
00435 void PhyTime_ISR(void)
00436 {
00437     if( pNextEvent->callback == PhyTime_OverflowCB )
00438     {
00439         gPhyTimerOverflow++;
00440     }
00441     
00442     if( gpfPhyTimeNotify )
00443     {
00444         gpfPhyTimeNotify();
00445     }
00446     else
00447     {
00448         PhyTime_RunCallback();
00449         PhyTime_Maintenance();
00450     }
00451 }
00452 
00453 /*! *********************************************************************************
00454 * \brief  Initialize the PHY Timer module
00455 *
00456 * \return  phyTimeStatus_t
00457 *
00458 ********************************************************************************** */
00459 phyTimeStatus_t PhyTime_TimerInit( void (*cb)(void) )
00460 {
00461     if( gpfPhyTimeNotify )
00462         return gPhyTimeError_c;
00463 
00464     gpfPhyTimeNotify = cb;
00465     gPhyTimerOverflow = 0;
00466     FLib_MemSet( mPhyTimers, 0, sizeof(mPhyTimers) );
00467 
00468     /* Schedule Overflow Calback */
00469     pNextEvent = &mPhyTimers[0];
00470     pNextEvent->callback = PhyTime_OverflowCB;
00471     pNextEvent->timestamp = (gPhyTimerOverflow+1) << gPhyTimeShift_c;
00472     PhyTimeSetWaitTimeout( (uint32_t*)&pNextEvent->timestamp );
00473 
00474     return gPhyTimeOk_c;
00475 }
00476 
00477 /*! *********************************************************************************
00478 * \brief  Returns a 64bit timestamp value to be used by the MAC Layer
00479 *
00480 * \return  phyTimeTimestamp_t PHY timestamp
00481 *
00482 ********************************************************************************** */
00483 phyTimeTimestamp_t PhyTime_GetTimestamp(void)
00484 {
00485     phyTimeTimestamp_t time = 0;
00486 
00487     OSA_EnterCritical(kCriticalDisableInt);
00488     PhyTimeReadClock( (uint32_t*)&time );
00489     time |= (gPhyTimerOverflow << gPhyTimeShift_c);
00490     OSA_ExitCritical(kCriticalDisableInt);
00491 
00492     return time;
00493 }
00494 
00495 /*! *********************************************************************************
00496 * \brief  Schedules an event
00497 *
00498 * \param[in]  pEvent  event to be scheduled
00499 *
00500 * \return  phyTimeTimerId_t  the id of the alocated timer
00501 *
00502 ********************************************************************************** */
00503 phyTimeTimerId_t PhyTime_ScheduleEvent( phyTimeEvent_t *pEvent )
00504 {
00505     phyTimeTimerId_t tmr;
00506 
00507     /* Parameter validation */
00508     if( NULL == pEvent->callback )
00509     {
00510         return gInvalidTimerId_c;
00511     }
00512 
00513     /* Search for a free slot (slot 0 is reserved for the Overflow calback) */
00514     OSA_EnterCritical(kCriticalDisableInt);
00515     for( tmr=1; tmr<gMaxPhyTimers_c; tmr++ )
00516     {
00517         if( mPhyTimers[tmr].callback == NULL )
00518         {
00519             mPhyTimers[tmr] = *pEvent;
00520             break;
00521         }
00522     }
00523     OSA_ExitCritical(kCriticalDisableInt);
00524 
00525     if( tmr >= gMaxPhyTimers_c )
00526         return gInvalidTimerId_c;
00527 
00528     /* Program the next event */
00529     if((NULL == pNextEvent) ||
00530        (NULL != pNextEvent  && mPhyTimers[tmr].timestamp < pNextEvent->timestamp))
00531     {
00532         PhyTime_Maintenance();
00533     }
00534 
00535     return tmr;
00536 }
00537 
00538 /*! *********************************************************************************
00539 * \brief  Cancel an event
00540 *
00541 * \param[in]  timerId  the Id of the timer
00542 *
00543 * \return  phyTimeStatus_t
00544 *
00545 ********************************************************************************** */
00546 phyTimeStatus_t PhyTime_CancelEvent( phyTimeTimerId_t timerId )
00547 {
00548     if( (timerId == 0) || (timerId >= gMaxPhyTimers_c) || (NULL == mPhyTimers[timerId].callback) )
00549     {
00550         return gPhyTimeNotFound_c;
00551     }
00552 
00553     OSA_EnterCritical(kCriticalDisableInt);
00554     if( pNextEvent == &mPhyTimers[timerId] )
00555         pNextEvent = NULL;
00556 
00557     mPhyTimers[timerId].callback = NULL;
00558     OSA_ExitCritical(kCriticalDisableInt);
00559 
00560     return gPhyTimeOk_c;
00561 }
00562 
00563 /*! *********************************************************************************
00564 * \brief  Cancel all event with the specified paameter
00565 *
00566 * \param[in]  param  event parameter
00567 *
00568 * \return  phyTimeStatus_t
00569 *
00570 ********************************************************************************** */
00571 phyTimeStatus_t PhyTime_CancelEventsWithParam ( uint32_t param )
00572 {
00573     uint32_t i;
00574     phyTimeStatus_t status = gPhyTimeNotFound_c;
00575 
00576     OSA_EnterCritical(kCriticalDisableInt);
00577     for( i=1; i<gMaxPhyTimers_c; i++ )
00578     {
00579         if( mPhyTimers[i].callback && (param == mPhyTimers[i].parameter) )
00580         {
00581             status = gPhyTimeOk_c;
00582             mPhyTimers[i].callback = NULL;
00583             if( pNextEvent == &mPhyTimers[i] )
00584                 pNextEvent = NULL;
00585         }
00586     }
00587     OSA_ExitCritical(kCriticalDisableInt);
00588 
00589     return status;
00590 }
00591 
00592 /*! *********************************************************************************
00593 * \brief  Run the callback for the recently expired event
00594 *
00595 ********************************************************************************** */
00596 void PhyTime_RunCallback( void )
00597 {
00598     uint32_t param;
00599     phyTimeCallback_t cb;
00600 
00601     if( pNextEvent )
00602     {
00603         OSA_EnterCritical(kCriticalDisableInt);
00604 
00605         param = pNextEvent->parameter;
00606         cb = pNextEvent->callback;
00607         pNextEvent->callback = NULL;
00608         pNextEvent = NULL;
00609 
00610         OSA_ExitCritical(kCriticalDisableInt);
00611 
00612         cb(param);
00613     }
00614 }
00615 
00616 /*! *********************************************************************************
00617 * \brief  Expire events too close to be scheduled.
00618 *         Program the next event
00619 *
00620 ********************************************************************************** */
00621 void PhyTime_Maintenance( void )
00622 {
00623     phyTimeTimestamp_t currentTime;
00624     phyTimeEvent_t *pEv;
00625 
00626     PhyTimeDisableWaitTimeout();
00627 
00628     while(1)
00629     {
00630         OSA_EnterCritical(kCriticalDisableInt);
00631         
00632         pEv = PhyTime_GetNextEvent();
00633         currentTime = PhyTime_GetTimestamp();
00634         
00635         /* Program next event if exists */
00636         if( pEv )
00637         {
00638             pNextEvent = pEv;
00639             
00640             if( pEv->timestamp > (currentTime + gPhyTimeMinSetupTime_c) )
00641             {
00642                 PhyTimeSetWaitTimeout( (uint32_t*)&pEv->timestamp );
00643                 pEv = NULL;
00644             }
00645         }
00646 
00647         OSA_ExitCritical(kCriticalDisableInt);
00648 
00649         if( !pEv )
00650             break;
00651 
00652         PhyTime_RunCallback();
00653     }
00654     
00655 }
00656 
00657 
00658 /*! *********************************************************************************
00659 * \brief  Timer Overflow callback
00660 *
00661 * \param[in]  param
00662 *
00663 ********************************************************************************** */
00664 static void PhyTime_OverflowCB( uint32_t param )
00665 {
00666     (void)param;
00667 
00668     /* Reprogram the next overflow callback */
00669     mPhyTimers[0].callback = PhyTime_OverflowCB;
00670     mPhyTimers[0].timestamp = (gPhyTimerOverflow+1) << 24;
00671 }
00672 
00673 /*! *********************************************************************************
00674 * \brief  Search for the next event to be scheduled
00675 *
00676 * \return phyTimeEvent_t pointer to the next event to be scheduled
00677 *
00678 ********************************************************************************** */
00679 static phyTimeEvent_t* PhyTime_GetNextEvent( void )
00680 {
00681     phyTimeEvent_t *pEv = NULL;
00682     uint32_t i;
00683 
00684     /* Search for the next event to be serviced */
00685     for( i=0; i<gMaxPhyTimers_c; i++ )
00686     {
00687         if( NULL != mPhyTimers[i].callback )
00688         {
00689             if( NULL == pEv )
00690             {
00691                 pEv = &mPhyTimers[i];
00692             }
00693             /* Check which event expires first */
00694             else if( mPhyTimers[i].timestamp < pEv->timestamp )
00695             {
00696                 pEv = &mPhyTimers[i];
00697             }
00698         }
00699     }
00700 
00701     return pEv;
00702 }