Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add disco_f411ve #1135

Merged
merged 1 commit into from
Mar 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 15 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -624,73 +624,74 @@ We have out-of-box support for many development boards including documentation.
<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-f411ve">DISCO-F411VE</a></td>
</tr><tr>
<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>
<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>
</tr><tr>
<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>
<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>
</tr><tr>
<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>
<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>
</tr><tr>
<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>
<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>
</tr><tr>
<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>
<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>
</tr><tr>
<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>
<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>
</tr><tr>
<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>
<td align="center"><a href="https://modm.io/reference/config/modm-nucleo-g070rb">NUCLEO-G070RB</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>
</tr><tr>
<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>
<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>
</tr><tr>
<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>
<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>
</tr><tr>
<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>
<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>
</tr><tr>
<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>
<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>
</tr><tr>
<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>
<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>
</tr><tr>
<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>
<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>
</tr><tr>
<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>
</table>
Expand Down
1 change: 1 addition & 0 deletions examples/generic/usb/project.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<!-- <extends>modm:disco-f072rb</extends> -->
<!-- <extends>modm:disco-f303vc</extends> -->
<!-- <extends>modm:disco-f407vg</extends> -->
<!-- <extends>modm:disco-f411ve</extends> -->
<!-- <extends>modm:disco-f429zi</extends> -->
<!-- <extends>modm:disco-f469ni</extends> -->
<!-- <extends>modm:disco-f746ng</extends> -->
Expand Down
231 changes: 231 additions & 0 deletions src/modm/board/disco_f411ve/board.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
/*
* Copyright (c) 2024, Thomas Sommer
*
* 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/.
*/
// ----------------------------------------------------------------------------
#pragma once

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

using namespace modm::platform;

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

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

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 Spi5 = Apb2;

static constexpr uint32_t Usart1 = Apb2;
static constexpr uint32_t Usart2 = Apb1;
static constexpr uint32_t Usart3 = Apb1;
static constexpr uint32_t Uart4 = Apb1;
static constexpr uint32_t Uart5 = Apb1;
static constexpr uint32_t Usart6 = Apb2;
static constexpr uint32_t Uart7 = Apb1;
static constexpr uint32_t Uart8 = 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 Timer9 = Apb2Timer;
static constexpr uint32_t Timer10 = Apb2Timer;
static constexpr uint32_t Timer11 = Apb2Timer;

static constexpr uint32_t Usb = 48_MHz;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this correct?

Copy link
Contributor Author

@TomSaw TomSaw Mar 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've setup a PWM on Timer10 and Timer11, confirmed the output frequency and looks fine.

But could not make USB / TinyUSB working.
Please give me some advice!

Observations:

  • Power on without Usb-Cable, Leds blink period = 2.5s -> Seems to be the initial default
  • Connecting an Usb-Cable, the Leds blink period remains at 2.5s -> tud_mount_cb() not invoked.
  • However, when disconnecting the Usb-Cable, the blink period changes to 250ms -> tud_umount_cb() invoked!
  • Reconnecting the cable again, changes nothing. The blink period remains at 250ms.
  • Only a reset gets me back to 2.5s right now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's cos the USB is running at 50MHz and not 48MHz, hence my question about whether this clock is correct ;-P It probably works for a short time, but then gets out of sync.

CubeMX shows this solution running the CPU at 96MHz and USB at 48MHz:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, the /Q prescaler isn't set at all, so the USB probably runs at 100MHz or something completely wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, i have not really tried to iunderstand the clock system yet. So i got a copy of CubeMX as it looks like an usefull reference. Have seen this graphical configurator before but your screenshot finally convinced me to give it a closer look, thanks!

USB now works 😄

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I swapped the prescalers to align with the CubeMX solution, so the CPU now runs at 96MHz and the USB still at 48MHz.

Copy link
Contributor Author

@TomSaw TomSaw Mar 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PLL statements in all board.hpp could be moved above the SystemClock struct to calculate
SystemClock::Frequency and SystemClock::Usb

