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

📄 hal_sleep.c

📁 一些基于IRA环境开发的zigbee实例程序
💻 C
📖 第 1 页 / 共 2 页
字号:
  /* DEEP sleep can only be entered when zgPollRate == 0.
   * This is to eliminate any possibility of entering PM3 between
   * two network timers.
   */
#if !defined (RTR_NWK) && defined (NWK_AUTO_POLL)
  if ((timeout > HAL_SLEEP_MS_TO_320US(PM_MIN_SLEEP_TIME)) ||
      (timeout == 0 && zgPollRate == 0))
#else
  if ((timeout > HAL_SLEEP_MS_TO_320US(PM_MIN_SLEEP_TIME)) ||
      (timeout == 0))
#endif
  {
    halIntState_t intState, ien0, ien1, ien2;
    HAL_ENTER_CRITICAL_SECTION(intState);

    /* always use "deep sleep" to turn off radio VREG on CC2430 */
    if (MAC_PwrOffReq(MAC_PWR_SLEEP_DEEP) == MAC_SUCCESS)
    {
      while ( (HAL_SLEEP_MS_TO_320US(halAccumulatedSleepTime) < timeout) || (timeout == 0) )
      {
        /* get peripherals ready for sleep */
        HalKeyEnterSleep();

#ifdef HAL_SLEEP_DEBUG_LED
        HAL_TURN_OFF_LED3();
#else
        /* use this to turn LEDs off during sleep */
        HalLedEnterSleep();
#endif

        /* set main clock source to RC oscillator for Rev B and Rev D */
        HAL_SLEEP_SET_MAIN_CLOCK_RC();

        /* enable sleep timer interrupt */
        if (timeout != 0)
        {
          if (timeout > HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME ))
          {
            timeout -= HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME );
            halSleepSetTimer(HAL_SLEEP_MS_TO_320US( MAX_SLEEP_TIME ));
          }
          else
          {
            /* set sleep timer */
            halSleepSetTimer(timeout);
          }

          /* set up sleep timer interrupt */
          HAL_SLEEP_TIMER_CLEAR_INT();
          HAL_SLEEP_TIMER_ENABLE_INT();
        }

#ifdef HAL_SLEEP_DEBUG_LED
        if (halPwrMgtMode == CC2430_PM1)
        {
          HAL_TURN_ON_LED1();
        }
        else
        {
          HAL_TURN_OFF_LED1();
        }
#endif

        /* save interrupt enable registers and disable all interrupts */
        HAL_SLEEP_IE_BACKUP_AND_DISABLE(ien0, ien1, ien2);

        /* This is to check if the stack is exceeding the disappearing
         * RAM boundary of 0xF000. If the stack does exceed the boundary
         * (unlikely), do not enter sleep until the stack is back to normal.
         */
        if ( ((uint16)(*( __idata uint16*)(CSTK_PTR)) >= 0xF000) )
        {
          HAL_EXIT_CRITICAL_SECTION(intState);

          /* AN044 - DELAYING EXTERNAL INTERRUPTS, do not relocate this line.
           * it has to stay as close to PCON.IDLE = 1 as possible.
           */
          //EXTERNAL_INTERRUPT_DELAY();   //屏蔽低功郝

          /* set CC2430 power mode */
          HAL_SLEEP_SET_POWER_MODE(halPwrMgtMode);
          /* wake up from sleep */

          HAL_ENTER_CRITICAL_SECTION(intState);
        }

        /* restore interrupt enable registers */
        HAL_SLEEP_IE_RESTORE(ien0, ien1, ien2);

        /* disable sleep timer interrupt */
        HAL_SLEEP_TIMER_DISABLE_INT();

        /* set main clock source to crystal for Rev B and Rev D only */
        HAL_SLEEP_SET_MAIN_CLOCK_CRYSTAL();

        /* Calculate timer elasped */
        halAccumulatedSleepTime += (HalTimerElapsed() / TICK_COUNT);

        /* deduct the sleep time for the next iteration */
        if ( osal_timeout > halAccumulatedSleepTime)
        {
          osal_timeout -= halAccumulatedSleepTime;
        }

        /* if the remaining time is less than the PM_MIN_SLEEP_TIME
         * burn the remaining time in a delay loop
         * AN044 - MINIMUM SLEEP PERIODS WITH PULL-DOWN RESISTOR
         */
        if ( osal_timeout < PM_MIN_SLEEP_TIME )
        {
          halSleepWait(osal_timeout*1000);
          halAccumulatedSleepTime += osal_timeout;
          osal_timeout = halAccumulatedSleepTime;
        }

#ifdef HAL_SLEEP_DEBUG_LED
        HAL_TURN_ON_LED3();
#else
        /* use this to turn LEDs back on after sleep */
        HalLedExitSleep();
#endif

        /* handle peripherals; exit loop if key presses */
        if ( HalKeyExitSleep() )
        {
#if defined (PM2_HOLDOFF_TIME) && (PM2_HOLDOFF_TIME > 0)
          /* The deepest sleep alowwed is PM1 until after the timer expired
           * AN044 - COMBINING POWER MODES
           */
          halSleepLevel = CC2430_PM1;
          osal_stop_timerEx (Hal_TaskID, HAL_SLEEP_TIMER_EVENT);
          osal_start_timerEx (Hal_TaskID, HAL_SLEEP_TIMER_EVENT, PM2_HOLDOFF_TIME);
#endif /* (PM2_HOLDOFF_TIME > 0) */
          break;
        }

        /* exit loop if no timer active */
        if ( timeout == 0 ) break;
      }

      /* power on the MAC; blocks until completion */
      MAC_PwrOnReq();

      /* adjust OSAL timers */
      osal_adjust_timers();

    }

    HAL_EXIT_CRITICAL_SECTION(intState);
  }
}

