ソースを参照

rework code a bit for better debugging
split search and found view into two separate pages

g3gg0 2 年 前
コミット
56e1a8ea19
5 ファイル変更349 行追加319 行削除
  1. 1 1
      application.fam
  2. 328 303
      swd_probe_app.c
  3. 12 10
      swd_probe_app.h
  4. 8 3
      swd_scripts/halt.swd
  5. 0 2
      usb_uart.c

+ 1 - 1
application.fam

@@ -4,7 +4,7 @@ App(
     apptype=FlipperAppType.PLUGIN,
     apptype=FlipperAppType.PLUGIN,
     entry_point="swd_probe_app_main",
     entry_point="swd_probe_app_main",
     cdefines=["APP_SWD_PROBE"],
     cdefines=["APP_SWD_PROBE"],
-    requires=["gui", "storage", "dialogs"],
+    requires=["notification", "gui", "storage", "dialogs", "cli"],
     stack_size=2 * 1024,
     stack_size=2 * 1024,
     order=10,
     order=10,
     fap_icon="icons/app.png",
     fap_icon="icons/app.png",

+ 328 - 303
swd_probe_app.c

@@ -67,7 +67,7 @@ static const char* gpio_name(uint8_t mask) {
 }
 }
 
 
 static void swd_configure_pins(AppFSM* const ctx, bool output) {
 static void swd_configure_pins(AppFSM* const ctx, bool output) {
-    if(ctx->mode_page != ModePageScan && ctx->io_num_swc < 8 && ctx->io_num_swd < 8) {
+    if(ctx->mode_page > ModePageFound && ctx->io_num_swc < 8 && ctx->io_num_swd < 8) {
         furi_hal_gpio_init(
         furi_hal_gpio_init(
             gpios[ctx->io_num_swc], GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
             gpios[ctx->io_num_swc], GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
         if(!output) {
         if(!output) {
@@ -105,7 +105,7 @@ static void swd_configure_pins(AppFSM* const ctx, bool output) {
 }
 }
 
 
 static void swd_set_clock(AppFSM* const ctx, const uint8_t level) {
 static void swd_set_clock(AppFSM* const ctx, const uint8_t level) {
-    if(ctx->mode_page != ModePageScan && ctx->io_num_swc < 8) {
+    if(ctx->mode_page > ModePageFound && ctx->io_num_swc < 8) {
         furi_hal_gpio_write(gpios[ctx->io_num_swc], level);
         furi_hal_gpio_write(gpios[ctx->io_num_swc], level);
         return;
         return;
     }
     }
@@ -125,7 +125,7 @@ static void swd_set_clock(AppFSM* const ctx, const uint8_t level) {
 }
 }
 
 
 static void swd_set_data(AppFSM* const ctx, const uint8_t level) {
 static void swd_set_data(AppFSM* const ctx, const uint8_t level) {
-    if(ctx->mode_page != ModePageScan && ctx->io_num_swd < 8) {
+    if(ctx->mode_page > ModePageFound && ctx->io_num_swd < 8) {
         furi_hal_gpio_write(gpios[ctx->io_num_swd], level);
         furi_hal_gpio_write(gpios[ctx->io_num_swd], level);
         return;
         return;
     }
     }
@@ -145,7 +145,7 @@ static void swd_set_data(AppFSM* const ctx, const uint8_t level) {
 }
 }
 
 
 static uint8_t swd_get_data(AppFSM* const ctx) {
 static uint8_t swd_get_data(AppFSM* const ctx) {
-    if(ctx->mode_page != ModePageScan && ctx->io_num_swd < 8) {
+    if(ctx->mode_page > ModePageFound && ctx->io_num_swd < 8) {
         return furi_hal_gpio_read(gpios[ctx->io_num_swd]);
         return furi_hal_gpio_read(gpios[ctx->io_num_swd]);
     }
     }
 
 
@@ -206,6 +206,8 @@ static void swd_write(AppFSM* const ctx, const uint8_t* data, size_t bits) {
 }
 }
 
 
 static uint8_t swd_transfer(AppFSM* const ctx, bool ap, bool write, uint8_t a23, uint32_t* data) {
 static uint8_t swd_transfer(AppFSM* const ctx, bool ap, bool write, uint8_t a23, uint32_t* data) {
+    notification_message(ctx->notification, &sequence_set_red_255);
+
     swd_set_data(ctx, false);
     swd_set_data(ctx, false);
     swd_configure_pins(ctx, true);
     swd_configure_pins(ctx, true);
 
 
@@ -241,6 +243,7 @@ static uint8_t swd_transfer(AppFSM* const ctx, bool ap, bool write, uint8_t a23,
     }
     }
 
 
     if(ack != 0x01) {
     if(ack != 0x01) {
+        notification_message(ctx->notification, &sequence_reset_red);
         return ack;
         return ack;
     }
     }
 
 
@@ -267,22 +270,26 @@ static uint8_t swd_transfer(AppFSM* const ctx, bool ap, bool write, uint8_t a23,
         bool parity = swd_read_bit(ctx);
         bool parity = swd_read_bit(ctx);
 
 
         if(parity != __builtin_parity(*data)) {
         if(parity != __builtin_parity(*data)) {
+            notification_message(ctx->notification, &sequence_reset_red);
             return 8;
             return 8;
         }
         }
     }
     }
     swd_set_data(ctx, false);
     swd_set_data(ctx, false);
     swd_configure_pins(ctx, true);
     swd_configure_pins(ctx, true);
+    notification_message(ctx->notification, &sequence_reset_red);
 
 
     return ack;
     return ack;
 }
 }
 
 
 /* A line reset is achieved by holding the data signal HIGH for at least 50 clock cycles, followed by at least two idle cycles. */
 /* A line reset is achieved by holding the data signal HIGH for at least 50 clock cycles, followed by at least two idle cycles. */
 static void swd_line_reset(AppFSM* const ctx) {
 static void swd_line_reset(AppFSM* const ctx) {
+    notification_message(ctx->notification, &sequence_set_red_255);
     for(int bitcount = 0; bitcount < 50; bitcount += 8) {
     for(int bitcount = 0; bitcount < 50; bitcount += 8) {
         swd_write_byte(ctx, 0xFF, 8);
         swd_write_byte(ctx, 0xFF, 8);
     }
     }
     swd_write_byte(ctx, 0, 8);
     swd_write_byte(ctx, 0, 8);
     ctx->dp_regs.select_ok = false;
     ctx->dp_regs.select_ok = false;
+    notification_message(ctx->notification, &sequence_reset_red);
 }
 }
 
 
 static void swd_abort(AppFSM* const ctx) {
 static void swd_abort(AppFSM* const ctx) {
@@ -946,7 +953,7 @@ static bool swd_scriptfunc_status(ScriptContext* ctx) {
     swd_script_skip_whitespace(ctx);
     swd_script_skip_whitespace(ctx);
     swd_script_get_number(ctx, &status);
     swd_script_get_number(ctx, &status);
 
 
-    ctx->status_ignore = status == 0;
+    ctx->status_ignore = (status == 0);
 
 
     swd_script_seek_newline(ctx);
     swd_script_seek_newline(ctx);
 
 
@@ -1018,7 +1025,7 @@ static bool swd_scriptfunc_message(ScriptContext* ctx) {
     }
     }
 
 
     if(wait_time <= 60 * 1000) {
     if(wait_time <= 60 * 1000) {
-        strcpy(ctx->app->state_string, message);
+        strncpy(ctx->app->state_string, message, sizeof(ctx->app->state_string));
         swd_script_gui_refresh(ctx);
         swd_script_gui_refresh(ctx);
         furi_delay_ms(wait_time);
         furi_delay_ms(wait_time);
         if(show_dialog) {
         if(show_dialog) {
@@ -1278,9 +1285,6 @@ static bool swd_scriptfunc_mem_dump(ScriptContext* ctx) {
             } else {
             } else {
                 break;
                 break;
             }
             }
-            if(access_ok) {
-                break;
-            }
         }
         }
         if(ctx->abort) {
         if(ctx->abort) {
             DBGS("aborting");
             DBGS("aborting");
@@ -1362,8 +1366,7 @@ static bool swd_scriptfunc_mem_write(ScriptContext* ctx) {
                 "Failed write 0x%08lX",
                 "Failed write 0x%08lX",
                 address);
                 address);
             swd_script_gui_refresh(ctx);
             swd_script_gui_refresh(ctx);
-        }
-        if(access_ok) {
+        } else {
             break;
             break;
         }
         }
     }
     }
@@ -1432,8 +1435,7 @@ static bool swd_scriptfunc_mem_ldmst(ScriptContext* ctx) {
                 "Failed access 0x%08lX",
                 "Failed access 0x%08lX",
                 address);
                 address);
             swd_script_gui_refresh(ctx);
             swd_script_gui_refresh(ctx);
-        }
-        if(access_ok) {
+        } else {
             break;
             break;
         }
         }
     }
     }
@@ -1919,11 +1921,13 @@ static void draw_model(Canvas* const canvas) {
     zoom += speed * 0.005;
     zoom += speed * 0.005;
 }
 }
 
 
-static void render_callback(Canvas* const canvas, void* cb_ctx) {
-    AppFSM* ctx = acquire_mutex((ValueMutex*)cb_ctx, 25);
-    if(ctx == NULL) {
-        return;
-    }
+static void render_callback(Canvas* const canvas, void* ctx_in) {
+    furi_assert(canvas);
+    furi_assert(ctx_in);
+
+    AppFSM* ctx = ctx_in;
+    DBGS("furi_mutex_acquire");
+    furi_mutex_acquire(ctx->gui_mutex, FuriWaitForever);
 
 
     char buffer[64];
     char buffer[64];
     int y = 10;
     int y = 10;
@@ -1931,330 +1935,343 @@ static void render_callback(Canvas* const canvas, void* cb_ctx) {
     canvas_draw_frame(canvas, 0, 0, 128, 64);
     canvas_draw_frame(canvas, 0, 0, 128, 64);
     canvas_set_font(canvas, FontPrimary);
     canvas_set_font(canvas, FontPrimary);
 
 
-    if(ctx->detected_device) {
-        /* if seen less than a quarter second ago */
-        switch(ctx->mode_page) {
-        case ModePageScan: {
-            if((ctx->detected_timeout + TIMER_HZ / 4) >= TIMER_HZ * TIMEOUT) {
-                snprintf(buffer, sizeof(buffer), "FOUND!");
-            } else {
-                /* if it was seen more than a quarter second ago, show countdown */
-                snprintf(
-                    buffer,
-                    sizeof(buffer),
-                    "FOUND! (%lus)",
-                    (ctx->detected_timeout / TIMER_HZ) + 1);
-            }
-            canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, buffer);
-            y += 10;
-            canvas_set_font(canvas, FontKeyboard);
+    DBG("render page %lu (%s)", ctx->mode_page, ctx->detected_device ? "Detected" : "Searching");
 
 
-            snprintf(
-                buffer,
-                sizeof(buffer),
-                "SWC/SWD: %s/%s",
-                gpio_name(ctx->io_swc),
-                gpio_name(ctx->io_swd));
-            canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
-            y += 10;
-            snprintf(buffer, sizeof(buffer), "DPIDR 0x%08lX", ctx->dp_regs.dpidr);
-            canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
-            y += 10;
+    if(!ctx->detected_device) {
+        ctx->mode_page = ModePageScan;
+    } else if(ctx->mode_page == ModePageScan) {
+        ctx->mode_page = ModePageFound;
+    }
 
 
-            snprintf(
-                buffer,
-                sizeof(buffer),
-                "Part %02X Rev %X DAPv%d",
-                ctx->dpidr_info.partno,
-                ctx->dpidr_info.revision,
-                ctx->dpidr_info.version);
-            canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
-            y += 10;
+    /* if seen less than a quarter second ago */
+    switch(ctx->mode_page) {
+    case ModePageScan: {
+        ctx->mode_page = 0;
+        draw_model(canvas);
 
 
-            canvas_set_font(canvas, FontSecondary);
-            snprintf(buffer, sizeof(buffer), "%s", jep106_manufacturer(ctx->dpidr_info.designer));
-            canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
-            y += 10;
+        canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "Searching");
+        y += 14;
 
 
-            canvas_set_font(canvas, FontSecondary);
-            elements_button_left(canvas, "Script");
-            elements_button_right(canvas, "DP Regs");
+        canvas_set_font(canvas, FontSecondary);
 
 
-            break;
-        }
-        case ModePageDPRegs: {
-            canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "DP Registers");
-            y += 10;
-            canvas_set_font(canvas, FontKeyboard);
-            if(ctx->dp_regs.dpidr_ok) {
-                snprintf(buffer, sizeof(buffer), "DPIDR %08lX", ctx->dp_regs.dpidr);
-                canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
-            }
+        bool info_page = (ctx->loop_count % 500) >= 250;
+        if(info_page) {
+            canvas_draw_str(canvas, 2, y, "Connect GND with target GND");
             y += 10;
             y += 10;
-
-            if(ctx->dp_regs.ctrlstat_ok) {
-                snprintf(buffer, sizeof(buffer), "CTRL  %08lX", ctx->dp_regs.ctrlstat);
-                canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
-            }
+            canvas_draw_str(canvas, 2, y, "and any two GPIOs with pads");
             y += 10;
             y += 10;
+            canvas_draw_str(canvas, 2, y, "you want to check for SWD");
 
 
-            if(ctx->dp_regs.targetid_ok) {
-                snprintf(buffer, sizeof(buffer), "TGTID %08lX", ctx->dp_regs.targetid);
-                canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
+            canvas_set_font(canvas, FontPrimary);
+            canvas_draw_str(canvas, 111, 62, "2/2");
+        } else {
+            const char* filename = "<none>";
+            if(strlen(ctx->script_detected) > 0) {
+                const char* slash = strrchr(ctx->script_detected, '/');
+                if(slash) {
+                    filename = &slash[1];
+                } else {
+                    filename = ctx->script_detected;
+                }
             }
             }
-            y += 10;
 
 
-            if(ctx->dp_regs.eventstat_ok) {
-                snprintf(buffer, sizeof(buffer), "EVTST %08lX", ctx->dp_regs.eventstat);
-                canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
-            }
-            y += 10;
             canvas_set_font(canvas, FontSecondary);
             canvas_set_font(canvas, FontSecondary);
-            elements_button_left(canvas, "Scan");
-            elements_button_right(canvas, "DPID");
-            break;
-        }
-        case ModePageDPID: {
-            canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "DP ID Register");
+            canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "Autoexec Script");
             y += 10;
             y += 10;
             canvas_set_font(canvas, FontKeyboard);
             canvas_set_font(canvas, FontKeyboard);
-            if(ctx->dpidr_info.version != 2) {
-                snprintf(buffer, sizeof(buffer), "TARGETID not supported");
-                canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
-                y += 10;
-            } else {
-                if(ctx->dp_regs.targetid_ok) {
-                    snprintf(buffer, sizeof(buffer), "TGTID %08lX", ctx->dp_regs.targetid);
-                    canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
-                    y += 10;
-
-                    snprintf(buffer, sizeof(buffer), "Part No. %04X", ctx->targetid_info.partno);
-                    canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
-                    y += 10;
-                    snprintf(
-                        buffer,
-                        sizeof(buffer),
-                        "%s",
-                        jep106_manufacturer(ctx->targetid_info.designer));
-                    canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
-                    y += 10;
-                }
-            }
+            canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, filename);
+            y += 16;
+
             canvas_set_font(canvas, FontSecondary);
             canvas_set_font(canvas, FontSecondary);
-            elements_button_left(canvas, "DP Regs");
-            elements_button_right(canvas, "APs");
-            break;
+            canvas_draw_icon(canvas, 14, y - 5, &I_ButtonUp_7x4);
+            canvas_draw_icon(canvas, 78, y - 5, &I_ButtonDown_7x4);
+            canvas_draw_str(canvas, 23, y, "Clear");
+            canvas_draw_str(canvas, 87, y, "Choose");
+
+            canvas_set_font(canvas, FontPrimary);
+            canvas_draw_str(canvas, 111, 62, "1/2");
         }
         }
-        case ModePageAPID: {
-            canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "AP Menu");
-            y += 10;
-            canvas_set_font(canvas, FontKeyboard);
+        canvas_set_font(canvas, FontSecondary);
+        elements_button_left(canvas, "Script");
+        break;
+    }
+    case ModePageFound: {
+        if((ctx->detected_timeout + TIMER_HZ / 4) >= TIMER_HZ * TIMEOUT) {
+            snprintf(buffer, sizeof(buffer), "FOUND!");
+        } else {
+            /* if it was seen more than a quarter second ago, show countdown */
+            snprintf(
+                buffer, sizeof(buffer), "FOUND! (%lus)", (ctx->detected_timeout / TIMER_HZ) + 1);
+        }
+        canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, buffer);
+        y += 10;
+        canvas_set_font(canvas, FontKeyboard);
+
+        snprintf(
+            buffer,
+            sizeof(buffer),
+            "SWC/SWD: %s/%s",
+            gpio_name(ctx->io_swc),
+            gpio_name(ctx->io_swd));
+        canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
+        y += 10;
+        snprintf(buffer, sizeof(buffer), "DPIDR 0x%08lX", ctx->dp_regs.dpidr);
+        canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
+        y += 10;
+
+        snprintf(
+            buffer,
+            sizeof(buffer),
+            "Part %02X Rev %X DAPv%d",
+            ctx->dpidr_info.partno,
+            ctx->dpidr_info.revision,
+            ctx->dpidr_info.version);
+        canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
+        y += 10;
 
 
-            char state = ' ';
-            if(ctx->ap_pos >= ctx->ap_scanned && ctx->ap_pos <= ctx->ap_scanned + 10) {
-                state = '*';
-            }
+        canvas_set_font(canvas, FontSecondary);
+        snprintf(buffer, sizeof(buffer), "%s", jep106_manufacturer(ctx->dpidr_info.designer));
+        canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
+        y += 10;
 
 
-            if(!ctx->apidr_info[ctx->ap_pos].ok) {
-                snprintf(buffer, sizeof(buffer), "[%d]%c<none>", ctx->ap_pos, state);
-                canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
-                y += 10;
+        canvas_set_font(canvas, FontSecondary);
+        elements_button_left(canvas, "Script");
+        elements_button_right(canvas, "DP Regs");
 
 
-                if(ctx->ap_pos == 0) {
-                    for(size_t pos = 0; pos < COUNT(ctx->apidr_info); pos++) {
-                        if(ctx->apidr_info[pos].ok) {
-                            ctx->ap_pos = pos;
-                        }
-                    }
-                }
-            } else {
-                const char* class = "";
+        break;
+    }
+    case ModePageDPRegs: {
+        canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "DP Registers");
+        y += 10;
+        canvas_set_font(canvas, FontKeyboard);
+        if(ctx->dp_regs.dpidr_ok) {
+            snprintf(buffer, sizeof(buffer), "DPIDR %08lX", ctx->dp_regs.dpidr);
+            canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
+        }
+        y += 10;
 
 
-                switch(ctx->apidr_info[ctx->ap_pos].class) {
-                case 0:
-                    class = "und";
-                    break;
-                case 1:
-                    class = "COM";
-                    break;
-                case 8:
-                    class = "MEM";
-                    break;
-                default:
-                    class = "unk";
-                    break;
-                }
+        if(ctx->dp_regs.ctrlstat_ok) {
+            snprintf(buffer, sizeof(buffer), "CTRL  %08lX", ctx->dp_regs.ctrlstat);
+            canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
+        }
+        y += 10;
 
 
-                const char* types[] = {
-                    "COM-AP",
-                    "AHB3",
-                    "APB2 or APB3",
-                    "Type unknown",
-                    "AXI3 or AXI4",
-                    "AHB5",
-                    "APB4 and APB5",
-                    "AXI5",
-                    "AHB5 enh.",
-                };
-                const char* type = "Type unk";
-
-                if(ctx->apidr_info[ctx->ap_pos].type < COUNT(types)) {
-                    type = types[ctx->apidr_info[ctx->ap_pos].type];
-                }
+        if(ctx->dp_regs.targetid_ok) {
+            snprintf(buffer, sizeof(buffer), "TGTID %08lX", ctx->dp_regs.targetid);
+            canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
+        }
+        y += 10;
 
 
-                snprintf(buffer, sizeof(buffer), "[%d]%c%s, %s", ctx->ap_pos, state, class, type);
-                canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
-                y += 10;
+        if(ctx->dp_regs.eventstat_ok) {
+            snprintf(buffer, sizeof(buffer), "EVTST %08lX", ctx->dp_regs.eventstat);
+            canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
+        }
+        y += 10;
+        canvas_set_font(canvas, FontSecondary);
+        elements_button_left(canvas, "Scan");
+        elements_button_right(canvas, "DPID");
 
 
-                snprintf(
-                    buffer, sizeof(buffer), "Base 0x%08lX", ctx->apidr_info[ctx->ap_pos].base);
+        break;
+    }
+
+    case ModePageDPID: {
+        canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "DP ID Register");
+        y += 10;
+        canvas_set_font(canvas, FontKeyboard);
+        if(ctx->dpidr_info.version != 2) {
+            snprintf(buffer, sizeof(buffer), "TARGETID not supported");
+            canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
+            y += 10;
+        } else {
+            if(ctx->dp_regs.targetid_ok) {
+                snprintf(buffer, sizeof(buffer), "TGTID %08lX", ctx->dp_regs.targetid);
                 canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
                 canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
                 y += 10;
                 y += 10;
 
 
-                snprintf(
-                    buffer,
-                    sizeof(buffer),
-                    "Rev %d Var %d",
-                    ctx->apidr_info[ctx->ap_pos].revision,
-                    ctx->apidr_info[ctx->ap_pos].variant);
+                snprintf(buffer, sizeof(buffer), "Part No. %04X", ctx->targetid_info.partno);
                 canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
                 canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
                 y += 10;
                 y += 10;
-
                 snprintf(
                 snprintf(
-                    buffer,
-                    sizeof(buffer),
-                    "%s",
-                    jep106_manufacturer(ctx->apidr_info[ctx->ap_pos].designer));
+                    buffer, sizeof(buffer), "%s", jep106_manufacturer(ctx->targetid_info.designer));
                 canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
                 canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
                 y += 10;
                 y += 10;
-
-                elements_button_center(canvas, "Show");
             }
             }
-            canvas_set_font(canvas, FontSecondary);
-            elements_button_left(canvas, "DPID");
-            elements_scrollbar_pos(
-                canvas, 4, 10, 40, ctx->ap_pos / 32, COUNT(ctx->apidr_info) / 32);
-        } break;
-
-            /* hex dump view */
-        case ModePageHexDump: {
-            canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "Hex dump");
-            y += 10;
-            canvas_set_font(canvas, FontKeyboard);
+        }
+        canvas_set_font(canvas, FontSecondary);
+        elements_button_left(canvas, "DP Regs");
+        elements_button_right(canvas, "APs");
+        break;
+    }
 
 
-            canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, "Addr:");
+    case ModePageAPID: {
+        canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "AP Menu");
+        y += 10;
+        canvas_set_font(canvas, FontKeyboard);
 
 
-            snprintf(buffer, sizeof(buffer), "%08lX", ctx->hex_addr);
-            canvas_draw_str_aligned(canvas, 38, y, AlignLeft, AlignBottom, buffer);
-            uint32_t font_width = canvas_glyph_width(canvas, '0');
-            uint32_t x = 37 + (7 - ctx->hex_select) * font_width;
+        char state = ' ';
+        if(ctx->ap_pos >= ctx->ap_scanned && ctx->ap_pos <= ctx->ap_scanned + 10) {
+            state = '*';
+        }
 
 
-            /* draw selection */
-            canvas_draw_line(canvas, x, y + 1, x + font_width, y + 1);
+        if(!ctx->apidr_info[ctx->ap_pos].ok) {
+            snprintf(buffer, sizeof(buffer), "[%d]%c<none>", ctx->ap_pos, state);
+            canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
             y += 10;
             y += 10;
 
 
-            uint32_t byte_num = 0;
-            for(int line = 0; line < 4; line++) {
-                uint32_t x_pos = 5;
-
-                for(int byte_pos = 0; byte_pos < 8; byte_pos++) {
-                    if(ctx->hex_buffer_valid[byte_num / 4]) {
-                        snprintf(buffer, sizeof(buffer), "%02X", ctx->hex_buffer[byte_num]);
-                    } else {
-                        snprintf(buffer, sizeof(buffer), "--");
+            if(ctx->ap_pos == 0) {
+                for(size_t pos = 0; pos < COUNT(ctx->apidr_info); pos++) {
+                    if(ctx->apidr_info[pos].ok) {
+                        ctx->ap_pos = pos;
                     }
                     }
-                    byte_num++;
-                    canvas_draw_str_aligned(canvas, x_pos, y, AlignLeft, AlignBottom, buffer);
-                    x_pos += font_width * 2 + font_width / 2;
                 }
                 }
-                y += 10;
             }
             }
+        } else {
+            const char* class = "";
 
 
-            break;
-        }
+            switch(ctx->apidr_info[ctx->ap_pos].class) {
+            case 0:
+                class = "und";
+                break;
+            case 1:
+                class = "COM";
+                break;
+            case 8:
+                class = "MEM";
+                break;
+            default:
+                class = "unk";
+                break;
+            }
 
 
-        /* hex dump view */
-        case ModePageScript: {
-            canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "Script");
+            const char* types[] = {
+                "COM-AP",
+                "AHB3",
+                "APB2 or APB3",
+                "Type unknown",
+                "AXI3 or AXI4",
+                "AHB5",
+                "APB4 and APB5",
+                "AXI5",
+                "AHB5 enh.",
+            };
+            const char* type = "Type unk";
+
+            if(ctx->apidr_info[ctx->ap_pos].type < COUNT(types)) {
+                type = types[ctx->apidr_info[ctx->ap_pos].type];
+            }
+
+            snprintf(buffer, sizeof(buffer), "[%d]%c%s, %s", ctx->ap_pos, state, class, type);
+            canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
             y += 10;
             y += 10;
