[FL-2399, FL-2261] Tickless sleep shenanigans (#1168)
* Disable USART in sleep * Restore UART state on suspend/resume * FuriHal: Enable stop mode and add insomnia to I2C and SPI * Remove IDLE interrupt * FuriHal: add FPU isr and disable all FPU interrupt, add core2 stop mode configuration on deep sleep * FuriHal: tie stop mode debug with debug rtc flag * FuriHal: adjust flash latency on clock switch, tie mcu debug with RTC debug flag * FuriHal: move resource init to early stage * Add EXTI pending check, enable debug traps with compile-time flag * Wrap sleep debug functions in conditional compilation * Remove erroneous changed * Do not use CSS, remove it from everywhere * Enable/disable USB on VBUS connect (prototype) * FuriHal: add LPMS and DEEPSLEEP magic, workaround state inconsistency between cores * FuriHal: honor c1 LMPS * USB mode switch fix * Applications: add flags and insomnia bypass system * Correct spelling * FuriHal: cleanup insomnia usage, reset sleep flags on wakeup, add shutdown api * FuriHal: extra check on reinit request * FuriHal: rename gpio_display_rst pin to gpio_display_rst_n * FuriHal: add debug HAL * FuriHal: add some magic to core2 reload procedure, fix issue with crash on ble keyboard exit * FuriHal: cleanup ble glue, add BLE_GLUE_DEBUG flag * FuriHal: ble reinit API, move os timer to LPTIM1 for deep sleep capability, shutdown that works * FuriHal: take insomnia while shutdown * Remove USB switch on/off on VBUS change * Better tick skew handling * Improve tick consistency under load * Add USB_HP dummy IRQ handler * Move interrupt check closer to sleep * Clean up includes * Re-enable Insomnia globally * FuriHal: enable CSS * FuriHal: remove questionable core2 clock shenanigans * FuriHal: use core1 RCC registers in idle timer config * FuriHal: return back CSS handlers, add lptim isr dispatching Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com> Co-authored-by: nminaylov <nm29719@gmail.com>
This commit is contained in:
		
							parent
							
								
									73477cceed
								
							
						
					
					
						commit
						01434265f6
					
				| @ -32,7 +32,6 @@ void AccessorApp::run(void) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| AccessorApp::AccessorApp() { | AccessorApp::AccessorApp() { | ||||||
|     furi_hal_power_insomnia_enter(); |  | ||||||
|     notification = static_cast<NotificationApp*>(furi_record_open("notification")); |     notification = static_cast<NotificationApp*>(furi_record_open("notification")); | ||||||
|     onewire_host = onewire_host_alloc(); |     onewire_host = onewire_host_alloc(); | ||||||
|     furi_hal_power_enable_otg(); |     furi_hal_power_enable_otg(); | ||||||
| @ -42,7 +41,6 @@ AccessorApp::~AccessorApp() { | |||||||
|     furi_hal_power_disable_otg(); |     furi_hal_power_disable_otg(); | ||||||
|     furi_record_close("notification"); |     furi_record_close("notification"); | ||||||
|     onewire_host_free(onewire_host); |     onewire_host_free(onewire_host); | ||||||
|     furi_hal_power_insomnia_exit(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| AccessorAppViewManager* AccessorApp::get_view_manager() { | AccessorAppViewManager* AccessorApp::get_view_manager() { | ||||||
|  | |||||||
| @ -74,61 +74,113 @@ extern int32_t system_settings_app(void* p); | |||||||
| const FlipperApplication FLIPPER_SERVICES[] = { | const FlipperApplication FLIPPER_SERVICES[] = { | ||||||
| /* Services */ | /* Services */ | ||||||
| #ifdef SRV_RPC | #ifdef SRV_RPC | ||||||
|     {.app = rpc_srv, .name = "RpcSrv", .stack_size = 1024 * 4, .icon = NULL}, |     {.app = rpc_srv, | ||||||
|  |      .name = "RpcSrv", | ||||||
|  |      .stack_size = 1024 * 4, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_BT | #ifdef SRV_BT | ||||||
|     {.app = bt_srv, .name = "BtSrv", .stack_size = 1024, .icon = NULL}, |     {.app = bt_srv, | ||||||
|  |      .name = "BtSrv", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_CLI | #ifdef SRV_CLI | ||||||
|     {.app = cli_srv, .name = "CliSrv", .stack_size = 4096, .icon = NULL}, |     {.app = cli_srv, | ||||||
|  |      .name = "CliSrv", | ||||||
|  |      .stack_size = 4096, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_DIALOGS | #ifdef SRV_DIALOGS | ||||||
|     {.app = dialogs_srv, .name = "DialogsSrv", .stack_size = 1024, .icon = NULL}, |     {.app = dialogs_srv, | ||||||
|  |      .name = "DialogsSrv", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_DOLPHIN | #ifdef SRV_DOLPHIN | ||||||
|     {.app = dolphin_srv, .name = "DolphinSrv", .stack_size = 1024, .icon = NULL}, |     {.app = dolphin_srv, | ||||||
|  |      .name = "DolphinSrv", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_DESKTOP | #ifdef SRV_DESKTOP | ||||||
| #ifdef SRV_UPDATER | #ifdef SRV_UPDATER | ||||||
| #error SRV_UPDATER and SRV_DESKTOP are mutually exclusive! | #error SRV_UPDATER and SRV_DESKTOP are mutually exclusive! | ||||||
| #endif | #endif | ||||||
|     {.app = desktop_srv, .name = "DesktopSrv", .stack_size = 2048, .icon = NULL}, |     {.app = desktop_srv, | ||||||
|  |      .name = "DesktopSrv", | ||||||
|  |      .stack_size = 2048, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_GUI | #ifdef SRV_GUI | ||||||
|     {.app = gui_srv, .name = "GuiSrv", .stack_size = 2048, .icon = NULL}, |     {.app = gui_srv, | ||||||
|  |      .name = "GuiSrv", | ||||||
|  |      .stack_size = 2048, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_INPUT | #ifdef SRV_INPUT | ||||||
|     {.app = input_srv, .name = "InputSrv", .stack_size = 1024, .icon = NULL}, |     {.app = input_srv, | ||||||
|  |      .name = "InputSrv", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_LOADER | #ifdef SRV_LOADER | ||||||
|     {.app = loader_srv, .name = "LoaderSrv", .stack_size = 1024, .icon = NULL}, |     {.app = loader_srv, | ||||||
|  |      .name = "LoaderSrv", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_NOTIFICATION | #ifdef SRV_NOTIFICATION | ||||||
|     {.app = notification_srv, .name = "NotificationSrv", .stack_size = 1536, .icon = NULL}, |     {.app = notification_srv, | ||||||
|  |      .name = "NotificationSrv", | ||||||
|  |      .stack_size = 1536, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_POWER | #ifdef SRV_POWER | ||||||
|     {.app = power_srv, .name = "PowerSrv", .stack_size = 1024, .icon = NULL}, |     {.app = power_srv, | ||||||
|  |      .name = "PowerSrv", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_STORAGE | #ifdef SRV_STORAGE | ||||||
|     {.app = storage_srv, .name = "StorageSrv", .stack_size = 3072, .icon = NULL}, |     {.app = storage_srv, | ||||||
|  |      .name = "StorageSrv", | ||||||
|  |      .stack_size = 3072, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_UPDATER | #ifdef SRV_UPDATER | ||||||
| #ifdef SRV_DESKTOP | #ifdef SRV_DESKTOP | ||||||
| #error SRV_UPDATER and SRV_DESKTOP are mutually exclusive! | #error SRV_UPDATER and SRV_DESKTOP are mutually exclusive! | ||||||
| #endif | #endif | ||||||
|     {.app = updater_srv, .name = "UpdaterSrv", .stack_size = 2048, .icon = NULL}, |     {.app = updater_srv, | ||||||
|  |      .name = "UpdaterSrv", | ||||||
|  |      .stack_size = 2048, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -139,7 +191,11 @@ const FlipperApplication FLIPPER_SYSTEM_APPS[] = { | |||||||
| #ifdef SRV_UPDATER | #ifdef SRV_UPDATER | ||||||
| #error APP_UPDATER and SRV_UPDATER are mutually exclusive! | #error APP_UPDATER and SRV_UPDATER are mutually exclusive! | ||||||
| #endif | #endif | ||||||
|     {.app = updater_srv, .name = "UpdaterApp", .stack_size = 2048, .icon = NULL}, |     {.app = updater_srv, | ||||||
|  |      .name = "UpdaterApp", | ||||||
|  |      .stack_size = 2048, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -149,35 +205,67 @@ const size_t FLIPPER_SYSTEM_APPS_COUNT = COUNT_OF(FLIPPER_SYSTEM_APPS); | |||||||
| const FlipperApplication FLIPPER_APPS[] = { | const FlipperApplication FLIPPER_APPS[] = { | ||||||
| 
 | 
 | ||||||
| #ifdef APP_SUBGHZ | #ifdef APP_SUBGHZ | ||||||
|     {.app = subghz_app, .name = "Sub-GHz", .stack_size = 2048, .icon = &A_Sub1ghz_14}, |     {.app = subghz_app, | ||||||
|  |      .name = "Sub-GHz", | ||||||
|  |      .stack_size = 2048, | ||||||
|  |      .icon = &A_Sub1ghz_14, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_LF_RFID | #ifdef APP_LF_RFID | ||||||
|     {.app = lfrfid_app, .name = "125 kHz RFID", .stack_size = 2048, .icon = &A_125khz_14}, |     {.app = lfrfid_app, | ||||||
|  |      .name = "125 kHz RFID", | ||||||
|  |      .stack_size = 2048, | ||||||
|  |      .icon = &A_125khz_14, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_NFC | #ifdef APP_NFC | ||||||
|     {.app = nfc_app, .name = "NFC", .stack_size = 4096, .icon = &A_NFC_14}, |     {.app = nfc_app, | ||||||
|  |      .name = "NFC", | ||||||
|  |      .stack_size = 4096, | ||||||
|  |      .icon = &A_NFC_14, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_INFRARED | #ifdef APP_INFRARED | ||||||
|     {.app = infrared_app, .name = "Infrared", .stack_size = 1024 * 3, .icon = &A_Infrared_14}, |     {.app = infrared_app, | ||||||
|  |      .name = "Infrared", | ||||||
|  |      .stack_size = 1024 * 3, | ||||||
|  |      .icon = &A_Infrared_14, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_GPIO | #ifdef APP_GPIO | ||||||
|     {.app = gpio_app, .name = "GPIO", .stack_size = 1024, .icon = &A_GPIO_14}, |     {.app = gpio_app, | ||||||
|  |      .name = "GPIO", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = &A_GPIO_14, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_IBUTTON | #ifdef APP_IBUTTON | ||||||
|     {.app = ibutton_app, .name = "iButton", .stack_size = 2048, .icon = &A_iButton_14}, |     {.app = ibutton_app, | ||||||
|  |      .name = "iButton", | ||||||
|  |      .stack_size = 2048, | ||||||
|  |      .icon = &A_iButton_14, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_BAD_USB | #ifdef APP_BAD_USB | ||||||
|     {.app = bad_usb_app, .name = "Bad USB", .stack_size = 2048, .icon = &A_BadUsb_14}, |     {.app = bad_usb_app, | ||||||
|  |      .name = "Bad USB", | ||||||
|  |      .stack_size = 2048, | ||||||
|  |      .icon = &A_BadUsb_14, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_U2F | #ifdef APP_U2F | ||||||
|     {.app = u2f_app, .name = "U2F", .stack_size = 2048, .icon = &A_U2F_14}, |     {.app = u2f_app, | ||||||
|  |      .name = "U2F", | ||||||
|  |      .stack_size = 2048, | ||||||
|  |      .icon = &A_U2F_14, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| }; | }; | ||||||
| @ -234,15 +322,27 @@ const size_t FLIPPER_ON_SYSTEM_START_COUNT = COUNT_OF(FLIPPER_ON_SYSTEM_START); | |||||||
| // Plugin menu
 | // Plugin menu
 | ||||||
| const FlipperApplication FLIPPER_PLUGINS[] = { | const FlipperApplication FLIPPER_PLUGINS[] = { | ||||||
| #ifdef APP_BLE_HID | #ifdef APP_BLE_HID | ||||||
|     {.app = bt_hid_app, .name = "Bluetooth Remote", .stack_size = 1024, .icon = NULL}, |     {.app = bt_hid_app, | ||||||
|  |      .name = "Bluetooth Remote", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_MUSIC_PLAYER | #ifdef APP_MUSIC_PLAYER | ||||||
|     {.app = music_player_app, .name = "Music Player", .stack_size = 1024, .icon = &A_Plugins_14}, |     {.app = music_player_app, | ||||||
|  |      .name = "Music Player", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = &A_Plugins_14, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_SNAKE_GAME | #ifdef APP_SNAKE_GAME | ||||||
|     {.app = snake_game_app, .name = "Snake Game", .stack_size = 1024, .icon = &A_Plugins_14}, |     {.app = snake_game_app, | ||||||
|  |      .name = "Snake Game", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = &A_Plugins_14, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -251,108 +351,201 @@ const size_t FLIPPER_PLUGINS_COUNT = COUNT_OF(FLIPPER_PLUGINS); | |||||||
| // Plugin menu
 | // Plugin menu
 | ||||||
| const FlipperApplication FLIPPER_DEBUG_APPS[] = { | const FlipperApplication FLIPPER_DEBUG_APPS[] = { | ||||||
| #ifdef APP_BLINK | #ifdef APP_BLINK | ||||||
|     {.app = blink_test_app, .name = "Blink Test", .stack_size = 1024, .icon = NULL}, |     {.app = blink_test_app, | ||||||
|  |      .name = "Blink Test", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_VIBRO_TEST | #ifdef APP_VIBRO_TEST | ||||||
|     {.app = vibro_test_app, .name = "Vibro Test", .stack_size = 1024, .icon = NULL}, |     {.app = vibro_test_app, | ||||||
|  |      .name = "Vibro Test", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_KEYPAD_TEST | #ifdef APP_KEYPAD_TEST | ||||||
|     {.app = keypad_test_app, .name = "Keypad Test", .stack_size = 1024, .icon = NULL}, |     {.app = keypad_test_app, | ||||||
|  |      .name = "Keypad Test", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_ACCESSOR | #ifdef APP_ACCESSOR | ||||||
|     {.app = accessor_app, .name = "Accessor", .stack_size = 4096, .icon = NULL}, |     {.app = accessor_app, | ||||||
|  |      .name = "Accessor", | ||||||
|  |      .stack_size = 4096, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_USB_TEST | #ifdef APP_USB_TEST | ||||||
|     {.app = usb_test_app, .name = "USB Test", .stack_size = 1024, .icon = NULL}, |     {.app = usb_test_app, | ||||||
|  |      .name = "USB Test", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_USB_MOUSE | #ifdef APP_USB_MOUSE | ||||||
|     {.app = usb_mouse_app, .name = "USB Mouse Demo", .stack_size = 1024, .icon = NULL}, |     {.app = usb_mouse_app, | ||||||
|  |      .name = "USB Mouse Demo", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_UART_ECHO | #ifdef APP_UART_ECHO | ||||||
|     {.app = uart_echo_app, .name = "Uart Echo", .stack_size = 2048, .icon = NULL}, |     {.app = uart_echo_app, | ||||||
|  |      .name = "Uart Echo", | ||||||
|  |      .stack_size = 2048, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_INFRARED_MONITOR | #ifdef APP_INFRARED_MONITOR | ||||||
|     {.app = infrared_monitor_app, .name = "Infrared Monitor", .stack_size = 1024, .icon = NULL}, |     {.app = infrared_monitor_app, | ||||||
|  |      .name = "Infrared Monitor", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_SCENED | #ifdef APP_SCENED | ||||||
|     {.app = scened_app, .name = "Templated Scene", .stack_size = 1024, .icon = NULL}, |     {.app = scened_app, | ||||||
|  |      .name = "Templated Scene", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_LF_RFID | #ifdef APP_LF_RFID | ||||||
|     {.app = lfrfid_debug_app, .name = "LF-RFID Debug", .stack_size = 1024, .icon = NULL}, |     {.app = lfrfid_debug_app, | ||||||
|  |      .name = "LF-RFID Debug", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_BT | #ifdef SRV_BT | ||||||
|     {.app = bt_debug_app, .name = "Bluetooth Debug", .stack_size = 1024, .icon = NULL}, |     {.app = bt_debug_app, | ||||||
|  |      .name = "Bluetooth Debug", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_UNIT_TESTS | #ifdef APP_UNIT_TESTS | ||||||
|     {.app = delay_test_app, .name = "Delay Test", .stack_size = 1024, .icon = NULL}, |     {.app = delay_test_app, | ||||||
|  |      .name = "Delay Test", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_DISPLAY_TEST | #ifdef APP_DISPLAY_TEST | ||||||
|     {.app = display_test_app, .name = "Display Test", .stack_size = 1024, .icon = NULL}, |     {.app = display_test_app, | ||||||
|  |      .name = "Display Test", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_BATTERY_TEST | #ifdef APP_BATTERY_TEST | ||||||
|     {.app = battery_test_app, .name = "Battery Test", .stack_size = 1024, .icon = NULL}, |     {.app = battery_test_app, | ||||||
|  |      .name = "Battery Test", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_TEXT_BOX_TEST | #ifdef APP_TEXT_BOX_TEST | ||||||
|     {.app = text_box_test_app, .name = "Text Box Test", .stack_size = 1024, .icon = NULL}, |     {.app = text_box_test_app, | ||||||
|  |      .name = "Text Box Test", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| const size_t FLIPPER_DEBUG_APPS_COUNT = COUNT_OF(FLIPPER_DEBUG_APPS); | const size_t FLIPPER_DEBUG_APPS_COUNT = COUNT_OF(FLIPPER_DEBUG_APPS); | ||||||
| 
 | 
 | ||||||
| #ifdef APP_ARCHIVE | #ifdef APP_ARCHIVE | ||||||
| const FlipperApplication FLIPPER_ARCHIVE = | const FlipperApplication FLIPPER_ARCHIVE = { | ||||||
|     {.app = archive_app, .name = "Archive", .stack_size = 4096, .icon = &A_FileManager_14}; |     .app = archive_app, | ||||||
|  |     .name = "Archive", | ||||||
|  |     .stack_size = 4096, | ||||||
|  |     .icon = &A_FileManager_14, | ||||||
|  |     .flags = FlipperApplicationFlagDefault}; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| // Settings menu
 | // Settings menu
 | ||||||
| const FlipperApplication FLIPPER_SETTINGS_APPS[] = { | const FlipperApplication FLIPPER_SETTINGS_APPS[] = { | ||||||
| #ifdef SRV_BT | #ifdef SRV_BT | ||||||
|     {.app = bt_settings_app, .name = "Bluetooth", .stack_size = 1024, .icon = NULL}, |     {.app = bt_settings_app, | ||||||
|  |      .name = "Bluetooth", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_NOTIFICATION | #ifdef SRV_NOTIFICATION | ||||||
|     {.app = notification_settings_app, |     {.app = notification_settings_app, | ||||||
|      .name = "LCD and Notifications", |      .name = "LCD and Notifications", | ||||||
|      .stack_size = 1024, |      .stack_size = 1024, | ||||||
|      .icon = NULL}, |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_STORAGE | #ifdef SRV_STORAGE | ||||||
|     {.app = storage_settings_app, .name = "Storage", .stack_size = 2048, .icon = NULL}, |     {.app = storage_settings_app, | ||||||
|  |      .name = "Storage", | ||||||
|  |      .stack_size = 2048, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_POWER | #ifdef SRV_POWER | ||||||
|     {.app = power_settings_app, .name = "Power", .stack_size = 1024, .icon = NULL}, |     {.app = power_settings_app, | ||||||
|  |      .name = "Power", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagInsomniaSafe}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_DESKTOP | #ifdef SRV_DESKTOP | ||||||
|     {.app = desktop_settings_app, .name = "Desktop", .stack_size = 1024, .icon = NULL}, |     {.app = desktop_settings_app, | ||||||
|  |      .name = "Desktop", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_PASSPORT | #ifdef APP_PASSPORT | ||||||
|     {.app = passport_app, .name = "Passport", .stack_size = 1024, .icon = NULL}, |     {.app = passport_app, | ||||||
|  |      .name = "Passport", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef SRV_GUI | #ifdef SRV_GUI | ||||||
|     {.app = system_settings_app, .name = "System", .stack_size = 1024, .icon = NULL}, |     {.app = system_settings_app, | ||||||
|  |      .name = "System", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| #ifdef APP_ABOUT | #ifdef APP_ABOUT | ||||||
|     {.app = about_settings_app, .name = "About", .stack_size = 1024, .icon = NULL}, |     {.app = about_settings_app, | ||||||
|  |      .name = "About", | ||||||
|  |      .stack_size = 1024, | ||||||
|  |      .icon = NULL, | ||||||
|  |      .flags = FlipperApplicationFlagDefault}, | ||||||
| #endif | #endif | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -3,11 +3,17 @@ | |||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include <gui/icon.h> | #include <gui/icon.h> | ||||||
| 
 | 
 | ||||||
|  | typedef enum { | ||||||
|  |     FlipperApplicationFlagDefault = 0, | ||||||
|  |     FlipperApplicationFlagInsomniaSafe = (1 << 0), | ||||||
|  | } FlipperApplicationFlag; | ||||||
|  | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     const FuriThreadCallback app; |     const FuriThreadCallback app; | ||||||
|     const char* name; |     const char* name; | ||||||
|     const size_t stack_size; |     const size_t stack_size; | ||||||
|     const Icon* icon; |     const Icon* icon; | ||||||
|  |     const FlipperApplicationFlag flags; | ||||||
| } FlipperApplication; | } FlipperApplication; | ||||||
| 
 | 
 | ||||||
| typedef void (*FlipperOnStartHook)(void); | typedef void (*FlipperOnStartHook)(void); | ||||||
|  | |||||||
| @ -17,8 +17,6 @@ const CanvasFontParameters canvas_font_params[FontTotalNumber] = { | |||||||
| Canvas* canvas_init() { | Canvas* canvas_init() { | ||||||
|     Canvas* canvas = malloc(sizeof(Canvas)); |     Canvas* canvas = malloc(sizeof(Canvas)); | ||||||
| 
 | 
 | ||||||
|     furi_hal_power_insomnia_enter(); |  | ||||||
| 
 |  | ||||||
|     // Setup u8g2
 |     // Setup u8g2
 | ||||||
|     u8g2_Setup_st756x_flipper(&canvas->fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32); |     u8g2_Setup_st756x_flipper(&canvas->fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32); | ||||||
|     canvas->orientation = CanvasOrientationHorizontal; |     canvas->orientation = CanvasOrientationHorizontal; | ||||||
| @ -31,8 +29,6 @@ Canvas* canvas_init() { | |||||||
|     canvas_clear(canvas); |     canvas_clear(canvas); | ||||||
|     canvas_commit(canvas); |     canvas_commit(canvas); | ||||||
| 
 | 
 | ||||||
|     furi_hal_power_insomnia_exit(); |  | ||||||
| 
 |  | ||||||
|     return canvas; |     return canvas; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -41,7 +41,6 @@ iButtonApp::iButtonApp() | |||||||
|     : notification{"notification"} |     : notification{"notification"} | ||||||
|     , storage{"storage"} |     , storage{"storage"} | ||||||
|     , dialogs{"dialogs"} { |     , dialogs{"dialogs"} { | ||||||
|     furi_hal_power_insomnia_enter(); |  | ||||||
|     key = ibutton_key_alloc(); |     key = ibutton_key_alloc(); | ||||||
|     key_worker = ibutton_worker_alloc(); |     key_worker = ibutton_worker_alloc(); | ||||||
|     ibutton_worker_start_thread(key_worker); |     ibutton_worker_start_thread(key_worker); | ||||||
| @ -56,8 +55,6 @@ iButtonApp::~iButtonApp() { | |||||||
|     ibutton_worker_stop_thread(key_worker); |     ibutton_worker_stop_thread(key_worker); | ||||||
|     ibutton_worker_free(key_worker); |     ibutton_worker_free(key_worker); | ||||||
|     ibutton_key_free(key); |     ibutton_key_free(key); | ||||||
| 
 |  | ||||||
|     furi_hal_power_insomnia_exit(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| iButtonAppViewManager* iButtonApp::get_view_manager() { | iButtonAppViewManager* iButtonApp::get_view_manager() { | ||||||
|  | |||||||
| @ -31,11 +31,9 @@ LfRfidApp::LfRfidApp() | |||||||
|     , storage{"storage"} |     , storage{"storage"} | ||||||
|     , dialogs{"dialogs"} |     , dialogs{"dialogs"} | ||||||
|     , text_store(40) { |     , text_store(40) { | ||||||
|     furi_hal_power_insomnia_enter(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| LfRfidApp::~LfRfidApp() { | LfRfidApp::~LfRfidApp() { | ||||||
|     furi_hal_power_insomnia_exit(); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void LfRfidApp::run(void* _args) { | void LfRfidApp::run(void* _args) { | ||||||
|  | |||||||
| @ -238,7 +238,10 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con | |||||||
|     if(thread_state == FuriThreadStateRunning) { |     if(thread_state == FuriThreadStateRunning) { | ||||||
|         event.type = LoaderEventTypeApplicationStarted; |         event.type = LoaderEventTypeApplicationStarted; | ||||||
|         furi_pubsub_publish(loader_instance->pubsub, &event); |         furi_pubsub_publish(loader_instance->pubsub, &event); | ||||||
|  | 
 | ||||||
|  |         if(!loader_instance->application->flags & FlipperApplicationFlagInsomniaSafe) { | ||||||
|             furi_hal_power_insomnia_enter(); |             furi_hal_power_insomnia_enter(); | ||||||
|  |         } | ||||||
|     } else if(thread_state == FuriThreadStateStopped) { |     } else if(thread_state == FuriThreadStateStopped) { | ||||||
|         FURI_LOG_I( |         FURI_LOG_I( | ||||||
|             TAG, |             TAG, | ||||||
| @ -251,7 +254,9 @@ static void loader_thread_state_callback(FuriThreadState thread_state, void* con | |||||||
|             loader_instance->application_arguments = NULL; |             loader_instance->application_arguments = NULL; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         if(!loader_instance->application->flags & FlipperApplicationFlagInsomniaSafe) { | ||||||
|             furi_hal_power_insomnia_exit(); |             furi_hal_power_insomnia_exit(); | ||||||
|  |         } | ||||||
|         loader_unlock(instance); |         loader_unlock(instance); | ||||||
| 
 | 
 | ||||||
|         event.type = LoaderEventTypeApplicationStopped; |         event.type = LoaderEventTypeApplicationStopped; | ||||||
|  | |||||||
| @ -86,7 +86,6 @@ void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state) { | |||||||
| int32_t nfc_worker_task(void* context) { | int32_t nfc_worker_task(void* context) { | ||||||
|     NfcWorker* nfc_worker = context; |     NfcWorker* nfc_worker = context; | ||||||
| 
 | 
 | ||||||
|     furi_hal_power_insomnia_enter(); |  | ||||||
|     furi_hal_nfc_exit_sleep(); |     furi_hal_nfc_exit_sleep(); | ||||||
| 
 | 
 | ||||||
|     if(nfc_worker->state == NfcWorkerStateDetect) { |     if(nfc_worker->state == NfcWorkerStateDetect) { | ||||||
| @ -110,7 +109,6 @@ int32_t nfc_worker_task(void* context) { | |||||||
|     } |     } | ||||||
|     furi_hal_nfc_sleep(); |     furi_hal_nfc_sleep(); | ||||||
|     nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); |     nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); | ||||||
|     furi_hal_power_insomnia_exit(); |  | ||||||
| 
 | 
 | ||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  | |||||||
| @ -39,12 +39,10 @@ void storage_data_init(StorageData* storage) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool storage_data_lock(StorageData* storage) { | bool storage_data_lock(StorageData* storage) { | ||||||
|     furi_hal_power_insomnia_enter(); |  | ||||||
|     return (osMutexAcquire(storage->mutex, osWaitForever) == osOK); |     return (osMutexAcquire(storage->mutex, osWaitForever) == osOK); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool storage_data_unlock(StorageData* storage) { | bool storage_data_unlock(StorageData* storage) { | ||||||
|     furi_hal_power_insomnia_exit(); |  | ||||||
|     return (osMutexRelease(storage->mutex) == osOK); |     return (osMutexRelease(storage->mutex) == osOK); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -396,7 +396,7 @@ typedef enum { | |||||||
|  * keep debugger enabled while in any low power mode when set to 1 |  * keep debugger enabled while in any low power mode when set to 1 | ||||||
|  * should be set to 0 in production |  * should be set to 0 in production | ||||||
|  */ |  */ | ||||||
| #define CFG_DEBUGGER_SUPPORTED 0 | #define CFG_DEBUGGER_SUPPORTED 1 | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
|  * When set to 1, the traces are enabled in the BLE services |  * When set to 1, the traces are enabled in the BLE services | ||||||
|  | |||||||
| @ -1,25 +1,3 @@ | |||||||
| /* USER CODE BEGIN Header */ |  | ||||||
| /**
 |  | ||||||
|  ****************************************************************************** |  | ||||||
|   * File Name          : app_debug.c |  | ||||||
|   * Description        : Debug capabilities source file for STM32WPAN Middleware |  | ||||||
|  ****************************************************************************** |  | ||||||
|   * @attention |  | ||||||
|   * |  | ||||||
|   * <h2><center>© Copyright (c) 2020 STMicroelectronics. |  | ||||||
|   * All rights reserved.</center></h2> |  | ||||||
|   * |  | ||||||
|   * This software component is licensed by ST under Ultimate Liberty license |  | ||||||
|   * SLA0044, the "License"; You may not use this file except in compliance with |  | ||||||
|   * the License. You may obtain a copy of the License at: |  | ||||||
|   *                             www.st.com/SLA0044 |  | ||||||
|   * |  | ||||||
|  ****************************************************************************** |  | ||||||
|  */ |  | ||||||
| /* USER CODE END Header */ |  | ||||||
| 
 |  | ||||||
| /* Includes ------------------------------------------------------------------*/ |  | ||||||
| /* USER CODE BEGIN Includes */ |  | ||||||
| #include "utilities_common.h" | #include "utilities_common.h" | ||||||
| 
 | 
 | ||||||
| #include "app_common.h" | #include "app_common.h" | ||||||
| @ -28,10 +6,7 @@ | |||||||
| #include "tl.h" | #include "tl.h" | ||||||
| #include "dbg_trace.h" | #include "dbg_trace.h" | ||||||
| #include <furi_hal.h> | #include <furi_hal.h> | ||||||
| /* USER CODE END Includes */ |  | ||||||
| 
 | 
 | ||||||
| /* Private typedef -----------------------------------------------------------*/ |  | ||||||
| /* USER CODE BEGIN PTD */ |  | ||||||
| typedef PACKED_STRUCT { | typedef PACKED_STRUCT { | ||||||
|     GPIO_TypeDef* port; |     GPIO_TypeDef* port; | ||||||
|     uint16_t pin; |     uint16_t pin; | ||||||
| @ -39,10 +14,7 @@ typedef PACKED_STRUCT { | |||||||
|     uint8_t reserved; |     uint8_t reserved; | ||||||
| } | } | ||||||
| APPD_GpioConfig_t; | APPD_GpioConfig_t; | ||||||
| /* USER CODE END PTD */ |  | ||||||
| 
 | 
 | ||||||
| /* Private defines -----------------------------------------------------------*/ |  | ||||||
| /* USER CODE BEGIN PD */ |  | ||||||
| #define GPIO_NBR_OF_RF_SIGNALS 9 | #define GPIO_NBR_OF_RF_SIGNALS 9 | ||||||
| #define GPIO_CFG_NBR_OF_FEATURES 34 | #define GPIO_CFG_NBR_OF_FEATURES 34 | ||||||
| #define NBR_OF_TRACES_CONFIG_PARAMETERS 4 | #define NBR_OF_TRACES_CONFIG_PARAMETERS 4 | ||||||
| @ -51,12 +23,11 @@ APPD_GpioConfig_t; | |||||||
| /**
 | /**
 | ||||||
|  * THIS SHALL BE SET TO A VALUE DIFFERENT FROM 0 ONLY ON REQUEST FROM ST SUPPORT |  * THIS SHALL BE SET TO A VALUE DIFFERENT FROM 0 ONLY ON REQUEST FROM ST SUPPORT | ||||||
|  */ |  */ | ||||||
| #define BLE_DTB_CFG 7 | #define BLE_DTB_CFG 0 | ||||||
|  | // #define BLE_DTB_CFG 7
 | ||||||
| #define SYS_DBG_CFG1 (SHCI_C2_DEBUG_OPTIONS_IPCORE_LP | SHCI_C2_DEBUG_OPTIONS_CPU2_STOP_EN) | #define SYS_DBG_CFG1 (SHCI_C2_DEBUG_OPTIONS_IPCORE_LP | SHCI_C2_DEBUG_OPTIONS_CPU2_STOP_EN) | ||||||
| /* USER CODE END PD */ |  | ||||||
| 
 | 
 | ||||||
| /* Private variables ---------------------------------------------------------*/ | /* Private variables ---------------------------------------------------------*/ | ||||||
| /* USER CODE BEGIN PV */ |  | ||||||
| PLACE_IN_SECTION("MB_MEM2") | PLACE_IN_SECTION("MB_MEM2") | ||||||
| ALIGN(4) static SHCI_C2_DEBUG_TracesConfig_t APPD_TracesConfig = {0, 0, 0, 0}; | ALIGN(4) static SHCI_C2_DEBUG_TracesConfig_t APPD_TracesConfig = {0, 0, 0, 0}; | ||||||
| PLACE_IN_SECTION("MB_MEM2") | PLACE_IN_SECTION("MB_MEM2") | ||||||
| @ -91,7 +62,7 @@ static const APPD_GpioConfig_t aGpioConfigList[GPIO_CFG_NBR_OF_FEATURES] = { | |||||||
|     {GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_TRACES_TX - Set on Entry / Reset on Exit */ |     {GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IPCC_TRACES_TX - Set on Entry / Reset on Exit */ | ||||||
|     {GPIOA, LL_GPIO_PIN_6, 1, 0}, /* HARD_FAULT - Set on Entry / Reset on Exit */ |     {GPIOA, LL_GPIO_PIN_6, 1, 0}, /* HARD_FAULT - Set on Entry / Reset on Exit */ | ||||||
|     /* From v1.1.1 */ |     /* From v1.1.1 */ | ||||||
|     {GPIOA, LL_GPIO_PIN_0, 0, 0}, /* IP_CORE_LP_STATUS - Set on Entry / Reset on Exit */ |     {GPIOC, LL_GPIO_PIN_1, 1, 0}, /* IP_CORE_LP_STATUS - Set on Entry / Reset on Exit */ | ||||||
|     /* From v1.2.0 */ |     /* From v1.2.0 */ | ||||||
|     {GPIOA, LL_GPIO_PIN_0, 0, 0}, /* END_OF_CONNECTION_EVENT - Set on Entry / Reset on Exit */ |     {GPIOA, LL_GPIO_PIN_0, 0, 0}, /* END_OF_CONNECTION_EVENT - Set on Entry / Reset on Exit */ | ||||||
|     {GPIOA, LL_GPIO_PIN_0, 0, 0}, /* TIMER_SERVER_CALLBACK - Toggle on Entry */ |     {GPIOA, LL_GPIO_PIN_0, 0, 0}, /* TIMER_SERVER_CALLBACK - Toggle on Entry */ | ||||||
| @ -130,65 +101,20 @@ static const APPD_GpioConfig_t aRfConfigList[GPIO_NBR_OF_RF_SIGNALS] = { | |||||||
|     {GPIOB, LL_GPIO_PIN_10, 0, 0}, /* DTB18 - FSM4 */ |     {GPIOB, LL_GPIO_PIN_10, 0, 0}, /* DTB18 - FSM4 */ | ||||||
| }; | }; | ||||||
| #endif | #endif | ||||||
| /* USER CODE END PV */ |  | ||||||
| 
 | 
 | ||||||
| /* Global variables ----------------------------------------------------------*/ |  | ||||||
| /* USER CODE BEGIN GV */ |  | ||||||
| /* USER CODE END GV */ |  | ||||||
| 
 |  | ||||||
| /* Private function prototypes -----------------------------------------------*/ |  | ||||||
| /* USER CODE BEGIN PFP */ |  | ||||||
| static void APPD_SetCPU2GpioConfig(void); | static void APPD_SetCPU2GpioConfig(void); | ||||||
| static void APPD_BleDtbCfg(void); | static void APPD_BleDtbCfg(void); | ||||||
| /* USER CODE END PFP */ |  | ||||||
| 
 |  | ||||||
| /* Functions Definition ------------------------------------------------------*/ |  | ||||||
| void APPD_Init(void) { |  | ||||||
| /* USER CODE BEGIN APPD_Init */ |  | ||||||
| #if(CFG_DEBUGGER_SUPPORTED == 1) |  | ||||||
|     /**
 |  | ||||||
|    * Keep debugger enabled while in any low power mode |  | ||||||
|    */ |  | ||||||
|     LL_DBGMCU_EnableDBGSleepMode(); |  | ||||||
|     LL_DBGMCU_EnableDBGStopMode(); |  | ||||||
| 
 |  | ||||||
|     /***************** ENABLE DEBUGGER *************************************/ |  | ||||||
|     LL_EXTI_EnableIT_32_63(LL_EXTI_LINE_48); |  | ||||||
| 
 |  | ||||||
| #else |  | ||||||
|     LL_GPIO_InitTypeDef gpio_config = {0}; |  | ||||||
|     LL_PWR_EnableVddUSB(); |  | ||||||
| 
 |  | ||||||
|     gpio_config.Mode = LL_GPIO_MODE_ANALOG; |  | ||||||
|     gpio_config.Speed = LL_GPIO_SPEED_FREQ_LOW; |  | ||||||
|     // gpio_config.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
 |  | ||||||
|     // gpio_config.Pull = LL_GPIO_PULL_NO;
 |  | ||||||
|     // gpio_config.Alternate = LL_GPIO_AF_10;
 |  | ||||||
|     gpio_config.Pin = LL_GPIO_PIN_15 | LL_GPIO_PIN_14 | LL_GPIO_PIN_13; |  | ||||||
|     LL_GPIO_Init(GPIOA, &gpio_config); |  | ||||||
| 
 |  | ||||||
|     gpio_config.Pin = LL_GPIO_PIN_4 | LL_GPIO_PIN_3; |  | ||||||
|     LL_GPIO_Init(GPIOB, &gpio_config); |  | ||||||
| 
 |  | ||||||
|     LL_DBGMCU_DisableDBGSleepMode(); |  | ||||||
|     LL_DBGMCU_DisableDBGStopMode(); |  | ||||||
|     LL_DBGMCU_DisableDBGStandbyMode(); |  | ||||||
| 
 |  | ||||||
| #endif /* (CFG_DEBUGGER_SUPPORTED == 1) */ |  | ||||||
| 
 | 
 | ||||||
|  | void APPD_Init() { | ||||||
| #if(CFG_DEBUG_TRACE != 0) | #if(CFG_DEBUG_TRACE != 0) | ||||||
|     DbgTraceInit(); |     DbgTraceInit(); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     APPD_SetCPU2GpioConfig(); |     APPD_SetCPU2GpioConfig(); | ||||||
|     APPD_BleDtbCfg(); |     APPD_BleDtbCfg(); | ||||||
| 
 |  | ||||||
|     /* USER CODE END APPD_Init */ |  | ||||||
|     return; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void APPD_EnableCPU2(void) { | void APPD_EnableCPU2(void) { | ||||||
|     /* USER CODE BEGIN APPD_EnableCPU2 */ |  | ||||||
|     SHCI_C2_DEBUG_Init_Cmd_Packet_t DebugCmdPacket = { |     SHCI_C2_DEBUG_Init_Cmd_Packet_t DebugCmdPacket = { | ||||||
|         {{0, 0, 0}}, /**< Does not need to be initialized */ |         {{0, 0, 0}}, /**< Does not need to be initialized */ | ||||||
|         {(uint8_t*)aGpioConfigList, |         {(uint8_t*)aGpioConfigList, | ||||||
| @ -204,6 +130,7 @@ void APPD_EnableCPU2(void) { | |||||||
|     /** GPIO DEBUG Initialization */ |     /** GPIO DEBUG Initialization */ | ||||||
|     SHCI_C2_DEBUG_Init(&DebugCmdPacket); |     SHCI_C2_DEBUG_Init(&DebugCmdPacket); | ||||||
| 
 | 
 | ||||||
|  |     // We don't need External Power Amplifier
 | ||||||
|     // LL_GPIO_InitTypeDef  gpio_config;
 |     // LL_GPIO_InitTypeDef  gpio_config;
 | ||||||
|     // gpio_config.Pull = GPIO_NOPULL;
 |     // gpio_config.Pull = GPIO_NOPULL;
 | ||||||
|     // gpio_config.Mode = GPIO_MODE_OUTPUT_PP;
 |     // gpio_config.Mode = GPIO_MODE_OUTPUT_PP;
 | ||||||
| @ -212,17 +139,10 @@ void APPD_EnableCPU2(void) { | |||||||
|     // HAL_GPIO_Init(GPIOC, &gpio_config);
 |     // HAL_GPIO_Init(GPIOC, &gpio_config);
 | ||||||
|     // SHCI_C2_ExtpaConfig((uint32_t)GPIOC, LL_GPIO_PIN_3, EXT_PA_ENABLED_LOW, EXT_PA_ENABLED);
 |     // SHCI_C2_ExtpaConfig((uint32_t)GPIOC, LL_GPIO_PIN_3, EXT_PA_ENABLED_LOW, EXT_PA_ENABLED);
 | ||||||
| 
 | 
 | ||||||
|     /* USER CODE END APPD_EnableCPU2 */ |  | ||||||
|     return; |     return; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*************************************************************
 |  | ||||||
|  * |  | ||||||
|  * LOCAL FUNCTIONS |  | ||||||
|  * |  | ||||||
|  *************************************************************/ |  | ||||||
| static void APPD_SetCPU2GpioConfig(void) { | static void APPD_SetCPU2GpioConfig(void) { | ||||||
|     /* USER CODE BEGIN APPD_SetCPU2GpioConfig */ |  | ||||||
|     LL_GPIO_InitTypeDef gpio_config = {0}; |     LL_GPIO_InitTypeDef gpio_config = {0}; | ||||||
|     uint8_t local_loop; |     uint8_t local_loop; | ||||||
|     uint16_t gpioa_pin_list; |     uint16_t gpioa_pin_list; | ||||||
| @ -259,8 +179,9 @@ static void APPD_SetCPU2GpioConfig(void) { | |||||||
|     gpio_config.OutputType = LL_GPIO_OUTPUT_PUSHPULL; |     gpio_config.OutputType = LL_GPIO_OUTPUT_PUSHPULL; | ||||||
|     gpio_config.Pull = LL_GPIO_PULL_NO; |     gpio_config.Pull = LL_GPIO_PULL_NO; | ||||||
| 
 | 
 | ||||||
|     gpio_config.Pin = LL_GPIO_PIN_15 | LL_GPIO_PIN_14 | LL_GPIO_PIN_13; |     // Never disable SWD, why would you?
 | ||||||
|     LL_GPIO_Init(GPIOA, &gpio_config); |     // gpio_config.Pin = LL_GPIO_PIN_15 | LL_GPIO_PIN_14 | LL_GPIO_PIN_13;
 | ||||||
|  |     // LL_GPIO_Init(GPIOA, &gpio_config);
 | ||||||
| 
 | 
 | ||||||
|     if(gpioa_pin_list != 0) { |     if(gpioa_pin_list != 0) { | ||||||
|         gpio_config.Pin = gpioa_pin_list; |         gpio_config.Pin = gpioa_pin_list; | ||||||
| @ -282,13 +203,9 @@ static void APPD_SetCPU2GpioConfig(void) { | |||||||
|         LL_GPIO_Init(GPIOC, &gpio_config); |         LL_GPIO_Init(GPIOC, &gpio_config); | ||||||
|         LL_GPIO_ResetOutputPin(GPIOC, gpioa_pin_list); |         LL_GPIO_ResetOutputPin(GPIOC, gpioa_pin_list); | ||||||
|     } |     } | ||||||
| 
 |  | ||||||
|     /* USER CODE END APPD_SetCPU2GpioConfig */ |  | ||||||
|     return; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void APPD_BleDtbCfg(void) { | static void APPD_BleDtbCfg(void) { | ||||||
| /* USER CODE BEGIN APPD_BleDtbCfg */ |  | ||||||
| #if(BLE_DTB_CFG != 0) | #if(BLE_DTB_CFG != 0) | ||||||
|     LL_GPIO_InitTypeDef gpio_config = {0}; |     LL_GPIO_InitTypeDef gpio_config = {0}; | ||||||
|     uint8_t local_loop; |     uint8_t local_loop; | ||||||
| @ -304,11 +221,9 @@ static void APPD_BleDtbCfg(void) { | |||||||
|             case(uint32_t)GPIOA: |             case(uint32_t)GPIOA: | ||||||
|                 gpioa_pin_list |= aRfConfigList[local_loop].pin; |                 gpioa_pin_list |= aRfConfigList[local_loop].pin; | ||||||
|                 break; |                 break; | ||||||
| 
 |  | ||||||
|             case(uint32_t)GPIOB: |             case(uint32_t)GPIOB: | ||||||
|                 gpiob_pin_list |= aRfConfigList[local_loop].pin; |                 gpiob_pin_list |= aRfConfigList[local_loop].pin; | ||||||
|                 break; |                 break; | ||||||
| 
 |  | ||||||
|             default: |             default: | ||||||
|                 break; |                 break; | ||||||
|             } |             } | ||||||
| @ -334,16 +249,8 @@ static void APPD_BleDtbCfg(void) { | |||||||
|         LL_GPIO_Init(GPIOB, &gpio_config); |         LL_GPIO_Init(GPIOB, &gpio_config); | ||||||
|     } |     } | ||||||
| #endif | #endif | ||||||
| 
 |  | ||||||
|     /* USER CODE END APPD_BleDtbCfg */ |  | ||||||
|     return; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /*************************************************************
 |  | ||||||
|  * |  | ||||||
|  * WRAP FUNCTIONS |  | ||||||
|  * |  | ||||||
| *************************************************************/ |  | ||||||
| #if(CFG_DEBUG_TRACE != 0) | #if(CFG_DEBUG_TRACE != 0) | ||||||
| void DbgOutputInit(void) { | void DbgOutputInit(void) { | ||||||
| } | } | ||||||
| @ -353,5 +260,3 @@ void DbgOutputTraces(uint8_t* p_data, uint16_t size, void (*cb)(void)) { | |||||||
|     cb(); |     cb(); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 |  | ||||||
| /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ |  | ||||||
|  | |||||||
| @ -63,9 +63,10 @@ void ble_glue_init() { | |||||||
|     LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI); |     LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI); | ||||||
|     /* Initialize the CPU2 reset value before starting CPU2 with C2BOOT */ |     /* Initialize the CPU2 reset value before starting CPU2 with C2BOOT */ | ||||||
|     LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); |     LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); | ||||||
|     furi_hal_power_insomnia_enter(); |  | ||||||
| 
 | 
 | ||||||
|     // APPD_Init();
 | #ifdef BLE_GLUE_DEBUG | ||||||
|  |     APPD_Init(); | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|     // Initialize all transport layers
 |     // Initialize all transport layers
 | ||||||
|     TL_MM_Config_t tl_mm_config; |     TL_MM_Config_t tl_mm_config; | ||||||
| @ -198,7 +199,6 @@ bool ble_glue_start() { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     bool ret = false; |     bool ret = false; | ||||||
|     furi_hal_power_insomnia_enter(); |  | ||||||
|     if(ble_app_init()) { |     if(ble_app_init()) { | ||||||
|         FURI_LOG_I(TAG, "Radio stack started"); |         FURI_LOG_I(TAG, "Radio stack started"); | ||||||
|         ble_glue->status = BleGlueStatusRadioStackRunning; |         ble_glue->status = BleGlueStatusRadioStackRunning; | ||||||
| @ -213,7 +213,6 @@ bool ble_glue_start() { | |||||||
|         ble_glue->status = BleGlueStatusRadioStackMissing; |         ble_glue->status = BleGlueStatusRadioStackMissing; | ||||||
|         ble_app_thread_stop(); |         ble_app_thread_stop(); | ||||||
|     } |     } | ||||||
|     furi_hal_power_insomnia_exit(); |  | ||||||
| 
 | 
 | ||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| @ -293,8 +292,10 @@ static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status) { | |||||||
|  */ |  */ | ||||||
| static void ble_glue_sys_user_event_callback(void* pPayload) { | static void ble_glue_sys_user_event_callback(void* pPayload) { | ||||||
|     UNUSED(pPayload); |     UNUSED(pPayload); | ||||||
|     /* Traces channel initialization */ | 
 | ||||||
|     // APPD_EnableCPU2( );
 | #ifdef BLE_GLUE_DEBUG | ||||||
|  |     APPD_EnableCPU2(); | ||||||
|  | #endif | ||||||
| 
 | 
 | ||||||
|     TL_AsynchEvt_t* p_sys_event = |     TL_AsynchEvt_t* p_sys_event = | ||||||
|         (TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload); |         (TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload); | ||||||
| @ -309,10 +310,8 @@ static void ble_glue_sys_user_event_callback(void* pPayload) { | |||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         ble_glue->status = BleGlueStatusC2Started; |         ble_glue->status = BleGlueStatusC2Started; | ||||||
|         furi_hal_power_insomnia_exit(); |  | ||||||
|     } else if(p_sys_event->subevtcode == SHCI_SUB_EVT_ERROR_NOTIF) { |     } else if(p_sys_event->subevtcode == SHCI_SUB_EVT_ERROR_NOTIF) { | ||||||
|         FURI_LOG_E(TAG, "Error during initialization"); |         FURI_LOG_E(TAG, "Error during initialization"); | ||||||
|         furi_hal_power_insomnia_exit(); |  | ||||||
|     } else if(p_sys_event->subevtcode == SHCI_SUB_EVT_BLE_NVM_RAM_UPDATE) { |     } else if(p_sys_event->subevtcode == SHCI_SUB_EVT_BLE_NVM_RAM_UPDATE) { | ||||||
|         SHCI_C2_BleNvmRamUpdate_Evt_t* p_sys_ble_nvm_ram_update_event = |         SHCI_C2_BleNvmRamUpdate_Evt_t* p_sys_ble_nvm_ram_update_event = | ||||||
|             (SHCI_C2_BleNvmRamUpdate_Evt_t*)p_sys_event->payload; |             (SHCI_C2_BleNvmRamUpdate_Evt_t*)p_sys_event->payload; | ||||||
|  | |||||||
| @ -115,7 +115,6 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { | |||||||
|         if(gap->enable_adv) { |         if(gap->enable_adv) { | ||||||
|             // Restart advertising
 |             // Restart advertising
 | ||||||
|             gap_advertise_start(GapStateAdvFast); |             gap_advertise_start(GapStateAdvFast); | ||||||
|             furi_hal_power_insomnia_exit(); |  | ||||||
|         } |         } | ||||||
|         GapEvent event = {.type = GapEventTypeDisconnected}; |         GapEvent event = {.type = GapEventTypeDisconnected}; | ||||||
|         gap->on_event_cb(event, gap->context); |         gap->on_event_cb(event, gap->context); | ||||||
| @ -151,8 +150,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { | |||||||
|             } |             } | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case EVT_LE_CONN_COMPLETE: |         case EVT_LE_CONN_COMPLETE: { | ||||||
|             furi_hal_power_insomnia_enter(); |  | ||||||
|             hci_le_connection_complete_event_rp0* event = |             hci_le_connection_complete_event_rp0* event = | ||||||
|                 (hci_le_connection_complete_event_rp0*)meta_evt->data; |                 (hci_le_connection_complete_event_rp0*)meta_evt->data; | ||||||
|             gap->connection_params.conn_interval = event->Conn_Interval; |             gap->connection_params.conn_interval = event->Conn_Interval; | ||||||
| @ -169,7 +167,7 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { | |||||||
|             gap_verify_connection_parameters(gap); |             gap_verify_connection_parameters(gap); | ||||||
|             // Start pairing by sending security request
 |             // Start pairing by sending security request
 | ||||||
|             aci_gap_slave_security_req(event->Connection_Handle); |             aci_gap_slave_security_req(event->Connection_Handle); | ||||||
|             break; |         } break; | ||||||
| 
 | 
 | ||||||
|         case EVT_LE_ADVERTISING_REPORT: { |         case EVT_LE_ADVERTISING_REPORT: { | ||||||
|             if(gap_scan) { |             if(gap_scan) { | ||||||
| @ -414,7 +412,9 @@ static void gap_advertise_start(GapState new_state) { | |||||||
|         // Stop advertising
 |         // Stop advertising
 | ||||||
|         status = aci_gap_set_non_discoverable(); |         status = aci_gap_set_non_discoverable(); | ||||||
|         if(status) { |         if(status) { | ||||||
|             FURI_LOG_E(TAG, "Stop Advertising Failed, result: %d", status); |             FURI_LOG_E(TAG, "set_non_discoverable failed %d", status); | ||||||
|  |         } else { | ||||||
|  |             FURI_LOG_D(TAG, "set_non_discoverable success"); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|     // Configure advertising
 |     // Configure advertising
 | ||||||
| @ -431,7 +431,7 @@ static void gap_advertise_start(GapState new_state) { | |||||||
|         0, |         0, | ||||||
|         0); |         0); | ||||||
|     if(status) { |     if(status) { | ||||||
|         FURI_LOG_E(TAG, "Set discoverable err: %d", status); |         FURI_LOG_E(TAG, "set_discoverable failed %d", status); | ||||||
|     } |     } | ||||||
|     gap->state = new_state; |     gap->state = new_state; | ||||||
|     GapEvent event = {.type = GapEventTypeStartAdvertising}; |     GapEvent event = {.type = GapEventTypeStartAdvertising}; | ||||||
| @ -440,14 +440,25 @@ static void gap_advertise_start(GapState new_state) { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void gap_advertise_stop() { | static void gap_advertise_stop() { | ||||||
|  |     tBleStatus ret; | ||||||
|     if(gap->state > GapStateIdle) { |     if(gap->state > GapStateIdle) { | ||||||
|         if(gap->state == GapStateConnected) { |         if(gap->state == GapStateConnected) { | ||||||
|             // Terminate connection
 |             // Terminate connection
 | ||||||
|             aci_gap_terminate(gap->service.connection_handle, 0x13); |             ret = aci_gap_terminate(gap->service.connection_handle, 0x13); | ||||||
|  |             if(ret != BLE_STATUS_SUCCESS) { | ||||||
|  |                 FURI_LOG_E(TAG, "terminate failed %d", ret); | ||||||
|  |             } else { | ||||||
|  |                 FURI_LOG_D(TAG, "terminate success"); | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         // Stop advertising
 |         // Stop advertising
 | ||||||
|         osTimerStop(gap->advertise_timer); |         osTimerStop(gap->advertise_timer); | ||||||
|         aci_gap_set_non_discoverable(); |         ret = aci_gap_set_non_discoverable(); | ||||||
|  |         if(ret != BLE_STATUS_SUCCESS) { | ||||||
|  |             FURI_LOG_E(TAG, "set_non_discoverable failed %d", ret); | ||||||
|  |         } else { | ||||||
|  |             FURI_LOG_D(TAG, "set_non_discoverable success"); | ||||||
|  |         } | ||||||
|         gap->state = GapStateIdle; |         gap->state = GapStateIdle; | ||||||
|     } |     } | ||||||
|     GapEvent event = {.type = GapEventTypeStopAdvertising}; |     GapEvent event = {.type = GapEventTypeStopAdvertising}; | ||||||
|  | |||||||
| @ -10,10 +10,10 @@ void furi_hal_init_early() { | |||||||
|     furi_hal_clock_init_early(); |     furi_hal_clock_init_early(); | ||||||
|     furi_hal_delay_init(); |     furi_hal_delay_init(); | ||||||
| 
 | 
 | ||||||
|     furi_hal_os_init(); |  | ||||||
| 
 |  | ||||||
|     furi_hal_resources_init_early(); |     furi_hal_resources_init_early(); | ||||||
| 
 | 
 | ||||||
|  |     furi_hal_os_init(); | ||||||
|  | 
 | ||||||
|     furi_hal_spi_init_early(); |     furi_hal_spi_init_early(); | ||||||
| 
 | 
 | ||||||
|     furi_hal_i2c_init_early(); |     furi_hal_i2c_init_early(); | ||||||
|  | |||||||
| @ -134,7 +134,6 @@ bool furi_hal_bt_start_radio_stack() { | |||||||
|         // Wait until C2 is started or timeout
 |         // Wait until C2 is started or timeout
 | ||||||
|         if(!ble_glue_wait_for_c2_start(FURI_HAL_BT_C2_START_TIMEOUT)) { |         if(!ble_glue_wait_for_c2_start(FURI_HAL_BT_C2_START_TIMEOUT)) { | ||||||
|             FURI_LOG_E(TAG, "Core2 start failed"); |             FURI_LOG_E(TAG, "Core2 start failed"); | ||||||
|             LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); |  | ||||||
|             ble_glue_thread_stop(); |             ble_glue_thread_stop(); | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| @ -154,7 +153,6 @@ bool furi_hal_bt_start_radio_stack() { | |||||||
|         // Starting radio stack
 |         // Starting radio stack
 | ||||||
|         if(!ble_glue_start()) { |         if(!ble_glue_start()) { | ||||||
|             FURI_LOG_E(TAG, "Failed to start radio stack"); |             FURI_LOG_E(TAG, "Failed to start radio stack"); | ||||||
|             LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); |  | ||||||
|             ble_glue_thread_stop(); |             ble_glue_thread_stop(); | ||||||
|             ble_app_thread_stop(); |             ble_app_thread_stop(); | ||||||
|             break; |             break; | ||||||
| @ -221,27 +219,39 @@ bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb, | |||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void furi_hal_bt_reinit() { | ||||||
|  |     FURI_LOG_I(TAG, "Disconnect and stop advertising"); | ||||||
|  |     furi_hal_bt_stop_advertising(); | ||||||
|  | 
 | ||||||
|  |     FURI_LOG_I(TAG, "Stop current profile services"); | ||||||
|  |     current_profile->stop(); | ||||||
|  | 
 | ||||||
|  |     // Magic happens here
 | ||||||
|  |     hci_reset(); | ||||||
|  | 
 | ||||||
|  |     FURI_LOG_I(TAG, "Stop BLE related RTOS threads"); | ||||||
|  |     ble_app_thread_stop(); | ||||||
|  |     gap_thread_stop(); | ||||||
|  | 
 | ||||||
|  |     FURI_LOG_I(TAG, "Reset SHCI"); | ||||||
|  |     furi_check(ble_glue_reinit_c2()); | ||||||
|  | 
 | ||||||
|  |     osDelay(100); | ||||||
|  |     ble_glue_thread_stop(); | ||||||
|  | 
 | ||||||
|  |     FURI_LOG_I(TAG, "Start BT initialization"); | ||||||
|  |     furi_hal_bt_init(); | ||||||
|  | 
 | ||||||
|  |     furi_hal_bt_start_radio_stack(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| bool furi_hal_bt_change_app(FuriHalBtProfile profile, GapEventCallback event_cb, void* context) { | bool furi_hal_bt_change_app(FuriHalBtProfile profile, GapEventCallback event_cb, void* context) { | ||||||
|     furi_assert(event_cb); |     furi_assert(event_cb); | ||||||
|     furi_assert(profile < FuriHalBtProfileNumber); |     furi_assert(profile < FuriHalBtProfileNumber); | ||||||
|     bool ret = true; |     bool ret = true; | ||||||
| 
 | 
 | ||||||
|     FURI_LOG_I(TAG, "Stop current profile services"); |     furi_hal_bt_reinit(); | ||||||
|     current_profile->stop(); | 
 | ||||||
|     FURI_LOG_I(TAG, "Disconnect and stop advertising"); |  | ||||||
|     furi_hal_bt_stop_advertising(); |  | ||||||
|     FURI_LOG_I(TAG, "Shutdow 2nd core"); |  | ||||||
|     LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); |  | ||||||
|     FURI_LOG_I(TAG, "Stop BLE related RTOS threads"); |  | ||||||
|     ble_app_thread_stop(); |  | ||||||
|     gap_thread_stop(); |  | ||||||
|     FURI_LOG_I(TAG, "Reset SHCI"); |  | ||||||
|     ble_glue_reinit_c2(); |  | ||||||
|     osDelay(100); |  | ||||||
|     ble_glue_thread_stop(); |  | ||||||
|     FURI_LOG_I(TAG, "Start BT initialization"); |  | ||||||
|     furi_hal_bt_init(); |  | ||||||
|     furi_hal_bt_start_radio_stack(); |  | ||||||
|     ret = furi_hal_bt_start_app(profile, event_cb, context); |     ret = furi_hal_bt_start_app(profile, event_cb, context); | ||||||
|     if(ret) { |     if(ret) { | ||||||
|         current_profile = &profile_config[profile]; |         current_profile = &profile_config[profile]; | ||||||
|  | |||||||
| @ -204,6 +204,8 @@ void furi_hal_clock_switch_to_hsi() { | |||||||
| 
 | 
 | ||||||
|     while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) |     while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSI) | ||||||
|         ; |         ; | ||||||
|  | 
 | ||||||
|  |     LL_FLASH_SetLatency(LL_FLASH_LATENCY_1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_clock_switch_to_pll() { | void furi_hal_clock_switch_to_pll() { | ||||||
| @ -215,6 +217,8 @@ void furi_hal_clock_switch_to_pll() { | |||||||
|     while(!LL_RCC_PLL_IsReady()) |     while(!LL_RCC_PLL_IsReady()) | ||||||
|         ; |         ; | ||||||
| 
 | 
 | ||||||
|  |     LL_FLASH_SetLatency(LL_FLASH_LATENCY_3); | ||||||
|  | 
 | ||||||
|     LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); |     LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); | ||||||
|     LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSE); |     LL_RCC_SetSMPSClockSource(LL_RCC_SMPS_CLKSOURCE_HSE); | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										20
									
								
								firmware/targets/f7/furi_hal/furi_hal_debug.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								firmware/targets/f7/furi_hal/furi_hal_debug.c
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,20 @@ | |||||||
|  | #include <furi_hal_debug.h> | ||||||
|  | 
 | ||||||
|  | #include <stm32wbxx_ll_exti.h> | ||||||
|  | #include <stm32wbxx_ll_system.h> | ||||||
|  | 
 | ||||||
|  | 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); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void furi_hal_debug_disable() { | ||||||
|  |     // Low power mode debug
 | ||||||
|  |     LL_DBGMCU_DisableDBGSleepMode(); | ||||||
|  |     LL_DBGMCU_DisableDBGStopMode(); | ||||||
|  |     LL_DBGMCU_DisableDBGStandbyMode(); | ||||||
|  |     LL_EXTI_DisableIT_32_63(LL_EXTI_LINE_48); | ||||||
|  | } | ||||||
| @ -1,6 +1,7 @@ | |||||||
| #include <furi_hal_i2c.h> | #include <furi_hal_i2c.h> | ||||||
| #include <furi_hal_delay.h> | #include <furi_hal_delay.h> | ||||||
| #include <furi_hal_version.h> | #include <furi_hal_version.h> | ||||||
|  | #include <furi_hal_power.h> | ||||||
| 
 | 
 | ||||||
| #include <stm32wbxx_ll_i2c.h> | #include <stm32wbxx_ll_i2c.h> | ||||||
| #include <stm32wbxx_ll_gpio.h> | #include <stm32wbxx_ll_gpio.h> | ||||||
| @ -23,6 +24,7 @@ void furi_hal_i2c_init() { | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_i2c_acquire(FuriHalI2cBusHandle* handle) { | void furi_hal_i2c_acquire(FuriHalI2cBusHandle* handle) { | ||||||
|  |     furi_hal_power_insomnia_enter(); | ||||||
|     // Lock bus access
 |     // Lock bus access
 | ||||||
|     handle->bus->callback(handle->bus, FuriHalI2cBusEventLock); |     handle->bus->callback(handle->bus, FuriHalI2cBusEventLock); | ||||||
|     // Ensuree that no active handle set
 |     // Ensuree that no active handle set
 | ||||||
| @ -46,6 +48,7 @@ void furi_hal_i2c_release(FuriHalI2cBusHandle* handle) { | |||||||
|     handle->bus->current_handle = NULL; |     handle->bus->current_handle = NULL; | ||||||
|     // Unlock bus
 |     // Unlock bus
 | ||||||
|     handle->bus->callback(handle->bus, FuriHalI2cBusEventUnlock); |     handle->bus->callback(handle->bus, FuriHalI2cBusEventUnlock); | ||||||
|  |     furi_hal_power_insomnia_exit(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_i2c_tx( | bool furi_hal_i2c_tx( | ||||||
|  | |||||||
| @ -7,12 +7,14 @@ | |||||||
| 
 | 
 | ||||||
| // Timer used for tickless idle
 | // Timer used for tickless idle
 | ||||||
| #define FURI_HAL_IDLE_TIMER_MAX 0xFFFF | #define FURI_HAL_IDLE_TIMER_MAX 0xFFFF | ||||||
| #define FURI_HAL_IDLE_TIMER LPTIM2 | #define FURI_HAL_IDLE_TIMER LPTIM1 | ||||||
| #define FURI_HAL_IDLE_TIMER_IRQ LPTIM2_IRQn | #define FURI_HAL_IDLE_TIMER_IRQ LPTIM1_IRQn | ||||||
| 
 | 
 | ||||||
| static inline void furi_hal_idle_timer_init() { | static inline void furi_hal_idle_timer_init() { | ||||||
|     // Configure clock source
 |     // Configure clock source
 | ||||||
|     LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM2_CLKSOURCE_LSE); |     LL_RCC_SetLPTIMClockSource(LL_RCC_LPTIM1_CLKSOURCE_LSE); | ||||||
|  |     // There is a theoretical possibility that we need it
 | ||||||
|  |     LL_APB1_GRP1_EnableClockSleep(LL_APB1_GRP1_PERIPH_LPTIM1); | ||||||
|     // Set interrupt priority and enable them
 |     // Set interrupt priority and enable them
 | ||||||
|     NVIC_SetPriority( |     NVIC_SetPriority( | ||||||
|         FURI_HAL_IDLE_TIMER_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0)); |         FURI_HAL_IDLE_TIMER_IRQ, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0)); | ||||||
|  | |||||||
| @ -54,6 +54,10 @@ const IRQn_Type furi_hal_interrupt_irqn[FuriHalInterruptIdMax] = { | |||||||
| 
 | 
 | ||||||
|     // HSEM
 |     // HSEM
 | ||||||
|     [FuriHalInterruptIdHsem] = HSEM_IRQn, |     [FuriHalInterruptIdHsem] = HSEM_IRQn, | ||||||
|  | 
 | ||||||
|  |     // LPTIMx
 | ||||||
|  |     [FuriHalInterruptIdLpTim1] = LPTIM1_IRQn, | ||||||
|  |     [FuriHalInterruptIdLpTim2] = LPTIM2_IRQn, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| __attribute__((always_inline)) static inline void | __attribute__((always_inline)) static inline void | ||||||
| @ -82,6 +86,16 @@ void furi_hal_interrupt_init() { | |||||||
| 
 | 
 | ||||||
|     NVIC_SetPriority(PendSV_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0)); |     NVIC_SetPriority(PendSV_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0)); | ||||||
| 
 | 
 | ||||||
|  |     NVIC_SetPriority(FPU_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0)); | ||||||
|  |     NVIC_EnableIRQ(FPU_IRQn); | ||||||
|  | 
 | ||||||
|  |     LL_SYSCFG_DisableIT_FPU_IOC(); | ||||||
|  |     LL_SYSCFG_DisableIT_FPU_DZC(); | ||||||
|  |     LL_SYSCFG_DisableIT_FPU_UFC(); | ||||||
|  |     LL_SYSCFG_DisableIT_FPU_OFC(); | ||||||
|  |     LL_SYSCFG_DisableIT_FPU_IDC(); | ||||||
|  |     LL_SYSCFG_DisableIT_FPU_IXC(); | ||||||
|  | 
 | ||||||
|     FURI_LOG_I(TAG, "Init OK"); |     FURI_LOG_I(TAG, "Init OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -120,82 +134,82 @@ void furi_hal_interrupt_set_isr_ex( | |||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Timer 2 */ | /* Timer 2 */ | ||||||
| void TIM2_IRQHandler(void) { | void TIM2_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdTIM2); |     furi_hal_interrupt_call(FuriHalInterruptIdTIM2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* Timer 1 Update */ | /* Timer 1 Update */ | ||||||
| void TIM1_UP_TIM16_IRQHandler(void) { | void TIM1_UP_TIM16_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdTim1UpTim16); |     furi_hal_interrupt_call(FuriHalInterruptIdTim1UpTim16); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void TIM1_TRG_COM_TIM17_IRQHandler(void) { | void TIM1_TRG_COM_TIM17_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdTim1TrgComTim17); |     furi_hal_interrupt_call(FuriHalInterruptIdTim1TrgComTim17); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void TIM1_CC_IRQHandler(void) { | void TIM1_CC_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdTim1Cc); |     furi_hal_interrupt_call(FuriHalInterruptIdTim1Cc); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* DMA 1 */ | /* DMA 1 */ | ||||||
| void DMA1_Channel1_IRQHandler(void) { | void DMA1_Channel1_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch1); |     furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DMA1_Channel2_IRQHandler(void) { | void DMA1_Channel2_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch2); |     furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DMA1_Channel3_IRQHandler(void) { | void DMA1_Channel3_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch3); |     furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch3); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DMA1_Channel4_IRQHandler(void) { | void DMA1_Channel4_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch4); |     furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch4); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DMA1_Channel5_IRQHandler(void) { | void DMA1_Channel5_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch5); |     furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch5); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DMA1_Channel6_IRQHandler(void) { | void DMA1_Channel6_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch6); |     furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch6); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DMA1_Channel7_IRQHandler(void) { | void DMA1_Channel7_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch7); |     furi_hal_interrupt_call(FuriHalInterruptIdDma1Ch7); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| /* DMA 2 */ | /* DMA 2 */ | ||||||
| void DMA2_Channel1_IRQHandler(void) { | void DMA2_Channel1_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch1); |     furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch1); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DMA2_Channel2_IRQHandler(void) { | void DMA2_Channel2_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch2); |     furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch2); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DMA2_Channel3_IRQHandler(void) { | void DMA2_Channel3_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch3); |     furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch3); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DMA2_Channel4_IRQHandler(void) { | void DMA2_Channel4_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch4); |     furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch4); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DMA2_Channel5_IRQHandler(void) { | void DMA2_Channel5_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch5); |     furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch5); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DMA2_Channel6_IRQHandler(void) { | void DMA2_Channel6_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch6); |     furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch6); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DMA2_Channel7_IRQHandler(void) { | void DMA2_Channel7_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch7); |     furi_hal_interrupt_call(FuriHalInterruptIdDma2Ch7); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void HSEM_IRQHandler(void) { | void HSEM_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdHsem); |     furi_hal_interrupt_call(FuriHalInterruptIdHsem); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -211,11 +225,11 @@ void TAMP_STAMP_LSECSS_IRQHandler(void) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void RCC_IRQHandler(void) { | void RCC_IRQHandler() { | ||||||
|     furi_hal_interrupt_call(FuriHalInterruptIdRcc); |     furi_hal_interrupt_call(FuriHalInterruptIdRcc); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void NMI_Handler(void) { | void NMI_Handler() { | ||||||
|     if(LL_RCC_IsActiveFlag_HSECSS()) { |     if(LL_RCC_IsActiveFlag_HSECSS()) { | ||||||
|         LL_RCC_ClearFlag_HSECSS(); |         LL_RCC_ClearFlag_HSECSS(); | ||||||
|         FURI_LOG_E(TAG, "HSE CSS fired: resetting system"); |         FURI_LOG_E(TAG, "HSE CSS fired: resetting system"); | ||||||
| @ -223,23 +237,23 @@ void NMI_Handler(void) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void HardFault_Handler(void) { | void HardFault_Handler() { | ||||||
|     furi_crash("HardFault"); |     furi_crash("HardFault"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void MemManage_Handler(void) { | void MemManage_Handler() { | ||||||
|     furi_crash("MemManage"); |     furi_crash("MemManage"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void BusFault_Handler(void) { | void BusFault_Handler() { | ||||||
|     furi_crash("BusFault"); |     furi_crash("BusFault"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void UsageFault_Handler(void) { | void UsageFault_Handler() { | ||||||
|     furi_crash("UsageFault"); |     furi_crash("UsageFault"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void DebugMon_Handler(void) { | void DebugMon_Handler() { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| #include "usbd_core.h" | #include "usbd_core.h" | ||||||
| @ -249,20 +263,35 @@ extern usbd_device udev; | |||||||
| extern void HW_IPCC_Tx_Handler(); | extern void HW_IPCC_Tx_Handler(); | ||||||
| extern void HW_IPCC_Rx_Handler(); | extern void HW_IPCC_Rx_Handler(); | ||||||
| 
 | 
 | ||||||
| void SysTick_Handler(void) { | void SysTick_Handler() { | ||||||
|     furi_hal_os_tick(); |     furi_hal_os_tick(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void USB_LP_IRQHandler(void) { | void USB_LP_IRQHandler() { | ||||||
| #ifndef FURI_RAM_EXEC | #ifndef FURI_RAM_EXEC | ||||||
|     usbd_poll(&udev); |     usbd_poll(&udev); | ||||||
| #endif | #endif | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void IPCC_C1_TX_IRQHandler(void) { | void USB_HP_IRQHandler() { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void IPCC_C1_TX_IRQHandler() { | ||||||
|     HW_IPCC_Tx_Handler(); |     HW_IPCC_Tx_Handler(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void IPCC_C1_RX_IRQHandler(void) { | void IPCC_C1_RX_IRQHandler() { | ||||||
|     HW_IPCC_Rx_Handler(); |     HW_IPCC_Rx_Handler(); | ||||||
| } | } | ||||||
|  | 
 | ||||||
|  | void FPU_IRQHandler() { | ||||||
|  |     furi_crash("FpuFault"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LPTIM1_IRQHandler() { | ||||||
|  |     furi_hal_interrupt_call(FuriHalInterruptIdLpTim1); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void LPTIM2_IRQHandler() { | ||||||
|  |     furi_hal_interrupt_call(FuriHalInterruptIdLpTim2); | ||||||
|  | } | ||||||
|  | |||||||
| @ -45,6 +45,10 @@ typedef enum { | |||||||
|     // HSEM
 |     // HSEM
 | ||||||
|     FuriHalInterruptIdHsem, |     FuriHalInterruptIdHsem, | ||||||
| 
 | 
 | ||||||
|  |     // LPTIMx
 | ||||||
|  |     FuriHalInterruptIdLpTim1, | ||||||
|  |     FuriHalInterruptIdLpTim2, | ||||||
|  | 
 | ||||||
|     // Service value
 |     // Service value
 | ||||||
|     FuriHalInterruptIdMax, |     FuriHalInterruptIdMax, | ||||||
| } FuriHalInterruptId; | } FuriHalInterruptId; | ||||||
|  | |||||||
| @ -1,8 +1,10 @@ | |||||||
| #include <furi_hal_os.h> | #include <furi_hal_os.h> | ||||||
| #include <furi_hal_clock.h> | #include <furi_hal_clock.h> | ||||||
| #include <furi_hal_power.h> | #include <furi_hal_power.h> | ||||||
| #include <furi_hal_delay.h> | #include <furi_hal_gpio.h> | ||||||
|  | #include <furi_hal_resources.h> | ||||||
| #include <furi_hal_idle_timer.h> | #include <furi_hal_idle_timer.h> | ||||||
|  | 
 | ||||||
| #include <stm32wbxx_ll_cortex.h> | #include <stm32wbxx_ll_cortex.h> | ||||||
| 
 | 
 | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| @ -18,32 +20,32 @@ | |||||||
| #define FURI_HAL_IDLE_TIMER_TICK_PER_EPOCH (FURI_HAL_OS_IDLE_CNT_TO_TICKS(FURI_HAL_IDLE_TIMER_MAX)) | #define FURI_HAL_IDLE_TIMER_TICK_PER_EPOCH (FURI_HAL_OS_IDLE_CNT_TO_TICKS(FURI_HAL_IDLE_TIMER_MAX)) | ||||||
| #define FURI_HAL_OS_MAX_SLEEP (FURI_HAL_IDLE_TIMER_TICK_PER_EPOCH - 1) | #define FURI_HAL_OS_MAX_SLEEP (FURI_HAL_IDLE_TIMER_TICK_PER_EPOCH - 1) | ||||||
| 
 | 
 | ||||||
|  | #define FURI_HAL_OS_NVIC_IS_PENDING() (NVIC->ISPR[0] || NVIC->ISPR[1]) | ||||||
|  | #define FURI_HAL_OS_EXTI_LINE_0_31 0 | ||||||
|  | #define FURI_HAL_OS_EXTI_LINE_32_63 1 | ||||||
|  | 
 | ||||||
|  | // Arbitrary (but small) number for better tick consistency
 | ||||||
|  | #define FURI_HAL_OS_EXTRA_CNT 3 | ||||||
|  | 
 | ||||||
| #ifdef FURI_HAL_OS_DEBUG | #ifdef FURI_HAL_OS_DEBUG | ||||||
| #include <stm32wbxx_ll_gpio.h> | #include <stm32wbxx_ll_gpio.h> | ||||||
| 
 | 
 | ||||||
| #define LED_SLEEP_PORT GPIOA |  | ||||||
| #define LED_SLEEP_PIN LL_GPIO_PIN_7 |  | ||||||
| #define LED_TICK_PORT GPIOA |  | ||||||
| #define LED_TICK_PIN LL_GPIO_PIN_6 |  | ||||||
| #define LED_SECOND_PORT GPIOA |  | ||||||
| #define LED_SECOND_PIN LL_GPIO_PIN_4 |  | ||||||
| 
 |  | ||||||
| void furi_hal_os_timer_callback() { | void furi_hal_os_timer_callback() { | ||||||
|     LL_GPIO_TogglePin(LED_SECOND_PORT, LED_SECOND_PIN); |     furi_hal_gpio_write(&gpio_ext_pa4, !furi_hal_gpio_read(&gpio_ext_pa4)); | ||||||
| } | } | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
| extern void xPortSysTickHandler(); | extern void xPortSysTickHandler(); | ||||||
| 
 | 
 | ||||||
| static volatile uint32_t furi_hal_os_skew = 0; | static volatile uint32_t furi_hal_os_skew; | ||||||
| 
 | 
 | ||||||
| void furi_hal_os_init() { | void furi_hal_os_init() { | ||||||
|     furi_hal_idle_timer_init(); |     furi_hal_idle_timer_init(); | ||||||
| 
 | 
 | ||||||
| #ifdef FURI_HAL_OS_DEBUG | #ifdef FURI_HAL_OS_DEBUG | ||||||
|     LL_GPIO_SetPinMode(LED_SLEEP_PORT, LED_SLEEP_PIN, LL_GPIO_MODE_OUTPUT); |     furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull); | ||||||
|     LL_GPIO_SetPinMode(LED_TICK_PORT, LED_TICK_PIN, LL_GPIO_MODE_OUTPUT); |     furi_hal_gpio_init_simple(&gpio_ext_pa6, GpioModeOutputPushPull); | ||||||
|     LL_GPIO_SetPinMode(LED_SECOND_PORT, LED_SECOND_PIN, LL_GPIO_MODE_OUTPUT); |     furi_hal_gpio_init_simple(&gpio_ext_pa4, GpioModeOutputPushPull); | ||||||
|     osTimerId_t second_timer = osTimerNew(furi_hal_os_timer_callback, osTimerPeriodic, NULL, NULL); |     osTimerId_t second_timer = osTimerNew(furi_hal_os_timer_callback, osTimerPeriodic, NULL, NULL); | ||||||
|     osTimerStart(second_timer, FURI_HAL_OS_TICK_HZ); |     osTimerStart(second_timer, FURI_HAL_OS_TICK_HZ); | ||||||
| #endif | #endif | ||||||
| @ -54,12 +56,61 @@ void furi_hal_os_init() { | |||||||
| void furi_hal_os_tick() { | void furi_hal_os_tick() { | ||||||
|     if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { |     if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { | ||||||
| #ifdef FURI_HAL_OS_DEBUG | #ifdef FURI_HAL_OS_DEBUG | ||||||
|         LL_GPIO_TogglePin(LED_TICK_PORT, LED_TICK_PIN); |         furi_hal_gpio_write(&gpio_ext_pa6, !furi_hal_gpio_read(&gpio_ext_pa6)); | ||||||
| #endif | #endif | ||||||
|         xPortSysTickHandler(); |         xPortSysTickHandler(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | #ifdef FURI_HAL_OS_DEBUG | ||||||
|  | // Find out the IRQ number while debugging
 | ||||||
|  | static void furi_hal_os_nvic_dbg_trap() { | ||||||
|  |     for(int32_t i = WWDG_IRQn; i <= DMAMUX1_OVR_IRQn; i++) { | ||||||
|  |         if(NVIC_GetPendingIRQ(i)) { | ||||||
|  |             (void)i; | ||||||
|  |             // Break here
 | ||||||
|  |             __NOP(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | // Find out the EXTI line number while debugging
 | ||||||
|  | static void furi_hal_os_exti_dbg_trap(uint32_t exti, uint32_t val) { | ||||||
|  |     for(uint32_t i = 0; val; val >>= 1U, ++i) { | ||||||
|  |         if(val & 1U) { | ||||||
|  |             (void)exti; | ||||||
|  |             (void)i; | ||||||
|  |             // Break here
 | ||||||
|  |             __NOP(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | static inline bool furi_hal_os_is_pending_irq() { | ||||||
|  |     if(FURI_HAL_OS_NVIC_IS_PENDING()) { | ||||||
|  | #ifdef FURI_HAL_OS_DEBUG | ||||||
|  |         furi_hal_os_nvic_dbg_trap(); | ||||||
|  | #endif | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     uint32_t exti_lines_active; | ||||||
|  |     if((exti_lines_active = LL_EXTI_ReadFlag_0_31(LL_EXTI_LINE_ALL_0_31))) { | ||||||
|  | #ifdef FURI_HAL_OS_DEBUG | ||||||
|  |         furi_hal_os_exti_dbg_trap(FURI_HAL_OS_EXTI_LINE_0_31, exti_lines_active); | ||||||
|  | #endif | ||||||
|  |         return true; | ||||||
|  |     } else if((exti_lines_active = LL_EXTI_ReadFlag_32_63(LL_EXTI_LINE_ALL_32_63))) { | ||||||
|  | #ifdef FURI_HAL_OS_DEBUG | ||||||
|  |         furi_hal_os_exti_dbg_trap(FURI_HAL_OS_EXTI_LINE_32_63, exti_lines_active); | ||||||
|  | #endif | ||||||
|  |         return true; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     return false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| static inline uint32_t furi_hal_os_sleep(TickType_t expected_idle_ticks) { | static inline uint32_t furi_hal_os_sleep(TickType_t expected_idle_ticks) { | ||||||
|     // Stop ticks
 |     // Stop ticks
 | ||||||
|     furi_hal_clock_suspend_tick(); |     furi_hal_clock_suspend_tick(); | ||||||
| @ -68,20 +119,20 @@ 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)); |     furi_hal_idle_timer_start(FURI_HAL_OS_TICKS_TO_IDLE_CNT(expected_idle_ticks)); | ||||||
| 
 | 
 | ||||||
| #ifdef FURI_HAL_OS_DEBUG | #ifdef FURI_HAL_OS_DEBUG | ||||||
|     LL_GPIO_ResetOutputPin(LED_SLEEP_PORT, LED_SLEEP_PIN); |     furi_hal_gpio_write(&gpio_ext_pa7, 0); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     // Go to sleep mode
 |     // Go to sleep mode
 | ||||||
|     furi_hal_power_sleep(); |     furi_hal_power_sleep(); | ||||||
| 
 | 
 | ||||||
| #ifdef FURI_HAL_OS_DEBUG | #ifdef FURI_HAL_OS_DEBUG | ||||||
|     LL_GPIO_SetOutputPin(LED_SLEEP_PORT, LED_SLEEP_PIN); |     furi_hal_gpio_write(&gpio_ext_pa7, 1); | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     // Calculate how much time we spent in the sleep
 |     // Calculate how much time we spent in the sleep
 | ||||||
|     uint32_t after_cnt = furi_hal_idle_timer_get_cnt() + furi_hal_os_skew; |     uint32_t after_cnt = furi_hal_idle_timer_get_cnt() + furi_hal_os_skew + FURI_HAL_OS_EXTRA_CNT; | ||||||
|     uint32_t after_tick = FURI_HAL_OS_IDLE_CNT_TO_TICKS(after_cnt); |     uint32_t after_tick = FURI_HAL_OS_IDLE_CNT_TO_TICKS(after_cnt); | ||||||
|     furi_hal_os_skew = after_cnt - (after_cnt / after_tick); |     furi_hal_os_skew = after_cnt - FURI_HAL_OS_TICKS_TO_IDLE_CNT(after_tick); | ||||||
| 
 | 
 | ||||||
|     bool cmpm = LL_LPTIM_IsActiveFlag_CMPM(FURI_HAL_IDLE_TIMER); |     bool cmpm = LL_LPTIM_IsActiveFlag_CMPM(FURI_HAL_IDLE_TIMER); | ||||||
|     bool arrm = LL_LPTIM_IsActiveFlag_ARRM(FURI_HAL_IDLE_TIMER); |     bool arrm = LL_LPTIM_IsActiveFlag_ARRM(FURI_HAL_IDLE_TIMER); | ||||||
| @ -110,7 +161,7 @@ void vPortSuppressTicksAndSleep(TickType_t expected_idle_ticks) { | |||||||
|     __disable_irq(); |     __disable_irq(); | ||||||
| 
 | 
 | ||||||
|     // Confirm OS that sleep is still possible
 |     // Confirm OS that sleep is still possible
 | ||||||
|     if(eTaskConfirmSleepModeStatus() == eAbortSleep) { |     if(eTaskConfirmSleepModeStatus() == eAbortSleep || furi_hal_os_is_pending_irq()) { | ||||||
|         __enable_irq(); |         __enable_irq(); | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -2,6 +2,7 @@ | |||||||
| #include <furi_hal_clock.h> | #include <furi_hal_clock.h> | ||||||
| #include <furi_hal_bt.h> | #include <furi_hal_bt.h> | ||||||
| #include <furi_hal_resources.h> | #include <furi_hal_resources.h> | ||||||
|  | #include <furi_hal_uart.h> | ||||||
| 
 | 
 | ||||||
| #include <stm32wbxx_ll_rcc.h> | #include <stm32wbxx_ll_rcc.h> | ||||||
| #include <stm32wbxx_ll_pwr.h> | #include <stm32wbxx_ll_pwr.h> | ||||||
| @ -17,6 +18,12 @@ | |||||||
| 
 | 
 | ||||||
| #define TAG "FuriHalPower" | #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 | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     volatile uint8_t insomnia; |     volatile uint8_t insomnia; | ||||||
|     volatile uint8_t deep_insomnia; |     volatile uint8_t deep_insomnia; | ||||||
| @ -28,7 +35,7 @@ typedef struct { | |||||||
| 
 | 
 | ||||||
| static volatile FuriHalPower furi_hal_power = { | static volatile FuriHalPower furi_hal_power = { | ||||||
|     .insomnia = 0, |     .insomnia = 0, | ||||||
|     .deep_insomnia = 1, |     .deep_insomnia = FURI_HAL_POWER_DEEP_INSOMNIA, | ||||||
|     .suppress_charge = 0, |     .suppress_charge = 0, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @ -70,11 +77,6 @@ const ParamCEDV cedv = { | |||||||
|     .DOD100 = 3299, |     .DOD100 = 3299, | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| void HAL_RCC_CSSCallback(void) { |  | ||||||
|     // TODO: notify user about issue with HSE
 |  | ||||||
|     furi_hal_power_reset(); |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| void furi_hal_power_init() { | void furi_hal_power_init() { | ||||||
|     LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); |     LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); | ||||||
|     LL_PWR_SMPS_SetMode(LL_PWR_SMPS_STEP_DOWN); |     LL_PWR_SMPS_SetMode(LL_PWR_SMPS_STEP_DOWN); | ||||||
| @ -84,6 +86,11 @@ void furi_hal_power_init() { | |||||||
|     bq25896_init(&furi_hal_i2c_handle_power); |     bq25896_init(&furi_hal_i2c_handle_power); | ||||||
|     furi_hal_i2c_release(&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"); |     FURI_LOG_I(TAG, "Init OK"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -140,12 +147,28 @@ void furi_hal_power_light_sleep() { | |||||||
|     __WFI(); |     __WFI(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | 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() { | void furi_hal_power_deep_sleep() { | ||||||
|  |     furi_hal_power_suspend_aux_periphs(); | ||||||
|  | 
 | ||||||
|     while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)) |     while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)) | ||||||
|         ; |         ; | ||||||
| 
 | 
 | ||||||
|     if(!LL_HSEM_1StepLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID)) { |     if(!LL_HSEM_1StepLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID)) { | ||||||
|         if(LL_PWR_IsActiveFlag_C2DS()) { |         if(LL_PWR_IsActiveFlag_C2DS() || LL_PWR_IsActiveFlag_C2SB()) { | ||||||
|             // Release ENTRY_STOP_MODE semaphore
 |             // Release ENTRY_STOP_MODE semaphore
 | ||||||
|             LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0); |             LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0); | ||||||
| 
 | 
 | ||||||
| @ -163,7 +186,8 @@ void furi_hal_power_deep_sleep() { | |||||||
|     LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0); |     LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0); | ||||||
| 
 | 
 | ||||||
|     // Prepare deep sleep
 |     // Prepare deep sleep
 | ||||||
|     LL_PWR_SetPowerMode(LL_PWR_MODE_STOP1); |     LL_PWR_SetPowerMode(LL_PWR_MODE_STOP2); | ||||||
|  |     LL_C2_PWR_SetPowerMode(LL_PWR_MODE_STOP2); | ||||||
|     LL_LPM_EnableDeepSleep(); |     LL_LPM_EnableDeepSleep(); | ||||||
| 
 | 
 | ||||||
| #if defined(__CC_ARM) | #if defined(__CC_ARM) | ||||||
| @ -173,6 +197,15 @@ void furi_hal_power_deep_sleep() { | |||||||
| 
 | 
 | ||||||
|     __WFI(); |     __WFI(); | ||||||
| 
 | 
 | ||||||
|  |     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 */ |     /* Release ENTRY_STOP_MODE semaphore */ | ||||||
|     LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0); |     LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0); | ||||||
| 
 | 
 | ||||||
| @ -184,13 +217,31 @@ void furi_hal_power_deep_sleep() { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0); |     LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0); | ||||||
|  | 
 | ||||||
|  |     furi_hal_power_resume_aux_periphs(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_power_sleep() { | void furi_hal_power_sleep() { | ||||||
|     if(furi_hal_power_deep_sleep_available()) { |     if(furi_hal_power_deep_sleep_available()) { | ||||||
|  | #ifdef FURI_HAL_OS_DEBUG | ||||||
|  |         furi_hal_gpio_write(&gpio_ext_pc3, 1); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|         furi_hal_power_deep_sleep(); |         furi_hal_power_deep_sleep(); | ||||||
|  | 
 | ||||||
|  | #ifdef FURI_HAL_OS_DEBUG | ||||||
|  |         furi_hal_gpio_write(&gpio_ext_pc3, 0); | ||||||
|  | #endif | ||||||
|     } else { |     } else { | ||||||
|  | #ifdef FURI_HAL_OS_DEBUG | ||||||
|  |         furi_hal_gpio_write(&gpio_ext_pb2, 1); | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|         furi_hal_power_light_sleep(); |         furi_hal_power_light_sleep(); | ||||||
|  | 
 | ||||||
|  | #ifdef FURI_HAL_OS_DEBUG | ||||||
|  |         furi_hal_gpio_write(&gpio_ext_pb2, 0); | ||||||
|  | #endif | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -215,6 +266,38 @@ bool furi_hal_power_is_charging() { | |||||||
|     return ret; |     return ret; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void furi_hal_power_shutdown() { | ||||||
|  |     furi_hal_power_insomnia_enter(); | ||||||
|  | 
 | ||||||
|  |     furi_hal_bt_reinit(); | ||||||
|  | 
 | ||||||
|  |     while(LL_HSEM_1StepLock(HSEM, CFG_HW_RCC_SEMID)) | ||||||
|  |         ; | ||||||
|  | 
 | ||||||
|  |     if(!LL_HSEM_1StepLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID)) { | ||||||
|  |         if(LL_PWR_IsActiveFlag_C2DS() || LL_PWR_IsActiveFlag_C2SB()) { | ||||||
|  |             // Release ENTRY_STOP_MODE semaphore
 | ||||||
|  |             LL_HSEM_ReleaseLock(HSEM, CFG_HW_ENTRY_STOP_MODE_SEMID, 0); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     // Prepare Wakeup pin
 | ||||||
|  |     LL_PWR_SetWakeUpPinPolarityLow(LL_PWR_WAKEUP_PIN2); | ||||||
|  |     LL_PWR_EnableWakeUpPin(LL_PWR_WAKEUP_PIN2); | ||||||
|  |     LL_C2_PWR_EnableWakeUpPin(LL_PWR_WAKEUP_PIN2); | ||||||
|  | 
 | ||||||
|  |     /* Release RCC semaphore */ | ||||||
|  |     LL_HSEM_ReleaseLock(HSEM, CFG_HW_RCC_SEMID, 0); | ||||||
|  | 
 | ||||||
|  |     LL_PWR_DisableBootC2(); | ||||||
|  |     LL_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); | ||||||
|  |     LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); | ||||||
|  |     LL_LPM_EnableDeepSleep(); | ||||||
|  | 
 | ||||||
|  |     __WFI(); | ||||||
|  |     furi_crash("Insomniac core2"); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void furi_hal_power_off() { | void furi_hal_power_off() { | ||||||
|     furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); |     furi_hal_i2c_acquire(&furi_hal_i2c_handle_power); | ||||||
|     bq25896_poweroff(&furi_hal_i2c_handle_power); |     bq25896_poweroff(&furi_hal_i2c_handle_power); | ||||||
|  | |||||||
| @ -1,6 +1,9 @@ | |||||||
| #include <furi_hal_resources.h> | #include <furi_hal_resources.h> | ||||||
| #include <furi.h> | #include <furi.h> | ||||||
| 
 | 
 | ||||||
|  | #include <stm32wbxx_ll_rcc.h> | ||||||
|  | #include <stm32wbxx_ll_pwr.h> | ||||||
|  | 
 | ||||||
| const GpioPin vibro_gpio = {.port = VIBRO_GPIO_Port, .pin = VIBRO_Pin}; | const GpioPin vibro_gpio = {.port = VIBRO_GPIO_Port, .pin = VIBRO_Pin}; | ||||||
| const GpioPin ibutton_gpio = {.port = iBTN_GPIO_Port, .pin = iBTN_Pin}; | const GpioPin ibutton_gpio = {.port = iBTN_GPIO_Port, .pin = iBTN_Pin}; | ||||||
| 
 | 
 | ||||||
| @ -9,7 +12,7 @@ const GpioPin gpio_rf_sw_0 = {.port = RF_SW_0_GPIO_Port, .pin = RF_SW_0_Pin}; | |||||||
| 
 | 
 | ||||||
| const GpioPin gpio_subghz_cs = {.port = CC1101_CS_GPIO_Port, .pin = CC1101_CS_Pin}; | const GpioPin gpio_subghz_cs = {.port = CC1101_CS_GPIO_Port, .pin = CC1101_CS_Pin}; | ||||||
| const GpioPin gpio_display_cs = {.port = DISPLAY_CS_GPIO_Port, .pin = DISPLAY_CS_Pin}; | const GpioPin gpio_display_cs = {.port = DISPLAY_CS_GPIO_Port, .pin = DISPLAY_CS_Pin}; | ||||||
| const GpioPin gpio_display_rst = {.port = DISPLAY_RST_GPIO_Port, .pin = DISPLAY_RST_Pin}; | const GpioPin gpio_display_rst_n = {.port = DISPLAY_RST_GPIO_Port, .pin = DISPLAY_RST_Pin}; | ||||||
| const GpioPin gpio_display_di = {.port = DISPLAY_DI_GPIO_Port, .pin = DISPLAY_DI_Pin}; | const GpioPin gpio_display_di = {.port = DISPLAY_DI_GPIO_Port, .pin = DISPLAY_DI_Pin}; | ||||||
| const GpioPin gpio_sdcard_cs = {.port = SD_CS_GPIO_Port, .pin = SD_CS_Pin}; | const GpioPin gpio_sdcard_cs = {.port = SD_CS_GPIO_Port, .pin = SD_CS_Pin}; | ||||||
| const GpioPin gpio_sdcard_cd = {.port = SD_CD_GPIO_Port, .pin = SD_CD_Pin}; | const GpioPin gpio_sdcard_cd = {.port = SD_CD_GPIO_Port, .pin = SD_CD_Pin}; | ||||||
| @ -72,14 +75,32 @@ const size_t input_pins_count = sizeof(input_pins) / sizeof(InputPin); | |||||||
| 
 | 
 | ||||||
| void furi_hal_resources_init_early() { | void furi_hal_resources_init_early() { | ||||||
|     furi_hal_gpio_init(&gpio_button_left, GpioModeInput, GpioPullUp, GpioSpeedLow); |     furi_hal_gpio_init(&gpio_button_left, GpioModeInput, GpioPullUp, GpioSpeedLow); | ||||||
|     furi_hal_gpio_init_simple(&gpio_display_rst, GpioModeOutputPushPull); | 
 | ||||||
|  |     // Display pins
 | ||||||
|  |     furi_hal_gpio_write(&gpio_display_rst_n, 1); | ||||||
|  |     furi_hal_gpio_init_simple(&gpio_display_rst_n, GpioModeOutputPushPull); | ||||||
|     furi_hal_gpio_init_simple(&gpio_display_di, GpioModeOutputPushPull); |     furi_hal_gpio_init_simple(&gpio_display_di, GpioModeOutputPushPull); | ||||||
| 
 | 
 | ||||||
|  |     // Alternative pull configuration for shutdown
 | ||||||
|  |     SET_BIT(PWR->PUCRB, DISPLAY_RST_Pin); | ||||||
|  |     CLEAR_BIT(PWR->PDCRB, DISPLAY_RST_Pin); | ||||||
|  |     SET_BIT(PWR->CR3, PWR_CR3_APC); | ||||||
|  | 
 | ||||||
|     // Hard reset USB
 |     // Hard reset USB
 | ||||||
|     furi_hal_gpio_init_simple(&gpio_usb_dm, GpioModeOutputOpenDrain); |     furi_hal_gpio_init_simple(&gpio_usb_dm, GpioModeOutputOpenDrain); | ||||||
|     furi_hal_gpio_init_simple(&gpio_usb_dp, GpioModeOutputOpenDrain); |     furi_hal_gpio_init_simple(&gpio_usb_dp, GpioModeOutputOpenDrain); | ||||||
|     furi_hal_gpio_write(&gpio_usb_dm, 0); |     furi_hal_gpio_write(&gpio_usb_dm, 0); | ||||||
|     furi_hal_gpio_write(&gpio_usb_dp, 0); |     furi_hal_gpio_write(&gpio_usb_dp, 0); | ||||||
|  | 
 | ||||||
|  |     // External header pins
 | ||||||
|  |     furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |     furi_hal_gpio_init(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |     furi_hal_gpio_init(&gpio_ext_pc3, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |     furi_hal_gpio_init(&gpio_ext_pb2, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |     furi_hal_gpio_init(&gpio_ext_pb3, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |     furi_hal_gpio_init(&gpio_ext_pa4, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |     furi_hal_gpio_init(&gpio_ext_pa6, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
|  |     furi_hal_gpio_init(&gpio_ext_pa7, GpioModeAnalog, GpioPullNo, GpioSpeedLow); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_resources_deinit_early() { | void furi_hal_resources_deinit_early() { | ||||||
| @ -92,19 +113,9 @@ void furi_hal_resources_init() { | |||||||
|             input_pins[i].gpio, GpioModeInterruptRiseFall, GpioPullUp, GpioSpeedLow); |             input_pins[i].gpio, GpioModeInterruptRiseFall, GpioPullUp, GpioSpeedLow); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     // External header pins
 |  | ||||||
|     furi_hal_gpio_init(&gpio_ext_pc0, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |  | ||||||
|     furi_hal_gpio_init(&gpio_ext_pc1, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |  | ||||||
|     furi_hal_gpio_init(&gpio_ext_pc3, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |  | ||||||
|     furi_hal_gpio_init(&gpio_ext_pb2, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |  | ||||||
|     furi_hal_gpio_init(&gpio_ext_pb3, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |  | ||||||
|     furi_hal_gpio_init(&gpio_ext_pa4, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |  | ||||||
|     furi_hal_gpio_init(&gpio_ext_pa6, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |  | ||||||
|     furi_hal_gpio_init(&gpio_ext_pa7, GpioModeAnalog, GpioPullNo, GpioSpeedLow); |  | ||||||
| 
 |  | ||||||
|     // Display pins
 |     // Display pins
 | ||||||
|     furi_hal_gpio_init(&gpio_display_rst, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     furi_hal_gpio_init(&gpio_display_rst_n, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|     furi_hal_gpio_write(&gpio_display_rst, 0); |     furi_hal_gpio_write(&gpio_display_rst_n, 0); | ||||||
| 
 | 
 | ||||||
|     furi_hal_gpio_init(&gpio_display_di, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); |     furi_hal_gpio_init(&gpio_display_di, GpioModeOutputPushPull, GpioPullNo, GpioSpeedLow); | ||||||
|     furi_hal_gpio_write(&gpio_display_di, 0); |     furi_hal_gpio_write(&gpio_display_di, 0); | ||||||
|  | |||||||
| @ -48,7 +48,7 @@ extern const GpioPin gpio_rf_sw_0; | |||||||
| 
 | 
 | ||||||
| extern const GpioPin gpio_subghz_cs; | extern const GpioPin gpio_subghz_cs; | ||||||
| extern const GpioPin gpio_display_cs; | extern const GpioPin gpio_display_cs; | ||||||
| extern const GpioPin gpio_display_rst; | extern const GpioPin gpio_display_rst_n; | ||||||
| extern const GpioPin gpio_display_di; | extern const GpioPin gpio_display_di; | ||||||
| extern const GpioPin gpio_sdcard_cs; | extern const GpioPin gpio_sdcard_cs; | ||||||
| extern const GpioPin gpio_sdcard_cd; | extern const GpioPin gpio_sdcard_cd; | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| #include <furi_hal_rtc.h> | #include <furi_hal_rtc.h> | ||||||
| #include <furi_hal_light.h> | #include <furi_hal_light.h> | ||||||
|  | #include <furi_hal_debug.h> | ||||||
| 
 | 
 | ||||||
| #include <stm32wbxx_ll_bus.h> | #include <stm32wbxx_ll_bus.h> | ||||||
| #include <stm32wbxx_ll_pwr.h> | #include <stm32wbxx_ll_pwr.h> | ||||||
| @ -36,7 +37,6 @@ void furi_hal_rtc_init_early() { | |||||||
|     // LSE and RTC
 |     // LSE and RTC
 | ||||||
|     LL_PWR_EnableBkUpAccess(); |     LL_PWR_EnableBkUpAccess(); | ||||||
|     if(!RTC_CLOCK_IS_READY()) { |     if(!RTC_CLOCK_IS_READY()) { | ||||||
|         // Start LSI1 needed for CSS
 |  | ||||||
|         LL_RCC_LSI1_Enable(); |         LL_RCC_LSI1_Enable(); | ||||||
|         // Try to start LSE normal way
 |         // Try to start LSE normal way
 | ||||||
|         LL_RCC_LSE_SetDriveCapability(LL_RCC_LSEDRIVE_HIGH); |         LL_RCC_LSE_SetDriveCapability(LL_RCC_LSEDRIVE_HIGH); | ||||||
| @ -55,8 +55,6 @@ void furi_hal_rtc_init_early() { | |||||||
|         } |         } | ||||||
|         // Set RTC domain clock to LSE
 |         // Set RTC domain clock to LSE
 | ||||||
|         LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE); |         LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE); | ||||||
|         // Enable LSE CSS
 |  | ||||||
|         LL_RCC_LSE_EnableCSS(); |  | ||||||
|     } |     } | ||||||
|     // Enable clocking
 |     // Enable clocking
 | ||||||
|     LL_RCC_EnableRTC(); |     LL_RCC_EnableRTC(); | ||||||
| @ -74,6 +72,12 @@ void furi_hal_rtc_init_early() { | |||||||
|         data->version = FURI_HAL_RTC_HEADER_VERSION; |         data->version = FURI_HAL_RTC_HEADER_VERSION; | ||||||
|         furi_hal_rtc_set_register(FuriHalRtcRegisterHeader, data_reg); |         furi_hal_rtc_set_register(FuriHalRtcRegisterHeader, data_reg); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { | ||||||
|  |         furi_hal_debug_enable(); | ||||||
|  |     } else { | ||||||
|  |         furi_hal_debug_disable(); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_rtc_deinit_early() { | void furi_hal_rtc_deinit_early() { | ||||||
| @ -126,6 +130,10 @@ void furi_hal_rtc_set_flag(FuriHalRtcFlag flag) { | |||||||
|     DeveloperReg* data = (DeveloperReg*)&data_reg; |     DeveloperReg* data = (DeveloperReg*)&data_reg; | ||||||
|     data->flags |= flag; |     data->flags |= flag; | ||||||
|     furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg); |     furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg); | ||||||
|  | 
 | ||||||
|  |     if(flag & FuriHalRtcFlagDebug) { | ||||||
|  |         furi_hal_debug_enable(); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag) { | void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag) { | ||||||
| @ -133,6 +141,10 @@ void furi_hal_rtc_reset_flag(FuriHalRtcFlag flag) { | |||||||
|     DeveloperReg* data = (DeveloperReg*)&data_reg; |     DeveloperReg* data = (DeveloperReg*)&data_reg; | ||||||
|     data->flags &= ~flag; |     data->flags &= ~flag; | ||||||
|     furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg); |     furi_hal_rtc_set_register(FuriHalRtcRegisterSystem, data_reg); | ||||||
|  | 
 | ||||||
|  |     if(flag & FuriHalRtcFlagDebug) { | ||||||
|  |         furi_hal_debug_disable(); | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| bool furi_hal_rtc_is_flag_set(FuriHalRtcFlag flag) { | bool furi_hal_rtc_is_flag_set(FuriHalRtcFlag flag) { | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| #include "furi_hal_spi.h" | #include "furi_hal_spi.h" | ||||||
| #include "furi_hal_resources.h" | #include "furi_hal_resources.h" | ||||||
|  | #include <furi_hal_power.h> | ||||||
| 
 | 
 | ||||||
| #include <stdbool.h> | #include <stdbool.h> | ||||||
| #include <string.h> | #include <string.h> | ||||||
| @ -55,6 +56,8 @@ void furi_hal_spi_bus_handle_deinit(FuriHalSpiBusHandle* handle) { | |||||||
| void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) { | void furi_hal_spi_acquire(FuriHalSpiBusHandle* handle) { | ||||||
|     furi_assert(handle); |     furi_assert(handle); | ||||||
| 
 | 
 | ||||||
|  |     furi_hal_power_insomnia_enter(); | ||||||
|  | 
 | ||||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventLock); |     handle->bus->callback(handle->bus, FuriHalSpiBusEventLock); | ||||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate); |     handle->bus->callback(handle->bus, FuriHalSpiBusEventActivate); | ||||||
| 
 | 
 | ||||||
| @ -75,6 +78,8 @@ void furi_hal_spi_release(FuriHalSpiBusHandle* handle) { | |||||||
|     // Bus events
 |     // Bus events
 | ||||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventDeactivate); |     handle->bus->callback(handle->bus, FuriHalSpiBusEventDeactivate); | ||||||
|     handle->bus->callback(handle->bus, FuriHalSpiBusEventUnlock); |     handle->bus->callback(handle->bus, FuriHalSpiBusEventUnlock); | ||||||
|  | 
 | ||||||
|  |     furi_hal_power_insomnia_exit(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) { | static void furi_hal_spi_bus_end_txrx(FuriHalSpiBusHandle* handle, uint32_t timeout) { | ||||||
|  | |||||||
| @ -8,6 +8,8 @@ | |||||||
| #include <furi.h> | #include <furi.h> | ||||||
| #include <furi_hal_delay.h> | #include <furi_hal_delay.h> | ||||||
| 
 | 
 | ||||||
|  | static bool furi_hal_usart_prev_enabled[2]; | ||||||
|  | 
 | ||||||
| static void (*irq_cb[2])(uint8_t ev, uint8_t data, void* context); | static void (*irq_cb[2])(uint8_t ev, uint8_t data, void* context); | ||||||
| static void* irq_ctx[2]; | static void* irq_ctx[2]; | ||||||
| 
 | 
 | ||||||
| @ -44,7 +46,6 @@ static void furi_hal_usart_init(uint32_t baud) { | |||||||
|         ; |         ; | ||||||
| 
 | 
 | ||||||
|     LL_USART_EnableIT_RXNE_RXFNE(USART1); |     LL_USART_EnableIT_RXNE_RXFNE(USART1); | ||||||
|     LL_USART_EnableIT_IDLE(USART1); |  | ||||||
|     NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); |     NVIC_SetPriority(USART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -81,7 +82,6 @@ static void furi_hal_lpuart_init(uint32_t baud) { | |||||||
|     furi_hal_uart_set_br(FuriHalUartIdLPUART1, baud); |     furi_hal_uart_set_br(FuriHalUartIdLPUART1, baud); | ||||||
| 
 | 
 | ||||||
|     LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1); |     LL_LPUART_EnableIT_RXNE_RXFNE(LPUART1); | ||||||
|     LL_LPUART_EnableIT_IDLE(LPUART1); |  | ||||||
|     NVIC_SetPriority(LPUART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); |     NVIC_SetPriority(LPUART1_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -136,6 +136,28 @@ void furi_hal_uart_deinit(FuriHalUartId ch) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void furi_hal_uart_suspend(FuriHalUartId channel) { | ||||||
|  |     if(channel == FuriHalUartIdLPUART1 && LL_LPUART_IsEnabled(LPUART1)) { | ||||||
|  |         LL_LPUART_Disable(LPUART1); | ||||||
|  |         furi_hal_usart_prev_enabled[channel] = true; | ||||||
|  |     } else if(channel == FuriHalUartIdUSART1 && LL_USART_IsEnabled(USART1)) { | ||||||
|  |         LL_USART_Disable(USART1); | ||||||
|  |         furi_hal_usart_prev_enabled[channel] = true; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void furi_hal_uart_resume(FuriHalUartId channel) { | ||||||
|  |     if(!furi_hal_usart_prev_enabled[channel]) { | ||||||
|  |         return; | ||||||
|  |     } else if(channel == FuriHalUartIdLPUART1) { | ||||||
|  |         LL_LPUART_Enable(LPUART1); | ||||||
|  |     } else if(channel == FuriHalUartIdUSART1) { | ||||||
|  |         LL_USART_Enable(USART1); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     furi_hal_usart_prev_enabled[channel] = false; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void furi_hal_uart_tx(FuriHalUartId ch, uint8_t* buffer, size_t buffer_size) { | void furi_hal_uart_tx(FuriHalUartId ch, uint8_t* buffer, size_t buffer_size) { | ||||||
|     if(ch == FuriHalUartIdUSART1) { |     if(ch == FuriHalUartIdUSART1) { | ||||||
|         if(LL_USART_IsEnabled(USART1) == 0) return; |         if(LL_USART_IsEnabled(USART1) == 0) return; | ||||||
| @ -189,22 +211,15 @@ void LPUART1_IRQHandler(void) { | |||||||
|     if(LL_LPUART_IsActiveFlag_RXNE_RXFNE(LPUART1)) { |     if(LL_LPUART_IsActiveFlag_RXNE_RXFNE(LPUART1)) { | ||||||
|         uint8_t data = LL_LPUART_ReceiveData8(LPUART1); |         uint8_t data = LL_LPUART_ReceiveData8(LPUART1); | ||||||
|         irq_cb[FuriHalUartIdLPUART1](UartIrqEventRXNE, data, irq_ctx[FuriHalUartIdLPUART1]); |         irq_cb[FuriHalUartIdLPUART1](UartIrqEventRXNE, data, irq_ctx[FuriHalUartIdLPUART1]); | ||||||
|     } else if(LL_LPUART_IsActiveFlag_IDLE(LPUART1)) { |  | ||||||
|         irq_cb[FuriHalUartIdLPUART1](UartIrqEventIDLE, 0, irq_ctx[FuriHalUartIdLPUART1]); |  | ||||||
|         LL_LPUART_ClearFlag_IDLE(LPUART1); |  | ||||||
|     } else if(LL_LPUART_IsActiveFlag_ORE(LPUART1)) { |     } else if(LL_LPUART_IsActiveFlag_ORE(LPUART1)) { | ||||||
|         LL_LPUART_ClearFlag_ORE(LPUART1); |         LL_LPUART_ClearFlag_ORE(LPUART1); | ||||||
|     } |     } | ||||||
|     //TODO: more events
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void USART1_IRQHandler(void) { | void USART1_IRQHandler(void) { | ||||||
|     if(LL_USART_IsActiveFlag_RXNE_RXFNE(USART1)) { |     if(LL_USART_IsActiveFlag_RXNE_RXFNE(USART1)) { | ||||||
|         uint8_t data = LL_USART_ReceiveData8(USART1); |         uint8_t data = LL_USART_ReceiveData8(USART1); | ||||||
|         irq_cb[FuriHalUartIdUSART1](UartIrqEventRXNE, data, irq_ctx[FuriHalUartIdUSART1]); |         irq_cb[FuriHalUartIdUSART1](UartIrqEventRXNE, data, irq_ctx[FuriHalUartIdUSART1]); | ||||||
|     } else if(LL_USART_IsActiveFlag_IDLE(USART1)) { |  | ||||||
|         irq_cb[FuriHalUartIdUSART1](UartIrqEventIDLE, 0, irq_ctx[FuriHalUartIdUSART1]); |  | ||||||
|         LL_USART_ClearFlag_IDLE(USART1); |  | ||||||
|     } else if(LL_USART_IsActiveFlag_ORE(USART1)) { |     } else if(LL_USART_IsActiveFlag_ORE(USART1)) { | ||||||
|         LL_USART_ClearFlag_ORE(USART1); |         LL_USART_ClearFlag_ORE(USART1); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -27,8 +27,6 @@ typedef enum { | |||||||
|  */ |  */ | ||||||
| typedef enum { | typedef enum { | ||||||
|     UartIrqEventRXNE, |     UartIrqEventRXNE, | ||||||
|     UartIrqEventIDLE, |  | ||||||
|     //TODO: more events
 |  | ||||||
| } UartIrqEvent; | } UartIrqEvent; | ||||||
| 
 | 
 | ||||||
| /**
 | /**
 | ||||||
| @ -46,6 +44,20 @@ void furi_hal_uart_init(FuriHalUartId channel, uint32_t baud); | |||||||
|  */ |  */ | ||||||
| void furi_hal_uart_deinit(FuriHalUartId channel); | void furi_hal_uart_deinit(FuriHalUartId channel); | ||||||
| 
 | 
 | ||||||
|  | /**
 | ||||||
|  |  * Suspend UART operation | ||||||
|  |  * Disables UART hardware, settings and callbacks are preserved | ||||||
|  |  * @param channel UART channel | ||||||
|  |  */ | ||||||
|  | void furi_hal_uart_suspend(FuriHalUartId channel); | ||||||
|  | 
 | ||||||
|  | /**
 | ||||||
|  |  * Resume UART operation | ||||||
|  |  * Resumes UART hardware from suspended state | ||||||
|  |  * @param channel UART channel | ||||||
|  |  */ | ||||||
|  | void furi_hal_uart_resume(FuriHalUartId channel); | ||||||
|  | 
 | ||||||
| /**
 | /**
 | ||||||
|  * Changes UART baudrate |  * Changes UART baudrate | ||||||
|  * @param channel UART channel |  * @param channel UART channel | ||||||
|  | |||||||
| @ -76,7 +76,9 @@ void furi_hal_usb_init(void) { | |||||||
|     usb.enabled = false; |     usb.enabled = false; | ||||||
|     usb.if_cur = NULL; |     usb.if_cur = NULL; | ||||||
|     NVIC_SetPriority(USB_LP_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); |     NVIC_SetPriority(USB_LP_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 5, 0)); | ||||||
|  |     NVIC_SetPriority(USB_HP_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0)); | ||||||
|     NVIC_EnableIRQ(USB_LP_IRQn); |     NVIC_EnableIRQ(USB_LP_IRQn); | ||||||
|  |     NVIC_EnableIRQ(USB_HP_IRQn); | ||||||
| 
 | 
 | ||||||
|     usb.thread = furi_thread_alloc(); |     usb.thread = furi_thread_alloc(); | ||||||
|     furi_thread_set_name(usb.thread, "UsbDriver"); |     furi_thread_set_name(usb.thread, "UsbDriver"); | ||||||
|  | |||||||
| @ -119,6 +119,10 @@ ifeq ($(FURI_HAL_USB_VCP_DEBUG), 1) | |||||||
| CFLAGS += -DFURI_HAL_USB_VCP_DEBUG | CFLAGS += -DFURI_HAL_USB_VCP_DEBUG | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
|  | ifeq ($(FURI_HAL_POWER_DEEP_SLEEP_ENABLED), 1) | ||||||
|  | CFLAGS += -DFURI_HAL_POWER_DEEP_SLEEP_ENABLED | ||||||
|  | endif | ||||||
|  | 
 | ||||||
| FURI_HAL_SUBGHZ_TX_GPIO ?= 0 | FURI_HAL_SUBGHZ_TX_GPIO ?= 0 | ||||||
| ifneq ($(FURI_HAL_SUBGHZ_TX_GPIO), 0) | ifneq ($(FURI_HAL_SUBGHZ_TX_GPIO), 0) | ||||||
| CFLAGS += -DFURI_HAL_SUBGHZ_TX_GPIO=$(FURI_HAL_SUBGHZ_TX_GPIO) | CFLAGS += -DFURI_HAL_SUBGHZ_TX_GPIO=$(FURI_HAL_SUBGHZ_TX_GPIO) | ||||||
| @ -128,6 +132,10 @@ ifeq ($(INVERT_RFID_IN), 1) | |||||||
| CFLAGS += -DINVERT_RFID_IN | CFLAGS += -DINVERT_RFID_IN | ||||||
| endif | endif | ||||||
| 
 | 
 | ||||||
|  | ifeq ($(BLE_GLUE_DEBUG), 1) | ||||||
|  | CFLAGS += -DBLE_GLUE_DEBUG | ||||||
|  | endif | ||||||
|  | 
 | ||||||
| FURI_HAL_DIR = $(TARGET_DIR)/furi_hal | FURI_HAL_DIR = $(TARGET_DIR)/furi_hal | ||||||
| CFLAGS += -I$(FURI_HAL_DIR) | CFLAGS += -I$(FURI_HAL_DIR) | ||||||
| C_SOURCES += $(wildcard $(FURI_HAL_DIR)/*.c) | C_SOURCES += $(wildcard $(FURI_HAL_DIR)/*.c) | ||||||
|  | |||||||
| @ -12,6 +12,7 @@ template <unsigned int N> struct STOP_EXTERNING_ME {}; | |||||||
| #include "furi_hal_clock.h" | #include "furi_hal_clock.h" | ||||||
| #include "furi_hal_crypto.h" | #include "furi_hal_crypto.h" | ||||||
| #include "furi_hal_console.h" | #include "furi_hal_console.h" | ||||||
|  | #include "furi_hal_debug.h" | ||||||
| #include "furi_hal_os.h" | #include "furi_hal_os.h" | ||||||
| #include "furi_hal_sd.h" | #include "furi_hal_sd.h" | ||||||
| #include "furi_hal_i2c.h" | #include "furi_hal_i2c.h" | ||||||
|  | |||||||
| @ -68,6 +68,12 @@ FuriHalBtStack furi_hal_bt_get_radio_stack(); | |||||||
| */ | */ | ||||||
| bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb, void* context); | bool furi_hal_bt_start_app(FuriHalBtProfile profile, GapEventCallback event_cb, void* context); | ||||||
| 
 | 
 | ||||||
|  | /** Reinitialize core2
 | ||||||
|  |  *  | ||||||
|  |  * Also can be used to prepare core2 for stop modes | ||||||
|  |  */ | ||||||
|  | void furi_hal_bt_reinit(); | ||||||
|  | 
 | ||||||
| /** Change BLE app
 | /** Change BLE app
 | ||||||
|  * Restarts 2nd core |  * Restarts 2nd core | ||||||
|  * |  * | ||||||
|  | |||||||
							
								
								
									
										23
									
								
								firmware/targets/furi_hal_include/furi_hal_debug.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								firmware/targets/furi_hal_include/furi_hal_debug.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,23 @@ | |||||||
|  | /**
 | ||||||
|  |  * @file furi_hal_debug.h | ||||||
|  |  * Debug HAL API | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <stdint.h> | ||||||
|  | #include <stdbool.h> | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | extern "C" { | ||||||
|  | #endif | ||||||
|  | 
 | ||||||
|  | /** Enable MCU debug */ | ||||||
|  | void furi_hal_debug_enable(); | ||||||
|  | 
 | ||||||
|  | /** Disable MCU debug */ | ||||||
|  | void furi_hal_debug_disable(); | ||||||
|  | 
 | ||||||
|  | #ifdef __cplusplus | ||||||
|  | } | ||||||
|  | #endif | ||||||
| @ -85,6 +85,9 @@ uint8_t furi_hal_power_get_bat_health_pct(); | |||||||
|  */ |  */ | ||||||
| bool furi_hal_power_is_charging(); | bool furi_hal_power_is_charging(); | ||||||
| 
 | 
 | ||||||
|  | /** Switch MCU to SHUTDOWN */ | ||||||
|  | void furi_hal_power_shutdown(); | ||||||
|  | 
 | ||||||
| /** Poweroff device
 | /** Poweroff device
 | ||||||
|  */ |  */ | ||||||
| void furi_hal_power_off(); | void furi_hal_power_off(); | ||||||
|  | |||||||
| @ -17,7 +17,7 @@ uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, vo | |||||||
|         asm("nop"); |         asm("nop"); | ||||||
|         break; |         break; | ||||||
|     case U8X8_MSG_GPIO_RESET: |     case U8X8_MSG_GPIO_RESET: | ||||||
|         furi_hal_gpio_write(&gpio_display_rst, arg_int); |         furi_hal_gpio_write(&gpio_display_rst_n, arg_int); | ||||||
|         break; |         break; | ||||||
|     default: |     default: | ||||||
|         return 0; |         return 0; | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Georgii Surkov
						Georgii Surkov