/**************************************************************************************************
 * @fn          halSleepSetTimer
 *
 * @brief       This function sets the CC2430 sleep timer compare value.  First it reads and
 *              stores the value of the sleep timer; this value is used later to update OSAL
 *              timers.  Then the timeout value is converted from 320 usec units to 32 kHz
 *              period units and the compare value is set to the timeout.
 *
 * input parameters
 *
 * @param       timeout - Timeout value in 320 usec units.  The sleep timer compare is set to
 *                        this value.
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 **************************************************************************************************
 */
void halSleepSetTimer(uint32 timeout)
{
  uint32 ticks;

  /* read the sleep timer; ST0 must be read first */
  ((uint8 *) &ticks)[UINT32_NDX0] = ST0;
  ((uint8 *) &ticks)[UINT32_NDX1] = ST1;
  ((uint8 *) &ticks)[UINT32_NDX2] = ST2;
  ((uint8 *) &ticks)[UINT32_NDX3] = 0;

  /* store value for later */
  halSleepTimerStart = ticks;


  /* Compute sleep timer compare value.  The ratio of 32 kHz ticks to 320 usec ticks
   * is 32768/3125 = 10.48576.  This is nearly 671/64 = 10.484375.
   */
  ticks += (timeout * 671) / 64;

  /* subtract the processing time spent in function halSleep() */
  ticks -= HAL_SLEEP_ADJ_TICKS;

  /* CC2430 Rev. B bug:  compare value must not be set higher than 0xFFFF7F */
  if((ticks & 0xFFFFFF) > 0xFFFF7F)
  {
    ticks = 0xFFFF7F;
  }

  /* set sleep timer compare; ST0 must be written last */
  ST2 = ((uint8 *) &ticks)[UINT32_NDX2];
  ST1 = ((uint8 *) &ticks)[UINT32_NDX1];
  ST0 = ((uint8 *) &ticks)[UINT32_NDX0];
}

/**************************************************************************************************
 * @fn          TimerElapsed
 *
 * @brief       Determine the number of OSAL timer ticks elapsed during sleep.
 *
 * input parameters
 *
 * @param       None.
 *
 * output parameters
 *
 * None.
 *
 * @return      Number of timer ticks elapsed during sleep.
 **************************************************************************************************
 */
uint32 TimerElapsed( void )
{
  return ( halAccumulatedSleepTime );
}

/**************************************************************************************************
 * @fn          HalTimerElapsed
 *
 * @brief       Determine the number of OSAL timer ticks elapsed during sleep.  This function
 *              relies on OSAL macro TICK_COUNT to be set to 1; then ticks are calculated in
 *              units of msec.  (Setting TICK_COUNT to 1 avoids a costly uint32 divide.)
 *
 * input parameters
 *
 * @param       None.
 *
 * output parameters
 *
 * None.
 *
 * @return      Number of timer ticks elapsed during sleep.
 **************************************************************************************************
 */
uint32 HalTimerElapsed( void )
{
  uint32 ticks;

  /* read the sleep timer; ST0 must be read first */
  ((uint8 *) &ticks)[UINT32_NDX0] = ST0;
  ((uint8 *) &ticks)[UINT32_NDX1] = ST1;
  ((uint8 *) &ticks)[UINT32_NDX2] = ST2;

  /* set bit 24 to handle wraparound */
  ((uint8 *) &ticks)[UINT32_NDX3] = 0x01;

  /* calculate elapsed time */
  ticks -= halSleepTimerStart;

  /* add back the processing time spent in function halSleep() */
  ticks += HAL_SLEEP_ADJ_TICKS;

  /* mask off excess if no wraparound */
  ticks &= 0x00FFFFFF;

  /* Convert elapsed time in milliseconds with round.  1000/32768 = 125/4096 */
  return ( ((ticks * 125) + 4095) / 4096 );
}

/**************************************************************************************************
 * @fn          halSleepWait
 *
 * @brief       Perform a blocking wait.
 *
 * input parameters
 *
 * @param       duration - Duration of wait in microseconds.
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 **************************************************************************************************
 */
void halSleepWait(uint16 duration)
{
  while (duration--)
  {
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
    asm("NOP");
  }
}

/**************************************************************************************************
 * @fn          halRestoreSleepLevel
 *
 * @brief       Restore the deepest timer sleep level.
 *
 * input parameters
 *
 * @param       None
 *
 * output parameters
 *
 *              None.
 *
 * @return      None.
 **************************************************************************************************
 */
void halRestoreSleepLevel( void )
{
  halSleepLevel = CC2430_PM2;
}

/**************************************************************************************************
 * @fn          halSleepTimerIsr
 *
 * @brief       Sleep timer ISR.
 *
 * input parameters
 *
 * None.
 *
 * output parameters
 *
 * None.
 *
 * @return      None.
 **************************************************************************************************
 */
HAL_ISR_FUNCTION(halSleepTimerIsr, ST_VECTOR)
{
  HAL_SLEEP_TIMER_CLEAR_INT();

  if( CHVER >= REV_E )
  {
    CLEAR_SLEEP_MODE();
  }
#ifdef HAL_SLEEP_DEBUG_POWER_MODE
  halSleepInt = TRUE;
#endif
}

⌨️ 快捷键说明

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