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…
Reference in New Issue
Block a user