Skip to content

Commit

Permalink
[board] Add support for STM32F401 Discovery
Browse files Browse the repository at this point in the history
  • Loading branch information
cajt authored and salkinium committed Jan 5, 2024
1 parent 8bcbe25 commit 2da6c2f
Show file tree
Hide file tree
Showing 4 changed files with 343 additions and 14 deletions.
29 changes: 15 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -622,75 +622,76 @@ We have out-of-box support for many development boards including documentation.
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f100rb">DISCO-F100RB</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f303vc">DISCO-F303VC</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f401vc">DISCO-F401VC</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f407vg">DISCO-F407VG</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f429zi">DISCO-F429ZI</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f469ni">DISCO-F469NI</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f469ni">DISCO-F469NI</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f746ng">DISCO-F746NG</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-disco-f769ni">DISCO-F769NI</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-disco-l152rc">DISCO-L152RC</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-disco-l476vg">DISCO-L476VG</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/config/modm-disco-l476vg">DISCO-L476VG</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-feather-m0">FEATHER-M0</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-feather-m4">FEATHER-M4</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-feather-rp2040">FEATHER-RP2040</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-mega-2560-pro">MEGA-2560-PRO</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/config/modm-mega-2560-pro">MEGA-2560-PRO</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f031k6">NUCLEO-F031K6</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f042k6">NUCLEO-F042K6</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f072rb">NUCLEO-F072RB</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f091rc">NUCLEO-F091RC</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f091rc">NUCLEO-F091RC</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f103rb">NUCLEO-F103RB</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f303k8">NUCLEO-F303K8</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f303re">NUCLEO-F303RE</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f334r8">NUCLEO-F334R8</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f334r8">NUCLEO-F334R8</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f401re">NUCLEO-F401RE</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f411re">NUCLEO-F411RE</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f429zi">NUCLEO-F429ZI</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f439zi">NUCLEO-F439ZI</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f439zi">NUCLEO-F439ZI</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f446re">NUCLEO-F446RE</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f446ze">NUCLEO-F446ZE</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f746zg">NUCLEO-F746ZG</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f767zi">NUCLEO-F767ZI</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-f767zi">NUCLEO-F767ZI</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-g071rb">NUCLEO-G071RB</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-g431kb">NUCLEO-G431KB</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-g431rb">NUCLEO-G431RB</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-g474re">NUCLEO-G474RE</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-g474re">NUCLEO-G474RE</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-h723zg">NUCLEO-H723ZG</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-h743zi">NUCLEO-H743ZI</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l031k6">NUCLEO-L031K6</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l053r8">NUCLEO-L053R8</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l053r8">NUCLEO-L053R8</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l152re">NUCLEO-L152RE</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l432kc">NUCLEO-L432KC</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l452re">NUCLEO-L452RE</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l476rg">NUCLEO-L476RG</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l476rg">NUCLEO-L476RG</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l496zg-p">NUCLEO-L496ZG-P</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-l552ze-q">NUCLEO-L552ZE-Q</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-u575zi-q">NUCLEO-U575ZI-Q</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-olimexino-stm32">OLIMEXINO-STM32</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/config/modm-olimexino-stm32">OLIMEXINO-STM32</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-raspberrypi">Raspberry Pi</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-rp-pico">Raspberry Pi Pico</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-samd21-mini">SAMD21-MINI</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-samd21-xplained-pro">SAMD21-XPLAINED-PRO</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/config/modm-samd21-xplained-pro">SAMD21-XPLAINED-PRO</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-same54-xplained-pro">SAME54-XPLAINED-PRO</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-same70-xplained">SAME70-XPLAINED</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-samg55-xplained-pro">SAMG55-XPLAINED-PRO</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-samv71-xplained-ultra">SAMV71-XPLAINED-ULTRA</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/config/modm-samv71-xplained-ultra">SAMV71-XPLAINED-ULTRA</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-srxe">Smart Response XE</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-stm32_f4ve">STM32-F4VE</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-stm32f030_demo">STM32F030-DEMO</a></td>
<td align="center"><a href="https://modm.io/reference/config/modm-thingplus-rp2040">THINGPLUS-RP2040</a></td>
</tr><tr>
<td align="center"><a href="https://modm.io/reference/config/modm-thingplus-rp2040">THINGPLUS-RP2040</a></td>
</tr>
</table>
<!--/bsptable-->
Expand Down
268 changes: 268 additions & 0 deletions src/modm/board/disco_f401vc/board.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
/*
* Copyright (c) 2013, Kevin Läufer
* Copyright (c) 2015-2018, Niklas Hauser
* Copyright (c) 2017, Sascha Schade
* Copyright (c) 2018, Antal Szabó
* Copyright (c) 2024, Carl Treudler
*
* This file is part of the modm project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
// ----------------------------------------------------------------------------

#ifndef MODM_STM32_F401_DISCOVERY_HPP
#define MODM_STM32_F401_DISCOVERY_HPP

#include <modm/platform.hpp>
#include <modm/architecture/interface/clock.hpp>
#include <modm/driver/inertial/lsm303a.hpp>
#include <modm/driver/inertial/l3gd20.hpp>

using namespace modm::platform;

namespace Board
{
/// @ingroup modm_board_disco_f401vc
/// @{
using namespace modm::literals;

/// STM32F401 running at 168MHz generated from the external 8MHz crystal
struct SystemClock
{
static constexpr uint32_t Frequency = 84_MHz;
static constexpr uint32_t Ahb = Frequency;
static constexpr uint32_t Apb1 = Frequency / 4;
static constexpr uint32_t Apb2 = Frequency / 2;

static constexpr uint32_t Adc = Apb2;

static constexpr uint32_t Spi1 = Apb2;
static constexpr uint32_t Spi2 = Apb1;
static constexpr uint32_t Spi3 = Apb1;
static constexpr uint32_t Spi4 = Apb2;

static constexpr uint32_t Usart1 = Apb2;
static constexpr uint32_t Usart2 = Apb1;
static constexpr uint32_t Usart6 = Apb1;

static constexpr uint32_t I2c1 = Apb1;
static constexpr uint32_t I2c2 = Apb1;
static constexpr uint32_t I2c3 = Apb1;

static constexpr uint32_t Apb1Timer = Apb1 * 2;
static constexpr uint32_t Apb2Timer = Apb2 * 2;
static constexpr uint32_t Timer1 = Apb2Timer;
static constexpr uint32_t Timer2 = Apb1Timer;
static constexpr uint32_t Timer3 = Apb1Timer;
static constexpr uint32_t Timer4 = Apb1Timer;
static constexpr uint32_t Timer5 = Apb1Timer;
static constexpr uint32_t Timer6 = Apb1Timer;
static constexpr uint32_t Timer7 = Apb1Timer;
static constexpr uint32_t Timer8 = Apb2Timer;
static constexpr uint32_t Timer9 = Apb2Timer;
static constexpr uint32_t Timer10 = Apb2Timer;
static constexpr uint32_t Timer11 = Apb2Timer;

static constexpr uint32_t Usb = 48_MHz;

static bool inline
enable()
{
Rcc::enableExternalCrystal(); // 8MHz
const Rcc::PllFactors pllFactors{
.pllM = 4, // 8MHz / M=4 -> 2MHz
.pllN = 168, // 2MHz * N=168 -> 336MHz
.pllP = 4, // 336MHz / P=4 -> 84MHz = F_cpu
.pllQ = 7 // 336MHz / Q=7 -> 48MHz = F_usb
};
Rcc::enablePll(Rcc::PllSource::ExternalCrystal, pllFactors);
// set flash latency for 84MHz
Rcc::setFlashLatency<Frequency>();
// switch system clock to PLL output
Rcc::enableSystemClock(Rcc::SystemClockSource::Pll);
Rcc::setAhbPrescaler(Rcc::AhbPrescaler::Div1);
// APB1 has max. 42MHz
// APB2 has max. 84MHz
Rcc::setApb1Prescaler(Rcc::Apb1Prescaler::Div4);
Rcc::setApb2Prescaler(Rcc::Apb2Prescaler::Div2);
// update frequencies for busy-wait delay functions
Rcc::updateCoreFrequency<Frequency>();

return true;
}
};

using Button = GpioInputA0;
using ClockOut = GpioOutputA8;
using SystemClockOut = GpioOutputC9;

using LedOrange = GpioOutputD13; // User LED 3
using LedGreen = GpioOutputD12; // User LED 4
using LedRed = GpioOutputD14; // User LED 5
using LedBlue = GpioOutputD15; // User LED 6

using Leds = SoftwareGpioPort< LedGreen, LedBlue, LedRed, LedOrange >;
/// @}

namespace lsm3
{
/// @ingroup modm_board_disco_f401vc
/// @{
using Drdy = GpioInputE2; // DRDY [LSM303DLHC_DRDY]: GPXTI2
using Int1 = GpioInputE4; // MEMS_INT3 [LSM303DLHC_INT1]: GPXTI4
using Int2 = GpioInputE5; // MEMS_INT4 [LSM303DLHC_INT2]: GPXTI5

using Scl = GpioB6; // I2C1_SCL [LSM303DLHC_SCL]: I2C1_SCL
using Sda = GpioB9; // I2C1_SDA [LSM303DLHC_SDA]: I2C1_SDA

using I2cMaster = I2cMaster1;
using Accelerometer = modm::Lsm303a< I2cMaster >;
/// @}
}

namespace l3g
{
/// @ingroup modm_board_disco_f401vc
/// @{
using Int1 = GpioInputE0; // MEMS_INT1 [L3GD20_INT1]: GPXTI0
using Int2 = GpioInputE1; // MEMS_INT2 [L3GD20_DRDY/INT2]: GPXTI1

using Cs = GpioOutputE3; // CS_I2C/SPI [L3GD20_CS_I2C/SPI]
using Sck = GpioOutputA5; // SPI1_SCK [L3GD20_SCL/SPC]
using Mosi = GpioOutputA7; // SPI1_MOSI [L3GD20_SDA/SDI/SDO]
using Miso = GpioInputA6; // SPI1_MISO [L3GD20_SA0/SDO]

using SpiMaster = SpiMaster1;
using Transport = modm::Lis3TransportSpi< SpiMaster, Cs >;
using Gyroscope = modm::L3gd20< Transport >;
/// @}
}

namespace cs43
{
/// @ingroup modm_board_disco_f401vc
/// @{
using Lrck = GpioOutputA4; // I2S3_WS
using Mclk = GpioOutputC7; // I2S3_MCK
using Sclk = GpioOutputC10; // I2S3_SCK
using Sdin = GpioOutputC12; // I2S3_SD

using Reset = GpioOutputD4; // Audio_RST
using Scl = GpioB6; // Audio_SCL
using Sda = GpioB9; // Audio_SDA

using I2cMaster = I2cMaster1;
//using I2sMaster = I2sMaster3;
/// @}
}


namespace mp45
{
/// @ingroup modm_board_disco_f401vc
/// @{
using Clk = GpioOutputB10; // CLK_IN: I2S2_CK
using Dout = GpioInputC3; // PDM_OUT: I2S2_SD
//using I2sMaster = I2sMaster2;
/// @}
}


namespace usb
{
/// @ingroup modm_board_disco_f401vc
/// @{
using Vbus = GpioInputA9; // VBUS_FS: USB_OTG_HS_VBUS
using Id = GpioA10; // OTG_FS_ID: USB_OTG_FS_ID
using Dm = GpioA11; // OTG_FS_DM: USB_OTG_FS_DM
using Dp = GpioA12; // OTG_FS_DP: USB_OTG_FS_DP

using Overcurrent = GpioInputD5; // OTG_FS_OverCurrent
using Power = GpioOutputC0; // OTG_FS_PowerSwitchOn

using Device = UsbFs;
/// @}
}


/// @ingroup modm_board_disco_f401vc
/// @{
inline void
initialize()
{
SystemClock::enable();
SysTickTimer::initialize<SystemClock>();

Leds::setOutput(modm::Gpio::Low);

Button::setInput();
}


inline void
initializeLsm3()
{
lsm3::Int1::setInput();
lsm3::Int2::setInput();
lsm3::Drdy::setInput();

lsm3::I2cMaster::connect<lsm3::Scl::Scl, lsm3::Sda::Sda>();
lsm3::I2cMaster::initialize<SystemClock, 400_kHz>();
}

/// not supported yet, due to missing I2S driver
inline void
initializeCs43()
{
// cs43::Lrck::connect(cs43::I2sMaster::Ws);
// cs43::Mclk::connect(cs43::I2sMaster::Mck);
// cs43::Sclk::connect(cs43::I2sMaster::Ck);
// cs43::Sdin::connect(cs43::I2sMaster::Sd);

cs43::Reset::setOutput(modm::Gpio::High);

cs43::I2cMaster::connect<cs43::Scl::Scl, cs43::Sda::Sda>();
cs43::I2cMaster::initialize<SystemClock, 100_kHz>();
}

inline void
initializeL3g()
{
l3g::Int1::setInput();
l3g::Int2::setInput();
l3g::Cs::setOutput(modm::Gpio::High);

l3g::SpiMaster::connect<l3g::Sck::Sck, l3g::Mosi::Mosi, l3g::Miso::Miso>();
l3g::SpiMaster::initialize<SystemClock, 10_MHz>();
l3g::SpiMaster::setDataMode(l3g::SpiMaster::DataMode::Mode3);
}

/// not supported yet, due to missing I2S driver
inline void
initializeMp45()
{
// mp45::Clk::connect(mp45::I2sMaster::Ck);
// mp45::Dout::connect(mp45::I2sMaster::Sd);
}

inline void
initializeUsbFs(uint8_t priority=3)
{
usb::Device::initialize<SystemClock>(priority);
usb::Device::connect<usb::Dm::Dm, usb::Dp::Dp, usb::Id::Id>();

usb::Overcurrent::setInput();
usb::Vbus::setInput();
// Enable VBUS sense (B device) via pin PA9
USB_OTG_FS->GCCFG &= ~USB_OTG_GCCFG_NOVBUSSENS;
USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_VBUSBSEN;
}

/// @}

}

#endif // MODM_STM32_F401_DISCOVERY_HPP
13 changes: 13 additions & 0 deletions src/modm/board/disco_f401vc/board.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<library>
<repositories>
<repository>
<path>../../../../repo.lb</path>
</repository>
</repositories>
<options>
<option name="modm:target">stm32f401vct6</option>
</options>
<modules>
<module>modm:board:disco-f401vc</module>
</modules>
</library>
Loading

0 comments on commit 2da6c2f

Please sign in to comment.