예제 #1
0
/**************************************************************************************************
 * @fn          macBackoffTimerCompareIsr
 *
 * @brief       Interrupt service routine that fires when the backoff count is equal
 *              to the trigger count.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
void macBackoffTimerCompareIsr(void)
{
  uint8 oldState;
  halIntState_t  s;

  HAL_ENTER_CRITICAL_SECTION(s);
  oldState = compareState;

  /* if compare is a rollover, set count to zero */
  if (oldState & COMPARE_STATE_ROLLOVER_BV)
  {
    MAC_RADIO_BACKOFF_SET_COUNT(0);
    macBackoffTimerRolloverCallback();
  }

  /* if compare is a trigger, reset for rollover and run the trigger callback */
  if (oldState & COMPARE_STATE_TRIGGER_BV)
  {
    compareState = COMPARE_STATE_ROLLOVER;
    MAC_RADIO_BACKOFF_SET_COMPARE(backoffTimerRollover);
    HAL_EXIT_CRITICAL_SECTION(s);
    macBackoffTimerTriggerCallback();
  }
  else if (oldState == COMPARE_STATE_ROLLOVER_AND_ARM_TRIGGER)
  {
    compareState = COMPARE_STATE_TRIGGER;
    MAC_RADIO_BACKOFF_SET_COMPARE(backoffTimerTrigger);
    HAL_EXIT_CRITICAL_SECTION(s);
  }
  else
  {
    HAL_EXIT_CRITICAL_SECTION(s);
  }
}
예제 #2
0
/**************************************************************************************************
 * @fn          macBackoffTimerSetTrigger
 *
 * @brief       Sets the trigger count for the backoff counter.  A callback is exectuted when
 *              the backoff count reaches the trigger
 *
 * @param       triggerBackoff - backoff count for new trigger
 *
 * @return      none
 **************************************************************************************************
 */
void macBackoffTimerSetTrigger(uint32 triggerBackoff)
{
  halIntState_t  s;

  MAC_ASSERT(triggerBackoff < backoffTimerRollover); /* trigger backoff must be less than rollover backoff */

  HAL_ENTER_CRITICAL_SECTION(s);
  backoffTimerTrigger = triggerBackoff;
  if (triggerBackoff > MAC_RADIO_BACKOFF_COUNT())
  {
    compareState = COMPARE_STATE_TRIGGER;
    MAC_RADIO_BACKOFF_SET_COMPARE(triggerBackoff);
  }
  else
  {
    if (triggerBackoff == 0)
    {
      compareState = COMPARE_STATE_ROLLOVER_AND_TRIGGER;
    }
    else
    {
      compareState = COMPARE_STATE_ROLLOVER_AND_ARM_TRIGGER;
    }
    MAC_RADIO_BACKOFF_SET_COMPARE(backoffTimerRollover);
  }
  HAL_EXIT_CRITICAL_SECTION(s);
}
/**************************************************************************************************
 * @fn          macBackoffTimerCancelTrigger
 *
 * @brief       Cancels the trigger for the backoff counter - obselete for CC253x and CC26xx.
 *              For CC253x and CC26xx, the timer trigger should never be late, therefore, no
 *              need to cancel.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
MAC_INTERNAL_API void macBackoffTimerCancelTrigger(void)
{
  MAC_RADIO_BACKOFF_COMPARE_CLEAR_INTERRUPT();

#if defined USE_ICALL || defined OSAL_PORT2TIRTOS
  /* backoffTimerTrigger must be set to a value
   * to properly use rollover value for the next wakeup time.
   */
  {
    halIntState_t intState;
    HAL_ENTER_CRITICAL_SECTION(intState);
    /* This code assumes that backoff timer callback does not cause
     * a problem when the callback is made at the rollover even if
     * no timer is associated with it. At the time the following
     * code is written, mac_timer.c can live with such a callback.
     * Setting backoff comparator value one greater than rollver value
     * might be conceived here to lift the above constraint,
     * but it would have to ensure that rollover value is never
     * the highest counter value, which is a more dangerous assumption.
     */
    backoffTimerTrigger = macBackoffTimerRollover;

    /* Note that MAC_RADIO_BACKOFF_COMPARE_CLEAR_INTERRUPT() is not implemented
     * correctly and hence backoff timer trigger interrupt can still occur.
     * Instead of fixing MAC_RADIO_BACKOFF_COMPARE_CLEAR_INTERRUPT() macro,
     * comparator is set again, to simplify interrupt handling.
     */
    MAC_RADIO_BACKOFF_SET_COMPARE(backoffTimerTrigger);

    MAC_BACKOFF_TIMER_UPDATE_WAKEUP();
    HAL_EXIT_CRITICAL_SECTION(intState);
  }
