1
mirror of https://github.com/flipperdevices/flipperzero-firmware.git synced 2025-12-12 04:41:26 +04:00

Furi: A Lot of Fixes (#3942)

- BT Service: cleanup code
- Dialog: correct release order in file browser
- Rpc: rollback to pre #3881 state
- Kernel: fix inverted behavior in furi_kernel_is_running
- Log: properly take mutex when kernel is not running
- Thread: rework tread control block scrubbing procedure, ensure that we don't do stupid things in idle task, add new priority for init task
- Timer: add control queue flush method, force flush on stop
- Furi: system init task now performs thread scrubbing
- BleGlue: add some extra checks
- FreeRTOSConfig: fix bunch of issues that were preventing configuration from being properly applied and cleanup
This commit is contained in:
あく
2024-10-14 14:39:09 +01:00
committed by GitHub
parent 344118c346
commit 5190aace88
19 changed files with 204 additions and 122 deletions

View File

@@ -430,13 +430,11 @@ static void bt_change_profile(Bt* bt, BtMessage* message) {
*message->profile_instance = NULL;
}
}
if(message->lock) api_lock_unlock(message->lock);
}
static void bt_close_connection(Bt* bt, BtMessage* message) {
static void bt_close_connection(Bt* bt) {
bt_close_rpc_connection(bt);
furi_hal_bt_stop_advertising();
if(message->lock) api_lock_unlock(message->lock);
}
static void bt_apply_settings(Bt* bt) {
@@ -484,19 +482,13 @@ static void bt_load_settings(Bt* bt) {
}
static void bt_handle_get_settings(Bt* bt, BtMessage* message) {
furi_assert(message->lock);
*message->data.settings = bt->bt_settings;
api_lock_unlock(message->lock);
}
static void bt_handle_set_settings(Bt* bt, BtMessage* message) {
furi_assert(message->lock);
bt->bt_settings = *message->data.csettings;
bt_apply_settings(bt);
bt_settings_save(&bt->bt_settings);
api_lock_unlock(message->lock);
}
static void bt_handle_reload_keys_settings(Bt* bt) {
@@ -548,6 +540,12 @@ int32_t bt_srv(void* p) {
while(1) {
furi_check(
furi_message_queue_get(bt->message_queue, &message, FuriWaitForever) == FuriStatusOk);
FURI_LOG_D(
TAG,
"call %d, lock 0x%p, result 0x%p",
message.type,
(void*)message.lock,
(void*)message.result);
if(message.type == BtMessageTypeUpdateStatus) {
// Update view ports
bt_statusbar_update(bt);
@@ -571,7 +569,7 @@ int32_t bt_srv(void* p) {
} else if(message.type == BtMessageTypeSetProfile) {
bt_change_profile(bt, &message);
} else if(message.type == BtMessageTypeDisconnect) {
bt_close_connection(bt, &message);
bt_close_connection(bt);
} else if(message.type == BtMessageTypeForgetBondedDevices) {
bt_keys_storage_delete(bt->keys_storage);
} else if(message.type == BtMessageTypeGetSettings) {
@@ -581,6 +579,8 @@ int32_t bt_srv(void* p) {
} else if(message.type == BtMessageTypeReloadKeysSettings) {
bt_handle_reload_keys_settings(bt);
}
if(message.lock) api_lock_unlock(message.lock);
}
return 0;

View File

@@ -54,11 +54,14 @@ bool dialogs_app_process_module_file_browser(const DialogsAppMessageDataFileBrow
ret = file_browser_context->result;
view_holder_set_view(view_holder, NULL);
view_holder_free(view_holder);
file_browser_stop(file_browser);
file_browser_free(file_browser);
view_holder_free(view_holder);
api_lock_free(file_browser_context->lock);
free(file_browser_context);
furi_record_close(RECORD_GUI);
return ret;

View File

@@ -67,7 +67,7 @@ static RpcSystemCallbacks rpc_systems[] = {
struct RpcSession {
Rpc* rpc;
FuriThreadId thread_id;
FuriThread* thread;
RpcHandlerDict_t handlers;
FuriStreamBuffer* stream;
@@ -172,7 +172,7 @@ size_t rpc_session_feed(
size_t bytes_sent = furi_stream_buffer_send(session->stream, encoded_bytes, size, timeout);
furi_thread_flags_set(session->thread_id, RpcEvtNewData);
furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtNewData);
return bytes_sent;
}
@@ -220,7 +220,7 @@ bool rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_t count) {
break;
} else {
/* Save disconnect flag and continue reading buffer */
furi_thread_flags_set(session->thread_id, RpcEvtDisconnect);
furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtDisconnect);
}
} else if(flags & RpcEvtNewData) {
// Just wake thread up
@@ -347,11 +347,8 @@ static int32_t rpc_session_worker(void* context) {
return 0;
}
static void rpc_session_thread_release_callback(
FuriThread* thread,
FuriThreadState thread_state,
void* context) {
if(thread_state == FuriThreadStateStopped) {
static void rpc_session_thread_pending_callback(void* context, uint32_t arg) {
UNUSED(arg);
RpcSession* session = (RpcSession*)context;
for(size_t i = 0; i < COUNT_OF(rpc_systems); ++i) {
@@ -371,9 +368,17 @@ static void rpc_session_thread_release_callback(
furi_mutex_release(session->callbacks_mutex);
furi_mutex_free(session->callbacks_mutex);
furi_thread_free(thread);
furi_thread_join(session->thread);
furi_thread_free(session->thread);
free(session);
}
static void
rpc_session_thread_state_callback(FuriThread* thread, FuriThreadState state, void* context) {
UNUSED(thread);
if(state == FuriThreadStateStopped) {
furi_timer_pending_callback(rpc_session_thread_pending_callback, context, 0);
}
}
RpcSession* rpc_session_open(Rpc* rpc, RpcOwner owner) {
@@ -404,14 +409,12 @@ RpcSession* rpc_session_open(Rpc* rpc, RpcOwner owner) {
};
rpc_add_handler(session, PB_Main_stop_session_tag, &rpc_handler);
FuriThread* thread =
furi_thread_alloc_ex("RpcSessionWorker", 3072, rpc_session_worker, session);
session->thread_id = furi_thread_get_id(thread);
session->thread = furi_thread_alloc_ex("RpcSessionWorker", 3072, rpc_session_worker, session);
furi_thread_set_state_context(thread, session);
furi_thread_set_state_callback(thread, rpc_session_thread_release_callback);
furi_thread_set_state_context(session->thread, session);
furi_thread_set_state_callback(session->thread, rpc_session_thread_state_callback);
furi_thread_start(thread);
furi_thread_start(session->thread);
return session;
}
@@ -423,7 +426,7 @@ void rpc_session_close(RpcSession* session) {
rpc_session_set_send_bytes_callback(session, NULL);
rpc_session_set_close_callback(session, NULL);
rpc_session_set_buffer_is_empty_callback(session, NULL);
furi_thread_flags_set(session->thread_id, RpcEvtDisconnect);
furi_thread_flags_set(furi_thread_get_id(session->thread), RpcEvtDisconnect);
}
void rpc_on_system_start(void* p) {

View File

@@ -33,7 +33,7 @@ bool furi_kernel_is_irq_or_masked(void) {
}
bool furi_kernel_is_running(void) {
return xTaskGetSchedulerState() != taskSCHEDULER_RUNNING;
return xTaskGetSchedulerState() == taskSCHEDULER_RUNNING;
}
int32_t furi_kernel_lock(void) {
@@ -129,6 +129,8 @@ uint32_t furi_kernel_get_tick_frequency(void) {
void furi_delay_tick(uint32_t ticks) {
furi_check(!furi_kernel_is_irq_or_masked());
furi_check(furi_thread_get_current_id() != xTaskGetIdleTaskHandle());
if(ticks == 0U) {
taskYIELD();
} else {
@@ -138,6 +140,7 @@ void furi_delay_tick(uint32_t ticks) {
FuriStatus furi_delay_until_tick(uint32_t tick) {
furi_check(!furi_kernel_is_irq_or_masked());
furi_check(furi_thread_get_current_id() != xTaskGetIdleTaskHandle());
TickType_t tcnt, delay;
FuriStatus stat;

View File

@@ -108,10 +108,17 @@ void furi_log_puts(const char* data) {
}
void furi_log_print_format(FuriLogLevel level, const char* tag, const char* format, ...) {
if(level <= furi_log.log_level &&
furi_mutex_acquire(furi_log.mutex, FuriWaitForever) == FuriStatusOk) {
FuriString* string;
string = furi_string_alloc();
do {
if(level > furi_log.log_level) {
break;
}
if(furi_mutex_acquire(furi_log.mutex, furi_kernel_is_running() ? FuriWaitForever : 0) !=
FuriStatusOk) {
break;
}
FuriString* string = furi_string_alloc();
const char* color = _FURI_LOG_CLR_RESET;
const char* log_letter = " ";
@@ -157,7 +164,7 @@ void furi_log_print_format(FuriLogLevel level, const char* tag, const char* form
furi_log_puts("\r\n");
furi_mutex_release(furi_log.mutex);
}
} while(0);
}
void furi_log_print_raw_format(FuriLogLevel level, const char* format, ...) {

View File

@@ -1,6 +1,7 @@
#include "thread.h"
#include "thread_i.h"
#include "thread_list_i.h"
#include "kernel.h"
#include "message_queue.h"
#include "memmgr.h"
#include "memmgr_heap.h"
#include "check.h"
@@ -67,6 +68,8 @@ static_assert(offsetof(FuriThread, container) == 0);
// Our idle priority should be equal to the one from FreeRTOS
static_assert(FuriThreadPriorityIdle == tskIDLE_PRIORITY);
static FuriMessageQueue* furi_thread_scrub_message_queue = NULL;
static size_t __furi_thread_stdout_write(FuriThread* thread, const char* data, size_t size);
static int32_t __furi_thread_stdout_flush(FuriThread* thread);
@@ -125,7 +128,9 @@ static void furi_thread_body(void* context) {
furi_thread_set_state(thread, FuriThreadStateStopping);
vTaskDelete(NULL);
furi_message_queue_put(furi_thread_scrub_message_queue, &thread, FuriWaitForever);
vTaskSuspend(NULL);
furi_thread_catch();
}
@@ -159,6 +164,31 @@ static void furi_thread_init_common(FuriThread* thread) {
}
}
void furi_thread_init(void) {
furi_thread_scrub_message_queue = furi_message_queue_alloc(8, sizeof(FuriThread*));
}
void furi_thread_scrub(void) {
FuriThread* thread_to_scrub = NULL;
while(true) {
furi_check(
furi_message_queue_get(
furi_thread_scrub_message_queue, &thread_to_scrub, FuriWaitForever) ==
FuriStatusOk);
TaskHandle_t task = (TaskHandle_t)thread_to_scrub;
// Delete task: FreeRTOS will remove task from all lists where it may be
vTaskDelete(task);
// Sanity check: ensure that local storage is ours and clear it
furi_check(pvTaskGetThreadLocalStoragePointer(task, 0) == thread_to_scrub);
vTaskSetThreadLocalStoragePointer(task, 0, NULL);
// Deliver thread stopped callback
furi_thread_set_state(thread_to_scrub, FuriThreadStateStopped);
}
}
FuriThread* furi_thread_alloc(void) {
FuriThread* thread = malloc(sizeof(FuriThread));
@@ -358,16 +388,6 @@ void furi_thread_start(FuriThread* thread) {
&thread->container) == (TaskHandle_t)thread);
}
void furi_thread_cleanup_tcb_event(TaskHandle_t task) {
FuriThread* thread = pvTaskGetThreadLocalStoragePointer(task, 0);
if(thread) {
// clear thread local storage
vTaskSetThreadLocalStoragePointer(task, 0, NULL);
furi_check(thread == (FuriThread*)task);
furi_thread_set_state(thread, FuriThreadStateStopped);
}
}
bool furi_thread_join(FuriThread* thread) {
furi_check(thread);
// Cannot join a service thread

View File

@@ -21,10 +21,10 @@ extern "C" {
* Many of the FuriThread functions MUST ONLY be called when the thread is STOPPED.
*/
typedef enum {
FuriThreadStateStopped, /**< Thread is stopped and is safe to release */
FuriThreadStateStopping, /**< Thread is stopping */
FuriThreadStateStarting, /**< Thread is starting */
FuriThreadStateRunning, /**< Thread is running */
FuriThreadStateStopped, /**< Thread is stopped and is safe to release. Event delivered from system init thread(TCB cleanup routine). It is safe to release thread instance. */
FuriThreadStateStopping, /**< Thread is stopping. Event delivered from child thread. */
FuriThreadStateStarting, /**< Thread is starting. Event delivered from parent(self) thread. */
FuriThreadStateRunning, /**< Thread is running. Event delivered from child thread. */
} FuriThreadState;
/**
@@ -32,6 +32,7 @@ typedef enum {
*/
typedef enum {
FuriThreadPriorityIdle = 0, /**< Idle priority */
FuriThreadPriorityInit = 4, /**< Init System Thread Priority */
FuriThreadPriorityLowest = 14, /**< Lowest */
FuriThreadPriorityLow = 15, /**< Low */
FuriThreadPriorityNormal = 16, /**< Normal, system default */
@@ -79,10 +80,12 @@ typedef void (*FuriThreadStdoutWriteCallback)(const char* data, size_t size);
/**
* @brief State change callback function pointer type.
*
* The function to be used as a state callback MUST follow this signature.
* The function to be used as a state callback MUST follow this
* signature.
*
* @param[in] pointer to the FuriThread instance that changed the state
* @param[in] state identifier of the state the thread has transitioned to
* @param[in] thread to the FuriThread instance that changed the state
* @param[in] state identifier of the state the thread has transitioned
* to
* @param[in,out] context pointer to a user-specified object
*/
typedef void (*FuriThreadStateCallback)(FuriThread* thread, FuriThreadState state, void* context);

7
furi/core/thread_i.h Normal file
View File

@@ -0,0 +1,7 @@
#pragma once
#include "thread.h"
void furi_thread_init(void);
void furi_thread_scrub(void);

View File

@@ -17,12 +17,24 @@ static_assert(offsetof(FuriTimer, container) == 0);
#define TIMER_DELETED_EVENT (1U << 0)
static void TimerCallback(TimerHandle_t hTimer) {
static void furi_timer_callback(TimerHandle_t hTimer) {
FuriTimer* instance = pvTimerGetTimerID(hTimer);
furi_check(instance);
instance->cb_func(instance->cb_context);
}
static void furi_timer_flush_epilogue(void* context, uint32_t arg) {
furi_assert(context);
UNUSED(arg);
EventGroupHandle_t hEvent = context;
// See https://github.com/FreeRTOS/FreeRTOS-Kernel/issues/1142
vTaskSuspendAll();
xEventGroupSetBits(hEvent, TIMER_DELETED_EVENT);
(void)xTaskResumeAll();
}
FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* context) {
furi_check((furi_kernel_is_irq_or_masked() == 0U) && (func != NULL));
@@ -33,23 +45,13 @@ FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* co
const UBaseType_t reload = (type == FuriTimerTypeOnce ? pdFALSE : pdTRUE);
const TimerHandle_t hTimer = xTimerCreateStatic(
NULL, portMAX_DELAY, reload, instance, TimerCallback, &instance->container);
NULL, portMAX_DELAY, reload, instance, furi_timer_callback, &instance->container);
furi_check(hTimer == (TimerHandle_t)instance);
return instance;
}
static void furi_timer_epilogue(void* context, uint32_t arg) {
furi_assert(context);
UNUSED(arg);
EventGroupHandle_t hEvent = context;
vTaskSuspendAll();
xEventGroupSetBits(hEvent, TIMER_DELETED_EVENT);
(void)xTaskResumeAll();
}
void furi_timer_free(FuriTimer* instance) {
furi_check(!furi_kernel_is_irq_or_masked());
furi_check(instance);
@@ -57,16 +59,21 @@ void furi_timer_free(FuriTimer* instance) {
TimerHandle_t hTimer = (TimerHandle_t)instance;
furi_check(xTimerDelete(hTimer, portMAX_DELAY) == pdPASS);
furi_timer_flush();
free(instance);
}
void furi_timer_flush(void) {
StaticEventGroup_t event_container = {};
EventGroupHandle_t hEvent = xEventGroupCreateStatic(&event_container);
furi_check(xTimerPendFunctionCall(furi_timer_epilogue, hEvent, 0, portMAX_DELAY) == pdPASS);
furi_check(
xTimerPendFunctionCall(furi_timer_flush_epilogue, hEvent, 0, portMAX_DELAY) == pdPASS);
furi_check(
xEventGroupWaitBits(hEvent, TIMER_DELETED_EVENT, pdFALSE, pdTRUE, portMAX_DELAY) ==
TIMER_DELETED_EVENT);
vEventGroupDelete(hEvent);
free(instance);
}
FuriStatus furi_timer_start(FuriTimer* instance, uint32_t ticks) {
@@ -112,6 +119,8 @@ FuriStatus furi_timer_stop(FuriTimer* instance) {
furi_check(xTimerStop(hTimer, portMAX_DELAY) == pdPASS);
furi_timer_flush();
return FuriStatusOk;
}

View File

@@ -35,6 +35,12 @@ FuriTimer* furi_timer_alloc(FuriTimerCallback func, FuriTimerType type, void* co
*/
void furi_timer_free(FuriTimer* instance);
/** Flush timer task control message queue
*
* Ensures that all commands before this point was processed.
*/
void furi_timer_flush(void);
/** Start timer
*
* @warning This is asynchronous call, real operation will happen as soon as
@@ -61,8 +67,7 @@ FuriStatus furi_timer_restart(FuriTimer* instance, uint32_t ticks);
/** Stop timer
*
* @warning This is asynchronous call, real operation will happen as soon as
* timer service process this request.
* @warning This is synchronous call that will be blocked till timer queue processed.
*
* @param instance The pointer to FuriTimer instance
*

View File

@@ -1,5 +1,7 @@
#include "furi.h"
#include "core/thread_i.h"
#include <FreeRTOS.h>
#include <queue.h>
@@ -7,6 +9,7 @@ void furi_init(void) {
furi_check(!furi_kernel_is_irq_or_masked());
furi_check(xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED);
furi_thread_init();
furi_log_init();
furi_record_init();
}
@@ -18,3 +21,7 @@ void furi_run(void) {
/* Start the kernel scheduler */
vTaskStartScheduler();
}
void furi_background(void) {
furi_thread_scrub();
}

View File

@@ -35,6 +35,8 @@ void furi_init(void);
void furi_run(void);
void furi_background(void);
#ifdef __cplusplus
}
#endif

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,76.0,,
Version,+,77.0,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
Header,+,applications/services/cli/cli.h,,
@@ -1102,6 +1102,7 @@ Function,-,ftello,off_t,FILE*
Function,-,ftrylockfile,int,FILE*
Function,-,funlockfile,void,FILE*
Function,-,funopen,FILE*,"const void*, int (*)(void*, char*, int), int (*)(void*, const char*, int), fpos_t (*)(void*, fpos_t, int), int (*)(void*)"
Function,-,furi_background,void,
Function,+,furi_delay_ms,void,uint32_t
Function,+,furi_delay_tick,void,uint32_t
Function,+,furi_delay_until_tick,FuriStatus,uint32_t
@@ -1672,6 +1673,7 @@ Function,+,furi_thread_stdout_write,size_t,"const char*, size_t"
Function,+,furi_thread_suspend,void,FuriThreadId
Function,+,furi_thread_yield,void,
Function,+,furi_timer_alloc,FuriTimer*,"FuriTimerCallback, FuriTimerType, void*"
Function,+,furi_timer_flush,void,
Function,+,furi_timer_free,void,FuriTimer*
Function,+,furi_timer_get_expire_time,uint32_t,FuriTimer*
Function,+,furi_timer_is_running,uint32_t,FuriTimer*
1 entry status name type params
2 Version + 76.0 77.0
3 Header + applications/services/bt/bt_service/bt.h
4 Header + applications/services/bt/bt_service/bt_keys_storage.h
5 Header + applications/services/cli/cli.h
1102 Function - ftrylockfile int FILE*
1103 Function - funlockfile void FILE*
1104 Function - funopen FILE* const void*, int (*)(void*, char*, int), int (*)(void*, const char*, int), fpos_t (*)(void*, fpos_t, int), int (*)(void*)
1105 Function - furi_background void
1106 Function + furi_delay_ms void uint32_t
1107 Function + furi_delay_tick void uint32_t
1108 Function + furi_delay_until_tick FuriStatus uint32_t
1673 Function + furi_thread_suspend void FuriThreadId
1674 Function + furi_thread_yield void
1675 Function + furi_timer_alloc FuriTimer* FuriTimerCallback, FuriTimerType, void*
1676 Function + furi_timer_flush void
1677 Function + furi_timer_free void FuriTimer*
1678 Function + furi_timer_get_expire_time uint32_t FuriTimer*
1679 Function + furi_timer_is_running uint32_t FuriTimer*

View File

@@ -1,5 +1,5 @@
entry,status,name,type,params
Version,+,76.0,,
Version,+,77.0,,
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
@@ -1207,6 +1207,7 @@ Function,-,ftello,off_t,FILE*
Function,-,ftrylockfile,int,FILE*
Function,-,funlockfile,void,FILE*
Function,-,funopen,FILE*,"const void*, int (*)(void*, char*, int), int (*)(void*, const char*, int), fpos_t (*)(void*, fpos_t, int), int (*)(void*)"
Function,-,furi_background,void,
Function,+,furi_delay_ms,void,uint32_t
Function,+,furi_delay_tick,void,uint32_t
Function,+,furi_delay_until_tick,FuriStatus,uint32_t
@@ -1886,6 +1887,7 @@ Function,+,furi_thread_stdout_write,size_t,"const char*, size_t"
Function,+,furi_thread_suspend,void,FuriThreadId
Function,+,furi_thread_yield,void,
Function,+,furi_timer_alloc,FuriTimer*,"FuriTimerCallback, FuriTimerType, void*"
Function,+,furi_timer_flush,void,
Function,+,furi_timer_free,void,FuriTimer*
Function,+,furi_timer_get_expire_time,uint32_t,FuriTimer*
Function,+,furi_timer_is_running,uint32_t,FuriTimer*
1 entry status name type params
2 Version + 76.0 77.0
3 Header + applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h
4 Header + applications/services/bt/bt_service/bt.h
5 Header + applications/services/bt/bt_service/bt_keys_storage.h
1207 Function - ftrylockfile int FILE*
1208 Function - funlockfile void FILE*
1209 Function - funopen FILE* const void*, int (*)(void*, char*, int), int (*)(void*, const char*, int), fpos_t (*)(void*, fpos_t, int), int (*)(void*)
1210 Function - furi_background void
1211 Function + furi_delay_ms void uint32_t
1212 Function + furi_delay_tick void uint32_t
1213 Function + furi_delay_until_tick FuriStatus uint32_t
1887 Function + furi_thread_suspend void FuriThreadId
1888 Function + furi_thread_yield void
1889 Function + furi_timer_alloc FuriTimer* FuriTimerCallback, FuriTimerType, void*
1890 Function + furi_timer_flush void
1891 Function + furi_timer_free void FuriTimer*
1892 Function + furi_timer_get_expire_time uint32_t FuriTimer*
1893 Function + furi_timer_is_running uint32_t FuriTimer*

View File

@@ -87,6 +87,8 @@ void ble_glue_init(void) {
TL_Init();
ble_glue->shci_mtx = furi_mutex_alloc(FuriMutexTypeNormal);
// Take mutex, SHCI will release it in most unusual way later
furi_check(furi_mutex_acquire(ble_glue->shci_mtx, FuriWaitForever) == FuriStatusOk);
// FreeRTOS system task creation
ble_event_thread_start();
@@ -248,7 +250,9 @@ void ble_glue_stop(void) {
ble_event_thread_stop();
// Free resources
furi_mutex_free(ble_glue->shci_mtx);
ble_glue->shci_mtx = NULL;
furi_timer_free(ble_glue->hardfault_check_timer);
ble_glue->hardfault_check_timer = NULL;
ble_glue_clear_shared_memory();
free(ble_glue);
@@ -309,10 +313,13 @@ BleGlueCommandResult ble_glue_force_c2_mode(BleGlueC2Mode desired_mode) {
static void ble_sys_status_not_callback(SHCI_TL_CmdStatus_t status) {
switch(status) {
case SHCI_TL_CmdBusy:
furi_mutex_acquire(ble_glue->shci_mtx, FuriWaitForever);
furi_check(
furi_mutex_acquire(
ble_glue->shci_mtx, furi_kernel_is_running() ? FuriWaitForever : 0) ==
FuriStatusOk);
break;
case SHCI_TL_CmdAvailable:
furi_mutex_release(ble_glue->shci_mtx);
furi_check(furi_mutex_release(ble_glue->shci_mtx) == FuriStatusOk);
break;
default:
break;

View File

@@ -129,7 +129,7 @@ BleEventFlowStatus ble_event_app_notification(void* pckt) {
event_pckt = (hci_event_pckt*)((hci_uart_pckt*)pckt)->data;
furi_check(gap);
furi_mutex_acquire(gap->state_mutex, FuriWaitForever);
furi_check(furi_mutex_acquire(gap->state_mutex, FuriWaitForever) == FuriStatusOk);
switch(event_pckt->evt) {
case HCI_DISCONNECTION_COMPLETE_EVT_CODE: {
@@ -304,7 +304,7 @@ BleEventFlowStatus ble_event_app_notification(void* pckt) {
break;
}
furi_mutex_release(gap->state_mutex);
furi_check(furi_mutex_release(gap->state_mutex) == FuriStatusOk);
return BleEventFlowEnable;
}
@@ -490,7 +490,7 @@ static void gap_advertise_stop(void) {
}
void gap_start_advertising(void) {
furi_mutex_acquire(gap->state_mutex, FuriWaitForever);
furi_check(furi_mutex_acquire(gap->state_mutex, FuriWaitForever) == FuriStatusOk);
if(gap->state == GapStateIdle) {
gap->state = GapStateStartingAdv;
FURI_LOG_I(TAG, "Start advertising");
@@ -498,18 +498,18 @@ void gap_start_advertising(void) {
GapCommand command = GapCommandAdvFast;
furi_check(furi_message_queue_put(gap->command_queue, &command, 0) == FuriStatusOk);
}
furi_mutex_release(gap->state_mutex);
furi_check(furi_mutex_release(gap->state_mutex) == FuriStatusOk);
}
void gap_stop_advertising(void) {
furi_mutex_acquire(gap->state_mutex, FuriWaitForever);
furi_check(furi_mutex_acquire(gap->state_mutex, FuriWaitForever) == FuriStatusOk);
if(gap->state > GapStateIdle) {
FURI_LOG_I(TAG, "Stop advertising");
gap->enable_adv = false;
GapCommand command = GapCommandAdvStop;
furi_check(furi_message_queue_put(gap->command_queue, &command, 0) == FuriStatusOk);
}
furi_mutex_release(gap->state_mutex);
furi_check(furi_mutex_release(gap->state_mutex) == FuriStatusOk);
}
static void gap_advetise_timer_callback(void* context) {
@@ -566,9 +566,9 @@ bool gap_init(GapConfig* config, GapEventCallback on_event_cb, void* context) {
GapState gap_get_state(void) {
GapState state;
if(gap) {
furi_mutex_acquire(gap->state_mutex, FuriWaitForever);
furi_check(furi_mutex_acquire(gap->state_mutex, FuriWaitForever) == FuriStatusOk);
state = gap->state;
furi_mutex_release(gap->state_mutex);
furi_check(furi_mutex_release(gap->state_mutex) == FuriStatusOk);
} else {
state = GapStateUninitialized;
}
@@ -577,17 +577,21 @@ GapState gap_get_state(void) {
void gap_thread_stop(void) {
if(gap) {
furi_mutex_acquire(gap->state_mutex, FuriWaitForever);
furi_check(furi_mutex_acquire(gap->state_mutex, FuriWaitForever) == FuriStatusOk);
gap->enable_adv = false;
GapCommand command = GapCommandKillThread;
furi_message_queue_put(gap->command_queue, &command, FuriWaitForever);
furi_mutex_release(gap->state_mutex);
furi_check(furi_mutex_release(gap->state_mutex) == FuriStatusOk);
furi_thread_join(gap->thread);
furi_thread_free(gap->thread);
gap->thread = NULL;
// Free resources
furi_mutex_free(gap->state_mutex);
gap->state_mutex = NULL;
furi_message_queue_free(gap->command_queue);
gap->command_queue = NULL;
furi_timer_free(gap->advertise_timer);
gap->advertise_timer = NULL;
ble_event_dispatcher_reset();
free(gap);
@@ -604,7 +608,7 @@ static int32_t gap_app(void* context) {
FURI_LOG_E(TAG, "Message queue get error: %d", status);
continue;
}
furi_mutex_acquire(gap->state_mutex, FuriWaitForever);
furi_check(furi_mutex_acquire(gap->state_mutex, FuriWaitForever) == FuriStatusOk);
if(command == GapCommandKillThread) {
break;
}
@@ -615,7 +619,7 @@ static int32_t gap_app(void* context) {
} else if(command == GapCommandAdvStop) {
gap_advertise_stop();
}
furi_mutex_release(gap->state_mutex);
furi_check(furi_mutex_release(gap->state_mutex) == FuriStatusOk);
}
return 0;

View File

@@ -202,7 +202,7 @@ bool furi_hal_spi_bus_trx_dma(
furi_check(size > 0);
// If scheduler is not running, use blocking mode
if(furi_kernel_is_running()) {
if(!furi_kernel_is_running()) {
return furi_hal_spi_bus_trx(handle, tx_buffer, rx_buffer, size, timeout_ms);
}

View File

@@ -84,6 +84,7 @@ to exclude the API function. */
#define INCLUDE_xTaskGetCurrentTaskHandle 1
#define INCLUDE_xTaskGetSchedulerState 1
#define INCLUDE_xTimerPendFunctionCall 1
#define INCLUDE_xTaskGetIdleTaskHandle 1
/* Workaround for various notification issues:
* - First one used by system primitives
@@ -129,25 +130,11 @@ See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY \
(configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS))
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
#ifdef DEBUG
#include <core/check.h>
#define configASSERT(x) \
if((x) == 0) { \
furi_crash("FreeRTOS Assert"); \
}
#endif
/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
standard names. */
#define vPortSVCHandler SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define USE_CUSTOM_SYSTICK_HANDLER_IMPLEMENTATION 1
#define configOVERRIDE_DEFAULT_TICK_CONFIGURATION \
1 /* required only for Keil but does not hurt otherwise */
#define traceTASK_SWITCHED_IN() \
extern void furi_hal_mpu_set_stack_protection(uint32_t* stack); \
furi_hal_mpu_set_stack_protection((uint32_t*)pxCurrentTCB->pxStack); \
@@ -157,6 +144,14 @@ standard names. */
// referencing `FreeRTOS_errno' here vvvvv because FreeRTOS calls our hook _before_ copying the value into the TCB, hence a manual write to the TCB would get overwritten
#define traceTASK_SWITCHED_OUT() FreeRTOS_errno = errno
#define portCLEAN_UP_TCB(pxTCB) \
extern void furi_thread_cleanup_tcb_event(TaskHandle_t task); \
furi_thread_cleanup_tcb_event(pxTCB)
/* Normal assert() semantics without relying on the provision of an assert.h
header file. */
#ifdef DEBUG
#define configASSERT(x) \
if((x) == 0) { \
furi_crash("FreeRTOS Assert"); \
}
#endif
// Must be last line of config because of recursion
#include <core/check.h>

View File

@@ -15,6 +15,8 @@ int32_t init_task(void* context) {
// Init flipper
flipper_init();
furi_background();
return 0;
}
@@ -25,7 +27,8 @@ int main(void) {
// Flipper critical FURI HAL
furi_hal_init_early();
FuriThread* main_thread = furi_thread_alloc_ex("Init", 4096, init_task, NULL);
FuriThread* main_thread = furi_thread_alloc_ex("InitSrv", 1024, init_task, NULL);
furi_thread_set_priority(main_thread, FuriThreadPriorityInit);
#ifdef FURI_RAM_EXEC
// Prevent entering sleep mode when executed from RAM