STM32F1 clock line method 'wrong'?

I’m looking into the SDIO and FSMC on my Tronxy X5SA, to try to get them working. However it appears that the clock enablement isn’t quite right…

In this function below to get the clock lines (for stm32f1xxx):

// Map a peripheral address to its enable bits
struct cline
lookup_clock_line(uint32_t periph_base)
{
    if (periph_base >= AHBPERIPH_BASE) {
        uint32_t bit = 1 << ((periph_base - AHBPERIPH_BASE) / 0x400);
        return (struct cline){.en=&RCC->AHBENR, .bit=bit};
    } else if (periph_base >= APB2PERIPH_BASE) {
        uint32_t bit = 1 << ((periph_base - APB2PERIPH_BASE) / 0x400);
        return (struct cline){.en=&RCC->APB2ENR, .rst=&RCC->APB2RSTR, .bit=bit};
    } else {
        uint32_t bit = 1 << ((periph_base - APB1PERIPH_BASE) / 0x400);
        return (struct cline){.en=&RCC->APB1ENR, .rst=&RCC->APB1RSTR, .bit=bit};
    }
}
....
#define   APB1PERIPH_BASE       0x40000000UL
#define   APB2PERIPH_BASE       0x40010000UL
#define   SDIO_BASE             0x40018000UL
#define   AHBPERIPH_BASE        0x40020000UL
#define   FSMC_R_BASE           0xA0000000UL 

From the reference manual for the STM32F103xx (and similar)
https://www.st.com/resource/en/reference_manual/rm0008-stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf
The SDIO_EN should be bit 10 in AHBENR, and FSMC_EN should be bit 8.
But, according to the calculation being done in Klipper right now, it tries to set bit 32 (1 << 32) of APB2ENR for SDIO, and is bonkers for FSMC.

Would there be strong objection to re-aligning the STM32 clock setting to more in line with STmicro example code usage?

  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
                         RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG |
                         RCC_APB2Periph_AFIO, ENABLE);

Where it’s expected that the AHB/APB1/APB2 positioning is known ahead of time?
Or perhaps just special casing some of these slightly whackier register allocations?

We typically just special case the exceptions - take a look at stm32g0.c for an example.

Cheers,
-Kevin

1 Like