Просмотр исходного кода

[FL-140] Core api dynamic records (#296)

* SYSTEM: tickless mode with deep sleep.
* Move FreeRTOS ticks to lptim2
* API: move all sumbodules init routines to one place. Timebase: working lptim2 at tick source.
* API Timebase: lp-timer routines, timer access safe zones prediction and synchronization. FreeRTOS: adjust configuration for tickless mode.
* NFC: support for tickless mode.
* API Timebase: improve tick error handling in IRQ. Apploader: use insomnia mode to run applications.
* BLE: prevent sleep while core2 starting
* HAL: nap while in insomnia mode
* init records work
* try to implement record delete
* tests and flapp
* flapp subsystem
* new core functions to get app stat, simplify core code
* fix thread termination
* add strdup to core
* fix tests
* Refactoring: remove all unusued parts, update API usage, aggreagate API sources and headers, new record storage
* Refactoring: update furi record api usage, cleanup code
* Fix broken merge for freertos apps
* Core, Target: fix compilation warnings
* Drop firmware target local
* HAL Timebase, Power, Clock: semaphore guarded access to clock and power modes, better sleep mode.
* SD-Filesystem: wait for all deps to arrive before adding widget. Core, BLE: disable debug dump to serial.
* delete old app example-ipc
* delete old app fatfs list
* fix strobe app, add input header
* delete old display driver
* comment old app qr-code
* fix sd-card test, add forced widget update
* remove unused new core test
* increase heap to 128k
* comment and assert old core tests
* fix syntax

Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
DrZlo13 5 лет назад
Родитель
Сommit
8f9b2513ff
100 измененных файлов с 659 добавлено и 1902 удалено
  1. 0 4
      .github/CODEOWNERS
  2. 0 10
      .github/workflows/ci.yml
  3. 1 8
      ReadMe.md
  4. 44 43
      applications/app-loader/app-loader.c
  5. 220 0
      applications/applications.c
  6. 14 289
      applications/applications.h
  7. 1 0
      applications/applications.mk
  8. 9 14
      applications/backlight-control/backlight-control.c
  9. 9 18
      applications/bt/bt.c
  10. 8 3
      applications/bt/bt_i.h
  11. 6 5
      applications/cc1101-workaround/cc1101-workaround.cpp
  12. 1 1
      applications/cc1101-workaround/cc1101.cpp
  13. 1 1
      applications/cc1101-workaround/cc1101.h
  14. 1 8
      applications/cli/cli.c
  15. 1 2
      applications/cli/cli_i.h
  16. 2 4
      applications/coreglitch_demo_0/coreglitch_demo_0.c
  17. 0 195
      applications/display-u8g2/display-u8g2.c
  18. 3 9
      applications/dolphin/dolphin.c
  19. 1 1
      applications/dolphin/dolphin_i.h
  20. 1 2
      applications/dolphin/dolphin_state.c
  21. 2 1
      applications/dolphin/dolphin_views.h
  22. 1 1
      applications/examples/blink.c
  23. 0 155
      applications/examples/fatfs_list.c
  24. 4 5
      applications/examples/input_dump.c
  25. 0 155
      applications/examples/ipc.c
  26. 3 3
      applications/examples/strobe.c
  27. 9 27
      applications/examples/u8g2_example.c
  28. 7 5
      applications/examples/u8g2_qrcode.c
  29. 2 7
      applications/examples/uart_write.c
  30. 3 2
      applications/examples/vibro.c
  31. 1 1
      applications/floopper-bloopper
  32. 5 7
      applications/gpio-tester/gpio-tester.c
  33. 1 2
      applications/gui/canvas.c
  34. 8 0
      applications/gui/canvas.h
  35. 8 0
      applications/gui/elements.h
  36. 3 8
      applications/gui/gui.c
  37. 8 0
      applications/gui/gui.h
  38. 2 2
      applications/gui/gui_event.c
  39. 8 0
      applications/gui/gui_event.h
  40. 1 3
      applications/gui/icon.c
  41. 8 0
      applications/gui/icon.h
  42. 9 9
      applications/gui/u8g2_periphery.c
  43. 8 0
      applications/gui/view.h
  44. 8 0
      applications/gui/view_dispatcher.h
  45. 1 1
      applications/gui/view_dispatcher_i.h
  46. 1 1
      applications/gui/view_i.h
  47. 1 5
      applications/gui/widget.c
  48. 8 0
      applications/gui/widget.h
  49. 1 1
      applications/ibutton/ibutton.cpp
  50. 3 11
      applications/input/input.c
  51. 1 2
      applications/irda/irda-decoder/irda-decoder.h
  52. 6 8
      applications/irda/irda.c
  53. 1 1
      applications/irda/irda_nec.c
  54. 1 1
      applications/irda/irda_nec.h
  55. 1 1
      applications/irda/irda_samsung.c
  56. 1 1
      applications/irda/irda_samsung.h
  57. 1 1
      applications/lf-rfid/em4100.c
  58. 5 8
      applications/lf-rfid/lf-rfid.c
  59. 3 10
      applications/menu/menu.c
  60. 1 3
      applications/menu/menu_event.c
  61. 1 2
      applications/menu/menu_item.c
  62. 6 8
      applications/music-player/music-player.c
  63. 3 9
      applications/nfc/nfc.c
  64. 1 1
      applications/nfc/nfc_i.h
  65. 1 1
      applications/nfc/nfc_views.h
  66. 1 2
      applications/nfc/nfc_worker_i.h
  67. 10 12
      applications/power/power.c
  68. 1 5
      applications/power/power_views.h
  69. 8 9
      applications/sd-card-test/sd-card-test.cpp
  70. 11 14
      applications/sd-filesystem/sd-filesystem.c
  71. 4 2
      applications/sd-filesystem/sd-filesystem.h
  72. 2 2
      applications/template/template.c.example
  73. 5 3
      applications/tests/furi_event_test.c
  74. 1 3
      applications/tests/furi_pubsub_test.c
  75. 3 5
      applications/tests/furi_record_test.c
  76. 1 1
      applications/tests/furi_value_expanders_test.c
  77. 4 2
      applications/tests/furi_valuemutex_test.c
  78. 4 2
      applications/tests/furiac_test.c
  79. 1 2
      applications/tests/minunit_test.c
  80. 1 3
      applications/tests/test_index.c
  81. 0 47
      core/api-basic/flapp.h
  82. 0 14
      core/api-basic/furi.c
  83. 0 26
      core/api-basic/furi.h
  84. 4 2
      core/api-hal/api-gpio.c
  85. 11 3
      core/api-hal/api-gpio.h
  86. 3 0
      core/api-hal/api-interrupt-mgr.c
  87. 11 2
      core/api-hal/api-interrupt-mgr.h
  88. 10 2
      core/api-hal/api-spi.h
  89. 0 48
      core/app.cpp
  90. 2 2
      core/core.mk
  91. 0 24
      core/flipper.h
  92. 0 16
      core/flipper_arduino.h
  93. 0 19
      core/flipper_v2.c
  94. 0 33
      core/flipper_v2.h
  95. 0 295
      core/furi-deprecated.c
  96. 0 207
      core/furi-deprecated.h
  97. 36 0
      core/furi.c
  98. 28 0
      core/furi.h
  99. 9 7
      core/furi/check.c
  100. 8 2
      core/furi/check.h

+ 0 - 4
.github/CODEOWNERS

@@ -19,10 +19,6 @@ firmware/targets/f4/api-hal/api-hal-boot.c @skotopes
 
 debug/** @skotopes
 
-# local target
-
-firmware/targets/local/** @glitchcore
-
 # BLE
 
 firmware/targets/f4/ble-glue/** @skotopes

+ 0 - 10
.github/workflows/ci.yml

@@ -32,16 +32,6 @@ jobs:
         with:
           run: /syntax_check.sh
 
-      - name: Build local testing firmware in docker
-        uses: ./.github/actions/docker
-        with:
-          run: make -C firmware TARGET=local
-
-      - name: Run local tests
-        uses: ./.github/actions/docker
-        with:
-          run: make -C firmware TARGET=local APP_TEST=1 run
-
       - name: Build F4 bootloader in docker
         uses: ./.github/actions/docker
         with:

+ 1 - 8
ReadMe.md

@@ -25,14 +25,7 @@ Flipper Zero's firmware consists of two components: Bootloader and main firmware
 
 ## Build from source
 
-You can run firmware locally (with HAL stub):
-
-* `docker-compose exec dev make -C firmware TARGET=local APP_TEST=1 run` for running tests
-* `docker-compose exec dev make -C firmware TARGET=local APP_*=1 run` for running examples (see `applications/applications.mk` for list of applications/examples)
-
-Or on your flipper:
-
-`docker-compose exec dev make -C firmware TARGET=f4 APP_*=1 flash` for build and flash dev board (see `applications/applications.mk` for list of applications/examples)
+`docker-compose exec dev make -C firmware TARGET=f4 APP_RELEASE=1 flash` for build and flash dev board (see `applications/applications.mk` for list of applications/examples)
 
 # Links
 * Task tracker: [Jira](https://flipperzero.atlassian.net/)

+ 44 - 43
applications/app-loader/app-loader.c

@@ -1,4 +1,4 @@
-#include "flipper_v2.h"
+#include <furi.h>
 #include <cli/cli.h>
 #include <gui/gui.h>
 #include "menu/menu.h"
@@ -8,14 +8,15 @@
 #include <api-hal.h>
 
 typedef struct {
-    FuriApp* handler;
+    osThreadAttr_t app_thread_attr;
+    osThreadId_t app_thread_id;
     Widget* widget;
-    const FlipperStartupApp* current_app;
+    const FuriApplication* current_app;
 } AppLoaderState;
 
 typedef struct {
     AppLoaderState* state;
-    const FlipperStartupApp* app;
+    const FuriApplication* app;
 } AppLoaderContext;
 
 // TODO add mutex for contex
@@ -36,7 +37,7 @@ static void input_callback(InputEvent* input_event, void* _ctx) {
     AppLoaderState* ctx = (AppLoaderState*)_ctx;
 
     if(input_event->state && input_event->input == InputBack) {
-        furiac_kill(ctx->handler);
+        osThreadTerminate(ctx->app_thread_id);
         widget_enabled_set(ctx->widget, false);
         api_hal_timebase_insomnia_exit();
     }
@@ -54,7 +55,16 @@ static void handle_menu(void* _ctx) {
     api_hal_timebase_insomnia_enter();
 
     ctx->state->current_app = ctx->app;
-    ctx->state->handler = furiac_start(ctx->app->app, ctx->app->name, NULL);
+    ctx->state->app_thread_attr.name = ctx->app->name;
+    ctx->state->app_thread_attr.attr_bits = osThreadDetached;
+    ctx->state->app_thread_attr.cb_mem = NULL;
+    ctx->state->app_thread_attr.cb_size = 0;
+    ctx->state->app_thread_attr.stack_mem = NULL;
+    ctx->state->app_thread_attr.stack_size = 1024;
+    ctx->state->app_thread_attr.priority = osPriorityNormal;
+    ctx->state->app_thread_attr.tz_module = 0;
+    ctx->state->app_thread_attr.reserved = 0;
+    ctx->state->app_thread_id = osThreadNew(ctx->app->app, NULL, &ctx->state->app_thread_attr);
 }
 
 static void handle_cli(string_t args, void* _ctx) {
@@ -65,13 +75,22 @@ static void handle_cli(string_t args, void* _ctx) {
     cli_print("Starting furi application\r\n");
 
     ctx->state->current_app = ctx->app;
-    ctx->state->handler = furiac_start(ctx->app->app, ctx->app->name, NULL);
+    ctx->state->app_thread_attr.name = ctx->app->name;
+    ctx->state->app_thread_attr.attr_bits = osThreadDetached;
+    ctx->state->app_thread_attr.cb_mem = NULL;
+    ctx->state->app_thread_attr.cb_size = 0;
+    ctx->state->app_thread_attr.stack_mem = NULL;
+    ctx->state->app_thread_attr.stack_size = 1024;
+    ctx->state->app_thread_attr.priority = osPriorityNormal;
+    ctx->state->app_thread_attr.tz_module = 0;
+    ctx->state->app_thread_attr.reserved = 0;
+    ctx->state->app_thread_id = osThreadNew(ctx->app->app, NULL, &ctx->state->app_thread_attr);
 
     cli_print("Press any key to kill application");
 
     char c;
     cli_read(&c, 1);
-    furiac_kill(ctx->state->handler);
+    osThreadTerminate(ctx->state->app_thread_id);
 }
 
 void app_loader(void* p) {
@@ -79,37 +98,23 @@ void app_loader(void* p) {
     furi_check(self_id);
 
     AppLoaderState state;
-    state.handler = NULL;
+    state.app_thread_id = NULL;
 
     state.widget = widget_alloc();
     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);
-    }
-
-    Cli* cli = furi_open("cli");
+    ValueMutex* menu_mutex = furi_record_open("menu");
+    Cli* cli = furi_record_open("cli");
+    Gui* gui = furi_record_open("gui");
 
-    // Open GUI and register widget
-    Gui* gui = furi_open("gui");
-    if(gui == NULL) {
-        printf("gui is not available\n");
-        furiac_exit(NULL);
-    }
     gui_add_widget(gui, state.widget, GuiLayerFullscreen);
 
-    // FURI startup
-    const size_t flipper_app_count = sizeof(FLIPPER_APPS) / sizeof(FLIPPER_APPS[0]);
-    const size_t flipper_plugins_count = sizeof(FLIPPER_PLUGINS) / sizeof(FLIPPER_PLUGINS[0]);
-
     // Main menu
     with_value_mutex(
         menu_mutex, (Menu * menu) {
-            for(size_t i = 0; i < flipper_app_count; i++) {
+            for(size_t i = 0; i < FLIPPER_APPS_size(); i++) {
                 AppLoaderContext* ctx = furi_alloc(sizeof(AppLoaderContext));
                 ctx->state = &state;
                 ctx->app = &FLIPPER_APPS[i];
@@ -123,13 +128,11 @@ void app_loader(void* p) {
                         ctx));
 
                 // Add cli command
-                if(cli) {
-                    string_t cli_name;
-                    string_init_set_str(cli_name, "app_");
-                    string_cat_str(cli_name, FLIPPER_APPS[i].name);
-                    cli_add_command(cli, string_get_cstr(cli_name), handle_cli, ctx);
-                    string_clear(cli_name);
-                }
+                string_t cli_name;
+                string_init_set_str(cli_name, "app_");
+                string_cat_str(cli_name, FLIPPER_APPS[i].name);
+                cli_add_command(cli, string_get_cstr(cli_name), handle_cli, ctx);
+                string_clear(cli_name);
             }
         });
 
@@ -157,7 +160,7 @@ void app_loader(void* p) {
             MenuItem* menu_plugins =
                 menu_item_alloc_menu("Plugins", assets_icons_get(A_Plugins_14));
 
-            for(size_t i = 0; i < flipper_plugins_count; i++) {
+            for(size_t i = 0; i < FLIPPER_PLUGINS_size(); i++) {
                 AppLoaderContext* ctx = furi_alloc(sizeof(AppLoaderContext));
                 ctx->state = &state;
                 ctx->app = &FLIPPER_PLUGINS[i];
@@ -171,13 +174,11 @@ void app_loader(void* p) {
                         ctx));
 
                 // Add cli command
-                if(cli) {
-                    string_t cli_name;
-                    string_init_set_str(cli_name, "app_");
-                    string_cat_str(cli_name, FLIPPER_PLUGINS[i].name);
-                    cli_add_command(cli, string_get_cstr(cli_name), handle_cli, ctx);
-                    string_clear(cli_name);
-                }
+                string_t cli_name;
+                string_init_set_str(cli_name, "app_");
+                string_cat_str(cli_name, FLIPPER_PLUGINS[i].name);
+                cli_add_command(cli, string_get_cstr(cli_name), handle_cli, ctx);
+                string_clear(cli_name);
             }
 
             menu_item_add(menu, menu_plugins);
@@ -186,4 +187,4 @@ void app_loader(void* p) {
     printf("[app loader] start\n");
 
     osThreadSuspend(self_id);
-}
+}

+ 220 - 0
applications/applications.c

@@ -0,0 +1,220 @@
+#include "applications.h"
+
+#ifdef APP_TEST
+void flipper_test_app(void* p);
+#endif
+
+void application_blink(void* p);
+void application_uart_write(void* p);
+void application_ipc_display(void* p);
+void application_ipc_widget(void* p);
+void application_input_dump(void* p);
+void display_u8g2(void* p);
+void u8g2_example(void* p);
+void input_task(void* p);
+void menu_task(void* p);
+void coreglitch_demo_0(void* p);
+void u8g2_qrcode(void* p);
+void fatfs_list(void* p);
+void gui_task(void* p);
+void backlight_control(void* p);
+void irda(void* p);
+void app_loader(void* p);
+void cc1101_workaround(void* p);
+void lf_rfid_workaround(void* p);
+void nfc_task(void* p);
+void dolphin_task(void* p);
+void power_task(void* p);
+void bt_task(void* p);
+void sd_card_test(void* p);
+void application_vibro(void* p);
+void app_gpio_test(void* p);
+void app_ibutton(void* p);
+void cli_task(void* p);
+void music_player(void* p);
+void sdnfc(void* p);
+void floopper_bloopper(void* p);
+void sd_filesystem(void* p);
+
+const FuriApplication FLIPPER_SERVICES[] = {
+#ifdef APP_DISPLAY
+    {.app = display_u8g2, .name = "display_u8g2", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_CLI
+    {.app = cli_task, .name = "cli_task", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_EXAMPLE_BLINK
+    {.app = application_blink, .name = "blink", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_INPUT
+    {.app = input_task, .name = "input_task", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_EXAMPLE_INPUT_DUMP
+    {.app = application_input_dump, .name = "input dump", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_GUI
+    {.app = backlight_control, .name = "backlight_control", .icon = A_Plugins_14},
+    {.app = gui_task, .name = "gui_task", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_MENU
+    {.app = menu_task, .name = "menu_task", .icon = A_Plugins_14},
+    {.app = app_loader, .name = "app_loader", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_SD_FILESYSTEM
+    {.app = sd_filesystem, .name = "sd_filesystem", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_DOLPHIN
+    {.app = dolphin_task, .name = "dolphin_task", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_POWER
+    {.app = power_task, .name = "power_task", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_BT
+    {.app = bt_task, .name = "bt_task", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_CC1101
+    {.app = cc1101_workaround, .name = "cc1101 workaround", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_LF_RFID
+    {.app = lf_rfid_workaround, .name = "lf rfid workaround", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_IRDA
+    {.app = irda, .name = "irda", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_NFC
+    {.app = nfc_task, .name = "nfc_task", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_TEST
+    {.app = flipper_test_app, .name = "test app", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_EXAMPLE_IPC
+    {.app = application_ipc_display, .name = "ipc display", .icon = A_Plugins_14},
+    {.app = application_ipc_widget, .name = "ipc widget", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_EXAMPLE_QRCODE
+    {.app = u8g2_qrcode, .name = "u8g2_qrcode", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_EXAMPLE_FATFS
+    {.app = fatfs_list, .name = "fatfs_list", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_EXAMPLE_DISPLAY
+    {.app = u8g2_example, .name = "u8g2_example", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_SPEAKER_DEMO
+    {.app = coreglitch_demo_0, .name = "coreglitch_demo_0", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_SD_TEST
+    {.app = sd_card_test, .name = "sd_card_test", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_MUSIC_PLAYER
+    {.app = music_player, .name = "music player", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_IBUTTON
+    {.app = app_ibutton, .name = "ibutton", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_GPIO_DEMO
+    {.app = app_gpio_test, .name = "gpio test", .icon = A_Plugins_14},
+#endif
+
+#ifdef APP_FLOOPPER_BLOOPPER
+    {.app = floopper_bloopper, .name = "Floopper Bloopper", .icon = A_Games_14},
+#endif
+
+#ifdef APP_SDNFC
+    {.app = sdnfc, .name = "sdnfc", .icon = A_Plugins_14},
+#endif
+};
+
+size_t FLIPPER_SERVICES_size() {
+    return sizeof(FLIPPER_SERVICES) / sizeof(FuriApplication);
+}
+
+// Main menu APP
+const FuriApplication FLIPPER_APPS[] = {
+#ifdef BUILD_CC1101
+    {.app = cc1101_workaround, .name = "Sub-1 GHz", .icon = A_Sub1ghz_14},
+#endif
+
+#ifdef BUILD_LF_RFID
+    {.app = lf_rfid_workaround, .name = "125 kHz RFID", .icon = A_125khz_14},
+#endif
+
+#ifdef BUILD_IRDA
+    {.app = irda, .name = "Infrared", .icon = A_Infrared_14},
+#endif
+
+#ifdef BUILD_IBUTTON
+    {.app = app_ibutton, .name = "iButton", .icon = A_iButton_14},
+#endif
+
+#ifdef BUILD_GPIO_DEMO
+    {.app = app_gpio_test, .name = "GPIO", .icon = A_GPIO_14},
+#endif
+};
+
+size_t FLIPPER_APPS_size() {
+    return sizeof(FLIPPER_APPS) / sizeof(FuriApplication);
+}
+
+// Plugin menu
+const FuriApplication FLIPPER_PLUGINS[] = {
+#ifdef BUILD_EXAMPLE_BLINK
+    {.app = application_blink, .name = "blink", .icon = A_Plugins_14},
+#endif
+
+#ifdef BUILD_EXAMPLE_INPUT_DUMP
+    {.app = application_input_dump, .name = "input dump", .icon = A_Plugins_14},
+#endif
+
+#ifdef BUILD_SPEAKER_DEMO
+    {.app = coreglitch_demo_0, .name = "coreglitch_demo_0", .icon = A_Plugins_14},
+#endif
+
+#ifdef BUILD_SD_TEST
+    {.app = sd_card_test, .name = "sd_card_test", .icon = A_Plugins_14},
+#endif
+
+#ifdef BUILD_VIBRO_DEMO
+    {.app = application_vibro, .name = "application_vibro", .icon = A_Plugins_14},
+#endif
+
+#ifdef BUILD_MUSIC_PLAYER
+    {.app = music_player, .name = "music player", .icon = A_Plugins_14},
+#endif
+
+#ifdef BUILD_FLOOPPER_BLOOPPER
+    {.app = floopper_bloopper, .name = "Floopper Bloopper", .icon = A_Games_14},
+#endif
+
+#ifdef BUILD_SDNFC
+    {.app = sdnfc, .name = "sdnfc", .icon = A_Plugins_14},
+#endif
+};
+
+size_t FLIPPER_PLUGINS_size() {
+    return sizeof(FLIPPER_PLUGINS) / sizeof(FuriApplication);
+}

+ 14 - 289
applications/applications.h

@@ -1,296 +1,21 @@
 #pragma once
 
-#include "flipper.h"
+#include <furi.h>
+#include <assets_icons.h>
 
-#ifdef APP_TEST
-void flipper_test_app(void* p);
-#endif
+typedef void (*FlipperApplication)(void*);
 
-void application_blink(void* p);
-void application_uart_write(void* p);
-void application_ipc_display(void* p);
-void application_ipc_widget(void* p);
-void application_input_dump(void* p);
+typedef struct {
+    const FlipperApplication app;
+    const char* name;
+    const IconName icon;
+} FuriApplication;
 
-void display_u8g2(void* p);
+extern const FuriApplication FLIPPER_SERVICES[];
+size_t FLIPPER_SERVICES_size();
 
-void u8g2_example(void* p);
+extern const FuriApplication FLIPPER_APPS[];
+size_t FLIPPER_APPS_size();
 
-void input_task(void* p);
-void menu_task(void* p);
-
-void coreglitch_demo_0(void* p);
-
-void u8g2_qrcode(void* p);
-void fatfs_list(void* p);
-void gui_task(void* p);
-void backlight_control(void* p);
-void irda(void* p);
-void app_loader(void* p);
-void cc1101_workaround(void* p);
-void lf_rfid_workaround(void* p);
-void nfc_task(void* p);
-void dolphin_task(void* p);
-void power_task(void* p);
-void bt_task(void* p);
-void sd_card_test(void* p);
-void application_vibro(void* p);
-void app_gpio_test(void* p);
-void app_ibutton(void* p);
-void cli_task(void* p);
-void music_player(void* p);
-void sdnfc(void* p);
-void floopper_bloopper(void* p);
-void sd_filesystem(void* p);
-
-const FlipperStartupApp FLIPPER_STARTUP[] = {
-#ifdef APP_DISPLAY
-    {.app = display_u8g2, .name = "display_u8g2", .libs = {0}, .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_CLI
-    {.app = cli_task, .name = "cli_task", .libs = {0}, .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_EXAMPLE_BLINK
-    {.app = application_blink,
-     .name = "blink",
-     .libs = {1, FURI_LIB{"input_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_INPUT
-    {.app = input_task, .name = "input_task", .libs = {0}, .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_EXAMPLE_INPUT_DUMP
-    {.app = application_input_dump,
-     .name = "input dump",
-     .libs = {1, FURI_LIB{"input_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_GUI
-    {.app = backlight_control,
-     .name = "backlight_control",
-     .libs = {1, FURI_LIB{"input_task"}},
-     .icon = A_Plugins_14},
-    {.app = gui_task, .name = "gui_task", .libs = {0}, .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_MENU
-    {.app = menu_task,
-     .name = "menu_task",
-     .libs = {1, FURI_LIB{"gui_task"}},
-     .icon = A_Plugins_14},
-    {.app = app_loader,
-     .name = "app_loader",
-     .libs = {2, FURI_LIB{"menu_task", "cli_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_SD_FILESYSTEM
-    {.app = sd_filesystem,
-     .name = "sd_filesystem",
-     .libs = {1, FURI_LIB{"menu_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_DOLPHIN
-    {.app = dolphin_task,
-     .name = "dolphin_task",
-     .libs = {1, FURI_LIB{"menu_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_POWER
-    {.app = power_task,
-     .name = "power_task",
-     .libs = {2, FURI_LIB{"cli_task", "gui_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_BT
-    {.app = bt_task, .name = "bt_task", .libs = {1, FURI_LIB{"cli_task"}}, .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_CC1101
-    {.app = cc1101_workaround,
-     .name = "cc1101 workaround",
-     .libs = {1, FURI_LIB{"gui_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_LF_RFID
-    {.app = lf_rfid_workaround,
-     .name = "lf rfid workaround",
-     .libs = {1, FURI_LIB{"gui_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_IRDA
-    {.app = irda, .name = "irda", .libs = {1, FURI_LIB{"gui_task"}}, .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_NFC
-    {.app = nfc_task, .name = "nfc_task", .libs = {1, FURI_LIB{"menu_task"}}, .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_TEST
-    {.app = flipper_test_app, .name = "test app", .libs = {0}, .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_EXAMPLE_IPC
-    {.app = application_ipc_display, .name = "ipc display", .libs = {0}, .icon = A_Plugins_14},
-    {.app = application_ipc_widget, .name = "ipc widget", .libs = {0}, .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_EXAMPLE_QRCODE
-    {.app = u8g2_qrcode,
-     .name = "u8g2_qrcode",
-     .libs = {1, FURI_LIB{"display_u8g2"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_EXAMPLE_FATFS
-    {.app = fatfs_list,
-     .name = "fatfs_list",
-     .libs = {2, FURI_LIB{"display_u8g2", "input_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_EXAMPLE_DISPLAY
-    {.app = u8g2_example,
-     .name = "u8g2_example",
-     .libs = {1, FURI_LIB{"display_u8g2"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_SPEAKER_DEMO
-    {.app = coreglitch_demo_0, .name = "coreglitch_demo_0", .libs = {0}, .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_SD_TEST
-    {.app = sd_card_test,
-     .name = "sd_card_test",
-     .libs = {2, FURI_LIB{"gui_task", "sd_filesystem"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_MUSIC_PLAYER
-    {.app = music_player,
-     .name = "music player",
-     .libs = {1, FURI_LIB{"gui_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_IBUTTON
-    {.app = app_ibutton,
-     .name = "ibutton",
-     .libs = {1, FURI_LIB{"gui_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_GPIO_DEMO
-    {.app = app_gpio_test,
-     .name = "gpio test",
-     .libs = {1, FURI_LIB{"gui_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef APP_FLOOPPER_BLOOPPER
-    {.app = floopper_bloopper,
-     .name = "Floopper Bloopper",
-     .libs = {1, FURI_LIB{"gui_task"}},
-     .icon = A_Games_14},
-#endif
-
-#ifdef APP_SDNFC
-    {.app = sdnfc, .name = "sdnfc", .libs = {1, FURI_LIB{"gui_task"}}, .icon = A_Plugins_14},
-#endif
-};
-
-// Main menu APP
-const FlipperStartupApp FLIPPER_APPS[] = {
-#ifdef BUILD_CC1101
-    {.app = cc1101_workaround,
-     .name = "Sub-1 GHz",
-     .libs = {1, FURI_LIB{"gui_task"}},
-     .icon = A_Sub1ghz_14},
-#endif
-
-#ifdef BUILD_LF_RFID
-    {.app = lf_rfid_workaround,
-     .name = "125 kHz RFID",
-     .libs = {1, FURI_LIB{"gui_task"}},
-     .icon = A_125khz_14},
-#endif
-
-#ifdef BUILD_IRDA
-    {.app = irda, .name = "Infrared", .libs = {1, FURI_LIB{"gui_task"}}, .icon = A_Infrared_14},
-#endif
-
-#ifdef BUILD_IBUTTON
-    {.app = app_ibutton,
-     .name = "iButton",
-     .libs = {1, FURI_LIB{"gui_task"}},
-     .icon = A_iButton_14},
-#endif
-
-#ifdef BUILD_GPIO_DEMO
-    {.app = app_gpio_test, .name = "GPIO", .libs = {1, FURI_LIB{"gui_task"}}, .icon = A_GPIO_14},
-#endif
-};
-
-// Plugin menu
-const FlipperStartupApp FLIPPER_PLUGINS[] = {
-#ifdef BUILD_EXAMPLE_BLINK
-    {.app = application_blink,
-     .name = "blink",
-     .libs = {1, FURI_LIB{"input_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef BUILD_EXAMPLE_INPUT_DUMP
-    {.app = application_input_dump,
-     .name = "input dump",
-     .libs = {1, FURI_LIB{"input_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef BUILD_SPEAKER_DEMO
-    {.app = coreglitch_demo_0, .name = "coreglitch_demo_0", .libs = {0}, .icon = A_Plugins_14},
-#endif
-
-#ifdef BUILD_SD_TEST
-    {.app = sd_card_test,
-     .name = "sd_card_test",
-     .libs = {2, FURI_LIB{"gui_task", "sd_filesystem"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef BUILD_VIBRO_DEMO
-    {.app = application_vibro,
-     .name = "application_vibro",
-     .libs = {1, FURI_LIB{"input_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef BUILD_MUSIC_PLAYER
-    {.app = music_player,
-     .name = "music player",
-     .libs = {1, FURI_LIB{"gui_task"}},
-     .icon = A_Plugins_14},
-#endif
-
-#ifdef BUILD_FLOOPPER_BLOOPPER
-    {.app = floopper_bloopper,
-     .name = "Floopper Bloopper",
-     .libs = {1, FURI_LIB{"gui_task"}},
-     .icon = A_Games_14},
-#endif
-
-#ifdef BUILD_SDNFC
-    {.app = sdnfc, .name = "sdnfc", .libs = {1, FURI_LIB{"gui_task"}}, .icon = A_Plugins_14},
-#endif
-};
+extern const FuriApplication FLIPPER_PLUGINS[];
+size_t FLIPPER_PLUGINS_size();

+ 1 - 0
applications/applications.mk

@@ -2,6 +2,7 @@ APP_DIR		= $(PROJECT_ROOT)/applications
 LIB_DIR 	= $(PROJECT_ROOT)/lib
 
 CFLAGS		+= -I$(APP_DIR)
+C_SOURCES	+= $(APP_DIR)/applications.c
 
 # Use APP_* for autostart app
 # Use BUILD_* for add app to build

+ 9 - 14
applications/backlight-control/backlight-control.c

@@ -1,11 +1,12 @@
-#include "flipper_v2.h"
+#include <furi.h>
+
+#define BACKLIGHT_TIME 10000
+#define BACKLIGHT_FLAG_ACTIVITY 0x00000001U
 
 static void event_cb(const void* value, void* ctx) {
-    xSemaphoreGive((SemaphoreHandle_t*)ctx);
+    osThreadFlagsSet((osThreadId_t)ctx, BACKLIGHT_FLAG_ACTIVITY);
 }
 
-const uint32_t BACKLIGHT_TIME = 10000;
-
 void backlight_control(void* p) {
     // TODO open record
     const GpioPin* backlight_record = &backlight_gpio;
@@ -14,20 +15,14 @@ void backlight_control(void* p) {
     gpio_init(backlight_record, GpioModeOutputPushPull);
     gpio_write(backlight_record, true);
 
-    StaticSemaphore_t event_descriptor;
-    SemaphoreHandle_t update = xSemaphoreCreateCountingStatic(255, 0, &event_descriptor);
-
     // open record
-    PubSub* event_record = furi_open("input_events");
-    furi_check(event_record);
-    subscribe_pubsub(event_record, event_cb, (void*)update);
-
-    // we ready to work
-    furiac_ready();
+    PubSub* event_record = furi_record_open("input_events");
+    subscribe_pubsub(event_record, event_cb, (void*)osThreadGetId());
 
     while(1) {
         // wait for event
-        if(xSemaphoreTake(update, BACKLIGHT_TIME) == pdTRUE) {
+        if(osThreadFlagsWait(BACKLIGHT_FLAG_ACTIVITY, osFlagsWaitAny, BACKLIGHT_TIME) ==
+           BACKLIGHT_FLAG_ACTIVITY) {
             gpio_write(backlight_record, true);
         } else {
             gpio_write(backlight_record, false);

+ 9 - 18
applications/bt/bt.c

@@ -2,16 +2,23 @@
 
 Bt* bt_alloc() {
     Bt* bt = furi_alloc(sizeof(Bt));
-    bt->cli = furi_open("cli");
+
+    bt->cli = furi_record_open("cli");
+    cli_add_command(bt->cli, "bt_info", bt_cli_info, bt);
+    bt->gui = furi_record_open("gui");
+    bt->menu = furi_record_open("menu");
 
     bt->statusbar_icon = assets_icons_get(I_Bluetooth_5x8);
     bt->statusbar_widget = widget_alloc();
     widget_set_width(bt->statusbar_widget, icon_get_width(bt->statusbar_icon));
     widget_draw_callback_set(bt->statusbar_widget, bt_draw_statusbar_callback, bt);
     widget_enabled_set(bt->statusbar_widget, false);
+    gui_add_widget(bt->gui, bt->statusbar_widget, GuiLayerStatusBarLeft);
 
     bt->menu_icon = assets_icons_get(A_Bluetooth_14);
     bt->menu_item = menu_item_alloc_menu("Bluetooth", bt->menu_icon);
+    with_value_mutex(
+        bt->menu, (Menu * menu) { menu_item_add(menu, bt->menu_item); });
 
     return bt;
 }
@@ -33,23 +40,7 @@ void bt_cli_info(string_t args, void* context) {
 void bt_task() {
     Bt* bt = bt_alloc();
 
-    if(bt->cli) {
-        cli_add_command(bt->cli, "bt_info", bt_cli_info, bt);
-    }
-
-    // TODO: add ValueMutex(bt) to "bt" record
-    if(!furi_create("bt", bt)) {
-        printf("[bt_task] unable to create bt record\n");
-        furiac_exit(NULL);
-    }
-
-    Gui* gui = furi_open("gui");
-    gui_add_widget(gui, bt->statusbar_widget, GuiLayerStatusBarLeft);
-
-    with_value_mutex(
-        furi_open("menu"), (Menu * menu) { menu_item_add(menu, bt->menu_item); });
-
-    furiac_ready();
+    furi_record_create("bt", bt);
 
     api_hal_bt_init();
 

+ 8 - 3
applications/bt/bt_i.h

@@ -2,10 +2,9 @@
 
 #include "bt.h"
 
-#include <cli/cli.h>
+#include <furi.h>
 
-#include <flipper.h>
-#include <flipper_v2.h>
+#include <cli/cli.h>
 
 #include <gui/gui.h>
 #include <gui/widget.h>
@@ -15,6 +14,8 @@
 
 typedef struct {
     Cli* cli;
+    Gui* gui;
+    ValueMutex* menu;
     // Status bar
     Icon* statusbar_icon;
     Widget* statusbar_widget;
@@ -26,3 +27,7 @@ typedef struct {
 Bt* bt_alloc();
 
 void bt_draw_statusbar_callback(Canvas* canvas, void* context);
+
+void bt_cli_info(string_t args, void* context);
+
+void bt_draw_statusbar_callback(Canvas* canvas, void* context);

+ 6 - 5
applications/cc1101-workaround/cc1101-workaround.cpp

@@ -1,6 +1,7 @@
-#include "flipper.h"
-
-#include "cc1101-workaround/cc1101.h"
+#include "cc1101.h"
+#include <furi.h>
+#include <gui/gui.h>
+#include <input/input.h>
 
 extern "C" void cli_print(const char* str);
 
@@ -335,7 +336,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
 }
 
 static void input_callback(InputEvent* input_event, void* ctx) {
-    osMessageQueueId_t event_queue = (QueueHandle_t)ctx;
+    osMessageQueueId_t event_queue = ctx;
 
     AppEvent event;
     event.type = EventTypeKey;
@@ -370,7 +371,7 @@ extern "C" void cc1101_workaround(void* p) {
     widget_input_callback_set(widget, input_callback, event_queue);
 
     // Open GUI and register widget
-    Gui* gui = (Gui*)furi_open("gui");
+    Gui* gui = (Gui*)furi_record_open("gui");
     if(gui == NULL) {
         printf("[cc1101] gui is not available\n");
         furiac_exit(NULL);

+ 1 - 1
applications/cc1101-workaround/cc1101.cpp

@@ -1,4 +1,4 @@
-#include "flipper_v2.h"
+#include <furi.h>
 #include "cc1101-workaround/cc1101.h"
 #include "spi.h"
 #include <math.h>

+ 1 - 1
applications/cc1101-workaround/cc1101.h

@@ -1,6 +1,6 @@
 #pragma once
 
-#include "flipper_v2.h"
+#include <furi.h>
 
 #define F_OSC 26e6
 

+ 1 - 8
applications/cli/cli.c

@@ -1,8 +1,6 @@
 #include "cli_i.h"
 #include "cli_commands.h"
 
-#include <api-hal-vcp.h>
-
 Cli* cli_alloc() {
     Cli* cli = furi_alloc(sizeof(Cli));
     CliCommandDict_init(cli->commands);
@@ -175,12 +173,7 @@ void cli_task(void* p) {
     // Init basic cli commands
     cli_commands_init(cli);
 
-    if(!furi_create("cli", cli)) {
-        printf("[cli_task] cannot create the cli record\n");
-        furiac_exit(NULL);
-    }
-
-    furiac_ready();
+    furi_record_create("cli", cli);
 
     while(1) {
         cli_process_input(cli);

+ 1 - 2
applications/cli/cli_i.h

@@ -2,8 +2,7 @@
 
 #include "cli.h"
 
-#include <flipper.h>
-#include <flipper_v2.h>
+#include <furi.h>
 
 #include <m-dict.h>
 

+ 2 - 4
applications/coreglitch_demo_0/coreglitch_demo_0.c

@@ -1,12 +1,10 @@
-#include "flipper.h"
+#include <furi.h>
 #include "u8g2/u8g2.h"
 
 extern TIM_HandleTypeDef SPEAKER_TIM;
 
 void coreglitch_demo_0(void* p) {
-    FuriRecordSubscriber* log = get_default_log();
-
-    fuprintf(log, "coreglitch demo!\n");
+    printf("coreglitch demo!\n");
 
     float notes[] = {
         0.0,

+ 0 - 195
applications/display-u8g2/display-u8g2.c

@@ -1,195 +0,0 @@
-#include "u8g2/u8g2.h"
-#include "flipper.h"
-#include "main.h"
-
-extern SPI_HandleTypeDef SPI_D;
-
-// TODO: fix log
-#ifdef DEBUG
-#undef DEBUG
-#endif
-
-// TODO rewrite u8g2 to pass thread-local context in this handlers
-
-static uint8_t
-u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) {
-    switch(msg) {
-    //Initialize SPI peripheral
-    case U8X8_MSG_GPIO_AND_DELAY_INIT:
-        /* HAL initialization contains all what we need so we can skip this part. */
-        break;
-
-    //Function which implements a delay, arg_int contains the amount of ms
-    case U8X8_MSG_DELAY_MILLI:
-        osDelay(arg_int);
-        break;
-
-    //Function which delays 10us
-    case U8X8_MSG_DELAY_10MICRO:
-        delay_us(10);
-        break;
-
-    //Function which delays 100ns
-    case U8X8_MSG_DELAY_100NANO:
-        asm("nop");
-        break;
-
-    // Function to define the logic level of the RESET line
-    case U8X8_MSG_GPIO_RESET:
-#ifdef DEBUG
-        fuprintf(log, "[u8g2] rst %d\n", arg_int);
-#endif
-
-        // TODO change it to FuriRecord pin
-        HAL_GPIO_WritePin(
-            DISPLAY_RST_GPIO_Port, DISPLAY_RST_Pin, arg_int ? GPIO_PIN_SET : GPIO_PIN_RESET);
-        break;
-
-    default:
-#ifdef DEBUG
-        fufuprintf(log, "[u8g2] unknown io %d\n", msg);
-#endif
-
-        return 0; //A message was received which is not implemented, return 0 to indicate an error
-    }
-
-    return 1; // command processed successfully.
-}
-
-static uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_ptr) {
-    switch(msg) {
-    case U8X8_MSG_BYTE_SEND:
-#ifdef DEBUG
-        fuprintf(log, "[u8g2] send %d bytes %02X\n", arg_int, ((uint8_t*)arg_ptr)[0]);
-#endif
-
-        // TODO change it to FuriRecord SPI
-        HAL_SPI_Transmit(&SPI_D, (uint8_t*)arg_ptr, arg_int, 10000);
-        break;
-
-    case U8X8_MSG_BYTE_SET_DC:
-#ifdef DEBUG
-        fuprintf(log, "[u8g2] dc %d\n", arg_int);
-#endif
-
-        // TODO change it to FuriRecord pin
-        HAL_GPIO_WritePin(
-            DISPLAY_DI_GPIO_Port, DISPLAY_DI_Pin, arg_int ? GPIO_PIN_SET : GPIO_PIN_RESET);
-        break;
-
-    case U8X8_MSG_BYTE_INIT:
-#ifdef DEBUG
-        fuprintf(log, "[u8g2] init\n");
-#endif
-
-        // TODO change it to FuriRecord pin
-        HAL_GPIO_WritePin(DISPLAY_CS_GPIO_Port, DISPLAY_CS_Pin, GPIO_PIN_RESET);
-        break;
-
-    case U8X8_MSG_BYTE_START_TRANSFER:
-#ifdef DEBUG
-        fuprintf(log, "[u8g2] start\n");
-#endif
-
-        // TODO change it to FuriRecord pin
-        HAL_GPIO_WritePin(DISPLAY_CS_GPIO_Port, DISPLAY_CS_Pin, GPIO_PIN_RESET);
-        asm("nop");
-        break;
-
-    case U8X8_MSG_BYTE_END_TRANSFER:
-#ifdef DEBUG
-        fuprintf(log, "[u8g2] end\n");
-#endif
-
-        asm("nop");
-        // TODO change it to FuriRecord pin
-        HAL_GPIO_WritePin(DISPLAY_CS_GPIO_Port, DISPLAY_CS_Pin, GPIO_PIN_SET);
-        break;
-
-    default:
-#ifdef DEBUG
-        fuprintf(log, "[u8g2] unknown xfer %d\n", msg);
-#endif
-
-        return 0;
-    }
-
-    return 1;
-}
-
-typedef struct {
-    SemaphoreHandle_t update; // queue to pass events from callback to app thread
-    FuriRecordSubscriber* log; // app logger
-} DisplayCtx;
-
-static void handle_fb_change(const void* fb, size_t fb_size, void* raw_ctx) {
-    DisplayCtx* ctx = (DisplayCtx*)raw_ctx; // make right type
-
-    // fuprintf(ctx->log, "[display_u8g2] change fb\n");
-
-    // send update to app thread
-    xSemaphoreGive(ctx->update);
-}
-
-void display_u8g2(void* p) {
-    FuriRecordSubscriber* log = get_default_log();
-
-    // TODO we need different app to contol backlight
-    HAL_GPIO_WritePin(DISPLAY_BACKLIGHT_GPIO_Port, DISPLAY_BACKLIGHT_Pin, GPIO_PIN_SET);
-
-    u8g2_t _u8g2;
-    u8g2_Setup_st7565_erc12864_alt_f(
-        &_u8g2, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32);
-    u8g2_InitDisplay(
-        &_u8g2); // send init sequence to the display, display is in sleep mode after this
-    u8g2_SetContrast(&_u8g2, 36);
-
-    if(!furi_create_deprecated("u8g2_fb", (void*)&_u8g2, sizeof(_u8g2))) {
-        fuprintf(log, "[display_u8g2] cannot create fb record\n");
-        furiac_exit(NULL);
-    }
-
-    StaticSemaphore_t event_descriptor;
-    // create stack-based counting semaphore
-    SemaphoreHandle_t update = xSemaphoreCreateCountingStatic(255, 0, &event_descriptor);
-
-    if(update == NULL) {
-        fuprintf(log, "[display_u8g2] cannot create update semaphore\n");
-        furiac_exit(NULL);
-    }
-
-    // save log and event queue in context structure
-    DisplayCtx ctx = {.update = update, .log = log};
-
-    // subscribe to record. ctx will be passed to handle_fb_change
-    FuriRecordSubscriber* fb_record =
-        furi_open_deprecated("u8g2_fb", false, false, handle_fb_change, NULL, &ctx);
-
-    if(fb_record == NULL) {
-        fuprintf(log, "[display] cannot open fb record\n");
-        furiac_exit(NULL);
-    }
-
-    u8g2_t* u8g2 = (u8g2_t*)furi_take(fb_record);
-    u8g2_SetPowerSave(u8g2, 0); // wake up display
-    u8g2_SendBuffer(u8g2);
-    furi_give(fb_record);
-
-    // we ready to work
-    furiac_ready();
-
-    while(1) {
-        // wait for event
-        if(xSemaphoreTake(update, 10000) == pdTRUE) {
-            HAL_GPIO_WritePin(DISPLAY_BACKLIGHT_GPIO_Port, DISPLAY_BACKLIGHT_Pin, GPIO_PIN_SET);
-
-            u8g2_t* u8g2 = (u8g2_t*)furi_take(fb_record);
-            u8g2_SetPowerSave(u8g2, 0); // wake up display
-            u8g2_SendBuffer(u8g2);
-            furi_give(fb_record);
-        } else {
-            // TODO we need different app to contol backlight
-            HAL_GPIO_WritePin(DISPLAY_BACKLIGHT_GPIO_Port, DISPLAY_BACKLIGHT_Pin, GPIO_PIN_RESET);
-        }
-    }
-}

