- Work on fixing erase check. Many implementations are plain broken.
authoroharboe <oharboe@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 3 Apr 2008 14:00:17 +0000 (14:00 +0000)
committeroharboe <oharboe@b42882b7-edfa-0310-969c-e2dbd0fdcd60>
Thu, 3 Apr 2008 14:00:17 +0000 (14:00 +0000)
Wrote a default flash erase check fn which uses CFI's target algorithm
w/fallback to memory reads.
- "flash info" no longer prints erase status as it is stale.
- "flash erase_check" now prints erase status. erase check can take a
*long* time. Work in progress
- arm7/9 with seperate srst & trst now supports reset init/halt
after a power outage. arm7/9 no longer makes any assumptions
about state of target when reset is asserted.
- fixes for srst & trst capable arm7/9 with reset init/halt
- prepare_reset_halt retired. This code needs to be inside
assert_reset anyway
- haven't been able to get stm32 write algorithm to work. Fallback
flash write does work. Haven't found a version of openocd trunk
where this works.
- added target_free_all_working_areas_restore() which can
let be of restoring backups. This is needed when asserting
reset as the target must be assumed to be an unknown state.
Added some comments to working areas API
- str9 reset script fixes
- some guidelines
- fixed dangling callbacks upon reset timeout

git-svn-id: svn://svn.berlios.de/openocd/trunk@536 b42882b7-edfa-0310-969c-e2dbd0fdcd60

22 files changed:
src/flash/cfi.c
src/flash/cfi.h
src/flash/flash.c
src/flash/stm32x.c
src/target/arm11.c
src/target/arm11.h
src/target/arm720t.c
src/target/arm7_9_common.c
src/target/arm7tdmi.c
src/target/arm920t.c
src/target/arm926ejs.c
src/target/arm966e.c
src/target/arm9tdmi.c
src/target/armv4_5.c
src/target/cortex_m3.c
src/target/event/str912_reset.script
src/target/feroceon.c
src/target/target.c
src/target/target.h
src/target/target/readme.txt [new file with mode: 0644]
src/target/target/stm32.cfg
src/target/xscale.c

index 6aad04a7ec7e14f3106752654568bae72c699834..3d83070962436c1f50376a57225b70b4ce44ad57 100644 (file)
@@ -45,7 +45,6 @@ int cfi_protect(struct flash_bank_s *bank, int set, int first, int last);
 int cfi_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count);
 int cfi_probe(struct flash_bank_s *bank);
 int cfi_auto_probe(struct flash_bank_s *bank);
-int cfi_erase_check(struct flash_bank_s *bank);
 int cfi_protect_check(struct flash_bank_s *bank);
 int cfi_info(struct flash_bank_s *bank, char *buf, int buf_size);
 
@@ -67,7 +66,7 @@ flash_driver_t cfi_flash =
        .write = cfi_write,
        .probe = cfi_probe,
        .auto_probe = cfi_auto_probe,
-       .erase_check = cfi_erase_check,
+       .erase_check = default_flash_blank_check,
        .protect_check = cfi_protect_check,
        .info = cfi_info
 };
@@ -627,7 +626,6 @@ int cfi_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **
        bank->driver_priv = cfi_info;
 
        cfi_info->write_algorithm = NULL;
-       cfi_info->erase_check_algorithm = NULL;
 
        cfi_info->x16_as_x8 = 0;
        cfi_info->jedec_probe = 0;
@@ -2092,121 +2090,6 @@ int cfi_auto_probe(struct flash_bank_s *bank)
        return cfi_probe(bank);
 }
 
