1
1
/**
2
2
* Copyright (c) 2021, Jeff McBride
3
+ * Copyright (c) 2021, Tomasz Wasilczyk
3
4
*
4
5
* This file is part of the modm project.
5
6
*
12
13
#include "clockgen.hpp"
13
14
#include <cmath>
14
15
15
-
16
16
// CMSIS Core compliance
17
- uint32_t modm_fastdata SystemCoreClock (8000000 );
17
+ constinit uint32_t modm_fastdata SystemCoreClock(modm::platform::ClockGen::BootFrequency );
18
18
modm_weak void SystemCoreClockUpdate() { /* Nothing to update */ }
19
19
20
20
namespace modm::platform
21
21
{
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 );
24
24
25
25
26
- static uint16_t divFromMasterClkPrescaler (MasterClkPrescaler pres) {
26
+ static constexpr uint16_t
27
+ divFromMasterClkPrescaler(MasterClkPrescaler pres)
28
+ {
27
29
switch(pres) {
28
30
case MasterClkPrescaler::CLK_1:
29
31
return 1;
@@ -46,76 +48,91 @@ static uint16_t divFromMasterClkPrescaler(MasterClkPrescaler pres) {
46
48
}
47
49
}
48
50
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;
54
55
SUPC->SUPC_CR = SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL;
55
56
}
56
57
57
-
58
-
59
-
60
- uint32_t ClockGen::masterClkFrequency () {
58
+ uint32_t
59
+ ClockGen::masterClkFrequency()
60
+ {
61
61
uint32_t mckr = PMC->PMC_MCKR;
62
62
MasterClkSource src = (MasterClkSource)((mckr & PMC_MCKR_CSS_Msk) >> PMC_MCKR_CSS_Pos);
63
63
MasterClkPrescaler pres = (MasterClkPrescaler)((mckr & PMC_MCKR_PRES_Msk) >> PMC_MCKR_PRES_Pos);
64
64
uint32_t div = divFromMasterClkPrescaler(pres);
65
- switch (src) {
65
+ switch(src)
66
+ {
66
67
case MasterClkSource::SLOW_CLK:
67
68
return SlowClkFreqHz / div;
68
69
case MasterClkSource::MAIN_CLK:
69
70
return mainClkFrequency() / div;
70
71
case MasterClkSource::PLLA_CLK:
71
72
return pllAFrequency() / div;
73
+ %% if target.family in ["g"]
72
74
case MasterClkSource::PLLB_CLK:
73
75
return pllBFrequency() / div;
76
+ %% elif target.family in ["v"]
77
+ case MasterClkSource::UPLL_CLK:
78
+ return 240'000'000; // UPLLDIV2
79
+ %% endif
74
80
default:
75
81
return 0;
76
82
}
77
83
}
78
84
79
- uint32_t ClockGen::mainClkFrequency () {
85
+ uint32_t
86
+ ClockGen::mainClkFrequency()
87
+ {
80
88
// NOTE: This does not support external main clk. To add this, we'll need
81
89
// a way for user supplied input frequency. For now, this assumes we're
82
90
// using the internal RC for main clock.
83
91
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;
93
109
}
94
110
95
- uint32_t ClockGen::pllAFrequency () {
111
+ uint32_t
112
+ ClockGen::pllAFrequency()
113
+ {
96
114
uint32_t mul = ((PMC->CKGR_PLLAR & CKGR_PLLAR_MULA_Msk) >> CKGR_PLLAR_MULA_Pos) + 1;
115
+ %% if target.family in ["g"]
97
116
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
101
124
return freq;
102
125
}
103
126
104
- uint32_t ClockGen::pllBFrequency () {
127
+ %% if target.family in ["g"]
128
+ uint32_t
129
+ ClockGen::pllBFrequency()
130
+ {
105
131
uint32_t mul = ((PMC->CKGR_PLLBR & CKGR_PLLBR_MULB_Msk) >> CKGR_PLLBR_MULB_Pos) + 1;
106
132
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;
110
134
return freq;
111
135
}
136
+ %% endif
112
137
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
0 commit comments