Skip to content

Commit 4826ca8

Browse files
committed
[I2S] Setup PLL for the I2S peripheral
Functions are added to be able to set up the I2S PLL at startup. PLL multipliers are taken over from ST's example: STM32F4-Discovery_FW_V1.1.0/Project/Audio_playback_and_record/src/system_stm32f4xx.c
1 parent e0d1327 commit 4826ca8

File tree

3 files changed

+56
-2
lines changed

3 files changed

+56
-2
lines changed

src/modm/board/disco_f407vg/board.hpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,17 @@ struct SystemClock {
8282
{
8383
Rcc::enableExternalCrystal(); // 8MHz
8484
const Rcc::PllFactors pllFactors{
85-
.pllM = 4, // 8MHz / M=4 -> 2MHz
86-
.pllN = 168, // 2MHz * N=168 -> 336MHz
85+
.pllM = 8, // 8MHz / M=8 -> 1MHz
86+
.pllN = 336, // 1MHz * N=336 -> 336MHz
8787
.pllP = 2, // 336MHz / P=2 -> 168MHz = F_cpu
8888
.pllQ = 7 // 336MHz / Q=7 -> 48MHz = F_usb
8989
};
9090
Rcc::enablePll(Rcc::PllSource::ExternalCrystal, pllFactors);
91+
const Rcc::PllI2sFactors pllI2sFactors{
92+
.pllN = 258, // 1 MHz * N=258 -> 258 MHz
93+
.pllR = 3 // 258 MHz / R=3 -> 86 MHz
94+
};
95+
Rcc::enablePllI2s(Rcc::PllSource::ExternalCrystal, pllI2sFactors, 2048);
9196
// set flash latency for 168MHz
9297
Rcc::setFlashLatency<Frequency>();
9398
// switch system clock to PLL output

src/modm/platform/clock/stm32/rcc.cpp.in

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,29 @@ modm::platform::Rcc::enablePll(PllSource source, const PllFactors& pllFactors, u
290290
%%endif
291291
}
292292

293+
%% if target["family"] == "f4"
294+
bool
295+
modm::platform::Rcc::enablePllI2s(PllSource, const PllI2sFactors& pllFactors, uint32_t waitCycles)
296+
{
297+
// Read reserved and don't care values and clear all other values
298+
uint32_t tmp = RCC->PLLI2SCFGR & ~(RCC_PLLI2SCFGR_PLLI2SN | RCC_PLLI2SCFGR_PLLI2SR);
299+
// set PLL divider and multiplier
300+
tmp |= (((uint32_t) pllFactors.pllN) << RCC_PLLI2SCFGR_PLLI2SN_Pos) & RCC_PLLI2SCFGR_PLLI2SN;
301+
tmp |= (((uint32_t) pllFactors.pllR) << RCC_PLLI2SCFGR_PLLI2SR_Pos) & RCC_PLLI2SCFGR_PLLI2SR;
302+
RCC->PLLI2SCFGR = tmp;
303+
304+
// enable I2S PLL
305+
RCC->CR |= RCC_CR_PLLI2SON;
306+
// wait till I2S PLL gets ready or time is up
307+
while ((RCC->CR & RCC_CR_PLLI2SRDY) == 0)
308+
{
309+
if (not --waitCycles)
310+
return false;
311+
}
312+
return true;
313+
}
314+
%% endif
315+
293316
%% if pllsai_p_usb
294317
bool
295318
modm::platform::Rcc::enablePllSai(const PllSaiFactors& pllFactors, uint32_t waitCycles)

src/modm/platform/clock/stm32/rcc.hpp.in

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -559,6 +559,32 @@ public:
559559
setHsiPredivider4Enabled(bool divideBy4, uint32_t waitCycles = 2048);
560560
%% endif
561561

562+
%% if target["family"] == "f4"
563+
/** TODO: comments
564+
* input clock is the HSE or HSI divided by M
565+
* f(VCO clock) = f(PLLI2S clock input) × (PLLI2SN / PLLM)
566+
* f(PLL I2S clock output) = f(VCO clock) / PLLI2SR
567+
*
568+
* \param pllN
569+
* PLLI2S multiplication factor for VCO
570+
* 50 <= PLLI2SN <= 432
571+
*
572+
* \param pllR
573+
* PLLI2S division factor for I2S clocks
574+
* Caution: The I2Ss requires a frequency lower than or equal to 192 MHz to work correctly.
575+
* 2 <= PLLR <= 7
576+
*/
577+
struct PllI2sFactors
578+
{
579+
const uint16_t pllN;
580+
const uint16_t pllR;
581+
};
582+
583+
/* TODO: comments */
584+
static bool
585+
enablePllI2s(PllSource, const PllI2sFactors& pllFactors, uint32_t waitCycles);
586+
%% endif
587+
562588
// sinks
563589
static bool
564590
enableSystemClock(SystemClockSource src, uint32_t waitCycles = 2048);

0 commit comments

Comments
 (0)