-int cfi_erase_check(struct flash_bank_s *bank)
-{
-       cfi_flash_bank_t *cfi_info = bank->driver_priv;
-       target_t *target = bank->target;
-       int i;
-       int retval;
-
-       if (bank->target->state != TARGET_HALTED)
-       {
-               return ERROR_TARGET_NOT_HALTED;
-       }
-
-       if (!cfi_info->erase_check_algorithm)
-       {
-               u32 erase_check_code[] =
-               {
-                       0xe4d03001,     /* ldrb r3, [r0], #1    */
-                       0xe0022003, /* and r2, r2, r3           */
-                       0xe2511001, /* subs r1, r1, #1          */
-                       0x1afffffb,     /* b -4                                 */
-                       0xeafffffe      /* b 0                                  */
-               };
-
-               /* make sure we have a working area */
-               if (target_alloc_working_area(target, 20, &cfi_info->erase_check_algorithm) != ERROR_OK)
-               {
-                       LOG_WARNING("no working area available, falling back to slow memory reads");
-               }
-               else
-               {
-                       u8 erase_check_code_buf[5 * 4];
-
-                       for (i = 0; i < 5; i++)
-                               target_buffer_set_u32(target, erase_check_code_buf + (i*4), erase_check_code[i]);
-
-                       /* write algorithm code to working area */
-                       target->type->write_memory(target, cfi_info->erase_check_algorithm->address, 4, 5, erase_check_code_buf);
-               }
-       }
-
-       if (!cfi_info->erase_check_algorithm)
-       {
-               u32 *buffer = malloc(4096);
-
-               for (i = 0; i < bank->num_sectors; i++)
-               {
-                       u32 address = bank->base + bank->sectors[i].offset;
-                       u32 size = bank->sectors[i].size;
-                       u32 check = 0xffffffffU;
-                       int erased = 1;
-
-                       while (size > 0)
-                       {
-                               u32 thisrun_size = (size > 4096) ? 4096 : size;
-                               int j;
-
-                               target->type->read_memory(target, address, 4, thisrun_size / 4, (u8*)buffer);
-
-                               for (j = 0; j < thisrun_size / 4; j++)
-                                       check &= buffer[j];
-
-                               if (check != 0xffffffff)
-                               {
-                                       erased = 0;
-                                       break;
-                               }
-
-                               size -= thisrun_size;
-                               address += thisrun_size;
-                       }
-
-                       bank->sectors[i].is_erased = erased;
-               }
-
-               free(buffer);
-       }
-       else
-       {
-               for (i = 0; i < bank->num_sectors; i++)
-               {
-                       u32 address = bank->base + bank->sectors[i].offset;
-                       u32 size = bank->sectors[i].size;
-
-                       reg_param_t reg_params[3];
-                       armv4_5_algorithm_t armv4_5_info;
-
-                       armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
-                       armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
-                       armv4_5_info.core_state = ARMV4_5_STATE_ARM;
-
-                       init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
-                       buf_set_u32(reg_params[0].value, 0, 32, address);
-
-                       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
-                       buf_set_u32(reg_params[1].value, 0, 32, size);
-
-                       init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
-                       buf_set_u32(reg_params[2].value, 0, 32, 0xff);
-
-                       if ((retval = target->type->run_algorithm(target, 0, NULL, 3, reg_params, cfi_info->erase_check_algorithm->address, cfi_info->erase_check_algorithm->address + 0x10, 10000, &armv4_5_info)) != ERROR_OK)
-                               return ERROR_FLASH_OPERATION_FAILED;
-
-                       if (buf_get_u32(reg_params[2].value, 0, 32) == 0xff)
-                               bank->sectors[i].is_erased = 1;
-                       else
-                               bank->sectors[i].is_erased = 0;
-
-                       destroy_reg_param(&reg_params[0]);
-                       destroy_reg_param(&reg_params[1]);
-                       destroy_reg_param(&reg_params[2]);
-               }
-       }
-
-       return ERROR_OK;
-}
 
 int cfi_intel_protect_check(struct flash_bank_s *bank)
 {
index 8099c4ea6ff37711f6f10d38f26a6b8c48b0cac6..803678d435f3829e5787abb9c9f8f3a71e80e5f4 100644 (file)
@@ -26,7 +26,7 @@
 typedef struct cfi_flash_bank_s
 {
        working_area_t *write_algorithm;
-       working_area_t *erase_check_algorithm;
+       
 
        int x16_as_x8;
        int jedec_probe;
index d5159b97f254c55d7efda85f58a957bc445306ff..9607725834692a6702e8ef7eebd6f0b3cba8cc2a 100644 (file)
 #include "fileio.h"
 #include "image.h"
 #include "log.h"
+#include "armv4_5.h"
+#include "algorithm.h"
+#include "binarybuffer.h"
+#include "armv7m.h"
 
 #include <string.h>
 #include <unistd.h>
@@ -336,22 +340,12 @@ int handle_flash_info_command(struct command_context_s *cmd_ctx, char *cmd, char
                        /* attempt auto probe */
                        if ((retval = p->driver->auto_probe(p)) != ERROR_OK)
                                return retval;
-                       
-                       if ((retval = p->driver->erase_check(p)) != ERROR_OK)
-                               return retval;
 
                        command_print(cmd_ctx, "#%i: %s at 0x%8.8x, size 0x%8.8x, buswidth %i, chipwidth %i",
                                                i, p->driver->name, p->base, p->size, p->bus_width, p->chip_width);
                        for (j = 0; j < p->num_sectors; j++)
                        {
-                               char *erase_state, *protect_state;
-
-                               if (p->sectors[j].is_erased == 0)
-                                       erase_state = "not erased";
-                               else if (p->sectors[j].is_erased == 1)
-                                       erase_state = "erased";
-                               else
-                                       erase_state = "erase state unknown";
+                               char *protect_state;
 
                                if (p->sectors[j].is_protected == 0)
                                        protect_state = "not protected";
@@ -360,9 +354,9 @@ int handle_flash_info_command(struct command_context_s *cmd_ctx, char *cmd, char
                                else
                                        protect_state = "protection state unknown";
 
-                               command_print(cmd_ctx, "\t#%i: 0x%8.8x (0x%x %ikB) %s, %s",
+                               command_print(cmd_ctx, "\t#%i: 0x%8.8x (0x%x %ikB) %s",
                                                        j, p->sectors[j].offset, p->sectors[j].size, p->sectors[j].size>>10,
-                                                       erase_state, protect_state);
+                                                       protect_state);
                        }
 
                        *buf = '\0'; /* initialize buffer, otherwise it migh contain garbage if driver function fails */
@@ -425,6 +419,7 @@ int handle_flash_erase_check_command(struct command_context_s *cmd_ctx, char *cm
        p = get_flash_bank_by_num(strtoul(args[0], NULL, 0));
        if (p)
        {
+               int j;
                if ((retval = p->driver->erase_check(p)) == ERROR_OK)
                {
                        command_print(cmd_ctx, "successfully checked erase state", p->driver->name, p->base);
@@ -434,6 +429,23 @@ int handle_flash_erase_check_command(struct command_context_s *cmd_ctx, char *cm
                        command_print(cmd_ctx, "unknown error when checking erase state of flash bank #%s at 0x%8.8x",
                                args[0], p->base);
                }
+               
+               for (j = 0; j < p->num_sectors; j++)
+               {
+                       char *erase_state;
+
+                       if (p->sectors[j].is_erased == 0)
+                               erase_state = "not erased";
+                       else if (p->sectors[j].is_erased == 1)
+                               erase_state = "erased";
+                       else
+                               erase_state = "erase state unknown";
+
+                       command_print(cmd_ctx, "\t#%i: 0x%8.8x (0x%x %ikB) %s",
+                                               j, p->sectors[j].offset, p->sectors[j].size, p->sectors[j].size>>10,
+                                               erase_state);
+               }
+               
        }
 
        return ERROR_OK;
@@ -1068,32 +1080,224 @@ int default_flash_blank_check(struct flash_bank_s *bank)
                return ERROR_TARGET_NOT_HALTED;
        }
        
+       int retval;
+       int fast_check=0;
+       working_area_t *erase_check_algorithm;
+#if 0
+       /* FIX! doesn't work yet... */
+       /*
+       char test(char *a, int len, char t)
+       {
+         int i=0;
+       
+         for (i=0; i<len; i++)
+               {
+                 t&=a[i];
+       
+               }
+       }
+       
+       $ arm-elf-gcc -c -mthumb -O3 test.c
+       
+       $ arm-elf-objdump --disassemble test.o
        
-       for (i = 0; i < bank->num_sectors; i++)
+       test.o:     file format elf32-littlearm
+       
+       Disassembly of section .text:
+       
+       00000000 <test>:
+          0:   b510            push    {r4, lr}
+          2:   0612            lsl     r2, r2, #24
+          4:   1c04            mov     r4, r0          (add r4, r0, #0)
+          6:   0e10            lsr     r0, r2, #24
+          8:   2200            mov     r2, #0
+          a:   2900            cmp     r1, #0
+          c:   dd04            ble     18 <test+0x18>
+          e:   5ca3            ldrb    r3, [r4, r2]
+         10:   3201            add     r2, #1
+         12:   4018            and     r0, r3
+         14:   428a            cmp     r2, r1
+         16:   dbfa            blt     e <test+0xe>
+         18:   bd10            pop     {r4, pc}
+         1a:   46c0            nop                     (mov r8, r8)
+       
+
+       */
+       u16 erase_check_code[] =
        {
-               int j;
-               bank->sectors[i].is_erased = 1;
+                0x0612,//            lsl     r2, r2, #24
+                0x1c04,//            mov     r4, r0          (add r4, r0, #0)
+                0x0e10,//            lsr     r0, r2, #24
+                0x2200,//            mov     r2, #0
+                0x2900,//            cmp     r1, #0
+                0xdd04,//            ble     18 <test+0x18>
+                0x5ca3,//            ldrb    r3, [r4, r2]
+                0x3201,//            add     r2, #1
+                0x4018,//            and     r0, r3
+                0x428a,//            cmp     r2, r1
+                0xdbfa,//            blt     e <test+0xe>
+                0x46c0,//            nop                     (mov r8, r8)
+                
+       };
+
+
+       
+       /* make sure we have a working area */
+       if (target_alloc_working_area(target, ((sizeof(erase_check_code)+3)/4)*4, &erase_check_algorithm) != ERROR_OK)
+       {
+               erase_check_algorithm = NULL;
+       }
+       
+       if (erase_check_algorithm)
+       {
+               u8 erase_check_code_buf[((sizeof(erase_check_code)+3)/4)*4];
+               LOG_DEBUG("Running fast flash erase check");
                
-               for (j=0; j<bank->sectors[i].size; j+=buffer_size)
+               for (i = 0; i < sizeof(erase_check_code)/sizeof(*erase_check_code); i++)
+                       target_buffer_set_u16(target, erase_check_code_buf + (i*2), erase_check_code[i]);
+
+               /* write algorithm code to working area */
+               if ((retval=target->type->write_memory(target, erase_check_algorithm->address, 2, sizeof(erase_check_code)/sizeof(*erase_check_code), erase_check_code_buf))==ERROR_OK)
                {
-                       int chunk;
-                       int retval;
-                       chunk=buffer_size;
-                       if (chunk>(j-bank->sectors[i].size))
+                       for (i = 0; i < bank->num_sectors; i++)
                        {
-                               chunk=(j-bank->sectors[i].size);
+                               u32 address = bank->base + bank->sectors[i].offset;
+                               u32 size = bank->sectors[i].size;
+       
+                               reg_param_t reg_params[3];
+                               armv7m_algorithm_t arm_info;
+       
+                               arm_info.common_magic = ARMV7M_COMMON_MAGIC;
+                               arm_info.core_mode = ARMV7M_MODE_ANY;
+                               arm_info.core_state = ARMV7M_STATE_THUMB;
+       
+                               init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
+                               buf_set_u32(reg_params[0].value, 0, 32, address);
+       
+                               init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
+                               buf_set_u32(reg_params[1].value, 0, 32, size);
+       
+                               init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
+                               buf_set_u32(reg_params[2].value, 0, 32, 0xff);
+       
+                               if ((retval = target->type->run_algorithm(target, 0, NULL, 3, reg_params, erase_check_algorithm->address, 
+                                               erase_check_algorithm->address + sizeof(erase_check_code) - 2, 10000, &arm_info)) != ERROR_OK)
+                                       break;
+       
+                               if (buf_get_u32(reg_params[2].value, 0, 32) == 0xff)
+                                       bank->sectors[i].is_erased = 1;
+                               else
+                                       bank->sectors[i].is_erased = 0;
+       
+                               destroy_reg_param(&reg_params[0]);
+                               destroy_reg_param(&reg_params[1]);
+                               destroy_reg_param(&reg_params[2]);
+                       }
+                       if (i == bank->num_sectors)
+                       {
+                               fast_check = 1;
                        }
+               } 
+               target_free_working_area(target, erase_check_algorithm);
+       }
+#endif
+       if (!fast_check)
+       {
+               /* try ARM7 instead */
+       
+               u32 erase_check_code[] =
+               {
+                       0xe4d03001,     /* ldrb r3, [r0], #1    */
+                       0xe0022003, /* and r2, r2, r3           */
+                       0xe2511001, /* subs r1, r1, #1          */
+                       0x1afffffb,     /* b -4                                 */
+                       0xeafffffe      /* b 0                                  */
+               };
+
+               /* make sure we have a working area */
+               if (target_alloc_working_area(target, 20, &erase_check_algorithm) == ERROR_OK)
+               {
+                       u8 erase_check_code_buf[5 * 4];
+
+                       for (i = 0; i < 5; i++)
+                               target_buffer_set_u32(target, erase_check_code_buf + (i*4), erase_check_code[i]);
+
+                       /* write algorithm code to working area */
+                       if ((retval=target->type->write_memory(target, erase_check_algorithm->address, 4, 5, erase_check_code_buf))==ERROR_OK)
+                       {
+                               for (i = 0; i < bank->num_sectors; i++)
+                               {
+                                       u32 address = bank->base + bank->sectors[i].offset;
+                                       u32 size = bank->sectors[i].size;
                        
-                       retval=target->type->read_memory(target, bank->base + bank->sectors[i].offset, 4, chunk/4, buffer);
-                       if (retval!=ERROR_OK)
-                               return retval;
-               
-                       for (nBytes = 0; nBytes < chunk; nBytes++)
+                                       reg_param_t reg_params[3];
+                                       armv4_5_algorithm_t armv4_5_info;
+                       
+                                       armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC;
+                                       armv4_5_info.core_mode = ARMV4_5_MODE_SVC;
+                                       armv4_5_info.core_state = ARMV4_5_STATE_ARM;
+                       
+                                       init_reg_param(&reg_params[0], "r0", 32, PARAM_OUT);
+                                       buf_set_u32(reg_params[0].value, 0, 32, address);
+                       
+                                       init_reg_param(&reg_params[1], "r1", 32, PARAM_OUT);
+                                       buf_set_u32(reg_params[1].value, 0, 32, size);
+                       
+                                       init_reg_param(&reg_params[2], "r2", 32, PARAM_IN_OUT);
+                                       buf_set_u32(reg_params[2].value, 0, 32, 0xff);
+                       
+                                       if ((retval = target->type->run_algorithm(target, 0, NULL, 3, reg_params, 
+                                                       erase_check_algorithm->address, erase_check_algorithm->address + 0x10, 10000, &armv4_5_info)) != ERROR_OK)
+                                               break;
+                       
+                                       if (buf_get_u32(reg_params[2].value, 0, 32) == 0xff)
+                                               bank->sectors[i].is_erased = 1;
+                                       else
+                                               bank->sectors[i].is_erased = 0;
+                       
+                                       destroy_reg_param(&reg_params[0]);
+                                       destroy_reg_param(&reg_params[1]);
+                                       destroy_reg_param(&reg_params[2]);
+                               }
+                               if (i == bank->num_sectors)
+                               {
+                                       fast_check = 1;
+                               }
+                       } 
+                       target_free_working_area(target, erase_check_algorithm);
+               }
+       }
+
+       
+       if (!fast_check)
+       {
+               LOG_USER("Running slow fallback erase check - add working memory");
+               for (i = 0; i < bank->num_sectors; i++)
+               {
+                       int j;
+                       bank->sectors[i].is_erased = 1;
+                       
+                       for (j=0; j<bank->sectors[i].size; j+=buffer_size)
                        {
-                               if (buffer[nBytes] != 0xFF)
+                               int chunk;
+                               int retval;
+                               chunk=buffer_size;
+                               if (chunk>(j-bank->sectors[i].size))
                                {
-                                       bank->sectors[i].is_erased = 0;
-                                       break;
+                                       chunk=(j-bank->sectors[i].size);
+                               }
+                               
+                               retval=target->type->read_memory(target, bank->base + bank->sectors[i].offset + j, 4, chunk/4, buffer);
+                               if (retval!=ERROR_OK)
+                                       return retval;
+                       
+                               for (nBytes = 0; nBytes < chunk; nBytes++)
+                               {
+                                       if (buffer[nBytes] != 0xFF)
+                                       {
+                                               bank->sectors[i].is_erased = 0;
+                                               break;
+                                       }
                                }
                        }
                }
index 7e26ece3a7de0167684028a93726f475931bacaa..e981310a4571be0f17afebad1f47d1d3776c9032 100644 (file)
@@ -43,7 +43,6 @@ int stm32x_probe(struct flash_bank_s *bank);
 int stm32x_auto_probe(struct flash_bank_s *bank);
 int stm32x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
 int stm32x_protect_check(struct flash_bank_s *bank);
-int stm32x_erase_check(struct flash_bank_s *bank);
 int stm32x_info(struct flash_bank_s *bank, char *buf, int buf_size);
 
 int stm32x_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
@@ -62,7 +61,7 @@ flash_driver_t stm32x_flash =
        .write = stm32x_write,
        .probe = stm32x_probe,
        .auto_probe = stm32x_auto_probe,
-       .erase_check = stm32x_erase_check,
+       .erase_check = default_flash_blank_check,
        .protect_check = stm32x_protect_check,
        .info = stm32x_info
 };
@@ -278,43 +277,6 @@ int stm32x_write_options(struct flash_bank_s *bank)
        return ERROR_OK;
 }
 
-int stm32x_blank_check(struct flash_bank_s *bank, int first, int last)
-{
-       target_t *target = bank->target;
-       u8 *buffer;
-       int i;
-       int nBytes;
-       
-       if ((first < 0) || (last > bank->num_sectors))
-               return ERROR_FLASH_SECTOR_INVALID;
-
-       if (target->state != TARGET_HALTED)
-       {
-               return ERROR_TARGET_NOT_HALTED;
-       }
-
-       buffer = malloc(256);
-       
-       for (i = first; i <= last; i++)
-       {
-               bank->sectors[i].is_erased = 1;
-
-               target->type->read_memory(target, bank->base + bank->sectors[i].offset, 4, 256/4, buffer);
-               
-               for (nBytes = 0; nBytes < 256; nBytes++)
-               {
-                       if (buffer[nBytes] != 0xFF)
-                       {
-                               bank->sectors[i].is_erased = 0;
-                               break;
-                       }
-               }       
-       }
-       
-       free(buffer);
-
-       return ERROR_OK;
-}
 
 int stm32x_protect_check(struct flash_bank_s *bank)
 {
@@ -477,7 +439,8 @@ int stm32x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 co
                return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;
        };
        
-       target_write_buffer(target, stm32x_info->write_algorithm->address, sizeof(stm32x_flash_write_code), stm32x_flash_write_code);
+       if ((retval=target_write_buffer(target, stm32x_info->write_algorithm->address, sizeof(stm32x_flash_write_code), stm32x_flash_write_code))!=ERROR_OK)
+               return retval;
 
        /* memory buffer */
        while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK)
@@ -507,7 +470,8 @@ int stm32x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 co
        {
                u32 thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count;
                
-               target_write_buffer(target, source->address, thisrun_count * 2, buffer);
+               if ((retval = target_write_buffer(target, source->address, thisrun_count * 2, buffer))!=ERROR_OK)
+                       break;
                
                buf_set_u32(reg_params[0].value, 0, 32, source->address);
                buf_set_u32(reg_params[1].value, 0, 32, address);
@@ -707,11 +671,6 @@ int stm32x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd,
        return ERROR_OK;
 }
 
-int stm32x_erase_check(struct flash_bank_s *bank)
-{
-       return stm32x_blank_check(bank, 0, bank->num_sectors - 1);
-}
-
 int stm32x_info(struct flash_bank_s *bank, char *buf, int buf_size)
 {
        snprintf(buf, buf_size, "stm32x flash driver info" );
index d459dbb054fea03c1bc922a31a527e8946b76712..adcbe74912efba7b083b11c2b23a5fce1aa0adf6 100644 (file)
@@ -72,7 +72,6 @@ target_type_t arm11_target =
     ARM11_HANDLER(assert_reset),
     ARM11_HANDLER(deassert_reset),
     ARM11_HANDLER(soft_reset_halt),
-    ARM11_HANDLER(prepare_reset_halt),
        
     ARM11_HANDLER(get_gdb_reg_list),
        
@@ -1025,12 +1024,6 @@ int arm11_soft_reset_halt(struct target_s *target)
     return ERROR_OK;
 }
 
-int arm11_prepare_reset_halt(struct target_s *target)
-{
-    FNC_INFO_NOTIMPLEMENTED;
-
-    return ERROR_OK;
-}
 
 
 /* target register access for gdb */
@@ -1707,7 +1700,7 @@ int arm11_handle_mrc_mcr(struct command_context_s *cmd_ctx, char *cmd, char **ar
 
        if (values[i] > arm11_coproc_instruction_limits[i])
        {
-           LOG_ERROR("Parameter %d out of bounds (%d max). %s",
+           LOG_ERROR("Parameter %ld out of bounds (%d max). %s",
                i + 2, arm11_coproc_instruction_limits[i],
                read ? arm11_mrc_syntax : arm11_mcr_syntax);
            return -1;
index 818db766a32679449665bbbfd22fbaedacd4709c..faa93f586de72a3b21556f7278a6e0ad8c1dc814 100644 (file)
@@ -193,7 +193,6 @@ int arm11_step(struct target_s *target, int current, u32 address, int handle_bre
 int arm11_assert_reset(struct target_s *target);
 int arm11_deassert_reset(struct target_s *target);
 int arm11_soft_reset_halt(struct target_s *target);
-int arm11_prepare_reset_halt(struct target_s *target);
 
 /* target register access for gdb */
 int arm11_get_gdb_reg_list(struct target_s *target, struct reg_s **reg_list[], int *reg_list_size);
index 118fff45ea125fc9c7f182519268bdf7261412d4..d364437a120873fb17cab2b12447ae84e02df8bf 100644 (file)
@@ -63,7 +63,6 @@ target_type_t arm720t_target =
        .assert_reset = arm7_9_assert_reset,
        .deassert_reset = arm7_9_deassert_reset,
        .soft_reset_halt = arm720t_soft_reset_halt,
-       .prepare_reset_halt = arm7_9_prepare_reset_halt,
        
        .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
 
index 5c91e9c3711a41b1e1e08a950713e33198e1c0c3..63767ae307bdb149d78d9a1df4d2e598409b15a8 100644 (file)
@@ -742,20 +742,18 @@ int arm7_9_assert_reset(target_t *target)
                LOG_ERROR("Can't assert SRST");
                return ERROR_FAIL;
        }
+
+       /* we can't know what state the target is in as we might e.g.
+        * be resetting after a power dropout, so we need to issue a tms/srst
+        */
        
-       if (target->state == TARGET_HALTED || target->state == TARGET_UNKNOWN)
-       {
-               /* if the target wasn't running, there might be working areas allocated */
-               target_free_all_working_areas(target);
-               
-               /* assert SRST and TRST */
-               /* system would get ouf sync if we didn't reset test-logic, too */
-               jtag_add_reset(1, 1);
-               
-               jtag_add_sleep(5000);
-               
-       }
+       /* assert SRST and TRST */
+       /* system would get ouf sync if we didn't reset test-logic, too */
+       jtag_add_reset(1, 1);
        
+       jtag_add_sleep(5000);
+
+       /* here we should issue a srst only, but we may have to assert trst as well */
        if (jtag_reset_config & RESET_SRST_PULLS_TRST)
        {
                jtag_add_reset(1, 1);
@@ -764,8 +762,13 @@ int arm7_9_assert_reset(target_t *target)
                jtag_add_reset(0, 1);
        }
        
+
        target->state = TARGET_RESET;
        jtag_add_sleep(50000);
+
+       /* at this point we TRST *may* be deasserted */
+       arm7_9_prepare_reset_halt(target);
+
        
        armv4_5_invalidate_core_regs(target);
 
@@ -908,31 +911,11 @@ int arm7_9_soft_reset_halt(struct target_s *target)
 
 int arm7_9_prepare_reset_halt(target_t *target)
 {
-       armv4_5_common_t *armv4_5 = target->arch_info;
-       arm7_9_common_t *arm7_9 = armv4_5->arch_info;
-       
-       /* poll the target, and resume if it was currently halted */
-       arm7_9_poll(target);
-       if (target->state == TARGET_HALTED)
+       if ((target->reset_mode!=RESET_HALT)&&(target->reset_mode!=RESET_INIT))
        {
-               arm7_9_resume(target, 1, 0x0, 0, 1);
-       }
-       
-       if (arm7_9->has_vector_catch)
-       {
-               /* program vector catch register to catch reset vector */
-               embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_VEC_CATCH], 0x1);
-       }
-       else
-       {
-               /* program watchpoint unit to match on reset vector address */
-               embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_ADDR_MASK], 0x3);
-               embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_DATA_MASK], 0x0);
-               embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_VALUE], 0x100);
-               embeddedice_write_reg(&arm7_9->eice_cache->reg_list[EICE_W0_CONTROL_MASK], 0xf7);
+               return ERROR_OK;
        }
