/* =========================================================================*/ typedef struct { __IO uint32_t CR1; /*!< USART Control register 1, Address offset: 0x00 */ . . . __IO uint32_t ISR; /*!< USART Interrupt and status register, ... */ } USART_TypeDef; // USART_Type . /* =========================================================================*/ #define USART1_BASE (APBPERIPH_BASE + 0x00013800) . . . #define USART1 ((USART_TypeDef *) USART1_BASE) #define USART1_BASE 0x400xx000U
// ---------------------------------------------------------------------------- if (USART1->ISR & (ONE_ISR_FLAG & OTHER_ISR_FLAG)) { }
// ---------------------------------------------------------------------------- USART_TypeDef & Usart1 = *USART1; // ---------------------------------------------------------------------------- if (Usart1.ISR & (ONE_ISR_FLAG & OTHER_ISR_FLAG)) { }
/* =========================================================================*/ typedef struct { . . . } RCC_TypeDef;
/* =========================================================================*/ __IO uint32_t CR;
/* =========================================================================*/ #define RCC ((RCC_TypeDef *)RCC_BASE)
// ---------------------------------------------------------------------------- RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
// ---------------------------------------------------------------------------- RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN;
// ---------------------------------------------------------------------------- Rcc.PortOn(Port::A);
// ---------------------------------------------------------------------------- Rcc.PortOn<Port::A, Port::B>();
// ---------------------------------------------------------------------------- TRcc & Rcc = *static_cast<TRcc *>RCC;
// ============================================================================ enum class GPort : uint32_t { A = RCC_APB2ENR_IOPAEN, B = RCC_APB2ENR_IOPBEN, C = RCC_APB2ENR_IOPCEN, }; // ---------------------------------------------------------------------------- class TRcc: public ::RCC_TypeDef { private: TRcc() = delete; ~TRcc() = delete; // ======================================================================== public: template<GPort... port> inline void PortOn(void) // (inline) { // -Og -O0 APB2ENR |= SetBits<(uint32_t)port...>(); } // ------------------------------------------------------------------------ #define BITMASK 0x01 // , #define MASKWIDTH 1 // . // #undef. private: // (fold) . template<uint8_t bitmask> inline constexpr uint32_t SetBits(void) { // , GPort enum // (, , bitmask ). // static_assert(bitmask < 16, " ."); return bitmask; } template<uint8_t bit1, uint8_t bit2, uint8_t... bit> inline constexpr uint32_t SetBits(void) { return SetBits<bit1>() | SetBits<bit2, bit...>(); } }; #undef BITMASK #undef MASKWIDTH // ------------------------------------------------------------------------ TRcc & Rcc = *static_cast<TRcc *>RCC;
Rcc.PortOn<GPort::A>();
ldr r3, [pc, #376] ; (0x8000608 <main()+392>) ldr r0, [r3, #24] orr.w r0, r0, #4 str r0, [r3, #24]
Rcc.PortOn<GPort::A, GPort::B, GPort::C>();
ldr r3, [pc, #380] ; (0x8000614 <main()+404>) ldr r0, [r3, #24] orr.w r0, r0, #4 ; APB2ENR |= GPort::A str r0, [r3, #24] ldr r0, [r3, #24] orr.w r0, r0, #28 ; APB2ENR |= Gport::B | GPort::C str r0, [r3, #24] #24]
// ---------------------------------------------------------------------------- class TRcc: public ::RCC_TypeDef { private: TRcc() = delete; // , ~TRcc() = delete; // . // ======================================================================== public: template<GPort... port> inline void PortOn(void) // (inline) { // -Og -O0 APB2ENR |= SetBits17<(uint32_t)port...>(); } // ------------------------------------------------------------------------ #define BITMASK 0x01 // , #define MASKWIDTH 1 // . // #undef. private: // (fold) . ++ 17. template<uint8_t... bitmask> inline constexpr uint32_t SetBits17(void) { return (bitmask | ...); // ... | bit } }; #undef BITMASK #undef MASKWIDTH
ldr r2, [pc, #372] ; (0x800060c <main()+396>) ldr r0, [r2, #24] orr.w r0, r0, #28 ; APB2ENR |= Gport::A | Gport::B | GPort::C str r0, [r3, #24]
Rcc.PortOn<Port::A, Port::B, Port::C>();
RCC->APB2 |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN;
ldr r2, [pc, #372] ; (0x800060c <main()+396>) [ RCC] ldr r0, [r2, #0] ; r0 = RCC->APB2 // [ APB2] orr.w r0, r0, #160 ; r0 |= 0x10100000 str r0, [r2, #0] ; RCC->APB2 = r0
Source: https://habr.com/ru/post/448288/
All Articles