+
+            snprintf(buffer, sizeof(buffer), "Base 0x%08lX", ctx->apidr_info[ctx->ap_pos].base);
+            canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
             y += 10;
             y += 10;
-            canvas_draw_str_aligned(canvas, 10, y, AlignLeft, AlignBottom, "Status:");
+
+            snprintf(
+                buffer,
+                sizeof(buffer),
+                "Rev %d Var %d",
+                ctx->apidr_info[ctx->ap_pos].revision,
+                ctx->apidr_info[ctx->ap_pos].variant);
+            canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
             y += 10;
             y += 10;
-            canvas_set_font(canvas, FontKeyboard);
-            canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, ctx->state_string);
+
+            snprintf(
+                buffer,
+                sizeof(buffer),
+                "%s",
+                jep106_manufacturer(ctx->apidr_info[ctx->ap_pos].designer));
+            canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, buffer);
             y += 10;
             y += 10;
 
 
-        } break;
+            elements_button_center(canvas, "Show");
         }
         }
-    } else {
-        draw_model(canvas);
+        canvas_set_font(canvas, FontSecondary);
+        elements_button_left(canvas, "DPID");
+        elements_scrollbar_pos(canvas, 4, 10, 40, ctx->ap_pos / 32, COUNT(ctx->apidr_info) / 32);
+        break;
+    }
 
 
-        canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "Searching");
-        y += 14;
+    /* hex dump view */
+    case ModePageHexDump: {
+        canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "Hex dump");
+        y += 10;
+        canvas_set_font(canvas, FontKeyboard);
 
 
-        canvas_set_font(canvas, FontSecondary);
+        canvas_draw_str_aligned(canvas, 5, y, AlignLeft, AlignBottom, "Addr:");
 
 
-        bool info_page = (ctx->loop_count % 500) >= 250;
-        if(info_page) {
-            canvas_draw_str(canvas, 2, y, "Connect GND with target GND");
-            y += 10;
-            canvas_draw_str(canvas, 2, y, "and any two GPIOs with pads");
-            y += 10;
-            canvas_draw_str(canvas, 2, y, "you want to check for SWD");
+        snprintf(buffer, sizeof(buffer), "%08lX", ctx->hex_addr);
+        canvas_draw_str_aligned(canvas, 38, y, AlignLeft, AlignBottom, buffer);
+        uint32_t font_width = canvas_glyph_width(canvas, '0');
+        uint32_t x = 37 + (7 - ctx->hex_select) * font_width;
 
 
-            canvas_set_font(canvas, FontPrimary);
-            canvas_draw_str(canvas, 111, 62, "2/2");
-        } else {
-            const char* filename = "<none>";
-            if(strlen(ctx->script_detected) > 0) {
-                const char* slash = strrchr(ctx->script_detected, '/');
-                if(slash) {
-                    filename = &slash[1];
+        /* draw selection */
+        canvas_draw_line(canvas, x, y + 1, x + font_width, y + 1);
+        y += 10;
+
+        uint32_t byte_num = 0;
+        for(int line = 0; line < 4; line++) {
+            uint32_t x_pos = 5;
+
+            for(int byte_pos = 0; byte_pos < 8; byte_pos++) {
+                if(ctx->hex_buffer_valid[byte_num / 4]) {
+                    snprintf(buffer, sizeof(buffer), "%02X", ctx->hex_buffer[byte_num]);
                 } else {
                 } else {
-                    filename = ctx->script_detected;
+                    snprintf(buffer, sizeof(buffer), "--");
                 }
                 }
+                byte_num++;
+                canvas_draw_str_aligned(canvas, x_pos, y, AlignLeft, AlignBottom, buffer);
+                x_pos += font_width * 2 + font_width / 2;
             }
             }
-
-            canvas_set_font(canvas, FontSecondary);
-            canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "Autoexec Script");
             y += 10;
             y += 10;
-            canvas_set_font(canvas, FontKeyboard);
-            canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, filename);
-            y += 16;
+        }
 
 
-            canvas_set_font(canvas, FontSecondary);
-            canvas_draw_icon(canvas, 14, y - 5, &I_ButtonUp_7x4);
-            canvas_draw_icon(canvas, 78, y - 5, &I_ButtonDown_7x4);
-            canvas_draw_str(canvas, 23, y, "Clear");
-            canvas_draw_str(canvas, 87, y, "Choose");
+        break;
+    }
 
 
-            canvas_set_font(canvas, FontPrimary);
-            canvas_draw_str(canvas, 111, 62, "1/2");
-        }
-        canvas_set_font(canvas, FontSecondary);
-        elements_button_left(canvas, "Script");
+    /* hex dump view */
+    case ModePageScript: {
+        canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, "Script");
+        y += 10;
+        y += 10;
+        canvas_draw_str_aligned(canvas, 10, y, AlignLeft, AlignBottom, "Status:");
+        y += 10;
+        canvas_set_font(canvas, FontKeyboard);
+        canvas_draw_str_aligned(canvas, 64, y, AlignCenter, AlignBottom, ctx->state_string);
+        y += 10;
+        break;
+    }
     }
     }
 
 