-       
-       return ERROR_OK;
+       return arm7_9_halt(target);
 }
 
 int arm7_9_halt(target_t *target)
@@ -961,15 +944,6 @@ int arm7_9_halt(target_t *target)
                        LOG_ERROR("can't request a halt while in reset if nSRST pulls nTRST");
                        return ERROR_TARGET_FAILURE;
                }
-               else
-               {
-                       /* we came here in a reset_halt or reset_init sequence
-                        * debug entry was already prepared in arm7_9_prepare_reset_halt()
-                        */
-                       target->debug_reason = DBG_REASON_DBGRQ;
-                       
-                       return ERROR_OK; 
-               }
        }
 
        if (arm7_9->use_dbgrq)
index d0cebfe4ebba99666d211fa71a27344409b14247..35902ba64a34d284457e257397cd5777ff644631 100644 (file)
@@ -68,7 +68,6 @@ target_type_t arm7tdmi_target =
        .assert_reset = arm7_9_assert_reset,
        .deassert_reset = arm7_9_deassert_reset,
        .soft_reset_halt = arm7_9_soft_reset_halt,
-       .prepare_reset_halt = arm7_9_prepare_reset_halt,
 
        .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
        
index 2468202fbc03de1893b2035388e717e90751d1d1..ae8814e5a4e087f4a2dc9dbfbba3a6059187cb04 100644 (file)
@@ -72,7 +72,6 @@ target_type_t arm920t_target =
        .assert_reset = arm7_9_assert_reset,
        .deassert_reset = arm7_9_deassert_reset,
        .soft_reset_halt = arm920t_soft_reset_halt,
