modm API documentation
General Purpose I/O (GPIO)

Classes

struct  modm::platform::Gpio
 
struct  modm::platform::GpioConnector< peripheral, Signals >
 
class  modm::platform::GpioInverted< Pin >
 
class  modm::platform::GpioSet< Gpios >
 
class  modm::platform::GpioStatic< GpioData >
 
class  modm::platform::GpioStatic< detail::DataUnused >
 
class  modm::platform::SoftwareGpioPort< Gpios >
 

Typedefs

using modm::platform::GpioUnused = GpioStatic< detail::DataUnused >
 
using modm::platform::GpioA0 = GpioStatic< detail::DataA0 >
 
using modm::platform::GpioOutputA0 = GpioA0
 
using modm::platform::GpioInputA0 = GpioA0
 
using modm::platform::GpioA1 = GpioStatic< detail::DataA1 >
 
using modm::platform::GpioOutputA1 = GpioA1
 
using modm::platform::GpioInputA1 = GpioA1
 
using modm::platform::GpioA2 = GpioStatic< detail::DataA2 >
 
using modm::platform::GpioOutputA2 = GpioA2
 
using modm::platform::GpioInputA2 = GpioA2
 
using modm::platform::GpioA3 = GpioStatic< detail::DataA3 >
 
using modm::platform::GpioOutputA3 = GpioA3
 
using modm::platform::GpioInputA3 = GpioA3
 
using modm::platform::GpioA4 = GpioStatic< detail::DataA4 >
 
using modm::platform::GpioOutputA4 = GpioA4
 
using modm::platform::GpioInputA4 = GpioA4
 
using modm::platform::GpioA5 = GpioStatic< detail::DataA5 >
 
using modm::platform::GpioOutputA5 = GpioA5
 
using modm::platform::GpioInputA5 = GpioA5
 
using modm::platform::GpioA6 = GpioStatic< detail::DataA6 >
 
using modm::platform::GpioOutputA6 = GpioA6
 
using modm::platform::GpioInputA6 = GpioA6
 
using modm::platform::GpioA7 = GpioStatic< detail::DataA7 >
 
using modm::platform::GpioOutputA7 = GpioA7
 
using modm::platform::GpioInputA7 = GpioA7
 
using modm::platform::GpioA8 = GpioStatic< detail::DataA8 >
 
using modm::platform::GpioOutputA8 = GpioA8
 
using modm::platform::GpioInputA8 = GpioA8
 
using modm::platform::GpioA9 = GpioStatic< detail::DataA9 >
 
using modm::platform::GpioOutputA9 = GpioA9
 
using modm::platform::GpioInputA9 = GpioA9
 
using modm::platform::GpioA10 = GpioStatic< detail::DataA10 >
 
using modm::platform::GpioOutputA10 = GpioA10
 
using modm::platform::GpioInputA10 = GpioA10
 
using modm::platform::GpioA11 = GpioStatic< detail::DataA11 >
 
using modm::platform::GpioOutputA11 = GpioA11
 
using modm::platform::GpioInputA11 = GpioA11
 
using modm::platform::GpioA12 = GpioStatic< detail::DataA12 >
 
using modm::platform::GpioOutputA12 = GpioA12
 
using modm::platform::GpioInputA12 = GpioA12
 
using modm::platform::GpioA13 = GpioStatic< detail::DataA13 >
 
using modm::platform::GpioOutputA13 = GpioA13
 
using modm::platform::GpioInputA13 = GpioA13
 
using modm::platform::GpioA14 = GpioStatic< detail::DataA14 >
 
using modm::platform::GpioOutputA14 = GpioA14
 
using modm::platform::GpioInputA14 = GpioA14
 
using modm::platform::GpioA15 = GpioStatic< detail::DataA15 >
 
using modm::platform::GpioOutputA15 = GpioA15
 
using modm::platform::GpioInputA15 = GpioA15
 
using modm::platform::GpioB0 = GpioStatic< detail::DataB0 >
 
using modm::platform::GpioOutputB0 = GpioB0
 
using modm::platform::GpioInputB0 = GpioB0
 
using modm::platform::GpioB1 = GpioStatic< detail::DataB1 >
 
using modm::platform::GpioOutputB1 = GpioB1
 
using modm::platform::GpioInputB1 = GpioB1
 
