Skip to content

Commit ce056cd

Browse files
committed
Added PLL management on STM32L0
1 parent e2dbe5f commit ce056cd

2 files changed

Lines changed: 125 additions & 72 deletions

File tree

include/clock.h

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ typedef enum _Clock_PLLPrescaler
372372

373373
typedef enum _Clock_PLLMultiplier
374374
{
375+
#if defined (LIBOHIBOARD_STM32L4) || defined (LIBOHIBOARD_STM32WB)
375376
CLOCK_PLLMULTIPLIER_8 = 8,
376377
CLOCK_PLLMULTIPLIER_9 = 9,
377378
CLOCK_PLLMULTIPLIER_10 = 10,
@@ -452,6 +453,19 @@ typedef enum _Clock_PLLMultiplier
452453
CLOCK_PLLMULTIPLIER_85 = 85,
453454
CLOCK_PLLMULTIPLIER_86 = 86,
454455

456+
#elif defined (LIBOHIBOARD_STM32L0)
457+
458+
CLOCK_PLLMULTIPLIER_3 = 0,
459+
CLOCK_PLLMULTIPLIER_4 = 1,
460+
CLOCK_PLLMULTIPLIER_6 = 2,
461+
CLOCK_PLLMULTIPLIER_8 = 3,
462+
CLOCK_PLLMULTIPLIER_12 = 4,
463+
CLOCK_PLLMULTIPLIER_16 = 5,
464+
CLOCK_PLLMULTIPLIER_24 = 6,
465+
CLOCK_PLLMULTIPLIER_32 = 7,
466+
CLOCK_PLLMULTIPLIER_48 = 8,
467+
468+
#endif
455469
} Clock_PLLMultiplier;
456470

457471
#if defined (LIBOHIBOARD_STM32L4) || defined (LIBOHIBOARD_STM32WB)
@@ -495,6 +509,19 @@ typedef struct _Clock_PLLConfig
495509

496510
#endif
497511

512+
#if defined (LIBOHIBOARD_STM32L0)
513+
514+
typedef enum _Clock_PLLDivider
515+
{
516+
CLOCK_PLLDIVIDER_NO = 0,
517+
CLOCK_PLLDIVIDER_2 = 1,
518+
CLOCK_PLLDIVIDER_3 = 2,
519+
CLOCK_PLLDIVIDER_4 = 3,
520+
521+
} Clock_PLLDivider;
522+
523+
#endif
524+
498525
typedef enum _Clock_McoDivider
499526
{
500527
CLOCK_MCODIVIDER_1 = 0,
@@ -624,6 +651,11 @@ typedef struct _Clock_Config
624651
Clock_PLLConfig pllSai2;
625652
#endif
626653

654+
#if defined (LIBOHIBOARD_STM32L0)
655+
Clock_PLLMultiplier pllMultiplier;
656+
Clock_PLLDivider pllDivider;
657+
#endif
658+
627659
Clock_McoDivider mcoPrescaler;
628660
Clock_McoSource mcoSource;
629661

source/STM32L0/clock_STM32L0.c

Lines changed: 93 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,8 @@ static const uint32_t CLOCK_MSI_RANGE[] =
195195
4194000,
196196
};
197197

198+
static const uint32_t CLOCK_PLL_MULTIPLIER[] = {3, 4, 6, 8, 12, 16, 24, 32, 48};
199+
static const uint32_t CLOCK_PLL_DIVIDER[] = {1, 2, 3, 4};
198200