-       .prepare_reset_halt = arm7_9_prepare_reset_halt,
        
        .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
 
index 4636023094d74bb9ccf825322bc0339e52c8bdc5..14cd674ae9c2b2eb6c3e0fe4f6e12560ed2ff5e9 100644 (file)
@@ -72,7 +72,6 @@ target_type_t arm926ejs_target =
        .assert_reset = arm7_9_assert_reset,
        .deassert_reset = arm7_9_deassert_reset,
        .soft_reset_halt = arm926ejs_soft_reset_halt,
-       .prepare_reset_halt = arm7_9_prepare_reset_halt,
        
        .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
 
index 0201ca56c227937bc609304b4d6886c7bb0e9e42..84c55cf4849ef473b9a6c8d7089fdd899a414079 100644 (file)
@@ -63,7 +63,6 @@ target_type_t arm966e_target =
        .assert_reset = arm7_9_assert_reset,
        .deassert_reset = arm7_9_deassert_reset,
        .soft_reset_halt = arm7_9_soft_reset_halt,
-       .prepare_reset_halt = arm7_9_prepare_reset_halt,
 
        .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
 
index 9811aeda603fd3eca6e60d07ae12b8d23a4e428e..4a4b9a1c1b08a52d7fda477966e5c5b27dffc5e0 100644 (file)
@@ -66,7 +66,6 @@ target_type_t arm9tdmi_target =
        .assert_reset = arm7_9_assert_reset,
        .deassert_reset = arm7_9_deassert_reset,
        .soft_reset_halt = arm7_9_soft_reset_halt,
