Skip to content

Commit 1c7af50

Browse files
committed
[stm32] Configure GPIO when connecting to USB
The HS port can use both the DP and DM or the ULPI signals. All signals *must* be configured for high speed though!
1 parent 76cbf62 commit 1c7af50

File tree

2 files changed

+99
-7
lines changed

2 files changed

+99
-7
lines changed

src/modm/platform/usb/stm32/module.lb

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#!/usr/bin/env python3
22
# -*- coding: utf-8 -*-
33
#
4-
# Copyright (c) 2020, Niklas Hauser
4+
# Copyright (c) 2020, 2024, Niklas Hauser
55
#
66
# This file is part of the modm project.
77
#
@@ -58,13 +58,19 @@ def common_usb_irqs(env):
5858
def generate_instance(env, port, otg=False):
5959
env.outbasepath = "modm/src/modm/platform/usb"
6060
irq_data = env.query(":platform:usb:irqs")
61+
all_signals = env.query(":platform:gpio:all_signals")
62+
ulpi_signals = {"Ulpick", "Ulpistp", "Ulpidir", "Ulpinxt",
63+
"Ulpid0", "Ulpid1", "Ulpid2", "Ulpid3",
64+
"Ulpid4", "Ulpid5", "Ulpid6", "Ulpid7"}
65+
is_ulpi = len(ulpi_signals & set(all_signals)) == len(ulpi_signals)
6166
env.substitutions = {
6267
"port": port,
6368
"peripheral": "Usbotg{}".format(port) if otg else "Usb",
6469
"is_otg": otg,
6570
"is_remap": irq_data["is_remap"],
6671
"irqs": irq_data["port_irqs"][port],
6772
"target": env[":target"].identifier,
73+
"is_ulpi": port == "hs" and is_ulpi,
6874
}
6975
if otg:
7076
env.template("usb.hpp.in", "usb_{}.hpp".format(port))
@@ -118,6 +124,7 @@ class UsbInstance(Module):
118124
module.description = "{} Speed".format("Full" if self.speed == "fs" else "High")
119125

120126
def prepare(self, module, options):
127+
module.depends(":platform:gpio")
121128
return True
122129

123130
def build(self, env):

src/modm/platform/usb/stm32/usb.hpp.in

