ВходНаше всё Теги codebook PARTS Поиск Опросы Закон Пятница
28 января
/1163419
Топик полностью
VladislavS. (12.01.2022 11:35, просмотров: 235) ответил evgeniy1294 на Всё это в своё время я уже делал. Допустить ошибку в какой-нибудь проверочной лямбде довольно легко, так что код безопасней не становится. Вы можете сказать, что ошибки будут выловлены, когда-нибудь, но производитель уже сделал это за вас.
В таком виде это не сильно отличается от того что можно сделать макросами в С. Ну, разве что, более строгая проверка типов. Например, метод Toggle. 
inline static void Toggle() noexcept(true) {
  static_assert((kType == Type::Output), "This gpio not output, check 'Type' field");
  GPIO_TypeDef* regs { reinterpret_cast<GPIO_TypeDef*>(kPort) };
            
  regs->ODR ^= kOdrMask;            
}

Что нового он нам принёс? Неатомарный доступ? А на этом контроллере от него можно избавиться и дополнительно оптимизировать.

template<uint32_t PM=PinsMask>
static inline void toggle()
{
  if constexpr (PM == 0xFFFF)
    base()->ODR = ~base()->ODR;
  else if constexpr (PM == 0x00FF)
    *pVU8(&base()->ODR) = ~*pVU8(&base()->ODR);
  else if constexpr (PM == 0xFF00)
    *(pVU8(&base()->ODR) + 1) = ~*(pVU8(&base()->ODR) + 1);
  else if constexpr (std::popcount(PM)==1)
  { if (base()->ODR & PM) clear(); else set(); }
  else  
    base()->BSRR = (PM << 16) | (~base()->ODR & PM);
}

template<uint32_t PM=PinsMask>
static inline void set()
{
  if constexpr((PM & 0xFF)==0)
    *(pVU8(&base()->BSRR)+1) = PM>>8;
  else
    base()->BSRR = PM;
}

template<uint32_t PM=PinsMask>
static inline void clear()
{
  if constexpr (PM == 0xFFFF)
    base()->ODR = 0;
  else if constexpr (PM == 0x00FF)
    *pVU8(&base()->ODR) = 0;
  else if constexpr (PM == 0xFF00)
    *(pVU8(&base()->ODR) + 1) = 0;
  else if constexpr((PM & 0xFF)==0)
    *(pVU8(&base()->BSRR)+3) = PM>>8;
  else
    *(pVU16(&base()->BSRR)+1) = PM;
}