From 3c453a2a2090b1040bba3b14f32e0231479c920e Mon Sep 17 00:00:00 2001 From: aanper Date: Sat, 17 Oct 2020 11:48:29 +0300 Subject: [PATCH 1/5] refactor menu mutexes --- applications/menu/menu.c | 52 ++++++++++++++++++++++++---------- applications/menu/menu_event.c | 17 ----------- applications/menu/menu_event.h | 4 --- 3 files changed, 37 insertions(+), 36 deletions(-) diff --git a/applications/menu/menu.c b/applications/menu/menu.c index a0261bf58..546fcceae 100644 --- a/applications/menu/menu.c +++ b/applications/menu/menu.c @@ -3,7 +3,6 @@ #include #include -#include #include #include @@ -25,23 +24,30 @@ struct Menu { void menu_widget_callback(CanvasApi* canvas, void* context); -Menu* menu_init() { +ValueMutex* menu_init() { Menu* menu = furi_alloc(sizeof(Menu)); // Event dispatcher menu->event = menu_event_alloc(); + ValueMutex* menu_mutex = furi_alloc(sizeof(ValueMutex)); + if(menu_mutex == NULL || !init_mutex(menu_mutex, menu, sizeof(Menu))) { + printf("[menu_task] cannot create menu mutex\n"); + furiac_exit(NULL); + } + // Allocate and configure widget menu->widget = widget_alloc(); - widget_draw_callback_set(menu->widget, menu_widget_callback, menu); - widget_input_callback_set(menu->widget, menu_event_input_callback, menu->event); // Open GUI and register fullscreen widget GuiApi* gui = furi_open("gui"); assert(gui); gui->add_widget(gui, menu->widget, WidgetLayerFullscreen); - return menu; + widget_draw_callback_set(menu->widget, menu_widget_callback, menu_mutex); + widget_input_callback_set(menu->widget, menu_event_input_callback, menu->event); + + return menu_mutex; } void menu_build_main(Menu* menu) { @@ -79,10 +85,9 @@ void menu_settings_item_add(Menu* menu, MenuItem* item) { void menu_widget_callback(CanvasApi* canvas, void* context) { assert(canvas); assert(context); - - Menu* menu = context; - - menu_event_lock(menu->event); + + Menu* menu = acquire_mutex((ValueMutex*)context, 100); // wait 10 ms to get mutex + if(menu == NULL) return; // redraw fail if(!menu->current) { canvas->clear(canvas); @@ -102,7 +107,8 @@ void menu_widget_callback(CanvasApi* canvas, void* context) { } } - menu_event_unlock(menu->event); + release_mutex((ValueMutex*)context, menu); + } void menu_update(Menu* menu) { @@ -172,10 +178,22 @@ void menu_exit(Menu* menu) { } void menu_task(void* p) { - Menu* menu = menu_init(); - menu_build_main(menu); + ValueMutex* menu_mutex = menu_init(); - if(!furi_create_deprecated("menu", menu, sizeof(menu))) { + MenuEvent* menu_event = NULL; + { + Menu* menu = acquire_mutex_block(menu_mutex); + assert(menu); + + menu_build_main(menu); + + // immutable thread-safe object + menu_event = menu->event; + + release_mutex(menu_mutex, menu); + } + + if(!furi_create("menu", menu_mutex)) { printf("[menu_task] cannot create the menu record\n"); furiac_exit(NULL); } @@ -183,10 +201,12 @@ void menu_task(void* p) { furiac_ready(); while(1) { - MenuMessage m = menu_event_next(menu->event); + MenuMessage m = menu_event_next(menu_event); + + Menu* menu = acquire_mutex_block(menu_mutex); if(!menu->current && m.type != MenuMessageTypeOk) { - continue; + } else if(m.type == MenuMessageTypeUp) { menu_up(menu); } else if(m.type == MenuMessageTypeDown) { @@ -204,5 +224,7 @@ void menu_task(void* p) { } else { // TODO: fail somehow? } + + release_mutex(menu_mutex, menu); } } diff --git a/applications/menu/menu_event.c b/applications/menu/menu_event.c index bd4799729..4470ffd6a 100644 --- a/applications/menu/menu_event.c +++ b/applications/menu/menu_event.c @@ -12,7 +12,6 @@ struct MenuEvent { osMessageQueueId_t mqueue; osTimerId_t timeout_timer; - osMutexId_t lock_mutex; }; void MenuEventimeout_callback(void* arg) { @@ -32,29 +31,15 @@ MenuEvent* menu_event_alloc() { osTimerNew(MenuEventimeout_callback, osTimerOnce, menu_event, NULL); assert(menu_event->timeout_timer); - menu_event->lock_mutex = osMutexNew(NULL); - assert(menu_event->lock_mutex); - - menu_event_lock(menu_event); - return menu_event; } void menu_event_free(MenuEvent* menu_event) { assert(menu_event); - menu_event_unlock(menu_event); assert(osMessageQueueDelete(menu_event->mqueue) == osOK); free(menu_event); } -void menu_event_lock(MenuEvent* menu_event) { - assert(osMutexAcquire(menu_event->lock_mutex, osWaitForever) == osOK); -} - -void menu_event_unlock(MenuEvent* menu_event) { - assert(osMutexRelease(menu_event->lock_mutex) == osOK); -} - void menu_event_activity_notify(MenuEvent* menu_event) { assert(menu_event); osTimerStart(menu_event->timeout_timer, 60000U); // 1m timeout, return to main @@ -63,10 +48,8 @@ void menu_event_activity_notify(MenuEvent* menu_event) { MenuMessage menu_event_next(MenuEvent* menu_event) { assert(menu_event); MenuMessage message; - menu_event_unlock(menu_event); while(osMessageQueueGet(menu_event->mqueue, &message, NULL, osWaitForever) != osOK) { }; - menu_event_lock(menu_event); return message; } diff --git a/applications/menu/menu_event.h b/applications/menu/menu_event.h index 858dc27b6..031b8f4e6 100644 --- a/applications/menu/menu_event.h +++ b/applications/menu/menu_event.h @@ -25,10 +25,6 @@ MenuEvent* menu_event_alloc(); void menu_event_free(MenuEvent* menu_event); -void menu_event_lock(MenuEvent* menu_event); - -void menu_event_unlock(MenuEvent* menu_event); - void menu_event_activity_notify(MenuEvent* menu_event); MenuMessage menu_event_next(MenuEvent* menu_event); From 566ba378ff8abd8cb588a9d5231459def150b968 Mon Sep 17 00:00:00 2001 From: aanper Date: Sat, 17 Oct 2020 11:48:52 +0300 Subject: [PATCH 2/5] add apploader example --- applications/app-loader/app-loader.c | 18 ++++++++++++++++++ applications/applications.mk | 1 + applications/startup.h | 2 ++ core/flipper.h | 2 ++ core/flipper_v2.h | 2 ++ 5 files changed, 25 insertions(+) create mode 100644 applications/app-loader/app-loader.c diff --git a/applications/app-loader/app-loader.c b/applications/app-loader/app-loader.c new file mode 100644 index 000000000..e15787af7 --- /dev/null +++ b/applications/app-loader/app-loader.c @@ -0,0 +1,18 @@ +#include "flipper.h" + +/* +render_loader + +handle_input + +handle_menu +*/ + +void app_loader(void* p) { + osThreadId_t self_id = osThreadGetId(); + assert(self_id); + + printf("[app loader] start\n"); + + osThreadSuspend(self_id); +} \ No newline at end of file diff --git a/applications/applications.mk b/applications/applications.mk index 188a2abed..3b4c4f9aa 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -16,6 +16,7 @@ APP_INPUT = 1 APP_GUI = 1 CFLAGS += -DAPP_MENU C_SOURCES += $(wildcard $(APP_DIR)/menu/*.c) +C_SOURCES += $(wildcard $(APP_DIR)/app-loader/*.c) endif APP_TEST ?= 0 diff --git a/applications/startup.h b/applications/startup.h index 847009dc2..342a22348 100644 --- a/applications/startup.h +++ b/applications/startup.h @@ -27,6 +27,7 @@ void u8g2_qrcode(void* p); void fatfs_list(void* p); void gui_task(void* p); void backlight_control(void* p); +void app_loader(void* p); const FlipperStartupApp FLIPPER_STARTUP[] = { #ifdef APP_DISPLAY @@ -44,6 +45,7 @@ const FlipperStartupApp FLIPPER_STARTUP[] = { #ifdef APP_MENU {.app = menu_task, .name = "menu_task", .libs = {1, FURI_LIB{"gui_task"}}}, + {.app = app_loader, .name = "app_loader", .libs = {1, FURI_LIB{"menu_task"}}}, #endif // {.app = coreglitch_demo_0, .name = "coreglitch_demo_0", .libs = ""}, diff --git a/core/flipper.h b/core/flipper.h index 8e4cd0985..890f0d25d 100644 --- a/core/flipper.h +++ b/core/flipper.h @@ -16,6 +16,8 @@ extern "C" { } #endif +#include + // Arduino defines #define pinMode app_gpio_init diff --git a/core/flipper_v2.h b/core/flipper_v2.h index 9e3bc90e9..6d3fa47fb 100644 --- a/core/flipper_v2.h +++ b/core/flipper_v2.h @@ -1,5 +1,7 @@ #pragma once +#include "flipper.h" + #include "api-basic/furi.h" //#include "api-basic/flapp.h" #include "cmsis_os2.h" From b9fbf7861610ed77ca04fd40be34355f3fb69246 Mon Sep 17 00:00:00 2001 From: aanper Date: Sat, 17 Oct 2020 12:58:14 +0300 Subject: [PATCH 3/5] sandbox gui --- applications/app-loader/app-loader.c | 118 +++++++++++++++++++++++++-- applications/applications.mk | 4 + applications/menu/menu.c | 13 +-- applications/menu/menu.h | 2 + applications/startup.h | 14 ---- core/flipper.h | 2 + 6 files changed, 121 insertions(+), 32 deletions(-) diff --git a/applications/app-loader/app-loader.c b/applications/app-loader/app-loader.c index e15787af7..54d5465b0 100644 --- a/applications/app-loader/app-loader.c +++ b/applications/app-loader/app-loader.c @@ -1,17 +1,123 @@ -#include "flipper.h" +#include "flipper_v2.h" +#include +#include "menu/menu.h" -/* -render_loader +typedef struct { + FuriApp* handler; + Widget* widget; + FlipperStartupApp* current_app; +} AppLoaderState; -handle_input +typedef struct { + AppLoaderState* state; + FlipperStartupApp* app; +} AppLoaderContext; -handle_menu -*/ +void render_callback(CanvasApi* canvas, void* _ctx) { + AppLoaderState* ctx = (AppLoaderState*)_ctx; + + canvas->clear(canvas); + canvas->set_color(canvas, ColorBlack); + canvas->set_font(canvas, FontPrimary); + canvas->draw_str(canvas, 2, 32, ctx->current_app->name); + + canvas->set_font(canvas, FontSecondary); + canvas->draw_str(canvas, 2, 44, "press back to exit"); +} + +void input_callback(InputEvent* input_event, void* _ctx) { + AppLoaderState* ctx = (AppLoaderState*)_ctx; + + if(input_event->state && input_event->input == InputBack){ + widget_enabled_set(ctx->widget, false); + } +} + +void handle_menu(void* _ctx) { + AppLoaderContext* ctx = (AppLoaderContext*)_ctx; + + ctx->state->current_app = ctx->app; + + widget_enabled_set(ctx->state->widget, true); + + // TODO create a dependency tree and run tasks in the desired order + // furiac_wait_libs(&FLIPPER_STARTUP[i].libs); + // handlers[i] = furiac_start(FLIPPER_STARTUP[i].app, FLIPPER_STARTUP[i].name, NULL); + // FuriApp* handlers[flipper_app_count]; +} + +void application_blink(void* p); +void application_uart_write(void* p); +void application_input_dump(void* p); + +const FlipperStartupApp FLIPPER_APPS[] = { + {.app = application_blink, .name = "blink", .libs = {0}}, + {.app = application_uart_write, .name = "uart write", .libs = {0}}, + {.app = application_input_dump, .name = "input dump", .libs = {1, FURI_LIB{"input_task"}}}, +}; void app_loader(void* p) { osThreadId_t self_id = osThreadGetId(); assert(self_id); + AppLoaderState state; + state.handler = NULL; + + state.widget = widget_alloc(); + assert(state.widget); + widget_enabled_set(state.widget, false); + widget_draw_callback_set(state.widget, render_callback, &state); + widget_input_callback_set(state.widget, input_callback, &state); + + ValueMutex* menu_mutex = furi_open("menu"); + if(menu_mutex == NULL) { + printf("menu is not available\n"); + furiac_exit(NULL); + } + + // Open GUI and register widget + GuiApi* gui = furi_open("gui"); + if(gui == NULL) { + printf("gui is not available\n"); + furiac_exit(NULL); + } + gui->add_widget(gui, state.widget, WidgetLayerFullscreen); + + { + Menu* menu = acquire_mutex_block(menu_mutex); + + // FURI startup + const size_t flipper_app_count = sizeof(FLIPPER_APPS) / sizeof(FLIPPER_APPS[0]); + + for(size_t i = 0; i < flipper_app_count; i++) { + AppLoaderContext* ctx = furi_alloc(sizeof(AppLoaderContext)); + ctx->state = &state; + ctx->app = &FLIPPER_APPS[i]; + + menu_item_add(menu, menu_item_alloc_function( + FLIPPER_APPS[i].name, + NULL, + handle_menu, + ctx + )); + } + + /* + menu_item_add(menu, menu_item_alloc_function("Sub 1 gHz", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("125 kHz RFID", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("Infrared", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("I-Button", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("USB", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("Bluetooth", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("GPIO / HW", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("U2F", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("Tamagotchi", NULL, NULL, NULL)); + menu_item_add(menu, menu_item_alloc_function("Plugins", NULL, NULL, NULL)); + */ + + release_mutex(menu_mutex, menu); + } + printf("[app loader] start\n"); osThreadSuspend(self_id); diff --git a/applications/applications.mk b/applications/applications.mk index 3b4c4f9aa..2f1c82ddd 100644 --- a/applications/applications.mk +++ b/applications/applications.mk @@ -17,6 +17,10 @@ APP_GUI = 1 CFLAGS += -DAPP_MENU C_SOURCES += $(wildcard $(APP_DIR)/menu/*.c) C_SOURCES += $(wildcard $(APP_DIR)/app-loader/*.c) + +APP_EXAMPLE_BLINK = 1 +APP_EXAMPLE_UART_WRITE = 1 +APP_EXAMPLE_INPUT_DUMP = 1 endif APP_TEST ?= 0 diff --git a/applications/menu/menu.c b/applications/menu/menu.c index 546fcceae..70bb3b072 100644 --- a/applications/menu/menu.c +++ b/applications/menu/menu.c @@ -55,17 +55,6 @@ void menu_build_main(Menu* menu) { // Root point menu->root = menu_item_alloc_menu(NULL, NULL); - menu_item_add(menu, menu_item_alloc_function("Sub 1 gHz", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("125 kHz RFID", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("Infrared", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("I-Button", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("USB", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("Bluetooth", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("GPIO / HW", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("U2F", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("Tamagotchi", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("Plugins", NULL, NULL, NULL)); - menu->settings = menu_item_alloc_menu("Setting", NULL); menu_item_subitem_add(menu->settings, menu_item_alloc_function("one", NULL, NULL, NULL)); menu_item_subitem_add(menu->settings, menu_item_alloc_function("two", NULL, NULL, NULL)); @@ -206,7 +195,7 @@ void menu_task(void* p) { Menu* menu = acquire_mutex_block(menu_mutex); if(!menu->current && m.type != MenuMessageTypeOk) { - + } else if(m.type == MenuMessageTypeUp) { menu_up(menu); } else if(m.type == MenuMessageTypeDown) { diff --git a/applications/menu/menu.h b/applications/menu/menu.h index 01c68be28..f8607fda1 100644 --- a/applications/menu/menu.h +++ b/applications/menu/menu.h @@ -1,5 +1,7 @@ #pragma once +#include "menu/menu_item.h" + typedef struct Menu Menu; typedef struct MenuItem MenuItem; diff --git a/applications/startup.h b/applications/startup.h index 342a22348..e0a2683f8 100644 --- a/applications/startup.h +++ b/applications/startup.h @@ -2,8 +2,6 @@ #include "flipper.h" -#define FURI_LIB (const char*[]) - #ifdef APP_TEST void flipper_test_app(void* p); #endif @@ -54,23 +52,11 @@ const FlipperStartupApp FLIPPER_STARTUP[] = { {.app = flipper_test_app, .name = "test app", .libs = {0}}, #endif -#ifdef APP_EXAMPLE_BLINK - {.app = application_blink, .name = "blink", .libs = {0}}, -#endif - -#ifdef APP_EXAMPLE_UART_WRITE - {.app = application_uart_write, .name = "uart write", .libs = {0}}, -#endif - #ifdef APP_EXAMPLE_IPC {.app = application_ipc_display, .name = "ipc display", .libs = {0}}, {.app = application_ipc_widget, .name = "ipc widget", .libs = {0}}, #endif -#ifdef APP_EXAMPLE_INPUT_DUMP - {.app = application_input_dump, .name = "input dump", .libs = {1, FURI_LIB{"input_task"}}}, -#endif - #ifdef APP_EXAMPLE_QRCODE {.app = u8g2_qrcode, .name = "u8g2_qrcode", .libs = {1, FURI_LIB{"display_u8g2"}}}, #endif diff --git a/core/flipper.h b/core/flipper.h index 890f0d25d..6f867a5f8 100644 --- a/core/flipper.h +++ b/core/flipper.h @@ -34,3 +34,5 @@ extern "C" { #define HIGH true void set_exitcode(uint32_t _exitcode); + +#define FURI_LIB (const char*[]) From 0f4799d70b7840bfba5fd7015d9ce8f14ebb8815 Mon Sep 17 00:00:00 2001 From: aanper Date: Sat, 17 Oct 2020 13:10:53 +0300 Subject: [PATCH 4/5] run/kill app, issue with multiple load --- applications/app-loader/app-loader.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/applications/app-loader/app-loader.c b/applications/app-loader/app-loader.c index 54d5465b0..1c7219cb0 100644 --- a/applications/app-loader/app-loader.c +++ b/applications/app-loader/app-loader.c @@ -29,6 +29,7 @@ void input_callback(InputEvent* input_event, void* _ctx) { AppLoaderState* ctx = (AppLoaderState*)_ctx; if(input_event->state && input_event->input == InputBack){ + furiac_kill(ctx->handler); widget_enabled_set(ctx->widget, false); } } @@ -36,14 +37,13 @@ void input_callback(InputEvent* input_event, void* _ctx) { void handle_menu(void* _ctx) { AppLoaderContext* ctx = (AppLoaderContext*)_ctx; - ctx->state->current_app = ctx->app; - widget_enabled_set(ctx->state->widget, true); - // TODO create a dependency tree and run tasks in the desired order + // TODO how to call this? // furiac_wait_libs(&FLIPPER_STARTUP[i].libs); - // handlers[i] = furiac_start(FLIPPER_STARTUP[i].app, FLIPPER_STARTUP[i].name, NULL); - // FuriApp* handlers[flipper_app_count]; + + ctx->state->current_app = ctx->app; + ctx->state->handler = furiac_start(ctx->app->app, ctx->app->name, NULL); } void application_blink(void* p); From 66f6df08cc08a6d6b4eef1a0dfc93922c3559eda Mon Sep 17 00:00:00 2001 From: aanper Date: Sat, 17 Oct 2020 13:41:50 +0300 Subject: [PATCH 5/5] syntax fix --- applications/app-loader/app-loader.c | 10 +++------- applications/menu/menu.c | 4 +--- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/applications/app-loader/app-loader.c b/applications/app-loader/app-loader.c index 1c7219cb0..81a9d84c2 100644 --- a/applications/app-loader/app-loader.c +++ b/applications/app-loader/app-loader.c @@ -28,7 +28,7 @@ void render_callback(CanvasApi* canvas, void* _ctx) { void input_callback(InputEvent* input_event, void* _ctx) { AppLoaderState* ctx = (AppLoaderState*)_ctx; - if(input_event->state && input_event->input == InputBack){ + if(input_event->state && input_event->input == InputBack) { furiac_kill(ctx->handler); widget_enabled_set(ctx->widget, false); } @@ -94,12 +94,8 @@ void app_loader(void* p) { ctx->state = &state; ctx->app = &FLIPPER_APPS[i]; - menu_item_add(menu, menu_item_alloc_function( - FLIPPER_APPS[i].name, - NULL, - handle_menu, - ctx - )); + menu_item_add( + menu, menu_item_alloc_function(FLIPPER_APPS[i].name, NULL, handle_menu, ctx)); } /* diff --git a/applications/menu/menu.c b/applications/menu/menu.c index 70bb3b072..b305c4cb0 100644 --- a/applications/menu/menu.c +++ b/applications/menu/menu.c @@ -74,7 +74,7 @@ void menu_settings_item_add(Menu* menu, MenuItem* item) { void menu_widget_callback(CanvasApi* canvas, void* context) { assert(canvas); assert(context); - + Menu* menu = acquire_mutex((ValueMutex*)context, 100); // wait 10 ms to get mutex if(menu == NULL) return; // redraw fail @@ -97,7 +97,6 @@ void menu_widget_callback(CanvasApi* canvas, void* context) { } release_mutex((ValueMutex*)context, menu); - } void menu_update(Menu* menu) { @@ -195,7 +194,6 @@ void menu_task(void* p) { Menu* menu = acquire_mutex_block(menu_mutex); if(!menu->current && m.type != MenuMessageTypeOk) { - } else if(m.type == MenuMessageTypeUp) { menu_up(menu); } else if(m.type == MenuMessageTypeDown) {