コード例 #1
0
ファイル: em_letimer.c プロジェクト: nashif/zephyr
/***************************************************************************//**
 * @brief
 *   Set the LETIMER compare register value.
 *
 * @note
 *   The setting of a compare register requires synchronization into the
 *   low frequency domain. If the same register is modified before a previous
 *   update has completed, this function will stall until the previous
 *   synchronization has completed. This only applies to the Gecko Family. See
 *   comments in the LETIMER_Sync() internal function call.
 *
 * @param[in] letimer
 *   A pointer to the LETIMER peripheral register block.
 *
 * @param[in] comp
 *   A compare register to set, either 0 or 1.
 *
 * @param[in] value
 *   An initialization value (<= 0x0000ffff).
 ******************************************************************************/
void LETIMER_CompareSet(LETIMER_TypeDef *letimer,
                        unsigned int comp,
                        uint32_t value)
{
  volatile uint32_t *compReg;

  EFM_ASSERT(LETIMER_REF_VALID(letimer)
             && LETIMER_COMP_REG_VALID(comp)
             && ((value & ~(_LETIMER_COMP0_COMP0_MASK
                            >> _LETIMER_COMP0_COMP0_SHIFT))
                 == 0));

  /* Initialize the selected compare value. */
  switch (comp) {
    case 0:
      compReg  = &(letimer->COMP0);
      break;

    case 1:
      compReg  = &(letimer->COMP1);
      break;

    default:
      /* An unknown compare register selected, abort. */
      return;
  }

#if defined(_EFM32_GECKO_FAMILY)
  /* LF register about to be modified requires sync; busy check. */
  regSync(letimer, comp ? LETIMER_SYNCBUSY_COMP1 : LETIMER_SYNCBUSY_COMP0);
#endif

  *compReg = value;
}
コード例 #2
0
ファイル: em_burtc.c プロジェクト: 8bitgeek/Espruino
/***************************************************************************//**
 * @brief Set BURTC compare channel
 *
 * @param[in] comp Compare channel index, must be 0 for Giant / Leopard Gecko
 *
 * @param[in] value New compare value
 ******************************************************************************/
void BURTC_CompareSet(unsigned int comp, uint32_t value)
{
  (void) comp;  /* Unused parameter when EFM_ASSERT is undefined. */

  EFM_ASSERT(comp == 0);

  /* Modification of COMP0 register requires sync with potential ongoing
   * register updates in LF domain. */
  regSync(BURTC_SYNCBUSY_COMP0);

  /* Configure compare channel 0 */
  BURTC->COMP0 = value;
}
コード例 #3
0
ファイル: em_letimer.c プロジェクト: nashif/zephyr
/***************************************************************************//**
 * @brief
 *   Start/stop LETIMER.
 *
 * @note
 *   The enabling/disabling of the LETIMER modifies the LETIMER CMD register
 *   which requires synchronization into the low-frequency domain. If this
 *   register is modified before a previous update to the same register has
 *   completed, this function will stall until the previous synchronization has
 *   completed. This only applies to the Gecko Family. See comments in the
 *   LETIMER_Sync() internal function call.
 *
 * @param[in] letimer
 *   A pointer to the LETIMER peripheral register block.
 *
 * @param[in] enable
 *   True to enable counting, false to disable.
 ******************************************************************************/
void LETIMER_Enable(LETIMER_TypeDef *letimer, bool enable)
{
  EFM_ASSERT(LETIMER_REF_VALID(letimer));

#if defined(_EFM32_GECKO_FAMILY)
  /* LF register about to be modified requires sync; busy check. */
  regSync(letimer, LETIMER_SYNCBUSY_CMD);
#elif defined (LETIMER_SYNCBUSY_START) && defined (LETIMER_SYNCBUSY_STOP)
  uint32_t syncBusyMask = LETIMER_SYNCBUSY_STOP | LETIMER_SYNCBUSY_START;
  while (letimer->SYNCBUSY & syncBusyMask) {
  }
#endif

  if (enable) {
    letimer->CMD = LETIMER_CMD_START;
  } else {
    letimer->CMD = LETIMER_CMD_STOP;
  }
}
コード例 #4
0
ファイル: em_letimer.c プロジェクト: nashif/zephyr
/***************************************************************************//**
 * @brief
 *   Set the LETIMER repeat counter register value.
 *
 * @note
 *   The setting of a repeat counter register requires synchronization into the
 *   low-frequency domain. If the same register is modified before a previous
 *   update has completed, this function will stall until the previous
 *   synchronization has completed. This only applies to the Gecko Family. See
 *   comments in the LETIMER_Sync() internal function call.
 *
 * @param[in] letimer
 *   A pointer to the LETIMER peripheral register block.
 *
 * @param[in] rep
 *   Repeat counter register to set, either 0 or 1.
 *
 * @param[in] value
 *   An initialization value (<= 0x0000ffff).
 ******************************************************************************/
