Skip to content

Commit 2da6c2f

Browse files
cajtsalkinium
authored andcommitted
[board] Add support for STM32F401 Discovery
1 parent 8bcbe25 commit 2da6c2f

File tree

4 files changed

+343
-14
lines changed

4 files changed

+343
-14
lines changed

README.md

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -622,75 +622,76 @@ We have out-of-box support for many development boards including documentation.
622622
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f100rb">DISCO-F100RB</a></td>
623623
</tr><tr>
624624
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f303vc">DISCO-F303VC</a></td>
625+
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f401vc">DISCO-F401VC</a></td>
625626
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f407vg">DISCO-F407VG</a></td>
626627
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f429zi">DISCO-F429ZI</a></td>
627-
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f469ni">DISCO-F469NI</a></td>
628628
</tr><tr>
629+
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f469ni">DISCO-F469NI</a></td>
629630
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f746ng">DISCO-F746NG</a></td>
630631
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f769ni">DISCO-F769NI</a></td>
631632
<td align="center"><a href="https://modm.io/reference/config/modm-disco-l152rc">DISCO-L152RC</a></td>
632-
<td align="center"><a href="https://modm.io/reference/config/modm-disco-l476vg">DISCO-L476VG</a></td>
633633
</tr><tr>
634+
<td align="center"><a href="https://modm.io/reference/config/modm-disco-l476vg">DISCO-L476VG</a></td>
634635
<td align="center"><a href="https://modm.io/reference/config/modm-feather-m0">FEATHER-M0</a></td>
635636
<td align="center"><a href="https://modm.io/reference/config/modm-feather-m4">FEATHER-M4</a></td>
636637
<td align="center"><a href="https://modm.io/reference/config/modm-feather-rp2040">FEATHER-RP2040</a></td>
637-
<td align="center"><a href="https://modm.io/reference/config/modm-mega-2560-pro">MEGA-2560-PRO</a></td>
638638
</tr><tr>
639+
<td align="center"><a href="https://modm.io/reference/config/modm-mega-2560-pro">MEGA-2560-PRO</a></td>
639640
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f031k6">NUCLEO-F031K6</a></td>
640641
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f042k6">NUCLEO-F042K6</a></td>
641642
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f072rb">NUCLEO-F072RB</a></td>
642-
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f091rc">NUCLEO-F091RC</a></td>
643643
</tr><tr>
644+
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f091rc">NUCLEO-F091RC</a></td>
644645
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f103rb">NUCLEO-F103RB</a></td>
645646
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f303k8">NUCLEO-F303K8</a></td>
646647
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f303re">NUCLEO-F303RE</a></td>
647-
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f334r8">NUCLEO-F334R8</a></td>
648648
</tr><tr>
649+
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f334r8">NUCLEO-F334R8</a></td>
649650
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f401re">NUCLEO-F401RE</a></td>
650651
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f411re">NUCLEO-F411RE</a></td>
651652
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f429zi">NUCLEO-F429ZI</a></td>
652-
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f439zi">NUCLEO-F439ZI</a></td>
653653
</tr><tr>
654+
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f439zi">NUCLEO-F439ZI</a></td>
654655
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f446re">NUCLEO-F446RE</a></td>
655656
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f446ze">NUCLEO-F446ZE</a></td>
656657
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f746zg">NUCLEO-F746ZG</a></td>
657-
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f767zi">NUCLEO-F767ZI</a></td>
658658
</tr><tr>
659+
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f767zi">NUCLEO-F767ZI</a></td>
659660
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-g071rb">NUCLEO-G071RB</a></td>
660661
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-g431kb">NUCLEO-G431KB</a></td>
661662
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-g431rb">NUCLEO-G431RB</a></td>
662-
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-g474re">NUCLEO-G474RE</a></td>
663663
</tr><tr>
664+
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-g474re">NUCLEO-G474RE</a></td>
664665
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-h723zg">NUCLEO-H723ZG</a></td>
665666
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-h743zi">NUCLEO-H743ZI</a></td>
666667
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l031k6">NUCLEO-L031K6</a></td>
667-
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l053r8">NUCLEO-L053R8</a></td>
668668
</tr><tr>
669+
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l053r8">NUCLEO-L053R8</a></td>
669670
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l152re">NUCLEO-L152RE</a></td>
670671
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l432kc">NUCLEO-L432KC</a></td>
671672
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l452re">NUCLEO-L452RE</a></td>
672-
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l476rg">NUCLEO-L476RG</a></td>
673673
</tr><tr>
674+
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l476rg">NUCLEO-L476RG</a></td>
674675
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l496zg-p">NUCLEO-L496ZG-P</a></td>
675676
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l552ze-q">NUCLEO-L552ZE-Q</a></td>
676677
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-u575zi-q">NUCLEO-U575ZI-Q</a></td>
677-
<td align="center"><a href="https://modm.io/reference/config/modm-olimexino-stm32">OLIMEXINO-STM32</a></td>
678678
</tr><tr>
679+
<td align="center"><a href="https://modm.io/reference/config/modm-olimexino-stm32">OLIMEXINO-STM32</a></td>
679680
<td align="center"><a href="https://modm.io/reference/config/modm-raspberrypi">Raspberry Pi</a></td>
680681
<td align="center"><a href="https://modm.io/reference/config/modm-rp-pico">Raspberry Pi Pico</a></td>
681682
<td align="center"><a href="https://modm.io/reference/config/modm-samd21-mini">SAMD21-MINI</a></td>
682-
<td align="center"><a href="https://modm.io/reference/config/modm-samd21-xplained-pro">SAMD21-XPLAINED-PRO</a></td>
683683
</tr><tr>
684+
<td align="center"><a href="https://modm.io/reference/config/modm-samd21-xplained-pro">SAMD21-XPLAINED-PRO</a></td>
684685
<td align="center"><a href="https://modm.io/reference/config/modm-same54-xplained-pro">SAME54-XPLAINED-PRO</a></td>
685686
<td align="center"><a href="https://modm.io/reference/config/modm-same70-xplained">SAME70-XPLAINED</a></td>
686687
<td align="center"><a href="https://modm.io/reference/config/modm-samg55-xplained-pro">SAMG55-XPLAINED-PRO</a></td>
687-
<td align="center"><a href="https://modm.io/reference/config/modm-samv71-xplained-ultra">SAMV71-XPLAINED-ULTRA</a></td>
688688
</tr><tr>
689+
<td align="center"><a href="https://modm.io/reference/config/modm-samv71-xplained-ultra">SAMV71-XPLAINED-ULTRA</a></td>
689690
<td align="center"><a href="https://modm.io/reference/config/modm-srxe">Smart Response XE</a></td>
690691
<td align="center"><a href="https://modm.io/reference/config/modm-stm32_f4ve">STM32-F4VE</a></td>
691692
<td align="center"><a href="https://modm.io/reference/config/modm-stm32f030_demo">STM32F030-DEMO</a></td>
692-
<td align="center"><a href="https://modm.io/reference/config/modm-thingplus-rp2040">THINGPLUS-RP2040</a></td>
693693
</tr><tr>
694+
<td align="center"><a href="https://modm.io/reference/config/modm-thingplus-rp2040">THINGPLUS-RP2040</a></td>
694695
</tr>
695696
</table>
696697
<!--/bsptable-->

