Вт фев 04, 2020 01:38:58
Вт фев 04, 2020 03:03:08
Lum1noFor писал(а):при досчитывании таймером до значения регистра ARR таймер сбрасывается и генерируется событие, так?
Вт фев 04, 2020 07:30:36
Вт фев 04, 2020 09:21:55
Вт фев 04, 2020 09:36:52
Вт фев 04, 2020 09:49:52
Вт фев 04, 2020 10:29:46
Вт фев 04, 2020 10:38:14
Вт фев 04, 2020 10:43:43
Вт фев 04, 2020 11:40:56
Вт фев 04, 2020 12:51:26
Вт фев 04, 2020 14:07:06
Вт фев 04, 2020 14:21:51
#pragma once
//========================
// STM32F0, STM32F3, STM32F4, STM32L0 GPIO Port
//========================
#include "../../PinModeList.h"
namespace STM32Fx_GPIO
{
using namespace PIN_MODE_LIST;
template<STM32Fx_PinMode Mode>
_static_always_inline_ constexpr bool isAnalog() { return Mode == STM32Fx_PinMode::Analog; }
template<STM32Fx_PinMode Mode>
_static_always_inline_ constexpr bool isAfMode() { return (uint32_t(Mode) & 3) == 2; }
template<STM32Fx_PinMode Mode>
_static_always_inline_ constexpr bool isOpenDrain() { return uint32_t(Mode) & 0x10; }
template<STM32Fx_PinMode Mode>
_static_always_inline_ constexpr bool isInputMode()
{
if constexpr ( Mode == STM32Fx_PinMode::Input_Floating || Mode == STM32Fx_PinMode::Input_PullUp ||
Mode == STM32Fx_PinMode::Input_PullDown || Mode == STM32Fx_PinMode::Analog )
return true;
else
return false;
}
template<STM32Fx_PinMode Mode, uint32_t AF>
_static_always_inline_ constexpr bool isOutputStateDefined()
{
return (isAfMode<Mode>() || isInputMode<Mode>()) ? false : (AF<2) ? true : false;
}
template<uint32_t GpioID, uint32_t PinsMask, typename TPM = STM32Fx_MODE::NotDefined,
uint32_t pwr_moder=0, uint32_t pwr_ospeedr=0, uint32_t pwr_pupdr=0>
class TSTM32Fx_GPIO : public GpioTemplate<GpioID, 16, PinsMask, TPM>
{
static_assert(PinsMask<=makeMask(16), "MAX port width is 16 bits");
private:
_static_always_inline_ auto base() { return (GPIO_TypeDef*)GpioID; }
using pVU8 = volatile uint8_t*;
using pVU16 = volatile uint16_t*;
using pVU32 = volatile uint32_t*;
public:
static constexpr uint32_t pwrModer = pwr_moder;
static constexpr uint32_t pwrOspeedr = pwr_ospeedr;
static constexpr uint32_t pwrPupdr = pwr_pupdr;
constexpr _always_inline_ TSTM32Fx_GPIO() = default;
template<uint32_t NewPinsMask, uint32_t NewGpioID=GpioID, typename NewTPM = TPM>
_static_always_inline_ constexpr auto clone() { return TypeBox<TSTM32Fx_GPIO<NewGpioID,NewPinsMask,NewTPM>>{}; }
_always_inline_ TSTM32Fx_GPIO& operator=(const TSTM32Fx_GPIO& gpio)
{
write(gpio.read());
return *this;
}
_always_inline_ TSTM32Fx_GPIO& operator=(uint32_t value)
{
write(value);
return *this;
}
_always_inline_ operator uint32_t() const { return read(); }
template<uint32_t PM=PinsMask>
_static_always_inline_ void write(uint32_t data) // Тут вроде uint16_t надо
{
if constexpr (PM==0) return;
if constexpr (PM == 0xFFFF)
base()->ODR = data;
else if constexpr (PM == 0x00FF)
*pVU8(&base()->ODR) = data;
else if constexpr (PM == 0xFF00)
*(pVU8(&base()->ODR) + 1) = data >> 8;
else
base()->BSRR = (PM << 16) | (data & PM);
}
template<uint32_t PM=PinsMask, typename... SortedPins> // SortedPins надо для Dummy
_static_always_inline_ uint32_t read(TypeList<SortedPins...> pins = {})
{
return readReg16<PM>(&base()->IDR);
}
template<uint32_t PM=PinsMask>
_static_always_inline_ uint32_t readOutput()
{
return readReg16<PM>(&base()->ODR);
}
template<uint32_t PM=PinsMask>
_static_always_inline_ void set()
{
if constexpr((PM & 0xFF)==0)
*(pVU8(&base()->BSRR)+1) = PM>>8;
else
base()->BSRR = PM;
}
template<uint32_t PM=PinsMask>
_static_always_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;
}
template<uint32_t PM=PinsMask>
_static_always_inline_ void toggle()
{
if constexpr (PM == 0xFFFF)
base()->ODR = ~base()->ODR;
if constexpr (PM == 0x00FF)
*pVU8(&base()->ODR) = ~*pVU8(&base()->ODR);
else if constexpr (PM == 0xFF00)
*(pVU8(&base()->ODR) + 1) = ~*(pVU8(&base()->ODR) + 1);
else
base()->BSRR = (PM << 16) | (~base()->ODR & PM);
}
template<uint32_t PM=PinsMask>
_static_always_inline_ void lock()
{
base()->LCKR = PM | GPIO_LCKR_LCKK;
base()->LCKR = PM;
base()->LCKR = PM | GPIO_LCKR_LCKK;
}
// Same mode for all pins set
_static_always_inline_ void mode()
{
static constexpr auto mode_list = generate<countSetBits(PinsMask),TPM>();
mode_<false,PinsMask>(mode_list);
}
// Same mode for all pins set
template<typename T, typename = std::enable_if_t<IsPinMode<T>() > >
_static_always_inline_ void mode()
{
static constexpr auto mode_list = generate<countSetBits(PinsMask),T>();
mode_<false,PinsMask>(mode_list);
}
template<typename ML, typename = std::enable_if_t<IsPinModeList<ML>()>>
_static_always_inline_ void modes()
{
static_assert(countSetBits(PinsMask) == ML::Size, "ModeList and Port size is not Equal!");
mode_<false,PinsMask>(ML::modes_);
}
template<bool UsePwrCfg=false, uint32_t PM=PinsMask, typename... ML>
_static_always_inline_ void modes(TypeList<ML...> modes)
{
static_assert(countSetBits(PM) == sizeof...(ML), "ModeList and Port size is not Equal!");
mode_<UsePwrCfg,PM>(modes);
}
private:
enum class GpioRegs { Ospeedr = 1, Otyper = 2, Pupdr = 4, AfrL = 8, AfrH = 16, State = 32 };
template<uint32_t dmask>
_static_always_inline_ void writeReg32(pVU32 reg, uint32_t value)
{
if constexpr (dmask==0) return;
if constexpr (dmask == 0xFFFF'FFFF)
*reg = value;
else if constexpr (dmask == 0x0000'FFFF)
*pVU16(reg) = value;
else if constexpr (dmask == 0xFFFF'0000)
*(pVU16(reg) + 1) = value >> 16;
else if constexpr (dmask == 0x0000'00FF)
*pVU8(reg) = value;
else if constexpr (dmask == 0x0000'FF00)
*(pVU8(reg) + 1) = value >> 8;
else if constexpr (dmask == 0x00FF'0000)
*(pVU8(reg) + 2) = value >> 16;
else if constexpr (dmask == 0xFF00'0000)
*(pVU8(reg) + 3) = value >> 24;
else if constexpr ((dmask & 0xFFFF'FF00)==0)
*pVU8(reg) = (*pVU8(reg) & ~dmask) | value;
else if constexpr (!(dmask & 0xFFFF'00FF))
*(pVU8(reg) + 1) = (*(pVU8(reg) + 1) & ~(dmask >> 8)) | (value >> 8);
else if constexpr (!(dmask & 0xFF00'FFFF))
*(pVU8(reg) + 2) = (*(pVU8(reg) + 2) & ~(dmask >> 16)) | (value >> 16);
else if constexpr (!(dmask & 0x00FF'FFFF))
*(pVU8(reg) + 3) = (*(pVU8(reg) + 3) & ~(dmask >> 24)) | (value >> 24);
else if constexpr (!(dmask & 0xFFFF'0000))
*pVU16(reg) = (*pVU16(reg) & ~dmask) | value;
else if constexpr (!(dmask & 0x0000'FFFF))
*(pVU16(reg) + 1) = (*(pVU16(reg) + 1) & ~(dmask >> 16)) | (value >> 16);
else
*reg = (*reg & ~dmask) | value;
}
template<uint32_t pmask>
_static_always_inline_ void writeReg16(pVU32 reg, uint32_t value)
{
if constexpr (pmask==0) return;
if constexpr (pmask==0xFFFF)
*pVU16(reg) = value;
else if constexpr (pmask==0x00FF)
*pVU8(reg) = value;
else if constexpr (pmask==0xFF00)
*(pVU8(reg) + 1) = value >> 8;
else if constexpr (!(pmask & 0xFF00))
*pVU8(reg) = (*pVU8(reg) & ~pmask) | value;
else if constexpr ((pmask & 0x00FF)==0)
*(pVU8(reg) + 1) = (*(pVU8(reg) + 1) & ~(pmask>>8)) | (value>>8);
else
*reg = (*reg & ~pmask) | value;
}
template<uint32_t pmask>
_static_always_inline_ uint32_t readReg16(pVU32 reg)
{
if constexpr (pmask == 0xFFFF)
return *reg;
else if constexpr (pmask == 0x00FF)
return *pVU8(reg);
else if constexpr (pmask == 0xFF00)
return *(pVU8(reg) + 1)<<8;
else
return *reg & pmask;
}
template<uint32_t DMask, uint32_t Regmask>
_static_always_inline_ constexpr uint32_t OptimizeDMask()
{
if constexpr ((DMask==0) || (Regmask==0)) return 0;
else if constexpr (((DMask & 0x0000'00FF)==0x0000'00FF) && !(Regmask & 0xFFFF'FF00)) return 0x0000'00FF;
else if constexpr (((DMask & 0x0000'FF00)==0x0000'FF00) && !(Regmask & 0xFFFF'00FF)) return 0x0000'FF00;
else if constexpr (((DMask & 0x00FF'0000)==0x00FF'0000) && !(Regmask & 0xFF00'FFFF)) return 0x00FF'0000;
else if constexpr (((DMask & 0xFF00'0000)==0xFF00'0000) && !(Regmask & 0x00FF'FFFF)) return 0xFF00'0000;
else if constexpr (((DMask & 0x0000'FFFF)==0x0000'FFFF) && !(Regmask & 0xFFFF'0000)) return 0x0000'FFFF;
else if constexpr (((DMask & 0xFFFF'0000)==0xFFFF'0000) && !(Regmask & 0x0000'FFFF)) return 0xFFFF'0000;
else if constexpr (DMask==0xFFFF'FFFF) return 0xFFFF'FFFF;
else return Regmask;
}
template<uint32_t Mask, uint32_t Regmask>
_static_always_inline_ constexpr uint32_t OptimizeMask()
{
if constexpr ((Mask==0)||(Regmask==0)) return 0;
else if constexpr (((Mask & 0x00FF)==0x00FF) && !(Regmask & 0xFF00)) return 0x00FF;
else if constexpr (((Mask & 0xFF00)==0xFF00) && !(Regmask & 0x00FF)) return 0xFF00;
else if constexpr (Mask==0xFFFF) return 0xFFFF;
else return Regmask;
}
template<bool UsePwrCfg=false, uint32_t PMask, typename... Modes>
_static_always_inline_ void mode_(TypeList<Modes...> modes)
{
static_assert(countSetBits(PMask) == PinModeList<Modes...>::Size, "ModeList and Port size is not Equal!");
static constexpr uint32_t dm = dmask(PMask);
static constexpr auto modeTuple = getModeValues<PMask>(PinModeList<Modes...>::modes_);
[[maybe_unused]] static constexpr auto UsedRegs = std::get< 0>(modeTuple);
[[maybe_unused]] static constexpr auto Moder = std::get< 1>(modeTuple);
[[maybe_unused]] static constexpr auto Ospeedr = std::get< 2>(modeTuple);
[[maybe_unused]] static constexpr auto OspeedrMask = std::get< 3>(modeTuple);
[[maybe_unused]] static constexpr auto Pupdr = std::get< 4>(modeTuple);
[[maybe_unused]] static constexpr auto PupdrMask = std::get< 5>(modeTuple);
[[maybe_unused]] static constexpr auto Otyper = std::get< 6>(modeTuple);
[[maybe_unused]] static constexpr auto OtyperMask = std::get< 7>(modeTuple);
[[maybe_unused]] static constexpr auto AfrL = std::get< 8>(modeTuple);
[[maybe_unused]] static constexpr auto AfrLMask = std::get< 9>(modeTuple);
[[maybe_unused]] static constexpr auto AfrH = std::get<10>(modeTuple);
[[maybe_unused]] static constexpr auto AfrHMask = std::get<11>(modeTuple);
[[maybe_unused]] static constexpr auto State = std::get<12>(modeTuple);
[[maybe_unused]] static constexpr auto StateMask = std::get<13>(modeTuple);
writeReg32<UsePwrCfg ? OptimizeDMask<dm,Moder^pwrModer>() : dm>(&base()->MODER,Moder);
if constexpr (hasFlag(UsedRegs, GpioRegs::Pupdr))
writeReg32<OptimizeDMask<dm, PupdrMask&(UsePwrCfg?(Pupdr^pwrPupdr):0xFFFFFFFF)>()>(&base()->PUPDR, Pupdr);
if constexpr (hasFlag(UsedRegs, GpioRegs::Ospeedr))
writeReg32<OptimizeDMask<dm, OspeedrMask&(UsePwrCfg?(Ospeedr^pwrOspeedr):0xFFFFFFFF)>()>(&base()->OSPEEDR, Ospeedr);
if constexpr (hasFlag(UsedRegs, GpioRegs::Otyper))
{
if constexpr ( !UsePwrCfg || (UsePwrCfg && (Otyper!=0)) )
{
#ifdef STM32L0_ERRATA //Errata: 2.1.1 Writing in byte mode to the GPIOx_OTYPER register does not work
if constexpr (PMask==0xFFFF)
base()->OTYPER = Otyper; //+
else
base()->OTYPER = (base()->OTYPER & ~PMask) | Otyper; //+
#else
writeReg16<OptimizeMask<PMask, OtyperMask>()>(&base()->OTYPER, Otyper);
#endif
}
}
if constexpr (hasFlag(UsedRegs, GpioRegs::AfrL))
writeReg32<OptimizeDMask<qmask(PMask), AfrLMask&(UsePwrCfg?AfrL:0xFFFFFFFF)>()>(&base()->AFR[0], AfrL);
if constexpr (hasFlag(UsedRegs, GpioRegs::AfrH))
writeReg32<OptimizeDMask<qmask(PMask>>8), AfrHMask&(UsePwrCfg?AfrH:0xFFFFFFFF)>()>(&base()->AFR[1], AfrH);
if constexpr (hasFlag(UsedRegs, GpioRegs::State))
write<StateMask&(UsePwrCfg?State:0xFFFFFFFF)>(State);
}
template<uint32_t PMask, GpioRegs Regs=GpioRegs(0), uint32_t Moder=0, uint32_t Ospeedr=0, uint32_t OspeedrMask=0,
uint32_t Pupdr=0, uint32_t PupdrMask=0, uint32_t Otyper=0, uint32_t OtyperMask=0,
uint32_t AfrL=0, uint32_t AfrLMask=0, uint32_t AfrH=0, uint32_t AfrHMask=0,
uint32_t State=0, uint32_t StateMask=0, typename... Modes>
_static_always_inline_ constexpr auto getModeValues(TypeList<Modes...> modes)
{
if constexpr(!empty(modes))
{
constexpr uint32_t msb_num = MostSignificantBitNum(PMask);
constexpr uint32_t msb = 1U<<msb_num;
constexpr auto mode = decltype(head(modes))::pin_mode;
static_assert(mode!=STM32Fx_PinMode::NotDefined,"Pin mode undefined");
constexpr uint32_t af = decltype(head(modes))::af;
static_assert( (isAfMode<mode>() && (af<16)) || !isAfMode<mode>(), "Alternate Function is not defined");
constexpr auto UsedRegs = ( !isInputMode<mode>() ? GpioRegs::Otyper | GpioRegs::Ospeedr : GpioRegs(0) ) |
( isOutputStateDefined<mode,af>() ? GpioRegs::State : GpioRegs(0) ) |
( (isAfMode<mode>() && (msb&0x00FF)) ? GpioRegs::AfrL : GpioRegs(0) ) |
( (isAfMode<mode>() && (msb&0xFF00)) ? GpioRegs::AfrH : GpioRegs(0) ) |
( !isAnalog<mode>() ? GpioRegs::Pupdr : GpioRegs(0) ) | Regs;
constexpr uint32_t moder = Moder | (uint32_t(mode) & 3) << msb_num * 2;
constexpr uint32_t ospeedr = Ospeedr | ((uint32_t(mode) >> 2) & 3) << msb_num * 2;
constexpr uint32_t ospeedrmask = OspeedrMask | ((isInputMode<mode>() ? 0 : 3U) << msb_num * 2);
constexpr uint32_t pupdr = Pupdr | ((uint32_t(mode) >> 5) & 3) << msb_num * 2;
constexpr uint32_t pupdrmask = PupdrMask | ((isAnalog<mode>() ? 0 : 3U) << msb_num * 2);
constexpr uint32_t otyper = Otyper | ((uint32_t(mode) >> 4) & 1) << msb_num;
constexpr uint32_t otypermask = OtyperMask | ((isInputMode<mode>() ? 0 : 1U) << msb_num);
constexpr uint32_t afrl = AfrL | ((msb&0x00FF)? (af&0xF) << msb_num * 4 : 0);
constexpr uint32_t afrlmask = AfrLMask | ((isAfMode<mode>() && (msb&0x00FF)) ? 0xFU << msb_num * 4 : 0);
constexpr uint32_t afrh = AfrH | ((msb&0xFF00)? (af&0xF) << (msb_num-8) * 4 : 0);
constexpr uint32_t afrhmask = AfrHMask | ((isAfMode<mode>() && (msb&0xFF00)) ? 0xFU << (msb_num-8) * 4 : 0);
constexpr uint32_t state = State | (isOutputStateDefined<mode,af>() ? af*msb : 0);
constexpr uint32_t statemask = StateMask | (isOutputStateDefined<mode,af>() ? msb : 0);
return getModeValues< PMask&~msb, UsedRegs, moder, ospeedr, ospeedrmask, pupdr, pupdrmask,
otyper, otypermask, afrl, afrlmask, afrh, afrhmask, state, statemask>(pop_front(modes));
}
return std::make_tuple(Regs, Moder, Ospeedr, OspeedrMask, Pupdr, PupdrMask, Otyper, OtyperMask,
AfrL, AfrLMask, AfrH, AfrHMask, State, StateMask);
}
};
#define MAKE_PORT(PORT_NAME, PWR_CFG) \
template<uint32_t PinsMask = 0xFFFF, typename TPM = STM32Fx_MODE::NotDefined> \
using Gpio##PORT_NAME = TSTM32Fx_GPIO<GPIO##PORT_NAME##_BASE, PinsMask, TPM, PWR_CFG>;\
#ifdef GPIOA
MAKE_PORT(A,PWR_CFG_A)
MAKE_16PINS(GpioA,A)
#endif
#ifdef GPIOB
MAKE_PORT(B,PWR_CFG_B)
MAKE_16PINS(GpioB,B)
#endif
#ifdef GPIOC
MAKE_PORT(C,PWR_CFG_C)
MAKE_16PINS(GpioC,C)
#endif
#ifdef GPIOD
MAKE_PORT(D,PWR_CFG_D)
MAKE_16PINS(GpioD,D)
#endif
#ifdef GPIOE
MAKE_PORT(E,PWR_CFG_E)
MAKE_16PINS(GpioE,E)
#endif
#ifdef GPIOF
MAKE_PORT(F,PWR_CFG_F)
MAKE_16PINS(GpioF,F)
#endif
#ifdef GPIOG
MAKE_PORT(G,PWR_CFG_G)
MAKE_16PINS(GpioG,G)
#endif
#ifdef GPIOH
MAKE_PORT(H,PWR_CFG_H)
MAKE_16PINS(GpioH,H)
#endif
} //namespace STM32Fx_GPIO
Вт фев 04, 2020 14:53:10
Ага, отладкофобы форум атакуют!VladislavS писал(а):Прямо бунт на корабле какой-то сегодня
Расизм, нацизм, фашизм и т. д. тоже!Eddy_Em писал(а):Толерастия до добра никогда не доводит.
Ср фев 05, 2020 10:05:07
Круто! Только вот представить, какой там жуткий оверхед!..VladislavS писал(а):Вот примерчик моей билиотеки GPIO.
Ср фев 05, 2020 10:37:01
Ср фев 05, 2020 10:41:22
GPIOC->CRH = CRH(13, CNF_PPOUTPUT|MODE_SLOW);
Ср фев 05, 2020 13:42:31
Ср фев 05, 2020 17:37:45
Ср фев 05, 2020 18:11:49