online compiler and debugger for c/c++

code. compile. run. debug. share.
Source Code    Language
#include <cstddef> #include <cstdint> #include <type_traits> #include <initializer_list> #define __forceinline _Pragma("inline=forced") //#define __forceinline //Режим доступа к регистрам struct WriteMode {}; struct ReadMode {}; struct ReadWriteMode: public WriteMode, public ReadMode {}; //Тип регистров в зависимости от размера template <uint32_t size> struct RegisterType {} ; template<> struct RegisterType<8> { using Type = uint8_t ; } ; template<> struct RegisterType<16> { using Type = uint16_t ; } ; template<> struct RegisterType<32> { using Type = uint32_t ; } ; template<> struct RegisterType<64> { using Type = uint64_t ; } ; //Базовый класс для работы с регистром template<uint32_t address, size_t size, typename AccessMode> struct RegisterBase { static constexpr auto Address = address ; using Type = typename RegisterType<size>::Type ; //Метод Write будет работать только для регистров, в которые можно записать значение __forceinline template<typename T = AccessMode, class = typename std::enable_if_t<std::is_base_of<WriteMode, T>::value>> inline static void Set(Type value) { *reinterpret_cast<Type *>(address) = value ; } //Метод Get возвращает целое значение регистра, будет работать только для регистров, которые можно считать __forceinline template<typename T = AccessMode, class = typename std::enable_if_t<std::is_base_of<ReadMode, T>::value>> inline static Type Get() { return *reinterpret_cast<Type *>(address) ; } } ; //Базовый класс для работы с битовыми полями регистров template<typename Reg, size_t offset, size_t size, typename AccessMode> struct RegisterField { using RegType = typename Reg::Type ; using Register = Reg ; static constexpr RegType Offset = offset ; static constexpr RegType Size = size ; using Access = AccessMode ; //Метод устанавливает значение битового поля, только в случае, если оно достпуно для записи __forceinline template<typename T = AccessMode, class = typename std::enable_if_t<std::is_base_of<WriteMode, T>::value>> static void Set(RegType value) { RegType newRegValue = *reinterpret_cast<RegType *>(Reg::Address) ; //Сохраняем текущее значение регистра newRegValue &= ~ (((1 << size) - 1) << offset); //Вначале нужно очистить старое значение битового поля newRegValue |= (value << offset) ; // Затем установить новое *reinterpret_cast<RegType *>(Reg::Address) = newRegValue ; //И записать новое значение в регистр } //Метод устанавливает проверяет установлено ли значение битового поля __forceinline template<typename T = AccessMode, class = typename std::enable_if_t<std::is_base_of<ReadMode, T>::value>> inline static RegType Get() { return ((*reinterpret_cast<RegType *>(Reg::Address)) & (((1U << size) - 1U) << offset)) >> offset ; } }; //Базовый класс для работы с битовыми полями регистров template<typename Field, typename Base, typename Field::Register::Type value> struct FieldValueBase { using RegType = typename Field::Register::Type ; //Метод устанавливает значение битового поля, только в случае, если оно достпуно для записи __forceinline template<typename T = typename Field::Access, class = typename std::enable_if_t<std::is_base_of<WriteMode, T>::value>> static void Set() { RegType newRegValue = *reinterpret_cast<RegType *>(Field::Register::Address) ; //Сохраняем текущее значение регистра newRegValue &= ~ (((1 << Field::Size) - 1) << Field::Offset); //Вначале нужно очистить старое значение битового поля newRegValue |= (value << Field::Offset) ; // Затем установить новое *reinterpret_cast<RegType *>(Field::Register::Address) = newRegValue ; //И записать новое значение в регистр } //Метод устанавливает проверяет установлено ли значение битового поля __forceinline template<typename T = typename Field::Access, class = typename std::enable_if_t<std::is_base_of<ReadMode, T>::value>> inline static bool IsSet() { return ((*reinterpret_cast<RegType *>(Field::Register::Address)) & static_cast<RegType>(((1 << Field::Size) - 1) << Field::Offset)) == (value << Field::Offset) ; } }; //Класс для работы с битовыми полями. Добавился тип Base, который необходим для того, чтобы проверить, что //В регистре устанавливаются те битовые поля, которые допустимы для данного регистра //template<typename Reg, size_t offset, size_t size, typename AccessMode, typename Base, typename Reg::Type value> template<typename Field, typename Base, typename Field::Register::Type value> //struct FieldValue: public FieldValueBase<Reg, offset, size, AccessMode, value> struct FieldValue: public FieldValueBase<Field, Base, value> { using Type = typename Field::Register::Type ; constexpr static auto Mask = static_cast<Type>(1U << Field::Size) - 1U ; constexpr static auto Value = value ; constexpr static auto Offset = Field::Offset ; using BaseType = Base ; using Access = typename Field::Access ; } ; //Класс для работы с регистром, можно передавать список Битовых полей для установки и проверки template<uint32_t address, size_t size, typename AccessMode, typename FieldValueBaseType, typename ...Args> class Register { public: using Type = typename RegisterType<size>::Type; //Метод Set устанавливает битовые поля, только если регистр может использоваться для записи __forceinline template<typename T = AccessMode, class = typename std::enable_if_t<std::is_base_of<WriteMode, T>::value>> static void Set() { Type newRegValue = *reinterpret_cast<Type *>(address) ; //Сохраняем текущее значение регистра newRegValue &= ~GetMask() ; //Сбрасываем битовые поля, которые нужно будет установить newRegValue |= GetValue() ; //Устанавливаем новые значения битовых полей *reinterpret_cast<Type *>(address) = newRegValue ; //Записываем в регистра новое значение } //Метод IsSet проверяет что все битовые поля из переданного набора установлены __forceinline template<typename T = AccessMode, class = typename std::enable_if_t<std::is_base_of<ReadMode, T>::value>> static bool IsSet() { Type newRegValue = *reinterpret_cast<Type *>(address) ; return ((newRegValue & GetMask()) == GetValue()) ; } private: //Вспомогательный метод, возвращает маску для конктретного битового поля на этапе компиляции. //Метод определен только в случае, если тип битового поля и базовый тип битового поля для регистра совпадают. //Т.е. нельзя устанвоить набор битов не соотвествующих набору для для данного регистра. __forceinline template<typename T, class = typename std::enable_if_t<std::is_same<FieldValueBaseType, typename T::BaseType>::value>> static constexpr auto GetIndividualMask() { Type result = T::Mask << T::Offset ; return result ; } //Вспомогательный метод, расчитывает общую маску для всего набора битовых полей на этапе компиляции. static constexpr auto GetMask() { const auto values = {GetIndividualMask<Args>()...} ; //распаковываем набор битовых полей через список инициализации Type result = 0UL; for (auto const v: values) { result |= v ; //для каждого битового поля устанавливаем битовую маску } return result ; } //Вспомогательный метод, возвращает значение для конктретного битового поля на этапе компиляции. //Метод определен только в случае, если тип битового поля и базовый тип битового поля для регистра совпадают. //Т.е. нельзя устанвоить набор битов не соотвествующих набору для для данного регистра. __forceinline template<typename T, class = typename std::enable_if_t<std::is_same<FieldValueBaseType, typename T::BaseType>::value>> static constexpr auto GetIndividualValue() { Type result = T::Value << T::Offset ; return result ; } //Вспомогательный метод, расчитывает значение которое нужно установить в регистре для всего набора битовых полей static constexpr auto GetValue() { const auto values = {GetIndividualValue<Args>()...}; Type result = 0UL; for (const auto v: values) { result |= v ; } return result ; } }; template <typename Reg, size_t offset, size_t size, typename AccessMode, typename BaseType> struct RCC_AHBENR_GPIOAEN_Values: public RegisterField<Reg, offset, size, AccessMode> { using Disable = FieldValue<RCC_AHBENR_GPIOAEN_Values, BaseType, 0U> ; using Enable = FieldValue<RCC_AHBENR_GPIOAEN_Values, BaseType, 1U> ; } ; struct RCC { struct RCCAHB1ENRBase {} ; struct AHB1ENR : public RegisterBase<0x40023830, 32, ReadWriteMode> { using GPIOAEN = RCC_AHBENR_GPIOAEN_Values<RCC::AHB1ENR, 0, 1, ReadWriteMode, RCCAHB1ENRBase> ; } ; } ; template <typename Reg, size_t offset, size_t size, typename AccessMode, typename BaseType> struct GPIOA_IDR_IDR_Values: public RegisterField<Reg, offset, size, AccessMode> { using NotSet = FieldValue<GPIOA_IDR_IDR_Values, BaseType, 0U> ; using Set = FieldValue<GPIOA_IDR_IDR_Values, BaseType, 1U> ; } ; template <typename Reg, size_t offset, size_t size, typename AccessMode, typename BaseType> struct GPIOA_MODER_MODER_Values: public RegisterField<Reg, offset, size, AccessMode> { using Input = FieldValue<GPIOA_MODER_MODER_Values, BaseType, 0U> ; using Output = FieldValue<GPIOA_MODER_MODER_Values, BaseType, 1U> ; using Alternate = FieldValue<GPIOA_MODER_MODER_Values, BaseType, 2U> ; using Analog = FieldValue<GPIOA_MODER_MODER_Values, BaseType, 3U> ; } ; template <typename Reg, size_t offset, size_t size, typename AccessMode, typename BaseType> struct GPIOA_BSRR_BR_Values: public RegisterField<Reg, offset, size, AccessMode> { using None = FieldValue<GPIOA_BSRR_BR_Values, BaseType, 0U> ; using Reset = FieldValue<GPIOA_BSRR_BR_Values, BaseType, 1U> ; } ; template <typename Reg, size_t offset, size_t size, typename AccessMode, typename BaseType> struct GPIOA_BSRR_BS_Values: public RegisterField<Reg, offset, size, AccessMode> { using None = FieldValue<GPIOA_BSRR_BS_Values, BaseType, 0U> ; using Set = FieldValue<GPIOA_BSRR_BS_Values, BaseType, 1U> ; } ; struct GPIOA { struct GPIOAMODERBase {} ; struct MODER : public RegisterBase<0x40020000, 32, ReadWriteMode> { using MODER15 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 30, 2, ReadWriteMode, GPIOAMODERBase> ; using MODER14 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 28, 2, ReadWriteMode, GPIOAMODERBase> ; using MODER13 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 26, 2, ReadWriteMode, GPIOAMODERBase> ; using MODER12 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 24, 2, ReadWriteMode, GPIOAMODERBase> ; using MODER11 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 22, 2, ReadWriteMode, GPIOAMODERBase> ; using MODER10 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 20, 2, ReadWriteMode, GPIOAMODERBase> ; using MODER9 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 18, 2, ReadWriteMode, GPIOAMODERBase> ; using MODER8 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 16, 2, ReadWriteMode, GPIOAMODERBase> ; using MODER7 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 14, 2, ReadWriteMode, GPIOAMODERBase> ; using MODER6 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 12, 2, ReadWriteMode, GPIOAMODERBase> ; using MODER5 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 10, 2, ReadWriteMode, GPIOAMODERBase> ; using MODER4 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 8, 2, ReadWriteMode, GPIOAMODERBase> ; using MODER3 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 6, 2, ReadWriteMode, GPIOAMODERBase> ; using MODER2 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 4, 2, ReadWriteMode, GPIOAMODERBase> ; using MODER1 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 2, 2, ReadWriteMode, GPIOAMODERBase> ; using MODER0 = GPIOA_MODER_MODER_Values<GPIOA::MODER, 0, 2, ReadWriteMode, GPIOAMODERBase> ; } ; template<typename... T> using MODERPack = Register<0x40020000, 32, ReadWriteMode, GPIOAMODERBase, T...> ; struct GPIOAIDRBase {} ; struct IDR : public RegisterBase<0x40020010, 32, ReadMode> { using IDR15 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 15, 1, ReadMode, GPIOAIDRBase> ; using IDR14 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 14, 1, ReadMode, GPIOAIDRBase> ; using IDR13 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 13, 1, ReadMode, GPIOAIDRBase> ; using IDR12 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 12, 1, ReadMode, GPIOAIDRBase> ; using IDR11 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 11, 1, ReadMode, GPIOAIDRBase> ; using IDR10 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 10, 1, ReadMode, GPIOAIDRBase> ; using IDR9 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 9, 1, ReadMode, GPIOAIDRBase> ; using IDR8 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 8, 1, ReadMode, GPIOAIDRBase> ; using IDR7 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 7, 1, ReadMode, GPIOAIDRBase> ; using IDR6 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 6, 1, ReadMode, GPIOAIDRBase> ; using IDR5 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 5, 1, ReadMode, GPIOAIDRBase> ; using IDR4 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 4, 1, ReadMode, GPIOAIDRBase> ; using IDR3 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 3, 1, ReadMode, GPIOAIDRBase> ; using IDR2 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 2, 1, ReadMode, GPIOAIDRBase> ; using IDR1 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 1, 1, ReadMode, GPIOAIDRBase> ; using IDR0 = GPIOA_IDR_IDR_Values<GPIOA::IDR, 0, 1, ReadMode, GPIOAIDRBase> ; } ; template<typename... T> using IDRPack = Register<0x40020010, 32, ReadMode, GPIOAIDRBase, T...> ; struct GPIOABSRRBase {} ; struct BSRR : public RegisterBase<0x40020018, 32, WriteMode> { using BR15 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 31, 1, WriteMode, GPIOABSRRBase> ; using BR14 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 30, 1, WriteMode, GPIOABSRRBase> ; using BR13 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 29, 1, WriteMode, GPIOABSRRBase> ; using BR12 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 28, 1, WriteMode, GPIOABSRRBase> ; using BR11 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 27, 1, WriteMode, GPIOABSRRBase> ; using BR10 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 26, 1, WriteMode, GPIOABSRRBase> ; using BR9 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 25, 1, WriteMode, GPIOABSRRBase> ; using BR8 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 24, 1, WriteMode, GPIOABSRRBase> ; using BR7 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 23, 1, WriteMode, GPIOABSRRBase> ; using BR6 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 22, 1, WriteMode, GPIOABSRRBase> ; using BR5 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 21, 1, WriteMode, GPIOABSRRBase> ; using BR4 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 20, 1, WriteMode, GPIOABSRRBase> ; using BR3 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 19, 1, WriteMode, GPIOABSRRBase> ; using BR2 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 18, 1, WriteMode, GPIOABSRRBase> ; using BR1 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 17, 1, WriteMode, GPIOABSRRBase> ; using BR0 = GPIOA_BSRR_BR_Values<GPIOA::BSRR, 16, 1, WriteMode, GPIOABSRRBase> ; using BS15 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 15, 1, WriteMode, GPIOABSRRBase> ; using BS14 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 14, 1, WriteMode, GPIOABSRRBase> ; using BS13 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 13, 1, WriteMode, GPIOABSRRBase> ; using BS12 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 12, 1, WriteMode, GPIOABSRRBase> ; using BS11 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 11, 1, WriteMode, GPIOABSRRBase> ; using BS10 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 10, 1, WriteMode, GPIOABSRRBase> ; using BS9 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 9, 1, WriteMode, GPIOABSRRBase> ; using BS8 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 8, 1, WriteMode, GPIOABSRRBase> ; using BS7 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 7, 1, WriteMode, GPIOABSRRBase> ; using BS6 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 6, 1, WriteMode, GPIOABSRRBase> ; using BS5 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 5, 1, WriteMode, GPIOABSRRBase> ; using BS4 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 4, 1, WriteMode, GPIOABSRRBase> ; using BS3 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 3, 1, WriteMode, GPIOABSRRBase> ; using BS2 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 2, 1, WriteMode, GPIOABSRRBase> ; using BS1 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 1, 1, WriteMode, GPIOABSRRBase> ; using BS0 = GPIOA_BSRR_BS_Values<GPIOA::BSRR, 0, 1, WriteMode, GPIOABSRRBase> ; } ; template<typename... T> using BSRRPack = Register<0x40020018, 32, WriteMode, GPIOABSRRBase, T...> ; } ; int main() { RCC::AHB1ENR::GPIOAEN::Enable::Set() ; RCC::AHB1ENR::GPIOAEN::Enable::Set() ; GPIOA::MODER::MODER15::Output::Set() ; GPIOA::MODERPack< GPIOA::MODER::MODER12::Output, GPIOA::MODER::MODER14::Analog >::Set() ; //******************************************* // Включаем тактирование на порту GPIOA //Ошибка компиляции, у регистра APB1ENR нет поля GPIOAEN //RCC::APB1ENR::GPIOAEN::Enable::Set() ; //Все хорошо, подали тактирование на порт GPIOA RCC::AHB1ENR::GPIOAEN::Enable::Set() ; //Ошибка компиляции, RCC::APB2ENR::TIM1EN::Enable не //является полем регистра APB1ENR //RCC::APB1ENRPack<RCC::APB1ENR::TIM2EN::Enable, // RCC::APB2ENR::TIM1EN::Enable>::Set(); //Ошибка компиляции, регистр BSRR только для записи //auto result = GPIOA::BSRR::Get() ; //Ошибка компиляции, значение Reset только для записи // if (GPIOA::BSRR::BS1::Reset::IsSet()) { //do something } //Ошибка компиляции, значение поля регистра только для чтения // GPIOA::IDR::IDR5::On::Set() GPIOA::MODER::MODER15::Output::Set() ; auto result = GPIOA::MODER::MODER15::Output::IsSet() ; GPIOA::MODER::Set(2U) ; auto test = GPIOA::MODER::Get() ; GPIOA::MODERPack< GPIOA::MODER::MODER15::Output, GPIOA::MODER::MODER14::Analog >::Set() ; result = GPIOA::MODERPack< GPIOA::MODER::MODER15::Output, GPIOA::MODER::MODER14::Analog >::IsSet() ; ; GPIOA::MODER::MODER15::Set(2U) ; test = GPIOA::MODER::MODER15::Get() ; auto i = GPIOA::IDR::Get() ; GPIOA::BSRRPack<GPIOA::BSRR::BR0::Reset, GPIOA::BSRR::BR4::Reset >::Set() ; return 0 ; }

Compiling Program...

Command line arguments:
Standard Input: Interactive Console Text

                

                

Program is not being debugged. Click "Debug" button to start program in debug mode.

#FunctionFile:Line
VariableValue
RegisterValue
ExpressionValue