void stm32_rcc_enablelse(void) { uint32_t regval; /* The LSE is in the RTC domain and write access is denied to this domain * after reset, you have to enable write access using DBP bit in the PWR CR * register before to configuring the LSE. */ stm32_pwr_enablebkp(true); /* Enable the External Low-Speed (LSE) oscillator by setting the LSEON bit * the RCC BDCR register. */ regval = getreg32(STM32_RCC_BDCR); regval |= RCC_BDCR_LSEON; putreg32(regval,STM32_RCC_BDCR); /* Wait for the LSE clock to be ready */ while (((regval = getreg32(STM32_RCC_BDCR)) & RCC_BDCR_LSERDY) == 0); /* Disable backup domain access if it was disabled on entry */ stm32_pwr_enablebkp(false); }
void board_go_to_standby(void) { /* We cannot power-off display from interrrupt. */ if (!up_interrupt_context()) { sched_lock(); /* Power-off display. */ #ifdef CONFIG_THINGSEE_DISPLAY_MODULE board_lcdoff(); #endif } DEBUGASSERT((getreg32(STM32_PWR_CR) & PWR_CR_DBP) == 0); stm32_pwr_enablebkp(true); /* Setup bootloader to jump directly to firmware. */ putreg32(BOARD_FIRMWARE_BASE_ADDR, CONFIG_BOOTLOADER_ADDR_BKREG); /* Setup backup register for standby mode (checked after reset in boot-up * routine). */ putreg32(CONFIG_STANDBYMODE_MAGIC, CONFIG_STANDBYMODE_MAGIC_BKREG); stm32_pwr_enablebkp(false); lldbg("Driving MCU to standby mode (with wake-up by power-button)...\n"); up_mdelay(250); board_systemreset(); }
int board_shutdown() { stm32_pwr_enablebkp(true); /* XXX wow, this is evil - write a magic number into backup register zero */ *(uint32_t *)0x40002850 = 0xdeaddead; stm32_pwr_enablebkp(false); up_mdelay(50); up_systemreset(); while (1); return 0; }
void px4_systemreset(bool to_bootloader) { if (to_bootloader) { stm32_pwr_enablebkp(true); /* XXX wow, this is evil - write a magic number into backup register zero */ *(uint32_t *)0x40002850 = 0xb007b007; stm32_pwr_enablebkp(false); } up_systemreset(); /* lock up here */ while (true); }
void stm32_rcc_enablelse(void) { /* The LSE is in the RTC domain and write access is denied to this domain * after reset, you have to enable write access using DBP bit in the PWR CR * register before to configuring the LSE. */ stm32_pwr_enablebkp(true); #if defined(CONFIG_STM32_STM32L15XX) /* Enable the External Low-Speed (LSE) oscillator by setting the LSEON bit * the RCC CSR register. */ modifyreg32(STM32_RCC_CSR, 0, RCC_CSR_LSEON); /* Wait for the LSE clock to be ready */ while ((getreg32(STM32_RCC_CSR) & RCC_CSR_LSERDY) == 0) { up_waste(); } #else /* Enable the External Low-Speed (LSE) oscillator by setting the LSEON bit * the RCC BDCR register. */ modifyreg16(STM32_RCC_BDCR, 0, RCC_BDCR_LSEON); /* Wait for the LSE clock to be ready */ while ((getreg16(STM32_RCC_BDCR) & RCC_BDCR_LSERDY) == 0) { up_waste(); } #endif /* Disable backup domain access if it was disabled on entry */ stm32_pwr_enablebkp(false); }
static inline void rtc_wprlock(void) { /* Writing any wrong key re-activates the write protection. */ putreg32(0xff, STM32_RTC_WPR); /* Disable write access to the backup domain (RTC registers, RTC backup data * registers and backup SRAM). */ (void)stm32_pwr_enablebkp(false); }
static int board_button_irq(int irq, FAR void *context) { static struct timespec time_down; if (board_pwr_button_down()) { led_on(BOARD_LED_RED); clock_gettime(CLOCK_REALTIME, &time_down); } else { led_off(BOARD_LED_RED); struct timespec now; clock_gettime(CLOCK_REALTIME, &now); uint64_t tdown_ms = time_down.tv_sec * 1000 + time_down.tv_nsec / 1000000; uint64_t tnow_ms = now.tv_sec * 1000 + now.tv_nsec / 1000000; if (tdown_ms != 0 && (tnow_ms - tdown_ms) >= MS_PWR_BUTTON_DOWN) { led_on(BOARD_LED_BLUE); up_mdelay(200); stm32_pwr_enablebkp(true); /* XXX wow, this is evil - write a magic number into backup register zero */ *(uint32_t *)0x40002850 = 0xdeaddead; stm32_pwr_enablebkp(false); up_mdelay(50); up_systemreset(); while (1); } } return OK; }
void px4_systemreset(bool to_bootloader) { if (to_bootloader) { #ifndef CONFIG_ARCH_BOARD_SIM stm32_pwr_enablebkp(); #endif /* XXX wow, this is evil - write a magic number into backup register zero */ *(uint32_t *)0x40002850 = 0xb007b007; } up_systemreset(); /* lock up here */ while (true); }
void systemreset(bool to_bootloader) { #ifdef CONFIG_ARCH_CHIP_STM32 if (to_bootloader) { stm32_pwr_enablebkp(); /* XXX wow, this is evil - write a magic number into backup register zero */ *(uint32_t *)0x40002850 = 0xb007b007; } #endif up_systemreset(); /* lock up here */ while (true); }
static void rtc_wprunlock(void) { /* Enable write access to the backup domain (RTC registers, RTC backup data * registers and backup SRAM). */ (void)stm32_pwr_enablebkp(true); /* The following steps are required to unlock the write protection on all the * RTC registers (except for RTC_ISR[13:8], RTC_TAFCR, and RTC_BKPxR). * * 1. Write 0xCA into the RTC_WPR register. * 2. Write 0x53 into the RTC_WPR register. * * Writing a wrong key re-activates the write protection. */ putreg32(0xca, STM32_RTC_WPR); putreg32(0x53, STM32_RTC_WPR); }
void up_boot_standby_mode(void) { uint32_t gpio_off_mask; uint32_t regval; int i; DEBUGASSERT((getreg32(STM32_PWR_CR) & PWR_CR_DBP) != 0); /* * This function is called from up_boot.c, stm32_boardinitialize(). OS is not * running yet. Regulators and chip-selects have been initialized. IWDG not * enabled. If board has HWWDG, we must enable it from this function before * going to standby mode. */ regval = getreg32(CONFIG_STANDBYMODE_MAGIC_BKREG); if (regval != CONFIG_STANDBYMODE_MAGIC) { g_board_wakeup_from_standby = (regval == CONFIG_STANDBYMODE_MAGIC + 1); /* Standby mode was not requested, continue with regular boot. */ putreg32(0, CONFIG_STANDBYMODE_MAGIC_BKREG); for (i = 0; i < 4; i++) up_lowputc('r'); return; } #if defined(CONFIG_STM32_DFU) || defined (CONFIG_BOARD_HALTIAN_HWWDG) up_irqinitialize(); #endif /* Go into standby mode. */ putreg32(CONFIG_STANDBYMODE_MAGIC + 1, CONFIG_STANDBYMODE_MAGIC_BKREG); for (i = 0; i < 4; i++) up_lowputc('s'); /* Setup bootloader to jump directly to firmware. */ putreg32(BOARD_FIRMWARE_BASE_ADDR, CONFIG_BOOTLOADER_ADDR_BKREG); /* Now disable backup register access. If following interrupt handlers * access backup registers, they need to make sure to re-enable access. */ stm32_pwr_enablebkp(false); while (true) { /* Configure SDcard pins. */ gpio_initialize_sdcard_pins(); /* Configure display GPIOs. */ gpio_off_mask = ~(GPIO_PUPD_MASK | GPIO_MODE_MASK | GPIO_OUTPUT_SET); stm32_configgpio(GPIO_CHIP_SELECT_DISPLAY); stm32_configgpio(GPIO_LCD_SSD1309_CMDDATA); stm32_configgpio(GPIO_LCD_SSD1309_RESET); stm32_configgpio((GPIO_SPI2_MOSI & gpio_off_mask) | GPIO_OUTPUT_CLEAR | GPIO_OUTPUT); stm32_configgpio((GPIO_SPI2_SCK & gpio_off_mask) | GPIO_OUTPUT_CLEAR | GPIO_OUTPUT); /* Reconfigure GPIO's for stop mode (most pins are setup as analog input). */ up_reconfigure_gpios_for_pmstop(); /* We must kick HWWDG even from standby mode, else it resets device. */ board_wdginitialize_autokick(hwwdg_irq_in_standby); /* Setup 'power'-button as EXTI for wake-up. */ stm32_configgpio(GPIO_BTN_POWERKEY); stm32_gpiosetevent(GPIO_BTN_POWERKEY, true, false, true, button_pressed_down_handler); /* Our standby-mode is really ARM core's stop-mode. Enter stop-mode with MCU internal regulator in low-power mode. */ (void)stm32_pmstop(true); standby_do_trace('p'); } }
void stm32_boardinitialize(void) { #ifdef BOARD_HAS_BOOTLOADER /* Check if IWDG is enabled by bootloader. This is the case when * CONFIG_BOOTLOADER_NOWD_BKREG has lowest bit cleared. */ if ((getreg32(CONFIG_BOOTLOADER_NOWD_BKREG) & 1) == 0) { int i; /* Bootloader has enabled IWDG. This happens after POR-reset (since * backup-registers have been reset to zero) and after firmware update. * * Disabling IWDG is used as early boot firmware check (new firmware * started). We now enable NOWD flag and do reset loop with ADDR value * set to application firmware. * * If firmware does not manage to do early boot and gets stuck, IWDG will * reset device and bootloader will either attempt to flash backup * firmware or will reset loop by IWDG until 'current boot try count' * reaches threshold and bootloader boots device to DFU-mode. */ for (i = 0; i < 4; i++) up_lowputc('>'); /* Enable BKREG writing. */ stm32_pwr_enablebkp(true); /* Make bootloader disable IWDG. */ putreg32(1, CONFIG_BOOTLOADER_NOWD_BKREG); /* Setup bootloader to jump directly to firmware. */ putreg32(BOARD_FIRMWARE_BASE_ADDR, CONFIG_BOOTLOADER_ADDR_BKREG); /* Disable BKREG writing. */ stm32_pwr_enablebkp(false); /* Do system reset. */ board_systemreset(); } #endif /* BOARD_HAS_BOOTLOADER */ #if defined(CONFIG_ASSERT_COUNT_BKREG) /* Check value of assert counter (note: does not enable/disable BKREG access * with argument==0). */ if (up_add_assert_count(0) >= CONFIG_ASSERT_COUNT_TO_DFU_MODE) { const char *str = "\nToo many ASSERT resets; something wrong with software. Forcing DFU mode!\n"; while (*str) up_lowputc(*str++); up_mdelay(500); up_reset_to_system_bootloader(); } #endif /* Setup GPIOs based on HW version. */ up_configure_dynamic_gpios(); /* Configure MCU so that debugging is possible in idle modes. */ #ifdef CONFIG_STM32_KEEP_CORE_CLOCK_ENABLED_IN_IDLE_MODES uint32_t cr = getreg32(STM32_DBGMCU_CR); cr |= DBGMCU_CR_STANDBY | DBGMCU_CR_STOP | DBGMCU_CR_SLEEP; putreg32(cr, STM32_DBGMCU_CR); #endif #ifdef CONFIG_BOARD_MCO_SYSCLK /* Output SYSCLK to MCO pin for clock measurements. */ stm32_configgpio(GPIO_MCO); stm32_mcodivconfig(RCC_CFGR_MCOSEL_SYSCLK, RCC_CFGR_MCOPRE_DIV4); #endif /* Configure on-board LEDs if LED support has been selected. */ #ifdef CONFIG_ARCH_LEDS board_led_initialize(); #endif /* Configure chip-select pins. */ board_initialize_chipselects(); /* Configure SDcard pins (needs to be after chip-select init, to pull SDcard * CS down). */ gpio_initialize_sdcard_pins(); /* Configure power control pins. */ board_initialize_pwrctl_pins(); /* Initialize modem gpios. */ up_modem_initialize_gpios(); /* Initialize unused gpio pads. */ gpio_initialize_unused_pads(); /* Enable BKREG writing. */ stm32_pwr_enablebkp(true); /* Reset 'current boot try count' for bootloader. */ putreg32(0, CONFIG_BOOTLOADER_CBTC_BKREG); /* Make bootloader disable IWDG. */ putreg32(1, CONFIG_BOOTLOADER_NOWD_BKREG); /* Check if we need to enter standby/power-off mode. */ up_boot_standby_mode(); /* Disable BKREG writing. */ stm32_pwr_enablebkp(false); /* Force enable capsense and 9-axis for duration * of I2C initialization. After bus initialization * is done, this is undone and drivers will take care * of requesting power for themselves. */ board_pwrctl_get(PWRCTL_SWITCH_CAPSENSE_SENSOR); board_pwrctl_get(PWRCTL_SWITCH_9AXIS_INERTIAL_SENSOR); /* Flash mass-erase can leave option-bytes is bad shape, restore defaults if * needed. */ up_check_and_restore_valid_optionbytes(); /* Configure SPI chip selects if 1) SPI is not disabled, and 2) the weak function * stm32_spiinitialize() has been brought into the link. */ #if defined(CONFIG_STM32_SPI1) || defined(CONFIG_STM32_SPI2) || defined(CONFIG_STM32_SPI3) if (stm32_spiinitialize) { stm32_spiinitialize(); } #endif /* Give early information about reset reason. */ print_reset_reason(); }
static void stm32_stdclockconfig(void) { uint32_t regval; volatile int32_t timeout; #ifdef STM32_BOARD_USEHSI /* Enable Internal High-Speed Clock (HSI) */ regval = getreg32(STM32_RCC_CR); regval |= RCC_CR_HSION; /* Enable HSI */ putreg32(regval, STM32_RCC_CR); /* Wait until the HSI is ready (or until a timeout elapsed) */ for (timeout = HSIRDY_TIMEOUT; timeout > 0; timeout--) { /* Check if the HSIRDY flag is the set in the CR */ if ((getreg32(STM32_RCC_CR) & RCC_CR_HSIRDY) != 0) { /* If so, then break-out with timeout > 0 */ break; } } #endif #ifdef STM32_BOARD_USEHSE /* Enable External High-Speed Clock (HSE) */ regval = getreg32(STM32_RCC_CR); regval |= RCC_CR_HSEON; /* Enable HSE */ putreg32(regval, STM32_RCC_CR); /* Wait until the HSE is ready (or until a timeout elapsed) */ for (timeout = HSERDY_TIMEOUT; timeout > 0; timeout--) { /* Check if the HSERDY flag is the set in the CR */ if ((getreg32(STM32_RCC_CR) & RCC_CR_HSERDY) != 0) { /* If so, then break-out with timeout > 0 */ break; } } #endif #ifdef STM32_BOARD_USEMSI /* Enable MSI clock */ regval = getreg32(STM32_RCC_CR); regval |= STM32_BOARD_MSIRANGE; regval |= RCC_CR_MSIRGSEL; /* Select new MSIRANGE */ putreg32(regval, STM32_RCC_CR); /* Wait until the MSI is ready (or until a timeout elapsed) */ for (timeout = MSIRDY_TIMEOUT; timeout > 0; timeout--) { /* Check if the MSIRDY flag is the set in the CR */ if ((getreg32(STM32_RCC_CR) & RCC_CR_MSIRDY) != 0) { /* If so, then break-out with timeout > 0 */ break; } } #endif /* Check for a timeout. If this timeout occurs, then we are hosed. We * have no real back-up plan, although the following logic makes it look * as though we do. */ if (timeout > 0) { /* Select regulator voltage output Scale 1 mode to support system * frequencies up to 80 MHz. */ regval = getreg32(STM32_RCC_APB1ENR1); regval |= RCC_APB1ENR1_PWREN; putreg32(regval, STM32_RCC_APB1ENR1); regval = getreg32(STM32_PWR_CR1); regval &= ~PWR_CR1_VOS_MASK; regval |= PWR_CR1_VOS_RANGE1; putreg32(regval, STM32_PWR_CR1); /* Set the HCLK source/divider */ regval = getreg32(STM32_RCC_CFGR); regval &= ~RCC_CFGR_HPRE_MASK; regval |= STM32_RCC_CFGR_HPRE; putreg32(regval, STM32_RCC_CFGR); /* Set the PCLK2 divider */ regval = getreg32(STM32_RCC_CFGR); regval &= ~RCC_CFGR_PPRE2_MASK; regval |= STM32_RCC_CFGR_PPRE2; putreg32(regval, STM32_RCC_CFGR); /* Set the PCLK1 divider */ regval = getreg32(STM32_RCC_CFGR); regval &= ~RCC_CFGR_PPRE1_MASK; regval |= STM32_RCC_CFGR_PPRE1; putreg32(regval, STM32_RCC_CFGR); /* Set the PLL dividers and multiplers to configure the main PLL */ regval = (STM32_PLLCFG_PLLM | STM32_PLLCFG_PLLN | STM32_PLLCFG_PLLP | STM32_PLLCFG_PLLSRC | STM32_PLLCFG_PLLQ | STM32_PLLCFG_PLLR); #ifdef STM32_PLLCFG_PLLP_EN regval |= RCC_PLLCFG_PLLPEN; #endif #ifdef STM32_PLLCFG_PLLQ_EN regval |= RCC_PLLCFG_PLLQEN; #endif #ifdef STM32_PLLCFG_PLLR_EN regval |= RCC_PLLCFG_PLLREN; #endif putreg32(regval, STM32_RCC_PLLCFG); /* Enable the main PLL */ regval = getreg32(STM32_RCC_CR); regval |= RCC_CR_PLLON; putreg32(regval, STM32_RCC_CR); /* Wait until the PLL is ready */ while ((getreg32(STM32_RCC_CR) & RCC_CR_PLLRDY) == 0) { } #ifdef STM32_BOARD_USE_PLLSAI1 /* Set the PLL dividers and multipliers to configure the SAI1 PLL */ regval = (STM32_PLLSAI1CFG_PLLN | STM32_PLLSAI1CFG_PLLP | STM32_PLLSAI1CFG_PLLQ | STM32_PLLSAI1CFG_PLLR); #ifdef STM32_PLLSAI1CFG_PLLP_EN regval |= RCC_PLLSAI1CFG_PLLPEN; #endif #ifdef STM32_PLLSAI1CFG_PLLQ_EN regval |= RCC_PLLSAI1CFG_PLLQEN; #endif #ifdef STM32_PLLSAI1CFG_PLLR_EN regval |= RCC_PLLSAI1CFG_PLLREN; #endif putreg32(regval, STM32_RCC_PLLSAI1CFGR); /* Enable the SAI1 PLL */ regval = getreg32(STM32_RCC_CR); regval |= RCC_CR_PLLSAI1ON; putreg32(regval, STM32_RCC_CR); /* Wait until the PLL is ready */ while ((getreg32(STM32_RCC_CR) & RCC_CR_PLLSAI1RDY) == 0) { } #endif #ifdef STM32_BOARD_USE_PLLSAI2 /* Set the PLL dividers and multipliers to configure the SAI2 PLL */ regval = (STM32_PLLSAI2CFG_PLLN | STM32_PLLSAI2CFG_PLLP | STM32_PLLSAI2CFG_PLLQ | STM32_PLLSAI2CFG_PLLR); #ifdef STM32_PLLSAI2CFG_PLLP_EN regval |= RCC_PLLSAI2CFG_PLLPEN; #endif #ifdef STM32_PLLSAI2CFG_PLLQ_EN regval |= RCC_PLLSAI2CFG_PLLQEN; #endif #ifdef STM32_PLLSAI2CFG_PLLR_EN regval |= RCC_PLLSAI2CFG_PLLREN; #endif putreg32(regval, STM32_RCC_PLLSAI2CFGR); /* Enable the SAI2 PLL */ regval = getreg32(STM32_RCC_CR); regval |= RCC_CR_PLLSAI2ON; putreg32(regval, STM32_RCC_CR); /* Wait until the PLL is ready */ while ((getreg32(STM32_RCC_CR) & RCC_CR_PLLSAI2RDY) == 0) { } #endif /* Enable FLASH prefetch, instruction cache, data cache, and 4 wait states */ #ifdef CONFIG_STM32_FLASH_PREFETCH regval = (FLASH_ACR_LATENCY_4 | FLASH_ACR_ICEN | FLASH_ACR_DCEN | FLASH_ACR_PRFTEN); #else regval = (FLASH_ACR_LATENCY_4 | FLASH_ACR_ICEN | FLASH_ACR_DCEN); #endif putreg32(regval, STM32_FLASH_ACR); /* Select the main PLL as system clock source */ regval = getreg32(STM32_RCC_CFGR); regval &= ~RCC_CFGR_SW_MASK; regval |= RCC_CFGR_SW_PLL; putreg32(regval, STM32_RCC_CFGR); /* Wait until the PLL source is used as the system clock source */ while ((getreg32(STM32_RCC_CFGR) & RCC_CFGR_SWS_MASK) != RCC_CFGR_SWS_PLL) { } #ifdef STM32_BOARD_USELSE /* Enable low speed external (LSE) clock source */ stm32_pwr_enablebkp(); stm32_rcc_enablelse(); # ifdef STM32_BOARD_USEMSI /* Now that LSE is up, auto trim the MSI */ regval = getreg32(STM32_RCC_CR); regval |= RCC_CR_MSIPLLEN; putreg32(regval, STM32_RCC_CR); # endif #endif } }