]> git.gag.com Git - fw/openocd/blobdiff - src/target/target.c
target: remove handle_profile_command memory leak
[fw/openocd] / src / target / target.c
index cb54ced5e5733ac42044b37371f498d4a55103c9..b868383d1bed017654b2dfcceb232060293c0fe4 100644 (file)
@@ -102,6 +102,7 @@ extern struct target_type nds32_v2_target;
 extern struct target_type nds32_v3_target;
 extern struct target_type nds32_v3m_target;
 extern struct target_type or1k_target;
+extern struct target_type quark_x10xx_target;
 
 static struct target_type *target_types[] = {
        &arm7tdmi_target,
@@ -130,6 +131,7 @@ static struct target_type *target_types[] = {
        &nds32_v3_target,
        &nds32_v3m_target,
        &or1k_target,
+       &quark_x10xx_target,
        NULL,
 };
 
@@ -851,7 +853,7 @@ done:
  */
 
 int target_run_flash_async_algorithm(struct target *target,
-               uint8_t *buffer, uint32_t count, int block_size,
+               const uint8_t *buffer, uint32_t count, int block_size,
                int num_mem_params, struct mem_param *mem_params,
                int num_reg_params, struct reg_param *reg_params,
                uint32_t buffer_start, uint32_t buffer_size,
@@ -1359,7 +1361,7 @@ int target_unregister_event_callback(int (*callback)(struct target *target,
        return ERROR_OK;
 }
 
-static int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
+int target_unregister_timer_callback(int (*callback)(void *priv), void *priv)
 {
        struct target_timer_callback **p = &target_timer_callbacks;
        struct target_timer_callback *c = target_timer_callbacks;
@@ -2377,6 +2379,10 @@ static int handle_target(void *priv)
        for (struct target *target = all_targets;
                        is_jtag_poll_safe() && target;
                        target = target->next) {
+
+               if (!target_was_examined(target))
+                       continue;
+
                if (!target->tap->enabled)
                        continue;
 
@@ -3614,14 +3620,15 @@ COMMAND_HANDLER(handle_profile_command)
        uint32_t offset;
        uint32_t num_of_sampels;
        int retval = ERROR_OK;
+
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], offset);
+
        uint32_t *samples = malloc(sizeof(uint32_t) * MAX_PROFILE_SAMPLE_NUM);
        if (samples == NULL) {
                LOG_ERROR("No memory to store samples.");
                return ERROR_FAIL;
        }
 
-       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], offset);
-
        /**
         * Some cores let us sample the PC without the
         * annoying halt/resume step; for example, ARMv7 PCSR.
@@ -5642,6 +5649,198 @@ COMMAND_HANDLER(handle_ps_command)
        }
 }
 
+static void binprint(struct command_context *cmd_ctx, const char *text, const uint8_t *buf, int size)
+{
+       if (text != NULL)
+               command_print_sameline(cmd_ctx, "%s", text);
+       for (int i = 0; i < size; i++)
+               command_print_sameline(cmd_ctx, " %02x", buf[i]);
+       command_print(cmd_ctx, " ");
+}
+
+COMMAND_HANDLER(handle_test_mem_access_command)
+{
+       struct target *target = get_current_target(CMD_CTX);
+       uint32_t test_size;
+       int retval = ERROR_OK;
+
+       if (target->state != TARGET_HALTED) {
+               LOG_INFO("target not halted !!");
+               return ERROR_FAIL;
+       }
+
+       if (CMD_ARGC != 1)
+               return ERROR_COMMAND_SYNTAX_ERROR;
+
+       COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], test_size);
+
+       /* Test reads */
+       size_t num_bytes = test_size + 4;
+
+       struct working_area *wa = NULL;
+       retval = target_alloc_working_area(target, num_bytes, &wa);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Not enough working area");
+               return ERROR_FAIL;
+       }
+
+       uint8_t *test_pattern = malloc(num_bytes);
+
+       for (size_t i = 0; i < num_bytes; i++)
+               test_pattern[i] = rand();
+
+       retval = target_write_memory(target, wa->address, 1, num_bytes, test_pattern);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Test pattern write failed");
+               goto out;
+       }
+
+       for (int host_offset = 0; host_offset <= 1; host_offset++) {
+               for (int size = 1; size <= 4; size *= 2) {
+                       for (int offset = 0; offset < 4; offset++) {
+                               uint32_t count = test_size / size;
+                               size_t host_bufsiz = (count + 2) * size + host_offset;
+                               uint8_t *read_ref = malloc(host_bufsiz);
+                               uint8_t *read_buf = malloc(host_bufsiz);
+
+                               for (size_t i = 0; i < host_bufsiz; i++) {
+                                       read_ref[i] = rand();
+                                       read_buf[i] = read_ref[i];
+                               }
+                               command_print_sameline(CMD_CTX,
+                                               "Test read %d x %d @ %d to %saligned buffer: ", count,
+                                               size, offset, host_offset ? "un" : "");
+
+                               struct duration bench;
+                               duration_start(&bench);
+
+                               retval = target_read_memory(target, wa->address + offset, size, count,
+                                               read_buf + size + host_offset);
+
+                               duration_measure(&bench);
+
+                               if (retval == ERROR_TARGET_UNALIGNED_ACCESS) {
+                                       command_print(CMD_CTX, "Unsupported alignment");
+                                       goto next;
+                               } else if (retval != ERROR_OK) {
+                                       command_print(CMD_CTX, "Memory read failed");
+                                       goto next;
+                               }
+
+                               /* replay on host */
+                               memcpy(read_ref + size + host_offset, test_pattern + offset, count * size);
+
+                               /* check result */
+                               int result = memcmp(read_ref, read_buf, host_bufsiz);
+                               if (result == 0) {
+                                       command_print(CMD_CTX, "Pass in %fs (%0.3f KiB/s)",
+                                                       duration_elapsed(&bench),
+                                                       duration_kbps(&bench, count * size));
+                               } else {
+                                       command_print(CMD_CTX, "Compare failed");
+                                       binprint(CMD_CTX, "ref:", read_ref, host_bufsiz);
+                                       binprint(CMD_CTX, "buf:", read_buf, host_bufsiz);
+                               }
+next:
+                               free(read_ref);
+                               free(read_buf);
+                       }
+               }
+       }
+
+out:
+       free(test_pattern);
+
+       if (wa != NULL)
+               target_free_working_area(target, wa);
+
+       /* Test writes */
+       num_bytes = test_size + 4 + 4 + 4;
+
+       retval = target_alloc_working_area(target, num_bytes, &wa);
+       if (retval != ERROR_OK) {
+               LOG_ERROR("Not enough working area");
+               return ERROR_FAIL;
+       }
+
+       test_pattern = malloc(num_bytes);
+
+       for (size_t i = 0; i < num_bytes; i++)
+               test_pattern[i] = rand();
+
+       for (int host_offset = 0; host_offset <= 1; host_offset++) {
+               for (int size = 1; size <= 4; size *= 2) {
+                       for (int offset = 0; offset < 4; offset++) {
+                               uint32_t count = test_size / size;
+                               size_t host_bufsiz = count * size + host_offset;
+                               uint8_t *read_ref = malloc(num_bytes);
+                               uint8_t *read_buf = malloc(num_bytes);
+                               uint8_t *write_buf = malloc(host_bufsiz);
+
+                               for (size_t i = 0; i < host_bufsiz; i++)
+                                       write_buf[i] = rand();
+                               command_print_sameline(CMD_CTX,
+                                               "Test write %d x %d @ %d from %saligned buffer: ", count,
+                                               size, offset, host_offset ? "un" : "");
+
+                               retval = target_write_memory(target, wa->address, 1, num_bytes, test_pattern);
+                               if (retval != ERROR_OK) {
+                                       command_print(CMD_CTX, "Test pattern write failed");
+                                       goto nextw;
+                               }
+
+                               /* replay on host */
+                               memcpy(read_ref, test_pattern, num_bytes);
+                               memcpy(read_ref + size + offset, write_buf + host_offset, count * size);
+
+                               struct duration bench;
+                               duration_start(&bench);
+
+                               retval = target_write_memory(target, wa->address + size + offset, size, count,
+                                               write_buf + host_offset);
+
+                               duration_measure(&bench);
+
+                               if (retval == ERROR_TARGET_UNALIGNED_ACCESS) {
+                                       command_print(CMD_CTX, "Unsupported alignment");
+                                       goto nextw;
+                               } else if (retval != ERROR_OK) {
+                                       command_print(CMD_CTX, "Memory write failed");
+                                       goto nextw;
+                               }
+
+                               /* read back */
+                               retval = target_read_memory(target, wa->address, 1, num_bytes, read_buf);
+                               if (retval != ERROR_OK) {
+                                       command_print(CMD_CTX, "Test pattern write failed");
+                                       goto nextw;
+                               }
+
+                               /* check result */
+                               int result = memcmp(read_ref, read_buf, num_bytes);
+                               if (result == 0) {
+                                       command_print(CMD_CTX, "Pass in %fs (%0.3f KiB/s)",
+                                                       duration_elapsed(&bench),
+                                                       duration_kbps(&bench, count * size));
+                               } else {
+                                       command_print(CMD_CTX, "Compare failed");
+                                       binprint(CMD_CTX, "ref:", read_ref, num_bytes);
+                                       binprint(CMD_CTX, "buf:", read_buf, num_bytes);
+                               }
+nextw:
+                               free(read_ref);
+                               free(read_buf);
+                       }
+               }
+       }
+
+       free(test_pattern);
+
+       if (wa != NULL)
+               target_free_working_area(target, wa);
+       return retval;
+}
+
 static const struct command_registration target_exec_command_handlers[] = {
        {
                .name = "fast_load_image",
@@ -5679,9 +5878,9 @@ static const struct command_registration target_exec_command_handlers[] = {
                .name = "reg",
                .handler = handle_reg_command,
                .mode = COMMAND_EXEC,
-               .help = "display or set a register; with no arguments, "
-                       "displays all registers and their values",
-               .usage = "[(register_name|register_number) [value]]",
+               .help = "display (reread from target with \"force\") or set a register; "
+                       "with no arguments, displays all registers and their values",
+               .usage = "[(register_number|register_name) [(value|'force')]]",
        },
        {
                .name = "poll",
@@ -5861,6 +6060,13 @@ static const struct command_registration target_exec_command_handlers[] = {
                .help = "list all tasks ",
                .usage = " ",
        },
+       {
+               .name = "test_mem_access",
+               .handler = handle_test_mem_access_command,
+               .mode = COMMAND_EXEC,
+               .help = "Test the target's memory access functions",
+               .usage = "size",
+       },
 
        COMMAND_REGISTRATION_DONE
 };