From: ntfreak Date: Sun, 24 Jun 2007 15:04:07 +0000 (+0000) Subject: - ST STM32x cortex support added X-Git-Tag: v0.1.0~1101 X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=commitdiff_plain;h=8c290412d28f9eef568dac0cfc20ccd4a9eca4d5 - ST STM32x cortex support added - ST STM32x flash support added - cleaned up armv7m and cortex-m3 support, removed luminary specific code - cortex-m3 16bit read/write added (required for STM32x flash programming) git-svn-id: svn://svn.berlios.de/openocd/trunk@177 b42882b7-edfa-0310-969c-e2dbd0fdcd60 --- diff --git a/src/flash/Makefile.am b/src/flash/Makefile.am index 7b5c52222d..76c8c180ff 100644 --- a/src/flash/Makefile.am +++ b/src/flash/Makefile.am @@ -1,5 +1,7 @@ INCLUDES = -I$(top_srcdir)/src/helper -I$(top_srcdir)/src/jtag -I$(top_srcdir)/src/target $(all_includes) METASOURCES = AUTO noinst_LIBRARIES = libflash.a -libflash_a_SOURCES = flash.c lpc2000.c cfi.c non_cfi.c at91sam7.c str7x.c str9x.c nand.c lpc3180_nand_controller.c stellaris.c str9xpec.c -noinst_HEADERS = flash.h lpc2000.h cfi.h non_cfi.h at91sam7.h str7x.h str9x.h nand.h lpc3180_nand_controller.h stellaris.h str9xpec.h +libflash_a_SOURCES = flash.c lpc2000.c cfi.c non_cfi.c at91sam7.c str7x.c str9x.c nand.c lpc3180_nand_controller.c \ + stellaris.c str9xpec.c stm32x.c +noinst_HEADERS = flash.h lpc2000.h cfi.h non_cfi.h at91sam7.h str7x.h str9x.h nand.h lpc3180_nand_controller.h \ + stellaris.h str9xpec.h stm32x.h diff --git a/src/flash/flash.c b/src/flash/flash.c index eaa1e17eec..1e091d2666 100644 --- a/src/flash/flash.c +++ b/src/flash/flash.c @@ -57,6 +57,7 @@ extern flash_driver_t str7x_flash; extern flash_driver_t str9x_flash; extern flash_driver_t stellaris_flash; extern flash_driver_t str9xpec_flash; +extern flash_driver_t stm32x_flash; flash_driver_t *flash_drivers[] = { @@ -67,6 +68,7 @@ flash_driver_t *flash_drivers[] = &str9x_flash, &stellaris_flash, &str9xpec_flash, + &stm32x_flash, NULL, }; diff --git a/src/flash/stm32x.c b/src/flash/stm32x.c new file mode 100644 index 0000000000..bb41f73297 --- /dev/null +++ b/src/flash/stm32x.c @@ -0,0 +1,859 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dominic Rath * + * Dominic.Rath@gmx.de * + * * + * 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 * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "replacements.h" + +#include "stm32x.h" +#include "flash.h" +#include "target.h" +#include "log.h" +#include "armv7m.h" +#include "algorithm.h" +#include "binarybuffer.h" + +#include +#include + +int stm32x_register_commands(struct command_context_s *cmd_ctx); +int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank); +int stm32x_erase(struct flash_bank_s *bank, int first, int last); +int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last); +int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count); +int stm32x_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); +int stm32x_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int stm32x_handle_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int stm32x_handle_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); +int stm32x_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc); + +flash_driver_t stm32x_flash = +{ + .name = "stm32x", + .register_commands = stm32x_register_commands, + .flash_bank_command = stm32x_flash_bank_command, + .erase = stm32x_erase, + .protect = stm32x_protect, + .write = stm32x_write, + .probe = stm32x_probe, + .erase_check = stm32x_erase_check, + .protect_check = stm32x_protect_check, + .info = stm32x_info +}; + +int stm32x_register_commands(struct command_context_s *cmd_ctx) +{ + command_t *stm32x_cmd = register_command(cmd_ctx, NULL, "stm32x", NULL, COMMAND_ANY, "stm32x flash specific commands"); + + register_command(cmd_ctx, stm32x_cmd, "lock", stm32x_handle_lock_command, COMMAND_EXEC, + "lock device"); + register_command(cmd_ctx, stm32x_cmd, "unlock", stm32x_handle_unlock_command, COMMAND_EXEC, + "unlock protected device"); + register_command(cmd_ctx, stm32x_cmd, "mass_erase", stm32x_handle_mass_erase_command, COMMAND_EXEC, + "mass erase device"); + register_command(cmd_ctx, stm32x_cmd, "options_read", stm32x_handle_options_read_command, COMMAND_EXEC, + "read device option bytes"); + register_command(cmd_ctx, stm32x_cmd, "options_write", stm32x_handle_options_write_command, COMMAND_EXEC, + "write device option bytes"); + return ERROR_OK; +} + +int stm32x_build_block_list(struct flash_bank_s *bank) +{ + int i; + int num_sectors = 0; + + switch (bank->size) + { + case 32 * 1024: + num_sectors = 32; + break; + case 64 * 1024: + num_sectors = 64; + break; + case 128 * 1024: + num_sectors = 128; + break; + default: + ERROR("BUG: unknown bank->size encountered"); + exit(-1); + } + + bank->num_sectors = num_sectors; + bank->sectors = malloc(sizeof(flash_sector_t) * num_sectors); + + for (i = 0; i < num_sectors; i++) + { + bank->sectors[i].offset = i * 1024; + bank->sectors[i].size = 1024; + bank->sectors[i].is_erased = -1; + bank->sectors[i].is_protected = 1; + } + + return ERROR_OK; +} + +/* flash bank stm32x 0 0 + */ +int stm32x_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank) +{ + stm32x_flash_bank_t *stm32x_info; + + if (argc < 6) + { + WARNING("incomplete flash_bank stm32x configuration"); + return ERROR_FLASH_BANK_INVALID; + } + + stm32x_info = malloc(sizeof(stm32x_flash_bank_t)); + bank->driver_priv = stm32x_info; + + if (bank->base != 0x08000000) + { + WARNING("overriding flash base address for STM32x device with 0x08000000"); + bank->base = 0x08000000; + } + + stm32x_info->target = get_target_by_num(strtoul(args[5], NULL, 0)); + if (!stm32x_info->target) + { + ERROR("no target '%s' configured", args[5]); + exit(-1); + } + + stm32x_build_block_list(bank); + + stm32x_info->write_algorithm = NULL; + + return ERROR_OK; +} + +u32 stm32x_get_flash_status(flash_bank_t *bank) +{ + stm32x_flash_bank_t *stm32x_info = bank->driver_priv; + target_t *target = stm32x_info->target; + u32 status; + + target_read_u32(target, STM32_FLASH_SR, &status); + + return status; +} + +u32 stm32x_wait_status_busy(flash_bank_t *bank, int timeout) +{ + u32 status; + + /* wait for busy to clear */ + while (((status = stm32x_get_flash_status(bank)) & FLASH_BSY) && (timeout-- > 0)) + { + DEBUG("status: 0x%x", status); + usleep(1000); + } + + return status; +} + +int stm32x_blank_check(struct flash_bank_s *bank, int first, int last) +{ + stm32x_flash_bank_t *stm32x_info = bank->driver_priv; + target_t *target = stm32x_info->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) +{ + stm32x_flash_bank_t *stm32x_info = bank->driver_priv; + target_t *target = stm32x_info->target; + + u32 protection; + int i, s; + + if (target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + /* each bit refers to a 4bank protection */ + target_read_u32(target, STM32_FLASH_WRPR, &protection); + + for (i = 0; i < 32; i++) + { + int set = 1; + + if( protection & (1 << i)) + set = 0; + + for (s = 0; s < 4; s++) + bank->sectors[(i * 4) + s].is_protected = set; + } + + return ERROR_OK; +} + +int stm32x_erase(struct flash_bank_s *bank, int first, int last) +{ + stm32x_flash_bank_t *stm32x_info = bank->driver_priv; + target_t *target = stm32x_info->target; + + int i; + u32 status; + + /* unlock flash registers */ + target_write_u32(target, STM32_FLASH_KEYR, KEY1); + target_write_u32(target, STM32_FLASH_KEYR, KEY2); + + if (target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + for (i = first; i <= last; i++) + { + target_write_u32(target, STM32_FLASH_CR, FLASH_PER); + target_write_u32(target, STM32_FLASH_AR, bank->base + bank->sectors[i].offset); + target_write_u32(target, STM32_FLASH_CR, FLASH_PER|FLASH_STRT); + + status = stm32x_wait_status_busy(bank, 10); + + if( status & FLASH_WRPRTERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & FLASH_PGERR ) + return ERROR_FLASH_OPERATION_FAILED; + bank->sectors[i].is_erased = 1; + } + + target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK); + + return ERROR_OK; +} + +int stm32x_protect(struct flash_bank_s *bank, int set, int first, int last) +{ + stm32x_flash_bank_t *stm32x_info = bank->driver_priv; + target_t *target = stm32x_info->target; + + if (target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + return ERROR_OK; +} + +int stm32x_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) +{ + stm32x_flash_bank_t *stm32x_info = bank->driver_priv; + target_t *target = stm32x_info->target; + u32 buffer_size = 8192; + working_area_t *source; + u32 address = bank->base + offset; + reg_param_t reg_params[6]; + armv7m_algorithm_t armv7m_info; + int retval = ERROR_OK; + + u8 stm32x_flash_write_code[] = { + /* write: */ + 0xDF, 0xF8, 0x24, 0x40, /* ldr r4, STM32_FLASH_CR */ + 0x09, 0x4D, /* ldr r5, STM32_FLASH_SR */ + 0x4F, 0xF0, 0x01, 0x03, /* mov r3, #1 */ + 0x23, 0x60, /* str r3, [r4, #0] */ + 0x30, 0xF8, 0x02, 0x3B, /* ldrh r3, [r0], #2 */ + 0x21, 0xF8, 0x02, 0x3B, /* strh r3, [r1], #2 */ + /* busy: */ + 0x2B, 0x68, /* ldr r3, [r5, #0] */ + 0x13, 0xF0, 0x01, 0x0F, /* tst r3, #0x01 */ + 0xFB, 0xD0, /* beq busy */ + 0x13, 0xF0, 0x14, 0x0F, /* tst r3, #0x14 */ + 0x01, 0xD1, /* bne exit */ + 0x01, 0x3A, /* subs r2, r2, #1 */ + 0xED, 0xD1, /* bne write */ + /* exit: */ + 0xFE, 0xE7, /* b exit */ + 0x10, 0x20, 0x02, 0x40, /* STM32_FLASH_CR: .word 0x40022010 */ + 0x0C, 0x20, 0x02, 0x40 /* STM32_FLASH_SR: .word 0x4002200C */ + }; + + /* flash write code */ + if (!stm32x_info->write_algorithm) + { + if (target_alloc_working_area(target, sizeof(stm32x_flash_write_code), &stm32x_info->write_algorithm) != ERROR_OK) + { + WARNING("no working area available, can't do block memory writes"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + }; + + target_write_buffer(target, stm32x_info->write_algorithm->address, sizeof(stm32x_flash_write_code), stm32x_flash_write_code); + } + + /* memory buffer */ + while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) + { + buffer_size /= 2; + if (buffer_size <= 256) + { + /* if we already allocated the writing code, but failed to get a buffer, free the algorithm */ + if (stm32x_info->write_algorithm) + target_free_working_area(target, stm32x_info->write_algorithm); + + WARNING("no large enough working area available, can't do block memory writes"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + }; + + armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; + armv7m_info.core_mode = ARMV7M_MODE_ANY; + armv7m_info.core_state = ARMV7M_STATE_THUMB; + + init_reg_param(®_params[0], "r0", 32, PARAM_OUT); + init_reg_param(®_params[1], "r1", 32, PARAM_OUT); + init_reg_param(®_params[2], "r2", 32, PARAM_OUT); + init_reg_param(®_params[3], "r3", 32, PARAM_IN); + init_reg_param(®_params[4], "r4", 32, PARAM_IN); + init_reg_param(®_params[5], "r5", 32, PARAM_IN); + + while (count > 0) + { + u32 thisrun_count = (count > (buffer_size / 2)) ? (buffer_size / 2) : count; + + target_write_buffer(target, source->address, thisrun_count * 2, buffer); + + buf_set_u32(reg_params[0].value, 0, 32, source->address); + buf_set_u32(reg_params[1].value, 0, 32, address); + buf_set_u32(reg_params[2].value, 0, 32, thisrun_count); + + if ((retval = target->type->run_algorithm(target, 0, NULL, 6, reg_params, stm32x_info->write_algorithm->address, \ + stm32x_info->write_algorithm->address + (sizeof(stm32x_flash_write_code) - 10), 10000, &armv7m_info)) != ERROR_OK) + { + ERROR("error executing str7x flash write algorithm"); + break; + } + + if (buf_get_u32(reg_params[3].value, 0, 32) & 0x14) + { + retval = ERROR_FLASH_OPERATION_FAILED; + break; + } + + buffer += thisrun_count * 2; + address += thisrun_count * 2; + count -= thisrun_count; + } + + target_free_working_area(target, source); + + destroy_reg_param(®_params[0]); + destroy_reg_param(®_params[1]); + destroy_reg_param(®_params[2]); + destroy_reg_param(®_params[3]); + destroy_reg_param(®_params[4]); + destroy_reg_param(®_params[5]); + + return retval; +} + +int stm32x_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) +{ + stm32x_flash_bank_t *stm32x_info = bank->driver_priv; + target_t *target = stm32x_info->target; + u32 words_remaining = (count / 2); + u32 bytes_remaining = (count & 0x00000001); + u32 address = bank->base + offset; + u32 bytes_written = 0; + u8 status; + u32 retval; + + if (target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + if (offset & 0x1) + { + WARNING("offset 0x%x breaks required 2-byte alignment", offset); + return ERROR_FLASH_DST_BREAKS_ALIGNMENT; + } + + /* unlock flash registers */ + target_write_u32(target, STM32_FLASH_KEYR, KEY1); + target_write_u32(target, STM32_FLASH_KEYR, KEY2); + + /* multiple half words (2-byte) to be programmed? */ + if (words_remaining > 0) + { + /* try using a block write */ + if ((retval = stm32x_write_block(bank, buffer, offset, words_remaining)) != ERROR_OK) + { + if (retval == ERROR_TARGET_RESOURCE_NOT_AVAILABLE) + { + /* if block write failed (no sufficient working area), + * we use normal (slow) single dword accesses */ + WARNING("couldn't use block writes, falling back to single memory accesses"); + } + else if (retval == ERROR_FLASH_OPERATION_FAILED) + { + ERROR("flash writing failed with error code: 0x%x", retval); + return ERROR_FLASH_OPERATION_FAILED; + } + } + else + { + buffer += words_remaining * 2; + address += words_remaining * 2; + words_remaining = 0; + } + } + + while (words_remaining > 0) + { + target_write_u32(target, STM32_FLASH_CR, FLASH_PG); + target_write_u16(target, address, *(u16*)(buffer + bytes_written)); + + status = stm32x_wait_status_busy(bank, 5); + + if( status & FLASH_WRPRTERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & FLASH_PGERR ) + return ERROR_FLASH_OPERATION_FAILED; + + bytes_written += 2; + words_remaining--; + address += 2; + } + + if (bytes_remaining) + { + u8 last_halfword[2] = {0xff, 0xff}; + int i = 0; + + while(bytes_remaining > 0) + { + last_halfword[i++] = *(buffer + bytes_written); + bytes_remaining--; + bytes_written++; + } + + target_write_u32(target, STM32_FLASH_CR, FLASH_PG); + target_write_u16(target, address, *(u16*)last_halfword); + + status = stm32x_wait_status_busy(bank, 5); + + if( status & FLASH_WRPRTERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & FLASH_PGERR ) + return ERROR_FLASH_OPERATION_FAILED; + } + + target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK); + + return ERROR_OK; +} + +int stm32x_probe(struct flash_bank_s *bank) +{ + return ERROR_OK; +} + +int stm32x_handle_part_id_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + 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" ); + return ERROR_OK; +} + +int stm32x_handle_lock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + flash_bank_t *bank; + u32 status; + target_t *target = NULL; + stm32x_flash_bank_t *stm32x_info = NULL; + + if (argc < 1) + { + command_print(cmd_ctx, "stm32x lock "); + return ERROR_OK; + } + + bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); + if (!bank) + { + command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); + return ERROR_OK; + } + + stm32x_info = bank->driver_priv; + + target = stm32x_info->target; + + if (target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + /* unlock flash registers */ + target_write_u32(target, STM32_FLASH_KEYR, KEY1); + target_write_u32(target, STM32_FLASH_KEYR, KEY2); + + /* unlock option flash registers */ + target_write_u32(target, STM32_FLASH_OPTKEYR, KEY1); + target_write_u32(target, STM32_FLASH_OPTKEYR, KEY2); + + /* erase option bytes */ + target_write_u32(target, STM32_FLASH_CR, FLASH_OPTER|FLASH_OPTWRE); + target_write_u32(target, STM32_FLASH_CR, FLASH_OPTER|FLASH_STRT|FLASH_OPTWRE); + + status = stm32x_wait_status_busy(bank, 10); + + if( status & FLASH_WRPRTERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & FLASH_PGERR ) + return ERROR_FLASH_OPERATION_FAILED; + + /* program option bytes */ + target_write_u32(target, STM32_FLASH_CR, FLASH_OPTPG|FLASH_OPTWRE); + + /* set readout protection */ + target_write_u16(target, STM32_OB_ADR, 0); + + status = stm32x_wait_status_busy(bank, 10); + + if( status & FLASH_WRPRTERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & FLASH_PGERR ) + return ERROR_FLASH_OPERATION_FAILED; + + target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK); + command_print(cmd_ctx, "stm32x locked"); + + return ERROR_OK; +} + +int stm32x_handle_unlock_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + flash_bank_t *bank; + u32 status; + target_t *target = NULL; + stm32x_flash_bank_t *stm32x_info = NULL; + + if (argc < 1) + { + command_print(cmd_ctx, "stm32x unlock "); + return ERROR_OK; + } + + bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); + if (!bank) + { + command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); + return ERROR_OK; + } + + stm32x_info = bank->driver_priv; + + target = stm32x_info->target; + + if (target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + /* unlock flash registers */ + target_write_u32(target, STM32_FLASH_KEYR, KEY1); + target_write_u32(target, STM32_FLASH_KEYR, KEY2); + + /* unlock option flash registers */ + target_write_u32(target, STM32_FLASH_OPTKEYR, KEY1); + target_write_u32(target, STM32_FLASH_OPTKEYR, KEY2); + + /* erase option bytes */ + target_write_u32(target, STM32_FLASH_CR, FLASH_OPTER|FLASH_OPTWRE); + target_write_u32(target, STM32_FLASH_CR, FLASH_OPTER|FLASH_STRT|FLASH_OPTWRE); + + status = stm32x_wait_status_busy(bank, 10); + + if( status & FLASH_WRPRTERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & FLASH_PGERR ) + return ERROR_FLASH_OPERATION_FAILED; + + /* program option bytes */ + target_write_u32(target, STM32_FLASH_CR, FLASH_OPTPG|FLASH_OPTWRE); + + /* clear readout protection and complementary option bytes */ + target_write_u16(target, STM32_OB_ADR, 0x5AA5); + + status = stm32x_wait_status_busy(bank, 10); + + if( status & FLASH_WRPRTERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & FLASH_PGERR ) + return ERROR_FLASH_OPERATION_FAILED; + + target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK); + command_print(cmd_ctx, "stm32x unlocked"); + + return ERROR_OK; +} + +int stm32x_handle_options_read_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + flash_bank_t *bank; + u32 optionbyte; + target_t *target = NULL; + stm32x_flash_bank_t *stm32x_info = NULL; + + if (argc < 1) + { + command_print(cmd_ctx, "stm32x options_read "); + return ERROR_OK; + } + + bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); + if (!bank) + { + command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); + return ERROR_OK; + } + + stm32x_info = bank->driver_priv; + + target = stm32x_info->target; + + if (target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + //target_read_u32(target, STM32_OB_ADR, &optionbyte); + //command_print(cmd_ctx, "Option Byte 0: 0x%x", optionbyte); + //target_read_u32(target, STM32_OB_ADR+4, &optionbyte); + //command_print(cmd_ctx, "Option Byte 1: 0x%x", optionbyte); + //target_read_u32(target, STM32_OB_ADR+8, &optionbyte); + //command_print(cmd_ctx, "Option Byte 2: 0x%x", optionbyte); + //target_read_u32(target, STM32_OB_ADR+12, &optionbyte); + //command_print(cmd_ctx, "Option Byte 3: 0x%x", optionbyte); + + target_read_u32(target, STM32_FLASH_OBR, &optionbyte); + command_print(cmd_ctx, "Option Byte: 0x%x", optionbyte); + + if (buf_get_u32((u8*)&optionbyte, OPT_ERROR, 1)) + command_print(cmd_ctx, "Option Byte Complement Error"); + + if (buf_get_u32((u8*)&optionbyte, OPT_READOUT, 1)) + command_print(cmd_ctx, "Readout Protection On"); + else + command_print(cmd_ctx, "Readout Protection Off"); + + if (buf_get_u32((u8*)&optionbyte, OPT_RDWDGSW, 1)) + command_print(cmd_ctx, "Software Watchdog"); + else + command_print(cmd_ctx, "Hardware Watchdog"); + + if (buf_get_u32((u8*)&optionbyte, OPT_RDRSTSTOP, 1)) + command_print(cmd_ctx, "Stop: No reset generated"); + else + command_print(cmd_ctx, "Stop: Reset generated"); + + if (buf_get_u32((u8*)&optionbyte, OPT_RDRSTSTDBY, 1)) + command_print(cmd_ctx, "Standby: No reset generated"); + else + command_print(cmd_ctx, "Standby: Reset generated"); + + return ERROR_OK; +} + +int stm32x_handle_options_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + flash_bank_t *bank; + target_t *target = NULL; + stm32x_flash_bank_t *stm32x_info = NULL; + u16 optionbyte = 0xF8; + u32 status; + + if (argc < 4) + { + command_print(cmd_ctx, "stm32x options_write "); + return ERROR_OK; + } + + bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); + if (!bank) + { + command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); + return ERROR_OK; + } + + stm32x_info = bank->driver_priv; + + target = stm32x_info->target; + + if (target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + if (strcmp(args[1], "SWWDG") == 0) + { + optionbyte |= (1<<0); + } + else + { + optionbyte &= ~(1<<0); + } + + if (strcmp(args[2], "NORSTSTNDBY") == 0) + { + optionbyte |= (1<<1); + } + else + { + optionbyte &= ~(1<<1); + } + + if (strcmp(args[3], "NORSTSTOP") == 0) + { + optionbyte |= (1<<2); + } + else + { + optionbyte &= ~(1<<2); + } + + /* unlock flash registers */ + target_write_u32(target, STM32_FLASH_KEYR, KEY1); + target_write_u32(target, STM32_FLASH_KEYR, KEY2); + + /* unlock option flash registers */ + target_write_u32(target, STM32_FLASH_OPTKEYR, KEY1); + target_write_u32(target, STM32_FLASH_OPTKEYR, KEY2); + + /* program option bytes */ + target_write_u32(target, STM32_FLASH_CR, FLASH_OPTPG|FLASH_OPTWRE); + + /* write option byte */ + target_write_u16(target, STM32_OB_ADR + 2, optionbyte); + + status = stm32x_wait_status_busy(bank, 10); + + if( status & FLASH_WRPRTERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & FLASH_PGERR ) + return ERROR_FLASH_OPERATION_FAILED; + + target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK); + + return ERROR_OK; +} + +int stm32x_handle_mass_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc) +{ + flash_bank_t *bank; + u32 status; + target_t *target = NULL; + stm32x_flash_bank_t *stm32x_info = NULL; + + if (argc < 1) + { + command_print(cmd_ctx, "stm32x mass_erase "); + return ERROR_OK; + } + + bank = get_flash_bank_by_num(strtoul(args[0], NULL, 0)); + if (!bank) + { + command_print(cmd_ctx, "flash bank '#%s' is out of bounds", args[0]); + return ERROR_OK; + } + + stm32x_info = bank->driver_priv; + + target = stm32x_info->target; + + if (target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } + + /* unlock option flash registers */ + target_write_u32(target, STM32_FLASH_KEYR, KEY1); + target_write_u32(target, STM32_FLASH_KEYR, KEY2); + + /* mass erase flash memory */ + target_write_u32(target, STM32_FLASH_CR, FLASH_MER); + target_write_u32(target, STM32_FLASH_CR, FLASH_MER|FLASH_STRT); + + status = stm32x_wait_status_busy(bank, 10); + + if( status & FLASH_WRPRTERR ) + return ERROR_FLASH_OPERATION_FAILED; + if( status & FLASH_PGERR ) + return ERROR_FLASH_OPERATION_FAILED; + + target_write_u32(target, STM32_FLASH_CR, FLASH_LOCK); + + return ERROR_OK; +} diff --git a/src/flash/stm32x.h b/src/flash/stm32x.h new file mode 100644 index 0000000000..ad189ac495 --- /dev/null +++ b/src/flash/stm32x.h @@ -0,0 +1,84 @@ +/*************************************************************************** + * Copyright (C) 2005 by Dominic Rath * + * Dominic.Rath@gmx.de * + * * + * 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 * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef STM32X_H +#define STM32X_H + +#include "flash.h" +#include "target.h" + +typedef struct stm32x_flash_bank_s +{ + struct target_s *target; + working_area_t *write_algorithm; +} stm32x_flash_bank_t; + +/* stm32x register locations */ + +#define STM32_FLASH_ACR 0x40022000 +#define STM32_FLASH_KEYR 0x40022004 +#define STM32_FLASH_OPTKEYR 0x40022008 +#define STM32_FLASH_SR 0x4002200C +#define STM32_FLASH_CR 0x40022010 +#define STM32_FLASH_AR 0x40022014 +#define STM32_FLASH_OBR 0x4002201C +#define STM32_FLASH_WRPR 0x40022020 + +/* option byte location */ + +#define STM32_OB_ADR 0x1FFFF800 + +/* FLASH_CR register bits */ + +#define FLASH_PG (1<<0) +#define FLASH_PER (1<<1) +#define FLASH_MER (1<<2) +#define FLASH_OPTPG (1<<4) +#define FLASH_OPTER (1<<5) +#define FLASH_STRT (1<<6) +#define FLASH_LOCK (1<<7) +#define FLASH_OPTWRE (1<<9) + +/* FLASH_SR regsiter bits */ + +#define FLASH_BSY (1<<0) +#define FLASH_PGERR (1<<2) +#define FLASH_WRPRTERR (1<<4) +#define FLASH_EOP (1<<5) + +/* STM32_FLASH_OBR bit definitions (reading) */ + +#define OPT_ERROR 0 +#define OPT_READOUT 1 +#define OPT_RDWDGSW 2 +#define OPT_RDRSTSTOP 3 +#define OPT_RDRSTSTDBY 4 + +/* register unlock keys */ + +#define KEY1 0x45670123 +#define KEY2 0xCDEF89AB + +typedef struct stm32x_mem_layout_s { + u32 sector_start; + u32 sector_size; +} stm32x_mem_layout_t; + +#endif /* STM32X_H */ + diff --git a/src/target/arm_disassembler.c b/src/target/arm_disassembler.c index ed7fe655f8..7028e9f515 100644 --- a/src/target/arm_disassembler.c +++ b/src/target/arm_disassembler.c @@ -346,7 +346,7 @@ int evaluate_load_store(u32 opcode, u32 address, arm_instruction_t *instruction) if (offset_12) snprintf(offset, 32, ", #%s0x%x", (U) ? "" : "-", offset_12); else - snprintf(offset, 32, ""); + snprintf(offset, 32, "%s", ""); instruction->info.load_store.offset_mode = 0; instruction->info.load_store.offset.offset = offset_12; diff --git a/src/target/armv7m.c b/src/target/armv7m.c index d77eb0bdef..335d0accdf 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -129,8 +129,10 @@ enum armv7m_runcontext armv7m_get_context(target_t *target) /* get pointers to arch-specific information */ armv7m_common_t *armv7m = target->arch_info; - if (armv7m->process_context == armv7m->core_cache) return ARMV7M_PROCESS_CONTEXT; - if (armv7m->debug_context == armv7m->core_cache) return ARMV7M_DEBUG_CONTEXT; + if (armv7m->process_context == armv7m->core_cache) + return ARMV7M_PROCESS_CONTEXT; + if (armv7m->debug_context == armv7m->core_cache) + return ARMV7M_DEBUG_CONTEXT; ERROR("Invalid runcontext"); exit(-1); @@ -177,9 +179,11 @@ int armv7m_use_context(target_t *target, enum armv7m_runcontext new_ctx) char enamebuf[32]; char *armv7m_exception_string(int number) { - if ((number<0)|(number>511)) return "Invalid exception"; - if (number<16) return armv7m_exception_strings[number]; - sprintf(enamebuf,"External Interrupt(%i)",number-16); + if ((number < 0) | (number > 511)) + return "Invalid exception"; + if (number < 16) + return armv7m_exception_strings[number]; + sprintf(enamebuf, "External Interrupt(%i)", number - 16); return enamebuf; } @@ -252,26 +256,22 @@ int armv7m_write_core_reg(struct target_s *target, int num) if ((num < 0) || (num >= ARMV7NUMCOREREGS)) return ERROR_INVALID_ARGUMENTS; - reg_value = buf_get_u32(armv7m->core_cache->reg_list[num].value, 0, 32); armv7m_core_reg = armv7m->core_cache->reg_list[num].arch_info; retval = armv7m->store_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, reg_value); if (retval != ERROR_OK) { - ERROR("JTAG failure"); - armv7m->core_cache->reg_list[num].dirty=1; - return ERROR_JTAG_DEVICE_ERROR; + ERROR("JTAG failure"); + armv7m->core_cache->reg_list[num].dirty=1; + return ERROR_JTAG_DEVICE_ERROR; } DEBUG("write core reg %i value 0x%x",num ,reg_value); armv7m->core_cache->reg_list[num].valid=1; armv7m->core_cache->reg_list[num].dirty=0; return ERROR_OK; - } - - int armv7m_invalidate_core_regs(target_t *target) { /* get pointers to arch-specific information */ @@ -287,14 +287,12 @@ int armv7m_invalidate_core_regs(target_t *target) return ERROR_OK; } - int armv7m_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_size) { /* get pointers to arch-specific information */ armv7m_common_t *armv7m = target->arch_info; int i; - if (target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; @@ -306,7 +304,7 @@ int armv7m_get_gdb_reg_list(target_t *target, reg_t **reg_list[], int *reg_list_ /* TODOLATER correct list of registers, names ? */ for (i = 0; i < *reg_list_size; i++) { - if (iprocess_context->reg_list[i]; //(*reg_list)[i] = &armv7m->core_cache->reg_list[i]; else @@ -382,7 +380,7 @@ int armv7m_run_algorithm(struct target_s *target, int num_mem_params, mem_param_ armv7m_set_core_reg(reg, reg_params[i].value); } - /* ARMV7M always runs in Tumb state */ + /* ARMV7M always runs in Thumb state */ exit_breakpoint_size = 2; if ((retval = breakpoint_add(target, exit_point, exit_breakpoint_size, BKPT_SOFT)) != ERROR_OK) { @@ -415,7 +413,7 @@ int armv7m_run_algorithm(struct target_s *target, int num_mem_params, mem_param_ } } armv7m->load_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 15, &pc); - DEBUG("failed algoritm halted at 0x%x ",pc); + DEBUG("failed algoritm halted at 0x%x ", pc); retval = ERROR_TARGET_TIMEOUT; } } @@ -450,7 +448,7 @@ int armv7m_run_algorithm(struct target_s *target, int num_mem_params, mem_param_ exit(-1); } - armv7m_core_reg_t * armv7m_core_reg = reg->arch_info; + armv7m_core_reg_t *armv7m_core_reg = reg->arch_info; //armv7m->load_core_reg_u32(target, armv7m_core_reg->type, armv7m_core_reg->num, ®value); //buf_set_u32(reg_params[i].value, 0, 32, regvalue); buf_set_u32(reg_params[i].value, 0, 32, buf_get_u32(reg->value, 0, 32)); @@ -464,11 +462,9 @@ int armv7m_run_algorithm(struct target_s *target, int num_mem_params, mem_param_ // armv7m->core_cache->reg_list[i].dirty = 1; //} - // ????armv7m->core_state = core_state; // ????armv7m->core_mode = core_mode; - return retval; } @@ -478,20 +474,19 @@ int armv7m_arch_state(struct target_s *target, char *buf, int buf_size) armv7m_common_t *armv7m = target->arch_info; snprintf(buf, buf_size, - "target halted in %s state due to %s, current mode: %s %s\nxPSR: 0x%8.8x pc: 0x%8.8x", - armv7m_state_strings[armv7m->core_state], - target_debug_reason_strings[target->debug_reason], - armv7m_mode_strings[armv7m->core_mode], - armv7m_exception_string(armv7m->exception_number), - buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32), - buf_get_u32(armv7m->core_cache->reg_list[15].value, 0, 32)); + "target halted in %s state due to %s, current mode: %s %s\nxPSR: 0x%8.8x pc: 0x%8.8x", + armv7m_state_strings[armv7m->core_state], + target_debug_reason_strings[target->debug_reason], + armv7m_mode_strings[armv7m->core_mode], + armv7m_exception_string(armv7m->exception_number), + buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32), + buf_get_u32(armv7m->core_cache->reg_list[15].value, 0, 32)); return ERROR_OK; } reg_cache_t *armv7m_build_reg_cache(target_t *target) { - /* get pointers to arch-specific information */ armv7m_common_t *armv7m = target->arch_info; arm_jtag_t *jtag_info = &armv7m->jtag_info; @@ -560,16 +555,13 @@ reg_cache_t *armv7m_build_reg_cache(target_t *target) int armv7m_init_target(struct command_context_s *cmd_ctx, struct target_s *target) { - armv7m_build_reg_cache(target); return ERROR_OK; - } int armv7m_init_arch_info(target_t *target, armv7m_common_t *armv7m) { - /* register arch-specific functions */ target->arch_info = armv7m; @@ -580,11 +572,9 @@ int armv7m_init_arch_info(target_t *target, armv7m_common_t *armv7m) return ERROR_OK; } - int armv7m_register_commands(struct command_context_s *cmd_ctx) { int retval; return ERROR_OK; - } diff --git a/src/target/armv7m.h b/src/target/armv7m.h index cf2b3c7000..49043e1d3b 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -26,7 +26,6 @@ #include "target.h" #include "arm_jtag.h" - enum armv7m_mode { ARMV7M_MODE_HANDLER = 0, @@ -56,17 +55,18 @@ enum armv7m_runcontext }; extern char* armv7m_state_strings[]; +extern char* armv7m_exception_strings[]; -//#define ARMV7NUMCOREREGS 23 +extern char *armv7m_exception_string(int number); /* offsets into armv7m core register cache */ enum { ARMV7M_PC = 15, ARMV7M_xPSR = 16, - ARMV7M_MSP , - ARMV7M_PSP , - ARMV7M_PRIMASK , + ARMV7M_MSP, + ARMV7M_PSP, + ARMV7M_PRIMASK, ARMV7M_BASEPRI, ARMV7M_FAULTMASK, ARMV7M_CONTROL, @@ -163,8 +163,9 @@ extern int armv7m_run_algorithm(struct target_s *target, int num_mem_params, mem extern int armv7m_invalidate_core_regs(target_t *target); - - +extern enum armv7m_runcontext armv7m_get_context(target_t *target); +extern int armv7m_use_context(target_t *target, enum armv7m_runcontext new_ctx); +extern enum armv7m_runcontext armv7m_get_context(target_t *target); /* Thumb mode instructions */ diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index 8b140b3e98..ac8d7dfd6e 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -71,13 +71,15 @@ int breakpoint_add(target_t *target, u32 address, u32 length, enum breakpoint_ty { case ERROR_TARGET_RESOURCE_NOT_AVAILABLE: INFO("can't add %s breakpoint, resource not available", breakpoint_type_strings[(*breakpoint_p)->type]); - free (*breakpoint_p); + free((*breakpoint_p)->orig_instr); + free(*breakpoint_p); *breakpoint_p = NULL; return retval; break; case ERROR_TARGET_NOT_HALTED: INFO("can't add breakpoint while target is running"); - free (*breakpoint_p); + free((*breakpoint_p)->orig_instr); + free(*breakpoint_p); *breakpoint_p = NULL; return retval; break; diff --git a/src/target/cortex_m3.c b/src/target/cortex_m3.c index 93521cf6e6..b342fce297 100644 --- a/src/target/cortex_m3.c +++ b/src/target/cortex_m3.c @@ -28,6 +28,7 @@ #include "replacements.h" #include "cortex_m3.h" +#include "armv7m.h" #include "register.h" #include "target.h" @@ -88,7 +89,6 @@ target_type_t cortexm3_target = int cortex_m3_clear_halt(target_t *target) { - /* get pointers to arch-specific information */ armv7m_common_t *armv7m = target->arch_info; cortex_m3_common_t *cortex_m3 = armv7m->arch_info; @@ -110,11 +110,11 @@ int cortex_m3_single_step_core(target_t *target) cortex_m3_common_t *cortex_m3 = armv7m->arch_info; swjdp_common_t *swjdp = &cortex_m3->swjdp_info; - if (!(cortex_m3->dcb_dhcsr&C_MASKINTS)) + if (!(cortex_m3->dcb_dhcsr & C_MASKINTS)) ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_MASKINTS | C_HALT | C_DEBUGEN ); ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_MASKINTS | C_STEP | C_DEBUGEN ); cortex_m3->dcb_dhcsr |= C_MASKINTS; - DEBUG(""); + DEBUG(" "); cortex_m3_clear_halt(target); return ERROR_OK; @@ -134,7 +134,7 @@ int cortex_m3_exec_opcode(target_t *target,u32 opcode, int len /* MODE, r0_inval ahbap_write_system_u32(swjdp, 0x20000000, opcode); ahbap_write_coreregister_u32(swjdp, 0x20000000, 15); cortex_m3_single_step_core(target); - armv7m->core_cache->reg_list[15].dirty=1; + armv7m->core_cache->reg_list[15].dirty = 1; retvalue = ahbap_write_system_atomic_u32(swjdp, 0x20000000, savedram); } @@ -162,15 +162,15 @@ int cortex_m3_endreset_event(target_t *target) cortex_m3_common_t *cortex_m3 = armv7m->arch_info; swjdp_common_t *swjdp = &cortex_m3->swjdp_info; cortex_m3_fp_comparator_t *fp_list = cortex_m3->fp_comparator_list; - cortex_m3_dwt_comparator_t * dwt_list = cortex_m3->dwt_comparator_list; + cortex_m3_dwt_comparator_t *dwt_list = cortex_m3->dwt_comparator_list; - DEBUG(""); + DEBUG(" "); /* Enable debug requests */ ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr); if (!(cortex_m3->dcb_dhcsr&C_DEBUGEN)) ahbap_write_system_u32(swjdp, DCB_DHCSR, DBGKEY | C_DEBUGEN ); /* Enable trace and dwt */ - ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA|VC_HARDERR|VC_BUSERR|VC_CORERESET ); + ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET ); /* Monitor bus faults */ ahbap_write_system_u32(swjdp, NVIC_SHCSR, SHCSR_BUSFAULTENA ); @@ -178,17 +178,17 @@ int cortex_m3_endreset_event(target_t *target) target_write_u32(target, FP_CTRL, 3); /* Restore FPB registers */ - for (i=0;ifp_num_code+cortex_m3->fp_num_lit;i++) + for ( i = 0; i < cortex_m3->fp_num_code + cortex_m3->fp_num_lit; i++) { target_write_u32(target, fp_list[i].fpcr_address, fp_list[i].fpcr_value); } /* Restore DWT registers */ - for (i=0;idwt_num_comp;i++) + for ( i = 0; i < cortex_m3->dwt_num_comp; i++) { target_write_u32(target, dwt_list[i].dwt_comparator_address, dwt_list[i].comp); - target_write_u32(target, dwt_list[i].dwt_comparator_address|0x4, dwt_list[i].mask); - target_write_u32(target, dwt_list[i].dwt_comparator_address|0x8, dwt_list[i].function); + target_write_u32(target, dwt_list[i].dwt_comparator_address | 0x4, dwt_list[i].mask); + target_write_u32(target, dwt_list[i].dwt_comparator_address | 0x8, dwt_list[i].function); } /* Make sure working_areas are all free */ @@ -211,7 +211,7 @@ int cortex_m3_examine_debug_reason(target_t *target) /* only check the debug reason if we don't know it already */ if ((target->debug_reason != DBG_REASON_DBGRQ) - && (target->debug_reason != DBG_REASON_SINGLESTEP)) + && (target->debug_reason != DBG_REASON_SINGLESTEP)) { /* INCOPMPLETE */ @@ -231,7 +231,7 @@ int cortex_m3_examine_debug_reason(target_t *target) int cortex_m3_examine_exception_reason(target_t *target) { - u32 shcsr,except_sr,cfsr=-1,except_ar=-1; + u32 shcsr, except_sr, cfsr = -1, except_ar = -1; /* get pointers to arch-specific information */ armv7m_common_t *armv7m = target->arch_info; @@ -245,7 +245,7 @@ int cortex_m3_examine_exception_reason(target_t *target) break; case 3: /* Hard Fault */ ahbap_read_system_atomic_u32(swjdp, NVIC_HFSR, &except_sr); - if (except_sr&0x40000000) + if (except_sr & 0x40000000) { ahbap_read_system_u32(swjdp, NVIC_CFSR, &cfsr); } @@ -262,28 +262,24 @@ int cortex_m3_examine_exception_reason(target_t *target) ahbap_read_system_u32(swjdp, NVIC_CFSR, &except_sr); break; case 11: /* SVCall */ - break; case 12: /* Debug Monitor */ ahbap_read_system_u32(swjdp, NVIC_DFSR, &except_sr); break; case 14: /* PendSV */ - break; case 15: /* SysTick */ - break; default: except_sr = 0; break; - } swjdp_transaction_endcheck(swjdp); - DEBUG("%s SHCSR 0x%x, SR 0x%x, CFSR 0x%x, AR 0x%x",armv7m_exception_string(armv7m->exception_number),shcsr,except_sr,cfsr, except_ar); + DEBUG("%s SHCSR 0x%x, SR 0x%x, CFSR 0x%x, AR 0x%x", armv7m_exception_string(armv7m->exception_number), \ + shcsr, except_sr, cfsr, except_ar); return ERROR_OK; } - int cortex_m3_debug_entry(target_t *target) { int i, irq_is_pending; @@ -295,7 +291,7 @@ int cortex_m3_debug_entry(target_t *target) cortex_m3_common_t *cortex_m3 = armv7m->arch_info; swjdp_common_t *swjdp = &cortex_m3->swjdp_info; - DEBUG(""); + DEBUG(" "); if (armv7m->pre_debug_entry) armv7m->pre_debug_entry(target); @@ -316,10 +312,10 @@ int cortex_m3_debug_entry(target_t *target) xPSR = buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32); /* For IT instructions xPSR must be reloaded on resume and clear on debug exec*/ - if (xPSR&0xf00) + if (xPSR & 0xf00) { armv7m->core_cache->reg_list[ARMV7M_xPSR].dirty = 1; - cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR&~0xff); + cortex_m3_store_core_reg_u32(target, ARMV7M_REGISTER_CORE_GP, 16, xPSR &~ 0xff); } @@ -333,14 +329,14 @@ int cortex_m3_debug_entry(target_t *target) #endif /* Are we in an exception handler */ - armv7m->core_mode = (xPSR&0x1FF)?ARMV7M_MODE_HANDLER:ARMV7M_MODE_THREAD; - armv7m->exception_number = xPSR&0x1FF;; + armv7m->core_mode = (xPSR & 0x1FF) ? ARMV7M_MODE_HANDLER : ARMV7M_MODE_THREAD; + armv7m->exception_number = xPSR & 0x1FF; if (armv7m->exception_number) { cortex_m3_examine_exception_reason(target); } - DEBUG("entered debug state at PC 0x%x ", *(u32*)(armv7m->core_cache->reg_list[15].value), target_state_strings[target->state]); + DEBUG("entered debug state at PC 0x%x, target->state: %s ", *(u32*)(armv7m->core_cache->reg_list[15].value), target_state_strings[target->state]); if (armv7m->post_debug_entry) armv7m->post_debug_entry(target); @@ -356,7 +352,7 @@ int cortex_m3_restore_context(target_t *target) armv7m_common_t *armv7m = target->arch_info; cortex_m3_common_t *cortex_m3 = armv7m->arch_info; - DEBUG(""); + DEBUG(" "); if (armv7m->pre_restore_context) armv7m->pre_restore_context(target); @@ -379,7 +375,6 @@ int cortex_m3_restore_context(target_t *target) return ERROR_OK; } - enum target_state cortex_m3_poll(target_t *target) { int retval; @@ -425,13 +420,12 @@ enum target_state cortex_m3_poll(target_t *target) } if (prev_target_state == TARGET_DEBUG_RUNNING) { - DEBUG(""); + DEBUG(" "); if ((retval = cortex_m3_debug_entry(target)) != ERROR_OK) return retval; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); } - } /* @@ -439,10 +433,9 @@ enum target_state cortex_m3_poll(target_t *target) target->state = TARGET_SLEEP; */ - /* Read Debug Fault Status Register, added to figure out the lockup when running flashtest.script */ ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr); - DEBUG("dcb_dhcsr %x, nvic_dfsr %x, target->state: %s", cortex_m3->dcb_dhcsr, cortex_m3->nvic_dfsr, target_state_strings[target->state]); + DEBUG("dcb_dhcsr %x, nvic_dfsr %x, target->state: %s", cortex_m3->dcb_dhcsr, cortex_m3->nvic_dfsr, target_state_strings[target->state]); return target->state; } @@ -469,8 +462,8 @@ int cortex_m3_soft_reset_halt(struct target_s *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; - u32 dcb_dhcsr=0; - int retval, timeout=0; + u32 dcb_dhcsr = 0; + int retval, timeout = 0; /* Check that we are using process_context, or change and print warning */ if (armv7m_get_context(target) != ARMV7M_PROCESS_CONTEXT) @@ -480,7 +473,7 @@ int cortex_m3_soft_reset_halt(struct target_s *target) } /* Enter debug state on reset, cf. end_reset_event() */ - ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA|VC_HARDERR|VC_BUSERR|VC_CORERESET ); + ahbap_write_system_u32(swjdp, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET ); /* Request a reset */ ahbap_write_system_atomic_u32(swjdp, NVIC_AIRCR, AIRCR_VECTKEY | AIRCR_VECTRESET ); @@ -495,14 +488,14 @@ int cortex_m3_soft_reset_halt(struct target_s *target) if (retval == ERROR_OK) { ahbap_read_system_atomic_u32(swjdp, NVIC_DFSR, &cortex_m3->nvic_dfsr); - if ( (dcb_dhcsr&S_HALT)&&(cortex_m3->nvic_dfsr&DFSR_VCATCH) ) + if ((dcb_dhcsr&S_HALT) && (cortex_m3->nvic_dfsr & DFSR_VCATCH)) { - DEBUG("system reset-halted, dcb_dhcsr 0x%x, nvic_dfsr 0x%x",dcb_dhcsr,cortex_m3->nvic_dfsr); + DEBUG("system reset-halted, dcb_dhcsr 0x%x, nvic_dfsr 0x%x", dcb_dhcsr, cortex_m3->nvic_dfsr); cortex_m3_poll(target); return ERROR_OK; } else - DEBUG("waiting for system reset-halt, dcb_dhcsr 0x%x, %i ms",dcb_dhcsr,timeout); + DEBUG("waiting for system reset-halt, dcb_dhcsr 0x%x, %i ms", dcb_dhcsr, timeout); } timeout++; usleep(1000); @@ -534,14 +527,12 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand WARNING("Incorrect context in resume"); armv7m_use_context(target, ARMV7M_PROCESS_CONTEXT); } - - + target_free_all_working_areas(target); cortex_m3_enable_breakpoints(target); cortex_m3_enable_watchpoints(target); /* TODOLATER Interrupt handling/disable for debug execution, cache ... ... */ - } dcb_dhcsr = DBGKEY | C_DEBUGEN; @@ -562,7 +553,7 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_PRIMASK].value, 0, 32, 1); /* Make sure we are in Thumb mode */ buf_set_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32, - buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32)|(1<<24)); + buf_get_u32(armv7m->core_cache->reg_list[ARMV7M_xPSR].value, 0, 32) | (1<<24)); } /* current = 1: continue on current pc, otherwise continue at
*/ @@ -591,7 +582,7 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand } /* Set/Clear C_MASKINTS in a separate operation */ - if ((cortex_m3->dcb_dhcsr&C_MASKINTS) != (dcb_dhcsr&C_MASKINTS)) + if ((cortex_m3->dcb_dhcsr & C_MASKINTS) != (dcb_dhcsr & C_MASKINTS)) ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, dcb_dhcsr | C_HALT ); /* Restart core */ ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, dcb_dhcsr ); @@ -612,11 +603,10 @@ int cortex_m3_resume(struct target_s *target, int current, u32 address, int hand DEBUG("target debug resumed at 0x%x",resume_pc); } - return ERROR_OK; } -int irqstepcount=0; +//int irqstepcount=0; int cortex_m3_step(struct target_s *target, int current, u32 address, int handle_breakpoints) { /* get pointers to arch-specific information */ @@ -653,7 +643,7 @@ int cortex_m3_step(struct target_s *target, int current, u32 address, int handle target_call_event_callbacks(target, TARGET_EVENT_RESUMED); - if (cortex_m3->dcb_dhcsr&C_MASKINTS) + if (cortex_m3->dcb_dhcsr & C_MASKINTS) ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN ); ahbap_write_system_atomic_u32(swjdp, DCB_DHCSR, DBGKEY| C_STEP | C_DEBUGEN); ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &cortex_m3->dcb_dhcsr); @@ -665,14 +655,13 @@ int cortex_m3_step(struct target_s *target, int current, u32 address, int handle if (breakpoint) cortex_m3_set_breakpoint(target, breakpoint); - DEBUG("target stepped dcb_dhcsr=0x%x nvic_icsr=0x%x",cortex_m3->dcb_dhcsr,cortex_m3->nvic_icsr); + DEBUG("target stepped dcb_dhcsr = 0x%x nvic_icsr = 0x%x", cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr); cortex_m3_debug_entry(target); target_call_event_callbacks(target, TARGET_EVENT_HALTED); - DEBUG("target stepped dcb_dhcsr=0x%x nvic_icsr=0x%x",cortex_m3->dcb_dhcsr,cortex_m3->nvic_icsr); + DEBUG("target stepped dcb_dhcsr = 0x%x nvic_icsr = 0x%x", cortex_m3->dcb_dhcsr, cortex_m3->nvic_icsr); return ERROR_OK; - } int cortex_m3_assert_reset(target_t *target) @@ -738,7 +727,6 @@ int cortex_m3_assert_reset(target_t *target) armv7m_invalidate_core_regs(target); return ERROR_OK; - } int cortex_m3_deassert_reset(target_t *target) @@ -749,13 +737,13 @@ int cortex_m3_deassert_reset(target_t *target) jtag_add_reset(0, 0); return ERROR_OK; - } void cortex_m3_unset_all_breakpoints_and_watchpoints(struct target_s *target) { } + void cortex_m3_enable_breakpoints(struct target_s *target) { breakpoint_t *breakpoint = target->breakpoints; @@ -788,37 +776,36 @@ int cortex_m3_set_breakpoint(struct target_s *target, breakpoint_t *breakpoint) if (cortex_m3->auto_bp_type) { - breakpoint->type = (breakpoint->address<0x20000000)?BKPT_HARD:BKPT_SOFT; + breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT; } if (breakpoint->type == BKPT_HARD) { - while(comparator_list[fp_num].used && (fp_numfp_num_code)) + while(comparator_list[fp_num].used && (fp_num < cortex_m3->fp_num_code)) fp_num++; - if (fp_num>=cortex_m3->fp_num_code) + if (fp_num >= cortex_m3->fp_num_code) { DEBUG("ERROR Can not find free FP Comparator"); WARNING("ERROR Can not find free FP Comparator"); exit(-1); } - breakpoint->set = fp_num+1; - hilo = (breakpoint->address & 0x2)? FPCR_REPLACE_BKPT_HIGH:FPCR_REPLACE_BKPT_LOW; + breakpoint->set = fp_num + 1; + hilo = (breakpoint->address & 0x2) ? FPCR_REPLACE_BKPT_HIGH : FPCR_REPLACE_BKPT_LOW; comparator_list[fp_num].used = 1; - comparator_list[fp_num].fpcr_value = breakpoint->address&0x1FFFFFFC | hilo | 1; + comparator_list[fp_num].fpcr_value = (breakpoint->address & 0x1FFFFFFC) | hilo | 1; target_write_u32(target, comparator_list[fp_num].fpcr_address, comparator_list[fp_num].fpcr_value); - DEBUG("fpc_num %i fpcr_value 0x%x", fp_num, comparator_list[fp_num].fpcr_value); + DEBUG("fpc_num %i fpcr_value 0x%x", fp_num, comparator_list[fp_num].fpcr_value); } else if (breakpoint->type == BKPT_SOFT) { u8 code[4]; buf_set_u32(code, 0, 32, ARMV7M_T_BKPT(0x11)); - target->type->read_memory(target, breakpoint->address&0xFFFFFFFE, breakpoint->length, 1, breakpoint->orig_instr); - target->type->write_memory(target, breakpoint->address&0xFFFFFFFE, breakpoint->length, 1, code); + target->type->read_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, breakpoint->orig_instr); + target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, breakpoint->length, 1, code); breakpoint->set = 0x11; /* Any nice value but 0 */ } return ERROR_OK; - } int cortex_m3_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint) @@ -836,8 +823,8 @@ int cortex_m3_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint if (breakpoint->type == BKPT_HARD) { - int fp_num = breakpoint->set-1; - if ((fp_num<0)||(fp_num>=cortex_m3->fp_num_code)) + int fp_num = breakpoint->set - 1; + if ((fp_num < 0) || (fp_num >= cortex_m3->fp_num_code)) { DEBUG("Invalid FP Comparator number in breakpoint"); return ERROR_OK; @@ -851,11 +838,11 @@ int cortex_m3_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint /* restore original instruction (kept in target endianness) */ if (breakpoint->length == 4) { - target->type->write_memory(target, breakpoint->address&0xFFFFFFFE, 4, 1, breakpoint->orig_instr); + target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, 4, 1, breakpoint->orig_instr); } else { - target->type->write_memory(target, breakpoint->address&0xFFFFFFFE, 2, 1, breakpoint->orig_instr); + target->type->write_memory(target, breakpoint->address & 0xFFFFFFFE, 2, 1, breakpoint->orig_instr); } } breakpoint->set = 0; @@ -863,7 +850,6 @@ int cortex_m3_unset_breakpoint(struct target_s *target, breakpoint_t *breakpoint return ERROR_OK; } - int cortex_m3_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint) { /* get pointers to arch-specific information */ @@ -872,16 +858,16 @@ int cortex_m3_add_breakpoint(struct target_s *target, breakpoint_t *breakpoint) if (cortex_m3->auto_bp_type) { - breakpoint->type = (breakpoint->address<0x20000000)?BKPT_HARD:BKPT_SOFT; + breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT; } - if ((breakpoint->type == BKPT_HARD) && (breakpoint->address>=0x20000000)) + if ((breakpoint->type == BKPT_HARD) && (breakpoint->address >= 0x20000000)) { INFO("flash patch comparator requested outside code memory region"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; } - if ((breakpoint->type == BKPT_SOFT) && (breakpoint->address<0x20000000)) + if ((breakpoint->type == BKPT_SOFT) && (breakpoint->address < 0x20000000)) { INFO("soft breakpoint requested in code (flash) memory region"); return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -920,7 +906,7 @@ int cortex_m3_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoin if (cortex_m3->auto_bp_type) { - breakpoint->type = (breakpoint->address<0x20000000)?BKPT_HARD:BKPT_SOFT; + breakpoint->type = (breakpoint->address < 0x20000000) ? BKPT_HARD : BKPT_SOFT; } if (breakpoint->set) @@ -934,19 +920,6 @@ int cortex_m3_remove_breakpoint(struct target_s *target, breakpoint_t *breakpoin return ERROR_OK; } -void cortex_m3_enable_watchpoints(struct target_s *target) -{ - watchpoint_t *watchpoint = target->watchpoints; - - /* set any pending watchpoints */ - while (watchpoint) - { - if (watchpoint->set == 0) - cortex_m3_set_watchpoint(target, watchpoint); - watchpoint = watchpoint->next; - } -} - int cortex_m3_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint) { int dwt_num=0; @@ -965,30 +938,30 @@ int cortex_m3_set_watchpoint(struct target_s *target, watchpoint_t *watchpoint) if (watchpoint->mask == 0xffffffffu) { - while(comparator_list[dwt_num].used && (dwt_numdwt_num_comp)) + while(comparator_list[dwt_num].used && (dwt_num < cortex_m3->dwt_num_comp)) dwt_num++; - if (dwt_num>=cortex_m3->dwt_num_comp) + if (dwt_num >= cortex_m3->dwt_num_comp) { DEBUG("ERROR Can not find free DWT Comparator"); WARNING("ERROR Can not find free DWT Comparator"); return -1; } - watchpoint->set = dwt_num+1; + watchpoint->set = dwt_num + 1; mask = 0; temp = watchpoint->length; - while (temp>1) + while (temp > 1) { - temp = temp/2; + temp = temp / 2; mask++; } comparator_list[dwt_num].used = 1; comparator_list[dwt_num].comp = watchpoint->address; comparator_list[dwt_num].mask = mask; - comparator_list[dwt_num].function = watchpoint->rw+5; + comparator_list[dwt_num].function = watchpoint->rw + 5; target_write_u32(target, comparator_list[dwt_num].dwt_comparator_address, comparator_list[dwt_num].comp); target_write_u32(target, comparator_list[dwt_num].dwt_comparator_address|0x4, comparator_list[dwt_num].mask); target_write_u32(target, comparator_list[dwt_num].dwt_comparator_address|0x8, comparator_list[dwt_num].function); - DEBUG("dwt_num %i 0x%x 0x%x 0x%x", dwt_num, comparator_list[dwt_num].comp, comparator_list[dwt_num].mask, comparator_list[dwt_num].function); + DEBUG("dwt_num %i 0x%x 0x%x 0x%x", dwt_num, comparator_list[dwt_num].comp, comparator_list[dwt_num].mask, comparator_list[dwt_num].function); } else { @@ -1014,9 +987,9 @@ int cortex_m3_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint return ERROR_OK; } - dwt_num = watchpoint->set-1; + dwt_num = watchpoint->set - 1; - if ((dwt_num<0)||(dwt_num>=cortex_m3->dwt_num_comp)) + if ((dwt_num < 0) || (dwt_num >= cortex_m3->dwt_num_comp)) { DEBUG("Invalid DWT Comparator number in watchpoint"); return ERROR_OK; @@ -1030,8 +1003,6 @@ int cortex_m3_unset_watchpoint(struct target_s *target, watchpoint_t *watchpoint return ERROR_OK; } - - int cortex_m3_add_watchpoint(struct target_s *target, watchpoint_t *watchpoint) { /* get pointers to arch-specific information */ @@ -1081,6 +1052,18 @@ int cortex_m3_remove_watchpoint(struct target_s *target, watchpoint_t *watchpoin return ERROR_OK; } +void cortex_m3_enable_watchpoints(struct target_s *target) +{ + watchpoint_t *watchpoint = target->watchpoints; + + /* set any pending watchpoints */ + while (watchpoint) + { + if (watchpoint->set == 0) + cortex_m3_set_watchpoint(target, watchpoint); + watchpoint = watchpoint->next; + } +} int cortex_m3_load_core_reg_u32(struct target_s *target, enum armv7m_regtype type, u32 num, u32 * value) { @@ -1116,16 +1099,15 @@ int cortex_m3_load_core_reg_u32(struct target_s *target, enum armv7m_regtype typ ahbap_write_coreregister_u32(swjdp, 0x20000000, 15); cortex_m3_single_step_core(target); ahbap_read_coreregister_u32(swjdp, value, 0); - armv7m->core_cache->reg_list[0].dirty=1; - armv7m->core_cache->reg_list[15].dirty=1; + armv7m->core_cache->reg_list[0].dirty = 1; + armv7m->core_cache->reg_list[15].dirty = 1; ahbap_write_system_u32(swjdp, 0x20000000, savedram); swjdp_transaction_endcheck(swjdp); - DEBUG("load from special reg %i value 0x%x",SYSm, *value); + DEBUG("load from special reg %i value 0x%x", SYSm, *value); } else return ERROR_INVALID_ARGUMENTS; return ERROR_OK; - } int cortex_m3_store_core_reg_u32(struct target_s *target, enum armv7m_regtype type, u32 num, u32 value) @@ -1142,11 +1124,11 @@ int cortex_m3_store_core_reg_u32(struct target_s *target, enum armv7m_regtype ty retval = ahbap_write_coreregister_u32(swjdp, value, num); if (retval != ERROR_OK) { - ERROR("JTAG failure %i",retval); - armv7m->core_cache->reg_list[num].dirty=1; + ERROR("JTAG failure %i", retval); + armv7m->core_cache->reg_list[num].dirty = 1; return ERROR_JTAG_DEVICE_ERROR; } - DEBUG("write core reg %i value 0x%x",num, value); + DEBUG("write core reg %i value 0x%x", num, value); } else if (type == ARMV7M_REGISTER_CORE_SP) /* Special purpose core register */ { @@ -1163,21 +1145,18 @@ int cortex_m3_store_core_reg_u32(struct target_s *target, enum armv7m_regtype ty ahbap_write_coreregister_u32(swjdp, 0x20000000, 15); cortex_m3_single_step_core(target); ahbap_write_coreregister_u32(swjdp, tempr0, 0); - armv7m->core_cache->reg_list[15].dirty=1; + armv7m->core_cache->reg_list[15].dirty = 1; ahbap_write_system_u32(swjdp, 0x20000000, savedram); swjdp_transaction_endcheck(swjdp); - DEBUG("write special reg %i value 0x%x ",SYSm, value); + DEBUG("write special reg %i value 0x%x ", SYSm, value); } else return ERROR_INVALID_ARGUMENTS; - return ERROR_OK; - + return ERROR_OK; } - int cortex_m3_read_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer) { - /* get pointers to arch-specific information */ armv7m_common_t *armv7m = target->arch_info; cortex_m3_common_t *cortex_m3 = armv7m->arch_info; @@ -1196,12 +1175,12 @@ int cortex_m3_read_memory(struct target_s *target, u32 address, u32 size, u32 co case 4: /* TODOLATER Check error return value ! */ { - ahbap_read_buf(swjdp, buffer, 4*count, address); + ahbap_read_buf(swjdp, buffer, 4 * count, address); } break; case 2: { - ahbap_read_buf(swjdp, buffer, 2*count, address); + ahbap_read_buf_u16(swjdp, buffer, 2 * count, address); } break; case 1: @@ -1213,14 +1192,12 @@ int cortex_m3_read_memory(struct target_s *target, u32 address, u32 size, u32 co ERROR("BUG: we shouldn't get here"); exit(-1); } - - + return ERROR_OK; } int cortex_m3_write_memory(struct target_s *target, u32 address, u32 size, u32 count, u8 *buffer) { - /* get pointers to arch-specific information */ armv7m_common_t *armv7m = target->arch_info; cortex_m3_common_t *cortex_m3 = armv7m->arch_info; @@ -1238,12 +1215,12 @@ int cortex_m3_write_memory(struct target_s *target, u32 address, u32 size, u32 c case 4: /* TODOLATER Check error return value ! */ { - ahbap_write_buf(swjdp, buffer, 4*count, address); + ahbap_write_buf(swjdp, buffer, 4 * count, address); } break; case 2: { - ahbap_write_buf(swjdp, buffer, 2*count, address); + ahbap_write_buf_u16(swjdp, buffer, 2 * count, address); } break; case 1: @@ -1261,14 +1238,11 @@ int cortex_m3_write_memory(struct target_s *target, u32 address, u32 size, u32 c int cortex_m3_bulk_write_memory(target_t *target, u32 address, u32 count, u8 *buffer) { - - cortex_m3_write_memory(target, address, 4,count,buffer); + cortex_m3_write_memory(target, address, 4, count, buffer); return ERROR_OK; } - - void cortex_m3_build_reg_cache(target_t *target) { armv7m_build_reg_cache(target); @@ -1287,48 +1261,43 @@ int cortex_m3_init_target(struct command_context_s *cmd_ctx, struct target_s *ta cortex_m3_build_reg_cache(target); ahbap_debugport_init(swjdp); - /* Read from Device Identification Registers, IS THIS CORTEX OR Luminary Micro SPECIFIC ?? */ - target_read_u32(target, CPUID, &cpuid ); - if (cpuid == 0x410fc231) - DEBUG("CORTEX-M3 processor"); - DEBUG("cpuid %x",cpuid); - /* Probably only valid for LMI parts, move to flash/stellaris ? */ - target_read_u32(target, SYSTEM_CONTROL_BASE|0x04, &did1); - target_read_u32(target,SYSTEM_CONTROL_BASE|0x08,&dc0); - DEBUG("did1 %x",did1); - DEBUG("dc0 %x",dc0); + /* Read from Device Identification Registers */ + target_read_u32(target, CPUID, &cpuid); + if (((cpuid >> 4) & 0xc3f) == 0xc23) + DEBUG("CORTEX-M3 processor detected"); + DEBUG("cpuid %x", cpuid); - target_read_u32(target,NVIC_ICTR,&ictr); - cortex_m3->intlinesnum = (ictr&0x1F) + 1; - cortex_m3->intsetenable = calloc(cortex_m3->intlinesnum,4); - for (i=0;iintlinesnum;i++) + target_read_u32(target, NVIC_ICTR, &ictr); + cortex_m3->intlinesnum = (ictr & 0x1F) + 1; + cortex_m3->intsetenable = calloc(cortex_m3->intlinesnum, 4); + for (i = 0; i < cortex_m3->intlinesnum; i++) { - target_read_u32(target,NVIC_ISE0+4*i,cortex_m3->intsetenable+i); - DEBUG(" interrupt enable[%i]=0x%x",i,cortex_m3->intsetenable[i]); + target_read_u32(target, NVIC_ISE0 + 4 * i, cortex_m3->intsetenable + i); + DEBUG("interrupt enable[%i] = 0x%x", i, cortex_m3->intsetenable[i]); } /* Setup FPB */ target_read_u32(target, FP_CTRL, &fpcr); cortex_m3->auto_bp_type = 1; - cortex_m3->fp_num_code = (fpcr>>4)&0xF; - cortex_m3->fp_num_lit = (fpcr>>8)&0xF; + cortex_m3->fp_num_code = (fpcr >> 4) & 0xF; + cortex_m3->fp_num_lit = (fpcr >> 8) & 0xF; cortex_m3->fp_code_available = cortex_m3->fp_num_code; cortex_m3->fp_comparator_list=calloc(cortex_m3->fp_num_code+cortex_m3->fp_num_lit, sizeof(cortex_m3_fp_comparator_t)); - for (i=0;ifp_num_code+cortex_m3->fp_num_lit;i++) + for (i = 0; i < cortex_m3->fp_num_code + cortex_m3->fp_num_lit; i++) { - cortex_m3->fp_comparator_list[i].type = (ifp_num_code)?FPCR_CODE:FPCR_LITERAL; - cortex_m3->fp_comparator_list[i].fpcr_address = FP_COMP0+4*i; + cortex_m3->fp_comparator_list[i].type = (i < cortex_m3->fp_num_code) ? FPCR_CODE : FPCR_LITERAL; + cortex_m3->fp_comparator_list[i].fpcr_address = FP_COMP0 + 4 * i; } - DEBUG("FPB fpcr 0x%x, numcode %i, numlit %i",fpcr,cortex_m3->fp_num_code,cortex_m3->fp_num_lit); + DEBUG("FPB fpcr 0x%x, numcode %i, numlit %i", fpcr, cortex_m3->fp_num_code, cortex_m3->fp_num_lit); /* Setup DWT */ target_read_u32(target, DWT_CTRL, &dwtcr); - cortex_m3->dwt_num_comp = (dwtcr>>28)&0xF; + cortex_m3->dwt_num_comp = (dwtcr >> 28) & 0xF; cortex_m3->dwt_comp_available = cortex_m3->dwt_num_comp; cortex_m3->dwt_comparator_list=calloc(cortex_m3->dwt_num_comp, sizeof(cortex_m3_dwt_comparator_t)); - for (i=0; idwt_num_comp; i++) + for (i = 0; i < cortex_m3->dwt_num_comp; i++) { - cortex_m3->dwt_comparator_list[i].dwt_comparator_address = DWT_COMP0+0x10*i; + cortex_m3->dwt_comparator_list[i].dwt_comparator_address = DWT_COMP0 + 0x10 * i; } return ERROR_OK; @@ -1345,7 +1314,7 @@ int cortex_m3_init_arch_info(target_t *target, cortex_m3_common_t *cortex_m3, in armv7m_common_t *armv7m; armv7m = &cortex_m3->armv7m; - arm_jtag_t * jtag_info = &cortex_m3->jtag_info; + arm_jtag_t *jtag_info = &cortex_m3->jtag_info; /* prepare JTAG information for the new target */ cortex_m3->jtag_info.chain_pos = chain_pos; diff --git a/src/target/cortex_m3.h b/src/target/cortex_m3.h index 63a5c43b19..7061d668ab 100644 --- a/src/target/cortex_m3.h +++ b/src/target/cortex_m3.h @@ -40,7 +40,6 @@ extern char* cortex_m3_state_strings[]; #define DCB_DCRDR 0xE000EDF8 #define DCB_DEMCR 0xE000EDFC - #define DCRSR_WnR (1<<16) #define DWT_CTRL 0xE0001000 @@ -107,7 +106,6 @@ extern char* cortex_m3_state_strings[]; #define DFSR_DWTTRAP 4 #define DFSR_VCATCH 8 - #define FPCR_CODE 0 #define FPCR_LITERAL 1 #define FPCR_REPLACE_REMAP (0<<30) @@ -149,16 +147,16 @@ typedef struct cortex_m3_common_s int fp_num_code; int fp_code_available; int auto_bp_type; - cortex_m3_fp_comparator_t * fp_comparator_list; + cortex_m3_fp_comparator_t *fp_comparator_list; /* DWT */ int dwt_num_comp; int dwt_comp_available; - cortex_m3_dwt_comparator_t * dwt_comparator_list; + cortex_m3_dwt_comparator_t *dwt_comparator_list; /* Interrupts */ int intlinesnum; - u32 * intsetenable; + u32 *intsetenable; /* u32 arm_bkpt; @@ -189,7 +187,6 @@ typedef struct cortex_m3_common_s void *arch_info; } cortex_m3_common_t; - extern void cortex_m3_build_reg_cache(target_t *target); enum target_state cortex_m3_poll(target_t *target); diff --git a/src/target/cortex_swjdp.c b/src/target/cortex_swjdp.c index e50c684374..0815f6ed95 100644 --- a/src/target/cortex_swjdp.c +++ b/src/target/cortex_swjdp.c @@ -25,6 +25,9 @@ * Cortex-M3™ TRM, ARM DDI 0337C * * * ***************************************************************************/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif #include "replacements.h" @@ -55,17 +58,17 @@ are immediatley available. ***************************************************************************/ /* Scan out and in from target ordered u8 buffers */ -int swjdp_scan(arm_jtag_t *jtag_info, u8 chain, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue, u8 *ack) +int swjdp_scan(arm_jtag_t *jtag_info, u8 instr, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue, u8 *ack) { scan_field_t fields[2]; u8 out_addr_buf; jtag_add_end_state(TAP_RTI); - arm_jtag_set_instr(jtag_info, chain, NULL); + arm_jtag_set_instr(jtag_info, instr, NULL); fields[0].device = jtag_info->chain_pos; fields[0].num_bits = 3; - buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr>>1)&0x6) | (RnW&0x1)); + buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1)); fields[0].out_value = &out_addr_buf; fields[0].out_mask = NULL; fields[0].in_value = ack; @@ -87,22 +90,21 @@ int swjdp_scan(arm_jtag_t *jtag_info, u8 chain, u8 reg_addr, u8 RnW, u8 *outvalu jtag_add_dr_scan(2, fields, -1, NULL); return ERROR_OK; - } /* Scan out and in from host ordered u32 variables */ -int swjdp_scan_u32(arm_jtag_t *jtag_info, u8 chain, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue, u8 *ack) +int swjdp_scan_u32(arm_jtag_t *jtag_info, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue, u8 *ack) { scan_field_t fields[2]; u8 out_value_buf[4]; u8 out_addr_buf; jtag_add_end_state(TAP_RTI); - arm_jtag_set_instr(jtag_info, chain, NULL); + arm_jtag_set_instr(jtag_info, instr, NULL); fields[0].device = jtag_info->chain_pos; fields[0].num_bits = 3; - buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr>>1)&0x6) | (RnW&0x1)); + buf_set_u32(&out_addr_buf, 0, 3, ((reg_addr >> 1) & 0x6) | (RnW & 0x1)); fields[0].out_value = &out_addr_buf; fields[0].out_mask = NULL; fields[0].in_value = ack; @@ -133,21 +135,19 @@ int swjdp_scan_u32(arm_jtag_t *jtag_info, u8 chain, u8 reg_addr, u8 RnW, u32 out jtag_add_dr_scan(2, fields, -1, NULL); return ERROR_OK; - } /* scan_inout_check adds one extra inscan for DPAP_READ commands to read variables */ -int scan_inout_check(swjdp_common_t *swjdp, u8 chain, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue) +int scan_inout_check(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u8 *outvalue, u8 *invalue) { - - swjdp_scan(swjdp->jtag_info, chain, reg_addr, RnW, outvalue, NULL, NULL); - if ((RnW==DPAP_READ) && (invalue != NULL)) + swjdp_scan(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL); + if ((RnW == DPAP_READ) && (invalue != NULL)) { swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack); } /* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and the check CTRL_STAT */ - if ((chain == SWJDP_IR_APACC)&&(swjdp->trans_mode == TRANS_MODE_ATOMIC)) + if ((instr == SWJDP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC)) { return swjdp_transaction_endcheck(swjdp); } @@ -155,17 +155,17 @@ int scan_inout_check(swjdp_common_t *swjdp, u8 chain, u8 reg_addr, u8 RnW, u8 *o return ERROR_OK; } -int scan_inout_check_u32(swjdp_common_t *swjdp, u8 chain, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue) +int scan_inout_check_u32(swjdp_common_t *swjdp, u8 instr, u8 reg_addr, u8 RnW, u32 outvalue, u32 *invalue) { - swjdp_scan_u32(swjdp->jtag_info, chain, reg_addr, RnW, outvalue, NULL, NULL); + swjdp_scan_u32(swjdp->jtag_info, instr, reg_addr, RnW, outvalue, NULL, NULL); if ((RnW==DPAP_READ) && (invalue != NULL)) { swjdp_scan_u32(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, invalue, &swjdp->ack); } /* In TRANS_MODE_ATOMIC all SWJDP_IR_APACC transactions wait for ack=OK/FAULT and the check CTRL_STAT */ - if ((chain == SWJDP_IR_APACC)&&(swjdp->trans_mode == TRANS_MODE_ATOMIC)) + if ((instr == SWJDP_IR_APACC) && (swjdp->trans_mode == TRANS_MODE_ATOMIC)) { return swjdp_transaction_endcheck(swjdp); } @@ -177,17 +177,18 @@ int swjdp_transaction_endcheck(swjdp_common_t *swjdp) { int waitcount = 0; u32 ctrlstat; - u8 ack=0; scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat); jtag_execute_queue(); - swjdp->ack = swjdp->ack&0x7; + + swjdp->ack = swjdp->ack & 0x7; + while (swjdp->ack != 2) { - if (swjdp->ack==1) + if (swjdp->ack == 1) { waitcount++; - if (waitcount>100) + if (waitcount > 100) { WARNING("Timeout waiting for ACK = OK/FAULT in SWJDP transaction"); return ERROR_JTAG_DEVICE_ERROR; @@ -200,42 +201,47 @@ int swjdp_transaction_endcheck(swjdp_common_t *swjdp) } scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat); jtag_execute_queue(); - swjdp->ack = swjdp->ack&0x7; + swjdp->ack = swjdp->ack & 0x7; } /* Check for STICKYERR and STICKYORUN */ - if (ctrlstat & (SSTICKYORUN|SSTICKYERR)) + if (ctrlstat & (SSTICKYORUN | SSTICKYERR)) { - DEBUG(" swjdp: CTRL/STAT error 0x%x",ctrlstat); + DEBUG("swjdp: CTRL/STAT error 0x%x", ctrlstat); /* Check power to debug regions */ - if ((ctrlstat&0xf0000000)!=0xf0000000) + if ((ctrlstat & 0xf0000000) != 0xf0000000) { ahbap_debugport_init(swjdp); } else { u32 dcb_dhcsr,nvic_shcsr, nvic_bfar, nvic_cfsr; - if (ctrlstat&SSTICKYORUN) ERROR("SWJ-DP OVERRUN - check clock or reduce jtag speed"); - if (ctrlstat&SSTICKYERR) ERROR("SWJ-DP STICKY ERROR"); + + if (ctrlstat & SSTICKYORUN) + ERROR("SWJ-DP OVERRUN - check clock or reduce jtag speed"); + + if (ctrlstat & SSTICKYERR) + ERROR("SWJ-DP STICKY ERROR"); + /* Clear Sticky Error Bits */ - scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_WRITE, swjdp->dp_ctrl_stat|SSTICKYORUN|SSTICKYERR, NULL); + scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_WRITE, swjdp->dp_ctrl_stat | SSTICKYORUN | SSTICKYERR, NULL); scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, DP_CTRL_STAT, DPAP_READ, 0, &ctrlstat); jtag_execute_queue(); + DEBUG("swjdp: status 0x%x", ctrlstat); + /* Can we find out the reason for the error ?? */ ahbap_read_system_atomic_u32(swjdp, DCB_DHCSR, &dcb_dhcsr); ahbap_read_system_atomic_u32(swjdp, NVIC_SHCSR, &nvic_shcsr); ahbap_read_system_atomic_u32(swjdp, NVIC_CFSR, &nvic_cfsr); ahbap_read_system_atomic_u32(swjdp, NVIC_BFAR, &nvic_bfar); - //DEBUG("dcb_dhcsr %x, nvic_shcsr %x, nvic_cfsr %x, nvic_bfar %x",dcb_dhcsr,nvic_shcsr,nvic_cfsr,nvic_bfar); - ERROR("dcb_dhcsr %x, nvic_shcsr %x, nvic_cfsr %x, nvic_bfar %x",dcb_dhcsr,nvic_shcsr,nvic_cfsr,nvic_bfar); + ERROR("dcb_dhcsr 0x%x, nvic_shcsr 0x%x, nvic_cfsr 0x%x, nvic_bfar 0x%x", dcb_dhcsr, nvic_shcsr, nvic_cfsr, nvic_bfar); } jtag_execute_queue(); return ERROR_JTAG_DEVICE_ERROR; } return ERROR_OK; - } /*************************************************************************** @@ -250,12 +256,10 @@ int swjdp_write_dpacc(swjdp_common_t *swjdp, u32 value, u8 reg_addr) buf_set_u32(out_value_buf, 0, 32, value); return scan_inout_check(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_WRITE, out_value_buf, NULL); - } int swjdp_read_dpacc(swjdp_common_t *swjdp, u32 *value, u8 reg_addr) { - scan_inout_check_u32(swjdp, SWJDP_IR_DPACC, reg_addr, DPAP_READ, 0, value); return ERROR_OK; @@ -264,9 +268,9 @@ int swjdp_read_dpacc(swjdp_common_t *swjdp, u32 *value, u8 reg_addr) int swjdp_bankselect_apacc(swjdp_common_t *swjdp,u32 reg_addr) { u32 select; - select = (reg_addr&0xFF0000F0); + select = (reg_addr & 0xFF0000F0); - if ( select != swjdp->dp_select_value ) + if (select != swjdp->dp_select_value) { swjdp_write_dpacc(swjdp, select, DP_SELECT); swjdp->dp_select_value = select; @@ -317,17 +321,16 @@ int ahbap_read_reg_u32(swjdp_common_t *swjdp, u32 reg_addr, u32 *value) int ahbap_setup_accessport(swjdp_common_t *swjdp, u32 csw, u32 tar) { - csw = csw | CSW_DBGSWENABLE | CSW_MASTER_DEBUG | CSW_HPROT; - if ( csw != swjdp->ap_csw_value ) + if (csw != swjdp->ap_csw_value) { - //DEBUG("swjdp : Set CSW %x",csw); + //DEBUG("swjdp : Set CSW %x",csw); ahbap_write_reg_u32(swjdp, AHBAP_CSW, csw ); swjdp->ap_csw_value = csw; } - if ( tar != swjdp->ap_tar_value ) + if (tar != swjdp->ap_tar_value) { - //DEBUG("swjdp : Set TAR %x",tar); + //DEBUG("swjdp : Set TAR %x",tar); ahbap_write_reg_u32(swjdp, AHBAP_TAR, tar ); swjdp->ap_tar_value = tar; } @@ -349,11 +352,10 @@ int ahbap_setup_accessport(swjdp_common_t *swjdp, u32 csw, u32 tar) *****************************************************************************/ int ahbap_read_system_u32(swjdp_common_t *swjdp, u32 address, u32 *value) { - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address&0xFFFFFFF0); - ahbap_read_reg_u32(swjdp, AHBAP_BD0|address&0xC, value ); + ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0); + ahbap_read_reg_u32(swjdp, AHBAP_BD0 | (address & 0xC), value ); return ERROR_OK; } @@ -374,18 +376,16 @@ int ahbap_read_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 *value) *****************************************************************************/ int ahbap_write_system_u32(swjdp_common_t *swjdp, u32 address, u32 value) { - swjdp->trans_mode = TRANS_MODE_COMPOSITE; - ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address&0xFFFFFFF0); - ahbap_write_reg_u32(swjdp, AHBAP_BD0|address&0xC, value ); + ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, address & 0xFFFFFFF0); + ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (address & 0xC), value ); return ERROR_OK; } int ahbap_write_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 value) { - ahbap_write_system_u32(swjdp, address, value); return swjdp_transaction_endcheck(swjdp); @@ -401,53 +401,53 @@ int ahbap_write_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 value) int ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address) { u32 outvalue; - int wcount, blocksize, writecount, errorcount=0, retval=ERROR_OK; + int wcount, blocksize, writecount, errorcount = 0, retval = ERROR_OK; swjdp->trans_mode = TRANS_MODE_COMPOSITE; - while ( (address&0x3)&&(count>0) ) + while ((address & 0x3) && (count > 0)) { ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address); - outvalue = (*buffer++)<<8*(address&0x3) ; + outvalue = (*buffer++) << 8 * (address & 0x3); ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue ); swjdp_transaction_endcheck(swjdp); count--; address++; } - wcount = count>>2; - count = count-4*wcount; - while (wcount>0) + wcount = count >> 2; + count = count - 4 * wcount; + while (wcount > 0) { /* Adjust to read within 4K block boundaries */ - blocksize = (0x1000-(0xFFF&address))>>2; - if (wcount> 2; + if (wcount < blocksize) blocksize = wcount; ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address); for (writecount=0; writecount1) + if (errorcount > 1) { WARNING("Block read error address %x, count %x", address, count); return ERROR_JTAG_DEVICE_ERROR; } } - - while (count>0) + + while (count > 0) { ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address); - outvalue = (*buffer++)<<8*(address&0x3) ; + outvalue = (*buffer++) << 8 * (address & 0x3); ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue ); retval = swjdp_transaction_endcheck(swjdp); count--; @@ -457,6 +457,27 @@ int ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address) return retval; } +int ahbap_write_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address) +{ + u32 outvalue; + int retval = ERROR_OK; + + swjdp->trans_mode = TRANS_MODE_COMPOSITE; + + while (count > 0) + { + ahbap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address); + outvalue = *((u16*)buffer) << 8 * (address & 0x3); + ahbap_write_reg_u32(swjdp, AHBAP_DRW, outvalue ); + retval = swjdp_transaction_endcheck(swjdp); + count -= 2; + address += 2; + buffer += 2; + } + + return retval; +} + /***************************************************************************** * * * ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address) * @@ -467,60 +488,60 @@ int ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address) int ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address) { u32 invalue; - int wcount, blocksize, readcount, errorcount=0, retval=ERROR_OK; + int wcount, blocksize, readcount, errorcount = 0, retval = ERROR_OK; swjdp->trans_mode = TRANS_MODE_COMPOSITE; - while ( (address&0x3)&&(count>0) ) + while ((address & 0x3) && (count > 0)) { ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address); - ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue ); + ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue); swjdp_transaction_endcheck(swjdp); - *buffer++ = (invalue>>8*(address&0x3))&0xFF; + *buffer++ = (invalue >> 8 * (address & 0x3)) & 0xFF; count--; address++; } - wcount = count>>2; - count = count-4*wcount; - while (wcount>0) + wcount = count >> 2; + count = count - 4 * wcount; + while (wcount > 0) { /* Adjust to read within 4K block boundaries */ - blocksize = (0x1000-(0xFFF&address))>>2; - if (wcount> 2; + if (wcount < blocksize) blocksize = wcount; ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address); /* Scan out first read */ swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, NULL, NULL); - for (readcount=0; readcountjtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, buffer+4*readcount, &swjdp->ack); + swjdp_scan(swjdp->jtag_info, SWJDP_IR_APACC, AHBAP_DRW, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack); } /* Scan in last value */ - swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, buffer+4*readcount, &swjdp->ack); - if (swjdp_transaction_endcheck(swjdp)==ERROR_OK) + swjdp_scan(swjdp->jtag_info, SWJDP_IR_DPACC, 0xC, DPAP_READ, 0, buffer + 4 * readcount, &swjdp->ack); + if (swjdp_transaction_endcheck(swjdp) == ERROR_OK) { - wcount = wcount-blocksize; - address += 4*blocksize; - buffer += 4*blocksize; + wcount = wcount - blocksize; + address += 4 * blocksize; + buffer += 4 * blocksize; } else { errorcount++; } - if (errorcount>1) + if (errorcount > 1) { WARNING("Block read error address %x, count %x", address, count); return ERROR_JTAG_DEVICE_ERROR; } } - while (count>0) + while (count > 0) { ahbap_setup_accessport(swjdp, CSW_8BIT | CSW_ADDRINC_SINGLE, address); ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue ); retval = swjdp_transaction_endcheck(swjdp); - *buffer++ = (invalue>>8*(address&0x3))&0xFF; + *buffer++ = (invalue >> 8 * (address & 0x3)) & 0xFF; count--; address++; } @@ -528,35 +549,56 @@ int ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address) return retval; } +int ahbap_read_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address) +{ + u32 invalue; + int retval = ERROR_OK; + + swjdp->trans_mode = TRANS_MODE_COMPOSITE; + + while (count > 0) + { + ahbap_setup_accessport(swjdp, CSW_16BIT | CSW_ADDRINC_SINGLE, address); + ahbap_read_reg_u32(swjdp, AHBAP_DRW, &invalue ); + retval = swjdp_transaction_endcheck(swjdp); + *((u16*)buffer) = (invalue >> 8 * (address & 0x3)); + count -= 2; + address += 2; + buffer += 2; + } + + return retval; +} + int ahbap_block_read_u32(swjdp_common_t *swjdp, u32 *buffer, int count, u32 address) { - int readcount, errorcount=0; + int readcount, errorcount = 0; u32 blockmax, blocksize; swjdp->trans_mode = TRANS_MODE_COMPOSITE; - while (count>0) + while (count > 0) { /* Adjust to read within 4K block boundaries */ - blocksize = (0x1000-(0xFFF&address))>>2; - if (count> 2; + if (count < blocksize) blocksize = count; ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_SINGLE, address); - for (readcount=0; readcount1) + if (errorcount > 1) { WARNING("Block read error address %x, count %x", address, count); return ERROR_JTAG_DEVICE_ERROR; @@ -571,12 +613,12 @@ int ahbap_read_coreregister_u32(swjdp_common_t *swjdp, u32 *value, int regnum) swjdp->trans_mode = TRANS_MODE_COMPOSITE; /* ahbap_write_system_u32(swjdp, DCB_DCRSR, regnum); */ - ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR&0xFFFFFFF0); - ahbap_write_reg_u32(swjdp, AHBAP_BD0|DCB_DCRSR&0xC, regnum ); + ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0); + ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRSR & 0xC), regnum ); /* ahbap_read_system_u32(swjdp, DCB_DCRDR, value); */ - ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR&0xFFFFFFF0); - ahbap_read_reg_u32(swjdp, AHBAP_BD0|DCB_DCRDR&0xC, value ); + ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0); + ahbap_read_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRDR & 0xC), value ); return swjdp_transaction_endcheck(swjdp); } @@ -586,65 +628,64 @@ int ahbap_write_coreregister_u32(swjdp_common_t *swjdp, u32 value, int regnum) swjdp->trans_mode = TRANS_MODE_COMPOSITE; /* ahbap_write_system_u32(swjdp, DCB_DCRDR, core_regs[i]); */ - ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR&0xFFFFFFF0); - ahbap_write_reg_u32(swjdp, AHBAP_BD0|DCB_DCRDR&0xC, value ); + ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRDR & 0xFFFFFFF0); + ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRDR & 0xC), value ); /* ahbap_write_system_u32(swjdp, DCB_DCRSR, i | DCRSR_WnR ); */ - ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR&0xFFFFFFF0); - ahbap_write_reg_u32(swjdp, AHBAP_BD0|DCB_DCRSR&0xC, regnum | DCRSR_WnR ); + ahbap_setup_accessport(swjdp, CSW_32BIT | CSW_ADDRINC_OFF, DCB_DCRSR & 0xFFFFFFF0); + ahbap_write_reg_u32(swjdp, AHBAP_BD0 | (DCB_DCRSR & 0xC), regnum | DCRSR_WnR ); return swjdp_transaction_endcheck(swjdp); } int ahbap_debugport_init(swjdp_common_t *swjdp) { - -u32 idreg, romaddr, dummy; -u32 ctrlstat; -int cnt=0; -DEBUG(""); + u32 idreg, romaddr, dummy; + u32 ctrlstat; + int cnt = 0; + + DEBUG(" "); + swjdp->ap_csw_value = -1; swjdp->ap_tar_value = -1; swjdp->trans_mode = TRANS_MODE_ATOMIC; swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT); swjdp_write_dpacc(swjdp, SSTICKYERR, DP_CTRL_STAT); swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT); - - swjdp->dp_ctrl_stat = CDBGPWRUPREQ|CSYSPWRUPREQ; + + swjdp->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat, DP_CTRL_STAT); swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT); jtag_execute_queue(); /* Check that we have debug power domains activated */ - while (!(ctrlstat & CDBGPWRUPACK) && (cnt++<10)) + while (!(ctrlstat & CDBGPWRUPACK) && (cnt++ < 10)) { - DEBUG(" swjdp: wait CDBGPWRUPACK"); + DEBUG("swjdp: wait CDBGPWRUPACK"); swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT); jtag_execute_queue(); - usleep(10000); } - while (!(ctrlstat & CSYSPWRUPACK) && (cnt++<10)) + while (!(ctrlstat & CSYSPWRUPACK) && (cnt++ < 10)) { - DEBUG(" swjdp: wait CSYSPWRUPACK"); + DEBUG("swjdp: wait CSYSPWRUPACK"); swjdp_read_dpacc(swjdp, &ctrlstat, DP_CTRL_STAT); jtag_execute_queue(); usleep(10000); } - swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT); /* With debug power on we can activate OVERRUN checking */ - swjdp->dp_ctrl_stat = CDBGPWRUPREQ|CSYSPWRUPREQ|CORUNDETECT; + swjdp->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT; swjdp_write_dpacc(swjdp, swjdp->dp_ctrl_stat , DP_CTRL_STAT); swjdp_read_dpacc(swjdp, &dummy, DP_CTRL_STAT); - ahbap_read_reg_u32(swjdp, 0xFC, &idreg ); - ahbap_read_reg_u32(swjdp, 0xF8, &romaddr ); + ahbap_read_reg_u32(swjdp, 0xFC, &idreg); + ahbap_read_reg_u32(swjdp, 0xF8, &romaddr); -DEBUG("AHB-AP ID Register 0x%x, Debug ROM Address 0x%x",idreg,romaddr); + DEBUG("AHB-AP ID Register 0x%x, Debug ROM Address 0x%x", idreg, romaddr); return ERROR_OK; } diff --git a/src/target/cortex_swjdp.h b/src/target/cortex_swjdp.h index 093f2ed54d..ad6c69a67c 100644 --- a/src/target/cortex_swjdp.h +++ b/src/target/cortex_swjdp.h @@ -44,8 +44,6 @@ #define CSYSPWRUPREQ (1<<30) #define CSYSPWRUPACK (1<<31) - - #define AHBAP_CSW 0x00 #define AHBAP_TAR 0x04 #define AHBAP_DRW 0x0C @@ -56,7 +54,6 @@ #define AHBAP_DBGROMA 0xF8 #define AHBAP_IDR 0xFC - #define CSW_8BIT 0 #define CSW_16BIT 1 #define CSW_32BIT 2 @@ -65,17 +62,17 @@ #define CSW_ADDRINC_OFF 0 #define CSW_ADDRINC_SINGLE (1<<4) #define CSW_ADDRINC_PACKED (2<<4) -#define CSW_HPROT (1<<25) +#define CSW_HPROT (1<<25) #define CSW_MASTER_DEBUG (1<<29) -#define CSW_DBGSWENABLE (1<<31) -#define TRANS_MODE_NONE 0 +#define CSW_DBGSWENABLE (1<<31) +/* transaction mode */ +#define TRANS_MODE_NONE 0 /* Transaction waits for previous to complete */ #define TRANS_MODE_ATOMIC 1 /* Freerunning transactions with delays and overrun checking */ #define TRANS_MODE_COMPOSITE 2 - typedef struct swjdp_reg_s { int addr; @@ -96,7 +93,7 @@ typedef struct swjdp_common_s u8 trans_mode; u8 trans_rw; u8 ack; - u32 * trans_value; + u32 *trans_value; } swjdp_common_t; /* Internal functions used in the module, partial transactions, use with caution */ @@ -112,7 +109,6 @@ extern int ahbap_read_system_u32(swjdp_common_t *swjdp, u32 address, u32 *value) extern int ahbap_write_system_u32(swjdp_common_t *swjdp, u32 address, u32 value); extern int swjdp_transaction_endcheck(swjdp_common_t *swjdp); - /* External interface, complete atomic operations */ /* Host endian word transfer of single memory and system registers */ extern int ahbap_read_system_atomic_u32(swjdp_common_t *swjdp, u32 address, u32 *value); @@ -124,6 +120,11 @@ extern int ahbap_write_block(swjdp_common_t *swjdp, u8 *buffer, int bytecount, u extern int ahbap_read_coreregister_u32(swjdp_common_t *swjdp, u32 *value, int regnum); extern int ahbap_write_coreregister_u32(swjdp_common_t *swjdp, u32 value, int regnum); +extern int ahbap_read_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address); +extern int ahbap_read_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address); +extern int ahbap_write_buf(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address); +extern int ahbap_write_buf_u16(swjdp_common_t *swjdp, u8 *buffer, int count, u32 address); + /* Initialisation of the debug system, power domains and registers */ extern int ahbap_debugport_init(swjdp_common_t *swjdp); diff --git a/src/target/target.c b/src/target/target.c index 2eeb2bfc5c..07c450cd31 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -653,6 +653,7 @@ int target_write_buffer(struct target_s *target, u32 address, u32 size, u8 *buff { if ((retval = target->type->write_memory(target, address, 1, size, buffer)) != ERROR_OK) return retval; + return ERROR_OK; } /* handle unaligned head bytes */ @@ -711,6 +712,7 @@ int target_read_buffer(struct target_s *target, u32 address, u32 size, u8 *buffe { if ((retval = target->type->read_memory(target, address, 1, size, buffer)) != ERROR_OK) return retval; + return ERROR_OK; } /* handle unaligned head bytes */