Skip to content

Commit a22d568

Browse files
committed
proto for blue_pill_f103, board/disco_f411ve
1 parent e551cb3 commit a22d568

File tree

4 files changed

+225
-48
lines changed

4 files changed

+225
-48
lines changed

src/modm/board/blue_pill_f103/board.hpp

Lines changed: 43 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,44 @@ 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 ExternalLSEclock = ;
31+
static constexpr uint32_t ExternalHSEclock = 8_MHz;
32+
33+
static constexpr Rcc::PllFactors pllFactors{
34+
.pllMul = 9,
35+
.usbPrediv = Rcc::UsbPrescaler::Div1_5
36+
};
37+
static constexpr Rcc::AhbPrescaler Ahb_prescaler = Rcc::AhbPrescaler::Div1;
38+
static constexpr Rcc::Apb1Prescaler Apb1_prescaler = Rcc::Apb1Prescaler::Div2;
39+
static constexpr Rcc::Apb2Prescaler Apb2_prescaler = Rcc::Apb2Prescaler::Div1;
40+
41+
// ------------------------------------------
42+
43+
static constexpr int HsePredivision = 1;
44+
static constexpr int PllClock = ExternalHSEclock / HsePredivision * pllFactors.pllMul; // 72 Mhz
45+
46+
// System Clock MUX
47+
static constexpr uint32_t Clock = PllClock;
48+
static_assert(Clock <= 72_MHz, "Clock has max. 72MHz!");
49+
50+
static constexpr uint32_t Ahb = Clock / RccProto::prescalerToValue<Ahb_prescaler>();
51+
static_assert(Ahb <= 72_MHz, "Ahb has max. 72MHz!");
52+
53+
static constexpr uint32_t Apb1 = Ahb / RccProto::prescalerToValue<Apb1_prescaler>();
54+
static_assert(Apb1 <= 36_MHz, "Apb1 has max. 36MHz!");
55+
56+
static constexpr uint32_t Apb2 = Ahb / RccProto::prescalerToValue<Apb2_prescaler>();
57+
static_assert(Apb2 <= 72_MHz, "Apb2 has max. 72MHz!");
58+
59+
// @todo is this correct?
60+
static constexpr uint32_t Apb1Timer = Apb1 * (RccProto::prescalerToValue<Apb1_prescaler>() == 1 ? 1 : 2);
61+
static constexpr uint32_t Apb2Timer = Apb2 * (RccProto::prescalerToValue<Apb2_prescaler>() == 1 ? 1 : 2);
62+
63+
// ------------------------------------------
64+
65+
static constexpr uint32_t Frequency = Ahb;
3466

3567
static constexpr uint32_t Adc = Apb2;
3668

@@ -49,42 +81,28 @@ struct SystemClock
4981
static constexpr uint32_t I2c1 = Apb1;
5082
static constexpr uint32_t I2c2 = Apb1;
5183

52-
static constexpr uint32_t Apb1Timer = Apb1 * 2;
53-
static constexpr uint32_t Apb2Timer = Apb2 * 1;
5484
static constexpr uint32_t Timer1 = Apb2Timer;
5585
static constexpr uint32_t Timer2 = Apb1Timer;
5686
static constexpr uint32_t Timer3 = Apb1Timer;
5787
static constexpr uint32_t Timer4 = Apb1Timer;
5888

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

6292
static bool inline
6393
enable()
6494
{
6595
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-
};
7296
Rcc::enablePll(Rcc::PllSource::ExternalCrystal, pllFactors);
7397

7498
// set flash latency for 72MHz
7599
Rcc::setFlashLatency<Frequency>();
76100

77101
// switch system clock to PLL output
78102
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);
103+
Rcc::setAhbPrescaler(Ahb_prescaler);
104+
Rcc::setApb1Prescaler(Apb1_prescaler);
105+
Rcc::setApb2Prescaler(Apb2_prescaler);
88106

89107
// update frequencies for busy-wait delay functions
90108
Rcc::updateCoreFrequency<Frequency>();
@@ -129,5 +147,3 @@ initializeUsbFs(uint8_t priority=3)
129147
/// @}
130148

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

src/modm/board/disco_f411ve/board.hpp