using modm::platform::GpioB2 = GpioStatic< detail::DataB2 >
 
using modm::platform::GpioOutputB2 = GpioB2
 
using modm::platform::GpioInputB2 = GpioB2
 
using modm::platform::GpioB3 = GpioStatic< detail::DataB3 >
 
using modm::platform::GpioOutputB3 = GpioB3
 
using modm::platform::GpioInputB3 = GpioB3
 
using modm::platform::GpioB4 = GpioStatic< detail::DataB4 >
 
using modm::platform::GpioOutputB4 = GpioB4
 
using modm::platform::GpioInputB4 = GpioB4
 
using modm::platform::GpioB5 = GpioStatic< detail::DataB5 >
 
using modm::platform::GpioOutputB5 = GpioB5
 
using modm::platform::GpioInputB5 = GpioB5
 
using modm::platform::GpioB6 = GpioStatic< detail::DataB6 >
 
using modm::platform::GpioOutputB6 = GpioB6
 
using modm::platform::GpioInputB6 = GpioB6
 
using modm::platform::GpioB7 = GpioStatic< detail::DataB7 >
 
using modm::platform::GpioOutputB7 = GpioB7
 
using modm::platform::GpioInputB7 = GpioB7
 
using modm::platform::GpioB8 = GpioStatic< detail::DataB8 >
 
using modm::platform::GpioOutputB8 = GpioB8
 
using modm::platform::GpioInputB8 = GpioB8
 
using modm::platform::GpioB9 = GpioStatic< detail::DataB9 >
 
using modm::platform::GpioOutputB9 = GpioB9
 
using modm::platform::GpioInputB9 = GpioB9
 
using modm::platform::GpioB10 = GpioStatic< detail::DataB10 >
 
using modm::platform::GpioOutputB10 = GpioB10
 
using modm::platform::GpioInputB10 = GpioB10
 
using modm::platform::GpioB11 = GpioStatic< detail::DataB11 >
 
using modm::platform::GpioOutputB11 = GpioB11
 
using modm::platform::GpioInputB11 = GpioB11
 
using modm::platform::GpioB12 = GpioStatic< detail::DataB12 >
 
using modm::platform::GpioOutputB12 = GpioB12
 
using modm::platform::GpioInputB12 = GpioB12
 
using modm::platform::GpioB13 = GpioStatic< detail::DataB13 >
 
using modm::platform::GpioOutputB13 = GpioB13
 
using modm::platform::GpioInputB13 = GpioB13
 
using modm::platform::GpioB14 = GpioStatic< detail::DataB14 >
 
using modm::platform::GpioOutputB14 = GpioB14
 
using modm::platform::GpioInputB14 = GpioB14
 
using modm::platform::GpioB15 = GpioStatic< detail::DataB15 >
 
using modm::platform::GpioOutputB15 = GpioB15
 
using modm::platform::GpioInputB15 = GpioB15
 
using modm::platform::GpioC0 = GpioStatic< detail::DataC0 >
 
using modm::platform::GpioOutputC0 = GpioC0
 
using modm::platform::GpioInputC0 = GpioC0
 
using modm::platform::GpioC1 = GpioStatic< detail::DataC1 >
 
using modm::platform::GpioOutputC1 = GpioC1
 
using modm::platform::GpioInputC1 = GpioC1
 
using modm::platform::GpioC2 = GpioStatic< detail::DataC2 >
 
using modm::platform::GpioOutputC2 = GpioC2
 
using modm::platform::GpioInputC2 = GpioC2
 
using modm::platform::GpioC3 = GpioStatic< detail::DataC3 >
 
using modm::platform::GpioOutputC3 = GpioC3
 
using modm::platform::GpioInputC3 = GpioC3
 
using modm::platform::GpioC4 = GpioStatic< detail::DataC4 >
 
using modm::platform::GpioOutputC4 = GpioC4
 
using modm::platform::GpioInputC4 = GpioC4
 
using modm::platform::GpioC5 = GpioStatic< detail::DataC5 >
 
using modm::platform::GpioOutputC5 = GpioC5
 
using modm::platform::GpioInputC5 = GpioC5
 
using modm::platform::GpioC6 = GpioStatic< detail::DataC6 >
 
using modm::platform::GpioOutputC6 = GpioC6
 