#endif /* defined USE_ICALL || defined OSAL_PORT2TIRTOS */

}
예제 #4
0
/**************************************************************************************************
 * @fn          macBackoffTimerCancelTrigger
 *
 * @brief       Cancels the trigger for the backoff counter.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
void macBackoffTimerCancelTrigger(void)
{
  halIntState_t  s;

  HAL_ENTER_CRITICAL_SECTION(s);
  compareState = COMPARE_STATE_ROLLOVER;
  MAC_RADIO_BACKOFF_SET_COMPARE(backoffTimerRollover);
  HAL_EXIT_CRITICAL_SECTION(s);
}
예제 #5
0
/**************************************************************************************************
 * @fn          macBackoffTimerSetRollover
 *
 * @brief       Set rollover count of backoff timer.
 *
 * @param       rolloverBackoff - backoff count where count is reset to zero
 *
 * @return      none
 **************************************************************************************************
 */
void macBackoffTimerSetRollover(uint32 rolloverBackoff)
{
  halIntState_t  s;

  MAC_ASSERT(rolloverBackoff > MAC_RADIO_BACKOFF_COUNT());  /* rollover value must be greater than count */

  HAL_ENTER_CRITICAL_SECTION(s);
  backoffTimerRollover = rolloverBackoff;
  MAC_RADIO_BACKOFF_SET_COMPARE(rolloverBackoff);
  HAL_EXIT_CRITICAL_SECTION(s);
}
/**************************************************************************************************
 * @fn          macBackoffTimerSetTrigger
 *
 * @brief       Sets the trigger count for the backoff counter.  A callback is exectuted when
 *              the backoff count reaches the trigger
 *
 * @param       triggerBackoff - backoff count for new trigger
 *
 * @return      none
 **************************************************************************************************
 */
MAC_INTERNAL_API void macBackoffTimerSetTrigger(uint32 triggerBackoff)
{
  halIntState_t  s;

  MAC_ASSERT(triggerBackoff < macBackoffTimerRollover); /* trigger backoff must be less than rollover backoff */
  DBG_PRINT1(DBGSYS, "MAC_RADIO_BACKOFF_SET_COMPARE(%u)", triggerBackoff);
  
  HAL_ENTER_CRITICAL_SECTION(s);
  backoffTimerTrigger = triggerBackoff;
  MAC_RADIO_BACKOFF_SET_COMPARE(triggerBackoff);
  MAC_BACKOFF_TIMER_UPDATE_WAKEUP();
  HAL_EXIT_CRITICAL_SECTION(s);
}
예제 #7
0
/**************************************************************************************************
 * @fn          macBackoffTimerSetTrigger
 *
 * @brief       Sets the trigger count for the backoff counter.  A callback is exectuted when
 *              the backoff count reaches the trigger
 *
 * @param       triggerBackoff - backoff count for new trigger
 *
 * @return      none
 **************************************************************************************************
 */
