/***************************************************************************//** * @brief * Set 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. * * @param[in] letimer * Pointer to LETIMER peripheral register block * * @param[in] rep * Repeat counter register to set, either 0 or 1 * * @param[in] value * Initialization value (<= 0x0000ffff) ******************************************************************************/ void LETIMER_RepeatSet(LETIMER_TypeDef *letimer, unsigned int rep, uint32_t value) { volatile uint32_t *repReg; uint32_t syncbusy; EFM_ASSERT(LETIMER_REF_VALID(letimer) && LETIMER_REP_REG_VALID(rep) && ((value & ~(_LETIMER_REP0_REP0_MASK >> _LETIMER_REP0_REP0_SHIFT)) == 0)); /* Initialize selected compare value */ switch (rep) { case 0: repReg = &(letimer->REP0); syncbusy = LETIMER_SYNCBUSY_REP0; break; case 1: repReg = &(letimer->REP1); syncbusy = LETIMER_SYNCBUSY_REP1; break; default: /* Unknown compare register selected, abort */ return; } /* LF register about to be modified require sync. busy check */ LETIMER_Sync(letimer, syncbusy); *repReg = value; }
/***************************************************************************//** * @brief * Set 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 * comment in the LETIMER_Sync() internal function call. * * @param[in] letimer * Pointer to LETIMER peripheral register block * * @param[in] comp * Compare register to set, either 0 or 1 * * @param[in] value * 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 selected compare value */ switch (comp) { case 0: compReg = &(letimer->COMP0); break; case 1: compReg = &(letimer->COMP1); break; default: /* Unknown compare register selected, abort */ return; } #if defined(_EFM32_GECKO_FAMILY) /* LF register about to be modified require sync. busy check */ LETIMER_Sync(letimer, comp ? LETIMER_SYNCBUSY_COMP1 : LETIMER_SYNCBUSY_COMP0); #endif *compReg = value; }
/***************************************************************************//** * @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. * * @param[in] letimer * Pointer to 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)); /* LF register about to be modified require sync. busy check */ LETIMER_Sync(letimer, LETIMER_SYNCBUSY_CMD); if (enable) { letimer->CMD = LETIMER_CMD_START; } else { letimer->CMD = LETIMER_CMD_STOP; } }
/***************************************************************************//** * @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 to the use of this function if configuring the LETIMER to start when * initialization is completed. * * @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 comment in the * LETIMER_Sync() internal function call. * * @param[in] letimer * Pointer to LETIMER peripheral register block. * * @param[in] init * Pointer to LETIMER initialization structure. ******************************************************************************/ void LETIMER_Init(LETIMER_TypeDef *letimer, const LETIMER_Init_TypeDef *init) { uint32_t tmp = 0; EFM_ASSERT(LETIMER_REF_VALID(letimer)); /* Stop 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 require sync. busy check */ LETIMER_Sync(letimer, LETIMER_SYNCBUSY_CMD); #endif letimer->CMD = LETIMER_CMD_STOP; } /* Configure DEBUGRUN flag, sets whether or not counter should be * updated when debugger is active */ if (init->debugRun) { tmp |= LETIMER_CTRL_DEBUGRUN; } if (init->rtcComp0Enable) { tmp |= LETIMER_CTRL_RTCC0TEN; } if (init->rtcComp1Enable) { tmp |= LETIMER_CTRL_RTCC1TEN; } if (init->comp0Top) { tmp |= LETIMER_CTRL_COMP0TOP; } 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 require sync. busy check */ LETIMER_Sync(letimer, LETIMER_SYNCBUSY_CTRL); #endif letimer->CTRL = tmp; /* Start 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 require sync. busy check */ LETIMER_Sync(letimer, LETIMER_SYNCBUSY_CMD); #endif letimer->CMD = LETIMER_CMD_START; } }