diff --git a/firmware/targets/f6/ble-glue/ble_glue.c b/firmware/targets/f6/ble-glue/ble_glue.c index 35c16223..45503683 100644 --- a/firmware/targets/f6/ble-glue/ble_glue.c +++ b/firmware/targets/f6/ble-glue/ble_glue.c @@ -19,6 +19,16 @@ PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t ble_glue_system_cmd_b PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_system_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255U]; PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_ble_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255]; +typedef enum { + // Stage 1: core2 startup and FUS + BleGlueStatusStartup, + BleGlueStatusBroken, + BleGlueStatusFusStarted, + // Stage 2: radio stack + BleGlueStatusRadioStackStarted, + BleGlueStatusRadioStackMissing +} BleGlueStatus; + typedef struct { osMutexId_t shci_mtx; osSemaphoreId_t shci_sem; @@ -35,13 +45,6 @@ static void ble_glue_user_event_thread(void *argument); static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status); static void ble_glue_sys_user_event_callback(void* pPayload); -BleGlueStatus ble_glue_get_status() { - if(!ble_glue) { - return BleGlueStatusUninitialized; - } - return ble_glue->status; -} - void ble_glue_set_key_storage_changed_callback(BleGlueKeyStorageChangedCallback callback, void* context) { furi_assert(ble_glue); furi_assert(callback); @@ -96,6 +99,68 @@ void ble_glue_init() { */ } +static bool ble_glue_wait_status(BleGlueStatus status) { + bool ret = false; + size_t countdown = 1000; + while (countdown > 0) { + if (ble_glue->status == status) { + ret = true; + break; + } + countdown--; + osDelay(1); + } + return ret; +} + +bool ble_glue_start() { + furi_assert(ble_glue); + + if (!ble_glue_wait_status(BleGlueStatusFusStarted)) { + // shutdown core2 power + FURI_LOG_E(TAG, "Core2 catastrophic failure, cutting its power"); + LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); + ble_glue->status = BleGlueStatusBroken; + furi_hal_power_insomnia_exit(); + return false; + } + + bool ret = false; + furi_hal_power_insomnia_enter(); + if(ble_app_init()) { + FURI_LOG_I(TAG, "Radio stack started"); + ble_glue->status = BleGlueStatusRadioStackStarted; + ret = true; + if(SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7) == SHCI_Success) { + FURI_LOG_I(TAG, "Flash activity control switched to SEM7"); + } else { + FURI_LOG_E(TAG, "Failed to switch flash activity control to SEM7"); + } + } else { + FURI_LOG_E(TAG, "Radio stack startup failed"); + ble_glue->status = BleGlueStatusRadioStackMissing; + } + furi_hal_power_insomnia_exit(); + + return ret; +} + +bool ble_glue_is_alive() { + if(!ble_glue) { + return false; + } + + return ble_glue->status >= BleGlueStatusFusStarted; +} + +bool ble_glue_is_radio_stack_ready() { + if(!ble_glue) { + return false; + } + + return ble_glue->status == BleGlueStatusRadioStackStarted; +} + static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status) { switch (status) { case SHCI_TL_CmdBusy: @@ -126,18 +191,8 @@ static void ble_glue_sys_user_event_callback( void * pPayload ) { TL_AsynchEvt_t *p_sys_event = (TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload); if(p_sys_event->subevtcode == SHCI_SUB_EVT_CODE_READY) { - if(ble_app_init()) { - FURI_LOG_I(TAG, "BLE stack started"); - ble_glue->status = BleGlueStatusStarted; - if(SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7) == SHCI_Success) { - FURI_LOG_I(TAG, "Flash activity control switched to SEM7"); - } else { - FURI_LOG_E(TAG, "Failed to switch flash activity control to SEM7"); - } - } else { - FURI_LOG_E(TAG, "BLE stack startup failed"); - ble_glue->status = BleGlueStatusBleStackMissing; - } + FURI_LOG_I(TAG, "Fus started"); + ble_glue->status = BleGlueStatusFusStarted; furi_hal_power_insomnia_exit(); } else if(p_sys_event->subevtcode == SHCI_SUB_EVT_ERROR_NOTIF) { FURI_LOG_E(TAG, "Error during initialization"); diff --git a/firmware/targets/f6/ble-glue/ble_glue.h b/firmware/targets/f6/ble-glue/ble_glue.h index e9d6c03f..ac668c42 100644 --- a/firmware/targets/f6/ble-glue/ble_glue.h +++ b/firmware/targets/f6/ble-glue/ble_glue.h @@ -1,6 +1,7 @@ #pragma once #include +#include #ifdef __cplusplus extern "C" { @@ -8,17 +9,33 @@ extern "C" { typedef void(*BleGlueKeyStorageChangedCallback)(uint8_t* change_addr_start, uint16_t size, void* context); -typedef enum { - BleGlueStatusUninitialized, - BleGlueStatusStartup, - BleGlueStatusBleStackMissing, - BleGlueStatusStarted -} BleGlueStatus; +/** Initialize start core2 and initialize transport */ void ble_glue_init(); -BleGlueStatus ble_glue_get_status(); +/** Start Core2 Radio stack + * + * @return true on success + */ +bool ble_glue_start(); +/** Is core2 alive and at least FUS is running + * + * @return true if core2 is alive + */ +bool ble_glue_is_alive(); + +/** Is core2 radio stack present and ready + * + * @return true if present and ready + */ +bool ble_glue_is_radio_stack_ready(); + +/** Set callback for NVM in RAM changes + * + * @param[in] callback The callback to call on NVM change + * @param context The context for callback + */ void ble_glue_set_key_storage_changed_callback(BleGlueKeyStorageChangedCallback callback, void* context); #ifdef __cplusplus diff --git a/firmware/targets/f6/ble-glue/gap.c b/firmware/targets/f6/ble-glue/gap.c index 7c7041cb..2fd29f10 100644 --- a/firmware/targets/f6/ble-glue/gap.c +++ b/firmware/targets/f6/ble-glue/gap.c @@ -374,7 +374,7 @@ static void gap_advetise_timer_callback(void* context) { } bool gap_init(BleEventCallback on_event_cb, void* context) { - if (ble_glue_get_status() != BleGlueStatusStarted) { + if (!ble_glue_is_radio_stack_ready()) { return false; } diff --git a/firmware/targets/f6/furi-hal/furi-hal-bt.c b/firmware/targets/f6/furi-hal/furi-hal-bt.c index 95a07b9d..b74a9e29 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-bt.c +++ b/firmware/targets/f6/furi-hal/furi-hal-bt.c @@ -6,10 +6,19 @@ #include +#define TAG "FuriHalBt" + osMutexId_t furi_hal_bt_core2_mtx = NULL; void furi_hal_bt_init() { furi_hal_bt_core2_mtx = osMutexNew(NULL); + furi_assert(furi_hal_bt_core2_mtx); + + // Explicitly tell that we are in charge of CLK48 domain + HAL_HSEM_FastTake(CFG_HW_CLK48_CONFIG_SEMID); + + // Start Core2 + ble_glue_init(); } void furi_hal_bt_lock_core2() { @@ -22,30 +31,16 @@ void furi_hal_bt_unlock_core2() { furi_check(osMutexRelease(furi_hal_bt_core2_mtx) == osOK); } -static bool furi_hal_bt_wait_startup() { - uint16_t counter = 0; - while (!(ble_glue_get_status() == BleGlueStatusStarted || ble_glue_get_status() == BleGlueStatusBleStackMissing)) { - osDelay(10); - counter++; - if (counter > 1000) { - return false; - } - } - return true; -} - bool furi_hal_bt_start_core2() { furi_assert(furi_hal_bt_core2_mtx); - bool ret = false; osMutexAcquire(furi_hal_bt_core2_mtx, osWaitForever); // Explicitly tell that we are in charge of CLK48 domain HAL_HSEM_FastTake(CFG_HW_CLK48_CONFIG_SEMID); // Start Core2 - ble_glue_init(); - // Wait for Core2 start - ret = furi_hal_bt_wait_startup(); + bool ret = ble_glue_start(); osMutexRelease(furi_hal_bt_core2_mtx); + return ret; } @@ -84,14 +79,8 @@ bool furi_hal_bt_tx(uint8_t* data, uint16_t size) { return serial_svc_update_tx(data, size); } -bool furi_hal_bt_get_key_storage_buff(uint8_t** key_buff_addr, uint16_t* key_buff_size) { - bool ret = false; - BleGlueStatus status = ble_glue_get_status(); - if(status == BleGlueStatusUninitialized || BleGlueStatusStarted) { - ble_app_get_key_storage_buff(key_buff_addr, key_buff_size); - ret = true; - } - return ret; +void furi_hal_bt_get_key_storage_buff(uint8_t** key_buff_addr, uint16_t* key_buff_size) { + ble_app_get_key_storage_buff(key_buff_addr, key_buff_size); } void furi_hal_bt_set_key_storage_change_callback(BleGlueKeyStorageChangedCallback callback, void* context) { @@ -110,8 +99,7 @@ void furi_hal_bt_nvm_sram_sem_release() { } void furi_hal_bt_dump_state(string_t buffer) { - BleGlueStatus status = ble_glue_get_status(); - if (status == BleGlueStatusStarted) { + if (furi_hal_bt_is_alive()) { uint8_t HCI_Version; uint16_t HCI_Revision; uint8_t LMP_PAL_Version; @@ -132,8 +120,7 @@ void furi_hal_bt_dump_state(string_t buffer) { } bool furi_hal_bt_is_alive() { - BleGlueStatus status = ble_glue_get_status(); - return (status == BleGlueStatusBleStackMissing) || (status == BleGlueStatusStarted); + return ble_glue_is_alive(); } bool furi_hal_bt_is_active() { diff --git a/firmware/targets/f6/furi-hal/furi-hal-flash.c b/firmware/targets/f6/furi-hal/furi-hal-flash.c index 8bee45c0..156a26a9 100644 --- a/firmware/targets/f6/furi-hal/furi-hal-flash.c +++ b/firmware/targets/f6/furi-hal/furi-hal-flash.c @@ -127,8 +127,7 @@ static void furi_hal_flash_begin(bool erase_flag) { furi_hal_bt_lock_core2(); // If Core2 is running use IPC locking - BleGlueStatus status = ble_glue_get_status(); - if(status == BleGlueStatusStarted || status == BleGlueStatusBleStackMissing) { + if(furi_hal_bt_is_alive()) { furi_hal_flash_begin_with_core2(erase_flag); } else { furi_hal_flash_unlock(); @@ -159,8 +158,7 @@ static void furi_hal_flash_end_with_core2(bool erase_flag) { static void furi_hal_flash_end(bool erase_flag) { // If Core2 is running use IPC locking - BleGlueStatus status = ble_glue_get_status(); - if(status == BleGlueStatusStarted || status == BleGlueStatusBleStackMissing) { + if(furi_hal_bt_is_alive()) { furi_hal_flash_end_with_core2(erase_flag); } else { furi_hal_flash_lock(); diff --git a/firmware/targets/f7/ble-glue/ble_glue.c b/firmware/targets/f7/ble-glue/ble_glue.c index 35c16223..45503683 100644 --- a/firmware/targets/f7/ble-glue/ble_glue.c +++ b/firmware/targets/f7/ble-glue/ble_glue.c @@ -19,6 +19,16 @@ PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t ble_glue_system_cmd_b PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_system_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255U]; PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_ble_spare_event_buff[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255]; +typedef enum { + // Stage 1: core2 startup and FUS + BleGlueStatusStartup, + BleGlueStatusBroken, + BleGlueStatusFusStarted, + // Stage 2: radio stack + BleGlueStatusRadioStackStarted, + BleGlueStatusRadioStackMissing +} BleGlueStatus; + typedef struct { osMutexId_t shci_mtx; osSemaphoreId_t shci_sem; @@ -35,13 +45,6 @@ static void ble_glue_user_event_thread(void *argument); static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status); static void ble_glue_sys_user_event_callback(void* pPayload); -BleGlueStatus ble_glue_get_status() { - if(!ble_glue) { - return BleGlueStatusUninitialized; - } - return ble_glue->status; -} - void ble_glue_set_key_storage_changed_callback(BleGlueKeyStorageChangedCallback callback, void* context) { furi_assert(ble_glue); furi_assert(callback); @@ -96,6 +99,68 @@ void ble_glue_init() { */ } +static bool ble_glue_wait_status(BleGlueStatus status) { + bool ret = false; + size_t countdown = 1000; + while (countdown > 0) { + if (ble_glue->status == status) { + ret = true; + break; + } + countdown--; + osDelay(1); + } + return ret; +} + +bool ble_glue_start() { + furi_assert(ble_glue); + + if (!ble_glue_wait_status(BleGlueStatusFusStarted)) { + // shutdown core2 power + FURI_LOG_E(TAG, "Core2 catastrophic failure, cutting its power"); + LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); + ble_glue->status = BleGlueStatusBroken; + furi_hal_power_insomnia_exit(); + return false; + } + + bool ret = false; + furi_hal_power_insomnia_enter(); + if(ble_app_init()) { + FURI_LOG_I(TAG, "Radio stack started"); + ble_glue->status = BleGlueStatusRadioStackStarted; + ret = true; + if(SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7) == SHCI_Success) { + FURI_LOG_I(TAG, "Flash activity control switched to SEM7"); + } else { + FURI_LOG_E(TAG, "Failed to switch flash activity control to SEM7"); + } + } else { + FURI_LOG_E(TAG, "Radio stack startup failed"); + ble_glue->status = BleGlueStatusRadioStackMissing; + } + furi_hal_power_insomnia_exit(); + + return ret; +} + +bool ble_glue_is_alive() { + if(!ble_glue) { + return false; + } + + return ble_glue->status >= BleGlueStatusFusStarted; +} + +bool ble_glue_is_radio_stack_ready() { + if(!ble_glue) { + return false; + } + + return ble_glue->status == BleGlueStatusRadioStackStarted; +} + static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status) { switch (status) { case SHCI_TL_CmdBusy: @@ -126,18 +191,8 @@ static void ble_glue_sys_user_event_callback( void * pPayload ) { TL_AsynchEvt_t *p_sys_event = (TL_AsynchEvt_t*)(((tSHCI_UserEvtRxParam*)pPayload)->pckt->evtserial.evt.payload); if(p_sys_event->subevtcode == SHCI_SUB_EVT_CODE_READY) { - if(ble_app_init()) { - FURI_LOG_I(TAG, "BLE stack started"); - ble_glue->status = BleGlueStatusStarted; - if(SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7) == SHCI_Success) { - FURI_LOG_I(TAG, "Flash activity control switched to SEM7"); - } else { - FURI_LOG_E(TAG, "Failed to switch flash activity control to SEM7"); - } - } else { - FURI_LOG_E(TAG, "BLE stack startup failed"); - ble_glue->status = BleGlueStatusBleStackMissing; - } + FURI_LOG_I(TAG, "Fus started"); + ble_glue->status = BleGlueStatusFusStarted; furi_hal_power_insomnia_exit(); } else if(p_sys_event->subevtcode == SHCI_SUB_EVT_ERROR_NOTIF) { FURI_LOG_E(TAG, "Error during initialization"); diff --git a/firmware/targets/f7/ble-glue/ble_glue.h b/firmware/targets/f7/ble-glue/ble_glue.h index e9d6c03f..ac668c42 100644 --- a/firmware/targets/f7/ble-glue/ble_glue.h +++ b/firmware/targets/f7/ble-glue/ble_glue.h @@ -1,6 +1,7 @@ #pragma once #include +#include #ifdef __cplusplus extern "C" { @@ -8,17 +9,33 @@ extern "C" { typedef void(*BleGlueKeyStorageChangedCallback)(uint8_t* change_addr_start, uint16_t size, void* context); -typedef enum { - BleGlueStatusUninitialized, - BleGlueStatusStartup, - BleGlueStatusBleStackMissing, - BleGlueStatusStarted -} BleGlueStatus; +/** Initialize start core2 and initialize transport */ void ble_glue_init(); -BleGlueStatus ble_glue_get_status(); +/** Start Core2 Radio stack + * + * @return true on success + */ +bool ble_glue_start(); +/** Is core2 alive and at least FUS is running + * + * @return true if core2 is alive + */ +bool ble_glue_is_alive(); + +/** Is core2 radio stack present and ready + * + * @return true if present and ready + */ +bool ble_glue_is_radio_stack_ready(); + +/** Set callback for NVM in RAM changes + * + * @param[in] callback The callback to call on NVM change + * @param context The context for callback + */ void ble_glue_set_key_storage_changed_callback(BleGlueKeyStorageChangedCallback callback, void* context); #ifdef __cplusplus diff --git a/firmware/targets/f7/ble-glue/gap.c b/firmware/targets/f7/ble-glue/gap.c index 7c7041cb..2fd29f10 100644 --- a/firmware/targets/f7/ble-glue/gap.c +++ b/firmware/targets/f7/ble-glue/gap.c @@ -374,7 +374,7 @@ static void gap_advetise_timer_callback(void* context) { } bool gap_init(BleEventCallback on_event_cb, void* context) { - if (ble_glue_get_status() != BleGlueStatusStarted) { + if (!ble_glue_is_radio_stack_ready()) { return false; } diff --git a/firmware/targets/f7/furi-hal/furi-hal-bt.c b/firmware/targets/f7/furi-hal/furi-hal-bt.c index 95a07b9d..b74a9e29 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-bt.c +++ b/firmware/targets/f7/furi-hal/furi-hal-bt.c @@ -6,10 +6,19 @@ #include +#define TAG "FuriHalBt" + osMutexId_t furi_hal_bt_core2_mtx = NULL; void furi_hal_bt_init() { furi_hal_bt_core2_mtx = osMutexNew(NULL); + furi_assert(furi_hal_bt_core2_mtx); + + // Explicitly tell that we are in charge of CLK48 domain + HAL_HSEM_FastTake(CFG_HW_CLK48_CONFIG_SEMID); + + // Start Core2 + ble_glue_init(); } void furi_hal_bt_lock_core2() { @@ -22,30 +31,16 @@ void furi_hal_bt_unlock_core2() { furi_check(osMutexRelease(furi_hal_bt_core2_mtx) == osOK); } -static bool furi_hal_bt_wait_startup() { - uint16_t counter = 0; - while (!(ble_glue_get_status() == BleGlueStatusStarted || ble_glue_get_status() == BleGlueStatusBleStackMissing)) { - osDelay(10); - counter++; - if (counter > 1000) { - return false; - } - } - return true; -} - bool furi_hal_bt_start_core2() { furi_assert(furi_hal_bt_core2_mtx); - bool ret = false; osMutexAcquire(furi_hal_bt_core2_mtx, osWaitForever); // Explicitly tell that we are in charge of CLK48 domain HAL_HSEM_FastTake(CFG_HW_CLK48_CONFIG_SEMID); // Start Core2 - ble_glue_init(); - // Wait for Core2 start - ret = furi_hal_bt_wait_startup(); + bool ret = ble_glue_start(); osMutexRelease(furi_hal_bt_core2_mtx); + return ret; } @@ -84,14 +79,8 @@ bool furi_hal_bt_tx(uint8_t* data, uint16_t size) { return serial_svc_update_tx(data, size); } -bool furi_hal_bt_get_key_storage_buff(uint8_t** key_buff_addr, uint16_t* key_buff_size) { - bool ret = false; - BleGlueStatus status = ble_glue_get_status(); - if(status == BleGlueStatusUninitialized || BleGlueStatusStarted) { - ble_app_get_key_storage_buff(key_buff_addr, key_buff_size); - ret = true; - } - return ret; +void furi_hal_bt_get_key_storage_buff(uint8_t** key_buff_addr, uint16_t* key_buff_size) { + ble_app_get_key_storage_buff(key_buff_addr, key_buff_size); } void furi_hal_bt_set_key_storage_change_callback(BleGlueKeyStorageChangedCallback callback, void* context) { @@ -110,8 +99,7 @@ void furi_hal_bt_nvm_sram_sem_release() { } void furi_hal_bt_dump_state(string_t buffer) { - BleGlueStatus status = ble_glue_get_status(); - if (status == BleGlueStatusStarted) { + if (furi_hal_bt_is_alive()) { uint8_t HCI_Version; uint16_t HCI_Revision; uint8_t LMP_PAL_Version; @@ -132,8 +120,7 @@ void furi_hal_bt_dump_state(string_t buffer) { } bool furi_hal_bt_is_alive() { - BleGlueStatus status = ble_glue_get_status(); - return (status == BleGlueStatusBleStackMissing) || (status == BleGlueStatusStarted); + return ble_glue_is_alive(); } bool furi_hal_bt_is_active() { diff --git a/firmware/targets/f7/furi-hal/furi-hal-flash.c b/firmware/targets/f7/furi-hal/furi-hal-flash.c index 8bee45c0..156a26a9 100644 --- a/firmware/targets/f7/furi-hal/furi-hal-flash.c +++ b/firmware/targets/f7/furi-hal/furi-hal-flash.c @@ -127,8 +127,7 @@ static void furi_hal_flash_begin(bool erase_flag) { furi_hal_bt_lock_core2(); // If Core2 is running use IPC locking - BleGlueStatus status = ble_glue_get_status(); - if(status == BleGlueStatusStarted || status == BleGlueStatusBleStackMissing) { + if(furi_hal_bt_is_alive()) { furi_hal_flash_begin_with_core2(erase_flag); } else { furi_hal_flash_unlock(); @@ -159,8 +158,7 @@ static void furi_hal_flash_end_with_core2(bool erase_flag) { static void furi_hal_flash_end(bool erase_flag) { // If Core2 is running use IPC locking - BleGlueStatus status = ble_glue_get_status(); - if(status == BleGlueStatusStarted || status == BleGlueStatusBleStackMissing) { + if(furi_hal_bt_is_alive()) { furi_hal_flash_end_with_core2(erase_flag); } else { furi_hal_flash_lock(); diff --git a/firmware/targets/furi-hal-include/furi-hal-bt.h b/firmware/targets/furi-hal-include/furi-hal-bt.h index acbdfc36..c7d86165 100644 --- a/firmware/targets/furi-hal-include/furi-hal-bt.h +++ b/firmware/targets/furi-hal-include/furi-hal-bt.h @@ -69,12 +69,10 @@ bool furi_hal_bt_is_alive(); /** Get key storage buffer address and size * - * @param key_buff_addr pointer to store buffer address - * @param key_buff_size pointer to store buffer size - * - * @return true on success + * @param key_buff_addr pointer to store buffer address + * @param key_buff_size pointer to store buffer size */ -bool furi_hal_bt_get_key_storage_buff(uint8_t** key_buff_addr, uint16_t* key_buff_size); +void furi_hal_bt_get_key_storage_buff(uint8_t** key_buff_addr, uint16_t* key_buff_size); /** Get SRAM2 hardware semaphore * @note Must be called before SRAM2 read/write operations