Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[stm32] Clock: pass pll factors as struct #361

Merged
merged 1 commit into from
Mar 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)
rleh marked this conversation as resolved.
Show resolved Hide resolved
{
%% 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