Skip to content

Commit

Permalink
[stm32] clock: pass pll factors as struct
Browse files Browse the repository at this point in the history
  • Loading branch information
rleh committed Mar 19, 2020
1 parent 23ec952 commit e3ba913
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 47 deletions.
63 changes: 23 additions & 40 deletions src/modm/platform/clock/stm32/rcc.cpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -139,11 +139,10 @@ modm::platform::Rcc::enableLowSpeedExternalCrystal(uint32_t waitCycles)
return retval;
}

%% if target["family"] in ["f2", "f4", "f7"]
// ----------------------------------------------------------------------------
bool
modm::platform::Rcc::enablePll(PllSource source, uint8_t pllM, uint16_t pllN, uint8_t pllP, uint32_t waitCycles)
modm::platform::Rcc::enablePll(PllSource source, const PllFactors& pllFactors, uint32_t waitCycles)
{
%% if target["family"] in ["f2", "f4", "f7"]
// Read reserved values and clear all other values
uint32_t tmp = RCC->PLLCFGR & ~(RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM
| RCC_PLLCFGR_PLLN | RCC_PLLCFGR_PLLP | RCC_PLLCFGR_PLLQ);
Expand All @@ -152,13 +151,13 @@ modm::platform::Rcc::enablePll(PllSource source, uint8_t pllM, uint16_t pllN, ui
tmp |= static_cast<uint32_t>(source);

// PLLM (0) = factor is user defined VCO input frequency must be configured to 2MHz
tmp |= ((uint32_t) pllM) & RCC_PLLCFGR_PLLM;
tmp |= ((uint32_t) pllFactors.pllM) & RCC_PLLCFGR_PLLM;

// PLLN (6) = factor is user defined
tmp |= (((uint32_t) pllN) << RCC_PLLCFGR_PLLN_Pos) & RCC_PLLCFGR_PLLN;
tmp |= (((uint32_t) pllFactors.pllN) << RCC_PLLCFGR_PLLN_Pos) & RCC_PLLCFGR_PLLN;

// PLLP (16) divider for CPU frequency; (00: PLLP = 2, 01: PLLP = 4, etc.)
tmp |= (((uint32_t) (pllP / 2) - 1) << RCC_PLLCFGR_PLLP_Pos) & RCC_PLLCFGR_PLLP;
tmp |= (((uint32_t) (pllFactors.pllP / 2) - 1) << RCC_PLLCFGR_PLLP_Pos) & RCC_PLLCFGR_PLLP;

// PLLQ (24) divider for USB frequency; (0-15)
// tmp |= (((uint32_t) pllQ) << RCC_PLLCFGR_PLLQ_Pos) & RCC_PLLCFGR_PLLQ;
Expand All @@ -172,13 +171,9 @@ modm::platform::Rcc::enablePll(PllSource source, uint8_t pllM, uint16_t pllN, ui
;

return tmp;
}

%% elif target["family"] in ["g0", "l4", "g4"]
// ----------------------------------------------------------------------------
bool
modm::platform::Rcc::enablePll(PllSource source,
uint8_t pllM, uint16_t pllN, uint8_t pllR, uint32_t waitCycles)
{

// Read reserved values and clear all other values
uint32_t tmp = RCC->PLLCFGR & ~(
RCC_PLLCFGR_PLLSRC | RCC_PLLCFGR_PLLM | RCC_PLLCFGR_PLLN |
Expand All @@ -192,18 +187,18 @@ modm::platform::Rcc::enablePll(PllSource source,
tmp |= static_cast<uint32_t>(source);

// PLLM factor is user defined VCO input frequency must be configured between 4MHz and 16Mhz
tmp |= (uint32_t(pllM - 1) << RCC_PLLCFGR_PLLM_Pos) & RCC_PLLCFGR_PLLM;
tmp |= (uint32_t(pllFactors.pllM - 1) << RCC_PLLCFGR_PLLM_Pos) & RCC_PLLCFGR_PLLM;

// PLLN factor is user defined: between 64 and 344 MHz
tmp |= (uint32_t(pllN) << RCC_PLLCFGR_PLLN_Pos) & RCC_PLLCFGR_PLLN;
tmp |= (uint32_t(pllFactors.pllN) << RCC_PLLCFGR_PLLN_Pos) & RCC_PLLCFGR_PLLN;

// PLLR divider for CPU frequency
%% if target["family"] in ["g0"]
tmp |= ((uint32_t(pllR) - 1) << RCC_PLLCFGR_PLLR_Pos) & RCC_PLLCFGR_PLLR;
tmp |= ((uint32_t(pllFactors.pllR) - 1) << RCC_PLLCFGR_PLLR_Pos) & RCC_PLLCFGR_PLLR;
// PLLP divider for P frequency
// tmp |= ((uint32_t(pllP) - 1) << RCC_PLLCFGR_PLLP_Pos) & RCC_PLLCFGR_PLLP;
%% else
tmp |= ((uint32_t(pllR / 2) - 1) << RCC_PLLCFGR_PLLR_Pos) & RCC_PLLCFGR_PLLR;
tmp |= ((uint32_t(pllFactors.pllR / 2) - 1) << RCC_PLLCFGR_PLLR_Pos) & RCC_PLLCFGR_PLLR;
// PLLQ (21) divider for USB frequency; (00: PLLQ = 2, 01: PLLQ = 4, etc.)
// tmp |= (((uint32_t) (pllQ / 2) - 1) << RCC_PLLCFGR_PLLQ_Pos) & RCC_PLLCFGR_PLLQ;
// enable pll USB clock output
Expand All @@ -222,18 +217,15 @@ modm::platform::Rcc::enablePll(PllSource source,
;

return tmp;
}

%% elif target["family"] in ["l1"]
// ----------------------------------------------------------------------------
bool
modm::platform::Rcc::enablePll(PllSource source, PllMultiplier pllMul, uint8_t pllDiv, uint32_t waitCycles)
{

uint32_t tmp = RCC->CFGR & ~(RCC_CFGR_PLLMUL | RCC_CFGR_PLLSRC | RCC_CFGR_PLLDIV);
// PLLSRC source for pll
tmp |= static_cast<uint32_t>(source);
// Pll multiplication factor
tmp |= static_cast<uint32_t>(pllMul);
tmp |= (static_cast<uint32_t>(pllDiv - 1) << RCC_CFGR_PLLDIV_Pos) & RCC_CFGR_PLLDIV;
tmp |= static_cast<uint32_t>(pllFactors.pllMul);
tmp |= (static_cast<uint32_t>(pllFactors.pllDiv - 1) << RCC_CFGR_PLLDIV_Pos) & RCC_CFGR_PLLDIV;
RCC->CFGR = tmp;

// enable pll
Expand All @@ -242,19 +234,10 @@ modm::platform::Rcc::enablePll(PllSource source, PllMultiplier pllMul, uint8_t p
;

return tmp;
}
%% else
// ----------------------------------------------------------------------------
bool
modm::platform::Rcc::enablePll(PllSource source,
%% if pllprediv2
uint8_t pllMul, uint8_t pllPrediv, uint8_t pllPrediv2, uint32_t waitCycles)
%% elif pllprediv
uint8_t pllMul, uint8_t pllPrediv, uint32_t waitCycles)


%% else
uint8_t pllMul, uint32_t waitCycles)
%% endif
{

%% set pullmul = 'RCC_CFGR_PLLMULL' if target["family"] == "f1" else 'RCC_CFGR_PLLMUL'
// Read reserved values and clear all other values
%% if usbprescaler
Expand All @@ -270,20 +253,20 @@ modm::platform::Rcc::enablePll(PllSource source,
tmp |= static_cast<uint32_t>(source);

// Pll multiplication factor
tmp |= (static_cast<uint32_t>(pllMul - 2) << 18) & {{pullmul}};
tmp |= (static_cast<uint32_t>(pllFactors.pllMul - 2) << 18) & {{pullmul}};

%% if pllprediv
%% set mask = 'RCC_CFGR2_PREDIV1' if target["family"] == "f1" else 'RCC_CFGR2_PREDIV'
#ifdef {{mask}}
// HSE PREDIV division factor
RCC->CFGR2 = (RCC->CFGR2 & ~({{mask}})) | (uint32_t(pllPrediv - 1) & {{mask}});
RCC->CFGR2 = (RCC->CFGR2 & ~({{mask}})) | (uint32_t(pllFactors.pllPrediv - 1) & {{mask}});
#else
if (uint32_t(pllPrediv - 1) & 0x1) tmp |= RCC_CFGR_PLLXTPRE;
if (uint32_t(pllFactors.pllPrediv - 1) & 0x1) tmp |= RCC_CFGR_PLLXTPRE;
#endif
%% endif
RCC->CFGR = tmp;
%% if pllprediv2
RCC->CFGR2 = (RCC->CFGR2 & ~(RCC_CFGR2_PREDIV2)) | ((uint32_t(pllPrediv2 - 1) << 4) & RCC_CFGR2_PREDIV2);
RCC->CFGR2 = (RCC->CFGR2 & ~(RCC_CFGR2_PREDIV2)) | ((uint32_t(pllFactors.pllPrediv2 - 1) << 4) & RCC_CFGR2_PREDIV2);
%% endif
// enable pll
RCC->CR |= RCC_CR_PLLON;
Expand All @@ -292,8 +275,8 @@ modm::platform::Rcc::enablePll(PllSource source,
;

return tmp;
}
%%endif
}

// ----------------------------------------------------------------------------
bool
Expand Down
131 changes: 124 additions & 7 deletions src/modm/platform/clock/stm32/rcc.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,93 @@ public:
static bool
enableLowSpeedExternalCrystal(uint32_t waitCycles = 2048);

// plls
/**
%% if target["family"] in ["f2", "f4", "f7", "l4", "g0", "g4"]
* \code
* VCO input frequency = PLL input clock frequency / PLLM [with 2 <= PLLM <= 63]
* VCO output frequency = VCO input frequency × PLLN [with 64 <= PLLN <= 432]
* \endcode
*
* \param pllM
* Division factor for the main PLL (PLL) and
* audio PLL (PLLI2S) input clock (with 2 <= pllM <= 63).
* The software has to set these bits correctly to ensure
* that frequency of selected source divided by pllM
* is in ranges from 1 to 2 MHz.
*
* \param pllN
* Main PLL (PLL) multiplication factor for VCO (with 64 <= pllN <= 432).
* The software has to set these bits correctly to ensure
* that the VCO output frequency is
* - 336 MHz for ST32F4. Core will run at 168 MHz.
* - 240 MHz for ST32F2. Core will run at 120 MHz.
*
%% if target["family"] in ["l4", "g0", "g4"]
* \param pllR
*
%% else
* \param pllP
*
%% endif
%% elif target["family"] in ["l1"]
* \param pllMul
*
* \param pllDiv
*
%% else
* \param pllMul
*
%% if pllprediv2
* \param pllPrediv
*
* \param pllPrediv2
*
%% elif pllprediv
* \param pllPrediv
*
%% endif
%% endif
*/
struct PllFactors
{
%% if target["family"] in ["f2", "f4", "f7", "l4", "g0", "g4"]
const uint8_t pllM;
const uint16_t pllN;
%% if target["family"] in ["l4", "g0", "g4"]
const uint8_t pllR;
%% else
const uint8_t pllP;
%% endif
%% elif target["family"] in ["l1"]
const PllMultiplier pllMul;
const uint8_t pllDiv;
%% else
uint8_t pllMul;
%% if pllprediv2
const uint8_t pllPrediv;
const uint8_t pllPrediv2;
%% elif pllprediv
const uint8_t pllPrediv;
%% endif
%% endif
};

/**
* Enable PLL.
*
* \param source
* Source select for PLL. If you are using HSE you must
* enable it first (see enableHse()).
*
* \param factors
* Struct with all pll factors. \see PllFactors.
*
* \param waitCycles
* Number of cycles to wait for the pll to stabilise. Default: 2048.
*/
static bool
enablePll(PllSource source, const PllFactors& pllFactors, uint32_t waitCycles = 2048);

%% if target["family"] in ["f2", "f4", "f7", "l4", "g0", "g4"]
/**
* Enable PLL.
Expand Down Expand Up @@ -338,28 +424,59 @@ public:
* Example:
*
*/
static bool
[[deprecated("Use PllFactors as argument instead")]] static bool
enablePll(PllSource source, uint8_t pllM, uint16_t pllN,
%% if target["family"] in ["l4", "g0", "g4"]
uint8_t pllR,
%% else
uint8_t pllP,
%% endif
uint32_t waitCycles = 2048);
uint32_t waitCycles = 2048)
{
PllFactors pllFactors{
.pllM = pllM,
.pllN = pllN,
%% if target["family"] in ["l4", "g0", "g4"]
.pllR = pllR,
%% else
.pllP = pllP,
%% endif
};
return enablePll(source, pllFactors, waitCycles);
}
%% elif target["family"] in ["l1"]
static bool
[[deprecated("Use PllFactors as argument instead")]] static bool
enablePll(PllSource source, PllMultiplier pllMul, uint8_t pllDiv,
uint32_t waitCycles = 2048);
uint32_t waitCycles = 2048)
{
PllFactors pllFactors{
.pllMul = pllMul,
.pllDiv = pllDiv,
};
return enablePll(source, pllFactors, waitCycles);
}
%% else
static bool
[[deprecated("Use PllFactors as argument instead")]] static bool
enablePll(PllSource source,
uint8_t pllMul,
%% if pllprediv2
uint8_t pllPrediv, uint8_t pllPrediv2,
%% elif pllprediv
uint8_t pllPrediv,
%% endif
uint32_t waitCycles = 2048);
uint32_t waitCycles = 2048)
{
PllFactors pllFactors{
.pllMul = pllMul,
%% if pllprediv2
.pllPrediv = pllPrediv,
.pllPrediv2 = pllPrediv2,
%% elif pllprediv
.pllPrediv = pllPrediv,
%% endif
};
return enablePll(source, pllFactors, waitCycles);
}
%% endif

// sinks
Expand Down

0 comments on commit e3ba913

Please sign in to comment.