199201
typedef struct _Clock_Device
200202
{
@@ -261,7 +263,7 @@ static System_Errors Clock_deInit (void);
261263
*
262264
* @return value of PLL source clock.
263265
*/
264-
//static uint32_t Clock_getActualPllInputValue (void);
266+
static uint32_t Clock_getActualPllInputValue (void);
265267

266268
/**
267269
* Return the source clock of PLL set in configuration struct.
@@ -270,7 +272,7 @@ static System_Errors Clock_deInit (void);
270272
*
271273
* @return value of source clock of PLL.
272274
*/
273-
//static uint32_t Clock_getConfigPllValue (Clock_Config *config, Clock_PLLConfig *pllConfig);
275+
static uint32_t Clock_getConfigPllValue (Clock_Config *config);
274276

275277
/**
276278
* Return the clock set for MSI in configuration struct.
@@ -320,14 +322,16 @@ static uint32_t Clock_getActualSystemValue (void)
320322
// case CLOCK_SYSTEMSOURCESWS_HSE:
321323
// systemClock = clk0.externalClock;
322324
// break;
323-
// case CLOCK_SYSTEMSOURCESWS_PLL:
324-
// {
325-
// uint32_t pllmClock = Clock_getActualPllInputValue();
326-
// uint32_t pllnReg = UTILITY_READ_REGISTER_BIT(clk0.regmap->PLLCFGR, RCC_PLLCFGR_PLLN_Msk) >> RCC_PLLCFGR_PLLN_Pos;
327-
// uint32_t pllrReg = UTILITY_READ_REGISTER_BIT(clk0.regmap->PLLCFGR, RCC_PLLCFGR_PLLR_Msk) >> RCC_PLLCFGR_PLLR_Pos;
328-
// systemClock = (((pllmClock) * pllnReg) / ((pllrReg + 1) * 2));
329-
// }
330-
// break;
325+
case CLOCK_SYSTEMSOURCESWS_PLL:
326+
{
327+
uint32_t pllClock = Clock_getActualPllInputValue();
328+
329+
uint32_t mult = UTILITY_READ_REGISTER_BIT(clk.regmap->CFGR, RCC_CFGR_PLLMUL_Msk) >> RCC_CFGR_PLLMUL_Pos;
330+
uint32_t div = UTILITY_READ_REGISTER_BIT(clk.regmap->CFGR, RCC_CFGR_PLLDIV_Msk) >> RCC_CFGR_PLLDIV_Pos;
331+
332+
systemClock = (((pllClock) * CLOCK_PLL_MULTIPLIER[mult]) / (CLOCK_PLL_DIVIDER[div]));
333+
}
334+
break;
331335
}
332336

333337
return systemClock;
@@ -593,6 +597,54 @@ static System_Errors Clock_oscillatorConfig (Clock_Config* config)
593597
}
594598
}
595599

600+
if (config->sysSource == CLOCK_SYSTEMSOURCE_PLL)
601+
{
602+
if (config->pllState == CLOCK_OSCILLATORSTATE_ON)
603+
{
604+
// Disable the PLL by setting PLLON to 0 in Clock control register (RCC_CR).
605+
UTILITY_CLEAR_REGISTER_BIT(clk.regmap->CR,RCC_CR_PLLON);
606+
// Wait until PLLRDY is cleared. The PLL is now fully stopped.
607+
tickstart = System_currentTick();
608+
while (UTILITY_READ_REGISTER_BIT(clk.regmap->CR, RCC_CR_PLLRDY) == 1)
609+
{
610+
// 2ms minimum
611+
if ((System_currentTick() - tickstart) > 20u)
612+
return ERRORS_CLOCK_TIMEOUT;
613+
}
614+
615+
// FIXME: Some check on parameters validity!
616+
617+
// Change the desired parameter.
618+
UTILITY_MODIFY_REGISTER(clk.regmap->CFGR, RCC_CFGR_PLLSRC_Msk, (config->pllSource << RCC_CFGR_PLLSRC_Pos));
619+
UTILITY_MODIFY_REGISTER(clk.regmap->CFGR, RCC_CFGR_PLLMUL_Msk, (config->pllMultiplier << RCC_CFGR_PLLMUL_Pos));
620+
UTILITY_MODIFY_REGISTER(clk.regmap->CFGR, RCC_CFGR_PLLDIV_Msk, (config->pllDivider << RCC_CFGR_PLLDIV_Pos));
621+
622+
// Enable the PLL again by setting PLLON to 1.
623+
UTILITY_SET_REGISTER_BIT(clk.regmap->CR,RCC_CR_PLLON);
624+
625+
// Wait until PLLRDY is cleared. The PLL is now fully started.
626+
tickstart = System_currentTick();
627+
while (UTILITY_READ_REGISTER_BIT(clk.regmap->CR, RCC_CR_PLLRDY) == 1)
628+
{
629+
// 2ms minimum
630+
if ((System_currentTick() - tickstart) > 20u)
631+
return ERRORS_CLOCK_TIMEOUT;
632+
}
633+
}
634+
else
635+
{
636+
// Disable the PLL by setting PLLON to 0 in Clock control register (RCC_CR).
637+
UTILITY_CLEAR_REGISTER_BIT(clk.regmap->CR,RCC_CR_PLLON);
638+
// Wait until PLLRDY is cleared. The PLL is now fully stopped.
639+
tickstart = System_currentTick();
640+
while (UTILITY_READ_REGISTER_BIT(clk.regmap->CR, RCC_CR_PLLRDY) == 1)
641+
{
642+
// 2ms minimum
643+
if ((System_currentTick() - tickstart) > 20u)
644+
return ERRORS_CLOCK_TIMEOUT;
645+
}
646+
}
647+
}
596648
// UTILITY_MODIFY_REGISTER(clk.regmap->CFGR, RCC_CFGR_MCOSEL_Msk, (config->mcoSource << RCC_CFGR_MCOSEL_Pos));
597649
// UTILITY_MODIFY_REGISTER(clk.regmap->CFGR, RCC_CFGR_MCOPRE_Msk, (config->mcoPrescaler << RCC_CFGR_MCOPRE_Pos));
598650

@@ -610,13 +662,13 @@ static System_Errors Clock_outputConfig (Clock_Config* config)
610662
// PLL is selected as sys clock
611663
if (config->sysSource == CLOCK_SYSTEMSOURCE_PLL)
612664
{
613-
// // Check if the source is ready
614-
// if (UTILITY_READ_REGISTER_BIT(clk0.regmap->CR,RCC_CR_PLLRDY) == 0)
615-
// {
616-
// return ERRORS_CLOCK_PLL_NOT_READY;
617-
// }
618-
//
619-
// cfgrSW = RCC_CFGR_SW_PLL;
665+
// Check if the source is ready
666+
if (UTILITY_READ_REGISTER_BIT(clk.regmap->CR,RCC_CR_PLLRDY) == 0)
667+
{
668+
return ERRORS_CLOCK_PLL_NOT_READY;
669+
}
670+
671+
cfgrSW = RCC_CFGR_SW_PLL;
620672
}
621673
else if (config->sysSource == CLOCK_SYSTEMSOURCE_HSI)
622674
{
@@ -1321,42 +1373,14 @@ uint32_t Clock_getConfigOscillatorValue (Clock_Config *config)
13211373
#endif
13221374
break;
13231375
case CLOCK_SYSTEMSOURCE_PLL:
1324-
// systemClock = Clock_getConfigPllValue(config, &config->pll);
1376+
systemClock = Clock_getConfigPllValue(config);
13251377
break;
13261378
}
13271379

13281380
return systemClock;
13291381
}
13301382

1331-
#if 0
1332-
static uint32_t Clock_getActualPllInputValue(void)
1333-
{
1334-
uint32_t baseClock = 0, pllmClock = 0;
1335-
Clock_PllSource pllSource = (Clock_PllSource)(UTILITY_READ_REGISTER_BIT(clk0.regmap->PLLCFGR, RCC_PLLCFGR_PLLSRC_Msk));
1336-
uint32_t pllmReg = UTILITY_READ_REGISTER_BIT(clk0.regmap->PLLCFGR, RCC_PLLCFGR_PLLM_Msk) >> RCC_PLLCFGR_PLLM_Pos;
1337-
1338-
switch (pllSource)
1339-
{
1340-
default:
1341-
case CLOCK_PLLSOURCE_NONE:
1342-
baseClock = 0;
1343-
break;
1344-
case CLOCK_PLLSOURCE_MSI:
1345-
baseClock = Clock_getActualMsiValue();
1346-
break;
1347-
case CLOCK_PLLSOURCE_HSI:
1348-
baseClock = CLOCK_FREQ_HSI;
1349-
break;
1350-
case CLOCK_PLLSOURCE_HSE:
1351-
baseClock = clk0.externalClock;
1352-
break;
1353-
}
1354-
1355-
pllmClock = ((baseClock) / (pllmReg + 1));
1356-
return pllmClock;
1357-
}
1358-
1359-
static uint32_t Clock_getConfigPllValue (Clock_Config* config, Clock_PLLConfig *pllConfig)
1383+
static uint32_t Clock_getConfigPllValue (Clock_Config* config)
13601384
{
13611385
uint32_t base = 0, frequency = 0;
13621386

@@ -1366,47 +1390,44 @@ static uint32_t Clock_getConfigPllValue (Clock_Config* config, Clock_PLLConfig *
13661390
case CLOCK_PLLSOURCE_NONE:
13671391
return 0;
13681392

1369-
case CLOCK_PLLSOURCE_MSI:
1370-
base = Clock_msiRange[config->msiRange];
1371-
break;
1372-
13731393
case CLOCK_PLLSOURCE_HSI:
13741394
base = CLOCK_FREQ_HSI;
13751395
break;
1376-
1377-
case CLOCK_PLLSOURCE_HSE:
1378-
base = clk0.externalClock;
1379-
break;
13801396
}
13811397

13821398
frequency = base / (config->pllPrescaler + 1);
1383-
frequency *= pllConfig->multiplier;
13841399

1385-
switch (pllConfig->dividerR)
1386-
{
1387-
case CLOCK_PLLDIVIDER_R_2:
1388-
frequency /= 2;
1389-
break;
1400+
frequency *= CLOCK_PLL_MULTIPLIER[config->pllMultiplier];
1401+
frequency /= CLOCK_PLL_DIVIDER[config->pllDivider];
13901402

1391-
case CLOCK_PLLDIVIDER_R_4:
1392-
frequency /= 4;
1393-
break;
1403+
return frequency;
1404+
}
13941405

1395-
case CLOCK_PLLDIVIDER_R_6:
1396-
frequency /= 6;
1397-
break;
1406+
static uint32_t Clock_getActualPllInputValue (void)
1407+
{
1408+
uint32_t baseClock = 0, pllmClock = 0;
1409+
Clock_PllSource pllSource = (Clock_PllSource)(UTILITY_READ_REGISTER_BIT(clk.regmap->CFGR, RCC_CFGR_PLLSRC_Msk));
13981410

1411+
//uint32_t pre = UTILITY_READ_REGISTER_BIT(clk.regmap->CFGR, RCC_CFGR_PLLMUL_Msk) >> RCC_CFGR_PLLMUL_Pos;
1412+
//uint32_t mult = UTILITY_READ_REGISTER_BIT(clk.regmap->CFGR, RCC_CFGR_PLLMUL_Msk) >> RCC_CFGR_PLLMUL_Pos;
1413+
//uint32_t div = UTILITY_READ_REGISTER_BIT(clk.regmap->CFGR, RCC_CFGR_PLLDIV_Msk) >> RCC_CFGR_PLLDIV_Pos;
1414+
1415+
switch (pllSource)
1416+
{
13991417
default:
1400-
case CLOCK_PLLDIVIDER_R_8:
1401-
frequency /= 8;
1418+
case CLOCK_PLLSOURCE_NONE:
1419+
baseClock = 0;
1420+
break;
1421+
case CLOCK_PLLSOURCE_HSI:
1422+
baseClock = CLOCK_FREQ_HSI;
14021423
break;
14031424
}
14041425

1405-
return frequency;
1426+
//pllmClock = ((baseClock) / (pllmReg + 1));
1427+
//return pllmClock;
1428+
return baseClock;
14061429
}
14071430

1408-
#endif
1409-
14101431
#endif // LIBOHIBOARD_STM32L0
14111432

14121433
#ifdef __cplusplus

0 commit comments

Comments
 (0)