1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

Merge pull request #20609 from Enoch247/improve-stm32-periph-enable.2

cpu/stm32: de-duplicate ifdefs
This commit is contained in:
benpicco 2024-05-24 09:52:06 +00:00 committed by GitHub
commit fb4e0ccf10
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 459 additions and 324 deletions

View File

@ -14,16 +14,43 @@
* @brief Shared CPU specific function for the STM32 CPU family
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Joshua DeWeese <jdeweese@primecontrols.com>
*
* @}
*/
#include "periph/cpu_common.h"
#include <assert.h>
#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

View File

@ -23,6 +23,8 @@
#include <stdint.h>
#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;
/**