src/modm/board/disco_f401vc/board.hpp

Lines changed: 268 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,268 @@
1+
/*
2+
* Copyright (c) 2013, Kevin Läufer
3+
* Copyright (c) 2015-2018, Niklas Hauser
4+
* Copyright (c) 2017, Sascha Schade
5+
* Copyright (c) 2018, Antal Szabó
6+
* Copyright (c) 2024, Carl Treudler
7+
*
8+
* This file is part of the modm project.
9+
*
10+
* This Source Code Form is subject to the terms of the Mozilla Public
11+
* License, v. 2.0. If a copy of the MPL was not distributed with this
12+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
13+
*/
14+
// ----------------------------------------------------------------------------
15+
16+
#ifndef MODM_STM32_F401_DISCOVERY_HPP
17+
#define MODM_STM32_F401_DISCOVERY_HPP
18+
19+
#include <modm/platform.hpp>
20+
#include <modm/architecture/interface/clock.hpp>
21+
#include <modm/driver/inertial/lsm303a.hpp>
22+
#include <modm/driver/inertial/l3gd20.hpp>
23+
24+
using namespace modm::platform;
25+
26+
namespace Board
27+
{
28+
/// @ingroup modm_board_disco_f401vc
29+
/// @{
30+
using namespace modm::literals;
31+
32+
/// STM32F401 running at 168MHz generated from the external 8MHz crystal
33+
struct SystemClock
34+
{
35+
static constexpr uint32_t Frequency = 84_MHz;
36+
static constexpr uint32_t Ahb = Frequency;
37+
static constexpr uint32_t Apb1 = Frequency / 4;
38+
static constexpr uint32_t Apb2 = Frequency / 2;
39+
40+
static constexpr uint32_t Adc = Apb2;
41+
42+
static constexpr uint32_t Spi1 = Apb2;
43+
static constexpr uint32_t Spi2 = Apb1;
44+
static constexpr uint32_t Spi3 = Apb1;
45+
static constexpr uint32_t Spi4 = Apb2;
46+
47+
static constexpr uint32_t Usart1 = Apb2;
48+
static constexpr uint32_t Usart2 = Apb1;
49+
static constexpr uint32_t Usart6 = Apb1;
50+
51+
static constexpr uint32_t I2c1 = Apb1;
52+
static constexpr uint32_t I2c2 = Apb1;
53+
static constexpr uint32_t I2c3 = Apb1;
54+
55+
static constexpr uint32_t Apb1Timer = Apb1 * 2;
56+
static constexpr uint32_t Apb2Timer = Apb2 * 2;
57+
static constexpr uint32_t Timer1 = Apb2Timer;
58+
static constexpr uint32_t Timer2 = Apb1Timer;
59+
static constexpr uint32_t Timer3 = Apb1Timer;
60+
static constexpr uint32_t Timer4 = Apb1Timer;
61+
static constexpr uint32_t Timer5 = Apb1Timer;
62+
static constexpr uint32_t Timer6 = Apb1Timer;
63+
static constexpr uint32_t Timer7 = Apb1Timer;
64+
static constexpr uint32_t Timer8 = Apb2Timer;
65+
static constexpr uint32_t Timer9 = Apb2Timer;
66+
static constexpr uint32_t Timer10 = Apb2Timer;
67+
static constexpr uint32_t Timer11 = Apb2Timer;
68+
69+
static constexpr uint32_t Usb = 48_MHz;
70+
71+
static bool inline
72+
enable()
73+
{
74+
Rcc::enableExternalCrystal(); // 8MHz
75+
const Rcc::PllFactors pllFactors{
76+
.pllM = 4, // 8MHz / M=4 -> 2MHz
77+
.pllN = 168, // 2MHz * N=168 -> 336MHz
78+
.pllP = 4, // 336MHz / P=4 -> 84MHz = F_cpu
79+
.pllQ = 7 // 336MHz / Q=7 -> 48MHz = F_usb
80+
};
81+
Rcc::enablePll(Rcc::PllSource::ExternalCrystal, pllFactors);
82+
// set flash latency for 84MHz
83+
Rcc::setFlashLatency<Frequency>();
84+
// switch system clock to PLL output
85+
Rcc::enableSystemClock(Rcc::SystemClockSource::Pll);
86+
Rcc::setAhbPrescaler(Rcc::AhbPrescaler::Div1);
87+
// APB1 has max. 42MHz
88+
// APB2 has max. 84MHz
89+
Rcc::setApb1Prescaler(Rcc::Apb1Prescaler::Div4);
90+
Rcc::setApb2Prescaler(Rcc::Apb2Prescaler::Div2);
91+
// update frequencies for busy-wait delay functions
92+
Rcc::updateCoreFrequency<Frequency>();
93+
94+
return true;
95+
}
96+
};
97+
98+
using Button = GpioInputA0;
99+
using ClockOut = GpioOutputA8;
100+
using SystemClockOut = GpioOutputC9;
101+
102+
using LedOrange = GpioOutputD13; // User LED 3
103+
using LedGreen = GpioOutputD12; // User LED 4
104+
using LedRed = GpioOutputD14; // User LED 5
105+
using LedBlue = GpioOutputD15; // User LED 6
106+
107+
using Leds = SoftwareGpioPort< LedGreen, LedBlue, LedRed, LedOrange >;
108+
/// @}
109+
110+
namespace lsm3
111+
{
112+
/// @ingroup modm_board_disco_f401vc
113+
/// @{
114+
using Drdy = GpioInputE2; // DRDY [LSM303DLHC_DRDY]: GPXTI2
115+
using Int1 = GpioInputE4; // MEMS_INT3 [LSM303DLHC_INT1]: GPXTI4
116+
using Int2 = GpioInputE5; // MEMS_INT4 [LSM303DLHC_INT2]: GPXTI5
117+
118+
using Scl = GpioB6; // I2C1_SCL [LSM303DLHC_SCL]: I2C1_SCL
119+
using Sda = GpioB9; // I2C1_SDA [LSM303DLHC_SDA]: I2C1_SDA
120+
121+
using I2cMaster = I2cMaster1;
122+
using Accelerometer = modm::Lsm303a< I2cMaster >;
123+
/// @}
124+
}
125+
126+
namespace l3g
127+
{
128+
/// @ingroup modm_board_disco_f401vc
129+
/// @{
130+
using Int1 = GpioInputE0; // MEMS_INT1 [L3GD20_INT1]: GPXTI0
131+
using Int2 = GpioInputE1; // MEMS_INT2 [L3GD20_DRDY/INT2]: GPXTI1
132+
133+
using Cs = GpioOutputE3; // CS_I2C/SPI [L3GD20_CS_I2C/SPI]
134+
using Sck = GpioOutputA5; // SPI1_SCK [L3GD20_SCL/SPC]
135+
using Mosi = GpioOutputA7; // SPI1_MOSI [L3GD20_SDA/SDI/SDO]
136+
using Miso = GpioInputA6; // SPI1_MISO [L3GD20_SA0/SDO]
137+
138+
using SpiMaster = SpiMaster1;
139+
using Transport = modm::Lis3TransportSpi< SpiMaster, Cs >;
140+
using Gyroscope = modm::L3gd20< Transport >;
141+
/// @}
142+
}
143+
144+
namespace cs43
145+
{
146+
/// @ingroup modm_board_disco_f401vc
147+
/// @{
148+
using Lrck = GpioOutputA4; // I2S3_WS
149+
using Mclk = GpioOutputC7; // I2S3_MCK
150+
using Sclk = GpioOutputC10; // I2S3_SCK
151+
using Sdin = GpioOutputC12; // I2S3_SD
152+
153+
using Reset = GpioOutputD4; // Audio_RST
154+
using Scl = GpioB6; // Audio_SCL
155+
using Sda = GpioB9; // Audio_SDA
156+
157+
using I2cMaster = I2cMaster1;
158+
//using I2sMaster = I2sMaster3;
159+
/// @}
160+
}
161+
162+
163+
namespace mp45
164+
{
165+
/// @ingroup modm_board_disco_f401vc
166+
/// @{
167+
using Clk = GpioOutputB10; // CLK_IN: I2S2_CK
168+
using Dout = GpioInputC3; // PDM_OUT: I2S2_SD
169+
//using I2sMaster = I2sMaster2;
170+
/// @}
171+
}
172+
173+
174+
namespace usb
175+
{
176+
/// @ingroup modm_board_disco_f401vc
177+
/// @{
178+
using Vbus = GpioInputA9; // VBUS_FS: USB_OTG_HS_VBUS
179+
using Id = GpioA10; // OTG_FS_ID: USB_OTG_FS_ID
180+
using Dm = GpioA11; // OTG_FS_DM: USB_OTG_FS_DM
181+
using Dp = GpioA12; // OTG_FS_DP: USB_OTG_FS_DP
182+
183+
using Overcurrent = GpioInputD5; // OTG_FS_OverCurrent
184+
using Power = GpioOutputC0; // OTG_FS_PowerSwitchOn
185+
186+
using Device = UsbFs;
187+
/// @}
188+
}
189+
190+
191+
/// @ingroup modm_board_disco_f401vc
192+
/// @{
193+
inline void
194+
initialize()
195+
{
196+
SystemClock::enable();
197+
SysTickTimer::initialize<SystemClock>();
198+
199+
Leds::setOutput(modm::Gpio::Low);
200+
201+
Button::setInput();
202+
}
203+
204+
205+
inline void
206+
initializeLsm3()
207+
{
208+
lsm3::Int1::setInput();
209+
lsm3::Int2::setInput();
210+
lsm3::Drdy::setInput();
211+
212+
lsm3::I2cMaster::connect<lsm3::Scl::Scl, lsm3::Sda::Sda>();
213+
lsm3::I2cMaster::initialize<SystemClock, 400_kHz>();
214+
}
215+
216+
/// not supported yet, due to missing I2S driver
217+
inline void
218+
initializeCs43()
219+
{
220+
// cs43::Lrck::connect(cs43::I2sMaster::Ws);
221+
// cs43::Mclk::connect(cs43::I2sMaster::Mck);
222+
// cs43::Sclk::connect(cs43::I2sMaster::Ck);
223+
// cs43::Sdin::connect(cs43::I2sMaster::Sd);
224+
225+
cs43::Reset::setOutput(modm::Gpio::High);
226+
227+
cs43::I2cMaster::connect<cs43::Scl::Scl, cs43::Sda::Sda>();
228+
cs43::I2cMaster::initialize<SystemClock, 100_kHz>();
229+
}
230+
231+
inline void
232+
initializeL3g()
233+
{
234+
l3g::Int1::setInput();
235+
l3g::Int2::setInput();
236+
l3g::Cs::setOutput(modm::Gpio::High);
237+
238+
l3g::SpiMaster::connect<l3g::Sck::Sck, l3g::Mosi::Mosi, l3g::Miso::Miso>();
239+
l3g::SpiMaster::initialize<SystemClock, 10_MHz>();
240+
l3g::SpiMaster::setDataMode(l3g::SpiMaster::DataMode::Mode3);
241+
}
242+
243+
/// not supported yet, due to missing I2S driver
244+
inline void
245+
initializeMp45()
246+
{
247+
// mp45::Clk::connect(mp45::I2sMaster::Ck);
248+
// mp45::Dout::connect(mp45::I2sMaster::Sd);
249+
}
250+
251+
inline void
252+
initializeUsbFs(uint8_t priority=3)
253+
{
254+
usb::Device::initialize<SystemClock>(priority);
255+
usb::Device::connect<usb::Dm::Dm, usb::Dp::Dp, usb::Id::Id>();
256+
257+
usb::Overcurrent::setInput();
258+
usb::Vbus::setInput();
259+
// Enable VBUS sense (B device) via pin PA9
260+
USB_OTG_FS->GCCFG &= ~USB_OTG_GCCFG_NOVBUSSENS;
261+
USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBUSBSEN;
262+
}
263+
264+
/// @}
265+
266+
}
267+
268+
#endif // MODM_STM32_F401_DISCOVERY_HPP

src/modm/board/disco_f401vc/board.xml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<library>
2+
<repositories>
3+
<repository>
4+
<path>../../../../repo.lb</path>
5+
</repository>
6+
</repositories>
7+
<options>
8+
<option name="modm:target">stm32f401vct6</option>
9+
</options>
10+
<modules>
11+
<module>modm:board:disco-f401vc</module>
12+
</modules>
13+
</library>

0 commit comments

Comments
 (0)