Skip to content

Commit

Permalink
[stm32] Configure GPIO when connecting to USB
Browse files Browse the repository at this point in the history
The HS port can use both the DP and DM or the ULPI signals.
All signals *must* be configured for high speed though!
  • Loading branch information
salkinium committed Jan 5, 2024
1 parent 76cbf62 commit 1c7af50
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 7 deletions.
9 changes: 8 additions & 1 deletion src/modm/platform/usb/stm32/module.lb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2020, Niklas Hauser
# Copyright (c) 2020, 2024, Niklas Hauser
#
# This file is part of the modm project.
#
Expand Down Expand Up @@ -58,13 +58,19 @@ def common_usb_irqs(env):
def generate_instance(env, port, otg=False):
env.outbasepath = "modm/src/modm/platform/usb"
irq_data = env.query(":platform:usb:irqs")
all_signals = env.query(":platform:gpio:all_signals")
ulpi_signals = {"Ulpick", "Ulpistp", "Ulpidir", "Ulpinxt",
"Ulpid0", "Ulpid1", "Ulpid2", "Ulpid3",
"Ulpid4", "Ulpid5", "Ulpid6", "Ulpid7"}
is_ulpi = len(ulpi_signals & set(all_signals)) == len(ulpi_signals)
env.substitutions = {
"port": port,
"peripheral": "Usbotg{}".format(port) if otg else "Usb",
"is_otg": otg,
"is_remap": irq_data["is_remap"],
"irqs": irq_data["port_irqs"][port],
"target": env[":target"].identifier,
"is_ulpi": port == "hs" and is_ulpi,
}
if otg:
env.template("usb.hpp.in", "usb_{}.hpp".format(port))
Expand Down Expand Up @@ -118,6 +124,7 @@ class UsbInstance(Module):
module.description = "{} Speed".format("Full" if self.speed == "fs" else "High")

def prepare(self, module, options):
module.depends(":platform:gpio")
return True

