MX 2 лет назад
Родитель
Сommit
030f928772
8 измененных файлов с 117 добавлено и 4 удалено
  1. 1 0
      application.fam
  2. 5 0
      docs/changelog.md
  3. 5 0
      esp_flasher_app.c
  4. 1 1
      esp_flasher_app.h
  5. 5 0
      esp_flasher_app_i.h
  6. 74 3
      esp_flasher_worker.c
  7. 4 0
      esp_flasher_worker.h
  8. 22 0
      scenes/esp_flasher_scene_start.c

+ 1 - 0
application.fam

@@ -1,6 +1,7 @@
 App(
 App(
     appid="esp_flasher",
     appid="esp_flasher",
     name="ESP Flasher",
     name="ESP Flasher",
+    fap_version=(1,1),
     apptype=FlipperAppType.EXTERNAL,
     apptype=FlipperAppType.EXTERNAL,
     entry_point="esp_flasher_app",
     entry_point="esp_flasher_app",
     requires=["gui"],
     requires=["gui"],

+ 5 - 0
docs/changelog.md

@@ -1,3 +1,8 @@
+## v1.1
+
+Auto-reset and notifications! For supported boards (RTS and DTR connected), flasher will now automatically enter the bootloader and reset the board. Also added notifications for user feedback (blue LED for duration of flash, vibrate when done).
+
+
 ## v1.0
 ## v1.0
 
 
 Initial ESP flasher release! Supports hardcoded addresses for bootloader, partition table, NVS, boot_app0, and firmware, with a toggle for ESP32-S3 (different bootloader address).
 Initial ESP flasher release! Supports hardcoded addresses for bootloader, partition table, NVS, boot_app0, and firmware, with a toggle for ESP32-S3 (different bootloader address).

+ 5 - 0
esp_flasher_app.c

@@ -27,6 +27,7 @@ EspFlasherApp* esp_flasher_app_alloc() {
     app->gui = furi_record_open(RECORD_GUI);
     app->gui = furi_record_open(RECORD_GUI);
     app->dialogs = furi_record_open(RECORD_DIALOGS);
     app->dialogs = furi_record_open(RECORD_DIALOGS);
     app->storage = furi_record_open(RECORD_STORAGE);
     app->storage = furi_record_open(RECORD_STORAGE);
+    app->notification = furi_record_open(RECORD_NOTIFICATION);
 
 
     app->view_dispatcher = view_dispatcher_alloc();
     app->view_dispatcher = view_dispatcher_alloc();
     app->scene_manager = scene_manager_alloc(&esp_flasher_scene_handlers, app);
     app->scene_manager = scene_manager_alloc(&esp_flasher_scene_handlers, app);
@@ -65,6 +66,9 @@ EspFlasherApp* esp_flasher_app_alloc() {
 
 
     app->flash_worker_busy = false;
     app->flash_worker_busy = false;
 
 
+    app->reset = false;
+    app->boot = false;
+
     scene_manager_next_scene(app->scene_manager, EspFlasherSceneStart);
     scene_manager_next_scene(app->scene_manager, EspFlasherSceneStart);
 
 
     return app;
     return app;
@@ -103,6 +107,7 @@ void esp_flasher_app_free(EspFlasherApp* app) {
     furi_record_close(RECORD_GUI);
     furi_record_close(RECORD_GUI);
     furi_record_close(RECORD_STORAGE);
     furi_record_close(RECORD_STORAGE);
     furi_record_close(RECORD_DIALOGS);
     furi_record_close(RECORD_DIALOGS);
+    furi_record_close(RECORD_NOTIFICATION);
 
 
     free(app);
     free(app);
 }
 }

+ 1 - 1
esp_flasher_app.h

@@ -4,7 +4,7 @@
 extern "C" {
 extern "C" {
 #endif
 #endif
 
 
-#define ESP_FLASHER_APP_VERSION "v1.0"
+#define ESP_FLASHER_APP_VERSION "v1.1"
 
 
 typedef struct EspFlasherApp EspFlasherApp;
 typedef struct EspFlasherApp EspFlasherApp;
 
 

+ 5 - 0
esp_flasher_app_i.h

@@ -20,6 +20,7 @@
 #include <storage/storage.h>
 #include <storage/storage.h>
 #include <lib/toolbox/path.h>
 #include <lib/toolbox/path.h>
 #include <dialogs/dialogs.h>
 #include <dialogs/dialogs.h>
+#include <notification/notification_messages.h>
 
 
 #define ESP_FLASHER_TEXT_BOX_STORE_SIZE (4096)
 #define ESP_FLASHER_TEXT_BOX_STORE_SIZE (4096)
 
 
@@ -47,6 +48,7 @@ struct EspFlasherApp {
     TextBox* text_box;
     TextBox* text_box;
     Storage* storage;
     Storage* storage;
     DialogsApp* dialogs;
     DialogsApp* dialogs;
+    NotificationApp* notification;
 
 
     VariableItemList* var_item_list;
     VariableItemList* var_item_list;
     Widget* widget;
     Widget* widget;
@@ -54,6 +56,9 @@ struct EspFlasherApp {
 
 
     EspFlasherUart* uart;
     EspFlasherUart* uart;
 
 
+    bool reset;
+    bool boot;
+
     bool selected_flash_options[NUM_FLASH_OPTIONS];
     bool selected_flash_options[NUM_FLASH_OPTIONS];
     int num_selected_flash_options;
     int num_selected_flash_options;
     char bin_file_path_boot[100];
     char bin_file_path_boot[100];

+ 74 - 3
esp_flasher_worker.c

@@ -131,6 +131,9 @@ static int32_t esp_flasher_flash_bin(void* context) {
     flash_rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
     flash_rx_stream = furi_stream_buffer_alloc(RX_BUF_SIZE, 1);
     timer = furi_timer_alloc(_timer_callback, FuriTimerTypePeriodic, app);
     timer = furi_timer_alloc(_timer_callback, FuriTimerTypePeriodic, app);
 
 
+    // turn on flipper blue LED for duration of flash
+    notification_message(app->notification, &sequence_set_only_blue_255);
+
     loader_port_debug_print("Connecting\n");
     loader_port_debug_print("Connecting\n");
     esp_loader_connect_args_t connect_config = ESP_LOADER_CONNECT_DEFAULT();
     esp_loader_connect_args_t connect_config = ESP_LOADER_CONNECT_DEFAULT();
     err = esp_loader_connect(&connect_config);
     err = esp_loader_connect(&connect_config);
@@ -169,9 +172,20 @@ static int32_t esp_flasher_flash_bin(void* context) {
         loader_port_debug_print("Restoring transmission rate\n");
         loader_port_debug_print("Restoring transmission rate\n");
         furi_hal_uart_set_br(FuriHalUartIdUSART1, 115200);
         furi_hal_uart_set_br(FuriHalUartIdUSART1, 115200);
 #endif
 #endif
-        loader_port_debug_print("Done flashing. Please reset the board manually.\n");
+        loader_port_debug_print("Done flashing. Please reset the board manually if it doesn't auto-reset.\n");
+
+        // auto-reset for supported boards
+        loader_port_reset_target();
+
+        // short buzz to alert user
+        notification_message(app->notification, &sequence_set_vibro_on);
+        loader_port_delay_ms(50);
+        notification_message(app->notification, &sequence_reset_vibro);
     }
     }
 
 
+    // turn off flipper blue LED
+    notification_message(app->notification, &sequence_reset_blue);
+
     // done
     // done
     app->flash_worker_busy = false;
     app->flash_worker_busy = false;
 
 
@@ -182,6 +196,48 @@ static int32_t esp_flasher_flash_bin(void* context) {
     return 0;
     return 0;
 }
 }
 
 
+static void _initDTR(void) {
+    furi_hal_gpio_init(&gpio_ext_pc3, GpioModeOutputPushPull, GpioPullDown, GpioSpeedVeryHigh);
+}
+
+static void _initRTS(void) {
+    furi_hal_gpio_init(&gpio_ext_pb2, GpioModeOutputPushPull, GpioPullDown, GpioSpeedVeryHigh);
+}
+
+static void _setDTR(bool state) {
+    furi_hal_gpio_write(&gpio_ext_pc3, state);
+}
+
+static void _setRTS(bool state) {
+    furi_hal_gpio_write(&gpio_ext_pb2, state);
+}
+
+static int32_t esp_flasher_reset(void* context) {
+    EspFlasherApp* app = (void*)context;
+
+    app->flash_worker_busy = true;
+
+    _setDTR(false);
+    _initDTR();
+    _setRTS(false);
+    _initRTS();
+
+    if (app->reset) {
+        loader_port_debug_print("Resetting board\n");
+        loader_port_reset_target();
+    } else if (app->boot) {
+        loader_port_debug_print("Entering bootloader\n");
+        loader_port_enter_bootloader();
+    }
+
+    // done
+    app->flash_worker_busy = false;
+    app->reset = false;
+    app->boot = false;
+
+    return 0;
+}
+
 void esp_flasher_worker_start_thread(EspFlasherApp* app) {
 void esp_flasher_worker_start_thread(EspFlasherApp* app) {
     global_app = app;
     global_app = app;
 
 
@@ -189,7 +245,11 @@ void esp_flasher_worker_start_thread(EspFlasherApp* app) {
     furi_thread_set_name(app->flash_worker, "EspFlasherFlashWorker");
     furi_thread_set_name(app->flash_worker, "EspFlasherFlashWorker");
     furi_thread_set_stack_size(app->flash_worker, 2048);
     furi_thread_set_stack_size(app->flash_worker, 2048);
     furi_thread_set_context(app->flash_worker, app);
     furi_thread_set_context(app->flash_worker, app);
-    furi_thread_set_callback(app->flash_worker, esp_flasher_flash_bin);
+    if (app->reset || app->boot) {
+        furi_thread_set_callback(app->flash_worker, esp_flasher_reset);
+    } else {
+        furi_thread_set_callback(app->flash_worker, esp_flasher_flash_bin);
+    }
     furi_thread_start(app->flash_worker);
     furi_thread_start(app->flash_worker);
 }
 }
 
 
@@ -213,8 +273,19 @@ esp_loader_error_t loader_port_write(const uint8_t* data, uint16_t size, uint32_
     return ESP_LOADER_SUCCESS;
     return ESP_LOADER_SUCCESS;
 }
 }
 
 
+void loader_port_reset_target(void) {
+    _setDTR(true);
+    loader_port_delay_ms(SERIAL_FLASHER_RESET_HOLD_TIME_MS);
+    _setDTR(false);
+}
+
 void loader_port_enter_bootloader(void) {
 void loader_port_enter_bootloader(void) {
-    // unimplemented
+    _setDTR(true);
+    loader_port_delay_ms(SERIAL_FLASHER_RESET_HOLD_TIME_MS);
+    _setRTS(true);
+    _setDTR(false);
+    loader_port_delay_ms(SERIAL_FLASHER_BOOT_HOLD_TIME_MS);
+    _setRTS(false);
 }
 }
 
 
 void loader_port_delay_ms(uint32_t ms) {
 void loader_port_delay_ms(uint32_t ms) {

+ 4 - 0
esp_flasher_worker.h

@@ -2,7 +2,11 @@
 
 
 #include "esp_flasher_app_i.h"
 #include "esp_flasher_app_i.h"
 #include "esp_flasher_uart.h"
 #include "esp_flasher_uart.h"
+#ifndef SERIAL_FLASHER_INTERFACE_UART
 #define SERIAL_FLASHER_INTERFACE_UART /* TODO why is application.fam not passing this via cdefines */
 #define SERIAL_FLASHER_INTERFACE_UART /* TODO why is application.fam not passing this via cdefines */
+#endif
+#define SERIAL_FLASHER_RESET_HOLD_TIME_MS 100
+#define SERIAL_FLASHER_BOOT_HOLD_TIME_MS 50
 #include "esp_loader_io.h"
 #include "esp_loader_io.h"
 
 
 #define ESP_ADDR_BOOT_S3 0x0
 #define ESP_ADDR_BOOT_S3 0x0

+ 22 - 0
scenes/esp_flasher_scene_start.c

@@ -3,6 +3,8 @@
 enum SubmenuIndex {
 enum SubmenuIndex {
     SubmenuIndexEspFlasherFlash,
     SubmenuIndexEspFlasherFlash,
     SubmenuIndexEspFlasherAbout,
     SubmenuIndexEspFlasherAbout,
+    SubmenuIndexEspFlasherReset,
+    SubmenuIndexEspFlasherBootloader,
 };
 };
 
 
 void esp_flasher_scene_start_submenu_callback(void* context, uint32_t index) {
 void esp_flasher_scene_start_submenu_callback(void* context, uint32_t index) {
@@ -23,6 +25,18 @@ void esp_flasher_scene_start_on_enter(void* context) {
         SubmenuIndexEspFlasherFlash,
         SubmenuIndexEspFlasherFlash,
         esp_flasher_scene_start_submenu_callback,
         esp_flasher_scene_start_submenu_callback,
         app);
         app);
+    submenu_add_item(
+        submenu,
+        "Reset Board",
+        SubmenuIndexEspFlasherReset,
+        esp_flasher_scene_start_submenu_callback,
+        app);
+    submenu_add_item(
+        submenu,
+        "Enter Bootloader",
+        SubmenuIndexEspFlasherBootloader,
+        esp_flasher_scene_start_submenu_callback,
+        app);
     submenu_add_item(
     submenu_add_item(
         submenu,
         submenu,
         "About",
         "About",
@@ -48,6 +62,14 @@ bool esp_flasher_scene_start_on_event(void* context, SceneManagerEvent event) {
         } else if(event.event == SubmenuIndexEspFlasherFlash) {
         } else if(event.event == SubmenuIndexEspFlasherFlash) {
             scene_manager_next_scene(app->scene_manager, EspFlasherSceneBrowse);
             scene_manager_next_scene(app->scene_manager, EspFlasherSceneBrowse);
             consumed = true;
             consumed = true;
+        } else if(event.event == SubmenuIndexEspFlasherReset) {
+            app->reset = true;
+            scene_manager_next_scene(app->scene_manager, EspFlasherSceneConsoleOutput);
+            consumed = true;
+        } else if(event.event == SubmenuIndexEspFlasherBootloader) {
+            app->boot = true;
+            scene_manager_next_scene(app->scene_manager, EspFlasherSceneConsoleOutput);
+            consumed = true;
         }
         }
         scene_manager_set_scene_state(app->scene_manager, EspFlasherSceneStart, event.event);
         scene_manager_set_scene_state(app->scene_manager, EspFlasherSceneStart, event.event);
     }
     }