[FL-872] Furi, API-HAL, App-Loader cleanup and improvements (#334)
* Furi: replace obsolete furiac_exit with osThreadExit, drop obsolete apis and test. Rename systemd to flipper and move to separate file, cleanup. ApiHal: Rename timebase to os and move freertos hooks there, move insomnia api to power module. * Furi: new thread helper * Furi: cleanup thread documentation * Flipper, AppLoader: update to use FuriThread. Update tasks signatures to match FuriThreadCallback signature. * F4: rename API_HAL_TIMEBASE_DEBUG to API_HAL_OS_DEBUG * Applications: rename FuriApplication to FlipperApplication, use FuriThreadCallback signature for apps. * C++ app template sample, new exit method
This commit is contained in:
@@ -8,20 +8,19 @@
|
||||
#include <api-hal.h>
|
||||
|
||||
typedef struct {
|
||||
osThreadAttr_t app_thread_attr;
|
||||
osThreadId_t app_thread_id;
|
||||
FuriThread* thread;
|
||||
ViewPort* view_port;
|
||||
const FuriApplication* current_app;
|
||||
const FlipperApplication* current_app;
|
||||
} AppLoaderState;
|
||||
|
||||
typedef struct {
|
||||
AppLoaderState* state;
|
||||
const FuriApplication* app;
|
||||
const FlipperApplication* app;
|
||||
} AppLoaderContext;
|
||||
|
||||
// TODO add mutex for contex
|
||||
|
||||
static void render_callback(Canvas* canvas, void* _ctx) {
|
||||
static void app_loader_render_callback(Canvas* canvas, void* _ctx) {
|
||||
AppLoaderState* ctx = (AppLoaderState*)_ctx;
|
||||
|
||||
canvas_clear(canvas);
|
||||
@@ -33,77 +32,71 @@ static void render_callback(Canvas* canvas, void* _ctx) {
|
||||
canvas_draw_str(canvas, 2, 44, "press back to exit");
|
||||
}
|
||||
|
||||
static void input_callback(InputEvent* input_event, void* _ctx) {
|
||||
static void app_loader_input_callback(InputEvent* input_event, void* _ctx) {
|
||||
AppLoaderState* ctx = (AppLoaderState*)_ctx;
|
||||
|
||||
if(input_event->type == InputTypeShort && input_event->key == InputKeyBack) {
|
||||
osThreadTerminate(ctx->app_thread_id);
|
||||
view_port_enabled_set(ctx->view_port, false);
|
||||
api_hal_timebase_insomnia_exit();
|
||||
furi_thread_terminate(ctx->thread);
|
||||
}
|
||||
}
|
||||
|
||||
static void handle_menu(void* _ctx) {
|
||||
static void app_loader_menu_callback(void* _ctx) {
|
||||
AppLoaderContext* ctx = (AppLoaderContext*)_ctx;
|
||||
|
||||
if(ctx->app->app == NULL) return;
|
||||
|
||||
view_port_enabled_set(ctx->state->view_port, true);
|
||||
|
||||
// TODO how to call this?
|
||||
// furiac_wait_libs(&FLIPPER_STARTUP[i].libs);
|
||||
api_hal_timebase_insomnia_enter();
|
||||
api_hal_power_insomnia_enter();
|
||||
|
||||
ctx->state->current_app = ctx->app;
|
||||
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 = ctx->app->stack_size;
|
||||
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);
|
||||
|
||||
furi_thread_set_name(ctx->state->thread, ctx->app->name);
|
||||
furi_thread_set_stack_size(ctx->state->thread, ctx->app->stack_size);
|
||||
furi_thread_set_callback(ctx->state->thread, ctx->app->app);
|
||||
furi_thread_start(ctx->state->thread);
|
||||
}
|
||||
|
||||
static void handle_cli(string_t args, void* _ctx) {
|
||||
static void app_loader_cli_callback(string_t args, void* _ctx) {
|
||||
AppLoaderContext* ctx = (AppLoaderContext*)_ctx;
|
||||
|
||||
if(ctx->app->app == NULL) return;
|
||||
|
||||
printf("Starting furi application\r\n");
|
||||
|
||||
ctx->state->current_app = ctx->app;
|
||||
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 = ctx->app->stack_size;
|
||||
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);
|
||||
api_hal_power_insomnia_enter();
|
||||
|
||||
furi_thread_set_name(ctx->state->thread, ctx->app->name);
|
||||
furi_thread_set_stack_size(ctx->state->thread, ctx->app->stack_size);
|
||||
furi_thread_set_callback(ctx->state->thread, ctx->app->app);
|
||||
furi_thread_start(ctx->state->thread);
|
||||
|
||||
printf("Press any key to kill application");
|
||||
|
||||
char c;
|
||||
cli_read(&c, 1);
|
||||
osThreadTerminate(ctx->state->app_thread_id);
|
||||
furi_thread_terminate(ctx->state->thread);
|
||||
}
|
||||
|
||||
void app_loader(void* p) {
|
||||
osThreadId_t self_id = osThreadGetId();
|
||||
furi_check(self_id);
|
||||
void app_loader_thread_state_callback(FuriThreadState state, void* context) {
|
||||
furi_assert(context);
|
||||
AppLoaderState* app_loader_state = context;
|
||||
if(state == FuriThreadStateStopped) {
|
||||
view_port_enabled_set(app_loader_state->view_port, false);
|
||||
api_hal_power_insomnia_exit();
|
||||
}
|
||||
}
|
||||
|
||||
int32_t app_loader(void* p) {
|
||||
AppLoaderState state;
|
||||
state.app_thread_id = NULL;
|
||||
state.thread = furi_thread_alloc();
|
||||
furi_thread_set_state_context(state.thread, &state);
|
||||
furi_thread_set_state_callback(state.thread, app_loader_thread_state_callback);
|
||||
|
||||
state.view_port = view_port_alloc();
|
||||
view_port_enabled_set(state.view_port, false);
|
||||
view_port_draw_callback_set(state.view_port, render_callback, &state);
|
||||
view_port_input_callback_set(state.view_port, input_callback, &state);
|
||||
view_port_draw_callback_set(state.view_port, app_loader_render_callback, &state);
|
||||
view_port_input_callback_set(state.view_port, app_loader_input_callback, &state);
|
||||
|
||||
ValueMutex* menu_mutex = furi_record_open("menu");
|
||||
Cli* cli = furi_record_open("cli");
|
||||
@@ -114,7 +107,7 @@ void app_loader(void* p) {
|
||||
// Main menu
|
||||
with_value_mutex(
|
||||
menu_mutex, (Menu * menu) {
|
||||
for(size_t i = 0; i < FLIPPER_APPS_size(); i++) {
|
||||
for(size_t i = 0; i < FLIPPER_APPS_COUNT; i++) {
|
||||
AppLoaderContext* ctx = furi_alloc(sizeof(AppLoaderContext));
|
||||
ctx->state = &state;
|
||||
ctx->app = &FLIPPER_APPS[i];
|
||||
@@ -124,14 +117,14 @@ void app_loader(void* p) {
|
||||
menu_item_alloc_function(
|
||||
FLIPPER_APPS[i].name,
|
||||
assets_icons_get(FLIPPER_APPS[i].icon),
|
||||
handle_menu,
|
||||
app_loader_menu_callback,
|
||||
ctx));
|
||||
|
||||
// Add cli command
|
||||
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);
|
||||
cli_add_command(cli, string_get_cstr(cli_name), app_loader_cli_callback, ctx);
|
||||
string_clear(cli_name);
|
||||
}
|
||||
});
|
||||
@@ -160,7 +153,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_size(); i++) {
|
||||
for(size_t i = 0; i < FLIPPER_PLUGINS_COUNT; i++) {
|
||||
AppLoaderContext* ctx = furi_alloc(sizeof(AppLoaderContext));
|
||||
ctx->state = &state;
|
||||
ctx->app = &FLIPPER_PLUGINS[i];
|
||||
@@ -170,14 +163,14 @@ void app_loader(void* p) {
|
||||
menu_item_alloc_function(
|
||||
FLIPPER_PLUGINS[i].name,
|
||||
assets_icons_get(FLIPPER_PLUGINS[i].icon),
|
||||
handle_menu,
|
||||
app_loader_menu_callback,
|
||||
ctx));
|
||||
|
||||
// Add cli command
|
||||
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);
|
||||
cli_add_command(cli, string_get_cstr(cli_name), app_loader_cli_callback, ctx);
|
||||
string_clear(cli_name);
|
||||
}
|
||||
|
||||
@@ -186,5 +179,9 @@ void app_loader(void* p) {
|
||||
|
||||
printf("[app loader] start\r\n");
|
||||
|
||||
osThreadSuspend(self_id);
|
||||
while(1) {
|
||||
osThreadSuspend(osThreadGetId());
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1,41 +1,40 @@
|
||||
#include "applications.h"
|
||||
|
||||
#ifdef APP_TEST
|
||||
void flipper_test_app(void* p);
|
||||
int32_t flipper_test_app(void* p);
|
||||
#endif
|
||||
|
||||
void application_blink(void* p);
|
||||
void application_uart_write(void* p);
|
||||
void application_input_dump(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);
|
||||
int32_t application_blink(void* p);
|
||||
int32_t application_uart_write(void* p);
|
||||
int32_t application_input_dump(void* p);
|
||||
int32_t u8g2_example(void* p);
|
||||
int32_t input_task(void* p);
|
||||
int32_t menu_task(void* p);
|
||||
int32_t coreglitch_demo_0(void* p);
|
||||
int32_t u8g2_qrcode(void* p);
|
||||
int32_t gui_task(void* p);
|
||||
int32_t backlight_control(void* p);
|
||||
int32_t irda(void* p);
|
||||
int32_t app_loader(void* p);
|
||||
int32_t cc1101_workaround(void* p);
|
||||
int32_t lf_rfid_workaround(void* p);
|
||||
int32_t nfc_task(void* p);
|
||||
int32_t dolphin_task(void* p);
|
||||
int32_t power_task(void* p);
|
||||
int32_t bt_task(void* p);
|
||||
int32_t sd_card_test(void* p);
|
||||
int32_t application_vibro(void* p);
|
||||
int32_t app_gpio_test(void* p);
|
||||
int32_t app_ibutton(void* p);
|
||||
int32_t cli_task(void* p);
|
||||
int32_t music_player(void* p);
|
||||
int32_t sdnfc(void* p);
|
||||
int32_t floopper_bloopper(void* p);
|
||||
int32_t sd_filesystem(void* p);
|
||||
|
||||
void gui_test(void* p);
|
||||
int32_t gui_test(void* p);
|
||||
|
||||
const FuriApplication FLIPPER_SERVICES[] = {
|
||||
const FlipperApplication FLIPPER_SERVICES[] = {
|
||||
#ifdef APP_CLI
|
||||
{.app = cli_task, .name = "cli_task", .stack_size = 1024, .icon = A_Plugins_14},
|
||||
#endif
|
||||
@@ -111,10 +110,6 @@ const FuriApplication FLIPPER_SERVICES[] = {
|
||||
{.app = u8g2_qrcode, .name = "u8g2_qrcode", .stack_size = 1024, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_EXAMPLE_FATFS
|
||||
{.app = fatfs_list, .name = "fatfs_list", .stack_size = 1024, .icon = A_Plugins_14},
|
||||
#endif
|
||||
|
||||
#ifdef APP_EXAMPLE_DISPLAY
|
||||
{.app = u8g2_example, .name = "u8g2_example", .stack_size = 1024, .icon = A_Plugins_14},
|
||||
#endif
|
||||
@@ -155,12 +150,10 @@ const FuriApplication FLIPPER_SERVICES[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
size_t FLIPPER_SERVICES_size() {
|
||||
return sizeof(FLIPPER_SERVICES) / sizeof(FuriApplication);
|
||||
}
|
||||
const size_t FLIPPER_SERVICES_COUNT = sizeof(FLIPPER_SERVICES) / sizeof(FlipperApplication);
|
||||
|
||||
// Main menu APP
|
||||
const FuriApplication FLIPPER_APPS[] = {
|
||||
const FlipperApplication FLIPPER_APPS[] = {
|
||||
#ifdef BUILD_CC1101
|
||||
{.app = cc1101_workaround, .name = "Sub-1 GHz", .stack_size = 1024, .icon = A_Sub1ghz_14},
|
||||
#endif
|
||||
@@ -182,12 +175,10 @@ const FuriApplication FLIPPER_APPS[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
size_t FLIPPER_APPS_size() {
|
||||
return sizeof(FLIPPER_APPS) / sizeof(FuriApplication);
|
||||
}
|
||||
const size_t FLIPPER_APPS_COUNT = sizeof(FLIPPER_APPS) / sizeof(FlipperApplication);
|
||||
|
||||
// Plugin menu
|
||||
const FuriApplication FLIPPER_PLUGINS[] = {
|
||||
const FlipperApplication FLIPPER_PLUGINS[] = {
|
||||
#ifdef BUILD_EXAMPLE_BLINK
|
||||
{.app = application_blink, .name = "blink", .stack_size = 1024, .icon = A_Plugins_14},
|
||||
#endif
|
||||
@@ -231,6 +222,4 @@ const FuriApplication FLIPPER_PLUGINS[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
size_t FLIPPER_PLUGINS_size() {
|
||||
return sizeof(FLIPPER_PLUGINS) / sizeof(FuriApplication);
|
||||
}
|
||||
const size_t FLIPPER_PLUGINS_COUNT = sizeof(FLIPPER_PLUGINS) / sizeof(FlipperApplication);
|
||||
|
@@ -3,20 +3,27 @@
|
||||
#include <furi.h>
|
||||
#include <assets_icons.h>
|
||||
|
||||
typedef void (*FlipperApplication)(void*);
|
||||
|
||||
typedef struct {
|
||||
const FlipperApplication app;
|
||||
const FuriThreadCallback app;
|
||||
const char* name;
|
||||
const size_t stack_size;
|
||||
const IconName icon;
|
||||
} FuriApplication;
|
||||
} FlipperApplication;
|
||||
|
||||
extern const FuriApplication FLIPPER_SERVICES[];
|
||||
size_t FLIPPER_SERVICES_size();
|
||||
/* Services list
|
||||
* Spawned on startup
|
||||
*/
|
||||
extern const FlipperApplication FLIPPER_SERVICES[];
|
||||
extern const size_t FLIPPER_SERVICES_COUNT;
|
||||
|
||||
extern const FuriApplication FLIPPER_APPS[];
|
||||
size_t FLIPPER_APPS_size();
|
||||
/* Apps list
|
||||
* Spawned by app-loader
|
||||
*/
|
||||
extern const FlipperApplication FLIPPER_APPS[];
|
||||
extern const size_t FLIPPER_APPS_COUNT;
|
||||
|
||||
extern const FuriApplication FLIPPER_PLUGINS[];
|
||||
size_t FLIPPER_PLUGINS_size();
|
||||
/* Plugins list
|
||||
* Spawned by app-loader
|
||||
*/
|
||||
extern const FlipperApplication FLIPPER_PLUGINS[];
|
||||
extern const size_t FLIPPER_PLUGINS_COUNT;
|
||||
|
@@ -78,15 +78,12 @@ endif
|
||||
APP_TEST ?= 0
|
||||
ifeq ($(APP_TEST), 1)
|
||||
CFLAGS += -DAPP_TEST
|
||||
C_SOURCES += $(APP_DIR)/tests/furiac_test.c
|
||||
C_SOURCES += $(APP_DIR)/tests/furi_record_test.c
|
||||
C_SOURCES += $(APP_DIR)/tests/test_index.c
|
||||
C_SOURCES += $(APP_DIR)/tests/minunit_test.c
|
||||
C_SOURCES += $(APP_DIR)/tests/furi_valuemutex_test.c
|
||||
C_SOURCES += $(APP_DIR)/tests/furi_pubsub_test.c
|
||||
C_SOURCES += $(APP_DIR)/tests/furi_memmgr_test.c
|
||||
C_SOURCES += $(APP_DIR)/tests/furi_value_expanders_test.c
|
||||
C_SOURCES += $(APP_DIR)/tests/furi_event_test.c
|
||||
endif
|
||||
|
||||
APP_EXAMPLE_BLINK ?= 0
|
||||
@@ -147,18 +144,6 @@ C_SOURCES += $(APP_DIR)/examples/u8g2_qrcode.c
|
||||
C_SOURCES += $(LIB_DIR)/qrcode/qrcode.c
|
||||
endif
|
||||
|
||||
APP_EXAMPLE_FATFS ?= 0
|
||||
ifeq ($(APP_EXAMPLE_FATFS), 1)
|
||||
CFLAGS += -DAPP_EXAMPLE_FATFS
|
||||
BUILD_EXAMPLE_FATFS = 1
|
||||
endif
|
||||
BUILD_EXAMPLE_FATFS ?= 0
|
||||
ifeq ($(BUILD_EXAMPLE_FATFS), 1)
|
||||
CFLAGS += -DBUILD_EXAMPLE_FATFS
|
||||
C_SOURCES += $(APP_DIR)/examples/fatfs_list.c
|
||||
APP_INPUT = 1
|
||||
endif
|
||||
|
||||
APP_CC1101 ?= 0
|
||||
ifeq ($(APP_CC1101), 1)
|
||||
CFLAGS += -DAPP_CC1101
|
||||
|
@@ -7,7 +7,7 @@ static void event_cb(const void* value, void* ctx) {
|
||||
osThreadFlagsSet((osThreadId_t)ctx, BACKLIGHT_FLAG_ACTIVITY);
|
||||
}
|
||||
|
||||
void backlight_control(void* p) {
|
||||
int32_t backlight_control(void* p) {
|
||||
// TODO open record
|
||||
const GpioPin* backlight_record = &backlight_gpio;
|
||||
|
||||
@@ -28,4 +28,6 @@ void backlight_control(void* p) {
|
||||
gpio_write(backlight_record, false);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@@ -37,7 +37,7 @@ void bt_cli_info(string_t args, void* context) {
|
||||
string_clear(buffer);
|
||||
}
|
||||
|
||||
void bt_task() {
|
||||
int32_t bt_task() {
|
||||
Bt* bt = bt_alloc();
|
||||
|
||||
furi_record_create("bt", bt);
|
||||
@@ -48,4 +48,6 @@ void bt_task() {
|
||||
view_port_enabled_set(bt->statusbar_view_port, api_hal_bt_is_alive());
|
||||
osDelay(1024);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -345,7 +345,7 @@ static void input_callback(InputEvent* input_event, void* ctx) {
|
||||
osMessageQueuePut(event_queue, &event, 0, 0);
|
||||
}
|
||||
|
||||
extern "C" void cc1101_workaround(void* p) {
|
||||
extern "C" int32_t cc1101_workaround(void* p) {
|
||||
osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(AppEvent), NULL);
|
||||
furi_check(event_queue);
|
||||
|
||||
@@ -363,7 +363,7 @@ extern "C" void cc1101_workaround(void* p) {
|
||||
ValueMutex state_mutex;
|
||||
if(!init_mutex(&state_mutex, &_state, sizeof(State))) {
|
||||
printf("[cc1101] cannot create mutex\r\n");
|
||||
furiac_exit(NULL);
|
||||
return 255;
|
||||
}
|
||||
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
@@ -375,7 +375,7 @@ extern "C" void cc1101_workaround(void* p) {
|
||||
Gui* gui = (Gui*)furi_record_open("gui");
|
||||
if(gui == NULL) {
|
||||
printf("[cc1101] gui is not available\r\n");
|
||||
furiac_exit(NULL);
|
||||
return 255;
|
||||
}
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
@@ -397,7 +397,7 @@ extern "C" void cc1101_workaround(void* p) {
|
||||
printf("[cc1101] init done: %d\r\n", address);
|
||||
} else {
|
||||
printf("[cc1101] init fail\r\n");
|
||||
furiac_exit(NULL);
|
||||
return 255;
|
||||
}
|
||||
|
||||
cc1101.SpiStrobe(CC1101_SIDLE);
|
||||
@@ -439,7 +439,7 @@ extern "C" void cc1101_workaround(void* p) {
|
||||
|
||||
// TODO remove all view_ports create by app
|
||||
view_port_enabled_set(view_port, false);
|
||||
furiac_exit(NULL);
|
||||
return 255;
|
||||
}
|
||||
|
||||
if(event.value.input.type == InputTypeShort &&
|
||||
@@ -597,4 +597,6 @@ extern "C" void cc1101_workaround(void* p) {
|
||||
release_mutex(&state_mutex, state);
|
||||
view_port_update(view_port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@@ -172,7 +172,7 @@ void cli_add_command(Cli* cli, const char* name, CliCallback callback, void* con
|
||||
string_clear(name_str);
|
||||
}
|
||||
|
||||
void cli_task(void* p) {
|
||||
int32_t cli_task(void* p) {
|
||||
Cli* cli = cli_alloc();
|
||||
|
||||
// Init basic cli commands
|
||||
@@ -184,4 +184,6 @@ void cli_task(void* p) {
|
||||
while(1) {
|
||||
cli_process_input(cli);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
extern TIM_HandleTypeDef SPEAKER_TIM;
|
||||
|
||||
void coreglitch_demo_0(void* p) {
|
||||
int32_t coreglitch_demo_0(void* p) {
|
||||
printf("coreglitch demo!\r\n");
|
||||
|
||||
float notes[] = {
|
||||
@@ -47,4 +47,6 @@ void coreglitch_demo_0(void* p) {
|
||||
delay(100);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -129,7 +129,7 @@ void dolphin_deed(Dolphin* dolphin, DolphinDeed deed) {
|
||||
furi_check(osMessageQueuePut(dolphin->event_queue, &event, 0, osWaitForever) == osOK);
|
||||
}
|
||||
|
||||
void dolphin_task() {
|
||||
int32_t dolphin_task() {
|
||||
Dolphin* dolphin = dolphin_alloc();
|
||||
|
||||
Gui* gui = furi_record_open("gui");
|
||||
@@ -163,4 +163,6 @@ void dolphin_task() {
|
||||
dolphin_state_save(dolphin->state);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -12,7 +12,7 @@ void rgb_set(
|
||||
gpio_write(led_b, !b);
|
||||
}
|
||||
|
||||
void application_blink(void* p) {
|
||||
int32_t application_blink(void* p) {
|
||||
// TODO open record
|
||||
const GpioPin* led_r_record = &led_gpio[0];
|
||||
const GpioPin* led_g_record = &led_gpio[1];
|
||||
@@ -41,4 +41,6 @@ void application_blink(void* p) {
|
||||
rgb_set(0, 0, 0, led_r_record, led_g_record, led_b_record);
|
||||
delay(500);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@@ -13,7 +13,7 @@ static void event_cb(const void* value, void* ctx) {
|
||||
printf("event: %02x %s\r\n", event->key, event->type ? "pressed" : "released");
|
||||
}
|
||||
|
||||
void application_input_dump(void* p) {
|
||||
int32_t application_input_dump(void* p) {
|
||||
// open record
|
||||
PubSub* event_record = furi_record_open("input_events");
|
||||
subscribe_pubsub(event_record, event_cb, NULL);
|
||||
@@ -23,4 +23,6 @@ void application_input_dump(void* p) {
|
||||
for(;;) {
|
||||
delay(100);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#include "u8g2/u8g2.h"
|
||||
#include <furi.h>
|
||||
|
||||
void u8g2_example(void* p) {
|
||||
int32_t u8g2_example(void* p) {
|
||||
// open record
|
||||
u8g2_t* fb = furi_record_open("u8g2_fb");
|
||||
u8g2_SetFont(fb, u8g2_font_6x10_mf);
|
||||
@@ -10,5 +10,5 @@ void u8g2_example(void* p) {
|
||||
u8g2_DrawStr(fb, 2, 12, "hello world!");
|
||||
furi_record_close("u8g2_fb");
|
||||
|
||||
furiac_exit(NULL);
|
||||
return 0;
|
||||
}
|
@@ -13,7 +13,7 @@ void u8g2_DrawPixelSize(u8g2_t* u8g2, uint8_t x, uint8_t y, uint8_t size) {
|
||||
}
|
||||
}
|
||||
|
||||
void u8g2_qrcode(void* p) {
|
||||
int32_t u8g2_qrcode(void* p) {
|
||||
// open record
|
||||
FuriRecordSubscriber* fb_record =
|
||||
furi_open_deprecated("u8g2_fb", false, false, NULL, NULL, NULL);
|
||||
@@ -38,7 +38,7 @@ void u8g2_qrcode(void* p) {
|
||||
|
||||
if(fb_record == NULL) {
|
||||
printf("[view_port] cannot create fb record\r\n");
|
||||
furiac_exit(NULL);
|
||||
return 255;
|
||||
}
|
||||
|
||||
u8g2_t* fb = furi_take(fb_record);
|
||||
@@ -63,12 +63,14 @@ void u8g2_qrcode(void* p) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
furiac_exit(NULL);
|
||||
return 255;
|
||||
}
|
||||
|
||||
furi_commit(fb_record);
|
||||
|
||||
delay(1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
*/
|
@@ -1,7 +1,7 @@
|
||||
#include <furi.h>
|
||||
#include <string.h>
|
||||
|
||||
void application_uart_write(void* p) {
|
||||
int32_t application_uart_write(void* p) {
|
||||
// Red led for showing progress
|
||||
GpioPin led = {.pin = GPIO_PIN_8, .port = GPIOA};
|
||||
// TODO open record
|
||||
@@ -29,4 +29,6 @@ void application_uart_write(void* p) {
|
||||
// delay with overall perion of 1s
|
||||
delay(950);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@@ -21,7 +21,7 @@ static void button_handler(const void* value, void* _ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
void application_vibro(void* p) {
|
||||
int32_t application_vibro(void* p) {
|
||||
Ctx ctx = {.led = (GpioPin*)&led_gpio[1], .vibro = (GpioPin*)&vibro_gpio};
|
||||
|
||||
gpio_init(ctx.led, GpioModeOutputOpenDrain);
|
||||
@@ -37,4 +37,6 @@ void application_vibro(void* p) {
|
||||
while(1) {
|
||||
osDelay(osWaitForever);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
Submodule applications/floopper-bloopper updated: 598edd5419...a68a7eb200
@@ -57,7 +57,7 @@ static void input_callback(InputEvent* input_event, void* ctx) {
|
||||
osMessageQueuePut(event_queue, &event, 0, 0);
|
||||
}
|
||||
|
||||
void app_gpio_test(void* p) {
|
||||
int32_t app_gpio_test(void* p) {
|
||||
osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(AppEvent), NULL);
|
||||
furi_check(event_queue);
|
||||
|
||||
@@ -67,7 +67,7 @@ void app_gpio_test(void* p) {
|
||||
ValueMutex state_mutex;
|
||||
if(!init_mutex(&state_mutex, &_state, sizeof(State))) {
|
||||
printf("[gpio-tester] cannot create mutex\r\n");
|
||||
furiac_exit(NULL);
|
||||
return 255;
|
||||
}
|
||||
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
@@ -98,7 +98,7 @@ void app_gpio_test(void* p) {
|
||||
printf("[gpio-tester] bye!\r\n");
|
||||
// TODO remove all view_ports create by app
|
||||
view_port_enabled_set(view_port, false);
|
||||
furiac_exit(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(event.value.input.type == InputTypeShort &&
|
||||
@@ -130,4 +130,6 @@ void app_gpio_test(void* p) {
|
||||
release_mutex(&state_mutex, state);
|
||||
view_port_update(view_port);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -92,7 +92,7 @@ void text_input_callback(void* context, char* text) {
|
||||
next_view(context);
|
||||
}
|
||||
|
||||
void gui_test(void* param) {
|
||||
int32_t gui_test(void* param) {
|
||||
(void)param;
|
||||
GuiTester* gui_tester = gui_test_alloc();
|
||||
|
||||
@@ -154,4 +154,6 @@ void gui_test(void* param) {
|
||||
while(1) {
|
||||
osDelay(1000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@@ -280,7 +280,7 @@ Gui* gui_alloc() {
|
||||
return gui;
|
||||
}
|
||||
|
||||
void gui_task(void* p) {
|
||||
int32_t gui_task(void* p) {
|
||||
Gui* gui = gui_alloc();
|
||||
|
||||
furi_record_create("gui", gui);
|
||||
@@ -302,4 +302,6 @@ void gui_task(void* p) {
|
||||
gui_redraw(gui);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -23,7 +23,7 @@ void AppiButton::run() {
|
||||
gpio_init(red_led_record, GpioModeOutputOpenDrain);
|
||||
gpio_init(green_led_record, GpioModeOutputOpenDrain);
|
||||
|
||||
api_hal_timebase_insomnia_enter();
|
||||
api_hal_power_insomnia_enter();
|
||||
app_ready();
|
||||
|
||||
AppiButtonEvent event;
|
||||
@@ -35,9 +35,9 @@ void AppiButton::run() {
|
||||
event.value.input.key == InputKeyBack) {
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
api_hal_timebase_insomnia_exit();
|
||||
api_hal_power_insomnia_exit();
|
||||
|
||||
osThreadExit();
|
||||
return;
|
||||
}
|
||||
|
||||
if(event.value.input.type == InputTypeShort &&
|
||||
@@ -174,7 +174,8 @@ void AppiButton::switch_to_mode(uint8_t mode_index) {
|
||||
}
|
||||
|
||||
// app enter function
|
||||
extern "C" void app_ibutton(void* p) {
|
||||
extern "C" int32_t app_ibutton(void* p) {
|
||||
AppiButton* app = new AppiButton();
|
||||
app->run();
|
||||
return 0;
|
||||
}
|
@@ -18,7 +18,7 @@ void input_isr(void* _pin, void* _ctx) {
|
||||
osThreadFlagsSet(input->thread, INPUT_THREAD_FLAG_ISR);
|
||||
}
|
||||
|
||||
void input_task() {
|
||||
int32_t input_task() {
|
||||
input = furi_alloc(sizeof(Input));
|
||||
input->thread = osThreadGetId();
|
||||
init_pubsub(&input->event_pubsub);
|
||||
@@ -69,4 +69,6 @@ void input_task() {
|
||||
osThreadFlagsWait(INPUT_THREAD_FLAG_ISR, osFlagsWaitAny, osWaitForever);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -234,7 +234,7 @@ void init_packet(
|
||||
state->packets[index].command = command;
|
||||
}
|
||||
|
||||
void irda(void* p) {
|
||||
int32_t irda(void* p) {
|
||||
osMessageQueueId_t event_queue = osMessageQueueNew(32, sizeof(AppEvent), NULL);
|
||||
|
||||
State _state;
|
||||
@@ -262,7 +262,7 @@ void irda(void* p) {
|
||||
ValueMutex state_mutex;
|
||||
if(!init_mutex(&state_mutex, &_state, sizeof(State))) {
|
||||
printf("cannot create mutex\r\n");
|
||||
furiac_exit(NULL);
|
||||
return 255;
|
||||
}
|
||||
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
@@ -316,7 +316,7 @@ void irda(void* p) {
|
||||
osMessageQueueDelete(event_queue);
|
||||
|
||||
// exit
|
||||
furiac_exit(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(event.value.input.type == InputTypeShort &&
|
||||
|
@@ -160,7 +160,7 @@ static void extract_data(uint8_t* buf, uint8_t* customer, uint32_t* em_data) {
|
||||
*em_data = data;
|
||||
}
|
||||
|
||||
void lf_rfid_workaround(void* p) {
|
||||
int32_t lf_rfid_workaround(void* p) {
|
||||
osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(AppEvent), NULL);
|
||||
|
||||
// create pin
|
||||
@@ -195,7 +195,7 @@ void lf_rfid_workaround(void* p) {
|
||||
ValueMutex state_mutex;
|
||||
if(!init_mutex(&state_mutex, &_state, sizeof(State))) {
|
||||
printf("cannot create mutex\r\n");
|
||||
furiac_exit(NULL);
|
||||
return 255;
|
||||
}
|
||||
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
@@ -293,7 +293,7 @@ void lf_rfid_workaround(void* p) {
|
||||
|
||||
// TODO remove all view_ports create by app
|
||||
view_port_enabled_set(view_port, false);
|
||||
furiac_exit(NULL);
|
||||
return 255;
|
||||
}
|
||||
|
||||
if(event.value.input.type == InputTypePress &&
|
||||
@@ -356,4 +356,6 @@ void lf_rfid_workaround(void* p) {
|
||||
release_mutex(&state_mutex, state);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -35,7 +35,7 @@ ValueMutex* menu_init() {
|
||||
ValueMutex* menu_mutex = furi_alloc(sizeof(ValueMutex));
|
||||
if(menu_mutex == NULL || !init_mutex(menu_mutex, menu, sizeof(Menu))) {
|
||||
printf("[menu_task] cannot create menu mutex\r\n");
|
||||
furiac_exit(NULL);
|
||||
furi_check(0);
|
||||
}
|
||||
|
||||
// OpenGui record
|
||||
@@ -223,7 +223,7 @@ void menu_exit(Menu* menu) {
|
||||
menu_update(menu);
|
||||
}
|
||||
|
||||
void menu_task(void* p) {
|
||||
int32_t menu_task(void* p) {
|
||||
ValueMutex* menu_mutex = menu_init();
|
||||
|
||||
MenuEvent* menu_event = NULL;
|
||||
@@ -267,4 +267,6 @@ void menu_task(void* p) {
|
||||
|
||||
release_mutex(menu_mutex, menu);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -356,7 +356,7 @@ void music_player_thread(void* p) {
|
||||
}
|
||||
}
|
||||
|
||||
void music_player(void* p) {
|
||||
int32_t music_player(void* p) {
|
||||
osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(MusicDemoEvent), NULL);
|
||||
|
||||
State _state;
|
||||
@@ -370,7 +370,7 @@ void music_player(void* p) {
|
||||
ValueMutex state_mutex;
|
||||
if(!init_mutex(&state_mutex, &_state, sizeof(State))) {
|
||||
printf("cannot create mutex\r\n");
|
||||
furiac_exit(NULL);
|
||||
return 255;
|
||||
}
|
||||
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
@@ -394,7 +394,7 @@ void music_player(void* p) {
|
||||
|
||||
if(player == NULL) {
|
||||
printf("cannot create player thread\r\n");
|
||||
furiac_exit(NULL);
|
||||
return 255;
|
||||
}
|
||||
|
||||
MusicDemoEvent event;
|
||||
@@ -449,4 +449,6 @@ void music_player(void* p) {
|
||||
view_port_update(view_port);
|
||||
release_mutex(&state_mutex, state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -100,7 +100,7 @@ void nfc_start(Nfc* nfc, NfcView view_id, NfcWorkerState worker_state) {
|
||||
}
|
||||
}
|
||||
|
||||
void nfc_task(void* p) {
|
||||
int32_t nfc_task(void* p) {
|
||||
Nfc* nfc = nfc_alloc();
|
||||
|
||||
Gui* gui = furi_record_open("gui");
|
||||
@@ -142,4 +142,6 @@ void nfc_task(void* p) {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -41,4 +41,4 @@ void nfc_menu_field_callback(void* context);
|
||||
|
||||
void nfc_start(Nfc* nfc, NfcView view_id, NfcWorkerState worker_state);
|
||||
|
||||
void nfc_task(void* p);
|
||||
int32_t nfc_task(void* p);
|
@@ -55,7 +55,7 @@ void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state) {
|
||||
void nfc_worker_task(void* context) {
|
||||
NfcWorker* nfc_worker = context;
|
||||
|
||||
api_hal_timebase_insomnia_enter();
|
||||
api_hal_power_insomnia_enter();
|
||||
|
||||
rfalLowPowerModeStop();
|
||||
if(nfc_worker->state == NfcWorkerStatePoll) {
|
||||
@@ -69,7 +69,7 @@ void nfc_worker_task(void* context) {
|
||||
|
||||
nfc_worker_change_state(nfc_worker, NfcWorkerStateReady);
|
||||
|
||||
api_hal_timebase_insomnia_exit();
|
||||
api_hal_power_insomnia_exit();
|
||||
osThreadExit();
|
||||
}
|
||||
|
||||
|
@@ -177,7 +177,7 @@ void power_cli_otg_off(string_t args, void* context) {
|
||||
api_hal_power_disable_otg();
|
||||
}
|
||||
|
||||
void power_task(void* p) {
|
||||
int32_t power_task(void* p) {
|
||||
(void)p;
|
||||
Power* power = power_alloc();
|
||||
|
||||
@@ -223,4 +223,6 @@ void power_task(void* p) {
|
||||
view_port_enabled_set(power->usb_view_port, api_hal_power_is_charging());
|
||||
osDelay(1024);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -904,7 +904,8 @@ void SdTest::render(Canvas* canvas) {
|
||||
}
|
||||
|
||||
// app enter function
|
||||
extern "C" void sd_card_test(void* p) {
|
||||
extern "C" int32_t sd_card_test(void* p) {
|
||||
SdTest* app = new SdTest();
|
||||
app->run();
|
||||
return 0;
|
||||
}
|
@@ -101,9 +101,7 @@ SdApp* sd_app_alloc() {
|
||||
SdApp* sd_app = furi_alloc(sizeof(SdApp));
|
||||
|
||||
// init inner fs data
|
||||
if(!_fs_init(&sd_app->info)) {
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
furi_check(_fs_init(&sd_app->info));
|
||||
|
||||
sd_app->event_queue = osMessageQueueNew(8, sizeof(InputEvent), NULL);
|
||||
|
||||
@@ -476,7 +474,7 @@ static void cli_sd_info(string_t args, void* _ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
void sd_filesystem(void* p) {
|
||||
int32_t sd_filesystem(void* p) {
|
||||
SdApp* sd_app = sd_app_alloc();
|
||||
FS_Api* fs_api = fs_api_alloc();
|
||||
|
||||
@@ -555,4 +553,6 @@ void sd_filesystem(void* p) {
|
||||
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
@@ -161,7 +161,8 @@ void AppSdNFC::blink_green() {
|
||||
}
|
||||
|
||||
// app enter function
|
||||
extern "C" void sdnfc(void* p) {
|
||||
extern "C" int32_t sdnfc(void* p) {
|
||||
AppSdNFC* app = new AppSdNFC();
|
||||
app->run();
|
||||
return 0;
|
||||
}
|
@@ -37,7 +37,7 @@ static void input_callback(InputEvent* input_event, void* ctx) {
|
||||
osMessageQueuePut(event_queue, &event, 0, 0);
|
||||
}
|
||||
|
||||
void template_app(void* p) {
|
||||
int32_t template_app(void* p) {
|
||||
osMessageQueueId_t event_queue = osMessageQueueNew(8, sizeof(Event), NULL);
|
||||
|
||||
State _state;
|
||||
@@ -45,7 +45,7 @@ void template_app(void* p) {
|
||||
ValueMutex state_mutex;
|
||||
if(!init_mutex(&state_mutex, &_state, sizeof(State))) {
|
||||
printf("cannot create mutex\r\n");
|
||||
furiac_exit(NULL);
|
||||
return 255;
|
||||
}
|
||||
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
@@ -57,7 +57,7 @@ void template_app(void* p) {
|
||||
Gui* gui = furi_record_open("gui");
|
||||
if(gui == NULL) {
|
||||
printf("gui is not available\r\n");
|
||||
furiac_exit(NULL);
|
||||
return 255;
|
||||
}
|
||||
gui_add_view_port(gui, view_port, /* specify UI layer */);
|
||||
|
||||
@@ -99,4 +99,6 @@ void template_app(void* p) {
|
||||
|
||||
release_mutex(&state_mutex, state);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1,33 +0,0 @@
|
||||
#include <furi.h>
|
||||
#include "minunit.h"
|
||||
|
||||
static void furi_concurent_app(void* p) {
|
||||
Event* event = p;
|
||||
|
||||
signal_event(event);
|
||||
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
|
||||
void test_furi_event() {
|
||||
mu_assert(false, "please reimplement or delete test");
|
||||
|
||||
/*Event event;
|
||||
|
||||
mu_check(init_event(&event));
|
||||
|
||||
// The event should not be signalled right after creation
|
||||
mu_check(!wait_event_with_timeout(&event, 100));
|
||||
|
||||
// Create second app
|
||||
FuriApp* second_app __attribute__((unused)) =
|
||||
furiac_start(furi_concurent_app, "furi concurent app", (void*)&event);
|
||||
|
||||
// The event should be signalled now
|
||||
mu_check(wait_event_with_timeout(&event, 100));
|
||||
|
||||
// The event should not be signalled once it's processed
|
||||
mu_check(!wait_event_with_timeout(&event, 100));
|
||||
|
||||
mu_check(delete_event(&event));*/
|
||||
}
|
@@ -1,145 +0,0 @@
|
||||
#include <furi.h>
|
||||
#include "minunit.h"
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint8_t red;
|
||||
uint8_t green;
|
||||
uint8_t blue;
|
||||
} Rgb;
|
||||
|
||||
static uint32_t rgb_final_state;
|
||||
|
||||
static void rgb_clear(void* ctx, void* state) {
|
||||
Rgb* rgb = state;
|
||||
rgb->red = 0;
|
||||
rgb->green = 0;
|
||||
rgb->blue = 0;
|
||||
}
|
||||
|
||||
static void rgb_commit(void* ctx, void* state) {
|
||||
Rgb* rgb = state;
|
||||
rgb_final_state = ((uint32_t)rgb->red) | (((uint32_t)rgb->green) << 8) |
|
||||
(((uint32_t)rgb->blue) << 16);
|
||||
}
|
||||
|
||||
static void set_red_composer(void* ctx, void* state) {
|
||||
Rgb* rgb = state;
|
||||
uint8_t* red = ctx;
|
||||
|
||||
rgb->red = *red;
|
||||
}
|
||||
|
||||
void test_furi_value_composer() {
|
||||
Rgb rgb = {0, 0, 0};
|
||||
ValueComposer composer;
|
||||
Rgb layer1_rgb = {0, 0, 0};
|
||||
ValueMutex layer1_mutex;
|
||||
uint8_t layer2_red = 0;
|
||||
|
||||
rgb_final_state = 0xdeadbeef;
|
||||
|
||||
mu_check(init_composer(&composer, &rgb));
|
||||
|
||||
mu_check(init_mutex(&layer1_mutex, &layer1_rgb, sizeof(layer1_rgb)));
|
||||
|
||||
perform_compose(&composer, rgb_clear, rgb_commit, NULL);
|
||||
mu_assert_int_eq(0xdeadbeef, rgb_final_state);
|
||||
|
||||
ValueComposerHandle* layer1_handle =
|
||||
add_compose_layer(&composer, COPY_COMPOSE, &layer1_mutex, UiLayerNotify);
|
||||
mu_assert_pointers_not_eq(layer1_handle, NULL);
|
||||
|
||||
// RGB state should be updated with the layer1 state
|
||||
perform_compose(&composer, rgb_clear, rgb_commit, NULL);
|
||||
mu_assert_int_eq(0x000000, rgb_final_state);
|
||||
|
||||
layer2_red = 0xcc;
|
||||
ValueComposerHandle* layer2_handle =
|
||||
add_compose_layer(&composer, set_red_composer, &layer2_red, UiLayerAboveNotify);
|
||||
mu_assert_pointers_not_eq(layer2_handle, NULL);
|
||||
|
||||
// RGB state should be updated with the layer1 and layer2 state, in order
|
||||
perform_compose(&composer, rgb_clear, rgb_commit, NULL);
|
||||
mu_assert_int_eq(0x0000cc, rgb_final_state);
|
||||
|
||||
// Change layer1 state
|
||||
Rgb* state = acquire_mutex(&layer1_mutex, 0);
|
||||
mu_assert_pointers_not_eq(state, NULL);
|
||||
state->red = 0x12;
|
||||
state->green = 0x34;
|
||||
state->blue = 0x56;
|
||||
release_mutex(&layer1_mutex, state);
|
||||
|
||||
// Nothing should happen, we need to trigger composition request first
|
||||
perform_compose(&composer, rgb_clear, rgb_commit, NULL);
|
||||
mu_assert_int_eq(0x0000cc, rgb_final_state);
|
||||
|
||||
request_compose(layer1_handle);
|
||||
|
||||
perform_compose(&composer, rgb_clear, rgb_commit, NULL);
|
||||
mu_assert_int_eq(0x5634cc, rgb_final_state);
|
||||
|
||||
// Change layer2 state
|
||||
layer2_red = 0xff;
|
||||
|
||||
// Nothing should happen, we need to trigger composition request first
|
||||
perform_compose(&composer, rgb_clear, rgb_commit, NULL);
|
||||
mu_assert_int_eq(0x5634cc, rgb_final_state);
|
||||
|
||||
request_compose(layer2_handle);
|
||||
|
||||
perform_compose(&composer, rgb_clear, rgb_commit, NULL);
|
||||
mu_assert_int_eq(0x5634ff, rgb_final_state);
|
||||
|
||||
// Remove layer1
|
||||
mu_check(remove_compose_layer(layer1_handle));
|
||||
|
||||
perform_compose(&composer, rgb_clear, rgb_commit, NULL);
|
||||
mu_assert_int_eq(0x0000ff, rgb_final_state);
|
||||
|
||||
// Remove layer2
|
||||
mu_check(remove_compose_layer(layer2_handle));
|
||||
|
||||
perform_compose(&composer, rgb_clear, rgb_commit, NULL);
|
||||
mu_assert_int_eq(0x000000, rgb_final_state);
|
||||
|
||||
mu_check(delete_composer(&composer));
|
||||
}
|
||||
|
||||
static const uint32_t notify_value_0 = 0x12345678;
|
||||
static const uint32_t notify_value_1 = 0x11223344;
|
||||
|
||||
static uint32_t pubsub_value = 0;
|
||||
|
||||
void test_value_manager_handler(const void* arg, void* ctx) {
|
||||
pubsub_value = *(uint32_t*)arg;
|
||||
}
|
||||
|
||||
void test_furi_value_manager() {
|
||||
uint32_t value = 0;
|
||||
ValueManager managed;
|
||||
|
||||
mu_check(init_managed(&managed, &value, sizeof(value)));
|
||||
|
||||
pubsub_value = 0;
|
||||
|
||||
PubSubItem* test_pubsub_item;
|
||||
test_pubsub_item = subscribe_pubsub(&managed.pubsub, test_value_manager_handler, 0);
|
||||
mu_assert_pointers_not_eq(test_pubsub_item, NULL);
|
||||
|
||||
mu_check(write_managed(&managed, (void*)¬ify_value_0, sizeof(notify_value_0), 100));
|
||||
|
||||
mu_assert_int_eq(pubsub_value, notify_value_0);
|
||||
|
||||
uint32_t* ptr = acquire_mutex(&managed.value, 100);
|
||||
mu_assert_pointers_not_eq(ptr, NULL);
|
||||
|
||||
*ptr = notify_value_1;
|
||||
|
||||
mu_check(commit_managed(&managed, ptr));
|
||||
|
||||
mu_assert_int_eq(pubsub_value, notify_value_1);
|
||||
|
||||
mu_check(delete_managed(&managed));
|
||||
}
|
@@ -60,7 +60,7 @@ void furi_concurent_app(void* p) {
|
||||
ValueMutex* mutex = (ValueMutex*)p;
|
||||
if(mutex == NULL) {
|
||||
printf("cannot open mutex\r\n");
|
||||
furiac_exit(NULL);
|
||||
osThreadExit();
|
||||
}
|
||||
|
||||
for(size_t i = 0; i < 10; i++) {
|
||||
@@ -69,7 +69,7 @@ void furi_concurent_app(void* p) {
|
||||
if(value == NULL) {
|
||||
printf("cannot take record\r\n");
|
||||
release_mutex(mutex, value);
|
||||
furiac_exit(NULL);
|
||||
osThreadExit();
|
||||
}
|
||||
|
||||
// emulate read-modify-write broken by context switching
|
||||
@@ -83,7 +83,7 @@ void furi_concurent_app(void* p) {
|
||||
release_mutex(mutex, value);
|
||||
}
|
||||
|
||||
furiac_exit(NULL);
|
||||
osThreadExit();
|
||||
}
|
||||
|
||||
void test_furi_concurrent_access() {
|
||||
|
@@ -1,134 +0,0 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <furi.h>
|
||||
|
||||
/*
|
||||
Test: creating and killing task
|
||||
|
||||
1. create task
|
||||
2. delay 10 ms
|
||||
3. kill task
|
||||
4. check that value changes
|
||||
5. delay 2 ms
|
||||
6. check that value stay unchanged
|
||||
*/
|
||||
|
||||
void create_kill_app(void* p) {
|
||||
// this app simply increase counter
|
||||
uint8_t* counter = (uint8_t*)p;
|
||||
while(1) {
|
||||
*counter = *counter + 1;
|
||||
delay(1);
|
||||
}
|
||||
}
|
||||
|
||||
bool test_furi_ac_create_kill() {
|
||||
mu_assert(false, "please reimplement or delete test");
|
||||
/*
|
||||
uint8_t counter = 0;
|
||||
|
||||
uint8_t value_a = counter;
|
||||
|
||||
FuriApp* widget = furiac_start(create_kill_app, "create_kill_app", (void*)&counter);
|
||||
if(widget == NULL) {
|
||||
printf("create widget fail\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
delay(10);
|
||||
|
||||
if(!furiac_kill(widget)) {
|
||||
printf("kill widget fail\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(value_a == counter) {
|
||||
printf("counter unchanged\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
value_a = counter;
|
||||
|
||||
delay(10);
|
||||
|
||||
if(value_a != counter) {
|
||||
printf("counter changes after kill (counter = %d vs %d)\n", value_a, counter);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
Test: switch between tasks
|
||||
1. init s
|
||||
2. create task A, add 'A" to sequence'
|
||||
3. switch to task B, add 'B' to sequence
|
||||
4. exit from task B -> switch to A and add 'A' to sequence
|
||||
5. cleanup: exit from task A
|
||||
6. check sequence
|
||||
*/
|
||||
|
||||
#define TEST_SWITCH_CONTEXT_SEQ_SIZE 8
|
||||
|
||||
typedef struct {
|
||||
char sequence[TEST_SWITCH_CONTEXT_SEQ_SIZE];
|
||||
size_t count;
|
||||
} TestSwitchSequence;
|
||||
|
||||
void task_a(void*);
|
||||
void task_b(void*);
|
||||
|
||||
void task_a(void* p) {
|
||||
// simply starts, add 'A' letter to sequence and switch
|
||||
// if sequence counter = 0, call task B, exit otherwise
|
||||
|
||||
TestSwitchSequence* seq = (TestSwitchSequence*)p;
|
||||
|
||||
seq->sequence[seq->count] = 'A';
|
||||
seq->count++;
|
||||
|
||||
if(seq->count == 1) {
|
||||
furiac_switch(task_b, "task B", p);
|
||||
|
||||
// if switch unsuccessfull, this code will executed
|
||||
seq->sequence[seq->count] = 'x';
|
||||
seq->count++;
|
||||
} else {
|
||||
// add '/' symbol on exit
|
||||
seq->sequence[seq->count] = '/';
|
||||
seq->count++;
|
||||
furiac_exit(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
// application simply add 'B' end exit
|
||||
void task_b(void* p) {
|
||||
TestSwitchSequence* seq = (TestSwitchSequence*)p;
|
||||
|
||||
seq->sequence[seq->count] = 'B';
|
||||
seq->count++;
|
||||
|
||||
furiac_exit(p);
|
||||
}
|
||||
|
||||
bool test_furi_ac_switch_exit() {
|
||||
// init sequence
|
||||
TestSwitchSequence seq;
|
||||
seq.count = 0;
|
||||
|
||||
furiac_start(task_a, "task A", (void*)&seq);
|
||||
// TODO how to check that all child task ends?
|
||||
|
||||
delay(10); // wait while task do its work
|
||||
|
||||
seq.sequence[seq.count] = '\0';
|
||||
|
||||
if(strcmp(seq.sequence, "ABA/") != 0) {
|
||||
printf("wrong sequence: %s\n", seq.sequence);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@@ -3,17 +3,11 @@
|
||||
#include "minunit_vars.h"
|
||||
#include "minunit.h"
|
||||
|
||||
bool test_furi_ac_create_kill();
|
||||
bool test_furi_ac_switch_exit();
|
||||
|
||||
// v2 tests
|
||||
void test_furi_create_open();
|
||||
void test_furi_valuemutex();
|
||||
void test_furi_concurrent_access();
|
||||
void test_furi_pubsub();
|
||||
void test_furi_value_composer();
|
||||
void test_furi_value_manager();
|
||||
void test_furi_event();
|
||||
|
||||
void test_furi_memmgr();
|
||||
|
||||
@@ -31,14 +25,6 @@ MU_TEST(test_check) {
|
||||
mu_check(foo != 6);
|
||||
}
|
||||
|
||||
MU_TEST(mu_test_furi_ac_create_kill) {
|
||||
mu_assert_int_eq(test_furi_ac_create_kill(), true);
|
||||
}
|
||||
|
||||
MU_TEST(mu_test_furi_ac_switch_exit) {
|
||||
mu_assert_int_eq(test_furi_ac_switch_exit(), true);
|
||||
}
|
||||
|
||||
// v2 tests
|
||||
MU_TEST(mu_test_furi_create_open) {
|
||||
test_furi_create_open();
|
||||
@@ -62,30 +48,16 @@ MU_TEST(mu_test_furi_memmgr) {
|
||||
test_furi_memmgr();
|
||||
}
|
||||
|
||||
MU_TEST(mu_test_furi_value_expanders) {
|
||||
test_furi_value_composer();
|
||||
test_furi_value_manager();
|
||||
}
|
||||
|
||||
MU_TEST(mu_test_furi_event) {
|
||||
test_furi_event();
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(test_suite) {
|
||||
MU_SUITE_CONFIGURE(&test_setup, &test_teardown);
|
||||
|
||||
MU_RUN_TEST(test_check);
|
||||
MU_RUN_TEST(mu_test_furi_ac_create_kill);
|
||||
MU_RUN_TEST(mu_test_furi_ac_switch_exit);
|
||||
|
||||
// v2 tests
|
||||
MU_RUN_TEST(mu_test_furi_create_open);
|
||||
MU_RUN_TEST(mu_test_furi_valuemutex);
|
||||
MU_RUN_TEST(mu_test_furi_concurrent_access);
|
||||
MU_RUN_TEST(mu_test_furi_pubsub);
|
||||
MU_RUN_TEST(mu_test_furi_value_expanders);
|
||||
MU_RUN_TEST(mu_test_furi_event);
|
||||
|
||||
MU_RUN_TEST(mu_test_furi_memmgr);
|
||||
}
|
||||
|
||||
|
@@ -5,7 +5,7 @@
|
||||
|
||||
int run_minunit();
|
||||
|
||||
void flipper_test_app(void* p) {
|
||||
int32_t flipper_test_app(void* p) {
|
||||
// create pins
|
||||
GpioPin red = {.pin = LED_RED_Pin, .port = LED_RED_GPIO_Port};
|
||||
GpioPin green = {.pin = LED_GREEN_Pin, .port = LED_GREEN_GPIO_Port};
|
||||
@@ -38,7 +38,5 @@ void flipper_test_app(void* p) {
|
||||
gpio_write(blue_record, true);
|
||||
}
|
||||
|
||||
set_exitcode(exitcode);
|
||||
|
||||
furiac_exit(NULL);
|
||||
return 0;
|
||||
}
|
Reference in New Issue
Block a user