void __start(void) { const uint32_t *src; uint32_t *dest; /* Configure the uart so that we can get debug output as soon as possible */ stm32_clockconfig(); stm32_fpuconfig(); stm32_lowsetup(); stm32_gpioinit(); showprogress('A'); /* Clear .bss. We'll do this inline (vs. calling memset) just to be * certain that there are no issues with the state of global variables. */ for (dest = &_sbss; dest < &_ebss; ) { *dest++ = 0; } showprogress('B'); /* Move the intialized data section from his temporary holding spot in * FLASH into the correct place in SRAM. The correct place in SRAM is * give by _sdata and _edata. The temporary location is in FLASH at the * end of all of the other read-only data (.text, .rodata) at _eronly. */ for (src = &_eronly, dest = &_sdata; dest < &_edata; ) { *dest++ = *src++; } showprogress('C'); /* Perform early serial initialization */ #ifdef USE_EARLYSERIALINIT up_earlyserialinit(); #endif showprogress('D'); /* Initialize onboard resources */ stm32_boardinitialize(); showprogress('E'); /* Then start NuttX */ showprogress('\r'); showprogress('\n'); os_start(); /* Shoulnd't get here */ for(;;); }
static void standby_do_trace(char ch) { int i; /* Stop mode disables HSE/HSI/PLL and wake happens with default system * clock (MSI, 2Mhz). Reconfigure clocks to enable USART2. */ stm32_clockconfig(); /* Stop mode exit traces. */ for (i = 0; i < 4; i++) up_lowputc(ch); }
void board_deepsleep_with_stopmode(uint32_t secs) { #if defined(CONFIG_RTC) && defined(CONFIG_RTC_DATETIME) struct tm t; struct timespec ts; struct timespec rtc_start_ts; struct timespec rtc_end_ts; #endif #ifdef CONFIG_BOARD_DEEPSLEEP_RECONFIGURE_GPIOS uint32_t gpio_off_mask; bool sdcard_enabled; #endif uint32_t regval; int ret; #ifdef DEEPSLEEP_WAKETIME_DEBUG static struct timespec wake_ts; #endif #ifdef DEEPSLEEP_SLEEPTIME_DEBUG bool slept = false; #endif /* Do not allow other tasks to takeover (for example, by wake-up with semaphore * from EXTI interrupt) before we have restored MCU functionalities. */ sched_lock(); #ifdef DEEPSLEEP_SLEEPTIME_DEBUG lldbg("sleep for %d\n", secs); #endif #ifdef CONFIG_BOARD_DEEPSLEEP_RECONFIGURE_GPIOS /* Special support for SDcard. */ if (stm32_gpioread(GPIO_CHIP_SELECT_SDCARD) == false) { lldbg("ERROR! SDcard communication active while trying deep-sleep!\n"); goto skip_deepsleep; } /* Following devices do not have proper GPIO reconfigure recovery yet (and * some cannot work with deep-sleep at all). Abort deep-sleep instead of * introducing hard-to-diagnose bugs and general instability. */ if (stm32_gpioread(GPIO_REGULATOR_WLAN)) { lldbg("ERROR! Trying to deep-sleep when WLAN active!\n"); goto skip_deepsleep; } if (stm32_gpioread(GPIO_PWR_SWITCH_MODEM)) { lldbg("ERROR! Trying to deep-sleep when Modem active!\n"); goto skip_deepsleep; } if (stm32_gpioread(GPIO_REGULATOR_GPS)) { lldbg("ERROR! Trying to deep-sleep when GPS active!\n"); goto skip_deepsleep; } if (stm32_gpioread(GPIO_REGULATOR_BLUETOOTH)) { lldbg("ERROR! Trying to deep-sleep when Bluetooth active!\n"); goto skip_deepsleep; } if (stm32_gpioread(GPIO_REGULATOR_DISPLAY)) { lldbg("ERROR! Trying to deep-sleep when Display active!\n"); goto skip_deepsleep; } #endif /* CONFIG_BOARD_DEEPSLEEP_RECONFIGURE_GPIOS */ #if defined(CONFIG_RTC) && defined(CONFIG_RTC_DATETIME) /* Get RTC clock before STOP. */ stm32_rtc_getdatetime_with_subseconds(&t, &rtc_start_ts.tv_nsec); rtc_start_ts.tv_sec = mktime(&t); /* Get current time. */ ret = clock_gettime(CLOCK_REALTIME, &ts); DEBUGASSERT(ret != ERROR); /* Add nanoseconds to entropy pool. */ add_time_randomness(ts.tv_nsec); #endif #ifdef DEEPSLEEP_WAKETIME_DEBUG if (wake_ts.tv_nsec || wake_ts.tv_sec) { struct timespec curr_ts; int64_t msecs; clock_gettime(CLOCK_REALTIME, &curr_ts); msecs = ((int64_t)curr_ts.tv_sec - wake_ts.tv_sec) * 1000; msecs += ((int64_t)curr_ts.tv_nsec - wake_ts.tv_nsec) / (1000 * 1000); lldbg("sleep to sleep time: %d msecs\n", (int)msecs); } else { lldbg("first sleep (for %u secs)\n", secs); } #endif #ifdef CONFIG_RTC_PERIODIC_AUTORELOAD_WAKEUP if (secs > 0) { /* Prepare RTC for wake-up. */ ret = up_rtc_setperiodicwakeup(secs, NULL); DEBUGASSERT(ret == OK); } #else DEBUGASSERT(secs == 0); #endif /* Prevent USART interrupt activity, make sure that last transmission has * completed. */ stm32_serial_set_suspend(true); #ifdef CONFIG_BOARD_DEEPSLEEP_RECONFIGURE_GPIOS /* Read control state of SDCard regulator (TODO: add proper pwrctl api) */ sdcard_enabled = stm32_gpioread(GPIO_REGULATOR_SDCARD); if (sdcard_enabled) { /* Mark SDcard as disconnected for block driver. */ mmcsd_slot_pm_suspend(CONFIG_BOARD_MMCSDSLOTNO); } /* Force SDcard off. */ stm32_gpiowrite(GPIO_REGULATOR_SDCARD, false); /* SDcard is off, and does not react on GPIOs. Force GPIOs low to avoid leak * current. */ gpio_off_mask = ~(GPIO_PUPD_MASK | GPIO_MODE_MASK | GPIO_OUTPUT_SET); stm32_configgpio((GPIO_SPI3_MOSI & gpio_off_mask) | GPIO_OUTPUT_CLEAR | GPIO_OUTPUT); stm32_configgpio((GPIO_SPI3_MISO & gpio_off_mask) | GPIO_OUTPUT_CLEAR | GPIO_OUTPUT); stm32_configgpio((GPIO_SPI3_SCK & gpio_off_mask) | GPIO_OUTPUT_CLEAR | GPIO_OUTPUT); stm32_configgpio((GPIO_CHIP_SELECT_SDCARD & 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(); #endif #if defined(CONFIG_USBDEV) && defined (CONFIG_STM32_USB) /* Reset USB peripheral */ regval = getreg32(STM32_RCC_APB1RSTR); putreg32(regval | RCC_APB1RSTR_USBRST, STM32_RCC_APB1RSTR); putreg32(regval, STM32_RCC_APB1RSTR); #endif #if defined(CONFIG_STM32_PWR) /* Disable PVD during sleep because I_DD (PVD/BOR) consumes 2.6 uA, and because there is nothing better to do than die while sleeping if lose power in stop-mode. */ stm32_pwr_disablepvd(); #endif #ifndef CONFIG_BOARD_DEEPSLEEP_SKIP_PMSTOP /* Enter stop-mode with MCU internal regulator in low-power mode. */ ret = stm32_pmstop(true); #endif #ifdef DEEPSLEEP_SLEEPTIME_DEBUG slept = true; #endif #if defined(CONFIG_STM32_PWR) /* Re-enable PVD and check if voltage has dropped too much while we slept. We might have enough power for MCU, but not for SD card or other peripherals. */ stm32_pwr_enablepvd(); board_pwr_checkpvd(); #endif #ifdef CONFIG_RTC_PERIODIC_AUTORELOAD_WAKEUP if (secs > 0) { /* Prevent more wake-ups. */ (void)up_rtc_cancelperiodicwakeup(); } #endif #if defined(CONFIG_RTC) && defined(CONFIG_RTC_DATETIME) /* Get RTC clock after STOP. */ stm32_rtc_getdatetime_with_subseconds(&t, &rtc_end_ts.tv_nsec); rtc_end_ts.tv_sec = mktime(&t); /* Advance time by RTC. */ ts.tv_sec += rtc_end_ts.tv_sec - rtc_start_ts.tv_sec; ts.tv_nsec += rtc_end_ts.tv_nsec - rtc_start_ts.tv_nsec; if (ts.tv_nsec < 0) { ts.tv_nsec += 1000 * 1000 * 1000; ts.tv_sec--; } if (ts.tv_nsec >= 1000 * 1000 * 1000) { ts.tv_nsec -= 1000 * 1000 * 1000; ts.tv_sec++; } /* Set current time / date */ ret = clock_settime(CLOCK_REALTIME, &ts); DEBUGASSERT(ret != ERROR); #ifdef DEEPSLEEP_WAKETIME_DEBUG wake_ts = ts; #endif #if defined(CONFIG_CLOCK_MONOTONIC) && defined(CONFIG_CLOCK_MONOTONIC_OFFSET_TIME) /* Get amount of time adjusted by RTC. */ ts.tv_sec = rtc_end_ts.tv_sec - rtc_start_ts.tv_sec; ts.tv_nsec = rtc_end_ts.tv_nsec - rtc_start_ts.tv_nsec; if (ts.tv_nsec < 0) { ts.tv_nsec += 1000 * 1000 * 1000; ts.tv_sec--; } if (ts.tv_nsec >= 1000 * 1000 * 1000) { ts.tv_nsec -= 1000 * 1000 * 1000; ts.tv_sec++; } /* Adjust CLOCK_MONOTONIC offset. */ clock_increase_monotonic_offset(&ts); #endif #endif /* Stop mode disables HSE/HSI/PLL and wake happens with default system * clock (MSI, 2Mhz). So reconfigure clocks early on. RTC is however * handled before this for accurate time keeping. */ stm32_clockconfig(); #ifdef CONFIG_BOARD_DEEPSLEEP_RECONFIGURE_GPIOS /* Restore pin configuration */ up_restore_gpios_after_pmstop(); #endif #if defined(CONFIG_USBDEV) && defined (CONFIG_STM32_USB) /* Initialize USB */ /* TODO initialize USB properly, up_usbinitialize() call alone is not sufficient */ up_usbinitialize(); #endif /* Resume serial ports after setting up system clock, as USART baud rate is * configured relative to system clock. */ stm32_serial_set_suspend(false); /* Check that we have enough battery left, just in case PVD detection missed it. */ board_pwr_checkvbat(false); #ifdef CONFIG_BOARD_DEEPSLEEP_RECONFIGURE_GPIOS /* Special support for SD card. */ /* Restore SDcard GPIOs */ stm32_configgpio(GPIO_SPI3_MOSI); stm32_configgpio(GPIO_SPI3_MISO); stm32_configgpio(GPIO_SPI3_SCK); stm32_configgpio(GPIO_CHIP_SELECT_SDCARD); if (sdcard_enabled) { /* Re-enable power now that GPIOs are in correct state. */ stm32_gpiowrite(GPIO_REGULATOR_SDCARD, true); /* Mark SDcard as reconnected for block driver, will reinitialize/reconfigure * SDcard. Apparently, block driver works fine without additional delay * for regulator. Might be because plug-in nature of SDcards require * block driver to keep retrying initialization until card stabilizes. */ mmcsd_slot_pm_resume(CONFIG_BOARD_MMCSDSLOTNO); } skip_deepsleep: #endif /* Allow scheduler to switch tasks. */ sched_unlock(); #ifdef DEEPSLEEP_SLEEPTIME_DEBUG if (slept) { /* Get amount of time adjusted by RTC. */ ts.tv_sec = rtc_end_ts.tv_sec - rtc_start_ts.tv_sec; ts.tv_nsec = rtc_end_ts.tv_nsec - rtc_start_ts.tv_nsec; if (ts.tv_nsec < 0) { ts.tv_nsec += 1000 * 1000 * 1000; ts.tv_sec--; } if (ts.tv_nsec >= 1000 * 1000 * 1000) { ts.tv_nsec -= 1000 * 1000 * 1000; ts.tv_sec++; } lldbg("slept for %u.%03u\n", ts.tv_sec, ts.tv_nsec / (1000 * 1000)); } #endif }