[FL-3226] Deep Sleep Idle (#2569)
* Improve RNG error handling * Sync RTC shadow registers on Stop mode exit * Implement working STOP2 mode * Fix formatting * FuriHal: disable SWD pins if debug is disabled * Power: cleanup battery info view, handle zero current report from gauge * Fbt: add command line argument for extra global defines * FuriHal: cleanup debug defines in power and os, drop deep_insomnia counter. * Add a setting to disable deep sleep * Clean up furi_hal_power * FuriHal,FapLoader,Debug: implement debug in stop mode, workaround resume in stop * FuriHal: document OS and power subsystems debugging * Furi: enable debug interface on crash --------- Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
		| @@ -1,5 +1,5 @@ | ||||
| entry,status,name,type,params | ||||
| Version,+,21.0,, | ||||
| Version,+,22.0,, | ||||
| Header,+,applications/services/bt/bt_service/bt.h,, | ||||
| Header,+,applications/services/cli/cli.h,, | ||||
| Header,+,applications/services/cli/cli_vcp.h,, | ||||
| @@ -901,6 +901,7 @@ Function,+,furi_hal_crypto_verify_enclave,_Bool,"uint8_t*, uint8_t*" | ||||
| Function,+,furi_hal_crypto_verify_key,_Bool,uint8_t | ||||
| Function,+,furi_hal_debug_disable,void, | ||||
| Function,+,furi_hal_debug_enable,void, | ||||
| Function,+,furi_hal_debug_is_gdb_session_active,_Bool, | ||||
| Function,-,furi_hal_deinit_early,void, | ||||
| Function,-,furi_hal_flash_erase,void,uint8_t | ||||
| Function,-,furi_hal_flash_get_base,size_t, | ||||
| @@ -983,7 +984,6 @@ Function,-,furi_hal_os_init,void, | ||||
| Function,+,furi_hal_os_tick,void, | ||||
| Function,+,furi_hal_power_check_otg_status,void, | ||||
| Function,+,furi_hal_power_debug_get,void,"PropertyValueCallback, void*" | ||||
| Function,+,furi_hal_power_deep_sleep_available,_Bool, | ||||
| Function,+,furi_hal_power_disable_external_3_3v,void, | ||||
| Function,+,furi_hal_power_disable_otg,void, | ||||
| Function,+,furi_hal_power_enable_external_3_3v,void, | ||||
| @@ -1059,6 +1059,7 @@ Function,+,furi_hal_rtc_set_locale_units,void,FuriHalRtcLocaleUnits | ||||
| Function,+,furi_hal_rtc_set_log_level,void,uint8_t | ||||
| Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t | ||||
| Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t" | ||||
| Function,+,furi_hal_rtc_sync_shadow,void, | ||||
| Function,+,furi_hal_rtc_validate_datetime,_Bool,FuriHalRtcDateTime* | ||||
| Function,+,furi_hal_speaker_acquire,_Bool,uint32_t | ||||
| Function,-,furi_hal_speaker_deinit,void, | ||||
| @@ -2149,6 +2150,8 @@ Variable,+,gpio_ext_pd0,const GpioPin, | ||||
| Variable,+,gpio_ext_pe4,const GpioPin, | ||||
| Variable,+,gpio_i2c_power_scl,const GpioPin, | ||||
| Variable,+,gpio_i2c_power_sda,const GpioPin, | ||||
| Variable,+,gpio_ibutton,const GpioPin, | ||||
| Variable,+,gpio_periph_power,const GpioPin, | ||||
| Variable,+,gpio_pins,const GpioPinRecord[], | ||||
| Variable,+,gpio_pins_count,const size_t, | ||||
| Variable,+,gpio_sdcard_cd,const GpioPin, | ||||
| @@ -2157,11 +2160,13 @@ Variable,+,gpio_speaker,const GpioPin, | ||||
| Variable,+,gpio_spi_d_miso,const GpioPin, | ||||
| Variable,+,gpio_spi_d_mosi,const GpioPin, | ||||
| Variable,+,gpio_spi_d_sck,const GpioPin, | ||||
| Variable,+,gpio_swclk,const GpioPin, | ||||
| Variable,+,gpio_swdio,const GpioPin, | ||||
| Variable,+,gpio_usart_rx,const GpioPin, | ||||
| Variable,+,gpio_usart_tx,const GpioPin, | ||||
| Variable,+,gpio_usb_dm,const GpioPin, | ||||
| Variable,+,gpio_usb_dp,const GpioPin, | ||||
| Variable,+,gpio_ibutton,const GpioPin, | ||||
| Variable,+,gpio_vibro,const GpioPin, | ||||
| Variable,+,input_pins,const InputPin[], | ||||
| Variable,+,input_pins_count,const size_t, | ||||
| Variable,+,message_blink_set_color_blue,const NotificationMessage, | ||||
| @@ -2309,7 +2314,6 @@ Variable,+,message_red_255,const NotificationMessage, | ||||
| Variable,+,message_sound_off,const NotificationMessage, | ||||
| Variable,+,message_vibro_off,const NotificationMessage, | ||||
| Variable,+,message_vibro_on,const NotificationMessage, | ||||
| Variable,+,gpio_periph_power,const GpioPin, | ||||
| Variable,+,sequence_audiovisual_alert,const NotificationSequence, | ||||
| Variable,+,sequence_blink_blue_10,const NotificationSequence, | ||||
| Variable,+,sequence_blink_blue_100,const NotificationSequence, | ||||
| @@ -2364,4 +2368,3 @@ Variable,+,usb_cdc_single,FuriHalUsbInterface, | ||||
| Variable,+,usb_hid,FuriHalUsbInterface, | ||||
| Variable,+,usb_hid_u2f,FuriHalUsbInterface, | ||||
| Variable,+,usbd_devfs,const usbd_driver, | ||||
| Variable,+,gpio_vibro,const GpioPin, | ||||
|   | ||||
| 
 | 
| @@ -6,6 +6,9 @@ | ||||
|  | ||||
| #define TAG "FuriHalResources" | ||||
|  | ||||
| const GpioPin gpio_swdio = {.port = GPIOA, .pin = LL_GPIO_PIN_13}; | ||||
| const GpioPin gpio_swclk = {.port = GPIOA, .pin = LL_GPIO_PIN_14}; | ||||
|  | ||||
| const GpioPin gpio_vibro = {.port = GPIOA, .pin = LL_GPIO_PIN_8}; | ||||
| const GpioPin gpio_ibutton = {.port = GPIOB, .pin = LL_GPIO_PIN_14}; | ||||
|  | ||||
|   | ||||
| @@ -50,6 +50,9 @@ extern const size_t input_pins_count; | ||||
| extern const GpioPinRecord gpio_pins[]; | ||||
| extern const size_t gpio_pins_count; | ||||
|  | ||||
| extern const GpioPin gpio_swdio; | ||||
| extern const GpioPin gpio_swclk; | ||||
|  | ||||
| extern const GpioPin gpio_vibro; | ||||
| extern const GpioPin gpio_ibutton; | ||||
|  | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| entry,status,name,type,params | ||||
| Version,+,21.0,, | ||||
| Version,+,22.0,, | ||||
| Header,+,applications/services/bt/bt_service/bt.h,, | ||||
| Header,+,applications/services/cli/cli.h,, | ||||
| Header,+,applications/services/cli/cli_vcp.h,, | ||||
| @@ -1082,6 +1082,7 @@ Function,+,furi_hal_crypto_verify_enclave,_Bool,"uint8_t*, uint8_t*" | ||||
| Function,+,furi_hal_crypto_verify_key,_Bool,uint8_t | ||||
| Function,+,furi_hal_debug_disable,void, | ||||
| Function,+,furi_hal_debug_enable,void, | ||||
| Function,+,furi_hal_debug_is_gdb_session_active,_Bool, | ||||
| Function,-,furi_hal_deinit_early,void, | ||||
| Function,-,furi_hal_flash_erase,void,uint8_t | ||||
| Function,-,furi_hal_flash_get_base,size_t, | ||||
| @@ -1212,7 +1213,6 @@ Function,-,furi_hal_os_init,void, | ||||
| Function,+,furi_hal_os_tick,void, | ||||
| Function,+,furi_hal_power_check_otg_status,void, | ||||
| Function,+,furi_hal_power_debug_get,void,"PropertyValueCallback, void*" | ||||
| Function,+,furi_hal_power_deep_sleep_available,_Bool, | ||||
| Function,+,furi_hal_power_disable_external_3_3v,void, | ||||
| Function,+,furi_hal_power_disable_otg,void, | ||||
| Function,+,furi_hal_power_enable_external_3_3v,void, | ||||
| @@ -1313,6 +1313,7 @@ Function,+,furi_hal_rtc_set_locale_units,void,FuriHalRtcLocaleUnits | ||||
| Function,+,furi_hal_rtc_set_log_level,void,uint8_t | ||||
| Function,+,furi_hal_rtc_set_pin_fails,void,uint32_t | ||||
| Function,+,furi_hal_rtc_set_register,void,"FuriHalRtcRegister, uint32_t" | ||||
| Function,+,furi_hal_rtc_sync_shadow,void, | ||||
| Function,+,furi_hal_rtc_validate_datetime,_Bool,FuriHalRtcDateTime* | ||||
| Function,+,furi_hal_speaker_acquire,_Bool,uint32_t | ||||
| Function,-,furi_hal_speaker_deinit,void, | ||||
| @@ -3076,10 +3077,12 @@ Variable,+,gpio_ext_pc1,const GpioPin, | ||||
| Variable,+,gpio_ext_pc3,const GpioPin, | ||||
| Variable,+,gpio_i2c_power_scl,const GpioPin, | ||||
| Variable,+,gpio_i2c_power_sda,const GpioPin, | ||||
| Variable,+,gpio_ibutton,const GpioPin, | ||||
| Variable,+,gpio_infrared_rx,const GpioPin, | ||||
| Variable,+,gpio_infrared_tx,const GpioPin, | ||||
| Variable,+,gpio_nfc_cs,const GpioPin, | ||||
| Variable,+,gpio_nfc_irq_rfid_pull,const GpioPin, | ||||
| Variable,+,gpio_periph_power,const GpioPin, | ||||
| Variable,+,gpio_pins,const GpioPinRecord[], | ||||
| Variable,+,gpio_pins_count,const size_t, | ||||
| Variable,+,gpio_rf_sw_0,const GpioPin, | ||||
| @@ -3096,11 +3099,13 @@ Variable,+,gpio_spi_r_miso,const GpioPin, | ||||
| Variable,+,gpio_spi_r_mosi,const GpioPin, | ||||
| Variable,+,gpio_spi_r_sck,const GpioPin, | ||||
| Variable,+,gpio_subghz_cs,const GpioPin, | ||||
| Variable,+,gpio_swclk,const GpioPin, | ||||
| Variable,+,gpio_swdio,const GpioPin, | ||||
| Variable,+,gpio_usart_rx,const GpioPin, | ||||
| Variable,+,gpio_usart_tx,const GpioPin, | ||||
| Variable,+,gpio_usb_dm,const GpioPin, | ||||
| Variable,+,gpio_usb_dp,const GpioPin, | ||||
| Variable,+,gpio_ibutton,const GpioPin, | ||||
| Variable,+,gpio_vibro,const GpioPin, | ||||
| Variable,+,input_pins,const InputPin[], | ||||
| Variable,+,input_pins_count,const size_t, | ||||
| Variable,+,lfrfid_protocols,const ProtocolBase*[], | ||||
| @@ -3249,7 +3254,6 @@ Variable,+,message_red_255,const NotificationMessage, | ||||
| Variable,+,message_sound_off,const NotificationMessage, | ||||
| Variable,+,message_vibro_off,const NotificationMessage, | ||||
| Variable,+,message_vibro_on,const NotificationMessage, | ||||
| Variable,+,gpio_periph_power,const GpioPin, | ||||
| Variable,+,sequence_audiovisual_alert,const NotificationSequence, | ||||
| Variable,+,sequence_blink_blue_10,const NotificationSequence, | ||||
| Variable,+,sequence_blink_blue_100,const NotificationSequence, | ||||
| @@ -3307,4 +3311,3 @@ Variable,+,usb_cdc_single,FuriHalUsbInterface, | ||||
| Variable,+,usb_hid,FuriHalUsbInterface, | ||||
| Variable,+,usb_hid_u2f,FuriHalUsbInterface, | ||||
| Variable,+,usbd_devfs,const usbd_driver, | ||||
| Variable,+,gpio_vibro,const GpioPin, | ||||
|   | ||||
| 
 | 
| @@ -58,12 +58,6 @@ void ble_glue_init() { | ||||
|     ble_glue = malloc(sizeof(BleGlue)); | ||||
|     ble_glue->status = BleGlueStatusStartup; | ||||
|  | ||||
|     // Configure the system Power Mode | ||||
|     // Select HSI as system clock source after Wake Up from Stop mode | ||||
|     LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI); | ||||
|     /* Initialize the CPU2 reset value before starting CPU2 with C2BOOT */ | ||||
|     LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); | ||||
|  | ||||
| #ifdef BLE_GLUE_DEBUG | ||||
|     APPD_Init(); | ||||
| #endif | ||||
|   | ||||
| @@ -63,6 +63,10 @@ void furi_hal_clock_init() { | ||||
|     LL_RCC_HSI_Enable(); | ||||
|     while(!HS_CLOCK_IS_READY()) | ||||
|         ; | ||||
|     /* Select HSI as system clock source after Wake Up from Stop mode | ||||
|      * Must be set before enabling CSS */ | ||||
|     LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI); | ||||
|  | ||||
|     LL_RCC_HSE_EnableCSS(); | ||||
|  | ||||
|     /* LSE and LSI1 configuration and activation */ | ||||
| @@ -215,11 +219,14 @@ void furi_hal_clock_switch_to_hsi() { | ||||
| void furi_hal_clock_switch_to_pll() { | ||||
|     LL_RCC_HSE_Enable(); | ||||
|     LL_RCC_PLL_Enable(); | ||||
|     LL_RCC_PLLSAI1_Enable(); | ||||
|  | ||||
|     while(!LL_RCC_HSE_IsReady()) | ||||
|         ; | ||||
|     while(!LL_RCC_PLL_IsReady()) | ||||
|         ; | ||||
|     while(!LL_RCC_PLLSAI1_IsReady()) | ||||
|         ; | ||||
|  | ||||
|     LL_FLASH_SetLatency(LL_FLASH_LATENCY_3); | ||||
|  | ||||
| @@ -296,4 +303,4 @@ void furi_hal_clock_mco_disable() { | ||||
|     LL_RCC_MSI_Disable(); | ||||
|     while(LL_RCC_MSI_IsReady() != 0) | ||||
|         ; | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -3,12 +3,26 @@ | ||||
| #include <stm32wbxx_ll_exti.h> | ||||
| #include <stm32wbxx_ll_system.h> | ||||
|  | ||||
| #include <furi_hal_gpio.h> | ||||
| #include <furi_hal_resources.h> | ||||
|  | ||||
| volatile bool furi_hal_debug_gdb_session_active = false; | ||||
|  | ||||
| void furi_hal_debug_enable() { | ||||
|     // Low power mode debug | ||||
|     LL_DBGMCU_EnableDBGSleepMode(); | ||||
|     LL_DBGMCU_EnableDBGStopMode(); | ||||
|     LL_DBGMCU_EnableDBGStandbyMode(); | ||||
|     LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_48); | ||||
|     // SWD GPIO | ||||
|     furi_hal_gpio_init_ex( | ||||
|         &gpio_swdio, | ||||
|         GpioModeAltFunctionPushPull, | ||||
|         GpioPullUp, | ||||
|         GpioSpeedVeryHigh, | ||||
|         GpioAltFn0JTMS_SWDIO); | ||||
|     furi_hal_gpio_init_ex( | ||||
|         &gpio_swclk, GpioModeAltFunctionPushPull, GpioPullDown, GpioSpeedLow, GpioAltFn0JTCK_SWCLK); | ||||
| } | ||||
|  | ||||
| void furi_hal_debug_disable() { | ||||
| @@ -17,4 +31,11 @@ void furi_hal_debug_disable() { | ||||
|     LL_DBGMCU_DisableDBGStopMode(); | ||||
|     LL_DBGMCU_DisableDBGStandbyMode(); | ||||
|     LL_EXTI_DisableIT_32_63(LL_EXTI_LINE_48); | ||||
|     // SWD GPIO | ||||
|     furi_hal_gpio_init_simple(&gpio_swdio, GpioModeAnalog); | ||||
|     furi_hal_gpio_init_simple(&gpio_swclk, GpioModeAnalog); | ||||
| } | ||||
|  | ||||
| bool furi_hal_debug_is_gdb_session_active() { | ||||
|     return furi_hal_debug_gdb_session_active; | ||||
| } | ||||
| @@ -28,11 +28,24 @@ | ||||
| // Arbitrary (but small) number for better tick consistency | ||||
| #define FURI_HAL_OS_EXTRA_CNT 3 | ||||
|  | ||||
| #ifndef FURI_HAL_OS_DEBUG_AWAKE_GPIO | ||||
| #define FURI_HAL_OS_DEBUG_AWAKE_GPIO (&gpio_ext_pa7) | ||||
| #endif | ||||
|  | ||||
| #ifndef FURI_HAL_OS_DEBUG_TICK_GPIO | ||||
| #define FURI_HAL_OS_DEBUG_TICK_GPIO (&gpio_ext_pa6) | ||||
| #endif | ||||
|  | ||||
| #ifndef FURI_HAL_OS_DEBUG_SECOND_GPIO | ||||
| #define FURI_HAL_OS_DEBUG_SECOND_GPIO (&gpio_ext_pa4) | ||||
| #endif | ||||
|  | ||||
| #ifdef FURI_HAL_OS_DEBUG | ||||
| #include <stm32wbxx_ll_gpio.h> | ||||
|  | ||||
| void furi_hal_os_timer_callback() { | ||||
|     furi_hal_gpio_write(&gpio_ext_pa4, !furi_hal_gpio_read(&gpio_ext_pa4)); | ||||
|     furi_hal_gpio_write( | ||||
|         FURI_HAL_OS_DEBUG_SECOND_GPIO, !furi_hal_gpio_read(FURI_HAL_OS_DEBUG_SECOND_GPIO)); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| @@ -44,9 +57,11 @@ void furi_hal_os_init() { | ||||
|     furi_hal_idle_timer_init(); | ||||
|  | ||||
| #ifdef FURI_HAL_OS_DEBUG | ||||
|     furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull); | ||||
|     furi_hal_gpio_init_simple(&gpio_ext_pa6, GpioModeOutputPushPull); | ||||
|     furi_hal_gpio_init_simple(&gpio_ext_pa4, GpioModeOutputPushPull); | ||||
|     furi_hal_gpio_init_simple(FURI_HAL_OS_DEBUG_AWAKE_GPIO, GpioModeOutputPushPull); | ||||
|     furi_hal_gpio_init_simple(FURI_HAL_OS_DEBUG_TICK_GPIO, GpioModeOutputPushPull); | ||||
|     furi_hal_gpio_init_simple(FURI_HAL_OS_DEBUG_SECOND_GPIO, GpioModeOutputPushPull); | ||||
|     furi_hal_gpio_write(FURI_HAL_OS_DEBUG_AWAKE_GPIO, 1); | ||||
|  | ||||
|     FuriTimer* second_timer = | ||||
|         furi_timer_alloc(furi_hal_os_timer_callback, FuriTimerTypePeriodic, NULL); | ||||
|     furi_timer_start(second_timer, FURI_HAL_OS_TICK_HZ); | ||||
| @@ -58,7 +73,8 @@ void furi_hal_os_init() { | ||||
| void furi_hal_os_tick() { | ||||
|     if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { | ||||
| #ifdef FURI_HAL_OS_DEBUG | ||||
|         furi_hal_gpio_write(&gpio_ext_pa6, !furi_hal_gpio_read(&gpio_ext_pa6)); | ||||
|         furi_hal_gpio_write( | ||||
|             FURI_HAL_OS_DEBUG_TICK_GPIO, !furi_hal_gpio_read(FURI_HAL_OS_DEBUG_TICK_GPIO)); | ||||
| #endif | ||||
|         xPortSysTickHandler(); | ||||
|     } | ||||
| @@ -121,14 +137,14 @@ static inline uint32_t furi_hal_os_sleep(TickType_t expected_idle_ticks) { | ||||
|     furi_hal_idle_timer_start(FURI_HAL_OS_TICKS_TO_IDLE_CNT(expected_idle_ticks)); | ||||
|  | ||||
| #ifdef FURI_HAL_OS_DEBUG | ||||
|     furi_hal_gpio_write(&gpio_ext_pa7, 0); | ||||
|     furi_hal_gpio_write(FURI_HAL_OS_DEBUG_AWAKE_GPIO, 0); | ||||
| #endif | ||||
|  | ||||
|     // Go to sleep mode | ||||
|     furi_hal_power_sleep(); | ||||
|  | ||||
| #ifdef FURI_HAL_OS_DEBUG | ||||
|     furi_hal_gpio_write(&gpio_ext_pa7, 1); | ||||
|     furi_hal_gpio_write(FURI_HAL_OS_DEBUG_AWAKE_GPIO, 1); | ||||
| #endif | ||||
|  | ||||
|     // Calculate how much time we spent in the sleep | ||||
|   | ||||
| @@ -4,6 +4,8 @@ | ||||
| #include <furi_hal_vibro.h> | ||||
| #include <furi_hal_resources.h> | ||||
| #include <furi_hal_uart.h> | ||||
| #include <furi_hal_rtc.h> | ||||
| #include <furi_hal_debug.h> | ||||
|  | ||||
| #include <stm32wbxx_ll_rcc.h> | ||||
| #include <stm32wbxx_ll_pwr.h> | ||||
| @@ -19,15 +21,16 @@ | ||||
|  | ||||
| #define TAG "FuriHalPower" | ||||
|  | ||||
| #ifdef FURI_HAL_POWER_DEEP_SLEEP_ENABLED | ||||
| #define FURI_HAL_POWER_DEEP_INSOMNIA 0 | ||||
| #else | ||||
| #define FURI_HAL_POWER_DEEP_INSOMNIA 1 | ||||
| #ifndef FURI_HAL_POWER_DEBUG_WFI_GPIO | ||||
| #define FURI_HAL_POWER_DEBUG_WFI_GPIO (&gpio_ext_pb2) | ||||
| #endif | ||||
|  | ||||
| #ifndef FURI_HAL_POWER_DEBUG_STOP_GPIO | ||||
| #define FURI_HAL_POWER_DEBUG_STOP_GPIO (&gpio_ext_pc3) | ||||
| #endif | ||||
|  | ||||
| typedef struct { | ||||
|     volatile uint8_t insomnia; | ||||
|     volatile uint8_t deep_insomnia; | ||||
|     volatile uint8_t suppress_charge; | ||||
|  | ||||
|     uint8_t gauge_initialized; | ||||
| @@ -36,7 +39,6 @@ typedef struct { | ||||
|  | ||||
| static volatile FuriHalPower furi_hal_power = { | ||||
|     .insomnia = 0, | ||||
|     .deep_insomnia = FURI_HAL_POWER_DEEP_INSOMNIA, | ||||
|     .suppress_charge = 0, | ||||
| }; | ||||
|  | ||||
| @@ -79,19 +81,23 @@ const ParamCEDV cedv = { | ||||
| }; | ||||
|  | ||||
| void furi_hal_power_init() { | ||||
| #ifdef FURI_HAL_POWER_DEBUG | ||||
|     furi_hal_gpio_init_simple(FURI_HAL_POWER_DEBUG_WFI_GPIO, GpioModeOutputPushPull); | ||||
|     furi_hal_gpio_init_simple(FURI_HAL_POWER_DEBUG_STOP_GPIO, GpioModeOutputPushPull); | ||||
|     furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_WFI_GPIO, 0); | ||||
|     furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_STOP_GPIO, 0); | ||||
| #endif | ||||
|  | ||||
|     LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); | ||||
|     LL_PWR_SMPS_SetMode(LL_PWR_SMPS_STEP_DOWN); | ||||
|     LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2); | ||||
|     LL_C2_PWR_SetPowerMode(LL_PWR_MODE_STOP2); | ||||
|  | ||||
|     furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); | ||||
|     bq27220_init(&furi_hal_i2c_handle_power, &cedv); | ||||
|     bq25896_init(&furi_hal_i2c_handle_power); | ||||
|     furi_hal_i2c_release(&furi_hal_i2c_handle_power); | ||||
|  | ||||
| #ifdef FURI_HAL_OS_DEBUG | ||||
|     furi_hal_gpio_init_simple(&gpio_ext_pb2, GpioModeOutputPushPull); | ||||
|     furi_hal_gpio_init_simple(&gpio_ext_pc3, GpioModeOutputPushPull); | ||||
| #endif | ||||
|  | ||||
|     FURI_LOG_I(TAG, "Init OK"); | ||||
| } | ||||
|  | ||||
| @@ -140,11 +146,12 @@ bool furi_hal_power_sleep_available() { | ||||
|     return furi_hal_power.insomnia == 0; | ||||
| } | ||||
|  | ||||
| bool furi_hal_power_deep_sleep_available() { | ||||
|     return furi_hal_bt_is_alive() && furi_hal_power.deep_insomnia == 0; | ||||
| static inline bool furi_hal_power_deep_sleep_available() { | ||||
|     return furi_hal_bt_is_alive() && !furi_hal_rtc_is_flag_set(FuriHalRtcFlagLegacySleep) && | ||||
|            !furi_hal_debug_is_gdb_session_active(); | ||||
| } | ||||
|  | ||||
| void furi_hal_power_light_sleep() { | ||||
| static inline void furi_hal_power_light_sleep() { | ||||
|     __WFI(); | ||||
| } | ||||
|  | ||||
| @@ -152,17 +159,15 @@ static inline void furi_hal_power_suspend_aux_periphs() { | ||||
|     // Disable USART | ||||
|     furi_hal_uart_suspend(FuriHalUartIdUSART1); | ||||
|     furi_hal_uart_suspend(FuriHalUartIdLPUART1); | ||||
|     // TODO: Disable USB | ||||
| } | ||||
|  | ||||
| static inline void furi_hal_power_resume_aux_periphs() { | ||||
|     // Re-enable USART | ||||
|     furi_hal_uart_resume(FuriHalUartIdUSART1); | ||||
|     furi_hal_uart_resume(FuriHalUartIdLPUART1); | ||||
|     // TODO: Re-enable USB | ||||
| } | ||||
|  | ||||
| void furi_hal_power_deep_sleep() { | ||||
| static inline void furi_hal_power_deep_sleep() { | ||||
|     furi_hal_power_suspend_aux_periphs(); | ||||
|  | ||||
|     while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)) | ||||
| @@ -187,8 +192,6 @@ void furi_hal_power_deep_sleep() { | ||||
|     LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0); | ||||
|  | ||||
|     // Prepare deep sleep | ||||
|     LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2); | ||||
|     LL_C2_PWR_SetPowerMode(LL_PWR_MODE_STOP2); | ||||
|     LL_LPM_EnableDeepSleep(); | ||||
|  | ||||
| #if defined(__CC_ARM) | ||||
| @@ -200,13 +203,6 @@ void furi_hal_power_deep_sleep() { | ||||
|  | ||||
|     LL_LPM_EnableSleep(); | ||||
|  | ||||
|     // Make sure that values differ to prevent disaster on wfi | ||||
|     LL_PWR_SetPowerMode(LL_PWR_MODE_STOP0); | ||||
|     LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); | ||||
|  | ||||
|     LL_PWR_ClearFlag_C1STOP_C1STB(); | ||||
|     LL_PWR_ClearFlag_C2STOP_C2STB(); | ||||
|  | ||||
|     /* Release ENTRY_STOP_MODE semaphore */ | ||||
|     LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0); | ||||
|  | ||||
| @@ -220,28 +216,25 @@ void furi_hal_power_deep_sleep() { | ||||
|     LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0); | ||||
|  | ||||
|     furi_hal_power_resume_aux_periphs(); | ||||
|     furi_hal_rtc_sync_shadow(); | ||||
| } | ||||
|  | ||||
| void furi_hal_power_sleep() { | ||||
|     if(furi_hal_power_deep_sleep_available()) { | ||||
| #ifdef FURI_HAL_OS_DEBUG | ||||
|         furi_hal_gpio_write(&gpio_ext_pc3, 1); | ||||
| #ifdef FURI_HAL_POWER_DEBUG | ||||
|         furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_STOP_GPIO, 1); | ||||
| #endif | ||||
|  | ||||
|         furi_hal_power_deep_sleep(); | ||||
|  | ||||
| #ifdef FURI_HAL_OS_DEBUG | ||||
|         furi_hal_gpio_write(&gpio_ext_pc3, 0); | ||||
| #ifdef FURI_HAL_POWER_DEBUG | ||||
|         furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_STOP_GPIO, 0); | ||||
| #endif | ||||
|     } else { | ||||
| #ifdef FURI_HAL_OS_DEBUG | ||||
|         furi_hal_gpio_write(&gpio_ext_pb2, 1); | ||||
| #ifdef FURI_HAL_POWER_DEBUG | ||||
|         furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_WFI_GPIO, 1); | ||||
| #endif | ||||
|  | ||||
|         furi_hal_power_light_sleep(); | ||||
|  | ||||
| #ifdef FURI_HAL_OS_DEBUG | ||||
|         furi_hal_gpio_write(&gpio_ext_pb2, 0); | ||||
| #ifdef FURI_HAL_POWER_DEBUG | ||||
|         furi_hal_gpio_write(FURI_HAL_POWER_DEBUG_WFI_GPIO, 0); | ||||
| #endif | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -9,19 +9,35 @@ | ||||
|  | ||||
| #define TAG "FuriHalRandom" | ||||
|  | ||||
| static uint32_t furi_hal_random_read_rng() { | ||||
|     while(LL_RNG_IsActiveFlag_CECS(RNG) && LL_RNG_IsActiveFlag_SECS(RNG) && | ||||
|           !LL_RNG_IsActiveFlag_DRDY(RNG)) { | ||||
|         /* Error handling as described in RM0434, pg. 582-583 */ | ||||
|         if(LL_RNG_IsActiveFlag_CECS(RNG)) { | ||||
|             /* Clock error occurred */ | ||||
|             LL_RNG_ClearFlag_CEIS(RNG); | ||||
|         } | ||||
|  | ||||
|         if(LL_RNG_IsActiveFlag_SECS(RNG)) { | ||||
|             /* Noise source error occurred */ | ||||
|             LL_RNG_ClearFlag_SEIS(RNG); | ||||
|  | ||||
|             for(uint32_t i = 0; i < 12; ++i) { | ||||
|                 const volatile uint32_t discard = LL_RNG_ReadRandData32(RNG); | ||||
|                 UNUSED(discard); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return LL_RNG_ReadRandData32(RNG); | ||||
| } | ||||
|  | ||||
| uint32_t furi_hal_random_get() { | ||||
|     while(LL_HSEM_1StepLock(HSEM, CFG_HW_RNG_SEMID)) | ||||
|         ; | ||||
|     LL_RNG_Enable(RNG); | ||||
|  | ||||
|     while(!LL_RNG_IsActiveFlag_DRDY(RNG)) | ||||
|         ; | ||||
|  | ||||
|     if((LL_RNG_IsActiveFlag_CECS(RNG)) || (LL_RNG_IsActiveFlag_SECS(RNG))) { | ||||
|         furi_crash("TRNG error"); | ||||
|     } | ||||
|  | ||||
|     uint32_t random_val = LL_RNG_ReadRandData32(RNG); | ||||
|     const uint32_t random_val = furi_hal_random_read_rng(); | ||||
|  | ||||
|     LL_RNG_Disable(RNG); | ||||
|     LL_HSEM_ReleaseLock(HSEM, CFG_HW_RNG_SEMID, 0); | ||||
| @@ -35,15 +51,7 @@ void furi_hal_random_fill_buf(uint8_t* buf, uint32_t len) { | ||||
|     LL_RNG_Enable(RNG); | ||||
|  | ||||
|     for(uint32_t i = 0; i < len; i += 4) { | ||||
|         while(!LL_RNG_IsActiveFlag_DRDY(RNG)) | ||||
|             ; | ||||
|  | ||||
|         if((LL_RNG_IsActiveFlag_CECS(RNG)) || (LL_RNG_IsActiveFlag_SECS(RNG))) { | ||||
|             furi_crash("TRNG error"); | ||||
|         } | ||||
|  | ||||
|         uint32_t random_val = LL_RNG_ReadRandData32(RNG); | ||||
|  | ||||
|         const uint32_t random_val = furi_hal_random_read_rng(); | ||||
|         uint8_t len_cur = ((i + 4) < len) ? (4) : (len - i); | ||||
|         memcpy(&buf[i], &random_val, len_cur); | ||||
|     } | ||||
|   | ||||
| @@ -6,6 +6,9 @@ | ||||
|  | ||||
| #define TAG "FuriHalResources" | ||||
|  | ||||
| const GpioPin gpio_swdio = {.port = GPIOA, .pin = LL_GPIO_PIN_13}; | ||||
| const GpioPin gpio_swclk = {.port = GPIOA, .pin = LL_GPIO_PIN_14}; | ||||
|  | ||||
| const GpioPin gpio_vibro = {.port = VIBRO_GPIO_Port, .pin = VIBRO_Pin}; | ||||
| const GpioPin gpio_ibutton = {.port = iBTN_GPIO_Port, .pin = iBTN_Pin}; | ||||
|  | ||||
|   | ||||
| @@ -50,6 +50,9 @@ extern const size_t input_pins_count; | ||||
| extern const GpioPinRecord gpio_pins[]; | ||||
| extern const size_t gpio_pins_count; | ||||
|  | ||||
| extern const GpioPin gpio_swdio; | ||||
| extern const GpioPin gpio_swclk; | ||||
|  | ||||
| extern const GpioPin gpio_vibro; | ||||
| extern const GpioPin gpio_ibutton; | ||||
|  | ||||
|   | ||||
| @@ -165,6 +165,14 @@ void furi_hal_rtc_init() { | ||||
|     FURI_LOG_I(TAG, "Init OK"); | ||||
| } | ||||
|  | ||||
| void furi_hal_rtc_sync_shadow() { | ||||
|     if(!LL_RTC_IsShadowRegBypassEnabled(RTC)) { | ||||
|         LL_RTC_ClearFlag_RS(RTC); | ||||
|         while(!LL_RTC_IsActiveFlag_RS(RTC)) { | ||||
|         }; | ||||
|     } | ||||
| } | ||||
|  | ||||
| uint32_t furi_hal_rtc_get_register(FuriHalRtcRegister reg) { | ||||
|     return LL_RTC_BAK_GetRegister(RTC, reg); | ||||
| } | ||||
| @@ -312,12 +320,7 @@ void furi_hal_rtc_set_datetime(FuriHalRtcDateTime* datetime) { | ||||
|     /* Exit Initialization mode */ | ||||
|     LL_RTC_DisableInitMode(RTC); | ||||
|  | ||||
|     /* If RTC_CR_BYPSHAD bit = 0, wait for synchro else this check is not needed */ | ||||
|     if(!LL_RTC_IsShadowRegBypassEnabled(RTC)) { | ||||
|         LL_RTC_ClearFlag_RS(RTC); | ||||
|         while(!LL_RTC_IsActiveFlag_RS(RTC)) { | ||||
|         }; | ||||
|     } | ||||
|     furi_hal_rtc_sync_shadow(); | ||||
|  | ||||
|     /* Enable write protection */ | ||||
|     LL_RTC_EnableWriteProtection(RTC); | ||||
|   | ||||
| @@ -18,6 +18,9 @@ void furi_hal_debug_enable(); | ||||
| /** Disable MCU debug */ | ||||
| void furi_hal_debug_disable(); | ||||
|  | ||||
| /** Check if GDB debug session is active */ | ||||
| bool furi_hal_debug_is_gdb_session_active(); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|   | ||||
| @@ -58,12 +58,6 @@ void furi_hal_power_insomnia_exit(); | ||||
|  */ | ||||
| bool furi_hal_power_sleep_available(); | ||||
|  | ||||
| /** Check if deep sleep availble | ||||
|  * | ||||
|  * @return     true if available | ||||
|  */ | ||||
| bool furi_hal_power_deep_sleep_available(); | ||||
|  | ||||
| /** Go to sleep | ||||
|  */ | ||||
| void furi_hal_power_sleep(); | ||||
|   | ||||
| @@ -30,6 +30,7 @@ typedef enum { | ||||
|     FuriHalRtcFlagLock = (1 << 2), | ||||
|     FuriHalRtcFlagC2Update = (1 << 3), | ||||
|     FuriHalRtcFlagHandOrient = (1 << 4), | ||||
|     FuriHalRtcFlagLegacySleep = (1 << 5), | ||||
| } FuriHalRtcFlag; | ||||
|  | ||||
| typedef enum { | ||||
| @@ -85,6 +86,9 @@ void furi_hal_rtc_deinit_early(); | ||||
| /** Initialize RTC subsystem */ | ||||
| void furi_hal_rtc_init(); | ||||
|  | ||||
| /** Force sync shadow registers */ | ||||
| void furi_hal_rtc_sync_shadow(); | ||||
|  | ||||
| /** Get RTC register content | ||||
|  * | ||||
|  * @param[in]  reg   The register identifier | ||||
|   | ||||
		Reference in New Issue
	
	Block a user