X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Ftarget%2Farmv7m.c;h=7d3bd73674d554e8aa14fd96991418c687a023e6;hp=e2f710f147aeab260927253525d59982b18a0d17;hb=6fa18a455f7aa78182cdead94278a8659f2dbc89;hpb=d0e763ac7ef6aa17b17bd00ccdfbccfb4eacda69 diff --git a/src/target/armv7m.c b/src/target/armv7m.c index e2f710f147..7d3bd73674 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -11,6 +11,9 @@ * Copyright (C) 2007,2008 Øyvind Harboe * * oyvind.harboe@zylin.com * * * + * Copyright (C) 2018 by Liviu Ionescu * + * * + * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * @@ -37,6 +40,7 @@ #include "armv7m.h" #include "algorithm.h" #include "register.h" +#include "semihosting_common.h" #if 0 #define _DEBUG_INSTRUCTION_EXECUTION_ @@ -318,7 +322,7 @@ int armv7m_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int armv7m_run_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, uint32_t exit_point, + target_addr_t entry_point, target_addr_t exit_point, int timeout_ms, void *arch_info) { int retval; @@ -343,7 +347,7 @@ int armv7m_run_algorithm(struct target *target, int armv7m_start_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t entry_point, uint32_t exit_point, + target_addr_t entry_point, target_addr_t exit_point, void *arch_info) { struct armv7m_common *armv7m = target_to_armv7m(target); @@ -431,7 +435,7 @@ int armv7m_start_algorithm(struct target *target, int armv7m_wait_algorithm(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, struct reg_param *reg_params, - uint32_t exit_point, int timeout_ms, + target_addr_t exit_point, int timeout_ms, void *arch_info) { struct armv7m_common *armv7m = target_to_armv7m(target); @@ -461,7 +465,7 @@ int armv7m_wait_algorithm(struct target *target, armv7m->load_core_reg_u32(target, 15, &pc); if (exit_point && (pc != exit_point)) { - LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 ", expected 0x%" PRIx32, + LOG_DEBUG("failed algorithm halted at 0x%" PRIx32 ", expected 0x%" TARGET_PRIxADDR, pc, exit_point); return ERROR_TARGET_TIMEOUT; @@ -536,11 +540,15 @@ int armv7m_arch_state(struct target *target) struct arm *arm = &armv7m->arm; uint32_t ctrl, sp; + /* avoid filling log waiting for fileio reply */ + if (target->semihosting && target->semihosting->hit_fileio) + return ERROR_OK; + ctrl = buf_get_u32(arm->core_cache->reg_list[ARMV7M_CONTROL].value, 0, 32); sp = buf_get_u32(arm->core_cache->reg_list[ARMV7M_R13].value, 0, 32); LOG_USER("target halted due to %s, current mode: %s %s\n" - "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32 "%s", + "xPSR: %#8.8" PRIx32 " pc: %#8.8" PRIx32 " %csp: %#8.8" PRIx32 "%s%s", debug_reason_name(target), arm_mode_name(arm->core_mode), armv7m_exception_string(armv7m->exception_number), @@ -548,7 +556,8 @@ int armv7m_arch_state(struct target *target) buf_get_u32(arm->pc->value, 0, 32), (ctrl & 0x02) ? 'p' : 'm', sp, - arm->is_semihosting ? ", semihosting" : ""); + (target->semihosting && target->semihosting->is_active) ? ", semihosting" : "", + (target->semihosting && target->semihosting->is_fileio) ? " fileio" : ""); return ERROR_OK; } @@ -677,7 +686,7 @@ int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m) /** Generates a CRC32 checksum of a memory region. */ int armv7m_checksum_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *checksum) + target_addr_t address, uint32_t count, uint32_t *checksum) { struct working_area *crc_algorithm; struct armv7m_algorithm armv7m_info; @@ -726,59 +735,134 @@ cleanup: return retval; } -/** Checks whether a memory region is zeroed. */ +/** Checks an array of memory regions whether they are erased. */ int armv7m_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank) + struct target_memory_check_block *blocks, int num_blocks, uint8_t erased_value) { struct working_area *erase_check_algorithm; - struct reg_param reg_params[3]; + struct working_area *erase_check_params; + struct reg_param reg_params[2]; struct armv7m_algorithm armv7m_info; int retval; + static bool timed_out; + static const uint8_t erase_check_code[] = { #include "../../contrib/loaders/erase_check/armv7m_erase_check.inc" }; + const uint32_t code_size = sizeof(erase_check_code); + /* make sure we have a working area */ - if (target_alloc_working_area(target, sizeof(erase_check_code), + if (target_alloc_working_area(target, code_size, &erase_check_algorithm) != ERROR_OK) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; retval = target_write_buffer(target, erase_check_algorithm->address, - sizeof(erase_check_code), (uint8_t *)erase_check_code); + code_size, erase_check_code); if (retval != ERROR_OK) - goto cleanup; + goto cleanup1; + + /* prepare blocks array for algo */ + struct algo_block { + union { + uint32_t size; + uint32_t result; + }; + uint32_t address; + }; + + uint32_t avail = target_get_working_area_avail(target); + int blocks_to_check = avail / sizeof(struct algo_block) - 1; + if (num_blocks < blocks_to_check) + blocks_to_check = num_blocks; + + struct algo_block *params = malloc((blocks_to_check+1)*sizeof(struct algo_block)); + if (params == NULL) { + retval = ERROR_FAIL; + goto cleanup1; + } + + int i; + uint32_t total_size = 0; + for (i = 0; i < blocks_to_check; i++) { + total_size += blocks[i].size; + target_buffer_set_u32(target, (uint8_t *)&(params[i].size), + blocks[i].size / sizeof(uint32_t)); + target_buffer_set_u32(target, (uint8_t *)&(params[i].address), + blocks[i].address); + } + target_buffer_set_u32(target, (uint8_t *)&(params[blocks_to_check].size), 0); + + uint32_t param_size = (blocks_to_check + 1) * sizeof(struct algo_block); + if (target_alloc_working_area(target, param_size, + &erase_check_params) != ERROR_OK) { + retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + goto cleanup2; + } + + retval = target_write_buffer(target, erase_check_params->address, + param_size, (uint8_t *)params); + if (retval != ERROR_OK) + goto cleanup3; + + uint32_t erased_word = erased_value | (erased_value << 8) + | (erased_value << 16) | (erased_value << 24); + + LOG_DEBUG("Starting erase check of %d blocks, parameters@" + TARGET_ADDR_FMT, blocks_to_check, erase_check_params->address); armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; init_reg_param(®_params[0], "r0", 32, PARAM_OUT); - buf_set_u32(reg_params[0].value, 0, 32, address); + buf_set_u32(reg_params[0].value, 0, 32, erase_check_params->address); init_reg_param(®_params[1], "r1", 32, PARAM_OUT); - buf_set_u32(reg_params[1].value, 0, 32, count); + buf_set_u32(reg_params[1].value, 0, 32, erased_word); - init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); - buf_set_u32(reg_params[2].value, 0, 32, 0xff); + /* assume CPU clk at least 1 MHz */ + int timeout = (timed_out ? 30000 : 2000) + total_size * 3 / 1000; retval = target_run_algorithm(target, - 0, - NULL, - 3, - reg_params, - erase_check_algorithm->address, - erase_check_algorithm->address + (sizeof(erase_check_code) - 2), - 10000, - &armv7m_info); + 0, NULL, + ARRAY_SIZE(reg_params), reg_params, + erase_check_algorithm->address, + erase_check_algorithm->address + (code_size - 2), + timeout, + &armv7m_info); + + timed_out = retval == ERROR_TARGET_TIMEOUT; + if (retval != ERROR_OK && !timed_out) + goto cleanup4; + + retval = target_read_buffer(target, erase_check_params->address, + param_size, (uint8_t *)params); + if (retval != ERROR_OK) + goto cleanup4; - if (retval == ERROR_OK) - *blank = buf_get_u32(reg_params[2].value, 0, 32); + for (i = 0; i < blocks_to_check; i++) { + uint32_t result = target_buffer_get_u32(target, + (uint8_t *)&(params[i].result)); + if (result != 0 && result != 1) + break; + + blocks[i].result = result; + } + if (i && timed_out) + LOG_INFO("Slow CPU clock: %d blocks checked, %d remain. Continuing...", i, num_blocks-i); + + retval = i; /* return number of blocks really checked */ +cleanup4: destroy_reg_param(®_params[0]); destroy_reg_param(®_params[1]); - destroy_reg_param(®_params[2]); -cleanup: +cleanup3: + target_free_working_area(target, erase_check_params); +cleanup2: + free(params); +cleanup1: target_free_working_area(target, erase_check_algorithm); return retval; @@ -822,8 +906,5 @@ const struct command_registration armv7m_command_handlers[] = { { .chain = arm_command_handlers, }, - { - .chain = dap_command_handlers, - }, COMMAND_REGISTRATION_DONE };