mirror of
https://github.com/flipperdevices/flipperzero-firmware.git
synced 2025-12-12 04:41:26 +04:00
[FL-3954, FL-3955] New CLI architecture (#4111)
* feat: FuriThread stdin * ci: fix f18 * feat: stdio callback context * feat: FuriPipe * POTENTIALLY EXPLOSIVE pipe welding * fix: non-explosive welding * Revert welding * docs: furi_pipe * feat: pipe event loop integration * update f18 sdk * f18 * docs: make doxygen happy * fix: event loop not triggering when pipe attached to stdio * fix: partial stdout in pipe * allow simultaneous in and out subscription in event loop * feat: vcp i/o * feat: cli ansi stuffs and history * feat: more line editing * working but slow cli rewrite * restore previous speed after 4 days of debugging 🥲 * fix: cli_app_should_stop * fix: cli and event_loop memory leaks * style: remove commented out code * ci: fix pvs warnings * fix: unit tests, event_loop crash * ci: fix build * ci: silence pvs warning * feat: cli gpio * ci: fix formatting * Fix memory leak during event loop unsubscription * Event better memory leak fix * feat: cli completions * Merge remote-tracking branch 'origin/dev' into portasynthinca3/3928-cli-threads * merge fixups * temporarily exclude speaker_debug app * pvs and unit tests fixups * feat: commands in fals * move commands out of flash, code cleanup * ci: fix errors * fix: run commands in buffer when stopping session * speedup cli file transfer * fix f18 * separate cli_shell into modules * fix pvs warning * fix qflipper refusing to connect * remove temp debug logs * remove erroneous conclusion * Fix memory leak during event loop unsubscription * Event better memory leak fix * unit test for the fix * improve thread stdio callback signatures * pipe stdout timeout * update api symbols * fix f18, formatting * fix pvs warnings * increase stack size, hope to fix unit tests * cli: revert flag changes * cli: fix formatting * cli, fbt: loopback perf benchmark * thread, event_loop: subscribing to thread flags * cli: signal internal events using thread flags, improve performance * fix f18, formatting * event_loop: fix crash * storage_cli: increase write_chunk buffer size again * cli: explanation for order=0 * thread, event_loop: thread flags callback refactor * cli: increase stack size * cli: rename cli_app_should_stop -> cli_is_pipe_broken_or_is_etx_next_char * cli: use plain array instead of mlib for history * cli: prepend file name to static fns * cli: fix formatting * cli_shell: increase stack size * cli: fix rpc lockup * cli: better lockup fix * cli: fix f18 * fix merge --------- Co-authored-by: Georgii Surkov <georgii.surkov@outlook.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
@@ -41,6 +41,16 @@ extern "C" {
|
||||
#define CLAMP(x, upper, lower) (MIN(upper, MAX(x, lower)))
|
||||
#endif
|
||||
|
||||
#ifndef CLAMP_WRAPAROUND
|
||||
#define CLAMP_WRAPAROUND(x, upper, lower) \
|
||||
({ \
|
||||
__typeof__(x) _x = (x); \
|
||||
__typeof__(upper) _upper = (upper); \
|
||||
__typeof__(lower) _lower = (lower); \
|
||||
(_x > _upper) ? _lower : ((_x < _lower) ? _upper : _x); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifndef COUNT_OF
|
||||
#define COUNT_OF(x) (sizeof(x) / sizeof(x[0]))
|
||||
#endif
|
||||
|
||||
@@ -78,6 +78,7 @@ void furi_event_loop_free(FuriEventLoop* instance) {
|
||||
furi_event_loop_process_timer_queue(instance);
|
||||
furi_check(TimerList_empty_p(instance->timer_list));
|
||||
furi_check(WaitingList_empty_p(instance->waiting_list));
|
||||
furi_check(!instance->are_thread_flags_subscribed);
|
||||
|
||||
FuriEventLoopTree_clear(instance->tree);
|
||||
PendingQueue_clear(instance->pending_queue);
|
||||
@@ -243,6 +244,10 @@ void furi_event_loop_run(FuriEventLoop* instance) {
|
||||
} else if(flags & FuriEventLoopFlagPending) {
|
||||
furi_event_loop_process_pending_callbacks(instance);
|
||||
|
||||
} else if(flags & FuriEventLoopFlagThreadFlag) {
|
||||
if(instance->are_thread_flags_subscribed)
|
||||
instance->thread_flags_callback(instance->thread_flags_callback_context);
|
||||
|
||||
} else {
|
||||
furi_crash();
|
||||
}
|
||||
@@ -416,6 +421,24 @@ void furi_event_loop_subscribe_mutex(
|
||||
instance, mutex, &furi_mutex_event_loop_contract, event, callback, context);
|
||||
}
|
||||
|
||||
void furi_event_loop_subscribe_thread_flags(
|
||||
FuriEventLoop* instance,
|
||||
FuriEventLoopThreadFlagsCallback callback,
|
||||
void* context) {
|
||||
furi_check(instance);
|
||||
furi_check(callback);
|
||||
furi_check(!instance->are_thread_flags_subscribed);
|
||||
instance->are_thread_flags_subscribed = true;
|
||||
instance->thread_flags_callback = callback;
|
||||
instance->thread_flags_callback_context = context;
|
||||
}
|
||||
|
||||
void furi_event_loop_unsubscribe_thread_flags(FuriEventLoop* instance) {
|
||||
furi_check(instance);
|
||||
furi_check(instance->are_thread_flags_subscribed);
|
||||
instance->are_thread_flags_subscribed = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Public generic unsubscription API
|
||||
*/
|
||||
@@ -538,6 +561,25 @@ static bool furi_event_loop_item_is_waiting(FuriEventLoopItem* instance) {
|
||||
return instance->WaitingList.prev || instance->WaitingList.next;
|
||||
}
|
||||
|
||||
void furi_event_loop_thread_flag_callback(FuriThreadId thread_id) {
|
||||
TaskHandle_t hTask = (TaskHandle_t)thread_id;
|
||||
BaseType_t yield;
|
||||
|
||||
if(FURI_IS_IRQ_MODE()) {
|
||||
yield = pdFALSE;
|
||||
(void)xTaskNotifyIndexedFromISR(
|
||||
hTask,
|
||||
FURI_EVENT_LOOP_FLAG_NOTIFY_INDEX,
|
||||
FuriEventLoopFlagThreadFlag,
|
||||
eSetBits,
|
||||
&yield);
|
||||
portYIELD_FROM_ISR(yield);
|
||||
} else {
|
||||
(void)xTaskNotifyIndexed(
|
||||
hTask, FURI_EVENT_LOOP_FLAG_NOTIFY_INDEX, FuriEventLoopFlagThreadFlag, eSetBits);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Internal event loop link API, used by supported primitives
|
||||
*/
|
||||
|
||||
@@ -203,6 +203,12 @@ typedef void FuriEventLoopObject;
|
||||
*/
|
||||
typedef void (*FuriEventLoopEventCallback)(FuriEventLoopObject* object, void* context);
|
||||
|
||||
/** Callback type for event loop thread flag events
|
||||
*
|
||||
* @param context The context that was provided upon subscription
|
||||
*/
|
||||
typedef void (*FuriEventLoopThreadFlagsCallback)(void* context);
|
||||
|
||||
/** Opaque event flag type */
|
||||
typedef struct FuriEventFlag FuriEventFlag;
|
||||
|
||||
@@ -304,6 +310,23 @@ void furi_event_loop_subscribe_mutex(
|
||||
FuriEventLoopEventCallback callback,
|
||||
void* context);
|
||||
|
||||
/** Subscribe to thread flag events of the current thread
|
||||
*
|
||||
* @param instance The Event Loop instance
|
||||
* @param callback The callback to call when a flag has been set
|
||||
* @param context The context for callback
|
||||
*/
|
||||
void furi_event_loop_subscribe_thread_flags(
|
||||
FuriEventLoop* instance,
|
||||
FuriEventLoopThreadFlagsCallback callback,
|
||||
void* context);
|
||||
|
||||
/** Unsubscribe from thread flag events of the current thread
|
||||
*
|
||||
* @param instance The Event Loop instance
|
||||
*/
|
||||
void furi_event_loop_unsubscribe_thread_flags(FuriEventLoop* instance);
|
||||
|
||||
/** Unsubscribe from events (common)
|
||||
*
|
||||
* @param instance The Event Loop instance
|
||||
|
||||
@@ -4,12 +4,14 @@
|
||||
#include "event_loop_link_i.h"
|
||||
#include "event_loop_timer_i.h"
|
||||
#include "event_loop_tick_i.h"
|
||||
#include "event_loop_thread_flag_interface.h"
|
||||
|
||||
#include <m-list.h>
|
||||
#include <m-bptree.h>
|
||||
#include <m-i-list.h>
|
||||
|
||||
#include "thread.h"
|
||||
#include "thread_i.h"
|
||||
|
||||
struct FuriEventLoopItem {
|
||||
// Source
|
||||
@@ -50,11 +52,12 @@ typedef enum {
|
||||
FuriEventLoopFlagStop = (1 << 1),
|
||||
FuriEventLoopFlagTimer = (1 << 2),
|
||||
FuriEventLoopFlagPending = (1 << 3),
|
||||
FuriEventLoopFlagThreadFlag = (1 << 4),
|
||||
} FuriEventLoopFlag;
|
||||
|
||||
#define FuriEventLoopFlagAll \
|
||||
(FuriEventLoopFlagEvent | FuriEventLoopFlagStop | FuriEventLoopFlagTimer | \
|
||||
FuriEventLoopFlagPending)
|
||||
FuriEventLoopFlagPending | FuriEventLoopFlagThreadFlag)
|
||||
|
||||
typedef enum {
|
||||
FuriEventLoopProcessStatusComplete,
|
||||
@@ -94,4 +97,9 @@ struct FuriEventLoop {
|
||||
PendingQueue_t pending_queue;
|
||||
// Tick event
|
||||
FuriEventLoopTick tick;
|
||||
|
||||
// Thread flags callback
|
||||
bool are_thread_flags_subscribed;
|
||||
FuriEventLoopThreadFlagsCallback thread_flags_callback;
|
||||
void* thread_flags_callback_context;
|
||||
};
|
||||
|
||||
10
furi/core/event_loop_thread_flag_interface.h
Normal file
10
furi/core/event_loop_thread_flag_interface.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include "thread.h"
|
||||
|
||||
/**
|
||||
* @brief Notify `FuriEventLoop` that `furi_thread_flags_set` has been called
|
||||
*
|
||||
* @param thread_id Thread id
|
||||
*/
|
||||
extern void furi_event_loop_thread_flag_callback(FuriThreadId thread_id);
|
||||
@@ -7,6 +7,7 @@
|
||||
#include "check.h"
|
||||
#include "common_defines.h"
|
||||
#include "string.h"
|
||||
#include "event_loop_thread_flag_interface.h"
|
||||
|
||||
#include "log.h"
|
||||
#include <furi_hal_rtc.h>
|
||||
@@ -501,6 +502,9 @@ uint32_t furi_thread_flags_set(FuriThreadId thread_id, uint32_t flags) {
|
||||
(void)xTaskNotifyAndQueryIndexed(hTask, THREAD_NOTIFY_INDEX, 0, eNoAction, &rflags);
|
||||
}
|
||||
}
|
||||
|
||||
furi_event_loop_thread_flag_callback(thread_id);
|
||||
|
||||
/* Return flags after setting */
|
||||
return rflags;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user