Last active
July 1, 2016 07:44
-
-
Save bfueldner/5691b7ddcea3dc22d5b98163a4808497 to your computer and use it in GitHub Desktop.
Set alternate pin function on STM32F4xx with variadic template
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* Usage: function<PA2::usart2_tx, PA3::usart2_rx>(); */ | |
enum class alternate_t | |
{ | |
AF0 = 0x0, | |
AF1 = 0x1, | |
AF2 = 0x2, | |
AF3 = 0x3, | |
AF4 = 0x4, | |
AF5 = 0x5, | |
AF6 = 0x6, | |
AF7 = 0x7, | |
AF8 = 0x8, | |
AF9 = 0x9, | |
AF10 = 0xa, | |
AF11 = 0xb, | |
AF12 = 0xc, | |
AF13 = 0xd, | |
AF14 = 0xe, | |
AF15 = 0xf, | |
}; | |
template<const std::uint8_t index_, const std::uint32_t base_, const alternate_t alternate_> | |
struct pin_tag | |
{ | |
static_assert(index_ <= 16, "Pin index out of range"); | |
static constexpr std::uint8_t index = index_; | |
static constexpr std::uint32_t base = base_ + 0x20 + ((index & 0x08) >> 1); | |
static constexpr std::uint32_t value = std::uint32_t(alternate_) << ((index & 0x7) << 2); | |
static constexpr std::uint32_t mask = 0xF << ((index & 0x7) << 2); | |
}; | |
namespace PA0 { | |
typedef pin_tag<0, gpioA::base, alternate_t::AF1> tim2_ch1; | |
typedef pin_tag<0, gpioA::base, alternate_t::AF1> tim2_etr; | |
typedef pin_tag<0, gpioA::base, alternate_t::AF2> tim5_ch1; | |
typedef pin_tag<0, gpioA::base, alternate_t::AF7> usart2_cts; | |
} | |
namespace PA1 { | |
typedef pin_tag<1, gpioA::base, alternate_t::AF1> tim2_ch2; | |
typedef pin_tag<1, gpioA::base, alternate_t::AF2> tim5_ch2; | |
typedef pin_tag<1, gpioA::base, alternate_t::AF5> spi4_mosi; | |
typedef pin_tag<1, gpioA::base, alternate_t::AF5> i2s4_sd; | |
typedef pin_tag<1, gpioA::base, alternate_t::AF7> usart2_rts; | |
} | |
namespace PA2 { | |
typedef pin_tag<2, gpioA::base, alternate_t::AF1> tim2_ch3; | |
typedef pin_tag<2, gpioA::base, alternate_t::AF2> tim5_ch3; | |
typedef pin_tag<2, gpioA::base, alternate_t::AF3> tim9_ch1; | |
typedef pin_tag<2, gpioA::base, alternate_t::AF5> i2s2_ckin; | |
typedef pin_tag<2, gpioA::base, alternate_t::AF7> usart2_tx; | |
} | |
namespace PA3 { | |
typedef pin_tag<3, gpioA::base, alternate_t::AF1> tim2_ch4; | |
typedef pin_tag<3, gpioA::base, alternate_t::AF2> tim5_ch4; | |
typedef pin_tag<3, gpioA::base, alternate_t::AF3> tim9_ch2; | |
typedef pin_tag<3, gpioA::base, alternate_t::AF5> i2s2_mck; | |
typedef pin_tag<3, gpioA::base, alternate_t::AF7> usart2_rx; | |
} | |
/** | |
* @brief Set alternate pin function | |
*/ | |
template<typename T> | |
void function(const std::uint32_t value = 0, const std::uint32_t mask = 0) | |
{ | |
typedef T config; | |
*((uint32_t*)config::base) = (*((uint32_t*)config::base) & ~(config::mask | mask)) | config::value | value; | |
} | |
template<typename T, typename Tn, typename... Args> | |
void function(const std::uint32_t value = 0, const std::uint32_t mask = 0) | |
{ | |
typedef T config; | |
typedef Tn config_next; | |
static_assert(config::base == config_next::base, "Elements must have the same register address"); | |
function<Tn, Args...>(config::value | value, config::mask | mask); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment