-
-
Save salkinium/7113bb72c1f33ee6677d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// coding: utf-8 | |
/* Copyright (c) 2011, Roboterclub Aachen e.V. | |
* All Rights Reserved. | |
* | |
* The file is part of the xpcc library and is released under the 3-clause BSD | |
* license. See the file `LICENSE` for the full license governing this code. | |
*/ | |
// ---------------------------------------------------------------------------- | |
#include "../../../device.hpp" | |
#include "clock.hpp" | |
// ---------------------------------------------------------------------------- | |
bool | |
xpcc::stm32::ClockControl::enableInternalClock(uint32_t waitCycles) | |
{ | |
bool retval; | |
RCC->CR |= RCC_CR_HSION; | |
while (not (retval = (RCC->CR & RCC_CR_HSIRDY)) and --waitCycles) | |
; | |
return retval; | |
} | |
bool | |
xpcc::stm32::ClockControl::enableExternalClock(uint32_t waitCycles) | |
{ | |
bool retval; | |
RCC->CR |= RCC_CR_HSEBYP | RCC_CR_HSEON; | |
while (not (retval = (RCC->CR & RCC_CR_HSERDY)) and --waitCycles) | |
; | |
return retval; | |
} | |
bool | |
xpcc::stm32::ClockControl::enableExternalCrystal(uint32_t waitCycles) | |
{ | |
bool retval; | |
RCC->CR = (RCC->CR & ~RCC_CR_HSEBYP) | RCC_CR_HSEON; | |
while (not (retval = (RCC->CR & RCC_CR_HSERDY)) and --waitCycles) | |
; | |
return retval; | |
} | |
bool | |
xpcc::stm32::ClockControl::enableLowSpeedInternalClock(uint32_t waitCycles) | |
{ | |
bool retval; | |
RCC->CSR |= RCC_CSR_LSION; | |
while (not (retval = (RCC->CSR & RCC_CSR_LSIRDY)) and --waitCycles) | |
; | |
return retval; | |
} | |
bool | |
xpcc::stm32::ClockControl::enableLowSpeedExternalClock(uint32_t waitCycles) | |
{ | |
bool retval; | |
RCC->BDCR |= RCC_BDCR_LSEBYP | RCC_BDCR_LSEON; | |
while (not (retval = (RCC->BDCR & RCC_BDCR_LSERDY)) and --waitCycles) | |
; | |
return retval; | |
} | |
bool | |
xpcc::stm32::ClockControl::enableLowSpeedExternalCrystal(uint32_t waitCycles) | |
{ | |
bool retval; | |
RCC->BDCR = (RCC->BDCR & ~RCC_BDCR_LSEBYP) | RCC_BDCR_LSEON; | |
while (not (retval = (RCC->BDCR & RCC_BDCR_LSERDY)) and --waitCycles) | |
; | |
return retval; | |
} | |
// ---------------------------------------------------------------------------- | |
bool | |
xpcc::stm32::ClockControl::enablePll(PllSource source, | |
UsbPrescaler usb, | |
uint8_t pllMul, uint8_t pllPrediv, uint32_t waitCycles) | |
{ | |
// Read reserved values and clear all other values | |
uint32_t tmp = RCC->CFGR & ~(RCC_CFGR_USBPRE | RCC_CFGR_PLLMULL | RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE); | |
// Divide Output for USB Clock by 1.5? | |
tmp |= static_cast<uint32_t>(usb); | |
// PLLSRC source for pll | |
tmp |= static_cast<uint32_t>(source); | |
// Pll multiplication factor | |
tmp |= (static_cast<uint32_t>(pllMul - 2) << 18) & RCC_CFGR_PLLMULL; | |
#ifdef RCC_CFGR2_PREDIV1 | |
// HSE PREDIV division factor | |
RCC->CFGR2 = (RCC->CFGR2 & ~(RCC_CFGR2_PREDIV1)) | (uint32_t(pllPrediv - 1) & RCC_CFGR2_PREDIV1); | |
#else | |
if (uint32_t(pllPrediv - 1) & 0x1) tmp |= RCC_CFGR_PLLXTPRE; | |
#endif | |
RCC->CFGR = tmp; | |
// enable pll | |
RCC->CR |= RCC_CR_PLLON; | |
while (not (tmp = (RCC->CR & RCC_CR_PLLRDY)) and --waitCycles) | |
; | |
return tmp; | |
} | |
// ---------------------------------------------------------------------------- | |
bool | |
xpcc::stm32::ClockControl::enableSystemClock(SystemClockSource src, uint32_t waitCycles) | |
{ | |
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_SW) | uint32_t(src); | |
// Wait till the main PLL is used as system clock source | |
src = SystemClockSource(uint32_t(src) << 2); | |
while ((RCC->CFGR & RCC_CFGR_SWS) != uint32_t(src)) | |
{ | |
if (not --waitCycles) | |
return false; | |
} | |
return true; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// coding: utf-8 | |
/* Copyright (c) 2011, Roboterclub Aachen e.V. | |
* All Rights Reserved. | |
* | |
* The file is part of the xpcc library and is released under the 3-clause BSD | |
* license. See the file `LICENSE` for the full license governing this code. | |
*/ | |
// ---------------------------------------------------------------------------- | |
#ifndef XPCC_STM32_CLOCK_HPP | |
#define XPCC_STM32_CLOCK_HPP | |
#include <stdint.h> | |
#include "../../../device.hpp" | |
#include "../generic/common_clock.hpp" | |
// #include "static.hpp" | |
using namespace xpcc::clock; | |
namespace xpcc | |
{ | |
namespace stm32 | |
{ | |
/** | |
* Clock management. | |
* | |
* For using the internal clock (which is 16MHz) use: | |
* \code | |
* typedef xpcc::stm32::Clock C; | |
* enablePll(C::PllSource::PLL_HSI, 8, 120); // for STM32F2xx | |
* enablePll(C::PllSource::PLL_HSI, 8, 168); // for STM32F4xx | |
* switchToPll(); | |
* \endcode | |
* | |
* For using an external crystal with 8 MHz use: | |
* \code | |
* typedef xpcc::stm32::Clock C; | |
* if (enableHse(C::HseConfig::HSE_CRYSTAL)) | |
* { | |
* enablePll(C::PllSource::PLL_HSE, 4, 120); // for STM32F2xx | |
* enablePll(C::PllSource::PLL_HSE, 4, 168); // for STM32F4xx | |
* switchToPll(); | |
* } | |
* \endcode | |
* | |
* For using an external oscillator with 25 MHz use: | |
* \code | |
* if (enableHse(HSE_BYPASS)) | |
* { | |
* enablePll(PLL_HSE, 25, 240); // for STM32F2xx | |
* enablePll(PLL_HSE, 25, 336); // for STM32F4xx | |
* switchToPll(); | |
* } | |
* \endcode | |
* | |
* \ingroup stm32f2_4 | |
*/ | |
class ClockControl | |
{ | |
public: | |
enum class | |
ClockSource | |
{ | |
InternalClock, | |
ExternalClock, | |
ExternalCrystal, | |
LowSpeedInternalClock, | |
LowSpeedExternalClock, | |
LowSpeedExternalCrystal, | |
}; | |
enum class | |
PllSource : uint32_t | |
{ | |
/// High speed internal clock (8 MHz) | |
Hsi = 0, | |
/// High speed external clock (see HseConfig) | |
Hse = RCC_CFGR_PLLSRC, | |
InternalClock = Hsi, | |
ExternalClock = Hse, | |
ExternalCrystal = Hse, | |
}; | |
enum class | |
SystemClockSource : uint32_t | |
{ | |
Hsi = RCC_CFGR_SW_HSI, | |
Hse = RCC_CFGR_SW_HSE, | |
Pll = RCC_CFGR_SW_PLL, | |
InternalClock = Hsi, | |
ExternalClock = Hse, | |
ExternalCrystal = Hse, | |
}; | |
enum class | |
RealTimeClockSource : uint32_t | |
{ | |
Lsi = RCC_BDCR_RTCSEL_LSI, | |
Lse = RCC_BDCR_RTCSEL_LSE, | |
Hse = RCC_BDCR_RTCSEL_HSE, | |
ExternalClock = Hse, | |
ExternalCrystal = Hse, | |
LowSpeedInternalClock = Lsi, | |
LowSpeedExternalClock = Lse, | |
LowSpeedExternalCrystal = Lse | |
}; | |
enum class | |
WatchdogClockSource : uint32_t | |
{ | |
LowSpeedInternalClock = 0 | |
}; | |
enum class | |
AhbPrescaler : uint32_t | |
{ | |
Div1 = RCC_CFGR_HPRE_DIV1, | |
Div2 = RCC_CFGR_HPRE_DIV2, | |
Div4 = RCC_CFGR_HPRE_DIV4, | |
Div8 = RCC_CFGR_HPRE_DIV8, | |
Div16 = RCC_CFGR_HPRE_DIV16, | |
Div64 = RCC_CFGR_HPRE_DIV64, | |
Div128 = RCC_CFGR_HPRE_DIV128, | |
Div256 = RCC_CFGR_HPRE_DIV256, | |
Div512 = RCC_CFGR_HPRE_DIV512 | |
}; | |
enum class | |
Apb1Prescaler : uint32_t | |
{ | |
Div1 = RCC_CFGR_PPRE1_DIV1, | |
Div2 = RCC_CFGR_PPRE1_DIV2, | |
Div4 = RCC_CFGR_PPRE1_DIV4, | |
Div8 = RCC_CFGR_PPRE1_DIV8, | |
Div16 = RCC_CFGR_PPRE1_DIV16 | |
}; | |
enum class | |
Apb2Prescaler : uint32_t | |
{ | |
Div1 = RCC_CFGR_PPRE2_DIV1, | |
Div2 = RCC_CFGR_PPRE2_DIV2, | |
Div4 = RCC_CFGR_PPRE2_DIV4, | |
Div8 = RCC_CFGR_PPRE2_DIV8, | |
Div16 = RCC_CFGR_PPRE2_DIV16 | |
}; | |
enum class | |
ClockOutputSource : uint32_t | |
{ | |
SystemClock = RCC_CFGR_MCO_SYSCLK, | |
InternalClock = RCC_CFGR_MCO_HSI, | |
ExternalClock = RCC_CFGR_MCO_HSE, | |
ExternalCrystal = RCC_CFGR_MCO_HSE, | |
Pll = RCC_CFGR_MCO_PLLCLK_DIV2, ///< divided by 2 | |
}; | |
enum class | |
UsbPrescaler : uint32_t | |
{ | |
DivideBy1Point5 = 0, | |
DoNotDivide = RCC_CFGR_USBPRE, | |
}; | |
public: | |
// sources | |
static bool | |
enableInternalClock(uint32_t waitCycles = 2048); | |
static bool | |
enableExternalClock(uint32_t waitCycles = 2048); | |
static bool | |
enableExternalCrystal(uint32_t waitCycles = 2048); | |
static bool | |
enableLowSpeedInternalClock(uint32_t waitCycles = 2048); | |
static bool | |
enableLowSpeedExternalClock(uint32_t waitCycles = 2048); | |
static bool | |
enableLowSpeedExternalCrystal(uint32_t waitCycles = 2048); | |
// plls | |
static bool | |
enablePll(PllSource source, | |
UsbPrescaler usb, | |
uint8_t pllMul, uint8_t pllPrediv, uint32_t waitCycles = 2048); | |
// sinks | |
static bool | |
enableSystemClock(SystemClockSource src, uint32_t waitCycles = 2048); | |
static inline bool | |
enableRealTimeClock(RealTimeClockSource src) | |
{ | |
RCC->BDCR = (RCC->BDCR & ~RCC_BDCR_RTCSEL) | RCC_BDCR_RTCEN | uint32_t(src); | |
return true; | |
} | |
static inline bool | |
enableWatchdogClock(WatchdogClockSource /*src*/) | |
{ return true; } | |
static inline bool | |
enableClockOutput(ClockOutputSource src) | |
{ | |
RCC->CFGR = (RCC->CFGR & ~(RCC_CFGR_MCO))| uint32_t(src); | |
return true; | |
} | |
public: | |
static inline bool | |
setAhbPrescaler(AhbPrescaler prescaler) | |
{ | |
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_HPRE) | uint32_t(prescaler); | |
return true; | |
} | |
static inline bool | |
setApb1Prescaler(Apb1Prescaler prescaler) | |
{ | |
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_PPRE1) | uint32_t(prescaler); | |
return true; | |
} | |
static inline bool | |
setApb2Prescaler(Apb2Prescaler prescaler) | |
{ | |
RCC->CFGR = (RCC->CFGR & ~RCC_CFGR_PPRE2) | uint32_t(prescaler); | |
return true; | |
} | |
public: | |
static inline uint32_t | |
getCpuFrequency() | |
{ | |
return xpcc::clock::fcpu; | |
} | |
static inline uint32_t | |
getCpuFrequencykHz() | |
{ | |
return xpcc::clock::fcpu_kHz; | |
} | |
static inline uint32_t | |
getCpuFrequencyMHz() | |
{ | |
return xpcc::clock::fcpu_MHz; | |
} | |
}; | |
} // namespace stm32 | |
} // namespace xpcc | |
#endif // XPCC_STM32_CLOCK_HPP |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment