summaryrefslogtreecommitdiff
path: root/ucoo/hal/gpio
diff options
context:
space:
mode:
authorNicolas Schodet2016-07-25 15:18:40 +0200
committerNicolas Schodet2019-10-09 23:05:44 +0200
commit4695b47da68a5b2f75270bea21e15b8f1b9fd6ff (patch)
tree6e5ef4d34ee69bcd6c6627f25a0ca3aa902d47e3 /ucoo/hal/gpio
parentd7df91926bdb529e68eff9a215aef72072803b6e (diff)
Switch to CMSIS
Diffstat (limited to 'ucoo/hal/gpio')
-rw-r--r--ucoo/hal/gpio/gpio.stm32f1.cc60
-rw-r--r--ucoo/hal/gpio/gpio.stm32f1.hh67
-rw-r--r--ucoo/hal/gpio/gpio.stm32f4.cc104
-rw-r--r--ucoo/hal/gpio/gpio.stm32f4.hh74
-rw-r--r--ucoo/hal/gpio/test/test_gpio.stm32f1.cc14
-rw-r--r--ucoo/hal/gpio/test/test_gpio.stm32f4.cc20
6 files changed, 255 insertions, 84 deletions
diff --git a/ucoo/hal/gpio/gpio.stm32f1.cc b/ucoo/hal/gpio/gpio.stm32f1.cc
index 0e6c7ee..4927b4e 100644
--- a/ucoo/hal/gpio/gpio.stm32f1.cc
+++ b/ucoo/hal/gpio/gpio.stm32f1.cc
@@ -21,30 +21,37 @@
// DEALINGS IN THE SOFTWARE.
//
// }}}
-#include "gpio.stm32f1.hh"
+#include "ucoo/hal/gpio/gpio.stm32f1.hh"
+#include "ucoo/common.hh"
namespace ucoo {
+GpioPort GPIOA (reg::GPIOA, Rcc::GPIOA);
+GpioPort GPIOB (reg::GPIOB, Rcc::GPIOB);
+GpioPort GPIOC (reg::GPIOC, Rcc::GPIOC);
+GpioPort GPIOD (reg::GPIOD, Rcc::GPIOD);
+GpioPort GPIOE (reg::GPIOE, Rcc::GPIOE);
+
void
Gpio::set ()
{
- GPIO_BSRR (port_) = mask_;
+ port_->BSRR = mask_;
}
void
Gpio::reset ()
{
- GPIO_BRR (port_) = mask_;
+ port_->BRR = mask_;
}
/// Helper to avoid virtual dance.
static inline void
-Gpio_set (uint32_t port, uint16_t mask, bool state)
+Gpio_set (GPIO_TypeDef *port, uint16_t mask, bool state)
{
if (state)
- GPIO_BSRR (port) = mask;
+ port->BSRR = mask;
else
- GPIO_BRR (port) = mask;
+ port->BRR = mask;
}
void
@@ -57,13 +64,13 @@ void
Gpio::toggle ()
{
// Avoid read/modify/write ODR, to achieve atomic operation.
- Gpio_set (port_, mask_, !(GPIO_ODR (port_) & mask_));
+ Gpio_set (port_, mask_, !(port_->ODR & mask_));
}
bool
Gpio::get () const
{
- return GPIO_IDR (port_) & mask_;
+ return port_->IDR & mask_;
}
/// Set four bits in a register for the corresponding one-bit mask.
@@ -81,11 +88,11 @@ qmask_set (uint32_t mask, uint32_t reg, uint32_t bits)
void
Gpio::input ()
{
- uint32_t cnf_mode = static_cast<uint8_t> (input_cnf_) | GPIO_MODE_INPUT;
+ uint32_t cnf_mode = static_cast<uint8_t> (input_cnf_) | GPIO_MODE_Input;
if (mask_ & 0xff)
- GPIO_CRL (port_) = qmask_set (mask_, GPIO_CRL (port_), cnf_mode);
+ port_->CRL = qmask_set (mask_, port_->CRL, cnf_mode);
else
- GPIO_CRH (port_) = qmask_set (mask_ >> 8, GPIO_CRH (port_), cnf_mode);
+ port_->CRH = qmask_set (mask_ >> 8, port_->CRH, cnf_mode);
output_ = false;
}
@@ -95,9 +102,9 @@ Gpio::output ()
uint32_t cnf_mode = static_cast<uint8_t> (output_cnf_)
| static_cast<uint8_t> (speed_);
if (mask_ & 0xff)
- GPIO_CRL (port_) = qmask_set (mask_, GPIO_CRL (port_), cnf_mode);
+ port_->CRL = qmask_set (mask_, port_->CRL, cnf_mode);
else
- GPIO_CRH (port_) = qmask_set (mask_ >> 8, GPIO_CRH (port_), cnf_mode);
+ port_->CRH = qmask_set (mask_ >> 8, port_->CRH, cnf_mode);
output_ = true;
}
@@ -125,4 +132,31 @@ Gpio::speed (Speed s)
output ();
}
+int
+GpioPort::get_port_index () const
+{
+ int port;
+ switch (rcc_)
+ {
+ case Rcc::GPIOA:
+ port = 0;
+ break;
+ case Rcc::GPIOB:
+ port = 1;
+ break;
+ case Rcc::GPIOC:
+ port = 2;
+ break;
+ case Rcc::GPIOD:
+ port = 3;
+ break;
+ case Rcc::GPIOE:
+ port = 4;
+ break;
+ default:
+ assert_unreachable ();
+ }
+ return port;
+}
+
} // namespace ucoo
diff --git a/ucoo/hal/gpio/gpio.stm32f1.hh b/ucoo/hal/gpio/gpio.stm32f1.hh
index 7673998..0cc9bf1 100644
--- a/ucoo/hal/gpio/gpio.stm32f1.hh
+++ b/ucoo/hal/gpio/gpio.stm32f1.hh
@@ -24,38 +24,38 @@
//
// }}}
#include "ucoo/intf/io.hh"
-
-#include <libopencm3/stm32/gpio.h>
+#include "ucoo/arch/reg.hh"
+#include "ucoo/arch/rcc.stm32.hh"
namespace ucoo {
+class GpioPort;
+
/// General purpose input/output on STM32F1.
class Gpio : public Io
{
public:
enum class InputCnf : uint8_t
{
- ANALOG = GPIO_CNF_INPUT_ANALOG << 2,
- FLOAT = GPIO_CNF_INPUT_FLOAT << 2,
+ ANALOG = GPIO_CNF_Input_Analog << 2,
+ FLOAT = GPIO_CNF_Input_Float << 2,
// Up/Down is selected using output register.
- PULL_UPDOWN = GPIO_CNF_INPUT_PULL_UPDOWN << 2,
+ PULL_UPDOWN = GPIO_CNF_Input_PullUpDown << 2,
};
enum class OutputCnf : uint8_t
{
- PUSHPULL = GPIO_CNF_OUTPUT_PUSHPULL << 2,
- OPENDRAIN = GPIO_CNF_OUTPUT_OPENDRAIN << 2,
- ALTFN_PUSH_PULL = GPIO_CNF_OUTPUT_ALTFN_PUSHPULL << 2,
- ALTFN_OPENDRAIN = GPIO_CNF_OUTPUT_ALTFN_OPENDRAIN << 2,
+ PUSHPULL = GPIO_CNF_Output_PushPull << 2,
+ OPENDRAIN = GPIO_CNF_Output_OpenDrain << 2,
+ AF_PUSH_PULL = GPIO_CNF_Output_AFPushPull << 2,
+ AF_OPENDRAIN = GPIO_CNF_Output_AFOpenDrain << 2,
};
enum class Speed : uint8_t
{
- SPEED_2MHZ = GPIO_MODE_OUTPUT_2_MHZ,
- SPEED_10MHZ = GPIO_MODE_OUTPUT_10_MHZ,
- SPEED_50MHZ = GPIO_MODE_OUTPUT_50_MHZ,
+ SPEED_2MHZ = GPIO_MODE_Output_2MHz,
+ SPEED_10MHZ = GPIO_MODE_Output_10MHz,
+ SPEED_50MHZ = GPIO_MODE_Output_50MHz,
};
public:
- /// Constructor, take the PORT base address, and pin BIT number.
- Gpio (uint32_t port, int bit);
/// See Io::set.
void set ();
/// See Io::reset.
@@ -77,8 +77,12 @@ class Gpio : public Io
/// Set output speed.
void speed (Speed s);
private:
+ /// Constructor, take a port, and pin BIT number.
+ Gpio (GpioPort &port, int bit);
+ friend GpioPort;
+ private:
/// Port register base address.
- const uint32_t port_;
+ GPIO_TypeDef * const port_;
/// IO bitmask.
const uint16_t mask_;
/// Configuration for input.
@@ -91,9 +95,32 @@ class Gpio : public Io
bool output_;
};
+/// General purpose input/output port on STM32F1.
+class GpioPort
+{
+ GPIO_TypeDef * const port_;
+ const Rcc rcc_;
+ friend class Gpio;
+ public:
+ /// Constructor.
+ GpioPort (GPIO_TypeDef *port, Rcc rcc)
+ : port_ (port), rcc_ (rcc) { }
+ /// Enable port.
+ void enable ()
+ { rcc_peripheral_clock_enable (rcc_); }
+ /// Disable port.
+ void disable ()
+ { rcc_peripheral_clock_disable (rcc_); }
+ /// Return a port GPIO.
+ Gpio operator[] (int bit)
+ { return Gpio (*this, bit); }
+ /// Get the index of the port, used with Exti.
+ int get_port_index () const;
+};
+
inline
-Gpio::Gpio (uint32_t port, int bit)
- : port_ (port), mask_ (1u << bit),
+Gpio::Gpio (GpioPort &port, int bit)
+ : port_ (port.port_), mask_ (1u << bit),
input_cnf_ (InputCnf::FLOAT),
output_cnf_ (OutputCnf::PUSHPULL),
speed_ (Speed::SPEED_10MHZ),
@@ -101,6 +128,12 @@ Gpio::Gpio (uint32_t port, int bit)
{
}
+extern GpioPort GPIOA;
+extern GpioPort GPIOB;
+extern GpioPort GPIOC;
+extern GpioPort GPIOD;
+extern GpioPort GPIOE;
+
} // namespace ucoo
#endif // ucoo_hal_gpio_gpio_stm32f1_hh
diff --git a/ucoo/hal/gpio/gpio.stm32f4.cc b/ucoo/hal/gpio/gpio.stm32f4.cc
index 60e3231..1640b03 100644
--- a/ucoo/hal/gpio/gpio.stm32f4.cc
+++ b/ucoo/hal/gpio/gpio.stm32f4.cc
@@ -21,30 +21,43 @@
// DEALINGS IN THE SOFTWARE.
//
// }}}
-#include "gpio.stm32f4.hh"
+#include "ucoo/hal/gpio/gpio.stm32f4.hh"
+#include "ucoo/common.hh"
namespace ucoo {
+GpioPort GPIOA (reg::GPIOA, Rcc::GPIOA);
+GpioPort GPIOB (reg::GPIOB, Rcc::GPIOB);
+GpioPort GPIOC (reg::GPIOC, Rcc::GPIOC);
+GpioPort GPIOD (reg::GPIOD, Rcc::GPIOD);
+GpioPort GPIOE (reg::GPIOE, Rcc::GPIOE);
+GpioPort GPIOF (reg::GPIOF, Rcc::GPIOF);
+GpioPort GPIOG (reg::GPIOG, Rcc::GPIOG);
+GpioPort GPIOH (reg::GPIOH, Rcc::GPIOH);
+GpioPort GPIOI (reg::GPIOI, Rcc::GPIOI);
+GpioPort GPIOJ (reg::GPIOJ, Rcc::GPIOJ);
+GpioPort GPIOK (reg::GPIOK, Rcc::GPIOK);
+
void
Gpio::set ()
{
- GPIO_BSRR (port_) = mask_;
+ port_->BSRR = mask_;
}
void
Gpio::reset ()
{
- GPIO_BSRR (port_) = mask_ << 16;
+ port_->BSRR = mask_ << 16;
}
/// Helper to avoid virtual dance.
static inline void
-Gpio_set (uint32_t port, uint16_t mask, bool state)
+Gpio_set (GPIO_TypeDef *port, uint16_t mask, bool state)
{
if (state)
- GPIO_BSRR (port) = mask;
+ port->BSRR = mask;
else
- GPIO_BSRR (port) = mask << 16;
+ port->BSRR = mask << 16;
}
void
@@ -57,13 +70,13 @@ void
Gpio::toggle ()
{
// Avoid read/modify/write ODR, to achieve atomic operation.
- Gpio_set (port_, mask_, !(GPIO_ODR (port_) & mask_));
+ Gpio_set (port_, mask_, !(port_->ODR & mask_));
}
bool
Gpio::get () const
{
- return GPIO_IDR (port_) & mask_;
+ return port_->IDR & mask_;
}
/// Set two bits in a register for the corresponding one-bit mask.
@@ -92,46 +105,95 @@ qmask_set (uint32_t mask, uint32_t reg, uint32_t bits)
void
Gpio::input ()
{
- GPIO_MODER (port_) = dmask_set (mask_, GPIO_MODER (port_),
- GPIO_MODE_INPUT);
+ port_->MODER = dmask_set (mask_, port_->MODER, GPIO_MODER_Input);
}
void
Gpio::output ()
{
- GPIO_MODER (port_) = dmask_set (mask_, GPIO_MODER (port_),
- GPIO_MODE_OUTPUT);
+ port_->MODER = dmask_set (mask_, port_->MODER, GPIO_MODER_Output);
}
void
Gpio::pull (Pull dir)
{
- GPIO_PUPDR (port_) = dmask_set (mask_, GPIO_PUPDR (port_),
- static_cast<uint32_t> (dir));
+ port_->PUPDR = dmask_set (mask_, port_->PUPDR,
+ static_cast<uint32_t> (dir));
}
void
Gpio::speed (Speed s)
{
- GPIO_OSPEEDR (port_) = dmask_set (mask_, GPIO_OSPEEDR (port_),
- static_cast<uint32_t> (s));
+ port_->OSPEEDR = dmask_set (mask_, port_->OSPEEDR,
+ static_cast<uint32_t> (s));
+}
+
+void
+Gpio::type (Type t)
+{
+ port_->OTYPER = (port_->OTYPER & ~mask_)
+ | (mask_ * static_cast<uint32_t> (t));
}
void
Gpio::af (int num)
{
- GPIO_MODER (port_) = dmask_set (mask_, GPIO_MODER (port_), GPIO_MODE_AF);
+ port_->MODER = dmask_set (mask_, port_->MODER, GPIO_MODER_AF);
if (mask_ & 0xff)
- GPIO_AFRL (port_) = qmask_set (mask_, GPIO_AFRL (port_), num);
+ port_->AFR[0] = qmask_set (mask_, port_->AFR[0], num);
else
- GPIO_AFRH (port_) = qmask_set (mask_ >> 8, GPIO_AFRH (port_), num);
+ port_->AFR[1] = qmask_set (mask_ >> 8, port_->AFR[1], num);
}
void
Gpio::analog ()
{
- GPIO_MODER (port_) = dmask_set (mask_, GPIO_MODER (port_),
- GPIO_MODE_ANALOG);
+ port_->MODER = dmask_set (mask_, port_->MODER, GPIO_MODER_Analog);
+}
+
+int
+GpioPort::get_port_index () const
+{
+ int port;
+ switch (rcc_)
+ {
+ case Rcc::GPIOA:
+ port = 0;
+ break;
+ case Rcc::GPIOB:
+ port = 1;
+ break;
+ case Rcc::GPIOC:
+ port = 2;
+ break;
+ case Rcc::GPIOD:
+ port = 3;
+ break;
+ case Rcc::GPIOE:
+ port = 4;
+ break;
+ case Rcc::GPIOF:
+ port = 5;
+ break;
+ case Rcc::GPIOG:
+ port = 6;
+ break;
+ case Rcc::GPIOH:
+ port = 7;
+ break;
+ case Rcc::GPIOI:
+ port = 8;
+ break;
+ case Rcc::GPIOJ:
+ port = 9;
+ break;
+ case Rcc::GPIOK:
+ port = 10;
+ break;
+ default:
+ assert_unreachable ();
+ }
+ return port;
}
} // namespace ucoo
diff --git a/ucoo/hal/gpio/gpio.stm32f4.hh b/ucoo/hal/gpio/gpio.stm32f4.hh
index fa73fa2..356a575 100644
--- a/ucoo/hal/gpio/gpio.stm32f4.hh
+++ b/ucoo/hal/gpio/gpio.stm32f4.hh
@@ -24,31 +24,36 @@
//
// }}}
#include "ucoo/intf/io.hh"
-
-#include <libopencm3/stm32/gpio.h>
+#include "ucoo/arch/reg.hh"
+#include "ucoo/arch/rcc.stm32.hh"
namespace ucoo {
+class GpioPort;
+
/// General purpose input/output on STM32F4.
class Gpio : public Io
{
public:
enum class Pull : uint32_t
{
- NONE = GPIO_PUPD_NONE,
- UP = GPIO_PUPD_PULLUP,
- DOWN = GPIO_PUPD_PULLDOWN,
+ NONE,
+ UP,
+ DOWN,
};
enum class Speed : uint32_t
{
- SPEED_2MHZ = GPIO_OSPEED_2MHZ,
- SPEED_25MHZ = GPIO_OSPEED_25MHZ,
- SPEED_50MHZ = GPIO_OSPEED_50MHZ,
- SPEED_100MHZ = GPIO_OSPEED_100MHZ,
+ SPEED_2MHZ,
+ SPEED_25MHZ,
+ SPEED_50MHZ,
+ SPEED_100MHZ,
+ };
+ enum class Type : uint32_t
+ {
+ PUSH_PULL,
+ OPEN_DRAIN,
};
public:
- /// Constructor, take the PORT base address, and pin BIT number.
- Gpio (uint32_t port, int bit);
/// See Io::set.
void set ();
/// See Io::reset.
@@ -67,23 +72,64 @@ class Gpio : public Io
void pull (Pull dir);
/// Set output speed.
void speed (Speed s);
+ /// Set output type.
+ void type (Type t);
/// Set alternate function.
void af (int num);
/// Set as analog.
void analog ();
private:
+ /// Constructor, take a port, and pin BIT number.
+ Gpio (GpioPort &port, int bit);
+ friend GpioPort;
+ private:
/// Port register base address.
- const uint32_t port_;
+ GPIO_TypeDef * const port_;
/// IO bitmask.
const uint16_t mask_;
};
+/// General purpose input/output port on STM32F4.
+class GpioPort
+{
+ GPIO_TypeDef * const port_;
+ const Rcc rcc_;
+ friend class Gpio;
+ public:
+ /// Constructor.
+ GpioPort (GPIO_TypeDef *port, Rcc rcc)
+ : port_ (port), rcc_ (rcc) { }
+ /// Enable port.
+ void enable ()
+ { rcc_peripheral_clock_enable (rcc_); }
+ /// Disable port.
+ void disable ()
+ { rcc_peripheral_clock_disable (rcc_); }
+ /// Return a port GPIO.
+ Gpio operator[] (int bit)
+ { return Gpio (*this, bit); }
+ /// Get the index of the port, used with Exti.
+ int get_port_index () const;
+};
+
inline
-Gpio::Gpio (uint32_t port, int bit)
- : port_ (port), mask_ (1u << bit)
+Gpio::Gpio (GpioPort &port, int bit)
+ : port_ (port.port_), mask_ (1u << bit)
{
}
+extern GpioPort GPIOA;
+extern GpioPort GPIOB;
+extern GpioPort GPIOC;
+extern GpioPort GPIOD;
+extern GpioPort GPIOE;
+extern GpioPort GPIOF;
+extern GpioPort GPIOG;
+extern GpioPort GPIOH;
+extern GpioPort GPIOI;
+extern GpioPort GPIOJ;
+extern GpioPort GPIOK;
+
} // namespace ucoo
#endif // ucoo_hal_gpio_gpio_stm32f4_hh
diff --git a/ucoo/hal/gpio/test/test_gpio.stm32f1.cc b/ucoo/hal/gpio/test/test_gpio.stm32f1.cc
index 0135a32..d3fe1c2 100644
--- a/ucoo/hal/gpio/test/test_gpio.stm32f1.cc
+++ b/ucoo/hal/gpio/test/test_gpio.stm32f1.cc
@@ -25,8 +25,6 @@
#include "ucoo/hal/gpio/gpio.hh"
#include "ucoo/utils/delay.hh"
-#include <libopencm3/stm32/rcc.h>
-
void
test (ucoo::Io &loop_in, ucoo::Io &led1, ucoo::Io &led2, ucoo::Io &led3,
ucoo::Io &led4)
@@ -54,12 +52,12 @@ int
main (int argc, const char **argv)
{
ucoo::arch_init (argc, argv);
- rcc_periph_clock_enable (RCC_GPIOC);
- ucoo::Gpio loop_in (GPIOC, 5);
- ucoo::Gpio led1 (GPIOC, 6);
- ucoo::Gpio led2 (GPIOC, 7);
- ucoo::Gpio led3 (GPIOC, 8);
- ucoo::Gpio led4 (GPIOC, 9);
+ ucoo::GPIOC.enable ();
+ ucoo::Gpio loop_in (ucoo::GPIOC[5]);
+ ucoo::Gpio led1 (ucoo::GPIOC[6]);
+ ucoo::Gpio led2 (ucoo::GPIOC[7]);
+ ucoo::Gpio led3 (ucoo::GPIOC[8]);
+ ucoo::Gpio led4 (ucoo::GPIOC[9]);
test (loop_in, led1, led2, led3, led4);
return 0;
}
diff --git a/ucoo/hal/gpio/test/test_gpio.stm32f4.cc b/ucoo/hal/gpio/test/test_gpio.stm32f4.cc
index a51017c..6932a05 100644
--- a/ucoo/hal/gpio/test/test_gpio.stm32f4.cc
+++ b/ucoo/hal/gpio/test/test_gpio.stm32f4.cc
@@ -25,8 +25,6 @@
#include "ucoo/hal/gpio/gpio.hh"
#include "ucoo/utils/delay.hh"
-#include <libopencm3/stm32/rcc.h>
-
void
test (ucoo::Io &loop_out, ucoo::Io &loop_in, ucoo::Io &led3, ucoo::Io &led4,
ucoo::Io &led5, ucoo::Io &led6)
@@ -56,16 +54,16 @@ int
main (int argc, const char **argv)
{
ucoo::arch_init (argc, argv);
- rcc_periph_clock_enable (RCC_GPIOB);
- rcc_periph_clock_enable (RCC_GPIOD);
+ ucoo::GPIOB.enable ();
+ ucoo::GPIOD.enable ();
// For this test, shorten B6 & B7 to have loopback.
- gpio_mode_setup (GPIOB, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, GPIO7);
- ucoo::Gpio loop_out (GPIOB, 6);
- ucoo::Gpio loop_in (GPIOB, 7);
- ucoo::Gpio led3 (GPIOD, 13);
- ucoo::Gpio led4 (GPIOD, 12);
- ucoo::Gpio led5 (GPIOD, 14);
- ucoo::Gpio led6 (GPIOD, 15);
+ ucoo::Gpio loop_out (ucoo::GPIOB[6]);
+ ucoo::Gpio loop_in (ucoo::GPIOB[7]);
+ loop_in.pull (ucoo::Gpio::Pull::UP);
+ ucoo::Gpio led3 (ucoo::GPIOD[13]);
+ ucoo::Gpio led4 (ucoo::GPIOD[12]);
+ ucoo::Gpio led5 (ucoo::GPIOD[14]);
+ ucoo::Gpio led6 (ucoo::GPIOD[15]);
test (loop_out, loop_in, led3, led4, led5, led6);
return 0;
}