using modm::platform::GpioInputC6 = GpioC6
 
using modm::platform::GpioC7 = GpioStatic< detail::DataC7 >
 
using modm::platform::GpioOutputC7 = GpioC7
 
using modm::platform::GpioInputC7 = GpioC7
 
using modm::platform::GpioC8 = GpioStatic< detail::DataC8 >
 
using modm::platform::GpioOutputC8 = GpioC8
 
using modm::platform::GpioInputC8 = GpioC8
 
using modm::platform::GpioC9 = GpioStatic< detail::DataC9 >
 
using modm::platform::GpioOutputC9 = GpioC9
 
using modm::platform::GpioInputC9 = GpioC9
 
using modm::platform::GpioC10 = GpioStatic< detail::DataC10 >
 
using modm::platform::GpioOutputC10 = GpioC10
 
using modm::platform::GpioInputC10 = GpioC10
 
using modm::platform::GpioC11 = GpioStatic< detail::DataC11 >
 
using modm::platform::GpioOutputC11 = GpioC11
 
using modm::platform::GpioInputC11 = GpioC11
 
using modm::platform::GpioC12 = GpioStatic< detail::DataC12 >
 
using modm::platform::GpioOutputC12 = GpioC12
 
using modm::platform::GpioInputC12 = GpioC12
 
using modm::platform::GpioC13 = GpioStatic< detail::DataC13 >
 
using modm::platform::GpioOutputC13 = GpioC13
 
using modm::platform::GpioInputC13 = GpioC13
 
using modm::platform::GpioC14 = GpioStatic< detail::DataC14 >
 
using modm::platform::GpioOutputC14 = GpioC14
 
using modm::platform::GpioInputC14 = GpioC14
 
using modm::platform::GpioC15 = GpioStatic< detail::DataC15 >
 
using modm::platform::GpioOutputC15 = GpioC15
 
using modm::platform::GpioInputC15 = GpioC15
 
using modm::platform::GpioD0 = GpioStatic< detail::DataD0 >
 
using modm::platform::GpioOutputD0 = GpioD0
 
using modm::platform::GpioInputD0 = GpioD0
 
using modm::platform::GpioD1 = GpioStatic< detail::DataD1 >
 
using modm::platform::GpioOutputD1 = GpioD1
 
using modm::platform::GpioInputD1 = GpioD1
 
using modm::platform::GpioD2 = GpioStatic< detail::DataD2 >
 
using modm::platform::GpioOutputD2 = GpioD2
 
using modm::platform::GpioInputD2 = GpioD2
 
using modm::platform::GpioD3 = GpioStatic< detail::DataD3 >
 
using modm::platform::GpioOutputD3 = GpioD3
 
using modm::platform::GpioInputD3 = GpioD3
 
using modm::platform::GpioD4 = GpioStatic< detail::DataD4 >
 
using modm::platform::GpioOutputD4 = GpioD4
 
using modm::platform::GpioInputD4 = GpioD4
 
using modm::platform::GpioD5 = GpioStatic< detail::DataD5 >
 
using modm::platform::GpioOutputD5 = GpioD5
 
using modm::platform::GpioInputD5 = GpioD5
 
using modm::platform::GpioD6 = GpioStatic< detail::DataD6 >
 
using modm::platform::GpioOutputD6 = GpioD6
 
using modm::platform::GpioInputD6 = GpioD6
 
using modm::platform::GpioD8 = GpioStatic< detail::DataD8 >
 
using modm::platform::GpioOutputD8 = GpioD8
 
using modm::platform::GpioInputD8 = GpioD8
 
using modm::platform::GpioD9 = GpioStatic< detail::DataD9 >
 
using modm::platform::GpioOutputD9 = GpioD9
 
using modm::platform::GpioInputD9 = GpioD9
 
using modm::platform::GpioF0 = GpioStatic< detail::DataF0 >
 
using modm::platform::GpioOutputF0 = GpioF0
 
using modm::platform::GpioInputF0 = GpioF0
 
using modm::platform::GpioF1 = GpioStatic< detail::DataF1 >
 
using modm::platform::GpioOutputF1 = GpioF1
 
using modm::platform::GpioInputF1 = GpioF1
 
using modm::platform::GpioF2 = GpioStatic< detail::DataF2 >
 