Lines changed: 91 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* Copyright (c) 2020, Erik Henriksson
3-
* Copyright (c) 2020, Niklas Hauser
3+
* Copyright (c) 2020, 2024, Niklas Hauser
44
*
55
* This file is part of the modm project.
66
*
@@ -33,6 +33,14 @@ public:
3333
#ifdef PWR_CR2_USV
3434
PWR->CR2 |= PWR_CR2_USV;
3535
#endif
36+
%% elif target.family in ["h5"]
37+
#ifdef PWR_USBSCR_USB33DEN
38+
PWR->USBSCR |= PWR_USBSCR_USB33DEN;
39+
#endif
40+
%% elif target.family in ["h7"]
41+
#ifdef PWR_CR3_USB33DEN
42+
PWR->CR3 |= PWR_CR3_USB33DEN;
43+
#endif
3644
%% endif
3745
Rcc::enable<Peripheral::{{ peripheral }}>();
3846
%% if is_remap
@@ -48,20 +56,97 @@ public:
4856
connect()
4957
{
5058
using Connector = GpioConnector<Peripheral::{{ peripheral }}, Signals...>;
51-
%% if port == "fs"
5259
using Dp = typename Connector::template GetSignal< Gpio::Signal::Dp >;
5360
using Dm = typename Connector::template GetSignal< Gpio::Signal::Dm >;
5461
%% if is_otg
5562
using Id = typename Connector::template GetSignal< Gpio::Signal::Id >;
5663
%% endif
57-
static_assert(((Connector::template IsValid<Dp> and Connector::template IsValid<Dm>) and sizeof...(Signals) >= 2),
58-
"{{ name }}::connect() requires at least one Dp and one Dm signal!");
64+
static constexpr bool all_usb =
65+
Connector::template IsValid<Dp> and Connector::template IsValid<Dm>;
66+
%% if is_ulpi
67+
static constexpr bool any_usb =
68+
Connector::template IsValid<Dp> or Connector::template IsValid<Dm>;
69+
70+
using Ulpick = typename Connector::template GetSignal< Gpio::Signal::Ulpick >;
71+
using Ulpistp = typename Connector::template GetSignal< Gpio::Signal::Ulpistp >;
72+
using Ulpidir = typename Connector::template GetSignal< Gpio::Signal::Ulpidir >;
73+
using Ulpinxt = typename Connector::template GetSignal< Gpio::Signal::Ulpinxt >;
74+
using Ulpid0 = typename Connector::template GetSignal< Gpio::Signal::Ulpid0 >;
75+
using Ulpid1 = typename Connector::template GetSignal< Gpio::Signal::Ulpid1 >;
76+
using Ulpid2 = typename Connector::template GetSignal< Gpio::Signal::Ulpid2 >;
77+
using Ulpid3 = typename Connector::template GetSignal< Gpio::Signal::Ulpid3 >;
78+
using Ulpid4 = typename Connector::template GetSignal< Gpio::Signal::Ulpid4 >;
79+
using Ulpid5 = typename Connector::template GetSignal< Gpio::Signal::Ulpid5 >;
80+
using Ulpid6 = typename Connector::template GetSignal< Gpio::Signal::Ulpid6 >;
81+
using Ulpid7 = typename Connector::template GetSignal< Gpio::Signal::Ulpid7 >;
82+
83+
static constexpr bool all_ulpi =
84+
Connector::template IsValid< Ulpick > and
85+
Connector::template IsValid< Ulpistp > and
86+
Connector::template IsValid< Ulpidir > and
87+
Connector::template IsValid< Ulpinxt > and
88+
Connector::template IsValid< Ulpid0 > and
89+
Connector::template IsValid< Ulpid1 > and
90+
Connector::template IsValid< Ulpid2 > and
91+
Connector::template IsValid< Ulpid3 > and
92+
Connector::template IsValid< Ulpid4 > and
93+
Connector::template IsValid< Ulpid5 > and
94+
Connector::template IsValid< Ulpid6 > and
95+
Connector::template IsValid< Ulpid7 >;
96+
static constexpr bool any_ulpi =
97+
Connector::template IsValid< Ulpick > or
98+
Connector::template IsValid< Ulpistp > or
99+
Connector::template IsValid< Ulpidir > or
100+
Connector::template IsValid< Ulpinxt > or
101+
Connector::template IsValid< Ulpid0 > or
102+
Connector::template IsValid< Ulpid1 > or
103+
Connector::template IsValid< Ulpid2 > or
104+
Connector::template IsValid< Ulpid3 > or
105+
Connector::template IsValid< Ulpid4 > or
106+
Connector::template IsValid< Ulpid5 > or
107+
Connector::template IsValid< Ulpid6 > or
108+
Connector::template IsValid< Ulpid7 >;
59109

110+
static_assert((any_ulpi xor any_usb) and (all_ulpi or all_usb),
111+
"{{ name }}::connect() requires at least Dp, Dm (+Id) signals OR 12 ULPI signals:\n"
112+
" - CK\n"
113+
" - STP\n"
114+
" - DIR\n"
115+
" - NXT\n"
116+
" - D0\n"
117+
" - D1\n"
118+
" - D2\n"
119+
" - D3\n"
120+
" - D4\n"
121+
" - D5\n"
122+
" - D6\n"
123+
" - D7");
124+
125+
if constexpr (all_ulpi and not all_usb)
126+
{
127+
Rcc::enable<Peripheral::{{ peripheral }}ulpi>();
128+
GpioSet< Ulpick, Ulpistp, Ulpidir, Ulpinxt, Ulpid0, Ulpid1,
129+
Ulpid2, Ulpid3, Ulpid4, Ulpid5, Ulpid6, Ulpid7>::configure(
130+
Gpio::OutputType::PushPull, Gpio::OutputSpeed::High);
131+
}
132+
else if constexpr (not all_ulpi and all_usb)
133+
{
134+
Rcc::disable<Peripheral::{{ peripheral }}ulpi>();
135+
%% set idt = "\t"
136+
%% else
137+
static_assert(all_usb and sizeof...(Signals) >= 2,
138+
"{{ name }}::connect() requires at least one Dp and one Dm signal!");
139+
%% set idt = ""
140+
%% endif
141+
{{idt}}GpioSet<Dp, Dm>::configure(Gpio::OutputType::PushPull, Gpio::OutputSpeed::High);
60142
%% if is_otg
61-
Id::configure(Gpio::OutputType::OpenDrain, Gpio::OutputSpeed::High);
62-
Id::configure(Gpio::InputType::PullUp);
143+
{{idt}}Id::configure(Gpio::OutputType::OpenDrain, Gpio::OutputSpeed::High);
144+
{{idt}}Id::configure(Gpio::InputType::PullUp);
63145
%% endif
146+
%% if is_ulpi
147+
}
64148
%% endif
149+
65150
Connector::connect();
66151
}
67152
};

0 commit comments

Comments
 (0)