+ 3 - 9
applications/dolphin/dolphin.c

@@ -67,8 +67,7 @@ Dolphin* dolphin_alloc() {
     // State
     dolphin->state = dolphin_state_alloc();
     // Menu
-    dolphin->menu_vm = furi_open("menu");
-    furi_check(dolphin->menu_vm);
+    dolphin->menu_vm = furi_record_open("menu");
     // GUI
     dolphin->idle_view_dispatcher = view_dispatcher_alloc();
     // First start View
@@ -125,7 +124,7 @@ void dolphin_deed(Dolphin* dolphin, DolphinDeed deed) {
 void dolphin_task() {
     Dolphin* dolphin = dolphin_alloc();
 
-    Gui* gui = furi_open("gui");
+    Gui* gui = furi_record_open("gui");
     view_dispatcher_attach_to_gui(dolphin->idle_view_dispatcher, gui, ViewDispatcherTypeWindow);
     if(dolphin_state_load(dolphin->state)) {
         view_dispatcher_switch_to_view(dolphin->idle_view_dispatcher, DolphinViewIdleMain);
@@ -138,12 +137,7 @@ void dolphin_task() {
             model->butthurt = dolphin_state_get_butthurt(dolphin->state);
         });
 
-    if(!furi_create("dolphin", dolphin)) {
-        printf("[dolphin_task] cannot create the dolphin record\n");
-        furiac_exit(NULL);
-    }
-
-    furiac_ready();
+    furi_record_create("dolphin", dolphin);
 
     DolphinEvent event;
     while(1) {

+ 1 - 1
applications/dolphin/dolphin_i.h

@@ -4,7 +4,7 @@
 #include "dolphin_state.h"
 #include "dolphin_views.h"
 
-#include <flipper_v2.h>
+#include <furi.h>
 
 #include <gui/gui.h>
 #include <gui/view_dispatcher.h>

+ 1 - 2
applications/dolphin/dolphin_state.c

@@ -1,6 +1,5 @@
 #include "dolphin_state.h"
-#include <api-hal-flash.h>
-#include <flipper_v2.h>
+#include <furi.h>
 
 typedef struct {
     uint8_t magic;

+ 2 - 1
applications/dolphin/dolphin_views.h

@@ -3,7 +3,8 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include <gui/canvas.h>
-#include <flipper_v2.h>
+#include <input/input.h>
+#include <furi.h>
 
 // Idle scree
 typedef enum {

+ 1 - 1
applications/examples/blink.c

@@ -1,4 +1,4 @@
-#include "flipper_v2.h"
+#include <furi.h>
 
 void rgb_set(
     bool r,

+ 0 - 155
applications/examples/fatfs_list.c

@@ -1,155 +0,0 @@
-#include "u8g2/u8g2.h"
-#include "fatfs/ff.h"
-#include "flipper_v2.h"
-#include <stdio.h>
-
-extern uint8_t BSP_SD_Init();
-
-// TODO currently we have small stack, so it will be static
-FuriRecordSubscriber* furi_log;
-#define STR_BUFFER_SIZE 128
-char str_buffer[STR_BUFFER_SIZE];
-uint8_t line_current = 0;
-uint16_t line_position = 0;
-
-// TODO this should be in the target driver
-FATFS SD_FatFs;
-char SD_Path[4];
-
-typedef enum {
-    EventTypeStart,
-    EventTypeKey,
-} AppEventType;
-
-typedef struct {
-    union {
-        InputEvent input;
-    } value;
-    AppEventType type;
-} AppEvent;
-
-static void event_cb(const void* value, void* ctx) {
-    QueueHandle_t event_queue = (QueueHandle_t)ctx;
-
-    AppEvent event;
-    event.type = EventTypeKey;
-    event.value.input = *(InputEvent*)value;
-    xQueueSend(event_queue, (void*)&event, 0);
-}
-
-void fatfs_list(void* p) {
-    const uint8_t line_size = 10;
-    const uint8_t lines_on_display = 6;
-
-    uint8_t bsp_result;
-    FRESULT result;
-    DIR dir;
-    FILINFO fno;
-    AppEvent event;
-
-    QueueHandle_t event_queue = xQueueCreate(2, sizeof(AppEvent));
-
-    furi_log = get_default_log();
-    fuprintf(furi_log, "[fatfs_list] app start\n");
-    fuprintf(furi_log, "[fatfs_list] wait for sd insert\n");
-
-    while(!hal_gpio_read_sd_detect()) {
-        delay(100);
-    }
-
-    fuprintf(furi_log, "[fatfs_list] sd inserted\n");
-
-    FuriRecordSubscriber* fb_record =
-        furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL);
-    if(fb_record == NULL) {
-        fuprintf(furi_log, "[fatfs_list] cannot create fb record\n");
-        furiac_exit(NULL);
-    }
-
-    PubSub* event_record = furi_open("input_events");
-    if(event_record == NULL) {
-        fuprintf(furi_log, "[fatfs_list] cannot open input_events record\n");
-        furiac_exit(NULL);
-    }
-    PubSubItem* subscription = subscribe_pubsub(event_record, event_cb, event_queue);
-    if(subscription == NULL) {
-        fuprintf(furi_log, "[fatfs_list] cannot register input_events callback\n");
-        furiac_exit(NULL);
-    }
-
-    bsp_result = BSP_SD_Init();
-
-    if(bsp_result != 0) {
-        fuprintf(furi_log, "[fatfs_list] SD card init error\n");
-        furiac_exit(NULL);
-    }
-
-    result = f_mount(&SD_FatFs, (TCHAR const*)SD_Path, 1);
-
-    if(result != FR_OK) {
-        fuprintf(furi_log, "[fatfs_list] SD card mount error\n");
-        furiac_exit(NULL);
-    }
-
-    // ok, now we can work with sd card
-
-    // send start event
-    event.type = EventTypeStart;
-    xQueueSend(event_queue, (void*)&event, 0);
-
-    while(1) {
-        if(xQueueReceive(event_queue, (void*)&event, portMAX_DELAY)) {
-            // process buttons event
-            if(event.type == EventTypeKey) {
-                // button pressed
-                if(event.value.input.state == true) {
-                    if(event.value.input.input == InputUp && line_position > 0) {
-                        line_position--;
-                    }
-                    if(event.value.input.input == InputDown) {
-                        line_position++;
-                    }
-                }
-            }
-
-            line_current = 1;
-
-            // open root dir
-            result = f_opendir(&dir, "");
-
-            while(1) {
-                // read a directory item
-                result = f_readdir(&dir, &fno);
-
-                if(result != FR_OK) {
-                    // cannot read dir
-                    break;
-                }
-
-                if(fno.fname[0] == 0) {
-                    // Break on end of dir
-                    break;
-                }
-
-                // draw files on display
-                if(line_current > line_position &&
-                   line_current <= (line_position + lines_on_display)) {
-                    if(fno.fattrib & AM_DIR) {
-                        snprintf(str_buffer, STR_BUFFER_SIZE, "DIR %s\n", fno.fname);
-                    } else {
-                        snprintf(str_buffer, STR_BUFFER_SIZE, "FIL %s\n", fno.fname);
-                    }
-                    fuprintf(furi_log, str_buffer);
-                }
-
-                line_current++;
-            }
-
-            result = f_closedir(&dir);
-
-            furi_commit(fb_record);
-        }
-    }
-
-    furiac_exit(NULL);
-}

+ 4 - 5
applications/examples/input_dump.c

@@ -1,5 +1,6 @@
-#include "flipper_v2.h"
+#include <furi.h>
 #include <stdio.h>
+#include <input/input.h>
 
 typedef union {
     unsigned int packed;
@@ -21,12 +22,10 @@ static void event_cb(const void* value, void* ctx) {
 
 void application_input_dump(void* p) {
     // open record
-    ValueManager* state_record = furi_open("input_state");
-    furi_check(state_record);
+    ValueManager* state_record = furi_record_open("input_state");
     subscribe_pubsub(&state_record->pubsub, state_cb, NULL);
 
-    PubSub* event_record = furi_open("input_events");
-    furi_check(event_record);
+    PubSub* event_record = furi_record_open("input_events");
     subscribe_pubsub(event_record, event_cb, NULL);
 
     printf("Example app [input dump]\n");

+ 0 - 155
applications/examples/ipc.c

@@ -1,155 +0,0 @@
-#include "flipper.h"
-#include <string.h>
-
-#define FB_WIDTH 10
-#define FB_HEIGHT 3
-#define FB_SIZE (FB_WIDTH * FB_HEIGHT)
-
-// context structure used for pass some object from app thread to callback
-typedef struct {
-    SemaphoreHandle_t events; // queue to pass events from callback to app thread
-    FuriRecordSubscriber* log; // app logger
-} IpcCtx;
-
-static void handle_fb_change(const void* fb, size_t fb_size, void* raw_ctx) {
-    IpcCtx* ctx = (IpcCtx*)raw_ctx; // make right type
-
-    fuprintf(ctx->log, "[cb] framebuffer updated\n");
-
-    // send event to app thread
-    xSemaphoreGive(ctx->events);
-
-    // Attention! Please, do not make blocking operation like IO and waits inside callback
-    // Remember that callback execute in calling thread/context
-}
-
-static void print_fb(char* fb, FuriRecordSubscriber* log) {
-    if(fb == NULL) return;
-
-    /* draw framebuffer like this:
-    +==========+
-    |          |
-    |          |
-    |          |
-    +==========+
-    */
-
-    char row_buffer[FB_WIDTH + 1];
-    row_buffer[FB_WIDTH] = '\0';
-
-    // FB layout is hardcoded here
-    fuprintf(log, "+==========+\n");
-    for(uint8_t i = 0; i < FB_HEIGHT; i++) {
-        strncpy(row_buffer, &fb[FB_WIDTH * i], FB_WIDTH);
-        fuprintf(log, "|%s|\n", row_buffer);
-    }
-    fuprintf(log, "+==========+\n");
-}
-
-void application_ipc_display(void* p) {
-    // get logger
-    FuriRecordSubscriber* log = get_default_log();
-
-    // create ASCII "framebuffer"
-    // FB_WIDTH x FB_HEIGHT char buffer
-    char _framebuffer[FB_SIZE];
-
-    // init framebuffer by spaces
-    for(size_t i = 0; i < FB_SIZE; i++) {
-        _framebuffer[i] = ' ';
-    }
-
-    // create record
-    if(!furi_create_deprecated("test_fb", (void*)_framebuffer, FB_SIZE)) {
-        fuprintf(log, "[display] cannot create fb record\n");
-        furiac_exit(NULL);
-    }
-
-    StaticSemaphore_t event_descriptor;
-    // create stack-based counting semaphore
-    SemaphoreHandle_t events = xSemaphoreCreateCountingStatic(255, 0, &event_descriptor);
-
-    if(events == NULL) {
-        fuprintf(log, "[display] cannot create event semaphore\n");
-        furiac_exit(NULL);
-    }
-
-    // save log and event queue in context structure
-    IpcCtx ctx = {.events = events, .log = log};
-
-    // subscribe to record. ctx will be passed to handle_fb_change
-    FuriRecordSubscriber* fb_record =
-        furi_open_deprecated("test_fb", false, false, handle_fb_change, NULL, &ctx);
-
-    if(fb_record == NULL) {
-        fuprintf(log, "[display] cannot open fb record\n");
-        furiac_exit(NULL);
-    }
-
-#ifdef HW_DISPLAY
-    // on Flipper target -- open screen
-
-    // draw border
-
-#else
-    // on Local target -- print "blank screen"
-    {
-        void* fb = furi_take(fb_record);
-        print_fb((char*)fb, log);
-        furi_give(fb_record);
-    }
-#endif
-
-    while(1) {
-        // wait for event
-        if(xSemaphoreTake(events, portMAX_DELAY) == pdTRUE) {
-            fuprintf(log, "[display] get fb update\n\n");
-
-#ifdef HW_DISPLAY
-// on Flipper target draw the screen
-#else
-            // on local target just print
-            {
-                void* fb = furi_take(fb_record);
-                print_fb((char*)fb, log);
-                furi_give(fb_record);
-            }
-#endif
-        }
-    }
-}
-
-// Widget application
-void application_ipc_widget(void* p) {
-    FuriRecordSubscriber* log = get_default_log();
-
-    // open record
-    FuriRecordSubscriber* fb_record =
-        furi_open_deprecated("test_fb", false, false, NULL, NULL, NULL);
-
-    if(fb_record == NULL) {
-        fuprintf(log, "[widget] cannot create fb record\n");
-        furiac_exit(NULL);
-    }
-
-    uint8_t counter = 0;
-
-    while(1) {
-        delay(120);
-
-        // write some ascii demo here: '#'' symbol run on overall screen
-        char* fb = (char*)furi_take(fb_record);
-
-        if(fb == NULL) furiac_exit(NULL);
-
-        for(size_t i = 0; i < FB_SIZE; i++) {
-            fb[i] = ' ';
-        }
-
-        fb[counter % FB_SIZE] = '#';
-
-        furi_commit(fb_record);
-
-        counter++;
-    }
-}

+ 3 - 3
applications/examples/strobe.c

@@ -1,4 +1,5 @@
-#include "flipper_v2.h"
+#include <furi.h>
+#include <input.h>
 
 static void event_cb(const void* value, void* ctx) {
     const InputEvent* event = value;
@@ -38,8 +39,7 @@ void application_strobe(void* p) {
     ValueMutex delay_mutex;
     init_mutex(&delay_mutex, &delay_time_holder, sizeof(delay_time_holder));
 
-    PubSub* event_record = furi_open("input_events");
-    furi_check(event_record);
+    PubSub* event_record = furi_record_open("input_events");
     subscribe_pubsub(event_record, event_cb, &delay_mutex);
 
     while(1) {

+ 9 - 27
applications/examples/u8g2_example.c

@@ -1,32 +1,14 @@
 #include "u8g2/u8g2.h"
-#include "flipper.h"
+#include <furi.h>
 
 void u8g2_example(void* p) {
-    FuriRecordSubscriber* log = get_default_log();
-
     // open record
-    FuriRecordSubscriber* fb_record =
-        furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL);
-
-    if(fb_record == NULL) {
-        fuprintf(log, "[widget] cannot create fb record\n");
-        furiac_exit(NULL);
-    }
-
-    while(1) {
-        u8g2_t* fb = furi_take(fb_record);
-        if(fb != NULL) {
-            u8g2_SetFont(fb, u8g2_font_6x10_mf);
-            u8g2_SetDrawColor(fb, 1);
-            u8g2_SetFontMode(fb, 1);
-            u8g2_DrawStr(fb, 2, 12, "hello world!");
-        }
-        furi_commit(fb_record);
-
-        if(fb != NULL) {
-            furiac_exit(NULL);
-        }
-
-        delay(1);
-    }
+    u8g2_t* fb = furi_record_open("u8g2_fb");
+    u8g2_SetFont(fb, u8g2_font_6x10_mf);
+    u8g2_SetDrawColor(fb, 1);
+    u8g2_SetFontMode(fb, 1);
+    u8g2_DrawStr(fb, 2, 12, "hello world!");
+    furi_record_close("u8g2_fb");
+
+    furiac_exit(NULL);
 }

+ 7 - 5
applications/examples/u8g2_qrcode.c

@@ -1,6 +1,9 @@
 #include "u8g2/u8g2.h"
 #include "qrcode/qrcode.h"
-#include "flipper.h"
+#include <furi.h>
+
+/*
+TODO: rework with new app api
 
 void u8g2_DrawPixelSize(u8g2_t* u8g2, uint8_t x, uint8_t y, uint8_t size) {
     for(uint8_t px = 0; px < size; px++) {
@@ -11,8 +14,6 @@ void u8g2_DrawPixelSize(u8g2_t* u8g2, uint8_t x, uint8_t y, uint8_t size) {
 }
 
 void u8g2_qrcode(void* p) {
-    FuriRecordSubscriber* log = get_default_log();
-
     // open record
     FuriRecordSubscriber* fb_record =
         furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL);
@@ -36,7 +37,7 @@ void u8g2_qrcode(void* p) {
     qrcode_initText(&qrcode, qrcodeBytes, qr_version, qr_error_correction, "HELLO FLIPPER");
 
     if(fb_record == NULL) {
-        fuprintf(log, "[widget] cannot create fb record\n");
+        printf("[widget] cannot create fb record\n");
         furiac_exit(NULL);
     }
 
@@ -69,4 +70,5 @@ void u8g2_qrcode(void* p) {
 
         delay(1);
     }
-}
+}
+*/

+ 2 - 7
applications/examples/uart_write.c

@@ -1,7 +1,5 @@
-#include "flipper.h"
+#include <furi.h>
 #include <string.h>
-#include "log.h"
-#include "flipper_v2.h"
 
 void application_uart_write(void* p) {
     // Red led for showing progress
@@ -11,12 +9,9 @@ void application_uart_write(void* p) {
 
     gpio_init(led_record, GpioModeOutputOpenDrain);
 
-    // get_default_log open "tty" record
-    FuriRecordSubscriber* log = get_default_log();
-
     // create buffer
     const char test_string[] = "test\n";
-    furi_write(log, test_string, strlen(test_string));
+    printf(test_string);
 
     // for example, create counter and show its value
     uint8_t counter = 0;

+ 3 - 2
applications/examples/vibro.c

@@ -1,4 +1,5 @@
-#include "flipper_v2.h"
+#include <furi.h>
+#include <input/input.h>
 
 typedef struct {
     GpioPin* led;
@@ -24,7 +25,7 @@ void application_vibro(void* p) {
     gpio_write(ctx.vibro, false);
 
     // subscribe on buttons
-    PubSub* event_record = furi_open("input_events");
+    PubSub* event_record = furi_record_open("input_events");
     furi_check(event_record);
     subscribe_pubsub(event_record, button_handler, &ctx);
 

+ 1 - 1
applications/floopper-bloopper

@@ -1 +1 @@
-Subproject commit 25a2cc076c3162aad721e0d92009cfa7b9100c7a
+Subproject commit 621044255a8be4d2c3f342e2b22178a342ccbfe8

+ 5 - 7
applications/gpio-tester/gpio-tester.c

@@ -1,4 +1,6 @@
-#include "flipper_v2.h"
+#include <furi.h>
+#include <gui/gui.h>
+#include <input/input.h>
 
 typedef struct {
     const char* name;
@@ -47,7 +49,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
 }
 
 static void input_callback(InputEvent* input_event, void* ctx) {
-    osMessageQueueId_t event_queue = (QueueHandle_t)ctx;
+    osMessageQueueId_t event_queue = ctx;
 
     AppEvent event;
     event.type = EventTypeKey;
@@ -74,11 +76,7 @@ void app_gpio_test(void* p) {
     widget_input_callback_set(widget, input_callback, event_queue);
 
     // Open GUI and register widget
-    Gui* gui = (Gui*)furi_open("gui");
-    if(gui == NULL) {
-        printf("[gpio-tester] gui is not available\n");
-        furiac_exit(NULL);
-    }
+    Gui* gui = furi_record_open("gui");
     gui_add_widget(gui, widget, GuiLayerFullscreen);
 
     // configure pin

+ 1 - 2
applications/gui/canvas.c

@@ -1,8 +1,7 @@
 #include "canvas_i.h"
 #include "icon_i.h"
 
-#include <flipper.h>
-#include <flipper_v2.h>
+#include <furi.h>
 
 struct Canvas {
     u8g2_t fb;

+ 8 - 0
applications/gui/canvas.h

@@ -5,6 +5,10 @@
 #include <gui/icon.h>
 #include <assets_icons_i.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef enum {
     ColorWhite = 0x00,
     ColorBlack = 0x01,
@@ -91,3 +95,7 @@ void canvas_draw_line(Canvas* canvas, uint8_t x1, uint8_t y1, uint8_t x2, uint8_
  * Draw glyph
  */
 void canvas_draw_glyph(Canvas* canvas, uint8_t x, uint8_t y, uint16_t ch);
+
+#ifdef __cplusplus
+}
+#endif

+ 8 - 0
applications/gui/elements.h

@@ -3,6 +3,10 @@
 #include <stdint.h>
 #include "canvas.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /*
  * Draw scrollbar on canvas.
  * width 3px, height equal to canvas height
@@ -17,3 +21,7 @@ void elements_scrollbar(Canvas* canvas, uint8_t pos, uint8_t total);
  * @param width, height - frame width and height
  */
 void elements_frame(Canvas* canvas, uint8_t x, uint8_t y, uint8_t width, uint8_t height);
+
+#ifdef __cplusplus
+}
+#endif

+ 3 - 8
applications/gui/gui.c

@@ -1,8 +1,7 @@
 #include "gui.h"
 #include "gui_i.h"
 
-#include <flipper.h>
-#include <flipper_v2.h>
+#include <furi.h>
 #include <m-array.h>
 #include <stdio.h>
 
@@ -207,13 +206,9 @@ Gui* gui_alloc() {
 
 void gui_task(void* p) {
     Gui* gui = gui_alloc();
-    // Create FURI record
-    if(!furi_create("gui", gui)) {
-        printf("[gui_task] cannot create the gui record\n");
-        furiac_exit(NULL);
-    }
 
-    furiac_ready();
+    // Create FURI record
+    furi_record_create("gui", gui);
 
     // Forever dispatch
     while(1) {

+ 8 - 0
applications/gui/gui.h

@@ -3,6 +3,10 @@
 #include "widget.h"
 #include "canvas.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 #define GUI_DISPLAY_WIDTH 128
 #define GUI_DISPLAY_HEIGHT 64
 
@@ -40,3 +44,7 @@ void gui_add_widget(Gui* gui, Widget* widget, GuiLayer layer);
  * @remarks thread safe
  */
 void gui_remove_widget(Gui* gui, Widget* widget);
+
+#ifdef __cplusplus
+}
+#endif

+ 2 - 2
applications/gui/gui_event.c

@@ -1,6 +1,6 @@
 #include "gui_event.h"
 
-#include <flipper_v2.h>
+#include <furi.h>
 
 #define GUI_EVENT_MQUEUE_SIZE 8
 
@@ -45,7 +45,7 @@ GuiEvent* gui_event_alloc() {
     // osTimerStart(gui_event->timer, 1024 / 4);
 
     // Input
-    gui_event->input_event_record = furi_open("input_events");
+    gui_event->input_event_record = furi_record_open("input_events");
     furi_check(gui_event->input_event_record != NULL);
     subscribe_pubsub(gui_event->input_event_record, gui_event_input_events_callback, gui_event);
 

+ 8 - 0
applications/gui/gui_event.h

@@ -3,6 +3,10 @@
 #include <stdint.h>
 #include <input/input.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef enum {
     GuiMessageTypeRedraw = 0x00,
     GuiMessageTypeInput = 0x01,
@@ -23,3 +27,7 @@ void gui_event_free(GuiEvent* gui_event);
 void gui_event_messsage_send(GuiEvent* gui_event, GuiMessage* message);
 
 GuiMessage gui_event_message_next(GuiEvent* gui_event);
+
+#ifdef __cplusplus
+}
+#endif

+ 1 - 3
applications/gui/icon.c

@@ -1,8 +1,6 @@
 #include "icon_i.h"
 
-#include <cmsis_os2.h>
-#include <flipper.h>
-#include <flipper_v2.h>
+#include <furi.h>
 
 Icon* icon_alloc(const IconData* data) {
     Icon* icon = furi_alloc(sizeof(Icon));

+ 8 - 0
applications/gui/icon.h

@@ -3,6 +3,10 @@
 #include <stdint.h>
 #include <stdbool.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef struct IconData IconData;
 typedef struct Icon Icon;
 
@@ -41,3 +45,7 @@ void icon_start_animation(Icon* icon);
  * Stop icon animation
  */
 void icon_stop_animation(Icon* icon);
+
+#ifdef __cplusplus
+}
+#endif

+ 9 - 9
applications/gui/u8g2_periphery.c

@@ -1,5 +1,5 @@
 #include "u8g2/u8g2.h"
-#include "flipper.h"
+#include <furi.h>
 #include <main.h>
 
 extern SPI_HandleTypeDef SPI_D;
@@ -34,7 +34,7 @@ uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, vo
     // Function to define the logic level of the RESET line
     case U8X8_MSG_GPIO_RESET:
 #ifdef DEBUG
-        fuprintf(log, "[u8g2] rst %d\n", arg_int);
+        printf("[u8g2] rst %d\n", arg_int);
 #endif
 
         // TODO change it to FuriRecord pin
@@ -44,7 +44,7 @@ uint8_t u8g2_gpio_and_delay_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, vo
 
     default:
 #ifdef DEBUG
-        fufuprintf(log, "[u8g2] unknown io %d\n", msg);
+        printf("[u8g2] unknown io %d\n", msg);
 #endif
 
         return 0; //A message was received which is not implemented, return 0 to indicate an error
@@ -57,7 +57,7 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_
     switch(msg) {
     case U8X8_MSG_BYTE_SEND:
 #ifdef DEBUG
-        fuprintf(log, "[u8g2] send %d bytes %02X\n", arg_int, ((uint8_t*)arg_ptr)[0]);
+        printf("[u8g2] send %d bytes %02X\n", arg_int, ((uint8_t*)arg_ptr)[0]);
 #endif
 
         // TODO change it to FuriRecord SPI
@@ -66,7 +66,7 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_
 
     case U8X8_MSG_BYTE_SET_DC:
 #ifdef DEBUG
-        fuprintf(log, "[u8g2] dc %d\n", arg_int);
+        printf("[u8g2] dc %d\n", arg_int);
 #endif
 
         // TODO change it to FuriRecord pin
@@ -76,7 +76,7 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_
 
     case U8X8_MSG_BYTE_INIT:
 #ifdef DEBUG
-        fuprintf(log, "[u8g2] init\n");
+        printf("[u8g2] init\n");
 #endif
 
         // TODO change it to FuriRecord pin
@@ -85,7 +85,7 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_
 
     case U8X8_MSG_BYTE_START_TRANSFER:
 #ifdef DEBUG
-        fuprintf(log, "[u8g2] start\n");
+        printf("[u8g2] start\n");
 #endif
 
         // TODO: SPI manager
@@ -98,7 +98,7 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_
 
     case U8X8_MSG_BYTE_END_TRANSFER:
 #ifdef DEBUG
-        fuprintf(log, "[u8g2] end\n");
+        printf("[u8g2] end\n");
 #endif
 
         asm("nop");
@@ -112,7 +112,7 @@ uint8_t u8x8_hw_spi_stm32(u8x8_t* u8x8, uint8_t msg, uint8_t arg_int, void* arg_
 
     default:
 #ifdef DEBUG
-        fuprintf(log, "[u8g2] unknown xfer %d\n", msg);
+        printf("[u8g2] unknown xfer %d\n", msg);
 #endif
 
         return 0;

+ 8 - 0
applications/gui/view.h

@@ -3,6 +3,10 @@
 #include <input/input.h>
 #include "canvas.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* Hides drawing widget */
 #define VIEW_NONE 0xFFFFFFFF
 /* Ignore navigation event */
@@ -127,3 +131,7 @@ void view_commit_model(View* view);
         ({ void __fn__ function_body __fn__; })(p); \
         view_commit_model(view);                    \
     }
+
+#ifdef __cplusplus
+}
+#endif

+ 8 - 0
applications/gui/view_dispatcher.h

@@ -3,6 +3,10 @@
 #include "view.h"
 #include "gui.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /* ViewDispatcher widget placement */
 typedef enum {
     ViewDispatcherTypeNone, /* Special layer for internal use only */
@@ -43,3 +47,7 @@ void view_dispatcher_attach_to_gui(
     ViewDispatcher* view_dispatcher,
     Gui* gui,
     ViewDispatcherType type);
+
+#ifdef __cplusplus
+}
+#endif

+ 1 - 1
applications/gui/view_dispatcher_i.h

@@ -2,7 +2,7 @@
 
 #include "view_dispatcher.h"
 #include "view_i.h"
-#include <flipper_v2.h>
+#include <furi.h>
 #include <m-dict.h>
 
 DICT_DEF2(ViewDict, uint32_t, M_DEFAULT_OPLIST, View*, M_PTR_OPLIST)

+ 1 - 1
applications/gui/view_i.h

@@ -2,7 +2,7 @@
 
 #include "view.h"
 #include "view_dispatcher_i.h"
-#include <flipper_v2.h>
+#include <furi.h>
 
 typedef struct {
     void* data;

+ 1 - 5
applications/gui/widget.c

@@ -1,8 +1,6 @@
 #include "widget_i.h"
 
-#include <cmsis_os.h>
-#include <flipper.h>
-#include <flipper_v2.h>
+#include <furi.h>
 
 #include "gui.h"
 #include "gui_i.h"
@@ -73,8 +71,6 @@ void widget_update(Widget* widget) {
 
 void widget_gui_set(Widget* widget, Gui* gui) {
     furi_assert(widget);
-    furi_assert(gui);
-
     widget->gui = gui;
 }
 

+ 8 - 0
applications/gui/widget.h

@@ -3,6 +3,10 @@
 #include <input/input.h>
 #include "canvas.h"
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef struct Widget Widget;
 
 /*
@@ -65,3 +69,7 @@ void widget_input_callback_set(Widget* widget, WidgetInputCallback callback, voi
  * Rendering will happen later after GUI system process signal.
  */
 void widget_update(Widget* widget);
+
+#ifdef __cplusplus
+}
+#endif

+ 1 - 1
applications/ibutton/ibutton.cpp

@@ -32,7 +32,7 @@ void AppiButton::run() {
                     printf("[ibutton] bye!\n");
                     // TODO remove all widgets create by app
                     widget_enabled_set(widget, false);
-                    furiac_exit(NULL);
+                    osThreadExit();
                 }
 
                 if(event.value.input.state && event.value.input.input == InputLeft) {

+ 3 - 11
applications/input/input.c

@@ -1,6 +1,6 @@
 #include <input/input.h>
 #include <stdio.h>
-#include <flipper_v2.h>
+#include <furi.h>
 
 #ifdef APP_NFC
 void nfc_isr(void);
@@ -35,18 +35,10 @@ void input_task(void* p) {
         furiac_exit(NULL);
     }
 
-    if(!furi_create("input_state", &input_state_record)) {
-        printf("[input_task] cannot create the input_state record\n");
-        furiac_exit(NULL);
-    }
-
-    if(!furi_create("input_events", &input_events_record)) {
-        printf("[input_task] cannot create the input_events record\n");
-        furiac_exit(NULL);
-    }
+    furi_record_create("input_state", &input_state_record);
+    furi_record_create("input_events", &input_events_record);
 
     // we ready to work
-    furiac_ready();
     initialized = true;
 
     // Force state update

+ 1 - 2
applications/irda/irda-decoder/irda-decoder.h

@@ -1,6 +1,5 @@
 #pragma once
-#include "flipper.h"
-#include "flipper_v2.h"
+#include <furi.h>
 #include "irda-decoder-nec.h"
 #include "irda-decoder-types.h"
 

+ 6 - 8
applications/irda/irda.c

@@ -1,5 +1,7 @@
-#include "flipper.h"
-#include "flipper_v2.h"
+#include <furi.h>
+#include <gui/gui.h>
+#include <input/input.h>
+
 #include "irda_nec.h"
 #include "irda_samsung.h"
 #include "irda_protocols.h"
@@ -185,7 +187,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
 }
 
 static void input_callback(InputEvent* input_event, void* ctx) {
-    osMessageQueueId_t event_queue = (QueueHandle_t)ctx;
+    osMessageQueueId_t event_queue = ctx;
 
     AppEvent event;
     event.type = EventTypeKey;
@@ -271,11 +273,7 @@ void irda(void* p) {
     widget_input_callback_set(widget, input_callback, event_queue);
 
     // Open GUI and register widget
-    Gui* gui = (Gui*)furi_open("gui");
-    if(gui == NULL) {
-        printf("gui is not available\n");
-        furiac_exit(NULL);
-    }
+    Gui* gui = furi_record_open("gui");
     gui_add_widget(gui, widget, GuiLayerFullscreen);
 
     // Red LED

+ 1 - 1
applications/irda/irda_nec.c

@@ -1,4 +1,4 @@
-#include "flipper.h"
+#include <furi.h>
 #include "irda_nec.h"
 #include "irda_protocols.h"
 

+ 1 - 1
applications/irda/irda_nec.h

@@ -1,4 +1,4 @@
 #pragma once
-#include "flipper.h"
+#include <furi.h>
 
 void ir_nec_send(uint16_t addr, uint8_t data);

+ 1 - 1
applications/irda/irda_samsung.c

@@ -1,4 +1,4 @@
-#include "flipper.h"
+#include <furi.h>
 #include "irda_samsung.h"
 #include "irda_protocols.h"
 

+ 1 - 1
applications/irda/irda_samsung.h

@@ -1,4 +1,4 @@
 #pragma once
-#include "flipper.h"
+#include <furi.h>
 
 void ir_samsung_send(uint16_t addr, uint16_t data);

+ 1 - 1
applications/lf-rfid/em4100.c

@@ -1,4 +1,4 @@
-#include "flipper_v2.h"
+#include <furi.h>
 
 void prepare_data(uint32_t ID, uint32_t VENDOR, uint8_t* data) {
     uint8_t value[10];

+ 5 - 8
applications/lf-rfid/lf-rfid.c

@@ -1,4 +1,5 @@
-#include "flipper_v2.h"
+#include <furi.h>
+#include <gui/gui.h>
 
 typedef enum { EventTypeTick, EventTypeKey, EventTypeRx } EventType;
 
@@ -45,7 +46,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
 }
 
 static void input_callback(InputEvent* input_event, void* ctx) {
-    osMessageQueueId_t event_queue = (QueueHandle_t)ctx;
+    osMessageQueueId_t event_queue = ctx;
 
     AppEvent event;
     event.type = EventTypeKey;
@@ -67,7 +68,7 @@ void comparator_trigger_callback(void* hcomp, void* comp_ctx) {
 
     // gpio_write(&debug_0, true);
 
-    osMessageQueueId_t event_queue = (QueueHandle_t)comp_ctx;
+    osMessageQueueId_t event_queue = comp_ctx;
 
     AppEvent event;
     event.type = EventTypeRx;
@@ -202,11 +203,7 @@ void lf_rfid_workaround(void* p) {
     widget_input_callback_set(widget, input_callback, event_queue);
 
     // Open GUI and register widget
-    Gui* gui = (Gui*)furi_open("gui");
-    if(gui == NULL) {
-        printf("gui is not available\n");
-        furiac_exit(NULL);
-    }
+    Gui* gui = furi_record_open("gui");
     gui_add_widget(gui, widget, GuiLayerFullscreen);
 
     AppEvent event;

+ 3 - 10
applications/menu/menu.c

@@ -1,9 +1,8 @@
 #include "menu.h"
-#include <cmsis_os.h>
 #include <stdio.h>
 #include <stdbool.h>
 
-#include <flipper_v2.h>
+#include <furi.h>
 #include <gui/gui.h>
 #include <gui/elements.h>
 
@@ -42,8 +41,7 @@ ValueMutex* menu_init() {
     menu->widget = widget_alloc();
 
     // Open GUI and register fullscreen widget
-    Gui* gui = furi_open("gui");
-    furi_check(gui);
+    Gui* gui = furi_record_open("gui");
     gui_add_widget(gui, menu->widget, GuiLayerFullscreen);
 
     widget_enabled_set(menu->widget, false);
@@ -237,12 +235,7 @@ void menu_task(void* p) {
         release_mutex(menu_mutex, menu);
     }
 
-    if(!furi_create("menu", menu_mutex)) {
-        printf("[menu_task] cannot create the menu record\n");
-        furiac_exit(NULL);
-    }
-
-    furiac_ready();
+    furi_record_create("menu", menu_mutex);
 
     while(1) {
         MenuMessage m = menu_event_next(menu_event);

+ 1 - 3
applications/menu/menu_event.c

@@ -1,11 +1,9 @@
 #include "menu_event.h"
 
-#include <cmsis_os.h>
 #include <string.h>
 #include <stdlib.h>
 
-#include <flipper.h>
-#include <flipper_v2.h>
+#include <furi.h>
 
 #define MENU_MESSAGE_MQUEUE_SIZE 8
 

+ 1 - 2
applications/menu/menu_item.c

@@ -1,8 +1,7 @@
 #include "menu_item.h"
 #include <stdlib.h>
 #include <string.h>
-#include <flipper.h>
-#include <flipper_v2.h>
+#include <furi.h>
 
 struct MenuItem {
     MenuItemType type;

+ 6 - 8
applications/music-player/music-player.c

@@ -1,4 +1,6 @@
-#include "flipper_v2.h"
+#include <furi.h>
+#include <gui/gui.h>
+#include <input/input.h>
 
 // TODO float note freq
 typedef enum {
@@ -302,7 +304,7 @@ static void render_callback(Canvas* canvas, void* ctx) {
 }
 
 static void input_callback(InputEvent* input_event, void* ctx) {
-    osMessageQueueId_t event_queue = (QueueHandle_t)ctx;
+    osMessageQueueId_t event_queue = ctx;
 
     MusicDemoEvent event;
     event.type = EventTypeKey;
@@ -376,15 +378,11 @@ void music_player(void* p) {
     widget_input_callback_set(widget, input_callback, event_queue);
 
     // Open GUI and register widget
-    Gui* gui = (Gui*)furi_open("gui");
-    if(gui == NULL) {
-        printf("gui is not available\n");
-        furiac_exit(NULL);
-    }
+    Gui* gui = furi_record_open("gui");
     gui_add_widget(gui, widget, GuiLayerFullscreen);
 
     // open input record
-    PubSub* input_events_record = furi_open("input_events");
+    PubSub* input_events_record = furi_record_open("input_events");
     // prepare "do nothing" event
     InputEvent input_event = {InputRight, true};
 

+ 3 - 9
applications/nfc/nfc.c

@@ -16,8 +16,7 @@ Nfc* nfc_alloc() {
     nfc->worker = nfc_worker_alloc(nfc->message_queue);
 
     nfc->icon = assets_icons_get(A_NFC_14);
-    nfc->menu_vm = furi_open("menu");
-    furi_check(nfc->menu_vm);
+    nfc->menu_vm = furi_record_open("menu");
 
     nfc->menu = menu_item_alloc_menu("NFC", nfc->icon);
     menu_item_subitem_add(
@@ -102,18 +101,13 @@ void nfc_start(Nfc* nfc, NfcView view_id, NfcWorkerState worker_state) {
 void nfc_task(void* p) {
     Nfc* nfc = nfc_alloc();
 
-    Gui* gui = furi_open("gui");
+    Gui* gui = furi_record_open("gui");
     view_dispatcher_attach_to_gui(nfc->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
 
     with_value_mutex(
         nfc->menu_vm, (Menu * menu) { menu_item_add(menu, nfc->menu); });
 
-    if(!furi_create("nfc", nfc)) {
-        printf("[nfc_task] cannot create nfc record\n");
-        furiac_exit(NULL);
-    }
-
-    furiac_ready();
+    furi_record_create("nfc", nfc);
 
     NfcMessage message;
     while(1) {

+ 1 - 1
applications/nfc/nfc_i.h

@@ -5,7 +5,7 @@
 #include "nfc_views.h"
 #include "nfc_worker.h"
 
-#include <flipper_v2.h>
+#include <furi.h>
 
 #include <gui/gui.h>
 #include <gui/view.h>

+ 1 - 1
applications/nfc/nfc_views.h

@@ -3,7 +3,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include <gui/canvas.h>
-#include <flipper_v2.h>
+#include <furi.h>
 
 #include "nfc_types.h"
 

+ 1 - 2
applications/nfc/nfc_worker_i.h

@@ -3,8 +3,7 @@
 #include "nfc_types.h"
 #include "nfc_worker.h"
 
-#include <flipper_v2.h>
-#include <cmsis_os2.h>
+#include <furi.h>
 #include <stdbool.h>
 
 #include <rfal_analogConfig.h>

+ 10 - 12
applications/power/power.c

@@ -1,7 +1,7 @@
 #include "power.h"
 #include "power_views.h"
 
-#include <flipper_v2.h>
+#include <furi.h>
 
 #include <menu/menu.h>
 #include <menu/menu_item.h>
@@ -12,8 +12,8 @@
 #include <gui/view_dispatcher.h>
 
 #include <assets_icons.h>
-#include <api-hal-power.h>
 #include <cli/cli.h>
+#include <stm32wbxx.h>
 
 struct Power {
     ViewDispatcher* view_dispatcher;
@@ -47,6 +47,10 @@ void power_draw_battery_callback(Canvas* canvas, void* context) {
         });
 }
 
+uint32_t power_info_back_callback(void* context) {
+    return VIEW_NONE;
+}
+
 void power_menu_off_callback(void* context) {
     api_hal_power_off();
 }
@@ -71,10 +75,9 @@ void power_menu_info_callback(void* context) {
 Power* power_alloc() {
     Power* power = furi_alloc(sizeof(Power));
 
-    power->menu_vm = furi_open("menu");
-    furi_check(power->menu_vm);
+    power->menu_vm = furi_record_open("menu");
 
-    power->cli = furi_open("cli");
+    power->cli = furi_record_open("cli");
 
     power->menu = menu_item_alloc_menu("Power", NULL);
     menu_item_subitem_add(
@@ -163,7 +166,7 @@ void power_task(void* p) {
         cli_add_command(power->cli, "power_otg_off", power_cli_otg_off, power);
     }
 
-    Gui* gui = furi_open("gui");
+    Gui* gui = furi_record_open("gui");
     gui_add_widget(gui, power->usb_widget, GuiLayerStatusBarLeft);
     gui_add_widget(gui, power->battery_widget, GuiLayerStatusBarRight);
     view_dispatcher_attach_to_gui(power->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
@@ -171,14 +174,9 @@ void power_task(void* p) {
     with_value_mutex(
         power->menu_vm, (Menu * menu) { menu_item_add(menu, power->menu); });
 
-    if(!furi_create("power", power)) {
-        printf("[power_task] unable to create power record\n");
-        furiac_exit(NULL);
-    }
-
     api_hal_power_init();
 
-    furiac_ready();
+    furi_record_create("power", power);
 
     while(1) {
         with_view_model(

+ 1 - 5
applications/power/power_views.h

@@ -2,8 +2,8 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include <furi.h>
 #include <gui/canvas.h>
-#include <flipper_v2.h>
 #include <gui/view.h>
 
 typedef enum { PowerViewInfo } PowerView;
@@ -24,8 +24,4 @@ typedef struct {
     uint8_t charge;
 } PowerInfoModel;
 
-static uint32_t power_info_back_callback(void* context) {
-    return VIEW_NONE;
-}
-
 void power_info_draw_callback(Canvas* canvas, void* context);

+ 8 - 9
applications/sd-card-test/sd-card-test.cpp

@@ -104,23 +104,21 @@ void SdTest::run() {
 
     app_ready();
 
-    fs_api = static_cast<FS_Api*>(furi_open("sdcard"));
+    fs_api = static_cast<FS_Api*>(furi_record_open("sdcard"));
 
     if(fs_api == NULL) {
         set_error({"cannot get sdcard api"});
         exit();
     }
 
-    Cli* cli = static_cast<Cli*>(furi_open("cli"));
+    Cli* cli = static_cast<Cli*>(furi_record_open("cli"));
 
-    if(cli != NULL) {
-        // read_benchmark and write_benchmark signatures are same. so we must use tags
-        auto cli_read_cb = cbc::obtain_connector<0>(this, &SdTest::cli_read_benchmark);
-        cli_add_command(cli, "sd_read_test", cli_read_cb, this);
+    // read_benchmark and write_benchmark signatures are same. so we must use tags
+    auto cli_read_cb = cbc::obtain_connector<0>(this, &SdTest::cli_read_benchmark);
+    cli_add_command(cli, "sd_read_test", cli_read_cb, this);
 
-        auto cli_write_cb = cbc::obtain_connector<1>(this, &SdTest::cli_write_benchmark);
-        cli_add_command(cli, "sd_write_test", cli_write_cb, this);
-    }
+    auto cli_write_cb = cbc::obtain_connector<1>(this, &SdTest::cli_write_benchmark);
+    cli_add_command(cli, "sd_write_test", cli_write_cb, this);
 
     detect_sd_card();
     get_sd_card_info();
@@ -893,6 +891,7 @@ template <class T> void SdTest::set_text(std::initializer_list<T> list) {
 
     printf("------------------------\n");
     release_state();
+    update_gui();
 }
 
 // render app

+ 11 - 14
applications/sd-filesystem/sd-filesystem.c

@@ -480,22 +480,19 @@ void sd_filesystem(void* p) {
     SdApp* sd_app = sd_app_alloc();
     FS_Api* fs_api = fs_api_alloc();
 
-    Gui* gui = furi_open("gui");
+    Gui* gui = furi_record_open("gui");
+    Cli* cli = furi_record_open("cli");
+    ValueMutex* menu_vm = furi_record_open("menu");
+
     gui_add_widget(gui, sd_app->widget, GuiLayerFullscreen);
     gui_add_widget(gui, sd_app->icon.widget, GuiLayerStatusBarLeft);
 
-    Cli* cli = furi_open("cli");
-
-    if(cli != NULL) {
-        cli_add_command(cli, "sd_status", cli_sd_status, sd_app);
-        cli_add_command(cli, "sd_format", cli_sd_format, sd_app);
-        cli_add_command(cli, "sd_info", cli_sd_info, sd_app);
-    }
+    cli_add_command(cli, "sd_status", cli_sd_status, sd_app);
+    cli_add_command(cli, "sd_format", cli_sd_format, sd_app);
+    cli_add_command(cli, "sd_info", cli_sd_info, sd_app);
 
     // add api record
-    if(!furi_create("sdcard", fs_api)) {
-        furiac_exit(NULL);
-    }
+    furi_record_create("sdcard", fs_api);
 
     // init menu
     // TODO menu icon
@@ -510,15 +507,15 @@ void sd_filesystem(void* p) {
         menu_item, menu_item_alloc_function("Eject", NULL, app_sd_eject_callback, sd_app));
 
     // add item to menu
-    ValueMutex* menu_vm = furi_open("menu");
     furi_check(menu_vm);
     with_value_mutex(
         menu_vm, (Menu * menu) { menu_item_add(menu, menu_item); });
 
-    furiac_ready();
-
     printf("[sd_filesystem] start\n");
 
+    // add api record
+    furi_record_create("sdcard", fs_api);
+
     // sd card cycle
     bool sd_was_present = true;
 

+ 4 - 2
applications/sd-filesystem/sd-filesystem.h

@@ -1,6 +1,8 @@
 #pragma once
-#include "flipper.h"
-#include "flipper_v2.h"
+
+#include <furi.h>
+#include <gui/gui.h>
+#include <input/input.h>
 
 #define SD_FS_MAX_FILES _FS_LOCK
 #define SD_STATE_LINES_COUNT 6

+ 2 - 2
applications/template/template.c.example

@@ -1,4 +1,4 @@
-#include "flipper_v2.h"
+#include <furi.h>
 
 typedef enum {
     EventTypeTick,
@@ -54,7 +54,7 @@ void template_app(void* p) {
     widget_input_callback_set(widget, input_callback, event_queue);
 
     // Open GUI and register widget
-    Gui* gui = (Gui*)furi_open("gui");
+    Gui* gui = furi_record_open("gui");
     if(gui == NULL) {
         printf("gui is not available\n");
         furiac_exit(NULL);

+ 5 - 3
applications/tests/furi_event_test.c

@@ -1,4 +1,4 @@
-#include "flipper_v2.h"
+#include <furi.h>
 #include "minunit.h"
 
 static void furi_concurent_app(void* p) {
@@ -10,7 +10,9 @@ static void furi_concurent_app(void* p) {
 }
 
 void test_furi_event() {
-    Event event;
+    mu_assert(false, "please reimplement or delete test");
+
+    /*Event event;
 
     mu_check(init_event(&event));
 
@@ -27,5 +29,5 @@ void test_furi_event() {
     // The event should not be signalled once it's processed
     mu_check(!wait_event_with_timeout(&event, 100));
 
-    mu_check(delete_event(&event));
+    mu_check(delete_event(&event));*/
 }

+ 1 - 3
applications/tests/furi_pubsub_test.c

@@ -1,8 +1,6 @@
 #include <stdio.h>
 #include <string.h>
-#include "flipper_v2.h"
-#include "log.h"
-
+#include <furi.h>
 #include "minunit.h"
 
 const uint32_t context_value = 0xdeadbeef;

+ 3 - 5
applications/tests/furi_record_test.c

@@ -1,16 +1,14 @@
 #include <stdio.h>
 #include <string.h>
-#include "flipper.h"
-#include "flipper_v2.h"
-#include "log.h"
+#include <furi.h>
 #include "minunit.h"
 
 void test_furi_create_open() {
     // 1. Create record
     uint8_t test_data = 0;
-    mu_check(furi_create("test/holding", (void*)&test_data));
+    furi_record_create("test/holding", (void*)&test_data);
 
     // 2. Open it
-    void* record = furi_open("test/holding");
+    void* record = furi_record_open("test/holding");
     mu_assert_pointers_eq(record, &test_data);
 }

+ 1 - 1
applications/tests/furi_value_expanders_test.c

@@ -1,4 +1,4 @@
-#include "flipper_v2.h"
+#include <furi.h>
 #include "minunit.h"
 #include <stdint.h>
 

+ 4 - 2
applications/tests/furi_valuemutex_test.c

@@ -1,7 +1,6 @@
 #include <stdio.h>
 #include <string.h>
-#include "flipper_v2.h"
-#include "log.h"
+#include <furi.h>
 
 #include "minunit.h"
 
@@ -88,6 +87,8 @@ void furi_concurent_app(void* p) {
 }
 
 void test_furi_concurrent_access() {
+    mu_assert(false, "please reimplement or delete test");
+    /*
     // 1. Create holding record
     ConcurrentValue value = {.a = 0, .b = 0};
     ValueMutex mutex;
@@ -123,4 +124,5 @@ void test_furi_concurrent_access() {
     mu_assert_int_eq(value.a, value.b);
 
     mu_check(delete_mutex(&mutex));
+    */
 }

+ 4 - 2
applications/tests/furiac_test.c

@@ -1,7 +1,6 @@
 #include <stdio.h>
 #include <string.h>
-#include "flipper.h"
-#include "log.h"
+#include <furi.h>
 
 /*
 Test: creating and killing task
@@ -24,6 +23,8 @@ void create_kill_app(void* p) {
 }
 
 bool test_furi_ac_create_kill() {
+    mu_assert(false, "please reimplement or delete test");
+    /*
     uint8_t counter = 0;
 
     uint8_t value_a = counter;
@@ -56,6 +57,7 @@ bool test_furi_ac_create_kill() {
     }
 
     return true;
+    */
 }
 
 /*

+ 1 - 2
applications/tests/minunit_test.c

@@ -1,6 +1,5 @@
 #include <stdio.h>
-#include "flipper.h"
-#include "log.h"
+#include <furi.h>
 #include "minunit_vars.h"
 #include "minunit.h"
 

+ 1 - 3
applications/tests/test_index.c

@@ -1,7 +1,5 @@
 #include <stdio.h>
-#include "flipper.h"
-#include "flipper_v2.h"
-#include "log.h"
+#include <furi.h>
 
 // #include "flipper-core.h" TODO: Rust build disabled
 

+ 0 - 47
core/api-basic/flapp.h

@@ -1,47 +0,0 @@
-#pragma once
-
-#include "flipper.h"
-
-// == Flipper Application control (flapp) ==
-
-typedef FlappHandler uint32_t; // TODO
-
-/*
-simply starts application. It call `app` entrypoint with `param` passed as argument
-Useful for daemon applications and pop-up.
-*/
-FlappHandler* flapp_start(void(app*)(void*), char* name, void* param);
-
-/*
-swtich to other application.
-System **stop current app**, call `app` entrypoint with `param` passed
-as argument and save current application entrypoint to `prev` field in
-current application registry. Useful for UI or "active" application.
-*/
-FlappHandler* flapp_switch(void(app*)(void*), char* name, void* param);
-
-/*
-Exit application
-stop current application (stop thread and clear application's stack),
-start application from `prev` entry in current application registry,
-cleanup current application registry.
-*/
-void flapp_exit(void* param);
-
-/*
-stop specified `app` without returning to `prev` application.
-*/
-bool flapp_kill(FlappHandler* app);
-
-/*
-If case one app depend on other, notify that app is ready.
-*/
-void flapp_ready();
-
-/*
-Register on-exit callback.
-It called before app will be killed.
-Not recommended to use in user scenario, only for system purpose
-(unregister callbacks, release mutexes, etc.)
-*/
-bool flapp_on_exit(void(cb*)(void*), void* ctx);

+ 0 - 14
core/api-basic/furi.c

@@ -1,14 +0,0 @@
-#include "furi.h"
-#include "furi-deprecated.h"
-
-bool furi_create(const char* name, void* ptr) {
-    return furi_create_deprecated(name, ptr, sizeof(size_t));
-}
-
-void* furi_open(const char* name) {
-    FuriRecordSubscriber* record = furi_open_deprecated(name, false, false, NULL, NULL, NULL);
-    void* res = furi_take(record);
-    furi_give(record);
-
-    return res;
-}

+ 0 - 26
core/api-basic/furi.h

@@ -1,26 +0,0 @@
-#pragma once
-
-#include "flipper.h"
-
-/*
-== Flipper universal registry implementation (FURI) ==
-
-## Requirements
-
-* start daemon app
-* kill app
-* start child thread (kill when parent app was killed)
-* switch between UI apps
-*/
-
-/*
-Create record.
-creates new record in registry and store pointer into it
-*/
-bool furi_create(const char* name, void* ptr);
-
-/*
-Open record.
-get stored pointer by its name
-*/
-void* furi_open(const char* name);

+ 4 - 2
core/api-hal/api-gpio.c

@@ -1,4 +1,6 @@
 #include "api-gpio.h"
+#include <cmsis_os2.h>
+#include <furi/record.h>
 
 osMutexId_t gpioInitMutex;
 
@@ -37,7 +39,7 @@ void gpio_disable(GpioDisableRecord* gpio_record) {
 
 // get GPIO record
 ValueMutex* gpio_open_mutex(const char* name) {
-    ValueMutex* gpio_mutex = (ValueMutex*)furi_open(name);
+    ValueMutex* gpio_mutex = (ValueMutex*)furi_record_open(name);
 
     // TODO disable gpio on app exit
     //if(gpio_mutex != NULL) flapp_on_exit(gpio_disable, gpio_mutex);
@@ -48,6 +50,6 @@ ValueMutex* gpio_open_mutex(const char* name) {
 // get GPIO record and acquire mutex
 GpioPin* gpio_open(const char* name) {
     ValueMutex* gpio_mutex = gpio_open_mutex(name);
-    GpioPin* gpio_pin = acquire_mutex(gpio_mutex, FLIPPER_HELPER_TIMEOUT);
+    GpioPin* gpio_pin = acquire_mutex(gpio_mutex, osWaitForever);
     return gpio_pin;
 }

+ 11 - 3
core/api-hal/api-gpio.h

@@ -1,7 +1,11 @@
 #pragma once
-#include "flipper.h"
-#include "flipper_v2.h"
+
 #include "api-hal-gpio.h"
+#include <furi/valuemutex.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 typedef struct {
     ValueMutex* gpio_mutex;
@@ -38,4 +42,8 @@ void gpio_disable(GpioDisableRecord* gpio_record);
 ValueMutex* gpio_open_mutex(const char* name);
 
 // get GPIO record and acquire mutex
-GpioPin* gpio_open(const char* name);
+GpioPin* gpio_open(const char* name);
+
+#ifdef __cplusplus
+}
+#endif

+ 3 - 0
core/api-hal/api-interrupt-mgr.c

@@ -1,5 +1,8 @@
 #include "api-interrupt-mgr.h"
 
+#include <m-list.h>
+#include <cmsis_os2.h>
+
 LIST_DEF(list_interrupt, InterruptCallbackItem, M_POD_OPLIST);
 list_interrupt_t interrupts;
 osMutexId_t interrupt_list_mutex;

+ 11 - 2
core/api-hal/api-interrupt-mgr.h

@@ -1,5 +1,10 @@
 #pragma once
-#include "flipper_v2.h"
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 typedef void (*InterruptCallback)(void*, void*);
 
@@ -18,4 +23,8 @@ typedef struct {
 bool api_interrupt_init();
 void api_interrupt_add(InterruptCallback callback, InterruptType type, void* context);
 void api_interrupt_remove(InterruptCallback callback);
-void api_interrupt_call(InterruptType type, void* hw);
+void api_interrupt_call(InterruptType type, void* hw);
+
+#ifdef __cplusplus
+}
+#endif

+ 10 - 2
core/api-hal/api-spi.h

@@ -1,4 +1,8 @@
-#include "flipper_v2.h"
+#include <furi.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 /*
 struct used for handling SPI info.
@@ -133,4 +137,8 @@ void cc1101_example() {
     }
 }
 ```
-*/
+*/
+
+#ifdef __cplusplus
+}
+#endif

+ 0 - 48
core/app.cpp

@@ -1,48 +0,0 @@
-#include <stdio.h>
-#include "flipper.h"
-#include "flipper_v2.h"
-
-extern "C" {
-#include "log.h"
-#include "applications.h"
-#include "tty_uart.h"
-}
-
-// for testing purpose
-uint32_t exitcode = 0;
-extern "C" void set_exitcode(uint32_t _exitcode) {
-    exitcode = _exitcode;
-}
-
-extern "C" int app() {
-    init_flipper_api();
-    register_tty_uart();
-
-    FuriRecordSubscriber* log = get_default_log();
-    fuprintf(log, "\n=== Welcome to Flipper Zero! ===\n\n");
-
-    // FURI startup
-    const size_t flipper_app_count = sizeof(FLIPPER_STARTUP) / sizeof(FLIPPER_STARTUP[0]);
-    FuriApp* handlers[flipper_app_count];
-
-    for(size_t i = 0; i < flipper_app_count; i++) {
-        // 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);
-    }
-
-    bool is_alive = false;
-    do {
-        is_alive = false;
-        for(size_t i = 0; i < flipper_app_count; i++) {
-            if(handlers[i]->handler != NULL) {
-                is_alive = true;
-            }
-        }
-        delay(500);
-    } while(is_alive);
-
-    fuprintf(log, "\n=== Bye from Flipper Zero! ===\n\n");
-
-    return (int)exitcode;
-}

+ 2 - 2
core/core.mk

@@ -1,8 +1,8 @@
 CORE_DIR		= $(PROJECT_ROOT)/core
 
-CFLAGS			+= -I$(CORE_DIR)
+CFLAGS			+= -I$(CORE_DIR) -D_GNU_SOURCE
 ASM_SOURCES		+= $(wildcard $(CORE_DIR)/*.s)
 C_SOURCES		+= $(wildcard $(CORE_DIR)/*.c)
-C_SOURCES		+= $(wildcard $(CORE_DIR)/api-basic/*.c)
+C_SOURCES		+= $(wildcard $(CORE_DIR)/furi/*.c)
 C_SOURCES		+= $(wildcard $(CORE_DIR)/api-hal/*.c)
 CPP_SOURCES		+= $(wildcard $(CORE_DIR)/*.cpp)

+ 0 - 24
core/flipper.h

@@ -1,24 +0,0 @@
-#pragma once
-
-#include "api-hal.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "main.h"
-#include "cmsis_os.h"
-#include "furi-deprecated.h"
-
-#include "log.h"
-#include "input/input.h"
-
-#include <stdio.h>
-
-void set_exitcode(uint32_t _exitcode);
-
-#define FURI_LIB (const char*[])
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 16
core/flipper_arduino.h

@@ -1,16 +0,0 @@
-#pragma once
-#include "stdint.h"
-
-// Arduino defines
-#define pinMode gpio_init
-#define digitalWrite gpio_write
-#define digitalRead gpio_read
-#define delayMicroseconds delay_us
-#define delay osDelay
-
-#define OUTPUT GpioModeOutputPushPull
-#define INPUT GpioModeInput
-#define LOW false
-#define HIGH true
-
-typedef uint8_t byte;

+ 0 - 19
core/flipper_v2.c

@@ -1,19 +0,0 @@
-#include "flipper_v2.h"
-
-bool init_flipper_api(void) {
-    bool no_errors = true;
-
-    if(!furi_init()) {
-        no_errors = false;
-    }
-
-    if(!gpio_api_init()) {
-        no_errors = false;
-    }
-
-    if(!api_interrupt_init()) {
-        no_errors = false;
-    }
-
-    return no_errors;
-}

+ 0 - 33
core/flipper_v2.h

@@ -1,33 +0,0 @@
-#pragma once
-
-#include "flipper.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include "api-basic/furi.h"
-//#include "api-basic/flapp.h"
-#include "cmsis_os2.h"
-#include "api-basic/valuemutex.h"
-#include "api-basic/pubsub.h"
-#include "api-basic/value-expanders.h"
-#include "api-basic/event.h"
-
-#include "api-basic/memmgr.h"
-#include "api-basic/check.h"
-
-#include "api-hal/api-gpio.h"
-#include "api-hal/api-interrupt-mgr.h"
-#include "api-hal-resources.h"
-
-#include "gui/gui.h"
-
-// tmeout for helper functions
-#define FLIPPER_HELPER_TIMEOUT 10
-
-bool init_flipper_api(void);
-
-#ifdef __cplusplus
-}
-#endif

+ 0 - 295
core/furi-deprecated.c

@@ -1,295 +0,0 @@
-#include "furi-deprecated.h"
-#include <string.h>
-
-// TODO: this file contains printf, that not implemented on uC target
-
-#ifdef FURI_DEBUG
-#include <stdio.h>
-#endif
-
-#define MAX_RECORD_COUNT 32
-
-static FuriRecord records[MAX_RECORD_COUNT];
-static size_t current_buffer_idx = 0;
-osMutexId_t furi_core_mutex;
-
-bool furi_init(void) {
-    furi_core_mutex = osMutexNew(NULL);
-    if(furi_core_mutex == NULL) return false;
-    return true;
-}
-
-// find record pointer by name
-static FuriRecord* find_record(const char* name) {
-    if(name == NULL) return NULL;
-
-    FuriRecord* res = NULL;
-    for(size_t i = 0; i < MAX_RECORD_COUNT; i++) {
-        if(records[i].name != NULL && strcmp(name, records[i].name) == 0) {
-            res = &records[i];
-        }
-    }
-
-    return res;
-}
-
-// TODO: change open-create to only open
-bool furi_create_deprecated(const char* name, void* value, size_t size) {
-#ifdef FURI_DEBUG
-    printf("[FURI] creating %s record\n", name);
-#endif
-
-    // acquire mutex to prevent simultaneous write to record with same index
-    if(osMutexAcquire(furi_core_mutex, osWaitForever) != osOK) {
-        return false;
-    }
-
-    FuriRecord* record = find_record(name);
-
-    if(record != NULL) {
-#ifdef FURI_DEBUG
-        printf("[FURI] record already exist\n");
-#endif
-
-        record->value = value;
-        record->size = size;
-
-        return true;
-    }
-
-    // record not exist, create new
-
-    if(current_buffer_idx >= MAX_RECORD_COUNT) {
-// max record count exceed
-#ifdef FURI_DEBUG
-        printf("[FURI] create: max record count exceed\n");
-#endif
-        return NULL;
-    }
-
-    records[current_buffer_idx].mute_counter = 0;
-    records[current_buffer_idx].mutex =
-        xSemaphoreCreateMutexStatic(&records[current_buffer_idx].mutex_buffer);
-    records[current_buffer_idx].value = value;
-    records[current_buffer_idx].size = size;
-    records[current_buffer_idx].name = name;
-
-    for(size_t i = 0; i < MAX_RECORD_SUBSCRIBERS; i++) {
-        records[current_buffer_idx].subscribers[i].allocated = false;
-        records[current_buffer_idx].subscribers[i].ctx = NULL;
-    }
-
-    current_buffer_idx++;
-
-    osMutexRelease(furi_core_mutex);
-
-    return true;
-}
-
-FuriRecordSubscriber* furi_open_deprecated(
-    const char* name,
-    bool solo,
-    bool no_mute,
-    FlipperRecordCallback value_callback,
-    FlipperRecordStateCallback state_callback,
-    void* ctx) {
-#ifdef FURI_DEBUG
-    printf("[FURI] opening %s record\n", name);
-#endif
-
-    // get furi record by name
-    FuriRecord* record = find_record(name);
-
-    if(record == NULL) {
-// cannot find record
-#ifdef FURI_DEBUG
-        printf("[FURI] cannot find record %s\n", name);
-#endif
-
-        // create record if not exist
-        if(!furi_create_deprecated(name, NULL, 0)) {
-            return NULL;
-        }
-
-        record = find_record(name);
-
-        if(record == NULL) {
-            return NULL;
-        }
-    }
-
-    // allocate subscriber
-    FuriRecordSubscriber* subscriber = NULL;
-
-    for(size_t i = 0; i < MAX_RECORD_SUBSCRIBERS; i++) {
-        if(!record->subscribers[i].allocated) {
-            subscriber = &record->subscribers[i];
-            break;
-        }
-    }
-
-    if(subscriber == NULL) {
-// cannot add subscriber (full)
-#ifdef FURI_DEBUG
-        printf("[FURI] open: cannot add subscriber (full)\n");
-#endif
-
-        return NULL;
-    }
-
-    // increase mute_counter
-    if(solo) {
-        record->mute_counter++;
-    }
-
-    // set all parameters
-    subscriber->allocated = true;
-    subscriber->mute_counter = record->mute_counter;
-    subscriber->no_mute = no_mute;
-    subscriber->cb = value_callback;
-    subscriber->state_cb = state_callback;
-    subscriber->record = record;
-    subscriber->ctx = ctx;
-
-    // register record in application
-    FuriApp* current_task = find_task(xTaskGetCurrentTaskHandle());
-
-    if(current_task != NULL) {
-        current_task->records[current_task->records_count] = record;
-        current_task->records_count++;
-    } else {
-#ifdef FURI_DEBUG
-        printf("[FURI] open: no current task\n");
-#endif
-    }
-
-    return subscriber;
-}
-
-void furi_close(FuriRecordSubscriber* handler) {
-#ifdef FURI_DEBUG
-    printf("[FURI] closing %s record\n", handler->record->name);
-#endif
-
-    // deallocate subscriber
-    handler->allocated = false;
-
-    // set mute counter to next max value
-    uint8_t max_mute_counter = 0;
-    for(size_t i = 0; i < MAX_RECORD_SUBSCRIBERS; i++) {
-        if(handler->record->subscribers[i].allocated) {
-            if(handler->record->subscribers[i].mute_counter > max_mute_counter) {
-                max_mute_counter = handler->record->subscribers[i].mute_counter;
-            }
-        }
-    }
-    handler->record->mute_counter = max_mute_counter;
-}
-
-static void furi_notify(FuriRecordSubscriber* handler, const void* value, size_t size) {
-    for(size_t i = 0; i < MAX_RECORD_SUBSCRIBERS; i++) {
-        if(handler->record->subscribers[i].allocated) {
-            if(handler->record->subscribers[i].cb != NULL) {
-                handler->record->subscribers[i].cb(
-                    value, size, handler->record->subscribers[i].ctx);
-            }
-        }
-    }
-}
-
-void* furi_take(FuriRecordSubscriber* handler) {
-    if(handler == NULL || handler->record == NULL) return NULL;
-
-    if(xSemaphoreTake(handler->record->mutex, portMAX_DELAY) == pdTRUE) {
-        return handler->record->value;
-    } else {
-        return NULL;
-    }
-}
-
-void furi_give(FuriRecordSubscriber* handler) {
-    if(handler == NULL || handler->record == NULL) return;
-
-    xSemaphoreGive(handler->record->mutex);
-}
-
-void furi_commit(FuriRecordSubscriber* handler) {
-    if(handler == NULL || handler->record == NULL) return;
-
-    furi_notify(handler, handler->record->value, handler->record->size);
-    furi_give(handler);
-}
-
-bool furi_read(FuriRecordSubscriber* handler, void* value, size_t size) {
-#ifdef FURI_DEBUG
-    printf("[FURI] read from %s\n", handler->record->name);
-#endif
-
-    if(handler == NULL || handler->record == NULL || value == NULL) return false;
-
-    if(size > handler->record->size) return false;
-
-    // return false if read from pipe
-    if(handler->record->value == NULL) return false;
-
-    furi_take(handler);
-    memcpy(value, handler->record->value, size);
-    furi_notify(handler, value, size);
-    furi_give(handler);
-
-    return true;
-}
-
-bool furi_write(FuriRecordSubscriber* handler, const void* value, size_t size) {
-#ifdef FURI_DEBUG
-    printf("[FURI] write to %s\n", handler->record->name);
-#endif
-
-    if(handler == NULL || handler->record == NULL || value == NULL) {
-#ifdef FURI_DEBUG
-        printf(
-            "[FURI] write: null param %x %x\n",
-            (uint32_t)(size_t)handler,
-            (uint32_t)(size_t)value);
-#endif
-
-        return false;
-    }
-
-    // check if closed
-    if(!handler->allocated) {
-#ifdef FURI_DEBUG
-        printf("[FURI] write: handler closed\n");
-#endif
-        return false;
-    }
-
-    if(handler->record->value != NULL && size > handler->record->size) {
-#ifdef FURI_DEBUG
-        printf("[FURI] write: wrong size %d\n", (uint32_t)size);
-#endif
-        return false;
-    }
-
-    // check mute
-    if(handler->record->mute_counter != handler->mute_counter && !handler->no_mute) {
-#ifdef FURI_DEBUG
-        printf("[FURI] write: muted\n");
-#endif
-        return false;
-    }
-
-    furi_take(handler);
-    if(handler->record->value != NULL) {
-        // real write to value
-        memcpy(handler->record->value, value, size);
-
-        // notify subscribers
-        furi_notify(handler, handler->record->value, handler->record->size);
-    } else {
-        furi_notify(handler, value, size);
-    }
-    furi_give(handler);
-
-    return true;
-}

+ 0 - 207
core/furi-deprecated.h

@@ -1,207 +0,0 @@
-#pragma once
-
-#include "cmsis_os.h"
-
-#ifdef HAVE_FREERTOS
-#include <semphr.h>
-#endif
-
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <assert.h>
-
-#include "assets_icons.h"
-
-#define MAX_TASK_RECORDS 8
-#define MAX_RECORD_SUBSCRIBERS 8
-
-inline static void* furi_alloc(size_t size) {
-    void* p = malloc(size);
-    assert(p);
-    return memset(p, 0, size);
-}
-
-/// application is just a function
-typedef void (*FlipperApplication)(void*);
-
-/// pointer to value callback function
-typedef void (*FlipperRecordCallback)(const void*, size_t, void*);
-
-typedef enum {
-    FlipperRecordStateMute, ///< record open and mute this handler
-    FlipperRecordStateUnmute, ///< record unmuted
-    FlipperRecordStateDeleted ///< record owner halt
-} FlipperRecordState;
-
-/// pointer to state callback function
-typedef void (*FlipperRecordStateCallback)(FlipperRecordState, void*);
-
-struct _FuriRecord;
-
-typedef struct {
-    bool allocated;
-    FlipperRecordCallback cb; ///< value cb
-    FlipperRecordStateCallback state_cb; ///< state cb
-    uint8_t mute_counter; ///< see "wiki/FURI#mute-algorithm"
-    bool no_mute;
-    struct _FuriRecord* record; ///< parent record
-    void* ctx;
-} FuriRecordSubscriber;
-
-/// FURI record handler
-struct _FuriRecord {
-    const char* name;
-    void* value;
-    size_t size;
-    StaticSemaphore_t mutex_buffer;
-    SemaphoreHandle_t mutex;
-    uint8_t mute_counter;
-    FuriRecordSubscriber subscribers[MAX_RECORD_SUBSCRIBERS];
-};
-
-typedef struct _FuriRecord FuriRecord;
-
-/// store info about active task
-typedef struct {
-    const char* name;
-    FlipperApplication application;
-    const char* prev_name;
-    FlipperApplication prev;
-    TaskHandle_t handler;
-    uint8_t records_count; ///< count of records which task open
-    FuriRecord* records[MAX_TASK_RECORDS]; ///< list of records which task open
-
-    bool ready;
-} FuriApp;
-
-// application dependency info
-typedef struct {
-    uint8_t count;
-    const char** name;
-} FlipperAppLibrary;
-
-// application startup info
-typedef struct {
-    FlipperApplication app;
-    const char* name;
-    FlipperAppLibrary libs;
-    IconName icon;
-} FlipperStartupApp;
-
-// Init core
-bool furi_init(void);
-
-/*!
-Simply starts application.
-It call app entrypoint with param passed as argument.
-Useful for daemon applications and pop-up.
-*/
-FuriApp* furiac_start(FlipperApplication app, const char* name, void* param);
-
-/*!
-Swtich to other application.
-FURI stop current app, call app entrypoint with param passed as
-argument and save current application entrypoint to prev field
-in current application registry.
-Useful for UI or "active" application.
-*/
-void furiac_switch(FlipperApplication app, char* name, void* param);
-
-/*!
-Stop current application
-(stop thread and clear application's stack), start application
-from prev entry in current application registry, cleanup current
-application registry.
-*/
-void furiac_exit(void* param);
-
-/*!
-Mark application as prepared and ready to perform actions
-*/
-void furiac_ready();
-
-/* 
-Wait for the libraries we depend on
-*/
-void furiac_wait_libs(const FlipperAppLibrary* libs);
-
-/*!
-Stop specified app without returning to prev application.
-*/
-bool furiac_kill(FuriApp* app);
-
-// find task pointer by handle
-FuriApp* find_task(TaskHandle_t handler);
-
-/*!
-Creates named FURI record.
-\param[in] name you can open this record anywhere
-\param[in] value pointer to data.
-\param[in] size size of data.
-If NULL, create FURI Pipe (only callbacks management, no data/mutex)
-
-Returns false if registry have not enough memory for creating.
-*/
-bool furi_create_deprecated(const char* name, void* value, size_t size);
-
-/*!
-Opens existing FURI record by name.
-Returns NULL if record does not exist.
-\param[in] solo if true another applications handlers set into "muted" state.
-When appication has exited or record has closed, all handlers is unmuted.
-It may be useful for concurrently acces to resources like framebuffer or beeper.
-\param[in] no_mute if true, another applications cannot mute this handler.
-*/
-FuriRecordSubscriber* furi_open_deprecated(
-    const char* name,
-    bool solo,
-    bool no_mute,
-    FlipperRecordCallback value_callback,
-    FlipperRecordStateCallback state_callback,
-    void* ctx);
-
-/*!
-
-*/
-void furi_close(FuriRecordSubscriber* handler);
-
-/*!
-read message from record.
-Returns true if success, false otherwise (closed/non-existent record)
-Also return false if you try to read from FURI pipe
-
-TODO: enum return value with execution status
-*/
-bool furi_read(FuriRecordSubscriber* record, void* data, size_t size);
-
-/*!
-write message to record.
-Returns true if success, false otherwise (closed/non-existent record or muted).
-
-TODO: enum return value with execution status
-*/
-bool furi_write(FuriRecordSubscriber* record, const void* data, size_t size);
-
-/*!
-lock value mutex.
-It can be useful if records contain pointer to buffer which you want to change.
-You must call furi_give after operation on data and
-you shouldn't block executing between take and give calls
-
-Returns pointer to data, NULL if closed/non-existent record or muted
-
-TODO: enum return value with execution status
-*/
-void* furi_take(FuriRecordSubscriber* record);
-
-/*!
-unlock value mutex.
-*/
-void furi_give(FuriRecordSubscriber* record);
-
-/*!
-unlock value mutex and notify subscribers that data is chaned.
-*/
-void furi_commit(FuriRecordSubscriber* handler);

+ 36 - 0
core/furi.c

@@ -0,0 +1,36 @@
+#include "furi.h"
+#include <applications.h>
+
+// for testing purpose
+uint32_t exitcode = 0;
+
+void set_exitcode(uint32_t _exitcode) {
+    exitcode = _exitcode;
+}
+
+void furi_init() {
+    gpio_api_init();
+    api_interrupt_init();
+    furi_record_init();
+    furi_stdglue_init();
+}
+
+int systemd() {
+    furi_init();
+
+    // FURI startup
+    for(size_t i = 0; i < FLIPPER_SERVICES_size(); i++) {
+        osThreadAttr_t* attr = furi_alloc(sizeof(osThreadAttr_t));
+        attr->name = FLIPPER_SERVICES[i].name;
+        attr->stack_size = 1024;
+        osThreadNew(FLIPPER_SERVICES[i].app, NULL, attr);
+    }
+
+    while(1) {
+        osThreadSuspend(osThreadGetId());
+    }
+
+    printf("\n=== Bye from Flipper Zero! ===\n\n");
+
+    return (int)exitcode;
+}

+ 28 - 0
core/furi.h

@@ -0,0 +1,28 @@
+#pragma once
+
+#include <cmsis_os2.h>
+
+#include <furi/check.h>
+#include <furi/event.h>
+#include <furi/memmgr.h>
+#include <furi/pubsub.h>
+#include <furi/record.h>
+#include <furi/stdglue.h>
+#include <furi/value-expanders.h>
+#include <furi/valuemutex.h>
+
+#include <api-hal/api-gpio.h>
+#include <api-hal/api-interrupt-mgr.h>
+
+#include <api-hal.h>
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define furiac_exit(ptr) osThreadExit()
+
+#ifdef __cplusplus
+}
+#endif

+ 9 - 7
core/api-basic/check.c → core/furi/check.c

@@ -1,5 +1,6 @@
 #include "check.h"
 #include "api-hal-task.h"
+#include <stdio.h>
 
 void __furi_abort(void);
 
@@ -22,20 +23,21 @@ void __furi_check_debug(const char* file, int line, const char* function, const
     if(task_is_isr_context()) {
         printf(" in [ISR] context");
     } else {
-        FuriApp* app = find_task(xTaskGetCurrentTaskHandle());
+        // FuriApp* app = find_task(xTaskGetCurrentTaskHandle());
 
-        if(app == NULL) {
-            printf(", in [main] context");
-        } else {
-            printf(", in [%s] app context", app->name);
-        }
+        // if(app == NULL) {
+        //     printf(", in [main] context");
+        // } else {
+        //     printf(", in [%s] app context", app->name);
+        // }
     }
 
     __furi_abort();
 }
 
 void __furi_abort(void) {
-    taskDISABLE_INTERRUPTS();
+    __disable_irq();
+    asm("bkpt 1");
     while(1) {
     }
 }

+ 8 - 2
core/api-basic/check.h → core/furi/check.h

@@ -1,6 +1,8 @@
 #pragma once
 
-#include "flipper.h"
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 // Find how to how get function's pretty name
 #ifndef __FURI_CHECK_FUNC
@@ -38,4 +40,8 @@
 // !NDEBUG
 
 void __furi_check(void);
-void __furi_check_debug(const char* file, int line, const char* function, const char* condition);
+void __furi_check_debug(const char* file, int line, const char* function, const char* condition);
+
+#ifdef __cplusplus
+}
+#endif

Некоторые файлы не были показаны из-за большого количества измененных файлов