Skip to content

Commit 5557d17

Browse files
committed
fixup! [rp] Add GPIO module
1 parent 6c11367 commit 5557d17

File tree

1 file changed

+122
-5
lines changed

1 file changed

+122
-5
lines changed

src/modm/platform/gpio/rp/module.md

Lines changed: 122 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,125 @@
1-
# RP2040 Signals API
1+
# General Purpose I/O (GPIO)
22

3-
This module provides a way to use the GPIO pins of the RP2040 device. The raw
4-
GPIO API is defined with the following goals:
3+
This module provides register access to GPIO and connect their signals to the
4+
respective peripherals in a compile-time verified way.
55

6-
- Statically type checked
7-
- Aligned (to the extent possible) with other modm platforms
6+
Each GPIO is represented as its own class with only static methods, which
7+
implement the `modm::GpioIO` interface and provide additional platform-specific
8+
methods.
89

10+
```cpp
11+
using namespace modm::platform;
12+
13+
using Button = GpioInput0;
14+
Button::setInput(Gpio::InputType::PullUp);
15+
bool input = Button::read();
16+
17+
using Led = GpioInverted<GpioOuput3>; // inverts the IO logic of the pin
18+
19+
Led::setOutput(Gpio::OutputType::PushPull, Gpio::OutputSpeed::Fast);
20+
Led::set(input);
21+
22+
using Signal = Gpio4;
23+
Signal::setFunction(4); // For func id see datasheet
24+
Signal::disconnect(); // Switch back to floating input
25+
26+
using OpenDrain = GpioOpenDrain<Gpio5>;
27+
OpenDrain::setInput(Gpio::InputType::PullUp);
28+
OpenDrain::set(); // Input with Pullup
29+
OpenDrain::reset(); // Output with PushPull Low
30+
```
31+
32+
You can also use an unordered set of GPIOs, which is useful when configuring a
33+
large number of pins, since the register accesses will be bundled and thus less
34+
code is generated.
35+
36+
```cpp
37+
using Set = GpioSet<Gpio0, Gpio27, Gpio12, Gpio4>;
38+
Set::setInput();
39+
```
40+
41+
To write and read a set of GPIOs, you need to use an ordered implementation,
42+
which defines the pins from MSB to LSB, left-to-right. You can also check the
43+
number of ports in case your use-case requires atomic reads/writes.
44+
45+
```cpp
46+
using Port = SoftwareGpioPort<Gpio10, Gpio2, Gpio6, Gpio14>;
47+
static_assert(Port::number_of_ports == 1, "Read/write needs to be atomic");
48+
Port::setInput(Gpio::InputType::PullUp);
49+
uint8_t nibble = Port::read();
50+
Port::setOutput();
51+
Port::write(nibble);
52+
```
53+
54+
For efficient access you can use a strictly-ordered implementation with a start
55+
pin and width. Note that you can reverse the data order with a negative width.
56+
57+
```cpp
58+
using Port = GpioPort<Gpio0, 8>;
59+
Port::setOutput();
60+
Port::write(data);
61+
62+
using ReversePort = GpioPort<Gpio7, -8>;
63+
ReversePort::setInput();
64+
uint8_t data = ReversePort::read();
65+
```
66+
67+
Finally, you can use an empty GPIO implementation in cases where the API
68+
requires a GPIO, but you don't need one, for example, a bit-banged SPI without
69+
MISO pin:
70+
71+
```cpp
72+
// write only SPI
73+
using SPI = modm::platform::BitBangSpiMaster<Gpio0, Gpio1, GpioUnused>;
74+
```
75+
76+
77+
## Function Signals
78+
79+
To make it easier to connect pins with peripherals, this module implements a
80+
compile-time map of (pin, signal, peripheral) to Function ID (func).
81+
Note that you must provide both peripherals and signals to be unambiguous.
82+
83+
```cpp
84+
GpioConnector<Peripheral::Uart1, Gpio0::Tx, Gpio1::Rx>::connect();
85+
```
86+
87+
However, it is recommended to wrap this functionality into a separate function
88+
`Driver::connect<Signals...>(config)`, so that additional driver specific pin
89+
configuration can be done:
90+
91+
```cpp
92+
template< class... Signals >
93+
void Uart1::connect()
94+
{
95+
Connector = GpioConnector<Peripheral::Uart1, Signals...>;
96+
Connector::disconnect(); // reset to floating input
97+
98+
// extract pins from signals
99+
using Rx = Connector::GetSignal<Gpio::Signal::Rx>;
100+
using Tx = Connector::GetSignal<Gpio::Signal::Tx>;
101+
// if not found, returns GpioUnused, you can check for this case
102+
static_assert(not Connector::isValid<Tx>,
103+
"This UART driver requires the Tx signal");
104+
105+
// configure both pins
106+
Rx::configure(Gpio::InputType::PullUp);
107+
Tx::configure(Gpio::OutputType::PushPull);
108+
109+
// connect both pins to alternate functions
110+
// This will static assert if signals do not make sense
111+
Connector::connect();
112+
}
113+
// Connect these pin signals to Uart1
114+
Uart1::connect<Gpio0::Tx, Gpio1::Rx>();
115+
```
116+
117+
Note that you may pass a *variable* number of signals to this connect function,
118+
leaving out signals you don't need and adding signals that are not required.
119+
120+
```cpp
121+
// Connect only one signal
122+
Uart1::connect<Gpio0::Tx>();
123+
// Connect more signals than required
124+
Uart1::connect<Gpio0::Tx, Gpio2::Cts>();
125+
```

0 commit comments

Comments
 (0)