void LETIMER_RepeatSet(LETIMER_TypeDef *letimer,
                       unsigned int rep,
                       uint32_t value)
{
  volatile uint32_t *repReg;
#if defined(_EFM32_GECKO_FAMILY)
  uint32_t          syncbusy;
#endif
  EFM_ASSERT(LETIMER_REF_VALID(letimer)
             && LETIMER_REP_REG_VALID(rep)
             && ((value & ~(_LETIMER_REP0_REP0_MASK
                            >> _LETIMER_REP0_REP0_SHIFT))
                 == 0));

  /* Initialize the selected compare value. */
  switch (rep) {
    case 0:
      repReg = &(letimer->REP0);
#if defined(_EFM32_GECKO_FAMILY)
      syncbusy = LETIMER_SYNCBUSY_REP0;
#endif
      break;

    case 1:
      repReg = &(letimer->REP1);
#if defined(_EFM32_GECKO_FAMILY)
      syncbusy = LETIMER_SYNCBUSY_REP1;
#endif
      break;

    default:
      /* An unknown compare register selected, abort. */
      return;
  }

#if defined(_EFM32_GECKO_FAMILY)
  /* LF register about to be modified requires sync; busy check. */
  regSync(letimer, syncbusy);
#endif

  *repReg = value;
}
コード例 #5
0
ファイル: em_burtc.c プロジェクト: 8bitgeek/Espruino
/***************************************************************************//**
 * @brief Initialize BURTC
 *
 * @details
 *    Configures the BURTC peripheral.
 *
 * @note
 *   Before initialization, BURTC module must first be enabled by clearing the
 *   reset bit in the RMU, i.e.
 * @verbatim
 *   RMU_ResetControl(rmuResetBU, rmuResetModeClear);
 * @endverbatim
 *   Compare channel 0 must be configured outside this function, before
 *   initialization if enable is set to true. The counter will always be reset.
 *
 * @param[in] burtcInit
 *   Pointer to BURTC initialization structure
 ******************************************************************************/
void BURTC_Init(const BURTC_Init_TypeDef *burtcInit)
{
  uint32_t ctrl;
  uint32_t presc;

  /* Check initializer structure integrity */
  EFM_ASSERT(burtcInit != (BURTC_Init_TypeDef *) 0);
  /* Clock divider must be between 1 and 128, really on the form 2^n */
  EFM_ASSERT((burtcInit->clkDiv >= 1) && (burtcInit->clkDiv <= 128));
  /* Ignored compare bits during low power operation must be less than 7 */
  /* Note! Giant Gecko revision C errata, do NOT use LPCOMP=7 */
  EFM_ASSERT(burtcInit->lowPowerComp <= 6);
  /* You cannot enable the BURTC if mode is set to disabled */
  EFM_ASSERT((burtcInit->enable == false) ||
             ((burtcInit->enable == true)
              && (burtcInit->mode != burtcModeDisable)));
  /* Low power mode is only available with LFRCO or LFXO as clock source */
  EFM_ASSERT((burtcInit->clkSel != burtcClkSelULFRCO)
             || ((burtcInit->clkSel == burtcClkSelULFRCO)
                  && (burtcInit->lowPowerMode == burtcLPDisable)));

  /* Calculate prescaler value from clock divider input */
  /* Note! If clock select (clkSel) is ULFRCO, a clock divisor (clkDiv) of
     value 1 will select a 2kHz ULFRCO clock, while any other value will
     select a 1kHz ULFRCO clock source. */
  presc = divToLog2(burtcInit->clkDiv);

  /* Make sure all registers are updated simultaneously */
  if (burtcInit->enable)
  {
    BURTC_FreezeEnable(true);
  }

  /* Modification of LPMODE register requires sync with potential ongoing
   * register updates in LF domain. */
  regSync(BURTC_SYNCBUSY_LPMODE);

  /* Configure low power mode */
  BURTC->LPMODE = (uint32_t) (burtcInit->lowPowerMode);

  /* New configuration */
  ctrl = (BURTC_CTRL_RSTEN
          | (burtcInit->mode)
          | (burtcInit->debugRun << _BURTC_CTRL_DEBUGRUN_SHIFT)
          | (burtcInit->compare0Top << _BURTC_CTRL_COMP0TOP_SHIFT)
          | (burtcInit->lowPowerComp << _BURTC_CTRL_LPCOMP_SHIFT)
          | (presc << _BURTC_CTRL_PRESC_SHIFT)
          | (burtcInit->clkSel)
          | (burtcInit->timeStamp << _BURTC_CTRL_BUMODETSEN_SHIFT));

  /* Clear interrupts */
  BURTC_IntClear(0xFFFFFFFF);

  /* Set new configuration */
  BURTC->CTRL = ctrl;

  /* Enable BURTC and counter */
  if (burtcInit->enable)
  {
    /* To enable BURTC counter, we need to disable reset */
    BURTC_Enable(true);

    /* Clear freeze */
    BURTC_FreezeEnable(false);
  }
}
コード例 #6
0
ファイル: em_letimer.c プロジェクト: nashif/zephyr
/***************************************************************************//**
 * @brief
 *   Initialize LETIMER.
 *
 * @details
 *   Note that the compare/repeat values must be set separately with
 *   LETIMER_CompareSet() and LETIMER_RepeatSet(). That should probably be done
 *   prior using this function if configuring the LETIMER to start when
 *   initialization is complete.
 *
 * @note
 *   The initialization of the LETIMER modifies the LETIMER CTRL/CMD registers
 *   which require synchronization into the low-frequency domain. If any of those
 *   registers are modified before a previous update to the same register has
 *   completed, this function will stall until the previous synchronization has
 *   completed. This only applies to the Gecko Family. See comments in the
 *   LETIMER_Sync() internal function call.
 *
 * @param[in] letimer
 *   A pointer to the LETIMER peripheral register block.
 *
 * @param[in] init
 *   A pointer to the LETIMER initialization structure.
 ******************************************************************************/