-    release_mutex((ValueMutex*)cb_ctx, ctx);
+    DBGS("furi_mutex_release");
+    furi_mutex_release(ctx->gui_mutex);
 }
 }
 
 
-static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
-    furi_assert(event_queue);
+static void input_callback(InputEvent* input_event, void* ctx_in) {
+    furi_assert(input_event);
+    furi_assert(ctx_in);
+    AppFSM* ctx = ctx_in;
 
 
+    DBGS("furi_message_queue_get_count");
     /* better skip than sorry */
     /* better skip than sorry */
-    if(furi_message_queue_get_count(event_queue) < QUEUE_SIZE) {
+    if(furi_message_queue_get_count(ctx->event_queue) < QUEUE_SIZE) {
+        DBGS("furi_message_queue_put");
         AppEvent event = {.type = EventKeyPress, .input = *input_event};
         AppEvent event = {.type = EventKeyPress, .input = *input_event};
-        furi_message_queue_put(event_queue, &event, 100);
+        furi_message_queue_put(ctx->event_queue, &event, 100);
     }
     }
 }
 }
 
 
-static void timer_tick_callback(FuriMessageQueue* event_queue) {
-    furi_assert(event_queue);
+static void timer_tick_callback(void* ctx_in) {
+    furi_assert(ctx_in);
+    AppFSM* ctx = ctx_in;
 
 
+    //DBGS("furi_message_queue_get_count");
     /* filling buffer makes no sense, as we lost timing anyway */
     /* filling buffer makes no sense, as we lost timing anyway */
-    if(furi_message_queue_get_count(event_queue) < 1) {
+    if(furi_message_queue_get_count(ctx->event_queue) < 1) {
+        //DBGS("furi_message_queue_put");
         AppEvent event = {.type = EventTimerTick};
         AppEvent event = {.type = EventTimerTick};
-        furi_message_queue_put(event_queue, &event, 100);
+        furi_message_queue_put(ctx->event_queue, &event, 100);
     }
     }
 }
 }
 
 
