diff --git a/cpu/stm32/cpu_common.c b/cpu/stm32/cpu_common.c index a3eddd5826..999795b15d 100644 --- a/cpu/stm32/cpu_common.c +++ b/cpu/stm32/cpu_common.c @@ -14,16 +14,43 @@ * @brief Shared CPU specific function for the STM32 CPU family * * @author Hauke Petersen + * @author Joshua DeWeese * * @} */ +#include "periph/cpu_common.h" + +#include + +#include "compiler_hints.h" +#include "modules.h" #include "periph_conf.h" #include "periph_cpu.h" #define ENABLE_DEBUG 0 #include "debug.h" +#if defined(CPU_FAM_STM32F2) || \ + defined(CPU_FAM_STM32F4) || \ + defined(CPU_FAM_STM32F7) || \ + defined(CPU_FAM_STM32L1) + #define APB1_PERIPH_LP_EN RCC->APB1LPENR + #define APB2_PERIPH_LP_EN RCC->APB2LPENR + #ifdef AHB_PERIPH_EN + #define AHB_PERIPH_LP_EN RCC->AHBLPENR + #endif + #ifdef AHB1_PERIPH_EN + #define AHB1_PERIPH_LP_EN RCC->AHB1LPENR + #endif + #ifdef AHB2_PERIPH_EN + #define AHB2_PERIPH_LP_EN RCC->AHB2LPENR + #endif + #ifdef AHB3_PERIPH_EN + #define AHB3_PERIPH_LP_EN RCC->AHB3LPENR + #endif +#endif + /** * @brief Timer specific additional bus clock prescaler * @@ -51,13 +78,291 @@ static const uint8_t apbmul[] = { [APB12] = 1, #endif #endif +#if defined(APB2_PERIPH_EN) #if (CLOCK_APB2 < CLOCK_CORECLOCK) [APB2] = 2 #else [APB2] = 1 #endif +#endif }; +static volatile uint32_t* _rcc_en_reg(bus_t bus) +{ + switch (bus) { +#ifdef APB1_PERIPH_EN + case APB1: + return &APB1_PERIPH_EN; +#endif +#ifdef APB12_PERIPH_EN + case APB12: + return &APB12_PERIPH_EN; +#endif +#ifdef APB2_PERIPH_EN + case APB2: + return &APB2_PERIPH_EN; +#endif +#ifdef APB22_PERIPH_EN + case APB22: + return &APB22_PERIPH_EN; +#endif +#ifdef APB3_PERIPH_EN + case APB3: + return &APB3_PERIPH_EN; +#endif +#ifdef APB4_PERIPH_EN + case APB4: + return &APB4_PERIPH_EN; +#endif +#ifdef AHB_PERIPH_EN + case AHB: + return &AHB_PERIPH_EN; +#endif +#ifdef AHB1_PERIPH_EN + case AHB1: + return &AHB1_PERIPH_EN; +#endif +#ifdef AHB2_PERIPH_EN + case AHB2: + return &AHB2_PERIPH_EN; +#endif +#ifdef AHB22_PERIPH_EN + case AHB22: + return &AHB22_PERIPH_EN; +#endif +#ifdef AHB3_PERIPH_EN + case AHB3: + return &AHB3_PERIPH_EN; +#endif +#ifdef AHB4_PERIPH_EN + case AHB4: + return &AHB4_PERIPH_EN; +#endif +#ifdef IOP_PERIPH_EN + case IOP: + return &IOP_PERIPH_EN; +#endif + + case BUS_NUMOF: + assert(false); + return NULL; + } + + assert(false); + return NULL; +} + +static volatile uint32_t* _rcc_dis_reg(bus_t bus) +{ + /* Note this switch case is designed in such a way that a default is only + provided when all other cases are *not* provided. This is to ensure that + either all cases or no cases are provided. Anything else will cause the + compiler to emit a warning. */ + switch (bus) { +#ifdef APB1_PERIPH_DIS + #define RCC_REG_IS_ATOMIC 1 + case APB1: + return &APB1_PERIPH_DIS; + #endif +#ifdef APB12_PERIPH_DIS + #define RCC_REG_IS_ATOMIC 1 + case APB12: + return &APB12_PERIPH_DIS; +#endif +#ifdef APB2_PERIPH_DIS + #define RCC_REG_IS_ATOMIC 1 + case APB2: + return &APB2_PERIPH_DIS; +#endif +#ifdef APB22_PERIPH_DIS + #define RCC_REG_IS_ATOMIC 1 + case APB22: + return &APB22_PERIPH_DIS; +#endif +#ifdef APB3_PERIPH_DIS + #define RCC_REG_IS_ATOMIC 1 + case APB3: + return &APB3_PERIPH_DIS; +#endif +#ifdef APB4_PERIPH_DIS + #define RCC_REG_IS_ATOMIC 1 + case APB4: + return &APB4_PERIPH_DIS; +#endif +#ifdef AHB_PERIPH_DIS + #define RCC_REG_IS_ATOMIC 1 + case AHB: + return &AHB_PERIPH_DIS; +#endif +#ifdef AHB1_PERIPH_DIS + #define RCC_REG_IS_ATOMIC 1 + case AHB1: + return &AHB1_PERIPH_DIS; +#endif +#ifdef AHB2_PERIPH_DIS + #define RCC_REG_IS_ATOMIC 1 + case AHB2: + return &AHB2_PERIPH_DIS; +#endif +#ifdef AHB22_PERIPH_DIS + #define RCC_REG_IS_ATOMIC 1 + case AHB22: + return &AHB22_PERIPH_DIS; +#endif +#ifdef AHB3_PERIPH_DIS + #define RCC_REG_IS_ATOMIC 1 + case AHB3: + return &AHB3_PERIPH_DIS; +#endif +#ifdef AHB4_PERIPH_DIS + #define RCC_REG_IS_ATOMIC 1 + case AHB4: + return &AHB4_PERIPH_DIS; +#endif +#ifdef IOP_PERIPH_DIS + #define RCC_REG_IS_ATOMIC 1 + case IOP: + return &IOP_PERIPH_DIS; +#endif + + /* If MCU does not have separate set/clear bits. */ +#if RCC_REG_IS_ATOMIC == 0 + default: + return _rcc_en_reg(bus); +#else + case BUS_NUMOF: + assert(false); + return NULL; +#endif + } + + assert(false); + return NULL; +} + +static volatile uint32_t* _rcc_lp_en_reg(bus_t bus) +{ + /* Note this switch case is designed in such a way that a default is only + provided when all other cases are *not* provided. This is to ensure that + either all cases or no cases are provided. Anything else will cause the + compiler to emit a warning. */ + switch (bus) { +#ifdef APB1_PERIPH_LP_EN + #define HAS_LP_MODE 1 + case APB1: + return &APB1_PERIPH_LP_EN; +#endif +#ifdef APB12_PERIPH_LP_EN + #define HAS_LP_MODE 1 + case APB12: + return &APB12_PERIPH_LP_EN; +#endif +#ifdef APB2_PERIPH_LP_EN + #define HAS_LP_MODE 1 + case APB2: + return &APB2_PERIPH_LP_EN; +#endif +#ifdef APB22_PERIPH_LP_EN + #define HAS_LP_MODE 1 + case APB22: + return &APB22_PERIPH_LP_EN; +#endif +#ifdef APB3_PERIPH_LP_EN + #define HAS_LP_MODE 1 + case APB3: + return &APB3_PERIPH_LP_EN; +#endif +#ifdef APB4_PERIPH_LP_EN + #define HAS_LP_MODE 1 + case APB4: + return &APB4_PERIPH_LP_EN; +#endif +#ifdef AHB_PERIPH_LP_EN + #define HAS_LP_MODE 1 + case AHB: + return &AHB_PERIPH_LP_EN; +#endif +#ifdef AHB1_PERIPH_LP_EN + #define HAS_LP_MODE 1 + case AHB1: + return &AHB1_PERIPH_LP_EN; +#endif +#ifdef AHB2_PERIPH_LP_EN + #define HAS_LP_MODE 1 + case AHB2: + return &AHB2_PERIPH_LP_EN; +#endif +#ifdef AHB22_PERIPH_LP_EN + #define HAS_LP_MODE 1 + case AHB22: + return &AHB22_PERIPH_LP_EN; +#endif +#ifdef AHB3_PERIPH_LP_EN + #define HAS_LP_MODE 1 + case AHB3: + return &AHB3_PERIPH_LP_EN; +#endif +#ifdef AHB4_PERIPH_LP_EN + #define HAS_LP_MODE 1 + case AHB4: + return &AHB4_PERIPH_LP_EN; +#endif +#ifdef IOP_PERIPH_LP_EN + #define HAS_LP_MODE 1 + case IOP: + return &IOP_PERIPH_LP_EN; +#endif + +#if HAS_LP_MODE == 0 + default: + /* fall through */ +#endif + case BUS_NUMOF: + assert(false); + return NULL; + } + + assert(false); + return NULL; +} + +static volatile uint32_t* _rcc_lp_dis_reg(bus_t bus) +{ +#if RCC_REG_IS_ATOMIC && HAS_LP_MODE + #error "Atomic disable of periph-in-low-power-mode not implemented yet." +#endif + + return _rcc_lp_en_reg(bus); +} + +static void _rcc_reg_set(volatile uint32_t *reg, uint32_t mask) +{ + assert(reg); + + if (IS_ACTIVE(RCC_REG_IS_ATOMIC)) { + *reg = mask; + } + else { + const int irq_state = irq_disable(); + *reg |= mask; + irq_restore(irq_state); + } +} + +static void _rcc_reg_clr(volatile uint32_t *reg, uint32_t mask) +{ + assert(reg); + + if (IS_ACTIVE(RCC_REG_IS_ATOMIC)) { + *reg = mask; + } + else { + const int irq_state = irq_disable(); + *reg &= ~(mask); + irq_restore(irq_state); + } +} + uint32_t periph_apb_clk(bus_t bus) { #ifdef CLOCK_APB2 @@ -77,317 +382,46 @@ uint32_t periph_timer_clk(bus_t bus) void periph_clk_en(bus_t bus, uint32_t mask) { - switch (bus) { - case APB1: -#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32L5) || \ - defined(CPU_FAM_STM32U5) || defined(CPU_FAM_STM32WL) - RCC->APB1ENR1 |= mask; -#elif defined(CPU_FAM_STM32G0) || defined(CPU_FAM_STM32C0) - RCC->APBENR1 |= mask; -#elif defined(CPU_FAM_STM32MP1) - RCC->MC_APB1ENSETR |= mask; -#else - RCC->APB1ENR |= mask; -#endif - break; -#if !defined(CPU_FAM_STM32G0) && !defined(CPU_FAM_STM32C0) - case APB2: -#if defined(CPU_FAM_STM32MP1) - RCC->MC_APB2ENSETR |= mask; -#else - RCC->APB2ENR |= mask; -#endif - break; -#endif -#if defined(CPU_FAM_STM32WL) || defined(CPU_FAM_STM32U5) - case APB3: - RCC->APB3ENR |= mask; - break; -#endif -#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32L5) || \ - defined(CPU_FAM_STM32U5) || defined(CPU_FAM_STM32WL) - case APB12: - RCC->APB1ENR2 |= mask; - break; -#elif defined(CPU_FAM_STM32G0) || defined(CPU_FAM_STM32C0) - case APB12: - RCC->APBENR2 |= mask; - break; -#endif -#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32G0) || \ - defined(CPU_FAM_STM32C0) - case AHB: - RCC->AHBENR |= mask; - break; - case IOP: - RCC->IOPENR |= mask; - break; -#elif defined(CPU_FAM_STM32L1) || defined(CPU_FAM_STM32F1) || \ - defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) - case AHB: - RCC->AHBENR |= mask; - break; -#elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || \ - defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32F7) || \ - defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) || \ - defined(CPU_FAM_STM32L5) || defined(CPU_FAM_STM32U5) || \ - defined(CPU_FAM_STM32WL) - case AHB1: - RCC->AHB1ENR |= mask; - break; -/* STM32F410 RCC doesn't provide AHB2 and AHB3 */ -#if !defined(CPU_LINE_STM32F410Rx) - case AHB2: -#if defined(CPU_FAM_STM32U5) - RCC->AHB2ENR1 |= mask; -#else - RCC->AHB2ENR |= mask; -#endif - break; -#if defined(CPU_FAM_STM32U5) - case AHB22: - RCC->AHB2ENR2 |= mask; - break; -#endif - case AHB3: - RCC->AHB3ENR |= mask; - break; -#endif -#endif -#if defined(CPU_FAM_STM32MP1) - case AHB4: - RCC->MC_AHB4ENSETR |= mask; - break; -#endif - default: - DEBUG("unsupported bus %d\n", (int)bus); - break; - } + assert(bus < BUS_NUMOF); + + _rcc_reg_set(_rcc_en_reg(bus), mask); + /* stm32xx-errata: Delay after a RCC peripheral clock enable */ __DSB(); } void periph_clk_dis(bus_t bus, uint32_t mask) { - switch (bus) { - case APB1: -#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32L5) || \ - defined(CPU_FAM_STM32U5) || defined(CPU_FAM_STM32WL) - RCC->APB1ENR1 &= ~(mask); -#elif defined(CPU_FAM_STM32G0) || defined(CPU_FAM_STM32C0) - RCC->APBENR1 &= ~(mask); -#elif defined(CPU_FAM_STM32MP1) - /* Write 1 to clear */ - RCC->MC_APB1ENCLRR |= mask; -#else - RCC->APB1ENR &= ~(mask); -#endif - break; -#if !defined(CPU_FAM_STM32G0) && !defined(CPU_FAM_STM32C0) - case APB2: -#if defined(CPU_FAM_STM32MP1) - RCC->MC_APB2ENCLRR |= mask; -#else - RCC->APB2ENR &= ~(mask); -#endif - break; -#endif -#if defined(CPU_FAM_STM32WL) || defined(CPU_FAM_STM32U5) - case APB3: - RCC->APB3ENR &= ~(mask); - break; -#endif -#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32L5) || \ - defined(CPU_FAM_STM32U5) || defined(CPU_FAM_STM32WL) - case APB12: - RCC->APB1ENR2 &= ~(mask); - break; -#elif defined(CPU_FAM_STM32G0) || defined(CPU_FAM_STM32C0) - case APB12: - RCC->APBENR2 &= ~(mask); - break; -#endif -#if defined(CPU_FAM_STM32L0) - case AHB: - RCC->AHBENR &= ~(mask); - break; - case IOP: - RCC->IOPENR &= ~(mask); - break; -#elif defined(CPU_FAM_STM32L1) || defined(CPU_FAM_STM32F1) || \ - defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) - case AHB: - RCC->AHBENR &= ~(mask); - break; -#elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || \ - defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32F7) || \ - defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) || \ - defined(CPU_FAM_STM32L5) || defined(CPU_FAM_STM32U5) || \ - defined(CPU_FAM_STM32WL) - case AHB1: - RCC->AHB1ENR &= ~(mask); - break; -/* STM32F410 RCC doesn't provide AHB2 and AHB3 */ -#if !defined(CPU_LINE_STM32F410Rx) - case AHB2: -#if defined(CPU_FAM_STM32U5) - RCC->AHB2ENR1 &= ~(mask); -#else - RCC->AHB2ENR &= ~(mask); -#endif - break; -#if defined(CPU_FAM_STM32U5) - case AHB22: - RCC->AHB2ENR2 &= ~(mask); - break; -#endif - case AHB3: - RCC->AHB3ENR &= ~(mask); - break; -#endif -#if defined(CPU_FAM_STM32WB) - case AHB4: - RCC->AHB3ENR &= ~(mask); - break; -#endif -#endif - default: - DEBUG("unsupported bus %d\n", (int)bus); - break; - } + assert(bus < BUS_NUMOF); + _rcc_reg_clr(_rcc_dis_reg(bus), mask); } -#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32G4) || \ - defined(CPU_FAM_STM32L5) || defined(CPU_FAM_STM32U5) +MAYBE_UNUSED static inline +void _periph_lpclk_en(bus_t bus, uint32_t mask) +{ + assert(bus < BUS_NUMOF); + _rcc_reg_set(_rcc_lp_en_reg(bus), mask); +} + +MAYBE_UNUSED static inline +void _periph_lpclk_dis(bus_t bus, uint32_t mask) +{ + assert(bus < BUS_NUMOF); + _rcc_reg_clr(_rcc_lp_dis_reg(bus), mask); +} + +#if HAS_LP_MODE void periph_lpclk_en(bus_t bus, uint32_t mask) { - switch (bus) { - case APB1: - RCC->APB1SMENR1 |= mask; - break; - case APB12: - RCC->APB1SMENR2 |= mask; - break; - case APB2: - RCC->APB2SMENR |= mask; - break; - case AHB1: - RCC->AHB1SMENR |= mask; - break; - case AHB2: -#if defined(CPU_FAM_STM32U5) - RCC->AHB2SMENR1 |= mask; -#else - RCC->AHB2SMENR |= mask; -#endif - break; -#if defined(CPU_FAM_STM32U5) - case AHB22: - RCC->AHB2SMENR2 |= mask; - break; -#endif - case AHB3: - RCC->AHB3SMENR |= mask; - break; - default: - DEBUG("unsupported bus %d\n", (int)bus); - break; - } + /* call the function's implementation, which is outside the ifdef */ + _periph_lpclk_en(bus, mask); } +#endif +#if HAS_LP_MODE void periph_lpclk_dis(bus_t bus, uint32_t mask) { - switch (bus) { - case APB1: - RCC->APB1SMENR1 &= ~(mask); - break; - case APB12: - RCC->APB1SMENR2 &= ~(mask); - break; - case APB2: - RCC->APB2SMENR &= ~(mask); - break; - case AHB1: - RCC->AHB1SMENR &= ~(mask); - break; - case AHB2: -#if defined(CPU_FAM_STM32U5) - RCC->AHB2SMENR1 &= ~(mask); -#else - RCC->AHB2SMENR &= ~(mask); -#endif - break; -#if defined(CPU_FAM_STM32U5) - case AHB22: - RCC->AHB2SMENR2 &= ~(mask); - break; -#endif - case AHB3: - RCC->AHB3SMENR &= ~(mask); - break; - default: - DEBUG("unsupported bus %d\n", (int)bus); - break; - } -} -#elif defined(CPU_FAM_STM32F2) || \ - defined(CPU_FAM_STM32F4) || \ - defined(CPU_FAM_STM32F7) -void periph_lpclk_en(bus_t bus, uint32_t mask) -{ - switch (bus) { - case APB1: - RCC->APB1LPENR |= mask; - break; - case APB2: - RCC->APB2LPENR |= mask; - break; - case AHB1: - RCC->AHB1LPENR |= mask; - break; -/* STM32F410 RCC doesn't provide AHB2 and AHB3 */ -#if !defined(CPU_LINE_STM32F410Rx) - case AHB2: - RCC->AHB2LPENR |= mask; - break; - case AHB3: - RCC->AHB3LPENR |= mask; - break; -#endif - default: - DEBUG("unsupported bus %d\n", (int)bus); - break; - } -} - -void periph_lpclk_dis(bus_t bus, uint32_t mask) -{ - switch (bus) { - case APB1: - RCC->APB1LPENR &= ~(mask); - break; - case APB2: - RCC->APB2LPENR &= ~(mask); - break; - case AHB1: - RCC->AHB1LPENR &= ~(mask); - break; -/* STM32F410 RCC doesn't provide AHB2 and AHB3 */ -#if !defined(CPU_LINE_STM32F410Rx) - case AHB2: - RCC->AHB2LPENR &= ~(mask); - break; - case AHB3: - RCC->AHB3LPENR &= ~(mask); - break; -#endif - default: - DEBUG("unsupported bus %d\n", (int)bus); - break; - } + /* call the function's implementation, which is outside the ifdef */ + _periph_lpclk_dis(bus, mask); } #endif diff --git a/cpu/stm32/include/periph/cpu_common.h b/cpu/stm32/include/periph/cpu_common.h index 88b743c38e..89094f0727 100644 --- a/cpu/stm32/include/periph/cpu_common.h +++ b/cpu/stm32/include/periph/cpu_common.h @@ -23,6 +23,8 @@ #include +#include "cpu_conf.h" + #ifdef __cplusplus extern "C" { #endif @@ -68,49 +70,148 @@ extern "C" { #error "error: LSI clock speed not defined for your target CPU" #endif +/* if CPU has APB1 bus */ +#if defined(CPU_FAM_STM32G4) || \ + defined(CPU_FAM_STM32L4) || \ + defined(CPU_FAM_STM32L5) || \ + defined(CPU_FAM_STM32U5) || \ + defined(CPU_FAM_STM32WB) || \ + defined(CPU_FAM_STM32WL) + #define APB1_PERIPH_EN RCC->APB1ENR1 + #define APB12_PERIPH_EN RCC->APB1ENR2 +#elif defined(CPU_FAM_STM32C0) || \ + defined(CPU_FAM_STM32G0) + #define APB1_PERIPH_EN RCC->APBENR1 + #define APB12_PERIPH_EN RCC->APBENR2 +#elif defined(CPU_FAM_STM32MP1) + #define APB1_PERIPH_EN RCC->MC_APB1ENSETR + #define APB1_PERIPH_DIS RCC->MC_APB1ENCLRR +#elif defined(APB1PERIPH_BASE) || \ + defined(CPU_FAM_STM32F0) || \ + defined(CPU_FAM_STM32L0) + #define APB1_PERIPH_EN RCC->APB1ENR +#endif + +/* if CPU has APB2 bus */ +#if defined(CPU_FAM_STM32MP1) + #define APB2_PERIPH_EN RCC->MC_APB2ENSETR + #define APB2_PERIPH_DIS RCC->MC_APB2ENCLRR +#elif defined(APB2PERIPH_BASE) || \ + defined(CPU_FAM_STM32F0) || \ + defined(CPU_FAM_STM32L0) + #define APB2_PERIPH_EN RCC->APB2ENR +#endif + +/* if CPU has APB3 bus */ +#if defined(CPU_FAM_STM32WB) + /* CPU has APB3, but no periph enable registers for the bus. */ + #undef APB3_PERIPH_EN /* not defined */ +#elif defined(APB3PERIPH_BASE) || \ + defined(APB3PERIPH_BASE_S) + #define APB3_PERIPH_EN RCC->APB3ENR +#endif + +/* if CPU has AHB/AHB1 bus */ +#if defined(AHBPERIPH_BASE) || \ + defined(CPU_FAM_STM32F3) + #define AHB_PERIPH_EN RCC->AHBENR +#elif defined(CPU_FAM_STM32MP1) + /* CPU has AHB1, but no periph enable registers for the bus. */ + #undef AHB1_PERIPH_EN /* not defined */ + #undef AHB1_PERIPH_DIS /* not defined */ +#elif defined(AHB1PERIPH_BASE) + #define AHB1_PERIPH_EN RCC->AHB1ENR +#endif + +/* if CPU has AHB2 bus */ +#if defined(CPU_FAM_STM32F0) || \ + defined(CPU_FAM_STM32F3) + /* CPU has AHB2, but no periph enable registers for the bus. */ + #undef AHB2_PERIPH_EN /* not defined */ +#elif defined(CPU_FAM_STM32U5) + #define AHB2_PERIPH_EN RCC->AHB2ENR1 + #define AHB22_PERIPH_EN RCC->AHB2ENR2 +#elif defined(CPU_FAM_STM32F4) && defined(RCC_AHB2_SUPPORT) + #define AHB2_PERIPH_EN RCC->AHB2ENR +#elif defined(CPU_FAM_STM32MP1) + #define AHB2_PERIPH_EN RCC->MC_AHB2ENSETR + #define AHB2_PERIPH_DIS RCC->MC_AHB2ENCLRR +#elif defined(AHB2PERIPH_BASE) + #define AHB2_PERIPH_EN RCC->AHB2ENR +#endif + +/* if CPU has AHB3 bus */ +#if defined(CPU_FAM_STM32F3) + /* CPU has AHB3, but no periph enable registers for the bus. */ + #undef AHB3_PERIPH_EN /* not defined */ +#elif defined(CPU_FAM_STM32F4) && defined(RCC_AHB3_SUPPORT) + #define AHB3_PERIPH_EN RCC->AHB3ENR +#elif defined(CPU_FAM_STM32MP1) + #define AHB3_PERIPH_EN RCC->MC_AHB3ENSETR + #define AHB3_PERIPH_DIS RCC->MC_AHB3ENCLRR +#elif defined(AHB3PERIPH_BASE) || \ + defined(AHB3PERIPH_BASE_S) || \ + defined(CPU_FAM_STM32F2) || \ + defined(CPU_FAM_STM32F7) || \ + defined(CPU_FAM_STM32G4) || \ + defined(CPU_FAM_STM32L4) + #define AHB3_PERIPH_EN RCC->AHB3ENR +#endif + +/* if CPU has AHB4 bus */ +#if defined(CPU_FAM_STM32MP1) + #define AHB4_PERIPH_EN RCC->MC_AHB4ENSETR + #define AHB4_PERIPH_DIS RCC->MC_AHB4ENCLRR +#elif defined(AHB4PERIPH_BASE) + /* AHB3ENR is not a typo here. It controls both AHB3 and AHB4. */ + #define AHB4_PERIPH_EN RCC->AHB3ENR +#endif + +/* if CPU has IOP bus */ +#if defined(IOPPERIPH_BASE) || \ + defined(RCC_IOPENR_GPIOAEN) || \ + defined(RCC_IOPENR_IOPAEN) + #define IOP_PERIPH_EN RCC->IOPENR +#endif + /** * @brief Available peripheral buses */ typedef enum { +#if defined(APB1_PERIPH_EN) APB1, /**< APB1 bus */ - APB2, /**< APB2 bus */ -#if defined(CPU_FAM_STM32WL) || defined(CPU_FAM_STM32U5) - APB3, #endif -#if defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32WB) || \ - defined(CPU_FAM_STM32G4) || defined(CPU_FAM_STM32G0) || \ - defined(CPU_FAM_STM32L5) || defined(CPU_FAM_STM32U5) || \ - defined(CPU_FAM_STM32WL) || defined(CPU_FAM_STM32C0) +#if defined(APB12_PERIPH_EN) APB12, /**< AHB1 bus, second register */ #endif -#if defined(CPU_FAM_STM32L0) || defined(CPU_FAM_STM32G0) || \ - defined(CPU_FAM_STM32C0) +#if defined(APB2_PERIPH_EN) + APB2, /**< APB2 bus */ +#endif +#if defined(APB3_PERIPH_EN) + APB3, /**< APB3 bus */ +#endif +#if defined(AHB_PERIPH_EN) AHB, /**< AHB bus */ - IOP, /**< IOP bus */ -#elif defined(CPU_FAM_STM32L1) || defined(CPU_FAM_STM32F1) || \ - defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) - AHB, /**< AHB bus */ -#elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || \ - defined(CPU_FAM_STM32L4) || defined(CPU_FAM_STM32F7) || \ - defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32G4) || \ - defined(CPU_FAM_STM32L5) || defined(CPU_FAM_STM32U5) || \ - defined(CPU_FAM_STM32WL) +#endif +#if defined(AHB1_PERIPH_EN) AHB1, /**< AHB1 bus */ +#endif +#if defined(AHB2_PERIPH_EN) AHB2, /**< AHB2 bus */ -#if defined(CPU_FAM_STM32U5) +#endif +#if defined(AHB22_PERIPH_EN) AHB22, /**< AHB2 bus, second register */ #endif +#if defined(AHB3_PERIPH_EN) AHB3, /**< AHB3 bus */ -#elif defined(CPU_FAM_STM32MP1) - AHB1, /**< AHB1 bus */ - AHB2, /**< AHB2 bus */ - AHB3, /**< AHB3 bus */ -#else -#warning "unsupported stm32XX family" #endif -#if defined(CPU_FAM_STM32WB) || defined(CPU_FAM_STM32MP1) +#if defined(AHB4_PERIPH_EN) AHB4, /**< AHB4 bus */ #endif +#if defined(IOP_PERIPH_EN) + IOP, /**< IOP bus */ +#endif + BUS_NUMOF /**< number of buses */ } bus_t; /**