def build(self, env):
Expand Down
97 changes: 91 additions & 6 deletions src/modm/platform/usb/stm32/usb.hpp.in
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2020, Erik Henriksson
* Copyright (c) 2020, Niklas Hauser
* Copyright (c) 2020, 2024, Niklas Hauser
*
* This file is part of the modm project.
*
Expand Down Expand Up @@ -33,6 +33,14 @@ public:
#ifdef PWR_CR2_USV
PWR->CR2 |= PWR_CR2_USV;
#endif
%% elif target.family in ["h5"]
#ifdef PWR_USBSCR_USB33DEN
PWR->USBSCR |= PWR_USBSCR_USB33DEN;
#endif
%% elif target.family in ["h7"]
#ifdef PWR_CR3_USB33DEN
PWR->CR3 |= PWR_CR3_USB33DEN;
#endif
%% endif
Rcc::enable<Peripheral::{{ peripheral }}>();
%% if is_remap
Expand All @@ -48,20 +56,97 @@ public:
connect()
{
using Connector = GpioConnector<Peripheral::{{ peripheral }}, Signals...>;
%% if port == "fs"
using Dp = typename Connector::template GetSignal< Gpio::Signal::Dp >;
using Dm = typename Connector::template GetSignal< Gpio::Signal::Dm >;
%% if is_otg
using Id = typename Connector::template GetSignal< Gpio::Signal::Id >;
%% endif
static_assert(((Connector::template IsValid<Dp> and Connector::template IsValid<Dm>) and sizeof...(Signals) >= 2),
"{{ name }}::connect() requires at least one Dp and one Dm signal!");
static constexpr bool all_usb =
Connector::template IsValid<Dp> and Connector::template IsValid<Dm>;
%% if is_ulpi
static constexpr bool any_usb =
Connector::template IsValid<Dp> or Connector::template IsValid<Dm>;

using Ulpick = typename Connector::template GetSignal< Gpio::Signal::Ulpick >;
using Ulpistp = typename Connector::template GetSignal< Gpio::Signal::Ulpistp >;
using Ulpidir = typename Connector::template GetSignal< Gpio::Signal::Ulpidir >;
using Ulpinxt = typename Connector::template GetSignal< Gpio::Signal::Ulpinxt >;
using Ulpid0 = typename Connector::template GetSignal< Gpio::Signal::Ulpid0 >;
using Ulpid1 = typename Connector::template GetSignal< Gpio::Signal::Ulpid1 >;
using Ulpid2 = typename Connector::template GetSignal< Gpio::Signal::Ulpid2 >;
using Ulpid3 = typename Connector::template GetSignal< Gpio::Signal::Ulpid3 >;
using Ulpid4 = typename Connector::template GetSignal< Gpio::Signal::Ulpid4 >;
using Ulpid5 = typename Connector::template GetSignal< Gpio::Signal::Ulpid5 >;
using Ulpid6 = typename Connector::template GetSignal< Gpio::Signal::Ulpid6 >;
using Ulpid7 = typename Connector::template GetSignal< Gpio::Signal::Ulpid7 >;

static constexpr bool all_ulpi =
Connector::template IsValid< Ulpick > and
Connector::template IsValid< Ulpistp > and
Connector::template IsValid< Ulpidir > and
Connector::template IsValid< Ulpinxt > and
Connector::template IsValid< Ulpid0 > and
Connector::template IsValid< Ulpid1 > and
Connector::template IsValid< Ulpid2 > and
Connector::template IsValid< Ulpid3 > and
Connector::template IsValid< Ulpid4 > and
Connector::template IsValid< Ulpid5 > and
Connector::template IsValid< Ulpid6 > and
Connector::template IsValid< Ulpid7 >;
static constexpr bool any_ulpi =
Connector::template IsValid< Ulpick > or
Connector::template IsValid< Ulpistp > or
Connector::template IsValid< Ulpidir > or
Connector::template IsValid< Ulpinxt > or
Connector::template IsValid< Ulpid0 > or
Connector::template IsValid< Ulpid1 > or
Connector::template IsValid< Ulpid2 > or
Connector::template IsValid< Ulpid3 > or
Connector::template IsValid< Ulpid4 > or
Connector::template IsValid< Ulpid5 > or
Connector::template IsValid< Ulpid6 > or
Connector::template IsValid< Ulpid7 >;

static_assert((any_ulpi xor any_usb) and (all_ulpi or all_usb),
"{{ name }}::connect() requires at least Dp, Dm (+Id) signals OR 12 ULPI signals:\n"
" - CK\n"
" - STP\n"
" - DIR\n"
" - NXT\n"
" - D0\n"
" - D1\n"
" - D2\n"
" - D3\n"
" - D4\n"
" - D5\n"
" - D6\n"
" - D7");

if constexpr (all_ulpi and not all_usb)
{
Rcc::enable<Peripheral::{{ peripheral }}ulpi>();
GpioSet< Ulpick, Ulpistp, Ulpidir, Ulpinxt, Ulpid0, Ulpid1,
Ulpid2, Ulpid3, Ulpid4, Ulpid5, Ulpid6, Ulpid7>::configure(
Gpio::OutputType::PushPull, Gpio::OutputSpeed::High);
}
else if constexpr (not all_ulpi and all_usb)
{
Rcc::disable<Peripheral::{{ peripheral }}ulpi>();
%% set idt = "\t"
%% else
static_assert(all_usb and sizeof...(Signals) >= 2,
"{{ name }}::connect() requires at least one Dp and one Dm signal!");
%% set idt = ""
%% endif
{{idt}}GpioSet<Dp, Dm>::configure(Gpio::OutputType::PushPull, Gpio::OutputSpeed::High);
%% if is_otg
Id::configure(Gpio::OutputType::OpenDrain, Gpio::OutputSpeed::High);
Id::configure(Gpio::InputType::PullUp);
{{idt}}Id::configure(Gpio::OutputType::OpenDrain, Gpio::OutputSpeed::High);
{{idt}}Id::configure(Gpio::InputType::PullUp);
%% endif
%% if is_ulpi
}
%% endif

Connector::connect();
}
};
Expand Down

0 comments on commit 1c7af50

Please sign in to comment.