Skip to content

Instantly share code, notes, and snippets.

@bfueldner
Last active July 1, 2016 07:44
Show Gist options
  • Save bfueldner/5691b7ddcea3dc22d5b98163a4808497 to your computer and use it in GitHub Desktop.
Save bfueldner/5691b7ddcea3dc22d5b98163a4808497 to your computer and use it in GitHub Desktop.
Set alternate pin function on STM32F4xx with variadic template
/* 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