-       .prepare_reset_halt = arm7_9_prepare_reset_halt,
 
        .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
 
index dfd38ebe22a8972abc8ceab3bfb49a09aa6c32ee..0b6b34570a6f702461ddd241ea6ad949917accb1 100644 (file)
@@ -504,6 +504,7 @@ int armv4_5_run_algorithm(struct target_s *target, int num_mem_params, mem_param
        int exit_breakpoint_size = 0;
        int i;
        int retval = ERROR_OK;
+       LOG_DEBUG("Running algorithm");
        
        if (armv4_5_algorithm_info->common_magic != ARMV4_5_COMMON_MAGIC)
        {
index aa67474508052eb9b8f1933797f7154b3d6cddc6..406a00af47194652c57b3696ecc0725267c3ecb8 100644 (file)
@@ -70,7 +70,6 @@ target_type_t cortexm3_target =
        .assert_reset = cortex_m3_assert_reset,
        .deassert_reset = cortex_m3_deassert_reset,
        .soft_reset_halt = cortex_m3_soft_reset_halt,
-       .prepare_reset_halt = cortex_m3_prepare_reset_halt,
        
        .get_gdb_reg_list = armv7m_get_gdb_reg_list,
 
@@ -202,9 +201,6 @@ int cortex_m3_endreset_event(target_t *target)
        }
        swjdp_transaction_endcheck(swjdp);
        
-       /* Make sure working_areas are all free */
-       target_free_all_working_areas(target);
-       
        /* We are in process context */
        armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
        armv7m_invalidate_core_regs(target);
@@ -704,6 +700,7 @@ int cortex_m3_assert_reset(target_t *target)
        armv7m_common_t *armv7m = target->arch_info;
        cortex_m3_common_t *cortex_m3 = armv7m->arch_info;
        swjdp_common_t *swjdp = &cortex_m3->swjdp_info;
+       int retval;
        
        LOG_DEBUG("target->state: %s", target_state_strings[target->state]);
        
@@ -712,7 +709,10 @@ int cortex_m3_assert_reset(target_t *target)
                LOG_ERROR("Can't assert SRST");
                return ERROR_FAIL;
        }
