Skip to content
Draft
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
33 changes: 24 additions & 9 deletions examples/stm32f3_discovery/blink/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,45 @@

using namespace Board;

RtGpio north = Board::LedNorth();
RtGpio northEast = Board::LedNorthEast();
RtGpio east = Board::LedEast();
RtGpio southEast = Board::LedSouthEast();
RtGpio south = Board::LedSouth();
RtGpio southWest = Board::LedSouthWest();
RtGpio west = Board::LedWest();
RtGpio northWest = Board::LedNorthWest();

modm::Gpio &gnorth = north;

int
main()
{
Board::initialize();

Board::LedNorth::set();
using Config = modm::Gpio::Config;
gnorth.configure(Config::Output | Config::OpenDrain |
Config::PullUp | Config::SpeedLow |
Config::LogicInverted);
gnorth.set(true);

while (true)
{
Board::LedNorth::toggle();
north.toggle();
modm::delay(100ms);
Board::LedNorthEast::toggle();
northEast.toggle();
modm::delay(100ms);
Board::LedEast::toggle();
east.toggle();
modm::delay(100ms);
Board::LedSouthEast::toggle();
southEast.toggle();
modm::delay(100ms);
Board::LedSouth::toggle();
south.toggle();
modm::delay(100ms);
Board::LedSouthWest::toggle();
southWest.toggle();
modm::delay(100ms);
Board::LedWest::toggle();
west.toggle();
modm::delay(100ms);
Board::LedNorthWest::toggle();
northWest.toggle();
modm::delay(100ms);
}

Expand Down
41 changes: 37 additions & 4 deletions src/modm/architecture/interface/gpio.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,19 @@
*/
// ----------------------------------------------------------------------------

#ifndef MODM_GPIO_HPP
#define MODM_GPIO_HPP
#pragma once

#include <stdint.h>
#include <modm/architecture/utils.hpp>
#include <modm/architecture/interface/register.hpp>

namespace modm
{

/// @ingroup modm_architecture_gpio
struct Gpio
class Gpio
{
public:
/**
* These constants refer to the *logical* state of the GPIO.
* The physical state is determined by the configuration and external connection.
Expand All @@ -40,6 +41,39 @@ struct Gpio
InOut = 2, //< GPIO is both Input and Output
Special = 3, //< GPIO is configured with a special purpose
};

// Delegate to the platform for the Config_t implementation
#include <modm/platform/gpio/config.hpp>

public:
virtual ~Gpio() {};

// Config methods
virtual void
configure(Config_t config) = 0;

// Input methods
virtual bool
read() const = 0;

// Output methods
virtual void
set(bool value) = 0;

virtual bool
isSet() const = 0;

virtual void
toggle()
{ set(not isSet()); }

inline void
set()
{ set(true); }

inline void
reset()
{ set(false); }
};

/**
Expand Down Expand Up @@ -187,4 +221,3 @@ class GpioPort

} // namespace modm

#endif // MODM_GPIO_HPP
93 changes: 93 additions & 0 deletions src/modm/platform/gpio/stm32/config.hpp.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
* Copyright (c) 2016-2018, Niklas Hauser
*
* 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

enum class
Config : uint32_t
{
/// @cond
_Mode = 0x8000'0000,
Copy link
Member

@chris-durand chris-durand May 15, 2021

Choose a reason for hiding this comment

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

Identifiers starting with _ + upper case letters are reserved in C++ for the standard library implementation.

_ModeMaskAf = 0x0000'000f,
_ModeShiftAf = 0,
_ModeMask = 0x0000'0030,
_ModeShift = 4,
_Alternate = 0x20 | _Mode,

_Input = 0x4000'0000,
_InputMask = 0x0000'0f00,
_InputShift = 8,

_Output = 0x2000'0000,
_OutputMask = 0x0000'f000,
_OutputShift = 12,

_Speed = 0x1000'0000,
_SpeedMask = 0x0003'0000,
_SpeedShift = 16,

_Logic = 0x0800'0000,
_LogicMask = 0x0010'0000,
_LogicShift = 20,
/// @endcond

Input = 0x00 | _Mode,
Output = 0x10 | _Mode,
%% if target["family"] in ["f1"]
Alternate = 0x20 | _Mode,
%% endif
Analog = 0x30 | _Mode,

%% if target["family"] in ["f1"]
Floating = 0x400 | _Input,
PullUp = 0x900 | _Input,
PullDown = 0x800 | _Input,
%% else
Floating = 0x000 | _Input,
PullUp = 0x100 | _Input,
PullDown = 0x200 | _Input,
%% endif

PushPull = 0x0000 | _Output,
%% if target["family"] in ["f1"]
OpenDrain = 0x4000 | _Output,
%% else
OpenDrain = 0x1000 | _Output,
%% endif

%% if target["family"] in ["f1"]
SpeedLow = 0x2'0000 | _Speed,
SpeedMedium = 0x1'0000 | _Speed,
SpeedHigh = 0x3'0000 | _Speed,
SpeedVeryHigh = 0x3'0000 | _Speed,
%% elif target["family"] in ["f0", "f3"]
SpeedLow = 0x0'0000 | _Speed,
SpeedMedium = 0x1'0000 | _Speed,
SpeedHigh = 0x3'0000 | _Speed,
SpeedVeryHigh = 0x3'0000 | _Speed,
%% else
SpeedLow = 0x0'0000 | _Speed,
SpeedMedium = 0x1'0000 | _Speed,
SpeedHigh = 0x2'0000 | _Speed,
SpeedVeryHigh = 0x3'0000 | _Speed,
%% endif

LogicNormal = 0x00'0000 | _Logic,
LogicInverted = 0x10'0000 | _Logic,
};
MODM_FLAGS32(Config);

%% if target["family"] not in ["f1"]
static constexpr Config_t
ConfigAlternate(uint8_t af)
{ return Config::_Mode | Config(0x20 | (af & 0xf)); }
%% endif

1 change: 1 addition & 0 deletions src/modm/platform/gpio/stm32/module.lb
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ def build(env):
if "f1" in driver["type"]:
env.template("connector_specialized.hpp.in", filters={"formatPeripheral": get_driver, "printSignalMap": print_remap_group_table})
env.template("base.hpp.in")
env.template("config.hpp.in")
env.template("unused.hpp.in")
if len(env["enable_ports"]):
env.template("enable.cpp.in")
Expand Down
25 changes: 24 additions & 1 deletion src/modm/platform/gpio/stm32/pin.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ using GpioInput{{ port ~ pin }} = Gpio{{ port ~ pin }};

/// IO class for Pin {{port ~ pin}}
/// @ingroup modm_platform_gpio
class Gpio{{ port ~ pin }} : public Gpio, public ::modm::GpioIO
class Gpio{{ port ~ pin }} : public Gpio
{
template<class... Gpios>
friend class GpioSet;
Expand All @@ -40,10 +40,14 @@ class Gpio{{ port ~ pin }} : public Gpio, public ::modm::GpioIO
friend class Adc1; friend class Adc2;
friend class Adc3; friend class Adc4;
public:
using Direction = ::modm::Gpio::Direction;
using Config = ::modm::Gpio::Config;
using Config_t = ::modm::Gpio::Config_t;
using Output = Gpio{{ port ~ pin }};
using Input = Gpio{{ port ~ pin }};
using IO = Gpio{{ port ~ pin }};
using Type = Gpio{{ port ~ pin }};
static constexpr Direction direction = Direction::InOut;
static constexpr bool isInverted = false;
static constexpr Port port = Port::{{port}}; ///< Port name
static constexpr uint8_t pin = {{pin}}; ///< Pin number
Expand Down Expand Up @@ -85,6 +89,24 @@ public:
};
%% endif

inline static void configure(Config_t config)
{
if (config & Config::_Input)
configure(InputType( (config & Config::_InputMask).value >> uint8_t(Config::_InputShift) ));
if (config & Config::_Output)
configure(OutputType( (config & Config::_OutputMask).value >> uint8_t(Config::_OutputShift) ),
(config & Config::_Speed) ? OutputSpeed( (config & Config::_SpeedMask).value >>
uint8_t(Config::_SpeedShift) ) :
OutputSpeed::MHz50); else
if (config & Config::_Speed)
configure(OutputSpeed( (config & Config::_SpeedMask).value >> uint8_t(Config::_SpeedShift) ));

if (config & Config::Input) setInput(); else
if (config & Config::Output) setOutput(); else
if (config & Config::Analog) setAnalogInput(); else
if (config & Config::_Alternate) setAlternateFunction(config.value);
}

public:
// GpioOutput
// start documentation inherited
Expand All @@ -99,6 +121,7 @@ public:
}
inline static bool isSet() { return ({{reg}}->ODR & mask); }
// stop documentation inherited
inline static void configure(OutputSpeed speed) { PinSet::configure(speed); }
inline static void configure(OutputType type, OutputSpeed speed = OutputSpeed::MHz50) { PinSet::configure(type, speed); }
inline static void setOutput(OutputType type, OutputSpeed speed = OutputSpeed::MHz50) { PinSet::setOutput(type, speed); }
// GpioInput
Expand Down
22 changes: 22 additions & 0 deletions src/modm/platform/gpio/stm32/pin_f1.hpp.in
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,14 @@ struct Gpio{{ port ~ pin }} : public Gpio, ::modm::GpioIO
using PinSet = GpioSet<Gpio{{ port ~ pin }}>;
friend class Adc1; friend class Adc2; friend class Adc3;
public:
using Direction = ::modm::Gpio::Direction;
using Config = ::modm::Gpio::Config;
using Config_t = ::modm::Gpio::Config_t;
using Output = Gpio{{ port ~ pin }};
using Input = Gpio{{ port ~ pin }};
using IO = Gpio{{ port ~ pin }};
using Type = Gpio{{ port ~ pin }};
static constexpr Direction direction = Direction::InOut;
static constexpr bool isInverted = false;
static constexpr Port port = Port::{{port}}; ///< Port name
static constexpr uint8_t pin = {{pin}}; ///< Pin Number
Expand All @@ -67,6 +71,23 @@ public:
inline static void setAnalogInput() { PinSet::setAnalogInput(); }
/// @endcond

inline static void configure(Config_t config)
{
if (config & Config::_Input)
configure(InputType( (config & Config::_InputMask).value >> uint8_t(Config::_InputShift) ));
if (config & Config::_Output)
configure(OutputType( (config & Config::_OutputMask).value >> uint8_t(Config::_OutputShift) ),
(config & Config::_Speed) ? OutputSpeed( (config & Config::_SpeedMask).value >>
uint8_t(Config::_SpeedShift) ) :
OutputSpeed::MHz50); else
if (config & Config::_Speed)
configure(OutputSpeed( (config & Config::_SpeedMask).value >> uint8_t(Config::_SpeedShift) ));

if (config & Config::Input) setInput(); else
if (config & Config::Output) setOutput(); else
if (config & Config::Analog) setAnalogInput();
}

public:
// GpioOutput
// start documentation inherited
Expand All @@ -81,6 +102,7 @@ public:
}
inline static bool isSet() { return ({{reg}}->ODR & mask); }
// stop documentation inherited
inline static void configure(OutputSpeed speed) { PinSet::configure(speed); }
inline static void configure(OutputType type, OutputSpeed speed = OutputSpeed::MHz50) { PinSet::configure(type, speed); }
inline static void setOutput(OutputType type, OutputSpeed speed = OutputSpeed::MHz50) { PinSet::setOutput(type, speed); }
// GpioInput
Expand Down
Loading