diff --git a/applications/main/fap_loader/fap_loader_app.c b/applications/main/fap_loader/fap_loader_app.c index f5c7af02..7af5244a 100644 --- a/applications/main/fap_loader/fap_loader_app.c +++ b/applications/main/fap_loader/fap_loader_app.c @@ -1,6 +1,7 @@ #include "fap_loader_app.h" #include +#include #include #include @@ -23,8 +24,6 @@ struct FapLoader { Loading* loading; }; -volatile bool fap_loader_debug_active = false; - bool fap_loader_load_name_and_icon( FuriString* path, Storage* storage, @@ -111,7 +110,7 @@ static bool fap_loader_run_selected_app(FapLoader* loader) { FuriThread* thread = flipper_application_spawn(loader->app, NULL); /* This flag is set by the debugger - to break on app start */ - if(fap_loader_debug_active) { + if(furi_hal_debug_is_gdb_session_active()) { FURI_LOG_W(TAG, "Triggering BP for debugger"); /* After hitting this, you can set breakpoints in your .fap's code * Note that you have to toggle breakpoints that were set before */ diff --git a/applications/settings/power_settings_app/views/battery_info.c b/applications/settings/power_settings_app/views/battery_info.c index 7394fd3c..0956cae4 100644 --- a/applications/settings/power_settings_app/views/battery_info.c +++ b/applications/settings/power_settings_app/views/battery_info.c @@ -4,8 +4,8 @@ #include #include -#define LOW_CHARGE_THRESHOLD 10 -#define HIGH_DRAIN_CURRENT_THRESHOLD 100 +#define LOW_CHARGE_THRESHOLD (10) +#define HIGH_DRAIN_CURRENT_THRESHOLD (-100) struct BatteryInfo { View* view; @@ -25,14 +25,13 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { char header[20] = {}; char value[20] = {}; - int32_t drain_current = data->gauge_current * (-1000); - uint32_t charge_current = data->gauge_current * 1000; + int32_t current = 1000.0f * data->gauge_current; // Draw battery canvas_draw_icon(canvas, x, y, &I_BatteryBody_52x28); - if(charge_current > 0) { + if(current > 0) { canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceCharging_29x14); - } else if(drain_current > HIGH_DRAIN_CURRENT_THRESHOLD) { + } else if(current < HIGH_DRAIN_CURRENT_THRESHOLD) { canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceConfused_29x14); } else if(data->charge < LOW_CHARGE_THRESHOLD) { canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNopower_29x14); @@ -44,7 +43,7 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { elements_bubble(canvas, 53, 0, 71, 39); // Set text - if(charge_current > 0) { + if(current > 0) { snprintf(emote, sizeof(emote), "%s", "Yummy!"); snprintf(header, sizeof(header), "%s", "Charging at"); snprintf( @@ -53,34 +52,36 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) { "%lu.%luV %lumA", (uint32_t)(data->vbus_voltage), (uint32_t)(data->vbus_voltage * 10) % 10, - charge_current); - } else if(drain_current > 0) { + current); + } else if(current < 0) { snprintf( emote, sizeof(emote), "%s", - drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "Oh no!" : "Om-nom-nom!"); + current < HIGH_DRAIN_CURRENT_THRESHOLD ? "Oh no!" : "Om-nom-nom!"); snprintf(header, sizeof(header), "%s", "Consumption is"); snprintf( value, sizeof(value), "%ld %s", - drain_current, - drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "mA!" : "mA"); - } else if(drain_current != 0) { - snprintf(header, 20, "..."); - } else if(data->charge_voltage_limit < 4.2) { - // Non-default battery charging limit, mention it - snprintf(emote, sizeof(emote), "Charged!"); - snprintf(header, sizeof(header), "Limited to"); - snprintf( - value, - sizeof(value), - "%lu.%luV", - (uint32_t)(data->charge_voltage_limit), - (uint32_t)(data->charge_voltage_limit * 10) % 10); + ABS(current), + current < HIGH_DRAIN_CURRENT_THRESHOLD ? "mA!" : "mA"); + } else if(data->vbus_voltage > 0) { + if(data->charge_voltage_limit < 4.2) { + // Non-default battery charging limit, mention it + snprintf(emote, sizeof(emote), "Charged!"); + snprintf(header, sizeof(header), "Limited to"); + snprintf( + value, + sizeof(value), + "%lu.%luV", + (uint32_t)(data->charge_voltage_limit), + (uint32_t)(data->charge_voltage_limit * 10) % 10); + } else { + snprintf(header, sizeof(header), "Charged!"); + } } else { - snprintf(header, sizeof(header), "Charged!"); + snprintf(header, sizeof(header), "Napping..."); } canvas_draw_str_aligned(canvas, 92, y + 3, AlignCenter, AlignCenter, emote); diff --git a/applications/settings/system/system_settings.c b/applications/settings/system/system_settings.c index cb74d7a8..597710a5 100644 --- a/applications/settings/system/system_settings.c +++ b/applications/settings/system/system_settings.c @@ -141,6 +141,21 @@ static void hand_orient_changed(VariableItem* item) { loader_update_menu(); } +const char* const sleep_method[] = { + "Default", + "Legacy", +}; + +static void sleep_method_changed(VariableItem* item) { + uint8_t index = variable_item_get_current_value_index(item); + variable_item_set_current_value_text(item, sleep_method[index]); + if(index) { + furi_hal_rtc_set_flag(FuriHalRtcFlagLegacySleep); + } else { + furi_hal_rtc_reset_flag(FuriHalRtcFlagLegacySleep); + } +} + static uint32_t system_settings_exit(void* context) { UNUSED(context); return VIEW_NONE; @@ -218,6 +233,12 @@ SystemSettings* system_settings_alloc() { variable_item_set_current_value_index(item, value_index); variable_item_set_current_value_text(item, heap_trace_mode_text[value_index]); + item = variable_item_list_add( + app->var_item_list, "Sleep Method", COUNT_OF(sleep_method), sleep_method_changed, app); + value_index = furi_hal_rtc_is_flag_set(FuriHalRtcFlagLegacySleep) ? 1 : 0; + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, sleep_method[value_index]); + view_set_previous_callback( variable_item_list_get_view(app->var_item_list), system_settings_exit); view_dispatcher_add_view( diff --git a/debug/flipperapps.py b/debug/flipperapps.py index 1dc5ebd0..90582c1e 100644 --- a/debug/flipperapps.py +++ b/debug/flipperapps.py @@ -135,6 +135,7 @@ class FlipperAppStateHelper: self.app_list_ptr = None self.app_list_entry_type = None self._current_apps: list[AppState] = [] + self.set_debug_mode(True) def _walk_app_list(self, list_head): while list_head: @@ -195,7 +196,7 @@ class FlipperAppStateHelper: self.set_debug_mode(False) def set_debug_mode(self, mode: bool) -> None: - gdb.execute(f"set variable fap_loader_debug_active = {int(mode)}") + gdb.execute(f"set variable furi_hal_debug_gdb_session_active = {int(mode)}") # Init additional 'fap-set-debug-elf-root' command and set up hooks diff --git a/documentation/FuriHalDebuging.md b/documentation/FuriHalDebuging.md new file mode 100644 index 00000000..8ff77016 --- /dev/null +++ b/documentation/FuriHalDebuging.md @@ -0,0 +1,26 @@ +# Furi HAL Debugging + +Some Furi subsystem got additional debugging features that can be enabled by adding additional defines to firmware compilation. +Usually they are used for low level tracing and profiling or signal redirection/duplication. + + +## FuriHalOs + +`--extra-define=FURI_HAL_OS_DEBUG` enables tick, tick suppression, idle and time flow. + +There are 3 signals that will be exposed to external GPIO pins: + +- `AWAKE` - `PA7` - High when system is busy with computations, low when sleeping. Can be used to track transitions to sleep mode. +- `TICK` - `PA6` - Flipped on system tick, only flips when no tick suppression in progress. Can be used to track tick skew and abnormal task scheduling. +- `SECOND` - `PA4` - Flipped each second. Can be used for tracing RT issue: time flow disturbance means system doesn't conforms Hard RT. + + + +## FuriHalPower + +`--extra-define=FURI_HAL_POWER_DEBUG` enables power subsystem mode transitions tracing. + +There are 2 signals that will be exposed to external GPIO pins: + +- `WFI` - `PB2` - Light sleep (wait for interrupt) used. Basically this is lightest and most non-breaking things power save mode. All function and debug should work correctly in this mode. +- `STOP` - `PC3` - STOP mode used. Platform deep sleep mode. Extremely fragile mode where most of the silicon is disabled or in unusable state. Debugging MCU in this mode is nearly impossible. \ No newline at end of file diff --git a/documentation/fbt.md b/documentation/fbt.md index 14d63e9c..23b2e2b5 100644 --- a/documentation/fbt.md +++ b/documentation/fbt.md @@ -105,6 +105,7 @@ To run cleanup (think of `make clean`) for specified targets, add the `-c` optio - `--options optionfile.py` (default value `fbt_options.py`) - load a file with multiple configuration values - `--extra-int-apps=app1,app2,appN` - force listed apps to be built as internal with the `firmware` target - `--extra-ext-apps=app1,app2,appN` - force listed apps to be built as external with the `firmware_extapps` target +- `--extra-define=A --extra-define=B=C ` - extra global defines that will be passed to the C/C++ compiler, can be specified multiple times - `--proxy-env=VAR1,VAR2` - additional environment variables to expose to subprocesses spawned by `fbt`. By default, `fbt` sanitizes the execution environment and doesn't forward all inherited environment variables. You can find the list of variables that are always forwarded in the `environ.scons` file. ## Configuration diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index 5d5b7bbc..493f5963 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -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, diff --git a/firmware/targets/f18/furi_hal/furi_hal_resources.c b/firmware/targets/f18/furi_hal/furi_hal_resources.c index 4a7015d1..6db483db 100644 --- a/firmware/targets/f18/furi_hal/furi_hal_resources.c +++ b/firmware/targets/f18/furi_hal/furi_hal_resources.c @@ -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}; diff --git a/firmware/targets/f18/furi_hal/furi_hal_resources.h b/firmware/targets/f18/furi_hal/furi_hal_resources.h index 3c4708d1..7d2caab3 100644 --- a/firmware/targets/f18/furi_hal/furi_hal_resources.h +++ b/firmware/targets/f18/furi_hal/furi_hal_resources.h @@ -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; diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 89984352..3ef57813 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -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, diff --git a/firmware/targets/f7/ble_glue/ble_glue.c b/firmware/targets/f7/ble_glue/ble_glue.c index 83562c73..a2f2f1a9 100644 --- a/firmware/targets/f7/ble_glue/ble_glue.c +++ b/firmware/targets/f7/ble_glue/ble_glue.c @@ -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 diff --git a/firmware/targets/f7/furi_hal/furi_hal_clock.c b/firmware/targets/f7/furi_hal/furi_hal_clock.c index cf19451e..d85524ce 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_clock.c +++ b/firmware/targets/f7/furi_hal/furi_hal_clock.c @@ -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) ; -} \ No newline at end of file +} diff --git a/firmware/targets/f7/furi_hal/furi_hal_debug.c b/firmware/targets/f7/furi_hal/furi_hal_debug.c index 3b5dfe62..3dc03ea6 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_debug.c +++ b/firmware/targets/f7/furi_hal/furi_hal_debug.c @@ -3,12 +3,26 @@ #include #include +#include +#include + +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; +} \ No newline at end of file diff --git a/firmware/targets/f7/furi_hal/furi_hal_os.c b/firmware/targets/f7/furi_hal/furi_hal_os.c index ee9743e6..3fc1fbea 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_os.c +++ b/firmware/targets/f7/furi_hal/furi_hal_os.c @@ -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 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 diff --git a/firmware/targets/f7/furi_hal/furi_hal_power.c b/firmware/targets/f7/furi_hal/furi_hal_power.c index fd601ec7..9a87cef1 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_power.c +++ b/firmware/targets/f7/furi_hal/furi_hal_power.c @@ -4,6 +4,8 @@ #include #include #include +#include +#include #include #include @@ -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 } } diff --git a/firmware/targets/f7/furi_hal/furi_hal_random.c b/firmware/targets/f7/furi_hal/furi_hal_random.c index f36407cc..d3461c4d 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_random.c +++ b/firmware/targets/f7/furi_hal/furi_hal_random.c @@ -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); } diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.c b/firmware/targets/f7/furi_hal/furi_hal_resources.c index 912912b4..abfd977e 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.c +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.c @@ -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}; diff --git a/firmware/targets/f7/furi_hal/furi_hal_resources.h b/firmware/targets/f7/furi_hal/furi_hal_resources.h index f2991730..6e585c51 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_resources.h +++ b/firmware/targets/f7/furi_hal/furi_hal_resources.h @@ -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; diff --git a/firmware/targets/f7/furi_hal/furi_hal_rtc.c b/firmware/targets/f7/furi_hal/furi_hal_rtc.c index 84e7fe39..7bd45c35 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_rtc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_rtc.c @@ -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); diff --git a/firmware/targets/furi_hal_include/furi_hal_debug.h b/firmware/targets/furi_hal_include/furi_hal_debug.h index 88397bbb..befbb4f4 100644 --- a/firmware/targets/furi_hal_include/furi_hal_debug.h +++ b/firmware/targets/furi_hal_include/furi_hal_debug.h @@ -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 diff --git a/firmware/targets/furi_hal_include/furi_hal_power.h b/firmware/targets/furi_hal_include/furi_hal_power.h index 462e20e4..00182fa2 100644 --- a/firmware/targets/furi_hal_include/furi_hal_power.h +++ b/firmware/targets/furi_hal_include/furi_hal_power.h @@ -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(); diff --git a/firmware/targets/furi_hal_include/furi_hal_rtc.h b/firmware/targets/furi_hal_include/furi_hal_rtc.h index b16b04a6..0d9f46f0 100644 --- a/firmware/targets/furi_hal_include/furi_hal_rtc.h +++ b/firmware/targets/furi_hal_include/furi_hal_rtc.h @@ -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 diff --git a/furi/core/check.c b/furi/core/check.c index 910527ce..64f9f72f 100644 --- a/furi/core/check.c +++ b/furi/core/check.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -117,6 +118,8 @@ FURI_NORETURN void __furi_crash() { if(debug) { furi_hal_console_puts("\r\nSystem halted. Connect debugger for more info\r\n"); furi_hal_console_puts("\033[0m\r\n"); + furi_hal_debug_enable(); + RESTORE_REGISTERS_AND_HALT_MCU(true); } else { furi_hal_rtc_set_fault_data((uint32_t)__furi_check_message); diff --git a/furi/core/core_defines.h b/furi/core/core_defines.h index 03a364ab..830bb191 100644 --- a/furi/core/core_defines.h +++ b/furi/core/core_defines.h @@ -24,6 +24,10 @@ extern "C" { }) #endif +#ifndef ABS +#define ABS(a) ({ (a) < 0 ? -(a) : (a); }) +#endif + #ifndef ROUND_UP_TO #define ROUND_UP_TO(a, b) \ ({ \ diff --git a/site_scons/cc.scons b/site_scons/cc.scons index 1eb6a337..55ab72ba 100644 --- a/site_scons/cc.scons +++ b/site_scons/cc.scons @@ -36,6 +36,7 @@ ENV.AppendUnique( ], CPPDEFINES=[ "_GNU_SOURCE", + *GetOption("extra_defines"), ], LINKFLAGS=[ "-mcpu=cortex-m4", diff --git a/site_scons/commandline.scons b/site_scons/commandline.scons index d832a466..2e948662 100644 --- a/site_scons/commandline.scons +++ b/site_scons/commandline.scons @@ -26,6 +26,14 @@ AddOption( help="List of applications to add to firmware's built-ins. Also see FIRMWARE_APP_SET and FIRMWARE_APPS", ) +AddOption( + "--extra-define", + action="append", + dest="extra_defines", + default=[], + help="Extra global define that will be passed to C/C++ compiler, can be specified multiple times", +) + AddOption( "--extra-ext-apps", action="store",