👉🏾 This would document the causality and the "...Usb requires 48Mhz..." assertion somewhere else in modm would have catched me!

Something like this:

static constexpr uint32_t CrystalHSE = 8;
const Rcc::PllFactors pllFactors {
   ...
}

static constexpr uint32_t MainPllClock = CrystalHSE / PllFactors.pllM * PllFactors.pllN;

static constexpr uint32_t SystemClock::Frequency = MainPllClock / PllFactors.pllP;
static constexpr uint32_t SystemClock::Usb = MainPllClock / PllFactors.pllQ;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ohhhhhhh, that's an excellent idea!!! I'll merge this first, then prototype it. We can probably also put the AHB/APB prescalers in there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Something easy, to build up 'momentum of success' will also support my motivational chemistry to complete the old graphic related PRs.

Copy link
Contributor Author

@TomSaw TomSaw Mar 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've quickly sketched this in #1137


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

return true;
}
};

using LedUsb = GpioOutputA9;
using ClockOut = GpioOutputA8;
using SystemClockOut = GpioOutputC9;

using Button = GpioInputA0;

// 4 user colored LEDs aligned in a circle
using LedGreen = GpioOutputD12;
using LedOrange = GpioOutputD13;
using LedRed = GpioOutputD14;
using LedBlue = GpioOutputD15;
using Leds = SoftwareGpioPort<LedGreen, LedBlue, LedRed, LedOrange>;
/// @}

namespace lis3
{
/// @ingroup modm_board_disco_f411ve
/// @{
using Int = GpioInputE1; // LIS302DL_INT2

using Cs = GpioOutputE3; // LIS302DL_CS_I2C/SPI
using Sck = GpioOutputA5; // SPI1_SCK
using Mosi = GpioOutputA7; // SPI1_MOSI
using Miso = GpioInputA6; // SPI1_MISO

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


namespace cs43
{
/// @ingroup modm_board_disco_f411ve
/// @{
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_f411ve
/// @{
using Clk = GpioOutputB10; // CLK_IN: I2S2_CK
using Dout = GpioInputC3; // PDM_OUT: I2S2_SD
// using I2sMaster = I2sMaster2;
/// @}
}


namespace usb
{
/// @ingroup modm_board_disco_f411ve
/// @{
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_f411ve
/// @{
inline void
initialize()
{
SystemClock::enable();
SysTickTimer::initialize<SystemClock>();

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

Button::setInput(Gpio::InputType::Floating);
}

inline void
initializeLis3()
{
lis3::Int::setInput();
lis3::Cs::setOutput(modm::Gpio::High);

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

/// 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>();
}

/// 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;
}
/// @}
}
14 changes: 14 additions & 0 deletions src/modm/board/disco_f411ve/board.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<library>
<repositories>
<repository>
<path>../../../../repo.lb</path>
</repository>
</repositories>

<options>
<option name="modm:target">stm32f411vet6</option>
</options>
<modules>
<module>modm:board:disco-f411ve</module>
</modules>
</library>
46 changes: 46 additions & 0 deletions src/modm/board/disco_f411ve/module.lb
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2024, Thomas Sommer
#
# 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/.
# -----------------------------------------------------------------------------

def init(module):
module.name = ":board:disco-f411ve"
module.description = """\
# STM32F4DISCOVERY

[Discovery kit for STM32F411](https://www.st.com/en/evaluation-tools/32f411ediscovery.html)
"""

def prepare(module, options):
if not options[":target"].partname.startswith("stm32f411ve"):
return False

module.depends(
":architecture:clock",
":driver:lis3dsh",
":driver:lsm303a",
":driver:l3gd20",
":platform:clock",
":platform:core",
":platform:gpio",
":platform:i2c:1",
":platform:spi:1",
":platform:usb:fs")
return True

def build(env):
env.outbasepath = "modm/src/modm/board"
env.substitutions = {
"with_logger": False,
"with_assert": env.has_module(":architecture:assert")
}
env.template("../board.cpp.in", "board.cpp")
env.copy('.')
env.collect(":build:openocd.source", "board/stm32f4discovery.cfg");