Fix GUI freeze after NFC classic read (#1074)
* nfc worker: add delay for task switching * device info service: fix rpc version characteristic * firmware: move FreeRTOSConfig.h to target include * dev_info service: fix typo * ble glue: use osThreadFlags instead of osEventFlags * Infrared: fix issue with timer lockup * FuriHal: yeld in flash lock routine * ble: change connection parameters, display actual params * ble: verify connection parameters * ble: fix typo Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
		
							parent
							
								
									8b833cb7eb
								
							
						
					
					
						commit
						0bf2702210
					
				| @ -780,6 +780,7 @@ void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { | |||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                 if(nfc_worker->state != NfcWorkerStateReadMifareClassic) break; |                 if(nfc_worker->state != NfcWorkerStateReadMifareClassic) break; | ||||||
|  |                 osDelay(1); | ||||||
|             } |             } | ||||||
|             if(nfc_worker->state != NfcWorkerStateReadMifareClassic) break; |             if(nfc_worker->state != NfcWorkerStateReadMifareClassic) break; | ||||||
|             if(sector_key_found) { |             if(sector_key_found) { | ||||||
|  | |||||||
| @ -77,11 +77,13 @@ to exclude the API function. */ | |||||||
| /* CMSIS-RTOS V2 flags */ | /* CMSIS-RTOS V2 flags */ | ||||||
| #define configUSE_OS2_THREAD_SUSPEND_RESUME 1 | #define configUSE_OS2_THREAD_SUSPEND_RESUME 1 | ||||||
| #define configUSE_OS2_THREAD_ENUMERATE 1 | #define configUSE_OS2_THREAD_ENUMERATE 1 | ||||||
| #define configUSE_OS2_EVENTFLAGS_FROM_ISR 1 |  | ||||||
| #define configUSE_OS2_THREAD_FLAGS 1 | #define configUSE_OS2_THREAD_FLAGS 1 | ||||||
| #define configUSE_OS2_TIMER 1 | #define configUSE_OS2_TIMER 1 | ||||||
| #define configUSE_OS2_MUTEX 1 | #define configUSE_OS2_MUTEX 1 | ||||||
| 
 | 
 | ||||||
|  | // NEVER TO BE USED, because of their hard realtime nature
 | ||||||
|  | // #define configUSE_OS2_EVENTFLAGS_FROM_ISR 1
 | ||||||
|  | 
 | ||||||
| /* CMSIS-RTOS */ | /* CMSIS-RTOS */ | ||||||
| #define configTASK_NOTIFICATION_ARRAY_ENTRIES 2 | #define configTASK_NOTIFICATION_ARRAY_ENTRIES 2 | ||||||
| #define CMSIS_TASK_NOTIFY_INDEX 1 | #define CMSIS_TASK_NOTIFY_INDEX 1 | ||||||
| @ -24,7 +24,6 @@ typedef struct { | |||||||
|     osMutexId_t hci_mtx; |     osMutexId_t hci_mtx; | ||||||
|     osSemaphoreId_t hci_sem; |     osSemaphoreId_t hci_sem; | ||||||
|     FuriThread* thread; |     FuriThread* thread; | ||||||
|     osEventFlagsId_t event_flags; |  | ||||||
| } BleApp; | } BleApp; | ||||||
| 
 | 
 | ||||||
| static BleApp* ble_app = NULL; | static BleApp* ble_app = NULL; | ||||||
| @ -39,7 +38,6 @@ bool ble_app_init() { | |||||||
|     // Allocate semafore and mutex for ble command buffer access
 |     // Allocate semafore and mutex for ble command buffer access
 | ||||||
|     ble_app->hci_mtx = osMutexNew(NULL); |     ble_app->hci_mtx = osMutexNew(NULL); | ||||||
|     ble_app->hci_sem = osSemaphoreNew(1, 0, NULL); |     ble_app->hci_sem = osSemaphoreNew(1, 0, NULL); | ||||||
|     ble_app->event_flags = osEventFlagsNew(NULL); |  | ||||||
|     // HCI transport layer thread to handle user asynch events
 |     // HCI transport layer thread to handle user asynch events
 | ||||||
|     ble_app->thread = furi_thread_alloc(); |     ble_app->thread = furi_thread_alloc(); | ||||||
|     furi_thread_set_name(ble_app->thread, "BleHciDriver"); |     furi_thread_set_name(ble_app->thread, "BleHciDriver"); | ||||||
| @ -108,15 +106,14 @@ void ble_app_get_key_storage_buff(uint8_t** addr, uint16_t* size) { | |||||||
| 
 | 
 | ||||||
| void ble_app_thread_stop() { | void ble_app_thread_stop() { | ||||||
|     if(ble_app) { |     if(ble_app) { | ||||||
|         osEventFlagsSet(ble_app->event_flags, BLE_APP_FLAG_KILL_THREAD); |         osThreadId_t thread_id = furi_thread_get_thread_id(ble_app->thread); | ||||||
|  |         furi_assert(thread_id); | ||||||
|  |         osThreadFlagsSet(thread_id, BLE_APP_FLAG_KILL_THREAD); | ||||||
|         furi_thread_join(ble_app->thread); |         furi_thread_join(ble_app->thread); | ||||||
|         furi_thread_free(ble_app->thread); |         furi_thread_free(ble_app->thread); | ||||||
|         // Wait to make sure that EventFlags delivers pending events before memory free
 |  | ||||||
|         osDelay(50); |  | ||||||
|         // Free resources
 |         // Free resources
 | ||||||
|         osMutexDelete(ble_app->hci_mtx); |         osMutexDelete(ble_app->hci_mtx); | ||||||
|         osSemaphoreDelete(ble_app->hci_sem); |         osSemaphoreDelete(ble_app->hci_sem); | ||||||
|         osEventFlagsDelete(ble_app->event_flags); |  | ||||||
|         free(ble_app); |         free(ble_app); | ||||||
|         ble_app = NULL; |         ble_app = NULL; | ||||||
|         memset(&ble_app_cmd_buffer, 0, sizeof(ble_app_cmd_buffer)); |         memset(&ble_app_cmd_buffer, 0, sizeof(ble_app_cmd_buffer)); | ||||||
| @ -125,9 +122,9 @@ void ble_app_thread_stop() { | |||||||
| 
 | 
 | ||||||
| static int32_t ble_app_hci_thread(void* arg) { | static int32_t ble_app_hci_thread(void* arg) { | ||||||
|     uint32_t flags = 0; |     uint32_t flags = 0; | ||||||
|  | 
 | ||||||
|     while(1) { |     while(1) { | ||||||
|         flags = osEventFlagsWait( |         flags = osThreadFlagsWait(BLE_APP_FLAG_ALL, osFlagsWaitAny, osWaitForever); | ||||||
|             ble_app->event_flags, BLE_APP_FLAG_ALL, osFlagsWaitAny, osWaitForever); |  | ||||||
|         if(flags & BLE_APP_FLAG_KILL_THREAD) { |         if(flags & BLE_APP_FLAG_KILL_THREAD) { | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| @ -142,7 +139,9 @@ static int32_t ble_app_hci_thread(void* arg) { | |||||||
| // Called by WPAN lib
 | // Called by WPAN lib
 | ||||||
| void hci_notify_asynch_evt(void* pdata) { | void hci_notify_asynch_evt(void* pdata) { | ||||||
|     if(ble_app) { |     if(ble_app) { | ||||||
|         osEventFlagsSet(ble_app->event_flags, BLE_APP_FLAG_HCI_EVENT); |         osThreadId_t thread_id = furi_thread_get_thread_id(ble_app->thread); | ||||||
|  |         furi_assert(thread_id); | ||||||
|  |         osThreadFlagsSet(thread_id, BLE_APP_FLAG_HCI_EVENT); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -40,7 +40,6 @@ typedef enum { | |||||||
| typedef struct { | typedef struct { | ||||||
|     osMutexId_t shci_mtx; |     osMutexId_t shci_mtx; | ||||||
|     osSemaphoreId_t shci_sem; |     osSemaphoreId_t shci_sem; | ||||||
|     osEventFlagsId_t event_flags; |  | ||||||
|     FuriThread* thread; |     FuriThread* thread; | ||||||
|     BleGlueStatus status; |     BleGlueStatus status; | ||||||
|     BleGlueKeyStorageChangedCallback callback; |     BleGlueKeyStorageChangedCallback callback; | ||||||
| @ -83,7 +82,6 @@ void ble_glue_init() { | |||||||
| 
 | 
 | ||||||
|     ble_glue->shci_mtx = osMutexNew(NULL); |     ble_glue->shci_mtx = osMutexNew(NULL); | ||||||
|     ble_glue->shci_sem = osSemaphoreNew(1, 0, NULL); |     ble_glue->shci_sem = osSemaphoreNew(1, 0, NULL); | ||||||
|     ble_glue->event_flags = osEventFlagsNew(NULL); |  | ||||||
| 
 | 
 | ||||||
|     // FreeRTOS system task creation
 |     // FreeRTOS system task creation
 | ||||||
|     ble_glue->thread = furi_thread_alloc(); |     ble_glue->thread = furi_thread_alloc(); | ||||||
| @ -257,15 +255,14 @@ static void ble_glue_clear_shared_memory() { | |||||||
| 
 | 
 | ||||||
| void ble_glue_thread_stop() { | void ble_glue_thread_stop() { | ||||||
|     if(ble_glue) { |     if(ble_glue) { | ||||||
|         osEventFlagsSet(ble_glue->event_flags, BLE_GLUE_FLAG_KILL_THREAD); |         osThreadId_t thread_id = furi_thread_get_thread_id(ble_glue->thread); | ||||||
|  |         furi_assert(thread_id); | ||||||
|  |         osThreadFlagsSet(thread_id, BLE_GLUE_FLAG_KILL_THREAD); | ||||||
|         furi_thread_join(ble_glue->thread); |         furi_thread_join(ble_glue->thread); | ||||||
|         furi_thread_free(ble_glue->thread); |         furi_thread_free(ble_glue->thread); | ||||||
|         // Wait to make sure that EventFlags delivers pending events before memory free
 |  | ||||||
|         osDelay(50); |  | ||||||
|         // Free resources
 |         // Free resources
 | ||||||
|         osMutexDelete(ble_glue->shci_mtx); |         osMutexDelete(ble_glue->shci_mtx); | ||||||
|         osSemaphoreDelete(ble_glue->shci_sem); |         osSemaphoreDelete(ble_glue->shci_sem); | ||||||
|         osEventFlagsDelete(ble_glue->event_flags); |  | ||||||
|         ble_glue_clear_shared_memory(); |         ble_glue_clear_shared_memory(); | ||||||
|         free(ble_glue); |         free(ble_glue); | ||||||
|         ble_glue = NULL; |         ble_glue = NULL; | ||||||
| @ -275,9 +272,9 @@ void ble_glue_thread_stop() { | |||||||
| // Wrap functions
 | // Wrap functions
 | ||||||
| static int32_t ble_glue_shci_thread(void* context) { | static int32_t ble_glue_shci_thread(void* context) { | ||||||
|     uint32_t flags = 0; |     uint32_t flags = 0; | ||||||
|  | 
 | ||||||
|     while(true) { |     while(true) { | ||||||
|         flags = osEventFlagsWait( |         flags = osThreadFlagsWait(BLE_GLUE_FLAG_ALL, osFlagsWaitAny, osWaitForever); | ||||||
|             ble_glue->event_flags, BLE_GLUE_FLAG_ALL, osFlagsWaitAny, osWaitForever); |  | ||||||
|         if(flags & BLE_GLUE_FLAG_SHCI_EVENT) { |         if(flags & BLE_GLUE_FLAG_SHCI_EVENT) { | ||||||
|             shci_user_evt_proc(); |             shci_user_evt_proc(); | ||||||
|         } |         } | ||||||
| @ -292,7 +289,9 @@ static int32_t ble_glue_shci_thread(void* context) { | |||||||
| void shci_notify_asynch_evt(void* pdata) { | void shci_notify_asynch_evt(void* pdata) { | ||||||
|     UNUSED(pdata); |     UNUSED(pdata); | ||||||
|     if(ble_glue) { |     if(ble_glue) { | ||||||
|         osEventFlagsSet(ble_glue->event_flags, BLE_GLUE_FLAG_SHCI_EVENT); |         osThreadId_t thread_id = furi_thread_get_thread_id(ble_glue->thread); | ||||||
|  |         furi_assert(thread_id); | ||||||
|  |         osThreadFlagsSet(thread_id, BLE_GLUE_FLAG_SHCI_EVENT); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | |||||||
							
								
								
									
										12
									
								
								firmware/targets/f7/ble_glue/dev_info_service.c
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						
									
										12
									
								
								firmware/targets/f7/ble_glue/dev_info_service.c
									
									
									
									
									
										
										
										Normal file → Executable file
									
								
							| @ -8,8 +8,6 @@ | |||||||
| 
 | 
 | ||||||
| #define TAG "BtDevInfoSvc" | #define TAG "BtDevInfoSvc" | ||||||
| 
 | 
 | ||||||
| #define DEV_INFO_RPC_VERSION_CHAR_MAX_SIZE (10) |  | ||||||
| 
 |  | ||||||
| typedef struct { | typedef struct { | ||||||
|     uint16_t service_handle; |     uint16_t service_handle; | ||||||
|     uint16_t man_name_char_handle; |     uint16_t man_name_char_handle; | ||||||
| @ -26,6 +24,7 @@ static const char dev_info_serial_num[] = "1.0"; | |||||||
| static const char dev_info_firmware_rev_num[] = TOSTRING(TARGET); | static const char dev_info_firmware_rev_num[] = TOSTRING(TARGET); | ||||||
| static const char dev_info_software_rev_num[] = GIT_COMMIT " " GIT_BRANCH " " GIT_BRANCH_NUM | static const char dev_info_software_rev_num[] = GIT_COMMIT " " GIT_BRANCH " " GIT_BRANCH_NUM | ||||||
|                                                            " " BUILD_DATE; |                                                            " " BUILD_DATE; | ||||||
|  | static const char dev_info_rpc_version[] = TOSTRING(PROTOBUF_MAJOR_VERSION.PROTOBUF_MINOR_VERSION); | ||||||
| 
 | 
 | ||||||
| static const uint8_t dev_info_rpc_version_uuid[] = | static const uint8_t dev_info_rpc_version_uuid[] = | ||||||
|     {0x33, 0xa9, 0xb5, 0x3e, 0x87, 0x5d, 0x1a, 0x8e, 0xc8, 0x47, 0x5e, 0xae, 0x6d, 0x66, 0xf6, 0x03}; |     {0x33, 0xa9, 0xb5, 0x3e, 0x87, 0x5d, 0x1a, 0x8e, 0xc8, 0x47, 0x5e, 0xae, 0x6d, 0x66, 0xf6, 0x03}; | ||||||
| @ -107,7 +106,7 @@ void dev_info_svc_start() { | |||||||
|         dev_info_svc->service_handle, |         dev_info_svc->service_handle, | ||||||
|         UUID_TYPE_128, |         UUID_TYPE_128, | ||||||
|         (const Char_UUID_t*)dev_info_rpc_version_uuid, |         (const Char_UUID_t*)dev_info_rpc_version_uuid, | ||||||
|         DEV_INFO_RPC_VERSION_CHAR_MAX_SIZE, |         strlen(dev_info_rpc_version), | ||||||
|         CHAR_PROP_READ, |         CHAR_PROP_READ, | ||||||
|         ATTR_PERMISSION_AUTHEN_READ, |         ATTR_PERMISSION_AUTHEN_READ, | ||||||
|         GATT_DONT_NOTIFY_EVENTS, |         GATT_DONT_NOTIFY_EVENTS, | ||||||
| @ -155,18 +154,15 @@ void dev_info_svc_start() { | |||||||
|     if(status) { |     if(status) { | ||||||
|         FURI_LOG_E(TAG, "Failed to update software revision char: %d", status); |         FURI_LOG_E(TAG, "Failed to update software revision char: %d", status); | ||||||
|     } |     } | ||||||
|     string_t rpc_version; |  | ||||||
|     string_init_printf(rpc_version, "%d.%d", PROTOBUF_MAJOR_VERSION, PROTOBUF_MINOR_VERSION); |  | ||||||
|     status = aci_gatt_update_char_value( |     status = aci_gatt_update_char_value( | ||||||
|         dev_info_svc->service_handle, |         dev_info_svc->service_handle, | ||||||
|         dev_info_svc->rpc_version_char_handle, |         dev_info_svc->rpc_version_char_handle, | ||||||
|         0, |         0, | ||||||
|         strlen(string_get_cstr(rpc_version)), |         strlen(dev_info_rpc_version), | ||||||
|         (uint8_t*)string_get_cstr(rpc_version)); |         (uint8_t*)dev_info_rpc_version); | ||||||
|     if(status) { |     if(status) { | ||||||
|         FURI_LOG_E(TAG, "Failed to update rpc version char: %d", status); |         FURI_LOG_E(TAG, "Failed to update rpc version char: %d", status); | ||||||
|     } |     } | ||||||
|     string_clear(rpc_version); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void dev_info_svc_stop() { | void dev_info_svc_stop() { | ||||||
|  | |||||||
| @ -10,6 +10,8 @@ | |||||||
| #define FAST_ADV_TIMEOUT 30000 | #define FAST_ADV_TIMEOUT 30000 | ||||||
| #define INITIAL_ADV_TIMEOUT 60000 | #define INITIAL_ADV_TIMEOUT 60000 | ||||||
| 
 | 
 | ||||||
|  | #define GAP_INTERVAL_TO_MS(x) (uint16_t)((x)*1.25) | ||||||
|  | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     uint16_t gap_svc_handle; |     uint16_t gap_svc_handle; | ||||||
|     uint16_t dev_name_char_handle; |     uint16_t dev_name_char_handle; | ||||||
| @ -23,6 +25,7 @@ typedef struct { | |||||||
| typedef struct { | typedef struct { | ||||||
|     GapSvc service; |     GapSvc service; | ||||||
|     GapConfig* config; |     GapConfig* config; | ||||||
|  |     GapConnectionParams connection_params; | ||||||
|     GapState state; |     GapState state; | ||||||
|     osMutexId_t state_mutex; |     osMutexId_t state_mutex; | ||||||
|     GapEventCallback on_event_cb; |     GapEventCallback on_event_cb; | ||||||
| @ -58,6 +61,33 @@ static GapScan* gap_scan = NULL; | |||||||
| static void gap_advertise_start(GapState new_state); | static void gap_advertise_start(GapState new_state); | ||||||
| static int32_t gap_app(void* context); | static int32_t gap_app(void* context); | ||||||
| 
 | 
 | ||||||
|  | static void gap_verify_connection_parameters(Gap* gap) { | ||||||
|  |     furi_assert(gap); | ||||||
|  | 
 | ||||||
|  |     FURI_LOG_I( | ||||||
|  |         TAG, | ||||||
|  |         "Connection parameters: Connection Interval: %d (%d ms), Slave Latency: %d, Supervision Timeout: %d", | ||||||
|  |         gap->connection_params.conn_interval, | ||||||
|  |         GAP_INTERVAL_TO_MS(gap->connection_params.conn_interval), | ||||||
|  |         gap->connection_params.slave_latency, | ||||||
|  |         gap->connection_params.supervisor_timeout); | ||||||
|  | 
 | ||||||
|  |     // Send connection parameters request update if necessary
 | ||||||
|  |     GapConnectionParamsRequest* params = &gap->config->conn_param; | ||||||
|  |     if(params->conn_int_min > gap->connection_params.conn_interval || | ||||||
|  |        params->conn_int_max < gap->connection_params.conn_interval) { | ||||||
|  |         FURI_LOG_W(TAG, "Unsupported connection interval. Request connection parameters update"); | ||||||
|  |         if(aci_l2cap_connection_parameter_update_req( | ||||||
|  |                gap->service.connection_handle, | ||||||
|  |                params->conn_int_min, | ||||||
|  |                params->conn_int_max, | ||||||
|  |                gap->connection_params.slave_latency, | ||||||
|  |                gap->connection_params.supervisor_timeout)) { | ||||||
|  |             FURI_LOG_E(TAG, "Failed to request connection parameters update"); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { | SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { | ||||||
|     hci_event_pckt* event_pckt; |     hci_event_pckt* event_pckt; | ||||||
|     evt_le_meta_event* meta_evt; |     evt_le_meta_event* meta_evt; | ||||||
| @ -97,12 +127,11 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { | |||||||
|         case EVT_LE_CONN_UPDATE_COMPLETE: { |         case EVT_LE_CONN_UPDATE_COMPLETE: { | ||||||
|             hci_le_connection_update_complete_event_rp0* event = |             hci_le_connection_update_complete_event_rp0* event = | ||||||
|                 (hci_le_connection_update_complete_event_rp0*)meta_evt->data; |                 (hci_le_connection_update_complete_event_rp0*)meta_evt->data; | ||||||
|             FURI_LOG_I( |             gap->connection_params.conn_interval = event->Conn_Interval; | ||||||
|                 TAG, |             gap->connection_params.slave_latency = event->Conn_Latency; | ||||||
|                 "Connection interval: %d, latency: %d, supervision timeout: %d", |             gap->connection_params.supervisor_timeout = event->Supervision_Timeout; | ||||||
|                 event->Conn_Interval, |             FURI_LOG_I(TAG, "Connection parameters event complete"); | ||||||
|                 event->Conn_Latency, |             gap_verify_connection_parameters(gap); | ||||||
|                 event->Supervision_Timeout); |  | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
| @ -124,31 +153,22 @@ SVCCTL_UserEvtFlowStatus_t SVCCTL_App_Notification(void* pckt) { | |||||||
| 
 | 
 | ||||||
|         case EVT_LE_CONN_COMPLETE: |         case EVT_LE_CONN_COMPLETE: | ||||||
|             furi_hal_power_insomnia_enter(); |             furi_hal_power_insomnia_enter(); | ||||||
|             hci_le_connection_complete_event_rp0* connection_complete_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; | ||||||
|             FURI_LOG_I( |             gap->connection_params.conn_interval = event->Conn_Interval; | ||||||
|                 TAG, |             gap->connection_params.slave_latency = event->Conn_Latency; | ||||||
|                 "Connection complete for connection handle 0x%x", |             gap->connection_params.supervisor_timeout = event->Supervision_Timeout; | ||||||
|                 connection_complete_event->Connection_Handle); |  | ||||||
| 
 | 
 | ||||||
|             // Stop advertising as connection completed
 |             // Stop advertising as connection completed
 | ||||||
|             osTimerStop(gap->advertise_timer); |             osTimerStop(gap->advertise_timer); | ||||||
| 
 | 
 | ||||||
|             // Update connection status and handle
 |             // Update connection status and handle
 | ||||||
|             gap->state = GapStateConnected; |             gap->state = GapStateConnected; | ||||||
|             gap->service.connection_handle = connection_complete_event->Connection_Handle; |             gap->service.connection_handle = event->Connection_Handle; | ||||||
|             GapConnectionParams* params = &gap->config->conn_param; |  | ||||||
|             if(aci_l2cap_connection_parameter_update_req( |  | ||||||
|                    gap->service.connection_handle, |  | ||||||
|                    params->conn_int_min, |  | ||||||
|                    params->conn_int_max, |  | ||||||
|                    params->slave_latency, |  | ||||||
|                    params->supervisor_timeout)) { |  | ||||||
|                 FURI_LOG_W(TAG, "Failed to request connection parameters update"); |  | ||||||
|             } |  | ||||||
| 
 | 
 | ||||||
|  |             gap_verify_connection_parameters(gap); | ||||||
|             // Start pairing by sending security request
 |             // Start pairing by sending security request
 | ||||||
|             aci_gap_slave_security_req(connection_complete_event->Connection_Handle); |             aci_gap_slave_security_req(event->Connection_Handle); | ||||||
|             break; |             break; | ||||||
| 
 | 
 | ||||||
|         case EVT_LE_ADVERTISING_REPORT: { |         case EVT_LE_ADVERTISING_REPORT: { | ||||||
|  | |||||||
| @ -55,12 +55,18 @@ typedef enum { | |||||||
|     GapPairingPinCodeVerifyYesNo, |     GapPairingPinCodeVerifyYesNo, | ||||||
| } GapPairing; | } GapPairing; | ||||||
| 
 | 
 | ||||||
|  | typedef struct { | ||||||
|  |     uint16_t conn_interval; | ||||||
|  |     uint16_t slave_latency; | ||||||
|  |     uint16_t supervisor_timeout; | ||||||
|  | } GapConnectionParams; | ||||||
|  | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     uint16_t conn_int_min; |     uint16_t conn_int_min; | ||||||
|     uint16_t conn_int_max; |     uint16_t conn_int_max; | ||||||
|     uint16_t slave_latency; |     uint16_t slave_latency; | ||||||
|     uint16_t supervisor_timeout; |     uint16_t supervisor_timeout; | ||||||
| } GapConnectionParams; | } GapConnectionParamsRequest; | ||||||
| 
 | 
 | ||||||
| typedef struct { | typedef struct { | ||||||
|     uint16_t adv_service_uuid; |     uint16_t adv_service_uuid; | ||||||
| @ -69,7 +75,7 @@ typedef struct { | |||||||
|     GapPairing pairing_method; |     GapPairing pairing_method; | ||||||
|     uint8_t mac_address[GAP_MAC_ADDR_SIZE]; |     uint8_t mac_address[GAP_MAC_ADDR_SIZE]; | ||||||
|     char adv_name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH]; |     char adv_name[FURI_HAL_VERSION_DEVICE_NAME_LENGTH]; | ||||||
|     GapConnectionParams conn_param; |     GapConnectionParamsRequest conn_param; | ||||||
| } GapConfig; | } GapConfig; | ||||||
| 
 | 
 | ||||||
| bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context); | bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context); | ||||||
|  | |||||||
| @ -44,8 +44,8 @@ FuriHalBtProfileConfig profile_config[FuriHalBtProfileNumber] = { | |||||||
|                     .mac_address = FURI_HAL_BT_DEFAULT_MAC_ADDR, |                     .mac_address = FURI_HAL_BT_DEFAULT_MAC_ADDR, | ||||||
|                     .conn_param = |                     .conn_param = | ||||||
|                         { |                         { | ||||||
|                             .conn_int_min = 0x08, |                             .conn_int_min = 0x18, // 30 ms
 | ||||||
|                             .conn_int_max = 0x18, |                             .conn_int_max = 0x24, // 45 ms
 | ||||||
|                             .slave_latency = 0, |                             .slave_latency = 0, | ||||||
|                             .supervisor_timeout = 0, |                             .supervisor_timeout = 0, | ||||||
|                         }, |                         }, | ||||||
| @ -62,13 +62,12 @@ FuriHalBtProfileConfig profile_config[FuriHalBtProfileNumber] = { | |||||||
|                     .bonding_mode = true, |                     .bonding_mode = true, | ||||||
|                     .pairing_method = GapPairingPinCodeVerifyYesNo, |                     .pairing_method = GapPairingPinCodeVerifyYesNo, | ||||||
|                     .mac_address = FURI_HAL_BT_DEFAULT_MAC_ADDR, |                     .mac_address = FURI_HAL_BT_DEFAULT_MAC_ADDR, | ||||||
|                     // TODO optimize
 |  | ||||||
|                     .conn_param = |                     .conn_param = | ||||||
|                         { |                         { | ||||||
|                             .conn_int_min = 0x12, |                             .conn_int_min = 0x18, // 30 ms
 | ||||||
|                             .conn_int_max = 0x1e, |                             .conn_int_max = 0x24, // 45 ms
 | ||||||
|                             .slave_latency = 6, |                             .slave_latency = 0, | ||||||
|                             .supervisor_timeout = 700, |                             .supervisor_timeout = 0, | ||||||
|                         }, |                         }, | ||||||
|                 }, |                 }, | ||||||
|         }, |         }, | ||||||
|  | |||||||
| @ -124,18 +124,14 @@ static void furi_hal_flash_begin_with_core2(bool erase_flag) { | |||||||
|         // Actually we already have mutex for it, but specification is specification
 |         // Actually we already have mutex for it, but specification is specification
 | ||||||
|         if(LL_HSEM_IsSemaphoreLocked(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID)) { |         if(LL_HSEM_IsSemaphoreLocked(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU1_SEMID)) { | ||||||
|             taskEXIT_CRITICAL(); |             taskEXIT_CRITICAL(); | ||||||
|             continue; |             osThreadYield(); | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         //
 |  | ||||||
|         if(LL_HSEM_IsSemaphoreLocked(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID)) { |  | ||||||
|             taskEXIT_CRITICAL(); |  | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Take sempahopre and prevent core2 from anything funky
 |         // Take sempahopre and prevent core2 from anything funky
 | ||||||
|         if(LL_HSEM_1StepLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID) != 0) { |         if(LL_HSEM_1StepLock(HSEM, CFG_HW_BLOCK_FLASH_REQ_BY_CPU2_SEMID) != 0) { | ||||||
|             taskEXIT_CRITICAL(); |             taskEXIT_CRITICAL(); | ||||||
|  |             osThreadYield(); | ||||||
|             continue; |             continue; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -51,7 +51,6 @@ struct InfraredWorkerSignal { | |||||||
| struct InfraredWorker { | struct InfraredWorker { | ||||||
|     FuriThread* thread; |     FuriThread* thread; | ||||||
|     StreamBufferHandle_t stream; |     StreamBufferHandle_t stream; | ||||||
|     osEventFlagsId_t events; |  | ||||||
| 
 | 
 | ||||||
|     InfraredWorkerSignal signal; |     InfraredWorkerSignal signal; | ||||||
|     InfraredWorkerState state; |     InfraredWorkerState state; | ||||||
| @ -93,7 +92,8 @@ static void infrared_worker_furi_hal_message_sent_isr_callback(void* context); | |||||||
| 
 | 
 | ||||||
| static void infrared_worker_rx_timeout_callback(void* context) { | static void infrared_worker_rx_timeout_callback(void* context) { | ||||||
|     InfraredWorker* instance = context; |     InfraredWorker* instance = context; | ||||||
|     uint32_t flags_set = osEventFlagsSet(instance->events, INFRARED_WORKER_RX_TIMEOUT_RECEIVED); |     uint32_t flags_set = osThreadFlagsSet( | ||||||
|  |         furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_RX_TIMEOUT_RECEIVED); | ||||||
|     furi_check(flags_set & INFRARED_WORKER_RX_TIMEOUT_RECEIVED); |     furi_check(flags_set & INFRARED_WORKER_RX_TIMEOUT_RECEIVED); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -110,7 +110,7 @@ static void infrared_worker_rx_callback(void* context, bool level, uint32_t dura | |||||||
|                                                        INFRARED_WORKER_OVERRUN; |                                                        INFRARED_WORKER_OVERRUN; | ||||||
|     portYIELD_FROM_ISR(xHigherPriorityTaskWoken); |     portYIELD_FROM_ISR(xHigherPriorityTaskWoken); | ||||||
| 
 | 
 | ||||||
|     uint32_t flags_set = osEventFlagsSet(instance->events, events); |     uint32_t flags_set = osThreadFlagsSet(furi_thread_get_thread_id(instance->thread), events); | ||||||
|     furi_check(flags_set & events); |     furi_check(flags_set & events); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -152,7 +152,8 @@ static void | |||||||
|             instance->signal.timings[instance->signal.timings_cnt] = duration; |             instance->signal.timings[instance->signal.timings_cnt] = duration; | ||||||
|             ++instance->signal.timings_cnt; |             ++instance->signal.timings_cnt; | ||||||
|         } else { |         } else { | ||||||
|             uint32_t flags_set = osEventFlagsSet(instance->events, INFRARED_WORKER_OVERRUN); |             uint32_t flags_set = osThreadFlagsSet( | ||||||
|  |                 furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_OVERRUN); | ||||||
|             furi_check(flags_set & INFRARED_WORKER_OVERRUN); |             furi_check(flags_set & INFRARED_WORKER_OVERRUN); | ||||||
|             instance->rx.overrun = true; |             instance->rx.overrun = true; | ||||||
|         } |         } | ||||||
| @ -166,8 +167,7 @@ static int32_t infrared_worker_rx_thread(void* thread_context) { | |||||||
|     TickType_t last_blink_time = 0; |     TickType_t last_blink_time = 0; | ||||||
| 
 | 
 | ||||||
|     while(1) { |     while(1) { | ||||||
|         events = |         events = osThreadFlagsWait(INFRARED_WORKER_ALL_RX_EVENTS, 0, osWaitForever); | ||||||
|             osEventFlagsWait(instance->events, INFRARED_WORKER_ALL_RX_EVENTS, 0, osWaitForever); |  | ||||||
|         furi_check(events & INFRARED_WORKER_ALL_RX_EVENTS); /* at least one caught */ |         furi_check(events & INFRARED_WORKER_ALL_RX_EVENTS); /* at least one caught */ | ||||||
| 
 | 
 | ||||||
|         if(events & INFRARED_WORKER_RX_RECEIVED) { |         if(events & INFRARED_WORKER_RX_RECEIVED) { | ||||||
| @ -238,7 +238,6 @@ InfraredWorker* infrared_worker_alloc() { | |||||||
|     instance->blink_enable = false; |     instance->blink_enable = false; | ||||||
|     instance->notification = furi_record_open("notification"); |     instance->notification = furi_record_open("notification"); | ||||||
|     instance->state = InfraredWorkerStateIdle; |     instance->state = InfraredWorkerStateIdle; | ||||||
|     instance->events = osEventFlagsNew(NULL); |  | ||||||
| 
 | 
 | ||||||
|     return instance; |     return instance; | ||||||
| } | } | ||||||
| @ -252,7 +251,6 @@ void infrared_worker_free(InfraredWorker* instance) { | |||||||
|     infrared_free_encoder(instance->infrared_encoder); |     infrared_free_encoder(instance->infrared_encoder); | ||||||
|     vStreamBufferDelete(instance->stream); |     vStreamBufferDelete(instance->stream); | ||||||
|     furi_thread_free(instance->thread); |     furi_thread_free(instance->thread); | ||||||
|     osEventFlagsDelete(instance->events); |  | ||||||
| 
 | 
 | ||||||
|     free(instance); |     free(instance); | ||||||
| } | } | ||||||
| @ -263,7 +261,6 @@ void infrared_worker_rx_start(InfraredWorker* instance) { | |||||||
| 
 | 
 | ||||||
|     xStreamBufferSetTriggerLevel(instance->stream, sizeof(LevelDuration)); |     xStreamBufferSetTriggerLevel(instance->stream, sizeof(LevelDuration)); | ||||||
| 
 | 
 | ||||||
|     osEventFlagsClear(instance->events, INFRARED_WORKER_ALL_EVENTS); |  | ||||||
|     furi_thread_set_callback(instance->thread, infrared_worker_rx_thread); |     furi_thread_set_callback(instance->thread, infrared_worker_rx_thread); | ||||||
|     furi_thread_start(instance->thread); |     furi_thread_start(instance->thread); | ||||||
| 
 | 
 | ||||||
| @ -285,7 +282,7 @@ void infrared_worker_rx_stop(InfraredWorker* instance) { | |||||||
|     furi_hal_infrared_async_rx_set_capture_isr_callback(NULL, NULL); |     furi_hal_infrared_async_rx_set_capture_isr_callback(NULL, NULL); | ||||||
|     furi_hal_infrared_async_rx_stop(); |     furi_hal_infrared_async_rx_stop(); | ||||||
| 
 | 
 | ||||||
|     osEventFlagsSet(instance->events, INFRARED_WORKER_EXIT); |     osThreadFlagsSet(furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_EXIT); | ||||||
|     furi_thread_join(instance->thread); |     furi_thread_join(instance->thread); | ||||||
| 
 | 
 | ||||||
|     BaseType_t xReturn = xStreamBufferReset(instance->stream); |     BaseType_t xReturn = xStreamBufferReset(instance->stream); | ||||||
| @ -330,7 +327,6 @@ void infrared_worker_tx_start(InfraredWorker* instance) { | |||||||
|     // size have to be greater than api hal infrared async tx buffer size
 |     // size have to be greater than api hal infrared async tx buffer size
 | ||||||
|     xStreamBufferSetTriggerLevel(instance->stream, sizeof(InfraredWorkerTiming)); |     xStreamBufferSetTriggerLevel(instance->stream, sizeof(InfraredWorkerTiming)); | ||||||
| 
 | 
 | ||||||
|     osEventFlagsClear(instance->events, INFRARED_WORKER_ALL_EVENTS); |  | ||||||
|     furi_thread_set_callback(instance->thread, infrared_worker_tx_thread); |     furi_thread_set_callback(instance->thread, infrared_worker_tx_thread); | ||||||
| 
 | 
 | ||||||
|     instance->tx.steady_signal_sent = false; |     instance->tx.steady_signal_sent = false; | ||||||
| @ -346,7 +342,8 @@ void infrared_worker_tx_start(InfraredWorker* instance) { | |||||||
| 
 | 
 | ||||||
| static void infrared_worker_furi_hal_message_sent_isr_callback(void* context) { | static void infrared_worker_furi_hal_message_sent_isr_callback(void* context) { | ||||||
|     InfraredWorker* instance = context; |     InfraredWorker* instance = context; | ||||||
|     uint32_t flags_set = osEventFlagsSet(instance->events, INFRARED_WORKER_TX_MESSAGE_SENT); |     uint32_t flags_set = osThreadFlagsSet( | ||||||
|  |         furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_TX_MESSAGE_SENT); | ||||||
|     furi_check(flags_set & INFRARED_WORKER_TX_MESSAGE_SENT); |     furi_check(flags_set & INFRARED_WORKER_TX_MESSAGE_SENT); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| @ -372,7 +369,8 @@ static FuriHalInfraredTxGetDataState | |||||||
|         state = FuriHalInfraredTxGetDataStateDone; |         state = FuriHalInfraredTxGetDataStateDone; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     uint32_t flags_set = osEventFlagsSet(instance->events, INFRARED_WORKER_TX_FILL_BUFFER); |     uint32_t flags_set = osThreadFlagsSet( | ||||||
|  |         furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_TX_FILL_BUFFER); | ||||||
|     furi_check(flags_set & INFRARED_WORKER_TX_FILL_BUFFER); |     furi_check(flags_set & INFRARED_WORKER_TX_FILL_BUFFER); | ||||||
| 
 | 
 | ||||||
|     return state; |     return state; | ||||||
| @ -500,7 +498,7 @@ static int32_t infrared_worker_tx_thread(void* thread_context) { | |||||||
|             furi_hal_infrared_async_tx_wait_termination(); |             furi_hal_infrared_async_tx_wait_termination(); | ||||||
|             instance->state = InfraredWorkerStateStartTx; |             instance->state = InfraredWorkerStateStartTx; | ||||||
| 
 | 
 | ||||||
|             events = osEventFlagsGet(instance->events); |             events = osThreadFlagsGet(); | ||||||
|             if(events & INFRARED_WORKER_EXIT) { |             if(events & INFRARED_WORKER_EXIT) { | ||||||
|                 exit = true; |                 exit = true; | ||||||
|                 break; |                 break; | ||||||
| @ -508,8 +506,7 @@ static int32_t infrared_worker_tx_thread(void* thread_context) { | |||||||
| 
 | 
 | ||||||
|             break; |             break; | ||||||
|         case InfraredWorkerStateRunTx: |         case InfraredWorkerStateRunTx: | ||||||
|             events = osEventFlagsWait( |             events = osThreadFlagsWait(INFRARED_WORKER_ALL_TX_EVENTS, 0, osWaitForever); | ||||||
|                 instance->events, INFRARED_WORKER_ALL_TX_EVENTS, 0, osWaitForever); |  | ||||||
|             furi_check(events & INFRARED_WORKER_ALL_TX_EVENTS); /* at least one caught */ |             furi_check(events & INFRARED_WORKER_ALL_TX_EVENTS); /* at least one caught */ | ||||||
| 
 | 
 | ||||||
|             if(events & INFRARED_WORKER_EXIT) { |             if(events & INFRARED_WORKER_EXIT) { | ||||||
| @ -561,7 +558,7 @@ void infrared_worker_tx_stop(InfraredWorker* instance) { | |||||||
|     furi_assert(instance); |     furi_assert(instance); | ||||||
|     furi_assert(instance->state != InfraredWorkerStateRunRx); |     furi_assert(instance->state != InfraredWorkerStateRunRx); | ||||||
| 
 | 
 | ||||||
|     osEventFlagsSet(instance->events, INFRARED_WORKER_EXIT); |     osThreadFlagsSet(furi_thread_get_thread_id(instance->thread), INFRARED_WORKER_EXIT); | ||||||
|     furi_thread_join(instance->thread); |     furi_thread_join(instance->thread); | ||||||
|     furi_hal_infrared_async_tx_set_data_isr_callback(NULL, NULL); |     furi_hal_infrared_async_tx_set_data_isr_callback(NULL, NULL); | ||||||
|     furi_hal_infrared_async_tx_set_signal_sent_isr_callback(NULL, NULL); |     furi_hal_infrared_async_tx_set_signal_sent_isr_callback(NULL, NULL); | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 gornekich
						gornekich