@@ -2281,9 +2298,13 @@ static void on_timer_tick(AppFSM* ctx) {
     ctx->loop_count++;
     ctx->loop_count++;
 
 
     switch(ctx->mode_page) {
     switch(ctx->mode_page) {
-    case ModePageScan: {
+    case ModePageScan:
+    case ModePageFound: {
         /* reset after timeout */
         /* reset after timeout */
-        if(ctx->detected_timeout == 0) {
+        if(ctx->detected_timeout > 0) {
+            ctx->detected_timeout--;
+        } else {
+            DBGS("Reset detected flag");
             ctx->detected_device = false;
             ctx->detected_device = false;
             ctx->io_swd = 0xFF;
             ctx->io_swd = 0xFF;
             ctx->io_swc = 0xFF;
             ctx->io_swc = 0xFF;
@@ -2294,8 +2315,6 @@ static void on_timer_tick(AppFSM* ctx) {
             memset(&ctx->targetid_info, 0x00, sizeof(ctx->targetid_info));
             memset(&ctx->targetid_info, 0x00, sizeof(ctx->targetid_info));
             memset(&ctx->apidr_info, 0x00, sizeof(ctx->apidr_info));
             memset(&ctx->apidr_info, 0x00, sizeof(ctx->apidr_info));
             ctx->script_detected_executed = false;
             ctx->script_detected_executed = false;
-        } else {
-            ctx->detected_timeout--;
         }
         }
 
 
         ctx->detected = false;
         ctx->detected = false;
@@ -2313,6 +2332,7 @@ static void on_timer_tick(AppFSM* ctx) {
 
 
         /* now when detected a device, set the timeout */
         /* now when detected a device, set the timeout */
         if(ctx->detected) {
         if(ctx->detected) {
+            DBGS("Set detected flag");
             ctx->detected_device = true;
             ctx->detected_device = true;
             ctx->detected_timeout = TIMER_HZ * TIMEOUT;
             ctx->detected_timeout = TIMER_HZ * TIMEOUT;
 
 
@@ -2389,7 +2409,7 @@ static void on_timer_tick(AppFSM* ctx) {
 
 
                     ctx->mode_page = ModePageScript;
                     ctx->mode_page = ModePageScript;
                     swd_execute_script(ctx, ctx->script_detected);
                     swd_execute_script(ctx, ctx->script_detected);
-                    ctx->mode_page = ModePageScan;
+                    ctx->mode_page = ModePageFound;
                 }
                 }
                 furi_mutex_release(ctx->swd_mutex);
                 furi_mutex_release(ctx->swd_mutex);
             }
             }
@@ -2471,7 +2491,8 @@ static bool swd_message_process(AppFSM* ctx) {
                     default:
                     default:
                         break;
                         break;
 
 
-                    case ModePageScan: {
+                    case ModePageScan:
+                    case ModePageFound: {
                         strcpy(ctx->script_detected, "");
                         strcpy(ctx->script_detected, "");
                         break;
                         break;
                     }
                     }
@@ -2547,7 +2568,8 @@ static bool swd_message_process(AppFSM* ctx) {
                         if(ctx->hex_select < 7) {
                         if(ctx->hex_select < 7) {
                             ctx->hex_select++;
                             ctx->hex_select++;
                         }
                         }
-                    } else if(ctx->mode_page == ModePageScan) {
+                    } else if((ctx->mode_page == ModePageScan) || (ctx->mode_page == ModePageFound)) {
+                        uint32_t mode_page = ctx->mode_page;
                         FuriString* result_path = furi_string_alloc_printf(ANY_PATH("swd"));
                         FuriString* result_path = furi_string_alloc_printf(ANY_PATH("swd"));
                         FuriString* preselected = furi_string_alloc_printf(
                         FuriString* preselected = furi_string_alloc_printf(
                             (strlen(ctx->script_detected) > 0) ? ctx->script_detected :
                             (strlen(ctx->script_detected) > 0) ? ctx->script_detected :
@@ -2561,7 +2583,7 @@ static bool swd_message_process(AppFSM* ctx) {
                             const char* path = furi_string_get_cstr(result_path);
                             const char* path = furi_string_get_cstr(result_path);
                             ctx->mode_page = ModePageScript;
                             ctx->mode_page = ModePageScript;
                             swd_execute_script(ctx, path);
                             swd_execute_script(ctx, path);
-                            ctx->mode_page = ModePageScan;
+                            ctx->mode_page = mode_page;
                         }
                         }
 
 
                         furi_string_free(result_path);
                         furi_string_free(result_path);
@@ -2585,9 +2607,11 @@ static bool swd_message_process(AppFSM* ctx) {
                         ctx->mode_page = ModePageAPID;
                         ctx->mode_page = ModePageAPID;
                     } else if(ctx->mode_page == ModePageScript) {
                     } else if(ctx->mode_page == ModePageScript) {
                         ctx->script->abort = true;
                         ctx->script->abort = true;
-                    } else if(ctx->mode_page != ModePageScan) {
+                    } else if(ctx->mode_page > ModePageFound) {
                         ctx->mode_page = ModePageScan;
                         ctx->mode_page = ModePageScan;
-                    } else {
+                    } else if(ctx->mode_page == ModePageScan) {
+                        processing = false;
+                    } else if(ctx->mode_page == ModePageFound) {
                         processing = false;
                         processing = false;
                     }
                     }
                     break;
                     break;
@@ -2632,26 +2656,22 @@ int32_t swd_probe_app_main(void* p) {
 
 
     AppFSM* app = malloc(sizeof(AppFSM));
     AppFSM* app = malloc(sizeof(AppFSM));
 
 
+    DBGS("App init");
     app_init(app);
     app_init(app);
 
 
-    if(!init_mutex(&app->state_mutex, app, sizeof(AppFSM))) {
-        FURI_LOG_E(TAG, "cannot create mutex\r\n");
-        free(app);
-        return 255;
-    }
-
+    DBGS("furi_record_open");
     app->notification = furi_record_open(RECORD_NOTIFICATION);
     app->notification = furi_record_open(RECORD_NOTIFICATION);
     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->view_port = view_port_alloc();
-    app->event_queue = furi_message_queue_alloc(QUEUE_SIZE, sizeof(AppEvent));
-    app->timer = furi_timer_alloc(timer_tick_callback, FuriTimerTypePeriodic, app->event_queue);
+    DBGS("furi_mutex_alloc");
     app->swd_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
     app->swd_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
+    app->gui_mutex = furi_mutex_alloc(FuriMutexTypeNormal);
+    app->event_queue = furi_message_queue_alloc(QUEUE_SIZE, sizeof(AppEvent));
 
 
+    DBGS("usb_uart_enable");
     UsbUartConfig uart_config;
     UsbUartConfig uart_config;
-
     uart_config.vcp_ch = 1;
     uart_config.vcp_ch = 1;
     uart_config.rx_data = &data_received;
     uart_config.rx_data = &data_received;
     uart_config.rx_data_ctx = app;
     uart_config.rx_data_ctx = app;
@@ -2661,27 +2681,30 @@ int32_t swd_probe_app_main(void* p) {
     app->commandline->max_tries = 1;
     app->commandline->max_tries = 1;
     app->commandline->app = app;
     app->commandline->app = app;
 
 
-    view_port_draw_callback_set(app->view_port, render_callback, &app->state_mutex);
-    view_port_input_callback_set(app->view_port, input_callback, app->event_queue);
+    DBGS("view_port_alloc");
+    app->view_port = view_port_alloc();
+    view_port_draw_callback_set(app->view_port, render_callback, app);
+    view_port_input_callback_set(app->view_port, input_callback, app);
     gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);
     gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);
 
 
-    notification_message_block(app->notification, &sequence_display_backlight_enforce_on);
+    DBGS("furi_timer_alloc");
+    app->timer = furi_timer_alloc(timer_tick_callback, FuriTimerTypePeriodic, app);
+    furi_timer_start(app->timer, furi_kernel_get_tick_frequency() / TIMER_HZ);
 
 
+    DBGS("notification_message_block");
+    notification_message(app->notification, &sequence_display_backlight_enforce_on);
+
+    DBGS("swd_execute_script");
     swd_execute_script(app, ANY_PATH("swd/startup.swd"));
     swd_execute_script(app, ANY_PATH("swd/startup.swd"));
 
 
     DOLPHIN_DEED(DolphinDeedPluginGameStart);
     DOLPHIN_DEED(DolphinDeedPluginGameStart);
 
 
-    furi_timer_start(app->timer, furi_kernel_get_tick_frequency() / TIMER_HZ);
-
+    DBGS("processing");
     for(bool processing = true; processing;) {
     for(bool processing = true; processing;) {
-        //AppFSM* ctx = (AppFSM*)acquire_mutex_block(&app->state_mutex);
-
         processing = swd_message_process(app);
         processing = swd_message_process(app);
 
 
         view_port_update(app->view_port);
         view_port_update(app->view_port);
 
 
-        //release_mutex(&ctx->state_mutex, ctx);
-
         bool beep = false;
         bool beep = false;
 
 
         if(app->detected_device && !app->detected_notified) {
         if(app->detected_device && !app->detected_notified) {
@@ -2700,14 +2723,16 @@ int32_t swd_probe_app_main(void* p) {
 
 
     furi_timer_free(app->timer);
     furi_timer_free(app->timer);
 
 
-    notification_message_block(app->notification, &sequence_display_backlight_enforce_auto);
+    notification_message(app->notification, &sequence_display_backlight_enforce_auto);
 
 
     usb_uart_disable(app->uart);
     usb_uart_disable(app->uart);
+
     view_port_enabled_set(app->view_port, false);
     view_port_enabled_set(app->view_port, false);
     gui_remove_view_port(app->gui, app->view_port);
     gui_remove_view_port(app->gui, app->view_port);
     view_port_free(app->view_port);
     view_port_free(app->view_port);
+
     furi_message_queue_free(app->event_queue);
     furi_message_queue_free(app->event_queue);
-    delete_mutex(&app->state_mutex);
+    furi_mutex_free(app->gui_mutex);
     furi_mutex_free(app->swd_mutex);
     furi_mutex_free(app->swd_mutex);
     free(app);
     free(app);
 
 

+ 12 - 10
swd_probe_app.h

@@ -33,10 +33,11 @@
 
 
 typedef enum {
 typedef enum {
     ModePageScan = 0,
     ModePageScan = 0,
-    ModePageDPRegs = 1,
-    ModePageDPID = 2,
-    ModePageAPID = 3,
-    ModePageCount = 4,
+    ModePageFound = 1,
+    ModePageDPRegs = 2,
+    ModePageDPID = 3,
+    ModePageAPID = 4,
+    ModePageCount = 5,
     ModePageHexDump = 0x100,
     ModePageHexDump = 0x100,
     ModePageScript = 0x101,
     ModePageScript = 0x101,
 } ModePages;
 } ModePages;
@@ -125,17 +126,18 @@ typedef struct {
 typedef struct sScriptContext ScriptContext;
 typedef struct sScriptContext ScriptContext;
 
 
 typedef struct {
 typedef struct {
-    FuriMessageQueue* event_queue;
-    FuriTimer* timer;
-    NotificationApp* notification;
     Storage* storage;
     Storage* storage;
-    ViewPort* view_port;
     Gui* gui;
     Gui* gui;
     DialogsApp* dialogs;
     DialogsApp* dialogs;
+    NotificationApp* notification;
+
+    FuriTimer* timer;
     UsbUart* uart;
     UsbUart* uart;
+    ViewPort* view_port;
 
 
+    FuriMessageQueue* event_queue;
     FuriMutex* swd_mutex;
     FuriMutex* swd_mutex;
-    ValueMutex state_mutex;
+    FuriMutex* gui_mutex;
 
 
     swd_targetid_info_t targetid_info;
     swd_targetid_info_t targetid_info;
     swd_dpidr_info_t dpidr_info;
     swd_dpidr_info_t dpidr_info;
@@ -152,7 +154,7 @@ typedef struct {
     uint8_t io_swd;
     uint8_t io_swd;
     uint8_t io_num_swc;
     uint8_t io_num_swc;
     uint8_t io_num_swd;
     uint8_t io_num_swd;
-    uint32_t detected_timeout;
+    int32_t detected_timeout;
     uint32_t swd_clock_delay;
     uint32_t swd_clock_delay;
     uint32_t swd_idle_bits;
     uint32_t swd_idle_bits;
     bool detected;
     bool detected;

+ 8 - 3
swd_scripts/halt.swd

@@ -1,6 +1,11 @@
+
+# make sure errors do not cause a script abort
 errors ignore
 errors ignore
-status 0
-message 0 "HAMMER TIME! Try to halt the CPU"
+
+message 0 "HAMMER TIME! Trying to halt CPU"
+ap_select 0
+
+# loop writing the halt bits
 .label l1
 .label l1
-mem_write 0xE000EDF0 0xA05F0004
+mem_write 0xE000EDF0 0xA05F0003
 goto l1
 goto l1

+ 0 - 2
usb_uart.c

@@ -186,11 +186,9 @@ static void vcp_on_line_config(void* context, struct usb_cdc_line_coding* config
 
 
 UsbUart* usb_uart_enable(UsbUartConfig* cfg) {
 UsbUart* usb_uart_enable(UsbUartConfig* cfg) {
     UsbUart* usb_uart = malloc(sizeof(UsbUart));
     UsbUart* usb_uart = malloc(sizeof(UsbUart));
-
     memcpy(&(usb_uart->cfg_new), cfg, sizeof(UsbUartConfig));
     memcpy(&(usb_uart->cfg_new), cfg, sizeof(UsbUartConfig));
 
 
     usb_uart->thread = furi_thread_alloc_ex("UsbUartWorker", 1024, usb_uart_worker, usb_uart);
     usb_uart->thread = furi_thread_alloc_ex("UsbUartWorker", 1024, usb_uart_worker, usb_uart);
-
     furi_thread_start(usb_uart->thread);
     furi_thread_start(usb_uart->thread);
     return usb_uart;
     return usb_uart;
 }
 }