Skip to content

Commit

Permalink
[gpio] Fix comments + test USB example
Browse files Browse the repository at this point in the history
  • Loading branch information
henrikssn committed Oct 6, 2020
1 parent 4b1cd6d commit 32e15b6
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 44 deletions.
4 changes: 2 additions & 2 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ AllowShortFunctionsOnASingleLine: Inline
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: All
AlwaysBreakAfterReturnType: TopLevel
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: All
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
BinPackArguments: true
Expand Down
3 changes: 2 additions & 1 deletion examples/samd/usbserial/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ int main()
TCC0->PER.bit.PER = SystemClock::Frequency / 1000;
TCC0->CC[3].bit.CC = SystemClock::Frequency / 2000;
TCC0->CTRLA.bit.ENABLE = true;
D12::Wo3<Peripheral::Tcc0>::connect();
using Tcc = Peripherals::Tcc<0>;
D12::As<PeripheralPin::Wo>::Connector<Tcc, Tcc::Wo<3>>::connect();
GenericClockController::connect<ClockPeripheral::Tcc0>(ClockGenerator::System);

tusb_init();
Expand Down
9 changes: 5 additions & 4 deletions src/modm/board/feather_m0/board.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ using Sck = GpioB11;
using Mosi = GpioB10;
using Miso = GpioA12;

using Rx = GpioA11::Rx;
using Tx = GpioA10::Tx;
using Rx = GpioA11;
using Tx = GpioA10;

using D13 = GpioA17;
using D12 = GpioA19;
Expand Down Expand Up @@ -87,7 +87,8 @@ struct SystemClock
// static constexpr uint32_t Timer3 = Apb1Timer;
// static constexpr uint32_t Timer4 = Apb1Timer;

