BleGlue: reorder initialization sequence, move core2 start to early stage. (#816)
This commit is contained in:
		@@ -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");
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include <stdbool.h>
 | 
			
		||||
 | 
			
		||||
#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
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,10 +6,19 @@
 | 
			
		||||
 | 
			
		||||
#include <furi.h>
 | 
			
		||||
 | 
			
		||||
#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() {
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user