Lines changed: 54 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,53 @@ 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 ExternalLSEclock = ;
31+
static constexpr uint32_t ExternalHSEclock = 8_MHz;
32+
33+
static constexpr Rcc::PllFactors pllFactors{
34+
.pllM = 8,
35+
.pllN = 336,
36+
.pllP = 4,
37+
.pllQ = 7,
38+
};
39+
static constexpr Rcc::AhbPrescaler Ahb_prescaler = Rcc::AhbPrescaler::Div1;
40+
static constexpr Rcc::Apb1Prescaler Apb1_prescaler = Rcc::Apb1Prescaler::Div2;
41+
static constexpr Rcc::Apb2Prescaler Apb2_prescaler = Rcc::Apb2Prescaler::Div1;
42+
43+
// ------------------------------------------
44+
45+
static constexpr int HsePredivision = 1;
46+
static constexpr uint32_t PllClock = ExternalHSEclock / HsePredivision / pllFactors.pllM * pllFactors.pllN;
47+
48+
static constexpr uint32_t Clock = PllClock / pllFactors.pllP; // 96_Mhz
49+
static_assert(Clock <= 100_MHz, "Clock has max. 100MHz!");
50+
51+
static constexpr uint32_t Ahb = Clock / RccProto::prescalerToValue<Ahb_prescaler>();
52+
static_assert(Ahb <= 100_MHz, "Ahb has max. 100MHz!");
53+
54+
static constexpr uint32_t Apb1 = Ahb / RccProto::prescalerToValue<Apb1_prescaler>();
55+
static_assert(Apb1 <= 50_MHz, "Apb1 has max. 50MHz!");
56+
57+
static constexpr uint32_t Apb2 = Ahb / RccProto::prescalerToValue<Apb2_prescaler>();
58+
static_assert(Apb2 <= 100_MHz, "Apb2 has max. 100MHz!");
59+
60+
// @todo is this correct?
61+
// prescaler is one ? -> multiply by one, otherwise multiply by two
62+
static constexpr uint32_t Apb1Timer = Apb1 * (RccProto::prescalerToValue<Apb1_prescaler>() == 1 ? 1 : 2);
63+
static constexpr uint32_t Apb2Timer = Apb2 * (RccProto::prescalerToValue<Apb2_prescaler>() == 1 ? 1 : 2);
64+
65+
// static_assert(Ahb == 84_MHz, "Wrong");
66+
// static_assert(Apb1 == 42_MHz, "Wrong");
67+
// static_assert(Apb2 == 84_MHz, "Wrong");
68+
// static_assert(Apb1Timer == 84_MHz, "Wrong");
69+
// static_assert(Apb2Timer == 84_MHz, "Wrong");
70+
71+
// ------------------------------------------
72+
73+
static constexpr uint32_t Frequency = Ahb;
3274

3375
static constexpr uint32_t Adc = Apb2;
3476

@@ -51,8 +93,6 @@ struct SystemClock
5193
static constexpr uint32_t I2c2 = Apb1;
5294
static constexpr uint32_t I2c3 = Apb1;
5395

54-
static constexpr uint32_t Apb1Timer = Apb1 * 2;
55-
static constexpr uint32_t Apb2Timer = Apb2 * 2;
5696
static constexpr uint32_t Timer1 = Apb2Timer;
5797
static constexpr uint32_t Timer2 = Apb1Timer;
5898
static constexpr uint32_t Timer3 = Apb1Timer;
@@ -62,27 +102,20 @@ struct SystemClock
62102
static constexpr uint32_t Timer10 = Apb2Timer;
63103
static constexpr uint32_t Timer11 = Apb2Timer;
64104

65-
static constexpr uint32_t Usb = 48_MHz;
105+
static constexpr uint32_t Usb = PllClock / pllFactors.pllQ; // 48_Mhz
66106

67107
static bool inline enable()
68108
{
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-
};
109+
/// STM32F411 running at 84MHz generated from the external 8MHz crystal
110+
Rcc::enableExternalCrystal();
76111
Rcc::enablePll(Rcc::PllSource::ExternalCrystal, pllFactors);
77112
// set flash latency for 100MHz
78113
Rcc::setFlashLatency<Frequency>();
79114
// switch system clock to PLL output
80115
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);
116+
Rcc::setAhbPrescaler(Ahb_prescaler);
117+
Rcc::setApb1Prescaler(Apb1_prescaler);
118+
Rcc::setApb2Prescaler(Apb2_prescaler);
86119
// update frequencies for busy-wait delay functions
87120
Rcc::updateCoreFrequency<Frequency>();
88121

@@ -188,7 +221,7 @@ initializeLis3()
188221
lis3::Cs::setOutput(modm::Gpio::High);
189222

190223
lis3::SpiMaster::connect<lis3::Sck::Sck, lis3::Mosi::Mosi, lis3::Miso::Miso>();
191-
lis3::SpiMaster::initialize<SystemClock, 6_MHz>();
224+
lis3::SpiMaster::initialize<SystemClock, 5.25_MHz>();
192225
lis3::SpiMaster::setDataMode(lis3::SpiMaster::DataMode::Mode3);
193226
}
194227

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

0 commit comments

Comments
 (0)