void LETIMER_Init(LETIMER_TypeDef *letimer, const LETIMER_Init_TypeDef *init)
{
  uint32_t tmp = 0;

  EFM_ASSERT(LETIMER_REF_VALID(letimer));

#if defined (LETIMER_EN_EN)
  letimer->EN_SET = LETIMER_EN_EN;
#endif

  /* Stop the timer if specified to be disabled and running. */
  if (!(init->enable) && (letimer->STATUS & LETIMER_STATUS_RUNNING)) {
#if defined(_EFM32_GECKO_FAMILY)
    /* LF register about to be modified requires sync; busy check. */
    regSync(letimer, LETIMER_SYNCBUSY_CMD);
#elif defined(LETIMER_SYNCBUSY_STOP)
    while (letimer->SYNCBUSY & LETIMER_SYNCBUSY_STOP) {
    }
#endif
    letimer->CMD = LETIMER_CMD_STOP;
  }

  /* Configure the DEBUGRUN flag, which sets whether or not the counter should be
   * updated when the debugger is active. */
  if (init->debugRun) {
    tmp |= LETIMER_CTRL_DEBUGRUN;
  }

#if defined(LETIMER_CTRL_RTCC0TEN)
  if (init->rtcComp0Enable) {
    tmp |= LETIMER_CTRL_RTCC0TEN;
  }

  if (init->rtcComp1Enable) {
    tmp |= LETIMER_CTRL_RTCC1TEN;
  }
#endif

  if ((init->comp0Top) || (init->topValue != 0U)) {
#if defined (LETIMER_CTRL_COMP0TOP)
    tmp |= LETIMER_CTRL_COMP0TOP;
    letimer->COMP0 = init->topValue;
#elif defined (LETIMER_CTRL_CNTTOPEN)
    tmp |= LETIMER_CTRL_CNTTOPEN;
    letimer->TOP = init->topValue;
#endif
  }

  if (init->bufTop) {
    tmp |= LETIMER_CTRL_BUFTOP;
  }

  if (init->out0Pol) {
    tmp |= LETIMER_CTRL_OPOL0;
  }

  if (init->out1Pol) {
    tmp |= LETIMER_CTRL_OPOL1;
  }

  tmp |= init->ufoa0 << _LETIMER_CTRL_UFOA0_SHIFT;
  tmp |= init->ufoa1 << _LETIMER_CTRL_UFOA1_SHIFT;
  tmp |= init->repMode << _LETIMER_CTRL_REPMODE_SHIFT;

#if defined(_EFM32_GECKO_FAMILY)
  /* LF register about to be modified requires sync; busy check. */
  regSync(letimer, LETIMER_SYNCBUSY_CTRL);
#endif
  letimer->CTRL = tmp;

  /* Start the timer if specified to be enabled and not already running. */
  if (init->enable && !(letimer->STATUS & LETIMER_STATUS_RUNNING)) {
#if defined(_EFM32_GECKO_FAMILY)
    /* LF register about to be modified requires sync; busy check. */
    regSync(letimer, LETIMER_SYNCBUSY_CMD);
#elif defined(LETIMER_SYNCBUSY_START)
    while (letimer->SYNCBUSY & LETIMER_SYNCBUSY_START) {
    }
#endif
    letimer->CMD = LETIMER_CMD_START;
  }
}