/*! * @cond DOXYGEN_PRIVATE * * @brief Sets up timer with divider settings closest to the requested period in microseconds. * * The function gets the value of the base frequency of the timer via clock manager and calculates required * divider ratio. If the required period is a large value, then the code will try to use a low-frequency * external clock if available. * * Called by hwtimer_set_freq() and hwtimer_set_period(). * Fills in the divider (actual total divider) and modulo (sub-tick resolution) members of the hwtimer_t structure. * * @param hwtimer[in] Pointer to hwtimer structure. * @param period[in] Required period of timer in micro seconds. * * @return kHwtimerSuccess Success. * @return kHwtimerInvalidInput Divider is equal too big. * * @see HWTIMER_SYS_SystickInit * @see HWTIMER_SYS_SystickDeinit * @see HWTIMER_SYS_SystickStart * @see HWTIMER_SYS_SystickStop * @see HWTIMER_SYS_SystickGet_time * @see HWTIMER_SYS_SystickIsrAction */ static _hwtimer_error_code_t HWTIMER_SYS_SystickSetDiv(hwtimer_t *hwtimer, uint32_t period) { assert(NULL != hwtimer); uint64_t divider; #if FSL_FEATURE_SYSTICK_HAS_EXT_REF /* Set the clock source back to core freq */ CLOCK_SYS_SetSystickSrc(kClockSystickSrcCore); #endif /* Get Core clock frequency */ hwtimer->clockFreq = CLOCK_SYS_GetSystickFreq(); divider = (((uint64_t)hwtimer->clockFreq * period)) / 1000000U ; /* if divider is greater than 24b value we return an error */ if ((divider - 1U) & ~SysTick_LOAD_RELOAD_Msk) { #if FSL_FEATURE_SYSTICK_HAS_EXT_REF /* Check if we can use a slower clock source to get required period */ CLOCK_SYS_SetSystickSrc(kClockSystickSrcExtRef); hwtimer->clockFreq = CLOCK_SYS_GetSystickFreq(); divider = (((uint64_t)hwtimer->clockFreq * period)) / 1000000U ; if ((divider - 1U) & ~SysTick_LOAD_RELOAD_Msk) { return kHwtimerInvalidInput; } #else return kHwtimerInvalidInput; #endif } /* * A start value of 0 (divider == 1) is possible, but has no effect because the * SysTick interrupt and COUNTFLAG are activated when counting from 1 to 0. */ if (divider == 1U) { divider = 2U; /* Set smallest possible value for divider. */ } SysTick->LOAD = divider - 1U; /* Store in struct. */ hwtimer->divider = divider; hwtimer->modulo = divider; return kHwtimerSuccess; }
clock_manager_error_code_t CLOCK_SYS_GetFreq(clock_names_t clockName, uint32_t *frequency) { clock_manager_error_code_t returnCode = kClockManagerSuccess; switch (clockName) { case kCoreClock: case kSystemClock: *frequency = CLOCK_SYS_GetCoreClockFreq(); break; case kPlatformClock: *frequency = CLOCK_SYS_GetSystemClockFreq(); break; case kBusClock: *frequency = CLOCK_SYS_GetBusClockFreq(); break; case kFlashClock: *frequency = CLOCK_SYS_GetFlashClockFreq(); break; case kOsc32kClock: *frequency = CLOCK_SYS_GetExternalRefClock32kFreq(); break; case kOsc0ErClock: *frequency = CLOCK_SYS_GetOsc0ExternalRefClockFreq(); break; case kRtcoutClock: *frequency = CLOCK_SYS_GetRtcOutFreq(); break; case kMcgFfClock: *frequency = CLOCK_SYS_GetFixedFreqClockFreq(); break; case kMcgFllClock: *frequency = CLOCK_HAL_GetFllClk(MCG); break; case kMcgPll0Clock: *frequency = CLOCK_HAL_GetPll0Clk(MCG); break; case kMcgOutClock: *frequency = CLOCK_HAL_GetOutClk(MCG); break; case kMcgIrClock: *frequency = CLOCK_HAL_GetInternalRefClk(MCG); break; case kLpoClock: *frequency = CLOCK_SYS_GetLpoClockFreq(); break; case kSystickClock: *frequency = CLOCK_SYS_GetSystickFreq(); break; default: *frequency = 0U; returnCode = kClockManagerNoSuchClockName; break; } return returnCode; }
/* ** =================================================================== ** Method : OSA_TimeInit (component fsl_os_abstraction) ** ** Description : ** This function initializes the timer used in BM OSA, the ** functions such as OSA_TimeDelay, OSA_TimeGetMsec, and the ** timeout are all based on this timer. ** This method is internal. It is used by Processor Expert only. ** =================================================================== */ void OSA_TimeInit(void) { uint64_t divider; /* Disable timer and interrupt */ SysTick->CTRL = 0U; /* A write of any value to current value register clears the field to 0, and also clears the SYST_CSR COUNTFLAG bit to 0. */ SysTick->VAL = 0U; #if FSL_FEATURE_SYSTICK_HAS_EXT_REF /* Set the clock source back to core freq */ CLOCK_SYS_SetSystickSrc(kClockSystickSrcCore); #endif /* Get SysTick counter input frequency and compute divider value */ divider = ((((uint64_t)CLOCK_SYS_GetSystickFreq() * OSA1_TIMER_PERIOD_US)) / 1000000U); assert(divider != 0U); /* Set divide input clock of systick timer */ SysTick->LOAD = (uint32_t)(divider - 1U); /* Set interrupt priority and enable interrupt */ NVIC_SetPriority(SysTick_IRQn, 7U); /* Run timer and enable interrupt */ SysTick->CTRL = (SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_TICKINT_Msk); }