static bool inline enable()
static bool inline
enable()
{
GenericClockController::setFlashLatency<Frequency>();
GenericClockController::initExternalCrystal();
Expand All @@ -107,7 +108,7 @@ initialize()
{
SystemClock::enable();
SysTickTimer::initialize<SystemClock>();
Uart0::connect<Rx, Tx>();
Uart0::connect<Rx::Rx, Tx::Tx>();
Uart0::initialize<SystemClock, 115'200_Bd>();

Led::setOutput(modm::Gpio::Low);
Expand Down
14 changes: 8 additions & 6 deletions src/modm/platform/extint/sam/extint.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ class ExternalInterrupt
* be used to akeup the CPU from standby mode, make sure this clock is
* actually running in standby. Defaults to external 32.768kHz crystal osc.
*/
static void initialize(ClockGenerator clockGen = ClockGenerator::ExternalCrystal32K,
int priority = (1ul << __NVIC_PRIO_BITS) - 1ul);
static void
initialize(ClockGenerator clockGen = ClockGenerator::ExternalCrystal32K,
int priority = (1ul << __NVIC_PRIO_BITS) - 1ul);

protected:
static std::array<std::function<void()>, 16> handlers_;
Expand All @@ -81,9 +82,9 @@ class ExtInt : private ExternalInterrupt
* If true (default), allows the CPU to wakeup from interrupt
* from this instance.
*/
static void initialize(std::function<void()> handler,
InputTrigger trigger = InputTrigger::RisingEdge,
bool wakeupEnabled = true);
static void
initialize(std::function<void()> handler, InputTrigger trigger = InputTrigger::RisingEdge,
bool wakeupEnabled = true);

/**
* Connects a GPIO pin to this External Interrupt instance.
Expand All @@ -92,7 +93,8 @@ class ExtInt : private ExternalInterrupt
* The GPIO pin to connect this instance to.
*/
template<class GpioPin>
static void connect()
static void
connect()
{
using Eic = Peripherals::Eic;
using Pin = typename GpioPin::template As<PeripheralPin::ExtInt>;
Expand Down
2 changes: 1 addition & 1 deletion src/modm/platform/gpio/sam/module.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ The Connection API was designed with the following goals:
As a few examples, the following situations will crash compilation:

- Usage of drivers which don't exist on the pin
- Passing a pin which has a connection to the driver but not the correct instance
- Passing a pin which has a connection to the driver but not the correct instance
- Passing a pin which connects to the driver/instance but not the correct Peripheral signal
- Using multiple signals from the same pin in a *single* Peripheral
- Using the same signal from multiple pins in a *single* Peripheral
Expand Down
100 changes: 74 additions & 26 deletions src/modm/platform/gpio/sam/pin.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ enum class PeripheralPin
ExtInt,
Dm,
Dp,
Wo,
};

template<typename... Tuples>
Expand Down Expand Up @@ -112,7 +113,8 @@ struct PinCfgMixin
template<class PinConfig, class... PinConfigs>
struct PinCfgMixin<PinConfig, PinConfigs...>
{
inline static void set(uint8_t cfg)
inline static void
set(uint8_t cfg)
{
if constexpr (PinConfig::port == PortName::A)
{
Expand All @@ -131,39 +133,51 @@ class GpioSet : protected PinCfgMixin<PinConfigs...>
protected:
using PinCfg = PinCfgMixin<PinConfigs...>;

static constexpr uint32_t mask(PortName port)
static constexpr uint32_t
mask(PortName port)
{
return (((PinConfigs::port == port) ? 1u << PinConfigs::pin : 0u) | ...);
}

inline static void setPortReg(size_t offset)
inline static constexpr uint32_t*
getPortReg(size_t offset)
{
if constexpr (mask(PortName::A) != 0)
{ *(uint32_t *)(&PORT->Group[0] + offset) = mask(PortName::A); }
if constexpr (mask(PortName::B) != 0)
{ *(uint32_t *)(&PORT->Group[1] + offset) = mask(PortName::B); }
return (uint32_t*)(&PORT->Group[0]) + offset / sizeof(uint32_t);
}

inline static constexpr void
setPortReg(size_t offset)
{
if constexpr (mask(PortName::A) != 0) { *getPortReg(offset) = mask(PortName::A); }
if constexpr (mask(PortName::B) != 0) { *getPortReg(offset) = mask(PortName::B); }
}

template<PortName port>
inline static uint32_t readPortReg(size_t offset)
inline static constexpr uint32_t
readPortReg(size_t offset)
{
if constexpr (port == PortName::A)
{
static_assert(mask(PortName::A) != 0,
"Trying to read port which is not in the GpioSet!");
return *(uint32_t *)(&PORT->Group[0] + offset) & mask(PortName::A);
return *getPortReg(offset) & mask(PortName::A);
} else if constexpr (port == PortName::B)
{
static_assert(mask(PortName::B) != 0,
"Trying to read port which is not in the GpioSet!");
return *(uint32_t *)(&PORT->Group[1] + offset) & mask(PortName::A);
return *getPortReg(offset) & mask(PortName::A);
}
}

public:
inline static void setOutput() { setPortReg(PORT_DIRSET_OFFSET); }
inline static void
setOutput()
{
setPortReg(PORT_DIRSET_OFFSET);
}

inline static void setOutput(bool status)
inline static void
setOutput(bool status)
{
setOutput();
set(status);
Expand All @@ -173,37 +187,62 @@ class GpioSet : protected PinCfgMixin<PinConfigs...>

static void configure(OutputType, OutputSpeed = OutputSpeed::MHz50) {}

static void setInput() { setPortReg(PORT_DIRCLR_OFFSET); }
static void
setInput()
{
setPortReg(PORT_DIRCLR_OFFSET);
}

static void setInput(InputType type)
static void
setInput(InputType type)
{
configure(type);
setInput();
}

static void configure(InputType type)
static void
configure(InputType type)
{
set(type == InputType::PullUp);
PinCfg::set(PORT_PINCFG_INEN | (type != InputType::Floating) << PORT_PINCFG_PULLEN_Pos);
}

static void setAnalogInput() {}
static void
setAnalogInput()
{}

static void set() { setPortReg(PORT_OUTSET_OFFSET); }
static void
set()
{
setPortReg(PORT_OUTSET_OFFSET);
}

static void set(bool status)
static void
set(bool status)
{
if (status)
set();
else
reset();
}

static void reset() { setPortReg(PORT_OUTCLR_OFFSET); }
static void
reset()
{
setPortReg(PORT_OUTCLR_OFFSET);
}

static void toggle() { setPortReg(PORT_OUTTGL_OFFSET); }
static void
toggle()
{
setPortReg(PORT_OUTTGL_OFFSET);
}

static void disconnect() { setInput(InputType::Floating); }
static void
disconnect()
{
setInput(InputType::Floating);
}
};

template<class PinConfig>
Expand All @@ -225,9 +264,17 @@ class Gpio : public GpioSet<PinConfig>, public ::modm::GpioIO
using Dm = As<PeripheralPin::Dm>;
using Dp = As<PeripheralPin::Dp>;

inline static bool read() { return Base::readPortReg<PinConfig::port>(PORT_IN_OFFSET); }
inline static bool
read()
{
return Base::readPortReg<PinConfig::port>(PORT_IN_OFFSET);
}

inline static void write(bool status) { Base::set(status); }
inline static void
write(bool status)
{
Base::set(status);
}
};

template<class PinConfig>
Expand Down Expand Up @@ -276,10 +323,11 @@ struct Gpio<PinConfig>::As : public Gpio<PinConfig>
using PinSignal = typename GetSingleSignal<ValidatedSignals>::type;
using Signal = typename PinSignal::signal;

inline static void connect()
inline static void
connect()
{
Base::PinCfg::set(PORT_PINCFG_INEN);
if constexpr (PinConfig::pin >> 1)
Base::PinCfg::set(PORT_PINCFG_PMUXEN);
if constexpr (PinConfig::pin & 1u)
{
PORT->Group[uint32_t(PinConfig::port)].PMUX[PinConfig::pin >> 1].bit.PMUXO =
uint32_t(PinSignal::function);
Expand Down
7 changes: 3 additions & 4 deletions src/modm/platform/usb/sam/usb.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,14 @@ class Usb
NVIC_SetPriority(USB_IRQn, priority);
}

template< class... Pins >
template<class... Pins>
static void
connect()
{
using DpPin = GetPin_t<PeripheralPin::Dp, Pins...>;
using DmPin = GetPin_t<PeripheralPin::Dm, Pins...>;
static_assert(
!std::is_same_v<typename DpPin::Base, typename DmPin::Base>,
"Dp and Dm cannot use the same pin!");
static_assert(!std::is_same_v<typename DpPin::Base, typename DmPin::Base>,
"Dp and Dm cannot use the same pin!");
using Usb = Peripherals::Usb;
using DpConnector = typename DpPin::template Connector<Usb, Usb::Dp>;
using DmConnector = typename DmPin::template Connector<Usb, Usb::Dm>;
Expand Down

0 comments on commit 32e15b6

Please sign in to comment.