-
+       /* FIX!!! should this be removed as we're asserting trst anyway? */
+       if ((retval=cortex_m3_prepare_reset_halt(target))!=ERROR_OK)
+               return retval;
+       
        ahbap_write_system_u32(swjdp, DCB_DCRDR, 0 );
        
        if (target->reset_mode == RESET_RUN)
@@ -720,7 +720,7 @@ int cortex_m3_assert_reset(target_t *target)
                /* Set/Clear C_MASKINTS in a separate operation */
                if (cortex_m3->dcb_dhcsr & C_MASKINTS)
                        ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN | C_HALT );
-               
+       
                cortex_m3_clear_halt(target);
                                                        
                /* Enter debug state on reset, cf. end_reset_event() */ 
@@ -730,10 +730,10 @@ int cortex_m3_assert_reset(target_t *target)
        
        if (target->state == TARGET_HALTED || target->state == TARGET_UNKNOWN)
        {
-               /* assert SRST and TRST */
-               /* system would get ouf sync if we didn't reset test-logic, too */
-               jtag_add_reset(1, 1);
-               jtag_add_sleep(5000);
+       /* assert SRST and TRST */
+       /* system would get ouf sync if we didn't reset test-logic, too */
+       jtag_add_reset(1, 1);
+       jtag_add_sleep(5000);
        }
 
        if (jtag_reset_config & RESET_SRST_PULLS_TRST)