using modm::platform::GpioOutputF2 = GpioF2
 
using modm::platform::GpioInputF2 = GpioF2
 

Detailed Description

lbuild module: modm:platform:gpio

This module provides register access to GPIO and connect their signals to the respective peripherals in a compile-time verified way. This module also enables all GPIO peripheral clocks on startup by default.

Each GPIO is represented as its own class with only static methods, which implement the modm::GpioIO interface and provide additional platform-specific methods.

using namespace modm::platform;
using Button = GpioA0;
Button::setInput(Gpio::InputType::PullUp);
bool input = Button::read();
using Led = GpioInverted<GpioB3>; // inverts the IO logic of the pin
Led::setOutput(Gpio::OutputType::OpenDrain, Gpio::OutputSpeed::MHz2);
Led::set(input);
using Analog = GpioC12;
Analog::setAnalogInput(); // Use pin for ADC/DAC/COMP
Analog::lock(); // this prevents changes until next reboot
using Signal = GpioD9;
Signal::setAlternateFunction(4); // For AF id see datasheet
Signal::setAlternateFunction(); // STM32F1 has no AF id
Signal::disconnect(); // Switch back to floating input
// Some STM32s have remappable pinouts
GpioA11::remap(); // STM32G0: Remap A9 -> A11.

You can also use an unordered set of GPIOs, which is useful when configuring a large number of pins, since the register accesses will be bundled and thus less code is generated.

using Set = GpioSet<GpioA0, GpioB1, GpioC2, GpioD3>;
Set::setInput();

To write and read a set of GPIOs, you need to use an ordered implementation, which defines the pins from MSB to LSB, left-to-right. You can also check the number of ports in case your use-case requires atomic reads/writes.

using Port = SoftwareGpioPort<GpioA10, GpioA2, GpioA6, GpioA14>;
static_assert(Port::number_of_ports == 1, "Read/write needs to be atomic");
Port::setOutput(Gpio::OutputType::OpenDrain);
Port::configure(Gpio::InputType::PullUp);
uint8_t nibble = Port::read();
Port::write(nibble);

For efficient access you can use a strictly-ordered implementation with a start pin and width. Note that you can reverse the data order with a negative width.

using Port = GpioPort<GpioA0, 8>;
Port::setOutput();
Port::write(data);
using ReversePort = GpioPort<GpioB7, -8>;
ReversePort::setInput();
uint8_t data = ReversePort::read();

Finally, you can use an empty GPIO implementation in cases where the API requires a GPIO, but you don't need one, for example, a bit-banged SPI without MISO pin:

Alternate Function Signals

To make it easier to connect pins with peripherals, this module implements a compile-time map of (pin, signal, peripheral) to Alternate Function ID (AF). Note that you must provide both peripherals and signals to be unambiguous.

GpioConnector<Peripheral::Usart1, GpioD0::Tx, GpioD1::Rx>::connect();

However, it is recommended to wrap this functionality into a separate function Driver::connect<Signals...>(config), so that additional driver specific pin configuration can be done:

template< class... Signals >
void Uart1::connect()
{
Connector = GpioConnector<Peripheral::Usart1, Signals...>;
Connector::disconnect(); // reset to floating input
// extract pins from signals
using Rx = Connector::GetSignal<Gpio::Signal::Rx>;
using Tx = Connector::GetSignal<Gpio::Signal::Tx>;
// if not found, returns GpioUnused, you can check for this case
static_assert(not Connector::isValid<Tx>,
"This UART driver requires the Tx signal");
// configure both pins
Rx::configure(Gpio::InputType::PullUp);
Tx::configure(Gpio::OutputType::PushPull);
// connect both pins to alternate functions
// This will static assert if signals do not make sense
Connector::connect();
}
// Connect these pin signals to Usart1
Uart1::connect<GpioD0::Tx, GpioD1::Rx>();

Note that you may pass a variable number of signals to this connect function, leaving out signals you don't need and adding signals that are not required.

// Connect only one signal
Uart1::connect<GpioD0::Tx>();
// Connect more signals than required
Uart1::connect<GpioD0::Tx, GpioD2::Cts>();

Module Options

modm:platform:gpio:enable_ports: Enable clock for these GPIO ports during startup

Generated with: {A, B, C, D, F} in [A, B, C, D, F]