diff --git a/applications/app-loader/app-loader.c b/applications/app-loader/app-loader.c index 09c444255..401a78a2b 100644 --- a/applications/app-loader/app-loader.c +++ b/applications/app-loader/app-loader.c @@ -1,4 +1,5 @@ #include "flipper_v2.h" +#include #include #include "menu/menu.h" #include "menu/menu_item.h" @@ -52,6 +53,21 @@ static void handle_menu(void* _ctx) { ctx->state->handler = furiac_start(ctx->app->app, ctx->app->name, NULL); } +static void handle_cli(string_t args, void* _ctx) { + AppLoaderContext* ctx = (AppLoaderContext*)_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); + + cli_print("Press any key to kill application"); + + char c; + cli_read(&c, 1); + furiac_kill(ctx->state->handler); +} + void app_loader(void* p) { osThreadId_t self_id = osThreadGetId(); furi_check(self_id); @@ -72,6 +88,8 @@ void app_loader(void* p) { furiac_exit(NULL); } + Cli* cli = furi_open("cli"); + // Open GUI and register widget GuiApi* gui = furi_open("gui"); if(gui == NULL) { @@ -93,20 +111,16 @@ void app_loader(void* p) { state.menu_plugins, menu_item_alloc_function( FLIPPER_APPS[i].name, assets_icons_get(A_Infrared_14), handle_menu, ctx)); - } - /* - menu_item_add(menu, menu_item_alloc_function("Sub 1 gHz", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("125 kHz RFID", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("Infrared", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("I-Button", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("USB", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("Bluetooth", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("GPIO / HW", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("U2F", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("Tamagotchi", NULL, NULL, NULL)); - menu_item_add(menu, menu_item_alloc_function("Plugins", NULL, NULL, NULL)); - */ + // 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); + } + } } with_value_mutex( diff --git a/applications/applications.h b/applications/applications.h index 79ff55803..a210efbf4 100644 --- a/applications/applications.h +++ b/applications/applications.h @@ -67,7 +67,7 @@ const FlipperStartupApp FLIPPER_STARTUP[] = { #ifdef APP_MENU {.app = menu_task, .name = "menu_task", .libs = {1, FURI_LIB{"gui_task"}}}, - {.app = app_loader, .name = "app_loader", .libs = {1, FURI_LIB{"menu_task"}}}, + {.app = app_loader, .name = "app_loader", .libs = {2, FURI_LIB{"menu_task", "cli_task"}}}, #endif #ifdef APP_IRUKAGOTCHI diff --git a/applications/cli/cli.c b/applications/cli/cli.c index f6fdfb1d7..befebf082 100644 --- a/applications/cli/cli.c +++ b/applications/cli/cli.c @@ -20,6 +20,7 @@ void cli_free(Cli* cli) { } void cli_reset_state(Cli* cli) { + // Release allocated buffer, reset state string_clear(cli->line); string_init(cli->line); } @@ -28,6 +29,10 @@ void cli_putc(char c) { api_hal_vcp_tx((uint8_t*)&c, 1); } +void cli_read(char* buffer, size_t size) { + api_hal_vcp_rx((uint8_t*)buffer, size); +} + void cli_print(const char* str) { api_hal_vcp_tx((uint8_t*)str, strlen(str)); } @@ -103,6 +108,7 @@ void cli_enter(Cli* cli) { cli_putc(CliSymbolAsciiBell); } + string_clear(command); // Always finish with clean state cli_reset_state(cli); } @@ -145,6 +151,13 @@ void cli_process_input(Cli* cli) { void cli_add_command(Cli* cli, const char* name, CliCallback callback, void* context) { string_t name_str; string_init_set_str(name_str, name); + string_strim(name_str); + + size_t name_replace; + do { + name_replace = string_replace_str(name_str, " ", "_"); + } while(name_replace != STRING_FAILURE); + CliCommand c; c.callback = callback; c.context = context; @@ -152,6 +165,8 @@ void cli_add_command(Cli* cli, const char* name, CliCallback callback, void* con furi_check(osMutexAcquire(cli->mutex, osWaitForever) == osOK); CliCommandDict_set_at(cli->commands, name_str, c); furi_check(osMutexRelease(cli->mutex) == osOK); + + string_clear(name_str); } void cli_task(void* p) { diff --git a/applications/power/power.c b/applications/power/power.c index bf4789f9e..6dabe3557 100644 --- a/applications/power/power.c +++ b/applications/power/power.c @@ -87,17 +87,32 @@ void power_free(Power* power) { } void power_cli_poweroff(string_t args, void* context) { - cli_print("Poweroff in 5 seconds"); - osDelay(5000); + cli_print("Poweroff in 3 seconds"); + osDelay(3000); api_hal_power_off(); } +void power_cli_reset(string_t args, void* context) { + cli_print("NVIC System Reset in 3 seconds"); + osDelay(3000); + NVIC_SystemReset(); +} + +void power_cli_dfu(string_t args, void* context) { + cli_print("NVIC System Reset to DFU mode in 3 seconds"); + api_hal_boot_set_mode(ApiHalBootModeDFU); + osDelay(3000); + NVIC_SystemReset(); +} + void power_task(void* p) { (void)p; Power* power = power_alloc(); if(power->cli) { cli_add_command(power->cli, "poweroff", power_cli_poweroff, power); + cli_add_command(power->cli, "reset", power_cli_reset, power); + cli_add_command(power->cli, "dfu", power_cli_dfu, power); } FuriRecordSubscriber* gui_record = furi_open_deprecated("gui", false, false, NULL, NULL, NULL); diff --git a/core/boot.h b/core/boot.h deleted file mode 100644 index 29b83d80d..000000000 --- a/core/boot.h +++ /dev/null @@ -1,15 +0,0 @@ -/* -Flipper devices inc. - -Bootloader API, must be implemented by target -*/ - -#ifndef __BOOT_H -#define __BOOT_H - -/* - * @brief Request DFU and reboot -*/ -void boot_restart_in_dfu(); - -#endif diff --git a/firmware/targets/Inc/api-hal-boot.h b/firmware/targets/Inc/api-hal-boot.h new file mode 100644 index 000000000..bdd0b6ea6 --- /dev/null +++ b/firmware/targets/Inc/api-hal-boot.h @@ -0,0 +1,8 @@ +#pragma once + +typedef enum { + ApiHalBootModeNormal, + ApiHalBootModeDFU +} ApiHalBootMode; + +void api_hal_boot_set_mode(ApiHalBootMode mode); diff --git a/firmware/targets/Inc/api-hal.h b/firmware/targets/Inc/api-hal.h index e91b05bd7..e2b6c701b 100644 --- a/firmware/targets/Inc/api-hal.h +++ b/firmware/targets/Inc/api-hal.h @@ -1,5 +1,6 @@ #pragma once +#include "api-hal-boot.h" #include "api-hal-gpio.h" #include "api-hal-delay.h" #include "api-hal-pwm.h" diff --git a/firmware/targets/f2/api-hal/api-hal-boot.c b/firmware/targets/f2/api-hal/api-hal-boot.c new file mode 100644 index 000000000..55eceabec --- /dev/null +++ b/firmware/targets/f2/api-hal/api-hal-boot.c @@ -0,0 +1,13 @@ +#include +#include + +#define BOOT_REQUEST_NONE 0x00000000 +#define BOOT_REQUEST_DFU 0xDF00B000 + +void api_hal_boot_set_mode(ApiHalBootMode mode) { + if (mode == ApiHalBootModeNormal) { + LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_NONE); + } else if (mode == ApiHalBootModeDFU) { + LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_DFU); + } +} \ No newline at end of file diff --git a/firmware/targets/f3/api-hal/api-hal-boot.c b/firmware/targets/f3/api-hal/api-hal-boot.c new file mode 100644 index 000000000..b47e8a8af --- /dev/null +++ b/firmware/targets/f3/api-hal/api-hal-boot.c @@ -0,0 +1,13 @@ +#include +#include + +#define BOOT_REQUEST_NONE 0x00000000 +#define BOOT_REQUEST_DFU 0xDF00B000 + +void api_hal_boot_set_mode(ApiHalBootMode mode) { + if (mode == ApiHalBootModeNormal) { + LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_NONE); + } else if (mode == ApiHalBootModeDFU) { + LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, BOOT_REQUEST_DFU); + } +} \ No newline at end of file diff --git a/lib/app-template/app-template.h b/lib/app-template/app-template.h index cca2f62f1..36937b2d6 100644 --- a/lib/app-template/app-template.h +++ b/lib/app-template/app-template.h @@ -91,7 +91,7 @@ template void AppTemplate::release_ template bool AppTemplate::get_event(TEvent* event, uint32_t timeout) { - osStatus_t event_status = osMessageQueueGet(event_queue, &event, NULL, timeout); + osStatus_t event_status = osMessageQueueGet(event_queue, event, NULL, timeout); return (event_status == osOK); }