diff --git a/cpu/stm32_common/cpu_init.c b/cpu/stm32_common/cpu_init.c index c11866217a..e64ba3f38b 100644 --- a/cpu/stm32_common/cpu_init.c +++ b/cpu/stm32_common/cpu_init.c @@ -26,6 +26,8 @@ * @author Víctor Ariño * @author Kaspar Schleiser * @author Vincent Dupont + * @author Oleg Artamonov + * @author Francisco Molina * * @} */ @@ -41,6 +43,100 @@ #define BIT_APB_PWREN RCC_APB1ENR_PWREN #endif +#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F1) || \ + defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F3) || \ + defined(CPU_FAM_STM32F4) || defined(CPU_FAM_STM32F7) + +#define STM32_CPU_MAX_GPIOS (12U) + +#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F3) +#define GPIO_CLK (AHB) +#define GPIO_CLK_ENR (RCC->AHBENR) +#define GPIO_CLK_ENR_MASK (0xFFFF0000) +#elif defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || \ + defined(CPU_FAM_STM32F7) +#define GPIO_CLK (AHB1) +#define GPIO_CLK_ENR (RCC->AHB1ENR) +#define GPIO_CLK_ENR_MASK (0x0000FFFF) +#elif defined(CPU_FAM_STM32F1) +#define GPIO_CLK (APB2) +#define GPIO_CLK_ENR (RCC->APB2ENR) +#define GPIO_CLK_ENR_MASK (0x000001FC) +#endif + +#ifndef DISABLE_JTAG +#define DISABLE_JTAG 0 +#endif + +/** + * @brief Initialize gpio to AIN + * + * stm32f need to have all there pins initialized to AIN so the consumption + * of the input Schmitt trigger is saved when running in STOP mode. + * + * @see https://comm.eefocus.com/media/download/index/id-1013834 + */ +static void _gpio_init_ain(void) +{ + uint32_t ahb_gpio_clocks; + + /* enable GPIO clock and save GPIO clock configuration */ + ahb_gpio_clocks = GPIO_CLK_ENR & GPIO_CLK_ENR_MASK; + periph_clk_en(GPIO_CLK, GPIO_CLK_ENR_MASK); + + /* switch all GPIOs to AIN mode to minimize power consumption */ + for (uint8_t i = 0; i < STM32_CPU_MAX_GPIOS; i++) { + GPIO_TypeDef *port; + port = (GPIO_TypeDef *)(GPIOA_BASE + i*(GPIOB_BASE - GPIOA_BASE)); + if (IS_GPIO_ALL_INSTANCE(port)) { + if (!DISABLE_JTAG) { +#if defined(CPU_FAM_STM32F1) + switch (i) { + /* preserve JTAG pins on PORTA and PORTB */ + case 0: + port->CR[0] = GPIO_CRL_CNF; + port->CR[1] = GPIO_CRH_CNF & 0x000FFFFF; + break; + case 1: + port->CR[0] = GPIO_CRL_CNF & 0xFFF00FFF; + port->CR[1] = GPIO_CRH_CNF; + break; + default: + port->CR[0] = GPIO_CRL_CNF; + port->CR[1] = GPIO_CRH_CNF; + break; + } +#else /* ! defined(CPU_FAM_STM32F1) */ + switch (i) { + /* preserve JTAG pins on PORTA and PORTB */ + case 0: + port->MODER = 0xABFFFFFF; + break; + case 1: + port->MODER = 0xFFFFFEBF; + break; + default: + port->MODER = 0xFFFFFFFF; + break; + } +#endif /* defined(CPU_FAM_STM32F1) */ + } + else { +#if defined(CPU_FAM_STM32F1) + port->CR[0] = GPIO_CRL_CNF; + port->CR[1] = GPIO_CRH_CNF; +#else + port->MODER = 0xFFFFFFFF; +#endif + } + } + } + + /* restore GPIO clocks */ + periph_clk_en(GPIO_CLK, ahb_gpio_clocks); +} +#endif + void cpu_init(void) { /* initialize the Cortex-M core */ @@ -49,6 +145,11 @@ void cpu_init(void) periph_clk_en(APB1, BIT_APB_PWREN); /* initialize the system clock as configured in the periph_conf.h */ stmclk_init_sysclk(); +#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32F1) || \ + defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F3) || \ + defined(CPU_FAM_STM32F4) || defined(CPU_FAM_STM32F7) + _gpio_init_ain(); +#endif #ifdef MODULE_PERIPH_DMA /* initialize DMA streams */ dma_init();