Skip to content

Commit 13a306f

Browse files
committed
proto for board/blue_pill_f103 and board/disco_f411ve
1 parent 54dd9df commit 13a306f

File tree

4 files changed

+205
-48
lines changed

4 files changed

+205
-48
lines changed

src/modm/board/blue_pill_f103/board.hpp

Lines changed: 37 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@
1010
*/
1111
// ----------------------------------------------------------------------------
1212

13-
#ifndef MODM_STM32_F103C8T6_BLUE_PILL_HPP
14-
#define MODM_STM32_F103C8T6_BLUE_PILL_HPP
13+
#pragma once
1514

1615
#include <modm/platform.hpp>
1716
#include <modm/architecture/interface/clock.hpp>
1817

18+
#include "rcc_prototype.hpp"
19+
1920
using namespace modm::platform;
2021

2122
namespace Board
@@ -24,13 +25,38 @@ namespace Board
2425
/// @{
2526
using namespace modm::literals;
2627

27-
/// STM32F103 running at 72MHz generated from the external 8MHz crystal
2828
struct SystemClock
2929
{
30-
static constexpr uint32_t Frequency = 72_MHz;
31-
static constexpr uint32_t Ahb = Frequency;
32-
static constexpr uint32_t Apb1 = Frequency / 2;
33-
static constexpr uint32_t Apb2 = Frequency;
30+
static constexpr uint32_t ExternalCrystalClock = 8_MHz;
31+
32+
static constexpr Rcc::PllFactors pllFactors{
33+
.pllMul = 9,
34+
.usbPrediv = Rcc::UsbPrescaler::Div1_5
35+
};
36+
static constexpr Rcc::AhbPrescaler Ahb_pre = Rcc::AhbPrescaler::Div1;
37+
static constexpr Rcc::Apb1Prescaler Apb1_pre = Rcc::Apb1Prescaler::Div2;
38+
static constexpr Rcc::Apb2Prescaler Apb2_pre = Rcc::Apb2Prescaler::Div1;
39+
40+
// ------------------------------------------
41+
42+
static constexpr uint32_t MainPllClock = ExternalCrystalClock * pllFactors.pllMul; // 72 Mhz
43+
44+
static constexpr uint32_t Ahb = MainPllClock / RccProto::prescalerToValue<Ahb_pre>();
45+
static constexpr uint32_t Apb1 = Ahb / RccProto::prescalerToValue<Apb1_pre>();
46+
static constexpr uint32_t Apb2 = Ahb / RccProto::prescalerToValue<Apb2_pre>();
47+
48+
// @todo find a nice home for these assert's
49+
static_assert(Ahb <= 72_MHz, "Apb1 has max. 72MHz!");
50+
static_assert(Apb1 <= 36_MHz, "Apb1 has max. 36MHz!");
51+
static_assert(Apb2 <= 72_MHz, "Apb2 has max. 72MHz!");
52+
53+
// @todo is this correct?
54+
static constexpr uint32_t Apb1Timer = Apb1 * (RccProto::prescalerToValue<Apb1_pre>() == 1 ? 1 : 2);
55+
static constexpr uint32_t Apb2Timer = Apb2 * (RccProto::prescalerToValue<Apb2_pre>() == 1 ? 1 : 2);
56+
57+
// ------------------------------------------
58+
59+
static constexpr uint32_t Frequency = Ahb;
3460

3561
static constexpr uint32_t Adc = Apb2;
3662

@@ -49,42 +75,28 @@ struct SystemClock
4975
static constexpr uint32_t I2c1 = Apb1;
5076
static constexpr uint32_t I2c2 = Apb1;
5177

52-
static constexpr uint32_t Apb1Timer = Apb1 * 2;
53-
static constexpr uint32_t Apb2Timer = Apb2 * 1;
5478
static constexpr uint32_t Timer1 = Apb2Timer;
5579
static constexpr uint32_t Timer2 = Apb1Timer;
5680
static constexpr uint32_t Timer3 = Apb1Timer;
5781
static constexpr uint32_t Timer4 = Apb1Timer;
5882

59-
static constexpr uint32_t Usb = Ahb / 1.5;
83+
static constexpr uint32_t Usb = Ahb / RccProto::prescalerToValue<pllFactors.usbPrediv>(); // 48 MHz!
6084
static constexpr uint32_t Iwdg = Rcc::LsiFrequency;
6185

6286
static bool inline
6387
enable()
6488
{
6589
Rcc::enableExternalCrystal();
66-
67-
// external clock * 9 = 72MHz, => 72/1.5 = 48 => good for USB
68-
const Rcc::PllFactors pllFactors{
69-
.pllMul = 9,
70-
.usbPrediv = Rcc::UsbPrescaler::Div1_5
71-
};
7290
Rcc::enablePll(Rcc::PllSource::ExternalCrystal, pllFactors);
7391

7492
// set flash latency for 72MHz
7593
Rcc::setFlashLatency<Frequency>();
7694

7795
// switch system clock to PLL output
7896
Rcc::enableSystemClock(Rcc::SystemClockSource::Pll);
79-
80-
// AHB has max 72MHz
81-
Rcc::setAhbPrescaler(Rcc::AhbPrescaler::Div1);
82-
83-
// APB1 has max. 36MHz
84-
Rcc::setApb1Prescaler(Rcc::Apb1Prescaler::Div2);
85-
86-
// APB2 has max. 72MHz
87-
Rcc::setApb2Prescaler(Rcc::Apb2Prescaler::Div1);
97+
Rcc::setAhbPrescaler(Ahb_pre);
98+
Rcc::setApb1Prescaler(Apb1_pre);
99+
Rcc::setApb2Prescaler(Apb2_pre);
88100

89101
// update frequencies for busy-wait delay functions
90102
Rcc::updateCoreFrequency<Frequency>();
@@ -129,5 +141,3 @@ initializeUsbFs(uint8_t priority=3)
129141
/// @}
130142

131143
} // Board namespace
132-
133-
#endif // MODM_STM32_F103C8T6_BLUE_PILL_HPP
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
#pragma once
2+
3+
#include <modm/architecture/interface/clock.hpp>
4+
5+
namespace modm::platform {
6+
7+
// @todo integrate with /platform/clock/stm32/rcc.hpp.in
8+
class RccProto {
9+
public:
10+
template<Rcc::AhbPrescaler Prescaler>
11+
static consteval int
12+
prescalerToValue()
13+
{
14+
switch(Prescaler) {
15+
case Rcc::AhbPrescaler::Div1: return 1;
16+
case Rcc::AhbPrescaler::Div2: return 2;
17+
case Rcc::AhbPrescaler::Div4: return 4;
18+
case Rcc::AhbPrescaler::Div8: return 8;
19+
case Rcc::AhbPrescaler::Div16: return 16;
20+
case Rcc::AhbPrescaler::Div64: return 64;
21+
case Rcc::AhbPrescaler::Div128: return 128;
22+
case Rcc::AhbPrescaler::Div256: return 256;
23+
case Rcc::AhbPrescaler::Div512: return 512;
24+
};
25+
}
26+
27+
template<Rcc::Apb1Prescaler Prescaler>
28+
static consteval int
29+
prescalerToValue()
30+
{
31+
switch(Prescaler) {
32+
case Rcc::Apb1Prescaler::Div1: return 1;
33+
case Rcc::Apb1Prescaler::Div2: return 2;
34+
case Rcc::Apb1Prescaler::Div4: return 4;
35+
case Rcc::Apb1Prescaler::Div8: return 8;
36+
case Rcc::Apb1Prescaler::Div16: return 16;
37+
};
38+
}
39+
40+
template<Rcc::Apb2Prescaler Prescaler>
41+
static consteval int
42+
prescalerToValue()
43+
{
44+
switch(Prescaler) {
45+
case Rcc::Apb2Prescaler::Div1: return 1;
46+
case Rcc::Apb2Prescaler::Div2: return 2;
47+
case Rcc::Apb2Prescaler::Div4: return 4;
48+
case Rcc::Apb2Prescaler::Div8: return 8;
49+
case Rcc::Apb2Prescaler::Div16: return 16;
50+
}
51+
}
52+
53+
template<Rcc::UsbPrescaler Prescaler>
54+
static consteval float
55+
prescalerToValue()
56+
{
57+
switch(Prescaler) {
58+
case Rcc::UsbPrescaler::Div1: return 1;
59+
case Rcc::UsbPrescaler::Div1_5: return 1.5;
60+
}
61+
}
62+
};
63+
64+
}

src/modm/board/disco_f411ve/board.hpp

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include <modm/driver/inertial/lis3dsh.hpp>
1515
#include <modm/platform.hpp>
1616

17+
#include "rcc_prototype.hpp"
18+
1719
using namespace modm::platform;
1820

1921
namespace Board
@@ -22,13 +24,49 @@ namespace Board
2224
/// @{
2325
using namespace modm::literals;
2426

25-
/// STM32F411 running at 96MHz generated from the external 8MHz crystal
27+
2628
struct SystemClock
2729
{
28-
static constexpr uint32_t Frequency = 96_MHz;
29-
static constexpr uint32_t Ahb = Frequency;
30-
static constexpr uint32_t Apb1 = Frequency / 2;
31-
static constexpr uint32_t Apb2 = Frequency;
30+
static constexpr uint32_t ExternalCrystalClock = 8_MHz;
31+
32+
static constexpr Rcc::PllFactors pllFactors{
33+
.pllM = 8,
34+
.pllN = 336,
35+
.pllP = 4,
36+
.pllQ = 7,
37+
};
38+
static constexpr Rcc::AhbPrescaler Ahb_pre = Rcc::AhbPrescaler::Div1;
39+
static constexpr Rcc::Apb1Prescaler Apb1_pre = Rcc::Apb1Prescaler::Div2;
40+
static constexpr Rcc::Apb2Prescaler Apb2_pre = Rcc::Apb2Prescaler::Div1;
41+
42+
// ------------------------------------------
43+
44+
static constexpr uint32_t MainPllClock = ExternalCrystalClock / pllFactors.pllM * pllFactors.pllN;
45+
static constexpr uint32_t SystemFrequency = MainPllClock / pllFactors.pllP; // 96_Mhz
46+
47+
static constexpr uint32_t Ahb = SystemFrequency / RccProto::prescalerToValue<Ahb_pre>();
48+
static constexpr uint32_t Apb1 = Ahb / RccProto::prescalerToValue<Apb1_pre>();
49+
static constexpr uint32_t Apb2 = Ahb / RccProto::prescalerToValue<Apb2_pre>();
50+
51+
// @todo find a nice home for these
52+
static_assert(SystemFrequency <= 100_MHz, "SystemFrequency has max. 100MHz!");
53+
static_assert(Apb1 <= 50_MHz, "Apb1 has max. 50MHz!");
54+
static_assert(Apb2 <= 100_MHz, "Apb2 has max. 100MHz!");
55+
56+
// @todo is this correct?
57+
// prescaler is one ? -> multiply by one, otherwise multiply by two
58+
static constexpr uint32_t Apb1Timer = Apb1 * (RccProto::prescalerToValue<Apb1_pre>() == 1 ? 1 : 2);
59+
static constexpr uint32_t Apb2Timer = Apb2 * (RccProto::prescalerToValue<Apb2_pre>() == 1 ? 1 : 2);
60+
61+
// static_assert(Ahb == 84_MHz, "Wrong");
62+
// static_assert(Apb1 == 42_MHz, "Wrong");
63+
// static_assert(Apb2 == 84_MHz, "Wrong");
64+
// static_assert(Apb1Timer == 84_MHz, "Wrong");
65+
// static_assert(Apb2Timer == 84_MHz, "Wrong");
66+
67+
// ------------------------------------------
68+
69+
static constexpr uint32_t Frequency = Ahb;
3270

3371
static constexpr uint32_t Adc = Apb2;
3472

@@ -51,8 +89,6 @@ struct SystemClock
5189
static constexpr uint32_t I2c2 = Apb1;
5290
static constexpr uint32_t I2c3 = Apb1;
5391

54-
static constexpr uint32_t Apb1Timer = Apb1 * 2;
55-
static constexpr uint32_t Apb2Timer = Apb2 * 2;
5692
static constexpr uint32_t Timer1 = Apb2Timer;
5793
static constexpr uint32_t Timer2 = Apb1Timer;
5894
static constexpr uint32_t Timer3 = Apb1Timer;
@@ -62,27 +98,20 @@ struct SystemClock
6298
static constexpr uint32_t Timer10 = Apb2Timer;
6399
static constexpr uint32_t Timer11 = Apb2Timer;
64100

65-
static constexpr uint32_t Usb = 48_MHz;
101+
static constexpr uint32_t Usb = MainPllClock / pllFactors.pllQ; // 48_Mhz
66102

67103
static bool inline enable()
68104
{
69-
Rcc::enableExternalCrystal(); // 8MHz
70-
const Rcc::PllFactors pllFactors{
71-
.pllM = 7, // 8MHz / M=7 -> ~1.14MHz
72-
.pllN = 336, // 1.14MHz * N=336 -> 384MHz
73-
.pllP = 4, // 384MHz / P=4 -> 96MHz = F_cpu
74-
.pllQ = 8, // 384MHz / P=8 -> 48MHz = F_usb
75-
};
105+
/// STM32F411 running at 84MHz generated from the external 8MHz crystal
106+
Rcc::enableExternalCrystal();
76107
Rcc::enablePll(Rcc::PllSource::ExternalCrystal, pllFactors);
77108
// set flash latency for 100MHz
78109
Rcc::setFlashLatency<Frequency>();
79110
// switch system clock to PLL output
80111
Rcc::enableSystemClock(Rcc::SystemClockSource::Pll);
81-
Rcc::setAhbPrescaler(Rcc::AhbPrescaler::Div1);
82-
// APB1 has max. 50MHz
83-
// APB2 has max. 100MHz
84-
Rcc::setApb1Prescaler(Rcc::Apb1Prescaler::Div2);
85-
Rcc::setApb2Prescaler(Rcc::Apb2Prescaler::Div1);
112+
Rcc::setAhbPrescaler(Ahb_pre);
113+
Rcc::setApb1Prescaler(Apb1_pre);
114+
Rcc::setApb2Prescaler(Apb2_pre);
86115
// update frequencies for busy-wait delay functions
87116
Rcc::updateCoreFrequency<Frequency>();
88117

@@ -188,7 +217,7 @@ initializeLis3()
188217
lis3::Cs::setOutput(modm::Gpio::High);
189218

190219
lis3::SpiMaster::connect<lis3::Sck::Sck, lis3::Mosi::Mosi, lis3::Miso::Miso>();
191-
lis3::SpiMaster::initialize<SystemClock, 6_MHz>();
220+
lis3::SpiMaster::initialize<SystemClock, 5.25_MHz>();
192221
lis3::SpiMaster::setDataMode(lis3::SpiMaster::DataMode::Mode3);
193222
}
194223

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#pragma once
2+
3+
#include <modm/architecture/interface/clock.hpp>
4+
5+
namespace modm::platform {
6+
7+
// @todo integrate with /platform/clock/stm32/rcc.hpp.in
8+
class RccProto {
9+
public:
10+
template<Rcc::AhbPrescaler Prescaler>
11+
static consteval int
12+
prescalerToValue()
13+
{
14+
switch(Prescaler) {
15+
case Rcc::AhbPrescaler::Div1: return 1;
16+
case Rcc::AhbPrescaler::Div2: return 2;
17+
case Rcc::AhbPrescaler::Div4: return 4;
18+
case Rcc::AhbPrescaler::Div8: return 8;
19+
case Rcc::AhbPrescaler::Div16: return 16;
20+
case Rcc::AhbPrescaler::Div64: return 64;
21+
case Rcc::AhbPrescaler::Div128: return 128;
22+
case Rcc::AhbPrescaler::Div256: return 256;
23+
case Rcc::AhbPrescaler::Div512: return 512;
24+
};
25+
}
26+
27+
template<Rcc::Apb1Prescaler Prescaler>
28+
static consteval int
29+
prescalerToValue()
30+
{
31+
switch(Prescaler) {
32+
case Rcc::Apb1Prescaler::Div1: return 1;
33+
case Rcc::Apb1Prescaler::Div2: return 2;
34+
case Rcc::Apb1Prescaler::Div4: return 4;
35+
case Rcc::Apb1Prescaler::Div8: return 8;
36+
case Rcc::Apb1Prescaler::Div16: return 16;
37+
};
38+
}
39+
40+
template<Rcc::Apb2Prescaler Prescaler>
41+
static consteval int
42+
prescalerToValue()
43+
{
44+
switch(Prescaler) {
45+
case Rcc::Apb2Prescaler::Div1: return 1;
46+
case Rcc::Apb2Prescaler::Div2: return 2;
47+
case Rcc::Apb2Prescaler::Div4: return 4;
48+
case Rcc::Apb2Prescaler::Div8: return 8;
49+
case Rcc::Apb2Prescaler::Div16: return 16;
50+
}
51+
}
52+
};
53+
54+
}

0 commit comments

Comments
 (0)