BleGlue: reorder initialization sequence, move core2 start to early stage. (#816)

This commit is contained in:
あく 2021-11-13 05:41:54 +03:00 committed by GitHub
parent 70d0519178
commit b2356c7318
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 235 additions and 123 deletions

View File

@ -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");

View File

@ -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

View File

@ -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;
}

View File

@ -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() {

View File

@ -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();

View File

@ -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");

View File

@ -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

View File

@ -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;
}

View File

@ -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() {

View File

@ -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();

View File

@ -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