@@ -747,6 +747,12 @@ int cortex_m3_assert_reset(target_t *target)
        target->state = TARGET_RESET;
        jtag_add_sleep(50000);
        
+       #if 0
+       if ((target->reset_mode==RESET_HALT)||(target->reset_mode==RESET_INIT))
+       {
+               cortex_m3_halt(target);
+       }
+       #endif
        armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT);
        armv7m_invalidate_core_regs(target);
 
index 8178c82c702f987d4e2834858951a3a02913ac6e..bbec5976114214ff25d3f165b8f10324d38888fd 100644 (file)
@@ -18,4 +18,5 @@ mww 0x54000018, 0x18 #Enable CS on both banks
 mww 0x5C002034, 0x0191 # PFQBC enabled / DTCM & AHB wait-states disabled\r
 arm966e cp15 15, 0x60000 #Set bits 17-18 (DTCM/ITCM order bits) of the Core Configuration Control Register\r
 \r
+str9x flash_config 0 4 2 0 0x80000\r
 flash protect 0 0 7 off\r
index bad110e061a41c8ec84846b619bb205a7868ad1a..0c1d46dabc7fb199051b11da1c5240e20da79452 100644 (file)
@@ -76,7 +76,6 @@ target_type_t feroceon_target =
        .assert_reset = arm7_9_assert_reset,
        .deassert_reset = arm7_9_deassert_reset,
        .soft_reset_halt = arm926ejs_soft_reset_halt,
-       .prepare_reset_halt = arm7_9_prepare_reset_halt,
        
        .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
 
index f098ef3484ec648d82dd5ccae7b56aa996dc8aac..f90834d1bd8263c006922ed4e8d843022fa3b041 100644 (file)
@@ -284,21 +284,16 @@ int target_process_reset(struct command_context_s *cmd_ctx)
                                        break;
                        } 
                }
-               switch (target->reset_mode)
-               {
-                       case RESET_HALT:
-                       case RESET_INIT:
-                               target->type->prepare_reset_halt(target);
-                               break;
-                       default:
-                               break;
-               }
                target = target->next;
        }
        
        target = targets;
        while (target)
        {
+               /* we have no idea what state the target is in, so we
+                * have to drop working areas
+                */
+               target_free_all_working_areas_restore(target, 0);
                target->type->assert_reset(target);
                target = target->next;
        }
@@ -343,6 +338,8 @@ int target_process_reset(struct command_context_s *cmd_ctx)
        }
        jtag_execute_queue();
        
+       LOG_DEBUG("Waiting for halted stated as approperiate");
+       
        /* Wait for reset to complete, maximum 5 seconds. */    
        gettimeofday(&timeout, NULL);
        timeval_add_time(&timeout, 5, 0);
