Skip to content

Commit 94a3a72

Browse files
twasilczyksalkinium
authored andcommitted
Implement clock support for SAMV
1 parent bcba5eb commit 94a3a72

File tree

9 files changed

+601
-315
lines changed

9 files changed

+601
-315
lines changed

src/modm/platform/clock/sam/gclk.hpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,9 @@ ClockGenerator : uint32_t
3535
Internal8M = 3,
3636
};
3737

38-
enum class ClockPeripheral : uint32_t {
38+
enum class
39+
ClockPeripheral : uint32_t
40+
{
3941
Dfll48 = GCLK_CLKCTRL_ID_DFLL48_Val,
4042
Fdpll = GCLK_CLKCTRL_ID_FDPLL_Val,
4143
Fdpll32K = GCLK_CLKCTRL_ID_FDPLL32K_Val,
Lines changed: 59 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/**
22
* Copyright (c) 2021, Jeff McBride
3+
* Copyright (c) 2021, Tomasz Wasilczyk
34
*
45
* This file is part of the modm project.
56
*
@@ -12,18 +13,19 @@
1213
#include "clockgen.hpp"
1314
#include <cmath>
1415

15-
1616
// CMSIS Core compliance
17-
uint32_t modm_fastdata SystemCoreClock(8000000);
17+
constinit uint32_t modm_fastdata SystemCoreClock(modm::platform::ClockGen::BootFrequency);
1818
modm_weak void SystemCoreClockUpdate() { /* Nothing to update */ }
1919

2020
namespace modm::platform
2121
{
22-
uint16_t modm_fastdata delay_fcpu_MHz = computeDelayMhz(8'000'000);
23-
uint16_t modm_fastdata delay_ns_per_loop = computeDelayNsPerLoop(8'000'000);
22+
constinit uint16_t modm_fastdata delay_fcpu_MHz = computeDelayMhz(ClockGen::BootFrequency);
23+
constinit uint16_t modm_fastdata delay_ns_per_loop = computeDelayNsPerLoop(ClockGen::BootFrequency);
2424

2525

26-
static uint16_t divFromMasterClkPrescaler(MasterClkPrescaler pres) {
26+
static constexpr uint16_t
27+
divFromMasterClkPrescaler(MasterClkPrescaler pres)
28+
{
2729
switch(pres) {
2830
case MasterClkPrescaler::CLK_1:
2931
return 1;
@@ -46,76 +48,91 @@ static uint16_t divFromMasterClkPrescaler(MasterClkPrescaler pres) {
4648
}
4749
}
4850

49-
void ClockGen::enableExternal32Khz(bool crystal_bypass) {
50-
if(crystal_bypass) {
51-
SUPC->SUPC_MR |= SUPC_MR_OSCBYPASS;
52-
}
53-
51+
void
52+
ClockGen::enableExternal32Khz(bool crystal_bypass)
53+
{
54+
if (crystal_bypass) SUPC->SUPC_MR |= SUPC_MR_OSCBYPASS;
5455
SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL;
5556
}
5657

57-
58-
59-
60-
uint32_t ClockGen::masterClkFrequency() {
58+
uint32_t
59+
ClockGen::masterClkFrequency()
60+
{
6161
uint32_t mckr = PMC->PMC_MCKR;
6262
MasterClkSource src = (MasterClkSource)((mckr & PMC_MCKR_CSS_Msk) >> PMC_MCKR_CSS_Pos);
6363
MasterClkPrescaler pres = (MasterClkPrescaler)((mckr & PMC_MCKR_PRES_Msk) >> PMC_MCKR_PRES_Pos);
6464
uint32_t div = divFromMasterClkPrescaler(pres);
65-
switch(src) {
65+
switch(src)
66+
{
6667
case MasterClkSource::SLOW_CLK:
6768
return SlowClkFreqHz / div;
6869
case MasterClkSource::MAIN_CLK:
6970
return mainClkFrequency() / div;
7071
case MasterClkSource::PLLA_CLK:
7172
return pllAFrequency() / div;
73+
%% if target.family in ["g"]
7274
case MasterClkSource::PLLB_CLK:
7375
return pllBFrequency() / div;
76+
%% elif target.family in ["v"]
77+
case MasterClkSource::UPLL_CLK:
78+
return 240'000'000; // UPLLDIV2
79+
%% endif
7480
default:
7581
return 0;
7682
}
7783
}
7884

79-
uint32_t ClockGen::mainClkFrequency() {
85+
uint32_t
86+
ClockGen::mainClkFrequency()
87+
{
8088
// NOTE: This does not support external main clk. To add this, we'll need
8189
// a way for user supplied input frequency. For now, this assumes we're
8290
// using the internal RC for main clock.
8391
uint32_t moscrcf = (PMC->CKGR_MOR & CKGR_MOR_MOSCRCF_Msk) >> CKGR_MOR_MOSCRCF_Pos;
84-
if(moscrcf == (uint32_t)MainInternalFreq::Rc8Mhz) {
85-
return 8'000'000;
86-
} else if(moscrcf == (uint32_t)MainInternalFreq::Rc16Mhz) {
87-
return 16'000'000;
88-
} else if(moscrcf == (uint32_t)MainInternalFreq::Rc24Mhz) {
89-
return 24'000'000;
90-
} else {
91-
return 0;
92-
}
92+
const auto freq = MainInternalFreq(moscrcf);
93+
#ifdef CKGR_MOR_MOSCRCF_4_MHz_Val
94+
if (freq == MainInternalFreq::Rc4Mhz) return 4'000'000;
95+
#endif
96+
#ifdef CKGR_MOR_MOSCRCF_8_MHz_Val
97+
if (freq == MainInternalFreq::Rc8Mhz) return 8'000'000;
98+
#endif
99+
#ifdef CKGR_MOR_MOSCRCF_12_MHz_Val
100+
if (freq == MainInternalFreq::Rc12Mhz) return 12'000'000;
101+
#endif
102+
#ifdef CKGR_MOR_MOSCRCF_16_MHz_Val
103+
if (freq == MainInternalFreq::Rc16Mhz) return 16'000'000;
104+
#endif
105+
#ifdef CKGR_MOR_MOSCRCF_24_MHz_Val
106+
if (freq == MainInternalFreq::Rc24Mhz) return 24'000'000;
107+
#endif
108+
return 0;
93109
}
94110

95-
uint32_t ClockGen::pllAFrequency() {
111+
uint32_t
112+
ClockGen::pllAFrequency()
113+
{
96114
uint32_t mul = ((PMC->CKGR_PLLAR & CKGR_PLLAR_MULA_Msk) >> CKGR_PLLAR_MULA_Pos) + 1;
115+
%% if target.family in ["g"]
97116
uint32_t freq = SlowClkFreqHz * mul;
98-
if(PMC->PMC_MCKR & PMC_MCKR_PLLADIV2) {
99-
freq /= 2;
100-
}
117+
if(PMC->PMC_MCKR & PMC_MCKR_PLLADIV2) freq /= 2;
118+
%% elif target.family in ["v"]
119+
uint32_t freq = mainClkFrequency() * mul;
120+
const auto diva = ((PMC->CKGR_PLLAR & CKGR_PLLAR_DIVA_Msk) >> CKGR_PLLAR_DIVA_Pos);
121+
if (diva == 0) return 0; // PLLA is disabled
122+
freq /= diva;
123+
%% endif
101124
return freq;
102125
}
103126

104-
uint32_t ClockGen::pllBFrequency() {
127+
%% if target.family in ["g"]
128+
uint32_t
129+
ClockGen::pllBFrequency()
130+
{
105131
uint32_t mul = ((PMC->CKGR_PLLBR & CKGR_PLLBR_MULB_Msk) >> CKGR_PLLBR_MULB_Pos) + 1;
106132
uint32_t freq = SlowClkFreqHz * mul;
107-
if(PMC->PMC_MCKR & PMC_MCKR_PLLBDIV2) {
108-
freq /= 2;
109-
}
133+
if(PMC->PMC_MCKR & PMC_MCKR_PLLBDIV2) freq /= 2;
110134
return freq;
111135
}
136+
%% endif
112137

113-
114-
void ClockGen::setMainInternalFreq(MainInternalFreq freq) {
115-
PMC->CKGR_MOR =
116-
(PMC->CKGR_MOR & ~(CKGR_MOR_MOSCRCF_Msk)) |
117-
CKGR_MOR_MOSCRCF((uint32_t)freq) |
118-
CKGR_MOR_KEY_PASSWD;
119-
}
120-
121-
} // namespace modm::platform
138+
} // namespace modm::platform

src/modm/platform/clock/sam_pmc/clockgen.hpp

Lines changed: 0 additions & 152 deletions
This file was deleted.

0 commit comments

Comments
 (0)