MAC_INTERNAL_API void macBackoffTimerSetTrigger(uint32 triggerBackoff)
{
  halIntState_t  s;

  MAC_ASSERT(triggerBackoff < backoffTimerRollover); /* trigger backoff must be less than rollover backoff */

  HAL_ENTER_CRITICAL_SECTION(s);
  backoffTimerTrigger = triggerBackoff;
  MAC_RADIO_BACKOFF_SET_COMPARE(triggerBackoff);
  if (triggerBackoff == MAC_RADIO_BACKOFF_COUNT())
  {
    /* Clear the interrupt and fire it manually */
    MAC_RADIO_BACKOFF_COMPARE_CLEAR_INTERRUPT();
    HAL_EXIT_CRITICAL_SECTION(s);
    macBackoffTimerTriggerCallback();
  }
  else
  {
    HAL_EXIT_CRITICAL_SECTION(s);
  }
}
/**************************************************************************************************
 * @fn          macBackoffTimerInit
 *
 * @brief       Intializes backoff timer.
 *
 * @param       none
 *
 * @return      none
 **************************************************************************************************
 */
MAC_INTERNAL_API void macBackoffTimerInit(void)
{
  macPrevPeriodRatCount = macBackoffTimerRollover = 0;

  /* backoffTimerTrigger has to be set to maximum possible value of
   * macBackoffTimerRollover value initially.
   * Otherwise, incorrect backoffTimerTrigger value shall be compared
   * all the time in macBackoffTimerUpdateWakeup() function, casting
   * incorrect vote.
   */
  backoffTimerTrigger = MAC_BACKOFF_TIMER_DEFAULT_NONBEACON_ROLLOVER;

  MAC_RADIO_CLEAR_BACKOFF_COUNT();
#if defined USE_ICALL || defined OSAL_PORT2TIRTOS
  // Clear events
  macBackoffTimerEvents = 0;

#ifdef USE_ICALL
  // Register hook function to handle events.
  if (!osal_eventloop_hook)
  {
    /* Don't overwrite if the hook is already set up.
     * Note that the hook might have been set up to perform other things
     * as well in which case the other hook function has to call
     * macBackoffTimerEventHandler.
     */
    osal_eventloop_hook = macBackoffTimerEventHandler;
  }
#endif /* USE_ICALL */

  macBackoffTimerImpending = FALSE;

#ifdef USE_ICALL
  /* Start timer just to initialize the timer ID to reuse in the module.
   * This also serves the purpose of allocating resources upfront,
   * in order to prevent a case of running out of timer resource
   * when the timer has to be started.
   * Note that macBackoffTimerSetRollover() may trigger setting timer
   * and hence the timer set up must happen before macBackoffTimerSetRollover()
   * call. */
  if (ICall_setTimer(1, macBackoffTimerICallTimerCback, NULL,
                     &macBackoffTimerICallTimerID) != ICALL_ERRNO_SUCCESS)
  {
    MAC_ASSERT(0);
  }
#endif /* USE_ICALL */
#ifdef OSAL_PORT2TIRTOS
  if (!macBackoffWakeupClock)
  {
    /* Creates a wakeup clock */
    Clock_Params params;
    Clock_Params_init(&params);
    params.startFlag = FALSE;
    params.period = 0;
    macBackoffWakeupClock =
      Clock_create((Clock_FuncPtr) macBackoffTimerICallTimerCback,
                   1, &params, NULL);
    MAC_ASSERT(macBackoffWakeupClock);
    /* No need to stop clock, the clock event will reprogram next wake time */
  }
#endif /* OSAL_PORT2TIRTOS */

  /* Note that macPwrVote() is called done from macBackoffTimerSetRollover()
   * call and hence there is no need to make the call here. */
#endif /* defined USE_ICALL || defined OSAL_PORT2TIRTOS */

  macBackoffTimerSetRollover(MAC_BACKOFF_TIMER_DEFAULT_NONBEACON_ROLLOVER);

  /* Since interrupt disable/enable mechanism is not implemented for backoff
   * timer trigger interrupt for CC26xx, comparator value has to be set
   * so that the timer trigger interrupt is not triggered.
   * See comment inside macBackoffTimerCancelTrigger() for relevant
   * information */
  MAC_RADIO_BACKOFF_SET_COMPARE(backoffTimerTrigger);
}
static
#endif /* USE_ICALL */
void macBackoffTimerEventHandler(void)
{
  halIntState_t is;
  uint8 events;
  HAL_ENTER_CRITICAL_SECTION(is);
  events = macBackoffTimerEvents;
  macBackoffTimerEvents = 0;
  HAL_EXIT_CRITICAL_SECTION(is);

  if (events & MAC_BACKOFF_TIMER_EVENT_POWER_WAKEUP)
  {
    // Wakeup radio
    // Turning on radio domain before clock set up seems to cause
    // unexpected interrupt.
    // Hence interrupt shall be disabled here.
    MB_DisableInts();

    // Enable clocks for all radio internal modules.
    // Use Non-Buff access for safety and check for sanity
    HWREG(RFC_PWR_NONBUF_BASE + RFC_PWR_O_PWMCLKEN) = 0x7FF;

    /* Setup mailbox */
    macSetupMailbox();

#ifdef DEBUG_SW_TRACE
    /* re-enable RF trace output for FPGA */
    MB_SendCommand( BUILD_DIRECT_PARAM_EXT_CMD( CMD_ENABLE_DEBUG, 0x1D40 ) ); /* or 0x1940 for less trace */
    DBG_PRINT0(DBGSYS, "RF Trace Resumes...");
#endif /* DEBUG_SW_TRACE */

    /* Start off CM0. Patch it. */
    macSetupRfHal();

    /* Restore states */
    MAC_RADIO_SET_CHANNEL(macPhyChannel);
    MAC_RADIO_SET_PAN_COORDINATOR(macPanCoordinator);
    MAC_RADIO_SET_PAN_ID(pMacPib->panId);
    MAC_RADIO_SET_SHORT_ADDR(pMacPib->shortAddress);
    MAC_RADIO_SET_IEEE_ADDR(pMacPib->extendedAddress.addr.extAddr);

#if !defined( USE_FPGA )
#ifdef USE_ICALL
    // Switch back to HFOSC.
    while (!ICall_pwrIsStableXOSCHF());
    ICall_pwrSwitchXOSCHF();
#endif /* USE_ICALL */
#ifdef OSAL_PORT2TIRTOS
    // Switches back to HFOSC.
    while (!Power_isStableXOSC_HF());
    Power_switchXOSC_HF();
#endif /* OSAL_PORT2TIRTOS */
#endif /* !defined( USE_FPGA ) */

    /* Synchronize RAT timer */
    macSyncStartRAT(macRATValue);

    /* Turn on autoack */
    MAC_RADIO_TURN_ON_AUTO_ACK();

    /* Initialize SRCEXTPENDEN and SRCSHORTPENDEN to zeros */
    MAC_RADIO_SRC_MATCH_INIT_EXTPENDEN();
    MAC_RADIO_SRC_MATCH_INIT_SHORTPENDEN();

    /* Start 15.4 Radio */
    macSetupRadio();

    /* Restore timer comparators */
    MAC_RADIO_BACKOFF_SET_PERIOD(macBackoffTimerRollover);
    MAC_RADIO_BACKOFF_SET_COMPARE(backoffTimerTrigger);

#if 0 /* Following code should be disabled normally */
    /* Code for wakeup lead time calibration */
    {
      static uint32 macBackoffTimerMinMargin = 0xffffffffu;
      uint32 delta = macPrevPeriodRatCount +
        backoffTimerTrigger * MAC_BACKOFF_TO_RAT_RATIO - MAC_RAT_COUNT;
      if (delta < macBackoffTimerMinMargin)
      {
        macBackoffTimerMinMargin = delta;
      }
    }
#endif
  }

  /* Note that MAC_BACKOFF_TIMER_EVENT_POWER_TIMER_EXP handling must always
   * occur after handling of MAC_BACKOFF_TIMER_EVENT_POWER_WAKEUP event
   * because the device might be waking up upon the timer event itself
   * in which case, radio has to be turned on before updating the RAT timer.
   */
  if (events & MAC_BACKOFF_TIMER_EVENT_POWER_TIMER_EXP)
  {
    /* Update wakeup schedule, which most likely would vote not to enter
     * sleep state. */
    HAL_ENTER_CRITICAL_SECTION(is);
    MAC_BACKOFF_TIMER_UPDATE_WAKEUP();
    HAL_EXIT_CRITICAL_SECTION(is);
  }
}