@@ -355,14 +352,18 @@ int target_process_reset(struct command_context_s *cmd_ctx)
                target = targets;
                while (target)
                {
+                       LOG_DEBUG("Polling target");
                        target->type->poll(target);
-                       if ((target->reset_mode == RESET_RUN_AND_INIT) || (target->reset_mode == RESET_RUN_AND_HALT))
+                       if ((target->reset_mode == RESET_RUN_AND_INIT) || 
+                                       (target->reset_mode == RESET_RUN_AND_HALT) ||
+                                       (target->reset_mode == RESET_HALT) ||
+                                       (target->reset_mode == RESET_INIT))
                        {
                                if (target->state != TARGET_HALTED)
                                {
                                        if ((now.tv_sec > timeout.tv_sec) || ((now.tv_sec == timeout.tv_sec) && (now.tv_usec >= timeout.tv_usec)))
                                        {
-                                               LOG_USER("Timed out waiting for reset");
+                                               LOG_USER("Timed out waiting for halt after reset");
                                                goto done;
                                        }
                                        /* this will send alive messages on e.g. GDB remote protocol. */
@@ -384,6 +385,16 @@ int target_process_reset(struct command_context_s *cmd_ctx)
        /* We want any events to be processed before the prompt */
        target_call_timer_callbacks_now();
 
+       /* if we timed out we need to unregister these handlers */
+       target = targets;
+       while (target)
+       {
+               target_unregister_timer_callback(target_run_and_halt_handler, target);
+               target = target->next;
+       }
+       target_unregister_event_callback(target_init_handler, cmd_ctx);
+                               
+       
        jtag->speed(jtag_speed_post_reset);
        
        return retval;
@@ -722,12 +733,12 @@ int target_alloc_working_area(struct target_s *target, u32 size, working_area_t
        return ERROR_OK;
 }
 
-int target_free_working_area(struct target_s *target, working_area_t *area)
+int target_free_working_area_restore(struct target_s *target, working_area_t *area, int restore)
 {
        if (area->free)
                return ERROR_OK;
        
-       if (target->backup_working_area)
+       if (restore&&target->backup_working_area)
                target->type->write_memory(target, area->address, 4, area->size / 4, area->backup);
        
        area->free = 1;
@@ -739,14 +750,19 @@ int target_free_working_area(struct target_s *target, working_area_t *area)
        return ERROR_OK;
 }
 
-int target_free_all_working_areas(struct target_s *target)
+int target_free_working_area(struct target_s *target, working_area_t *area)
+{
+       return target_free_working_area_restore(target, area, 1);
+}
+
+int target_free_all_working_areas_restore(struct target_s *target, int restore)
 {
        working_area_t *c = target->working_areas;
 
        while (c)
        {
                working_area_t *next = c->next;
-               target_free_working_area(target, c);
+               target_free_working_area_restore(target, c, restore);
                
                if (c->backup)
                        free(c->backup);
@@ -761,6 +777,11 @@ int target_free_all_working_areas(struct target_s *target)
        return ERROR_OK;
 }
 
+int target_free_all_working_areas(struct target_s *target)
+{
+       return target_free_all_working_areas_restore(target, 1); 
+}
+
 int target_register_commands(struct command_context_s *cmd_ctx)
 {
        register_command(cmd_ctx, NULL, "target", handle_target_command, COMMAND_CONFIG, NULL);
index fa83949b3b77652cbcd03e14e52ad1d4a7d44c49..6ce8fee9fccca1ca51f6566e9e2b10cece11d39f 100644 (file)
@@ -121,11 +121,19 @@ typedef struct target_type_s
        int (*resume)(struct target_s *target, int current, u32 address, int handle_breakpoints, int debug_execution);
        int (*step)(struct target_s *target, int current, u32 address, int handle_breakpoints);
        
-       /* target reset control */
+       /* target reset control. assert reset can be invoked when OpenOCD and
+        * the target is out of sync.
+        * 
+        * A typical example is that the target was power cycled while OpenOCD
+        * thought the target was halted or running.
+        * 
+        * assert_reset() can therefore make no assumptions whatsoever about the
+        * state of the target 
+        * 
+        */
        int (*assert_reset)(struct target_s *target);
        int (*deassert_reset)(struct target_s *target);
        int (*soft_reset_halt)(struct target_s *target);
-       int (*prepare_reset_halt)(struct target_s *target);
        
        /* target register access for gdb.
         * 
@@ -258,9 +266,23 @@ extern int target_write_buffer(struct target_s *target, u32 address, u32 size, u
 extern int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffer);
 extern int target_checksum_memory(struct target_s *target, u32 address, u32 size, u32* crc);
 
+/* DANGER!!!!!
+ * 
+ * if "area" passed in to target_alloc_working_area() points to a memory
+ * location that goes out of scope (e.g. a pointer on the stack), then
+ * the caller of target_alloc_working_area() is responsible for invoking
+ * target_free_working_area() before "area" goes out of scope.
+ * 
+ * target_free_all_working_areas() will NULL out the "area" pointer
+ * upon resuming or resetting the CPU.
+ * 
+ */
 extern int target_alloc_working_area(struct target_s *target, u32 size, working_area_t **area);
 extern int target_free_working_area(struct target_s *target, working_area_t *area);
+extern int target_free_working_area_restore(struct target_s *target, working_area_t *area, int restore);
 extern int target_free_all_working_areas(struct target_s *target);
+extern int target_free_all_working_areas_restore(struct target_s *target, int restore);
+
 
 extern target_t *targets;
 
diff --git a/src/target/target/readme.txt b/src/target/target/readme.txt
new file mode 100644 (file)
index 0000000..b8bf5dc
--- /dev/null
@@ -0,0 +1,18 @@
+Prerequisites:\r
+The users of OpenOCD as well as computer programs interacting with OpenOCD are expecting that certain commands \r
+do the same thing across all the targets.\r
+\r
+Rules to follow when writing scripts:\r
+\r
+1. The configuration script should be defined such as , for example, the following sequences are working:\r
+       reset\r
+       flash info <bank>\r
+and\r
+       reset \r
+       flash erase_address <start> <len>\r
+       \r
+In most cases this can be accomplished by specifying the default startup mode as reset_init (target command \r
+in the configuration file).\r
\r
+2. If the target is correctly configured, flash must be writable without any other helper commands. It is \r
+assumed that all write-protect mechanisms should be disabled.\r
index 68c42e5b5887bd9c0528ae45a9be5c2b9a409f7e..0cffeb1df7eeb18ec6ac5fd7314d757af3c4e6bf 100644 (file)
@@ -11,7 +11,7 @@ jtag_device 5 0x1 0x1 0x1e
 
 #target <type> <startup mode>
 #target arm7tdmi <reset mode> <chainpos> <endianness> <variant>
-target cortex_m3 little reset_halt 0
+target cortex_m3 little reset_init 0
 run_and_halt_time 0 30
 
 working_area 0 0x20000000 16384 nobackup
index 89ecc2658739484cafabcc79d7e9d4a09513afb6..1d379f59184879c9fe7a1a297698b5170fbc1878 100644 (file)
@@ -64,7 +64,6 @@ int xscale_restore_context(target_t *target);
 int xscale_assert_reset(target_t *target);
 int xscale_deassert_reset(target_t *target);
 int xscale_soft_reset_halt(struct target_s *target);
-int xscale_prepare_reset_halt(struct target_s *target);
 
 int xscale_set_reg_u32(reg_t *reg, u32 value);
 
@@ -105,7 +104,6 @@ target_type_t xscale_target =
        .assert_reset = xscale_assert_reset,
        .deassert_reset = xscale_deassert_reset,
        .soft_reset_halt = xscale_soft_reset_halt,
-       .prepare_reset_halt = xscale_prepare_reset_halt,
 
        .get_gdb_reg_list = armv4_5_get_gdb_reg_list,
 
@@ -1780,14 +1778,6 @@ int xscale_soft_reset_halt(struct target_s *target)
        return ERROR_OK;
 }
 
-int xscale_prepare_reset_halt(struct target_s *target)
-{
-       /* nothing to be done for reset_halt on XScale targets
-        * we always halt after a reset to upload the debug handler
-        */
-       return ERROR_OK;
-}
-
 int xscale_read_core_reg(struct target_s *target, int num, enum armv4_5_mode mode)
 {
 

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)