[FL-1952] BLE bonding fix (#805)
* furi-hal-bt: add mutex guarding core2 state * ble-glue: configure ble keys storage in SRAM2 * bt: add load and save ble keys in internal storage * bt: improve work furi_hal_bt API * bt: rework app_entry -> ble_glue * bt: apply changes for f6 target * desktop: remove furi check * ble-glue: comment NVM in SRAM2 configuration * FuriHal: fix flash controller state corruption, fix incorrect semaphore release, implement C1-C2 flash controller access according to spec. Gui: change logging level. * Libs: better lfs integration with lfs_config. * Ble: switch C2 NVM to RAM. * FuriHalCrypto: ensure that core2 is alive before sending shci commands * Ble: fix incorrect nvm buffer size Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
		| @@ -427,16 +427,5 @@ typedef enum | ||||
| #define DBG_TRACE_MSG_QUEUE_SIZE 4096 | ||||
| #define MAX_DBG_TRACE_MSG_SIZE 1024 | ||||
|  | ||||
| /****************************************************************************** | ||||
|  * FreeRTOS | ||||
|  ******************************************************************************/ | ||||
| #define CFG_SHCI_USER_EVT_PROCESS_NAME        "ble_shci_evt" | ||||
| #define CFG_SHCI_USER_EVT_PROCESS_ATTR_BITS   (0) | ||||
| #define CFG_SHCI_USER_EVT_PROCESS_CB_MEM      (0) | ||||
| #define CFG_SHCI_USER_EVT_PROCESS_CB_SIZE     (0) | ||||
| #define CFG_SHCI_USER_EVT_PROCESS_STACK_MEM   (0) | ||||
| #define CFG_SHCI_USER_EVT_PROCESS_PRIORITY    osPriorityNone | ||||
| #define CFG_SHCI_USER_EVT_PROCESS_STACK_SIZE  (128 * 7) | ||||
|  | ||||
| #define CFG_OTP_BASE_ADDRESS    OTP_AREA_BASE | ||||
| #define CFG_OTP_END_ADRESS      OTP_AREA_END_ADDR | ||||
|   | ||||
| @@ -1,180 +0,0 @@ | ||||
| #include "app_common.h" | ||||
| #include "main.h" | ||||
| #include "app_entry.h" | ||||
| #include "ble_app.h" | ||||
| #include "ble.h" | ||||
| #include "tl.h" | ||||
| #include "cmsis_os.h" | ||||
| #include "shci_tl.h" | ||||
| #include "app_debug.h" | ||||
| #include <furi-hal.h> | ||||
|  | ||||
| extern RTC_HandleTypeDef hrtc; | ||||
|  | ||||
| #define POOL_SIZE (CFG_TLBLE_EVT_QUEUE_LENGTH*4U*DIVC(( sizeof(TL_PacketHeader_t) + TL_BLE_EVENT_FRAME_SIZE ), 4U)) | ||||
|  | ||||
| PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t EvtPool[POOL_SIZE]; | ||||
| PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t SystemCmdBuffer; | ||||
| PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t SystemSpareEvtBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255U]; | ||||
| PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t BleSpareEvtBuffer[sizeof(TL_PacketHeader_t) + TL_EVT_HDR_SIZE + 255]; | ||||
|  | ||||
| osMutexId_t MtxShciId; | ||||
| osSemaphoreId_t SemShciId; | ||||
| osThreadId_t ShciUserEvtProcessId; | ||||
|  | ||||
| volatile static BleGlueStatus ble_glue_status = BleGlueStatusUninitialized; | ||||
|  | ||||
| const osThreadAttr_t ShciUserEvtProcess_attr = { | ||||
|     .name = CFG_SHCI_USER_EVT_PROCESS_NAME, | ||||
|     .attr_bits = CFG_SHCI_USER_EVT_PROCESS_ATTR_BITS, | ||||
|     .cb_mem = CFG_SHCI_USER_EVT_PROCESS_CB_MEM, | ||||
|     .cb_size = CFG_SHCI_USER_EVT_PROCESS_CB_SIZE, | ||||
|     .stack_mem = CFG_SHCI_USER_EVT_PROCESS_STACK_MEM, | ||||
|     .priority = CFG_SHCI_USER_EVT_PROCESS_PRIORITY, | ||||
|     .stack_size = CFG_SHCI_USER_EVT_PROCESS_STACK_SIZE | ||||
| }; | ||||
|  | ||||
| static void ShciUserEvtProcess(void *argument); | ||||
| static void SystemPower_Config( void ); | ||||
| static void appe_Tl_Init( void ); | ||||
| static void APPE_SysStatusNot( SHCI_TL_CmdStatus_t status ); | ||||
| static void APPE_SysUserEvtRx( void * pPayload ); | ||||
|  | ||||
| BleGlueStatus APPE_Status() { | ||||
|   return ble_glue_status; | ||||
| } | ||||
|  | ||||
| void APPE_Init() { | ||||
|   ble_glue_status = BleGlueStatusStartup; | ||||
|   SystemPower_Config(); /**< Configure the system Power Mode */ | ||||
|  | ||||
|   // APPD_Init(); | ||||
|   furi_hal_power_insomnia_enter(); | ||||
|  | ||||
|   appe_Tl_Init();	/* Initialize all transport layers */ | ||||
|  | ||||
|   /** | ||||
|    * From now, the application is waiting for the ready event ( VS_HCI_C2_Ready ) | ||||
|    * received on the system channel before starting the Stack | ||||
|    * This system event is received with APPE_SysUserEvtRx() | ||||
|    */ | ||||
| } | ||||
|  | ||||
| /************************************************************* | ||||
|  * | ||||
|  * LOCAL FUNCTIONS | ||||
|  * | ||||
|  *************************************************************/ | ||||
|  | ||||
| /** | ||||
|  * @brief  Configure the system for power optimization | ||||
|  * | ||||
|  * @note  This API configures the system to be ready for low power mode | ||||
|  * | ||||
|  * @param  None | ||||
|  * @retval None | ||||
|  */ | ||||
| static void SystemPower_Config(void) { | ||||
|   // Select HSI as system clock source after Wake Up from Stop mode | ||||
|   LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI); | ||||
|  | ||||
|   /* Initialize the CPU2 reset value before starting CPU2 with C2BOOT */ | ||||
|   LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); | ||||
| } | ||||
|  | ||||
| static void appe_Tl_Init( void ) { | ||||
|   TL_MM_Config_t tl_mm_config; | ||||
|   SHCI_TL_HciInitConf_t SHci_Tl_Init_Conf; | ||||
|   /**< Reference table initialization */ | ||||
|   TL_Init(); | ||||
|  | ||||
|   MtxShciId = osMutexNew( NULL ); | ||||
|   SemShciId = osSemaphoreNew( 1, 0, NULL ); /*< Create the semaphore and make it busy at initialization */ | ||||
|  | ||||
|   /** FreeRTOS system task creation */ | ||||
|   ShciUserEvtProcessId = osThreadNew(ShciUserEvtProcess, NULL, &ShciUserEvtProcess_attr); | ||||
|  | ||||
|   /**< System channel initialization */ | ||||
|   SHci_Tl_Init_Conf.p_cmdbuffer = (uint8_t*)&SystemCmdBuffer; | ||||
|   SHci_Tl_Init_Conf.StatusNotCallBack = APPE_SysStatusNot; | ||||
|   shci_init(APPE_SysUserEvtRx, (void*) &SHci_Tl_Init_Conf); | ||||
|  | ||||
|   /**< Memory Manager channel initialization */ | ||||
|   tl_mm_config.p_BleSpareEvtBuffer = BleSpareEvtBuffer; | ||||
|   tl_mm_config.p_SystemSpareEvtBuffer = SystemSpareEvtBuffer; | ||||
|   tl_mm_config.p_AsynchEvtPool = EvtPool; | ||||
|   tl_mm_config.AsynchEvtPoolSize = POOL_SIZE; | ||||
|   TL_MM_Init( &tl_mm_config ); | ||||
|  | ||||
|   TL_Enable(); | ||||
| } | ||||
|  | ||||
| static void APPE_SysStatusNot( SHCI_TL_CmdStatus_t status ) { | ||||
|   switch (status) { | ||||
|     case SHCI_TL_CmdBusy: | ||||
|       osMutexAcquire( MtxShciId, osWaitForever ); | ||||
|       break; | ||||
|     case SHCI_TL_CmdAvailable: | ||||
|       osMutexRelease( MtxShciId ); | ||||
|       break; | ||||
|     default: | ||||
|       break; | ||||
|   } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The type of the payload for a system user event is tSHCI_UserEvtRxParam | ||||
|  * When the system event is both : | ||||
|  *    - a ready event (subevtcode = SHCI_SUB_EVT_CODE_READY) | ||||
|  *    - reported by the FUS (sysevt_ready_rsp == FUS_FW_RUNNING) | ||||
|  * The buffer shall not be released | ||||
|  * ( eg ((tSHCI_UserEvtRxParam*)pPayload)->status shall be set to SHCI_TL_UserEventFlow_Disable ) | ||||
|  * When the status is not filled, the buffer is released by default | ||||
|  */ | ||||
| static void APPE_SysUserEvtRx( void * pPayload ) { | ||||
|   UNUSED(pPayload); | ||||
|   /* Traces channel initialization */ | ||||
|   // APPD_EnableCPU2( ); | ||||
|    | ||||
|   if(ble_app_init()) { | ||||
|     FURI_LOG_I("Core2", "BLE stack started"); | ||||
|     ble_glue_status = BleGlueStatusStarted; | ||||
|   } else { | ||||
|     FURI_LOG_E("Core2", "BLE stack startup failed"); | ||||
|     ble_glue_status = BleGlueStatusBroken; | ||||
|   } | ||||
|   furi_hal_power_insomnia_exit(); | ||||
| } | ||||
|  | ||||
| /************************************************************* | ||||
|  * | ||||
|  * FREERTOS WRAPPER FUNCTIONS | ||||
|  * | ||||
| *************************************************************/ | ||||
| static void ShciUserEvtProcess(void *argument) { | ||||
|   UNUSED(argument); | ||||
|   for(;;) { | ||||
|     osThreadFlagsWait(1, osFlagsWaitAny, osWaitForever); | ||||
|     shci_user_evt_proc(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| /************************************************************* | ||||
|  * | ||||
|  * WRAP FUNCTIONS | ||||
|  * | ||||
|  *************************************************************/ | ||||
| void shci_notify_asynch_evt(void* pdata) { | ||||
|   UNUSED(pdata); | ||||
|   osThreadFlagsSet( ShciUserEvtProcessId, 1 ); | ||||
| } | ||||
|  | ||||
| void shci_cmd_resp_release(uint32_t flag) { | ||||
|   UNUSED(flag); | ||||
|   osSemaphoreRelease( SemShciId ); | ||||
| } | ||||
|  | ||||
| void shci_cmd_resp_wait(uint32_t timeout) { | ||||
|   UNUSED(timeout); | ||||
|   osSemaphoreAcquire( SemShciId, osWaitForever ); | ||||
| } | ||||
| @@ -1,20 +0,0 @@ | ||||
| #pragma once | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| typedef enum { | ||||
|     BleGlueStatusUninitialized, | ||||
|     BleGlueStatusStartup, | ||||
|     BleGlueStatusBroken, | ||||
|     BleGlueStatusStarted | ||||
| } BleGlueStatus; | ||||
|  | ||||
| void APPE_Init(); | ||||
|  | ||||
| BleGlueStatus APPE_Status(); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } /* extern "C" */ | ||||
| #endif | ||||
| @@ -11,6 +11,7 @@ | ||||
| #define BLE_APP_TAG "ble app" | ||||
|  | ||||
| PLACE_IN_SECTION("MB_MEM1") ALIGN(4) static TL_CmdPacket_t ble_app_cmd_buffer; | ||||
| PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint32_t ble_app_nvm[BLE_NVM_SRAM_SIZE]; | ||||
|  | ||||
| typedef struct { | ||||
|     osMutexId_t hci_mtx; | ||||
| @@ -26,8 +27,8 @@ static void ble_app_hci_event_handler(void * pPayload); | ||||
| static void ble_app_hci_status_not_handler(HCI_TL_CmdStatus_t status); | ||||
|  | ||||
| bool ble_app_init() { | ||||
|     SHCI_CmdStatus_t status; | ||||
|     ble_app = furi_alloc(sizeof(BleApp)); | ||||
|  | ||||
|     // Allocate semafore and mutex for ble command buffer access | ||||
|     ble_app->hci_mtx = osMutexNew(NULL); | ||||
|     ble_app->hci_sem = osSemaphoreNew(1, 0, NULL); | ||||
| @@ -43,6 +44,18 @@ bool ble_app_init() { | ||||
|     }; | ||||
|     hci_init(ble_app_hci_event_handler, (void*)&hci_tl_config); | ||||
|  | ||||
|     // Configure NVM store for pairing data | ||||
|     SHCI_C2_CONFIG_Cmd_Param_t config_param = { | ||||
|         .PayloadCmdSize = SHCI_C2_CONFIG_PAYLOAD_CMD_SIZE, | ||||
|         .Config1 =SHCI_C2_CONFIG_CONFIG1_BIT0_BLE_NVM_DATA_TO_SRAM, | ||||
|         .BleNvmRamAddress = (uint32_t)ble_app_nvm, | ||||
|         .EvtMask1 = SHCI_C2_CONFIG_EVTMASK1_BIT1_BLE_NVM_RAM_UPDATE_ENABLE, | ||||
|     }; | ||||
|     status = SHCI_C2_Config(&config_param); | ||||
|     if(status) { | ||||
|         FURI_LOG_E(BLE_APP_TAG, "Failed to configure 2nd core: %d", status); | ||||
|     } | ||||
|  | ||||
|     // Start ble stack on 2nd core | ||||
|     SHCI_C2_Ble_Init_Cmd_Packet_t ble_init_cmd_packet = { | ||||
|         .Header = {{0,0,0}}, // Header unused | ||||
| @@ -67,13 +80,18 @@ bool ble_app_init() { | ||||
|             0, | ||||
|         } | ||||
|     }; | ||||
|     SHCI_CmdStatus_t status = SHCI_C2_BLE_Init(&ble_init_cmd_packet); | ||||
|     status = SHCI_C2_BLE_Init(&ble_init_cmd_packet); | ||||
|     if(status) { | ||||
|         FURI_LOG_E(BLE_APP_TAG, "Failed to start ble stack: %d", status); | ||||
|     } | ||||
|     return status == SHCI_Success; | ||||
| } | ||||
|  | ||||
| void ble_app_get_key_storage_buff(uint8_t** addr, uint16_t* size) { | ||||
|     *addr = (uint8_t*)ble_app_nvm; | ||||
|     *size = sizeof(ble_app_nvm); | ||||
| } | ||||
|  | ||||
| static void ble_app_hci_thread(void *arg) { | ||||
|     while(1) { | ||||
|         osThreadFlagsWait(1, osFlagsWaitAny, osWaitForever); | ||||
|   | ||||
| @@ -5,8 +5,10 @@ extern "C" { | ||||
| #endif | ||||
|  | ||||
| #include <stdbool.h> | ||||
| #include <stdint.h> | ||||
|  | ||||
| bool ble_app_init(); | ||||
| void ble_app_get_key_storage_buff(uint8_t** addr, uint16_t* size); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
|   | ||||
							
								
								
									
										173
									
								
								firmware/targets/f7/ble-glue/ble_glue.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								firmware/targets/f7/ble-glue/ble_glue.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,173 @@ | ||||
| #include "ble_glue.h" | ||||
| #include "app_common.h" | ||||
| #include "main.h" | ||||
| #include "ble_app.h" | ||||
| #include "ble.h" | ||||
| #include "tl.h" | ||||
| #include "shci.h" | ||||
| #include "cmsis_os.h" | ||||
| #include "shci_tl.h" | ||||
| #include "app_debug.h" | ||||
| #include <furi-hal.h> | ||||
|  | ||||
| #define POOL_SIZE (CFG_TLBLE_EVT_QUEUE_LENGTH*4U*DIVC(( sizeof(TL_PacketHeader_t) + TL_BLE_EVENT_FRAME_SIZE ), 4U)) | ||||
|  | ||||
| PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static uint8_t ble_glue_event_pool[POOL_SIZE]; | ||||
| PLACE_IN_SECTION("MB_MEM2") ALIGN(4) static TL_CmdPacket_t ble_glue_system_cmd_buff; | ||||
| 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 struct { | ||||
|     osMutexId_t shci_mtx; | ||||
|     osSemaphoreId_t shci_sem; | ||||
|     osThreadId_t shci_user_event_thread_id; | ||||
|     osThreadAttr_t shci_user_event_thread_attr; | ||||
|     BleGlueStatus status; | ||||
|     BleGlueKeyStorageChangedCallback callback; | ||||
|     void* context; | ||||
| } BleGlue; | ||||
|  | ||||
| static BleGlue* ble_glue = NULL; | ||||
|  | ||||
| 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); | ||||
|     ble_glue->callback = callback; | ||||
|     ble_glue->context = context; | ||||
| } | ||||
|  | ||||
| void ble_glue_init() { | ||||
|     ble_glue = furi_alloc(sizeof(BleGlue)); | ||||
|     ble_glue->status = BleGlueStatusStartup; | ||||
|     ble_glue->shci_user_event_thread_attr.name = "ble_shci_evt"; | ||||
|     ble_glue->shci_user_event_thread_attr.stack_size = 1024; | ||||
|  | ||||
|     // Configure the system Power Mode | ||||
|     // Select HSI as system clock source after Wake Up from Stop mode | ||||
|     LL_RCC_SetClkAfterWakeFromStop(LL_RCC_STOP_WAKEUPCLOCK_HSI); | ||||
|     /* Initialize the CPU2 reset value before starting CPU2 with C2BOOT */ | ||||
|     LL_C2_PWR_SetPowerMode(LL_PWR_MODE_SHUTDOWN); | ||||
|     furi_hal_power_insomnia_enter(); | ||||
|  | ||||
|     // APPD_Init(); | ||||
|  | ||||
|     // Initialize all transport layers | ||||
|     TL_MM_Config_t tl_mm_config; | ||||
|     SHCI_TL_HciInitConf_t SHci_Tl_Init_Conf; | ||||
|     // Reference table initialization | ||||
|     TL_Init(); | ||||
|  | ||||
|     ble_glue->shci_mtx = osMutexNew(NULL); | ||||
|     ble_glue->shci_sem = osSemaphoreNew(1, 0, NULL); | ||||
|  | ||||
|     // FreeRTOS system task creation | ||||
|     ble_glue->shci_user_event_thread_id = osThreadNew(ble_glue_user_event_thread, NULL, &ble_glue->shci_user_event_thread_attr); | ||||
|  | ||||
|     // System channel initialization | ||||
|     SHci_Tl_Init_Conf.p_cmdbuffer = (uint8_t*)&ble_glue_system_cmd_buff; | ||||
|     SHci_Tl_Init_Conf.StatusNotCallBack = ble_glue_sys_status_not_callback; | ||||
|     shci_init(ble_glue_sys_user_event_callback, (void*) &SHci_Tl_Init_Conf); | ||||
|  | ||||
|     /**< Memory Manager channel initialization */ | ||||
|     tl_mm_config.p_BleSpareEvtBuffer = ble_glue_ble_spare_event_buff; | ||||
|     tl_mm_config.p_SystemSpareEvtBuffer = ble_glue_system_spare_event_buff; | ||||
|     tl_mm_config.p_AsynchEvtPool = ble_glue_event_pool; | ||||
|     tl_mm_config.AsynchEvtPoolSize = POOL_SIZE; | ||||
|     TL_MM_Init( &tl_mm_config ); | ||||
|     TL_Enable(); | ||||
|  | ||||
|     /* | ||||
|      * From now, the application is waiting for the ready event ( VS_HCI_C2_Ready ) | ||||
|      * received on the system channel before starting the Stack | ||||
|      * This system event is received with ble_glue_sys_user_event_callback() | ||||
|      */ | ||||
| } | ||||
|  | ||||
| static void ble_glue_sys_status_not_callback(SHCI_TL_CmdStatus_t status) { | ||||
|     switch (status) { | ||||
|     case SHCI_TL_CmdBusy: | ||||
|         osMutexAcquire( ble_glue->shci_mtx, osWaitForever ); | ||||
|         break; | ||||
|     case SHCI_TL_CmdAvailable: | ||||
|         osMutexRelease( ble_glue->shci_mtx ); | ||||
|         break; | ||||
|     default: | ||||
|         break; | ||||
|   } | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * The type of the payload for a system user event is tSHCI_UserEvtRxParam | ||||
|  * When the system event is both : | ||||
|  *    - a ready event (subevtcode = SHCI_SUB_EVT_CODE_READY) | ||||
|  *    - reported by the FUS (sysevt_ready_rsp == FUS_FW_RUNNING) | ||||
|  * The buffer shall not be released | ||||
|  * ( eg ((tSHCI_UserEvtRxParam*)pPayload)->status shall be set to SHCI_TL_UserEventFlow_Disable ) | ||||
|  * When the status is not filled, the buffer is released by default | ||||
|  */ | ||||
| static void ble_glue_sys_user_event_callback( void * pPayload ) { | ||||
|     UNUSED(pPayload); | ||||
|     /* Traces channel initialization */ | ||||
|     // APPD_EnableCPU2( ); | ||||
|  | ||||
|     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("Core2", "BLE stack started"); | ||||
|             ble_glue->status = BleGlueStatusStarted; | ||||
|             if(SHCI_C2_SetFlashActivityControl(FLASH_ACTIVITY_CONTROL_SEM7) == SHCI_Success) { | ||||
|                 FURI_LOG_I("Core2", "Flash activity control switched to SEM7"); | ||||
|             } else { | ||||
|                 FURI_LOG_E("Core2", "Failed to switch flash activity control to SEM7"); | ||||
|             } | ||||
|         } else { | ||||
|             FURI_LOG_E("Core2", "BLE stack startup failed"); | ||||
|             ble_glue->status = BleGlueStatusBleStackMissing; | ||||
|         } | ||||
|         furi_hal_power_insomnia_exit(); | ||||
|     } else if(p_sys_event->subevtcode == SHCI_SUB_EVT_ERROR_NOTIF) { | ||||
|         FURI_LOG_E("Core2", "Error during initialization"); | ||||
|         furi_hal_power_insomnia_exit(); | ||||
|     } 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_event->payload; | ||||
|         if(ble_glue->callback) { | ||||
|             ble_glue->callback((uint8_t*)p_sys_ble_nvm_ram_update_event->StartAddress, p_sys_ble_nvm_ram_update_event->Size, ble_glue->context); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Wrap functions | ||||
| static void ble_glue_user_event_thread(void *argument) { | ||||
|     UNUSED(argument); | ||||
|     for(;;) { | ||||
|         osThreadFlagsWait(1, osFlagsWaitAny, osWaitForever); | ||||
|         shci_user_evt_proc(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void shci_notify_asynch_evt(void* pdata) { | ||||
|     UNUSED(pdata); | ||||
|     osThreadFlagsSet(ble_glue->shci_user_event_thread_id, 1); | ||||
| } | ||||
|  | ||||
| void shci_cmd_resp_release(uint32_t flag) { | ||||
|     UNUSED(flag); | ||||
|     osSemaphoreRelease(ble_glue->shci_sem); | ||||
| } | ||||
|  | ||||
| void shci_cmd_resp_wait(uint32_t timeout) { | ||||
|     UNUSED(timeout); | ||||
|     osSemaphoreAcquire(ble_glue->shci_sem, osWaitForever); | ||||
| } | ||||
							
								
								
									
										26
									
								
								firmware/targets/f7/ble-glue/ble_glue.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								firmware/targets/f7/ble-glue/ble_glue.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| #pragma once | ||||
|  | ||||
| #include <stdint.h> | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| typedef void(*BleGlueKeyStorageChangedCallback)(uint8_t* change_addr_start, uint16_t size, void* context); | ||||
|  | ||||
| typedef enum { | ||||
|     BleGlueStatusUninitialized, | ||||
|     BleGlueStatusStartup, | ||||
|     BleGlueStatusBleStackMissing, | ||||
|     BleGlueStatusStarted | ||||
| } BleGlueStatus; | ||||
|  | ||||
| void ble_glue_init(); | ||||
|  | ||||
| BleGlueStatus ble_glue_get_status(); | ||||
|  | ||||
| void ble_glue_set_key_storage_changed_callback(BleGlueKeyStorageChangedCallback callback, void* context); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
| @@ -1,6 +1,5 @@ | ||||
| #include "gap.h" | ||||
|  | ||||
| #include "app_entry.h" | ||||
| #include "ble.h" | ||||
|  | ||||
| #include "cmsis_os.h" | ||||
| @@ -375,7 +374,7 @@ static void gap_advetise_timer_callback(void* context) { | ||||
| } | ||||
|  | ||||
| bool gap_init(BleEventCallback on_event_cb, void* context) { | ||||
|     if (APPE_Status() != BleGlueStatusStarted) { | ||||
|     if (ble_glue_get_status() != BleGlueStatusStarted) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -29,6 +29,37 @@ | ||||
|  * Semaphores | ||||
|  * THIS SHALL NO BE CHANGED AS THESE SEMAPHORES ARE USED AS WELL ON THE CM0+ | ||||
|  *****************************************************************************/ | ||||
| /** | ||||
| * Index of the semaphore used the prevent conflicts after standby sleep. | ||||
| * Each CPUs takes this semaphore at standby wakeup until conclicting elements are restored. | ||||
| */ | ||||
| #define CFG_HW_PWR_STANDBY_SEMID                               10 | ||||
| /** | ||||
| *  The CPU2 may be configured to store the Thread persistent data either in internal NVM storage on CPU2 or in | ||||
| *  SRAM2 buffer provided by the user application. This can be configured with the system command SHCI_C2_Config() | ||||
| *  When the CPU2 is requested to store persistent data in SRAM2, it can write data in this buffer at any time when needed. | ||||
| *  In order to read consistent data with the CPU1 from the SRAM2 buffer, the flow should be: | ||||
| *  + CPU1 takes CFG_HW_THREAD_NVM_SRAM_SEMID semaphore | ||||
| *  + CPU1 reads all persistent data from SRAM2 (most of the time, the goal is to write these data into an NVM managed by CPU1) | ||||
| *  + CPU1 releases CFG_HW_THREAD_NVM_SRAM_SEMID semaphore | ||||
| *  CFG_HW_THREAD_NVM_SRAM_SEMID semaphore makes sure CPU2 does not update the persistent data in SRAM2 at the same time CPU1 is reading them. | ||||
| *  There is no timing constraint on how long this semaphore can be kept. | ||||
| */ | ||||
| #define CFG_HW_THREAD_NVM_SRAM_SEMID                           9 | ||||
|  | ||||
| /** | ||||
| *  The CPU2 may be configured to store the BLE persistent data either in internal NVM storage on CPU2 or in | ||||
| *  SRAM2 buffer provided by the user application. This can be configured with the system command SHCI_C2_Config() | ||||
| *  When the CPU2 is requested to store persistent data in SRAM2, it can write data in this buffer at any time when needed. | ||||
| *  In order to read consistent data with the CPU1 from the SRAM2 buffer, the flow should be: | ||||
| *  + CPU1 takes CFG_HW_BLE_NVM_SRAM_SEMID semaphore | ||||
| *  + CPU1 reads all persistent data from SRAM2 (most of the time, the goal is to write these data into an NVM managed by CPU1) | ||||
| *  + CPU1 releases CFG_HW_BLE_NVM_SRAM_SEMID semaphore | ||||
| *  CFG_HW_BLE_NVM_SRAM_SEMID semaphore makes sure CPU2 does not update the persistent data in SRAM2 at the same time CPU1 is reading them. | ||||
| *  There is no timing constraint on how long this semaphore can be kept. | ||||
| */ | ||||
| #define CFG_HW_BLE_NVM_SRAM_SEMID                              8 | ||||
|  | ||||
| /** | ||||
| *  Index of the semaphore used by CPU2 to prevent the CPU1 to either write or erase data in flash | ||||
| *  The CPU1 shall not either write or erase in flash when this semaphore is taken by the CPU2 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user