From 56e60b0982b5f7fc00e3ca8c43887f2221d7ad76 Mon Sep 17 00:00:00 2001 From: Spencer Oliver Date: Tue, 4 Oct 2016 09:38:21 +0100 Subject: stm32l4x: fix incorrect device id mask Change-Id: I37cf9cbdd07dc3764d2c719b7c6ed5852aea3943 Signed-off-by: Spencer Oliver Reviewed-on: http://openocd.zylin.com/3799 Tested-by: jenkins --- src/flash/nor/stm32l4x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 129b281..7a75c52 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -698,7 +698,7 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size) if (retval != ERROR_OK) return retval; - uint16_t device_id = dbgmcu_idcode & 0xffff; + uint16_t device_id = dbgmcu_idcode & 0xfff; uint8_t rev_id = dbgmcu_idcode >> 28; uint8_t rev_minor = 0; int i; @@ -713,7 +713,7 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size) const char *device_str; switch (device_id) { - case 0x6415: + case 0x415: device_str = "STM32L4xx"; break; -- cgit v1.1 From 5108fb591b845ba066430ded56ca9c17e26d3f3f Mon Sep 17 00:00:00 2001 From: Peter Kuhar Date: Tue, 4 Oct 2016 09:32:25 +0100 Subject: STM32L433 Flash support Added new chip id based flash size. Change-Id: I5b5e71074af0e50352443f66f88adfc6e14280bf Signed-off-by: Peter Kuhar Reviewed-on: http://openocd.zylin.com/3732 Tested-by: jenkins Reviewed-by: Spencer Oliver --- src/flash/nor/stm32l4x.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 7a75c52..762df74 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -617,6 +617,9 @@ static int stm32l4_probe(struct flash_bank *bank) case 0x415: max_flash_size_in_kb = 1024; break; + case 0x435: + max_flash_size_in_kb = 256; + break; default: LOG_WARNING("Cannot identify target as a STM32L4 family."); return ERROR_FAIL; @@ -717,6 +720,10 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size) device_str = "STM32L4xx"; break; + case 0x435: + device_str = "STM32L43x"; + break; + default: snprintf(buf, buf_size, "Cannot identify target as a STM32L4\n"); return ERROR_FAIL; -- cgit v1.1 From 727f178ab9d7cee04d883555aa57b917c3f2296c Mon Sep 17 00:00:00 2001 From: Kent Brinkley Date: Tue, 21 Oct 2014 07:46:30 -0700 Subject: mips: Added #define for scan_delay legacy mode default value Believe in using defines to make maintenance easier. Change-Id: I8edf151352131bbf2b884dfcd67ca5764b11b13c Signed-off-by: Kent Brinkley Reviewed-on: http://openocd.zylin.com/2350 Reviewed-by: Andreas Fritiofson Tested-by: jenkins --- src/target/mips32.c | 4 ++-- src/target/mips32.h | 2 ++ src/target/mips_m4k.c | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/target/mips32.c b/src/target/mips32.c index 3292446..8c77986 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -384,7 +384,7 @@ int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, s mips32->read_core_reg = mips32_read_core_reg; mips32->write_core_reg = mips32_write_core_reg; - mips32->ejtag_info.scan_delay = 2000000; /* Initial default value */ + mips32->ejtag_info.scan_delay = MIPS32_SCAN_DELAY_LEGACY_MODE; /* Initial default value */ mips32->ejtag_info.mode = 0; /* Initial default value */ return ERROR_OK; @@ -911,7 +911,7 @@ COMMAND_HANDLER(mips32_handle_scan_delay_command) return ERROR_COMMAND_SYNTAX_ERROR; command_print(CMD_CTX, "scan delay: %d nsec", ejtag_info->scan_delay); - if (ejtag_info->scan_delay >= 2000000) { + if (ejtag_info->scan_delay >= MIPS32_SCAN_DELAY_LEGACY_MODE) { ejtag_info->mode = 0; command_print(CMD_CTX, "running in legacy mode"); } else { diff --git a/src/target/mips32.h b/src/target/mips32.h index bfd2cf5..8362f5e 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -61,6 +61,8 @@ #define MIPS32_ARCH_REL1 0x0 #define MIPS32_ARCH_REL2 0x1 +#define MIPS32_SCAN_DELAY_LEGACY_MODE 2000000 + /* offsets into mips32 core register cache */ enum { MIPS32_PC = 37, diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 0daa71c..db69b95 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -1339,7 +1339,7 @@ COMMAND_HANDLER(mips_m4k_handle_scan_delay_command) return ERROR_COMMAND_SYNTAX_ERROR; command_print(CMD_CTX, "scan delay: %d nsec", ejtag_info->scan_delay); - if (ejtag_info->scan_delay >= 2000000) { + if (ejtag_info->scan_delay >= MIPS32_SCAN_DELAY_LEGACY_MODE) { ejtag_info->mode = 0; command_print(CMD_CTX, "running in legacy mode"); } else { -- cgit v1.1 From 7919694832ec989b71b93a9a9563a05c9e503d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 14 Aug 2016 18:14:09 +0200 Subject: x86_32_common: Fix typo in function name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit pyhs -> phys Change-Id: Ie7edc74f1693b42f26e1e8475a93a7a6b9255cdd Signed-off-by: Andreas Färber Reviewed-on: http://openocd.zylin.com/3672 Reviewed-by: Andreas Fritiofson Tested-by: jenkins --- src/target/x86_32_common.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/target/x86_32_common.c b/src/target/x86_32_common.c index 3f4c7aa..c21167e 100644 --- a/src/target/x86_32_common.c +++ b/src/target/x86_32_common.c @@ -48,7 +48,7 @@ static int read_mem(struct target *t, uint32_t size, uint32_t addr, uint8_t *buf); static int write_mem(struct target *t, uint32_t size, uint32_t addr, const uint8_t *buf); -static int calcaddr_pyhsfromlin(struct target *t, uint32_t addr, +static int calcaddr_physfromlin(struct target *t, uint32_t addr, uint32_t *physaddr); static int read_phys_mem(struct target *t, uint32_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer); @@ -134,7 +134,7 @@ int x86_32_common_virt2phys(struct target *t, uint32_t address, uint32_t *physic } else { /* target halted in protected mode */ - if (calcaddr_pyhsfromlin(t, address, physical) != ERROR_OK) { + if (calcaddr_physfromlin(t, address, physical) != ERROR_OK) { LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32, __func__, address); return ERROR_FAIL; @@ -444,7 +444,7 @@ static int write_mem(struct target *t, uint32_t size, return retval; } -int calcaddr_pyhsfromlin(struct target *t, uint32_t addr, uint32_t *physaddr) +int calcaddr_physfromlin(struct target *t, uint32_t addr, uint32_t *physaddr) { uint8_t entry_buffer[8]; @@ -592,7 +592,7 @@ int x86_32_common_read_memory(struct target *t, uint32_t addr, return retval; } uint32_t physaddr = 0; - if (calcaddr_pyhsfromlin(t, addr, &physaddr) != ERROR_OK) { + if (calcaddr_physfromlin(t, addr, &physaddr) != ERROR_OK) { LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32, __func__, addr); retval = ERROR_FAIL; } @@ -646,7 +646,7 @@ int x86_32_common_write_memory(struct target *t, uint32_t addr, return retval; } uint32_t physaddr = 0; - if (calcaddr_pyhsfromlin(t, addr, &physaddr) != ERROR_OK) { + if (calcaddr_physfromlin(t, addr, &physaddr) != ERROR_OK) { LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32, __func__, addr); retval = ERROR_FAIL; @@ -1016,7 +1016,7 @@ static int set_swbp(struct target *t, struct breakpoint *bp) uint8_t opcode = SW_BP_OPCODE; uint8_t readback; - if (calcaddr_pyhsfromlin(t, bp->address, &physaddr) != ERROR_OK) + if (calcaddr_physfromlin(t, bp->address, &physaddr) != ERROR_OK) return ERROR_FAIL; if (read_phys_mem(t, physaddr, 1, 1, bp->orig_instr)) return ERROR_FAIL; @@ -1072,7 +1072,7 @@ static int unset_swbp(struct target *t, struct breakpoint *bp) uint8_t current_instr; /* check that user program has not modified breakpoint instruction */ - if (calcaddr_pyhsfromlin(t, bp->address, &physaddr) != ERROR_OK) + if (calcaddr_physfromlin(t, bp->address, &physaddr) != ERROR_OK) return ERROR_FAIL; if (read_phys_mem(t, physaddr, 1, 1, ¤t_instr)) return ERROR_FAIL; -- cgit v1.1 From 5fd5699859db4be2dadef69c85adbb0acda36e84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 14 Aug 2016 18:48:38 +0200 Subject: nds32: Fix typo in debug log MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wathcpoint -> watchpoint Change-Id: If84cfb5097ed17ef97491667c622ba7d870ac9c2 Signed-off-by: Andreas Färber Reviewed-on: http://openocd.zylin.com/3673 Tested-by: jenkins Reviewed-by: Spencer Oliver --- src/target/nds32_v2.c | 4 ++-- src/target/nds32_v3.c | 4 ++-- src/target/nds32_v3m.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/target/nds32_v2.c b/src/target/nds32_v2.c index da8bbbc..4497551 100644 --- a/src/target/nds32_v2.c +++ b/src/target/nds32_v2.c @@ -184,7 +184,7 @@ static int nds32_v2_activate_hardware_watchpoint(struct target *target) /* set value */ aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0); - LOG_DEBUG("Add hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num, + LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num, wp->address, wp->mask); } @@ -204,7 +204,7 @@ static int nds32_v2_deactivate_hardware_watchpoint(struct target *target) /* disable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0); - LOG_DEBUG("Remove hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, + LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num, wp->address, wp->mask); } diff --git a/src/target/nds32_v3.c b/src/target/nds32_v3.c index 43d7054..35b72e3 100644 --- a/src/target/nds32_v3.c +++ b/src/target/nds32_v3.c @@ -128,7 +128,7 @@ static int nds32_v3_activate_hardware_watchpoint(struct target *target) /* set value */ aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0); - LOG_DEBUG("Add hardware wathcpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, + LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; @@ -169,7 +169,7 @@ static int nds32_v3_deactivate_hardware_watchpoint(struct target *target) /* disable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0); - LOG_DEBUG("Remove hardware wathcpoint %" PRId32 " at %08" PRIx32 + LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; diff --git a/src/target/nds32_v3m.c b/src/target/nds32_v3m.c index 919c0c8..2d52bc3 100644 --- a/src/target/nds32_v3m.c +++ b/src/target/nds32_v3m.c @@ -125,7 +125,7 @@ static int nds32_v3m_activate_hardware_watchpoint(struct target *target) /* enable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config); - LOG_DEBUG("Add hardware wathcpoint %" PRId32 " at %08" PRIx32 + LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; @@ -166,7 +166,7 @@ static int nds32_v3m_deactivate_hardware_watchpoint(struct target *target) /* disable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0); - LOG_DEBUG("Remove hardware wathcpoint %" PRId32 " at %08" PRIx32 + LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; } else if (nds32_v3m->nds32.global_stop) { -- cgit v1.1 From db6c6f5da4deaffc548122703e6951d0b1710603 Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Sun, 14 Aug 2016 15:15:27 +0200 Subject: ftdi: don't wait forever if we fail MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently if ftdi device is removed, OpenOCD will stall forever. Only kill -9 will help in this case. This patch makes use of libusb timeout functions and trying to break out of while loop if some error is detected. [andreas.fritiofson@gmail.com]: Add missing retval check Change-Id: I97506190e376026705f14ef9fe37dc811b99b3ac Signed-off-by: Oleksij Rempel Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3419 Reviewed-by: Andreas Färber Tested-by: jenkins --- src/jtag/drivers/mpsse.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c index 0ef88ba..3c1c97c 100644 --- a/src/jtag/drivers/mpsse.c +++ b/src/jtag/drivers/mpsse.c @@ -872,6 +872,8 @@ int mpsse_flush(struct mpsse_ctx *ctx) libusb_fill_bulk_transfer(write_transfer, ctx->usb_dev, ctx->out_ep, ctx->write_buffer, ctx->write_count, write_cb, &write_result, ctx->usb_write_timeout); retval = libusb_submit_transfer(write_transfer); + if (retval != LIBUSB_SUCCESS) + goto error_check; if (ctx->read_count) { read_transfer = libusb_alloc_transfer(0); @@ -879,22 +881,36 @@ int mpsse_flush(struct mpsse_ctx *ctx) ctx->read_chunk_size, read_cb, &read_result, ctx->usb_read_timeout); retval = libusb_submit_transfer(read_transfer); + if (retval != LIBUSB_SUCCESS) + goto error_check; } /* Polling loop, more or less taken from libftdi */ while (!write_result.done || !read_result.done) { - retval = libusb_handle_events(ctx->usb_ctx); + struct timeval timeout_usb; + + timeout_usb.tv_sec = 1; + timeout_usb.tv_usec = 0; + + retval = libusb_handle_events_timeout_completed(ctx->usb_ctx, &timeout_usb, NULL); keep_alive(); - if (retval != LIBUSB_SUCCESS && retval != LIBUSB_ERROR_INTERRUPTED) { + if (retval == LIBUSB_ERROR_NO_DEVICE || retval == LIBUSB_ERROR_INTERRUPTED) + break; + + if (retval != LIBUSB_SUCCESS) { libusb_cancel_transfer(write_transfer); if (read_transfer) libusb_cancel_transfer(read_transfer); - while (!write_result.done || !read_result.done) - if (libusb_handle_events(ctx->usb_ctx) != LIBUSB_SUCCESS) + while (!write_result.done || !read_result.done) { + retval = libusb_handle_events_timeout_completed(ctx->usb_ctx, + &timeout_usb, NULL); + if (retval != LIBUSB_SUCCESS) break; + } } } +error_check: if (retval != LIBUSB_SUCCESS) { LOG_ERROR("libusb_handle_events() failed with %s", libusb_error_name(retval)); retval = ERROR_FAIL; -- cgit v1.1 From 400dbedaeec230d9438d2c95a61ee63f2c15cc6d Mon Sep 17 00:00:00 2001 From: Michael Dietz Date: Mon, 30 May 2016 01:54:47 -0700 Subject: nRF51: Fix bug in Code memory size. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code memory size was a bug and seemed to be working by accident since there happened to be 256 pages in the device that was tested on which corresponded to 256kb. Also don't fail if memory size != expected memory size based on hwid as this hwid is unstable and should be used only for debug/diagnostics. Change-Id: I4e98f7498a36c53fc51783eddfdaba704d30e3ca Signed-off-by: Michael Dietz Reviewed-on: http://openocd.zylin.com/3510 Tested-by: jenkins Reviewed-by: Jiří Pinkava Reviewed-by: Tomas Vanek --- src/flash/nor/nrf51.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/flash/nor/nrf51.c b/src/flash/nor/nrf51.c index 69bf666..60f6d3c 100644 --- a/src/flash/nor/nrf51.c +++ b/src/flash/nor/nrf51.c @@ -108,7 +108,6 @@ enum nrf51_nvmc_config_bits { struct nrf51_info { uint32_t code_page_size; - uint32_t code_memory_size; struct { bool probed; @@ -641,29 +640,29 @@ static int nrf51_probe(struct flash_bank *bank) LOG_WARNING("Unknown device (HWID 0x%08" PRIx32 ")", hwid); } - if (bank->base == NRF51_FLASH_BASE) { + /* The value stored in NRF51_FICR_CODEPAGESIZE is the number of bytes in one page of FLASH. */ res = target_read_u32(chip->target, NRF51_FICR_CODEPAGESIZE, - &chip->code_page_size); + &chip->code_page_size); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code page size"); return res; } + /* Note the register name is misleading, + * NRF51_FICR_CODESIZE is the number of pages in flash memory, not the number of bytes! */ res = target_read_u32(chip->target, NRF51_FICR_CODESIZE, - &chip->code_memory_size); + (uint32_t *) &bank->num_sectors); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code memory size"); return res; } - if (spec && chip->code_memory_size != spec->flash_size_kb) { - LOG_ERROR("Chip's reported Flash capacity does not match expected one"); - return ERROR_FAIL; - } + bank->size = bank->num_sectors * chip->code_page_size; + + if (spec && bank->size / 1024 != spec->flash_size_kb) + LOG_WARNING("Chip's reported Flash capacity does not match expected one"); - bank->size = chip->code_memory_size * 1024; - bank->num_sectors = bank->size / chip->code_page_size; bank->sectors = calloc(bank->num_sectors, sizeof((bank->sectors)[0])); if (!bank->sectors) @@ -1272,7 +1271,7 @@ static int nrf51_info(struct flash_bank *bank, char *buf, int buf_size) "reset value for XTALFREQ: %"PRIx32"\n" "firmware id: 0x%04"PRIx32, ficr[0].value, - ficr[1].value, + (ficr[1].value * ficr[0].value) / 1024, (ficr[2].value == 0xFFFFFFFF) ? 0 : ficr[2].value / 1024, ((ficr[3].value & 0xFF) == 0x00) ? "present" : "not present", ficr[4].value, -- cgit v1.1 From 12aee423db1aa1d315392dbaa60122c871054714 Mon Sep 17 00:00:00 2001 From: Robert Jordens Date: Mon, 21 Dec 2015 13:36:14 -0700 Subject: xilinx_bscan_spi: port to new migen and clean-up MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * port to new migen * streamline package/part specification * add pullup (Series3, Series6) and pullnone (Series7) for unused pins as xilinx impact/vivado do it. * specify respective toolchains * build Series7 with vivado (broader support, faster) * point to prebuilt bitstreams at https://github.com/jordens/bscan_spi_bitstreams Change-Id: Ibfef3d78f855b754425f3e6131e2e49fa111e09a Signed-off-by: Robert Jordens Reviewed-on: http://openocd.zylin.com/3173 Reviewed-by: Andreas Fritiofson Tested-by: jenkins Reviewed-by: Robert Jördens Reviewed-by: William D. Jones Reviewed-by: Tim "mithro" Ansell --- contrib/loaders/flash/fpga/xilinx_bscan_spi.py | 314 ++++++++++--------------- 1 file changed, 121 insertions(+), 193 deletions(-) diff --git a/contrib/loaders/flash/fpga/xilinx_bscan_spi.py b/contrib/loaders/flash/fpga/xilinx_bscan_spi.py index a107a6a..fa4ec2a 100755 --- a/contrib/loaders/flash/fpga/xilinx_bscan_spi.py +++ b/contrib/loaders/flash/fpga/xilinx_bscan_spi.py @@ -13,20 +13,21 @@ # GNU General Public License for more details. # -from migen.fhdl.std import * -from mibuild.generic_platform import * -from mibuild.xilinx import XilinxPlatform -from mibuild.xilinx.vivado import XilinxVivadoToolchain -from mibuild.xilinx.ise import XilinxISEToolchain +from migen import * +from migen.build.generic_platform import * +from migen.build import xilinx """ This migen script produces proxy bitstreams to allow programming SPI flashes -behind FPGAs. JTAG signalling is connected directly to SPI signalling. CS_N is -asserted when the JTAG IR contains the USER1 instruction and the state is -SHIFT-DR. +behind FPGAs. + +Bitstream binaries built with this script are available at: +https://github.com/jordens/bscan_spi_bitstreams -Xilinx bscan cells sample TDO on falling TCK and forward it. +JTAG signalling is connected directly to SPI signalling. CS_N is +asserted when the JTAG IR contains the USER1 instruction and the state is +SHIFT-DR. Xilinx bscan cells sample TDO on falling TCK and forward it. MISO requires sampling on rising CLK and leads to one cycle of latency. https://github.com/m-labs/migen @@ -35,8 +36,10 @@ https://github.com/m-labs/migen class Spartan3(Module): macro = "BSCAN_SPARTAN3" + toolchain = "ise" def __init__(self, platform): + platform.toolchain.bitgen_opt += " -g compress -g UnusedPin:Pullup" self.clock_domains.cd_jtag = ClockDomain(reset_less=True) spi = platform.request("spiflash") shift = Signal() @@ -58,7 +61,10 @@ class Spartan3A(Spartan3): class Spartan6(Module): + toolchain = "ise" + def __init__(self, platform): + platform.toolchain.bitgen_opt += " -g compress -g UnusedPin:Pullup" self.clock_domains.cd_jtag = ClockDomain(reset_less=True) spi = platform.request("spiflash") shift = Signal() @@ -72,7 +78,13 @@ class Spartan6(Module): class Series7(Module): + toolchain = "vivado" + def __init__(self, platform): + platform.toolchain.bitstream_commands.extend([ + "set_property BITSTREAM.GENERAL.COMPRESS True [current_design]", + "set_property BITSTREAM.CONFIG.UNUSEDPIN Pullnone [current_design]", + ]) self.clock_domains.cd_jtag = ClockDomain(reset_less=True) spi = platform.request("spiflash") clk = Signal() @@ -89,184 +101,105 @@ class Series7(Module): i_USRCCLKTS=0, i_USRDONEO=1, i_USRDONETS=1) -class XilinxBscanSpi(XilinxPlatform): +class XilinxBscanSpi(xilinx.XilinxPlatform): + packages = { + # (package-speedgrade, id): [cs_n, clk, mosi, miso, *pullups] + ("cp132", 1): ["M2", "N12", "N2", "N8"], + ("fg320", 1): ["U3", "U16", "T4", "N10"], + ("fg320", 2): ["V3", "U16", "T11", "V16"], + ("fg484", 1): ["Y4", "AA20", "AB14", "AB20"], + ("fgg484", 1): ["Y4", "AA20", "AB14", "AB20"], + ("fgg400", 1): ["Y2", "Y19", "W12", "W18"], + ("ftg256", 1): ["T2", "R14", "P10", "T14"], + ("ft256", 1): ["T2", "R14", "P10", "T14"], + ("fg400", 1): ["Y2", "Y19", "W12", "W18"], + ("cs484", 1): ["U7", "V17", "V13", "W17"], + ("qg144-2", 1): ["P38", "P70", "P64", "P65", "P62", "P61"], + ("cpg196-2", 1): ["P2", "N13", "P11", "N11", "N10", "P10"], + ("cpg236-1", 1): ["K19", None, "D18", "D19", "G18", "F18"], + ("csg484-2", 1): ["AB5", "W17", "AB17", "Y17", "V13", "W13"], + ("csg324-2", 1): ["V3", "R15", "T13", "R13", "T14", "V14"], + ("csg324-1", 1): ["L13", None, "K17", "K18", "L14", "M14"], + ("fbg484-1", 1): ["T19", None, "P22", "R22", "P21", "R21"], + ("fbg484-1", 2): ["L16", None, "H18", "H19", "G18", "F19"], + ("fbg676-1", 1): ["C23", None, "B24", "A25", "B22", "A22"], + ("ffg901-1", 1): ["V26", None, "R30", "T30", "R28", "T28"], + ("ffg1156-1", 1): ["V30", None, "AA33", "AA34", "Y33", "Y34"], + ("ffg1157-1", 1): ["AL33", None, "AN33", "AN34", "AK34", "AL34"], + ("ffg1158-1", 1): ["C24", None, "A23", "A24", "B26", "A26"], + ("ffg1926-1", 1): ["AK33", None, "AN34", "AN35", "AJ34", "AK34"], + ("fhg1761-1", 1): ["AL36", None, "AM36", "AN36", "AJ36", "AJ37"], + ("flg1155-1", 1): ["AL28", None, "AE28", "AF28", "AJ29", "AJ30"], + ("flg1932-1", 1): ["V32", None, "T33", "R33", "U31", "T31"], + ("flg1926-1", 1): ["AK33", None, "AN34", "AN35", "AJ34", "AK34"], + } + pinouts = { # bitstreams are named by die, package does not matter, speed grade # should not matter. - # cs_n, clk, mosi, miso, *pullups - "xc3s100e": ("cp132", - ["M2", "N12", "N2", "N8"], - "LVCMOS33", Spartan3), - "xc3s1200e": ("fg320", - ["U3", "U16", "T4", "N10"], - "LVCMOS33", Spartan3), - "xc3s1400a": ("fg484", - ["Y4", "AA20", "AB14", "AB20"], - "LVCMOS33", Spartan3A), - "xc3s1400an": ("fgg484", - ["Y4", "AA20", "AB14", "AB20"], - "LVCMOS33", Spartan3A), - "xc3s1600e": ("fg320", - ["U3", "U16", "T4", "N10"], - "LVCMOS33", Spartan3), - "xc3s200a": ("fg320", - ["V3", "U16", "T11", "V16"], - "LVCMOS33", Spartan3A), - "xc3s200an": ("ftg256", - ["T2", "R14", "P10", "T14"], - "LVCMOS33", Spartan3A), - "xc3s250e": ("cp132", - ["M2", "N12", "N2", "N8"], - "LVCMOS33", Spartan3), - "xc3s400a": ("fg320", - ["V3", "U16", "T11", "V16"], - "LVCMOS33", Spartan3A), - "xc3s400an": ("fgg400", - ["Y2", "Y19", "W12", "W18"], - "LVCMOS33", Spartan3A), - "xc3s500e": ("cp132", - ["M2", "N12", "N2", "N8"], - "LVCMOS33", Spartan3), - "xc3s50a": ("ft256", - ["T2", "R14", "P10", "T14"], - "LVCMOS33", Spartan3A), - "xc3s50an": ("ftg256", - ["T2", "R14", "P10", "T14"], - "LVCMOS33", Spartan3A), - "xc3s700a": ("fg400", - ["Y2", "Y19", "W12", "W18"], - "LVCMOS33", Spartan3A), - "xc3s700an": ("fgg484", - ["Y4", "AA20", "AB14", "AB20"], - "LVCMOS33", Spartan3A), - "xc3sd1800a": ("cs484", - ["U7", "V17", "V13", "W17"], - "LVCMOS33", Spartan3A), - "xc3sd3400a": ("cs484", - ["U7", "V17", "V13", "W17"], - "LVCMOS33", Spartan3A), - - "xc6slx100": ("csg484-2", - ["AB5", "W17", "AB17", "Y17", "V13", "W13"], - "LVCMOS33", Spartan6), - "xc6slx100t": ("csg484-2", - ["AB5", "W17", "AB17", "Y17", "V13", "W13"], - "LVCMOS33", Spartan6), - "xc6slx150": ("csg484-2", - ["AB5", "W17", "AB17", "Y17", "V13", "W13"], - "LVCMOS33", Spartan6), - "xc6slx150t": ("csg484-2", - ["AB5", "W17", "AB17", "Y17", "V13", "W13"], - "LVCMOS33", Spartan6), - "xc6slx16": ("cpg196-2", - ["P2", "N13", "P11", "N11", "N10", "P10"], - "LVCMOS33", Spartan6), - "xc6slx25": ("csg324-2", - ["V3", "R15", "T13", "R13", "T14", "V14"], - "LVCMOS33", Spartan6), - "xc6slx25t": ("csg324-2", - ["V3", "R15", "T13", "R13", "T14", "V14"], - "LVCMOS33", Spartan6), - "xc6slx45": ("csg324-2", - ["V3", "R15", "T13", "R13", "T14", "V14"], - "LVCMOS33", Spartan6), - "xc6slx45t": ("csg324-2", - ["V3", "R15", "T13", "R13", "T14", "V14"], - "LVCMOS33", Spartan6), - "xc6slx4": ("cpg196-2", - ["P2", "N13", "P11", "N11", "N10", "P10"], - "LVCMOS33", Spartan6), - "xc6slx4t": ("qg144-2", - ["P38", "P70", "P64", "P65", "P62", "P61"], - "LVCMOS33", Spartan6), - "xc6slx75": ("csg484-2", - ["AB5", "W17", "AB17", "Y17", "V13", "W13"], - "LVCMOS33", Spartan6), - "xc6slx75t": ("csg484-2", - ["AB5", "W17", "AB17", "Y17", "V13", "W13"], - "LVCMOS33", Spartan6), - "xc6slx9": ("cpg196-2", - ["P2", "N13", "P11", "N11", "N10", "P10"], - "LVCMOS33", Spartan6), - "xc6slx9t": ("qg144-2", - ["P38", "P70", "P64", "P65", "P62", "P61"], - "LVCMOS33", Spartan6), - - "xc7a100t": ("csg324-1", - ["L13", None, "K17", "K18", "L14", "M14"], - "LVCMOS25", Series7), - "xc7a15t": ("cpg236-1", - ["K19", None, "D18", "D19", "G18", "F18"], - "LVCMOS25", Series7), - "xc7a200t": ("fbg484-1", - ["T19", None, "P22", "R22", "P21", "R21"], - "LVCMOS25", Series7), - "xc7a35t": ("cpg236-1", - ["K19", None, "D18", "D19", "G18", "F18"], - "LVCMOS25", Series7), - "xc7a50t": ("cpg236-1", - ["K19", None, "D18", "D19", "G18", "F18"], - "LVCMOS25", Series7), - "xc7a75t": ("csg324-1", - ["L13", None, "K17", "K18", "L14", "M14"], - "LVCMOS25", Series7), - "xc7k160t": ("fbg484-1", - ["L16", None, "H18", "H19", "G18", "F19"], - "LVCMOS25", Series7), - "xc7k325t": ("fbg676-1", - ["C23", None, "B24", "A25", "B22", "A22"], - "LVCMOS25", Series7), - "xc7k355t": ("ffg901-1", - ["V26", None, "R30", "T30", "R28", "T28"], - "LVCMOS25", Series7), - "xc7k410t": ("fbg676-1", - ["C23", None, "B24", "A25", "B22", "A22"], - "LVCMOS25", Series7), - "xc7k420t": ("ffg1156-1", - ["V30", None, "AA33", "AA34", "Y33", "Y34"], - "LVCMOS25", Series7), - "xc7k480t": ("ffg1156-1", - ["V30", None, "AA33", "AA34", "Y33", "Y34"], - "LVCMOS25", Series7), - "xc7k70t": ("fbg484-1", - ["L16", None, "H18", "H19", "G18", "F19"], - "LVCMOS25", Series7), - "xc7v2000t": ("fhg1761-1", - ["AL36", None, "AM36", "AN36", "AJ36", "AJ37"], - "LVCMOS18", Series7), - "xc7v585t": ("ffg1157-1", - ["AL33", None, "AN33", "AN34", "AK34", "AL34"], - "LVCMOS18", Series7), - "xc7vh580t": ("flg1155-1", - ["AL28", None, "AE28", "AF28", "AJ29", "AJ30"], - "LVCMOS18", Series7), - "xc7vh870t": ("flg1932-1", - ["V32", None, "T33", "R33", "U31", "T31"], - "LVCMOS18", Series7), - "xc7vx1140t": ("flg1926-1", - ["AK33", None, "AN34", "AN35", "AJ34", "AK34"], - "LVCMOS18", Series7), - "xc7vx330t": ("ffg1157-1", - ["AL33", None, "AN33", "AN34", "AK34", "AL34"], - "LVCMOS18", Series7), - "xc7vx415t": ("ffg1157-1", - ["AL33", None, "AN33", "AN34", "AK34", "AL34"], - "LVCMOS18", Series7), - "xc7vx485t": ("ffg1157-1", - ["AL33", None, "AN33", "AN34", "AK34", "AL34"], - "LVCMOS18", Series7), - "xc7vx550t": ("ffg1158-1", - ["C24", None, "A23", "A24", "B26", "A26"], - "LVCMOS18", Series7), - "xc7vx690t": ("ffg1157-1", - ["AL33", None, "AN33", "AN34", "AK34", "AL34"], - "LVCMOS18", Series7), - "xc7vx980t": ("ffg1926-1", - ["AK33", None, "AN34", "AN35", "AJ34", "AK34"], - "LVCMOS18", Series7), + # + # chip: (package, id, standard, class) + "xc3s100e": ("cp132", 1, "LVCMOS33", Spartan3), + "xc3s1200e": ("fg320", 1, "LVCMOS33", Spartan3), + "xc3s1400a": ("fg484", 1, "LVCMOS33", Spartan3A), + "xc3s1400an": ("fgg484", 1, "LVCMOS33", Spartan3A), + "xc3s1600e": ("fg320", 1, "LVCMOS33", Spartan3), + "xc3s200a": ("fg320", 2, "LVCMOS33", Spartan3A), + "xc3s200an": ("ftg256", 1, "LVCMOS33", Spartan3A), + "xc3s250e": ("cp132", 1, "LVCMOS33", Spartan3), + "xc3s400a": ("fg320", 2, "LVCMOS33", Spartan3A), + "xc3s400an": ("fgg400", 1, "LVCMOS33", Spartan3A), + "xc3s500e": ("cp132", 1, "LVCMOS33", Spartan3), + "xc3s50a": ("ft256", 1, "LVCMOS33", Spartan3A), + "xc3s50an": ("ftg256", 1, "LVCMOS33", Spartan3A), + "xc3s700a": ("fg400", 1, "LVCMOS33", Spartan3A), + "xc3s700an": ("fgg484", 1, "LVCMOS33", Spartan3A), + "xc3sd1800a": ("cs484", 1, "LVCMOS33", Spartan3A), + "xc3sd3400a": ("cs484", 1, "LVCMOS33", Spartan3A), + + "xc6slx100": ("csg484-2", 1, "LVCMOS33", Spartan6), + "xc6slx100t": ("csg484-2", 1, "LVCMOS33", Spartan6), + "xc6slx150": ("csg484-2", 1, "LVCMOS33", Spartan6), + "xc6slx150t": ("csg484-2", 1, "LVCMOS33", Spartan6), + "xc6slx16": ("cpg196-2", 1, "LVCMOS33", Spartan6), + "xc6slx25": ("csg324-2", 1, "LVCMOS33", Spartan6), + "xc6slx25t": ("csg324-2", 1, "LVCMOS33", Spartan6), + "xc6slx45": ("csg324-2", 1, "LVCMOS33", Spartan6), + "xc6slx45t": ("csg324-2", 1, "LVCMOS33", Spartan6), + "xc6slx4": ("cpg196-2", 1, "LVCMOS33", Spartan6), + "xc6slx4t": ("qg144-2", 1, "LVCMOS33", Spartan6), + "xc6slx75": ("csg484-2", 1, "LVCMOS33", Spartan6), + "xc6slx75t": ("csg484-2", 1, "LVCMOS33", Spartan6), + "xc6slx9": ("cpg196-2", 1, "LVCMOS33", Spartan6), + "xc6slx9t": ("qg144-2", 1, "LVCMOS33", Spartan6), + + "xc7a100t": ("csg324-1", 1, "LVCMOS25", Series7), + "xc7a15t": ("cpg236-1", 1, "LVCMOS25", Series7), + "xc7a200t": ("fbg484-1", 1, "LVCMOS25", Series7), + "xc7a35t": ("cpg236-1", 1, "LVCMOS25", Series7), + "xc7a50t": ("cpg236-1", 1, "LVCMOS25", Series7), + "xc7a75t": ("csg324-1", 1, "LVCMOS25", Series7), + "xc7k160t": ("fbg484-1", 2, "LVCMOS25", Series7), + "xc7k325t": ("fbg676-1", 1, "LVCMOS25", Series7), + "xc7k355t": ("ffg901-1", 1, "LVCMOS25", Series7), + "xc7k410t": ("fbg676-1", 1, "LVCMOS25", Series7), + "xc7k420t": ("ffg1156-1", 1, "LVCMOS25", Series7), + "xc7k480t": ("ffg1156-1", 1, "LVCMOS25", Series7), + "xc7k70t": ("fbg484-1", 2, "LVCMOS25", Series7), + "xc7v2000t": ("fhg1761-1", 1, "LVCMOS18", Series7), + "xc7v585t": ("ffg1157-1", 1, "LVCMOS18", Series7), + "xc7vh580t": ("flg1155-1", 1, "LVCMOS18", Series7), + "xc7vh870t": ("flg1932-1", 1, "LVCMOS18", Series7), + "xc7vx1140t": ("flg1926-1", 1, "LVCMOS18", Series7), + "xc7vx330t": ("ffg1157-1", 1, "LVCMOS18", Series7), + "xc7vx415t": ("ffg1157-1", 1, "LVCMOS18", Series7), + "xc7vx485t": ("ffg1157-1", 1, "LVCMOS18", Series7), + "xc7vx550t": ("ffg1158-1", 1, "LVCMOS18", Series7), + "xc7vx690t": ("ffg1157-1", 1, "LVCMOS18", Series7), + "xc7vx980t": ("ffg1926-1", 1, "LVCMOS18", Series7), } - def __init__(self, device, pins, std): + def __init__(self, device, pins, std, toolchain="ise"): cs_n, clk, mosi, miso = pins[:4] io = ["spiflash", 0, Subsignal("cs_n", Pins(cs_n)), @@ -278,26 +211,21 @@ class XilinxBscanSpi(XilinxPlatform): io.append(Subsignal("clk", Pins(clk))) for i, p in enumerate(pins[4:]): io.append(Subsignal("pullup{}".format(i), Pins(p), Misc("PULLUP"))) - - XilinxPlatform.__init__(self, device, [io]) - if isinstance(self.toolchain, XilinxVivadoToolchain): - self.toolchain.bitstream_commands.append( - "set_property BITSTREAM.GENERAL.COMPRESS True [current_design]" - ) - elif isinstance(self.toolchain, XilinxISEToolchain): - self.toolchain.bitgen_opt += " -g compress" + xilinx.XilinxPlatform.__init__(self, device, [io], toolchain=toolchain) @classmethod def make(cls, device, errors=False): - pkg, pins, std, Top = cls.pinouts[device] - platform = cls("{}-{}".format(device, pkg), pins, std) + pkg, id, std, Top = cls.pinouts[device] + pins = cls.packages[(pkg, id)] + platform = cls("{}-{}".format(device, pkg), pins, std, Top.toolchain) top = Top(platform) name = "bscan_spi_{}".format(device) dir = "build_{}".format(device) try: platform.build(top, build_name=name, build_dir=dir) except Exception as e: - print("ERROR: build failed for {}: {}".format(device, e)) + print(("ERROR: xilinx_bscan_spi build failed " + "for {}: {}").format(device, e)) if errors: raise -- cgit v1.1 From 9292899bf407b8f9add0380031067c1dac472b41 Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Tue, 4 Oct 2016 13:26:10 +0200 Subject: stm32f2x: Increase options write timeout Large flash parts time out when unlocking. Mass erase time is specified as 32 seconds worst case for some parts. Automatic mass erase is probably not using x8 parallelism, though, but a too large timeout shouldn't hurt. Also, use the new define instead of hardcoded timeout when mass erasing. Change-Id: Ib5af60d52ed7d53277bfe7176c4c44f79d3a26bc Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3738 Tested-by: jenkins Reviewed-by: Spencer Oliver --- src/flash/nor/stm32f2x.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/flash/nor/stm32f2x.c b/src/flash/nor/stm32f2x.c index 1acab82..4d75095 100644 --- a/src/flash/nor/stm32f2x.c +++ b/src/flash/nor/stm32f2x.c @@ -110,6 +110,9 @@ #define FLASH_ERASE_TIMEOUT 10000 #define FLASH_WRITE_TIMEOUT 5 +/* Mass erase time can be as high as 32 s in x8 mode. */ +#define FLASH_MASS_ERASE_TIMEOUT 33000 + #define STM32_FLASH_BASE 0x40023c00 #define STM32_FLASH_ACR 0x40023c00 #define STM32_FLASH_KEYR 0x40023c04 @@ -399,8 +402,8 @@ static int stm32x_write_options(struct flash_bank *bank) if (retval != ERROR_OK) return retval; - /* wait for completion */ - retval = stm32x_wait_status_busy(bank, FLASH_ERASE_TIMEOUT); + /* wait for completion, this might trigger a security erase and take a while */ + retval = stm32x_wait_status_busy(bank, FLASH_MASS_ERASE_TIMEOUT); if (retval != ERROR_OK) return retval; @@ -1257,7 +1260,7 @@ static int stm32x_mass_erase(struct flash_bank *bank) if (retval != ERROR_OK) return retval; - retval = stm32x_wait_status_busy(bank, 30000); + retval = stm32x_wait_status_busy(bank, FLASH_MASS_ERASE_TIMEOUT); if (retval != ERROR_OK) return retval; -- cgit v1.1 From 640894e7316b4e45ee4533c611a3d4c4bee6177a Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 17 Sep 2016 17:36:20 +0200 Subject: cortex_m: fix autoincrement range of Cortex-M7 Cortex-M7 has autoincrement range only 1024 bytes, surprisingly smaller than M3, M4. Change-Id: I35ff1f0e093aac4af79f98eb3b8058d4295942d1 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3737 Tested-by: jenkins Reviewed-by: Spencer Oliver --- src/target/cortex_m.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index a6a9309..4566e2e 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1976,10 +1976,14 @@ int cortex_m_examine(struct target *target) armv7m->arm.core_cache->num_regs = ARMV7M_NUM_CORE_REGS_NOFP; } - if ((i == 3 || i == 4 || i == 7) && !armv7m->stlink) { - /* Cortex-M3/M4/M7 have at least 4096 bytes autoincrement range, - * s. ARM IHI 0031C: MEM-AP 7.2.2 */ - armv7m->debug_ap->tar_autoincr_block = (1 << 12); + if (!armv7m->stlink) { + if (i == 3 || i == 4) + /* Cortex-M3/M4 have 4096 bytes autoincrement range, + * s. ARM IHI 0031C: MEM-AP 7.2.2 */ + armv7m->debug_ap->tar_autoincr_block = (1 << 12); + else if (i == 7) + /* Cortex-M7 has only 1024 bytes autoincrement range */ + armv7m->debug_ap->tar_autoincr_block = (1 << 10); } /* Configure trace modules */ -- cgit v1.1 From 3c8832fe6eb32489ed8208229a831abb73cf4b1e Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 18 Aug 2016 12:02:08 +0200 Subject: helper/log: Add log_vprintf_lf() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add log_vprintf_lf() to enable the possibility to output log messages with a variable argument list. Change-Id: I7fd6e93db63a7d98f662df2881a42e4d923c3848 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3709 Tested-by: jenkins Reviewed-by: Andreas Färber Reviewed-by: Paul Fertser --- src/helper/log.c | 39 +++++++++++++++++++++++++-------------- src/helper/log.h | 2 ++ 2 files changed, 27 insertions(+), 14 deletions(-) diff --git a/src/helper/log.c b/src/helper/log.c index 79cbd8e..e7af803 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -191,6 +191,30 @@ void log_printf(enum log_levels level, va_end(ap); } +void log_vprintf_lf(enum log_levels level, const char *file, unsigned line, + const char *function, const char *format, va_list args) +{ + char *tmp; + + count++; + + if (level > debug_level) + return; + + tmp = alloc_vprintf(format, args); + + if (!tmp) + return; + + /* + * Note: alloc_vprintf() guarantees that the buffer is at least one + * character longer. + */ + strcat(tmp, "\n"); + log_puts(level, file, line, function, tmp); + free(tmp); +} + void log_printf_lf(enum log_levels level, const char *file, unsigned line, @@ -198,23 +222,10 @@ void log_printf_lf(enum log_levels level, const char *format, ...) { - char *string; va_list ap; - count++; - if (level > debug_level) - return; - va_start(ap, format); - - string = alloc_vprintf(format, ap); - if (string != NULL) { - strcat(string, "\n"); /* alloc_vprintf guaranteed the buffer to be at least one - *char longer */ - log_puts(level, file, line, function, string); - free(string); - } - + log_vprintf_lf(level, file, line, function, format, ap); va_end(ap); } diff --git a/src/helper/log.h b/src/helper/log.h index eb222cb..6b93816 100644 --- a/src/helper/log.h +++ b/src/helper/log.h @@ -60,6 +60,8 @@ enum log_levels { void log_printf(enum log_levels level, const char *file, unsigned line, const char *function, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6))); +void log_vprintf_lf(enum log_levels level, const char *file, unsigned line, + const char *function, const char *format, va_list args); void log_printf_lf(enum log_levels level, const char *file, unsigned line, const char *function, const char *format, ...) __attribute__ ((format (PRINTF_ATTRIBUTE_FORMAT, 5, 6))); -- cgit v1.1 From 8515da60a80880db1f4c632a1ecfef383f6136d8 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 16 Aug 2016 18:36:27 +0200 Subject: jlink: Adjust log verbosity of libjaylink Currently, the log verbosity of libjaylink is not accessible from the user interface. Therefore, changing the log verbosity of libjaylink is only possible from within the J-Link driver source code which is not acceptable for end users. Output the libjaylink log messages through the logging module of OpenOCD rather than directly to stderr. Change-Id: I6bf7bf8f4c8a12fb9e955eeced68224545fa0b5c Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3701 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/jtag/drivers/jlink.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 3009058..441e3ef 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -502,6 +502,35 @@ static bool adjust_swd_buffer_size(void) return true; } +static int jaylink_log_handler(const struct jaylink_context *ctx, int level, + const char *format, va_list args, void *user_data) +{ + enum log_levels tmp; + + switch (level) { + case JAYLINK_LOG_LEVEL_ERROR: + tmp = LOG_LVL_ERROR; + break; + case JAYLINK_LOG_LEVEL_WARNING: + tmp = LOG_LVL_WARNING; + break; + /* + * Forward info messages to the debug output because they are more verbose + * than info messages of OpenOCD. + */ + case JAYLINK_LOG_LEVEL_INFO: + case JAYLINK_LOG_LEVEL_DEBUG: + tmp = LOG_LVL_DEBUG; + break; + default: + tmp = LOG_LVL_WARNING; + } + + log_vprintf_lf(tmp, __FILE__, __LINE__, __func__, format, args); + + return 0; +} + static int jlink_init(void) { int ret; @@ -523,6 +552,15 @@ static int jlink_init(void) return ERROR_JTAG_INIT_FAILED; } + ret = jaylink_log_set_callback(jayctx, &jaylink_log_handler, NULL); + + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_log_set_callback() failed: %s.", + jaylink_strerror_name(ret)); + jaylink_exit(jayctx); + return ERROR_JTAG_INIT_FAILED; + } + ret = jaylink_get_device_list(jayctx, &devs); if (ret < 0) { -- cgit v1.1 From f109a93075b746e2fc94e5fa1fbdaddb61d6326b Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 15 May 2016 13:25:46 +0200 Subject: libjaylink: Update for API changes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update to latest libjaylink version and incorporate API changes. The major change in libjaylink is a rework of the device discovery. Please test device discovery extensively, especially with multiple devices connected. All other changes in libjaylink are of minor importance for OpenOCD. Change-Id: I9a50e83f59557505ce29809c7762c5df1cec10eb Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3735 Reviewed-by: Andreas Färber Reviewed-by: Steven Stallion Tested-by: jenkins Reviewed-by: Paul Fertser --- src/jtag/drivers/jlink.c | 57 ++++++++++++++++++++++++++++++--------------- src/jtag/drivers/libjaylink | 2 +- 2 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 441e3ef..95c6d8d 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -314,12 +314,11 @@ static int jlink_execute_queue(void) static int jlink_speed(int speed) { int ret; - uint32_t freq; - uint16_t divider; + struct jaylink_speed tmp; int max_speed; if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_SPEEDS)) { - ret = jaylink_get_speeds(devh, &freq, ÷r); + ret = jaylink_get_speeds(devh, &tmp); if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_get_speeds() failed: %s.", @@ -327,8 +326,8 @@ static int jlink_speed(int speed) return ERROR_JTAG_DEVICE_ERROR; } - freq = freq / 1000; - max_speed = freq / divider; + tmp.freq /= 1000; + max_speed = tmp.freq / tmp.div; } else { max_speed = JLINK_MAX_SPEED; } @@ -433,15 +432,16 @@ static int select_interface(void) static int jlink_register(void) { int ret; - int i; + size_t i; bool handle_found; + size_t count; if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER)) return ERROR_OK; - ret = jaylink_register(devh, &conn, connlist, NULL, NULL); + ret = jaylink_register(devh, &conn, connlist, &count); - if (ret < 0) { + if (ret != JAYLINK_OK) { LOG_ERROR("jaylink_register() failed: %s.", jaylink_strerror_name(ret)); return ERROR_FAIL; @@ -449,7 +449,7 @@ static int jlink_register(void) handle_found = false; - for (i = 0; i < ret; i++) { + for (i = 0; i < count; i++) { if (connlist[i].handle == conn.handle) { handle_found = true; break; @@ -502,8 +502,9 @@ static bool adjust_swd_buffer_size(void) return true; } -static int jaylink_log_handler(const struct jaylink_context *ctx, int level, - const char *format, va_list args, void *user_data) +static int jaylink_log_handler(const struct jaylink_context *ctx, + enum jaylink_log_level level, const char *format, va_list args, + void *user_data) { enum log_levels tmp; @@ -561,10 +562,19 @@ static int jlink_init(void) return ERROR_JTAG_INIT_FAILED; } - ret = jaylink_get_device_list(jayctx, &devs); + ret = jaylink_discovery_scan(jayctx, 0); - if (ret < 0) { - LOG_ERROR("jaylink_get_device_list() failed: %s.", + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_discovery_scan() failed: %s.", + jaylink_strerror_name(ret)); + jaylink_exit(jayctx); + return ERROR_JTAG_INIT_FAILED; + } + + ret = jaylink_get_devices(jayctx, &devs, NULL); + + if (ret != JAYLINK_OK) { + LOG_ERROR("jaylink_get_devices() failed: %s.", jaylink_strerror_name(ret)); jaylink_exit(jayctx); return ERROR_JTAG_INIT_FAILED; @@ -614,7 +624,7 @@ static int jlink_init(void) LOG_ERROR("Failed to open device: %s.", jaylink_strerror_name(ret)); } - jaylink_free_device_list(devs, 1); + jaylink_free_devices(devs, true); if (!found_device) { LOG_ERROR("No J-Link device found."); @@ -723,7 +733,7 @@ static int jlink_init(void) conn.handle = 0; conn.pid = 0; - conn.hid = 0; + strcpy(conn.hid, "0.0.0.0"); conn.iid = 0; conn.cid = 0; @@ -767,6 +777,7 @@ static int jlink_init(void) static int jlink_quit(void) { int ret; + size_t count; if (trace_enabled) { ret = jaylink_swo_stop(devh); @@ -777,9 +788,9 @@ static int jlink_quit(void) } if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_REGISTER)) { - ret = jaylink_unregister(devh, &conn, connlist, NULL, NULL); + ret = jaylink_unregister(devh, &conn, connlist, &count); - if (ret < 0) + if (ret != JAYLINK_OK) LOG_ERROR("jaylink_unregister() failed: %s.", jaylink_strerror_name(ret)); } @@ -916,14 +927,22 @@ COMMAND_HANDLER(jlink_usb_command) COMMAND_HANDLER(jlink_serial_command) { + int ret; + if (CMD_ARGC != 1) { command_print(CMD_CTX, "Need exactly one argument for jlink serial."); return ERROR_COMMAND_SYNTAX_ERROR; } - if (sscanf(CMD_ARGV[0], "%" SCNd32, &serial_number) != 1) { + ret = jaylink_parse_serial_number(CMD_ARGV[0], &serial_number); + + if (ret == JAYLINK_ERR) { command_print(CMD_CTX, "Invalid serial number: %s.", CMD_ARGV[0]); return ERROR_FAIL; + } else if (ret != JAYLINK_OK) { + command_print(CMD_CTX, "jaylink_parse_serial_number() failed: %s.", + jaylink_strerror_name(ret)); + return ERROR_FAIL; } use_serial_number = true; diff --git a/src/jtag/drivers/libjaylink b/src/jtag/drivers/libjaylink index d57dee6..58a409d 160000 --- a/src/jtag/drivers/libjaylink +++ b/src/jtag/drivers/libjaylink @@ -1 +1 @@ -Subproject commit d57dee67bc756291b7d8b51d350d1c6213e514f0 +Subproject commit 58a409dcbc83b63417d5dc2b4c3cb0bd3e0e53fd -- cgit v1.1 From ca6ccad439f64870543c7955190a28a311ec341f Mon Sep 17 00:00:00 2001 From: Sandeep Mistry Date: Wed, 23 Dec 2015 12:10:32 -0500 Subject: gdb server: Add back support to disable the gdb server via the gdb_port config As per the documentation, used "disabled" as the value to disable, as this is the same value to disable the telnet and tcl server. Change-Id: Idc4a8580098ec1107dcc6e1f59e817ecdebc38ac Signed-off-by: Sandeep Mistry Reviewed-on: http://openocd.zylin.com/3175 Tested-by: jenkins Reviewed-by: Cristian Maglie Reviewed-by: Spencer Oliver --- doc/openocd.texi | 2 +- src/server/gdb_server.c | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 8146654..9558704 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2109,7 +2109,7 @@ communicate via pipes(stdin/out or named pipes). The name the normal use cases. No arguments reports GDB port. "pipe" means listen to stdin -output to stdout, an integer is base port number, "disable" +output to stdout, an integer is base port number, "disabled" disables the gdb server. When using "pipe", also use log_output to redirect the log diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 4a18198..d09a8be 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -2921,6 +2921,11 @@ static int gdb_target_start(struct target *target, const char *port) static int gdb_target_add_one(struct target *target) { + if (strcmp(gdb_port, "disabled") == 0) { + LOG_INFO("gdb port disabled"); + return ERROR_OK; + } + /* one gdb instance per smp list */ if ((target->smp) && (target->gdb_service)) return ERROR_OK; @@ -3114,7 +3119,7 @@ static const struct command_registration gdb_command_handlers[] = { "server listens for the next port number after the " "base port number specified. " "No arguments reports GDB port. \"pipe\" means listen to stdin " - "output to stdout, an integer is base port number, \"disable\" disables " + "output to stdout, an integer is base port number, \"disabled\" disables " "port. Any other string is are interpreted as named pipe to listen to. " "Output pipe is the same name as input pipe, but with 'o' appended.", .usage = "[port_num]", -- cgit v1.1 From 537c019ced7dd91ad1fd9ac58908d94f24650357 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Tue, 28 Jun 2016 12:12:34 +0300 Subject: tcl/board: add configuration for Novena's integrated FPGA Change-Id: Iecd57c0ef59cfde98de36464a73436f57b0835e2 Signed-off-by: Sean Cross Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3532 Tested-by: jenkins Reviewed-by: Spencer Oliver --- tcl/board/novena-internal-fpga.cfg | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 tcl/board/novena-internal-fpga.cfg diff --git a/tcl/board/novena-internal-fpga.cfg b/tcl/board/novena-internal-fpga.cfg new file mode 100644 index 0000000..87495e3 --- /dev/null +++ b/tcl/board/novena-internal-fpga.cfg @@ -0,0 +1,25 @@ +# +# Novena open hardware and F/OSS-friendly computing platform +# +# Design documentation: +# http://www.kosagi.com/w/index.php?title=Novena_PVT_Design_Source +# +# +-------------+--------------+------+-------+---------+ +# | Pad name | Schematic | GPIO | sysfs | JTAG | +# +-------------+--------------+------+-------+---------+ +# | DISP0_DAT13 | FPGA_RESET_N | 5-07 | 135 | RESET_N | +# | DISP0_DAT14 | FPGA_TCK | 5-08 | 136 | TCK | +# | DISP0_DAT15 | FPGA_TDI | 5-09 | 137 | TDI | +# | DISP0_DAT16 | FPGA_TDO | 5-10 | 138 | TDO | +# | DISP0_DAT17 | FPGA_TMS | 5-11 | 139 | TMS | +# +-------------+--------------+------+-------+---------+ + +interface sysfsgpio + +transport select jtag + +# TCK TMS TDI TDO +sysfsgpio_jtag_nums 136 139 137 138 + +source [find cpld/xilinx-xc6s.cfg] + -- cgit v1.1 From 9d98f8b7a7d0a4c1d50c1d5d9df62dc2d0ede26c Mon Sep 17 00:00:00 2001 From: Vivien Didelot Date: Wed, 21 Sep 2016 11:16:47 -0400 Subject: tcl/board: add Linksys WAG200G config The Linksys WAG200G router has a TI AR7 SoC and a 4MB Flash layout similar to the Netgear DG834v3 router [1]. Below is an example of a successful flash recovery, using a TUMPA, connected to the MIPS EJTAG 2.6 header (JP102) of the router. WAG200G [2] TUMPA [3] Desc Pin Pin Desc ------------------------ nTRST 1 3 nTRST TDI 3 5 TDI TDO 5 13 TDO TMS 7 7 TMS TCK 9 9 TCK nSRST 11 15 RST GND 2 4 GND Note that nSRST is optional to halt the CPU, but is required to probe the flash. For instance, recover the kernel with: $ sudo ./src/openocd -s tcl \ -f interface/ftdi/tumpa.cfg \ -f tools/firmware-recovery.tcl \ -c 'board linksys-wag200g; reset_config srst_only; flash_part kernel /path/to/kernel.bin; shutdown' [1] https://wiki.openwrt.org/toh/linksys/wag200g [2] https://www.linux-mips.org/wiki/JTAG#JTAG_headers [3] http://www.tiaowiki.com/w/TIAO_USB_Multi_Protocol_Adapter_User's_Manual#20_PIN_JTAG_Connector Change-Id: I952ba9f706e2e4f8f95ca03a5fa58f391ca030b6 Signed-off-by: Vivien Didelot Reviewed-on: http://openocd.zylin.com/3776 Tested-by: jenkins Reviewed-by: Spencer Oliver --- tcl/board/linksys-wag200g.cfg | 27 +++++++++++++++++++++++++++ tcl/tools/firmware-recovery.tcl | 1 + 2 files changed, 28 insertions(+) create mode 100644 tcl/board/linksys-wag200g.cfg diff --git a/tcl/board/linksys-wag200g.cfg b/tcl/board/linksys-wag200g.cfg new file mode 100644 index 0000000..aa4887f --- /dev/null +++ b/tcl/board/linksys-wag200g.cfg @@ -0,0 +1,27 @@ +# +# Linksys WAG200G Router +# +# The stock firmware Flash layout is organized as follow: +# +# Start End Device +# 0x90000000 0x90020000 /dev/mtdblock/2 +# 0x90020000 0x900d0000 /dev/mtdblock/1 +# 0x900d0000 0x903a0000 /dev/mtdblock/0 +# 0x903a0000 0x903e0000 /dev/mtdblock/5 +# 0x903e0000 0x903f0000 /dev/mtdblock/3 +# 0x903f0000 0x90400000 /dev/mtdblock/4 + +set partition_list { + adam2 { "Adam2 bootloader" 0x90000000 0x00020000 } + kernel { "Kernel" 0x90020000 0x000b0000 } + rootfs { "Root FS" 0x900d0000 0x002d0000 } + lang { "Minix language part" 0x903a0000 0x00040000 } + config { "Firmware config" 0x903e0000 0x00010000 } + adam2env { "Adam2 environment" 0x903f0000 0x00010000 } +} + +source [find target/ti-ar7.cfg] + +# External 4MB MXIC 29LV320MBTC Flash (Manufacturer/Device: 0x00c2 0x227e) +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME cfi 0x90000000 0x00400000 2 2 $_TARGETNAME diff --git a/tcl/tools/firmware-recovery.tcl b/tcl/tools/firmware-recovery.tcl index 6e23540..8e017ce 100644 --- a/tcl/tools/firmware-recovery.tcl +++ b/tcl/tools/firmware-recovery.tcl @@ -4,6 +4,7 @@ echo "Use -c firmware_help to get help\n" set known_boards { "asus-rt-n16 ASUS RT-N16" "asus-rt-n66u ASUS RT-N66U" + "linksys-wag200g Linksys WAG200G" "linksys-wrt54gl Linksys WRT54GL v1.1" "netgear-dg834v3 Netgear DG834G v3" "tp-link_tl-mr3020 TP-LINK TL-MR3020" -- cgit v1.1 From 5fa3bfa074ccc826c51151ac5c306987c99bf2b2 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sun, 21 Aug 2016 15:27:23 +0200 Subject: flash Kinetis: fix mdm check_security regression in JTAG mode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 6d5b4d709cb05e8daf0350ac507b928da95d0abb causes failed assert when JTAG transport is selected: src/target/arm_adi_v5.h:346: dap_queue_ap_read: Assertion `ap->dap->ops != ((void *)0)' failed. As check_security runs early in examine-start event, dap->ops must be checked. Change-Id: Ibd8312a3c668fbce834eed9790eabeed794117aa Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3712 Tested-by: jenkins Reviewed-by: Andreas Färber Reviewed-by: Spencer Oliver --- src/flash/nor/kinetis.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index d02918b..0b738e2 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -609,6 +609,9 @@ COMMAND_HANDLER(kinetis_check_flash_security_status) return ERROR_OK; } + if (!dap->ops) + return ERROR_OK; /* too early to check, in JTAG mode ops may not be initialised */ + uint32_t val; int retval; @@ -623,7 +626,7 @@ COMMAND_HANDLER(kinetis_check_flash_security_status) } if (val == 0) - return ERROR_OK; + return ERROR_OK; /* dap not yet initialised */ bool found = false; for (size_t i = 0; i < ARRAY_SIZE(kinetis_known_mdm_ids); i++) { -- cgit v1.1 From 67c9a5561ec7355a4a91d6ea7b861bb2c1a83c03 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Thu, 29 Sep 2016 20:41:29 +0300 Subject: jtag: drivers: cmsis-dap: add TRST handling Even when TRST and SRST are not present in reset_config we still should set them appropriately (to 1) as we can't tristate them anyhow. Change-Id: Iec5bcf09340136f5e6ccfb05fa2697c53fa6609f Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3798 Tested-by: jenkins Reviewed-by: Matthias Welwarsky Reviewed-by: Tomas Vanek --- src/jtag/drivers/cmsis_dap_usb.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap_usb.c b/src/jtag/drivers/cmsis_dap_usb.c index a07064b..7791840 100644 --- a/src/jtag/drivers/cmsis_dap_usb.c +++ b/src/jtag/drivers/cmsis_dap_usb.c @@ -118,6 +118,13 @@ static bool swd_mode; * Bit 7: nRESET */ +#define SWJ_PIN_TCK (1<<0) +#define SWJ_PIN_TMS (1<<1) +#define SWJ_PIN_TDI (1<<2) +#define SWJ_PIN_TDO (1<<3) +#define SWJ_PIN_TRST (1<<5) +#define SWJ_PIN_SRST (1<<7) + /* CMSIS-DAP SWD Commands */ #define CMD_DAP_SWD_CONFIGURE 0x13 @@ -764,12 +771,12 @@ static int cmsis_dap_get_status(void) if (retval == ERROR_OK) { LOG_INFO("SWCLK/TCK = %d SWDIO/TMS = %d TDI = %d TDO = %d nTRST = %d nRESET = %d", - (d & (0x01 << 0)) ? 1 : 0, /* Bit 0: SWCLK/TCK */ - (d & (0x01 << 1)) ? 1 : 0, /* Bit 1: SWDIO/TMS */ - (d & (0x01 << 2)) ? 1 : 0, /* Bit 2: TDI */ - (d & (0x01 << 3)) ? 1 : 0, /* Bit 3: TDO */ - (d & (0x01 << 5)) ? 1 : 0, /* Bit 5: nTRST */ - (d & (0x01 << 7)) ? 1 : 0); /* Bit 7: nRESET */ + (d & SWJ_PIN_TCK) ? 1 : 0, + (d & SWJ_PIN_TMS) ? 1 : 0, + (d & SWJ_PIN_TDI) ? 1 : 0, + (d & SWJ_PIN_TDO) ? 1 : 0, + (d & SWJ_PIN_TRST) ? 1 : 0, + (d & SWJ_PIN_SRST) ? 1 : 0); } return retval; @@ -990,8 +997,17 @@ static int cmsis_dap_quit(void) static void cmsis_dap_execute_reset(struct jtag_command *cmd) { - int retval = cmsis_dap_cmd_DAP_SWJ_Pins(cmd->cmd.reset->srst ? 0 : (1 << 7), \ - (1 << 7), 0, NULL); + /* Set both TRST and SRST even if they're not enabled as + * there's no way to tristate them */ + uint8_t pins = 0; + + if (!cmd->cmd.reset->srst) + pins |= SWJ_PIN_SRST; + if (!cmd->cmd.reset->trst) + pins |= SWJ_PIN_TRST; + + int retval = cmsis_dap_cmd_DAP_SWJ_Pins(pins, + SWJ_PIN_TRST | SWJ_PIN_SRST, 0, NULL); if (retval != ERROR_OK) LOG_ERROR("CMSIS-DAP: Interface reset failed"); } -- cgit v1.1 From 3ae41fcf825277a56fadeea3dfde6bacf7e8e6c8 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Tue, 4 Oct 2016 14:22:41 +0300 Subject: jtag: drivers: mpsse: ignore error to detach kernel driver This makes it possible to run OpenOCD as unprivileged user on FreeBSD. Change-Id: If1182d09ad2d51f370ae7e6da02f19c7a21c66c9 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3800 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/drivers/mpsse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jtag/drivers/mpsse.c b/src/jtag/drivers/mpsse.c index 3c1c97c..924c974 100644 --- a/src/jtag/drivers/mpsse.c +++ b/src/jtag/drivers/mpsse.c @@ -247,8 +247,8 @@ static bool open_matching_device(struct mpsse_ctx *ctx, const uint16_t *vid, con err = libusb_detach_kernel_driver(ctx->usb_dev, ctx->interface); if (err != LIBUSB_SUCCESS && err != LIBUSB_ERROR_NOT_FOUND && err != LIBUSB_ERROR_NOT_SUPPORTED) { - LOG_ERROR("libusb_detach_kernel_driver() failed with %s", libusb_error_name(err)); - goto error; + LOG_WARNING("libusb_detach_kernel_driver() failed with %s, trying to continue anyway", + libusb_error_name(err)); } err = libusb_claim_interface(ctx->usb_dev, ctx->interface); -- cgit v1.1 From da7459415079002a52f516a6d00a31474d61b495 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 21 Aug 2016 20:12:02 +0200 Subject: target: Fix working_area_phys_spec comment MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit working_area_phys_spec clearly refers to the physical, not virtual address. Change-Id: I639ea00bb5d05e845b8a56815a571375849f1225 Signed-off-by: Andreas Färber Reviewed-on: http://openocd.zylin.com/3714 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- src/target/target.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/target.h b/src/target/target.h index 0cee117..a1a30ff 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -154,7 +154,7 @@ struct target { * upon first allocation from virtual/physical address. */ bool working_area_virt_spec; /* virtual address specified? */ uint32_t working_area_virt; /* virtual address */ - bool working_area_phys_spec; /* virtual address specified? */ + bool working_area_phys_spec; /* physical address specified? */ uint32_t working_area_phys; /* physical address */ uint32_t working_area_size; /* size in bytes */ uint32_t backup_working_area; /* whether the content of the working area has to be preserved */ -- cgit v1.1 From 5fba5068b74cb277683be1f29ed10a234c74d7ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 21 Aug 2016 22:12:52 +0200 Subject: breakpoints: Add missing space in error message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A space after the format specifier was missing. Change-Id: Ib67eb0fb0d6e05d765206d30d5e4a74cb41bb47b Signed-off-by: Andreas Färber Reviewed-on: http://openocd.zylin.com/3715 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/breakpoints.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index 9591714..c4a959d 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -403,7 +403,7 @@ int watchpoint_add(struct target *target, uint32_t address, uint32_t length, || watchpoint->mask != mask || watchpoint->rw != rw) { LOG_ERROR("address 0x%8.8" PRIx32 - "already has watchpoint %d", + " already has watchpoint %d", address, watchpoint->unique_id); return ERROR_FAIL; } -- cgit v1.1 From c06ac3b5d357351e34438452a72a14e534910c6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 21 Aug 2016 22:49:17 +0200 Subject: target: Add missing spaces in error messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Insert a space before parenthesis in logs that we will need to touch for 64-bit target addresses. While at it, do a couple more surrounding whitespace fixes. Change-Id: I1080c0470aab51cf7bd56e67e934344d0bf4c5c1 Signed-off-by: Andreas Färber Reviewed-on: http://openocd.zylin.com/3716 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- src/target/target.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 56d9eee..fefaa0e 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -2034,8 +2034,8 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size, return ERROR_OK; if ((address + size - 1) < address) { - /* GDB can request this when e.g. PC is 0xfffffffc*/ - LOG_ERROR("address + size wrapped(0x%08x, 0x%08x)", + /* GDB can request this when e.g. PC is 0xfffffffc */ + LOG_ERROR("address + size wrapped (0x%08x, 0x%08x)", (unsigned)address, (unsigned)size); return ERROR_FAIL; @@ -2095,8 +2095,8 @@ int target_read_buffer(struct target *target, uint32_t address, uint32_t size, u return ERROR_OK; if ((address + size - 1) < address) { - /* GDB can request this when e.g. PC is 0xfffffffc*/ - LOG_ERROR("address + size wrapped(0x%08" PRIx32 ", 0x%08" PRIx32 ")", + /* GDB can request this when e.g. PC is 0xfffffffc */ + LOG_ERROR("address + size wrapped (0x%08" PRIx32 ", 0x%08" PRIx32 ")", address, size); return ERROR_FAIL; @@ -4002,7 +4002,7 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, sprintf(buf, "mem2array address: 0x%08" PRIx32 " is not aligned for %" PRId32 " byte reads", addr, width); - Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL); + Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL); return JIM_ERR; } @@ -4208,7 +4208,7 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", (unsigned int)addr, (int)width); - Jim_AppendStrings(interp, Jim_GetResult(interp), buf , NULL); + Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL); return JIM_ERR; } -- cgit v1.1 From 10aeff925936a43e873acfd0068b1eea03781051 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 21 Aug 2016 20:56:44 +0200 Subject: target: Clean up format strings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clean up some type casts and misuses of format specifiers in preparation for target address type changes. Change-Id: Idf08286f41bca636e35a09e8ddc1d71af3d6e151 Signed-off-by: Andreas Färber Reviewed-on: http://openocd.zylin.com/3717 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/target/target.c | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index fefaa0e..e3c8168 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -2022,8 +2022,8 @@ static int target_profiling_default(struct target *target, uint32_t *samples, */ int target_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer) { - LOG_DEBUG("writing buffer of %i byte at 0x%8.8x", - (int)size, (unsigned)address); + LOG_DEBUG("writing buffer of %" PRIi32 " byte at 0x%8.8" PRIx32, + size, address); if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); @@ -2035,9 +2035,9 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size, if ((address + size - 1) < address) { /* GDB can request this when e.g. PC is 0xfffffffc */ - LOG_ERROR("address + size wrapped (0x%08x, 0x%08x)", - (unsigned)address, - (unsigned)size); + LOG_ERROR("address + size wrapped (0x%08" PRIx32 ", 0x%08" PRIx32 ")", + address, + size); return ERROR_FAIL; } @@ -2083,8 +2083,8 @@ static int target_write_buffer_default(struct target *target, uint32_t address, */ int target_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer) { - LOG_DEBUG("reading buffer of %i byte at 0x%8.8x", - (int)size, (unsigned)address); + LOG_DEBUG("reading buffer of %" PRIi32 " byte at 0x%8.8" PRIx32, + size, address); if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); @@ -2153,7 +2153,7 @@ int target_checksum_memory(struct target *target, uint32_t address, uint32_t siz if (retval != ERROR_OK) { buffer = malloc(size); if (buffer == NULL) { - LOG_ERROR("error allocating buffer for section (%d bytes)", (int)size); + LOG_ERROR("error allocating buffer for section (%" PRId32 " bytes)", size); return ERROR_COMMAND_SYNTAX_ERROR; } retval = target_read_buffer(target, address, size, buffer); @@ -2254,7 +2254,7 @@ int target_read_u16(struct target *target, uint32_t address, uint16_t *value) if (retval == ERROR_OK) { *value = target_buffer_get_u16(target, value_buf); - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%4.4x", + LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%4.4" PRIx16, address, *value); } else { @@ -2276,7 +2276,7 @@ int target_read_u8(struct target *target, uint32_t address, uint8_t *value) int retval = target_read_memory(target, address, 1, 1, value); if (retval == ERROR_OK) { - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2x", + LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2" PRIx8, address, *value); } else { @@ -2339,7 +2339,7 @@ int target_write_u16(struct target *target, uint32_t address, uint16_t value) return ERROR_FAIL; } - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8x", + LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx16, address, value); @@ -2359,7 +2359,7 @@ int target_write_u8(struct target *target, uint32_t address, uint8_t value) return ERROR_FAIL; } - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2x", + LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2" PRIx8, address, value); retval = target_write_memory(target, address, 1, 1, &value); @@ -4031,10 +4031,10 @@ static int target_mem2array(Jim_Interp *interp, struct target *target, int argc, retval = target_read_memory(target, addr, width, count, buffer); if (retval != ERROR_OK) { /* BOO !*/ - LOG_ERROR("mem2array: Read @ 0x%08x, w=%d, cnt=%d, failed", - (unsigned int)addr, - (int)width, - (int)count); + LOG_ERROR("mem2array: Read @ 0x%08" PRIx32 ", w=%" PRId32 ", cnt=%" PRId32 ", failed", + addr, + width, + count); Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "mem2array: cannot read memory", NULL); e = JIM_ERR; @@ -4205,9 +4205,9 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, } else { char buf[100]; Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - sprintf(buf, "array2mem address: 0x%08x is not aligned for %d byte reads", - (unsigned int)addr, - (int)width); + sprintf(buf, "array2mem address: 0x%08" PRIx32 " is not aligned for %" PRId32 " byte reads", + addr, + width); Jim_AppendStrings(interp, Jim_GetResult(interp), buf, NULL); return JIM_ERR; } @@ -4254,10 +4254,10 @@ static int target_array2mem(Jim_Interp *interp, struct target *target, retval = target_write_memory(target, addr, width, count, buffer); if (retval != ERROR_OK) { /* BOO !*/ - LOG_ERROR("array2mem: Write @ 0x%08x, w=%d, cnt=%d, failed", - (unsigned int)addr, - (int)width, - (int)count); + LOG_ERROR("array2mem: Write @ 0x%08" PRIx32 ", w=%" PRId32 ", cnt=%" PRId32 ", failed", + addr, + width, + count); Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); Jim_AppendStrings(interp, Jim_GetResult(interp), "array2mem: cannot read memory", NULL); e = JIM_ERR; -- cgit v1.1 From 674141e8a7a6413cb803d90c2a20150260015f81 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 22 May 2016 19:44:27 +0200 Subject: helper: Make unhexify() robust on invalid data The current implementation is not suitable for user provided data because it does not detect invalid inputs in many cases. For example, the string "aa0xbb" is successfully converted to the 3 bytes: 0xaa, 0x00 and 0xbb. An other example is "aabi" which is successfully converted to the 2 bytes: 0xaa and 0x0b. Both are obviously incorrect. Make unhexify() robust on invalid data and use more appropriate data types for its parameters. Also, add a small documentation for the function. Change-Id: Idb799beb86fc608b066c8a76365021ed44c7f890 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3792 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/helper/binarybuffer.c | 39 ++++++++++++++++++++++++++++++++------- src/helper/binarybuffer.h | 2 +- src/jtag/drivers/ti_icdi_usb.c | 6 +++--- src/rtos/rtos.c | 2 +- src/server/gdb_server.c | 4 ++-- 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index c1e6322..26aa8cc 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -369,17 +369,42 @@ void bit_copy_discard(struct bit_copy_queue *q) } } -int unhexify(char *bin, const char *hex, int count) +/** + * Convert a string of hexadecimal pairs into its binary + * representation. + * + * @param[out] bin Buffer to store binary representation. The buffer size must + * be at least @p count. + * @param[in] hex String with hexadecimal pairs to convert into its binary + * representation. + * @param[in] count Number of hexadecimal pairs to convert. + * + * @return The number of converted hexadecimal pairs. + */ +size_t unhexify(uint8_t *bin, const char *hex, size_t count) { - int i, tmp; + size_t i; + char tmp; - for (i = 0; i < count; i++) { - if (sscanf(hex + (2 * i), "%02x", &tmp) != 1) - return i; - bin[i] = tmp; + if (!bin || !hex) + return 0; + + memset(bin, 0, count); + + for (i = 0; i < 2 * count; i++) { + if (hex[i] >= 'a' && hex[i] <= 'f') + tmp = hex[i] - 'a' + 10; + else if (hex[i] >= 'A' && hex[i] <= 'F') + tmp = hex[i] - 'A' + 10; + else if (hex[i] >= '0' && hex[i] <= '9') + tmp = hex[i] - '0'; + else + return i / 2; + + bin[i / 2] |= tmp << (4 * ((i + 1) % 2)); } - return i; + return i / 2; } int hexify(char *hex, const char *bin, int count, int out_maxlen) diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h index dd0d275..b035779 100644 --- a/src/helper/binarybuffer.h +++ b/src/helper/binarybuffer.h @@ -234,7 +234,7 @@ void bit_copy_discard(struct bit_copy_queue *q); /* functions to convert to/from hex encoded buffer * used in ti-icdi driver and gdb server */ -int unhexify(char *bin, const char *hex, int count); +size_t unhexify(uint8_t *bin, const char *hex, size_t count); int hexify(char *hex, const char *bin, int count, int out_maxlen); void buffer_shr(void *_buf, unsigned buf_len, unsigned count); diff --git a/src/jtag/drivers/ti_icdi_usb.c b/src/jtag/drivers/ti_icdi_usb.c index 3db03b0..7a6272f 100644 --- a/src/jtag/drivers/ti_icdi_usb.c +++ b/src/jtag/drivers/ti_icdi_usb.c @@ -266,7 +266,7 @@ static int icdi_get_cmd_result(void *handle) if (h->read_buffer[offset] == 'E') { /* get error code */ - char result; + uint8_t result; if (unhexify(&result, h->read_buffer + offset + 1, 1) != 1) return ERROR_FAIL; return result; @@ -328,7 +328,7 @@ static int icdi_usb_version(void *handle) } /* convert reply */ - if (unhexify(version, h->read_buffer + 2, 4) != 4) { + if (unhexify((uint8_t *)version, h->read_buffer + 2, 4) != 4) { LOG_WARNING("unable to get ICDI version"); return ERROR_OK; } @@ -495,7 +495,7 @@ static int icdi_usb_read_reg(void *handle, int num, uint32_t *val) /* convert result */ uint8_t buf[4]; - if (unhexify((char *)buf, h->read_buffer + 2, 4) != 4) { + if (unhexify(buf, h->read_buffer + 2, 4) != 4) { LOG_ERROR("failed to convert result"); return ERROR_FAIL; } diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 4c99ad2..448c49c 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -213,7 +213,7 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s goto done; /* Decode any symbol name in the packet*/ - int len = unhexify(cur_sym, strchr(packet + 8, ':') + 1, strlen(strchr(packet + 8, ':') + 1)); + size_t len = unhexify((uint8_t *)cur_sym, strchr(packet + 8, ':') + 1, strlen(strchr(packet + 8, ':') + 1)); cur_sym[len] = 0; if ((strcmp(packet, "qSymbol::") != 0) && /* GDB is not offering symbol lookup for the first time */ diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index d09a8be..f85fa1b 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1449,7 +1449,7 @@ static int gdb_write_memory_packet(struct connection *connection, LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len); - if (unhexify((char *)buffer, separator, len) != (int)len) + if (unhexify(buffer, separator, len) != len) LOG_ERROR("unable to decode memory packet"); retval = target_write_buffer(target, addr, len, buffer); @@ -2277,7 +2277,7 @@ static int gdb_query_packet(struct connection *connection, if (packet_size > 6) { char *cmd; cmd = malloc((packet_size - 6) / 2 + 1); - int len = unhexify(cmd, packet + 6, (packet_size - 6) / 2); + size_t len = unhexify((uint8_t *)cmd, packet + 6, (packet_size - 6) / 2); cmd[len] = 0; /* We want to print all debug output to GDB connection */ -- cgit v1.1 From b9ee6dd4655310c0553f4eef853213b11c1df28f Mon Sep 17 00:00:00 2001 From: Gabrielle Trotter Date: Fri, 21 Oct 2016 15:35:08 -0400 Subject: atsamv: Support for ATSAMS70N19 Memory Configuration Change-Id: I3c17fcb7ee053f92aa583149bea7b8e33b3b86f7 Signed-off-by: gtrotter@bulogics.com Reviewed-on: http://openocd.zylin.com/3834 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/atsamv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/flash/nor/atsamv.c b/src/flash/nor/atsamv.c index d21419d..73f0238 100644 --- a/src/flash/nor/atsamv.c +++ b/src/flash/nor/atsamv.c @@ -363,6 +363,9 @@ static int samv_probe(struct flash_bank *bank) uint8_t nvm_size_code = (device_id >> 8) & 0xf; switch (nvm_size_code) { + case 10: + bank->size = 512 * 1024; + break; case 12: bank->size = 1024 * 1024; break; -- cgit v1.1 From eaacb900dd3ce5257dcfec35a8032a873d141b6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Sun, 8 May 2016 23:49:07 +0200 Subject: flash/nor: Add erased_value to drivers and pass it to targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit struct flash_driver has a default_padded_value field that is similar, but it can be changed by the user for the specific purpose of padding. Add a new erased_value field and initialize it for all targets, particularly stm32lx, xmc4xxx and virtual. Use this value in core.c:default_flash_mem_blank_check(), the slow path. Extend the target API to pass erased_value down to target code. Adding an argument ensures that we catch all callers. This allows us to merge xmc4xxx.c:xmc4xxx_blank_check_memory() into armv7m:armv7m_blank_check_memory(). It further allows us to use default_flash_blank_check() in place of xmc4xxx.c:xmc4xxx_flash_blank_check(), adding a potential slow path fallback, as well as stm32lx:stm32lx_erase_check(), adding the potential armv7m fast path with fallback to default_flash_mem_blank_check(). Fix a mips32 code comment while at it (zeroed -> erased). The armv4_5 and mips32 target implementations will now error out if an erase value other than 0xff is used, causing default_flash_blank_check() to fall back to the default_flank_mem_blank_check() slow path. Change-Id: I39323fbbc4b71c256cd567e439896d0245d4745f Signed-off-by: Andreas Färber Reviewed-on: http://openocd.zylin.com/3497 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/at91sam7.c | 2 +- src/flash/nor/core.c | 6 +-- src/flash/nor/core.h | 3 ++ src/flash/nor/stm32lx.c | 54 +------------------------- src/flash/nor/tcl.c | 2 +- src/flash/nor/virtual.c | 1 + src/flash/nor/xmc4xxx.c | 99 ++---------------------------------------------- src/target/arm.h | 2 +- src/target/armv4_5.c | 10 ++++- src/target/armv7m.c | 28 +++++++++++--- src/target/armv7m.h | 2 +- src/target/mips32.c | 12 ++++-- src/target/mips32.h | 2 +- src/target/target.c | 5 ++- src/target/target.h | 2 +- src/target/target_type.h | 2 +- 16 files changed, 61 insertions(+), 171 deletions(-) diff --git a/src/flash/nor/at91sam7.c b/src/flash/nor/at91sam7.c index ccb1a74..03f771c 100644 --- a/src/flash/nor/at91sam7.c +++ b/src/flash/nor/at91sam7.c @@ -661,7 +661,7 @@ static int at91sam7_erase_check(struct flash_bank *bank) retval = target_blank_check_memory(target, bank->base + bank->sectors[nSector].offset, bank->sectors[nSector].size, - &blank); + &blank, bank->erased_value); if (retval != ERROR_OK) { fast_check = 0; break; diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index 7a62ba1..8f6306f 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -288,7 +288,7 @@ static int default_flash_mem_blank_check(struct flash_bank *bank) goto done; for (nBytes = 0; nBytes < chunk; nBytes++) { - if (buffer[nBytes] != 0xFF) { + if (buffer[nBytes] != bank->erased_value) { bank->sectors[i].is_erased = 0; break; } @@ -319,12 +319,12 @@ int default_flash_blank_check(struct flash_bank *bank) uint32_t address = bank->base + bank->sectors[i].offset; uint32_t size = bank->sectors[i].size; - retval = target_blank_check_memory(target, address, size, &blank); + retval = target_blank_check_memory(target, address, size, &blank, bank->erased_value); if (retval != ERROR_OK) { fast_check = 0; break; } - if (blank == 0xFF) + if (blank == bank->erased_value) bank->sectors[i].is_erased = 1; else bank->sectors[i].is_erased = 0; diff --git a/src/flash/nor/core.h b/src/flash/nor/core.h index 60d4483..338363e 100644 --- a/src/flash/nor/core.h +++ b/src/flash/nor/core.h @@ -90,6 +90,9 @@ struct flash_bank { int chip_width; /**< Width of the chip in bytes (1,2,4 bytes) */ int bus_width; /**< Maximum bus width, in bytes (1,2,4 bytes) */ + /** Erased value. Defaults to 0xFF. */ + uint8_t erased_value; + /** Default padded value used, normally this matches the flash * erased value. Defaults to 0xFF. */ uint8_t default_padded_value; diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c index 376c0f8..0b39233 100644 --- a/src/flash/nor/stm32lx.c +++ b/src/flash/nor/stm32lx.c @@ -300,7 +300,7 @@ FLASH_BANK_COMMAND_HANDLER(stm32lx_flash_bank_command) stm32lx_info->user_bank_size = bank->size; /* the stm32l erased value is 0x00 */ - bank->default_padded_value = 0x00; + bank->default_padded_value = bank->erased_value = 0x00; return ERROR_OK; } @@ -884,56 +884,6 @@ static int stm32lx_auto_probe(struct flash_bank *bank) return stm32lx_probe(bank); } -static int stm32lx_erase_check(struct flash_bank *bank) -{ - struct target *target = bank->target; - const int buffer_size = 4096; - int i; - uint32_t nBytes; - int retval = ERROR_OK; - - if (bank->target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - uint8_t *buffer = malloc(buffer_size); - if (buffer == NULL) { - LOG_ERROR("failed to allocate read buffer"); - return ERROR_FAIL; - } - - for (i = 0; i < bank->num_sectors; i++) { - uint32_t j; - bank->sectors[i].is_erased = 1; - - /* Loop chunk by chunk over the sector */ - for (j = 0; j < bank->sectors[i].size; j += buffer_size) { - uint32_t chunk; - chunk = buffer_size; - if (chunk > (j - bank->sectors[i].size)) - chunk = (j - bank->sectors[i].size); - - retval = target_read_memory(target, bank->base - + bank->sectors[i].offset + j, 4, chunk / 4, buffer); - if (retval != ERROR_OK) - break; - - for (nBytes = 0; nBytes < chunk; nBytes++) { - if (buffer[nBytes] != 0x00) { - bank->sectors[i].is_erased = 0; - break; - } - } - } - if (retval != ERROR_OK) - break; - } - free(buffer); - - return retval; -} - /* This method must return a string displaying information about the bank */ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size) { @@ -1022,7 +972,7 @@ struct flash_driver stm32lx_flash = { .read = default_flash_read, .probe = stm32lx_probe, .auto_probe = stm32lx_auto_probe, - .erase_check = stm32lx_erase_check, + .erase_check = default_flash_blank_check, .protect_check = stm32lx_protect_check, .info = stm32lx_get_info, }; diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 6dd2140..d62fa74 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -1012,7 +1012,7 @@ COMMAND_HANDLER(handle_flash_bank_command) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], c->size); COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], c->chip_width); COMMAND_PARSE_NUMBER(int, CMD_ARGV[4], c->bus_width); - c->default_padded_value = 0xff; + c->default_padded_value = c->erased_value = 0xff; c->num_sectors = 0; c->sectors = NULL; c->num_prot_blocks = 0; diff --git a/src/flash/nor/virtual.c b/src/flash/nor/virtual.c index 3cb793e..06981f4 100644 --- a/src/flash/nor/virtual.c +++ b/src/flash/nor/virtual.c @@ -44,6 +44,7 @@ static void virtual_update_bank_info(struct flash_bank *bank) bank->size = master_bank->size; bank->chip_width = master_bank->chip_width; bank->bus_width = master_bank->bus_width; + bank->erased_value = master_bank->erased_value; bank->default_padded_value = master_bank->default_padded_value; bank->num_sectors = master_bank->num_sectors; bank->sectors = master_bank->sectors; diff --git a/src/flash/nor/xmc4xxx.c b/src/flash/nor/xmc4xxx.c index 2a52269..f396ca3 100644 --- a/src/flash/nor/xmc4xxx.c +++ b/src/flash/nor/xmc4xxx.c @@ -319,8 +319,8 @@ static int xmc4xxx_load_bank_layout(struct flash_bank *bank) } /* This part doesn't follow the typical standard of 0xff - * being the default padding value.*/ - bank->default_padded_value = 0x00; + * being the erased value.*/ + bank->default_padded_value = bank->erased_value = 0x00; return ERROR_OK; } @@ -617,99 +617,6 @@ static int xmc4xxx_enter_page_mode(struct flash_bank *bank) return res; } -/* The logical erase value of an xmc4xxx memory cell is 0x00, - * therefore, we cannot use the built in flash blank check and must - * implement our own */ - -/** Checks whether a memory region is zeroed. */ -static int xmc4xxx_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank) -{ - struct working_area *erase_check_algorithm; - struct reg_param reg_params[3]; - struct armv7m_algorithm armv7m_info; - int retval; - - static const uint8_t erase_check_code[] = { -#include "../../../contrib/loaders/erase_check/armv7m_0_erase_check.inc" - }; - - /* make sure we have a working area */ - if (target_alloc_working_area(target, sizeof(erase_check_code), - &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); - if (retval != ERROR_OK) - goto cleanup; - - 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); - - init_reg_param(®_params[1], "r1", 32, PARAM_OUT); - buf_set_u32(reg_params[1].value, 0, 32, count); - - init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); - buf_set_u32(reg_params[2].value, 0, 32, 0x00); - - 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); - - if (retval == ERROR_OK) - *blank = buf_get_u32(reg_params[2].value, 0, 32); - - destroy_reg_param(®_params[0]); - destroy_reg_param(®_params[1]); - destroy_reg_param(®_params[2]); - -cleanup: - target_free_working_area(target, erase_check_algorithm); - - return retval; -} - -static int xmc4xxx_flash_blank_check(struct flash_bank *bank) -{ - struct target *target = bank->target; - int i; - int retval = ERROR_OK; - uint32_t blank; - - if (bank->target->state != TARGET_HALTED) { - LOG_ERROR("Target not halted"); - return ERROR_TARGET_NOT_HALTED; - } - - for (i = 0; i < bank->num_sectors; i++) { - uint32_t address = bank->base + bank->sectors[i].offset; - uint32_t size = bank->sectors[i].size; - - LOG_DEBUG("Erase checking 0x%08"PRIx32, address); - retval = xmc4xxx_blank_check_memory(target, address, size, &blank); - - if (retval != ERROR_OK) - break; - - if (blank == 0x00) - bank->sectors[i].is_erased = 1; - else - bank->sectors[i].is_erased = 0; - } - - return retval; -} - static int xmc4xxx_write_page(struct flash_bank *bank, const uint8_t *pg_buf, uint32_t offset, bool user_config) { @@ -1439,7 +1346,7 @@ struct flash_driver xmc4xxx_flash = { .read = default_flash_read, .probe = xmc4xxx_probe, .auto_probe = xmc4xxx_probe, - .erase_check = xmc4xxx_flash_blank_check, + .erase_check = default_flash_blank_check, .info = xmc4xxx_get_info_command, .protect_check = xmc4xxx_protect_check, .protect = xmc4xxx_protect, diff --git a/src/target/arm.h b/src/target/arm.h index 163db23..28022e3 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -232,7 +232,7 @@ int armv4_5_run_algorithm_inner(struct target *target, int arm_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum); int arm_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank); + uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value); void arm_set_cpsr(struct arm *arm, uint32_t cpsr); struct reg *arm_reg_current(struct arm *arm, unsigned regnum); diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index e6ecfc8..1a31d40 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -1486,7 +1486,7 @@ cleanup: * */ int arm_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank) + uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value) { struct working_area *check_algorithm; struct reg_param reg_params[3]; @@ -1502,6 +1502,12 @@ int arm_blank_check_memory(struct target *target, assert(sizeof(check_code_le) % 4 == 0); + if (erased_value != 0xff) { + LOG_ERROR("Erase value 0x%02" PRIx8 " not yet supported for ARMv4/v5 targets", + erased_value); + return ERROR_FAIL; + } + /* make sure we have a working area */ retval = target_alloc_working_area(target, sizeof(check_code_le), &check_algorithm); @@ -1529,7 +1535,7 @@ int arm_blank_check_memory(struct target *target, buf_set_u32(reg_params[1].value, 0, 32, count); init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); - buf_set_u32(reg_params[2].value, 0, 32, 0xff); + buf_set_u32(reg_params[2].value, 0, 32, erased_value); /* armv4 must exit using a hardware breakpoint */ if (arm->is_armv4) diff --git a/src/target/armv7m.c b/src/target/armv7m.c index e2f710f..60b244a 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -726,26 +726,42 @@ cleanup: return retval; } -/** Checks whether a memory region is zeroed. */ +/** Checks whether a memory region is erased. */ int armv7m_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank) + uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value) { struct working_area *erase_check_algorithm; struct reg_param reg_params[3]; struct armv7m_algorithm armv7m_info; + const uint8_t *code; + uint32_t code_size; int retval; static const uint8_t erase_check_code[] = { #include "../../contrib/loaders/erase_check/armv7m_erase_check.inc" }; + static const uint8_t zero_erase_check_code[] = { +#include "../../contrib/loaders/erase_check/armv7m_0_erase_check.inc" + }; + + switch (erased_value) { + case 0x00: + code = zero_erase_check_code; + code_size = sizeof(zero_erase_check_code); + break; + case 0xff: + default: + code = erase_check_code; + 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, code); if (retval != ERROR_OK) goto cleanup; @@ -759,7 +775,7 @@ int armv7m_blank_check_memory(struct target *target, buf_set_u32(reg_params[1].value, 0, 32, count); init_reg_param(®_params[2], "r2", 32, PARAM_IN_OUT); - buf_set_u32(reg_params[2].value, 0, 32, 0xff); + buf_set_u32(reg_params[2].value, 0, 32, erased_value); retval = target_run_algorithm(target, 0, @@ -767,7 +783,7 @@ int armv7m_blank_check_memory(struct target *target, 3, reg_params, erase_check_algorithm->address, - erase_check_algorithm->address + (sizeof(erase_check_code) - 2), + erase_check_algorithm->address + (code_size - 2), 10000, &armv7m_info); diff --git a/src/target/armv7m.h b/src/target/armv7m.h index 90cad00..304c72d 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -225,7 +225,7 @@ int armv7m_restore_context(struct target *target); int armv7m_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum); int armv7m_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank); + uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value); int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found); diff --git a/src/target/mips32.c b/src/target/mips32.c index 8c77986..27caebe 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -771,9 +771,9 @@ int mips32_checksum_memory(struct target *target, uint32_t address, return retval; } -/** Checks whether a memory region is zeroed. */ +/** Checks whether a memory region is erased. */ int mips32_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank) + uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value) { struct working_area *erase_check_algorithm; struct reg_param reg_params[3]; @@ -789,6 +789,12 @@ int mips32_blank_check_memory(struct target *target, 0x7000003F /* sdbbp */ }; + if (erased_value != 0xff) { + LOG_ERROR("Erase value 0x%02" PRIx8 " not yet supported for MIPS32", + erased_value); + return ERROR_FAIL; + } + /* make sure we have a working area */ if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -810,7 +816,7 @@ int mips32_blank_check_memory(struct target *target, buf_set_u32(reg_params[1].value, 0, 32, count); init_reg_param(®_params[2], "r6", 32, PARAM_IN_OUT); - buf_set_u32(reg_params[2].value, 0, 32, 0xff); + buf_set_u32(reg_params[2].value, 0, 32, erased_value); int retval = target_run_algorithm(target, 0, NULL, 3, reg_params, erase_check_algorithm->address, diff --git a/src/target/mips32.h b/src/target/mips32.h index 8362f5e..d493b39 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -249,6 +249,6 @@ int mips32_get_gdb_reg_list(struct target *target, int mips32_checksum_memory(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum); int mips32_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank); + uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value); #endif /* OPENOCD_TARGET_MIPS32_H */ diff --git a/src/target/target.c b/src/target/target.c index e3c8168..9fc9d20 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -2178,7 +2178,8 @@ int target_checksum_memory(struct target *target, uint32_t address, uint32_t siz return retval; } -int target_blank_check_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* blank) +int target_blank_check_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* blank, + uint8_t erased_value) { int retval; if (!target_was_examined(target)) { @@ -2189,7 +2190,7 @@ int target_blank_check_memory(struct target *target, uint32_t address, uint32_t if (target->type->blank_check_memory == 0) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - retval = target->type->blank_check_memory(target, address, size, blank); + retval = target->type->blank_check_memory(target, address, size, blank, erased_value); return retval; } diff --git a/src/target/target.h b/src/target/target.h index a1a30ff..8f6a7d9 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -579,7 +579,7 @@ int target_read_buffer(struct target *target, int target_checksum_memory(struct target *target, uint32_t address, uint32_t size, uint32_t *crc); int target_blank_check_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t *blank); + uint32_t address, uint32_t size, uint32_t *blank, uint8_t erased_value); int target_wait_state(struct target *target, enum target_state state, int ms); /** diff --git a/src/target/target_type.h b/src/target/target_type.h index eaa8a71..2473c62 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -131,7 +131,7 @@ struct target_type { int (*checksum_memory)(struct target *target, uint32_t address, uint32_t count, uint32_t *checksum); int (*blank_check_memory)(struct target *target, uint32_t address, - uint32_t count, uint32_t *blank); + uint32_t count, uint32_t *blank, uint8_t erased_value); /* * target break-/watchpoint control -- cgit v1.1 From 4b50872ffe1375c57bc82122dc76ed0324ab91ef Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Wed, 5 Oct 2016 19:12:12 +0300 Subject: flash: nor: lpc2000: handle lpc11xx parts with more than 96k memory Known big flash parts such as LPC11u68/e68 have a non-uniform memory organisation, the first 24 sectors are 4k, the rest are 32k. Change-Id: Icf515152dfc54ec0ca187561d2d63088b9640f14 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3802 Tested-by: jenkins Reviewed-by: akaWolf Reviewed-by: Freddie Chopin --- src/flash/nor/lpc2000.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/flash/nor/lpc2000.c b/src/flash/nor/lpc2000.c index 76cd86b..190684a 100644 --- a/src/flash/nor/lpc2000.c +++ b/src/flash/nor/lpc2000.c @@ -259,6 +259,8 @@ #define IAP_CODE_LEN 0x34 +#define LPC11xx_REG_SECTORS 24 + typedef enum { lpc2000_v1, lpc2000_v2, @@ -554,14 +556,21 @@ static int lpc2000_build_sector_list(struct flash_bank *bank) exit(-1); } lpc2000_info->cmd51_max_buffer = 512; /* smallest MCU in the series, LPC1110, has 1 kB of SRAM */ - bank->num_sectors = bank->size / 4096; + unsigned int large_sectors = 0; + unsigned int normal_sectors = bank->size / 4096; + + if (normal_sectors > LPC11xx_REG_SECTORS) { + large_sectors = (normal_sectors - LPC11xx_REG_SECTORS) / 8; + normal_sectors = LPC11xx_REG_SECTORS; + } + + bank->num_sectors = normal_sectors + large_sectors; bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); for (int i = 0; i < bank->num_sectors; i++) { bank->sectors[i].offset = offset; - /* all sectors are 4kB-sized */ - bank->sectors[i].size = 4 * 1024; + bank->sectors[i].size = (i < LPC11xx_REG_SECTORS ? 4 : 32) * 1024; offset += bank->sectors[i].size; bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; -- cgit v1.1 From 19df456a79c912b9e2162ef05c1fd0c02ec7b14a Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Wed, 5 Oct 2016 07:57:38 -0700 Subject: Perform small writes before sending OK. To speed up downloads, OpenOCD sends gdb OK when a write is received, even before the write has actually occurred. The failure is then returned for the next write. That leads to the following confusing behavior: ``` (gdb) p/x *((int*)0xdeadbeef)=8675309 $2 = 0x845fed (gdb) p/x *((int*)0x80000000)=6874742 Cannot access memory at address 0x80000000 ``` While it's actually the first write that failed. This change hacks around this problem by not sending OK for small writes (len<8) until the write has actually occurred. This does not impact download speed, since during downloads (almost) all writes will have much larger length. Change-Id: I1f8b9bb19b0707487f840df6871e372e4ba228dd Signed-off-by: Tim Newsome Reviewed-on: http://openocd.zylin.com/3803 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/server/gdb_server.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index f85fa1b..7fd579b 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1473,6 +1473,10 @@ static int gdb_write_memory_binary_packet(struct connection *connection, uint32_t len = 0; int retval = ERROR_OK; + /* Packets larger than fast_limit bytes will be acknowledged instantly on + * the assumption that we're in a download and it's important to go as fast + * as possible. */ + uint32_t fast_limit = 8; /* skip command character */ packet++; @@ -1493,19 +1497,23 @@ static int gdb_write_memory_binary_packet(struct connection *connection, struct gdb_connection *gdb_connection = connection->priv; - if (gdb_connection->mem_write_error) { + if (gdb_connection->mem_write_error) retval = ERROR_FAIL; - /* now that we have reported the memory write error, we can clear the condition */ - gdb_connection->mem_write_error = false; - } - /* By replying the packet *immediately* GDB will send us a new packet - * while we write the last one to the target. - */ - if (retval == ERROR_OK) - gdb_put_packet(connection, "OK", 2); - else { + if (retval == ERROR_OK) { + if (len >= fast_limit) { + /* By replying the packet *immediately* GDB will send us a new packet + * while we write the last one to the target. + * We only do this for larger writes, so that users who do something like: + * p *((int*)0xdeadbeef)=8675309 + * will get immediate feedback that that write failed. + */ + gdb_put_packet(connection, "OK", 2); + } + } else { retval = gdb_error(connection, retval); + /* now that we have reported the memory write error, we can clear the condition */ + gdb_connection->mem_write_error = false; if (retval != ERROR_OK) return retval; } @@ -1518,6 +1526,15 @@ static int gdb_write_memory_binary_packet(struct connection *connection, gdb_connection->mem_write_error = true; } + if (len < fast_limit) { + if (retval != ERROR_OK) { + gdb_error(connection, retval); + gdb_connection->mem_write_error = false; + } else { + gdb_put_packet(connection, "OK", 2); + } + } + return ERROR_OK; } -- cgit v1.1 From f6b8a4ea65b885150ed581bf4f9372486e298415 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Pinkava?= Date: Fri, 9 Sep 2016 13:22:59 +0200 Subject: nrf51: show proper part number MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I3e8169eb577888ee54541a1e864a8ad5a9a7cfd1 Signed-off-by: Jiří Pinkava Reviewed-on: http://openocd.zylin.com/3733 Tested-by: jenkins Reviewed-by: Fredrik Hederstierna Reviewed-by: Michael Dietz Reviewed-by: Freddie Chopin --- src/flash/nor/nrf51.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/src/flash/nor/nrf51.c b/src/flash/nor/nrf51.c index 60f6d3c..a41bc05 100644 --- a/src/flash/nor/nrf51.c +++ b/src/flash/nor/nrf51.c @@ -120,6 +120,7 @@ struct nrf51_info { struct nrf51_device_spec { uint16_t hwid; + const char *part; const char *variant; const char *build_code; unsigned int flash_size_kb; @@ -141,30 +142,35 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = { /* nRF51822 Devices (IC rev 1). */ { .hwid = 0x001D, + .part = "51822", .variant = "QFAA", .build_code = "CA/C0", .flash_size_kb = 256, }, { .hwid = 0x0026, + .part = "51822", .variant = "QFAB", .build_code = "AA", .flash_size_kb = 128, }, { .hwid = 0x0027, + .part = "51822", .variant = "QFAB", .build_code = "A0", .flash_size_kb = 128, }, { .hwid = 0x0020, + .part = "51822", .variant = "CEAA", .build_code = "BA", .flash_size_kb = 256, }, { .hwid = 0x002F, + .part = "51822", .variant = "CEAA", .build_code = "B0", .flash_size_kb = 256, @@ -173,54 +179,63 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = { /* nRF51822 Devices (IC rev 2). */ { .hwid = 0x002A, + .part = "51822", .variant = "QFAA", .build_code = "FA0", .flash_size_kb = 256, }, { .hwid = 0x0044, + .part = "51822", .variant = "QFAA", .build_code = "GC0", .flash_size_kb = 256, }, { .hwid = 0x003C, + .part = "51822", .variant = "QFAA", .build_code = "G0", .flash_size_kb = 256, }, { .hwid = 0x0057, + .part = "51822", .variant = "QFAA", .build_code = "G2", .flash_size_kb = 256, }, { .hwid = 0x0058, + .part = "51822", .variant = "QFAA", .build_code = "G3", .flash_size_kb = 256, }, { .hwid = 0x004C, + .part = "51822", .variant = "QFAB", .build_code = "B0", .flash_size_kb = 128, }, { .hwid = 0x0040, + .part = "51822", .variant = "CEAA", .build_code = "CA0", .flash_size_kb = 256, }, { .hwid = 0x0047, + .part = "51822", .variant = "CEAA", .build_code = "DA0", .flash_size_kb = 256, }, { .hwid = 0x004D, + .part = "51822", .variant = "CEAA", .build_code = "D00", .flash_size_kb = 256, @@ -229,42 +244,49 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = { /* nRF51822 Devices (IC rev 3). */ { .hwid = 0x0072, + .part = "51822", .variant = "QFAA", .build_code = "H0", .flash_size_kb = 256, }, { .hwid = 0x007B, + .part = "51822", .variant = "QFAB", .build_code = "C0", .flash_size_kb = 128, }, { .hwid = 0x0083, + .part = "51822", .variant = "QFAC", .build_code = "A0", .flash_size_kb = 256, }, { .hwid = 0x0084, + .part = "51822", .variant = "QFAC", .build_code = "A1", .flash_size_kb = 256, }, { .hwid = 0x007D, + .part = "51822", .variant = "CDAB", .build_code = "A0", .flash_size_kb = 128, }, { .hwid = 0x0079, + .part = "51822", .variant = "CEAA", .build_code = "E0", .flash_size_kb = 256, }, { .hwid = 0x0087, + .part = "51822", .variant = "CFAC", .build_code = "A0", .flash_size_kb = 256, @@ -273,18 +295,21 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = { /* nRF51422 Devices (IC rev 1). */ { .hwid = 0x001E, + .part = "51422", .variant = "QFAA", .build_code = "CA", .flash_size_kb = 256, }, { .hwid = 0x0024, + .part = "51422", .variant = "QFAA", .build_code = "C0", .flash_size_kb = 256, }, { .hwid = 0x0031, + .part = "51422", .variant = "CEAA", .build_code = "A0A", .flash_size_kb = 256, @@ -293,24 +318,28 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = { /* nRF51422 Devices (IC rev 2). */ { .hwid = 0x002D, + .part = "51422", .variant = "QFAA", .build_code = "DAA", .flash_size_kb = 256, }, { .hwid = 0x002E, + .part = "51422", .variant = "QFAA", .build_code = "E0", .flash_size_kb = 256, }, { .hwid = 0x0061, + .part = "51422", .variant = "QFAB", .build_code = "A00", .flash_size_kb = 128, }, { .hwid = 0x0050, + .part = "51422", .variant = "CEAA", .build_code = "B0", .flash_size_kb = 256, @@ -319,42 +348,49 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = { /* nRF51422 Devices (IC rev 3). */ { .hwid = 0x0073, + .part = "51422", .variant = "QFAA", .build_code = "F0", .flash_size_kb = 256, }, { .hwid = 0x007C, + .part = "51422", .variant = "QFAB", .build_code = "B0", .flash_size_kb = 128, }, { .hwid = 0x0085, + .part = "51422", .variant = "QFAC", .build_code = "A0", .flash_size_kb = 256, }, { .hwid = 0x0086, + .part = "51422", .variant = "QFAC", .build_code = "A1", .flash_size_kb = 256, }, { .hwid = 0x007E, + .part = "51422", .variant = "CDAB", .build_code = "A0", .flash_size_kb = 128, }, { .hwid = 0x007A, + .part = "51422", .variant = "CEAA", .build_code = "C0", .flash_size_kb = 256, }, { .hwid = 0x0088, + .part = "51422", .variant = "CFAC", .build_code = "A0", .flash_size_kb = 256, @@ -365,6 +401,7 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = { in the nRF51 Series Compatibility Matrix V1.0. */ { .hwid = 0x0071, + .part = "51822", .variant = "QFAC", .build_code = "AB", .flash_size_kb = 256, @@ -626,16 +663,18 @@ static int nrf51_probe(struct flash_bank *bank) * bytes of the CONFIGID register */ const struct nrf51_device_spec *spec = NULL; - for (size_t i = 0; i < ARRAY_SIZE(nrf51_known_devices_table); i++) + for (size_t i = 0; i < ARRAY_SIZE(nrf51_known_devices_table); i++) { if (hwid == nrf51_known_devices_table[i].hwid) { spec = &nrf51_known_devices_table[i]; break; } + } if (!chip->bank[0].probed && !chip->bank[1].probed) { if (spec) - LOG_INFO("nRF51822-%s(build code: %s) %ukB Flash", - spec->variant, spec->build_code, spec->flash_size_kb); + LOG_INFO("nRF%s-%s(build code: %s) %ukB Flash", + spec->part, spec->variant, spec->build_code, + spec->flash_size_kb); else LOG_WARNING("Unknown device (HWID 0x%08" PRIx32 ")", hwid); } -- cgit v1.1 From ca19c82d94ae8448520d40b1c4fc3abd44afb857 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Fri, 23 Sep 2016 14:08:21 -0700 Subject: Make OpenOCD build using -Og. With -Og gcc doesn't perform as many optimizations, and as a result warns about some code that it wouldn't otherwise warn about. These fixes all assign values to otherwise uninitialized variables. Change-Id: I9a6ea5eadd73673891ecfec568b8b00d78b596a5 Signed-off-by: Tim Newsome Reviewed-on: http://openocd.zylin.com/3779 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Freddie Chopin --- src/flash/nor/kinetis.c | 2 +- src/flash/nor/niietcm4.c | 6 ++++-- src/flash/nor/xmc4xxx.c | 8 +++----- src/target/xscale.c | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 0b738e2..2e34bcb 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -1340,7 +1340,7 @@ static int kinetis_make_ram_ready(struct target *target) static int kinetis_write_sections(struct flash_bank *bank, const uint8_t *buffer, uint32_t offset, uint32_t count) { - int result; + int result = ERROR_OK; struct kinetis_flash_bank *kinfo = bank->driver_priv; uint8_t *buffer_aligned = NULL; /* diff --git a/src/flash/nor/niietcm4.c b/src/flash/nor/niietcm4.c index 9238222..4a849fd 100644 --- a/src/flash/nor/niietcm4.c +++ b/src/flash/nor/niietcm4.c @@ -230,7 +230,8 @@ static int niietcm4_uopstatus_check(struct flash_bank *bank) static int niietcm4_dump_uflash_page(struct flash_bank *bank, uint32_t *dump, int page_num, int mem_type) { struct target *target = bank->target; - int i, retval; + int i; + int retval = ERROR_OK; uint32_t uflash_cmd; if (mem_type == INFO_MEM_TYPE) @@ -265,7 +266,8 @@ static int niietcm4_dump_uflash_page(struct flash_bank *bank, uint32_t *dump, in static int niietcm4_load_uflash_page(struct flash_bank *bank, uint32_t *dump, int page_num, int mem_type) { struct target *target = bank->target; - int i, retval; + int i; + int retval = ERROR_OK; uint32_t uflash_cmd; if (mem_type == INFO_MEM_TYPE) diff --git a/src/flash/nor/xmc4xxx.c b/src/flash/nor/xmc4xxx.c index f396ca3..b761951 100644 --- a/src/flash/nor/xmc4xxx.c +++ b/src/flash/nor/xmc4xxx.c @@ -998,11 +998,6 @@ static int xmc4xxx_flash_unprotect(struct flash_bank *bank, int32_t level) uint32_t addr; int res; - if ((level < 0) || (level > 1)) { - LOG_ERROR("Invalid user level. Must be 0-1"); - return ERROR_FAIL; - } - switch (level) { case 0: addr = UCB0_BASE; @@ -1010,6 +1005,9 @@ static int xmc4xxx_flash_unprotect(struct flash_bank *bank, int32_t level) case 1: addr = UCB1_BASE; break; + default: + LOG_ERROR("Invalid user level. Must be 0-1"); + return ERROR_FAIL; } res = xmc4xxx_erase_sector(bank, addr, true); diff --git a/src/target/xscale.c b/src/target/xscale.c index 3d5abdf..140ea58 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -2667,7 +2667,7 @@ static int xscale_analyze_trace(struct target *target, struct command_context *c struct xscale_common *xscale = target_to_xscale(target); struct xscale_trace_data *trace_data = xscale->trace.data; int i, retval; - uint32_t breakpoint_pc; + uint32_t breakpoint_pc = 0; struct arm_instruction instruction; uint32_t current_pc = 0;/* initialized when address determined */ -- cgit v1.1 From 058ed7a43f3253225649a552b09bb1f066ce467d Mon Sep 17 00:00:00 2001 From: Rick Foos Date: Mon, 25 Jul 2016 15:02:19 -0500 Subject: tcl/board: Add board configuration for nRF51-DK, and nRF52-DK. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both boards use SEGGER interface. nRF52 flash driver is in change 3511. The board files were needed for transport select to SWD. The default jtag transport didn't failover to SWD. Change-Id: Id9c72aa88eeeb6a4e1999ee182f5284dbe535c05 Signed-off-by: Rick Foos Reviewed-on: http://openocd.zylin.com/3600 Tested-by: jenkins Reviewed-by: Fredrik Hederstierna Reviewed-by: Michael Dietz Reviewed-by: Jiří Pinkava Reviewed-by: Freddie Chopin --- tcl/board/nordic_nrf51_dk.cfg | 9 +++++++++ tcl/board/nordic_nrf52_dk.cfg | 9 +++++++++ 2 files changed, 18 insertions(+) create mode 100644 tcl/board/nordic_nrf51_dk.cfg create mode 100644 tcl/board/nordic_nrf52_dk.cfg diff --git a/tcl/board/nordic_nrf51_dk.cfg b/tcl/board/nordic_nrf51_dk.cfg new file mode 100644 index 0000000..96f5471 --- /dev/null +++ b/tcl/board/nordic_nrf51_dk.cfg @@ -0,0 +1,9 @@ +# +# Nordic Semiconductor NRF51 Development Kit (nRF6824) +# + +source [find interface/jlink.cfg] + +transport select swd + +source [find target/nrf51.cfg] diff --git a/tcl/board/nordic_nrf52_dk.cfg b/tcl/board/nordic_nrf52_dk.cfg new file mode 100644 index 0000000..9f52866 --- /dev/null +++ b/tcl/board/nordic_nrf52_dk.cfg @@ -0,0 +1,9 @@ +# +# Nordic Semiconductor NRF52 Development Kit (nRF52832) +# + +source [find interface/jlink.cfg] + +transport select swd + +source [find target/nrf52.cfg] -- cgit v1.1 From d3445cd146f8efa6f5bdbd636f51e247ec7de766 Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Fri, 11 Mar 2016 22:16:04 +0100 Subject: cfg: Don't check BS TAP IDCODE in STM32 configs Instead of updating these regularly we can just accept any IDCODE for the boundary scan TAP. The only downside might be that it's not immediately obvious if you source a config for the wrong type of STM32. Change-Id: I96d4d81699a491b3a46de3f0d3fd078ffddad4e4 Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3385 Tested-by: jenkins --- tcl/target/stm32f1x.cfg | 31 +------------------------------ tcl/target/stm32f2x.cfg | 11 +---------- tcl/target/stm32f3x.cfg | 21 +-------------------- tcl/target/stm32f4x.cfg | 33 +-------------------------------- tcl/target/stm32f7x.cfg | 11 +---------- tcl/target/stm32l1.cfg | 22 +--------------------- tcl/target/stm32l4x.cfg | 11 +---------- 7 files changed, 7 insertions(+), 133 deletions(-) diff --git a/tcl/target/stm32f1x.cfg b/tcl/target/stm32f1x.cfg index bd02e95..5a4c2fa 100644 --- a/tcl/target/stm32f1x.cfg +++ b/tcl/target/stm32f1x.cfg @@ -37,37 +37,8 @@ if { [info exists CPUTAPID] } { swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID -if { [info exists BSTAPID] } { - # FIXME this never gets used to override defaults... - set _BSTAPID $BSTAPID -} else { - # See STM Document RM0008 - # Section 29.6.2 - # Low density devices, Rev A - set _BSTAPID1 0x06412041 - # Medium density devices, Rev A - set _BSTAPID2 0x06410041 - # Medium density devices, Rev B and Rev Z - set _BSTAPID3 0x16410041 - set _BSTAPID4 0x06420041 - # High density devices, Rev A - set _BSTAPID5 0x06414041 - # Connectivity line devices, Rev A and Rev Z - set _BSTAPID6 0x06418041 - # XL line devices, Rev A - set _BSTAPID7 0x06430041 - # VL line devices, Rev A and Z In medium-density and high-density value line devices - set _BSTAPID8 0x06420041 - # VL line devices, Rev A - set _BSTAPID9 0x06428041 -} - if {[using_jtag]} { - swj_newdap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID1 \ - -expected-id $_BSTAPID2 -expected-id $_BSTAPID3 \ - -expected-id $_BSTAPID4 -expected-id $_BSTAPID5 \ - -expected-id $_BSTAPID6 -expected-id $_BSTAPID7 \ - -expected-id $_BSTAPID8 -expected-id $_BSTAPID9 + jtag newtap $_CHIPNAME bs -irlen 5 } set _TARGETNAME $_CHIPNAME.cpu diff --git a/tcl/target/stm32f2x.cfg b/tcl/target/stm32f2x.cfg index 0e734de..44955d4 100644 --- a/tcl/target/stm32f2x.cfg +++ b/tcl/target/stm32f2x.cfg @@ -50,17 +50,8 @@ if { [info exists CPUTAPID] } { swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID -if { [info exists BSTAPID] } { - set _BSTAPID $BSTAPID -} else { - # See STM Document RM0033 - # Section 32.6.2 - # - set _BSTAPID 0x06411041 -} - if {[using_jtag]} { - swj_newdap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID + jtag newtap $_CHIPNAME bs -irlen 5 } set _TARGETNAME $_CHIPNAME.cpu diff --git a/tcl/target/stm32f3x.cfg b/tcl/target/stm32f3x.cfg index f3ea40b..0c8919f 100644 --- a/tcl/target/stm32f3x.cfg +++ b/tcl/target/stm32f3x.cfg @@ -50,27 +50,8 @@ if { [info exists CPUTAPID] } { swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID -if { [info exists BSTAPID] } { - set _BSTAPID $BSTAPID -} else { - # STM Document RM0316 rev 5 for STM32F302/303 B/C size - set _BSTAPID1 0x06422041 - # STM Document RM0313 rev 3 for STM32F37x - set _BSTAPID2 0x06432041 - # STM Document RM364 rev 1 for STM32F334 - set _BSTAPID3 0x06438041 - # STM Document RM316 rev 5 for STM32F303 6/8 size - # STM Document RM365 rev 3 for STM32F302 6/8 size - # STM Document RM366 rev 2 for STM32F301 6/8 size - set _BSTAPID4 0x06439041 - # STM Document RM016 rev 5 for STM32F303 D/E size - set _BSTAPID5 0x06446041 -} - if {[using_jtag]} { - swj_newdap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID1 \ - -expected-id $_BSTAPID2 -expected-id $_BSTAPID3 \ - -expected-id $_BSTAPID4 -expected-id $_BSTAPID5 + jtag newtap $_CHIPNAME bs -irlen 5 } set _TARGETNAME $_CHIPNAME.cpu diff --git a/tcl/target/stm32f4x.cfg b/tcl/target/stm32f4x.cfg index 2d5cf37..7a0af9f 100644 --- a/tcl/target/stm32f4x.cfg +++ b/tcl/target/stm32f4x.cfg @@ -37,39 +37,8 @@ if { [info exists CPUTAPID] } { swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID -if { [info exists BSTAPID] } { - set _BSTAPID $BSTAPID -} else { - # See STM Document RM0090 - # Section 38.6.2 - # STM32F405xx/07xx and STM32F415xx/17xx - set _BSTAPID1 0x06413041 - # STM32F42xxx and STM32F43xxx - set _BSTAPID2 0x06419041 - # See STM Document RM0368 (Rev. 3) - # STM32F401B/C - set _BSTAPID3 0x06423041 - # STM32F401D/E - set _BSTAPID4 0x06433041 - # See STM Document RM0383 (Rev 2) - # STM32F411 - set _BSTAPID5 0x06431041 - # See STM Document RM0386 - # STM32F469 - set _BSTAPID6 0x06434041 - # See STM Document RM0401 - # STM32F410 - set _BSTAPID7 0x06458041 - # STM32F412 - set _BSTAPID8 0x06441041 -} - if {[using_jtag]} { - swj_newdap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID1 \ - -expected-id $_BSTAPID2 -expected-id $_BSTAPID3 \ - -expected-id $_BSTAPID4 -expected-id $_BSTAPID5 \ - -expected-id $_BSTAPID6 -expected-id $_BSTAPID7 \ - -expected-id $_BSTAPID8 + jtag newtap $_CHIPNAME bs -irlen 5 } set _TARGETNAME $_CHIPNAME.cpu diff --git a/tcl/target/stm32f7x.cfg b/tcl/target/stm32f7x.cfg index 05470d4..4065e2a 100755 --- a/tcl/target/stm32f7x.cfg +++ b/tcl/target/stm32f7x.cfg @@ -37,17 +37,8 @@ if { [info exists CPUTAPID] } { swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID -if { [info exists BSTAPID] } { - set _BSTAPID $BSTAPID -} else { - # See STM Document RM0385 - # Section 40.6.1 - # STM32F75xxG - set _BSTAPID1 0x06449041 -} - if {[using_jtag]} { - swj_newdap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID1 + jtag newtap $_CHIPNAME bs -irlen 5 } set _TARGETNAME $_CHIPNAME.cpu diff --git a/tcl/target/stm32l1.cfg b/tcl/target/stm32l1.cfg index 790c495..a8d6fdf 100644 --- a/tcl/target/stm32l1.cfg +++ b/tcl/target/stm32l1.cfg @@ -46,28 +46,8 @@ if { [info exists CPUTAPID] } { swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID -if { [info exists BSTAPID] } { - # FIXME this never gets used to override defaults... - set _BSTAPID $BSTAPID -} else { - # See STM Document RM0038 Section 30.6.1 Rev. 12 - - # Low and medium density - set _BSTAPID1 0x06416041 - # Cat.2 device (medium+ density) - set _BSTAPID2 0x06429041 - # Cat.3 device (medium+ density) - set _BSTAPID3 0x06427041 - # Cat.4 device, STM32L15/6xxD or Cat.3 device, some STM32L15/6xxC-A models - set _BSTAPID4 0x06436041 - # Cat.5 device (high density), STM32L15/6xxE - set _BSTAPID5 0x06437041 -} - if {[using_jtag]} { - swj_newdap $_CHIPNAME bs -irlen 5 \ - -expected-id $_BSTAPID1 -expected-id $_BSTAPID2 -expected-id $_BSTAPID3 \ - -expected-id $_BSTAPID4 -expected-id $_BSTAPID5 + jtag newtap $_CHIPNAME bs -irlen 5 } set _TARGETNAME $_CHIPNAME.cpu diff --git a/tcl/target/stm32l4x.cfg b/tcl/target/stm32l4x.cfg index dec0069..9cad7c4 100644 --- a/tcl/target/stm32l4x.cfg +++ b/tcl/target/stm32l4x.cfg @@ -37,17 +37,8 @@ if { [info exists CPUTAPID] } { swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID -if { [info exists BSTAPID] } { - set _BSTAPID $BSTAPID -} else { - # See STM Document RM0351 - # Section 44.6.3 - # STM32L4X6 - set _BSTAPID1 0x06415041 -} - if {[using_jtag]} { - swj_newdap $_CHIPNAME bs -irlen 5 -expected-id $_BSTAPID1 + jtag newtap $_CHIPNAME bs -irlen 5 } set _TARGETNAME $_CHIPNAME.cpu -- cgit v1.1 From b10037a0b784cab94e21b37c976ad2b5174d52ae Mon Sep 17 00:00:00 2001 From: HarishKumar Date: Tue, 9 Dec 2014 19:38:08 +0530 Subject: Tcl commands: Fix improper return status in flash commands and load_image. Nand write command : nand_fileio_cleanup() always returns ERROR_OK. Due to this, handle_nand_write_command() retuns ERROR_OK in the case of nand failure. ERROR_FAIL should be returned. Flash erase_sector command : handle_flash_erase_command() always returns ERROR_OK even if the erase functionality of actual driver implementation fails. retval value should be returned. Flash write_bank command : handle_flash_write_bank_command() returns ERROR_OK even if fileio_open() and fileio_read fails. ERROR_FAIL should be returned. Load_image command : handle_load_image_command() retuns ERROR_OK even if image_open() fails. ERROR_FAIL should be returned. When the buffer is null, breaking the loop without setting retval = ERROR_FAIL would cause load_image to return ERROR_OK. Change-Id: Ice32f6036971ab5e8e4dd65edf54b394b001c80c Signed-off-by: HarishKumar Reviewed-on: http://openocd.zylin.com/2431 Reviewed-by: Andreas Fritiofson Tested-by: jenkins --- src/flash/nand/tcl.c | 6 ++++-- src/flash/nor/tcl.c | 6 +++--- src/target/target.c | 3 ++- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/flash/nand/tcl.c b/src/flash/nand/tcl.c index cbdeda5..d9738c5 100644 --- a/src/flash/nand/tcl.c +++ b/src/flash/nand/tcl.c @@ -254,7 +254,8 @@ COMMAND_HANDLER(handle_nand_write_command) int bytes_read = nand_fileio_read(nand, &s); if (bytes_read <= 0) { command_print(CMD_CTX, "error while reading file"); - return nand_fileio_cleanup(&s); + nand_fileio_cleanup(&s); + return ERROR_FAIL; } s.size -= bytes_read; @@ -264,7 +265,8 @@ COMMAND_HANDLER(handle_nand_write_command) command_print(CMD_CTX, "failed writing file %s " "to NAND flash %s at offset 0x%8.8" PRIx32, CMD_ARGV[1], CMD_ARGV[0], s.address); - return nand_fileio_cleanup(&s); + nand_fileio_cleanup(&s); + return retval; } s.address += s.page_size; } diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index d62fa74..6936822 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -341,7 +341,7 @@ COMMAND_HANDLER(handle_flash_erase_command) "in %fs", first, last, p->bank_number, duration_elapsed(&bench)); } - return ERROR_OK; + return retval; } COMMAND_HANDLER(handle_flash_protect_command) @@ -600,7 +600,7 @@ COMMAND_HANDLER(handle_flash_write_bank_command) COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); if (fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY) != ERROR_OK) - return ERROR_OK; + return ERROR_FAIL; size_t filesize; retval = fileio_size(fileio, &filesize); @@ -619,7 +619,7 @@ COMMAND_HANDLER(handle_flash_write_bank_command) if (fileio_read(fileio, filesize, buffer, &buf_cnt) != ERROR_OK) { free(buffer); fileio_close(fileio); - return ERROR_OK; + return ERROR_FAIL; } retval = flash_driver_write(p, buffer, offset, buf_cnt); diff --git a/src/target/target.c b/src/target/target.c index 9fc9d20..c23590e 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3166,7 +3166,7 @@ COMMAND_HANDLER(handle_load_image_command) duration_start(&bench); if (image_open(&image, CMD_ARGV[0], (CMD_ARGC >= 3) ? CMD_ARGV[2] : NULL) != ERROR_OK) - return ERROR_OK; + return ERROR_FAIL; image_size = 0x0; retval = ERROR_OK; @@ -3176,6 +3176,7 @@ COMMAND_HANDLER(handle_load_image_command) command_print(CMD_CTX, "error allocating buffer for section (%d bytes)", (int)(image.sections[i].size)); + retval = ERROR_FAIL; break; } -- cgit v1.1 From d1bdcdcc8d429a2ce06fb35f82a67b2487b72ec3 Mon Sep 17 00:00:00 2001 From: Andrey Smirnov Date: Sat, 8 Aug 2015 15:18:16 -0700 Subject: semihosting armv7a: Add support for ARMv7-A Add semihosting support for ARMv7-A based processors. Tested with custom Vybrid VF610 based board and Pandaboard ES (Rev. B1) board (Cortex-A9). Change-Id: I6b896a61c1c6a1c5dcf89de834486f82dd6c80a2 Signed-off-by: Andrey Smirnov Signed-off-by: Tsung-Han Lin Reviewed-on: http://openocd.zylin.com/2908 Reviewed-by: Andreas Fritiofson Tested-by: jenkins --- src/target/arm_semihosting.c | 31 ++++++++++++++++++++++++++++--- src/target/armv7a.c | 29 +++++++++++++++++++++++++++++ src/target/armv7a.h | 13 +++++++++++++ src/target/cortex_a.c | 20 +++++++++++++++++++- 4 files changed, 89 insertions(+), 4 deletions(-) diff --git a/src/target/arm_semihosting.c b/src/target/arm_semihosting.c index 2fd6580..63335ff 100644 --- a/src/target/arm_semihosting.c +++ b/src/target/arm_semihosting.c @@ -39,8 +39,10 @@ #include "armv4_5.h" #include "arm7_9_common.h" #include "armv7m.h" +#include "armv7a.h" #include "cortex_m.h" #include "register.h" +#include "arm_opcodes.h" #include "arm_semihosting.h" #include #include @@ -415,7 +417,8 @@ static int do_semihosting(struct target *target) /* REVISIT this looks wrong ... ARM11 and Cortex-A8 * should work this way at least sometimes. */ - if (is_arm7_9(target_to_arm7_9(target))) { + if (is_arm7_9(target_to_arm7_9(target)) || + is_armv7a(target_to_armv7a(target))) { uint32_t spsr; /* return value in R0 */ @@ -468,20 +471,42 @@ static int do_semihosting(struct target *target) int arm_semihosting(struct target *target, int *retval) { struct arm *arm = target_to_arm(target); + struct armv7a_common *armv7a = target_to_armv7a(target); uint32_t pc, lr, spsr; struct reg *r; if (!arm->is_semihosting) return 0; - if (is_arm7_9(target_to_arm7_9(target))) { + if (is_arm7_9(target_to_arm7_9(target)) || + is_armv7a(armv7a)) { + uint32_t vbar = 0x00000000; + if (arm->core_mode != ARM_MODE_SVC) return 0; + if (is_armv7a(armv7a)) { + struct arm_dpm *dpm = armv7a->arm.dpm; + + *retval = dpm->prepare(dpm); + if (*retval == ERROR_OK) { + *retval = dpm->instr_read_data_r0(dpm, + ARMV4_5_MRC(15, 0, 0, 12, 0, 0), + &vbar); + + dpm->finish(dpm); + + if (*retval != ERROR_OK) + return 1; + } else { + return 1; + } + } + /* Check for PC == 0x00000008 or 0xffff0008: Supervisor Call vector. */ r = arm->pc; pc = buf_get_u32(r->value, 0, 32); - if (pc != 0x00000008 && pc != 0xffff0008) + if (pc != (vbar + 0x00000008) && pc != 0xffff0008) return 0; r = arm_reg_current(arm, 14); diff --git a/src/target/armv7a.c b/src/target/armv7a.c index 37eb1b5..6021def 100644 --- a/src/target/armv7a.c +++ b/src/target/armv7a.c @@ -679,11 +679,40 @@ done: } +static int armv7a_setup_semihosting(struct target *target, int enable) +{ + struct armv7a_common *armv7a = target_to_armv7a(target); + uint32_t vcr; + int ret; + + ret = mem_ap_read_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_VCR, + &vcr); + if (ret < 0) { + LOG_ERROR("Failed to read VCR register\n"); + return ret; + } + + if (enable) + vcr |= DBG_VCR_SVC_MASK; + else + vcr &= ~DBG_VCR_SVC_MASK; + + ret = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_VCR, + vcr); + if (ret < 0) + LOG_ERROR("Failed to write VCR register\n"); + + return ret; +} + int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a) { struct arm *arm = &armv7a->arm; arm->arch_info = armv7a; target->arch_info = &armv7a->arm; + arm->setup_semihosting = armv7a_setup_semihosting; /* target is useful in all function arm v4 5 compatible */ armv7a->arm.target = target; armv7a->arm.common_magic = ARM_COMMON_MAGIC; diff --git a/src/target/armv7a.h b/src/target/armv7a.h index 6461ba9..6a62f72 100644 --- a/src/target/armv7a.h +++ b/src/target/armv7a.h @@ -134,6 +134,12 @@ target_to_armv7a(struct target *target) return container_of(target->arch_info, struct armv7a_common, arm); } +static inline bool is_armv7a(struct armv7a_common *armv7a) +{ + return armv7a->common_magic == ARMV7_COMMON_MAGIC; +} + + /* register offsets from armv7a.debug_base */ /* See ARMv7a arch spec section C10.2 */ @@ -172,6 +178,13 @@ target_to_armv7a(struct target *target) /* See ARMv7a arch spec section C10.8 */ #define CPUDBG_AUTHSTATUS 0xFB8 +/* Masks for Vector Catch register */ +#define DBG_VCR_FIQ_MASK ((1 << 31) | (1 << 7)) +#define DBG_VCR_IRQ_MASK ((1 << 30) | (1 << 6)) +#define DBG_VCR_DATA_ABORT_MASK ((1 << 28) | (1 << 4)) +#define DBG_VCR_PREF_ABORT_MASK ((1 << 27) | (1 << 3)) +#define DBG_VCR_SVC_MASK ((1 << 26) | (1 << 2)) + int armv7a_arch_state(struct target *target); int armv7a_identify_cache(struct target *target); int armv7a_init_arch_info(struct target *target, struct armv7a_common *armv7a); diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index d1590f6..0a689ea 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -53,6 +53,7 @@ #include "target_request.h" #include "target_type.h" #include "arm_opcodes.h" +#include "arm_semihosting.h" #include static int cortex_a_poll(struct target *target); @@ -915,6 +916,10 @@ static int cortex_a_poll(struct target *target) if (retval != ERROR_OK) return retval; } + + if (arm_semihosting(target, &retval) != 0) + return retval; + target_call_event_callbacks(target, TARGET_EVENT_HALTED); } @@ -1201,7 +1206,7 @@ static int cortex_a_resume(struct target *target, int current, static int cortex_a_debug_entry(struct target *target) { int i; - uint32_t regfile[16], cpsr, dscr; + uint32_t regfile[16], cpsr, spsr, dscr; int retval = ERROR_OK; struct working_area *regfile_working_area = NULL; struct cortex_a_common *cortex_a = target_to_cortex_a(target); @@ -1250,6 +1255,7 @@ static int cortex_a_debug_entry(struct target *target) if (cortex_a->fast_reg_read) target_alloc_working_area(target, 64, ®file_working_area); + /* First load register acessible through core debug port*/ if (!regfile_working_area) retval = arm_dpm_read_current_registers(&armv7a->dpm); @@ -1294,6 +1300,17 @@ static int cortex_a_debug_entry(struct target *target) reg->dirty = reg->valid; } + /* read Saved PSR */ + retval = cortex_a_dap_read_coreregister_u32(target, &spsr, 17); + /* store current spsr */ + if (retval != ERROR_OK) + return retval; + + reg = arm->spsr; + buf_set_u32(reg->value, 0, 32, spsr); + reg->valid = 1; + reg->dirty = 0; + #if 0 /* TODO, Move this */ uint32_t cp15_control_register, cp15_cacr, cp15_nacr; @@ -2953,6 +2970,7 @@ static int cortex_a_examine_first(struct target *target) struct cortex_a_common *cortex_a = target_to_cortex_a(target); struct armv7a_common *armv7a = &cortex_a->armv7a_common; struct adiv5_dap *swjdp = armv7a->arm.dap; + int i; int retval = ERROR_OK; uint32_t didr, ctypr, ttypr, cpuid, dbg_osreg; -- cgit v1.1 From 75c3f4a25c9a1250ecba2eb40dbe1c4f16087184 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 30 Mar 2016 11:19:16 +0200 Subject: AM335x: Disable watchdog on 'reset halt' At least on my (phyCORE-AM335X) system, the AM335x watchdog needs to be disabled to use OpenOCD for more than 6.5 seconds after reset. Change-Id: I3d883a9f572b0ccb92f9864853a00c372e39d7f2 Signed-off-by: Harald Welte Reviewed-on: http://openocd.zylin.com/3391 Tested-by: jenkins Reviewed-by: Tom Rini Reviewed-by: Paul Fertser --- tcl/target/am335x.cfg | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tcl/target/am335x.cfg b/tcl/target/am335x.cfg index 7409615..3ca196b 100644 --- a/tcl/target/am335x.cfg +++ b/tcl/target/am335x.cfg @@ -76,3 +76,35 @@ target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.dap -dbgbase 0x80 # SRAM: 64K at 0x4030.0000; use the first 16K $_TARGETNAME configure -work-area-phys 0x40300000 -work-area-size 0x4000 + + +# when putting the target into 'reset halt', we need to disable the watchdog as +# it would otherwise trigger while we're in JTAG +# FIXME: unify with target/am437x.cfg +source [find mem_helper.tcl] +set WDT1_BASE_ADDR 0x44e35000 +set WDT1_W_PEND_WSPR [expr $WDT1_BASE_ADDR + 0x0034] +set WDT1_WSPR [expr $WDT1_BASE_ADDR + 0x0048] +proc disable_watchdog { } { + global WDT1_WSPR + global WDT1_W_PEND_WSPR + global _TARGETNAME + + set curstate [$_TARGETNAME curstate] + + if { [string compare $curstate halted] == 0 } { + set WDT_DISABLE_SEQ1 0xaaaa + set WDT_DISABLE_SEQ2 0x5555 + + mww phys $WDT1_WSPR $WDT_DISABLE_SEQ1 + + # Empty body to make sure this executes as fast as possible. + # We don't want any delays here otherwise romcode might start + # executing and end up changing state of certain IPs. + while { [expr [mrw $WDT1_W_PEND_WSPR] & 0x10] } { } + + mww phys $WDT1_WSPR $WDT_DISABLE_SEQ2 + while { [expr [mrw $WDT1_W_PEND_WSPR] & 0x10] } { } + } +} +$_TARGETNAME configure -event reset-end { disable_watchdog } -- cgit v1.1 From 009943010420e49c2632769e9e21502b8166ba41 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 5 Aug 2016 21:50:33 +0200 Subject: cortex_a/r/m: fix handling of un-examined cores On multi-core systems, with some cores in power-down state, examination will fail for these cores. Make sure assert- and deassert_reset functions don't crash due to uninitialized variables. Change-Id: I472f8d19af2cd3c770c05f3e57a31b35a863b687 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3552 Tested-by: jenkins Reviewed-by: Jiri Kastner Reviewed-by: Tomas Vanek --- src/target/cortex_a.c | 26 +++++++++++++++++--------- src/target/cortex_m.c | 15 ++++++++++++++- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 0a689ea..256edbc 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -853,7 +853,8 @@ static int cortex_a_halt_smp(struct target *target) head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; - if ((curr != target) && (curr->state != TARGET_HALTED)) + if ((curr != target) && (curr->state != TARGET_HALTED) + && target_was_examined(curr)) retval += cortex_a_halt(curr); head = head->next; } @@ -1156,7 +1157,8 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints) head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; - if ((curr != target) && (curr->state != TARGET_RUNNING)) { + if ((curr != target) && (curr->state != TARGET_RUNNING) + && target_was_examined(curr)) { /* resume current address , not in step mode */ retval += cortex_a_internal_restore(curr, 1, &address, handle_breakpoints, 0); @@ -1936,7 +1938,8 @@ static int cortex_a_assert_reset(struct target *target) } /* registers are now invalid */ - register_cache_invalidate(armv7a->arm.core_cache); + if (target_was_examined(target)) + register_cache_invalidate(armv7a->arm.core_cache); target->state = TARGET_RESET; @@ -1952,17 +1955,22 @@ static int cortex_a_deassert_reset(struct target *target) /* be certain SRST is off */ jtag_add_reset(0, 0); - retval = cortex_a_poll(target); - if (retval != ERROR_OK) - return retval; + if (target_was_examined(target)) { + retval = cortex_a_poll(target); + if (retval != ERROR_OK) + return retval; + } if (target->reset_halt) { if (target->state != TARGET_HALTED) { LOG_WARNING("%s: ran after reset and before halt ...", target_name(target)); - retval = target_halt(target); - if (retval != ERROR_OK) - return retval; + if (target_was_examined(target)) { + retval = target_halt(target); + if (retval != ERROR_OK) + return retval; + } else + target->state = TARGET_UNKNOWN; } } diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 4566e2e..4270f8f 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -981,6 +981,18 @@ static int cortex_m_assert_reset(struct target *target) bool srst_asserted = false; + if (!target_was_examined(target)) { + if (jtag_reset_config & RESET_HAS_SRST) { + adapter_assert_reset(); + if (target->reset_halt) + LOG_ERROR("Target not examined, will not halt after reset!"); + return ERROR_OK; + } else { + LOG_ERROR("Target not examined, reset NOT asserted!"); + return ERROR_FAIL; + } + } + if ((jtag_reset_config & RESET_HAS_SRST) && (jtag_reset_config & RESET_SRST_NO_GATING)) { adapter_assert_reset(); @@ -1101,7 +1113,8 @@ static int cortex_m_deassert_reset(struct target *target) enum reset_types jtag_reset_config = jtag_get_reset_config(); if ((jtag_reset_config & RESET_HAS_SRST) && - !(jtag_reset_config & RESET_SRST_NO_GATING)) { + !(jtag_reset_config & RESET_SRST_NO_GATING) && + target_was_examined(target)) { int retval = dap_dp_init(armv7m->debug_ap->dap); if (retval != ERROR_OK) { LOG_ERROR("DP initialisation failed"); -- cgit v1.1 From 22b4a0f40da200563a32e5bab86aceecf486ddd3 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 22 Jul 2016 13:19:19 +0200 Subject: flash Kinetis: longword programming changed to flash_async_algorithm Change-Id: I9c40acfad37760c3dab454f2432817b2d420792d Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3563 Reviewed-by: Steven Stallion Tested-by: jenkins Reviewed-by: Freddie Chopin --- contrib/loaders/flash/kinetis/Makefile | 19 ++++ contrib/loaders/flash/kinetis/kinetis_flash.inc | 6 ++ contrib/loaders/flash/kinetis/kinetis_flash.s | 101 ++++++++++++++++++ src/flash/nor/kinetis.c | 131 +++++++----------------- 4 files changed, 161 insertions(+), 96 deletions(-) create mode 100644 contrib/loaders/flash/kinetis/Makefile create mode 100644 contrib/loaders/flash/kinetis/kinetis_flash.inc create mode 100644 contrib/loaders/flash/kinetis/kinetis_flash.s diff --git a/contrib/loaders/flash/kinetis/Makefile b/contrib/loaders/flash/kinetis/Makefile new file mode 100644 index 0000000..b240f53 --- /dev/null +++ b/contrib/loaders/flash/kinetis/Makefile @@ -0,0 +1,19 @@ +BIN2C = ../../../../src/helper/bin2char.sh + +CROSS_COMPILE ?= arm-none-eabi- +AS = $(CROSS_COMPILE)as +OBJCOPY = $(CROSS_COMPILE)objcopy + +all: kinetis_flash.inc + +%.elf: %.s + $(AS) $< -o $@ + +%.bin: %.elf + $(OBJCOPY) -Obinary $< $@ + +%.inc: %.bin + $(BIN2C) < $< > $@ + +clean: + -rm -f *.elf *.bin *.inc diff --git a/contrib/loaders/flash/kinetis/kinetis_flash.inc b/contrib/loaders/flash/kinetis/kinetis_flash.inc new file mode 100644 index 0000000..c93797b --- /dev/null +++ b/contrib/loaders/flash/kinetis/kinetis_flash.inc @@ -0,0 +1,6 @@ +/* Autogenerated with ../../../../src/helper/bin2char.sh */ +0x16,0x68,0x00,0x2e,0x1f,0xd0,0x55,0x68,0xb5,0x42,0xf9,0xd0,0x60,0x60,0x06,0x27, +0xe7,0x71,0x2f,0x68,0xa7,0x60,0x80,0x27,0x27,0x70,0x04,0x35,0x9d,0x42,0x01,0xd3, +0x15,0x1c,0x08,0x35,0x55,0x60,0x16,0x68,0x00,0x2e,0x0c,0xd0,0x26,0x78,0x3e,0x42, +0xf9,0xd0,0x70,0x27,0x3e,0x42,0x04,0xd1,0x04,0x30,0x01,0x39,0x00,0x29,0xdf,0xd1, +0x01,0xe0,0x00,0x25,0x55,0x60,0x00,0xbe, diff --git a/contrib/loaders/flash/kinetis/kinetis_flash.s b/contrib/loaders/flash/kinetis/kinetis_flash.s new file mode 100644 index 0000000..c8e6e05 --- /dev/null +++ b/contrib/loaders/flash/kinetis/kinetis_flash.s @@ -0,0 +1,101 @@ +/*************************************************************************** + * Copyright (C) 2015 by Ivan Meleca * + * ivan@artekit.eu * + * * + * Copyright (C) 2016 by Tomas Vanek * + * vanekt@fbl.cz * + * * + * 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. * + ***************************************************************************/ + + /* Params: + * r0 = flash destination address in/out + * r1 = longword count + * r2 = workarea start address + * r3 = workarea end address + * r4 = FTFx base + */ + + .text + .cpu cortex-m0plus + .code 16 + .thumb_func + + .align 2 + + /* r5 = rp + * r6 = wp, tmp + * r7 = tmp + */ + + /* old longword algo: 6.680 KiB/s @ adapter_khz 2000 + * this async algo: 19.808 KiB/s @ adapter_khz 2000 + */ + +FTFx_FSTAT = 0 +FTFx_FCCOB3 = 4 +FTFx_FCCOB0 = 7 +FTFx_FCCOB7 = 8 + +wait_fifo: + ldr r6, [r2, #0] /* read wp */ + cmp r6, #0 /* abort if wp == 0 */ + beq exit + + ldr r5, [r2, #4] /* read rp */ + cmp r5, r6 /* wait until rp != wp */ + beq wait_fifo + + str r0, [r4, #FTFx_FCCOB3] /* set flash address */ + mov r7, #6 + strb r7, [r4, #FTFx_FCCOB0] /* flash command */ + + ldr r7, [r5] /* set longword data = *rp */ + str r7, [r4, #FTFx_FCCOB7] + + mov r7, #128 + strb r7, [r4, #FTFx_FSTAT] + + add r5, #4 /* rp += 4 */ + cmp r5, r3 /* Wrap? */ + bcc no_wrap + mov r5, r2 + add r5, #8 + +no_wrap: + str r5, [r2, #4] /* Store rp */ + +wait_ccif: + ldr r6, [r2, #0] /* read wp */ + cmp r6, #0 /* abort if wp == 0 */ + beq exit + + ldrb r6, [r4, #FTFx_FSTAT] + tst r6, r7 + beq wait_ccif + + mov r7, #0x70 + tst r6, r7 + bne error + + add r0, #4 /* flash address += 4, do not increment before err check */ + + sub r1, #1 /* word_count-- */ + cmp r1, #0 + bne wait_fifo + b exit + +error: + mov r5, #0 + str r5, [r2, #4] /* set rp = 0 on error */ + +exit: + bkpt #0 diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 2e34bcb..b640b3f 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -865,65 +865,7 @@ static int kinetis_ftfx_prepare(struct target *target) /* Kinetis Program-LongWord Microcodes */ static const uint8_t kinetis_flash_write_code[] = { - /* Params: - * r0 - workarea buffer - * r1 - target address - * r2 - wordcount - * Clobbered: - * r4 - tmp - * r5 - tmp - * r6 - tmp - * r7 - tmp - */ - - /* .L1: */ - /* for(register uint32_t i=0;idriver_priv; uint32_t address = kinfo->prog_base + offset; - struct reg_param reg_params[3]; + uint32_t end_address; + struct reg_param reg_params[5]; struct armv7m_algorithm armv7m_info; - int retval = ERROR_OK; - - /* Params: - * r0 - workarea buffer - * r1 - target address - * r2 - wordcount - * Clobbered: - * r4 - tmp - * r5 - tmp - * r6 - tmp - * r7 - tmp - */ + int retval; + uint8_t fstat; /* Increase buffer_size if needed */ if (buffer_size < (target->working_area_size/2)) @@ -982,35 +915,39 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer, armv7m_info.common_magic = ARMV7M_COMMON_MAGIC; armv7m_info.core_mode = ARM_MODE_THREAD; - init_reg_param(®_params[0], "r0", 32, PARAM_OUT); /* *pLW (*buffer) */ - init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* faddr */ - init_reg_param(®_params[2], "r2", 32, PARAM_OUT); /* number of words to program */ + init_reg_param(®_params[0], "r0", 32, PARAM_IN_OUT); /* address */ + init_reg_param(®_params[1], "r1", 32, PARAM_OUT); /* word count */ + init_reg_param(®_params[2], "r2", 32, PARAM_OUT); + init_reg_param(®_params[3], "r3", 32, PARAM_OUT); + init_reg_param(®_params[4], "r4", 32, PARAM_OUT); - /* write code buffer and use Flash programming code within kinetis */ - /* Set breakpoint to 0 with time-out of 1000 ms */ - while (wcount > 0) { - uint32_t thisrun_count = (wcount > (buffer_size / 4)) ? (buffer_size / 4) : wcount; + buf_set_u32(reg_params[0].value, 0, 32, address); + buf_set_u32(reg_params[1].value, 0, 32, wcount); + buf_set_u32(reg_params[2].value, 0, 32, source->address); + buf_set_u32(reg_params[3].value, 0, 32, source->address + source->size); + buf_set_u32(reg_params[4].value, 0, 32, FTFx_FSTAT); - retval = target_write_buffer(target, source->address, thisrun_count * 4, buffer); - if (retval != ERROR_OK) - break; + retval = target_run_flash_async_algorithm(target, buffer, wcount, 4, + 0, NULL, + 5, reg_params, + source->address, source->size, + write_algorithm->address, 0, + &armv7m_info); - 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 == ERROR_FLASH_OPERATION_FAILED) { + end_address = buf_get_u32(reg_params[0].value, 0, 32); - retval = target_run_algorithm(target, 0, NULL, 3, reg_params, - write_algorithm->address, 0, 100000, &armv7m_info); - if (retval != ERROR_OK) { - LOG_ERROR("Error executing kinetis Flash programming algorithm"); - retval = ERROR_FLASH_OPERATION_FAILED; - break; - } + LOG_ERROR("Error writing flash at %08" PRIx32, end_address); - buffer += thisrun_count * 4; - address += thisrun_count * 4; - wcount -= thisrun_count; - } + retval = target_read_u8(target, FTFx_FSTAT, &fstat); + if (retval == ERROR_OK) { + retval = kinetis_ftfx_decode_error(fstat); + + /* reset error flags */ + target_write_u8(target, FTFx_FSTAT, 0x70); + } + } else if (retval != ERROR_OK) + LOG_ERROR("Error executing kinetis Flash programming algorithm"); target_free_working_area(target, source); target_free_working_area(target, write_algorithm); @@ -1018,6 +955,8 @@ static int kinetis_write_block(struct flash_bank *bank, const uint8_t *buffer, 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]); return retval; } -- cgit v1.1 From 61c18ee486fe7d4c5d65718ba540cb5f76b0da1f Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 22 Jul 2016 19:46:40 +0200 Subject: flash Kinetis: add cache invalidate for KLx series Change-Id: I0177a052cbc380e01405dc139538b731b4f0ed62 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3565 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/flash/nor/kinetis.c | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index b640b3f..3177473 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -102,6 +102,7 @@ #define WDOG_STCTRH 0x40052000 #define SMC_PMCTRL 0x4007E001 #define SMC_PMSTAT 0x4007E003 +#define MCM_PLACR 0xF000300C /* Values */ #define PM_STAT_RUN 0x01 @@ -231,7 +232,8 @@ struct kinetis_flash_bank { FS_PROGRAM_SECTOR = 1, FS_PROGRAM_LONGWORD = 2, FS_PROGRAM_PHRASE = 4, /* Unsupported */ - FS_INVALIDATE_CACHE = 8, + FS_INVALIDATE_CACHE_K = 8, + FS_INVALIDATE_CACHE_L = 0x10, } flash_support; }; @@ -1178,12 +1180,13 @@ static int kinetis_check_run_mode(struct target *target) static void kinetis_invalidate_flash_cache(struct flash_bank *bank) { struct kinetis_flash_bank *kinfo = bank->driver_priv; - uint8_t pfb01cr_byte2 = 0xf0; - if (!(kinfo->flash_support & FS_INVALIDATE_CACHE)) - return; + if (kinfo->flash_support & FS_INVALIDATE_CACHE_K) + target_write_u8(bank->target, FMC_PFB01CR + 2, 0xf0); + + else if (kinfo->flash_support & FS_INVALIDATE_CACHE_L) + target_write_u8(bank->target, MCM_PLACR + 1, 0x04); - target_write_memory(bank->target, FMC_PFB01CR + 2, 1, 1, &pfb01cr_byte2); return; } @@ -1546,7 +1549,7 @@ static int kinetis_probe(struct flash_bank *bank) pflash_sector_size_bytes = 1<<10; nvm_sector_size_bytes = 1<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_K_SDID_K10_M72: case KINETIS_K_SDID_K20_M72: @@ -1559,7 +1562,7 @@ static int kinetis_probe(struct flash_bank *bank) pflash_sector_size_bytes = 2<<10; nvm_sector_size_bytes = 1<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; kinfo->max_flash_prog_size = 1<<10; break; case KINETIS_K_SDID_K10_M100: @@ -1575,7 +1578,7 @@ static int kinetis_probe(struct flash_bank *bank) pflash_sector_size_bytes = 2<<10; nvm_sector_size_bytes = 2<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_K_SDID_K21_M120: case KINETIS_K_SDID_K22_M120: @@ -1584,7 +1587,7 @@ static int kinetis_probe(struct flash_bank *bank) kinfo->max_flash_prog_size = 1<<10; nvm_sector_size_bytes = 4<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_K_SDID_K10_M120: case KINETIS_K_SDID_K20_M120: @@ -1594,7 +1597,7 @@ static int kinetis_probe(struct flash_bank *bank) pflash_sector_size_bytes = 4<<10; nvm_sector_size_bytes = 4<<10; num_blocks = 4; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; default: LOG_ERROR("Unsupported K-family FAMID"); @@ -1608,7 +1611,7 @@ static int kinetis_probe(struct flash_bank *bank) /* K02FN64, K02FN128: FTFA, 2kB sectors */ pflash_sector_size_bytes = 2<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX2: { @@ -1623,7 +1626,7 @@ static int kinetis_probe(struct flash_bank *bank) /* MK24FN1M */ pflash_sector_size_bytes = 4<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; kinfo->max_flash_prog_size = 1<<10; break; } @@ -1633,7 +1636,7 @@ static int kinetis_probe(struct flash_bank *bank) /* K22 with new-style SDID - smaller pflash with FTFA, 2kB sectors */ pflash_sector_size_bytes = 2<<10; /* autodetect 1 or 2 blocks */ - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; } LOG_ERROR("Unsupported Kinetis K22 DIEID"); @@ -1644,12 +1647,12 @@ static int kinetis_probe(struct flash_bank *bank) if ((kinfo->sim_sdid & (KINETIS_SDID_DIEID_MASK)) == KINETIS_SDID_DIEID_K24FN256) { /* K24FN256 - smaller pflash with FTFA */ num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; } /* K24FN1M without errata 7534 */ num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; kinfo->max_flash_prog_size = 1<<10; break; @@ -1663,7 +1666,7 @@ static int kinetis_probe(struct flash_bank *bank) nvm_sector_size_bytes = 4<<10; kinfo->max_flash_prog_size = 1<<10; num_blocks = 2; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; case KINETIS_SDID_FAMILYID_K2X | KINETIS_SDID_SUBFAMID_KX6: @@ -1674,7 +1677,7 @@ static int kinetis_probe(struct flash_bank *bank) nvm_sector_size_bytes = 4<<10; kinfo->max_flash_prog_size = 1<<10; num_blocks = 4; - kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; default: LOG_ERROR("Unsupported Kinetis FAMILYID SUBFAMID"); @@ -1686,7 +1689,7 @@ static int kinetis_probe(struct flash_bank *bank) pflash_sector_size_bytes = 1<<10; nvm_sector_size_bytes = 1<<10; /* autodetect 1 or 2 blocks */ - kinfo->flash_support = FS_PROGRAM_LONGWORD; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; break; case KINETIS_SDID_SERIESID_KV: @@ -1696,14 +1699,14 @@ static int kinetis_probe(struct flash_bank *bank) /* KV10: FTFA, 1kB sectors */ pflash_sector_size_bytes = 1<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; break; case KINETIS_SDID_FAMILYID_K1X | KINETIS_SDID_SUBFAMID_KX1: /* KV11: FTFA, 2kB sectors */ pflash_sector_size_bytes = 2<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_L; break; case KINETIS_SDID_FAMILYID_K3X | KINETIS_SDID_SUBFAMID_KX0: @@ -1712,7 +1715,7 @@ static int kinetis_probe(struct flash_bank *bank) /* KV31: FTFA, 2kB sectors, 2 blocks */ pflash_sector_size_bytes = 2<<10; /* autodetect 1 or 2 blocks */ - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; case KINETIS_SDID_FAMILYID_K4X | KINETIS_SDID_SUBFAMID_KX2: @@ -1721,7 +1724,7 @@ static int kinetis_probe(struct flash_bank *bank) /* KV4x: FTFA, 4kB sectors */ pflash_sector_size_bytes = 4<<10; num_blocks = 1; - kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; break; default: -- cgit v1.1 From 09253ffd13038a465ab7a2ffc8475259d54da1e4 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Tue, 2 Aug 2016 16:49:31 +0200 Subject: flash Kinetis: Family K8x added Change-Id: I8c090a6fe6c204ce20622006490f896c2a55292f Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3614 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/flash/nor/kinetis.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 3177473..49a6e27 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -207,6 +207,7 @@ #define KINETIS_SDID_FAMILYID_K4X 0x40000000 #define KINETIS_SDID_FAMILYID_K6X 0x60000000 #define KINETIS_SDID_FAMILYID_K7X 0x70000000 +#define KINETIS_SDID_FAMILYID_K8X 0x80000000 struct kinetis_flash_bank { bool probed; @@ -1679,6 +1680,16 @@ static int kinetis_probe(struct flash_bank *bank) num_blocks = 4; kinfo->flash_support = FS_PROGRAM_PHRASE | FS_PROGRAM_SECTOR | FS_INVALIDATE_CACHE_K; break; + + case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX0: + case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX1: + case KINETIS_SDID_FAMILYID_K8X | KINETIS_SDID_SUBFAMID_KX2: + /* K80FN256, K81FN256, K82FN256 */ + pflash_sector_size_bytes = 4<<10; + num_blocks = 1; + kinfo->flash_support = FS_PROGRAM_LONGWORD | FS_INVALIDATE_CACHE_K; + break; + default: LOG_ERROR("Unsupported Kinetis FAMILYID SUBFAMID"); } -- cgit v1.1 From 607edefb53ae5ca4120a7967c4cfed3184bb09d2 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Thu, 3 Nov 2016 17:31:33 +0300 Subject: flash: nor: mdr: do not mass erase when clearing INFO memory The MDR parts have two kinds of memory: main (regular memory-mapped memory for code and data) and "info" (not memory-mapped). When OpenOCD is requested to erase the info memory block, it should do just that, instead of erasing everything including main memory. Change-Id: I498142ca50d4a7b669b7776180b0dbcea63a5328 Reported-by: Eldar Khayrullin Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3853 Tested-by: jenkins Reviewed-by: Eldar Khayrullin Reviewed-by: Freddie Chopin --- src/flash/nor/mdr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/flash/nor/mdr.c b/src/flash/nor/mdr.c index 374cb6f..8ceb1bf 100644 --- a/src/flash/nor/mdr.c +++ b/src/flash/nor/mdr.c @@ -171,7 +171,8 @@ static int mdr_erase(struct flash_bank *bank, int first, int last) if (retval != ERROR_OK) goto reset_pg_and_lock; - if ((first == 0) && (last == (bank->num_sectors - 1))) { + if ((first == 0) && (last == (bank->num_sectors - 1)) && + !mdr_info->mem_type) { retval = mdr_mass_erase(bank); goto reset_pg_and_lock; } -- cgit v1.1 From 7d2ad65c6400dea415cd7e0b19d502488b371bfc Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 27 Jul 2016 16:50:25 +0200 Subject: flash at91samd, at91sam4l: fix improper use of mem_ap_ call Since merge of #3149 OpenOCD start with an unresponsive SAMD or SAM4L resulted in segfaults. First was in cortex_m_assert_reset (fixed by #3552), second was in samd_handle_reset_deassert() /sam4l_handle_reset_deassert(). The change replaces mem_ap_write_u32/8 by target_write_u32/8. It also takes better care about examining and polling target before debug control registers are set. It prevents lockup when 'reset halt' is issued on unresponsive cpu. Change-Id: I2516489f4771aebfc1118d174f527497b8a201ad Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3603 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- src/flash/nor/at91sam4l.c | 13 +++++++++---- src/flash/nor/at91samd.c | 11 ++++++++--- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/flash/nor/at91sam4l.c b/src/flash/nor/at91sam4l.c index 4710512..0a605d5 100644 --- a/src/flash/nor/at91sam4l.c +++ b/src/flash/nor/at91sam4l.c @@ -645,10 +645,15 @@ static int sam4l_write(struct flash_bank *bank, const uint8_t *buffer, COMMAND_HANDLER(sam4l_handle_reset_deassert) { struct target *target = get_current_target(CMD_CTX); - struct armv7m_common *armv7m = target_to_armv7m(target); int retval = ERROR_OK; enum reset_types jtag_reset_config = jtag_get_reset_config(); + /* If the target has been unresponsive before, try to re-establish + * communication now - CPU is held in reset by DSU, DAP is working */ + if (!target_was_examined(target)) + target_examine_one(target); + target_poll(target); + /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset() * so we just release reset held by SMAP * @@ -657,14 +662,14 @@ COMMAND_HANDLER(sam4l_handle_reset_deassert) * After vectreset SMAP release is not needed however makes no harm */ if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) { - retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); + retval = target_write_u32(target, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); if (retval == ERROR_OK) - retval = mem_ap_write_atomic_u32(armv7m->debug_ap, DCB_DEMCR, + retval = target_write_u32(target, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); /* do not return on error here, releasing SMAP reset is more important */ } - int retval2 = mem_ap_write_atomic_u32(armv7m->debug_ap, SMAP_SCR, SMAP_SCR_HCR); + int retval2 = target_write_u32(target, SMAP_SCR, SMAP_SCR_HCR); if (retval2 != ERROR_OK) return retval2; diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c index 58b367a..cdc43b8 100644 --- a/src/flash/nor/at91samd.c +++ b/src/flash/nor/at91samd.c @@ -1018,10 +1018,15 @@ COMMAND_HANDLER(samd_handle_bootloader_command) COMMAND_HANDLER(samd_handle_reset_deassert) { struct target *target = get_current_target(CMD_CTX); - struct armv7m_common *armv7m = target_to_armv7m(target); int retval = ERROR_OK; enum reset_types jtag_reset_config = jtag_get_reset_config(); + /* If the target has been unresponsive before, try to re-establish + * communication now - CPU is held in reset by DSU, DAP is working */ + if (!target_was_examined(target)) + target_examine_one(target); + target_poll(target); + /* In case of sysresetreq, debug retains state set in cortex_m_assert_reset() * so we just release reset held by DSU * @@ -1030,9 +1035,9 @@ COMMAND_HANDLER(samd_handle_reset_deassert) * After vectreset DSU release is not needed however makes no harm */ if (target->reset_halt && (jtag_reset_config & RESET_HAS_SRST)) { - retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); + retval = target_write_u32(target, DCB_DHCSR, DBGKEY | C_HALT | C_DEBUGEN); if (retval == ERROR_OK) - retval = mem_ap_write_u32(armv7m->debug_ap, DCB_DEMCR, + retval = target_write_u32(target, DCB_DEMCR, TRCENA | VC_HARDERR | VC_BUSERR | VC_CORERESET); /* do not return on error here, releasing DSU reset is more important */ } -- cgit v1.1 From 21832327eed48be9d44607890d11d31b88d1bd30 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Wed, 10 Aug 2016 09:40:34 +0300 Subject: Replace "daemon" with "server" in user-visible strings Since OpenOCD doesn't fit most common definitions of the word "daemon", using it in the documentation is confusing. Reported by IRC user ohsix. Change-Id: I688d722771b084b17c2a7af8e83fd64bab6141b8 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3634 Reviewed-by: Andreas Fritiofson Tested-by: jenkins --- doc/openocd.texi | 20 ++++++++++---------- src/target/image.c | 4 ++-- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 9558704..ff5593d 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -66,7 +66,7 @@ Free Documentation License''. * Running:: Running OpenOCD * OpenOCD Project Setup:: OpenOCD Project Setup * Config File Guidelines:: Config File Guidelines -* Daemon Configuration:: Daemon Configuration +* Server Configuration:: Server Configuration * Debug Adapter Configuration:: Debug Adapter Configuration * Reset Configuration:: Reset Configuration * TAP Declaration:: TAP Declaration @@ -752,13 +752,13 @@ on the command line or, if there were no @option{-c command} or At the end of the configuration stage it verifies the JTAG scan chain defined using those commands; your configuration should ensure that this always succeeds. -Normally, OpenOCD then starts running as a daemon. +Normally, OpenOCD then starts running as a server. Alternatively, commands may be used to terminate the configuration stage early, perform work (such as updating some flash memory), -and then shut down without acting as a daemon. +and then shut down without acting as a server. -Once OpenOCD starts running as a daemon, it waits for connections from -clients (Telnet, GDB, Other) and processes the commands issued through +Once OpenOCD starts running as a server, it waits for connections from +clients (Telnet, GDB, RPC) and processes the commands issued through those channels. If you are having problems, you can enable internal debug messages via @@ -775,7 +775,7 @@ informational messages, warnings and errors. You can also change this setting from within a telnet or gdb session using @command{debug_level} (@pxref{debuglevel,,debug_level}). -You can redirect all output from the daemon to a file using the +You can redirect all output from the server to a file using the @option{-l } switch. Note! OpenOCD will launch the GDB & telnet server even if it can not @@ -1994,8 +1994,8 @@ proc setc15 @{regs value@} @{ -@node Daemon Configuration -@chapter Daemon Configuration +@node Server Configuration +@chapter Server Configuration @cindex initialization The commands here are commonly found in the openocd.cfg file and are used to specify what TCP/IP ports are used, and how GDB should be @@ -6715,7 +6715,7 @@ port is 5555. @end itemize -@section Daemon Commands +@section Server Commands @deffn {Command} exit Exits the current telnet session. @@ -6741,7 +6741,7 @@ Useful in connection with script files @end deffn @deffn Command shutdown [@option{error}] -Close the OpenOCD daemon, disconnecting all clients (GDB, telnet, +Close the OpenOCD server, disconnecting all clients (GDB, telnet, other). If option @option{error} is used, OpenOCD will return a non-zero exit code to the parent process. @end deffn diff --git a/src/target/image.c b/src/target/image.c index 0612ea7..f97d904 100644 --- a/src/target/image.c +++ b/src/target/image.c @@ -729,7 +729,7 @@ int image_open(struct image *image, const char *url, const char *type_string) retval = image_ihex_buffer_complete(image); if (retval != ERROR_OK) { LOG_ERROR( - "failed buffering IHEX image, check daemon output for additional information"); + "failed buffering IHEX image, check server output for additional information"); fileio_close(image_ihex->fileio); return retval; } @@ -780,7 +780,7 @@ int image_open(struct image *image, const char *url, const char *type_string) retval = image_mot_buffer_complete(image); if (retval != ERROR_OK) { LOG_ERROR( - "failed buffering S19 image, check daemon output for additional information"); + "failed buffering S19 image, check server output for additional information"); fileio_close(image_mot->fileio); return retval; } -- cgit v1.1 From 37ed4751e857563d39b2da04360c9bd2b576aed0 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Mon, 6 Jun 2016 22:01:33 +0200 Subject: configure.ac: Fix libjaylink integration Do not configure internal libjaylink if libusb-1.0 is not available or if J-Link driver is disabled (--disable-jlink). Change-Id: I021bca91dbbc33888a997c664f7836225306c3ef Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3528 Tested-by: jenkins Reviewed-by: Paul Fertser --- configure.ac | 38 ++++++++++++++++++-------------------- src/Makefile.am | 4 ++++ src/jtag/drivers/Makefile.am | 1 + 3 files changed, 23 insertions(+), 20 deletions(-) diff --git a/configure.ac b/configure.ac index fb5514e..bec3b39 100644 --- a/configure.ac +++ b/configure.ac @@ -201,7 +201,6 @@ m4_define([ADAPTER_OPT], [m4_translit(ADAPTER_ARG($1), [_], [-])]) m4_define([USB1_ADAPTERS], [[[ftdi], [MPSSE mode of FTDI based devices], [FTDI]], - [[jlink], [Segger J-Link JTAG Programmer], [JLINK]], [[stlink], [ST-Link JTAG Programmer], [HLADAPTER_STLINK]], [[ti_icdi], [TI ICDI JTAG Programmer], [HLADAPTER_ICDI]], [[ulink], [Keil ULINK JTAG Programmer], [ULINK]], @@ -221,6 +220,9 @@ m4_define([USB0_ADAPTERS], m4_define([HIDAPI_ADAPTERS], [[[cmsis_dap], [CMSIS-DAP Compliant Debugger], [CMSIS_DAP]]]) +m4_define([LIBJAYLINK_ADAPTERS], + [[[jlink], [Segger J-Link JTAG Programmer], [JLINK]]]) + #======================================== # FTD2XXX support comes in 4 forms. # (1) win32 - via a zip file @@ -379,7 +381,7 @@ m4_define([AC_ARG_ADAPTERS], [ ]) ]) -AC_ARG_ADAPTERS([USB1_ADAPTERS, USB_ADAPTERS, USB0_ADAPTERS, HIDAPI_ADAPTERS], [auto]) +AC_ARG_ADAPTERS([USB1_ADAPTERS, USB_ADAPTERS, USB0_ADAPTERS, HIDAPI_ADAPTERS, LIBJAYLINK_ADAPTERS], [auto]) AC_ARG_ENABLE([parport], AS_HELP_STRING([--enable-parport], [Enable building the pc parallel port driver]), @@ -792,19 +794,6 @@ if test $use_internal_jimtcl = yes; then fi fi -if test $use_internal_libjaylink = yes; then - if test -f "$srcdir/src/jtag/drivers/libjaylink/configure.ac"; then - ( cd $srcdir/src/jtag/drivers/libjaylink/ && ./autogen.sh ) - AX_CONFIG_SUBDIR_OPTION([src/jtag/drivers/libjaylink], - [--enable-subproject-build]) - else - AC_MSG_ERROR([Internal libjaylink not found, run either 'git submodule init' and 'git submodule update' or disable internal libjaylink with --disable-internal-libjaylink.]) - fi -else - PKG_CHECK_MODULES([libjaylink], [libjaylink >= 0.1], - [CFLAGS="$CFLAGS $libjaylink_CFLAGS"; LIBS="$LIBS $libjaylink_LIBS"; HAVE_LIBJAYLINK=yes], [HAVE_LIBJAYLINK=no]) -fi - if test $build_remote_bitbang = yes; then build_bitbang=yes AC_DEFINE([BUILD_REMOTE_BITBANG], [1], [1 if you want the Remote Bitbang JTAG driver.]) @@ -1160,6 +1149,9 @@ for hidapi_lib in hidapi hidapi-hidraw hidapi-libusb; do ]) done +PKG_CHECK_MODULES([libjaylink], [libjaylink >= 0.1], + [HAVE_LIBJAYLINK=yes], [HAVE_LIBJAYLINK=no]) + m4_define([PROCESS_ADAPTERS], [ m4_foreach([adapter], [$1], [ if test $2; then @@ -1182,6 +1174,7 @@ PROCESS_ADAPTERS([USB1_ADAPTERS], [$use_libusb1 = yes], [libusb-1.x]) PROCESS_ADAPTERS([USB_ADAPTERS], [$use_libusb1 = yes -o $use_libusb0 = yes], [libusb-1.x or libusb-0.1]) PROCESS_ADAPTERS([USB0_ADAPTERS], [$use_libusb0 = yes], [libusb-0.1]) PROCESS_ADAPTERS([HIDAPI_ADAPTERS], [$use_hidapi = yes], [hidapi]) +PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], [$use_libusb1 = yes -a $use_internal_libjaylink = yes -o $HAVE_LIBJAYLINK = yes], [libusb-1.x or libjaylink-0.1]) if test $enable_stlink != no -o $enable_ti_icdi != no; then AC_DEFINE([BUILD_HLADAPTER], [1], [1 if you want the High Level JTAG driver.]) @@ -1190,11 +1183,15 @@ else fi AM_CONDITIONAL([HLADAPTER], [test $enable_stlink != no -o $enable_ti_icdi != no]) -# Disable J-Link driver if internal libjaylink is disabled and libjaylink was -# not found by pkg-config. if test $enable_jlink != no; then - if test $use_internal_libjaylink$HAVE_LIBJAYLINK = nono; then - enable_jlink=no + if test $use_internal_libjaylink = yes; then + if test -f "$srcdir/src/jtag/drivers/libjaylink/configure.ac"; then + ( cd $srcdir/src/jtag/drivers/libjaylink/ && ./autogen.sh ) + AX_CONFIG_SUBDIR_OPTION([src/jtag/drivers/libjaylink], + [--enable-subproject-build]) + else + AC_MSG_ERROR([Internal libjaylink not found, run either 'git submodule init' and 'git submodule update' or disable internal libjaylink with --disable-internal-libjaylink.]) + fi fi fi @@ -1317,7 +1314,8 @@ echo echo echo OpenOCD configuration summary echo -------------------------------------------------- -m4_foreach([adapter], [USB1_ADAPTERS, USB_ADAPTERS, USB0_ADAPTERS, HIDAPI_ADAPTERS], +m4_foreach([adapter], [USB1_ADAPTERS, USB_ADAPTERS, USB0_ADAPTERS, + HIDAPI_ADAPTERS, LIBJAYLINK_ADAPTERS], [s=m4_format(["%-40s"], ADAPTER_DESC([adapter])) case $ADAPTER_VAR([adapter]) in auto) diff --git a/src/Makefile.am b/src/Makefile.am index 26e02d0..fe40336 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -76,6 +76,10 @@ libopenocd_la_LIBADD = \ $(LIBFTDI_LIBS) $(MINGWLDADD) \ $(HIDAPI_LIBS) $(LIBUSB0_LIBS) $(LIBUSB1_LIBS) +if !INTERNAL_LIBJAYLINK +libopenocd_la_LIBADD += $(libjaylink_LIBS) +endif + STARTUP_TCL_SRCS = \ $(srcdir)/helper/startup.tcl \ $(srcdir)/jtag/startup.tcl \ diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index 2aaf8fd..00d8371 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -33,6 +33,7 @@ noinst_LTLIBRARIES += libjaylink_internal.la libocdjtagdrivers_la_LIBADD += libjaylink_internal.la else DRIVERFILES += jlink.c +libocdjtagdrivers_la_CPPFLAGS += $(libjaylink_CFLAGS) endif endif -- cgit v1.1 From efa90d0f7850951a6296cfcbaf5f99e325d8b245 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 11 Jun 2016 15:06:21 +0200 Subject: drivers/Makefile.am: Fix libjaylink integration Include libjaylink in DIST_SUBDIRS only if J-Link driver is enabled. Change-Id: Ib32bb6a5d8fe9bb6e93d968802733eb4973f2c25 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3529 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/jtag/drivers/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index 00d8371..c81c08e 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -167,8 +167,10 @@ noinst_HEADERS = \ DIST_SUBDIRS = usb_blaster +if JLINK if INTERNAL_LIBJAYLINK DIST_SUBDIRS += libjaylink endif +endif MAINTAINERCLEANFILES = $(srcdir)/Makefile.in -- cgit v1.1 From 84111194b8e39cd27cbeedfa876a775ffea7d1c5 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sat, 11 Jun 2016 16:00:18 +0200 Subject: configure.ac: Fix J-Link adapter description The J-Link driver is not JTAG only and the correct spelling of the company is "SEGGER". Change-Id: Ic1062247d3bf0d564960f1ac6dfc86ffb34593e0 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3530 Tested-by: jenkins Reviewed-by: Paul Fertser --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index bec3b39..1fcafe0 100644 --- a/configure.ac +++ b/configure.ac @@ -221,7 +221,7 @@ m4_define([HIDAPI_ADAPTERS], [[[cmsis_dap], [CMSIS-DAP Compliant Debugger], [CMSIS_DAP]]]) m4_define([LIBJAYLINK_ADAPTERS], - [[[jlink], [Segger J-Link JTAG Programmer], [JLINK]]]) + [[[jlink], [SEGGER J-Link Programmer], [JLINK]]]) #======================================== # FTD2XXX support comes in 4 forms. -- cgit v1.1 From f60d42b0e2d7c1bde4f75cf5fcaeddf11d21f7ed Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 24 Jul 2016 13:06:33 +0200 Subject: Fix autogen.sh invocation of libjaylink Move autogen.sh invocation of libjaylink from the configure to the bootstrap script because the configure script is included in tarball releases but autotools are not required to be available on end-user machines. Thanks to Paul Fertser for spotting this. Change-Id: I5489ae83885157a01803eed51a7328e47d67ea6d Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3569 Tested-by: jenkins Reviewed-by: Paul Fertser --- bootstrap | 7 +++++++ configure.ac | 1 - 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/bootstrap b/bootstrap index 3b60fc6..ad5e7bd 100755 --- a/bootstrap +++ b/bootstrap @@ -39,5 +39,12 @@ else git submodule update fi +if [ -x src/jtag/drivers/libjaylink/autogen.sh ]; then + ( + cd src/jtag/drivers/libjaylink + ./autogen.sh + ) +fi + echo "Bootstrap complete. Quick build instructions:" echo "./configure ...." diff --git a/configure.ac b/configure.ac index 1fcafe0..52b2e96 100644 --- a/configure.ac +++ b/configure.ac @@ -1186,7 +1186,6 @@ AM_CONDITIONAL([HLADAPTER], [test $enable_stlink != no -o $enable_ti_icdi != no] if test $enable_jlink != no; then if test $use_internal_libjaylink = yes; then if test -f "$srcdir/src/jtag/drivers/libjaylink/configure.ac"; then - ( cd $srcdir/src/jtag/drivers/libjaylink/ && ./autogen.sh ) AX_CONFIG_SUBDIR_OPTION([src/jtag/drivers/libjaylink], [--enable-subproject-build]) else -- cgit v1.1 From cc2d4f015f72d7c30d613b50572eb9f31fac515a Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Mon, 15 Feb 2016 21:59:28 +0100 Subject: Remove since long deprecated ft2232 driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Purge all legacy interface configurations so there's no more confusion over which one to use. Also remove doc/INSTALL.txt which mentions ft2232 but otherwise just duplicates what INSTALL says. Change-Id: Ic94f808f123d4917e600b79309f1272c78a7bb11 Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3236 Tested-by: jenkins Reviewed-by: Andreas Färber Reviewed-by: Freddie Chopin --- README | 5 +- TODO | 3 - configure.ac | 97 +- doc/INSTALL.txt | 204 -- doc/Makefile.am | 3 +- doc/manual/release.txt | 2 +- doc/openocd.texi | 113 +- src/jtag/drivers/Makefile.am | 3 - src/jtag/drivers/ft2232.c | 4308 ------------------------------- src/jtag/drivers/ftd2xx_common.h | 2 +- src/jtag/interfaces.c | 12 - tcl/interface/axm0432.cfg | 11 - tcl/interface/busblaster.cfg | 14 - tcl/interface/calao-usb-a9260-c01.cfg | 13 - tcl/interface/calao-usb-a9260-c02.cfg | 13 - tcl/interface/cortino.cfg | 11 - tcl/interface/digilent-hs1.cfg | 15 - tcl/interface/dlp-usb1232h.cfg | 14 - tcl/interface/flossjtag-noeeprom.cfg | 19 - tcl/interface/flossjtag.cfg | 20 - tcl/interface/flyswatter.cfg | 10 - tcl/interface/flyswatter2.cfg | 10 - tcl/interface/hilscher_nxhx10_etm.cfg | 11 - tcl/interface/hilscher_nxhx500_etm.cfg | 11 - tcl/interface/hilscher_nxhx500_re.cfg | 11 - tcl/interface/hilscher_nxhx50_etm.cfg | 11 - tcl/interface/hilscher_nxhx50_re.cfg | 11 - tcl/interface/hitex_str9-comstick.cfg | 11 - tcl/interface/icebear.cfg | 11 - tcl/interface/jtag-lock-pick_tiny_2.cfg | 10 - tcl/interface/jtagkey-tiny.cfg | 9 - tcl/interface/jtagkey.cfg | 11 - tcl/interface/jtagkey2.cfg | 11 - tcl/interface/jtagkey2p.cfg | 11 - tcl/interface/kt-link.cfg | 10 - tcl/interface/lisa-l.cfg | 11 - tcl/interface/luminary-icdi.cfg | 21 - tcl/interface/luminary-lm3s811.cfg | 18 - tcl/interface/luminary.cfg | 31 - tcl/interface/minimodule.cfg | 10 - tcl/interface/neodb.cfg | 10 - tcl/interface/ngxtech.cfg | 10 - tcl/interface/olimex-arm-usb-ocd-h.cfg | 11 - tcl/interface/olimex-arm-usb-ocd.cfg | 11 - tcl/interface/olimex-arm-usb-tiny-h.cfg | 11 - tcl/interface/olimex-jtag-tiny.cfg | 11 - tcl/interface/oocdlink.cfg | 12 - tcl/interface/opendous_ftdi.cfg | 15 - tcl/interface/openocd-usb-hs.cfg | 11 - tcl/interface/openocd-usb.cfg | 11 - tcl/interface/openrd.cfg | 12 - tcl/interface/redbee-econotag.cfg | 13 - tcl/interface/redbee-usb.cfg | 13 - tcl/interface/sheevaplug.cfg | 12 - tcl/interface/signalyzer-h2.cfg | 11 - tcl/interface/signalyzer-h4.cfg | 11 - tcl/interface/signalyzer-lite.cfg | 11 - tcl/interface/signalyzer.cfg | 11 - tcl/interface/stm32-stick.cfg | 11 - tcl/interface/turtelizer2.cfg | 15 - tcl/interface/vpaclink.cfg | 10 - tcl/interface/xds100v2.cfg | 10 - 62 files changed, 13 insertions(+), 5372 deletions(-) delete mode 100644 doc/INSTALL.txt delete mode 100644 src/jtag/drivers/ft2232.c delete mode 100644 tcl/interface/axm0432.cfg delete mode 100644 tcl/interface/busblaster.cfg delete mode 100644 tcl/interface/calao-usb-a9260-c01.cfg delete mode 100644 tcl/interface/calao-usb-a9260-c02.cfg delete mode 100644 tcl/interface/cortino.cfg delete mode 100644 tcl/interface/digilent-hs1.cfg delete mode 100644 tcl/interface/dlp-usb1232h.cfg delete mode 100644 tcl/interface/flossjtag-noeeprom.cfg delete mode 100644 tcl/interface/flossjtag.cfg delete mode 100644 tcl/interface/flyswatter.cfg delete mode 100644 tcl/interface/flyswatter2.cfg delete mode 100644 tcl/interface/hilscher_nxhx10_etm.cfg delete mode 100644 tcl/interface/hilscher_nxhx500_etm.cfg delete mode 100644 tcl/interface/hilscher_nxhx500_re.cfg delete mode 100644 tcl/interface/hilscher_nxhx50_etm.cfg delete mode 100644 tcl/interface/hilscher_nxhx50_re.cfg delete mode 100644 tcl/interface/hitex_str9-comstick.cfg delete mode 100644 tcl/interface/icebear.cfg delete mode 100644 tcl/interface/jtag-lock-pick_tiny_2.cfg delete mode 100644 tcl/interface/jtagkey-tiny.cfg delete mode 100644 tcl/interface/jtagkey.cfg delete mode 100644 tcl/interface/jtagkey2.cfg delete mode 100644 tcl/interface/jtagkey2p.cfg delete mode 100644 tcl/interface/kt-link.cfg delete mode 100644 tcl/interface/lisa-l.cfg delete mode 100644 tcl/interface/luminary-icdi.cfg delete mode 100644 tcl/interface/luminary-lm3s811.cfg delete mode 100644 tcl/interface/luminary.cfg delete mode 100644 tcl/interface/minimodule.cfg delete mode 100644 tcl/interface/neodb.cfg delete mode 100644 tcl/interface/ngxtech.cfg delete mode 100644 tcl/interface/olimex-arm-usb-ocd-h.cfg delete mode 100644 tcl/interface/olimex-arm-usb-ocd.cfg delete mode 100644 tcl/interface/olimex-arm-usb-tiny-h.cfg delete mode 100644 tcl/interface/olimex-jtag-tiny.cfg delete mode 100644 tcl/interface/oocdlink.cfg delete mode 100644 tcl/interface/opendous_ftdi.cfg delete mode 100644 tcl/interface/openocd-usb-hs.cfg delete mode 100644 tcl/interface/openocd-usb.cfg delete mode 100644 tcl/interface/openrd.cfg delete mode 100644 tcl/interface/redbee-econotag.cfg delete mode 100644 tcl/interface/redbee-usb.cfg delete mode 100644 tcl/interface/sheevaplug.cfg delete mode 100644 tcl/interface/signalyzer-h2.cfg delete mode 100644 tcl/interface/signalyzer-h4.cfg delete mode 100644 tcl/interface/signalyzer-lite.cfg delete mode 100644 tcl/interface/signalyzer.cfg delete mode 100644 tcl/interface/stm32-stick.cfg delete mode 100644 tcl/interface/turtelizer2.cfg delete mode 100644 tcl/interface/vpaclink.cfg delete mode 100644 tcl/interface/xds100v2.cfg diff --git a/README b/README index df4bc3b..7ca5957 100644 --- a/README +++ b/README @@ -45,9 +45,6 @@ e.g.: openocd -f interface/stlink-v2-1.cfg -c "transport select hla_swd" \ -f target/stm32l0.cfg -NB: when using an FTDI-based adapter you should prefer configs in the -ftdi directory; the old configs for the ft2232 are deprecated. - After OpenOCD startup, connect GDB with (gdb) target extended-remote localhost:3333 @@ -228,7 +225,7 @@ USB-based adapters depend on libusb-1.0 and some older drivers require libusb-0.1 or libusb-compat-0.1. A compatible implementation, such as FreeBSD's, additionally needs the corresponding .pc files. -USB-Blaster, ASIX Presto, OpenJTAG and ft2232 interface adapter +USB-Blaster, ASIX Presto and OpenJTAG interface adapter drivers need either one of: - libftdi: http://www.intra2net.com/en/developer/libftdi/index.php - ftd2xx: http://www.ftdichip.com/Drivers/D2XX.htm (proprietary, diff --git a/TODO b/TODO index f50af3e..aa43fdd 100644 --- a/TODO +++ b/TODO @@ -93,9 +93,6 @@ interface support: -# rewrite implementation to use non-blocking I/O - J-Link driver: - fix to work with long scan chains, such as R.Doss's svf test. -- FT2232 (libftdi): - - make performance comparable to alternatives (on Win32, D2XX is faster) - - make usability comparable to alternatives - Autodetect USB based adapters; this should be easy on Linux. If there's more than one, list the options; otherwise, just select that one. diff --git a/configure.ac b/configure.ac index 52b2e96..5fb4d2c 100644 --- a/configure.ac +++ b/configure.ac @@ -397,26 +397,6 @@ AC_ARG_ENABLE([parport_giveio], [Enable use of giveio for parport (for CygWin only)]), [parport_use_giveio=$enableval], [parport_use_giveio=]) -AC_ARG_ENABLE([ft2232_libftdi], [], [ -if test $enableval = yes; then - AC_MSG_ERROR([The ft2232 driver is deprecated, use --enable-ftdi to build its replacement, or force the old driver with --enable-legacy-ft2232_libftdi]) -fi -]) - -AC_ARG_ENABLE([ft2232_ftd2xx], [], [ -if test $enableval = yes; then - AC_MSG_ERROR([The ft2232 driver is deprecated, use --enable-ftdi to build its replacement, or force the old driver with --enable-legacy-ft2232_ftd2xx]) -fi -]) - -AC_ARG_ENABLE([legacy-ft2232_libftdi], - AS_HELP_STRING([--enable-legacy-ft2232_libftdi], [(DEPRECATED) Enable building support for FT2232 based devices using the libftdi library]), - [build_ft2232_libftdi=$enableval], [build_ft2232_libftdi=no]) - -AC_ARG_ENABLE([legacy-ft2232_ftd2xx], - AS_HELP_STRING([--enable-legacy-ft2232_ftd2xx], [(DEPRECATED) Enable building support for FT2232 based devices using the D2XX library from ftdichip.com]), - [build_ft2232_ftd2xx=$enableval], [build_ft2232_ftd2xx=no]) - AC_ARG_ENABLE([jtag_vpi], AS_HELP_STRING([--enable-jtag_vpi], [Enable building support for JTAG VPI]), [build_jtag_vpi=$enableval], [build_jtag_vpi=no]) @@ -699,18 +679,6 @@ else AC_DEFINE([BUILD_BITBANG], [0], [0 if you don't want a bitbang interface.]) fi -if test $build_ft2232_libftdi = yes; then - AC_DEFINE([BUILD_FT2232_LIBFTDI], [1], [1 if you want libftdi ft2232.]) -else - AC_DEFINE([BUILD_FT2232_LIBFTDI], [0], [0 if you don't want libftdi ft2232.]) -fi - -if test $build_ft2232_ftd2xx = yes; then - AC_DEFINE([BUILD_FT2232_FTD2XX], [1], [1 if you want ftd2xx ft2232.]) -else - AC_DEFINE([BUILD_FT2232_FTD2XX], [0], [0 if you don't want ftd2xx ft2232.]) -fi - if test $build_usb_blaster_libftdi = yes; then AC_DEFINE([BUILD_USB_BLASTER_LIBFTDI], [1], [1 if you want libftdi usb_blaster.]) else @@ -815,7 +783,7 @@ then AC_MSG_ERROR([The option: with_ftd2xx_linux_tardir is for LINUX only.]) fi -if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes -o $build_openjtag_ftd2xx = yes; then +if test $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes -o $build_openjtag_ftd2xx = yes; then AC_MSG_CHECKING([for ftd2xx.lib exists (win32)]) # if we are given a zipdir... @@ -864,7 +832,7 @@ then AC_MSG_ERROR([The option: with_ftd2xx_linux_tardir is for LINUX only.]) fi -if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then +if test $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then AC_MSG_CHECKING([for libftd2xx.a (darwin)]) if test ! -f /usr/local/include/ftd2xx.h ; then @@ -885,10 +853,10 @@ then AC_MSG_ERROR([The option: --with-ftd2xx-win32-zipdir is for win32 only]) fi -if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes -o $build_openjtag_ftd2xx = yes; then +if test $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes -o $build_openjtag_ftd2xx = yes; then # Must be linux if test $host_os != linux-gnu && test $host_os != linux ; then - AC_MSG_ERROR([The (linux) ftd2xx library from FTDICHIP.com is linux only. Try --enable-ft2232-libftdi instead]) + AC_MSG_ERROR([The (linux) ftd2xx library from FTDICHIP.com is linux only. Try --enable-*-libftdi instead]) fi # Are we given a TAR directory? if test "${with_ftd2xx_linux_tardir+set}" = set @@ -948,7 +916,7 @@ if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_b fi fi # linux -if test $build_ft2232_ftd2xx = yes -o $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then +if test $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then # Before we go any further - make sure we can *BUILD* and *RUN* # a simple app with the "ftd2xx.lib" file - in what ever form we where given @@ -982,29 +950,6 @@ AC_RUN_IFELSE([AC_LANG_PROGRAM([[ AC_MSG_RESULT([Skipping as we are cross-compiling]) ]) -AC_MSG_CHECKING([for ftd2xx highspeed device support]) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include "confdefs.h" -#if IS_WIN32 -#include "windows.h" -#endif -#include -#include - -DWORD x = FT_DEVICE_4232H; - ]], [])], [ - AC_DEFINE([BUILD_FT2232_HIGHSPEED], [1], - [Support FT2232H/FT4232HS with FTD2XX or libftdi.]) - build_ft2232_highspeed=yes - ], [ - build_ft2232_highspeed=no - ]) - AC_MSG_RESULT([$build_ft2232_highspeed]) - - if test $build_ft2232_highspeed = no; then - AC_MSG_WARN([You need a newer FTD2XX driver (version 2.04.16 or later).]) - fi - AC_MSG_CHECKING([for ftd2xx FT232H device support]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include "confdefs.h" @@ -1032,7 +977,7 @@ LDFLAGS=$LDFLAGS_SAVE CFLAGS=$CFLAGS_SAVE fi -if test $build_ft2232_libftdi = yes -o $build_usb_blaster_libftdi = yes -o \ +if test $build_usb_blaster_libftdi = yes -o \ $build_openjtag_ftdi = yes -o $build_presto_libftdi = yes; then # we can have libftdi or libftdi1, so check it and use the latest one @@ -1079,25 +1024,6 @@ if test $build_ft2232_libftdi = yes -o $build_usb_blaster_libftdi = yes -o \ AC_SEARCH_LIBS([ftdi_new], [], [], [AC_MSG_ERROR([Cannot link with libftdi])]) ]) -AC_MSG_CHECKING([for libftdi highspeed device support]) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -#include - ]], [[ -enum ftdi_chip_type x = TYPE_2232H; - ]])], [ - AC_DEFINE([BUILD_FT2232_HIGHSPEED], [1], - [Support FT2232H/FT4232HS with FTD2XX or libftdi.]) - build_ft2232_highspeed=yes - ], [ - build_ft2232_highspeed=no - ]) - AC_MSG_RESULT([$build_ft2232_highspeed]) - - if test $build_ft2232_highspeed = no; then - AC_MSG_WARN([You need a newer libftdi version (0.16 or later).]) - fi - AC_MSG_CHECKING([for libftdi FT232H device support]) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ #include @@ -1205,8 +1131,6 @@ AM_CONDITIONAL([IOUTIL], [test $build_ioutil = yes]) AM_CONDITIONAL([AT91RM9200], [test $build_at91rm9200 = yes]) AM_CONDITIONAL([BCM2835GPIO], [test $build_bcm2835gpio = yes]) AM_CONDITIONAL([BITBANG], [test $build_bitbang = yes]) -AM_CONDITIONAL([FT2232_LIBFTDI], [test $build_ft2232_libftdi = yes]) -AM_CONDITIONAL([FT2232_DRIVER], [test $build_ft2232_ftd2xx = yes -o $build_ft2232_libftdi = yes]) AM_CONDITIONAL([USB_BLASTER_LIBFTDI], [test $build_usb_blaster_libftdi = yes]) AM_CONDITIONAL([USB_BLASTER_FTD2XX], [test $build_usb_blaster_ftd2xx = yes]) AM_CONDITIONAL([JTAG_VPI], [test $build_jtag_vpi = yes -o $build_jtag_vpi = yes]) @@ -1329,12 +1253,3 @@ m4_foreach([adapter], [USB1_ADAPTERS, USB_ADAPTERS, USB0_ADAPTERS, esac ]) echo - -if test $build_ft2232_libftdi = yes -o $build_ft2232_ftd2xx = yes; then - if test $enable_ftdi = no; then - AC_MSG_WARN([Building the deprecated 'ft2232' adapter driver but not its replacement!]) - AC_MSG_WARN([Please consider using --enable-ftdi instead.]) - else - AC_MSG_WARN([Building the deprecated 'ft2232' adapter driver.]) - fi -fi diff --git a/doc/INSTALL.txt b/doc/INSTALL.txt deleted file mode 100644 index c329be2..0000000 --- a/doc/INSTALL.txt +++ /dev/null @@ -1,204 +0,0 @@ -TODO!!! this should be merged into openocd.texi!!! - - -Prerequisites -============= - -When building with support for FTDI FT2232 based devices, you need at least -one of the following libraries: - -- libftdi (http://www.intra2net.com/opensource/ftdi/) -- libftd2xx (http://www.ftdichip.com/Drivers/D2XX.htm) - -On Windows, you need either Cygwin or MinGW, but compilation for MinGW is also -possible using a Cygwin host. - -Basic Installation -================== - - OpenOCD is distributed without autotools generated files, i.e. without a -configure script. Run ./bootstrap in the openocd directory to have all -necessary files generated. - - You have to explicitly enable desired JTAG interfaces during configure: - -./configure --enable-parport --enable-ft2232-libftdi (OR --enable-ft2232-ftd2xx) \ - --enable-amtjtagaccel - - Under Windows/Cygwin, only the ftd2xx driver is supported for FT2232 based -devices. You have to specify the location of the FTDI driver package with the ---with-ftd2xx=/full/path/name option. - -Under Linux you can choose to build the parport driver with support for -/dev/parportN instead of the default access with direct port I/O using ---enable-parport_ppdev. This has the advantage of running OpenOCD without root -privileges at the expense of a slight performance decrease. This is also -available on FreeBSD using PPI, but the naming of the devices is different. - -Generic installation instructions -================================= - - These are generic installation instructions. - - The `configure' shell script attempts to guess correct values for -various system-dependent variables used during compilation. It uses -those values to create a `Makefile' in each directory of the package. -It may also create one or more `.h' files containing system-dependent -definitions. Finally, it creates a shell script `config.status' that -you can run in the future to recreate the current configuration, a file -`config.cache' that saves the results of its tests to speed up -reconfiguring, and a file `config.log' containing compiler output -(useful mainly for debugging `configure'). - - If you need to do unusual things to compile the package, please try -to figure out how `configure' could check whether to do them, and mail -diffs or instructions to the address given in the `README' so they can -be considered for the next release. If at some point `config.cache' -contains results you don't want to keep, you may remove or edit it. - - The file `configure.in' is used to create `configure' by a program -called `autoconf'. You only need `configure.in' if you want to change -it or regenerate `configure' using a newer version of `autoconf'. - -The simplest way to compile this package is: - - 1. `cd' to the directory containing the package's source code and type - `./configure' to configure the package for your system. If you're - using `csh' on an old version of System V, you might need to type - `sh ./configure' instead to prevent `csh' from trying to execute - `configure' itself. - - Running `configure' takes a while. While running, it prints some - messages telling which features it is checking for. - - 2. Type `make' to compile the package. - - 3. Type `make install' to install the programs and any data files and - documentation. - - 4. You can remove the program binaries and object files from the - source code directory by typing `make clean'. - -Compilers and Options -===================== - - Some systems require unusual options for compilation or linking that -the `configure' script does not know about. You can give `configure' -initial values for variables by setting them in the environment. Using -a Bourne-compatible shell, you can do that on the command line like -this: - CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure - -Or on systems that have the `env' program, you can do it like this: - env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure - -Compiling For Multiple Architectures -==================================== - - You can compile the package for more than one kind of computer at the -same time, by placing the object files for each architecture in their -own directory. To do this, you must use a version of `make' that -supports the `VPATH' variable, such as GNU `make'. `cd' to the -directory where you want the object files and executables to go and run -the `configure' script. `configure' automatically checks for the -source code in the directory that `configure' is in and in `..'. - - If you have to use a `make' that does not supports the `VPATH' -variable, you have to compile the package for one architecture at a time -in the source code directory. After you have installed the package for -one architecture, use `make distclean' before reconfiguring for another -architecture. - -Installation Names -================== - - By default, `make install' will install the package's files in -`/usr/local/bin', `/usr/local/man', etc. You can specify an -installation prefix other than `/usr/local' by giving `configure' the -option `--prefix=PATH'. - - You can specify separate installation prefixes for -architecture-specific files and architecture-independent files. If you -give `configure' the option `--exec-prefix=PATH', the package will use -PATH as the prefix for installing programs and libraries. -Documentation and other data files will still use the regular prefix. - - If the package supports it, you can cause programs to be installed -with an extra prefix or suffix on their names by giving `configure' the -option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. - -Optional Features -================= - - Some packages pay attention to `--enable-FEATURE' options to -`configure', where FEATURE indicates an optional part of the package. -They may also pay attention to `--with-PACKAGE' options, where PACKAGE -is something like `gnu-as' or `x' (for the X Window System). The -`README' should mention any `--enable-' and `--with-' options that the -package recognizes. - - For packages that use the X Window System, `configure' can usually -find the X include and library files automatically, but if it doesn't, -you can use the `configure' options `--x-includes=DIR' and -`--x-libraries=DIR' to specify their locations. - -Specifying the System Type -========================== - - There may be some features `configure' can not figure out -automatically, but needs to determine by the type of host the package -will run on. Usually `configure' can figure that out, but if it prints -a message saying it can not guess the host type, give it the -`--host=TYPE' option. TYPE can either be a short name for the system -type, such as `sun4', or a canonical name with three fields: - CPU-COMPANY-SYSTEM - -See the file `config.sub' for the possible values of each field. If -`config.sub' isn't included in this package, then this package doesn't -need to know the host type. - - If you are building compiler tools for cross-compiling, you can also -use the `--target=TYPE' option to select the type of system they will -produce code for and the `--build=TYPE' option to select the type of -system on which you are compiling the package. - -Sharing Defaults -================ - - If you want to set default values for `configure' scripts to share, -you can create a site shell script called `config.site' that gives -default values for variables like `CC', `cache_file', and `prefix'. -`configure' looks for `PREFIX/share/config.site' if it exists, then -`PREFIX/etc/config.site' if it exists. Or, you can set the -`CONFIG_SITE' environment variable to the location of the site script. -A warning: not all `configure' scripts look for a site script. - -Operation Controls -================== - - `configure' recognizes the following options to control how it -operates. - -`--cache-file=FILE' - Use and save the results of the tests in FILE instead of - `./config.cache'. Set FILE to `/dev/null' to disable caching, for - debugging `configure'. - -`--help' - Print a summary of the options to `configure', and exit. - -`--quiet' -`--silent' -`-q' - Do not print messages saying which checks are being made. - -`--srcdir=DIR' - Look for the package's source code in directory DIR. Usually - `configure' can determine that directory automatically. - -`--version' - Print the version of Autoconf used to generate the `configure' - script, and exit. - -`configure' also accepts some other, not widely useful, options. - diff --git a/doc/Makefile.am b/doc/Makefile.am index 935c8f9..24f68a1 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -2,8 +2,7 @@ info_TEXINFOS = openocd.texi openocd_TEXINFOS = fdl.texi man_MANS = openocd.1 EXTRA_DIST = openocd.1 \ - manual \ - INSTALL.txt + manual MAINTAINERCLEANFILES = \ $(srcdir)/Makefile.in \ diff --git a/doc/manual/release.txt b/doc/manual/release.txt index d144756..83f668f 100644 --- a/doc/manual/release.txt +++ b/doc/manual/release.txt @@ -334,7 +334,7 @@ git tag -m "The openocd-${PACKAGE_VERSION} release." "${PACKAGE_TAG}" configuring its contents, using them to build a copy of OpenOCD, and verifying that the result prints the correct release version in its startup banner. (For example, - "configure --enable-ft2232_libftdi --enable-parport" + "configure --enable-parport" then "make" and run "src/openocd -v" as a sanity check.) -# Run make docs to create the documentation which will be published. diff --git a/doc/openocd.texi b/doc/openocd.texi index ff5593d..34cf69d 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -898,7 +898,7 @@ using a Signalyzer FT2232-based JTAG adapter to talk to a board with an Atmel AT91SAM7X256 microcontroller: @example -source [find interface/signalyzer.cfg] +source [find interface/ftdi/signalyzer.cfg] # GDB can also flash my flash! gdb_memory_map enable @@ -910,7 +910,7 @@ source [find target/sam7x256.cfg] Here is the command line equivalent of that configuration: @example -openocd -f interface/signalyzer.cfg \ +openocd -f interface/ftdi/signalyzer.cfg \ -c "gdb_memory_map enable" \ -c "gdb_flash_program enable" \ -f target/sam7x256.cfg @@ -2403,109 +2403,12 @@ A dummy software-only driver for debugging. Cirrus Logic EP93xx based single-board computer bit-banging (in development) @end deffn -@deffn {Interface Driver} {ft2232} -FTDI FT2232 (USB) based devices over one of the userspace libraries. - -Note that this driver has several flaws and the @command{ftdi} driver is -recommended as its replacement. - -These interfaces have several commands, used to configure the driver -before initializing the JTAG scan chain: - -@deffn {Config Command} {ft2232_device_desc} description -Provides the USB device description (the @emph{iProduct string}) -of the FTDI FT2232 device. If not -specified, the FTDI default value is used. This setting is only valid -if compiled with FTD2XX support. -@end deffn - -@deffn {Config Command} {ft2232_serial} serial-number -Specifies the @var{serial-number} of the FTDI FT2232 device to use, -in case the vendor provides unique IDs and more than one FT2232 device -is connected to the host. -If not specified, serial numbers are not considered. -(Note that USB serial numbers can be arbitrary Unicode strings, -and are not restricted to containing only decimal digits.) -@end deffn - -@deffn {Config Command} {ft2232_layout} name -Each vendor's FT2232 device can use different GPIO signals -to control output-enables, reset signals, and LEDs. -Currently valid layout @var{name} values include: -@itemize @minus -@item @b{axm0432_jtag} Axiom AXM-0432 -@item @b{comstick} Hitex STR9 comstick -@item @b{cortino} Hitex Cortino JTAG interface -@item @b{evb_lm3s811} TI/Luminary Micro EVB_LM3S811 as a JTAG interface, -either for the local Cortex-M3 (SRST only) -or in a passthrough mode (neither SRST nor TRST) -This layout can not support the SWO trace mechanism, and should be -used only for older boards (before rev C). -@item @b{luminary_icdi} This layout should be used with most TI/Luminary -eval boards, including Rev C LM3S811 eval boards and the eponymous -ICDI boards, to debug either the local Cortex-M3 or in passthrough mode -to debug some other target. It can support the SWO trace mechanism. -@item @b{flyswatter} Tin Can Tools Flyswatter -@item @b{icebear} ICEbear JTAG adapter from Section 5 -@item @b{jtagkey} Amontec JTAGkey and JTAGkey-Tiny (and compatibles) -@item @b{jtagkey2} Amontec JTAGkey2 (and compatibles) -@item @b{m5960} American Microsystems M5960 -@item @b{olimex-jtag} Olimex ARM-USB-OCD and ARM-USB-Tiny -@item @b{oocdlink} OOCDLink -@c oocdlink ~= jtagkey_prototype_v1 -@item @b{redbee-econotag} Integrated with a Redbee development board. -@item @b{redbee-usb} Integrated with a Redbee USB-stick development board. -@item @b{sheevaplug} Marvell Sheevaplug development kit -@item @b{signalyzer} Xverve Signalyzer -@item @b{stm32stick} Hitex STM32 Performance Stick -@item @b{turtelizer2} egnite Software turtelizer2 -@item @b{usbjtag} "USBJTAG-1" layout described in the OpenOCD diploma thesis -@end itemize -@end deffn - -@deffn {Config Command} {ft2232_vid_pid} [vid pid]+ -The vendor ID and product ID of the FTDI FT2232 device. If not specified, the FTDI -default values are used. -Currently, up to eight [@var{vid}, @var{pid}] pairs may be given, e.g. -@example -ft2232_vid_pid 0x0403 0xcff8 0x15ba 0x0003 -@end example -@end deffn - -@deffn {Config Command} {ft2232_latency} ms -On some systems using FT2232 based JTAG interfaces the FT_Read function call in -ft2232_read() fails to return the expected number of bytes. This can be caused by -USB communication delays and has proved hard to reproduce and debug. Setting the -FT2232 latency timer to a larger value increases delays for short USB packets but it -also reduces the risk of timeouts before receiving the expected number of bytes. -The OpenOCD default value is 2 and for some systems a value of 10 has proved useful. -@end deffn - -@deffn {Config Command} {ft2232_channel} channel -Used to select the channel of the ft2232 chip to use (between 1 and 4). -The default value is 1. -@end deffn - -For example, the interface config file for a -Turtelizer JTAG Adapter looks something like this: - -@example -interface ft2232 -ft2232_device_desc "Turtelizer JTAG/RS232 Adapter" -ft2232_layout turtelizer2 -ft2232_vid_pid 0x0403 0xbdc8 -@end example -@end deffn - @deffn {Interface Driver} {ftdi} This driver is for adapters using the MPSSE (Multi-Protocol Synchronous Serial Engine) mode built into many FTDI chips, such as the FT2232, FT4232 and FT232H. -It is a complete rewrite to address a large number of problems with the ft2232 -interface driver. The driver is using libusb-1.0 in asynchronous mode to talk to the FTDI device, -bypassing intermediate libraries like libftdi of D2XX. Performance-wise it is -consistently faster than the ft2232 driver, sometimes several times faster. +bypassing intermediate libraries like libftdi of D2XX. A major improvement of this driver is that support for new FTDI based adapters can be added competely through configuration files, without the need to patch @@ -9344,16 +9247,6 @@ supply stable enough for the Amontec JTAGkey to be operated. @b{Laptops running on battery have this problem too...} -@item @b{USB Power} When using the Amontec JTAGkey, sometimes OpenOCD crashes with the -following error messages: "Error: ft2232.c:201 ft2232_read(): FT_Read returned: -4" and "Error: ft2232.c:365 ft2232_send_and_recv(): couldn't read from FT2232". -What does that mean and what might be the reason for this? - -First of all, the reason might be the USB power supply. Try using a self-powered -hub instead of a direct connection to your computer. Secondly, the error code 4 -corresponds to an FT_IO_ERROR, which means that the driver for the FTDI USB -chip ran into some sort of error - this points us to a USB problem. - @item @b{GDB Disconnects} When using the Amontec JTAGkey, sometimes OpenOCD crashes with the following error message: "Error: gdb_server.c:101 gdb_get_char(): read: 10054". What does that mean and what might be the reason for this? diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index c81c08e..4c4e774 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -60,9 +60,6 @@ endif if DUMMY DRIVERFILES += dummy.c endif -if FT2232_DRIVER -DRIVERFILES += ft2232.c -endif if FTDI DRIVERFILES += ftdi.c mpsse.c endif diff --git a/src/jtag/drivers/ft2232.c b/src/jtag/drivers/ft2232.c deleted file mode 100644 index 621da8e..0000000 --- a/src/jtag/drivers/ft2232.c +++ /dev/null @@ -1,4308 +0,0 @@ -/*************************************************************************** -* Copyright (C) 2009 by Øyvind Harboe * -* Øyvind Harboe * -* * -* Copyright (C) 2009 by SoftPLC Corporation. http://softplc.com * -* Dick Hollenbeck * -* * -* Copyright (C) 2004, 2006 by Dominic Rath * -* Dominic.Rath@gmx.de * -* * -* Copyright (C) 2008 by Spencer Oliver * -* spen@spen-soft.co.uk * -* * -* 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, see . * -***************************************************************************/ - -/** - * @file - * JTAG adapters based on the FT2232 full and high speed USB parts are - * popular low cost JTAG debug solutions. Many FT2232 based JTAG adapters - * are discrete, but development boards may integrate them as alternatives - * to more capable (and expensive) third party JTAG pods. - * - * JTAG uses only one of the two communications channels ("MPSSE engines") - * on these devices. Adapters based on FT4232 parts have four ports/channels - * (A/B/C/D), instead of just two (A/B). - * - * Especially on development boards integrating one of these chips (as - * opposed to discrete pods/dongles), the additional channels can be used - * for a variety of purposes, but OpenOCD only uses one channel at a time. - * - * - As a USB-to-serial adapter for the target's console UART ... - * which may be able to support ROM boot loaders that load initial - * firmware images to flash (or SRAM). - * - * - On systems which support ARM's SWD in addition to JTAG, or instead - * of it, that second port can be used for reading SWV/SWO trace data. - * - * - Additional JTAG links, e.g. to a CPLD or * FPGA. - * - * FT2232 based JTAG adapters are "dumb" not "smart", because most JTAG - * request/response interactions involve round trips over the USB link. - * A "smart" JTAG adapter has intelligence close to the scan chain, so it - * can for example poll quickly for a status change (usually taking on the - * order of microseconds not milliseconds) before beginning a queued - * transaction which require the previous one to have completed. - * - * There are dozens of adapters of this type, differing in details which - * this driver needs to understand. Those "layout" details are required - * as part of FT2232 driver configuration. - * - * This code uses information contained in the MPSSE specification which was - * found here: - * http://www.ftdichip.com/Documents/AppNotes/AN2232C-01_MPSSE_Cmnd.pdf - * Hereafter this is called the "MPSSE Spec". - * - * The datasheet for the ftdichip.com's FT2232D part is here: - * http://www.ftdichip.com/Documents/DataSheets/DS_FT2232D.pdf - * - * Also note the issue with code 0x4b (clock data to TMS) noted in - * http://developer.intra2net.com/mailarchive/html/libftdi/2009/msg00292.html - * which can affect longer JTAG state paths. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -/* project specific includes */ -#include -#include -#include - -#if IS_CYGWIN == 1 -#include -#endif - -#include - -#if (BUILD_FT2232_FTD2XX == 1 && BUILD_FT2232_LIBFTDI == 1) -#error "BUILD_FT2232_FTD2XX && BUILD_FT2232_LIBFTDI are mutually exclusive" -#elif (BUILD_FT2232_FTD2XX != 1 && BUILD_FT2232_LIBFTDI != 1) -#error "BUILD_FT2232_FTD2XX || BUILD_FT2232_LIBFTDI must be chosen" -#endif - -/* FT2232 access library includes */ -#if BUILD_FT2232_FTD2XX == 1 -#include -#include "ftd2xx_common.h" - -enum ftdi_interface { - INTERFACE_ANY = 0, - INTERFACE_A = 1, - INTERFACE_B = 2, - INTERFACE_C = 3, - INTERFACE_D = 4 -}; - -#elif BUILD_FT2232_LIBFTDI == 1 -#include -#endif - -/* max TCK for the high speed devices 30000 kHz */ -#define FTDI_x232H_MAX_TCK 30000 -/* max TCK for the full speed devices 6000 kHz */ -#define FTDI_2232C_MAX_TCK 6000 -/* this speed value tells that RTCK is requested */ -#define RTCK_SPEED -1 - -/* - * On my Athlon XP 1900+ EHCI host with FT2232H JTAG dongle I get read timeout - * errors with a retry count of 100. Increasing it solves the problem for me. - * - Dimitar - * - * FIXME There's likely an issue with the usb_read_timeout from libftdi. - * Fix that (libusb? kernel? libftdi? here?) and restore the retry count - * to something sane. - */ -#define LIBFTDI_READ_RETRY_COUNT 2000 - -#ifndef BUILD_FT2232_HIGHSPEED - #if BUILD_FT2232_FTD2XX == 1 - enum { FT_DEVICE_2232H = 6, FT_DEVICE_4232H, FT_DEVICE_232H }; - #elif BUILD_FT2232_LIBFTDI == 1 - enum ftdi_chip_type { TYPE_2232H = 4, TYPE_4232H = 5, TYPE_232H = 6 }; - #endif -#endif - -/** - * Send out \a num_cycles on the TCK line while the TAP(s) are in a - * stable state. Calling code must ensure that current state is stable, - * that verification is not done in here. - * - * @param num_cycles The number of clocks cycles to send. - * @param cmd The command to send. - * - * @returns ERROR_OK on success, or ERROR_JTAG_QUEUE_FAILED on failure. - */ -static int ft2232_stableclocks(int num_cycles, struct jtag_command *cmd); - -static char *ft2232_device_desc_A; -static char *ft2232_device_desc; -static char *ft2232_serial; -static uint8_t ft2232_latency = 2; -static unsigned ft2232_max_tck = FTDI_2232C_MAX_TCK; -static int ft2232_channel = INTERFACE_ANY; - -#define MAX_USB_IDS 8 -/* vid = pid = 0 marks the end of the list */ -static uint16_t ft2232_vid[MAX_USB_IDS + 1] = { 0x0403, 0 }; -static uint16_t ft2232_pid[MAX_USB_IDS + 1] = { 0x6010, 0 }; - -struct ft2232_layout { - const char *name; - int (*init)(void); - void (*reset)(int trst, int srst); - void (*blink)(void); - int channel; -}; - -/* init procedures for supported layouts */ -static int usbjtag_init(void); -static int jtagkey_init(void); -static int lm3s811_jtag_init(void); -static int icdi_jtag_init(void); -static int olimex_jtag_init(void); -static int flyswatter1_init(void); -static int flyswatter2_init(void); -static int minimodule_init(void); -static int turtle_init(void); -static int comstick_init(void); -static int stm32stick_init(void); -static int axm0432_jtag_init(void); -static int sheevaplug_init(void); -static int icebear_jtag_init(void); -static int cortino_jtag_init(void); -static int signalyzer_init(void); -static int signalyzer_h_init(void); -static int ktlink_init(void); -static int redbee_init(void); -static int lisa_l_init(void); -static int flossjtag_init(void); -static int xds100v2_init(void); -static int digilent_hs1_init(void); - -/* reset procedures for supported layouts */ -static void ftx23_reset(int trst, int srst); -static void jtagkey_reset(int trst, int srst); -static void olimex_jtag_reset(int trst, int srst); -static void flyswatter1_reset(int trst, int srst); -static void flyswatter2_reset(int trst, int srst); -static void minimodule_reset(int trst, int srst); -static void turtle_reset(int trst, int srst); -static void comstick_reset(int trst, int srst); -static void stm32stick_reset(int trst, int srst); -static void axm0432_jtag_reset(int trst, int srst); -static void sheevaplug_reset(int trst, int srst); -static void icebear_jtag_reset(int trst, int srst); -static void signalyzer_h_reset(int trst, int srst); -static void ktlink_reset(int trst, int srst); -static void redbee_reset(int trst, int srst); -static void xds100v2_reset(int trst, int srst); -static void digilent_hs1_reset(int trst, int srst); - -/* blink procedures for layouts that support a blinking led */ -static void olimex_jtag_blink(void); -static void flyswatter1_jtag_blink(void); -static void flyswatter2_jtag_blink(void); -static void turtle_jtag_blink(void); -static void signalyzer_h_blink(void); -static void ktlink_blink(void); -static void lisa_l_blink(void); -static void flossjtag_blink(void); - -/* common transport support options */ - -/* static const char *jtag_and_swd[] = { "jtag", "swd", NULL }; */ - -static const struct ft2232_layout ft2232_layouts[] = { - { .name = "usbjtag", - .init = usbjtag_init, - .reset = ftx23_reset, - }, - { .name = "jtagkey", - .init = jtagkey_init, - .reset = jtagkey_reset, - }, - { .name = "jtagkey_prototype_v1", - .init = jtagkey_init, - .reset = jtagkey_reset, - }, - { .name = "oocdlink", - .init = jtagkey_init, - .reset = jtagkey_reset, - }, - { .name = "signalyzer", - .init = signalyzer_init, - .reset = ftx23_reset, - }, - { .name = "evb_lm3s811", - .init = lm3s811_jtag_init, - .reset = ftx23_reset, - }, - { .name = "luminary_icdi", - .init = icdi_jtag_init, - .reset = ftx23_reset, - }, - { .name = "olimex-jtag", - .init = olimex_jtag_init, - .reset = olimex_jtag_reset, - .blink = olimex_jtag_blink - }, - { .name = "flyswatter", - .init = flyswatter1_init, - .reset = flyswatter1_reset, - .blink = flyswatter1_jtag_blink - }, - { .name = "flyswatter2", - .init = flyswatter2_init, - .reset = flyswatter2_reset, - .blink = flyswatter2_jtag_blink - }, - { .name = "minimodule", - .init = minimodule_init, - .reset = minimodule_reset, - }, - { .name = "turtelizer2", - .init = turtle_init, - .reset = turtle_reset, - .blink = turtle_jtag_blink - }, - { .name = "comstick", - .init = comstick_init, - .reset = comstick_reset, - }, - { .name = "stm32stick", - .init = stm32stick_init, - .reset = stm32stick_reset, - }, - { .name = "axm0432_jtag", - .init = axm0432_jtag_init, - .reset = axm0432_jtag_reset, - }, - { .name = "sheevaplug", - .init = sheevaplug_init, - .reset = sheevaplug_reset, - }, - { .name = "icebear", - .init = icebear_jtag_init, - .reset = icebear_jtag_reset, - }, - { .name = "cortino", - .init = cortino_jtag_init, - .reset = comstick_reset, - }, - { .name = "signalyzer-h", - .init = signalyzer_h_init, - .reset = signalyzer_h_reset, - .blink = signalyzer_h_blink - }, - { .name = "ktlink", - .init = ktlink_init, - .reset = ktlink_reset, - .blink = ktlink_blink - }, - { .name = "redbee-econotag", - .init = redbee_init, - .reset = redbee_reset, - }, - { .name = "redbee-usb", - .init = redbee_init, - .reset = redbee_reset, - .channel = INTERFACE_B, - }, - { .name = "lisa-l", - .init = lisa_l_init, - .reset = ftx23_reset, - .blink = lisa_l_blink, - .channel = INTERFACE_B, - }, - { .name = "flossjtag", - .init = flossjtag_init, - .reset = ftx23_reset, - .blink = flossjtag_blink, - }, - { .name = "xds100v2", - .init = xds100v2_init, - .reset = xds100v2_reset, - }, - { .name = "digilent-hs1", - .init = digilent_hs1_init, - .reset = digilent_hs1_reset, - .channel = INTERFACE_A, - }, - { .name = NULL, /* END OF TABLE */ }, -}; - -/* bitmask used to drive nTRST; usually a GPIOLx signal */ -static uint8_t nTRST; -static uint8_t nTRSTnOE; -/* bitmask used to drive nSRST; usually a GPIOLx signal */ -static uint8_t nSRST; -static uint8_t nSRSTnOE; - -/** the layout being used with this debug session */ -static const struct ft2232_layout *layout; - -/** default bitmask values driven on DBUS: TCK/TDI/TDO/TMS and GPIOL(0..4) */ -static uint8_t low_output; - -/* note that direction bit == 1 means that signal is an output */ - -/** default direction bitmask for DBUS: TCK/TDI/TDO/TMS and GPIOL(0..4) */ -static uint8_t low_direction; -/** default value bitmask for CBUS GPIOH(0..4) */ -static uint8_t high_output; -/** default direction bitmask for CBUS GPIOH(0..4) */ -static uint8_t high_direction; - -#if BUILD_FT2232_FTD2XX == 1 -static FT_HANDLE ftdih; -static FT_DEVICE ftdi_device; -#elif BUILD_FT2232_LIBFTDI == 1 -static struct ftdi_context ftdic; -static enum ftdi_chip_type ftdi_device; -#endif - -static struct jtag_command *first_unsent; /* next command that has to be sent */ -static int require_send; - -/* http://urjtag.wiki.sourceforge.net/Cable + FT2232 says: - - "There is a significant difference between libftdi and libftd2xx. The latter - one allows to schedule up to 64*64 bytes of result data while libftdi fails - with more than 4*64. As a consequence, the FT2232 driver is forced to - perform around 16x more USB transactions for long command streams with TDO - capture when running with libftdi." - - No idea how we get - #define FT2232_BUFFER_SIZE 131072 - a comment would have been nice. -*/ - -#if BUILD_FT2232_FTD2XX == 1 -#define FT2232_BUFFER_READ_QUEUE_SIZE (64*64) -#else -#define FT2232_BUFFER_READ_QUEUE_SIZE (64*4) -#endif - -#define FT2232_BUFFER_SIZE 131072 - -static uint8_t *ft2232_buffer; -static int ft2232_buffer_size; -static int ft2232_read_pointer; -static int ft2232_expect_read; - -/** - * Function buffer_write - * writes a byte into the byte buffer, "ft2232_buffer", which must be sent later. - * @param val is the byte to send. - */ -static inline void buffer_write(uint8_t val) -{ - assert(ft2232_buffer); - assert((unsigned) ft2232_buffer_size < (unsigned) FT2232_BUFFER_SIZE); - ft2232_buffer[ft2232_buffer_size++] = val; -} - -/** - * Function buffer_read - * returns a byte from the byte buffer. - */ -static inline uint8_t buffer_read(void) -{ - assert(ft2232_buffer); - assert(ft2232_read_pointer < ft2232_buffer_size); - return ft2232_buffer[ft2232_read_pointer++]; -} - -/** - * Clocks out \a bit_count bits on the TMS line, starting with the least - * significant bit of tms_bits and progressing to more significant bits. - * Rigorous state transition logging is done here via tap_set_state(). - * - * @param mpsse_cmd One of the MPSSE TMS oriented commands such as - * 0x4b or 0x6b. See the MPSSE spec referenced above for their - * functionality. The MPSSE command "Clock Data to TMS/CS Pin (no Read)" - * is often used for this, 0x4b. - * - * @param tms_bits Holds the sequence of bits to send. - * @param tms_count Tells how many bits in the sequence. - * @param tdi_bit A single bit to pass on to TDI before the first TCK - * cycle and held static for the duration of TMS clocking. - * - * See the MPSSE spec referenced above. - */ -static void clock_tms(uint8_t mpsse_cmd, int tms_bits, int tms_count, bool tdi_bit) -{ - uint8_t tms_byte; - int i; - int tms_ndx; /* bit index into tms_byte */ - - assert(tms_count > 0); - - DEBUG_JTAG_IO("mpsse cmd=%02x, tms_bits = 0x%08x, bit_count=%d", - mpsse_cmd, tms_bits, tms_count); - - for (tms_byte = tms_ndx = i = 0; i < tms_count; ++i, tms_bits >>= 1) { - bool bit = tms_bits & 1; - - if (bit) - tms_byte |= (1 << tms_ndx); - - /* always do state transitions in public view */ - tap_set_state(tap_state_transition(tap_get_state(), bit)); - - /* we wrote a bit to tms_byte just above, increment bit index. if bit was zero - * also increment. - */ - ++tms_ndx; - - if (tms_ndx == 7 || i == tms_count-1) { - buffer_write(mpsse_cmd); - buffer_write(tms_ndx - 1); - - /* Bit 7 of the byte is passed on to TDI/DO before the first TCK/SK of - * TMS/CS and is held static for the duration of TMS/CS clocking. - */ - buffer_write(tms_byte | (tdi_bit << 7)); - } - } -} - -/** - * Function get_tms_buffer_requirements - * returns what clock_tms() will consume if called with - * same \a bit_count. - */ -static inline int get_tms_buffer_requirements(int bit_count) -{ - return ((bit_count + 6)/7) * 3; -} - -/** - * Function move_to_state - * moves the TAP controller from the current state to a - * \a goal_state through a path given by tap_get_tms_path(). State transition - * logging is performed by delegation to clock_tms(). - * - * @param goal_state is the destination state for the move. - */ -static void move_to_state(tap_state_t goal_state) -{ - tap_state_t start_state = tap_get_state(); - - /* goal_state is 1/2 of a tuple/pair of states which allow convenient - * lookup of the required TMS pattern to move to this state from the start state. - */ - - /* do the 2 lookups */ - int tms_bits = tap_get_tms_path(start_state, goal_state); - int tms_count = tap_get_tms_path_len(start_state, goal_state); - - DEBUG_JTAG_IO("start=%s goal=%s", tap_state_name(start_state), tap_state_name(goal_state)); - - clock_tms(0x4b, tms_bits, tms_count, 0); -} - -static int ft2232_write(uint8_t *buf, int size, uint32_t *bytes_written) -{ -#if BUILD_FT2232_FTD2XX == 1 - FT_STATUS status; - DWORD dw_bytes_written = 0; - status = FT_Write(ftdih, buf, size, &dw_bytes_written); - if (status != FT_OK) { - *bytes_written = dw_bytes_written; - LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } else - *bytes_written = dw_bytes_written; - -#elif BUILD_FT2232_LIBFTDI == 1 - int retval = ftdi_write_data(&ftdic, buf, size); - if (retval < 0) { - *bytes_written = 0; - LOG_ERROR("ftdi_write_data: %s", ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } else - *bytes_written = retval; - -#endif - - if (*bytes_written != (uint32_t)size) - return ERROR_JTAG_DEVICE_ERROR; - - return ERROR_OK; -} - -static int ft2232_read(uint8_t *buf, uint32_t size, uint32_t *bytes_read) -{ -#if BUILD_FT2232_FTD2XX == 1 - DWORD dw_bytes_read; - FT_STATUS status; - int timeout = 5; - *bytes_read = 0; - - while ((*bytes_read < size) && timeout--) { - status = FT_Read(ftdih, buf + *bytes_read, size - - *bytes_read, &dw_bytes_read); - if (status != FT_OK) { - *bytes_read = 0; - LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_read += dw_bytes_read; - } - -#elif BUILD_FT2232_LIBFTDI == 1 - int retval; - int timeout = LIBFTDI_READ_RETRY_COUNT; - *bytes_read = 0; - - while ((*bytes_read < size) && timeout--) { - retval = ftdi_read_data(&ftdic, buf + *bytes_read, size - *bytes_read); - if (retval < 0) { - *bytes_read = 0; - LOG_ERROR("ftdi_read_data: %s", ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_read += retval; - } - -#endif - - if (*bytes_read < size) { - LOG_ERROR("couldn't read enough bytes from " - "FT2232 device (%i < %i)", - (unsigned)*bytes_read, - (unsigned)size); - return ERROR_JTAG_DEVICE_ERROR; - } - - return ERROR_OK; -} - -static bool ft2232_device_is_highspeed(void) -{ -#if BUILD_FT2232_FTD2XX == 1 - return (ftdi_device == FT_DEVICE_2232H) || (ftdi_device == FT_DEVICE_4232H) - #ifdef HAS_ENUM_FT232H - || (ftdi_device == FT_DEVICE_232H) - #endif - ; -#elif BUILD_FT2232_LIBFTDI == 1 - return (ftdi_device == TYPE_2232H || ftdi_device == TYPE_4232H - #ifdef HAS_ENUM_FT232H - || ftdi_device == TYPE_232H - #endif - ); -#endif -} - -/* - * Commands that only apply to the highspeed FTx232H devices (FT2232H, FT4232H, FT232H). - * See chapter 6 in http://www.ftdichip.com/Documents/AppNotes/ - * AN_108_Command_Processor_for_MPSSE_and_MCU_Host_Bus_Emulation_Modes.pdf - */ - -static int ftx232h_adaptive_clocking(bool enable) -{ - uint8_t buf = enable ? 0x96 : 0x97; - LOG_DEBUG("%2.2x", buf); - - uint32_t bytes_written; - int retval; - - retval = ft2232_write(&buf, sizeof(buf), &bytes_written); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't write command to %s adaptive clocking" - , enable ? "enable" : "disable"); - return retval; - } - - return ERROR_OK; -} - -/** - * Enable/disable the clk divide by 5 of the 60MHz master clock. - * This result in a JTAG clock speed range of 91.553Hz-6MHz - * respective 457.763Hz-30MHz. - */ -static int ftx232h_clk_divide_by_5(bool enable) -{ - uint32_t bytes_written; - uint8_t buf = enable ? 0x8b : 0x8a; - - if (ft2232_write(&buf, sizeof(buf), &bytes_written) != ERROR_OK) { - LOG_ERROR("couldn't write command to %s clk divide by 5" - , enable ? "enable" : "disable"); - return ERROR_JTAG_INIT_FAILED; - } - ft2232_max_tck = enable ? FTDI_2232C_MAX_TCK : FTDI_x232H_MAX_TCK; - LOG_INFO("max TCK change to: %u kHz", ft2232_max_tck); - - return ERROR_OK; -} - -static int ft2232_speed(int speed) -{ - uint8_t buf[3]; - int retval; - uint32_t bytes_written; - - retval = ERROR_OK; - bool enable_adaptive_clocking = (RTCK_SPEED == speed); - if (ft2232_device_is_highspeed()) - retval = ftx232h_adaptive_clocking(enable_adaptive_clocking); - else if (enable_adaptive_clocking) { - LOG_ERROR("ft2232 device %lu does not support RTCK" - , (long unsigned int)ftdi_device); - return ERROR_FAIL; - } - - if ((enable_adaptive_clocking) || (ERROR_OK != retval)) - return retval; - - buf[0] = 0x86; /* command "set divisor" */ - buf[1] = speed & 0xff; /* valueL (0 = 6MHz, 1 = 3MHz, 2 = 2.0MHz, ...*/ - buf[2] = (speed >> 8) & 0xff; /* valueH */ - - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - retval = ft2232_write(buf, sizeof(buf), &bytes_written); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't set FT2232 TCK speed"); - return retval; - } - - return ERROR_OK; -} - -static int ft2232_speed_div(int speed, int *khz) -{ - /* Take a look in the FT2232 manual, - * AN2232C-01 Command Processor for - * MPSSE and MCU Host Bus. Chapter 3.8 */ - - *khz = (RTCK_SPEED == speed) ? 0 : ft2232_max_tck / (1 + speed); - - return ERROR_OK; -} - -static int ft2232_khz(int khz, int *jtag_speed) -{ - if (khz == 0) { - if (ft2232_device_is_highspeed()) { - *jtag_speed = RTCK_SPEED; - return ERROR_OK; - } else { - LOG_DEBUG("RCLK not supported"); - return ERROR_FAIL; - } - } - - /* Take a look in the FT2232 manual, - * AN2232C-01 Command Processor for - * MPSSE and MCU Host Bus. Chapter 3.8 - * - * We will calc here with a multiplier - * of 10 for better rounding later. */ - - /* Calc speed, (ft2232_max_tck / khz) - 1 - * Use 65000 for better rounding */ - *jtag_speed = ((ft2232_max_tck*10) / khz) - 10; - - /* Add 0.9 for rounding */ - *jtag_speed += 9; - - /* Calc real speed */ - *jtag_speed = *jtag_speed / 10; - - /* Check if speed is greater than 0 */ - if (*jtag_speed < 0) - *jtag_speed = 0; - - /* Check max value */ - if (*jtag_speed > 0xFFFF) - *jtag_speed = 0xFFFF; - - return ERROR_OK; -} - -static void ft2232_end_state(tap_state_t state) -{ - if (tap_is_state_stable(state)) - tap_set_end_state(state); - else { - LOG_ERROR("BUG: %s is not a stable end state", tap_state_name(state)); - exit(-1); - } -} - -static void ft2232_read_scan(enum scan_type type, uint8_t *buffer, int scan_size) -{ - int num_bytes = (scan_size + 7) / 8; - int bits_left = scan_size; - int cur_byte = 0; - - while (num_bytes-- > 1) { - buffer[cur_byte++] = buffer_read(); - bits_left -= 8; - } - - buffer[cur_byte] = 0x0; - - /* There is one more partial byte left from the clock data in/out instructions */ - if (bits_left > 1) - buffer[cur_byte] = buffer_read() >> 1; - /* This shift depends on the length of the - *clock data to tms instruction, insterted - *at end of the scan, now fixed to a two - *step transition in ft2232_add_scan */ - buffer[cur_byte] = (buffer[cur_byte] | (((buffer_read()) << 1) & 0x80)) >> (8 - bits_left); -} - -static void ft2232_debug_dump_buffer(void) -{ - int i; - char line[256]; - char *line_p = line; - - for (i = 0; i < ft2232_buffer_size; i++) { - line_p += snprintf(line_p, - sizeof(line) - (line_p - line), - "%2.2x ", - ft2232_buffer[i]); - if (i % 16 == 15) { - LOG_DEBUG("%s", line); - line_p = line; - } - } - - if (line_p != line) - LOG_DEBUG("%s", line); -} - -static int ft2232_send_and_recv(struct jtag_command *first, struct jtag_command *last) -{ - struct jtag_command *cmd; - uint8_t *buffer; - int scan_size; - enum scan_type type; - int retval; - uint32_t bytes_written = 0; - uint32_t bytes_read = 0; - -#ifdef _DEBUG_USB_IO_ - struct timeval start, inter, inter2, end; - struct timeval d_inter, d_inter2, d_end; -#endif - -#ifdef _DEBUG_USB_COMMS_ - LOG_DEBUG("write buffer (size %i):", ft2232_buffer_size); - ft2232_debug_dump_buffer(); -#endif - -#ifdef _DEBUG_USB_IO_ - gettimeofday(&start, NULL); -#endif - - retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't write MPSSE commands to FT2232"); - return retval; - } - -#ifdef _DEBUG_USB_IO_ - gettimeofday(&inter, NULL); -#endif - - if (ft2232_expect_read) { - /* FIXME this "timeout" is never changed ... */ - int timeout = LIBFTDI_READ_RETRY_COUNT; - ft2232_buffer_size = 0; - -#ifdef _DEBUG_USB_IO_ - gettimeofday(&inter2, NULL); -#endif - - retval = ft2232_read(ft2232_buffer, ft2232_expect_read, &bytes_read); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't read from FT2232"); - return retval; - } - -#ifdef _DEBUG_USB_IO_ - gettimeofday(&end, NULL); - - timeval_subtract(&d_inter, &inter, &start); - timeval_subtract(&d_inter2, &inter2, &start); - timeval_subtract(&d_end, &end, &start); - - LOG_INFO("inter: %u.%06u, inter2: %u.%06u end: %u.%06u", - (unsigned)d_inter.tv_sec, (unsigned)d_inter.tv_usec, - (unsigned)d_inter2.tv_sec, (unsigned)d_inter2.tv_usec, - (unsigned)d_end.tv_sec, (unsigned)d_end.tv_usec); -#endif - - ft2232_buffer_size = bytes_read; - - if (ft2232_expect_read != ft2232_buffer_size) { - LOG_ERROR("ft2232_expect_read (%i) != " - "ft2232_buffer_size (%i) " - "(%i retries)", - ft2232_expect_read, - ft2232_buffer_size, - LIBFTDI_READ_RETRY_COUNT - timeout); - ft2232_debug_dump_buffer(); - - exit(-1); - } - -#ifdef _DEBUG_USB_COMMS_ - LOG_DEBUG("read buffer (%i retries): %i bytes", - LIBFTDI_READ_RETRY_COUNT - timeout, - ft2232_buffer_size); - ft2232_debug_dump_buffer(); -#endif - } - - ft2232_expect_read = 0; - ft2232_read_pointer = 0; - - /* return ERROR_OK, unless a jtag_read_buffer returns a failed check - * that wasn't handled by a caller-provided error handler - */ - retval = ERROR_OK; - - cmd = first; - while (cmd != last) { - switch (cmd->type) { - case JTAG_SCAN: - type = jtag_scan_type(cmd->cmd.scan); - if (type != SCAN_OUT) { - scan_size = jtag_scan_size(cmd->cmd.scan); - buffer = calloc(DIV_ROUND_UP(scan_size, 8), 1); - ft2232_read_scan(type, buffer, scan_size); - if (jtag_read_buffer(buffer, cmd->cmd.scan) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - free(buffer); - } - break; - - default: - break; - } - - cmd = cmd->next; - } - - ft2232_buffer_size = 0; - - return retval; -} - -/** - * Function ft2232_add_pathmove - * moves the TAP controller from the current state to a new state through the - * given path, where path is an array of tap_state_t's. - * - * @param path is an array of tap_stat_t which gives the states to traverse through - * ending with the last state at path[num_states-1] - * @param num_states is the count of state steps to move through - */ -static void ft2232_add_pathmove(tap_state_t *path, int num_states) -{ - int state_count = 0; - - assert((unsigned) num_states <= 32u); /* tms_bits only holds 32 bits */ - - DEBUG_JTAG_IO("-"); - - /* this loop verifies that the path is legal and logs each state in the path */ - while (num_states) { - unsigned char tms_byte = 0; /* zero this on each MPSSE batch */ - int bit_count = 0; - int num_states_batch = num_states > 7 ? 7 : num_states; - - /* command "Clock Data to TMS/CS Pin (no Read)" */ - buffer_write(0x4b); - - /* number of states remaining */ - buffer_write(num_states_batch - 1); - - while (num_states_batch--) { - /* either TMS=0 or TMS=1 must work ... */ - if (tap_state_transition(tap_get_state(), false) == path[state_count]) - buf_set_u32(&tms_byte, bit_count++, 1, 0x0); - else if (tap_state_transition(tap_get_state(), true) == path[state_count]) - buf_set_u32(&tms_byte, bit_count++, 1, 0x1); - - /* ... or else the caller goofed BADLY */ - else { - LOG_ERROR("BUG: %s -> %s isn't a valid " - "TAP state transition", - tap_state_name(tap_get_state()), - tap_state_name(path[state_count])); - exit(-1); - } - - tap_set_state(path[state_count]); - state_count++; - num_states--; - } - - buffer_write(tms_byte); - } - tap_set_end_state(tap_get_state()); -} - -static void ft2232_add_scan(bool ir_scan, enum scan_type type, uint8_t *buffer, int scan_size) -{ - int num_bytes = (scan_size + 7) / 8; - int bits_left = scan_size; - int cur_byte = 0; - int last_bit; - - if (!ir_scan) { - if (tap_get_state() != TAP_DRSHIFT) - move_to_state(TAP_DRSHIFT); - } else { - if (tap_get_state() != TAP_IRSHIFT) - move_to_state(TAP_IRSHIFT); - } - - /* add command for complete bytes */ - while (num_bytes > 1) { - int thisrun_bytes; - if (type == SCAN_IO) { - /* Clock Data Bytes In and Out LSB First */ - buffer_write(0x39); - /* LOG_DEBUG("added TDI bytes (io %i)", num_bytes); */ - } else if (type == SCAN_OUT) { - /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */ - buffer_write(0x19); - /* LOG_DEBUG("added TDI bytes (o)"); */ - } else if (type == SCAN_IN) { - /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */ - buffer_write(0x28); - /* LOG_DEBUG("added TDI bytes (i %i)", num_bytes); */ - } - - thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1); - num_bytes -= thisrun_bytes; - - buffer_write((uint8_t) (thisrun_bytes - 1)); - buffer_write((uint8_t) ((thisrun_bytes - 1) >> 8)); - - if (type != SCAN_IN) { - /* add complete bytes */ - while (thisrun_bytes-- > 0) { - buffer_write(buffer[cur_byte++]); - bits_left -= 8; - } - } else /* (type == SCAN_IN) */ - bits_left -= 8 * (thisrun_bytes); - } - - /* the most signifcant bit is scanned during TAP movement */ - if (type != SCAN_IN) - last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1; - else - last_bit = 0; - - /* process remaining bits but the last one */ - if (bits_left > 1) { - if (type == SCAN_IO) { - /* Clock Data Bits In and Out LSB First */ - buffer_write(0x3b); - /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */ - } else if (type == SCAN_OUT) { - /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ - buffer_write(0x1b); - /* LOG_DEBUG("added TDI bits (o)"); */ - } else if (type == SCAN_IN) { - /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ - buffer_write(0x2a); - /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */ - } - - buffer_write(bits_left - 2); - if (type != SCAN_IN) - buffer_write(buffer[cur_byte]); - } - - if ((ir_scan && (tap_get_end_state() == TAP_IRSHIFT)) - || (!ir_scan && (tap_get_end_state() == TAP_DRSHIFT))) { - if (type == SCAN_IO) { - /* Clock Data Bits In and Out LSB First */ - buffer_write(0x3b); - /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */ - } else if (type == SCAN_OUT) { - /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ - buffer_write(0x1b); - /* LOG_DEBUG("added TDI bits (o)"); */ - } else if (type == SCAN_IN) { - /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ - buffer_write(0x2a); - /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */ - } - buffer_write(0x0); - if (type != SCAN_IN) - buffer_write(last_bit); - } else { - int tms_bits; - int tms_count; - uint8_t mpsse_cmd; - - /* move from Shift-IR/DR to end state */ - if (type != SCAN_OUT) { - /* We always go to the PAUSE state in two step at the end of an IN or IO - *scan - * This must be coordinated with the bit shifts in ft2232_read_scan */ - tms_bits = 0x01; - tms_count = 2; - /* Clock Data to TMS/CS Pin with Read */ - mpsse_cmd = 0x6b; - } else { - tms_bits = tap_get_tms_path(tap_get_state(), tap_get_end_state()); - tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); - /* Clock Data to TMS/CS Pin (no Read) */ - mpsse_cmd = 0x4b; - } - - DEBUG_JTAG_IO("finish %s", (type == SCAN_OUT) ? "without read" : "via PAUSE"); - clock_tms(mpsse_cmd, tms_bits, tms_count, last_bit); - } - - if (tap_get_state() != tap_get_end_state()) - move_to_state(tap_get_end_state()); -} - -static int ft2232_large_scan(struct scan_command *cmd, - enum scan_type type, - uint8_t *buffer, - int scan_size) -{ - int num_bytes = (scan_size + 7) / 8; - int bits_left = scan_size; - int cur_byte = 0; - int last_bit; - uint8_t *receive_buffer = malloc(DIV_ROUND_UP(scan_size, 8)); - uint8_t *receive_pointer = receive_buffer; - uint32_t bytes_written; - uint32_t bytes_read; - int retval; - int thisrun_read = 0; - - if (!receive_buffer) { - LOG_ERROR("failed to allocate memory"); - exit(-1); - } - - if (cmd->ir_scan) { - LOG_ERROR("BUG: large IR scans are not supported"); - exit(-1); - } - - if (tap_get_state() != TAP_DRSHIFT) - move_to_state(TAP_DRSHIFT); - - retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't write MPSSE commands to FT2232"); - exit(-1); - } - LOG_DEBUG("ft2232_buffer_size: %i, bytes_written: %i", - ft2232_buffer_size, (int)bytes_written); - ft2232_buffer_size = 0; - - /* add command for complete bytes */ - while (num_bytes > 1) { - int thisrun_bytes; - - if (type == SCAN_IO) { - /* Clock Data Bytes In and Out LSB First */ - buffer_write(0x39); - /* LOG_DEBUG("added TDI bytes (io %i)", num_bytes); */ - } else if (type == SCAN_OUT) { - /* Clock Data Bytes Out on -ve Clock Edge LSB First (no Read) */ - buffer_write(0x19); - /* LOG_DEBUG("added TDI bytes (o)"); */ - } else if (type == SCAN_IN) { - /* Clock Data Bytes In on +ve Clock Edge LSB First (no Write) */ - buffer_write(0x28); - /* LOG_DEBUG("added TDI bytes (i %i)", num_bytes); */ - } - - thisrun_bytes = (num_bytes > 65537) ? 65536 : (num_bytes - 1); - thisrun_read = thisrun_bytes; - num_bytes -= thisrun_bytes; - buffer_write((uint8_t) (thisrun_bytes - 1)); - buffer_write((uint8_t) ((thisrun_bytes - 1) >> 8)); - - if (type != SCAN_IN) { - /* add complete bytes */ - while (thisrun_bytes-- > 0) { - buffer_write(buffer[cur_byte]); - cur_byte++; - bits_left -= 8; - } - } else /* (type == SCAN_IN) */ - bits_left -= 8 * (thisrun_bytes); - - retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't write MPSSE commands to FT2232"); - exit(-1); - } - LOG_DEBUG("ft2232_buffer_size: %i, bytes_written: %i", - ft2232_buffer_size, - (int)bytes_written); - ft2232_buffer_size = 0; - - if (type != SCAN_OUT) { - retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't read from FT2232"); - exit(-1); - } - LOG_DEBUG("thisrun_read: %i, bytes_read: %i", - thisrun_read, - (int)bytes_read); - receive_pointer += bytes_read; - } - } - - thisrun_read = 0; - - /* the most signifcant bit is scanned during TAP movement */ - if (type != SCAN_IN) - last_bit = (buffer[cur_byte] >> (bits_left - 1)) & 0x1; - else - last_bit = 0; - - /* process remaining bits but the last one */ - if (bits_left > 1) { - if (type == SCAN_IO) { - /* Clock Data Bits In and Out LSB First */ - buffer_write(0x3b); - /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */ - } else if (type == SCAN_OUT) { - /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ - buffer_write(0x1b); - /* LOG_DEBUG("added TDI bits (o)"); */ - } else if (type == SCAN_IN) { - /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ - buffer_write(0x2a); - /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */ - } - buffer_write(bits_left - 2); - if (type != SCAN_IN) - buffer_write(buffer[cur_byte]); - - if (type != SCAN_OUT) - thisrun_read += 2; - } - - if (tap_get_end_state() == TAP_DRSHIFT) { - if (type == SCAN_IO) { - /* Clock Data Bits In and Out LSB First */ - buffer_write(0x3b); - /* LOG_DEBUG("added TDI bits (io) %i", bits_left - 1); */ - } else if (type == SCAN_OUT) { - /* Clock Data Bits Out on -ve Clock Edge LSB First (no Read) */ - buffer_write(0x1b); - /* LOG_DEBUG("added TDI bits (o)"); */ - } else if (type == SCAN_IN) { - /* Clock Data Bits In on +ve Clock Edge LSB First (no Write) */ - buffer_write(0x2a); - /* LOG_DEBUG("added TDI bits (i %i)", bits_left - 1); */ - } - buffer_write(0x0); - buffer_write(last_bit); - } else { - int tms_bits = tap_get_tms_path(tap_get_state(), tap_get_end_state()); - int tms_count = tap_get_tms_path_len(tap_get_state(), tap_get_end_state()); - uint8_t mpsse_cmd; - - /* move from Shift-IR/DR to end state */ - if (type != SCAN_OUT) { - /* Clock Data to TMS/CS Pin with Read */ - mpsse_cmd = 0x6b; - /* LOG_DEBUG("added TMS scan (read)"); */ - } else { - /* Clock Data to TMS/CS Pin (no Read) */ - mpsse_cmd = 0x4b; - /* LOG_DEBUG("added TMS scan (no read)"); */ - } - - DEBUG_JTAG_IO("finish, %s", (type == SCAN_OUT) ? "no read" : "read"); - clock_tms(mpsse_cmd, tms_bits, tms_count, last_bit); - } - - if (type != SCAN_OUT) - thisrun_read += 1; - - retval = ft2232_write(ft2232_buffer, ft2232_buffer_size, &bytes_written); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't write MPSSE commands to FT2232"); - exit(-1); - } - LOG_DEBUG("ft2232_buffer_size: %i, bytes_written: %i", - ft2232_buffer_size, - (int)bytes_written); - ft2232_buffer_size = 0; - - if (type != SCAN_OUT) { - retval = ft2232_read(receive_pointer, thisrun_read, &bytes_read); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't read from FT2232"); - exit(-1); - } - LOG_DEBUG("thisrun_read: %i, bytes_read: %i", - thisrun_read, - (int)bytes_read); - } - - free(receive_buffer); - - return ERROR_OK; -} - -static int ft2232_predict_scan_out(int scan_size, enum scan_type type) -{ - int predicted_size = 3; - int num_bytes = (scan_size - 1) / 8; - - if (tap_get_state() != TAP_DRSHIFT) - predicted_size += get_tms_buffer_requirements( - tap_get_tms_path_len(tap_get_state(), TAP_DRSHIFT)); - - if (type == SCAN_IN) { /* only from device to host */ - /* complete bytes */ - predicted_size += DIV_ROUND_UP(num_bytes, 65536) * 3; - - /* remaining bits - 1 (up to 7) */ - predicted_size += ((scan_size - 1) % 8) ? 2 : 0; - } else {/* host to device, or bidirectional - * complete bytes */ - predicted_size += num_bytes + DIV_ROUND_UP(num_bytes, 65536) * 3; - - /* remaining bits -1 (up to 7) */ - predicted_size += ((scan_size - 1) % 8) ? 3 : 0; - } - - return predicted_size; -} - -static int ft2232_predict_scan_in(int scan_size, enum scan_type type) -{ - int predicted_size = 0; - - if (type != SCAN_OUT) { - /* complete bytes */ - predicted_size += - (DIV_ROUND_UP(scan_size, 8) > 1) ? (DIV_ROUND_UP(scan_size, 8) - 1) : 0; - - /* remaining bits - 1 */ - predicted_size += ((scan_size - 1) % 8) ? 1 : 0; - - /* last bit (from TMS scan) */ - predicted_size += 1; - } - - /* LOG_DEBUG("scan_size: %i, predicted_size: %i", scan_size, predicted_size); */ - - return predicted_size; -} - -/* semi-generic FT2232/FT4232 reset code */ -static void ftx23_reset(int trst, int srst) -{ - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (trst == 1) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - low_direction |= nTRSTnOE; /* switch to output pin (output is low) */ - else - low_output &= ~nTRST; /* switch output low */ - } else if (trst == 0) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - low_direction &= ~nTRSTnOE; /* switch to input pin (high-Z + internal - *and external pullup) */ - else - low_output |= nTRST; /* switch output high */ - } - - if (srst == 1) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - low_output &= ~nSRST; /* switch output low */ - else - low_direction |= nSRSTnOE; /* switch to output pin (output is low) */ - } else if (srst == 0) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - low_output |= nSRST; /* switch output high */ - else - low_direction &= ~nSRSTnOE; /* switch to input pin (high-Z) */ - } - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); -} - -static void jtagkey_reset(int trst, int srst) -{ - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (trst == 1) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output &= ~nTRSTnOE; - else - high_output &= ~nTRST; - } else if (trst == 0) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output |= nTRSTnOE; - else - high_output |= nTRST; - } - - if (srst == 1) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - high_output &= ~nSRST; - else - high_output &= ~nSRSTnOE; - } else if (srst == 0) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - high_output |= nSRST; - else - high_output |= nSRSTnOE; - } - - /* command "set data bits high byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", - trst, - srst, - high_output, - high_direction); -} - -static void olimex_jtag_reset(int trst, int srst) -{ - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (trst == 1) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output &= ~nTRSTnOE; - else - high_output &= ~nTRST; - } else if (trst == 0) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output |= nTRSTnOE; - else - high_output |= nTRST; - } - - if (srst == 1) - high_output |= nSRST; - else if (srst == 0) - high_output &= ~nSRST; - - /* command "set data bits high byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", - trst, - srst, - high_output, - high_direction); -} - -static void axm0432_jtag_reset(int trst, int srst) -{ - if (trst == 1) { - tap_set_state(TAP_RESET); - high_output &= ~nTRST; - } else if (trst == 0) - high_output |= nTRST; - - if (srst == 1) - high_output &= ~nSRST; - else if (srst == 0) - high_output |= nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", - trst, - srst, - high_output, - high_direction); -} - -static void flyswatter_reset(int trst, int srst) -{ - if (trst == 1) - low_output &= ~nTRST; - else if (trst == 0) - low_output |= nTRST; - - if (srst == 1) - low_output |= nSRST; - else if (srst == 0) - low_output &= ~nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); - LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", - trst, - srst, - low_output, - low_direction); -} - -static void flyswatter1_reset(int trst, int srst) -{ - flyswatter_reset(trst, srst); -} - -static void flyswatter2_reset(int trst, int srst) -{ - flyswatter_reset(trst, !srst); -} - -static void minimodule_reset(int trst, int srst) -{ - if (srst == 1) - low_output &= ~nSRST; - else if (srst == 0) - low_output |= nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); - LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", - trst, - srst, - low_output, - low_direction); -} - -static void turtle_reset(int trst, int srst) -{ - if (trst == 1) - LOG_ERROR("Can't assert TRST: the adapter lacks this signal"); - - if (srst == 1) - low_output |= nSRST; - else if (srst == 0) - low_output &= ~nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); - LOG_DEBUG("srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", - srst, - low_output, - low_direction); -} - -static void comstick_reset(int trst, int srst) -{ - if (trst == 1) - high_output &= ~nTRST; - else if (trst == 0) - high_output |= nTRST; - - if (srst == 1) - high_output &= ~nSRST; - else if (srst == 0) - high_output |= nSRST; - - /* command "set data bits high byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", - trst, - srst, - high_output, - high_direction); -} - -static void stm32stick_reset(int trst, int srst) -{ - if (trst == 1) - high_output &= ~nTRST; - else if (trst == 0) - high_output |= nTRST; - - if (srst == 1) - low_output &= ~nSRST; - else if (srst == 0) - low_output |= nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); - - /* command "set data bits high byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", - trst, - srst, - high_output, - high_direction); -} - -static void sheevaplug_reset(int trst, int srst) -{ - if (trst == 1) - high_output &= ~nTRST; - else if (trst == 0) - high_output |= nTRST; - - if (srst == 1) - high_output &= ~nSRSTnOE; - else if (srst == 0) - high_output |= nSRSTnOE; - - /* command "set data bits high byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", - trst, - srst, - high_output, - high_direction); -} - -static void redbee_reset(int trst, int srst) -{ - if (trst == 1) { - tap_set_state(TAP_RESET); - high_output &= ~nTRST; - } else if (trst == 0) - high_output |= nTRST; - - if (srst == 1) - high_output &= ~nSRST; - else if (srst == 0) - high_output |= nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, " - "high_direction: 0x%2.2x", trst, srst, high_output, - high_direction); -} - -static void xds100v2_reset(int trst, int srst) -{ - if (trst == 1) { - tap_set_state(TAP_RESET); - high_output &= ~nTRST; - } else if (trst == 0) - high_output |= nTRST; - - if (srst == 1) - high_output |= nSRST; - else if (srst == 0) - high_output &= ~nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, " - "high_direction: 0x%2.2x", trst, srst, high_output, - high_direction); -} - -static int ft2232_execute_runtest(struct jtag_command *cmd) -{ - int retval; - int i; - int predicted_size = 0; - retval = ERROR_OK; - - DEBUG_JTAG_IO("runtest %i cycles, end in %s", - cmd->cmd.runtest->num_cycles, - tap_state_name(cmd->cmd.runtest->end_state)); - - /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 0; - if (tap_get_state() != TAP_IDLE) - predicted_size += 3; - predicted_size += 3 * DIV_ROUND_UP(cmd->cmd.runtest->num_cycles, 7); - if (cmd->cmd.runtest->end_state != TAP_IDLE) - predicted_size += 3; - if (tap_get_end_state() != TAP_IDLE) - predicted_size += 3; - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - require_send = 0; - first_unsent = cmd; - } - if (tap_get_state() != TAP_IDLE) { - move_to_state(TAP_IDLE); - require_send = 1; - } - i = cmd->cmd.runtest->num_cycles; - while (i > 0) { - /* there are no state transitions in this code, so omit state tracking */ - - /* command "Clock Data to TMS/CS Pin (no Read)" */ - buffer_write(0x4b); - - /* scan 7 bits */ - buffer_write((i > 7) ? 6 : (i - 1)); - - /* TMS data bits */ - buffer_write(0x0); - - i -= (i > 7) ? 7 : i; - /* LOG_DEBUG("added TMS scan (no read)"); */ - } - - ft2232_end_state(cmd->cmd.runtest->end_state); - - if (tap_get_state() != tap_get_end_state()) - move_to_state(tap_get_end_state()); - - require_send = 1; - DEBUG_JTAG_IO("runtest: %i, end in %s", - cmd->cmd.runtest->num_cycles, - tap_state_name(tap_get_end_state())); - return retval; -} - -static int ft2232_execute_statemove(struct jtag_command *cmd) -{ - int predicted_size = 0; - int retval = ERROR_OK; - - DEBUG_JTAG_IO("statemove end in %s", - tap_state_name(cmd->cmd.statemove->end_state)); - - /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 3; - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - require_send = 0; - first_unsent = cmd; - } - ft2232_end_state(cmd->cmd.statemove->end_state); - - /* For TAP_RESET, ignore the current recorded state. It's often - * wrong at server startup, and this transation is critical whenever - * it's requested. - */ - if (tap_get_end_state() == TAP_RESET) { - clock_tms(0x4b, 0xff, 5, 0); - require_send = 1; - - /* shortest-path move to desired end state */ - } else if (tap_get_state() != tap_get_end_state()) { - move_to_state(tap_get_end_state()); - require_send = 1; - } - - return retval; -} - -/** - * Clock a bunch of TMS (or SWDIO) transitions, to change the JTAG - * (or SWD) state machine. - */ -static int ft2232_execute_tms(struct jtag_command *cmd) -{ - int retval = ERROR_OK; - unsigned num_bits = cmd->cmd.tms->num_bits; - const uint8_t *bits = cmd->cmd.tms->bits; - unsigned count; - - DEBUG_JTAG_IO("TMS: %d bits", num_bits); - - /* only send the maximum buffer size that FT2232C can handle */ - count = 3 * DIV_ROUND_UP(num_bits, 4); - if (ft2232_buffer_size + 3*count + 1 > FT2232_BUFFER_SIZE) { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - - require_send = 0; - first_unsent = cmd; - } - - /* Shift out in batches of at most 6 bits; there's a report of an - * FT2232 bug in this area, where shifting exactly 7 bits can make - * problems with TMS signaling for the last clock cycle: - * - * http://developer.intra2net.com/mailarchive/html/ - * libftdi/2009/msg00292.html - * - * Command 0x4b is: "Clock Data to TMS/CS Pin (no Read)" - * - * Note that pathmoves in JTAG are not often seven bits, so that - * isn't a particularly likely situation outside of "special" - * signaling such as switching between JTAG and SWD modes. - */ - while (num_bits) { - if (num_bits <= 6) { - buffer_write(0x4b); - buffer_write(num_bits - 1); - buffer_write(*bits & 0x3f); - break; - } - - /* Yes, this is lazy ... we COULD shift out more data - * bits per operation, but doing it in nybbles is easy - */ - buffer_write(0x4b); - buffer_write(3); - buffer_write(*bits & 0xf); - num_bits -= 4; - - count = (num_bits > 4) ? 4 : num_bits; - - buffer_write(0x4b); - buffer_write(count - 1); - buffer_write((*bits >> 4) & 0xf); - num_bits -= count; - - bits++; - } - - require_send = 1; - return retval; -} - -static int ft2232_execute_pathmove(struct jtag_command *cmd) -{ - int predicted_size = 0; - int retval = ERROR_OK; - - tap_state_t *path = cmd->cmd.pathmove->path; - int num_states = cmd->cmd.pathmove->num_states; - - DEBUG_JTAG_IO("pathmove: %i states, current: %s end: %s", num_states, - tap_state_name(tap_get_state()), - tap_state_name(path[num_states-1])); - - /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 3 * DIV_ROUND_UP(num_states, 7); - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - - require_send = 0; - first_unsent = cmd; - } - - ft2232_add_pathmove(path, num_states); - require_send = 1; - - return retval; -} - -static int ft2232_execute_scan(struct jtag_command *cmd) -{ - uint8_t *buffer; - int scan_size; /* size of IR or DR scan */ - int predicted_size = 0; - int retval = ERROR_OK; - - enum scan_type type = jtag_scan_type(cmd->cmd.scan); - - DEBUG_JTAG_IO("%s type:%d", cmd->cmd.scan->ir_scan ? "IRSCAN" : "DRSCAN", type); - - scan_size = jtag_build_buffer(cmd->cmd.scan, &buffer); - - predicted_size = ft2232_predict_scan_out(scan_size, type); - if ((predicted_size + 1) > FT2232_BUFFER_SIZE) { - LOG_DEBUG("oversized ft2232 scan (predicted_size > FT2232_BUFFER_SIZE)"); - /* unsent commands before this */ - if (first_unsent != cmd) - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - - /* current command */ - ft2232_end_state(cmd->cmd.scan->end_state); - ft2232_large_scan(cmd->cmd.scan, type, buffer, scan_size); - require_send = 0; - first_unsent = cmd->next; - if (buffer) - free(buffer); - return retval; - } else if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - LOG_DEBUG( - "ft2232 buffer size reached, sending queued commands (first_unsent: %p, cmd: %p)", - first_unsent, - cmd); - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - require_send = 0; - first_unsent = cmd; - } - ft2232_expect_read += ft2232_predict_scan_in(scan_size, type); - /* LOG_DEBUG("new read size: %i", ft2232_expect_read); */ - ft2232_end_state(cmd->cmd.scan->end_state); - ft2232_add_scan(cmd->cmd.scan->ir_scan, type, buffer, scan_size); - require_send = 1; - if (buffer) - free(buffer); - DEBUG_JTAG_IO("%s scan, %i bits, end in %s", - (cmd->cmd.scan->ir_scan) ? "IR" : "DR", scan_size, - tap_state_name(tap_get_end_state())); - return retval; - -} - -static int ft2232_execute_reset(struct jtag_command *cmd) -{ - int retval; - int predicted_size = 0; - retval = ERROR_OK; - - DEBUG_JTAG_IO("reset trst: %i srst %i", - cmd->cmd.reset->trst, cmd->cmd.reset->srst); - - /* only send the maximum buffer size that FT2232C can handle */ - predicted_size = 3; - if (ft2232_buffer_size + predicted_size + 1 > FT2232_BUFFER_SIZE) { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - require_send = 0; - first_unsent = cmd; - } - - if ((cmd->cmd.reset->trst == 1) || - (cmd->cmd.reset->srst && (jtag_get_reset_config() & RESET_SRST_PULLS_TRST))) - tap_set_state(TAP_RESET); - - layout->reset(cmd->cmd.reset->trst, cmd->cmd.reset->srst); - require_send = 1; - - DEBUG_JTAG_IO("trst: %i, srst: %i", - cmd->cmd.reset->trst, cmd->cmd.reset->srst); - return retval; -} - -static int ft2232_execute_sleep(struct jtag_command *cmd) -{ - int retval; - retval = ERROR_OK; - - DEBUG_JTAG_IO("sleep %" PRIi32, cmd->cmd.sleep->us); - - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - first_unsent = cmd->next; - jtag_sleep(cmd->cmd.sleep->us); - DEBUG_JTAG_IO("sleep %" PRIi32 " usec while in %s", - cmd->cmd.sleep->us, - tap_state_name(tap_get_state())); - return retval; -} - -static int ft2232_execute_stableclocks(struct jtag_command *cmd) -{ - int retval; - retval = ERROR_OK; - - /* this is only allowed while in a stable state. A check for a stable - * state was done in jtag_add_clocks() - */ - if (ft2232_stableclocks(cmd->cmd.stableclocks->num_cycles, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - DEBUG_JTAG_IO("clocks %i while in %s", - cmd->cmd.stableclocks->num_cycles, - tap_state_name(tap_get_state())); - return retval; -} - -static int ft2232_execute_command(struct jtag_command *cmd) -{ - int retval; - - switch (cmd->type) { - case JTAG_RESET: - retval = ft2232_execute_reset(cmd); - break; - case JTAG_RUNTEST: - retval = ft2232_execute_runtest(cmd); - break; - case JTAG_TLR_RESET: - retval = ft2232_execute_statemove(cmd); - break; - case JTAG_PATHMOVE: - retval = ft2232_execute_pathmove(cmd); - break; - case JTAG_SCAN: - retval = ft2232_execute_scan(cmd); - break; - case JTAG_SLEEP: - retval = ft2232_execute_sleep(cmd); - break; - case JTAG_STABLECLOCKS: - retval = ft2232_execute_stableclocks(cmd); - break; - case JTAG_TMS: - retval = ft2232_execute_tms(cmd); - break; - default: - LOG_ERROR("BUG: unknown JTAG command type encountered"); - retval = ERROR_JTAG_QUEUE_FAILED; - break; - } - return retval; -} - -static int ft2232_execute_queue(void) -{ - struct jtag_command *cmd = jtag_command_queue; /* currently processed command */ - int retval; - - first_unsent = cmd; /* next command that has to be sent */ - require_send = 0; - - /* return ERROR_OK, unless ft2232_send_and_recv reports a failed check - * that wasn't handled by a caller-provided error handler - */ - retval = ERROR_OK; - - ft2232_buffer_size = 0; - ft2232_expect_read = 0; - - /* blink, if the current layout has that feature */ - if (layout->blink) - layout->blink(); - - while (cmd) { - /* fill the write buffer with the desired command */ - if (ft2232_execute_command(cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - /* Start reading input before FT2232 TX buffer fills up. - * Sometimes this happens because we don't know the - * length of the last command before we execute it. So - * we simple inform the user. - */ - cmd = cmd->next; - - if (ft2232_expect_read >= FT2232_BUFFER_READ_QUEUE_SIZE) { - if (ft2232_expect_read > (FT2232_BUFFER_READ_QUEUE_SIZE+1)) - LOG_DEBUG("read buffer size looks too high %d/%d", - ft2232_expect_read, - (FT2232_BUFFER_READ_QUEUE_SIZE+1)); - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - first_unsent = cmd; - } - } - - if (require_send > 0) - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - - return retval; -} - -#if BUILD_FT2232_FTD2XX == 1 -static int ft2232_init_ftd2xx(uint16_t vid, uint16_t pid, int more, int *try_more) -{ - FT_STATUS status; - DWORD deviceID; - char SerialNumber[16]; - char Description[64]; - DWORD openex_flags = 0; - char *openex_string = NULL; - uint8_t latency_timer; - - if (layout == NULL) { - LOG_WARNING("No ft2232 layout specified'"); - return ERROR_JTAG_INIT_FAILED; - } - - LOG_DEBUG("'ft2232' interface using FTD2XX with '%s' layout (%4.4x:%4.4x)", - layout->name, vid, pid); - -#if IS_WIN32 == 0 - /* Add non-standard Vid/Pid to the linux driver */ - status = FT_SetVIDPID(vid, pid); - if (status != FT_OK) - LOG_WARNING("couldn't add %4.4x:%4.4x", vid, pid); - -#endif - - if (ft2232_device_desc && ft2232_serial) { - LOG_WARNING( - "can't open by device description and serial number, giving precedence to serial"); - ft2232_device_desc = NULL; - } - - if (ft2232_device_desc) { - openex_string = ft2232_device_desc; - openex_flags = FT_OPEN_BY_DESCRIPTION; - } else if (ft2232_serial) { - openex_string = ft2232_serial; - openex_flags = FT_OPEN_BY_SERIAL_NUMBER; - } else { - LOG_ERROR("neither device description nor serial number specified"); - LOG_ERROR( - "please add \"ft2232_device_desc \" or \"ft2232_serial \" to your .cfg file"); - - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_OpenEx(openex_string, openex_flags, &ftdih); - if (status != FT_OK) { - /* under Win32, the FTD2XX driver appends an "A" to the end - * of the description, if we tried by the desc, then - * try by the alternate "A" description. */ - if (openex_string == ft2232_device_desc) { - /* Try the alternate method. */ - openex_string = ft2232_device_desc_A; - status = FT_OpenEx(openex_string, openex_flags, &ftdih); - if (status == FT_OK) { - /* yea, the "alternate" method worked! */ - } else { - /* drat, give the user a meaningfull message. - * telling the use we tried *BOTH* methods. */ - LOG_WARNING("Unable to open FTDI Device tried: '%s' and '%s'", - ft2232_device_desc, - ft2232_device_desc_A); - } - } - } - - if (status != FT_OK) { - DWORD num_devices; - - if (more) { - LOG_WARNING("unable to open ftdi device (trying more): %s", - ftd2xx_status_string(status)); - *try_more = 1; - return ERROR_JTAG_INIT_FAILED; - } - LOG_ERROR("unable to open ftdi device: %s", - ftd2xx_status_string(status)); - status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY); - if (status == FT_OK) { - char **desc_array = malloc(sizeof(char *) * (num_devices + 1)); - uint32_t i; - - for (i = 0; i < num_devices; i++) - desc_array[i] = malloc(64); - - desc_array[num_devices] = NULL; - - status = FT_ListDevices(desc_array, &num_devices, FT_LIST_ALL | openex_flags); - - if (status == FT_OK) { - LOG_ERROR("ListDevices: %" PRIu32, (uint32_t)num_devices); - for (i = 0; i < num_devices; i++) - LOG_ERROR("%" PRIu32 ": \"%s\"", i, desc_array[i]); - } - - for (i = 0; i < num_devices; i++) - free(desc_array[i]); - - free(desc_array); - } else - LOG_ERROR("ListDevices: NONE"); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_SetLatencyTimer(ftdih, ft2232_latency); - if (status != FT_OK) { - LOG_ERROR("unable to set latency timer: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_GetLatencyTimer(ftdih, &latency_timer); - if (status != FT_OK) { - /* ftd2xx 1.04 (linux) has a bug when calling FT_GetLatencyTimer - * so ignore errors if using this driver version */ - DWORD dw_version; - - status = FT_GetDriverVersion(ftdih, &dw_version); - LOG_ERROR("unable to get latency timer: %s", - ftd2xx_status_string(status)); - - if ((status == FT_OK) && (dw_version == 0x10004)) { - LOG_ERROR("ftd2xx 1.04 detected - this has known issues " \ - "with FT_GetLatencyTimer, upgrade to a newer version"); - } else - return ERROR_JTAG_INIT_FAILED; - } else - LOG_DEBUG("current latency timer: %i", latency_timer); - - status = FT_SetTimeouts(ftdih, 5000, 5000); - if (status != FT_OK) { - LOG_ERROR("unable to set timeouts: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_SetBitMode(ftdih, 0x0b, 2); - if (status != FT_OK) { - LOG_ERROR("unable to enable bit i/o mode: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_GetDeviceInfo(ftdih, &ftdi_device, &deviceID, - SerialNumber, Description, NULL); - if (status != FT_OK) { - LOG_ERROR("unable to get FT_GetDeviceInfo: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_INIT_FAILED; - } else { - static const char *type_str[] = { - "BM", "AM", "100AX", "UNKNOWN", "2232C", "232R", "2232H", "4232H", "232H" - }; - unsigned no_of_known_types = ARRAY_SIZE(type_str) - 1; - unsigned type_index = ((unsigned)ftdi_device <= no_of_known_types) - ? ftdi_device : FT_DEVICE_UNKNOWN; - LOG_INFO("device: %" PRIu32 " \"%s\"", (uint32_t)ftdi_device, type_str[type_index]); - LOG_INFO("deviceID: %" PRIu32, (uint32_t)deviceID); - LOG_INFO("SerialNumber: %s", SerialNumber); - LOG_INFO("Description: %s", Description); - } - - return ERROR_OK; -} - -static int ft2232_purge_ftd2xx(void) -{ - FT_STATUS status; - - status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX); - if (status != FT_OK) { - LOG_ERROR("error purging ftd2xx device: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -#endif /* BUILD_FT2232_FTD2XX == 1 */ - -#if BUILD_FT2232_LIBFTDI == 1 -static int ft2232_init_libftdi(uint16_t vid, uint16_t pid, int more, int *try_more, int channel) -{ - uint8_t latency_timer; - - if (layout == NULL) { - LOG_WARNING("No ft2232 layout specified'"); - return ERROR_JTAG_INIT_FAILED; - } - - LOG_DEBUG("'ft2232' interface using libftdi with '%s' layout (%4.4x:%4.4x)", - layout->name, vid, pid); - - if (ftdi_init(&ftdic) < 0) - return ERROR_JTAG_INIT_FAILED; - - /* default to INTERFACE_A */ - if (channel == INTERFACE_ANY) - channel = INTERFACE_A; - if (ftdi_set_interface(&ftdic, channel) < 0) { - LOG_ERROR("unable to select FT2232 channel A: %s", ftdic.error_str); - return ERROR_JTAG_INIT_FAILED; - } - - /* context, vendor id, product id */ - if (ftdi_usb_open_desc(&ftdic, vid, pid, ft2232_device_desc, ft2232_serial) < 0) { - if (more) - LOG_WARNING("unable to open ftdi device (trying more): %s", - ftdic.error_str); - else - LOG_ERROR("unable to open ftdi device: %s", ftdic.error_str); - *try_more = 1; - return ERROR_JTAG_INIT_FAILED; - } - - /* There is already a reset in ftdi_usb_open_desc, this should be redundant */ - if (ftdi_usb_reset(&ftdic) < 0) { - LOG_ERROR("unable to reset ftdi device"); - return ERROR_JTAG_INIT_FAILED; - } - - if (ftdi_set_latency_timer(&ftdic, ft2232_latency) < 0) { - LOG_ERROR("unable to set latency timer"); - return ERROR_JTAG_INIT_FAILED; - } - - if (ftdi_get_latency_timer(&ftdic, &latency_timer) < 0) { - LOG_ERROR("unable to get latency timer"); - return ERROR_JTAG_INIT_FAILED; - } else - LOG_DEBUG("current latency timer: %i", latency_timer); - - ftdi_set_bitmode(&ftdic, 0x0b, 2); /* ctx, JTAG I/O mask */ - - ftdi_device = ftdic.type; - static const char *type_str[] = { - "AM", "BM", "2232C", "R", "2232H", "4232H", "232H", "Unknown" - }; - unsigned no_of_known_types = ARRAY_SIZE(type_str) - 1; - unsigned type_index = ((unsigned)ftdi_device < no_of_known_types) - ? ftdi_device : no_of_known_types; - LOG_DEBUG("FTDI chip type: %i \"%s\"", (int)ftdi_device, type_str[type_index]); - return ERROR_OK; -} - -static int ft2232_purge_libftdi(void) -{ - if (ftdi_usb_purge_buffers(&ftdic) < 0) { - LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -#endif /* BUILD_FT2232_LIBFTDI == 1 */ - -static int ft2232_set_data_bits_low_byte(uint8_t value, uint8_t direction) -{ - uint8_t buf[3]; - uint32_t bytes_written; - - buf[0] = 0x80; /* command "set data bits low byte" */ - buf[1] = value; /* value */ - buf[2] = direction; /* direction */ - - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { - LOG_ERROR("couldn't initialize data bits low byte"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int ft2232_set_data_bits_high_byte(uint8_t value, uint8_t direction) -{ - uint8_t buf[3]; - uint32_t bytes_written; - - buf[0] = 0x82; /* command "set data bits high byte" */ - buf[1] = value; /* value */ - buf[2] = direction; /* direction */ - - LOG_DEBUG("%2.2x %2.2x %2.2x", buf[0], buf[1], buf[2]); - - if (ft2232_write(buf, sizeof(buf), &bytes_written) != ERROR_OK) { - LOG_ERROR("couldn't initialize data bits high byte"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int ft2232_init(void) -{ - uint8_t buf[1]; - int retval; - uint32_t bytes_written; - - LOG_WARNING("Using DEPRECATED interface driver 'ft2232'"); -#if BUILD_FTDI - LOG_INFO("Consider using the 'ftdi' interface driver, with configuration files in interface/ftdi/..."); -#endif - - if (tap_get_tms_path_len(TAP_IRPAUSE, TAP_IRPAUSE) == 7) - LOG_DEBUG("ft2232 interface using 7 step jtag state transitions"); - else - LOG_DEBUG("ft2232 interface using shortest path jtag state transitions"); - if (layout == NULL) { - LOG_WARNING("No ft2232 layout specified'"); - return ERROR_JTAG_INIT_FAILED; - } - - for (int i = 0; 1; i++) { - /* - * "more indicates that there are more IDs to try, so we should - * not print an error for an ID mismatch (but for anything - * else, we should). - * - * try_more indicates that the error code returned indicates an - * ID mismatch (and nothing else) and that we should proceeed - * with the next ID pair. - */ - int more = ft2232_vid[i + 1] || ft2232_pid[i + 1]; - int try_more = 0; - -#if BUILD_FT2232_FTD2XX == 1 - retval = ft2232_init_ftd2xx(ft2232_vid[i], ft2232_pid[i], - more, &try_more); -#elif BUILD_FT2232_LIBFTDI == 1 - retval = ft2232_init_libftdi(ft2232_vid[i], ft2232_pid[i], - more, &try_more, ft2232_channel); -#endif - if (retval >= 0) - break; - if (!more || !try_more) - return retval; - } - - ft2232_buffer_size = 0; - ft2232_buffer = malloc(FT2232_BUFFER_SIZE); - - if (layout->init() != ERROR_OK) - return ERROR_JTAG_INIT_FAILED; - - if (ft2232_device_is_highspeed()) { -#ifndef BUILD_FT2232_HIGHSPEED - #if BUILD_FT2232_FTD2XX == 1 - LOG_WARNING( - "High Speed device found - You need a newer FTD2XX driver (version 2.04.16 or later)"); - #elif BUILD_FT2232_LIBFTDI == 1 - LOG_WARNING( - "High Speed device found - You need a newer libftdi version (0.16 or later)"); - #endif -#endif - /* make sure the legacy mode is disabled */ - if (ftx232h_clk_divide_by_5(false) != ERROR_OK) - return ERROR_JTAG_INIT_FAILED; - } - - buf[0] = 0x85; /* Disconnect TDI/DO to TDO/DI for Loopback */ - retval = ft2232_write(buf, 1, &bytes_written); - if (retval != ERROR_OK) { - LOG_ERROR("couldn't write to FT2232 to disable loopback"); - return ERROR_JTAG_INIT_FAILED; - } - -#if BUILD_FT2232_FTD2XX == 1 - return ft2232_purge_ftd2xx(); -#elif BUILD_FT2232_LIBFTDI == 1 - return ft2232_purge_libftdi(); -#endif - - return ERROR_OK; -} - -/** Updates defaults for DBUS signals: the four JTAG signals - * (TCK, TDI, TDO, TMS) and * the four GPIOL signals. - */ -static inline void ftx232_dbus_init(void) -{ - low_output = 0x08; - low_direction = 0x0b; -} - -/** Initializes DBUS signals: the four JTAG signals (TCK, TDI, TDO, TMS), - * the four GPIOL signals. Initialization covers value and direction, - * as customized for each layout. - */ -static int ftx232_dbus_write(void) -{ - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { - low_direction &= ~nTRSTnOE; /* nTRST input */ - low_output &= ~nTRST; /* nTRST = 0 */ - } else { - low_direction |= nTRSTnOE; /* nTRST output */ - low_output |= nTRST; /* nTRST = 1 */ - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) { - low_direction |= nSRSTnOE; /* nSRST output */ - low_output |= nSRST; /* nSRST = 1 */ - } else { - low_direction &= ~nSRSTnOE; /* nSRST input */ - low_output &= ~nSRST; /* nSRST = 0 */ - } - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 DBUS"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int usbjtag_init(void) -{ - /* - * NOTE: This is now _specific_ to the "usbjtag" layout. - * Don't try cram any more layouts into this. - */ - ftx232_dbus_init(); - - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x40; - nSRSTnOE = 0x40; - - return ftx232_dbus_write(); -} - -static int lm3s811_jtag_init(void) -{ - ftx232_dbus_init(); - - /* There are multiple revisions of LM3S811 eval boards: - * - Rev B (and older?) boards have no SWO trace support. - * - Rev C boards add ADBUS_6 DBG_ENn and BDBUS_4 SWO_EN; - * they should use the "luminary_icdi" layout instead. - */ - nTRST = 0x0; - nTRSTnOE = 0x00; - nSRST = 0x20; - nSRSTnOE = 0x20; - low_output = 0x88; - low_direction = 0x8b; - - return ftx232_dbus_write(); -} - -static int icdi_jtag_init(void) -{ - ftx232_dbus_init(); - - /* Most Luminary eval boards support SWO trace output, - * and should use this "luminary_icdi" layout. - * - * ADBUS 0..3 are used for JTAG as usual. GPIOs are used - * to switch between JTAG and SWD, or switch the ft2232 UART - * on the second MPSSE channel/interface (BDBUS) - * between (i) the stellaris UART (on Luminary boards) - * or (ii) SWO trace data (generic). - * - * We come up in JTAG mode and may switch to SWD later (with - * SWO/trace option if SWD is active). - * - * DBUS == GPIO-Lx - * CBUS == GPIO-Hx - */ - - -#define ICDI_JTAG_EN (1 << 7) /* ADBUS 7 (a.k.a. DBGMOD) */ -#define ICDI_DBG_ENn (1 << 6) /* ADBUS 6 */ -#define ICDI_SRST (1 << 5) /* ADBUS 5 */ - - - /* GPIOs on second channel/interface (UART) ... */ -#define ICDI_SWO_EN (1 << 4) /* BDBUS 4 */ -#define ICDI_TX_SWO (1 << 1) /* BDBUS 1 */ -#define ICDI_VCP_RX (1 << 0) /* BDBUS 0 (to stellaris UART) */ - - nTRST = 0x0; - nTRSTnOE = 0x00; - nSRST = ICDI_SRST; - nSRSTnOE = ICDI_SRST; - - low_direction |= ICDI_JTAG_EN | ICDI_DBG_ENn; - low_output |= ICDI_JTAG_EN; - low_output &= ~ICDI_DBG_ENn; - - return ftx232_dbus_write(); -} - -static int signalyzer_init(void) -{ - ftx232_dbus_init(); - - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x20; - nSRSTnOE = 0x20; - return ftx232_dbus_write(); -} - -static int axm0432_jtag_init(void) -{ - low_output = 0x08; - low_direction = 0x2b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - if (strcmp(layout->name, "axm0432_jtag") == 0) { - nTRST = 0x08; - nTRSTnOE = 0x0; /* No output enable for TRST*/ - nSRST = 0x04; - nSRSTnOE = 0x0; /* No output enable for SRST*/ - } else { - LOG_ERROR("BUG: axm0432_jtag_init called for non axm0432 layout"); - exit(-1); - } - - high_output = 0x0; - high_direction = 0x0c; - - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - LOG_ERROR("can't set nTRSTOE to push-pull on the Dicarlo jtag"); - else - high_output |= nTRST; - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - LOG_ERROR("can't set nSRST to push-pull on the Dicarlo jtag"); - else - high_output |= nSRST; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'Dicarlo' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int redbee_init(void) -{ - low_output = 0x08; - low_direction = 0x2b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'redbee' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x08; - nTRSTnOE = 0x0; /* No output enable for TRST*/ - nSRST = 0x04; - nSRSTnOE = 0x0; /* No output enable for SRST*/ - - high_output = 0x0; - high_direction = 0x0c; - - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - LOG_ERROR("can't set nTRSTOE to push-pull on redbee"); - else - high_output |= nTRST; - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - LOG_ERROR("can't set nSRST to push-pull on redbee"); - else - high_output |= nSRST; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'redbee' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int jtagkey_init(void) -{ - low_output = 0x08; - low_direction = 0x1b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - if (strcmp(layout->name, "jtagkey") == 0) { - nTRST = 0x01; - nTRSTnOE = 0x4; - nSRST = 0x02; - nSRSTnOE = 0x08; - } else if ((strcmp(layout->name, "jtagkey_prototype_v1") == 0) - || (strcmp(layout->name, "oocdlink") == 0)) { - nTRST = 0x02; - nTRSTnOE = 0x1; - nSRST = 0x08; - nSRSTnOE = 0x04; - } else { - LOG_ERROR("BUG: jtagkey_init called for non jtagkey layout"); - exit(-1); - } - - high_output = 0x0; - high_direction = 0x0f; - - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { - high_output |= nTRSTnOE; - high_output &= ~nTRST; - } else { - high_output &= ~nTRSTnOE; - high_output |= nTRST; - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) { - high_output &= ~nSRSTnOE; - high_output |= nSRST; - } else { - high_output |= nSRSTnOE; - high_output &= ~nSRST; - } - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'JTAGkey' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int olimex_jtag_init(void) -{ - low_output = 0x08; - low_direction = 0x1b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x01; - nTRSTnOE = 0x4; - nSRST = 0x02; - nSRSTnOE = 0x00;/* no output enable for nSRST */ - - high_output = 0x0; - high_direction = 0x0f; - - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { - high_output |= nTRSTnOE; - high_output &= ~nTRST; - } else { - high_output &= ~nTRSTnOE; - high_output |= nTRST; - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - LOG_ERROR("can't set nSRST to push-pull on the Olimex ARM-USB-OCD"); - else - high_output &= ~nSRST; - - /* turn red LED on */ - high_output |= 0x08; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'Olimex' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int flyswatter_init(int rev) -{ - low_output = 0x18; - low_direction = 0x7b; - - if ((rev < 0) || (rev > 3)) { - LOG_ERROR("bogus 'flyswatter' revision supplied (%i)", rev); - return ERROR_JTAG_INIT_FAILED; - } - - if (rev == 1) - low_direction |= 1 << 7; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x10; - nTRSTnOE = 0x0; /* not output enable for nTRST */ - nSRST = 0x20; - nSRSTnOE = 0x00; /* no output enable for nSRST */ - - high_output = 0x00; - - if (rev == 1) - high_direction = 0x0c; - else - high_direction = 0x01; - - /* turn red LED3 on, LED2 off */ - high_output |= 0x08; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'flyswatter' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int flyswatter1_init(void) -{ - return flyswatter_init(1); -} - -static int flyswatter2_init(void) -{ - return flyswatter_init(2); -} - -static int minimodule_init(void) -{ - low_output = 0x18; /* check if srst should be 1 or 0 initially. (0x08) (flyswatter was - * 0x18) */ - low_direction = 0xfb; /* 0xfb; */ - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'minimodule' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - - nSRST = 0x20; - - high_output = 0x00; - high_direction = 0x05; - - /* turn red LED3 on, LED2 off */ - /* high_output |= 0x08; */ - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'minimodule' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int turtle_init(void) -{ - low_output = 0x08; - low_direction = 0x5b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nSRST = 0x40; - - high_output = 0x00; - high_direction = 0x0C; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'turtelizer2' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int comstick_init(void) -{ - low_output = 0x08; - low_direction = 0x0b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x01; - nTRSTnOE = 0x00; /* no output enable for nTRST */ - nSRST = 0x02; - nSRSTnOE = 0x00; /* no output enable for nSRST */ - - high_output = 0x03; - high_direction = 0x03; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'comstick' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int stm32stick_init(void) -{ - low_output = 0x88; - low_direction = 0x8b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x01; - nTRSTnOE = 0x00; /* no output enable for nTRST */ - nSRST = 0x80; - nSRSTnOE = 0x00; /* no output enable for nSRST */ - - high_output = 0x01; - high_direction = 0x03; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'stm32stick' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int sheevaplug_init(void) -{ - low_output = 0x08; - low_direction = 0x1b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRSTnOE = 0x1; - nTRST = 0x02; - nSRSTnOE = 0x4; - nSRST = 0x08; - - high_output = 0x0; - high_direction = 0x0f; - - /* nTRST is always push-pull */ - high_output &= ~nTRSTnOE; - high_output |= nTRST; - - /* nSRST is always open-drain */ - high_output |= nSRSTnOE; - high_output &= ~nSRST; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'sheevaplug' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int cortino_jtag_init(void) -{ - low_output = 0x08; - low_direction = 0x1b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'cortino' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x01; - nTRSTnOE = 0x00; /* no output enable for nTRST */ - nSRST = 0x02; - nSRSTnOE = 0x00; /* no output enable for nSRST */ - - high_output = 0x03; - high_direction = 0x03; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'cortino' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static int lisa_l_init(void) -{ - ftx232_dbus_init(); - - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x40; - nSRSTnOE = 0x40; - - high_output = 0x00; - high_direction = 0x18; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'lisa_l' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ftx232_dbus_write(); -} - -static int flossjtag_init(void) -{ - ftx232_dbus_init(); - - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x40; - nSRSTnOE = 0x40; - - high_output = 0x00; - high_direction = 0x18; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'Floss-JTAG' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ftx232_dbus_write(); -} - -/* - * The reference schematic from TI for the XDS100v2 has a CPLD on which opens - * the door for a number of different configurations - * - * Known Implementations: - * http://processors.wiki.ti.com/images/9/93/TMS570LS20216_USB_STICK_Schematic.pdf - * - * http://processors.wiki.ti.com/index.php/XDS100 (rev2) - * * CLPD logic: Rising edge to enable outputs (XDS100_PWR_RST) - * * ACBUS3 to transition 0->1 (OE rising edge) - * * CPLD logic: Put the EMU0/1 pins in Hi-Z: - * * ADBUS5/GPIOL1 = EMU_EN = 1 - * * ADBUS6/GPIOL2 = EMU0 = 0 - * * ACBUS4/SPARE0 = EMU1 = 0 - * * CPLD logic: Disable loopback - * * ACBUS6/SPARE2 = LOOPBACK = 0 - */ -#define XDS100_nEMU_EN (1<<5) -#define XDS100_nEMU0 (1<<6) - -#define XDS100_PWR_RST (1<<3) -#define XDS100_nEMU1 (1<<4) -#define XDS100_LOOPBACK (1<<6) -static int xds100v2_init(void) -{ - /* These are in the lower byte */ - nTRST = 0x10; - nTRSTnOE = 0x10; - - /* These aren't actually used on 14 pin connectors - * These are in the upper byte */ - nSRST = 0x01; - nSRSTnOE = 0x01; - - low_output = 0x08 | nTRST | XDS100_nEMU_EN; - low_direction = 0x0b | nTRSTnOE | XDS100_nEMU_EN | XDS100_nEMU0; - - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'xds100v2' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - high_output = 0; - high_direction = nSRSTnOE | XDS100_LOOPBACK | XDS100_PWR_RST | XDS100_nEMU1; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't put CPLD in to reset with 'xds100v2' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - high_output |= XDS100_PWR_RST; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't bring CPLD out of reset with 'xds100v2' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static void olimex_jtag_blink(void) -{ - /* Olimex ARM-USB-OCD has a LED connected to ACBUS3 - * ACBUS3 is bit 3 of the GPIOH port - */ - high_output ^= 0x08; - - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); -} - -static void flyswatter_jtag_blink(unsigned char led) -{ - buffer_write(0x82); - buffer_write(high_output ^ led); - buffer_write(high_direction); -} - -static void flyswatter1_jtag_blink(void) -{ - /* - * Flyswatter has two LEDs connected to ACBUS2 and ACBUS3 - */ - flyswatter_jtag_blink(0xc); -} - -static void flyswatter2_jtag_blink(void) -{ - /* - * Flyswatter2 only has one LED connected to ACBUS2 - */ - flyswatter_jtag_blink(0x4); -} - -static void turtle_jtag_blink(void) -{ - /* - * Turtelizer2 has two LEDs connected to ACBUS2 and ACBUS3 - */ - if (high_output & 0x08) - high_output = 0x04; - else - high_output = 0x08; - - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); -} - -static void lisa_l_blink(void) -{ - /* - * Lisa/L has two LEDs connected to BCBUS3 and BCBUS4 - */ - if (high_output & 0x10) - high_output = 0x08; - else - high_output = 0x10; - - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); -} - -static void flossjtag_blink(void) -{ - /* - * Floss-JTAG has two LEDs connected to ACBUS3 and ACBUS4 - */ - if (high_output & 0x10) - high_output = 0x08; - else - high_output = 0x10; - - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); -} - -static int ft2232_quit(void) -{ -#if BUILD_FT2232_FTD2XX == 1 - - FT_Close(ftdih); -#elif BUILD_FT2232_LIBFTDI == 1 - ftdi_usb_close(&ftdic); - - ftdi_deinit(&ftdic); -#endif - - free(ft2232_buffer); - ft2232_buffer = NULL; - - return ERROR_OK; -} - -COMMAND_HANDLER(ft2232_handle_device_desc_command) -{ - char *cp; - char buf[200]; - if (CMD_ARGC == 1) { - ft2232_device_desc = strdup(CMD_ARGV[0]); - cp = strchr(ft2232_device_desc, 0); - /* under Win32, the FTD2XX driver appends an "A" to the end - * of the description, this examines the given desc - * and creates the 'missing' _A or non_A variable. */ - if ((cp[-1] == 'A') && (cp[-2] == ' ')) { - /* it was, so make this the "A" version. */ - ft2232_device_desc_A = ft2232_device_desc; - /* and *CREATE* the non-A version. */ - strcpy(buf, ft2232_device_desc); - cp = strchr(buf, 0); - cp[-2] = 0; - ft2232_device_desc = strdup(buf); - } else { - /* A not defined - * so create it */ - sprintf(buf, "%s A", ft2232_device_desc); - ft2232_device_desc_A = strdup(buf); - } - } else - LOG_ERROR("expected exactly one argument to ft2232_device_desc "); - - return ERROR_OK; -} - -COMMAND_HANDLER(ft2232_handle_serial_command) -{ - if (CMD_ARGC == 1) - ft2232_serial = strdup(CMD_ARGV[0]); - else - return ERROR_COMMAND_SYNTAX_ERROR; - - return ERROR_OK; -} - -COMMAND_HANDLER(ft2232_handle_layout_command) -{ - if (CMD_ARGC != 1) - return ERROR_COMMAND_SYNTAX_ERROR; - - if (layout) { - LOG_ERROR("already specified ft2232_layout %s", - layout->name); - return (strcmp(layout->name, CMD_ARGV[0]) != 0) - ? ERROR_FAIL - : ERROR_OK; - } - - for (const struct ft2232_layout *l = ft2232_layouts; l->name; l++) { - if (strcmp(l->name, CMD_ARGV[0]) == 0) { - layout = l; - ft2232_channel = l->channel; - return ERROR_OK; - } - } - - LOG_ERROR("No FT2232 layout '%s' found", CMD_ARGV[0]); - return ERROR_FAIL; -} - -COMMAND_HANDLER(ft2232_handle_vid_pid_command) -{ - if (CMD_ARGC > MAX_USB_IDS * 2) { - LOG_WARNING("ignoring extra IDs in ft2232_vid_pid " - "(maximum is %d pairs)", MAX_USB_IDS); - CMD_ARGC = MAX_USB_IDS * 2; - } - if (CMD_ARGC < 2 || (CMD_ARGC & 1)) { - LOG_WARNING("incomplete ft2232_vid_pid configuration directive"); - if (CMD_ARGC < 2) - return ERROR_COMMAND_SYNTAX_ERROR; - /* remove the incomplete trailing id */ - CMD_ARGC -= 1; - } - - unsigned i; - for (i = 0; i < CMD_ARGC; i += 2) { - COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i], ft2232_vid[i >> 1]); - COMMAND_PARSE_NUMBER(u16, CMD_ARGV[i + 1], ft2232_pid[i >> 1]); - } - - /* - * Explicitly terminate, in case there are multiples instances of - * ft2232_vid_pid. - */ - ft2232_vid[i >> 1] = ft2232_pid[i >> 1] = 0; - - return ERROR_OK; -} - -COMMAND_HANDLER(ft2232_handle_latency_command) -{ - if (CMD_ARGC == 1) - ft2232_latency = atoi(CMD_ARGV[0]); - else - return ERROR_COMMAND_SYNTAX_ERROR; - - return ERROR_OK; -} - -COMMAND_HANDLER(ft2232_handle_channel_command) -{ - if (CMD_ARGC == 1) { - ft2232_channel = atoi(CMD_ARGV[0]); - if (ft2232_channel < 0 || ft2232_channel > 4) - LOG_ERROR("ft2232_channel must be in the 0 to 4 range"); - } else - LOG_ERROR("expected exactly one argument to ft2232_channel "); - - return ERROR_OK; -} - -static int ft2232_stableclocks(int num_cycles, struct jtag_command *cmd) -{ - int retval = 0; - - /* 7 bits of either ones or zeros. */ - uint8_t tms = (tap_get_state() == TAP_RESET ? 0x7F : 0x00); - - while (num_cycles > 0) { - /* the command 0x4b, "Clock Data to TMS/CS Pin (no Read)" handles - * at most 7 bits per invocation. Here we invoke it potentially - * several times. - */ - int bitcount_per_command = (num_cycles > 7) ? 7 : num_cycles; - - if (ft2232_buffer_size + 3 >= FT2232_BUFFER_SIZE) { - if (ft2232_send_and_recv(first_unsent, cmd) != ERROR_OK) - retval = ERROR_JTAG_QUEUE_FAILED; - - first_unsent = cmd; - } - - /* there are no state transitions in this code, so omit state tracking */ - - /* command "Clock Data to TMS/CS Pin (no Read)" */ - buffer_write(0x4b); - - /* scan 7 bit */ - buffer_write(bitcount_per_command - 1); - - /* TMS data bits are either all zeros or ones to stay in the current stable state */ - buffer_write(tms); - - require_send = 1; - - num_cycles -= bitcount_per_command; - } - - return retval; -} - -/* --------------------------------------------------------------------- - * Support for IceBear JTAG adapter from Section5: - * http://section5.ch/icebear - * - * Author: Sten, debian@sansys-electronic.com - */ - -/* Icebear pin layout - * - * ADBUS5 (nEMU) nSRST | 2 1| GND (10k->VCC) - * GND GND | 4 3| n.c. - * ADBUS3 TMS | 6 5| ADBUS6 VCC - * ADBUS0 TCK | 8 7| ADBUS7 (GND) - * ADBUS4 nTRST |10 9| ACBUS0 (GND) - * ADBUS1 TDI |12 11| ACBUS1 (GND) - * ADBUS2 TDO |14 13| GND GND - * - * ADBUS0 O L TCK ACBUS0 GND - * ADBUS1 O L TDI ACBUS1 GND - * ADBUS2 I TDO ACBUS2 n.c. - * ADBUS3 O H TMS ACBUS3 n.c. - * ADBUS4 O H nTRST - * ADBUS5 O H nSRST - * ADBUS6 - VCC - * ADBUS7 - GND - */ -static int icebear_jtag_init(void) -{ - low_direction = 0x0b; /* output: TCK TDI TMS; input: TDO */ - low_output = 0x08; /* high: TMS; low: TCK TDI */ - nTRST = 0x10; - nSRST = 0x20; - - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if ((jtag_reset_config & RESET_TRST_OPEN_DRAIN) != 0) - low_direction &= ~nTRST; /* nTRST high impedance */ - else { - low_direction |= nTRST; - low_output |= nTRST; - } - - low_direction |= nSRST; - low_output |= nSRST; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (low)"); - return ERROR_JTAG_INIT_FAILED; - } - - high_output = 0x0; - high_direction = 0x00; - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'IceBear' layout (high)"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static void icebear_jtag_reset(int trst, int srst) -{ - if (trst == 1) { - low_direction |= nTRST; - low_output &= ~nTRST; - } else if (trst == 0) { - enum reset_types jtag_reset_config = jtag_get_reset_config(); - if ((jtag_reset_config & RESET_TRST_OPEN_DRAIN) != 0) - low_direction &= ~nTRST; - else - low_output |= nTRST; - } - - if (srst == 1) - low_output &= ~nSRST; - else if (srst == 0) - low_output |= nSRST; - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); - - LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, low_direction: 0x%2.2x", - trst, - srst, - low_output, - low_direction); -} - -/* --------------------------------------------------------------------- - * Support for Signalyzer H2 and Signalyzer H4 - * JTAG adapter from Xverve Technologies Inc. - * http://www.signalyzer.com or http://www.xverve.com - * - * Author: Oleg Seiljus, oleg@signalyzer.com - */ -static unsigned char signalyzer_h_side; -static unsigned int signalyzer_h_adapter_type; - -static int signalyzer_h_ctrl_write(int address, unsigned short value); - -#if BUILD_FT2232_FTD2XX == 1 -static int signalyzer_h_ctrl_read(int address, unsigned short *value); -#endif - -#define SIGNALYZER_COMMAND_ADDR 128 -#define SIGNALYZER_DATA_BUFFER_ADDR 129 - -#define SIGNALYZER_COMMAND_VERSION 0x41 -#define SIGNALYZER_COMMAND_RESET 0x42 -#define SIGNALYZER_COMMAND_POWERCONTROL_GET 0x50 -#define SIGNALYZER_COMMAND_POWERCONTROL_SET 0x51 -#define SIGNALYZER_COMMAND_PWM_SET 0x52 -#define SIGNALYZER_COMMAND_LED_SET 0x53 -#define SIGNALYZER_COMMAND_ADC 0x54 -#define SIGNALYZER_COMMAND_GPIO_STATE 0x55 -#define SIGNALYZER_COMMAND_GPIO_MODE 0x56 -#define SIGNALYZER_COMMAND_GPIO_PORT 0x57 -#define SIGNALYZER_COMMAND_I2C 0x58 - -#define SIGNALYZER_CHAN_A 1 -#define SIGNALYZER_CHAN_B 2 -/* LEDS use channel C */ -#define SIGNALYZER_CHAN_C 4 - -#define SIGNALYZER_LED_GREEN 1 -#define SIGNALYZER_LED_RED 2 - -#define SIGNALYZER_MODULE_TYPE_EM_LT16_A 0x0301 -#define SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG 0x0302 -#define SIGNALYZER_MODULE_TYPE_EM_JTAG 0x0303 -#define SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P 0x0304 -#define SIGNALYZER_MODULE_TYPE_EM_JTAG_P 0x0305 - - -static int signalyzer_h_ctrl_write(int address, unsigned short value) -{ -#if BUILD_FT2232_FTD2XX == 1 - return FT_WriteEE(ftdih, address, value); -#elif BUILD_FT2232_LIBFTDI == 1 - return 0; -#endif -} - -#if BUILD_FT2232_FTD2XX == 1 -static int signalyzer_h_ctrl_read(int address, unsigned short *value) -{ - return FT_ReadEE(ftdih, address, value); -} -#endif - -static int signalyzer_h_led_set(unsigned char channel, unsigned char led, - int on_time_ms, int off_time_ms, unsigned char cycles) -{ - unsigned char on_time; - unsigned char off_time; - - if (on_time_ms < 0xFFFF) - on_time = (unsigned char)(on_time_ms / 62); - else - on_time = 0xFF; - - off_time = (unsigned char)(off_time_ms / 62); - -#if BUILD_FT2232_FTD2XX == 1 - FT_STATUS status; - - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - ((uint32_t)(channel << 8) | led)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 1), - ((uint32_t)(on_time << 8) | off_time)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 2), - ((uint32_t)cycles)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_LED_SET); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - return ERROR_OK; -#elif BUILD_FT2232_LIBFTDI == 1 - int retval; - - retval = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - ((uint32_t)(channel << 8) | led)); - if (retval < 0) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } - - retval = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 1), - ((uint32_t)(on_time << 8) | off_time)); - if (retval < 0) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } - - retval = signalyzer_h_ctrl_write((SIGNALYZER_DATA_BUFFER_ADDR + 2), - (uint32_t)cycles); - if (retval < 0) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } - - retval = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_LED_SET); - if (retval < 0) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftdi_get_error_string(&ftdic)); - return ERROR_JTAG_DEVICE_ERROR; - } - - return ERROR_OK; -#endif -} - -static int signalyzer_h_init(void) -{ -#if BUILD_FT2232_FTD2XX == 1 - FT_STATUS status; - int i; -#endif - - char *end_of_desc; - - uint16_t read_buf[12] = { 0 }; - - /* turn on center green led */ - signalyzer_h_led_set(SIGNALYZER_CHAN_C, SIGNALYZER_LED_GREEN, - 0xFFFF, 0x00, 0x00); - - /* determine what channel config wants to open - * TODO: change me... current implementation is made to work - * with openocd description parsing. - */ - end_of_desc = strrchr(ft2232_device_desc, 0x00); - - if (end_of_desc) { - signalyzer_h_side = *(end_of_desc - 1); - if (signalyzer_h_side == 'B') - signalyzer_h_side = SIGNALYZER_CHAN_B; - else - signalyzer_h_side = SIGNALYZER_CHAN_A; - } else { - LOG_ERROR("No Channel was specified"); - return ERROR_FAIL; - } - - signalyzer_h_led_set(signalyzer_h_side, SIGNALYZER_LED_GREEN, - 1000, 1000, 0xFF); - -#if BUILD_FT2232_FTD2XX == 1 - /* read signalyzer versionining information */ - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_VERSION); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - for (i = 0; i < 10; i++) { - status = signalyzer_h_ctrl_read((SIGNALYZER_DATA_BUFFER_ADDR + i), - &read_buf[i]); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_read returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - } - - LOG_INFO("Signalyzer: ID info: { %.4x %.4x %.4x %.4x %.4x %.4x %.4x }", - read_buf[0], read_buf[1], read_buf[2], read_buf[3], - read_buf[4], read_buf[5], read_buf[6]); - - /* set gpio register */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - (uint32_t)(signalyzer_h_side << 8)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0404); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_GPIO_STATE); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - /* read adapter type information */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - ((uint32_t)(signalyzer_h_side << 8) | 0x01)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write( - (SIGNALYZER_DATA_BUFFER_ADDR + 1), 0xA000); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write( - (SIGNALYZER_DATA_BUFFER_ADDR + 2), 0x0008); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_I2C); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - usleep(100000); - - status = signalyzer_h_ctrl_read(SIGNALYZER_COMMAND_ADDR, &read_buf[0]); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_read returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - if (read_buf[0] != 0x0498) - signalyzer_h_adapter_type = 0x0000; - else { - for (i = 0; i < 4; i++) { - status = signalyzer_h_ctrl_read((SIGNALYZER_DATA_BUFFER_ADDR + i), &read_buf[i]); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_read returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - } - - signalyzer_h_adapter_type = read_buf[0]; - } - -#elif BUILD_FT2232_LIBFTDI == 1 - /* currently libftdi does not allow reading individual eeprom - * locations, therefore adapter type cannot be detected. - * override with most common type - */ - signalyzer_h_adapter_type = SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG; -#endif - - enum reset_types jtag_reset_config = jtag_get_reset_config(); - - /* ADAPTOR: EM_LT16_A */ - if (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_LT16_A) { - LOG_INFO("Signalyzer: EM-LT (16-channel level translator) " - "detected. (HW: %2x).", (read_buf[1] >> 8)); - - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x20; - nSRSTnOE = 0x20; - - low_output = 0x08; - low_direction = 0x1b; - - high_output = 0x0; - high_direction = 0x0; - - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { - low_direction &= ~nTRSTnOE; /* nTRST input */ - low_output &= ~nTRST; /* nTRST = 0 */ - } else { - low_direction |= nTRSTnOE; /* nTRST output */ - low_output |= nTRST; /* nTRST = 1 */ - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) { - low_direction |= nSRSTnOE; /* nSRST output */ - low_output |= nSRST; /* nSRST = 1 */ - } else { - low_direction &= ~nSRSTnOE; /* nSRST input */ - low_output &= ~nSRST; /* nSRST = 0 */ - } - -#if BUILD_FT2232_FTD2XX == 1 - /* enable power to the module */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - ((uint32_t)(signalyzer_h_side << 8) | 0x01)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_POWERCONTROL_SET); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - /* set gpio mode register */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - (uint32_t)(signalyzer_h_side << 8)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0000); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_MODE); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - /* set gpio register */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - (uint32_t)(signalyzer_h_side << 8)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x4040); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_GPIO_STATE); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } -#endif - } - /* ADAPTOR: EM_ARM_JTAG, EM_ARM_JTAG_P, EM_JTAG, EM_JTAG_P */ - else if ((signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG) || - (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P) || - (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG) || - (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG_P)) { - if (signalyzer_h_adapter_type - == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG) - LOG_INFO("Signalyzer: EM-ARM-JTAG (ARM JTAG) " - "detected. (HW: %2x).", (read_buf[1] >> 8)); - else if (signalyzer_h_adapter_type - == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P) - LOG_INFO("Signalyzer: EM-ARM-JTAG_P " - "(ARM JTAG with PSU) detected. (HW: %2x).", - (read_buf[1] >> 8)); - else if (signalyzer_h_adapter_type - == SIGNALYZER_MODULE_TYPE_EM_JTAG) - LOG_INFO("Signalyzer: EM-JTAG (Generic JTAG) " - "detected. (HW: %2x).", (read_buf[1] >> 8)); - else if (signalyzer_h_adapter_type - == SIGNALYZER_MODULE_TYPE_EM_JTAG_P) - LOG_INFO("Signalyzer: EM-JTAG-P " - "(Generic JTAG with PSU) detected. (HW: %2x).", - (read_buf[1] >> 8)); - - nTRST = 0x02; - nTRSTnOE = 0x04; - nSRST = 0x08; - nSRSTnOE = 0x10; - - low_output = 0x08; - low_direction = 0x1b; - - high_output = 0x0; - high_direction = 0x1f; - - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { - high_output |= nTRSTnOE; - high_output &= ~nTRST; - } else { - high_output &= ~nTRSTnOE; - high_output |= nTRST; - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) { - high_output &= ~nSRSTnOE; - high_output |= nSRST; - } else { - high_output |= nSRSTnOE; - high_output &= ~nSRST; - } - -#if BUILD_FT2232_FTD2XX == 1 - /* enable power to the module */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - ((uint32_t)(signalyzer_h_side << 8) | 0x01)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, - SIGNALYZER_COMMAND_POWERCONTROL_SET); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - /* set gpio mode register (IO_16 and IO_17 set as analog - * inputs, other is gpio) - */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - (uint32_t)(signalyzer_h_side << 8)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0060); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_MODE); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - /* set gpio register (all inputs, for -P modules, - * PSU will be turned off) - */ - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR, - (uint32_t)(signalyzer_h_side << 8)); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_DATA_BUFFER_ADDR + 1, 0x0000); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - status = signalyzer_h_ctrl_write(SIGNALYZER_COMMAND_ADDR, SIGNALYZER_COMMAND_GPIO_STATE); - if (status != FT_OK) { - LOG_ERROR("signalyzer_h_ctrl_write returned: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } -#endif - } else if (signalyzer_h_adapter_type == 0x0000) { - LOG_INFO("Signalyzer: No external modules were detected."); - - nTRST = 0x10; - nTRSTnOE = 0x10; - nSRST = 0x20; - nSRSTnOE = 0x20; - - low_output = 0x08; - low_direction = 0x1b; - - high_output = 0x0; - high_direction = 0x0; - - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { - low_direction &= ~nTRSTnOE; /* nTRST input */ - low_output &= ~nTRST; /* nTRST = 0 */ - } else { - low_direction |= nTRSTnOE; /* nTRST output */ - low_output |= nTRST; /* nTRST = 1 */ - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) { - low_direction |= nSRSTnOE; /* nSRST output */ - low_output |= nSRST; /* nSRST = 1 */ - } else { - low_direction &= ~nSRSTnOE; /* nSRST input */ - low_output &= ~nSRST; /* nSRST = 0 */ - } - } else { - LOG_ERROR("Unknown module type is detected: %.4x", - signalyzer_h_adapter_type); - return ERROR_JTAG_DEVICE_ERROR; - } - - /* initialize low byte of controller for jtag operation */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize Signalyzer-H layout"); - return ERROR_JTAG_INIT_FAILED; - } - -#if BUILD_FT2232_FTD2XX == 1 - if (ftdi_device == FT_DEVICE_2232H) { - /* initialize high byte of controller for jtag operation */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize Signalyzer-H layout"); - return ERROR_JTAG_INIT_FAILED; - } - } -#elif BUILD_FT2232_LIBFTDI == 1 - if (ftdi_device == TYPE_2232H) { - /* initialize high byte of controller for jtag operation */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize Signalyzer-H layout"); - return ERROR_JTAG_INIT_FAILED; - } - } -#endif - return ERROR_OK; -} - -static void signalyzer_h_reset(int trst, int srst) -{ - enum reset_types jtag_reset_config = jtag_get_reset_config(); - - /* ADAPTOR: EM_LT16_A */ - if (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_LT16_A) { - if (trst == 1) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - /* switch to output pin (output is low) */ - low_direction |= nTRSTnOE; - else - /* switch output low */ - low_output &= ~nTRST; - } else if (trst == 0) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - /* switch to input pin (high-Z + internal - * and external pullup) */ - low_direction &= ~nTRSTnOE; - else - /* switch output high */ - low_output |= nTRST; - } - - if (srst == 1) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - /* switch output low */ - low_output &= ~nSRST; - else - /* switch to output pin (output is low) */ - low_direction |= nSRSTnOE; - } else if (srst == 0) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - /* switch output high */ - low_output |= nSRST; - else - /* switch to input pin (high-Z) */ - low_direction &= ~nSRSTnOE; - } - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); - LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, " - "low_direction: 0x%2.2x", - trst, srst, low_output, low_direction); - } - /* ADAPTOR: EM_ARM_JTAG, EM_ARM_JTAG_P, EM_JTAG, EM_JTAG_P */ - else if ((signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG) || - (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_ARM_JTAG_P) || - (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG) || - (signalyzer_h_adapter_type == SIGNALYZER_MODULE_TYPE_EM_JTAG_P)) { - if (trst == 1) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output &= ~nTRSTnOE; - else - high_output &= ~nTRST; - } else if (trst == 0) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output |= nTRSTnOE; - else - high_output |= nTRST; - } - - if (srst == 1) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - high_output &= ~nSRST; - else - high_output &= ~nSRSTnOE; - } else if (srst == 0) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - high_output |= nSRST; - else - high_output |= nSRSTnOE; - } - - /* command "set data bits high byte" */ - buffer_write(0x82); - buffer_write(high_output); - buffer_write(high_direction); - LOG_INFO("trst: %i, srst: %i, high_output: 0x%2.2x, " - "high_direction: 0x%2.2x", - trst, srst, high_output, high_direction); - } else if (signalyzer_h_adapter_type == 0x0000) { - if (trst == 1) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - /* switch to output pin (output is low) */ - low_direction |= nTRSTnOE; - else - /* switch output low */ - low_output &= ~nTRST; - } else if (trst == 0) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - /* switch to input pin (high-Z + internal - * and external pullup) */ - low_direction &= ~nTRSTnOE; - else - /* switch output high */ - low_output |= nTRST; - } - - if (srst == 1) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - /* switch output low */ - low_output &= ~nSRST; - else - /* switch to output pin (output is low) */ - low_direction |= nSRSTnOE; - } else if (srst == 0) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - /* switch output high */ - low_output |= nSRST; - else - /* switch to input pin (high-Z) */ - low_direction &= ~nSRSTnOE; - } - - /* command "set data bits low byte" */ - buffer_write(0x80); - buffer_write(low_output); - buffer_write(low_direction); - LOG_DEBUG("trst: %i, srst: %i, low_output: 0x%2.2x, " - "low_direction: 0x%2.2x", - trst, srst, low_output, low_direction); - } -} - -static void signalyzer_h_blink(void) -{ - signalyzer_h_led_set(signalyzer_h_side, SIGNALYZER_LED_RED, 100, 0, 1); -} - -/******************************************************************** - * Support for KT-LINK - * JTAG adapter from KRISTECH - * http://www.kristech.eu - *******************************************************************/ -static int ktlink_init(void) -{ - uint8_t swd_en = 0x20; /* 0x20 SWD disable, 0x00 SWD enable (ADBUS5) */ - - low_output = 0x08 | swd_en; /* value; TMS=1,TCK=0,TDI=0,SWD=swd_en */ - low_direction = 0x3B; /* out=1; TCK/TDI/TMS=out,TDO=in,SWD=out,RTCK=in,SRSTIN=in */ - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - nTRST = 0x01; - nSRST = 0x02; - nTRSTnOE = 0x04; - nSRSTnOE = 0x08; - - high_output = 0x80; /* turn LED on */ - high_direction = 0xFF; /* all outputs */ - - enum reset_types jtag_reset_config = jtag_get_reset_config(); - - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) { - high_output |= nTRSTnOE; - high_output &= ~nTRST; - } else { - high_output &= ~nTRSTnOE; - high_output |= nTRST; - } - - if (jtag_reset_config & RESET_SRST_PUSH_PULL) { - high_output &= ~nSRSTnOE; - high_output |= nSRST; - } else { - high_output |= nSRSTnOE; - high_output &= ~nSRST; - } - - /* initialize high byte for jtag */ - if (ft2232_set_data_bits_high_byte(high_output, high_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'ktlink' layout"); - return ERROR_JTAG_INIT_FAILED; - } - - return ERROR_OK; -} - -static void ktlink_reset(int trst, int srst) -{ - enum reset_types jtag_reset_config = jtag_get_reset_config(); - - if (trst == 1) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output &= ~nTRSTnOE; - else - high_output &= ~nTRST; - } else if (trst == 0) { - if (jtag_reset_config & RESET_TRST_OPEN_DRAIN) - high_output |= nTRSTnOE; - else - high_output |= nTRST; - } - - if (srst == 1) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - high_output &= ~nSRST; - else - high_output &= ~nSRSTnOE; - } else if (srst == 0) { - if (jtag_reset_config & RESET_SRST_PUSH_PULL) - high_output |= nSRST; - else - high_output |= nSRSTnOE; - } - - buffer_write(0x82); /* command "set data bits high byte" */ - buffer_write(high_output); - buffer_write(high_direction); - LOG_DEBUG("trst: %i, srst: %i, high_output: 0x%2.2x, high_direction: 0x%2.2x", - trst, - srst, - high_output, - high_direction); -} - -static void ktlink_blink(void) -{ - /* LED connected to ACBUS7 */ - high_output ^= 0x80; - - buffer_write(0x82); /* command "set data bits high byte" */ - buffer_write(high_output); - buffer_write(high_direction); -} - -/******************************************************************** - * Support for Digilent HS-1 - * JTAG adapter from Digilent - * http://www.digilent.com - * Author: Stephane Bonnet bonnetst@hds.utc.fr - *******************************************************************/ - -static int digilent_hs1_init(void) -{ - /* the adapter only supports the base JTAG signals, no nTRST - nor nSRST */ - low_output = 0x88; - low_direction = 0x8b; - - /* initialize low byte for jtag */ - if (ft2232_set_data_bits_low_byte(low_output, low_direction) != ERROR_OK) { - LOG_ERROR("couldn't initialize FT2232 with 'digilent_hs1' layout"); - return ERROR_JTAG_INIT_FAILED; - } - return ERROR_OK; -} - -static void digilent_hs1_reset(int trst, int srst) -{ - /* Dummy function, no reset signals supported. */ -} - -static const struct command_registration ft2232_command_handlers[] = { - { - .name = "ft2232_device_desc", - .handler = &ft2232_handle_device_desc_command, - .mode = COMMAND_CONFIG, - .help = "set the USB device description of the FTDI FT2232 device", - .usage = "description_string", - }, - { - .name = "ft2232_serial", - .handler = &ft2232_handle_serial_command, - .mode = COMMAND_CONFIG, - .help = "set the serial number of the FTDI FT2232 device", - .usage = "serial_string", - }, - { - .name = "ft2232_layout", - .handler = &ft2232_handle_layout_command, - .mode = COMMAND_CONFIG, - .help = "set the layout of the FT2232 GPIO signals used " - "to control output-enables and reset signals", - .usage = "layout_name", - }, - { - .name = "ft2232_vid_pid", - .handler = &ft2232_handle_vid_pid_command, - .mode = COMMAND_CONFIG, - .help = "the vendor ID and product ID of the FTDI FT2232 device", - .usage = "(vid pid)* ", - }, - { - .name = "ft2232_latency", - .handler = &ft2232_handle_latency_command, - .mode = COMMAND_CONFIG, - .help = "set the FT2232 latency timer to a new value", - .usage = "value", - }, - { - .name = "ft2232_channel", - .handler = &ft2232_handle_channel_command, - .mode = COMMAND_CONFIG, - .help = "set the FT2232 channel to a new value", - .usage = "value", - }, - COMMAND_REGISTRATION_DONE -}; - -struct jtag_interface ft2232_interface = { - .name = "ft2232", - .supported = DEBUG_CAP_TMS_SEQ, - .commands = ft2232_command_handlers, - .transports = jtag_only, - - .init = ft2232_init, - .quit = ft2232_quit, - .speed = ft2232_speed, - .speed_div = ft2232_speed_div, - .khz = ft2232_khz, - .execute_queue = ft2232_execute_queue, -}; diff --git a/src/jtag/drivers/ftd2xx_common.h b/src/jtag/drivers/ftd2xx_common.h index 14b8455..eaf14ae 100644 --- a/src/jtag/drivers/ftd2xx_common.h +++ b/src/jtag/drivers/ftd2xx_common.h @@ -20,7 +20,7 @@ #ifndef OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H #define OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H -#if ((BUILD_FT2232_FTD2XX == 1) || (BUILD_PRESTO_FTD2XX == 1) || (BUILD_USB_BLASTER_FTD2XX == 1)) +#if ((BUILD_PRESTO_FTD2XX == 1) || (BUILD_USB_BLASTER_FTD2XX == 1)) #include static const char *ftd2xx_status_string(FT_STATUS status) diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index 64fdd71..1ee29d2 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -51,12 +51,6 @@ extern struct jtag_interface parport_interface; #if BUILD_DUMMY == 1 extern struct jtag_interface dummy_interface; #endif -#if BUILD_FT2232_FTD2XX == 1 -extern struct jtag_interface ft2232_interface; -#endif -#if BUILD_FT2232_LIBFTDI == 1 -extern struct jtag_interface ft2232_interface; -#endif #if BUILD_FTDI == 1 extern struct jtag_interface ftdi_interface; #endif @@ -150,12 +144,6 @@ struct jtag_interface *jtag_interfaces[] = { #if BUILD_DUMMY == 1 &dummy_interface, #endif -#if BUILD_FT2232_FTD2XX == 1 - &ft2232_interface, -#endif -#if BUILD_FT2232_LIBFTDI == 1 - &ft2232_interface, -#endif #if BUILD_FTDI == 1 &ftdi_interface, #endif diff --git a/tcl/interface/axm0432.cfg b/tcl/interface/axm0432.cfg deleted file mode 100644 index d2a2aaa..0000000 --- a/tcl/interface/axm0432.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Axiom axm0432 -# -# http://www.axman.com -# - -interface ft2232 -ft2232_device_desc "Symphony SoundBite" -ft2232_layout "axm0432_jtag" -ft2232_vid_pid 0x0403 0x6010 - diff --git a/tcl/interface/busblaster.cfg b/tcl/interface/busblaster.cfg deleted file mode 100644 index f87a482..0000000 --- a/tcl/interface/busblaster.cfg +++ /dev/null @@ -1,14 +0,0 @@ -# -# Dangerous Prototypes - Bus Blaster -# -# The Bus Blaster has a configurable buffer between the FTDI FT2232H and the -# JTAG header which allows it to emulate various debugger types. It comes -# configured as a JTAGkey device. -# -# http://dangerousprototypes.com/docs/Bus_Blaster -# - -interface ft2232 -ft2232_device_desc "Dual RS232-HS" -ft2232_layout jtagkey -ft2232_vid_pid 0x0403 0x6010 diff --git a/tcl/interface/calao-usb-a9260-c01.cfg b/tcl/interface/calao-usb-a9260-c01.cfg deleted file mode 100644 index c660671..0000000 --- a/tcl/interface/calao-usb-a9260-c01.cfg +++ /dev/null @@ -1,13 +0,0 @@ -# -# CALAO Systems USB-A9260-C01 -# -# http://www.calao-systems.com/ -# - -interface ft2232 -ft2232_layout jtagkey -ft2232_device_desc "USB-A9260" -ft2232_vid_pid 0x0403 0x6010 -script interface/calao-usb-a9260.cfg -script target/at91sam9260minimal.cfg - diff --git a/tcl/interface/calao-usb-a9260-c02.cfg b/tcl/interface/calao-usb-a9260-c02.cfg deleted file mode 100644 index 2461b70..0000000 --- a/tcl/interface/calao-usb-a9260-c02.cfg +++ /dev/null @@ -1,13 +0,0 @@ -# -# CALAO Systems USB-A9260-C02 -# -# http://www.calao-systems.com/ -# - -interface ft2232 -ft2232_layout jtagkey -ft2232_device_desc "USB-A9260" -ft2232_vid_pid 0x0403 0x6001 -script interface/calao-usb-a9260.cfg -script target/at91sam9260minimal.cfg - diff --git a/tcl/interface/cortino.cfg b/tcl/interface/cortino.cfg deleted file mode 100644 index e2b2301..0000000 --- a/tcl/interface/cortino.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Hitex Cortino -# -# http://www.hitex.com/index.php?id=cortino -# - -interface ft2232 -ft2232_device_desc "Cortino" -ft2232_layout cortino -ft2232_vid_pid 0x0640 0x0032 - diff --git a/tcl/interface/digilent-hs1.cfg b/tcl/interface/digilent-hs1.cfg deleted file mode 100644 index e35f0cf..0000000 --- a/tcl/interface/digilent-hs1.cfg +++ /dev/null @@ -1,15 +0,0 @@ -# -# Digilent HS1 -# -# The Digilent HS1 is a high-speed FT2232H-based adapter, compliant with the -# Xilinx JTAG 14-pin pinout. -# It does not support ARM reset signals (SRST and TRST) but can still be used for -# hardware debugging, with some limitations. -# -# http://www.digilentinc.com/Products/Detail.cfm?NavPath=2,395,922&Prod=JTAG-HS1 -# - -interface ft2232 -ft2232_device_desc "Digilent Adept USB Device" -ft2232_layout digilent-hs1 -ft2232_vid_pid 0x0403 0x6010 diff --git a/tcl/interface/dlp-usb1232h.cfg b/tcl/interface/dlp-usb1232h.cfg deleted file mode 100644 index 7432413..0000000 --- a/tcl/interface/dlp-usb1232h.cfg +++ /dev/null @@ -1,14 +0,0 @@ -# -# DLP Design DLP-USB1232H USB-to-UART/FIFO interface module -# -# http://www.dlpdesign.com/usb/usb1232h.shtml -# -# Schematics for OpenOCD usage: -# http://randomprojects.org/wiki/DLP-USB1232H_and_OpenOCD_based_JTAG_adapter -# - -interface ft2232 -ft2232_device_desc "Dual RS232-HS" -ft2232_layout usbjtag -ft2232_vid_pid 0x0403 0x6010 - diff --git a/tcl/interface/flossjtag-noeeprom.cfg b/tcl/interface/flossjtag-noeeprom.cfg deleted file mode 100644 index 66c010b..0000000 --- a/tcl/interface/flossjtag-noeeprom.cfg +++ /dev/null @@ -1,19 +0,0 @@ -# -# FlossJTAG -# -# http://github.com/esden/floss-jtag -# -# This is the pre v0.3 Floss-JTAG compatible config file. It can also be used -# for newer versions of Floss-JTAG with empty or not populated EEPROM. If you -# have several Floss-JTAG connected you have to use the USB ID to select a -# specific one. -# -# If you have a Floss-JTAG WITH EEPROM that is programmed, use the -# flossjtag.cfg file. -# - -interface ft2232 -ft2232_vid_pid 0x0403 0x6010 -ft2232_device_desc "Dual RS232-HS" -ft2232_layout "usbjtag" -ft2232_latency 2 diff --git a/tcl/interface/flossjtag.cfg b/tcl/interface/flossjtag.cfg deleted file mode 100644 index fbbabc1..0000000 --- a/tcl/interface/flossjtag.cfg +++ /dev/null @@ -1,20 +0,0 @@ -# -# FlossJTAG -# -# http://github.com/esden/floss-jtag -# -# This is the v0.3 and v1.0 Floss-JTAG compatible config file. It relies on the -# existence of an EEPROM on Floss-JTAG containing a name. If you have several -# Floss-JTAG adapters connected you can use the serial number to select a -# specific device. -# -# If your Floss-JTAG does not have an EEPROM, or the EEPROM is empty, use the -# flossjtag-noeeprom.cfg file. -# - -interface ft2232 -ft2232_vid_pid 0x0403 0x6010 -ft2232_device_desc "FLOSS-JTAG" -#ft2232_serial "FJ000001" -ft2232_layout "flossjtag" -ft2232_latency 2 diff --git a/tcl/interface/flyswatter.cfg b/tcl/interface/flyswatter.cfg deleted file mode 100644 index 5bac05b..0000000 --- a/tcl/interface/flyswatter.cfg +++ /dev/null @@ -1,10 +0,0 @@ -# -# TinCanTools Flyswatter -# -# http://www.tincantools.com/product.php?productid=16134 -# - -interface ft2232 -ft2232_device_desc "Flyswatter" -ft2232_layout "flyswatter" -ft2232_vid_pid 0x0403 0x6010 diff --git a/tcl/interface/flyswatter2.cfg b/tcl/interface/flyswatter2.cfg deleted file mode 100644 index 21e7fed..0000000 --- a/tcl/interface/flyswatter2.cfg +++ /dev/null @@ -1,10 +0,0 @@ -# -# TinCanTools Flyswatter 2 -# -# http://www.tincantools.com/product.php?productid=16153 -# - -interface ft2232 -ft2232_device_desc "Flyswatter2" -ft2232_layout "flyswatter2" -ft2232_vid_pid 0x0403 0x6010 diff --git a/tcl/interface/hilscher_nxhx10_etm.cfg b/tcl/interface/hilscher_nxhx10_etm.cfg deleted file mode 100644 index b16ed1a..0000000 --- a/tcl/interface/hilscher_nxhx10_etm.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Hilscher NXHX 10-ETM -# -# http://de.hilscher.com/products_details_hardware.html?p_id=P_4ce145a5983e6 -# - -interface ft2232 -ft2232_device_desc "NXHX 10-ETM" -ft2232_layout comstick -ft2232_vid_pid 0x0640 0x0028 -adapter_khz 6000 diff --git a/tcl/interface/hilscher_nxhx500_etm.cfg b/tcl/interface/hilscher_nxhx500_etm.cfg deleted file mode 100644 index 840ffaf..0000000 --- a/tcl/interface/hilscher_nxhx500_etm.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Hilscher NXHX 500-ETM -# -# http://de.hilscher.com/files_design/8/NXHX500-ETM_description_Rev01_EN.pdf -# - -interface ft2232 -ft2232_device_desc "NXHX 500-ETM" -ft2232_layout comstick -ft2232_vid_pid 0x0640 0x0028 -adapter_khz 6000 diff --git a/tcl/interface/hilscher_nxhx500_re.cfg b/tcl/interface/hilscher_nxhx500_re.cfg deleted file mode 100644 index 1d1b754..0000000 --- a/tcl/interface/hilscher_nxhx500_re.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Hilscher NXHX 500-RE -# -# http://de.hilscher.com/products_details_hardware.html?p_id=P_461ff2053bad1&bs=20 -# - -interface ft2232 -ft2232_device_desc "NXHX 500-RE" -ft2232_layout comstick -ft2232_vid_pid 0x0640 0x0028 -adapter_khz 6000 diff --git a/tcl/interface/hilscher_nxhx50_etm.cfg b/tcl/interface/hilscher_nxhx50_etm.cfg deleted file mode 100644 index ff98c28..0000000 --- a/tcl/interface/hilscher_nxhx50_etm.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Hilscher NXHX 50-ETM -# -# http://de.hilscher.com/files_design/8/NXHX50-ETM_description_Rev01_EN.pdf -# - -interface ft2232 -ft2232_device_desc "NXHX 50-ETM" -ft2232_layout comstick -ft2232_vid_pid 0x0640 0x0028 -adapter_khz 6000 diff --git a/tcl/interface/hilscher_nxhx50_re.cfg b/tcl/interface/hilscher_nxhx50_re.cfg deleted file mode 100644 index 0573e03..0000000 --- a/tcl/interface/hilscher_nxhx50_re.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Hilscher NXHX 50-RE -# -# http://de.hilscher.com/products_details_hardware.html?p_id=P_483c0f582ad36&bs=20 -# - -interface ft2232 -ft2232_device_desc "NXHX50-RE" -ft2232_layout comstick -ft2232_vid_pid 0x0640 0x0028 -adapter_khz 6000 diff --git a/tcl/interface/hitex_str9-comstick.cfg b/tcl/interface/hitex_str9-comstick.cfg deleted file mode 100644 index a38be78..0000000 --- a/tcl/interface/hitex_str9-comstick.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Hitex STR9-comStick -# -# http://www.hitex.com/index.php?id=383 -# - -interface ft2232 -ft2232_device_desc "STR9-comStick" -ft2232_layout comstick -ft2232_vid_pid 0x0640 0x002c - diff --git a/tcl/interface/icebear.cfg b/tcl/interface/icebear.cfg deleted file mode 100644 index 88b5e36..0000000 --- a/tcl/interface/icebear.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Section5 ICEBear -# -# http://section5.ch/icebear -# - -interface ft2232 -ft2232_device_desc "ICEbear JTAG adapter" -ft2232_layout icebear -ft2232_vid_pid 0x0403 0xc140 - diff --git a/tcl/interface/jtag-lock-pick_tiny_2.cfg b/tcl/interface/jtag-lock-pick_tiny_2.cfg deleted file mode 100644 index 539f0f9..0000000 --- a/tcl/interface/jtag-lock-pick_tiny_2.cfg +++ /dev/null @@ -1,10 +0,0 @@ -# -# DISTORTEC JTAG-lock-pick Tiny 2 -# -# http://www.distortec.com -# - -interface ft2232 -ft2232_device_desc "JTAG-lock-pick Tiny 2" -ft2232_layout ktlink -ft2232_vid_pid 0x0403 0x8220 diff --git a/tcl/interface/jtagkey-tiny.cfg b/tcl/interface/jtagkey-tiny.cfg deleted file mode 100644 index 633fdda..0000000 --- a/tcl/interface/jtagkey-tiny.cfg +++ /dev/null @@ -1,9 +0,0 @@ -# -# Amontec JTAGkey-tiny -# -# http://www.amontec.com/jtagkey-tiny.shtml -# - -# The JTAGkey-tiny uses exactly the same config as the JTAGkey. -source [find interface/jtagkey.cfg] - diff --git a/tcl/interface/jtagkey.cfg b/tcl/interface/jtagkey.cfg deleted file mode 100644 index ca45dfc..0000000 --- a/tcl/interface/jtagkey.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Amontec JTAGkey -# -# http://www.amontec.com/jtagkey.shtml -# - -interface ft2232 -ft2232_device_desc "Amontec JTAGkey" -ft2232_layout jtagkey -ft2232_vid_pid 0x0403 0xcff8 - diff --git a/tcl/interface/jtagkey2.cfg b/tcl/interface/jtagkey2.cfg deleted file mode 100644 index 40a0b0d..0000000 --- a/tcl/interface/jtagkey2.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Amontec JTAGkey2 -# -# http://www.amontec.com/jtagkey2.shtml -# - -interface ft2232 -ft2232_device_desc "Amontec JTAGkey-2" -ft2232_layout jtagkey -ft2232_vid_pid 0x0403 0xCFF8 - diff --git a/tcl/interface/jtagkey2p.cfg b/tcl/interface/jtagkey2p.cfg deleted file mode 100644 index 98a9417..0000000 --- a/tcl/interface/jtagkey2p.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Amontec JTAGkey2P -# -# http://www.amontec.com/jtagkey2p.shtml -# - -interface ft2232 -ft2232_device_desc "Amontec JTAGkey-2P" -ft2232_layout jtagkey -ft2232_vid_pid 0x0403 0xCFF8 - diff --git a/tcl/interface/kt-link.cfg b/tcl/interface/kt-link.cfg deleted file mode 100644 index 93af8e4..0000000 --- a/tcl/interface/kt-link.cfg +++ /dev/null @@ -1,10 +0,0 @@ -# -# Kristech KT-Link -# -# http://www.kristech.eu -# - -interface ft2232 -ft2232_device_desc "KT-LINK" -ft2232_layout ktlink -ft2232_vid_pid 0x0403 0xBBE2 diff --git a/tcl/interface/lisa-l.cfg b/tcl/interface/lisa-l.cfg deleted file mode 100644 index cc7d6cc..0000000 --- a/tcl/interface/lisa-l.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Lisa/L -# -# http://paparazzi.enac.fr/wiki/Lisa -# - -interface ft2232 -ft2232_vid_pid 0x0403 0x6010 -ft2232_device_desc "Lisa/L" -ft2232_layout "lisa-l" -ft2232_latency 2 diff --git a/tcl/interface/luminary-icdi.cfg b/tcl/interface/luminary-icdi.cfg deleted file mode 100644 index 94e00ae..0000000 --- a/tcl/interface/luminary-icdi.cfg +++ /dev/null @@ -1,21 +0,0 @@ -# -# Luminary Micro Stellaris LM3S9B9x Evaluation Kits -# In-Circuit Debug Interface (ICDI) Board -# -# Essentially all Luminary debug hardware is the same, (with both -# JTAG and SWD support compatible with ICDI boards. This ICDI adapter -# configuration is JTAG-only, but the same hardware handles SWD too. -# -# This is a discrete FT2232 based debug board which supports ARM's -# JTAG/SWD connectors in both backwards-compatible 20-pin format and -# in the new-style compact 10-pin. There's also an 8-pin connector -# with serial port support. It's included with LM3S9B9x eval boards. -# -# http://www.luminarymicro.com/products/ek-lm3s9b90.html -# http://www.luminarymicro.com/products/ek-lm3s9b92.html -# - -interface ft2232 -ft2232_device_desc "Luminary Micro ICDI Board" -ft2232_layout luminary_icdi -ft2232_vid_pid 0x0403 0xbcda diff --git a/tcl/interface/luminary-lm3s811.cfg b/tcl/interface/luminary-lm3s811.cfg deleted file mode 100644 index fd747c0..0000000 --- a/tcl/interface/luminary-lm3s811.cfg +++ /dev/null @@ -1,18 +0,0 @@ -# -# Luminary Micro Stellaris LM3S811 Evaluation Kit -# -# http://www.luminarymicro.com/products/stellaris_811_evaluation_kits.html -# -# NOTE: this is only for boards *before* Rev C, which adds support -# for SWO tracing with ADBUS_6 DBG_ENn and BDBUS_4 SWO_EN signals. -# The "evb_lm3s811" layout doesn't set up those signals. -# -# Rev C boards work more like the other Stellaris eval boards. They -# need to use the "luminary_icdi" layout to work correctly. -# - -interface ft2232 -ft2232_device_desc "LM3S811 Evaluation Board" -ft2232_layout evb_lm3s811 -ft2232_vid_pid 0x0403 0xbcd9 - diff --git a/tcl/interface/luminary.cfg b/tcl/interface/luminary.cfg deleted file mode 100644 index e94e514..0000000 --- a/tcl/interface/luminary.cfg +++ /dev/null @@ -1,31 +0,0 @@ -# -# Luminary Micro Stellaris Evaluation Kits -# -# http://www.luminarymicro.com/products/evaluation_kits.html -# -# There are a number of evaluation kits for Stellaris Cortex-M3 chips. -# Currently they all bundle FT2232 based debug support. When that is -# used (instead of an external adapter), use this config file in one -# of these two modes: -# -# - Eval board debug ... debug of the Stellaris chip via port A. -# -# - Other board debug ... same thing, but the board acts as a debug -# adapter for another board (using a standard ARM JTAG connector). -# The Stellaris chip stays in reset. -# -# Those support both JTAG and SWD. SWD is an ARM-only two-wire debug -# protocol; in 2009, OpenOCD does not support SWD. -# -# Port B of the FT2232 chip is normally used as a serial link to the -# Stellaris chip. On most boards (but not older LM3S811 eval boards), -# when SWD is used Port B may instead be used to read low-bandwidth -# "SWO trace" data, including so-called "printf style" output from -# firmware via the ITM module as well as profile data. -# - -interface ft2232 -ft2232_device_desc "Stellaris Evaluation Board" -ft2232_layout luminary_icdi -ft2232_vid_pid 0x0403 0xbcd9 - diff --git a/tcl/interface/minimodule.cfg b/tcl/interface/minimodule.cfg deleted file mode 100644 index c8f9ba1..0000000 --- a/tcl/interface/minimodule.cfg +++ /dev/null @@ -1,10 +0,0 @@ -# -# FTDI MiniModule -# -# http://www.ftdichip.com/Support/Documents/DataSheets/Modules/DS_FT2232H_Mini_Module.pdf -# - -interface ft2232 -ft2232_device_desc "FT2232H MiniModule" -ft2232_layout "minimodule" -ft2232_vid_pid 0x0403 0x6010 diff --git a/tcl/interface/neodb.cfg b/tcl/interface/neodb.cfg deleted file mode 100644 index 8e2f526..0000000 --- a/tcl/interface/neodb.cfg +++ /dev/null @@ -1,10 +0,0 @@ -# -# Openmoko USB JTAG/RS232 adapter -# -# http://wiki.openmoko.org/wiki/Debug_Board_v3 -# - -interface ft2232 -ft2232_device_desc "Debug Board for Neo1973" -ft2232_layout jtagkey -ft2232_vid_pid 0x1457 0x5118 diff --git a/tcl/interface/ngxtech.cfg b/tcl/interface/ngxtech.cfg deleted file mode 100644 index 9dfe01c..0000000 --- a/tcl/interface/ngxtech.cfg +++ /dev/null @@ -1,10 +0,0 @@ -# -# NGX ARM USB JTAG -# -# http://shop.ngxtechnologies.com/product_info.php?cPath=26&products_id=30 -# - -interface ft2232 -ft2232_device_desc "NGX JTAG A" -ft2232_vid_pid 0x0403 0x6010 -ft2232_layout "oocdlink" diff --git a/tcl/interface/olimex-arm-usb-ocd-h.cfg b/tcl/interface/olimex-arm-usb-ocd-h.cfg deleted file mode 100644 index 47daa92..0000000 --- a/tcl/interface/olimex-arm-usb-ocd-h.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Olimex ARM-USB-OCD-H -# -# http://www.olimex.com/dev/arm-usb-ocd.html -# - -interface ft2232 -ft2232_device_desc "Olimex OpenOCD JTAG ARM-USB-OCD-H" -ft2232_layout olimex-jtag -ft2232_vid_pid 0x15ba 0x002b - diff --git a/tcl/interface/olimex-arm-usb-ocd.cfg b/tcl/interface/olimex-arm-usb-ocd.cfg deleted file mode 100644 index 569dcef..0000000 --- a/tcl/interface/olimex-arm-usb-ocd.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Olimex ARM-USB-OCD -# -# http://www.olimex.com/dev/arm-usb-ocd.html -# - -interface ft2232 -ft2232_device_desc "Olimex OpenOCD JTAG" -ft2232_layout olimex-jtag -ft2232_vid_pid 0x15ba 0x0003 - diff --git a/tcl/interface/olimex-arm-usb-tiny-h.cfg b/tcl/interface/olimex-arm-usb-tiny-h.cfg deleted file mode 100644 index b6aa952..0000000 --- a/tcl/interface/olimex-arm-usb-tiny-h.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Olimex ARM-USB-TINY-H -# -# http://www.olimex.com/dev/arm-usb-tiny-h.html -# - -interface ft2232 -ft2232_device_desc "Olimex OpenOCD JTAG ARM-USB-TINY-H" -ft2232_layout olimex-jtag -ft2232_vid_pid 0x15ba 0x002a - diff --git a/tcl/interface/olimex-jtag-tiny.cfg b/tcl/interface/olimex-jtag-tiny.cfg deleted file mode 100644 index f28ed9d..0000000 --- a/tcl/interface/olimex-jtag-tiny.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Olimex ARM-USB-TINY -# -# http://www.olimex.com/dev/arm-usb-tiny.html -# - -interface ft2232 -ft2232_device_desc "Olimex OpenOCD JTAG TINY" -ft2232_layout olimex-jtag -ft2232_vid_pid 0x15ba 0x0004 - diff --git a/tcl/interface/oocdlink.cfg b/tcl/interface/oocdlink.cfg deleted file mode 100644 index 4e962f5..0000000 --- a/tcl/interface/oocdlink.cfg +++ /dev/null @@ -1,12 +0,0 @@ -# -# Joern Kaipf's OOCDLink -# -# http://www.joernonline.de/contrexx2/cms/index.php?page=126 -# - -interface ft2232 -ft2232_device_desc "OOCDLink" -ft2232_layout oocdlink -ft2232_vid_pid 0x0403 0xbaf8 -adapter_khz 5 - diff --git a/tcl/interface/opendous_ftdi.cfg b/tcl/interface/opendous_ftdi.cfg deleted file mode 100644 index e0e05c4..0000000 --- a/tcl/interface/opendous_ftdi.cfg +++ /dev/null @@ -1,15 +0,0 @@ -# -# Opendous -# -# http://code.google.com/p/opendous/wiki/JTAG -# -# According to the website, it is similar to jtagkey, but it uses channel B -# (and it has a different pid number). -# - -interface ft2232 -ft2232_device_desc "Dual RS232-HS" -ft2232_layout jtagkey -ft2232_vid_pid 0x0403 0x6010 -ft2232_channel 2 - diff --git a/tcl/interface/openocd-usb-hs.cfg b/tcl/interface/openocd-usb-hs.cfg deleted file mode 100644 index ddf3dce..0000000 --- a/tcl/interface/openocd-usb-hs.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# embedded projects openocd usb adapter v3 -# -# http://shop.embedded-projects.net/index.php?module=artikel&action=artikel&id=14 -# - -interface ft2232 -ft2232_vid_pid 0x0403 0x6010 -ft2232_device_desc "Dual RS232-HS" -ft2232_layout "oocdlink" -ft2232_latency 2 diff --git a/tcl/interface/openocd-usb.cfg b/tcl/interface/openocd-usb.cfg deleted file mode 100644 index 4000b23..0000000 --- a/tcl/interface/openocd-usb.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Hubert Hoegl's USB to JTAG -# -# http://www.hs-augsburg.de/~hhoegl/proj/usbjtag/usbjtag.html -# - -interface ft2232 -ft2232_vid_pid 0x0403 0x6010 -ft2232_device_desc "Dual RS232" -ft2232_layout "oocdlink" -ft2232_latency 2 diff --git a/tcl/interface/openrd.cfg b/tcl/interface/openrd.cfg deleted file mode 100644 index 322b508..0000000 --- a/tcl/interface/openrd.cfg +++ /dev/null @@ -1,12 +0,0 @@ -# -# Marvell OpenRD -# -# http://www.marvell.com/products/embedded_processors/developer/kirkwood/openrd.jsp -# - -interface ft2232 -ft2232_layout sheevaplug -ft2232_vid_pid 0x0403 0x9e90 -ft2232_device_desc "OpenRD JTAGKey FT2232D B" -adapter_khz 3000 - diff --git a/tcl/interface/redbee-econotag.cfg b/tcl/interface/redbee-econotag.cfg deleted file mode 100644 index 7e17a05..0000000 --- a/tcl/interface/redbee-econotag.cfg +++ /dev/null @@ -1,13 +0,0 @@ -# -# Redwire Redbee-Econotag -# -# http://www.redwirellc.com/store/node/1 -# -# The Redbee-Econotag has an onboard FT2232H with: -# - FT2232H channel A wired to mc13224v JTAG -# - FT2232H channel B wired to mc13224v UART1 -# - -interface ft2232 -ft2232_layout redbee-econotag -ft2232_vid_pid 0x0403 0x6010 diff --git a/tcl/interface/redbee-usb.cfg b/tcl/interface/redbee-usb.cfg deleted file mode 100644 index 5e7e4f7..0000000 --- a/tcl/interface/redbee-usb.cfg +++ /dev/null @@ -1,13 +0,0 @@ -# -# Redwire Redbee-USB -# -# http://www.redwirellc.com -# -# The Redbee-USB has an onboard FT2232H with: -# - FT2232H channel B wired to mc13224v JTAG -# - FT2232H channel A wired to mc13224v UART1 -# - -interface ft2232 -ft2232_layout redbee-usb -ft2232_vid_pid 0x0403 0x6010 diff --git a/tcl/interface/sheevaplug.cfg b/tcl/interface/sheevaplug.cfg deleted file mode 100644 index d46d71e..0000000 --- a/tcl/interface/sheevaplug.cfg +++ /dev/null @@ -1,12 +0,0 @@ -# -# Marvel SheevaPlug Development Kit -# -# http://www.marvell.com/products/embedded_processors/developer/kirkwood/sheevaplug.jsp -# - -interface ft2232 -ft2232_layout sheevaplug -ft2232_vid_pid 0x9e88 0x9e8f -ft2232_device_desc "SheevaPlug JTAGKey FT2232D B" -adapter_khz 2000 - diff --git a/tcl/interface/signalyzer-h2.cfg b/tcl/interface/signalyzer-h2.cfg deleted file mode 100644 index 24288ac..0000000 --- a/tcl/interface/signalyzer-h2.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Xverve Signalyzer H2 (DT-USB-SH2) -# -# http://www.signalyzer.com -# - -interface ft2232 -ft2232_device_desc "Signalyzer H2" -ft2232_layout signalyzer-h -ft2232_vid_pid 0x0403 0xbca2 - diff --git a/tcl/interface/signalyzer-h4.cfg b/tcl/interface/signalyzer-h4.cfg deleted file mode 100644 index d2b260b..0000000 --- a/tcl/interface/signalyzer-h4.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Xverve Signalyzer H4 (DT-USB-SH4) -# -# http://www.signalyzer.com -# - -interface ft2232 -ft2232_device_desc "Signalyzer H4" -ft2232_layout signalyzer-h -ft2232_vid_pid 0x0403 0xbca4 - diff --git a/tcl/interface/signalyzer-lite.cfg b/tcl/interface/signalyzer-lite.cfg deleted file mode 100644 index 834bc0c..0000000 --- a/tcl/interface/signalyzer-lite.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Xverve Signalyzer LITE (DT-USB-SLITE) -# -# http://www.signalyzer.com -# - -interface ft2232 -ft2232_device_desc "Signalyzer LITE" -ft2232_layout signalyzer -ft2232_vid_pid 0x0403 0xbca1 - diff --git a/tcl/interface/signalyzer.cfg b/tcl/interface/signalyzer.cfg deleted file mode 100644 index b0581c5..0000000 --- a/tcl/interface/signalyzer.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Xverve Signalyzer Tool (DT-USB-ST) -# -# http://www.signalyzer.com -# - -interface ft2232 -ft2232_device_desc "Signalyzer" -ft2232_layout signalyzer -ft2232_vid_pid 0x0403 0xbca0 - diff --git a/tcl/interface/stm32-stick.cfg b/tcl/interface/stm32-stick.cfg deleted file mode 100644 index 9dcf816..0000000 --- a/tcl/interface/stm32-stick.cfg +++ /dev/null @@ -1,11 +0,0 @@ -# -# Hitex STM32-PerformanceStick -# -# http://www.hitex.com/index.php?id=340 -# - -interface ft2232 -ft2232_device_desc "STM32-PerformanceStick" -ft2232_layout stm32stick -ft2232_vid_pid 0x0640 0x002d - diff --git a/tcl/interface/turtelizer2.cfg b/tcl/interface/turtelizer2.cfg deleted file mode 100644 index c5e10c0..0000000 --- a/tcl/interface/turtelizer2.cfg +++ /dev/null @@ -1,15 +0,0 @@ -# -# egnite Turtelizer 2 -# -# http://www.ethernut.de/en/hardware/turtelizer/index.html -# -# Deprecated, if possible use tcl/interface/ftdi/turtelizer... -# To run, one of following configure option needed -# --enable-legacy-ft2232_libftdi -# --enable-legacy-ft2232_ftd2xx - -interface ft2232 -ft2232_device_desc "Turtelizer JTAG/RS232 Adapter" -ft2232_layout turtelizer2 -ft2232_vid_pid 0x0403 0xbdc8 - diff --git a/tcl/interface/vpaclink.cfg b/tcl/interface/vpaclink.cfg deleted file mode 100644 index a4795d3..0000000 --- a/tcl/interface/vpaclink.cfg +++ /dev/null @@ -1,10 +0,0 @@ -# -# Voipac VPACLink -# -# http://voipac.com/27M-JTG-000 -# - -interface ft2232 -ft2232_device_desc "VPACLink A" -ft2232_layout oocdlink -ft2232_vid_pid 0x0403 0x6010 diff --git a/tcl/interface/xds100v2.cfg b/tcl/interface/xds100v2.cfg deleted file mode 100644 index f14f1d8..0000000 --- a/tcl/interface/xds100v2.cfg +++ /dev/null @@ -1,10 +0,0 @@ -# -# Texas Instruments XDS100v2 -# -# http://processors.wiki.ti.com/index.php/XDS100#XDS100v2_Features -# - -interface ft2232 -ft2232_device_desc "Texas Instruments Inc.XDS100 Ver 2.0" -ft2232_layout xds100v2 -ft2232_vid_pid 0x0403 0xa6d0 -- cgit v1.1 From bcaf775fc10d88d2c63c06bafada141895318b34 Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Mon, 15 Feb 2016 23:17:24 +0100 Subject: Remove support for the GPL incompatible FTDI D2XX library Convert Presto, OpenJTAG and USB-Blaster (I) adapter drivers to libftdi only. Change-Id: Ib28887620a3dcbb754b9dbf87b9731acca3ac600 Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3237 Tested-by: jenkins Reviewed-by: Ricardo Ribalda Delgado Reviewed-by: Freddie Chopin --- README | 42 +-- configure.ac | 364 ++------------------- doc/openocd.texi | 2 +- src/jtag/drivers/Makefile.am | 3 +- src/jtag/drivers/ftd2xx_common.h | 55 ---- src/jtag/drivers/openjtag.c | 173 +--------- src/jtag/drivers/presto.c | 219 ------------- src/jtag/drivers/usb_blaster/Makefile.am | 6 +- src/jtag/drivers/usb_blaster/ublast_access.h | 7 +- .../drivers/usb_blaster/ublast_access_ftd2xx.c | 180 ---------- src/jtag/drivers/usb_blaster/usb_blaster.c | 9 +- src/jtag/interfaces.c | 8 +- tcl/board/telo.cfg | 3 - tcl/interface/usb-jtag.cfg | 4 +- 14 files changed, 44 insertions(+), 1031 deletions(-) delete mode 100644 src/jtag/drivers/ftd2xx_common.h delete mode 100644 src/jtag/drivers/usb_blaster/ublast_access_ftd2xx.c diff --git a/README b/README index 7ca5957..792d7e3 100644 --- a/README +++ b/README @@ -181,10 +181,6 @@ suggestions: particular hardware; - Use "ftdi" interface adapter driver for the FTDI-based devices. -As a PACKAGER, never link against the FTD2XX library, as the resulting -binaries can't be legally distributed, due to the restrictions of the -GPL. - ================ Building OpenOCD @@ -226,10 +222,8 @@ libusb-0.1 or libusb-compat-0.1. A compatible implementation, such as FreeBSD's, additionally needs the corresponding .pc files. USB-Blaster, ASIX Presto and OpenJTAG interface adapter -drivers need either one of: +drivers need: - libftdi: http://www.intra2net.com/en/developer/libftdi/index.php - - ftd2xx: http://www.ftdichip.com/Drivers/D2XX.htm (proprietary, - GPL-incompatible) CMSIS-DAP support needs HIDAPI library. @@ -301,40 +295,6 @@ use both the --enable-parport AND the --enable-parport-giveio option if you want to use giveio instead of ioperm parallel port access method. -Using FTDI's FTD2XX -------------------- - -The (closed source) FTDICHIP.COM solution is faster than libftdi on -Windows. That is the motivation for supporting it even though its -licensing restricts it to non-redistributable OpenOCD binaries, and it -is not available for all operating systems used with OpenOCD. You may, -however, build such copies for personal use. - -The FTDICHIP drivers come as either a (win32) ZIP file, or a (Linux) -TAR.GZ file. You must unpack them ``some where'' convenient. As of this -writing FTDICHIP does not supply means to install these files "in an -appropriate place." - -You should use the following ./configure options to make use of -FTD2XX: - - --with-ftd2xx-win32-zipdir - Where (CYGWIN/MINGW) the zip file from ftdichip.com - was unpacked - --with-ftd2xx-linux-tardir - Where (Linux/Unix) the tar file from ftdichip.com - was unpacked - --with-ftd2xx-lib=(static|shared) - Use static or shared ftd2xx libs (default is static) - -Remember, this library is binary-only, while OpenOCD is licenced -according to GNU GPLv2 without any exceptions. That means that -_distributing_ copies of OpenOCD built with the FTDI code would -violate the OpenOCD licensing terms. - -Note that on Linux there is no good reason to use these FTDI binaries; -they are no faster (on Linux) than libftdi, and cause licensing issues. - ========================== Obtaining OpenOCD From GIT diff --git a/configure.ac b/configure.ac index 5fb4d2c..a47a184 100644 --- a/configure.ac +++ b/configure.ac @@ -159,36 +159,6 @@ else fi AC_MSG_RESULT([$build_release]) -AC_ARG_WITH(ftd2xx, - AS_HELP_STRING([--with-ftd2xx=],[This option has been removed.]), - [ -# Option Given. -cat << __EOF__ - -The option: --with-ftd2xx= has been removed. -On Linux, the new option is: - - --with-ftd2xx-linux-tardir=/path/to/files - -Where is the path the the directory where the "tar.gz" file -from FTDICHIP.COM was unpacked, for example: - - --with-ftd2xx-linux-tardir=${HOME}/libftd2xx0.4.16 - -On Cygwin/MingW32, the new option is: - - --with-ftd2xx-win32-zipdir=/path/to/files - -Where is the path to the directory where the "zip" file from -FTDICHIP.COM was unpacked, for example: - - --with-ftd2xx-win32-zipdir=${HOME}/ftd2xx.cdm.files - -__EOF__ - - AC_MSG_ERROR([Sorry Cannot continue]) - ], [true]) - # Adapter drivers # 1st column -- configure option # 2nd column -- description @@ -223,63 +193,6 @@ m4_define([HIDAPI_ADAPTERS], m4_define([LIBJAYLINK_ADAPTERS], [[[jlink], [SEGGER J-Link Programmer], [JLINK]]]) -#======================================== -# FTD2XXX support comes in 4 forms. -# (1) win32 - via a zip file -# (2) linux - via a tar file -# (3) linux/cygwin/mingw - via libftdi -# (4) darwin - installed under /usr/local -# -# In case (1) and (2) we need to know where the package was unpacked. - -AC_ARG_WITH(ftd2xx-win32-zipdir, - AS_HELP_STRING([--with-ftd2xx-win32-zipdir],[Where (CYGWIN/MINGW) the zip file from ftdichip.com was unpacked (default=search)]), - [ - # option present - if test -d $with_ftd2xx_win32_zipdir - then - with_ftd2xx_win32_zipdir=`cd $with_ftd2xx_win32_zipdir && pwd` - AC_MSG_NOTICE([Using: ftdichip.com library: $with_ftd2xx_win32_zipdir]) - else - AC_MSG_ERROR([Parameter to --with-ftd2xx-win32-zipdir is not a dir: $with_ftd2xx_win32_zipdir]) - fi - ], [true]) - -AC_ARG_WITH(ftd2xx-linux-tardir, - AS_HELP_STRING([--with-ftd2xx-linux-tardir], [Where (Linux/Unix) the tar file from ftdichip.com was unpacked (default=search)]), - [ - # Option present - if test $is_win32 = yes ; then - AC_MSG_ERROR([The option: --with-ftd2xx-linux-tardir is only usable on linux]) - fi - if test -d $with_ftd2xx_linux_tardir - then - with_ftd2xx_linux_tardir=`cd $with_ftd2xx_linux_tardir && pwd` - AC_MSG_NOTICE([Using: ftdichip.com library: $with_ftd2xx_linux_tardir]) - else - AC_MSG_ERROR([Parameter to --with-ftd2xx-linux-tardir is not a dir: $with_ftd2xx_linux_tardir]) - fi - ], [true]) - -AC_ARG_WITH(ftd2xx-lib, - AS_HELP_STRING([--with-ftd2xx-lib], - [Use static or shared ftd2xx libs (default=static)]), - [ - case "$withval" in - static) - with_ftd2xx_lib=$withval - ;; - shared) - with_ftd2xx_lib=$withval - ;; - *) - AC_MSG_ERROR([Option: --with-ftd2xx-lib=static or --with-ftd2xx-lib=shared not, $withval]) - ;; - esac - ], [ - # Default is static - it is simpler :-( - with_ftd2xx_lib=static - ]) AC_ARG_ENABLE([doxygen-html], AS_HELP_STRING([--disable-doxygen-html], @@ -402,12 +315,8 @@ AC_ARG_ENABLE([jtag_vpi], [build_jtag_vpi=$enableval], [build_jtag_vpi=no]) AC_ARG_ENABLE([usb_blaster_libftdi], - AS_HELP_STRING([--enable-usb_blaster_libftdi], [Enable building support for the Altera USB-Blaster using the libftdi driver, opensource alternate of FTD2XX]), - [build_usb_blaster_libftdi=$enableval], [build_usb_blaster_libftdi=no]) - -AC_ARG_ENABLE([usb_blaster_ftd2xx], - AS_HELP_STRING([--enable-usb_blaster_ftd2xx], [Enable building support for the Altera USB-Blaster using the FTD2XX driver from ftdichip.com]), - [build_usb_blaster_ftd2xx=$enableval], [build_usb_blaster_ftd2xx=no]) + AS_HELP_STRING([--enable-usb_blaster_libftdi], [Enable building support for the Altera USB-Blaster using the libftdi driver]), + [build_usb_blaster=$enableval], [build_usb_blaster=no]) AC_ARG_ENABLE([amtjtagaccel], AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]), @@ -452,20 +361,12 @@ AC_ARG_ENABLE([gw16012], [build_gw16012=$enableval], [build_gw16012=no]) AC_ARG_ENABLE([presto_libftdi], - AS_HELP_STRING([--enable-presto_libftdi], [Enable building support for ASIX Presto Programmer using the libftdi driver]), - [build_presto_libftdi=$enableval], [build_presto_libftdi=no]) - -AC_ARG_ENABLE([presto_ftd2xx], - AS_HELP_STRING([--enable-presto_ftd2xx], [Enable building support for ASIX Presto Programmer using the FTD2XX driver]), - [build_presto_ftd2xx=$enableval], [build_presto_ftd2xx=no]) - -AC_ARG_ENABLE([openjtag_ftd2xx], - AS_HELP_STRING([--enable-openjtag_ftd2xx], [Enable building support for the OpenJTAG Programmer with ftd2xx driver]), - [build_openjtag_ftd2xx=$enableval], [build_openjtag_ftd2xx=no]) + AS_HELP_STRING([--enable-presto_libftdi], [Enable building support for ASIX Presto Programmer using the libftdi library]), + [build_presto=$enableval], [build_presto=no]) AC_ARG_ENABLE([openjtag_ftdi], - AS_HELP_STRING([--enable-openjtag_ftdi], [Enable building support for the OpenJTAG Programmer with ftdi driver]), - [build_openjtag_ftdi=$enableval], [build_openjtag_ftdi=no]) + AS_HELP_STRING([--enable-openjtag_ftdi], [Enable building support for the OpenJTAG Programmer with libftdi library]), + [build_openjtag=$enableval], [build_openjtag=no]) AC_ARG_ENABLE([oocd_trace], AS_HELP_STRING([--enable-oocd_trace], @@ -679,10 +580,10 @@ else AC_DEFINE([BUILD_BITBANG], [0], [0 if you don't want a bitbang interface.]) fi -if test $build_usb_blaster_libftdi = yes; then - AC_DEFINE([BUILD_USB_BLASTER_LIBFTDI], [1], [1 if you want libftdi usb_blaster.]) +if test $build_usb_blaster = yes; then + AC_DEFINE([BUILD_USB_BLASTER], [1], [1 if you want libftdi usb_blaster.]) else - AC_DEFINE([BUILD_USB_BLASTER_LIBFTDI], [0], [0 if you don't want libftdi usb_blaster.]) + AC_DEFINE([BUILD_USB_BLASTER], [0], [0 if you don't want libftdi usb_blaster.]) fi if test $build_jtag_vpi = yes; then @@ -691,12 +592,6 @@ else AC_DEFINE([BUILD_JTAG_VPI], [0], [0 if you don't want JTAG VPI.]) fi -if test $build_usb_blaster_ftd2xx = yes; then - AC_DEFINE([BUILD_USB_BLASTER_FTD2XX], [1], [1 if you want ftd2xx usb_blaster.]) -else - AC_DEFINE([BUILD_USB_BLASTER_FTD2XX], [0], [0 if you don't want ftd2xx usb_blaster.]) -fi - if test $build_amtjtagaccel = yes; then AC_DEFINE([BUILD_AMTJTAGACCEL], [1], [1 if you want the Amontec JTAG-Accelerator driver.]) else @@ -709,18 +604,11 @@ else AC_DEFINE([BUILD_GW16012], [0], [0 if you don't want the Gateworks GW16012 driver.]) fi -if test $build_presto_libftdi = yes; then +if test $build_presto = yes; then build_bitq=yes - AC_DEFINE([BUILD_PRESTO_LIBFTDI], [1], [1 if you want the ASIX PRESTO driver using libftdi.]) + AC_DEFINE([BUILD_PRESTO], [1], [1 if you want the ASIX PRESTO driver using libftdi.]) else - AC_DEFINE([BUILD_PRESTO_LIBFTDI], [0], [0 if you don't want the ASIX PRESTO driver using libftdi.]) -fi - -if test $build_presto_ftd2xx = yes; then - build_bitq=yes - AC_DEFINE([BUILD_PRESTO_FTD2XX], [1], [1 if you want the ASIX PRESTO driver using FTD2XX.]) -else - AC_DEFINE([BUILD_PRESTO_FTD2XX], [0], [0 if you don't want the ASIX PRESTO driver using FTD2XX.]) + AC_DEFINE([BUILD_PRESTO], [0], [0 if you don't want the ASIX PRESTO driver using libftdi.]) fi if test $build_bitq = yes; then @@ -729,17 +617,11 @@ else AC_DEFINE([BUILD_BITQ], [0], [0 if you don't want a bitq interface.]) fi -AC_DEFINE([BUILD_OPENJTAG], [0], [0 if you don't want the OpenJTAG driver.]) -AC_DEFINE([BUILD_OPENJTAG_FTD2XX], [0], [0 if you don't want the OpenJTAG driver with FTD2XX driver.]) -AC_DEFINE([BUILD_OPENJTAG_LIBFTDI], [0], [0 if you don't want to build OpenJTAG driver with libftdi.]) -if test $build_openjtag_ftd2xx = yes; then +if test $build_openjtag = yes; then AC_DEFINE([BUILD_OPENJTAG], [1], [1 if you want the OpenJTAG driver.]) - AC_DEFINE([BUILD_OPENJTAG_FTD2XX], [1], [1 if you want the OpenJTAG driver with FTD2XX driver.]) -fi -if test $build_openjtag_ftdi = yes; then - AC_DEFINE([BUILD_OPENJTAG], [1], [1 if you want the OpenJTAG drvier.]) - AC_DEFINE([BUILD_OPENJTAG_LIBFTDI], [1], [1 if you want to build OpenJTAG with FTDI driver.]) +else + AC_DEFINE([BUILD_OPENJTAG], [0], [0 if you don't want the OpenJTAG driver.]) fi if test $build_oocd_trace = yes; then @@ -775,210 +657,8 @@ if test $build_sysfsgpio = yes; then else AC_DEFINE([BUILD_SYSFSGPIO], [0], [0 if you don't want SysfsGPIO driver.]) fi -#-- Deal with MingW/Cygwin FTD2XX issues - -if test $is_win32 = yes; then -if test "${with_ftd2xx_linux_tardir+set}" = set -then - AC_MSG_ERROR([The option: with_ftd2xx_linux_tardir is for LINUX only.]) -fi - -if test $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes -o $build_openjtag_ftd2xx = yes; then - AC_MSG_CHECKING([for ftd2xx.lib exists (win32)]) - - # if we are given a zipdir... - if test "${with_ftd2xx_win32_zipdir+set}" = set - then - # Set the CFLAGS for "ftd2xx.h" - f=$with_ftd2xx_win32_zipdir/ftd2xx.h - if test ! -f $f ; then - AC_MSG_ERROR([File: $f cannot be found]) - fi - CFLAGS="$CFLAGS -I$with_ftd2xx_win32_zipdir" - - # And calculate the LDFLAGS for the machine - case "$host_cpu" in - i?86|x86_32) - LDFLAGS="$LDFLAGS -L$with_ftd2xx_win32_zipdir/i386" - LIBS="$LIBS -lftd2xx" - f=$with_ftd2xx_win32_zipdir/i386/ftd2xx.lib - ;; - amd64|x86_64) - LDFLAGS="$LDFLAGS -L$with_ftd2xx_win32_zipdir/amd64" - LIBS="$LIBS -lftd2xx" - f=$with_ftd2xx_win32_zipdir/amd64/ftd2xx.lib - ;; - *) - AC_MSG_ERROR([Unknown Win32 host cpu: $host_cpu]) - ;; - esac - if test ! -f $f ; then - AC_MSG_ERROR([Library: $f not found]) - fi - else - LIBS="$LIBS -lftd2xx" - AC_MSG_WARN([ASSUMPTION: The (win32) FTDICHIP.COM files: ftd2xx.h and ftd2xx.lib are in a proper place]) - fi -fi -fi # win32 - -if test $is_darwin = yes ; then -if test "${with_ftd2xx_win32_zipdir+set}" = set -then - AC_MSG_ERROR([The option: --with-ftd2xx-win32-zipdir is for win32 only]) -fi -if test "${with_ftd2xx_linux_tardir+set}" = set -then - AC_MSG_ERROR([The option: with_ftd2xx_linux_tardir is for LINUX only.]) -fi - -if test $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then - AC_MSG_CHECKING([for libftd2xx.a (darwin)]) - - if test ! -f /usr/local/include/ftd2xx.h ; then - AC_MSG_ERROR([ftd2xx library from FTDICHIP.com seems to be missing, cannot find: /usr/local/include/ftd2xx.h]) - fi - - CFLAGS="$CFLAGS -I/usr/local/include" - LDFLAGS="$LDFLAGS -L/usr/local/lib" - LIBS="$LIBS -lftd2xx" - AC_MSG_RESULT([-L/usr/local/lib -lftd2xx]) -fi -fi # darwin - -if test $is_win32 = no && test $is_darwin = no ; then - -if test "${with_ftd2xx_win32_zipdir+set}" = set -then - AC_MSG_ERROR([The option: --with-ftd2xx-win32-zipdir is for win32 only]) -fi - -if test $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes -o $build_openjtag_ftd2xx = yes; then - # Must be linux - if test $host_os != linux-gnu && test $host_os != linux ; then - AC_MSG_ERROR([The (linux) ftd2xx library from FTDICHIP.com is linux only. Try --enable-*-libftdi instead]) - fi - # Are we given a TAR directory? - if test "${with_ftd2xx_linux_tardir+set}" = set - then - AC_MSG_CHECKING([uninstalled ftd2xx distribution]) - # The .H file is simple.. - FTD2XX_H=$with_ftd2xx_linux_tardir/ftd2xx.h - if test ! -f "${FTD2XX_H}"; then - AC_MSG_ERROR([Option: --with-ftd2xx-linux-tardir appears wrong, cannot find: ${FTD2XX_H}]) - fi - CFLAGS="$CFLAGS -I$with_ftd2xx_linux_tardir" - if test $with_ftd2xx_lib = shared; then - FTD2XX_LDFLAGS="-L$with_ftd2xx_linux_tardir" - FTD2XX_LIB="-lftd2xx" - else - # Test #1 - v1.0.x - case "$host_cpu" in - i?86|x86_32) - dir=build/i386;; - amd64|x86_64) - dir=build/x86_64;; - *) - dir=none;; - esac - if test -f "$with_ftd2xx_linux_tardir/$dir/libftd2xx.a"; then - FTD2XX_LDFLAGS="-L$with_ftd2xx_linux_tardir/$dir" - # Also needs -lrt - FTD2XX_LIB="-lftd2xx -lrt" - else - # Test Number2. - # Grr.. perhaps it exists as a version number? - FTD2XX_LIB="$with_ftd2xx_linux_tardir/static_lib/libftd2xx.a.*.*.*" - count=`ls ${FTD2XX_LIB} | wc -l` - if test $count -gt 1 ; then - AC_MSG_ERROR([Multiple libftd2xx.a files found in: $with_ftd2xx_linux_tardir/static_lib sorry cannot handle this yet]) - fi - if test $count -ne 1 ; then - AC_MSG_ERROR([Not found: $f, option: --with-ftd2xx-linux-tardir appears to be wrong]) - fi - # Because the "-l" rules do not understand version numbers... - # we will just stuff the absolute path onto the LIBS variable - FTD2XX_LIB="`ls ${FTD2XX_LIB}` -lpthread" - FTD2XX_LDFLAGS="" - fi - fi - LDFLAGS="${LDFLAGS} ${FTD2XX_LDFLAGS}" - LIBS="${FTD2XX_LIB} ${LIBS}" - AC_MSG_RESULT([${FTD2XX_LDFLAGS} ${FTD2XX_LIB}]) - else - AC_CHECK_HEADER([ftd2xx.h],[],[ - AC_MSG_ERROR([You seem to be missing the FTD2xx driver header file.]) - ]) - AC_SEARCH_LIBS([FT_GetLibraryVersion],[ftd2xx],,[ - AC_MSG_ERROR([You appear to be missing the FTD2xx driver library.]) - ],[-lrt -lusb-1.0]) - fi -fi -fi # linux - -if test $build_presto_ftd2xx = yes -o $build_usb_blaster_ftd2xx = yes ; then - -# Before we go any further - make sure we can *BUILD* and *RUN* -# a simple app with the "ftd2xx.lib" file - in what ever form we where given -# We should be able to compile, link and run this test program now -AC_MSG_CHECKING([whether ftd2xx library works]) - -# -# Save the LDFLAGS for later.. -LDFLAGS_SAVE=$LDFLAGS -CFLAGS_SAVE=$CFLAGS -_LDFLAGS=`eval echo $LDFLAGS` -_CFLAGS=`eval echo $CFLAGS` -LDFLAGS=$_LDFLAGS -CFLAGS=$_CFLAGS - -AC_RUN_IFELSE([AC_LANG_PROGRAM([[ -#include "confdefs.h" -#if IS_WIN32 -#include "windows.h" -#endif -#include -#include - ]], [[ - DWORD x; - FT_GetLibraryVersion( &x ); - ]])], [ - AC_MSG_RESULT([Success!]) - ], [ - AC_MSG_ERROR([Cannot build & run test program using ftd2xx.lib]) - ], [ - AC_MSG_RESULT([Skipping as we are cross-compiling]) - ]) - -AC_MSG_CHECKING([for ftd2xx FT232H device support]) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include "confdefs.h" -#if IS_WIN32 -#include "windows.h" -#endif -#include -#include - -DWORD x = FT_DEVICE_232H; - ]], [])], [ - AC_DEFINE([HAS_ENUM_FT232H], [1], - [Support FT232H with FTD2XX or libftdi.]) - has_enum_ft232h=yes - ], [ - has_enum_ft232h=no - ]) - AC_MSG_RESULT([$has_enum_ft232h]) - - if test $has_enum_ft232h = no; then - AC_MSG_WARN([You need a newer FTD2XX driver (version 2.08.12 or later).]) - fi - -LDFLAGS=$LDFLAGS_SAVE -CFLAGS=$CFLAGS_SAVE -fi -if test $build_usb_blaster_libftdi = yes -o \ - $build_openjtag_ftdi = yes -o $build_presto_libftdi = yes; then +if test $build_usb_blaster = yes -o $build_openjtag = yes -o $build_presto = yes; then # we can have libftdi or libftdi1, so check it and use the latest one PKG_CHECK_MODULES([LIBFTDI], [libftdi1], [use_libftdi=yes], [use_libftdi=no]) @@ -1032,7 +712,7 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ enum ftdi_chip_type x = TYPE_232H; ]])], [ AC_DEFINE([HAS_ENUM_FT232H], [1], - [Support FT232H with FTD2XX or libftdi.]) + [Support FT232H with libftdi.]) has_enum_ft232h=yes ], [ has_enum_ft232h=no @@ -1131,15 +811,13 @@ AM_CONDITIONAL([IOUTIL], [test $build_ioutil = yes]) AM_CONDITIONAL([AT91RM9200], [test $build_at91rm9200 = yes]) AM_CONDITIONAL([BCM2835GPIO], [test $build_bcm2835gpio = yes]) AM_CONDITIONAL([BITBANG], [test $build_bitbang = yes]) -AM_CONDITIONAL([USB_BLASTER_LIBFTDI], [test $build_usb_blaster_libftdi = yes]) -AM_CONDITIONAL([USB_BLASTER_FTD2XX], [test $build_usb_blaster_ftd2xx = yes]) AM_CONDITIONAL([JTAG_VPI], [test $build_jtag_vpi = yes -o $build_jtag_vpi = yes]) -AM_CONDITIONAL([USB_BLASTER_DRIVER], [test $build_usb_blaster_ftd2xx = yes -o $build_usb_blaster_libftdi = yes -o $enable_usb_blaster_2 != no]) +AM_CONDITIONAL([USB_BLASTER_DRIVER], [test $build_usb_blaster = yes -o $enable_usb_blaster_2 != no]) +AM_CONDITIONAL([USB_BLASTER], [test $build_usb_blaster = yes]) AM_CONDITIONAL([AMTJTAGACCEL], [test $build_amtjtagaccel = yes]) AM_CONDITIONAL([GW16012], [test $build_gw16012 = yes]) -AM_CONDITIONAL([PRESTO_LIBFTDI], [test $build_presto_libftdi = yes]) -AM_CONDITIONAL([PRESTO_DRIVER], [test $build_presto_ftd2xx = yes -o $build_presto_libftdi = yes]) -AM_CONDITIONAL([OPENJTAG], [test $build_openjtag_ftd2xx = yes -o $build_openjtag_ftdi = yes]) +AM_CONDITIONAL([PRESTO], [test $build_presto = yes]) +AM_CONDITIONAL([OPENJTAG], [test $build_openjtag = yes]) AM_CONDITIONAL([OOCD_TRACE], [test $build_oocd_trace = yes]) AM_CONDITIONAL([REMOTE_BITBANG], [test $build_remote_bitbang = yes]) AM_CONDITIONAL([BUSPIRATE], [test $build_buspirate = yes]) diff --git a/doc/openocd.texi b/doc/openocd.texi index 34cf69d..0fef9fb 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2624,7 +2624,7 @@ reset_config srst_only @end example @end deffn -@deffn {Command} {usb_blaster_lowlevel_driver} (@option{ftdi}|@option{ftd2xx}|@option{ublast2}) +@deffn {Command} {usb_blaster_lowlevel_driver} (@option{ftdi}|@option{ublast2}) Chooses the low level access method for the adapter. If not specified, @option{ftdi} is selected unless it wasn't enabled during the configure stage. USB-Blaster II needs @option{ublast2}. diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index 4c4e774..1322c0f 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -85,7 +85,7 @@ endif if BITQ DRIVERFILES += bitq.c endif -if PRESTO_DRIVER +if PRESTO DRIVERFILES += presto.c endif if USBPROG @@ -145,7 +145,6 @@ endif noinst_HEADERS = \ bitbang.h \ bitq.h \ - ftd2xx_common.h \ libusb0_common.h \ libusb1_common.h \ libusb_common.h \ diff --git a/src/jtag/drivers/ftd2xx_common.h b/src/jtag/drivers/ftd2xx_common.h deleted file mode 100644 index eaf14ae..0000000 --- a/src/jtag/drivers/ftd2xx_common.h +++ /dev/null @@ -1,55 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2011 by Spencer Oliver * - * * - * Written by Arnim Laeuger, 2008 (from urjtag) * - * * - * 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, see . * - ***************************************************************************/ - -#ifndef OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H -#define OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H - -#if ((BUILD_PRESTO_FTD2XX == 1) || (BUILD_USB_BLASTER_FTD2XX == 1)) -#include - -static const char *ftd2xx_status_string(FT_STATUS status) -{ - switch (status) { - case FT_OK: return "OK"; - case FT_INVALID_HANDLE: return "invalid handle"; - case FT_DEVICE_NOT_FOUND: return "device not found"; - case FT_DEVICE_NOT_OPENED: return "device not opened"; - case FT_IO_ERROR: return "io error"; - case FT_INSUFFICIENT_RESOURCES: return "insufficient resources"; - case FT_INVALID_PARAMETER: return "invalid parameter"; - case FT_INVALID_BAUD_RATE: return "invalid baud rate"; - - case FT_DEVICE_NOT_OPENED_FOR_ERASE: return "device not opened for erase"; - case FT_DEVICE_NOT_OPENED_FOR_WRITE: return "device not opened for write"; - case FT_FAILED_TO_WRITE_DEVICE: return "failed to write device"; - case FT_EEPROM_READ_FAILED: return "eeprom read failed"; - case FT_EEPROM_WRITE_FAILED: return "eeprom write failed"; - case FT_EEPROM_ERASE_FAILED: return "eeprom erase failed"; - case FT_EEPROM_NOT_PRESENT: return "eeprom not present"; - case FT_EEPROM_NOT_PROGRAMMED: return "eeprom not programmed"; - case FT_INVALID_ARGS: return "invalid args"; - case FT_NOT_SUPPORTED: return "not supported"; - case FT_OTHER_ERROR: return "other error"; - } - - return "undefined FTD2xx error"; -} - -#endif -#endif /* OPENOCD_JTAG_DRIVERS_FTD2XX_COMMON_H */ diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index 157020e..5d1084c 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -1,6 +1,6 @@ /******************************************************************************* * Driver for OpenJTAG Project (www.openjtag.org) * - * Compatible with libftdi and ftd2xx drivers. * + * Compatible with libftdi driver. * * * * Copyright (C) 2010 by Ivan Meleca * * * @@ -66,19 +66,8 @@ typedef enum openjtag_tap_state { OPENJTAG_TAP_UPDATE_IR = 15, } openjtag_tap_state_t; -#if (BUILD_OPENJTAG_FTD2XX == 1 && BUILD_OPENJTAG_LIBFTDI == 1) -#error "BUILD_OPENJTAG_FTD2XX && BUILD_OPENJTAG_LIBFTDI " - "are mutually exclusive" -#elif (BUILD_OPENJTAG_FTD2XX != 1 && BUILD_OPENJTAG_LIBFTDI != 1) -#error "BUILD_OPENJTAG_FTD2XX || BUILD_OPENJTAG_LIBFTDI must be chosen" -#endif - /* OPENJTAG access library includes */ -#if BUILD_OPENJTAG_FTD2XX == 1 -#include -#elif BUILD_OPENJTAG_LIBFTDI == 1 #include -#endif /* OpenJTAG vid/pid */ static uint16_t openjtag_vid = 0x0403; @@ -86,12 +75,7 @@ static uint16_t openjtag_pid = 0x6001; static char *openjtag_device_desc; -#if BUILD_OPENJTAG_FTD2XX == 1 -static FT_HANDLE ftdih; - -#elif BUILD_OPENJTAG_LIBFTDI == 1 static struct ftdi_context ftdic; -#endif #define OPENJTAG_BUFFER_SIZE 504 #define OPENJTAG_MAX_PENDING_RESULTS 256 @@ -204,23 +188,6 @@ static int8_t openjtag_get_tap_state(int8_t state) static int openjtag_buf_write( uint8_t *buf, int size, uint32_t *bytes_written) { -#if BUILD_OPENJTAG_FTD2XX == 1 - FT_STATUS status; - DWORD dw_bytes_written; - -#ifdef _DEBUG_USB_COMMS_ - openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE); -#endif - - status = FT_Write(ftdih, buf, size, &dw_bytes_written); - if (status != FT_OK) { - *bytes_written = dw_bytes_written; - LOG_ERROR("FT_Write returned: %u", status); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_written = dw_bytes_written; - return ERROR_OK; -#elif BUILD_OPENJTAG_LIBFTDI == 1 int retval; #ifdef _DEBUG_USB_COMMS_ openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE); @@ -236,36 +203,10 @@ static int openjtag_buf_write( *bytes_written += retval; return ERROR_OK; -#endif } static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read) { - -#if BUILD_OPENJTAG_FTD2XX == 1 - DWORD dw_bytes_read; - FT_STATUS status; - int timeout = 50; - - *bytes_read = 0; - while (qty && (*bytes_read < qty) && timeout--) { - - status = FT_Read(ftdih, buf + *bytes_read, - qty - *bytes_read, &dw_bytes_read); - if (status != FT_OK) { - *bytes_read = dw_bytes_read; - LOG_ERROR("FT_Read returned: %u", status); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_read += dw_bytes_read; - } - -#ifdef _DEBUG_USB_COMMS_ - openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ); -#endif - - return ERROR_OK; -#elif BUILD_OPENJTAG_LIBFTDI == 1 int retval; int timeout = 5; @@ -287,7 +228,6 @@ static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read) openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ); #endif -#endif return ERROR_OK; } @@ -339,105 +279,19 @@ static int openjtag_init(void) { uint8_t latency_timer; -#if BUILD_OPENJTAG_FTD2XX == 1 - FT_STATUS status; -#endif - -usb_tx_buf_offs = 0; -usb_rx_buf_len = 0; -openjtag_scan_result_count = 0; + usb_tx_buf_offs = 0; + usb_rx_buf_len = 0; + openjtag_scan_result_count = 0; -#if BUILD_OPENJTAG_FTD2XX == 1 - LOG_DEBUG("'openjtag' interface using FTD2XX"); -#elif BUILD_OPENJTAG_LIBFTDI == 1 LOG_DEBUG("'openjtag' interface using libftdi"); -#endif -/* Open by device description */ -if (openjtag_device_desc == NULL) { - LOG_WARNING("no openjtag device description specified, " + /* Open by device description */ + if (openjtag_device_desc == NULL) { + LOG_WARNING("no openjtag device description specified, " "using default 'Open JTAG Project'"); - openjtag_device_desc = "Open JTAG Project"; -} - -#if BUILD_OPENJTAG_FTD2XX == 1 - -#if IS_WIN32 == 0 - /* Add non-standard Vid/Pid to the linux driver */ - status = FT_SetVIDPID(openjtag_vid, openjtag_pid); - if (status != FT_OK) { - LOG_WARNING("couldn't add %4.4x:%4.4x", - openjtag_vid, openjtag_pid); - } -#endif - - status = FT_OpenEx(openjtag_device_desc, FT_OPEN_BY_DESCRIPTION, - &ftdih); - if (status != FT_OK) { - DWORD num_devices; - - LOG_ERROR("unable to open ftdi device: %u", status); - status = FT_ListDevices(&num_devices, NULL, - FT_LIST_NUMBER_ONLY); - if (status == FT_OK) { - char **desc_array = malloc(sizeof(char *) - * (num_devices + 1)); - unsigned int i; - - for (i = 0; i < num_devices; i++) - desc_array[i] = malloc(64); - desc_array[num_devices] = NULL; - - status = FT_ListDevices(desc_array, &num_devices, - FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION); - - if (status == FT_OK) { - LOG_ERROR("ListDevices: %u\n", num_devices); - for (i = 0; i < num_devices; i++) - LOG_ERROR("%i: %s", i, desc_array[i]); - } - - for (i = 0; i < num_devices; i++) - free(desc_array[i]); - free(desc_array); - } else { - LOG_ERROR("ListDevices: NONE\n"); - } - return ERROR_JTAG_INIT_FAILED; + openjtag_device_desc = "Open JTAG Project"; } - status = FT_SetLatencyTimer(ftdih, 2); - if (status != FT_OK) { - LOG_ERROR("unable to set latency timer: %u", status); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_GetLatencyTimer(ftdih, &latency_timer); - if (status != FT_OK) { - LOG_ERROR("unable to get latency timer: %u", status); - return ERROR_JTAG_INIT_FAILED; - } - LOG_DEBUG("current latency timer: %i", latency_timer); - - status = FT_SetBitMode(ftdih, 0x00, 0x40); - if (status != FT_OK) { - LOG_ERROR("unable to disable bit i/o mode: %u", status); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_SetTimeouts(ftdih, 50, 0); - if (status != FT_OK) { - LOG_ERROR("unable to set timeouts: %u", status); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX); - if (status != FT_OK) { - LOG_ERROR("unable to FT_Purge() %u", status); - return ERROR_JTAG_INIT_FAILED; - } - -#elif BUILD_OPENJTAG_LIBFTDI == 1 if (ftdi_init(&ftdic) < 0) return ERROR_JTAG_INIT_FAILED; @@ -470,18 +324,11 @@ if (openjtag_device_desc == NULL) { ftdi_get_error_string(&ftdic)); return ERROR_JTAG_DEVICE_ERROR; } -#endif -#if BUILD_OPENJTAG_FTD2XX == 1 - status = FT_Purge(ftdih, FT_PURGE_RX | FT_PURGE_TX); - if (status != FT_OK) - return ERROR_JTAG_INIT_FAILED; -#elif BUILD_OPENJTAG_LIBFTDI == 1 if (ftdi_usb_purge_buffers(&ftdic) < 0) { LOG_ERROR("ftdi_purge_buffers: %s", ftdic.error_str); return ERROR_JTAG_INIT_FAILED; } -#endif /* OpenJTAG speed */ openjtag_sendcommand(0xE0); /*Start at slowest adapter speed*/ @@ -494,12 +341,8 @@ if (openjtag_device_desc == NULL) { static int openjtag_quit(void) { -#if BUILD_OPENJTAG_FTD2XX == 1 - FT_Close(ftdih); -#elif BUILD_OPENJTAG_LIBFTDI == 1 ftdi_usb_close(&ftdic); ftdi_deinit(&ftdic); -#endif return ERROR_OK; } diff --git a/src/jtag/drivers/presto.c b/src/jtag/drivers/presto.c index 0a18dc9..49caa67 100644 --- a/src/jtag/drivers/presto.c +++ b/src/jtag/drivers/presto.c @@ -34,14 +34,7 @@ #include "bitq.h" /* PRESTO access library includes */ -#if BUILD_PRESTO_FTD2XX == 1 -#include -#include "ftd2xx_common.h" -#elif BUILD_PRESTO_LIBFTDI == 1 #include -#else -#error "BUG: either FTD2XX and LIBFTDI has to be used" -#endif /* -------------------------------------------------------------------------- */ @@ -55,13 +48,8 @@ #define BUFFER_SIZE (64*62) struct presto { -#if BUILD_PRESTO_FTD2XX == 1 - FT_HANDLE handle; - FT_STATUS status; -#elif BUILD_PRESTO_LIBFTDI == 1 struct ftdi_context ftdic; int retval; -#endif char serial[FT_DEVICE_SERNUM_LEN]; @@ -95,15 +83,6 @@ static uint8_t presto_init_seq[] = { static int presto_write(uint8_t *buf, uint32_t size) { -#if BUILD_PRESTO_FTD2XX == 1 - DWORD ftbytes; - presto->status = FT_Write(presto->handle, buf, size, &ftbytes); - if (presto->status != FT_OK) { - LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(presto->status)); - return ERROR_JTAG_DEVICE_ERROR; - } - -#elif BUILD_PRESTO_LIBFTDI == 1 uint32_t ftbytes; presto->retval = ftdi_write_data(&presto->ftdic, buf, size); if (presto->retval < 0) { @@ -111,7 +90,6 @@ static int presto_write(uint8_t *buf, uint32_t size) return ERROR_JTAG_DEVICE_ERROR; } ftbytes = presto->retval; -#endif if (ftbytes != size) { LOG_ERROR("couldn't write the requested number of bytes to PRESTO (%u < %u)", @@ -124,15 +102,6 @@ static int presto_write(uint8_t *buf, uint32_t size) static int presto_read(uint8_t *buf, uint32_t size) { -#if BUILD_PRESTO_FTD2XX == 1 - DWORD ftbytes; - presto->status = FT_Read(presto->handle, buf, size, &ftbytes); - if (presto->status != FT_OK) { - LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(presto->status)); - return ERROR_JTAG_DEVICE_ERROR; - } - -#elif BUILD_PRESTO_LIBFTDI == 1 uint32_t ftbytes = 0; struct timeval timeout, now; @@ -152,7 +121,6 @@ static int presto_read(uint8_t *buf, uint32_t size) ((now.tv_sec == timeout.tv_sec) && (now.tv_usec > timeout.tv_usec))) break; } -#endif if (ftbytes != size) { /* this is just a warning, there might have been timeout when detecting PRESTO, @@ -165,150 +133,6 @@ static int presto_read(uint8_t *buf, uint32_t size) return ERROR_OK; } -#if BUILD_PRESTO_FTD2XX == 1 -static int presto_open_ftd2xx(char *req_serial) -{ - uint32_t i; - DWORD numdevs; - DWORD vidpid; - char devname[FT_DEVICE_NAME_LEN]; - FT_DEVICE device; - - BYTE presto_data; - DWORD ftbytes; - - presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; - -#if IS_WIN32 == 0 - /* Add non-standard Vid/Pid to the linux driver */ - presto->status = FT_SetVIDPID(PRESTO_VID, PRESTO_PID); - if (presto->status != FT_OK) { - LOG_ERROR("couldn't add PRESTO VID/PID"); - exit(-1); - } -#endif - - presto->status = FT_ListDevices(&numdevs, NULL, FT_LIST_NUMBER_ONLY); - if (presto->status != FT_OK) { - LOG_ERROR("FT_ListDevices failed: %s", ftd2xx_status_string(presto->status)); - return ERROR_JTAG_DEVICE_ERROR; - } - - LOG_DEBUG("FTDI devices available: %" PRIu32, (uint32_t)numdevs); - for (i = 0; i < numdevs; i++) { - presto->status = FT_Open(i, &(presto->handle)); - if (presto->status != FT_OK) { - /* this is not fatal, the device may be legitimately open by other process, - *hence debug message only */ - LOG_DEBUG("FT_Open failed: %s", ftd2xx_status_string(presto->status)); - continue; - } - LOG_DEBUG("FTDI device %i open", (int)i); - - presto->status = FT_GetDeviceInfo(presto->handle, &device, - &vidpid, presto->serial, devname, NULL); - if (presto->status == FT_OK) { - if (vidpid == PRESTO_VID_PID && (req_serial == NULL || - !strcmp(presto->serial, req_serial))) - break; - } else - LOG_DEBUG("FT_GetDeviceInfo failed: %s", ftd2xx_status_string( - presto->status)); - - LOG_DEBUG("FTDI device %i does not match, closing", (int)i); - FT_Close(presto->handle); - presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; - } - - if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE) - return ERROR_JTAG_DEVICE_ERROR; /* presto not open, return */ - - presto->status = FT_SetLatencyTimer(presto->handle, 1); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_SetTimeouts(presto->handle, 100, 0); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto_data = 0xD0; - presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - /* delay between first write/read turnaround (after purge?) necessary - * under Linux for unknown reason, - * probably a bug in library threading */ - usleep(100000); - presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - if (ftbytes != 1) { - LOG_DEBUG("PRESTO reset"); - - presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - presto->status = FT_SetBitMode(presto->handle, 0x80, 1); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - presto->status = FT_SetBaudRate(presto->handle, 9600); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto_data = 0; - for (i = 0; i < 4 * 62; i++) { - presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - } - usleep(100000); - - presto->status = FT_SetBitMode(presto->handle, 0x00, 0); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto_data = 0xD0; - presto->status = FT_Write(presto->handle, &presto_data, 1, &ftbytes); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - /* delay between first write/read turnaround (after purge?) necessary under Linux for unknown reason, - probably a bug in library threading */ - usleep(100000); - presto->status = FT_Read(presto->handle, &presto_data, 1, &ftbytes); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - if (ftbytes != 1) { - LOG_DEBUG("PRESTO not responding"); - return ERROR_JTAG_DEVICE_ERROR; - } - } - - presto->status = FT_SetTimeouts(presto->handle, 0, 0); - if (presto->status != FT_OK) - return ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_Write(presto->handle, &presto_init_seq, - sizeof(presto_init_seq), &ftbytes); - - if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq)) - return ERROR_JTAG_DEVICE_ERROR; - - return ERROR_OK; -} - -#elif BUILD_PRESTO_LIBFTDI == 1 static int presto_open_libftdi(char *req_serial) { uint8_t presto_data; @@ -371,7 +195,6 @@ static int presto_open_libftdi(char *req_serial) return ERROR_OK; } -#endif /* BUILD_PRESTO_LIBFTDI == 1 */ static int presto_open(char *req_serial) { @@ -391,11 +214,7 @@ static int presto_open(char *req_serial) presto->jtag_speed = 0; -#if BUILD_PRESTO_FTD2XX == 1 - return presto_open_ftd2xx(req_serial); -#elif BUILD_PRESTO_LIBFTDI == 1 return presto_open_libftdi(req_serial); -#endif } static int presto_close(void) @@ -403,35 +222,6 @@ static int presto_close(void) int result = ERROR_OK; -#if BUILD_PRESTO_FTD2XX == 1 - DWORD ftbytes; - - if (presto->handle == (FT_HANDLE)INVALID_HANDLE_VALUE) - return result; - - presto->status = FT_Purge(presto->handle, FT_PURGE_TX | FT_PURGE_RX); - if (presto->status != FT_OK) - result = ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_Write(presto->handle, - &presto_init_seq, - sizeof(presto_init_seq), - &ftbytes); - if (presto->status != FT_OK || ftbytes != sizeof(presto_init_seq)) - result = ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_SetLatencyTimer(presto->handle, 16); - if (presto->status != FT_OK) - result = ERROR_JTAG_DEVICE_ERROR; - - presto->status = FT_Close(presto->handle); - if (presto->status != FT_OK) - result = ERROR_JTAG_DEVICE_ERROR; - else - presto->handle = (FT_HANDLE)INVALID_HANDLE_VALUE; - -#elif BUILD_PRESTO_LIBFTDI == 1 - presto->retval = ftdi_write_data(&presto->ftdic, presto_init_seq, sizeof(presto_init_seq)); if (presto->retval != sizeof(presto_init_seq)) result = ERROR_JTAG_DEVICE_ERROR; @@ -445,7 +235,6 @@ static int presto_close(void) result = ERROR_JTAG_DEVICE_ERROR; else ftdi_deinit(&presto->ftdic); -#endif return result; } @@ -455,11 +244,7 @@ static int presto_flush(void) if (presto->buff_out_pos == 0) return ERROR_OK; -#if BUILD_PRESTO_FTD2XX == 1 - if (presto->status != FT_OK) { -#elif BUILD_PRESTO_LIBFTDI == 1 if (presto->retval < 0) { -#endif LOG_DEBUG("error in previous communication, canceling I/O operation"); return ERROR_JTAG_DEVICE_ERROR; } @@ -502,13 +287,9 @@ static int presto_sendbyte(int data) } else return ERROR_JTAG_DEVICE_ERROR; -#if BUILD_PRESTO_FTD2XX == 1 - if (presto->buff_out_pos >= BUFFER_SIZE) -#elif BUILD_PRESTO_LIBFTDI == 1 /* libftdi does not do background read, be sure that USB IN buffer does not overflow (128 *bytes only!) */ if (presto->buff_out_pos >= BUFFER_SIZE || presto->buff_in_exp == 128) -#endif return presto_flush(); return ERROR_OK; diff --git a/src/jtag/drivers/usb_blaster/Makefile.am b/src/jtag/drivers/usb_blaster/Makefile.am index 0fb4700..0d4ef61 100644 --- a/src/jtag/drivers/usb_blaster/Makefile.am +++ b/src/jtag/drivers/usb_blaster/Makefile.am @@ -7,14 +7,10 @@ libocdusbblaster_la_SOURCES = $(USB_BLASTER_SRC) USB_BLASTER_SRC = usb_blaster.c -if USB_BLASTER_LIBFTDI +if USB_BLASTER USB_BLASTER_SRC += ublast_access_ftdi.c endif -if USB_BLASTER_FTD2XX -USB_BLASTER_SRC += ublast_access_ftd2xx.c -endif - if USB_BLASTER_2 USB_BLASTER_SRC += ublast2_access_libusb.c endif diff --git a/src/jtag/drivers/usb_blaster/ublast_access.h b/src/jtag/drivers/usb_blaster/ublast_access.h index 00349d2..252f003 100644 --- a/src/jtag/drivers/usb_blaster/ublast_access.h +++ b/src/jtag/drivers/usb_blaster/ublast_access.h @@ -56,19 +56,16 @@ struct ublast_lowlevel { /** * ublast_register_ftdi - get a lowlevel USB Blaster driver - * ublast_register_ftd2xx - get a lowlevel USB Blaster driver * ublast2_register_libusb - get a lowlevel USB Blaster II driver * - * Get a lowlevel USB-Blaster driver. In the current implementation, there are 3 + * Get a lowlevel USB-Blaster driver. In the current implementation, there are 2 * possible lowlevel drivers : - * - one based on libftdi from ftdichip.com - * - one based on libftdxx, the free alternative + * - one based on libftdi, * - one based on libusb, specific to the USB-Blaster II * * Returns the lowlevel driver structure. */ extern struct ublast_lowlevel *ublast_register_ftdi(void); -extern struct ublast_lowlevel *ublast_register_ftd2xx(void); extern struct ublast_lowlevel *ublast2_register_libusb(void); #endif /* OPENOCD_JTAG_DRIVERS_USB_BLASTER_UBLAST_ACCESS_H */ diff --git a/src/jtag/drivers/usb_blaster/ublast_access_ftd2xx.c b/src/jtag/drivers/usb_blaster/ublast_access_ftd2xx.c deleted file mode 100644 index ffcf312..0000000 --- a/src/jtag/drivers/usb_blaster/ublast_access_ftd2xx.c +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Driver for USB-JTAG, Altera USB-Blaster and compatibles - * - * Inspired from original code from Kolja Waschk's USB-JTAG project - * (http://www.ixo.de/info/usb_jtag/), and from openocd project. - * - * Copyright (C) 2012 Robert Jarzmik robert.jarzmik@free.fr - * Copyright (C) 2011 Ali Lown ali@lown.me.uk - * Copyright (C) 2009 Catalin Patulea cat@vv.carleton.ca - * Copyright (C) 2006 Kolja Waschk usbjtag@ixo.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, see . - * - */ - -#ifdef HAVE_CONFIG_H -#include -#endif -#include -#include - -#include "ublast_access.h" - -#include -#include "jtag/drivers/ftd2xx_common.h" - -static FT_HANDLE *ublast_getftdih(struct ublast_lowlevel *low) -{ - return low->priv; -} - -static int ublast_ftd2xx_write(struct ublast_lowlevel *low, uint8_t *buf, int size, - uint32_t *bytes_written) -{ - FT_STATUS status; - DWORD dw_bytes_written; - FT_HANDLE *ftdih = ublast_getftdih(low); - - status = FT_Write(*ftdih, buf, size, &dw_bytes_written); - if (status != FT_OK) { - *bytes_written = dw_bytes_written; - LOG_ERROR("FT_Write returned: %s", ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_written = dw_bytes_written; - return ERROR_OK; -} - -static int ublast_ftd2xx_read(struct ublast_lowlevel *low, uint8_t *buf, - unsigned size, uint32_t *bytes_read) -{ - DWORD dw_bytes_read; - FT_STATUS status; - FT_HANDLE *ftdih = ublast_getftdih(low); - - status = FT_Read(*ftdih, buf, size, &dw_bytes_read); - if (status != FT_OK) { - *bytes_read = dw_bytes_read; - LOG_ERROR("FT_Read returned: %s", ftd2xx_status_string(status)); - return ERROR_JTAG_DEVICE_ERROR; - } - *bytes_read = dw_bytes_read; - return ERROR_OK; -} - -static int ublast_ftd2xx_init(struct ublast_lowlevel *low) -{ - FT_STATUS status; - FT_HANDLE *ftdih = ublast_getftdih(low); - uint8_t latency_timer; - - LOG_INFO("usb blaster interface using FTD2XX"); - /* Open by device description */ - if (low->ublast_device_desc == NULL) { - LOG_WARNING("no usb blaster device description specified, " - "using default 'USB-Blaster'"); - low->ublast_device_desc = "USB-Blaster"; - } - -#if IS_WIN32 == 0 - /* Add non-standard Vid/Pid to the linux driver */ - status = FT_SetVIDPID(low->ublast_vid, low->ublast_pid); - if (status != FT_OK) { - LOG_WARNING("couldn't add %4.4x:%4.4x", - low->ublast_vid, low->ublast_pid); - } -#endif - status = FT_OpenEx(low->ublast_device_desc, FT_OPEN_BY_DESCRIPTION, - ftdih); - if (status != FT_OK) { - DWORD num_devices; - - LOG_ERROR("unable to open ftdi device: %s", - ftd2xx_status_string(status)); - status = FT_ListDevices(&num_devices, NULL, FT_LIST_NUMBER_ONLY); - if (status == FT_OK) { - char **desc_array = - malloc(sizeof(char *) * (num_devices + 1)); - unsigned int i; - - for (i = 0; i < num_devices; i++) - desc_array[i] = malloc(64); - desc_array[num_devices] = NULL; - - status = FT_ListDevices(desc_array, &num_devices, - FT_LIST_ALL | FT_OPEN_BY_DESCRIPTION); - - if (status == FT_OK) { - LOG_ERROR("ListDevices: %" PRIu32, (uint32_t)num_devices); - for (i = 0; i < num_devices; i++) - LOG_ERROR("%i: %s", i, desc_array[i]); - } - - for (i = 0; i < num_devices; i++) - free(desc_array[i]); - free(desc_array); - } else { - printf("ListDevices: NONE\n"); - } - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_SetLatencyTimer(*ftdih, 2); - if (status != FT_OK) { - LOG_ERROR("unable to set latency timer: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_INIT_FAILED; - } - - status = FT_GetLatencyTimer(*ftdih, &latency_timer); - if (status != FT_OK) - LOG_ERROR("unable to get latency timer: %s", - ftd2xx_status_string(status)); - else - LOG_DEBUG("current latency timer: %i", latency_timer); - - status = FT_SetBitMode(*ftdih, 0x00, 0); - if (status != FT_OK) { - LOG_ERROR("unable to disable bit i/o mode: %s", - ftd2xx_status_string(status)); - return ERROR_JTAG_INIT_FAILED; - } - return ERROR_OK; -} - -static int ublast_ftd2xx_quit(struct ublast_lowlevel *low) -{ - FT_HANDLE *ftdih = ublast_getftdih(low); - - FT_Close(*ftdih); - return ERROR_OK; -} - -static struct ublast_lowlevel_priv { - FT_HANDLE ftdih; -} info; - -static struct ublast_lowlevel low = { - .open = ublast_ftd2xx_init, - .close = ublast_ftd2xx_quit, - .read = ublast_ftd2xx_read, - .write = ublast_ftd2xx_write, - .priv = &info, -}; - -struct ublast_lowlevel *ublast_register_ftd2xx(void) -{ - return &low; -} diff --git a/src/jtag/drivers/usb_blaster/usb_blaster.c b/src/jtag/drivers/usb_blaster/usb_blaster.c index 8f3f327..a975bd1 100644 --- a/src/jtag/drivers/usb_blaster/usb_blaster.c +++ b/src/jtag/drivers/usb_blaster/usb_blaster.c @@ -147,12 +147,9 @@ struct drvs_map { }; static struct drvs_map lowlevel_drivers_map[] = { -#if BUILD_USB_BLASTER_LIBFTDI +#if BUILD_USB_BLASTER { .name = "ftdi", .drv_register = ublast_register_ftdi }, #endif -#if BUILD_USB_BLASTER_FTD2XX - { .name = "ftd2xx", .drv_register = ublast_register_ftd2xx }, -#endif #if BUILD_USB_BLASTER_2 { .name = "ublast2", .drv_register = ublast2_register_libusb }, #endif @@ -1048,8 +1045,8 @@ static const struct command_registration ublast_command_handlers[] = { .name = "usb_blaster_lowlevel_driver", .handler = ublast_handle_lowlevel_drv_command, .mode = COMMAND_CONFIG, - .help = "set the lowlevel access for the USB Blaster (ftdi, ftd2xx, ublast2)", - .usage = "(ftdi|ftd2xx|ublast2)", + .help = "set the lowlevel access for the USB Blaster (ftdi, ublast2)", + .usage = "(ftdi|ublast2)", }, { .name = "usb_blaster_pin", diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index 1ee29d2..ad656a8 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -54,7 +54,7 @@ extern struct jtag_interface dummy_interface; #if BUILD_FTDI == 1 extern struct jtag_interface ftdi_interface; #endif -#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1 || BUILD_USB_BLASTER_2 == 1 +#if BUILD_USB_BLASTER == 1 || BUILD_USB_BLASTER_2 == 1 extern struct jtag_interface usb_blaster_interface; #endif #if BUILD_JTAG_VPI == 1 @@ -72,7 +72,7 @@ extern struct jtag_interface at91rm9200_interface; #if BUILD_GW16012 == 1 extern struct jtag_interface gw16012_interface; #endif -#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1 +#if BUILD_PRESTO extern struct jtag_interface presto_interface; #endif #if BUILD_USBPROG == 1 @@ -147,7 +147,7 @@ struct jtag_interface *jtag_interfaces[] = { #if BUILD_FTDI == 1 &ftdi_interface, #endif -#if BUILD_USB_BLASTER_LIBFTDI == 1 || BUILD_USB_BLASTER_FTD2XX == 1 || BUILD_USB_BLASTER_2 == 1 +#if BUILD_USB_BLASTER || BUILD_USB_BLASTER_2 == 1 &usb_blaster_interface, #endif #if BUILD_JTAG_VPI == 1 @@ -165,7 +165,7 @@ struct jtag_interface *jtag_interfaces[] = { #if BUILD_GW16012 == 1 &gw16012_interface, #endif -#if BUILD_PRESTO_LIBFTDI == 1 || BUILD_PRESTO_FTD2XX == 1 +#if BUILD_PRESTO &presto_interface, #endif #if BUILD_USBPROG == 1 diff --git a/tcl/board/telo.cfg b/tcl/board/telo.cfg index 126f388..1d3afdf 100644 --- a/tcl/board/telo.cfg +++ b/tcl/board/telo.cfg @@ -8,9 +8,6 @@ source [find target/c100helper.tcl] # Telo board & C100 support trst and srst -# Note that libftd2xx.so tries to assert srst -# which break this script -# use libftdi.so library instead with this script # make the reset asserted to # allow RC circuit to discharge for: [ms] adapter_nsrst_assert_width 100 diff --git a/tcl/interface/usb-jtag.cfg b/tcl/interface/usb-jtag.cfg index 15274d5..cb4d29b 100644 --- a/tcl/interface/usb-jtag.cfg +++ b/tcl/interface/usb-jtag.cfg @@ -27,11 +27,11 @@ # # TODO: Refactor the usb_blaster driver to allow loading firmware using any low # level driver. Loading firmware is currently only supported on the ublast2 -# driver but ixo-usb-jtag requires the ftdi or ftd2xx driver. +# driver but ixo-usb-jtag requires the ftdi driver. interface usb_blaster usb_blaster_vid_pid 0x16C0 0x06AD usb_blaster_device_desc "Van Ooijen Technische Informatica" # ixo-usb-jtag is only compatible with the ublast1 protocol implemented via the -# ftdi or ftd2xx modes, using ublast2 will cause openocd to hang. +# ftdi modes, using ublast2 will cause openocd to hang. usb_blaster_lowlevel_driver ftdi -- cgit v1.1 From 25d7ba19c9e70cf5b912f660cf6aaa93d9ca120f Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Wed, 24 Aug 2016 11:18:41 +0200 Subject: tcl at91samdXX.cfg: update config to current OpenOCD status Remove comment about workaround of not working 'reset halt' - not needed as 'reset halt' is working as expected @ EDBG with srst_only. Add srst_pulls_trst to reset_config as it no more triggers an error. Change-Id: I47cf445690c46ccfb866900cddbfcaefc8649f82 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3722 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- tcl/target/at91samdXX.cfg | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tcl/target/at91samdXX.cfg b/tcl/target/at91samdXX.cfg index 47b4f5f..9a3c292 100644 --- a/tcl/target/at91samdXX.cfg +++ b/tcl/target/at91samdXX.cfg @@ -50,13 +50,7 @@ $_TARGETNAME configure -event reset-deassert-post { } # SRST (wired to RESET_N) resets debug circuitry -# srst_pulls_trst is not configured here to avoid an error raised in reset halt -reset_config srst_gates_jtag - -# Atmel's EDBG (on-board cmsis-dap adapter of Xplained kits) cannot -# stop the MCU before it starts executing code if hardware RESETN -# line is configured by command "reset_config srst_only" -# Use "reset_config none" (default) before flash programming. +reset_config srst_gates_jtag srst_pulls_trst # Do not use a reset button with other SWD adapter than Atmel's EDBG. # DSU usually locks MCU in reset state until you issue a reset command -- cgit v1.1 From 4732471b2e122357403fbcaa53fb712db0d8235e Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 18 Jul 2016 22:59:17 +0200 Subject: flash/nor: at91samd protection bits write fix Flash protection set on a device with MANW=1 was lost after reset. Since #2903 the driver honored MANW bit and issued Write Page command just for main flash write. This change adds similar technique to samd_modify_user_row(). Minor code improvements: samd_check_error() returns error code corresponding to error type instead of bool. samd_check_error() does not clear STATUS register if no error bit is set. Eliminated double error check in call sequence samd_issue_nvmctrl_command() folowed by samd_check_error(). Missing error code ERROR_FLASH_PROTECTED added to src/flash/common.h. Change-Id: Icf59ab8803305d0cb3170c8a5089b8f9828b99f8 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3550 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- src/flash/common.h | 1 + src/flash/nor/at91samd.c | 83 +++++++++++++++++++++++++----------------------- 2 files changed, 44 insertions(+), 40 deletions(-) diff --git a/src/flash/common.h b/src/flash/common.h index ce26fcc..4244f13 100644 --- a/src/flash/common.h +++ b/src/flash/common.h @@ -44,5 +44,6 @@ bool flash_driver_name_matches(const char *name, const char *expected); #define ERROR_FLASH_SECTOR_NOT_ERASED (-906) #define ERROR_FLASH_BANK_NOT_PROBED (-907) #define ERROR_FLASH_OPER_UNSUPPORTED (-908) +#define ERROR_FLASH_PROTECTED (-909) #endif /* OPENOCD_FLASH_COMMON_H */ diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c index cdc43b8..2673b0e 100644 --- a/src/flash/nor/at91samd.c +++ b/src/flash/nor/at91samd.c @@ -423,39 +423,43 @@ static int samd_probe(struct flash_bank *bank) return ERROR_OK; } -static bool samd_check_error(struct target *target) +static int samd_check_error(struct target *target) { - int ret; - bool error; + int ret, ret2; uint16_t status; ret = target_read_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, &status); if (ret != ERROR_OK) { LOG_ERROR("Can't read NVM status"); - return true; + return ret; } - if (status & 0x001C) { - if (status & (1 << 4)) /* NVME */ - LOG_ERROR("SAMD: NVM Error"); - if (status & (1 << 3)) /* LOCKE */ - LOG_ERROR("SAMD: NVM lock error"); - if (status & (1 << 2)) /* PROGE */ - LOG_ERROR("SAMD: NVM programming error"); + if ((status & 0x001C) == 0) + return ERROR_OK; - error = true; - } else { - error = false; + if (status & (1 << 4)) { /* NVME */ + LOG_ERROR("SAMD: NVM Error"); + ret = ERROR_FLASH_OPERATION_FAILED; + } + + if (status & (1 << 3)) { /* LOCKE */ + LOG_ERROR("SAMD: NVM lock error"); + ret = ERROR_FLASH_PROTECTED; + } + + if (status & (1 << 2)) { /* PROGE */ + LOG_ERROR("SAMD: NVM programming error"); + ret = ERROR_FLASH_OPER_UNSUPPORTED; } /* Clear the error conditions by writing a one to them */ - ret = target_write_u16(target, + ret2 = target_write_u16(target, SAMD_NVMCTRL + SAMD_NVMCTRL_STATUS, status); - if (ret != ERROR_OK) + if (ret2 != ERROR_OK) LOG_ERROR("Can't clear NVM error conditions"); - return error; + return ret; } static int samd_issue_nvmctrl_command(struct target *target, uint16_t cmd) @@ -474,10 +478,7 @@ static int samd_issue_nvmctrl_command(struct target *target, uint16_t cmd) return res; /* Check to see if the NVM command resulted in an error condition. */ - if (samd_check_error(target)) - return ERROR_FAIL; - - return ERROR_OK; + return samd_check_error(target); } static int samd_erase_row(struct target *target, uint32_t address) @@ -531,12 +532,19 @@ static int samd_modify_user_row(struct target *target, uint32_t value, uint8_t startb, uint8_t endb) { int res; + uint32_t nvm_ctrlb; + bool manual_wp = true; if (is_user_row_reserved_bit(startb) || is_user_row_reserved_bit(endb)) { LOG_ERROR("Can't modify bits in the requested range"); return ERROR_FAIL; } + /* Check if we need to do manual page write commands */ + res = target_read_u32(target, SAMD_NVMCTRL + SAMD_NVMCTRL_CTRLB, &nvm_ctrlb); + if (res == ERROR_OK) + manual_wp = (nvm_ctrlb & SAMD_NVM_CTRLB_MANW) != 0; + /* Retrieve the MCU's page size, in bytes. This is also the size of the * entire User Row. */ uint32_t page_size; @@ -559,8 +567,8 @@ static int samd_modify_user_row(struct target *target, uint32_t value, if (!buf) return ERROR_FAIL; - /* Read the user row (comprising one page) by half-words. */ - res = target_read_memory(target, SAMD_USER_ROW, 2, page_size / 2, buf); + /* Read the user row (comprising one page) by words. */ + res = target_read_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf); if (res != ERROR_OK) goto out_user_row; @@ -579,20 +587,18 @@ static int samd_modify_user_row(struct target *target, uint32_t value, /* Modify */ buf_set_u32(buf, startb, endb - startb + 1, value); - /* Write the page buffer back out to the target. A Flash write will be - * triggered automatically. */ + /* Write the page buffer back out to the target. */ res = target_write_memory(target, SAMD_USER_ROW, 4, page_size / 4, buf); if (res != ERROR_OK) goto out_user_row; - if (samd_check_error(target)) { - res = ERROR_FAIL; - goto out_user_row; + if (manual_wp) { + /* Trigger flash write */ + res = samd_issue_nvmctrl_command(target, SAMD_NVM_CMD_WAP); + } else { + res = samd_check_error(target); } - /* Success */ - res = ERROR_OK; - out_user_row: free(buf); @@ -784,18 +790,15 @@ static int samd_write(struct flash_bank *bank, const uint8_t *buffer, * then issue CMD_WP always */ if (manual_wp || pg_offset + 4 * nw < chip->page_size) { res = samd_issue_nvmctrl_command(bank->target, SAMD_NVM_CMD_WP); - if (res != ERROR_OK) { - LOG_ERROR("%s: %d", __func__, __LINE__); - goto free_pb; - } - } + } else { + /* Access through AHB is stalled while flash is being programmed */ + usleep(200); - /* Access through AHB is stalled while flash is being programmed */ - usleep(200); + res = samd_check_error(bank->target); + } - if (samd_check_error(bank->target)) { + if (res != ERROR_OK) { LOG_ERROR("%s: write failed at address 0x%08" PRIx32, __func__, address); - res = ERROR_FAIL; goto free_pb; } -- cgit v1.1 From ab9d92490cf37fb4cbb394f85d7c8385474dff3f Mon Sep 17 00:00:00 2001 From: Peter Lawrence Date: Fri, 27 Nov 2015 17:28:16 -0600 Subject: tcl: Support for Analog Devices ADSP-SC58x target tcl to enable debugging of ARM Cortex-A5 on ADSP-SC58x Change-Id: I378f8b94b7d6d6b9d0567985abc0e36aea7c8dea Signed-off-by: Peter Lawrence Reviewed-on: http://openocd.zylin.com/3125 Tested-by: jenkins Reviewed-by: Spencer Oliver Reviewed-by: Andreas Fritiofson Reviewed-by: Matthias Welwarsky --- tcl/target/adsp-sc58x.cfg | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 tcl/target/adsp-sc58x.cfg diff --git a/tcl/target/adsp-sc58x.cfg b/tcl/target/adsp-sc58x.cfg new file mode 100644 index 0000000..369137e --- /dev/null +++ b/tcl/target/adsp-sc58x.cfg @@ -0,0 +1,45 @@ +# Analog Devices ADSP-SC58x (ARM Cortex-A5 plus one or two SHARC+ DSPs) + +# evaluation boards by Analog Devices (and designs derived from them) use a non-standard 10-pin 0.05" ARM Cortex Debug Connector +# pin 9 (GND or GNDDetect) has been usurped with JTAG /TRST +# as a result, a standards-compliant debug pod will only force the processor's debug interface into reset, preventing usage +# so, a connector adapter must be employed on these boards to isolate or otherwise prevent /TRST from being asserted + +transport select swd +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME ADSP-SC58x +} + +if { [info exists ENDIAN] } { + set _ENDIAN $ENDIAN +} else { + set _ENDIAN little +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x3BA02477 +} + +swj_newdap $_CHIPNAME cpu -expected-id $_CPUTAPID + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_a -endian $_ENDIAN -chain-position $_TARGETNAME + +$_TARGETNAME configure -event examine-end { + global _TARGETNAME + sc58x_enabledebug $_TARGETNAME +} + +proc sc58x_enabledebug {target} { + # Enable debugging functionality by setting relevant bits in the TAPC_DBGCTL register + # the "phys" option is critical; the OpenOCD Cortex-A target code prevents normal mww when the target is not halted + # however, it is not possible to halt the target unless these register bits have been set + $target mww phys 0x31131000 0xFFFF +} + -- cgit v1.1 From 53a936afc0092f4a65975d35bab0e10944fad3db Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 11 Nov 2016 14:39:09 +0100 Subject: Add -defer-examine option to target create command The '-defer-examine' option to target create allows declaring targets that are present on the chain, but not fully functional. They will be skipped by the initial arp_examine as well as arp_examine after reset. Manual examine using 'arp_examine' is needed to examine them, with the idea that some kind of actions is neeed to bring them to a state where examine will succeed (if at all possible). In order to allow value less options to target command, I had to relax the goi.argc check in jim_target_configure(). Change-Id: I9bf4e8d27eb6476dd9353d15f48965a8cfd5c122 Signed-off-by: Esben Haabendal Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3076 Tested-by: jenkins Reviewed-by: Tomas Vanek --- doc/openocd.texi | 6 +++- src/rtos/rtos.c | 5 ++- src/target/startup.tcl | 14 ++++++++- src/target/target.c | 84 +++++++++++++++++++++++++++++++++++++++++++++----- src/target/target.h | 3 ++ 5 files changed, 102 insertions(+), 10 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 0fef9fb..4ce6187 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4126,6 +4126,10 @@ The value should normally correspond to a static mapping for the @option{FreeRTOS}|@option{linux}|@option{ChibiOS}|@option{embKernel}|@option{mqx} @xref{gdbrtossupport,,RTOS Support}. +@item @code{-defer-examine} -- skip target examination at initial JTAG chain +scan and after a reset. A manual call to arp_examine is required to +access the target for debugging. + @end itemize @end deffn @@ -4162,7 +4166,7 @@ omap3530.cpu mww 0x5555 123 The commands supported by OpenOCD target objects are: -@deffn Command {$target_name arp_examine} +@deffn Command {$target_name arp_examine} @option{allow-defer} @deffnx Command {$target_name arp_halt} @deffnx Command {$target_name arp_poll} @deffnx Command {$target_name arp_reset} diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 448c49c..aa8efbe 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -104,6 +104,7 @@ int rtos_create(Jim_GetOptInfo *goi, struct target *target) int x; const char *cp; struct Jim_Obj *res; + int e; if (!goi->isconfigure && goi->argc != 0) { Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS"); @@ -112,7 +113,9 @@ int rtos_create(Jim_GetOptInfo *goi, struct target *target) os_free(target); - Jim_GetOpt_String(goi, &cp, NULL); + e = Jim_GetOpt_String(goi, &cp, NULL); + if (e != JIM_OK) + return e; if (0 == strcmp(cp, "auto")) { /* Auto detect tries to look up all symbols for each RTOS, diff --git a/src/target/startup.tcl b/src/target/startup.tcl index cf2813b..9bbc6e3 100644 --- a/src/target/startup.tcl +++ b/src/target/startup.tcl @@ -65,7 +65,7 @@ proc ocd_process_reset_inner { MODE } { foreach t $targets { if {![using_jtag] || [jtag tapisenabled [$t cget -chain-position]]} { $t invoke-event examine-start - set err [catch "$t arp_examine"] + set err [catch "$t arp_examine allow-defer"] if { $err == 0 } { $t invoke-event examine-end } @@ -111,6 +111,12 @@ proc ocd_process_reset_inner { MODE } { continue } + # don't wait for targets where examination is deferred + # they can not be halted anyway at this point + if { ![$t was_examined] && [$t examine_deferred] } { + continue + } + # Wait upto 1 second for target to halt. Why 1sec? Cause # the JTAG tap reset signal might be hooked to a slow # resistor/capacitor circuit - and it might take a while @@ -135,6 +141,12 @@ proc ocd_process_reset_inner { MODE } { continue } + # don't wait for targets where examination is deferred + # they can not be halted anyway at this point + if { ![$t was_examined] && [$t examine_deferred] } { + continue + } + set err [catch "$t arp_waitstate halted 5000"] # Did it halt? if { $err == 0 } { diff --git a/src/target/target.c b/src/target/target.c index c23590e..4c5ddd3 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -283,6 +283,10 @@ const char *target_state_name(struct target *t) LOG_ERROR("Invalid target state: %d", (int)(t->state)); cp = "(*BUG*unknown*BUG*)"; } + + if (!target_was_examined(t) && t->defer_examine) + cp = "examine deferred"; + return cp; } @@ -731,6 +735,9 @@ int target_examine(void) continue; } + if (target->defer_examine) + continue; + retval = target_examine_one(target); if (retval != ERROR_OK) return retval; @@ -4325,6 +4332,7 @@ enum target_cfg_param { TCFG_CHAIN_POSITION, TCFG_DBGBASE, TCFG_RTOS, + TCFG_DEFER_EXAMINE, }; static Jim_Nvp nvp_config_opts[] = { @@ -4339,6 +4347,7 @@ static Jim_Nvp nvp_config_opts[] = { { .name = "-chain-position", .value = TCFG_CHAIN_POSITION }, { .name = "-dbgbase", .value = TCFG_DBGBASE }, { .name = "-rtos", .value = TCFG_RTOS }, + { .name = "-defer-examine", .value = TCFG_DEFER_EXAMINE }, { .name = NULL, .value = -1 } }; @@ -4613,6 +4622,13 @@ no_params: } /* loop for more */ break; + + case TCFG_DEFER_EXAMINE: + /* DEFER_EXAMINE */ + target->defer_examine = true; + /* loop for more */ + break; + } } /* while (goi->argc) */ @@ -4627,12 +4643,9 @@ static int jim_target_configure(Jim_Interp *interp, int argc, Jim_Obj * const *a Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); goi.isconfigure = !strcmp(Jim_GetString(argv[0], NULL), "configure"); - int need_args = 1 + goi.isconfigure; - if (goi.argc < need_args) { + if (goi.argc < 1) { Jim_WrongNumArgs(goi.interp, goi.argc, goi.argv, - goi.isconfigure - ? "missing: -option VALUE ..." - : "missing: -option ..."); + "missing: -option ..."); return JIM_ERR; } struct target *target = Jim_CmdPrivData(goi.interp); @@ -4883,20 +4896,58 @@ static int jim_target_tap_disabled(Jim_Interp *interp) static int jim_target_examine(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { - if (argc != 1) { - Jim_WrongNumArgs(interp, 1, argv, "[no parameters]"); + bool allow_defer = false; + + Jim_GetOptInfo goi; + Jim_GetOpt_Setup(&goi, interp, argc - 1, argv + 1); + if (goi.argc > 1) { + const char *cmd_name = Jim_GetString(argv[0], NULL); + Jim_SetResultFormatted(goi.interp, + "usage: %s ['allow-defer']", cmd_name); return JIM_ERR; } + if (goi.argc > 0 && + strcmp(Jim_GetString(argv[1], NULL), "allow-defer") == 0) { + /* consume it */ + struct Jim_Obj *obj; + int e = Jim_GetOpt_Obj(&goi, &obj); + if (e != JIM_OK) + return e; + allow_defer = true; + } + struct target *target = Jim_CmdPrivData(interp); if (!target->tap->enabled) return jim_target_tap_disabled(interp); + if (allow_defer && target->defer_examine) { + LOG_INFO("Deferring arp_examine of %s", target_name(target)); + LOG_INFO("Use arp_examine command to examine it manually!"); + return JIM_OK; + } + int e = target->type->examine(target); if (e != ERROR_OK) return JIM_ERR; return JIM_OK; } +static int jim_target_was_examined(Jim_Interp *interp, int argc, Jim_Obj * const *argv) +{ + struct target *target = Jim_CmdPrivData(interp); + + Jim_SetResultBool(interp, target_was_examined(target)); + return JIM_OK; +} + +static int jim_target_examine_deferred(Jim_Interp *interp, int argc, Jim_Obj * const *argv) +{ + struct target *target = Jim_CmdPrivData(interp); + + Jim_SetResultBool(interp, target->defer_examine); + return JIM_OK; +} + static int jim_target_halt_gdb(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { if (argc != 1) { @@ -4964,6 +5015,10 @@ static int jim_target_reset(Jim_Interp *interp, int argc, Jim_Obj *const *argv) target_name(target)); return JIM_ERR; } + + if (target->defer_examine) + target_reset_examined(target); + /* determine if we should halt or not. */ target->reset_halt = !!a; /* When this happens - all workareas are invalid. */ @@ -5174,6 +5229,21 @@ static const struct command_registration target_instance_command_handlers[] = { .mode = COMMAND_EXEC, .jim_handler = jim_target_examine, .help = "used internally for reset processing", + .usage = "arp_examine ['allow-defer']", + }, + { + .name = "was_examined", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_was_examined, + .help = "used internally for reset processing", + .usage = "was_examined", + }, + { + .name = "examine_deferred", + .mode = COMMAND_EXEC, + .jim_handler = jim_target_examine_deferred, + .help = "used internally for reset processing", + .usage = "examine_deferred", }, { .name = "arp_halt_gdb", diff --git a/src/target/target.h b/src/target/target.h index 8f6a7d9..7f6ac14 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -130,6 +130,9 @@ struct target { struct jtag_tap *tap; /* where on the jtag chain is this */ int32_t coreid; /* which device on the TAP? */ + /** Should we defer examine to later */ + bool defer_examine; + /** * Indicates whether this target has been examined. * -- cgit v1.1 From 0a2f1b29e678c97c7981090f769e841cbd583442 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Wed, 23 Nov 2016 10:15:50 +0100 Subject: cortex_a: remove partnum magic from arp_examine and dbginit Depending on the Debug implementation the "OS Lock" feature might be implemented or not. It is not actually depending on the part number of the implemented ARM core but on the DBGOSLSR.OSLM bits. This patch removes querying the part number and implements proper parsing of OSLM. Result is a more generic approach that will work out-of-box on more devices. Change-Id: I79e052869c2f9af1d7fdedef42faddb7292e7332 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3213 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/arm_dpm.h | 21 +++++++ src/target/cortex_a.c | 166 ++++++++++++++------------------------------------ src/target/cortex_a.h | 2 - 3 files changed, 68 insertions(+), 121 deletions(-) diff --git a/src/target/arm_dpm.h b/src/target/arm_dpm.h index fa87baf..bbcae78 100644 --- a/src/target/arm_dpm.h +++ b/src/target/arm_dpm.h @@ -198,4 +198,25 @@ void arm_dpm_report_wfar(struct arm_dpm *, uint32_t wfar); void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dcsr); +/* PRCR (Device Power-down and Reset Control Register) bits */ +#define PRCR_DEBUG_NO_POWER_DOWN (1 << 0) +#define PRCR_WARM_RESET (1 << 1) +#define PRCR_HOLD_NON_DEBUG_RESET (1 << 2) + +/* PRSR (Device Power-down and Reset Status Register) bits */ +#define PRSR_POWERUP_STATUS (1 << 0) +#define PRSR_STICKY_POWERDOWN_STATUS (1 << 1) +#define PRSR_RESET_STATUS (1 << 2) +#define PRSR_STICKY_RESET_STATUS (1 << 3) +#define PRSR_HALTED (1 << 4) /* v7.1 Debug only */ +#define PRSR_OSLK (1 << 5) /* v7.1 Debug only */ +#define PRSR_DLK (1 << 6) /* v7.1 Debug only */ + +/* OSLSR (OS Lock Status Register) bits */ +#define OSLSR_OSLM0 (1 << 0) +#define OSLSR_OSLK (1 << 1) +#define OSLSR_nTT (1 << 2) +#define OSLSR_OSLM1 (1 << 3) +#define OSLSR_OSLM (OSLSR_OSLM0|OSLSR_OSLM1) + #endif /* OPENOCD_TARGET_ARM_DPM_H */ diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 256edbc..1f51c4e 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -198,77 +198,15 @@ static int cortex_a_mmu_modify(struct target *target, int enable) /* * Cortex-A Basic debug access, very low level assumes state is saved */ -static int cortex_a8_init_debug_access(struct target *target) -{ - struct armv7a_common *armv7a = target_to_armv7a(target); - int retval; - - LOG_DEBUG(" "); - - /* Unlocking the debug registers for modification - * The debugport might be uninitialised so try twice */ - retval = mem_ap_write_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55); - if (retval != ERROR_OK) { - /* try again */ - retval = mem_ap_write_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55); - if (retval == ERROR_OK) - LOG_USER( - "Locking debug access failed on first, but succeeded on second try."); - } - - return retval; -} - -/* - * Cortex-A Basic debug access, very low level assumes state is saved - */ static int cortex_a_init_debug_access(struct target *target) { struct armv7a_common *armv7a = target_to_armv7a(target); int retval; - uint32_t dbg_osreg; - uint32_t cortex_part_num; - struct cortex_a_common *cortex_a = target_to_cortex_a(target); - - LOG_DEBUG(" "); - cortex_part_num = (cortex_a->cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> - CORTEX_A_MIDR_PARTNUM_SHIFT; - - switch (cortex_part_num) { - case CORTEX_A7_PARTNUM: - case CORTEX_A15_PARTNUM: - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_OSLSR, - &dbg_osreg); - if (retval != ERROR_OK) - return retval; - - LOG_DEBUG("DBGOSLSR 0x%" PRIx32, dbg_osreg); - - if (dbg_osreg & CPUDBG_OSLAR_LK_MASK) - /* Unlocking the DEBUG OS registers for modification */ - retval = mem_ap_write_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_OSLAR, - 0); - break; - - case CORTEX_A5_PARTNUM: - case CORTEX_A8_PARTNUM: - case CORTEX_A9_PARTNUM: - default: - retval = cortex_a8_init_debug_access(target); - } - - if (retval != ERROR_OK) - return retval; - /* Clear Sticky Power Down status Bit in PRSR to enable access to - the registers in the Core Power Domain */ - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg); - LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg); + /* lock memory-mapped access to debug registers to prevent + * software interference */ + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_LOCKACCESS, 0); if (retval != ERROR_OK) return retval; @@ -2981,7 +2919,7 @@ static int cortex_a_examine_first(struct target *target) int i; int retval = ERROR_OK; - uint32_t didr, ctypr, ttypr, cpuid, dbg_osreg; + uint32_t didr, cpuid, dbg_osreg; retval = dap_dp_init(swjdp); if (retval != ERROR_OK) { @@ -3043,79 +2981,69 @@ static int cortex_a_examine_first(struct target *target) armv7a->debug_base = target->dbgbase; retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_CPUID, &cpuid); - if (retval != ERROR_OK) - return retval; - - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_CPUID, &cpuid); - if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "CPUID"); - return retval; - } - - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_CTYPR, &ctypr); - if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "CTYPR"); - return retval; - } - - retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_TTYPR, &ttypr); + armv7a->debug_base + CPUDBG_DIDR, &didr); if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "TTYPR"); + LOG_DEBUG("Examine %s failed", "DIDR"); return retval; } retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_DIDR, &didr); + armv7a->debug_base + CPUDBG_CPUID, &cpuid); if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "DIDR"); + LOG_DEBUG("Examine %s failed", "CPUID"); return retval; } - LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid); - LOG_DEBUG("ctypr = 0x%08" PRIx32, ctypr); - LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr); LOG_DEBUG("didr = 0x%08" PRIx32, didr); + LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid); - cortex_a->cpuid = cpuid; - cortex_a->ctypr = ctypr; - cortex_a->ttypr = ttypr; cortex_a->didr = didr; + cortex_a->cpuid = cpuid; - /* Unlocking the debug registers */ - if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT == - CORTEX_A15_PARTNUM) { - - retval = mem_ap_write_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_OSLAR, - 0); - - if (retval != ERROR_OK) - return retval; + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg); + if ((dbg_osreg & PRSR_POWERUP_STATUS) == 0) { + LOG_ERROR("target->coreid %" PRId32 " powered down!", target->coreid); + target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */ + return ERROR_TARGET_INIT_FAILED; } - /* Unlocking the debug registers */ - if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT == - CORTEX_A7_PARTNUM) { - retval = mem_ap_write_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_OSLAR, - 0); + if (dbg_osreg & PRSR_STICKY_RESET_STATUS) + LOG_DEBUG("target->coreid %" PRId32 " was reset!", target->coreid); - if (retval != ERROR_OK) - return retval; - - } + /* Read DBGOSLSR and check if OSLK is implemented */ retval = mem_ap_read_atomic_u32(armv7a->debug_ap, - armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg); - + armv7a->debug_base + CPUDBG_OSLSR, &dbg_osreg); if (retval != ERROR_OK) return retval; + LOG_DEBUG("target->coreid %" PRId32 " DBGOSLSR 0x%" PRIx32, target->coreid, dbg_osreg); - LOG_DEBUG("target->coreid %" PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg); + /* check if OS Lock is implemented */ + if ((dbg_osreg & OSLSR_OSLM) == OSLSR_OSLM0 || (dbg_osreg & OSLSR_OSLM) == OSLSR_OSLM1) { + /* check if OS Lock is set */ + if (dbg_osreg & OSLSR_OSLK) { + LOG_DEBUG("target->coreid %" PRId32 " OSLock set! Trying to unlock", target->coreid); + + retval = mem_ap_write_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_OSLAR, + 0); + if (retval == ERROR_OK) + retval = mem_ap_read_atomic_u32(armv7a->debug_ap, + armv7a->debug_base + CPUDBG_OSLSR, &dbg_osreg); + + /* if we fail to access the register or cannot reset the OSLK bit, bail out */ + if (retval != ERROR_OK || (dbg_osreg & OSLSR_OSLK) != 0) { + LOG_ERROR("target->coreid %" PRId32 " OSLock sticky, core not powered?", + target->coreid); + target->state = TARGET_UNKNOWN; /* TARGET_NO_POWER? */ + return ERROR_TARGET_INIT_FAILED; + } + } + } armv7a->arm.core_type = ARM_MODE_MON; diff --git a/src/target/cortex_a.h b/src/target/cortex_a.h index ea08c67..ff03432 100644 --- a/src/target/cortex_a.h +++ b/src/target/cortex_a.h @@ -97,8 +97,6 @@ struct cortex_a_common { int fast_reg_read; uint32_t cpuid; - uint32_t ctypr; - uint32_t ttypr; uint32_t didr; enum cortex_a_isrmasking_mode isrmasking_mode; -- cgit v1.1 From cac446ca6bb9566f06f705beb168eb5c49bee27e Mon Sep 17 00:00:00 2001 From: Jiri Kastner Date: Fri, 11 Nov 2016 10:50:13 +0100 Subject: dap_dp_init: remove loop current loop sounds to me like 'we don't know what we do, let's do it ten times, maybe we will have luck'. should be enough to 'ping' debug port using reading CRTL_STAT. tested on cortex-a8, snapdragon, jetson k1, cortex-r5, cortex-r4 Change-Id: Ibc62ac1eca06c141f4fccd5de7b11350ca1f35fd Signed-off-by: Jiri Kastner Tested-by: Jiri Kastner Reviewed-on: http://openocd.zylin.com/3193 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Liviu Dudau Reviewed-by: Paul Fertser --- src/target/arm_adi_v5.c | 86 ++++++++++++++++++++++++------------------------- 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index f58afdc..39f2b39 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -612,60 +612,58 @@ int dap_dp_init(struct adiv5_dap *dap) dap->select = DP_SELECT_INVALID; dap->last_read = NULL; - for (size_t i = 0; i < 10; i++) { + for (size_t i = 0; i < 30; i++) { /* DP initialization */ - retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); - if (retval != ERROR_OK) - continue; - - retval = dap_queue_dp_write(dap, DP_CTRL_STAT, SSTICKYERR); - if (retval != ERROR_OK) - continue; + retval = dap_dp_read_atomic(dap, DP_CTRL_STAT, NULL); + if (retval == ERROR_OK) + break; + } - retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); - if (retval != ERROR_OK) - continue; + retval = dap_queue_dp_write(dap, DP_CTRL_STAT, SSTICKYERR); + if (retval != ERROR_OK) + return retval; - dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; - retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat); - if (retval != ERROR_OK) - continue; + retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); + if (retval != ERROR_OK) + return retval; - /* Check that we have debug power domains activated */ - LOG_DEBUG("DAP: wait CDBGPWRUPACK"); - retval = dap_dp_poll_register(dap, DP_CTRL_STAT, - CDBGPWRUPACK, CDBGPWRUPACK, - DAP_POWER_DOMAIN_TIMEOUT); - if (retval != ERROR_OK) - continue; + dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ; + retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat); + if (retval != ERROR_OK) + return retval; - LOG_DEBUG("DAP: wait CSYSPWRUPACK"); - retval = dap_dp_poll_register(dap, DP_CTRL_STAT, - CSYSPWRUPACK, CSYSPWRUPACK, - DAP_POWER_DOMAIN_TIMEOUT); - if (retval != ERROR_OK) - continue; + /* Check that we have debug power domains activated */ + LOG_DEBUG("DAP: wait CDBGPWRUPACK"); + retval = dap_dp_poll_register(dap, DP_CTRL_STAT, + CDBGPWRUPACK, CDBGPWRUPACK, + DAP_POWER_DOMAIN_TIMEOUT); + if (retval != ERROR_OK) + return retval; - retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); - if (retval != ERROR_OK) - continue; + LOG_DEBUG("DAP: wait CSYSPWRUPACK"); + retval = dap_dp_poll_register(dap, DP_CTRL_STAT, + CSYSPWRUPACK, CSYSPWRUPACK, + DAP_POWER_DOMAIN_TIMEOUT); + if (retval != ERROR_OK) + return retval; - /* With debug power on we can activate OVERRUN checking */ - dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT; - retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat); - if (retval != ERROR_OK) - continue; - retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); - if (retval != ERROR_OK) - continue; + retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); + if (retval != ERROR_OK) + return retval; - retval = dap_run(dap); - if (retval != ERROR_OK) - continue; + /* With debug power on we can activate OVERRUN checking */ + dap->dp_ctrl_stat = CDBGPWRUPREQ | CSYSPWRUPREQ | CORUNDETECT; + retval = dap_queue_dp_write(dap, DP_CTRL_STAT, dap->dp_ctrl_stat); + if (retval != ERROR_OK) + return retval; + retval = dap_queue_dp_read(dap, DP_CTRL_STAT, NULL); + if (retval != ERROR_OK) + return retval; - break; - } + retval = dap_run(dap); + if (retval != ERROR_OK) + return retval; return retval; } -- cgit v1.1 From b9417ea19c93442679b352a415e5542a573cd08d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 11 Nov 2016 01:15:56 +0100 Subject: xmc4xxx: Add support for XMC4300 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit XMC4300 can reuse the existing XMC4700/XMC4800 sectors support. Add support for XMC4300 AA to the info command. Change-Id: Id929a51d20c73bd869a4457ffedc48ad5fa3f2df Signed-off-by: Andreas Färber Reviewed-on: http://openocd.zylin.com/3875 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/flash/nor/xmc4xxx.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/flash/nor/xmc4xxx.c b/src/flash/nor/xmc4xxx.c index b761951..02df46a 100644 --- a/src/flash/nor/xmc4xxx.c +++ b/src/flash/nor/xmc4xxx.c @@ -183,7 +183,7 @@ /* Flash controller configuration values */ #define FLASH_ID_XMC4500 0xA2 -#define FLASH_ID_XMC4700_4800 0x92 +#define FLASH_ID_XMC4300_XMC4700_4800 0x92 #define FLASH_ID_XMC4100_4200 0x9C #define FLASH_ID_XMC4400 0x9F @@ -383,7 +383,7 @@ static int xmc4xxx_probe(struct flash_bank *bank) bank->num_sectors = 12; LOG_DEBUG("XMC4xxx: XMC4500 detected."); break; - case FLASH_ID_XMC4700_4800: + case FLASH_ID_XMC4300_XMC4700_4800: bank->num_sectors = 16; LOG_DEBUG("XMC4xxx: XMC4700/4800 detected."); break; @@ -851,6 +851,14 @@ static int xmc4xxx_get_info_command(struct flash_bank *bank, char *buf, int buf_ break; } break; + case 0x300: + dev_str = "XMC4300"; + + switch (rev_id) { + case 0x1: + rev_str = "AA"; + } + break; case 0x400: dev_str = "XMC4400"; -- cgit v1.1 From 420c15de6c3e423d2e1cb717f2210d0d13be9578 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20F=C3=A4rber?= Date: Fri, 11 Nov 2016 01:42:48 +0100 Subject: tcl/board: Add Infineon XMC4300 Relax EtherCAT Kit config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Tested with "J-Link Lite-XMC4200 Rev.1 compiled Jul 18 2014 17:28:26". Change-Id: I31482734af7621593a244ffac9dd223408470609 Signed-off-by: Andreas Färber Reviewed-on: http://openocd.zylin.com/3876 Tested-by: jenkins Reviewed-by: Paul Fertser --- tcl/board/xmc4300-relax.cfg | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 tcl/board/xmc4300-relax.cfg diff --git a/tcl/board/xmc4300-relax.cfg b/tcl/board/xmc4300-relax.cfg new file mode 100644 index 0000000..bb46ccf --- /dev/null +++ b/tcl/board/xmc4300-relax.cfg @@ -0,0 +1,12 @@ +# +# Infineon XMC4300 Relax EtherCAT Kit +# + +# +# Segger J-Link Lite XMC4200 on-board +# +source [find interface/jlink.cfg] +transport select swd + +set CHIPNAME xmc4300 +source [find target/xmc4xxx.cfg] -- cgit v1.1 From 29964c79846ea419e113dc90c0d74f1a7e16e70a Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 10 Nov 2016 20:53:26 +0100 Subject: target: Add verify_image_checksum command This avoids the secondary binary search if the checksum is different Change-Id: I986ba7687cea76f30e37a6bca58aabde18198263 Signed-off-by: Evan Hunter Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/2869 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Paul Fertser --- doc/openocd.texi | 7 +++++++ src/target/target.c | 32 +++++++++++++++++++++++++++----- 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 4ce6187..497a20b 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -6984,6 +6984,13 @@ The file format may optionally be specified This will first attempt a comparison using a CRC checksum, if this fails it will try a binary compare. @end deffn +@deffn Command {verify_image_checksum} filename address [@option{bin}|@option{ihex}|@option{elf}] +Verify @var{filename} against target memory starting at @var{address}. +The file format may optionally be specified +(@option{bin}, @option{ihex}, or @option{elf}) +This perform a comparison using a CRC checksum only +@end deffn + @section Breakpoint and Watchpoint commands @cindex breakpoint diff --git a/src/target/target.c b/src/target/target.c index 4c5ddd3..26bae4b 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -3299,7 +3299,13 @@ COMMAND_HANDLER(handle_dump_image_command) return retval; } -static COMMAND_HELPER(handle_verify_image_command_internal, int verify) +enum verify_mode { + IMAGE_TEST = 0, + IMAGE_VERIFY = 1, + IMAGE_CHECKSUM_ONLY = 2 +}; + +static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode verify) { uint8_t *buffer; size_t buf_cnt; @@ -3357,7 +3363,7 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) break; } - if (verify) { + if (verify >= IMAGE_VERIFY) { /* calculate checksum of image */ retval = image_calculate_checksum(buffer, buf_cnt, &checksum); if (retval != ERROR_OK) { @@ -3370,7 +3376,12 @@ static COMMAND_HELPER(handle_verify_image_command_internal, int verify) free(buffer); break; } - + if ((checksum != mem_checksum) && (verify == IMAGE_CHECKSUM_ONLY)) { + LOG_ERROR("checksum mismatch"); + free(buffer); + retval = ERROR_FAIL; + goto done; + } if (checksum != mem_checksum) { /* failed crc checksum, fall back to a binary compare */ uint8_t *data; @@ -3435,14 +3446,19 @@ done: return retval; } +COMMAND_HANDLER(handle_verify_image_checksum_command) +{ + return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_CHECKSUM_ONLY); +} + COMMAND_HANDLER(handle_verify_image_command) { - return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 1); + return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_VERIFY); } COMMAND_HANDLER(handle_test_image_command) { - return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, 0); + return CALL_COMMAND_HANDLER(handle_verify_image_command_internal, IMAGE_TEST); } static int handle_bp_command_list(struct command_context *cmd_ctx) @@ -6219,6 +6235,12 @@ static const struct command_registration target_exec_command_handlers[] = { .usage = "filename address size", }, { + .name = "verify_image_checksum", + .handler = handle_verify_image_checksum_command, + .mode = COMMAND_EXEC, + .usage = "filename [offset [type]]", + }, + { .name = "verify_image", .handler = handle_verify_image_command, .mode = COMMAND_EXEC, -- cgit v1.1 From 1eae39b40d5338e96194ad3c83949718a857a2a2 Mon Sep 17 00:00:00 2001 From: Steven Stallion Date: Fri, 15 Jul 2016 22:01:00 -0500 Subject: rtos: add support for uC/OS-III This patch introduces RTOS support for uC/OS-III. Currently, only FPU-less ARM Cortex-M targets are supported. Due to the configurability of the RTOS, an OpenOCD-specific file must be linked along with the project to determine the correct offsets within the OS_TCB structure. In addition to the above, a crash was fixed in rtos_get_gdb_reg_list such that RTOS support could be used between resets without restarting OpenOCD and support for the Hg packet was cleaned up. Change-Id: Ide004a689e6b886185df665c00fb644629eb31d1 Signed-off-by: Steven Stallion Reviewed-on: http://openocd.zylin.com/3556 Tested-by: jenkins Reviewed-by: Paul Fertser --- contrib/rtos-helpers/uCOS-III-openocd.c | 32 ++ doc/openocd.texi | 10 +- src/rtos/Makefile.am | 4 +- src/rtos/rtos.c | 25 +- src/rtos/rtos_ucos_iii_stackings.c | 53 ++++ src/rtos/rtos_ucos_iii_stackings.h | 30 ++ src/rtos/uCOS-III.c | 509 ++++++++++++++++++++++++++++++++ 7 files changed, 653 insertions(+), 10 deletions(-) create mode 100644 contrib/rtos-helpers/uCOS-III-openocd.c create mode 100644 src/rtos/rtos_ucos_iii_stackings.c create mode 100644 src/rtos/rtos_ucos_iii_stackings.h create mode 100644 src/rtos/uCOS-III.c diff --git a/contrib/rtos-helpers/uCOS-III-openocd.c b/contrib/rtos-helpers/uCOS-III-openocd.c new file mode 100644 index 0000000..9037334 --- /dev/null +++ b/contrib/rtos-helpers/uCOS-III-openocd.c @@ -0,0 +1,32 @@ +/* + * uC/OS-III does not provide a fixed layout for OS_TCB, which makes it + * impossible to determine the appropriate offsets within the structure + * unaided. A priori knowledge of offsets based on os_dbg.c is tied to a + * specific release and thusly, brittle. The constants defined below + * provide the neccessary information OpenOCD needs to provide support + * in the most robust manner possible. + * + * This file should be linked along with the project to enable RTOS + * support for uC/OS-III. + */ + +#include + +#if OS_CFG_DBG_EN == 0 +#error "OS_CFG_DBG_EN is required to enable RTOS support for OpenOCD" +#endif + +#define OFFSET_OF(type, member) ((CPU_SIZE_T)&(((type *)0)->member)) + +#ifdef __GNUC__ +#define USED __attribute__((used)) +#else +#define USED +#endif + +const CPU_SIZE_T USED openocd_OS_TCB_StkPtr_offset = OFFSET_OF(OS_TCB, StkPtr); +const CPU_SIZE_T USED openocd_OS_TCB_NamePtr_offset = OFFSET_OF(OS_TCB, NamePtr); +const CPU_SIZE_T USED openocd_OS_TCB_TaskState_offset = OFFSET_OF(OS_TCB, TaskState); +const CPU_SIZE_T USED openocd_OS_TCB_Prio_offset = OFFSET_OF(OS_TCB, Prio); +const CPU_SIZE_T USED openocd_OS_TCB_DbgPrevPtr_offset = OFFSET_OF(OS_TCB, DbgPrevPtr); +const CPU_SIZE_T USED openocd_OS_TCB_DbgNextPtr_offset = OFFSET_OF(OS_TCB, DbgNextPtr); diff --git a/doc/openocd.texi b/doc/openocd.texi index 497a20b..372683a 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4123,7 +4123,8 @@ The value should normally correspond to a static mapping for the @anchor{rtostype} @item @code{-rtos} @var{rtos_type} -- enable rtos support for target, @var{rtos_type} can be one of @option{auto}|@option{eCos}|@option{ThreadX}| -@option{FreeRTOS}|@option{linux}|@option{ChibiOS}|@option{embKernel}|@option{mqx} +@option{FreeRTOS}|@option{linux}|@option{ChibiOS}|@option{embKernel}|@option{mqx}| +@option{uCOS-III} @xref{gdbrtossupport,,RTOS Support}. @item @code{-defer-examine} -- skip target examination at initial JTAG chain @@ -8833,6 +8834,7 @@ Currently supported rtos's include: @item @option{ChibiOS} @item @option{embKernel} @item @option{mqx} +@item @option{uCOS-III} @end itemize @quotation Note @@ -8866,10 +8868,12 @@ Rtos::sCurrentTask, Rtos::sListReady, Rtos::sListSleep, Rtos::sListSuspended, Rtos::sMaxPriorities, Rtos::sCurrentTaskCount. @item mqx symbols _mqx_kernel_data, MQX_init_struct. +@item uC/OS-III symbols +OSRunning, OSTCBCurPtr, OSTaskDbgListPtr, OSTaskQty @end table For most RTOS supported the above symbols will be exported by default. However for -some, eg. FreeRTOS, extra steps must be taken. +some, eg. FreeRTOS and uC/OS-III, extra steps must be taken. These RTOSes may require additional OpenOCD-specific file to be linked along with the project: @@ -8877,6 +8881,8 @@ along with the project: @table @code @item FreeRTOS contrib/rtos-helpers/FreeRTOS-openocd.c +@item uC/OS-III +contrib/rtos-helpers/uCOS-III-openocd.c @end table @node Tcl Scripting API diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am index fdca394..a9122b2 100644 --- a/src/rtos/Makefile.am +++ b/src/rtos/Makefile.am @@ -20,8 +20,8 @@ include $(top_srcdir)/common.mk METASOURCES = AUTO noinst_LTLIBRARIES = librtos.la -noinst_HEADERS = rtos.h rtos_standard_stackings.h rtos_ecos_stackings.h linux_header.h rtos_chibios_stackings.h rtos_embkernel_stackings.h rtos_mqx_stackings.h -librtos_la_SOURCES = rtos.c rtos_standard_stackings.c rtos_ecos_stackings.c rtos_chibios_stackings.c rtos_embkernel_stackings.c rtos_mqx_stackings.c FreeRTOS.c ThreadX.c eCos.c linux.c ChibiOS.c embKernel.c mqx.c +noinst_HEADERS = rtos.h rtos_standard_stackings.h rtos_ecos_stackings.h linux_header.h rtos_chibios_stackings.h rtos_embkernel_stackings.h rtos_mqx_stackings.h rtos_ucos_iii_stackings.h +librtos_la_SOURCES = rtos.c rtos_standard_stackings.c rtos_ecos_stackings.c rtos_chibios_stackings.c rtos_embkernel_stackings.c rtos_mqx_stackings.c rtos_ucos_iii_stackings.c FreeRTOS.c ThreadX.c eCos.c linux.c ChibiOS.c embKernel.c mqx.c uCOS-III.c librtos_la_CFLAGS = if IS_MINGW diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index aa8efbe..785fc61 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -34,6 +34,7 @@ extern struct rtos_type Linux_os; extern struct rtos_type ChibiOS_rtos; extern struct rtos_type embKernel_rtos; extern struct rtos_type mqx_rtos; +extern struct rtos_type uCOS_III_rtos; static struct rtos_type *rtos_types[] = { &ThreadX_rtos, @@ -43,6 +44,7 @@ static struct rtos_type *rtos_types[] = { &ChibiOS_rtos, &embKernel_rtos, &mqx_rtos, + &uCOS_III_rtos, NULL }; @@ -400,9 +402,14 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa } else if (packet[0] == 'H') { /* Set current thread ( 'c' for step and continue, 'g' for * all other operations ) */ if ((packet[1] == 'g') && (target->rtos != NULL)) { - sscanf(packet, "Hg%16" SCNx64, &target->rtos->current_threadid); - LOG_DEBUG("RTOS: GDB requested to set current thread to 0x%" PRIx64 "\r\n", - target->rtos->current_threadid); + threadid_t threadid; + sscanf(packet, "Hg%16" SCNx64, &threadid); + LOG_DEBUG("RTOS: GDB requested to set current thread to 0x%" PRIx64, threadid); + /* threadid of 0 indicates target should choose */ + if (threadid == 0) + target->rtos->current_threadid = target->rtos->current_thread; + else + target->rtos->current_threadid = threadid; } gdb_put_packet(connection, "OK", 2); return ERROR_OK; @@ -426,9 +433,13 @@ int rtos_get_gdb_reg_list(struct connection *connection) current_threadid, target->rtos->current_thread); - target->rtos->type->get_thread_reg_list(target->rtos, - current_threadid, - &hex_reg_list); + int retval = target->rtos->type->get_thread_reg_list(target->rtos, + current_threadid, + &hex_reg_list); + if (retval != ERROR_OK) { + LOG_ERROR("RTOS: failed to get register list"); + return retval; + } if (hex_reg_list != NULL) { gdb_put_packet(connection, hex_reg_list, strlen(hex_reg_list)); @@ -546,5 +557,7 @@ void rtos_free_threadlist(struct rtos *rtos) free(rtos->thread_details); rtos->thread_details = NULL; rtos->thread_count = 0; + rtos->current_threadid = -1; + rtos->current_thread = 0; } } diff --git a/src/rtos/rtos_ucos_iii_stackings.c b/src/rtos/rtos_ucos_iii_stackings.c new file mode 100644 index 0000000..f2f5564 --- /dev/null +++ b/src/rtos/rtos_ucos_iii_stackings.c @@ -0,0 +1,53 @@ +/*************************************************************************** + * Copyright (C) 2016 by Square, Inc. * + * Steven Stallion * + * * + * 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, see . * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "rtos.h" +#include "rtos_standard_stackings.h" +#include "target/armv7m.h" + +static const struct stack_register_offset rtos_uCOS_III_Cortex_M_stack_offsets[ARMV7M_NUM_CORE_REGS] = { + { 0x20, 32 }, /* r0 */ + { 0x24, 32 }, /* r1 */ + { 0x28, 32 }, /* r2 */ + { 0x2c, 32 }, /* r3 */ + { 0x00, 32 }, /* r4 */ + { 0x04, 32 }, /* r5 */ + { 0x08, 32 }, /* r6 */ + { 0x0c, 32 }, /* r7 */ + { 0x10, 32 }, /* r8 */ + { 0x14, 32 }, /* r9 */ + { 0x18, 32 }, /* r10 */ + { 0x1c, 32 }, /* r11 */ + { 0x30, 32 }, /* r12 */ + { -2, 32 }, /* sp */ + { 0x34, 32 }, /* lr */ + { 0x38, 32 }, /* pc */ + { 0x3c, 32 }, /* xPSR */ +}; + +const struct rtos_register_stacking rtos_uCOS_III_Cortex_M_stacking = { + 0x40, /* stack_registers_size */ + -1, /* stack_growth_direction */ + ARMV7M_NUM_CORE_REGS, /* num_output_registers */ + rtos_generic_stack_align8, /* stack_alignment */ + rtos_uCOS_III_Cortex_M_stack_offsets /* register_offsets */ +}; diff --git a/src/rtos/rtos_ucos_iii_stackings.h b/src/rtos/rtos_ucos_iii_stackings.h new file mode 100644 index 0000000..c462cd7 --- /dev/null +++ b/src/rtos/rtos_ucos_iii_stackings.h @@ -0,0 +1,30 @@ +/*************************************************************************** + * Copyright (C) 2016 by Square, Inc. * + * Steven Stallion * + * * + * 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, see . * + ***************************************************************************/ + +#ifndef OPENOCD_RTOS_RTOS_UCOS_III_STACKINGS_H +#define OPENOCD_RTOS_RTOS_UCOS_III_STACKINGS_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "rtos.h" + +extern const struct rtos_register_stacking rtos_uCOS_III_Cortex_M_stacking; + +#endif /* OPENOCD_RTOS_RTOS_UCOS_III_STACKINGS_H */ diff --git a/src/rtos/uCOS-III.c b/src/rtos/uCOS-III.c new file mode 100644 index 0000000..75cfe52 --- /dev/null +++ b/src/rtos/uCOS-III.c @@ -0,0 +1,509 @@ +/*************************************************************************** + * Copyright (C) 2016 by Square, Inc. * + * Steven Stallion * + * * + * 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, see . * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "target/target.h" +#include "target/target_type.h" +#include "rtos.h" +#include "helper/log.h" +#include "helper/types.h" +#include "rtos/rtos_ucos_iii_stackings.h" + +#ifndef UCOS_III_MAX_STRLEN +#define UCOS_III_MAX_STRLEN 64 +#endif + +#ifndef UCOS_III_MAX_THREADS +#define UCOS_III_MAX_THREADS 256 +#endif + +struct uCOS_III_params { + const char *target_name; + const unsigned char pointer_width; + symbol_address_t thread_stack_offset; + symbol_address_t thread_name_offset; + symbol_address_t thread_state_offset; + symbol_address_t thread_priority_offset; + symbol_address_t thread_prev_offset; + symbol_address_t thread_next_offset; + bool thread_offsets_updated; + size_t threadid_start; + const struct rtos_register_stacking *stacking_info; + size_t num_threads; + symbol_address_t threads[]; +}; + +static const struct uCOS_III_params uCOS_III_params_list[] = { + { + "cortex_m", /* target_name */ + sizeof(uint32_t), /* pointer_width */ + 0, /* thread_stack_offset */ + 0, /* thread_name_offset */ + 0, /* thread_state_offset */ + 0, /* thread_priority_offset */ + 0, /* thread_prev_offset */ + 0, /* thread_next_offset */ + false, /* thread_offsets_updated */ + 1, /* threadid_start */ + &rtos_uCOS_III_Cortex_M_stacking, /* stacking_info */ + 0, /* num_threads */ + }, +}; + +static const char * const uCOS_III_symbol_list[] = { + "OSRunning", + "OSTCBCurPtr", + "OSTaskDbgListPtr", + "OSTaskQty", + + /* also see: contrib/rtos-helpers/uCOS-III-openocd.c */ + "openocd_OS_TCB_StkPtr_offset", + "openocd_OS_TCB_NamePtr_offset", + "openocd_OS_TCB_TaskState_offset", + "openocd_OS_TCB_Prio_offset", + "openocd_OS_TCB_DbgPrevPtr_offset", + "openocd_OS_TCB_DbgNextPtr_offset", + NULL +}; + +enum uCOS_III_symbol_values { + uCOS_III_VAL_OSRunning, + uCOS_III_VAL_OSTCBCurPtr, + uCOS_III_VAL_OSTaskDbgListPtr, + uCOS_III_VAL_OSTaskQty, + + /* also see: contrib/rtos-helpers/uCOS-III-openocd.c */ + uCOS_III_VAL_OS_TCB_StkPtr_offset, + uCOS_III_VAL_OS_TCB_NamePtr_offset, + uCOS_III_VAL_OS_TCB_TaskState_offset, + uCOS_III_VAL_OS_TCB_Prio_offset, + uCOS_III_VAL_OS_TCB_DbgPrevPtr_offset, + uCOS_III_VAL_OS_TCB_DbgNextPtr_offset, +}; + +static const char * const uCOS_III_thread_state_list[] = { + "Ready", + "Delay", + "Pend", + "Pend Timeout", + "Suspended", + "Delay Suspended", + "Pend Suspended", + "Pend Timeout Suspended", +}; + +static int uCOS_III_find_or_create_thread(struct rtos *rtos, symbol_address_t thread_address, + threadid_t *threadid) +{ + struct uCOS_III_params *params = rtos->rtos_specific_params; + size_t thread_index; + + for (thread_index = 0; thread_index < params->num_threads; thread_index++) + if (params->threads[thread_index] == thread_address) + goto found; + + if (params->num_threads == UCOS_III_MAX_THREADS) { + LOG_WARNING("uCOS-III: too many threads; increase UCOS_III_MAX_THREADS"); + return ERROR_FAIL; + } + + params->threads[thread_index] = thread_address; + params->num_threads++; +found: + *threadid = thread_index + params->threadid_start; + return ERROR_OK; +} + +static int uCOS_III_find_thread_address(struct rtos *rtos, threadid_t threadid, + symbol_address_t *thread_address) +{ + struct uCOS_III_params *params = rtos->rtos_specific_params; + size_t thread_index; + + thread_index = threadid - params->threadid_start; + if (thread_index >= params->num_threads) { + LOG_ERROR("uCOS-III: failed to find thread address"); + return ERROR_FAIL; + } + + *thread_address = params->threads[thread_index]; + return ERROR_OK; +} + +static int uCOS_III_find_last_thread_address(struct rtos *rtos, symbol_address_t *thread_address) +{ + struct uCOS_III_params *params = rtos->rtos_specific_params; + int retval; + + /* read the thread list head */ + symbol_address_t thread_list_address = 0; + + retval = target_read_memory(rtos->target, + rtos->symbols[uCOS_III_VAL_OSTaskDbgListPtr].address, + params->pointer_width, + 1, + (void *)&thread_list_address); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to read thread list address"); + return retval; + } + + /* advance to end of thread list */ + do { + *thread_address = thread_list_address; + + retval = target_read_memory(rtos->target, + thread_list_address + params->thread_next_offset, + params->pointer_width, + 1, + (void *)&thread_list_address); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to read next thread address"); + return retval; + } + } while (thread_list_address != 0); + + return ERROR_OK; +} + +static int uCOS_III_update_thread_offsets(struct rtos *rtos) +{ + struct uCOS_III_params *params = rtos->rtos_specific_params; + + if (params->thread_offsets_updated) + return ERROR_OK; + + const struct thread_offset_map { + enum uCOS_III_symbol_values symbol_value; + symbol_address_t *thread_offset; + } thread_offset_maps[] = { + { + uCOS_III_VAL_OS_TCB_StkPtr_offset, + ¶ms->thread_stack_offset, + }, + { + uCOS_III_VAL_OS_TCB_NamePtr_offset, + ¶ms->thread_name_offset, + }, + { + uCOS_III_VAL_OS_TCB_TaskState_offset, + ¶ms->thread_state_offset, + }, + { + uCOS_III_VAL_OS_TCB_Prio_offset, + ¶ms->thread_priority_offset, + }, + { + uCOS_III_VAL_OS_TCB_DbgPrevPtr_offset, + ¶ms->thread_prev_offset, + }, + { + uCOS_III_VAL_OS_TCB_DbgNextPtr_offset, + ¶ms->thread_next_offset, + }, + }; + + for (size_t i = 0; i < ARRAY_SIZE(thread_offset_maps); i++) { + const struct thread_offset_map *thread_offset_map = &thread_offset_maps[i]; + + int retval = target_read_memory(rtos->target, + rtos->symbols[thread_offset_map->symbol_value].address, + params->pointer_width, + 1, + (void *)thread_offset_map->thread_offset); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to read thread offset"); + return retval; + } + } + + params->thread_offsets_updated = true; + return ERROR_OK; +} + +static int uCOS_III_detect_rtos(struct target *target) +{ + return target->rtos->symbols != NULL && + target->rtos->symbols[uCOS_III_VAL_OSRunning].address != 0; +} + +static int uCOS_III_reset_handler(struct target *target, enum target_reset_mode reset_mode, void *priv) +{ + struct uCOS_III_params *params = target->rtos->rtos_specific_params; + + params->thread_offsets_updated = false; + params->num_threads = 0; + + return ERROR_OK; +} + +static int uCOS_III_create(struct target *target) +{ + struct uCOS_III_params *params; + + for (size_t i = 0; i < ARRAY_SIZE(uCOS_III_params_list); i++) + if (strcmp(uCOS_III_params_list[i].target_name, target->type->name) == 0) { + params = malloc(sizeof(*params) + + UCOS_III_MAX_THREADS * sizeof(*params->threads)); + if (params == NULL) { + LOG_ERROR("uCOS-III: out of memory"); + return ERROR_FAIL; + } + + memcpy(params, &uCOS_III_params_list[i], sizeof(uCOS_III_params_list[i])); + target->rtos->rtos_specific_params = (void *)params; + + target_register_reset_callback(uCOS_III_reset_handler, NULL); + + return ERROR_OK; + } + + LOG_ERROR("uCOS-III: target not supported: %s", target->type->name); + return ERROR_FAIL; +} + +static int uCOS_III_update_threads(struct rtos *rtos) +{ + struct uCOS_III_params *params = rtos->rtos_specific_params; + int retval; + + /* free previous thread details */ + rtos_free_threadlist(rtos); + + /* verify RTOS is running */ + uint8_t rtos_running; + + retval = target_read_u8(rtos->target, + rtos->symbols[uCOS_III_VAL_OSRunning].address, + &rtos_running); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to read RTOS running"); + return retval; + } + + if (!rtos_running) { + rtos->thread_details = calloc(1, sizeof(struct thread_detail)); + if (rtos->thread_details == NULL) { + LOG_ERROR("uCOS-III: out of memory"); + return ERROR_FAIL; + } + + rtos->thread_count = 1; + rtos->thread_details->threadid = 0; + rtos->thread_details->exists = true; + rtos->current_thread = 0; + + return ERROR_OK; + } + + /* update thread offsets */ + retval = uCOS_III_update_thread_offsets(rtos); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to update thread offsets"); + return retval; + } + + /* read current thread address */ + symbol_address_t current_thread_address = 0; + + retval = target_read_memory(rtos->target, + rtos->symbols[uCOS_III_VAL_OSTCBCurPtr].address, + params->pointer_width, + 1, + (void *)¤t_thread_address); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to read current thread address"); + return retval; + } + + /* read number of tasks */ + retval = target_read_u16(rtos->target, + rtos->symbols[uCOS_III_VAL_OSTaskQty].address, + (void *)&rtos->thread_count); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to read thread count"); + return retval; + } + + rtos->thread_details = calloc(rtos->thread_count, sizeof(struct thread_detail)); + if (rtos->thread_details == NULL) { + LOG_ERROR("uCOS-III: out of memory"); + return ERROR_FAIL; + } + + /* + * uC/OS-III adds tasks in LIFO order; advance to the end of the + * list and work backwards to preserve the intended order. + */ + symbol_address_t thread_address = 0; + + retval = uCOS_III_find_last_thread_address(rtos, &thread_address); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to find last thread address"); + return retval; + } + + for (int i = 0; i < rtos->thread_count; i++) { + struct thread_detail *thread_detail = &rtos->thread_details[i]; + char thread_str_buffer[UCOS_III_MAX_STRLEN + 1]; + + /* find or create new threadid */ + retval = uCOS_III_find_or_create_thread(rtos, + thread_address, + &thread_detail->threadid); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to find or create thread"); + return retval; + } + + if (thread_address == current_thread_address) + rtos->current_thread = thread_detail->threadid; + + thread_detail->exists = true; + + /* read thread name */ + symbol_address_t thread_name_address = 0; + + retval = target_read_memory(rtos->target, + thread_address + params->thread_name_offset, + params->pointer_width, + 1, + (void *)&thread_name_address); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to name address"); + return retval; + } + + retval = target_read_buffer(rtos->target, + thread_name_address, + sizeof(thread_str_buffer), + (void *)thread_str_buffer); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to read thread name"); + return retval; + } + + thread_str_buffer[sizeof(thread_str_buffer) - 1] = '\0'; + thread_detail->thread_name_str = strdup(thread_str_buffer); + + /* read thread extra info */ + uint8_t thread_state; + uint8_t thread_priority; + + retval = target_read_u8(rtos->target, + thread_address + params->thread_state_offset, + &thread_state); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to read thread state"); + return retval; + } + + retval = target_read_u8(rtos->target, + thread_address + params->thread_priority_offset, + &thread_priority); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to read thread priority"); + return retval; + } + + const char *thread_state_str; + + if (thread_state < ARRAY_SIZE(uCOS_III_thread_state_list)) + thread_state_str = uCOS_III_thread_state_list[thread_state]; + else + thread_state_str = "Unknown"; + + snprintf(thread_str_buffer, sizeof(thread_str_buffer), "State: %s, Priority: %d", + thread_state_str, thread_priority); + thread_detail->extra_info_str = strdup(thread_str_buffer); + + /* read previous thread address */ + retval = target_read_memory(rtos->target, + thread_address + params->thread_prev_offset, + params->pointer_width, + 1, + (void *)&thread_address); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to read previous thread address"); + return retval; + } + } + + return ERROR_OK; +} + +static int uCOS_III_get_thread_reg_list(struct rtos *rtos, threadid_t threadid, char **hex_reg_list) +{ + struct uCOS_III_params *params = rtos->rtos_specific_params; + int retval; + + /* find thread address for threadid */ + symbol_address_t thread_address = 0; + + retval = uCOS_III_find_thread_address(rtos, threadid, &thread_address); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to find thread address"); + return retval; + } + + /* read thread stack address */ + symbol_address_t stack_address = 0; + + retval = target_read_memory(rtos->target, + thread_address + params->thread_stack_offset, + params->pointer_width, + 1, + (void *)&stack_address); + if (retval != ERROR_OK) { + LOG_ERROR("uCOS-III: failed to read stack address"); + return retval; + } + + return rtos_generic_stack_read(rtos->target, + params->stacking_info, + stack_address, + hex_reg_list); +} + +static int uCOS_III_get_symbol_list_to_lookup(symbol_table_elem_t *symbol_list[]) +{ + *symbol_list = calloc(ARRAY_SIZE(uCOS_III_symbol_list), sizeof(symbol_table_elem_t)); + if (*symbol_list == NULL) { + LOG_ERROR("uCOS-III: out of memory"); + return ERROR_FAIL; + } + + for (size_t i = 0; i < ARRAY_SIZE(uCOS_III_symbol_list); i++) + (*symbol_list)[i].symbol_name = uCOS_III_symbol_list[i]; + + return ERROR_OK; +} + +const struct rtos_type uCOS_III_rtos = { + .name = "uCOS-III", + .detect_rtos = uCOS_III_detect_rtos, + .create = uCOS_III_create, + .update_threads = uCOS_III_update_threads, + .get_thread_reg_list = uCOS_III_get_thread_reg_list, + .get_symbol_list_to_lookup = uCOS_III_get_symbol_list_to_lookup, +}; -- cgit v1.1 From 3b021e013f2e120b8c8e3d141849934edf2bdceb Mon Sep 17 00:00:00 2001 From: Evan Hunter Date: Tue, 12 Jan 2016 18:32:18 +0000 Subject: Cortex-R: Force usage of physical memory read/write since there is no MMU Change-Id: I69d6e6301ab66744258fe650a76c7241bebe00a8 Signed-off-by: Evan Hunter Reviewed-on: http://openocd.zylin.com/3203 Tested-by: jenkins Reviewed-by: Girts Folkmanis Reviewed-by: Matthias Welwarsky Reviewed-by: Jiri Kastner Reviewed-by: Paul Fertser --- src/target/cortex_a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 1f51c4e..91fa48e 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -3522,8 +3522,8 @@ struct target_type cortexr4_target = { /* REVISIT allow exporting VFP3 registers ... */ .get_gdb_reg_list = arm_get_gdb_reg_list, - .read_memory = cortex_a_read_memory, - .write_memory = cortex_a_write_memory, + .read_memory = cortex_a_read_phys_memory, + .write_memory = cortex_a_write_phys_memory, .checksum_memory = arm_checksum_memory, .blank_check_memory = arm_blank_check_memory, -- cgit v1.1 From 063253fa89b2d48104b43783c03ff7161c5d1a5a Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Sun, 6 Nov 2016 21:14:34 +0100 Subject: helper: Update jep106 database to JEP106AT Change-Id: I2dac416189d16938597c073fd35ad654bca7484c Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3871 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/helper/jep106.inc | 45 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/src/helper/jep106.inc b/src/helper/jep106.inc index 1895005..c0295a6 100644 --- a/src/helper/jep106.inc +++ b/src/helper/jep106.inc @@ -884,7 +884,7 @@ [7][0x01 - 1] = "Siklu Communication Ltd.", [7][0x02 - 1] = "A Force Manufacturing Ltd.", [7][0x03 - 1] = "Strontium", -[7][0x04 - 1] = "Abilis Systems", +[7][0x04 - 1] = "ALi Corp (Abilis Systems)", [7][0x05 - 1] = "Siglead, Inc.", [7][0x06 - 1] = "Ubicom, Inc.", [7][0x07 - 1] = "Unifosa Corporation", @@ -893,7 +893,7 @@ [7][0x0a - 1] = "Visipro.", [7][0x0b - 1] = "EKMemory", [7][0x0c - 1] = "Microelectronics Institute ZTE", -[7][0x0d - 1] = "Cognovo Ltd.", +[7][0x0d - 1] = "u-blox AG", [7][0x0e - 1] = "Carry Technology Co. Ltd.", [7][0x0f - 1] = "Nokia", [7][0x10 - 1] = "King Tiger Technology", @@ -1101,12 +1101,12 @@ [8][0x5c - 1] = "Vitesse Enterprise Co.", [8][0x5d - 1] = "Foxtronn International Corporation", [8][0x5e - 1] = "Bretelon Inc.", -[8][0x5f - 1] = "Zbit Semiconductor, Inc.", +[8][0x5f - 1] = "Graphcore", [8][0x60 - 1] = "Eoplex Inc", [8][0x61 - 1] = "MaxLinear, Inc.", [8][0x62 - 1] = "ETA Devices", [8][0x63 - 1] = "LOKI", -[8][0x64 - 1] = "IMS Semiconductor Co., Ltd", +[8][0x64 - 1] = "IMS Electronics Co., Ltd.", [8][0x65 - 1] = "Dosilicon Co., Ltd.", [8][0x66 - 1] = "Dolphin Integration", [8][0x67 - 1] = "Shenzhen Mic Electronics Technology", @@ -1116,4 +1116,41 @@ [8][0x6b - 1] = "Kingred Electronic Technology Ltd.", [8][0x6c - 1] = "Chao Yue Zhuo Computer Business Dept.", [8][0x6d - 1] = "Guangzhou Si Nuo Electronic Technology.", +[8][0x6e - 1] = "Crocus Technology Inc.", +[8][0x6f - 1] = "Creative Chips GmbH", +[8][0x70 - 1] = "GE Aviation Systems LLC.", +[8][0x71 - 1] = "Asgard", +[8][0x72 - 1] = "Good Wealth Technology Ltd.", +[8][0x73 - 1] = "TriCor Technologies", +[8][0x74 - 1] = "Nova-Systems GmbH", +[8][0x75 - 1] = "JUHOR", +[8][0x76 - 1] = "Zhuhai Douke Commerce Co. Ltd.", +[8][0x77 - 1] = "DSL Memory", +[8][0x78 - 1] = "Anvo-Systems Dresden GmbH", +[8][0x79 - 1] = "Realtek", +[8][0x7a - 1] = "AltoBeam", +[8][0x7b - 1] = "Wave Computing", +[8][0x7c - 1] = "Beijing TrustNet Technology Co. Ltd.", +[8][0x7d - 1] = "Innovium, Inc.", +[8][0x7e - 1] = "Starsway Technology Limited", +[9][0x01 - 1] = "Weltronics Co. LTD", +[9][0x02 - 1] = "VMware, Inc.", +[9][0x03 - 1] = "Hewlett Packard Enterprise", +[9][0x04 - 1] = "INTENSO", +[9][0x05 - 1] = "Puya Semiconductor", +[9][0x06 - 1] = "MEMORFI", +[9][0x07 - 1] = "MSC Technologies GmbH", +[9][0x08 - 1] = "Txrui", +[9][0x09 - 1] = "SiFive, Inc.", +[9][0x0a - 1] = "Spreadtrum Communications", +[9][0x0b - 1] = "Paragon Technology (Shenzhen) Ltd.", +[9][0x0c - 1] = "UMAX Technology", +[9][0x0d - 1] = "Shenzhen Yong Sheng Technology", +[9][0x0e - 1] = "SNOAMOO (Shenzhen Kai Zhuo Yue)", +[9][0x0f - 1] = "Daten Tecnologia LTDA", +[9][0x10 - 1] = "Shenzhen XinRuiYan Electronics", +[9][0x11 - 1] = "Eta Compute", +[9][0x12 - 1] = "Energous", +[9][0x13 - 1] = "Raspberry Pi Trading Ltd.", +[9][0x14 - 1] = "Shenzhen Chixingzhe Tech Co. Ltd.", /* EOF */ -- cgit v1.1 From aa2c38d50cfc30b651b47cfe93dcc4238c887d68 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Fri, 4 Nov 2016 14:18:21 +0300 Subject: jtag: drivers: cmsis-dap: fix operation with SAMD10 Xplained board Change-Id: I9164edeb83c9a9106e74798e98b9517177e83358 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3856 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/jtag/drivers/cmsis_dap_usb.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/jtag/drivers/cmsis_dap_usb.c b/src/jtag/drivers/cmsis_dap_usb.c index 7791840..dd37522 100644 --- a/src/jtag/drivers/cmsis_dap_usb.c +++ b/src/jtag/drivers/cmsis_dap_usb.c @@ -316,9 +316,11 @@ static int cmsis_dap_usb_open(void) int packet_size = PACKET_SIZE; /* atmel cmsis-dap uses 512 byte reports */ + /* except when it doesn't e.g. with mEDBG on SAMD10 Xplained + * board */ /* TODO: HID report descriptor should be parsed instead of * hardcoding a match by VID */ - if (target_vid == 0x03eb) + if (target_vid == 0x03eb && target_pid != 0x2145) packet_size = 512 + 1; cmsis_dap_handle->packet_buffer = malloc(packet_size); -- cgit v1.1 From c591f109c3ad1cdc66b3ba241c6be95f789c3410 Mon Sep 17 00:00:00 2001 From: Owen Kirby Date: Tue, 25 Oct 2016 15:48:56 -0700 Subject: at91sam4: Add flash description and chipid for SAM4Cxx variants. Chip ID and flash layout taken from Atmel-11102F-ATARM-SAM4C32-SAM4C16-SAM4C8-SAM4C4-Datasheet_27-Mar-15 and tested on a SAM4C32-EK (rev A). Change-Id: I68aae5b60994c0b5964ea9031d40bc76ba025675 Signed-off-by: Owen Kirby Reviewed-on: http://openocd.zylin.com/3527 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/at91sam4.c | 199 +++++++++++++++++++++++++++++++++++++++++++- tcl/target/at91sam4c32x.cfg | 9 ++ tcl/target/at91sam4cXXX.cfg | 7 ++ 3 files changed, 211 insertions(+), 4 deletions(-) create mode 100644 tcl/target/at91sam4c32x.cfg create mode 100644 tcl/target/at91sam4cXXX.cfg diff --git a/src/flash/nor/at91sam4.c b/src/flash/nor/at91sam4.c index 50aa98b..51198af 100644 --- a/src/flash/nor/at91sam4.c +++ b/src/flash/nor/at91sam4.c @@ -65,8 +65,9 @@ #define REG_NAME_WIDTH (12) -/* at91sam4s/at91sam4e series (has always one flash bank)*/ +/* at91sam4s/at91sam4e/at91sam4c series (has always one flash bank)*/ #define FLASH_BANK_BASE_S 0x00400000 +#define FLASH_BANK_BASE_C 0x01000000 /* at91sam4sd series (two one flash banks), first bank address */ #define FLASH_BANK0_BASE_SD FLASH_BANK_BASE_S @@ -75,6 +76,10 @@ /* at91sam4sd32x, second bank address */ #define FLASH_BANK1_BASE_2048K_SD (FLASH_BANK0_BASE_SD+(2048*1024/2)) +/* at91sam4c32x, first and second bank address */ +#define FLASH_BANK0_BASE_C32 FLASH_BANK_BASE_C +#define FLASH_BANK1_BASE_C32 (FLASH_BANK_BASE_C+(2048*1024/2)) + #define AT91C_EFC_FCMD_GETD (0x0) /* (EFC) Get Flash Descriptor */ #define AT91C_EFC_FCMD_WP (0x1) /* (EFC) Write Page */ #define AT91C_EFC_FCMD_WPL (0x2) /* (EFC) Write Page and Lock */ @@ -258,6 +263,188 @@ static struct sam4_chip *get_current_sam4(struct command_context *cmd_ctx) /* these are used to *initialize* the "pChip->details" structure. */ static const struct sam4_chip_details all_sam4_details[] = { + /* Start at91sam4c* series */ + /* at91sam4c32e - LQFP144 */ + { + .chipid_cidr = 0xA66D0EE0, + .name = "at91sam4c32e", + .total_flash_size = 2024 * 1024, + .total_sram_size = 256 * 1024, + .n_gpnvms = 3, + .n_banks = 2, +/* .bank[0] = { */ + { + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_C32, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_C32, + .controller_address = 0x400e0c00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, + }, + }, + /* at91sam4c32c - LQFP100 */ + { + .chipid_cidr = 0xA64D0EE0, + .name = "at91sam4c32c", + .total_flash_size = 2024 * 1024, + .total_sram_size = 256 * 1024, + .n_gpnvms = 3, + .n_banks = 2, +/* .bank[0] = { */ + { + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_C32, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_C32, + .controller_address = 0x400e0c00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, + }, + }, + /* at91sam4c16c - LQFP100 */ + { + .chipid_cidr = 0xA64C0CE0, + .name = "at91sam4c16c", + .total_flash_size = 1024 * 1024, + .total_sram_size = 128 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_C, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + /* at91sam4c8c - LQFP100 */ + { + .chipid_cidr = 0xA64C0AE0, + .name = "at91sam4c8c", + .total_flash_size = 512 * 1024, + .total_sram_size = 128 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_C, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + /* at91sam4c4c (rev B) - LQFP100 */ + { + .chipid_cidr = 0xA64C0CE5, + .name = "at91sam4c4c", + .total_flash_size = 256 * 1024, + .total_sram_size = 128 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_C, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 256 * 1024, + .nsectors = 32, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, /* Start at91sam4e* series */ /*atsam4e16e - LQFP144/LFBGA144*/ @@ -1402,7 +1589,7 @@ static uint32_t sam4_reg_fieldname(struct sam4_chip *pChip, static const char _unknown[] = "unknown"; static const char *const eproc_names[] = { - _unknown, /* 0 */ + "Cortex-M7", /* 0 */ "arm946es", /* 1 */ "arm7tdmi", /* 2 */ "Cortex-M3", /* 3 */ @@ -1430,7 +1617,7 @@ static const char *const nvpsize[] = { "64K bytes", /* 5 */ _unknown, /* 6 */ "128K bytes", /* 7 */ - _unknown, /* 8 */ + "160K bytes", /* 8 */ "256K bytes", /* 9 */ "512K bytes", /* 10 */ _unknown, /* 11 */ @@ -1478,6 +1665,8 @@ static const struct archnames { unsigned value; const char *name; } archnames[] { 0x60, "AT91SAM7Axx Series" }, { 0x61, "AT91SAM7AQxx Series" }, { 0x63, "AT91x63 Series" }, + { 0x64, "SAM4CxxC (100-pin version)" }, + { 0x66, "SAM4CxxE (144-pin version)" }, { 0x70, "AT91SAM7Sxx Series" }, { 0x71, "AT91SAM7XCxx Series" }, { 0x72, "AT91SAM7SExx Series" }, @@ -1975,15 +2164,17 @@ FLASH_BANK_COMMAND_HANDLER(sam4_flash_bank_command) /* at91sam4s series only has bank 0*/ /* at91sam4sd series has the same address for bank 0 (FLASH_BANK0_BASE_SD)*/ case FLASH_BANK_BASE_S: + case FLASH_BANK_BASE_C: bank->driver_priv = &(pChip->details.bank[0]); bank->bank_number = 0; pChip->details.bank[0].pChip = pChip; pChip->details.bank[0].pBank = bank; break; - /* Bank 1 of at91sam4sd series */ + /* Bank 1 of at91sam4sd/at91sam4c32 series */ case FLASH_BANK1_BASE_1024K_SD: case FLASH_BANK1_BASE_2048K_SD: + case FLASH_BANK1_BASE_C32: bank->driver_priv = &(pChip->details.bank[1]); bank->bank_number = 1; pChip->details.bank[1].pChip = pChip; diff --git a/tcl/target/at91sam4c32x.cfg b/tcl/target/at91sam4c32x.cfg new file mode 100644 index 0000000..5344e0c --- /dev/null +++ b/tcl/target/at91sam4c32x.cfg @@ -0,0 +1,9 @@ +# script for ATMEL sam4c32, a Cortex-M4 chip +# + +source [find target/at91sam4XXX.cfg] + +set _FLASHNAME $_CHIPNAME.flash0 +flash bank $_FLASHNAME at91sam4 0x01000000 0 1 1 $_TARGETNAME +set _FLASHNAME $_CHIPNAME.flash1 +flash bank $_FLASHNAME at91sam4 0x01100000 0 1 1 $_TARGETNAME diff --git a/tcl/target/at91sam4cXXX.cfg b/tcl/target/at91sam4cXXX.cfg new file mode 100644 index 0000000..3f10c61 --- /dev/null +++ b/tcl/target/at91sam4cXXX.cfg @@ -0,0 +1,7 @@ +# script for ATMEL sam4c, a Cortex-M4 chip +# + +source [find target/at91sam4XXX.cfg] + +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME at91sam4 0x01000000 0 1 1 $_TARGETNAME -- cgit v1.1 From dc0a009ef411e323f7626000dfe2c0dfd1b044e5 Mon Sep 17 00:00:00 2001 From: Owen Kirby Date: Tue, 25 Oct 2016 20:49:04 -0700 Subject: at91sam4: Add missing SAM4S family CHIPIDs and remove FWS=6. Add missing CHIPID values for all SAM4S parts listed in revision K of Atmel-11100-32-bit Cortex-M4-Microcontroller-SAM4S_Datasheet.pdf. I have also removed the FWS=6 workaround, as this appears to be a copy-paste error from the SAM3X family. Change-Id: I1ce1d82911f39d6fcb8f04034f5c9c9bf2818466 Signed-off-by: Owen Kirby Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3837 Tested-by: jenkins --- src/flash/nor/at91sam4.c | 292 ++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 275 insertions(+), 17 deletions(-) diff --git a/src/flash/nor/at91sam4.c b/src/flash/nor/at91sam4.c index 51198af..94d5bfd 100644 --- a/src/flash/nor/at91sam4.c +++ b/src/flash/nor/at91sam4.c @@ -666,7 +666,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, @@ -682,7 +682,7 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, }, - /*atsam4s16b - LQFP64/QFN64*/ + /*atsam4s16b - LQFP64/QFN64/WLCSP64*/ { .chipid_cidr = 0x289C0CE0, .name = "at91sam4s16b", @@ -699,7 +699,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, @@ -732,7 +732,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, @@ -765,7 +765,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, @@ -798,7 +798,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, @@ -814,7 +814,7 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, }, - /*atsam4s8b - LQFP64/BGA64*/ + /*atsam4s8b - LQFP64/QFN64/WLCSP64*/ { .chipid_cidr = 0x289C0AE0, .name = "at91sam4s8b", @@ -831,7 +831,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, @@ -864,7 +864,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, @@ -881,7 +881,75 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, - /*atsam4s4a - LQFP48/BGA48*/ + /*atsam4s4c - LQFP100/BGA100*/ + { + .chipid_cidr = 0x28ab09e0, + .name = "at91sam4s4c", + .total_flash_size = 256 * 1024, + .total_sram_size = 64 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 256 * 1024, + .nsectors = 32, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + + /*atsam4s4b - LQFP64/QFN64/WLCSP64*/ + { + .chipid_cidr = 0x289b09e0, + .name = "at91sam4s4b", + .total_flash_size = 256 * 1024, + .total_sram_size = 64 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 256 * 1024, + .nsectors = 32, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + + /*atsam4s4a - LQFP48/QFN48*/ { .chipid_cidr = 0x288b09e0, .name = "at91sam4s4a", @@ -898,7 +966,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK_BASE_S, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 256 * 1024, .nsectors = 32, @@ -915,7 +983,109 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, - /*at91sam4sd32c*/ + /*atsam4s2c - LQFP100/BGA100*/ + { + .chipid_cidr = 0x28ab07e0, + .name = "at91sam4s2c", + .total_flash_size = 128 * 1024, + .total_sram_size = 64 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 128 * 1024, + .nsectors = 16, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + + /*atsam4s2b - LQPF64/QFN64/WLCSP64*/ + { + .chipid_cidr = 0x289b07e0, + .name = "at91sam4s2b", + .total_flash_size = 128 * 1024, + .total_sram_size = 64 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 128 * 1024, + .nsectors = 16, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + + /*atsam4s2a - LQFP48/QFN48*/ + { + .chipid_cidr = 0x288b07e0, + .name = "at91sam4s2a", + .total_flash_size = 128 * 1024, + .total_sram_size = 64 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + { +/* .bank[0] = {*/ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 128 * 1024, + .nsectors = 16, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = {*/ + { + .present = 0, + .probed = 0, + .bank_number = 1, + + }, + }, + }, + + /*at91sam4sd32c - LQFP100/BGA100*/ { .chipid_cidr = 0x29a70ee0, .name = "at91sam4sd32c", @@ -933,7 +1103,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK0_BASE_SD, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, @@ -949,7 +1119,51 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 1, .base_address = FLASH_BANK1_BASE_2048K_SD, .controller_address = 0x400e0c00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, + }, + }, + + /*at91sam4sd32b - LQFP64/BGA64*/ + { + .chipid_cidr = 0x29970ee0, + .name = "at91sam4sd32b", + .total_flash_size = 2048 * 1024, + .total_sram_size = 160 * 1024, + .n_gpnvms = 3, + .n_banks = 2, + +/* .bank[0] = { */ + { + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_SD, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 1024 * 1024, + .nsectors = 128, + .sector_size = 8192, + .page_size = 512, + }, + +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_2048K_SD, + .controller_address = 0x400e0c00, + .flash_wait_states = 5, .present = 1, .size_bytes = 1024 * 1024, .nsectors = 128, @@ -959,7 +1173,7 @@ static const struct sam4_chip_details all_sam4_details[] = { }, }, - /*at91sam4sd16c*/ + /*at91sam4sd16c - LQFP100/BGA100*/ { .chipid_cidr = 0x29a70ce0, .name = "at91sam4sd16c", @@ -977,7 +1191,7 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 0, .base_address = FLASH_BANK0_BASE_SD, .controller_address = 0x400e0a00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, @@ -993,7 +1207,51 @@ static const struct sam4_chip_details all_sam4_details[] = { .bank_number = 1, .base_address = FLASH_BANK1_BASE_1024K_SD, .controller_address = 0x400e0c00, - .flash_wait_states = 6, /* workaround silicon bug */ + .flash_wait_states = 5, + .present = 1, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, + }, + }, + + /*at91sam4sd16b - LQFP64/BGA64*/ + { + .chipid_cidr = 0x29970ce0, + .name = "at91sam4sd16b", + .total_flash_size = 1024 * 1024, + .total_sram_size = 160 * 1024, + .n_gpnvms = 3, + .n_banks = 2, + +/* .bank[0] = { */ + { + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK0_BASE_SD, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, + +/* .bank[1] = { */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 1, + .base_address = FLASH_BANK1_BASE_1024K_SD, + .controller_address = 0x400e0c00, + .flash_wait_states = 5, .present = 1, .size_bytes = 512 * 1024, .nsectors = 64, -- cgit v1.1 From c0e7ccbd87cf491b065bf18bbdb6a73b741c2698 Mon Sep 17 00:00:00 2001 From: Steven Stallion Date: Fri, 22 Jul 2016 15:43:11 -0500 Subject: semihosting: support fileio operation This patch adds support for bridging semihosting to GDB's File-I/O remote protocol extension. For the most part operations match up 1:1, however some require a working area to complete successfully, namely operations that devolve to read, stat, and gettimeofday. A new command was added to enable support for fileio named `arm semihosting_fileio`, which ensures that the default behavior remains intact for those that prefer it. Finally, redundant logging was removed from the target_arch_state function; this permits ARM targets to quiesce log output when polling for a fileio reply. This prevents filling the logs with halt/resume messages when using semihosting fileio. Change-Id: Ifbb864fc2373336a501cc0332675b887b552e1ee Signed-off-by: Steven Stallion Reviewed-on: http://openocd.zylin.com/3566 Tested-by: jenkins Reviewed-by: Steven Stallion Reviewed-by: Paul Fertser --- doc/openocd.texi | 11 + src/target/arm.h | 12 + src/target/arm7tdmi.c | 3 +- src/target/arm9tdmi.c | 2 + src/target/arm_semihosting.c | 512 ++++++++++++++++++++++++++++++------------- src/target/arm_semihosting.h | 1 + src/target/armv4_5.c | 47 +++- src/target/armv7m.c | 9 +- src/target/cortex_a.c | 1 + src/target/cortex_m.c | 1 + src/target/hla_target.c | 2 +- src/target/target.c | 5 +- 12 files changed, 448 insertions(+), 158 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 372683a..1cca4ab 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -7404,6 +7404,17 @@ requests by using a special SVC instruction that is trapped at the Supervisor Call vector by OpenOCD. @end deffn +@deffn Command {arm semihosting_fileio} [@option{enable}|@option{disable}] +@cindex ARM semihosting +Display status of semihosting fileio, after optionally changing that +status. + +Enabling this option forwards semihosting I/O to GDB process using the +File-I/O remote protocol extension. This is especially useful for +interacting with remote files or displaying console messages in the +debugger. +@end deffn + @section ARMv4 and ARMv5 Architecture @cindex ARMv4 @cindex ARMv5 diff --git a/src/target/arm.h b/src/target/arm.h index 28022e3..226dd65 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -130,6 +130,18 @@ struct arm { /** Flag reporting whether semihosting is active. */ bool is_semihosting; + /** Flag reporting whether semihosting fileio is active. */ + bool is_semihosting_fileio; + + /** Flag reporting whether semihosting fileio operation is active. */ + bool semihosting_hit_fileio; + + /** Current semihosting operation. */ + int semihosting_op; + + /** Current semihosting result. */ + int semihosting_result; + /** Value to be returned by semihosting SYS_ERRNO request. */ int semihosting_errno; diff --git a/src/target/arm7tdmi.c b/src/target/arm7tdmi.c index 58ab027..9dcb302 100644 --- a/src/target/arm7tdmi.c +++ b/src/target/arm7tdmi.c @@ -30,6 +30,7 @@ #include "target_type.h" #include "register.h" #include "arm_opcodes.h" +#include "arm_semihosting.h" /* * For information about ARM7TDMI, see ARM DDI 0210C (r4p1) @@ -615,7 +616,7 @@ static void arm7tdmi_build_reg_cache(struct target *target) int arm7tdmi_init_target(struct command_context *cmd_ctx, struct target *target) { arm7tdmi_build_reg_cache(target); - + arm_semihosting_init(target); return ERROR_OK; } diff --git a/src/target/arm9tdmi.c b/src/target/arm9tdmi.c index eed965a..82b430f 100644 --- a/src/target/arm9tdmi.c +++ b/src/target/arm9tdmi.c @@ -30,6 +30,7 @@ #include "target_type.h" #include "register.h" #include "arm_opcodes.h" +#include "arm_semihosting.h" /* * NOTE: this holds code that's used with multiple ARM9 processors: @@ -714,6 +715,7 @@ int arm9tdmi_init_target(struct command_context *cmd_ctx, struct target *target) { arm9tdmi_build_reg_cache(target); + arm_semihosting_init(target); return ERROR_OK; } diff --git a/src/target/arm_semihosting.c b/src/target/arm_semihosting.c index 63335ff..2525119 100644 --- a/src/target/arm_semihosting.c +++ b/src/target/arm_semihosting.c @@ -5,6 +5,9 @@ * Copyright (C) 2010 by Spencer Oliver * * spen@spen-soft.co.uk * * * + * Copyright (C) 2016 by Square, Inc. * + * Steven Stallion * + * * * 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 * @@ -43,6 +46,7 @@ #include "cortex_m.h" #include "register.h" #include "arm_opcodes.h" +#include "target_type.h" #include "arm_semihosting.h" #include #include @@ -63,13 +67,59 @@ static const int open_modeflags[12] = { O_RDWR | O_CREAT | O_APPEND | O_BINARY }; +static int post_result(struct target *target) +{ + struct arm *arm = target_to_arm(target); + + /* REVISIT this looks wrong ... ARM11 and Cortex-A8 + * should work this way at least sometimes. + */ + if (is_arm7_9(target_to_arm7_9(target)) || + is_armv7a(target_to_armv7a(target))) { + uint32_t spsr; + + /* return value in R0 */ + buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, arm->semihosting_result); + arm->core_cache->reg_list[0].dirty = 1; + + /* LR --> PC */ + buf_set_u32(arm->core_cache->reg_list[15].value, 0, 32, + buf_get_u32(arm_reg_current(arm, 14)->value, 0, 32)); + arm->core_cache->reg_list[15].dirty = 1; + + /* saved PSR --> current PSR */ + spsr = buf_get_u32(arm->spsr->value, 0, 32); + + /* REVISIT should this be arm_set_cpsr(arm, spsr) + * instead of a partially unrolled version? + */ + + buf_set_u32(arm->cpsr->value, 0, 32, spsr); + arm->cpsr->dirty = 1; + arm->core_mode = spsr & 0x1f; + if (spsr & 0x20) + arm->core_state = ARM_STATE_THUMB; + + } else { + /* resume execution, this will be pc+2 to skip over the + * bkpt instruction */ + + /* return result in R0 */ + buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, arm->semihosting_result); + arm->core_cache->reg_list[0].dirty = 1; + } + + return ERROR_OK; +} + static int do_semihosting(struct target *target) { struct arm *arm = target_to_arm(target); + struct gdb_fileio_info *fileio_info = target->fileio_info; uint32_t r0 = buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32); uint32_t r1 = buf_get_u32(arm->core_cache->reg_list[1].value, 0, 32); uint8_t params[16]; - int retval, result; + int retval; /* * TODO: lots of security issues are not considered yet, such as: @@ -77,10 +127,10 @@ static int do_semihosting(struct target *target) * - no safety checks on opened/deleted/renamed file paths * Beware the target app you use this support with. * - * TODO: explore mapping requests to GDB's "File-I/O Remote - * Protocol Extension" ... when GDB is active. + * TODO: unsupported semihosting fileio operations could be + * implemented if we had a small working area at our disposal. */ - switch (r0) { + switch ((arm->semihosting_op = r0)) { case 0x01: /* SYS_OPEN */ retval = target_read_memory(target, r1, 4, 3, params); if (retval != ERROR_OK) @@ -89,27 +139,40 @@ static int do_semihosting(struct target *target) uint32_t a = target_buffer_get_u32(target, params+0); uint32_t m = target_buffer_get_u32(target, params+4); uint32_t l = target_buffer_get_u32(target, params+8); - if (l <= 255 && m <= 11) { - uint8_t fn[256]; - retval = target_read_memory(target, a, 1, l, fn); - if (retval != ERROR_OK) - return retval; - fn[l] = 0; - if (strcmp((char *)fn, ":tt") == 0) { - if (m < 4) - result = dup(STDIN_FILENO); - else - result = dup(STDOUT_FILENO); - } else { - /* cygwin requires the permission setting - * otherwise it will fail to reopen a previously - * written file */ - result = open((char *)fn, open_modeflags[m], 0644); + uint8_t fn[256]; + retval = target_read_memory(target, a, 1, l, fn); + if (retval != ERROR_OK) + return retval; + fn[l] = 0; + if (arm->is_semihosting_fileio) { + if (strcmp((char *)fn, ":tt") == 0) + arm->semihosting_result = 0; + else { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "open"; + fileio_info->param_1 = a; + fileio_info->param_2 = l; + fileio_info->param_3 = open_modeflags[m]; + fileio_info->param_4 = 0644; } - arm->semihosting_errno = errno; } else { - result = -1; - arm->semihosting_errno = EINVAL; + if (l <= 255 && m <= 11) { + if (strcmp((char *)fn, ":tt") == 0) { + if (m < 4) + arm->semihosting_result = dup(STDIN_FILENO); + else + arm->semihosting_result = dup(STDOUT_FILENO); + } else { + /* cygwin requires the permission setting + * otherwise it will fail to reopen a previously + * written file */ + arm->semihosting_result = open((char *)fn, open_modeflags[m], 0644); + } + arm->semihosting_errno = errno; + } else { + arm->semihosting_result = -1; + arm->semihosting_errno = EINVAL; + } } } break; @@ -120,33 +183,63 @@ static int do_semihosting(struct target *target) return retval; else { int fd = target_buffer_get_u32(target, params+0); - result = close(fd); - arm->semihosting_errno = errno; + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "close"; + fileio_info->param_1 = fd; + } else { + arm->semihosting_result = close(fd); + arm->semihosting_errno = errno; + } } break; case 0x03: /* SYS_WRITEC */ - { + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "write"; + fileio_info->param_1 = 1; + fileio_info->param_2 = r1; + fileio_info->param_3 = 1; + } else { unsigned char c; retval = target_read_memory(target, r1, 1, 1, &c); if (retval != ERROR_OK) return retval; putchar(c); - result = 0; + arm->semihosting_result = 0; } break; case 0x04: /* SYS_WRITE0 */ - do { - unsigned char c; - retval = target_read_memory(target, r1++, 1, 1, &c); - if (retval != ERROR_OK) - return retval; - if (!c) - break; - putchar(c); - } while (1); - result = 0; + if (arm->is_semihosting_fileio) { + size_t count = 0; + for (uint32_t a = r1;; a++) { + unsigned char c; + retval = target_read_memory(target, a, 1, 1, &c); + if (retval != ERROR_OK) + return retval; + if (c == '\0') + break; + count++; + } + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "write"; + fileio_info->param_1 = 1; + fileio_info->param_2 = r1; + fileio_info->param_3 = count; + } else { + do { + unsigned char c; + retval = target_read_memory(target, r1++, 1, 1, &c); + if (retval != ERROR_OK) + return retval; + if (!c) + break; + putchar(c); + } while (1); + arm->semihosting_result = 0; + } break; case 0x05: /* SYS_WRITE */ @@ -157,21 +250,29 @@ static int do_semihosting(struct target *target) int fd = target_buffer_get_u32(target, params+0); uint32_t a = target_buffer_get_u32(target, params+4); size_t l = target_buffer_get_u32(target, params+8); - uint8_t *buf = malloc(l); - if (!buf) { - result = -1; - arm->semihosting_errno = ENOMEM; + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "write"; + fileio_info->param_1 = fd; + fileio_info->param_2 = a; + fileio_info->param_3 = l; } else { - retval = target_read_buffer(target, a, l, buf); - if (retval != ERROR_OK) { + uint8_t *buf = malloc(l); + if (!buf) { + arm->semihosting_result = -1; + arm->semihosting_errno = ENOMEM; + } else { + retval = target_read_buffer(target, a, l, buf); + if (retval != ERROR_OK) { + free(buf); + return retval; + } + arm->semihosting_result = write(fd, buf, l); + arm->semihosting_errno = errno; + if (arm->semihosting_result >= 0) + arm->semihosting_result = l - arm->semihosting_result; free(buf); - return retval; } - result = write(fd, buf, l); - arm->semihosting_errno = errno; - if (result >= 0) - result = l - result; - free(buf); } } break; @@ -184,42 +285,60 @@ static int do_semihosting(struct target *target) int fd = target_buffer_get_u32(target, params+0); uint32_t a = target_buffer_get_u32(target, params+4); ssize_t l = target_buffer_get_u32(target, params+8); - uint8_t *buf = malloc(l); - if (!buf) { - result = -1; - arm->semihosting_errno = ENOMEM; + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "read"; + fileio_info->param_1 = fd; + fileio_info->param_2 = a; + fileio_info->param_3 = l; } else { - result = read(fd, buf, l); - arm->semihosting_errno = errno; - if (result >= 0) { - retval = target_write_buffer(target, a, result, buf); - if (retval != ERROR_OK) { - free(buf); - return retval; + uint8_t *buf = malloc(l); + if (!buf) { + arm->semihosting_result = -1; + arm->semihosting_errno = ENOMEM; + } else { + arm->semihosting_result = read(fd, buf, l); + arm->semihosting_errno = errno; + if (arm->semihosting_result >= 0) { + retval = target_write_buffer(target, a, arm->semihosting_result, buf); + if (retval != ERROR_OK) { + free(buf); + return retval; + } + arm->semihosting_result = l - arm->semihosting_result; } - result = l - result; + free(buf); } - free(buf); } } break; case 0x07: /* SYS_READC */ - result = getchar(); + if (arm->is_semihosting_fileio) { + LOG_ERROR("SYS_READC not supported by semihosting fileio"); + return ERROR_FAIL; + } + arm->semihosting_result = getchar(); break; case 0x08: /* SYS_ISERROR */ retval = target_read_memory(target, r1, 4, 1, params); if (retval != ERROR_OK) return retval; - result = (target_buffer_get_u32(target, params+0) != 0); + arm->semihosting_result = (target_buffer_get_u32(target, params+0) != 0); break; case 0x09: /* SYS_ISTTY */ - retval = target_read_memory(target, r1, 4, 1, params); - if (retval != ERROR_OK) - return retval; - result = isatty(target_buffer_get_u32(target, params+0)); + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "isatty"; + fileio_info->param_1 = r1; + } else { + retval = target_read_memory(target, r1, 4, 1, params); + if (retval != ERROR_OK) + return retval; + arm->semihosting_result = isatty(target_buffer_get_u32(target, params+0)); + } break; case 0x0a: /* SYS_SEEK */ @@ -229,27 +348,39 @@ static int do_semihosting(struct target *target) else { int fd = target_buffer_get_u32(target, params+0); off_t pos = target_buffer_get_u32(target, params+4); - result = lseek(fd, pos, SEEK_SET); - arm->semihosting_errno = errno; - if (result == pos) - result = 0; + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "lseek"; + fileio_info->param_1 = fd; + fileio_info->param_2 = pos; + fileio_info->param_3 = SEEK_SET; + } else { + arm->semihosting_result = lseek(fd, pos, SEEK_SET); + arm->semihosting_errno = errno; + if (arm->semihosting_result == pos) + arm->semihosting_result = 0; + } } break; case 0x0c: /* SYS_FLEN */ + if (arm->is_semihosting_fileio) { + LOG_ERROR("SYS_FLEN not supported by semihosting fileio"); + return ERROR_FAIL; + } retval = target_read_memory(target, r1, 4, 1, params); if (retval != ERROR_OK) return retval; else { int fd = target_buffer_get_u32(target, params+0); struct stat buf; - result = fstat(fd, &buf); - if (result == -1) { + arm->semihosting_result = fstat(fd, &buf); + if (arm->semihosting_result == -1) { arm->semihosting_errno = errno; - result = -1; + arm->semihosting_result = -1; break; } - result = buf.st_size; + arm->semihosting_result = buf.st_size; } break; @@ -260,17 +391,24 @@ static int do_semihosting(struct target *target) else { uint32_t a = target_buffer_get_u32(target, params+0); uint32_t l = target_buffer_get_u32(target, params+4); - if (l <= 255) { - uint8_t fn[256]; - retval = target_read_memory(target, a, 1, l, fn); - if (retval != ERROR_OK) - return retval; - fn[l] = 0; - result = remove((char *)fn); - arm->semihosting_errno = errno; + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "unlink"; + fileio_info->param_1 = a; + fileio_info->param_2 = l; } else { - result = -1; - arm->semihosting_errno = EINVAL; + if (l <= 255) { + uint8_t fn[256]; + retval = target_read_memory(target, a, 1, l, fn); + if (retval != ERROR_OK) + return retval; + fn[l] = 0; + arm->semihosting_result = remove((char *)fn); + arm->semihosting_errno = errno; + } else { + arm->semihosting_result = -1; + arm->semihosting_errno = EINVAL; + } } } break; @@ -284,31 +422,40 @@ static int do_semihosting(struct target *target) uint32_t l1 = target_buffer_get_u32(target, params+4); uint32_t a2 = target_buffer_get_u32(target, params+8); uint32_t l2 = target_buffer_get_u32(target, params+12); - if (l1 <= 255 && l2 <= 255) { - uint8_t fn1[256], fn2[256]; - retval = target_read_memory(target, a1, 1, l1, fn1); - if (retval != ERROR_OK) - return retval; - retval = target_read_memory(target, a2, 1, l2, fn2); - if (retval != ERROR_OK) - return retval; - fn1[l1] = 0; - fn2[l2] = 0; - result = rename((char *)fn1, (char *)fn2); - arm->semihosting_errno = errno; + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "rename"; + fileio_info->param_1 = a1; + fileio_info->param_2 = l1; + fileio_info->param_3 = a2; + fileio_info->param_4 = l2; } else { - result = -1; - arm->semihosting_errno = EINVAL; + if (l1 <= 255 && l2 <= 255) { + uint8_t fn1[256], fn2[256]; + retval = target_read_memory(target, a1, 1, l1, fn1); + if (retval != ERROR_OK) + return retval; + retval = target_read_memory(target, a2, 1, l2, fn2); + if (retval != ERROR_OK) + return retval; + fn1[l1] = 0; + fn2[l2] = 0; + arm->semihosting_result = rename((char *)fn1, (char *)fn2); + arm->semihosting_errno = errno; + } else { + arm->semihosting_result = -1; + arm->semihosting_errno = EINVAL; + } } } break; case 0x11: /* SYS_TIME */ - result = time(NULL); + arm->semihosting_result = time(NULL); break; case 0x13: /* SYS_ERRNO */ - result = arm->semihosting_errno; + arm->semihosting_result = arm->semihosting_errno; break; case 0x15: /* SYS_GET_CMDLINE */ @@ -321,12 +468,12 @@ static int do_semihosting(struct target *target) char *arg = "foobar"; uint32_t s = strlen(arg) + 1; if (l < s) - result = -1; + arm->semihosting_result = -1; else { retval = target_write_buffer(target, a, s, (uint8_t *)arg); if (retval != ERROR_OK) return retval; - result = 0; + arm->semihosting_result = 0; } } break; @@ -342,7 +489,7 @@ static int do_semihosting(struct target *target) retval = target_write_memory(target, a, 4, 4, params); if (retval != ERROR_OK) return retval; - result = 0; + arm->semihosting_result = 0; } break; @@ -386,17 +533,24 @@ static int do_semihosting(struct target *target) else { uint32_t len = target_buffer_get_u32(target, params+4); uint32_t c_ptr = target_buffer_get_u32(target, params); - uint8_t cmd[256]; - if (len > 255) { - result = -1; - arm->semihosting_errno = EINVAL; + if (arm->is_semihosting_fileio) { + arm->semihosting_hit_fileio = true; + fileio_info->identifier = "system"; + fileio_info->param_1 = c_ptr; + fileio_info->param_2 = len; } else { - memset(cmd, 0x0, 256); - retval = target_read_memory(target, c_ptr, 1, len, cmd); - if (retval != ERROR_OK) - return retval; - else - result = system((const char *)cmd); + uint8_t cmd[256]; + if (len > 255) { + arm->semihosting_result = -1; + arm->semihosting_errno = EINVAL; + } else { + memset(cmd, 0x0, 256); + retval = target_read_memory(target, c_ptr, 1, len, cmd); + if (retval != ERROR_OK) + return retval; + else + arm->semihosting_result = system((const char *)cmd); + } } } break; @@ -408,51 +562,84 @@ static int do_semihosting(struct target *target) default: fprintf(stderr, "semihosting: unsupported call %#x\n", (unsigned) r0); - result = -1; + arm->semihosting_result = -1; arm->semihosting_errno = ENOTSUP; } - /* resume execution to the original mode */ + return ERROR_OK; +} - /* REVISIT this looks wrong ... ARM11 and Cortex-A8 - * should work this way at least sometimes. +static int get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info) +{ + struct arm *arm = target_to_arm(target); + + /* To avoid uneccessary duplication, semihosting prepares the + * fileio_info structure out-of-band when the target halts. See + * do_semihosting for more detail. */ - if (is_arm7_9(target_to_arm7_9(target)) || - is_armv7a(target_to_armv7a(target))) { - uint32_t spsr; + if (!arm->is_semihosting_fileio || !arm->semihosting_hit_fileio) + return ERROR_FAIL; - /* return value in R0 */ - buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, result); - arm->core_cache->reg_list[0].dirty = 1; + return ERROR_OK; +} - /* LR --> PC */ - buf_set_u32(arm->core_cache->reg_list[15].value, 0, 32, - buf_get_u32(arm_reg_current(arm, 14)->value, 0, 32)); - arm->core_cache->reg_list[15].dirty = 1; +static int gdb_fileio_end(struct target *target, int result, int fileio_errno, bool ctrl_c) +{ + struct arm *arm = target_to_arm(target); + struct gdb_fileio_info *fileio_info = target->fileio_info; - /* saved PSR --> current PSR */ - spsr = buf_get_u32(arm->spsr->value, 0, 32); + /* clear pending status */ + arm->semihosting_hit_fileio = false; - /* REVISIT should this be arm_set_cpsr(arm, spsr) - * instead of a partially unrolled version? - */ + arm->semihosting_result = result; + arm->semihosting_errno = fileio_errno; - buf_set_u32(arm->cpsr->value, 0, 32, spsr); - arm->cpsr->dirty = 1; - arm->core_mode = spsr & 0x1f; - if (spsr & 0x20) - arm->core_state = ARM_STATE_THUMB; + /* Some fileio results do not match up with what the semihosting + * operation expects; for these operations, we munge the results + * below: + */ + switch (arm->semihosting_op) { + case 0x05: /* SYS_WRITE */ + if (result < 0) + arm->semihosting_result = fileio_info->param_3; + else + arm->semihosting_result = 0; + break; - } else { - /* resume execution, this will be pc+2 to skip over the - * bkpt instruction */ + case 0x06: /* SYS_READ */ + if (result == (int)fileio_info->param_3) + arm->semihosting_result = 0; + if (result <= 0) + arm->semihosting_result = fileio_info->param_3; + break; - /* return result in R0 */ - buf_set_u32(arm->core_cache->reg_list[0].value, 0, 32, result); - arm->core_cache->reg_list[0].dirty = 1; + case 0x0a: /* SYS_SEEK */ + if (result > 0) + arm->semihosting_result = 0; + break; } - return target_resume(target, 1, 0, 0, 0); + return post_result(target); +} + +/** + * Initialize ARM semihosting support. + * + * @param target Pointer to the ARM target to initialize. + * @return An error status if there is a problem during initialization. + */ +int arm_semihosting_init(struct target *target) +{ + target->fileio_info = malloc(sizeof(*target->fileio_info)); + if (target->fileio_info == NULL) { + LOG_ERROR("out of memory"); + return ERROR_FAIL; + } + + target->type->get_gdb_fileio_info = get_gdb_fileio_info; + target->type->gdb_fileio_end = gdb_fileio_end; + + return ERROR_OK; } /** @@ -576,6 +763,35 @@ int arm_semihosting(struct target *target, int *retval) return 0; } - *retval = do_semihosting(target); - return 1; + /* Perform semihosting if we are not waiting on a fileio + * operation to complete. + */ + if (!arm->semihosting_hit_fileio) { + *retval = do_semihosting(target); + if (*retval != ERROR_OK) { + LOG_ERROR("Failed semihosting operation"); + return 0; + } + } + + /* Post result to target if we are not waiting on a fileio + * operation to complete: + */ + if (!arm->semihosting_hit_fileio) { + *retval = post_result(target); + if (*retval != ERROR_OK) { + LOG_ERROR("Failed to post semihosting result"); + return 0; + } + + *retval = target_resume(target, 1, 0, 0, 0); + if (*retval != ERROR_OK) { + LOG_ERROR("Failed to resume target"); + return 0; + } + + return 1; + } + + return 0; } diff --git a/src/target/arm_semihosting.h b/src/target/arm_semihosting.h index 7b5c0b2..011f19f 100644 --- a/src/target/arm_semihosting.h +++ b/src/target/arm_semihosting.h @@ -19,6 +19,7 @@ #ifndef OPENOCD_TARGET_ARM_SEMIHOSTING_H #define OPENOCD_TARGET_ARM_SEMIHOSTING_H +int arm_semihosting_init(struct target *target); int arm_semihosting(struct target *target, int *retval); #endif /* OPENOCD_TARGET_ARM_SEMIHOSTING_H */ diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 1a31d40..624a254 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -666,14 +666,19 @@ int arm_arch_state(struct target *target) return ERROR_FAIL; } + /* avoid filling log waiting for fileio reply */ + if (arm->semihosting_hit_fileio) + return ERROR_OK; + LOG_USER("target halted in %s state due to %s, current mode: %s\n" - "cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s", + "cpsr: 0x%8.8" PRIx32 " pc: 0x%8.8" PRIx32 "%s%s", arm_state_strings[arm->core_state], debug_reason_name(target), arm_mode_name(arm->core_mode), buf_get_u32(arm->cpsr->value, 0, 32), buf_get_u32(arm->pc->value, 0, 32), - arm->is_semihosting ? ", semihosting" : ""); + arm->is_semihosting ? ", semihosting" : "", + arm->is_semihosting_fileio ? " fileio" : ""); return ERROR_OK; } @@ -1055,6 +1060,37 @@ COMMAND_HANDLER(handle_arm_semihosting_command) return ERROR_OK; } +COMMAND_HANDLER(handle_arm_semihosting_fileio_command) +{ + struct target *target = get_current_target(CMD_CTX); + + if (target == NULL) { + LOG_ERROR("No target selected"); + return ERROR_FAIL; + } + + struct arm *arm = target_to_arm(target); + + if (!is_arm(arm)) { + command_print(CMD_CTX, "current target isn't an ARM"); + return ERROR_FAIL; + } + + if (!arm->is_semihosting) { + command_print(CMD_CTX, "semihosting is not enabled"); + return ERROR_FAIL; + } + + if (CMD_ARGC > 0) + COMMAND_PARSE_ENABLE(CMD_ARGV[0], arm->is_semihosting_fileio); + + command_print(CMD_CTX, "semihosting fileio is %s", + arm->is_semihosting_fileio + ? "enabled" : "disabled"); + + return ERROR_OK; +} + static const struct command_registration arm_exec_command_handlers[] = { { .name = "reg", @@ -1097,6 +1133,13 @@ static const struct command_registration arm_exec_command_handlers[] = { .usage = "['enable'|'disable']", .help = "activate support for semihosting operations", }, + { + "semihosting_fileio", + .handler = handle_arm_semihosting_fileio_command, + .mode = COMMAND_EXEC, + .usage = "['enable'|'disable']", + .help = "activate support for semihosting fileio operations", + }, COMMAND_REGISTRATION_DONE }; diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 60b244a..64d18d7 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -536,11 +536,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 (arm->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 +552,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" : ""); + arm->is_semihosting ? ", semihosting" : "", + arm->is_semihosting_fileio ? " fileio" : ""); return ERROR_OK; } diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 91fa48e..ed2f613 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -3103,6 +3103,7 @@ static int cortex_a_init_target(struct command_context *cmd_ctx, struct target *target) { /* examine_first() does a bunch of this */ + arm_semihosting_init(target); return ERROR_OK; } diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 4270f8f..f674cc5 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1696,6 +1696,7 @@ static int cortex_m_init_target(struct command_context *cmd_ctx, struct target *target) { armv7m_build_reg_cache(target); + arm_semihosting_init(target); return ERROR_OK; } diff --git a/src/target/hla_target.c b/src/target/hla_target.c index e02abc4..feeb11f 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -341,7 +341,7 @@ static int adapter_init_target(struct command_context *cmd_ctx, LOG_DEBUG("%s", __func__); armv7m_build_reg_cache(target); - + arm_semihosting_init(target); return ERROR_OK; } diff --git a/src/target/target.c b/src/target/target.c index 26bae4b..17902a5 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1944,13 +1944,10 @@ int target_arch_state(struct target *target) { int retval; if (target == NULL) { - LOG_USER("No target has been configured"); + LOG_WARNING("No target has been configured"); return ERROR_OK; } - LOG_USER("%s: target state: %s", target_name(target), - target_state_name(target)); - if (target->state != TARGET_HALTED) return ERROR_OK; -- cgit v1.1 From 50dd7207eaae9d2d1f02e7996135d6257c03b395 Mon Sep 17 00:00:00 2001 From: Steven Stallion Date: Wed, 20 Jul 2016 21:09:24 -0500 Subject: gdb_server: support qXfer:threads:read packet This patch adds support for the qXfer:threads:read packet. In addition to providing a more efficient method of updating thread state, recent versions of GDB (7.11.1 and up) can also report remote thread names. While thread names are not enabled in this patch due to its limited applicability at the moment, it can be enabled at a later date with little effort. As a part of revamping how threads are presented to GDB, extra info strings for each of the supported RTOSes were updated to match conventions present in the GDB source code. For more information, see remote_threads_extra_info() in remote.c. This results in a much smoother experience when interacting with GDB. It is also worth mentioning that use of qXfer:threads:read works around a number of regressions in older versions of GDB regarding remote thread display. Trust me, it's great. Change-Id: I97dd6a93c342ceb9b9d0023b6359db0e5604c6e6 Signed-off-by: Steven Stallion Reviewed-on: http://openocd.zylin.com/3559 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Paul Fertser --- src/rtos/ChibiOS.c | 6 +-- src/rtos/FreeRTOS.c | 2 +- src/rtos/ThreadX.c | 4 +- src/rtos/eCos.c | 4 +- src/rtos/embKernel.c | 6 +-- src/rtos/linux.c | 6 +-- src/rtos/mqx.c | 10 ++-- src/rtos/rtos.c | 6 +-- src/server/gdb_server.c | 125 +++++++++++++++++++++++++++++++++++++++++++++++- 9 files changed, 145 insertions(+), 24 deletions(-) diff --git a/src/rtos/ChibiOS.c b/src/rtos/ChibiOS.c index 00e9df7..1bc1af8 100644 --- a/src/rtos/ChibiOS.c +++ b/src/rtos/ChibiOS.c @@ -440,11 +440,11 @@ static int ChibiOS_update_threads(struct rtos *rtos) if (threadState < CHIBIOS_NUM_STATES) state_desc = ChibiOS_thread_states[threadState]; else - state_desc = "Unknown state"; + state_desc = "Unknown"; curr_thrd_details->extra_info_str = malloc(strlen( - state_desc)+1); - strcpy(curr_thrd_details->extra_info_str, state_desc); + state_desc)+8); + sprintf(curr_thrd_details->extra_info_str, "State: %s", state_desc); curr_thrd_details->exists = true; diff --git a/src/rtos/FreeRTOS.c b/src/rtos/FreeRTOS.c index 52cebad..83961eb 100644 --- a/src/rtos/FreeRTOS.c +++ b/src/rtos/FreeRTOS.c @@ -362,7 +362,7 @@ static int FreeRTOS_update_threads(struct rtos *rtos) rtos->thread_details[tasks_found].exists = true; if (rtos->thread_details[tasks_found].threadid == rtos->current_thread) { - char running_str[] = "Running"; + char running_str[] = "State: Running"; rtos->thread_details[tasks_found].extra_info_str = malloc( sizeof(running_str)); strcpy(rtos->thread_details[tasks_found].extra_info_str, diff --git a/src/rtos/ThreadX.c b/src/rtos/ThreadX.c index 8267b9f..ab8a66e 100644 --- a/src/rtos/ThreadX.c +++ b/src/rtos/ThreadX.c @@ -408,8 +408,8 @@ static int ThreadX_update_threads(struct rtos *rtos) state_desc = "Unknown state"; rtos->thread_details[tasks_found].extra_info_str = malloc(strlen( - state_desc)+1); - strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc); + state_desc)+8); + sprintf(rtos->thread_details[tasks_found].extra_info_str, "State: %s", state_desc); rtos->thread_details[tasks_found].exists = true; diff --git a/src/rtos/eCos.c b/src/rtos/eCos.c index e38e11f..edc3d8b 100644 --- a/src/rtos/eCos.c +++ b/src/rtos/eCos.c @@ -261,8 +261,8 @@ static int eCos_update_threads(struct rtos *rtos) state_desc = "Unknown state"; rtos->thread_details[tasks_found].extra_info_str = malloc(strlen( - state_desc)+1); - strcpy(rtos->thread_details[tasks_found].extra_info_str, state_desc); + state_desc)+8); + sprintf(rtos->thread_details[tasks_found].extra_info_str, "State: %s", state_desc); rtos->thread_details[tasks_found].exists = true; diff --git a/src/rtos/embKernel.c b/src/rtos/embKernel.c index ceb313f..e515383 100644 --- a/src/rtos/embKernel.c +++ b/src/rtos/embKernel.c @@ -168,11 +168,11 @@ static int embKernel_get_tasks_details(struct rtos *rtos, int64_t iterable, cons return retval; details->extra_info_str = malloc(EMBKERNEL_MAX_THREAD_NAME_STR_SIZE); if (task == rtos->current_thread) { - snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "Pri=%u, Running", + snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: Running, Priority: %u", (unsigned int) priority); } else { - snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "Pri=%u, %s", (unsigned int) priority, - state_str); + snprintf(details->extra_info_str, EMBKERNEL_MAX_THREAD_NAME_STR_SIZE, "State: %s, Priority: %u", + state_str, (unsigned int) priority); } LOG_OUTPUT("Getting task details: iterable=0x%08X, task=0x%08X, name=%s\n", (unsigned int)iterable, diff --git a/src/rtos/linux.c b/src/rtos/linux.c index 8c150af..31d6618 100644 --- a/src/rtos/linux.c +++ b/src/rtos/linux.c @@ -1213,7 +1213,7 @@ int linux_thread_extra_info(struct target *target, if (temp->threadid == threadid) { char *pid = " PID: "; char *pid_current = "*PID: "; - char *name = "NAME: "; + char *name = "Name: "; int str_size = strlen(pid) + strlen(name); char *tmp_str = calloc(1, str_size + 50); char *tmp_str_ptr = tmp_str; @@ -1225,9 +1225,7 @@ int linux_thread_extra_info(struct target *target, else tmp_str_ptr += sprintf(tmp_str_ptr, "%s", pid); - tmp_str_ptr += - sprintf(tmp_str_ptr, "%d", (int)temp->pid); - tmp_str_ptr += sprintf(tmp_str_ptr, "%s", " | "); + tmp_str_ptr += sprintf(tmp_str_ptr, "%d, ", (int)temp->pid); sprintf(tmp_str_ptr, "%s", name); sprintf(tmp_str_ptr, "%s", temp->name); char *hex_str = calloc(1, strlen(tmp_str) * 2 + 1); diff --git a/src/rtos/mqx.c b/src/rtos/mqx.c index b8095a0..63a48c5 100644 --- a/src/rtos/mqx.c +++ b/src/rtos/mqx.c @@ -353,7 +353,7 @@ static int mqx_update_threads( uint32_t task_name_addr = 0, task_id = 0, task_errno = 0; uint32_t state_index = 0, state_max = 0; uint32_t extra_info_length = 0; - char *state_name = "unknown state"; + char *state_name = "Unknown"; /* set current taskpool address */ if (ERROR_OK != mqx_get_member( @@ -435,13 +435,13 @@ static int mqx_update_threads( * calculate length as: * state length + address length + errno length + formatter length */ - extra_info_length += strlen((void *)state_name) + 8 + 8 + 8; + extra_info_length += strlen((void *)state_name) + 7 + 13 + 8 + 15 + 8; rtos->thread_details[i].extra_info_str = malloc(extra_info_length + 1); if (NULL == rtos->thread_details[i].extra_info_str) return ERROR_FAIL; - snprintf( - rtos->thread_details[i].extra_info_str, extra_info_length, "%s : 0x%"PRIx32 " : %" PRIu32, - state_name, task_addr, task_errno + snprintf(rtos->thread_details[i].extra_info_str, extra_info_length, + "State: %s, Address: 0x%" PRIx32 ", Error Code: %" PRIu32, + state_name, task_addr, task_errno ); /* set active thread */ if (active_td_addr == task_addr) diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 785fc61..6938336 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -306,14 +306,14 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa if (detail->extra_info_str != NULL) str_size += strlen(detail->extra_info_str); - char *tmp_str = calloc(str_size + 4, sizeof(char)); + char *tmp_str = calloc(str_size + 9, sizeof(char)); char *tmp_str_ptr = tmp_str; if (detail->thread_name_str != NULL) - tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->thread_name_str); + tmp_str_ptr += sprintf(tmp_str_ptr, "Name: %s", detail->thread_name_str); if (detail->extra_info_str != NULL) { if (tmp_str_ptr != tmp_str) - tmp_str_ptr += sprintf(tmp_str_ptr, " : "); + tmp_str_ptr += sprintf(tmp_str_ptr, ", "); tmp_str_ptr += sprintf(tmp_str_ptr, "%s", detail->extra_info_str); } diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 7fd579b..6f111e1 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -90,6 +90,8 @@ struct gdb_connection { bool attached; /* temporarily used for target description support */ struct target_desc_format target_desc; + /* temporarily used for thread list support */ + char *thread_list; }; #if 0 @@ -934,6 +936,7 @@ static int gdb_new_connection(struct connection *connection) gdb_connection->attached = true; gdb_connection->target_desc.tdesc = NULL; gdb_connection->target_desc.tdesc_length = 0; + gdb_connection->thread_list = NULL; /* send ACK to GDB for debug request */ gdb_write(connection, "+", 1); @@ -2283,6 +2286,95 @@ error: return retval; } +static int gdb_generate_thread_list(struct target *target, char **thread_list_out) +{ + struct rtos *rtos = target->rtos; + int retval = ERROR_OK; + char *thread_list = NULL; + int pos = 0; + int size = 0; + + xml_printf(&retval, &thread_list, &pos, &size, + "\n" + "\n"); + + if (rtos != NULL) { + for (int i = 0; i < rtos->thread_count; i++) { + struct thread_detail *thread_detail = &rtos->thread_details[i]; + + if (!thread_detail->exists) + continue; + + xml_printf(&retval, &thread_list, &pos, &size, + "", thread_detail->threadid); + + if (thread_detail->thread_name_str != NULL) + xml_printf(&retval, &thread_list, &pos, &size, + "Name: %s", thread_detail->thread_name_str); + + if (thread_detail->extra_info_str != NULL) { + if (thread_detail->thread_name_str != NULL) + xml_printf(&retval, &thread_list, &pos, &size, + ", "); + xml_printf(&retval, &thread_list, &pos, &size, + thread_detail->extra_info_str); + } + + xml_printf(&retval, &thread_list, &pos, &size, + "\n"); + } + } + + xml_printf(&retval, &thread_list, &pos, &size, + "\n"); + + if (retval == ERROR_OK) + *thread_list_out = thread_list; + else + free(thread_list); + + return retval; +} + +static int gdb_get_thread_list_chunk(struct target *target, char **thread_list, + char **chunk, int32_t offset, uint32_t length) +{ + if (*thread_list == NULL) { + int retval = gdb_generate_thread_list(target, thread_list); + if (retval != ERROR_OK) { + LOG_ERROR("Unable to Generate Thread List"); + return ERROR_FAIL; + } + } + + size_t thread_list_length = strlen(*thread_list); + char transfer_type; + + length = MIN(length, thread_list_length - offset); + if (length < (thread_list_length - offset)) + transfer_type = 'm'; + else + transfer_type = 'l'; + + *chunk = malloc(length + 2); + if (*chunk == NULL) { + LOG_ERROR("Unable to allocate memory"); + return ERROR_FAIL; + } + + (*chunk)[0] = transfer_type; + strncpy((*chunk) + 1, (*thread_list) + offset, length); + (*chunk)[1 + length] = '\0'; + + /* After gdb-server sends out last chunk, invalidate thread list. */ + if (transfer_type == 'l') { + free(*thread_list); + *thread_list = NULL; + } + + return ERROR_OK; +} + static int gdb_query_packet(struct connection *connection, char const *packet, int packet_size) { @@ -2372,7 +2464,7 @@ static int gdb_query_packet(struct connection *connection, &buffer, &pos, &size, - "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;QStartNoAckMode+", + "PacketSize=%x;qXfer:memory-map:read%c;qXfer:features:read%c;qXfer:threads:read+;QStartNoAckMode+", (GDB_BUFFER_SIZE - 1), ((gdb_use_memory_map == 1) && (flash_get_bank_count() > 0)) ? '+' : '-', (gdb_target_desc_supported == 1) ? '+' : '-'); @@ -2420,6 +2512,37 @@ static int gdb_query_packet(struct connection *connection, free(xml); return ERROR_OK; + } else if (strncmp(packet, "qXfer:threads:read:", 19) == 0) { + char *xml = NULL; + int retval = ERROR_OK; + + int offset; + unsigned int length; + + /* skip command character */ + packet += 19; + + if (decode_xfer_read(packet, NULL, &offset, &length) < 0) { + gdb_send_error(connection, 01); + return ERROR_OK; + } + + /* Target should prepare correct thread list for annex. + * The first character of returned xml is 'm' or 'l'. 'm' for + * there are *more* chunks to transfer. 'l' for it is the *last* + * chunk of target description. + */ + retval = gdb_get_thread_list_chunk(target, &gdb_connection->thread_list, + &xml, offset, length); + if (retval != ERROR_OK) { + gdb_error(connection, retval); + return retval; + } + + gdb_put_packet(connection, xml, strlen(xml)); + + free(xml); + return ERROR_OK; } else if (strncmp(packet, "QStartNoAckMode", 15) == 0) { gdb_connection->noack_mode = 1; gdb_put_packet(connection, "OK", 2); -- cgit v1.1 From 1461237073e377d315799999b8e29f1605084449 Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Thu, 18 Aug 2016 05:16:29 +0000 Subject: jtag: drivers: bcm2835gpio: set 4ma drive, slow slew rate Both the drive strength and slew rate are currently set to very high values. This causes the waveforms to overshoot and be less reliable when operating at high speed. This patch lowers the slew rate and sets the drive strength to 4ma, improving the waveform output. Change-Id: I761d35cd64bc54a9e94043904ef00a003b056af0 Signed-off-by: Sean Cross Reviewed-on: http://openocd.zylin.com/3707 Tested-by: jenkins Reviewed-by: Paul Fertser Reviewed-by: Tomas Vanek Reviewed-by: Philipp Guehring --- src/jtag/drivers/bcm2835gpio.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jtag/drivers/bcm2835gpio.c b/src/jtag/drivers/bcm2835gpio.c index 1622b22..a41caf0 100644 --- a/src/jtag/drivers/bcm2835gpio.c +++ b/src/jtag/drivers/bcm2835gpio.c @@ -468,8 +468,8 @@ static int bcm2835gpio_init(void) return ERROR_JTAG_INIT_FAILED; } - /* set 16mA drive strength */ - pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000018 + 7; + /* set 4mA drive strength, slew rate limited, hysteresis on */ + pads_base[BCM2835_PADS_GPIO_0_27_OFFSET] = 0x5a000008 + 1; tdo_gpio_mode = MODE_GPIO(tdo_gpio); tdi_gpio_mode = MODE_GPIO(tdi_gpio); -- cgit v1.1 From 69ff7354d9c9accf09374772310098f1f00e8ccb Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 22 May 2016 20:35:34 +0200 Subject: helper: Code cleanup for hexify() Simplify hexify() and do not longer use 0 as special case for the parameter 'count' to determine the string length of the binary input. Instead, use strlen() outside of the function if needed. Additionally, fix the return value and return the length of the converted string. The old function always returned 2 * count. Also, use more appropriate data types for the function parameters and add a small documentation. Change-Id: I133a8ab786b8f7c1296afcaf9c0a0b43881e5112 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3793 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/helper/binarybuffer.c | 37 +++++++++++++++++++++++++++++-------- src/helper/binarybuffer.h | 2 +- src/jtag/drivers/ti_icdi_usb.c | 5 +++-- src/rtos/linux.c | 3 ++- src/rtos/rtos.c | 7 +++++-- src/server/gdb_server.c | 5 +++-- src/server/tcl_server.c | 2 +- src/target/smp.c | 3 ++- 8 files changed, 46 insertions(+), 18 deletions(-) diff --git a/src/helper/binarybuffer.c b/src/helper/binarybuffer.c index 26aa8cc..76f657f 100644 --- a/src/helper/binarybuffer.c +++ b/src/helper/binarybuffer.c @@ -45,6 +45,11 @@ static const unsigned char bit_reverse_table256[] = { 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF }; +static const char hex_digits[] = { + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + 'a', 'b', 'c', 'd', 'e', 'f' +}; + void *buf_cpy(const void *from, void *_to, unsigned size) { if (NULL == from || NULL == _to) @@ -407,18 +412,34 @@ size_t unhexify(uint8_t *bin, const char *hex, size_t count) return i / 2; } -int hexify(char *hex, const char *bin, int count, int out_maxlen) +/** + * Convert binary data into a string of hexadecimal pairs. + * + * @param[out] hex Buffer to store string of hexadecimal pairs. The buffer size + * must be at least @p length. + * @param[in] bin Buffer with binary data to convert into hexadecimal pairs. + * @param[in] count Number of bytes to convert. + * @param[in] length Maximum number of characters, including null-terminator, + * to store into @p hex. + * + * @returns The length of the converted string excluding null-terminator. + */ +size_t hexify(char *hex, const uint8_t *bin, size_t count, size_t length) { - int i, cmd_len = 0; + size_t i; + uint8_t tmp; - /* May use a length, or a null-terminated string as input. */ - if (count == 0) - count = strlen(bin); + if (!length) + return 0; - for (i = 0; i < count; i++) - cmd_len += snprintf(hex + cmd_len, out_maxlen - cmd_len, "%02x", bin[i] & 0xff); + for (i = 0; i < length - 1 && i < 2 * count; i++) { + tmp = (bin[i / 2] >> (4 * ((i + 1) % 2))) & 0x0f; + hex[i] = hex_digits[tmp]; + } - return cmd_len; + hex[i] = 0; + + return i; } void buffer_shr(void *_buf, unsigned buf_len, unsigned count) diff --git a/src/helper/binarybuffer.h b/src/helper/binarybuffer.h index b035779..f1da8c4 100644 --- a/src/helper/binarybuffer.h +++ b/src/helper/binarybuffer.h @@ -235,7 +235,7 @@ void bit_copy_discard(struct bit_copy_queue *q); /* functions to convert to/from hex encoded buffer * used in ti-icdi driver and gdb server */ size_t unhexify(uint8_t *bin, const char *hex, size_t count); -int hexify(char *hex, const char *bin, int count, int out_maxlen); +size_t hexify(char *hex, const uint8_t *bin, size_t count, size_t out_maxlen); void buffer_shr(void *_buf, unsigned buf_len, unsigned count); #endif /* OPENOCD_HELPER_BINARYBUFFER_H */ diff --git a/src/jtag/drivers/ti_icdi_usb.c b/src/jtag/drivers/ti_icdi_usb.c index 7a6272f..171ac66 100644 --- a/src/jtag/drivers/ti_icdi_usb.c +++ b/src/jtag/drivers/ti_icdi_usb.c @@ -242,7 +242,8 @@ static int icdi_send_remote_cmd(void *handle, const char *data) struct icdi_usb_handle_s *h = handle; size_t cmd_len = sprintf(h->write_buffer, PACKET_START "qRcmd,"); - cmd_len += hexify(h->write_buffer + cmd_len, data, 0, h->max_packet - cmd_len); + cmd_len += hexify(h->write_buffer + cmd_len, (const uint8_t *)data, + strlen(data), h->max_packet - cmd_len); return icdi_send_packet(handle, cmd_len); } @@ -512,7 +513,7 @@ static int icdi_usb_write_reg(void *handle, int num, uint32_t val) h_u32_to_le(buf, val); int cmd_len = snprintf(cmd, sizeof(cmd), "P%x=", num); - hexify(cmd + cmd_len, (const char *)buf, 4, sizeof(cmd)); + hexify(cmd + cmd_len, buf, 4, sizeof(cmd)); result = icdi_send_cmd(handle, cmd); if (result != ERROR_OK) diff --git a/src/rtos/linux.c b/src/rtos/linux.c index 31d6618..e5a4efc 100644 --- a/src/rtos/linux.c +++ b/src/rtos/linux.c @@ -1229,7 +1229,8 @@ int linux_thread_extra_info(struct target *target, sprintf(tmp_str_ptr, "%s", name); sprintf(tmp_str_ptr, "%s", temp->name); char *hex_str = calloc(1, strlen(tmp_str) * 2 + 1); - int pkt_len = hexify(hex_str, tmp_str, 0, strlen(tmp_str) * 2 + 1); + size_t pkt_len = hexify(hex_str, (const uint8_t *)tmp_str, + strlen(tmp_str), strlen(tmp_str) * 2 + 1); gdb_put_packet(connection, hex_str, pkt_len); free(hex_str); free(tmp_str); diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c index 6938336..84ee498 100644 --- a/src/rtos/rtos.c +++ b/src/rtos/rtos.c @@ -266,7 +266,9 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s } reply_len = snprintf(reply, sizeof(reply), "qSymbol:"); - reply_len += hexify(reply + reply_len, next_sym->symbol_name, 0, sizeof(reply) - reply_len); + reply_len += hexify(reply + reply_len, + (const uint8_t *)next_sym->symbol_name, strlen(next_sym->symbol_name), + sizeof(reply) - reply_len); done: gdb_put_packet(connection, reply, reply_len); @@ -321,7 +323,8 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa (size_t) (tmp_str_ptr - tmp_str)); char *hex_str = malloc(strlen(tmp_str) * 2 + 1); - int pkt_len = hexify(hex_str, tmp_str, 0, strlen(tmp_str) * 2 + 1); + size_t pkt_len = hexify(hex_str, (const uint8_t *)tmp_str, + strlen(tmp_str), strlen(tmp_str) * 2 + 1); gdb_put_packet(connection, hex_str, pkt_len); free(hex_str); diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index 6f111e1..fe00744 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -697,7 +697,8 @@ static int gdb_output_con(struct connection *connection, const char *line) return ERROR_GDB_BUFFER_TOO_SMALL; hex_buffer[0] = 'O'; - int pkt_len = hexify(hex_buffer + 1, line, bin_size, bin_size * 2 + 1); + size_t pkt_len = hexify(hex_buffer + 1, (const uint8_t *)line, bin_size, + bin_size * 2 + 1); int retval = gdb_put_packet(connection, hex_buffer, pkt_len + 1); free(hex_buffer); @@ -1407,7 +1408,7 @@ static int gdb_read_memory_packet(struct connection *connection, if (retval == ERROR_OK) { hex_buffer = malloc(len * 2 + 1); - int pkt_len = hexify(hex_buffer, (char *)buffer, len, len * 2 + 1); + size_t pkt_len = hexify(hex_buffer, buffer, len, len * 2 + 1); gdb_put_packet(connection, hex_buffer, pkt_len); diff --git a/src/server/tcl_server.c b/src/server/tcl_server.c index 15a8736..0077339 100644 --- a/src/server/tcl_server.c +++ b/src/server/tcl_server.c @@ -105,7 +105,7 @@ static int tcl_target_callback_trace_handler(struct target *target, if (tclc->tc_trace) { hex = malloc(hex_len); buf = malloc(max_len); - hexify(hex, (const char *)data, len, hex_len); + hexify(hex, data, len, hex_len); snprintf(buf, max_len, "%s%s%s", header, hex, trailer); tcl_output(connection, buf, strlen(buf)); free(hex); diff --git a/src/target/smp.c b/src/target/smp.c index 3dc6f6d..bdf81a0 100644 --- a/src/target/smp.c +++ b/src/target/smp.c @@ -64,7 +64,8 @@ int gdb_read_smp_packet(struct connection *connection, char hex_buffer[len * 2 + 1]; uint8_t buffer[len]; buf_set_u32(buffer, 0, len * 8, target->gdb_service->core[0]); - int pkt_len = hexify(hex_buffer, (char *)buffer, sizeof(buffer), sizeof(hex_buffer)); + size_t pkt_len = hexify(hex_buffer, buffer, sizeof(buffer), + sizeof(hex_buffer)); retval = gdb_put_packet(connection, hex_buffer, pkt_len); } -- cgit v1.1 From 1d8b6b743416bfda8f82c80aa2278c2d88e2afaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vianney=20le=20Cl=C3=A9ment=20de=20Saint-Marcq?= Date: Tue, 2 Jun 2015 16:55:42 +0200 Subject: jtag/drivers/openjtag: Add support for Cypress CY7C65215 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Cypress CY7C65215 Dual Channel USB-Serial Bridge Controller [1] understands the OpenJTAG protocol over a proprietary USB interface. This patch adds support for the CY7C65215 to the openjtag interface driver. A new configuration option, `openjtag_variant`, allows to select the transport to use. Libusb (1.x or 0.1) is now a hard dependency of the openjtag driver. This should not be a big issue as libftdi also depends on it. [1] http://www.cypress.com/?rID=82870 Change-Id: I55ffb3fd9e006eb311e405d9fb836bb119644bfd Signed-off-by: Vianney le Clément de Saint-Marcq Signed-off-by: Ricardo Ribalda Delgado Reviewed-on: http://openocd.zylin.com/2805 Tested-by: jenkins Reviewed-by: Jiri Kastner Reviewed-by: Paul Fertser --- configure.ac | 7 ++ doc/openocd.texi | 21 ++++ src/jtag/drivers/openjtag.c | 273 +++++++++++++++++++++++++++++++++++++++----- 3 files changed, 275 insertions(+), 26 deletions(-) diff --git a/configure.ac b/configure.ac index a47a184..1e6be14 100644 --- a/configure.ac +++ b/configure.ac @@ -782,6 +782,13 @@ PROCESS_ADAPTERS([USB0_ADAPTERS], [$use_libusb0 = yes], [libusb-0.1]) PROCESS_ADAPTERS([HIDAPI_ADAPTERS], [$use_hidapi = yes], [hidapi]) PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], [$use_libusb1 = yes -a $use_internal_libjaylink = yes -o $HAVE_LIBJAYLINK = yes], [libusb-1.x or libjaylink-0.1]) +if test $build_openjtag = yes; then + if test $use_libusb1 != yes -a $use_libusb0 != yes; then + AC_MSG_ERROR([libusb-1.x or libusb-0.1 is required for the OpenJTAG Programmer]) + build_openjtag=no + fi +fi + if test $enable_stlink != no -o $enable_ti_icdi != no; then AC_DEFINE([BUILD_HLADAPTER], [1], [1 if you want the High Level JTAG driver.]) else diff --git a/doc/openocd.texi b/doc/openocd.texi index 1cca4ab..7c2152b 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2912,6 +2912,27 @@ pinout. @end deffn +@deffn {Interface Driver} {openjtag} +OpenJTAG compatible USB adapter. +This defines some driver-specific commands: + +@deffn {Config Command} {openjtag_variant} variant +Specifies the variant of the OpenJTAG adapter (see @uref{http://www.openjtag.org/}). +Currently valid @var{variant} values include: + +@itemize @minus +@item @b{standard} Standard variant (default). +@item @b{cy7c65215} Cypress CY7C65215 Dual Channel USB-Serial Bridge Controller +(see @uref{http://www.cypress.com/?rID=82870}). +@end itemize +@end deffn + +@deffn {Config Command} {openjtag_device_desc} string +The USB device description string of the adapter. +This value is only used with the standard variant. +@end deffn +@end deffn + @section Transport Configuration @cindex Transport As noted earlier, depending on the version of OpenOCD you use, diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index 5d1084c..bb0ff74 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -1,6 +1,10 @@ /******************************************************************************* * Driver for OpenJTAG Project (www.openjtag.org) * - * Compatible with libftdi driver. * + * Compatible with libftdi and ftd2xx drivers. * + * * + * Cypress CY7C65215 support * + * Copyright (C) 2015 Vianney le Clément de Saint-Marcq, Essensium NV * + * * * * * Copyright (C) 2010 by Ivan Meleca * * * @@ -41,7 +45,18 @@ #include #include -#include "usb_common.h" +#include "libusb_common.h" + +static enum { + OPENJTAG_VARIANT_STANDARD, + OPENJTAG_VARIANT_CY7C65215, +} openjtag_variant = OPENJTAG_VARIANT_STANDARD; + +static const char * const openjtag_variant_names[] = { + "standard", + "cy7c65215", + NULL +}; /* * OpenJTAG-OpenOCD state conversion @@ -96,10 +111,24 @@ static uint8_t usb_rx_buf[OPENJTAG_BUFFER_SIZE]; static struct openjtag_scan_result openjtag_scan_result_buffer[OPENJTAG_MAX_PENDING_RESULTS]; static int openjtag_scan_result_count; -/* Openocd usb handler */ -struct openocd { - struct usb_dev_handle *usb_handle; -}; +static jtag_libusb_device_handle *usbh; + +/* CY7C65215 model only */ +#define CY7C65215_JTAG_REQUEST 0x40 /* bmRequestType: vendor host-to-device */ +#define CY7C65215_JTAG_ENABLE 0xD0 /* bRequest: enable JTAG */ +#define CY7C65215_JTAG_DISABLE 0xD1 /* bRequest: disable JTAG */ +#define CY7C65215_JTAG_READ 0xD2 /* bRequest: read buffer */ +#define CY7C65215_JTAG_WRITE 0xD3 /* bRequest: write buffer */ + +#define CY7C65215_USB_TIMEOUT 100 + +static const uint16_t cy7c65215_vids[] = {0x04b4, 0}; +static const uint16_t cy7c65215_pids[] = {0x0007, 0}; + +#define CY7C65215_JTAG_CLASS 0xff +#define CY7C65215_JTAG_SUBCLASS 0x04 + +static unsigned int ep_in, ep_out; #ifdef _DEBUG_USB_COMMS_ @@ -185,7 +214,7 @@ static int8_t openjtag_get_tap_state(int8_t state) } } -static int openjtag_buf_write( +static int openjtag_buf_write_standard( uint8_t *buf, int size, uint32_t *bytes_written) { int retval; @@ -205,8 +234,54 @@ static int openjtag_buf_write( return ERROR_OK; } -static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read) +static int openjtag_buf_write_cy7c65215( + uint8_t *buf, int size, uint32_t *bytes_written) +{ + int ret; + +#ifdef _DEBUG_USB_COMMS_ + openjtag_debug_buffer(buf, size, DEBUG_TYPE_WRITE); +#endif + + if (size == 0) { + *bytes_written = 0; + return ERROR_OK; + } + + ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST, + CY7C65215_JTAG_WRITE, size, 0, + NULL, 0, CY7C65215_USB_TIMEOUT); + if (ret < 0) { + LOG_ERROR("vendor command failed, error %d", ret); + return ERROR_JTAG_DEVICE_ERROR; + } + + ret = jtag_libusb_bulk_write(usbh, ep_out, (char *)buf, size, + CY7C65215_USB_TIMEOUT); + if (ret < 0) { + LOG_ERROR("bulk write failed, error %d", ret); + return ERROR_JTAG_DEVICE_ERROR; + } + *bytes_written = ret; + + return ERROR_OK; +} + +static int openjtag_buf_write( + uint8_t *buf, int size, uint32_t *bytes_written) +{ + switch (openjtag_variant) { + case OPENJTAG_VARIANT_CY7C65215: + return openjtag_buf_write_cy7c65215(buf, size, bytes_written); + default: + return openjtag_buf_write_standard(buf, size, bytes_written); + } +} + +static int openjtag_buf_read_standard( + uint8_t *buf, uint32_t qty, uint32_t *bytes_read) { + int retval; int timeout = 5; @@ -231,6 +306,50 @@ static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read) return ERROR_OK; } +static int openjtag_buf_read_cy7c65215( + uint8_t *buf, uint32_t qty, uint32_t *bytes_read) +{ + int ret; + + if (qty == 0) { + *bytes_read = 0; + goto out; + } + + ret = jtag_libusb_control_transfer(usbh, CY7C65215_JTAG_REQUEST, + CY7C65215_JTAG_READ, qty, 0, + NULL, 0, CY7C65215_USB_TIMEOUT); + if (ret < 0) { + LOG_ERROR("vendor command failed, error %d", ret); + return ERROR_JTAG_DEVICE_ERROR; + } + + ret = jtag_libusb_bulk_read(usbh, ep_in, (char *)buf, qty, + CY7C65215_USB_TIMEOUT); + if (ret < 0) { + LOG_ERROR("bulk read failed, error %d", ret); + return ERROR_JTAG_DEVICE_ERROR; + } + *bytes_read = ret; + +out: +#ifdef _DEBUG_USB_COMMS_ + openjtag_debug_buffer(buf, *bytes_read, DEBUG_TYPE_READ); +#endif + + return ERROR_OK; +} + +static int openjtag_buf_read(uint8_t *buf, uint32_t qty, uint32_t *bytes_read) +{ + switch (openjtag_variant) { + case OPENJTAG_VARIANT_CY7C65215: + return openjtag_buf_read_cy7c65215(buf, qty, bytes_read); + default: + return openjtag_buf_read_standard(buf, qty, bytes_read); + } +} + static int openjtag_sendcommand(uint8_t cmd) { uint32_t written; @@ -275,16 +394,10 @@ static int openjtag_speed(int speed) return ERROR_OK; } -static int openjtag_init(void) +static int openjtag_init_standard(void) { uint8_t latency_timer; - usb_tx_buf_offs = 0; - usb_rx_buf_len = 0; - openjtag_scan_result_count = 0; - - LOG_DEBUG("'openjtag' interface using libftdi"); - /* Open by device description */ if (openjtag_device_desc == NULL) { LOG_WARNING("no openjtag device description specified, " @@ -330,16 +443,70 @@ static int openjtag_init(void) return ERROR_JTAG_INIT_FAILED; } - /* OpenJTAG speed */ - openjtag_sendcommand(0xE0); /*Start at slowest adapter speed*/ + return ERROR_OK; +} + +static int openjtag_init_cy7c65215(void) +{ + int ret; + + usbh = NULL; + ret = jtag_libusb_open(cy7c65215_vids, cy7c65215_pids, NULL, &usbh); + if (ret != ERROR_OK) { + LOG_ERROR("unable to open cy7c65215 device"); + goto err; + } + + ret = jtag_libusb_choose_interface(usbh, &ep_in, &ep_out, + CY7C65215_JTAG_CLASS, + CY7C65215_JTAG_SUBCLASS, -1); + if (ret != ERROR_OK) { + LOG_ERROR("unable to claim JTAG interface"); + goto err; + } - /* MSB */ - openjtag_sendcommand(0x75); + ret = jtag_libusb_control_transfer(usbh, + CY7C65215_JTAG_REQUEST, + CY7C65215_JTAG_ENABLE, + 0, 0, NULL, 0, CY7C65215_USB_TIMEOUT); + if (ret < 0) { + LOG_ERROR("could not enable JTAG module"); + goto err; + } return ERROR_OK; + +err: + if (usbh != NULL) + jtag_libusb_close(usbh); + return ERROR_JTAG_INIT_FAILED; } -static int openjtag_quit(void) +static int openjtag_init(void) +{ + int ret; + + usb_tx_buf_offs = 0; + usb_rx_buf_len = 0; + openjtag_scan_result_count = 0; + + switch (openjtag_variant) { + case OPENJTAG_VARIANT_CY7C65215: + ret = openjtag_init_cy7c65215(); + break; + default: + ret = openjtag_init_standard(); + } + if (ret != ERROR_OK) + return ret; + + openjtag_speed(375); /* Start at slowest adapter speed */ + openjtag_sendcommand(0x75); /* MSB */ + + return ERROR_OK; +} + +static int openjtag_quit_standard(void) { ftdi_usb_close(&ftdic); ftdi_deinit(&ftdic); @@ -347,6 +514,32 @@ static int openjtag_quit(void) return ERROR_OK; } +static int openjtag_quit_cy7c65215(void) +{ + int ret; + + ret = jtag_libusb_control_transfer(usbh, + CY7C65215_JTAG_REQUEST, + CY7C65215_JTAG_DISABLE, + 0, 0, NULL, 0, CY7C65215_USB_TIMEOUT); + if (ret < 0) + LOG_WARNING("could not disable JTAG module"); + + jtag_libusb_close(usbh); + + return ERROR_OK; +} + +static int openjtag_quit(void) +{ + switch (openjtag_variant) { + case OPENJTAG_VARIANT_CY7C65215: + return openjtag_quit_cy7c65215(); + default: + return openjtag_quit_standard(); + } +} + static void openjtag_write_tap_buffer(void) { uint32_t written; @@ -379,8 +572,8 @@ static int openjtag_execute_tap_queue(void) uint8_t *buffer = openjtag_scan_result_buffer[res_count].buffer; - while (len) { - if (len <= 8) { + while (len > 0) { + if (len <= 8 && openjtag_variant != OPENJTAG_VARIANT_CY7C65215) { DEBUG_JTAG_IO("bits < 8 buf = 0x%X, will be 0x%X", usb_rx_buf[rx_offs], usb_rx_buf[rx_offs] >> (8 - len)); buffer[count] = usb_rx_buf[rx_offs] >> (8 - len); @@ -567,11 +760,14 @@ static void openjtag_execute_runtest(struct jtag_command *cmd) if (cmd->cmd.runtest->num_cycles > 16) LOG_WARNING("num_cycles > 16 on run test"); - uint8_t command; - command = 7; - command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4; + if (openjtag_variant != OPENJTAG_VARIANT_CY7C65215 || + cmd->cmd.runtest->num_cycles) { + uint8_t command; + command = 7; + command |= ((cmd->cmd.runtest->num_cycles - 1) & 0x0F) << 4; - openjtag_add_byte(command); + openjtag_add_byte(command); + } tap_set_end_state(end_state); if (tap_get_end_state() != tap_get_state()) { @@ -659,6 +855,24 @@ COMMAND_HANDLER(openjtag_handle_device_desc_command) return ERROR_OK; } +COMMAND_HANDLER(openjtag_handle_variant_command) +{ + if (CMD_ARGC == 1) { + const char * const *name = openjtag_variant_names; + int variant = 0; + for (; *name; name++, variant++) { + if (strcasecmp(CMD_ARGV[0], *name) == 0) { + openjtag_variant = variant; + return ERROR_OK; + } + } + LOG_ERROR("unknown openjtag variant '%s'", CMD_ARGV[0]); + } else { + LOG_ERROR("require exactly one argument to " + "openjtag_variant "); + } + return ERROR_OK; +} static const struct command_registration openjtag_command_handlers[] = { { @@ -668,6 +882,13 @@ static const struct command_registration openjtag_command_handlers[] = { .help = "set the USB device description of the OpenJTAG", .usage = "description-string", }, + { + .name = "openjtag_variant", + .handler = openjtag_handle_variant_command, + .mode = COMMAND_CONFIG, + .help = "set the OpenJTAG variant", + .usage = "variant-string", + }, COMMAND_REGISTRATION_DONE }; -- cgit v1.1 From 097aa2979e0eefa822d4a16f055dcf9fc31e3dde Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Sun, 13 Nov 2016 13:23:08 +0100 Subject: cortex_m: allow setting debug ap during create This patch adds a Cortex-M private configuration option that allows setting the acess point during target creation. This circumvents situations in hybrid systems when the correct access point can not be automatically detected. Change-Id: If313a5250e6e66509bb9080f3498feab7781dced Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3639 Tested-by: jenkins Reviewed-by: Paul Fertser --- doc/openocd.texi | 4 ++++ src/target/arm_adi_v5.c | 35 +++++++++++++++++++++++++++++++++++ src/target/arm_adi_v5.h | 6 ++++++ src/target/cortex_m.c | 23 ++++++++++++++++++----- src/target/cortex_m.h | 2 ++ src/target/target.h | 1 + 6 files changed, 66 insertions(+), 5 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 7c2152b..b47d2c4 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4152,6 +4152,10 @@ The value should normally correspond to a static mapping for the scan and after a reset. A manual call to arp_examine is required to access the target for debugging. +@item @code{-ap-num} @var{ap_number} -- set DAP access port for target, +@var{ap_number} is the numeric index of the DAP AP the target is connected to. +Use this option with systems where multiple, independent cores are connected +to separate access ports of the same DAP. @end itemize @end deffn diff --git a/src/target/arm_adi_v5.c b/src/target/arm_adi_v5.c index 39f2b39..eafc2dd 100644 --- a/src/target/arm_adi_v5.c +++ b/src/target/arm_adi_v5.c @@ -1359,6 +1359,41 @@ static int dap_info_command(struct command_context *cmd_ctx, return ERROR_OK; } +int adiv5_jim_configure(struct target *target, Jim_GetOptInfo *goi) +{ + struct adiv5_private_config *pc; + const char *arg; + jim_wide ap_num; + int e; + + /* check if argv[0] is for us */ + arg = Jim_GetString(goi->argv[0], NULL); + if (strcmp(arg, "-ap-num")) + return JIM_CONTINUE; + + e = Jim_GetOpt_String(goi, &arg, NULL); + if (e != JIM_OK) + return e; + + if (goi->argc == 0) { + Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "-ap-num ?ap-number? ..."); + return JIM_ERR; + } + + e = Jim_GetOpt_Wide(goi, &ap_num); + if (e != JIM_OK) + return e; + + if (target->private_config == NULL) { + pc = calloc(1, sizeof(struct adiv5_private_config)); + target->private_config = pc; + pc->ap_num = ap_num; + } + + + return JIM_OK; +} + COMMAND_HANDLER(handle_dap_info_command) { struct target *target = get_current_target(CMD_CTX); diff --git a/src/target/arm_adi_v5.h b/src/target/arm_adi_v5.h index 3220d8b..bf9cb5c 100644 --- a/src/target/arm_adi_v5.h +++ b/src/target/arm_adi_v5.h @@ -504,4 +504,10 @@ int dap_to_jtag(struct target *target); extern const struct command_registration dap_command_handlers[]; +struct adiv5_private_config { + int ap_num; +}; + +extern int adiv5_jim_configure(struct target *target, Jim_GetOptInfo *goi); + #endif /* OPENOCD_TARGET_ARM_ADI_V5_H */ diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index f674cc5..36a7746 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -1709,6 +1709,7 @@ void cortex_m_deinit_target(struct target *target) cortex_m_dwt_free(target); armv7m_free_reg_cache(target); + free(target->private_config); free(cortex_m); } @@ -1912,11 +1913,15 @@ int cortex_m_examine(struct target *target) return retval; } - /* Search for the MEM-AP */ - retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7m->debug_ap); - if (retval != ERROR_OK) { - LOG_ERROR("Could not find MEM-AP to control the core"); - return retval; + if (cortex_m->apsel < 0) { + /* Search for the MEM-AP */ + retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7m->debug_ap); + if (retval != ERROR_OK) { + LOG_ERROR("Could not find MEM-AP to control the core"); + return retval; + } + } else { + armv7m->debug_ap = dap_ap(swjdp, cortex_m->apsel); } /* Leave (only) generic DAP stuff for debugport_init(); */ @@ -2180,6 +2185,13 @@ static int cortex_m_target_create(struct target *target, Jim_Interp *interp) cortex_m->common_magic = CORTEX_M_COMMON_MAGIC; cortex_m_init_arch_info(target, cortex_m, target->tap); + if (target->private_config != NULL) { + struct adiv5_private_config *pc = + (struct adiv5_private_config *)target->private_config; + cortex_m->apsel = pc->ap_num; + } else + cortex_m->apsel = -1; + return ERROR_OK; } @@ -2441,6 +2453,7 @@ struct target_type cortexm_target = { .commands = cortex_m_command_handlers, .target_create = cortex_m_target_create, + .target_jim_configure = adiv5_jim_configure, .init_target = cortex_m_init_target, .examine = cortex_m_examine, .deinit_target = cortex_m_deinit_target, diff --git a/src/target/cortex_m.h b/src/target/cortex_m.h index eabaac4..3d9714b 100644 --- a/src/target/cortex_m.h +++ b/src/target/cortex_m.h @@ -188,6 +188,8 @@ struct cortex_m_common { enum cortex_m_isrmasking_mode isrmasking_mode; struct armv7m_common armv7m; + + int apsel; }; static inline struct cortex_m_common * diff --git a/src/target/target.h b/src/target/target.h index 7f6ac14..e86b700 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -173,6 +173,7 @@ struct target { struct debug_msg_receiver *dbgmsg; /* list of debug message receivers */ uint32_t dbg_msg_enabled; /* debug message status */ void *arch_info; /* architecture specific information */ + void *private_config; /* pointer to target specific config data (for jim_configure hook) */ struct target *next; /* next target in list */ int display; /* display async info in telnet session. Do not display -- cgit v1.1 From a9d30ceafe01e35a514787ceca10072777b271bf Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Sun, 6 Nov 2016 13:22:42 +0100 Subject: configure: Detect libftdi using pkgconfig Auto-enable libftdi adapter drivers if found, just like libusb and hidapi based adapters. Change-Id: I71a10c90c8b999c4cae9b4f8fb5e97971d03083b Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3238 Tested-by: jenkins Reviewed-by: Xiaofan Reviewed-by: Paul Fertser --- configure.ac | 135 ++++++++++++----------------------------------------------- 1 file changed, 26 insertions(+), 109 deletions(-) diff --git a/configure.ac b/configure.ac index 1e6be14..d43525e 100644 --- a/configure.ac +++ b/configure.ac @@ -190,6 +190,11 @@ m4_define([USB0_ADAPTERS], m4_define([HIDAPI_ADAPTERS], [[[cmsis_dap], [CMSIS-DAP Compliant Debugger], [CMSIS_DAP]]]) +m4_define([LIBFTDI_ADAPTERS], + [[[usb_blaster], [Altera USB-Blaster Compatible], [USB_BLASTER]], + [[presto], [ASIX Presto Adapter], [PRESTO]], + [[openjtag], [OpenJTAG Adapter], [OPENJTAG]]]) + m4_define([LIBJAYLINK_ADAPTERS], [[[jlink], [SEGGER J-Link Programmer], [JLINK]]]) @@ -294,7 +299,14 @@ m4_define([AC_ARG_ADAPTERS], [ ]) ]) -AC_ARG_ADAPTERS([USB1_ADAPTERS, USB_ADAPTERS, USB0_ADAPTERS, HIDAPI_ADAPTERS, LIBJAYLINK_ADAPTERS], [auto]) +AC_ARG_ADAPTERS([ + USB1_ADAPTERS, + USB_ADAPTERS, + USB0_ADAPTERS, + HIDAPI_ADAPTERS, + LIBFTDI_ADAPTERS, + LIBJAYLINK_ADAPTERS + ],[auto]) AC_ARG_ENABLE([parport], AS_HELP_STRING([--enable-parport], [Enable building the pc parallel port driver]), @@ -314,10 +326,6 @@ AC_ARG_ENABLE([jtag_vpi], AS_HELP_STRING([--enable-jtag_vpi], [Enable building support for JTAG VPI]), [build_jtag_vpi=$enableval], [build_jtag_vpi=no]) -AC_ARG_ENABLE([usb_blaster_libftdi], - AS_HELP_STRING([--enable-usb_blaster_libftdi], [Enable building support for the Altera USB-Blaster using the libftdi driver]), - [build_usb_blaster=$enableval], [build_usb_blaster=no]) - AC_ARG_ENABLE([amtjtagaccel], AS_HELP_STRING([--enable-amtjtagaccel], [Enable building the Amontec JTAG-Accelerator driver]), [build_amtjtagaccel=$enableval], [build_amtjtagaccel=no]) @@ -360,14 +368,6 @@ AC_ARG_ENABLE([gw16012], AS_HELP_STRING([--enable-gw16012], [Enable building support for the Gateworks GW16012 JTAG Programmer]), [build_gw16012=$enableval], [build_gw16012=no]) -AC_ARG_ENABLE([presto_libftdi], - AS_HELP_STRING([--enable-presto_libftdi], [Enable building support for ASIX Presto Programmer using the libftdi library]), - [build_presto=$enableval], [build_presto=no]) - -AC_ARG_ENABLE([openjtag_ftdi], - AS_HELP_STRING([--enable-openjtag_ftdi], [Enable building support for the OpenJTAG Programmer with libftdi library]), - [build_openjtag=$enableval], [build_openjtag=no]) - AC_ARG_ENABLE([oocd_trace], AS_HELP_STRING([--enable-oocd_trace], [Enable building support for some prototype OpenOCD+trace ETM capture hardware]), @@ -580,12 +580,6 @@ else AC_DEFINE([BUILD_BITBANG], [0], [0 if you don't want a bitbang interface.]) fi -if test $build_usb_blaster = yes; then - AC_DEFINE([BUILD_USB_BLASTER], [1], [1 if you want libftdi usb_blaster.]) -else - AC_DEFINE([BUILD_USB_BLASTER], [0], [0 if you don't want libftdi usb_blaster.]) -fi - if test $build_jtag_vpi = yes; then AC_DEFINE([BUILD_JTAG_VPI], [1], [1 if you want JTAG VPI.]) else @@ -604,26 +598,12 @@ else AC_DEFINE([BUILD_GW16012], [0], [0 if you don't want the Gateworks GW16012 driver.]) fi -if test $build_presto = yes; then - build_bitq=yes - AC_DEFINE([BUILD_PRESTO], [1], [1 if you want the ASIX PRESTO driver using libftdi.]) -else - AC_DEFINE([BUILD_PRESTO], [0], [0 if you don't want the ASIX PRESTO driver using libftdi.]) -fi - if test $build_bitq = yes; then AC_DEFINE([BUILD_BITQ], [1], [1 if you want a bitq interface.]) else AC_DEFINE([BUILD_BITQ], [0], [0 if you don't want a bitq interface.]) fi - -if test $build_openjtag = yes; then - AC_DEFINE([BUILD_OPENJTAG], [1], [1 if you want the OpenJTAG driver.]) -else - AC_DEFINE([BUILD_OPENJTAG], [0], [0 if you don't want the OpenJTAG driver.]) -fi - if test $build_oocd_trace = yes; then AC_DEFINE([BUILD_OOCD_TRACE], [1], [1 if you want the OpenOCD+trace ETM capture driver.]) else @@ -658,77 +638,6 @@ else AC_DEFINE([BUILD_SYSFSGPIO], [0], [0 if you don't want SysfsGPIO driver.]) fi -if test $build_usb_blaster = yes -o $build_openjtag = yes -o $build_presto = yes; then - - # we can have libftdi or libftdi1, so check it and use the latest one - PKG_CHECK_MODULES([LIBFTDI], [libftdi1], [use_libftdi=yes], [use_libftdi=no]) - if test $use_libftdi = no; then - PKG_CHECK_MODULES([LIBFTDI], [libftdi], [use_libftdi=yes], [use_libftdi=no]) - fi - if test $use_libftdi = no; then - AC_MSG_ERROR([The libftdi driver is not present on your system.]) - fi - - # - # Try to build a small program. - AC_MSG_CHECKING([Build & Link with libftdi...]) - - LDFLAGS_SAVE=$LDFLAGS - CFLAGS_SAVE=$CFLAGS - LIBS_SAVE=$LIBS - _LDFLAGS=`eval echo $LDFLAGS` - _CFLAGS=`eval echo $CFLAGS` - _LIBS=`eval echo $LIBS` - LDFLAGS=$_LDFLAGS - CFLAGS="$_CFLAGS $LIBFTDI_CFLAGS" - LIBS="$_LIBS $LIBFTDI_LIBS" - - AC_RUN_IFELSE([AC_LANG_PROGRAM([[ -#include -#include - ]], [[ - struct ftdi_context *p; - p = ftdi_new(); - if( p != NULL ){ - return 0; - } else { - fprintf( stderr, "calling ftdi_new() failed\n"); - return 1; - } - ]])], [ - AC_MSG_RESULT([Success]) - ], [ - AC_MSG_ERROR([Cannot build & run test program using libftdi]) - ], [ - AC_MSG_RESULT([Skipping as we are cross-compiling, trying build only]) - AC_SEARCH_LIBS([ftdi_new], [], [], [AC_MSG_ERROR([Cannot link with libftdi])]) - ]) - -AC_MSG_CHECKING([for libftdi FT232H device support]) -AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ -#include -#include - ]], [[ -enum ftdi_chip_type x = TYPE_232H; - ]])], [ - AC_DEFINE([HAS_ENUM_FT232H], [1], - [Support FT232H with libftdi.]) - has_enum_ft232h=yes - ], [ - has_enum_ft232h=no - ]) - AC_MSG_RESULT([$has_enum_ft232h]) - - if test $has_enum_ft232h = no; then - AC_MSG_WARN([You need a newer libftdi version (0.20 or later).]) - fi - - # Restore the 'unexpanded ldflags' - LDFLAGS=$LDFLAGS_SAVE - CFLAGS=$CFLAGS_SAVE - LIBS=$LIBS_SAVE -fi - PKG_CHECK_MODULES([LIBUSB1], [libusb-1.0], [ use_libusb1=yes AC_DEFINE([HAVE_LIBUSB1], [1], [Define if you have libusb-1.x]) @@ -755,6 +664,10 @@ for hidapi_lib in hidapi hidapi-hidraw hidapi-libusb; do ]) done +PKG_CHECK_MODULES([LIBFTDI], [libftdi1], [use_libftdi=yes], [ + PKG_CHECK_MODULES([LIBFTDI], [libftdi], [use_libftdi=yes], [use_libftdi=no]) +]) + PKG_CHECK_MODULES([libjaylink], [libjaylink >= 0.1], [HAVE_LIBJAYLINK=yes], [HAVE_LIBJAYLINK=no]) @@ -780,6 +693,7 @@ PROCESS_ADAPTERS([USB1_ADAPTERS], [$use_libusb1 = yes], [libusb-1.x]) PROCESS_ADAPTERS([USB_ADAPTERS], [$use_libusb1 = yes -o $use_libusb0 = yes], [libusb-1.x or libusb-0.1]) PROCESS_ADAPTERS([USB0_ADAPTERS], [$use_libusb0 = yes], [libusb-0.1]) PROCESS_ADAPTERS([HIDAPI_ADAPTERS], [$use_hidapi = yes], [hidapi]) +PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], [$use_libftdi = yes], [libftdi]) PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], [$use_libusb1 = yes -a $use_internal_libjaylink = yes -o $HAVE_LIBJAYLINK = yes], [libusb-1.x or libjaylink-0.1]) if test $build_openjtag = yes; then @@ -807,6 +721,11 @@ if test $enable_jlink != no; then fi fi +# Presto needs the bitq module +if test $enable_presto != no; then + build_bitq=yes +fi + AM_CONDITIONAL([RELEASE], [test $build_release = yes]) AM_CONDITIONAL([PARPORT], [test $build_parport = yes]) AM_CONDITIONAL([DUMMY], [test $build_dummy = yes]) @@ -819,12 +738,9 @@ AM_CONDITIONAL([AT91RM9200], [test $build_at91rm9200 = yes]) AM_CONDITIONAL([BCM2835GPIO], [test $build_bcm2835gpio = yes]) AM_CONDITIONAL([BITBANG], [test $build_bitbang = yes]) AM_CONDITIONAL([JTAG_VPI], [test $build_jtag_vpi = yes -o $build_jtag_vpi = yes]) -AM_CONDITIONAL([USB_BLASTER_DRIVER], [test $build_usb_blaster = yes -o $enable_usb_blaster_2 != no]) -AM_CONDITIONAL([USB_BLASTER], [test $build_usb_blaster = yes]) +AM_CONDITIONAL([USB_BLASTER_DRIVER], [test $enable_usb_blaster != no -o $enable_usb_blaster_2 != no]) AM_CONDITIONAL([AMTJTAGACCEL], [test $build_amtjtagaccel = yes]) AM_CONDITIONAL([GW16012], [test $build_gw16012 = yes]) -AM_CONDITIONAL([PRESTO], [test $build_presto = yes]) -AM_CONDITIONAL([OPENJTAG], [test $build_openjtag = yes]) AM_CONDITIONAL([OOCD_TRACE], [test $build_oocd_trace = yes]) AM_CONDITIONAL([REMOTE_BITBANG], [test $build_remote_bitbang = yes]) AM_CONDITIONAL([BUSPIRATE], [test $build_buspirate = yes]) @@ -837,6 +753,7 @@ AM_CONDITIONAL([IS_WIN32], [test $is_win32 = yes]) AM_CONDITIONAL([IS_DARWIN], [test $is_darwin = yes]) AM_CONDITIONAL([BITQ], [test $build_bitq = yes]) AM_CONDITIONAL([CMSIS_DAP], [test $use_hidapi = yes]) +AM_CONDITIONAL([USE_LIBFTDI], [test $use_libftdi = yes]) AM_CONDITIONAL([MINIDRIVER], [test $build_minidriver = yes]) AM_CONDITIONAL([MINIDRIVER_DUMMY], [test $build_minidriver_dummy = yes]) @@ -923,7 +840,7 @@ echo echo OpenOCD configuration summary echo -------------------------------------------------- m4_foreach([adapter], [USB1_ADAPTERS, USB_ADAPTERS, USB0_ADAPTERS, - HIDAPI_ADAPTERS, LIBJAYLINK_ADAPTERS], + HIDAPI_ADAPTERS, LIBFTDI_ADAPTERS, LIBJAYLINK_ADAPTERS], [s=m4_format(["%-40s"], ADAPTER_DESC([adapter])) case $ADAPTER_VAR([adapter]) in auto) -- cgit v1.1 From e311b2f097eee38f9a05eae909b1bce64b58a8ba Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Mon, 15 Feb 2016 23:52:39 +0100 Subject: configure: Remove conflicting CMSIS_DAP conditional It's already defined by PROCESS_ADAPTERS. Change-Id: I3bbcb0f77c645e9c5a98c2d5069c178358d1516b Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3239 Tested-by: jenkins Reviewed-by: Paul Fertser --- configure.ac | 1 - 1 file changed, 1 deletion(-) diff --git a/configure.ac b/configure.ac index d43525e..95d76c9 100644 --- a/configure.ac +++ b/configure.ac @@ -752,7 +752,6 @@ AM_CONDITIONAL([IS_MINGW], [test $is_mingw = yes]) AM_CONDITIONAL([IS_WIN32], [test $is_win32 = yes]) AM_CONDITIONAL([IS_DARWIN], [test $is_darwin = yes]) AM_CONDITIONAL([BITQ], [test $build_bitq = yes]) -AM_CONDITIONAL([CMSIS_DAP], [test $use_hidapi = yes]) AM_CONDITIONAL([USE_LIBFTDI], [test $use_libftdi = yes]) AM_CONDITIONAL([MINIDRIVER], [test $build_minidriver = yes]) -- cgit v1.1 From fff81c3baac920dabce4093f53a22bab209bf870 Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Tue, 16 Feb 2016 23:19:28 +0100 Subject: configure: Remove unused BUILD_BITQ and BUILD_BITBANG define Change-Id: Ibfb5e414dd77d2ce4b835007722eb18da3820f3a Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3668 Tested-by: jenkins Reviewed-by: Paul Fertser --- configure.ac | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/configure.ac b/configure.ac index 95d76c9..e7c6ee1 100644 --- a/configure.ac +++ b/configure.ac @@ -574,12 +574,6 @@ else AC_DEFINE([PARPORT_USE_GIVEIO], [0], [0 if you don't want parport to use giveio.]) fi -if test $build_bitbang = yes; then - AC_DEFINE([BUILD_BITBANG], [1], [1 if you want a bitbang interface.]) -else - AC_DEFINE([BUILD_BITBANG], [0], [0 if you don't want a bitbang interface.]) -fi - if test $build_jtag_vpi = yes; then AC_DEFINE([BUILD_JTAG_VPI], [1], [1 if you want JTAG VPI.]) else @@ -598,12 +592,6 @@ else AC_DEFINE([BUILD_GW16012], [0], [0 if you don't want the Gateworks GW16012 driver.]) fi -if test $build_bitq = yes; then - AC_DEFINE([BUILD_BITQ], [1], [1 if you want a bitq interface.]) -else - AC_DEFINE([BUILD_BITQ], [0], [0 if you don't want a bitq interface.]) -fi - if test $build_oocd_trace = yes; then AC_DEFINE([BUILD_OOCD_TRACE], [1], [1 if you want the OpenOCD+trace ETM capture driver.]) else -- cgit v1.1 From 3a4af874874ad623553ac061a771d428bce1e814 Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Fri, 4 Nov 2016 21:44:19 +0100 Subject: Remove build date from banner for releases In support for reproducible builds, see https://wiki.debian.org/ReproducibleBuilds Fixes Debian bug #834316. Change-Id: Id81ec72a87bf6dd99abfd2a0ae074658111bc9a3 Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3866 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/Makefile.am | 3 ++- src/openocd.c | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Makefile.am b/src/Makefile.am index fe40336..bad4153 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -38,7 +38,7 @@ noinst_HEADERS = \ hello.h \ openocd.h -libopenocd_la_CPPFLAGS = -DPKGBLDDATE=\"`date +%F-%R`\" +libopenocd_la_CPPFLAGS = # banner output includes RELSTR appended to $VERSION from the configure script # guess-rev.sh returns either a repository version ID or "-snapshot" @@ -48,6 +48,7 @@ libopenocd_la_CPPFLAGS += -DGITVERSION=\"\" else libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\" libopenocd_la_CPPFLAGS += -DGITVERSION=\"`cd $(top_srcdir) && git describe`\" +libopenocd_la_CPPFLAGS += -DPKGBLDDATE=\"`date +%F-%R`\" endif # add default CPPFLAGS diff --git a/src/openocd.c b/src/openocd.c index b5bb44b..94fab3a 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -45,8 +45,13 @@ #include #endif +#ifdef PKGBLDDATE #define OPENOCD_VERSION \ "Open On-Chip Debugger " VERSION RELSTR " (" PKGBLDDATE ")" +#else +#define OPENOCD_VERSION \ + "Open On-Chip Debugger " VERSION RELSTR +#endif static const char openocd_startup_tcl[] = { #include "startup_tcl.inc" -- cgit v1.1 From cdba6ba0ad63d256f896c834b03732a5eefc7a13 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 10 Nov 2016 20:33:02 +0100 Subject: cortex_a: fix reset for SWD transport Change b0698501b0e789091e9f9f1427b32af304888769 fixed reset for i.MX6 and TI Sitara SoCs but broke reset for cortex-a targets that use SWD. This patch is a work- around that forces asserting SRST when SWD is used. Change-Id: I7e39f2a469b9b4b2b74ad48ba49f2eeb58528921 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3641 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/cortex_a.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index ed2f613..d0eac75 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -54,6 +54,7 @@ #include "target_type.h" #include "arm_opcodes.h" #include "arm_semihosting.h" +#include "jtag/swd.h" #include static int cortex_a_poll(struct target *target); @@ -1867,9 +1868,15 @@ static int cortex_a_assert_reset(struct target *target) /* REVISIT handle "pulls" cases, if there's * hardware that needs them to work. */ - if (target->reset_halt) - if (jtag_get_reset_config() & RESET_SRST_NO_GATING) - jtag_add_reset(0, 1); + + /* + * FIXME: fix reset when transport is SWD. This is a temporary + * work-around for release v0.10 that is not intended to stay! + */ + if (transport_is_swd() || + (target->reset_halt && (jtag_get_reset_config() & RESET_SRST_NO_GATING))) + jtag_add_reset(0, 1); + } else { LOG_ERROR("%s: how to reset?", target_name(target)); return ERROR_FAIL; -- cgit v1.1 From 1039ed3ff2138c9d0d820b143159738f8a73cb2e Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Wed, 2 Nov 2016 22:34:42 +0100 Subject: xscale: Move debug handler to contrib/loaders Avoid special rules to generate array at compile time by shipping the generated file. Convert to Makefile build like the other loaders. Change-Id: I5a05edddcfaff3d395086cd3aa33120f8a7aa9dc Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3864 Tested-by: jenkins Reviewed-by: Paul Fertser --- contrib/loaders/Makefile | 3 +- contrib/loaders/debug/xscale/Makefile | 33 ++ contrib/loaders/debug/xscale/debug_handler.S | 716 +++++++++++++++++++++++++ contrib/loaders/debug/xscale/debug_handler.inc | 101 ++++ contrib/loaders/debug/xscale/debug_handler.ld | 49 ++ contrib/loaders/debug/xscale/protocol.h | 68 +++ src/target/Makefile.am | 13 - src/target/xscale.c | 2 +- src/target/xscale/build.sh | 7 - src/target/xscale/debug_handler.S | 716 ------------------------- src/target/xscale/debug_handler.bin | Bin 1592 -> 0 bytes src/target/xscale/debug_handler.cmd | 49 -- src/target/xscale/protocol.h | 68 --- 13 files changed, 970 insertions(+), 855 deletions(-) create mode 100644 contrib/loaders/debug/xscale/Makefile create mode 100644 contrib/loaders/debug/xscale/debug_handler.S create mode 100644 contrib/loaders/debug/xscale/debug_handler.inc create mode 100644 contrib/loaders/debug/xscale/debug_handler.ld create mode 100644 contrib/loaders/debug/xscale/protocol.h delete mode 100755 src/target/xscale/build.sh delete mode 100644 src/target/xscale/debug_handler.S delete mode 100755 src/target/xscale/debug_handler.bin delete mode 100644 src/target/xscale/debug_handler.cmd delete mode 100644 src/target/xscale/protocol.h diff --git a/contrib/loaders/Makefile b/contrib/loaders/Makefile index 2e5eba8..31cccb5 100644 --- a/contrib/loaders/Makefile +++ b/contrib/loaders/Makefile @@ -12,7 +12,8 @@ ARM_CROSS_COMPILE ?= arm-none-eabi- arm_dirs = \ flash/fm4 \ flash/kinetis_ke \ - flash/xmc1xxx + flash/xmc1xxx \ + debug/xscale arm: for d in $(common_dirs); do \ diff --git a/contrib/loaders/debug/xscale/Makefile b/contrib/loaders/debug/xscale/Makefile new file mode 100644 index 0000000..a0455c7 --- /dev/null +++ b/contrib/loaders/debug/xscale/Makefile @@ -0,0 +1,33 @@ +BIN2C = ../../../../src/helper/bin2char.sh + +CROSS_COMPILE ?= arm-none-eabi- + +CC=$(CROSS_COMPILE)gcc +OBJCOPY=$(CROSS_COMPILE)objcopy +OBJDUMP=$(CROSS_COMPILE)objdump + +CFLAGS = -static -nostartfiles -mlittle-endian -Wa,-EL +LDFLAGS = -Tdebug_handler.ld + +all: debug_handler.inc + +.PHONY: clean + +.INTERMEDIATE: debug_handler.elf + +debug_handler.elf: protocol.h + +%.elf: %.S + $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ + +%.lst: %.elf + $(OBJDUMP) -S $< > $@ + +%.bin: %.elf + $(OBJCOPY) -Obinary $< $@ + +%.inc: %.bin + $(BIN2C) < $< > $@ + +clean: + -rm -f *.elf *.lst *.bin *.inc diff --git a/contrib/loaders/debug/xscale/debug_handler.S b/contrib/loaders/debug/xscale/debug_handler.S new file mode 100644 index 0000000..66dfa88 --- /dev/null +++ b/contrib/loaders/debug/xscale/debug_handler.S @@ -0,0 +1,716 @@ +/*************************************************************************** + * Copyright (C) 2006 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, see . * + ***************************************************************************/ +#include "protocol.h" + + .text + .align 4 + +@ Disable thumb mode + .code 32 + +@ send word to debugger +.macro m_send_to_debugger reg +1: + mrc p14, 0, r15, c14, c0, 0 + bvs 1b + mcr p14, 0, \reg, c8, c0, 0 +.endm + +@ receive word from debugger +.macro m_receive_from_debugger reg +1: + mrc p14, 0, r15, c14, c0, 0 + bpl 1b + mrc p14, 0, \reg, c9, c0, 0 +.endm + +@ save register on debugger, small +.macro m_small_save_reg reg + mov r0, \reg + bl send_to_debugger +.endm + +@ save status register on debugger, small +.macro m_small_save_psr + mrs r0, spsr + bl send_to_debugger +.endm + +@ wait for all outstanding coprocessor accesses to complete +.macro m_cpwait + mrc p15, 0, r0, c2, c0, 0 + mov r0, r0 + sub pc, pc, #4 +.endm + +.global reset_handler +.global undef_handler +.global swi_handler +.global prefetch_abort_handler +.global data_abort_handler +.global irq_handler +.global fiq_handler + +.section .part1 , "ax" + +reset_handler: + @ read DCSR + mrc p14, 0, r13, c10, c0 + @ check if global enable bit (GE) is set + ands r13, r13, #0x80000000 + + bne debug_handler + + @ set global enable bit (GE) + mov r13, #0xc0000000 + mcr p14, 0, r13, c10, c0 + +debug_handler: + + @ save r0 without modifying other registers + m_send_to_debugger r0 + + @ save lr (program PC) without branching (use macro) + m_send_to_debugger r14 + + @ save non-banked registers and spsr (program CPSR) + m_small_save_reg r1 + m_small_save_reg r2 + m_small_save_reg r3 + m_small_save_reg r4 + m_small_save_reg r5 + m_small_save_reg r6 + m_small_save_reg r7 + m_small_save_psr + + mrs r0, spsr + + @ prepare program PSR for debug use (clear Thumb, set I/F to disable interrupts) + bic r0, r0, #PSR_T + orr r0, r0, #(PSR_I | PSR_F) + + @ examine mode bits + and r1, r0, #MODE_MASK + cmp r1, #MODE_USR + + bne not_user_mode + + @ replace USR mode with SYS + bic r0, r0, #MODE_MASK + orr r0, r0, #MODE_SYS + +not_user_mode: + + b save_banked_registers + +@ command loop +@ wait for command from debugger, than execute desired function +get_command: + bl receive_from_debugger + + @ 0x0n - register access + cmp r0, #0x0 + beq get_banked_registers + + cmp r0, #0x1 + beq set_banked_registers + + @ 0x1n - read memory + cmp r0, #0x11 + beq read_byte + + cmp r0, #0x12 + beq read_half_word + + cmp r0, #0x14 + beq read_word + + @ 0x2n - write memory + cmp r0, #0x21 + beq write_byte + + cmp r0, #0x22 + beq write_half_word + + cmp r0, #0x24 + beq write_word + + @ 0x3n - program execution + cmp r0, #0x30 + beq resume + + cmp r0, #0x31 + beq resume_w_trace + + @ 0x4n - coprocessor access + cmp r0, #0x40 + beq read_cp_reg + + cmp r0, #0x41 + beq write_cp_reg + + @ 0x5n - cache and mmu functions + cmp r0, #0x50 + beq clean_d_cache + + cmp r0, #0x51 + beq invalidate_d_cache + + cmp r0, #0x52 + beq invalidate_i_cache + + cmp r0, #0x53 + beq cpwait + + @ 0x6n - misc functions + cmp r0, #0x60 + beq clear_sa + + cmp r0, #0x61 + beq read_trace_buffer + + cmp r0, #0x62 + beq clean_trace_buffer + + @ return (back to get_command) + b get_command + +@ ---- + +@ resume program execution +resume: + @ restore CPSR (SPSR_dbg) + bl receive_from_debugger + msr spsr, r0 + + @ restore registers (r7 - r0) + bl receive_from_debugger @ r7 + mov r7, r0 + bl receive_from_debugger @ r6 + mov r6, r0 + bl receive_from_debugger @ r5 + mov r5, r0 + bl receive_from_debugger @ r4 + mov r4, r0 + bl receive_from_debugger @ r3 + mov r3, r0 + bl receive_from_debugger @ r2 + mov r2, r0 + bl receive_from_debugger @ r1 + mov r1, r0 + bl receive_from_debugger @ r0 + + @ resume addresss + m_receive_from_debugger lr + + @ branch back to application code, restoring CPSR + subs pc, lr, #0 + +@ get banked registers +@ receive mode bits from host, then run into save_banked_registers to + +get_banked_registers: + bl receive_from_debugger + +@ save banked registers +@ r0[4:0]: desired mode bits +save_banked_registers: + @ backup CPSR + mrs r7, cpsr + msr cpsr_c, r0 + nop + + @ keep current mode bits in r1 for later use + and r1, r0, #MODE_MASK + + @ backup banked registers + m_send_to_debugger r8 + m_send_to_debugger r9 + m_send_to_debugger r10 + m_send_to_debugger r11 + m_send_to_debugger r12 + m_send_to_debugger r13 + m_send_to_debugger r14 + + @ if not in SYS mode (or USR, which we replaced with SYS before) + cmp r1, #MODE_SYS + + beq no_spsr_to_save + + @ backup SPSR + mrs r0, spsr + m_send_to_debugger r0 + +no_spsr_to_save: + + @ restore CPSR for SDS + msr cpsr_c, r7 + nop + + @ return + b get_command + +@ ---- + + +@ set banked registers +@ receive mode bits from host, then run into save_banked_registers to + +set_banked_registers: + bl receive_from_debugger + +@ restore banked registers +@ r0[4:0]: desired mode bits +restore_banked_registers: + @ backup CPSR + mrs r7, cpsr + msr cpsr_c, r0 + nop + + @ keep current mode bits in r1 for later use + and r1, r0, #MODE_MASK + + @ set banked registers + m_receive_from_debugger r8 + m_receive_from_debugger r9 + m_receive_from_debugger r10 + m_receive_from_debugger r11 + m_receive_from_debugger r12 + m_receive_from_debugger r13 + m_receive_from_debugger r14 + + @ if not in SYS mode (or USR, which we replaced with SYS before) + cmp r1, #MODE_SYS + + beq no_spsr_to_restore + + @ set SPSR + m_receive_from_debugger r0 + msr spsr, r0 + +no_spsr_to_restore: + + @ restore CPSR for SDS + msr cpsr_c, r7 + nop + + @ return + b get_command + +@ ---- + +read_byte: + @ r2: address + bl receive_from_debugger + mov r2, r0 + + @ r1: count + bl receive_from_debugger + mov r1, r0 + +rb_loop: + ldrb r0, [r2], #1 + + @ drain write- (and fill-) buffer to work around XScale errata + mcr p15, 0, r8, c7, c10, 4 + + bl send_to_debugger + + subs r1, r1, #1 + bne rb_loop + + @ return + b get_command + +@ ---- + +read_half_word: + @ r2: address + bl receive_from_debugger + mov r2, r0 + + @ r1: count + bl receive_from_debugger + mov r1, r0 + +rh_loop: + ldrh r0, [r2], #2 + + @ drain write- (and fill-) buffer to work around XScale errata + mcr p15, 0, r8, c7, c10, 4 + + bl send_to_debugger + + subs r1, r1, #1 + bne rh_loop + + @ return + b get_command + +@ ---- + +read_word: + @ r2: address + bl receive_from_debugger + mov r2, r0 + + @ r1: count + bl receive_from_debugger + mov r1, r0 + +rw_loop: + ldr r0, [r2], #4 + + @ drain write- (and fill-) buffer to work around XScale errata + mcr p15, 0, r8, c7, c10, 4 + + bl send_to_debugger + + subs r1, r1, #1 + bne rw_loop + + @ return + b get_command + +@ ---- + +write_byte: + @ r2: address + bl receive_from_debugger + mov r2, r0 + + @ r1: count + bl receive_from_debugger + mov r1, r0 + +wb_loop: + bl receive_from_debugger + strb r0, [r2], #1 + + @ drain write- (and fill-) buffer to work around XScale errata + mcr p15, 0, r8, c7, c10, 4 + + subs r1, r1, #1 + bne wb_loop + + @ return + b get_command + +@ ---- + +write_half_word: + @ r2: address + bl receive_from_debugger + mov r2, r0 + + @ r1: count + bl receive_from_debugger + mov r1, r0 + +wh_loop: + bl receive_from_debugger + strh r0, [r2], #2 + + @ drain write- (and fill-) buffer to work around XScale errata + mcr p15, 0, r8, c7, c10, 4 + + subs r1, r1, #1 + bne wh_loop + + @ return + b get_command + +@ ---- + +write_word: + @ r2: address + bl receive_from_debugger + mov r2, r0 + + @ r1: count + bl receive_from_debugger + mov r1, r0 + +ww_loop: + bl receive_from_debugger + str r0, [r2], #4 + + @ drain write- (and fill-) buffer to work around XScale errata + mcr p15, 0, r8, c7, c10, 4 + + subs r1, r1, #1 + bne ww_loop + + @ return + b get_command + +@ ---- + +clear_sa: + @ read DCSR + mrc p14, 0, r0, c10, c0 + + @ clear SA bit + bic r0, r0, #0x20 + + @ write DCSR + mcr p14, 0, r0, c10, c0 + + @ return + b get_command + +@ ---- + +clean_d_cache: + @ r0: cache clean area + bl receive_from_debugger + + mov r1, #1024 +clean_loop: + mcr p15, 0, r0, c7, c2, 5 + add r0, r0, #32 + subs r1, r1, #1 + bne clean_loop + + @ return + b get_command + +@ ---- + +invalidate_d_cache: + mcr p15, 0, r0, c7, c6, 0 + + @ return + b get_command + +@ ---- + +invalidate_i_cache: + mcr p15, 0, r0, c7, c5, 0 + + @ return + b get_command + +@ ---- + +cpwait: + m_cpwait + + @return + b get_command + +@ ---- + +.section .part2 , "ax" + +read_cp_reg: + @ requested cp register + bl receive_from_debugger + + adr r1, read_cp_table + add pc, r1, r0, lsl #3 + +read_cp_table: + mrc p15, 0, r0, c0, c0, 0 @ XSCALE_MAINID + b read_cp_reg_reply + mrc p15, 0, r0, c0, c0, 1 @ XSCALE_CACHETYPE + b read_cp_reg_reply + mrc p15, 0, r0, c1, c0, 0 @ XSCALE_CTRL + b read_cp_reg_reply + mrc p15, 0, r0, c1, c0, 1 @ XSCALE_AUXCTRL + b read_cp_reg_reply + mrc p15, 0, r0, c2, c0, 0 @ XSCALE_TTB + b read_cp_reg_reply + mrc p15, 0, r0, c3, c0, 0 @ XSCALE_DAC + b read_cp_reg_reply + mrc p15, 0, r0, c5, c0, 0 @ XSCALE_FSR + b read_cp_reg_reply + mrc p15, 0, r0, c6, c0, 0 @ XSCALE_FAR + b read_cp_reg_reply + mrc p15, 0, r0, c13, c0, 0 @ XSCALE_PID + b read_cp_reg_reply + mrc p15, 0, r0, c15, c0, 0 @ XSCALE_CP_ACCESS + b read_cp_reg_reply + mrc p15, 0, r0, c14, c8, 0 @ XSCALE_IBCR0 + b read_cp_reg_reply + mrc p15, 0, r0, c14, c9, 0 @ XSCALE_IBCR1 + b read_cp_reg_reply + mrc p15, 0, r0, c14, c0, 0 @ XSCALE_DBR0 + b read_cp_reg_reply + mrc p15, 0, r0, c14, c3, 0 @ XSCALE_DBR1 + b read_cp_reg_reply + mrc p15, 0, r0, c14, c4, 0 @ XSCALE_DBCON + b read_cp_reg_reply + mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG + b read_cp_reg_reply + mrc p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0 + b read_cp_reg_reply + mrc p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1 + b read_cp_reg_reply + mrc p14, 0, r0, c10, c0, 0 @ XSCALE_DCSR + b read_cp_reg_reply + +read_cp_reg_reply: + bl send_to_debugger + + @ return + b get_command + +@ ---- + +write_cp_reg: + @ requested cp register + bl receive_from_debugger + mov r1, r0 + + @ value to be written + bl receive_from_debugger + + adr r2, write_cp_table + add pc, r2, r1, lsl #3 + +write_cp_table: + mcr p15, 0, r0, c0, c0, 0 @ XSCALE_MAINID (0x0) + b get_command + mcr p15, 0, r0, c0, c0, 1 @ XSCALE_CACHETYPE (0x1) + b get_command + mcr p15, 0, r0, c1, c0, 0 @ XSCALE_CTRL (0x2) + b get_command + mcr p15, 0, r0, c1, c0, 1 @ XSCALE_AUXCTRL (0x3) + b get_command + mcr p15, 0, r0, c2, c0, 0 @ XSCALE_TTB (0x4) + b get_command + mcr p15, 0, r0, c3, c0, 0 @ XSCALE_DAC (0x5) + b get_command + mcr p15, 0, r0, c5, c0, 0 @ XSCALE_FSR (0x6) + b get_command + mcr p15, 0, r0, c6, c0, 0 @ XSCALE_FAR (0x7) + b get_command + mcr p15, 0, r0, c13, c0, 0 @ XSCALE_PID (0x8) + b get_command + mcr p15, 0, r0, c15, c0, 0 @ XSCALE_CP_ACCESS (0x9) + b get_command + mcr p15, 0, r0, c14, c8, 0 @ XSCALE_IBCR0 (0xa) + b get_command + mcr p15, 0, r0, c14, c9, 0 @ XSCALE_IBCR1 (0xb) + b get_command + mcr p15, 0, r0, c14, c0, 0 @ XSCALE_DBR0 (0xc) + b get_command + mcr p15, 0, r0, c14, c3, 0 @ XSCALE_DBR1 (0xd) + b get_command + mcr p15, 0, r0, c14, c4, 0 @ XSCALE_DBCON (0xe) + b get_command + mcr p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG (0xf) + b get_command + mcr p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0 (0x10) + b get_command + mcr p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1 (0x11) + b get_command + mcr p14, 0, r0, c10, c0, 0 @ XSCALE_DCSR (0x12) + b get_command + +@ ---- + +read_trace_buffer: + + @ dump 256 entries from trace buffer + mov r1, #256 +read_tb_loop: + mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG + bl send_to_debugger + subs r1, r1, #1 + bne read_tb_loop + + @ dump checkpoint register 0 + mrc p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0 (0x10) + bl send_to_debugger + + @ dump checkpoint register 1 + mrc p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1 (0x11) + bl send_to_debugger + + @ return + b get_command + +@ ---- + +clean_trace_buffer: + + @ clean 256 entries from trace buffer + mov r1, #256 +clean_tb_loop: + mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG + subs r1, r1, #1 + bne clean_tb_loop + + @ return + b get_command + +@ ---- + + +@ resume program execution with trace buffer enabled +resume_w_trace: + @ restore CPSR (SPSR_dbg) + bl receive_from_debugger + msr spsr, r0 + + @ restore registers (r7 - r0) + bl receive_from_debugger @ r7 + mov r7, r0 + bl receive_from_debugger @ r6 + mov r6, r0 + bl receive_from_debugger @ r5 + mov r5, r0 + bl receive_from_debugger @ r4 + mov r4, r0 + bl receive_from_debugger @ r3 + mov r3, r0 + bl receive_from_debugger @ r2 + mov r2, r0 + bl receive_from_debugger @ r1 + mov r1, r0 + bl receive_from_debugger @ r0 + + @ resume addresss + m_receive_from_debugger lr + + mrc p14, 0, r13, c10, c0, 0 @ XSCALE_DCSR + orr r13, r13, #1 + mcr p14, 0, r13, c10, c0, 0 @ XSCALE_DCSR + + @ branch back to application code, restoring CPSR + subs pc, lr, #0 + +undef_handler: +swi_handler: +prefetch_abort_handler: +data_abort_handler: +irq_handler: +fiq_handler: +1: + b 1b + +send_to_debugger: + m_send_to_debugger r0 + mov pc, lr + +receive_from_debugger: + m_receive_from_debugger r0 + mov pc, lr + diff --git a/contrib/loaders/debug/xscale/debug_handler.inc b/contrib/loaders/debug/xscale/debug_handler.inc new file mode 100644 index 0000000..d7f54e7 --- /dev/null +++ b/contrib/loaders/debug/xscale/debug_handler.inc @@ -0,0 +1,101 @@ +/* Autogenerated with ../../../../src/helper/bin2char.sh */ +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x10,0xde,0x1a,0xee,0x02,0xd1,0x1d,0xe2,0x01,0x00,0x00,0x1a,0x03,0xd1,0xa0,0xe3, +0x10,0xde,0x0a,0xee,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,0x10,0x0e,0x08,0xee, +0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,0x10,0xee,0x08,0xee,0x01,0x00,0xa0,0xe1, +0x70,0x01,0x00,0xeb,0x02,0x00,0xa0,0xe1,0x6e,0x01,0x00,0xeb,0x03,0x00,0xa0,0xe1, +0x6c,0x01,0x00,0xeb,0x04,0x00,0xa0,0xe1,0x6a,0x01,0x00,0xeb,0x05,0x00,0xa0,0xe1, +0x68,0x01,0x00,0xeb,0x06,0x00,0xa0,0xe1,0x66,0x01,0x00,0xeb,0x07,0x00,0xa0,0xe1, +0x64,0x01,0x00,0xeb,0x00,0x00,0x4f,0xe1,0x62,0x01,0x00,0xeb,0x00,0x00,0x4f,0xe1, +0x20,0x00,0xc0,0xe3,0xc0,0x00,0x80,0xe3,0x1f,0x10,0x00,0xe2,0x10,0x00,0x51,0xe3, +0x01,0x00,0x00,0x1a,0x1f,0x00,0xc0,0xe3,0x1f,0x00,0x80,0xe3,0x3d,0x00,0x00,0xea, +0x5c,0x01,0x00,0xeb,0x00,0x00,0x50,0xe3,0x39,0x00,0x00,0x0a,0x01,0x00,0x50,0xe3, +0x5a,0x00,0x00,0x0a,0x11,0x00,0x50,0xe3,0x7b,0x00,0x00,0x0a,0x12,0x00,0x50,0xe3, +0x83,0x00,0x00,0x0a,0x14,0x00,0x50,0xe3,0x8b,0x00,0x00,0x0a,0x21,0x00,0x50,0xe3, +0x93,0x00,0x00,0x0a,0x22,0x00,0x50,0xe3,0x9b,0x00,0x00,0x0a,0x24,0x00,0x50,0xe3, +0xa3,0x00,0x00,0x0a,0x30,0x00,0x50,0xe3,0x14,0x00,0x00,0x0a,0x31,0x00,0x50,0xe3, +0x2b,0x01,0x00,0x0a,0x40,0x00,0x50,0xe3,0xc4,0x00,0x00,0x0a,0x41,0x00,0x50,0xe3, +0xed,0x00,0x00,0x0a,0x50,0x00,0x50,0xe3,0xa7,0x00,0x00,0x0a,0x51,0x00,0x50,0xe3, +0xac,0x00,0x00,0x0a,0x52,0x00,0x50,0xe3,0xac,0x00,0x00,0x0a,0x53,0x00,0x50,0xe3, +0xac,0x00,0x00,0x0a,0x60,0x00,0x50,0xe3,0x9b,0x00,0x00,0x0a,0x61,0x00,0x50,0xe3, +0x0c,0x01,0x00,0x0a,0x62,0x00,0x50,0xe3,0x14,0x01,0x00,0x0a,0xd7,0xff,0xff,0xea, +0x34,0x01,0x00,0xeb,0x00,0xf0,0x69,0xe1,0x32,0x01,0x00,0xeb,0x00,0x70,0xa0,0xe1, +0x30,0x01,0x00,0xeb,0x00,0x60,0xa0,0xe1,0x2e,0x01,0x00,0xeb,0x00,0x50,0xa0,0xe1, +0x2c,0x01,0x00,0xeb,0x00,0x40,0xa0,0xe1,0x2a,0x01,0x00,0xeb,0x00,0x30,0xa0,0xe1, +0x28,0x01,0x00,0xeb,0x00,0x20,0xa0,0xe1,0x26,0x01,0x00,0xeb,0x00,0x10,0xa0,0xe1, +0x24,0x01,0x00,0xeb,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a,0x10,0xee,0x19,0xee, +0x00,0xf0,0x5e,0xe2,0x1f,0x01,0x00,0xeb,0x00,0x70,0x0f,0xe1,0x00,0xf0,0x21,0xe1, +0x00,0x00,0xa0,0xe1,0x1f,0x10,0x00,0xe2,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a, +0x10,0x8e,0x08,0xee,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,0x10,0x9e,0x08,0xee, +0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,0x10,0xae,0x08,0xee,0x10,0xfe,0x1e,0xee, +0xfd,0xff,0xff,0x6a,0x10,0xbe,0x08,0xee,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a, +0x10,0xce,0x08,0xee,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,0x10,0xde,0x08,0xee, +0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a,0x10,0xee,0x08,0xee,0x1f,0x00,0x51,0xe3, +0x03,0x00,0x00,0x0a,0x00,0x00,0x4f,0xe1,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a, +0x10,0x0e,0x08,0xee,0x07,0xf0,0x21,0xe1,0x00,0x00,0xa0,0xe1,0x9f,0xff,0xff,0xea, +0xfc,0x00,0x00,0xeb,0x00,0x70,0x0f,0xe1,0x00,0xf0,0x21,0xe1,0x00,0x00,0xa0,0xe1, +0x1f,0x10,0x00,0xe2,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a,0x10,0x8e,0x19,0xee, +0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a,0x10,0x9e,0x19,0xee,0x10,0xfe,0x1e,0xee, +0xfd,0xff,0xff,0x5a,0x10,0xae,0x19,0xee,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a, +0x10,0xbe,0x19,0xee,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a,0x10,0xce,0x19,0xee, +0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a,0x10,0xde,0x19,0xee,0x10,0xfe,0x1e,0xee, +0xfd,0xff,0xff,0x5a,0x10,0xee,0x19,0xee,0x1f,0x00,0x51,0xe3,0x03,0x00,0x00,0x0a, +0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a,0x10,0x0e,0x19,0xee,0x00,0xf0,0x69,0xe1, +0x07,0xf0,0x21,0xe1,0x00,0x00,0xa0,0xe1,0x7c,0xff,0xff,0xea,0xd9,0x00,0x00,0xeb, +0x00,0x20,0xa0,0xe1,0xd7,0x00,0x00,0xeb,0x00,0x10,0xa0,0xe1,0x01,0x00,0xd2,0xe4, +0x9a,0x8f,0x07,0xee,0xcf,0x00,0x00,0xeb,0x01,0x10,0x51,0xe2,0xfa,0xff,0xff,0x1a, +0x72,0xff,0xff,0xea,0xcf,0x00,0x00,0xeb,0x00,0x20,0xa0,0xe1,0xcd,0x00,0x00,0xeb, +0x00,0x10,0xa0,0xe1,0xb2,0x00,0xd2,0xe0,0x9a,0x8f,0x07,0xee,0xc5,0x00,0x00,0xeb, +0x01,0x10,0x51,0xe2,0xfa,0xff,0xff,0x1a,0x68,0xff,0xff,0xea,0xc5,0x00,0x00,0xeb, +0x00,0x20,0xa0,0xe1,0xc3,0x00,0x00,0xeb,0x00,0x10,0xa0,0xe1,0x04,0x00,0x92,0xe4, +0x9a,0x8f,0x07,0xee,0xbb,0x00,0x00,0xeb,0x01,0x10,0x51,0xe2,0xfa,0xff,0xff,0x1a, +0x5e,0xff,0xff,0xea,0xbb,0x00,0x00,0xeb,0x00,0x20,0xa0,0xe1,0xb9,0x00,0x00,0xeb, +0x00,0x10,0xa0,0xe1,0xb7,0x00,0x00,0xeb,0x01,0x00,0xc2,0xe4,0x9a,0x8f,0x07,0xee, +0x01,0x10,0x51,0xe2,0xfa,0xff,0xff,0x1a,0x54,0xff,0xff,0xea,0xb1,0x00,0x00,0xeb, +0x00,0x20,0xa0,0xe1,0xaf,0x00,0x00,0xeb,0x00,0x10,0xa0,0xe1,0xad,0x00,0x00,0xeb, +0xb2,0x00,0xc2,0xe0,0x9a,0x8f,0x07,0xee,0x01,0x10,0x51,0xe2,0xfa,0xff,0xff,0x1a, +0x4a,0xff,0xff,0xea,0xa7,0x00,0x00,0xeb,0x00,0x20,0xa0,0xe1,0xa5,0x00,0x00,0xeb, +0x00,0x10,0xa0,0xe1,0xa3,0x00,0x00,0xeb,0x04,0x00,0x82,0xe4,0x9a,0x8f,0x07,0xee, +0x01,0x10,0x51,0xe2,0xfa,0xff,0xff,0x1a,0x40,0xff,0xff,0xea,0x10,0x0e,0x1a,0xee, +0x20,0x00,0xc0,0xe3,0x10,0x0e,0x0a,0xee,0x3c,0xff,0xff,0xea,0x99,0x00,0x00,0xeb, +0x01,0x1b,0xa0,0xe3,0xb2,0x0f,0x07,0xee,0x20,0x00,0x80,0xe2,0x01,0x10,0x51,0xe2, +0xfb,0xff,0xff,0x1a,0x35,0xff,0xff,0xea,0x16,0x0f,0x07,0xee,0x33,0xff,0xff,0xea, +0x15,0x0f,0x07,0xee,0x31,0xff,0xff,0xea,0x10,0x0f,0x12,0xee,0x00,0x00,0xa0,0xe1, +0x04,0xf0,0x4f,0xe2,0x2d,0xff,0xff,0xea,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x80,0x00,0x00,0xeb,0x00,0x10,0x8f,0xe2,0x80,0xf1,0x81,0xe0,0x10,0x0f,0x10,0xee, +0x23,0x00,0x00,0xea,0x30,0x0f,0x10,0xee,0x21,0x00,0x00,0xea,0x10,0x0f,0x11,0xee, +0x1f,0x00,0x00,0xea,0x30,0x0f,0x11,0xee,0x1d,0x00,0x00,0xea,0x10,0x0f,0x12,0xee, +0x1b,0x00,0x00,0xea,0x10,0x0f,0x13,0xee,0x19,0x00,0x00,0xea,0x10,0x0f,0x15,0xee, +0x17,0x00,0x00,0xea,0x10,0x0f,0x16,0xee,0x15,0x00,0x00,0xea,0x10,0x0f,0x1d,0xee, +0x13,0x00,0x00,0xea,0x10,0x0f,0x1f,0xee,0x11,0x00,0x00,0xea,0x18,0x0f,0x1e,0xee, +0x0f,0x00,0x00,0xea,0x19,0x0f,0x1e,0xee,0x0d,0x00,0x00,0xea,0x10,0x0f,0x1e,0xee, +0x0b,0x00,0x00,0xea,0x13,0x0f,0x1e,0xee,0x09,0x00,0x00,0xea,0x14,0x0f,0x1e,0xee, +0x07,0x00,0x00,0xea,0x10,0x0e,0x1b,0xee,0x05,0x00,0x00,0xea,0x10,0x0e,0x1c,0xee, +0x03,0x00,0x00,0xea,0x10,0x0e,0x1d,0xee,0x01,0x00,0x00,0xea,0x10,0x0e,0x1a,0xee, +0xff,0xff,0xff,0xea,0x53,0x00,0x00,0xeb,0xf8,0xfe,0xff,0xea,0x55,0x00,0x00,0xeb, +0x00,0x10,0xa0,0xe1,0x53,0x00,0x00,0xeb,0x00,0x20,0x8f,0xe2,0x81,0xf1,0x82,0xe0, +0x10,0x0f,0x00,0xee,0xf1,0xfe,0xff,0xea,0x30,0x0f,0x00,0xee,0xef,0xfe,0xff,0xea, +0x10,0x0f,0x01,0xee,0xed,0xfe,0xff,0xea,0x30,0x0f,0x01,0xee,0xeb,0xfe,0xff,0xea, +0x10,0x0f,0x02,0xee,0xe9,0xfe,0xff,0xea,0x10,0x0f,0x03,0xee,0xe7,0xfe,0xff,0xea, +0x10,0x0f,0x05,0xee,0xe5,0xfe,0xff,0xea,0x10,0x0f,0x06,0xee,0xe3,0xfe,0xff,0xea, +0x10,0x0f,0x0d,0xee,0xe1,0xfe,0xff,0xea,0x10,0x0f,0x0f,0xee,0xdf,0xfe,0xff,0xea, +0x18,0x0f,0x0e,0xee,0xdd,0xfe,0xff,0xea,0x19,0x0f,0x0e,0xee,0xdb,0xfe,0xff,0xea, +0x10,0x0f,0x0e,0xee,0xd9,0xfe,0xff,0xea,0x13,0x0f,0x0e,0xee,0xd7,0xfe,0xff,0xea, +0x14,0x0f,0x0e,0xee,0xd5,0xfe,0xff,0xea,0x10,0x0e,0x0b,0xee,0xd3,0xfe,0xff,0xea, +0x10,0x0e,0x0c,0xee,0xd1,0xfe,0xff,0xea,0x10,0x0e,0x0d,0xee,0xcf,0xfe,0xff,0xea, +0x10,0x0e,0x0a,0xee,0xcd,0xfe,0xff,0xea,0x01,0x1c,0xa0,0xe3,0x10,0x0e,0x1b,0xee, +0x24,0x00,0x00,0xeb,0x01,0x10,0x51,0xe2,0xfb,0xff,0xff,0x1a,0x10,0x0e,0x1c,0xee, +0x20,0x00,0x00,0xeb,0x10,0x0e,0x1d,0xee,0x1e,0x00,0x00,0xeb,0xc3,0xfe,0xff,0xea, +0x01,0x1c,0xa0,0xe3,0x10,0x0e,0x1b,0xee,0x01,0x10,0x51,0xe2,0xfc,0xff,0xff,0x1a, +0xbe,0xfe,0xff,0xea,0x1b,0x00,0x00,0xeb,0x00,0xf0,0x69,0xe1,0x19,0x00,0x00,0xeb, +0x00,0x70,0xa0,0xe1,0x17,0x00,0x00,0xeb,0x00,0x60,0xa0,0xe1,0x15,0x00,0x00,0xeb, +0x00,0x50,0xa0,0xe1,0x13,0x00,0x00,0xeb,0x00,0x40,0xa0,0xe1,0x11,0x00,0x00,0xeb, +0x00,0x30,0xa0,0xe1,0x0f,0x00,0x00,0xeb,0x00,0x20,0xa0,0xe1,0x0d,0x00,0x00,0xeb, +0x00,0x10,0xa0,0xe1,0x0b,0x00,0x00,0xeb,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a, +0x10,0xee,0x19,0xee,0x10,0xde,0x1a,0xee,0x01,0xd0,0x8d,0xe3,0x10,0xde,0x0a,0xee, +0x00,0xf0,0x5e,0xe2,0xfe,0xff,0xff,0xea,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x6a, +0x10,0x0e,0x08,0xee,0x0e,0xf0,0xa0,0xe1,0x10,0xfe,0x1e,0xee,0xfd,0xff,0xff,0x5a, +0x10,0x0e,0x19,0xee,0x0e,0xf0,0xa0,0xe1, diff --git a/contrib/loaders/debug/xscale/debug_handler.ld b/contrib/loaders/debug/xscale/debug_handler.ld new file mode 100644 index 0000000..d943b13 --- /dev/null +++ b/contrib/loaders/debug/xscale/debug_handler.ld @@ -0,0 +1,49 @@ +/* identify the Entry Point */ +ENTRY(reset_handler) + +/* specify the mini-ICache memory areas */ +MEMORY +{ + mini_icache_0 (x) : ORIGIN = 0x0, LENGTH = 1024 /* first part of mini icache (sets 0-31) */ + mini_icache_1 (x) : ORIGIN = 0x400, LENGTH = 1024 /* second part of mini icache (sets 0-31) */ +} + +/* now define the output sections */ +SECTIONS +{ + .part1 : + { + LONG(0) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + *(.part1) + } >mini_icache_0 + + .part2 : + { + LONG(0) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + LONG(0) + *(.part2) + FILL(0x0) + } >mini_icache_1 + + /DISCARD/ : + { + *(.text) + *(.glue_7) + *(.glue_7t) + *(.data) + *(.bss) + } +} diff --git a/contrib/loaders/debug/xscale/protocol.h b/contrib/loaders/debug/xscale/protocol.h new file mode 100644 index 0000000..cb01655 --- /dev/null +++ b/contrib/loaders/debug/xscale/protocol.h @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (C) 2006 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, see . * + ***************************************************************************/ + +#define REG_R0 0 +#define REG_R1 1 +#define REG_R2 2 +#define REG_R3 3 +#define REG_R4 4 +#define REG_R5 5 +#define REG_R6 6 +#define REG_R7 7 +#define REG_R8 8 +#define REG_R9 9 +#define REG_R10 10 +#define REG_R11 11 +#define REG_R12 12 +#define REG_R13 13 +#define REG_R14 14 +#define REG_R15 15 +#define REG_CPSR 16 +#define REG_SPSR 17 + +#define MODE_USR 0x10 +#define MODE_FIQ 0x11 +#define MODE_IRQ 0x12 +#define MODE_SVC 0x13 +#define MODE_ABT 0x17 +#define MODE_UND 0x1b +#define MODE_SYS 0x1f + +#define MODE_ANY 0x40 +#define MODE_CURRENT 0x80 + +#define MODE_MASK 0x1f +#define PSR_I 0x80 +#define PSR_F 0x40 +#define PSR_T 0x20 + +#define XSCALE_DBG_MAINID 0x0 +#define XSCALE_DBG_CACHETYPE 0x1 +#define XSCALE_DBG_CTRL 0x2 +#define XSCALE_DBG_AUXCTRL 0x3 +#define XSCALE_DBG_TTB 0x4 +#define XSCALE_DBG_DAC 0x5 +#define XSCALE_DBG_FSR 0x6 +#define XSCALE_DBG_FAR 0x7 +#define XSCALE_DBG_PID 0x8 +#define XSCALE_DBG_CPACCESS 0x9 +#define XSCALE_DBG_IBCR0 0xa +#define XSCALE_DBG_IBCR1 0xb +#define XSCALE_DBG_DBR0 0xc +#define XSCALE_DBG_DBR1 0xd +#define XSCALE_DBG_DBCON 0xe diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 5b6916d..dc7973d 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -9,19 +9,6 @@ endif SUBDIRS = openrisc libtarget_la_LIBADD = $(top_builddir)/src/target/openrisc/libopenrisc.la -BIN2C = $(top_srcdir)/src/helper/bin2char.sh - -DEBUG_HANDLER = $(srcdir)/xscale/debug_handler.bin -EXTRA_DIST = \ - startup.tcl \ - $(wildcard $(srcdir)/xscale/*) - -DEBUG_HEADER = xscale_debug.inc -BUILT_SOURCES = $(DEBUG_HEADER) -CLEANFILES = $(DEBUG_HEADER) - -$(DEBUG_HEADER): $(DEBUG_HANDLER) $(BIN2C) - $(BIN2C) < $< > $@ || { rm -f $@; false; } METASOURCES = AUTO noinst_LTLIBRARIES = libtarget.la diff --git a/src/target/xscale.c b/src/target/xscale.c index 140ea58..e54033f 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -73,7 +73,7 @@ static int xscale_read_trace(struct target *); * mini-ICache, which is 2K of code writable only via JTAG. */ static const uint8_t xscale_debug_handler[] = { -#include "xscale_debug.inc" +#include "../../contrib/loaders/debug/xscale/debug_handler.inc" }; static const char *const xscale_reg_list[] = { diff --git a/src/target/xscale/build.sh b/src/target/xscale/build.sh deleted file mode 100755 index fc828b2..0000000 --- a/src/target/xscale/build.sh +++ /dev/null @@ -1,7 +0,0 @@ -arm-none-eabi-gcc -c debug_handler.S -o debug_handler.o -arm-none-eabi-ld -EL -n -Tdebug_handler.cmd debug_handler.o -o debug_handler.out -arm-none-eabi-objcopy -O binary debug_handler.out debug_handler.bin - -#arm-none-eabi-gcc -mbig-endian -c debug_handler.S -o debug_handler_be.o -#arm-none-eabi-ld -EB -n -Tdebug_handler.cmd debug_handler_be.o -o debug_handler_be.out -#arm-none-eabi-objcopy -O binary debug_handler_be.out debug_handler_be.bin diff --git a/src/target/xscale/debug_handler.S b/src/target/xscale/debug_handler.S deleted file mode 100644 index 66dfa88..0000000 --- a/src/target/xscale/debug_handler.S +++ /dev/null @@ -1,716 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 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, see . * - ***************************************************************************/ -#include "protocol.h" - - .text - .align 4 - -@ Disable thumb mode - .code 32 - -@ send word to debugger -.macro m_send_to_debugger reg -1: - mrc p14, 0, r15, c14, c0, 0 - bvs 1b - mcr p14, 0, \reg, c8, c0, 0 -.endm - -@ receive word from debugger -.macro m_receive_from_debugger reg -1: - mrc p14, 0, r15, c14, c0, 0 - bpl 1b - mrc p14, 0, \reg, c9, c0, 0 -.endm - -@ save register on debugger, small -.macro m_small_save_reg reg - mov r0, \reg - bl send_to_debugger -.endm - -@ save status register on debugger, small -.macro m_small_save_psr - mrs r0, spsr - bl send_to_debugger -.endm - -@ wait for all outstanding coprocessor accesses to complete -.macro m_cpwait - mrc p15, 0, r0, c2, c0, 0 - mov r0, r0 - sub pc, pc, #4 -.endm - -.global reset_handler -.global undef_handler -.global swi_handler -.global prefetch_abort_handler -.global data_abort_handler -.global irq_handler -.global fiq_handler - -.section .part1 , "ax" - -reset_handler: - @ read DCSR - mrc p14, 0, r13, c10, c0 - @ check if global enable bit (GE) is set - ands r13, r13, #0x80000000 - - bne debug_handler - - @ set global enable bit (GE) - mov r13, #0xc0000000 - mcr p14, 0, r13, c10, c0 - -debug_handler: - - @ save r0 without modifying other registers - m_send_to_debugger r0 - - @ save lr (program PC) without branching (use macro) - m_send_to_debugger r14 - - @ save non-banked registers and spsr (program CPSR) - m_small_save_reg r1 - m_small_save_reg r2 - m_small_save_reg r3 - m_small_save_reg r4 - m_small_save_reg r5 - m_small_save_reg r6 - m_small_save_reg r7 - m_small_save_psr - - mrs r0, spsr - - @ prepare program PSR for debug use (clear Thumb, set I/F to disable interrupts) - bic r0, r0, #PSR_T - orr r0, r0, #(PSR_I | PSR_F) - - @ examine mode bits - and r1, r0, #MODE_MASK - cmp r1, #MODE_USR - - bne not_user_mode - - @ replace USR mode with SYS - bic r0, r0, #MODE_MASK - orr r0, r0, #MODE_SYS - -not_user_mode: - - b save_banked_registers - -@ command loop -@ wait for command from debugger, than execute desired function -get_command: - bl receive_from_debugger - - @ 0x0n - register access - cmp r0, #0x0 - beq get_banked_registers - - cmp r0, #0x1 - beq set_banked_registers - - @ 0x1n - read memory - cmp r0, #0x11 - beq read_byte - - cmp r0, #0x12 - beq read_half_word - - cmp r0, #0x14 - beq read_word - - @ 0x2n - write memory - cmp r0, #0x21 - beq write_byte - - cmp r0, #0x22 - beq write_half_word - - cmp r0, #0x24 - beq write_word - - @ 0x3n - program execution - cmp r0, #0x30 - beq resume - - cmp r0, #0x31 - beq resume_w_trace - - @ 0x4n - coprocessor access - cmp r0, #0x40 - beq read_cp_reg - - cmp r0, #0x41 - beq write_cp_reg - - @ 0x5n - cache and mmu functions - cmp r0, #0x50 - beq clean_d_cache - - cmp r0, #0x51 - beq invalidate_d_cache - - cmp r0, #0x52 - beq invalidate_i_cache - - cmp r0, #0x53 - beq cpwait - - @ 0x6n - misc functions - cmp r0, #0x60 - beq clear_sa - - cmp r0, #0x61 - beq read_trace_buffer - - cmp r0, #0x62 - beq clean_trace_buffer - - @ return (back to get_command) - b get_command - -@ ---- - -@ resume program execution -resume: - @ restore CPSR (SPSR_dbg) - bl receive_from_debugger - msr spsr, r0 - - @ restore registers (r7 - r0) - bl receive_from_debugger @ r7 - mov r7, r0 - bl receive_from_debugger @ r6 - mov r6, r0 - bl receive_from_debugger @ r5 - mov r5, r0 - bl receive_from_debugger @ r4 - mov r4, r0 - bl receive_from_debugger @ r3 - mov r3, r0 - bl receive_from_debugger @ r2 - mov r2, r0 - bl receive_from_debugger @ r1 - mov r1, r0 - bl receive_from_debugger @ r0 - - @ resume addresss - m_receive_from_debugger lr - - @ branch back to application code, restoring CPSR - subs pc, lr, #0 - -@ get banked registers -@ receive mode bits from host, then run into save_banked_registers to - -get_banked_registers: - bl receive_from_debugger - -@ save banked registers -@ r0[4:0]: desired mode bits -save_banked_registers: - @ backup CPSR - mrs r7, cpsr - msr cpsr_c, r0 - nop - - @ keep current mode bits in r1 for later use - and r1, r0, #MODE_MASK - - @ backup banked registers - m_send_to_debugger r8 - m_send_to_debugger r9 - m_send_to_debugger r10 - m_send_to_debugger r11 - m_send_to_debugger r12 - m_send_to_debugger r13 - m_send_to_debugger r14 - - @ if not in SYS mode (or USR, which we replaced with SYS before) - cmp r1, #MODE_SYS - - beq no_spsr_to_save - - @ backup SPSR - mrs r0, spsr - m_send_to_debugger r0 - -no_spsr_to_save: - - @ restore CPSR for SDS - msr cpsr_c, r7 - nop - - @ return - b get_command - -@ ---- - - -@ set banked registers -@ receive mode bits from host, then run into save_banked_registers to - -set_banked_registers: - bl receive_from_debugger - -@ restore banked registers -@ r0[4:0]: desired mode bits -restore_banked_registers: - @ backup CPSR - mrs r7, cpsr - msr cpsr_c, r0 - nop - - @ keep current mode bits in r1 for later use - and r1, r0, #MODE_MASK - - @ set banked registers - m_receive_from_debugger r8 - m_receive_from_debugger r9 - m_receive_from_debugger r10 - m_receive_from_debugger r11 - m_receive_from_debugger r12 - m_receive_from_debugger r13 - m_receive_from_debugger r14 - - @ if not in SYS mode (or USR, which we replaced with SYS before) - cmp r1, #MODE_SYS - - beq no_spsr_to_restore - - @ set SPSR - m_receive_from_debugger r0 - msr spsr, r0 - -no_spsr_to_restore: - - @ restore CPSR for SDS - msr cpsr_c, r7 - nop - - @ return - b get_command - -@ ---- - -read_byte: - @ r2: address - bl receive_from_debugger - mov r2, r0 - - @ r1: count - bl receive_from_debugger - mov r1, r0 - -rb_loop: - ldrb r0, [r2], #1 - - @ drain write- (and fill-) buffer to work around XScale errata - mcr p15, 0, r8, c7, c10, 4 - - bl send_to_debugger - - subs r1, r1, #1 - bne rb_loop - - @ return - b get_command - -@ ---- - -read_half_word: - @ r2: address - bl receive_from_debugger - mov r2, r0 - - @ r1: count - bl receive_from_debugger - mov r1, r0 - -rh_loop: - ldrh r0, [r2], #2 - - @ drain write- (and fill-) buffer to work around XScale errata - mcr p15, 0, r8, c7, c10, 4 - - bl send_to_debugger - - subs r1, r1, #1 - bne rh_loop - - @ return - b get_command - -@ ---- - -read_word: - @ r2: address - bl receive_from_debugger - mov r2, r0 - - @ r1: count - bl receive_from_debugger - mov r1, r0 - -rw_loop: - ldr r0, [r2], #4 - - @ drain write- (and fill-) buffer to work around XScale errata - mcr p15, 0, r8, c7, c10, 4 - - bl send_to_debugger - - subs r1, r1, #1 - bne rw_loop - - @ return - b get_command - -@ ---- - -write_byte: - @ r2: address - bl receive_from_debugger - mov r2, r0 - - @ r1: count - bl receive_from_debugger - mov r1, r0 - -wb_loop: - bl receive_from_debugger - strb r0, [r2], #1 - - @ drain write- (and fill-) buffer to work around XScale errata - mcr p15, 0, r8, c7, c10, 4 - - subs r1, r1, #1 - bne wb_loop - - @ return - b get_command - -@ ---- - -write_half_word: - @ r2: address - bl receive_from_debugger - mov r2, r0 - - @ r1: count - bl receive_from_debugger - mov r1, r0 - -wh_loop: - bl receive_from_debugger - strh r0, [r2], #2 - - @ drain write- (and fill-) buffer to work around XScale errata - mcr p15, 0, r8, c7, c10, 4 - - subs r1, r1, #1 - bne wh_loop - - @ return - b get_command - -@ ---- - -write_word: - @ r2: address - bl receive_from_debugger - mov r2, r0 - - @ r1: count - bl receive_from_debugger - mov r1, r0 - -ww_loop: - bl receive_from_debugger - str r0, [r2], #4 - - @ drain write- (and fill-) buffer to work around XScale errata - mcr p15, 0, r8, c7, c10, 4 - - subs r1, r1, #1 - bne ww_loop - - @ return - b get_command - -@ ---- - -clear_sa: - @ read DCSR - mrc p14, 0, r0, c10, c0 - - @ clear SA bit - bic r0, r0, #0x20 - - @ write DCSR - mcr p14, 0, r0, c10, c0 - - @ return - b get_command - -@ ---- - -clean_d_cache: - @ r0: cache clean area - bl receive_from_debugger - - mov r1, #1024 -clean_loop: - mcr p15, 0, r0, c7, c2, 5 - add r0, r0, #32 - subs r1, r1, #1 - bne clean_loop - - @ return - b get_command - -@ ---- - -invalidate_d_cache: - mcr p15, 0, r0, c7, c6, 0 - - @ return - b get_command - -@ ---- - -invalidate_i_cache: - mcr p15, 0, r0, c7, c5, 0 - - @ return - b get_command - -@ ---- - -cpwait: - m_cpwait - - @return - b get_command - -@ ---- - -.section .part2 , "ax" - -read_cp_reg: - @ requested cp register - bl receive_from_debugger - - adr r1, read_cp_table - add pc, r1, r0, lsl #3 - -read_cp_table: - mrc p15, 0, r0, c0, c0, 0 @ XSCALE_MAINID - b read_cp_reg_reply - mrc p15, 0, r0, c0, c0, 1 @ XSCALE_CACHETYPE - b read_cp_reg_reply - mrc p15, 0, r0, c1, c0, 0 @ XSCALE_CTRL - b read_cp_reg_reply - mrc p15, 0, r0, c1, c0, 1 @ XSCALE_AUXCTRL - b read_cp_reg_reply - mrc p15, 0, r0, c2, c0, 0 @ XSCALE_TTB - b read_cp_reg_reply - mrc p15, 0, r0, c3, c0, 0 @ XSCALE_DAC - b read_cp_reg_reply - mrc p15, 0, r0, c5, c0, 0 @ XSCALE_FSR - b read_cp_reg_reply - mrc p15, 0, r0, c6, c0, 0 @ XSCALE_FAR - b read_cp_reg_reply - mrc p15, 0, r0, c13, c0, 0 @ XSCALE_PID - b read_cp_reg_reply - mrc p15, 0, r0, c15, c0, 0 @ XSCALE_CP_ACCESS - b read_cp_reg_reply - mrc p15, 0, r0, c14, c8, 0 @ XSCALE_IBCR0 - b read_cp_reg_reply - mrc p15, 0, r0, c14, c9, 0 @ XSCALE_IBCR1 - b read_cp_reg_reply - mrc p15, 0, r0, c14, c0, 0 @ XSCALE_DBR0 - b read_cp_reg_reply - mrc p15, 0, r0, c14, c3, 0 @ XSCALE_DBR1 - b read_cp_reg_reply - mrc p15, 0, r0, c14, c4, 0 @ XSCALE_DBCON - b read_cp_reg_reply - mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG - b read_cp_reg_reply - mrc p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0 - b read_cp_reg_reply - mrc p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1 - b read_cp_reg_reply - mrc p14, 0, r0, c10, c0, 0 @ XSCALE_DCSR - b read_cp_reg_reply - -read_cp_reg_reply: - bl send_to_debugger - - @ return - b get_command - -@ ---- - -write_cp_reg: - @ requested cp register - bl receive_from_debugger - mov r1, r0 - - @ value to be written - bl receive_from_debugger - - adr r2, write_cp_table - add pc, r2, r1, lsl #3 - -write_cp_table: - mcr p15, 0, r0, c0, c0, 0 @ XSCALE_MAINID (0x0) - b get_command - mcr p15, 0, r0, c0, c0, 1 @ XSCALE_CACHETYPE (0x1) - b get_command - mcr p15, 0, r0, c1, c0, 0 @ XSCALE_CTRL (0x2) - b get_command - mcr p15, 0, r0, c1, c0, 1 @ XSCALE_AUXCTRL (0x3) - b get_command - mcr p15, 0, r0, c2, c0, 0 @ XSCALE_TTB (0x4) - b get_command - mcr p15, 0, r0, c3, c0, 0 @ XSCALE_DAC (0x5) - b get_command - mcr p15, 0, r0, c5, c0, 0 @ XSCALE_FSR (0x6) - b get_command - mcr p15, 0, r0, c6, c0, 0 @ XSCALE_FAR (0x7) - b get_command - mcr p15, 0, r0, c13, c0, 0 @ XSCALE_PID (0x8) - b get_command - mcr p15, 0, r0, c15, c0, 0 @ XSCALE_CP_ACCESS (0x9) - b get_command - mcr p15, 0, r0, c14, c8, 0 @ XSCALE_IBCR0 (0xa) - b get_command - mcr p15, 0, r0, c14, c9, 0 @ XSCALE_IBCR1 (0xb) - b get_command - mcr p15, 0, r0, c14, c0, 0 @ XSCALE_DBR0 (0xc) - b get_command - mcr p15, 0, r0, c14, c3, 0 @ XSCALE_DBR1 (0xd) - b get_command - mcr p15, 0, r0, c14, c4, 0 @ XSCALE_DBCON (0xe) - b get_command - mcr p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG (0xf) - b get_command - mcr p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0 (0x10) - b get_command - mcr p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1 (0x11) - b get_command - mcr p14, 0, r0, c10, c0, 0 @ XSCALE_DCSR (0x12) - b get_command - -@ ---- - -read_trace_buffer: - - @ dump 256 entries from trace buffer - mov r1, #256 -read_tb_loop: - mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG - bl send_to_debugger - subs r1, r1, #1 - bne read_tb_loop - - @ dump checkpoint register 0 - mrc p14, 0, r0, c12, c0, 0 @ XSCALE_CHKPT0 (0x10) - bl send_to_debugger - - @ dump checkpoint register 1 - mrc p14, 0, r0, c13, c0, 0 @ XSCALE_CHKPT1 (0x11) - bl send_to_debugger - - @ return - b get_command - -@ ---- - -clean_trace_buffer: - - @ clean 256 entries from trace buffer - mov r1, #256 -clean_tb_loop: - mrc p14, 0, r0, c11, c0, 0 @ XSCALE_TBREG - subs r1, r1, #1 - bne clean_tb_loop - - @ return - b get_command - -@ ---- - - -@ resume program execution with trace buffer enabled -resume_w_trace: - @ restore CPSR (SPSR_dbg) - bl receive_from_debugger - msr spsr, r0 - - @ restore registers (r7 - r0) - bl receive_from_debugger @ r7 - mov r7, r0 - bl receive_from_debugger @ r6 - mov r6, r0 - bl receive_from_debugger @ r5 - mov r5, r0 - bl receive_from_debugger @ r4 - mov r4, r0 - bl receive_from_debugger @ r3 - mov r3, r0 - bl receive_from_debugger @ r2 - mov r2, r0 - bl receive_from_debugger @ r1 - mov r1, r0 - bl receive_from_debugger @ r0 - - @ resume addresss - m_receive_from_debugger lr - - mrc p14, 0, r13, c10, c0, 0 @ XSCALE_DCSR - orr r13, r13, #1 - mcr p14, 0, r13, c10, c0, 0 @ XSCALE_DCSR - - @ branch back to application code, restoring CPSR - subs pc, lr, #0 - -undef_handler: -swi_handler: -prefetch_abort_handler: -data_abort_handler: -irq_handler: -fiq_handler: -1: - b 1b - -send_to_debugger: - m_send_to_debugger r0 - mov pc, lr - -receive_from_debugger: - m_receive_from_debugger r0 - mov pc, lr - diff --git a/src/target/xscale/debug_handler.bin b/src/target/xscale/debug_handler.bin deleted file mode 100755 index 2dde185..0000000 Binary files a/src/target/xscale/debug_handler.bin and /dev/null differ diff --git a/src/target/xscale/debug_handler.cmd b/src/target/xscale/debug_handler.cmd deleted file mode 100644 index d943b13..0000000 --- a/src/target/xscale/debug_handler.cmd +++ /dev/null @@ -1,49 +0,0 @@ -/* identify the Entry Point */ -ENTRY(reset_handler) - -/* specify the mini-ICache memory areas */ -MEMORY -{ - mini_icache_0 (x) : ORIGIN = 0x0, LENGTH = 1024 /* first part of mini icache (sets 0-31) */ - mini_icache_1 (x) : ORIGIN = 0x400, LENGTH = 1024 /* second part of mini icache (sets 0-31) */ -} - -/* now define the output sections */ -SECTIONS -{ - .part1 : - { - LONG(0) - LONG(0) - LONG(0) - LONG(0) - LONG(0) - LONG(0) - LONG(0) - LONG(0) - *(.part1) - } >mini_icache_0 - - .part2 : - { - LONG(0) - LONG(0) - LONG(0) - LONG(0) - LONG(0) - LONG(0) - LONG(0) - LONG(0) - *(.part2) - FILL(0x0) - } >mini_icache_1 - - /DISCARD/ : - { - *(.text) - *(.glue_7) - *(.glue_7t) - *(.data) - *(.bss) - } -} diff --git a/src/target/xscale/protocol.h b/src/target/xscale/protocol.h deleted file mode 100644 index cb01655..0000000 --- a/src/target/xscale/protocol.h +++ /dev/null @@ -1,68 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2006 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, see . * - ***************************************************************************/ - -#define REG_R0 0 -#define REG_R1 1 -#define REG_R2 2 -#define REG_R3 3 -#define REG_R4 4 -#define REG_R5 5 -#define REG_R6 6 -#define REG_R7 7 -#define REG_R8 8 -#define REG_R9 9 -#define REG_R10 10 -#define REG_R11 11 -#define REG_R12 12 -#define REG_R13 13 -#define REG_R14 14 -#define REG_R15 15 -#define REG_CPSR 16 -#define REG_SPSR 17 - -#define MODE_USR 0x10 -#define MODE_FIQ 0x11 -#define MODE_IRQ 0x12 -#define MODE_SVC 0x13 -#define MODE_ABT 0x17 -#define MODE_UND 0x1b -#define MODE_SYS 0x1f - -#define MODE_ANY 0x40 -#define MODE_CURRENT 0x80 - -#define MODE_MASK 0x1f -#define PSR_I 0x80 -#define PSR_F 0x40 -#define PSR_T 0x20 - -#define XSCALE_DBG_MAINID 0x0 -#define XSCALE_DBG_CACHETYPE 0x1 -#define XSCALE_DBG_CTRL 0x2 -#define XSCALE_DBG_AUXCTRL 0x3 -#define XSCALE_DBG_TTB 0x4 -#define XSCALE_DBG_DAC 0x5 -#define XSCALE_DBG_FSR 0x6 -#define XSCALE_DBG_FAR 0x7 -#define XSCALE_DBG_PID 0x8 -#define XSCALE_DBG_CPACCESS 0x9 -#define XSCALE_DBG_IBCR0 0xa -#define XSCALE_DBG_IBCR1 0xb -#define XSCALE_DBG_DBR0 0xc -#define XSCALE_DBG_DBR1 0xd -#define XSCALE_DBG_DBCON 0xe -- cgit v1.1 From c37a88c92f0234df6206a4b58c23d20563a22afc Mon Sep 17 00:00:00 2001 From: kevin Date: Mon, 17 Oct 2016 12:46:26 +0100 Subject: flash/nor/efm32: Support flash size smaller than 32k The current implementation fails on devices with less than 32k of flash (such as several devices in the Zero Gecko family) because the 'assert' assumes (incorrectly) that the number of flash banks will always be >= 32. This change ensures that at least one word of lock bits is always read in order to support devices with less than 32k of flash. Signed-off-by: Kevlar Harness Change-Id: I59febe2cb690c893a5057a5f72918e146cf2afe4 Reviewed-on: http://openocd.zylin.com/3806 Tested-by: jenkins Reviewed-by: Marc Schink Reviewed-by: Paul Fertser --- src/flash/nor/efm32.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/flash/nor/efm32.c b/src/flash/nor/efm32.c index 0b33829..81c1a37 100644 --- a/src/flash/nor/efm32.c +++ b/src/flash/nor/efm32.c @@ -456,10 +456,10 @@ static int efm32x_read_lock_data(struct flash_bank *bank) uint32_t *ptr = NULL; int ret = 0; - assert(!(bank->num_sectors & 0x1f)); + assert(bank->num_sectors > 0); - data_size = bank->num_sectors / 8; /* number of data bytes */ - data_size /= 4; /* ...and data dwords */ + /* calculate the number of 32-bit words to read (one lock bit per sector) */ + data_size = (bank->num_sectors + 31) / 32; ptr = efm32x_info->lb_page; -- cgit v1.1 From 2e0e11b76645d6b38bc4986d8000e4e47e391596 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 30 Sep 2015 18:58:19 +0200 Subject: jlink: Add EMUCOM support EMUCOM is a way to communicate with a J-Link device via so called channels. A channel can either be read or written in a single operation. Beside the reserved channels for SEGGER, there are channels available to implement vendor and/or device specific functionalities. For example, EMUCOM is used on many starter and development kits from Silicon Labs to access power measurements and various other information and settings. Change-Id: I6094109c043b34aed4a40ceabe71f30ff896bf1d Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3794 Tested-by: jenkins Reviewed-by: Paul Fertser --- doc/openocd.texi | 20 +++++++ src/jtag/drivers/jlink.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 163 insertions(+) diff --git a/doc/openocd.texi b/doc/openocd.texi index b47d2c4..440aa04 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2702,6 +2702,26 @@ Reset the current configuration. @deffn {Command} {jlink config write} Write the current configuration to the internal persistent storage. @end deffn +@deffn {Command} {jlink emucom write } +Write data to an EMUCOM channel. The data needs to be encoded as hexadecimal +pairs. + +The following example shows how to write the three bytes 0xaa, 0x0b and 0x23 to +the EMUCOM channel 0x10: +@example +> jlink emucom write 0x10 aa0b23 +@end example +@end deffn +@deffn {Command} {jlink emucom read } +Read data from an EMUCOM channel. The read data is encoded as hexadecimal +pairs. + +The following example shows how to read 4 bytes from the EMUCOM channel 0x0: +@example +> jlink emucom read 0x0 4 +77a90000 +@end example +@end deffn @deffn {Config} {jlink usb} <@option{0} to @option{3}> Set the USB address of the interface, in case more than one adapter is connected to the host. If not specified, USB addresses are not considered. Device diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 95c6d8d..e5bfd32 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -1602,6 +1602,125 @@ COMMAND_HANDLER(jlink_handle_config_command) return ERROR_OK; } +COMMAND_HANDLER(jlink_handle_emucom_write_command) +{ + int ret; + size_t tmp; + uint32_t channel; + uint32_t length; + uint8_t *buf; + size_t dummy; + + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_EMUCOM)) { + LOG_ERROR("Device does not support EMUCOM."); + return ERROR_FAIL; + } + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], channel); + + tmp = strlen(CMD_ARGV[1]); + + if (tmp % 2 != 0) { + LOG_ERROR("Data must be encoded as hexadecimal pairs."); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + buf = malloc(tmp / 2); + + if (!buf) { + LOG_ERROR("Failed to allocate buffer."); + return ERROR_FAIL; + } + + dummy = unhexify(buf, CMD_ARGV[1], tmp / 2); + + if (dummy != (tmp / 2)) { + LOG_ERROR("Data must be encoded as hexadecimal pairs."); + free(buf); + return ERROR_COMMAND_ARGUMENT_INVALID; + } + + length = tmp / 2; + ret = jaylink_emucom_write(devh, channel, buf, &length); + + free(buf); + + if (ret == JAYLINK_ERR_DEV_NOT_SUPPORTED) { + LOG_ERROR("Channel not supported by the device."); + return ERROR_FAIL; + } else if (ret != JAYLINK_OK) { + LOG_ERROR("Failed to write to channel: %s.", + jaylink_strerror_name(ret)); + return ERROR_FAIL; + } + + if (length != (tmp / 2)) + LOG_WARNING("Only %" PRIu32 " bytes written to the channel.", length); + + return ERROR_OK; +} + +COMMAND_HANDLER(jlink_handle_emucom_read_command) +{ + int ret; + uint32_t channel; + uint32_t length; + uint8_t *buf; + size_t tmp; + + if (CMD_ARGC != 2) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (!jaylink_has_cap(caps, JAYLINK_DEV_CAP_EMUCOM)) { + LOG_ERROR("Device does not support EMUCOM."); + return ERROR_FAIL; + } + + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], channel); + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); + + buf = malloc(length * 3 + 1); + + if (!buf) { + LOG_ERROR("Failed to allocate buffer."); + return ERROR_FAIL; + } + + ret = jaylink_emucom_read(devh, channel, buf, &length); + + if (ret == JAYLINK_ERR_DEV_NOT_SUPPORTED) { + LOG_ERROR("Channel is not supported by the device."); + free(buf); + return ERROR_FAIL; + } else if (ret == JAYLINK_ERR_DEV_NOT_AVAILABLE) { + LOG_ERROR("Channel is not available for the requested amount of data. " + "%" PRIu32 " bytes are avilable.", length); + free(buf); + return ERROR_FAIL; + } else if (ret != JAYLINK_OK) { + LOG_ERROR("Failed to read from channel: %s.", + jaylink_strerror_name(ret)); + free(buf); + return ERROR_FAIL; + } + + tmp = hexify((char *)buf + length, buf, length, 2 * length + 1); + + if (tmp != 2 * length) { + LOG_ERROR("Failed to convert data into hexadecimal string."); + free(buf); + return ERROR_FAIL; + } + + command_print(CMD_CTX, "%s", buf + length); + free(buf); + + return ERROR_OK; +} + static const struct command_registration jlink_config_subcommand_handlers[] = { { .name = "usb", @@ -1647,6 +1766,24 @@ static const struct command_registration jlink_config_subcommand_handlers[] = { COMMAND_REGISTRATION_DONE }; +static const struct command_registration jlink_emucom_subcommand_handlers[] = { + { + .name = "write", + .handler = &jlink_handle_emucom_write_command, + .mode = COMMAND_EXEC, + .help = "write to a channel", + .usage = " ", + }, + { + .name = "read", + .handler = &jlink_handle_emucom_read_command, + .mode = COMMAND_EXEC, + .help = "read from a channel", + .usage = " " + }, + COMMAND_REGISTRATION_DONE +}; + static const struct command_registration jlink_subcommand_handlers[] = { { .name = "jtag", @@ -1696,6 +1833,12 @@ static const struct command_registration jlink_subcommand_handlers[] = { "this will show the device configuration", .chain = jlink_config_subcommand_handlers, }, + { + .name = "emucom", + .mode = COMMAND_EXEC, + .help = "access EMUCOM channel", + .chain = jlink_emucom_subcommand_handlers + }, COMMAND_REGISTRATION_DONE }; -- cgit v1.1 From a2942c95c818f98a0f8605449a17b0a794ef9a50 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Wed, 16 Nov 2016 14:21:52 +0100 Subject: libjaylink: Update to latest master branch The changes since the last update are mainly related to the build system, preparations and cleanups for the upcoming release. If there are no bugs reported, this will be the last update before the libjaylink 0.1.0 release. Change-Id: I4cec9bb61159f6153690aaf39c1d12ba0baacf9b Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3886 Tested-by: jenkins Reviewed-by: Xiaofan Reviewed-by: Paul Fertser --- src/jtag/drivers/jlink.c | 12 ++++++------ src/jtag/drivers/libjaylink | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index e5bfd32..65ff81a 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -674,7 +674,7 @@ static int jlink_init(void) } } - jtag_command_version = JAYLINK_JTAG_V2; + jtag_command_version = JAYLINK_JTAG_VERSION_2; if (jaylink_has_cap(caps, JAYLINK_DEV_CAP_GET_HW_VERSION)) { ret = jaylink_get_hardware_version(devh, &hwver); @@ -690,7 +690,7 @@ static int jlink_init(void) LOG_INFO("Hardware version: %u.%02u", hwver.major, hwver.minor); if (hwver.major >= 5) - jtag_command_version = JAYLINK_JTAG_V3; + jtag_command_version = JAYLINK_JTAG_VERSION_3; } if (iface == JAYLINK_TIF_SWD) { @@ -1008,10 +1008,10 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command) if (!CMD_ARGC) { switch (jtag_command_version) { - case JAYLINK_JTAG_V2: + case JAYLINK_JTAG_VERSION_2: version = 2; break; - case JAYLINK_JTAG_V3: + case JAYLINK_JTAG_VERSION_3: version = 3; break; default: @@ -1027,10 +1027,10 @@ COMMAND_HANDLER(jlink_handle_jlink_jtag_command) switch (tmp) { case 2: - jtag_command_version = JAYLINK_JTAG_V2; + jtag_command_version = JAYLINK_JTAG_VERSION_2; break; case 3: - jtag_command_version = JAYLINK_JTAG_V3; + jtag_command_version = JAYLINK_JTAG_VERSION_3; break; default: command_print(CMD_CTX, "Invalid argument: %s.", CMD_ARGV[0]); diff --git a/src/jtag/drivers/libjaylink b/src/jtag/drivers/libjaylink index 58a409d..dfa9bc8 160000 --- a/src/jtag/drivers/libjaylink +++ b/src/jtag/drivers/libjaylink @@ -1 +1 @@ -Subproject commit 58a409dcbc83b63417d5dc2b4c3cb0bd3e0e53fd +Subproject commit dfa9bc8e91b0c3a89df3ceaf78c93780fd0a186e -- cgit v1.1 From 082b88bc8ae5ba71b06a6c7e6e1ce1d26657dbb5 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 18 Nov 2016 17:27:16 +0100 Subject: jlink: Output libjaylink version Output the package version of libjaylink to ease debugging. Change-Id: I3b9da6d046d140ba850056c98e67bed22c885ee0 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3887 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/jtag/drivers/jlink.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/jtag/drivers/jlink.c b/src/jtag/drivers/jlink.c index 65ff81a..bd3c5e0 100644 --- a/src/jtag/drivers/jlink.c +++ b/src/jtag/drivers/jlink.c @@ -545,6 +545,9 @@ static int jlink_init(void) enum jaylink_usb_address address; size_t length; + LOG_DEBUG("Using libjaylink %s (compiled with %s).", + jaylink_version_package_get_string(), JAYLINK_VERSION_PACKAGE_STRING); + ret = jaylink_init(&jayctx); if (ret != JAYLINK_OK) { -- cgit v1.1 From 44f21c9d4362e479158d0852bc16c0cde5d5b53d Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Tue, 16 Feb 2016 23:26:58 +0100 Subject: configure: Replace shell constructs with M4sh macros AS_IF and AS_CASE should be used instead of if and case to properly handle macros in conditional branches. Also guard all tests against empty variables and embedded spaces which makes it possible to remove some variable defaults. Change-Id: Ib675177690d406a80ee98dd5d105296a7cdc7b8a Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3669 Tested-by: jenkins Reviewed-by: Paul Fertser --- configure.ac | 409 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 198 insertions(+), 211 deletions(-) diff --git a/configure.ac b/configure.ac index e7c6ee1..9ac4110 100644 --- a/configure.ac +++ b/configure.ac @@ -7,10 +7,10 @@ m4_include([config_subdir.m4])dnl # check for makeinfo before calling AM_INIT_AUTOMAKE AC_CHECK_PROG([MAKEINFO], [makeinfo], [makeinfo]) -if test "x$MAKEINFO" = "x"; then +AS_IF([test "x$MAKEINFO" = "x"], [ MAKEINFO='echo makeinfo missing; true' AC_MSG_WARN([Info documentation will not be built.]) -fi +]) AC_SUBST([MAKEINFO]) AM_INIT_AUTOMAKE([-Wall -Wno-portability dist-bzip2 dist-zip subdir-objects]) @@ -143,20 +143,13 @@ AC_CHECK_FUNCS([gettimeofday]) AC_CHECK_FUNCS([usleep]) AC_CHECK_FUNCS([vasprintf]) -build_bitbang=no -build_bitq=no -is_cygwin=no -is_mingw=no -is_win32=no -is_darwin=no - # guess-rev.sh only exists in the repository, not in the released archives AC_MSG_CHECKING([whether to build a release]) -if test -x $srcdir/guess-rev.sh ; then +AS_IF([test -x "$srcdir/guess-rev.sh"], [ build_release=no -else +], [ build_release=yes -fi +]) AC_MSG_RESULT([$build_release]) # Adapter drivers @@ -258,21 +251,21 @@ AC_ARG_ENABLE([verbose_usb_comms], AC_MSG_CHECKING([whether to enable verbose JTAG I/O messages]); AC_MSG_RESULT([$debug_jtag_io]) -if test $debug_jtag_io = yes; then +AS_IF([test "x$debug_jtag_io" = "xyes"], [ AC_DEFINE([_DEBUG_JTAG_IO_],[1], [Print verbose JTAG I/O messages]) -fi +]) AC_MSG_CHECKING([whether to enable verbose USB I/O messages]); AC_MSG_RESULT([$debug_usb_io]) -if test $debug_usb_io = yes; then +AS_IF([test "x$debug_usb_io" = "xyes"], [ AC_DEFINE([_DEBUG_USB_IO_],[1], [Print verbose USB I/O messages]) -fi +]) AC_MSG_CHECKING([whether to enable verbose USB communication messages]); AC_MSG_RESULT([$debug_usb_comms]) -if test $debug_usb_comms = yes; then +AS_IF([test "x$debug_usb_comms" = "xyes"], [ AC_DEFINE([_DEBUG_USB_COMMS_],[1], [Print verbose USB communication messages]) -fi +]) debug_malloc=no AC_ARG_ENABLE([malloc_logging], @@ -282,9 +275,9 @@ AC_ARG_ENABLE([malloc_logging], AC_MSG_CHECKING([whether to enable malloc free space logging]); AC_MSG_RESULT([$debug_malloc]) -if test $debug_malloc = yes; then +AS_IF([test "x$debug_malloc" = "xyes"], [ AC_DEFINE([_DEBUG_FREE_SPACE_],[1], [Include malloc free space in logging]) -fi +]) AC_ARG_ENABLE([dummy], AS_HELP_STRING([--enable-dummy], [Enable building the dummy port driver]), @@ -342,8 +335,8 @@ AC_ARG_ENABLE([ioutil], AS_HELP_STRING([--enable-ioutil], [Enable ioutil functions - useful for standalone OpenOCD implementations]), [build_ioutil=$enableval], [build_ioutil=no]) -case "${host_cpu}" in - arm*) +AS_CASE(["${host_cpu}"], + [arm*], [ AC_ARG_ENABLE([ep93xx], AS_HELP_STRING([--enable-ep93xx], [Enable building support for EP93xx based SBCs]), [build_ep93xx=$enableval], [build_ep93xx=no]) @@ -355,14 +348,12 @@ case "${host_cpu}" in AC_ARG_ENABLE([bcm2835gpio], AS_HELP_STRING([--enable-bcm2835gpio], [Enable building support for bitbanging on BCM2835 (as found in Raspberry Pi)]), [build_bcm2835gpio=$enableval], [build_bcm2835gpio=no]) - ;; - - *) + ], + [ build_ep93xx=no build_at91rm9200=no build_bcm2835gpio=no - ;; -esac +]) AC_ARG_ENABLE([gw16012], AS_HELP_STRING([--enable-gw16012], [Enable building support for the Gateworks GW16012 JTAG Programmer]), @@ -396,14 +387,14 @@ AC_ARG_ENABLE([internal-libjaylink], build_minidriver=no AC_MSG_CHECKING([whether to enable ZY1000 minidriver]) -if test $build_zy1000 = yes; then - if test $build_minidriver = yes; then +AS_IF([test "x$build_zy1000" = "xyes"], [ + AS_IF([test "x$build_minidriver" = "xyes"], [ AC_MSG_ERROR([Multiple minidriver options have been enabled.]) - fi + ]) AC_DEFINE([HAVE_JTAG_MINIDRIVER_H], [1], [Define to 1 if you have the header file.]) build_minidriver=yes -fi +]) AC_MSG_RESULT([$build_zy1000]) AC_ARG_ENABLE([remote-bitbang], @@ -411,220 +402,217 @@ AC_ARG_ENABLE([remote-bitbang], [build_remote_bitbang=$enableval], [build_remote_bitbang=no]) AC_MSG_CHECKING([whether to enable dummy minidriver]) -if test $build_minidriver_dummy = yes; then - if test $build_minidriver = yes; then +AS_IF([test "x$build_minidriver_dummy" = "xyes"], [ + AS_IF([test "x$build_minidriver" = "xyes"], [ AC_MSG_ERROR([Multiple minidriver options have been enabled.]) - fi + ]) build_minidriver=yes AC_DEFINE([BUILD_MINIDRIVER_DUMMY], [1], [Use the dummy minidriver.]) AC_DEFINE([HAVE_JTAG_MINIDRIVER_H], [1], [Define to 1 if you have the header file.]) -fi +]) AC_MSG_RESULT([$build_minidriver_dummy]) AC_MSG_CHECKING([whether standard drivers can be built]) -if test "$build_minidriver" = yes; then +AS_IF([test "x$build_minidriver" = "xyes"], [ AC_MSG_RESULT([no]) AC_MSG_WARN([Using the minidriver disables all other drivers.]) sleep 2 -else +], [ AC_MSG_RESULT([yes]) -fi +]) -case "${host_cpu}" in - i?86|x86*) - ;; - *) - if test x$parport_use_ppdev = xno; then +AS_CASE(["${host_cpu}"], + [i?86|x86*], [], + [ + AS_IF([test "x$parport_use_ppdev" = "xno"], [ AC_MSG_WARN([--disable-parport-ppdev is not supported by the host CPU]) - fi + ]) parport_use_ppdev=yes - ;; -esac +]) -case $host in - *-cygwin*) +AS_CASE([$host], + [*-cygwin*], [ is_win32=yes parport_use_ppdev=no AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[return __MINGW32__;]])], [is_mingw=yes],[is_mingw=no]) - if test $is_mingw = yes; then + AS_IF([test "x$is_mingw" = "xyes"], [ AC_DEFINE([IS_MINGW], [1], [1 if building for MinGW.]) - if test x$parport_use_giveio = xno; then + AS_IF([test "x$parport_use_giveio" = "xno"], [ AC_MSG_WARN([--disable-parport-giveio is not supported by MinGW32 hosts]) - fi + ]) parport_use_giveio=yes is_cygwin=no - else + ], [ is_cygwin=yes AC_DEFINE([IS_CYGWIN], [1], [1 if building for Cygwin.]) # sys/io.h needed under cygwin for parport access - if test $build_parport = yes; then + AS_IF([test "x$build_parport" = "xyes"], [ AC_CHECK_HEADERS([sys/io.h],[],AC_MSG_ERROR([Please install the cygwin ioperm package])) - fi - fi + ]) + ]) AC_DEFINE([IS_WIN32], [1], [1 if building for Win32.]) AC_DEFINE([IS_DARWIN], [0], [0 if not building for Darwin.]) - ;; - *-mingw* | *-msys*) + ], + [*-mingw* | *-msys*], [ is_mingw=yes is_win32=yes parport_use_ppdev=no - if test x$parport_use_giveio = xno; then + AS_IF([test "x$parport_use_giveio" = "xno"], [ AC_MSG_WARN([--disable-parport-giveio is not supported by MinGW32 hosts]) - fi + ]) parport_use_giveio=yes - if test x$build_buspirate = xyes; then + AS_IF([test "x$build_buspirate" = "xyes"], [ AC_MSG_ERROR([buspirate currently not supported by MinGW32 hosts]) - fi + ]) CFLAGS="$CFLAGS -D__USE_MINGW_ANSI_STDIO" AC_DEFINE([IS_MINGW], [1], [1 if building for MinGW.]) AC_DEFINE([IS_WIN32], [1], [1 if building for Win32.]) AC_DEFINE([IS_DARWIN], [0], [0 if not building for Darwin.]) - ;; - *darwin*) + ], + [*darwin*], [ is_darwin=yes - if test x$parport_use_giveio = xyes; then + AS_IF([test "x$parport_use_giveio" = "xyes"], [ AC_MSG_WARN([--enable-parport-giveio cannot be used by Darwin hosts]) - fi + ]) parport_use_giveio=no AC_DEFINE([IS_CYGWIN], [0], [0 if not building for Cygwin.]) AC_DEFINE([IS_WIN32], [0], [0 if not building for Win32.]) AC_DEFINE([IS_DARWIN], [1], [1 if building for Darwin.]) - ;; - *) - if test x$parport_use_giveio = xyes; then + ], + [ + AS_IF([test "x$parport_use_giveio" = "xyes"], [ AC_MSG_WARN([--enable-parport-giveio cannot be used by ]$host[ hosts]) - fi + ]) parport_use_giveio=no AC_DEFINE([IS_CYGWIN], [0], [0 if not building for Cygwin.]) AC_DEFINE([IS_WIN32], [0], [0 if not building for Win32.]) AC_DEFINE([IS_DARWIN], [0], [0 if not building for Darwin.]) - ;; -esac +]) -if test $is_win32 = yes; then +AS_IF([test "x$is_win32" = "xyes"], [ AC_DEFINE([WIN32_LEAN_AND_MEAN], [1], [1 to exclude old conflicting definitions when building on Windows]) -fi +]) -if test $build_parport = yes; then +AS_IF([test "x$build_parport" = "xyes"], [ build_bitbang=yes AC_DEFINE([BUILD_PARPORT], [1], [1 if you want parport.]) -else +], [ AC_DEFINE([BUILD_PARPORT], [0], [0 if you don't want parport.]) -fi +]) -if test $build_dummy = yes; then +AS_IF([test "x$build_dummy" = "xyes"], [ build_bitbang=yes AC_DEFINE([BUILD_DUMMY], [1], [1 if you want dummy driver.]) -else +], [ AC_DEFINE([BUILD_DUMMY], [0], [0 if you don't want dummy driver.]) -fi +]) -if test $build_ep93xx = yes; then +AS_IF([test "x$build_ep93xx" = "xyes"], [ build_bitbang=yes AC_DEFINE([BUILD_EP93XX], [1], [1 if you want ep93xx.]) -else +], [ AC_DEFINE([BUILD_EP93XX], [0], [0 if you don't want ep93xx.]) -fi +]) -if test $build_zy1000 = yes; then +AS_IF([test "x$build_zy1000" = "xyes"], [ AC_DEFINE([BUILD_ZY1000], [1], [1 if you want ZY1000.]) -else +], [ AC_DEFINE([BUILD_ZY1000], [0], [0 if you don't want ZY1000.]) -fi +]) -if test $build_zy1000_master = yes; then +AS_IF([test "x$build_zy1000_master" = "xyes"], [ AC_DEFINE([BUILD_ZY1000_MASTER], [1], [1 if you want ZY1000 JTAG master registers.]) -else +], [ AC_DEFINE([BUILD_ZY1000_MASTER], [0], [0 if you don't want ZY1000 JTAG master registers.]) -fi +]) -if test $build_at91rm9200 = yes; then +AS_IF([test "x$build_at91rm9200" = "xyes"], [ build_bitbang=yes AC_DEFINE([BUILD_AT91RM9200], [1], [1 if you want at91rm9200.]) -else +], [ AC_DEFINE([BUILD_AT91RM9200], [0], [0 if you don't want at91rm9200.]) -fi +]) -if test $build_bcm2835gpio = yes; then +AS_IF([test "x$build_bcm2835gpio" = "xyes"], [ build_bitbang=yes AC_DEFINE([BUILD_BCM2835GPIO], [1], [1 if you want bcm2835gpio.]) -else +], [ AC_DEFINE([BUILD_BCM2835GPIO], [0], [0 if you don't want bcm2835gpio.]) -fi +]) -if test x$parport_use_ppdev = xyes; then +AS_IF([test "x$parport_use_ppdev" = "xyes"], [ AC_DEFINE([PARPORT_USE_PPDEV], [1], [1 if you want parport to use ppdev.]) -else +], [ AC_DEFINE([PARPORT_USE_PPDEV], [0], [0 if you don't want parport to use ppdev.]) -fi +]) -if test x$parport_use_giveio = xyes; then +AS_IF([test "x$parport_use_giveio" = "xyes"], [ AC_DEFINE([PARPORT_USE_GIVEIO], [1], [1 if you want parport to use giveio.]) -else +], [ AC_DEFINE([PARPORT_USE_GIVEIO], [0], [0 if you don't want parport to use giveio.]) -fi +]) -if test $build_jtag_vpi = yes; then +AS_IF([test "x$build_jtag_vpi" = "xyes"], [ AC_DEFINE([BUILD_JTAG_VPI], [1], [1 if you want JTAG VPI.]) -else +], [ AC_DEFINE([BUILD_JTAG_VPI], [0], [0 if you don't want JTAG VPI.]) -fi +]) -if test $build_amtjtagaccel = yes; then +AS_IF([test "x$build_amtjtagaccel" = "xyes"], [ AC_DEFINE([BUILD_AMTJTAGACCEL], [1], [1 if you want the Amontec JTAG-Accelerator driver.]) -else +], [ AC_DEFINE([BUILD_AMTJTAGACCEL], [0], [0 if you don't want the Amontec JTAG-Accelerator driver.]) -fi +]) -if test $build_gw16012 = yes; then +AS_IF([test "x$build_gw16012" = "xyes"], [ AC_DEFINE([BUILD_GW16012], [1], [1 if you want the Gateworks GW16012 driver.]) -else +], [ AC_DEFINE([BUILD_GW16012], [0], [0 if you don't want the Gateworks GW16012 driver.]) -fi +]) -if test $build_oocd_trace = yes; then +AS_IF([test "x$build_oocd_trace" = "xyes"], [ AC_DEFINE([BUILD_OOCD_TRACE], [1], [1 if you want the OpenOCD+trace ETM capture driver.]) -else +], [ AC_DEFINE([BUILD_OOCD_TRACE], [0], [0 if you don't want the OpenOCD+trace ETM capture driver.]) -fi +]) -if test $build_buspirate = yes; then +AS_IF([test "x$build_buspirate" = "xyes"], [ AC_DEFINE([BUILD_BUSPIRATE], [1], [1 if you want the Buspirate JTAG driver.]) -else +], [ AC_DEFINE([BUILD_BUSPIRATE], [0], [0 if you don't want the Buspirate JTAG driver.]) -fi +]) -if test $use_internal_jimtcl = yes; then - if test -f "$srcdir/jimtcl/configure.ac"; then +AS_IF([test "x$use_internal_jimtcl" = "xyes"], [ + AS_IF([test -f "$srcdir/jimtcl/configure.ac"], [ AX_CONFIG_SUBDIR_OPTION([jimtcl], [--disable-install-jim]) - else + ], [ AC_MSG_ERROR([jimtcl not found, run git submodule init and git submodule update.]) - fi -fi + ]) +]) -if test $build_remote_bitbang = yes; then +AS_IF([test "x$build_remote_bitbang" = "xyes"], [ build_bitbang=yes AC_DEFINE([BUILD_REMOTE_BITBANG], [1], [1 if you want the Remote Bitbang JTAG driver.]) -else +], [ AC_DEFINE([BUILD_REMOTE_BITBANG], [0], [0 if you don't want the Remote Bitbang JTAG driver.]) -fi +]) -if test $build_sysfsgpio = yes; then +AS_IF([test "x$build_sysfsgpio" = "xyes"], [ build_bitbang=yes AC_DEFINE([BUILD_SYSFSGPIO], [1], [1 if you want the SysfsGPIO driver.]) -else +], [ AC_DEFINE([BUILD_SYSFSGPIO], [0], [0 if you don't want SysfsGPIO driver.]) -fi +]) PKG_CHECK_MODULES([LIBUSB1], [libusb-1.0], [ use_libusb1=yes @@ -661,92 +649,92 @@ PKG_CHECK_MODULES([libjaylink], [libjaylink >= 0.1], m4_define([PROCESS_ADAPTERS], [ m4_foreach([adapter], [$1], [ - if test $2; then - if test $ADAPTER_VAR([adapter]) != no; then + AS_IF([test $2], [ + AS_IF([test "x$ADAPTER_VAR([adapter])" != "xno"], [ AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [1], [1 if you want the ]ADAPTER_DESC([adapter]).) - else + ], [ AC_DEFINE([BUILD_]ADAPTER_SYM([adapter]), [0], [0 if you do not want the ]ADAPTER_DESC([adapter]).) - fi - else - if test $ADAPTER_VAR([adapter]) = yes; then + ]) + ], [ + AS_IF([test "x$ADAPTER_VAR([adapter])" = "xyes"], [ AC_MSG_ERROR([$3 is required for the ADAPTER_DESC([adapter])]) - fi + ]) ADAPTER_VAR([adapter])=no - fi - AM_CONDITIONAL(ADAPTER_SYM([adapter]), [test $ADAPTER_VAR([adapter]) != no]) + ]) + AM_CONDITIONAL(ADAPTER_SYM([adapter]), [test "x$ADAPTER_VAR([adapter])" != "xno"]) ]) ]) -PROCESS_ADAPTERS([USB1_ADAPTERS], [$use_libusb1 = yes], [libusb-1.x]) -PROCESS_ADAPTERS([USB_ADAPTERS], [$use_libusb1 = yes -o $use_libusb0 = yes], [libusb-1.x or libusb-0.1]) -PROCESS_ADAPTERS([USB0_ADAPTERS], [$use_libusb0 = yes], [libusb-0.1]) -PROCESS_ADAPTERS([HIDAPI_ADAPTERS], [$use_hidapi = yes], [hidapi]) -PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], [$use_libftdi = yes], [libftdi]) -PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], [$use_libusb1 = yes -a $use_internal_libjaylink = yes -o $HAVE_LIBJAYLINK = yes], [libusb-1.x or libjaylink-0.1]) - -if test $build_openjtag = yes; then - if test $use_libusb1 != yes -a $use_libusb0 != yes; then - AC_MSG_ERROR([libusb-1.x or libusb-0.1 is required for the OpenJTAG Programmer]) - build_openjtag=no - fi -fi +PROCESS_ADAPTERS([USB1_ADAPTERS], ["x$use_libusb1" = "xyes"], [libusb-1.x]) +PROCESS_ADAPTERS([USB_ADAPTERS], ["x$use_libusb1" = "xyes" -o "x$use_libusb0" = "xyes"], [libusb-1.x or libusb-0.1]) +PROCESS_ADAPTERS([USB0_ADAPTERS], ["x$use_libusb0" = "xyes"], [libusb-0.1]) +PROCESS_ADAPTERS([HIDAPI_ADAPTERS], ["x$use_hidapi" = "xyes"], [hidapi]) +PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], ["x$use_libftdi" = "xyes"], [libftdi]) +PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_libusb1" = "xyes" -a "x$use_internal_libjaylink" = "xyes" -o "x$HAVE_LIBJAYLINK" = "xyes"], [libusb-1.x or libjaylink-0.1]) + +AS_IF([test "x$build_openjtag" = "xyes"], [ + AS_IF([test "x$use_libusb1" != "xyes" -a "x$use_libusb0" != "xyes"], [ + AC_MSG_ERROR([libusb-1.x or libusb-0.1 is required for the OpenJTAG Programmer]) + build_openjtag=no + ]) +]) -if test $enable_stlink != no -o $enable_ti_icdi != no; then +AS_IF([test "x$enable_stlink" != "xno" -o "x$enable_ti_icdi" != "xno"], [ AC_DEFINE([BUILD_HLADAPTER], [1], [1 if you want the High Level JTAG driver.]) -else +], [ AC_DEFINE([BUILD_HLADAPTER], [0], [0 if you want the High Level JTAG driver.]) -fi -AM_CONDITIONAL([HLADAPTER], [test $enable_stlink != no -o $enable_ti_icdi != no]) +]) +AM_CONDITIONAL([HLADAPTER], [test "x$enable_stlink" != "xno" -o "x$enable_ti_icdi" != "xno"]) -if test $enable_jlink != no; then - if test $use_internal_libjaylink = yes; then - if test -f "$srcdir/src/jtag/drivers/libjaylink/configure.ac"; then +AS_IF([test "x$enable_jlink" != "xno"], [ + AS_IF([test "x$use_internal_libjaylink" = "xyes"], [ + AS_IF([test -f "$srcdir/src/jtag/drivers/libjaylink/configure.ac"], [ AX_CONFIG_SUBDIR_OPTION([src/jtag/drivers/libjaylink], [--enable-subproject-build]) - else + ], [ AC_MSG_ERROR([Internal libjaylink not found, run either 'git submodule init' and 'git submodule update' or disable internal libjaylink with --disable-internal-libjaylink.]) - fi - fi -fi + ]) + ]) +]) # Presto needs the bitq module -if test $enable_presto != no; then +AS_IF([test "x$enable_presto" != "xno"], [ build_bitq=yes -fi - -AM_CONDITIONAL([RELEASE], [test $build_release = yes]) -AM_CONDITIONAL([PARPORT], [test $build_parport = yes]) -AM_CONDITIONAL([DUMMY], [test $build_dummy = yes]) -AM_CONDITIONAL([GIVEIO], [test x$parport_use_giveio = xyes]) -AM_CONDITIONAL([EP93XX], [test $build_ep93xx = yes]) -AM_CONDITIONAL([ZY1000], [test $build_zy1000 = yes]) -AM_CONDITIONAL([ZY1000_MASTER], [test $build_zy1000_master = yes]) -AM_CONDITIONAL([IOUTIL], [test $build_ioutil = yes]) -AM_CONDITIONAL([AT91RM9200], [test $build_at91rm9200 = yes]) -AM_CONDITIONAL([BCM2835GPIO], [test $build_bcm2835gpio = yes]) -AM_CONDITIONAL([BITBANG], [test $build_bitbang = yes]) -AM_CONDITIONAL([JTAG_VPI], [test $build_jtag_vpi = yes -o $build_jtag_vpi = yes]) -AM_CONDITIONAL([USB_BLASTER_DRIVER], [test $enable_usb_blaster != no -o $enable_usb_blaster_2 != no]) -AM_CONDITIONAL([AMTJTAGACCEL], [test $build_amtjtagaccel = yes]) -AM_CONDITIONAL([GW16012], [test $build_gw16012 = yes]) -AM_CONDITIONAL([OOCD_TRACE], [test $build_oocd_trace = yes]) -AM_CONDITIONAL([REMOTE_BITBANG], [test $build_remote_bitbang = yes]) -AM_CONDITIONAL([BUSPIRATE], [test $build_buspirate = yes]) -AM_CONDITIONAL([SYSFSGPIO], [test $build_sysfsgpio = yes]) -AM_CONDITIONAL([USE_LIBUSB0], [test $use_libusb0 = yes]) -AM_CONDITIONAL([USE_LIBUSB1], [test $use_libusb1 = yes]) -AM_CONDITIONAL([IS_CYGWIN], [test $is_cygwin = yes]) -AM_CONDITIONAL([IS_MINGW], [test $is_mingw = yes]) -AM_CONDITIONAL([IS_WIN32], [test $is_win32 = yes]) -AM_CONDITIONAL([IS_DARWIN], [test $is_darwin = yes]) -AM_CONDITIONAL([BITQ], [test $build_bitq = yes]) -AM_CONDITIONAL([USE_LIBFTDI], [test $use_libftdi = yes]) - -AM_CONDITIONAL([MINIDRIVER], [test $build_minidriver = yes]) -AM_CONDITIONAL([MINIDRIVER_DUMMY], [test $build_minidriver_dummy = yes]) - -AM_CONDITIONAL([INTERNAL_JIMTCL], [test $use_internal_jimtcl = yes]) -AM_CONDITIONAL([INTERNAL_LIBJAYLINK], [test $use_internal_libjaylink = yes]) +]) + +AM_CONDITIONAL([RELEASE], [test "x$build_release" = "xyes"]) +AM_CONDITIONAL([PARPORT], [test "x$build_parport" = "xyes"]) +AM_CONDITIONAL([DUMMY], [test "x$build_dummy" = "xyes"]) +AM_CONDITIONAL([GIVEIO], [test "x$parport_use_giveio" = "xyes"]) +AM_CONDITIONAL([EP93XX], [test "x$build_ep93xx" = "xyes"]) +AM_CONDITIONAL([ZY1000], [test "x$build_zy1000" = "xyes"]) +AM_CONDITIONAL([ZY1000_MASTER], [test "x$build_zy1000_master" = "xyes"]) +AM_CONDITIONAL([IOUTIL], [test "x$build_ioutil" = "xyes"]) +AM_CONDITIONAL([AT91RM9200], [test "x$build_at91rm9200" = "xyes"]) +AM_CONDITIONAL([BCM2835GPIO], [test "x$build_bcm2835gpio" = "xyes"]) +AM_CONDITIONAL([BITBANG], [test "x$build_bitbang" = "xyes"]) +AM_CONDITIONAL([JTAG_VPI], [test "x$build_jtag_vpi" = "xyes" -o "x$build_jtag_vpi" = "xyes"]) +AM_CONDITIONAL([USB_BLASTER_DRIVER], [test "x$enable_usb_blaster" != "xno" -o "x$enable_usb_blaster_2" != "xno"]) +AM_CONDITIONAL([AMTJTAGACCEL], [test "x$build_amtjtagaccel" = "xyes"]) +AM_CONDITIONAL([GW16012], [test "x$build_gw16012" = "xyes"]) +AM_CONDITIONAL([OOCD_TRACE], [test "x$build_oocd_trace" = "xyes"]) +AM_CONDITIONAL([REMOTE_BITBANG], [test "x$build_remote_bitbang" = "xyes"]) +AM_CONDITIONAL([BUSPIRATE], [test "x$build_buspirate" = "xyes"]) +AM_CONDITIONAL([SYSFSGPIO], [test "x$build_sysfsgpio" = "xyes"]) +AM_CONDITIONAL([USE_LIBUSB0], [test "x$use_libusb0" = "xyes"]) +AM_CONDITIONAL([USE_LIBUSB1], [test "x$use_libusb1" = "xyes"]) +AM_CONDITIONAL([IS_CYGWIN], [test "x$is_cygwin" = "xyes"]) +AM_CONDITIONAL([IS_MINGW], [test "x$is_mingw" = "xyes"]) +AM_CONDITIONAL([IS_WIN32], [test "x$is_win32" = "xyes"]) +AM_CONDITIONAL([IS_DARWIN], [test "x$is_darwin" = "xyes"]) +AM_CONDITIONAL([BITQ], [test "x$build_bitq" = "xyes"]) +AM_CONDITIONAL([USE_LIBFTDI], [test "x$use_libftdi" = "xyes"]) + +AM_CONDITIONAL([MINIDRIVER], [test "x$build_minidriver" = "xyes"]) +AM_CONDITIONAL([MINIDRIVER_DUMMY], [test "x$build_minidriver_dummy" = "xyes"]) + +AM_CONDITIONAL([INTERNAL_JIMTCL], [test "x$use_internal_jimtcl" = "xyes"]) +AM_CONDITIONAL([INTERNAL_LIBJAYLINK], [test "x$use_internal_libjaylink" = "xyes"]) # Look for environ alternatives. Possibility #1: is environ in unistd.h or stdlib.h? AC_MSG_CHECKING([for environ in unistd.h and stdlib.h]) @@ -775,28 +763,28 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ AC_MSG_RESULT([${has_environ}]) ]) -if test "${has_environ}" != "yes" ; then +AS_IF([test "x${has_environ}" != "xyes" ], [ AC_MSG_FAILURE([Could not find 'environ' in unistd.h or available libraries.]) -fi +]) AC_DEFINE([_GNU_SOURCE],[1],[Use GNU C library extensions (e.g. stdndup).]) # set default gcc warnings GCC_WARNINGS="-Wall -Wstrict-prototypes -Wformat-security -Wshadow" -if test "${gcc_wextra}" = yes; then +AS_IF([test "x${gcc_wextra}" = "xyes"], [ GCC_WARNINGS="${GCC_WARNINGS} -Wextra -Wno-unused-parameter" GCC_WARNINGS="${GCC_WARNINGS} -Wbad-function-cast" GCC_WARNINGS="${GCC_WARNINGS} -Wcast-align" GCC_WARNINGS="${GCC_WARNINGS} -Wredundant-decls" -fi -if test "${gcc_werror}" = yes; then +]) +AS_IF([test "x${gcc_werror}" = "xyes"], [ GCC_WARNINGS="${GCC_WARNINGS} -Werror" -fi +]) # overide default gcc cflags -if test $gcc_warnings = yes; then +AS_IF([test "x$gcc_warnings" = "xyes"], [ CFLAGS="$CFLAGS $GCC_WARNINGS" -fi +]) AC_CONFIG_FILES([ Makefile @@ -829,16 +817,15 @@ echo -------------------------------------------------- m4_foreach([adapter], [USB1_ADAPTERS, USB_ADAPTERS, USB0_ADAPTERS, HIDAPI_ADAPTERS, LIBFTDI_ADAPTERS, LIBJAYLINK_ADAPTERS], [s=m4_format(["%-40s"], ADAPTER_DESC([adapter])) - case $ADAPTER_VAR([adapter]) in - auto) + AS_CASE([$ADAPTER_VAR([adapter])], + [auto], [ echo "$s"yes '(auto)' - ;; - yes) + ], + [yes], [ echo "$s"yes - ;; - no) + ], + [no], [ echo "$s"no - ;; - esac + ]) ]) echo -- cgit v1.1 From 50e2253ab9433e5ff2d01a7338477a44e7cf8a6f Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Sat, 13 Aug 2016 10:42:30 +0200 Subject: target: Replace malloc+manual zeroing with calloc Change-Id: I3c782c34b59cb36b8ca1d36e9c804c67bae5cb45 Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3667 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/target.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index 17902a5..c8a3ce4 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -5408,14 +5408,7 @@ static int target_create(Jim_GetOptInfo *goi) target->halt_issued = false; /* initialize trace information */ - target->trace_info = malloc(sizeof(struct trace)); - target->trace_info->num_trace_points = 0; - target->trace_info->trace_points_size = 0; - target->trace_info->trace_points = NULL; - target->trace_info->trace_history_size = 0; - target->trace_info->trace_history = NULL; - target->trace_info->trace_history_pos = 0; - target->trace_info->trace_history_overflowed = 0; + target->trace_info = calloc(1, sizeof(struct trace)); target->dbgmsg = NULL; target->dbg_msg_enabled = 0; -- cgit v1.1 From 702b150a6bf92fe56cf0cea72ccfad2d06eb64bc Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 13 Nov 2016 15:02:55 +0300 Subject: target: LS1_SAP: fix "declaration of 'read' shadows a global" warning Change-Id: I7070193819cc134f9fe1427c20a11160ec415ccb Reported-by: Jens Bauer Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3877 Tested-by: jenkins --- src/target/ls1_sap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target/ls1_sap.c b/src/target/ls1_sap.c index 944e725..b4d814b 100644 --- a/src/target/ls1_sap.c +++ b/src/target/ls1_sap.c @@ -127,7 +127,7 @@ static void ls1_sap_set_addr_high(struct jtag_tap *tap, uint16_t addr_high) } static void ls1_sap_memory_cmd(struct jtag_tap *tap, uint32_t address, - int32_t size, int read) + int32_t size, bool rnw) { struct scan_field field; uint8_t cmd[8]; @@ -138,7 +138,7 @@ static void ls1_sap_memory_cmd(struct jtag_tap *tap, uint32_t address, field.out_value = cmd; buf_set_u64(cmd, 0, 9, 0); buf_set_u64(cmd, 9, 3, size); - buf_set_u64(cmd, 12, 1, !!read); + buf_set_u64(cmd, 12, 1, rnw); buf_set_u64(cmd, 13, 3, 0); buf_set_u64(cmd, 16, 32, address); buf_set_u64(cmd, 48, 16, 0); @@ -190,7 +190,7 @@ static int ls1_sap_read_memory(struct target *target, uint32_t address, ls1_sap_set_addr_high(target->tap, 0); while (count--) { - ls1_sap_memory_cmd(target->tap, address, size, 1); + ls1_sap_memory_cmd(target->tap, address, size, true); ls1_sap_memory_read(target->tap, size, buffer); address += size; buffer += size; @@ -213,7 +213,7 @@ static int ls1_sap_write_memory(struct target *target, uint32_t address, ls1_sap_set_addr_high(target->tap, 0); while (count--) { - ls1_sap_memory_cmd(target->tap, address, size, 0); + ls1_sap_memory_cmd(target->tap, address, size, false); ls1_sap_memory_write(target->tap, size, buffer); address += size; buffer += size; -- cgit v1.1 From 95de342a93445faa99b32d8dfecc947e3a5b49cb Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Sun, 6 Nov 2016 12:48:02 +0100 Subject: configure: Use same case for libjaylink as for other libs Change-Id: I60d91a0543d9b8c580254cdc5f04b2e60209b98b Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3868 Tested-by: jenkins Reviewed-by: Paul Fertser --- configure.ac | 6 +++--- src/Makefile.am | 2 +- src/jtag/drivers/Makefile.am | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index 9ac4110..5fa5a63 100644 --- a/configure.ac +++ b/configure.ac @@ -644,8 +644,8 @@ PKG_CHECK_MODULES([LIBFTDI], [libftdi1], [use_libftdi=yes], [ PKG_CHECK_MODULES([LIBFTDI], [libftdi], [use_libftdi=yes], [use_libftdi=no]) ]) -PKG_CHECK_MODULES([libjaylink], [libjaylink >= 0.1], - [HAVE_LIBJAYLINK=yes], [HAVE_LIBJAYLINK=no]) +PKG_CHECK_MODULES([LIBJAYLINK], [libjaylink >= 0.1], + [use_libjaylink=yes], [use_libjaylink=no]) m4_define([PROCESS_ADAPTERS], [ m4_foreach([adapter], [$1], [ @@ -670,7 +670,7 @@ PROCESS_ADAPTERS([USB_ADAPTERS], ["x$use_libusb1" = "xyes" -o "x$use_libusb0" = PROCESS_ADAPTERS([USB0_ADAPTERS], ["x$use_libusb0" = "xyes"], [libusb-0.1]) PROCESS_ADAPTERS([HIDAPI_ADAPTERS], ["x$use_hidapi" = "xyes"], [hidapi]) PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], ["x$use_libftdi" = "xyes"], [libftdi]) -PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_libusb1" = "xyes" -a "x$use_internal_libjaylink" = "xyes" -o "x$HAVE_LIBJAYLINK" = "xyes"], [libusb-1.x or libjaylink-0.1]) +PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_libusb1" = "xyes" -a "x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libusb-1.x or libjaylink-0.1]) AS_IF([test "x$build_openjtag" = "xyes"], [ AS_IF([test "x$use_libusb1" != "xyes" -a "x$use_libusb0" != "xyes"], [ diff --git a/src/Makefile.am b/src/Makefile.am index bad4153..699917c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -78,7 +78,7 @@ libopenocd_la_LIBADD = \ $(HIDAPI_LIBS) $(LIBUSB0_LIBS) $(LIBUSB1_LIBS) if !INTERNAL_LIBJAYLINK -libopenocd_la_LIBADD += $(libjaylink_LIBS) +libopenocd_la_LIBADD += $(LIBJAYLINK_LIBS) endif STARTUP_TCL_SRCS = \ diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index 1322c0f..a50c927 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -33,7 +33,7 @@ noinst_LTLIBRARIES += libjaylink_internal.la libocdjtagdrivers_la_LIBADD += libjaylink_internal.la else DRIVERFILES += jlink.c -libocdjtagdrivers_la_CPPFLAGS += $(libjaylink_CFLAGS) +libocdjtagdrivers_la_CPPFLAGS += $(LIBJAYLINK_CFLAGS) endif endif -- cgit v1.1 From 1789445c8283521951543d5a130fbf10b3594705 Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Sun, 6 Nov 2016 12:48:52 +0100 Subject: configure: Add USE_* conditionals for hidapi and libjaylink For consistency with other libs. Change-Id: Id37329a00db5ab668f4c2c9ce53d2c41976649b1 Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3869 Tested-by: jenkins Reviewed-by: Marc Schink Reviewed-by: Paul Fertser --- configure.ac | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure.ac b/configure.ac index 5fa5a63..e178d45 100644 --- a/configure.ac +++ b/configure.ac @@ -729,6 +729,8 @@ AM_CONDITIONAL([IS_WIN32], [test "x$is_win32" = "xyes"]) AM_CONDITIONAL([IS_DARWIN], [test "x$is_darwin" = "xyes"]) AM_CONDITIONAL([BITQ], [test "x$build_bitq" = "xyes"]) AM_CONDITIONAL([USE_LIBFTDI], [test "x$use_libftdi" = "xyes"]) +AM_CONDITIONAL([USE_HIDAPI], [test "x$use_hidapi" = "xyes"]) +AM_CONDITIONAL([USE_LIBJAYLINK], [test "x$use_libjaylink" = "xyes"]) AM_CONDITIONAL([MINIDRIVER], [test "x$build_minidriver" = "xyes"]) AM_CONDITIONAL([MINIDRIVER_DUMMY], [test "x$build_minidriver_dummy" = "xyes"]) -- cgit v1.1 From ef4c139ce224e4d3784bcff411604c1908b13da6 Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Sun, 6 Nov 2016 15:49:35 +0100 Subject: configure: Don't set user variables CFLAGS is a user variable and shouldn't be set in either configure.ac or Makefile.am because that makes it impossible to override compiler flags at configure or make time. AC_SUBST the default warning flags into AM_CFLAGS instead, which is emitted before CFLAGS on the compiler command line. Do the same thing with a mingw-specific flag as well. Change-Id: I6ac3a3c8b7e0abf6f0e60ea239b549d68ea6d370 Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3870 Tested-by: jenkins Reviewed-by: Paul Fertser --- common.mk | 5 ++++- configure.ac | 4 ++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/common.mk b/common.mk index f301c3a..dbacf19 100644 --- a/common.mk +++ b/common.mk @@ -1,6 +1,9 @@ # common flags used in openocd build -AM_CPPFLAGS = -I$(top_srcdir)/src \ +AM_CFLAGS = $(GCC_WARNINGS) + +AM_CPPFLAGS = $(HOST_CPPFLAGS)\ + -I$(top_srcdir)/src \ -I$(top_builddir)/src \ -I$(top_srcdir)/src/helper \ -DPKGDATADIR=\"$(pkgdatadir)\" \ diff --git a/configure.ac b/configure.ac index e178d45..5058524 100644 --- a/configure.ac +++ b/configure.ac @@ -471,7 +471,7 @@ AS_CASE([$host], AC_MSG_ERROR([buspirate currently not supported by MinGW32 hosts]) ]) - CFLAGS="$CFLAGS -D__USE_MINGW_ANSI_STDIO" + AC_SUBST([HOST_CPPFLAGS], [-D__USE_MINGW_ANSI_STDIO]) AC_DEFINE([IS_MINGW], [1], [1 if building for MinGW.]) AC_DEFINE([IS_WIN32], [1], [1 if building for Win32.]) @@ -785,7 +785,7 @@ AS_IF([test "x${gcc_werror}" = "xyes"], [ # overide default gcc cflags AS_IF([test "x$gcc_warnings" = "xyes"], [ - CFLAGS="$CFLAGS $GCC_WARNINGS" + AC_SUBST([GCC_WARNINGS], [$GCC_WARNINGS]) ]) AC_CONFIG_FILES([ -- cgit v1.1 From f2e93b597f7ea2f284be9bb66ddbc27be8fd281f Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Sun, 6 Nov 2016 16:50:22 +0100 Subject: configure: Consolidate platform defines Change-Id: Iebc775baadeeb5e963fb48c0a9e8d87d26d9035a Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3863 Tested-by: jenkins Reviewed-by: Paul Fertser --- configure.ac | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 5058524..247c61c 100644 --- a/configure.ac +++ b/configure.ac @@ -439,7 +439,6 @@ AS_CASE([$host], AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [[return __MINGW32__;]])], [is_mingw=yes],[is_mingw=no]) AS_IF([test "x$is_mingw" = "xyes"], [ - AC_DEFINE([IS_MINGW], [1], [1 if building for MinGW.]) AS_IF([test "x$parport_use_giveio" = "xno"], [ AC_MSG_WARN([--disable-parport-giveio is not supported by MinGW32 hosts]) ]) @@ -447,15 +446,11 @@ AS_CASE([$host], is_cygwin=no ], [ is_cygwin=yes - AC_DEFINE([IS_CYGWIN], [1], [1 if building for Cygwin.]) # sys/io.h needed under cygwin for parport access AS_IF([test "x$build_parport" = "xyes"], [ AC_CHECK_HEADERS([sys/io.h],[],AC_MSG_ERROR([Please install the cygwin ioperm package])) ]) ]) - - AC_DEFINE([IS_WIN32], [1], [1 if building for Win32.]) - AC_DEFINE([IS_DARWIN], [0], [0 if not building for Darwin.]) ], [*-mingw* | *-msys*], [ is_mingw=yes @@ -472,10 +467,6 @@ AS_CASE([$host], ]) AC_SUBST([HOST_CPPFLAGS], [-D__USE_MINGW_ANSI_STDIO]) - - AC_DEFINE([IS_MINGW], [1], [1 if building for MinGW.]) - AC_DEFINE([IS_WIN32], [1], [1 if building for Win32.]) - AC_DEFINE([IS_DARWIN], [0], [0 if not building for Darwin.]) ], [*darwin*], [ is_darwin=yes @@ -484,23 +475,36 @@ AS_CASE([$host], AC_MSG_WARN([--enable-parport-giveio cannot be used by Darwin hosts]) ]) parport_use_giveio=no - - AC_DEFINE([IS_CYGWIN], [0], [0 if not building for Cygwin.]) - AC_DEFINE([IS_WIN32], [0], [0 if not building for Win32.]) - AC_DEFINE([IS_DARWIN], [1], [1 if building for Darwin.]) ], [ AS_IF([test "x$parport_use_giveio" = "xyes"], [ AC_MSG_WARN([--enable-parport-giveio cannot be used by ]$host[ hosts]) ]) parport_use_giveio=no +]) + +AS_IF([test "x$is_cygwin" = "xyes"], [ + AC_DEFINE([IS_CYGWIN], [1], [1 if building for Cygwin.]) +], [ AC_DEFINE([IS_CYGWIN], [0], [0 if not building for Cygwin.]) - AC_DEFINE([IS_WIN32], [0], [0 if not building for Win32.]) - AC_DEFINE([IS_DARWIN], [0], [0 if not building for Darwin.]) +]) + +AS_IF([test "x$is_mingw" = "xyes"], [ + AC_DEFINE([IS_MINGW], [1], [1 if building for Mingw.]) +], [ + AC_DEFINE([IS_MINGW], [0], [0 if not building for Mingw.]) ]) AS_IF([test "x$is_win32" = "xyes"], [ - AC_DEFINE([WIN32_LEAN_AND_MEAN], [1], [1 to exclude old conflicting definitions when building on Windows]) + AC_DEFINE([IS_WIN32], [1], [1 if building for Win32.]) +], [ + AC_DEFINE([IS_WIN32], [0], [0 if not building for Win32.]) +]) + +AS_IF([test "x$is_darwin" = "xyes"], [ + AC_DEFINE([IS_DARWIN], [1], [1 if building for Darwin.]) +], [ + AC_DEFINE([IS_DARWIN], [0], [0 if not building for Darwin.]) ]) AS_IF([test "x$build_parport" = "xyes"], [ -- cgit v1.1 From 5be455a710c57bbbbd49c2d671b42098db7be5dc Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Sun, 6 Nov 2016 20:19:26 +0100 Subject: Convert to non-recursive make Change-Id: I11f8bc8553957e2ff083c09e72e16881e4d3bb6f Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3865 Tested-by: jenkins Reviewed-by: Paul Fertser --- .gitignore | 2 +- Makefile.am | 64 +++++-- README | 2 +- common.mk | 15 -- configure.ac | 19 -- doc/Makefile.am | 21 +-- src/Makefile.am | 136 +++++--------- src/flash/Makefile.am | 30 +-- src/flash/nand/Makefile.am | 79 ++++---- src/flash/nor/Makefile.am | 127 ++++++------- src/helper/Makefile.am | 87 ++++----- src/jtag/Makefile.am | 96 ++++------ src/jtag/aice/Makefile.am | 41 ++-- src/jtag/drivers/Makefile.am | 200 ++++++++++---------- src/jtag/drivers/libusb_common.h | 4 +- src/jtag/drivers/usb_blaster/Makefile.am | 19 +- src/jtag/hla/Makefile.am | 34 ++-- src/pld/Makefile.am | 16 +- src/rtos/Makefile.am | 54 +++--- src/server/Makefile.am | 32 ++-- src/svf/Makefile.am | 10 +- src/target/Makefile.am | 312 +++++++++++++++---------------- src/target/breakpoints.h | 2 + src/target/openrisc/Makefile.am | 30 ++- src/transport/Makefile.am | 15 +- src/xsvf/Makefile.am | 10 +- 26 files changed, 657 insertions(+), 800 deletions(-) delete mode 100644 common.mk diff --git a/.gitignore b/.gitignore index 0f217a9..f1021b2 100644 --- a/.gitignore +++ b/.gitignore @@ -52,8 +52,8 @@ doc/openocd.pg doc/openocd.toc doc/openocd.tp doc/openocd.vr -doc/texinfo.tex doc/version.texi +texinfo.tex src/openocd src/openocd.exe diff --git a/Makefile.am b/Makefile.am index 2ddc96d..579d3a7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,15 +12,34 @@ nobase_dist_pkgdata_DATA = \ contrib/libdcc/README \ contrib/99-openocd.rules -if INTERNAL_JIMTCL -SUBDIRS = jimtcl -else SUBDIRS = +DIST_SUBDIRS = +bin_PROGRAMS = +noinst_LTLIBRARIES = +info_TEXINFOS = +dist_man_MANS = +EXTRA_DIST = + +if INTERNAL_JIMTCL +SUBDIRS += jimtcl +DIST_SUBDIRS += jimtcl endif -SUBDIRS += src doc +# common flags used in openocd build +AM_CFLAGS = $(GCC_WARNINGS) + +AM_CPPFLAGS = $(HOST_CPPFLAGS)\ + -I$(top_srcdir)/src \ + -I$(top_builddir)/src \ + -I$(top_srcdir)/src/helper \ + -DPKGDATADIR=\"$(pkgdatadir)\" \ + -DBINDIR=\"$(bindir)\" -EXTRA_DIST = \ +if INTERNAL_JIMTCL +AM_CPPFLAGS += -I$(top_srcdir)/jimtcl \ + -I$(top_builddir)/jimtcl +endif +EXTRA_DIST += \ BUGS \ HACKING \ NEWTAPS \ @@ -96,17 +115,26 @@ distclean-local: DISTCLEANFILES = doxygen.log +METASOURCES = AUTO + +BUILT_SOURCES = +CLEANFILES = + MAINTAINERCLEANFILES = \ - $(srcdir)/INSTALL \ - $(srcdir)/configure \ - $(srcdir)/Makefile.in \ - $(srcdir)/depcomp \ - $(srcdir)/config.guess \ - $(srcdir)/config.sub \ - $(srcdir)/config.h.in \ - $(srcdir)/config.h.in~ \ - $(srcdir)/compile \ - $(srcdir)/ltmain.sh \ - $(srcdir)/missing \ - $(srcdir)/aclocal.m4 \ - $(srcdir)/install-sh + %D%/INSTALL \ + %D%/configure \ + %D%/Makefile.in \ + %D%/depcomp \ + %D%/config.guess \ + %D%/config.sub \ + %D%/config.h.in \ + %D%/config.h.in~ \ + %D%/compile \ + %D%/ltmain.sh \ + %D%/missing \ + %D%/aclocal.m4 \ + %D%/install-sh \ + %D%/texinfo.tex + +include src/Makefile.am +include doc/Makefile.am diff --git a/README b/README index 792d7e3..615ae81 100644 --- a/README +++ b/README @@ -214,7 +214,7 @@ You'll also need: Additionally, for building from git: - autoconf >= 2.64 -- automake >= 1.9 +- automake >= 1.14 - texinfo USB-based adapters depend on libusb-1.0 and some older drivers require diff --git a/common.mk b/common.mk deleted file mode 100644 index dbacf19..0000000 --- a/common.mk +++ /dev/null @@ -1,15 +0,0 @@ - -# common flags used in openocd build -AM_CFLAGS = $(GCC_WARNINGS) - -AM_CPPFLAGS = $(HOST_CPPFLAGS)\ - -I$(top_srcdir)/src \ - -I$(top_builddir)/src \ - -I$(top_srcdir)/src/helper \ - -DPKGDATADIR=\"$(pkgdatadir)\" \ - -DBINDIR=\"$(bindir)\" - -if INTERNAL_JIMTCL -AM_CPPFLAGS += -I$(top_srcdir)/jimtcl \ - -I$(top_builddir)/jimtcl -endif diff --git a/configure.ac b/configure.ac index 247c61c..c6c31be 100644 --- a/configure.ac +++ b/configure.ac @@ -794,25 +794,6 @@ AS_IF([test "x$gcc_warnings" = "xyes"], [ AC_CONFIG_FILES([ Makefile - src/Makefile - src/helper/Makefile - src/jtag/Makefile - src/jtag/drivers/Makefile - src/jtag/drivers/usb_blaster/Makefile - src/jtag/hla/Makefile - src/jtag/aice/Makefile - src/transport/Makefile - src/target/openrisc/Makefile - src/xsvf/Makefile - src/svf/Makefile - src/target/Makefile - src/rtos/Makefile - src/server/Makefile - src/flash/Makefile - src/flash/nor/Makefile - src/flash/nand/Makefile - src/pld/Makefile - doc/Makefile ]) AC_OUTPUT diff --git a/doc/Makefile.am b/doc/Makefile.am index 24f68a1..6759203 100644 --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -1,12 +1,11 @@ -info_TEXINFOS = openocd.texi -openocd_TEXINFOS = fdl.texi -man_MANS = openocd.1 -EXTRA_DIST = openocd.1 \ - manual +info_TEXINFOS += %D%/openocd.texi +%C%_openocd_TEXINFOS = %D%/fdl.texi -MAINTAINERCLEANFILES = \ - $(srcdir)/Makefile.in \ - $(srcdir)/mdate-sh \ - $(srcdir)/stamp-vti \ - $(srcdir)/version.texi \ - $(srcdir)/texinfo.tex +dist_man_MANS += %D%/openocd.1 + +EXTRA_DIST += %D%/manual + +MAINTAINERCLEANFILES += \ + %D%/mdate-sh \ + %D%/stamp-vti \ + %D%/version.texi diff --git a/src/Makefile.am b/src/Makefile.am index 699917c..07981aa 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,61 +1,41 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libopenocd.la +bin_PROGRAMS += %D%/openocd -SUBDIRS = \ - jtag \ - helper \ - target \ - transport \ - flash \ - svf \ - xsvf \ - pld \ - server \ - rtos +%C%_openocd_SOURCES = \ + %D%/main.c -noinst_LTLIBRARIES = libopenocd.la -bin_PROGRAMS = openocd +%C%_libopenocd_la_SOURCES = \ + %D%/hello.c %D%/hello.h \ + %D%/openocd.c %D%/openocd.h -MAINFILE = main.c +%C%_openocd_LDADD = %D%/libopenocd.la -openocd_SOURCES = $(MAINFILE) -openocd_LDADD = libopenocd.la +%C%_openocd_LDADD += $(MINGWLDADD) if INTERNAL_JIMTCL -openocd_LDADD += $(top_builddir)/jimtcl/libjim.a +%C%_openocd_LDADD += $(top_builddir)/jimtcl/libjim.a else -openocd_LDADD += -ljim +%C%_openocd_LDADD += -ljim endif -if ULINK -openocd_LDADD += -lm -endif - -libopenocd_la_SOURCES = \ - hello.c \ - openocd.c - -noinst_HEADERS = \ - hello.h \ - openocd.h - -libopenocd_la_CPPFLAGS = +%C%_libopenocd_la_CPPFLAGS = # banner output includes RELSTR appended to $VERSION from the configure script # guess-rev.sh returns either a repository version ID or "-snapshot" if RELEASE -libopenocd_la_CPPFLAGS += -DRELSTR=\"\" -libopenocd_la_CPPFLAGS += -DGITVERSION=\"\" +%C%_libopenocd_la_CPPFLAGS += -DRELSTR=\"\" +%C%_libopenocd_la_CPPFLAGS += -DGITVERSION=\"\" else -libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\" -libopenocd_la_CPPFLAGS += -DGITVERSION=\"`cd $(top_srcdir) && git describe`\" -libopenocd_la_CPPFLAGS += -DPKGBLDDATE=\"`date +%F-%R`\" +%C%_libopenocd_la_CPPFLAGS += -DRELSTR=\"`$(top_srcdir)/guess-rev.sh $(top_srcdir)`\" +%C%_libopenocd_la_CPPFLAGS += -DGITVERSION=\"`cd $(top_srcdir) && git describe`\" +%C%_libopenocd_la_CPPFLAGS += -DPKGBLDDATE=\"`date +%F-%R`\" endif # add default CPPFLAGS -libopenocd_la_CPPFLAGS += $(AM_CPPFLAGS) $(CPPFLAGS) +%C%_libopenocd_la_CPPFLAGS += $(AM_CPPFLAGS) $(CPPFLAGS) # the library search path. -libopenocd_la_LDFLAGS = $(all_libraries) +%C%_libopenocd_la_LDFLAGS = $(all_libraries) if IS_MINGW MINGWLDADD = -lws2_32 @@ -63,59 +43,43 @@ else MINGWLDADD = endif -libopenocd_la_LIBADD = \ - $(top_builddir)/src/xsvf/libxsvf.la \ - $(top_builddir)/src/svf/libsvf.la \ - $(top_builddir)/src/pld/libpld.la \ - $(top_builddir)/src/jtag/libjtag.la \ - $(top_builddir)/src/transport/libtransport.la \ - $(top_builddir)/src/flash/libflash.la \ - $(top_builddir)/src/target/libtarget.la \ - $(top_builddir)/src/server/libserver.la \ - $(top_builddir)/src/rtos/librtos.la \ - $(top_builddir)/src/helper/libhelper.la \ - $(LIBFTDI_LIBS) $(MINGWLDADD) \ - $(HIDAPI_LIBS) $(LIBUSB0_LIBS) $(LIBUSB1_LIBS) - -if !INTERNAL_LIBJAYLINK -libopenocd_la_LIBADD += $(LIBJAYLINK_LIBS) -endif - -STARTUP_TCL_SRCS = \ - $(srcdir)/helper/startup.tcl \ - $(srcdir)/jtag/startup.tcl \ - $(srcdir)/target/startup.tcl \ - $(srcdir)/flash/startup.tcl \ - $(srcdir)/server/startup.tcl - -EXTRA_DIST = $(STARTUP_TCL_SRCS) +%C%_libopenocd_la_LIBADD = \ + %D%/xsvf/libxsvf.la \ + %D%/svf/libsvf.la \ + %D%/pld/libpld.la \ + %D%/jtag/libjtag.la \ + %D%/transport/libtransport.la \ + %D%/flash/libflash.la \ + %D%/target/libtarget.la \ + %D%/server/libserver.la \ + %D%/rtos/librtos.la \ + %D%/helper/libhelper.la -BUILT_SOURCES = startup_tcl.inc +BIN2C = $(srcdir)/%D%/helper/bin2char.sh -startup.tcl: $(STARTUP_TCL_SRCS) - cat $^ > $@ +STARTUP_TCL_SRCS = +EXTRA_DIST += $(STARTUP_TCL_SRCS) -BIN2C = $(top_srcdir)/src/helper/bin2char.sh +BUILT_SOURCES += %D%/startup_tcl.inc # Convert .tcl to c-array -startup_tcl.inc: startup.tcl $(BIN2C) - $(BIN2C) < $< > $@ || { rm -f $@; false; } +%D%/startup_tcl.inc: $(STARTUP_TCL_SRCS) + cat $^ | $(BIN2C) > $@ || { rm -f $@; false; } # add generated files to make clean list -CLEANFILES = startup.tcl startup_tcl.inc +CLEANFILES += %D%/startup_tcl.inc # we do not want generated file in the dist -dist-hook: - rm -f $(distdir)/startup_tcl.inc - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in - -# The "quick" target builds executables & reinstalls the executables -# Primary use: developer types to quicken the edit/compile/debug -# cycle. by not requiring a "full build and full install". Note the -# assumption is: You are only rebuilding the EXE.... and everything -# else is/was previously installed. -# -# use at your own risk -quick: all install-binPROGRAMS - +#dist-hook: +# rm -f $(distdir)/%D%/startup_tcl.inc + +include %D%/helper/Makefile.am +include %D%/jtag/Makefile.am +include %D%/transport/Makefile.am +include %D%/xsvf/Makefile.am +include %D%/svf/Makefile.am +include %D%/target/Makefile.am +include %D%/rtos/Makefile.am +include %D%/server/Makefile.am +include %D%/flash/Makefile.am +include %D%/pld/Makefile.am diff --git a/src/flash/Makefile.am b/src/flash/Makefile.am index ece4018..a1b46f8 100644 --- a/src/flash/Makefile.am +++ b/src/flash/Makefile.am @@ -1,23 +1,13 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libflash.la +%C%_libflash_la_SOURCES = \ + %D%/common.c %D%/common.h \ + %D%/mflash.c %D%/mflash.h -SUBDIRS = \ - nor \ - nand +%C%_libflash_la_LIBADD = \ + %D%/nor/libocdflashnor.la \ + %D%/nand/libocdflashnand.la -METASOURCES = AUTO -noinst_LTLIBRARIES = libflash.la -libflash_la_SOURCES = \ - common.c \ - mflash.c +STARTUP_TCL_SRCS += %D%/startup.tcl -libflash_la_LIBADD = \ - $(top_builddir)/src/flash/nor/libocdflashnor.la \ - $(top_builddir)/src/flash/nand/libocdflashnand.la - -noinst_HEADERS = \ - common.h \ - mflash.h - -EXTRA_DIST = startup.tcl - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +include %D%/nor/Makefile.am +include %D%/nand/Makefile.am diff --git a/src/flash/nand/Makefile.am b/src/flash/nand/Makefile.am index 2ddd096..abe90f8 100644 --- a/src/flash/nand/Makefile.am +++ b/src/flash/nand/Makefile.am @@ -1,46 +1,43 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libocdflashnand.la -noinst_LTLIBRARIES = libocdflashnand.la - -libocdflashnand_la_SOURCES = \ - ecc.c \ - ecc_kw.c \ - core.c \ - fileio.c \ - tcl.c \ - arm_io.c \ +%C%_libocdflashnand_la_SOURCES = \ + %D%/ecc.c \ + %D%/ecc_kw.c \ + %D%/core.c \ + %D%/fileio.c \ + %D%/tcl.c \ + %D%/arm_io.c \ $(NAND_DRIVERS) \ - driver.c + %D%/driver.c \ + $(NANDHEADERS) NAND_DRIVERS = \ - nonce.c \ - davinci.c \ - lpc3180.c \ - lpc32xx.c \ - mxc.c \ - mx3.c \ - orion.c \ - s3c24xx.c \ - s3c2410.c \ - s3c2412.c \ - s3c2440.c \ - s3c2443.c \ - s3c6400.c \ - at91sam9.c \ - nuc910.c - -noinst_HEADERS = \ - arm_io.h \ - core.h \ - driver.h \ - fileio.h \ - imp.h \ - lpc3180.h \ - lpc32xx.h \ - mxc.h \ - mx3.h \ - s3c24xx.h \ - s3c24xx_regs.h \ - nuc910.h + %D%/nonce.c \ + %D%/davinci.c \ + %D%/lpc3180.c \ + %D%/lpc32xx.c \ + %D%/mxc.c \ + %D%/mx3.c \ + %D%/orion.c \ + %D%/s3c24xx.c \ + %D%/s3c2410.c \ + %D%/s3c2412.c \ + %D%/s3c2440.c \ + %D%/s3c2443.c \ + %D%/s3c6400.c \ + %D%/at91sam9.c \ + %D%/nuc910.c -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +NANDHEADERS = \ + %D%/arm_io.h \ + %D%/core.h \ + %D%/driver.h \ + %D%/fileio.h \ + %D%/imp.h \ + %D%/lpc3180.h \ + %D%/lpc32xx.h \ + %D%/mxc.h \ + %D%/mx3.h \ + %D%/s3c24xx.h \ + %D%/s3c24xx_regs.h \ + %D%/nuc910.h diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index c167e8f..727e4f2 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -1,69 +1,66 @@ -include $(top_srcdir)/common.mk - -noinst_LTLIBRARIES = libocdflashnor.la -libocdflashnor_la_SOURCES = \ - core.c \ - tcl.c \ +noinst_LTLIBRARIES += %D%/libocdflashnor.la +%C%_libocdflashnor_la_SOURCES = \ + %D%/core.c \ + %D%/tcl.c \ $(NOR_DRIVERS) \ - drivers.c + %D%/drivers.c \ + $(NORHEADERS) NOR_DRIVERS = \ - aduc702x.c \ - aducm360.c \ - ambiqmicro.c \ - at91sam4.c \ - at91sam4l.c \ - at91samd.c \ - at91sam3.c \ - at91sam7.c \ - atsamv.c \ - avrf.c \ - cfi.c \ - dsp5680xx_flash.c \ - efm32.c \ - em357.c \ - faux.c \ - fm3.c \ - fm4.c \ - jtagspi.c \ - kinetis.c \ - kinetis_ke.c \ - lpc2000.c \ - lpc288x.c \ - lpc2900.c \ - lpcspifi.c \ - mdr.c \ - mrvlqspi.c \ - niietcm4.c \ - non_cfi.c \ - nrf51.c \ - numicro.c \ - ocl.c \ - pic32mx.c \ - psoc4.c \ - sim3x.c \ - spi.c \ - stmsmi.c \ - stellaris.c \ - stm32f1x.c \ - stm32f2x.c \ - stm32lx.c \ - stm32l4x.c \ - str7x.c \ - str9x.c \ - str9xpec.c \ - tms470.c \ - virtual.c \ - xmc1xxx.c \ - xmc4xxx.c - -noinst_HEADERS = \ - core.h \ - cfi.h \ - driver.h \ - imp.h \ - non_cfi.h \ - ocl.h \ - spi.h + %D%/aduc702x.c \ + %D%/aducm360.c \ + %D%/ambiqmicro.c \ + %D%/at91sam4.c \ + %D%/at91sam4l.c \ + %D%/at91samd.c \ + %D%/at91sam3.c \ + %D%/at91sam7.c \ + %D%/atsamv.c \ + %D%/avrf.c \ + %D%/cfi.c \ + %D%/dsp5680xx_flash.c \ + %D%/efm32.c \ + %D%/em357.c \ + %D%/faux.c \ + %D%/fm3.c \ + %D%/fm4.c \ + %D%/jtagspi.c \ + %D%/kinetis.c \ + %D%/kinetis_ke.c \ + %D%/lpc2000.c \ + %D%/lpc288x.c \ + %D%/lpc2900.c \ + %D%/lpcspifi.c \ + %D%/mdr.c \ + %D%/mrvlqspi.c \ + %D%/niietcm4.c \ + %D%/non_cfi.c \ + %D%/nrf51.c \ + %D%/numicro.c \ + %D%/ocl.c \ + %D%/pic32mx.c \ + %D%/psoc4.c \ + %D%/sim3x.c \ + %D%/spi.c \ + %D%/stmsmi.c \ + %D%/stellaris.c \ + %D%/stm32f1x.c \ + %D%/stm32f2x.c \ + %D%/stm32lx.c \ + %D%/stm32l4x.c \ + %D%/str7x.c \ + %D%/str9x.c \ + %D%/str9xpec.c \ + %D%/tms470.c \ + %D%/virtual.c \ + %D%/xmc1xxx.c \ + %D%/xmc4xxx.c -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +NORHEADERS = \ + %D%/core.h \ + %D%/cfi.h \ + %D%/driver.h \ + %D%/imp.h \ + %D%/non_cfi.h \ + %D%/ocl.h \ + %D%/spi.h diff --git a/src/helper/Makefile.am b/src/helper/Makefile.am index 64caf98..3623894 100644 --- a/src/helper/Makefile.am +++ b/src/helper/Makefile.am @@ -1,56 +1,49 @@ -include $(top_srcdir)/common.mk - -METASOURCES = AUTO -noinst_LTLIBRARIES = libhelper.la - -CONFIGFILES = options.c time_support_common.c - -libhelper_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) - -libhelper_la_SOURCES = \ - binarybuffer.c \ - $(CONFIGFILES) \ - configuration.c \ - log.c \ - command.c \ - time_support.c \ - replacements.c \ - fileio.c \ - util.c \ - jep106.c \ - jim-nvp.c +noinst_LTLIBRARIES += %D%/libhelper.la + +%C%_libhelper_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) + +%C%_libhelper_la_SOURCES = \ + %D%/binarybuffer.c \ + %D%/options.c \ + %D%/time_support_common.c \ + %D%/configuration.c \ + %D%/log.c \ + %D%/command.c \ + %D%/time_support.c \ + %D%/replacements.c \ + %D%/fileio.c \ + %D%/util.c \ + %D%/jep106.c \ + %D%/jim-nvp.c \ + %D%/binarybuffer.h \ + %D%/configuration.h \ + %D%/ioutil.h \ + %D%/list.h \ + %D%/util.h \ + %D%/types.h \ + %D%/log.h \ + %D%/command.h \ + %D%/time_support.h \ + %D%/replacements.h \ + %D%/fileio.h \ + %D%/system.h \ + %D%/jep106.h \ + %D%/jep106.inc \ + %D%/jim-nvp.h if IOUTIL -libhelper_la_SOURCES += ioutil.c +%C%_libhelper_la_SOURCES += %D%/ioutil.c else -libhelper_la_SOURCES += ioutil_stubs.c +%C%_libhelper_la_SOURCES += %D%/ioutil_stubs.c endif -libhelper_la_CFLAGS = +%C%_libhelper_la_CFLAGS = if IS_MINGW # FD_* macros are sloppy with their signs on MinGW32 platform -libhelper_la_CFLAGS += -Wno-sign-compare +%C%_libhelper_la_CFLAGS += -Wno-sign-compare endif -noinst_HEADERS = \ - binarybuffer.h \ - configuration.h \ - ioutil.h \ - list.h \ - util.h \ - types.h \ - log.h \ - command.h \ - time_support.h \ - replacements.h \ - fileio.h \ - system.h \ - bin2char.sh \ - jep106.h \ - jep106.inc \ - update_jep106.pl \ - jim-nvp.h - -EXTRA_DIST = startup.tcl - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +STARTUP_TCL_SRCS += %D%/startup.tcl +EXTRA_DIST += \ + %D%/bin2char.sh \ + %D%/update_jep106.pl diff --git a/src/jtag/Makefile.am b/src/jtag/Makefile.am index db3e6ff..50ee263 100644 --- a/src/jtag/Makefile.am +++ b/src/jtag/Makefile.am @@ -1,86 +1,72 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libjtag.la -METASOURCES = AUTO -noinst_LTLIBRARIES = libjtag.la +JTAG_SRCS = +%C%_libjtag_la_LIBADD = -SUBDIRS = -DRIVERFILES = -libjtag_la_LIBADD = - -CLEANFILES = - -BUILT_SOURCES = - -BUILT_SOURCES += minidriver_imp.h -CLEANFILES += minidriver_imp.h +BUILT_SOURCES += %D%/minidriver_imp.h +CLEANFILES += %D%/minidriver_imp.h if MINIDRIVER if ZY1000 -DRIVERFILES += zy1000/zy1000.c -JTAG_MINIDRIVER_DIR = $(srcdir)/zy1000 +JTAG_SRCS += %D%/zy1000/zy1000.c +JTAG_MINIDRIVER_DIR = %D%/zy1000 endif if MINIDRIVER_DUMMY -DRIVERFILES += minidummy/minidummy.c commands.c -JTAG_MINIDRIVER_DIR = $(srcdir)/minidummy +JTAG_SRCS += %D%/minidummy/minidummy.c %D%/commands.c +JTAG_MINIDRIVER_DIR = %D%/minidummy endif -MINIDRIVER_IMP_DIR = $(srcdir)/minidriver +MINIDRIVER_IMP_DIR = %D%/minidriver -jtag_minidriver.h: $(JTAG_MINIDRIVER_DIR)/jtag_minidriver.h +%D%/jtag_minidriver.h: $(JTAG_MINIDRIVER_DIR)/jtag_minidriver.h cp $< $@ -BUILT_SOURCES += jtag_minidriver.h +BUILT_SOURCES += %D%/jtag_minidriver.h -CLEANFILES += jtag_minidriver.h +CLEANFILES += %D%/jtag_minidriver.h else -MINIDRIVER_IMP_DIR = $(srcdir)/drivers -DRIVERFILES += commands.c +MINIDRIVER_IMP_DIR = %D%/drivers +JTAG_SRCS += %D%/commands.c if HLADAPTER -SUBDIRS += hla -libjtag_la_LIBADD += $(top_builddir)/src/jtag/hla/libocdhla.la +include %D%/hla/Makefile.am +%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/hla/libocdhla.la endif if AICE -SUBDIRS += aice -libjtag_la_LIBADD += $(top_builddir)/src/jtag/aice/libocdaice.la +include %D%/aice/Makefile.am +%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/aice/libocdaice.la endif -SUBDIRS += drivers -libjtag_la_LIBADD += $(top_builddir)/src/jtag/drivers/libocdjtagdrivers.la - +include %D%/drivers/Makefile.am +%C%_libjtag_la_LIBADD += $(top_builddir)/%D%/drivers/libocdjtagdrivers.la endif - # endif // MINIDRIVER -minidriver_imp.h: $(MINIDRIVER_IMP_DIR)/minidriver_imp.h +%D%/minidriver_imp.h: $(MINIDRIVER_IMP_DIR)/minidriver_imp.h cp $< $@ -libjtag_la_SOURCES = \ - adapter.c \ - core.c \ - interface.c \ - interfaces.c \ - tcl.c \ - $(DRIVERFILES) - -noinst_HEADERS = \ - commands.h \ - driver.h \ - interface.h \ - interfaces.h \ - minidriver.h \ - jtag.h \ - minidriver/minidriver_imp.h \ - minidummy/jtag_minidriver.h \ - swd.h \ - tcl.h - -EXTRA_DIST = startup.tcl - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +%C%_libjtag_la_SOURCES = \ + %D%/adapter.c \ + %D%/core.c \ + %D%/interface.c \ + %D%/interfaces.c \ + %D%/tcl.c \ + %D%/commands.h \ + %D%/driver.h \ + %D%/interface.h \ + %D%/interfaces.h \ + %D%/minidriver.h \ + %D%/jtag.h \ + %D%/minidriver/minidriver_imp.h \ + %D%/minidummy/jtag_minidriver.h \ + %D%/swd.h \ + %D%/tcl.h \ + $(JTAG_SRCS) + +STARTUP_TCL_SRCS += %D%/startup.tcl diff --git a/src/jtag/aice/Makefile.am b/src/jtag/aice/Makefile.am index 7b9469d..97e3825 100644 --- a/src/jtag/aice/Makefile.am +++ b/src/jtag/aice/Makefile.am @@ -1,27 +1,14 @@ -include $(top_srcdir)/common.mk - -AM_CPPFLAGS += -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) $(LIBUSB0_CFLAGS) - -noinst_LTLIBRARIES = libocdaice.la - -libocdaice_la_SOURCES = \ - $(AICEFILES) - -AICEFILES = - -if AICE -AICEFILES += aice_transport.c -AICEFILES += aice_interface.c -AICEFILES += aice_port.c -AICEFILES += aice_usb.c -AICEFILES += aice_pipe.c -endif - -noinst_HEADERS = \ - aice_transport.h \ - aice_interface.h \ - aice_port.h \ - aice_usb.h \ - aice_pipe.h - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +noinst_LTLIBRARIES += %D%/libocdaice.la + +%C%_libocdaice_la_CPPFLAGS = -I$(top_srcdir)/src/jtag/drivers $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) $(LIBUSB0_CFLAGS) +%C%_libocdaice_la_SOURCES = \ + %D%/aice_transport.c \ + %D%/aice_interface.c \ + %D%/aice_port.c \ + %D%/aice_usb.c \ + %D%/aice_pipe.c \ + %D%/aice_transport.h \ + %D%/aice_interface.h \ + %D%/aice_port.h \ + %D%/aice_usb.h \ + %D%/aice_pipe.h diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index a50c927..c26d997 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -1,172 +1,174 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libocdjtagdrivers.la +%C%_libocdjtagdrivers_la_LIBADD = -noinst_LTLIBRARIES = libocdjtagdrivers.la -libocdjtagdrivers_la_LIBADD = +%C%_libocdjtagdrivers_la_SOURCES = \ + $(DRIVERFILES) \ + $(DRIVERHEADERS) -libocdjtagdrivers_la_SOURCES = \ - $(DRIVERFILES) +%C%_libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS) -libocdjtagdrivers_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) \ - $(LIBUSB0_CFLAGS) $(HIDAPI_CFLAGS) $(LIBFTDI_CFLAGS) +ULINK_FIRMWARE = %D%/OpenULINK -ULINK_FIRMWARE = $(srcdir)/OpenULINK - -EXTRA_DIST = $(ULINK_FIRMWARE) \ - usb_blaster/README.CheapClone \ - Makefile.rlink \ - rlink_call.m4 \ - rlink_init.m4 +EXTRA_DIST += $(ULINK_FIRMWARE) \ + %D%/usb_blaster/README.CheapClone \ + %D%/Makefile.rlink \ + %D%/rlink_call.m4 \ + %D%/rlink_init.m4 DRIVERFILES = -SUBDIRS= -if JLINK -if INTERNAL_LIBJAYLINK -SUBDIRS += libjaylink +# Standard Driver: common files +DRIVERFILES += %D%/driver.c -libjaylink_internal_la_SOURCES = jlink.c -libjaylink_internal_la_LIBADD = libjaylink/libjaylink/libjaylink.la -libjaylink_internal_la_CPPFLAGS = -I$(builddir)/libjaylink/libjaylink \ - -I$(srcdir)/libjaylink $(AM_CPPFLAGS) +if USE_LIBUSB1 +DRIVERFILES += %D%/libusb1_common.c +%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBUSB1_CFLAGS) +%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB1_LIBS) +endif -noinst_LTLIBRARIES += libjaylink_internal.la -libocdjtagdrivers_la_LIBADD += libjaylink_internal.la -else -DRIVERFILES += jlink.c -libocdjtagdrivers_la_CPPFLAGS += $(LIBJAYLINK_CFLAGS) +if USE_LIBUSB0 +DRIVERFILES += %D%/usb_common.c +%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBUSB0_CFLAGS) +%C%_libocdjtagdrivers_la_LIBADD += $(LIBUSB0_LIBS) +if !USE_LIBUSB1 +DRIVERFILES += %D%/libusb0_common.c endif endif -# Standard Driver: common files -DRIVERFILES += driver.c +if USE_LIBFTDI +%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBFTDI_CFLAGS) +%C%_libocdjtagdrivers_la_LIBADD += $(LIBFTDI_LIBS) +endif -if USE_LIBUSB1 -DRIVERFILES += libusb1_common.c +if USE_HIDAPI +%C%_libocdjtagdrivers_la_CPPFLAGS += $(HIDAPI_CFLAGS) +%C%_libocdjtagdrivers_la_LIBADD += $(HIDAPI_LIBS) endif -if USE_LIBUSB0 -DRIVERFILES += usb_common.c -if !USE_LIBUSB1 -DRIVERFILES += libusb0_common.c +if USE_LIBJAYLINK +%C%_libocdjtagdrivers_la_CPPFLAGS += $(LIBJAYLINK_CFLAGS) +%C%_libocdjtagdrivers_la_LIBADD += $(LIBJAYLINK_LIBS) +endif + +if JLINK +DRIVERFILES += %D%/jlink.c +if INTERNAL_LIBJAYLINK +SUBDIRS += %D%/libjaylink +DIST_SUBDIRS += %D%/libjaylink + +%C%_libocdjtagdrivers_la_LIBADD += %D%/libjaylink/libjaylink/libjaylink.la +%C%_libocdjtagdrivers_la_CPPFLAGS += -I$(builddir)/%D%/libjaylink/libjaylink -I$(srcdir)/%D%/libjaylink endif endif if BITBANG -DRIVERFILES += bitbang.c +DRIVERFILES += %D%/bitbang.c endif if PARPORT -DRIVERFILES += parport.c +DRIVERFILES += %D%/parport.c endif if DUMMY -DRIVERFILES += dummy.c +DRIVERFILES += %D%/dummy.c endif if FTDI -DRIVERFILES += ftdi.c mpsse.c +DRIVERFILES += %D%/ftdi.c %D%/mpsse.c endif if JTAG_VPI -DRIVERFILES += jtag_vpi.c +DRIVERFILES += %D%/jtag_vpi.c endif if USB_BLASTER_DRIVER -SUBDIRS += usb_blaster -libocdjtagdrivers_la_LIBADD += $(top_builddir)/src/jtag/drivers/usb_blaster/libocdusbblaster.la +%C%_libocdjtagdrivers_la_LIBADD += %D%/usb_blaster/libocdusbblaster.la endif if AMTJTAGACCEL -DRIVERFILES += amt_jtagaccel.c +DRIVERFILES += %D%/amt_jtagaccel.c endif if EP93XX -DRIVERFILES += ep93xx.c +DRIVERFILES += %D%/ep93xx.c endif if AT91RM9200 -DRIVERFILES += at91rm9200.c +DRIVERFILES += %D%/at91rm9200.c endif if GW16012 -DRIVERFILES += gw16012.c +DRIVERFILES += %D%/gw16012.c endif if BITQ -DRIVERFILES += bitq.c +DRIVERFILES += %D%/bitq.c endif if PRESTO -DRIVERFILES += presto.c +DRIVERFILES += %D%/presto.c endif if USBPROG -DRIVERFILES += usbprog.c +DRIVERFILES += %D%/usbprog.c endif if RLINK -DRIVERFILES += rlink.c rlink_speed_table.c +DRIVERFILES += %D%/rlink.c %D%/rlink_speed_table.c endif if ULINK -DRIVERFILES += ulink.c +DRIVERFILES += %D%/ulink.c ulinkdir = $(pkgdatadir)/OpenULINK dist_ulink_DATA = $(ULINK_FIRMWARE)/ulink_firmware.hex +%C%_libocdjtagdrivers_la_LIBADD += -lm endif if VSLLINK -DRIVERFILES += versaloon/usbtoxxx/usbtogpio.c -DRIVERFILES += versaloon/usbtoxxx/usbtojtagraw.c -DRIVERFILES += versaloon/usbtoxxx/usbtoswd.c -DRIVERFILES += versaloon/usbtoxxx/usbtopwr.c -DRIVERFILES += versaloon/usbtoxxx/usbtoxxx.c -DRIVERFILES += versaloon/versaloon.c -DRIVERFILES += vsllink.c +DRIVERFILES += %D%/versaloon/usbtoxxx/usbtogpio.c +DRIVERFILES += %D%/versaloon/usbtoxxx/usbtojtagraw.c +DRIVERFILES += %D%/versaloon/usbtoxxx/usbtoswd.c +DRIVERFILES += %D%/versaloon/usbtoxxx/usbtopwr.c +DRIVERFILES += %D%/versaloon/usbtoxxx/usbtoxxx.c +DRIVERFILES += %D%/versaloon/versaloon.c +DRIVERFILES += %D%/vsllink.c endif if ARMJTAGEW -DRIVERFILES += arm-jtag-ew.c +DRIVERFILES += %D%/arm-jtag-ew.c endif if BUSPIRATE -DRIVERFILES += buspirate.c +DRIVERFILES += %D%/buspirate.c endif if REMOTE_BITBANG -DRIVERFILES += remote_bitbang.c +DRIVERFILES += %D%/remote_bitbang.c endif if HLADAPTER -DRIVERFILES += stlink_usb.c -DRIVERFILES += ti_icdi_usb.c +DRIVERFILES += %D%/stlink_usb.c +DRIVERFILES += %D%/ti_icdi_usb.c endif if OSBDM -DRIVERFILES += osbdm.c +DRIVERFILES += %D%/osbdm.c endif if OPENDOUS -DRIVERFILES += opendous.c +DRIVERFILES += %D%/opendous.c endif if SYSFSGPIO -DRIVERFILES += sysfsgpio.c +DRIVERFILES += %D%/sysfsgpio.c endif if BCM2835GPIO -DRIVERFILES += bcm2835gpio.c +DRIVERFILES += %D%/bcm2835gpio.c endif if OPENJTAG -DRIVERFILES += openjtag.c +DRIVERFILES += %D%/openjtag.c endif if CMSIS_DAP -DRIVERFILES += cmsis_dap_usb.c -endif - -noinst_HEADERS = \ - bitbang.h \ - bitq.h \ - libusb0_common.h \ - libusb1_common.h \ - libusb_common.h \ - minidriver_imp.h \ - mpsse.h \ - rlink.h \ - rlink_dtc_cmd.h \ - rlink_ep1_cmd.h \ - rlink_st7.h \ - usb_common.h \ - versaloon/usbtoxxx/usbtoxxx.h \ - versaloon/usbtoxxx/usbtoxxx_internal.h \ - versaloon/versaloon.h \ - versaloon/versaloon_include.h \ - versaloon/versaloon_internal.h - -DIST_SUBDIRS = usb_blaster - -if JLINK -if INTERNAL_LIBJAYLINK -DIST_SUBDIRS += libjaylink -endif -endif - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +DRIVERFILES += %D%/cmsis_dap_usb.c +endif + +DRIVERHEADERS = \ + %D%/bitbang.h \ + %D%/bitq.h \ + %D%/libusb0_common.h \ + %D%/libusb1_common.h \ + %D%/libusb_common.h \ + %D%/minidriver_imp.h \ + %D%/mpsse.h \ + %D%/rlink.h \ + %D%/rlink_dtc_cmd.h \ + %D%/rlink_ep1_cmd.h \ + %D%/rlink_st7.h \ + %D%/usb_common.h \ + %D%/versaloon/usbtoxxx/usbtoxxx.h \ + %D%/versaloon/usbtoxxx/usbtoxxx_internal.h \ + %D%/versaloon/versaloon.h \ + %D%/versaloon/versaloon_include.h \ + %D%/versaloon/versaloon_internal.h + +include %D%/usb_blaster/Makefile.am diff --git a/src/jtag/drivers/libusb_common.h b/src/jtag/drivers/libusb_common.h index 563af10..599a0a9 100644 --- a/src/jtag/drivers/libusb_common.h +++ b/src/jtag/drivers/libusb_common.h @@ -19,9 +19,9 @@ #define OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H #ifdef HAVE_LIBUSB1 -#include +#include "libusb1_common.h" #else -#include +#include "libusb0_common.h" #endif #endif /* OPENOCD_JTAG_DRIVERS_LIBUSB_COMMON_H */ diff --git a/src/jtag/drivers/usb_blaster/Makefile.am b/src/jtag/drivers/usb_blaster/Makefile.am index 0d4ef61..a6694c5 100644 --- a/src/jtag/drivers/usb_blaster/Makefile.am +++ b/src/jtag/drivers/usb_blaster/Makefile.am @@ -1,20 +1,13 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libocdusbblaster.la +%C%_libocdusbblaster_la_SOURCES = $(USB_BLASTER_SRC) +%C%_libocdusbblaster_la_CPPFLAGS = -I$(top_srcdir)/src/jtag/drivers $(AM_CPPFLAGS) $(LIBUSB1_CFLAGS) $(LIBFTDI_CFLAGS) -AM_CPPFLAGS += -I$(top_srcdir)/src/jtag/drivers $(LIBUSB1_CFLAGS) $(LIBFTDI_CFLAGS) - -noinst_LTLIBRARIES = libocdusbblaster.la -libocdusbblaster_la_SOURCES = $(USB_BLASTER_SRC) - -USB_BLASTER_SRC = usb_blaster.c +USB_BLASTER_SRC = %D%/usb_blaster.c %D%/ublast_access.h if USB_BLASTER -USB_BLASTER_SRC += ublast_access_ftdi.c +USB_BLASTER_SRC += %D%/ublast_access_ftdi.c endif if USB_BLASTER_2 -USB_BLASTER_SRC += ublast2_access_libusb.c +USB_BLASTER_SRC += %D%/ublast2_access_libusb.c endif - -noinst_HEADERS = ublast_access.h - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in diff --git a/src/jtag/hla/Makefile.am b/src/jtag/hla/Makefile.am index 4fbc70e..6bb2960 100644 --- a/src/jtag/hla/Makefile.am +++ b/src/jtag/hla/Makefile.am @@ -1,23 +1,11 @@ -include $(top_srcdir)/common.mk - -noinst_LTLIBRARIES = libocdhla.la - -libocdhla_la_SOURCES = \ - $(HLFILES) - -HLFILES = - -if HLADAPTER -HLFILES += hla_transport.c -HLFILES += hla_tcl.c -HLFILES += hla_interface.c -HLFILES += hla_layout.c -endif - -noinst_HEADERS = \ - hla_interface.h \ - hla_layout.h \ - hla_tcl.h \ - hla_transport.h - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +noinst_LTLIBRARIES += %D%/libocdhla.la + +%C%_libocdhla_la_SOURCES = \ + %D%/hla_transport.c \ + %D%/hla_tcl.c \ + %D%/hla_interface.c \ + %D%/hla_layout.c \ + %D%/hla_transport.h \ + %D%/hla_interface.h \ + %D%/hla_layout.h \ + %D%/hla_tcl.h diff --git a/src/pld/Makefile.am b/src/pld/Makefile.am index 93b79f4..7f3a554 100644 --- a/src/pld/Makefile.am +++ b/src/pld/Makefile.am @@ -1,8 +1,8 @@ -include $(top_srcdir)/common.mk - -METASOURCES = AUTO -noinst_LTLIBRARIES = libpld.la -noinst_HEADERS = pld.h xilinx_bit.h virtex2.h -libpld_la_SOURCES = pld.c xilinx_bit.c virtex2.c - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +noinst_LTLIBRARIES += %D%/libpld.la +%C%_libpld_la_SOURCES = \ + %D%/pld.c \ + %D%/xilinx_bit.c \ + %D%/virtex2.c \ + %D%/pld.h \ + %D%/xilinx_bit.h \ + %D%/virtex2.h diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am index a9122b2..aca266e 100644 --- a/src/rtos/Makefile.am +++ b/src/rtos/Makefile.am @@ -1,32 +1,32 @@ -# *************************************************************************** -# * Copyright (C) 2011 by Broadcom Corporation * -# * Evan Hunter - ehunter@broadcom.com * -# * * -# * 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, see . * -# *************************************************************************** +noinst_LTLIBRARIES += %D%/librtos.la +%C%_librtos_la_SOURCES = \ + %D%/rtos.c \ + %D%/rtos_standard_stackings.c \ + %D%/rtos_ecos_stackings.c \ + %D%/rtos_chibios_stackings.c \ + %D%/rtos_embkernel_stackings.c \ + %D%/rtos_mqx_stackings.c \ + %D%/rtos_ucos_iii_stackings.c \ + %D%/FreeRTOS.c \ + %D%/ThreadX.c \ + %D%/eCos.c \ + %D%/linux.c \ + %D%/ChibiOS.c \ + %D%/embKernel.c \ + %D%/mqx.c \ + %D%/uCOS-III.c \ + %D%/rtos.h \ + %D%/rtos_standard_stackings.h \ + %D%/rtos_ecos_stackings.h \ + %D%/linux_header.h \ + %D%/rtos_chibios_stackings.h \ + %D%/rtos_embkernel_stackings.h \ + %D%/rtos_mqx_stackings.h \ + %D%/rtos_ucos_iii_stackings.h -include $(top_srcdir)/common.mk +%C%_librtos_la_CFLAGS = -METASOURCES = AUTO -noinst_LTLIBRARIES = librtos.la -noinst_HEADERS = rtos.h rtos_standard_stackings.h rtos_ecos_stackings.h linux_header.h rtos_chibios_stackings.h rtos_embkernel_stackings.h rtos_mqx_stackings.h rtos_ucos_iii_stackings.h -librtos_la_SOURCES = rtos.c rtos_standard_stackings.c rtos_ecos_stackings.c rtos_chibios_stackings.c rtos_embkernel_stackings.c rtos_mqx_stackings.c rtos_ucos_iii_stackings.c FreeRTOS.c ThreadX.c eCos.c linux.c ChibiOS.c embKernel.c mqx.c uCOS-III.c - -librtos_la_CFLAGS = if IS_MINGW # FD_* macros are sloppy with their signs on MinGW32 platform -librtos_la_CFLAGS += -Wno-sign-compare +%C%_librtos_la_CFLAGS += -Wno-sign-compare endif - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in diff --git a/src/server/Makefile.am b/src/server/Makefile.am index 04d3035..5970d03 100644 --- a/src/server/Makefile.am +++ b/src/server/Makefile.am @@ -1,23 +1,19 @@ -include $(top_srcdir)/common.mk +noinst_LTLIBRARIES += %D%/libserver.la +%C%_libserver_la_SOURCES = \ + %D%/server.c \ + %D%/telnet_server.c \ + %D%/gdb_server.c \ + %D%/server.h \ + %D%/telnet_server.h \ + %D%/gdb_server.h \ + %D%/server_stubs.c \ + %D%/tcl_server.c \ + %D%/tcl_server.h -METASOURCES = AUTO -noinst_LTLIBRARIES = libserver.la -noinst_HEADERS = server.h telnet_server.h gdb_server.h -libserver_la_SOURCES = server.c telnet_server.c gdb_server.c - -libserver_la_SOURCES += server_stubs.c - -libserver_la_CFLAGS = +%C%_libserver_la_CFLAGS = if IS_MINGW # FD_* macros are sloppy with their signs on MinGW32 platform -libserver_la_CFLAGS += -Wno-sign-compare +%C%_libserver_la_CFLAGS += -Wno-sign-compare endif -# tcl server addons -noinst_HEADERS += tcl_server.h -libserver_la_SOURCES += tcl_server.c - -EXTRA_DIST = \ - startup.tcl - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +STARTUP_TCL_SRCS += %D%/startup.tcl diff --git a/src/svf/Makefile.am b/src/svf/Makefile.am index 3a14d20..5603d53 100644 --- a/src/svf/Makefile.am +++ b/src/svf/Makefile.am @@ -1,8 +1,2 @@ -include $(top_srcdir)/common.mk - -METASOURCES = AUTO -noinst_LTLIBRARIES = libsvf.la -noinst_HEADERS = svf.h -libsvf_la_SOURCES = svf.c - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +noinst_LTLIBRARIES += %D%/libsvf.la +%C%_libsvf_la_SOURCES = %D%/svf.c %D%/svf.h diff --git a/src/target/Makefile.am b/src/target/Makefile.am index dc7973d..eb0d62e 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -1,18 +1,15 @@ -include $(top_srcdir)/common.mk - if OOCD_TRACE -OOCD_TRACE_FILES = oocd_trace.c +OOCD_TRACE_FILES = %D%/oocd_trace.c else OOCD_TRACE_FILES = endif -SUBDIRS = openrisc -libtarget_la_LIBADD = $(top_builddir)/src/target/openrisc/libopenrisc.la +%C%_libtarget_la_LIBADD = %D%/openrisc/libopenrisc.la +STARTUP_TCL_SRCS += %D%/startup.tcl -METASOURCES = AUTO -noinst_LTLIBRARIES = libtarget.la -libtarget_la_SOURCES = \ +noinst_LTLIBRARIES += %D%/libtarget.la +%C%_libtarget_la_SOURCES = \ $(TARGET_CORE_SRC) \ $(ARM_DEBUG_SRC) \ $(ARMV4_5_SRC) \ @@ -23,178 +20,175 @@ libtarget_la_SOURCES = \ $(MIPS32_SRC) \ $(NDS32_SRC) \ $(INTEL_IA32_SRC) \ - avrt.c \ - dsp563xx.c \ - dsp563xx_once.c \ - dsp5680xx.c \ - hla_target.c + %D%/avrt.c \ + %D%/dsp563xx.c \ + %D%/dsp563xx_once.c \ + %D%/dsp5680xx.c \ + %D%/hla_target.c TARGET_CORE_SRC = \ - algorithm.c \ - register.c \ - image.c \ - breakpoints.c \ - target.c \ - target_request.c \ - testee.c \ - smp.c + %D%/algorithm.c \ + %D%/register.c \ + %D%/image.c \ + %D%/breakpoints.c \ + %D%/target.c \ + %D%/target_request.c \ + %D%/testee.c \ + %D%/smp.c ARMV4_5_SRC = \ - armv4_5.c \ - armv4_5_mmu.c \ - armv4_5_cache.c \ + %D%/armv4_5.c \ + %D%/armv4_5_mmu.c \ + %D%/armv4_5_cache.c \ $(ARM7_9_SRC) ARM7_9_SRC = \ - arm7_9_common.c \ - arm7tdmi.c \ - arm720t.c \ - arm9tdmi.c \ - arm920t.c \ - arm966e.c \ - arm946e.c \ - arm926ejs.c \ - feroceon.c + %D%/arm7_9_common.c \ + %D%/arm7tdmi.c \ + %D%/arm720t.c \ + %D%/arm9tdmi.c \ + %D%/arm920t.c \ + %D%/arm966e.c \ + %D%/arm946e.c \ + %D%/arm926ejs.c \ + %D%/feroceon.c ARM_MISC_SRC = \ - fa526.c \ - xscale.c + %D%/fa526.c \ + %D%/xscale.c ARMV6_SRC = \ - arm11.c \ - arm11_dbgtap.c + %D%/arm11.c \ + %D%/arm11_dbgtap.c ARMV7_SRC = \ - armv7m.c \ - armv7m_trace.c \ - cortex_m.c \ - armv7a.c \ - cortex_a.c \ - ls1_sap.c + %D%/armv7m.c \ + %D%/armv7m_trace.c \ + %D%/cortex_m.c \ + %D%/armv7a.c \ + %D%/cortex_a.c \ + %D%/ls1_sap.c ARM_DEBUG_SRC = \ - arm_dpm.c \ - arm_jtag.c \ - arm_disassembler.c \ - arm_simulator.c \ - arm_semihosting.c \ - arm_adi_v5.c \ - armv7a_cache.c \ - armv7a_cache_l2x.c \ - adi_v5_jtag.c \ - adi_v5_swd.c \ - embeddedice.c \ - trace.c \ - etb.c \ - etm.c \ + %D%/arm_dpm.c \ + %D%/arm_jtag.c \ + %D%/arm_disassembler.c \ + %D%/arm_simulator.c \ + %D%/arm_semihosting.c \ + %D%/arm_adi_v5.c \ + %D%/armv7a_cache.c \ + %D%/armv7a_cache_l2x.c \ + %D%/adi_v5_jtag.c \ + %D%/adi_v5_swd.c \ + %D%/embeddedice.c \ + %D%/trace.c \ + %D%/etb.c \ + %D%/etm.c \ $(OOCD_TRACE_FILES) \ - etm_dummy.c + %D%/etm_dummy.c AVR32_SRC = \ - avr32_ap7k.c \ - avr32_jtag.c \ - avr32_mem.c \ - avr32_regs.c + %D%/avr32_ap7k.c \ + %D%/avr32_jtag.c \ + %D%/avr32_mem.c \ + %D%/avr32_regs.c MIPS32_SRC = \ - mips32.c \ - mips_m4k.c \ - mips32_pracc.c \ - mips32_dmaacc.c \ - mips_ejtag.c + %D%/mips32.c \ + %D%/mips_m4k.c \ + %D%/mips32_pracc.c \ + %D%/mips32_dmaacc.c \ + %D%/mips_ejtag.c NDS32_SRC = \ - nds32.c \ - nds32_reg.c \ - nds32_cmd.c \ - nds32_disassembler.c \ - nds32_tlb.c \ - nds32_v2.c \ - nds32_v3_common.c \ - nds32_v3.c \ - nds32_v3m.c \ - nds32_aice.c + %D%/nds32.c \ + %D%/nds32_reg.c \ + %D%/nds32_cmd.c \ + %D%/nds32_disassembler.c \ + %D%/nds32_tlb.c \ + %D%/nds32_v2.c \ + %D%/nds32_v3_common.c \ + %D%/nds32_v3.c \ + %D%/nds32_v3m.c \ + %D%/nds32_aice.c INTEL_IA32_SRC = \ - quark_x10xx.c \ - quark_d20xx.c \ - lakemont.c \ - x86_32_common.c - -noinst_HEADERS = \ - algorithm.h \ - arm.h \ - arm_dpm.h \ - arm_jtag.h \ - arm_adi_v5.h \ - armv7a_cache.h \ - armv7a_cache_l2x.h \ - arm_disassembler.h \ - arm_opcodes.h \ - arm_simulator.h \ - arm_semihosting.h \ - arm7_9_common.h \ - arm7tdmi.h \ - arm720t.h \ - arm9tdmi.h \ - arm920t.h \ - arm926ejs.h \ - arm966e.h \ - arm946e.h \ - arm11.h \ - arm11_dbgtap.h \ - armv4_5.h \ - armv4_5_mmu.h \ - armv4_5_cache.h \ - armv7a.h \ - armv7m.h \ - armv7m_trace.h \ - avrt.h \ - dsp563xx.h \ - dsp563xx_once.h \ - dsp5680xx.h \ - breakpoints.h \ - cortex_m.h \ - cortex_a.h \ - embeddedice.h \ - etb.h \ - etm.h \ - etm_dummy.h \ - image.h \ - mips32.h \ - mips_m4k.h \ - mips_ejtag.h \ - mips32_pracc.h \ - mips32_dmaacc.h \ - oocd_trace.h \ - register.h \ - target.h \ - target_type.h \ - trace.h \ - target_request.h \ - trace.h \ - xscale.h \ - smp.h \ - avr32_ap7k.h \ - avr32_jtag.h \ - avr32_mem.h \ - avr32_regs.h \ - nds32.h \ - nds32_cmd.h \ - nds32_disassembler.h \ - nds32_edm.h \ - nds32_insn.h \ - nds32_reg.h \ - nds32_tlb.h \ - nds32_v2.h \ - nds32_v3_common.h \ - nds32_v3.h \ - nds32_v3m.h \ - nds32_aice.h \ - lakemont.h \ - x86_32_common.h - -ocddatadir = $(pkglibdir) -nobase_dist_ocddata_DATA = - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in + %D%/quark_x10xx.c \ + %D%/quark_d20xx.c \ + %D%/lakemont.c \ + %D%/x86_32_common.c + +%C%_libtarget_la_SOURCES += \ + %D%/algorithm.h \ + %D%/arm.h \ + %D%/arm_dpm.h \ + %D%/arm_jtag.h \ + %D%/arm_adi_v5.h \ + %D%/armv7a_cache.h \ + %D%/armv7a_cache_l2x.h \ + %D%/arm_disassembler.h \ + %D%/arm_opcodes.h \ + %D%/arm_simulator.h \ + %D%/arm_semihosting.h \ + %D%/arm7_9_common.h \ + %D%/arm7tdmi.h \ + %D%/arm720t.h \ + %D%/arm9tdmi.h \ + %D%/arm920t.h \ + %D%/arm926ejs.h \ + %D%/arm966e.h \ + %D%/arm946e.h \ + %D%/arm11.h \ + %D%/arm11_dbgtap.h \ + %D%/armv4_5.h \ + %D%/armv4_5_mmu.h \ + %D%/armv4_5_cache.h \ + %D%/armv7a.h \ + %D%/armv7m.h \ + %D%/armv7m_trace.h \ + %D%/avrt.h \ + %D%/dsp563xx.h \ + %D%/dsp563xx_once.h \ + %D%/dsp5680xx.h \ + %D%/breakpoints.h \ + %D%/cortex_m.h \ + %D%/cortex_a.h \ + %D%/embeddedice.h \ + %D%/etb.h \ + %D%/etm.h \ + %D%/etm_dummy.h \ + %D%/image.h \ + %D%/mips32.h \ + %D%/mips_m4k.h \ + %D%/mips_ejtag.h \ + %D%/mips32_pracc.h \ + %D%/mips32_dmaacc.h \ + %D%/oocd_trace.h \ + %D%/register.h \ + %D%/target.h \ + %D%/target_type.h \ + %D%/trace.h \ + %D%/target_request.h \ + %D%/trace.h \ + %D%/xscale.h \ + %D%/smp.h \ + %D%/avr32_ap7k.h \ + %D%/avr32_jtag.h \ + %D%/avr32_mem.h \ + %D%/avr32_regs.h \ + %D%/nds32.h \ + %D%/nds32_cmd.h \ + %D%/nds32_disassembler.h \ + %D%/nds32_edm.h \ + %D%/nds32_insn.h \ + %D%/nds32_reg.h \ + %D%/nds32_tlb.h \ + %D%/nds32_v2.h \ + %D%/nds32_v3_common.h \ + %D%/nds32_v3.h \ + %D%/nds32_v3m.h \ + %D%/nds32_aice.h \ + %D%/lakemont.h \ + %D%/x86_32_common.h + +include %D%/openrisc/Makefile.am diff --git a/src/target/breakpoints.h b/src/target/breakpoints.h index 6e260ab..842fc18 100644 --- a/src/target/breakpoints.h +++ b/src/target/breakpoints.h @@ -19,6 +19,8 @@ #ifndef OPENOCD_TARGET_BREAKPOINTS_H #define OPENOCD_TARGET_BREAKPOINTS_H +#include + struct target; enum breakpoint_type { diff --git a/src/target/openrisc/Makefile.am b/src/target/openrisc/Makefile.am index b00a30d..5a2549a 100644 --- a/src/target/openrisc/Makefile.am +++ b/src/target/openrisc/Makefile.am @@ -1,18 +1,12 @@ -include $(top_srcdir)/common.mk - -noinst_LTLIBRARIES = libopenrisc.la -libopenrisc_la_SOURCES = $(OPENRISC_SRC) - -OPENRISC_SRC = \ - or1k.c \ - or1k_du_adv.c \ - or1k_tap_mohor.c \ - or1k_tap_vjtag.c \ - or1k_tap_xilinx_bscan.c \ - jsp_server.c - -noinst_HEADERS = \ - or1k.h \ - or1k_du.h \ - or1k_tap.h \ - jsp_server.h +noinst_LTLIBRARIES += %D%/libopenrisc.la +%C%_libopenrisc_la_SOURCES = \ + %D%/or1k.c \ + %D%/or1k_du_adv.c \ + %D%/or1k_tap_mohor.c \ + %D%/or1k_tap_vjtag.c \ + %D%/or1k_tap_xilinx_bscan.c \ + %D%/jsp_server.c \ + %D%/or1k.h \ + %D%/or1k_du.h \ + %D%/or1k_tap.h \ + %D%/jsp_server.h diff --git a/src/transport/Makefile.am b/src/transport/Makefile.am index 7c6224a..9076d9b 100644 --- a/src/transport/Makefile.am +++ b/src/transport/Makefile.am @@ -1,11 +1,4 @@ -include $(top_srcdir)/common.mk - -#METASOURCES = AUTO -noinst_LTLIBRARIES = libtransport.la -libtransport_la_SOURCES = \ - transport.c - -noinst_HEADERS = \ - transport.h - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +noinst_LTLIBRARIES += %D%/libtransport.la +%C%_libtransport_la_SOURCES = \ + %D%/transport.c \ + %D%/transport.h diff --git a/src/xsvf/Makefile.am b/src/xsvf/Makefile.am index 1b9cfab..61e6fb9 100644 --- a/src/xsvf/Makefile.am +++ b/src/xsvf/Makefile.am @@ -1,8 +1,2 @@ -include $(top_srcdir)/common.mk - -METASOURCES = AUTO -noinst_LTLIBRARIES = libxsvf.la -noinst_HEADERS = xsvf.h -libxsvf_la_SOURCES = xsvf.c - -MAINTAINERCLEANFILES = $(srcdir)/Makefile.in +noinst_LTLIBRARIES += %D%/libxsvf.la +%C%_libxsvf_la_SOURCES = %D%/xsvf.c %D%/xsvf.h -- cgit v1.1 From 621742727a40e190e073d9fde7f4bce3c01e81c5 Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Fri, 18 Nov 2016 20:56:18 +0100 Subject: configure: De-duplicate code in AC_CHECK_HEADERS Combine all checks that have the same required includes. Change-Id: I9b4567766e037922c2ffb737f32e9c12af43bf0e Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3884 Tested-by: jenkins Reviewed-by: Paul Fertser --- configure.ac | 58 +--------------------------------------------------------- 1 file changed, 1 insertion(+), 57 deletions(-) diff --git a/configure.ac b/configure.ac index c6c31be..f25dbc5 100644 --- a/configure.ac +++ b/configure.ac @@ -45,67 +45,11 @@ AC_SEARCH_LIBS([ioperm], [ioperm]) AC_SEARCH_LIBS([dlopen], [dl]) AC_CHECK_HEADERS([sys/socket.h]) -AC_CHECK_HEADERS([arpa/inet.h], [], [], [dnl -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -]) AC_CHECK_HEADERS([elf.h]) AC_CHECK_HEADERS([dirent.h]) AC_CHECK_HEADERS([fcntl.h]) -AC_CHECK_HEADERS([ifaddrs.h], [], [], [dnl -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -]) AC_CHECK_HEADERS([malloc.h]) AC_CHECK_HEADERS([netdb.h]) -AC_CHECK_HEADERS([netinet/in.h], [], [], [dnl -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -]) -AC_CHECK_HEADERS([netinet/tcp.h], [], [], [dnl -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif -#ifdef HAVE_SYS_SOCKET_H -# include -#endif -]) AC_CHECK_HEADERS([poll.h]) AC_CHECK_HEADERS([pthread.h]) AC_CHECK_HEADERS([strings.h]) @@ -116,7 +60,7 @@ AC_CHECK_HEADERS([sys/stat.h]) AC_CHECK_HEADERS([sys/time.h]) AC_CHECK_HEADERS([sys/types.h]) AC_CHECK_HEADERS([unistd.h]) -AC_CHECK_HEADERS([net/if.h], [], [], [dnl +AC_CHECK_HEADERS([arpa/inet.h ifaddrs.h netinet/in.h netinet/tcp.h net/if.h], [], [], [dnl #include #ifdef STDC_HEADERS # include -- cgit v1.1 From f8d2262c4beab4e54951c6b1f242d95e78849316 Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Fri, 18 Nov 2016 21:21:10 +0100 Subject: Deprecate ZY1000, ioutils and oocd_trace These have not been maintained for a very long time so I say it's time we remove them. Change-Id: Ic091978d734be09347e271736df0f7f7f9095243 Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3885 Tested-by: jenkins Reviewed-by: Paul Fertser --- configure.ac | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/configure.ac b/configure.ac index f25dbc5..0935c75 100644 --- a/configure.ac +++ b/configure.ac @@ -760,3 +760,26 @@ m4_foreach([adapter], [USB1_ADAPTERS, USB_ADAPTERS, USB0_ADAPTERS, ]) ]) echo + +AS_IF([test "x$build_oocd_trace" = "xyes"], [ + echo 'WARNING! Deprecated configure option (--enable-oocd_trace)' + echo 'The oocd_trace driver is deprecated and will be removed in the next release.' + echo 'If you regularly use this driver, please report to the OpenOCD Mailing List.' + echo +]) + +AS_IF([test "x$build_zy1000" = "xyes" -o "x$build_zy1000_master" = "xyes"], [ + echo 'WARNING! Deprecated configure option (--enable-zy1000, --enable-zy1000-master)' + echo 'Support for the ZY1000 platform is deprecated and will be removed in the next' + echo 'release. If you regularly use this platform, please report to the OpenOCD' + echo 'Mailing List.' + echo +]) + +AS_IF([test "x$build_ioutil" = "xyes"], [ + echo 'WARNING! Deprecated configure option (--enable-ioutil)' + echo 'Support for the ioutil functions is deprecated and will be removed in the next' + echo 'release. If you regularly depend on this functionality, please report to the' + echo 'OpenOCD Mailing List.' + echo +]) -- cgit v1.1 From a033a27f6e2b2a8d3207e7d95ba13d3956ecdfbf Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Fri, 18 Nov 2016 21:49:44 +0100 Subject: configure: Fail on enabling sysfsgpio on non-linux OS Change-Id: I5036d8eca6a6e6ed47e3b9ff78bc3a3bf34491fb Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3888 Tested-by: jenkins Reviewed-by: Paul Fertser --- configure.ac | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configure.ac b/configure.ac index 0935c75..f7deae4 100644 --- a/configure.ac +++ b/configure.ac @@ -316,6 +316,14 @@ AC_ARG_ENABLE([sysfsgpio], AS_HELP_STRING([--enable-sysfsgpio], [Enable building support for programming driven via sysfs gpios.]), [build_sysfsgpio=$enableval], [build_sysfsgpio=no]) +AS_CASE([$host_os], + [linux*], [], + [ + AS_IF([test "x$build_sysfsgpio" = "xyes"], [ + AC_MSG_ERROR([sysfsgpio is only available on linux]) + ]) +]) + AC_ARG_ENABLE([minidriver_dummy], AS_HELP_STRING([--enable-minidriver-dummy], [Enable the dummy minidriver.]), [build_minidriver_dummy=$enableval], [build_minidriver_dummy=no]) -- cgit v1.1 From 49cac156bb23ef304e4a8520b1c5600846fac0cc Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 14 Nov 2016 19:20:36 +0100 Subject: stm32l0.cfg: Add examine-end event like on other STM32 targets. Enable debug in standby/stop/sleep. Stop watchdogs during halt. Change-Id: I8383a191cd897118bd88bf78528d05943f3a368e Signed-off-by: Uwe Bonnes Reviewed-on: http://openocd.zylin.com/3882 Tested-by: jenkins Reviewed-by: Paul Fertser --- tcl/target/stm32l0.cfg | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/tcl/target/stm32l0.cfg b/tcl/target/stm32l0.cfg index fd8f951..245213b 100644 --- a/tcl/target/stm32l0.cfg +++ b/tcl/target/stm32l0.cfg @@ -4,6 +4,7 @@ # source [find target/swj-dp.tcl] +source [find mem_helper.tcl] if { [info exists CHIPNAME] } { set _CHIPNAME $CHIPNAME @@ -75,3 +76,12 @@ $_TARGETNAME configure -event reset-init { $_TARGETNAME configure -event reset-start { adapter_khz 300 } + +$_TARGETNAME configure -event examine-end { + # DBGMCU_CR |= DBG_STANDBY | DBG_STOP | DBG_SLEEP + mmw 0x40015804 0x00000007 0 + + # Stop watchdog counters during halt + # DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP + mmw 0x40015808 0x00001800 0 +} -- cgit v1.1 From 0c2de8b3d0bcc79cac026945d7f29989bbe4084f Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Mon, 25 Jul 2016 14:43:35 +0200 Subject: board: add configuration for freescale twr-vf65gs10 system module This patch contains configuration for the twr-vf65gs10 system module of the Freescale (NXP) tower system. It provides support for both the CMSIS-DAP available via USB and the Cortex+ETM connector on J5. The configuration also contains DDR and clock init code hooked into the reset-init event handler. Change-Id: I68303e0038e137dcadc57525e662428769fb69f2 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3564 Tested-by: jenkins Reviewed-by: Andreas Fritiofson Reviewed-by: Paul Fertser --- tcl/board/twr-vf65gs10.cfg | 201 ++++++++++++++++++++++++++++++++++++ tcl/board/twr-vf65gs10_cmsisdap.cfg | 15 +++ 2 files changed, 216 insertions(+) create mode 100644 tcl/board/twr-vf65gs10.cfg create mode 100644 tcl/board/twr-vf65gs10_cmsisdap.cfg diff --git a/tcl/board/twr-vf65gs10.cfg b/tcl/board/twr-vf65gs10.cfg new file mode 100644 index 0000000..a80407f --- /dev/null +++ b/tcl/board/twr-vf65gs10.cfg @@ -0,0 +1,201 @@ +# +# Board configuration file for the Freescale VF65GS10 tower board +# +# Board has a 20 pin Cortex+ETM debug connector with only nSRST available +reset_config srst_only + +# This configuration file only deals with the hardware JTAG. +# There is has also an embedded Kinetis K20 with OpenSDA +# where a CMSIS-DAP application can be installed. + +# Source generic VF6xx target configuration +source [find target/vybrid_vf6xx.cfg] + +# basic DDR memory init, setting up pad configuration +# for DDR first then configuring the DDRMC for the +# board +proc ddr_init { } { + # iomux ddr + mww phys 0x40048220 0x00000180 + mww phys 0x40048224 0x00000180 + mww phys 0x40048228 0x00000180 + mww phys 0x4004822c 0x00000180 + mww phys 0x40048230 0x00000180 + mww phys 0x40048234 0x00000180 + mww phys 0x40048238 0x00000180 + mww phys 0x4004823c 0x00000180 + mww phys 0x40048240 0x00000180 + mww phys 0x40048244 0x00000180 + mww phys 0x40048248 0x00000180 + mww phys 0x4004824c 0x00000180 + mww phys 0x40048250 0x00000180 + mww phys 0x40048254 0x00000180 + mww phys 0x40048258 0x00000180 + mww phys 0x4004825c 0x00000180 + mww phys 0x40048260 0x00000180 + mww phys 0x40048264 0x00000180 + mww phys 0x40048268 0x00000180 + mww phys 0x4004826c 0x00000180 + mww phys 0x40048270 0x00000180 + mww phys 0x40048274 0x00000180 + mww phys 0x40048278 0x00000180 + mww phys 0x4004827c 0x00010180 + mww phys 0x40048280 0x00010180 + mww phys 0x40048284 0x00010180 + mww phys 0x40048288 0x00010180 + mww phys 0x4004828c 0x00010180 + mww phys 0x40048290 0x00010180 + mww phys 0x40048294 0x00010180 + mww phys 0x40048298 0x00010180 + mww phys 0x4004829c 0x00010180 + mww phys 0x400482a0 0x00010180 + mww phys 0x400482a4 0x00010180 + mww phys 0x400482a8 0x00010180 + mww phys 0x400482ac 0x00010180 + mww phys 0x400482b0 0x00010180 + mww phys 0x400482b4 0x00010180 + mww phys 0x400482b8 0x00010180 + mww phys 0x400482bc 0x00010180 + mww phys 0x400482c0 0x00010180 + mww phys 0x400482c4 0x00010180 + mww phys 0x400482c8 0x00010180 + mww phys 0x400482cc 0x00000180 + mww phys 0x400482d0 0x00000180 + mww phys 0x400482d4 0x00000180 + mww phys 0x400482d8 0x00000180 + mww phys 0x4004821c 0x000001a0 + # ddr_ctrl_init + mww phys 0x400ae000 0x00000600 + mww phys 0x400ae008 0x00000020 + mww phys 0x400ae028 0x00013880 + mww phys 0x400ae02c 0x00030d40 + mww phys 0x400ae030 0x0000050c + mww phys 0x400ae034 0x15040400 + mww phys 0x400ae038 0x1406040f + mww phys 0x400ae040 0x04040000 + mww phys 0x400ae044 0x006db00c + mww phys 0x400ae048 0x00000403 + mww phys 0x400ae050 0x01000000 + mww phys 0x400ae054 0x00060001 + mww phys 0x400ae058 0x000c0000 + mww phys 0x400ae05c 0x03000200 + mww phys 0x400ae060 0x00000006 + mww phys 0x400ae064 0x00010000 + mww phys 0x400ae068 0x0c30002c + mww phys 0x400ae070 0x00000000 + mww phys 0x400ae074 0x00000003 + mww phys 0x400ae078 0x0000000a + mww phys 0x400ae07c 0x003001d4 + mww phys 0x400ae084 0x00010000 + mww phys 0x400ae088 0x00050500 + mww phys 0x400ae098 0x00000000 + mww phys 0x400ae09c 0x04001002 + mww phys 0x400ae0a4 0x00000001 + mww phys 0x400ae0c0 0x00460420 + mww phys 0x400ae108 0x01000200 + mww phys 0x400ae10c 0x00000040 + mww phys 0x400ae114 0x00000200 + mww phys 0x400ae118 0x00000040 + mww phys 0x400ae120 0x00000000 + mww phys 0x400ae124 0x0a010300 + mww phys 0x400ae128 0x01014040 + mww phys 0x400ae12c 0x01010101 + mww phys 0x400ae130 0x03030100 + mww phys 0x400ae134 0x01000101 + mww phys 0x400ae138 0x0700000c + mww phys 0x400ae13c 0x00000000 + mww phys 0x400ae148 0x10000000 + mww phys 0x400ae15c 0x01000000 + mww phys 0x400ae160 0x00040000 + mww phys 0x400ae164 0x00000002 + mww phys 0x400ae16c 0x00020000 + mww phys 0x400ae180 0x00002819 + mww phys 0x400ae184 0x01000000 + mww phys 0x400ae188 0x00000000 + mww phys 0x400ae18c 0x00000000 + mww phys 0x400ae198 0x00000000 + mww phys 0x400ae1a4 0x00000c00 + mww phys 0x400ae1a8 0x00000000 + mww phys 0x400ae1b8 0x0000000c + mww phys 0x400ae1c8 0x00000000 + mww phys 0x400ae1cc 0x00000000 + mww phys 0x400ae1d4 0x00000000 + mww phys 0x400ae1d8 0x01010000 + mww phys 0x400ae1e0 0x02020000 + mww phys 0x400ae1e4 0x00000202 + mww phys 0x400ae1e8 0x01010064 + mww phys 0x400ae1ec 0x00010101 + mww phys 0x400ae1f0 0x00000064 + mww phys 0x400ae1f8 0x00000800 + mww phys 0x400ae210 0x00000506 + mww phys 0x400ae224 0x00020000 + mww phys 0x400ae228 0x01000000 + mww phys 0x400ae22c 0x04070303 + mww phys 0x400ae230 0x00000040 + mww phys 0x400ae23c 0x06000080 + mww phys 0x400ae240 0x04070303 + mww phys 0x400ae244 0x00000040 + mww phys 0x400ae248 0x00000040 + mww phys 0x400ae24c 0x000f0000 + mww phys 0x400ae250 0x000f0000 + mww phys 0x400ae25c 0x00000101 + mww phys 0x400ae268 0x682c4000 + mww phys 0x400ae26c 0x00000012 + mww phys 0x400ae278 0x00000006 + mww phys 0x400ae284 0x00010202 + mww phys 0x400ae400 0x00002613 + mww phys 0x400ae440 0x00002613 + mww phys 0x400ae404 0x00002615 + mww phys 0x400ae444 0x00002615 + mww phys 0x400ae408 0x00210000 + mww phys 0x400ae448 0x00210000 + mww phys 0x400ae488 0x00210000 + mww phys 0x400ae40c 0x0001012a + mww phys 0x400ae44c 0x0001012a + mww phys 0x400ae48c 0x0001012a + mww phys 0x400ae410 0x00002400 + mww phys 0x400ae450 0x00002400 + mww phys 0x400ae490 0x00002400 + mww phys 0x400ae4c4 0x00000000 + mww phys 0x400ae4c8 0x00001100 + mww phys 0x400ae4d0 0x00010101 + mww phys 0x400ae000 0x00000601 +} + +# clock control init, setting up basic +# clocks +proc clock_init { } { + # captured from u-boot + mww phys 0x4006b040 0xffffffff + mww phys 0x4006b044 0xffffffff + mww phys 0x4006b048 0xffffffff + mww phys 0x4006b04c 0xffffffff + mww phys 0x4006b050 0xffffffff + mww phys 0x4006b058 0xffffffff + mww phys 0x4006b05c 0xffffffff + mww phys 0x4006b060 0xffffffff + mww phys 0x4006b064 0xffffffff + mww phys 0x4006b068 0xffffffff + mww phys 0x40050030 0x00002001 + mww phys 0x40050270 0x80002001 + mww phys 0x4006b000 0x00011005 + mww phys 0x4006b008 0x0001ff24 + mww phys 0x4006b00c 0x00000810 + mww phys 0x4006b010 0x00cc0000 + mww phys 0x4006b014 0x01000000 + mww phys 0x4006b018 0x20000000 + mww phys 0x4006b01c 0x0000001f + mww phys 0x4006b020 0x00000000 +} + +# This function applies the initial configuration after a "reset init" +# command +proc board_init { } { + clock_init + ddr_init +} + +# hook the init function into the reset-init event +${_TARGETNAME}0 configure -event reset-init { board_init } +# set a slow default JTAG clock, can be overridden later +adapter_khz 1000 diff --git a/tcl/board/twr-vf65gs10_cmsisdap.cfg b/tcl/board/twr-vf65gs10_cmsisdap.cfg new file mode 100644 index 0000000..e8db754 --- /dev/null +++ b/tcl/board/twr-vf65gs10_cmsisdap.cfg @@ -0,0 +1,15 @@ +# +# Board configuration file for the Freescale VF65GS10 tower board +# +# CMSIS-DAP via USB-OTG connector +# +source [find interface/cmsis-dap.cfg] + +# only SWD is supported by the CMSIS-DAP on this board +transport select swd + +# Source generic part of twr-vf65gs10 configuration +source [find board/twr-vf65gs10.cfg] + +# override reset configuration +reset_config srst_only \ No newline at end of file -- cgit v1.1 From 0dc707a6d6c4d65375dbc522d73ef1c00e36b447 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Tue, 13 Dec 2016 10:44:51 +0300 Subject: jtag: drivers: ulink: fix uninitialised variable warning This prevents clean build when --enable-verbose-jtag-io is used. Change-Id: I5c9e6968cfa425b1f6f92f59156b6ae38cb9af18 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3907 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- src/jtag/drivers/ulink.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/drivers/ulink.c b/src/jtag/drivers/ulink.c index c319a11..550df1c 100644 --- a/src/jtag/drivers/ulink.c +++ b/src/jtag/drivers/ulink.c @@ -2066,7 +2066,7 @@ static int ulink_khz(int khz, int *jtag_speed) } #ifdef _DEBUG_JTAG_IO_ - long f_tck, f_tms, f_scan_in, f_scan_out, f_scan_io; + long f_tck = 0, f_tms = 0, f_scan_in = 0, f_scan_out = 0, f_scan_io = 0; ulink_calculate_frequency(DELAY_CLOCK_TCK, ulink_handle->delay_clock_tck, &f_tck); -- cgit v1.1 From a5cff3acd37770b2e0f54857c63eee5a1f85fea0 Mon Sep 17 00:00:00 2001 From: Jiri Kastner Date: Fri, 5 Jun 2015 15:45:49 +0200 Subject: contrib: udev: modify rules for users physically in front of machine (TAG+="uaccess") Modern desktop systems with systemd recommend this way to give users access to devices. We change permissions to sane value along the way. See e.g. https://lists.debian.org/debian-devel-announce/2016/11/msg00008.html We also change the filename to put it in order with 71-seat.rules, 60 is default for dh_installudev so pick that as a reasonable value. Change-Id: I15f6fb1b6be853ac097d0ca91955609f9e5eb9cf Signed-off-by: Jiri Kastner Reviewed-on: http://openocd.zylin.com/2804 Tested-by: jenkins Reviewed-by: Robert Jordens Reviewed-by: Andreas Fritiofson --- Makefile.am | 2 +- README | 2 +- contrib/60-openocd.rules | 134 +++++++++++++++++++++++++++++++++++++++++++++++ contrib/99-openocd.rules | 134 ----------------------------------------------- 4 files changed, 136 insertions(+), 136 deletions(-) create mode 100644 contrib/60-openocd.rules delete mode 100644 contrib/99-openocd.rules diff --git a/Makefile.am b/Makefile.am index 579d3a7..69077f8 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,7 +10,7 @@ nobase_dist_pkgdata_DATA = \ contrib/libdcc/dcc_stdio.h \ contrib/libdcc/example.c \ contrib/libdcc/README \ - contrib/99-openocd.rules + contrib/60-openocd.rules SUBDIRS = DIST_SUBDIRS = diff --git a/README b/README index 615ae81..dec3673 100644 --- a/README +++ b/README @@ -233,7 +233,7 @@ Permissions delegation Running OpenOCD with root/administrative permissions is strongly discouraged for security reasons. -For USB devices on GNU/Linux you should use the contrib/99-openocd.rules +For USB devices on GNU/Linux you should use the contrib/60-openocd.rules file. It probably belongs somewhere in /etc/udev/rules.d, but consult your operating system documentation to be sure. Do not forget to add yourself to the "plugdev" group. diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules new file mode 100644 index 0000000..3da1f73 --- /dev/null +++ b/contrib/60-openocd.rules @@ -0,0 +1,134 @@ +# Copy this file to /etc/udev/rules.d/ + +ACTION!="add|change", GOTO="openocd_rules_end" +SUBSYSTEM!="usb|tty|hidraw", GOTO="openocd_rules_end" + +# Please keep this list sorted by VID:PID + +# opendous and estick +ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="204f", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Original FT232/FT245 VID:PID +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Original FT2232 VID:PID +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Original FT4232 VID:PID +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Original FT232H VID:PID +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# DISTORTEC JTAG-lock-pick Tiny 2 +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8220", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# TUMPA, TUMPA Lite +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a98", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a99", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# XDS100v2 +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a6d0", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Xverve Signalyzer Tool (DT-USB-ST), Signalyzer LITE (DT-USB-SLITE) +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca0", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca1", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# TI/Luminary Stellaris Evaluation Board FTDI (several) +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcd9", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# TI/Luminary Stellaris In-Circuit Debug Interface FTDI (ICDI) Board +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcda", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# egnite Turtelizer 2 +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bdc8", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Section5 ICEbear +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c140", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c141", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Amontec JTAGkey and JTAGkey-tiny +ATTRS{idVendor}=="0403", ATTRS{idProduct}=="cff8", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# TI ICDI +ATTRS{idVendor}=="0451", ATTRS{idProduct}=="c32a", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# STLink v1 +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3744", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# STLink v2 +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# STLink v2-1 +ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Hilscher NXHX Boards +ATTRS{idVendor}=="0640", ATTRS{idProduct}=="0028", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Hitex STR9-comStick +ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002c", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Hitex STM32-PerformanceStick +ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002d", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Altera USB Blaster +ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6001", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Amontec JTAGkey-HiSpeed +ATTRS{idVendor}=="0fbb", ATTRS{idProduct}=="1000", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# SEGGER J-Link +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0101", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0102", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0103", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0104", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0105", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0107", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0108", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1010", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1011", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1012", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1013", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1014", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1015", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1016", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1017", MODE="660", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1018", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Raisonance RLink +ATTRS{idVendor}=="138e", ATTRS{idProduct}=="9000", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Debug Board for Neo1973 +ATTRS{idVendor}=="1457", ATTRS{idProduct}=="5118", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Olimex ARM-USB-OCD +ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0003", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Olimex ARM-USB-OCD-TINY +ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0004", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Olimex ARM-JTAG-EW +ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="001e", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Olimex ARM-USB-OCD-TINY-H +ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002a", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Olimex ARM-USB-OCD-H +ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002b", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# USBprog with OpenOCD firmware +ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board +ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Marvell Sheevaplug +ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Keil Software, Inc. ULink +ATTRS{idVendor}=="c251", ATTRS{idProduct}=="2710", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# CMSIS-DAP compatible adapters +ATTRS{product}=="*CMSIS-DAP*", MODE="660", GROUP="plugdev", TAG+="uaccess" + +LABEL="openocd_rules_end" diff --git a/contrib/99-openocd.rules b/contrib/99-openocd.rules deleted file mode 100644 index 057c4b7..0000000 --- a/contrib/99-openocd.rules +++ /dev/null @@ -1,134 +0,0 @@ -# Copy this file to /etc/udev/rules.d/ - -ACTION!="add|change", GOTO="openocd_rules_end" -SUBSYSTEM!="usb|tty|hidraw", GOTO="openocd_rules_end" - -# Please keep this list sorted by VID:PID - -# opendous and estick -ATTRS{idVendor}=="03eb", ATTRS{idProduct}=="204f", MODE="664", GROUP="plugdev" - -# Original FT232/FT245 VID:PID -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="664", GROUP="plugdev" - -# Original FT2232 VID:PID -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", MODE="664", GROUP="plugdev" - -# Original FT4232 VID:PID -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6011", MODE="664", GROUP="plugdev" - -# Original FT232H VID:PID -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="664", GROUP="plugdev" - -# DISTORTEC JTAG-lock-pick Tiny 2 -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8220", MODE="664", GROUP="plugdev" - -# TUMPA, TUMPA Lite -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a98", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="8a99", MODE="664", GROUP="plugdev" - -# XDS100v2 -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="a6d0", MODE="664", GROUP="plugdev" - -# Xverve Signalyzer Tool (DT-USB-ST), Signalyzer LITE (DT-USB-SLITE) -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca0", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bca1", MODE="664", GROUP="plugdev" - -# TI/Luminary Stellaris Evaluation Board FTDI (several) -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcd9", MODE="664", GROUP="plugdev" - -# TI/Luminary Stellaris In-Circuit Debug Interface FTDI (ICDI) Board -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bcda", MODE="664", GROUP="plugdev" - -# egnite Turtelizer 2 -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="bdc8", MODE="664", GROUP="plugdev" - -# Section5 ICEbear -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c140", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="c141", MODE="664", GROUP="plugdev" - -# Amontec JTAGkey and JTAGkey-tiny -ATTRS{idVendor}=="0403", ATTRS{idProduct}=="cff8", MODE="664", GROUP="plugdev" - -# TI ICDI -ATTRS{idVendor}=="0451", ATTRS{idProduct}=="c32a", MODE="664", GROUP="plugdev" - -# STLink v1 -ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3744", MODE="664", GROUP="plugdev" - -# STLink v2 -ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE="664", GROUP="plugdev" - -# STLink v2-1 -ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE="664", GROUP="plugdev" - -# Hilscher NXHX Boards -ATTRS{idVendor}=="0640", ATTRS{idProduct}=="0028", MODE="664", GROUP="plugdev" - -# Hitex STR9-comStick -ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002c", MODE="664", GROUP="plugdev" - -# Hitex STM32-PerformanceStick -ATTRS{idVendor}=="0640", ATTRS{idProduct}=="002d", MODE="664", GROUP="plugdev" - -# Altera USB Blaster -ATTRS{idVendor}=="09fb", ATTRS{idProduct}=="6001", MODE="664", GROUP="plugdev" - -# Amontec JTAGkey-HiSpeed -ATTRS{idVendor}=="0fbb", ATTRS{idProduct}=="1000", MODE="664", GROUP="plugdev" - -# SEGGER J-Link -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0101", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0102", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0103", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0104", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0105", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0107", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="0108", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1010", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1011", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1012", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1013", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1014", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1015", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1016", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1017", MODE="664", GROUP="plugdev" -ATTRS{idVendor}=="1366", ATTRS{idProduct}=="1018", MODE="664", GROUP="plugdev" - -# Raisonance RLink -ATTRS{idVendor}=="138e", ATTRS{idProduct}=="9000", MODE="664", GROUP="plugdev" - -# Debug Board for Neo1973 -ATTRS{idVendor}=="1457", ATTRS{idProduct}=="5118", MODE="664", GROUP="plugdev" - -# Olimex ARM-USB-OCD -ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0003", MODE="664", GROUP="plugdev" - -# Olimex ARM-USB-OCD-TINY -ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="0004", MODE="664", GROUP="plugdev" - -# Olimex ARM-JTAG-EW -ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="001e", MODE="664", GROUP="plugdev" - -# Olimex ARM-USB-OCD-TINY-H -ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002a", MODE="664", GROUP="plugdev" - -# Olimex ARM-USB-OCD-H -ATTRS{idVendor}=="15ba", ATTRS{idProduct}=="002b", MODE="664", GROUP="plugdev" - -# USBprog with OpenOCD firmware -ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="664", GROUP="plugdev" - -# TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board -ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="664", GROUP="plugdev" - -# Marvell Sheevaplug -ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="664", GROUP="plugdev" - -# Keil Software, Inc. ULink -ATTRS{idVendor}=="c251", ATTRS{idProduct}=="2710", MODE="664", GROUP="plugdev" - -# CMSIS-DAP compatible adapters -ATTRS{product}=="*CMSIS-DAP*", MODE="664", GROUP="plugdev" - -LABEL="openocd_rules_end" -- cgit v1.1 From 56d163ce79510c7756567df00ae54155757eaa0f Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Tue, 16 Aug 2016 09:52:28 +0300 Subject: jimtcl: update to 0.77, the current version, enable only specific modules This is needed to fix build on aarch64 to get updated config.guess. Because some newer JimTcl modules that get enabled are failing to build on some of the platforms OpenOCD supports, enable only a fixed set that shouldn't cause any issues. We also disable running Jim Tcl tests on distcheck because they never worked (before 85358e479e5bbf295a5aaf743f3c29a5e1a4fd1c Jim commit) but didn't break Jenkins build; with newer version they're getting run and fail due to limited permissions for filesystem and networking operations. Change-Id: I0b6c6a00bf2cf0902bbb01c9c0224fe93c74ac94 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3700 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- Makefile.am | 4 ++++ configure.ac | 2 +- jimtcl | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/Makefile.am b/Makefile.am index 69077f8..930a307 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,6 +5,10 @@ AUTOMAKE_OPTIONS = gnu 1.6 # make sure we pass the correct jimtcl flags to distcheck DISTCHECK_CONFIGURE_FLAGS = --disable-install-jim +# do not run Jim Tcl tests (esp. during distcheck) +check-recursive: + @true + nobase_dist_pkgdata_DATA = \ contrib/libdcc/dcc_stdio.c \ contrib/libdcc/dcc_stdio.h \ diff --git a/configure.ac b/configure.ac index f7deae4..5630b11 100644 --- a/configure.ac +++ b/configure.ac @@ -550,7 +550,7 @@ AS_IF([test "x$build_buspirate" = "xyes"], [ AS_IF([test "x$use_internal_jimtcl" = "xyes"], [ AS_IF([test -f "$srcdir/jimtcl/configure.ac"], [ - AX_CONFIG_SUBDIR_OPTION([jimtcl], [--disable-install-jim]) + AX_CONFIG_SUBDIR_OPTION([jimtcl], [--disable-install-jim --with-ext="eventloop array clock regexp stdlib tclcompat" --without-ext="default"]) ], [ AC_MSG_ERROR([jimtcl not found, run git submodule init and git submodule update.]) ]) diff --git a/jimtcl b/jimtcl index 51f65c6..a9bf597 160000 --- a/jimtcl +++ b/jimtcl @@ -1 +1 @@ -Subproject commit 51f65c6d38fbf86e1f0b036ad336761fd2ab7fa0 +Subproject commit a9bf5975fd0f89974d689a2d9ebd0873c8d64787 -- cgit v1.1 From 6ddf26c83d0a87b3eb26f75a7da95f13b9c348d9 Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Sat, 19 Nov 2016 21:43:22 +0100 Subject: Search for scripts relative to the executable on all(?) platforms Add a helper to hide the platform-dependent method to get a canonical, absolute, /-separated path to the executable. Use this and the relative path from BINDIR to PKGDATADIR to construct a search path that finds the scripts even if the installation dir is moved, as long as the structure below $prefix is maintained. This method should fully support all the tricks you can to with autotools to customize the installed layout such as overriding the default directories at configure-time and overriding the configured directories at build-time. The exe path detection methods are combined from http://openocd.zylin.com/3388 by Rick Foos and http://openocd.zylin.com/3537 by Steven Stallion, as well as tips found all over internet. Change-Id: Ifc9cc9dd0bf52fbd67b1b0f2383318cda0c422c4 Signed-off-by: Andreas Fritiofson Signed-off-by: Steven Stallion Reviewed-on: http://openocd.zylin.com/3889 Tested-by: jenkins Reviewed-by: Rick Foos Reviewed-by: Paul Fertser --- configure.ac | 2 + src/helper/options.c | 155 ++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 124 insertions(+), 33 deletions(-) diff --git a/configure.ac b/configure.ac index 5630b11..687e95c 100644 --- a/configure.ac +++ b/configure.ac @@ -57,6 +57,7 @@ AC_CHECK_HEADERS([sys/ioctl.h]) AC_CHECK_HEADERS([sys/param.h]) AC_CHECK_HEADERS([sys/select.h]) AC_CHECK_HEADERS([sys/stat.h]) +AC_CHECK_HEADERS([sys/sysctl.h]) AC_CHECK_HEADERS([sys/time.h]) AC_CHECK_HEADERS([sys/types.h]) AC_CHECK_HEADERS([unistd.h]) @@ -86,6 +87,7 @@ AC_CHECK_FUNCS([strnlen]) AC_CHECK_FUNCS([gettimeofday]) AC_CHECK_FUNCS([usleep]) AC_CHECK_FUNCS([vasprintf]) +AC_CHECK_FUNCS([realpath]) # guess-rev.sh only exists in the repository, not in the released archives AC_MSG_CHECKING([whether to build a release]) diff --git a/src/helper/options.c b/src/helper/options.c index b7db10f..409abee 100644 --- a/src/helper/options.c +++ b/src/helper/options.c @@ -29,6 +29,15 @@ #include +#include +#include +#if IS_DARWIN +#include +#endif +#ifdef HAVE_SYS_SYSCTL_H +#include +#endif + static int help_flag, version_flag; static const struct option long_options[] = { @@ -50,52 +59,129 @@ int configuration_output_handler(struct command_context *context, const char *li return ERROR_OK; } -#ifdef _WIN32 -static char *find_suffix(const char *text, const char *suffix) +/* Return the canonical path to the directory the openocd executable is in. + * The path should be absolute, use / as path separator and have all symlinks + * resolved. The returned string is malloc'd. */ +static char *find_exe_path(void) { - size_t text_len = strlen(text); - size_t suffix_len = strlen(suffix); + char *exepath = NULL; + + do { +#if IS_WIN32 && !IS_CYGWIN + exepath = malloc(MAX_PATH); + if (exepath == NULL) + break; + GetModuleFileName(NULL, exepath, MAX_PATH); - if (suffix_len == 0) - return (char *)text + text_len; + /* Convert path separators to UNIX style, should work on Windows also. */ + for (char *p = exepath; *p; p++) { + if (*p == '\\') + *p = '/'; + } - if (suffix_len > text_len || strncmp(text + text_len - suffix_len, suffix, suffix_len) != 0) - return NULL; /* Not a suffix of text */ +#elif IS_DARWIN + exepath = malloc(PROC_PIDPATHINFO_MAXSIZE); + if (exepath == NULL) + break; + if (proc_pidpath(getpid(), exepath, PROC_PIDPATHINFO_MAXSIZE) <= 0) { + free(exepath); + exepath = NULL; + } - return (char *)text + text_len - suffix_len; -} +#elif defined(CTL_KERN) && defined(KERN_PROC) && defined(KERN_PROC_PATHNAME) /* *BSD */ +#ifndef PATH_MAX +#define PATH_MAX 1024 #endif + char *path = malloc(PATH_MAX); + if (path == NULL) + break; + int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; + size_t size = PATH_MAX; -static void add_default_dirs(void) -{ - const char *run_prefix; - char *path; + if (sysctl(mib, (u_int)ARRAY_SIZE(mib), path, &size, NULL, 0) != 0) + break; -#ifdef _WIN32 - char strExePath[MAX_PATH]; - GetModuleFileName(NULL, strExePath, MAX_PATH); +#ifdef HAVE_REALPATH + exepath = realpath(path, NULL); + free(path); +#else + exepath = path; +#endif - /* Strip executable file name, leaving path */ - *strrchr(strExePath, '\\') = '\0'; +#elif defined(HAVE_REALPATH) /* Assume POSIX.1-2008 */ + /* Try Unices in order of likelihood. */ + exepath = realpath("/proc/self/exe", NULL); /* Linux/Cygwin */ + if (exepath == NULL) + exepath = realpath("/proc/self/path/a.out", NULL); /* Solaris */ + if (exepath == NULL) + exepath = realpath("/proc/curproc/file", NULL); /* FreeBSD (Should be covered above) */ +#endif + } while (0); + + if (exepath != NULL) { + /* Strip executable file name, leaving path */ + *strrchr(exepath, '/') = '\0'; + } else { + LOG_WARNING("Could not determine executable path, using configured BINDIR."); + LOG_DEBUG("BINDIR = %s", BINDIR); +#ifdef HAVE_REALPATH + exepath = realpath(BINDIR, NULL); +#else + exepath = strdup(BINDIR); +#endif + } + + return exepath; +} - /* Convert path separators to UNIX style, should work on Windows also. */ - for (char *p = strExePath; *p; p++) { - if (*p == '\\') - *p = '/'; +static char *find_relative_path(const char *from, const char *to) +{ + size_t i; + + /* Skip common /-separated parts of from and to */ + i = 0; + for (size_t n = 0; from[n] == to[n]; n++) { + if (from[n] == '\0') { + i = n; + break; + } + if (from[n] == '/') + i = n + 1; + } + from += i; + to += i; + + /* Count number of /-separated non-empty parts of from */ + i = 0; + while (from[0] != '\0') { + if (from[0] != '/') + i++; + char *next = strchr(from, '/'); + if (next == NULL) + break; + from = next + 1; } - char *end_of_prefix = find_suffix(strExePath, BINDIR); - if (end_of_prefix != NULL) - *end_of_prefix = '\0'; + /* Prepend that number of ../ in front of to */ + char *relpath = malloc(i * 3 + strlen(to) + 1); + relpath[0] = '\0'; + for (size_t n = 0; n < i; n++) + strcat(relpath, "../"); + strcat(relpath, to); - run_prefix = strExePath; -#else - run_prefix = ""; -#endif + return relpath; +} + +static void add_default_dirs(void) +{ + char *path; + char *exepath = find_exe_path(); + char *bin2data = find_relative_path(BINDIR, PKGDATADIR); LOG_DEBUG("bindir=%s", BINDIR); LOG_DEBUG("pkgdatadir=%s", PKGDATADIR); - LOG_DEBUG("run_prefix=%s", run_prefix); + LOG_DEBUG("exepath=%s", exepath); + LOG_DEBUG("bin2data=%s", bin2data); /* * The directory containing OpenOCD-supplied scripts should be @@ -129,17 +215,20 @@ static void add_default_dirs(void) } #endif - path = alloc_printf("%s%s%s", run_prefix, PKGDATADIR, "/site"); + path = alloc_printf("%s/%s/%s", exepath, bin2data, "site"); if (path) { add_script_search_dir(path); free(path); } - path = alloc_printf("%s%s%s", run_prefix, PKGDATADIR, "/scripts"); + path = alloc_printf("%s/%s/%s", exepath, bin2data, "scripts"); if (path) { add_script_search_dir(path); free(path); } + + free(exepath); + free(bin2data); } int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) -- cgit v1.1 From ee4f11dd6822608b60363766646c96c5290ab7ba Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sat, 10 Dec 2016 11:02:52 +0300 Subject: README: fix a typo Change-Id: I1ad1ba001f8fad0fffa9b6bd5b21dd58be4f6181 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3902 Tested-by: jenkins Reviewed-by: Chengyu Zheng --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index dec3673..581082e 100644 --- a/README +++ b/README @@ -4,7 +4,7 @@ Welcome to OpenOCD! OpenOCD provides on-chip programming and debugging support with a layered architecture of JTAG interface and TAP support including: -- (X)SVF playback to faciliate automated boundary scan and FPGA/CPLD +- (X)SVF playback to facilitate automated boundary scan and FPGA/CPLD programming; - debug target support (e.g. ARM, MIPS): single-stepping, breakpoints/watchpoints, gprof profiling, etc; -- cgit v1.1 From d491b88dd94afb7c796dbe89ea52aecdefebf1cc Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Mon, 12 Dec 2016 11:50:17 +0300 Subject: target: cortex_a: fix segfault when SPSR is not properly handled OpenOCD doesn't (yet) know how to handle HYP mode properly so spsr register is not getting initialised when OpenOCD connects to a target stopped in this mode. Reported on IRC by thinkfat and nearffxx. Change-Id: I4bda9ba0c582c8e9cacefe708cc4a3d947151f84 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3906 Tested-by: jenkins Reviewed-by: Matthias Welwarsky Reviewed-by: Chengyu Zheng --- src/target/cortex_a.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index d0eac75..8c8a2b7 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -1241,16 +1241,18 @@ static int cortex_a_debug_entry(struct target *target) reg->dirty = reg->valid; } - /* read Saved PSR */ - retval = cortex_a_dap_read_coreregister_u32(target, &spsr, 17); - /* store current spsr */ - if (retval != ERROR_OK) - return retval; + if (arm->spsr) { + /* read Saved PSR */ + retval = cortex_a_dap_read_coreregister_u32(target, &spsr, 17); + /* store current spsr */ + if (retval != ERROR_OK) + return retval; - reg = arm->spsr; - buf_set_u32(reg->value, 0, 32, spsr); - reg->valid = 1; - reg->dirty = 0; + reg = arm->spsr; + buf_set_u32(reg->value, 0, 32, spsr); + reg->valid = 1; + reg->dirty = 0; + } #if 0 /* TODO, Move this */ -- cgit v1.1 From 7582e2fd281153a9a7c9318a3dda010efd2a13ed Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Wed, 30 Nov 2016 12:51:35 +0300 Subject: tcl: target: imx5{1,3}: remove bogus tapenable command This seems to be a leftover from borrowing from omap3* configs. Since SJC is not enabling or disabling the DAP tap, and the tap is always available, the extra tapenable command causes warnings on startup (can't enable what's already enabled). Change-Id: I7514436d565aa5b91876dbdab547956f36dcab77 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3892 Tested-by: jenkins --- tcl/target/imx51.cfg | 3 --- tcl/target/imx53.cfg | 3 --- 2 files changed, 6 deletions(-) diff --git a/tcl/target/imx51.cfg b/tcl/target/imx51.cfg index b143aad..d10cf9f 100644 --- a/tcl/target/imx51.cfg +++ b/tcl/target/imx51.cfg @@ -36,9 +36,6 @@ target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.DAP # some TCK tycles are required to activate the DEBUG power domain jtag configure $_CHIPNAME.SJC -event post-reset "runtest 100" -# have the DAP "always" be active -jtag configure $_CHIPNAME.SJC -event setup "jtag tapenable $_CHIPNAME.DAP" - proc imx51_dbginit {target} { # General Cortex-A8 debug initialisation cortex_a dbginit diff --git a/tcl/target/imx53.cfg b/tcl/target/imx53.cfg index 87a3008..5ad6473 100644 --- a/tcl/target/imx53.cfg +++ b/tcl/target/imx53.cfg @@ -36,9 +36,6 @@ target create $_TARGETNAME cortex_a -chain-position $_CHIPNAME.DAP # some TCK tycles are required to activate the DEBUG power domain jtag configure $_CHIPNAME.SJC -event post-reset "runtest 100" -# have the DAP "always" be active -jtag configure $_CHIPNAME.SJC -event setup "jtag tapenable $_CHIPNAME.DAP" - proc imx53_dbginit {target} { # General Cortex-A8 debug initialisation cortex_a dbginit -- cgit v1.1 From 6f34e64b09b2a61156e837b3077dae619c60f2ea Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Tue, 29 Nov 2016 21:14:15 +0300 Subject: target: armv7a: remove unused level_num field from armv7a_cachesize This was never used and produces warnings on some systems. Change-Id: I48d2c5b79890bb2d70c5fae95278b8eb62743398 Reported-by: Tommy Murphy Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3891 Tested-by: jenkins --- src/target/armv7a.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/target/armv7a.h b/src/target/armv7a.h index 6a62f72..c5c03c8 100644 --- a/src/target/armv7a.h +++ b/src/target/armv7a.h @@ -48,7 +48,6 @@ struct armv7a_l2x_cache { }; struct armv7a_cachesize { - uint32_t level_num; /* cache dimensionning */ uint32_t linelen; uint32_t associativity; -- cgit v1.1 From 46aed121b90701a11e62f2affa194861f6e32b0a Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Wed, 20 Jul 2016 21:24:31 +0300 Subject: doc: add a cross-reference to GDB threading commands Change-Id: If4766ba0053fc94cd47495e442fcf288241af218 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3557 Tested-by: jenkins --- doc/openocd.texi | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 440aa04..93632d4 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -8871,7 +8871,11 @@ end @anchor{gdbrtossupport} OpenOCD includes RTOS support, this will however need enabling as it defaults to disabled. -It can be enabled by passing @option{-rtos} arg to the target @xref{rtostype,,RTOS Type}. +It can be enabled by passing @option{-rtos} arg to the target. @xref{rtostype,,RTOS Type}. + +@xref{Threads, Debugging Programs with Multiple Threads, +Debugging Programs with Multiple Threads, gdb, GDB manual}, for details about relevant +GDB commands. @* An example setup is below: -- cgit v1.1 From d611f5bcb8402637030ef1500321d603aa16c9b5 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 25 Dec 2016 14:15:23 +0300 Subject: doc: fix underfull and overfull boxes This is needed to generate PDF user manual without typesetting artifacts. Change-Id: Ibcbd804dac2b9415459327f53f6fad0dc38fa5c6 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3919 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- doc/openocd.texi | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 93632d4..8c10a26 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4163,9 +4163,9 @@ The value should normally correspond to a static mapping for the @anchor{rtostype} @item @code{-rtos} @var{rtos_type} -- enable rtos support for target, -@var{rtos_type} can be one of @option{auto}|@option{eCos}|@option{ThreadX}| -@option{FreeRTOS}|@option{linux}|@option{ChibiOS}|@option{embKernel}|@option{mqx}| -@option{uCOS-III} +@var{rtos_type} can be one of @option{auto}, @option{eCos}, +@option{ThreadX}, @option{FreeRTOS}, @option{linux}, @option{ChibiOS}, +@option{embKernel}, @option{mqx}, @option{uCOS-III} @xref{gdbrtossupport,,RTOS Support}. @item @code{-defer-examine} -- skip target examination at initial JTAG chain @@ -4752,8 +4752,10 @@ the flash bank defined at address 0x1fc00000. Any cmds executed on the virtual banks are actually performed on the physical banks. @example flash bank $_FLASHNAME pic32mx 0x1fc00000 0 0 0 $_TARGETNAME -flash bank vbank0 virtual 0xbfc00000 0 0 0 $_TARGETNAME $_FLASHNAME -flash bank vbank1 virtual 0x9fc00000 0 0 0 $_TARGETNAME $_FLASHNAME +flash bank vbank0 virtual 0xbfc00000 0 0 0 \ + $_TARGETNAME $_FLASHNAME +flash bank vbank1 virtual 0x9fc00000 0 0 0 \ + $_TARGETNAME $_FLASHNAME @end example @end deffn @@ -4819,8 +4821,8 @@ Since signaling between JTAG and SPI is compatible, all that is required for a proxy bitstream is to connect TDI-MOSI, TDO-MISO, TCK-CLK and activate the flash chip select when the JTAG state machine is in SHIFT-DR. Such a bitstream for several Xilinx FPGAs can be found in -@file{contrib/loaders/flash/fpga/xilinx_bscan_spi.py}. It requires migen -(@url{http://github.com/m-labs/migen}) and a Xilinx toolchain to build. +@file{contrib/loaders/flash/fpga/xilinx_bscan_spi.py}. It requires +@uref{https://github.com/m-labs/migen, migen} and a Xilinx toolchain to build. This flash bank driver requires a target on a JTAG tap and will access that tap directly. Since no support from the target is needed, the target can be a @@ -4843,7 +4845,8 @@ For the bitstreams generated from @file{xilinx_bscan_spi.py} this is the target create $_TARGETNAME testee -chain-position $_CHIPNAME.fpga set _XILINX_USER1 0x02 set _DR_LENGTH 1 -flash bank $_FLASHNAME spi 0x0 0 0 0 $_TARGETNAME $_XILINX_USER1 $_DR_LENGTH +flash bank $_FLASHNAME spi 0x0 0 0 0 \ + $_TARGETNAME $_XILINX_USER1 $_DR_LENGTH @end example @end deffn @@ -4949,7 +4952,8 @@ and the second bank starts after the first. # Flash bank 0 flash bank $_FLASHNAME ambiqmicro 0 0x00040000 0 0 $_TARGETNAME # Flash bank 1 - same size as bank0, starts after bank 0. -flash bank $_FLASHNAME ambiqmicro 0x00040000 0x00040000 0 0 $_TARGETNAME +flash bank $_FLASHNAME ambiqmicro 0x00040000 0x00040000 0 0 \ + $_TARGETNAME @end example Flash is programmed using custom entry points into the bootloader. @@ -5223,8 +5227,10 @@ with @code{x} treated as wildcard and otherwise case (and any trailing characters) ignored. @example -flash bank $@{_FLASHNAME@}0 fm4 0x00000000 0 0 0 $_TARGETNAME S6E2CCAJ0A -flash bank $@{_FLASHNAME@}1 fm4 0x00100000 0 0 0 $_TARGETNAME S6E2CCAJ0A +flash bank $@{_FLASHNAME@}0 fm4 0x00000000 0 0 0 \ + $_TARGETNAME S6E2CCAJ0A +flash bank $@{_FLASHNAME@}1 fm4 0x00100000 0 0 0 \ + $_TARGETNAME S6E2CCAJ0A @end example @emph{The current implementation is incomplete. Protection is not supported, nor is Chip Erase (only Sector Erase is implemented).} -- cgit v1.1 From d6fad0c90d4078076252b3b26271c1bab1691565 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Fri, 4 Nov 2016 13:53:58 +0300 Subject: NEWS: prepare for new release Change-Id: I141ff17f6dcab7e164a19c91b975ddd455d26dbc Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3854 Tested-by: jenkins --- NEWS | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 9df1650..9f6cbf3 100644 --- a/NEWS +++ b/NEWS @@ -2,27 +2,149 @@ This file includes highlights of the changes made in the OpenOCD source archive release. JTAG Layer: + * New driver for J-Link adapters based on libjaylink + (including support for FPGA configuration and EMUCOM) + * FTDI improvements to work at 30MHz clock + * BCM2835 native driver SWD and Raspberry Pi2 support + * BCM2835 is set to 4ma drive, slow slew rate + * ixo-usb-jtag (emulation of an Altera Bus Blaster I on + Cypress FX2 IC) support + * JTAG pass-through mode for CMSIS-DAP (including support for + FPGA configuration) + * OpenJTAG support for Cypress CY7C65215 + * connect_assert_srst support for SWD + * Xilinx Virtex-II Series7 bitstream loading support + * Use JEP106 data to decode IDs + * Deprecated "ft2232" driver removed (use "ftdi" instead) + * GPL-incompatible FTDI D2XX library support dropped (Presto, + OpenJTAG and USB-Blaster I are using libftdi only now) + * ZY1000 support dropped (unmaintained since long) + * oocd_trace support dropped Boundary Scan: Target Layer: + * ARMv7-A, Cortex-M, Cortex-A/R important fixes and + improvements (allowing e.g. simultaneous debugging of A8 and + M3 cores, JTAG WAIT support etc.) + * ARM Cortex-A,R allow interrupt disable during single-step + (maskisr command) + * Semihosting support for ARMv7-A + * ARM Cortex-M7 support + * Intel Quark mcu D2000 support + * Freescale LS102x SAP support + * ThreadX RTOS support on ARM926E-JS + * Cortex-M RTOS stack alignment fixes + * FreeRTOS FPU support + * uC/OS-III RTOS support + * bridging semihosting to GDB's File-I/O support + * -defer-examine option added to target create command + * verify_image_checksum command added Flash Layer: + * Atmel SAM4S, SAM4N, SAM4C support + * Atmel SAMV, SAMS, SAME (Cortex-M7) support + * Atmel AT91SAMD handle reset run/halt in DSU, other fixes + * Atmel AT91SAML21, SAML22, SAMC20/SAMC21, SAMD09 support + * ST STM32F4x support + * ST STM32F74x/76x/77x, STM32L4 support + * ST STM32L0 categories 1, 2 and 5 support + * Kinetis K02, K21, K22, K24, K26, K63, K64, K66 support + * Kinetis KE, KVx, K8x families support + * Kinetis FlexNVM handling + * Kinetis flash protection, security, mass_erase improvements + * Infineon XMC4xxx family support + * Infineon XMC1000 flash driver + * Energy Micro EFM32 Happy Gecko support + * Energy Micro EFM32 debug interface lock support + * Analog Devices ADuCM360 support + * Unified Nuvoton NuMicro flash driver + * NIIET K1921VK01T (Cortex-M4) support + * Nordic Semiconductor nRF51 improvements + * Spansion FM4 flash (including MB9BFx64/x65, S6E2DH) driver + * Ambiq Micro Apollo flash driver + * PIC32MX new device IDs, 17x/27x flash support + * read_bank() and verify_bank() NOR flash internal API to + allow reading (and verifying) non-memory-mapped devices + * JTAGSPI driver to access SPI NOR flashes via a trivial + FPGA proxy + * Milandr read/verify for Info memory support + * Various discrete SPI NOR flashes support + * CFI 16-bit flash reversed endianness support Board, Target, and Interface Configuration Scripts: + * Digilent JTAG-HS2, JTAG-HS3 interfaces configs + * FTDI UM232H module as JTAG interface config + * 100ask's OpenJTAG interface config + * MBFTDI interface config + * XDS100v3 interface config + * Freescale Vybrid VF6xx target config + * EmCraft VF6 SOM and baseboard configs + * Freescale SabreSD board config + * Freescale VF65GS10 tower board config + * Pipistrello Xilinx Spartan6 LX45 FPGA board config + * miniSpartan6+ board config + * Xilinx Kintex7 Development board config + * Parallella-I board config + * Digilent Atlys and Analog Discovery board configs + * Numato Opsis board config + * Xilinx Spartan 6 FPGA "Device DNA" reading support + * Altera 10M50 FPGA (MAX10 family) target config + * Altera EPM240 CPLD (MAXII family) target config + * Marsohod2, Marsohod3 FPGA, Marsohod CPLD boards configs + * Novena's integrated FPGA board config + * XMOS XS1-XAU8A-10's ARM core config + * XMOS xCORE-XA Core Module board config + * Exynos5250 target config + * Arndale board config + * FM4 MB9BFxxx family configs + * Spansion SK-FM4-U120-9B560 board config + * Diolan LPC4357-DB1 board config + * ST STM32F469 discovery board config + * ST STM32F7-DISCO, STM327[4|5]6G-EVAL boards configs + * ST STM32L4 discovery, NUCLEO L476RG, STM32F429I-DISC1 boards + configs + * Atheros AR2313, AR2315 targets config + * Netgear WP102 board config + * La Fonera FON2200 board config + * Linksys WAG200G board config + * LPC-Link2 board config + * NXP LPC4370 target config + * Atmel SAMV, SAMS, SAME target configs + * Atmel SAM E70 Xplained, SAM V71 Xplained Ultra boards + configs + * Nordic nRF52 target config + * Nordic nRF51-DK, nRF52-DK boards configs + * Infineon XMC4700 Relax Kit, XMC4800 Relax EtherCAT Kit, + XMC4300 Relax EtherCAT Kit boards configs + * Renesas S7G2 target config + * Renesas DK-S7G2 board config + * Altera EP3C10 FPGA (Cyclone III family) target config + * TI MSP432P4xx target config + * Cypress PSoC 5LP target config + * Analog Devices ADSP-SC58x target config (Cortex-A5 core only) Server Layer: + * tcl_trace command for async target trace output via Tcl RPC Documentation: Build and Release: + * Various fixes thanks to http://coccinellery.org/ + * libftdi is now autodetected with pkgconfig + * Releases should now support reproducible builds + * Conversion to non-recursive make, requires automake >= 1.14 + * Udev rules modified to add uaccess tag and moved to + 60-openocd.rules + * Support searching for scripts relative to the openocd binary + for all major architectures This release also contains a number of other important functional and cosmetic bugfixes. For more details about what has changed since the last release, see the git repository history: -http://sourceforge.net/p/openocd/code/ci/v0.x.0/log/?path= +http://sourceforge.net/p/openocd/code/ci/v0.10.0-rc1/log/?path= For older NEWS, see the NEWS files associated with each release -- cgit v1.1 From 1edc019f0226fceba7a58b35551adee57a9c6eac Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 25 Dec 2016 17:17:07 +0300 Subject: The openocd-0.10.0-rc1 release candidate Signed-off-by: Paul Fertser --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 687e95c..4dc48c1 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.64) -AC_INIT([openocd], [0.10.0-dev], +AC_INIT([openocd], [0.10.0-rc1], [OpenOCD Mailing List ]) AC_CONFIG_SRCDIR([src/openocd.c]) -- cgit v1.1 From c404ff5d3a2ec568daa106455845dd403b08dab4 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 25 Dec 2016 18:12:22 +0300 Subject: Restore -dev suffix Signed-off-by: Paul Fertser --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 4dc48c1..cd7ee17 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.64) -AC_INIT([openocd], [0.10.0-rc1], +AC_INIT([openocd], [0.10.0-rc1-dev], [OpenOCD Mailing List ]) AC_CONFIG_SRCDIR([src/openocd.c]) -- cgit v1.1 From 33db10a1587da4452f1f3daf3b73e8ab2443969c Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 29 Dec 2016 19:59:07 +0100 Subject: libjaylink: Update to 0.1.0 release Change-Id: I5a905ccda346c09187f7f8e8229ae71d3353128f Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3946 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/jtag/drivers/libjaylink | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/drivers/libjaylink b/src/jtag/drivers/libjaylink index dfa9bc8..699b700 160000 --- a/src/jtag/drivers/libjaylink +++ b/src/jtag/drivers/libjaylink @@ -1 +1 @@ -Subproject commit dfa9bc8e91b0c3a89df3ceaf78c93780fd0a186e +Subproject commit 699b7001d34a79c8e7064503dde1bede786fd7f0 -- cgit v1.1 From 7851207cf0d03428904a80f64db295268919ce86 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 25 Dec 2016 20:24:57 +0300 Subject: jtag: drivers: build usb_blaster only if enabled Fix build failure when libusb dev files are not available and so usb_blaster is disabled. Change-Id: I4cda7df689cdb4b62b733cbbab813241cf561e29 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3920 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- src/jtag/drivers/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index c26d997..e411412 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -78,6 +78,7 @@ DRIVERFILES += %D%/jtag_vpi.c endif if USB_BLASTER_DRIVER %C%_libocdjtagdrivers_la_LIBADD += %D%/usb_blaster/libocdusbblaster.la +include %D%/usb_blaster/Makefile.am endif if AMTJTAGACCEL DRIVERFILES += %D%/amt_jtagaccel.c @@ -171,4 +172,3 @@ DRIVERHEADERS = \ %D%/versaloon/versaloon_include.h \ %D%/versaloon/versaloon_internal.h -include %D%/usb_blaster/Makefile.am -- cgit v1.1 From 7436f7c2c0318fabce777d8886b302e3ca128606 Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Tue, 27 Dec 2016 01:47:23 +0100 Subject: helper,rtos,server: Restore missing warning flags These libraries override the used CFLAGS without adding the defaults. This didn't have any effect until change http://openocd.zylin.com/3870 (ef4c139). Restore by adding AM_CLAGS to the per-target CFLAGS. Interestingly, automake seems to clear the CFLAGS for the target even if the override variable is only mentioned within a non-active conditional branch, such as the IS_MINGW for the affected libraries. Change-Id: I805206865e59e3fa33a7ea3c0d3472e51219351c Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3927 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/helper/Makefile.am | 2 +- src/rtos/Makefile.am | 2 +- src/server/Makefile.am | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/helper/Makefile.am b/src/helper/Makefile.am index 3623894..e0f7f49 100644 --- a/src/helper/Makefile.am +++ b/src/helper/Makefile.am @@ -37,7 +37,7 @@ else %C%_libhelper_la_SOURCES += %D%/ioutil_stubs.c endif -%C%_libhelper_la_CFLAGS = +%C%_libhelper_la_CFLAGS = $(AM_CFLAGS) if IS_MINGW # FD_* macros are sloppy with their signs on MinGW32 platform %C%_libhelper_la_CFLAGS += -Wno-sign-compare diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am index aca266e..c59ee3f 100644 --- a/src/rtos/Makefile.am +++ b/src/rtos/Makefile.am @@ -24,7 +24,7 @@ noinst_LTLIBRARIES += %D%/librtos.la %D%/rtos_mqx_stackings.h \ %D%/rtos_ucos_iii_stackings.h -%C%_librtos_la_CFLAGS = +%C%_librtos_la_CFLAGS = $(AM_CFLAGS) if IS_MINGW # FD_* macros are sloppy with their signs on MinGW32 platform diff --git a/src/server/Makefile.am b/src/server/Makefile.am index 5970d03..804efac 100644 --- a/src/server/Makefile.am +++ b/src/server/Makefile.am @@ -10,7 +10,7 @@ noinst_LTLIBRARIES += %D%/libserver.la %D%/tcl_server.c \ %D%/tcl_server.h -%C%_libserver_la_CFLAGS = +%C%_libserver_la_CFLAGS = $(AM_CFLAGS) if IS_MINGW # FD_* macros are sloppy with their signs on MinGW32 platform %C%_libserver_la_CFLAGS += -Wno-sign-compare -- cgit v1.1 From 52a396656aee2227fad8c9b54576ffec571e7e3e Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Tue, 3 Jan 2017 00:18:34 +0100 Subject: doc: Improve ftdi driver section Fix typo and a sentence that sounds strange since the ft2232 driver was removed. Add documentation for the SWD signal usage. Remove the text mentioning a default VID:PID which doesn't exist. Change-Id: I27eba571f2f7c46bdb6ae623ab285595018e99d9 Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3935 Tested-by: jenkins Reviewed-by: Paul Fertser --- doc/openocd.texi | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 8c10a26..5977c40 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2408,11 +2408,10 @@ This driver is for adapters using the MPSSE (Multi-Protocol Synchronous Serial Engine) mode built into many FTDI chips, such as the FT2232, FT4232 and FT232H. The driver is using libusb-1.0 in asynchronous mode to talk to the FTDI device, -bypassing intermediate libraries like libftdi of D2XX. +bypassing intermediate libraries like libftdi or D2XX. -A major improvement of this driver is that support for new FTDI based adapters -can be added competely through configuration files, without the need to patch -and rebuild OpenOCD. +Support for new FTDI based adapters can be added competely through +configuration files, without the need to patch and rebuild OpenOCD. The driver uses a signal abstraction to enable Tcl configuration files to define outputs for one or several FTDI GPIO. These outputs can then be @@ -2421,6 +2420,12 @@ are reserved for nTRST, nSRST and LED (for blink) so that they, if defined, will be used for their customary purpose. Inputs can be read using the @command{ftdi_get_signal} command. +To support SWD, a signal named SWD_EN must be defined. It is set to 1 when the +SWD protocol is selected. When set, the adapter should route the SWDIO pin to +the data input. An SWDIO_OE signal, if defined, will be set to 1 or 0 as +required by the protocol, to tell the adapter to drive the data output onto +the SWDIO pin or keep the SWDIO pin Hi-Z, respectively. + Depending on the type of buffer attached to the FTDI GPIO, the outputs have to be controlled differently. In order to support tristateable signals such as nSRST, both a data GPIO and an output-enable GPIO can be specified for each @@ -2439,9 +2444,8 @@ These interfaces have several commands, used to configure the driver before initializing the JTAG scan chain: @deffn {Config Command} {ftdi_vid_pid} [vid pid]+ -The vendor ID and product ID of the adapter. If not specified, the FTDI -default values are used. -Currently, up to eight [@var{vid}, @var{pid}] pairs may be given, e.g. +The vendor ID and product ID of the adapter. Up to eight +[@var{vid}, @var{pid}] pairs may be given, e.g. @example ftdi_vid_pid 0x0403 0xcff8 0x15ba 0x0003 @end example -- cgit v1.1 From 2934ac454e32b21b1bd624189745d9f21ee79b46 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 12 Jan 2017 17:06:12 +0100 Subject: adi_v5_jtag: make sure SSTICKYERR is cleared after a POR Don't terminate the transaction end-check early if debug power-loss was detected, without clearing SSTICKYERR. Change-Id: I83b6a4a20523eea42e48a15297f972a730aa21a8 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3947 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/adi_v5_jtag.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/target/adi_v5_jtag.c b/src/target/adi_v5_jtag.c index 2717c9e..c7dc4f7 100644 --- a/src/target/adi_v5_jtag.c +++ b/src/target/adi_v5_jtag.c @@ -574,8 +574,6 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap) if ((ctrlstat & (CDBGPWRUPREQ | CDBGPWRUPACK | CSYSPWRUPREQ | CSYSPWRUPACK)) != (CDBGPWRUPREQ | CDBGPWRUPACK | CSYSPWRUPREQ | CSYSPWRUPACK)) { LOG_ERROR("Debug regions are unpowered, an unexpected reset might have happened"); - retval = ERROR_JTAG_DEVICE_ERROR; - goto done; } if (ctrlstat & SSTICKYERR) @@ -590,10 +588,7 @@ static int jtagdp_transaction_endcheck(struct adiv5_dap *dap) if (retval != ERROR_OK) goto done; - if (ctrlstat & SSTICKYERR) { - retval = ERROR_JTAG_DEVICE_ERROR; - goto done; - } + retval = ERROR_JTAG_DEVICE_ERROR; } done: -- cgit v1.1 From 390c9aca1f9400d956020b3d1657237bcc1ffe68 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Sat, 7 Jan 2017 17:04:30 +0100 Subject: tcl at91samdXX.cfg: partially revert change 3722 Commit 25d7ba19c9e70cf5b912f660cf6aaa93d9ca120f introduced a problem with 'reset halt' due to setting srst_pulls_trst: Error: cortex_m.c:595 cortex_m_halt(): can't request a halt while in reset if nSRST pulls nTRST Sorry, I don't know why I overlooked it when I tested #3722. Change-Id: I41e9473dd91a86d93cf3e78b1fbbdfe1dd188d83 Reported-by: Ladislav Laska Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3942 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- tcl/target/at91samdXX.cfg | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tcl/target/at91samdXX.cfg b/tcl/target/at91samdXX.cfg index 9a3c292..93a95c8 100644 --- a/tcl/target/at91samdXX.cfg +++ b/tcl/target/at91samdXX.cfg @@ -50,7 +50,8 @@ $_TARGETNAME configure -event reset-deassert-post { } # SRST (wired to RESET_N) resets debug circuitry -reset_config srst_gates_jtag srst_pulls_trst +# srst_pulls_trst is not configured here to avoid an error raised in reset halt +reset_config srst_gates_jtag # Do not use a reset button with other SWD adapter than Atmel's EDBG. # DSU usually locks MCU in reset state until you issue a reset command -- cgit v1.1 From 93bc4ec40ffb9c30f170af3f1e3551c4b198507f Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Thu, 22 Dec 2016 21:47:20 +0100 Subject: flash/nor: fix doc/help and range test for flash protect Commit 77a1c01ccbb1150ffe749a7373cf6c4dc15ecad0 introduced infrastructure for utilizing protection blocks of different size than erase sector. Parts of doc/help kept reading 'sector' instead of 'protection block'. flash_driver_protect() parameter range testing did not switched to bank->num_prot_blocks. This change fixes it. Change-Id: Iec301761190a1a1bcc4cb005a519b9e5e4fede51 Reported-by: Mark Odell Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3917 Tested-by: jenkins Reviewed-by: Mark Odell Reviewed-by: Paul Fertser --- doc/openocd.texi | 9 ++++++--- src/flash/nor/core.c | 15 +++++++++++---- src/flash/nor/tcl.c | 7 ++++--- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 5977c40..45b341c 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4714,12 +4714,15 @@ and possibly stale information. @anchor{flashprotect} @deffn Command {flash protect} num first last (@option{on}|@option{off}) -Enable (@option{on}) or disable (@option{off}) protection of flash sectors -in flash bank @var{num}, starting at sector @var{first} +Enable (@option{on}) or disable (@option{off}) protection of flash blocks +in flash bank @var{num}, starting at protection block @var{first} and continuing up to and including @var{last}. -Providing a @var{last} sector of @option{last} +Providing a @var{last} block of @option{last} specifies "to the end of the flash bank". The @var{num} parameter is a value shown by @command{flash banks}. +The protection block is usually identical to a flash sector. +Some devices may utilize a protection block distinct from flash sector. +See @command{flash info} for a list of protection blocks. @end deffn @deffn Command {flash padded_value} num value diff --git a/src/flash/nor/core.c b/src/flash/nor/core.c index 8f6306f..ab69a32 100644 --- a/src/flash/nor/core.c +++ b/src/flash/nor/core.c @@ -50,10 +50,17 @@ int flash_driver_erase(struct flash_bank *bank, int first, int last) int flash_driver_protect(struct flash_bank *bank, int set, int first, int last) { int retval; + int num_blocks; + + if (bank->num_prot_blocks) + num_blocks = bank->num_prot_blocks; + else + num_blocks = bank->num_sectors; + /* callers may not supply illegal parameters ... */ - if (first < 0 || first > last || last >= bank->num_sectors) { - LOG_ERROR("illegal sector range"); + if (first < 0 || first > last || last >= num_blocks) { + LOG_ERROR("illegal protection block range"); return ERROR_FAIL; } @@ -69,11 +76,11 @@ int flash_driver_protect(struct flash_bank *bank, int set, int first, int last) * the target could have reset, power cycled, been hot plugged, * the application could have run, etc. * - * Drivers only receive valid sector range. + * Drivers only receive valid protection block range. */ retval = bank->driver->protect(bank, set, first, last); if (retval != ERROR_OK) - LOG_ERROR("failed setting protection for areas %d to %d", first, last); + LOG_ERROR("failed setting protection for blocks %d to %d", first, last); return retval; } diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 6936822..0b72a12 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -936,10 +936,11 @@ static const struct command_registration flash_exec_command_handlers[] = { .name = "protect", .handler = handle_flash_protect_command, .mode = COMMAND_EXEC, - .usage = "bank_id first_sector [last_sector|'last'] " + .usage = "bank_id first_block [last_block|'last'] " "('on'|'off')", - .help = "Turn protection on or off for a range of sectors " - "in a given flash bank.", + .help = "Turn protection on or off for a range of protection " + "blocks or sectors in a given flash bank. " + "See 'flash info' output for a list of blocks.", }, { .name = "padded_value", -- cgit v1.1 From af4a2f35184e856c08d4727393ecf9b9f09ae65b Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sat, 7 Jan 2017 21:51:32 +0300 Subject: jtag: core: report TRST and SRST as asserted only when they really are When SRST is never enabled, the global jtag_srst variable is left at its initial state, that is, -1, and it does _not_ mean SRST is currently asserted. Same about TRST. Fixes "reset halt" in cases when srst_pulls_trst but srst usage is not enabled. Change-Id: I8d2e9120479de4cfbf5561033926c9ef945eecc9 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3943 Tested-by: jenkins Reviewed-by: Andreas Fritiofson Reviewed-by: Tomas Vanek --- src/jtag/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jtag/core.c b/src/jtag/core.c index 77269e4..8c79eb2 100644 --- a/src/jtag/core.c +++ b/src/jtag/core.c @@ -1717,11 +1717,11 @@ void jtag_set_reset_config(enum reset_types type) int jtag_get_trst(void) { - return jtag_trst; + return jtag_trst == 1; } int jtag_get_srst(void) { - return jtag_srst; + return jtag_srst == 1; } void jtag_set_nsrst_delay(unsigned delay) -- cgit v1.1 From f6279c00c35c1efddcd69ba25a1928ef56c4887a Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 15 Jan 2017 14:22:50 +0300 Subject: NEWS: mention SWO capture facility of the new J-Link driver Change-Id: I4fc150584f3f0c5df5c39ae512125b42893331f0 Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3948 Tested-by: jenkins --- NEWS | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 9f6cbf3..a7f68c8 100644 --- a/NEWS +++ b/NEWS @@ -3,7 +3,7 @@ source archive release. JTAG Layer: * New driver for J-Link adapters based on libjaylink - (including support for FPGA configuration and EMUCOM) + (including support for FPGA configuration, SWO and EMUCOM) * FTDI improvements to work at 30MHz clock * BCM2835 native driver SWD and Raspberry Pi2 support * BCM2835 is set to 4ma drive, slow slew rate @@ -144,7 +144,7 @@ This release also contains a number of other important functional and cosmetic bugfixes. For more details about what has changed since the last release, see the git repository history: -http://sourceforge.net/p/openocd/code/ci/v0.10.0-rc1/log/?path= +http://sourceforge.net/p/openocd/code/ci/v0.10.0-rc2/log/?path= For older NEWS, see the NEWS files associated with each release -- cgit v1.1 From 9e741717757903656f3b8038f40335e8261f4487 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 15 Jan 2017 18:26:52 +0300 Subject: The openocd-0.10.0-rc2 release candidate Signed-off-by: Paul Fertser --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index cd7ee17..1a4c43c 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.64) -AC_INIT([openocd], [0.10.0-rc1-dev], +AC_INIT([openocd], [0.10.0-rc2], [OpenOCD Mailing List ]) AC_CONFIG_SRCDIR([src/openocd.c]) -- cgit v1.1 From 1c4aa20b21015340bd6dcfb03939c88b58506e5e Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 15 Jan 2017 19:11:27 +0300 Subject: Restore -dev suffix Signed-off-by: Paul Fertser --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 1a4c43c..ec47b43 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.64) -AC_INIT([openocd], [0.10.0-rc2], +AC_INIT([openocd], [0.10.0-rc2-dev], [OpenOCD Mailing List ]) AC_CONFIG_SRCDIR([src/openocd.c]) -- cgit v1.1 From 59820c18d0d8be93344b00a10a2a4e56601fb094 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 19 Jan 2017 16:57:04 +0100 Subject: arm_dpm: avoid duplicating the register cache This bug was already attempted to fix in an earlier patch but merging the "defer-examine" feature caused a regression, which this patch tries to fix again. Change-Id: Ie1ad1516f0d7f130d44e003d6c29dcc1a02a82ca Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3951 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/arm_dpm.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index 8ad6575..62c6175 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -972,11 +972,14 @@ int arm_dpm_setup(struct arm_dpm *dpm) arm->read_core_reg = arm_dpm_read_core_reg; arm->write_core_reg = arm_dpm_write_core_reg; - cache = arm_build_reg_cache(target, arm); - if (!cache) - return ERROR_FAIL; + /* avoid duplicating the register cache */ + if (arm->core_cache == NULL) { + cache = arm_build_reg_cache(target, arm); + if (!cache) + return ERROR_FAIL; - *register_get_last_cache_p(&target->reg_cache) = cache; + *register_get_last_cache_p(&target->reg_cache) = cache; + } /* coprocessor access setup */ arm->mrc = dpm_mrc; -- cgit v1.1 From 0e7bcf850bd2fe2f09f0ee527e8e51bc5b8f2882 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 22 Jan 2017 16:01:15 +0300 Subject: NEWS: last pre-release changes Change-Id: I93203717f9096880298c10efebf05d59f888f34b Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/3954 Tested-by: jenkins --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index a7f68c8..e3b1e25 100644 --- a/NEWS +++ b/NEWS @@ -144,7 +144,7 @@ This release also contains a number of other important functional and cosmetic bugfixes. For more details about what has changed since the last release, see the git repository history: -http://sourceforge.net/p/openocd/code/ci/v0.10.0-rc2/log/?path= +http://sourceforge.net/p/openocd/code/ci/v0.10.0/log/?path= For older NEWS, see the NEWS files associated with each release -- cgit v1.1 From 646566e006acd58fb9ac405511d3ecca79f26d55 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 22 Jan 2017 23:31:28 +0300 Subject: The openocd-0.10.0 release Signed-off-by: Paul Fertser --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index ec47b43..6949402 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.64) -AC_INIT([openocd], [0.10.0-rc2-dev], +AC_INIT([openocd], [0.10.0], [OpenOCD Mailing List ]) AC_CONFIG_SRCDIR([src/openocd.c]) -- cgit v1.1 From 0ecee8326608a070b476a757cf517d0f50b5ca07 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Mon, 23 Jan 2017 00:46:51 +0300 Subject: Restore normal development cycle Signed-off-by: Paul Fertser --- NEWS | 124 +---------------------------------------------- NEWS-0.10.0 | 155 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 2 +- 3 files changed, 157 insertions(+), 124 deletions(-) create mode 100644 NEWS-0.10.0 diff --git a/NEWS b/NEWS index e3b1e25..9df1650 100644 --- a/NEWS +++ b/NEWS @@ -2,149 +2,27 @@ This file includes highlights of the changes made in the OpenOCD source archive release. JTAG Layer: - * New driver for J-Link adapters based on libjaylink - (including support for FPGA configuration, SWO and EMUCOM) - * FTDI improvements to work at 30MHz clock - * BCM2835 native driver SWD and Raspberry Pi2 support - * BCM2835 is set to 4ma drive, slow slew rate - * ixo-usb-jtag (emulation of an Altera Bus Blaster I on - Cypress FX2 IC) support - * JTAG pass-through mode for CMSIS-DAP (including support for - FPGA configuration) - * OpenJTAG support for Cypress CY7C65215 - * connect_assert_srst support for SWD - * Xilinx Virtex-II Series7 bitstream loading support - * Use JEP106 data to decode IDs - * Deprecated "ft2232" driver removed (use "ftdi" instead) - * GPL-incompatible FTDI D2XX library support dropped (Presto, - OpenJTAG and USB-Blaster I are using libftdi only now) - * ZY1000 support dropped (unmaintained since long) - * oocd_trace support dropped Boundary Scan: Target Layer: - * ARMv7-A, Cortex-M, Cortex-A/R important fixes and - improvements (allowing e.g. simultaneous debugging of A8 and - M3 cores, JTAG WAIT support etc.) - * ARM Cortex-A,R allow interrupt disable during single-step - (maskisr command) - * Semihosting support for ARMv7-A - * ARM Cortex-M7 support - * Intel Quark mcu D2000 support - * Freescale LS102x SAP support - * ThreadX RTOS support on ARM926E-JS - * Cortex-M RTOS stack alignment fixes - * FreeRTOS FPU support - * uC/OS-III RTOS support - * bridging semihosting to GDB's File-I/O support - * -defer-examine option added to target create command - * verify_image_checksum command added Flash Layer: - * Atmel SAM4S, SAM4N, SAM4C support - * Atmel SAMV, SAMS, SAME (Cortex-M7) support - * Atmel AT91SAMD handle reset run/halt in DSU, other fixes - * Atmel AT91SAML21, SAML22, SAMC20/SAMC21, SAMD09 support - * ST STM32F4x support - * ST STM32F74x/76x/77x, STM32L4 support - * ST STM32L0 categories 1, 2 and 5 support - * Kinetis K02, K21, K22, K24, K26, K63, K64, K66 support - * Kinetis KE, KVx, K8x families support - * Kinetis FlexNVM handling - * Kinetis flash protection, security, mass_erase improvements - * Infineon XMC4xxx family support - * Infineon XMC1000 flash driver - * Energy Micro EFM32 Happy Gecko support - * Energy Micro EFM32 debug interface lock support - * Analog Devices ADuCM360 support - * Unified Nuvoton NuMicro flash driver - * NIIET K1921VK01T (Cortex-M4) support - * Nordic Semiconductor nRF51 improvements - * Spansion FM4 flash (including MB9BFx64/x65, S6E2DH) driver - * Ambiq Micro Apollo flash driver - * PIC32MX new device IDs, 17x/27x flash support - * read_bank() and verify_bank() NOR flash internal API to - allow reading (and verifying) non-memory-mapped devices - * JTAGSPI driver to access SPI NOR flashes via a trivial - FPGA proxy - * Milandr read/verify for Info memory support - * Various discrete SPI NOR flashes support - * CFI 16-bit flash reversed endianness support Board, Target, and Interface Configuration Scripts: - * Digilent JTAG-HS2, JTAG-HS3 interfaces configs - * FTDI UM232H module as JTAG interface config - * 100ask's OpenJTAG interface config - * MBFTDI interface config - * XDS100v3 interface config - * Freescale Vybrid VF6xx target config - * EmCraft VF6 SOM and baseboard configs - * Freescale SabreSD board config - * Freescale VF65GS10 tower board config - * Pipistrello Xilinx Spartan6 LX45 FPGA board config - * miniSpartan6+ board config - * Xilinx Kintex7 Development board config - * Parallella-I board config - * Digilent Atlys and Analog Discovery board configs - * Numato Opsis board config - * Xilinx Spartan 6 FPGA "Device DNA" reading support - * Altera 10M50 FPGA (MAX10 family) target config - * Altera EPM240 CPLD (MAXII family) target config - * Marsohod2, Marsohod3 FPGA, Marsohod CPLD boards configs - * Novena's integrated FPGA board config - * XMOS XS1-XAU8A-10's ARM core config - * XMOS xCORE-XA Core Module board config - * Exynos5250 target config - * Arndale board config - * FM4 MB9BFxxx family configs - * Spansion SK-FM4-U120-9B560 board config - * Diolan LPC4357-DB1 board config - * ST STM32F469 discovery board config - * ST STM32F7-DISCO, STM327[4|5]6G-EVAL boards configs - * ST STM32L4 discovery, NUCLEO L476RG, STM32F429I-DISC1 boards - configs - * Atheros AR2313, AR2315 targets config - * Netgear WP102 board config - * La Fonera FON2200 board config - * Linksys WAG200G board config - * LPC-Link2 board config - * NXP LPC4370 target config - * Atmel SAMV, SAMS, SAME target configs - * Atmel SAM E70 Xplained, SAM V71 Xplained Ultra boards - configs - * Nordic nRF52 target config - * Nordic nRF51-DK, nRF52-DK boards configs - * Infineon XMC4700 Relax Kit, XMC4800 Relax EtherCAT Kit, - XMC4300 Relax EtherCAT Kit boards configs - * Renesas S7G2 target config - * Renesas DK-S7G2 board config - * Altera EP3C10 FPGA (Cyclone III family) target config - * TI MSP432P4xx target config - * Cypress PSoC 5LP target config - * Analog Devices ADSP-SC58x target config (Cortex-A5 core only) Server Layer: - * tcl_trace command for async target trace output via Tcl RPC Documentation: Build and Release: - * Various fixes thanks to http://coccinellery.org/ - * libftdi is now autodetected with pkgconfig - * Releases should now support reproducible builds - * Conversion to non-recursive make, requires automake >= 1.14 - * Udev rules modified to add uaccess tag and moved to - 60-openocd.rules - * Support searching for scripts relative to the openocd binary - for all major architectures This release also contains a number of other important functional and cosmetic bugfixes. For more details about what has changed since the last release, see the git repository history: -http://sourceforge.net/p/openocd/code/ci/v0.10.0/log/?path= +http://sourceforge.net/p/openocd/code/ci/v0.x.0/log/?path= For older NEWS, see the NEWS files associated with each release diff --git a/NEWS-0.10.0 b/NEWS-0.10.0 new file mode 100644 index 0000000..e3b1e25 --- /dev/null +++ b/NEWS-0.10.0 @@ -0,0 +1,155 @@ +This file includes highlights of the changes made in the OpenOCD +source archive release. + +JTAG Layer: + * New driver for J-Link adapters based on libjaylink + (including support for FPGA configuration, SWO and EMUCOM) + * FTDI improvements to work at 30MHz clock + * BCM2835 native driver SWD and Raspberry Pi2 support + * BCM2835 is set to 4ma drive, slow slew rate + * ixo-usb-jtag (emulation of an Altera Bus Blaster I on + Cypress FX2 IC) support + * JTAG pass-through mode for CMSIS-DAP (including support for + FPGA configuration) + * OpenJTAG support for Cypress CY7C65215 + * connect_assert_srst support for SWD + * Xilinx Virtex-II Series7 bitstream loading support + * Use JEP106 data to decode IDs + * Deprecated "ft2232" driver removed (use "ftdi" instead) + * GPL-incompatible FTDI D2XX library support dropped (Presto, + OpenJTAG and USB-Blaster I are using libftdi only now) + * ZY1000 support dropped (unmaintained since long) + * oocd_trace support dropped + +Boundary Scan: + +Target Layer: + * ARMv7-A, Cortex-M, Cortex-A/R important fixes and + improvements (allowing e.g. simultaneous debugging of A8 and + M3 cores, JTAG WAIT support etc.) + * ARM Cortex-A,R allow interrupt disable during single-step + (maskisr command) + * Semihosting support for ARMv7-A + * ARM Cortex-M7 support + * Intel Quark mcu D2000 support + * Freescale LS102x SAP support + * ThreadX RTOS support on ARM926E-JS + * Cortex-M RTOS stack alignment fixes + * FreeRTOS FPU support + * uC/OS-III RTOS support + * bridging semihosting to GDB's File-I/O support + * -defer-examine option added to target create command + * verify_image_checksum command added + +Flash Layer: + * Atmel SAM4S, SAM4N, SAM4C support + * Atmel SAMV, SAMS, SAME (Cortex-M7) support + * Atmel AT91SAMD handle reset run/halt in DSU, other fixes + * Atmel AT91SAML21, SAML22, SAMC20/SAMC21, SAMD09 support + * ST STM32F4x support + * ST STM32F74x/76x/77x, STM32L4 support + * ST STM32L0 categories 1, 2 and 5 support + * Kinetis K02, K21, K22, K24, K26, K63, K64, K66 support + * Kinetis KE, KVx, K8x families support + * Kinetis FlexNVM handling + * Kinetis flash protection, security, mass_erase improvements + * Infineon XMC4xxx family support + * Infineon XMC1000 flash driver + * Energy Micro EFM32 Happy Gecko support + * Energy Micro EFM32 debug interface lock support + * Analog Devices ADuCM360 support + * Unified Nuvoton NuMicro flash driver + * NIIET K1921VK01T (Cortex-M4) support + * Nordic Semiconductor nRF51 improvements + * Spansion FM4 flash (including MB9BFx64/x65, S6E2DH) driver + * Ambiq Micro Apollo flash driver + * PIC32MX new device IDs, 17x/27x flash support + * read_bank() and verify_bank() NOR flash internal API to + allow reading (and verifying) non-memory-mapped devices + * JTAGSPI driver to access SPI NOR flashes via a trivial + FPGA proxy + * Milandr read/verify for Info memory support + * Various discrete SPI NOR flashes support + * CFI 16-bit flash reversed endianness support + +Board, Target, and Interface Configuration Scripts: + * Digilent JTAG-HS2, JTAG-HS3 interfaces configs + * FTDI UM232H module as JTAG interface config + * 100ask's OpenJTAG interface config + * MBFTDI interface config + * XDS100v3 interface config + * Freescale Vybrid VF6xx target config + * EmCraft VF6 SOM and baseboard configs + * Freescale SabreSD board config + * Freescale VF65GS10 tower board config + * Pipistrello Xilinx Spartan6 LX45 FPGA board config + * miniSpartan6+ board config + * Xilinx Kintex7 Development board config + * Parallella-I board config + * Digilent Atlys and Analog Discovery board configs + * Numato Opsis board config + * Xilinx Spartan 6 FPGA "Device DNA" reading support + * Altera 10M50 FPGA (MAX10 family) target config + * Altera EPM240 CPLD (MAXII family) target config + * Marsohod2, Marsohod3 FPGA, Marsohod CPLD boards configs + * Novena's integrated FPGA board config + * XMOS XS1-XAU8A-10's ARM core config + * XMOS xCORE-XA Core Module board config + * Exynos5250 target config + * Arndale board config + * FM4 MB9BFxxx family configs + * Spansion SK-FM4-U120-9B560 board config + * Diolan LPC4357-DB1 board config + * ST STM32F469 discovery board config + * ST STM32F7-DISCO, STM327[4|5]6G-EVAL boards configs + * ST STM32L4 discovery, NUCLEO L476RG, STM32F429I-DISC1 boards + configs + * Atheros AR2313, AR2315 targets config + * Netgear WP102 board config + * La Fonera FON2200 board config + * Linksys WAG200G board config + * LPC-Link2 board config + * NXP LPC4370 target config + * Atmel SAMV, SAMS, SAME target configs + * Atmel SAM E70 Xplained, SAM V71 Xplained Ultra boards + configs + * Nordic nRF52 target config + * Nordic nRF51-DK, nRF52-DK boards configs + * Infineon XMC4700 Relax Kit, XMC4800 Relax EtherCAT Kit, + XMC4300 Relax EtherCAT Kit boards configs + * Renesas S7G2 target config + * Renesas DK-S7G2 board config + * Altera EP3C10 FPGA (Cyclone III family) target config + * TI MSP432P4xx target config + * Cypress PSoC 5LP target config + * Analog Devices ADSP-SC58x target config (Cortex-A5 core only) + +Server Layer: + * tcl_trace command for async target trace output via Tcl RPC + +Documentation: + +Build and Release: + * Various fixes thanks to http://coccinellery.org/ + * libftdi is now autodetected with pkgconfig + * Releases should now support reproducible builds + * Conversion to non-recursive make, requires automake >= 1.14 + * Udev rules modified to add uaccess tag and moved to + 60-openocd.rules + * Support searching for scripts relative to the openocd binary + for all major architectures + + +This release also contains a number of other important functional and +cosmetic bugfixes. For more details about what has changed since the +last release, see the git repository history: + +http://sourceforge.net/p/openocd/code/ci/v0.10.0/log/?path= + + +For older NEWS, see the NEWS files associated with each release +(i.e. NEWS-). + +For more information about contributing test reports, bug fixes, or new +features and device support, please read the new Developer Manual (or +the BUGS and PATCHES.txt files in the source archive). diff --git a/configure.ac b/configure.ac index 6949402..2543eca 100644 --- a/configure.ac +++ b/configure.ac @@ -1,5 +1,5 @@ AC_PREREQ(2.64) -AC_INIT([openocd], [0.10.0], +AC_INIT([openocd], [0.10.0+dev], [OpenOCD Mailing List ]) AC_CONFIG_SRCDIR([src/openocd.c]) -- cgit v1.1 From 47b8cf84202bf792cf66fbfa01169e9592236b8a Mon Sep 17 00:00:00 2001 From: Dongxue Zhang Date: Mon, 23 Sep 2013 16:27:03 +0800 Subject: target: Add 64-bit target address support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define a target_addr_t type to support 32-bit and 64-bit addresses at the same time. Also define matching TARGET_PRI*ADDR format macros as well as a convenient TARGET_ADDR_FMT. In targets that are 32-bit (avr32, nds32, arm7/9/11, fm4, xmc1000) be least invasive by leaving the formatting unchanged apart from the type; for generic code adopt TARGET_ADDR_FMT as unified address format. Don't silently change gdb formatting here, leave that to later. Add COMMAND_PARSE_ADDRESS() macro to abstract the address type. Implement it using its own parse_target_addr() function, in the hopes of catching pointer type mismatches better. Add '--disable-target64' configure option to revert to previous 32-bit target address behavior. Change-Id: I2e91d205862ceb14f94b3e72a7e99ee0373a85d5 Signed-off-by: Dongxue Zhang Signed-off-by: David Ung [AF: Default to enabling (Paul Fertser), rename macros, simplify] Signed-off-by: Andreas Färber Signed-off-by: Matthias Welwarsky --- configure.ac | 12 ++ src/flash/nor/cfi.c | 2 +- src/flash/nor/fm4.c | 2 +- src/flash/nor/lpc2000.c | 2 +- src/flash/nor/lpcspifi.c | 2 +- src/flash/nor/xmc1xxx.c | 2 +- src/helper/command.c | 2 + src/helper/command.h | 6 + src/helper/types.h | 30 +++- src/jtag/aice/aice_pipe.c | 4 +- src/jtag/aice/aice_port.h | 2 +- src/jtag/aice/aice_usb.c | 6 +- src/rtos/linux.c | 4 +- src/server/gdb_server.c | 8 +- src/target/algorithm.h | 2 +- src/target/arm.h | 6 +- src/target/arm11.c | 22 +-- src/target/arm720t.c | 8 +- src/target/arm7_9_common.c | 37 ++--- src/target/arm7_9_common.h | 16 +-- src/target/arm920t.c | 10 +- src/target/arm920t.h | 4 +- src/target/arm926ejs.c | 10 +- src/target/arm926ejs.h | 2 +- src/target/arm946e.c | 4 +- src/target/armv4_5.c | 16 +-- src/target/armv4_5_mmu.h | 5 +- src/target/armv7a.h | 2 +- src/target/armv7a_cache_l2x.c | 46 +++---- src/target/armv7a_cache_l2x.h | 2 +- src/target/armv7m.c | 12 +- src/target/armv7m.h | 10 +- src/target/avr32_ap7k.c | 14 +- src/target/avrt.c | 8 +- src/target/breakpoints.c | 43 +++--- src/target/breakpoints.h | 19 +-- src/target/cortex_a.c | 67 ++++----- src/target/cortex_m.c | 14 +- src/target/dsp563xx.c | 22 +-- src/target/dsp5680xx.c | 14 +- src/target/feroceon.c | 4 +- src/target/hla_target.c | 20 +-- src/target/image.h | 2 +- src/target/lakemont.c | 4 +- src/target/lakemont.h | 4 +- src/target/ls1_sap.c | 12 +- src/target/mips32.c | 12 +- src/target/mips32.h | 6 +- src/target/mips32_pracc.c | 2 +- src/target/mips_m4k.c | 30 ++-- src/target/nds32.c | 20 +-- src/target/nds32.h | 14 +- src/target/nds32_aice.c | 4 +- src/target/nds32_aice.h | 4 +- src/target/nds32_tlb.c | 8 +- src/target/nds32_tlb.h | 8 +- src/target/nds32_v2.c | 26 ++-- src/target/nds32_v3.c | 8 +- src/target/nds32_v3_common.c | 22 +-- src/target/nds32_v3_common.h | 14 +- src/target/nds32_v3m.c | 8 +- src/target/openrisc/or1k.c | 33 +++-- src/target/target.c | 309 ++++++++++++++++++++++++++++-------------- src/target/target.h | 47 ++++--- src/target/target_type.h | 33 +++-- src/target/x86_32_common.c | 85 ++++++------ src/target/x86_32_common.h | 10 +- src/target/xscale.c | 26 ++-- 68 files changed, 728 insertions(+), 546 deletions(-) diff --git a/configure.ac b/configure.ac index 2543eca..6e60733 100644 --- a/configure.ac +++ b/configure.ac @@ -339,6 +339,10 @@ AC_ARG_ENABLE([internal-libjaylink], [Disable building internal libjaylink]), [use_internal_libjaylink=$enableval], [use_internal_libjaylink=yes]) +AC_ARG_ENABLE([target64], + AS_HELP_STRING([--disable-target64], [Disable 64-bit target address]), + [build_target64=$enableval], [build_target64=yes]) + build_minidriver=no AC_MSG_CHECKING([whether to enable ZY1000 minidriver]) AS_IF([test "x$build_zy1000" = "xyes"], [ @@ -572,6 +576,13 @@ AS_IF([test "x$build_sysfsgpio" = "xyes"], [ AC_DEFINE([BUILD_SYSFSGPIO], [0], [0 if you don't want SysfsGPIO driver.]) ]) +AS_IF([test "x$build_target64" = "xyes"], [ + AC_DEFINE([BUILD_TARGET64], [1], [1 if you want 64-bit addresses.]) +], [ + AC_DEFINE([BUILD_TARGET64], [0], [0 if you don't want 64-bit addresses.]) +]) + + PKG_CHECK_MODULES([LIBUSB1], [libusb-1.0], [ use_libusb1=yes AC_DEFINE([HAVE_LIBUSB1], [1], [Define if you have libusb-1.x]) @@ -689,6 +700,7 @@ AM_CONDITIONAL([BITQ], [test "x$build_bitq" = "xyes"]) AM_CONDITIONAL([USE_LIBFTDI], [test "x$use_libftdi" = "xyes"]) AM_CONDITIONAL([USE_HIDAPI], [test "x$use_hidapi" = "xyes"]) AM_CONDITIONAL([USE_LIBJAYLINK], [test "x$use_libjaylink" = "xyes"]) +AM_CONDITIONAL([TARGET64], [test "x$build_target64" = "xyes"]) AM_CONDITIONAL([MINIDRIVER], [test "x$build_minidriver" = "xyes"]) AM_CONDITIONAL([MINIDRIVER_DUMMY], [test "x$build_minidriver_dummy" = "xyes"]) diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index f7d8a90..dca33f6 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -1312,7 +1312,7 @@ static int cfi_intel_write_block(struct flash_bank *bank, const uint8_t *buffer, busy_pattern_val = cfi_command_val(bank, 0x80); error_pattern_val = cfi_command_val(bank, 0x7e); - LOG_DEBUG("Using target buffer at 0x%08" PRIx32 " and of size 0x%04" PRIx32, + LOG_DEBUG("Using target buffer at " TARGET_ADDR_FMT " and of size 0x%04" PRIx32, source->address, buffer_size); /* Programming main loop */ diff --git a/src/flash/nor/fm4.c b/src/flash/nor/fm4.c index c348c1d..c8fe8b6 100644 --- a/src/flash/nor/fm4.c +++ b/src/flash/nor/fm4.c @@ -272,7 +272,7 @@ static int fm4_flash_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t halfwords = MIN(halfword_count, data_workarea->size / 2); uint32_t addr = bank->base + offset; - LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" PRIx32, + LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" TARGET_PRIxADDR, MIN(halfwords * 2, byte_count), data_workarea->address); retval = target_write_buffer(target, data_workarea->address, diff --git a/src/flash/nor/lpc2000.c b/src/flash/nor/lpc2000.c index 190684a..9da5da2 100644 --- a/src/flash/nor/lpc2000.c +++ b/src/flash/nor/lpc2000.c @@ -688,7 +688,7 @@ static int lpc2000_iap_working_area_init(struct flash_bank *bank, struct working int retval = target_write_memory(target, (*iap_working_area)->address, 4, 2, jump_gate); if (retval != ERROR_OK) { - LOG_ERROR("Write memory at address 0x%8.8" PRIx32 " failed (check work_area definition)", + LOG_ERROR("Write memory at address 0x%8.8" TARGET_PRIxADDR " failed (check work_area definition)", (*iap_working_area)->address); target_free_working_area(target, *iap_working_area); } diff --git a/src/flash/nor/lpcspifi.c b/src/flash/nor/lpcspifi.c index 4eb6cc3..943c151 100644 --- a/src/flash/nor/lpcspifi.c +++ b/src/flash/nor/lpcspifi.c @@ -186,7 +186,7 @@ static int lpcspifi_set_hw_mode(struct flash_bank *bank) return retval; } - LOG_DEBUG("Writing algorithm to working area at 0x%08" PRIx32, + LOG_DEBUG("Writing algorithm to working area at 0x%08" TARGET_PRIxADDR, spifi_init_algorithm->address); /* Write algorithm to working area */ retval = target_write_buffer(target, diff --git a/src/flash/nor/xmc1xxx.c b/src/flash/nor/xmc1xxx.c index bb2ec12..0a76b21 100644 --- a/src/flash/nor/xmc1xxx.c +++ b/src/flash/nor/xmc1xxx.c @@ -305,7 +305,7 @@ static int xmc1xxx_write(struct flash_bank *bank, const uint8_t *buffer, uint32_t blocks = MIN(block_count, data_workarea->size / NVM_BLOCK_SIZE); uint32_t addr = bank->base + offset; - LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" PRIx32, + LOG_DEBUG("copying %" PRId32 " bytes to SRAM 0x%08" TARGET_PRIxADDR, MIN(blocks * NVM_BLOCK_SIZE, byte_count), data_workarea->address); diff --git a/src/helper/command.c b/src/helper/command.c index fc4aac7..5deaee8 100644 --- a/src/helper/command.c +++ b/src/helper/command.c @@ -1410,6 +1410,8 @@ DEFINE_PARSE_ULONGLONG(_u32, uint32_t, 0, UINT32_MAX) DEFINE_PARSE_ULONGLONG(_u16, uint16_t, 0, UINT16_MAX) DEFINE_PARSE_ULONGLONG(_u8, uint8_t, 0, UINT8_MAX) +DEFINE_PARSE_ULONGLONG(_target_addr, target_addr_t, 0, TARGET_ADDR_MAX) + #define DEFINE_PARSE_LONGLONG(name, type, min, max) \ DEFINE_PARSE_WRAPPER(name, type, min, max, long long, _llong) DEFINE_PARSE_LONGLONG(_int, int, n < INT_MIN, INT_MAX) diff --git a/src/helper/command.h b/src/helper/command.h index 5c39660..bd24156 100644 --- a/src/helper/command.h +++ b/src/helper/command.h @@ -357,10 +357,13 @@ DECLARE_PARSE_WRAPPER(_u16, uint16_t); DECLARE_PARSE_WRAPPER(_u8, uint8_t); DECLARE_PARSE_WRAPPER(_int, int); +DECLARE_PARSE_WRAPPER(_s64, int64_t); DECLARE_PARSE_WRAPPER(_s32, int32_t); DECLARE_PARSE_WRAPPER(_s16, int16_t); DECLARE_PARSE_WRAPPER(_s8, int8_t); +DECLARE_PARSE_WRAPPER(_target_addr, target_addr_t); + /** * @brief parses the string @a in into @a out as a @a type, or prints * a command error and passes the error code to the caller. If an error @@ -382,6 +385,9 @@ DECLARE_PARSE_WRAPPER(_s8, int8_t); } \ } while (0) +#define COMMAND_PARSE_ADDRESS(in, out) \ + COMMAND_PARSE_NUMBER(target_addr, in, out) + /** * Parse the string @c as a binary parameter, storing the boolean value * in @c out. The strings @c on and @c off are used to match different diff --git a/src/helper/types.h b/src/helper/types.h index 1854ba8..58c9e72 100644 --- a/src/helper/types.h +++ b/src/helper/types.h @@ -296,14 +296,21 @@ static inline int parity_u32(uint32_t x) */ #if !defined(_STDINT_H) -#define PRIx32 "x" #define PRId32 "d" -#define SCNx32 "x" #define PRIi32 "i" +#define PRIo32 "o" #define PRIu32 "u" +#define PRIx32 "x" +#define PRIX32 "X" +#define SCNx32 "x" #define PRId8 PRId32 #define SCNx64 "llx" +#define PRId64 "lld" +#define PRIi64 "lli" +#define PRIo64 "llo" +#define PRIu64 "llu" #define PRIx64 "llx" +#define PRIX64 "llX" typedef CYG_ADDRWORD intptr_t; typedef int64_t intmax_t; @@ -337,4 +344,23 @@ typedef uint64_t uintmax_t; #endif +#if BUILD_TARGET64 +typedef uint64_t target_addr_t; +#define TARGET_ADDR_MAX UINT64_MAX +#define TARGET_PRIdADDR PRId64 +#define TARGET_PRIuADDR PRIu64 +#define TARGET_PRIoADDR PRIo64 +#define TARGET_PRIxADDR PRIx64 +#define TARGET_PRIXADDR PRIX64 +#else +typedef uint32_t target_addr_t; +#define TARGET_ADDR_MAX UINT32_MAX +#define TARGET_PRIdADDR PRId32 +#define TARGET_PRIuADDR PRIu32 +#define TARGET_PRIoADDR PRIo32 +#define TARGET_PRIxADDR PRIx32 +#define TARGET_PRIXADDR PRIX32 +#endif +#define TARGET_ADDR_FMT "0x%8.8" TARGET_PRIxADDR + #endif /* OPENOCD_HELPER_TYPES_H */ diff --git a/src/jtag/aice/aice_pipe.c b/src/jtag/aice/aice_pipe.c index 18ad40e..bdc8c09 100644 --- a/src/jtag/aice/aice_pipe.c +++ b/src/jtag/aice/aice_pipe.c @@ -786,8 +786,8 @@ static int aice_pipe_memory_mode(uint32_t coreid, enum nds_memory_select mem_sel return ERROR_FAIL; } -static int aice_pipe_read_tlb(uint32_t coreid, uint32_t virtual_address, - uint32_t *physical_address) +static int aice_pipe_read_tlb(uint32_t coreid, target_addr_t virtual_address, + target_addr_t *physical_address) { char line[AICE_PIPE_MAXLINE]; char command[AICE_PIPE_MAXLINE]; diff --git a/src/jtag/aice/aice_port.h b/src/jtag/aice/aice_port.h index 4568ce1..d3d6a1a 100644 --- a/src/jtag/aice/aice_port.h +++ b/src/jtag/aice/aice_port.h @@ -180,7 +180,7 @@ struct aice_port_api_s { int (*memory_mode)(uint32_t coreid, enum nds_memory_select mem_select); /** */ - int (*read_tlb)(uint32_t coreid, uint32_t virtual_address, uint32_t *physical_address); + int (*read_tlb)(uint32_t coreid, target_addr_t virtual_address, target_addr_t *physical_address); /** */ int (*cache_ctl)(uint32_t coreid, uint32_t subtype, uint32_t address); diff --git a/src/jtag/aice/aice_usb.c b/src/jtag/aice/aice_usb.c index b27f720..b36e390 100644 --- a/src/jtag/aice/aice_usb.c +++ b/src/jtag/aice/aice_usb.c @@ -3424,10 +3424,10 @@ static int aice_usb_memory_mode(uint32_t coreid, enum nds_memory_select mem_sele return ERROR_OK; } -static int aice_usb_read_tlb(uint32_t coreid, uint32_t virtual_address, - uint32_t *physical_address) +static int aice_usb_read_tlb(uint32_t coreid, target_addr_t virtual_address, + target_addr_t *physical_address) { - LOG_DEBUG("aice_usb_read_tlb, virtual address: 0x%08" PRIx32, virtual_address); + LOG_DEBUG("aice_usb_read_tlb, virtual address: 0x%08" TARGET_PRIxADDR, virtual_address); uint32_t instructions[4]; uint32_t probe_result; diff --git a/src/rtos/linux.c b/src/rtos/linux.c index e5a4efc..3efaab1 100644 --- a/src/rtos/linux.c +++ b/src/rtos/linux.c @@ -105,11 +105,11 @@ static int linux_os_dummy_update(struct rtos *rtos) return 0; } -static int linux_compute_virt2phys(struct target *target, uint32_t address) +static int linux_compute_virt2phys(struct target *target, target_addr_t address) { struct linux_os *linux_os = (struct linux_os *) target->rtos->rtos_specific_params; - uint32_t pa = 0; + target_addr_t pa = 0; int retval = target->type->virt2phys(target, address, &pa); if (retval != ERROR_OK) { LOG_ERROR("Cannot compute linux virt2phys translation"); diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index fe00744..c293f5b 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -735,22 +735,22 @@ static void gdb_signal_reply(struct target *target, struct connection *connectio stop_reason[0] = '\0'; if (target->debug_reason == DBG_REASON_WATCHPOINT) { enum watchpoint_rw hit_wp_type; - uint32_t hit_wp_address; + target_addr_t hit_wp_address; if (watchpoint_hit(target, &hit_wp_type, &hit_wp_address) == ERROR_OK) { switch (hit_wp_type) { case WPT_WRITE: snprintf(stop_reason, sizeof(stop_reason), - "watch:%08" PRIx32 ";", hit_wp_address); + "watch:%08" TARGET_PRIxADDR ";", hit_wp_address); break; case WPT_READ: snprintf(stop_reason, sizeof(stop_reason), - "rwatch:%08" PRIx32 ";", hit_wp_address); + "rwatch:%08" TARGET_PRIxADDR ";", hit_wp_address); break; case WPT_ACCESS: snprintf(stop_reason, sizeof(stop_reason), - "awatch:%08" PRIx32 ";", hit_wp_address); + "awatch:%08" TARGET_PRIxADDR ";", hit_wp_address); break; default: break; diff --git a/src/target/algorithm.h b/src/target/algorithm.h index d216a82..8894241 100644 --- a/src/target/algorithm.h +++ b/src/target/algorithm.h @@ -26,7 +26,7 @@ enum param_direction { }; struct mem_param { - uint32_t address; + target_addr_t address; uint32_t size; uint8_t *value; enum param_direction direction; diff --git a/src/target/arm.h b/src/target/arm.h index 226dd65..77a2f7b 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -231,7 +231,7 @@ int arm_init_arch_info(struct target *target, struct arm *arm); int armv4_5_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 armv4_5_run_algorithm_inner(struct target *target, int num_mem_params, struct mem_param *mem_params, @@ -242,9 +242,9 @@ int armv4_5_run_algorithm_inner(struct target *target, int timeout_ms, void *arch_info)); int arm_checksum_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *checksum); + target_addr_t address, uint32_t count, uint32_t *checksum); int arm_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value); + target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value); void arm_set_cpsr(struct arm *arm, uint32_t cpsr); struct reg *arm_reg_current(struct arm *arm, unsigned regnum); diff --git a/src/target/arm11.c b/src/target/arm11.c index cbe4d45..13fbd20 100644 --- a/src/target/arm11.c +++ b/src/target/arm11.c @@ -42,7 +42,7 @@ static int arm11_step(struct target *target, int current, - uint32_t address, int handle_breakpoints); + target_addr_t address, int handle_breakpoints); /** Check and if necessary take control of the system @@ -449,7 +449,7 @@ static uint32_t arm11_nextpc(struct arm11_common *arm11, int current, uint32_t a } static int arm11_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { /* LOG_DEBUG("current %d address %08x handle_breakpoints %d debug_execution %d", */ /* current, address, handle_breakpoints, debug_execution); */ @@ -467,7 +467,7 @@ static int arm11_resume(struct target *target, int current, address = arm11_nextpc(arm11, current, address); - LOG_DEBUG("RESUME PC %08" PRIx32 "%s", address, !current ? "!" : ""); + LOG_DEBUG("RESUME PC %08" TARGET_PRIxADDR "%s", address, !current ? "!" : ""); /* clear breakpoints/watchpoints and VCR*/ CHECK_RETVAL(arm11_sc7_clear_vbw(arm11)); @@ -481,7 +481,7 @@ static int arm11_resume(struct target *target, int current, for (bp = target->breakpoints; bp; bp = bp->next) { if (bp->address == address) { - LOG_DEBUG("must step over %08" PRIx32 "", bp->address); + LOG_DEBUG("must step over %08" TARGET_PRIxADDR "", bp->address); arm11_step(target, 1, 0, 0); break; } @@ -507,7 +507,7 @@ static int arm11_resume(struct target *target, int current, CHECK_RETVAL(arm11_sc7_run(arm11, brp, ARRAY_SIZE(brp))); - LOG_DEBUG("Add BP %d at %08" PRIx32, brp_num, + LOG_DEBUG("Add BP %d at %08" TARGET_PRIxADDR, brp_num, bp->address); brp_num++; @@ -557,7 +557,7 @@ static int arm11_resume(struct target *target, int current, } static int arm11_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { LOG_DEBUG("target->state: %s", target_state_name(target)); @@ -571,7 +571,7 @@ static int arm11_step(struct target *target, int current, address = arm11_nextpc(arm11, current, address); - LOG_DEBUG("STEP PC %08" PRIx32 "%s", address, !current ? "!" : ""); + LOG_DEBUG("STEP PC %08" TARGET_PRIxADDR "%s", address, !current ? "!" : ""); /** \todo TODO: Thumb not supported here */ @@ -583,13 +583,13 @@ static int arm11_step(struct target *target, int current, /* skip over BKPT */ if ((next_instruction & 0xFFF00070) == 0xe1200070) { address = arm11_nextpc(arm11, 0, address + 4); - LOG_DEBUG("Skipping BKPT %08" PRIx32, address); + LOG_DEBUG("Skipping BKPT %08" TARGET_PRIxADDR, address); } /* skip over Wait for interrupt / Standby * mcr 15, 0, r?, cr7, cr0, {4} */ else if ((next_instruction & 0xFFFF0FFF) == 0xee070f90) { address = arm11_nextpc(arm11, 0, address + 4); - LOG_DEBUG("Skipping WFI %08" PRIx32, address); + LOG_DEBUG("Skipping WFI %08" TARGET_PRIxADDR, address); } /* ignore B to self */ else if ((next_instruction & 0xFEFFFFFF) == 0xeafffffe) @@ -887,7 +887,7 @@ static int arm11_read_memory_inner(struct target *target, } static int arm11_read_memory(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) @@ -1043,7 +1043,7 @@ static int arm11_write_memory_inner(struct target *target, } static int arm11_write_memory(struct target *target, - uint32_t address, uint32_t size, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { /* pointer increment matters only for multi-unit writes ... diff --git a/src/target/arm720t.c b/src/target/arm720t.c index 3991e19..bcbfa9d 100644 --- a/src/target/arm720t.c +++ b/src/target/arm720t.c @@ -271,7 +271,7 @@ static int arm720_mmu(struct target *target, int *enabled) } static int arm720_virt2phys(struct target *target, - uint32_t virtual, uint32_t *physical) + target_addr_t virtual, target_addr_t *physical) { uint32_t cb; struct arm720t_common *arm720t = target_to_arm720(target); @@ -286,7 +286,7 @@ static int arm720_virt2phys(struct target *target, } static int arm720t_read_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int retval; struct arm720t_common *arm720t = target_to_arm720(target); @@ -309,7 +309,7 @@ static int arm720t_read_memory(struct target *target, } static int arm720t_read_phys_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct arm720t_common *arm720t = target_to_arm720(target); @@ -317,7 +317,7 @@ static int arm720t_read_phys_memory(struct target *target, } static int arm720t_write_phys_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct arm720t_common *arm720t = target_to_arm720(target); diff --git a/src/target/arm7_9_common.c b/src/target/arm7_9_common.c index c1d5c79..7fd1ed9 100644 --- a/src/target/arm7_9_common.c +++ b/src/target/arm7_9_common.c @@ -101,7 +101,8 @@ static void arm7_9_assign_wp(struct arm7_9_common *arm7_9, struct breakpoint *br arm7_9->wp_available--; } else LOG_ERROR("BUG: no hardware comparator available"); - LOG_DEBUG("BPID: %" PRId32 " (0x%08" PRIx32 ") using hw wp: %d", + + LOG_DEBUG("BPID: %" PRId32 " (0x%08" TARGET_PRIxADDR ") using hw wp: %d", breakpoint->unique_id, breakpoint->address, breakpoint->set); @@ -187,7 +188,7 @@ static int arm7_9_set_breakpoint(struct target *target, struct breakpoint *break struct arm7_9_common *arm7_9 = target_to_arm7_9(target); int retval = ERROR_OK; - LOG_DEBUG("BPID: %" PRId32 ", Address: 0x%08" PRIx32 ", Type: %d", + LOG_DEBUG("BPID: %" PRId32 ", Address: 0x%08" TARGET_PRIxADDR ", Type: %d", breakpoint->unique_id, breakpoint->address, breakpoint->type); @@ -244,7 +245,7 @@ static int arm7_9_set_breakpoint(struct target *target, struct breakpoint *break if (retval != ERROR_OK) return retval; if (verify != arm7_9->arm_bkpt) { - LOG_ERROR("Unable to set 32 bit software breakpoint at address %08" PRIx32 + LOG_ERROR("Unable to set 32 bit software breakpoint at address %08" TARGET_PRIxADDR " - check that memory is read/writable", breakpoint->address); return ERROR_OK; } @@ -264,7 +265,7 @@ static int arm7_9_set_breakpoint(struct target *target, struct breakpoint *break if (retval != ERROR_OK) return retval; if (verify != arm7_9->thumb_bkpt) { - LOG_ERROR("Unable to set thumb software breakpoint at address %08" PRIx32 + LOG_ERROR("Unable to set thumb software breakpoint at address %08" TARGET_PRIxADDR " - check that memory is read/writable", breakpoint->address); return ERROR_OK; } @@ -299,7 +300,7 @@ static int arm7_9_unset_breakpoint(struct target *target, struct breakpoint *bre int retval = ERROR_OK; struct arm7_9_common *arm7_9 = target_to_arm7_9(target); - LOG_DEBUG("BPID: %" PRId32 ", Address: 0x%08" PRIx32, + LOG_DEBUG("BPID: %" PRId32 ", Address: 0x%08" TARGET_PRIxADDR, breakpoint->unique_id, breakpoint->address); @@ -1692,7 +1693,7 @@ static void arm7_9_enable_breakpoints(struct target *target) int arm7_9_resume(struct target *target, int current, - uint32_t address, + target_addr_t address, int handle_breakpoints, int debug_execution) { @@ -1724,7 +1725,7 @@ int arm7_9_resume(struct target *target, breakpoint = breakpoint_find(target, buf_get_u32(arm->pc->value, 0, 32)); if (breakpoint != NULL) { - LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (id: %" PRId32, + LOG_DEBUG("unset breakpoint at 0x%8.8" TARGET_PRIxADDR " (id: %" PRId32, breakpoint->address, breakpoint->unique_id); retval = arm7_9_unset_breakpoint(target, breakpoint); @@ -1783,7 +1784,7 @@ int arm7_9_resume(struct target *target, LOG_DEBUG("new PC after step: 0x%8.8" PRIx32, buf_get_u32(arm->pc->value, 0, 32)); - LOG_DEBUG("set breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); + LOG_DEBUG("set breakpoint at 0x%8.8" TARGET_PRIxADDR "", breakpoint->address); retval = arm7_9_set_breakpoint(target, breakpoint); if (retval != ERROR_OK) return retval; @@ -1894,7 +1895,7 @@ void arm7_9_disable_eice_step(struct target *target) embeddedice_store_reg(&arm7_9->eice_cache->reg_list[EICE_W1_CONTROL_VALUE]); } -int arm7_9_step(struct target *target, int current, uint32_t address, int handle_breakpoints) +int arm7_9_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { struct arm7_9_common *arm7_9 = target_to_arm7_9(target); struct arm *arm = &arm7_9->arm; @@ -2094,7 +2095,7 @@ static int arm7_9_write_core_reg(struct target *target, struct reg *r, } int arm7_9_read_memory(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) @@ -2109,7 +2110,7 @@ int arm7_9_read_memory(struct target *target, int retval; int last_reg = 0; - LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", + LOG_DEBUG("address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); if (target->state != TARGET_HALTED) { @@ -2247,7 +2248,8 @@ int arm7_9_read_memory(struct target *target, if (((cpsr & 0x1f) == ARM_MODE_ABT) && (arm->core_mode != ARM_MODE_ABT)) { LOG_WARNING( - "memory read caused data abort (address: 0x%8.8" PRIx32 ", size: 0x%" PRIx32 ", count: 0x%" PRIx32 ")", + "memory read caused data abort " + "(address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%" PRIx32 ", count: 0x%" PRIx32 ")", address, size, count); @@ -2263,7 +2265,7 @@ int arm7_9_read_memory(struct target *target, } int arm7_9_write_memory(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) @@ -2460,7 +2462,8 @@ int arm7_9_write_memory(struct target *target, if (((cpsr & 0x1f) == ARM_MODE_ABT) && (arm->core_mode != ARM_MODE_ABT)) { LOG_WARNING( - "memory write caused data abort (address: 0x%8.8" PRIx32 ", size: 0x%" PRIx32 ", count: 0x%" PRIx32 ")", + "memory write caused data abort " + "(address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%" PRIx32 ", count: 0x%" PRIx32 ")", address, size, count); @@ -2476,7 +2479,7 @@ int arm7_9_write_memory(struct target *target, } int arm7_9_write_memory_opt(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) @@ -2576,7 +2579,7 @@ static const uint32_t dcc_code[] = { }; int arm7_9_bulk_write_memory(struct target *target, - uint32_t address, + target_addr_t address, uint32_t count, const uint8_t *buffer) { @@ -2632,7 +2635,7 @@ int arm7_9_bulk_write_memory(struct target *target, uint32_t endaddress = buf_get_u32(reg_params[0].value, 0, 32); if (endaddress != (address + count*4)) { LOG_ERROR( - "DCC write failed, expected end address 0x%08" PRIx32 " got 0x%0" PRIx32 "", + "DCC write failed, expected end address 0x%08" TARGET_PRIxADDR " got 0x%0" PRIx32 "", (address + count*4), endaddress); retval = ERROR_FAIL; diff --git a/src/target/arm7_9_common.h b/src/target/arm7_9_common.h index 044384b..811f9c5 100644 --- a/src/target/arm7_9_common.h +++ b/src/target/arm7_9_common.h @@ -122,13 +122,13 @@ struct arm7_9_common { * Used as a fallback when bulk writes are unavailable, or for writing data needed to * do the bulk writes. */ - int (*write_memory)(struct target *target, uint32_t address, + int (*write_memory)(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); /** * Write target memory in multiples of 4 bytes, optimized for * writing large quantities of data. */ - int (*bulk_write_memory)(struct target *target, uint32_t address, + int (*bulk_write_memory)(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer); }; @@ -155,19 +155,19 @@ int arm7_9_early_halt(struct target *target); int arm7_9_soft_reset_halt(struct target *target); int arm7_9_halt(struct target *target); -int arm7_9_resume(struct target *target, int current, uint32_t address, +int arm7_9_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution); -int arm7_9_step(struct target *target, int current, uint32_t address, +int arm7_9_step(struct target *target, int current, target_addr_t address, int handle_breakpoints); -int arm7_9_read_memory(struct target *target, uint32_t address, +int arm7_9_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); -int arm7_9_write_memory(struct target *target, uint32_t address, +int arm7_9_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); -int arm7_9_write_memory_opt(struct target *target, uint32_t address, +int arm7_9_write_memory_opt(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int arm7_9_write_memory_no_opt(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); -int arm7_9_bulk_write_memory(struct target *target, uint32_t address, +int arm7_9_bulk_write_memory(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer); int arm7_9_run_algorithm(struct target *target, int num_mem_params, diff --git a/src/target/arm920t.c b/src/target/arm920t.c index 2c96d19..7927a2b 100644 --- a/src/target/arm920t.c +++ b/src/target/arm920t.c @@ -553,7 +553,7 @@ static int arm920_mmu(struct target *target, int *enabled) } static int arm920_virt2phys(struct target *target, - uint32_t virt, uint32_t *phys) + target_addr_t virt, target_addr_t *phys) { uint32_t cb; struct arm920t_common *arm920t = target_to_arm920(target); @@ -568,7 +568,7 @@ static int arm920_virt2phys(struct target *target, } /** Reads a buffer, in the specified word size, with current MMU settings. */ -int arm920t_read_memory(struct target *target, uint32_t address, +int arm920t_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int retval; @@ -580,7 +580,7 @@ int arm920t_read_memory(struct target *target, uint32_t address, static int arm920t_read_phys_memory(struct target *target, - uint32_t address, uint32_t size, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct arm920t_common *arm920t = target_to_arm920(target); @@ -590,7 +590,7 @@ static int arm920t_read_phys_memory(struct target *target, } static int arm920t_write_phys_memory(struct target *target, - uint32_t address, uint32_t size, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct arm920t_common *arm920t = target_to_arm920(target); @@ -600,7 +600,7 @@ static int arm920t_write_phys_memory(struct target *target, } /** Writes a buffer, in the specified word size, with current MMU settings. */ -int arm920t_write_memory(struct target *target, uint32_t address, +int arm920t_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval; diff --git a/src/target/arm920t.h b/src/target/arm920t.h index 3401b09..2e3b08c 100644 --- a/src/target/arm920t.h +++ b/src/target/arm920t.h @@ -55,9 +55,9 @@ struct arm920t_tlb_entry { int arm920t_arch_state(struct target *target); int arm920t_soft_reset_halt(struct target *target); int arm920t_read_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); int arm920t_write_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int arm920t_post_debug_entry(struct target *target); void arm920t_pre_restore_context(struct target *target); int arm920t_get_ttb(struct target *target, uint32_t *result); diff --git a/src/target/arm926ejs.c b/src/target/arm926ejs.c index d7c043e..58de778 100644 --- a/src/target/arm926ejs.c +++ b/src/target/arm926ejs.c @@ -594,7 +594,7 @@ int arm926ejs_soft_reset_halt(struct target *target) } /** Writes a buffer, in the specified word size, with current MMU settings. */ -int arm926ejs_write_memory(struct target *target, uint32_t address, +int arm926ejs_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval; @@ -623,7 +623,7 @@ int arm926ejs_write_memory(struct target *target, uint32_t address, return retval; } - uint32_t pa; + target_addr_t pa; retval = target->type->virt2phys(target, address, &pa); if (retval != ERROR_OK) return retval; @@ -655,7 +655,7 @@ int arm926ejs_write_memory(struct target *target, uint32_t address, } static int arm926ejs_write_phys_memory(struct target *target, - uint32_t address, uint32_t size, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct arm926ejs_common *arm926ejs = target_to_arm926(target); @@ -665,7 +665,7 @@ static int arm926ejs_write_phys_memory(struct target *target, } static int arm926ejs_read_phys_memory(struct target *target, - uint32_t address, uint32_t size, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct arm926ejs_common *arm926ejs = target_to_arm926(target); @@ -736,7 +736,7 @@ COMMAND_HANDLER(arm926ejs_handle_cache_info_command) return armv4_5_handle_cache_info_command(CMD_CTX, &arm926ejs->armv4_5_mmu.armv4_5_cache); } -static int arm926ejs_virt2phys(struct target *target, uint32_t virtual, uint32_t *physical) +static int arm926ejs_virt2phys(struct target *target, target_addr_t virtual, target_addr_t *physical) { uint32_t cb; struct arm926ejs_common *arm926ejs = target_to_arm926(target); diff --git a/src/target/arm926ejs.h b/src/target/arm926ejs.h index 02b4ef8..d4fd0cb 100644 --- a/src/target/arm926ejs.h +++ b/src/target/arm926ejs.h @@ -47,7 +47,7 @@ int arm926ejs_init_arch_info(struct target *target, struct arm926ejs_common *arm926ejs, struct jtag_tap *tap); int arm926ejs_arch_state(struct target *target); int arm926ejs_write_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int arm926ejs_soft_reset_halt(struct target *target); extern const struct command_registration arm926ejs_command_handlers[]; diff --git a/src/target/arm946e.c b/src/target/arm946e.c index 5ee31cc..06c9fc3 100644 --- a/src/target/arm946e.c +++ b/src/target/arm946e.c @@ -487,7 +487,7 @@ uint32_t arm946e_invalidate_icache(struct target *target, uint32_t address, } /** Writes a buffer, in the specified word size, with current MMU settings. */ -int arm946e_write_memory(struct target *target, uint32_t address, +int arm946e_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval; @@ -535,7 +535,7 @@ int arm946e_write_memory(struct target *target, uint32_t address, } -int arm946e_read_memory(struct target *target, uint32_t address, +int arm946e_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int retval; diff --git a/src/target/armv4_5.c b/src/target/armv4_5.c index 624a254..2029ca9 100644 --- a/src/target/armv4_5.c +++ b/src/target/armv4_5.c @@ -816,7 +816,7 @@ COMMAND_HANDLER(handle_arm_disassemble_command) } struct arm *arm = target_to_arm(target); - uint32_t address; + target_addr_t address; int count = 1; int thumb = 0; @@ -840,7 +840,7 @@ COMMAND_HANDLER(handle_arm_disassemble_command) COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], count); /* FALL THROUGH */ case 1: - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); if (address & 0x01) { if (!thumb) { command_print(CMD_CTX, "Disassemble as Thumb"); @@ -1434,8 +1434,8 @@ int armv4_5_run_algorithm(struct target *target, 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) { @@ -1444,8 +1444,8 @@ int armv4_5_run_algorithm(struct target *target, mem_params, num_reg_params, reg_params, - entry_point, - exit_point, + (uint32_t)entry_point, + (uint32_t)exit_point, timeout_ms, arch_info, armv4_5_run_algorithm_completion); @@ -1456,7 +1456,7 @@ int armv4_5_run_algorithm(struct target *target, * */ int arm_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 arm_algorithm arm_algo; @@ -1529,7 +1529,7 @@ cleanup: * */ int arm_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value) + target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value) { struct working_area *check_algorithm; struct reg_param reg_params[3]; diff --git a/src/target/armv4_5_mmu.h b/src/target/armv4_5_mmu.h index 0f52121..7beaf4e 100644 --- a/src/target/armv4_5_mmu.h +++ b/src/target/armv4_5_mmu.h @@ -25,8 +25,9 @@ struct target; struct armv4_5_mmu_common { int (*get_ttb)(struct target *target, uint32_t *result); - int (*read_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); - int (*write_memory)(struct target *target, uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); + int (*read_memory)(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); + int (*write_memory)(struct target *target, target_addr_t address, + uint32_t size, uint32_t count, const uint8_t *buffer); int (*disable_mmu_caches)(struct target *target, int mmu, int d_u_cache, int i_cache); int (*enable_mmu_caches)(struct target *target, int mmu, int d_u_cache, int i_cache); struct armv4_5_cache_common armv4_5_cache; diff --git a/src/target/armv7a.h b/src/target/armv7a.h index c5c03c8..14112e4 100644 --- a/src/target/armv7a.h +++ b/src/target/armv7a.h @@ -90,7 +90,7 @@ struct armv7a_mmu_common { uint32_t ttbr_mask[2]; uint32_t ttbr_range[2]; - int (*read_physical_memory)(struct target *target, uint32_t address, uint32_t size, + int (*read_physical_memory)(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); struct armv7a_cache_common armv7a_cache; uint32_t mmu_enabled; diff --git a/src/target/armv7a_cache_l2x.c b/src/target/armv7a_cache_l2x.c index 7988438..e181f26 100644 --- a/src/target/armv7a_cache_l2x.c +++ b/src/target/armv7a_cache_l2x.c @@ -63,12 +63,12 @@ int arm7a_l2x_flush_all_data(struct target *target) l2_way_val = (1 << l2x_cache->way) - 1; - return target_write_phys_memory(target, + return target_write_phys_u32(target, l2x_cache->base + L2X0_CLEAN_INV_WAY, - 4, 1, (uint8_t *)&l2_way_val); + l2_way_val); } -int armv7a_l2x_cache_flush_virt(struct target *target, uint32_t virt, +int armv7a_l2x_cache_flush_virt(struct target *target, target_addr_t virt, uint32_t size) { struct armv7a_common *armv7a = target_to_armv7a(target); @@ -83,16 +83,15 @@ int armv7a_l2x_cache_flush_virt(struct target *target, uint32_t virt, return retval; for (i = 0; i < size; i += linelen) { - uint32_t pa, offs = virt + i; + target_addr_t pa, offs = virt + i; /* FIXME: use less verbose virt2phys? */ retval = target->type->virt2phys(target, offs, &pa); if (retval != ERROR_OK) goto done; - retval = target_write_phys_memory(target, - l2x_cache->base + L2X0_CLEAN_INV_LINE_PA, - 4, 1, (uint8_t *)&pa); + retval = target_write_phys_u32(target, + l2x_cache->base + L2X0_CLEAN_INV_LINE_PA, pa); if (retval != ERROR_OK) goto done; } @@ -104,7 +103,7 @@ done: return retval; } -static int armv7a_l2x_cache_inval_virt(struct target *target, uint32_t virt, +static int armv7a_l2x_cache_inval_virt(struct target *target, target_addr_t virt, uint32_t size) { struct armv7a_common *armv7a = target_to_armv7a(target); @@ -119,16 +118,15 @@ static int armv7a_l2x_cache_inval_virt(struct target *target, uint32_t virt, return retval; for (i = 0; i < size; i += linelen) { - uint32_t pa, offs = virt + i; + target_addr_t pa, offs = virt + i; /* FIXME: use less verbose virt2phys? */ retval = target->type->virt2phys(target, offs, &pa); if (retval != ERROR_OK) goto done; - retval = target_write_phys_memory(target, - l2x_cache->base + L2X0_INV_LINE_PA, - 4, 1, (uint8_t *)&pa); + retval = target_write_phys_u32(target, + l2x_cache->base + L2X0_INV_LINE_PA, pa); if (retval != ERROR_OK) goto done; } @@ -140,7 +138,7 @@ done: return retval; } -static int armv7a_l2x_cache_clean_virt(struct target *target, uint32_t virt, +static int armv7a_l2x_cache_clean_virt(struct target *target, target_addr_t virt, unsigned int size) { struct armv7a_common *armv7a = target_to_armv7a(target); @@ -155,16 +153,15 @@ static int armv7a_l2x_cache_clean_virt(struct target *target, uint32_t virt, return retval; for (i = 0; i < size; i += linelen) { - uint32_t pa, offs = virt + i; + target_addr_t pa, offs = virt + i; /* FIXME: use less verbose virt2phys? */ retval = target->type->virt2phys(target, offs, &pa); if (retval != ERROR_OK) goto done; - retval = target_write_phys_memory(target, - l2x_cache->base + L2X0_CLEAN_LINE_PA, - 4, 1, (uint8_t *)&pa); + retval = target_write_phys_u32(target, + l2x_cache->base + L2X0_CLEAN_LINE_PA, pa); if (retval != ERROR_OK) goto done; } @@ -252,7 +249,8 @@ COMMAND_HANDLER(arm7a_l2x_cache_flush_all_command) COMMAND_HANDLER(arm7a_l2x_cache_flush_virt_cmd) { struct target *target = get_current_target(CMD_CTX); - uint32_t virt, size; + target_addr_t virt; + uint32_t size; if (CMD_ARGC == 0 || CMD_ARGC > 2) return ERROR_COMMAND_SYNTAX_ERROR; @@ -262,7 +260,7 @@ COMMAND_HANDLER(arm7a_l2x_cache_flush_virt_cmd) else size = 1; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], virt); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], virt); return armv7a_l2x_cache_flush_virt(target, virt, size); } @@ -270,7 +268,8 @@ COMMAND_HANDLER(arm7a_l2x_cache_flush_virt_cmd) COMMAND_HANDLER(arm7a_l2x_cache_inval_virt_cmd) { struct target *target = get_current_target(CMD_CTX); - uint32_t virt, size; + target_addr_t virt; + uint32_t size; if (CMD_ARGC == 0 || CMD_ARGC > 2) return ERROR_COMMAND_SYNTAX_ERROR; @@ -280,7 +279,7 @@ COMMAND_HANDLER(arm7a_l2x_cache_inval_virt_cmd) else size = 1; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], virt); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], virt); return armv7a_l2x_cache_inval_virt(target, virt, size); } @@ -288,7 +287,8 @@ COMMAND_HANDLER(arm7a_l2x_cache_inval_virt_cmd) COMMAND_HANDLER(arm7a_l2x_cache_clean_virt_cmd) { struct target *target = get_current_target(CMD_CTX); - uint32_t virt, size; + target_addr_t virt; + uint32_t size; if (CMD_ARGC == 0 || CMD_ARGC > 2) return ERROR_COMMAND_SYNTAX_ERROR; @@ -298,7 +298,7 @@ COMMAND_HANDLER(arm7a_l2x_cache_clean_virt_cmd) else size = 1; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], virt); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], virt); return armv7a_l2x_cache_clean_virt(target, virt, size); } diff --git a/src/target/armv7a_cache_l2x.h b/src/target/armv7a_cache_l2x.h index 3d9ad81..f98b554 100644 --- a/src/target/armv7a_cache_l2x.h +++ b/src/target/armv7a_cache_l2x.h @@ -151,7 +151,7 @@ struct l2c_init_data { extern const struct command_registration arm7a_l2x_cache_command_handler[]; -int armv7a_l2x_cache_flush_virt(struct target *target, uint32_t virt, +int armv7a_l2x_cache_flush_virt(struct target *target, target_addr_t virt, uint32_t size); int arm7a_l2x_flush_all_data(struct target *target); diff --git a/src/target/armv7m.c b/src/target/armv7m.c index 64d18d7..e0911c3 100644 --- a/src/target/armv7m.c +++ b/src/target/armv7m.c @@ -318,7 +318,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 +343,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 +431,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 +461,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; @@ -682,7 +682,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; @@ -733,7 +733,7 @@ cleanup: /** Checks whether a memory region is erased. */ int armv7m_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value) + target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value) { struct working_area *erase_check_algorithm; struct reg_param reg_params[3]; diff --git a/src/target/armv7m.h b/src/target/armv7m.h index 304c72d..284bb9c 100644 --- a/src/target/armv7m.h +++ b/src/target/armv7m.h @@ -203,19 +203,19 @@ int armv7m_init_arch_info(struct target *target, struct armv7m_common *armv7m); 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 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); 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); int armv7m_invalidate_core_regs(struct target *target); @@ -223,9 +223,9 @@ int armv7m_invalidate_core_regs(struct target *target); int armv7m_restore_context(struct target *target); 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); int armv7m_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value); + target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value); int armv7m_maybe_skip_bkpt_inst(struct target *target, bool *inst_found); diff --git a/src/target/avr32_ap7k.c b/src/target/avr32_ap7k.c index e5634f2..f8da8d5 100644 --- a/src/target/avr32_ap7k.c +++ b/src/target/avr32_ap7k.c @@ -312,7 +312,7 @@ static int avr32_ap7k_deassert_reset(struct target *target) } static int avr32_ap7k_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { struct avr32_ap7k_common *ap7k = target_to_ap7k(target); struct breakpoint *breakpoint = NULL; @@ -348,7 +348,7 @@ static int avr32_ap7k_resume(struct target *target, int current, /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { - LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); + LOG_DEBUG("unset breakpoint at 0x%8.8" TARGET_PRIxADDR "", breakpoint->address); #if 0 avr32_ap7k_unset_breakpoint(target, breakpoint); avr32_ap7k_single_step_core(target); @@ -394,7 +394,7 @@ static int avr32_ap7k_resume(struct target *target, int current, } static int avr32_ap7k_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { LOG_ERROR("%s: implement me", __func__); @@ -431,12 +431,12 @@ static int avr32_ap7k_remove_watchpoint(struct target *target, return ERROR_OK; } -static int avr32_ap7k_read_memory(struct target *target, uint32_t address, +static int avr32_ap7k_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct avr32_ap7k_common *ap7k = target_to_ap7k(target); - LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", + LOG_DEBUG("address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); @@ -472,12 +472,12 @@ static int avr32_ap7k_read_memory(struct target *target, uint32_t address, return ERROR_OK; } -static int avr32_ap7k_write_memory(struct target *target, uint32_t address, +static int avr32_ap7k_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct avr32_ap7k_common *ap7k = target_to_ap7k(target); - LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", + LOG_DEBUG("address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); diff --git a/src/target/avrt.c b/src/target/avrt.c index 40a1297..1e1898c 100644 --- a/src/target/avrt.c +++ b/src/target/avrt.c @@ -33,9 +33,9 @@ static int avr_init_target(struct command_context *cmd_ctx, struct target *targe static int avr_arch_state(struct target *target); static int avr_poll(struct target *target); static int avr_halt(struct target *target); -static int avr_resume(struct target *target, int current, uint32_t address, +static int avr_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution); -static int avr_step(struct target *target, int current, uint32_t address, +static int avr_step(struct target *target, int current, target_addr_t address, int handle_breakpoints); static int avr_assert_reset(struct target *target); @@ -116,14 +116,14 @@ static int avr_halt(struct target *target) return ERROR_OK; } -static int avr_resume(struct target *target, int current, uint32_t address, +static int avr_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution) { LOG_DEBUG("%s", __func__); return ERROR_OK; } -static int avr_step(struct target *target, int current, uint32_t address, int handle_breakpoints) +static int avr_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { LOG_DEBUG("%s", __func__); return ERROR_OK; diff --git a/src/target/breakpoints.c b/src/target/breakpoints.c index c4a959d..7cf4a69 100644 --- a/src/target/breakpoints.c +++ b/src/target/breakpoints.c @@ -42,7 +42,7 @@ static const char * const watchpoint_rw_strings[] = { static int bpwp_unique_id; int breakpoint_add_internal(struct target *target, - uint32_t address, + target_addr_t address, uint32_t length, enum breakpoint_type type) { @@ -60,7 +60,7 @@ int breakpoint_add_internal(struct target *target, * breakpoint" ... check all the parameters before * succeeding. */ - LOG_DEBUG("Duplicate Breakpoint address: 0x%08" PRIx32 " (BP %" PRIu32 ")", + LOG_DEBUG("Duplicate Breakpoint address: " TARGET_ADDR_FMT " (BP %" PRIu32 ")", address, breakpoint->unique_id); return ERROR_OK; } @@ -98,7 +98,7 @@ fail: return retval; } - LOG_DEBUG("added %s breakpoint at 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %" PRIu32 ")", + LOG_DEBUG("added %s breakpoint at " TARGET_ADDR_FMT " of length 0x%8.8x, (BPID: %" PRIu32 ")", breakpoint_type_strings[(*breakpoint_p)->type], (*breakpoint_p)->address, (*breakpoint_p)->length, (*breakpoint_p)->unique_id); @@ -159,7 +159,7 @@ int context_breakpoint_add_internal(struct target *target, } int hybrid_breakpoint_add_internal(struct target *target, - uint32_t address, + target_addr_t address, uint32_t asid, uint32_t length, enum breakpoint_type type) @@ -180,7 +180,7 @@ int hybrid_breakpoint_add_internal(struct target *target, asid, breakpoint->unique_id); return -1; } else if ((breakpoint->address == address) && (breakpoint->asid == 0)) { - LOG_DEBUG("Duplicate Breakpoint IVA: 0x%08" PRIx32 " (BP %" PRIu32 ")", + LOG_DEBUG("Duplicate Breakpoint IVA: " TARGET_ADDR_FMT " (BP %" PRIu32 ")", address, breakpoint->unique_id); return -1; @@ -208,7 +208,7 @@ int hybrid_breakpoint_add_internal(struct target *target, return retval; } LOG_DEBUG( - "added %s Hybrid breakpoint at address 0x%8.8" PRIx32 " of length 0x%8.8x, (BPID: %" PRIu32 ")", + "added %s Hybrid breakpoint at address " TARGET_ADDR_FMT " of length 0x%8.8x, (BPID: %" PRIu32 ")", breakpoint_type_strings[(*breakpoint_p)->type], (*breakpoint_p)->address, (*breakpoint_p)->length, @@ -218,7 +218,7 @@ int hybrid_breakpoint_add_internal(struct target *target, } int breakpoint_add(struct target *target, - uint32_t address, + target_addr_t address, uint32_t length, enum breakpoint_type type) { @@ -263,7 +263,7 @@ int context_breakpoint_add(struct target *target, return context_breakpoint_add_internal(target, asid, length, type); } int hybrid_breakpoint_add(struct target *target, - uint32_t address, + target_addr_t address, uint32_t asid, uint32_t length, enum breakpoint_type type) @@ -310,7 +310,7 @@ static void breakpoint_free(struct target *target, struct breakpoint *breakpoint free(breakpoint); } -int breakpoint_remove_internal(struct target *target, uint32_t address) +int breakpoint_remove_internal(struct target *target, target_addr_t address) { struct breakpoint *breakpoint = target->breakpoints; @@ -329,11 +329,11 @@ int breakpoint_remove_internal(struct target *target, uint32_t address) return 1; } else { if (!target->smp) - LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address); + LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT " found", address); return 0; } } -void breakpoint_remove(struct target *target, uint32_t address) +void breakpoint_remove(struct target *target, target_addr_t address) { int found = 0; if (target->smp) { @@ -346,7 +346,7 @@ void breakpoint_remove(struct target *target, uint32_t address) head = head->next; } if (found == 0) - LOG_ERROR("no breakpoint at address 0x%8.8" PRIx32 " found", address); + LOG_ERROR("no breakpoint at address " TARGET_ADDR_FMT " found", address); } else breakpoint_remove_internal(target, address); } @@ -375,7 +375,7 @@ void breakpoint_clear_target(struct target *target) } -struct breakpoint *breakpoint_find(struct target *target, uint32_t address) +struct breakpoint *breakpoint_find(struct target *target, target_addr_t address) { struct breakpoint *breakpoint = target->breakpoints; @@ -388,7 +388,7 @@ struct breakpoint *breakpoint_find(struct target *target, uint32_t address) return NULL; } -int watchpoint_add(struct target *target, uint32_t address, uint32_t length, +int watchpoint_add(struct target *target, target_addr_t address, uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask) { struct watchpoint *watchpoint = target->watchpoints; @@ -402,7 +402,7 @@ int watchpoint_add(struct target *target, uint32_t address, uint32_t length, || watchpoint->value != value || watchpoint->mask != mask || watchpoint->rw != rw) { - LOG_ERROR("address 0x%8.8" PRIx32 + LOG_ERROR("address " TARGET_ADDR_FMT " already has watchpoint %d", address, watchpoint->unique_id); return ERROR_FAIL; @@ -436,7 +436,7 @@ int watchpoint_add(struct target *target, uint32_t address, uint32_t length, default: reason = "unrecognized error"; bye: - LOG_ERROR("can't add %s watchpoint at 0x%8.8" PRIx32 ", %s", + LOG_ERROR("can't add %s watchpoint at " TARGET_ADDR_FMT ", %s", watchpoint_rw_strings[(*watchpoint_p)->rw], address, reason); free(*watchpoint_p); @@ -444,7 +444,7 @@ bye: return retval; } - LOG_DEBUG("added %s watchpoint at 0x%8.8" PRIx32 + LOG_DEBUG("added %s watchpoint at " TARGET_ADDR_FMT " of length 0x%8.8" PRIx32 " (WPID: %d)", watchpoint_rw_strings[(*watchpoint_p)->rw], (*watchpoint_p)->address, @@ -475,7 +475,7 @@ static void watchpoint_free(struct target *target, struct watchpoint *watchpoint free(watchpoint); } -void watchpoint_remove(struct target *target, uint32_t address) +void watchpoint_remove(struct target *target, target_addr_t address) { struct watchpoint *watchpoint = target->watchpoints; @@ -488,7 +488,7 @@ void watchpoint_remove(struct target *target, uint32_t address) if (watchpoint) watchpoint_free(target, watchpoint); else - LOG_ERROR("no watchpoint at address 0x%8.8" PRIx32 " found", address); + LOG_ERROR("no watchpoint at address " TARGET_ADDR_FMT " found", address); } void watchpoint_clear_target(struct target *target) @@ -499,7 +499,8 @@ void watchpoint_clear_target(struct target *target) watchpoint_free(target, target->watchpoints); } -int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *address) +int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, + target_addr_t *address) { int retval; struct watchpoint *hit_watchpoint; @@ -511,7 +512,7 @@ int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *addr *rw = hit_watchpoint->rw; *address = hit_watchpoint->address; - LOG_DEBUG("Found hit watchpoint at 0x%8.8" PRIx32 " (WPID: %d)", + LOG_DEBUG("Found hit watchpoint at " TARGET_ADDR_FMT " (WPID: %d)", hit_watchpoint->address, hit_watchpoint->unique_id); diff --git a/src/target/breakpoints.h b/src/target/breakpoints.h index 842fc18..51bd05a 100644 --- a/src/target/breakpoints.h +++ b/src/target/breakpoints.h @@ -33,7 +33,7 @@ enum watchpoint_rw { }; struct breakpoint { - uint32_t address; + target_addr_t address; uint32_t asid; int length; enum breakpoint_type type; @@ -45,7 +45,7 @@ struct breakpoint { }; struct watchpoint { - uint32_t address; + target_addr_t address; uint32_t length; uint32_t mask; uint32_t value; @@ -57,22 +57,23 @@ struct watchpoint { void breakpoint_clear_target(struct target *target); int breakpoint_add(struct target *target, - uint32_t address, uint32_t length, enum breakpoint_type type); + target_addr_t address, uint32_t length, enum breakpoint_type type); int context_breakpoint_add(struct target *target, uint32_t asid, uint32_t length, enum breakpoint_type type); int hybrid_breakpoint_add(struct target *target, - uint32_t address, uint32_t asid, uint32_t length, enum breakpoint_type type); -void breakpoint_remove(struct target *target, uint32_t address); + target_addr_t address, uint32_t asid, uint32_t length, enum breakpoint_type type); +void breakpoint_remove(struct target *target, target_addr_t address); -struct breakpoint *breakpoint_find(struct target *target, uint32_t address); +struct breakpoint *breakpoint_find(struct target *target, target_addr_t address); void watchpoint_clear_target(struct target *target); int watchpoint_add(struct target *target, - uint32_t address, uint32_t length, + target_addr_t address, uint32_t length, enum watchpoint_rw rw, uint32_t value, uint32_t mask); -void watchpoint_remove(struct target *target, uint32_t address); +void watchpoint_remove(struct target *target, target_addr_t address); /* report type and address of just hit watchpoint */ -int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, uint32_t *address); +int watchpoint_hit(struct target *target, enum watchpoint_rw *rw, + target_addr_t *address); #endif /* OPENOCD_TARGET_BREAKPOINTS_H */ diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 8c8a2b7..62ac361 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -75,7 +75,7 @@ static int cortex_a_dap_write_coreregister_u32(struct target *target, static int cortex_a_mmu(struct target *target, int *enabled); static int cortex_a_mmu_modify(struct target *target, int enable); static int cortex_a_virt2phys(struct target *target, - uint32_t virt, uint32_t *phys); + target_addr_t virt, target_addr_t *phys); static int cortex_a_read_cpu_memory(struct target *target, uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); @@ -937,7 +937,7 @@ static int cortex_a_halt(struct target *target) } static int cortex_a_internal_restore(struct target *target, int current, - uint32_t *address, int handle_breakpoints, int debug_execution) + target_addr_t *address, int handle_breakpoints, int debug_execution) { struct armv7a_common *armv7a = target_to_armv7a(target); struct arm *arm = &armv7a->arm; @@ -1092,7 +1092,7 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints) int retval = 0; struct target_list *head; struct target *curr; - uint32_t address; + target_addr_t address; head = target->head; while (head != (struct target_list *)NULL) { curr = head->target; @@ -1110,7 +1110,7 @@ static int cortex_a_restore_smp(struct target *target, int handle_breakpoints) } static int cortex_a_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { int retval = 0; /* dummy resume for smp toggle in order to reduce gdb impact */ @@ -1134,11 +1134,11 @@ static int cortex_a_resume(struct target *target, int current, if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); - LOG_DEBUG("target resumed at 0x%" PRIx32, address); + LOG_DEBUG("target resumed at " TARGET_ADDR_FMT, address); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); - LOG_DEBUG("target debug resumed at 0x%" PRIx32, address); + LOG_DEBUG("target debug resumed at " TARGET_ADDR_FMT, address); } return ERROR_OK; @@ -1344,7 +1344,7 @@ int cortex_a_set_dscr_bits(struct target *target, unsigned long bit_mask, unsign return retval; } -static int cortex_a_step(struct target *target, int current, uint32_t address, +static int cortex_a_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { struct cortex_a_common *cortex_a = target_to_cortex_a(target); @@ -2639,7 +2639,7 @@ out: */ static int cortex_a_read_phys_memory(struct target *target, - uint32_t address, uint32_t size, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct armv7a_common *armv7a = target_to_armv7a(target); @@ -2650,7 +2650,7 @@ static int cortex_a_read_phys_memory(struct target *target, if (!count || !buffer) return ERROR_COMMAND_SYNTAX_ERROR; - LOG_DEBUG("Reading memory at real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, + LOG_DEBUG("Reading memory at real address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, address, size, count); if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num)) @@ -2664,14 +2664,14 @@ static int cortex_a_read_phys_memory(struct target *target, return retval; } -static int cortex_a_read_memory(struct target *target, uint32_t address, +static int cortex_a_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int retval; /* cortex_a handles unaligned memory access */ - LOG_DEBUG("Reading memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, - size, count); + LOG_DEBUG("Reading memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, + address, size, count); cortex_a_prep_memaccess(target, 0); retval = cortex_a_read_cpu_memory(target, address, size, count, buffer); @@ -2680,11 +2680,11 @@ static int cortex_a_read_memory(struct target *target, uint32_t address, return retval; } -static int cortex_a_read_memory_ahb(struct target *target, uint32_t address, +static int cortex_a_read_memory_ahb(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int mmu_enabled = 0; - uint32_t virt, phys; + target_addr_t virt, phys; int retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; @@ -2694,8 +2694,8 @@ static int cortex_a_read_memory_ahb(struct target *target, uint32_t address, return target_read_memory(target, address, size, count, buffer); /* cortex_a handles unaligned memory access */ - LOG_DEBUG("Reading memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, - size, count); + LOG_DEBUG("Reading memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, + address, size, count); /* determine if MMU was enabled on target stop */ if (!armv7a->is_armv7r) { @@ -2710,7 +2710,8 @@ static int cortex_a_read_memory_ahb(struct target *target, uint32_t address, if (retval != ERROR_OK) return retval; - LOG_DEBUG("Reading at virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32, + LOG_DEBUG("Reading at virtual address. " + "Translating v:" TARGET_ADDR_FMT " to r:" TARGET_ADDR_FMT, virt, phys); address = phys; } @@ -2724,7 +2725,7 @@ static int cortex_a_read_memory_ahb(struct target *target, uint32_t address, } static int cortex_a_write_phys_memory(struct target *target, - uint32_t address, uint32_t size, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct armv7a_common *armv7a = target_to_armv7a(target); @@ -2735,8 +2736,8 @@ static int cortex_a_write_phys_memory(struct target *target, if (!count || !buffer) return ERROR_COMMAND_SYNTAX_ERROR; - LOG_DEBUG("Writing memory to real address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, - size, count); + LOG_DEBUG("Writing memory to real address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, + address, size, count); if (armv7a->memory_ap_available && (apsel == armv7a->memory_ap->ap_num)) return mem_ap_write_buf(armv7a->memory_ap, buffer, size, count, address); @@ -2749,14 +2750,14 @@ static int cortex_a_write_phys_memory(struct target *target, return retval; } -static int cortex_a_write_memory(struct target *target, uint32_t address, +static int cortex_a_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int retval; /* cortex_a handles unaligned memory access */ - LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, - size, count); + LOG_DEBUG("Writing memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, + address, size, count); /* memory writes bypass the caches, must flush before writing */ armv7a_cache_auto_flush_on_write(target, address, size * count); @@ -2767,11 +2768,11 @@ static int cortex_a_write_memory(struct target *target, uint32_t address, return retval; } -static int cortex_a_write_memory_ahb(struct target *target, uint32_t address, +static int cortex_a_write_memory_ahb(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int mmu_enabled = 0; - uint32_t virt, phys; + target_addr_t virt, phys; int retval; struct armv7a_common *armv7a = target_to_armv7a(target); struct adiv5_dap *swjdp = armv7a->arm.dap; @@ -2781,8 +2782,8 @@ static int cortex_a_write_memory_ahb(struct target *target, uint32_t address, return target_write_memory(target, address, size, count, buffer); /* cortex_a handles unaligned memory access */ - LOG_DEBUG("Writing memory at address 0x%" PRIx32 "; size %" PRId32 "; count %" PRId32, address, - size, count); + LOG_DEBUG("Writing memory at address " TARGET_ADDR_FMT "; size %" PRId32 "; count %" PRId32, + address, size, count); /* determine if MMU was enabled on target stop */ if (!armv7a->is_armv7r) { @@ -2797,7 +2798,8 @@ static int cortex_a_write_memory_ahb(struct target *target, uint32_t address, if (retval != ERROR_OK) return retval; - LOG_DEBUG("Writing to virtual address. Translating v:0x%" PRIx32 " to r:0x%" PRIx32, + LOG_DEBUG("Writing to virtual address. " + "Translating v:" TARGET_ADDR_FMT " to r:" TARGET_ADDR_FMT, virt, phys); address = phys; @@ -2811,7 +2813,7 @@ static int cortex_a_write_memory_ahb(struct target *target, uint32_t address, return retval; } -static int cortex_a_read_buffer(struct target *target, uint32_t address, +static int cortex_a_read_buffer(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer) { uint32_t size; @@ -2845,7 +2847,7 @@ static int cortex_a_read_buffer(struct target *target, uint32_t address, return ERROR_OK; } -static int cortex_a_write_buffer(struct target *target, uint32_t address, +static int cortex_a_write_buffer(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer) { uint32_t size; @@ -3202,7 +3204,7 @@ static int cortex_a_mmu(struct target *target, int *enabled) } static int cortex_a_virt2phys(struct target *target, - uint32_t virt, uint32_t *phys) + target_addr_t virt, target_addr_t *phys) { int retval = ERROR_FAIL; struct armv7a_common *armv7a = target_to_armv7a(target); @@ -3220,7 +3222,8 @@ static int cortex_a_virt2phys(struct target *target, retval = cortex_a_mmu_modify(target, 1); if (retval != ERROR_OK) goto done; - retval = armv7a_mmu_translate_va_pa(target, virt, phys, 1); + retval = armv7a_mmu_translate_va_pa(target, (uint32_t)virt, + (uint32_t *)phys, 1); } done: return retval; diff --git a/src/target/cortex_m.c b/src/target/cortex_m.c index 36a7746..e80cd23 100644 --- a/src/target/cortex_m.c +++ b/src/target/cortex_m.c @@ -682,7 +682,7 @@ void cortex_m_enable_breakpoints(struct target *target) } static int cortex_m_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { struct armv7m_common *armv7m = target_to_armv7m(target); struct breakpoint *breakpoint = NULL; @@ -750,7 +750,7 @@ static int cortex_m_resume(struct target *target, int current, /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { - LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %" PRIu32 ")", + LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT " (ID: %" PRIu32 ")", breakpoint->address, breakpoint->unique_id); cortex_m_unset_breakpoint(target, breakpoint); @@ -782,7 +782,7 @@ static int cortex_m_resume(struct target *target, int current, /* int irqstepcount = 0; */ static int cortex_m_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { struct cortex_m_common *cortex_m = target_to_cm(target); struct armv7m_common *armv7m = &cortex_m->armv7m; @@ -1198,7 +1198,7 @@ int cortex_m_set_breakpoint(struct target *target, struct breakpoint *breakpoint breakpoint->set = true; } - LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)", + LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: " TARGET_ADDR_FMT " Length: %d (set=%d)", breakpoint->unique_id, (int)(breakpoint->type), breakpoint->address, @@ -1219,7 +1219,7 @@ int cortex_m_unset_breakpoint(struct target *target, struct breakpoint *breakpoi return ERROR_OK; } - LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: 0x%08" PRIx32 " Length: %d (set=%d)", + LOG_DEBUG("BPID: %" PRIu32 ", Type: %d, Address: " TARGET_ADDR_FMT " Length: %d (set=%d)", breakpoint->unique_id, (int)(breakpoint->type), breakpoint->address, @@ -1664,7 +1664,7 @@ static int cortex_m_store_core_reg_u32(struct target *target, return ERROR_OK; } -static int cortex_m_read_memory(struct target *target, uint32_t address, +static int cortex_m_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct armv7m_common *armv7m = target_to_armv7m(target); @@ -1678,7 +1678,7 @@ static int cortex_m_read_memory(struct target *target, uint32_t address, return mem_ap_read_buf(armv7m->debug_ap, buffer, size, count, address); } -static int cortex_m_write_memory(struct target *target, uint32_t address, +static int cortex_m_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct armv7m_common *armv7m = target_to_armv7m(target); diff --git a/src/target/dsp563xx.c b/src/target/dsp563xx.c index 783a019..1d728df 100644 --- a/src/target/dsp563xx.c +++ b/src/target/dsp563xx.c @@ -1117,7 +1117,7 @@ static int dsp563xx_halt(struct target *target) static int dsp563xx_resume(struct target *target, int current, - uint32_t address, + target_addr_t address, int handle_breakpoints, int debug_execution) { @@ -1290,7 +1290,7 @@ static int dsp563xx_step_ex(struct target *target, static int dsp563xx_step(struct target *target, int current, - uint32_t address, + target_addr_t address, int handle_breakpoints) { int err; @@ -1374,7 +1374,7 @@ static int dsp563xx_deassert_reset(struct target *target) static int dsp563xx_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 i; @@ -1592,7 +1592,7 @@ static int dsp563xx_read_memory_core(struct target *target, static int dsp563xx_read_memory(struct target *target, int mem_type, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) @@ -1660,7 +1660,7 @@ static int dsp563xx_read_memory(struct target *target, } static int dsp563xx_read_memory_default(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) @@ -1671,7 +1671,7 @@ static int dsp563xx_read_memory_default(struct target *target, } static int dsp563xx_read_buffer_default(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, uint8_t *buffer) { @@ -1682,7 +1682,7 @@ static int dsp563xx_read_buffer_default(struct target *target, static int dsp563xx_write_memory_core(struct target *target, int mem_type, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) @@ -1694,7 +1694,7 @@ static int dsp563xx_write_memory_core(struct target *target, const uint8_t *b; LOG_DEBUG( - "memtype: %d address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", + "memtype: %d address: 0x%8.8" TARGET_PRIxADDR ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", mem_type, address, size, @@ -1766,7 +1766,7 @@ static int dsp563xx_write_memory_core(struct target *target, static int dsp563xx_write_memory(struct target *target, int mem_type, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) @@ -1834,7 +1834,7 @@ static int dsp563xx_write_memory(struct target *target, } static int dsp563xx_write_memory_default(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) @@ -1844,7 +1844,7 @@ static int dsp563xx_write_memory_default(struct target *target, } static int dsp563xx_write_buffer_default(struct target *target, - uint32_t address, + target_addr_t address, uint32_t size, const uint8_t *buffer) { diff --git a/src/target/dsp5680xx.c b/src/target/dsp5680xx.c index 205d8fe..a50f2cd 100644 --- a/src/target/dsp5680xx.c +++ b/src/target/dsp5680xx.c @@ -1011,7 +1011,7 @@ static int dsp5680xx_poll(struct target *target) } static int dsp5680xx_resume(struct target *target, int current, - uint32_t address, int hb, int d) + target_addr_t address, int hb, int d) { if (target->state == TARGET_RUNNING) { LOG_USER("Target already running."); @@ -1168,7 +1168,7 @@ static int dsp5680xx_read_32_single(struct target *t, uint32_t a, return retval; } -static int dsp5680xx_read(struct target *t, uint32_t a, uint32_t size, +static int dsp5680xx_read(struct target *t, target_addr_t a, uint32_t size, uint32_t count, uint8_t *buf) { struct target *target = t; @@ -1423,7 +1423,7 @@ static int dsp5680xx_write_32(struct target *t, uint32_t a, uint32_t c, * * @return */ -static int dsp5680xx_write(struct target *t, uint32_t a, uint32_t s, uint32_t c, +static int dsp5680xx_write(struct target *t, target_addr_t a, uint32_t s, uint32_t c, const uint8_t *b) { /* TODO Cannot write 32bit to odd address, will write 0x12345678 as 0x5678 0x0012 */ @@ -1468,7 +1468,7 @@ static int dsp5680xx_write(struct target *t, uint32_t a, uint32_t s, uint32_t c, return retval; } -static int dsp5680xx_write_buffer(struct target *t, uint32_t a, uint32_t size, +static int dsp5680xx_write_buffer(struct target *t, target_addr_t a, uint32_t size, const uint8_t *b) { check_halt_and_debug(t); @@ -1485,7 +1485,7 @@ static int dsp5680xx_write_buffer(struct target *t, uint32_t a, uint32_t size, * * @return */ -static int dsp5680xx_read_buffer(struct target *t, uint32_t a, uint32_t size, +static int dsp5680xx_read_buffer(struct target *t, target_addr_t a, uint32_t size, uint8_t *buf) { check_halt_and_debug(t); @@ -1505,7 +1505,7 @@ static int dsp5680xx_read_buffer(struct target *t, uint32_t a, uint32_t size, * * @return */ -static int dsp5680xx_checksum_memory(struct target *t, uint32_t a, uint32_t s, +static int dsp5680xx_checksum_memory(struct target *t, target_addr_t a, uint32_t s, uint32_t *checksum) { return ERROR_FAIL; @@ -2262,7 +2262,7 @@ int dsp5680xx_f_lock(struct target *target) return retval; } -static int dsp5680xx_step(struct target *target, int current, uint32_t address, +static int dsp5680xx_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { err_check(ERROR_FAIL, DSP5680XX_ERROR_NOT_IMPLEMENTED_STEP, diff --git a/src/target/feroceon.c b/src/target/feroceon.c index f12e4e4..6b14ab6 100644 --- a/src/target/feroceon.c +++ b/src/target/feroceon.c @@ -460,7 +460,7 @@ static int feroceon_examine_debug_reason(struct target *target) } static int feroceon_bulk_write_memory(struct target *target, - uint32_t address, uint32_t count, const uint8_t *buffer) + target_addr_t address, uint32_t count, const uint8_t *buffer) { int retval; struct arm *arm = target->arch_info; @@ -565,7 +565,7 @@ static int feroceon_bulk_write_memory(struct target *target, buf_get_u32(arm->core_cache->reg_list[0].value, 0, 32); if (endaddress != address + count*4) { LOG_ERROR("DCC write failed," - " expected end address 0x%08" PRIx32 + " expected end address 0x%08" TARGET_PRIxADDR " got 0x%0" PRIx32 "", address + count*4, endaddress); retval = ERROR_FAIL; diff --git a/src/target/hla_target.c b/src/target/hla_target.c index feeb11f..78dc8c5 100644 --- a/src/target/hla_target.c +++ b/src/target/hla_target.c @@ -584,7 +584,7 @@ static int adapter_halt(struct target *target) } static int adapter_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, + target_addr_t address, int handle_breakpoints, int debug_execution) { int res; @@ -594,8 +594,8 @@ static int adapter_resume(struct target *target, int current, struct breakpoint *breakpoint = NULL; struct reg *pc; - LOG_DEBUG("%s %d 0x%08" PRIx32 " %d %d", __func__, current, address, - handle_breakpoints, debug_execution); + LOG_DEBUG("%s %d " TARGET_ADDR_FMT " %d %d", __func__, current, + address, handle_breakpoints, debug_execution); if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); @@ -642,7 +642,7 @@ static int adapter_resume(struct target *target, int current, /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { - LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 " (ID: %" PRIu32 ")", + LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT " (ID: %" PRIu32 ")", breakpoint->address, breakpoint->unique_id); cortex_m_unset_breakpoint(target, breakpoint); @@ -675,7 +675,7 @@ static int adapter_resume(struct target *target, int current, } static int adapter_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { int res; struct hl_interface_s *adapter = target_to_adapter(target); @@ -738,7 +738,7 @@ static int adapter_step(struct target *target, int current, return ERROR_OK; } -static int adapter_read_memory(struct target *target, uint32_t address, +static int adapter_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { @@ -747,12 +747,13 @@ static int adapter_read_memory(struct target *target, uint32_t address, if (!count || !buffer) return ERROR_COMMAND_SYNTAX_ERROR; - LOG_DEBUG("%s 0x%08" PRIx32 " %" PRIu32 " %" PRIu32, __func__, address, size, count); + LOG_DEBUG("%s " TARGET_ADDR_FMT " %" PRIu32 " %" PRIu32, + __func__, address, size, count); return adapter->layout->api->read_mem(adapter->handle, address, size, count, buffer); } -static int adapter_write_memory(struct target *target, uint32_t address, +static int adapter_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { @@ -761,7 +762,8 @@ static int adapter_write_memory(struct target *target, uint32_t address, if (!count || !buffer) return ERROR_COMMAND_SYNTAX_ERROR; - LOG_DEBUG("%s 0x%08" PRIx32 " %" PRIu32 " %" PRIu32, __func__, address, size, count); + LOG_DEBUG("%s " TARGET_ADDR_FMT " %" PRIu32 " %" PRIu32, + __func__, address, size, count); return adapter->layout->api->write_mem(adapter->handle, address, size, count, buffer); } diff --git a/src/target/image.h b/src/target/image.h index 9bf7af3..9907a5f 100644 --- a/src/target/image.h +++ b/src/target/image.h @@ -46,7 +46,7 @@ enum image_type { }; struct imagesection { - uint32_t base_address; + target_addr_t base_address; uint32_t size; int flags; void *private; /* private data */ diff --git a/src/target/lakemont.c b/src/target/lakemont.c index 27efc69..2bd12fd 100644 --- a/src/target/lakemont.c +++ b/src/target/lakemont.c @@ -994,7 +994,7 @@ int lakemont_halt(struct target *t) } } -int lakemont_resume(struct target *t, int current, uint32_t address, +int lakemont_resume(struct target *t, int current, target_addr_t address, int handle_breakpoints, int debug_execution) { struct breakpoint *bp = NULL; @@ -1036,7 +1036,7 @@ int lakemont_resume(struct target *t, int current, uint32_t address, } int lakemont_step(struct target *t, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { struct x86_32_common *x86_32 = target_to_x86_32(t); uint32_t eflags = buf_get_u32(x86_32->cache->reg_list[EFLAGS].value, 0, 32); diff --git a/src/target/lakemont.h b/src/target/lakemont.h index b07a056..98efd44 100644 --- a/src/target/lakemont.h +++ b/src/target/lakemont.h @@ -95,10 +95,10 @@ int lakemont_init_arch_info(struct target *t, struct x86_32_common *x86_32); int lakemont_poll(struct target *t); int lakemont_arch_state(struct target *t); int lakemont_halt(struct target *t); -int lakemont_resume(struct target *t, int current, uint32_t address, +int lakemont_resume(struct target *t, int current, target_addr_t address, int handle_breakpoints, int debug_execution); int lakemont_step(struct target *t, int current, - uint32_t address, int handle_breakpoints); + target_addr_t address, int handle_breakpoints); int lakemont_reset_assert(struct target *t); int lakemont_reset_deassert(struct target *t); int lakemont_update_after_probemode_entry(struct target *t); diff --git a/src/target/ls1_sap.c b/src/target/ls1_sap.c index b4d814b..bc46ed4 100644 --- a/src/target/ls1_sap.c +++ b/src/target/ls1_sap.c @@ -64,14 +64,14 @@ static int ls1_sap_halt(struct target *target) return ERROR_OK; } -static int ls1_sap_resume(struct target *target, int current, uint32_t address, +static int ls1_sap_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution) { LOG_DEBUG("%s", __func__); return ERROR_OK; } -static int ls1_sap_step(struct target *target, int current, uint32_t address, +static int ls1_sap_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { LOG_DEBUG("%s", __func__); @@ -178,10 +178,10 @@ static void ls1_sap_memory_write(struct jtag_tap *tap, uint32_t size, jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); } -static int ls1_sap_read_memory(struct target *target, uint32_t address, +static int ls1_sap_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { - LOG_DEBUG("Reading memory at physical address 0x%" PRIx32 + LOG_DEBUG("Reading memory at physical address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, address, size, count); if (count == 0 || buffer == NULL) @@ -199,11 +199,11 @@ static int ls1_sap_read_memory(struct target *target, uint32_t address, return jtag_execute_queue(); } -static int ls1_sap_write_memory(struct target *target, uint32_t address, +static int ls1_sap_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { - LOG_DEBUG("Writing memory at physical address 0x%" PRIx32 + LOG_DEBUG("Writing memory at physical address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, address, size, count); diff --git a/src/target/mips32.c b/src/target/mips32.c index 27caebe..cec4549 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -391,8 +391,8 @@ int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, s } /* run to exit point. return error if exit point was not reached. */ -static int mips32_run_and_wait(struct target *target, uint32_t entry_point, - int timeout_ms, uint32_t exit_point, struct mips32_common *mips32) +static int mips32_run_and_wait(struct target *target, target_addr_t entry_point, + int timeout_ms, target_addr_t exit_point, struct mips32_common *mips32) { uint32_t pc; int retval; @@ -425,8 +425,8 @@ static int mips32_run_and_wait(struct target *target, uint32_t entry_point, int mips32_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, int timeout_ms, void *arch_info) + struct reg_param *reg_params, target_addr_t entry_point, + target_addr_t exit_point, int timeout_ms, void *arch_info) { struct mips32_common *mips32 = target_to_mips32(target); struct mips32_algorithm *mips32_algorithm_info = arch_info; @@ -696,7 +696,7 @@ int mips32_enable_interrupts(struct target *target, int enable) return ERROR_OK; } -int mips32_checksum_memory(struct target *target, uint32_t address, +int mips32_checksum_memory(struct target *target, target_addr_t address, uint32_t count, uint32_t *checksum) { struct working_area *crc_algorithm; @@ -773,7 +773,7 @@ int mips32_checksum_memory(struct target *target, uint32_t address, /** Checks whether a memory region is erased. */ int mips32_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value) + target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value) { struct working_area *erase_check_algorithm; struct reg_param reg_params[3]; diff --git a/src/target/mips32.h b/src/target/mips32.h index d493b39..2e7067f 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -232,7 +232,7 @@ struct reg_cache *mips32_build_reg_cache(struct target *target); int mips32_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 mips32_configure_break_unit(struct target *target); @@ -246,9 +246,9 @@ int mips32_register_commands(struct command_context *cmd_ctx); int mips32_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); -int mips32_checksum_memory(struct target *target, uint32_t address, +int mips32_checksum_memory(struct target *target, target_addr_t address, uint32_t count, uint32_t *checksum); int mips32_blank_check_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *blank, uint8_t erased_value); + target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value); #endif /* OPENOCD_TARGET_MIPS32_H */ diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 7cc0424..5456e8c 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -1035,7 +1035,7 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are ejtag_info->fast_access_save = write_t; } - LOG_DEBUG("%s using 0x%.8" PRIx32 " for write handler", __func__, source->address); + LOG_DEBUG("%s using 0x%.8" TARGET_PRIxADDR " for write handler", __func__, source->address); jmp_code[0] |= UPPER16(source->address); jmp_code[1] |= LOWER16(source->address); diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index db69b95..bd3c602 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -44,7 +44,7 @@ static int mips_m4k_internal_restore(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution); static int mips_m4k_halt(struct target *target); -static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, +static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer); static int mips_m4k_examine_debug_reason(struct target *target) @@ -469,7 +469,8 @@ static int mips_m4k_internal_restore(struct target *target, int current, /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { - LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); + LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT "", + breakpoint->address); mips_m4k_unset_breakpoint(target, breakpoint); mips_m4k_single_step_core(target); mips_m4k_set_breakpoint(target, breakpoint); @@ -500,7 +501,7 @@ static int mips_m4k_internal_restore(struct target *target, int current, } static int mips_m4k_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { int retval = ERROR_OK; @@ -527,7 +528,7 @@ static int mips_m4k_resume(struct target *target, int current, } static int mips_m4k_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { /* get pointers to arch-specific information */ struct mips32_common *mips32 = target_to_mips32(target); @@ -655,7 +656,7 @@ static int mips_m4k_set_breakpoint(struct target *target, if (retval != ERROR_OK) return retval; if (verify != MIPS32_SDBBP) { - LOG_ERROR("Unable to set 32bit breakpoint at address %08" PRIx32 + LOG_ERROR("Unable to set 32-bit breakpoint at address " TARGET_ADDR_FMT " - check that memory is read/writable", breakpoint->address); return ERROR_OK; } @@ -674,7 +675,7 @@ static int mips_m4k_set_breakpoint(struct target *target, if (retval != ERROR_OK) return retval; if (verify != MIPS16_SDBBP) { - LOG_ERROR("Unable to set 16bit breakpoint at address %08" PRIx32 + LOG_ERROR("Unable to set 16-bit breakpoint at address " TARGET_ADDR_FMT " - check that memory is read/writable", breakpoint->address); return ERROR_OK; } @@ -949,13 +950,13 @@ static void mips_m4k_enable_watchpoints(struct target *target) } } -static int mips_m4k_read_memory(struct target *target, uint32_t address, +static int mips_m4k_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; - LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); if (target->state != TARGET_HALTED) { @@ -1008,13 +1009,13 @@ static int mips_m4k_read_memory(struct target *target, uint32_t address, return retval; } -static int mips_m4k_write_memory(struct target *target, uint32_t address, +static int mips_m4k_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; - LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, size, count); if (target->state != TARGET_HALTED) { @@ -1139,7 +1140,7 @@ static int mips_m4k_examine(struct target *target) return ERROR_OK; } -static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, +static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer) { struct mips32_common *mips32 = target_to_mips32(target); @@ -1148,7 +1149,8 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, int retval; int write_t = 1; - LOG_DEBUG("address: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32 "", address, count); + LOG_DEBUG("address: " TARGET_ADDR_FMT ", count: 0x%8.8" PRIx32 "", + address, count); /* check alignment */ if (address & 0x3u) @@ -1175,8 +1177,8 @@ static int mips_m4k_bulk_write_memory(struct target *target, uint32_t address, if (address <= fast_data_area->address + fast_data_area->size && fast_data_area->address <= address + count) { - LOG_ERROR("fast_data (0x%8.8" PRIx32 ") is within write area " - "(0x%8.8" PRIx32 "-0x%8.8" PRIx32 ").", + LOG_ERROR("fast_data (" TARGET_ADDR_FMT ") is within write area " + "(" TARGET_ADDR_FMT "-" TARGET_ADDR_FMT ").", fast_data_area->address, address, address + count); LOG_ERROR("Change work-area-phys or load_image address!"); return ERROR_FAIL; diff --git a/src/target/nds32.c b/src/target/nds32.c index 2926b23..e4bb17f 100644 --- a/src/target/nds32.c +++ b/src/target/nds32.c @@ -823,7 +823,7 @@ int nds32_read_memory(struct target *target, uint32_t address, return aice_read_mem_unit(aice, address, size, count, buffer); } -int nds32_read_phys_memory(struct target *target, uint32_t address, +int nds32_read_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct aice_port_s *aice = target_to_aice(target); @@ -932,7 +932,7 @@ int nds32_write_memory(struct target *target, uint32_t address, return aice_write_mem_unit(aice, address, size, count, buffer); } -int nds32_write_phys_memory(struct target *target, uint32_t address, +int nds32_write_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct aice_port_s *aice = target_to_aice(target); @@ -1674,7 +1674,7 @@ int nds32_init_arch_info(struct target *target, struct nds32 *nds32) return ERROR_OK; } -int nds32_virtual_to_physical(struct target *target, uint32_t address, uint32_t *physical) +int nds32_virtual_to_physical(struct target *target, target_addr_t address, target_addr_t *physical) { struct nds32 *nds32 = target_to_nds32(target); @@ -1692,7 +1692,7 @@ int nds32_virtual_to_physical(struct target *target, uint32_t address, uint32_t return ERROR_FAIL; } -int nds32_cache_sync(struct target *target, uint32_t address, uint32_t length) +int nds32_cache_sync(struct target *target, target_addr_t address, uint32_t length) { struct aice_port_s *aice = target_to_aice(target); struct nds32 *nds32 = target_to_nds32(target); @@ -1738,7 +1738,7 @@ int nds32_cache_sync(struct target *target, uint32_t address, uint32_t length) /* Because PSW.IT is turned off under debug exception, address MUST * be physical address. L1I_VA_INVALIDATE uses PSW.IT to decide * address translation or not. */ - uint32_t physical_addr; + target_addr_t physical_addr; if (ERROR_FAIL == target->type->virt2phys(target, cur_address, &physical_addr)) return ERROR_FAIL; @@ -1764,7 +1764,7 @@ uint32_t nds32_nextpc(struct nds32 *nds32, int current, uint32_t address) } int nds32_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { LOG_DEBUG("target->state: %s", target_state_name(target)); @@ -1778,7 +1778,7 @@ int nds32_step(struct target *target, int current, address = nds32_nextpc(nds32, current, address); - LOG_DEBUG("STEP PC %08" PRIx32 "%s", address, !current ? "!" : ""); + LOG_DEBUG("STEP PC %08" TARGET_PRIxADDR "%s", address, !current ? "!" : ""); /** set DSSIM */ uint32_t ir14_value; @@ -2120,9 +2120,9 @@ int nds32_poll(struct target *target) } int nds32_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { - LOG_DEBUG("current %d address %08" PRIx32 + LOG_DEBUG("current %d address %08" TARGET_PRIxADDR " handle_breakpoints %d" " debug_execution %d", current, address, handle_breakpoints, debug_execution); @@ -2136,7 +2136,7 @@ int nds32_resume(struct target *target, int current, address = nds32_nextpc(nds32, current, address); - LOG_DEBUG("RESUME PC %08" PRIx32 "%s", address, !current ? "!" : ""); + LOG_DEBUG("RESUME PC %08" TARGET_PRIxADDR "%s", address, !current ? "!" : ""); if (!debug_execution) target_free_all_working_areas(target); diff --git a/src/target/nds32.h b/src/target/nds32.h index 88af4f3..141dbf4 100644 --- a/src/target/nds32.h +++ b/src/target/nds32.h @@ -400,23 +400,23 @@ extern int nds32_get_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t * extern int nds32_set_mapped_reg(struct nds32 *nds32, unsigned regnum, uint32_t value); extern int nds32_edm_config(struct nds32 *nds32); -extern int nds32_cache_sync(struct target *target, uint32_t address, uint32_t length); +extern int nds32_cache_sync(struct target *target, target_addr_t address, uint32_t length); extern int nds32_mmu(struct target *target, int *enabled); -extern int nds32_virtual_to_physical(struct target *target, uint32_t address, - uint32_t *physical); -extern int nds32_read_phys_memory(struct target *target, uint32_t address, +extern int nds32_virtual_to_physical(struct target *target, target_addr_t address, + target_addr_t *physical); +extern int nds32_read_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); -extern int nds32_write_phys_memory(struct target *target, uint32_t address, +extern int nds32_write_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); extern uint32_t nds32_nextpc(struct nds32 *nds32, int current, uint32_t address); extern int nds32_examine_debug_reason(struct nds32 *nds32); extern int nds32_step(struct target *target, int current, - uint32_t address, int handle_breakpoints); + target_addr_t address, int handle_breakpoints); extern int nds32_target_state(struct nds32 *nds32, enum target_state *state); extern int nds32_halt(struct target *target); extern int nds32_poll(struct target *target); extern int nds32_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution); + target_addr_t address, int handle_breakpoints, int debug_execution); extern int nds32_assert_reset(struct target *target); extern int nds32_init(struct nds32 *nds32); extern int nds32_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *fileio_info); diff --git a/src/target/nds32_aice.c b/src/target/nds32_aice.c index bdfafb5..e494a3e 100644 --- a/src/target/nds32_aice.c +++ b/src/target/nds32_aice.c @@ -42,8 +42,8 @@ int aice_write_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t val) return aice->port->api->write_reg_64(aice->coreid, num, val); } -int aice_read_tlb(struct aice_port_s *aice, uint32_t virtual_address, - uint32_t *physical_address) +int aice_read_tlb(struct aice_port_s *aice, target_addr_t virtual_address, + target_addr_t *physical_address) { if (aice->port->api->read_tlb == NULL) { LOG_WARNING("Not implemented: %s", __func__); diff --git a/src/target/nds32_aice.h b/src/target/nds32_aice.h index ae801ed..5ea3b16 100644 --- a/src/target/nds32_aice.h +++ b/src/target/nds32_aice.h @@ -23,8 +23,8 @@ int aice_read_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t *val); int aice_write_reg_64(struct aice_port_s *aice, uint32_t num, uint64_t val); -int aice_read_tlb(struct aice_port_s *aice, uint32_t virtual_address, - uint32_t *physical_address); +int aice_read_tlb(struct aice_port_s *aice, target_addr_t virtual_address, + target_addr_t *physical_address); int aice_cache_ctl(struct aice_port_s *aice, uint32_t subtype, uint32_t address); int aice_set_retry_times(struct aice_port_s *aice, uint32_t a_retry_times); int aice_program_edm(struct aice_port_s *aice, char *command_sequence); diff --git a/src/target/nds32_tlb.c b/src/target/nds32_tlb.c index 6a91a0f..c4bce1a 100644 --- a/src/target/nds32_tlb.c +++ b/src/target/nds32_tlb.c @@ -22,8 +22,8 @@ #include "nds32_aice.h" #include "nds32_tlb.h" -int nds32_probe_tlb(struct nds32 *nds32, const uint32_t virtual_address, - uint32_t *physical_address) +int nds32_probe_tlb(struct nds32 *nds32, const target_addr_t virtual_address, + target_addr_t *physical_address) { struct target *target = nds32->target; struct aice_port_s *aice = target_to_aice(target); @@ -38,8 +38,8 @@ struct page_table_walker_info_s page_table_info[PAGE_SIZE_NUM] = { {0xFF000000, 22, 0x00FFE000, 11, 0x00001FFF, 0xFFFFF000, 0xFFFFE000, 0xFFFFE000}, }; -int nds32_walk_page_table(struct nds32 *nds32, const uint32_t virtual_address, - uint32_t *physical_address) +int nds32_walk_page_table(struct nds32 *nds32, const target_addr_t virtual_address, + target_addr_t *physical_address) { struct target *target = nds32->target; uint32_t value_mr1; diff --git a/src/target/nds32_tlb.h b/src/target/nds32_tlb.h index ada2c19..62512c1 100644 --- a/src/target/nds32_tlb.h +++ b/src/target/nds32_tlb.h @@ -39,9 +39,9 @@ struct page_table_walker_info_s { uint32_t ppn_mask; }; -extern int nds32_probe_tlb(struct nds32 *nds32, const uint32_t virtual_address, - uint32_t *physical_address); -extern int nds32_walk_page_table(struct nds32 *nds32, const uint32_t virtual_address, - uint32_t *physical_address); +extern int nds32_probe_tlb(struct nds32 *nds32, const target_addr_t virtual_address, + target_addr_t *physical_address); +extern int nds32_walk_page_table(struct nds32 *nds32, const target_addr_t virtual_address, + target_addr_t *physical_address); #endif /* OPENOCD_TARGET_NDS32_TLB_H */ diff --git a/src/target/nds32_v2.c b/src/target/nds32_v2.c index 4497551..29489a0 100644 --- a/src/target/nds32_v2.c +++ b/src/target/nds32_v2.c @@ -112,7 +112,7 @@ static int nds32_v2_activate_hardware_breakpoint(struct target *target) /* enable breakpoint (physical address) */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0xA); - LOG_DEBUG("Add hardware BP %" PRId32 " at %08" PRIx32, hbr_index, + LOG_DEBUG("Add hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index, bp->address); hbr_index++; @@ -139,7 +139,7 @@ static int nds32_v2_deactivate_hardware_breakpoint(struct target *target) else return ERROR_FAIL; - LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" PRIx32, hbr_index, + LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index, bp->address); hbr_index++; @@ -184,7 +184,7 @@ static int nds32_v2_activate_hardware_watchpoint(struct target *target) /* set value */ aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0); - LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, wp_num, + LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32, wp_num, wp->address, wp->mask); } @@ -204,7 +204,7 @@ static int nds32_v2_deactivate_hardware_watchpoint(struct target *target) /* disable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0); - LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, + LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32, wp_num, wp->address, wp->mask); } @@ -405,7 +405,7 @@ static int nds32_v2_deassert_reset(struct target *target) } static int nds32_v2_checksum_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *checksum) + target_addr_t address, uint32_t count, uint32_t *checksum) { LOG_WARNING("Not implemented: %s", __func__); @@ -561,8 +561,8 @@ static int nds32_v2_run_algorithm(struct target *target, 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) { @@ -635,11 +635,11 @@ static int nds32_v2_examine(struct target *target) return ERROR_OK; } -static int nds32_v2_translate_address(struct target *target, uint32_t *address) +static int nds32_v2_translate_address(struct target *target, target_addr_t *address) { struct nds32 *nds32 = target_to_nds32(target); struct nds32_memory *memory = &(nds32->memory); - uint32_t physical_address; + target_addr_t physical_address; /* Following conditions need to do address translation * 1. BUS mode @@ -656,7 +656,7 @@ static int nds32_v2_translate_address(struct target *target, uint32_t *address) return ERROR_OK; } -static int nds32_v2_read_buffer(struct target *target, uint32_t address, +static int nds32_v2_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); @@ -676,7 +676,7 @@ static int nds32_v2_read_buffer(struct target *target, uint32_t address, return nds32_read_buffer(target, address, size, buffer); } -static int nds32_v2_write_buffer(struct target *target, uint32_t address, +static int nds32_v2_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); @@ -696,7 +696,7 @@ static int nds32_v2_write_buffer(struct target *target, uint32_t address, return nds32_write_buffer(target, address, size, buffer); } -static int nds32_v2_read_memory(struct target *target, uint32_t address, +static int nds32_v2_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); @@ -716,7 +716,7 @@ static int nds32_v2_read_memory(struct target *target, uint32_t address, return nds32_read_memory(target, address, size, count, buffer); } -static int nds32_v2_write_memory(struct target *target, uint32_t address, +static int nds32_v2_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); diff --git a/src/target/nds32_v3.c b/src/target/nds32_v3.c index 35b72e3..e5d146b 100644 --- a/src/target/nds32_v3.c +++ b/src/target/nds32_v3.c @@ -53,7 +53,7 @@ static int nds32_v3_activate_hardware_breakpoint(struct target *target) /* enable breakpoint (physical address) */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + hbr_index, 0xA); - LOG_DEBUG("Add hardware BP %" PRId32 " at %08" PRIx32, hbr_index, + LOG_DEBUG("Add hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index, bp->address); } else { return ERROR_FAIL; @@ -81,7 +81,7 @@ static int nds32_v3_deactivate_hardware_breakpoint(struct target *target) return ERROR_FAIL; } - LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" PRIx32, hbr_index, + LOG_DEBUG("Remove hardware BP %" PRId32 " at %08" TARGET_PRIxADDR, hbr_index, bp->address); } @@ -128,7 +128,7 @@ static int nds32_v3_activate_hardware_watchpoint(struct target *target) /* set value */ aice_write_debug_reg(aice, NDS_EDM_SR_BPV0 + wp_num, 0); - LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" PRIx32 " mask %08" PRIx32, + LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; @@ -169,7 +169,7 @@ static int nds32_v3_deactivate_hardware_watchpoint(struct target *target) /* disable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0); - LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" PRIx32 + LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; diff --git a/src/target/nds32_v3_common.c b/src/target/nds32_v3_common.c index 191f4b5..271ffdd 100644 --- a/src/target/nds32_v3_common.c +++ b/src/target/nds32_v3_common.c @@ -368,7 +368,7 @@ int nds32_v3_target_request_data(struct target *target, } int nds32_v3_checksum_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *checksum) + target_addr_t address, uint32_t count, uint32_t *checksum) { LOG_WARNING("Not implemented: %s", __func__); @@ -434,8 +434,8 @@ int nds32_v3_run_algorithm(struct target *target, 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) { @@ -444,7 +444,7 @@ int nds32_v3_run_algorithm(struct target *target, return ERROR_FAIL; } -int nds32_v3_read_buffer(struct target *target, uint32_t address, +int nds32_v3_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); @@ -456,7 +456,7 @@ int nds32_v3_read_buffer(struct target *target, uint32_t address, return ERROR_TARGET_NOT_HALTED; } - uint32_t physical_address; + target_addr_t physical_address; /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ @@ -502,7 +502,7 @@ int nds32_v3_read_buffer(struct target *target, uint32_t address, return result; } -int nds32_v3_write_buffer(struct target *target, uint32_t address, +int nds32_v3_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); @@ -514,7 +514,7 @@ int nds32_v3_write_buffer(struct target *target, uint32_t address, return ERROR_TARGET_NOT_HALTED; } - uint32_t physical_address; + target_addr_t physical_address; /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ @@ -564,7 +564,7 @@ int nds32_v3_write_buffer(struct target *target, uint32_t address, return nds32_write_buffer(target, address, size, buffer); } -int nds32_v3_read_memory(struct target *target, uint32_t address, +int nds32_v3_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); @@ -576,7 +576,7 @@ int nds32_v3_read_memory(struct target *target, uint32_t address, return ERROR_TARGET_NOT_HALTED; } - uint32_t physical_address; + target_addr_t physical_address; /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ @@ -622,7 +622,7 @@ int nds32_v3_read_memory(struct target *target, uint32_t address, return result; } -int nds32_v3_write_memory(struct target *target, uint32_t address, +int nds32_v3_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct nds32 *nds32 = target_to_nds32(target); @@ -634,7 +634,7 @@ int nds32_v3_write_memory(struct target *target, uint32_t address, return ERROR_TARGET_NOT_HALTED; } - uint32_t physical_address; + target_addr_t physical_address; /* BUG: If access range crosses multiple pages, the translation will not correct * for second page or so. */ diff --git a/src/target/nds32_v3_common.h b/src/target/nds32_v3_common.h index 1f5df19..23393e5 100644 --- a/src/target/nds32_v3_common.h +++ b/src/target/nds32_v3_common.h @@ -34,7 +34,7 @@ void nds32_v3_common_register_callback(struct nds32_v3_common_callback *callback int nds32_v3_target_request_data(struct target *target, uint32_t size, uint8_t *buffer); int nds32_v3_checksum_memory(struct target *target, - uint32_t address, uint32_t count, uint32_t *checksum); + target_addr_t address, uint32_t count, uint32_t *checksum); int nds32_v3_hit_watchpoint(struct target *target, struct watchpoint **hit_watchpoint); int nds32_v3_target_create_common(struct target *target, struct nds32 *nds32); @@ -43,17 +43,17 @@ int nds32_v3_run_algorithm(struct target *target, 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 nds32_v3_read_buffer(struct target *target, uint32_t address, +int nds32_v3_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer); -int nds32_v3_write_buffer(struct target *target, uint32_t address, +int nds32_v3_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer); -int nds32_v3_read_memory(struct target *target, uint32_t address, +int nds32_v3_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); -int nds32_v3_write_memory(struct target *target, uint32_t address, +int nds32_v3_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int nds32_v3_init_target(struct command_context *cmd_ctx, struct target *target); diff --git a/src/target/nds32_v3m.c b/src/target/nds32_v3m.c index 2d52bc3..86903a5 100644 --- a/src/target/nds32_v3m.c +++ b/src/target/nds32_v3m.c @@ -50,7 +50,7 @@ static int nds32_v3m_activate_hardware_breakpoint(struct target *target) /* enable breakpoint (physical address) */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + brp_num, 0xA); - LOG_DEBUG("Add hardware BP %u at %08" PRIx32, brp_num, + LOG_DEBUG("Add hardware BP %u at %08" TARGET_PRIxADDR, brp_num, bp->address); brp_num--; @@ -78,7 +78,7 @@ static int nds32_v3m_deactivate_hardware_breakpoint(struct target *target) else return ERROR_FAIL; - LOG_DEBUG("Remove hardware BP %u at %08" PRIx32, brp_num, + LOG_DEBUG("Remove hardware BP %u at %08" TARGET_PRIxADDR, brp_num, bp->address); brp_num--; @@ -125,7 +125,7 @@ static int nds32_v3m_activate_hardware_watchpoint(struct target *target) /* enable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, wp_config); - LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" PRIx32 + LOG_DEBUG("Add hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; @@ -166,7 +166,7 @@ static int nds32_v3m_deactivate_hardware_watchpoint(struct target *target) /* disable watchpoint */ aice_write_debug_reg(aice, NDS_EDM_SR_BPC0 + wp_num, 0x0); - LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" PRIx32 + LOG_DEBUG("Remove hardware watchpoint %" PRId32 " at %08" TARGET_PRIxADDR " mask %08" PRIx32, wp_num, wp->address, wp->mask); wp_num++; } else if (nds32_v3m->nds32.global_stop) { diff --git a/src/target/openrisc/or1k.c b/src/target/openrisc/or1k.c index 2cc869f..3895ddf 100644 --- a/src/target/openrisc/or1k.c +++ b/src/target/openrisc/or1k.c @@ -861,7 +861,7 @@ static int or1k_resume_or_step(struct target *target, int current, /* Single step past breakpoint at current address */ breakpoint = breakpoint_find(target, resume_pc); if (breakpoint) { - LOG_DEBUG("Unset breakpoint at 0x%08" PRIx32, breakpoint->address); + LOG_DEBUG("Unset breakpoint at 0x%08" TARGET_PRIxADDR, breakpoint->address); retval = or1k_remove_breakpoint(target, breakpoint); if (retval != ERROR_OK) return retval; @@ -897,7 +897,8 @@ static int or1k_resume_or_step(struct target *target, int current, } static int or1k_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, + int debug_execution) { return or1k_resume_or_step(target, current, address, handle_breakpoints, @@ -906,7 +907,7 @@ static int or1k_resume(struct target *target, int current, } static int or1k_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { return or1k_resume_or_step(target, current, address, handle_breakpoints, @@ -922,7 +923,7 @@ static int or1k_add_breakpoint(struct target *target, struct or1k_du *du_core = or1k_to_du(or1k); uint8_t data; - LOG_DEBUG("Adding breakpoint: addr 0x%08" PRIx32 ", len %d, type %d, set: %d, id: %" PRId32, + LOG_DEBUG("Adding breakpoint: addr 0x%08" TARGET_PRIxADDR ", len %d, type %d, set: %d, id: %" PRId32, breakpoint->address, breakpoint->length, breakpoint->type, breakpoint->set, breakpoint->unique_id); @@ -937,7 +938,7 @@ static int or1k_add_breakpoint(struct target *target, 1, &data); if (retval != ERROR_OK) { - LOG_ERROR("Error while reading the instruction at 0x%08" PRIx32, + LOG_ERROR("Error while reading the instruction at 0x%08" TARGET_PRIxADDR, breakpoint->address); return retval; } @@ -958,14 +959,15 @@ static int or1k_add_breakpoint(struct target *target, or1k_trap_insn); if (retval != ERROR_OK) { - LOG_ERROR("Error while writing OR1K_TRAP_INSTR at 0x%08" PRIx32, + LOG_ERROR("Error while writing OR1K_TRAP_INSTR at 0x%08" TARGET_PRIxADDR, breakpoint->address); return retval; } /* invalidate instruction cache */ + uint32_t addr = breakpoint->address; retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, - OR1K_ICBIR_CPU_REG_ADD, 1, &breakpoint->address); + OR1K_ICBIR_CPU_REG_ADD, 1, &addr); if (retval != ERROR_OK) { LOG_ERROR("Error while invalidating the ICACHE"); return retval; @@ -980,7 +982,7 @@ static int or1k_remove_breakpoint(struct target *target, struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); - LOG_DEBUG("Removing breakpoint: addr 0x%08" PRIx32 ", len %d, type %d, set: %d, id: %" PRId32, + LOG_DEBUG("Removing breakpoint: addr 0x%08" TARGET_PRIxADDR ", len %d, type %d, set: %d, id: %" PRId32, breakpoint->address, breakpoint->length, breakpoint->type, breakpoint->set, breakpoint->unique_id); @@ -996,14 +998,15 @@ static int or1k_remove_breakpoint(struct target *target, breakpoint->orig_instr); if (retval != ERROR_OK) { - LOG_ERROR("Error while writing back the instruction at 0x%08" PRIx32, + LOG_ERROR("Error while writing back the instruction at 0x%08" TARGET_PRIxADDR, breakpoint->address); return retval; } /* invalidate instruction cache */ + uint32_t addr = breakpoint->address; retval = du_core->or1k_jtag_write_cpu(&or1k->jtag, - OR1K_ICBIR_CPU_REG_ADD, 1, &breakpoint->address); + OR1K_ICBIR_CPU_REG_ADD, 1, &addr); if (retval != ERROR_OK) { LOG_ERROR("Error while invalidating the ICACHE"); return retval; @@ -1026,13 +1029,13 @@ static int or1k_remove_watchpoint(struct target *target, return ERROR_OK; } -static int or1k_read_memory(struct target *target, uint32_t address, +static int or1k_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); - LOG_DEBUG("Read memory at 0x%08" PRIx32 ", size: %" PRIu32 ", count: 0x%08" PRIx32, address, size, count); + LOG_DEBUG("Read memory at 0x%08" TARGET_PRIxADDR ", size: %" PRIu32 ", count: 0x%08" PRIx32, address, size, count); if (target->state != TARGET_HALTED) { LOG_ERROR("Target not halted"); @@ -1053,13 +1056,13 @@ static int or1k_read_memory(struct target *target, uint32_t address, return du_core->or1k_jtag_read_memory(&or1k->jtag, address, size, count, buffer); } -static int or1k_write_memory(struct target *target, uint32_t address, +static int or1k_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct or1k_common *or1k = target_to_or1k(target); struct or1k_du *du_core = or1k_to_du(or1k); - LOG_DEBUG("Write memory at 0x%08" PRIx32 ", size: %" PRIu32 ", count: 0x%08" PRIx32, address, size, count); + LOG_DEBUG("Write memory at 0x%08" TARGET_PRIxADDR ", size: %" PRIu32 ", count: 0x%08" PRIx32, address, size, count); if (target->state != TARGET_HALTED) { LOG_WARNING("Target not halted"); @@ -1203,7 +1206,7 @@ int or1k_get_gdb_fileio_info(struct target *target, struct gdb_fileio_info *file return ERROR_FAIL; } -static int or1k_checksum_memory(struct target *target, uint32_t address, +static int or1k_checksum_memory(struct target *target, target_addr_t address, uint32_t count, uint32_t *checksum) { return ERROR_FAIL; diff --git a/src/target/target.c b/src/target/target.c index c8a3ce4..40baf8e 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -58,9 +58,9 @@ /* default halt wait timeout (ms) */ #define DEFAULT_HALT_TIMEOUT 5000 -static int target_read_buffer_default(struct target *target, uint32_t address, +static int target_read_buffer_default(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer); -static int target_write_buffer_default(struct target *target, uint32_t address, +static int target_write_buffer_default(struct target *target, target_addr_t address, uint32_t count, const uint8_t *buffer); static int target_array2mem(Jim_Interp *interp, struct target *target, int argc, Jim_Obj * const *argv); @@ -597,7 +597,8 @@ int target_halt(struct target *target) * hand the infrastructure for running such helpers might use this * procedure but rely on hardware breakpoint to detect termination.) */ -int target_resume(struct target *target, int current, uint32_t address, int handle_breakpoints, int debug_execution) +int target_resume(struct target *target, int current, target_addr_t address, + int handle_breakpoints, int debug_execution) { int retval; @@ -668,7 +669,7 @@ static int target_process_reset(struct command_context *cmd_ctx, enum target_res } static int identity_virt2phys(struct target *target, - uint32_t virtual, uint32_t *physical) + target_addr_t virtual, target_addr_t *physical) { *physical = virtual; return ERROR_OK; @@ -1034,7 +1035,7 @@ int target_run_flash_async_algorithm(struct target *target, } int target_read_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); @@ -1048,7 +1049,7 @@ int target_read_memory(struct target *target, } int target_read_phys_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); @@ -1062,7 +1063,7 @@ int target_read_phys_memory(struct target *target, } int target_write_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); @@ -1076,7 +1077,7 @@ int target_write_memory(struct target *target, } int target_write_phys_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer) + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); @@ -1164,7 +1165,7 @@ int target_get_gdb_reg_list(struct target *target, return target->type->get_gdb_reg_list(target, reg_list, reg_list_size, reg_class); } int target_step(struct target *target, - int current, uint32_t address, int handle_breakpoints) + int current, target_addr_t address, int handle_breakpoints) { return target->type->step(target, current, address, handle_breakpoints); } @@ -1635,7 +1636,7 @@ static void print_wa_layout(struct target *target) struct working_area *c = target->working_areas; while (c) { - LOG_DEBUG("%c%c 0x%08"PRIx32"-0x%08"PRIx32" (%"PRIu32" bytes)", + LOG_DEBUG("%c%c " TARGET_ADDR_FMT "-" TARGET_ADDR_FMT " (%" PRIu32 " bytes)", c->backup ? 'b' : ' ', c->free ? ' ' : '*', c->address, c->address + c->size - 1, c->size); c = c->next; @@ -1720,7 +1721,7 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w if (!enabled) { if (target->working_area_phys_spec) { LOG_DEBUG("MMU disabled, using physical " - "address for working memory 0x%08"PRIx32, + "address for working memory " TARGET_ADDR_FMT, target->working_area_phys); target->working_area = target->working_area_phys; } else { @@ -1731,7 +1732,7 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w } else { if (target->working_area_virt_spec) { LOG_DEBUG("MMU enabled, using virtual " - "address for working memory 0x%08"PRIx32, + "address for working memory " TARGET_ADDR_FMT, target->working_area_virt); target->working_area = target->working_area_virt; } else { @@ -1774,7 +1775,8 @@ int target_alloc_working_area_try(struct target *target, uint32_t size, struct w /* Split the working area into the requested size */ target_split_working_area(c, size); - LOG_DEBUG("allocated new working area of %"PRIu32" bytes at address 0x%08"PRIx32, size, c->address); + LOG_DEBUG("allocated new working area of %" PRIu32 " bytes at address " TARGET_ADDR_FMT, + size, c->address); if (target->backup_working_area) { if (c->backup == NULL) { @@ -1818,7 +1820,7 @@ static int target_restore_working_area(struct target *target, struct working_are if (target->backup_working_area && area->backup != NULL) { retval = target_write_memory(target, area->address, 4, area->size / 4, area->backup); if (retval != ERROR_OK) - LOG_ERROR("failed to restore %"PRIu32" bytes of working area at address 0x%08"PRIx32, + LOG_ERROR("failed to restore %" PRIu32 " bytes of working area at address " TARGET_ADDR_FMT, area->size, area->address); } @@ -1842,7 +1844,7 @@ static int target_free_working_area_restore(struct target *target, struct workin area->free = true; - LOG_DEBUG("freed %"PRIu32" bytes of working area at address 0x%08"PRIx32, + LOG_DEBUG("freed %" PRIu32 " bytes of working area at address " TARGET_ADDR_FMT, area->size, area->address); /* mark user pointer invalid */ @@ -2024,9 +2026,9 @@ static int target_profiling_default(struct target *target, uint32_t *samples, * mode respectively, otherwise data is handled as quickly as * possible */ -int target_write_buffer(struct target *target, uint32_t address, uint32_t size, const uint8_t *buffer) +int target_write_buffer(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer) { - LOG_DEBUG("writing buffer of %" PRIi32 " byte at 0x%8.8" PRIx32, + LOG_DEBUG("writing buffer of %" PRIi32 " byte at " TARGET_ADDR_FMT, size, address); if (!target_was_examined(target)) { @@ -2039,7 +2041,7 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size, if ((address + size - 1) < address) { /* GDB can request this when e.g. PC is 0xfffffffc */ - LOG_ERROR("address + size wrapped (0x%08" PRIx32 ", 0x%08" PRIx32 ")", + LOG_ERROR("address + size wrapped (" TARGET_ADDR_FMT ", 0x%08" PRIx32 ")", address, size); return ERROR_FAIL; @@ -2048,7 +2050,8 @@ int target_write_buffer(struct target *target, uint32_t address, uint32_t size, return target->type->write_buffer(target, address, size, buffer); } -static int target_write_buffer_default(struct target *target, uint32_t address, uint32_t count, const uint8_t *buffer) +static int target_write_buffer_default(struct target *target, + target_addr_t address, uint32_t count, const uint8_t *buffer) { uint32_t size; @@ -2085,9 +2088,9 @@ static int target_write_buffer_default(struct target *target, uint32_t address, * mode respectively, otherwise data is handled as quickly as * possible */ -int target_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer) +int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer) { - LOG_DEBUG("reading buffer of %" PRIi32 " byte at 0x%8.8" PRIx32, + LOG_DEBUG("reading buffer of %" PRIi32 " byte at " TARGET_ADDR_FMT, size, address); if (!target_was_examined(target)) { @@ -2100,7 +2103,7 @@ int target_read_buffer(struct target *target, uint32_t address, uint32_t size, u if ((address + size - 1) < address) { /* GDB can request this when e.g. PC is 0xfffffffc */ - LOG_ERROR("address + size wrapped (0x%08" PRIx32 ", 0x%08" PRIx32 ")", + LOG_ERROR("address + size wrapped (" TARGET_ADDR_FMT ", 0x%08" PRIx32 ")", address, size); return ERROR_FAIL; @@ -2109,7 +2112,7 @@ int target_read_buffer(struct target *target, uint32_t address, uint32_t size, u return target->type->read_buffer(target, address, size, buffer); } -static int target_read_buffer_default(struct target *target, uint32_t address, uint32_t count, uint8_t *buffer) +static int target_read_buffer_default(struct target *target, target_addr_t address, uint32_t count, uint8_t *buffer) { uint32_t size; @@ -2142,7 +2145,7 @@ static int target_read_buffer_default(struct target *target, uint32_t address, u return ERROR_OK; } -int target_checksum_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* crc) +int target_checksum_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t* crc) { uint8_t *buffer; int retval; @@ -2182,7 +2185,7 @@ int target_checksum_memory(struct target *target, uint32_t address, uint32_t siz return retval; } -int target_blank_check_memory(struct target *target, uint32_t address, uint32_t size, uint32_t* blank, +int target_blank_check_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t* blank, uint8_t erased_value) { int retval; @@ -2199,7 +2202,7 @@ int target_blank_check_memory(struct target *target, uint32_t address, uint32_t return retval; } -int target_read_u64(struct target *target, uint64_t address, uint64_t *value) +int target_read_u64(struct target *target, target_addr_t address, uint64_t *value) { uint8_t value_buf[8]; if (!target_was_examined(target)) { @@ -2211,19 +2214,19 @@ int target_read_u64(struct target *target, uint64_t address, uint64_t *value) if (retval == ERROR_OK) { *value = target_buffer_get_u64(target, value_buf); - LOG_DEBUG("address: 0x%" PRIx64 ", value: 0x%16.16" PRIx64 "", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%16.16" PRIx64 "", address, *value); } else { *value = 0x0; - LOG_DEBUG("address: 0x%" PRIx64 " failed", + LOG_DEBUG("address: " TARGET_ADDR_FMT " failed", address); } return retval; } -int target_read_u32(struct target *target, uint32_t address, uint32_t *value) +int target_read_u32(struct target *target, target_addr_t address, uint32_t *value) { uint8_t value_buf[4]; if (!target_was_examined(target)) { @@ -2235,19 +2238,19 @@ int target_read_u32(struct target *target, uint32_t address, uint32_t *value) if (retval == ERROR_OK) { *value = target_buffer_get_u32(target, value_buf); - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "", address, *value); } else { *value = 0x0; - LOG_DEBUG("address: 0x%8.8" PRIx32 " failed", + LOG_DEBUG("address: " TARGET_ADDR_FMT " failed", address); } return retval; } -int target_read_u16(struct target *target, uint32_t address, uint16_t *value) +int target_read_u16(struct target *target, target_addr_t address, uint16_t *value) { uint8_t value_buf[2]; if (!target_was_examined(target)) { @@ -2259,19 +2262,19 @@ int target_read_u16(struct target *target, uint32_t address, uint16_t *value) if (retval == ERROR_OK) { *value = target_buffer_get_u16(target, value_buf); - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%4.4" PRIx16, + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%4.4" PRIx16, address, *value); } else { *value = 0x0; - LOG_DEBUG("address: 0x%8.8" PRIx32 " failed", + LOG_DEBUG("address: " TARGET_ADDR_FMT " failed", address); } return retval; } -int target_read_u8(struct target *target, uint32_t address, uint8_t *value) +int target_read_u8(struct target *target, target_addr_t address, uint8_t *value) { if (!target_was_examined(target)) { LOG_ERROR("Target not examined yet"); @@ -2281,19 +2284,19 @@ int target_read_u8(struct target *target, uint32_t address, uint8_t *value) int retval = target_read_memory(target, address, 1, 1, value); if (retval == ERROR_OK) { - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2" PRIx8, + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8, address, *value); } else { *value = 0x0; - LOG_DEBUG("address: 0x%8.8" PRIx32 " failed", + LOG_DEBUG("address: " TARGET_ADDR_FMT " failed", address); } return retval; } -int target_write_u64(struct target *target, uint64_t address, uint64_t value) +int target_write_u64(struct target *target, target_addr_t address, uint64_t value) { int retval; uint8_t value_buf[8]; @@ -2302,7 +2305,7 @@ int target_write_u64(struct target *target, uint64_t address, uint64_t value) return ERROR_FAIL; } - LOG_DEBUG("address: 0x%" PRIx64 ", value: 0x%16.16" PRIx64 "", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%16.16" PRIx64 "", address, value); @@ -2314,7 +2317,7 @@ int target_write_u64(struct target *target, uint64_t address, uint64_t value) return retval; } -int target_write_u32(struct target *target, uint32_t address, uint32_t value) +int target_write_u32(struct target *target, target_addr_t address, uint32_t value) { int retval; uint8_t value_buf[4]; @@ -2323,7 +2326,7 @@ int target_write_u32(struct target *target, uint32_t address, uint32_t value) return ERROR_FAIL; } - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx32 "", + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "", address, value); @@ -2335,7 +2338,7 @@ int target_write_u32(struct target *target, uint32_t address, uint32_t value) return retval; } -int target_write_u16(struct target *target, uint32_t address, uint16_t value) +int target_write_u16(struct target *target, target_addr_t address, uint16_t value) { int retval; uint8_t value_buf[2]; @@ -2344,7 +2347,7 @@ int target_write_u16(struct target *target, uint32_t address, uint16_t value) return ERROR_FAIL; } - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%8.8" PRIx16, + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx16, address, value); @@ -2356,7 +2359,7 @@ int target_write_u16(struct target *target, uint32_t address, uint16_t value) return retval; } -int target_write_u8(struct target *target, uint32_t address, uint8_t value) +int target_write_u8(struct target *target, target_addr_t address, uint8_t value) { int retval; if (!target_was_examined(target)) { @@ -2364,7 +2367,7 @@ int target_write_u8(struct target *target, uint32_t address, uint8_t value) return ERROR_FAIL; } - LOG_DEBUG("address: 0x%8.8" PRIx32 ", value: 0x%2.2" PRIx8, + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8, address, value); retval = target_write_memory(target, address, 1, 1, &value); @@ -2374,6 +2377,87 @@ int target_write_u8(struct target *target, uint32_t address, uint8_t value) return retval; } +int target_write_phys_u64(struct target *target, target_addr_t address, uint64_t value) +{ + int retval; + uint8_t value_buf[8]; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%16.16" PRIx64 "", + address, + value); + + target_buffer_set_u64(target, value_buf, value); + retval = target_write_phys_memory(target, address, 8, 1, value_buf); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; +} + +int target_write_phys_u32(struct target *target, target_addr_t address, uint32_t value) +{ + int retval; + uint8_t value_buf[4]; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx32 "", + address, + value); + + target_buffer_set_u32(target, value_buf, value); + retval = target_write_phys_memory(target, address, 4, 1, value_buf); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; +} + +int target_write_phys_u16(struct target *target, target_addr_t address, uint16_t value) +{ + int retval; + uint8_t value_buf[2]; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%8.8" PRIx16, + address, + value); + + target_buffer_set_u16(target, value_buf, value); + retval = target_write_phys_memory(target, address, 2, 1, value_buf); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; +} + +int target_write_phys_u8(struct target *target, target_addr_t address, uint8_t value) +{ + int retval; + if (!target_was_examined(target)) { + LOG_ERROR("Target not examined yet"); + return ERROR_FAIL; + } + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", value: 0x%2.2" PRIx8, + address, value); + + retval = target_write_phys_memory(target, address, 1, 1, &value); + if (retval != ERROR_OK) + LOG_DEBUG("failed: %i", retval); + + return retval; +} + static int find_target(struct command_context *cmd_ctx, const char *name) { struct target *target = get_target(name); @@ -2877,9 +2961,9 @@ COMMAND_HANDLER(handle_resume_command) /* with no CMD_ARGV, resume from current pc, addr = 0, * with one arguments, addr = CMD_ARGV[0], * handle breakpoints, not debugging */ - uint32_t addr = 0; + target_addr_t addr = 0; if (CMD_ARGC == 1) { - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); current = 0; } @@ -2896,10 +2980,10 @@ COMMAND_HANDLER(handle_step_command) /* with no CMD_ARGV, step from current pc, addr = 0, * with one argument addr = CMD_ARGV[0], * handle breakpoints, debugging */ - uint32_t addr = 0; + target_addr_t addr = 0; int current_pc = 1; if (CMD_ARGC == 1) { - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); current_pc = 0; } @@ -2909,7 +2993,7 @@ COMMAND_HANDLER(handle_step_command) } static void handle_md_output(struct command_context *cmd_ctx, - struct target *target, uint32_t address, unsigned size, + struct target *target, target_addr_t address, unsigned size, unsigned count, const uint8_t *buffer) { const unsigned line_bytecnt = 32; @@ -2920,6 +3004,9 @@ static void handle_md_output(struct command_context *cmd_ctx, const char *value_fmt; switch (size) { + case 8: + value_fmt = "%16.16llx "; + break; case 4: value_fmt = "%8.8x "; break; @@ -2939,13 +3026,16 @@ static void handle_md_output(struct command_context *cmd_ctx, if (i % line_modulo == 0) { output_len += snprintf(output + output_len, sizeof(output) - output_len, - "0x%8.8x: ", - (unsigned)(address + (i*size))); + TARGET_ADDR_FMT ": ", + (address + (i * size))); } - uint32_t value = 0; + uint64_t value = 0; const uint8_t *value_ptr = buffer + i * size; switch (size) { + case 8: + value = target_buffer_get_u64(target, value_ptr); + break; case 4: value = target_buffer_get_u32(target, value_ptr); break; @@ -2973,6 +3063,9 @@ COMMAND_HANDLER(handle_md_command) unsigned size = 0; switch (CMD_NAME[2]) { + case 'd': + size = 8; + break; case 'w': size = 4; break; @@ -2988,7 +3081,7 @@ COMMAND_HANDLER(handle_md_command) bool physical = strcmp(CMD_ARGV[0], "phys") == 0; int (*fn)(struct target *target, - uint32_t address, uint32_t size_value, uint32_t count, uint8_t *buffer); + target_addr_t address, uint32_t size_value, uint32_t count, uint8_t *buffer); if (physical) { CMD_ARGC--; CMD_ARGV++; @@ -2998,8 +3091,8 @@ COMMAND_HANDLER(handle_md_command) if ((CMD_ARGC < 1) || (CMD_ARGC > 2)) return ERROR_COMMAND_SYNTAX_ERROR; - uint32_t address; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); + target_addr_t address; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); unsigned count = 1; if (CMD_ARGC == 2) @@ -3018,14 +3111,14 @@ COMMAND_HANDLER(handle_md_command) } typedef int (*target_write_fn)(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); static int target_fill_mem(struct target *target, - uint32_t address, + target_addr_t address, target_write_fn fn, unsigned data_size, /* value */ - uint32_t b, + uint64_t b, /* count */ unsigned c) { @@ -3040,6 +3133,9 @@ static int target_fill_mem(struct target *target, for (unsigned i = 0; i < chunk_size; i++) { switch (data_size) { + case 8: + target_buffer_set_u64(target, target_buf + i * data_size, b); + break; case 4: target_buffer_set_u32(target, target_buf + i * data_size, b); break; @@ -3088,11 +3184,11 @@ COMMAND_HANDLER(handle_mw_command) if ((CMD_ARGC < 2) || (CMD_ARGC > 3)) return ERROR_COMMAND_SYNTAX_ERROR; - uint32_t address; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address); + target_addr_t address; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], address); - uint32_t value; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], value); + target_addr_t value; + COMMAND_PARSE_ADDRESS(CMD_ARGV[1], value); unsigned count = 1; if (CMD_ARGC == 3) @@ -3101,6 +3197,9 @@ COMMAND_HANDLER(handle_mw_command) struct target *target = get_current_target(CMD_CTX); unsigned wordsize; switch (CMD_NAME[2]) { + case 'd': + wordsize = 8; + break; case 'w': wordsize = 4; break; @@ -3118,7 +3217,7 @@ COMMAND_HANDLER(handle_mw_command) } static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image, - uint32_t *min_address, uint32_t *max_address) + target_addr_t *min_address, target_addr_t *max_address) { if (CMD_ARGC < 1 || CMD_ARGC > 5) return ERROR_COMMAND_SYNTAX_ERROR; @@ -3126,8 +3225,8 @@ static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image, /* a base address isn't always necessary, * default to 0x0 (i.e. don't relocate) */ if (CMD_ARGC >= 2) { - uint32_t addr; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr); + target_addr_t addr; + COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr); image->base_address = addr; image->base_address_set = 1; } else @@ -3136,9 +3235,9 @@ static COMMAND_HELPER(parse_load_image_command_CMD_ARGV, struct image *image, image->start_address_set = 0; if (CMD_ARGC >= 4) - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[3], *min_address); + COMMAND_PARSE_ADDRESS(CMD_ARGV[3], *min_address); if (CMD_ARGC == 5) { - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[4], *max_address); + COMMAND_PARSE_ADDRESS(CMD_ARGV[4], *max_address); /* use size (given) to find max (required) */ *max_address += *min_address; } @@ -3154,8 +3253,8 @@ COMMAND_HANDLER(handle_load_image_command) uint8_t *buffer; size_t buf_cnt; uint32_t image_size; - uint32_t min_address = 0; - uint32_t max_address = 0xffffffff; + target_addr_t min_address = 0; + target_addr_t max_address = -1; int i; struct image image; @@ -3214,7 +3313,7 @@ COMMAND_HANDLER(handle_load_image_command) break; } image_size += length; - command_print(CMD_CTX, "%u bytes written at address 0x%8.8" PRIx32 "", + command_print(CMD_CTX, "%u bytes written at address " TARGET_ADDR_FMT "", (unsigned int)length, image.sections[i].base_address + offset); } @@ -3239,15 +3338,15 @@ COMMAND_HANDLER(handle_dump_image_command) struct fileio *fileio; uint8_t *buffer; int retval, retvaltemp; - uint32_t address, size; + target_addr_t address, size; struct duration bench; struct target *target = get_current_target(CMD_CTX); if (CMD_ARGC != 3) return ERROR_COMMAND_SYNTAX_ERROR; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], address); - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], size); + COMMAND_PARSE_ADDRESS(CMD_ARGV[1], address); + COMMAND_PARSE_ADDRESS(CMD_ARGV[2], size); uint32_t buf_size = (size > 4096) ? 4096 : size; buffer = malloc(buf_size); @@ -3328,8 +3427,8 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver duration_start(&bench); if (CMD_ARGC >= 2) { - uint32_t addr; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], addr); + target_addr_t addr; + COMMAND_PARSE_ADDRESS(CMD_ARGV[1], addr); image.base_address = addr; image.base_address_set = 1; } else { @@ -3419,7 +3518,7 @@ static COMMAND_HELPER(handle_verify_image_command_internal, enum verify_mode ver free(data); } } else { - command_print(CMD_CTX, "address 0x%08" PRIx32 " length 0x%08zx", + command_print(CMD_CTX, "address " TARGET_ADDR_FMT " length 0x%08zx", image.sections[i].base_address, buf_cnt); } @@ -3466,7 +3565,7 @@ static int handle_bp_command_list(struct command_context *cmd_ctx) if (breakpoint->type == BKPT_SOFT) { char *buf = buf_to_str(breakpoint->orig_instr, breakpoint->length, 16); - command_print(cmd_ctx, "IVA breakpoint: 0x%8.8" PRIx32 ", 0x%x, %i, 0x%s", + command_print(cmd_ctx, "IVA breakpoint: " TARGET_ADDR_FMT ", 0x%x, %i, 0x%s", breakpoint->address, breakpoint->length, breakpoint->set, buf); @@ -3477,13 +3576,13 @@ static int handle_bp_command_list(struct command_context *cmd_ctx) breakpoint->asid, breakpoint->length, breakpoint->set); else if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { - command_print(cmd_ctx, "Hybrid breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i", + command_print(cmd_ctx, "Hybrid breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i", breakpoint->address, breakpoint->length, breakpoint->set); command_print(cmd_ctx, "\t|--->linked with ContextID: 0x%8.8" PRIx32, breakpoint->asid); } else - command_print(cmd_ctx, "Breakpoint(IVA): 0x%8.8" PRIx32 ", 0x%x, %i", + command_print(cmd_ctx, "Breakpoint(IVA): " TARGET_ADDR_FMT ", 0x%x, %i", breakpoint->address, breakpoint->length, breakpoint->set); } @@ -3494,7 +3593,7 @@ static int handle_bp_command_list(struct command_context *cmd_ctx) } static int handle_bp_command_set(struct command_context *cmd_ctx, - uint32_t addr, uint32_t asid, uint32_t length, int hw) + target_addr_t addr, uint32_t asid, uint32_t length, int hw) { struct target *target = get_current_target(cmd_ctx); int retval; @@ -3502,7 +3601,7 @@ static int handle_bp_command_set(struct command_context *cmd_ctx, if (asid == 0) { retval = breakpoint_add(target, addr, length, hw); if (ERROR_OK == retval) - command_print(cmd_ctx, "breakpoint set at 0x%8.8" PRIx32 "", addr); + command_print(cmd_ctx, "breakpoint set at " TARGET_ADDR_FMT "", addr); else { LOG_ERROR("Failure setting breakpoint, the same address(IVA) is already used"); return retval; @@ -3537,7 +3636,7 @@ static int handle_bp_command_set(struct command_context *cmd_ctx, COMMAND_HANDLER(handle_bp_command) { - uint32_t addr; + target_addr_t addr; uint32_t asid; uint32_t length; int hw = BKPT_SOFT; @@ -3548,17 +3647,15 @@ COMMAND_HANDLER(handle_bp_command) case 2: asid = 0; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); case 3: if (strcmp(CMD_ARGV[2], "hw") == 0) { hw = BKPT_HARD; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); - + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], length); - asid = 0; return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); } else if (strcmp(CMD_ARGV[2], "hw_ctx") == 0) { @@ -3571,7 +3668,7 @@ COMMAND_HANDLER(handle_bp_command) case 4: hw = BKPT_HARD; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], asid); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], length); return handle_bp_command_set(CMD_CTX, addr, asid, length, hw); @@ -3586,8 +3683,8 @@ COMMAND_HANDLER(handle_rbp_command) if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - uint32_t addr; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], addr); + target_addr_t addr; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], addr); struct target *target = get_current_target(CMD_CTX); breakpoint_remove(target, addr); @@ -3603,7 +3700,7 @@ COMMAND_HANDLER(handle_wp_command) struct watchpoint *watchpoint = target->watchpoints; while (watchpoint) { - command_print(CMD_CTX, "address: 0x%8.8" PRIx32 + command_print(CMD_CTX, "address: " TARGET_ADDR_FMT ", len: 0x%8.8" PRIx32 ", r/w/a: %i, value: 0x%8.8" PRIx32 ", mask: 0x%8.8" PRIx32, @@ -3688,14 +3785,14 @@ COMMAND_HANDLER(handle_virt2phys_command) if (CMD_ARGC != 1) return ERROR_COMMAND_SYNTAX_ERROR; - uint32_t va; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], va); - uint32_t pa; + target_addr_t va; + COMMAND_PARSE_ADDRESS(CMD_ARGV[0], va); + target_addr_t pa; struct target *target = get_current_target(CMD_CTX); int retval = target->type->virt2phys(target, va, &pa); if (retval == ERROR_OK) - command_print(CMD_CTX, "Physical address 0x%08" PRIx32 "", pa); + command_print(CMD_CTX, "Physical address " TARGET_ADDR_FMT "", pa); return retval; } @@ -4771,7 +4868,7 @@ static int jim_target_md(Jim_Interp *interp, int argc, Jim_Obj *const *argv) } int (*fn)(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); fn = target_read_memory; int e; @@ -5643,7 +5740,7 @@ static const struct command_registration target_subcommand_handlers[] = { }; struct FastLoad { - uint32_t address; + target_addr_t address; uint8_t *data; int length; @@ -5670,8 +5767,8 @@ COMMAND_HANDLER(handle_fast_load_image_command) uint8_t *buffer; size_t buf_cnt; uint32_t image_size; - uint32_t min_address = 0; - uint32_t max_address = 0xffffffff; + target_addr_t min_address = 0; + target_addr_t max_address = -1; int i; struct image image; @@ -6142,6 +6239,13 @@ static const struct command_registration target_exec_command_handlers[] = { .usage = "[address]", }, { + .name = "mdd", + .handler = handle_md_command, + .mode = COMMAND_EXEC, + .help = "display memory words", + .usage = "['phys'] address [count]", + }, + { .name = "mdw", .handler = handle_md_command, .mode = COMMAND_EXEC, @@ -6163,6 +6267,13 @@ static const struct command_registration target_exec_command_handlers[] = { .usage = "['phys'] address [count]", }, { + .name = "mwd", + .handler = handle_mw_command, + .mode = COMMAND_EXEC, + .help = "write memory word", + .usage = "['phys'] address value [count]", + }, + { .name = "mww", .handler = handle_mw_command, .mode = COMMAND_EXEC, diff --git a/src/target/target.h b/src/target/target.h index e86b700..41c9333 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -93,7 +93,7 @@ enum target_endianness { }; struct working_area { - uint32_t address; + target_addr_t address; uint32_t size; bool free; uint8_t *backup; @@ -156,9 +156,9 @@ struct target { uint32_t working_area; /* working area (initialised RAM). Evaluated * upon first allocation from virtual/physical address. */ bool working_area_virt_spec; /* virtual address specified? */ - uint32_t working_area_virt; /* virtual address */ + target_addr_t working_area_virt; /* virtual address */ bool working_area_phys_spec; /* physical address specified? */ - uint32_t working_area_phys; /* physical address */ + target_addr_t working_area_phys; /* physical address */ uint32_t working_area_size; /* size in bytes */ uint32_t backup_working_area; /* whether the content of the working area has to be preserved */ struct working_area *working_areas;/* list of allocated working areas */ @@ -353,7 +353,7 @@ int target_unregister_trace_callback( * yet it is possible to detect error conditions. */ int target_poll(struct target *target); -int target_resume(struct target *target, int current, uint32_t address, +int target_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution); int target_halt(struct target *target); int target_call_event_callbacks(struct target *target, enum target_event event); @@ -474,7 +474,7 @@ int target_get_gdb_reg_list(struct target *target, * This routine is a wrapper for target->type->step. */ int target_step(struct target *target, - int current, uint32_t address, int handle_breakpoints); + int current, target_addr_t address, int handle_breakpoints); /** * Run an algorithm on the @a target given. * @@ -527,9 +527,9 @@ int target_run_flash_async_algorithm(struct target *target, * This routine is a wrapper for target->type->read_memory. */ int target_read_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); int target_read_phys_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); /** * Write @a count items of @a size bytes to the memory of @a target at * the @a address given. @a address must be aligned to @a size @@ -548,9 +548,9 @@ int target_read_phys_memory(struct target *target, * This routine is wrapper for target->type->write_memory. */ int target_write_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); int target_write_phys_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t count, const uint8_t *buffer); + target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); /* * Write to target memory using the virtual address. @@ -577,13 +577,13 @@ int target_write_phys_memory(struct target *target, * peripheral registers which do not support byte operations. */ int target_write_buffer(struct target *target, - uint32_t address, uint32_t size, const uint8_t *buffer); + target_addr_t address, uint32_t size, const uint8_t *buffer); int target_read_buffer(struct target *target, - uint32_t address, uint32_t size, uint8_t *buffer); + target_addr_t address, uint32_t size, uint8_t *buffer); int target_checksum_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t *crc); + target_addr_t address, uint32_t size, uint32_t *crc); int target_blank_check_memory(struct target *target, - uint32_t address, uint32_t size, uint32_t *blank, uint8_t erased_value); + target_addr_t address, uint32_t size, uint32_t *blank, uint8_t erased_value); int target_wait_state(struct target *target, enum target_state state, int ms); /** @@ -659,14 +659,19 @@ void target_buffer_set_u64_array(struct target *target, uint8_t *buffer, uint32_ void target_buffer_set_u32_array(struct target *target, uint8_t *buffer, uint32_t count, const uint32_t *srcbuf); void target_buffer_set_u16_array(struct target *target, uint8_t *buffer, uint32_t count, const uint16_t *srcbuf); -int target_read_u64(struct target *target, uint64_t address, uint64_t *value); -int target_read_u32(struct target *target, uint32_t address, uint32_t *value); -int target_read_u16(struct target *target, uint32_t address, uint16_t *value); -int target_read_u8(struct target *target, uint32_t address, uint8_t *value); -int target_write_u64(struct target *target, uint64_t address, uint64_t value); -int target_write_u32(struct target *target, uint32_t address, uint32_t value); -int target_write_u16(struct target *target, uint32_t address, uint16_t value); -int target_write_u8(struct target *target, uint32_t address, uint8_t value); +int target_read_u64(struct target *target, target_addr_t address, uint64_t *value); +int target_read_u32(struct target *target, target_addr_t address, uint32_t *value); +int target_read_u16(struct target *target, target_addr_t address, uint16_t *value); +int target_read_u8(struct target *target, target_addr_t address, uint8_t *value); +int target_write_u64(struct target *target, target_addr_t address, uint64_t value); +int target_write_u32(struct target *target, target_addr_t address, uint32_t value); +int target_write_u16(struct target *target, target_addr_t address, uint16_t value); +int target_write_u8(struct target *target, target_addr_t address, uint8_t value); + +int target_write_phys_u64(struct target *target, target_addr_t address, uint64_t value); +int target_write_phys_u32(struct target *target, target_addr_t address, uint32_t value); +int target_write_phys_u16(struct target *target, target_addr_t address, uint16_t value); +int target_write_phys_u8(struct target *target, target_addr_t address, uint8_t value); /* Issues USER() statements with target state information */ int target_arch_state(struct target *target); diff --git a/src/target/target_type.h b/src/target/target_type.h index 2473c62..34e2778 100644 --- a/src/target/target_type.h +++ b/src/target/target_type.h @@ -53,11 +53,10 @@ struct target_type { /* halt will log a warning, but return ERROR_OK if the target is already halted. */ int (*halt)(struct target *target); - int (*resume)(struct target *target, int current, uint32_t address, + int (*resume)(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution); - int (*step)(struct target *target, int current, uint32_t address, + int (*step)(struct target *target, int current, target_addr_t address, int handle_breakpoints); - /* target reset control. assert reset can be invoked when OpenOCD and * the target is out of sync. * @@ -111,26 +110,26 @@ struct target_type { * Target memory read callback. Do @b not call this function * directly, use target_read_memory() instead. */ - int (*read_memory)(struct target *target, uint32_t address, + int (*read_memory)(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); /** * Target memory write callback. Do @b not call this function * directly, use target_write_memory() instead. */ - int (*write_memory)(struct target *target, uint32_t address, + int (*write_memory)(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer); /* Default implementation will do some fancy alignment to improve performance, target can override */ - int (*read_buffer)(struct target *target, uint32_t address, + int (*read_buffer)(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer); /* Default implementation will do some fancy alignment to improve performance, target can override */ - int (*write_buffer)(struct target *target, uint32_t address, + int (*write_buffer)(struct target *target, target_addr_t address, uint32_t size, const uint8_t *buffer); - int (*checksum_memory)(struct target *target, uint32_t address, + int (*checksum_memory)(struct target *target, target_addr_t address, uint32_t count, uint32_t *checksum); - int (*blank_check_memory)(struct target *target, uint32_t address, + int (*blank_check_memory)(struct target *target, target_addr_t address, uint32_t count, uint32_t *blank, uint8_t erased_value); /* @@ -175,15 +174,15 @@ struct target_type { */ int (*run_algorithm)(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, - struct reg_param *reg_param, uint32_t entry_point, - uint32_t exit_point, int timeout_ms, void *arch_info); + struct reg_param *reg_param, target_addr_t entry_point, + target_addr_t exit_point, int timeout_ms, void *arch_info); int (*start_algorithm)(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, - struct reg_param *reg_param, uint32_t entry_point, - uint32_t exit_point, void *arch_info); + struct reg_param *reg_param, target_addr_t entry_point, + target_addr_t exit_point, void *arch_info); int (*wait_algorithm)(struct target *target, int num_mem_params, struct mem_param *mem_params, int num_reg_params, - struct reg_param *reg_param, uint32_t exit_point, + struct reg_param *reg_param, target_addr_t exit_point, int timeout_ms, void *arch_info); const struct command_registration *commands; @@ -233,7 +232,7 @@ struct target_type { /* translate from virtual to physical address. Default implementation is successful * no-op(i.e. virtual==physical). */ - int (*virt2phys)(struct target *target, uint32_t address, uint32_t *physical); + int (*virt2phys)(struct target *target, target_addr_t address, target_addr_t *physical); /* read directly from physical memory. caches are bypassed and untouched. * @@ -243,13 +242,13 @@ struct target_type { * * Default implementation is to call read_memory. */ - int (*read_phys_memory)(struct target *target, uint32_t phys_address, + int (*read_phys_memory)(struct target *target, target_addr_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer); /* * same as read_phys_memory, except that it writes... */ - int (*write_phys_memory)(struct target *target, uint32_t phys_address, + int (*write_phys_memory)(struct target *target, target_addr_t phys_address, uint32_t size, uint32_t count, const uint8_t *buffer); int (*mmu)(struct target *target, int *enabled); diff --git a/src/target/x86_32_common.c b/src/target/x86_32_common.c index c21167e..34f92ea 100644 --- a/src/target/x86_32_common.c +++ b/src/target/x86_32_common.c @@ -48,8 +48,8 @@ static int read_mem(struct target *t, uint32_t size, uint32_t addr, uint8_t *buf); static int write_mem(struct target *t, uint32_t size, uint32_t addr, const uint8_t *buf); -static int calcaddr_physfromlin(struct target *t, uint32_t addr, - uint32_t *physaddr); +static int calcaddr_physfromlin(struct target *t, target_addr_t addr, + target_addr_t *physaddr); static int read_phys_mem(struct target *t, uint32_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer); static int write_phys_mem(struct target *t, uint32_t phys_address, @@ -113,7 +113,7 @@ int x86_32_common_mmu(struct target *t, int *enabled) return ERROR_OK; } -int x86_32_common_virt2phys(struct target *t, uint32_t address, uint32_t *physical) +int x86_32_common_virt2phys(struct target *t, target_addr_t address, target_addr_t *physical) { struct x86_32_common *x86_32 = target_to_x86_32(t); @@ -135,7 +135,7 @@ int x86_32_common_virt2phys(struct target *t, uint32_t address, uint32_t *physic } else { /* target halted in protected mode */ if (calcaddr_physfromlin(t, address, physical) != ERROR_OK) { - LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32, + LOG_ERROR("%s failed to calculate physical address from " TARGET_ADDR_FMT, __func__, address); return ERROR_FAIL; } @@ -143,7 +143,7 @@ int x86_32_common_virt2phys(struct target *t, uint32_t address, uint32_t *physic return ERROR_OK; } -int x86_32_common_read_phys_mem(struct target *t, uint32_t phys_address, +int x86_32_common_read_phys_mem(struct target *t, target_addr_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer) { struct x86_32_common *x86_32 = target_to_x86_32(t); @@ -226,7 +226,7 @@ static int read_phys_mem(struct target *t, uint32_t phys_address, return retval; } -int x86_32_common_write_phys_mem(struct target *t, uint32_t phys_address, +int x86_32_common_write_phys_mem(struct target *t, target_addr_t phys_address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct x86_32_common *x86_32 = target_to_x86_32(t); @@ -235,7 +235,7 @@ int x86_32_common_write_phys_mem(struct target *t, uint32_t phys_address, check_not_halted(t); if (!count || !buffer || !phys_address) { - LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32, + LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=" TARGET_ADDR_FMT, __func__, count, buffer, phys_address); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -444,7 +444,7 @@ static int write_mem(struct target *t, uint32_t size, return retval; } -int calcaddr_physfromlin(struct target *t, uint32_t addr, uint32_t *physaddr) +int calcaddr_physfromlin(struct target *t, target_addr_t addr, target_addr_t *physaddr) { uint8_t entry_buffer[8]; @@ -568,16 +568,16 @@ int calcaddr_physfromlin(struct target *t, uint32_t addr, uint32_t *physaddr) return ERROR_OK; } -int x86_32_common_read_memory(struct target *t, uint32_t addr, +int x86_32_common_read_memory(struct target *t, target_addr_t addr, uint32_t size, uint32_t count, uint8_t *buf) { int retval = ERROR_OK; struct x86_32_common *x86_32 = target_to_x86_32(t); - LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p", + LOG_DEBUG("addr=" TARGET_ADDR_FMT ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p", addr, size, count, buf); check_not_halted(t); if (!count || !buf || !addr) { - LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32, + LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=" TARGET_ADDR_FMT, __func__, count, buf, addr); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -591,9 +591,10 @@ int x86_32_common_read_memory(struct target *t, uint32_t addr, LOG_ERROR("%s could not disable paging", __func__); return retval; } - uint32_t physaddr = 0; + target_addr_t physaddr = 0; if (calcaddr_physfromlin(t, addr, &physaddr) != ERROR_OK) { - LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32, __func__, addr); + LOG_ERROR("%s failed to calculate physical address from " TARGET_ADDR_FMT, + __func__, addr); retval = ERROR_FAIL; } /* TODO: !!! Watch out for page boundaries @@ -603,7 +604,8 @@ int x86_32_common_read_memory(struct target *t, uint32_t addr, if (retval == ERROR_OK && x86_32_common_read_phys_mem(t, physaddr, size, count, buf) != ERROR_OK) { - LOG_ERROR("%s failed to read memory from physical address 0x%08" PRIx32, __func__, physaddr); + LOG_ERROR("%s failed to read memory from physical address " TARGET_ADDR_FMT, + __func__, physaddr); retval = ERROR_FAIL; } /* restore PG bit if it was cleared prior (regardless of retval) */ @@ -615,7 +617,8 @@ int x86_32_common_read_memory(struct target *t, uint32_t addr, } else { /* paging is off - linear address is physical address */ if (x86_32_common_read_phys_mem(t, addr, size, count, buf) != ERROR_OK) { - LOG_ERROR("%s failed to read memory from address 0%08" PRIx32, __func__, addr); + LOG_ERROR("%s failed to read memory from address " TARGET_ADDR_FMT, + __func__, addr); retval = ERROR_FAIL; } } @@ -623,16 +626,16 @@ int x86_32_common_read_memory(struct target *t, uint32_t addr, return retval; } -int x86_32_common_write_memory(struct target *t, uint32_t addr, +int x86_32_common_write_memory(struct target *t, target_addr_t addr, uint32_t size, uint32_t count, const uint8_t *buf) { int retval = ERROR_OK; struct x86_32_common *x86_32 = target_to_x86_32(t); - LOG_DEBUG("addr=0x%08" PRIx32 ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p", + LOG_DEBUG("addr=" TARGET_ADDR_FMT ", size=%" PRIu32 ", count=0x%" PRIx32 ", buf=%p", addr, size, count, buf); check_not_halted(t); if (!count || !buf || !addr) { - LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=0x%08" PRIx32, + LOG_ERROR("%s invalid params count=0x%" PRIx32 ", buf=%p, addr=" TARGET_ADDR_FMT, __func__, count, buf, addr); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -645,9 +648,9 @@ int x86_32_common_write_memory(struct target *t, uint32_t addr, LOG_ERROR("%s could not disable paging", __func__); return retval; } - uint32_t physaddr = 0; + target_addr_t physaddr = 0; if (calcaddr_physfromlin(t, addr, &physaddr) != ERROR_OK) { - LOG_ERROR("%s failed to calculate physical address from 0x%08" PRIx32, + LOG_ERROR("%s failed to calculate physical address from " TARGET_ADDR_FMT, __func__, addr); retval = ERROR_FAIL; } @@ -657,7 +660,7 @@ int x86_32_common_write_memory(struct target *t, uint32_t addr, */ if (retval == ERROR_OK && x86_32_common_write_phys_mem(t, physaddr, size, count, buf) != ERROR_OK) { - LOG_ERROR("%s failed to write memory to physical address 0x%08" PRIx32, + LOG_ERROR("%s failed to write memory to physical address " TARGET_ADDR_FMT, __func__, physaddr); retval = ERROR_FAIL; } @@ -671,7 +674,7 @@ int x86_32_common_write_memory(struct target *t, uint32_t addr, /* paging is off - linear address is physical address */ if (x86_32_common_write_phys_mem(t, addr, size, count, buf) != ERROR_OK) { - LOG_ERROR("%s failed to write memory to address 0x%08" PRIx32, + LOG_ERROR("%s failed to write memory to address " TARGET_ADDR_FMT, __func__, addr); retval = ERROR_FAIL; } @@ -852,7 +855,7 @@ int x86_32_common_remove_watchpoint(struct target *t, struct watchpoint *wp) int x86_32_common_add_breakpoint(struct target *t, struct breakpoint *bp) { - LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address); + LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address); if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; /* set_breakpoint() will return ERROR_TARGET_RESOURCE_NOT_AVAILABLE if all @@ -863,7 +866,7 @@ int x86_32_common_add_breakpoint(struct target *t, struct breakpoint *bp) int x86_32_common_remove_breakpoint(struct target *t, struct breakpoint *bp) { - LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address); + LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address); if (check_not_halted(t)) return ERROR_TARGET_NOT_HALTED; if (bp->set) @@ -1003,7 +1006,7 @@ static int unset_hwbp(struct target *t, struct breakpoint *bp) debug_reg_list[hwbp_num].used = 0; debug_reg_list[hwbp_num].bp_value = 0; - LOG_USER("%s hardware breakpoint %" PRIu32 " removed from 0x%08" PRIx32 " (hwreg=%d)", + LOG_USER("%s hardware breakpoint %" PRIu32 " removed from " TARGET_ADDR_FMT " (hwreg=%d)", __func__, bp->unique_id, bp->address, hwbp_num); return ERROR_OK; } @@ -1012,7 +1015,7 @@ static int set_swbp(struct target *t, struct breakpoint *bp) { struct x86_32_common *x86_32 = target_to_x86_32(t); LOG_DEBUG("id %" PRIx32, bp->unique_id); - uint32_t physaddr; + target_addr_t physaddr; uint8_t opcode = SW_BP_OPCODE; uint8_t readback; @@ -1032,7 +1035,7 @@ static int set_swbp(struct target *t, struct breakpoint *bp) return ERROR_FAIL; if (readback != SW_BP_OPCODE) { - LOG_ERROR("%s software breakpoint error at 0x%08" PRIx32 ", check memory", + LOG_ERROR("%s software breakpoint error at " TARGET_ADDR_FMT ", check memory", __func__, bp->address); LOG_ERROR("%s readback=0x%02" PRIx8 " orig=0x%02" PRIx8 "", __func__, readback, *bp->orig_instr); @@ -1059,7 +1062,7 @@ static int set_swbp(struct target *t, struct breakpoint *bp) addto = addto->next; addto->next = new_patch; } - LOG_USER("%s software breakpoint %" PRIu32 " set at 0x%08" PRIx32, + LOG_USER("%s software breakpoint %" PRIu32 " set at " TARGET_ADDR_FMT, __func__, bp->unique_id, bp->address); return ERROR_OK; } @@ -1068,7 +1071,7 @@ static int unset_swbp(struct target *t, struct breakpoint *bp) { struct x86_32_common *x86_32 = target_to_x86_32(t); LOG_DEBUG("id %" PRIx32, bp->unique_id); - uint32_t physaddr; + target_addr_t physaddr; uint8_t current_instr; /* check that user program has not modified breakpoint instruction */ @@ -1081,7 +1084,7 @@ static int unset_swbp(struct target *t, struct breakpoint *bp) if (write_phys_mem(t, physaddr, 1, 1, bp->orig_instr)) return ERROR_FAIL; } else { - LOG_ERROR("%s software breakpoint remove error at 0x%08" PRIx32 ", check memory", + LOG_ERROR("%s software breakpoint remove error at " TARGET_ADDR_FMT ", check memory", __func__, bp->address); LOG_ERROR("%s current=0x%02" PRIx8 " orig=0x%02" PRIx8 "", __func__, current_instr, *bp->orig_instr); @@ -1107,7 +1110,7 @@ static int unset_swbp(struct target *t, struct breakpoint *bp) } } - LOG_USER("%s software breakpoint %" PRIu32 " removed from 0x%08" PRIx32, + LOG_USER("%s software breakpoint %" PRIu32 " removed from " TARGET_ADDR_FMT, __func__, bp->unique_id, bp->address); return ERROR_OK; } @@ -1116,7 +1119,7 @@ static int set_breakpoint(struct target *t, struct breakpoint *bp) { int error = ERROR_OK; struct x86_32_common *x86_32 = target_to_x86_32(t); - LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address); + LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address); if (bp->set) { LOG_ERROR("breakpoint already set"); return error; @@ -1124,7 +1127,7 @@ static int set_breakpoint(struct target *t, struct breakpoint *bp) if (bp->type == BKPT_HARD) { error = set_hwbp(t, bp); if (error != ERROR_OK) { - LOG_ERROR("%s error setting hardware breakpoint at 0x%08" PRIx32, + LOG_ERROR("%s error setting hardware breakpoint at " TARGET_ADDR_FMT, __func__, bp->address); return error; } @@ -1132,7 +1135,7 @@ static int set_breakpoint(struct target *t, struct breakpoint *bp) if (x86_32->sw_bpts_supported(t)) { error = set_swbp(t, bp); if (error != ERROR_OK) { - LOG_ERROR("%s error setting software breakpoint at 0x%08" PRIx32, + LOG_ERROR("%s error setting software breakpoint at " TARGET_ADDR_FMT, __func__, bp->address); return error; } @@ -1147,7 +1150,7 @@ static int set_breakpoint(struct target *t, struct breakpoint *bp) static int unset_breakpoint(struct target *t, struct breakpoint *bp) { - LOG_DEBUG("type=%d, addr=0x%08" PRIx32, bp->type, bp->address); + LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, bp->type, bp->address); if (!bp->set) { LOG_WARNING("breakpoint not set"); return ERROR_OK; @@ -1155,13 +1158,13 @@ static int unset_breakpoint(struct target *t, struct breakpoint *bp) if (bp->type == BKPT_HARD) { if (unset_hwbp(t, bp) != ERROR_OK) { - LOG_ERROR("%s error removing hardware breakpoint at 0x%08" PRIx32, + LOG_ERROR("%s error removing hardware breakpoint at " TARGET_ADDR_FMT, __func__, bp->address); return ERROR_FAIL; } } else { if (unset_swbp(t, bp) != ERROR_OK) { - LOG_ERROR("%s error removing software breakpoint at 0x%08" PRIx32, + LOG_ERROR("%s error removing software breakpoint at " TARGET_ADDR_FMT, __func__, bp->address); return ERROR_FAIL; } @@ -1175,7 +1178,7 @@ static int set_watchpoint(struct target *t, struct watchpoint *wp) struct x86_32_common *x86_32 = target_to_x86_32(t); struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list; int wp_num = 0; - LOG_DEBUG("type=%d, addr=0x%08" PRIx32, wp->rw, wp->address); + LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, wp->rw, wp->address); if (wp->set) { LOG_ERROR("%s watchpoint already set", __func__); @@ -1220,7 +1223,7 @@ static int set_watchpoint(struct target *t, struct watchpoint *wp) wp->set = wp_num + 1; debug_reg_list[wp_num].used = 1; debug_reg_list[wp_num].bp_value = wp->address; - LOG_USER("'%s' watchpoint %d set at 0x%08" PRIx32 " with length %" PRIu32 " (hwreg=%d)", + LOG_USER("'%s' watchpoint %d set at " TARGET_ADDR_FMT " with length %" PRIu32 " (hwreg=%d)", wp->rw == WPT_READ ? "read" : wp->rw == WPT_WRITE ? "write" : wp->rw == WPT_ACCESS ? "access" : "?", wp->unique_id, wp->address, wp->length, wp_num); @@ -1231,7 +1234,7 @@ static int unset_watchpoint(struct target *t, struct watchpoint *wp) { struct x86_32_common *x86_32 = target_to_x86_32(t); struct x86_32_dbg_reg *debug_reg_list = x86_32->hw_break_list; - LOG_DEBUG("type=%d, addr=0x%08" PRIx32, wp->rw, wp->address); + LOG_DEBUG("type=%d, addr=" TARGET_ADDR_FMT, wp->rw, wp->address); if (!wp->set) { LOG_WARNING("watchpoint not set"); return ERROR_OK; @@ -1249,7 +1252,7 @@ static int unset_watchpoint(struct target *t, struct watchpoint *wp) debug_reg_list[wp_num].bp_value = 0; wp->set = 0; - LOG_USER("'%s' watchpoint %d removed from 0x%08" PRIx32 " with length %" PRIu32 " (hwreg=%d)", + LOG_USER("'%s' watchpoint %d removed from " TARGET_ADDR_FMT " with length %" PRIu32 " (hwreg=%d)", wp->rw == WPT_READ ? "read" : wp->rw == WPT_WRITE ? "write" : wp->rw == WPT_ACCESS ? "access" : "?", wp->unique_id, wp->address, wp->length, wp_num); diff --git a/src/target/x86_32_common.h b/src/target/x86_32_common.h index b5877da..0aaa963 100644 --- a/src/target/x86_32_common.h +++ b/src/target/x86_32_common.h @@ -309,14 +309,14 @@ int x86_32_get_gdb_reg_list(struct target *t, int x86_32_common_init_arch_info(struct target *target, struct x86_32_common *x86_32); int x86_32_common_mmu(struct target *t, int *enabled); -int x86_32_common_virt2phys(struct target *t, uint32_t address, uint32_t *physical); -int x86_32_common_read_phys_mem(struct target *t, uint32_t phys_address, +int x86_32_common_virt2phys(struct target *t, target_addr_t address, target_addr_t *physical); +int x86_32_common_read_phys_mem(struct target *t, target_addr_t phys_address, uint32_t size, uint32_t count, uint8_t *buffer); -int x86_32_common_write_phys_mem(struct target *t, uint32_t phys_address, +int x86_32_common_write_phys_mem(struct target *t, target_addr_t phys_address, uint32_t size, uint32_t count, const uint8_t *buffer); -int x86_32_common_read_memory(struct target *t, uint32_t addr, +int x86_32_common_read_memory(struct target *t, target_addr_t addr, uint32_t size, uint32_t count, uint8_t *buf); -int x86_32_common_write_memory(struct target *t, uint32_t addr, +int x86_32_common_write_memory(struct target *t, target_addr_t addr, uint32_t size, uint32_t count, const uint8_t *buf); int x86_32_common_read_io(struct target *t, uint32_t addr, uint32_t size, uint8_t *buf); diff --git a/src/target/xscale.c b/src/target/xscale.c index e54033f..8fe8a2c 100644 --- a/src/target/xscale.c +++ b/src/target/xscale.c @@ -59,7 +59,7 @@ /* forward declarations */ static int xscale_resume(struct target *, int current, - uint32_t address, int handle_breakpoints, int debug_execution); + target_addr_t address, int handle_breakpoints, int debug_execution); static int xscale_debug_entry(struct target *); static int xscale_restore_banked(struct target *); static int xscale_get_reg(struct reg *reg); @@ -1120,7 +1120,7 @@ static void xscale_free_trace_data(struct xscale_common *xscale) } static int xscale_resume(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { struct xscale_common *xscale = target_to_xscale(target); struct arm *arm = &xscale->arm; @@ -1165,7 +1165,8 @@ static int xscale_resume(struct target *target, int current, enum trace_mode saved_trace_mode; /* there's a breakpoint at the current PC, we have to step over it */ - LOG_DEBUG("unset breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); + LOG_DEBUG("unset breakpoint at " TARGET_ADDR_FMT "", + breakpoint->address); xscale_unset_breakpoint(target, breakpoint); /* calculate PC of next instruction */ @@ -1222,7 +1223,8 @@ static int xscale_resume(struct target *target, int current, LOG_DEBUG("disable single-step"); xscale_disable_single_step(target); - LOG_DEBUG("set breakpoint at 0x%8.8" PRIx32 "", breakpoint->address); + LOG_DEBUG("set breakpoint at " TARGET_ADDR_FMT "", + breakpoint->address); xscale_set_breakpoint(target, breakpoint); } } @@ -1384,7 +1386,7 @@ static int xscale_step_inner(struct target *target, int current, } static int xscale_step(struct target *target, int current, - uint32_t address, int handle_breakpoints) + target_addr_t address, int handle_breakpoints) { struct arm *arm = target_to_arm(target); struct breakpoint *breakpoint = NULL; @@ -1778,7 +1780,7 @@ dirty: return ERROR_OK; } -static int xscale_read_memory(struct target *target, uint32_t address, +static int xscale_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct xscale_common *xscale = target_to_xscale(target); @@ -1786,7 +1788,7 @@ static int xscale_read_memory(struct target *target, uint32_t address, uint32_t i; int retval; - LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32, + LOG_DEBUG("address: " TARGET_ADDR_FMT ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32, address, size, count); @@ -1864,7 +1866,7 @@ static int xscale_read_memory(struct target *target, uint32_t address, return ERROR_OK; } -static int xscale_read_phys_memory(struct target *target, uint32_t address, +static int xscale_read_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { struct xscale_common *xscale = target_to_xscale(target); @@ -1879,13 +1881,13 @@ static int xscale_read_phys_memory(struct target *target, uint32_t address, return ERROR_FAIL; } -static int xscale_write_memory(struct target *target, uint32_t address, +static int xscale_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct xscale_common *xscale = target_to_xscale(target); int retval; - LOG_DEBUG("address: 0x%8.8" PRIx32 ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32, + LOG_DEBUG("address: " TARGET_ADDR_FMT ", size: 0x%8.8" PRIx32 ", count: 0x%8.8" PRIx32, address, size, count); @@ -1963,7 +1965,7 @@ static int xscale_write_memory(struct target *target, uint32_t address, return ERROR_OK; } -static int xscale_write_phys_memory(struct target *target, uint32_t address, +static int xscale_write_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { struct xscale_common *xscale = target_to_xscale(target); @@ -3093,7 +3095,7 @@ COMMAND_HANDLER(xscale_handle_cache_info_command) } static int xscale_virt2phys(struct target *target, - uint32_t virtual, uint32_t *physical) + target_addr_t virtual, target_addr_t *physical) { struct xscale_common *xscale = target_to_xscale(target); uint32_t cb; -- cgit v1.1 From ea45db5c8a3f4329e870d695cb571251b5aa3102 Mon Sep 17 00:00:00 2001 From: David Ung Date: Fri, 16 Jan 2015 17:22:00 -0800 Subject: server: Allow 64 address to be send over GBD server Accept 64 bit addresses from GDB read memory packet. Also allow breakpoint/stepping addresses to take 64bit values. Change-Id: I9bf7b44affe24839cf30897c55ad17fdd29edf14 Signed-off-by: David Ung Signed-off-by: Matthias Welwarsky --- src/server/gdb_server.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/src/server/gdb_server.c b/src/server/gdb_server.c index c293f5b..483e551 100644 --- a/src/server/gdb_server.c +++ b/src/server/gdb_server.c @@ -1355,7 +1355,7 @@ static int gdb_read_memory_packet(struct connection *connection, { struct target *target = get_target_from_connection(connection); char *separator; - uint32_t addr = 0; + uint64_t addr = 0; uint32_t len = 0; uint8_t *buffer; @@ -1366,7 +1366,7 @@ static int gdb_read_memory_packet(struct connection *connection, /* skip command character */ packet++; - addr = strtoul(packet, &separator, 16); + addr = strtoull(packet, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete read memory packet received, dropping connection"); @@ -1383,7 +1383,7 @@ static int gdb_read_memory_packet(struct connection *connection, buffer = malloc(len); - LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len); + LOG_DEBUG("addr: 0x%16.16" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len); retval = target_read_buffer(target, addr, len, buffer); @@ -1426,7 +1426,7 @@ static int gdb_write_memory_packet(struct connection *connection, { struct target *target = get_target_from_connection(connection); char *separator; - uint32_t addr = 0; + uint64_t addr = 0; uint32_t len = 0; uint8_t *buffer; @@ -1435,7 +1435,7 @@ static int gdb_write_memory_packet(struct connection *connection, /* skip command character */ packet++; - addr = strtoul(packet, &separator, 16); + addr = strtoull(packet, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete write memory packet received, dropping connection"); @@ -1451,7 +1451,7 @@ static int gdb_write_memory_packet(struct connection *connection, buffer = malloc(len); - LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len); + LOG_DEBUG("addr: 0x%" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len); if (unhexify(buffer, separator, len) != len) LOG_ERROR("unable to decode memory packet"); @@ -1473,7 +1473,7 @@ static int gdb_write_memory_binary_packet(struct connection *connection, { struct target *target = get_target_from_connection(connection); char *separator; - uint32_t addr = 0; + uint64_t addr = 0; uint32_t len = 0; int retval = ERROR_OK; @@ -1485,7 +1485,7 @@ static int gdb_write_memory_binary_packet(struct connection *connection, /* skip command character */ packet++; - addr = strtoul(packet, &separator, 16); + addr = strtoull(packet, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete write memory binary packet received, dropping connection"); @@ -1523,7 +1523,7 @@ static int gdb_write_memory_binary_packet(struct connection *connection, } if (len) { - LOG_DEBUG("addr: 0x%8.8" PRIx32 ", len: 0x%8.8" PRIx32 "", addr, len); + LOG_DEBUG("addr: 0x%" PRIx64 ", len: 0x%8.8" PRIx32 "", addr, len); retval = target_write_buffer(target, addr, len, (uint8_t *)separator); if (retval != ERROR_OK) @@ -1547,13 +1547,13 @@ static int gdb_step_continue_packet(struct connection *connection, { struct target *target = get_target_from_connection(connection); int current = 0; - uint32_t address = 0x0; + uint64_t address = 0x0; int retval = ERROR_OK; LOG_DEBUG("-"); if (packet_size > 1) - address = strtoul(packet + 1, NULL, 16); + address = strtoull(packet + 1, NULL, 16); else current = 1; @@ -1577,7 +1577,7 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, int type; enum breakpoint_type bp_type = BKPT_SOFT /* dummy init to avoid warning */; enum watchpoint_rw wp_type = WPT_READ /* dummy init to avoid warning */; - uint32_t address; + uint64_t address; uint32_t size; char *separator; int retval; @@ -1609,7 +1609,7 @@ static int gdb_breakpoint_watchpoint_packet(struct connection *connection, return ERROR_SERVER_REMOTE_CLOSED; } - address = strtoul(separator + 1, &separator, 16); + address = strtoull(separator + 1, &separator, 16); if (*separator != ',') { LOG_ERROR("incomplete breakpoint/watchpoint packet received, dropping connection"); -- cgit v1.1 From 9cbfc9feb35ce0fcc9bb67a4d83b02100ee65f88 Mon Sep 17 00:00:00 2001 From: David Ung Date: Fri, 3 Apr 2015 16:55:59 -0700 Subject: arm_dpm: Add new state ARM_STATE_AARCH64 Add new enum ARM_STATE_AARCH64 to the list of possible states. Change-Id: I3cb2df70f8d5803a63d8374bf3eb75de988e24f8 Signed-off-by: David Ung Signed-off-by: Matthias Welwarsky --- src/target/arm.h | 1 + src/target/arm_dpm.c | 4 ++++ src/target/cortex_a.c | 3 +++ 3 files changed, 8 insertions(+) diff --git a/src/target/arm.h b/src/target/arm.h index 77a2f7b..5713fc0 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -78,6 +78,7 @@ enum arm_state { ARM_STATE_THUMB, ARM_STATE_JAZELLE, ARM_STATE_THUMB_EE, + ARM_STATE_AARCH64, }; #define ARM_COMMON_MAGIC 0x0A450A45 diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index 62c6175..3b18719 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -165,6 +165,9 @@ static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) /* core-specific ... ? */ LOG_WARNING("Jazelle PC adjustment unknown"); break; + case ARM_STATE_AARCH64: + LOG_ERROR("AARCH64: 32bit read requested"); + break; } break; default: @@ -905,6 +908,7 @@ void arm_dpm_report_wfar(struct arm_dpm *dpm, uint32_t addr) addr -= 4; break; case ARM_STATE_JAZELLE: + case ARM_STATE_AARCH64: /* ?? */ break; } diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 62ac361..1cf6656 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -992,6 +992,9 @@ static int cortex_a_internal_restore(struct target *target, int current, case ARM_STATE_JAZELLE: LOG_ERROR("How do I resume into Jazelle state??"); return ERROR_FAIL; + case ARM_STATE_AARCH64: + LOG_ERROR("Shoudn't be in AARCH64 state"); + return ERROR_FAIL; } LOG_DEBUG("resume pc = 0x%08" PRIx32, resume_pc); buf_set_u32(arm->pc->value, 0, 32, resume_pc); -- cgit v1.1 From 84a0bb4a3c3c883b22f95abc7f1428faef3936f1 Mon Sep 17 00:00:00 2001 From: David Ung Date: Fri, 16 Jan 2015 18:04:06 -0800 Subject: arm_dpm: Add 64bit register handling. Add various function to read/write ARMv8 registers. Change-Id: I16f2829bdd0e87b050a51e414ff675d5c21bcbae Signed-off-by: David Ung Signed-off-by: Matthias Welwarsky --- src/target/arm_dpm.c | 333 ++++++++++++++++++++++++++++++++++++++------------- src/target/arm_dpm.h | 10 ++ 2 files changed, 257 insertions(+), 86 deletions(-) diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index 3b18719..0c84be5 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -130,11 +130,11 @@ int dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) return retval; } -/* just read the register -- rely on the core mode being right */ -static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) + +static int dpm_read_reg32(struct arm_dpm *dpm, struct reg *r, unsigned regnum) { uint32_t value; - int retval; + int retval = ERROR_FAIL; switch (regnum) { case 0 ... 14: @@ -190,10 +190,57 @@ static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) return retval; } -/* just write the register -- rely on the core mode being right */ -static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +static int dpm_read_reg64(struct arm_dpm *dpm, struct reg *r, unsigned regnum) { - int retval; + uint64_t value; + uint32_t i; + int retval = ERROR_FAIL; + + switch (regnum) { + case 0 ... 30: + i = 0xd5130400 + regnum; /* msr dbgdtr_el0,reg */ + retval = dpm->instr_read_data_dcc_64(dpm, i, &value); + break; + case 31: /* SP */ + i = 0x910003e0; + retval = dpm->instr_read_data_r0_64(dpm, i, &value); + break; + case 32: /* PC */ + i = 0xd53b4520; + retval = dpm->instr_read_data_r0_64(dpm, i, &value); + break; + case 33: /* CPSR */ + i = 0xd53b4500; + retval = dpm->instr_read_data_r0_64(dpm, i, &value); + break; + + default: + break; + } + + if (retval == ERROR_OK) { + buf_set_u64(r->value, 0, 64, value); + r->valid = true; + r->dirty = false; + LOG_DEBUG("READ: %s, %16.16llx", r->name, (long long)value); + } + + return retval; +} + + +/* just read the register -- rely on the core mode being right */ +static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +{ + if (r->size == 64) + return dpm_read_reg64(dpm, r, regnum); + else + return dpm_read_reg32(dpm, r, regnum); +} + +static int dpm_write_reg32(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +{ + int retval = ERROR_FAIL; uint32_t value = buf_get_u32(r->value, 0, 32); switch (regnum) { @@ -243,19 +290,46 @@ static int dpm_write_pc_core_state(struct arm_dpm *dpm, struct reg *r) return dpm->instr_write_data_r0(dpm, ARMV4_5_BX(0), value); } -/** - * Read basic registers of the the current context: R0 to R15, and CPSR; - * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb). - * In normal operation this is called on entry to halting debug state, - * possibly after some other operations supporting restore of debug state - * or making sure the CPU is fully idle (drain write buffer, etc). - */ -int arm_dpm_read_current_registers(struct arm_dpm *dpm) +static int dpm_write_reg64(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +{ + int retval = ERROR_FAIL; + uint32_t i; + uint64_t value = buf_get_u64(r->value, 0, 64); + + switch (regnum) { + case 0 ... 30: + i = 0xd5330400 + regnum; + retval = dpm->instr_write_data_dcc(dpm, i, value); + break; + + default: + break; + } + + if (retval == ERROR_OK) { + r->dirty = false; + LOG_DEBUG("WRITE: %s, %16.16llx", r->name, (unsigned long long)value); + } + + return retval; +} + +/* just write the register -- rely on the core mode being right */ +static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +{ + if (r->size == 64) + return dpm_write_reg64(dpm, r, regnum); + else + return dpm_write_reg32(dpm, r, regnum); +} + +static int arm_dpm_read_current_registers_i(struct arm_dpm *dpm) { struct arm *arm = dpm->arm; - uint32_t cpsr; + uint32_t cpsr, instr, core_regs; int retval; struct reg *r; + enum arm_state core_state = arm->core_state; retval = dpm->prepare(dpm); if (retval != ERROR_OK) @@ -270,16 +344,22 @@ int arm_dpm_read_current_registers(struct arm_dpm *dpm) } r->dirty = true; - retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRS(0, 0), &cpsr); + if (core_state == ARM_STATE_AARCH64) + instr = 0xd53b4500; /* mrs x0, dspsr_el0 */ + else + instr = ARMV4_5_MRS(0, 0); + retval = dpm->instr_read_data_r0(dpm, instr, &cpsr); if (retval != ERROR_OK) goto fail; /* update core mode and state, plus shadow mapping for R8..R14 */ arm_set_cpsr(arm, cpsr); + core_regs = arm->core_cache->num_regs; + /* REVISIT we can probably avoid reading R1..R14, saving time... */ - for (unsigned i = 1; i < 16; i++) { - r = arm_reg_current(arm, i); + for (unsigned i = 1; i < core_regs; i++) { + r = dpm->arm_reg_current(arm, i); if (r->valid) continue; @@ -300,6 +380,23 @@ fail: return retval; } +/** + * Read basic registers of the the current context: R0 to R15, and CPSR; + * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb). + * In normal operation this is called on entry to halting debug state, + * possibly after some other operations supporting restore of debug state + * or making sure the CPU is fully idle (drain write buffer, etc). + */ +int arm_dpm_read_current_registers(struct arm_dpm *dpm) +{ + return arm_dpm_read_current_registers_i(dpm); +} + +int arm_dpm_read_current_registers_64(struct arm_dpm *dpm) +{ + return arm_dpm_read_current_registers_i(dpm); +} + /* Avoid needless I/O ... leave breakpoints and watchpoints alone * unless they're removed, or need updating because of single-stepping * or running debugger code. @@ -348,59 +445,14 @@ done: static int dpm_add_breakpoint(struct target *target, struct breakpoint *bp); -/** - * Writes all modified core registers for all processor modes. In normal - * operation this is called on exit from halting debug state. - * - * @param dpm: represents the processor - * @param bpwp: true ensures breakpoints and watchpoints are set, - * false ensures they are cleared - */ -int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) + +static int arm_dpm_write_dirty_registers_32(struct arm_dpm *dpm) { struct arm *arm = dpm->arm; struct reg_cache *cache = arm->core_cache; int retval; bool did_write; - retval = dpm->prepare(dpm); - if (retval != ERROR_OK) - goto done; - - /* If we're managing hardware breakpoints for this core, enable - * or disable them as requested. - * - * REVISIT We don't yet manage them for ANY cores. Eventually - * we should be able to assume we handle them; but until then, - * cope with the hand-crafted breakpoint code. - */ - if (arm->target->type->add_breakpoint == dpm_add_breakpoint) { - for (unsigned i = 0; i < dpm->nbp; i++) { - struct dpm_bp *dbp = dpm->dbp + i; - struct breakpoint *bp = dbp->bp; - - retval = dpm_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp, - bp ? &bp->set : NULL); - if (retval != ERROR_OK) - goto done; - } - } - - /* enable/disable watchpoints */ - for (unsigned i = 0; i < dpm->nwp; i++) { - struct dpm_wp *dwp = dpm->dwp + i; - struct watchpoint *wp = dwp->wp; - - retval = dpm_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp, - wp ? &wp->set : NULL); - if (retval != ERROR_OK) - goto done; - } - - /* NOTE: writes to breakpoint and watchpoint registers might - * be queued, and need (efficient/batched) flushing later. - */ - /* Scan the registers until we find one that's both dirty and * eligible for flushing. Flush that and everything else that * shares the same core mode setting. Typically this won't @@ -436,20 +488,20 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) /* cope with special cases */ switch (regnum) { - case 8 ... 12: - /* r8..r12 "anything but FIQ" case; - * we "know" core mode is accurate - * since we haven't changed it yet - */ - if (arm->core_mode == ARM_MODE_FIQ - && ARM_MODE_ANY - != mode) - tmode = ARM_MODE_USR; - break; - case 16: - /* SPSR */ - regnum++; - break; + case 8 ... 12: + /* r8..r12 "anything but FIQ" case; + * we "know" core mode is accurate + * since we haven't changed it yet + */ + if (arm->core_mode == ARM_MODE_FIQ + && ARM_MODE_ANY + != mode) + tmode = ARM_MODE_USR; + break; + case 16: + /* SPSR */ + regnum++; + break; } /* REVISIT error checks */ @@ -463,8 +515,8 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) continue; retval = dpm_write_reg(dpm, - &cache->reg_list[i], - regnum); + &cache->reg_list[i], + regnum); if (retval != ERROR_OK) goto done; } @@ -504,6 +556,106 @@ int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) goto done; cache->reg_list[0].dirty = false; +done: + return retval; +} + +static int arm_dpm_write_dirty_registers_64(struct arm_dpm *dpm) +{ + struct arm *arm = dpm->arm; + struct reg_cache *cache = arm->core_cache; + int retval; + + /* Scan the registers until we find one that's both dirty and + * eligible for flushing. Flush that and everything else that + * shares the same core mode setting. Typically this won't + * actually find anything to do... + */ + + /* check everything except our scratch register R0 */ + for (unsigned i = 1; i < 32; i++) { + struct arm_reg *r; + unsigned regnum; + + if (!cache->reg_list[i].dirty) + continue; + + r = cache->reg_list[i].arch_info; + regnum = r->num; + retval = dpm_write_reg(dpm, + &cache->reg_list[i], + regnum); + if (retval != ERROR_OK) + goto done; + } + + /* flush R0 -- it's *very* dirty by now */ + retval = dpm_write_reg(dpm, &cache->reg_list[0], 0); + if (retval != ERROR_OK) + goto done; + cache->reg_list[0].dirty = false; + +done: + return retval; +} + +/** + * Writes all modified core registers for all processor modes. In normal + * operation this is called on exit from halting debug state. + * + * @param dpm: represents the processor + * @param bpwp: true ensures breakpoints and watchpoints are set, + * false ensures they are cleared + */ +int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) +{ + struct arm *arm = dpm->arm; + struct reg_cache *cache = arm->core_cache; + int retval; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + + /* If we're managing hardware breakpoints for this core, enable + * or disable them as requested. + * + * REVISIT We don't yet manage them for ANY cores. Eventually + * we should be able to assume we handle them; but until then, + * cope with the hand-crafted breakpoint code. + */ + if (arm->target->type->add_breakpoint == dpm_add_breakpoint) { + for (unsigned i = 0; i < dpm->nbp; i++) { + struct dpm_bp *dbp = dpm->dbp + i; + struct breakpoint *bp = dbp->bp; + + retval = dpm_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp, + bp ? &bp->set : NULL); + if (retval != ERROR_OK) + goto done; + } + } + + /* enable/disable watchpoints */ + for (unsigned i = 0; i < dpm->nwp; i++) { + struct dpm_wp *dwp = dpm->dwp + i; + struct watchpoint *wp = dwp->wp; + + retval = dpm_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp, + wp ? &wp->set : NULL); + if (retval != ERROR_OK) + goto done; + } + + /* NOTE: writes to breakpoint and watchpoint registers might + * be queued, and need (efficient/batched) flushing later. + */ + + if (cache->reg_list[0].size == 64) + retval = arm_dpm_write_dirty_registers_64(dpm); + else + retval = arm_dpm_write_dirty_registers_32(dpm); + /* (void) */ dpm->finish(dpm); done: return retval; @@ -973,8 +1125,8 @@ int arm_dpm_setup(struct arm_dpm *dpm) /* register access setup */ arm->full_context = arm_dpm_full_context; - arm->read_core_reg = arm_dpm_read_core_reg; - arm->write_core_reg = arm_dpm_write_core_reg; + arm->read_core_reg = arm->read_core_reg ? : arm_dpm_read_core_reg; + arm->write_core_reg = arm->write_core_reg ? : arm_dpm_write_core_reg; /* avoid duplicating the register cache */ if (arm->core_cache == NULL) { @@ -999,12 +1151,21 @@ int arm_dpm_setup(struct arm_dpm *dpm) target->type->add_watchpoint = dpm_add_watchpoint; target->type->remove_watchpoint = dpm_remove_watchpoint; + + if (dpm->arm_reg_current == 0) + dpm->arm_reg_current = arm_reg_current; + /* FIXME add vector catch support */ - dpm->nbp = 1 + ((dpm->didr >> 24) & 0xf); - dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp); + if (arm->core_state == ARM_STATE_AARCH64) { + dpm->nbp = 1 + ((dpm->didr >> 24) & 0xf); + dpm->nwp = 1 + ((dpm->didr >> 28) & 0xf); + } else { + dpm->nbp = 1 + ((dpm->didr >> 12) & 0xf); + dpm->nwp = 1 + ((dpm->didr >> 20) & 0xf); + } - dpm->nwp = 1 + ((dpm->didr >> 28) & 0xf); + dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp); dpm->dwp = calloc(dpm->nwp, sizeof *dpm->dwp); if (!dpm->dbp || !dpm->dwp) { diff --git a/src/target/arm_dpm.h b/src/target/arm_dpm.h index bbcae78..9cc0304 100644 --- a/src/target/arm_dpm.h +++ b/src/target/arm_dpm.h @@ -86,10 +86,19 @@ struct arm_dpm { int (*instr_read_data_dcc)(struct arm_dpm *, uint32_t opcode, uint32_t *data); + int (*instr_read_data_dcc_64)(struct arm_dpm *, + uint32_t opcode, uint64_t *data); + /** Runs one instruction, reading data from r0 after execution. */ int (*instr_read_data_r0)(struct arm_dpm *, uint32_t opcode, uint32_t *data); + int (*instr_read_data_r0_64)(struct arm_dpm *, + uint32_t opcode, uint64_t *data); + + struct reg *(*arm_reg_current)(struct arm *arm, + unsigned regnum); + /* BREAKPOINT/WATCHPOINT SUPPORT */ /** @@ -131,6 +140,7 @@ int arm_dpm_setup(struct arm_dpm *dpm); int arm_dpm_initialize(struct arm_dpm *dpm); int arm_dpm_read_current_registers(struct arm_dpm *); +int arm_dpm_read_current_registers_64(struct arm_dpm *); int dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode); -- cgit v1.1 From d376f7f51831ca8816bb4aca00076b0668462775 Mon Sep 17 00:00:00 2001 From: David Ung Date: Thu, 15 Jan 2015 17:22:20 -0800 Subject: aarch64: Add ARMv8 AARCH64 support files Add new AARCH64 target and ARMv8 support files. This is an instantiation from the cortex_a files but modified to support 64bit ARMv8. Not all features are complete, notably breakpts and single stepping are not yet implemented. Currently it lets you halt of the processors, resume, dump cpu registers, read/write memory and getting a stack trace with gdb. > halt invalid mode value encountered 5 target state: halted unrecognized psr mode: 0x5 target halted in ARM state due to debug-request, current mode: UNRECOGNIZED cpsr: 0x600001c5 pc: 0x00093528 MMU: disabled, D-Cache: disabled, I-Cache: disabled > targets TargetName Type Endian TapName State -- ------------------ ---------- ------ ------------------ ------------ 0* cpu0 aarch64 little cpu.dap halted > reg ===== arm v8 registers (0) r0 (/64): 0x00000000FFFFFFED (dirty) (1) r1 (/64): 0x00000000F76E4000 (2) r2 (/64): 0x0000000000000000 (3) r3 (/64): 0x0000000000010000 (4) r4 (/64): 0xFFFFFFC06E2939E1 (5) r5 (/64): 0x0000000000000018 (6) r6 (/64): 0x003A699CFB3C8480 (7) r7 (/64): 0x0000000053555555 (8) r8 (/64): 0x00FFFFFFFFFFFFFF (9) r9 (/64): 0x000000001FFEF992 (10) r10 (/64): 0x0000000000000001 (11) r11 (/64): 0x0000000000000000 (12) r12 (/64): 0x00000000000000F0 (13) r13 (/64): 0x00000000EFDFEAC8 (14) r14 (/64): 0x00000000F6DDA659 (15) r15 (/64): 0x0000000000000000 (16) r16 (/64): 0xFFFFFFC0000F9094 (17) r17 (/64): 0x0000000000000000 (18) r18 (/64): 0x0000000000000000 (19) r19 (/64): 0xFFFFFFC00087C000 (20) r20 (/64): 0x0000000000000002 (21) r21 (/64): 0xFFFFFFC000867C28 (22) r22 (/64): 0xFFFFFFC000916A52 (23) r23 (/64): 0xFFFFFFC00116D8B0 (24) r24 (/64): 0xFFFFFFC000774A0C (25) r25 (/64): 0x000000008007B000 (26) r26 (/64): 0x000000008007D000 (27) r27 (/64): 0xFFFFFFC000080450 (28) r28 (/64): 0x0000004080000000 (29) r29 (/64): 0xFFFFFFC00087FF20 (30) r30 (/64): 0xFFFFFFC000085114 (31) sp (/64): 0xFFFFFFC00087FF20 (32) pc (/64): 0xFFFFFFC000093528 (33) xPSR (/64): 0x00000000600001C5 And from gdb (gdb) bt #0 cpu_do_idle () at /mnt/host/source/src/third_party/kernel/3.14/arch/arm64/mm/proc.S:87 #1 0xffffffc000085114 in arch_cpu_idle () at /mnt/host/source/src/third_party/kernel/3.14/arch/arm64/kernel/process.c:107 #2 0x0000000000000000 in ?? () Change-Id: Iccb1d15c7d8ace7b9e811dac3c9757ced4d0f618 Signed-off-by: David Ung Signed-off-by: Matthias Welwarsky --- src/target/Makefile.am | 10 + src/target/aarch64.c | 2601 ++++++++++++++++++++++++++++++++++++++++++++++++ src/target/aarch64.h | 78 ++ src/target/arm.h | 5 + src/target/arm_dpm.c | 30 +- src/target/arm_dpm.h | 7 + src/target/armv8.c | 774 ++++++++++++++ src/target/armv8.h | 201 ++++ src/target/target.c | 4 + 9 files changed, 3701 insertions(+), 9 deletions(-) create mode 100644 src/target/aarch64.c create mode 100644 src/target/aarch64.h create mode 100644 src/target/armv8.c create mode 100644 src/target/armv8.h diff --git a/src/target/Makefile.am b/src/target/Makefile.am index eb0d62e..a17496c 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -26,6 +26,10 @@ noinst_LTLIBRARIES += %D%/libtarget.la %D%/dsp5680xx.c \ %D%/hla_target.c +if TARGET64 +%C%_libtarget_la_SOURCES +=$(ARMV8_SRC) +endif + TARGET_CORE_SRC = \ %D%/algorithm.c \ %D%/register.c \ @@ -69,6 +73,10 @@ ARMV7_SRC = \ %D%/cortex_a.c \ %D%/ls1_sap.c +ARMV8_SRC = \ + %D%/aarch64.c \ + %D%/armv8.c + ARM_DEBUG_SRC = \ %D%/arm_dpm.c \ %D%/arm_jtag.c \ @@ -146,6 +154,7 @@ INTEL_IA32_SRC = \ %D%/armv7a.h \ %D%/armv7m.h \ %D%/armv7m_trace.h \ + %D%/armv8.h \ %D%/avrt.h \ %D%/dsp563xx.h \ %D%/dsp563xx_once.h \ @@ -153,6 +162,7 @@ INTEL_IA32_SRC = \ %D%/breakpoints.h \ %D%/cortex_m.h \ %D%/cortex_a.h \ + %D%/aarch64.h \ %D%/embeddedice.h \ %D%/etb.h \ %D%/etm.h \ diff --git a/src/target/aarch64.c b/src/target/aarch64.c new file mode 100644 index 0000000..8ac64eb --- /dev/null +++ b/src/target/aarch64.c @@ -0,0 +1,2601 @@ +/*************************************************************************** + * Copyright (C) 2015 by David Ung * + * * + * 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., * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "breakpoints.h" +#include "aarch64.h" +#include "register.h" +#include "target_request.h" +#include "target_type.h" +#include "arm_opcodes.h" +#include + +static int aarch64_poll(struct target *target); +static int aarch64_debug_entry(struct target *target); +static int aarch64_restore_context(struct target *target, bool bpwp); +static int aarch64_set_breakpoint(struct target *target, + struct breakpoint *breakpoint, uint8_t matchmode); +static int aarch64_set_context_breakpoint(struct target *target, + struct breakpoint *breakpoint, uint8_t matchmode); +static int aarch64_set_hybrid_breakpoint(struct target *target, + struct breakpoint *breakpoint); +static int aarch64_unset_breakpoint(struct target *target, + struct breakpoint *breakpoint); +static int aarch64_mmu(struct target *target, int *enabled); +static int aarch64_virt2phys(struct target *target, + target_addr_t virt, target_addr_t *phys); +static int aarch64_read_apb_ab_memory(struct target *target, + uint64_t address, uint32_t size, uint32_t count, uint8_t *buffer); +static int aarch64_instr_write_data_r0(struct arm_dpm *dpm, + uint32_t opcode, uint32_t data); + +static int aarch64_restore_system_control_reg(struct target *target) +{ + int retval = ERROR_OK; + + struct aarch64_common *aarch64 = target_to_aarch64(target); + struct armv8_common *armv8 = target_to_armv8(target); + + if (aarch64->system_control_reg != aarch64->system_control_reg_curr) { + aarch64->system_control_reg_curr = aarch64->system_control_reg; + retval = aarch64_instr_write_data_r0(armv8->arm.dpm, + 0xd5181000, + aarch64->system_control_reg); + } + + return retval; +} + +/* check address before aarch64_apb read write access with mmu on + * remove apb predictible data abort */ +static int aarch64_check_address(struct target *target, uint32_t address) +{ + /* TODO */ + return ERROR_OK; +} +/* modify system_control_reg in order to enable or disable mmu for : + * - virt2phys address conversion + * - read or write memory in phys or virt address */ +static int aarch64_mmu_modify(struct target *target, int enable) +{ + struct aarch64_common *aarch64 = target_to_aarch64(target); + struct armv8_common *armv8 = &aarch64->armv8_common; + int retval = ERROR_OK; + + if (enable) { + /* if mmu enabled at target stop and mmu not enable */ + if (!(aarch64->system_control_reg & 0x1U)) { + LOG_ERROR("trying to enable mmu on target stopped with mmu disable"); + return ERROR_FAIL; + } + if (!(aarch64->system_control_reg_curr & 0x1U)) { + aarch64->system_control_reg_curr |= 0x1U; + retval = aarch64_instr_write_data_r0(armv8->arm.dpm, + 0xd5181000, + aarch64->system_control_reg_curr); + } + } else { + if (aarch64->system_control_reg_curr & 0x4U) { + /* data cache is active */ + aarch64->system_control_reg_curr &= ~0x4U; + /* flush data cache armv7 function to be called */ + if (armv8->armv8_mmu.armv8_cache.flush_all_data_cache) + armv8->armv8_mmu.armv8_cache.flush_all_data_cache(target); + } + if ((aarch64->system_control_reg_curr & 0x1U)) { + aarch64->system_control_reg_curr &= ~0x1U; + retval = aarch64_instr_write_data_r0(armv8->arm.dpm, + 0xd5181000, + aarch64->system_control_reg_curr); + } + } + return retval; +} + +/* + * Basic debug access, very low level assumes state is saved + */ +static int aarch64_init_debug_access(struct target *target) +{ + struct armv8_common *armv8 = target_to_armv8(target); + int retval; + uint32_t dummy; + + LOG_DEBUG(" "); + + /* Unlocking the debug registers for modification + * The debugport might be uninitialised so try twice */ + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55); + if (retval != ERROR_OK) { + /* try again */ + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55); + if (retval == ERROR_OK) + LOG_USER("Locking debug access failed on first, but succeeded on second try."); + } + if (retval != ERROR_OK) + return retval; + /* Clear Sticky Power Down status Bit in PRSR to enable access to + the registers in the Core Power Domain */ + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_PRSR, &dummy); + if (retval != ERROR_OK) + return retval; + + /* Enabling of instruction execution in debug mode is done in debug_entry code */ + + /* Resync breakpoint registers */ + + /* Since this is likely called from init or reset, update target state information*/ + return aarch64_poll(target); +} + +/* To reduce needless round-trips, pass in a pointer to the current + * DSCR value. Initialize it to zero if you just need to know the + * value on return from this function; or DSCR_INSTR_COMP if you + * happen to know that no instruction is pending. + */ +static int aarch64_exec_opcode(struct target *target, + uint32_t opcode, uint32_t *dscr_p) +{ + uint32_t dscr; + int retval; + struct armv8_common *armv8 = target_to_armv8(target); + dscr = dscr_p ? *dscr_p : 0; + + LOG_DEBUG("exec opcode 0x%08" PRIx32, opcode); + + /* Wait for InstrCompl bit to be set */ + long long then = timeval_ms(); + while ((dscr & DSCR_INSTR_COMP) == 0) { + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + if (retval != ERROR_OK) { + LOG_ERROR("Could not read DSCR register, opcode = 0x%08" PRIx32, opcode); + return retval; + } + if (timeval_ms() > then + 1000) { + LOG_ERROR("Timeout waiting for aarch64_exec_opcode"); + return ERROR_FAIL; + } + } + + retval = mem_ap_write_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_ITR, opcode); + if (retval != ERROR_OK) + return retval; + + then = timeval_ms(); + do { + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + if (retval != ERROR_OK) { + LOG_ERROR("Could not read DSCR register"); + return retval; + } + if (timeval_ms() > then + 1000) { + LOG_ERROR("Timeout waiting for aarch64_exec_opcode"); + return ERROR_FAIL; + } + } while ((dscr & DSCR_INSTR_COMP) == 0); /* Wait for InstrCompl bit to be set */ + + if (dscr_p) + *dscr_p = dscr; + + return retval; +} + +/* Write to memory mapped registers directly with no cache or mmu handling */ +static int aarch64_dap_write_memap_register_u32(struct target *target, + uint32_t address, + uint32_t value) +{ + int retval; + struct armv8_common *armv8 = target_to_armv8(target); + + retval = mem_ap_write_atomic_u32(armv8->debug_ap, address, value); + + return retval; +} + +/* + * AARCH64 implementation of Debug Programmer's Model + * + * NOTE the invariant: these routines return with DSCR_INSTR_COMP set, + * so there's no need to poll for it before executing an instruction. + * + * NOTE that in several of these cases the "stall" mode might be useful. + * It'd let us queue a few operations together... prepare/finish might + * be the places to enable/disable that mode. + */ + +static inline struct aarch64_common *dpm_to_a8(struct arm_dpm *dpm) +{ + return container_of(dpm, struct aarch64_common, armv8_common.dpm); +} + +static int aarch64_write_dcc(struct aarch64_common *a8, uint32_t data) +{ + LOG_DEBUG("write DCC 0x%08" PRIx32, data); + return mem_ap_write_u32(a8->armv8_common.debug_ap, + a8->armv8_common.debug_base + CPUDBG_DTRRX, data); +} + +static int aarch64_write_dcc_64(struct aarch64_common *a8, uint64_t data) +{ + int ret; + LOG_DEBUG("write DCC 0x%08" PRIx32, (unsigned)data); + LOG_DEBUG("write DCC 0x%08" PRIx32, (unsigned)(data >> 32)); + ret = mem_ap_write_u32(a8->armv8_common.debug_ap, + a8->armv8_common.debug_base + CPUDBG_DTRRX, data); + ret += mem_ap_write_u32(a8->armv8_common.debug_ap, + a8->armv8_common.debug_base + CPUDBG_DTRTX, data >> 32); + return ret; +} + +static int aarch64_read_dcc(struct aarch64_common *a8, uint32_t *data, + uint32_t *dscr_p) +{ + uint32_t dscr = DSCR_INSTR_COMP; + int retval; + + if (dscr_p) + dscr = *dscr_p; + + /* Wait for DTRRXfull */ + long long then = timeval_ms(); + while ((dscr & DSCR_DTR_TX_FULL) == 0) { + retval = mem_ap_read_atomic_u32(a8->armv8_common.debug_ap, + a8->armv8_common.debug_base + CPUDBG_DSCR, + &dscr); + if (retval != ERROR_OK) + return retval; + if (timeval_ms() > then + 1000) { + LOG_ERROR("Timeout waiting for read dcc"); + return ERROR_FAIL; + } + } + + retval = mem_ap_read_atomic_u32(a8->armv8_common.debug_ap, + a8->armv8_common.debug_base + CPUDBG_DTRTX, + data); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("read DCC 0x%08" PRIx32, *data); + + if (dscr_p) + *dscr_p = dscr; + + return retval; +} +static int aarch64_read_dcc_64(struct aarch64_common *a8, uint64_t *data, + uint32_t *dscr_p) +{ + uint32_t dscr = DSCR_INSTR_COMP; + uint32_t higher; + int retval; + + if (dscr_p) + dscr = *dscr_p; + + /* Wait for DTRRXfull */ + long long then = timeval_ms(); + while ((dscr & DSCR_DTR_TX_FULL) == 0) { + retval = mem_ap_read_atomic_u32(a8->armv8_common.debug_ap, + a8->armv8_common.debug_base + CPUDBG_DSCR, + &dscr); + if (retval != ERROR_OK) + return retval; + if (timeval_ms() > then + 1000) { + LOG_ERROR("Timeout waiting for read dcc"); + return ERROR_FAIL; + } + } + + retval = mem_ap_read_atomic_u32(a8->armv8_common.debug_ap, + a8->armv8_common.debug_base + CPUDBG_DTRTX, + (uint32_t *)data); + if (retval != ERROR_OK) + return retval; + + retval = mem_ap_read_atomic_u32(a8->armv8_common.debug_ap, + a8->armv8_common.debug_base + CPUDBG_DTRRX, + &higher); + if (retval != ERROR_OK) + return retval; + + *data = *(uint32_t *)data | (uint64_t)higher << 32; + LOG_DEBUG("read DCC 0x%16.16" PRIx64, *data); + + if (dscr_p) + *dscr_p = dscr; + + return retval; +} + +static int aarch64_dpm_prepare(struct arm_dpm *dpm) +{ + struct aarch64_common *a8 = dpm_to_a8(dpm); + uint32_t dscr; + int retval; + + /* set up invariant: INSTR_COMP is set after ever DPM operation */ + long long then = timeval_ms(); + for (;; ) { + retval = mem_ap_read_atomic_u32(a8->armv8_common.debug_ap, + a8->armv8_common.debug_base + CPUDBG_DSCR, + &dscr); + if (retval != ERROR_OK) + return retval; + if ((dscr & DSCR_INSTR_COMP) != 0) + break; + if (timeval_ms() > then + 1000) { + LOG_ERROR("Timeout waiting for dpm prepare"); + return ERROR_FAIL; + } + } + + /* this "should never happen" ... */ + if (dscr & DSCR_DTR_RX_FULL) { + LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr); + /* Clear DCCRX */ + retval = aarch64_exec_opcode( + a8->armv8_common.arm.target, + 0xd5130400, + &dscr); + if (retval != ERROR_OK) + return retval; + } + + return retval; +} + +static int aarch64_dpm_finish(struct arm_dpm *dpm) +{ + /* REVISIT what could be done here? */ + return ERROR_OK; +} + +static int aarch64_instr_write_data_dcc(struct arm_dpm *dpm, + uint32_t opcode, uint32_t data) +{ + struct aarch64_common *a8 = dpm_to_a8(dpm); + int retval; + uint32_t dscr = DSCR_INSTR_COMP; + + retval = aarch64_write_dcc(a8, data); + if (retval != ERROR_OK) + return retval; + + return aarch64_exec_opcode( + a8->armv8_common.arm.target, + opcode, + &dscr); +} + +static int aarch64_instr_write_data_dcc_64(struct arm_dpm *dpm, + uint32_t opcode, uint64_t data) +{ + struct aarch64_common *a8 = dpm_to_a8(dpm); + int retval; + uint32_t dscr = DSCR_INSTR_COMP; + + retval = aarch64_write_dcc_64(a8, data); + if (retval != ERROR_OK) + return retval; + + return aarch64_exec_opcode( + a8->armv8_common.arm.target, + opcode, + &dscr); +} + +static int aarch64_instr_write_data_r0(struct arm_dpm *dpm, + uint32_t opcode, uint32_t data) +{ + struct aarch64_common *a8 = dpm_to_a8(dpm); + uint32_t dscr = DSCR_INSTR_COMP; + int retval; + + retval = aarch64_write_dcc(a8, data); + if (retval != ERROR_OK) + return retval; + + retval = aarch64_exec_opcode( + a8->armv8_common.arm.target, + 0xd5330500, + &dscr); + if (retval != ERROR_OK) + return retval; + + /* then the opcode, taking data from R0 */ + retval = aarch64_exec_opcode( + a8->armv8_common.arm.target, + opcode, + &dscr); + + return retval; +} + +static int aarch64_instr_write_data_r0_64(struct arm_dpm *dpm, + uint32_t opcode, uint64_t data) +{ + struct aarch64_common *a8 = dpm_to_a8(dpm); + uint32_t dscr = DSCR_INSTR_COMP; + int retval; + + retval = aarch64_write_dcc_64(a8, data); + if (retval != ERROR_OK) + return retval; + + retval = aarch64_exec_opcode( + a8->armv8_common.arm.target, + 0xd5330400, + &dscr); + if (retval != ERROR_OK) + return retval; + + /* then the opcode, taking data from R0 */ + retval = aarch64_exec_opcode( + a8->armv8_common.arm.target, + opcode, + &dscr); + + return retval; +} + +static int aarch64_instr_cpsr_sync(struct arm_dpm *dpm) +{ + struct target *target = dpm->arm->target; + uint32_t dscr = DSCR_INSTR_COMP; + + /* "Prefetch flush" after modifying execution status in CPSR */ + return aarch64_exec_opcode(target, + ARMV4_5_MCR(15, 0, 0, 7, 5, 4), + &dscr); +} + +static int aarch64_instr_read_data_dcc(struct arm_dpm *dpm, + uint32_t opcode, uint32_t *data) +{ + struct aarch64_common *a8 = dpm_to_a8(dpm); + int retval; + uint32_t dscr = DSCR_INSTR_COMP; + + /* the opcode, writing data to DCC */ + retval = aarch64_exec_opcode( + a8->armv8_common.arm.target, + opcode, + &dscr); + if (retval != ERROR_OK) + return retval; + + return aarch64_read_dcc(a8, data, &dscr); +} + +static int aarch64_instr_read_data_dcc_64(struct arm_dpm *dpm, + uint32_t opcode, uint64_t *data) +{ + struct aarch64_common *a8 = dpm_to_a8(dpm); + int retval; + uint32_t dscr = DSCR_INSTR_COMP; + + /* the opcode, writing data to DCC */ + retval = aarch64_exec_opcode( + a8->armv8_common.arm.target, + opcode, + &dscr); + if (retval != ERROR_OK) + return retval; + + return aarch64_read_dcc_64(a8, data, &dscr); +} + +static int aarch64_instr_read_data_r0(struct arm_dpm *dpm, + uint32_t opcode, uint32_t *data) +{ + struct aarch64_common *a8 = dpm_to_a8(dpm); + uint32_t dscr = DSCR_INSTR_COMP; + int retval; + + /* the opcode, writing data to R0 */ + retval = aarch64_exec_opcode( + a8->armv8_common.arm.target, + opcode, + &dscr); + if (retval != ERROR_OK) + return retval; + + /* write R0 to DCC */ + retval = aarch64_exec_opcode( + a8->armv8_common.arm.target, + 0xd5130400, /* msr dbgdtr_el0, x0 */ + &dscr); + if (retval != ERROR_OK) + return retval; + + return aarch64_read_dcc(a8, data, &dscr); +} + +static int aarch64_instr_read_data_r0_64(struct arm_dpm *dpm, + uint32_t opcode, uint64_t *data) +{ + struct aarch64_common *a8 = dpm_to_a8(dpm); + uint32_t dscr = DSCR_INSTR_COMP; + int retval; + + /* the opcode, writing data to R0 */ + retval = aarch64_exec_opcode( + a8->armv8_common.arm.target, + opcode, + &dscr); + if (retval != ERROR_OK) + return retval; + + /* write R0 to DCC */ + retval = aarch64_exec_opcode( + a8->armv8_common.arm.target, + 0xd5130400, /* msr dbgdtr_el0, x0 */ + &dscr); + if (retval != ERROR_OK) + return retval; + + return aarch64_read_dcc_64(a8, data, &dscr); +} + +static int aarch64_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, + uint32_t addr, uint32_t control) +{ + struct aarch64_common *a8 = dpm_to_a8(dpm); + uint32_t vr = a8->armv8_common.debug_base; + uint32_t cr = a8->armv8_common.debug_base; + int retval; + + switch (index_t) { + case 0 ... 15: /* breakpoints */ + vr += CPUDBG_BVR_BASE; + cr += CPUDBG_BCR_BASE; + break; + case 16 ... 31: /* watchpoints */ + vr += CPUDBG_WVR_BASE; + cr += CPUDBG_WCR_BASE; + index_t -= 16; + break; + default: + return ERROR_FAIL; + } + vr += 4 * index_t; + cr += 4 * index_t; + + LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x", + (unsigned) vr, (unsigned) cr); + + retval = aarch64_dap_write_memap_register_u32(dpm->arm->target, + vr, addr); + if (retval != ERROR_OK) + return retval; + retval = aarch64_dap_write_memap_register_u32(dpm->arm->target, + cr, control); + return retval; +} + +static int aarch64_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) +{ + return ERROR_OK; + +#if 0 + struct aarch64_common *a8 = dpm_to_a8(dpm); + uint32_t cr; + + switch (index_t) { + case 0 ... 15: + cr = a8->armv8_common.debug_base + CPUDBG_BCR_BASE; + break; + case 16 ... 31: + cr = a8->armv8_common.debug_base + CPUDBG_WCR_BASE; + index_t -= 16; + break; + default: + return ERROR_FAIL; + } + cr += 4 * index_t; + + LOG_DEBUG("A8: bpwp disable, cr %08x", (unsigned) cr); + + /* clear control register */ + return aarch64_dap_write_memap_register_u32(dpm->arm->target, cr, 0); +#endif +} + +static int aarch64_dpm_setup(struct aarch64_common *a8, uint32_t debug) +{ + struct arm_dpm *dpm = &a8->armv8_common.dpm; + int retval; + + dpm->arm = &a8->armv8_common.arm; + dpm->didr = debug; + + dpm->prepare = aarch64_dpm_prepare; + dpm->finish = aarch64_dpm_finish; + + dpm->instr_write_data_dcc = aarch64_instr_write_data_dcc; + dpm->instr_write_data_dcc_64 = aarch64_instr_write_data_dcc_64; + dpm->instr_write_data_r0 = aarch64_instr_write_data_r0; + dpm->instr_write_data_r0_64 = aarch64_instr_write_data_r0_64; + dpm->instr_cpsr_sync = aarch64_instr_cpsr_sync; + + dpm->instr_read_data_dcc = aarch64_instr_read_data_dcc; + dpm->instr_read_data_dcc_64 = aarch64_instr_read_data_dcc_64; + dpm->instr_read_data_r0 = aarch64_instr_read_data_r0; + dpm->instr_read_data_r0_64 = aarch64_instr_read_data_r0_64; + + dpm->arm_reg_current = armv8_reg_current; + + dpm->bpwp_enable = aarch64_bpwp_enable; + dpm->bpwp_disable = aarch64_bpwp_disable; + + retval = arm_dpm_setup(dpm); + if (retval == ERROR_OK) + retval = arm_dpm_initialize(dpm); + + return retval; +} +static struct target *get_aarch64(struct target *target, int32_t coreid) +{ + struct target_list *head; + struct target *curr; + + head = target->head; + while (head != (struct target_list *)NULL) { + curr = head->target; + if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED)) + return curr; + head = head->next; + } + return target; +} +static int aarch64_halt(struct target *target); + +static int aarch64_halt_smp(struct target *target) +{ + int retval = 0; + struct target_list *head; + struct target *curr; + head = target->head; + while (head != (struct target_list *)NULL) { + curr = head->target; + if ((curr != target) && (curr->state != TARGET_HALTED)) + retval += aarch64_halt(curr); + head = head->next; + } + return retval; +} + +static int update_halt_gdb(struct target *target) +{ + int retval = 0; + if (target->gdb_service && target->gdb_service->core[0] == -1) { + target->gdb_service->target = target; + target->gdb_service->core[0] = target->coreid; + retval += aarch64_halt_smp(target); + } + return retval; +} + +/* + * Cortex-A8 Run control + */ + +static int aarch64_poll(struct target *target) +{ + int retval = ERROR_OK; + uint32_t dscr; + struct aarch64_common *aarch64 = target_to_aarch64(target); + struct armv8_common *armv8 = &aarch64->armv8_common; + enum target_state prev_target_state = target->state; + /* toggle to another core is done by gdb as follow */ + /* maint packet J core_id */ + /* continue */ + /* the next polling trigger an halt event sent to gdb */ + if ((target->state == TARGET_HALTED) && (target->smp) && + (target->gdb_service) && + (target->gdb_service->target == NULL)) { + target->gdb_service->target = + get_aarch64(target, target->gdb_service->core[1]); + target_call_event_callbacks(target, TARGET_EVENT_HALTED); + return retval; + } + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + if (retval != ERROR_OK) + return retval; + aarch64->cpudbg_dscr = dscr; + + if (DSCR_RUN_MODE(dscr) == (DSCR_CORE_HALTED | DSCR_CORE_RESTARTED)) { + if (prev_target_state != TARGET_HALTED) { + /* We have a halting debug event */ + LOG_DEBUG("Target halted"); + target->state = TARGET_HALTED; + if ((prev_target_state == TARGET_RUNNING) + || (prev_target_state == TARGET_UNKNOWN) + || (prev_target_state == TARGET_RESET)) { + retval = aarch64_debug_entry(target); + if (retval != ERROR_OK) + return retval; + if (target->smp) { + retval = update_halt_gdb(target); + if (retval != ERROR_OK) + return retval; + } + target_call_event_callbacks(target, + TARGET_EVENT_HALTED); + } + if (prev_target_state == TARGET_DEBUG_RUNNING) { + LOG_DEBUG(" "); + + retval = aarch64_debug_entry(target); + if (retval != ERROR_OK) + return retval; + if (target->smp) { + retval = update_halt_gdb(target); + if (retval != ERROR_OK) + return retval; + } + + target_call_event_callbacks(target, + TARGET_EVENT_DEBUG_HALTED); + } + } + } else if (DSCR_RUN_MODE(dscr) == DSCR_CORE_RESTARTED) + target->state = TARGET_RUNNING; + else { + LOG_DEBUG("Unknown target state dscr = 0x%08" PRIx32, dscr); + target->state = TARGET_UNKNOWN; + } + + return retval; +} + +static int aarch64_halt(struct target *target) +{ + int retval = ERROR_OK; + uint32_t dscr; + struct armv8_common *armv8 = target_to_armv8(target); + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0, &dscr); + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0, 1); + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0, &dscr); + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0x140, &dscr); + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0x140, 6); + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0x140, &dscr); + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0xa0, &dscr); + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0xa0, 5); + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0xa0, &dscr); + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0xa4, &dscr); + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0xa4, 2); + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0xa4, &dscr); + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0x20, &dscr); + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0x20, 4); + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0x20, &dscr); + + /* + * enter halting debug mode + */ + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + if (retval != ERROR_OK) + return retval; + +# /* STATUS */ + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0x134, &dscr); + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0x1c, &dscr); + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0x1c, 1); + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0x1c, &dscr); + + + long long then = timeval_ms(); + for (;; ) { + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + if (retval != ERROR_OK) + return retval; + if ((dscr & DSCR_CORE_HALTED) != 0) + break; + if (timeval_ms() > then + 1000) { + LOG_ERROR("Timeout waiting for halt"); + return ERROR_FAIL; + } + } + + target->debug_reason = DBG_REASON_DBGRQ; + + return ERROR_OK; +} + +static int aarch64_internal_restore(struct target *target, int current, + uint64_t *address, int handle_breakpoints, int debug_execution) +{ + struct armv8_common *armv8 = target_to_armv8(target); + struct arm *arm = &armv8->arm; + int retval; + uint64_t resume_pc; + + if (!debug_execution) + target_free_all_working_areas(target); + + /* current = 1: continue on current pc, otherwise continue at
*/ + resume_pc = buf_get_u64(arm->pc->value, 0, 64); + if (!current) + resume_pc = *address; + else + *address = resume_pc; + + /* Make sure that the Armv7 gdb thumb fixups does not + * kill the return address + */ + switch (arm->core_state) { + case ARM_STATE_ARM: + case ARM_STATE_AARCH64: + resume_pc &= 0xFFFFFFFFFFFFFFFC; + break; + case ARM_STATE_THUMB: + case ARM_STATE_THUMB_EE: + /* When the return address is loaded into PC + * bit 0 must be 1 to stay in Thumb state + */ + resume_pc |= 0x1; + break; + case ARM_STATE_JAZELLE: + LOG_ERROR("How do I resume into Jazelle state??"); + return ERROR_FAIL; + } + LOG_DEBUG("resume pc = 0x%16" PRIx64, resume_pc); + buf_set_u64(arm->pc->value, 0, 64, resume_pc); + arm->pc->dirty = 1; + arm->pc->valid = 1; +#if 0 + /* restore dpm_mode at system halt */ + dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY); +#endif + /* called it now before restoring context because it uses cpu + * register r0 for restoring system control register */ + retval = aarch64_restore_system_control_reg(target); + if (retval != ERROR_OK) + return retval; + retval = aarch64_restore_context(target, handle_breakpoints); + if (retval != ERROR_OK) + return retval; + target->debug_reason = DBG_REASON_NOTHALTED; + target->state = TARGET_RUNNING; + + /* registers are now invalid */ + register_cache_invalidate(arm->core_cache); + +#if 0 + /* the front-end may request us not to handle breakpoints */ + if (handle_breakpoints) { + /* Single step past breakpoint at current address */ + breakpoint = breakpoint_find(target, resume_pc); + if (breakpoint) { + LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address); + cortex_m3_unset_breakpoint(target, breakpoint); + cortex_m3_single_step_core(target); + cortex_m3_set_breakpoint(target, breakpoint); + } + } +#endif + + return retval; +} + +static int aarch64_internal_restart(struct target *target) +{ + struct armv8_common *armv8 = target_to_armv8(target); + struct arm *arm = &armv8->arm; + int retval; + uint32_t dscr; + /* + * * Restart core and wait for it to be started. Clear ITRen and sticky + * * exception flags: see ARMv7 ARM, C5.9. + * + * REVISIT: for single stepping, we probably want to + * disable IRQs by default, with optional override... + */ + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + if (retval != ERROR_OK) + return retval; + + if ((dscr & DSCR_INSTR_COMP) == 0) + LOG_ERROR("DSCR InstrCompl must be set before leaving debug!"); + + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, dscr & ~DSCR_ITR_EN); + if (retval != ERROR_OK) + return retval; + + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DRCR, DRCR_RESTART | + DRCR_CLEAR_EXCEPTIONS); + if (retval != ERROR_OK) + return retval; + + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0x10, 1); + if (retval != ERROR_OK) + return retval; + + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x10000 + 0x1c, 2); + if (retval != ERROR_OK) + return retval; + + long long then = timeval_ms(); + for (;; ) { + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + if (retval != ERROR_OK) + return retval; + if ((dscr & DSCR_CORE_RESTARTED) != 0) + break; + if (timeval_ms() > then + 1000) { + LOG_ERROR("Timeout waiting for resume"); + return ERROR_FAIL; + } + } + + target->debug_reason = DBG_REASON_NOTHALTED; + target->state = TARGET_RUNNING; + + /* registers are now invalid */ + register_cache_invalidate(arm->core_cache); + + return ERROR_OK; +} + +static int aarch64_restore_smp(struct target *target, int handle_breakpoints) +{ + int retval = 0; + struct target_list *head; + struct target *curr; + uint64_t address; + head = target->head; + while (head != (struct target_list *)NULL) { + curr = head->target; + if ((curr != target) && (curr->state != TARGET_RUNNING)) { + /* resume current address , not in step mode */ + retval += aarch64_internal_restore(curr, 1, &address, + handle_breakpoints, 0); + retval += aarch64_internal_restart(curr); + } + head = head->next; + + } + return retval; +} + +static int aarch64_resume(struct target *target, int current, + target_addr_t address, int handle_breakpoints, int debug_execution) +{ + int retval = 0; + uint64_t resume_addr; + + if (address) { + LOG_DEBUG("resuming with custom address not supported"); + return ERROR_FAIL; + } + + /* dummy resume for smp toggle in order to reduce gdb impact */ + if ((target->smp) && (target->gdb_service->core[1] != -1)) { + /* simulate a start and halt of target */ + target->gdb_service->target = NULL; + target->gdb_service->core[0] = target->gdb_service->core[1]; + /* fake resume at next poll we play the target core[1], see poll*/ + target_call_event_callbacks(target, TARGET_EVENT_RESUMED); + return 0; + } + aarch64_internal_restore(target, current, &resume_addr, handle_breakpoints, debug_execution); + if (target->smp) { + target->gdb_service->core[0] = -1; + retval = aarch64_restore_smp(target, handle_breakpoints); + if (retval != ERROR_OK) + return retval; + } + aarch64_internal_restart(target); + + if (!debug_execution) { + target->state = TARGET_RUNNING; + target_call_event_callbacks(target, TARGET_EVENT_RESUMED); + LOG_DEBUG("target resumed at 0x%" PRIx64, resume_addr); + } else { + target->state = TARGET_DEBUG_RUNNING; + target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); + LOG_DEBUG("target debug resumed at 0x%" PRIx64, resume_addr); + } + + return ERROR_OK; +} + +static int aarch64_debug_entry(struct target *target) +{ + uint32_t dscr; + int retval = ERROR_OK; + struct aarch64_common *aarch64 = target_to_aarch64(target); + struct armv8_common *armv8 = target_to_armv8(target); + + LOG_DEBUG("dscr = 0x%08" PRIx32, aarch64->cpudbg_dscr); + + /* REVISIT surely we should not re-read DSCR !! */ + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + if (retval != ERROR_OK) + return retval; + + /* REVISIT see A8 TRM 12.11.4 steps 2..3 -- make sure that any + * imprecise data aborts get discarded by issuing a Data + * Synchronization Barrier: ARMV4_5_MCR(15, 0, 0, 7, 10, 4). + */ + + /* Enable the ITR execution once we are in debug mode */ + dscr |= DSCR_ITR_EN; + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, dscr); + if (retval != ERROR_OK) + return retval; + + /* Examine debug reason */ + arm_dpm_report_dscr(&armv8->dpm, aarch64->cpudbg_dscr); + + /* save address of instruction that triggered the watchpoint? */ + if (target->debug_reason == DBG_REASON_WATCHPOINT) { + uint32_t wfar; + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_WFAR, + &wfar); + if (retval != ERROR_OK) + return retval; + arm_dpm_report_wfar(&armv8->dpm, wfar); + } + + retval = arm_dpm_read_current_registers_64(&armv8->dpm); + + if (armv8->post_debug_entry) { + retval = armv8->post_debug_entry(target); + if (retval != ERROR_OK) + return retval; + } + + return retval; +} + +static int aarch64_post_debug_entry(struct target *target) +{ + struct aarch64_common *aarch64 = target_to_aarch64(target); + struct armv8_common *armv8 = &aarch64->armv8_common; + struct armv8_mmu_common *armv8_mmu = &armv8->armv8_mmu; + uint32_t sctlr_el1 = 0; + int retval; + + mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DRCR, 1<<2); + retval = aarch64_instr_read_data_r0(armv8->arm.dpm, + 0xd5381000, &sctlr_el1); + if (retval != ERROR_OK) + return retval; + + LOG_DEBUG("sctlr_el1 = %#8.8x", sctlr_el1); + aarch64->system_control_reg = sctlr_el1; + aarch64->system_control_reg_curr = sctlr_el1; + aarch64->curr_mode = armv8->arm.core_mode; + + armv8_mmu->mmu_enabled = sctlr_el1 & 0x1U ? 1 : 0; + armv8_mmu->armv8_cache.d_u_cache_enabled = sctlr_el1 & 0x4U ? 1 : 0; + armv8_mmu->armv8_cache.i_cache_enabled = sctlr_el1 & 0x1000U ? 1 : 0; + +#if 0 + if (armv8->armv8_mmu.armv8_cache.ctype == -1) + armv8_identify_cache(target); +#endif + + return ERROR_OK; +} + +static int aarch64_step(struct target *target, int current, target_addr_t address, + int handle_breakpoints) +{ + struct armv8_common *armv8 = target_to_armv8(target); + struct arm *arm = &armv8->arm; + struct breakpoint *breakpoint = NULL; + struct breakpoint stepbreakpoint; + struct reg *r; + int retval; + + if (target->state != TARGET_HALTED) { + LOG_WARNING("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* current = 1: continue on current pc, otherwise continue at
*/ + r = arm->pc; + if (!current) + buf_set_u64(r->value, 0, 64, address); + else + address = buf_get_u64(r->value, 0, 64); + + /* The front-end may request us not to handle breakpoints. + * But since Cortex-A8 uses breakpoint for single step, + * we MUST handle breakpoints. + */ + handle_breakpoints = 1; + if (handle_breakpoints) { + breakpoint = breakpoint_find(target, address); + if (breakpoint) + aarch64_unset_breakpoint(target, breakpoint); + } + + /* Setup single step breakpoint */ + stepbreakpoint.address = address; + stepbreakpoint.length = 4; + stepbreakpoint.type = BKPT_HARD; + stepbreakpoint.set = 0; + + /* Break on IVA mismatch */ + aarch64_set_breakpoint(target, &stepbreakpoint, 0x04); + + target->debug_reason = DBG_REASON_SINGLESTEP; + + retval = aarch64_resume(target, 1, address, 0, 0); + if (retval != ERROR_OK) + return retval; + + long long then = timeval_ms(); + while (target->state != TARGET_HALTED) { + retval = aarch64_poll(target); + if (retval != ERROR_OK) + return retval; + if (timeval_ms() > then + 1000) { + LOG_ERROR("timeout waiting for target halt"); + return ERROR_FAIL; + } + } + + aarch64_unset_breakpoint(target, &stepbreakpoint); + + target->debug_reason = DBG_REASON_BREAKPOINT; + + if (breakpoint) + aarch64_set_breakpoint(target, breakpoint, 0); + + if (target->state != TARGET_HALTED) + LOG_DEBUG("target stepped"); + + return ERROR_OK; +} + +static int aarch64_restore_context(struct target *target, bool bpwp) +{ + struct armv8_common *armv8 = target_to_armv8(target); + + LOG_DEBUG(" "); + + if (armv8->pre_restore_context) + armv8->pre_restore_context(target); + + return arm_dpm_write_dirty_registers(&armv8->dpm, bpwp); + + return ERROR_OK; +} + +/* + * Cortex-A8 Breakpoint and watchpoint functions + */ + +/* Setup hardware Breakpoint Register Pair */ +static int aarch64_set_breakpoint(struct target *target, + struct breakpoint *breakpoint, uint8_t matchmode) +{ + int retval; + int brp_i = 0; + uint32_t control; + uint8_t byte_addr_select = 0x0F; + struct aarch64_common *aarch64 = target_to_aarch64(target); + struct armv8_common *armv8 = &aarch64->armv8_common; + struct aarch64_brp *brp_list = aarch64->brp_list; + + if (breakpoint->set) { + LOG_WARNING("breakpoint already set"); + return ERROR_OK; + } + + if (breakpoint->type == BKPT_HARD) { + while (brp_list[brp_i].used && (brp_i < aarch64->brp_num)) + brp_i++; + if (brp_i >= aarch64->brp_num) { + LOG_ERROR("ERROR Can not find free Breakpoint Register Pair"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + breakpoint->set = brp_i + 1; + if (breakpoint->length == 2) + byte_addr_select = (3 << (breakpoint->address & 0x02)); + control = ((matchmode & 0x7) << 20) + | (byte_addr_select << 5) + | (3 << 1) | 1; + brp_list[brp_i].used = 1; + brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC); + brp_list[brp_i].control = control; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn, + brp_list[brp_i].value); + if (retval != ERROR_OK) + return retval; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn, + brp_list[brp_i].control); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("brp %i control 0x%0" PRIx32 " value 0x%" TARGET_PRIxADDR, brp_i, + brp_list[brp_i].control, + brp_list[brp_i].value); + } else if (breakpoint->type == BKPT_SOFT) { + uint8_t code[4]; + if (breakpoint->length == 2) + buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11)); + else + buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11)); + retval = target_read_memory(target, + breakpoint->address & 0xFFFFFFFE, + breakpoint->length, 1, + breakpoint->orig_instr); + if (retval != ERROR_OK) + return retval; + retval = target_write_memory(target, + breakpoint->address & 0xFFFFFFFE, + breakpoint->length, 1, code); + if (retval != ERROR_OK) + return retval; + breakpoint->set = 0x11; /* Any nice value but 0 */ + } + + return ERROR_OK; +} + +static int aarch64_set_context_breakpoint(struct target *target, + struct breakpoint *breakpoint, uint8_t matchmode) +{ + int retval = ERROR_FAIL; + int brp_i = 0; + uint32_t control; + uint8_t byte_addr_select = 0x0F; + struct aarch64_common *aarch64 = target_to_aarch64(target); + struct armv8_common *armv8 = &aarch64->armv8_common; + struct aarch64_brp *brp_list = aarch64->brp_list; + + if (breakpoint->set) { + LOG_WARNING("breakpoint already set"); + return retval; + } + /*check available context BRPs*/ + while ((brp_list[brp_i].used || + (brp_list[brp_i].type != BRP_CONTEXT)) && (brp_i < aarch64->brp_num)) + brp_i++; + + if (brp_i >= aarch64->brp_num) { + LOG_ERROR("ERROR Can not find free Breakpoint Register Pair"); + return ERROR_FAIL; + } + + breakpoint->set = brp_i + 1; + control = ((matchmode & 0x7) << 20) + | (byte_addr_select << 5) + | (3 << 1) | 1; + brp_list[brp_i].used = 1; + brp_list[brp_i].value = (breakpoint->asid); + brp_list[brp_i].control = control; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn, + brp_list[brp_i].value); + if (retval != ERROR_OK) + return retval; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn, + brp_list[brp_i].control); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("brp %i control 0x%0" PRIx32 " value 0x%" TARGET_PRIxADDR, brp_i, + brp_list[brp_i].control, + brp_list[brp_i].value); + return ERROR_OK; + +} + +static int aarch64_set_hybrid_breakpoint(struct target *target, struct breakpoint *breakpoint) +{ + int retval = ERROR_FAIL; + int brp_1 = 0; /* holds the contextID pair */ + int brp_2 = 0; /* holds the IVA pair */ + uint32_t control_CTX, control_IVA; + uint8_t CTX_byte_addr_select = 0x0F; + uint8_t IVA_byte_addr_select = 0x0F; + uint8_t CTX_machmode = 0x03; + uint8_t IVA_machmode = 0x01; + struct aarch64_common *aarch64 = target_to_aarch64(target); + struct armv8_common *armv8 = &aarch64->armv8_common; + struct aarch64_brp *brp_list = aarch64->brp_list; + + if (breakpoint->set) { + LOG_WARNING("breakpoint already set"); + return retval; + } + /*check available context BRPs*/ + while ((brp_list[brp_1].used || + (brp_list[brp_1].type != BRP_CONTEXT)) && (brp_1 < aarch64->brp_num)) + brp_1++; + + printf("brp(CTX) found num: %d\n", brp_1); + if (brp_1 >= aarch64->brp_num) { + LOG_ERROR("ERROR Can not find free Breakpoint Register Pair"); + return ERROR_FAIL; + } + + while ((brp_list[brp_2].used || + (brp_list[brp_2].type != BRP_NORMAL)) && (brp_2 < aarch64->brp_num)) + brp_2++; + + printf("brp(IVA) found num: %d\n", brp_2); + if (brp_2 >= aarch64->brp_num) { + LOG_ERROR("ERROR Can not find free Breakpoint Register Pair"); + return ERROR_FAIL; + } + + breakpoint->set = brp_1 + 1; + breakpoint->linked_BRP = brp_2; + control_CTX = ((CTX_machmode & 0x7) << 20) + | (brp_2 << 16) + | (0 << 14) + | (CTX_byte_addr_select << 5) + | (3 << 1) | 1; + brp_list[brp_1].used = 1; + brp_list[brp_1].value = (breakpoint->asid); + brp_list[brp_1].control = control_CTX; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUDBG_BVR_BASE + 4 * brp_list[brp_1].BRPn, + brp_list[brp_1].value); + if (retval != ERROR_OK) + return retval; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUDBG_BCR_BASE + 4 * brp_list[brp_1].BRPn, + brp_list[brp_1].control); + if (retval != ERROR_OK) + return retval; + + control_IVA = ((IVA_machmode & 0x7) << 20) + | (brp_1 << 16) + | (IVA_byte_addr_select << 5) + | (3 << 1) | 1; + brp_list[brp_2].used = 1; + brp_list[brp_2].value = (breakpoint->address & 0xFFFFFFFC); + brp_list[brp_2].control = control_IVA; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUDBG_BVR_BASE + 4 * brp_list[brp_2].BRPn, + brp_list[brp_2].value); + if (retval != ERROR_OK) + return retval; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUDBG_BCR_BASE + 4 * brp_list[brp_2].BRPn, + brp_list[brp_2].control); + if (retval != ERROR_OK) + return retval; + + return ERROR_OK; +} + +static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *breakpoint) +{ + int retval; + struct aarch64_common *aarch64 = target_to_aarch64(target); + struct armv8_common *armv8 = &aarch64->armv8_common; + struct aarch64_brp *brp_list = aarch64->brp_list; + + if (!breakpoint->set) { + LOG_WARNING("breakpoint not set"); + return ERROR_OK; + } + + if (breakpoint->type == BKPT_HARD) { + if ((breakpoint->address != 0) && (breakpoint->asid != 0)) { + int brp_i = breakpoint->set - 1; + int brp_j = breakpoint->linked_BRP; + if ((brp_i < 0) || (brp_i >= aarch64->brp_num)) { + LOG_DEBUG("Invalid BRP number in breakpoint"); + return ERROR_OK; + } + LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%" TARGET_PRIxADDR, brp_i, + brp_list[brp_i].control, brp_list[brp_i].value); + brp_list[brp_i].used = 0; + brp_list[brp_i].value = 0; + brp_list[brp_i].control = 0; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUDBG_BCR_BASE + 16 * brp_list[brp_i].BRPn, + brp_list[brp_i].control); + if (retval != ERROR_OK) + return retval; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUDBG_BVR_BASE + 16 * brp_list[brp_i].BRPn, + brp_list[brp_i].value); + if (retval != ERROR_OK) + return retval; + if ((brp_j < 0) || (brp_j >= aarch64->brp_num)) { + LOG_DEBUG("Invalid BRP number in breakpoint"); + return ERROR_OK; + } + LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx64, brp_j, + brp_list[brp_j].control, brp_list[brp_j].value); + brp_list[brp_j].used = 0; + brp_list[brp_j].value = 0; + brp_list[brp_j].control = 0; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUDBG_BCR_BASE + 16 * brp_list[brp_j].BRPn, + brp_list[brp_j].control); + if (retval != ERROR_OK) + return retval; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUDBG_BVR_BASE + 16 * brp_list[brp_j].BRPn, + brp_list[brp_j].value); + if (retval != ERROR_OK) + return retval; + breakpoint->linked_BRP = 0; + breakpoint->set = 0; + return ERROR_OK; + + } else { + int brp_i = breakpoint->set - 1; + if ((brp_i < 0) || (brp_i >= aarch64->brp_num)) { + LOG_DEBUG("Invalid BRP number in breakpoint"); + return ERROR_OK; + } + LOG_DEBUG("rbp %i control 0x%0" PRIx32 " value 0x%0" PRIx64, brp_i, + brp_list[brp_i].control, brp_list[brp_i].value); + brp_list[brp_i].used = 0; + brp_list[brp_i].value = 0; + brp_list[brp_i].control = 0; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn, + brp_list[brp_i].control); + if (retval != ERROR_OK) + return retval; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn, + brp_list[brp_i].value); + if (retval != ERROR_OK) + return retval; + breakpoint->set = 0; + return ERROR_OK; + } + } else { + /* restore original instruction (kept in target endianness) */ + if (breakpoint->length == 4) { + retval = target_write_memory(target, + breakpoint->address & 0xFFFFFFFFFFFFFFFE, + 4, 1, breakpoint->orig_instr); + if (retval != ERROR_OK) + return retval; + } else { + retval = target_write_memory(target, + breakpoint->address & 0xFFFFFFFFFFFFFFFE, + 2, 1, breakpoint->orig_instr); + if (retval != ERROR_OK) + return retval; + } + } + breakpoint->set = 0; + + return ERROR_OK; +} + +static int aarch64_add_breakpoint(struct target *target, + struct breakpoint *breakpoint) +{ + struct aarch64_common *aarch64 = target_to_aarch64(target); + + if ((breakpoint->type == BKPT_HARD) && (aarch64->brp_num_available < 1)) { + LOG_INFO("no hardware breakpoint available"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + + if (breakpoint->type == BKPT_HARD) + aarch64->brp_num_available--; + + return aarch64_set_breakpoint(target, breakpoint, 0x00); /* Exact match */ +} + +static int aarch64_add_context_breakpoint(struct target *target, + struct breakpoint *breakpoint) +{ + struct aarch64_common *aarch64 = target_to_aarch64(target); + + if ((breakpoint->type == BKPT_HARD) && (aarch64->brp_num_available < 1)) { + LOG_INFO("no hardware breakpoint available"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + + if (breakpoint->type == BKPT_HARD) + aarch64->brp_num_available--; + + return aarch64_set_context_breakpoint(target, breakpoint, 0x02); /* asid match */ +} + +static int aarch64_add_hybrid_breakpoint(struct target *target, + struct breakpoint *breakpoint) +{ + struct aarch64_common *aarch64 = target_to_aarch64(target); + + if ((breakpoint->type == BKPT_HARD) && (aarch64->brp_num_available < 1)) { + LOG_INFO("no hardware breakpoint available"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + + if (breakpoint->type == BKPT_HARD) + aarch64->brp_num_available--; + + return aarch64_set_hybrid_breakpoint(target, breakpoint); /* ??? */ +} + + +static int aarch64_remove_breakpoint(struct target *target, struct breakpoint *breakpoint) +{ + struct aarch64_common *aarch64 = target_to_aarch64(target); + +#if 0 +/* It is perfectly possible to remove breakpoints while the target is running */ + if (target->state != TARGET_HALTED) { + LOG_WARNING("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } +#endif + + if (breakpoint->set) { + aarch64_unset_breakpoint(target, breakpoint); + if (breakpoint->type == BKPT_HARD) + aarch64->brp_num_available++; + } + + return ERROR_OK; +} + +/* + * Cortex-A8 Reset functions + */ + +static int aarch64_assert_reset(struct target *target) +{ + struct armv8_common *armv8 = target_to_armv8(target); + + LOG_DEBUG(" "); + + /* FIXME when halt is requested, make it work somehow... */ + + /* Issue some kind of warm reset. */ + if (target_has_event_action(target, TARGET_EVENT_RESET_ASSERT)) + target_handle_event(target, TARGET_EVENT_RESET_ASSERT); + else if (jtag_get_reset_config() & RESET_HAS_SRST) { + /* REVISIT handle "pulls" cases, if there's + * hardware that needs them to work. + */ + jtag_add_reset(0, 1); + } else { + LOG_ERROR("%s: how to reset?", target_name(target)); + return ERROR_FAIL; + } + + /* registers are now invalid */ + register_cache_invalidate(armv8->arm.core_cache); + + target->state = TARGET_RESET; + + return ERROR_OK; +} + +static int aarch64_deassert_reset(struct target *target) +{ + int retval; + + LOG_DEBUG(" "); + + /* be certain SRST is off */ + jtag_add_reset(0, 0); + + retval = aarch64_poll(target); + if (retval != ERROR_OK) + return retval; + + if (target->reset_halt) { + if (target->state != TARGET_HALTED) { + LOG_WARNING("%s: ran after reset and before halt ...", + target_name(target)); + retval = target_halt(target); + if (retval != ERROR_OK) + return retval; + } + } + + return ERROR_OK; +} + +static int aarch64_write_apb_ab_memory(struct target *target, + uint64_t address, uint32_t size, + uint32_t count, const uint8_t *buffer) +{ + /* write memory through APB-AP */ + int retval = ERROR_COMMAND_SYNTAX_ERROR; + struct armv8_common *armv8 = target_to_armv8(target); + struct arm *arm = &armv8->arm; + int total_bytes = count * size; + int total_u32; + int start_byte = address & 0x3; + int end_byte = (address + total_bytes) & 0x3; + struct reg *reg; + uint32_t dscr; + uint8_t *tmp_buff = NULL; + uint32_t i = 0; + + LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx64 " size %" PRIu32 " count%" PRIu32, + address, size, count); + if (target->state != TARGET_HALTED) { + LOG_WARNING("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + total_u32 = DIV_ROUND_UP((address & 3) + total_bytes, 4); + + /* Mark register R0 as dirty, as it will be used + * for transferring the data. + * It will be restored automatically when exiting + * debug mode + */ + reg = armv8_reg_current(arm, 1); + reg->dirty = true; + + reg = armv8_reg_current(arm, 0); + reg->dirty = true; + + /* clear any abort */ + retval = mem_ap_write_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUDBG_DRCR, 1<<2); + if (retval != ERROR_OK) + return retval; + + /* This algorithm comes from either : + * Cortex-A8 TRM Example 12-25 + * Cortex-R4 TRM Example 11-26 + * (slight differences) + */ + + /* The algorithm only copies 32 bit words, so the buffer + * should be expanded to include the words at either end. + * The first and last words will be read first to avoid + * corruption if needed. + */ + tmp_buff = malloc(total_u32 * 4); + + if ((start_byte != 0) && (total_u32 > 1)) { + /* First bytes not aligned - read the 32 bit word to avoid corrupting + * the other bytes in the word. + */ + retval = aarch64_read_apb_ab_memory(target, (address & ~0x3), 4, 1, tmp_buff); + if (retval != ERROR_OK) + goto error_free_buff_w; + } + + /* If end of write is not aligned, or the write is less than 4 bytes */ + if ((end_byte != 0) || + ((total_u32 == 1) && (total_bytes != 4))) { + + /* Read the last word to avoid corruption during 32 bit write */ + int mem_offset = (total_u32-1) * 4; + retval = aarch64_read_apb_ab_memory(target, (address & ~0x3) + mem_offset, 4, 1, &tmp_buff[mem_offset]); + if (retval != ERROR_OK) + goto error_free_buff_w; + } + + /* Copy the write buffer over the top of the temporary buffer */ + memcpy(&tmp_buff[start_byte], buffer, total_bytes); + + /* We now have a 32 bit aligned buffer that can be written */ + + /* Read DSCR */ + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + if (retval != ERROR_OK) + goto error_free_buff_w; + + /* Set DTR mode to Normal*/ + dscr = (dscr & ~DSCR_EXT_DCC_MASK) | DSCR_EXT_DCC_NON_BLOCKING; + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, dscr); + if (retval != ERROR_OK) + goto error_free_buff_w; + + if (size > 4) { + LOG_WARNING("reading size >4 bytes not yet supported"); + goto error_unset_dtr_w; + } + + retval = aarch64_instr_write_data_dcc_64(arm->dpm, 0xd5330401, address+4); + if (retval != ERROR_OK) + goto error_unset_dtr_w; + + dscr = DSCR_INSTR_COMP; + while (i < count * size) { + uint32_t val; + + memcpy(&val, &buffer[i], size); + retval = aarch64_instr_write_data_dcc(arm->dpm, 0xd5330500, val); + if (retval != ERROR_OK) + goto error_unset_dtr_w; + + retval = aarch64_exec_opcode(target, 0xb81fc020, &dscr); + if (retval != ERROR_OK) + goto error_unset_dtr_w; + + retval = aarch64_exec_opcode(target, 0x91001021, &dscr); + if (retval != ERROR_OK) + goto error_unset_dtr_w; + + i += 4; + } + + /* Check for sticky abort flags in the DSCR */ + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + if (retval != ERROR_OK) + goto error_free_buff_w; + if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) { + /* Abort occurred - clear it and exit */ + LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); + mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DRCR, 1<<2); + goto error_free_buff_w; + } + + /* Done */ + free(tmp_buff); + return ERROR_OK; + +error_unset_dtr_w: + /* Unset DTR mode */ + mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + dscr = (dscr & ~DSCR_EXT_DCC_MASK) | DSCR_EXT_DCC_NON_BLOCKING; + mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, dscr); +error_free_buff_w: + LOG_ERROR("error"); + free(tmp_buff); + return ERROR_FAIL; +} + +static int aarch64_read_apb_ab_memory(struct target *target, + target_addr_t address, uint32_t size, + uint32_t count, uint8_t *buffer) +{ + /* read memory through APB-AP */ + + int retval = ERROR_COMMAND_SYNTAX_ERROR; + struct armv8_common *armv8 = target_to_armv8(target); + struct arm *arm = &armv8->arm; + struct reg *reg; + uint32_t dscr, val; + uint8_t *tmp_buff = NULL; + uint32_t i = 0; + + LOG_DEBUG("Reading APB-AP memory address 0x%" TARGET_PRIxADDR " size %" PRIu32 " count%" PRIu32, + address, size, count); + if (target->state != TARGET_HALTED) { + LOG_WARNING("target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* Mark register R0 as dirty, as it will be used + * for transferring the data. + * It will be restored automatically when exiting + * debug mode + */ + reg = armv8_reg_current(arm, 0); + reg->dirty = true; + + /* clear any abort */ + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DRCR, 1<<2); + if (retval != ERROR_OK) + goto error_free_buff_r; + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + if (retval != ERROR_OK) + goto error_unset_dtr_r; + + if (size > 4) { + LOG_WARNING("reading size >4 bytes not yet supported"); + goto error_unset_dtr_r; + } + + while (i < count * size) { + + retval = aarch64_instr_write_data_dcc_64(arm->dpm, 0xd5330400, address+4); + if (retval != ERROR_OK) + goto error_unset_dtr_r; + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + + dscr = DSCR_INSTR_COMP; + retval = aarch64_exec_opcode(target, 0xb85fc000, &dscr); + if (retval != ERROR_OK) + goto error_unset_dtr_r; + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + + retval = aarch64_instr_read_data_dcc(arm->dpm, 0xd5130400, &val); + if (retval != ERROR_OK) + goto error_unset_dtr_r; + memcpy(&buffer[i], &val, size); + i += 4; + address += 4; + } + + /* Clear any sticky error */ + mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DRCR, 1<<2); + + /* Done */ + return ERROR_OK; + +error_unset_dtr_r: + LOG_WARNING("DSCR = 0x%" PRIx32, dscr); + /* Todo: Unset DTR mode */ + +error_free_buff_r: + LOG_ERROR("error"); + free(tmp_buff); + + /* Clear any sticky error */ + mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DRCR, 1<<2); + + return ERROR_FAIL; +} + +static int aarch64_read_phys_memory(struct target *target, + target_addr_t address, uint32_t size, + uint32_t count, uint8_t *buffer) +{ + struct armv8_common *armv8 = target_to_armv8(target); + int retval = ERROR_COMMAND_SYNTAX_ERROR; + struct adiv5_dap *swjdp = armv8->arm.dap; + uint8_t apsel = swjdp->apsel; + LOG_DEBUG("Reading memory at real address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, + address, size, count); + + if (count && buffer) { + + if (armv8->memory_ap_available && (apsel == armv8->memory_ap->ap_num)) { + + /* read memory through AHB-AP */ + retval = mem_ap_read_buf(armv8->memory_ap, buffer, size, count, address); + } else { + /* read memory through APB-AP */ + retval = aarch64_mmu_modify(target, 0); + if (retval != ERROR_OK) + return retval; + retval = aarch64_read_apb_ab_memory(target, address, size, count, buffer); + } + } + return retval; +} + +static int aarch64_read_memory(struct target *target, target_addr_t address, + uint32_t size, uint32_t count, uint8_t *buffer) +{ + int mmu_enabled = 0; + target_addr_t virt, phys; + int retval; + struct armv8_common *armv8 = target_to_armv8(target); + struct adiv5_dap *swjdp = armv8->arm.dap; + uint8_t apsel = swjdp->apsel; + + /* aarch64 handles unaligned memory access */ + LOG_DEBUG("Reading memory at address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, address, + size, count); + + /* determine if MMU was enabled on target stop */ + if (!armv8->is_armv7r) { + retval = aarch64_mmu(target, &mmu_enabled); + if (retval != ERROR_OK) + return retval; + } + + if (armv8->memory_ap_available && (apsel == armv8->memory_ap->ap_num)) { + if (mmu_enabled) { + virt = address; + retval = aarch64_virt2phys(target, virt, &phys); + if (retval != ERROR_OK) + return retval; + + LOG_DEBUG("Reading at virtual address. Translating v:0x%" TARGET_PRIxADDR " to r:0x%" TARGET_PRIxADDR, + virt, phys); + address = phys; + } + retval = aarch64_read_phys_memory(target, address, size, count, + buffer); + } else { + if (mmu_enabled) { + retval = aarch64_check_address(target, address); + if (retval != ERROR_OK) + return retval; + /* enable MMU as we could have disabled it for phys + access */ + retval = aarch64_mmu_modify(target, 1); + if (retval != ERROR_OK) + return retval; + } + retval = aarch64_read_apb_ab_memory(target, address, size, + count, buffer); + } + return retval; +} + +static int aarch64_write_phys_memory(struct target *target, + target_addr_t address, uint32_t size, + uint32_t count, const uint8_t *buffer) +{ + struct armv8_common *armv8 = target_to_armv8(target); + struct adiv5_dap *swjdp = armv8->arm.dap; + int retval = ERROR_COMMAND_SYNTAX_ERROR; + uint8_t apsel = swjdp->apsel; + + LOG_DEBUG("Writing memory to real address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, address, + size, count); + + if (count && buffer) { + + if (armv8->memory_ap_available && (apsel == armv8->memory_ap->ap_num)) { + + /* write memory through AHB-AP */ + retval = mem_ap_write_buf(armv8->memory_ap, buffer, size, count, address); + } else { + + /* write memory through APB-AP */ + if (!armv8->is_armv7r) { + retval = aarch64_mmu_modify(target, 0); + if (retval != ERROR_OK) + return retval; + } + return aarch64_write_apb_ab_memory(target, address, size, count, buffer); + } + } + + + /* REVISIT this op is generic ARMv7-A/R stuff */ + if (retval == ERROR_OK && target->state == TARGET_HALTED) { + struct arm_dpm *dpm = armv8->arm.dpm; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + return retval; + + /* The Cache handling will NOT work with MMU active, the + * wrong addresses will be invalidated! + * + * For both ICache and DCache, walk all cache lines in the + * address range. Cortex-A8 has fixed 64 byte line length. + * + * REVISIT per ARMv7, these may trigger watchpoints ... + */ + + /* invalidate I-Cache */ + if (armv8->armv8_mmu.armv8_cache.i_cache_enabled) { + /* ICIMVAU - Invalidate Cache single entry + * with MVA to PoU + * MCR p15, 0, r0, c7, c5, 1 + */ + for (uint32_t cacheline = address; + cacheline < address + size * count; + cacheline += 64) { + retval = dpm->instr_write_data_r0(dpm, + ARMV4_5_MCR(15, 0, 0, 7, 5, 1), + cacheline); + if (retval != ERROR_OK) + return retval; + } + } + + /* invalidate D-Cache */ + if (armv8->armv8_mmu.armv8_cache.d_u_cache_enabled) { + /* DCIMVAC - Invalidate data Cache line + * with MVA to PoC + * MCR p15, 0, r0, c7, c6, 1 + */ + for (uint32_t cacheline = address; + cacheline < address + size * count; + cacheline += 64) { + retval = dpm->instr_write_data_r0(dpm, + ARMV4_5_MCR(15, 0, 0, 7, 6, 1), + cacheline); + if (retval != ERROR_OK) + return retval; + } + } + + /* (void) */ dpm->finish(dpm); + } + + return retval; +} + +static int aarch64_write_memory(struct target *target, target_addr_t address, + uint32_t size, uint32_t count, const uint8_t *buffer) +{ + int mmu_enabled = 0; + target_addr_t virt, phys; + int retval; + struct armv8_common *armv8 = target_to_armv8(target); + struct adiv5_dap *swjdp = armv8->arm.dap; + uint8_t apsel = swjdp->apsel; + + /* aarch64 handles unaligned memory access */ + LOG_DEBUG("Writing memory at address 0x%" TARGET_PRIxADDR "; size %" PRId32 + "; count %" PRId32, address, size, count); + + /* determine if MMU was enabled on target stop */ + if (!armv8->is_armv7r) { + retval = aarch64_mmu(target, &mmu_enabled); + if (retval != ERROR_OK) + return retval; + } + + if (armv8->memory_ap_available && (apsel == armv8->memory_ap->ap_num)) { + LOG_DEBUG("Writing memory to address 0x%" TARGET_PRIxADDR "; size %" + PRId32 "; count %" PRId32, address, size, count); + if (mmu_enabled) { + virt = address; + retval = aarch64_virt2phys(target, virt, &phys); + if (retval != ERROR_OK) + return retval; + + LOG_DEBUG("Writing to virtual address. Translating v:0x%" + TARGET_PRIxADDR " to r:0x%" TARGET_PRIxADDR, virt, phys); + address = phys; + } + retval = aarch64_write_phys_memory(target, address, size, + count, buffer); + } else { + if (mmu_enabled) { + retval = aarch64_check_address(target, address); + if (retval != ERROR_OK) + return retval; + /* enable MMU as we could have disabled it for phys access */ + retval = aarch64_mmu_modify(target, 1); + if (retval != ERROR_OK) + return retval; + } + retval = aarch64_write_apb_ab_memory(target, address, size, count, buffer); + } + return retval; +} + +static int aarch64_handle_target_request(void *priv) +{ + struct target *target = priv; + struct armv8_common *armv8 = target_to_armv8(target); + int retval; + + if (!target_was_examined(target)) + return ERROR_OK; + if (!target->dbg_msg_enabled) + return ERROR_OK; + + if (target->state == TARGET_RUNNING) { + uint32_t request; + uint32_t dscr; + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + + /* check if we have data */ + while ((dscr & DSCR_DTR_TX_FULL) && (retval == ERROR_OK)) { + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DTRTX, &request); + if (retval == ERROR_OK) { + target_request(target, request); + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + } + } + } + + return ERROR_OK; +} + +static int aarch64_examine_first(struct target *target) +{ + struct aarch64_common *aarch64 = target_to_aarch64(target); + struct armv8_common *armv8 = &aarch64->armv8_common; + struct adiv5_dap *swjdp = armv8->arm.dap; + int retval = ERROR_OK; + uint32_t pfr, debug, ctypr, ttypr, cpuid; + int i; + + /* We do one extra read to ensure DAP is configured, + * we call ahbap_debugport_init(swjdp) instead + */ + retval = dap_dp_init(swjdp); + if (retval != ERROR_OK) + return retval; + + /* Search for the APB-AB - it is needed for access to debug registers */ + retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv8->debug_ap); + if (retval != ERROR_OK) { + LOG_ERROR("Could not find APB-AP for debug access"); + return retval; + } + + retval = mem_ap_init(armv8->debug_ap); + if (retval != ERROR_OK) { + LOG_ERROR("Could not initialize the APB-AP"); + return retval; + } + + armv8->debug_ap->memaccess_tck = 80; + + /* Search for the AHB-AB */ + armv8->memory_ap_available = false; + retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv8->memory_ap); + if (retval == ERROR_OK) { + retval = mem_ap_init(armv8->memory_ap); + if (retval == ERROR_OK) + armv8->memory_ap_available = true; + } + if (retval != ERROR_OK) { + /* AHB-AP not found or unavailable - use the CPU */ + LOG_DEBUG("No AHB-AP available for memory access"); + } + + + if (!target->dbgbase_set) { + uint32_t dbgbase; + /* Get ROM Table base */ + uint32_t apid; + int32_t coreidx = target->coreid; + retval = dap_get_debugbase(armv8->debug_ap, &dbgbase, &apid); + if (retval != ERROR_OK) + return retval; + /* Lookup 0x15 -- Processor DAP */ + retval = dap_lookup_cs_component(armv8->debug_ap, dbgbase, 0x15, + &armv8->debug_base, &coreidx); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("Detected core %" PRId32 " dbgbase: %08" PRIx32, + coreidx, armv8->debug_base); + } else + armv8->debug_base = target->dbgbase; + + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x300, 0); + if (retval != ERROR_OK) { + LOG_DEBUG("Examine %s failed", "oslock"); + return retval; + } + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x88, &cpuid); + LOG_DEBUG("0x88 = %x", cpuid); + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x314, &cpuid); + LOG_DEBUG("0x314 = %x", cpuid); + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + 0x310, &cpuid); + LOG_DEBUG("0x310 = %x", cpuid); + if (retval != ERROR_OK) + return retval; + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_CPUID, &cpuid); + if (retval != ERROR_OK) { + LOG_DEBUG("Examine %s failed", "CPUID"); + return retval; + } + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_CTYPR, &ctypr); + if (retval != ERROR_OK) { + LOG_DEBUG("Examine %s failed", "CTYPR"); + return retval; + } + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_TTYPR, &ttypr); + if (retval != ERROR_OK) { + LOG_DEBUG("Examine %s failed", "TTYPR"); + return retval; + } + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + ID_AA64PFR0_EL1, &pfr); + if (retval != ERROR_OK) { + LOG_DEBUG("Examine %s failed", "ID_AA64DFR0_EL1"); + return retval; + } + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + ID_AA64DFR0_EL1, &debug); + if (retval != ERROR_OK) { + LOG_DEBUG("Examine %s failed", "ID_AA64DFR0_EL1"); + return retval; + } + + LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid); + LOG_DEBUG("ctypr = 0x%08" PRIx32, ctypr); + LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr); + LOG_DEBUG("ID_AA64PFR0_EL1 = 0x%08" PRIx32, pfr); + LOG_DEBUG("ID_AA64DFR0_EL1 = 0x%08" PRIx32, debug); + + armv8->arm.core_type = ARM_MODE_MON; + armv8->arm.core_state = ARM_STATE_AARCH64; + retval = aarch64_dpm_setup(aarch64, debug); + if (retval != ERROR_OK) + return retval; + + /* Setup Breakpoint Register Pairs */ + aarch64->brp_num = ((debug >> 12) & 0x0F) + 1; + aarch64->brp_num_context = ((debug >> 28) & 0x0F) + 1; + + /* hack - no context bpt support yet */ + aarch64->brp_num_context = 0; + + aarch64->brp_num_available = aarch64->brp_num; + aarch64->brp_list = calloc(aarch64->brp_num, sizeof(struct aarch64_brp)); + for (i = 0; i < aarch64->brp_num; i++) { + aarch64->brp_list[i].used = 0; + if (i < (aarch64->brp_num-aarch64->brp_num_context)) + aarch64->brp_list[i].type = BRP_NORMAL; + else + aarch64->brp_list[i].type = BRP_CONTEXT; + aarch64->brp_list[i].value = 0; + aarch64->brp_list[i].control = 0; + aarch64->brp_list[i].BRPn = i; + } + + LOG_DEBUG("Configured %i hw breakpoints", aarch64->brp_num); + + target_set_examined(target); + return ERROR_OK; +} + +static int aarch64_examine(struct target *target) +{ + int retval = ERROR_OK; + + /* don't re-probe hardware after each reset */ + if (!target_was_examined(target)) + retval = aarch64_examine_first(target); + + /* Configure core debug access */ + if (retval == ERROR_OK) + retval = aarch64_init_debug_access(target); + + return retval; +} + +/* + * Cortex-A8 target creation and initialization + */ + +static int aarch64_init_target(struct command_context *cmd_ctx, + struct target *target) +{ + /* examine_first() does a bunch of this */ + return ERROR_OK; +} + +static int aarch64_init_arch_info(struct target *target, + struct aarch64_common *aarch64, struct jtag_tap *tap) +{ + struct armv8_common *armv8 = &aarch64->armv8_common; + struct adiv5_dap *dap = armv8->arm.dap; + + armv8->arm.dap = dap; + + /* Setup struct aarch64_common */ + aarch64->common_magic = AARCH64_COMMON_MAGIC; + /* tap has no dap initialized */ + if (!tap->dap) { + tap->dap = dap_init(); + + /* Leave (only) generic DAP stuff for debugport_init() */ + tap->dap->tap = tap; + } + + armv8->arm.dap = tap->dap; + + aarch64->fast_reg_read = 0; + + /* register arch-specific functions */ + armv8->examine_debug_reason = NULL; + + armv8->post_debug_entry = aarch64_post_debug_entry; + + armv8->pre_restore_context = NULL; + + armv8->armv8_mmu.read_physical_memory = aarch64_read_phys_memory; + + /* REVISIT v7a setup should be in a v7a-specific routine */ + armv8_init_arch_info(target, armv8); + target_register_timer_callback(aarch64_handle_target_request, 1, 1, target); + + return ERROR_OK; +} + +static int aarch64_target_create(struct target *target, Jim_Interp *interp) +{ + struct aarch64_common *aarch64 = calloc(1, sizeof(struct aarch64_common)); + + aarch64->armv8_common.is_armv7r = false; + + return aarch64_init_arch_info(target, aarch64, target->tap); +} + +static int aarch64_mmu(struct target *target, int *enabled) +{ + if (target->state != TARGET_HALTED) { + LOG_ERROR("%s: target not halted", __func__); + return ERROR_TARGET_INVALID; + } + + *enabled = target_to_aarch64(target)->armv8_common.armv8_mmu.mmu_enabled; + return ERROR_OK; +} + +static int aarch64_virt2phys(struct target *target, target_addr_t virt, + target_addr_t *phys) +{ + int retval = ERROR_FAIL; + struct armv8_common *armv8 = target_to_armv8(target); + struct adiv5_dap *swjdp = armv8->arm.dap; + uint8_t apsel = swjdp->apsel; + if (armv8->memory_ap_available && (apsel == armv8->memory_ap->ap_num)) { + uint32_t ret; + retval = armv8_mmu_translate_va(target, + virt, &ret); + if (retval != ERROR_OK) + goto done; + *phys = ret; + } else {/* use this method if armv8->memory_ap not selected + * mmu must be enable in order to get a correct translation */ + retval = aarch64_mmu_modify(target, 1); + if (retval != ERROR_OK) + goto done; + retval = armv8_mmu_translate_va_pa(target, virt, phys, 1); + } +done: + return retval; +} + +COMMAND_HANDLER(aarch64_handle_cache_info_command) +{ + struct target *target = get_current_target(CMD_CTX); + struct armv8_common *armv8 = target_to_armv8(target); + + return armv8_handle_cache_info_command(CMD_CTX, + &armv8->armv8_mmu.armv8_cache); +} + + +COMMAND_HANDLER(aarch64_handle_dbginit_command) +{ + struct target *target = get_current_target(CMD_CTX); + if (!target_was_examined(target)) { + LOG_ERROR("target not examined yet"); + return ERROR_FAIL; + } + + return aarch64_init_debug_access(target); +} +COMMAND_HANDLER(aarch64_handle_smp_off_command) +{ + struct target *target = get_current_target(CMD_CTX); + /* check target is an smp target */ + struct target_list *head; + struct target *curr; + head = target->head; + target->smp = 0; + if (head != (struct target_list *)NULL) { + while (head != (struct target_list *)NULL) { + curr = head->target; + curr->smp = 0; + head = head->next; + } + /* fixes the target display to the debugger */ + target->gdb_service->target = target; + } + return ERROR_OK; +} + +COMMAND_HANDLER(aarch64_handle_smp_on_command) +{ + struct target *target = get_current_target(CMD_CTX); + struct target_list *head; + struct target *curr; + head = target->head; + if (head != (struct target_list *)NULL) { + target->smp = 1; + while (head != (struct target_list *)NULL) { + curr = head->target; + curr->smp = 1; + head = head->next; + } + } + return ERROR_OK; +} + +COMMAND_HANDLER(aarch64_handle_smp_gdb_command) +{ + struct target *target = get_current_target(CMD_CTX); + int retval = ERROR_OK; + struct target_list *head; + head = target->head; + if (head != (struct target_list *)NULL) { + if (CMD_ARGC == 1) { + int coreid = 0; + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid); + if (ERROR_OK != retval) + return retval; + target->gdb_service->core[1] = coreid; + + } + command_print(CMD_CTX, "gdb coreid %" PRId32 " -> %" PRId32, target->gdb_service->core[0] + , target->gdb_service->core[1]); + } + return ERROR_OK; +} + +static const struct command_registration aarch64_exec_command_handlers[] = { + { + .name = "cache_info", + .handler = aarch64_handle_cache_info_command, + .mode = COMMAND_EXEC, + .help = "display information about target caches", + .usage = "", + }, + { + .name = "dbginit", + .handler = aarch64_handle_dbginit_command, + .mode = COMMAND_EXEC, + .help = "Initialize core debug", + .usage = "", + }, + { .name = "smp_off", + .handler = aarch64_handle_smp_off_command, + .mode = COMMAND_EXEC, + .help = "Stop smp handling", + .usage = "", + }, + { + .name = "smp_on", + .handler = aarch64_handle_smp_on_command, + .mode = COMMAND_EXEC, + .help = "Restart smp handling", + .usage = "", + }, + { + .name = "smp_gdb", + .handler = aarch64_handle_smp_gdb_command, + .mode = COMMAND_EXEC, + .help = "display/fix current core played to gdb", + .usage = "", + }, + + + COMMAND_REGISTRATION_DONE +}; +static const struct command_registration aarch64_command_handlers[] = { + { + .chain = arm_command_handlers, + }, + { + .chain = armv8_command_handlers, + }, + { + .name = "cortex_a", + .mode = COMMAND_ANY, + .help = "Cortex-A command group", + .usage = "", + .chain = aarch64_exec_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + +struct target_type aarch64_target = { + .name = "aarch64", + + .poll = aarch64_poll, + .arch_state = armv8_arch_state, + + .halt = aarch64_halt, + .resume = aarch64_resume, + .step = aarch64_step, + + .assert_reset = aarch64_assert_reset, + .deassert_reset = aarch64_deassert_reset, + + /* REVISIT allow exporting VFP3 registers ... */ + .get_gdb_reg_list = armv8_get_gdb_reg_list, + + .read_memory = aarch64_read_memory, + .write_memory = aarch64_write_memory, + + .checksum_memory = arm_checksum_memory, + .blank_check_memory = arm_blank_check_memory, + + .run_algorithm = armv4_5_run_algorithm, + + .add_breakpoint = aarch64_add_breakpoint, + .add_context_breakpoint = aarch64_add_context_breakpoint, + .add_hybrid_breakpoint = aarch64_add_hybrid_breakpoint, + .remove_breakpoint = aarch64_remove_breakpoint, + .add_watchpoint = NULL, + .remove_watchpoint = NULL, + + .commands = aarch64_command_handlers, + .target_create = aarch64_target_create, + .init_target = aarch64_init_target, + .examine = aarch64_examine, + + .read_phys_memory = aarch64_read_phys_memory, + .write_phys_memory = aarch64_write_phys_memory, + .mmu = aarch64_mmu, + .virt2phys = aarch64_virt2phys, +}; diff --git a/src/target/aarch64.h b/src/target/aarch64.h new file mode 100644 index 0000000..513f06d --- /dev/null +++ b/src/target/aarch64.h @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (C) 2015 by David Ung * + * * + * 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., * + ***************************************************************************/ + +#ifndef AARCH64_H +#define AARCH64_H + +#include "armv8.h" + +#define AARCH64_COMMON_MAGIC 0x411fc082 + +#define CPUDBG_CPUID 0xD00 +#define CPUDBG_CTYPR 0xD04 +#define CPUDBG_TTYPR 0xD0C +#define ID_AA64PFR0_EL1 0xD20 +#define ID_AA64DFR0_EL1 0xD28 +#define CPUDBG_LOCKACCESS 0xFB0 +#define CPUDBG_LOCKSTATUS 0xFB4 + +#define BRP_NORMAL 0 +#define BRP_CONTEXT 1 + +#define AARCH64_PADDRDBG_CPU_SHIFT 13 + +struct aarch64_brp { + int used; + int type; + target_addr_t value; + uint32_t control; + uint8_t BRPn; +}; + +struct aarch64_common { + int common_magic; + + /* Context information */ + uint32_t cpudbg_dscr; + + uint32_t system_control_reg; + uint32_t system_control_reg_curr; + + enum arm_mode curr_mode; + + + /* Breakpoint register pairs */ + int brp_num_context; + int brp_num; + int brp_num_available; + struct aarch64_brp *brp_list; + + /* Use aarch64_read_regs_through_mem for fast register reads */ + int fast_reg_read; + + struct armv8_common armv8_common; + +}; + +static inline struct aarch64_common * +target_to_aarch64(struct target *target) +{ + return container_of(target->arch_info, struct aarch64_common, armv8_common.arm); +} + +#endif /* AARCH64_H */ diff --git a/src/target/arm.h b/src/target/arm.h index 5713fc0..e4f2038 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -218,6 +218,7 @@ struct arm_reg { }; struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm); +struct reg_cache *armv8_build_reg_cache(struct target *target); extern const struct command_registration arm_command_handlers[]; @@ -225,6 +226,9 @@ int arm_arch_state(struct target *target); int arm_get_gdb_reg_list(struct target *target, struct reg **reg_list[], int *reg_list_size, enum target_register_class reg_class); +int armv8_get_gdb_reg_list(struct target *target, + struct reg **reg_list[], int *reg_list_size, + enum target_register_class reg_class); int arm_init_arch_info(struct target *target, struct arm *arm); @@ -249,6 +253,7 @@ int arm_blank_check_memory(struct target *target, void arm_set_cpsr(struct arm *arm, uint32_t cpsr); struct reg *arm_reg_current(struct arm *arm, unsigned regnum); +struct reg *armv8_reg_current(struct arm *arm, unsigned regnum); extern struct reg arm_gdb_dummy_fp_reg; extern struct reg arm_gdb_dummy_fps_reg; diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index 0c84be5..55f253e 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -299,10 +299,15 @@ static int dpm_write_reg64(struct arm_dpm *dpm, struct reg *r, unsigned regnum) switch (regnum) { case 0 ... 30: i = 0xd5330400 + regnum; - retval = dpm->instr_write_data_dcc(dpm, i, value); + retval = dpm->instr_write_data_dcc_64(dpm, i, value); + break; + case 32: /* PC */ + i = 0xd51b4520; + retval = dpm->instr_write_data_r0_64(dpm, i, value); break; - default: + LOG_DEBUG("register %s (%16.16llx) not defined", r->name, + (unsigned long long)value); break; } @@ -354,6 +359,9 @@ static int arm_dpm_read_current_registers_i(struct arm_dpm *dpm) /* update core mode and state, plus shadow mapping for R8..R14 */ arm_set_cpsr(arm, cpsr); + if (core_state == ARM_STATE_AARCH64) + /* arm_set_cpsr changes core_state, restore it for now */ + arm->core_state = ARM_STATE_AARCH64; core_regs = arm->core_cache->num_regs; @@ -573,7 +581,7 @@ static int arm_dpm_write_dirty_registers_64(struct arm_dpm *dpm) */ /* check everything except our scratch register R0 */ - for (unsigned i = 1; i < 32; i++) { + for (unsigned i = 1; i <= 32; i++) { struct arm_reg *r; unsigned regnum; @@ -1119,7 +1127,7 @@ int arm_dpm_setup(struct arm_dpm *dpm) { struct arm *arm = dpm->arm; struct target *target = arm->target; - struct reg_cache *cache; + struct reg_cache *cache = 0; arm->dpm = dpm; @@ -1128,13 +1136,17 @@ int arm_dpm_setup(struct arm_dpm *dpm) arm->read_core_reg = arm->read_core_reg ? : arm_dpm_read_core_reg; arm->write_core_reg = arm->write_core_reg ? : arm_dpm_write_core_reg; - /* avoid duplicating the register cache */ - if (arm->core_cache == NULL) { - cache = arm_build_reg_cache(target, arm); + if (arm->core_cache != NULL) { + if (arm->core_state == ARM_STATE_AARCH64) { + cache = armv8_build_reg_cache(target); + target->reg_cache = cache; + } else { + cache = arm_build_reg_cache(target, arm); + *register_get_last_cache_p(&target->reg_cache) = cache; + } + if (!cache) return ERROR_FAIL; - - *register_get_last_cache_p(&target->reg_cache) = cache; } /* coprocessor access setup */ diff --git a/src/target/arm_dpm.h b/src/target/arm_dpm.h index 9cc0304..5b16e64 100644 --- a/src/target/arm_dpm.h +++ b/src/target/arm_dpm.h @@ -73,10 +73,17 @@ struct arm_dpm { int (*instr_write_data_dcc)(struct arm_dpm *, uint32_t opcode, uint32_t data); + int (*instr_write_data_dcc_64)(struct arm_dpm *, + uint32_t opcode, uint64_t data); + /** Runs one instruction, writing data to R0 before execution. */ int (*instr_write_data_r0)(struct arm_dpm *, uint32_t opcode, uint32_t data); + /** Runs one instruction, writing data to R0 before execution. */ + int (*instr_write_data_r0_64)(struct arm_dpm *, + uint32_t opcode, uint64_t data); + /** Optional core-specific operation invoked after CPSR writes. */ int (*instr_cpsr_sync)(struct arm_dpm *dpm); diff --git a/src/target/armv8.c b/src/target/armv8.c new file mode 100644 index 0000000..902d290 --- /dev/null +++ b/src/target/armv8.c @@ -0,0 +1,774 @@ +/*************************************************************************** + * Copyright (C) 2015 by David Ung * + * * + * 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., * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "armv8.h" +#include "arm_disassembler.h" + +#include "register.h" +#include +#include + +#include +#include +#include + +#include "arm_opcodes.h" +#include "target.h" +#include "target_type.h" + +static int armv8_read_core_reg(struct target *target, struct reg *r, + int num, enum arm_mode mode) +{ + uint64_t reg_value; + int retval; + struct arm_reg *armv8_core_reg; + struct armv8_common *armv8 = target_to_armv8(target); + + assert(num < (int)armv8->arm.core_cache->num_regs); + + armv8_core_reg = armv8->arm.core_cache->reg_list[num].arch_info; + retval = armv8->load_core_reg_u64(target, + armv8_core_reg->num, ®_value); + + buf_set_u64(armv8->arm.core_cache->reg_list[num].value, 0, 64, reg_value); + armv8->arm.core_cache->reg_list[num].valid = 1; + armv8->arm.core_cache->reg_list[num].dirty = 0; + + return retval; +} + +#if 0 +static int armv8_write_core_reg(struct target *target, struct reg *r, + int num, enum arm_mode mode, target_addr_t value) +{ + int retval; + struct arm_reg *armv8_core_reg; + struct armv8_common *armv8 = target_to_armv8(target); + + assert(num < (int)armv8->arm.core_cache->num_regs); + + armv8_core_reg = armv8->arm.core_cache->reg_list[num].arch_info; + retval = armv8->store_core_reg_u64(target, + armv8_core_reg->num, + value); + if (retval != ERROR_OK) { + LOG_ERROR("JTAG failure"); + armv8->arm.core_cache->reg_list[num].dirty = armv8->arm.core_cache->reg_list[num].valid; + return ERROR_JTAG_DEVICE_ERROR; + } + + LOG_DEBUG("write core reg %i value 0x%" PRIx64 "", num, value); + armv8->arm.core_cache->reg_list[num].valid = 1; + armv8->arm.core_cache->reg_list[num].dirty = 0; + + return ERROR_OK; +} +#endif + +static void armv8_show_fault_registers(struct target *target) +{ + /* TODO */ +} + +static int armv8_read_ttbcr(struct target *target) +{ + struct armv8_common *armv8 = target_to_armv8(target); + struct arm_dpm *dpm = armv8->arm.dpm; + uint32_t ttbcr; + int retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + /* MRC p15,0,,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/ + retval = dpm->instr_read_data_r0(dpm, + ARMV4_5_MRC(15, 0, 0, 2, 0, 2), + &ttbcr); + if (retval != ERROR_OK) + goto done; + armv8->armv8_mmu.ttbr1_used = ((ttbcr & 0x7) != 0) ? 1 : 0; + armv8->armv8_mmu.ttbr0_mask = 7 << (32 - ((ttbcr & 0x7))); +#if 0 + LOG_INFO("ttb1 %s ,ttb0_mask %x", + armv8->armv8_mmu.ttbr1_used ? "used" : "not used", + armv8->armv8_mmu.ttbr0_mask); +#endif + if (armv8->armv8_mmu.ttbr1_used == 1) { + LOG_INFO("SVC access above %" PRIx32, + (uint32_t)(0xffffffff & armv8->armv8_mmu.ttbr0_mask)); + armv8->armv8_mmu.os_border = 0xffffffff & armv8->armv8_mmu.ttbr0_mask; + } else { + /* fix me , default is hard coded LINUX border */ + armv8->armv8_mmu.os_border = 0xc0000000; + } +done: + dpm->finish(dpm); + return retval; +} + + +/* method adapted to cortex A : reused arm v4 v5 method*/ +int armv8_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val) +{ + uint32_t first_lvl_descriptor = 0x0; + uint32_t second_lvl_descriptor = 0x0; + int retval; + struct armv8_common *armv8 = target_to_armv8(target); + struct arm_dpm *dpm = armv8->arm.dpm; + uint32_t ttb = 0; /* default ttb0 */ + if (armv8->armv8_mmu.ttbr1_used == -1) + armv8_read_ttbcr(target); + if ((armv8->armv8_mmu.ttbr1_used) && + (va > (0xffffffff & armv8->armv8_mmu.ttbr0_mask))) { + /* select ttb 1 */ + ttb = 1; + } + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + + /* MRC p15,0,,c2,c0,ttb */ + retval = dpm->instr_read_data_r0(dpm, + ARMV4_5_MRC(15, 0, 0, 2, 0, ttb), + &ttb); + if (retval != ERROR_OK) + return retval; + retval = armv8->armv8_mmu.read_physical_memory(target, + (ttb & 0xffffc000) | ((va & 0xfff00000) >> 18), + 4, 1, (uint8_t *)&first_lvl_descriptor); + if (retval != ERROR_OK) + return retval; + first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *) + &first_lvl_descriptor); + /* reuse armv4_5 piece of code, specific armv8 changes may come later */ + LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor); + + if ((first_lvl_descriptor & 0x3) == 0) { + LOG_ERROR("Address translation failure"); + return ERROR_TARGET_TRANSLATION_FAULT; + } + + + if ((first_lvl_descriptor & 0x3) == 2) { + /* section descriptor */ + *val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff); + return ERROR_OK; + } + + if ((first_lvl_descriptor & 0x3) == 1) { + /* coarse page table */ + retval = armv8->armv8_mmu.read_physical_memory(target, + (first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10), + 4, 1, (uint8_t *)&second_lvl_descriptor); + if (retval != ERROR_OK) + return retval; + } else if ((first_lvl_descriptor & 0x3) == 3) { + /* fine page table */ + retval = armv8->armv8_mmu.read_physical_memory(target, + (first_lvl_descriptor & 0xfffff000) | ((va & 0x000ffc00) >> 8), + 4, 1, (uint8_t *)&second_lvl_descriptor); + if (retval != ERROR_OK) + return retval; + } + + second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *) + &second_lvl_descriptor); + + LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor); + + if ((second_lvl_descriptor & 0x3) == 0) { + LOG_ERROR("Address translation failure"); + return ERROR_TARGET_TRANSLATION_FAULT; + } + + if ((second_lvl_descriptor & 0x3) == 1) { + /* large page descriptor */ + *val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff); + return ERROR_OK; + } + + if ((second_lvl_descriptor & 0x3) == 2) { + /* small page descriptor */ + *val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff); + return ERROR_OK; + } + + if ((second_lvl_descriptor & 0x3) == 3) { + *val = (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff); + return ERROR_OK; + } + + /* should not happen */ + LOG_ERROR("Address translation failure"); + return ERROR_TARGET_TRANSLATION_FAULT; + +done: + return retval; +} + +/* V8 method VA TO PA */ +int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, + target_addr_t *val, int meminfo) +{ + return ERROR_OK; +} + +static int armv8_handle_inner_cache_info_command(struct command_context *cmd_ctx, + struct armv8_cache_common *armv8_cache) +{ + if (armv8_cache->ctype == -1) { + command_print(cmd_ctx, "cache not yet identified"); + return ERROR_OK; + } + + command_print(cmd_ctx, + "D-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes", + armv8_cache->d_u_size.linelen, + armv8_cache->d_u_size.associativity, + armv8_cache->d_u_size.nsets, + armv8_cache->d_u_size.cachesize); + + command_print(cmd_ctx, + "I-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes", + armv8_cache->i_size.linelen, + armv8_cache->i_size.associativity, + armv8_cache->i_size.nsets, + armv8_cache->i_size.cachesize); + + return ERROR_OK; +} + +static int _armv8_flush_all_data(struct target *target) +{ + struct armv8_common *armv8 = target_to_armv8(target); + struct arm_dpm *dpm = armv8->arm.dpm; + struct armv8_cachesize *d_u_size = + &(armv8->armv8_mmu.armv8_cache.d_u_size); + int32_t c_way, c_index = d_u_size->index; + int retval; + /* check that cache data is on at target halt */ + if (!armv8->armv8_mmu.armv8_cache.d_u_cache_enabled) { + LOG_INFO("flushed not performed :cache not on at target halt"); + return ERROR_OK; + } + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + do { + c_way = d_u_size->way; + do { + uint32_t value = (c_index << d_u_size->index_shift) + | (c_way << d_u_size->way_shift); + /* DCCISW */ + /* LOG_INFO ("%d %d %x",c_way,c_index,value); */ + retval = dpm->instr_write_data_r0(dpm, + ARMV4_5_MCR(15, 0, 0, 7, 14, 2), + value); + if (retval != ERROR_OK) + goto done; + c_way -= 1; + } while (c_way >= 0); + c_index -= 1; + } while (c_index >= 0); + return retval; +done: + LOG_ERROR("flushed failed"); + dpm->finish(dpm); + return retval; +} + +static int armv8_flush_all_data(struct target *target) +{ + int retval = ERROR_FAIL; + /* check that armv8_cache is correctly identify */ + struct armv8_common *armv8 = target_to_armv8(target); + if (armv8->armv8_mmu.armv8_cache.ctype == -1) { + LOG_ERROR("trying to flush un-identified cache"); + return retval; + } + + if (target->smp) { + /* look if all the other target have been flushed in order to flush level + * 2 */ + struct target_list *head; + struct target *curr; + head = target->head; + while (head != (struct target_list *)NULL) { + curr = head->target; + if (curr->state == TARGET_HALTED) { + LOG_INFO("Wait flushing data l1 on core %" PRId32, curr->coreid); + retval = _armv8_flush_all_data(curr); + } + head = head->next; + } + } else + retval = _armv8_flush_all_data(target); + return retval; +} + +int armv8_handle_cache_info_command(struct command_context *cmd_ctx, + struct armv8_cache_common *armv8_cache) +{ + if (armv8_cache->ctype == -1) { + command_print(cmd_ctx, "cache not yet identified"); + return ERROR_OK; + } + + if (armv8_cache->display_cache_info) + armv8_cache->display_cache_info(cmd_ctx, armv8_cache); + return ERROR_OK; +} + +/* retrieve core id cluster id */ +static int armv8_read_mpidr(struct target *target) +{ + int retval = ERROR_FAIL; + struct armv8_common *armv8 = target_to_armv8(target); + struct arm_dpm *dpm = armv8->arm.dpm; + uint32_t mpidr; + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + /* MRC p15,0,,c0,c0,5; read Multiprocessor ID register*/ + + retval = dpm->instr_read_data_r0(dpm, + ARMV4_5_MRC(15, 0, 0, 0, 0, 5), + &mpidr); + if (retval != ERROR_OK) + goto done; + if (mpidr & 1<<31) { + armv8->multi_processor_system = (mpidr >> 30) & 1; + armv8->cluster_id = (mpidr >> 8) & 0xf; + armv8->cpu_id = mpidr & 0x3; + LOG_INFO("%s cluster %x core %x %s", target_name(target), + armv8->cluster_id, + armv8->cpu_id, + armv8->multi_processor_system == 0 ? "multi core" : "mono core"); + + } else + LOG_ERROR("mpdir not in multiprocessor format"); + +done: + dpm->finish(dpm); + return retval; + + +} + +int armv8_identify_cache(struct target *target) +{ + /* read cache descriptor */ + int retval = ERROR_FAIL; + struct armv8_common *armv8 = target_to_armv8(target); + struct arm_dpm *dpm = armv8->arm.dpm; + uint32_t cache_selected, clidr; + uint32_t cache_i_reg, cache_d_reg; + struct armv8_cache_common *cache = &(armv8->armv8_mmu.armv8_cache); + if (!armv8->is_armv7r) + armv8_read_ttbcr(target); + retval = dpm->prepare(dpm); + + if (retval != ERROR_OK) + goto done; + /* retrieve CLIDR + * mrc p15, 1, r0, c0, c0, 1 @ read clidr */ + retval = dpm->instr_read_data_r0(dpm, + ARMV4_5_MRC(15, 1, 0, 0, 0, 1), + &clidr); + if (retval != ERROR_OK) + goto done; + clidr = (clidr & 0x7000000) >> 23; + LOG_INFO("number of cache level %" PRIx32, (uint32_t)(clidr / 2)); + if ((clidr / 2) > 1) { + /* FIXME not supported present in cortex A8 and later */ + /* in cortex A7, A15 */ + LOG_ERROR("cache l2 present :not supported"); + } + /* retrieve selected cache + * MRC p15, 2,, c0, c0, 0; Read CSSELR */ + retval = dpm->instr_read_data_r0(dpm, + ARMV4_5_MRC(15, 2, 0, 0, 0, 0), + &cache_selected); + if (retval != ERROR_OK) + goto done; + + retval = armv8->arm.mrc(target, 15, + 2, 0, /* op1, op2 */ + 0, 0, /* CRn, CRm */ + &cache_selected); + if (retval != ERROR_OK) + goto done; + /* select instruction cache + * MCR p15, 2,, c0, c0, 0; Write CSSELR + * [0] : 1 instruction cache selection , 0 data cache selection */ + retval = dpm->instr_write_data_r0(dpm, + ARMV4_5_MRC(15, 2, 0, 0, 0, 0), + 1); + if (retval != ERROR_OK) + goto done; + + /* read CCSIDR + * MRC P15,1,,C0, C0,0 ;on cortex A9 read CCSIDR + * [2:0] line size 001 eight word per line + * [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */ + retval = dpm->instr_read_data_r0(dpm, + ARMV4_5_MRC(15, 1, 0, 0, 0, 0), + &cache_i_reg); + if (retval != ERROR_OK) + goto done; + + /* select data cache*/ + retval = dpm->instr_write_data_r0(dpm, + ARMV4_5_MRC(15, 2, 0, 0, 0, 0), + 0); + if (retval != ERROR_OK) + goto done; + + retval = dpm->instr_read_data_r0(dpm, + ARMV4_5_MRC(15, 1, 0, 0, 0, 0), + &cache_d_reg); + if (retval != ERROR_OK) + goto done; + + /* restore selected cache */ + dpm->instr_write_data_r0(dpm, + ARMV4_5_MRC(15, 2, 0, 0, 0, 0), + cache_selected); + + if (retval != ERROR_OK) + goto done; + dpm->finish(dpm); + + /* put fake type */ + cache->d_u_size.linelen = 16 << (cache_d_reg & 0x7); + cache->d_u_size.cachesize = (((cache_d_reg >> 13) & 0x7fff)+1)/8; + cache->d_u_size.nsets = (cache_d_reg >> 13) & 0x7fff; + cache->d_u_size.associativity = ((cache_d_reg >> 3) & 0x3ff) + 1; + /* compute info for set way operation on cache */ + cache->d_u_size.index_shift = (cache_d_reg & 0x7) + 4; + cache->d_u_size.index = (cache_d_reg >> 13) & 0x7fff; + cache->d_u_size.way = ((cache_d_reg >> 3) & 0x3ff); + cache->d_u_size.way_shift = cache->d_u_size.way + 1; + { + int i = 0; + while (((cache->d_u_size.way_shift >> i) & 1) != 1) + i++; + cache->d_u_size.way_shift = 32-i; + } +#if 0 + LOG_INFO("data cache index %d << %d, way %d << %d", + cache->d_u_size.index, cache->d_u_size.index_shift, + cache->d_u_size.way, + cache->d_u_size.way_shift); + + LOG_INFO("data cache %d bytes %d KBytes asso %d ways", + cache->d_u_size.linelen, + cache->d_u_size.cachesize, + cache->d_u_size.associativity); +#endif + cache->i_size.linelen = 16 << (cache_i_reg & 0x7); + cache->i_size.associativity = ((cache_i_reg >> 3) & 0x3ff) + 1; + cache->i_size.nsets = (cache_i_reg >> 13) & 0x7fff; + cache->i_size.cachesize = (((cache_i_reg >> 13) & 0x7fff)+1)/8; + /* compute info for set way operation on cache */ + cache->i_size.index_shift = (cache_i_reg & 0x7) + 4; + cache->i_size.index = (cache_i_reg >> 13) & 0x7fff; + cache->i_size.way = ((cache_i_reg >> 3) & 0x3ff); + cache->i_size.way_shift = cache->i_size.way + 1; + { + int i = 0; + while (((cache->i_size.way_shift >> i) & 1) != 1) + i++; + cache->i_size.way_shift = 32-i; + } +#if 0 + LOG_INFO("instruction cache index %d << %d, way %d << %d", + cache->i_size.index, cache->i_size.index_shift, + cache->i_size.way, cache->i_size.way_shift); + + LOG_INFO("instruction cache %d bytes %d KBytes asso %d ways", + cache->i_size.linelen, + cache->i_size.cachesize, + cache->i_size.associativity); +#endif + /* if no l2 cache initialize l1 data cache flush function function */ + if (armv8->armv8_mmu.armv8_cache.flush_all_data_cache == NULL) { + armv8->armv8_mmu.armv8_cache.display_cache_info = + armv8_handle_inner_cache_info_command; + armv8->armv8_mmu.armv8_cache.flush_all_data_cache = + armv8_flush_all_data; + } + armv8->armv8_mmu.armv8_cache.ctype = 0; + +done: + dpm->finish(dpm); + armv8_read_mpidr(target); + return retval; + +} + +int armv8_init_arch_info(struct target *target, struct armv8_common *armv8) +{ + struct arm *arm = &armv8->arm; + arm->arch_info = armv8; + target->arch_info = &armv8->arm; + /* target is useful in all function arm v4 5 compatible */ + armv8->arm.target = target; + armv8->arm.common_magic = ARM_COMMON_MAGIC; + armv8->common_magic = ARMV8_COMMON_MAGIC; + + arm->read_core_reg = armv8_read_core_reg; +#if 0 + arm->write_core_reg = armv8_write_core_reg; +#endif + + armv8->armv8_mmu.armv8_cache.l2_cache = NULL; + armv8->armv8_mmu.armv8_cache.ctype = -1; + armv8->armv8_mmu.armv8_cache.flush_all_data_cache = NULL; + armv8->armv8_mmu.armv8_cache.display_cache_info = NULL; + return ERROR_OK; +} + +int armv8_arch_state(struct target *target) +{ + static const char * const state[] = { + "disabled", "enabled" + }; + + struct armv8_common *armv8 = target_to_armv8(target); + struct arm *arm = &armv8->arm; + + if (armv8->common_magic != ARMV8_COMMON_MAGIC) { + LOG_ERROR("BUG: called for a non-Armv8 target"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + arm_arch_state(target); + + if (armv8->is_armv7r) { + LOG_USER("D-Cache: %s, I-Cache: %s", + state[armv8->armv8_mmu.armv8_cache.d_u_cache_enabled], + state[armv8->armv8_mmu.armv8_cache.i_cache_enabled]); + } else { + LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s", + state[armv8->armv8_mmu.mmu_enabled], + state[armv8->armv8_mmu.armv8_cache.d_u_cache_enabled], + state[armv8->armv8_mmu.armv8_cache.i_cache_enabled]); + } + + if (arm->core_mode == ARM_MODE_ABT) + armv8_show_fault_registers(target); + if (target->debug_reason == DBG_REASON_WATCHPOINT) + LOG_USER("Watchpoint triggered at PC %#08x", + (unsigned) armv8->dpm.wp_pc); + + return ERROR_OK; +} + +static const struct { + unsigned id; + const char *name; + unsigned bits; + enum reg_type type; + const char *group; + const char *feature; +} armv8_regs[] = { + { ARMV8_R0, "x0", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R1, "x1", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R2, "x2", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R3, "x3", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R4, "x4", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R5, "x5", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R6, "x6", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R7, "x7", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R8, "x8", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R9, "x9", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R10, "x10", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R11, "x11", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R12, "x12", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R13, "x13", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R14, "x14", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R15, "x15", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R16, "x16", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R17, "x17", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R18, "x18", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R19, "x19", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R20, "x20", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R21, "x21", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R22, "x22", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R23, "x23", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R24, "x24", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R25, "x25", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R26, "x26", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R27, "x27", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R28, "x28", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R29, "x29", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R30, "x30", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + + { ARMV8_R31, "sp", 64, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_PC, "pc", 64, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.aarch64.core" }, + + { ARMV8_xPSR, "CPSR", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, +}; + +#define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs) + + +static int armv8_get_core_reg(struct reg *reg) +{ + int retval; + struct arm_reg *armv8_reg = reg->arch_info; + struct target *target = armv8_reg->target; + struct arm *arm = target_to_arm(target); + + if (target->state != TARGET_HALTED) + return ERROR_TARGET_NOT_HALTED; + + retval = arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode); + + return retval; +} + +static int armv8_set_core_reg(struct reg *reg, uint8_t *buf) +{ + struct arm_reg *armv8_reg = reg->arch_info; + struct target *target = armv8_reg->target; + uint64_t value = buf_get_u64(buf, 0, 64); + + if (target->state != TARGET_HALTED) + return ERROR_TARGET_NOT_HALTED; + + buf_set_u64(reg->value, 0, 64, value); + reg->dirty = 1; + reg->valid = 1; + + return ERROR_OK; +} + +static const struct reg_arch_type armv8_reg_type = { + .get = armv8_get_core_reg, + .set = armv8_set_core_reg, +}; + +/** Builds cache of architecturally defined registers. */ +struct reg_cache *armv8_build_reg_cache(struct target *target) +{ + struct armv8_common *armv8 = target_to_armv8(target); + struct arm *arm = &armv8->arm; + int num_regs = ARMV8_NUM_REGS; + struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache); + struct reg_cache *cache = malloc(sizeof(struct reg_cache)); + struct reg *reg_list = calloc(num_regs, sizeof(struct reg)); + struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg)); + struct reg_feature *feature; + int i; + + /* Build the process context cache */ + cache->name = "arm v8 registers"; + cache->next = NULL; + cache->reg_list = reg_list; + cache->num_regs = num_regs; + (*cache_p) = cache; + + for (i = 0; i < num_regs; i++) { + arch_info[i].num = armv8_regs[i].id; + arch_info[i].target = target; + arch_info[i].arm = arm; + + reg_list[i].name = armv8_regs[i].name; + reg_list[i].size = armv8_regs[i].bits; + reg_list[i].value = calloc(1, 4); + reg_list[i].dirty = 0; + reg_list[i].valid = 0; + reg_list[i].type = &armv8_reg_type; + reg_list[i].arch_info = &arch_info[i]; + + reg_list[i].group = armv8_regs[i].group; + reg_list[i].number = i; + reg_list[i].exist = true; + reg_list[i].caller_save = true; /* gdb defaults to true */ + + feature = calloc(1, sizeof(struct reg_feature)); + if (feature) { + feature->name = armv8_regs[i].feature; + reg_list[i].feature = feature; + } else + LOG_ERROR("unable to allocate feature list"); + + reg_list[i].reg_data_type = calloc(1, sizeof(struct reg_data_type)); + if (reg_list[i].reg_data_type) + reg_list[i].reg_data_type->type = armv8_regs[i].type; + else + LOG_ERROR("unable to allocate reg type list"); + } + + arm->cpsr = reg_list + ARMV8_xPSR; + arm->pc = reg_list + ARMV8_PC; + arm->core_cache = cache; + + return cache; +} + +struct reg *armv8_reg_current(struct arm *arm, unsigned regnum) +{ + struct reg *r; + + if (regnum > 33) + return NULL; + + r = arm->core_cache->reg_list + regnum; + return r; +} + +const struct command_registration armv8_command_handlers[] = { + { + .chain = dap_command_handlers, + }, + COMMAND_REGISTRATION_DONE +}; + + +int armv8_get_gdb_reg_list(struct target *target, + struct reg **reg_list[], int *reg_list_size, + enum target_register_class reg_class) +{ + struct arm *arm = target_to_arm(target); + int i; + + switch (reg_class) { + case REG_CLASS_GENERAL: + case REG_CLASS_ALL: + *reg_list_size = 34; + *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); + + for (i = 0; i < *reg_list_size; i++) + (*reg_list)[i] = armv8_reg_current(arm, i); + + return ERROR_OK; + break; + + default: + LOG_ERROR("not a valid register class type in query."); + return ERROR_FAIL; + break; + } +} diff --git a/src/target/armv8.h b/src/target/armv8.h new file mode 100644 index 0000000..080237d --- /dev/null +++ b/src/target/armv8.h @@ -0,0 +1,201 @@ +/*************************************************************************** + * Copyright (C) 2015 by David Ung * + * * + * 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., * + ***************************************************************************/ + +#ifndef OPENOCD_TARGET_ARMV8_H +#define OPENOCD_TARGET_ARMV8_H + +#include "arm_adi_v5.h" +#include "arm.h" +#include "armv4_5_mmu.h" +#include "armv4_5_cache.h" +#include "arm_dpm.h" + +enum { + ARMV8_R0, + ARMV8_R1, + ARMV8_R2, + ARMV8_R3, + ARMV8_R4, + ARMV8_R5, + ARMV8_R6, + ARMV8_R7, + ARMV8_R8, + ARMV8_R9, + ARMV8_R10, + ARMV8_R11, + ARMV8_R12, + ARMV8_R13, + ARMV8_R14, + ARMV8_R15, + ARMV8_R16, + ARMV8_R17, + ARMV8_R18, + ARMV8_R19, + ARMV8_R20, + ARMV8_R21, + ARMV8_R22, + ARMV8_R23, + ARMV8_R24, + ARMV8_R25, + ARMV8_R26, + ARMV8_R27, + ARMV8_R28, + ARMV8_R29, + ARMV8_R30, + ARMV8_R31, + + ARMV8_PC = 32, + ARMV8_xPSR = 33, + + ARMV8_LAST_REG, +}; + + +#define ARMV8_COMMON_MAGIC 0x0A450AAA + +/* VA to PA translation operations opc2 values*/ +#define V2PCWPR 0 +#define V2PCWPW 1 +#define V2PCWUR 2 +#define V2PCWUW 3 +#define V2POWPR 4 +#define V2POWPW 5 +#define V2POWUR 6 +#define V2POWUW 7 +/* L210/L220 cache controller support */ +struct armv8_l2x_cache { + uint32_t base; + uint32_t way; +}; + +struct armv8_cachesize { + uint32_t level_num; + /* cache dimensionning */ + uint32_t linelen; + uint32_t associativity; + uint32_t nsets; + uint32_t cachesize; + /* info for set way operation on cache */ + uint32_t index; + uint32_t index_shift; + uint32_t way; + uint32_t way_shift; +}; + +struct armv8_cache_common { + int ctype; + struct armv8_cachesize d_u_size; /* data cache */ + struct armv8_cachesize i_size; /* instruction cache */ + int i_cache_enabled; + int d_u_cache_enabled; + /* l2 external unified cache if some */ + void *l2_cache; + int (*flush_all_data_cache)(struct target *target); + int (*display_cache_info)(struct command_context *cmd_ctx, + struct armv8_cache_common *armv8_cache); +}; + +struct armv8_mmu_common { + /* following field mmu working way */ + int32_t ttbr1_used; /* -1 not initialized, 0 no ttbr1 1 ttbr1 used and */ + uint32_t ttbr0_mask;/* masked to be used */ + uint32_t os_border; + + int (*read_physical_memory)(struct target *target, target_addr_t address, + uint32_t size, uint32_t count, uint8_t *buffer); + struct armv8_cache_common armv8_cache; + uint32_t mmu_enabled; +}; + +struct armv8_common { + struct arm arm; + int common_magic; + struct reg_cache *core_cache; + + /* Core Debug Unit */ + struct arm_dpm dpm; + uint32_t debug_base; + struct adiv5_ap *debug_ap; + struct adiv5_ap *memory_ap; + bool memory_ap_available; + /* mdir */ + uint8_t multi_processor_system; + uint8_t cluster_id; + uint8_t cpu_id; + bool is_armv7r; + + /* cache specific to V7 Memory Management Unit compatible with v4_5*/ + struct armv8_mmu_common armv8_mmu; + + /* Direct processor core register read and writes */ + int (*load_core_reg_u64)(struct target *target, uint32_t num, uint64_t *value); + int (*store_core_reg_u64)(struct target *target, uint32_t num, uint64_t value); + + int (*examine_debug_reason)(struct target *target); + int (*post_debug_entry)(struct target *target); + + void (*pre_restore_context)(struct target *target); +}; + +static inline struct armv8_common * +target_to_armv8(struct target *target) +{ + return container_of(target->arch_info, struct armv8_common, arm); +} + +/* register offsets from armv8.debug_base */ + +#define CPUDBG_WFAR 0x018 +/* PCSR at 0x084 -or- 0x0a0 -or- both ... based on flags in DIDR */ +#define CPUDBG_DSCR 0x088 +#define CPUDBG_DRCR 0x090 +#define CPUDBG_PRCR 0x310 +#define CPUDBG_PRSR 0x314 + +#define CPUDBG_DTRRX 0x080 +#define CPUDBG_ITR 0x084 +#define CPUDBG_DTRTX 0x08c + +#define CPUDBG_BVR_BASE 0x400 +#define CPUDBG_BCR_BASE 0x408 +#define CPUDBG_WVR_BASE 0x180 +#define CPUDBG_WCR_BASE 0x1C0 +#define CPUDBG_VCR 0x01C + +#define CPUDBG_OSLAR 0x300 +#define CPUDBG_OSLSR 0x304 +#define CPUDBG_OSSRR 0x308 +#define CPUDBG_ECR 0x024 + +#define CPUDBG_DSCCR 0x028 + +#define CPUDBG_AUTHSTATUS 0xFB8 + +int armv8_arch_state(struct target *target); +int armv8_identify_cache(struct target *target); +int armv8_init_arch_info(struct target *target, struct armv8_common *armv8); +int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, + target_addr_t *val, int meminfo); +int armv8_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val); + +int armv8_handle_cache_info_command(struct command_context *cmd_ctx, + struct armv8_cache_common *armv8_cache); + +extern const struct command_registration armv8_command_handlers[]; + +#endif diff --git a/src/target/target.c b/src/target/target.c index 40baf8e..5c2164f 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -88,6 +88,7 @@ extern struct target_type dragonite_target; extern struct target_type xscale_target; extern struct target_type cortexm_target; extern struct target_type cortexa_target; +extern struct target_type aarch64_target; extern struct target_type cortexr4_target; extern struct target_type arm11_target; extern struct target_type ls1_sap_target; @@ -135,6 +136,9 @@ static struct target_type *target_types[] = { &or1k_target, &quark_x10xx_target, &quark_d20xx_target, +#if BUILD_TARGET64 + &aarch64_target, +#endif NULL, }; -- cgit v1.1 From 236c9966dd77b7d5d678a71d467492048f347a9b Mon Sep 17 00:00:00 2001 From: pierre Kuo Date: Tue, 17 Mar 2015 12:44:04 -0700 Subject: aarch64: Add hardware breakpoint support Enable the use of hardware breakpoint on AARCH64. Change-Id: I59caaa6d92ac60278af8938625b1790a1787372f Signed-off-by: pierre Kuo Signed-off-by: David Ung Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 8ac64eb..d991a31 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1254,6 +1254,7 @@ static int aarch64_set_breakpoint(struct target *target, } if (breakpoint->type == BKPT_HARD) { + int64_t bpt_value; while (brp_list[brp_i].used && (brp_i < aarch64->brp_num)) brp_i++; if (brp_i >= aarch64->brp_num) { @@ -1264,38 +1265,46 @@ static int aarch64_set_breakpoint(struct target *target, if (breakpoint->length == 2) byte_addr_select = (3 << (breakpoint->address & 0x02)); control = ((matchmode & 0x7) << 20) + | (1 << 13) | (byte_addr_select << 5) | (3 << 1) | 1; brp_list[brp_i].used = 1; - brp_list[brp_i].value = (breakpoint->address & 0xFFFFFFFC); + brp_list[brp_i].value = breakpoint->address & 0xFFFFFFFFFFFFFFFC; brp_list[brp_i].control = control; + bpt_value = brp_list[brp_i].value; + + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUDBG_BVR_BASE + 16 * brp_list[brp_i].BRPn, + (uint32_t)(bpt_value & 0xFFFFFFFF)); + if (retval != ERROR_OK) + return retval; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn, - brp_list[brp_i].value); + + CPUDBG_BVR_BASE + 4 + 16 * brp_list[brp_i].BRPn, + (uint32_t)(bpt_value >> 32)); if (retval != ERROR_OK) return retval; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn, + + CPUDBG_BCR_BASE + 16 * brp_list[brp_i].BRPn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; LOG_DEBUG("brp %i control 0x%0" PRIx32 " value 0x%" TARGET_PRIxADDR, brp_i, brp_list[brp_i].control, brp_list[brp_i].value); + } else if (breakpoint->type == BKPT_SOFT) { uint8_t code[4]; - if (breakpoint->length == 2) - buf_set_u32(code, 0, 32, ARMV5_T_BKPT(0x11)); - else - buf_set_u32(code, 0, 32, ARMV5_BKPT(0x11)); + buf_set_u32(code, 0, 32, 0xD4400000); + retval = target_read_memory(target, - breakpoint->address & 0xFFFFFFFE, + breakpoint->address & 0xFFFFFFFFFFFFFFFE, breakpoint->length, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; retval = target_write_memory(target, - breakpoint->address & 0xFFFFFFFE, + breakpoint->address & 0xFFFFFFFFFFFFFFFE, breakpoint->length, 1, code); if (retval != ERROR_OK) return retval; @@ -1465,11 +1474,6 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br brp_list[brp_i].control); if (retval != ERROR_OK) return retval; - retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BVR_BASE + 16 * brp_list[brp_i].BRPn, - brp_list[brp_i].value); - if (retval != ERROR_OK) - return retval; if ((brp_j < 0) || (brp_j >= aarch64->brp_num)) { LOG_DEBUG("Invalid BRP number in breakpoint"); return ERROR_OK; @@ -1484,11 +1488,6 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br brp_list[brp_j].control); if (retval != ERROR_OK) return retval; - retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BVR_BASE + 16 * brp_list[brp_j].BRPn, - brp_list[brp_j].value); - if (retval != ERROR_OK) - return retval; breakpoint->linked_BRP = 0; breakpoint->set = 0; return ERROR_OK; -- cgit v1.1 From 5ee67ce024fcbdb0292dce1384b41ac0d6f30426 Mon Sep 17 00:00:00 2001 From: David Ung Date: Thu, 23 Apr 2015 13:22:13 -0700 Subject: aarch64: Enable halting debug mode on breakpoint set Ensure that we allow halting debug mode after setting breakpoint Change-Id: I6f0d7a4a4775a93c133fb1ec31dfe3324d9f7395 Signed-off-by: David Ung Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index d991a31..c6354c2 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1247,6 +1247,7 @@ static int aarch64_set_breakpoint(struct target *target, struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = &aarch64->armv8_common; struct aarch64_brp *brp_list = aarch64->brp_list; + uint32_t dscr; if (breakpoint->set) { LOG_WARNING("breakpoint already set"); @@ -1311,6 +1312,17 @@ static int aarch64_set_breakpoint(struct target *target, breakpoint->set = 0x11; /* Any nice value but 0 */ } + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + /* Ensure that halting debug mode is enable */ + dscr = dscr | DSCR_HALT_DBG_MODE; + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, dscr); + if (retval != ERROR_OK) { + LOG_DEBUG("Failed to set DSCR.HDE"); + return retval; + } + return ERROR_OK; } -- cgit v1.1 From 13d13b2e2a5ed12bcc8f2f0dc44bb2beface4946 Mon Sep 17 00:00:00 2001 From: pierre Kuo Date: Thu, 23 Apr 2015 14:44:27 -0700 Subject: aarch64: Add instruction stepping support using hardware step Use AARCH64's hardware step event to do stepping. Change-Id: I2d029ceeadd381913d0c3355c8787b11dacff7f7 Signed-off-by: pierre Kuo Signed-off-by: David Ung Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 49 +++++++++++++------------------------------------ src/target/armv8.h | 1 + 2 files changed, 14 insertions(+), 36 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index c6354c2..276f4a3 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1150,45 +1150,23 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres int handle_breakpoints) { struct armv8_common *armv8 = target_to_armv8(target); - struct arm *arm = &armv8->arm; - struct breakpoint *breakpoint = NULL; - struct breakpoint stepbreakpoint; - struct reg *r; int retval; + uint32_t tmp; if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; } - /* current = 1: continue on current pc, otherwise continue at
*/ - r = arm->pc; - if (!current) - buf_set_u64(r->value, 0, 64, address); - else - address = buf_get_u64(r->value, 0, 64); - - /* The front-end may request us not to handle breakpoints. - * But since Cortex-A8 uses breakpoint for single step, - * we MUST handle breakpoints. - */ - handle_breakpoints = 1; - if (handle_breakpoints) { - breakpoint = breakpoint_find(target, address); - if (breakpoint) - aarch64_unset_breakpoint(target, breakpoint); - } - - /* Setup single step breakpoint */ - stepbreakpoint.address = address; - stepbreakpoint.length = 4; - stepbreakpoint.type = BKPT_HARD; - stepbreakpoint.set = 0; - - /* Break on IVA mismatch */ - aarch64_set_breakpoint(target, &stepbreakpoint, 0x04); + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DECR, &tmp); + if (retval != ERROR_OK) + return retval; - target->debug_reason = DBG_REASON_SINGLESTEP; + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DECR, (tmp|0x4)); + if (retval != ERROR_OK) + return retval; retval = aarch64_resume(target, 1, address, 0, 0); if (retval != ERROR_OK) @@ -1205,12 +1183,11 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres } } - aarch64_unset_breakpoint(target, &stepbreakpoint); - target->debug_reason = DBG_REASON_BREAKPOINT; - - if (breakpoint) - aarch64_set_breakpoint(target, breakpoint, 0); + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DECR, (tmp&(~0x4))); + if (retval != ERROR_OK) + return retval; if (target->state != TARGET_HALTED) LOG_DEBUG("target stepped"); diff --git a/src/target/armv8.h b/src/target/armv8.h index 080237d..58e4228 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -161,6 +161,7 @@ target_to_armv8(struct target *target) /* register offsets from armv8.debug_base */ #define CPUDBG_WFAR 0x018 +#define CPUDBG_DECR 0x024 /* PCSR at 0x084 -or- 0x0a0 -or- both ... based on flags in DIDR */ #define CPUDBG_DSCR 0x088 #define CPUDBG_DRCR 0x090 -- cgit v1.1 From a12c15e21f663550de518595e606633bf82b5d04 Mon Sep 17 00:00:00 2001 From: David Ung Date: Thu, 23 Apr 2015 14:49:01 -0700 Subject: aarch64: Enable resuming with address Enable resuming to an address. Change-Id: I29c7d3b56f6cbf8b3cd02c93733fc96f45000af3 Signed-off-by: David Ung Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 276f4a3..a2b020b 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1023,12 +1023,7 @@ static int aarch64_resume(struct target *target, int current, target_addr_t address, int handle_breakpoints, int debug_execution) { int retval = 0; - uint64_t resume_addr; - - if (address) { - LOG_DEBUG("resuming with custom address not supported"); - return ERROR_FAIL; - } + uint64_t addr = address; /* dummy resume for smp toggle in order to reduce gdb impact */ if ((target->smp) && (target->gdb_service->core[1] != -1)) { @@ -1039,7 +1034,8 @@ static int aarch64_resume(struct target *target, int current, target_call_event_callbacks(target, TARGET_EVENT_RESUMED); return 0; } - aarch64_internal_restore(target, current, &resume_addr, handle_breakpoints, debug_execution); + aarch64_internal_restore(target, current, &addr, handle_breakpoints, + debug_execution); if (target->smp) { target->gdb_service->core[0] = -1; retval = aarch64_restore_smp(target, handle_breakpoints); @@ -1051,11 +1047,11 @@ static int aarch64_resume(struct target *target, int current, if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); - LOG_DEBUG("target resumed at 0x%" PRIx64, resume_addr); + LOG_DEBUG("target resumed at 0x%" PRIu64, addr); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); - LOG_DEBUG("target debug resumed at 0x%" PRIx64, resume_addr); + LOG_DEBUG("target debug resumed at 0x%" PRIu64, addr); } return ERROR_OK; -- cgit v1.1 From 6b554b3b0e34fe0a1d37a1584baf3c3e32a76b57 Mon Sep 17 00:00:00 2001 From: David Ung Date: Mon, 20 Apr 2015 13:14:43 -0700 Subject: aarch64: Correct target state for hardware step When using hardware step for doing stepping, the existing DSCR records the event as external debug request. This will generate a SIGINT event to GDB and causes it to stop the stepping process. For aarch64, read DESR to check if the event is a hardware step and set state to DBG_REASON_SINGLESTEP. With this patch, GDB can now do source level stepping. Change-Id: I1d06f819578c74b3ac17376c67f882adddea1f52 Signed-off-by: David Ung Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 13 +++++++++++-- src/target/armv8.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index a2b020b..78d1973 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1063,6 +1063,7 @@ static int aarch64_debug_entry(struct target *target) int retval = ERROR_OK; struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = target_to_armv8(target); + uint32_t tmp; LOG_DEBUG("dscr = 0x%08" PRIx32, aarch64->cpudbg_dscr); @@ -1086,6 +1087,10 @@ static int aarch64_debug_entry(struct target *target) /* Examine debug reason */ arm_dpm_report_dscr(&armv8->dpm, aarch64->cpudbg_dscr); + mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DESR, &tmp); + if ((tmp & 0x7) == 0x4) + target->debug_reason = DBG_REASON_SINGLESTEP; /* save address of instruction that triggered the watchpoint? */ if (target->debug_reason == DBG_REASON_WATCHPOINT) { @@ -1164,12 +1169,16 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres if (retval != ERROR_OK) return retval; + target->debug_reason = DBG_REASON_SINGLESTEP; retval = aarch64_resume(target, 1, address, 0, 0); if (retval != ERROR_OK) return retval; long long then = timeval_ms(); while (target->state != TARGET_HALTED) { + mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DESR, &tmp); + LOG_DEBUG("DESR = %#x", tmp); retval = aarch64_poll(target); if (retval != ERROR_OK) return retval; @@ -1179,13 +1188,13 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres } } - target->debug_reason = DBG_REASON_BREAKPOINT; retval = mem_ap_write_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUDBG_DECR, (tmp&(~0x4))); if (retval != ERROR_OK) return retval; - if (target->state != TARGET_HALTED) + target_call_event_callbacks(target, TARGET_EVENT_HALTED); + if (target->state == TARGET_HALTED) LOG_DEBUG("target stepped"); return ERROR_OK; diff --git a/src/target/armv8.h b/src/target/armv8.h index 58e4228..47e3668 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -161,6 +161,7 @@ target_to_armv8(struct target *target) /* register offsets from armv8.debug_base */ #define CPUDBG_WFAR 0x018 +#define CPUDBG_DESR 0x020 #define CPUDBG_DECR 0x024 /* PCSR at 0x084 -or- 0x0a0 -or- both ... based on flags in DIDR */ #define CPUDBG_DSCR 0x088 -- cgit v1.1 From ced4108d26de948b293cc2bbe51f64dca64795e2 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 2 Sep 2016 10:38:08 +0200 Subject: aarch64: add symbolic definitions for armv8 opcodes To replace hexadecimal constants with descriptive names and increase flexibility. Change-Id: I6f7b6f045866ed8b9360f54b640ecdb307eebc51 Signed-off-by: Matthias Welwarsky --- src/target/Makefile.am | 1 + src/target/armv8_opcodes.h | 126 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 127 insertions(+) create mode 100644 src/target/armv8_opcodes.h diff --git a/src/target/Makefile.am b/src/target/Makefile.am index a17496c..e235776 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -155,6 +155,7 @@ INTEL_IA32_SRC = \ %D%/armv7m.h \ %D%/armv7m_trace.h \ %D%/armv8.h \ + %D%/armv8_opcodes.h \ %D%/avrt.h \ %D%/dsp563xx.h \ %D%/dsp563xx_once.h \ diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h new file mode 100644 index 0000000..4f696db --- /dev/null +++ b/src/target/armv8_opcodes.h @@ -0,0 +1,126 @@ +/* + * Copyright (C) 2015 by pierrr kuo + * vichy.kuo@gmail.com + * 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. + * + */ +#ifndef OPENOCD_TARGET_ARMV8_OPCODES_H +#define OPENOCD_TARGET_ARMV8_OPCODES_H + +#include "arm_opcodes.h" + +/* ARM V8 Move from system register to general purpose register + * R = 1: SPSR R = 0: CPSR + * Rn: target register + */ +#define SYSTEM_CUREL 0b1100001000010010 +#define SYSTEM_CUREL_MASK 0xC0 +#define SYSTEM_CUREL_SHIFT 6 +#define SYSTEM_CUREL_EL0 0x0 +#define SYSTEM_CUREL_EL1 0x1 +#define SYSTEM_CUREL_EL2 0x2 +#define SYSTEM_CUREL_EL3 0x3 +#define SYSTEM_CUREL_NONCH 0xF +#define SYSTEM_AARCH64 0x1 + +#define SYSTEM_AAR64_MODE_EL0t 0x0 +#define SYSTEM_AAR64_MODE_EL1t 0x4 +#define SYSTEM_AAR64_MODE_EL1h 0x5 +#define SYSTEM_AAR64_MODE_EL2t 0x8 +#define SYSTEM_AAR64_MODE_EL2h 0x9 +#define SYSTEM_AAR64_MODE_EL3t 0xC +#define SYSTEM_AAR64_MODE_EL3h 0xd + +#define SYSTEM_DAIF 0b1101101000010001 +#define SYSTEM_DAIF_MASK 0x3C0 +#define SYSTEM_DAIF_SHIFT 6 + +#define SYSTEM_ELR_EL1 0b1100001000000001 +#define SYSTEM_ELR_EL2 0b1110001000000001 +#define SYSTEM_ELR_EL3 0b1111001000000001 + +#define SYSTEM_FPCR 0b1101101000100000 +#define SYSTEM_FPSR 0b1101101000100001 +#define SYSTEM_DAIF 0b1101101000010001 +#define SYSTEM_NZCV 0b1101101000010000 +#define SYSTEM_SP_EL0 0b1100001000001000 +#define SYSTEM_SP_EL1 0b1110001000001000 +#define SYSTEM_SP_EL2 0b1111001000001000 +#define SYSTEM_SP_SEL 0b1100001000010000 +#define SYSTEM_SPSR_ABT 0b1110001000011001 +#define SYSTEM_SPSR_FIQ 0b1110001000011011 +#define SYSTEM_SPSR_IRQ 0b1110001000011000 +#define SYSTEM_SPSR_UND 0b1110001000011010 + +#define SYSTEM_SPSR_EL1 0b1100001000000000 +#define SYSTEM_SPSR_EL2 0b1110001000000000 +#define SYSTEM_SPSR_EL3 0b1111001000000000 + +#define SYSTEM_ISR_EL1 0b1100011000001000 + + +#define SYSTEM_DBG_DSPSR_EL0 0b1101101000101000 +#define SYSTEM_DBG_DLR_EL0 0b1101101000101001 +#define SYSTEM_DBG_DTRRX_EL0 0b1001100000101000 +#define SYSTEM_DBG_DTRTX_EL0 0b1001100000101000 +#define SYSTEM_DBG_DBGDTR_EL0 0b1001100000100000 + +#define SYSTEM_CCSIDR 0b1100100000000000 +#define SYSTEM_CLIDR 0b1100100000000001 +#define SYSTEM_CSSELR 0b1101000000000000 +#define SYSTEM_CTYPE 0b1101100000000001 + +#define SYSTEM_DCCISW 0b0100001111110010 +#define SYSTEM_DCCSW 0b0100001111010010 +#define SYSTEM_ICIVAU 0b0101101110101001 +#define SYSTEM_DCCVAU 0b0101101111011001 + +#define SYSTEM_MPIDR 0b1100000000000101 + +#define SYSTEM_TCR_EL1 0b1100000100000010 +#define SYSTEM_TCR_EL2 0b1110000100000010 +#define SYSTEM_TCR_EL3 0b1111000100000010 + +#define SYSTEM_TTBR0_EL1 0b1100000100000000 +#define SYSTEM_TTBR0_EL2 0b1110000100000000 +#define SYSTEM_TTBR0_EL3 0b1111000100000000 +#define SYSTEM_TTBR1_EL1 0b1100000100000001 + + + +#define ARMV8_MRS_DSPSR(Rt) (0xd53b4500 | (Rt)) +#define ARMV8_MSR_DSPSR(Rt) (0xd51b4500 | (Rt)) +#define ARMV8_MRS_DLR(Rt) (0xd53b4520 | (Rt)) +#define ARMV8_MSR_DLR(Rt) (0xd51b4520 | (Rt)) + +/* T32 ITR format */ +#define T32_FMTITR(instr) (((instr & 0x0000FFFF) << 16) | ((instr & 0xFFFF0000) >> 16)) + +#define ARMV8_DCPS1(IM) (0xd4a00001 | (((IM) & 0xFFFF) << 5)) +#define ARMV8_DCPS2(IM) (0xd4a00002 | (((IM) & 0xFFFF) << 5)) +#define ARMV8_DCPS3(IM) (0xd4a00003 | (((IM) & 0xFFFF) << 5)) + +#define DSB_SY 0xd5033F9F +#define ARMV8_MRS(System, Rt) (0xd5300000 | ((System) << 5) | (Rt)) +/* ARM V8 Move to system register. */ +#define ARMV8_MSR_GP(System, Rt) \ + (0xd5100000 | ((System) << 5) | (Rt)) +/* ARM V8 Move immediate to process state field. */ +#define ARMV8_MSR_IM(Op1, CRm, Op2) \ + (0xd500401f | ((Op1) << 16) | ((CRm) << 8) | ((Op2) << 5)) +#define ARMV8_BKPT(Im) (0xD4200000 | ((Im & 0xffff) << 5)) +#define ARMV8_MOVFSP_64(Rt) ((1 << 31) | 0x11000000 | (0x1f << 5) | (Rt)) +#define ARMV8_MOVTSP_64(Rt) ((1 << 31) | 0x11000000 | (Rt << 5) | (0x1F)) +#define ARMV8_MOVFSP_32(Rt) (0x11000000 | (0x1f << 5) | (Rt)) +#define ARMV8_MOVTSP_32(Rt) (0x11000000 | (Rt << 5) | (0x1F)) + + +#endif /* __ARM_OPCODES_H */ -- cgit v1.1 From f2a271e2643e8a57881d5db7aceb21fc36140bc2 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Sat, 3 Sep 2016 16:35:59 +0200 Subject: aarch64: fix reading of MPIDR read MPIDR register through correct MSR instruction. Change-Id: I7e2d00c2871191c4168b177a7a809443b0db4c82 Signed-off-by: Matthias Welwarsky --- src/target/armv8.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 902d290..e516518 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -33,6 +33,7 @@ #include #include +#include "armv8_opcodes.h" #include "arm_opcodes.h" #include "target.h" #include "target_type.h" @@ -351,7 +352,7 @@ static int armv8_read_mpidr(struct target *target) /* MRC p15,0,,c0,c0,5; read Multiprocessor ID register*/ retval = dpm->instr_read_data_r0(dpm, - ARMV4_5_MRC(15, 0, 0, 0, 0, 5), + ARMV8_MRS(SYSTEM_MPIDR, 0), &mpidr); if (retval != ERROR_OK) goto done; -- cgit v1.1 From df32af234cae1f24b0a0f3abf4b50859f9d26740 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Sat, 3 Sep 2016 17:12:18 +0200 Subject: target: add -ctibase config option in addition to -dbgbase Some vendors don't fully populate the ROM table, e.g. BCM2357 (used in Raspberry Pi 3) doesn't list CTI, however it is mandatory for halting an ARMv8 core and therefore it's always present (and required), regardless of the ROM table listing it or not. Change-Id: Ia18a4f1b5b931ccd19805b188ebf737c837c6b54 Signed-off-by: Matthias Welwarsky --- src/target/target.c | 17 ++++++++++++++++- src/target/target.h | 5 +++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/target/target.c b/src/target/target.c index 5c2164f..ee302ee 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -4445,6 +4445,7 @@ enum target_cfg_param { TCFG_COREID, TCFG_CHAIN_POSITION, TCFG_DBGBASE, + TCFG_CTIBASE, TCFG_RTOS, TCFG_DEFER_EXAMINE, }; @@ -4460,6 +4461,7 @@ static Jim_Nvp nvp_config_opts[] = { { .name = "-coreid", .value = TCFG_COREID }, { .name = "-chain-position", .value = TCFG_CHAIN_POSITION }, { .name = "-dbgbase", .value = TCFG_DBGBASE }, + { .name = "-ctibase", .value = TCFG_CTIBASE }, { .name = "-rtos", .value = TCFG_RTOS }, { .name = "-defer-examine", .value = TCFG_DEFER_EXAMINE }, { .name = NULL, .value = -1 } @@ -4726,7 +4728,20 @@ no_params: Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->dbgbase)); /* loop for more */ break; - + case TCFG_CTIBASE: + if (goi->isconfigure) { + e = Jim_GetOpt_Wide(goi, &w); + if (e != JIM_OK) + return e; + target->ctibase = (uint32_t)w; + target->ctibase_set = true; + } else { + if (goi->argc != 0) + goto no_params; + } + Jim_SetResult(goi->interp, Jim_NewIntObj(goi->interp, target->ctibase)); + /* loop for more */ + break; case TCFG_RTOS: /* RTOS */ { diff --git a/src/target/target.h b/src/target/target.h index 41c9333..76630b9 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -185,6 +185,11 @@ struct target { uint32_t dbgbase; /* Really a Cortex-A specific option, but there is no * system in place to support target specific options * currently. */ + + bool ctibase_set; /* By default the debug base is not set */ + uint32_t ctibase; /* Really a Cortex-A specific option, but there is no + * system in place to support target specific options + * currently. */ struct rtos *rtos; /* Instance of Real Time Operating System support */ bool rtos_auto_detect; /* A flag that indicates that the RTOS has been specified as "auto" * and must be detected when symbols are offered */ -- cgit v1.1 From a3b9e12aecc3021bc3022eca93d07f7d11255b3b Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Sat, 3 Sep 2016 23:20:58 +0200 Subject: aarch64: introduce dpm extension for ARMv8 Add or move ARMv8 related dpm function to their own source module Change-Id: Id93d50be0b8635bd40ddb2a74fe8746ff840d736 Signed-off-by: Matthias Welwarsky --- src/target/Makefile.am | 2 + src/target/aarch64.c | 30 +- src/target/arm.h | 21 ++ src/target/arm_dpm.c | 324 ++++------------ src/target/arm_dpm.h | 5 +- src/target/armv8.c | 174 +++++++++ src/target/armv8.h | 4 +- src/target/armv8_dpm.c | 985 +++++++++++++++++++++++++++++++++++++++++++++++++ src/target/armv8_dpm.h | 115 ++++++ 9 files changed, 1400 insertions(+), 260 deletions(-) create mode 100644 src/target/armv8_dpm.c create mode 100644 src/target/armv8_dpm.h diff --git a/src/target/Makefile.am b/src/target/Makefile.am index e235776..c20ac0f 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -74,6 +74,7 @@ ARMV7_SRC = \ %D%/ls1_sap.c ARMV8_SRC = \ + %D%/armv8_dpm.c \ %D%/aarch64.c \ %D%/armv8.c @@ -155,6 +156,7 @@ INTEL_IA32_SRC = \ %D%/armv7m.h \ %D%/armv7m_trace.h \ %D%/armv8.h \ + %D%/armv8_dpm.h \ %D%/armv8_opcodes.h \ %D%/avrt.h \ %D%/dsp563xx.h \ diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 78d1973..be02eb8 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -376,6 +376,18 @@ static int aarch64_dpm_finish(struct arm_dpm *dpm) return ERROR_OK; } +static int aarch64_instr_execute(struct arm_dpm *dpm, + uint32_t opcode) +{ + struct aarch64_common *a8 = dpm_to_a8(dpm); + uint32_t dscr = DSCR_ITE; + + return aarch64_exec_opcode( + a8->armv8_common.arm.target, + opcode, + &dscr); +} + static int aarch64_instr_write_data_dcc(struct arm_dpm *dpm, uint32_t opcode, uint32_t data) { @@ -638,6 +650,7 @@ static int aarch64_dpm_setup(struct aarch64_common *a8, uint32_t debug) dpm->prepare = aarch64_dpm_prepare; dpm->finish = aarch64_dpm_finish; + dpm->instr_execute = aarch64_instr_execute; dpm->instr_write_data_dcc = aarch64_instr_write_data_dcc; dpm->instr_write_data_dcc_64 = aarch64_instr_write_data_dcc_64; dpm->instr_write_data_r0 = aarch64_instr_write_data_r0; @@ -654,9 +667,9 @@ static int aarch64_dpm_setup(struct aarch64_common *a8, uint32_t debug) dpm->bpwp_enable = aarch64_bpwp_enable; dpm->bpwp_disable = aarch64_bpwp_disable; - retval = arm_dpm_setup(dpm); + retval = armv8_dpm_setup(dpm); if (retval == ERROR_OK) - retval = arm_dpm_initialize(dpm); + retval = armv8_dpm_initialize(dpm); return retval; } @@ -879,6 +892,8 @@ static int aarch64_internal_restore(struct target *target, int current, */ switch (arm->core_state) { case ARM_STATE_ARM: + resume_pc &= 0xFFFFFFFC; + break; case ARM_STATE_AARCH64: resume_pc &= 0xFFFFFFFFFFFFFFFC; break; @@ -897,10 +912,8 @@ static int aarch64_internal_restore(struct target *target, int current, buf_set_u64(arm->pc->value, 0, 64, resume_pc); arm->pc->dirty = 1; arm->pc->valid = 1; -#if 0 - /* restore dpm_mode at system halt */ - dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY); -#endif + dpmv8_modeswitch(&armv8->dpm, ARM_MODE_ANY); + /* called it now before restoring context because it uses cpu * register r0 for restoring system control register */ retval = aarch64_restore_system_control_reg(target); @@ -1104,7 +1117,7 @@ static int aarch64_debug_entry(struct target *target) arm_dpm_report_wfar(&armv8->dpm, wfar); } - retval = arm_dpm_read_current_registers_64(&armv8->dpm); + retval = armv8_dpm_read_current_registers(&armv8->dpm); if (armv8->post_debug_entry) { retval = armv8->post_debug_entry(target); @@ -1209,9 +1222,8 @@ static int aarch64_restore_context(struct target *target, bool bpwp) if (armv8->pre_restore_context) armv8->pre_restore_context(target); - return arm_dpm_write_dirty_registers(&armv8->dpm, bpwp); + return armv8_dpm_write_dirty_registers(&armv8->dpm, bpwp); - return ERROR_OK; } /* diff --git a/src/target/arm.h b/src/target/arm.h index e4f2038..2548038 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -66,6 +66,15 @@ enum arm_mode { ARM_MODE_USER_THREAD = 1, ARM_MODE_HANDLER = 2, + /* shift left 4 bits for armv8 64 */ + ARMV8_64_EL0T = 0x0F, + ARMV8_64_EL1T = 0x4F, + ARMV8_64_EL1H = 0x5F, + ARMV8_64_EL2T = 0x8F, + ARMV8_64_EL2H = 0x9F, + ARMV8_64_EL3T = 0xCF, + ARMV8_64_EL3H = 0xDF, + ARM_MODE_ANY = -1 }; @@ -180,6 +189,18 @@ struct arm { uint32_t CRn, uint32_t CRm, uint32_t value); + /** Read coprocessor register. */ + int (*mrs)(struct target *target, uint32_t op0, + uint32_t op1, uint32_t op2, + uint32_t CRn, uint32_t CRm, + uint32_t *value); + + /** Write coprocessor register. */ + int (*msr)(struct target *target, uint32_t cpnum, + uint32_t op1, uint32_t op2, + uint32_t CRn, uint32_t CRm, + uint32_t value); + void *arch_info; /** For targets conforming to ARM Debug Interface v5, diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index 55f253e..00ebeba 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -21,6 +21,7 @@ #include "arm.h" #include "arm_dpm.h" +#include "armv8_dpm.h" #include #include "register.h" #include "breakpoints.h" @@ -130,11 +131,11 @@ int dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) return retval; } - -static int dpm_read_reg32(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +/* just read the register -- rely on the core mode being right */ +static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) { uint32_t value; - int retval = ERROR_FAIL; + int retval; switch (regnum) { case 0 ... 14: @@ -165,8 +166,8 @@ static int dpm_read_reg32(struct arm_dpm *dpm, struct reg *r, unsigned regnum) /* core-specific ... ? */ LOG_WARNING("Jazelle PC adjustment unknown"); break; - case ARM_STATE_AARCH64: - LOG_ERROR("AARCH64: 32bit read requested"); + default: + LOG_WARNING("unknow core state"); break; } break; @@ -190,57 +191,10 @@ static int dpm_read_reg32(struct arm_dpm *dpm, struct reg *r, unsigned regnum) return retval; } -static int dpm_read_reg64(struct arm_dpm *dpm, struct reg *r, unsigned regnum) -{ - uint64_t value; - uint32_t i; - int retval = ERROR_FAIL; - - switch (regnum) { - case 0 ... 30: - i = 0xd5130400 + regnum; /* msr dbgdtr_el0,reg */ - retval = dpm->instr_read_data_dcc_64(dpm, i, &value); - break; - case 31: /* SP */ - i = 0x910003e0; - retval = dpm->instr_read_data_r0_64(dpm, i, &value); - break; - case 32: /* PC */ - i = 0xd53b4520; - retval = dpm->instr_read_data_r0_64(dpm, i, &value); - break; - case 33: /* CPSR */ - i = 0xd53b4500; - retval = dpm->instr_read_data_r0_64(dpm, i, &value); - break; - - default: - break; - } - - if (retval == ERROR_OK) { - buf_set_u64(r->value, 0, 64, value); - r->valid = true; - r->dirty = false; - LOG_DEBUG("READ: %s, %16.16llx", r->name, (long long)value); - } - - return retval; -} - - -/* just read the register -- rely on the core mode being right */ -static int dpm_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) -{ - if (r->size == 64) - return dpm_read_reg64(dpm, r, regnum); - else - return dpm_read_reg32(dpm, r, regnum); -} - -static int dpm_write_reg32(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +/* just write the register -- rely on the core mode being right */ +static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) { - int retval = ERROR_FAIL; + int retval; uint32_t value = buf_get_u32(r->value, 0, 32); switch (regnum) { @@ -290,51 +244,19 @@ static int dpm_write_pc_core_state(struct arm_dpm *dpm, struct reg *r) return dpm->instr_write_data_r0(dpm, ARMV4_5_BX(0), value); } -static int dpm_write_reg64(struct arm_dpm *dpm, struct reg *r, unsigned regnum) -{ - int retval = ERROR_FAIL; - uint32_t i; - uint64_t value = buf_get_u64(r->value, 0, 64); - - switch (regnum) { - case 0 ... 30: - i = 0xd5330400 + regnum; - retval = dpm->instr_write_data_dcc_64(dpm, i, value); - break; - case 32: /* PC */ - i = 0xd51b4520; - retval = dpm->instr_write_data_r0_64(dpm, i, value); - break; - default: - LOG_DEBUG("register %s (%16.16llx) not defined", r->name, - (unsigned long long)value); - break; - } - - if (retval == ERROR_OK) { - r->dirty = false; - LOG_DEBUG("WRITE: %s, %16.16llx", r->name, (unsigned long long)value); - } - - return retval; -} - -/* just write the register -- rely on the core mode being right */ -static int dpm_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) -{ - if (r->size == 64) - return dpm_write_reg64(dpm, r, regnum); - else - return dpm_write_reg32(dpm, r, regnum); -} - -static int arm_dpm_read_current_registers_i(struct arm_dpm *dpm) +/** + * Read basic registers of the the current context: R0 to R15, and CPSR; + * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb). + * In normal operation this is called on entry to halting debug state, + * possibly after some other operations supporting restore of debug state + * or making sure the CPU is fully idle (drain write buffer, etc). + */ +int arm_dpm_read_current_registers(struct arm_dpm *dpm) { struct arm *arm = dpm->arm; - uint32_t cpsr, instr, core_regs; + uint32_t cpsr; int retval; struct reg *r; - enum arm_state core_state = arm->core_state; retval = dpm->prepare(dpm); if (retval != ERROR_OK) @@ -349,25 +271,16 @@ static int arm_dpm_read_current_registers_i(struct arm_dpm *dpm) } r->dirty = true; - if (core_state == ARM_STATE_AARCH64) - instr = 0xd53b4500; /* mrs x0, dspsr_el0 */ - else - instr = ARMV4_5_MRS(0, 0); - retval = dpm->instr_read_data_r0(dpm, instr, &cpsr); + retval = dpm->instr_read_data_r0(dpm, ARMV4_5_MRS(0, 0), &cpsr); if (retval != ERROR_OK) goto fail; /* update core mode and state, plus shadow mapping for R8..R14 */ arm_set_cpsr(arm, cpsr); - if (core_state == ARM_STATE_AARCH64) - /* arm_set_cpsr changes core_state, restore it for now */ - arm->core_state = ARM_STATE_AARCH64; - - core_regs = arm->core_cache->num_regs; /* REVISIT we can probably avoid reading R1..R14, saving time... */ - for (unsigned i = 1; i < core_regs; i++) { - r = dpm->arm_reg_current(arm, i); + for (unsigned i = 1; i < 16; i++) { + r = arm_reg_current(arm, i); if (r->valid) continue; @@ -388,23 +301,6 @@ fail: return retval; } -/** - * Read basic registers of the the current context: R0 to R15, and CPSR; - * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb). - * In normal operation this is called on entry to halting debug state, - * possibly after some other operations supporting restore of debug state - * or making sure the CPU is fully idle (drain write buffer, etc). - */ -int arm_dpm_read_current_registers(struct arm_dpm *dpm) -{ - return arm_dpm_read_current_registers_i(dpm); -} - -int arm_dpm_read_current_registers_64(struct arm_dpm *dpm) -{ - return arm_dpm_read_current_registers_i(dpm); -} - /* Avoid needless I/O ... leave breakpoints and watchpoints alone * unless they're removed, or need updating because of single-stepping * or running debugger code. @@ -453,14 +349,59 @@ done: static int dpm_add_breakpoint(struct target *target, struct breakpoint *bp); - -static int arm_dpm_write_dirty_registers_32(struct arm_dpm *dpm) +/** + * Writes all modified core registers for all processor modes. In normal + * operation this is called on exit from halting debug state. + * + * @param dpm: represents the processor + * @param bpwp: true ensures breakpoints and watchpoints are set, + * false ensures they are cleared + */ +int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) { struct arm *arm = dpm->arm; struct reg_cache *cache = arm->core_cache; int retval; bool did_write; + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + + /* If we're managing hardware breakpoints for this core, enable + * or disable them as requested. + * + * REVISIT We don't yet manage them for ANY cores. Eventually + * we should be able to assume we handle them; but until then, + * cope with the hand-crafted breakpoint code. + */ + if (arm->target->type->add_breakpoint == dpm_add_breakpoint) { + for (unsigned i = 0; i < dpm->nbp; i++) { + struct dpm_bp *dbp = dpm->dbp + i; + struct breakpoint *bp = dbp->bp; + + retval = dpm_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp, + bp ? &bp->set : NULL); + if (retval != ERROR_OK) + goto done; + } + } + + /* enable/disable watchpoints */ + for (unsigned i = 0; i < dpm->nwp; i++) { + struct dpm_wp *dwp = dpm->dwp + i; + struct watchpoint *wp = dwp->wp; + + retval = dpm_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp, + wp ? &wp->set : NULL); + if (retval != ERROR_OK) + goto done; + } + + /* NOTE: writes to breakpoint and watchpoint registers might + * be queued, and need (efficient/batched) flushing later. + */ + /* Scan the registers until we find one that's both dirty and * eligible for flushing. Flush that and everything else that * shares the same core mode setting. Typically this won't @@ -564,106 +505,6 @@ static int arm_dpm_write_dirty_registers_32(struct arm_dpm *dpm) goto done; cache->reg_list[0].dirty = false; -done: - return retval; -} - -static int arm_dpm_write_dirty_registers_64(struct arm_dpm *dpm) -{ - struct arm *arm = dpm->arm; - struct reg_cache *cache = arm->core_cache; - int retval; - - /* Scan the registers until we find one that's both dirty and - * eligible for flushing. Flush that and everything else that - * shares the same core mode setting. Typically this won't - * actually find anything to do... - */ - - /* check everything except our scratch register R0 */ - for (unsigned i = 1; i <= 32; i++) { - struct arm_reg *r; - unsigned regnum; - - if (!cache->reg_list[i].dirty) - continue; - - r = cache->reg_list[i].arch_info; - regnum = r->num; - retval = dpm_write_reg(dpm, - &cache->reg_list[i], - regnum); - if (retval != ERROR_OK) - goto done; - } - - /* flush R0 -- it's *very* dirty by now */ - retval = dpm_write_reg(dpm, &cache->reg_list[0], 0); - if (retval != ERROR_OK) - goto done; - cache->reg_list[0].dirty = false; - -done: - return retval; -} - -/** - * Writes all modified core registers for all processor modes. In normal - * operation this is called on exit from halting debug state. - * - * @param dpm: represents the processor - * @param bpwp: true ensures breakpoints and watchpoints are set, - * false ensures they are cleared - */ -int arm_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) -{ - struct arm *arm = dpm->arm; - struct reg_cache *cache = arm->core_cache; - int retval; - - retval = dpm->prepare(dpm); - if (retval != ERROR_OK) - goto done; - - /* If we're managing hardware breakpoints for this core, enable - * or disable them as requested. - * - * REVISIT We don't yet manage them for ANY cores. Eventually - * we should be able to assume we handle them; but until then, - * cope with the hand-crafted breakpoint code. - */ - if (arm->target->type->add_breakpoint == dpm_add_breakpoint) { - for (unsigned i = 0; i < dpm->nbp; i++) { - struct dpm_bp *dbp = dpm->dbp + i; - struct breakpoint *bp = dbp->bp; - - retval = dpm_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp, - bp ? &bp->set : NULL); - if (retval != ERROR_OK) - goto done; - } - } - - /* enable/disable watchpoints */ - for (unsigned i = 0; i < dpm->nwp; i++) { - struct dpm_wp *dwp = dpm->dwp + i; - struct watchpoint *wp = dwp->wp; - - retval = dpm_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp, - wp ? &wp->set : NULL); - if (retval != ERROR_OK) - goto done; - } - - /* NOTE: writes to breakpoint and watchpoint registers might - * be queued, and need (efficient/batched) flushing later. - */ - - if (cache->reg_list[0].size == 64) - retval = arm_dpm_write_dirty_registers_64(dpm); - else - retval = arm_dpm_write_dirty_registers_32(dpm); - /* (void) */ dpm->finish(dpm); done: return retval; @@ -1133,20 +974,15 @@ int arm_dpm_setup(struct arm_dpm *dpm) /* register access setup */ arm->full_context = arm_dpm_full_context; - arm->read_core_reg = arm->read_core_reg ? : arm_dpm_read_core_reg; - arm->write_core_reg = arm->write_core_reg ? : arm_dpm_write_core_reg; + arm->read_core_reg = arm_dpm_read_core_reg; + arm->write_core_reg = arm_dpm_write_core_reg; if (arm->core_cache != NULL) { - if (arm->core_state == ARM_STATE_AARCH64) { - cache = armv8_build_reg_cache(target); - target->reg_cache = cache; - } else { - cache = arm_build_reg_cache(target, arm); - *register_get_last_cache_p(&target->reg_cache) = cache; - } - + cache = arm_build_reg_cache(target, arm); if (!cache) return ERROR_FAIL; + + *register_get_last_cache_p(&target->reg_cache) = cache; } /* coprocessor access setup */ @@ -1163,20 +999,10 @@ int arm_dpm_setup(struct arm_dpm *dpm) target->type->add_watchpoint = dpm_add_watchpoint; target->type->remove_watchpoint = dpm_remove_watchpoint; - - if (dpm->arm_reg_current == 0) - dpm->arm_reg_current = arm_reg_current; - /* FIXME add vector catch support */ - if (arm->core_state == ARM_STATE_AARCH64) { - dpm->nbp = 1 + ((dpm->didr >> 24) & 0xf); - dpm->nwp = 1 + ((dpm->didr >> 28) & 0xf); - } else { - dpm->nbp = 1 + ((dpm->didr >> 12) & 0xf); - dpm->nwp = 1 + ((dpm->didr >> 20) & 0xf); - } - + dpm->nbp = 1 + ((dpm->didr >> 24) & 0xf); + dpm->nwp = 1 + ((dpm->didr >> 28) & 0xf); dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp); dpm->dwp = calloc(dpm->nwp, sizeof *dpm->dwp); diff --git a/src/target/arm_dpm.h b/src/target/arm_dpm.h index 5b16e64..ad49b8c 100644 --- a/src/target/arm_dpm.h +++ b/src/target/arm_dpm.h @@ -59,7 +59,7 @@ struct arm_dpm { struct arm *arm; /** Cache of DIDR */ - uint32_t didr; + uint64_t didr; /** Invoke before a series of instruction operations */ int (*prepare)(struct arm_dpm *); @@ -67,6 +67,9 @@ struct arm_dpm { /** Invoke after a series of instruction operations */ int (*finish)(struct arm_dpm *); + /** Runs one instruction. */ + int (*instr_execute)(struct arm_dpm *, uint32_t opcode); + /* WRITE TO CPU */ /** Runs one instruction, writing data to DCC before execution. */ diff --git a/src/target/armv8.c b/src/target/armv8.c index e516518..537dadb 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -38,6 +38,105 @@ #include "target.h" #include "target_type.h" +static const char * const armv8_state_strings[] = { + "ARM", "Thumb", "Jazelle", "ThumbEE", "ARM64", +}; + +static const struct { + const char *name; + unsigned psr; + /* For user and system modes, these list indices for all registers. + * otherwise they're just indices for the shadow registers and SPSR. + */ + unsigned short n_indices; + const uint8_t *indices; +} armv8_mode_data[] = { + /* These special modes are currently only supported + * by ARMv6M and ARMv7M profiles */ + { + .name = "EL0T", + .psr = ARMV8_64_EL0T, + }, + { + .name = "EL1T", + .psr = ARMV8_64_EL1T, + }, + { + .name = "EL1H", + .psr = ARMV8_64_EL1H, + }, + { + .name = "EL2T", + .psr = ARMV8_64_EL2T, + }, + { + .name = "EL2H", + .psr = ARMV8_64_EL2H, + }, + { + .name = "EL3T", + .psr = ARMV8_64_EL3T, + }, + { + .name = "EL3H", + .psr = ARMV8_64_EL3H, + }, +}; + +/** Map PSR mode bits to the name of an ARM processor operating mode. */ +const char *armv8_mode_name(unsigned psr_mode) +{ + for (unsigned i = 0; i < ARRAY_SIZE(armv8_mode_data); i++) { + if (armv8_mode_data[i].psr == psr_mode) + return armv8_mode_data[i].name; + } + LOG_ERROR("unrecognized psr mode: %#02x", psr_mode); + return "UNRECOGNIZED"; +} + +int armv8_mode_to_number(enum arm_mode mode) +{ + switch (mode) { + case ARM_MODE_ANY: + /* map MODE_ANY to user mode */ + case ARM_MODE_USR: + return 0; + case ARM_MODE_FIQ: + return 1; + case ARM_MODE_IRQ: + return 2; + case ARM_MODE_SVC: + return 3; + case ARM_MODE_ABT: + return 4; + case ARM_MODE_UND: + return 5; + case ARM_MODE_SYS: + return 6; + case ARM_MODE_MON: + return 7; + case ARMV8_64_EL0T: + return 8; + case ARMV8_64_EL1T: + return 9; + case ARMV8_64_EL1H: + return 10; + case ARMV8_64_EL2T: + return 11; + case ARMV8_64_EL2H: + return 12; + case ARMV8_64_EL3T: + return 13; + case ARMV8_64_EL3H: + return 14; + + default: + LOG_ERROR("invalid mode value encountered %d", mode); + return -1; + } +} + + static int armv8_read_core_reg(struct target *target, struct reg *r, int num, enum arm_mode mode) { @@ -86,6 +185,81 @@ static int armv8_write_core_reg(struct target *target, struct reg *r, return ERROR_OK; } #endif +/** + * Configures host-side ARM records to reflect the specified CPSR. + * Later, code can use arm_reg_current() to map register numbers + * according to how they are exposed by this mode. + */ +void armv8_set_cpsr(struct arm *arm, uint32_t cpsr) +{ + uint32_t mode = cpsr & 0x1F; + + /* NOTE: this may be called very early, before the register + * cache is set up. We can't defend against many errors, in + * particular against CPSRs that aren't valid *here* ... + */ + if (arm->cpsr) { + buf_set_u32(arm->cpsr->value, 0, 32, cpsr); + arm->cpsr->valid = 1; + arm->cpsr->dirty = 0; + } + + /* Older ARMs won't have the J bit */ + enum arm_state state = 0xFF; + + if (((cpsr & 0x10) >> 4) == 0) { + state = ARM_STATE_AARCH64; + } else { + if (cpsr & (1 << 5)) { /* T */ + if (cpsr & (1 << 24)) { /* J */ + LOG_WARNING("ThumbEE -- incomplete support"); + state = ARM_STATE_THUMB_EE; + } else + state = ARM_STATE_THUMB; + } else { + if (cpsr & (1 << 24)) { /* J */ + LOG_ERROR("Jazelle state handling is BROKEN!"); + state = ARM_STATE_JAZELLE; + } else + state = ARM_STATE_ARM; + } + } + arm->core_state = state; + if (arm->core_state == ARM_STATE_AARCH64) { + switch (mode) { + case SYSTEM_AAR64_MODE_EL0t: + arm->core_mode = ARMV8_64_EL0T; + break; + case SYSTEM_AAR64_MODE_EL1t: + arm->core_mode = ARMV8_64_EL0T; + break; + case SYSTEM_AAR64_MODE_EL1h: + arm->core_mode = ARMV8_64_EL1H; + break; + case SYSTEM_AAR64_MODE_EL2t: + arm->core_mode = ARMV8_64_EL2T; + break; + case SYSTEM_AAR64_MODE_EL2h: + arm->core_mode = ARMV8_64_EL2H; + break; + case SYSTEM_AAR64_MODE_EL3t: + arm->core_mode = ARMV8_64_EL3T; + break; + case SYSTEM_AAR64_MODE_EL3h: + arm->core_mode = ARMV8_64_EL3H; + break; + default: + LOG_DEBUG("unknow mode 0x%x", (unsigned) (mode)); + break; + } + } else { + arm->core_mode = mode; + } + + LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr, + armv8_mode_name(arm->core_mode), + armv8_state_strings[arm->core_state]); +} static void armv8_show_fault_registers(struct target *target) { diff --git a/src/target/armv8.h b/src/target/armv8.h index 47e3668..ccb205c 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -23,7 +23,7 @@ #include "arm.h" #include "armv4_5_mmu.h" #include "armv4_5_cache.h" -#include "arm_dpm.h" +#include "armv8_dpm.h" enum { ARMV8_R0, @@ -198,6 +198,8 @@ int armv8_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val); int armv8_handle_cache_info_command(struct command_context *cmd_ctx, struct armv8_cache_common *armv8_cache); +void armv8_set_cpsr(struct arm *arm, uint32_t cpsr); + extern const struct command_registration armv8_command_handlers[]; #endif diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c new file mode 100644 index 0000000..dc6682b --- /dev/null +++ b/src/target/armv8_dpm.c @@ -0,0 +1,985 @@ +/* + * Copyright (C) 2009 by David Brownell + * + * 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. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "arm.h" +#include "armv8.h" +#include "armv8_dpm.h" +#include +#include "register.h" +#include "breakpoints.h" +#include "target_type.h" +#include "armv8_opcodes.h" + + +/** + * @file + * Implements various ARM DPM operations using architectural debug registers. + * These routines layer over core-specific communication methods to cope with + * implementation differences between cores like ARM1136 and Cortex-A8. + * + * The "Debug Programmers' Model" (DPM) for ARMv6 and ARMv7 is defined by + * Part C (Debug Architecture) of the ARM Architecture Reference Manual, + * ARMv7-A and ARMv7-R edition (ARM DDI 0406B). In OpenOCD, DPM operations + * are abstracted through internal programming interfaces to share code and + * to minimize needless differences in debug behavior between cores. + */ + +/*----------------------------------------------------------------------*/ + +/* + * Coprocessor support + */ + +/* Read coprocessor */ +static int dpmv8_mrc(struct target *target, int cpnum, + uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, + uint32_t *value) +{ + struct arm *arm = target_to_arm(target); + struct arm_dpm *dpm = arm->dpm; + int retval; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + return retval; + + LOG_DEBUG("MRC p%d, %d, r0, c%d, c%d, %d", cpnum, + (int) op1, (int) CRn, + (int) CRm, (int) op2); + + /* read coprocessor register into R0; return via DCC */ + retval = dpm->instr_read_data_r0(dpm, + T32_FMTITR(ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2)), + value); + + /* (void) */ dpm->finish(dpm); + return retval; +} + +static int dpmv8_mcr(struct target *target, int cpnum, + uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, + uint32_t value) +{ + struct arm *arm = target_to_arm(target); + struct arm_dpm *dpm = arm->dpm; + int retval; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + return retval; + + LOG_DEBUG("MCR p%d, %d, r0, c%d, c%d, %d", cpnum, + (int) op1, (int) CRn, + (int) CRm, (int) op2); + + /* read DCC into r0; then write coprocessor register from R0 */ + retval = dpm->instr_write_data_r0(dpm, + T32_FMTITR(ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2)), + value); + + /* (void) */ dpm->finish(dpm); + return retval; +} + +static int dpmv8_mrs(struct target *target, uint32_t op0, + uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, + uint32_t *value) +{ + struct arm *arm = target_to_arm(target); + struct arm_dpm *dpm = arm->dpm; + int retval; + uint32_t op_code; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + return retval; + op_code = ((op0 & 0x3) << 19 | (op1 & 0x7) << 16 | (CRn & 0xF) << 12 |\ + (CRm & 0xF) << 8 | (op2 & 0x7) << 5); + op_code >>= 5; + LOG_DEBUG("MRS p%d, %d, r0, c%d, c%d, %d", (int)op0, + (int) op1, (int) CRn, + (int) CRm, (int) op2); + /* read coprocessor register into R0; return via DCC */ + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS(op_code, 0), + value); + + /* (void) */ dpm->finish(dpm); + return retval; +} + +static int dpmv8_msr(struct target *target, uint32_t op0, + uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, + uint32_t value) +{ + struct arm *arm = target_to_arm(target); + struct arm_dpm *dpm = arm->dpm; + int retval; + uint32_t op_code; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + return retval; + + op_code = ((op0 & 0x3) << 19 | (op1 & 0x7) << 16 | (CRn & 0xF) << 12 |\ + (CRm & 0xF) << 8 | (op2 & 0x7) << 5); + op_code >>= 5; + LOG_DEBUG("MSR p%d, %d, r0, c%d, c%d, %d", (int)op0, + (int) op1, (int) CRn, + (int) CRm, (int) op2); + + /* read DCC into r0; then write coprocessor register from R0 */ + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MSR_GP(op_code, 0), + value); + + /* (void) */ dpm->finish(dpm); + return retval; +} + +/*----------------------------------------------------------------------*/ + +/* + * Register access utilities + */ + +/* Toggles between recorded core mode (USR, SVC, etc) and a temporary one. + * Routines *must* restore the original mode before returning!! + */ +int dpmv8_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) +{ + int retval; + uint32_t cpsr; + + /* restore previous mode */ + if (mode == ARM_MODE_ANY) + cpsr = buf_get_u32(dpm->arm->cpsr->value, 0, 32); + + /* else force to the specified mode */ + else + cpsr = mode >> 4; + + switch ((cpsr & 0xC) >> 2) { + case SYSTEM_CUREL_EL1: + retval = dpm->instr_execute(dpm, ARMV8_DCPS1(11)); + if (retval != ERROR_OK) + return retval; + break; + case SYSTEM_CUREL_EL2: + retval = dpm->instr_execute(dpm, ARMV8_DCPS2(11)); + if (retval != ERROR_OK) + return retval; + break; + break; + case SYSTEM_CUREL_EL3: + retval = dpm->instr_execute(dpm, ARMV8_DCPS3(11)); + if (retval != ERROR_OK) + return retval; + break; + break; + default: + LOG_DEBUG("unknow mode 0x%x", (unsigned) ((cpsr & 0xC) >> 2)); + break; + } + + + retval = dpm->instr_write_data_r0(dpm, ARMV8_MSR_DSPSR(0), cpsr); + if (retval != ERROR_OK) + return retval; + + if (dpm->instr_cpsr_sync) + retval = dpm->instr_cpsr_sync(dpm); + + return retval; +} + +/* just read the register -- rely on the core mode being right */ +static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +{ + uint32_t value; + uint64_t value_64; + int retval = ERROR_FAIL; + + switch (regnum) { + case 0 ... 30: + retval = dpm->instr_read_data_dcc_64(dpm, + ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, regnum), + &value_64); + break; + case 31: + retval = dpm->instr_read_data_r0_64(dpm, + ARMV8_MOVFSP_64(0), + &value_64); + break; + case 32: + retval = dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS_DLR(0), + &value_64); + break; + case 33: + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS_DSPSR(0), + &value); + default: + LOG_DEBUG("READ: %s fail", r->name); + break; + } + + if (retval == ERROR_OK) { + r->valid = true; + r->dirty = false; + buf_set_u64(r->value, 0, 32, value_64); + if (r->size == 64) + LOG_DEBUG("READ: %s, %16.8llx", r->name, (unsigned long long) value_64); + else + LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value); + } + return retval; +} + +/* just write the register -- rely on the core mode being right */ +static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +{ + int retval = ERROR_FAIL; + uint32_t value = 0xFFFFFFFF; + uint64_t value_64 = 0xFFFFFFFFFFFFFFFF; + + switch (regnum) { + case 0 ... 30: + value_64 = buf_get_u64(r->value, 0, 64); + retval = dpm->instr_write_data_dcc_64(dpm, + ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, regnum), + value_64); + break; + case 31: + value_64 = buf_get_u64(r->value, 0, 64); + retval = dpm->instr_write_data_r0_64(dpm, + ARMV8_MOVTSP_64(0), + value_64); + break; + case 32: + value_64 = buf_get_u64(r->value, 0, 64); + retval = dpm->instr_write_data_r0_64(dpm, + ARMV8_MSR_DLR(0), + value_64); + break; + case 33: + value = buf_get_u32(r->value, 0, 32); + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MSR_DSPSR(0), + value); + default: + LOG_DEBUG("write: %s fail", r->name); + break; + } + + + if (retval == ERROR_OK) { + r->dirty = false; + if (r->size == 64) + LOG_DEBUG("WRITE: %s, %16.8llx", r->name, (unsigned long long) value_64); + else + LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned) value); + } + + return retval; +} + +/** + * Read basic registers of the the current context: R0 to R15, and CPSR; + * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb). + * In normal operation this is called on entry to halting debug state, + * possibly after some other operations supporting restore of debug state + * or making sure the CPU is fully idle (drain write buffer, etc). + */ +int armv8_dpm_read_current_registers(struct arm_dpm *dpm) +{ + struct arm *arm = dpm->arm; + uint32_t cpsr; + int retval; + struct reg *r; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + return retval; + + /* read R0 first (it's used for scratch), then CPSR */ + r = arm->core_cache->reg_list + 0; + if (!r->valid) { + retval = dpmv8_read_reg(dpm, r, 0); + if (retval != ERROR_OK) + goto fail; + } + r->dirty = true; + /* read cpsr to r0 and get it back */ + retval = dpm->instr_read_data_r0(dpm, ARMV8_MRS_DSPSR(0), &cpsr); + if (retval != ERROR_OK) + goto fail; + + /* update core mode and state, plus shadow mapping for R8..R14 */ + armv8_set_cpsr(arm, cpsr); + + /* REVISIT we can probably avoid reading R1..R14, saving time... */ + for (unsigned i = 1; i < arm->core_cache->num_regs ; i++) { + r = armv8_reg_current(arm, i); + if (r->valid) + continue; + + retval = dpmv8_read_reg(dpm, r, i); + if (retval != ERROR_OK) + goto fail; + } + + /* NOTE: SPSR ignored (if it's even relevant). */ + + /* REVISIT the debugger can trigger various exceptions. See the + * ARMv7A architecture spec, section C5.7, for more info about + * what defenses are needed; v6 debug has the most issues. + */ + +fail: + /* (void) */ dpm->finish(dpm); + return retval; +} + +/* Avoid needless I/O ... leave breakpoints and watchpoints alone + * unless they're removed, or need updating because of single-stepping + * or running debugger code. + */ +static int dpmv8_maybe_update_bpwp(struct arm_dpm *dpm, bool bpwp, + struct dpm_bpwp *xp, int *set_p) +{ + int retval = ERROR_OK; + bool disable; + + if (!set_p) { + if (!xp->dirty) + goto done; + xp->dirty = false; + /* removed or startup; we must disable it */ + disable = true; + } else if (bpwp) { + if (!xp->dirty) + goto done; + /* disabled, but we must set it */ + xp->dirty = disable = false; + *set_p = true; + } else { + if (!*set_p) + goto done; + /* set, but we must temporarily disable it */ + xp->dirty = disable = true; + *set_p = false; + } + + if (disable) + retval = dpm->bpwp_disable(dpm, xp->number); + else + retval = dpm->bpwp_enable(dpm, xp->number, + xp->address, xp->control); + + if (retval != ERROR_OK) + LOG_ERROR("%s: can't %s HW %spoint %d", + disable ? "disable" : "enable", + target_name(dpm->arm->target), + (xp->number < 16) ? "break" : "watch", + xp->number & 0xf); +done: + return retval; +} + +static int dpmv8_add_breakpoint(struct target *target, struct breakpoint *bp); + +/** + * Writes all modified core registers for all processor modes. In normal + * operation this is called on exit from halting debug state. + * + * @param dpm: represents the processor + * @param bpwp: true ensures breakpoints and watchpoints are set, + * false ensures they are cleared + */ +int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) +{ + struct arm *arm = dpm->arm; + struct reg_cache *cache = arm->core_cache; + int retval; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + + /* If we're managing hardware breakpoints for this core, enable + * or disable them as requested. + * + * REVISIT We don't yet manage them for ANY cores. Eventually + * we should be able to assume we handle them; but until then, + * cope with the hand-crafted breakpoint code. + */ + if (arm->target->type->add_breakpoint == dpmv8_add_breakpoint) { + for (unsigned i = 0; i < dpm->nbp; i++) { + struct dpm_bp *dbp = dpm->dbp + i; + struct breakpoint *bp = dbp->bp; + + retval = dpmv8_maybe_update_bpwp(dpm, bpwp, &dbp->bpwp, + bp ? &bp->set : NULL); + if (retval != ERROR_OK) + goto done; + } + } + + /* enable/disable watchpoints */ + for (unsigned i = 0; i < dpm->nwp; i++) { + struct dpm_wp *dwp = dpm->dwp + i; + struct watchpoint *wp = dwp->wp; + + retval = dpmv8_maybe_update_bpwp(dpm, bpwp, &dwp->bpwp, + wp ? &wp->set : NULL); + if (retval != ERROR_OK) + goto done; + } + + /* NOTE: writes to breakpoint and watchpoint registers might + * be queued, and need (efficient/batched) flushing later. + */ + + /* Scan the registers until we find one that's both dirty and + * eligible for flushing. Flush that and everything else that + * shares the same core mode setting. Typically this won't + * actually find anything to do... + */ + + /* check everything except our scratch register R0 */ + for (unsigned i = 1; i < cache->num_regs; i++) { + struct arm_reg *r; + unsigned regnum; + + /* also skip PC, CPSR, and non-dirty */ + if (i == (arm->core_cache->num_regs - 2)) + continue; + if (arm->cpsr == cache->reg_list + i) + continue; + if (!cache->reg_list[i].dirty) + continue; + + r = cache->reg_list[i].arch_info; + regnum = r->num; + + retval = dpmv8_write_reg(dpm, + &cache->reg_list[i], + regnum); + if (retval != ERROR_OK) + goto done; + } + + + /* Restore original CPSR ... assuming either that we changed it, + * or it's dirty. Must write PC to ensure the return address is + * defined, and must not write it before CPSR. + */ + retval = dpmv8_modeswitch(dpm, ARM_MODE_ANY); + if (retval != ERROR_OK) + goto done; + arm->cpsr->dirty = false; + + retval = dpmv8_write_reg(dpm, arm->pc, (arm->core_cache->num_regs - 2)); + if (retval != ERROR_OK) + goto done; + arm->pc->dirty = false; + + /* flush R0 -- it's *very* dirty by now */ + retval = dpmv8_write_reg(dpm, &cache->reg_list[0], 0); + if (retval != ERROR_OK) + goto done; + cache->reg_list[0].dirty = false; + + /* (void) */ dpm->finish(dpm); +done: + return retval; +} + +/* + * Standard ARM register accessors ... there are three methods + * in "struct arm", to support individual read/write and bulk read + * of registers. + */ + +static int armv8_dpm_read_core_reg(struct target *target, struct reg *r, + int regnum, enum arm_mode mode) +{ + struct arm *arm = target_to_arm(target); + struct arm_dpm *dpm = target_to_arm(target)->dpm; + int retval; + int max = arm->core_cache->num_regs; + + if (regnum < 0 || regnum > max) + return ERROR_COMMAND_SYNTAX_ERROR; + + /* REVISIT what happens if we try to read SPSR in a core mode + * which has no such register? + */ + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + return retval; + + retval = dpmv8_read_reg(dpm, r, regnum); + if (retval != ERROR_OK) + goto fail; + +fail: + /* (void) */ dpm->finish(dpm); + return retval; +} + +static int armv8_dpm_write_core_reg(struct target *target, struct reg *r, + int regnum, enum arm_mode mode, uint8_t *value) +{ + struct arm *arm = target_to_arm(target); + struct arm_dpm *dpm = target_to_arm(target)->dpm; + int retval; + int max = arm->core_cache->num_regs; + + if (regnum < 0 || regnum > max) + return ERROR_COMMAND_SYNTAX_ERROR; + + /* REVISIT what happens if we try to write SPSR in a core mode + * which has no such register? + */ + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + return retval; + + retval = dpmv8_write_reg(dpm, r, regnum); + /* always clean up, regardless of error */ + + /* (void) */ dpm->finish(dpm); + return retval; +} + +static int armv8_dpm_full_context(struct target *target) +{ + struct arm *arm = target_to_arm(target); + struct arm_dpm *dpm = arm->dpm; + struct reg_cache *cache = arm->core_cache; + int retval; + bool did_read; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + + do { + enum arm_mode mode = ARM_MODE_ANY; + + did_read = false; + + /* We "know" arm_dpm_read_current_registers() was called so + * the unmapped registers (R0..R7, PC, AND CPSR) and some + * view of R8..R14 are current. We also "know" oddities of + * register mapping: special cases for R8..R12 and SPSR. + * + * Pick some mode with unread registers and read them all. + * Repeat until done. + */ + for (unsigned i = 0; i < cache->num_regs; i++) { + struct arm_reg *r; + + if (cache->reg_list[i].valid) + continue; + r = cache->reg_list[i].arch_info; + + /* may need to pick a mode and set CPSR */ + if (!did_read) { + did_read = true; + mode = r->mode; + + /* For regular (ARM_MODE_ANY) R8..R12 + * in case we've entered debug state + * in FIQ mode we need to patch mode. + */ + if (mode != ARM_MODE_ANY) + retval = dpmv8_modeswitch(dpm, mode); + else + retval = dpmv8_modeswitch(dpm, ARM_MODE_USR); + + if (retval != ERROR_OK) + goto done; + } + if (r->mode != mode) + continue; + + /* CPSR was read, so "R16" must mean SPSR */ + retval = dpmv8_read_reg(dpm, + &cache->reg_list[i], + (r->num == 16) ? 17 : r->num); + if (retval != ERROR_OK) + goto done; + } + + } while (did_read); + + retval = dpmv8_modeswitch(dpm, ARM_MODE_ANY); + /* (void) */ dpm->finish(dpm); +done: + return retval; +} + + +/*----------------------------------------------------------------------*/ + +/* + * Breakpoint and Watchpoint support. + * + * Hardware {break,watch}points are usually left active, to minimize + * debug entry/exit costs. When they are set or cleared, it's done in + * batches. Also, DPM-conformant hardware can update debug registers + * regardless of whether the CPU is running or halted ... though that + * fact isn't currently leveraged. + */ + +static int dpmv8_bpwp_setup(struct arm_dpm *dpm, struct dpm_bpwp *xp, + uint32_t addr, uint32_t length) +{ + uint32_t control; + + control = (1 << 0) /* enable */ + | (3 << 1); /* both user and privileged access */ + + /* Match 1, 2, or all 4 byte addresses in this word. + * + * FIXME: v7 hardware allows lengths up to 2 GB for BP and WP. + * Support larger length, when addr is suitably aligned. In + * particular, allow watchpoints on 8 byte "double" values. + * + * REVISIT allow watchpoints on unaligned 2-bit values; and on + * v7 hardware, unaligned 4-byte ones too. + */ + switch (length) { + case 1: + control |= (1 << (addr & 3)) << 5; + break; + case 2: + /* require 2-byte alignment */ + if (!(addr & 1)) { + control |= (3 << (addr & 2)) << 5; + break; + } + /* FALL THROUGH */ + case 4: + /* require 4-byte alignment */ + if (!(addr & 3)) { + control |= 0xf << 5; + break; + } + /* FALL THROUGH */ + default: + LOG_ERROR("unsupported {break,watch}point length/alignment"); + return ERROR_COMMAND_SYNTAX_ERROR; + } + + /* other shared control bits: + * bits 15:14 == 0 ... both secure and nonsecure states (v6.1+ only) + * bit 20 == 0 ... not linked to a context ID + * bit 28:24 == 0 ... not ignoring N LSBs (v7 only) + */ + + xp->address = addr & ~3; + xp->control = control; + xp->dirty = true; + + LOG_DEBUG("BPWP: addr %8.8" PRIx32 ", control %" PRIx32 ", number %d", + xp->address, control, xp->number); + + /* hardware is updated in write_dirty_registers() */ + return ERROR_OK; +} + +static int dpmv8_add_breakpoint(struct target *target, struct breakpoint *bp) +{ + struct arm *arm = target_to_arm(target); + struct arm_dpm *dpm = arm->dpm; + int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + + if (bp->length < 2) + return ERROR_COMMAND_SYNTAX_ERROR; + if (!dpm->bpwp_enable) + return retval; + + /* FIXME we need a generic solution for software breakpoints. */ + if (bp->type == BKPT_SOFT) + LOG_DEBUG("using HW bkpt, not SW..."); + + for (unsigned i = 0; i < dpm->nbp; i++) { + if (!dpm->dbp[i].bp) { + retval = dpmv8_bpwp_setup(dpm, &dpm->dbp[i].bpwp, + bp->address, bp->length); + if (retval == ERROR_OK) + dpm->dbp[i].bp = bp; + break; + } + } + + return retval; +} + +static int dpmv8_remove_breakpoint(struct target *target, struct breakpoint *bp) +{ + struct arm *arm = target_to_arm(target); + struct arm_dpm *dpm = arm->dpm; + int retval = ERROR_COMMAND_SYNTAX_ERROR; + + for (unsigned i = 0; i < dpm->nbp; i++) { + if (dpm->dbp[i].bp == bp) { + dpm->dbp[i].bp = NULL; + dpm->dbp[i].bpwp.dirty = true; + + /* hardware is updated in write_dirty_registers() */ + retval = ERROR_OK; + break; + } + } + + return retval; +} + +static int dpmv8_watchpoint_setup(struct arm_dpm *dpm, unsigned index_t, + struct watchpoint *wp) +{ + int retval; + struct dpm_wp *dwp = dpm->dwp + index_t; + uint32_t control; + + /* this hardware doesn't support data value matching or masking */ + if (wp->value || wp->mask != ~(uint32_t)0) { + LOG_DEBUG("watchpoint values and masking not supported"); + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + } + + retval = dpmv8_bpwp_setup(dpm, &dwp->bpwp, wp->address, wp->length); + if (retval != ERROR_OK) + return retval; + + control = dwp->bpwp.control; + switch (wp->rw) { + case WPT_READ: + control |= 1 << 3; + break; + case WPT_WRITE: + control |= 2 << 3; + break; + case WPT_ACCESS: + control |= 3 << 3; + break; + } + dwp->bpwp.control = control; + + dpm->dwp[index_t].wp = wp; + + return retval; +} + +static int dpmv8_add_watchpoint(struct target *target, struct watchpoint *wp) +{ + struct arm *arm = target_to_arm(target); + struct arm_dpm *dpm = arm->dpm; + int retval = ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + + if (dpm->bpwp_enable) { + for (unsigned i = 0; i < dpm->nwp; i++) { + if (!dpm->dwp[i].wp) { + retval = dpmv8_watchpoint_setup(dpm, i, wp); + break; + } + } + } + + return retval; +} + +static int dpmv8_remove_watchpoint(struct target *target, struct watchpoint *wp) +{ + struct arm *arm = target_to_arm(target); + struct arm_dpm *dpm = arm->dpm; + int retval = ERROR_COMMAND_SYNTAX_ERROR; + + for (unsigned i = 0; i < dpm->nwp; i++) { + if (dpm->dwp[i].wp == wp) { + dpm->dwp[i].wp = NULL; + dpm->dwp[i].bpwp.dirty = true; + + /* hardware is updated in write_dirty_registers() */ + retval = ERROR_OK; + break; + } + } + + return retval; +} + +void armv8_dpm_report_wfar(struct arm_dpm *dpm, uint64_t addr) +{ + switch (dpm->arm->core_state) { + case ARM_STATE_ARM: + case ARM_STATE_AARCH64: + addr -= 8; + break; + case ARM_STATE_THUMB: + case ARM_STATE_THUMB_EE: + addr -= 4; + break; + case ARM_STATE_JAZELLE: + /* ?? */ + break; + default: + LOG_DEBUG("Unknow core_state"); + break; + } + dpm->wp_pc = addr; +} + +/*----------------------------------------------------------------------*/ + +/* + * Other debug and support utilities + */ + +void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr) +{ + struct target *target = dpm->arm->target; + + dpm->dscr = dscr; + + /* Examine debug reason */ + switch (DSCR_ENTRY(dscr)) { + /* FALL THROUGH -- assume a v6 core in abort mode */ + case DSCRV8_ENTRY_HLT: /* HALT request from debugger */ + case DSCRV8_ENTRY_EXT_DEBUG: /* EDBGRQ */ + target->debug_reason = DBG_REASON_DBGRQ; + break; + case DSCRV8_ENTRY_HALT_STEP_EXECLU: /* HALT step */ + case DSCRV8_ENTRY_BKPT: /* SW BKPT */ + case DSCRV8_ENTRY_RESET_CATCH: /* Reset catch */ + case DSCRV8_ENTRY_OS_UNLOCK: /*OS unlock catch*/ + case DSCRV8_ENTRY_EXCEPTION_CATCH: /*exception catch*/ + case DSCRV8_ENTRY_HALT_STEP_NORMAL: /* Halt step*/ + case DSCRV8_ENTRY_SW_ACCESS_DBG: /*SW access dbg register*/ + target->debug_reason = DBG_REASON_BREAKPOINT; + break; + case DSCRV8_ENTRY_WATCHPOINT: /* asynch watchpoint */ + target->debug_reason = DBG_REASON_WATCHPOINT; + break; + default: + target->debug_reason = DBG_REASON_UNDEFINED; + break; + } + +} + +/*----------------------------------------------------------------------*/ + +/* + * Setup and management support. + */ + +/** + * Hooks up this DPM to its associated target; call only once. + * Initially this only covers the register cache. + * + * Oh, and watchpoints. Yeah. + */ +int armv8_dpm_setup(struct arm_dpm *dpm) +{ + struct arm *arm = dpm->arm; + struct target *target = arm->target; + struct reg_cache *cache; + arm->dpm = dpm; + + /* register access setup */ + arm->full_context = armv8_dpm_full_context; + arm->read_core_reg = armv8_dpm_read_core_reg; + arm->write_core_reg = armv8_dpm_write_core_reg; + + cache = armv8_build_reg_cache(target); + if (!cache) + return ERROR_FAIL; + + /* coprocessor access setup */ + arm->mrc = dpmv8_mrc; + arm->mcr = dpmv8_mcr; + arm->mrs = dpmv8_mrs; + arm->msr = dpmv8_msr; + /* breakpoint setup -- optional until it works everywhere */ + if (!target->type->add_breakpoint) { + target->type->add_breakpoint = dpmv8_add_breakpoint; + target->type->remove_breakpoint = dpmv8_remove_breakpoint; + } + + /* watchpoint setup */ + target->type->add_watchpoint = dpmv8_add_watchpoint; + target->type->remove_watchpoint = dpmv8_remove_watchpoint; + + /* FIXME add vector catch support */ + + dpm->nbp = 1 + ((dpm->didr >> 12) & 0xf); + dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp); + + dpm->nwp = 1 + ((dpm->didr >> 20) & 0xf); + dpm->dwp = calloc(dpm->nwp, sizeof *dpm->dwp); + + if (!dpm->dbp || !dpm->dwp) { + free(dpm->dbp); + free(dpm->dwp); + return ERROR_FAIL; + } + + LOG_INFO("%s: hardware has %d breakpoints, %d watchpoints", + target_name(target), dpm->nbp, dpm->nwp); + + /* REVISIT ... and some of those breakpoints could match + * execution context IDs... + */ + + return ERROR_OK; +} + +/** + * Reinitializes DPM state at the beginning of a new debug session + * or after a reset which may have affected the debug module. + */ +int armv8_dpm_initialize(struct arm_dpm *dpm) +{ + /* Disable all breakpoints and watchpoints at startup. */ + if (dpm->bpwp_disable) { + unsigned i; + + for (i = 0; i < dpm->nbp; i++) { + dpm->dbp[i].bpwp.number = i; + (void) dpm->bpwp_disable(dpm, i); + } + for (i = 0; i < dpm->nwp; i++) { + dpm->dwp[i].bpwp.number = 16 + i; + (void) dpm->bpwp_disable(dpm, 16 + i); + } + } else + LOG_WARNING("%s: can't disable breakpoints and watchpoints", + target_name(dpm->arm->target)); + + return ERROR_OK; +} diff --git a/src/target/armv8_dpm.h b/src/target/armv8_dpm.h new file mode 100644 index 0000000..416f4df --- /dev/null +++ b/src/target/armv8_dpm.h @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2009 by David Brownell + * + * 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. + */ + +#ifndef OPENOCD_TARGET_ARMV8_DPM_H +#define OPENOCD_TARGET_ARMV8_DPM_H + +#include "arm_dpm.h" + +/* forward-declare struct armv8_common */ +struct armv8_common; + +/** + * This wraps an implementation of DPM primitives. Each interface + * provider supplies a structure like this, which is the glue between + * upper level code and the lower level hardware access. + * + * It is a PRELIMINARY AND INCOMPLETE set of primitives, starting with + * support for CPU register access. + */ +int armv8_dpm_setup(struct arm_dpm *dpm); +int armv8_dpm_initialize(struct arm_dpm *dpm); + +int armv8_dpm_read_current_registers(struct arm_dpm *); +int dpmv8_modeswitch(struct arm_dpm *dpm, enum arm_mode mode); + + +int armv8_dpm_write_dirty_registers(struct arm_dpm *, bool bpwp); + +void armv8_dpm_report_wfar(struct arm_dpm *, uint64_t wfar); + +/* DSCR bits; see ARMv7a arch spec section C10.3.1. + * Not all v7 bits are valid in v6. + */ +#define DSCR_DEBUG_STATUS_MASK (0x1F << 0) +#define DSCR_ERR (0x1 << 6) +#define DSCR_SYS_ERROR_PEND (0x1 << 7) +#define DSCR_CUR_EL (0x3 << 8) +#define DSCR_EL_STATUS_MASK (0xF << 10) +#define DSCR_HDE (0x1 << 14) +#define DSCR_SDD (0x1 << 16) +#define DSCR_NON_SECURE (0x1 << 18) +#define DSCR_MA (0x1 << 20) +#define DSCR_TDA (0x1 << 21) +#define DSCR_INTDIS_MASK (0x3 << 22) +#define DSCR_ITE (0x1 << 24) +#define DSCR_PIPE_ADVANCE (0x1 << 25) +#define DSCR_TXU (0x1 << 26) +#define DSCR_RTO (0x1 << 27) /* bit 28 is reserved */ +#define DSCR_ITO (0x1 << 28) +#define DSCR_DTR_TX_FULL (0x1 << 29) +#define DSCR_DTR_RX_FULL (0x1 << 30) /* bit 31 is reserved */ + + + +/* Methods of entry into debug mode */ +#define DSCRV8_ENTRY_NON_DEBUG (0x2) +#define DSCRV8_ENTRY_RESTARTING (0x1) +#define DSCRV8_ENTRY_BKPT (0x7) +#define DSCRV8_ENTRY_EXT_DEBUG (0x13) +#define DSCRV8_ENTRY_HALT_STEP_NORMAL (0x1B) +#define DSCRV8_ENTRY_HALT_STEP_EXECLU (0x1F) +#define DSCRV8_ENTRY_OS_UNLOCK (0x23) +#define DSCRV8_ENTRY_RESET_CATCH (0x27) +#define DSCRV8_ENTRY_WATCHPOINT (0x2B) +#define DSCRV8_ENTRY_HLT (0x2F) +#define DSCRV8_ENTRY_SW_ACCESS_DBG (0x33) +#define DSCRV8_ENTRY_EXCEPTION_CATCH (0x37) +#define DSCRV8_ENTRY_HALT_STEP (0x3B) +#define DSCRV8_HALT_MASK (0x3C) + +/*DRCR registers*/ +#define DRCR_CSE (1 << 2) +#define DRCR_CSPA (1 << 3) +#define DRCR_CBRRQ (1 << 4) + + +/* DTR modes */ +#define DSCR_EXT_DCC_NON_BLOCKING (0x0 << 20) +#define DSCR_EXT_DCC_STALL_MODE (0x1 << 20) +#define DSCR_EXT_DCC_FAST_MODE (0x2 << 20) /* bits 22, 23 are reserved */ + + +/* DRCR (debug run control register) bits */ +#define DRCR_HALT (1 << 0) +#define DRCR_RESTART (1 << 1) +#define DRCR_CLEAR_EXCEPTIONS (1 << 2) + +/* PRCR (processor debug status register) bits */ +#define PRSR_PU (1 << 0) +#define PRSR_SPD (1 << 1) +#define PRSR_RESET (1 << 2) +#define PRSR_SR (1 << 3) +#define PRSR_HALT (1 << 4) +#define PRSR_OSLK (1 << 5) +#define PRSR_DLK (1 << 6) +#define PRSR_EDAD (1 << 7) +#define PRSR_SDAD (1 << 8) +#define PRSR_EPMAD (1 << 9) +#define PRSR_SPMAD (1 << 10) +#define PRSR_SDR (1 << 11) + +void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dcsr); + +#endif /* OPENOCD_TARGET_ARM_DPM_H */ -- cgit v1.1 From db97bb4a9dbc210b599dc5acc58696ea22eee0da Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 1 Sep 2016 21:14:46 +0200 Subject: aarch64: make DCC read/write functions operate on struct armv8_common Change the signature of aarch64_(read|write)_dcc[_64] to take a "struct armv8_common *" as the context to operate on. No functional change. Change-Id: Ie501113f65ea22aff2eee173ec717f6908a63494 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 61 ++++++++++++++++++++++++++-------------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index be02eb8..93db496 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -234,26 +234,26 @@ static inline struct aarch64_common *dpm_to_a8(struct arm_dpm *dpm) return container_of(dpm, struct aarch64_common, armv8_common.dpm); } -static int aarch64_write_dcc(struct aarch64_common *a8, uint32_t data) +static int aarch64_write_dcc(struct armv8_common *armv8, uint32_t data) { LOG_DEBUG("write DCC 0x%08" PRIx32, data); - return mem_ap_write_u32(a8->armv8_common.debug_ap, - a8->armv8_common.debug_base + CPUDBG_DTRRX, data); + return mem_ap_write_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DTRRX, data); } -static int aarch64_write_dcc_64(struct aarch64_common *a8, uint64_t data) +static int aarch64_write_dcc_64(struct armv8_common *armv8, uint64_t data) { int ret; - LOG_DEBUG("write DCC 0x%08" PRIx32, (unsigned)data); - LOG_DEBUG("write DCC 0x%08" PRIx32, (unsigned)(data >> 32)); - ret = mem_ap_write_u32(a8->armv8_common.debug_ap, - a8->armv8_common.debug_base + CPUDBG_DTRRX, data); - ret += mem_ap_write_u32(a8->armv8_common.debug_ap, - a8->armv8_common.debug_base + CPUDBG_DTRTX, data >> 32); + LOG_DEBUG("write DCC Low word0x%08" PRIx32, (unsigned)data); + LOG_DEBUG("write DCC High word 0x%08" PRIx32, (unsigned)(data >> 32)); + ret = mem_ap_write_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DTRRX, data); + ret += mem_ap_write_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DTRTX, data >> 32); return ret; } -static int aarch64_read_dcc(struct aarch64_common *a8, uint32_t *data, +static int aarch64_read_dcc(struct armv8_common *armv8, uint32_t *data, uint32_t *dscr_p) { uint32_t dscr = DSCR_INSTR_COMP; @@ -265,8 +265,8 @@ static int aarch64_read_dcc(struct aarch64_common *a8, uint32_t *data, /* Wait for DTRRXfull */ long long then = timeval_ms(); while ((dscr & DSCR_DTR_TX_FULL) == 0) { - retval = mem_ap_read_atomic_u32(a8->armv8_common.debug_ap, - a8->armv8_common.debug_base + CPUDBG_DSCR, + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; @@ -276,8 +276,8 @@ static int aarch64_read_dcc(struct aarch64_common *a8, uint32_t *data, } } - retval = mem_ap_read_atomic_u32(a8->armv8_common.debug_ap, - a8->armv8_common.debug_base + CPUDBG_DTRTX, + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DTRTX, data); if (retval != ERROR_OK) return retval; @@ -288,7 +288,8 @@ static int aarch64_read_dcc(struct aarch64_common *a8, uint32_t *data, return retval; } -static int aarch64_read_dcc_64(struct aarch64_common *a8, uint64_t *data, + +static int aarch64_read_dcc_64(struct armv8_common *armv8, uint64_t *data, uint32_t *dscr_p) { uint32_t dscr = DSCR_INSTR_COMP; @@ -301,8 +302,8 @@ static int aarch64_read_dcc_64(struct aarch64_common *a8, uint64_t *data, /* Wait for DTRRXfull */ long long then = timeval_ms(); while ((dscr & DSCR_DTR_TX_FULL) == 0) { - retval = mem_ap_read_atomic_u32(a8->armv8_common.debug_ap, - a8->armv8_common.debug_base + CPUDBG_DSCR, + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; @@ -312,14 +313,14 @@ static int aarch64_read_dcc_64(struct aarch64_common *a8, uint64_t *data, } } - retval = mem_ap_read_atomic_u32(a8->armv8_common.debug_ap, - a8->armv8_common.debug_base + CPUDBG_DTRTX, + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DTRTX, (uint32_t *)data); if (retval != ERROR_OK) return retval; - retval = mem_ap_read_atomic_u32(a8->armv8_common.debug_ap, - a8->armv8_common.debug_base + CPUDBG_DTRRX, + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DTRRX, &higher); if (retval != ERROR_OK) return retval; @@ -395,7 +396,7 @@ static int aarch64_instr_write_data_dcc(struct arm_dpm *dpm, int retval; uint32_t dscr = DSCR_INSTR_COMP; - retval = aarch64_write_dcc(a8, data); + retval = aarch64_write_dcc(&a8->armv8_common, data); if (retval != ERROR_OK) return retval; @@ -412,7 +413,7 @@ static int aarch64_instr_write_data_dcc_64(struct arm_dpm *dpm, int retval; uint32_t dscr = DSCR_INSTR_COMP; - retval = aarch64_write_dcc_64(a8, data); + retval = aarch64_write_dcc_64(&a8->armv8_common, data); if (retval != ERROR_OK) return retval; @@ -429,7 +430,7 @@ static int aarch64_instr_write_data_r0(struct arm_dpm *dpm, uint32_t dscr = DSCR_INSTR_COMP; int retval; - retval = aarch64_write_dcc(a8, data); + retval = aarch64_write_dcc(&a8->armv8_common, data); if (retval != ERROR_OK) return retval; @@ -456,7 +457,7 @@ static int aarch64_instr_write_data_r0_64(struct arm_dpm *dpm, uint32_t dscr = DSCR_INSTR_COMP; int retval; - retval = aarch64_write_dcc_64(a8, data); + retval = aarch64_write_dcc_64(&a8->armv8_common, data); if (retval != ERROR_OK) return retval; @@ -502,7 +503,7 @@ static int aarch64_instr_read_data_dcc(struct arm_dpm *dpm, if (retval != ERROR_OK) return retval; - return aarch64_read_dcc(a8, data, &dscr); + return aarch64_read_dcc(&a8->armv8_common, data, &dscr); } static int aarch64_instr_read_data_dcc_64(struct arm_dpm *dpm, @@ -520,7 +521,7 @@ static int aarch64_instr_read_data_dcc_64(struct arm_dpm *dpm, if (retval != ERROR_OK) return retval; - return aarch64_read_dcc_64(a8, data, &dscr); + return aarch64_read_dcc_64(&a8->armv8_common, data, &dscr); } static int aarch64_instr_read_data_r0(struct arm_dpm *dpm, @@ -546,7 +547,7 @@ static int aarch64_instr_read_data_r0(struct arm_dpm *dpm, if (retval != ERROR_OK) return retval; - return aarch64_read_dcc(a8, data, &dscr); + return aarch64_read_dcc(&a8->armv8_common, data, &dscr); } static int aarch64_instr_read_data_r0_64(struct arm_dpm *dpm, @@ -572,7 +573,7 @@ static int aarch64_instr_read_data_r0_64(struct arm_dpm *dpm, if (retval != ERROR_OK) return retval; - return aarch64_read_dcc_64(a8, data, &dscr); + return aarch64_read_dcc_64(&a8->armv8_common, data, &dscr); } static int aarch64_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, -- cgit v1.1 From 53573f7860cf33d7ef01608f4894f68de7ab8c73 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 15 Sep 2016 12:12:25 +0200 Subject: aarch64: Implement MA mode for bulk memory reads and writes - 64bit addresses are supported - Aarch32 state is supported Change-Id: I8c37fa166954d09195d08c6963b8017194e350f5 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 249 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 165 insertions(+), 84 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 93db496..33c7daa 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -26,7 +26,7 @@ #include "register.h" #include "target_request.h" #include "target_type.h" -#include "arm_opcodes.h" +#include "armv8_opcodes.h" #include static int aarch64_poll(struct target *target); @@ -43,7 +43,7 @@ static int aarch64_unset_breakpoint(struct target *target, static int aarch64_mmu(struct target *target, int *enabled); static int aarch64_virt2phys(struct target *target, target_addr_t virt, target_addr_t *phys); -static int aarch64_read_apb_ab_memory(struct target *target, +static int aarch64_read_apb_ap_memory(struct target *target, uint64_t address, uint32_t size, uint32_t count, uint8_t *buffer); static int aarch64_instr_write_data_r0(struct arm_dpm *dpm, uint32_t opcode, uint32_t data); @@ -1673,7 +1673,7 @@ static int aarch64_deassert_reset(struct target *target) return ERROR_OK; } -static int aarch64_write_apb_ab_memory(struct target *target, +static int aarch64_write_apb_ap_memory(struct target *target, uint64_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { @@ -1688,7 +1688,6 @@ static int aarch64_write_apb_ab_memory(struct target *target, struct reg *reg; uint32_t dscr; uint8_t *tmp_buff = NULL; - uint32_t i = 0; LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx64 " size %" PRIu32 " count%" PRIu32, address, size, count); @@ -1711,15 +1710,13 @@ static int aarch64_write_apb_ab_memory(struct target *target, reg->dirty = true; /* clear any abort */ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUDBG_DRCR, 1<<2); + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DRCR, DRCR_CSE); if (retval != ERROR_OK) return retval; - /* This algorithm comes from either : - * Cortex-A8 TRM Example 12-25 - * Cortex-R4 TRM Example 11-26 - * (slight differences) - */ + + /* This algorithm comes from DDI0487A.g, chapter J9.1 */ /* The algorithm only copies 32 bit words, so the buffer * should be expanded to include the words at either end. @@ -1732,7 +1729,7 @@ static int aarch64_write_apb_ab_memory(struct target *target, /* First bytes not aligned - read the 32 bit word to avoid corrupting * the other bytes in the word. */ - retval = aarch64_read_apb_ab_memory(target, (address & ~0x3), 4, 1, tmp_buff); + retval = aarch64_read_apb_ap_memory(target, (address & ~0x3), 4, 1, tmp_buff); if (retval != ERROR_OK) goto error_free_buff_w; } @@ -1743,7 +1740,7 @@ static int aarch64_write_apb_ab_memory(struct target *target, /* Read the last word to avoid corruption during 32 bit write */ int mem_offset = (total_u32-1) * 4; - retval = aarch64_read_apb_ab_memory(target, (address & ~0x3) + mem_offset, 4, 1, &tmp_buff[mem_offset]); + retval = aarch64_read_apb_ap_memory(target, (address & ~0x3) + mem_offset, 4, 1, &tmp_buff[mem_offset]); if (retval != ERROR_OK) goto error_free_buff_w; } @@ -1759,48 +1756,54 @@ static int aarch64_write_apb_ab_memory(struct target *target, if (retval != ERROR_OK) goto error_free_buff_w; - /* Set DTR mode to Normal*/ - dscr = (dscr & ~DSCR_EXT_DCC_MASK) | DSCR_EXT_DCC_NON_BLOCKING; + /* Set Normal access mode */ + dscr = (dscr & ~DSCR_MA); retval = mem_ap_write_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUDBG_DSCR, dscr); - if (retval != ERROR_OK) - goto error_free_buff_w; - if (size > 4) { - LOG_WARNING("reading size >4 bytes not yet supported"); - goto error_unset_dtr_w; - } + if (arm->core_state == ARM_STATE_AARCH64) { + /* Write X0 with value 'address' using write procedure */ + /* Step 1.a+b - Write the address for read access into DBGDTR_EL0 */ + retval += aarch64_write_dcc_64(armv8, address & ~0x3ULL); + /* Step 1.c - Copy value from DTR to R0 using instruction mrs DBGDTR_EL0, x0 */ + retval += aarch64_exec_opcode(target, + ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), &dscr); + } else { + /* Write R0 with value 'address' using write procedure */ + /* Step 1.a+b - Write the address for read access into DBGDTRRX */ + retval += aarch64_write_dcc(armv8, address & ~0x3ULL); + /* Step 1.c - Copy value from DTR to R0 using instruction mrc DBGDTRTXint, r0 */ + retval += aarch64_exec_opcode(target, + T32_FMTITR(ARMV4_5_MRC(14, 0, 0, 0, 5, 0)), &dscr); - retval = aarch64_instr_write_data_dcc_64(arm->dpm, 0xd5330401, address+4); + } + /* Step 1.d - Change DCC to memory mode */ + dscr = dscr | DSCR_MA; + retval += mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, dscr); if (retval != ERROR_OK) goto error_unset_dtr_w; - dscr = DSCR_INSTR_COMP; - while (i < count * size) { - uint32_t val; - - memcpy(&val, &buffer[i], size); - retval = aarch64_instr_write_data_dcc(arm->dpm, 0xd5330500, val); - if (retval != ERROR_OK) - goto error_unset_dtr_w; - - retval = aarch64_exec_opcode(target, 0xb81fc020, &dscr); - if (retval != ERROR_OK) - goto error_unset_dtr_w; - retval = aarch64_exec_opcode(target, 0x91001021, &dscr); - if (retval != ERROR_OK) - goto error_unset_dtr_w; + /* Step 2.a - Do the write */ + retval = mem_ap_write_buf_noincr(armv8->debug_ap, + tmp_buff, 4, total_u32, armv8->debug_base + CPUDBG_DTRRX); + if (retval != ERROR_OK) + goto error_unset_dtr_w; - i += 4; - } + /* Step 3.a - Switch DTR mode back to Normal mode */ + dscr = (dscr & ~DSCR_MA); + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, dscr); + if (retval != ERROR_OK) + goto error_unset_dtr_w; /* Check for sticky abort flags in the DSCR */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUDBG_DSCR, &dscr); if (retval != ERROR_OK) goto error_free_buff_w; - if (dscr & (DSCR_STICKY_ABORT_PRECISE | DSCR_STICKY_ABORT_IMPRECISE)) { + if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) { /* Abort occurred - clear it and exit */ LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); mem_ap_write_atomic_u32(armv8->debug_ap, @@ -1816,7 +1819,7 @@ error_unset_dtr_w: /* Unset DTR mode */ mem_ap_read_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUDBG_DSCR, &dscr); - dscr = (dscr & ~DSCR_EXT_DCC_MASK) | DSCR_EXT_DCC_NON_BLOCKING; + dscr = (dscr & ~DSCR_MA); mem_ap_write_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUDBG_DSCR, dscr); error_free_buff_w: @@ -1825,19 +1828,23 @@ error_free_buff_w: return ERROR_FAIL; } -static int aarch64_read_apb_ab_memory(struct target *target, +static int aarch64_read_apb_ap_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { /* read memory through APB-AP */ - int retval = ERROR_COMMAND_SYNTAX_ERROR; struct armv8_common *armv8 = target_to_armv8(target); struct arm *arm = &armv8->arm; + int total_bytes = count * size; + int total_u32; + int start_byte = address & 0x3; + int end_byte = (address + total_bytes) & 0x3; struct reg *reg; - uint32_t dscr, val; + uint32_t dscr; uint8_t *tmp_buff = NULL; - uint32_t i = 0; + uint8_t *u8buf_ptr; + uint32_t value; LOG_DEBUG("Reading APB-AP memory address 0x%" TARGET_PRIxADDR " size %" PRIu32 " count%" PRIu32, address, size, count); @@ -1846,72 +1853,146 @@ static int aarch64_read_apb_ab_memory(struct target *target, return ERROR_TARGET_NOT_HALTED; } - /* Mark register R0 as dirty, as it will be used + total_u32 = DIV_ROUND_UP((address & 3) + total_bytes, 4); + /* Mark register X0, X1 as dirty, as it will be used * for transferring the data. * It will be restored automatically when exiting * debug mode */ + reg = armv8_reg_current(arm, 1); + reg->dirty = true; + reg = armv8_reg_current(arm, 0); reg->dirty = true; - /* clear any abort */ + /* clear any abort */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DRCR, 1<<2); + armv8->debug_base + CPUDBG_DRCR, DRCR_CSE); if (retval != ERROR_OK) goto error_free_buff_r; + /* Read DSCR */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUDBG_DSCR, &dscr); + + /* This algorithm comes from DDI0487A.g, chapter J9.1 */ + + /* Set Normal access mode */ + dscr = (dscr & ~DSCR_MA); + retval += mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, dscr); + + if (arm->core_state == ARM_STATE_AARCH64) { + /* Write X0 with value 'address' using write procedure */ + /* Step 1.a+b - Write the address for read access into DBGDTR_EL0 */ + retval += aarch64_write_dcc_64(armv8, address & ~0x3ULL); + /* Step 1.c - Copy value from DTR to R0 using instruction mrs DBGDTR_EL0, x0 */ + retval += aarch64_exec_opcode(target, ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), &dscr); + /* Step 1.d - Dummy operation to ensure EDSCR.Txfull == 1 */ + retval += aarch64_exec_opcode(target, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 0), &dscr); + /* Step 1.e - Change DCC to memory mode */ + dscr = dscr | DSCR_MA; + retval += mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, dscr); + /* Step 1.f - read DBGDTRTX and discard the value */ + retval += mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DTRTX, &value); + } else { + /* Write R0 with value 'address' using write procedure */ + /* Step 1.a+b - Write the address for read access into DBGDTRRXint */ + retval += aarch64_write_dcc(armv8, address & ~0x3ULL); + /* Step 1.c - Copy value from DTR to R0 using instruction mrc DBGDTRTXint, r0 */ + retval += aarch64_exec_opcode(target, + T32_FMTITR(ARMV4_5_MRC(14, 0, 0, 0, 5, 0)), &dscr); + /* Step 1.d - Dummy operation to ensure EDSCR.Txfull == 1 */ + retval += aarch64_exec_opcode(target, + T32_FMTITR(ARMV4_5_MCR(14, 0, 0, 0, 5, 0)), &dscr); + /* Step 1.e - Change DCC to memory mode */ + dscr = dscr | DSCR_MA; + retval += mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, dscr); + /* Step 1.f - read DBGDTRTX and discard the value */ + retval += mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DTRTX, &value); + + } if (retval != ERROR_OK) goto error_unset_dtr_r; - if (size > 4) { - LOG_WARNING("reading size >4 bytes not yet supported"); - goto error_unset_dtr_r; - } + /* Optimize the read as much as we can, either way we read in a single pass */ + if ((start_byte) || (end_byte)) { + /* The algorithm only copies 32 bit words, so the buffer + * should be expanded to include the words at either end. + * The first and last words will be read into a temp buffer + * to avoid corruption + */ + tmp_buff = malloc(total_u32 * 4); + if (!tmp_buff) + goto error_unset_dtr_r; - while (i < count * size) { + /* use the tmp buffer to read the entire data */ + u8buf_ptr = tmp_buff; + } else + /* address and read length are aligned so read directly into the passed buffer */ + u8buf_ptr = buffer; - retval = aarch64_instr_write_data_dcc_64(arm->dpm, 0xd5330400, address+4); - if (retval != ERROR_OK) - goto error_unset_dtr_r; - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + /* Read the data - Each read of the DTRTX register causes the instruction to be reissued + * Abort flags are sticky, so can be read at end of transactions + * + * This data is read in aligned to 32 bit boundary. + */ - dscr = DSCR_INSTR_COMP; - retval = aarch64_exec_opcode(target, 0xb85fc000, &dscr); - if (retval != ERROR_OK) + /* Step 2.a - Loop n-1 times, each read of DBGDTRTX reads the data from [X0] and + * increments X0 by 4. */ + retval = mem_ap_read_buf_noincr(armv8->debug_ap, u8buf_ptr, 4, total_u32-1, + armv8->debug_base + CPUDBG_DTRTX); + if (retval != ERROR_OK) goto error_unset_dtr_r; - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); - retval = aarch64_instr_read_data_dcc(arm->dpm, 0xd5130400, &val); - if (retval != ERROR_OK) - goto error_unset_dtr_r; - memcpy(&buffer[i], &val, size); - i += 4; - address += 4; + /* Step 3.a - set DTR access mode back to Normal mode */ + dscr = (dscr & ~DSCR_MA); + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, dscr); + if (retval != ERROR_OK) + goto error_free_buff_r; + + /* Step 3.b - read DBGDTRTX for the final value */ + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DTRTX, &value); + memcpy(u8buf_ptr + (total_u32-1) * 4, &value, 4); + + /* Check for sticky abort flags in the DSCR */ + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + if (retval != ERROR_OK) + goto error_free_buff_r; + if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) { + /* Abort occurred - clear it and exit */ + LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); + mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DRCR, DRCR_CSE); + goto error_free_buff_r; } - /* Clear any sticky error */ - mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DRCR, 1<<2); + /* check if we need to copy aligned data by applying any shift necessary */ + if (tmp_buff) { + memcpy(buffer, tmp_buff + start_byte, total_bytes); + free(tmp_buff); + } /* Done */ return ERROR_OK; error_unset_dtr_r: - LOG_WARNING("DSCR = 0x%" PRIx32, dscr); - /* Todo: Unset DTR mode */ - + /* Unset DTR mode */ + mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, &dscr); + dscr = (dscr & ~DSCR_MA); + mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUDBG_DSCR, dscr); error_free_buff_r: LOG_ERROR("error"); free(tmp_buff); - - /* Clear any sticky error */ - mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DRCR, 1<<2); - return ERROR_FAIL; } @@ -1937,7 +2018,7 @@ static int aarch64_read_phys_memory(struct target *target, retval = aarch64_mmu_modify(target, 0); if (retval != ERROR_OK) return retval; - retval = aarch64_read_apb_ab_memory(target, address, size, count, buffer); + retval = aarch64_read_apb_ap_memory(target, address, size, count, buffer); } } return retval; @@ -1988,7 +2069,7 @@ static int aarch64_read_memory(struct target *target, target_addr_t address, if (retval != ERROR_OK) return retval; } - retval = aarch64_read_apb_ab_memory(target, address, size, + retval = aarch64_read_apb_ap_memory(target, address, size, count, buffer); } return retval; @@ -2020,7 +2101,7 @@ static int aarch64_write_phys_memory(struct target *target, if (retval != ERROR_OK) return retval; } - return aarch64_write_apb_ab_memory(target, address, size, count, buffer); + return aarch64_write_apb_ap_memory(target, address, size, count, buffer); } } @@ -2128,7 +2209,7 @@ static int aarch64_write_memory(struct target *target, target_addr_t address, if (retval != ERROR_OK) return retval; } - retval = aarch64_write_apb_ab_memory(target, address, size, count, buffer); + retval = aarch64_write_apb_ap_memory(target, address, size, count, buffer); } return retval; } -- cgit v1.1 From b085570de9550bf50938d57f50465d07ba3ed87b Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Sat, 17 Sep 2016 21:11:38 +0200 Subject: aarch64: deconflict debug register names CPUDBG_ -> CPUV8_DBG_ for armv8 debug registers. Change-Id: I3d24cc209309fa9bbeb5c3e6c88a572383c9360e Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 200 +++++++++++++++++++++++++-------------------------- src/target/armv8.h | 58 ++++++++------- 2 files changed, 131 insertions(+), 127 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 33c7daa..84e6db3 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -125,11 +125,11 @@ static int aarch64_init_debug_access(struct target *target) /* Unlocking the debug registers for modification * The debugport might be uninitialised so try twice */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55); + armv8->debug_base + CPUV8_DBG_LOCKACCESS, 0xC5ACCE55); if (retval != ERROR_OK) { /* try again */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_LOCKACCESS, 0xC5ACCE55); + armv8->debug_base + CPUV8_DBG_LOCKACCESS, 0xC5ACCE55); if (retval == ERROR_OK) LOG_USER("Locking debug access failed on first, but succeeded on second try."); } @@ -138,7 +138,7 @@ static int aarch64_init_debug_access(struct target *target) /* Clear Sticky Power Down status Bit in PRSR to enable access to the registers in the Core Power Domain */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_PRSR, &dummy); + armv8->debug_base + CPUV8_DBG_PRSR, &dummy); if (retval != ERROR_OK) return retval; @@ -152,7 +152,7 @@ static int aarch64_init_debug_access(struct target *target) /* To reduce needless round-trips, pass in a pointer to the current * DSCR value. Initialize it to zero if you just need to know the - * value on return from this function; or DSCR_INSTR_COMP if you + * value on return from this function; or DSCR_ITE if you * happen to know that no instruction is pending. */ static int aarch64_exec_opcode(struct target *target, @@ -167,9 +167,9 @@ static int aarch64_exec_opcode(struct target *target, /* Wait for InstrCompl bit to be set */ long long then = timeval_ms(); - while ((dscr & DSCR_INSTR_COMP) == 0) { + while ((dscr & DSCR_ITE) == 0) { retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) { LOG_ERROR("Could not read DSCR register, opcode = 0x%08" PRIx32, opcode); return retval; @@ -181,14 +181,14 @@ static int aarch64_exec_opcode(struct target *target, } retval = mem_ap_write_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_ITR, opcode); + armv8->debug_base + CPUV8_DBG_ITR, opcode); if (retval != ERROR_OK) return retval; then = timeval_ms(); do { retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) { LOG_ERROR("Could not read DSCR register"); return retval; @@ -197,7 +197,7 @@ static int aarch64_exec_opcode(struct target *target, LOG_ERROR("Timeout waiting for aarch64_exec_opcode"); return ERROR_FAIL; } - } while ((dscr & DSCR_INSTR_COMP) == 0); /* Wait for InstrCompl bit to be set */ + } while ((dscr & DSCR_ITE) == 0); /* Wait for InstrCompl bit to be set */ if (dscr_p) *dscr_p = dscr; @@ -221,7 +221,7 @@ static int aarch64_dap_write_memap_register_u32(struct target *target, /* * AARCH64 implementation of Debug Programmer's Model * - * NOTE the invariant: these routines return with DSCR_INSTR_COMP set, + * NOTE the invariant: these routines return with DSCR_ITE set, * so there's no need to poll for it before executing an instruction. * * NOTE that in several of these cases the "stall" mode might be useful. @@ -238,7 +238,7 @@ static int aarch64_write_dcc(struct armv8_common *armv8, uint32_t data) { LOG_DEBUG("write DCC 0x%08" PRIx32, data); return mem_ap_write_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DTRRX, data); + armv8->debug_base + CPUV8_DBG_DTRRX, data); } static int aarch64_write_dcc_64(struct armv8_common *armv8, uint64_t data) @@ -247,16 +247,16 @@ static int aarch64_write_dcc_64(struct armv8_common *armv8, uint64_t data) LOG_DEBUG("write DCC Low word0x%08" PRIx32, (unsigned)data); LOG_DEBUG("write DCC High word 0x%08" PRIx32, (unsigned)(data >> 32)); ret = mem_ap_write_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DTRRX, data); + armv8->debug_base + CPUV8_DBG_DTRRX, data); ret += mem_ap_write_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DTRTX, data >> 32); + armv8->debug_base + CPUV8_DBG_DTRTX, data >> 32); return ret; } static int aarch64_read_dcc(struct armv8_common *armv8, uint32_t *data, uint32_t *dscr_p) { - uint32_t dscr = DSCR_INSTR_COMP; + uint32_t dscr = DSCR_ITE; int retval; if (dscr_p) @@ -266,7 +266,7 @@ static int aarch64_read_dcc(struct armv8_common *armv8, uint32_t *data, long long then = timeval_ms(); while ((dscr & DSCR_DTR_TX_FULL) == 0) { retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; @@ -277,7 +277,7 @@ static int aarch64_read_dcc(struct armv8_common *armv8, uint32_t *data, } retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DTRTX, + armv8->debug_base + CPUV8_DBG_DTRTX, data); if (retval != ERROR_OK) return retval; @@ -292,7 +292,7 @@ static int aarch64_read_dcc(struct armv8_common *armv8, uint32_t *data, static int aarch64_read_dcc_64(struct armv8_common *armv8, uint64_t *data, uint32_t *dscr_p) { - uint32_t dscr = DSCR_INSTR_COMP; + uint32_t dscr = DSCR_ITE; uint32_t higher; int retval; @@ -303,7 +303,7 @@ static int aarch64_read_dcc_64(struct armv8_common *armv8, uint64_t *data, long long then = timeval_ms(); while ((dscr & DSCR_DTR_TX_FULL) == 0) { retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; @@ -314,13 +314,13 @@ static int aarch64_read_dcc_64(struct armv8_common *armv8, uint64_t *data, } retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DTRTX, + armv8->debug_base + CPUV8_DBG_DTRTX, (uint32_t *)data); if (retval != ERROR_OK) return retval; retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DTRRX, + armv8->debug_base + CPUV8_DBG_DTRRX, &higher); if (retval != ERROR_OK) return retval; @@ -344,11 +344,11 @@ static int aarch64_dpm_prepare(struct arm_dpm *dpm) long long then = timeval_ms(); for (;; ) { retval = mem_ap_read_atomic_u32(a8->armv8_common.debug_ap, - a8->armv8_common.debug_base + CPUDBG_DSCR, + a8->armv8_common.debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; - if ((dscr & DSCR_INSTR_COMP) != 0) + if ((dscr & DSCR_ITE) != 0) break; if (timeval_ms() > then + 1000) { LOG_ERROR("Timeout waiting for dpm prepare"); @@ -394,7 +394,7 @@ static int aarch64_instr_write_data_dcc(struct arm_dpm *dpm, { struct aarch64_common *a8 = dpm_to_a8(dpm); int retval; - uint32_t dscr = DSCR_INSTR_COMP; + uint32_t dscr = DSCR_ITE; retval = aarch64_write_dcc(&a8->armv8_common, data); if (retval != ERROR_OK) @@ -411,7 +411,7 @@ static int aarch64_instr_write_data_dcc_64(struct arm_dpm *dpm, { struct aarch64_common *a8 = dpm_to_a8(dpm); int retval; - uint32_t dscr = DSCR_INSTR_COMP; + uint32_t dscr = DSCR_ITE; retval = aarch64_write_dcc_64(&a8->armv8_common, data); if (retval != ERROR_OK) @@ -427,7 +427,7 @@ static int aarch64_instr_write_data_r0(struct arm_dpm *dpm, uint32_t opcode, uint32_t data) { struct aarch64_common *a8 = dpm_to_a8(dpm); - uint32_t dscr = DSCR_INSTR_COMP; + uint32_t dscr = DSCR_ITE; int retval; retval = aarch64_write_dcc(&a8->armv8_common, data); @@ -454,7 +454,7 @@ static int aarch64_instr_write_data_r0_64(struct arm_dpm *dpm, uint32_t opcode, uint64_t data) { struct aarch64_common *a8 = dpm_to_a8(dpm); - uint32_t dscr = DSCR_INSTR_COMP; + uint32_t dscr = DSCR_ITE; int retval; retval = aarch64_write_dcc_64(&a8->armv8_common, data); @@ -480,7 +480,7 @@ static int aarch64_instr_write_data_r0_64(struct arm_dpm *dpm, static int aarch64_instr_cpsr_sync(struct arm_dpm *dpm) { struct target *target = dpm->arm->target; - uint32_t dscr = DSCR_INSTR_COMP; + uint32_t dscr = DSCR_ITE; /* "Prefetch flush" after modifying execution status in CPSR */ return aarch64_exec_opcode(target, @@ -493,7 +493,7 @@ static int aarch64_instr_read_data_dcc(struct arm_dpm *dpm, { struct aarch64_common *a8 = dpm_to_a8(dpm); int retval; - uint32_t dscr = DSCR_INSTR_COMP; + uint32_t dscr = DSCR_ITE; /* the opcode, writing data to DCC */ retval = aarch64_exec_opcode( @@ -511,7 +511,7 @@ static int aarch64_instr_read_data_dcc_64(struct arm_dpm *dpm, { struct aarch64_common *a8 = dpm_to_a8(dpm); int retval; - uint32_t dscr = DSCR_INSTR_COMP; + uint32_t dscr = DSCR_ITE; /* the opcode, writing data to DCC */ retval = aarch64_exec_opcode( @@ -528,7 +528,7 @@ static int aarch64_instr_read_data_r0(struct arm_dpm *dpm, uint32_t opcode, uint32_t *data) { struct aarch64_common *a8 = dpm_to_a8(dpm); - uint32_t dscr = DSCR_INSTR_COMP; + uint32_t dscr = DSCR_ITE; int retval; /* the opcode, writing data to R0 */ @@ -554,7 +554,7 @@ static int aarch64_instr_read_data_r0_64(struct arm_dpm *dpm, uint32_t opcode, uint64_t *data) { struct aarch64_common *a8 = dpm_to_a8(dpm); - uint32_t dscr = DSCR_INSTR_COMP; + uint32_t dscr = DSCR_ITE; int retval; /* the opcode, writing data to R0 */ @@ -586,12 +586,12 @@ static int aarch64_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, switch (index_t) { case 0 ... 15: /* breakpoints */ - vr += CPUDBG_BVR_BASE; - cr += CPUDBG_BCR_BASE; + vr += CPUV8_DBG_BVR_BASE; + cr += CPUV8_DBG_BCR_BASE; break; case 16 ... 31: /* watchpoints */ - vr += CPUDBG_WVR_BASE; - cr += CPUDBG_WCR_BASE; + vr += CPUV8_DBG_WVR_BASE; + cr += CPUV8_DBG_WCR_BASE; index_t -= 16; break; default: @@ -617,15 +617,15 @@ static int aarch64_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) return ERROR_OK; #if 0 - struct aarch64_common *a8 = dpm_to_a8(dpm); + struct aarch64_common *a = dpm_to_a8(dpm); uint32_t cr; switch (index_t) { case 0 ... 15: - cr = a8->armv8_common.debug_base + CPUDBG_BCR_BASE; + cr = a->armv8_common.debug_base + CPUV8_DBG_BCR_BASE; break; case 16 ... 31: - cr = a8->armv8_common.debug_base + CPUDBG_WCR_BASE; + cr = a->armv8_common.debug_base + CPUV8_DBG_WCR_BASE; index_t -= 16; break; default: @@ -633,7 +633,7 @@ static int aarch64_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) } cr += 4 * index_t; - LOG_DEBUG("A8: bpwp disable, cr %08x", (unsigned) cr); + LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr); /* clear control register */ return aarch64_dap_write_memap_register_u32(dpm->arm->target, cr, 0); @@ -740,7 +740,7 @@ static int aarch64_poll(struct target *target) return retval; } retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; aarch64->cpudbg_dscr = dscr; @@ -835,7 +835,7 @@ static int aarch64_halt(struct target *target) * enter halting debug mode */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; @@ -854,7 +854,7 @@ static int aarch64_halt(struct target *target) long long then = timeval_ms(); for (;; ) { retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; if ((dscr & DSCR_CORE_HALTED) != 0) @@ -961,20 +961,20 @@ static int aarch64_internal_restart(struct target *target) */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; - if ((dscr & DSCR_INSTR_COMP) == 0) + if ((dscr & DSCR_ITE) == 0) LOG_ERROR("DSCR InstrCompl must be set before leaving debug!"); retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, dscr & ~DSCR_ITR_EN); + armv8->debug_base + CPUV8_DBG_DSCR, dscr & ~DSCR_ITR_EN); if (retval != ERROR_OK) return retval; retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DRCR, DRCR_RESTART | + armv8->debug_base + CPUV8_DBG_DRCR, DRCR_RESTART | DRCR_CLEAR_EXCEPTIONS); if (retval != ERROR_OK) return retval; @@ -992,7 +992,7 @@ static int aarch64_internal_restart(struct target *target) long long then = timeval_ms(); for (;; ) { retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; if ((dscr & DSCR_CORE_RESTARTED) != 0) @@ -1083,7 +1083,7 @@ static int aarch64_debug_entry(struct target *target) /* REVISIT surely we should not re-read DSCR !! */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; @@ -1095,14 +1095,14 @@ static int aarch64_debug_entry(struct target *target) /* Enable the ITR execution once we are in debug mode */ dscr |= DSCR_ITR_EN; retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, dscr); + armv8->debug_base + CPUV8_DBG_DSCR, dscr); if (retval != ERROR_OK) return retval; /* Examine debug reason */ arm_dpm_report_dscr(&armv8->dpm, aarch64->cpudbg_dscr); mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DESR, &tmp); + armv8->debug_base + CPUV8_DBG_EDESR, &tmp); if ((tmp & 0x7) == 0x4) target->debug_reason = DBG_REASON_SINGLESTEP; @@ -1111,7 +1111,7 @@ static int aarch64_debug_entry(struct target *target) uint32_t wfar; retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_WFAR, + armv8->debug_base + CPUV8_DBG_WFAR0, &wfar); if (retval != ERROR_OK) return retval; @@ -1138,7 +1138,7 @@ static int aarch64_post_debug_entry(struct target *target) int retval; mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DRCR, 1<<2); + armv8->debug_base + CPUV8_DBG_DRCR, 1<<2); retval = aarch64_instr_read_data_r0(armv8->arm.dpm, 0xd5381000, &sctlr_el1); if (retval != ERROR_OK) @@ -1174,12 +1174,12 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres } retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DECR, &tmp); + armv8->debug_base + CPUV8_DBG_EDECR, &tmp); if (retval != ERROR_OK) return retval; retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DECR, (tmp|0x4)); + armv8->debug_base + CPUV8_DBG_EDECR, (tmp|0x4)); if (retval != ERROR_OK) return retval; @@ -1191,7 +1191,7 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres long long then = timeval_ms(); while (target->state != TARGET_HALTED) { mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DESR, &tmp); + armv8->debug_base + CPUV8_DBG_EDESR, &tmp); LOG_DEBUG("DESR = %#x", tmp); retval = aarch64_poll(target); if (retval != ERROR_OK) @@ -1203,7 +1203,7 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres } retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DECR, (tmp&(~0x4))); + armv8->debug_base + CPUV8_DBG_EDECR, (tmp&(~0x4))); if (retval != ERROR_OK) return retval; @@ -1270,18 +1270,18 @@ static int aarch64_set_breakpoint(struct target *target, bpt_value = brp_list[brp_i].value; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BVR_BASE + 16 * brp_list[brp_i].BRPn, + + CPUV8_DBG_BVR_BASE + 16 * brp_list[brp_i].BRPn, (uint32_t)(bpt_value & 0xFFFFFFFF)); if (retval != ERROR_OK) return retval; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BVR_BASE + 4 + 16 * brp_list[brp_i].BRPn, + + CPUV8_DBG_BVR_BASE + 4 + 16 * brp_list[brp_i].BRPn, (uint32_t)(bpt_value >> 32)); if (retval != ERROR_OK) return retval; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BCR_BASE + 16 * brp_list[brp_i].BRPn, + + CPUV8_DBG_BCR_BASE + 16 * brp_list[brp_i].BRPn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; @@ -1308,11 +1308,11 @@ static int aarch64_set_breakpoint(struct target *target, } retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); /* Ensure that halting debug mode is enable */ - dscr = dscr | DSCR_HALT_DBG_MODE; + dscr = dscr | DSCR_HDE; retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, dscr); + armv8->debug_base + CPUV8_DBG_DSCR, dscr); if (retval != ERROR_OK) { LOG_DEBUG("Failed to set DSCR.HDE"); return retval; @@ -1354,12 +1354,12 @@ static int aarch64_set_context_breakpoint(struct target *target, brp_list[brp_i].value = (breakpoint->asid); brp_list[brp_i].control = control; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn, + + CPUV8_DBG_BVR_BASE + 4 * brp_list[brp_i].BRPn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn, + + CPUV8_DBG_BCR_BASE + 4 * brp_list[brp_i].BRPn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; @@ -1420,12 +1420,12 @@ static int aarch64_set_hybrid_breakpoint(struct target *target, struct breakpoin brp_list[brp_1].value = (breakpoint->asid); brp_list[brp_1].control = control_CTX; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_1].BRPn, + + CPUV8_DBG_BVR_BASE + 4 * brp_list[brp_1].BRPn, brp_list[brp_1].value); if (retval != ERROR_OK) return retval; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_1].BRPn, + + CPUV8_DBG_BCR_BASE + 4 * brp_list[brp_1].BRPn, brp_list[brp_1].control); if (retval != ERROR_OK) return retval; @@ -1438,12 +1438,12 @@ static int aarch64_set_hybrid_breakpoint(struct target *target, struct breakpoin brp_list[brp_2].value = (breakpoint->address & 0xFFFFFFFC); brp_list[brp_2].control = control_IVA; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_2].BRPn, + + CPUV8_DBG_BVR_BASE + 4 * brp_list[brp_2].BRPn, brp_list[brp_2].value); if (retval != ERROR_OK) return retval; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_2].BRPn, + + CPUV8_DBG_BCR_BASE + 4 * brp_list[brp_2].BRPn, brp_list[brp_2].control); if (retval != ERROR_OK) return retval; @@ -1477,7 +1477,7 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br brp_list[brp_i].value = 0; brp_list[brp_i].control = 0; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BCR_BASE + 16 * brp_list[brp_i].BRPn, + + CPUV8_DBG_BCR_BASE + 16 * brp_list[brp_i].BRPn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; @@ -1491,7 +1491,7 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br brp_list[brp_j].value = 0; brp_list[brp_j].control = 0; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BCR_BASE + 16 * brp_list[brp_j].BRPn, + + CPUV8_DBG_BCR_BASE + 16 * brp_list[brp_j].BRPn, brp_list[brp_j].control); if (retval != ERROR_OK) return retval; @@ -1511,12 +1511,12 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br brp_list[brp_i].value = 0; brp_list[brp_i].control = 0; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BCR_BASE + 4 * brp_list[brp_i].BRPn, + + CPUV8_DBG_BCR_BASE + 4 * brp_list[brp_i].BRPn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUDBG_BVR_BASE + 4 * brp_list[brp_i].BRPn, + + CPUV8_DBG_BVR_BASE + 4 * brp_list[brp_i].BRPn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; @@ -1711,7 +1711,7 @@ static int aarch64_write_apb_ap_memory(struct target *target, /* clear any abort */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DRCR, DRCR_CSE); + armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); if (retval != ERROR_OK) return retval; @@ -1752,14 +1752,14 @@ static int aarch64_write_apb_ap_memory(struct target *target, /* Read DSCR */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) goto error_free_buff_w; /* Set Normal access mode */ dscr = (dscr & ~DSCR_MA); retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, dscr); + armv8->debug_base + CPUV8_DBG_DSCR, dscr); if (arm->core_state == ARM_STATE_AARCH64) { /* Write X0 with value 'address' using write procedure */ @@ -1780,34 +1780,34 @@ static int aarch64_write_apb_ap_memory(struct target *target, /* Step 1.d - Change DCC to memory mode */ dscr = dscr | DSCR_MA; retval += mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, dscr); + armv8->debug_base + CPUV8_DBG_DSCR, dscr); if (retval != ERROR_OK) goto error_unset_dtr_w; /* Step 2.a - Do the write */ retval = mem_ap_write_buf_noincr(armv8->debug_ap, - tmp_buff, 4, total_u32, armv8->debug_base + CPUDBG_DTRRX); + tmp_buff, 4, total_u32, armv8->debug_base + CPUV8_DBG_DTRRX); if (retval != ERROR_OK) goto error_unset_dtr_w; /* Step 3.a - Switch DTR mode back to Normal mode */ dscr = (dscr & ~DSCR_MA); retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, dscr); + armv8->debug_base + CPUV8_DBG_DSCR, dscr); if (retval != ERROR_OK) goto error_unset_dtr_w; /* Check for sticky abort flags in the DSCR */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) goto error_free_buff_w; if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) { /* Abort occurred - clear it and exit */ LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DRCR, 1<<2); + armv8->debug_base + CPUV8_DBG_DRCR, 1<<2); goto error_free_buff_w; } @@ -1818,10 +1818,10 @@ static int aarch64_write_apb_ap_memory(struct target *target, error_unset_dtr_w: /* Unset DTR mode */ mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); dscr = (dscr & ~DSCR_MA); mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, dscr); + armv8->debug_base + CPUV8_DBG_DSCR, dscr); error_free_buff_w: LOG_ERROR("error"); free(tmp_buff); @@ -1867,20 +1867,20 @@ static int aarch64_read_apb_ap_memory(struct target *target, /* clear any abort */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DRCR, DRCR_CSE); + armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); if (retval != ERROR_OK) goto error_free_buff_r; /* Read DSCR */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); /* This algorithm comes from DDI0487A.g, chapter J9.1 */ /* Set Normal access mode */ dscr = (dscr & ~DSCR_MA); retval += mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, dscr); + armv8->debug_base + CPUV8_DBG_DSCR, dscr); if (arm->core_state == ARM_STATE_AARCH64) { /* Write X0 with value 'address' using write procedure */ @@ -1893,10 +1893,10 @@ static int aarch64_read_apb_ap_memory(struct target *target, /* Step 1.e - Change DCC to memory mode */ dscr = dscr | DSCR_MA; retval += mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, dscr); + armv8->debug_base + CPUV8_DBG_DSCR, dscr); /* Step 1.f - read DBGDTRTX and discard the value */ retval += mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DTRTX, &value); + armv8->debug_base + CPUV8_DBG_DTRTX, &value); } else { /* Write R0 with value 'address' using write procedure */ /* Step 1.a+b - Write the address for read access into DBGDTRRXint */ @@ -1910,10 +1910,10 @@ static int aarch64_read_apb_ap_memory(struct target *target, /* Step 1.e - Change DCC to memory mode */ dscr = dscr | DSCR_MA; retval += mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, dscr); + armv8->debug_base + CPUV8_DBG_DSCR, dscr); /* Step 1.f - read DBGDTRTX and discard the value */ retval += mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DTRTX, &value); + armv8->debug_base + CPUV8_DBG_DTRTX, &value); } if (retval != ERROR_OK) @@ -1945,32 +1945,32 @@ static int aarch64_read_apb_ap_memory(struct target *target, /* Step 2.a - Loop n-1 times, each read of DBGDTRTX reads the data from [X0] and * increments X0 by 4. */ retval = mem_ap_read_buf_noincr(armv8->debug_ap, u8buf_ptr, 4, total_u32-1, - armv8->debug_base + CPUDBG_DTRTX); + armv8->debug_base + CPUV8_DBG_DTRTX); if (retval != ERROR_OK) goto error_unset_dtr_r; /* Step 3.a - set DTR access mode back to Normal mode */ dscr = (dscr & ~DSCR_MA); retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, dscr); + armv8->debug_base + CPUV8_DBG_DSCR, dscr); if (retval != ERROR_OK) goto error_free_buff_r; /* Step 3.b - read DBGDTRTX for the final value */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DTRTX, &value); + armv8->debug_base + CPUV8_DBG_DTRTX, &value); memcpy(u8buf_ptr + (total_u32-1) * 4, &value, 4); /* Check for sticky abort flags in the DSCR */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) goto error_free_buff_r; if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) { /* Abort occurred - clear it and exit */ LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DRCR, DRCR_CSE); + armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); goto error_free_buff_r; } @@ -1986,10 +1986,10 @@ static int aarch64_read_apb_ap_memory(struct target *target, error_unset_dtr_r: /* Unset DTR mode */ mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); dscr = (dscr & ~DSCR_MA); mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, dscr); + armv8->debug_base + CPUV8_DBG_DSCR, dscr); error_free_buff_r: LOG_ERROR("error"); free(tmp_buff); @@ -2229,16 +2229,16 @@ static int aarch64_handle_target_request(void *priv) uint32_t request; uint32_t dscr; retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); /* check if we have data */ while ((dscr & DSCR_DTR_TX_FULL) && (retval == ERROR_OK)) { retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DTRTX, &request); + armv8->debug_base + CPUV8_DBG_DTRTX, &request); if (retval == ERROR_OK) { target_request(target, request); retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_DSCR, &dscr); + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); } } } @@ -2310,7 +2310,7 @@ static int aarch64_examine_first(struct target *target) armv8->debug_base = target->dbgbase; retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x300, 0); + armv8->debug_base + CPUV8_DBG_LOCKACCESS, 0xC5ACCE55); if (retval != ERROR_OK) { LOG_DEBUG("Examine %s failed", "oslock"); return retval; diff --git a/src/target/armv8.h b/src/target/armv8.h index ccb205c..41edb99 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -159,34 +159,38 @@ target_to_armv8(struct target *target) } /* register offsets from armv8.debug_base */ +#define CPUV8_DBG_MAINID0 0xD00 +#define CPUV8_DBG_CPUFEATURE0 0xD20 +#define CPUV8_DBG_DBGFEATURE0 0xD28 +#define CPUV8_DBG_MEMFEATURE0 0xD38 + +#define CPUV8_DBG_LOCKACCESS 0xFB0 +#define CPUV8_DBG_LOCKSTATUS 0xFB4 + +#define CPUV8_DBG_EDESR 0x20 +#define CPUV8_DBG_EDECR 0x24 +#define CPUV8_DBG_WFAR0 0x30 +#define CPUV8_DBG_WFAR1 0x34 +#define CPUV8_DBG_DSCR 0x088 +#define CPUV8_DBG_DRCR 0x090 +#define CPUV8_DBG_PRCR 0x310 +#define CPUV8_DBG_PRSR 0x314 + +#define CPUV8_DBG_DTRRX 0x080 +#define CPUV8_DBG_ITR 0x084 +#define CPUV8_DBG_SCR 0x088 +#define CPUV8_DBG_DTRTX 0x08c + +#define CPUV8_DBG_BVR_BASE 0x400 +#define CPUV8_DBG_BCR_BASE 0x408 +#define CPUV8_DBG_WVR_BASE 0x800 +#define CPUV8_DBG_WCR_BASE 0x808 +#define CPUV8_DBG_VCR 0x01C + +#define CPUV8_DBG_OSLAR 0x300 + +#define CPUV8_DBG_AUTHSTATUS 0xFB8 -#define CPUDBG_WFAR 0x018 -#define CPUDBG_DESR 0x020 -#define CPUDBG_DECR 0x024 -/* PCSR at 0x084 -or- 0x0a0 -or- both ... based on flags in DIDR */ -#define CPUDBG_DSCR 0x088 -#define CPUDBG_DRCR 0x090 -#define CPUDBG_PRCR 0x310 -#define CPUDBG_PRSR 0x314 - -#define CPUDBG_DTRRX 0x080 -#define CPUDBG_ITR 0x084 -#define CPUDBG_DTRTX 0x08c - -#define CPUDBG_BVR_BASE 0x400 -#define CPUDBG_BCR_BASE 0x408 -#define CPUDBG_WVR_BASE 0x180 -#define CPUDBG_WCR_BASE 0x1C0 -#define CPUDBG_VCR 0x01C - -#define CPUDBG_OSLAR 0x300 -#define CPUDBG_OSLSR 0x304 -#define CPUDBG_OSSRR 0x308 -#define CPUDBG_ECR 0x024 - -#define CPUDBG_DSCCR 0x028 - -#define CPUDBG_AUTHSTATUS 0xFB8 int armv8_arch_state(struct target *target); int armv8_identify_cache(struct target *target); -- cgit v1.1 From 4ba8388f2658314c0de944d088c964cb19d11050 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Sat, 17 Sep 2016 21:43:15 +0200 Subject: aarch64: fix context and hybrid hardware breakpoints Fix 64bit address setting Fix register spacing (16 instead of 4) Set HMC bit for all but linked context match breakpoints, where the bit is ignored anyway Change-Id: I48428f39154a6fe5fadc075ca918d1500a0bb241 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 84e6db3..d06e668 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1348,18 +1348,19 @@ static int aarch64_set_context_breakpoint(struct target *target, breakpoint->set = brp_i + 1; control = ((matchmode & 0x7) << 20) + | (1 << 13) | (byte_addr_select << 5) | (3 << 1) | 1; brp_list[brp_i].used = 1; brp_list[brp_i].value = (breakpoint->asid); brp_list[brp_i].control = control; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUV8_DBG_BVR_BASE + 4 * brp_list[brp_i].BRPn, + + CPUV8_DBG_BVR_BASE + 16 * brp_list[brp_i].BRPn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUV8_DBG_BCR_BASE + 4 * brp_list[brp_i].BRPn, + + CPUV8_DBG_BCR_BASE + 16 * brp_list[brp_i].BRPn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; @@ -1420,30 +1421,36 @@ static int aarch64_set_hybrid_breakpoint(struct target *target, struct breakpoin brp_list[brp_1].value = (breakpoint->asid); brp_list[brp_1].control = control_CTX; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUV8_DBG_BVR_BASE + 4 * brp_list[brp_1].BRPn, + + CPUV8_DBG_BVR_BASE + 16 * brp_list[brp_1].BRPn, brp_list[brp_1].value); if (retval != ERROR_OK) return retval; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUV8_DBG_BCR_BASE + 4 * brp_list[brp_1].BRPn, + + CPUV8_DBG_BCR_BASE + 16 * brp_list[brp_1].BRPn, brp_list[brp_1].control); if (retval != ERROR_OK) return retval; control_IVA = ((IVA_machmode & 0x7) << 20) | (brp_1 << 16) + | (1 << 13) | (IVA_byte_addr_select << 5) | (3 << 1) | 1; brp_list[brp_2].used = 1; - brp_list[brp_2].value = (breakpoint->address & 0xFFFFFFFC); + brp_list[brp_2].value = breakpoint->address & 0xFFFFFFFFFFFFFFFC; brp_list[brp_2].control = control_IVA; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUV8_DBG_BVR_BASE + 4 * brp_list[brp_2].BRPn, - brp_list[brp_2].value); + + CPUV8_DBG_BVR_BASE + 16 * brp_list[brp_2].BRPn, + brp_list[brp_2].value & 0xFFFFFFFF); if (retval != ERROR_OK) return retval; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUV8_DBG_BCR_BASE + 4 * brp_list[brp_2].BRPn, + + CPUV8_DBG_BVR_BASE + 4 + 16 * brp_list[brp_2].BRPn, + brp_list[brp_2].value >> 32); + if (retval != ERROR_OK) + return retval; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUV8_DBG_BCR_BASE + 16 * brp_list[brp_2].BRPn, brp_list[brp_2].control); if (retval != ERROR_OK) return retval; @@ -1511,12 +1518,12 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br brp_list[brp_i].value = 0; brp_list[brp_i].control = 0; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUV8_DBG_BCR_BASE + 4 * brp_list[brp_i].BRPn, + + CPUV8_DBG_BCR_BASE + 16 * brp_list[brp_i].BRPn, brp_list[brp_i].control); if (retval != ERROR_OK) return retval; retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base - + CPUV8_DBG_BVR_BASE + 4 * brp_list[brp_i].BRPn, + + CPUV8_DBG_BVR_BASE + 16 * brp_list[brp_i].BRPn, brp_list[brp_i].value); if (retval != ERROR_OK) return retval; -- cgit v1.1 From 21a5c404304bfc616de7648a3de67d91a2c43e66 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 11:02:36 +0200 Subject: aarch64: formalize use of CTI in halt and resume Use configured CTI base address instead of hardcoded value, if available. Use symbolic constants instead of raw hex offsets. Trim halt and resume code to what is actually necessary. Change-Id: I4997c2bcca7cebf5ad78859a6a12abe8639594ed Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 94 +++++++++++++++++++++------------------------------- src/target/armv8.h | 31 +++++++++++++++++ 2 files changed, 68 insertions(+), 57 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index d06e668..4097d11 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -796,59 +796,49 @@ static int aarch64_halt(struct target *target) uint32_t dscr; struct armv8_common *armv8 = target_to_armv8(target); - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0, &dscr); + /* enable CTI*/ retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0, 1); - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0, &dscr); + armv8->cti_base + CTI_CTR, 1); + if (retval != ERROR_OK) + return retval; - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0x140, &dscr); retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0x140, 6); - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0x140, &dscr); + armv8->cti_base + CTI_GATE, 3); + if (retval != ERROR_OK) + return retval; - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0xa0, &dscr); retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0xa0, 5); - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0xa0, &dscr); - - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0xa4, &dscr); - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0xa4, 2); - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0xa4, &dscr); + armv8->cti_base + CTI_OUTEN0, 1); + if (retval != ERROR_OK) + return retval; - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0x20, &dscr); retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0x20, 4); - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0x20, &dscr); + armv8->cti_base + CTI_OUTEN1, 2); + if (retval != ERROR_OK) + return retval; /* - * enter halting debug mode + * add HDE in halting debug mode */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; -# /* STATUS */ - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0x134, &dscr); + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DSCR, dscr | DSCR_HDE); + if (retval != ERROR_OK) + return retval; - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0x1c, &dscr); retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0x1c, 1); - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0x1c, &dscr); + armv8->cti_base + CTI_APPPULSE, 1); + if (retval != ERROR_OK) + return retval; + + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->cti_base + CTI_INACK, 1); + if (retval != ERROR_OK) + return retval; long long then = timeval_ms(); @@ -857,7 +847,7 @@ static int aarch64_halt(struct target *target) armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; - if ((dscr & DSCR_CORE_HALTED) != 0) + if ((dscr & DSCRV8_HALT_MASK) != 0) break; if (timeval_ms() > then + 1000) { LOG_ERROR("Timeout waiting for halt"); @@ -969,23 +959,7 @@ static int aarch64_internal_restart(struct target *target) LOG_ERROR("DSCR InstrCompl must be set before leaving debug!"); retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, dscr & ~DSCR_ITR_EN); - if (retval != ERROR_OK) - return retval; - - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, DRCR_RESTART | - DRCR_CLEAR_EXCEPTIONS); - if (retval != ERROR_OK) - return retval; - - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0x10, 1); - if (retval != ERROR_OK) - return retval; - - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x10000 + 0x1c, 2); + armv8->cti_base + CTI_APPPULSE, 2); if (retval != ERROR_OK) return retval; @@ -995,7 +969,7 @@ static int aarch64_internal_restart(struct target *target) armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; - if ((dscr & DSCR_CORE_RESTARTED) != 0) + if ((dscr & DSCR_HDE) != 0) break; if (timeval_ms() > then + 1000) { LOG_ERROR("Timeout waiting for resume"); @@ -1061,11 +1035,11 @@ static int aarch64_resume(struct target *target, int current, if (!debug_execution) { target->state = TARGET_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_RESUMED); - LOG_DEBUG("target resumed at 0x%" PRIu64, addr); + LOG_DEBUG("target resumed at 0x%" PRIx64, addr); } else { target->state = TARGET_DEBUG_RUNNING; target_call_event_callbacks(target, TARGET_EVENT_DEBUG_RESUMED); - LOG_DEBUG("target debug resumed at 0x%" PRIu64, addr); + LOG_DEBUG("target debug resumed at 0x%" PRIx64, addr); } return ERROR_OK; @@ -2316,6 +2290,12 @@ static int aarch64_examine_first(struct target *target) } else armv8->debug_base = target->dbgbase; + LOG_DEBUG("Target ctibase is 0x%x", target->ctibase); + if (target->ctibase == 0) + armv8->cti_base = target->ctibase = armv8->debug_base + 0x1000; + else + armv8->cti_base = target->ctibase; + retval = mem_ap_write_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_LOCKACCESS, 0xC5ACCE55); if (retval != ERROR_OK) { diff --git a/src/target/armv8.h b/src/target/armv8.h index 41edb99..9c6ccce 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -130,6 +130,8 @@ struct armv8_common { /* Core Debug Unit */ struct arm_dpm dpm; uint32_t debug_base; + uint32_t cti_base; + struct adiv5_ap *debug_ap; struct adiv5_ap *memory_ap; bool memory_ap_available; @@ -191,6 +193,35 @@ target_to_armv8(struct target *target) #define CPUV8_DBG_AUTHSTATUS 0xFB8 +/*define CTI(cross trigger interface)*/ +#define CTI_CTR 0x0 +#define CTI_INACK 0x10 +#define CTI_APPSET 0x14 +#define CTI_APPCLEAR 0x18 +#define CTI_APPPULSE 0x1C +#define CTI_INEN0 0x20 +#define CTI_INEN1 0x24 +#define CTI_INEN2 0x28 +#define CTI_INEN3 0x2C +#define CTI_INEN4 0x30 +#define CTI_INEN5 0x34 +#define CTI_INEN6 0x38 +#define CTI_INEN7 0x3C +#define CTI_OUTEN0 0xA0 +#define CTI_OUTEN1 0xA4 +#define CTI_OUTEN2 0xA8 +#define CTI_OUTEN3 0xAC +#define CTI_OUTEN4 0xB0 +#define CTI_OUTEN5 0xB4 +#define CTI_OUTEN6 0xB8 +#define CTI_OUTEN7 0xBC +#define CTI_TRIN_STATUS 0x130 +#define CTI_TROUT_STATUS 0x134 +#define CTI_CHIN_STATUS 0x138 +#define CTI_CHOU_STATUS 0x13C +#define CTI_GATE 0x140 +#define CTI_UNLOCK 0xFB0 + int armv8_arch_state(struct target *target); int armv8_identify_cache(struct target *target); -- cgit v1.1 From f28d5ee71fcbcd296d85e236013e16790732c3af Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 11:06:42 +0200 Subject: aarch64: fix error recovery in aarch64_dpm_prepare Flush DTRRX with a dummy read if it's full, clear sticky errors by writing CSE bit to EDRCR register. Change-Id: Ia42ae9d3859ba6cbe892d48584e21acdd4e25c84 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 4097d11..fcf600d 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -360,10 +360,14 @@ static int aarch64_dpm_prepare(struct arm_dpm *dpm) if (dscr & DSCR_DTR_RX_FULL) { LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr); /* Clear DCCRX */ - retval = aarch64_exec_opcode( - a8->armv8_common.arm.target, - 0xd5130400, - &dscr); + retval = mem_ap_read_u32(a8->armv8_common.debug_ap, + a8->armv8_common.debug_base + CPUV8_DBG_DTRRX, &dscr); + if (retval != ERROR_OK) + return retval; + + /* Clear sticky error */ + retval = mem_ap_write_u32(a8->armv8_common.debug_ap, + a8->armv8_common.debug_base + CPUV8_DBG_DRCR, DRCR_CSE); if (retval != ERROR_OK) return retval; } -- cgit v1.1 From 044e4b81080ad80815ce56636dfec9ecc5df5b13 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 11:10:55 +0200 Subject: aarch64: fix accesses to SCTLR_ELn register The system control register has several instances, depending on the exception level. Make sure to access always access the correct one. Change-Id: I9e867f4dbd9625762042f20ed905064ea4e3270f Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 169 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 142 insertions(+), 27 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index fcf600d..09e828e 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -57,11 +57,41 @@ static int aarch64_restore_system_control_reg(struct target *target) if (aarch64->system_control_reg != aarch64->system_control_reg_curr) { aarch64->system_control_reg_curr = aarch64->system_control_reg; - retval = aarch64_instr_write_data_r0(armv8->arm.dpm, - 0xd5181000, - aarch64->system_control_reg); + /* LOG_INFO("cp15_control_reg: %8.8" PRIx32, cortex_v8->cp15_control_reg); */ + + switch (armv8->arm.core_mode) { + case ARMV8_64_EL0T: + case ARMV8_64_EL1T: + case ARMV8_64_EL1H: + retval = armv8->arm.msr(target, 3, /*op 0*/ + 0, 1, /* op1, op2 */ + 0, 0, /* CRn, CRm */ + aarch64->system_control_reg); + if (retval != ERROR_OK) + return retval; + break; + case ARMV8_64_EL2T: + case ARMV8_64_EL2H: + retval = armv8->arm.msr(target, 3, /*op 0*/ + 4, 1, /* op1, op2 */ + 0, 0, /* CRn, CRm */ + aarch64->system_control_reg); + if (retval != ERROR_OK) + return retval; + break; + case ARMV8_64_EL3H: + case ARMV8_64_EL3T: + retval = armv8->arm.msr(target, 3, /*op 0*/ + 6, 1, /* op1, op2 */ + 0, 0, /* CRn, CRm */ + aarch64->system_control_reg); + if (retval != ERROR_OK) + return retval; + break; + default: + LOG_DEBUG("unknow cpu state 0x%x" PRIx32, armv8->arm.core_state); + } } - return retval; } @@ -82,16 +112,45 @@ static int aarch64_mmu_modify(struct target *target, int enable) int retval = ERROR_OK; if (enable) { - /* if mmu enabled at target stop and mmu not enable */ + /* if mmu enabled at target stop and mmu not enable */ if (!(aarch64->system_control_reg & 0x1U)) { LOG_ERROR("trying to enable mmu on target stopped with mmu disable"); return ERROR_FAIL; } if (!(aarch64->system_control_reg_curr & 0x1U)) { aarch64->system_control_reg_curr |= 0x1U; - retval = aarch64_instr_write_data_r0(armv8->arm.dpm, - 0xd5181000, - aarch64->system_control_reg_curr); + switch (armv8->arm.core_mode) { + case ARMV8_64_EL0T: + case ARMV8_64_EL1T: + case ARMV8_64_EL1H: + retval = armv8->arm.msr(target, 3, /*op 0*/ + 0, 0, /* op1, op2 */ + 1, 0, /* CRn, CRm */ + aarch64->system_control_reg_curr); + if (retval != ERROR_OK) + return retval; + break; + case ARMV8_64_EL2T: + case ARMV8_64_EL2H: + retval = armv8->arm.msr(target, 3, /*op 0*/ + 4, 0, /* op1, op2 */ + 1, 0, /* CRn, CRm */ + aarch64->system_control_reg_curr); + if (retval != ERROR_OK) + return retval; + break; + case ARMV8_64_EL3H: + case ARMV8_64_EL3T: + retval = armv8->arm.msr(target, 3, /*op 0*/ + 6, 0, /* op1, op2 */ + 1, 0, /* CRn, CRm */ + aarch64->system_control_reg_curr); + if (retval != ERROR_OK) + return retval; + break; + default: + LOG_DEBUG("unknow cpu state 0x%x" PRIx32, armv8->arm.core_state); + } } } else { if (aarch64->system_control_reg_curr & 0x4U) { @@ -103,9 +162,39 @@ static int aarch64_mmu_modify(struct target *target, int enable) } if ((aarch64->system_control_reg_curr & 0x1U)) { aarch64->system_control_reg_curr &= ~0x1U; - retval = aarch64_instr_write_data_r0(armv8->arm.dpm, - 0xd5181000, - aarch64->system_control_reg_curr); + switch (armv8->arm.core_mode) { + case ARMV8_64_EL0T: + case ARMV8_64_EL1T: + case ARMV8_64_EL1H: + retval = armv8->arm.msr(target, 3, /*op 0*/ + 0, 0, /* op1, op2 */ + 1, 0, /* CRn, CRm */ + aarch64->system_control_reg_curr); + if (retval != ERROR_OK) + return retval; + break; + case ARMV8_64_EL2T: + case ARMV8_64_EL2H: + retval = armv8->arm.msr(target, 3, /*op 0*/ + 4, 0, /* op1, op2 */ + 1, 0, /* CRn, CRm */ + aarch64->system_control_reg_curr); + if (retval != ERROR_OK) + return retval; + break; + case ARMV8_64_EL3H: + case ARMV8_64_EL3T: + retval = armv8->arm.msr(target, 3, /*op 0*/ + 6, 0, /* op1, op2 */ + 1, 0, /* CRn, CRm */ + aarch64->system_control_reg_curr); + if (retval != ERROR_OK) + return retval; + break; + default: + LOG_DEBUG("unknow cpu state 0x%x" PRIx32, armv8->arm.core_state); + break; + } } } return retval; @@ -1111,31 +1200,57 @@ static int aarch64_post_debug_entry(struct target *target) { struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = &aarch64->armv8_common; - struct armv8_mmu_common *armv8_mmu = &armv8->armv8_mmu; - uint32_t sctlr_el1 = 0; int retval; mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, 1<<2); - retval = aarch64_instr_read_data_r0(armv8->arm.dpm, - 0xd5381000, &sctlr_el1); - if (retval != ERROR_OK) - return retval; - - LOG_DEBUG("sctlr_el1 = %#8.8x", sctlr_el1); - aarch64->system_control_reg = sctlr_el1; - aarch64->system_control_reg_curr = sctlr_el1; - aarch64->curr_mode = armv8->arm.core_mode; - - armv8_mmu->mmu_enabled = sctlr_el1 & 0x1U ? 1 : 0; - armv8_mmu->armv8_cache.d_u_cache_enabled = sctlr_el1 & 0x4U ? 1 : 0; - armv8_mmu->armv8_cache.i_cache_enabled = sctlr_el1 & 0x1000U ? 1 : 0; + armv8->debug_base + CPUV8_DBG_DRCR, 1<<2); + switch (armv8->arm.core_mode) { + case ARMV8_64_EL0T: + case ARMV8_64_EL1T: + case ARMV8_64_EL1H: + retval = armv8->arm.mrs(target, 3, /*op 0*/ + 0, 0, /* op1, op2 */ + 1, 0, /* CRn, CRm */ + &aarch64->system_control_reg); + if (retval != ERROR_OK) + return retval; + break; + case ARMV8_64_EL2T: + case ARMV8_64_EL2H: + retval = armv8->arm.mrs(target, 3, /*op 0*/ + 4, 0, /* op1, op2 */ + 1, 0, /* CRn, CRm */ + &aarch64->system_control_reg); + if (retval != ERROR_OK) + return retval; + break; + case ARMV8_64_EL3H: + case ARMV8_64_EL3T: + retval = armv8->arm.mrs(target, 3, /*op 0*/ + 6, 0, /* op1, op2 */ + 1, 0, /* CRn, CRm */ + &aarch64->system_control_reg); + if (retval != ERROR_OK) + return retval; + break; + default: + LOG_DEBUG("unknow cpu state 0x%x" PRIx32, armv8->arm.core_state); + } + LOG_DEBUG("System_register: %8.8" PRIx32, aarch64->system_control_reg); + aarch64->system_control_reg_curr = aarch64->system_control_reg; #if 0 if (armv8->armv8_mmu.armv8_cache.ctype == -1) armv8_identify_cache(target); #endif + armv8->armv8_mmu.mmu_enabled = + (aarch64->system_control_reg & 0x1U) ? 1 : 0; + armv8->armv8_mmu.armv8_cache.d_u_cache_enabled = + (aarch64->system_control_reg & 0x4U) ? 1 : 0; + armv8->armv8_mmu.armv8_cache.i_cache_enabled = + (aarch64->system_control_reg & 0x1000U) ? 1 : 0; + aarch64->curr_mode = armv8->arm.core_mode; return ERROR_OK; } -- cgit v1.1 From 391109505fff97772c70f7dda02865e7a9863007 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 11:15:15 +0200 Subject: aarch64: use symbolic opcodes instead of hex values Use opcode definitions from armv8_opcodes.h where appropriate Change-Id: Iead33fb8e62eb2dd2419ef8932f7d46c087f51a8 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 09e828e..8ddc226 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -529,7 +529,7 @@ static int aarch64_instr_write_data_r0(struct arm_dpm *dpm, retval = aarch64_exec_opcode( a8->armv8_common.arm.target, - 0xd5330500, + ARMV8_MRS(SYSTEM_DBG_DTRRX_EL0, 0), &dscr); if (retval != ERROR_OK) return retval; @@ -556,7 +556,7 @@ static int aarch64_instr_write_data_r0_64(struct arm_dpm *dpm, retval = aarch64_exec_opcode( a8->armv8_common.arm.target, - 0xd5330400, + ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), &dscr); if (retval != ERROR_OK) return retval; @@ -577,7 +577,7 @@ static int aarch64_instr_cpsr_sync(struct arm_dpm *dpm) /* "Prefetch flush" after modifying execution status in CPSR */ return aarch64_exec_opcode(target, - ARMV4_5_MCR(15, 0, 0, 7, 5, 4), + DSB_SY, &dscr); } @@ -635,7 +635,7 @@ static int aarch64_instr_read_data_r0(struct arm_dpm *dpm, /* write R0 to DCC */ retval = aarch64_exec_opcode( a8->armv8_common.arm.target, - 0xd5130400, /* msr dbgdtr_el0, x0 */ + ARMV8_MSR_GP(SYSTEM_DBG_DTRTX_EL0, 0), /* msr dbgdtr_el0, x0 */ &dscr); if (retval != ERROR_OK) return retval; @@ -661,7 +661,7 @@ static int aarch64_instr_read_data_r0_64(struct arm_dpm *dpm, /* write R0 to DCC */ retval = aarch64_exec_opcode( a8->armv8_common.arm.target, - 0xd5130400, /* msr dbgdtr_el0, x0 */ + ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 0), /* msr dbgdtr_el0, x0 */ &dscr); if (retval != ERROR_OK) return retval; @@ -1384,8 +1384,7 @@ static int aarch64_set_breakpoint(struct target *target, } else if (breakpoint->type == BKPT_SOFT) { uint8_t code[4]; - buf_set_u32(code, 0, 32, 0xD4400000); - + buf_set_u32(code, 0, 32, ARMV8_BKPT(0x11)); retval = target_read_memory(target, breakpoint->address & 0xFFFFFFFFFFFFFFFE, breakpoint->length, 1, -- cgit v1.1 From d8abda4bd828f40fc76613f4d809d86f4c6f1c97 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 11:34:03 +0200 Subject: aarch64: fix entry into debug state - armv8 EDSCR has no ITR_EN bit, ITR is always enabled. Writes to this bit are ignored but we should not do them anyway - use dpmv8 function to report the reason for debug entry - WFAR is a 64bit register Change-Id: I07b81ecf105ceb7c3ae2f764bb408eb973c1d1de Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 34 +++++++++++++++------------------- src/target/arm_dpm.h | 2 +- 2 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 8ddc226..ef73afd 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1140,49 +1140,45 @@ static int aarch64_resume(struct target *target, int current, static int aarch64_debug_entry(struct target *target) { - uint32_t dscr; int retval = ERROR_OK; struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = target_to_armv8(target); - uint32_t tmp; LOG_DEBUG("dscr = 0x%08" PRIx32, aarch64->cpudbg_dscr); - /* REVISIT surely we should not re-read DSCR !! */ - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, &dscr); - if (retval != ERROR_OK) - return retval; - /* REVISIT see A8 TRM 12.11.4 steps 2..3 -- make sure that any * imprecise data aborts get discarded by issuing a Data * Synchronization Barrier: ARMV4_5_MCR(15, 0, 0, 7, 10, 4). */ - /* Enable the ITR execution once we are in debug mode */ - dscr |= DSCR_ITR_EN; + /* make sure to clear all sticky errors */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, dscr); + armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); if (retval != ERROR_OK) return retval; /* Examine debug reason */ - arm_dpm_report_dscr(&armv8->dpm, aarch64->cpudbg_dscr); - mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_EDESR, &tmp); - if ((tmp & 0x7) == 0x4) - target->debug_reason = DBG_REASON_SINGLESTEP; + armv8_dpm_report_dscr(&armv8->dpm, aarch64->cpudbg_dscr); /* save address of instruction that triggered the watchpoint? */ if (target->debug_reason == DBG_REASON_WATCHPOINT) { - uint32_t wfar; + uint32_t tmp; + uint64_t wfar = 0; retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_WFAR1, + &tmp); + if (retval != ERROR_OK) + return retval; + wfar = tmp; + wfar = (wfar << 32); + retval = mem_ap_read_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_WFAR0, - &wfar); + &tmp); if (retval != ERROR_OK) return retval; - arm_dpm_report_wfar(&armv8->dpm, wfar); + wfar |= tmp; + armv8_dpm_report_wfar(&armv8->dpm, wfar); } retval = armv8_dpm_read_current_registers(&armv8->dpm); diff --git a/src/target/arm_dpm.h b/src/target/arm_dpm.h index ad49b8c..27badf4 100644 --- a/src/target/arm_dpm.h +++ b/src/target/arm_dpm.h @@ -138,7 +138,7 @@ struct arm_dpm { struct dpm_wp *dwp; /** Address of the instruction which triggered a watchpoint. */ - uint32_t wp_pc; + target_addr_t wp_pc; /** Recent value of DSCR. */ uint32_t dscr; -- cgit v1.1 From 7eb95b1d72c0e4aea3499caf33312f8846bab262 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 11:43:27 +0200 Subject: aarch64: fix reading of translation table registers Correctly access and parse aarch64 ttbcr. Change-Id: I1b1652791a6b5200f58033925286292d838e8410 Signed-off-by: Matthias Welwarsky --- src/target/armv8.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++------ src/target/armv8.h | 8 ++++- 2 files changed, 100 insertions(+), 11 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 537dadb..5a96d96 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -266,31 +266,114 @@ static void armv8_show_fault_registers(struct target *target) /* TODO */ } +static uint8_t armv8_pa_size(uint32_t ps) +{ + uint8_t ret = 0; + switch (ps) { + case 0: + ret = 32; + break; + case 1: + ret = 36; + break; + case 2: + ret = 40; + break; + case 3: + ret = 42; + break; + case 4: + ret = 44; + break; + case 5: + ret = 48; + break; + default: + LOG_INFO("Unknow physicall address size"); + break; + } + return ret; +} + static int armv8_read_ttbcr(struct target *target) { struct armv8_common *armv8 = target_to_armv8(target); struct arm_dpm *dpm = armv8->arm.dpm; + struct arm *arm = &armv8->arm; uint32_t ttbcr; + uint64_t ttbcr_64; + int retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; - /* MRC p15,0,,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/ - retval = dpm->instr_read_data_r0(dpm, - ARMV4_5_MRC(15, 0, 0, 2, 0, 2), - &ttbcr); + + /* claaer ttrr1_used and ttbr0_mask */ + memset(&armv8->armv8_mmu.ttbr1_used, 0, sizeof(armv8->armv8_mmu.ttbr1_used)); + memset(&armv8->armv8_mmu.ttbr0_mask, 0, sizeof(armv8->armv8_mmu.ttbr0_mask)); + + switch (arm->core_mode) { + case ARMV8_64_EL3H: + case ARMV8_64_EL3T: + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS(SYSTEM_TCR_EL3, 0), + &ttbcr); + retval += dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_TTBR0_EL3, 0), + &armv8->ttbr_base); + if (retval != ERROR_OK) + goto done; + armv8->va_size = 64 - (ttbcr & 0x3F); + armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7); + armv8->page_size = (ttbcr >> 14) & 3; + break; + case ARMV8_64_EL2T: + case ARMV8_64_EL2H: + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS(SYSTEM_TCR_EL2, 0), + &ttbcr); + retval += dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_TTBR0_EL2, 0), + &armv8->ttbr_base); + if (retval != ERROR_OK) + goto done; + armv8->va_size = 64 - (ttbcr & 0x3F); + armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7); + armv8->page_size = (ttbcr >> 14) & 3; + break; + case ARMV8_64_EL0T: + case ARMV8_64_EL1T: + case ARMV8_64_EL1H: + retval = dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_TCR_EL1, 0), + &ttbcr_64); + armv8->va_size = 64 - (ttbcr_64 & 0x3F); + armv8->pa_size = armv8_pa_size((ttbcr_64 >> 32) & 7); + armv8->page_size = (ttbcr_64 >> 14) & 3; + armv8->armv8_mmu.ttbr1_used = (((ttbcr_64 >> 16) & 0x3F) != 0) ? 1 : 0; + armv8->armv8_mmu.ttbr0_mask = 0x0000FFFFFFFFFFFF; + retval += dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_TTBR0_EL1 | (armv8->armv8_mmu.ttbr1_used), 0), + &armv8->ttbr_base); + if (retval != ERROR_OK) + goto done; + break; + default: + LOG_ERROR("unknow core state"); + retval = ERROR_FAIL; + break; + } if (retval != ERROR_OK) goto done; - armv8->armv8_mmu.ttbr1_used = ((ttbcr & 0x7) != 0) ? 1 : 0; - armv8->armv8_mmu.ttbr0_mask = 7 << (32 - ((ttbcr & 0x7))); + #if 0 - LOG_INFO("ttb1 %s ,ttb0_mask %x", + LOG_INFO("ttb1 %s ,ttb0_mask %llx", armv8->armv8_mmu.ttbr1_used ? "used" : "not used", armv8->armv8_mmu.ttbr0_mask); #endif if (armv8->armv8_mmu.ttbr1_used == 1) { - LOG_INFO("SVC access above %" PRIx32, - (uint32_t)(0xffffffff & armv8->armv8_mmu.ttbr0_mask)); - armv8->armv8_mmu.os_border = 0xffffffff & armv8->armv8_mmu.ttbr0_mask; + LOG_INFO("TTBR0 access above %" PRIx64, + (uint64_t)(armv8->armv8_mmu.ttbr0_mask)); + armv8->armv8_mmu.os_border = armv8->armv8_mmu.ttbr0_mask; } else { /* fix me , default is hard coded LINUX border */ armv8->armv8_mmu.os_border = 0xc0000000; diff --git a/src/target/armv8.h b/src/target/armv8.h index 9c6ccce..b9e3f12 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -113,7 +113,7 @@ struct armv8_cache_common { struct armv8_mmu_common { /* following field mmu working way */ int32_t ttbr1_used; /* -1 not initialized, 0 no ttbr1 1 ttbr1 used and */ - uint32_t ttbr0_mask;/* masked to be used */ + uint64_t ttbr0_mask;/* masked to be used */ uint32_t os_border; int (*read_physical_memory)(struct target *target, target_addr_t address, @@ -141,6 +141,12 @@ struct armv8_common { uint8_t cpu_id; bool is_armv7r; + /* armv8 aarch64 need below information for page translation */ + uint8_t va_size; + uint8_t pa_size; + uint32_t page_size; + uint64_t ttbr_base; + /* cache specific to V7 Memory Management Unit compatible with v4_5*/ struct armv8_mmu_common armv8_mmu; -- cgit v1.1 From 4314624669fbeb5b4aed7ae33f9a031e022383c5 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 11:49:57 +0200 Subject: aarch64: fix cache identification Use correct instructions to access CLIDR, CSSELR and CCSIDR. Change-Id: I319b96c03a44fdb59fcb18a00f816f6af0261f0a Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 2 -- src/target/armv8.c | 44 ++++++++++++++++++-------------------------- 2 files changed, 18 insertions(+), 28 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index ef73afd..c2cd441 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1235,10 +1235,8 @@ static int aarch64_post_debug_entry(struct target *target) LOG_DEBUG("System_register: %8.8" PRIx32, aarch64->system_control_reg); aarch64->system_control_reg_curr = aarch64->system_control_reg; -#if 0 if (armv8->armv8_mmu.armv8_cache.ctype == -1) armv8_identify_cache(target); -#endif armv8->armv8_mmu.mmu_enabled = (aarch64->system_control_reg & 0x1U) ? 1 : 0; diff --git a/src/target/armv8.c b/src/target/armv8.c index 5a96d96..fda51ef 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -634,23 +634,22 @@ done: int armv8_identify_cache(struct target *target) { - /* read cache descriptor */ + /* read cache descriptor */ int retval = ERROR_FAIL; struct armv8_common *armv8 = target_to_armv8(target); struct arm_dpm *dpm = armv8->arm.dpm; uint32_t cache_selected, clidr; uint32_t cache_i_reg, cache_d_reg; struct armv8_cache_common *cache = &(armv8->armv8_mmu.armv8_cache); - if (!armv8->is_armv7r) - armv8_read_ttbcr(target); + armv8_read_ttbcr(target); retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; - /* retrieve CLIDR - * mrc p15, 1, r0, c0, c0, 1 @ read clidr */ + /* retrieve CLIDR + * mrc p15, 1, r0, c0, c0, 1 @ read clidr */ retval = dpm->instr_read_data_r0(dpm, - ARMV4_5_MRC(15, 1, 0, 0, 0, 1), + ARMV8_MRS(SYSTEM_CLIDR, 0), &clidr); if (retval != ERROR_OK) goto done; @@ -658,58 +657,51 @@ int armv8_identify_cache(struct target *target) LOG_INFO("number of cache level %" PRIx32, (uint32_t)(clidr / 2)); if ((clidr / 2) > 1) { /* FIXME not supported present in cortex A8 and later */ - /* in cortex A7, A15 */ + /* in cortex A7, A15 */ LOG_ERROR("cache l2 present :not supported"); } - /* retrieve selected cache - * MRC p15, 2,, c0, c0, 0; Read CSSELR */ + /* retrieve selected cache*/ retval = dpm->instr_read_data_r0(dpm, - ARMV4_5_MRC(15, 2, 0, 0, 0, 0), + ARMV8_MRS(SYSTEM_CSSELR, 0), &cache_selected); if (retval != ERROR_OK) goto done; - retval = armv8->arm.mrc(target, 15, - 2, 0, /* op1, op2 */ - 0, 0, /* CRn, CRm */ - &cache_selected); - if (retval != ERROR_OK) - goto done; + /* select instruction cache - * MCR p15, 2,, c0, c0, 0; Write CSSELR - * [0] : 1 instruction cache selection , 0 data cache selection */ + * [0] : 1 instruction cache selection , 0 data cache selection */ retval = dpm->instr_write_data_r0(dpm, - ARMV4_5_MRC(15, 2, 0, 0, 0, 0), + ARMV8_MRS(SYSTEM_CSSELR, 0), 1); if (retval != ERROR_OK) goto done; /* read CCSIDR * MRC P15,1,,C0, C0,0 ;on cortex A9 read CCSIDR - * [2:0] line size 001 eight word per line + * [2:0] line size 001 eight word per line * [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */ retval = dpm->instr_read_data_r0(dpm, - ARMV4_5_MRC(15, 1, 0, 0, 0, 0), + ARMV8_MRS(SYSTEM_CCSIDR, 0), &cache_i_reg); if (retval != ERROR_OK) goto done; - /* select data cache*/ + /* select data cache*/ retval = dpm->instr_write_data_r0(dpm, - ARMV4_5_MRC(15, 2, 0, 0, 0, 0), + ARMV8_MRS(SYSTEM_CSSELR, 0), 0); if (retval != ERROR_OK) goto done; retval = dpm->instr_read_data_r0(dpm, - ARMV4_5_MRC(15, 1, 0, 0, 0, 0), + ARMV8_MRS(SYSTEM_CCSIDR, 0), &cache_d_reg); if (retval != ERROR_OK) goto done; - /* restore selected cache */ + /* restore selected cache */ dpm->instr_write_data_r0(dpm, - ARMV4_5_MRC(15, 2, 0, 0, 0, 0), + ARMV8_MRS(SYSTEM_CSSELR, 0), cache_selected); if (retval != ERROR_OK) -- cgit v1.1 From 42574b3a10ca8b10e8b84b84c6427a3b9d09fe13 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 15:16:19 +0200 Subject: aarch64: correct breakpoint register offset armv8 breakpoint register spacing is 16, not 4 as in armv7-a Change-Id: I0d49d06878a0c9dab35cde478064e5366f01a8e0 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index c2cd441..4d4b461 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -690,8 +690,8 @@ static int aarch64_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, default: return ERROR_FAIL; } - vr += 4 * index_t; - cr += 4 * index_t; + vr += 16 * index_t; + cr += 16 * index_t; LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x", (unsigned) vr, (unsigned) cr); @@ -707,9 +707,6 @@ static int aarch64_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, static int aarch64_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) { - return ERROR_OK; - -#if 0 struct aarch64_common *a = dpm_to_a8(dpm); uint32_t cr; @@ -724,13 +721,13 @@ static int aarch64_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) default: return ERROR_FAIL; } - cr += 4 * index_t; + cr += 16 * index_t; LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr); /* clear control register */ return aarch64_dap_write_memap_register_u32(dpm->arm->target, cr, 0); -#endif + } static int aarch64_dpm_setup(struct aarch64_common *a8, uint32_t debug) -- cgit v1.1 From 667c1d0d16784d77c430f3f2a773ad2da4b72ea0 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 15:17:41 +0200 Subject: aarch64: clear breakpoint value register on removal Not only null control but also value of the breakpoint when it is removed. Change-Id: Id99c7e3644729c64e563f1fa8b0577f350be6a98 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 4d4b461..68de65d 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1571,6 +1571,16 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br brp_list[brp_i].control); if (retval != ERROR_OK) return retval; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUV8_DBG_BVR_BASE + 16 * brp_list[brp_i].BRPn, + (uint32_t)brp_list[brp_i].value); + if (retval != ERROR_OK) + return retval; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUV8_DBG_BVR_BASE + 4 + 16 * brp_list[brp_i].BRPn, + (uint32_t)brp_list[brp_i].value); + if (retval != ERROR_OK) + return retval; if ((brp_j < 0) || (brp_j >= aarch64->brp_num)) { LOG_DEBUG("Invalid BRP number in breakpoint"); return ERROR_OK; @@ -1585,6 +1595,17 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br brp_list[brp_j].control); if (retval != ERROR_OK) return retval; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUV8_DBG_BVR_BASE + 16 * brp_list[brp_j].BRPn, + (uint32_t)brp_list[brp_j].value); + if (retval != ERROR_OK) + return retval; + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUV8_DBG_BVR_BASE + 4 + 16 * brp_list[brp_j].BRPn, + (uint32_t)brp_list[brp_j].value); + if (retval != ERROR_OK) + return retval; + breakpoint->linked_BRP = 0; breakpoint->set = 0; return ERROR_OK; @@ -1610,6 +1631,12 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br brp_list[brp_i].value); if (retval != ERROR_OK) return retval; + + retval = aarch64_dap_write_memap_register_u32(target, armv8->debug_base + + CPUV8_DBG_BVR_BASE + 4 + 16 * brp_list[brp_i].BRPn, + (uint32_t)brp_list[brp_i].value); + if (retval != ERROR_OK) + return retval; breakpoint->set = 0; return ERROR_OK; } -- cgit v1.1 From 03861123d7ea0f031643afc0faa87027c58cbd11 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 15:18:47 +0200 Subject: aarch64: remove armv7-a virt-to-phys code Page table layout in aarch64 is very different from armv7-a layout. Remove the incorrect handling, to be replaced correct armv8 code in a later patch Change-Id: I64c728a72a24f9f4177726ccc07a02a8ca0d56ce Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 8 ++--- src/target/armv8.c | 100 +++++++-------------------------------------------- src/target/armv8.h | 12 +++++++ 3 files changed, 27 insertions(+), 93 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 68de65d..a2ed8b5 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2623,12 +2623,8 @@ static int aarch64_virt2phys(struct target *target, target_addr_t virt, if (retval != ERROR_OK) goto done; *phys = ret; - } else {/* use this method if armv8->memory_ap not selected - * mmu must be enable in order to get a correct translation */ - retval = aarch64_mmu_modify(target, 1); - if (retval != ERROR_OK) - goto done; - retval = armv8_mmu_translate_va_pa(target, virt, phys, 1); + } else { + LOG_ERROR("AAR64 processor not support translate va to pa"); } done: return retval; diff --git a/src/target/armv8.c b/src/target/armv8.c index fda51ef..f7c6e31 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -383,104 +383,30 @@ done: return retval; } +static int armv8_4K_translate(struct target *target, uint32_t va, uint32_t *val) +{ + LOG_ERROR("4K page Address translation need to add"); + return ERROR_FAIL; +} + /* method adapted to cortex A : reused arm v4 v5 method*/ int armv8_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val) { - uint32_t first_lvl_descriptor = 0x0; - uint32_t second_lvl_descriptor = 0x0; - int retval; + int retval = ERROR_FAIL; struct armv8_common *armv8 = target_to_armv8(target); struct arm_dpm *dpm = armv8->arm.dpm; - uint32_t ttb = 0; /* default ttb0 */ - if (armv8->armv8_mmu.ttbr1_used == -1) - armv8_read_ttbcr(target); - if ((armv8->armv8_mmu.ttbr1_used) && - (va > (0xffffffff & armv8->armv8_mmu.ttbr0_mask))) { - /* select ttb 1 */ - ttb = 1; - } + retval = dpm->prepare(dpm); + retval += armv8_read_ttbcr(target); if (retval != ERROR_OK) goto done; - - /* MRC p15,0,,c2,c0,ttb */ - retval = dpm->instr_read_data_r0(dpm, - ARMV4_5_MRC(15, 0, 0, 2, 0, ttb), - &ttb); - if (retval != ERROR_OK) - return retval; - retval = armv8->armv8_mmu.read_physical_memory(target, - (ttb & 0xffffc000) | ((va & 0xfff00000) >> 18), - 4, 1, (uint8_t *)&first_lvl_descriptor); - if (retval != ERROR_OK) - return retval; - first_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *) - &first_lvl_descriptor); - /* reuse armv4_5 piece of code, specific armv8 changes may come later */ - LOG_DEBUG("1st lvl desc: %8.8" PRIx32 "", first_lvl_descriptor); - - if ((first_lvl_descriptor & 0x3) == 0) { - LOG_ERROR("Address translation failure"); - return ERROR_TARGET_TRANSLATION_FAULT; - } - - - if ((first_lvl_descriptor & 0x3) == 2) { - /* section descriptor */ - *val = (first_lvl_descriptor & 0xfff00000) | (va & 0x000fffff); - return ERROR_OK; - } - - if ((first_lvl_descriptor & 0x3) == 1) { - /* coarse page table */ - retval = armv8->armv8_mmu.read_physical_memory(target, - (first_lvl_descriptor & 0xfffffc00) | ((va & 0x000ff000) >> 10), - 4, 1, (uint8_t *)&second_lvl_descriptor); - if (retval != ERROR_OK) - return retval; - } else if ((first_lvl_descriptor & 0x3) == 3) { - /* fine page table */ - retval = armv8->armv8_mmu.read_physical_memory(target, - (first_lvl_descriptor & 0xfffff000) | ((va & 0x000ffc00) >> 8), - 4, 1, (uint8_t *)&second_lvl_descriptor); - if (retval != ERROR_OK) - return retval; - } - - second_lvl_descriptor = target_buffer_get_u32(target, (uint8_t *) - &second_lvl_descriptor); - - LOG_DEBUG("2nd lvl desc: %8.8" PRIx32 "", second_lvl_descriptor); - - if ((second_lvl_descriptor & 0x3) == 0) { - LOG_ERROR("Address translation failure"); - return ERROR_TARGET_TRANSLATION_FAULT; - } - - if ((second_lvl_descriptor & 0x3) == 1) { - /* large page descriptor */ - *val = (second_lvl_descriptor & 0xffff0000) | (va & 0x0000ffff); - return ERROR_OK; - } - - if ((second_lvl_descriptor & 0x3) == 2) { - /* small page descriptor */ - *val = (second_lvl_descriptor & 0xfffff000) | (va & 0x00000fff); - return ERROR_OK; - } - - if ((second_lvl_descriptor & 0x3) == 3) { - *val = (second_lvl_descriptor & 0xfffffc00) | (va & 0x000003ff); - return ERROR_OK; - } - - /* should not happen */ - LOG_ERROR("Address translation failure"); - return ERROR_TARGET_TRANSLATION_FAULT; + if (armv8->page_size == 0) + return armv8_4K_translate(target, va, val); done: - return retval; + dpm->finish(dpm); + return ERROR_FAIL; } /* V8 method VA TO PA */ diff --git a/src/target/armv8.h b/src/target/armv8.h index b9e3f12..884d39a 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -228,6 +228,18 @@ target_to_armv8(struct target *target) #define CTI_GATE 0x140 #define CTI_UNLOCK 0xFB0 +#define PAGE_SIZE_4KB 0x1000 +#define PAGE_SIZE_4KB_LEVEL0_BITS 39 +#define PAGE_SIZE_4KB_LEVEL1_BITS 30 +#define PAGE_SIZE_4KB_LEVEL2_BITS 21 +#define PAGE_SIZE_4KB_LEVEL3_BITS 12 + +#define PAGE_SIZE_4KB_LEVEL0_MASK ((0x1FFULL) << PAGE_SIZE_4KB_LEVEL0_BITS) +#define PAGE_SIZE_4KB_LEVEL1_MASK ((0x1FFULL) << PAGE_SIZE_4KB_LEVEL1_BITS) +#define PAGE_SIZE_4KB_LEVEL2_MASK ((0x1FFULL) << PAGE_SIZE_4KB_LEVEL2_BITS) +#define PAGE_SIZE_4KB_LEVEL3_MASK ((0x1FFULL) << PAGE_SIZE_4KB_LEVEL3_BITS) + +#define PAGE_SIZE_4KB_TRBBASE_MASK 0xFFFFFFFFF000 int armv8_arch_state(struct target *target); int armv8_identify_cache(struct target *target); -- cgit v1.1 From f442a530fa14651cf417829e866b877449f29892 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 15:22:14 +0200 Subject: aarch64: use symbolic constant for register count Aarch64 has 34 registers, but use ARMV8_LAST_REG instead of raw integer constant. Change-Id: I86481899ade74f27fc90eff9f367d444c03e535e Signed-off-by: Matthias Welwarsky --- src/target/armv8.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index f7c6e31..06000c1 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -908,7 +908,7 @@ struct reg *armv8_reg_current(struct arm *arm, unsigned regnum) { struct reg *r; - if (regnum > 33) + if (regnum > (ARMV8_LAST_REG - 1)) return NULL; r = arm->core_cache->reg_list + regnum; @@ -933,14 +933,13 @@ int armv8_get_gdb_reg_list(struct target *target, switch (reg_class) { case REG_CLASS_GENERAL: case REG_CLASS_ALL: - *reg_list_size = 34; + *reg_list_size = ARMV8_LAST_REG; *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); - for (i = 0; i < *reg_list_size; i++) + for (i = 0; i < ARMV8_LAST_REG; i++) (*reg_list)[i] = armv8_reg_current(arm, i); return ERROR_OK; - break; default: LOG_ERROR("not a valid register class type in query."); -- cgit v1.1 From b273ec93c67895e376ce54b6c8086202696d0d81 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 15:23:27 +0200 Subject: aarch64: correct display for aarch64 state Aarch64 state has different PSTATE and exception level model. Correct the printout e.g. in poll command. Change-Id: I1820fd1836c7076ae0aa405fa335fd1a14a2e5b3 Signed-off-by: Matthias Welwarsky --- src/target/armv8.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 06000c1..d6b7dc8 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -724,6 +724,27 @@ int armv8_init_arch_info(struct target *target, struct armv8_common *armv8) return ERROR_OK; } +int armv8_aarch64_state(struct target *target) +{ + struct arm *arm = target_to_arm(target); + + if (arm->common_magic != ARM_COMMON_MAGIC) { + LOG_ERROR("BUG: called for a non-ARM target"); + return ERROR_FAIL; + } + + LOG_USER("target halted in %s state due to %s, current mode: %s\n" + "cpsr: 0x%8.8" PRIx32 " pc: 0x%" PRIx64 "%s", + armv8_state_strings[arm->core_state], + debug_reason_name(target), + armv8_mode_name(arm->core_mode), + buf_get_u32(arm->cpsr->value, 0, 32), + buf_get_u64(arm->pc->value, 0, 64), + arm->is_semihosting ? ", semihosting" : ""); + + return ERROR_OK; +} + int armv8_arch_state(struct target *target) { static const char * const state[] = { @@ -738,18 +759,15 @@ int armv8_arch_state(struct target *target) return ERROR_COMMAND_SYNTAX_ERROR; } - arm_arch_state(target); + if (arm->core_state == ARM_STATE_AARCH64) + armv8_aarch64_state(target); + else + arm_arch_state(target); - if (armv8->is_armv7r) { - LOG_USER("D-Cache: %s, I-Cache: %s", - state[armv8->armv8_mmu.armv8_cache.d_u_cache_enabled], - state[armv8->armv8_mmu.armv8_cache.i_cache_enabled]); - } else { - LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s", - state[armv8->armv8_mmu.mmu_enabled], - state[armv8->armv8_mmu.armv8_cache.d_u_cache_enabled], - state[armv8->armv8_mmu.armv8_cache.i_cache_enabled]); - } + LOG_USER("MMU: %s, D-Cache: %s, I-Cache: %s", + state[armv8->armv8_mmu.mmu_enabled], + state[armv8->armv8_mmu.armv8_cache.d_u_cache_enabled], + state[armv8->armv8_mmu.armv8_cache.i_cache_enabled]); if (arm->core_mode == ARM_MODE_ABT) armv8_show_fault_registers(target); -- cgit v1.1 From 6c096b2234b13033e7705b6148a74ed0c1923312 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 15:26:49 +0200 Subject: aarch64: fix first examination properly decode debug capabilities, remove superfluous register accesses. Change-Id: I2cca699b515262dd2a508d7be97826eb17b9c607 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 93 ++++++++++++++++++++++++---------------------------- 1 file changed, 42 insertions(+), 51 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index a2ed8b5..ae2ecbf 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -730,7 +730,7 @@ static int aarch64_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) } -static int aarch64_dpm_setup(struct aarch64_common *a8, uint32_t debug) +static int aarch64_dpm_setup(struct aarch64_common *a8, uint64_t debug) { struct arm_dpm *dpm = &a8->armv8_common.dpm; int retval; @@ -2368,9 +2368,12 @@ static int aarch64_examine_first(struct target *target) struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = &aarch64->armv8_common; struct adiv5_dap *swjdp = armv8->arm.dap; - int retval = ERROR_OK; - uint32_t pfr, debug, ctypr, ttypr, cpuid; int i; + int retval = ERROR_OK; + uint64_t debug, ttypr; + uint32_t cpuid; + uint32_t tmp0, tmp1; + debug = ttypr = cpuid = 0; /* We do one extra read to ensure DAP is configured, * we call ahbap_debugport_init(swjdp) instead @@ -2421,91 +2424,79 @@ static int aarch64_examine_first(struct target *target) &armv8->debug_base, &coreidx); if (retval != ERROR_OK) return retval; - LOG_DEBUG("Detected core %" PRId32 " dbgbase: %08" PRIx32, - coreidx, armv8->debug_base); + LOG_DEBUG("Detected core %" PRId32 " dbgbase: %08" PRIx32 + " apid: %08" PRIx32, coreidx, armv8->debug_base, apid); } else armv8->debug_base = target->dbgbase; - LOG_DEBUG("Target ctibase is 0x%x", target->ctibase); - if (target->ctibase == 0) - armv8->cti_base = target->ctibase = armv8->debug_base + 0x1000; - else - armv8->cti_base = target->ctibase; - retval = mem_ap_write_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_LOCKACCESS, 0xC5ACCE55); if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "oslock"); + LOG_DEBUG("LOCK debug access fail"); return retval; } - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x88, &cpuid); - LOG_DEBUG("0x88 = %x", cpuid); - - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x314, &cpuid); - LOG_DEBUG("0x314 = %x", cpuid); - - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + 0x310, &cpuid); - LOG_DEBUG("0x310 = %x", cpuid); - if (retval != ERROR_OK) - return retval; - - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_CPUID, &cpuid); + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_OSLAR, 0); if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "CPUID"); + LOG_DEBUG("Examine %s failed", "oslock"); return retval; } retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_CTYPR, &ctypr); + armv8->debug_base + CPUV8_DBG_MAINID0, &cpuid); if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "CTYPR"); + LOG_DEBUG("Examine %s failed", "CPUID"); return retval; } retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUDBG_TTYPR, &ttypr); + armv8->debug_base + CPUV8_DBG_MEMFEATURE0, &tmp0); + retval += mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_MEMFEATURE0 + 4, &tmp1); if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "TTYPR"); + LOG_DEBUG("Examine %s failed", "Memory Model Type"); return retval; } + ttypr |= tmp1; + ttypr = (ttypr << 32) | tmp0; retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + ID_AA64PFR0_EL1, &pfr); - if (retval != ERROR_OK) { - LOG_DEBUG("Examine %s failed", "ID_AA64DFR0_EL1"); - return retval; - } - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + ID_AA64DFR0_EL1, &debug); + armv8->debug_base + CPUV8_DBG_DBGFEATURE0, &tmp0); + retval += mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DBGFEATURE0 + 4, &tmp1); if (retval != ERROR_OK) { LOG_DEBUG("Examine %s failed", "ID_AA64DFR0_EL1"); return retval; } + debug |= tmp1; + debug = (debug << 32) | tmp0; LOG_DEBUG("cpuid = 0x%08" PRIx32, cpuid); - LOG_DEBUG("ctypr = 0x%08" PRIx32, ctypr); - LOG_DEBUG("ttypr = 0x%08" PRIx32, ttypr); - LOG_DEBUG("ID_AA64PFR0_EL1 = 0x%08" PRIx32, pfr); - LOG_DEBUG("ID_AA64DFR0_EL1 = 0x%08" PRIx32, debug); + LOG_DEBUG("ttypr = 0x%08" PRIx64, ttypr); + LOG_DEBUG("debug = 0x%08" PRIx64, debug); + + if (target->ctibase == 0) { + /* assume a v8 rom table layout */ + armv8->cti_base = target->ctibase = armv8->debug_base + 0x10000; + LOG_INFO("Target ctibase is not set, assuming 0x%0" PRIx32, target->ctibase); + } else + armv8->cti_base = target->ctibase; + + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->cti_base + CTI_UNLOCK , 0xC5ACCE55); + if (retval != ERROR_OK) + return retval; + armv8->arm.core_type = ARM_MODE_MON; - armv8->arm.core_state = ARM_STATE_AARCH64; retval = aarch64_dpm_setup(aarch64, debug); if (retval != ERROR_OK) return retval; /* Setup Breakpoint Register Pairs */ - aarch64->brp_num = ((debug >> 12) & 0x0F) + 1; - aarch64->brp_num_context = ((debug >> 28) & 0x0F) + 1; - - /* hack - no context bpt support yet */ - aarch64->brp_num_context = 0; - + aarch64->brp_num = (uint32_t)((debug >> 12) & 0x0F) + 1; + aarch64->brp_num_context = (uint32_t)((debug >> 28) & 0x0F) + 1; aarch64->brp_num_available = aarch64->brp_num; aarch64->brp_list = calloc(aarch64->brp_num, sizeof(struct aarch64_brp)); for (i = 0; i < aarch64->brp_num; i++) { -- cgit v1.1 From e8602889f9a9fce35eecc8109865fd9ae6d4d05e Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 15:31:29 +0200 Subject: aarch64: use correct A64 instructions for cache handling Replace A32 MCR with proper A64 MSR opcodes Change-Id: I64a60b17a58a26b199d2d1b2d5d91098e0c8cbd0 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 18 +++++++++--------- src/target/armv8.c | 3 +-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index ae2ecbf..d76da83 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2235,7 +2235,7 @@ static int aarch64_write_phys_memory(struct target *target, * wrong addresses will be invalidated! * * For both ICache and DCache, walk all cache lines in the - * address range. Cortex-A8 has fixed 64 byte line length. + * address range. Cortex-A has fixed 64 byte line length. * * REVISIT per ARMv7, these may trigger watchpoints ... */ @@ -2246,12 +2246,12 @@ static int aarch64_write_phys_memory(struct target *target, * with MVA to PoU * MCR p15, 0, r0, c7, c5, 1 */ - for (uint32_t cacheline = address; - cacheline < address + size * count; + for (uint32_t cacheline = 0; + cacheline < size * count; cacheline += 64) { retval = dpm->instr_write_data_r0(dpm, - ARMV4_5_MCR(15, 0, 0, 7, 5, 1), - cacheline); + ARMV8_MSR_GP(SYSTEM_ICIVAU, 0), + address + cacheline); if (retval != ERROR_OK) return retval; } @@ -2263,12 +2263,12 @@ static int aarch64_write_phys_memory(struct target *target, * with MVA to PoC * MCR p15, 0, r0, c7, c6, 1 */ - for (uint32_t cacheline = address; - cacheline < address + size * count; + for (uint32_t cacheline = 0; + cacheline < size * count; cacheline += 64) { retval = dpm->instr_write_data_r0(dpm, - ARMV4_5_MCR(15, 0, 0, 7, 6, 1), - cacheline); + ARMV8_MSR_GP(SYSTEM_DCCVAU, 0), + address + cacheline); if (retval != ERROR_OK) return retval; } diff --git a/src/target/armv8.c b/src/target/armv8.c index d6b7dc8..176c7ad 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -34,7 +34,6 @@ #include #include "armv8_opcodes.h" -#include "arm_opcodes.h" #include "target.h" #include "target_type.h" @@ -465,7 +464,7 @@ static int _armv8_flush_all_data(struct target *target) /* DCCISW */ /* LOG_INFO ("%d %d %x",c_way,c_index,value); */ retval = dpm->instr_write_data_r0(dpm, - ARMV4_5_MCR(15, 0, 0, 7, 14, 2), + ARMV8_MSR_GP(SYSTEM_DCCISW, 0), value); if (retval != ERROR_OK) goto done; -- cgit v1.1 From 4afa32ece148268a07313843c3f0a860c27f3309 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 15:34:21 +0200 Subject: aarch64: unify armv7-a and armv8 debug entry decoding Make DSCR_RUN_MODE() usable for armv8 and arm7 debug Change-Id: Ib3ba3000d5b6aa03e590f3ca4969e677474eb12c Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 8 ++------ src/target/arm_dpm.c | 16 ++++++---------- src/target/arm_dpm.h | 24 ++++++++++++------------ src/target/cortex_a.c | 6 +----- 4 files changed, 21 insertions(+), 33 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index d76da83..948a207 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -835,7 +835,7 @@ static int aarch64_poll(struct target *target) return retval; aarch64->cpudbg_dscr = dscr; - if (DSCR_RUN_MODE(dscr) == (DSCR_CORE_HALTED | DSCR_CORE_RESTARTED)) { + if (DSCR_RUN_MODE(dscr) == 0x3) { if (prev_target_state != TARGET_HALTED) { /* We have a halting debug event */ LOG_DEBUG("Target halted"); @@ -870,12 +870,8 @@ static int aarch64_poll(struct target *target) TARGET_EVENT_DEBUG_HALTED); } } - } else if (DSCR_RUN_MODE(dscr) == DSCR_CORE_RESTARTED) + } else target->state = TARGET_RUNNING; - else { - LOG_DEBUG("Unknown target state dscr = 0x%08" PRIx32, dscr); - target->state = TARGET_UNKNOWN; - } return retval; } diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index 00ebeba..f15bff7 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -930,20 +930,16 @@ void arm_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr) /* Examine debug reason */ switch (DSCR_ENTRY(dscr)) { - case 6: /* Data abort (v6 only) */ - case 7: /* Prefetch abort (v6 only) */ - /* FALL THROUGH -- assume a v6 core in abort mode */ - case 0: /* HALT request from debugger */ - case 4: /* EDBGRQ */ + case DSCR_ENTRY_HALT_REQ: /* HALT request from debugger */ + case DSCR_ENTRY_EXT_DBG_REQ: /* EDBGRQ */ target->debug_reason = DBG_REASON_DBGRQ; break; - case 1: /* HW breakpoint */ - case 3: /* SW BKPT */ - case 5: /* vector catch */ + case DSCR_ENTRY_BREAKPOINT: /* HW breakpoint */ + case DSCR_ENTRY_BKPT_INSTR: /* vector catch */ target->debug_reason = DBG_REASON_BREAKPOINT; break; - case 2: /* asynch watchpoint */ - case 10:/* precise watchpoint */ + case DSCR_ENTRY_IMPRECISE_WATCHPT: /* asynch watchpoint */ + case DSCR_ENTRY_PRECISE_WATCHPT:/* precise watchpoint */ target->debug_reason = DBG_REASON_WATCHPOINT; break; default: diff --git a/src/target/arm_dpm.h b/src/target/arm_dpm.h index 27badf4..63467d5 100644 --- a/src/target/arm_dpm.h +++ b/src/target/arm_dpm.h @@ -186,21 +186,21 @@ void arm_dpm_report_wfar(struct arm_dpm *, uint32_t wfar); #define DSCR_DTR_TX_FULL (0x1 << 29) #define DSCR_DTR_RX_FULL (0x1 << 30) /* bit 31 is reserved */ -#define DSCR_ENTRY(dscr) (((dscr) >> 2) & 0xf) -#define DSCR_RUN_MODE(dscr) ((dscr) & (DSCR_CORE_HALTED | DSCR_CORE_RESTARTED)) +#define DSCR_ENTRY(dscr) ((dscr) & 0x3f) +#define DSCR_RUN_MODE(dscr) ((dscr) & 0x03) /* Methods of entry into debug mode */ -#define DSCR_ENTRY_HALT_REQ (0x0 << 2) -#define DSCR_ENTRY_BREAKPOINT (0x1 << 2) -#define DSCR_ENTRY_IMPRECISE_WATCHPT (0x2 << 2) -#define DSCR_ENTRY_BKPT_INSTR (0x3 << 2) -#define DSCR_ENTRY_EXT_DBG_REQ (0x4 << 2) -#define DSCR_ENTRY_VECT_CATCH (0x5 << 2) -#define DSCR_ENTRY_D_SIDE_ABORT (0x6 << 2) /* v6 only */ -#define DSCR_ENTRY_I_SIDE_ABORT (0x7 << 2) /* v6 only */ -#define DSCR_ENTRY_OS_UNLOCK (0x8 << 2) -#define DSCR_ENTRY_PRECISE_WATCHPT (0xA << 2) +#define DSCR_ENTRY_HALT_REQ (0x03) +#define DSCR_ENTRY_BREAKPOINT (0x07) +#define DSCR_ENTRY_IMPRECISE_WATCHPT (0x0B) +#define DSCR_ENTRY_BKPT_INSTR (0x0F) +#define DSCR_ENTRY_EXT_DBG_REQ (0x13) +#define DSCR_ENTRY_VECT_CATCH (0x17) +#define DSCR_ENTRY_D_SIDE_ABORT (0x1B) /* v6 only */ +#define DSCR_ENTRY_I_SIDE_ABORT (0x1F) /* v6 only */ +#define DSCR_ENTRY_OS_UNLOCK (0x23) +#define DSCR_ENTRY_PRECISE_WATCHPT (0x2B) /* DTR modes */ #define DSCR_EXT_DCC_NON_BLOCKING (0x0 << 20) diff --git a/src/target/cortex_a.c b/src/target/cortex_a.c index 1cf6656..5d90e34 100644 --- a/src/target/cortex_a.c +++ b/src/target/cortex_a.c @@ -879,12 +879,8 @@ static int cortex_a_poll(struct target *target) TARGET_EVENT_DEBUG_HALTED); } } - } else if (DSCR_RUN_MODE(dscr) == DSCR_CORE_RESTARTED) + } else target->state = TARGET_RUNNING; - else { - LOG_DEBUG("Unknown target state dscr = 0x%08" PRIx32, dscr); - target->state = TARGET_UNKNOWN; - } return retval; } -- cgit v1.1 From 56ab6ab1594e71b690ace9b813fb31b465693acb Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 15:36:09 +0200 Subject: aarch64: fix armv8_set_core_reg when destination is cpsr When armv8_set_core_reg is used to set the value of the CPSR, also update the internal architecture state. Change-Id: I5f6a2be6fde8d91ec3352d8ba23c4aa90eb02977 Signed-off-by: Matthias Welwarsky --- src/target/armv8.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 176c7ad..ad06796 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -845,14 +845,20 @@ static int armv8_set_core_reg(struct reg *reg, uint8_t *buf) { struct arm_reg *armv8_reg = reg->arch_info; struct target *target = armv8_reg->target; + struct arm *arm = target_to_arm(target); uint64_t value = buf_get_u64(buf, 0, 64); if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; - buf_set_u64(reg->value, 0, 64, value); + if (reg == arm->cpsr) { + armv8_set_cpsr(arm, (uint32_t)value); + } else { + buf_set_u64(reg->value, 0, 64, value); + reg->valid = 1; + } + reg->dirty = 1; - reg->valid = 1; return ERROR_OK; } -- cgit v1.1 From ae7f2094c95ad4195f9136f708d5b95b75874eed Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 1 Sep 2016 22:27:28 +0200 Subject: aarch64: remove references to armv7-r aarch64 target doesn't support the -r profile anyway. Change-Id: Iaa470ed9f95ea495ab1bafdf401f55a1ebcefddf Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 27 +++++++++------------------ src/target/armv8.h | 1 - 2 files changed, 9 insertions(+), 19 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 948a207..e215206 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2152,11 +2152,9 @@ static int aarch64_read_memory(struct target *target, target_addr_t address, size, count); /* determine if MMU was enabled on target stop */ - if (!armv8->is_armv7r) { - retval = aarch64_mmu(target, &mmu_enabled); - if (retval != ERROR_OK) - return retval; - } + retval = aarch64_mmu(target, &mmu_enabled); + if (retval != ERROR_OK) + return retval; if (armv8->memory_ap_available && (apsel == armv8->memory_ap->ap_num)) { if (mmu_enabled) { @@ -2209,16 +2207,13 @@ static int aarch64_write_phys_memory(struct target *target, } else { /* write memory through APB-AP */ - if (!armv8->is_armv7r) { - retval = aarch64_mmu_modify(target, 0); - if (retval != ERROR_OK) - return retval; - } + retval = aarch64_mmu_modify(target, 0); + if (retval != ERROR_OK) + return retval; return aarch64_write_apb_ap_memory(target, address, size, count, buffer); } } - /* REVISIT this op is generic ARMv7-A/R stuff */ if (retval == ERROR_OK && target->state == TARGET_HALTED) { struct arm_dpm *dpm = armv8->arm.dpm; @@ -2291,11 +2286,9 @@ static int aarch64_write_memory(struct target *target, target_addr_t address, "; count %" PRId32, address, size, count); /* determine if MMU was enabled on target stop */ - if (!armv8->is_armv7r) { - retval = aarch64_mmu(target, &mmu_enabled); - if (retval != ERROR_OK) - return retval; - } + retval = aarch64_mmu(target, &mmu_enabled); + if (retval != ERROR_OK) + return retval; if (armv8->memory_ap_available && (apsel == armv8->memory_ap->ap_num)) { LOG_DEBUG("Writing memory to address 0x%" TARGET_PRIxADDR "; size %" @@ -2580,8 +2573,6 @@ static int aarch64_target_create(struct target *target, Jim_Interp *interp) { struct aarch64_common *aarch64 = calloc(1, sizeof(struct aarch64_common)); - aarch64->armv8_common.is_armv7r = false; - return aarch64_init_arch_info(target, aarch64, target->tap); } diff --git a/src/target/armv8.h b/src/target/armv8.h index 884d39a..169bcb3 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -139,7 +139,6 @@ struct armv8_common { uint8_t multi_processor_system; uint8_t cluster_id; uint8_t cpu_id; - bool is_armv7r; /* armv8 aarch64 need below information for page translation */ uint8_t va_size; -- cgit v1.1 From 9cc8cfe1b82ee333bbc6ca29bbc94f4419c8cf83 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 15 Sep 2016 09:14:31 +0200 Subject: aarch64: fix stepping from address The step command optionally carries a resume address. In this case, stepping should start not at the current PC, but at the given address. Change-Id: Id5792a3745f470cf29efa90c63d65f33d36f6b25 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index e215206..ae7f5a1 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1264,7 +1264,7 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres return retval; target->debug_reason = DBG_REASON_SINGLESTEP; - retval = aarch64_resume(target, 1, address, 0, 0); + retval = aarch64_resume(target, current, address, 0, 0); if (retval != ERROR_OK) return retval; -- cgit v1.1 From 1826f0af1ca20ce3f8cc8cb0e41f66372a1922d8 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 15 Sep 2016 10:19:42 +0200 Subject: aarch64: remove code for AHB-AP support Reduce complexity of memory access functions, anyway there are no ARMv8 platforms that actually contain an AHB-AP at all. while at it, fix virt-to-phys function signatures to expect target_addr_t. Change-Id: I55a369686f42993988b6323e5a77f38de12530a9 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 202 +++++++-------------------------------------------- src/target/armv8.c | 4 +- src/target/armv8.h | 6 +- 3 files changed, 31 insertions(+), 181 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index ae7f5a1..8c085d5 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2113,26 +2113,16 @@ static int aarch64_read_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { - struct armv8_common *armv8 = target_to_armv8(target); int retval = ERROR_COMMAND_SYNTAX_ERROR; - struct adiv5_dap *swjdp = armv8->arm.dap; - uint8_t apsel = swjdp->apsel; LOG_DEBUG("Reading memory at real address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, address, size, count); if (count && buffer) { - - if (armv8->memory_ap_available && (apsel == armv8->memory_ap->ap_num)) { - - /* read memory through AHB-AP */ - retval = mem_ap_read_buf(armv8->memory_ap, buffer, size, count, address); - } else { - /* read memory through APB-AP */ - retval = aarch64_mmu_modify(target, 0); - if (retval != ERROR_OK) - return retval; - retval = aarch64_read_apb_ap_memory(target, address, size, count, buffer); - } + /* read memory through APB-AP */ + retval = aarch64_mmu_modify(target, 0); + if (retval != ERROR_OK) + return retval; + retval = aarch64_read_apb_ap_memory(target, address, size, count, buffer); } return retval; } @@ -2141,11 +2131,7 @@ static int aarch64_read_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer) { int mmu_enabled = 0; - target_addr_t virt, phys; int retval; - struct armv8_common *armv8 = target_to_armv8(target); - struct adiv5_dap *swjdp = armv8->arm.dap; - uint8_t apsel = swjdp->apsel; /* aarch64 handles unaligned memory access */ LOG_DEBUG("Reading memory at address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, address, @@ -2156,116 +2142,33 @@ static int aarch64_read_memory(struct target *target, target_addr_t address, if (retval != ERROR_OK) return retval; - if (armv8->memory_ap_available && (apsel == armv8->memory_ap->ap_num)) { - if (mmu_enabled) { - virt = address; - retval = aarch64_virt2phys(target, virt, &phys); - if (retval != ERROR_OK) - return retval; - - LOG_DEBUG("Reading at virtual address. Translating v:0x%" TARGET_PRIxADDR " to r:0x%" TARGET_PRIxADDR, - virt, phys); - address = phys; - } - retval = aarch64_read_phys_memory(target, address, size, count, - buffer); - } else { - if (mmu_enabled) { - retval = aarch64_check_address(target, address); - if (retval != ERROR_OK) - return retval; - /* enable MMU as we could have disabled it for phys - access */ - retval = aarch64_mmu_modify(target, 1); - if (retval != ERROR_OK) - return retval; - } - retval = aarch64_read_apb_ap_memory(target, address, size, - count, buffer); + if (mmu_enabled) { + retval = aarch64_check_address(target, address); + if (retval != ERROR_OK) + return retval; + /* enable MMU as we could have disabled it for phys access */ + retval = aarch64_mmu_modify(target, 1); + if (retval != ERROR_OK) + return retval; } - return retval; + return aarch64_read_apb_ap_memory(target, address, size, count, buffer); } static int aarch64_write_phys_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { - struct armv8_common *armv8 = target_to_armv8(target); - struct adiv5_dap *swjdp = armv8->arm.dap; int retval = ERROR_COMMAND_SYNTAX_ERROR; - uint8_t apsel = swjdp->apsel; LOG_DEBUG("Writing memory to real address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, address, size, count); if (count && buffer) { - - if (armv8->memory_ap_available && (apsel == armv8->memory_ap->ap_num)) { - - /* write memory through AHB-AP */ - retval = mem_ap_write_buf(armv8->memory_ap, buffer, size, count, address); - } else { - - /* write memory through APB-AP */ - retval = aarch64_mmu_modify(target, 0); - if (retval != ERROR_OK) - return retval; - return aarch64_write_apb_ap_memory(target, address, size, count, buffer); - } - } - - /* REVISIT this op is generic ARMv7-A/R stuff */ - if (retval == ERROR_OK && target->state == TARGET_HALTED) { - struct arm_dpm *dpm = armv8->arm.dpm; - - retval = dpm->prepare(dpm); + /* write memory through APB-AP */ + retval = aarch64_mmu_modify(target, 0); if (retval != ERROR_OK) return retval; - - /* The Cache handling will NOT work with MMU active, the - * wrong addresses will be invalidated! - * - * For both ICache and DCache, walk all cache lines in the - * address range. Cortex-A has fixed 64 byte line length. - * - * REVISIT per ARMv7, these may trigger watchpoints ... - */ - - /* invalidate I-Cache */ - if (armv8->armv8_mmu.armv8_cache.i_cache_enabled) { - /* ICIMVAU - Invalidate Cache single entry - * with MVA to PoU - * MCR p15, 0, r0, c7, c5, 1 - */ - for (uint32_t cacheline = 0; - cacheline < size * count; - cacheline += 64) { - retval = dpm->instr_write_data_r0(dpm, - ARMV8_MSR_GP(SYSTEM_ICIVAU, 0), - address + cacheline); - if (retval != ERROR_OK) - return retval; - } - } - - /* invalidate D-Cache */ - if (armv8->armv8_mmu.armv8_cache.d_u_cache_enabled) { - /* DCIMVAC - Invalidate data Cache line - * with MVA to PoC - * MCR p15, 0, r0, c7, c6, 1 - */ - for (uint32_t cacheline = 0; - cacheline < size * count; - cacheline += 64) { - retval = dpm->instr_write_data_r0(dpm, - ARMV8_MSR_GP(SYSTEM_DCCVAU, 0), - address + cacheline); - if (retval != ERROR_OK) - return retval; - } - } - - /* (void) */ dpm->finish(dpm); + return aarch64_write_apb_ap_memory(target, address, size, count, buffer); } return retval; @@ -2275,11 +2178,7 @@ static int aarch64_write_memory(struct target *target, target_addr_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { int mmu_enabled = 0; - target_addr_t virt, phys; int retval; - struct armv8_common *armv8 = target_to_armv8(target); - struct adiv5_dap *swjdp = armv8->arm.dap; - uint8_t apsel = swjdp->apsel; /* aarch64 handles unaligned memory access */ LOG_DEBUG("Writing memory at address 0x%" TARGET_PRIxADDR "; size %" PRId32 @@ -2290,34 +2189,16 @@ static int aarch64_write_memory(struct target *target, target_addr_t address, if (retval != ERROR_OK) return retval; - if (armv8->memory_ap_available && (apsel == armv8->memory_ap->ap_num)) { - LOG_DEBUG("Writing memory to address 0x%" TARGET_PRIxADDR "; size %" - PRId32 "; count %" PRId32, address, size, count); - if (mmu_enabled) { - virt = address; - retval = aarch64_virt2phys(target, virt, &phys); - if (retval != ERROR_OK) - return retval; - - LOG_DEBUG("Writing to virtual address. Translating v:0x%" - TARGET_PRIxADDR " to r:0x%" TARGET_PRIxADDR, virt, phys); - address = phys; - } - retval = aarch64_write_phys_memory(target, address, size, - count, buffer); - } else { - if (mmu_enabled) { - retval = aarch64_check_address(target, address); - if (retval != ERROR_OK) - return retval; - /* enable MMU as we could have disabled it for phys access */ - retval = aarch64_mmu_modify(target, 1); - if (retval != ERROR_OK) - return retval; - } - retval = aarch64_write_apb_ap_memory(target, address, size, count, buffer); + if (mmu_enabled) { + retval = aarch64_check_address(target, address); + if (retval != ERROR_OK) + return retval; + /* enable MMU as we could have disabled it for phys access */ + retval = aarch64_mmu_modify(target, 1); + if (retval != ERROR_OK) + return retval; } - return retval; + return aarch64_write_apb_ap_memory(target, address, size, count, buffer); } static int aarch64_handle_target_request(void *priv) @@ -2386,20 +2267,6 @@ static int aarch64_examine_first(struct target *target) armv8->debug_ap->memaccess_tck = 80; - /* Search for the AHB-AB */ - armv8->memory_ap_available = false; - retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv8->memory_ap); - if (retval == ERROR_OK) { - retval = mem_ap_init(armv8->memory_ap); - if (retval == ERROR_OK) - armv8->memory_ap_available = true; - } - if (retval != ERROR_OK) { - /* AHB-AP not found or unavailable - use the CPU */ - LOG_DEBUG("No AHB-AP available for memory access"); - } - - if (!target->dbgbase_set) { uint32_t dbgbase; /* Get ROM Table base */ @@ -2590,22 +2457,7 @@ static int aarch64_mmu(struct target *target, int *enabled) static int aarch64_virt2phys(struct target *target, target_addr_t virt, target_addr_t *phys) { - int retval = ERROR_FAIL; - struct armv8_common *armv8 = target_to_armv8(target); - struct adiv5_dap *swjdp = armv8->arm.dap; - uint8_t apsel = swjdp->apsel; - if (armv8->memory_ap_available && (apsel == armv8->memory_ap->ap_num)) { - uint32_t ret; - retval = armv8_mmu_translate_va(target, - virt, &ret); - if (retval != ERROR_OK) - goto done; - *phys = ret; - } else { - LOG_ERROR("AAR64 processor not support translate va to pa"); - } -done: - return retval; + return armv8_mmu_translate_va(target, virt, phys); } COMMAND_HANDLER(aarch64_handle_cache_info_command) diff --git a/src/target/armv8.c b/src/target/armv8.c index ad06796..148ab6d 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -382,7 +382,7 @@ done: return retval; } -static int armv8_4K_translate(struct target *target, uint32_t va, uint32_t *val) +static int armv8_4K_translate(struct target *target, target_addr_t va, target_addr_t *val) { LOG_ERROR("4K page Address translation need to add"); return ERROR_FAIL; @@ -390,7 +390,7 @@ static int armv8_4K_translate(struct target *target, uint32_t va, uint32_t *val /* method adapted to cortex A : reused arm v4 v5 method*/ -int armv8_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val) +int armv8_mmu_translate_va(struct target *target, target_addr_t va, target_addr_t *val) { int retval = ERROR_FAIL; struct armv8_common *armv8 = target_to_armv8(target); diff --git a/src/target/armv8.h b/src/target/armv8.h index 169bcb3..f077045 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -131,10 +131,8 @@ struct armv8_common { struct arm_dpm dpm; uint32_t debug_base; uint32_t cti_base; - struct adiv5_ap *debug_ap; - struct adiv5_ap *memory_ap; - bool memory_ap_available; + /* mdir */ uint8_t multi_processor_system; uint8_t cluster_id; @@ -245,7 +243,7 @@ int armv8_identify_cache(struct target *target); int armv8_init_arch_info(struct target *target, struct armv8_common *armv8); int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, target_addr_t *val, int meminfo); -int armv8_mmu_translate_va(struct target *target, uint32_t va, uint32_t *val); +int armv8_mmu_translate_va(struct target *target, target_addr_t va, target_addr_t *val); int armv8_handle_cache_info_command(struct command_context *cmd_ctx, struct armv8_cache_common *armv8_cache); -- cgit v1.1 From 18ab54b82a4b5660bcd93f2481bd24e73c6a1ce6 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 15 Sep 2016 17:17:05 +0200 Subject: aarch64: fix duplication of register cache Change-Id: Ib4422e39171f19eea3f0b5a86f9dccdbb7044265 Signed-off-by: Matthias Welwarsky --- src/target/armv8_dpm.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index dc6682b..493ccca 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -916,9 +916,11 @@ int armv8_dpm_setup(struct arm_dpm *dpm) arm->read_core_reg = armv8_dpm_read_core_reg; arm->write_core_reg = armv8_dpm_write_core_reg; - cache = armv8_build_reg_cache(target); - if (!cache) - return ERROR_FAIL; + if (arm->core_cache == NULL) { + cache = armv8_build_reg_cache(target); + if (!cache) + return ERROR_FAIL; + } /* coprocessor access setup */ arm->mrc = dpmv8_mrc; -- cgit v1.1 From 11bc04e00c506346b8f35ba8b71d0598ef547f86 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 10:12:00 +0200 Subject: aarch64: fix register list According to gdb documentation, a register "cpsr" is expected if aarch64 features are announced. Also, the value buffer must be capable of holding a 64bit value (8 byte, not 4) Change-Id: I7aec4e84fa87eadb26797acd0d16c988b9852616 Signed-off-by: Matthias Welwarsky --- src/target/armv8.c | 66 +++++++++++++++++++++++++++--------------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 148ab6d..c351dfd 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -785,42 +785,42 @@ static const struct { const char *group; const char *feature; } armv8_regs[] = { - { ARMV8_R0, "x0", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R1, "x1", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R2, "x2", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R3, "x3", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R4, "x4", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R5, "x5", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R6, "x6", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R7, "x7", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R8, "x8", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R9, "x9", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R10, "x10", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R11, "x11", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R12, "x12", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R13, "x13", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R14, "x14", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R15, "x15", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R16, "x16", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R17, "x17", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R18, "x18", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R19, "x19", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R20, "x20", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R21, "x21", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R22, "x22", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R23, "x23", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R24, "x24", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R25, "x25", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R26, "x26", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R27, "x27", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R28, "x28", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R29, "x29", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R30, "x30", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R0, "x0", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R1, "x1", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R2, "x2", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R3, "x3", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R4, "x4", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R5, "x5", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R6, "x6", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R7, "x7", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R8, "x8", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R9, "x9", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R10, "x10", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R11, "x11", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R12, "x12", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R13, "x13", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R14, "x14", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R15, "x15", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R16, "x16", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R17, "x17", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R18, "x18", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R19, "x19", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R20, "x20", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R21, "x21", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R22, "x22", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R23, "x23", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R24, "x24", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R25, "x25", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R26, "x26", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R27, "x27", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R28, "x28", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R29, "x29", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R30, "x30", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, { ARMV8_R31, "sp", 64, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.aarch64.core" }, { ARMV8_PC, "pc", 64, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_xPSR, "CPSR", 64, REG_TYPE_INT, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_xPSR, "CPSR", 32, REG_TYPE_UINT32, "general", "org.gnu.gdb.aarch64.core" }, }; #define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs) @@ -895,7 +895,7 @@ struct reg_cache *armv8_build_reg_cache(struct target *target) reg_list[i].name = armv8_regs[i].name; reg_list[i].size = armv8_regs[i].bits; - reg_list[i].value = calloc(1, 4); + reg_list[i].value = calloc(1, 8); reg_list[i].dirty = 0; reg_list[i].valid = 0; reg_list[i].type = &armv8_reg_type; -- cgit v1.1 From df7069af556bd9601ec293a87e8465fb713b3a06 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 12:55:17 +0200 Subject: aarch64: report the correct reason for halting after singlestep Don't report breakpoint as debug reason when halt is due to a single-step event. Change-Id: Ie6c3ca1e5427c73eb726a038301b6a29a47d1217 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 22 ++++++++++------------ src/target/armv8_dpm.c | 5 ++++- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 8c085d5..b1534e3 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1246,7 +1246,7 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres { struct armv8_common *armv8 = target_to_armv8(target); int retval; - uint32_t tmp; + uint32_t edecr; if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); @@ -1254,25 +1254,26 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres } retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_EDECR, &tmp); + armv8->debug_base + CPUV8_DBG_EDECR, &edecr); if (retval != ERROR_OK) return retval; + /* make sure EDECR.SS is not set when restoring the register */ + edecr &= ~0x4; + + /* set EDECR.SS to enter hardware step mode */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_EDECR, (tmp|0x4)); + armv8->debug_base + CPUV8_DBG_EDECR, (edecr|0x4)); if (retval != ERROR_OK) return retval; - target->debug_reason = DBG_REASON_SINGLESTEP; + /* resume the target */ retval = aarch64_resume(target, current, address, 0, 0); if (retval != ERROR_OK) return retval; long long then = timeval_ms(); while (target->state != TARGET_HALTED) { - mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_EDESR, &tmp); - LOG_DEBUG("DESR = %#x", tmp); retval = aarch64_poll(target); if (retval != ERROR_OK) return retval; @@ -1282,15 +1283,12 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres } } + /* restore EDECR */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_EDECR, (tmp&(~0x4))); + armv8->debug_base + CPUV8_DBG_EDECR, edecr); if (retval != ERROR_OK) return retval; - target_call_event_callbacks(target, TARGET_EVENT_HALTED); - if (target->state == TARGET_HALTED) - LOG_DEBUG("target stepped"); - return ERROR_OK; } diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index 493ccca..08b1a20 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -874,11 +874,14 @@ void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr) target->debug_reason = DBG_REASON_DBGRQ; break; case DSCRV8_ENTRY_HALT_STEP_EXECLU: /* HALT step */ + case DSCRV8_ENTRY_HALT_STEP_NORMAL: /* Halt step*/ + case DSCRV8_ENTRY_HALT_STEP: + target->debug_reason = DBG_REASON_SINGLESTEP; + break; case DSCRV8_ENTRY_BKPT: /* SW BKPT */ case DSCRV8_ENTRY_RESET_CATCH: /* Reset catch */ case DSCRV8_ENTRY_OS_UNLOCK: /*OS unlock catch*/ case DSCRV8_ENTRY_EXCEPTION_CATCH: /*exception catch*/ - case DSCRV8_ENTRY_HALT_STEP_NORMAL: /* Halt step*/ case DSCRV8_ENTRY_SW_ACCESS_DBG: /*SW access dbg register*/ target->debug_reason = DBG_REASON_BREAKPOINT; break; -- cgit v1.1 From 4246fac240eb28e5a28112b71fc0b5f911e6c922 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 16 Sep 2016 13:46:08 +0200 Subject: aarch64: use correct instruction for software breakpoints External debuggers need to use HLT, not BRK. HLT generates a halting debug event while BRK generates a debug exception for self-hosted debugging. Change-Id: I24024b83668107f73a14cc75d951134917269e5c Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 2 +- src/target/armv8_dpm.c | 4 ++-- src/target/armv8_opcodes.h | 3 +++ 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index b1534e3..d38e042 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1369,7 +1369,7 @@ static int aarch64_set_breakpoint(struct target *target, } else if (breakpoint->type == BKPT_SOFT) { uint8_t code[4]; - buf_set_u32(code, 0, 32, ARMV8_BKPT(0x11)); + buf_set_u32(code, 0, 32, ARMV8_HLT(0x11)); retval = target_read_memory(target, breakpoint->address & 0xFFFFFFFFFFFFFFFE, breakpoint->length, 1, diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index 08b1a20..8c0d45a 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -869,7 +869,6 @@ void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr) /* Examine debug reason */ switch (DSCR_ENTRY(dscr)) { /* FALL THROUGH -- assume a v6 core in abort mode */ - case DSCRV8_ENTRY_HLT: /* HALT request from debugger */ case DSCRV8_ENTRY_EXT_DEBUG: /* EDBGRQ */ target->debug_reason = DBG_REASON_DBGRQ; break; @@ -878,7 +877,8 @@ void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr) case DSCRV8_ENTRY_HALT_STEP: target->debug_reason = DBG_REASON_SINGLESTEP; break; - case DSCRV8_ENTRY_BKPT: /* SW BKPT */ + case DSCRV8_ENTRY_HLT: /* HLT instruction (software breakpoint) */ + case DSCRV8_ENTRY_BKPT: /* SW BKPT (?) */ case DSCRV8_ENTRY_RESET_CATCH: /* Reset catch */ case DSCRV8_ENTRY_OS_UNLOCK: /*OS unlock catch*/ case DSCRV8_ENTRY_EXCEPTION_CATCH: /*exception catch*/ diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index 4f696db..a1fb5d4 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -116,7 +116,10 @@ /* ARM V8 Move immediate to process state field. */ #define ARMV8_MSR_IM(Op1, CRm, Op2) \ (0xd500401f | ((Op1) << 16) | ((CRm) << 8) | ((Op2) << 5)) + #define ARMV8_BKPT(Im) (0xD4200000 | ((Im & 0xffff) << 5)) +#define ARMV8_HLT(Im) (0x0D4400000 | ((Im & 0xffff) << 5)) + #define ARMV8_MOVFSP_64(Rt) ((1 << 31) | 0x11000000 | (0x1f << 5) | (Rt)) #define ARMV8_MOVTSP_64(Rt) ((1 << 31) | 0x11000000 | (Rt << 5) | (0x1F)) #define ARMV8_MOVFSP_32(Rt) (0x11000000 | (0x1f << 5) | (Rt)) -- cgit v1.1 From b430d0a1520903213e0796e9fcbc5ab180f1fbe8 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Mon, 19 Sep 2016 17:04:03 +0200 Subject: aarch64: disable interrupts when stepping [WIP] On live hardware, interrupts will happen while the core is held for stepping. The next step will most of the time execute an interrupt service instead of the next line of code, which is not what you expect. Disable interrupts through DSCR before resuming for a step, and re-enable them again after the step happened. This should be made configurable, like on cortex_a target. Change-Id: I94d8ffb58cf7579dedb66bc756b7eb6828b6e8e4 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index d38e042..88f9b5a 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1241,6 +1241,28 @@ static int aarch64_post_debug_entry(struct target *target) return ERROR_OK; } +static int aarch64_set_dscr_bits(struct target *target, unsigned long bit_mask, unsigned long value) +{ + struct armv8_common *armv8 = target_to_armv8(target); + uint32_t dscr; + + /* Read DSCR */ + int retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); + if (ERROR_OK != retval) + return retval; + + /* clear bitfield */ + dscr &= ~bit_mask; + /* put new value */ + dscr |= value & bit_mask; + + /* write new DSCR */ + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DSCR, dscr); + return retval; +} + static int aarch64_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { @@ -1267,6 +1289,11 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres if (retval != ERROR_OK) return retval; + /* disable interrupts while stepping */ + retval = aarch64_set_dscr_bits(target, 0x3 << 22, 0x3 << 22); + if (retval != ERROR_OK) + return ERROR_OK; + /* resume the target */ retval = aarch64_resume(target, current, address, 0, 0); if (retval != ERROR_OK) @@ -1289,6 +1316,11 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres if (retval != ERROR_OK) return retval; + /* restore interrupts */ + retval = aarch64_set_dscr_bits(target, 0x3 << 22, 0); + if (retval != ERROR_OK) + return ERROR_OK; + return ERROR_OK; } -- cgit v1.1 From e17d1d4dc870155010422095272d8a6c16435451 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Tue, 20 Sep 2016 11:16:30 +0200 Subject: aarch64: add cache handling functions For now only D-Cache flush (Clean&Invalidate) and I-Cache invalidate are implemented. That's enough for software breakpoints. Change-Id: I8e96d645a230b51e3490403f4564e59ba6a76cf3 Signed-off-by: Matthias Welwarsky --- src/target/Makefile.am | 4 +- src/target/armv8_cache.c | 122 +++++++++++++++++++++++++++++++++++++++++++++ src/target/armv8_cache.h | 26 ++++++++++ src/target/armv8_opcodes.h | 2 + 4 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 src/target/armv8_cache.c create mode 100644 src/target/armv8_cache.h diff --git a/src/target/Makefile.am b/src/target/Makefile.am index c20ac0f..0021f44 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -76,7 +76,8 @@ ARMV7_SRC = \ ARMV8_SRC = \ %D%/armv8_dpm.c \ %D%/aarch64.c \ - %D%/armv8.c + %D%/armv8.c \ + %D%/armv8_cache.c ARM_DEBUG_SRC = \ %D%/arm_dpm.c \ @@ -158,6 +159,7 @@ INTEL_IA32_SRC = \ %D%/armv8.h \ %D%/armv8_dpm.h \ %D%/armv8_opcodes.h \ + %D%/armv8_cache.h \ %D%/avrt.h \ %D%/dsp563xx.h \ %D%/dsp563xx_once.h \ diff --git a/src/target/armv8_cache.c b/src/target/armv8_cache.c new file mode 100644 index 0000000..fb18804 --- /dev/null +++ b/src/target/armv8_cache.c @@ -0,0 +1,122 @@ +/*************************************************************************** + * Copyright (C) 2016 by Matthias Welwarsky * + * matthias.welwarsky@sysgo.com * + * * + * 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, see . * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "armv8_cache.h" +#include "armv8_dpm.h" +#include "armv8_opcodes.h" + +static int armv8_d_cache_sanity_check(struct armv8_common *armv8) +{ + struct armv8_cache_common *armv8_cache = &armv8->armv8_mmu.armv8_cache; + + if (armv8_cache->d_u_cache_enabled) + return ERROR_OK; + + return ERROR_TARGET_INVALID; +} + +static int armv8_i_cache_sanity_check(struct armv8_common *armv8) +{ + struct armv8_cache_common *armv8_cache = &armv8->armv8_mmu.armv8_cache; + + if (armv8_cache->i_cache_enabled) + return ERROR_OK; + + return ERROR_TARGET_INVALID; +} + +int armv8_cache_d_inner_flush_virt(struct armv8_common *armv8, target_addr_t va, size_t size) +{ + struct arm_dpm *dpm = armv8->arm.dpm; + struct armv8_cache_common *armv8_cache = &armv8->armv8_mmu.armv8_cache; + uint64_t linelen = armv8_cache->d_u_size.linelen; + target_addr_t va_line, va_end; + int retval; + + retval = armv8_d_cache_sanity_check(armv8); + if (retval != ERROR_OK) + return retval; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + + va_line = va & (-linelen); + va_end = va + size; + + while (va_line < va_end) { + /* DC CIVAC */ + /* Aarch32: DCCIMVAC: ARMV4_5_MCR(15, 0, 0, 7, 14, 1) */ + retval = dpm->instr_write_data_r0_64(dpm, + ARMV8_SYS(SYSTEM_DCCIVAC, 0), va_line); + if (retval != ERROR_OK) + goto done; + va_line += linelen; + } + + dpm->finish(dpm); + return retval; + +done: + LOG_ERROR("d-cache invalidate failed"); + dpm->finish(dpm); + + return retval; +} + +int armv8_cache_i_inner_inval_virt(struct armv8_common *armv8, target_addr_t va, size_t size) +{ + struct arm_dpm *dpm = armv8->arm.dpm; + struct armv8_cache_common *armv8_cache = &armv8->armv8_mmu.armv8_cache; + uint64_t linelen = armv8_cache->i_size.linelen; + target_addr_t va_line, va_end; + int retval; + + retval = armv8_i_cache_sanity_check(armv8); + if (retval != ERROR_OK) + return retval; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + + va_line = va & (-linelen); + va_end = va + size; + + while (va_line < va_end) { + /* IC IVAU - Invalidate instruction cache by VA to PoU. */ + retval = dpm->instr_write_data_r0_64(dpm, + ARMV8_SYS(SYSTEM_ICIVAU, 0), va_line); + if (retval != ERROR_OK) + goto done; + va_line += linelen; + } + + dpm->finish(dpm); + return retval; + +done: + LOG_ERROR("d-cache invalidate failed"); + dpm->finish(dpm); + + return retval; +} diff --git a/src/target/armv8_cache.h b/src/target/armv8_cache.h new file mode 100644 index 0000000..fa46e16 --- /dev/null +++ b/src/target/armv8_cache.h @@ -0,0 +1,26 @@ +/*************************************************************************** + * Copyright (C) 2016 by Matthias Welwarsky * + * matthias.welwarsky@sysgo.com * + * * + * 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, see . * + ***************************************************************************/ +#ifndef OPENOCD_TARGET_ARMV8_CACHE_H_ +#define OPENOCD_TARGET_ARMV8_CACHE_H_ + +#include "armv8.h" + +extern int armv8_cache_d_inner_flush_virt(struct armv8_common *armv8, target_addr_t va, size_t size); +extern int armv8_cache_i_inner_inval_virt(struct armv8_common *armv8, target_addr_t va, size_t size); + +#endif /* OPENOCD_TARGET_ARMV8_CACHE_H_ */ diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index a1fb5d4..89d7440 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -82,6 +82,7 @@ #define SYSTEM_DCCSW 0b0100001111010010 #define SYSTEM_ICIVAU 0b0101101110101001 #define SYSTEM_DCCVAU 0b0101101111011001 +#define SYSTEM_DCCIVAC 0b0101101111110001 #define SYSTEM_MPIDR 0b1100000000000101 @@ -125,5 +126,6 @@ #define ARMV8_MOVFSP_32(Rt) (0x11000000 | (0x1f << 5) | (Rt)) #define ARMV8_MOVTSP_32(Rt) (0x11000000 | (Rt << 5) | (0x1F)) +#define ARMV8_SYS(System, Rt) (0xD5080000 | ((System) << 5) | Rt) #endif /* __ARM_OPCODES_H */ -- cgit v1.1 From c6ed75fb0e61cb710c91c935449330ac7b441799 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Tue, 20 Sep 2016 11:29:39 +0200 Subject: aarch64: add cache handling when setting/deleting soft breakpoints Flush D-Cache before, flush D-Cache and invalidate I-Cache after modifying the breakpoint location. Change-Id: Id2e2f4f2545c062de7e27275f66857357496d4ae Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 88f9b5a..1eb4d82 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -27,6 +27,7 @@ #include "target_request.h" #include "target_type.h" #include "armv8_opcodes.h" +#include "armv8_cache.h" #include static int aarch64_poll(struct target *target); @@ -1401,6 +1402,7 @@ static int aarch64_set_breakpoint(struct target *target, } else if (breakpoint->type == BKPT_SOFT) { uint8_t code[4]; + buf_set_u32(code, 0, 32, ARMV8_HLT(0x11)); retval = target_read_memory(target, breakpoint->address & 0xFFFFFFFFFFFFFFFE, @@ -1408,11 +1410,25 @@ static int aarch64_set_breakpoint(struct target *target, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; + + armv8_cache_d_inner_flush_virt(armv8, + breakpoint->address & 0xFFFFFFFFFFFFFFFE, + breakpoint->length); + retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFFFFFFFFFE, breakpoint->length, 1, code); if (retval != ERROR_OK) return retval; + + armv8_cache_d_inner_flush_virt(armv8, + breakpoint->address & 0xFFFFFFFFFFFFFFFE, + breakpoint->length); + + armv8_cache_i_inner_inval_virt(armv8, + breakpoint->address & 0xFFFFFFFFFFFFFFFE, + breakpoint->length); + breakpoint->set = 0x11; /* Any nice value but 0 */ } @@ -1668,6 +1684,11 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br } } else { /* restore original instruction (kept in target endianness) */ + + armv8_cache_d_inner_flush_virt(armv8, + breakpoint->address & 0xFFFFFFFFFFFFFFFE, + breakpoint->length); + if (breakpoint->length == 4) { retval = target_write_memory(target, breakpoint->address & 0xFFFFFFFFFFFFFFFE, @@ -1681,6 +1702,14 @@ static int aarch64_unset_breakpoint(struct target *target, struct breakpoint *br if (retval != ERROR_OK) return retval; } + + armv8_cache_d_inner_flush_virt(armv8, + breakpoint->address & 0xFFFFFFFFFFFFFFFE, + breakpoint->length); + + armv8_cache_i_inner_inval_virt(armv8, + breakpoint->address & 0xFFFFFFFFFFFFFFFE, + breakpoint->length); } breakpoint->set = 0; -- cgit v1.1 From 6b392dea66bbf72fef74fa8262385157a24f3750 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 29 Sep 2016 14:06:42 +0200 Subject: aarch64: update smp halt and resume to better facilitate CTI Set up CTI so that halt and resume requests get routed to all PEs in the SMP group. Change-Id: Ie92cfd3fe54632e5fdc049a6bf5b24b99451a8c9 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 150 ++++++++++++++++++++++++++------------------------- src/target/armv8.h | 5 ++ 2 files changed, 82 insertions(+), 73 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 1eb4d82..8d74dbd 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -212,19 +212,6 @@ static int aarch64_init_debug_access(struct target *target) LOG_DEBUG(" "); - /* Unlocking the debug registers for modification - * The debugport might be uninitialised so try twice */ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_LOCKACCESS, 0xC5ACCE55); - if (retval != ERROR_OK) { - /* try again */ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_LOCKACCESS, 0xC5ACCE55); - if (retval == ERROR_OK) - LOG_USER("Locking debug access failed on first, but succeeded on second try."); - } - if (retval != ERROR_OK) - return retval; /* Clear Sticky Power Down status Bit in PRSR to enable access to the registers in the Core Power Domain */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, @@ -232,7 +219,30 @@ static int aarch64_init_debug_access(struct target *target) if (retval != ERROR_OK) return retval; - /* Enabling of instruction execution in debug mode is done in debug_entry code */ + /* + * Static CTI configuration: + * Channel 0 -> trigger outputs HALT request to PE + * Channel 1 -> trigger outputs Resume request to PE + * Gate all channel trigger events from entering the CTM + */ + + /* Enable CTI */ + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->cti_base + CTI_CTR, 1); + /* By default, gate all channel triggers to and from the CTM */ + if (retval == ERROR_OK) + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->cti_base + CTI_GATE, 0); + /* output halt requests to PE on channel 0 trigger */ + if (retval == ERROR_OK) + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->cti_base + CTI_OUTEN0, CTI_CHNL(0)); + /* output restart requests to PE on channel 1 trigger */ + if (retval == ERROR_OK) + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->cti_base + CTI_OUTEN1, CTI_CHNL(1)); + if (retval != ERROR_OK) + return retval; /* Resync breakpoint registers */ @@ -783,16 +793,27 @@ static int aarch64_halt(struct target *target); static int aarch64_halt_smp(struct target *target) { - int retval = 0; - struct target_list *head; - struct target *curr; - head = target->head; + int retval = ERROR_OK; + struct target_list *head = target->head; + while (head != (struct target_list *)NULL) { - curr = head->target; - if ((curr != target) && (curr->state != TARGET_HALTED)) - retval += aarch64_halt(curr); + struct target *curr = head->target; + struct armv8_common *armv8 = target_to_armv8(curr); + + /* open the gate for channel 0 to let HALT requests pass to the CTM */ + if (curr->smp) + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->cti_base + CTI_GATE, CTI_CHNL(0)); + if (retval != ERROR_OK) + break; + head = head->next; } + + /* halt the target PE */ + if (retval == ERROR_OK) + retval = aarch64_halt(target); + return retval; } @@ -883,51 +904,23 @@ static int aarch64_halt(struct target *target) uint32_t dscr; struct armv8_common *armv8 = target_to_armv8(target); - /* enable CTI*/ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_CTR, 1); - if (retval != ERROR_OK) - return retval; - - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_GATE, 3); - if (retval != ERROR_OK) - return retval; - - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_OUTEN0, 1); - if (retval != ERROR_OK) - return retval; - - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_OUTEN1, 2); - if (retval != ERROR_OK) - return retval; - /* * add HDE in halting debug mode */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DSCR, &dscr); + if (retval == ERROR_OK) + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DSCR, dscr | DSCR_HDE); if (retval != ERROR_OK) return retval; + /* trigger an event on channel 0, this outputs a halt request to the PE */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, dscr | DSCR_HDE); - if (retval != ERROR_OK) - return retval; - - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_APPPULSE, 1); - if (retval != ERROR_OK) - return retval; - - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_INACK, 1); + armv8->cti_base + CTI_APPPULSE, CTI_CHNL(0)); if (retval != ERROR_OK) return retval; - long long then = timeval_ms(); for (;; ) { retval = mem_ap_read_atomic_u32(armv8->debug_ap, @@ -1023,7 +1016,7 @@ static int aarch64_internal_restore(struct target *target, int current, return retval; } -static int aarch64_internal_restart(struct target *target) +static int aarch64_internal_restart(struct target *target, bool slave_pe) { struct armv8_common *armv8 = target_to_armv8(target); struct arm *arm = &armv8->arm; @@ -1045,22 +1038,39 @@ static int aarch64_internal_restart(struct target *target) if ((dscr & DSCR_ITE) == 0) LOG_ERROR("DSCR InstrCompl must be set before leaving debug!"); + /* make sure to acknowledge the halt event before resuming */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_APPPULSE, 2); + armv8->cti_base + CTI_INACK, CTI_TRIG(HALT)); + + /* + * open the CTI gate for channel 1 so that the restart events + * get passed along to all PEs + */ + if (retval == ERROR_OK) + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->cti_base + CTI_GATE, CTI_CHNL(1)); if (retval != ERROR_OK) return retval; - long long then = timeval_ms(); - for (;; ) { - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, &dscr); + if (!slave_pe) { + /* trigger an event on channel 1, generates a restart request to the PE */ + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->cti_base + CTI_APPPULSE, CTI_CHNL(1)); if (retval != ERROR_OK) return retval; - if ((dscr & DSCR_HDE) != 0) - break; - if (timeval_ms() > then + 1000) { - LOG_ERROR("Timeout waiting for resume"); - return ERROR_FAIL; + + long long then = timeval_ms(); + for (;; ) { + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); + if (retval != ERROR_OK) + return retval; + if ((dscr & DSCR_HDE) != 0) + break; + if (timeval_ms() > then + 1000) { + LOG_ERROR("Timeout waiting for resume"); + return ERROR_FAIL; + } } } @@ -1086,7 +1096,7 @@ static int aarch64_restore_smp(struct target *target, int handle_breakpoints) /* resume current address , not in step mode */ retval += aarch64_internal_restore(curr, 1, &address, handle_breakpoints, 0); - retval += aarch64_internal_restart(curr); + retval += aarch64_internal_restart(curr, true); } head = head->next; @@ -1117,7 +1127,7 @@ static int aarch64_resume(struct target *target, int current, if (retval != ERROR_OK) return retval; } - aarch64_internal_restart(target); + aarch64_internal_restart(target, false); if (!debug_execution) { target->state = TARGET_RUNNING; @@ -2398,12 +2408,6 @@ static int aarch64_examine_first(struct target *target) } else armv8->cti_base = target->ctibase; - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_UNLOCK , 0xC5ACCE55); - if (retval != ERROR_OK) - return retval; - - armv8->arm.core_type = ARM_MODE_MON; retval = aarch64_dpm_setup(aarch64, debug); if (retval != ERROR_OK) diff --git a/src/target/armv8.h b/src/target/armv8.h index f077045..f6859b2 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -225,6 +225,11 @@ target_to_armv8(struct target *target) #define CTI_GATE 0x140 #define CTI_UNLOCK 0xFB0 +#define CTI_CHNL(x) (1 << x) +#define CTI_TRIG_HALT 0 +#define CTI_TRIG_RESUME 1 +#define CTI_TRIG(n) (1 << CTI_TRIG_##n) + #define PAGE_SIZE_4KB 0x1000 #define PAGE_SIZE_4KB_LEVEL0_BITS 39 #define PAGE_SIZE_4KB_LEVEL1_BITS 30 -- cgit v1.1 From a9931e6a3ce9672a63e05790efa167a677a36da5 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 15 Sep 2016 09:13:51 +0200 Subject: aarch64: add basic Aarch32 support Add database for common, equivalent opcodes for Aarch32 and Aarch64 execution states Revisit all functions that access Aarch64 specific registers or use Aarch64 opcodes and rewrite them to act depending on current state of the core. Add core register access functions for Aarch32 state Add function to determine the core execution state without reading DSPSR. Change-Id: I345e9f6d682fb4ba454e4b1d16bb5e1b27570691 Signed-off-by: Matthias Welwarsky --- src/target/Makefile.am | 1 + src/target/aarch64.c | 43 +++++------- src/target/armv8.c | 166 ++++++++++++++++++++++++++++++++++--------- src/target/armv8.h | 7 +- src/target/armv8_dpm.c | 171 +++++++++++++++++++++++++++++++++++++++------ src/target/armv8_opcodes.c | 66 +++++++++++++++++ src/target/armv8_opcodes.h | 35 ++++++++-- 7 files changed, 406 insertions(+), 83 deletions(-) create mode 100644 src/target/armv8_opcodes.c diff --git a/src/target/Makefile.am b/src/target/Makefile.am index 0021f44..e936d3f 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -75,6 +75,7 @@ ARMV7_SRC = \ ARMV8_SRC = \ %D%/armv8_dpm.c \ + %D%/armv8_opcodes.c \ %D%/aarch64.c \ %D%/armv8.c \ %D%/armv8_cache.c diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 8d74dbd..824a042 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -90,7 +90,10 @@ static int aarch64_restore_system_control_reg(struct target *target) return retval; break; default: - LOG_DEBUG("unknow cpu state 0x%x" PRIx32, armv8->arm.core_state); + retval = armv8->arm.mcr(target, 15, 0, 0, 1, 0, aarch64->system_control_reg); + if (retval != ERROR_OK) + return retval; + break; } } return retval; @@ -531,6 +534,7 @@ static int aarch64_instr_write_data_r0(struct arm_dpm *dpm, uint32_t opcode, uint32_t data) { struct aarch64_common *a8 = dpm_to_a8(dpm); + uint32_t dscr = DSCR_ITE; int retval; @@ -539,9 +543,7 @@ static int aarch64_instr_write_data_r0(struct arm_dpm *dpm, return retval; retval = aarch64_exec_opcode( - a8->armv8_common.arm.target, - ARMV8_MRS(SYSTEM_DBG_DTRRX_EL0, 0), - &dscr); + a8->armv8_common.arm.target, armv8_opcode(&a8->armv8_common, READ_REG_DTRRX), &dscr); if (retval != ERROR_OK) return retval; @@ -584,12 +586,11 @@ static int aarch64_instr_write_data_r0_64(struct arm_dpm *dpm, static int aarch64_instr_cpsr_sync(struct arm_dpm *dpm) { struct target *target = dpm->arm->target; + struct armv8_common *armv8 = target_to_armv8(target); uint32_t dscr = DSCR_ITE; /* "Prefetch flush" after modifying execution status in CPSR */ - return aarch64_exec_opcode(target, - DSB_SY, - &dscr); + return aarch64_exec_opcode(target, armv8_opcode(armv8, ARMV8_OPC_DSB_SY), &dscr); } static int aarch64_instr_read_data_dcc(struct arm_dpm *dpm, @@ -645,9 +646,7 @@ static int aarch64_instr_read_data_r0(struct arm_dpm *dpm, /* write R0 to DCC */ retval = aarch64_exec_opcode( - a8->armv8_common.arm.target, - ARMV8_MSR_GP(SYSTEM_DBG_DTRTX_EL0, 0), /* msr dbgdtr_el0, x0 */ - &dscr); + a8->armv8_common.arm.target, armv8_opcode(&a8->armv8_common, WRITE_REG_DTRTX), &dscr); if (retval != ERROR_OK) return retval; @@ -999,20 +998,6 @@ static int aarch64_internal_restore(struct target *target, int current, /* registers are now invalid */ register_cache_invalidate(arm->core_cache); -#if 0 - /* the front-end may request us not to handle breakpoints */ - if (handle_breakpoints) { - /* Single step past breakpoint at current address */ - breakpoint = breakpoint_find(target, resume_pc); - if (breakpoint) { - LOG_DEBUG("unset breakpoint at 0x%8.8x", breakpoint->address); - cortex_m3_unset_breakpoint(target, breakpoint); - cortex_m3_single_step_core(target); - cortex_m3_set_breakpoint(target, breakpoint); - } - } -#endif - return retval; } @@ -1202,8 +1187,10 @@ static int aarch64_post_debug_entry(struct target *target) struct armv8_common *armv8 = &aarch64->armv8_common; int retval; + /* clear sticky errors */ mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, 1<<2); + armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); + switch (armv8->arm.core_mode) { case ARMV8_64_EL0T: case ARMV8_64_EL1T: @@ -1234,8 +1221,12 @@ static int aarch64_post_debug_entry(struct target *target) return retval; break; default: - LOG_DEBUG("unknow cpu state 0x%x" PRIx32, armv8->arm.core_state); + retval = armv8->arm.mrc(target, 15, 0, 0, 1, 0, &aarch64->system_control_reg); + if (retval != ERROR_OK) + return retval; + break; } + LOG_DEBUG("System_register: %8.8" PRIx32, aarch64->system_control_reg); aarch64->system_control_reg_curr = aarch64->system_control_reg; diff --git a/src/target/armv8.c b/src/target/armv8.c index c351dfd..306a06e 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -38,7 +38,7 @@ #include "target_type.h" static const char * const armv8_state_strings[] = { - "ARM", "Thumb", "Jazelle", "ThumbEE", "ARM64", + "AArch32", "Thumb", "Jazelle", "ThumbEE", "AArch64", }; static const struct { @@ -53,6 +53,30 @@ static const struct { /* These special modes are currently only supported * by ARMv6M and ARMv7M profiles */ { + .name = "USR", + .psr = ARM_MODE_USR, + }, + { + .name = "FIQ", + .psr = ARM_MODE_FIQ, + }, + { + .name = "IRQ", + .psr = ARM_MODE_IRQ, + }, + { + .name = "SVC", + .psr = ARM_MODE_SVC, + }, + { + .name = "MON", + .psr = ARM_MODE_MON, + }, + { + .name = "ABT", + .psr = ARM_MODE_ABT, + }, + { .name = "EL0T", .psr = ARMV8_64_EL0T, }, @@ -260,9 +284,59 @@ void armv8_set_cpsr(struct arm *arm, uint32_t cpsr) armv8_state_strings[arm->core_state]); } +static void armv8_show_fault_registers32(struct armv8_common *armv8) +{ + uint32_t dfsr, ifsr, dfar, ifar; + struct arm_dpm *dpm = armv8->arm.dpm; + int retval; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + return; + + /* ARMV4_5_MRC(cpnum, op1, r0, CRn, CRm, op2) */ + + /* c5/c0 - {data, instruction} fault status registers */ + retval = dpm->instr_read_data_r0(dpm, + T32_FMTITR(ARMV4_5_MRC(15, 0, 0, 5, 0, 0)), + &dfsr); + if (retval != ERROR_OK) + goto done; + + retval = dpm->instr_read_data_r0(dpm, + T32_FMTITR(ARMV4_5_MRC(15, 0, 0, 5, 0, 1)), + &ifsr); + if (retval != ERROR_OK) + goto done; + + /* c6/c0 - {data, instruction} fault address registers */ + retval = dpm->instr_read_data_r0(dpm, + T32_FMTITR(ARMV4_5_MRC(15, 0, 0, 6, 0, 0)), + &dfar); + if (retval != ERROR_OK) + goto done; + + retval = dpm->instr_read_data_r0(dpm, + T32_FMTITR(ARMV4_5_MRC(15, 0, 0, 6, 0, 2)), + &ifar); + if (retval != ERROR_OK) + goto done; + + LOG_USER("Data fault registers DFSR: %8.8" PRIx32 + ", DFAR: %8.8" PRIx32, dfsr, dfar); + LOG_USER("Instruction fault registers IFSR: %8.8" PRIx32 + ", IFAR: %8.8" PRIx32, ifsr, ifar); + +done: + /* (void) */ dpm->finish(dpm); +} + static void armv8_show_fault_registers(struct target *target) { - /* TODO */ + struct armv8_common *armv8 = target_to_armv8(target); + + if (armv8->arm.core_state != ARM_STATE_AARCH64) + armv8_show_fault_registers32(armv8); } static uint8_t armv8_pa_size(uint32_t ps) @@ -294,6 +368,45 @@ static uint8_t armv8_pa_size(uint32_t ps) return ret; } +static int armv8_read_ttbcr32(struct target *target) +{ + struct armv8_common *armv8 = target_to_armv8(target); + struct arm_dpm *dpm = armv8->arm.dpm; + uint32_t ttbcr, ttbcr_n; + int retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + /* MRC p15,0,,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/ + retval = dpm->instr_read_data_r0(dpm, + T32_FMTITR(ARMV4_5_MRC(15, 0, 0, 2, 0, 2)), + &ttbcr); + if (retval != ERROR_OK) + goto done; + + LOG_DEBUG("ttbcr %" PRIx32, ttbcr); + + ttbcr_n = ttbcr & 0x7; + armv8->armv8_mmu.ttbcr = ttbcr; + + /* + * ARM Architecture Reference Manual (ARMv7-A and ARMv7-Redition), + * document # ARM DDI 0406C + */ + armv8->armv8_mmu.ttbr_range[0] = 0xffffffff >> ttbcr_n; + armv8->armv8_mmu.ttbr_range[1] = 0xffffffff; + armv8->armv8_mmu.ttbr_mask[0] = 0xffffffff << (14 - ttbcr_n); + armv8->armv8_mmu.ttbr_mask[1] = 0xffffffff << 14; + + LOG_DEBUG("ttbr1 %s, ttbr0_mask %" PRIx32 " ttbr1_mask %" PRIx32, + (ttbcr_n != 0) ? "used" : "not used", + armv8->armv8_mmu.ttbr_mask[0], + armv8->armv8_mmu.ttbr_mask[1]); + +done: + dpm->finish(dpm); + return retval; +} + static int armv8_read_ttbcr(struct target *target) { struct armv8_common *armv8 = target_to_armv8(target); @@ -528,14 +641,13 @@ static int armv8_read_mpidr(struct target *target) struct armv8_common *armv8 = target_to_armv8(target); struct arm_dpm *dpm = armv8->arm.dpm; uint32_t mpidr; + retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; /* MRC p15,0,,c0,c0,5; read Multiprocessor ID register*/ - retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS(SYSTEM_MPIDR, 0), - &mpidr); + retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_MPIDR), &mpidr); if (retval != ERROR_OK) goto done; if (mpidr & 1<<31) { @@ -566,18 +678,21 @@ int armv8_identify_cache(struct target *target) uint32_t cache_selected, clidr; uint32_t cache_i_reg, cache_d_reg; struct armv8_cache_common *cache = &(armv8->armv8_mmu.armv8_cache); - armv8_read_ttbcr(target); - retval = dpm->prepare(dpm); + int is_aarch64 = armv8->arm.core_state == ARM_STATE_AARCH64; + retval = is_aarch64 ? armv8_read_ttbcr(target) : armv8_read_ttbcr32(target); + if (retval != ERROR_OK) + return retval; + + retval = dpm->prepare(dpm); if (retval != ERROR_OK) goto done; - /* retrieve CLIDR - * mrc p15, 1, r0, c0, c0, 1 @ read clidr */ - retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS(SYSTEM_CLIDR, 0), - &clidr); + + /* retrieve CLIDR */ + retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_CLIDR), &clidr); if (retval != ERROR_OK) goto done; + clidr = (clidr & 0x7000000) >> 23; LOG_INFO("number of cache level %" PRIx32, (uint32_t)(clidr / 2)); if ((clidr / 2) > 1) { @@ -586,18 +701,13 @@ int armv8_identify_cache(struct target *target) LOG_ERROR("cache l2 present :not supported"); } /* retrieve selected cache*/ - retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS(SYSTEM_CSSELR, 0), - &cache_selected); + retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_CSSELR), &cache_selected); if (retval != ERROR_OK) goto done; - /* select instruction cache * [0] : 1 instruction cache selection , 0 data cache selection */ - retval = dpm->instr_write_data_r0(dpm, - ARMV8_MRS(SYSTEM_CSSELR, 0), - 1); + retval = dpm->instr_write_data_r0(dpm, armv8_opcode(armv8, WRITE_REG_CSSELR), 1); if (retval != ERROR_OK) goto done; @@ -605,30 +715,21 @@ int armv8_identify_cache(struct target *target) * MRC P15,1,,C0, C0,0 ;on cortex A9 read CCSIDR * [2:0] line size 001 eight word per line * [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */ - retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS(SYSTEM_CCSIDR, 0), - &cache_i_reg); + retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_CCSIDR), &cache_i_reg); if (retval != ERROR_OK) goto done; /* select data cache*/ - retval = dpm->instr_write_data_r0(dpm, - ARMV8_MRS(SYSTEM_CSSELR, 0), - 0); + retval = dpm->instr_write_data_r0(dpm, armv8_opcode(armv8, WRITE_REG_CSSELR), 0); if (retval != ERROR_OK) goto done; - retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS(SYSTEM_CCSIDR, 0), - &cache_d_reg); + retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_CCSIDR), &cache_d_reg); if (retval != ERROR_OK) goto done; /* restore selected cache */ - dpm->instr_write_data_r0(dpm, - ARMV8_MRS(SYSTEM_CSSELR, 0), - cache_selected); - + dpm->instr_write_data_r0(dpm, armv8_opcode(armv8, WRITE_REG_CSSELR), cache_selected); if (retval != ERROR_OK) goto done; dpm->finish(dpm); @@ -770,6 +871,7 @@ int armv8_arch_state(struct target *target) if (arm->core_mode == ARM_MODE_ABT) armv8_show_fault_registers(target); + if (target->debug_reason == DBG_REASON_WATCHPOINT) LOG_USER("Watchpoint triggered at PC %#08x", (unsigned) armv8->dpm.wp_pc); diff --git a/src/target/armv8.h b/src/target/armv8.h index f6859b2..fa3674b 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -116,6 +116,10 @@ struct armv8_mmu_common { uint64_t ttbr0_mask;/* masked to be used */ uint32_t os_border; + uint32_t ttbcr; /* cache for ttbcr register */ + uint32_t ttbr_mask[2]; + uint32_t ttbr_range[2]; + int (*read_physical_memory)(struct target *target, target_addr_t address, uint32_t size, uint32_t count, uint8_t *buffer); struct armv8_cache_common armv8_cache; @@ -133,6 +137,8 @@ struct armv8_common { uint32_t cti_base; struct adiv5_ap *debug_ap; + const uint32_t *opcodes; + /* mdir */ uint8_t multi_processor_system; uint8_t cluster_id; @@ -144,7 +150,6 @@ struct armv8_common { uint32_t page_size; uint64_t ttbr_base; - /* cache specific to V7 Memory Management Unit compatible with v4_5*/ struct armv8_mmu_common armv8_mmu; /* Direct processor core register read and writes */ diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index 8c0d45a..c3d5ec4 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -164,6 +164,7 @@ static int dpmv8_msr(struct target *target, uint32_t op0, */ int dpmv8_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) { + struct armv8_common *armv8 = (struct armv8_common *)dpm->arm->arch_info; int retval; uint32_t cpsr; @@ -199,7 +200,7 @@ int dpmv8_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) } - retval = dpm->instr_write_data_r0(dpm, ARMV8_MSR_DSPSR(0), cpsr); + retval = dpm->instr_write_data_r0(dpm, armv8_opcode(armv8, WRITE_REG_DSPSR), cpsr); if (retval != ERROR_OK) return retval; @@ -209,6 +210,86 @@ int dpmv8_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) return retval; } +static int dpmv8_read_reg32(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +{ + uint32_t value; + int retval = ERROR_FAIL; + bool valid = true; + + switch (regnum) { + case 0 ... 14: + /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */ + retval = dpm->instr_read_data_dcc(dpm, + T32_FMTITR(ARMV4_5_MCR(14, 0, regnum, 0, 5, 0)), + &value); + break; + case ARMV8_R31: + retval = dpm->instr_read_data_dcc(dpm, + T32_FMTITR(ARMV4_5_MCR(14, 0, 13, 0, 5, 0)), + &value); + break; + case ARMV8_PC: + retval = dpm->instr_read_data_r0(dpm, + T32_FMTITR(ARMV8_MRC_DLR(0)), + &value); + break; + case ARMV8_xPSR: + retval = dpm->instr_read_data_r0(dpm, + T32_FMTITR(ARMV8_MRC_DSPSR(0)), + &value); + break; + default: + LOG_DEBUG("READ: %s ignored", r->name); + retval = ERROR_OK; + value = 0xFFFFFFFF; + valid = false; + break; + } + + if (retval == ERROR_OK) { + r->valid = valid; + r->dirty = false; + buf_set_u64(r->value, 0, 32, value); + LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value); + } + return retval; +} + +static int dpmv8_write_reg32(struct arm_dpm *dpm, struct reg *r, unsigned regnum) +{ + int retval; + uint64_t value = buf_get_u64(r->value, 0, 32); + + switch (regnum) { + case 0 ... 14: + /* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */ + retval = dpm->instr_write_data_dcc(dpm, + T32_FMTITR(ARMV4_5_MRC(14, 0, regnum, 0, 5, 0)), value); + break; + case ARMV8_PC:/* PC + * read r0 from DCC; then "MOV pc, r0" */ + retval = dpm->instr_write_data_r0(dpm, + T32_FMTITR(ARMV8_MCR_DLR(0)), value); + break; + case ARMV8_xPSR: /* CPSR */ + /* read r0 from DCC, then "MCR r0, DSPSR" */ + retval = dpm->instr_write_data_r0(dpm, + T32_FMTITR(ARMV8_MCR_DSPSR(0)), value); + break; + default: + retval = ERROR_OK; + LOG_DEBUG("WRITE: %s ignored", r->name); + break; + } + + if (retval == ERROR_OK) { + r->dirty = false; + LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned) value); + } + + return retval; +} + /* just read the register -- rely on the core mode being right */ static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) { @@ -222,20 +303,21 @@ static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, regnum), &value_64); break; - case 31: + case ARMV8_R31: retval = dpm->instr_read_data_r0_64(dpm, ARMV8_MOVFSP_64(0), &value_64); break; - case 32: + case ARMV8_PC: retval = dpm->instr_read_data_r0_64(dpm, ARMV8_MRS_DLR(0), &value_64); break; - case 33: + case ARMV8_xPSR: retval = dpm->instr_read_data_r0(dpm, ARMV8_MRS_DSPSR(0), &value); + break; default: LOG_DEBUG("READ: %s fail", r->name); break; @@ -244,11 +326,13 @@ static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) if (retval == ERROR_OK) { r->valid = true; r->dirty = false; - buf_set_u64(r->value, 0, 32, value_64); - if (r->size == 64) + if (r->size == 64) { + buf_set_u64(r->value, 0, 64, value_64); LOG_DEBUG("READ: %s, %16.8llx", r->name, (unsigned long long) value_64); - else + } else { + buf_set_u32(r->value, 0, 32, value); LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value); + } } return retval; } @@ -267,23 +351,24 @@ static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, regnum), value_64); break; - case 31: + case ARMV8_R31: value_64 = buf_get_u64(r->value, 0, 64); retval = dpm->instr_write_data_r0_64(dpm, ARMV8_MOVTSP_64(0), value_64); break; - case 32: + case ARMV8_PC: value_64 = buf_get_u64(r->value, 0, 64); retval = dpm->instr_write_data_r0_64(dpm, ARMV8_MSR_DLR(0), value_64); break; - case 33: + case ARMV8_xPSR: value = buf_get_u32(r->value, 0, 32); retval = dpm->instr_write_data_r0(dpm, ARMV8_MSR_DSPSR(0), value); + break; default: LOG_DEBUG("write: %s fail", r->name); break; @@ -301,6 +386,36 @@ static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) return retval; } +static inline enum arm_state dpm_get_core_state(uint32_t dscr) +{ + int el = (dscr >> 8) & 0x3; + int rw = (dscr >> 10) & 0xF; + + LOG_DEBUG("EL:%i, RW:0x%x", el, rw); + + /* DSCR.RW = 0b1111 - all EL are using AArch64 state */ + if (rw == 0xF) + return ARM_STATE_AARCH64; + + /* DSCR.RW = 0b1110 - all EL > 0 are using AArch64 state */ + if (rw == 0xE && el > 0) + return ARM_STATE_AARCH64; + + /* DSCR.RW = 0b110x - all EL > 1 are using Aarch64 state */ + if ((rw & 0xE) == 0xC && el > 1) + return ARM_STATE_AARCH64; + + /* DSCR.RW = 0b10xx - all EL > 2 are using Aarch64 state */ + if ((rw & 0xC) == 0x8 && el > 2) + return ARM_STATE_AARCH64; + + /* DSCR.RW = 0b0xxx - all EL are using AArch32 state */ + if ((rw & 0x8) == 0) + return ARM_STATE_ARM; + + return ARM_STATE_ARM; +} + /** * Read basic registers of the the current context: R0 to R15, and CPSR; * sets the core mode (such as USR or IRQ) and state (such as ARM or Thumb). @@ -311,7 +426,10 @@ static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) int armv8_dpm_read_current_registers(struct arm_dpm *dpm) { struct arm *arm = dpm->arm; + struct armv8_common *armv8 = (struct armv8_common *)arm->arch_info; + enum arm_state core_state; uint32_t cpsr; + int retval; struct reg *r; @@ -319,16 +437,22 @@ int armv8_dpm_read_current_registers(struct arm_dpm *dpm) if (retval != ERROR_OK) return retval; + core_state = dpm_get_core_state(dpm->dscr); + + armv8_select_opcodes(armv8, core_state); + /* read R0 first (it's used for scratch), then CPSR */ r = arm->core_cache->reg_list + 0; if (!r->valid) { - retval = dpmv8_read_reg(dpm, r, 0); + retval = core_state == ARM_STATE_AARCH64 ? + dpmv8_read_reg(dpm, r, 0) : dpmv8_read_reg32(dpm, r, 0); if (retval != ERROR_OK) goto fail; } r->dirty = true; + /* read cpsr to r0 and get it back */ - retval = dpm->instr_read_data_r0(dpm, ARMV8_MRS_DSPSR(0), &cpsr); + retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_DSPSR), &cpsr); if (retval != ERROR_OK) goto fail; @@ -341,7 +465,9 @@ int armv8_dpm_read_current_registers(struct arm_dpm *dpm) if (r->valid) continue; - retval = dpmv8_read_reg(dpm, r, i); + retval = core_state == ARM_STATE_AARCH64 ? + dpmv8_read_reg(dpm, r, i) : dpmv8_read_reg32(dpm, r, i); + if (retval != ERROR_OK) goto fail; } @@ -419,6 +545,7 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) struct arm *arm = dpm->arm; struct reg_cache *cache = arm->core_cache; int retval; + bool is_aarch64 = arm->core_state == ARM_STATE_AARCH64; retval = dpm->prepare(dpm); if (retval != ERROR_OK) @@ -480,9 +607,8 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) r = cache->reg_list[i].arch_info; regnum = r->num; - retval = dpmv8_write_reg(dpm, - &cache->reg_list[i], - regnum); + retval = is_aarch64 ? dpmv8_write_reg(dpm, &cache->reg_list[i], regnum) + : dpmv8_write_reg32(dpm, &cache->reg_list[i], regnum); if (retval != ERROR_OK) goto done; } @@ -497,13 +623,15 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) goto done; arm->cpsr->dirty = false; - retval = dpmv8_write_reg(dpm, arm->pc, (arm->core_cache->num_regs - 2)); + retval = is_aarch64 ? dpmv8_write_reg(dpm, arm->pc, (arm->core_cache->num_regs - 2)) + : dpmv8_write_reg32(dpm, arm->pc, (arm->core_cache->num_regs - 2)); if (retval != ERROR_OK) goto done; arm->pc->dirty = false; /* flush R0 -- it's *very* dirty by now */ - retval = dpmv8_write_reg(dpm, &cache->reg_list[0], 0); + retval = is_aarch64 ? dpmv8_write_reg(dpm, &cache->reg_list[0], 0) + : dpmv8_write_reg32(dpm, &cache->reg_list[0], 0); if (retval != ERROR_OK) goto done; cache->reg_list[0].dirty = false; @@ -538,7 +666,8 @@ static int armv8_dpm_read_core_reg(struct target *target, struct reg *r, if (retval != ERROR_OK) return retval; - retval = dpmv8_read_reg(dpm, r, regnum); + retval = arm->core_state == ARM_STATE_AARCH64 ? + dpmv8_read_reg(dpm, r, regnum) : dpmv8_read_reg32(dpm, r, regnum); if (retval != ERROR_OK) goto fail; @@ -566,7 +695,9 @@ static int armv8_dpm_write_core_reg(struct target *target, struct reg *r, if (retval != ERROR_OK) return retval; - retval = dpmv8_write_reg(dpm, r, regnum); + retval = arm->core_state == ARM_STATE_AARCH64 ? + dpmv8_write_reg(dpm, r, regnum) : dpmv8_write_reg32(dpm, r, regnum); + /* always clean up, regardless of error */ /* (void) */ dpm->finish(dpm); diff --git a/src/target/armv8_opcodes.c b/src/target/armv8_opcodes.c new file mode 100644 index 0000000..78b60e0 --- /dev/null +++ b/src/target/armv8_opcodes.c @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2015 by Matthias Welwarsky + * + * 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. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "armv8.h" +#include "armv8_opcodes.h" + +static const uint32_t a64_opcodes[ARMV8_OPC_NUM] = { + [READ_REG_CLIDR] = ARMV8_MRS(SYSTEM_CLIDR, 0), + [READ_REG_CSSELR] = ARMV8_MRS(SYSTEM_CSSELR, 0), + [READ_REG_CCSIDR] = ARMV8_MRS(SYSTEM_CCSIDR, 0), + [WRITE_REG_CSSELR] = ARMV8_MSR_GP(SYSTEM_CSSELR, 0), + [READ_REG_MPIDR] = ARMV8_MRS(SYSTEM_MPIDR, 0), + [READ_REG_DTRRX] = ARMV8_MRS(SYSTEM_DBG_DTRRX_EL0, 0), + [WRITE_REG_DTRTX] = ARMV8_MSR_GP(SYSTEM_DBG_DTRTX_EL0, 0), + [WRITE_REG_DSPSR] = ARMV8_MSR_DSPSR(0), + [READ_REG_DSPSR] = ARMV8_MRS_DSPSR(0), + [ARMV8_OPC_DSB_SY] = ARMV8_DSB_SY, +}; + +static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { + [READ_REG_CLIDR] = T32_FMTITR(ARMV4_5_MRC(15, 1, 0, 0, 0, 1)), + [READ_REG_CSSELR] = T32_FMTITR(ARMV4_5_MRC(15, 2, 0, 0, 0, 0)), + [READ_REG_CCSIDR] = T32_FMTITR(ARMV4_5_MRC(15, 1, 0, 0, 0, 0)), + [WRITE_REG_CSSELR] = T32_FMTITR(ARMV4_5_MCR(15, 2, 0, 0, 0, 0)), + [READ_REG_MPIDR] = T32_FMTITR(ARMV4_5_MRC(15, 0, 0, 0, 0, 5)), + [READ_REG_DTRRX] = T32_FMTITR(ARMV4_5_MRC(14, 0, 0, 0, 5, 0)), + [WRITE_REG_DTRTX] = T32_FMTITR(ARMV4_5_MCR(14, 0, 0, 0, 5, 0)), + [WRITE_REG_DSPSR] = T32_FMTITR(ARMV8_MCR_DSPSR(0)), + [READ_REG_DSPSR] = T32_FMTITR(ARMV8_MRC_DSPSR(0)), + [ARMV8_OPC_DSB_SY] = T32_FMTITR(ARMV8_DSB_SY_T1), +}; + +void armv8_select_opcodes(struct armv8_common *armv8, bool state_is_aarch64) +{ + if (state_is_aarch64) + armv8->opcodes = &a64_opcodes[0]; + else + armv8->opcodes = &t32_opcodes[0]; +} + +uint32_t armv8_opcode(struct armv8_common *armv8, enum armv8_opcode code) +{ + if ((int)code >= ARMV8_OPC_NUM) + return -1; + + return *(armv8->opcodes + code); +} diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index 89d7440..9f5ebf8 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -95,8 +95,6 @@ #define SYSTEM_TTBR0_EL3 0b1111000100000000 #define SYSTEM_TTBR1_EL1 0b1100000100000001 - - #define ARMV8_MRS_DSPSR(Rt) (0xd53b4500 | (Rt)) #define ARMV8_MSR_DSPSR(Rt) (0xd51b4500 | (Rt)) #define ARMV8_MRS_DLR(Rt) (0xd53b4520 | (Rt)) @@ -105,11 +103,23 @@ /* T32 ITR format */ #define T32_FMTITR(instr) (((instr & 0x0000FFFF) << 16) | ((instr & 0xFFFF0000) >> 16)) +/* T32 instruction to access coprocessor registers */ +#define ARMV8_MCR_T1(cp, CRn, opc1, CRm, opc2, Rt) ARMV4_5_MCR(cp, opc1, Rt, CRn, CRm, opc2) +#define ARMV8_MRC_T1(cp, CRn, opc1, CRm, opc2, Rt) ARMV4_5_MRC(cp, opc1, Rt, CRn, CRm, opc2) + +/* T32 instructions to access DSPSR and DLR */ +#define ARMV8_MRC_DSPSR(Rt) ARMV8_MRC_T1(15, 4, 3, 5, 0, Rt) +#define ARMV8_MCR_DSPSR(Rt) ARMV8_MCR_T1(15, 4, 3, 5, 0, Rt) +#define ARMV8_MRC_DLR(Rt) ARMV8_MRC_T1(15, 4, 3, 5, 1, Rt) +#define ARMV8_MCR_DLR(Rt) ARMV8_MCR_T1(15, 4, 3, 5, 1, Rt) + #define ARMV8_DCPS1(IM) (0xd4a00001 | (((IM) & 0xFFFF) << 5)) #define ARMV8_DCPS2(IM) (0xd4a00002 | (((IM) & 0xFFFF) << 5)) #define ARMV8_DCPS3(IM) (0xd4a00003 | (((IM) & 0xFFFF) << 5)) -#define DSB_SY 0xd5033F9F +#define ARMV8_DSB_SY 0xd5033F9F +#define ARMV8_DSB_SY_T1 0xf3bf8f4f + #define ARMV8_MRS(System, Rt) (0xd5300000 | ((System) << 5) | (Rt)) /* ARM V8 Move to system register. */ #define ARMV8_MSR_GP(System, Rt) \ @@ -128,4 +138,21 @@ #define ARMV8_SYS(System, Rt) (0xD5080000 | ((System) << 5) | Rt) -#endif /* __ARM_OPCODES_H */ +enum armv8_opcode { + READ_REG_CLIDR, + READ_REG_CSSELR, + READ_REG_CCSIDR, + WRITE_REG_CSSELR, + READ_REG_MPIDR, + READ_REG_DTRRX, + WRITE_REG_DTRTX, + WRITE_REG_DSPSR, + READ_REG_DSPSR, + ARMV8_OPC_DSB_SY, + ARMV8_OPC_NUM, +}; + +extern uint32_t armv8_opcode(struct armv8_common *armv8, enum armv8_opcode); +extern void armv8_select_opcodes(struct armv8_common *armv8, bool state_is_aarch64); + +#endif /* OPENOCD_TARGET_ARMV8_OPCODES_H */ -- cgit v1.1 From ef263a45a272366836da10b7c42c916d43527f86 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 22 Sep 2016 21:16:31 +0200 Subject: aarch64: refactor armv8 dpm Move all DPM related functions from aarch64.c to armv8_dpm.c. Change-Id: I43404ff5db414ae898787a523d3219e5bee44889 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 523 ++----------------------------------------------- src/target/armv8_dpm.c | 427 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 440 insertions(+), 510 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 824a042..1d2abc7 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -46,8 +46,6 @@ static int aarch64_virt2phys(struct target *target, target_addr_t virt, target_addr_t *phys); static int aarch64_read_apb_ap_memory(struct target *target, uint64_t address, uint32_t size, uint32_t count, uint8_t *buffer); -static int aarch64_instr_write_data_r0(struct arm_dpm *dpm, - uint32_t opcode, uint32_t data); static int aarch64_restore_system_control_reg(struct target *target) { @@ -253,61 +251,6 @@ static int aarch64_init_debug_access(struct target *target) return aarch64_poll(target); } -/* To reduce needless round-trips, pass in a pointer to the current - * DSCR value. Initialize it to zero if you just need to know the - * value on return from this function; or DSCR_ITE if you - * happen to know that no instruction is pending. - */ -static int aarch64_exec_opcode(struct target *target, - uint32_t opcode, uint32_t *dscr_p) -{ - uint32_t dscr; - int retval; - struct armv8_common *armv8 = target_to_armv8(target); - dscr = dscr_p ? *dscr_p : 0; - - LOG_DEBUG("exec opcode 0x%08" PRIx32, opcode); - - /* Wait for InstrCompl bit to be set */ - long long then = timeval_ms(); - while ((dscr & DSCR_ITE) == 0) { - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, &dscr); - if (retval != ERROR_OK) { - LOG_ERROR("Could not read DSCR register, opcode = 0x%08" PRIx32, opcode); - return retval; - } - if (timeval_ms() > then + 1000) { - LOG_ERROR("Timeout waiting for aarch64_exec_opcode"); - return ERROR_FAIL; - } - } - - retval = mem_ap_write_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_ITR, opcode); - if (retval != ERROR_OK) - return retval; - - then = timeval_ms(); - do { - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, &dscr); - if (retval != ERROR_OK) { - LOG_ERROR("Could not read DSCR register"); - return retval; - } - if (timeval_ms() > then + 1000) { - LOG_ERROR("Timeout waiting for aarch64_exec_opcode"); - return ERROR_FAIL; - } - } while ((dscr & DSCR_ITE) == 0); /* Wait for InstrCompl bit to be set */ - - if (dscr_p) - *dscr_p = dscr; - - return retval; -} - /* Write to memory mapped registers directly with no cache or mmu handling */ static int aarch64_dap_write_memap_register_u32(struct target *target, uint32_t address, @@ -321,425 +264,6 @@ static int aarch64_dap_write_memap_register_u32(struct target *target, return retval; } -/* - * AARCH64 implementation of Debug Programmer's Model - * - * NOTE the invariant: these routines return with DSCR_ITE set, - * so there's no need to poll for it before executing an instruction. - * - * NOTE that in several of these cases the "stall" mode might be useful. - * It'd let us queue a few operations together... prepare/finish might - * be the places to enable/disable that mode. - */ - -static inline struct aarch64_common *dpm_to_a8(struct arm_dpm *dpm) -{ - return container_of(dpm, struct aarch64_common, armv8_common.dpm); -} - -static int aarch64_write_dcc(struct armv8_common *armv8, uint32_t data) -{ - LOG_DEBUG("write DCC 0x%08" PRIx32, data); - return mem_ap_write_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DTRRX, data); -} - -static int aarch64_write_dcc_64(struct armv8_common *armv8, uint64_t data) -{ - int ret; - LOG_DEBUG("write DCC Low word0x%08" PRIx32, (unsigned)data); - LOG_DEBUG("write DCC High word 0x%08" PRIx32, (unsigned)(data >> 32)); - ret = mem_ap_write_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DTRRX, data); - ret += mem_ap_write_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DTRTX, data >> 32); - return ret; -} - -static int aarch64_read_dcc(struct armv8_common *armv8, uint32_t *data, - uint32_t *dscr_p) -{ - uint32_t dscr = DSCR_ITE; - int retval; - - if (dscr_p) - dscr = *dscr_p; - - /* Wait for DTRRXfull */ - long long then = timeval_ms(); - while ((dscr & DSCR_DTR_TX_FULL) == 0) { - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, - &dscr); - if (retval != ERROR_OK) - return retval; - if (timeval_ms() > then + 1000) { - LOG_ERROR("Timeout waiting for read dcc"); - return ERROR_FAIL; - } - } - - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DTRTX, - data); - if (retval != ERROR_OK) - return retval; - LOG_DEBUG("read DCC 0x%08" PRIx32, *data); - - if (dscr_p) - *dscr_p = dscr; - - return retval; -} - -static int aarch64_read_dcc_64(struct armv8_common *armv8, uint64_t *data, - uint32_t *dscr_p) -{ - uint32_t dscr = DSCR_ITE; - uint32_t higher; - int retval; - - if (dscr_p) - dscr = *dscr_p; - - /* Wait for DTRRXfull */ - long long then = timeval_ms(); - while ((dscr & DSCR_DTR_TX_FULL) == 0) { - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, - &dscr); - if (retval != ERROR_OK) - return retval; - if (timeval_ms() > then + 1000) { - LOG_ERROR("Timeout waiting for read dcc"); - return ERROR_FAIL; - } - } - - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DTRTX, - (uint32_t *)data); - if (retval != ERROR_OK) - return retval; - - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DTRRX, - &higher); - if (retval != ERROR_OK) - return retval; - - *data = *(uint32_t *)data | (uint64_t)higher << 32; - LOG_DEBUG("read DCC 0x%16.16" PRIx64, *data); - - if (dscr_p) - *dscr_p = dscr; - - return retval; -} - -static int aarch64_dpm_prepare(struct arm_dpm *dpm) -{ - struct aarch64_common *a8 = dpm_to_a8(dpm); - uint32_t dscr; - int retval; - - /* set up invariant: INSTR_COMP is set after ever DPM operation */ - long long then = timeval_ms(); - for (;; ) { - retval = mem_ap_read_atomic_u32(a8->armv8_common.debug_ap, - a8->armv8_common.debug_base + CPUV8_DBG_DSCR, - &dscr); - if (retval != ERROR_OK) - return retval; - if ((dscr & DSCR_ITE) != 0) - break; - if (timeval_ms() > then + 1000) { - LOG_ERROR("Timeout waiting for dpm prepare"); - return ERROR_FAIL; - } - } - - /* this "should never happen" ... */ - if (dscr & DSCR_DTR_RX_FULL) { - LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr); - /* Clear DCCRX */ - retval = mem_ap_read_u32(a8->armv8_common.debug_ap, - a8->armv8_common.debug_base + CPUV8_DBG_DTRRX, &dscr); - if (retval != ERROR_OK) - return retval; - - /* Clear sticky error */ - retval = mem_ap_write_u32(a8->armv8_common.debug_ap, - a8->armv8_common.debug_base + CPUV8_DBG_DRCR, DRCR_CSE); - if (retval != ERROR_OK) - return retval; - } - - return retval; -} - -static int aarch64_dpm_finish(struct arm_dpm *dpm) -{ - /* REVISIT what could be done here? */ - return ERROR_OK; -} - -static int aarch64_instr_execute(struct arm_dpm *dpm, - uint32_t opcode) -{ - struct aarch64_common *a8 = dpm_to_a8(dpm); - uint32_t dscr = DSCR_ITE; - - return aarch64_exec_opcode( - a8->armv8_common.arm.target, - opcode, - &dscr); -} - -static int aarch64_instr_write_data_dcc(struct arm_dpm *dpm, - uint32_t opcode, uint32_t data) -{ - struct aarch64_common *a8 = dpm_to_a8(dpm); - int retval; - uint32_t dscr = DSCR_ITE; - - retval = aarch64_write_dcc(&a8->armv8_common, data); - if (retval != ERROR_OK) - return retval; - - return aarch64_exec_opcode( - a8->armv8_common.arm.target, - opcode, - &dscr); -} - -static int aarch64_instr_write_data_dcc_64(struct arm_dpm *dpm, - uint32_t opcode, uint64_t data) -{ - struct aarch64_common *a8 = dpm_to_a8(dpm); - int retval; - uint32_t dscr = DSCR_ITE; - - retval = aarch64_write_dcc_64(&a8->armv8_common, data); - if (retval != ERROR_OK) - return retval; - - return aarch64_exec_opcode( - a8->armv8_common.arm.target, - opcode, - &dscr); -} - -static int aarch64_instr_write_data_r0(struct arm_dpm *dpm, - uint32_t opcode, uint32_t data) -{ - struct aarch64_common *a8 = dpm_to_a8(dpm); - - uint32_t dscr = DSCR_ITE; - int retval; - - retval = aarch64_write_dcc(&a8->armv8_common, data); - if (retval != ERROR_OK) - return retval; - - retval = aarch64_exec_opcode( - a8->armv8_common.arm.target, armv8_opcode(&a8->armv8_common, READ_REG_DTRRX), &dscr); - if (retval != ERROR_OK) - return retval; - - /* then the opcode, taking data from R0 */ - retval = aarch64_exec_opcode( - a8->armv8_common.arm.target, - opcode, - &dscr); - - return retval; -} - -static int aarch64_instr_write_data_r0_64(struct arm_dpm *dpm, - uint32_t opcode, uint64_t data) -{ - struct aarch64_common *a8 = dpm_to_a8(dpm); - uint32_t dscr = DSCR_ITE; - int retval; - - retval = aarch64_write_dcc_64(&a8->armv8_common, data); - if (retval != ERROR_OK) - return retval; - - retval = aarch64_exec_opcode( - a8->armv8_common.arm.target, - ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), - &dscr); - if (retval != ERROR_OK) - return retval; - - /* then the opcode, taking data from R0 */ - retval = aarch64_exec_opcode( - a8->armv8_common.arm.target, - opcode, - &dscr); - - return retval; -} - -static int aarch64_instr_cpsr_sync(struct arm_dpm *dpm) -{ - struct target *target = dpm->arm->target; - struct armv8_common *armv8 = target_to_armv8(target); - uint32_t dscr = DSCR_ITE; - - /* "Prefetch flush" after modifying execution status in CPSR */ - return aarch64_exec_opcode(target, armv8_opcode(armv8, ARMV8_OPC_DSB_SY), &dscr); -} - -static int aarch64_instr_read_data_dcc(struct arm_dpm *dpm, - uint32_t opcode, uint32_t *data) -{ - struct aarch64_common *a8 = dpm_to_a8(dpm); - int retval; - uint32_t dscr = DSCR_ITE; - - /* the opcode, writing data to DCC */ - retval = aarch64_exec_opcode( - a8->armv8_common.arm.target, - opcode, - &dscr); - if (retval != ERROR_OK) - return retval; - - return aarch64_read_dcc(&a8->armv8_common, data, &dscr); -} - -static int aarch64_instr_read_data_dcc_64(struct arm_dpm *dpm, - uint32_t opcode, uint64_t *data) -{ - struct aarch64_common *a8 = dpm_to_a8(dpm); - int retval; - uint32_t dscr = DSCR_ITE; - - /* the opcode, writing data to DCC */ - retval = aarch64_exec_opcode( - a8->armv8_common.arm.target, - opcode, - &dscr); - if (retval != ERROR_OK) - return retval; - - return aarch64_read_dcc_64(&a8->armv8_common, data, &dscr); -} - -static int aarch64_instr_read_data_r0(struct arm_dpm *dpm, - uint32_t opcode, uint32_t *data) -{ - struct aarch64_common *a8 = dpm_to_a8(dpm); - uint32_t dscr = DSCR_ITE; - int retval; - - /* the opcode, writing data to R0 */ - retval = aarch64_exec_opcode( - a8->armv8_common.arm.target, - opcode, - &dscr); - if (retval != ERROR_OK) - return retval; - - /* write R0 to DCC */ - retval = aarch64_exec_opcode( - a8->armv8_common.arm.target, armv8_opcode(&a8->armv8_common, WRITE_REG_DTRTX), &dscr); - if (retval != ERROR_OK) - return retval; - - return aarch64_read_dcc(&a8->armv8_common, data, &dscr); -} - -static int aarch64_instr_read_data_r0_64(struct arm_dpm *dpm, - uint32_t opcode, uint64_t *data) -{ - struct aarch64_common *a8 = dpm_to_a8(dpm); - uint32_t dscr = DSCR_ITE; - int retval; - - /* the opcode, writing data to R0 */ - retval = aarch64_exec_opcode( - a8->armv8_common.arm.target, - opcode, - &dscr); - if (retval != ERROR_OK) - return retval; - - /* write R0 to DCC */ - retval = aarch64_exec_opcode( - a8->armv8_common.arm.target, - ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 0), /* msr dbgdtr_el0, x0 */ - &dscr); - if (retval != ERROR_OK) - return retval; - - return aarch64_read_dcc_64(&a8->armv8_common, data, &dscr); -} - -static int aarch64_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, - uint32_t addr, uint32_t control) -{ - struct aarch64_common *a8 = dpm_to_a8(dpm); - uint32_t vr = a8->armv8_common.debug_base; - uint32_t cr = a8->armv8_common.debug_base; - int retval; - - switch (index_t) { - case 0 ... 15: /* breakpoints */ - vr += CPUV8_DBG_BVR_BASE; - cr += CPUV8_DBG_BCR_BASE; - break; - case 16 ... 31: /* watchpoints */ - vr += CPUV8_DBG_WVR_BASE; - cr += CPUV8_DBG_WCR_BASE; - index_t -= 16; - break; - default: - return ERROR_FAIL; - } - vr += 16 * index_t; - cr += 16 * index_t; - - LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x", - (unsigned) vr, (unsigned) cr); - - retval = aarch64_dap_write_memap_register_u32(dpm->arm->target, - vr, addr); - if (retval != ERROR_OK) - return retval; - retval = aarch64_dap_write_memap_register_u32(dpm->arm->target, - cr, control); - return retval; -} - -static int aarch64_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) -{ - struct aarch64_common *a = dpm_to_a8(dpm); - uint32_t cr; - - switch (index_t) { - case 0 ... 15: - cr = a->armv8_common.debug_base + CPUV8_DBG_BCR_BASE; - break; - case 16 ... 31: - cr = a->armv8_common.debug_base + CPUV8_DBG_WCR_BASE; - index_t -= 16; - break; - default: - return ERROR_FAIL; - } - cr += 16 * index_t; - - LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr); - - /* clear control register */ - return aarch64_dap_write_memap_register_u32(dpm->arm->target, cr, 0); - -} - static int aarch64_dpm_setup(struct aarch64_common *a8, uint64_t debug) { struct arm_dpm *dpm = &a8->armv8_common.dpm; @@ -748,32 +272,13 @@ static int aarch64_dpm_setup(struct aarch64_common *a8, uint64_t debug) dpm->arm = &a8->armv8_common.arm; dpm->didr = debug; - dpm->prepare = aarch64_dpm_prepare; - dpm->finish = aarch64_dpm_finish; - - dpm->instr_execute = aarch64_instr_execute; - dpm->instr_write_data_dcc = aarch64_instr_write_data_dcc; - dpm->instr_write_data_dcc_64 = aarch64_instr_write_data_dcc_64; - dpm->instr_write_data_r0 = aarch64_instr_write_data_r0; - dpm->instr_write_data_r0_64 = aarch64_instr_write_data_r0_64; - dpm->instr_cpsr_sync = aarch64_instr_cpsr_sync; - - dpm->instr_read_data_dcc = aarch64_instr_read_data_dcc; - dpm->instr_read_data_dcc_64 = aarch64_instr_read_data_dcc_64; - dpm->instr_read_data_r0 = aarch64_instr_read_data_r0; - dpm->instr_read_data_r0_64 = aarch64_instr_read_data_r0_64; - - dpm->arm_reg_current = armv8_reg_current; - - dpm->bpwp_enable = aarch64_bpwp_enable; - dpm->bpwp_disable = aarch64_bpwp_disable; - retval = armv8_dpm_setup(dpm); if (retval == ERROR_OK) retval = armv8_dpm_initialize(dpm); return retval; } + static struct target *get_aarch64(struct target *target, int32_t coreid) { struct target_list *head; @@ -1853,6 +1358,7 @@ static int aarch64_write_apb_ap_memory(struct target *target, /* write memory through APB-AP */ int retval = ERROR_COMMAND_SYNTAX_ERROR; struct armv8_common *armv8 = target_to_armv8(target); + struct arm_dpm *dpm = &armv8->dpm; struct arm *arm = &armv8->arm; int total_bytes = count * size; int total_u32; @@ -1937,17 +1443,15 @@ static int aarch64_write_apb_ap_memory(struct target *target, if (arm->core_state == ARM_STATE_AARCH64) { /* Write X0 with value 'address' using write procedure */ /* Step 1.a+b - Write the address for read access into DBGDTR_EL0 */ - retval += aarch64_write_dcc_64(armv8, address & ~0x3ULL); /* Step 1.c - Copy value from DTR to R0 using instruction mrs DBGDTR_EL0, x0 */ - retval += aarch64_exec_opcode(target, - ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), &dscr); + retval = dpm->instr_write_data_dcc_64(dpm, + ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), address & ~0x3ULL); } else { /* Write R0 with value 'address' using write procedure */ /* Step 1.a+b - Write the address for read access into DBGDTRRX */ - retval += aarch64_write_dcc(armv8, address & ~0x3ULL); /* Step 1.c - Copy value from DTR to R0 using instruction mrc DBGDTRTXint, r0 */ - retval += aarch64_exec_opcode(target, - T32_FMTITR(ARMV4_5_MRC(14, 0, 0, 0, 5, 0)), &dscr); + dpm->instr_write_data_dcc(dpm, + T32_FMTITR(ARMV4_5_MRC(14, 0, 0, 0, 5, 0)), address & ~0x3ULL); } /* Step 1.d - Change DCC to memory mode */ @@ -2008,6 +1512,7 @@ static int aarch64_read_apb_ap_memory(struct target *target, /* read memory through APB-AP */ int retval = ERROR_COMMAND_SYNTAX_ERROR; struct armv8_common *armv8 = target_to_armv8(target); + struct arm_dpm *dpm = &armv8->dpm; struct arm *arm = &armv8->arm; int total_bytes = count * size; int total_u32; @@ -2058,11 +1563,11 @@ static int aarch64_read_apb_ap_memory(struct target *target, if (arm->core_state == ARM_STATE_AARCH64) { /* Write X0 with value 'address' using write procedure */ /* Step 1.a+b - Write the address for read access into DBGDTR_EL0 */ - retval += aarch64_write_dcc_64(armv8, address & ~0x3ULL); /* Step 1.c - Copy value from DTR to R0 using instruction mrs DBGDTR_EL0, x0 */ - retval += aarch64_exec_opcode(target, ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), &dscr); + retval += dpm->instr_write_data_dcc_64(dpm, + ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), address & ~0x3ULL); /* Step 1.d - Dummy operation to ensure EDSCR.Txfull == 1 */ - retval += aarch64_exec_opcode(target, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 0), &dscr); + retval += dpm->instr_execute(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 0)); /* Step 1.e - Change DCC to memory mode */ dscr = dscr | DSCR_MA; retval += mem_ap_write_atomic_u32(armv8->debug_ap, @@ -2073,13 +1578,11 @@ static int aarch64_read_apb_ap_memory(struct target *target, } else { /* Write R0 with value 'address' using write procedure */ /* Step 1.a+b - Write the address for read access into DBGDTRRXint */ - retval += aarch64_write_dcc(armv8, address & ~0x3ULL); /* Step 1.c - Copy value from DTR to R0 using instruction mrc DBGDTRTXint, r0 */ - retval += aarch64_exec_opcode(target, - T32_FMTITR(ARMV4_5_MRC(14, 0, 0, 0, 5, 0)), &dscr); + retval += dpm->instr_write_data_dcc(dpm, + T32_FMTITR(ARMV4_5_MRC(14, 0, 0, 0, 5, 0)), address & ~0x3ULL); /* Step 1.d - Dummy operation to ensure EDSCR.Txfull == 1 */ - retval += aarch64_exec_opcode(target, - T32_FMTITR(ARMV4_5_MCR(14, 0, 0, 0, 5, 0)), &dscr); + retval += dpm->instr_execute(dpm, T32_FMTITR(ARMV4_5_MCR(14, 0, 0, 0, 5, 0))); /* Step 1.e - Change DCC to memory mode */ dscr = dscr | DSCR_MA; retval += mem_ap_write_atomic_u32(armv8->debug_ap, diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index c3d5ec4..4bb2075 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -26,6 +26,8 @@ #include "target_type.h" #include "armv8_opcodes.h" +#include "helper/time_support.h" + /** * @file @@ -42,6 +44,410 @@ /*----------------------------------------------------------------------*/ +static int dpmv8_write_dcc(struct armv8_common *armv8, uint32_t data) +{ + LOG_DEBUG("write DCC 0x%08" PRIx32, data); + return mem_ap_write_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DTRRX, data); +} + +static int dpmv8_write_dcc_64(struct armv8_common *armv8, uint64_t data) +{ + int ret; + LOG_DEBUG("write DCC Low word 0x%08" PRIx32, (unsigned)data); + LOG_DEBUG("write DCC High word 0x%08" PRIx32, (unsigned)(data >> 32)); + ret = mem_ap_write_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DTRRX, data); + ret += mem_ap_write_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DTRTX, data >> 32); + return ret; +} + +static int dpmv8_read_dcc(struct armv8_common *armv8, uint32_t *data, + uint32_t *dscr_p) +{ + uint32_t dscr = DSCR_ITE; + int retval; + + if (dscr_p) + dscr = *dscr_p; + + /* Wait for DTRRXfull */ + long long then = timeval_ms(); + while ((dscr & DSCR_DTR_TX_FULL) == 0) { + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DSCR, + &dscr); + if (retval != ERROR_OK) + return retval; + if (timeval_ms() > then + 1000) { + LOG_ERROR("Timeout waiting for read dcc"); + return ERROR_FAIL; + } + } + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DTRTX, + data); + if (retval != ERROR_OK) + return retval; + LOG_DEBUG("read DCC 0x%08" PRIx32, *data); + + if (dscr_p) + *dscr_p = dscr; + + return retval; +} + +static int dpmv8_read_dcc_64(struct armv8_common *armv8, uint64_t *data, + uint32_t *dscr_p) +{ + uint32_t dscr = DSCR_ITE; + uint32_t higher; + int retval; + + if (dscr_p) + dscr = *dscr_p; + + /* Wait for DTRRXfull */ + long long then = timeval_ms(); + while ((dscr & DSCR_DTR_TX_FULL) == 0) { + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DSCR, + &dscr); + if (retval != ERROR_OK) + return retval; + if (timeval_ms() > then + 1000) { + LOG_ERROR("Timeout waiting for read dcc"); + return ERROR_FAIL; + } + } + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DTRTX, + (uint32_t *)data); + if (retval != ERROR_OK) + return retval; + + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DTRRX, + &higher); + if (retval != ERROR_OK) + return retval; + + *data = *(uint32_t *)data | (uint64_t)higher << 32; + LOG_DEBUG("read DCC 0x%16.16" PRIx64, *data); + + if (dscr_p) + *dscr_p = dscr; + + return retval; +} + +static int dpmv8_dpm_prepare(struct arm_dpm *dpm) +{ + struct armv8_common *armv8 = dpm->arm->arch_info; + uint32_t dscr; + int retval; + + /* set up invariant: INSTR_COMP is set after ever DPM operation */ + long long then = timeval_ms(); + for (;; ) { + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DSCR, + &dscr); + if (retval != ERROR_OK) + return retval; + if ((dscr & DSCR_ITE) != 0) + break; + if (timeval_ms() > then + 1000) { + LOG_ERROR("Timeout waiting for dpm prepare"); + return ERROR_FAIL; + } + } + + /* this "should never happen" ... */ + if (dscr & DSCR_DTR_RX_FULL) { + LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr); + /* Clear DCCRX */ + retval = mem_ap_read_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DTRRX, &dscr); + if (retval != ERROR_OK) + return retval; + + /* Clear sticky error */ + retval = mem_ap_write_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); + if (retval != ERROR_OK) + return retval; + } + + return retval; +} + +static int dpmv8_dpm_finish(struct arm_dpm *dpm) +{ + /* REVISIT what could be done here? */ + return ERROR_OK; +} + +static int dpmv8_exec_opcode(struct arm_dpm *dpm, + uint32_t opcode, uint32_t *p_dscr) +{ + struct armv8_common *armv8 = dpm->arm->arch_info; + uint32_t dscr = DSCR_ITE; + int retval; + + LOG_DEBUG("exec opcode 0x%08" PRIx32, opcode); + + if (p_dscr) + dscr = *p_dscr; + + /* Wait for InstrCompl bit to be set */ + long long then = timeval_ms(); + while ((dscr & DSCR_ITE) == 0) { + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); + if (retval != ERROR_OK) { + LOG_ERROR("Could not read DSCR register, opcode = 0x%08" PRIx32, opcode); + return retval; + } + if (timeval_ms() > then + 1000) { + LOG_ERROR("Timeout waiting for aarch64_exec_opcode"); + return ERROR_FAIL; + } + } + + retval = mem_ap_write_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_ITR, opcode); + if (retval != ERROR_OK) + return retval; + + then = timeval_ms(); + do { + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); + if (retval != ERROR_OK) { + LOG_ERROR("Could not read DSCR register"); + return retval; + } + if (timeval_ms() > then + 1000) { + LOG_ERROR("Timeout waiting for aarch64_exec_opcode"); + return ERROR_FAIL; + } + } while ((dscr & DSCR_ITE) == 0); /* Wait for InstrCompl bit to be set */ + + if (p_dscr) + *p_dscr = dscr; + + return retval; +} + +static int dpmv8_instr_execute(struct arm_dpm *dpm, uint32_t opcode) +{ + return dpmv8_exec_opcode(dpm, opcode, NULL); +} + +static int dpmv8_instr_write_data_dcc(struct arm_dpm *dpm, + uint32_t opcode, uint32_t data) +{ + struct armv8_common *armv8 = dpm->arm->arch_info; + int retval; + + retval = dpmv8_write_dcc(armv8, data); + if (retval != ERROR_OK) + return retval; + + return dpmv8_exec_opcode(dpm, opcode, 0); +} + +static int dpmv8_instr_write_data_dcc_64(struct arm_dpm *dpm, + uint32_t opcode, uint64_t data) +{ + struct armv8_common *armv8 = dpm->arm->arch_info; + int retval; + + retval = dpmv8_write_dcc_64(armv8, data); + if (retval != ERROR_OK) + return retval; + + return dpmv8_exec_opcode(dpm, opcode, 0); +} + +static int dpmv8_instr_write_data_r0(struct arm_dpm *dpm, + uint32_t opcode, uint32_t data) +{ + struct armv8_common *armv8 = dpm->arm->arch_info; + uint32_t dscr = DSCR_ITE; + int retval; + + retval = dpmv8_write_dcc(armv8, data); + if (retval != ERROR_OK) + return retval; + + retval = dpmv8_exec_opcode(dpm, armv8_opcode(armv8, READ_REG_DTRRX), &dscr); + if (retval != ERROR_OK) + return retval; + + /* then the opcode, taking data from R0 */ + return dpmv8_exec_opcode(dpm, opcode, &dscr); +} + +static int dpmv8_instr_write_data_r0_64(struct arm_dpm *dpm, + uint32_t opcode, uint64_t data) +{ + struct armv8_common *armv8 = dpm->arm->arch_info; + uint32_t dscr = DSCR_ITE; + int retval; + + retval = dpmv8_write_dcc_64(armv8, data); + if (retval != ERROR_OK) + return retval; + + retval = dpmv8_exec_opcode(dpm, ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), &dscr); + if (retval != ERROR_OK) + return retval; + + /* then the opcode, taking data from R0 */ + return dpmv8_exec_opcode(dpm, opcode, &dscr); +} + +static int dpmv8_instr_cpsr_sync(struct arm_dpm *dpm) +{ + struct armv8_common *armv8 = dpm->arm->arch_info; + /* "Prefetch flush" after modifying execution status in CPSR */ + return dpmv8_exec_opcode(dpm, armv8_opcode(armv8, ARMV8_OPC_DSB_SY), NULL); +} + +static int dpmv8_instr_read_data_dcc(struct arm_dpm *dpm, + uint32_t opcode, uint32_t *data) +{ + struct armv8_common *armv8 = dpm->arm->arch_info; + uint32_t dscr = DSCR_ITE; + int retval; + + /* the opcode, writing data to DCC */ + retval = dpmv8_exec_opcode(dpm, opcode, &dscr); + if (retval != ERROR_OK) + return retval; + + return dpmv8_read_dcc(armv8, data, &dscr); +} + +static int dpmv8_instr_read_data_dcc_64(struct arm_dpm *dpm, + uint32_t opcode, uint64_t *data) +{ + struct armv8_common *armv8 = dpm->arm->arch_info; + uint32_t dscr = DSCR_ITE; + int retval; + + /* the opcode, writing data to DCC */ + retval = dpmv8_exec_opcode(dpm, opcode, &dscr); + if (retval != ERROR_OK) + return retval; + + return dpmv8_read_dcc_64(armv8, data, &dscr); +} + +static int dpmv8_instr_read_data_r0(struct arm_dpm *dpm, + uint32_t opcode, uint32_t *data) +{ + struct armv8_common *armv8 = dpm->arm->arch_info; + uint32_t dscr = DSCR_ITE; + int retval; + + /* the opcode, writing data to R0 */ + retval = dpmv8_exec_opcode(dpm, opcode, &dscr); + if (retval != ERROR_OK) + return retval; + + /* write R0 to DCC */ + retval = dpmv8_exec_opcode(dpm, armv8_opcode(armv8, WRITE_REG_DTRTX), &dscr); + if (retval != ERROR_OK) + return retval; + + return dpmv8_read_dcc(armv8, data, &dscr); +} + +static int dpmv8_instr_read_data_r0_64(struct arm_dpm *dpm, + uint32_t opcode, uint64_t *data) +{ + struct armv8_common *armv8 = dpm->arm->arch_info; + uint32_t dscr = DSCR_ITE; + int retval; + + /* the opcode, writing data to R0 */ + retval = dpmv8_exec_opcode(dpm, opcode, &dscr); + if (retval != ERROR_OK) + return retval; + + /* write R0 to DCC */ + retval = dpmv8_exec_opcode(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 0), &dscr); + if (retval != ERROR_OK) + return retval; + + return dpmv8_read_dcc_64(armv8, data, &dscr); +} + +#if 0 +static int dpmv8_bpwp_enable(struct arm_dpm *dpm, unsigned index_t, + target_addr_t addr, uint32_t control) +{ + struct armv8_common *armv8 = dpm->arm->arch_info; + uint32_t vr = armv8->debug_base; + uint32_t cr = armv8->debug_base; + int retval; + + switch (index_t) { + case 0 ... 15: /* breakpoints */ + vr += CPUV8_DBG_BVR_BASE; + cr += CPUV8_DBG_BCR_BASE; + break; + case 16 ... 31: /* watchpoints */ + vr += CPUV8_DBG_WVR_BASE; + cr += CPUV8_DBG_WCR_BASE; + index_t -= 16; + break; + default: + return ERROR_FAIL; + } + vr += 16 * index_t; + cr += 16 * index_t; + + LOG_DEBUG("A8: bpwp enable, vr %08x cr %08x", + (unsigned) vr, (unsigned) cr); + + retval = mem_ap_write_atomic_u32(armv8->debug_ap, vr, addr); + if (retval != ERROR_OK) + return retval; + return mem_ap_write_atomic_u32(armv8->debug_ap, cr, control); +} +#endif + +static int dpmv8_bpwp_disable(struct arm_dpm *dpm, unsigned index_t) +{ + struct armv8_common *armv8 = dpm->arm->arch_info; + uint32_t cr; + + switch (index_t) { + case 0 ... 15: + cr = armv8->debug_base + CPUV8_DBG_BCR_BASE; + break; + case 16 ... 31: + cr = armv8->debug_base + CPUV8_DBG_WCR_BASE; + index_t -= 16; + break; + default: + return ERROR_FAIL; + } + cr += 16 * index_t; + + LOG_DEBUG("A: bpwp disable, cr %08x", (unsigned) cr); + + /* clear control register */ + return mem_ap_write_atomic_u32(armv8->debug_ap, cr, 0); +} + /* * Coprocessor support */ @@ -1061,6 +1467,27 @@ int armv8_dpm_setup(struct arm_dpm *dpm) arm->mcr = dpmv8_mcr; arm->mrs = dpmv8_mrs; arm->msr = dpmv8_msr; + + dpm->prepare = dpmv8_dpm_prepare; + dpm->finish = dpmv8_dpm_finish; + + dpm->instr_execute = dpmv8_instr_execute; + dpm->instr_write_data_dcc = dpmv8_instr_write_data_dcc; + dpm->instr_write_data_dcc_64 = dpmv8_instr_write_data_dcc_64; + dpm->instr_write_data_r0 = dpmv8_instr_write_data_r0; + dpm->instr_write_data_r0_64 = dpmv8_instr_write_data_r0_64; + dpm->instr_cpsr_sync = dpmv8_instr_cpsr_sync; + + dpm->instr_read_data_dcc = dpmv8_instr_read_data_dcc; + dpm->instr_read_data_dcc_64 = dpmv8_instr_read_data_dcc_64; + dpm->instr_read_data_r0 = dpmv8_instr_read_data_r0; + dpm->instr_read_data_r0_64 = dpmv8_instr_read_data_r0_64; + + dpm->arm_reg_current = armv8_reg_current; + +/* dpm->bpwp_enable = dpmv8_bpwp_enable; */ + dpm->bpwp_disable = dpmv8_bpwp_disable; + /* breakpoint setup -- optional until it works everywhere */ if (!target->type->add_breakpoint) { target->type->add_breakpoint = dpmv8_add_breakpoint; -- cgit v1.1 From b69750fd0ded4ee19861673106761627d88734e4 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 22 Sep 2016 21:29:42 +0200 Subject: aarch64: armv8 cache functions update Update cache identification to match functionality present in armv7a_cache.c Change-Id: I2dc4bee80f5a22b8728334d40331c183d1406f27 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 6 +- src/target/armv8.c | 301 ++++++--------------------------------------- src/target/armv8.h | 17 ++- src/target/armv8_cache.c | 299 +++++++++++++++++++++++++++++++++++++++++++- src/target/armv8_opcodes.h | 1 + 5 files changed, 353 insertions(+), 271 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 1d2abc7..05abe6b 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -735,8 +735,10 @@ static int aarch64_post_debug_entry(struct target *target) LOG_DEBUG("System_register: %8.8" PRIx32, aarch64->system_control_reg); aarch64->system_control_reg_curr = aarch64->system_control_reg; - if (armv8->armv8_mmu.armv8_cache.ctype == -1) - armv8_identify_cache(target); + if (armv8->armv8_mmu.armv8_cache.info == -1) { + armv8_identify_cache(armv8); + armv8_read_mpidr(armv8); + } armv8->armv8_mmu.mmu_enabled = (aarch64->system_control_reg & 0x1U) ? 1 : 0; diff --git a/src/target/armv8.c b/src/target/armv8.c index 306a06e..467c771 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -37,6 +37,8 @@ #include "target.h" #include "target_type.h" +#define __unused __attribute__((unused)) + static const char * const armv8_state_strings[] = { "AArch32", "Thumb", "Jazelle", "ThumbEE", "AArch64", }; @@ -208,6 +210,38 @@ static int armv8_write_core_reg(struct target *target, struct reg *r, return ERROR_OK; } #endif + +/* retrieve core id cluster id */ +int armv8_read_mpidr(struct armv8_common *armv8) +{ + int retval = ERROR_FAIL; + struct arm_dpm *dpm = armv8->arm.dpm; + uint32_t mpidr; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + + retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_MPIDR), &mpidr); + if (retval != ERROR_OK) + goto done; + if (mpidr & 1<<31) { + armv8->multi_processor_system = (mpidr >> 30) & 1; + armv8->cluster_id = (mpidr >> 8) & 0xf; + armv8->cpu_id = mpidr & 0x3; + LOG_INFO("%s cluster %x core %x %s", target_name(armv8->arm.target), + armv8->cluster_id, + armv8->cpu_id, + armv8->multi_processor_system == 0 ? "multi core" : "mono core"); + + } else + LOG_ERROR("mpdir not in multiprocessor format"); + +done: + dpm->finish(dpm); + return retval; +} + /** * Configures host-side ARM records to reflect the specified CPSR. * Later, code can use arm_reg_current() to map register numbers @@ -368,7 +402,7 @@ static uint8_t armv8_pa_size(uint32_t ps) return ret; } -static int armv8_read_ttbcr32(struct target *target) +static __unused int armv8_read_ttbcr32(struct target *target) { struct armv8_common *armv8 = target_to_armv8(target); struct arm_dpm *dpm = armv8->arm.dpm; @@ -528,103 +562,10 @@ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, return ERROR_OK; } -static int armv8_handle_inner_cache_info_command(struct command_context *cmd_ctx, - struct armv8_cache_common *armv8_cache) -{ - if (armv8_cache->ctype == -1) { - command_print(cmd_ctx, "cache not yet identified"); - return ERROR_OK; - } - - command_print(cmd_ctx, - "D-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes", - armv8_cache->d_u_size.linelen, - armv8_cache->d_u_size.associativity, - armv8_cache->d_u_size.nsets, - armv8_cache->d_u_size.cachesize); - - command_print(cmd_ctx, - "I-Cache: linelen %" PRIi32 ", associativity %" PRIi32 ", nsets %" PRIi32 ", cachesize %" PRId32 " KBytes", - armv8_cache->i_size.linelen, - armv8_cache->i_size.associativity, - armv8_cache->i_size.nsets, - armv8_cache->i_size.cachesize); - - return ERROR_OK; -} - -static int _armv8_flush_all_data(struct target *target) -{ - struct armv8_common *armv8 = target_to_armv8(target); - struct arm_dpm *dpm = armv8->arm.dpm; - struct armv8_cachesize *d_u_size = - &(armv8->armv8_mmu.armv8_cache.d_u_size); - int32_t c_way, c_index = d_u_size->index; - int retval; - /* check that cache data is on at target halt */ - if (!armv8->armv8_mmu.armv8_cache.d_u_cache_enabled) { - LOG_INFO("flushed not performed :cache not on at target halt"); - return ERROR_OK; - } - retval = dpm->prepare(dpm); - if (retval != ERROR_OK) - goto done; - do { - c_way = d_u_size->way; - do { - uint32_t value = (c_index << d_u_size->index_shift) - | (c_way << d_u_size->way_shift); - /* DCCISW */ - /* LOG_INFO ("%d %d %x",c_way,c_index,value); */ - retval = dpm->instr_write_data_r0(dpm, - ARMV8_MSR_GP(SYSTEM_DCCISW, 0), - value); - if (retval != ERROR_OK) - goto done; - c_way -= 1; - } while (c_way >= 0); - c_index -= 1; - } while (c_index >= 0); - return retval; -done: - LOG_ERROR("flushed failed"); - dpm->finish(dpm); - return retval; -} - -static int armv8_flush_all_data(struct target *target) -{ - int retval = ERROR_FAIL; - /* check that armv8_cache is correctly identify */ - struct armv8_common *armv8 = target_to_armv8(target); - if (armv8->armv8_mmu.armv8_cache.ctype == -1) { - LOG_ERROR("trying to flush un-identified cache"); - return retval; - } - - if (target->smp) { - /* look if all the other target have been flushed in order to flush level - * 2 */ - struct target_list *head; - struct target *curr; - head = target->head; - while (head != (struct target_list *)NULL) { - curr = head->target; - if (curr->state == TARGET_HALTED) { - LOG_INFO("Wait flushing data l1 on core %" PRId32, curr->coreid); - retval = _armv8_flush_all_data(curr); - } - head = head->next; - } - } else - retval = _armv8_flush_all_data(target); - return retval; -} - int armv8_handle_cache_info_command(struct command_context *cmd_ctx, struct armv8_cache_common *armv8_cache) { - if (armv8_cache->ctype == -1) { + if (armv8_cache->info == -1) { command_print(cmd_ctx, "cache not yet identified"); return ERROR_OK; } @@ -634,174 +575,6 @@ int armv8_handle_cache_info_command(struct command_context *cmd_ctx, return ERROR_OK; } -/* retrieve core id cluster id */ -static int armv8_read_mpidr(struct target *target) -{ - int retval = ERROR_FAIL; - struct armv8_common *armv8 = target_to_armv8(target); - struct arm_dpm *dpm = armv8->arm.dpm; - uint32_t mpidr; - - retval = dpm->prepare(dpm); - if (retval != ERROR_OK) - goto done; - /* MRC p15,0,,c0,c0,5; read Multiprocessor ID register*/ - - retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_MPIDR), &mpidr); - if (retval != ERROR_OK) - goto done; - if (mpidr & 1<<31) { - armv8->multi_processor_system = (mpidr >> 30) & 1; - armv8->cluster_id = (mpidr >> 8) & 0xf; - armv8->cpu_id = mpidr & 0x3; - LOG_INFO("%s cluster %x core %x %s", target_name(target), - armv8->cluster_id, - armv8->cpu_id, - armv8->multi_processor_system == 0 ? "multi core" : "mono core"); - - } else - LOG_ERROR("mpdir not in multiprocessor format"); - -done: - dpm->finish(dpm); - return retval; - - -} - -int armv8_identify_cache(struct target *target) -{ - /* read cache descriptor */ - int retval = ERROR_FAIL; - struct armv8_common *armv8 = target_to_armv8(target); - struct arm_dpm *dpm = armv8->arm.dpm; - uint32_t cache_selected, clidr; - uint32_t cache_i_reg, cache_d_reg; - struct armv8_cache_common *cache = &(armv8->armv8_mmu.armv8_cache); - int is_aarch64 = armv8->arm.core_state == ARM_STATE_AARCH64; - - retval = is_aarch64 ? armv8_read_ttbcr(target) : armv8_read_ttbcr32(target); - if (retval != ERROR_OK) - return retval; - - retval = dpm->prepare(dpm); - if (retval != ERROR_OK) - goto done; - - /* retrieve CLIDR */ - retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_CLIDR), &clidr); - if (retval != ERROR_OK) - goto done; - - clidr = (clidr & 0x7000000) >> 23; - LOG_INFO("number of cache level %" PRIx32, (uint32_t)(clidr / 2)); - if ((clidr / 2) > 1) { - /* FIXME not supported present in cortex A8 and later */ - /* in cortex A7, A15 */ - LOG_ERROR("cache l2 present :not supported"); - } - /* retrieve selected cache*/ - retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_CSSELR), &cache_selected); - if (retval != ERROR_OK) - goto done; - - /* select instruction cache - * [0] : 1 instruction cache selection , 0 data cache selection */ - retval = dpm->instr_write_data_r0(dpm, armv8_opcode(armv8, WRITE_REG_CSSELR), 1); - if (retval != ERROR_OK) - goto done; - - /* read CCSIDR - * MRC P15,1,,C0, C0,0 ;on cortex A9 read CCSIDR - * [2:0] line size 001 eight word per line - * [27:13] NumSet 0x7f 16KB, 0xff 32Kbytes, 0x1ff 64Kbytes */ - retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_CCSIDR), &cache_i_reg); - if (retval != ERROR_OK) - goto done; - - /* select data cache*/ - retval = dpm->instr_write_data_r0(dpm, armv8_opcode(armv8, WRITE_REG_CSSELR), 0); - if (retval != ERROR_OK) - goto done; - - retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_CCSIDR), &cache_d_reg); - if (retval != ERROR_OK) - goto done; - - /* restore selected cache */ - dpm->instr_write_data_r0(dpm, armv8_opcode(armv8, WRITE_REG_CSSELR), cache_selected); - if (retval != ERROR_OK) - goto done; - dpm->finish(dpm); - - /* put fake type */ - cache->d_u_size.linelen = 16 << (cache_d_reg & 0x7); - cache->d_u_size.cachesize = (((cache_d_reg >> 13) & 0x7fff)+1)/8; - cache->d_u_size.nsets = (cache_d_reg >> 13) & 0x7fff; - cache->d_u_size.associativity = ((cache_d_reg >> 3) & 0x3ff) + 1; - /* compute info for set way operation on cache */ - cache->d_u_size.index_shift = (cache_d_reg & 0x7) + 4; - cache->d_u_size.index = (cache_d_reg >> 13) & 0x7fff; - cache->d_u_size.way = ((cache_d_reg >> 3) & 0x3ff); - cache->d_u_size.way_shift = cache->d_u_size.way + 1; - { - int i = 0; - while (((cache->d_u_size.way_shift >> i) & 1) != 1) - i++; - cache->d_u_size.way_shift = 32-i; - } -#if 0 - LOG_INFO("data cache index %d << %d, way %d << %d", - cache->d_u_size.index, cache->d_u_size.index_shift, - cache->d_u_size.way, - cache->d_u_size.way_shift); - - LOG_INFO("data cache %d bytes %d KBytes asso %d ways", - cache->d_u_size.linelen, - cache->d_u_size.cachesize, - cache->d_u_size.associativity); -#endif - cache->i_size.linelen = 16 << (cache_i_reg & 0x7); - cache->i_size.associativity = ((cache_i_reg >> 3) & 0x3ff) + 1; - cache->i_size.nsets = (cache_i_reg >> 13) & 0x7fff; - cache->i_size.cachesize = (((cache_i_reg >> 13) & 0x7fff)+1)/8; - /* compute info for set way operation on cache */ - cache->i_size.index_shift = (cache_i_reg & 0x7) + 4; - cache->i_size.index = (cache_i_reg >> 13) & 0x7fff; - cache->i_size.way = ((cache_i_reg >> 3) & 0x3ff); - cache->i_size.way_shift = cache->i_size.way + 1; - { - int i = 0; - while (((cache->i_size.way_shift >> i) & 1) != 1) - i++; - cache->i_size.way_shift = 32-i; - } -#if 0 - LOG_INFO("instruction cache index %d << %d, way %d << %d", - cache->i_size.index, cache->i_size.index_shift, - cache->i_size.way, cache->i_size.way_shift); - - LOG_INFO("instruction cache %d bytes %d KBytes asso %d ways", - cache->i_size.linelen, - cache->i_size.cachesize, - cache->i_size.associativity); -#endif - /* if no l2 cache initialize l1 data cache flush function function */ - if (armv8->armv8_mmu.armv8_cache.flush_all_data_cache == NULL) { - armv8->armv8_mmu.armv8_cache.display_cache_info = - armv8_handle_inner_cache_info_command; - armv8->armv8_mmu.armv8_cache.flush_all_data_cache = - armv8_flush_all_data; - } - armv8->armv8_mmu.armv8_cache.ctype = 0; - -done: - dpm->finish(dpm); - armv8_read_mpidr(target); - return retval; - -} - int armv8_init_arch_info(struct target *target, struct armv8_common *armv8) { struct arm *arm = &armv8->arm; @@ -818,7 +591,7 @@ int armv8_init_arch_info(struct target *target, struct armv8_common *armv8) #endif armv8->armv8_mmu.armv8_cache.l2_cache = NULL; - armv8->armv8_mmu.armv8_cache.ctype = -1; + armv8->armv8_mmu.armv8_cache.info = -1; armv8->armv8_mmu.armv8_cache.flush_all_data_cache = NULL; armv8->armv8_mmu.armv8_cache.display_cache_info = NULL; return ERROR_OK; diff --git a/src/target/armv8.h b/src/target/armv8.h index fa3674b..2862ebd 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -97,12 +97,22 @@ struct armv8_cachesize { uint32_t way_shift; }; -struct armv8_cache_common { - int ctype; +/* information about one architecture cache at any level */ +struct armv8_arch_cache { + int ctype; /* cache type, CLIDR encoding */ struct armv8_cachesize d_u_size; /* data cache */ struct armv8_cachesize i_size; /* instruction cache */ +}; + +struct armv8_cache_common { + int info; + int loc; + uint32_t iminline; + uint32_t dminline; + struct armv8_arch_cache arch[6]; /* cache info, L1 - L7 */ int i_cache_enabled; int d_u_cache_enabled; + /* l2 external unified cache if some */ void *l2_cache; int (*flush_all_data_cache)(struct target *target); @@ -249,7 +259,8 @@ target_to_armv8(struct target *target) #define PAGE_SIZE_4KB_TRBBASE_MASK 0xFFFFFFFFF000 int armv8_arch_state(struct target *target); -int armv8_identify_cache(struct target *target); +int armv8_read_mpidr(struct armv8_common *armv8); +int armv8_identify_cache(struct armv8_common *armv8); int armv8_init_arch_info(struct target *target, struct armv8_common *armv8); int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, target_addr_t *val, int meminfo); diff --git a/src/target/armv8_cache.c b/src/target/armv8_cache.c index fb18804..f496c3c 100644 --- a/src/target/armv8_cache.c +++ b/src/target/armv8_cache.c @@ -24,6 +24,11 @@ #include "armv8_dpm.h" #include "armv8_opcodes.h" +/* CLIDR cache types */ +#define CACHE_LEVEL_HAS_UNIFIED_CACHE 0x4 +#define CACHE_LEVEL_HAS_D_CACHE 0x2 +#define CACHE_LEVEL_HAS_I_CACHE 0x1 + static int armv8_d_cache_sanity_check(struct armv8_common *armv8) { struct armv8_cache_common *armv8_cache = &armv8->armv8_mmu.armv8_cache; @@ -44,11 +49,72 @@ static int armv8_i_cache_sanity_check(struct armv8_common *armv8) return ERROR_TARGET_INVALID; } +static int armv8_cache_d_inner_flush_level(struct arm_dpm *dpm, struct armv8_cachesize *size, int cl) +{ + int retval = ERROR_OK; + int32_t c_way, c_index = size->index; + + LOG_DEBUG("cl %" PRId32, cl); + do { + c_way = size->way; + do { + uint32_t value = (c_index << size->index_shift) + | (c_way << size->way_shift) | (cl << 1); + /* + * DC CISW - Clean and invalidate data cache + * line by Set/Way. + */ + retval = dpm->instr_write_data_r0(dpm, + ARMV8_SYS(SYSTEM_DCCISW, 0), value); + if (retval != ERROR_OK) + goto done; + c_way -= 1; + } while (c_way >= 0); + c_index -= 1; + } while (c_index >= 0); + + done: + return retval; +} + +static int armv8_cache_d_inner_clean_inval_all(struct armv8_common *armv8) +{ + struct armv8_cache_common *cache = &(armv8->armv8_mmu.armv8_cache); + struct arm_dpm *dpm = armv8->arm.dpm; + int cl; + int retval; + + retval = armv8_d_cache_sanity_check(armv8); + if (retval != ERROR_OK) + return retval; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + + for (cl = 0; cl < cache->loc; cl++) { + /* skip i-only caches */ + if (cache->arch[cl].ctype < CACHE_LEVEL_HAS_D_CACHE) + continue; + + armv8_cache_d_inner_flush_level(dpm, &cache->arch[cl].d_u_size, cl); + } + + retval = dpm->finish(dpm); + return retval; + +done: + LOG_ERROR("clean invalidate failed"); + dpm->finish(dpm); + + return retval; +} + int armv8_cache_d_inner_flush_virt(struct armv8_common *armv8, target_addr_t va, size_t size) { struct arm_dpm *dpm = armv8->arm.dpm; struct armv8_cache_common *armv8_cache = &armv8->armv8_mmu.armv8_cache; - uint64_t linelen = armv8_cache->d_u_size.linelen; + uint64_t linelen = armv8_cache->dminline; target_addr_t va_line, va_end; int retval; @@ -87,7 +153,7 @@ int armv8_cache_i_inner_inval_virt(struct armv8_common *armv8, target_addr_t va, { struct arm_dpm *dpm = armv8->arm.dpm; struct armv8_cache_common *armv8_cache = &armv8->armv8_mmu.armv8_cache; - uint64_t linelen = armv8_cache->i_size.linelen; + uint64_t linelen = armv8_cache->iminline; target_addr_t va_line, va_end; int retval; @@ -120,3 +186,232 @@ done: return retval; } + +static int armv8_handle_inner_cache_info_command(struct command_context *cmd_ctx, + struct armv8_cache_common *armv8_cache) +{ + int cl; + + if (armv8_cache->info == -1) { + command_print(cmd_ctx, "cache not yet identified"); + return ERROR_OK; + } + + for (cl = 0; cl < armv8_cache->loc; cl++) { + struct armv8_arch_cache *arch = &(armv8_cache->arch[cl]); + + if (arch->ctype & 1) { + command_print(cmd_ctx, + "L%d I-Cache: linelen %" PRIi32 + ", associativity %" PRIi32 + ", nsets %" PRIi32 + ", cachesize %" PRId32 " KBytes", + cl+1, + arch->i_size.linelen, + arch->i_size.associativity, + arch->i_size.nsets, + arch->i_size.cachesize); + } + + if (arch->ctype >= 2) { + command_print(cmd_ctx, + "L%d D-Cache: linelen %" PRIi32 + ", associativity %" PRIi32 + ", nsets %" PRIi32 + ", cachesize %" PRId32 " KBytes", + cl+1, + arch->d_u_size.linelen, + arch->d_u_size.associativity, + arch->d_u_size.nsets, + arch->d_u_size.cachesize); + } + } + + return ERROR_OK; +} + +static int _armv8_flush_all_data(struct target *target) +{ + return armv8_cache_d_inner_clean_inval_all(target_to_armv8(target)); +} + +static int armv8_flush_all_data(struct target *target) +{ + int retval = ERROR_FAIL; + /* check that armv8_cache is correctly identify */ + struct armv8_common *armv8 = target_to_armv8(target); + if (armv8->armv8_mmu.armv8_cache.info == -1) { + LOG_ERROR("trying to flush un-identified cache"); + return retval; + } + + if (target->smp) { + /* look if all the other target have been flushed in order to flush level + * 2 */ + struct target_list *head; + struct target *curr; + head = target->head; + while (head != (struct target_list *)NULL) { + curr = head->target; + if (curr->state == TARGET_HALTED) { + LOG_INFO("Wait flushing data l1 on core %" PRId32, curr->coreid); + retval = _armv8_flush_all_data(curr); + } + head = head->next; + } + } else + retval = _armv8_flush_all_data(target); + return retval; +} + +static int get_cache_info(struct arm_dpm *dpm, int cl, int ct, uint32_t *cache_reg) +{ + int retval = ERROR_OK; + + /* select cache level */ + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MSR_GP(SYSTEM_CSSELR, 0), + (cl << 1) | (ct == 1 ? 1 : 0)); + if (retval != ERROR_OK) + goto done; + + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS(SYSTEM_CCSIDR, 0), + cache_reg); + done: + return retval; +} + +static struct armv8_cachesize decode_cache_reg(uint32_t cache_reg) +{ + struct armv8_cachesize size; + int i = 0; + + size.linelen = 16 << (cache_reg & 0x7); + size.associativity = ((cache_reg >> 3) & 0x3ff) + 1; + size.nsets = ((cache_reg >> 13) & 0x7fff) + 1; + size.cachesize = size.linelen * size.associativity * size.nsets / 1024; + + /* compute info for set way operation on cache */ + size.index_shift = (cache_reg & 0x7) + 4; + size.index = (cache_reg >> 13) & 0x7fff; + size.way = ((cache_reg >> 3) & 0x3ff); + + while (((size.way << i) & 0x80000000) == 0) + i++; + size.way_shift = i; + + return size; +} + +int armv8_identify_cache(struct armv8_common *armv8) +{ + /* read cache descriptor */ + int retval = ERROR_FAIL; + struct arm_dpm *dpm = armv8->arm.dpm; + uint32_t csselr, clidr, ctr; + uint32_t cache_reg; + int cl, ctype; + struct armv8_cache_common *cache = &(armv8->armv8_mmu.armv8_cache); + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + goto done; + + /* retrieve CTR */ + retval = dpm->instr_read_data_r0(dpm, ARMV8_MRS(SYSTEM_CTR, 0), &ctr); + if (retval != ERROR_OK) + goto done; + + cache->iminline = 4UL << (ctr & 0xf); + cache->dminline = 4UL << ((ctr & 0xf0000) >> 16); + LOG_DEBUG("ctr %" PRIx32 " ctr.iminline %" PRId32 " ctr.dminline %" PRId32, + ctr, cache->iminline, cache->dminline); + + /* retrieve CLIDR */ + retval = dpm->instr_read_data_r0(dpm, ARMV8_MRS(SYSTEM_CLIDR, 0), &clidr); + if (retval != ERROR_OK) + goto done; + + cache->loc = (clidr & 0x7000000) >> 24; + LOG_DEBUG("Number of cache levels to PoC %" PRId32, cache->loc); + + /* retrieve selected cache for later restore + * MRC p15, 2,, c0, c0, 0; Read CSSELR */ + retval = dpm->instr_read_data_r0(dpm, ARMV8_MRS(SYSTEM_CSSELR, 0), &csselr); + if (retval != ERROR_OK) + goto done; + + /* retrieve all available inner caches */ + for (cl = 0; cl < cache->loc; clidr >>= 3, cl++) { + + /* isolate cache type at current level */ + ctype = clidr & 7; + + /* skip reserved values */ + if (ctype > CACHE_LEVEL_HAS_UNIFIED_CACHE) + continue; + + /* separate d or unified d/i cache at this level ? */ + if (ctype & (CACHE_LEVEL_HAS_UNIFIED_CACHE | CACHE_LEVEL_HAS_D_CACHE)) { + /* retrieve d-cache info */ + retval = get_cache_info(dpm, cl, 0, &cache_reg); + if (retval != ERROR_OK) + goto done; + cache->arch[cl].d_u_size = decode_cache_reg(cache_reg); + + LOG_DEBUG("data/unified cache index %d << %d, way %d << %d", + cache->arch[cl].d_u_size.index, + cache->arch[cl].d_u_size.index_shift, + cache->arch[cl].d_u_size.way, + cache->arch[cl].d_u_size.way_shift); + + LOG_DEBUG("cacheline %d bytes %d KBytes asso %d ways", + cache->arch[cl].d_u_size.linelen, + cache->arch[cl].d_u_size.cachesize, + cache->arch[cl].d_u_size.associativity); + } + + /* separate i-cache at this level ? */ + if (ctype & CACHE_LEVEL_HAS_I_CACHE) { + /* retrieve i-cache info */ + retval = get_cache_info(dpm, cl, 1, &cache_reg); + if (retval != ERROR_OK) + goto done; + cache->arch[cl].i_size = decode_cache_reg(cache_reg); + + LOG_DEBUG("instruction cache index %d << %d, way %d << %d", + cache->arch[cl].i_size.index, + cache->arch[cl].i_size.index_shift, + cache->arch[cl].i_size.way, + cache->arch[cl].i_size.way_shift); + + LOG_DEBUG("cacheline %d bytes %d KBytes asso %d ways", + cache->arch[cl].i_size.linelen, + cache->arch[cl].i_size.cachesize, + cache->arch[cl].i_size.associativity); + } + + cache->arch[cl].ctype = ctype; + } + + /* restore selected cache */ + dpm->instr_write_data_r0(dpm, ARMV8_MSR_GP(SYSTEM_CSSELR, 0), csselr); + if (retval != ERROR_OK) + goto done; + + armv8->armv8_mmu.armv8_cache.info = 1; + + /* if no l2 cache initialize l1 data cache flush function function */ + if (armv8->armv8_mmu.armv8_cache.flush_all_data_cache == NULL) { + armv8->armv8_mmu.armv8_cache.display_cache_info = + armv8_handle_inner_cache_info_command; + armv8->armv8_mmu.armv8_cache.flush_all_data_cache = + armv8_flush_all_data; + } + +done: + dpm->finish(dpm); + return retval; + +} diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index 9f5ebf8..51dc15a 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -77,6 +77,7 @@ #define SYSTEM_CLIDR 0b1100100000000001 #define SYSTEM_CSSELR 0b1101000000000000 #define SYSTEM_CTYPE 0b1101100000000001 +#define SYSTEM_CTR 0b1101100000000001 #define SYSTEM_DCCISW 0b0100001111110010 #define SYSTEM_DCCSW 0b0100001111010010 -- cgit v1.1 From 40ce7374d3d6c495834b41f0a98f0bd6cb620dc4 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Mon, 26 Sep 2016 11:08:11 +0200 Subject: aarch64: remove bogus os_border calculation The artificial "os_border" doesn't exist in aarch64 state and is wrong for aarch32 state as well. Remove it. Change-Id: I7c673a1404b03aa78dbd505e115fa3a93f7ca05f Signed-off-by: Matthias Welwarsky --- src/target/armv8.c | 40 +++++----------------------------------- src/target/armv8.h | 1 - 2 files changed, 5 insertions(+), 36 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 467c771..d644963 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -441,7 +441,7 @@ done: return retval; } -static int armv8_read_ttbcr(struct target *target) +static __unused int armv8_read_ttbcr(struct target *target) { struct armv8_common *armv8 = target_to_armv8(target); struct arm_dpm *dpm = armv8->arm.dpm; @@ -511,48 +511,18 @@ static int armv8_read_ttbcr(struct target *target) if (retval != ERROR_OK) goto done; -#if 0 - LOG_INFO("ttb1 %s ,ttb0_mask %llx", - armv8->armv8_mmu.ttbr1_used ? "used" : "not used", - armv8->armv8_mmu.ttbr0_mask); -#endif - if (armv8->armv8_mmu.ttbr1_used == 1) { - LOG_INFO("TTBR0 access above %" PRIx64, - (uint64_t)(armv8->armv8_mmu.ttbr0_mask)); - armv8->armv8_mmu.os_border = armv8->armv8_mmu.ttbr0_mask; - } else { - /* fix me , default is hard coded LINUX border */ - armv8->armv8_mmu.os_border = 0xc0000000; - } + if (armv8->armv8_mmu.ttbr1_used == 1) + LOG_INFO("TTBR0 access above %" PRIx64, (uint64_t)(armv8->armv8_mmu.ttbr0_mask)); + done: dpm->finish(dpm); return retval; } -static int armv8_4K_translate(struct target *target, target_addr_t va, target_addr_t *val) -{ - LOG_ERROR("4K page Address translation need to add"); - return ERROR_FAIL; -} - - /* method adapted to cortex A : reused arm v4 v5 method*/ int armv8_mmu_translate_va(struct target *target, target_addr_t va, target_addr_t *val) { - int retval = ERROR_FAIL; - struct armv8_common *armv8 = target_to_armv8(target); - struct arm_dpm *dpm = armv8->arm.dpm; - - retval = dpm->prepare(dpm); - retval += armv8_read_ttbcr(target); - if (retval != ERROR_OK) - goto done; - if (armv8->page_size == 0) - return armv8_4K_translate(target, va, val); - -done: - dpm->finish(dpm); - return ERROR_FAIL; + return ERROR_OK; } /* V8 method VA TO PA */ diff --git a/src/target/armv8.h b/src/target/armv8.h index 2862ebd..07e3b41 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -124,7 +124,6 @@ struct armv8_mmu_common { /* following field mmu working way */ int32_t ttbr1_used; /* -1 not initialized, 0 no ttbr1 1 ttbr1 used and */ uint64_t ttbr0_mask;/* masked to be used */ - uint32_t os_border; uint32_t ttbcr; /* cache for ttbcr register */ uint32_t ttbr_mask[2]; -- cgit v1.1 From fc3ce94bba5420402ea11f37d2113b0b9e380bd0 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Mon, 26 Sep 2016 11:44:25 +0200 Subject: aarch64: slightly simplify breakpoint set function Set HDE bit through helper function instead of manual mem_ap access. Change-Id: I68c157870f3f3c47a875d425ade6e975d8075424 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 05abe6b..f818344 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -861,7 +861,6 @@ static int aarch64_set_breakpoint(struct target *target, struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = &aarch64->armv8_common; struct aarch64_brp *brp_list = aarch64->brp_list; - uint32_t dscr; if (breakpoint->set) { LOG_WARNING("breakpoint already set"); @@ -940,12 +939,8 @@ static int aarch64_set_breakpoint(struct target *target, breakpoint->set = 0x11; /* Any nice value but 0 */ } - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, &dscr); /* Ensure that halting debug mode is enable */ - dscr = dscr | DSCR_HDE; - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, dscr); + retval = aarch64_set_dscr_bits(target, DSCR_HDE, DSCR_HDE); if (retval != ERROR_OK) { LOG_DEBUG("Failed to set DSCR.HDE"); return retval; -- cgit v1.1 From 2b56f4f656e11f50d124e13e6d66a967ca45d373 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 6 Oct 2016 15:05:53 +0200 Subject: aarch64: provide virt2phys command Use AT commands to translate virtual to physical addresses based on current MMU configuration. Change-Id: I1bbd7d674c435541b617b17022fa9f7f0f01bdab Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 2 +- src/target/armv8.c | 78 +++++++++++++++++++++++++++++++++++++++++++++- src/target/armv8.h | 4 +++ src/target/armv8_opcodes.h | 7 +++++ 4 files changed, 89 insertions(+), 2 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index f818344..3510db2 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2011,7 +2011,7 @@ static int aarch64_mmu(struct target *target, int *enabled) static int aarch64_virt2phys(struct target *target, target_addr_t virt, target_addr_t *phys) { - return armv8_mmu_translate_va(target, virt, phys); + return armv8_mmu_translate_va_pa(target, virt, phys, 1); } COMMAND_HANDLER(aarch64_handle_cache_info_command) diff --git a/src/target/armv8.c b/src/target/armv8.c index d644963..3f3127e 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -529,7 +529,83 @@ int armv8_mmu_translate_va(struct target *target, target_addr_t va, target_addr int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, target_addr_t *val, int meminfo) { - return ERROR_OK; + struct armv8_common *armv8 = target_to_armv8(target); + struct arm *arm = target_to_arm(target); + struct arm_dpm *dpm = &armv8->dpm; + uint32_t retval; + uint32_t instr = 0; + uint64_t par; + + static const char * const shared_name[] = { + "Non-", "UNDEFINED ", "Outer ", "Inner " + }; + + static const char * const secure_name[] = { + "Secure", "Not Secure" + }; + + retval = dpm->prepare(dpm); + if (retval != ERROR_OK) + return retval; + + switch (armv8_curel_from_core_mode(arm)) { + case SYSTEM_CUREL_EL0: + instr = ARMV8_SYS(SYSTEM_ATS12E0R, 0); + /* can only execute instruction at EL2 */ + dpmv8_modeswitch(dpm, ARMV8_64_EL2T); + break; + case SYSTEM_CUREL_EL1: + instr = ARMV8_SYS(SYSTEM_ATS12E1R, 0); + /* can only execute instruction at EL2 */ + dpmv8_modeswitch(dpm, ARMV8_64_EL2T); + break; + case SYSTEM_CUREL_EL2: + instr = ARMV8_SYS(SYSTEM_ATS1E2R, 0); + break; + case SYSTEM_CUREL_EL3: + instr = ARMV8_SYS(SYSTEM_ATS1E3R, 0); + break; + + default: + break; + }; + + /* write VA to R0 and execute translation instruction */ + retval = dpm->instr_write_data_r0_64(dpm, instr, (uint64_t)va); + /* read result from PAR_EL1 */ + if (retval == ERROR_OK) + retval = dpm->instr_read_data_r0_64(dpm, ARMV8_MRS(SYSTEM_PAR_EL1, 0), &par); + + dpm->finish(dpm); + + /* switch back to saved PE mode */ + dpmv8_modeswitch(dpm, ARM_MODE_ANY); + + if (retval != ERROR_OK) + return retval; + + if (par & 1) { + LOG_ERROR("Address translation failed at stage %i, FST=%x, PTW=%i", + ((int)(par >> 9) & 1)+1, (int)(par >> 1) & 0x3f, (int)(par >> 8) & 1); + + *val = 0; + retval = ERROR_FAIL; + } else { + *val = (par & 0xFFFFFFFFF000UL) | (va & 0xFFF); + if (meminfo) { + int SH = (par >> 7) & 3; + int NS = (par >> 9) & 1; + int ATTR = (par >> 56) & 0xFF; + + char *memtype = (ATTR & 0xF0) == 0 ? "Device Memory" : "Normal Memory"; + + LOG_USER("%sshareable, %s", + shared_name[SH], secure_name[NS]); + LOG_USER("%s", memtype); + } + } + + return retval; } int armv8_handle_cache_info_command(struct command_context *cmd_ctx, diff --git a/src/target/armv8.h b/src/target/armv8.h index 07e3b41..497e482 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -270,6 +270,10 @@ int armv8_handle_cache_info_command(struct command_context *cmd_ctx, void armv8_set_cpsr(struct arm *arm, uint32_t cpsr); +static inline int armv8_curel_from_core_mode(struct arm *arm) +{ + return (arm->core_mode >> 6) & 3; +} extern const struct command_registration armv8_command_handlers[]; #endif diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index 51dc15a..41abe04 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -96,6 +96,13 @@ #define SYSTEM_TTBR0_EL3 0b1111000100000000 #define SYSTEM_TTBR1_EL1 0b1100000100000001 +/* ARMv8 address translation */ +#define SYSTEM_PAR_EL1 0b1100001110100000 +#define SYSTEM_ATS12E0R 0b0110001111000110 +#define SYSTEM_ATS12E1R 0b0110001111000100 +#define SYSTEM_ATS1E2R 0b0110001111000000 +#define SYSTEM_ATS1E3R 0b0111001111000000 + #define ARMV8_MRS_DSPSR(Rt) (0xd53b4500 | (Rt)) #define ARMV8_MSR_DSPSR(Rt) (0xd51b4500 | (Rt)) #define ARMV8_MRS_DLR(Rt) (0xd53b4520 | (Rt)) -- cgit v1.1 From 675b0170f2752c285de359f235e50a208f7f138a Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 6 Oct 2016 16:11:19 +0200 Subject: aarch64: simplify armv8_set_cpsr() Translate from cpsr value to "enum arm_mode" by shifting up 4 bits and filling the lowest nibble with 0xF. Change-Id: Ic32186104b0c29578c4f6f99e04840ab88a0017b Signed-off-by: Matthias Welwarsky --- src/target/armv8.c | 32 +++----------------------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 3f3127e..a572e23 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -282,36 +282,10 @@ void armv8_set_cpsr(struct arm *arm, uint32_t cpsr) } } arm->core_state = state; - if (arm->core_state == ARM_STATE_AARCH64) { - switch (mode) { - case SYSTEM_AAR64_MODE_EL0t: - arm->core_mode = ARMV8_64_EL0T; - break; - case SYSTEM_AAR64_MODE_EL1t: - arm->core_mode = ARMV8_64_EL0T; - break; - case SYSTEM_AAR64_MODE_EL1h: - arm->core_mode = ARMV8_64_EL1H; - break; - case SYSTEM_AAR64_MODE_EL2t: - arm->core_mode = ARMV8_64_EL2T; - break; - case SYSTEM_AAR64_MODE_EL2h: - arm->core_mode = ARMV8_64_EL2H; - break; - case SYSTEM_AAR64_MODE_EL3t: - arm->core_mode = ARMV8_64_EL3T; - break; - case SYSTEM_AAR64_MODE_EL3h: - arm->core_mode = ARMV8_64_EL3H; - break; - default: - LOG_DEBUG("unknow mode 0x%x", (unsigned) (mode)); - break; - } - } else { + if (arm->core_state == ARM_STATE_AARCH64) + arm->core_mode = (mode << 4) | 0xf; + else arm->core_mode = mode; - } LOG_DEBUG("set CPSR %#8.8x: %s mode, %s state", (unsigned) cpsr, armv8_mode_name(arm->core_mode), -- cgit v1.1 From a76e88daa645d7137c8415f48793525f2ba98545 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 6 Oct 2016 16:19:20 +0200 Subject: aarch64: allow reading system control register when halted in EL0 There's no access to system control register in EL0. Circumvent by moving the PE to EL1 before reading, and switch back to original mode afterwards. Change-Id: I309f4eea5597ffc88fc892e9bbb826982e8a44ec Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 3510db2..41bea2e 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -698,6 +698,8 @@ static int aarch64_post_debug_entry(struct target *target) switch (armv8->arm.core_mode) { case ARMV8_64_EL0T: + dpmv8_modeswitch(&armv8->dpm, ARMV8_64_EL1T); + /* fall through */ case ARMV8_64_EL1T: case ARMV8_64_EL1H: retval = armv8->arm.mrs(target, 3, /*op 0*/ @@ -725,13 +727,20 @@ static int aarch64_post_debug_entry(struct target *target) if (retval != ERROR_OK) return retval; break; - default: + + case ARM_MODE_SVC: retval = armv8->arm.mrc(target, 15, 0, 0, 1, 0, &aarch64->system_control_reg); if (retval != ERROR_OK) return retval; break; + + default: + LOG_INFO("cannot read system control register in this mode"); + break; } + dpmv8_modeswitch(&armv8->dpm, ARM_MODE_ANY); + LOG_DEBUG("System_register: %8.8" PRIx32, aarch64->system_control_reg); aarch64->system_control_reg_curr = aarch64->system_control_reg; -- cgit v1.1 From 2539a323081f046b14ad613b4a163baaf2679a9f Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 6 Oct 2016 16:36:29 +0200 Subject: aarch64: simplify armv8_read_ttbcr Read registers based on current EL instead of PE mode. Change-Id: I05d3219ac1bf8585e9f4f024a7e8599fea0913b6 Signed-off-by: Matthias Welwarsky --- src/target/armv8.c | 97 ++++++++++++++++++++++++++---------------------------- 1 file changed, 47 insertions(+), 50 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index a572e23..9b160a9 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -431,56 +431,53 @@ static __unused int armv8_read_ttbcr(struct target *target) memset(&armv8->armv8_mmu.ttbr1_used, 0, sizeof(armv8->armv8_mmu.ttbr1_used)); memset(&armv8->armv8_mmu.ttbr0_mask, 0, sizeof(armv8->armv8_mmu.ttbr0_mask)); - switch (arm->core_mode) { - case ARMV8_64_EL3H: - case ARMV8_64_EL3T: - retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS(SYSTEM_TCR_EL3, 0), - &ttbcr); - retval += dpm->instr_read_data_r0_64(dpm, - ARMV8_MRS(SYSTEM_TTBR0_EL3, 0), - &armv8->ttbr_base); - if (retval != ERROR_OK) - goto done; - armv8->va_size = 64 - (ttbcr & 0x3F); - armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7); - armv8->page_size = (ttbcr >> 14) & 3; - break; - case ARMV8_64_EL2T: - case ARMV8_64_EL2H: - retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS(SYSTEM_TCR_EL2, 0), - &ttbcr); - retval += dpm->instr_read_data_r0_64(dpm, - ARMV8_MRS(SYSTEM_TTBR0_EL2, 0), - &armv8->ttbr_base); - if (retval != ERROR_OK) - goto done; - armv8->va_size = 64 - (ttbcr & 0x3F); - armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7); - armv8->page_size = (ttbcr >> 14) & 3; - break; - case ARMV8_64_EL0T: - case ARMV8_64_EL1T: - case ARMV8_64_EL1H: - retval = dpm->instr_read_data_r0_64(dpm, - ARMV8_MRS(SYSTEM_TCR_EL1, 0), - &ttbcr_64); - armv8->va_size = 64 - (ttbcr_64 & 0x3F); - armv8->pa_size = armv8_pa_size((ttbcr_64 >> 32) & 7); - armv8->page_size = (ttbcr_64 >> 14) & 3; - armv8->armv8_mmu.ttbr1_used = (((ttbcr_64 >> 16) & 0x3F) != 0) ? 1 : 0; - armv8->armv8_mmu.ttbr0_mask = 0x0000FFFFFFFFFFFF; - retval += dpm->instr_read_data_r0_64(dpm, - ARMV8_MRS(SYSTEM_TTBR0_EL1 | (armv8->armv8_mmu.ttbr1_used), 0), - &armv8->ttbr_base); - if (retval != ERROR_OK) - goto done; - break; - default: - LOG_ERROR("unknow core state"); - retval = ERROR_FAIL; - break; + switch (armv8_curel_from_core_mode(arm)) { + case SYSTEM_CUREL_EL3: + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS(SYSTEM_TCR_EL3, 0), + &ttbcr); + retval += dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_TTBR0_EL3, 0), + &armv8->ttbr_base); + if (retval != ERROR_OK) + goto done; + armv8->va_size = 64 - (ttbcr & 0x3F); + armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7); + armv8->page_size = (ttbcr >> 14) & 3; + break; + case SYSTEM_CUREL_EL2: + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS(SYSTEM_TCR_EL2, 0), + &ttbcr); + retval += dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_TTBR0_EL2, 0), + &armv8->ttbr_base); + if (retval != ERROR_OK) + goto done; + armv8->va_size = 64 - (ttbcr & 0x3F); + armv8->pa_size = armv8_pa_size((ttbcr >> 16) & 7); + armv8->page_size = (ttbcr >> 14) & 3; + break; + case SYSTEM_CUREL_EL0: + case SYSTEM_CUREL_EL1: + retval = dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_TCR_EL1, 0), + &ttbcr_64); + armv8->va_size = 64 - (ttbcr_64 & 0x3F); + armv8->pa_size = armv8_pa_size((ttbcr_64 >> 32) & 7); + armv8->page_size = (ttbcr_64 >> 14) & 3; + armv8->armv8_mmu.ttbr1_used = (((ttbcr_64 >> 16) & 0x3F) != 0) ? 1 : 0; + armv8->armv8_mmu.ttbr0_mask = 0x0000FFFFFFFFFFFF; + retval += dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_TTBR0_EL1 | (armv8->armv8_mmu.ttbr1_used), 0), + &armv8->ttbr_base); + if (retval != ERROR_OK) + goto done; + break; + default: + LOG_ERROR("unknow core state"); + retval = ERROR_FAIL; + break; } if (retval != ERROR_OK) goto done; -- cgit v1.1 From 79c4c22e1570cf0d73bacb4d292951e614d0ab2f Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 6 Oct 2016 16:10:38 +0200 Subject: aarch64: register access rewrite All register access is now performed through common read/write functions, which delegate the actual register access to the armv8_common object. armv8_common contains function pointers to direct read and write requests to the respective low-level functions for each PE state. The respective read/write functions are selected on debug state entry. At the same time, T32 opcodes are now formatted for ITR in dpmv8_exec_opcode() and the T32_FMTITR macro is removed from global visibility. Change-Id: I9eaef017c7cc9e0c531e693c534901bfdbdb842c Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 28 +-- src/target/arm_dpm.h | 5 +- src/target/armv8.c | 456 +++++++++++++++++++++++++++++++++++++-------- src/target/armv8.h | 46 ++++- src/target/armv8_dpm.c | 373 ++++++++++++------------------------ src/target/armv8_dpm.h | 1 + src/target/armv8_opcodes.c | 20 +- src/target/armv8_opcodes.h | 17 +- 8 files changed, 580 insertions(+), 366 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 41bea2e..02f17d8 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -637,13 +637,15 @@ static int aarch64_debug_entry(struct target *target) int retval = ERROR_OK; struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = target_to_armv8(target); + struct arm_dpm *dpm = &armv8->dpm; + enum arm_state core_state; - LOG_DEBUG("dscr = 0x%08" PRIx32, aarch64->cpudbg_dscr); + LOG_DEBUG("%s dscr = 0x%08" PRIx32, target_name(target), aarch64->cpudbg_dscr); - /* REVISIT see A8 TRM 12.11.4 steps 2..3 -- make sure that any - * imprecise data aborts get discarded by issuing a Data - * Synchronization Barrier: ARMV4_5_MCR(15, 0, 0, 7, 10, 4). - */ + dpm->dscr = aarch64->cpudbg_dscr; + core_state = armv8_dpm_get_core_state(dpm); + armv8_select_opcodes(armv8, core_state == ARM_STATE_AARCH64); + armv8_select_reg_access(armv8, core_state == ARM_STATE_AARCH64); /* make sure to clear all sticky errors */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, @@ -677,11 +679,8 @@ static int aarch64_debug_entry(struct target *target) retval = armv8_dpm_read_current_registers(&armv8->dpm); - if (armv8->post_debug_entry) { + if (retval == ERROR_OK && armv8->post_debug_entry) retval = armv8->post_debug_entry(target); - if (retval != ERROR_OK) - return retval; - } return retval; } @@ -1457,7 +1456,7 @@ static int aarch64_write_apb_ap_memory(struct target *target, /* Step 1.a+b - Write the address for read access into DBGDTRRX */ /* Step 1.c - Copy value from DTR to R0 using instruction mrc DBGDTRTXint, r0 */ dpm->instr_write_data_dcc(dpm, - T32_FMTITR(ARMV4_5_MRC(14, 0, 0, 0, 5, 0)), address & ~0x3ULL); + ARMV4_5_MRC(14, 0, 0, 0, 5, 0), address & ~0x3ULL); } /* Step 1.d - Change DCC to memory mode */ @@ -1486,6 +1485,8 @@ static int aarch64_write_apb_ap_memory(struct target *target, armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) goto error_free_buff_w; + + dpm->dscr = dscr; if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) { /* Abort occurred - clear it and exit */ LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); @@ -1586,9 +1587,9 @@ static int aarch64_read_apb_ap_memory(struct target *target, /* Step 1.a+b - Write the address for read access into DBGDTRRXint */ /* Step 1.c - Copy value from DTR to R0 using instruction mrc DBGDTRTXint, r0 */ retval += dpm->instr_write_data_dcc(dpm, - T32_FMTITR(ARMV4_5_MRC(14, 0, 0, 0, 5, 0)), address & ~0x3ULL); + ARMV4_5_MRC(14, 0, 0, 0, 5, 0), address & ~0x3ULL); /* Step 1.d - Dummy operation to ensure EDSCR.Txfull == 1 */ - retval += dpm->instr_execute(dpm, T32_FMTITR(ARMV4_5_MCR(14, 0, 0, 0, 5, 0))); + retval += dpm->instr_execute(dpm, ARMV4_5_MCR(14, 0, 0, 0, 5, 0)); /* Step 1.e - Change DCC to memory mode */ dscr = dscr | DSCR_MA; retval += mem_ap_write_atomic_u32(armv8->debug_ap, @@ -1648,6 +1649,9 @@ static int aarch64_read_apb_ap_memory(struct target *target, armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) goto error_free_buff_r; + + dpm->dscr = dscr; + if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) { /* Abort occurred - clear it and exit */ LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); diff --git a/src/target/arm_dpm.h b/src/target/arm_dpm.h index 63467d5..f8d1248 100644 --- a/src/target/arm_dpm.h +++ b/src/target/arm_dpm.h @@ -143,6 +143,9 @@ struct arm_dpm { /** Recent value of DSCR. */ uint32_t dscr; + /** Recent exception level on armv8 */ + unsigned int last_el; + /* FIXME -- read/write DCSR methods and symbols */ }; @@ -150,10 +153,8 @@ int arm_dpm_setup(struct arm_dpm *dpm); int arm_dpm_initialize(struct arm_dpm *dpm); int arm_dpm_read_current_registers(struct arm_dpm *); -int arm_dpm_read_current_registers_64(struct arm_dpm *); int dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode); - int arm_dpm_write_dirty_registers(struct arm_dpm *, bool bpwp); void arm_dpm_report_wfar(struct arm_dpm *, uint32_t wfar); diff --git a/src/target/armv8.c b/src/target/armv8.c index 9b160a9..32fe048 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -161,55 +161,333 @@ int armv8_mode_to_number(enum arm_mode mode) } } - -static int armv8_read_core_reg(struct target *target, struct reg *r, - int num, enum arm_mode mode) +static int armv8_read_reg(struct armv8_common *armv8, int regnum, uint64_t *regval) { - uint64_t reg_value; + struct arm_dpm *dpm = &armv8->dpm; int retval; - struct arm_reg *armv8_core_reg; - struct armv8_common *armv8 = target_to_armv8(target); + uint32_t value; + uint64_t value_64; + + switch (regnum) { + case 0 ... 30: + retval = dpm->instr_read_data_dcc_64(dpm, + ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, regnum), &value_64); + break; + case ARMV8_SP: + retval = dpm->instr_read_data_r0_64(dpm, + ARMV8_MOVFSP_64(0), &value_64); + break; + case ARMV8_PC: + retval = dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS_DLR(0), &value_64); + break; + case ARMV8_xPSR: + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS_DSPSR(0), &value); + value_64 = value; + break; + case ARMV8_ELR_EL1: + retval = dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_ELR_EL1, 0), &value_64); + break; + case ARMV8_ELR_EL2: + retval = dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_ELR_EL2, 0), &value_64); + break; + case ARMV8_ELR_EL3: + retval = dpm->instr_read_data_r0_64(dpm, + ARMV8_MRS(SYSTEM_ELR_EL3, 0), &value_64); + break; + case ARMV8_ESR_EL1: + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS(SYSTEM_ESR_EL1, 0), &value); + value_64 = value; + break; + case ARMV8_ESR_EL2: + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS(SYSTEM_ESR_EL2, 0), &value); + value_64 = value; + break; + case ARMV8_ESR_EL3: + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS(SYSTEM_ESR_EL3, 0), &value); + value_64 = value; + break; + case ARMV8_SPSR_EL1: + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS(SYSTEM_SPSR_EL1, 0), &value); + value_64 = value; + break; + case ARMV8_SPSR_EL2: + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS(SYSTEM_SPSR_EL2, 0), &value); + value_64 = value; + break; + case ARMV8_SPSR_EL3: + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS(SYSTEM_SPSR_EL3, 0), &value); + value_64 = value; + break; + default: + retval = ERROR_FAIL; + break; + } - assert(num < (int)armv8->arm.core_cache->num_regs); + if (retval == ERROR_OK && regval != NULL) + *regval = value_64; - armv8_core_reg = armv8->arm.core_cache->reg_list[num].arch_info; - retval = armv8->load_core_reg_u64(target, - armv8_core_reg->num, ®_value); + return retval; +} - buf_set_u64(armv8->arm.core_cache->reg_list[num].value, 0, 64, reg_value); - armv8->arm.core_cache->reg_list[num].valid = 1; - armv8->arm.core_cache->reg_list[num].dirty = 0; +static int armv8_write_reg(struct armv8_common *armv8, int regnum, uint64_t value_64) +{ + struct arm_dpm *dpm = &armv8->dpm; + int retval; + uint32_t value; + + switch (regnum) { + case 0 ... 30: + retval = dpm->instr_write_data_dcc_64(dpm, + ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, regnum), + value_64); + break; + case ARMV8_SP: + retval = dpm->instr_write_data_r0_64(dpm, + ARMV8_MOVTSP_64(0), + value_64); + break; + case ARMV8_PC: + retval = dpm->instr_write_data_r0_64(dpm, + ARMV8_MSR_DLR(0), + value_64); + break; + case ARMV8_xPSR: + value = value_64; + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MSR_DSPSR(0), + value); + break; + /* registers clobbered by taking exception in debug state */ + case ARMV8_ELR_EL1: + retval = dpm->instr_write_data_r0_64(dpm, + ARMV8_MSR_GP(SYSTEM_ELR_EL1, 0), value_64); + break; + case ARMV8_ELR_EL2: + retval = dpm->instr_write_data_r0_64(dpm, + ARMV8_MSR_GP(SYSTEM_ELR_EL2, 0), value_64); + break; + case ARMV8_ELR_EL3: + retval = dpm->instr_write_data_r0_64(dpm, + ARMV8_MSR_GP(SYSTEM_ELR_EL3, 0), value_64); + break; + case ARMV8_ESR_EL1: + value = value_64; + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MSR_GP(SYSTEM_ESR_EL1, 0), value); + break; + case ARMV8_ESR_EL2: + value = value_64; + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MSR_GP(SYSTEM_ESR_EL2, 0), value); + break; + case ARMV8_ESR_EL3: + value = value_64; + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MSR_GP(SYSTEM_ESR_EL3, 0), value); + break; + case ARMV8_SPSR_EL1: + value = value_64; + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MSR_GP(SYSTEM_SPSR_EL1, 0), value); + break; + case ARMV8_SPSR_EL2: + value = value_64; + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MSR_GP(SYSTEM_SPSR_EL2, 0), value); + break; + case ARMV8_SPSR_EL3: + value = value_64; + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MSR_GP(SYSTEM_SPSR_EL3, 0), value); + break; + default: + retval = ERROR_FAIL; + break; + } return retval; } -#if 0 -static int armv8_write_core_reg(struct target *target, struct reg *r, - int num, enum arm_mode mode, target_addr_t value) +static int armv8_read_reg32(struct armv8_common *armv8, int regnum, uint64_t *regval) { + struct arm_dpm *dpm = &armv8->dpm; + uint32_t value = 0; int retval; - struct arm_reg *armv8_core_reg; - struct armv8_common *armv8 = target_to_armv8(target); - assert(num < (int)armv8->arm.core_cache->num_regs); + switch (regnum) { + case ARMV8_R0 ... ARMV8_R14: + /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */ + retval = dpm->instr_read_data_dcc(dpm, + ARMV4_5_MCR(14, 0, regnum, 0, 5, 0), + &value); + break; + case ARMV8_SP: + retval = dpm->instr_read_data_dcc(dpm, + ARMV4_5_MCR(14, 0, 13, 0, 5, 0), + &value); + break; + case ARMV8_PC: + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRC_DLR(0), + &value); + break; + case ARMV8_xPSR: + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRC_DSPSR(0), + &value); + break; + case ARMV8_ELR_EL1: /* mapped to LR_svc */ + retval = dpm->instr_read_data_dcc(dpm, + ARMV4_5_MCR(14, 0, 14, 0, 5, 0), + &value); + break; + case ARMV8_ELR_EL2: /* mapped to ELR_hyp */ + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS_T1(0, 14, 0, 1), + &value); + break; + case ARMV8_ELR_EL3: /* mapped to LR_mon */ + retval = dpm->instr_read_data_dcc(dpm, + ARMV4_5_MCR(14, 0, 14, 0, 5, 0), + &value); + break; + case ARMV8_ESR_EL1: /* mapped to DFSR */ + retval = dpm->instr_read_data_r0(dpm, + ARMV4_5_MRC(15, 0, 0, 5, 0, 0), + &value); + break; + case ARMV8_ESR_EL2: /* mapped to HSR */ + retval = dpm->instr_read_data_r0(dpm, + ARMV4_5_MRC(15, 4, 0, 5, 2, 0), + &value); + break; + case ARMV8_ESR_EL3: /* FIXME: no equivalent in aarch32? */ + retval = ERROR_FAIL; + break; + case ARMV8_SPSR_EL1: /* mapped to SPSR_svc */ + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS_xPSR_T1(1, 0), + &value); + break; + case ARMV8_SPSR_EL2: /* mapped to SPSR_hyp */ + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS_xPSR_T1(1, 0), + &value); + break; + case ARMV8_SPSR_EL3: /* mapped to SPSR_mon */ + retval = dpm->instr_read_data_r0(dpm, + ARMV8_MRS_xPSR_T1(1, 0), + &value); + break; + default: + retval = ERROR_FAIL; + break; + } + + if (retval == ERROR_OK && regval != NULL) + *regval = value; - armv8_core_reg = armv8->arm.core_cache->reg_list[num].arch_info; - retval = armv8->store_core_reg_u64(target, - armv8_core_reg->num, - value); - if (retval != ERROR_OK) { - LOG_ERROR("JTAG failure"); - armv8->arm.core_cache->reg_list[num].dirty = armv8->arm.core_cache->reg_list[num].valid; - return ERROR_JTAG_DEVICE_ERROR; + return retval; +} + +static int armv8_write_reg32(struct armv8_common *armv8, int regnum, uint64_t value) +{ + struct arm_dpm *dpm = &armv8->dpm; + int retval; + + switch (regnum) { + case ARMV8_R0 ... ARMV8_R14: + /* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */ + retval = dpm->instr_write_data_dcc(dpm, + ARMV4_5_MRC(14, 0, regnum, 0, 5, 0), value); + break; + case ARMV8_SP: + retval = dpm->instr_write_data_dcc(dpm, + ARMV4_5_MRC(14, 0, 13, 0, 5, 0), + value); + break; + case ARMV8_PC:/* PC + * read r0 from DCC; then "MOV pc, r0" */ + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MCR_DLR(0), value); + break; + case ARMV8_xPSR: /* CPSR */ + /* read r0 from DCC, then "MCR r0, DSPSR" */ + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MCR_DSPSR(0), value); + break; + case ARMV8_ELR_EL1: /* mapped to LR_svc */ + retval = dpm->instr_write_data_dcc(dpm, + ARMV4_5_MRC(14, 0, 14, 0, 5, 0), + value); + break; + case ARMV8_ELR_EL2: /* mapped to ELR_hyp */ + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MSR_GP_T1(0, 14, 0, 1), + value); + break; + case ARMV8_ELR_EL3: /* mapped to LR_mon */ + retval = dpm->instr_write_data_dcc(dpm, + ARMV4_5_MRC(14, 0, 14, 0, 5, 0), + value); + break; + case ARMV8_ESR_EL1: /* mapped to DFSR */ + retval = dpm->instr_write_data_r0(dpm, + ARMV4_5_MCR(15, 0, 0, 5, 0, 0), + value); + break; + case ARMV8_ESR_EL2: /* mapped to HSR */ + retval = dpm->instr_write_data_r0(dpm, + ARMV4_5_MCR(15, 4, 0, 5, 2, 0), + value); + break; + case ARMV8_ESR_EL3: /* FIXME: no equivalent in aarch32? */ + retval = ERROR_FAIL; + break; + case ARMV8_SPSR_EL1: /* mapped to SPSR_svc */ + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MSR_GP_xPSR_T1(1, 0, 15), + value); + break; + case ARMV8_SPSR_EL2: /* mapped to SPSR_hyp */ + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MSR_GP_xPSR_T1(1, 0, 15), + value); + break; + case ARMV8_SPSR_EL3: /* mapped to SPSR_mon */ + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MSR_GP_xPSR_T1(1, 0, 15), + value); + break; + default: + retval = ERROR_FAIL; + break; } - LOG_DEBUG("write core reg %i value 0x%" PRIx64 "", num, value); - armv8->arm.core_cache->reg_list[num].valid = 1; - armv8->arm.core_cache->reg_list[num].dirty = 0; + return retval; - return ERROR_OK; } -#endif + +void armv8_select_reg_access(struct armv8_common *armv8, bool is_aarch64) +{ + if (is_aarch64) { + armv8->read_reg_u64 = armv8_read_reg; + armv8->write_reg_u64 = armv8_write_reg; + } else { + armv8->read_reg_u64 = armv8_read_reg32; + armv8->write_reg_u64 = armv8_write_reg32; + } +} /* retrieve core id cluster id */ int armv8_read_mpidr(struct armv8_common *armv8) @@ -306,26 +584,26 @@ static void armv8_show_fault_registers32(struct armv8_common *armv8) /* c5/c0 - {data, instruction} fault status registers */ retval = dpm->instr_read_data_r0(dpm, - T32_FMTITR(ARMV4_5_MRC(15, 0, 0, 5, 0, 0)), + ARMV4_5_MRC(15, 0, 0, 5, 0, 0), &dfsr); if (retval != ERROR_OK) goto done; retval = dpm->instr_read_data_r0(dpm, - T32_FMTITR(ARMV4_5_MRC(15, 0, 0, 5, 0, 1)), + ARMV4_5_MRC(15, 0, 0, 5, 0, 1), &ifsr); if (retval != ERROR_OK) goto done; /* c6/c0 - {data, instruction} fault address registers */ retval = dpm->instr_read_data_r0(dpm, - T32_FMTITR(ARMV4_5_MRC(15, 0, 0, 6, 0, 0)), + ARMV4_5_MRC(15, 0, 0, 6, 0, 0), &dfar); if (retval != ERROR_OK) goto done; retval = dpm->instr_read_data_r0(dpm, - T32_FMTITR(ARMV4_5_MRC(15, 0, 0, 6, 0, 2)), + ARMV4_5_MRC(15, 0, 0, 6, 0, 2), &ifar); if (retval != ERROR_OK) goto done; @@ -386,7 +664,7 @@ static __unused int armv8_read_ttbcr32(struct target *target) goto done; /* MRC p15,0,,c2,c0,2 ; Read CP15 Translation Table Base Control Register*/ retval = dpm->instr_read_data_r0(dpm, - T32_FMTITR(ARMV4_5_MRC(15, 0, 0, 2, 0, 2)), + ARMV4_5_MRC(15, 0, 0, 2, 0, 2), &ttbcr); if (retval != ERROR_OK) goto done; @@ -431,7 +709,7 @@ static __unused int armv8_read_ttbcr(struct target *target) memset(&armv8->armv8_mmu.ttbr1_used, 0, sizeof(armv8->armv8_mmu.ttbr1_used)); memset(&armv8->armv8_mmu.ttbr0_mask, 0, sizeof(armv8->armv8_mmu.ttbr0_mask)); - switch (armv8_curel_from_core_mode(arm)) { + switch (armv8_curel_from_core_mode(arm->core_mode)) { case SYSTEM_CUREL_EL3: retval = dpm->instr_read_data_r0(dpm, ARMV8_MRS(SYSTEM_TCR_EL3, 0), @@ -519,7 +797,7 @@ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, if (retval != ERROR_OK) return retval; - switch (armv8_curel_from_core_mode(arm)) { + switch (armv8_curel_from_core_mode(arm->core_mode)) { case SYSTEM_CUREL_EL0: instr = ARMV8_SYS(SYSTEM_ATS12E0R, 0); /* can only execute instruction at EL2 */ @@ -602,11 +880,6 @@ int armv8_init_arch_info(struct target *target, struct armv8_common *armv8) armv8->arm.common_magic = ARM_COMMON_MAGIC; armv8->common_magic = ARMV8_COMMON_MAGIC; - arm->read_core_reg = armv8_read_core_reg; -#if 0 - arm->write_core_reg = armv8_write_core_reg; -#endif - armv8->armv8_mmu.armv8_cache.l2_cache = NULL; armv8->armv8_mmu.armv8_cache.info = -1; armv8->armv8_mmu.armv8_cache.flush_all_data_cache = NULL; @@ -673,46 +946,59 @@ static const struct { unsigned id; const char *name; unsigned bits; + enum arm_mode mode; enum reg_type type; const char *group; const char *feature; } armv8_regs[] = { - { ARMV8_R0, "x0", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R1, "x1", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R2, "x2", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R3, "x3", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R4, "x4", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R5, "x5", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R6, "x6", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R7, "x7", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R8, "x8", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R9, "x9", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R10, "x10", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R11, "x11", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R12, "x12", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R13, "x13", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R14, "x14", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R15, "x15", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R16, "x16", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R17, "x17", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R18, "x18", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R19, "x19", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R20, "x20", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R21, "x21", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R22, "x22", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R23, "x23", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R24, "x24", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R25, "x25", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R26, "x26", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R27, "x27", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R28, "x28", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R29, "x29", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_R30, "x30", 64, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, - - { ARMV8_R31, "sp", 64, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.aarch64.core" }, - { ARMV8_PC, "pc", 64, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.aarch64.core" }, - - { ARMV8_xPSR, "CPSR", 32, REG_TYPE_UINT32, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R0, "x0", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R1, "x1", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R2, "x2", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R3, "x3", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R4, "x4", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R5, "x5", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R6, "x6", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R7, "x7", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R8, "x8", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R9, "x9", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R10, "x10", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R11, "x11", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R12, "x12", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R13, "x13", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R14, "x14", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R15, "x15", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R16, "x16", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R17, "x17", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R18, "x18", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R19, "x19", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R20, "x20", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R21, "x21", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R22, "x22", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R23, "x23", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R24, "x24", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R25, "x25", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R26, "x26", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R27, "x27", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R28, "x28", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R29, "x29", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_R30, "x30", 64, ARM_MODE_ANY, REG_TYPE_UINT64, "general", "org.gnu.gdb.aarch64.core" }, + + { ARMV8_SP, "sp", 64, ARM_MODE_ANY, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.aarch64.core" }, + { ARMV8_PC, "pc", 64, ARM_MODE_ANY, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.aarch64.core" }, + + { ARMV8_xPSR, "CPSR", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.aarch64.core" }, + + { ARMV8_ELR_EL1, "ELR_EL1", 64, ARMV8_64_EL1H, REG_TYPE_CODE_PTR, "banked", "net.sourceforge.openocd.banked" }, + { ARMV8_ESR_EL1, "ESR_EL1", 32, ARMV8_64_EL1H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked" }, + { ARMV8_SPSR_EL1, "SPSR_EL1", 32, ARMV8_64_EL1H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked" }, + + { ARMV8_ELR_EL2, "ELR_EL2", 64, ARMV8_64_EL2H, REG_TYPE_CODE_PTR, "banked", "net.sourceforge.openocd.banked" }, + { ARMV8_ESR_EL2, "ESR_EL2", 32, ARMV8_64_EL2H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked" }, + { ARMV8_SPSR_EL2, "SPSR_EL2", 32, ARMV8_64_EL2H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked" }, + + { ARMV8_ELR_EL3, "ELR_EL3", 64, ARMV8_64_EL3H, REG_TYPE_CODE_PTR, "banked", "net.sourceforge.openocd.banked" }, + { ARMV8_ESR_EL3, "ESR_EL3", 32, ARMV8_64_EL3H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked" }, + { ARMV8_SPSR_EL3, "SPSR_EL3", 32, ARMV8_64_EL3H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked" }, }; #define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs) @@ -782,6 +1068,7 @@ struct reg_cache *armv8_build_reg_cache(struct target *target) for (i = 0; i < num_regs; i++) { arch_info[i].num = armv8_regs[i].id; + arch_info[i].mode = armv8_regs[i].mode; arch_info[i].target = target; arch_info[i].arm = arm; @@ -847,11 +1134,18 @@ int armv8_get_gdb_reg_list(struct target *target, switch (reg_class) { case REG_CLASS_GENERAL: + *reg_list_size = ARMV8_ELR_EL1; + *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); + + for (i = 0; i < *reg_list_size; i++) + (*reg_list)[i] = armv8_reg_current(arm, i); + + return ERROR_OK; case REG_CLASS_ALL: *reg_list_size = ARMV8_LAST_REG; *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); - for (i = 0; i < ARMV8_LAST_REG; i++) + for (i = 0; i < *reg_list_size; i++) (*reg_list)[i] = armv8_reg_current(arm, i); return ERROR_OK; diff --git a/src/target/armv8.h b/src/target/armv8.h index 497e482..85845e6 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -26,7 +26,7 @@ #include "armv8_dpm.h" enum { - ARMV8_R0, + ARMV8_R0 = 0, ARMV8_R1, ARMV8_R2, ARMV8_R3, @@ -57,11 +57,23 @@ enum { ARMV8_R28, ARMV8_R29, ARMV8_R30, - ARMV8_R31, + ARMV8_SP = 31, ARMV8_PC = 32, ARMV8_xPSR = 33, + ARMV8_ELR_EL1 = 34, + ARMV8_ESR_EL1 = 35, + ARMV8_SPSR_EL1 = 36, + + ARMV8_ELR_EL2 = 37, + ARMV8_ESR_EL2 = 38, + ARMV8_SPSR_EL2 = 39, + + ARMV8_ELR_EL3 = 40, + ARMV8_ESR_EL3 = 41, + ARMV8_SPSR_EL3 = 42, + ARMV8_LAST_REG, }; @@ -162,8 +174,8 @@ struct armv8_common { struct armv8_mmu_common armv8_mmu; /* Direct processor core register read and writes */ - int (*load_core_reg_u64)(struct target *target, uint32_t num, uint64_t *value); - int (*store_core_reg_u64)(struct target *target, uint32_t num, uint64_t value); + int (*read_reg_u64)(struct armv8_common *armv8, int num, uint64_t *value); + int (*write_reg_u64)(struct armv8_common *armv8, int num, uint64_t value); int (*examine_debug_reason)(struct target *target); int (*post_debug_entry)(struct target *target); @@ -270,10 +282,32 @@ int armv8_handle_cache_info_command(struct command_context *cmd_ctx, void armv8_set_cpsr(struct arm *arm, uint32_t cpsr); -static inline int armv8_curel_from_core_mode(struct arm *arm) +static inline unsigned int armv8_curel_from_core_mode(enum arm_mode core_mode) { - return (arm->core_mode >> 6) & 3; + switch (core_mode) { + /* Aarch32 modes */ + case ARM_MODE_USR: + return 0; + case ARM_MODE_SVC: + case ARM_MODE_ABT: /* FIXME: EL3? */ + case ARM_MODE_IRQ: /* FIXME: EL3? */ + case ARM_MODE_FIQ: /* FIXME: EL3? */ + case ARM_MODE_UND: /* FIXME: EL3? */ + case ARM_MODE_SYS: /* FIXME: EL3? */ + return 1; + /* case ARM_MODE_HYP: + * return 2; + */ + case ARM_MODE_MON: + return 3; + /* all Aarch64 modes */ + default: + return (core_mode >> 6) & 3; + } } + +void armv8_select_reg_access(struct armv8_common *armv8, bool is_aarch64); + extern const struct command_registration armv8_command_handlers[]; #endif diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index 4bb2075..a92f92c 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -28,6 +28,8 @@ #include "helper/time_support.h" +/* T32 ITR format */ +#define T32_FMTITR(instr) (((instr & 0x0000FFFF) << 16) | ((instr & 0xFFFF0000) >> 16)) /** * @file @@ -42,6 +44,29 @@ * to minimize needless differences in debug behavior between cores. */ +/** + * Get core state from EDSCR, without necessity to retrieve CPSR + */ +enum arm_state armv8_dpm_get_core_state(struct arm_dpm *dpm) +{ + int el = (dpm->dscr >> 8) & 0x3; + int rw = (dpm->dscr >> 10) & 0xF; + int pos; + + dpm->last_el = el; + + /* find the first '0' in DSCR.RW */ + for (pos = 3; pos >= 0; pos--) { + if ((rw & (1 << pos)) == 0) + break; + } + + if (el > pos) + return ARM_STATE_AARCH64; + + return ARM_STATE_ARM; +} + /*----------------------------------------------------------------------*/ static int dpmv8_write_dcc(struct armv8_common *armv8, uint32_t data) @@ -166,6 +191,9 @@ static int dpmv8_dpm_prepare(struct arm_dpm *dpm) } } + /* update the stored copy of dscr */ + dpm->dscr = dscr; + /* this "should never happen" ... */ if (dscr & DSCR_DTR_RX_FULL) { LOG_ERROR("DSCR_DTR_RX_FULL, dscr 0x%08" PRIx32, dscr); @@ -218,6 +246,9 @@ static int dpmv8_exec_opcode(struct arm_dpm *dpm, } } + if (armv8_dpm_get_core_state(dpm) != ARM_STATE_AARCH64) + opcode = T32_FMTITR(opcode); + retval = mem_ap_write_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_ITR, opcode); if (retval != ERROR_OK) @@ -237,6 +268,20 @@ static int dpmv8_exec_opcode(struct arm_dpm *dpm, } } while ((dscr & DSCR_ITE) == 0); /* Wait for InstrCompl bit to be set */ + /* update dscr and el after each command execution */ + dpm->dscr = dscr; + if (dpm->last_el != ((dscr >> 8) & 3)) + LOG_DEBUG("EL %i -> %i", dpm->last_el, (dscr >> 8) & 3); + dpm->last_el = (dscr >> 8) & 3; + + if (dscr & DSCR_ERR) { + LOG_ERROR("Opcode 0x%08"PRIx32", DSCR.ERR=1, DSCR.EL=%i", opcode, dpm->last_el); + /* clear the sticky error condition */ + mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); + retval = ERROR_FAIL; + } + if (p_dscr) *p_dscr = dscr; @@ -471,7 +516,7 @@ static int dpmv8_mrc(struct target *target, int cpnum, /* read coprocessor register into R0; return via DCC */ retval = dpm->instr_read_data_r0(dpm, - T32_FMTITR(ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2)), + ARMV4_5_MRC(cpnum, op1, 0, CRn, CRm, op2), value); /* (void) */ dpm->finish(dpm); @@ -496,7 +541,7 @@ static int dpmv8_mcr(struct target *target, int cpnum, /* read DCC into r0; then write coprocessor register from R0 */ retval = dpm->instr_write_data_r0(dpm, - T32_FMTITR(ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2)), + ARMV4_5_MCR(cpnum, op1, 0, CRn, CRm, op2), value); /* (void) */ dpm->finish(dpm); @@ -616,210 +661,50 @@ int dpmv8_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) return retval; } -static int dpmv8_read_reg32(struct arm_dpm *dpm, struct reg *r, unsigned regnum) -{ - uint32_t value; - int retval = ERROR_FAIL; - bool valid = true; - - switch (regnum) { - case 0 ... 14: - /* return via DCC: "MCR p14, 0, Rnum, c0, c5, 0" */ - retval = dpm->instr_read_data_dcc(dpm, - T32_FMTITR(ARMV4_5_MCR(14, 0, regnum, 0, 5, 0)), - &value); - break; - case ARMV8_R31: - retval = dpm->instr_read_data_dcc(dpm, - T32_FMTITR(ARMV4_5_MCR(14, 0, 13, 0, 5, 0)), - &value); - break; - case ARMV8_PC: - retval = dpm->instr_read_data_r0(dpm, - T32_FMTITR(ARMV8_MRC_DLR(0)), - &value); - break; - case ARMV8_xPSR: - retval = dpm->instr_read_data_r0(dpm, - T32_FMTITR(ARMV8_MRC_DSPSR(0)), - &value); - break; - default: - LOG_DEBUG("READ: %s ignored", r->name); - retval = ERROR_OK; - value = 0xFFFFFFFF; - valid = false; - break; - } - - if (retval == ERROR_OK) { - r->valid = valid; - r->dirty = false; - buf_set_u64(r->value, 0, 32, value); - LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value); - } - return retval; -} - -static int dpmv8_write_reg32(struct arm_dpm *dpm, struct reg *r, unsigned regnum) -{ - int retval; - uint64_t value = buf_get_u64(r->value, 0, 32); - - switch (regnum) { - case 0 ... 14: - /* load register from DCC: "MRC p14, 0, Rnum, c0, c5, 0" */ - retval = dpm->instr_write_data_dcc(dpm, - T32_FMTITR(ARMV4_5_MRC(14, 0, regnum, 0, 5, 0)), value); - break; - case ARMV8_PC:/* PC - * read r0 from DCC; then "MOV pc, r0" */ - retval = dpm->instr_write_data_r0(dpm, - T32_FMTITR(ARMV8_MCR_DLR(0)), value); - break; - case ARMV8_xPSR: /* CPSR */ - /* read r0 from DCC, then "MCR r0, DSPSR" */ - retval = dpm->instr_write_data_r0(dpm, - T32_FMTITR(ARMV8_MCR_DSPSR(0)), value); - break; - default: - retval = ERROR_OK; - LOG_DEBUG("WRITE: %s ignored", r->name); - break; - } - - if (retval == ERROR_OK) { - r->dirty = false; - LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned) value); - } - - return retval; -} - -/* just read the register -- rely on the core mode being right */ +/* + * Common register read, relies on armv8_select_reg_access() having been called. + */ static int dpmv8_read_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) { - uint32_t value; + struct armv8_common *armv8 = dpm->arm->arch_info; uint64_t value_64; - int retval = ERROR_FAIL; + int retval; - switch (regnum) { - case 0 ... 30: - retval = dpm->instr_read_data_dcc_64(dpm, - ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, regnum), - &value_64); - break; - case ARMV8_R31: - retval = dpm->instr_read_data_r0_64(dpm, - ARMV8_MOVFSP_64(0), - &value_64); - break; - case ARMV8_PC: - retval = dpm->instr_read_data_r0_64(dpm, - ARMV8_MRS_DLR(0), - &value_64); - break; - case ARMV8_xPSR: - retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS_DSPSR(0), - &value); - break; - default: - LOG_DEBUG("READ: %s fail", r->name); - break; - } + retval = armv8->read_reg_u64(armv8, regnum, &value_64); if (retval == ERROR_OK) { r->valid = true; r->dirty = false; - if (r->size == 64) { - buf_set_u64(r->value, 0, 64, value_64); + buf_set_u64(r->value, 0, r->size, value_64); + if (r->size == 64) LOG_DEBUG("READ: %s, %16.8llx", r->name, (unsigned long long) value_64); - } else { - buf_set_u32(r->value, 0, 32, value); - LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned) value); - } + else + LOG_DEBUG("READ: %s, %8.8x", r->name, (unsigned int) value_64); } - return retval; + return ERROR_OK; } -/* just write the register -- rely on the core mode being right */ +/* + * Common register write, relies on armv8_select_reg_access() having been called. + */ static int dpmv8_write_reg(struct arm_dpm *dpm, struct reg *r, unsigned regnum) { + struct armv8_common *armv8 = dpm->arm->arch_info; int retval = ERROR_FAIL; - uint32_t value = 0xFFFFFFFF; - uint64_t value_64 = 0xFFFFFFFFFFFFFFFF; - - switch (regnum) { - case 0 ... 30: - value_64 = buf_get_u64(r->value, 0, 64); - retval = dpm->instr_write_data_dcc_64(dpm, - ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, regnum), - value_64); - break; - case ARMV8_R31: - value_64 = buf_get_u64(r->value, 0, 64); - retval = dpm->instr_write_data_r0_64(dpm, - ARMV8_MOVTSP_64(0), - value_64); - break; - case ARMV8_PC: - value_64 = buf_get_u64(r->value, 0, 64); - retval = dpm->instr_write_data_r0_64(dpm, - ARMV8_MSR_DLR(0), - value_64); - break; - case ARMV8_xPSR: - value = buf_get_u32(r->value, 0, 32); - retval = dpm->instr_write_data_r0(dpm, - ARMV8_MSR_DSPSR(0), - value); - break; - default: - LOG_DEBUG("write: %s fail", r->name); - break; - } + uint64_t value_64; + value_64 = buf_get_u64(r->value, 0, r->size); + retval = armv8->write_reg_u64(armv8, regnum, value_64); if (retval == ERROR_OK) { r->dirty = false; if (r->size == 64) - LOG_DEBUG("WRITE: %s, %16.8llx", r->name, (unsigned long long) value_64); + LOG_DEBUG("WRITE: %s, %16.8llx", r->name, (unsigned long long)value_64); else - LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned) value); + LOG_DEBUG("WRITE: %s, %8.8x", r->name, (unsigned int)value_64); } - return retval; -} - -static inline enum arm_state dpm_get_core_state(uint32_t dscr) -{ - int el = (dscr >> 8) & 0x3; - int rw = (dscr >> 10) & 0xF; - - LOG_DEBUG("EL:%i, RW:0x%x", el, rw); - - /* DSCR.RW = 0b1111 - all EL are using AArch64 state */ - if (rw == 0xF) - return ARM_STATE_AARCH64; - - /* DSCR.RW = 0b1110 - all EL > 0 are using AArch64 state */ - if (rw == 0xE && el > 0) - return ARM_STATE_AARCH64; - - /* DSCR.RW = 0b110x - all EL > 1 are using Aarch64 state */ - if ((rw & 0xE) == 0xC && el > 1) - return ARM_STATE_AARCH64; - - /* DSCR.RW = 0b10xx - all EL > 2 are using Aarch64 state */ - if ((rw & 0xC) == 0x8 && el > 2) - return ARM_STATE_AARCH64; - - /* DSCR.RW = 0b0xxx - all EL are using AArch32 state */ - if ((rw & 0x8) == 0) - return ARM_STATE_ARM; - - return ARM_STATE_ARM; + return ERROR_OK; } /** @@ -833,60 +718,59 @@ int armv8_dpm_read_current_registers(struct arm_dpm *dpm) { struct arm *arm = dpm->arm; struct armv8_common *armv8 = (struct armv8_common *)arm->arch_info; - enum arm_state core_state; + struct reg_cache *cache; + struct reg *r; uint32_t cpsr; - int retval; - struct reg *r; retval = dpm->prepare(dpm); if (retval != ERROR_OK) return retval; - core_state = dpm_get_core_state(dpm->dscr); - - armv8_select_opcodes(armv8, core_state); + cache = arm->core_cache; /* read R0 first (it's used for scratch), then CPSR */ - r = arm->core_cache->reg_list + 0; + r = cache->reg_list + 0; if (!r->valid) { - retval = core_state == ARM_STATE_AARCH64 ? - dpmv8_read_reg(dpm, r, 0) : dpmv8_read_reg32(dpm, r, 0); + retval = dpmv8_read_reg(dpm, r, 0); if (retval != ERROR_OK) goto fail; } r->dirty = true; /* read cpsr to r0 and get it back */ - retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_DSPSR), &cpsr); + retval = dpm->instr_read_data_r0(dpm, + armv8_opcode(armv8, READ_REG_DSPSR), &cpsr); if (retval != ERROR_OK) goto fail; - /* update core mode and state, plus shadow mapping for R8..R14 */ + /* update core mode and state */ armv8_set_cpsr(arm, cpsr); - /* REVISIT we can probably avoid reading R1..R14, saving time... */ - for (unsigned i = 1; i < arm->core_cache->num_regs ; i++) { + for (unsigned int i = 1; i < cache->num_regs ; i++) { + struct arm_reg *arm_reg; + r = armv8_reg_current(arm, i); if (r->valid) continue; - retval = core_state == ARM_STATE_AARCH64 ? - dpmv8_read_reg(dpm, r, i) : dpmv8_read_reg32(dpm, r, i); + /* + * Only read registers that are available from the + * current EL (or core mode). + */ + arm_reg = r->arch_info; + if (arm_reg->mode != ARM_MODE_ANY && + dpm->last_el != armv8_curel_from_core_mode(arm_reg->mode)) + continue; + retval = dpmv8_read_reg(dpm, r, i); if (retval != ERROR_OK) goto fail; - } - - /* NOTE: SPSR ignored (if it's even relevant). */ - /* REVISIT the debugger can trigger various exceptions. See the - * ARMv7A architecture spec, section C5.7, for more info about - * what defenses are needed; v6 debug has the most issues. - */ + } fail: - /* (void) */ dpm->finish(dpm); + dpm->finish(dpm); return retval; } @@ -951,7 +835,6 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) struct arm *arm = dpm->arm; struct reg_cache *cache = arm->core_cache; int retval; - bool is_aarch64 = arm->core_state == ARM_STATE_AARCH64; retval = dpm->prepare(dpm); if (retval != ERROR_OK) @@ -991,59 +874,48 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) * be queued, and need (efficient/batched) flushing later. */ - /* Scan the registers until we find one that's both dirty and - * eligible for flushing. Flush that and everything else that - * shares the same core mode setting. Typically this won't - * actually find anything to do... - */ + /* Restore original core mode and state */ + retval = dpmv8_modeswitch(dpm, ARM_MODE_ANY); + if (retval != ERROR_OK) + goto done; /* check everything except our scratch register R0 */ for (unsigned i = 1; i < cache->num_regs; i++) { struct arm_reg *r; - unsigned regnum; - /* also skip PC, CPSR, and non-dirty */ - if (i == (arm->core_cache->num_regs - 2)) + /* skip PC and CPSR */ + if (i == ARMV8_PC || i == ARMV8_xPSR) continue; - if (arm->cpsr == cache->reg_list + i) + /* skip invalid */ + if (!cache->reg_list[i].valid) continue; + /* skip non-dirty */ if (!cache->reg_list[i].dirty) continue; + /* skip all registers not on the current EL */ r = cache->reg_list[i].arch_info; - regnum = r->num; + if (r->mode != ARM_MODE_ANY && + dpm->last_el != armv8_curel_from_core_mode(r->mode)) + continue; - retval = is_aarch64 ? dpmv8_write_reg(dpm, &cache->reg_list[i], regnum) - : dpmv8_write_reg32(dpm, &cache->reg_list[i], regnum); + retval = dpmv8_write_reg(dpm, &cache->reg_list[i], i); if (retval != ERROR_OK) - goto done; + break; } - - /* Restore original CPSR ... assuming either that we changed it, - * or it's dirty. Must write PC to ensure the return address is - * defined, and must not write it before CPSR. - */ - retval = dpmv8_modeswitch(dpm, ARM_MODE_ANY); - if (retval != ERROR_OK) - goto done; - arm->cpsr->dirty = false; - - retval = is_aarch64 ? dpmv8_write_reg(dpm, arm->pc, (arm->core_cache->num_regs - 2)) - : dpmv8_write_reg32(dpm, arm->pc, (arm->core_cache->num_regs - 2)); - if (retval != ERROR_OK) - goto done; - arm->pc->dirty = false; - + /* flush CPSR and PC */ + if (retval == ERROR_OK) + retval = dpmv8_write_reg(dpm, &cache->reg_list[ARMV8_xPSR], ARMV8_xPSR); + if (retval == ERROR_OK) + retval = dpmv8_write_reg(dpm, &cache->reg_list[ARMV8_PC], ARMV8_PC); /* flush R0 -- it's *very* dirty by now */ - retval = is_aarch64 ? dpmv8_write_reg(dpm, &cache->reg_list[0], 0) - : dpmv8_write_reg32(dpm, &cache->reg_list[0], 0); - if (retval != ERROR_OK) - goto done; - cache->reg_list[0].dirty = false; - - /* (void) */ dpm->finish(dpm); + if (retval == ERROR_OK) + retval = dpmv8_write_reg(dpm, &cache->reg_list[0], 0); + if (retval == ERROR_OK) + dpm->instr_cpsr_sync(dpm); done: + dpm->finish(dpm); return retval; } @@ -1061,19 +933,18 @@ static int armv8_dpm_read_core_reg(struct target *target, struct reg *r, int retval; int max = arm->core_cache->num_regs; - if (regnum < 0 || regnum > max) + if (regnum < 0 || regnum >= max) return ERROR_COMMAND_SYNTAX_ERROR; - /* REVISIT what happens if we try to read SPSR in a core mode + /* + * REVISIT what happens if we try to read SPSR in a core mode * which has no such register? */ - retval = dpm->prepare(dpm); if (retval != ERROR_OK) return retval; - retval = arm->core_state == ARM_STATE_AARCH64 ? - dpmv8_read_reg(dpm, r, regnum) : dpmv8_read_reg32(dpm, r, regnum); + retval = dpmv8_read_reg(dpm, r, regnum); if (retval != ERROR_OK) goto fail; @@ -1101,12 +972,11 @@ static int armv8_dpm_write_core_reg(struct target *target, struct reg *r, if (retval != ERROR_OK) return retval; - retval = arm->core_state == ARM_STATE_AARCH64 ? - dpmv8_write_reg(dpm, r, regnum) : dpmv8_write_reg32(dpm, r, regnum); + retval = dpmv8_write_reg(dpm, r, regnum); /* always clean up, regardless of error */ + dpm->finish(dpm); - /* (void) */ dpm->finish(dpm); return retval; } @@ -1402,6 +1272,7 @@ void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dscr) struct target *target = dpm->arm->target; dpm->dscr = dscr; + dpm->last_el = (dscr >> 8) & 3; /* Examine debug reason */ switch (DSCR_ENTRY(dscr)) { diff --git a/src/target/armv8_dpm.h b/src/target/armv8_dpm.h index 416f4df..6470461 100644 --- a/src/target/armv8_dpm.h +++ b/src/target/armv8_dpm.h @@ -111,5 +111,6 @@ void armv8_dpm_report_wfar(struct arm_dpm *, uint64_t wfar); #define PRSR_SDR (1 << 11) void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dcsr); +enum arm_state armv8_dpm_get_core_state(struct arm_dpm *dpm); #endif /* OPENOCD_TARGET_ARM_DPM_H */ diff --git a/src/target/armv8_opcodes.c b/src/target/armv8_opcodes.c index 78b60e0..3e18a02 100644 --- a/src/target/armv8_opcodes.c +++ b/src/target/armv8_opcodes.c @@ -37,16 +37,16 @@ static const uint32_t a64_opcodes[ARMV8_OPC_NUM] = { }; static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { - [READ_REG_CLIDR] = T32_FMTITR(ARMV4_5_MRC(15, 1, 0, 0, 0, 1)), - [READ_REG_CSSELR] = T32_FMTITR(ARMV4_5_MRC(15, 2, 0, 0, 0, 0)), - [READ_REG_CCSIDR] = T32_FMTITR(ARMV4_5_MRC(15, 1, 0, 0, 0, 0)), - [WRITE_REG_CSSELR] = T32_FMTITR(ARMV4_5_MCR(15, 2, 0, 0, 0, 0)), - [READ_REG_MPIDR] = T32_FMTITR(ARMV4_5_MRC(15, 0, 0, 0, 0, 5)), - [READ_REG_DTRRX] = T32_FMTITR(ARMV4_5_MRC(14, 0, 0, 0, 5, 0)), - [WRITE_REG_DTRTX] = T32_FMTITR(ARMV4_5_MCR(14, 0, 0, 0, 5, 0)), - [WRITE_REG_DSPSR] = T32_FMTITR(ARMV8_MCR_DSPSR(0)), - [READ_REG_DSPSR] = T32_FMTITR(ARMV8_MRC_DSPSR(0)), - [ARMV8_OPC_DSB_SY] = T32_FMTITR(ARMV8_DSB_SY_T1), + [READ_REG_CLIDR] = ARMV4_5_MRC(15, 1, 0, 0, 0, 1), + [READ_REG_CSSELR] = ARMV4_5_MRC(15, 2, 0, 0, 0, 0), + [READ_REG_CCSIDR] = ARMV4_5_MRC(15, 1, 0, 0, 0, 0), + [WRITE_REG_CSSELR] = ARMV4_5_MCR(15, 2, 0, 0, 0, 0), + [READ_REG_MPIDR] = ARMV4_5_MRC(15, 0, 0, 0, 0, 5), + [READ_REG_DTRRX] = ARMV4_5_MRC(14, 0, 0, 0, 5, 0), + [WRITE_REG_DTRTX] = ARMV4_5_MCR(14, 0, 0, 0, 5, 0), + [WRITE_REG_DSPSR] = ARMV8_MCR_DSPSR(0), + [READ_REG_DSPSR] = ARMV8_MRC_DSPSR(0), + [ARMV8_OPC_DSB_SY] = ARMV8_DSB_SY_T1, }; void armv8_select_opcodes(struct armv8_common *armv8, bool state_is_aarch64) diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index 41abe04..cb20c84 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -66,7 +66,6 @@ #define SYSTEM_ISR_EL1 0b1100011000001000 - #define SYSTEM_DBG_DSPSR_EL0 0b1101101000101000 #define SYSTEM_DBG_DLR_EL0 0b1101101000101001 #define SYSTEM_DBG_DTRRX_EL0 0b1001100000101000 @@ -103,14 +102,19 @@ #define SYSTEM_ATS1E2R 0b0110001111000000 #define SYSTEM_ATS1E3R 0b0111001111000000 +/* fault status and fault address */ +#define SYSTEM_FAR_EL1 0b1100001100000000 +#define SYSTEM_FAR_EL2 0b1110001100000000 +#define SYSTEM_FAR_EL3 0b1111001100000000 +#define SYSTEM_ESR_EL1 0b1100001010010000 +#define SYSTEM_ESR_EL2 0b1110001010010000 +#define SYSTEM_ESR_EL3 0b1111001010010000 + #define ARMV8_MRS_DSPSR(Rt) (0xd53b4500 | (Rt)) #define ARMV8_MSR_DSPSR(Rt) (0xd51b4500 | (Rt)) #define ARMV8_MRS_DLR(Rt) (0xd53b4520 | (Rt)) #define ARMV8_MSR_DLR(Rt) (0xd51b4520 | (Rt)) -/* T32 ITR format */ -#define T32_FMTITR(instr) (((instr & 0x0000FFFF) << 16) | ((instr & 0xFFFF0000) >> 16)) - /* T32 instruction to access coprocessor registers */ #define ARMV8_MCR_T1(cp, CRn, opc1, CRm, opc2, Rt) ARMV4_5_MCR(cp, opc1, Rt, CRn, CRm, opc2) #define ARMV8_MRC_T1(cp, CRn, opc1, CRm, opc2, Rt) ARMV4_5_MRC(cp, opc1, Rt, CRn, CRm, opc2) @@ -136,6 +140,11 @@ #define ARMV8_MSR_IM(Op1, CRm, Op2) \ (0xd500401f | ((Op1) << 16) | ((CRm) << 8) | ((Op2) << 5)) +#define ARMV8_MRS_T1(R, M1, Rd, M) (0xF3E08020 | (R << 20) | (M1 << 16) | (Rd << 8) | (M << 4)) +#define ARMV8_MRS_xPSR_T1(R, Rd) (0xF3EF8000 | (R << 20) | (Rd << 8)) +#define ARMV8_MSR_GP_T1(R, M1, Rd, M) (0xF3808020 | (R << 20) | (M1 << 8) | (Rd << 16) | (M << 4)) +#define ARMV8_MSR_GP_xPSR_T1(R, Rn, mask) (0xF3808000 | (R << 20) | (Rn << 16) | (mask << 8)) + #define ARMV8_BKPT(Im) (0xD4200000 | ((Im & 0xffff) << 5)) #define ARMV8_HLT(Im) (0x0D4400000 | ((Im & 0xffff) << 5)) -- cgit v1.1 From 946958cb723f0b123505234275ce9a653ddbfbd2 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 20 Oct 2016 11:31:40 +0200 Subject: aarch64: fix mode switching DCPS only allows to enter higher ELs, for lower ELs you need to use DRPS. Also, of course the encoding differs between A64 and T32. Both DCPS and DRPS also clobber DLR and DSPSR, which then need to be restored on resume. Change-Id: Ifa3dcfa94212702e57170bd59fd0bb25495fb6fd Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 6 +-- src/target/armv8.c | 16 ++++-- src/target/armv8_dpm.c | 128 +++++++++++++++++++++++++++++++-------------- src/target/armv8_dpm.h | 2 +- src/target/armv8_opcodes.c | 6 ++- src/target/armv8_opcodes.h | 12 +++-- 6 files changed, 119 insertions(+), 51 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 02f17d8..88e10c1 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -487,7 +487,7 @@ static int aarch64_internal_restore(struct target *target, int current, buf_set_u64(arm->pc->value, 0, 64, resume_pc); arm->pc->dirty = 1; arm->pc->valid = 1; - dpmv8_modeswitch(&armv8->dpm, ARM_MODE_ANY); + armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY); /* called it now before restoring context because it uses cpu * register r0 for restoring system control register */ @@ -697,7 +697,7 @@ static int aarch64_post_debug_entry(struct target *target) switch (armv8->arm.core_mode) { case ARMV8_64_EL0T: - dpmv8_modeswitch(&armv8->dpm, ARMV8_64_EL1T); + armv8_dpm_modeswitch(&armv8->dpm, ARMV8_64_EL1H); /* fall through */ case ARMV8_64_EL1T: case ARMV8_64_EL1H: @@ -738,7 +738,7 @@ static int aarch64_post_debug_entry(struct target *target) break; } - dpmv8_modeswitch(&armv8->dpm, ARM_MODE_ANY); + armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY); LOG_DEBUG("System_register: %8.8" PRIx32, aarch64->system_control_reg); aarch64->system_control_reg_curr = aarch64->system_control_reg; diff --git a/src/target/armv8.c b/src/target/armv8.c index 32fe048..b55c153 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -781,6 +781,7 @@ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, struct armv8_common *armv8 = target_to_armv8(target); struct arm *arm = target_to_arm(target); struct arm_dpm *dpm = &armv8->dpm; + enum arm_mode target_mode = ARM_MODE_ANY; uint32_t retval; uint32_t instr = 0; uint64_t par; @@ -801,12 +802,12 @@ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, case SYSTEM_CUREL_EL0: instr = ARMV8_SYS(SYSTEM_ATS12E0R, 0); /* can only execute instruction at EL2 */ - dpmv8_modeswitch(dpm, ARMV8_64_EL2T); + target_mode = ARMV8_64_EL2H; break; case SYSTEM_CUREL_EL1: instr = ARMV8_SYS(SYSTEM_ATS12E1R, 0); /* can only execute instruction at EL2 */ - dpmv8_modeswitch(dpm, ARMV8_64_EL2T); + target_mode = ARMV8_64_EL2H; break; case SYSTEM_CUREL_EL2: instr = ARMV8_SYS(SYSTEM_ATS1E2R, 0); @@ -819,16 +820,23 @@ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, break; }; + if (target_mode != ARM_MODE_ANY) + armv8_dpm_modeswitch(dpm, target_mode); + /* write VA to R0 and execute translation instruction */ retval = dpm->instr_write_data_r0_64(dpm, instr, (uint64_t)va); /* read result from PAR_EL1 */ if (retval == ERROR_OK) retval = dpm->instr_read_data_r0_64(dpm, ARMV8_MRS(SYSTEM_PAR_EL1, 0), &par); + /* switch back to saved PE mode */ + if (target_mode != ARM_MODE_ANY) + armv8_dpm_modeswitch(dpm, ARM_MODE_ANY); + dpm->finish(dpm); - /* switch back to saved PE mode */ - dpmv8_modeswitch(dpm, ARM_MODE_ANY); + if (retval != ERROR_OK) + return retval; if (retval != ERROR_OK) return retval; diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index a92f92c..d6f2b87 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -610,53 +610,103 @@ static int dpmv8_msr(struct target *target, uint32_t op0, * Register access utilities */ -/* Toggles between recorded core mode (USR, SVC, etc) and a temporary one. - * Routines *must* restore the original mode before returning!! - */ -int dpmv8_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) +int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) { struct armv8_common *armv8 = (struct armv8_common *)dpm->arm->arch_info; - int retval; + int retval = ERROR_OK; + unsigned int target_el; + enum arm_state core_state; uint32_t cpsr; /* restore previous mode */ - if (mode == ARM_MODE_ANY) + if (mode == ARM_MODE_ANY) { cpsr = buf_get_u32(dpm->arm->cpsr->value, 0, 32); - /* else force to the specified mode */ - else - cpsr = mode >> 4; + LOG_DEBUG("restoring mode, cpsr = 0x%08"PRIx32, cpsr); - switch ((cpsr & 0xC) >> 2) { - case SYSTEM_CUREL_EL1: - retval = dpm->instr_execute(dpm, ARMV8_DCPS1(11)); - if (retval != ERROR_OK) - return retval; - break; - case SYSTEM_CUREL_EL2: - retval = dpm->instr_execute(dpm, ARMV8_DCPS2(11)); - if (retval != ERROR_OK) - return retval; - break; - break; - case SYSTEM_CUREL_EL3: - retval = dpm->instr_execute(dpm, ARMV8_DCPS3(11)); - if (retval != ERROR_OK) - return retval; - break; - break; - default: - LOG_DEBUG("unknow mode 0x%x", (unsigned) ((cpsr & 0xC) >> 2)); - break; + } else { + LOG_DEBUG("setting mode 0x%"PRIx32, mode); + + /* else force to the specified mode */ + if (is_arm_mode(mode)) + cpsr = mode; + else + cpsr = mode >> 4; } + switch (cpsr & 0x1f) { + /* aarch32 modes */ + case ARM_MODE_USR: + target_el = 0; + break; + case ARM_MODE_SVC: + case ARM_MODE_ABT: + case ARM_MODE_IRQ: + case ARM_MODE_FIQ: + target_el = 1; + break; + /* + * TODO: handle ARM_MODE_HYP + * case ARM_MODE_HYP: + * target_el = 2; + * break; + */ + case ARM_MODE_MON: + target_el = 3; + break; + /* aarch64 modes */ + default: + target_el = (cpsr >> 2) & 3; + } - retval = dpm->instr_write_data_r0(dpm, armv8_opcode(armv8, WRITE_REG_DSPSR), cpsr); - if (retval != ERROR_OK) - return retval; + if (target_el > SYSTEM_CUREL_EL3) { + LOG_ERROR("%s: Invalid target exception level %i", __func__, target_el); + return ERROR_FAIL; + } + + LOG_DEBUG("target_el = %i, last_el = %i", target_el, dpm->last_el); + if (target_el > dpm->last_el) { + retval = dpm->instr_execute(dpm, + armv8_opcode(armv8, ARMV8_OPC_DCPS) | target_el); + } else { + core_state = armv8_dpm_get_core_state(dpm); + if (core_state != ARM_STATE_AARCH64) { + /* cannot do DRPS/ERET when already in EL0 */ + if (dpm->last_el != 0) { + /* load SPSR with the desired mode and execute DRPS */ + LOG_DEBUG("SPSR = 0x%08"PRIx32, cpsr); + retval = dpm->instr_write_data_r0(dpm, + ARMV8_MSR_GP_xPSR_T1(1, 0, 15), cpsr); + if (retval == ERROR_OK) + retval = dpm->instr_execute(dpm, armv8_opcode(armv8, ARMV8_OPC_DRPS)); + } + } else { + /* + * need to execute multiple DRPS instructions until target_el + * is reached + */ + while (retval == ERROR_OK && dpm->last_el != target_el) { + unsigned int cur_el = dpm->last_el; + retval = dpm->instr_execute(dpm, armv8_opcode(armv8, ARMV8_OPC_DRPS)); + if (cur_el == dpm->last_el) { + LOG_INFO("Cannot reach EL %i, SPSR corrupted?", target_el); + break; + } + } + } - if (dpm->instr_cpsr_sync) - retval = dpm->instr_cpsr_sync(dpm); + /* On executing DRPS, DSPSR and DLR become UNKNOWN, mark them as dirty */ + dpm->arm->cpsr->dirty = true; + dpm->arm->pc->dirty = true; + + /* + * re-evaluate the core state, we might be in Aarch32 state now + * we rely on dpm->dscr being up-to-date + */ + core_state = armv8_dpm_get_core_state(dpm); + armv8_select_opcodes(armv8, core_state == ARM_STATE_AARCH64); + armv8_select_reg_access(armv8, core_state == ARM_STATE_AARCH64); + } return retval; } @@ -875,7 +925,7 @@ int armv8_dpm_write_dirty_registers(struct arm_dpm *dpm, bool bpwp) */ /* Restore original core mode and state */ - retval = dpmv8_modeswitch(dpm, ARM_MODE_ANY); + retval = armv8_dpm_modeswitch(dpm, ARM_MODE_ANY); if (retval != ERROR_OK) goto done; @@ -1022,9 +1072,9 @@ static int armv8_dpm_full_context(struct target *target) * in FIQ mode we need to patch mode. */ if (mode != ARM_MODE_ANY) - retval = dpmv8_modeswitch(dpm, mode); + retval = armv8_dpm_modeswitch(dpm, mode); else - retval = dpmv8_modeswitch(dpm, ARM_MODE_USR); + retval = armv8_dpm_modeswitch(dpm, ARM_MODE_USR); if (retval != ERROR_OK) goto done; @@ -1042,7 +1092,7 @@ static int armv8_dpm_full_context(struct target *target) } while (did_read); - retval = dpmv8_modeswitch(dpm, ARM_MODE_ANY); + retval = armv8_dpm_modeswitch(dpm, ARM_MODE_ANY); /* (void) */ dpm->finish(dpm); done: return retval; diff --git a/src/target/armv8_dpm.h b/src/target/armv8_dpm.h index 6470461..48e2ca1 100644 --- a/src/target/armv8_dpm.h +++ b/src/target/armv8_dpm.h @@ -32,7 +32,7 @@ int armv8_dpm_setup(struct arm_dpm *dpm); int armv8_dpm_initialize(struct arm_dpm *dpm); int armv8_dpm_read_current_registers(struct arm_dpm *); -int dpmv8_modeswitch(struct arm_dpm *dpm, enum arm_mode mode); +int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode); int armv8_dpm_write_dirty_registers(struct arm_dpm *, bool bpwp); diff --git a/src/target/armv8_opcodes.c b/src/target/armv8_opcodes.c index 3e18a02..75ea946 100644 --- a/src/target/armv8_opcodes.c +++ b/src/target/armv8_opcodes.c @@ -33,7 +33,9 @@ static const uint32_t a64_opcodes[ARMV8_OPC_NUM] = { [WRITE_REG_DTRTX] = ARMV8_MSR_GP(SYSTEM_DBG_DTRTX_EL0, 0), [WRITE_REG_DSPSR] = ARMV8_MSR_DSPSR(0), [READ_REG_DSPSR] = ARMV8_MRS_DSPSR(0), - [ARMV8_OPC_DSB_SY] = ARMV8_DSB_SY, + [ARMV8_OPC_DSB_SY] = ARMV8_DSB_SY, + [ARMV8_OPC_DCPS] = ARMV8_DCPS(0, 11), + [ARMV8_OPC_DRPS] = ARMV8_DRPS, }; static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { @@ -47,6 +49,8 @@ static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { [WRITE_REG_DSPSR] = ARMV8_MCR_DSPSR(0), [READ_REG_DSPSR] = ARMV8_MRC_DSPSR(0), [ARMV8_OPC_DSB_SY] = ARMV8_DSB_SY_T1, + [ARMV8_OPC_DCPS] = ARMV8_DCPS_T1(0), + [ARMV8_OPC_DRPS] = ARMV8_ERET_T1, }; void armv8_select_opcodes(struct armv8_common *armv8, bool state_is_aarch64) diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index cb20c84..e57e7e9 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -125,9 +125,13 @@ #define ARMV8_MRC_DLR(Rt) ARMV8_MRC_T1(15, 4, 3, 5, 1, Rt) #define ARMV8_MCR_DLR(Rt) ARMV8_MCR_T1(15, 4, 3, 5, 1, Rt) -#define ARMV8_DCPS1(IM) (0xd4a00001 | (((IM) & 0xFFFF) << 5)) -#define ARMV8_DCPS2(IM) (0xd4a00002 | (((IM) & 0xFFFF) << 5)) -#define ARMV8_DCPS3(IM) (0xd4a00003 | (((IM) & 0xFFFF) << 5)) +#define ARMV8_DCPS1(IM) (0xd4a00001 | (((IM) & 0xFFFF) << 5)) +#define ARMV8_DCPS2(IM) (0xd4a00002 | (((IM) & 0xFFFF) << 5)) +#define ARMV8_DCPS3(IM) (0xd4a00003 | (((IM) & 0xFFFF) << 5)) +#define ARMV8_DCPS(EL, IM) (0xd4a00000 | (((IM) & 0xFFFF) << 5) | EL) +#define ARMV8_DCPS_T1(EL) (0xf78f8000 | EL) +#define ARMV8_DRPS 0xd6bf03e0 +#define ARMV8_ERET_T1 0xf3de8f00 #define ARMV8_DSB_SY 0xd5033F9F #define ARMV8_DSB_SY_T1 0xf3bf8f4f @@ -166,6 +170,8 @@ enum armv8_opcode { WRITE_REG_DSPSR, READ_REG_DSPSR, ARMV8_OPC_DSB_SY, + ARMV8_OPC_DCPS, + ARMV8_OPC_DRPS, ARMV8_OPC_NUM, }; -- cgit v1.1 From 62c2eb4b284e0a3deb2aad7163354200bd93e634 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 20 Oct 2016 13:20:26 +0200 Subject: aarch64: cache identification for aarch32 state Use proper T32 opcodes for cache identification when the PE is in Aarch32 state Change-Id: I9cd9169409889273a3fd61167f388e68d8dde86d Signed-off-by: Matthias Welwarsky --- src/target/armv8_cache.c | 17 +++++++++++------ src/target/armv8_opcodes.c | 2 ++ src/target/armv8_opcodes.h | 1 + 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/target/armv8_cache.c b/src/target/armv8_cache.c index f496c3c..31e4c79 100644 --- a/src/target/armv8_cache.c +++ b/src/target/armv8_cache.c @@ -266,17 +266,18 @@ static int armv8_flush_all_data(struct target *target) static int get_cache_info(struct arm_dpm *dpm, int cl, int ct, uint32_t *cache_reg) { + struct armv8_common *armv8 = dpm->arm->arch_info; int retval = ERROR_OK; /* select cache level */ retval = dpm->instr_write_data_r0(dpm, - ARMV8_MSR_GP(SYSTEM_CSSELR, 0), + armv8_opcode(armv8, WRITE_REG_CSSELR), (cl << 1) | (ct == 1 ? 1 : 0)); if (retval != ERROR_OK) goto done; retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS(SYSTEM_CCSIDR, 0), + armv8_opcode(armv8, READ_REG_CCSIDR), cache_reg); done: return retval; @@ -319,7 +320,8 @@ int armv8_identify_cache(struct armv8_common *armv8) goto done; /* retrieve CTR */ - retval = dpm->instr_read_data_r0(dpm, ARMV8_MRS(SYSTEM_CTR, 0), &ctr); + retval = dpm->instr_read_data_r0(dpm, + armv8_opcode(armv8, READ_REG_CTR), &ctr); if (retval != ERROR_OK) goto done; @@ -329,7 +331,8 @@ int armv8_identify_cache(struct armv8_common *armv8) ctr, cache->iminline, cache->dminline); /* retrieve CLIDR */ - retval = dpm->instr_read_data_r0(dpm, ARMV8_MRS(SYSTEM_CLIDR, 0), &clidr); + retval = dpm->instr_read_data_r0(dpm, + armv8_opcode(armv8, READ_REG_CLIDR), &clidr); if (retval != ERROR_OK) goto done; @@ -338,7 +341,8 @@ int armv8_identify_cache(struct armv8_common *armv8) /* retrieve selected cache for later restore * MRC p15, 2,, c0, c0, 0; Read CSSELR */ - retval = dpm->instr_read_data_r0(dpm, ARMV8_MRS(SYSTEM_CSSELR, 0), &csselr); + retval = dpm->instr_read_data_r0(dpm, + armv8_opcode(armv8, READ_REG_CSSELR), &csselr); if (retval != ERROR_OK) goto done; @@ -396,7 +400,8 @@ int armv8_identify_cache(struct armv8_common *armv8) } /* restore selected cache */ - dpm->instr_write_data_r0(dpm, ARMV8_MSR_GP(SYSTEM_CSSELR, 0), csselr); + dpm->instr_write_data_r0(dpm, + armv8_opcode(armv8, WRITE_REG_CSSELR), csselr); if (retval != ERROR_OK) goto done; diff --git a/src/target/armv8_opcodes.c b/src/target/armv8_opcodes.c index 75ea946..2b42cdf 100644 --- a/src/target/armv8_opcodes.c +++ b/src/target/armv8_opcodes.c @@ -24,6 +24,7 @@ #include "armv8_opcodes.h" static const uint32_t a64_opcodes[ARMV8_OPC_NUM] = { + [READ_REG_CTR] = ARMV8_MRS(SYSTEM_CTR, 0), [READ_REG_CLIDR] = ARMV8_MRS(SYSTEM_CLIDR, 0), [READ_REG_CSSELR] = ARMV8_MRS(SYSTEM_CSSELR, 0), [READ_REG_CCSIDR] = ARMV8_MRS(SYSTEM_CCSIDR, 0), @@ -39,6 +40,7 @@ static const uint32_t a64_opcodes[ARMV8_OPC_NUM] = { }; static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { + [READ_REG_CTR] = ARMV4_5_MRC(15, 0, 0, 0, 0, 1), [READ_REG_CLIDR] = ARMV4_5_MRC(15, 1, 0, 0, 0, 1), [READ_REG_CSSELR] = ARMV4_5_MRC(15, 2, 0, 0, 0, 0), [READ_REG_CCSIDR] = ARMV4_5_MRC(15, 1, 0, 0, 0, 0), diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index e57e7e9..b489d57 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -160,6 +160,7 @@ #define ARMV8_SYS(System, Rt) (0xD5080000 | ((System) << 5) | Rt) enum armv8_opcode { + READ_REG_CTR, READ_REG_CLIDR, READ_REG_CSSELR, READ_REG_CCSIDR, -- cgit v1.1 From c30f8d6a0716bb8151cd787d99dca65aa9845ed2 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 20 Oct 2016 13:37:11 +0200 Subject: aarch64: handle exceptions taken in debug state When an armv8-a PE causes an exception while halted, e.g. by performing a prohibited memory or register access, its state is affected in the same way as if it was running. That means, a number of registers is overwritten (notably DLR and DSPSR, but also others) and also potentially the exception level and therefore also the PE state can change. This state must be restored before resuming normal operation. This is done by marking the relevant cached registers "dirty" so that they are written back before resume. Change-Id: I9b6967a62d7cb23a477a9f7839f8d2b7087eed09 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 2 ++ src/target/armv8_dpm.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/target/armv8_dpm.h | 1 + 3 files changed, 60 insertions(+) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 88e10c1..ce4a8f6 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1492,6 +1492,7 @@ static int aarch64_write_apb_ap_memory(struct target *target, LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); mem_ap_write_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DRCR, 1<<2); + armv8_dpm_handle_exception(dpm); goto error_free_buff_w; } @@ -1657,6 +1658,7 @@ static int aarch64_read_apb_ap_memory(struct target *target, LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); mem_ap_write_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); + armv8_dpm_handle_exception(dpm); goto error_free_buff_r; } diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index d6f2b87..ee9e1f3 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -279,6 +279,7 @@ static int dpmv8_exec_opcode(struct arm_dpm *dpm, /* clear the sticky error condition */ mem_ap_write_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); + armv8_dpm_handle_exception(dpm); retval = ERROR_FAIL; } @@ -668,6 +669,9 @@ int armv8_dpm_modeswitch(struct arm_dpm *dpm, enum arm_mode mode) if (target_el > dpm->last_el) { retval = dpm->instr_execute(dpm, armv8_opcode(armv8, ARMV8_OPC_DCPS) | target_el); + + /* DCPS clobbers registers just like an exception taken */ + armv8_dpm_handle_exception(dpm); } else { core_state = armv8_dpm_get_core_state(dpm); if (core_state != ARM_STATE_AARCH64) { @@ -1311,6 +1315,59 @@ void armv8_dpm_report_wfar(struct arm_dpm *dpm, uint64_t addr) dpm->wp_pc = addr; } +/* + * Handle exceptions taken in debug state. This happens mostly for memory + * accesses that violated a MMU policy. Taking an exception while in debug + * state clobbers certain state registers on the target exception level. + * Just mark those registers dirty so that they get restored on resume. + * This works both for Aarch32 and Aarch64 states. + * + * This function must not perform any actions that trigger another exception + * or a recursion will happen. + */ +void armv8_dpm_handle_exception(struct arm_dpm *dpm) +{ + struct armv8_common *armv8 = dpm->arm->arch_info; + struct reg_cache *cache = dpm->arm->core_cache; + enum arm_state core_state; + uint64_t dlr; + uint32_t dspsr; + unsigned int el; + + static const int clobbered_regs_by_el[3][5] = { + { ARMV8_PC, ARMV8_xPSR, ARMV8_ELR_EL1, ARMV8_ESR_EL1, ARMV8_SPSR_EL1 }, + { ARMV8_PC, ARMV8_xPSR, ARMV8_ELR_EL2, ARMV8_ESR_EL2, ARMV8_SPSR_EL2 }, + { ARMV8_PC, ARMV8_xPSR, ARMV8_ELR_EL3, ARMV8_ESR_EL3, ARMV8_SPSR_EL3 }, + }; + + el = (dpm->dscr >> 8) & 3; + + /* safety check, must not happen since EL0 cannot be a target for an exception */ + if (el < SYSTEM_CUREL_EL1 || el > SYSTEM_CUREL_EL3) { + LOG_ERROR("%s: EL %i is invalid, DSCR corrupted?", __func__, el); + return; + } + + armv8->read_reg_u64(armv8, ARMV8_xPSR, &dlr); + dspsr = dlr; + armv8->read_reg_u64(armv8, ARMV8_PC, &dlr); + + LOG_DEBUG("Exception taken to EL %i, DLR=0x%016"PRIx64" DSPSR=0x%08"PRIx32, + el, dlr, dspsr); + + /* mark all clobbered registers as dirty */ + for (int i = 0; i < 5; i++) + cache->reg_list[clobbered_regs_by_el[el-1][i]].dirty = true; + + /* + * re-evaluate the core state, we might be in Aarch64 state now + * we rely on dpm->dscr being up-to-date + */ + core_state = armv8_dpm_get_core_state(dpm); + armv8_select_opcodes(armv8, core_state == ARM_STATE_AARCH64); + armv8_select_reg_access(armv8, core_state == ARM_STATE_AARCH64); +} + /*----------------------------------------------------------------------*/ /* diff --git a/src/target/armv8_dpm.h b/src/target/armv8_dpm.h index 48e2ca1..133b367 100644 --- a/src/target/armv8_dpm.h +++ b/src/target/armv8_dpm.h @@ -111,6 +111,7 @@ void armv8_dpm_report_wfar(struct arm_dpm *, uint64_t wfar); #define PRSR_SDR (1 << 11) void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dcsr); +void armv8_dpm_handle_exception(struct arm_dpm *dpm); enum arm_state armv8_dpm_get_core_state(struct arm_dpm *dpm); #endif /* OPENOCD_TARGET_ARM_DPM_H */ -- cgit v1.1 From 05bf20d05afbcbb723c16cfa0e2f3a93edb435f7 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 20 Oct 2016 13:59:35 +0200 Subject: aarch64: make sure to enable HDE for all SMP PEs to be halted When halting a group of PEs through CTI, HDE must be set in EDSCR for all of them. Change-Id: Iaa4bc0b0fe31e46a463c709d8274023225affd85 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 55 ++++++++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index ce4a8f6..947c1ec 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -279,6 +279,28 @@ static int aarch64_dpm_setup(struct aarch64_common *a8, uint64_t debug) return retval; } +static int aarch64_set_dscr_bits(struct target *target, unsigned long bit_mask, unsigned long value) +{ + struct armv8_common *armv8 = target_to_armv8(target); + uint32_t dscr; + + /* Read DSCR */ + int retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); + if (ERROR_OK != retval) + return retval; + + /* clear bitfield */ + dscr &= ~bit_mask; + /* put new value */ + dscr |= value & bit_mask; + + /* write new DSCR */ + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DSCR, dscr); + return retval; +} + static struct target *get_aarch64(struct target *target, int32_t coreid) { struct target_list *head; @@ -305,9 +327,12 @@ static int aarch64_halt_smp(struct target *target) struct armv8_common *armv8 = target_to_armv8(curr); /* open the gate for channel 0 to let HALT requests pass to the CTM */ - if (curr->smp) + if (curr->smp) { retval = mem_ap_write_atomic_u32(armv8->debug_ap, armv8->cti_base + CTI_GATE, CTI_CHNL(0)); + if (retval == ERROR_OK) + retval = aarch64_set_dscr_bits(curr, DSCR_HDE, DSCR_HDE); + } if (retval != ERROR_OK) break; @@ -411,11 +436,7 @@ static int aarch64_halt(struct target *target) /* * add HDE in halting debug mode */ - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, &dscr); - if (retval == ERROR_OK) - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, dscr | DSCR_HDE); + retval = aarch64_set_dscr_bits(target, DSCR_HDE, DSCR_HDE); if (retval != ERROR_OK) return retval; @@ -758,28 +779,6 @@ static int aarch64_post_debug_entry(struct target *target) return ERROR_OK; } -static int aarch64_set_dscr_bits(struct target *target, unsigned long bit_mask, unsigned long value) -{ - struct armv8_common *armv8 = target_to_armv8(target); - uint32_t dscr; - - /* Read DSCR */ - int retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, &dscr); - if (ERROR_OK != retval) - return retval; - - /* clear bitfield */ - dscr &= ~bit_mask; - /* put new value */ - dscr |= value & bit_mask; - - /* write new DSCR */ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, dscr); - return retval; -} - static int aarch64_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { -- cgit v1.1 From ba822308560d691263ca26b16d5c9e7a856fb262 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 20 Oct 2016 14:46:11 +0200 Subject: aarch64: allow reading TTBR register when halted in EL0 There's no access to TTBR in EL0. Circumvent by moving the PE to EL1 before reading, and switch back to original mode afterwards. Change-Id: I22891b958d3d7e6fad1cb27183c192d975d63d89 Signed-off-by: Matthias Welwarsky --- src/target/armv8.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/target/armv8.c b/src/target/armv8.c index b55c153..089982e 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -737,6 +737,8 @@ static __unused int armv8_read_ttbcr(struct target *target) armv8->page_size = (ttbcr >> 14) & 3; break; case SYSTEM_CUREL_EL0: + armv8_dpm_modeswitch(dpm, ARMV8_64_EL1H); + /* fall through */ case SYSTEM_CUREL_EL1: retval = dpm->instr_read_data_r0_64(dpm, ARMV8_MRS(SYSTEM_TCR_EL1, 0), @@ -764,6 +766,7 @@ static __unused int armv8_read_ttbcr(struct target *target) LOG_INFO("TTBR0 access above %" PRIx64, (uint64_t)(armv8->armv8_mmu.ttbr0_mask)); done: + armv8_dpm_modeswitch(dpm, ARM_MODE_ANY); dpm->finish(dpm); return retval; } -- cgit v1.1 From ccb1199d490b86e0f963a1d0509c748c800f20d4 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 20 Oct 2016 15:36:19 +0200 Subject: aarch64: enable aarch32 debugging with arm gdb When a PE is in Aarch32 state and gdb asks for a target description, provide a register view compatible with the "org.gnu.gdb.arm.core" feature. Only current-mode registers are exported, banked registers are not visible. Change-Id: I99a85d94831cf597fe8cff6a0a1818ce0a33613b Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 1 + src/target/armv8.c | 190 +++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 164 insertions(+), 27 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 947c1ec..d7d557d 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -590,6 +590,7 @@ static int aarch64_internal_restart(struct target *target, bool slave_pe) /* registers are now invalid */ register_cache_invalidate(arm->core_cache); + register_cache_invalidate(arm->core_cache->next); return ERROR_OK; } diff --git a/src/target/armv8.c b/src/target/armv8.c index 089982e..a2a099d 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1012,12 +1012,39 @@ static const struct { { ARMV8_SPSR_EL3, "SPSR_EL3", 32, ARMV8_64_EL3H, REG_TYPE_UINT32, "banked", "net.sourceforge.openocd.banked" }, }; -#define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs) +static const struct { + unsigned id; + const char *name; + unsigned bits; + enum arm_mode mode; + enum reg_type type; + const char *group; + const char *feature; +} armv8_regs32[] = { + { ARMV8_R0, "r0", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_R1, "r1", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_R2, "r2", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_R3, "r3", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_R4, "r4", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_R5, "r5", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_R6, "r6", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_R7, "r7", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_R8, "r8", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_R9, "r9", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_R10, "r10", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_R11, "r11", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_R12, "r12", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_R13, "sp", 32, ARM_MODE_ANY, REG_TYPE_DATA_PTR, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_R14, "lr", 32, ARM_MODE_ANY, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_PC, "pc", 32, ARM_MODE_ANY, REG_TYPE_CODE_PTR, "general", "org.gnu.gdb.arm.core" }, + { ARMV8_xPSR, "cpsr", 32, ARM_MODE_ANY, REG_TYPE_UINT32, "general", "org.gnu.gdb.arm.core" }, +}; +#define ARMV8_NUM_REGS ARRAY_SIZE(armv8_regs) +#define ARMV8_NUM_REGS32 ARRAY_SIZE(armv8_regs32) static int armv8_get_core_reg(struct reg *reg) { - int retval; struct arm_reg *armv8_reg = reg->arch_info; struct target *target = armv8_reg->target; struct arm *arm = target_to_arm(target); @@ -1025,9 +1052,7 @@ static int armv8_get_core_reg(struct reg *reg) if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; - retval = arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode); - - return retval; + return arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode); } static int armv8_set_core_reg(struct reg *reg, uint8_t *buf) @@ -1057,25 +1082,83 @@ static const struct reg_arch_type armv8_reg_type = { .set = armv8_set_core_reg, }; +static int armv8_get_core_reg32(struct reg *reg) +{ + struct arm_reg *armv8_reg = reg->arch_info; + struct target *target = armv8_reg->target; + struct arm *arm = target_to_arm(target); + struct reg_cache *cache = arm->core_cache; + struct reg *reg64; + int retval; + + LOG_DEBUG("reg.name:%s number:%i arm.num:%i value:0x%08" PRIx64, + reg->name, reg->number, armv8_reg->num, buf_get_u64(reg->value, 0, 32)); + + /* get the corresponding Aarch64 register */ + reg64 = cache->reg_list + armv8_reg->num; + if (reg64->valid) { + reg->valid = true; + return ERROR_OK; + } + + retval = arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode); + if (retval == ERROR_OK) + reg->valid = reg64->valid; + + return retval; +} + +static int armv8_set_core_reg32(struct reg *reg, uint8_t *buf) +{ + struct arm_reg *armv8_reg = reg->arch_info; + struct target *target = armv8_reg->target; + struct arm *arm = target_to_arm(target); + struct reg_cache *cache = arm->core_cache; + struct reg *reg64 = cache->reg_list + armv8_reg->num; + uint32_t value = buf_get_u32(buf, 0, 32); + + if (target->state != TARGET_HALTED) + return ERROR_TARGET_NOT_HALTED; + + if (reg64 == arm->cpsr) { + armv8_set_cpsr(arm, value); + } else { + buf_set_u32(reg->value, 0, 32, value); + reg->valid = 1; + reg64->valid = 1; + } + + reg64->dirty = 1; + + return ERROR_OK; +} + +static const struct reg_arch_type armv8_reg32_type = { + .get = armv8_get_core_reg32, + .set = armv8_set_core_reg32, +}; + /** Builds cache of architecturally defined registers. */ struct reg_cache *armv8_build_reg_cache(struct target *target) { struct armv8_common *armv8 = target_to_armv8(target); struct arm *arm = &armv8->arm; int num_regs = ARMV8_NUM_REGS; + int num_regs32 = ARMV8_NUM_REGS32; struct reg_cache **cache_p = register_get_last_cache_p(&target->reg_cache); struct reg_cache *cache = malloc(sizeof(struct reg_cache)); + struct reg_cache *cache32 = malloc(sizeof(struct reg_cache)); struct reg *reg_list = calloc(num_regs, sizeof(struct reg)); + struct reg *reg_list32 = calloc(num_regs32, sizeof(struct reg)); struct arm_reg *arch_info = calloc(num_regs, sizeof(struct arm_reg)); struct reg_feature *feature; int i; /* Build the process context cache */ - cache->name = "arm v8 registers"; - cache->next = NULL; + cache->name = "Aarch64 registers"; + cache->next = cache32; cache->reg_list = reg_list; cache->num_regs = num_regs; - (*cache_p) = cache; for (i = 0; i < num_regs; i++) { arch_info[i].num = armv8_regs[i].id; @@ -1086,8 +1169,6 @@ struct reg_cache *armv8_build_reg_cache(struct target *target) reg_list[i].name = armv8_regs[i].name; reg_list[i].size = armv8_regs[i].bits; reg_list[i].value = calloc(1, 8); - reg_list[i].dirty = 0; - reg_list[i].valid = 0; reg_list[i].type = &armv8_reg_type; reg_list[i].arch_info = &arch_info[i]; @@ -1114,6 +1195,38 @@ struct reg_cache *armv8_build_reg_cache(struct target *target) arm->pc = reg_list + ARMV8_PC; arm->core_cache = cache; + /* shadow cache for ARM mode registers */ + cache32->name = "Aarch32 registers"; + cache32->next = NULL; + cache32->reg_list = reg_list32; + cache32->num_regs = num_regs32; + + for (i = 0; i < num_regs32; i++) { + reg_list32[i].name = armv8_regs32[i].name; + reg_list32[i].size = armv8_regs32[i].bits; + reg_list32[i].value = &arch_info[armv8_regs32[i].id].value[0]; + reg_list32[i].type = &armv8_reg32_type; + reg_list32[i].arch_info = &arch_info[armv8_regs32[i].id]; + reg_list32[i].group = armv8_regs32[i].group; + reg_list32[i].number = i; + reg_list32[i].exist = true; + reg_list32[i].caller_save = true; + + feature = calloc(1, sizeof(struct reg_feature)); + if (feature) { + feature->name = armv8_regs32[i].feature; + reg_list32[i].feature = feature; + } else + LOG_ERROR("unable to allocate feature list"); + + reg_list32[i].reg_data_type = calloc(1, sizeof(struct reg_data_type)); + if (reg_list32[i].reg_data_type) + reg_list32[i].reg_data_type->type = armv8_regs32[i].type; + else + LOG_ERROR("unable to allocate reg type list"); + } + + (*cache_p) = cache; return cache; } @@ -1143,27 +1256,50 @@ int armv8_get_gdb_reg_list(struct target *target, struct arm *arm = target_to_arm(target); int i; - switch (reg_class) { - case REG_CLASS_GENERAL: - *reg_list_size = ARMV8_ELR_EL1; - *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); + if (arm->core_state == ARM_STATE_AARCH64) { - for (i = 0; i < *reg_list_size; i++) - (*reg_list)[i] = armv8_reg_current(arm, i); + LOG_DEBUG("Creating Aarch64 register list"); - return ERROR_OK; - case REG_CLASS_ALL: - *reg_list_size = ARMV8_LAST_REG; - *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); + switch (reg_class) { + case REG_CLASS_GENERAL: + *reg_list_size = ARMV8_ELR_EL1; + *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); - for (i = 0; i < *reg_list_size; i++) - (*reg_list)[i] = armv8_reg_current(arm, i); + for (i = 0; i < *reg_list_size; i++) + (*reg_list)[i] = armv8_reg_current(arm, i); + return ERROR_OK; - return ERROR_OK; + case REG_CLASS_ALL: + *reg_list_size = ARMV8_LAST_REG; + *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); - default: - LOG_ERROR("not a valid register class type in query."); - return ERROR_FAIL; - break; + for (i = 0; i < *reg_list_size; i++) + (*reg_list)[i] = armv8_reg_current(arm, i); + + return ERROR_OK; + + default: + LOG_ERROR("not a valid register class type in query."); + return ERROR_FAIL; + } + } else { + struct reg_cache *cache32 = arm->core_cache->next; + + LOG_DEBUG("Creating Aarch32 register list"); + + switch (reg_class) { + case REG_CLASS_GENERAL: + case REG_CLASS_ALL: + *reg_list_size = cache32->num_regs; + *reg_list = malloc(sizeof(struct reg *) * (*reg_list_size)); + + for (i = 0; i < *reg_list_size; i++) + (*reg_list)[i] = cache32->reg_list + i; + + return ERROR_OK; + default: + LOG_ERROR("not a valid register class type in query."); + return ERROR_FAIL; + } } } -- cgit v1.1 From 0a53bae0ea4007f171802b7d5e65499d4aa18ad0 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 20 Oct 2016 15:39:30 +0200 Subject: aarch64: cleanup context restore Remove register cache invalidation and target state changes that are handled appropriately in other functions. Change-Id: Ic903f41ddc267f4b8765ea022bd4d6da1017e21f Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index d7d557d..1220004 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -504,25 +504,16 @@ static int aarch64_internal_restore(struct target *target, int current, LOG_ERROR("How do I resume into Jazelle state??"); return ERROR_FAIL; } - LOG_DEBUG("resume pc = 0x%16" PRIx64, resume_pc); + LOG_DEBUG("resume pc = 0x%016" PRIx64, resume_pc); buf_set_u64(arm->pc->value, 0, 64, resume_pc); arm->pc->dirty = 1; arm->pc->valid = 1; - armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY); /* called it now before restoring context because it uses cpu * register r0 for restoring system control register */ retval = aarch64_restore_system_control_reg(target); - if (retval != ERROR_OK) - return retval; - retval = aarch64_restore_context(target, handle_breakpoints); - if (retval != ERROR_OK) - return retval; - target->debug_reason = DBG_REASON_NOTHALTED; - target->state = TARGET_RUNNING; - - /* registers are now invalid */ - register_cache_invalidate(arm->core_cache); + if (retval == ERROR_OK) + retval = aarch64_restore_context(target, handle_breakpoints); return retval; } -- cgit v1.1 From 9f4b5b509f016a8c78f44d2a668784fa7fc10e3f Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 20 Oct 2016 16:23:40 +0200 Subject: aarch64: discard async aborts on entering debug state recommended for Corte-A8 cores, not sure if necessary for ARMv8 based cores as well. Change-Id: Ibcb36170c5fac6a6b132de17f734c70a56919f9b Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 7 ++++++- src/target/armv8_dpm.c | 7 ++++++- src/target/armv8_opcodes.c | 2 ++ src/target/armv8_opcodes.h | 3 +++ 4 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 1220004..110f8dc 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -663,11 +663,16 @@ static int aarch64_debug_entry(struct target *target) /* make sure to clear all sticky errors */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); + + /* discard async exceptions */ + if (retval == ERROR_OK) + retval = dpm->instr_cpsr_sync(dpm); + if (retval != ERROR_OK) return retval; /* Examine debug reason */ - armv8_dpm_report_dscr(&armv8->dpm, aarch64->cpudbg_dscr); + armv8_dpm_report_dscr(dpm, aarch64->cpudbg_dscr); /* save address of instruction that triggered the watchpoint? */ if (target->debug_reason == DBG_REASON_WATCHPOINT) { diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index ee9e1f3..8caa8b6 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -360,9 +360,14 @@ static int dpmv8_instr_write_data_r0_64(struct arm_dpm *dpm, static int dpmv8_instr_cpsr_sync(struct arm_dpm *dpm) { + int retval; struct armv8_common *armv8 = dpm->arm->arch_info; + /* "Prefetch flush" after modifying execution status in CPSR */ - return dpmv8_exec_opcode(dpm, armv8_opcode(armv8, ARMV8_OPC_DSB_SY), NULL); + retval = dpmv8_exec_opcode(dpm, armv8_opcode(armv8, ARMV8_OPC_DSB_SY), &dpm->dscr); + if (retval == ERROR_OK) + dpmv8_exec_opcode(dpm, armv8_opcode(armv8, ARMV8_OPC_ISB_SY), &dpm->dscr); + return retval; } static int dpmv8_instr_read_data_dcc(struct arm_dpm *dpm, diff --git a/src/target/armv8_opcodes.c b/src/target/armv8_opcodes.c index 2b42cdf..7790144 100644 --- a/src/target/armv8_opcodes.c +++ b/src/target/armv8_opcodes.c @@ -37,6 +37,7 @@ static const uint32_t a64_opcodes[ARMV8_OPC_NUM] = { [ARMV8_OPC_DSB_SY] = ARMV8_DSB_SY, [ARMV8_OPC_DCPS] = ARMV8_DCPS(0, 11), [ARMV8_OPC_DRPS] = ARMV8_DRPS, + [ARMV8_OPC_ISB_SY] = ARMV8_ISB, }; static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { @@ -53,6 +54,7 @@ static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { [ARMV8_OPC_DSB_SY] = ARMV8_DSB_SY_T1, [ARMV8_OPC_DCPS] = ARMV8_DCPS_T1(0), [ARMV8_OPC_DRPS] = ARMV8_ERET_T1, + [ARMV8_OPC_ISB_SY] = ARMV8_ISB_SY_T1, }; void armv8_select_opcodes(struct armv8_common *armv8, bool state_is_aarch64) diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index b489d57..fe6b28a 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -135,6 +135,8 @@ #define ARMV8_DSB_SY 0xd5033F9F #define ARMV8_DSB_SY_T1 0xf3bf8f4f +#define ARMV8_ISB 0xd5033fdf +#define ARMV8_ISB_SY_T1 0xf3bf8f6f #define ARMV8_MRS(System, Rt) (0xd5300000 | ((System) << 5) | (Rt)) /* ARM V8 Move to system register. */ @@ -173,6 +175,7 @@ enum armv8_opcode { ARMV8_OPC_DSB_SY, ARMV8_OPC_DCPS, ARMV8_OPC_DRPS, + ARMV8_OPC_ISB_SY, ARMV8_OPC_NUM, }; -- cgit v1.1 From f7dbcc3fab3d5b52710f235ae3ead3135cf9c2e6 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 6 Oct 2016 16:37:25 +0200 Subject: aarch64: consolidate sticky error handling Move clearing of DSCR "Sticky Error" condition to the exception handling function. Clear once on entering debug state. Change-Id: Iec1d09d6f2d9cdd7e92953da5ea19f3e399ca12c Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 25 +++---------------------- src/target/armv8_dpm.c | 13 ++++--------- 2 files changed, 7 insertions(+), 31 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 110f8dc..b716122 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -538,7 +538,9 @@ static int aarch64_internal_restart(struct target *target, bool slave_pe) return retval; if ((dscr & DSCR_ITE) == 0) - LOG_ERROR("DSCR InstrCompl must be set before leaving debug!"); + LOG_ERROR("DSCR.ITE must be set before leaving debug!"); + if ((dscr & DSCR_ERR) != 0) + LOG_ERROR("DSCR.ERR must be cleared before leaving debug!"); /* make sure to acknowledge the halt event before resuming */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, @@ -709,10 +711,6 @@ static int aarch64_post_debug_entry(struct target *target) struct armv8_common *armv8 = &aarch64->armv8_common; int retval; - /* clear sticky errors */ - mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); - switch (armv8->arm.core_mode) { case ARMV8_64_EL0T: armv8_dpm_modeswitch(&armv8->dpm, ARMV8_64_EL1H); @@ -1389,13 +1387,6 @@ static int aarch64_write_apb_ap_memory(struct target *target, reg = armv8_reg_current(arm, 0); reg->dirty = true; - /* clear any abort */ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); - if (retval != ERROR_OK) - return retval; - - /* This algorithm comes from DDI0487A.g, chapter J9.1 */ /* The algorithm only copies 32 bit words, so the buffer @@ -1486,8 +1477,6 @@ static int aarch64_write_apb_ap_memory(struct target *target, if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) { /* Abort occurred - clear it and exit */ LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); - mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, 1<<2); armv8_dpm_handle_exception(dpm); goto error_free_buff_w; } @@ -1547,12 +1536,6 @@ static int aarch64_read_apb_ap_memory(struct target *target, reg = armv8_reg_current(arm, 0); reg->dirty = true; - /* clear any abort */ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); - if (retval != ERROR_OK) - goto error_free_buff_r; - /* Read DSCR */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DSCR, &dscr); @@ -1652,8 +1635,6 @@ static int aarch64_read_apb_ap_memory(struct target *target, if (dscr & (DSCR_ERR | DSCR_SYS_ERROR_PEND)) { /* Abort occurred - clear it and exit */ LOG_ERROR("abort occurred - dscr = 0x%08" PRIx32, dscr); - mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); armv8_dpm_handle_exception(dpm); goto error_free_buff_r; } diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index 8caa8b6..ef53452 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -202,12 +202,6 @@ static int dpmv8_dpm_prepare(struct arm_dpm *dpm) armv8->debug_base + CPUV8_DBG_DTRRX, &dscr); if (retval != ERROR_OK) return retval; - - /* Clear sticky error */ - retval = mem_ap_write_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); - if (retval != ERROR_OK) - return retval; } return retval; @@ -276,9 +270,6 @@ static int dpmv8_exec_opcode(struct arm_dpm *dpm, if (dscr & DSCR_ERR) { LOG_ERROR("Opcode 0x%08"PRIx32", DSCR.ERR=1, DSCR.EL=%i", opcode, dpm->last_el); - /* clear the sticky error condition */ - mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); armv8_dpm_handle_exception(dpm); retval = ERROR_FAIL; } @@ -1353,6 +1344,10 @@ void armv8_dpm_handle_exception(struct arm_dpm *dpm) return; } + /* Clear sticky error */ + mem_ap_write_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); + armv8->read_reg_u64(armv8, ARMV8_xPSR, &dlr); dspsr = dlr; armv8->read_reg_u64(armv8, ARMV8_PC, &dlr); -- cgit v1.1 From 822ebda6747b747f5c366bc41f3cc897f344aee4 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 20 Oct 2016 16:48:42 +0200 Subject: aarch64: enlarge value buffer of arm_reg to store 64 bit struct arm_reg::value[] must be 8 byte to hold a 64bit register value. Change-Id: If253e90731d0ee855eafd9d7b63b91f84630cc7c Signed-off-by: Matthias Welwarsky --- src/target/arm.h | 2 +- src/target/armv8.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/target/arm.h b/src/target/arm.h index 2548038..e5e336d 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -235,7 +235,7 @@ struct arm_reg { enum arm_mode mode; struct target *target; struct arm *arm; - uint8_t value[4]; + uint8_t value[8]; }; struct reg_cache *arm_build_reg_cache(struct target *target, struct arm *arm); diff --git a/src/target/armv8.c b/src/target/armv8.c index a2a099d..54ec42f 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1168,7 +1168,7 @@ struct reg_cache *armv8_build_reg_cache(struct target *target) reg_list[i].name = armv8_regs[i].name; reg_list[i].size = armv8_regs[i].bits; - reg_list[i].value = calloc(1, 8); + reg_list[i].value = &arch_info[i].value[0]; reg_list[i].type = &armv8_reg_type; reg_list[i].arch_info = &arch_info[i]; -- cgit v1.1 From 7d537dc8e974084356bcd78eb4a193b07b5b745c Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 20 Oct 2016 16:59:21 +0200 Subject: aarch64: improve debug output Make debug and error messages more informative, fix spelling and formatting errors Change-Id: I7245f42c5153bcc95676270814d30e91c113aaed Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 11 ++++++----- src/target/armv8_dpm.c | 7 +++---- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index b716122..f0ac32c 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -389,7 +389,7 @@ static int aarch64_poll(struct target *target) if (DSCR_RUN_MODE(dscr) == 0x3) { if (prev_target_state != TARGET_HALTED) { /* We have a halting debug event */ - LOG_DEBUG("Target halted"); + LOG_DEBUG("Target %s halted", target_name(target)); target->state = TARGET_HALTED; if ((prev_target_state == TARGET_RUNNING) || (prev_target_state == TARGET_UNKNOWN) @@ -839,13 +839,12 @@ static int aarch64_restore_context(struct target *target, bool bpwp) { struct armv8_common *armv8 = target_to_armv8(target); - LOG_DEBUG(" "); + LOG_DEBUG("%s", target_name(target)); if (armv8->pre_restore_context) armv8->pre_restore_context(target); return armv8_dpm_write_dirty_registers(&armv8->dpm, bpwp); - } /* @@ -1367,8 +1366,9 @@ static int aarch64_write_apb_ap_memory(struct target *target, uint32_t dscr; uint8_t *tmp_buff = NULL; - LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx64 " size %" PRIu32 " count%" PRIu32, + LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx64 " size %" PRIu32 " count %" PRIu32, address, size, count); + if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; @@ -1517,8 +1517,9 @@ static int aarch64_read_apb_ap_memory(struct target *target, uint8_t *u8buf_ptr; uint32_t value; - LOG_DEBUG("Reading APB-AP memory address 0x%" TARGET_PRIxADDR " size %" PRIu32 " count%" PRIu32, + LOG_DEBUG("Reading APB-AP memory address 0x%" TARGET_PRIxADDR " size %" PRIu32 " count %" PRIu32, address, size, count); + if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index ef53452..0188753 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -79,8 +79,7 @@ static int dpmv8_write_dcc(struct armv8_common *armv8, uint32_t data) static int dpmv8_write_dcc_64(struct armv8_common *armv8, uint64_t data) { int ret; - LOG_DEBUG("write DCC Low word 0x%08" PRIx32, (unsigned)data); - LOG_DEBUG("write DCC High word 0x%08" PRIx32, (unsigned)(data >> 32)); + LOG_DEBUG("write DCC 0x%016" PRIx64, data); ret = mem_ap_write_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DTRRX, data); ret += mem_ap_write_u32(armv8->debug_ap, @@ -143,7 +142,7 @@ static int dpmv8_read_dcc_64(struct armv8_common *armv8, uint64_t *data, if (retval != ERROR_OK) return retval; if (timeval_ms() > then + 1000) { - LOG_ERROR("Timeout waiting for read dcc"); + LOG_ERROR("Timeout waiting for DTR_TX_FULL, dscr = 0x%08" PRIx32, dscr); return ERROR_FAIL; } } @@ -1305,7 +1304,7 @@ void armv8_dpm_report_wfar(struct arm_dpm *dpm, uint64_t addr) /* ?? */ break; default: - LOG_DEBUG("Unknow core_state"); + LOG_DEBUG("Unknown core_state"); break; } dpm->wp_pc = addr; -- cgit v1.1 From 2407721e1487d14ecabf83793f929307e94eb452 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 20 Oct 2016 17:06:13 +0200 Subject: aarch64: remove unused struct components remove unused register index array from armv8_mode_data[] Change-Id: I686c20eeb3da413f5e9ef6058e31ce939741afb4 Signed-off-by: Matthias Welwarsky --- src/target/armv8.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 54ec42f..94a0e8e 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -46,11 +46,6 @@ static const char * const armv8_state_strings[] = { static const struct { const char *name; unsigned psr; - /* For user and system modes, these list indices for all registers. - * otherwise they're just indices for the shadow registers and SPSR. - */ - unsigned short n_indices; - const uint8_t *indices; } armv8_mode_data[] = { /* These special modes are currently only supported * by ARMv6M and ARMv7M profiles */ -- cgit v1.1 From 8f59ee387184a20c1e736aee45b5541d73755935 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 20 Oct 2016 17:13:36 +0200 Subject: aarch64: remove "mrs , currentel" opcode "currentel" special register is not accessible in debug state. Change-Id: I9022b01b423cd9ae8227ed018d6166078ba44832 Signed-off-by: Matthias Welwarsky --- src/target/armv8_opcodes.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index fe6b28a..53dcb7e 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -17,11 +17,6 @@ #include "arm_opcodes.h" -/* ARM V8 Move from system register to general purpose register - * R = 1: SPSR R = 0: CPSR - * Rn: target register - */ -#define SYSTEM_CUREL 0b1100001000010010 #define SYSTEM_CUREL_MASK 0xC0 #define SYSTEM_CUREL_SHIFT 6 #define SYSTEM_CUREL_EL0 0x0 -- cgit v1.1 From 91663206635022bfcb30b92e8462a773c225a77a Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 20 Oct 2016 17:15:00 +0200 Subject: aarch64: remove arm command chain from aarch64 target commands arm commands are mostly unusable anyway, remove them. to be replaced by aarch64 specific commands later Change-Id: Ie994771bc0e86cff1c26f68f1f51ce8ec352a509 Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index f0ac32c..4871738 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2126,9 +2126,6 @@ static const struct command_registration aarch64_exec_command_handlers[] = { }; static const struct command_registration aarch64_command_handlers[] = { { - .chain = arm_command_handlers, - }, - { .chain = armv8_command_handlers, }, { -- cgit v1.1 From 9d2e8aabb82ad440e14fd03d4007122c076eecb4 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 20 Oct 2016 17:22:26 +0200 Subject: aarch64: use cached value of dscr register where needed Instead of supplying a local, preinitialized "dscr" variable, use the cached value from arm_dpm, which is kept up-to-date anyway. Change-Id: I06d548d4dc6db68b9d984c83ed026fa9069d7875 Signed-off-by: Matthias Welwarsky --- src/target/armv8_dpm.c | 46 +++++++++++++++++++++------------------------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index 0188753..b4c14c2 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -82,7 +82,8 @@ static int dpmv8_write_dcc_64(struct armv8_common *armv8, uint64_t data) LOG_DEBUG("write DCC 0x%016" PRIx64, data); ret = mem_ap_write_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DTRRX, data); - ret += mem_ap_write_u32(armv8->debug_ap, + if (ret == ERROR_OK) + ret = mem_ap_write_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DTRTX, data >> 32); return ret; } @@ -174,7 +175,7 @@ static int dpmv8_dpm_prepare(struct arm_dpm *dpm) uint32_t dscr; int retval; - /* set up invariant: INSTR_COMP is set after ever DPM operation */ + /* set up invariant: ITE is set after ever DPM operation */ long long then = timeval_ms(); for (;; ) { retval = mem_ap_read_atomic_u32(armv8->debug_ap, @@ -216,7 +217,7 @@ static int dpmv8_exec_opcode(struct arm_dpm *dpm, uint32_t opcode, uint32_t *p_dscr) { struct armv8_common *armv8 = dpm->arm->arch_info; - uint32_t dscr = DSCR_ITE; + uint32_t dscr = dpm->dscr; int retval; LOG_DEBUG("exec opcode 0x%08" PRIx32, opcode); @@ -333,19 +334,18 @@ static int dpmv8_instr_write_data_r0_64(struct arm_dpm *dpm, uint32_t opcode, uint64_t data) { struct armv8_common *armv8 = dpm->arm->arch_info; - uint32_t dscr = DSCR_ITE; int retval; + /* transfer data from DCC to R0 */ retval = dpmv8_write_dcc_64(armv8, data); - if (retval != ERROR_OK) - return retval; - - retval = dpmv8_exec_opcode(dpm, ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), &dscr); - if (retval != ERROR_OK) - return retval; + if (retval == ERROR_OK) + retval = dpmv8_exec_opcode(dpm, ARMV8_MRS(SYSTEM_DBG_DBGDTR_EL0, 0), &dpm->dscr); /* then the opcode, taking data from R0 */ - return dpmv8_exec_opcode(dpm, opcode, &dscr); + if (retval == ERROR_OK) + retval = dpmv8_exec_opcode(dpm, opcode, &dpm->dscr); + + return retval; } static int dpmv8_instr_cpsr_sync(struct arm_dpm *dpm) @@ -364,70 +364,66 @@ static int dpmv8_instr_read_data_dcc(struct arm_dpm *dpm, uint32_t opcode, uint32_t *data) { struct armv8_common *armv8 = dpm->arm->arch_info; - uint32_t dscr = DSCR_ITE; int retval; /* the opcode, writing data to DCC */ - retval = dpmv8_exec_opcode(dpm, opcode, &dscr); + retval = dpmv8_exec_opcode(dpm, opcode, &dpm->dscr); if (retval != ERROR_OK) return retval; - return dpmv8_read_dcc(armv8, data, &dscr); + return dpmv8_read_dcc(armv8, data, &dpm->dscr); } static int dpmv8_instr_read_data_dcc_64(struct arm_dpm *dpm, uint32_t opcode, uint64_t *data) { struct armv8_common *armv8 = dpm->arm->arch_info; - uint32_t dscr = DSCR_ITE; int retval; /* the opcode, writing data to DCC */ - retval = dpmv8_exec_opcode(dpm, opcode, &dscr); + retval = dpmv8_exec_opcode(dpm, opcode, &dpm->dscr); if (retval != ERROR_OK) return retval; - return dpmv8_read_dcc_64(armv8, data, &dscr); + return dpmv8_read_dcc_64(armv8, data, &dpm->dscr); } static int dpmv8_instr_read_data_r0(struct arm_dpm *dpm, uint32_t opcode, uint32_t *data) { struct armv8_common *armv8 = dpm->arm->arch_info; - uint32_t dscr = DSCR_ITE; int retval; /* the opcode, writing data to R0 */ - retval = dpmv8_exec_opcode(dpm, opcode, &dscr); + retval = dpmv8_exec_opcode(dpm, opcode, &dpm->dscr); if (retval != ERROR_OK) return retval; /* write R0 to DCC */ - retval = dpmv8_exec_opcode(dpm, armv8_opcode(armv8, WRITE_REG_DTRTX), &dscr); + retval = dpmv8_exec_opcode(dpm, armv8_opcode(armv8, WRITE_REG_DTRTX), &dpm->dscr); if (retval != ERROR_OK) return retval; - return dpmv8_read_dcc(armv8, data, &dscr); + return dpmv8_read_dcc(armv8, data, &dpm->dscr); } static int dpmv8_instr_read_data_r0_64(struct arm_dpm *dpm, uint32_t opcode, uint64_t *data) { struct armv8_common *armv8 = dpm->arm->arch_info; - uint32_t dscr = DSCR_ITE; int retval; /* the opcode, writing data to R0 */ - retval = dpmv8_exec_opcode(dpm, opcode, &dscr); + retval = dpmv8_exec_opcode(dpm, opcode, &dpm->dscr); if (retval != ERROR_OK) return retval; /* write R0 to DCC */ - retval = dpmv8_exec_opcode(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 0), &dscr); + retval = dpmv8_exec_opcode(dpm, ARMV8_MSR_GP(SYSTEM_DBG_DBGDTR_EL0, 0), &dpm->dscr); if (retval != ERROR_OK) return retval; - return dpmv8_read_dcc_64(armv8, data, &dscr); + return dpmv8_read_dcc_64(armv8, data, &dpm->dscr); } #if 0 -- cgit v1.1 From beece50670e86c36d0de987c581db5250604695c Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 21 Oct 2016 16:59:28 +0200 Subject: aarch64: don't segfault on reset when target is not examined Basically port a fix that was already done for the cortex_a target. Change-Id: I4cf4519159bda03ed611bc0b2e340a5dad2d85fe Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 4871738..cabeb9c 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1316,7 +1316,8 @@ static int aarch64_assert_reset(struct target *target) } /* registers are now invalid */ - register_cache_invalidate(armv8->arm.core_cache); + if (target_was_examined(target)) + register_cache_invalidate(armv8->arm.core_cache); target->state = TARGET_RESET; @@ -1332,6 +1333,9 @@ static int aarch64_deassert_reset(struct target *target) /* be certain SRST is off */ jtag_add_reset(0, 0); + if (!target_was_examined(target)) + return ERROR_OK; + retval = aarch64_poll(target); if (retval != ERROR_OK) return retval; -- cgit v1.1 From 7c2dc138b32291e12e68ecd0391053d66efd53aa Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 21 Oct 2016 17:00:54 +0200 Subject: aarch64: don't try resuming if target is not halted At framework level, the resume hook is not protected. Make sure to not attempt a resume if the target is not halted. Change-Id: I4dd1975a95d6c513bd4f4e999e496bc11182a97a Signed-off-by: Matthias Welwarsky --- src/target/aarch64.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index cabeb9c..0a6b67f 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -624,6 +624,10 @@ static int aarch64_resume(struct target *target, int current, target_call_event_callbacks(target, TARGET_EVENT_RESUMED); return 0; } + + if (target->state != TARGET_HALTED) + return ERROR_TARGET_NOT_HALTED; + aarch64_internal_restore(target, current, &addr, handle_breakpoints, debug_execution); if (target->smp) { -- cgit v1.1 From 091c378728456bffec86218de0c2f0669144f053 Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Sun, 31 May 2015 02:18:36 +0000 Subject: flash/nor: avrf: support atmega128rfa1 Tested with a Dresden Elektronik deRFmega128 module. Change-Id: I91da3b11b60e78755360b08453ed368d6d396651 Signed-off-by: Karl Palsson Reviewed-on: http://openocd.zylin.com/2790 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/flash/nor/avrf.c | 1 + tcl/target/atmega128rfa1.cfg | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 tcl/target/atmega128rfa1.cfg diff --git a/src/flash/nor/avrf.c b/src/flash/nor/avrf.c index 627418c..11cc3b2 100644 --- a/src/flash/nor/avrf.c +++ b/src/flash/nor/avrf.c @@ -66,6 +66,7 @@ static const struct avrf_type avft_chips_info[] = { * eeprom_page_size, eeprom_page_num */ {"atmega128", 0x9702, 256, 512, 8, 512}, + {"atmega128rfa1", 0xa701, 128, 512, 8, 512}, {"at90can128", 0x9781, 256, 512, 8, 512}, {"at90usb128", 0x9782, 256, 512, 8, 512}, {"atmega164p", 0x940a, 128, 128, 4, 128}, diff --git a/tcl/target/atmega128rfa1.cfg b/tcl/target/atmega128rfa1.cfg new file mode 100644 index 0000000..2c12a61 --- /dev/null +++ b/tcl/target/atmega128rfa1.cfg @@ -0,0 +1,22 @@ +set _CHIPNAME avr +set _ENDIAN little + +# jtag speed +adapter_khz 4500 + +# avr jtag docs never connect RSTN +reset_config none + +#jtag scan chain +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x0a70103f +} +jtag newtap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME avr -endian $_ENDIAN -chain-position $_TARGETNAME + +set _FLASHNAME $_CHIPNAME.flash +flash bank $_FLASHNAME avr 0 0 0 0 $_TARGETNAME -- cgit v1.1 From 7c85165bc1a606883faa9bec51ebefbc652301f4 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 12 Feb 2017 10:59:49 +0100 Subject: aarch64: Fix #include guards MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I9445b04a210dcde5f8a7cf1560ef23eb53149178 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3975 Tested-by: jenkins Reviewed-by: Andreas Färber Reviewed-by: Matthias Welwarsky Reviewed-by: Paul Fertser --- src/target/aarch64.h | 6 +++--- src/target/armv8.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/target/aarch64.h b/src/target/aarch64.h index 513f06d..9491623 100644 --- a/src/target/aarch64.h +++ b/src/target/aarch64.h @@ -16,8 +16,8 @@ * Free Software Foundation, Inc., * ***************************************************************************/ -#ifndef AARCH64_H -#define AARCH64_H +#ifndef OPENOCD_TARGET_AARCH64_H +#define OPENOCD_TARGET_AARCH64_H #include "armv8.h" @@ -75,4 +75,4 @@ target_to_aarch64(struct target *target) return container_of(target->arch_info, struct aarch64_common, armv8_common.arm); } -#endif /* AARCH64_H */ +#endif /* OPENOCD_TARGET_AARCH64_H */ diff --git a/src/target/armv8.h b/src/target/armv8.h index 85845e6..3b2fc59 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -310,4 +310,4 @@ void armv8_select_reg_access(struct armv8_common *armv8, bool is_aarch64); extern const struct command_registration armv8_command_handlers[]; -#endif +#endif /* OPENOCD_TARGET_ARMV8_H */ -- cgit v1.1 From 5d00fd9d1dc504335dd71e474a3d61dec7696c40 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Wed, 26 Oct 2016 17:32:43 +0200 Subject: aarch64: fix software breakpoints when in aarch32 state Use the correct opcode for Aarch32 state, both for the breakpoint instruction itself and the cache handling functions. Change-Id: I975fa67b1e577b54f5c672a01d516419c6a614b2 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3981 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/aarch64.c | 2 +- src/target/armv8_cache.c | 11 ++++++----- src/target/armv8_dpm.c | 11 +++++++++++ src/target/armv8_opcodes.c | 8 ++++++++ src/target/armv8_opcodes.h | 5 +++++ 5 files changed, 31 insertions(+), 6 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 0a6b67f..833dc7a 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -915,7 +915,7 @@ static int aarch64_set_breakpoint(struct target *target, } else if (breakpoint->type == BKPT_SOFT) { uint8_t code[4]; - buf_set_u32(code, 0, 32, ARMV8_HLT(0x11)); + buf_set_u32(code, 0, 32, armv8_opcode(armv8, ARMV8_OPC_HLT)); retval = target_read_memory(target, breakpoint->address & 0xFFFFFFFFFFFFFFFE, breakpoint->length, 1, diff --git a/src/target/armv8_cache.c b/src/target/armv8_cache.c index 31e4c79..7f610c9 100644 --- a/src/target/armv8_cache.c +++ b/src/target/armv8_cache.c @@ -49,8 +49,9 @@ static int armv8_i_cache_sanity_check(struct armv8_common *armv8) return ERROR_TARGET_INVALID; } -static int armv8_cache_d_inner_flush_level(struct arm_dpm *dpm, struct armv8_cachesize *size, int cl) +static int armv8_cache_d_inner_flush_level(struct armv8_common *armv8, struct armv8_cachesize *size, int cl) { + struct arm_dpm *dpm = armv8->arm.dpm; int retval = ERROR_OK; int32_t c_way, c_index = size->index; @@ -65,7 +66,7 @@ static int armv8_cache_d_inner_flush_level(struct arm_dpm *dpm, struct armv8_cac * line by Set/Way. */ retval = dpm->instr_write_data_r0(dpm, - ARMV8_SYS(SYSTEM_DCCISW, 0), value); + armv8_opcode(armv8, ARMV8_OPC_DCCISW), value); if (retval != ERROR_OK) goto done; c_way -= 1; @@ -97,7 +98,7 @@ static int armv8_cache_d_inner_clean_inval_all(struct armv8_common *armv8) if (cache->arch[cl].ctype < CACHE_LEVEL_HAS_D_CACHE) continue; - armv8_cache_d_inner_flush_level(dpm, &cache->arch[cl].d_u_size, cl); + armv8_cache_d_inner_flush_level(armv8, &cache->arch[cl].d_u_size, cl); } retval = dpm->finish(dpm); @@ -133,7 +134,7 @@ int armv8_cache_d_inner_flush_virt(struct armv8_common *armv8, target_addr_t va, /* DC CIVAC */ /* Aarch32: DCCIMVAC: ARMV4_5_MCR(15, 0, 0, 7, 14, 1) */ retval = dpm->instr_write_data_r0_64(dpm, - ARMV8_SYS(SYSTEM_DCCIVAC, 0), va_line); + armv8_opcode(armv8, ARMV8_OPC_DCCIVAC), va_line); if (retval != ERROR_OK) goto done; va_line += linelen; @@ -171,7 +172,7 @@ int armv8_cache_i_inner_inval_virt(struct armv8_common *armv8, target_addr_t va, while (va_line < va_end) { /* IC IVAU - Invalidate instruction cache by VA to PoU. */ retval = dpm->instr_write_data_r0_64(dpm, - ARMV8_SYS(SYSTEM_ICIVAU, 0), va_line); + armv8_opcode(armv8, ARMV8_OPC_ICIVAU), va_line); if (retval != ERROR_OK) goto done; va_line += linelen; diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index b4c14c2..b06e456 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -336,6 +336,9 @@ static int dpmv8_instr_write_data_r0_64(struct arm_dpm *dpm, struct armv8_common *armv8 = dpm->arm->arch_info; int retval; + if (dpm->arm->core_state != ARM_STATE_AARCH64) + return dpmv8_instr_write_data_r0(dpm, opcode, data); + /* transfer data from DCC to R0 */ retval = dpmv8_write_dcc_64(armv8, data); if (retval == ERROR_OK) @@ -413,6 +416,14 @@ static int dpmv8_instr_read_data_r0_64(struct arm_dpm *dpm, struct armv8_common *armv8 = dpm->arm->arch_info; int retval; + if (dpm->arm->core_state != ARM_STATE_AARCH64) { + uint32_t tmp; + retval = dpmv8_instr_read_data_r0(dpm, opcode, &tmp); + if (retval == ERROR_OK) + *data = tmp; + return retval; + } + /* the opcode, writing data to R0 */ retval = dpmv8_exec_opcode(dpm, opcode, &dpm->dscr); if (retval != ERROR_OK) diff --git a/src/target/armv8_opcodes.c b/src/target/armv8_opcodes.c index 7790144..d3c0b3f 100644 --- a/src/target/armv8_opcodes.c +++ b/src/target/armv8_opcodes.c @@ -38,6 +38,10 @@ static const uint32_t a64_opcodes[ARMV8_OPC_NUM] = { [ARMV8_OPC_DCPS] = ARMV8_DCPS(0, 11), [ARMV8_OPC_DRPS] = ARMV8_DRPS, [ARMV8_OPC_ISB_SY] = ARMV8_ISB, + [ARMV8_OPC_DCCISW] = ARMV8_SYS(SYSTEM_DCCISW, 0), + [ARMV8_OPC_DCCIVAC] = ARMV8_SYS(SYSTEM_DCCIVAC, 0), + [ARMV8_OPC_ICIVAU] = ARMV8_SYS(SYSTEM_ICIVAU, 0), + [ARMV8_OPC_HLT] = ARMV8_HLT(11), }; static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { @@ -55,6 +59,10 @@ static const uint32_t t32_opcodes[ARMV8_OPC_NUM] = { [ARMV8_OPC_DCPS] = ARMV8_DCPS_T1(0), [ARMV8_OPC_DRPS] = ARMV8_ERET_T1, [ARMV8_OPC_ISB_SY] = ARMV8_ISB_SY_T1, + [ARMV8_OPC_DCCISW] = ARMV4_5_MCR(15, 0, 0, 7, 14, 2), + [ARMV8_OPC_DCCIVAC] = ARMV4_5_MCR(15, 0, 0, 7, 14, 1), + [ARMV8_OPC_ICIVAU] = ARMV4_5_MCR(15, 0, 0, 7, 5, 1), + [ARMV8_OPC_HLT] = ARMV8_HLT_A1(11), }; void armv8_select_opcodes(struct armv8_common *armv8, bool state_is_aarch64) diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index 53dcb7e..94694bc 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -148,6 +148,7 @@ #define ARMV8_BKPT(Im) (0xD4200000 | ((Im & 0xffff) << 5)) #define ARMV8_HLT(Im) (0x0D4400000 | ((Im & 0xffff) << 5)) +#define ARMV8_HLT_A1(Im) (0xE1000070 | ((Im & 0xFFF0) << 4) | (Im & 0xF)) #define ARMV8_MOVFSP_64(Rt) ((1 << 31) | 0x11000000 | (0x1f << 5) | (Rt)) #define ARMV8_MOVTSP_64(Rt) ((1 << 31) | 0x11000000 | (Rt << 5) | (0x1F)) @@ -171,6 +172,10 @@ enum armv8_opcode { ARMV8_OPC_DCPS, ARMV8_OPC_DRPS, ARMV8_OPC_ISB_SY, + ARMV8_OPC_DCCISW, + ARMV8_OPC_DCCIVAC, + ARMV8_OPC_ICIVAU, + ARMV8_OPC_HLT, ARMV8_OPC_NUM, }; -- cgit v1.1 From f988f5960450cf9e8c456bf8e3b4d2008e35a207 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Mon, 14 Nov 2016 12:18:43 +0100 Subject: aarch64: refactor SCTLR manipulation Reduce SLOCs in SCTLR retrieval and modification functions and make them less complex. Change-Id: Ida1a99c223743247f171b52eef80dc9886802101 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3982 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/aarch64.c | 229 +++++++++++++++++++-------------------------- src/target/armv8_opcodes.h | 4 + 2 files changed, 98 insertions(+), 135 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 833dc7a..7bd3d3c 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -49,7 +49,9 @@ static int aarch64_read_apb_ap_memory(struct target *target, static int aarch64_restore_system_control_reg(struct target *target) { + enum arm_mode target_mode = ARM_MODE_ANY; int retval = ERROR_OK; + uint32_t instr; struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = target_to_armv8(target); @@ -59,41 +61,45 @@ static int aarch64_restore_system_control_reg(struct target *target) /* LOG_INFO("cp15_control_reg: %8.8" PRIx32, cortex_v8->cp15_control_reg); */ switch (armv8->arm.core_mode) { - case ARMV8_64_EL0T: - case ARMV8_64_EL1T: - case ARMV8_64_EL1H: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 0, 1, /* op1, op2 */ - 0, 0, /* CRn, CRm */ - aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; + case ARMV8_64_EL0T: + target_mode = ARMV8_64_EL1H; + /* fall through */ + case ARMV8_64_EL1T: + case ARMV8_64_EL1H: + instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL1, 0); break; - case ARMV8_64_EL2T: - case ARMV8_64_EL2H: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 4, 1, /* op1, op2 */ - 0, 0, /* CRn, CRm */ - aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; + case ARMV8_64_EL2T: + case ARMV8_64_EL2H: + instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL2, 0); break; - case ARMV8_64_EL3H: - case ARMV8_64_EL3T: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 6, 1, /* op1, op2 */ - 0, 0, /* CRn, CRm */ - aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; + case ARMV8_64_EL3H: + case ARMV8_64_EL3T: + instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL3, 0); break; - default: - retval = armv8->arm.mcr(target, 15, 0, 0, 1, 0, aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; - break; - } + + case ARM_MODE_SVC: + case ARM_MODE_ABT: + case ARM_MODE_FIQ: + case ARM_MODE_IRQ: + instr = ARMV4_5_MCR(15, 0, 0, 1, 0, 0); + break; + + default: + LOG_INFO("cannot read system control register in this mode"); + return ERROR_FAIL; + } + + if (target_mode != ARM_MODE_ANY) + armv8_dpm_modeswitch(&armv8->dpm, target_mode); + + retval = armv8->dpm.instr_write_data_r0(&armv8->dpm, instr, aarch64->system_control_reg); + if (retval != ERROR_OK) + return retval; + + if (target_mode != ARM_MODE_ANY) + armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY); } + return retval; } @@ -112,6 +118,7 @@ static int aarch64_mmu_modify(struct target *target, int enable) struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = &aarch64->armv8_common; int retval = ERROR_OK; + uint32_t instr = 0; if (enable) { /* if mmu enabled at target stop and mmu not enable */ @@ -119,86 +126,42 @@ static int aarch64_mmu_modify(struct target *target, int enable) LOG_ERROR("trying to enable mmu on target stopped with mmu disable"); return ERROR_FAIL; } - if (!(aarch64->system_control_reg_curr & 0x1U)) { + if (!(aarch64->system_control_reg_curr & 0x1U)) aarch64->system_control_reg_curr |= 0x1U; - switch (armv8->arm.core_mode) { - case ARMV8_64_EL0T: - case ARMV8_64_EL1T: - case ARMV8_64_EL1H: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 0, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - aarch64->system_control_reg_curr); - if (retval != ERROR_OK) - return retval; - break; - case ARMV8_64_EL2T: - case ARMV8_64_EL2H: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 4, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - aarch64->system_control_reg_curr); - if (retval != ERROR_OK) - return retval; - break; - case ARMV8_64_EL3H: - case ARMV8_64_EL3T: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 6, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - aarch64->system_control_reg_curr); - if (retval != ERROR_OK) - return retval; - break; - default: - LOG_DEBUG("unknow cpu state 0x%x" PRIx32, armv8->arm.core_state); - } - } } else { if (aarch64->system_control_reg_curr & 0x4U) { /* data cache is active */ aarch64->system_control_reg_curr &= ~0x4U; - /* flush data cache armv7 function to be called */ + /* flush data cache armv8 function to be called */ if (armv8->armv8_mmu.armv8_cache.flush_all_data_cache) armv8->armv8_mmu.armv8_cache.flush_all_data_cache(target); } if ((aarch64->system_control_reg_curr & 0x1U)) { aarch64->system_control_reg_curr &= ~0x1U; - switch (armv8->arm.core_mode) { - case ARMV8_64_EL0T: - case ARMV8_64_EL1T: - case ARMV8_64_EL1H: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 0, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - aarch64->system_control_reg_curr); - if (retval != ERROR_OK) - return retval; - break; - case ARMV8_64_EL2T: - case ARMV8_64_EL2H: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 4, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - aarch64->system_control_reg_curr); - if (retval != ERROR_OK) - return retval; - break; - case ARMV8_64_EL3H: - case ARMV8_64_EL3T: - retval = armv8->arm.msr(target, 3, /*op 0*/ - 6, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - aarch64->system_control_reg_curr); - if (retval != ERROR_OK) - return retval; - break; - default: - LOG_DEBUG("unknow cpu state 0x%x" PRIx32, armv8->arm.core_state); - break; - } } } + + switch (armv8->arm.core_mode) { + case ARMV8_64_EL0T: + case ARMV8_64_EL1T: + case ARMV8_64_EL1H: + instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL1, 0); + break; + case ARMV8_64_EL2T: + case ARMV8_64_EL2H: + instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL2, 0); + break; + case ARMV8_64_EL3H: + case ARMV8_64_EL3T: + instr = ARMV8_MSR_GP(SYSTEM_SCTLR_EL3, 0); + break; + default: + LOG_DEBUG("unknown cpu state 0x%x" PRIx32, armv8->arm.core_state); + break; + } + + retval = armv8->dpm.instr_write_data_r0(&armv8->dpm, instr, + aarch64->system_control_reg_curr); return retval; } @@ -714,51 +677,47 @@ static int aarch64_post_debug_entry(struct target *target) struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = &aarch64->armv8_common; int retval; + enum arm_mode target_mode = ARM_MODE_ANY; + uint32_t instr; switch (armv8->arm.core_mode) { - case ARMV8_64_EL0T: - armv8_dpm_modeswitch(&armv8->dpm, ARMV8_64_EL1H); - /* fall through */ - case ARMV8_64_EL1T: - case ARMV8_64_EL1H: - retval = armv8->arm.mrs(target, 3, /*op 0*/ - 0, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - &aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; + case ARMV8_64_EL0T: + target_mode = ARMV8_64_EL1H; + /* fall through */ + case ARMV8_64_EL1T: + case ARMV8_64_EL1H: + instr = ARMV8_MRS(SYSTEM_SCTLR_EL1, 0); break; - case ARMV8_64_EL2T: - case ARMV8_64_EL2H: - retval = armv8->arm.mrs(target, 3, /*op 0*/ - 4, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - &aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; + case ARMV8_64_EL2T: + case ARMV8_64_EL2H: + instr = ARMV8_MRS(SYSTEM_SCTLR_EL2, 0); break; - case ARMV8_64_EL3H: - case ARMV8_64_EL3T: - retval = armv8->arm.mrs(target, 3, /*op 0*/ - 6, 0, /* op1, op2 */ - 1, 0, /* CRn, CRm */ - &aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; + case ARMV8_64_EL3H: + case ARMV8_64_EL3T: + instr = ARMV8_MRS(SYSTEM_SCTLR_EL3, 0); break; - case ARM_MODE_SVC: - retval = armv8->arm.mrc(target, 15, 0, 0, 1, 0, &aarch64->system_control_reg); - if (retval != ERROR_OK) - return retval; - break; + case ARM_MODE_SVC: + case ARM_MODE_ABT: + case ARM_MODE_FIQ: + case ARM_MODE_IRQ: + instr = ARMV4_5_MRC(15, 0, 0, 1, 0, 0); + break; - default: - LOG_INFO("cannot read system control register in this mode"); - break; + default: + LOG_INFO("cannot read system control register in this mode"); + return ERROR_FAIL; } - armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY); + if (target_mode != ARM_MODE_ANY) + armv8_dpm_modeswitch(&armv8->dpm, target_mode); + + retval = armv8->dpm.instr_read_data_r0(&armv8->dpm, instr, &aarch64->system_control_reg); + if (retval != ERROR_OK) + return retval; + + if (target_mode != ARM_MODE_ANY) + armv8_dpm_modeswitch(&armv8->dpm, ARM_MODE_ANY); LOG_DEBUG("System_register: %8.8" PRIx32, aarch64->system_control_reg); aarch64->system_control_reg_curr = aarch64->system_control_reg; diff --git a/src/target/armv8_opcodes.h b/src/target/armv8_opcodes.h index 94694bc..2d8ddd8 100644 --- a/src/target/armv8_opcodes.h +++ b/src/target/armv8_opcodes.h @@ -42,6 +42,10 @@ #define SYSTEM_ELR_EL2 0b1110001000000001 #define SYSTEM_ELR_EL3 0b1111001000000001 +#define SYSTEM_SCTLR_EL1 0b1100000010000000 +#define SYSTEM_SCTLR_EL2 0b1110000010000000 +#define SYSTEM_SCTLR_EL3 0b1111000010000000 + #define SYSTEM_FPCR 0b1101101000100000 #define SYSTEM_FPSR 0b1101101000100001 #define SYSTEM_DAIF 0b1101101000010001 -- cgit v1.1 From 06ba5492df66e997eafe294fced505b11e67f2fc Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Mon, 14 Nov 2016 12:23:24 +0100 Subject: aarch64: remove mrs/msr functions from struct arm No longer needed, no users. Change-Id: I0cc82a0ef11e1b72101fa9145f014e5d5d76df0e Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3983 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/arm.h | 12 ----------- src/target/armv8_dpm.c | 58 -------------------------------------------------- 2 files changed, 70 deletions(-) diff --git a/src/target/arm.h b/src/target/arm.h index e5e336d..d63ead2 100644 --- a/src/target/arm.h +++ b/src/target/arm.h @@ -189,18 +189,6 @@ struct arm { uint32_t CRn, uint32_t CRm, uint32_t value); - /** Read coprocessor register. */ - int (*mrs)(struct target *target, uint32_t op0, - uint32_t op1, uint32_t op2, - uint32_t CRn, uint32_t CRm, - uint32_t *value); - - /** Write coprocessor register. */ - int (*msr)(struct target *target, uint32_t cpnum, - uint32_t op1, uint32_t op2, - uint32_t CRn, uint32_t CRm, - uint32_t value); - void *arch_info; /** For targets conforming to ARM Debug Interface v5, diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index b06e456..acfd1bc 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -551,62 +551,6 @@ static int dpmv8_mcr(struct target *target, int cpnum, return retval; } -static int dpmv8_mrs(struct target *target, uint32_t op0, - uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, - uint32_t *value) -{ - struct arm *arm = target_to_arm(target); - struct arm_dpm *dpm = arm->dpm; - int retval; - uint32_t op_code; - - retval = dpm->prepare(dpm); - if (retval != ERROR_OK) - return retval; - op_code = ((op0 & 0x3) << 19 | (op1 & 0x7) << 16 | (CRn & 0xF) << 12 |\ - (CRm & 0xF) << 8 | (op2 & 0x7) << 5); - op_code >>= 5; - LOG_DEBUG("MRS p%d, %d, r0, c%d, c%d, %d", (int)op0, - (int) op1, (int) CRn, - (int) CRm, (int) op2); - /* read coprocessor register into R0; return via DCC */ - retval = dpm->instr_read_data_r0(dpm, - ARMV8_MRS(op_code, 0), - value); - - /* (void) */ dpm->finish(dpm); - return retval; -} - -static int dpmv8_msr(struct target *target, uint32_t op0, - uint32_t op1, uint32_t op2, uint32_t CRn, uint32_t CRm, - uint32_t value) -{ - struct arm *arm = target_to_arm(target); - struct arm_dpm *dpm = arm->dpm; - int retval; - uint32_t op_code; - - retval = dpm->prepare(dpm); - if (retval != ERROR_OK) - return retval; - - op_code = ((op0 & 0x3) << 19 | (op1 & 0x7) << 16 | (CRn & 0xF) << 12 |\ - (CRm & 0xF) << 8 | (op2 & 0x7) << 5); - op_code >>= 5; - LOG_DEBUG("MSR p%d, %d, r0, c%d, c%d, %d", (int)op0, - (int) op1, (int) CRn, - (int) CRm, (int) op2); - - /* read DCC into r0; then write coprocessor register from R0 */ - retval = dpm->instr_write_data_r0(dpm, - ARMV8_MSR_GP(op_code, 0), - value); - - /* (void) */ dpm->finish(dpm); - return retval; -} - /*----------------------------------------------------------------------*/ /* @@ -1449,8 +1393,6 @@ int armv8_dpm_setup(struct arm_dpm *dpm) /* coprocessor access setup */ arm->mrc = dpmv8_mrc; arm->mcr = dpmv8_mcr; - arm->mrs = dpmv8_mrs; - arm->msr = dpmv8_msr; dpm->prepare = dpmv8_dpm_prepare; dpm->finish = dpmv8_dpm_finish; -- cgit v1.1 From fa8700cdd58752671fb8d60ef65bf767e4aa1bc5 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Mon, 14 Nov 2016 21:54:26 +0100 Subject: aarch64: reduce debug output to improve legibility Suppress some very verbose LOG_DEBUG's that are not really useful any more. Change-Id: I67f10ba9510a9e34a027f378f4b62b8901ddc8a4 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3984 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/aarch64.c | 19 ------------------- src/target/armv8.c | 3 --- src/target/armv8_dpm.c | 6 ------ 3 files changed, 28 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 7bd3d3c..d3ed57c 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -1333,9 +1333,6 @@ static int aarch64_write_apb_ap_memory(struct target *target, uint32_t dscr; uint8_t *tmp_buff = NULL; - LOG_DEBUG("Writing APB-AP memory address 0x%" PRIx64 " size %" PRIu32 " count %" PRIu32, - address, size, count); - if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; @@ -1484,9 +1481,6 @@ static int aarch64_read_apb_ap_memory(struct target *target, uint8_t *u8buf_ptr; uint32_t value; - LOG_DEBUG("Reading APB-AP memory address 0x%" TARGET_PRIxADDR " size %" PRIu32 " count %" PRIu32, - address, size, count); - if (target->state != TARGET_HALTED) { LOG_WARNING("target not halted"); return ERROR_TARGET_NOT_HALTED; @@ -1634,8 +1628,6 @@ static int aarch64_read_phys_memory(struct target *target, uint32_t count, uint8_t *buffer) { int retval = ERROR_COMMAND_SYNTAX_ERROR; - LOG_DEBUG("Reading memory at real address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, - address, size, count); if (count && buffer) { /* read memory through APB-AP */ @@ -1653,10 +1645,6 @@ static int aarch64_read_memory(struct target *target, target_addr_t address, int mmu_enabled = 0; int retval; - /* aarch64 handles unaligned memory access */ - LOG_DEBUG("Reading memory at address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, address, - size, count); - /* determine if MMU was enabled on target stop */ retval = aarch64_mmu(target, &mmu_enabled); if (retval != ERROR_OK) @@ -1680,9 +1668,6 @@ static int aarch64_write_phys_memory(struct target *target, { int retval = ERROR_COMMAND_SYNTAX_ERROR; - LOG_DEBUG("Writing memory to real address 0x%" TARGET_PRIxADDR "; size %" PRId32 "; count %" PRId32, address, - size, count); - if (count && buffer) { /* write memory through APB-AP */ retval = aarch64_mmu_modify(target, 0); @@ -1700,10 +1685,6 @@ static int aarch64_write_memory(struct target *target, target_addr_t address, int mmu_enabled = 0; int retval; - /* aarch64 handles unaligned memory access */ - LOG_DEBUG("Writing memory at address 0x%" TARGET_PRIxADDR "; size %" PRId32 - "; count %" PRId32, address, size, count); - /* determine if MMU was enabled on target stop */ retval = aarch64_mmu(target, &mmu_enabled); if (retval != ERROR_OK) diff --git a/src/target/armv8.c b/src/target/armv8.c index 94a0e8e..7ae8cc9 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1086,9 +1086,6 @@ static int armv8_get_core_reg32(struct reg *reg) struct reg *reg64; int retval; - LOG_DEBUG("reg.name:%s number:%i arm.num:%i value:0x%08" PRIx64, - reg->name, reg->number, armv8_reg->num, buf_get_u64(reg->value, 0, 32)); - /* get the corresponding Aarch64 register */ reg64 = cache->reg_list + armv8_reg->num; if (reg64->valid) { diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index acfd1bc..56e2eb8 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -71,7 +71,6 @@ enum arm_state armv8_dpm_get_core_state(struct arm_dpm *dpm) static int dpmv8_write_dcc(struct armv8_common *armv8, uint32_t data) { - LOG_DEBUG("write DCC 0x%08" PRIx32, data); return mem_ap_write_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DTRRX, data); } @@ -79,7 +78,6 @@ static int dpmv8_write_dcc(struct armv8_common *armv8, uint32_t data) static int dpmv8_write_dcc_64(struct armv8_common *armv8, uint64_t data) { int ret; - LOG_DEBUG("write DCC 0x%016" PRIx64, data); ret = mem_ap_write_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DTRRX, data); if (ret == ERROR_OK) @@ -116,7 +114,6 @@ static int dpmv8_read_dcc(struct armv8_common *armv8, uint32_t *data, data); if (retval != ERROR_OK) return retval; - LOG_DEBUG("read DCC 0x%08" PRIx32, *data); if (dscr_p) *dscr_p = dscr; @@ -161,7 +158,6 @@ static int dpmv8_read_dcc_64(struct armv8_common *armv8, uint64_t *data, return retval; *data = *(uint32_t *)data | (uint64_t)higher << 32; - LOG_DEBUG("read DCC 0x%16.16" PRIx64, *data); if (dscr_p) *dscr_p = dscr; @@ -220,8 +216,6 @@ static int dpmv8_exec_opcode(struct arm_dpm *dpm, uint32_t dscr = dpm->dscr; int retval; - LOG_DEBUG("exec opcode 0x%08" PRIx32, opcode); - if (p_dscr) dscr = *p_dscr; -- cgit v1.1 From 7ed0b6333ded06f1e517d7fd3e15a400c98dc357 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Tue, 15 Nov 2016 22:10:03 +0100 Subject: aarch64: optimize core state detection Replace loop by right-shift. Inspired by patch from Alamy Liu Change-Id: I1285f4f54c0695a93fa42e9863ed8ffa4de00f70 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3985 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/armv8_dpm.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index 56e2eb8..ac53460 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -51,17 +51,11 @@ enum arm_state armv8_dpm_get_core_state(struct arm_dpm *dpm) { int el = (dpm->dscr >> 8) & 0x3; int rw = (dpm->dscr >> 10) & 0xF; - int pos; dpm->last_el = el; - /* find the first '0' in DSCR.RW */ - for (pos = 3; pos >= 0; pos--) { - if ((rw & (1 << pos)) == 0) - break; - } - - if (el > pos) + /* In Debug state, each bit gives the current Execution state of each EL */ + if ((rw >> el) & 0b1) return ARM_STATE_AARCH64; return ARM_STATE_ARM; -- cgit v1.1 From 9527d1e595e316a4155c808fafa3a0ea6baa72f2 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Sat, 19 Nov 2016 10:02:34 +0100 Subject: target: generic ARM CTI function wrapper Not specific to ARMv8, the Cross Trigger Interface deserves an independent access wrapper. Change-Id: I84f8faad15ed3515e0fff7f6cc5d1109ef91a869 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3986 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/Makefile.am | 6 +- src/target/arm_cti.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++ src/target/arm_cti.h | 73 ++++++++++++++++++++++++ 3 files changed, 225 insertions(+), 2 deletions(-) create mode 100644 src/target/arm_cti.c create mode 100644 src/target/arm_cti.h diff --git a/src/target/Makefile.am b/src/target/Makefile.am index e936d3f..597070c 100644 --- a/src/target/Makefile.am +++ b/src/target/Makefile.am @@ -96,7 +96,8 @@ ARM_DEBUG_SRC = \ %D%/etb.c \ %D%/etm.c \ $(OOCD_TRACE_FILES) \ - %D%/etm_dummy.c + %D%/etm_dummy.c \ + %D%/arm_cti.c AVR32_SRC = \ %D%/avr32_ap7k.c \ @@ -205,6 +206,7 @@ INTEL_IA32_SRC = \ %D%/nds32_v3m.h \ %D%/nds32_aice.h \ %D%/lakemont.h \ - %D%/x86_32_common.h + %D%/x86_32_common.h \ + %D%/arm_cti.h include %D%/openrisc/Makefile.am diff --git a/src/target/arm_cti.c b/src/target/arm_cti.c new file mode 100644 index 0000000..75169b2 --- /dev/null +++ b/src/target/arm_cti.c @@ -0,0 +1,148 @@ +/*************************************************************************** + * Copyright (C) 2016 by Matthias Welwarsky * + * * + * 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., * + * * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "target/arm_adi_v5.h" +#include "target/arm_cti.h" +#include "target/target.h" +#include "helper/time_support.h" + +struct arm_cti { + uint32_t base; + struct adiv5_ap *ap; +}; + +struct arm_cti *arm_cti_create(struct adiv5_ap *ap, uint32_t base) +{ + struct arm_cti *self = calloc(1, sizeof(struct arm_cti)); + if (!self) + return NULL; + + self->base = base; + self->ap = ap; + return self; +} + +static int arm_cti_mod_reg_bits(struct arm_cti *self, unsigned int reg, uint32_t mask, uint32_t value) +{ + uint32_t tmp; + + /* Read register */ + int retval = mem_ap_read_atomic_u32(self->ap, self->base + reg, &tmp); + if (ERROR_OK != retval) + return retval; + + /* clear bitfield */ + tmp &= ~mask; + /* put new value */ + tmp |= value & mask; + + /* write new value */ + return mem_ap_write_atomic_u32(self->ap, self->base + reg, tmp); +} + +int arm_cti_enable(struct arm_cti *self, bool enable) +{ + uint32_t val = enable ? 1 : 0; + + return mem_ap_write_atomic_u32(self->ap, self->base + CTI_CTR, val); +} + +int arm_cti_ack_events(struct arm_cti *self, uint32_t event) +{ + int retval; + uint32_t tmp; + + retval = mem_ap_write_atomic_u32(self->ap, self->base + CTI_INACK, event); + if (retval == ERROR_OK) { + int64_t then = timeval_ms(); + for (;;) { + retval = mem_ap_read_atomic_u32(self->ap, self->base + CTI_TROUT_STATUS, &tmp); + if (retval != ERROR_OK) + break; + if ((tmp & event) == 0) + break; + if (timeval_ms() > then + 1000) { + LOG_ERROR("timeout waiting for target"); + retval = ERROR_TARGET_TIMEOUT; + break; + } + } + } + + return retval; +} + +int arm_cti_gate_channel(struct arm_cti *self, uint32_t channel) +{ + if (channel > 31) + return ERROR_COMMAND_ARGUMENT_INVALID; + + return arm_cti_mod_reg_bits(self, CTI_GATE, CTI_CHNL(channel), 0); +} + +int arm_cti_ungate_channel(struct arm_cti *self, uint32_t channel) +{ + if (channel > 31) + return ERROR_COMMAND_ARGUMENT_INVALID; + + return arm_cti_mod_reg_bits(self, CTI_GATE, CTI_CHNL(channel), 0xFFFFFFFF); +} + +int arm_cti_write_reg(struct arm_cti *self, unsigned int reg, uint32_t value) +{ + return mem_ap_write_atomic_u32(self->ap, self->base + reg, value); +} + +int arm_cti_read_reg(struct arm_cti *self, unsigned int reg, uint32_t *p_value) +{ + if (p_value == NULL) + return ERROR_COMMAND_ARGUMENT_INVALID; + + return mem_ap_read_atomic_u32(self->ap, self->base + reg, p_value); +} + +int arm_cti_pulse_channel(struct arm_cti *self, uint32_t channel) +{ + if (channel > 31) + return ERROR_COMMAND_ARGUMENT_INVALID; + + return arm_cti_write_reg(self, CTI_APPPULSE, CTI_CHNL(channel)); +} + +int arm_cti_set_channel(struct arm_cti *self, uint32_t channel) +{ + if (channel > 31) + return ERROR_COMMAND_ARGUMENT_INVALID; + + return arm_cti_write_reg(self, CTI_APPSET, CTI_CHNL(channel)); +} + +int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel) +{ + if (channel > 31) + return ERROR_COMMAND_ARGUMENT_INVALID; + + return arm_cti_write_reg(self, CTI_APPCLEAR, CTI_CHNL(channel)); +} diff --git a/src/target/arm_cti.h b/src/target/arm_cti.h new file mode 100644 index 0000000..99724c4 --- /dev/null +++ b/src/target/arm_cti.h @@ -0,0 +1,73 @@ +/*************************************************************************** + * Copyright (C) 2016 by Matthias Welwarsky * + * * + * 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., * + * * + ***************************************************************************/ + +#ifndef OPENOCD_TARGET_ARM_CTI_H +#define OPENOCD_TARGET_ARM_CTI_H + +/*define CTI(cross trigger interface)*/ +#define CTI_CTR 0x0 +#define CTI_INACK 0x10 +#define CTI_APPSET 0x14 +#define CTI_APPCLEAR 0x18 +#define CTI_APPPULSE 0x1C +#define CTI_INEN0 0x20 +#define CTI_INEN1 0x24 +#define CTI_INEN2 0x28 +#define CTI_INEN3 0x2C +#define CTI_INEN4 0x30 +#define CTI_INEN5 0x34 +#define CTI_INEN6 0x38 +#define CTI_INEN7 0x3C +#define CTI_INEN(n) (0x20 + 4 * n) +#define CTI_OUTEN0 0xA0 +#define CTI_OUTEN1 0xA4 +#define CTI_OUTEN2 0xA8 +#define CTI_OUTEN3 0xAC +#define CTI_OUTEN4 0xB0 +#define CTI_OUTEN5 0xB4 +#define CTI_OUTEN6 0xB8 +#define CTI_OUTEN7 0xBC +#define CTI_OUTEN(n) (0xA0 + 4 * n) +#define CTI_TRIN_STATUS 0x130 +#define CTI_TROUT_STATUS 0x134 +#define CTI_CHIN_STATUS 0x138 +#define CTI_CHOU_STATUS 0x13C +#define CTI_GATE 0x140 +#define CTI_UNLOCK 0xFB0 + +#define CTI_CHNL(x) (1 << x) +#define CTI_TRIG_HALT 0 +#define CTI_TRIG_RESUME 1 +#define CTI_TRIG(n) (1 << CTI_TRIG_##n) + +/* forward-declare arm_cti struct */ +struct arm_cti; + +extern struct arm_cti *arm_cti_create(struct adiv5_ap *ap, uint32_t base); +extern int arm_cti_enable(struct arm_cti *self, bool enable); +extern int arm_cti_ack_events(struct arm_cti *self, uint32_t event); +extern int arm_cti_gate_channel(struct arm_cti *self, uint32_t channel); +extern int arm_cti_ungate_channel(struct arm_cti *self, uint32_t channel); +extern int arm_cti_write_reg(struct arm_cti *self, unsigned int reg, uint32_t value); +extern int arm_cti_read_reg(struct arm_cti *self, unsigned int reg, uint32_t *value); +extern int arm_cti_pulse_channel(struct arm_cti *self, uint32_t channel); +extern int arm_cti_set_channel(struct arm_cti *self, uint32_t channel); +extern int arm_cti_clear_channel(struct arm_cti *self, uint32_t channel); + +#endif /* OPENOCD_TARGET_ARM_CTI_H */ -- cgit v1.1 From 8b923532c16459d83655bab418b92e57f6d3312a Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Sun, 27 Nov 2016 11:28:01 +0100 Subject: aarch64: remove bogus address check before memory access Mmu faults can not be prevented on aarch64, they need to be taken and handled accordingly. Remove the remaining stub code. Change-Id: I6241efa594fe6b963624f9628cdf1c8e46588223 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3987 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/aarch64.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index d3ed57c..5dd6d7a 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -103,13 +103,6 @@ static int aarch64_restore_system_control_reg(struct target *target) return retval; } -/* check address before aarch64_apb read write access with mmu on - * remove apb predictible data abort */ -static int aarch64_check_address(struct target *target, uint32_t address) -{ - /* TODO */ - return ERROR_OK; -} /* modify system_control_reg in order to enable or disable mmu for : * - virt2phys address conversion * - read or write memory in phys or virt address */ @@ -1651,9 +1644,6 @@ static int aarch64_read_memory(struct target *target, target_addr_t address, return retval; if (mmu_enabled) { - retval = aarch64_check_address(target, address); - if (retval != ERROR_OK) - return retval; /* enable MMU as we could have disabled it for phys access */ retval = aarch64_mmu_modify(target, 1); if (retval != ERROR_OK) @@ -1691,9 +1681,6 @@ static int aarch64_write_memory(struct target *target, target_addr_t address, return retval; if (mmu_enabled) { - retval = aarch64_check_address(target, address); - if (retval != ERROR_OK) - return retval; /* enable MMU as we could have disabled it for phys access */ retval = aarch64_mmu_modify(target, 1); if (retval != ERROR_OK) -- cgit v1.1 From 095ff3d2103f9e8089b5b1fb0816d43874014e08 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Sun, 27 Nov 2016 11:39:47 +0100 Subject: armv8: load aarch32 register through aarch64 equivalent The aarch32 register cache is only a separate view of the aarch64 registers. Load aarch32 registers through their aarch64 equivalents. Change-Id: I3e932dfb782f03d73d30d942b24db340a5749e47 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3988 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/armv8.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 7ae8cc9..00ab6ed 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1093,7 +1093,7 @@ static int armv8_get_core_reg32(struct reg *reg) return ERROR_OK; } - retval = arm->read_core_reg(target, reg, armv8_reg->num, arm->core_mode); + retval = arm->read_core_reg(target, reg64, armv8_reg->num, arm->core_mode); if (retval == ERROR_OK) reg->valid = reg64->valid; @@ -1109,9 +1109,6 @@ static int armv8_set_core_reg32(struct reg *reg, uint8_t *buf) struct reg *reg64 = cache->reg_list + armv8_reg->num; uint32_t value = buf_get_u32(buf, 0, 32); - if (target->state != TARGET_HALTED) - return ERROR_TARGET_NOT_HALTED; - if (reg64 == arm->cpsr) { armv8_set_cpsr(arm, value); } else { @@ -1250,7 +1247,7 @@ int armv8_get_gdb_reg_list(struct target *target, if (arm->core_state == ARM_STATE_AARCH64) { - LOG_DEBUG("Creating Aarch64 register list"); + LOG_DEBUG("Creating Aarch64 register list for target %s", target_name(target)); switch (reg_class) { case REG_CLASS_GENERAL: @@ -1277,7 +1274,7 @@ int armv8_get_gdb_reg_list(struct target *target, } else { struct reg_cache *cache32 = arm->core_cache->next; - LOG_DEBUG("Creating Aarch32 register list"); + LOG_DEBUG("Creating Aarch32 register list for target %s", target_name(target)); switch (reg_class) { case REG_CLASS_GENERAL: -- cgit v1.1 From 6fb9f2e3ee05d8ff6241e6d61f7de0e71afeb45c Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Wed, 15 Feb 2017 14:57:21 +0100 Subject: armv8: factor out generic bit set/clr for debug registers introduce armv8_set_dbgreg_bits() function to make register bit-field modifications easier to read. Change-Id: I6b06f66262587fd301d848c9e0645e8327653de7 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3989 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/aarch64.c | 18 +----------------- src/target/armv8.c | 21 +++++++++++++++++++++ src/target/armv8.h | 1 + 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 5dd6d7a..65a5278 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -238,23 +238,7 @@ static int aarch64_dpm_setup(struct aarch64_common *a8, uint64_t debug) static int aarch64_set_dscr_bits(struct target *target, unsigned long bit_mask, unsigned long value) { struct armv8_common *armv8 = target_to_armv8(target); - uint32_t dscr; - - /* Read DSCR */ - int retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, &dscr); - if (ERROR_OK != retval) - return retval; - - /* clear bitfield */ - dscr &= ~bit_mask; - /* put new value */ - dscr |= value & bit_mask; - - /* write new DSCR */ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, dscr); - return retval; + return armv8_set_dbgreg_bits(armv8, CPUV8_DBG_DSCR, bit_mask, value); } static struct target *get_aarch64(struct target *target, int32_t coreid) diff --git a/src/target/armv8.c b/src/target/armv8.c index 00ab6ed..2f1d5c1 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -1292,3 +1292,24 @@ int armv8_get_gdb_reg_list(struct target *target, } } } + +int armv8_set_dbgreg_bits(struct armv8_common *armv8, unsigned int reg, unsigned long mask, unsigned long value) +{ + uint32_t tmp; + + /* Read register */ + int retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + reg, &tmp); + if (ERROR_OK != retval) + return retval; + + /* clear bitfield */ + tmp &= ~mask; + /* put new value */ + tmp |= value & mask; + + /* write new value */ + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + reg, tmp); + return retval; +} diff --git a/src/target/armv8.h b/src/target/armv8.h index 3b2fc59..1cb3a3b 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -307,6 +307,7 @@ static inline unsigned int armv8_curel_from_core_mode(enum arm_mode core_mode) } void armv8_select_reg_access(struct armv8_common *armv8, bool is_aarch64); +int armv8_set_dbgreg_bits(struct armv8_common *armv8, unsigned int reg, unsigned long mask, unsigned long value); extern const struct command_registration armv8_command_handlers[]; -- cgit v1.1 From d6535e0ce517bfb2c4c8acaef59eb73dd0c6d07c Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Wed, 15 Feb 2017 15:30:21 +0100 Subject: aarch64: reset fixes Make sure all core register caches are invalidated on reset assert, make sure to re-init debug registers on deassert. Change-Id: I82350d04cc3eaae5e35245d13d6c1fb0a8d59807 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3990 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/aarch64.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 65a5278..d14b54d 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -169,6 +169,13 @@ static int aarch64_init_debug_access(struct target *target) LOG_DEBUG(" "); + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_OSLAR, 0); + if (retval != ERROR_OK) { + LOG_DEBUG("Examine %s failed", "oslock"); + return retval; + } + /* Clear Sticky Power Down status Bit in PRSR to enable access to the registers in the Core Power Domain */ retval = mem_ap_read_atomic_u32(armv8->debug_ap, @@ -1256,8 +1263,10 @@ static int aarch64_assert_reset(struct target *target) } /* registers are now invalid */ - if (target_was_examined(target)) + if (target_was_examined(target)) { register_cache_invalidate(armv8->arm.core_cache); + register_cache_invalidate(armv8->arm.core_cache->next); + } target->state = TARGET_RESET; @@ -1290,7 +1299,7 @@ static int aarch64_deassert_reset(struct target *target) } } - return ERROR_OK; + return aarch64_init_debug_access(target); } static int aarch64_write_apb_ap_memory(struct target *target, -- cgit v1.1 From 257c434d3ff9a9f7a5d9cec1ed7a2bd1ff82eaf5 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 17 Feb 2017 13:42:50 +0100 Subject: aarch64: clean up target specific commands - rename "cortex_a" command group to "aarch64" - remove default blank check, checksum and algorithm hooks since they're not going to work in aarch64 mode anyway. Change-Id: Ieb0046786ed9425baf6774c68f42a8285cc2aefd Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3991 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/aarch64.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index d14b54d..da7d2a9 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -2057,9 +2057,9 @@ static const struct command_registration aarch64_command_handlers[] = { .chain = armv8_command_handlers, }, { - .name = "cortex_a", + .name = "aarch64", .mode = COMMAND_ANY, - .help = "Cortex-A command group", + .help = "Aarch64 command group", .usage = "", .chain = aarch64_exec_command_handlers, }, @@ -2085,11 +2085,6 @@ struct target_type aarch64_target = { .read_memory = aarch64_read_memory, .write_memory = aarch64_write_memory, - .checksum_memory = arm_checksum_memory, - .blank_check_memory = arm_blank_check_memory, - - .run_algorithm = armv4_5_run_algorithm, - .add_breakpoint = aarch64_add_breakpoint, .add_context_breakpoint = aarch64_add_context_breakpoint, .add_hybrid_breakpoint = aarch64_add_hybrid_breakpoint, -- cgit v1.1 From e513fe949bdd0d334a373a2e0adb6d9b8c036c69 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 17 Feb 2017 13:57:08 +0100 Subject: aarch64: clean up struct aarch64_common remove some rarely or completely unused components. Change-Id: Id285bb7075901016297fa173a874db7f11a840d7 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3992 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/aarch64.c | 26 ++++++++++++++------------ src/target/aarch64.h | 9 --------- 2 files changed, 14 insertions(+), 21 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index da7d2a9..29cbb07 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -331,7 +331,6 @@ static int aarch64_poll(struct target *target) armv8->debug_base + CPUV8_DBG_DSCR, &dscr); if (retval != ERROR_OK) return retval; - aarch64->cpudbg_dscr = dscr; if (DSCR_RUN_MODE(dscr) == 0x3) { if (prev_target_state != TARGET_HALTED) { @@ -601,22 +600,28 @@ static int aarch64_resume(struct target *target, int current, static int aarch64_debug_entry(struct target *target) { int retval = ERROR_OK; - struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = target_to_armv8(target); struct arm_dpm *dpm = &armv8->dpm; enum arm_state core_state; + uint32_t dscr; + + /* make sure to clear all sticky errors */ + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); + if (retval == ERROR_OK) + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_DSCR, &dscr); - LOG_DEBUG("%s dscr = 0x%08" PRIx32, target_name(target), aarch64->cpudbg_dscr); + if (retval != ERROR_OK) + return retval; + + LOG_DEBUG("%s dscr = 0x%08" PRIx32, target_name(target), dscr); - dpm->dscr = aarch64->cpudbg_dscr; + dpm->dscr = dscr; core_state = armv8_dpm_get_core_state(dpm); armv8_select_opcodes(armv8, core_state == ARM_STATE_AARCH64); armv8_select_reg_access(armv8, core_state == ARM_STATE_AARCH64); - /* make sure to clear all sticky errors */ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DRCR, DRCR_CSE); - /* discard async exceptions */ if (retval == ERROR_OK) retval = dpm->instr_cpsr_sync(dpm); @@ -625,7 +630,7 @@ static int aarch64_debug_entry(struct target *target) return retval; /* Examine debug reason */ - armv8_dpm_report_dscr(dpm, aarch64->cpudbg_dscr); + armv8_dpm_report_dscr(dpm, dscr); /* save address of instruction that triggered the watchpoint? */ if (target->debug_reason == DBG_REASON_WATCHPOINT) { @@ -717,7 +722,6 @@ static int aarch64_post_debug_entry(struct target *target) (aarch64->system_control_reg & 0x4U) ? 1 : 0; armv8->armv8_mmu.armv8_cache.i_cache_enabled = (aarch64->system_control_reg & 0x1000U) ? 1 : 0; - aarch64->curr_mode = armv8->arm.core_mode; return ERROR_OK; } @@ -1893,8 +1897,6 @@ static int aarch64_init_arch_info(struct target *target, armv8->arm.dap = tap->dap; - aarch64->fast_reg_read = 0; - /* register arch-specific functions */ armv8->examine_debug_reason = NULL; diff --git a/src/target/aarch64.h b/src/target/aarch64.h index 9491623..c9ec02d 100644 --- a/src/target/aarch64.h +++ b/src/target/aarch64.h @@ -48,25 +48,16 @@ struct aarch64_common { int common_magic; /* Context information */ - uint32_t cpudbg_dscr; - uint32_t system_control_reg; uint32_t system_control_reg_curr; - enum arm_mode curr_mode; - - /* Breakpoint register pairs */ int brp_num_context; int brp_num; int brp_num_available; struct aarch64_brp *brp_list; - /* Use aarch64_read_regs_through_mem for fast register reads */ - int fast_reg_read; - struct armv8_common armv8_common; - }; static inline struct aarch64_common * -- cgit v1.1 From bf1efe05bb71b7a6fe4ec1809a6aaa9b6073aede Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 17 Feb 2017 14:24:53 +0100 Subject: aarch64: run control rework This patch contains a major overhaul of the target run control, mainly for the sake of satisfying gdbs ideas of how a target should respond to various control requests for the debugger. The changes allow gdb a slightly better control on how cores are stepped: a core can be single-stepped while other cores remain halted or continue normal execution until the single-stepped core halts again. Also, on any halting event (user command or breakpoint) the system is brought into a stable state with all cores halted before the halt is signaled to the debugger. This patch also transitions the target code to make use of the new CTI abstraction instead of accessing CTI registers directly. Change-Id: I8ddc9abb119e04580d671b57ee12240c3f5070a0 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3993 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/aarch64.c | 864 ++++++++++++++++++++++++++++++++++--------------- src/target/armv8.h | 38 +-- src/target/armv8_dpm.h | 7 +- 3 files changed, 614 insertions(+), 295 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 29cbb07..9977c36 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -30,6 +30,18 @@ #include "armv8_cache.h" #include +#define __unused __attribute((unused)) + +enum restart_mode { + RESTART_LAZY, + RESTART_SYNC, +}; + +enum halt_mode { + HALT_LAZY, + HALT_SYNC, +}; + static int aarch64_poll(struct target *target); static int aarch64_debug_entry(struct target *target); static int aarch64_restore_context(struct target *target, bool bpwp); @@ -47,6 +59,9 @@ static int aarch64_virt2phys(struct target *target, static int aarch64_read_apb_ap_memory(struct target *target, uint64_t address, uint32_t size, uint32_t count, uint8_t *buffer); +#define foreach_smp_target(pos, head) \ + for (pos = head; (pos != NULL); pos = pos->next) + static int aarch64_restore_system_control_reg(struct target *target) { enum arm_mode target_mode = ARM_MODE_ANY; @@ -191,27 +206,22 @@ static int aarch64_init_debug_access(struct target *target) */ /* Enable CTI */ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_CTR, 1); - /* By default, gate all channel triggers to and from the CTM */ + retval = arm_cti_enable(armv8->cti, true); + /* By default, gate all channel events to and from the CTM */ if (retval == ERROR_OK) - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_GATE, 0); - /* output halt requests to PE on channel 0 trigger */ + retval = arm_cti_write_reg(armv8->cti, CTI_GATE, 0); + /* output halt requests to PE on channel 0 event */ if (retval == ERROR_OK) - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_OUTEN0, CTI_CHNL(0)); - /* output restart requests to PE on channel 1 trigger */ + retval = arm_cti_write_reg(armv8->cti, CTI_OUTEN0, CTI_CHNL(0)); + /* output restart requests to PE on channel 1 event */ if (retval == ERROR_OK) - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_OUTEN1, CTI_CHNL(1)); + retval = arm_cti_write_reg(armv8->cti, CTI_OUTEN1, CTI_CHNL(1)); if (retval != ERROR_OK) return retval; /* Resync breakpoint registers */ - /* Since this is likely called from init or reset, update target state information*/ - return aarch64_poll(target); + return ERROR_OK; } /* Write to memory mapped registers directly with no cache or mmu handling */ @@ -248,123 +258,270 @@ static int aarch64_set_dscr_bits(struct target *target, unsigned long bit_mask, return armv8_set_dbgreg_bits(armv8, CPUV8_DBG_DSCR, bit_mask, value); } -static struct target *get_aarch64(struct target *target, int32_t coreid) +static int aarch64_check_state_one(struct target *target, + uint32_t mask, uint32_t val, int *p_result, uint32_t *p_prsr) { - struct target_list *head; - struct target *curr; + struct armv8_common *armv8 = target_to_armv8(target); + uint32_t prsr; + int retval; - head = target->head; - while (head != (struct target_list *)NULL) { - curr = head->target; - if ((curr->coreid == coreid) && (curr->state == TARGET_HALTED)) - return curr; - head = head->next; + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_PRSR, &prsr); + if (retval != ERROR_OK) + return retval; + + if (p_prsr) + *p_prsr = prsr; + + if (p_result) + *p_result = (prsr & mask) == (val & mask); + + return ERROR_OK; +} + +static int aarch64_wait_halt_one(struct target *target) +{ + int retval = ERROR_OK; + uint32_t prsr; + + int64_t then = timeval_ms(); + for (;;) { + int halted; + + retval = aarch64_check_state_one(target, PRSR_HALT, PRSR_HALT, &halted, &prsr); + if (retval != ERROR_OK || halted) + break; + + if (timeval_ms() > then + 1000) { + retval = ERROR_TARGET_TIMEOUT; + LOG_DEBUG("target %s timeout, prsr=0x%08"PRIx32, target_name(target), prsr); + break; + } } - return target; + return retval; } -static int aarch64_halt(struct target *target); -static int aarch64_halt_smp(struct target *target) +static int aarch64_prepare_halt_smp(struct target *target, bool exc_target, struct target **p_first) { int retval = ERROR_OK; struct target_list *head = target->head; + struct target *first = NULL; + + LOG_DEBUG("target %s exc %i", target_name(target), exc_target); - while (head != (struct target_list *)NULL) { + while (head != NULL) { struct target *curr = head->target; struct armv8_common *armv8 = target_to_armv8(curr); + head = head->next; + + if (exc_target && curr == target) + continue; + if (!target_was_examined(curr)) + continue; + if (curr->state != TARGET_RUNNING) + continue; + + /* HACK: mark this target as prepared for halting */ + curr->debug_reason = DBG_REASON_DBGRQ; /* open the gate for channel 0 to let HALT requests pass to the CTM */ - if (curr->smp) { - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_GATE, CTI_CHNL(0)); - if (retval == ERROR_OK) - retval = aarch64_set_dscr_bits(curr, DSCR_HDE, DSCR_HDE); - } + retval = arm_cti_ungate_channel(armv8->cti, 0); + if (retval == ERROR_OK) + retval = aarch64_set_dscr_bits(curr, DSCR_HDE, DSCR_HDE); if (retval != ERROR_OK) break; - head = head->next; + LOG_DEBUG("target %s prepared", target_name(curr)); + + if (first == NULL) + first = curr; } + if (p_first) { + if (exc_target && first) + *p_first = first; + else + *p_first = target; + } + + return retval; +} + +static int aarch64_halt_one(struct target *target, enum halt_mode mode) +{ + int retval = ERROR_OK; + struct armv8_common *armv8 = target_to_armv8(target); + + LOG_DEBUG("%s", target_name(target)); + + /* allow Halting Debug Mode */ + retval = aarch64_set_dscr_bits(target, DSCR_HDE, DSCR_HDE); + if (retval != ERROR_OK) + return retval; + + /* trigger an event on channel 0, this outputs a halt request to the PE */ + retval = arm_cti_pulse_channel(armv8->cti, 0); + if (retval != ERROR_OK) + return retval; + + if (mode == HALT_SYNC) { + retval = aarch64_wait_halt_one(target); + if (retval != ERROR_OK) { + if (retval == ERROR_TARGET_TIMEOUT) + LOG_ERROR("Timeout waiting for target %s halt", target_name(target)); + return retval; + } + } + + return ERROR_OK; +} + +static int aarch64_halt_smp(struct target *target, bool exc_target) +{ + struct target *next = target; + int retval; + + /* prepare halt on all PEs of the group */ + retval = aarch64_prepare_halt_smp(target, exc_target, &next); + + if (exc_target && next == target) + return retval; + /* halt the target PE */ if (retval == ERROR_OK) - retval = aarch64_halt(target); + retval = aarch64_halt_one(next, HALT_LAZY); + + if (retval != ERROR_OK) + return retval; + + /* wait for all PEs to halt */ + int64_t then = timeval_ms(); + for (;;) { + bool all_halted = true; + struct target_list *head; + struct target *curr; + + foreach_smp_target(head, target->head) { + int halted; + + curr = head->target; + + if (!target_was_examined(curr)) + continue; + + retval = aarch64_check_state_one(curr, PRSR_HALT, PRSR_HALT, &halted, NULL); + if (retval != ERROR_OK || !halted) { + all_halted = false; + break; + } + } + + if (all_halted) + break; + + if (timeval_ms() > then + 1000) { + retval = ERROR_TARGET_TIMEOUT; + break; + } + + /* + * HACK: on Hi6220 there are 8 cores organized in 2 clusters + * and it looks like the CTI's are not connected by a common + * trigger matrix. It seems that we need to halt one core in each + * cluster explicitly. So if we find that a core has not halted + * yet, we trigger an explicit halt for the second cluster. + */ + retval = aarch64_halt_one(curr, HALT_LAZY); + if (retval != ERROR_OK) + break; + } return retval; } -static int update_halt_gdb(struct target *target) +static int update_halt_gdb(struct target *target, enum target_debug_reason debug_reason) { - int retval = 0; - if (target->gdb_service && target->gdb_service->core[0] == -1) { - target->gdb_service->target = target; - target->gdb_service->core[0] = target->coreid; - retval += aarch64_halt_smp(target); + struct target *gdb_target = NULL; + struct target_list *head; + struct target *curr; + + if (debug_reason == DBG_REASON_NOTHALTED) { + LOG_INFO("Halting remaining targets in SMP group"); + aarch64_halt_smp(target, true); } - return retval; + + /* poll all targets in the group, but skip the target that serves GDB */ + foreach_smp_target(head, target->head) { + curr = head->target; + /* skip calling context */ + if (curr == target) + continue; + if (!target_was_examined(curr)) + continue; + /* skip targets that were already halted */ + if (curr->state == TARGET_HALTED) + continue; + /* remember the gdb_service->target */ + if (curr->gdb_service != NULL) + gdb_target = curr->gdb_service->target; + /* skip it */ + if (curr == gdb_target) + continue; + + /* avoid recursion in aarch64_poll() */ + curr->smp = 0; + aarch64_poll(curr); + curr->smp = 1; + } + + /* after all targets were updated, poll the gdb serving target */ + if (gdb_target != NULL && gdb_target != target) + aarch64_poll(gdb_target); + + return ERROR_OK; } /* - * Cortex-A8 Run control + * Aarch64 Run control */ static int aarch64_poll(struct target *target) { + enum target_state prev_target_state; int retval = ERROR_OK; - uint32_t dscr; - struct aarch64_common *aarch64 = target_to_aarch64(target); - struct armv8_common *armv8 = &aarch64->armv8_common; - enum target_state prev_target_state = target->state; - /* toggle to another core is done by gdb as follow */ - /* maint packet J core_id */ - /* continue */ - /* the next polling trigger an halt event sent to gdb */ - if ((target->state == TARGET_HALTED) && (target->smp) && - (target->gdb_service) && - (target->gdb_service->target == NULL)) { - target->gdb_service->target = - get_aarch64(target, target->gdb_service->core[1]); - target_call_event_callbacks(target, TARGET_EVENT_HALTED); - return retval; - } - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, &dscr); + int halted; + + retval = aarch64_check_state_one(target, + PRSR_HALT, PRSR_HALT, &halted, NULL); if (retval != ERROR_OK) return retval; - if (DSCR_RUN_MODE(dscr) == 0x3) { + if (halted) { + prev_target_state = target->state; if (prev_target_state != TARGET_HALTED) { + enum target_debug_reason debug_reason = target->debug_reason; + /* We have a halting debug event */ - LOG_DEBUG("Target %s halted", target_name(target)); target->state = TARGET_HALTED; - if ((prev_target_state == TARGET_RUNNING) - || (prev_target_state == TARGET_UNKNOWN) - || (prev_target_state == TARGET_RESET)) { - retval = aarch64_debug_entry(target); - if (retval != ERROR_OK) - return retval; - if (target->smp) { - retval = update_halt_gdb(target); - if (retval != ERROR_OK) - return retval; - } - target_call_event_callbacks(target, - TARGET_EVENT_HALTED); - } - if (prev_target_state == TARGET_DEBUG_RUNNING) { - LOG_DEBUG(" "); - - retval = aarch64_debug_entry(target); - if (retval != ERROR_OK) - return retval; - if (target->smp) { - retval = update_halt_gdb(target); - if (retval != ERROR_OK) - return retval; - } + LOG_DEBUG("Target %s halted", target_name(target)); + retval = aarch64_debug_entry(target); + if (retval != ERROR_OK) + return retval; - target_call_event_callbacks(target, - TARGET_EVENT_DEBUG_HALTED); + if (target->smp) + update_halt_gdb(target, debug_reason); + + switch (prev_target_state) { + case TARGET_RUNNING: + case TARGET_UNKNOWN: + case TARGET_RESET: + target_call_event_callbacks(target, TARGET_EVENT_HALTED); + break; + case TARGET_DEBUG_RUNNING: + target_call_event_callbacks(target, TARGET_EVENT_DEBUG_HALTED); + break; + default: + break; } } } else @@ -375,43 +532,13 @@ static int aarch64_poll(struct target *target) static int aarch64_halt(struct target *target) { - int retval = ERROR_OK; - uint32_t dscr; - struct armv8_common *armv8 = target_to_armv8(target); - - /* - * add HDE in halting debug mode - */ - retval = aarch64_set_dscr_bits(target, DSCR_HDE, DSCR_HDE); - if (retval != ERROR_OK) - return retval; - - /* trigger an event on channel 0, this outputs a halt request to the PE */ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_APPPULSE, CTI_CHNL(0)); - if (retval != ERROR_OK) - return retval; - - long long then = timeval_ms(); - for (;; ) { - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, &dscr); - if (retval != ERROR_OK) - return retval; - if ((dscr & DSCRV8_HALT_MASK) != 0) - break; - if (timeval_ms() > then + 1000) { - LOG_ERROR("Timeout waiting for halt"); - return ERROR_FAIL; - } - } - - target->debug_reason = DBG_REASON_DBGRQ; + if (target->smp) + return aarch64_halt_smp(target, false); - return ERROR_OK; + return aarch64_halt_one(target, HALT_SYNC); } -static int aarch64_internal_restore(struct target *target, int current, +static int aarch64_restore_one(struct target *target, int current, uint64_t *address, int handle_breakpoints, int debug_execution) { struct armv8_common *armv8 = target_to_armv8(target); @@ -419,6 +546,8 @@ static int aarch64_internal_restore(struct target *target, int current, int retval; uint64_t resume_pc; + LOG_DEBUG("%s", target_name(target)); + if (!debug_execution) target_free_all_working_areas(target); @@ -464,19 +593,19 @@ static int aarch64_internal_restore(struct target *target, int current, return retval; } -static int aarch64_internal_restart(struct target *target, bool slave_pe) +/** + * prepare single target for restart + * + * + */ +static int aarch64_prepare_restart_one(struct target *target) { struct armv8_common *armv8 = target_to_armv8(target); - struct arm *arm = &armv8->arm; int retval; uint32_t dscr; - /* - * * Restart core and wait for it to be started. Clear ITRen and sticky - * * exception flags: see ARMv7 ARM, C5.9. - * - * REVISIT: for single stepping, we probably want to - * disable IRQs by default, with optional override... - */ + uint32_t tmp; + + LOG_DEBUG("%s", target_name(target)); retval = mem_ap_read_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DSCR, &dscr); @@ -488,70 +617,195 @@ static int aarch64_internal_restart(struct target *target, bool slave_pe) if ((dscr & DSCR_ERR) != 0) LOG_ERROR("DSCR.ERR must be cleared before leaving debug!"); - /* make sure to acknowledge the halt event before resuming */ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_INACK, CTI_TRIG(HALT)); - + /* acknowledge a pending CTI halt event */ + retval = arm_cti_ack_events(armv8->cti, CTI_TRIG(HALT)); /* * open the CTI gate for channel 1 so that the restart events - * get passed along to all PEs + * get passed along to all PEs. Also close gate for channel 0 + * to isolate the PE from halt events. */ if (retval == ERROR_OK) + retval = arm_cti_ungate_channel(armv8->cti, 1); + if (retval == ERROR_OK) + retval = arm_cti_gate_channel(armv8->cti, 0); + + /* make sure that DSCR.HDE is set */ + if (retval == ERROR_OK) { + dscr |= DSCR_HDE; retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_GATE, CTI_CHNL(1)); + armv8->debug_base + CPUV8_DBG_DSCR, dscr); + } + + /* clear sticky bits in PRSR, SDR is now 0 */ + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_PRSR, &tmp); + + return retval; +} + +static int aarch64_do_restart_one(struct target *target, enum restart_mode mode) +{ + struct armv8_common *armv8 = target_to_armv8(target); + int retval; + + LOG_DEBUG("%s", target_name(target)); + + /* trigger an event on channel 1, generates a restart request to the PE */ + retval = arm_cti_pulse_channel(armv8->cti, 1); if (retval != ERROR_OK) return retval; - if (!slave_pe) { - /* trigger an event on channel 1, generates a restart request to the PE */ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->cti_base + CTI_APPPULSE, CTI_CHNL(1)); - if (retval != ERROR_OK) - return retval; - - long long then = timeval_ms(); - for (;; ) { - retval = mem_ap_read_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_DSCR, &dscr); - if (retval != ERROR_OK) - return retval; - if ((dscr & DSCR_HDE) != 0) + if (mode == RESTART_SYNC) { + int64_t then = timeval_ms(); + for (;;) { + int resumed; + /* + * if PRSR.SDR is set now, the target did restart, even + * if it's now already halted again (e.g. due to breakpoint) + */ + retval = aarch64_check_state_one(target, + PRSR_SDR, PRSR_SDR, &resumed, NULL); + if (retval != ERROR_OK || resumed) break; + if (timeval_ms() > then + 1000) { - LOG_ERROR("Timeout waiting for resume"); - return ERROR_FAIL; + LOG_ERROR("%s: Timeout waiting for resume"PRIx32, target_name(target)); + retval = ERROR_TARGET_TIMEOUT; + break; } } } + if (retval != ERROR_OK) + return retval; + target->debug_reason = DBG_REASON_NOTHALTED; target->state = TARGET_RUNNING; - /* registers are now invalid */ - register_cache_invalidate(arm->core_cache); - register_cache_invalidate(arm->core_cache->next); - return ERROR_OK; } -static int aarch64_restore_smp(struct target *target, int handle_breakpoints) +static int aarch64_restart_one(struct target *target, enum restart_mode mode) { - int retval = 0; + int retval; + + LOG_DEBUG("%s", target_name(target)); + + retval = aarch64_prepare_restart_one(target); + if (retval == ERROR_OK) + retval = aarch64_do_restart_one(target, mode); + + return retval; +} + +/* + * prepare all but the current target for restart + */ +static int aarch64_prep_restart_smp(struct target *target, int handle_breakpoints, struct target **p_first) +{ + int retval = ERROR_OK; struct target_list *head; - struct target *curr; + struct target *first = NULL; uint64_t address; - head = target->head; - while (head != (struct target_list *)NULL) { - curr = head->target; - if ((curr != target) && (curr->state != TARGET_RUNNING)) { - /* resume current address , not in step mode */ - retval += aarch64_internal_restore(curr, 1, &address, - handle_breakpoints, 0); - retval += aarch64_internal_restart(curr, true); + + foreach_smp_target(head, target->head) { + struct target *curr = head->target; + + /* skip calling target */ + if (curr == target) + continue; + if (!target_was_examined(curr)) + continue; + if (curr->state != TARGET_HALTED) + continue; + + /* resume at current address, not in step mode */ + retval = aarch64_restore_one(curr, 1, &address, handle_breakpoints, 0); + if (retval == ERROR_OK) + retval = aarch64_prepare_restart_one(curr); + if (retval != ERROR_OK) { + LOG_ERROR("failed to restore target %s", target_name(curr)); + break; } - head = head->next; + /* remember the first valid target in the group */ + if (first == NULL) + first = curr; + } + + if (p_first) + *p_first = first; + + return retval; +} + + +static int aarch64_step_restart_smp(struct target *target) +{ + int retval = ERROR_OK; + struct target_list *head; + struct target *first = NULL; + + LOG_DEBUG("%s", target_name(target)); + + retval = aarch64_prep_restart_smp(target, 0, &first); + if (retval != ERROR_OK) + return retval; + if (first != NULL) + retval = aarch64_do_restart_one(first, RESTART_LAZY); + if (retval != ERROR_OK) { + LOG_DEBUG("error restarting target %s", target_name(first)); + return retval; } + + int64_t then = timeval_ms(); + for (;;) { + struct target *curr = target; + bool all_resumed = true; + + foreach_smp_target(head, target->head) { + uint32_t prsr; + int resumed; + + curr = head->target; + + if (curr == target) + continue; + + retval = aarch64_check_state_one(curr, + PRSR_SDR, PRSR_SDR, &resumed, &prsr); + if (retval != ERROR_OK || (!resumed && (prsr & PRSR_HALT))) { + all_resumed = false; + break; + } + + if (curr->state != TARGET_RUNNING) { + curr->state = TARGET_RUNNING; + curr->debug_reason = DBG_REASON_NOTHALTED; + target_call_event_callbacks(curr, TARGET_EVENT_RESUMED); + } + } + + if (all_resumed) + break; + + if (timeval_ms() > then + 1000) { + LOG_ERROR("%s: timeout waiting for target resume", __func__); + retval = ERROR_TARGET_TIMEOUT; + break; + } + /* + * HACK: on Hi6220 there are 8 cores organized in 2 clusters + * and it looks like the CTI's are not connected by a common + * trigger matrix. It seems that we need to halt one core in each + * cluster explicitly. So if we find that a core has not halted + * yet, we trigger an explicit resume for the second cluster. + */ + retval = aarch64_do_restart_one(curr, RESTART_LAZY); + if (retval != ERROR_OK) + break; +} + return retval; } @@ -561,28 +815,86 @@ static int aarch64_resume(struct target *target, int current, int retval = 0; uint64_t addr = address; - /* dummy resume for smp toggle in order to reduce gdb impact */ - if ((target->smp) && (target->gdb_service->core[1] != -1)) { - /* simulate a start and halt of target */ - target->gdb_service->target = NULL; - target->gdb_service->core[0] = target->gdb_service->core[1]; - /* fake resume at next poll we play the target core[1], see poll*/ - target_call_event_callbacks(target, TARGET_EVENT_RESUMED); - return 0; - } - if (target->state != TARGET_HALTED) return ERROR_TARGET_NOT_HALTED; - aarch64_internal_restore(target, current, &addr, handle_breakpoints, - debug_execution); + /* + * If this target is part of a SMP group, prepare the others + * targets for resuming. This involves restoring the complete + * target register context and setting up CTI gates to accept + * resume events from the trigger matrix. + */ if (target->smp) { - target->gdb_service->core[0] = -1; - retval = aarch64_restore_smp(target, handle_breakpoints); + retval = aarch64_prep_restart_smp(target, handle_breakpoints, NULL); if (retval != ERROR_OK) return retval; } - aarch64_internal_restart(target, false); + + /* all targets prepared, restore and restart the current target */ + retval = aarch64_restore_one(target, current, &addr, handle_breakpoints, + debug_execution); + if (retval == ERROR_OK) + retval = aarch64_restart_one(target, RESTART_SYNC); + if (retval != ERROR_OK) + return retval; + + if (target->smp) { + int64_t then = timeval_ms(); + for (;;) { + struct target *curr = target; + struct target_list *head; + bool all_resumed = true; + + foreach_smp_target(head, target->head) { + uint32_t prsr; + int resumed; + + curr = head->target; + if (curr == target) + continue; + if (!target_was_examined(curr)) + continue; + + retval = aarch64_check_state_one(curr, + PRSR_SDR, PRSR_SDR, &resumed, &prsr); + if (retval != ERROR_OK || (!resumed && (prsr & PRSR_HALT))) { + all_resumed = false; + break; + } + + if (curr->state != TARGET_RUNNING) { + curr->state = TARGET_RUNNING; + curr->debug_reason = DBG_REASON_NOTHALTED; + target_call_event_callbacks(curr, TARGET_EVENT_RESUMED); + } + } + + if (all_resumed) + break; + + if (timeval_ms() > then + 1000) { + LOG_ERROR("%s: timeout waiting for target %s to resume", __func__, target_name(curr)); + retval = ERROR_TARGET_TIMEOUT; + break; + } + + /* + * HACK: on Hi6220 there are 8 cores organized in 2 clusters + * and it looks like the CTI's are not connected by a common + * trigger matrix. It seems that we need to halt one core in each + * cluster explicitly. So if we find that a core has not halted + * yet, we trigger an explicit resume for the second cluster. + */ + retval = aarch64_do_restart_one(curr, RESTART_LAZY); + if (retval != ERROR_OK) + break; + } + } + + if (retval != ERROR_OK) + return retval; + + target->debug_reason = DBG_REASON_NOTHALTED; if (!debug_execution) { target->state = TARGET_RUNNING; @@ -622,10 +934,12 @@ static int aarch64_debug_entry(struct target *target) armv8_select_opcodes(armv8, core_state == ARM_STATE_AARCH64); armv8_select_reg_access(armv8, core_state == ARM_STATE_AARCH64); + /* close the CTI gate for all events */ + if (retval == ERROR_OK) + retval = arm_cti_write_reg(armv8->cti, CTI_GATE, 0); /* discard async exceptions */ if (retval == ERROR_OK) retval = dpm->instr_cpsr_sync(dpm); - if (retval != ERROR_OK) return retval; @@ -725,10 +1039,14 @@ static int aarch64_post_debug_entry(struct target *target) return ERROR_OK; } +/* + * single-step a target + */ static int aarch64_step(struct target *target, int current, target_addr_t address, int handle_breakpoints) { struct armv8_common *armv8 = target_to_armv8(target); + int saved_retval = ERROR_OK; int retval; uint32_t edecr; @@ -739,39 +1057,70 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres retval = mem_ap_read_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_EDECR, &edecr); - if (retval != ERROR_OK) - return retval; - /* make sure EDECR.SS is not set when restoring the register */ - edecr &= ~0x4; - /* set EDECR.SS to enter hardware step mode */ - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_EDECR, (edecr|0x4)); + if (retval == ERROR_OK) { + edecr &= ~0x4; + /* set EDECR.SS to enter hardware step mode */ + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_EDECR, (edecr|0x4)); + } + /* disable interrupts while stepping */ + if (retval == ERROR_OK) + retval = aarch64_set_dscr_bits(target, 0x3 << 22, 0x3 << 22); + /* bail out if stepping setup has failed */ if (retval != ERROR_OK) return retval; - /* disable interrupts while stepping */ - retval = aarch64_set_dscr_bits(target, 0x3 << 22, 0x3 << 22); - if (retval != ERROR_OK) - return ERROR_OK; + if (target->smp && !handle_breakpoints) { + /* + * isolate current target so that it doesn't get resumed + * together with the others + */ + retval = arm_cti_gate_channel(armv8->cti, 1); + /* resume all other targets in the group */ + if (retval == ERROR_OK) + retval = aarch64_step_restart_smp(target); + if (retval != ERROR_OK) { + LOG_ERROR("Failed to restart non-stepping targets in SMP group"); + return retval; + } + LOG_DEBUG("Restarted all non-stepping targets in SMP group"); + } + + /* all other targets running, restore and restart the current target */ + retval = aarch64_restore_one(target, current, &address, 0, 0); + if (retval == ERROR_OK) + retval = aarch64_restart_one(target, RESTART_LAZY); - /* resume the target */ - retval = aarch64_resume(target, current, address, 0, 0); if (retval != ERROR_OK) return retval; - long long then = timeval_ms(); - while (target->state != TARGET_HALTED) { - retval = aarch64_poll(target); - if (retval != ERROR_OK) - return retval; + LOG_DEBUG("target step-resumed at 0x%" PRIx64, address); + if (!handle_breakpoints) + target_call_event_callbacks(target, TARGET_EVENT_RESUMED); + + int64_t then = timeval_ms(); + for (;;) { + int stepped; + uint32_t prsr; + + retval = aarch64_check_state_one(target, + PRSR_SDR|PRSR_HALT, PRSR_SDR|PRSR_HALT, &stepped, &prsr); + if (retval != ERROR_OK || stepped) + break; + if (timeval_ms() > then + 1000) { - LOG_ERROR("timeout waiting for target halt"); - return ERROR_FAIL; + LOG_ERROR("timeout waiting for target %s halt after step", + target_name(target)); + retval = ERROR_TARGET_TIMEOUT; + break; } } + if (retval == ERROR_TARGET_TIMEOUT) + saved_retval = retval; + /* restore EDECR */ retval = mem_ap_write_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_EDECR, edecr); @@ -783,19 +1132,32 @@ static int aarch64_step(struct target *target, int current, target_addr_t addres if (retval != ERROR_OK) return ERROR_OK; - return ERROR_OK; + if (saved_retval != ERROR_OK) + return saved_retval; + + return aarch64_poll(target); } static int aarch64_restore_context(struct target *target, bool bpwp) { struct armv8_common *armv8 = target_to_armv8(target); + struct arm *arm = &armv8->arm; + + int retval; LOG_DEBUG("%s", target_name(target)); if (armv8->pre_restore_context) armv8->pre_restore_context(target); - return armv8_dpm_write_dirty_registers(&armv8->dpm, bpwp); + retval = armv8_dpm_write_dirty_registers(&armv8->dpm, bpwp); + if (retval == ERROR_OK) { + /* registers are now invalid */ + register_cache_invalidate(arm->core_cache); + register_cache_invalidate(arm->core_cache->next); + } + + return retval; } /* @@ -1723,6 +2085,7 @@ static int aarch64_examine_first(struct target *target) struct aarch64_common *aarch64 = target_to_aarch64(target); struct armv8_common *armv8 = &aarch64->armv8_common; struct adiv5_dap *swjdp = armv8->arm.dap; + uint32_t cti_base; int i; int retval = ERROR_OK; uint64_t debug, ttypr; @@ -1730,9 +2093,6 @@ static int aarch64_examine_first(struct target *target) uint32_t tmp0, tmp1; debug = ttypr = cpuid = 0; - /* We do one extra read to ensure DAP is configured, - * we call ahbap_debugport_init(swjdp) instead - */ retval = dap_dp_init(swjdp); if (retval != ERROR_OK) return retval; @@ -1750,7 +2110,7 @@ static int aarch64_examine_first(struct target *target) return retval; } - armv8->debug_ap->memaccess_tck = 80; + armv8->debug_ap->memaccess_tck = 10; if (!target->dbgbase_set) { uint32_t dbgbase; @@ -1770,10 +2130,29 @@ static int aarch64_examine_first(struct target *target) } else armv8->debug_base = target->dbgbase; - retval = mem_ap_write_atomic_u32(armv8->debug_ap, - armv8->debug_base + CPUV8_DBG_LOCKACCESS, 0xC5ACCE55); + uint32_t prsr; + int64_t then = timeval_ms(); + do { + retval = mem_ap_read_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_PRSR, &prsr); + if (retval == ERROR_OK) { + retval = mem_ap_write_atomic_u32(armv8->debug_ap, + armv8->debug_base + CPUV8_DBG_PRCR, PRCR_COREPURQ|PRCR_CORENPDRQ); + if (retval != ERROR_OK) { + LOG_DEBUG("write to PRCR failed"); + break; + } + } + + if (timeval_ms() > then + 1000) { + retval = ERROR_TARGET_TIMEOUT; + break; + } + + } while ((prsr & PRSR_PU) == 0); + if (retval != ERROR_OK) { - LOG_DEBUG("LOCK debug access fail"); + LOG_ERROR("target %s: failed to set power state of the core.", target_name(target)); return retval; } @@ -1819,12 +2198,15 @@ static int aarch64_examine_first(struct target *target) if (target->ctibase == 0) { /* assume a v8 rom table layout */ - armv8->cti_base = target->ctibase = armv8->debug_base + 0x10000; - LOG_INFO("Target ctibase is not set, assuming 0x%0" PRIx32, target->ctibase); + cti_base = armv8->debug_base + 0x10000; + LOG_INFO("Target ctibase is not set, assuming 0x%0" PRIx32, cti_base); } else - armv8->cti_base = target->ctibase; + cti_base = target->ctibase; + + armv8->cti = arm_cti_create(armv8->debug_ap, cti_base); + if (armv8->cti == NULL) + return ERROR_FAIL; - armv8->arm.core_type = ARM_MODE_MON; retval = aarch64_dpm_setup(aarch64, debug); if (retval != ERROR_OK) return retval; @@ -1847,6 +2229,9 @@ static int aarch64_examine_first(struct target *target) LOG_DEBUG("Configured %i hw breakpoints", aarch64->brp_num); + target->state = TARGET_RUNNING; + target->debug_reason = DBG_REASON_NOTHALTED; + target_set_examined(target); return ERROR_OK; } @@ -1881,32 +2266,22 @@ static int aarch64_init_arch_info(struct target *target, struct aarch64_common *aarch64, struct jtag_tap *tap) { struct armv8_common *armv8 = &aarch64->armv8_common; - struct adiv5_dap *dap = armv8->arm.dap; - - armv8->arm.dap = dap; /* Setup struct aarch64_common */ aarch64->common_magic = AARCH64_COMMON_MAGIC; /* tap has no dap initialized */ if (!tap->dap) { tap->dap = dap_init(); - - /* Leave (only) generic DAP stuff for debugport_init() */ tap->dap->tap = tap; } - armv8->arm.dap = tap->dap; /* register arch-specific functions */ armv8->examine_debug_reason = NULL; - armv8->post_debug_entry = aarch64_post_debug_entry; - armv8->pre_restore_context = NULL; - armv8->armv8_mmu.read_physical_memory = aarch64_read_phys_memory; - /* REVISIT v7a setup should be in a v7a-specific routine */ armv8_init_arch_info(target, armv8); target_register_timer_callback(aarch64_handle_target_request, 1, 1, target); @@ -1923,7 +2298,7 @@ static int aarch64_target_create(struct target *target, Jim_Interp *interp) static int aarch64_mmu(struct target *target, int *enabled) { if (target->state != TARGET_HALTED) { - LOG_ERROR("%s: target not halted", __func__); + LOG_ERROR("%s: target %s not halted", __func__, target_name(target)); return ERROR_TARGET_INVALID; } @@ -1994,27 +2369,6 @@ COMMAND_HANDLER(aarch64_handle_smp_on_command) return ERROR_OK; } -COMMAND_HANDLER(aarch64_handle_smp_gdb_command) -{ - struct target *target = get_current_target(CMD_CTX); - int retval = ERROR_OK; - struct target_list *head; - head = target->head; - if (head != (struct target_list *)NULL) { - if (CMD_ARGC == 1) { - int coreid = 0; - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], coreid); - if (ERROR_OK != retval) - return retval; - target->gdb_service->core[1] = coreid; - - } - command_print(CMD_CTX, "gdb coreid %" PRId32 " -> %" PRId32, target->gdb_service->core[0] - , target->gdb_service->core[1]); - } - return ERROR_OK; -} - static const struct command_registration aarch64_exec_command_handlers[] = { { .name = "cache_info", @@ -2043,14 +2397,6 @@ static const struct command_registration aarch64_exec_command_handlers[] = { .help = "Restart smp handling", .usage = "", }, - { - .name = "smp_gdb", - .handler = aarch64_handle_smp_gdb_command, - .mode = COMMAND_EXEC, - .help = "display/fix current core played to gdb", - .usage = "", - }, - COMMAND_REGISTRATION_DONE }; diff --git a/src/target/armv8.h b/src/target/armv8.h index 1cb3a3b..02663ca 100644 --- a/src/target/armv8.h +++ b/src/target/armv8.h @@ -24,6 +24,7 @@ #include "armv4_5_mmu.h" #include "armv4_5_cache.h" #include "armv8_dpm.h" +#include "arm_cti.h" enum { ARMV8_R0 = 0, @@ -155,7 +156,6 @@ struct armv8_common { /* Core Debug Unit */ struct arm_dpm dpm; uint32_t debug_base; - uint32_t cti_base; struct adiv5_ap *debug_ap; const uint32_t *opcodes; @@ -173,6 +173,8 @@ struct armv8_common { struct armv8_mmu_common armv8_mmu; + struct arm_cti *cti; + /* Direct processor core register read and writes */ int (*read_reg_u64)(struct armv8_common *armv8, int num, uint64_t *value); int (*write_reg_u64)(struct armv8_common *armv8, int num, uint64_t value); @@ -222,40 +224,6 @@ target_to_armv8(struct target *target) #define CPUV8_DBG_AUTHSTATUS 0xFB8 -/*define CTI(cross trigger interface)*/ -#define CTI_CTR 0x0 -#define CTI_INACK 0x10 -#define CTI_APPSET 0x14 -#define CTI_APPCLEAR 0x18 -#define CTI_APPPULSE 0x1C -#define CTI_INEN0 0x20 -#define CTI_INEN1 0x24 -#define CTI_INEN2 0x28 -#define CTI_INEN3 0x2C -#define CTI_INEN4 0x30 -#define CTI_INEN5 0x34 -#define CTI_INEN6 0x38 -#define CTI_INEN7 0x3C -#define CTI_OUTEN0 0xA0 -#define CTI_OUTEN1 0xA4 -#define CTI_OUTEN2 0xA8 -#define CTI_OUTEN3 0xAC -#define CTI_OUTEN4 0xB0 -#define CTI_OUTEN5 0xB4 -#define CTI_OUTEN6 0xB8 -#define CTI_OUTEN7 0xBC -#define CTI_TRIN_STATUS 0x130 -#define CTI_TROUT_STATUS 0x134 -#define CTI_CHIN_STATUS 0x138 -#define CTI_CHOU_STATUS 0x13C -#define CTI_GATE 0x140 -#define CTI_UNLOCK 0xFB0 - -#define CTI_CHNL(x) (1 << x) -#define CTI_TRIG_HALT 0 -#define CTI_TRIG_RESUME 1 -#define CTI_TRIG(n) (1 << CTI_TRIG_##n) - #define PAGE_SIZE_4KB 0x1000 #define PAGE_SIZE_4KB_LEVEL0_BITS 39 #define PAGE_SIZE_4KB_LEVEL1_BITS 30 diff --git a/src/target/armv8_dpm.h b/src/target/armv8_dpm.h index 133b367..c039359 100644 --- a/src/target/armv8_dpm.h +++ b/src/target/armv8_dpm.h @@ -96,7 +96,7 @@ void armv8_dpm_report_wfar(struct arm_dpm *, uint64_t wfar); #define DRCR_RESTART (1 << 1) #define DRCR_CLEAR_EXCEPTIONS (1 << 2) -/* PRCR (processor debug status register) bits */ +/* PRSR (processor debug status register) bits */ #define PRSR_PU (1 << 0) #define PRSR_SPD (1 << 1) #define PRSR_RESET (1 << 2) @@ -110,6 +110,11 @@ void armv8_dpm_report_wfar(struct arm_dpm *, uint64_t wfar); #define PRSR_SPMAD (1 << 10) #define PRSR_SDR (1 << 11) +/* PRCR (processor debug control register) bits */ +#define PRCR_CORENPDRQ (1 << 0) +#define PRCR_CWRR (1 << 2) +#define PRCR_COREPURQ (1 << 3) + void armv8_dpm_report_dscr(struct arm_dpm *dpm, uint32_t dcsr); void armv8_dpm_handle_exception(struct arm_dpm *dpm); enum arm_state armv8_dpm_get_core_state(struct arm_dpm *dpm); -- cgit v1.1 From 2861ed533bfadac2b9259540e18c34c505ff2060 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 17 Feb 2017 15:05:15 +0100 Subject: armv8: spelling and formatting updates small changes to correct code formatting and spelling of some log messages. Change-Id: I645e675f8f9f4731b0271ddc55f64e8cf56ec1db Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3994 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/armv8.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/target/armv8.c b/src/target/armv8.c index 2f1d5c1..db7a871 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -408,8 +408,7 @@ static int armv8_write_reg32(struct armv8_common *armv8, int regnum, uint64_t va break; case ARMV8_SP: retval = dpm->instr_write_data_dcc(dpm, - ARMV4_5_MRC(14, 0, 13, 0, 5, 0), - value); + ARMV4_5_MRC(14, 0, 13, 0, 5, 0), value); break; case ARMV8_PC:/* PC * read r0 from DCC; then "MOV pc, r0" */ @@ -505,10 +504,9 @@ int armv8_read_mpidr(struct armv8_common *armv8) LOG_INFO("%s cluster %x core %x %s", target_name(armv8->arm.target), armv8->cluster_id, armv8->cpu_id, - armv8->multi_processor_system == 0 ? "multi core" : "mono core"); - + armv8->multi_processor_system == 0 ? "multi core" : "single core"); } else - LOG_ERROR("mpdir not in multiprocessor format"); + LOG_ERROR("mpidr not in multiprocessor format"); done: dpm->finish(dpm); @@ -612,7 +610,7 @@ done: /* (void) */ dpm->finish(dpm); } -static void armv8_show_fault_registers(struct target *target) +static __unused void armv8_show_fault_registers(struct target *target) { struct armv8_common *armv8 = target_to_armv8(target); @@ -836,9 +834,6 @@ int armv8_mmu_translate_va_pa(struct target *target, target_addr_t va, if (retval != ERROR_OK) return retval; - if (retval != ERROR_OK) - return retval; - if (par & 1) { LOG_ERROR("Address translation failed at stage %i, FST=%x, PTW=%i", ((int)(par >> 9) & 1)+1, (int)(par >> 1) & 0x3f, (int)(par >> 8) & 1); -- cgit v1.1 From b73628141a932881953bb816ec7bfa47d9e40680 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 17 Feb 2017 16:21:41 +0100 Subject: armv8_dpm: retrieve only necessary registers on halt to speed up debugging, don't load the complete register context on a halt event, load only those registers that might be clobbered during debugging. Change-Id: I0b58e97aad6f28aefce4a52e870af61e1ef1a44f Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3995 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/armv8_dpm.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index ac53460..e5d10df 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -718,14 +718,22 @@ int armv8_dpm_read_current_registers(struct arm_dpm *dpm) cache = arm->core_cache; /* read R0 first (it's used for scratch), then CPSR */ - r = cache->reg_list + 0; + r = cache->reg_list + ARMV8_R0; if (!r->valid) { - retval = dpmv8_read_reg(dpm, r, 0); + retval = dpmv8_read_reg(dpm, r, ARMV8_R0); if (retval != ERROR_OK) goto fail; } r->dirty = true; + /* read R1, too, it will be clobbered during memory access */ + r = cache->reg_list + ARMV8_R1; + if (!r->valid) { + retval = dpmv8_read_reg(dpm, r, ARMV8_R1); + if (retval != ERROR_OK) + goto fail; + } + /* read cpsr to r0 and get it back */ retval = dpm->instr_read_data_r0(dpm, armv8_opcode(armv8, READ_REG_DSPSR), &cpsr); @@ -735,7 +743,7 @@ int armv8_dpm_read_current_registers(struct arm_dpm *dpm) /* update core mode and state */ armv8_set_cpsr(arm, cpsr); - for (unsigned int i = 1; i < cache->num_regs ; i++) { + for (unsigned int i = ARMV8_PC; i < cache->num_regs ; i++) { struct arm_reg *arm_reg; r = armv8_reg_current(arm, i); -- cgit v1.1 From 9981093ce076a388700b2f307a9dc79e14a6e0f1 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Fri, 17 Feb 2017 16:22:52 +0100 Subject: armv8_dpm: fix exception handling after handling of an exception in debug state, immediately restore the original core state. Change-Id: Ie53b63c9f19815f717f4df4390fbc13f0a204cc2 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3996 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/armv8_dpm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/target/armv8_dpm.c b/src/target/armv8_dpm.c index e5d10df..f4e7a07 100644 --- a/src/target/armv8_dpm.c +++ b/src/target/armv8_dpm.c @@ -1312,6 +1312,8 @@ void armv8_dpm_handle_exception(struct arm_dpm *dpm) core_state = armv8_dpm_get_core_state(dpm); armv8_select_opcodes(armv8, core_state == ARM_STATE_AARCH64); armv8_select_reg_access(armv8, core_state == ARM_STATE_AARCH64); + + armv8_dpm_modeswitch(dpm, ARM_MODE_ANY); } /*----------------------------------------------------------------------*/ -- cgit v1.1 From 77189db85630cef21a4887a9b1c15dac3fd48473 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 23 Feb 2017 14:52:45 +0100 Subject: tcl: add Hi6220 target and LeMaker HiKey board config configuration covers all 8 Cortex-A53 cores and auxiliary Cortex-M3 used for power management. Change-Id: I5509f275aa669abe285f9152935ecdcbcd0c402e Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/4009 Tested-by: jenkins Reviewed-by: Paul Fertser --- tcl/board/lemaker_hikey.cfg | 26 +++++++++++++++++++++ tcl/target/hi6220.cfg | 56 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) create mode 100644 tcl/board/lemaker_hikey.cfg create mode 100644 tcl/target/hi6220.cfg diff --git a/tcl/board/lemaker_hikey.cfg b/tcl/board/lemaker_hikey.cfg new file mode 100644 index 0000000..d724440 --- /dev/null +++ b/tcl/board/lemaker_hikey.cfg @@ -0,0 +1,26 @@ +# +# board configuration for LeMaker Hikey +# + +# board does not feature anything but JTAG +transport select jtag + +# SRST-only reset configuration +reset_config srst_only srst_push_pull + +source [find target/hi6220.cfg] + +# halt the cores when gdb attaches +${_TARGETNAME}0 configure -event gdb-attach "halt" + +# make sure the default target is the boot core +targets ${_TARGETNAME}0 + +proc core_up { args } { + global _TARGETNAME + + # examine remaining cores + foreach _core [set args] { + ${_TARGETNAME}$_core arp_examine + } +} diff --git a/tcl/target/hi6220.cfg b/tcl/target/hi6220.cfg new file mode 100644 index 0000000..7daa3c1 --- /dev/null +++ b/tcl/target/hi6220.cfg @@ -0,0 +1,56 @@ +# Hisilicon Hi6220 Target + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME hi6220 +} + +# +# Main DAP +# +if { [info exists DAP_TAPID] } { + set _DAP_TAPID $DAP_TAPID +} else { + set _DAP_TAPID 0x4ba00477 +} + +# declare the one JTAG tap to access the DAP +jtag newtap $_CHIPNAME dap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -ignore-version -enable + +# declare the 8 main application cores +set _TARGETNAME $_CHIPNAME.cpu +set _smp_command "" + +set $_TARGETNAME.cti(0) 0x80198000 +set $_TARGETNAME.cti(1) 0x80199000 +set $_TARGETNAME.cti(2) 0x8019A000 +set $_TARGETNAME.cti(3) 0x8019B000 +set $_TARGETNAME.cti(4) 0x801D8000 +set $_TARGETNAME.cti(5) 0x801D9000 +set $_TARGETNAME.cti(6) 0x801DA000 +set $_TARGETNAME.cti(7) 0x801DB000 + +set _cores 8 +for { set _core 0 } { $_core < $_cores } { incr _core 1 } { + + set _command "target create ${_TARGETNAME}$_core aarch64 \ + -chain-position $_CHIPNAME.dap -coreid $_core -ctibase [set $_TARGETNAME.cti($_core)]" + + if { $_core != 0 } { + # non-boot core examination may fail + set _command "$_command -defer-examine" + set _smp_command "$_smp_command ${_TARGETNAME}$_core" + } else { + # uncomment when "hawt" rtos is merged + # set _command "$_command -rtos hawt" + set _smp_command "target smp ${_TARGETNAME}$_core" + } + + eval $_command +} + +eval $_smp_command + +# declare the auxiliary Cortex-M3 core on AP #2 (runs mcuimage.bin) +target create ${_TARGETNAME}.m3 cortex_m -chain-position $_CHIPNAME.dap -ap-num 2 -defer-examine -- cgit v1.1 From 6b2acc0243f6dd54823c336ded8c20d16cdc50a3 Mon Sep 17 00:00:00 2001 From: Girts Folkmanis Date: Fri, 3 Mar 2017 09:49:58 -0800 Subject: arm_dpm: fix dpm setup When ARM64 support was being merged, a comparison ended up being inverted. This causes NULL pointer access when target attempts to use core cache. Change-Id: Ic8873ddd13dbdd8100856a71b4717f44cd336e23 Signed-off-by: Girts Folkmanis Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/4042 Reviewed-by: Matthias Welwarsky Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/arm_dpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target/arm_dpm.c b/src/target/arm_dpm.c index f15bff7..3e8180c 100644 --- a/src/target/arm_dpm.c +++ b/src/target/arm_dpm.c @@ -973,7 +973,7 @@ int arm_dpm_setup(struct arm_dpm *dpm) arm->read_core_reg = arm_dpm_read_core_reg; arm->write_core_reg = arm_dpm_write_core_reg; - if (arm->core_cache != NULL) { + if (arm->core_cache == NULL) { cache = arm_build_reg_cache(target, arm); if (!cache) return ERROR_FAIL; -- cgit v1.1 From 2804480b097ebf64810100a1c744188ee01ce3c0 Mon Sep 17 00:00:00 2001 From: Andreas Fritiofson Date: Thu, 29 Dec 2016 12:19:11 +0100 Subject: nrf51: Remove pointer cast Int may not be 32 bit long. Change-Id: I420f7efeb484eb35c1d7c20e1575b0b31ed8c9ff Signed-off-by: Andreas Fritiofson Reviewed-on: http://openocd.zylin.com/3930 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/flash/nor/nrf51.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/flash/nor/nrf51.c b/src/flash/nor/nrf51.c index a41bc05..e3f6c10 100644 --- a/src/flash/nor/nrf51.c +++ b/src/flash/nor/nrf51.c @@ -690,14 +690,15 @@ static int nrf51_probe(struct flash_bank *bank) /* Note the register name is misleading, * NRF51_FICR_CODESIZE is the number of pages in flash memory, not the number of bytes! */ - res = target_read_u32(chip->target, NRF51_FICR_CODESIZE, - (uint32_t *) &bank->num_sectors); + uint32_t num_sectors; + res = target_read_u32(chip->target, NRF51_FICR_CODESIZE, &num_sectors); if (res != ERROR_OK) { LOG_ERROR("Couldn't read code memory size"); return res; } - bank->size = bank->num_sectors * chip->code_page_size; + bank->num_sectors = num_sectors; + bank->size = num_sectors * chip->code_page_size; if (spec && bank->size / 1024 != spec->flash_size_kb) LOG_WARNING("Chip's reported Flash capacity does not match expected one"); -- cgit v1.1 From 332d66c75a89516750726f1a9d2b65a624037770 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Wed, 1 Mar 2017 16:15:33 +0100 Subject: aarch64: clear CTI halt event early at debug entry The halt event was left pending in the CTI, better to clear it immediately after debug entry. Change-Id: I6002f862681baf98769e3c73332a7f7f0ef938c1 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/4030 Tested-by: jenkins Reviewed-by: Paul Fertser --- src/target/aarch64.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index 9977c36..e647bba 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -923,6 +923,8 @@ static int aarch64_debug_entry(struct target *target) if (retval == ERROR_OK) retval = mem_ap_read_atomic_u32(armv8->debug_ap, armv8->debug_base + CPUV8_DBG_DSCR, &dscr); + if (retval == ERROR_OK) + retval = arm_cti_ack_events(armv8->cti, CTI_TRIG(HALT)); if (retval != ERROR_OK) return retval; -- cgit v1.1 From f605a23bc4b2620b493bd07241cd5928b74e197f Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Thu, 23 Feb 2017 14:17:15 +0100 Subject: aarch64: add some documentation document aarch64 specific commands and common ARMv7 and v8 DAP commands Change-Id: Icbb76209735ec734f2e67f82bfc7270edb40ad0b Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/4008 Tested-by: jenkins Reviewed-by: Paul Fertser --- doc/openocd.texi | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index 45b341c..c3053b7 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4004,6 +4004,7 @@ At this writing, the supported CPU types are: @item @code{cortex_a} -- this is an ARMv7 core with an MMU @item @code{cortex_m} -- this is an ARMv7 core, supporting only the compact Thumb2 instruction set. +@item @code{aarch64} -- this is an ARMv8-A core with an MMU @item @code{dragonite} -- resembles arm966e @item @code{dsp563xx} -- implements Freescale's 24-bit DSP. (Support for this is still incomplete.) @@ -4036,7 +4037,7 @@ The CPU name used by OpenOCD will reflect the CPU design that was licenced, not a vendor brand which incorporates that design. Name prefixes like arm7, arm9, arm11, and cortex reflect design generations; -while names like ARMv4, ARMv5, ARMv6, and ARMv7 +while names like ARMv4, ARMv5, ARMv6, ARMv7 and ARMv8 reflect an architecture version implemented by a CPU design. @anchor{targetconfiguration} @@ -4180,6 +4181,10 @@ access the target for debugging. @var{ap_number} is the numeric index of the DAP AP the target is connected to. Use this option with systems where multiple, independent cores are connected to separate access ports of the same DAP. + +@item @code{-ctibase} @var{address} -- set base address of Cross-Trigger interface (CTI) connected +to the target. Currently, only the @code{aarch64} target makes use of this option, where it is +a mandatory configuration for the target run control. @end itemize @end deffn @@ -7854,13 +7859,14 @@ coprocessor 14 register 7 itself) but all current ARM11 cores @emph{except the ARM1176} use the same six bits. @end deffn -@section ARMv7 Architecture +@section ARMv7 and ARMv8 Architecture @cindex ARMv7 +@cindex ARMv8 -@subsection ARMv7 Debug Access Port (DAP) specific commands +@subsection ARMv7 and ARMv8 Debug Access Port (DAP) specific commands @cindex Debug Access Port @cindex DAP -These commands are specific to ARM architecture v7 Debug Access Port (DAP), +These commands are specific to ARM architecture v7 and v8 Debug Access Port (DAP), included on Cortex-M and Cortex-A systems. They are available in addition to other core-specific commands that may be available. @@ -8114,6 +8120,29 @@ the peripherals. @xref{targetevents,,Target Events}. @end deffn +@subsection ARMv8-A specific commands +@cindex ARMv8-A +@cindex aarch64 + +@deffn Command {aarch64 cache_info} +Display information about target caches +@end deffn + +@deffn Command {aarch64 dbginit} +This command enables debugging by clearing the OS Lock and sticky power-down and reset +indications. It also establishes the expected, basic cross-trigger configuration the aarch64 +target code relies on. In a configuration file, the command would typically be called from a +@code{reset-end} or @code{reset-deassert-post} handler, to re-enable debugging after a system reset. +However, normally it is not necessary to use the command at all. +@end deffn + +@deffn Command {aarch64 smp_on|smp_off} +Enable and disable SMP handling. The state of SMP handling influences the way targets in an SMP group +are handled by the run control. With SMP handling enabled, issuing halt or resume to one core will trigger +halting or resuming of all cores in the group. The command @code{target smp} defines which targets are in the SMP +group. With SMP handling disabled, all targets need to be treated individually. +@end deffn + @section Intel Architecture Intel Quark X10xx is the first product in the Quark family of SoCs. It is an IA-32 -- cgit v1.1 From 568e84236bf3b58f4eef73cbed70f3544b44df1f Mon Sep 17 00:00:00 2001 From: Austin Morton Date: Tue, 28 Mar 2017 23:22:44 -0400 Subject: stlink: increase trace buffer size to maximum allowed on st-link v2 firmware Increasing the trace buffer size on the st-link itself gives openocd a greater chance of avoiding trace data overflowing within the st-link between polls when there is a large amount of data being sent over the trace port The st-link appears to split the given buffer size in half while one half is awaiting transfer over USB, the other half is being filled by DMA transfer. If you do not poll frequently enough, the DMA transfer will overflow back to the start of its current buffer, resulting in corrupted output Buffer size of 4096 bytes is the maximum allowed by the st-link v2 Change-Id: I169189b021c34f8d18de1601d78b8c5890367d68 Signed-off-by: Austin Morton Reviewed-on: http://openocd.zylin.com/4085 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Freddie Chopin --- src/jtag/drivers/stlink_usb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 699c41f..0bdcd31 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -216,7 +216,7 @@ struct stlink_usb_handle_s { #define STLINK_DEBUG_APIV2_DRIVE_NRST_HIGH 0x01 #define STLINK_DEBUG_APIV2_DRIVE_NRST_PULSE 0x02 -#define STLINK_TRACE_SIZE 1024 +#define STLINK_TRACE_SIZE 4096 #define STLINK_TRACE_MAX_HZ 2000000 #define STLINK_TRACE_MIN_VERSION 13 -- cgit v1.1 From 518fcd38834ef2f7b19707ccaa52914c2bea9f91 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 8 Jan 2017 20:19:29 +0100 Subject: target: Fix memory leak MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ib23dfd653d8edacb890a46179e9d437c027d58e8 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/4048 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Chengyu Zheng Reviewed-by: Andreas Färber --- src/target/target.c | 23 +++++++++++++++++++---- src/target/target.h | 2 +- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/target/target.c b/src/target/target.c index ee302ee..e04ecc4 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -1870,6 +1870,17 @@ int target_free_working_area(struct target *target, struct working_area *area) return target_free_working_area_restore(target, area, 1); } +static void target_destroy(struct target *target) +{ + if (target->type->deinit_target) + target->type->deinit_target(target); + + free(target->type); + free(target->trace_info); + free(target->cmd_name); + free(target); +} + void target_quit(void) { struct target_event_callback *pe = target_event_callbacks; @@ -1888,11 +1899,15 @@ void target_quit(void) } target_timer_callbacks = NULL; - for (struct target *target = all_targets; - target; target = target->next) { - if (target->type->deinit_target) - target->type->deinit_target(target); + for (struct target *target = all_targets; target;) { + struct target *tmp; + + tmp = target->next; + target_destroy(target); + target = tmp; } + + all_targets = NULL; } /* free resources and restore memory, if restoring memory fails, diff --git a/src/target/target.h b/src/target/target.h index 76630b9..53f9e26 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -125,7 +125,7 @@ enum target_register_class { /* target_type.h contains the full definition of struct target_type */ struct target { struct target_type *type; /* target type definition (name, access functions) */ - const char *cmd_name; /* tcl Name of target */ + char *cmd_name; /* tcl Name of target */ int target_number; /* DO NOT USE! field to be removed in 2010 */ struct jtag_tap *tap; /* where on the jtag chain is this */ int32_t coreid; /* which device on the TAP? */ -- cgit v1.1 From 668347e8248aa97b2006e08d48fbdddc5931786b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Wed, 12 Apr 2017 10:27:28 +0200 Subject: flash Kinetis: reduce a flash write message severity to info MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There is nothing the user can do if their device does not support sector programming, there is no reason to have this message at warning level. Change-Id: Ic9b7386e59b64fece7fbfdc543bdfeeed3eae73d Signed-off-by: Joakim Nohlgård Reviewed-on: http://openocd.zylin.com/4105 Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/flash/nor/kinetis.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/flash/nor/kinetis.c b/src/flash/nor/kinetis.c index 49a6e27..7e9bbde 100644 --- a/src/flash/nor/kinetis.c +++ b/src/flash/nor/kinetis.c @@ -1371,7 +1371,7 @@ static int kinetis_write_inner(struct flash_bank *bank, const uint8_t *buffer, if (!(kinfo->flash_support & FS_PROGRAM_SECTOR)) { /* fallback to longword write */ fallback = 1; - LOG_WARNING("This device supports Program Longword execution only."); + LOG_INFO("This device supports Program Longword execution only."); } else { result = kinetis_make_ram_ready(bank->target); if (result != ERROR_OK) { -- cgit v1.1 From 34eb2933d4a43adca556757e1a799ecbda88b0ec Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 9 Jan 2017 15:30:21 +0100 Subject: jtag/drivers cmsis-dap: fix speed setting on Atmel EDBG Without the change Atmel EDBG uses default clock freq about 168 kHz instead adapter_khz configured before interface init. Changing adapter speed after init works as expected. Testing shows the EDBG firmware resets speed to default during DAP_SWJ_Sequence. Tested with fw versions 03.1F.01AE and 02.09.0169 This change repeats the DAP_SWJ_Clock command after sending a SWJ sequence. Change-Id: Ic70457c5df635f47cad5e70b0dc83a083ea1b3a3 Reported-by: Ladislav Laska Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3944 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/jtag/drivers/cmsis_dap_usb.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/jtag/drivers/cmsis_dap_usb.c b/src/jtag/drivers/cmsis_dap_usb.c index dd37522..cffd5e7 100644 --- a/src/jtag/drivers/cmsis_dap_usb.c +++ b/src/jtag/drivers/cmsis_dap_usb.c @@ -821,7 +821,13 @@ static int cmsis_dap_swd_switch_seq(enum swd_special_seq seq) return ERROR_FAIL; } - return cmsis_dap_cmd_DAP_SWJ_Sequence(s_len, s); + retval = cmsis_dap_cmd_DAP_SWJ_Sequence(s_len, s); + if (retval != ERROR_OK) + return retval; + + /* Atmel EDBG needs renew clock setting after SWJ_Sequence + * otherwise default frequency is used */ + return cmsis_dap_cmd_DAP_SWJ_Clock(jtag_get_speed_khz()); } static int cmsis_dap_swd_open(void) -- cgit v1.1 From d7d7d8bd409124a39a961579e818e658697991c1 Mon Sep 17 00:00:00 2001 From: Matthias Bock Date: Wed, 19 Apr 2017 14:53:05 +0200 Subject: added interface config file for In-Circuit's ICprog OpenOCD JTAG adapter Change-Id: I9f9758d3a30bbcca9f750f604e011e5cc25809c5 Signed-off-by: Matthias Bock Reviewed-on: http://openocd.zylin.com/4107 Tested-by: jenkins Reviewed-by: Paul Fertser --- tcl/interface/ftdi/incircuit-icprog.cfg | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tcl/interface/ftdi/incircuit-icprog.cfg diff --git a/tcl/interface/ftdi/incircuit-icprog.cfg b/tcl/interface/ftdi/incircuit-icprog.cfg new file mode 100644 index 0000000..5e90a70 --- /dev/null +++ b/tcl/interface/ftdi/incircuit-icprog.cfg @@ -0,0 +1,14 @@ +# +# In-Circuit's ICprog OpenOCD JTAG Adapter +# https://shop.in-circuit.de/product_info.php?products_id=112 +# +# Schematics available at +# http://wiki.in-circuit.de/images/0/06/610000158A_openocd.pdf +# + +interface ftdi +ftdi_vid_pid 0x0403 0x6010 + +ftdi_layout_init 0x0508 0x0f1b +ftdi_layout_signal nSRST -noe 0x0400 -data 0x0800 +ftdi_layout_signal nTRST -noe 0x0100 -data 0x0200 -- cgit v1.1 From 6e8217784bfe4027a753f75a2c0fe732bfd8d2e0 Mon Sep 17 00:00:00 2001 From: Chengyu Zheng Date: Sun, 9 Apr 2017 18:55:02 +0200 Subject: tools/scripts/checkpatch.pl: fix unescaped brace Change-Id: If1d0fbe95223351ea098504cf24f076784b26a9c Signed-off-by: Chengyu Zheng Reviewed-on: http://openocd.zylin.com/4102 Tested-by: jenkins Reviewed-by: Freddie Chopin --- tools/scripts/checkpatch.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/scripts/checkpatch.pl b/tools/scripts/checkpatch.pl index 92befc6..b977d36 100755 --- a/tools/scripts/checkpatch.pl +++ b/tools/scripts/checkpatch.pl @@ -2224,7 +2224,7 @@ sub process { # function brace can't be on same line, except for #defines of do while, # or if closed on same line - if (($line=~/$Type\s*$Ident\(.*\).*\s{/) and + if (($line=~/$Type\s*$Ident\(.*\).*\s\{/) and !($line=~/\#\s*define.*do\s\{/) and !($line=~/}/)) { ERROR("OPEN_BRACE", "open brace '{' following function declarations go on the next line\n" . $herecurr); -- cgit v1.1 From 7829f31a6dd61297e97d8e94fe98a1658eac833e Mon Sep 17 00:00:00 2001 From: Damyan Mitev Date: Tue, 4 Apr 2017 10:12:44 +0300 Subject: nrf51: Add new HWID 0x008F Add new entry in nrf51_known_devices_table for nRF51822 chip found on chinese Core51822 dev board. The chp has markings N51822 / QFAAH1 / 1630FW Nordic Semiconductor nRF51 Series Compatibility matrix confirms that this chip has 256K Flash and 16K RAM. Change-Id: I571d15913c6f6e02a6f09c883d7dfc5a66b57c28 Signed-off-by: Damyan Mitev Reviewed-on: http://openocd.zylin.com/4091 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/flash/nor/nrf51.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/flash/nor/nrf51.c b/src/flash/nor/nrf51.c index e3f6c10..7b7acf4 100644 --- a/src/flash/nor/nrf51.c +++ b/src/flash/nor/nrf51.c @@ -291,6 +291,13 @@ static const struct nrf51_device_spec nrf51_known_devices_table[] = { .build_code = "A0", .flash_size_kb = 256, }, + { + .hwid = 0x008F, + .part = "51822", + .variant = "QFAA", + .build_code = "H1", + .flash_size_kb = 256, + }, /* nRF51422 Devices (IC rev 1). */ { -- cgit v1.1 From 1894292032cfa64a745349344ee7b6271867444f Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Wed, 4 Nov 2015 11:25:51 +0100 Subject: board: introduce base config for TI BeagleBone family boards This patch adds the file ti_beaglebone-base.cfg as the common base configuration for all TI BeagleBone derived boards. It also modifies ti_beaglebone.cfg to source the base board and only add the on-board JTAG adapter. Lastly, it adds a file ti_beaglebone_black.cfg with a suitable configuraton for the BeagleBone "Black" variant. Change-Id: I40cacb8abed7bdb308929713891f7b5e5b685c95 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/3099 Tested-by: jenkins Reviewed-by: Freddie Chopin --- tcl/board/ti_beaglebone-base.cfg | 4 ++++ tcl/board/ti_beaglebone.cfg | 4 ++-- tcl/board/ti_beaglebone_black.cfg | 8 ++++++++ 3 files changed, 14 insertions(+), 2 deletions(-) create mode 100644 tcl/board/ti_beaglebone-base.cfg create mode 100644 tcl/board/ti_beaglebone_black.cfg diff --git a/tcl/board/ti_beaglebone-base.cfg b/tcl/board/ti_beaglebone-base.cfg new file mode 100644 index 0000000..82d3c31 --- /dev/null +++ b/tcl/board/ti_beaglebone-base.cfg @@ -0,0 +1,4 @@ +# AM335x Beaglebone family base configuration +# http://beagleboard.org/bone + +source [find target/am335x.cfg] diff --git a/tcl/board/ti_beaglebone.cfg b/tcl/board/ti_beaglebone.cfg index 5d31d1d..a54ad62 100644 --- a/tcl/board/ti_beaglebone.cfg +++ b/tcl/board/ti_beaglebone.cfg @@ -6,8 +6,8 @@ source [find interface/ftdi/xds100v2.cfg] adapter_khz 16000 -source [find target/am335x.cfg] - reset_config trst_and_srst +source [find board/ti_beaglebone-base.cfg] + diff --git a/tcl/board/ti_beaglebone_black.cfg b/tcl/board/ti_beaglebone_black.cfg new file mode 100644 index 0000000..79fc1e8 --- /dev/null +++ b/tcl/board/ti_beaglebone_black.cfg @@ -0,0 +1,8 @@ +# AM335x Beaglebone Black +# http://beagleboard.org/bone + +adapter_khz 1000 + +reset_config trst_and_srst + +source [find board/ti_beaglebone-base.cfg] -- cgit v1.1 From f63af76466234cc905df6ea8e0f3fb5284c2058d Mon Sep 17 00:00:00 2001 From: Girts Date: Sat, 5 Nov 2016 14:38:55 -0700 Subject: help/options.c: add error handling for -d arg Fail if we fail to set debug level. Also, clarify in usage string that -d doesn't accept spaces. Change-Id: I9ea9945dc068e3e7cfd18b16ffa2a29366d6e4d1 Signed-off-by: Girts Folkmanis Reviewed-on: http://openocd.zylin.com/3880 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/helper/options.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/helper/options.c b/src/helper/options.c index 409abee..0016659 100644 --- a/src/helper/options.c +++ b/src/helper/options.c @@ -267,8 +267,10 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) case 'd': /* --debug | -d */ { char *command = alloc_printf("debug_level %s", optarg ? optarg : "3"); - command_run_line(cmd_ctx, command); + int retval = command_run_line(cmd_ctx, command); free(command); + if (retval != ERROR_OK) + return retval; break; } case 'l': /* --log_output | -l */ @@ -298,7 +300,8 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) LOG_OUTPUT("--version | -v\tdisplay OpenOCD version\n"); LOG_OUTPUT("--file | -f\tuse configuration file \n"); LOG_OUTPUT("--search | -s\tdir to search for config files and scripts\n"); - LOG_OUTPUT("--debug | -d\tset debug level <0-3>\n"); + LOG_OUTPUT("--debug | -d\tset debug level to 3\n"); + LOG_OUTPUT(" | -d\tset debug level to \n"); LOG_OUTPUT("--log_output | -l\tredirect log output to file \n"); LOG_OUTPUT("--command | -c\trun \n"); exit(-1); -- cgit v1.1 From b90d58db07459a353d20b052bd1e4732fec03aa5 Mon Sep 17 00:00:00 2001 From: Girts Date: Sat, 5 Nov 2016 14:38:55 -0700 Subject: helper/options.c: fail if unexpected cmdline arguments are present Previously openocd would silently ignore any incorrect arguments. Change-Id: Ibb40b57b8a9e07d191215486f3b3c4920a9963c7 Signed-off-by: Girts Folkmanis Reviewed-on: http://openocd.zylin.com/3879 Tested-by: jenkins Reviewed-by: Tomas Vanek --- src/helper/options.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/helper/options.c b/src/helper/options.c index 0016659..1cfa553 100644 --- a/src/helper/options.c +++ b/src/helper/options.c @@ -291,9 +291,18 @@ int parse_cmdline_args(struct command_context *cmd_ctx, int argc, char *argv[]) LOG_WARNING("deprecated option: -p/--pipe. Use '-c \"gdb_port pipe; " "log_output openocd.log\"' instead."); break; + default: /* '?' */ + /* getopt will emit an error message, all we have to do is bail. */ + return ERROR_FAIL; } } + if (optind < argc) { + /* Catch extra arguments on the command line. */ + LOG_OUTPUT("Unexpected command line argument: %s\n", argv[optind]); + return ERROR_FAIL; + } + if (help_flag) { LOG_OUTPUT("Open On-Chip Debugger\nLicensed under GNU GPL v2\n"); LOG_OUTPUT("--help | -h\tdisplay this help\n"); -- cgit v1.1 From 8addd9503eeb7704907d2340378d1200e3bbb99c Mon Sep 17 00:00:00 2001 From: Girts Date: Sat, 5 Nov 2016 14:38:55 -0700 Subject: help/log.c: better error handling for "log_output" * Close previous log file if one was opened before. * Return error if opening file fails. Change-Id: I103025cd86bcac785fe39e13bc7d5f79d78e38e7 Signed-off-by: Girts Folkmanis Reviewed-on: http://openocd.zylin.com/3878 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/helper/log.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/helper/log.c b/src/helper/log.c index e7af803..891613d 100644 --- a/src/helper/log.c +++ b/src/helper/log.c @@ -251,9 +251,15 @@ COMMAND_HANDLER(handle_log_output_command) { if (CMD_ARGC == 1) { FILE *file = fopen(CMD_ARGV[0], "w"); - - if (file) - log_output = file; + if (file == NULL) { + LOG_ERROR("failed to open output log '%s'", CMD_ARGV[0]); + return ERROR_FAIL; + } + if (log_output != stderr && log_output != NULL) { + /* Close previous log file, if it was open and wasn't stderr. */ + fclose(log_output); + } + log_output = file; } return ERROR_OK; -- cgit v1.1 From 73a94649606f31b46eb382dba6b3009035605c71 Mon Sep 17 00:00:00 2001 From: Jerome Lambourg Date: Wed, 6 Apr 2016 17:16:41 +0200 Subject: Add support for the ATMEL SAM G55 Xplained Pro board and CPU. Change-Id: Iffe59dcf9f2cb1f5949c37d11fe0d2141a47f8da Signed-off-by: Paul Fertser Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3922 Tested-by: jenkins Reviewed-by: Leo Zhang Reviewed-by: Freddie Chopin --- src/flash/nor/at91sam4.c | 70 +++++++++++++++++++++++++++++++++ tcl/board/atmel_samg55_xplained_pro.cfg | 11 ++++++ 2 files changed, 81 insertions(+) create mode 100644 tcl/board/atmel_samg55_xplained_pro.cfg diff --git a/src/flash/nor/at91sam4.c b/src/flash/nor/at91sam4.c index 94d5bfd..ff75b41 100644 --- a/src/flash/nor/at91sam4.c +++ b/src/flash/nor/at91sam4.c @@ -1340,6 +1340,74 @@ static const struct sam4_chip_details all_sam4_details[] = { } }, + /* atsamg55g19 */ + { + .chipid_cidr = 0x24470ae0, + .name = "atsamg55g19", + .total_flash_size = 512 * 1024, + .total_sram_size = 160 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + + { +/* .bank[0] = */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = */ + { + .present = 0, + .probed = 0, + .bank_number = 1, + }, + } + }, + + /* atsamg55j19 */ + { + .chipid_cidr = 0x24570ae0, + .name = "atsamg55j19", + .total_flash_size = 512 * 1024, + .total_sram_size = 160 * 1024, + .n_gpnvms = 2, + .n_banks = 1, + + { +/* .bank[0] = */ + { + .probed = 0, + .pChip = NULL, + .pBank = NULL, + .bank_number = 0, + .base_address = FLASH_BANK_BASE_S, + .controller_address = 0x400e0a00, + .flash_wait_states = 5, + .present = 1, + .size_bytes = 512 * 1024, + .nsectors = 64, + .sector_size = 8192, + .page_size = 512, + }, +/* .bank[1] = */ + { + .present = 0, + .probed = 0, + .bank_number = 1, + }, + } + }, + /* terminate */ { .chipid_cidr = 0, @@ -1917,6 +1985,8 @@ static const struct archnames { unsigned value; const char *name; } archnames[] { 0x42, "AT91x42 Series" }, { 0x43, "SAMG51 Series" }, + { 0x44, "SAMG55 Series (49-pin WLCSP)" }, + { 0x45, "SAMG55 Series (64-pin)" }, { 0x47, "SAMG53 Series" }, { 0x55, "AT91x55 Series" }, diff --git a/tcl/board/atmel_samg55_xplained_pro.cfg b/tcl/board/atmel_samg55_xplained_pro.cfg new file mode 100644 index 0000000..3797bf8 --- /dev/null +++ b/tcl/board/atmel_samg55_xplained_pro.cfg @@ -0,0 +1,11 @@ +# +# Atmel SAMG55 Xplained Pro evaluation kit. +# http://www.atmel.com/tools/ATSAMG55-XPRO.aspx +# + +source [find interface/cmsis-dap.cfg] + +# chip name +set CHIPNAME ATSAMG55J19 + +source [find target/at91samg5x.cfg] -- cgit v1.1 From 44ad4fdcb026e513681f2d8c4c812652b13a389c Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Mon, 9 Jan 2017 17:06:52 +0100 Subject: jtag/drivers cmsis-dap: do not limit speed so strictly Adapter clock frequency is set by 32-bit number and most adapters limit the highest speed safely. There is no reason to impose strict limit of 5000 kHz if some adapters can do more. While on it give informative error message in case of zero adapter_khz. Change-Id: I45c9804678e24496ea769ea9ca6036701b04dde9 Signed-off-by: Tomas Vanek Reviewed-on: http://openocd.zylin.com/3945 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/jtag/drivers/cmsis_dap_usb.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/jtag/drivers/cmsis_dap_usb.c b/src/jtag/drivers/cmsis_dap_usb.c index cffd5e7..86f7968 100644 --- a/src/jtag/drivers/cmsis_dap_usb.c +++ b/src/jtag/drivers/cmsis_dap_usb.c @@ -1499,13 +1499,11 @@ static int cmsis_dap_execute_queue(void) static int cmsis_dap_speed(int speed) { - if (speed > DAP_MAX_CLOCK) { - LOG_INFO("reduce speed request: %dkHz to %dkHz maximum", speed, DAP_MAX_CLOCK); - speed = DAP_MAX_CLOCK; - } + if (speed > DAP_MAX_CLOCK) + LOG_INFO("High speed (adapter_khz %d) may be limited by adapter firmware.", speed); if (speed == 0) { - LOG_INFO("RTCK not supported"); + LOG_ERROR("RTCK not supported. Set nonzero adapter_khz."); return ERROR_JTAG_NOT_IMPLEMENTED; } -- cgit v1.1 From 2e0e6c5634b65043938ab4eb6244566b747ddc06 Mon Sep 17 00:00:00 2001 From: Tomas Vanek Date: Fri, 3 Mar 2017 17:52:00 +0100 Subject: flash/nor/at91samd: fix chip erase of a secured device 'at91samd chip-erase' command did not work on secured device. Fix it changing address of DSU.CTRL register (see Atmel SAM D21 datasheet, 13.9. Intellectual Property Protection). While on it check error return of DSU.CTRL write. Change-Id: I83155a634a5458cdc0cc16c99c0e155eb1d8b3d6 Signed-off-by: Tomas Vanek Reported-by: Thomas Irmen Reviewed-on: http://openocd.zylin.com/4043 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/flash/nor/at91samd.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/flash/nor/at91samd.c b/src/flash/nor/at91samd.c index 2673b0e..f018e89 100644 --- a/src/flash/nor/at91samd.c +++ b/src/flash/nor/at91samd.c @@ -36,6 +36,7 @@ #define SAMD_DSU_STATUSA 1 /* DSU status register */ #define SAMD_DSU_DID 0x18 /* Device ID register */ +#define SAMD_DSU_CTRL_EXT 0x100 /* CTRL register, external access */ #define SAMD_NVMCTRL_CTRLA 0x00 /* NVM control A register */ #define SAMD_NVMCTRL_CTRLB 0x04 /* NVM control B register */ @@ -859,18 +860,23 @@ COMMAND_HANDLER(samd_handle_info_command) COMMAND_HANDLER(samd_handle_chip_erase_command) { struct target *target = get_current_target(CMD_CTX); + int res = ERROR_FAIL; if (target) { /* Enable access to the DSU by disabling the write protect bit */ target_write_u32(target, SAMD_PAC1, (1<<1)); + /* intentionally without error checking - not accessible on secured chip */ + /* Tell the DSU to perform a full chip erase. It takes about 240ms to * perform the erase. */ - target_write_u8(target, SAMD_DSU, (1<<4)); - - command_print(CMD_CTX, "chip erased"); + res = target_write_u8(target, SAMD_DSU + SAMD_DSU_CTRL_EXT, (1<<4)); + if (res == ERROR_OK) + command_print(CMD_CTX, "chip erase started"); + else + command_print(CMD_CTX, "write to DSU CTRL failed"); } - return ERROR_OK; + return res; } COMMAND_HANDLER(samd_handle_set_security_command) -- cgit v1.1 From ca9dcc86d7d9f465950a0670a8c7a852ae2ca798 Mon Sep 17 00:00:00 2001 From: Armin van der Togt Date: Thu, 2 Mar 2017 17:31:14 +0100 Subject: Fix flash writing on stm32l0 Fix "couldn't use loader, falling back to page memory writes" error on stm32l0 which was caused by the use of cortex-m3 instructions in the flash loader code. The loader is rewritten using cortex-m0 compatible instructions Signed-off-by: Armin van der Togt Change-Id: If23027b8e09f74e45129e1f8452a04bb994c424e Reviewed-on: http://openocd.zylin.com/4036 Tested-by: jenkins Reviewed-by: Freddie Chopin --- contrib/loaders/flash/stm32lx.S | 32 ++++++++++++++++---------------- src/flash/nor/stm32lx.c | 16 ++-------------- 2 files changed, 18 insertions(+), 30 deletions(-) diff --git a/contrib/loaders/flash/stm32lx.S b/contrib/loaders/flash/stm32lx.S index 88deed3..8f9fd0b 100644 --- a/contrib/loaders/flash/stm32lx.S +++ b/contrib/loaders/flash/stm32lx.S @@ -8,6 +8,9 @@ * Copyright (C) 2011 Clement Burin des Roziers * * clement.burin-des-roziers@hikob.com * * * + * Copyright (C) 2017 Armin van der Togt * + * armin@otheruse.nl * + * * * 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 * @@ -28,7 +31,7 @@ // Build : arm-eabi-gcc -c stm32lx.S .text .syntax unified - .cpu cortex-m3 + .cpu cortex-m0 .thumb .thumb_func .global write @@ -39,24 +42,21 @@ r2 - count */ - // Set 0 to r3 - movs r3, #0 + // r2 = source + count * 4 + lsls r2, r2, #2 + adds r2, r1, r2 // Go to compare - b.n test_done - + b test_done write_word: - // Load one word from address in r0, increment by 4 - ldr.w ip, [r1], #4 - // Store the word to address in r1, increment by 4 - str.w ip, [r0], #4 - // Increment r3 - adds r3, #1 - + // load word from address in r1 and increase r1 by 4 + ldmia r1!, {r3} + // store word to address in r0 and increase r0 by 4 + stmia r0!, {r3} test_done: - // Compare r3 and r2 - cmp r3, r2 - // Loop if not zero - bcc.n write_word + // compare r1 and r2 + cmp r1, r2 + // loop if not equal + bne write_word // Set breakpoint to exit bkpt #0x00 diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c index 0b39233..63dc961 100644 --- a/src/flash/nor/stm32lx.c +++ b/src/flash/nor/stm32lx.c @@ -450,19 +450,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff /* see contib/loaders/flash/stm32lx.S for src */ static const uint8_t stm32lx_flash_write_code[] = { - /* write_word: */ - 0x00, 0x23, /* movs r3, #0 */ - 0x04, 0xe0, /* b test_done */ - - /* write_word: */ - 0x51, 0xf8, 0x04, 0xcb, /* ldr ip, [r1], #4 */ - 0x40, 0xf8, 0x04, 0xcb, /* str ip, [r0], #4 */ - 0x01, 0x33, /* adds r3, #1 */ - - /* test_done: */ - 0x93, 0x42, /* cmp r3, r2 */ - 0xf8, 0xd3, /* bcc write_word */ - 0x00, 0xbe, /* bkpt 0 */ + 0x92, 0x00, 0x8A, 0x18, 0x01, 0xE0, 0x08, 0xC9, 0x08, 0xC0, 0x91, 0x42, 0xFB, 0xD1, 0x00, 0xBE }; /* Make sure we're performing a half-page aligned write. */ @@ -588,7 +576,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff * is reduced by 50% using this slower method. */ - LOG_WARNING("couldn't use loader, falling back to page memory writes"); + LOG_WARNING("Couldn't use loader, falling back to page memory writes"); while (count > 0) { uint32_t this_count; -- cgit v1.1 From e916bcda6435a60acaec30ce2edf9f3341c01c67 Mon Sep 17 00:00:00 2001 From: CezaryGapinski Date: Mon, 20 Mar 2017 12:33:05 +0100 Subject: stm32lx: fix dual-bank configuration for Cat.5 and Cat.6 devices MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Default values for .first_bank_size_kb and .has_dual_banks fields described in stm32lx_parts[] do not fully describe the real device memory layouts. Basing on: STM32L0x1 RM0377 STM32L0x2 RM0376 STM32L0x3 RM0367 STM32Lxxxx RM0038 correct values for memory layouts were selected: id = 0x447 STM32L0xx (Cat.5) <- dual bank flash for size 192 or 128 KBytes, single bank for 64 KBytes id = 0x436 STM32L1xx (Cat.4 / Cat.3 - Medium + / High Density) <- only one size of the bank, default values are correct id = 0x437 STM32L1xx (Cat.5 / Cat.6) <- always dual bank, but size of the bank can be different For that reason .part_info field in struct stm32lx_flash_bank is a dynamic field with fields copied from stm32lx_parts[] and overwriten to correct values for specific chips and memory sizes. Change-Id: If638cb0a9916097bfd4eda77d64feaf1ef2d2147 Signed-off-by: Cezary Gapiński Reviewed-on: http://openocd.zylin.com/4074 Tested-by: jenkins Reviewed-by: Andreas Fritiofson --- src/flash/nor/stm32lx.c | 119 ++++++++++++++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 50 deletions(-) diff --git a/src/flash/nor/stm32lx.c b/src/flash/nor/stm32lx.c index 63dc961..e4f499d 100644 --- a/src/flash/nor/stm32lx.c +++ b/src/flash/nor/stm32lx.c @@ -105,6 +105,7 @@ static int stm32lx_lock(struct flash_bank *bank); static int stm32lx_unlock(struct flash_bank *bank); static int stm32lx_mass_erase(struct flash_bank *bank); static int stm32lx_wait_until_bsy_clear_timeout(struct flash_bank *bank, int timeout); +static int stm32lx_update_part_info(struct flash_bank *bank, uint16_t flash_size_in_kb); struct stm32lx_rev { uint16_t rev; @@ -132,7 +133,7 @@ struct stm32lx_flash_bank { uint32_t user_bank_size; uint32_t flash_base; - const struct stm32lx_part_info *part_info; + struct stm32lx_part_info part_info; }; static const struct stm32lx_rev stm32_416_revs[] = { @@ -245,7 +246,7 @@ static const struct stm32lx_part_info stm32lx_parts[] = { .page_size = 256, .pages_per_sector = 16, .max_flash_size_kb = 512, - .first_bank_size_kb = 256, + .first_bank_size_kb = 0, /* determined in runtime */ .has_dual_banks = true, .flash_base = 0x40023C00, .fsize_base = 0x1FF800CC, @@ -258,8 +259,8 @@ static const struct stm32lx_part_info stm32lx_parts[] = { .page_size = 128, .pages_per_sector = 32, .max_flash_size_kb = 192, - .first_bank_size_kb = 128, - .has_dual_banks = true, + .first_bank_size_kb = 0, /* determined in runtime */ + .has_dual_banks = false, /* determined in runtime */ .flash_base = 0x40022000, .fsize_base = 0x1FF8007C, }, @@ -436,7 +437,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; - uint32_t hp_nb = stm32lx_info->part_info->page_size / 2; + uint32_t hp_nb = stm32lx_info->part_info.page_size / 2; uint32_t buffer_size = 16384; struct working_area *write_algorithm; struct working_area *source; @@ -483,7 +484,7 @@ static int stm32lx_write_half_pages(struct flash_bank *bank, const uint8_t *buff else buffer_size /= 2; - if (buffer_size <= stm32lx_info->part_info->page_size) { + if (buffer_size <= stm32lx_info->part_info.page_size) { /* we already allocated the writing code, but failed to get a * buffer, free the algorithm */ target_free_working_area(target, write_algorithm); @@ -617,7 +618,7 @@ static int stm32lx_write(struct flash_bank *bank, const uint8_t *buffer, struct target *target = bank->target; struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; - uint32_t hp_nb = stm32lx_info->part_info->page_size / 2; + uint32_t hp_nb = stm32lx_info->part_info.page_size / 2; uint32_t halfpages_number; uint32_t bytes_remaining = 0; uint32_t address = bank->base + offset; @@ -747,9 +748,9 @@ static int stm32lx_probe(struct flash_bank *bank) uint32_t device_id; uint32_t base_address = FLASH_BANK0_ADDRESS; uint32_t second_bank_base; + unsigned int n; stm32lx_info->probed = 0; - stm32lx_info->part_info = NULL; int retval = stm32lx_read_id_code(bank->target, &device_id); if (retval != ERROR_OK) @@ -759,22 +760,24 @@ static int stm32lx_probe(struct flash_bank *bank) LOG_DEBUG("device id = 0x%08" PRIx32 "", device_id); - for (unsigned int n = 0; n < ARRAY_SIZE(stm32lx_parts); n++) { - if ((device_id & 0xfff) == stm32lx_parts[n].id) - stm32lx_info->part_info = &stm32lx_parts[n]; + for (n = 0; n < ARRAY_SIZE(stm32lx_parts); n++) { + if ((device_id & 0xfff) == stm32lx_parts[n].id) { + stm32lx_info->part_info = stm32lx_parts[n]; + break; + } } - if (!stm32lx_info->part_info) { + if (n == ARRAY_SIZE(stm32lx_parts)) { LOG_WARNING("Cannot identify target as a STM32L family."); return ERROR_FAIL; } else { - LOG_INFO("Device: %s", stm32lx_info->part_info->device_str); + LOG_INFO("Device: %s", stm32lx_info->part_info.device_str); } - stm32lx_info->flash_base = stm32lx_info->part_info->flash_base; + stm32lx_info->flash_base = stm32lx_info->part_info.flash_base; /* Get the flash size from target. */ - retval = target_read_u16(target, stm32lx_info->part_info->fsize_base, + retval = target_read_u16(target, stm32lx_info->part_info.fsize_base, &flash_size_in_kb); /* 0x436 devices report their flash size as a 0 or 1 code indicating 384K @@ -791,29 +794,34 @@ static int stm32lx_probe(struct flash_bank *bank) * default to max target family */ if (retval != ERROR_OK || flash_size_in_kb == 0xffff || flash_size_in_kb == 0) { LOG_WARNING("STM32L flash size failed, probe inaccurate - assuming %dk flash", - stm32lx_info->part_info->max_flash_size_kb); - flash_size_in_kb = stm32lx_info->part_info->max_flash_size_kb; - } else if (flash_size_in_kb > stm32lx_info->part_info->max_flash_size_kb) { + stm32lx_info->part_info.max_flash_size_kb); + flash_size_in_kb = stm32lx_info->part_info.max_flash_size_kb; + } else if (flash_size_in_kb > stm32lx_info->part_info.max_flash_size_kb) { LOG_WARNING("STM32L probed flash size assumed incorrect since FLASH_SIZE=%dk > %dk, - assuming %dk flash", - flash_size_in_kb, stm32lx_info->part_info->max_flash_size_kb, - stm32lx_info->part_info->max_flash_size_kb); - flash_size_in_kb = stm32lx_info->part_info->max_flash_size_kb; + flash_size_in_kb, stm32lx_info->part_info.max_flash_size_kb, + stm32lx_info->part_info.max_flash_size_kb); + flash_size_in_kb = stm32lx_info->part_info.max_flash_size_kb; } - if (stm32lx_info->part_info->has_dual_banks) { + /* Overwrite default dual-bank configuration */ + retval = stm32lx_update_part_info(bank, flash_size_in_kb); + if (retval != ERROR_OK) + return ERROR_FAIL; + + if (stm32lx_info->part_info.has_dual_banks) { /* Use the configured base address to determine if this is the first or second flash bank. * Verify that the base address is reasonably correct and determine the flash bank size */ second_bank_base = base_address + - stm32lx_info->part_info->first_bank_size_kb * 1024; + stm32lx_info->part_info.first_bank_size_kb * 1024; if (bank->base == second_bank_base || !bank->base) { /* This is the second bank */ base_address = second_bank_base; flash_size_in_kb = flash_size_in_kb - - stm32lx_info->part_info->first_bank_size_kb; + stm32lx_info->part_info.first_bank_size_kb; } else if (bank->base == base_address) { /* This is the first bank */ - flash_size_in_kb = stm32lx_info->part_info->first_bank_size_kb; + flash_size_in_kb = stm32lx_info->part_info.first_bank_size_kb; } else { LOG_WARNING("STM32L flash bank base address config is incorrect." " 0x%" PRIx32 " but should rather be 0x%" PRIx32 " or 0x%" PRIx32, @@ -876,6 +884,9 @@ static int stm32lx_auto_probe(struct flash_bank *bank) static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size) { struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; + const struct stm32lx_part_info *info = &stm32lx_info->part_info; + uint16_t rev_id = stm32lx_info->idcode >> 16; + const char *rev_str = NULL; if (!stm32lx_info->probed) { int retval = stm32lx_probe(bank); @@ -886,32 +897,21 @@ static int stm32lx_get_info(struct flash_bank *bank, char *buf, int buf_size) } } - const struct stm32lx_part_info *info = stm32lx_info->part_info; - - if (info) { - const char *rev_str = NULL; - uint16_t rev_id = stm32lx_info->idcode >> 16; + for (unsigned int i = 0; i < info->num_revs; i++) + if (rev_id == info->revs[i].rev) + rev_str = info->revs[i].str; - for (unsigned int i = 0; i < info->num_revs; i++) - if (rev_id == info->revs[i].rev) - rev_str = info->revs[i].str; - - if (rev_str != NULL) { - snprintf(buf, buf_size, - "%s - Rev: %s", - stm32lx_info->part_info->device_str, rev_str); - } else { - snprintf(buf, buf_size, - "%s - Rev: unknown (0x%04x)", - stm32lx_info->part_info->device_str, rev_id); - } - - return ERROR_OK; + if (rev_str != NULL) { + snprintf(buf, buf_size, + "%s - Rev: %s", + info->device_str, rev_str); } else { - snprintf(buf, buf_size, "Cannot identify target as a STM32Lx"); - - return ERROR_FAIL; + snprintf(buf, buf_size, + "%s - Rev: unknown (0x%04x)", + info->device_str, rev_id); } + + return ERROR_OK; } static const struct command_registration stm32lx_exec_command_handlers[] = { @@ -1120,7 +1120,7 @@ static int stm32lx_erase_sector(struct flash_bank *bank, int sector) if (retval != ERROR_OK) return retval; - for (int page = 0; page < (int)stm32lx_info->part_info->pages_per_sector; + for (int page = 0; page < (int)stm32lx_info->part_info.pages_per_sector; page++) { reg32 = FLASH_PECR__PROG | FLASH_PECR__ERASE; retval = target_write_u32(target, @@ -1133,7 +1133,7 @@ static int stm32lx_erase_sector(struct flash_bank *bank, int sector) return retval; uint32_t addr = bank->base + bank->sectors[sector].offset + (page - * stm32lx_info->part_info->page_size); + * stm32lx_info->part_info.page_size); retval = target_write_u32(target, addr, 0x0); if (retval != ERROR_OK) return retval; @@ -1357,3 +1357,22 @@ static int stm32lx_mass_erase(struct flash_bank *bank) return ERROR_OK; } + +static int stm32lx_update_part_info(struct flash_bank *bank, uint16_t flash_size_in_kb) +{ + struct stm32lx_flash_bank *stm32lx_info = bank->driver_priv; + + switch (stm32lx_info->part_info.id) { + case 0x447: /* STM32L0xx (Cat.5) devices */ + if (flash_size_in_kb == 192 || flash_size_in_kb == 128) { + stm32lx_info->part_info.first_bank_size_kb = flash_size_in_kb / 2; + stm32lx_info->part_info.has_dual_banks = true; + } + break; + case 0x437: /* STM32L1xx (Cat.5/Cat.6) */ + stm32lx_info->part_info.first_bank_size_kb = flash_size_in_kb / 2; + break; + } + + return ERROR_OK; +} -- cgit v1.1 From b375052c58a4ef9b855ce9aa119cc1abf432d0c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20=C4=8Capek?= Date: Wed, 25 Jan 2017 10:11:48 +0100 Subject: tcl STM32L0xx - add support for dual banked targets and for Nucleo-64 STM32L073 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - stm32l0_dual_bank.cfg - implement dual bank configuration - st_nucleo_l073rz.cfg - implement new board script Change-Id: Ie8063e5bec45069a63d414d81b2068fe3cc7e4d7 Signed-off-by: Jan Čapek Reviewed-on: http://openocd.zylin.com/3957 Reviewed-by: Cezary Gapiński Reviewed-by: Karl Palsson Tested-by: jenkins Reviewed-by: Aurelio Lucchesi Reviewed-by: Freddie Chopin --- tcl/board/st_nucleo_l073rz.cfg | 12 ++++++++++++ tcl/target/stm32l0_dual_bank.cfg | 5 +++++ 2 files changed, 17 insertions(+) create mode 100644 tcl/board/st_nucleo_l073rz.cfg create mode 100644 tcl/target/stm32l0_dual_bank.cfg diff --git a/tcl/board/st_nucleo_l073rz.cfg b/tcl/board/st_nucleo_l073rz.cfg new file mode 100644 index 0000000..fa9dc87 --- /dev/null +++ b/tcl/board/st_nucleo_l073rz.cfg @@ -0,0 +1,12 @@ +# This is an ST NUCLEO-L073RZ board with single STM32L073RZ chip. +# http://www.st.com/en/evaluation-tools/nucleo-l073rz.html +source [find interface/stlink-v2-1.cfg] + +transport select hla_swd + +set WORKAREASIZE 0x2000 + +source [find target/stm32l0_dual_bank.cfg] + +# There is only system reset line and JTAG/SWD command can be issued when SRST +reset_config srst_only diff --git a/tcl/target/stm32l0_dual_bank.cfg b/tcl/target/stm32l0_dual_bank.cfg new file mode 100644 index 0000000..f9f1a4e --- /dev/null +++ b/tcl/target/stm32l0_dual_bank.cfg @@ -0,0 +1,5 @@ +source [find target/stm32l0.cfg] + +# Add the second flash bank. +set _FLASHNAME $_CHIPNAME.flash1 +flash bank $_FLASHNAME stm32lx 0 0 0 0 $_TARGETNAME -- cgit v1.1 From 790a7b2a8d22e04d9447d35d3bbb8684a11446a3 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Tue, 16 Aug 2016 09:39:36 +0200 Subject: flash/nor/tcl: Fix some format specifiers Change-Id: I2255aede9713cb7ef538d7433dd900d8da7a51ad Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3857 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/flash/nor/tcl.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 0b72a12..3619e2f 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -297,8 +297,8 @@ static int flash_check_sector_parameters(struct command_context *cmd_ctx, } if (!(last <= (num_sectors - 1))) { - command_print(cmd_ctx, "ERROR: last sector must be <= %d", - (int) num_sectors - 1); + command_print(cmd_ctx, "ERROR: last sector must be <= %" PRIu32, + num_sectors - 1); return ERROR_FAIL; } @@ -380,10 +380,9 @@ COMMAND_HANDLER(handle_flash_protect_command) retval = flash_driver_protect(p, set, first, last); if (retval == ERROR_OK) { - command_print(CMD_CTX, "%s protection for sectors %i " - "through %i on flash bank %d", - (set) ? "set" : "cleared", (int) first, - (int) last, p->bank_number); + command_print(CMD_CTX, "%s protection for sectors %" PRIu32 + " through %" PRIu32 " on flash bank %d", + (set) ? "set" : "cleared", first, last, p->bank_number); } return retval; @@ -690,9 +689,9 @@ COMMAND_HANDLER(handle_flash_read_bank_command) } if (duration_measure(&bench) == ERROR_OK) - command_print(CMD_CTX, "wrote %ld bytes to file %s from flash bank %u" + command_print(CMD_CTX, "wrote %zd bytes to file %s from flash bank %u" " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", - (long)written, CMD_ARGV[1], p->bank_number, offset, + written, CMD_ARGV[1], p->bank_number, offset, duration_elapsed(&bench), duration_kbps(&bench, written)); return retval; @@ -770,9 +769,9 @@ COMMAND_HANDLER(handle_flash_verify_bank_command) } if (duration_measure(&bench) == ERROR_OK) - command_print(CMD_CTX, "read %ld bytes from file %s and flash bank %u" + command_print(CMD_CTX, "read %zd bytes from file %s and flash bank %u" " at offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)", - (long)read_cnt, CMD_ARGV[1], p->bank_number, offset, + read_cnt, CMD_ARGV[1], p->bank_number, offset, duration_elapsed(&bench), duration_kbps(&bench, read_cnt)); differ = memcmp(buffer_file, buffer_flash, read_cnt); -- cgit v1.1 From 45f0e6d0626e4541158198c271519175ae79f5b5 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 4 Nov 2016 08:09:56 +0100 Subject: flash/nor/tcl: Make verify_bank parameter optional Make the 'offset' parameter optional, if omitted simply start at the beginning of the flash bank. Additionally, check if the argument is out of bounds of the flash bank. Change-Id: Id1959eee5c395666c35f26342c3c50134dd564e5 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3858 Tested-by: jenkins Reviewed-by: Tomas Vanek --- doc/openocd.texi | 5 +++-- src/flash/nor/tcl.c | 21 +++++++++++++++------ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/doc/openocd.texi b/doc/openocd.texi index c3053b7..a60474b 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4656,9 +4656,10 @@ and write the contents to the binary @file{filename}. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn -@deffn Command {flash verify_bank} num filename offset +@deffn Command {flash verify_bank} num filename [offset] Compare the contents of the binary file @var{filename} with the contents of the -flash @var{num} starting at @var{offset}. Fails if the contents do not match. +flash bank @var{num} starting at @var{offset}. If @var{offset} is omitted, +start at the beginning of the flash bank. Fail if the contents do not match. The @var{num} parameter is a value shown by @command{flash banks}. @end deffn diff --git a/src/flash/nor/tcl.c b/src/flash/nor/tcl.c index 3619e2f..b93d126 100644 --- a/src/flash/nor/tcl.c +++ b/src/flash/nor/tcl.c @@ -707,7 +707,7 @@ COMMAND_HANDLER(handle_flash_verify_bank_command) size_t filesize; int differ; - if (CMD_ARGC != 3) + if (CMD_ARGC < 2 || CMD_ARGC > 3) return ERROR_COMMAND_SYNTAX_ERROR; struct duration bench; @@ -718,7 +718,16 @@ COMMAND_HANDLER(handle_flash_verify_bank_command) if (ERROR_OK != retval) return retval; - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); + offset = 0; + + if (CMD_ARGC > 2) + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[2], offset); + + if (offset > p->size) { + LOG_ERROR("Offset 0x%8.8" PRIx32 " is out of range of the flash bank", + offset); + return ERROR_COMMAND_ARGUMENT_INVALID; + } retval = fileio_open(&fileio, CMD_ARGV[1], FILEIO_READ, FILEIO_BINARY); if (retval != ERROR_OK) { @@ -926,10 +935,10 @@ static const struct command_registration flash_exec_command_handlers[] = { .name = "verify_bank", .handler = handle_flash_verify_bank_command, .mode = COMMAND_EXEC, - .usage = "bank_id filename offset", - .help = "Read binary data from flash bank and file, " - "starting at specified byte offset from the " - "beginning of the bank. Compare the contents.", + .usage = "bank_id filename [offset]", + .help = "Compare the contents of a file with the contents of the " + "flash bank. Allow optional offset from beginning of the bank " + "(defaults to zero).", }, { .name = "protect", -- cgit v1.1 From 8f3d16f4ae828345c7cf7cd782db32dfc560bdd6 Mon Sep 17 00:00:00 2001 From: Hellosun Wu Date: Tue, 26 Jan 2016 13:36:49 +0800 Subject: libusb: Add transfer type filter to get correct ep The need for this due to AICE having 3 interfaces (EP1 IN-Interrupt, EP2 OUT-Bulk, EP6 IN-Bulk). Without it, the function will choose first two endpoint as read_ep/write_ep. This filter will check transfer types when get endpoint-id. Without this patch, AICE will not get correct endpoint. Change-Id: I4da93c7de41cd19e5095b4bfb42078b21f40b678 Signed-off-by: Hellosun Wu Reviewed-on: http://openocd.zylin.com/3218 Tested-by: jenkins Reviewed-by: Hsiangkai Wang Reviewed-by: Freddie Chopin --- src/jtag/aice/aice_usb.c | 8 +++++++- src/jtag/drivers/libusb0_common.c | 5 +++-- src/jtag/drivers/libusb0_common.h | 2 +- src/jtag/drivers/libusb1_common.c | 4 +++- src/jtag/drivers/libusb1_common.h | 3 ++- src/jtag/drivers/openjtag.c | 2 +- 6 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/jtag/aice/aice_usb.c b/src/jtag/aice/aice_usb.c index b36e390..50468f3 100644 --- a/src/jtag/aice/aice_usb.c +++ b/src/jtag/aice/aice_usb.c @@ -2135,10 +2135,16 @@ static int aice_usb_open(struct aice_port_param_s *param) /* usb_set_configuration required under win32 */ jtag_libusb_set_configuration(devh, 0); + jtag_libusb_claim_interface(devh, 0); unsigned int aice_read_ep; unsigned int aice_write_ep; - jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1); +#ifdef HAVE_LIBUSB1 + jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1, LIBUSB_TRANSFER_TYPE_BULK); +#else + jtag_libusb_choose_interface(devh, &aice_read_ep, &aice_write_ep, -1, -1, -1, USB_ENDPOINT_TYPE_BULK); +#endif + LOG_DEBUG("aice_read_ep=0x%x, aice_write_ep=0x%x", aice_read_ep, aice_write_ep); aice_handler.usb_read_ep = aice_read_ep; aice_handler.usb_write_ep = aice_write_ep; diff --git a/src/jtag/drivers/libusb0_common.c b/src/jtag/drivers/libusb0_common.c index e319751..1825543 100644 --- a/src/jtag/drivers/libusb0_common.c +++ b/src/jtag/drivers/libusb0_common.c @@ -146,7 +146,7 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, - int bclass, int subclass, int protocol) + int bclass, int subclass, int protocol, int trans_type) { struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); struct usb_interface *iface = udev->config->interface; @@ -157,7 +157,8 @@ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, for (int i = 0; i < desc->bNumEndpoints; i++) { if ((bclass > 0 && desc->bInterfaceClass != bclass) || (subclass > 0 && desc->bInterfaceSubClass != subclass) || - (protocol > 0 && desc->bInterfaceProtocol != protocol)) + (protocol > 0 && desc->bInterfaceProtocol != protocol) || + (trans_type > 0 && (desc->endpoint[i].bmAttributes & 0x3) != trans_type)) continue; uint8_t epnum = desc->endpoint[i].bEndpointAddress; diff --git a/src/jtag/drivers/libusb0_common.h b/src/jtag/drivers/libusb0_common.h index 7163b43..baa9e3c 100644 --- a/src/jtag/drivers/libusb0_common.h +++ b/src/jtag/drivers/libusb0_common.h @@ -67,7 +67,7 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, - int bclass, int subclass, int protocol); + int bclass, int subclass, int protocol, int trans_type); int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid); #endif /* OPENOCD_JTAG_DRIVERS_LIBUSB0_COMMON_H */ diff --git a/src/jtag/drivers/libusb1_common.c b/src/jtag/drivers/libusb1_common.c index f8b7c75..89f8092 100644 --- a/src/jtag/drivers/libusb1_common.c +++ b/src/jtag/drivers/libusb1_common.c @@ -187,7 +187,7 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, - int bclass, int subclass, int protocol) + int bclass, int subclass, int protocol, int trans_type) { struct jtag_libusb_device *udev = jtag_libusb_get_device(devh); const struct libusb_interface *inter; @@ -210,6 +210,8 @@ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, continue; epdesc = &interdesc->endpoint[k]; + if (trans_type > 0 && (epdesc->bmAttributes & 0x3) != trans_type) + continue; uint8_t epnum = epdesc->bEndpointAddress; bool is_input = epnum & 0x80; diff --git a/src/jtag/drivers/libusb1_common.h b/src/jtag/drivers/libusb1_common.h index fc6526a..7c73d29 100644 --- a/src/jtag/drivers/libusb1_common.h +++ b/src/jtag/drivers/libusb1_common.h @@ -69,12 +69,13 @@ int jtag_libusb_set_configuration(jtag_libusb_device_handle *devh, * @param bclass `bInterfaceClass` to match, or -1 to ignore this field. * @param subclass `bInterfaceSubClass` to match, or -1 to ignore this field. * @param protocol `bInterfaceProtocol` to match, or -1 to ignore this field. + * @param trans_type `bmAttributes Bits 0..1 Transfer type` to match, or -1 to ignore this field. * @returns Returns ERROR_OK on success, ERROR_FAIL otherwise. */ int jtag_libusb_choose_interface(struct jtag_libusb_device_handle *devh, unsigned int *usb_read_ep, unsigned int *usb_write_ep, - int bclass, int subclass, int protocol); + int bclass, int subclass, int protocol, int trans_type); int jtag_libusb_get_pid(struct jtag_libusb_device *dev, uint16_t *pid); #endif /* OPENOCD_JTAG_DRIVERS_LIBUSB1_COMMON_H */ diff --git a/src/jtag/drivers/openjtag.c b/src/jtag/drivers/openjtag.c index bb0ff74..8f11b4b 100644 --- a/src/jtag/drivers/openjtag.c +++ b/src/jtag/drivers/openjtag.c @@ -459,7 +459,7 @@ static int openjtag_init_cy7c65215(void) ret = jtag_libusb_choose_interface(usbh, &ep_in, &ep_out, CY7C65215_JTAG_CLASS, - CY7C65215_JTAG_SUBCLASS, -1); + CY7C65215_JTAG_SUBCLASS, -1, LIBUSB_TRANSFER_TYPE_BULK); if (ret != ERROR_OK) { LOG_ERROR("unable to claim JTAG interface"); goto err; -- cgit v1.1 From e683ff2ac7d02966cd2f49df58d9d7425298ac44 Mon Sep 17 00:00:00 2001 From: Byron Kubert Date: Mon, 26 Sep 2016 15:05:52 -0600 Subject: Added 512K flashing support for em3587 The Silicon Labs EM3587 and EM3588 may have 512K of flash. This fix allows for 512K to be specifiied on the command line when flashing a device. Change-Id: I18cc4bd0d14e1f2069066734a7396bcccf3de941 Signed-off-by: Byron Kubert Reviewed-on: http://openocd.zylin.com/3795 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/flash/nor/em357.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/flash/nor/em357.c b/src/flash/nor/em357.c index 1501562..a11743b 100644 --- a/src/flash/nor/em357.c +++ b/src/flash/nor/em357.c @@ -702,6 +702,11 @@ static int em357_probe(struct flash_bank *bank) num_pages = 128; page_size = 2048; break; + case 0x80000: + /* 512k -- 256 2k pages */ + num_pages = 256; + page_size = 2048; + break; default: LOG_WARNING("No size specified for em357 flash driver, assuming 192k!"); num_pages = 96; -- cgit v1.1 From 68e204f1e91a2756168825a30651805ceae22b77 Mon Sep 17 00:00:00 2001 From: Karl Palsson Date: Fri, 17 Feb 2017 10:38:26 +0000 Subject: udev: Add rules for Ambiq Micro EVK's. Udev rules for Ambiq Micro ftdi based EVK's. Two new vid:pid's: 2AEC:6010, and 2AEC:6011. Udev rule for multi-target Debug board 2AEC:1106 Change-Id: Id7430d0c70647752375230f4024be9f7a2ba95ce Signed-off-by: Rick Foos Signed-off-by: Karl Palsson Reviewed-on: http://openocd.zylin.com/3980 Tested-by: jenkins Reviewed-by: Freddie Chopin --- contrib/60-openocd.rules | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules index 3da1f73..3597c95 100644 --- a/contrib/60-openocd.rules +++ b/contrib/60-openocd.rules @@ -122,6 +122,11 @@ ATTRS{idVendor}=="1781", ATTRS{idProduct}=="0c63", MODE="660", GROUP="plugdev", # TI/Luminary Stellaris In-Circuit Debug Interface (ICDI) Board ATTRS{idVendor}=="1cbe", ATTRS{idProduct}=="00fd", MODE="660", GROUP="plugdev", TAG+="uaccess" +# Ambiq Micro EVK and Debug boards. +ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="6010", MODE="664", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="6011", MODE="664", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="2aec", ATTRS{idProduct}=="1106", MODE="664", GROUP="plugdev", TAG+="uaccess" + # Marvell Sheevaplug ATTRS{idVendor}=="9e88", ATTRS{idProduct}=="9e8f", MODE="660", GROUP="plugdev", TAG+="uaccess" -- cgit v1.1 From 3fe99295117bbd0702aebe2fbd26b641a8ffbf72 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Thu, 26 May 2016 16:02:27 +0200 Subject: tcl/board: Add STMicroelectronics STM32F7 Nucleo config Tested with STM32F746ZG Nucleo development board. Change-Id: Ia97b774b996a3be03e8e84342b93659c3632c18f Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3516 Tested-by: jenkins Reviewed-by: Freddie Chopin --- tcl/board/st_nucleo_f7.cfg | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tcl/board/st_nucleo_f7.cfg diff --git a/tcl/board/st_nucleo_f7.cfg b/tcl/board/st_nucleo_f7.cfg new file mode 100644 index 0000000..88a8a30 --- /dev/null +++ b/tcl/board/st_nucleo_f7.cfg @@ -0,0 +1,10 @@ +# STMicroelectronics STM32F7 Nucleo development board +# Known boards: NUCLEO-F746ZG and NUCLEO-F767ZI + +source [find interface/stlink-v2-1.cfg] + +transport select hla_swd + +source [find target/stm32f7x.cfg] + +reset_config srst_only -- cgit v1.1 From 832f5974f2b408a051b0f673ca64453deb960185 Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Mon, 20 Feb 2017 22:19:15 +0100 Subject: mips32, pic32 use uint8_t in 8 bit scan function Makes code shorter. Change-Id: I6cc01adffbea063ccb071ddf3a3e3d81727b29ce Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4004 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/flash/nor/pic32mx.c | 3 +-- src/target/mips_ejtag.c | 21 +++++++-------------- src/target/mips_ejtag.h | 2 +- 3 files changed, 9 insertions(+), 17 deletions(-) diff --git a/src/flash/nor/pic32mx.c b/src/flash/nor/pic32mx.c index de212ed..1f148fd 100644 --- a/src/flash/nor/pic32mx.c +++ b/src/flash/nor/pic32mx.c @@ -879,7 +879,6 @@ COMMAND_HANDLER(pic32mx_handle_pgm_word_command) COMMAND_HANDLER(pic32mx_handle_unlock_command) { - uint32_t mchip_cmd; struct target *target = NULL; struct mips_m4k_common *mips_m4k; struct mips_ejtag *ejtag_info; @@ -904,7 +903,7 @@ COMMAND_HANDLER(pic32mx_handle_unlock_command) mips_ejtag_set_instr(ejtag_info, MTAP_COMMAND); /* first check status of device */ - mchip_cmd = MCHP_STATUS; + uint8_t mchip_cmd = MCHP_STATUS; mips_ejtag_drscan_8(ejtag_info, &mchip_cmd); if (mchip_cmd & (1 << 7)) { /* device is not locked */ diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index 594711f..650af3e 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -169,31 +169,24 @@ void mips_ejtag_drscan_32_out(struct mips_ejtag *ejtag_info, uint32_t data) jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); } -int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint32_t *data) +int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint8_t *data) { - struct jtag_tap *tap; - tap = ejtag_info->tap; - assert(tap != NULL); + assert(ejtag_info->tap != NULL); + struct jtag_tap *tap = ejtag_info->tap; struct scan_field field; - uint8_t t[4] = {0, 0, 0, 0}, r[4]; - int retval; - field.num_bits = 8; - field.out_value = t; - buf_set_u32(t, 0, field.num_bits, *data); - field.in_value = r; + + field.out_value = data; + field.in_value = data; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); - retval = jtag_execute_queue(); + int retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("register read failed"); return retval; } - - *data = buf_get_u32(field.in_value, 0, 32); - return ERROR_OK; } diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index 6ef0867..2178afc 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -220,7 +220,7 @@ void mips_ejtag_add_scan_96(struct mips_ejtag *ejtag_info, void mips_ejtag_drscan_32_out(struct mips_ejtag *ejtag_info, uint32_t data); int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data); void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data); -int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint32_t *data); +int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint8_t *data); int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_t *data); int mips_ejtag_init(struct mips_ejtag *ejtag_info); -- cgit v1.1 From d81fc78d9bf6891251cb44eff9e70bd8781a2def Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Mon, 20 Feb 2017 23:05:38 +0100 Subject: mips32, add generic scan 32 function Will be used later, allow queuing all needed scans in a pracc access. This makes faster execution with ftdi based adapters working in sync with pracc. Added now because the overall code is shorter. Change-Id: Ib32b89307b75785f88870db8d7c9255dc5bbd426 Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4005 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips_ejtag.c | 48 +++++++++++++++++++----------------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index 650af3e..ebf0d73 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -121,52 +121,42 @@ void mips_ejtag_add_scan_96(struct mips_ejtag *ejtag_info, uint32_t ctrl, uint32 keep_alive(); } -int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data) +void mips_ejtag_drscan_32_queued(struct mips_ejtag *ejtag_info, uint32_t data_out, uint8_t *data_in) { - struct jtag_tap *tap; - tap = ejtag_info->tap; - assert(tap != NULL); + assert(ejtag_info->tap != NULL); + struct jtag_tap *tap = ejtag_info->tap; struct scan_field field; - uint8_t t[4], r[4]; - int retval; - field.num_bits = 32; - field.out_value = t; - buf_set_u32(t, 0, field.num_bits, *data); - field.in_value = r; + uint8_t scan_out[4]; + field.out_value = scan_out; + buf_set_u32(scan_out, 0, field.num_bits, data_out); + + field.in_value = data_in; jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); - retval = jtag_execute_queue(); + keep_alive(); +} + +int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data) +{ + uint8_t scan_in[4]; + mips_ejtag_drscan_32_queued(ejtag_info, *data, scan_in); + + int retval = jtag_execute_queue(); if (retval != ERROR_OK) { LOG_ERROR("register read failed"); return retval; } - *data = buf_get_u32(field.in_value, 0, 32); - - keep_alive(); - + *data = buf_get_u32(scan_in, 0, 32); return ERROR_OK; } void mips_ejtag_drscan_32_out(struct mips_ejtag *ejtag_info, uint32_t data) { - uint8_t t[4]; - struct jtag_tap *tap; - tap = ejtag_info->tap; - assert(tap != NULL); - - struct scan_field field; - - field.num_bits = 32; - field.out_value = t; - buf_set_u32(t, 0, field.num_bits, data); - - field.in_value = NULL; - - jtag_add_dr_scan(tap, 1, &field, TAP_IDLE); + mips_ejtag_drscan_32_queued(ejtag_info, data, NULL); } int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint8_t *data) -- cgit v1.1 From 99db18a995c8ef2913f1397dcc94d0533331e598 Mon Sep 17 00:00:00 2001 From: Juha Niskanen Date: Tue, 25 Apr 2017 09:07:58 +0300 Subject: stm32l4: support flashing L496 devices Change-Id: I3effc5b675c853433170391c5eaf46edc067b6e7 Signed-off-by: Juha Niskanen Reviewed-on: http://openocd.zylin.com/4108 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/flash/nor/stm32l4x.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index 762df74..db68539 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -614,6 +614,7 @@ static int stm32l4_probe(struct flash_bank *bank) /* set max flash size depending on family */ switch (device_id & 0xfff) { + case 0x461: case 0x415: max_flash_size_in_kb = 1024; break; @@ -716,8 +717,12 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size) const char *device_str; switch (device_id) { + case 0x461: + device_str = "STM32L496/4A6"; + break; + case 0x415: - device_str = "STM32L4xx"; + device_str = "STM32L475/476/486"; break; case 0x435: -- cgit v1.1 From b43b95e46022d3baf76b44f7be34bbf0e6119594 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Sun, 24 Jan 2016 20:58:24 +0100 Subject: server/server: Remove all exit() calls With this patch OpenOCD shuts down properly when errors occur in the server instead of just calling exit(). Change-Id: I2ae1a6153dafc88667951cab9152941cb487be85 Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3223 Reviewed-by: Tomas Vanek Tested-by: jenkins --- src/openocd.c | 4 +++- src/server/server.c | 51 ++++++++++++++++++++++++++++++++++------------ src/server/telnet_server.c | 20 ++++++++++-------- 3 files changed, 52 insertions(+), 23 deletions(-) diff --git a/src/openocd.c b/src/openocd.c index 94fab3a..83329b5 100644 --- a/src/openocd.c +++ b/src/openocd.c @@ -297,8 +297,10 @@ static int openocd_thread(int argc, char *argv[], struct command_context *cmd_ct if (init_at_startup) { ret = command_run_line(cmd_ctx, "init"); - if (ERROR_OK != ret) + if (ERROR_OK != ret) { + server_quit(); return ERROR_FAIL; + } } ret = server_loop(cmd_ctx); diff --git a/src/server/server.c b/src/server/server.c index f6889a0..8009d40 100644 --- a/src/server/server.c +++ b/src/server/server.c @@ -132,7 +132,9 @@ static int add_connection(struct service *service, struct command_context *cmd_c free(out_file); if (c->fd_out == -1) { LOG_ERROR("could not open %s", service->port); - exit(1); + command_done(c->cmd_ctx); + free(c); + return ERROR_FAIL; } LOG_INFO("accepting '%s' connection from pipe %s", service->name, service->port); @@ -191,7 +193,13 @@ static int remove_connection(struct service *service, struct connection *connect return ERROR_OK; } -/* FIX! make service return error instead of invoking exit() */ +static void free_service(struct service *c) +{ + free(c->name); + free(c->port); + free(c); +} + int add_service(char *name, const char *port, int max_connections, @@ -235,7 +243,8 @@ int add_service(char *name, c->fd = socket(AF_INET, SOCK_STREAM, 0); if (c->fd == -1) { LOG_ERROR("error creating socket: %s", strerror(errno)); - exit(-1); + free_service(c); + return ERROR_FAIL; } setsockopt(c->fd, @@ -255,7 +264,9 @@ int add_service(char *name, hp = gethostbyname(bindto_name); if (hp == NULL) { LOG_ERROR("couldn't resolve bindto address: %s", bindto_name); - exit(-1); + close_socket(c->fd); + free_service(c); + return ERROR_FAIL; } memcpy(&c->sin.sin_addr, hp->h_addr_list[0], hp->h_length); } @@ -263,7 +274,9 @@ int add_service(char *name, if (bind(c->fd, (struct sockaddr *)&c->sin, sizeof(c->sin)) == -1) { LOG_ERROR("couldn't bind %s to socket: %s", name, strerror(errno)); - exit(-1); + close_socket(c->fd); + free_service(c); + return ERROR_FAIL; } #ifndef _WIN32 @@ -281,7 +294,9 @@ int add_service(char *name, if (listen(c->fd, 1) == -1) { LOG_ERROR("couldn't listen on socket: %s", strerror(errno)); - exit(-1); + close_socket(c->fd); + free_service(c); + return ERROR_FAIL; } } else if (c->type == CONNECTION_STDINOUT) { c->fd = fileno(stdin); @@ -302,13 +317,15 @@ int add_service(char *name, /* we currenty do not support named pipes under win32 * so exit openocd for now */ LOG_ERROR("Named pipes currently not supported under this os"); - exit(1); + free_service(c); + return ERROR_FAIL; #else /* Pipe we're reading from */ c->fd = open(c->port, O_RDONLY | O_NONBLOCK); if (c->fd == -1) { LOG_ERROR("could not open %s", c->port); - exit(1); + free_service(c); + return ERROR_FAIL; } #endif } @@ -425,7 +442,7 @@ int server_loop(struct command_context *command_context) FD_ZERO(&read_fds); else { LOG_ERROR("error during select: %s", strerror(errno)); - exit(-1); + return ERROR_FAIL; } #else @@ -433,7 +450,7 @@ int server_loop(struct command_context *command_context) FD_ZERO(&read_fds); else { LOG_ERROR("error during select: %s", strerror(errno)); - exit(-1); + return ERROR_FAIL; } #endif } @@ -552,7 +569,7 @@ int server_preinit(void) if (WSAStartup(wVersionRequested, &wsaData) != 0) { LOG_ERROR("Failed to Open Winsock"); - exit(-1); + return ERROR_FAIL; } /* register ctrl-c handler */ @@ -570,10 +587,18 @@ int server_preinit(void) int server_init(struct command_context *cmd_ctx) { int ret = tcl_init(); - if (ERROR_OK != ret) + + if (ret != ERROR_OK) return ret; - return telnet_init("Open On-Chip Debugger"); + ret = telnet_init("Open On-Chip Debugger"); + + if (ret != ERROR_OK) { + remove_services(); + return ret; + } + + return ERROR_OK; } int server_quit(void) diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index 0f5769a..e5eb4bb 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -624,9 +624,8 @@ int telnet_init(char *banner) return ERROR_OK; } - struct telnet_service *telnet_service; - - telnet_service = malloc(sizeof(struct telnet_service)); + struct telnet_service *telnet_service = + malloc(sizeof(struct telnet_service)); if (!telnet_service) { LOG_ERROR("Failed to allocate telnet service."); @@ -635,13 +634,16 @@ int telnet_init(char *banner) telnet_service->banner = banner; - return add_service("telnet", - telnet_port, - CONNECTION_LIMIT_UNLIMITED, - telnet_new_connection, - telnet_input, - telnet_connection_closed, + int ret = add_service("telnet", telnet_port, CONNECTION_LIMIT_UNLIMITED, + telnet_new_connection, telnet_input, telnet_connection_closed, telnet_service); + + if (ret != ERROR_OK) { + free(telnet_service); + return ret; + } + + return ERROR_OK; } /* daemon configuration command telnet_port */ -- cgit v1.1 From 3421b89c9809cbb39cd4bb030687a5c9fd65ded6 Mon Sep 17 00:00:00 2001 From: Marc Schink Date: Fri, 29 Jan 2016 23:35:40 +0100 Subject: server/telnet: Remove exit() call Change-Id: I8ce99d7d62dfe3cad63cf6bc68f2faf2234e395c Signed-off-by: Marc Schink Reviewed-on: http://openocd.zylin.com/3224 Tested-by: jenkins Reviewed-by: Tomas Vanek Reviewed-by: Freddie Chopin --- src/server/telnet_server.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/server/telnet_server.c b/src/server/telnet_server.c index e5eb4bb..e33188b 100644 --- a/src/server/telnet_server.c +++ b/src/server/telnet_server.c @@ -573,7 +573,7 @@ static int telnet_input(struct connection *connection) break; default: LOG_ERROR("unknown telnet state"); - exit(-1); + return ERROR_FAIL; } bytes_read--; -- cgit v1.1 From 7ccd53bdde3f3a2fbd957f8b75f38125468c199f Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Mon, 20 Feb 2017 23:48:40 +0100 Subject: mips32, homogenize code in the scan functions Change-Id: I32fed3332857737048dd12da94fcaba140acb726 Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4006 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips_ejtag.c | 33 ++++++++++++++++----------------- src/target/mips_ejtag.h | 3 +-- 2 files changed, 17 insertions(+), 19 deletions(-) diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index ebf0d73..1fbdf3c 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -28,20 +28,20 @@ #include "mips_ejtag.h" #include "mips32_dmaacc.h" -void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, int new_instr) +void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, uint32_t new_instr) { - struct jtag_tap *tap; + assert(ejtag_info->tap != NULL); + struct jtag_tap *tap = ejtag_info->tap; - tap = ejtag_info->tap; - assert(tap != NULL); + if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != new_instr) { - if (buf_get_u32(tap->cur_instr, 0, tap->ir_length) != (uint32_t)new_instr) { struct scan_field field; - uint8_t t[4]; - field.num_bits = tap->ir_length; + + uint8_t t[4]; field.out_value = t; buf_set_u32(t, 0, field.num_bits, new_instr); + field.in_value = NULL; jtag_add_ir_scan(tap, &field, TAP_IDLE); @@ -182,13 +182,12 @@ int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint8_t *data) void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data) { - struct jtag_tap *tap; - tap = ejtag_info->tap; - assert(tap != NULL); + assert(ejtag_info->tap != NULL); + struct jtag_tap *tap = ejtag_info->tap; struct scan_field field; - field.num_bits = 8; + field.out_value = &data; field.in_value = NULL; @@ -427,22 +426,22 @@ int mips_ejtag_init(struct mips_ejtag *ejtag_info) int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_t *data) { - struct jtag_tap *tap; - - tap = ejtag_info->tap; - assert(tap != NULL); + assert(ejtag_info->tap != NULL); + struct jtag_tap *tap = ejtag_info->tap; struct scan_field fields[2]; - uint8_t spracc = 0; - uint8_t t[4] = {0, 0, 0, 0}; /* fastdata 1-bit register */ fields[0].num_bits = 1; + + uint8_t spracc = 0; fields[0].out_value = &spracc; fields[0].in_value = NULL; /* processor access data register 32 bit */ fields[1].num_bits = 32; + + uint8_t t[4] = {0, 0, 0, 0}; fields[1].out_value = t; if (write_t) { diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index 2178afc..3043df9 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -210,8 +210,7 @@ struct mips_ejtag { uint32_t ejtag_dba_step_size; /* size of step till next *DBAn register. */ }; -void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, - int new_instr); +void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, uint32_t new_instr); int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info); int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info); int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info, uint32_t *idcode); -- cgit v1.1 From 09ebc1afadcc710e3d0f37bdaba3d76a1487d306 Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Wed, 22 Feb 2017 23:14:36 +0100 Subject: mips32, drop unnecessary code in mips32_pracc.c Struct mips32_pracc_context no more in use. In current code cp0 reg/sel do not requires special handling. In sync mode ctx.store_count not used, drop check. In fasdata transfer function use mips32_pracc_read_ctrl_addr() to reduce code. Change-Id: Ibd4cfa5a44ebc106ed0db042f4e54a2e0b3d43cb Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4007 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips32_pracc.c | 72 ++++++++--------------------------------------- 1 file changed, 12 insertions(+), 60 deletions(-) diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 5456e8c..69d9a00 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -73,16 +73,6 @@ #include "mips32.h" #include "mips32_pracc.h" -struct mips32_pracc_context { - uint32_t *local_oparam; - int num_oparam; - const uint32_t *code; - int code_len; - uint32_t stack[32]; - int stack_offset; - struct mips_ejtag *ejtag_info; -}; - static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl) { uint32_t ejtag_ctrl; @@ -564,10 +554,10 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_r goto exit; pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ - pracc_add(&ctx, 0, MIPS32_MFC0(8, 0, 0) | (cp0_reg << 11) | cp0_sel); /* move COP0 [cp0_reg select] to $8 */ + pracc_add(&ctx, 0, MIPS32_MFC0(8, cp0_reg, cp0_sel)); /* move cp0 reg / sel to $8 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ + pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ @@ -576,23 +566,6 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_r exit: pracc_queue_free(&ctx); return ctx.retval; - - /** - * Note that our input parametes cp0_reg and cp0_sel - * are numbers (not gprs) which make part of mfc0 instruction opcode. - * - * These are not fix, but can be different for each mips32_cp0_read() function call, - * and that is why we must insert them directly into opcode, - * i.e. we can not pass it on EJTAG microprogram stack (via param_in), - * and put them into the gprs later from MIPS32_PRACC_STACK - * because mfc0 do not use gpr as a parameter for the cp0_reg and select part, - * but plain (immediate) number. - * - * MIPS32_MTC0 is implemented via MIPS32_R_INST macro. - * In order to insert our parameters, we must change rd and funct fields. - * - * code[2] |= (cp0_reg << 11) | cp0_sel; change rd and funct of MIPS32_R_INST macro - **/ } int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel) @@ -602,24 +575,18 @@ int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_r if (ctx.retval != ERROR_OK) goto exit; - pracc_add(&ctx, 0, MIPS32_LUI(15, UPPER16(val))); /* Load val to $15 */ + pracc_add(&ctx, 0, MIPS32_LUI(15, UPPER16(val))); /* Load val to $15 */ pracc_add(&ctx, 0, MIPS32_ORI(15, 15, LOWER16(val))); - pracc_add(&ctx, 0, MIPS32_MTC0(15, 0, 0) | (cp0_reg << 11) | cp0_sel); /* write cp0 reg / sel */ + pracc_add(&ctx, 0, MIPS32_MTC0(15, cp0_reg, cp0_sel)); /* write $15 to cp0 reg / sel */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ + pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); exit: pracc_queue_free(&ctx); return ctx.retval; - - /** - * Note that MIPS32_MTC0 macro is implemented via MIPS32_R_INST macro. - * In order to insert our parameters, we must change rd and funct fields. - * code[3] |= (cp0_reg << 11) | cp0_sel; change rd and funct fields of MIPS32_R_INST macro - **/ } /** @@ -956,9 +923,6 @@ int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */ - if (ejtag_info->mode == 0) - ctx.store_count++; /* Needed by legacy code, due to offset from reg0 */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs); ejtag_info->reg8 = regs[8]; /* reg8 is saved but not restored, next called function should restore it */ @@ -1015,7 +979,7 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are }; int retval, i; - uint32_t val, ejtag_ctrl, address; + uint32_t val, ejtag_ctrl; if (source->size < MIPS32_FASTDATA_HANDLER_SIZE) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -1054,19 +1018,13 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are mips_ejtag_drscan_32_out(ejtag_info, ejtag_ctrl); } - /* wait PrAcc pending bit for FASTDATA write */ - retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); + /* wait PrAcc pending bit for FASTDATA write, read address */ + retval = mips32_pracc_read_ctrl_addr(ejtag_info); if (retval != ERROR_OK) return retval; /* next fetch to dmseg should be in FASTDATA_AREA, check */ - address = 0; - mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); - retval = mips_ejtag_drscan_32(ejtag_info, &address); - if (retval != ERROR_OK) - return retval; - - if (address != MIPS32_PRACC_FASTDATA_AREA) + if (ejtag_info->pa_addr != MIPS32_PRACC_FASTDATA_AREA) return ERROR_FAIL; /* Send the load start address */ @@ -1100,17 +1058,11 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are return retval; } - retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); - if (retval != ERROR_OK) - return retval; - - address = 0; - mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); - retval = mips_ejtag_drscan_32(ejtag_info, &address); + retval = mips32_pracc_read_ctrl_addr(ejtag_info); if (retval != ERROR_OK) return retval; - if (address != MIPS32_PRACC_TEXT) + if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT) LOG_ERROR("mini program did not return to start"); return retval; -- cgit v1.1 From 5fdcbbdb25d19a36e3fed27edb21a805eb34399f Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Thu, 23 Feb 2017 15:14:46 +0100 Subject: mips32, mips32_pracc_finish() queued only In most of the cases there is no need to request execution, the check for a new pracc access already does it. Requesting execution if not needed makes execution slower and code larger due the additional checks. Reduce code in fasdata transfer function. Call for execution when exiting debug. Change-Id: I3b45f6d1f62da5fad3e3db84f82a9299b16e1bd9 Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4010 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips32_pracc.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 69d9a00..caa566b 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -116,24 +116,21 @@ static int mips32_pracc_read_ctrl_addr(struct mips_ejtag *ejtag_info) } /* Finish processor access */ -static int mips32_pracc_finish(struct mips_ejtag *ejtag_info) +static void mips32_pracc_finish(struct mips_ejtag *ejtag_info) { uint32_t ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); mips_ejtag_drscan_32_out(ejtag_info, ctrl); - - return jtag_execute_queue(); } int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info) { uint32_t jt_code = MIPS32_J((0x0FFFFFFF & MIPS32_PRACC_TEXT) >> 2); - int retval; /* do 3 0/nops to clean pipeline before a jump to pracc text, NOP in delay slot */ for (int i = 0; i != 5; i++) { /* Wait for pracc */ - retval = wait_for_pracc_rw(ejtag_info, &ejtag_info->pa_ctrl); + int retval = wait_for_pracc_rw(ejtag_info, &ejtag_info->pa_ctrl); if (retval != ERROR_OK) return retval; @@ -143,25 +140,21 @@ int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info) mips_ejtag_drscan_32_out(ejtag_info, data); /* finish pa */ - retval = mips32_pracc_finish(ejtag_info); - if (retval != ERROR_OK) - return retval; + mips32_pracc_finish(ejtag_info); } if (ejtag_info->mode != 0) /* async mode support only for MIPS ... */ return ERROR_OK; for (int i = 0; i != 2; i++) { - retval = mips32_pracc_read_ctrl_addr(ejtag_info); + int retval = mips32_pracc_read_ctrl_addr(ejtag_info); if (retval != ERROR_OK) return retval; if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT) { /* LEXRA/BMIPS ?, shift out another NOP, max 2 */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); mips_ejtag_drscan_32_out(ejtag_info, MIPS32_NOP); - retval = mips32_pracc_finish(ejtag_info); - if (retval != ERROR_OK) - return retval; + mips32_pracc_finish(ejtag_info); } else break; } @@ -298,12 +291,10 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct mips_ejtag_drscan_32_out(ejtag_info, instr); } /* finish processor access, let the processor eat! */ - retval = mips32_pracc_finish(ejtag_info); - if (retval != ERROR_OK) - return retval; + mips32_pracc_finish(ejtag_info); if (instr == MIPS32_DRET) /* after leaving debug mode nothing to do */ - return ERROR_OK; + return jtag_execute_queue(); if (store_pending == 0 && pass) { /* store access done, but after passing pracc text */ LOG_DEBUG("warning: store access pass pracc text"); @@ -1013,9 +1004,7 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are mips_ejtag_drscan_32_out(ejtag_info, jmp_code[i]); /* Clear the access pending bit (let the processor eat!) */ - ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC; - mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); - mips_ejtag_drscan_32_out(ejtag_info, ejtag_ctrl); + mips32_pracc_finish(ejtag_info); } /* wait PrAcc pending bit for FASTDATA write, read address */ -- cgit v1.1 From 9bdc3bf0a817e27879c6d2758d70ee274fe7dcb7 Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Thu, 23 Feb 2017 22:55:34 +0100 Subject: mips32, in wait_for_pracc_rw() use ejtag_info->pa_ctrl Makes code shorter In fasdata transfer fuction declare variables locally. Avoid cast. Change-Id: I0367b66339560fc20521a0598488e7ff9076808e Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4011 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips32_pracc.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index caa566b..4ca92ae 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -73,21 +73,20 @@ #include "mips32.h" #include "mips32_pracc.h" -static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl) +static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info) { - uint32_t ejtag_ctrl; int64_t then = timeval_ms(); /* wait for the PrAcc to become "1" */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); while (1) { - ejtag_ctrl = ejtag_info->ejtag_ctrl; - int retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_ctrl); + ejtag_info->pa_ctrl = ejtag_info->ejtag_ctrl; + int retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_info->pa_ctrl); if (retval != ERROR_OK) return retval; - if (ejtag_ctrl & EJTAG_CTRL_PRACC) + if (ejtag_info->pa_ctrl & EJTAG_CTRL_PRACC) break; int64_t timeout = timeval_ms() - then; @@ -97,22 +96,20 @@ static int wait_for_pracc_rw(struct mips_ejtag *ejtag_info, uint32_t *ctrl) } } - *ctrl = ejtag_ctrl; return ERROR_OK; } /* Shift in control and address for a new processor access, save them in ejtag_info */ static int mips32_pracc_read_ctrl_addr(struct mips_ejtag *ejtag_info) { - int retval = wait_for_pracc_rw(ejtag_info, &ejtag_info->pa_ctrl); + int retval = wait_for_pracc_rw(ejtag_info); if (retval != ERROR_OK) return retval; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); - ejtag_info->pa_addr = 0; - retval = mips_ejtag_drscan_32(ejtag_info, &ejtag_info->pa_addr); - return retval; + ejtag_info->pa_addr = 0; + return mips_ejtag_drscan_32(ejtag_info, &ejtag_info->pa_addr); } /* Finish processor access */ @@ -130,7 +127,7 @@ int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info) /* do 3 0/nops to clean pipeline before a jump to pracc text, NOP in delay slot */ for (int i = 0; i != 5; i++) { /* Wait for pracc */ - int retval = wait_for_pracc_rw(ejtag_info, &ejtag_info->pa_ctrl); + int retval = wait_for_pracc_rw(ejtag_info); if (retval != ERROR_OK) return retval; @@ -969,9 +966,6 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are MIPS32_NOP, }; - int retval, i; - uint32_t val, ejtag_ctrl; - if (source->size < MIPS32_FASTDATA_HANDLER_SIZE) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; @@ -995,8 +989,8 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are jmp_code[0] |= UPPER16(source->address); jmp_code[1] |= LOWER16(source->address); - for (i = 0; i < (int) ARRAY_SIZE(jmp_code); i++) { - retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); + for (unsigned i = 0; i < ARRAY_SIZE(jmp_code); i++) { + int retval = wait_for_pracc_rw(ejtag_info); if (retval != ERROR_OK) return retval; @@ -1008,7 +1002,7 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are } /* wait PrAcc pending bit for FASTDATA write, read address */ - retval = mips32_pracc_read_ctrl_addr(ejtag_info); + int retval = mips32_pracc_read_ctrl_addr(ejtag_info); if (retval != ERROR_OK) return retval; @@ -1017,11 +1011,11 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are return ERROR_FAIL; /* Send the load start address */ - val = addr; + uint32_t val = addr; mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA); mips_ejtag_fastdata_scan(ejtag_info, 1, &val); - retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); + retval = wait_for_pracc_rw(ejtag_info); if (retval != ERROR_OK) return retval; @@ -1034,7 +1028,7 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are if (ejtag_info->mode != 0) num_clocks = ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000; - for (i = 0; i < count; i++) { + for (int i = 0; i < count; i++) { jtag_add_clocks(num_clocks); retval = mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++); if (retval != ERROR_OK) -- cgit v1.1 From bff6205bab5531c92a269c1dab88ca535cdb4660 Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Fri, 24 Feb 2017 16:44:12 +0100 Subject: mips32, implement assembler li instruction Implement it as a function, the code was already in. Added optimize option. Change-Id: Ib9ad3f00d6c4f0b91c4e4960a50ec8d102f4e333 Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4017 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips32_pracc.c | 64 ++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 37 deletions(-) diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 4ca92ae..6da1843 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -321,6 +321,18 @@ inline void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t inst ctx->store_count++; } +inline void pracc_add_li32(struct pracc_queue_info *ctx, uint32_t reg_num, uint32_t data, bool optimize) +{ + if (LOWER16(data) == 0 && optimize) + pracc_add(ctx, 0, MIPS32_LUI(reg_num, UPPER16(data))); /* load only upper value */ + else if (UPPER16(data) == 0 && optimize) + pracc_add(ctx, 0, MIPS32_ORI(reg_num, 0, LOWER16(data))); /* load only lower */ + else { + pracc_add(ctx, 0, MIPS32_LUI(reg_num, UPPER16(data))); /* load upper and lower */ + pracc_add(ctx, 0, MIPS32_ORI(reg_num, reg_num, LOWER16(data))); + } +} + inline void pracc_queue_free(struct pracc_queue_info *ctx) { if (ctx->code_count > ctx->max_code) /* Only for internal check, will be erased */ @@ -438,8 +450,7 @@ int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 8)); /* lw $8, LOWER16(addr)($8) */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* sw $8,PRACC_OUT_OFFSET($15) */ - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 of $8 */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 of $8 */ + pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */ pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ @@ -499,10 +510,8 @@ int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size MIPS32_SW(8, PRACC_OUT_OFFSET + i * 4, 15)); /* store $8 at param out */ addr += size; } - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of reg 8 */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of reg 8 */ - pracc_add(&ctx, 0, MIPS32_LUI(9, UPPER16(ejtag_info->reg9))); /* restore upper 16 bits of reg 9 */ - pracc_add(&ctx, 0, MIPS32_ORI(9, 9, LOWER16(ejtag_info->reg9))); /* restore lower 16 bits of reg 9 */ + pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */ + pracc_add_li32(&ctx, 9, ejtag_info->reg9, 0); /* restore $9 */ pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ @@ -563,11 +572,9 @@ int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_r if (ctx.retval != ERROR_OK) goto exit; - pracc_add(&ctx, 0, MIPS32_LUI(15, UPPER16(val))); /* Load val to $15 */ - pracc_add(&ctx, 0, MIPS32_ORI(15, 15, LOWER16(val))); + pracc_add_li32(&ctx, 15, val, 0); /* Load val to $15 */ pracc_add(&ctx, 0, MIPS32_MTC0(15, cp0_reg, cp0_sel)); /* write $15 to cp0 reg / sel */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ @@ -621,8 +628,8 @@ static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info, pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ + pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */ + pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ @@ -732,15 +739,8 @@ static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info, last_upper_base_addr = upper_base_addr; } - if (size == 4) { /* for word writes check if one half word is 0 and load it accordingly */ - if (LOWER16(*buf32) == 0) - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(*buf32))); /* load only upper value */ - else if (UPPER16(*buf32) == 0) - pracc_add(&ctx, 0, MIPS32_ORI(8, 0, LOWER16(*buf32))); /* load only lower */ - else { - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(*buf32))); /* load upper and lower */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(*buf32))); - } + if (size == 4) { + pracc_add_li32(&ctx, 8, *buf32, 1); /* load with li32, optimize */ pracc_add(&ctx, 0, MIPS32_SW(8, LOWER16(addr), 15)); /* store word to memory */ buf32++; @@ -757,8 +757,7 @@ static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info, addr += size; } - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of reg 8 */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of reg 8 */ + pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */ pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ @@ -844,26 +843,17 @@ int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) if (ctx.retval != ERROR_OK) goto exit; - /* load registers 2 to 31 with lui and ori instructions, check if some instructions can be saved */ - for (int i = 2; i < 32; i++) { - if (LOWER16((regs[i])) == 0) /* if lower half word is 0, lui instruction only */ - pracc_add(&ctx, 0, MIPS32_LUI(i, UPPER16((regs[i])))); - else if (UPPER16((regs[i])) == 0) /* if upper half word is 0, ori with $0 only*/ - pracc_add(&ctx, 0, MIPS32_ORI(i, 0, LOWER16((regs[i])))); - else { /* default, load with lui and ori instructions */ - pracc_add(&ctx, 0, MIPS32_LUI(i, UPPER16((regs[i])))); - pracc_add(&ctx, 0, MIPS32_ORI(i, i, LOWER16((regs[i])))); - } - } + /* load registers 2 to 31 with li32, optimize */ + for (int i = 2; i < 32; i++) + pracc_add_li32(&ctx, i, regs[i], 1); for (int i = 0; i != 6; i++) { - pracc_add(&ctx, 0, MIPS32_LUI(1, UPPER16((regs[i + 32])))); /* load CPO value in $1, with lui and ori */ - pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[i + 32])))); - pracc_add(&ctx, 0, cp0_write_code[i]); /* write value from $1 to CPO register */ + pracc_add_li32(&ctx, 1, regs[i + 32], 0); /* load CPO value in $1 */ + pracc_add(&ctx, 0, cp0_write_code[i]); /* write value from $1 to CPO register */ } pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */ pracc_add(&ctx, 0, MIPS32_LUI(1, UPPER16((regs[1])))); /* load upper half word in $1 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[1])))); /* load lower half word in $1 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); -- cgit v1.1 From cb317eabf2d162365467aeb89b564828e5e6d6f3 Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Fri, 24 Feb 2017 23:39:39 +0100 Subject: mips32, write handler code in a more compact way Less code and probably cleaner. Don't check if it is ever ERROR_OK. Change-Id: I1045b58fd4542ec24430332f49679364ae97b1dc Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4018 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips32_pracc.c | 46 +++++++++++++++++----------------------------- 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 6da1843..45d2242 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -921,7 +921,6 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are int write_t, uint32_t addr, int count, uint32_t *buf) { uint32_t handler_code[] = { - /* caution when editing, table is modified below */ /* r15 points to the start of this code */ MIPS32_SW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15), MIPS32_SW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15), @@ -930,13 +929,14 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are /* start of fastdata area in t0 */ MIPS32_LUI(8, UPPER16(MIPS32_PRACC_FASTDATA_AREA)), MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA)), - MIPS32_LW(9, 0, 8), /* start addr in t1 */ - MIPS32_LW(10, 0, 8), /* end addr to t2 */ - /* loop: */ - /* 8 */ MIPS32_LW(11, 0, 0), /* lw t3,[t8 | r9] */ - /* 9 */ MIPS32_SW(11, 0, 0), /* sw t3,[r9 | r8] */ - MIPS32_BNE(10, 9, NEG16(3)), /* bne $t2,t1,loop */ - MIPS32_ADDI(9, 9, 4), /* addi t1,t1,4 */ + MIPS32_LW(9, 0, 8), /* start addr in t1 */ + MIPS32_LW(10, 0, 8), /* end addr to t2 */ + /* loop: */ + write_t ? MIPS32_LW(11, 0, 8) : MIPS32_LW(11, 0, 9), /* from xfer area : from memory */ + write_t ? MIPS32_SW(11, 0, 9) : MIPS32_SW(11, 0, 8), /* to memory : to xfer area */ + + MIPS32_BNE(10, 9, NEG16(3)), /* bne $t2,t1,loop */ + MIPS32_ADDI(9, 9, 4), /* addi t1,t1,4 */ MIPS32_LW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15), MIPS32_LW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15), @@ -949,25 +949,10 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */ }; - uint32_t jmp_code[] = { - /* 0 */ MIPS32_LUI(15, 0), /* addr of working area added below */ - /* 1 */ MIPS32_ORI(15, 15, 0), /* addr of working area added below */ - MIPS32_JR(15), /* jump to ram program */ - MIPS32_NOP, - }; - if (source->size < MIPS32_FASTDATA_HANDLER_SIZE) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; - if (write_t) { - handler_code[8] = MIPS32_LW(11, 0, 8); /* load data from probe at fastdata area */ - handler_code[9] = MIPS32_SW(11, 0, 9); /* store data to RAM @ r9 */ - } else { - handler_code[8] = MIPS32_LW(11, 0, 9); /* load data from RAM @ r9 */ - handler_code[9] = MIPS32_SW(11, 0, 8); /* store data to probe at fastdata area */ - } - - /* write program into RAM */ + /* write program into RAM */ if (write_t != ejtag_info->fast_access_save) { mips32_pracc_write_mem(ejtag_info, source->address, 4, ARRAY_SIZE(handler_code), handler_code); /* save previous operation to speed to any consecutive read/writes */ @@ -976,9 +961,14 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are LOG_DEBUG("%s using 0x%.8" TARGET_PRIxADDR " for write handler", __func__, source->address); - jmp_code[0] |= UPPER16(source->address); - jmp_code[1] |= LOWER16(source->address); + uint32_t jmp_code[] = { + MIPS32_LUI(15, UPPER16(source->address)), /* load addr of jump in $15 */ + MIPS32_ORI(15, 15, LOWER16(source->address)), + MIPS32_JR(15), /* jump to ram program */ + MIPS32_NOP, + }; + /* execute jump code, with no address check */ for (unsigned i = 0; i < ARRAY_SIZE(jmp_code); i++) { int retval = wait_for_pracc_rw(ejtag_info); if (retval != ERROR_OK) @@ -1020,9 +1010,7 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are for (int i = 0; i < count; i++) { jtag_add_clocks(num_clocks); - retval = mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++); - if (retval != ERROR_OK) - return retval; + mips_ejtag_fastdata_scan(ejtag_info, write_t, buf++); } retval = jtag_execute_queue(); -- cgit v1.1 From 3414daed26c87a41ba66f0fef6e6292564bb5111 Mon Sep 17 00:00:00 2001 From: Matthias Welwarsky Date: Tue, 2 May 2017 16:47:21 +0200 Subject: Fix compile failure on MacOSX MacOSX tool chain defines __unused in "sys/cdefs.h", causing a collision. Remove the local define to avoid polluting the compilers internal symbol namespace. Change-Id: I16370c4518e6aeec482dd689e7db80628f846ee3 Signed-off-by: Matthias Welwarsky Reviewed-on: http://openocd.zylin.com/4118 Reviewed-by: Steven Stallion Reviewed-by: Freddie Chopin Reviewed-by: Andreas Fritiofson Tested-by: jenkins --- src/target/aarch64.c | 2 -- src/target/armv8.c | 8 +++----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/src/target/aarch64.c b/src/target/aarch64.c index e647bba..5e5d3fc 100644 --- a/src/target/aarch64.c +++ b/src/target/aarch64.c @@ -30,8 +30,6 @@ #include "armv8_cache.h" #include -#define __unused __attribute((unused)) - enum restart_mode { RESTART_LAZY, RESTART_SYNC, diff --git a/src/target/armv8.c b/src/target/armv8.c index db7a871..df5e251 100644 --- a/src/target/armv8.c +++ b/src/target/armv8.c @@ -37,8 +37,6 @@ #include "target.h" #include "target_type.h" -#define __unused __attribute__((unused)) - static const char * const armv8_state_strings[] = { "AArch32", "Thumb", "Jazelle", "ThumbEE", "AArch64", }; @@ -610,7 +608,7 @@ done: /* (void) */ dpm->finish(dpm); } -static __unused void armv8_show_fault_registers(struct target *target) +static __attribute__((unused)) void armv8_show_fault_registers(struct target *target) { struct armv8_common *armv8 = target_to_armv8(target); @@ -647,7 +645,7 @@ static uint8_t armv8_pa_size(uint32_t ps) return ret; } -static __unused int armv8_read_ttbcr32(struct target *target) +static __attribute__((unused)) int armv8_read_ttbcr32(struct target *target) { struct armv8_common *armv8 = target_to_armv8(target); struct arm_dpm *dpm = armv8->arm.dpm; @@ -686,7 +684,7 @@ done: return retval; } -static __unused int armv8_read_ttbcr(struct target *target) +static __attribute__((unused)) int armv8_read_ttbcr(struct target *target) { struct armv8_common *armv8 = target_to_armv8(target); struct arm_dpm *dpm = armv8->arm.dpm; -- cgit v1.1 From c8b31aaa155be4361c090b369bc73f0f87751154 Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Sun, 26 Feb 2017 09:11:02 +0100 Subject: mips32, change in pracc_list for dynamic allocation pracc_list points to an array with code in the lower half and addr in the upper half. Change it to a struct with an instruction field and an address field. Requiered to make reallocation easier. As a side effect the code is less quirky. Change-Id: Ibf904a33a2f35a7f69284d2a2114f4b4ae79219f Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4019 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips32_pracc.c | 78 ++++++++++++++++++++++------------------------- src/target/mips32_pracc.h | 7 ++++- src/target/mips_ejtag.c | 4 +-- 3 files changed, 45 insertions(+), 44 deletions(-) diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 45d2242..c55688b 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -235,18 +235,17 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct restart = 1; continue; } - return ERROR_JTAG_DEVICE_ERROR; } /* check for store instruction at dmseg */ - uint32_t store_addr = ctx->pracc_list[ctx->max_code + code_count]; + uint32_t store_addr = ctx->pracc_list[code_count].addr; if (store_addr != 0) { if (store_addr > max_store_addr) max_store_addr = store_addr; store_pending++; } - instr = ctx->pracc_list[code_count++]; + instr = ctx->pracc_list[code_count++].instr; if (code_count == ctx->code_count) /* last instruction, start final check */ final_check = 1; @@ -306,7 +305,7 @@ inline void pracc_queue_init(struct pracc_queue_info *ctx) ctx->code_count = 0; ctx->store_count = 0; - ctx->pracc_list = malloc(2 * ctx->max_code * sizeof(uint32_t)); + ctx->pracc_list = malloc(ctx->max_code * sizeof(pa_list)); if (ctx->pracc_list == NULL) { LOG_ERROR("Out of memory"); ctx->retval = ERROR_FAIL; @@ -315,8 +314,8 @@ inline void pracc_queue_init(struct pracc_queue_info *ctx) inline void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr) { - ctx->pracc_list[ctx->max_code + ctx->code_count] = addr; - ctx->pracc_list[ctx->code_count++] = instr; + ctx->pracc_list[ctx->code_count].instr = instr; + ctx->pracc_list[ctx->code_count++].addr = addr; if (addr) ctx->store_count++; } @@ -367,16 +366,16 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ALL); int scan_count = 0; - for (int i = 0; i != 2 * ctx->code_count; i++) { - uint32_t data = 0; - if (i & 1u) { /* Check store address from previous instruction, if not the first */ - if (i < 2 || 0 == ctx->pracc_list[ctx->max_code + (i / 2) - 1]) - continue; - } else - data = ctx->pracc_list[i / 2]; - + for (int i = 0; i != ctx->code_count; i++) { jtag_add_clocks(num_clocks); - mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, data, scan_in[scan_count++].scan_96); + mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, ctx->pracc_list[i].instr, + scan_in[scan_count++].scan_96); + + /* Check store address from previous instruction, if not the first */ + if (i > 0 && ctx->pracc_list[i - 1].addr) { + jtag_add_clocks(num_clocks); + mips_ejtag_add_scan_96(ejtag_info, ejtag_ctrl, 0, scan_in[scan_count++].scan_96); + } } int retval = jtag_execute_queue(); /* execute queued scans */ @@ -385,24 +384,35 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in uint32_t fetch_addr = MIPS32_PRACC_TEXT; /* start address */ scan_count = 0; - for (int i = 0; i != 2 * ctx->code_count; i++) { /* verify every pracc access */ - uint32_t store_addr = 0; - if (i & 1u) { /* Read store addres from previous instruction, if not the first */ - store_addr = ctx->pracc_list[ctx->max_code + (i / 2) - 1]; - if (i < 2 || 0 == store_addr) - continue; - } - + for (int i = 0; i != ctx->code_count; i++) { /* verify every pracc access */ + /* check pracc bit */ ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32); + uint32_t addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32); if (!(ejtag_ctrl & EJTAG_CTRL_PRACC)) { LOG_ERROR("Error: access not pending count: %d", scan_count); retval = ERROR_FAIL; goto exit; } + if (ejtag_ctrl & EJTAG_CTRL_PRNW) { + LOG_ERROR("Not a fetch/read access, count: %d", scan_count); + retval = ERROR_FAIL; + goto exit; + } + if (addr != fetch_addr) { + LOG_ERROR("Fetch addr mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d", + addr, fetch_addr, scan_count); + retval = ERROR_FAIL; + goto exit; + } + fetch_addr += 4; + scan_count++; - uint32_t addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32); + /* check if previous intrucction is a store instruction at dmesg */ + if (i > 0 && ctx->pracc_list[i - 1].addr) { + uint32_t store_addr = ctx->pracc_list[i - 1].addr; + ejtag_ctrl = buf_get_u32(scan_in[scan_count].scan_32.ctrl, 0, 32); + addr = buf_get_u32(scan_in[scan_count].scan_32.addr, 0, 32); - if (store_addr != 0) { if (!(ejtag_ctrl & EJTAG_CTRL_PRNW)) { LOG_ERROR("Not a store/write access, count: %d", scan_count); retval = ERROR_FAIL; @@ -410,28 +420,14 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in } if (addr != store_addr) { LOG_ERROR("Store address mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d", - addr, store_addr, scan_count); + addr, store_addr, scan_count); retval = ERROR_FAIL; goto exit; } int buf_index = (addr - MIPS32_PRACC_PARAM_OUT) / 4; buf[buf_index] = buf_get_u32(scan_in[scan_count].scan_32.data, 0, 32); - - } else { - if (ejtag_ctrl & EJTAG_CTRL_PRNW) { - LOG_ERROR("Not a fetch/read access, count: %d", scan_count); - retval = ERROR_FAIL; - goto exit; - } - if (addr != fetch_addr) { - LOG_ERROR("Fetch addr mismatch, read: %" PRIx32 " expected: %" PRIx32 " count: %d", - addr, fetch_addr, scan_count); - retval = ERROR_FAIL; - goto exit; - } - fetch_addr += 4; + scan_count++; } - scan_count++; } exit: free(scan_in); diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index 2ede5b2..166cbb4 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -42,12 +42,17 @@ #define NEG16(v) (((~(v)) + 1) & 0xFFFF) /*#define NEG18(v) (((~(v)) + 1) & 0x3FFFF)*/ +typedef struct { + uint32_t instr; + uint32_t addr; +} pa_list; + struct pracc_queue_info { int retval; const int max_code; int code_count; int store_count; - uint32_t *pracc_list; /* Code and store addresses */ + pa_list *pracc_list; /* Code and store addresses at dmseg */ }; void pracc_queue_init(struct pracc_queue_info *ctx); void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr); diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index 1fbdf3c..943a868 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -272,8 +272,8 @@ error: int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info) { - uint32_t pracc_list[] = {MIPS32_DRET, 0}; - struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = pracc_list, .code_count = 1, .store_count = 0}; + pa_list pracc_list = {.instr = MIPS32_DRET, .addr = 0}; + struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = &pracc_list, .code_count = 1, .store_count = 0}; /* execute our dret instruction */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); -- cgit v1.1 From 1392c27cf9ff1a7f5f5477d23880f2e5c59c898e Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Sun, 26 Feb 2017 20:35:01 +0100 Subject: mips32, add realloc code If max_code is reached realloc memory. If fails to realloc the error is propagated and every call to pracc_add() returns immediately. The exec function logs the error. Change-Id: Idd4ed9d9b8b19b7d6842d0bc5ebb05f943726705 Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4020 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips32_pracc.c | 69 +++++++++++++++++++++-------------------------- src/target/mips32_pracc.h | 5 +++- src/target/mips_ejtag.c | 5 +--- 3 files changed, 35 insertions(+), 44 deletions(-) diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index c55688b..da1cee1 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -304,23 +304,31 @@ inline void pracc_queue_init(struct pracc_queue_info *ctx) ctx->retval = ERROR_OK; ctx->code_count = 0; ctx->store_count = 0; - - ctx->pracc_list = malloc(ctx->max_code * sizeof(pa_list)); - if (ctx->pracc_list == NULL) { - LOG_ERROR("Out of memory"); - ctx->retval = ERROR_FAIL; - } + ctx->max_code = 0; + ctx->pracc_list = NULL; } -inline void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr) +void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr) { + if (ctx->retval != ERROR_OK) /* On previous out of memory, return */ + return; + if (ctx->code_count == ctx->max_code) { + void *p = realloc(ctx->pracc_list, sizeof(pa_list) * (ctx->max_code + PRACC_BLOCK)); + if (p) { + ctx->max_code += PRACC_BLOCK; + ctx->pracc_list = p; + } else { + ctx->retval = ERROR_FAIL; /* Out of memory */ + return; + } + } ctx->pracc_list[ctx->code_count].instr = instr; ctx->pracc_list[ctx->code_count++].addr = addr; if (addr) ctx->store_count++; } -inline void pracc_add_li32(struct pracc_queue_info *ctx, uint32_t reg_num, uint32_t data, bool optimize) +void pracc_add_li32(struct pracc_queue_info *ctx, uint32_t reg_num, uint32_t data, bool optimize) { if (LOWER16(data) == 0 && optimize) pracc_add(ctx, 0, MIPS32_LUI(reg_num, UPPER16(data))); /* load only upper value */ @@ -334,14 +342,17 @@ inline void pracc_add_li32(struct pracc_queue_info *ctx, uint32_t reg_num, uint3 inline void pracc_queue_free(struct pracc_queue_info *ctx) { - if (ctx->code_count > ctx->max_code) /* Only for internal check, will be erased */ - LOG_ERROR("Internal error, code count: %d > max code: %d", ctx->code_count, ctx->max_code); if (ctx->pracc_list != NULL) free(ctx->pracc_list); } int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *buf) { + if (ctx->retval != ERROR_OK) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + if (ejtag_info->mode == 0) return mips32_pracc_exec(ejtag_info, ctx, buf); @@ -436,10 +447,8 @@ exit: int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf) { - struct pracc_queue_info ctx = {.max_code = 8}; + struct pracc_queue_info ctx; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16((addr + 0x8000)))); /* load $8 with modified upper address */ @@ -451,7 +460,6 @@ int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf); -exit: pracc_queue_free(&ctx); return ctx.retval; } @@ -462,10 +470,8 @@ int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t *)buf); uint32_t *data = NULL; - struct pracc_queue_info ctx = {.max_code = 256 * 3 + 8 + 1}; /* alloc memory for the worst case */ + struct pracc_queue_info ctx; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; if (size != 4) { data = malloc(256 * sizeof(uint32_t)); @@ -541,10 +547,8 @@ exit: int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel) { - struct pracc_queue_info ctx = {.max_code = 7}; + struct pracc_queue_info ctx; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ pracc_add(&ctx, 0, MIPS32_MFC0(8, cp0_reg, cp0_sel)); /* move cp0 reg / sel to $8 */ @@ -556,17 +560,14 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_r pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val); -exit: pracc_queue_free(&ctx); return ctx.retval; } int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel) { - struct pracc_queue_info ctx = {.max_code = 6}; + struct pracc_queue_info ctx; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; pracc_add_li32(&ctx, 15, val, 0); /* Load val to $15 */ @@ -575,7 +576,6 @@ int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_r pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); -exit: pracc_queue_free(&ctx); return ctx.retval; } @@ -610,10 +610,9 @@ exit: static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info, uint32_t start_addr, uint32_t end_addr, int cached, int rel) { - struct pracc_queue_info ctx = {.max_code = 256 * 2 + 5}; + struct pracc_queue_info ctx; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; + /** Find cache line size in bytes */ uint32_t clsiz; if (rel) { /* Release 2 (rel = 1) */ @@ -711,10 +710,8 @@ exit: static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, const void *buf) { - struct pracc_queue_info ctx = {.max_code = 128 * 3 + 5 + 1}; /* alloc memory for the worst case */ + struct pracc_queue_info ctx; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; const uint32_t *buf32 = buf; const uint16_t *buf16 = buf; @@ -834,10 +831,8 @@ int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) MIPS32_MTC0(1, 24, 0), /* move $1 to depc (pc) */ }; - struct pracc_queue_info ctx = {.max_code = 37 * 2 + 7 + 1}; + struct pracc_queue_info ctx; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; /* load registers 2 to 31 with li32, optimize */ for (int i = 2; i < 32; i++) @@ -856,7 +851,6 @@ int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) ejtag_info->reg8 = regs[8]; ejtag_info->reg9 = regs[9]; -exit: pracc_queue_free(&ctx); return ctx.retval; } @@ -872,10 +866,8 @@ int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) MIPS32_MFC0(8, 24, 0), /* move depc (pc) to $8 */ }; - struct pracc_queue_info ctx = {.max_code = 49}; + struct pracc_queue_info ctx; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; pracc_add(&ctx, 0, MIPS32_MTC0(1, 31, 0)); /* move $1 to COP0 DeSave */ pracc_add(&ctx, 0, MIPS32_LUI(1, PRACC_UPPER_BASE_ADDR)); /* $1 = MIP32_PRACC_BASE_ADDR */ @@ -901,7 +893,6 @@ int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) ejtag_info->reg8 = regs[8]; /* reg8 is saved but not restored, next called function should restore it */ ejtag_info->reg9 = regs[9]; -exit: pracc_queue_free(&ctx); return ctx.retval; } diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index 166cbb4..525d6e6 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -42,6 +42,8 @@ #define NEG16(v) (((~(v)) + 1) & 0xFFFF) /*#define NEG18(v) (((~(v)) + 1) & 0x3FFFF)*/ +#define PRACC_BLOCK 128 /* 1 Kbyte */ + typedef struct { uint32_t instr; uint32_t addr; @@ -49,13 +51,14 @@ typedef struct { struct pracc_queue_info { int retval; - const int max_code; int code_count; int store_count; + int max_code; /* max intstructions with currently allocated memory */ pa_list *pracc_list; /* Code and store addresses at dmseg */ }; void pracc_queue_init(struct pracc_queue_info *ctx); void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr); +void pracc_add_li32(struct pracc_queue_info *ctx, uint32_t reg_num, uint32_t data, bool optimize); void pracc_queue_free(struct pracc_queue_info *ctx); int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *buf); diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index 943a868..1a8a843 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -197,10 +197,8 @@ void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data) /* Set (to enable) or clear (to disable stepping) the SSt bit (bit 8) in Cp0 Debug reg (reg 23, sel 0) */ int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step) { - struct pracc_queue_info ctx = {.max_code = 7}; + struct pracc_queue_info ctx; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; pracc_add(&ctx, 0, MIPS32_MFC0(8, 23, 0)); /* move COP0 Debug to $8 */ pracc_add(&ctx, 0, MIPS32_ORI(8, 8, 0x0100)); /* set SSt bit in debug reg */ @@ -213,7 +211,6 @@ int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step) pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); -exit: pracc_queue_free(&ctx); return ctx.retval; } -- cgit v1.1 From e32058811794388038fcb7da930f3154c0cb7ea2 Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Mon, 27 Feb 2017 12:25:49 +0100 Subject: mips32, add option to avoid check in last instruction This option is needed, for example, when exiting debug mode in bmips targets. The last instruction is a NOP, not a DERET. When working in async mode this check is not done, mips32_pracc_queue_exec() pass the parameter to mips32_pracc_exec() and never use it. Change-Id: I4c7ed4feb1588b62e2645b955b501b6671113b36 Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4021 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips32_pracc.c | 60 ++++++++++++++++++++++++----------------------- src/target/mips32_pracc.h | 5 ++-- src/target/mips_ejtag.c | 4 ++-- 3 files changed, 36 insertions(+), 33 deletions(-) diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index da1cee1..7324246 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -159,7 +159,8 @@ int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info) return ERROR_OK; } -int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *param_out) +int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, + uint32_t *param_out, bool check_last) { int code_count = 0; int store_pending = 0; /* increases with every store instruction at dmseg, decreases with every store pa */ @@ -289,7 +290,7 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct /* finish processor access, let the processor eat! */ mips32_pracc_finish(ejtag_info); - if (instr == MIPS32_DRET) /* after leaving debug mode nothing to do */ + if (final_check && !check_last) /* last instr, don't check, execute and exit */ return jtag_execute_queue(); if (store_pending == 0 && pass) { /* store access done, but after passing pracc text */ @@ -346,7 +347,8 @@ inline void pracc_queue_free(struct pracc_queue_info *ctx) free(ctx->pracc_list); } -int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *buf) +int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, + uint32_t *buf, bool check_last) { if (ctx->retval != ERROR_OK) { LOG_ERROR("Out of memory"); @@ -354,7 +356,7 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in } if (ejtag_info->mode == 0) - return mips32_pracc_exec(ejtag_info, ctx, buf); + return mips32_pracc_exec(ejtag_info, ctx, buf, check_last); union scan_in { uint8_t scan_96[12]; @@ -459,7 +461,7 @@ int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf, 1); pracc_queue_free(&ctx); return ctx.retval; } @@ -491,40 +493,40 @@ int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size int this_round_count = (count > 256) ? 256 : count; uint32_t last_upper_base_addr = UPPER16((addr + 0x8000)); - pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ - pracc_add(&ctx, 0, MIPS32_LUI(9, last_upper_base_addr)); /* load the upper memory address in $9 */ + pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + pracc_add(&ctx, 0, MIPS32_LUI(9, last_upper_base_addr)); /* load the upper memory address in $9 */ for (int i = 0; i != this_round_count; i++) { /* Main code loop */ uint32_t upper_base_addr = UPPER16((addr + 0x8000)); - if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $9 */ + if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $9 */ pracc_add(&ctx, 0, MIPS32_LUI(9, upper_base_addr)); last_upper_base_addr = upper_base_addr; } if (size == 4) - pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 9)); /* load from memory to $8 */ + pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 9)); /* load from memory to $8 */ else if (size == 2) pracc_add(&ctx, 0, MIPS32_LHU(8, LOWER16(addr), 9)); else pracc_add(&ctx, 0, MIPS32_LBU(8, LOWER16(addr), 9)); pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + i * 4, - MIPS32_SW(8, PRACC_OUT_OFFSET + i * 4, 15)); /* store $8 at param out */ + MIPS32_SW(8, PRACC_OUT_OFFSET + i * 4, 15)); /* store $8 at param out */ addr += size; } pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */ pracc_add_li32(&ctx, 9, ejtag_info->reg9, 0); /* restore $9 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ + pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ if (size == 4) { - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf32); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf32, 1); if (ctx.retval != ERROR_OK) goto exit; buf32 += this_round_count; } else { - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, data); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, data, 1); if (ctx.retval != ERROR_OK) goto exit; @@ -550,16 +552,16 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_r struct pracc_queue_info ctx; pracc_queue_init(&ctx); - pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ pracc_add(&ctx, 0, MIPS32_MFC0(8, cp0_reg, cp0_sel)); /* move cp0 reg / sel to $8 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ + pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val, 1); pracc_queue_free(&ctx); return ctx.retval; } @@ -575,7 +577,7 @@ int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_r pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); pracc_queue_free(&ctx); return ctx.retval; } @@ -616,19 +618,19 @@ static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info, /** Find cache line size in bytes */ uint32_t clsiz; if (rel) { /* Release 2 (rel = 1) */ - pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ - pracc_add(&ctx, 0, MIPS32_RDHWR(8, MIPS32_SYNCI_STEP)); /* load synci_step value to $8 */ + pracc_add(&ctx, 0, MIPS32_RDHWR(8, MIPS32_SYNCI_STEP)); /* load synci_step value to $8 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ + pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, &clsiz); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, &clsiz, 1); if (ctx.retval != ERROR_OK) goto exit; @@ -689,7 +691,7 @@ static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info, pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_NOP); /* nop in delay slot */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); if (ctx.retval != ERROR_OK) goto exit; @@ -701,7 +703,7 @@ static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info, pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave*/ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); exit: pracc_queue_free(&ctx); return ctx.retval; @@ -755,7 +757,7 @@ static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info, pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); if (ctx.retval != ERROR_OK) goto exit; count -= this_round_count; @@ -847,7 +849,7 @@ int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[1])))); /* load lower half word in $1 */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); ejtag_info->reg8 = regs[8]; ejtag_info->reg9 = regs[9]; @@ -889,7 +891,7 @@ int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs, 1); ejtag_info->reg8 = regs[8]; /* reg8 is saved but not restored, next called function should restore it */ ejtag_info->reg9 = regs[9]; diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index 525d6e6..e990f8d 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -61,7 +61,7 @@ void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr); void pracc_add_li32(struct pracc_queue_info *ctx, uint32_t reg_num, uint32_t data, bool optimize); void pracc_queue_free(struct pracc_queue_info *ctx); int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, - struct pracc_queue_info *ctx, uint32_t *buf); + struct pracc_queue_info *ctx, uint32_t *buf, bool check_last); int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, void *buf); @@ -73,7 +73,8 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs); int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs); -int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, uint32_t *param_out); +int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ctx, + uint32_t *param_out, bool check_last); /** * \b mips32_cp0_read diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index 1a8a843..e35758d 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -210,7 +210,7 @@ int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step) pracc_add(&ctx, 0, MIPS32_B(NEG16((ctx.code_count + 1)))); /* jump to start */ pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); pracc_queue_free(&ctx); return ctx.retval; } @@ -273,7 +273,7 @@ int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info) struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = &pracc_list, .code_count = 1, .store_count = 0}; /* execute our dret instruction */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 0); /* pic32mx workaround, false pending at low core clock */ jtag_add_sleep(1000); -- cgit v1.1 From 6012a87d4464cdbf65ba46cb5c98d6113b5d7aea Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Mon, 27 Feb 2017 13:06:46 +0100 Subject: mips32, add microMips instruction subset Only reencoded MIPS32 instructions. Added some instructions for crc code. Micromips isa in debug mode is only needed for pic32mm cores. Pic32mz seems that only works with MIPS32 isa when in debug mode. Change-Id: I07059e153a7000ea9204f20b6b37edf6a7623455 Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4022 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips32.h | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) diff --git a/src/target/mips32.h b/src/target/mips32.h index 2e7067f..968c3f7 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -217,6 +217,101 @@ struct mips32_algorithm { #define MIPS32_SDBBP 0x7000003F /* MIPS32_J_INST(MIPS32_OP_SPECIAL2, MIPS32_OP_SDBBP) */ #define MIPS16_SDBBP 0xE801 +/*MICRO MIPS INSTRUCTIONS, see doc MD00582 */ +#define POOL32A 0X00u +#define POOL32AXf 0x3Cu +#define POOL32B 0x08u +#define POOL32I 0x10u +#define MMIPS32_OP_ADDI 0x04u +#define MMIPS32_OP_ADDIU 0x0Cu +#define MMIPS32_OP_ADDU 0x150u +#define MMIPS32_OP_AND 0x250u +#define MMIPS32_OP_ANDI 0x34u +#define MMIPS32_OP_BEQ 0x25u +#define MMIPS32_OP_BGTZ 0x06u +#define MMIPS32_OP_BNE 0x2Du +#define MMIPS32_OP_CACHE 0x06u +#define MMIPS32_OP_J 0x35u +#define MMIPS32_OP_JALR 0x03Cu +#define MMIPS32_OP_LB 0x07u +#define MMIPS32_OP_LBU 0x05u +#define MMIPS32_OP_LHU 0x0Du +#define MMIPS32_OP_LUI 0x0Du +#define MMIPS32_OP_LW 0x3Fu +#define MMIPS32_OP_MFC0 0x03u +#define MMIPS32_OP_MTC0 0x0Bu +#define MMIPS32_OP_MFLO 0x075u +#define MMIPS32_OP_MFHI 0x035u +#define MMIPS32_OP_MTLO 0x0F5u +#define MMIPS32_OP_MTHI 0x0B5u +#define MMIPS32_OP_MOVN 0x018u +#define MMIPS32_OP_ORI 0x14u +#define MMIPS32_OP_RDHWR 0x1ACu +#define MMIPS32_OP_SB 0x06u +#define MMIPS32_OP_SH 0x0Eu +#define MMIPS32_OP_SW 0x3Eu +#define MMIPS32_OP_SLTU 0x390u +#define MMIPS32_OP_SLL 0x000u +#define MMIPS32_OP_SLTI 0x24u +#define MMIPS32_OP_SRL 0x040u +#define MMIPS32_OP_SYNCI 0x10u +#define MMIPS32_OP_XOR 0x310u +#define MMIPS32_OP_XORI 0x1Cu + +#define MMIPS32_ADDI(tar, src, val) MIPS32_I_INST(MMIPS32_OP_ADDI, tar, src, val) +#define MMIPS32_ADDIU(tar, src, val) MIPS32_I_INST(MMIPS32_OP_ADDIU, tar, src, val) +#define MMIPS32_ADDU(dst, src, tar) MIPS32_R_INST(POOL32A, tar, src, dst, 0, MMIPS32_OP_ADDU) +#define MMIPS32_AND(dst, src, tar) MIPS32_R_INST(POOL32A, tar, src, dst, 0, MMIPS32_OP_AND) +#define MMIPS32_ANDI(tar, src, val) MIPS32_I_INST(MMIPS32_OP_ANDI, tar, src, val) + +#define MMIPS32_B(off) MMIPS32_BEQ(0, 0, off) +#define MMIPS32_BEQ(src, tar, off) MIPS32_I_INST(MMIPS32_OP_BEQ, tar, src, off) +#define MMIPS32_BGTZ(reg, off) MIPS32_I_INST(POOL32I, MMIPS32_OP_BGTZ, reg, off) +#define MMIPS32_BNE(src, tar, off) MIPS32_I_INST(MMIPS32_OP_BNE, tar, src, off) +#define MMIPS32_CACHE(op, off, base) MIPS32_R_INST(POOL32B, op, base, MMIPS32_OP_CACHE << 1, 0, off) + +#define MMIPS32_J(tar) MIPS32_J_INST(MMIPS32_OP_J, (0x07FFFFFFu & (tar)) >> 1) +#define MMIPS32_JR(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_JALR, POOL32AXf) +#define MMIPS32_LB(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LB, reg, base, off) +#define MMIPS32_LBU(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LBU, reg, base, off) +#define MMIPS32_LHU(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LHU, reg, base, off) +#define MMIPS32_LUI(reg, val) MIPS32_I_INST(POOL32I, MMIPS32_OP_LUI, reg, val) +#define MMIPS32_LW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LW, reg, base, off) + +#define MMIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(POOL32A, gpr, cpr, sel, MMIPS32_OP_MFC0, POOL32AXf) +#define MMIPS32_MFLO(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_MFLO, POOL32AXf) +#define MMIPS32_MFHI(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_MFHI, POOL32AXf) +#define MMIPS32_MTC0(gpr, cpr, sel) MIPS32_R_INST(POOL32A, gpr, cpr, sel, MMIPS32_OP_MTC0, POOL32AXf) +#define MMIPS32_MTLO(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_MTLO, POOL32AXf) +#define MMIPS32_MTHI(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_MTHI, POOL32AXf) + +#define MMIPS32_MOVN(dst, src, tar) MIPS32_R_INST(POOL32A, tar, src, dst, 0, MMIPS32_OP_MOVN) +#define MMIPS32_NOP 0 +#define MMIPS32_ORI(tar, src, val) MIPS32_I_INST(MMIPS32_OP_ORI, tar, src, val) +#define MMIPS32_RDHWR(tar, dst) MIPS32_R_INST(POOL32A, dst, tar, 0, MMIPS32_OP_RDHWR, POOL32AXf) +#define MMIPS32_SB(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SB, reg, base, off) +#define MMIPS32_SH(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SH, reg, base, off) +#define MMIPS32_SW(reg, off, base) MIPS32_I_INST(MMIPS32_OP_SW, reg, base, off) + +#define MMIPS32_SRL(reg, src, off) MIPS32_R_INST(POOL32A, reg, src, off, 0, MMIPS32_OP_SRL) +#define MMIPS32_SLTU(dst, src, tar) MIPS32_R_INST(POOL32A, tar, src, dst, 0, MMIPS32_OP_SLTU) +#define MMIPS32_SYNCI(off, base) MIPS32_I_INST(POOL32I, MMIPS32_OP_SYNCI, base, off) +#define MMIPS32_SLL(dst, src, sa) MIPS32_R_INST(POOL32A, dst, src, sa, 0, MMIPS32_OP_SLL) +#define MMIPS32_SLTI(tar, src, val) MIPS32_I_INST(MMIPS32_OP_SLTI, tar, src, val) +#define MMIPS32_SYNC 0x00001A7Cu /* MIPS32_R_INST(POOL32A, 0, 0, 0, 0x1ADu, POOL32AXf) */ + +#define MMIPS32_XOR(reg, val1, val2) MIPS32_R_INST(POOL32A, val1, val2, reg, 0, MMIPS32_OP_XOR) +#define MMIPS32_XORI(tar, src, val) MIPS32_I_INST(MMIPS32_OP_XORI, tar, src, val) + +#define MMIPS32_SYNCI_STEP 0x1u /* reg num od address step size to be used with synci instruction */ + + +/* ejtag specific instructions */ +#define MMIPS32_DRET 0x0000E37Cu /* MIPS32_R_INST(POOL32A, 0, 0, 0, 0x38D, POOL32AXf) */ +#define MMIPS32_SDBBP 0x0000DB7Cu /* MIPS32_R_INST(POOL32A, 0, 0, 0, 0x1BD, POOL32AXf) */ +#define MMIPS16_SDBBP 0x46C0u /* POOL16C instr */ + + extern const struct command_registration mips32_command_handlers[]; int mips32_arch_state(struct target *target); -- cgit v1.1 From 2279c23cdeaea05839a28ff3addf12b9b0f5357e Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Sun, 7 May 2017 11:58:25 +0200 Subject: mips32, add support for micromips in debug mode Micromips is 16bit oriented, branch and jumps are 16 bit based. The upper half 16bits of a 32bit instruction with the major opcode, must go first in the instruction stream, hence the SWAP16 macro and swap16 array function, needed if the code is written as 32 bit word in little endian cores. Endianess info added to ejtag_iinfo. Pointer to ejtag_info and isa field added to pracc context. MIPS32 code are renamed to MIPS32_ISA_... To select the isa, the new code has an additional isa parameter (1 for micromips, 0 for mips32). In JR instruction the isa bit must be set to execute micromips code. The suffix u is added to the OP codes to avoid signed/unsigned comparison errors and to make sure the right shift is performed logically. The isa in debug mode is updated in the poll function. Code for miniprograms, in kernel mode, need to be converted. CFI code only for mips32. Change-Id: I79a8b637d49b0e2d92b6dd5eb5aa8aa0520bf938 Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4032 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/flash/nor/cfi.c | 62 +++++----- src/target/mips32.c | 6 +- src/target/mips32.h | 224 ++++++++++++++++++++++------------ src/target/mips32_pracc.c | 304 ++++++++++++++++++++++++---------------------- src/target/mips32_pracc.h | 11 ++ src/target/mips_ejtag.c | 20 +-- src/target/mips_ejtag.h | 3 + src/target/mips_m4k.c | 14 ++- 8 files changed, 374 insertions(+), 270 deletions(-) diff --git a/src/flash/nor/cfi.c b/src/flash/nor/cfi.c index dca33f6..ac0db82 100644 --- a/src/flash/nor/cfi.c +++ b/src/flash/nor/cfi.c @@ -1424,50 +1424,50 @@ static int cfi_spansion_write_block_mips(struct flash_bank *bank, const uint8_t static const uint32_t mips_word_16_code[] = { /* start: */ - MIPS32_LHU(9, 0, 4), /* lhu $t1, ($a0) ; out = &saddr */ - MIPS32_ADDI(4, 4, 2), /* addi $a0, $a0, 2 ; saddr += 2 */ - MIPS32_SH(13, 0, 12), /* sh $t5, ($t4) ; *fl_unl_addr1 = fl_unl_cmd1 */ - MIPS32_SH(15, 0, 14), /* sh $t7, ($t6) ; *fl_unl_addr2 = fl_unl_cmd2 */ - MIPS32_SH(7, 0, 12), /* sh $a3, ($t4) ; *fl_unl_addr1 = fl_write_cmd */ - MIPS32_SH(9, 0, 5), /* sh $t1, ($a1) ; *daddr = out */ + MIPS32_LHU(0, 9, 0, 4), /* lhu $t1, ($a0) ; out = &saddr */ + MIPS32_ADDI(0, 4, 4, 2), /* addi $a0, $a0, 2 ; saddr += 2 */ + MIPS32_SH(0, 13, 0, 12), /* sh $t5, ($t4) ; *fl_unl_addr1 = fl_unl_cmd1 */ + MIPS32_SH(0, 15, 0, 14), /* sh $t7, ($t6) ; *fl_unl_addr2 = fl_unl_cmd2 */ + MIPS32_SH(0, 7, 0, 12), /* sh $a3, ($t4) ; *fl_unl_addr1 = fl_write_cmd */ + MIPS32_SH(0, 9, 0, 5), /* sh $t1, ($a1) ; *daddr = out */ MIPS32_NOP, /* nop */ /* busy: */ - MIPS32_LHU(10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ - MIPS32_XOR(11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ - MIPS32_AND(11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ - MIPS32_BNE(11, 8, 13), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ - MIPS32_NOP, /* nop */ - - MIPS32_SRL(10, 8, 2), /* srl $t2,$t0,2 ; temp1 = DQ7mask >> 2 */ - MIPS32_AND(11, 10, 11), /* and $t3, $t2, $t3 ; temp2 = temp2 & temp1 */ - MIPS32_BNE(11, 10, NEG16(8)), /* bne $t3, $t2, busy ; if (temp2 != temp1) goto busy */ - MIPS32_NOP, /* nop */ - - MIPS32_LHU(10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ - MIPS32_XOR(11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ - MIPS32_AND(11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ - MIPS32_BNE(11, 8, 4), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ + MIPS32_LHU(0, 10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ + MIPS32_XOR(0, 11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ + MIPS32_AND(0, 11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ + MIPS32_BNE(0, 11, 8, 13), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ + MIPS32_NOP, /* nop */ + + MIPS32_SRL(0, 10, 8, 2), /* srl $t2,$t0,2 ; temp1 = DQ7mask >> 2 */ + MIPS32_AND(0, 11, 10, 11), /* and $t3, $t2, $t3 ; temp2 = temp2 & temp1 */ + MIPS32_BNE(0, 11, 10, NEG16(8)), /* bne $t3, $t2, busy ; if (temp2 != temp1) goto busy */ + MIPS32_NOP, /* nop */ + + MIPS32_LHU(0, 10, 0, 5), /* lhu $t2, ($a1) ; temp1 = *daddr */ + MIPS32_XOR(0, 11, 9, 10), /* xor $t3, $a0, $t2 ; temp2 = out ^ temp1; */ + MIPS32_AND(0, 11, 8, 11), /* and $t3, $t0, $t3 ; temp2 = temp2 & DQ7mask */ + MIPS32_BNE(0, 11, 8, 4), /* bne $t3, $t0, cont ; if (temp2 != DQ7mask) goto cont */ MIPS32_NOP, /* nop */ - MIPS32_XOR(9, 9, 9), /* xor $t1, $t1, $t1 ; out = 0 */ - MIPS32_BEQ(9, 0, 11), /* beq $t1, $zero, done ; if (out == 0) goto done */ + MIPS32_XOR(0, 9, 9, 9), /* xor $t1, $t1, $t1 ; out = 0 */ + MIPS32_BEQ(0, 9, 0, 11), /* beq $t1, $zero, done ; if (out == 0) goto done */ MIPS32_NOP, /* nop */ /* cont: */ - MIPS32_ADDI(6, 6, NEG16(1)), /* addi, $a2, $a2, -1 ; numwrites-- */ - MIPS32_BNE(6, 0, 5), /* bne $a2, $zero, cont2 ; if (numwrite != 0) goto cont2 */ + MIPS32_ADDI(0, 6, 6, NEG16(1)), /* addi, $a2, $a2, -1 ; numwrites-- */ + MIPS32_BNE(0, 6, 0, 5), /* bne $a2, $zero, cont2 ; if (numwrite != 0) goto cont2 */ MIPS32_NOP, /* nop */ - MIPS32_LUI(9, 0), /* lui $t1, 0 */ - MIPS32_ORI(9, 9, 0x80), /* ori $t1, $t1, 0x80 ; out = 0x80 */ + MIPS32_LUI(0, 9, 0), /* lui $t1, 0 */ + MIPS32_ORI(0, 9, 9, 0x80), /* ori $t1, $t1, 0x80 ; out = 0x80 */ - MIPS32_B(4), /* b done ; goto done */ + MIPS32_B(0, 4), /* b done ; goto done */ MIPS32_NOP, /* nop */ /* cont2: */ - MIPS32_ADDI(5, 5, 2), /* addi $a0, $a0, 2 ; daddr += 2 */ - MIPS32_B(NEG16(33)), /* b start ; goto start */ + MIPS32_ADDI(0, 5, 5, 2), /* addi $a0, $a0, 2 ; daddr += 2 */ + MIPS32_B(0, NEG16(33)), /* b start ; goto start */ MIPS32_NOP, /* nop */ /* done: */ - MIPS32_SDBBP, /* sdbbp ; break(); */ + MIPS32_SDBBP(0), /* sdbbp ; break(); */ }; mips32_info.common_magic = MIPS32_COMMON_MAGIC; diff --git a/src/target/mips32.c b/src/target/mips32.c index cec4549..5c85fea 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -383,9 +383,11 @@ int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, s mips32->ejtag_info.tap = tap; mips32->read_core_reg = mips32_read_core_reg; mips32->write_core_reg = mips32_write_core_reg; - - mips32->ejtag_info.scan_delay = MIPS32_SCAN_DELAY_LEGACY_MODE; /* Initial default value */ + /* if unknown endianness defaults to little endian, 1 */ + mips32->ejtag_info.endianness = target->endianness == TARGET_BIG_ENDIAN ? 0 : 1; + mips32->ejtag_info.scan_delay = MIPS32_SCAN_DELAY_LEGACY_MODE; mips32->ejtag_info.mode = 0; /* Initial default value */ + mips32->ejtag_info.isa = 0; /* isa on debug mips32, updated by poll function */ return ERROR_OK; } diff --git a/src/target/mips32.h b/src/target/mips32.h index 968c3f7..d79451f 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -122,44 +122,49 @@ struct mips32_algorithm { enum mips32_isa_mode isa_mode; }; -#define MIPS32_OP_ADDIU 0x21 -#define MIPS32_OP_ANDI 0x0C -#define MIPS32_OP_BEQ 0x04 -#define MIPS32_OP_BGTZ 0x07 -#define MIPS32_OP_BNE 0x05 -#define MIPS32_OP_ADDI 0x08 -#define MIPS32_OP_AND 0x24 -#define MIPS32_OP_CACHE 0x2F -#define MIPS32_OP_COP0 0x10 -#define MIPS32_OP_J 0x02 -#define MIPS32_OP_JR 0x08 -#define MIPS32_OP_LUI 0x0F -#define MIPS32_OP_LW 0x23 -#define MIPS32_OP_LBU 0x24 -#define MIPS32_OP_LHU 0x25 -#define MIPS32_OP_MFHI 0x10 -#define MIPS32_OP_MTHI 0x11 -#define MIPS32_OP_MFLO 0x12 -#define MIPS32_OP_MTLO 0x13 -#define MIPS32_OP_RDHWR 0x3B -#define MIPS32_OP_SB 0x28 -#define MIPS32_OP_SH 0x29 -#define MIPS32_OP_SW 0x2B -#define MIPS32_OP_ORI 0x0D -#define MIPS32_OP_XORI 0x0E -#define MIPS32_OP_XOR 0x26 -#define MIPS32_OP_SLTU 0x2B -#define MIPS32_OP_SRL 0x03 -#define MIPS32_OP_SYNCI 0x1F - -#define MIPS32_OP_REGIMM 0x01 -#define MIPS32_OP_SDBBP 0x3F -#define MIPS32_OP_SPECIAL 0x00 -#define MIPS32_OP_SPECIAL2 0x07 -#define MIPS32_OP_SPECIAL3 0x1F - -#define MIPS32_COP0_MF 0x00 -#define MIPS32_COP0_MT 0x04 +#define MIPS32_OP_ADDU 0x21u +#define MIPS32_OP_ADDIU 0x09u +#define MIPS32_OP_ANDI 0x0Cu +#define MIPS32_OP_BEQ 0x04u +#define MIPS32_OP_BGTZ 0x07u +#define MIPS32_OP_BNE 0x05u +#define MIPS32_OP_ADDI 0x08u +#define MIPS32_OP_AND 0x24u +#define MIPS32_OP_CACHE 0x2Fu +#define MIPS32_OP_COP0 0x10u +#define MIPS32_OP_J 0x02u +#define MIPS32_OP_JR 0x08u +#define MIPS32_OP_LUI 0x0Fu +#define MIPS32_OP_LW 0x23u +#define MIPS32_OP_LB 0x20u +#define MIPS32_OP_LBU 0x24u +#define MIPS32_OP_LHU 0x25u +#define MIPS32_OP_MFHI 0x10u +#define MIPS32_OP_MTHI 0x11u +#define MIPS32_OP_MFLO 0x12u +#define MIPS32_OP_MTLO 0x13u +#define MIPS32_OP_RDHWR 0x3Bu +#define MIPS32_OP_SB 0x28u +#define MIPS32_OP_SH 0x29u +#define MIPS32_OP_SW 0x2Bu +#define MIPS32_OP_ORI 0x0Du +#define MIPS32_OP_XORI 0x0Eu +#define MIPS32_OP_XOR 0x26u +#define MIPS32_OP_SLTU 0x2Bu +#define MIPS32_OP_SRL 0x03u +#define MIPS32_OP_SYNCI 0x1Fu +#define MIPS32_OP_SLL 0x00u +#define MIPS32_OP_SLTI 0x0Au +#define MIPS32_OP_MOVN 0x0Bu + +#define MIPS32_OP_REGIMM 0x01u +#define MIPS32_OP_SDBBP 0x3Fu +#define MIPS32_OP_SPECIAL 0x00u +#define MIPS32_OP_SPECIAL2 0x07u +#define MIPS32_OP_SPECIAL3 0x1Fu + +#define MIPS32_COP0_MF 0x00u +#define MIPS32_COP0_MT 0x04u #define MIPS32_R_INST(opcode, rs, rt, rd, shamt, funct) \ (((opcode) << 26) | ((rs) << 21) | ((rt) << 16) | ((rd) << 11) | ((shamt) << 6) | (funct)) @@ -167,41 +172,52 @@ struct mips32_algorithm { (((opcode) << 26) | ((rs) << 21) | ((rt) << 16) | (immd)) #define MIPS32_J_INST(opcode, addr) (((opcode) << 26) | (addr)) -#define MIPS32_NOP 0 -#define MIPS32_ADDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDI, src, tar, val) -#define MIPS32_ADDU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_ADDIU) -#define MIPS32_AND(reg, off, val) MIPS32_R_INST(0, off, val, reg, 0, MIPS32_OP_AND) -#define MIPS32_ANDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ANDI, src, tar, val) -#define MIPS32_B(off) MIPS32_BEQ(0, 0, off) -#define MIPS32_BEQ(src, tar, off) MIPS32_I_INST(MIPS32_OP_BEQ, src, tar, off) -#define MIPS32_BGTZ(reg, off) MIPS32_I_INST(MIPS32_OP_BGTZ, reg, 0, off) -#define MIPS32_BNE(src, tar, off) MIPS32_I_INST(MIPS32_OP_BNE, src, tar, off) -#define MIPS32_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off) -#define MIPS32_J(tar) MIPS32_J_INST(MIPS32_OP_J, tar) -#define MIPS32_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR) -#define MIPS32_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MF, gpr, cpr, 0, sel) -#define MIPS32_MTC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MT, gpr, cpr, 0, sel) -#define MIPS32_LBU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LBU, base, reg, off) -#define MIPS32_LHU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LHU, base, reg, off) -#define MIPS32_LUI(reg, val) MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val) -#define MIPS32_LW(reg, off, base) MIPS32_I_INST(MIPS32_OP_LW, base, reg, off) -#define MIPS32_MFLO(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO) -#define MIPS32_MFHI(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI) -#define MIPS32_MTLO(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTLO) -#define MIPS32_MTHI(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTHI) -#define MIPS32_ORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ORI, src, tar, val) -#define MIPS32_XORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_XORI, src, tar, val) -#define MIPS32_RDHWR(tar, dst) MIPS32_R_INST(MIPS32_OP_SPECIAL3, 0, tar, dst, 0, MIPS32_OP_RDHWR) -#define MIPS32_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off) -#define MIPS32_SH(reg, off, base) MIPS32_I_INST(MIPS32_OP_SH, base, reg, off) -#define MIPS32_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off) -#define MIPS32_XOR(reg, val1, val2) MIPS32_R_INST(0, val1, val2, reg, 0, MIPS32_OP_XOR) -#define MIPS32_SRL(reg, src, off) MIPS32_R_INST(0, 0, src, reg, off, MIPS32_OP_SRL) -#define MIPS32_SLTU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_SLTU) -#define MIPS32_SYNCI(off, base) MIPS32_I_INST(MIPS32_OP_REGIMM, base, MIPS32_OP_SYNCI, off) - -#define MIPS32_SYNC 0xF -#define MIPS32_SYNCI_STEP 0x1 /* reg num od address step size to be used with synci instruction */ +#define MIPS32_ISA_NOP 0 +#define MIPS32_ISA_ADDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDI, src, tar, val) +#define MIPS32_ISA_ADDIU(tar, src, val) MIPS32_I_INST(MIPS32_OP_ADDIU, src, tar, val) +#define MIPS32_ISA_ADDU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_ADDU) +#define MIPS32_ISA_AND(dst, src, tar) MIPS32_R_INST(0, src, tar, dst, 0, MIPS32_OP_AND) +#define MIPS32_ISA_ANDI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ANDI, src, tar, val) + +#define MIPS32_ISA_B(off) MIPS32_ISA_BEQ(0, 0, off) +#define MIPS32_ISA_BEQ(src, tar, off) MIPS32_I_INST(MIPS32_OP_BEQ, src, tar, off) +#define MIPS32_ISA_BGTZ(reg, off) MIPS32_I_INST(MIPS32_OP_BGTZ, reg, 0, off) +#define MIPS32_ISA_BNE(src, tar, off) MIPS32_I_INST(MIPS32_OP_BNE, src, tar, off) +#define MIPS32_ISA_CACHE(op, off, base) MIPS32_I_INST(MIPS32_OP_CACHE, base, op, off) +#define MIPS32_ISA_J(tar) MIPS32_J_INST(MIPS32_OP_J, (0x0FFFFFFFu & (tar)) >> 2) +#define MIPS32_ISA_JR(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_JR) + +#define MIPS32_ISA_LB(reg, off, base) MIPS32_I_INST(MIPS32_OP_LB, base, reg, off) +#define MIPS32_ISA_LBU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LBU, base, reg, off) +#define MIPS32_ISA_LHU(reg, off, base) MIPS32_I_INST(MIPS32_OP_LHU, base, reg, off) +#define MIPS32_ISA_LUI(reg, val) MIPS32_I_INST(MIPS32_OP_LUI, 0, reg, val) +#define MIPS32_ISA_LW(reg, off, base) MIPS32_I_INST(MIPS32_OP_LW, base, reg, off) + +#define MIPS32_ISA_MFC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MF, gpr, cpr, 0, sel) +#define MIPS32_ISA_MTC0(gpr, cpr, sel) MIPS32_R_INST(MIPS32_OP_COP0, MIPS32_COP0_MT, gpr, cpr, 0, sel) +#define MIPS32_ISA_MFLO(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFLO) +#define MIPS32_ISA_MFHI(reg) MIPS32_R_INST(0, 0, 0, reg, 0, MIPS32_OP_MFHI) +#define MIPS32_ISA_MTLO(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTLO) +#define MIPS32_ISA_MTHI(reg) MIPS32_R_INST(0, reg, 0, 0, 0, MIPS32_OP_MTHI) + +#define MIPS32_ISA_MOVN(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_MOVN) +#define MIPS32_ISA_ORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_ORI, src, tar, val) +#define MIPS32_ISA_RDHWR(tar, dst) MIPS32_R_INST(MIPS32_OP_SPECIAL3, 0, tar, dst, 0, MIPS32_OP_RDHWR) +#define MIPS32_ISA_SB(reg, off, base) MIPS32_I_INST(MIPS32_OP_SB, base, reg, off) +#define MIPS32_ISA_SH(reg, off, base) MIPS32_I_INST(MIPS32_OP_SH, base, reg, off) +#define MIPS32_ISA_SW(reg, off, base) MIPS32_I_INST(MIPS32_OP_SW, base, reg, off) + +#define MIPS32_ISA_SLL(dst, src, sa) MIPS32_R_INST(MIPS32_OP_SPECIAL, 0, src, dst, sa, MIPS32_OP_SLL) +#define MIPS32_ISA_SLTI(tar, src, val) MIPS32_I_INST(MIPS32_OP_SLTI, src, tar, val) +#define MIPS32_ISA_SLTU(dst, src, tar) MIPS32_R_INST(MIPS32_OP_SPECIAL, src, tar, dst, 0, MIPS32_OP_SLTU) +#define MIPS32_ISA_SRL(reg, src, off) MIPS32_R_INST(0, 0, src, reg, off, MIPS32_OP_SRL) +#define MIPS32_ISA_SYNC 0xFu +#define MIPS32_ISA_SYNCI(off, base) MIPS32_I_INST(MIPS32_OP_REGIMM, base, MIPS32_OP_SYNCI, off) + +#define MIPS32_ISA_XOR(reg, val1, val2) MIPS32_R_INST(0, val1, val2, reg, 0, MIPS32_OP_XOR) +#define MIPS32_ISA_XORI(tar, src, val) MIPS32_I_INST(MIPS32_OP_XORI, src, tar, val) + +#define MIPS32_ISA_SYNCI_STEP 0x1 /* reg num od address step size to be used with synci instruction */ /** * Cache operations definitions @@ -213,9 +229,10 @@ struct mips32_algorithm { #define MIPS32_CACHE_I_HIT_INVALIDATE ((0x0 << 0) | (0x4 << 2)) /* ejtag specific instructions */ -#define MIPS32_DRET 0x4200001F -#define MIPS32_SDBBP 0x7000003F /* MIPS32_J_INST(MIPS32_OP_SPECIAL2, MIPS32_OP_SDBBP) */ -#define MIPS16_SDBBP 0xE801 +#define MIPS32_ISA_DRET 0x4200001Fu +/* MIPS32_ISA_J_INST(MIPS32_ISA_OP_SPECIAL2, MIPS32_ISA_OP_SDBBP) */ +#define MIPS32_ISA_SDBBP 0x7000003Fu +#define MIPS16_ISA_SDBBP 0xE801u /*MICRO MIPS INSTRUCTIONS, see doc MD00582 */ #define POOL32A 0X00u @@ -270,7 +287,7 @@ struct mips32_algorithm { #define MMIPS32_BNE(src, tar, off) MIPS32_I_INST(MMIPS32_OP_BNE, tar, src, off) #define MMIPS32_CACHE(op, off, base) MIPS32_R_INST(POOL32B, op, base, MMIPS32_OP_CACHE << 1, 0, off) -#define MMIPS32_J(tar) MIPS32_J_INST(MMIPS32_OP_J, (0x07FFFFFFu & (tar)) >> 1) +#define MMIPS32_J(tar) MIPS32_J_INST(MMIPS32_OP_J, ((0x07FFFFFFu & ((tar) >> 1)))) #define MMIPS32_JR(reg) MIPS32_R_INST(POOL32A, 0, reg, 0, MMIPS32_OP_JALR, POOL32AXf) #define MMIPS32_LB(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LB, reg, base, off) #define MMIPS32_LBU(reg, off, base) MIPS32_I_INST(MMIPS32_OP_LBU, reg, base, off) @@ -311,6 +328,59 @@ struct mips32_algorithm { #define MMIPS32_SDBBP 0x0000DB7Cu /* MIPS32_R_INST(POOL32A, 0, 0, 0, 0x1BD, POOL32AXf) */ #define MMIPS16_SDBBP 0x46C0u /* POOL16C instr */ +/* instruction code with isa selection */ +#define MIPS32_NOP 0 /* same for both isa's */ +#define MIPS32_ADDI(isa, tar, src, val) (isa ? MMIPS32_ADDI(tar, src, val) : MIPS32_ISA_ADDI(tar, src, val)) +#define MIPS32_ADDIU(isa, tar, src, val) (isa ? MMIPS32_ADDIU(tar, src, val) : MIPS32_ISA_ADDIU(tar, src, val)) +#define MIPS32_ADDU(isa, dst, src, tar) (isa ? MMIPS32_ADDU(dst, src, tar) : MIPS32_ISA_ADDU(dst, src, tar)) +#define MIPS32_AND(isa, dst, src, tar) (isa ? MMIPS32_AND(dst, src, tar) : MIPS32_ISA_AND(dst, src, tar)) +#define MIPS32_ANDI(isa, tar, src, val) (isa ? MMIPS32_ANDI(tar, src, val) : MIPS32_ISA_ANDI(tar, src, val)) + +#define MIPS32_B(isa, off) (isa ? MMIPS32_B(off) : MIPS32_ISA_B(off)) +#define MIPS32_BEQ(isa, src, tar, off) (isa ? MMIPS32_BEQ(src, tar, off) : MIPS32_ISA_BEQ(src, tar, off)) +#define MIPS32_BGTZ(isa, reg, off) (isa ? MMIPS32_BGTZ(reg, off) : MIPS32_ISA_BGTZ(reg, off)) +#define MIPS32_BNE(isa, src, tar, off) (isa ? MMIPS32_BNE(src, tar, off) : MIPS32_ISA_BNE(src, tar, off)) +#define MIPS32_CACHE(isa, op, off, base) (isa ? MMIPS32_CACHE(op, off, base) : MIPS32_ISA_CACHE(op, off, base)) + +#define MIPS32_J(isa, tar) (isa ? MMIPS32_J(tar) : MIPS32_ISA_J(tar)) +#define MIPS32_JR(isa, reg) (isa ? MMIPS32_JR(reg) : MIPS32_ISA_JR(reg)) +#define MIPS32_LB(isa, reg, off, base) (isa ? MMIPS32_LB(reg, off, base) : MIPS32_ISA_LB(reg, off, base)) +#define MIPS32_LBU(isa, reg, off, base) (isa ? MMIPS32_LBU(reg, off, base) : MIPS32_ISA_LBU(reg, off, base)) +#define MIPS32_LHU(isa, reg, off, base) (isa ? MMIPS32_LHU(reg, off, base) : MIPS32_ISA_LHU(reg, off, base)) +#define MIPS32_LW(isa, reg, off, base) (isa ? MMIPS32_LW(reg, off, base) : MIPS32_ISA_LW(reg, off, base)) +#define MIPS32_LUI(isa, reg, val) (isa ? MMIPS32_LUI(reg, val) : MIPS32_ISA_LUI(reg, val)) + +#define MIPS32_MFC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MFC0(gpr, cpr, sel) : MIPS32_ISA_MFC0(gpr, cpr, sel)) +#define MIPS32_MTC0(isa, gpr, cpr, sel) (isa ? MMIPS32_MTC0(gpr, cpr, sel) : MIPS32_ISA_MTC0(gpr, cpr, sel)) +#define MIPS32_MFLO(isa, reg) (isa ? MMIPS32_MFLO(reg) : MIPS32_ISA_MFLO(reg)) +#define MIPS32_MFHI(isa, reg) (isa ? MMIPS32_MFHI(reg) : MIPS32_ISA_MFHI(reg)) +#define MIPS32_MTLO(isa, reg) (isa ? MMIPS32_MTLO(reg) : MIPS32_ISA_MTLO(reg)) +#define MIPS32_MTHI(isa, reg) (isa ? MMIPS32_MTHI(reg) : MIPS32_ISA_MTHI(reg)) + +#define MIPS32_MOVN(isa, dst, src, tar) (isa ? MMIPS32_MOVN(dst, src, tar) : MIPS32_ISA_MOVN(dst, src, tar)) +#define MIPS32_ORI(isa, tar, src, val) (isa ? MMIPS32_ORI(tar, src, val) : MIPS32_ISA_ORI(tar, src, val)) +#define MIPS32_RDHWR(isa, tar, dst) (isa ? MMIPS32_RDHWR(tar, dst) : MIPS32_ISA_RDHWR(tar, dst)) +#define MIPS32_SB(isa, reg, off, base) (isa ? MMIPS32_SB(reg, off, base) : MIPS32_ISA_SB(reg, off, base)) +#define MIPS32_SH(isa, reg, off, base) (isa ? MMIPS32_SH(reg, off, base) : MIPS32_ISA_SH(reg, off, base)) +#define MIPS32_SW(isa, reg, off, base) (isa ? MMIPS32_SW(reg, off, base) : MIPS32_ISA_SW(reg, off, base)) + +#define MIPS32_SLL(isa, dst, src, sa) (isa ? MMIPS32_SLL(dst, src, sa) : MIPS32_ISA_SLL(dst, src, sa)) +#define MIPS32_SLTI(isa, tar, src, val) (isa ? MMIPS32_SLTI(tar, src, val) : MIPS32_ISA_SLTI(tar, src, val)) +#define MIPS32_SLTU(isa, dst, src, tar) (isa ? MMIPS32_SLTU(dst, src, tar) : MIPS32_ISA_SLTU(dst, src, tar)) +#define MIPS32_SRL(isa, reg, src, off) (isa ? MMIPS32_SRL(reg, src, off) : MIPS32_ISA_SRL(reg, src, off)) + +#define MIPS32_SYNCI(isa, off, base) (isa ? MMIPS32_SYNCI(off, base) : MIPS32_ISA_SYNCI(off, base)) +#define MIPS32_SYNC(isa) (isa ? MMIPS32_SYNC : MIPS32_ISA_SYNC) +#define MIPS32_XOR(isa, reg, val1, val2) (isa ? MMIPS32_XOR(reg, val1, val2) : MIPS32_ISA_XOR(reg, val1, val2)) +#define MIPS32_XORI(isa, tar, src, val) (isa ? MMIPS32_XORI(tar, src, val) : MIPS32_ISA_XORI(tar, src, val)) + +#define MIPS32_SYNCI_STEP 0x1 + +/* ejtag specific instructions */ +#define MIPS32_DRET(isa) (isa ? MMIPS32_DRET : MIPS32_ISA_DRET) +#define MIPS32_SDBBP(isa) (isa ? MMIPS32_SDBBP : MIPS32_ISA_SDBBP) + +#define MIPS16_SDBBP(isa) (isa ? MMIPS16_SDBBP : MIPS16_ISA_SDBBP) extern const struct command_registration mips32_command_handlers[]; diff --git a/src/target/mips32_pracc.c b/src/target/mips32_pracc.c index 7324246..790c8dc 100644 --- a/src/target/mips32_pracc.c +++ b/src/target/mips32_pracc.c @@ -122,8 +122,8 @@ static void mips32_pracc_finish(struct mips_ejtag *ejtag_info) int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info) { - uint32_t jt_code = MIPS32_J((0x0FFFFFFF & MIPS32_PRACC_TEXT) >> 2); - + uint32_t jt_code = MIPS32_J(ejtag_info->isa, MIPS32_PRACC_TEXT); + pracc_swap16_array(ejtag_info, &jt_code, 1); /* do 3 0/nops to clean pipeline before a jump to pracc text, NOP in delay slot */ for (int i = 0; i != 5; i++) { /* Wait for pracc */ @@ -148,7 +148,7 @@ int mips32_pracc_clean_text_jump(struct mips_ejtag *ejtag_info) if (retval != ERROR_OK) return retval; - if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT) { /* LEXRA/BMIPS ?, shift out another NOP, max 2 */ + if (ejtag_info->pa_addr != MIPS32_PRACC_TEXT) { /* LEXRA/BMIPS ?, shift out another NOP, max 2 */ mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); mips_ejtag_drscan_32_out(ejtag_info, MIPS32_NOP); mips32_pracc_finish(ejtag_info); @@ -163,7 +163,7 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct uint32_t *param_out, bool check_last) { int code_count = 0; - int store_pending = 0; /* increases with every store instruction at dmseg, decreases with every store pa */ + int store_pending = 0; /* increases with every store instr at dmseg, decreases with every store pa */ uint32_t max_store_addr = 0; /* for store pa address testing */ bool restart = 0; /* restarting control */ int restart_count = 0; @@ -186,12 +186,12 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct LOG_DEBUG("restarting code"); } - retval = mips32_pracc_read_ctrl_addr(ejtag_info); /* update current pa info: control and address */ + retval = mips32_pracc_read_ctrl_addr(ejtag_info); /* update current pa info: control and address */ if (retval != ERROR_OK) return retval; /* Check for read or write access */ - if (ejtag_info->pa_ctrl & EJTAG_CTRL_PRNW) { /* write/store access */ + if (ejtag_info->pa_ctrl & EJTAG_CTRL_PRNW) { /* write/store access */ /* Check for pending store from a previous store instruction at dmseg */ if (store_pending == 0) { LOG_DEBUG("unexpected write at address %" PRIx32, ejtag_info->pa_addr); @@ -202,8 +202,8 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct return ERROR_JTAG_DEVICE_ERROR; } else { /* check address */ - if (ejtag_info->pa_addr < MIPS32_PRACC_PARAM_OUT || ejtag_info->pa_addr > max_store_addr) { - + if (ejtag_info->pa_addr < MIPS32_PRACC_PARAM_OUT || + ejtag_info->pa_addr > max_store_addr) { LOG_DEBUG("writing at unexpected address %" PRIx32, ejtag_info->pa_addr); return ERROR_JTAG_DEVICE_ERROR; } @@ -227,7 +227,8 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct ejtag_info->pa_addr, MIPS32_PRACC_TEXT + code_count * 4); /* restart code execution only in some cases */ - if (code_count == 1 && ejtag_info->pa_addr == MIPS32_PRACC_TEXT && restart_count == 0) { + if (code_count == 1 && ejtag_info->pa_addr == MIPS32_PRACC_TEXT && + restart_count == 0) { LOG_DEBUG("restarting, without clean jump"); restart_count++; code_count = 0; @@ -264,13 +265,14 @@ int mips32_pracc_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_info *ct } } else { if (ejtag_info->pa_addr != (MIPS32_PRACC_TEXT + code_count * 4)) { - LOG_DEBUG("unexpected read address in final check: %" PRIx32 ", expected: %x", - ejtag_info->pa_addr, MIPS32_PRACC_TEXT + code_count * 4); + LOG_DEBUG("unexpected read address in final check: %" + PRIx32 ", expected: %x", ejtag_info->pa_addr, + MIPS32_PRACC_TEXT + code_count * 4); return ERROR_JTAG_DEVICE_ERROR; } } if (!pass) { - if ((code_count - ctx->code_count) > 1) { /* allow max 2 instruction delay slot */ + if ((code_count - ctx->code_count) > 1) { /* allow max 2 instr delay slot */ LOG_DEBUG("failed to jump back to pracc text"); return ERROR_JTAG_DEVICE_ERROR; } @@ -307,6 +309,7 @@ inline void pracc_queue_init(struct pracc_queue_info *ctx) ctx->store_count = 0; ctx->max_code = 0; ctx->pracc_list = NULL; + ctx->isa = ctx->ejtag_info->isa ? 1 : 0; } void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr) @@ -332,12 +335,12 @@ void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr) void pracc_add_li32(struct pracc_queue_info *ctx, uint32_t reg_num, uint32_t data, bool optimize) { if (LOWER16(data) == 0 && optimize) - pracc_add(ctx, 0, MIPS32_LUI(reg_num, UPPER16(data))); /* load only upper value */ + pracc_add(ctx, 0, MIPS32_LUI(ctx->isa, reg_num, UPPER16(data))); /* load only upper value */ else if (UPPER16(data) == 0 && optimize) - pracc_add(ctx, 0, MIPS32_ORI(reg_num, 0, LOWER16(data))); /* load only lower */ + pracc_add(ctx, 0, MIPS32_ORI(ctx->isa, reg_num, 0, LOWER16(data))); /* load only lower */ else { - pracc_add(ctx, 0, MIPS32_LUI(reg_num, UPPER16(data))); /* load upper and lower */ - pracc_add(ctx, 0, MIPS32_ORI(reg_num, reg_num, LOWER16(data))); + pracc_add(ctx, 0, MIPS32_LUI(ctx->isa, reg_num, UPPER16(data))); /* load upper and lower */ + pracc_add(ctx, 0, MIPS32_ORI(ctx->isa, reg_num, reg_num, LOWER16(data))); } } @@ -355,6 +358,10 @@ int mips32_pracc_queue_exec(struct mips_ejtag *ejtag_info, struct pracc_queue_in return ERROR_FAIL; } + if (ejtag_info->isa && ejtag_info->endianness) + for (int i = 0; i != ctx->code_count; i++) + ctx->pracc_list[i].instr = SWAP16(ctx->pracc_list[i].instr); + if (ejtag_info->mode == 0) return mips32_pracc_exec(ejtag_info, ctx, buf, check_last); @@ -449,17 +456,17 @@ exit: int mips32_pracc_read_u32(struct mips_ejtag *ejtag_info, uint32_t addr, uint32_t *buf) { - struct pracc_queue_info ctx; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16((addr + 0x8000)))); /* load $8 with modified upper address */ - pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 8)); /* lw $8, LOWER16(addr)($8) */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 8, UPPER16((addr + 0x8000)))); /* load $8 with modified upper addr */ + pracc_add(&ctx, 0, MIPS32_LW(ctx.isa, 8, LOWER16(addr), 8)); /* lw $8, LOWER16(addr)($8) */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, - MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* sw $8,PRACC_OUT_OFFSET($15) */ + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15)); /* sw $8,PRACC_OUT_OFFSET($15) */ pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* move COP0 DeSave to $15 */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* move COP0 DeSave to $15 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf, 1); pracc_queue_free(&ctx); @@ -471,10 +478,10 @@ int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size if (count == 1 && size == 4) return mips32_pracc_read_u32(ejtag_info, addr, (uint32_t *)buf); - uint32_t *data = NULL; - struct pracc_queue_info ctx; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); + uint32_t *data = NULL; if (size != 4) { data = malloc(256 * sizeof(uint32_t)); if (data == NULL) { @@ -490,35 +497,36 @@ int mips32_pracc_read_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int size while (count) { ctx.code_count = 0; ctx.store_count = 0; + int this_round_count = (count > 256) ? 256 : count; uint32_t last_upper_base_addr = UPPER16((addr + 0x8000)); - pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ - pracc_add(&ctx, 0, MIPS32_LUI(9, last_upper_base_addr)); /* load the upper memory address in $9 */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 9, last_upper_base_addr)); /* upper memory addr to $9 */ for (int i = 0; i != this_round_count; i++) { /* Main code loop */ uint32_t upper_base_addr = UPPER16((addr + 0x8000)); - if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $9 */ - pracc_add(&ctx, 0, MIPS32_LUI(9, upper_base_addr)); + if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper addr in $9 */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 9, upper_base_addr)); last_upper_base_addr = upper_base_addr; } - if (size == 4) - pracc_add(&ctx, 0, MIPS32_LW(8, LOWER16(addr), 9)); /* load from memory to $8 */ + if (size == 4) /* load from memory to $8 */ + pracc_add(&ctx, 0, MIPS32_LW(ctx.isa, 8, LOWER16(addr), 9)); else if (size == 2) - pracc_add(&ctx, 0, MIPS32_LHU(8, LOWER16(addr), 9)); + pracc_add(&ctx, 0, MIPS32_LHU(ctx.isa, 8, LOWER16(addr), 9)); else - pracc_add(&ctx, 0, MIPS32_LBU(8, LOWER16(addr), 9)); + pracc_add(&ctx, 0, MIPS32_LBU(ctx.isa, 8, LOWER16(addr), 9)); - pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + i * 4, - MIPS32_SW(8, PRACC_OUT_OFFSET + i * 4, 15)); /* store $8 at param out */ + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + i * 4, /* store $8 at param out */ + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + i * 4, 15)); addr += size; } pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */ pracc_add_li32(&ctx, 9, ejtag_info->reg9, 0); /* restore $9 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */ if (size == 4) { ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, buf32, 1); @@ -549,17 +557,17 @@ exit: int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_reg, uint32_t cp0_sel) { - struct pracc_queue_info ctx; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ - pracc_add(&ctx, 0, MIPS32_MFC0(8, cp0_reg, cp0_sel)); /* move cp0 reg / sel to $8 */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 8, cp0_reg, cp0_sel)); /* move cp0 reg / sel to $8 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, - MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, val, 1); pracc_queue_free(&ctx); @@ -568,14 +576,14 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, uint32_t *val, uint32_t cp0_r int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel) { - struct pracc_queue_info ctx; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); pracc_add_li32(&ctx, 15, val, 0); /* Load val to $15 */ - pracc_add(&ctx, 0, MIPS32_MTC0(15, cp0_reg, cp0_sel)); /* write $15 to cp0 reg / sel */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ + pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, cp0_reg, cp0_sel)); /* write $15 to cp0 reg / sel */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); pracc_queue_free(&ctx); @@ -612,23 +620,23 @@ int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_r static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info, uint32_t start_addr, uint32_t end_addr, int cached, int rel) { - struct pracc_queue_info ctx; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); /** Find cache line size in bytes */ uint32_t clsiz; if (rel) { /* Release 2 (rel = 1) */ - pracc_add(&ctx, 0, MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, PRACC_UPPER_BASE_ADDR)); /* $15 = MIPS32_PRACC_BASE_ADDR */ - pracc_add(&ctx, 0, MIPS32_RDHWR(8, MIPS32_SYNCI_STEP)); /* load synci_step value to $8 */ + pracc_add(&ctx, 0, MIPS32_RDHWR(ctx.isa, 8, MIPS32_SYNCI_STEP)); /* load synci_step value to $8 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT, - MIPS32_SW(8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET, 15)); /* store $8 to pracc_out */ pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, &clsiz, 1); if (ctx.retval != ERROR_OK) @@ -663,45 +671,48 @@ static int mips32_pracc_synchronize_cache(struct mips_ejtag *ejtag_info, end_addr |= clsiz - 1; ctx.code_count = 0; + ctx.store_count = 0; + int count = 0; uint32_t last_upper_base_addr = UPPER16((start_addr + 0x8000)); - pracc_add(&ctx, 0, MIPS32_LUI(15, last_upper_base_addr)); /* load upper memory base address to $15 */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, last_upper_base_addr)); /* load upper memory base addr to $15 */ while (start_addr <= end_addr) { /* main loop */ uint32_t upper_base_addr = UPPER16((start_addr + 0x8000)); - if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $15 */ - pracc_add(&ctx, 0, MIPS32_LUI(15, upper_base_addr)); + if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper addr in $15 */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, upper_base_addr)); last_upper_base_addr = upper_base_addr; } - if (rel) - pracc_add(&ctx, 0, MIPS32_SYNCI(LOWER16(start_addr), 15)); /* synci instruction, offset($15) */ + if (rel) /* synci instruction, offset($15) */ + pracc_add(&ctx, 0, MIPS32_SYNCI(ctx.isa, LOWER16(start_addr), 15)); else { - if (cached == 3) - pracc_add(&ctx, 0, MIPS32_CACHE(MIPS32_CACHE_D_HIT_WRITEBACK, - LOWER16(start_addr), 15)); /* cache Hit_Writeback_D, offset($15) */ - - pracc_add(&ctx, 0, MIPS32_CACHE(MIPS32_CACHE_I_HIT_INVALIDATE, - LOWER16(start_addr), 15)); /* cache Hit_Invalidate_I, offset($15) */ + if (cached == 3) /* cache Hit_Writeback_D, offset($15) */ + pracc_add(&ctx, 0, MIPS32_CACHE(ctx.isa, MIPS32_CACHE_D_HIT_WRITEBACK, + LOWER16(start_addr), 15)); + /* cache Hit_Invalidate_I, offset($15) */ + pracc_add(&ctx, 0, MIPS32_CACHE(ctx.isa, MIPS32_CACHE_I_HIT_INVALIDATE, + LOWER16(start_addr), 15)); } start_addr += clsiz; count++; - if (count == 256 && start_addr <= end_addr) { /* more ?, then execute code list */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_NOP); /* nop in delay slot */ + if (count == 256 && start_addr <= end_addr) { /* more ?, then execute code list */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* to start */ + pracc_add(&ctx, 0, MIPS32_NOP); /* nop in delay slot */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); if (ctx.retval != ERROR_OK) goto exit; - ctx.code_count = 0; + ctx.code_count = 0; /* reset counters for another loop */ + ctx.store_count = 0; count = 0; } } - pracc_add(&ctx, 0, MIPS32_SYNC); - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave*/ + pracc_add(&ctx, 0, MIPS32_SYNC(ctx.isa)); + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave*/ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); exit: @@ -712,7 +723,7 @@ exit: static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info, uint32_t addr, int size, int count, const void *buf) { - struct pracc_queue_info ctx; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); const uint32_t *buf32 = buf; @@ -722,31 +733,32 @@ static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info, while (count) { ctx.code_count = 0; ctx.store_count = 0; + int this_round_count = (count > 128) ? 128 : count; uint32_t last_upper_base_addr = UPPER16((addr + 0x8000)); - - pracc_add(&ctx, 0, MIPS32_LUI(15, last_upper_base_addr)); /* load $15 with memory base address */ + /* load $15 with memory base address */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, last_upper_base_addr)); for (int i = 0; i != this_round_count; i++) { uint32_t upper_base_addr = UPPER16((addr + 0x8000)); - if (last_upper_base_addr != upper_base_addr) { - pracc_add(&ctx, 0, MIPS32_LUI(15, upper_base_addr)); /* if needed, change upper address in $15*/ + if (last_upper_base_addr != upper_base_addr) { /* if needed, change upper address in $15*/ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 15, upper_base_addr)); last_upper_base_addr = upper_base_addr; } if (size == 4) { - pracc_add_li32(&ctx, 8, *buf32, 1); /* load with li32, optimize */ - pracc_add(&ctx, 0, MIPS32_SW(8, LOWER16(addr), 15)); /* store word to memory */ + pracc_add_li32(&ctx, 8, *buf32, 1); /* load with li32, optimize */ + pracc_add(&ctx, 0, MIPS32_SW(ctx.isa, 8, LOWER16(addr), 15)); /* store word to mem */ buf32++; } else if (size == 2) { - pracc_add(&ctx, 0, MIPS32_ORI(8, 0, *buf16)); /* load lower value */ - pracc_add(&ctx, 0, MIPS32_SH(8, LOWER16(addr), 15)); /* store half word to memory */ + pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 0, *buf16)); /* load lower value */ + pracc_add(&ctx, 0, MIPS32_SH(ctx.isa, 8, LOWER16(addr), 15)); /* store half word */ buf16++; } else { - pracc_add(&ctx, 0, MIPS32_ORI(8, 0, *buf8)); /* load lower value */ - pracc_add(&ctx, 0, MIPS32_SB(8, LOWER16(addr), 15)); /* store byte to memory */ + pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 0, *buf8)); /* load lower value */ + pracc_add(&ctx, 0, MIPS32_SB(ctx.isa, 8, LOWER16(addr), 15)); /* store byte */ buf8++; } addr += size; @@ -754,8 +766,8 @@ static int mips32_pracc_write_mem_generic(struct mips_ejtag *ejtag_info, pracc_add_li32(&ctx, 8, ejtag_info->reg8, 0); /* restore $8 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MFC0(15, 31, 0)); /* restore $15 from DeSave */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 15, 31, 0)); /* restore $15 from DeSave */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); if (ctx.retval != ERROR_OK) @@ -824,18 +836,18 @@ int mips32_pracc_write_mem(struct mips_ejtag *ejtag_info, uint32_t addr, int siz int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) { - static const uint32_t cp0_write_code[] = { - MIPS32_MTC0(1, 12, 0), /* move $1 to status */ - MIPS32_MTLO(1), /* move $1 to lo */ - MIPS32_MTHI(1), /* move $1 to hi */ - MIPS32_MTC0(1, 8, 0), /* move $1 to badvaddr */ - MIPS32_MTC0(1, 13, 0), /* move $1 to cause*/ - MIPS32_MTC0(1, 24, 0), /* move $1 to depc (pc) */ - }; - - struct pracc_queue_info ctx; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); + uint32_t cp0_write_code[] = { + MIPS32_MTC0(ctx.isa, 1, 12, 0), /* move $1 to status */ + MIPS32_MTLO(ctx.isa, 1), /* move $1 to lo */ + MIPS32_MTHI(ctx.isa, 1), /* move $1 to hi */ + MIPS32_MTC0(ctx.isa, 1, 8, 0), /* move $1 to badvaddr */ + MIPS32_MTC0(ctx.isa, 1, 13, 0), /* move $1 to cause*/ + MIPS32_MTC0(ctx.isa, 1, 24, 0), /* move $1 to depc (pc) */ + }; + /* load registers 2 to 31 with li32, optimize */ for (int i = 2; i < 32; i++) pracc_add_li32(&ctx, i, regs[i], 1); @@ -844,10 +856,10 @@ int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) pracc_add_li32(&ctx, 1, regs[i + 32], 0); /* load CPO value in $1 */ pracc_add(&ctx, 0, cp0_write_code[i]); /* write value from $1 to CPO register */ } - pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */ - pracc_add(&ctx, 0, MIPS32_LUI(1, UPPER16((regs[1])))); /* load upper half word in $1 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_ORI(1, 1, LOWER16((regs[1])))); /* load lower half word in $1 */ + pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); /* load $15 in DeSave */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, UPPER16((regs[1])))); /* load upper half word in $1 */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 1, 1, LOWER16((regs[1])))); /* load lower half word in $1 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); @@ -859,37 +871,37 @@ int mips32_pracc_write_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) { - static int cp0_read_code[] = { - MIPS32_MFC0(8, 12, 0), /* move status to $8 */ - MIPS32_MFLO(8), /* move lo to $8 */ - MIPS32_MFHI(8), /* move hi to $8 */ - MIPS32_MFC0(8, 8, 0), /* move badvaddr to $8 */ - MIPS32_MFC0(8, 13, 0), /* move cause to $8 */ - MIPS32_MFC0(8, 24, 0), /* move depc (pc) to $8 */ - }; - - struct pracc_queue_info ctx; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - pracc_add(&ctx, 0, MIPS32_MTC0(1, 31, 0)); /* move $1 to COP0 DeSave */ - pracc_add(&ctx, 0, MIPS32_LUI(1, PRACC_UPPER_BASE_ADDR)); /* $1 = MIP32_PRACC_BASE_ADDR */ + uint32_t cp0_read_code[] = { + MIPS32_MFC0(ctx.isa, 8, 12, 0), /* move status to $8 */ + MIPS32_MFLO(ctx.isa, 8), /* move lo to $8 */ + MIPS32_MFHI(ctx.isa, 8), /* move hi to $8 */ + MIPS32_MFC0(ctx.isa, 8, 8, 0), /* move badvaddr to $8 */ + MIPS32_MFC0(ctx.isa, 8, 13, 0), /* move cause to $8 */ + MIPS32_MFC0(ctx.isa, 8, 24, 0), /* move depc (pc) to $8 */ + }; + + pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 1, 31, 0)); /* move $1 to COP0 DeSave */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 1, PRACC_UPPER_BASE_ADDR)); /* $1 = MIP32_PRACC_BASE_ADDR */ for (int i = 2; i != 32; i++) /* store GPR's 2 to 31 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i * 4), - MIPS32_SW(i, PRACC_OUT_OFFSET + (i * 4), 1)); + MIPS32_SW(ctx.isa, i, PRACC_OUT_OFFSET + (i * 4), 1)); for (int i = 0; i != 6; i++) { pracc_add(&ctx, 0, cp0_read_code[i]); /* load COP0 needed registers to $8 */ pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + (i + 32) * 4, /* store $8 at PARAM OUT */ - MIPS32_SW(8, PRACC_OUT_OFFSET + (i + 32) * 4, 1)); + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + (i + 32) * 4, 1)); } - pracc_add(&ctx, 0, MIPS32_MFC0(8, 31, 0)); /* move DeSave to $8, reg1 value */ - pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + 4, /* store reg1 value from $8 to param out */ - MIPS32_SW(8, PRACC_OUT_OFFSET + 4, 1)); + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 8, 31, 0)); /* move DeSave to $8, reg1 value */ + pracc_add(&ctx, MIPS32_PRACC_PARAM_OUT + 4, /* store reg1 value from $8 to param out */ + MIPS32_SW(ctx.isa, 8, PRACC_OUT_OFFSET + 4, 1)); - pracc_add(&ctx, 0, MIPS32_MFC0(1, 31, 0)); /* move COP0 DeSave to $1, restore reg1 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16(ctx.code_count + 1))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_MTC0(15, 31, 0)); /* load $15 in DeSave */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 1, 31, 0)); /* move COP0 DeSave to $1, restore reg1 */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 15, 31, 0)); /* load $15 in DeSave */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, regs, 1); @@ -909,38 +921,40 @@ int mips32_pracc_read_regs(struct mips_ejtag *ejtag_info, uint32_t *regs) int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_area *source, int write_t, uint32_t addr, int count, uint32_t *buf) { + uint32_t isa = ejtag_info->isa ? 1 : 0; uint32_t handler_code[] = { /* r15 points to the start of this code */ - MIPS32_SW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15), - MIPS32_SW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15), - MIPS32_SW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15), - MIPS32_SW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15), + MIPS32_SW(isa, 8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15), + MIPS32_SW(isa, 9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15), + MIPS32_SW(isa, 10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15), + MIPS32_SW(isa, 11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15), /* start of fastdata area in t0 */ - MIPS32_LUI(8, UPPER16(MIPS32_PRACC_FASTDATA_AREA)), - MIPS32_ORI(8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA)), - MIPS32_LW(9, 0, 8), /* start addr in t1 */ - MIPS32_LW(10, 0, 8), /* end addr to t2 */ + MIPS32_LUI(isa, 8, UPPER16(MIPS32_PRACC_FASTDATA_AREA)), + MIPS32_ORI(isa, 8, 8, LOWER16(MIPS32_PRACC_FASTDATA_AREA)), + MIPS32_LW(isa, 9, 0, 8), /* start addr in t1 */ + MIPS32_LW(isa, 10, 0, 8), /* end addr to t2 */ /* loop: */ - write_t ? MIPS32_LW(11, 0, 8) : MIPS32_LW(11, 0, 9), /* from xfer area : from memory */ - write_t ? MIPS32_SW(11, 0, 9) : MIPS32_SW(11, 0, 8), /* to memory : to xfer area */ + write_t ? MIPS32_LW(isa, 11, 0, 8) : MIPS32_LW(isa, 11, 0, 9), /* from xfer area : from memory */ + write_t ? MIPS32_SW(isa, 11, 0, 9) : MIPS32_SW(isa, 11, 0, 8), /* to memory : to xfer area */ - MIPS32_BNE(10, 9, NEG16(3)), /* bne $t2,t1,loop */ - MIPS32_ADDI(9, 9, 4), /* addi t1,t1,4 */ + MIPS32_BNE(isa, 10, 9, NEG16(3 << isa)), /* bne $t2,t1,loop */ + MIPS32_ADDI(isa, 9, 9, 4), /* addi t1,t1,4 */ - MIPS32_LW(8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15), - MIPS32_LW(9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15), - MIPS32_LW(10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15), - MIPS32_LW(11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15), + MIPS32_LW(isa, 8, MIPS32_FASTDATA_HANDLER_SIZE - 4, 15), + MIPS32_LW(isa, 9, MIPS32_FASTDATA_HANDLER_SIZE - 8, 15), + MIPS32_LW(isa, 10, MIPS32_FASTDATA_HANDLER_SIZE - 12, 15), + MIPS32_LW(isa, 11, MIPS32_FASTDATA_HANDLER_SIZE - 16, 15), - MIPS32_LUI(15, UPPER16(MIPS32_PRACC_TEXT)), - MIPS32_ORI(15, 15, LOWER16(MIPS32_PRACC_TEXT)), - MIPS32_JR(15), /* jr start */ - MIPS32_MFC0(15, 31, 0), /* move COP0 DeSave to $15 */ + MIPS32_LUI(isa, 15, UPPER16(MIPS32_PRACC_TEXT)), + MIPS32_ORI(isa, 15, 15, LOWER16(MIPS32_PRACC_TEXT) | isa), /* isa bit for JR instr */ + MIPS32_JR(isa, 15), /* jr start */ + MIPS32_MFC0(isa, 15, 31, 0), /* move COP0 DeSave to $15 */ }; if (source->size < MIPS32_FASTDATA_HANDLER_SIZE) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + pracc_swap16_array(ejtag_info, handler_code, ARRAY_SIZE(handler_code)); /* write program into RAM */ if (write_t != ejtag_info->fast_access_save) { mips32_pracc_write_mem(ejtag_info, source->address, 4, ARRAY_SIZE(handler_code), handler_code); @@ -951,12 +965,14 @@ int mips32_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, struct working_are LOG_DEBUG("%s using 0x%.8" TARGET_PRIxADDR " for write handler", __func__, source->address); uint32_t jmp_code[] = { - MIPS32_LUI(15, UPPER16(source->address)), /* load addr of jump in $15 */ - MIPS32_ORI(15, 15, LOWER16(source->address)), - MIPS32_JR(15), /* jump to ram program */ - MIPS32_NOP, + MIPS32_LUI(isa, 15, UPPER16(source->address)), /* load addr of jump in $15 */ + MIPS32_ORI(isa, 15, 15, LOWER16(source->address) | isa), /* isa bit for JR instr */ + MIPS32_JR(isa, 15), /* jump to ram program */ + isa ? MIPS32_XORI(isa, 15, 15, 1) : MIPS32_NOP, /* drop isa bit, needed for LW/SW instructions */ }; + pracc_swap16_array(ejtag_info, jmp_code, ARRAY_SIZE(jmp_code)); + /* execute jump code, with no address check */ for (unsigned i = 0; i < ARRAY_SIZE(jmp_code); i++) { int retval = wait_for_pracc_rw(ejtag_info); diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index e990f8d..fe9f814 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -40,6 +40,7 @@ #define UPPER16(uint32_t) (uint32_t >> 16) #define LOWER16(uint32_t) (uint32_t & 0xFFFF) #define NEG16(v) (((~(v)) + 1) & 0xFFFF) +#define SWAP16(v) ((LOWER16(v) << 16) | (UPPER16(v))) /*#define NEG18(v) (((~(v)) + 1) & 0x3FFFF)*/ #define PRACC_BLOCK 128 /* 1 Kbyte */ @@ -50,12 +51,15 @@ typedef struct { } pa_list; struct pracc_queue_info { + struct mips_ejtag *ejtag_info; + unsigned isa; int retval; int code_count; int store_count; int max_code; /* max intstructions with currently allocated memory */ pa_list *pracc_list; /* Code and store addresses at dmseg */ }; + void pracc_queue_init(struct pracc_queue_info *ctx); void pracc_add(struct pracc_queue_info *ctx, uint32_t addr, uint32_t instr); void pracc_add_li32(struct pracc_queue_info *ctx, uint32_t reg_num, uint32_t data, bool optimize); @@ -108,4 +112,11 @@ int mips32_cp0_read(struct mips_ejtag *ejtag_info, int mips32_cp0_write(struct mips_ejtag *ejtag_info, uint32_t val, uint32_t cp0_reg, uint32_t cp0_sel); +inline void pracc_swap16_array(struct mips_ejtag *ejtag_info, uint32_t *buf, int count) +{ + if (ejtag_info->isa && ejtag_info->endianness) + for (int i = 0; i != count; i++) + buf[i] = SWAP16(buf[i]); +} + #endif /* OPENOCD_TARGET_MIPS32_PRACC_H */ diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index e35758d..d335c1b 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -197,18 +197,18 @@ void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data) /* Set (to enable) or clear (to disable stepping) the SSt bit (bit 8) in Cp0 Debug reg (reg 23, sel 0) */ int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step) { - struct pracc_queue_info ctx; + struct pracc_queue_info ctx = {.ejtag_info = ejtag_info}; pracc_queue_init(&ctx); - pracc_add(&ctx, 0, MIPS32_MFC0(8, 23, 0)); /* move COP0 Debug to $8 */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, 0x0100)); /* set SSt bit in debug reg */ + pracc_add(&ctx, 0, MIPS32_MFC0(ctx.isa, 8, 23, 0)); /* move COP0 Debug to $8 */ + pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 8, 0x0100)); /* set SSt bit in debug reg */ if (!enable_step) - pracc_add(&ctx, 0, MIPS32_XORI(8, 8, 0x0100)); /* clear SSt bit in debug reg */ + pracc_add(&ctx, 0, MIPS32_XORI(ctx.isa, 8, 8, 0x0100)); /* clear SSt bit in debug reg */ - pracc_add(&ctx, 0, MIPS32_MTC0(8, 23, 0)); /* move $8 to COP0 Debug */ - pracc_add(&ctx, 0, MIPS32_LUI(8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ - pracc_add(&ctx, 0, MIPS32_B(NEG16((ctx.code_count + 1)))); /* jump to start */ - pracc_add(&ctx, 0, MIPS32_ORI(8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ + pracc_add(&ctx, 0, MIPS32_MTC0(ctx.isa, 8, 23, 0)); /* move $8 to COP0 Debug */ + pracc_add(&ctx, 0, MIPS32_LUI(ctx.isa, 8, UPPER16(ejtag_info->reg8))); /* restore upper 16 bits of $8 */ + pracc_add(&ctx, 0, MIPS32_B(ctx.isa, NEG16((ctx.code_count + 1) << ctx.isa))); /* jump to start */ + pracc_add(&ctx, 0, MIPS32_ORI(ctx.isa, 8, 8, LOWER16(ejtag_info->reg8))); /* restore lower 16 bits of $8 */ ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 1); pracc_queue_free(&ctx); @@ -269,11 +269,11 @@ error: int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info) { - pa_list pracc_list = {.instr = MIPS32_DRET, .addr = 0}; + pa_list pracc_list = {.instr = MIPS32_DRET(ejtag_info->isa), .addr = 0}; struct pracc_queue_info ctx = {.max_code = 1, .pracc_list = &pracc_list, .code_count = 1, .store_count = 0}; /* execute our dret instruction */ - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 0); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, NULL, 0); /* shift out instr, omit last check */ /* pic32mx workaround, false pending at low core clock */ jtag_add_sleep(1000); diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index 3043df9..ade1b4c 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -58,6 +58,7 @@ #define EJTAG_CTRL_DERR (1 << 10) #define EJTAG_CTRL_DSTRT (1 << 11) #define EJTAG_CTRL_JTAGBRK (1 << 12) +#define EJTAG_CTRL_DBGISA (1 << 13) #define EJTAG_CTRL_SETDEV (1 << 14) #define EJTAG_CTRL_PROBEN (1 << 15) #define EJTAG_CTRL_PRRST (1 << 16) @@ -189,6 +190,8 @@ struct mips_ejtag { uint32_t pa_ctrl; uint32_t pa_addr; unsigned int ejtag_version; + uint32_t isa; + uint32_t endianness; /* Memory-Mapped Registers. This addresses are not same on different * EJTAG versions. */ diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index bd3c602..8b32d11 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -195,6 +195,8 @@ static int mips_m4k_poll(struct target *target) if (retval != ERROR_OK) return retval; + ejtag_info->isa = (ejtag_ctrl & EJTAG_CTRL_DBGISA) ? 1 : 0; + /* clear this bit before handling polling * as after reset registers will read zero */ if (ejtag_ctrl & EJTAG_CTRL_ROCC) { @@ -648,14 +650,14 @@ static int mips_m4k_set_breakpoint(struct target *target, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; - retval = target_write_u32(target, breakpoint->address, MIPS32_SDBBP); + retval = target_write_u32(target, breakpoint->address, MIPS32_SDBBP(ejtag_info->isa)); if (retval != ERROR_OK) return retval; retval = target_read_u32(target, breakpoint->address, &verify); if (retval != ERROR_OK) return retval; - if (verify != MIPS32_SDBBP) { + if (verify != MIPS32_SDBBP(ejtag_info->isa)) { LOG_ERROR("Unable to set 32-bit breakpoint at address " TARGET_ADDR_FMT " - check that memory is read/writable", breakpoint->address); return ERROR_OK; @@ -667,14 +669,14 @@ static int mips_m4k_set_breakpoint(struct target *target, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; - retval = target_write_u16(target, breakpoint->address, MIPS16_SDBBP); + retval = target_write_u16(target, breakpoint->address, MIPS16_SDBBP(ejtag_info->isa)); if (retval != ERROR_OK) return retval; retval = target_read_u16(target, breakpoint->address, &verify); if (retval != ERROR_OK) return retval; - if (verify != MIPS16_SDBBP) { + if (verify != MIPS16_SDBBP(ejtag_info->isa)) { LOG_ERROR("Unable to set 16-bit breakpoint at address " TARGET_ADDR_FMT " - check that memory is read/writable", breakpoint->address); return ERROR_OK; @@ -735,7 +737,7 @@ static int mips_m4k_unset_breakpoint(struct target *target, */ current_instr = target_buffer_get_u32(target, (uint8_t *)¤t_instr); - if (current_instr == MIPS32_SDBBP) { + if (current_instr == MIPS32_SDBBP(ejtag_info->isa)) { retval = target_write_memory(target, breakpoint->address, 4, 1, breakpoint->orig_instr); if (retval != ERROR_OK) @@ -750,7 +752,7 @@ static int mips_m4k_unset_breakpoint(struct target *target, if (retval != ERROR_OK) return retval; current_instr = target_buffer_get_u16(target, (uint8_t *)¤t_instr); - if (current_instr == MIPS16_SDBBP) { + if (current_instr == MIPS16_SDBBP(ejtag_info->isa)) { retval = target_write_memory(target, breakpoint->address, 2, 1, breakpoint->orig_instr); if (retval != ERROR_OK) -- cgit v1.1 From f5151b6d46cb0b939e3beb0fc61cb8718908f4b8 Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Sun, 7 May 2017 13:36:12 +0200 Subject: mips32, convert miniprograms with code definition Needed to run in micromips mode. Seems that if an isa is supported in debug mode it also supported in kernel mode. The contrary is not true. Change-Id: I1feb8e2c376f4db97089f05c20bc0cd177208fb3 Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4033 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips32.c | 107 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 44 deletions(-) diff --git a/src/target/mips32.c b/src/target/mips32.c index 5c85fea..c5b7fbc 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -705,47 +705,55 @@ int mips32_checksum_memory(struct target *target, target_addr_t address, struct reg_param reg_params[2]; struct mips32_algorithm mips32_info; - /* see contrib/loaders/checksum/mips32.s for src */ + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; - static const uint32_t mips_crc_code[] = { - 0x248C0000, /* addiu $t4, $a0, 0 */ - 0x24AA0000, /* addiu $t2, $a1, 0 */ - 0x2404FFFF, /* addiu $a0, $zero, 0xffffffff */ - 0x10000010, /* beq $zero, $zero, ncomp */ - 0x240B0000, /* addiu $t3, $zero, 0 */ + /* see contrib/loaders/checksum/mips32.s for src */ + uint32_t isa = ejtag_info->isa ? 1 : 0; + + uint32_t mips_crc_code[] = { + MIPS32_ADDIU(isa, 12, 4, 0), /* addiu $t4, $a0, 0 */ + MIPS32_ADDIU(isa, 10, 5, 0), /* addiu $t2, $a1, 0 */ + MIPS32_ADDIU(isa, 4, 0, 0xFFFF), /* addiu $a0, $zero, 0xffff */ + MIPS32_BEQ(isa, 0, 0, 0x10 << isa), /* beq $zero, $zero, ncomp */ + MIPS32_ADDIU(isa, 11, 0, 0), /* addiu $t3, $zero, 0 */ /* nbyte: */ - 0x81850000, /* lb $a1, ($t4) */ - 0x218C0001, /* addi $t4, $t4, 1 */ - 0x00052E00, /* sll $a1, $a1, 24 */ - 0x3C0204C1, /* lui $v0, 0x04c1 */ - 0x00852026, /* xor $a0, $a0, $a1 */ - 0x34471DB7, /* ori $a3, $v0, 0x1db7 */ - 0x00003021, /* addu $a2, $zero, $zero */ - /* loop: */ - 0x00044040, /* sll $t0, $a0, 1 */ - 0x24C60001, /* addiu $a2, $a2, 1 */ - 0x28840000, /* slti $a0, $a0, 0 */ - 0x01074826, /* xor $t1, $t0, $a3 */ - 0x0124400B, /* movn $t0, $t1, $a0 */ - 0x28C30008, /* slti $v1, $a2, 8 */ - 0x1460FFF9, /* bne $v1, $zero, loop */ - 0x01002021, /* addu $a0, $t0, $zero */ - /* ncomp: */ - 0x154BFFF0, /* bne $t2, $t3, nbyte */ - 0x256B0001, /* addiu $t3, $t3, 1 */ - 0x7000003F, /* sdbbp */ + MIPS32_LB(isa, 5, 0, 12), /* lb $a1, ($t4) */ + MIPS32_ADDI(isa, 12, 12, 1), /* addi $t4, $t4, 1 */ + MIPS32_SLL(isa, 5, 5, 24), /* sll $a1, $a1, 24 */ + MIPS32_LUI(isa, 2, 0x04c1), /* lui $v0, 0x04c1 */ + MIPS32_XOR(isa, 4, 4, 5), /* xor $a0, $a0, $a1 */ + MIPS32_ORI(isa, 7, 2, 0x1db7), /* ori $a3, $v0, 0x1db7 */ + MIPS32_ADDU(isa, 6, 0, 0), /* addu $a2, $zero, $zero */ + /* loop */ + MIPS32_SLL(isa, 8, 4, 1), /* sll $t0, $a0, 1 */ + MIPS32_ADDIU(isa, 6, 6, 1), /* addiu $a2, $a2, 1 */ + MIPS32_SLTI(isa, 4, 4, 0), /* slti $a0, $a0, 0 */ + MIPS32_XOR(isa, 9, 8, 7), /* xor $t1, $t0, $a3 */ + MIPS32_MOVN(isa, 8, 9, 4), /* movn $t0, $t1, $a0 */ + MIPS32_SLTI(isa, 3, 6, 8), /* slti $v1, $a2, 8 */ + MIPS32_BNE(isa, 3, 0, NEG16(7 << isa)), /* bne $v1, $zero, loop */ + MIPS32_ADDU(isa, 4, 8, 0), /* addu $a0, $t0, $zero */ + /* ncomp */ + MIPS32_BNE(isa, 10, 11, NEG16(16 << isa)), /* bne $t2, $t3, nbyte */ + MIPS32_ADDIU(isa, 11, 11, 1), /* addiu $t3, $t3, 1 */ + MIPS32_SDBBP(isa), }; /* make sure we have a working area */ if (target_alloc_working_area(target, sizeof(mips_crc_code), &crc_algorithm) != ERROR_OK) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + pracc_swap16_array(ejtag_info, mips_crc_code, ARRAY_SIZE(mips_crc_code)); + /* convert mips crc code into a buffer in target endianness */ uint8_t mips_crc_code_8[sizeof(mips_crc_code)]; target_buffer_set_u32_array(target, mips_crc_code_8, ARRAY_SIZE(mips_crc_code), mips_crc_code); - target_write_buffer(target, crc_algorithm->address, sizeof(mips_crc_code), mips_crc_code_8); + int retval = target_write_buffer(target, crc_algorithm->address, sizeof(mips_crc_code), mips_crc_code_8); + if (retval != ERROR_OK) + return retval; mips32_info.common_magic = MIPS32_COMMON_MAGIC; mips32_info.isa_mode = MIPS32_ISA_MIPS32; @@ -758,9 +766,11 @@ int mips32_checksum_memory(struct target *target, target_addr_t address, int timeout = 20000 * (1 + (count / (1024 * 1024))); - int retval = target_run_algorithm(target, 0, NULL, 2, reg_params, - crc_algorithm->address, crc_algorithm->address + (sizeof(mips_crc_code) - 4), timeout, - &mips32_info); + /* same isa as in debug mode */ + retval = target_run_algorithm(target, 0, NULL, 2, reg_params, + crc_algorithm->address | isa, + (crc_algorithm->address + (sizeof(mips_crc_code) - 4)) | isa, + timeout, &mips32_info); if (retval == ERROR_OK) *checksum = buf_get_u32(reg_params[0].value, 0, 32); @@ -781,32 +791,40 @@ int mips32_blank_check_memory(struct target *target, struct reg_param reg_params[3]; struct mips32_algorithm mips32_info; - static const uint32_t erase_check_code[] = { - /* nbyte: */ - 0x80880000, /* lb $t0, ($a0) */ - 0x00C83024, /* and $a2, $a2, $t0 */ - 0x24A5FFFF, /* addiu $a1, $a1, -1 */ - 0x14A0FFFC, /* bne $a1, $zero, nbyte */ - 0x24840001, /* addiu $a0, $a0, 1 */ - 0x7000003F /* sdbbp */ - }; + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; if (erased_value != 0xff) { LOG_ERROR("Erase value 0x%02" PRIx8 " not yet supported for MIPS32", erased_value); return ERROR_FAIL; } + uint32_t isa = ejtag_info->isa ? 1 : 0; + uint32_t erase_check_code[] = { + /* nbyte: */ + MIPS32_LB(isa, 8, 0, 4), /* lb $t0, ($a0) */ + MIPS32_AND(isa, 6, 6, 8), /* and $a2, $a2, $t0 */ + MIPS32_ADDIU(isa, 5, 5, NEG16(1)), /* addiu $a1, $a1, -1 */ + MIPS32_BNE(isa, 5, 0, NEG16(4 << isa)), /* bne $a1, $zero, nbyte */ + MIPS32_ADDIU(isa, 4, 4, 1), /* addiu $a0, $a0, 1 */ + MIPS32_SDBBP(isa) /* sdbbp */ + }; /* make sure we have a working area */ if (target_alloc_working_area(target, sizeof(erase_check_code), &erase_check_algorithm) != ERROR_OK) return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + pracc_swap16_array(ejtag_info, erase_check_code, ARRAY_SIZE(erase_check_code)); + /* convert erase check code into a buffer in target endianness */ uint8_t erase_check_code_8[sizeof(erase_check_code)]; target_buffer_set_u32_array(target, erase_check_code_8, ARRAY_SIZE(erase_check_code), erase_check_code); - target_write_buffer(target, erase_check_algorithm->address, sizeof(erase_check_code), erase_check_code_8); + int retval = target_write_buffer(target, erase_check_algorithm->address, + sizeof(erase_check_code), erase_check_code_8); + if (retval != ERROR_OK) + return retval; mips32_info.common_magic = MIPS32_COMMON_MAGIC; mips32_info.isa_mode = MIPS32_ISA_MIPS32; @@ -820,9 +838,10 @@ int mips32_blank_check_memory(struct target *target, init_reg_param(®_params[2], "r6", 32, PARAM_IN_OUT); buf_set_u32(reg_params[2].value, 0, 32, erased_value); - int retval = target_run_algorithm(target, 0, NULL, 3, reg_params, - erase_check_algorithm->address, - erase_check_algorithm->address + (sizeof(erase_check_code) - 4), + /* same isa as in debug mode */ + retval = target_run_algorithm(target, 0, NULL, 3, reg_params, + erase_check_algorithm->address | isa, + (erase_check_algorithm->address + (sizeof(erase_check_code) - 4)) | isa, 10000, &mips32_info); if (retval == ERROR_OK) -- cgit v1.1 From 4831ce4433adf4e2fbf5729bebf8c0f7c2fce1c1 Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Sun, 7 May 2017 18:39:17 +0200 Subject: mips32: add micromips isa handling Read and save configuration registers, up to 4. Config3 holds the micromips implementation info. Added isa implementation info to mips32_common. Added isa filter to avoid common mistakes, but only if one isa mode is implemented. When resuming the isa requested is set if more than one isa mode is implemented. Change-Id: I1d6526c5525bffac8d75e031b842b2edc6310e28 Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4123 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips32.c | 67 ++++++++++++++++++++++++++++++++++++++----------- src/target/mips32.h | 14 +++++++++++ src/target/mips_ejtag.h | 3 +++ src/target/mips_m4k.c | 15 +++++++---- src/target/mips_m4k.h | 11 ++++++++ 5 files changed, 91 insertions(+), 19 deletions(-) diff --git a/src/target/mips32.c b/src/target/mips32.c index c5b7fbc..93fb4e6 100644 --- a/src/target/mips32.c +++ b/src/target/mips32.c @@ -34,7 +34,7 @@ #include "register.h" static const char *mips_isa_strings[] = { - "MIPS32", "MIPS16" + "MIPS32", "MIPS16", "", "MICRO MIPS32", }; #define MIPS32_GDB_DUMMY_FP_REG 1 @@ -375,6 +375,7 @@ int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, s target->arch_info = mips32; mips32->common_magic = MIPS32_COMMON_MAGIC; mips32->fast_data_area = NULL; + mips32->isa_imp = MIPS32_ONLY; /* default */ /* has breakpoint/watchpoint unit been scanned */ mips32->bp_scanned = 0; @@ -388,7 +389,7 @@ int mips32_init_arch_info(struct target *target, struct mips32_common *mips32, s mips32->ejtag_info.scan_delay = MIPS32_SCAN_DELAY_LEGACY_MODE; mips32->ejtag_info.mode = 0; /* Initial default value */ mips32->ejtag_info.isa = 0; /* isa on debug mips32, updated by poll function */ - + mips32->ejtag_info.config_regs = 0; /* no config register read */ return ERROR_OK; } @@ -698,6 +699,50 @@ int mips32_enable_interrupts(struct target *target, int enable) return ERROR_OK; } +/* read config to config3 cp0 registers and log isa implementation */ +int mips32_read_config_regs(struct target *target) +{ + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; + + if (ejtag_info->config_regs == 0) + for (int i = 0; i != 4; i++) { + int retval = mips32_cp0_read(ejtag_info, &ejtag_info->config[i], 16, i); + if (retval != ERROR_OK) { + LOG_ERROR("isa info not available, failed to read cp0 config register: %" PRId32, i); + ejtag_info->config_regs = 0; + return retval; + } + ejtag_info->config_regs = i + 1; + if ((ejtag_info->config[i] & (1 << 31)) == 0) + break; /* no more config registers implemented */ + } + else + return ERROR_OK; /* already succesfully read */ + + LOG_DEBUG("read %"PRId32" config registers", ejtag_info->config_regs); + + if (ejtag_info->impcode & EJTAG_IMP_MIPS16) { + mips32->isa_imp = MIPS32_MIPS16; + LOG_USER("MIPS32 with MIPS16 support implemented"); + + } else if (ejtag_info->config_regs >= 4) { /* config3 implemented */ + unsigned isa_imp = (ejtag_info->config[3] & MIPS32_CONFIG3_ISA_MASK) >> MIPS32_CONFIG3_ISA_SHIFT; + if (isa_imp == 1) { + mips32->isa_imp = MMIPS32_ONLY; + LOG_USER("MICRO MIPS32 only implemented"); + + } else if (isa_imp != 0) { + mips32->isa_imp = MIPS32_MMIPS32; + LOG_USER("MIPS32 and MICRO MIPS32 implemented"); + } + } + + if (mips32->isa_imp == MIPS32_ONLY) /* initial default value */ + LOG_USER("MIPS32 only implemented"); + + return ERROR_OK; +} int mips32_checksum_memory(struct target *target, target_addr_t address, uint32_t count, uint32_t *checksum) { @@ -756,7 +801,7 @@ int mips32_checksum_memory(struct target *target, target_addr_t address, return retval; mips32_info.common_magic = MIPS32_COMMON_MAGIC; - mips32_info.isa_mode = MIPS32_ISA_MIPS32; + mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32; /* run isa as in debug mode */ init_reg_param(®_params[0], "r4", 32, PARAM_IN_OUT); buf_set_u32(reg_params[0].value, 0, 32, address); @@ -766,11 +811,8 @@ int mips32_checksum_memory(struct target *target, target_addr_t address, int timeout = 20000 * (1 + (count / (1024 * 1024))); - /* same isa as in debug mode */ - retval = target_run_algorithm(target, 0, NULL, 2, reg_params, - crc_algorithm->address | isa, - (crc_algorithm->address + (sizeof(mips_crc_code) - 4)) | isa, - timeout, &mips32_info); + retval = target_run_algorithm(target, 0, NULL, 2, reg_params, crc_algorithm->address, + crc_algorithm->address + (sizeof(mips_crc_code) - 4), timeout, &mips32_info); if (retval == ERROR_OK) *checksum = buf_get_u32(reg_params[0].value, 0, 32); @@ -827,7 +869,7 @@ int mips32_blank_check_memory(struct target *target, return retval; mips32_info.common_magic = MIPS32_COMMON_MAGIC; - mips32_info.isa_mode = MIPS32_ISA_MIPS32; + mips32_info.isa_mode = isa ? MIPS32_ISA_MMIPS32 : MIPS32_ISA_MIPS32; init_reg_param(®_params[0], "r4", 32, PARAM_OUT); buf_set_u32(reg_params[0].value, 0, 32, address); @@ -838,11 +880,8 @@ int mips32_blank_check_memory(struct target *target, init_reg_param(®_params[2], "r6", 32, PARAM_IN_OUT); buf_set_u32(reg_params[2].value, 0, 32, erased_value); - /* same isa as in debug mode */ - retval = target_run_algorithm(target, 0, NULL, 3, reg_params, - erase_check_algorithm->address | isa, - (erase_check_algorithm->address + (sizeof(erase_check_code) - 4)) | isa, - 10000, &mips32_info); + retval = target_run_algorithm(target, 0, NULL, 3, reg_params, erase_check_algorithm->address, + erase_check_algorithm->address + (sizeof(erase_check_code) - 4), 10000, &mips32_info); if (retval == ERROR_OK) *blank = buf_get_u32(reg_params[2].value, 0, 32); diff --git a/src/target/mips32.h b/src/target/mips32.h index d79451f..928598f 100644 --- a/src/target/mips32.h +++ b/src/target/mips32.h @@ -58,6 +58,9 @@ #define MIPS32_CONFIG1_DL_SHIFT 10 #define MIPS32_CONFIG1_DL_MASK (0x7 << MIPS32_CONFIG1_DL_SHIFT) +#define MIPS32_CONFIG3_ISA_SHIFT 14 +#define MIPS32_CONFIG3_ISA_MASK (3 << MIPS32_CONFIG3_ISA_SHIFT) + #define MIPS32_ARCH_REL1 0x0 #define MIPS32_ARCH_REL2 0x1 @@ -73,6 +76,14 @@ enum { enum mips32_isa_mode { MIPS32_ISA_MIPS32 = 0, MIPS32_ISA_MIPS16E = 1, + MIPS32_ISA_MMIPS32 = 3, +}; + +enum mips32_isa_imp { + MIPS32_ONLY = 0, + MMIPS32_ONLY = 1, + MIPS32_MIPS16 = 2, + MIPS32_MMIPS32 = 3, }; struct mips32_comparator { @@ -88,6 +99,7 @@ struct mips32_common { struct mips_ejtag ejtag_info; uint32_t core_regs[MIPS32NUMCOREREGS]; enum mips32_isa_mode isa_mode; + enum mips32_isa_imp isa_imp; /* working area for fastdata access */ struct working_area *fast_data_area; @@ -406,6 +418,8 @@ int mips32_enable_interrupts(struct target *target, int enable); int mips32_examine(struct target *target); +int mips32_read_config_regs(struct target *target); + int mips32_register_commands(struct command_context *cmd_ctx); int mips32_get_gdb_reg_list(struct target *target, diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index ade1b4c..226863f 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -183,6 +183,9 @@ struct mips_ejtag { uint32_t idcode; uint32_t ejtag_ctrl; int fast_access_save; + uint32_t config_regs; /* number of config registers read */ + uint32_t config[4]; /* cp0 config to config3 */ + uint32_t reg8; uint32_t reg9; unsigned scan_delay; diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 8b32d11..7ab30fe 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -41,7 +41,7 @@ static int mips_m4k_set_breakpoint(struct target *target, static int mips_m4k_unset_breakpoint(struct target *target, struct breakpoint *breakpoint); static int mips_m4k_internal_restore(struct target *target, int current, - uint32_t address, int handle_breakpoints, + target_addr_t address, int handle_breakpoints, int debug_execution); static int mips_m4k_halt(struct target *target); static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t address, @@ -108,11 +108,14 @@ static int mips_m4k_debug_entry(struct target *target) /* attempt to find halt reason */ mips_m4k_examine_debug_reason(target); + mips32_read_config_regs(target); + /* default to mips32 isa, it will be changed below if required */ mips32->isa_mode = MIPS32_ISA_MIPS32; - if (ejtag_info->impcode & EJTAG_IMP_MIPS16) - mips32->isa_mode = buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1); + /* other than mips32 only and isa bit set ? */ + if (mips32->isa_imp && buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1)) + mips32->isa_mode = mips32->isa_imp == 2 ? MIPS32_ISA_MIPS16E : MIPS32_ISA_MMIPS32; LOG_DEBUG("entered debug state at PC 0x%" PRIx32 ", target->state: %s", buf_get_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32), @@ -431,7 +434,7 @@ static int mips_m4k_restore_smp(struct target *target, uint32_t address, int han } static int mips_m4k_internal_restore(struct target *target, int current, - uint32_t address, int handle_breakpoints, int debug_execution) + target_addr_t address, int handle_breakpoints, int debug_execution) { struct mips32_common *mips32 = target_to_mips32(target); struct mips_ejtag *ejtag_info = &mips32->ejtag_info; @@ -451,12 +454,13 @@ static int mips_m4k_internal_restore(struct target *target, int current, /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) { + mips_m4k_isa_filter(mips32->isa_imp, &address); buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address); mips32->core_cache->reg_list[MIPS32_PC].dirty = 1; mips32->core_cache->reg_list[MIPS32_PC].valid = 1; } - if (ejtag_info->impcode & EJTAG_IMP_MIPS16) + if ((mips32->isa_imp > 1) && debug_execution) /* if more than one isa supported */ buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 1, mips32->isa_mode); if (!current) @@ -544,6 +548,7 @@ static int mips_m4k_step(struct target *target, int current, /* current = 1: continue on current pc, otherwise continue at
*/ if (!current) { + mips_m4k_isa_filter(mips32->isa_imp, &address); buf_set_u32(mips32->core_cache->reg_list[MIPS32_PC].value, 0, 32, address); mips32->core_cache->reg_list[MIPS32_PC].dirty = 1; mips32->core_cache->reg_list[MIPS32_PC].valid = 1; diff --git a/src/target/mips_m4k.h b/src/target/mips_m4k.h index cf82661..ea09ae5 100644 --- a/src/target/mips_m4k.h +++ b/src/target/mips_m4k.h @@ -41,6 +41,17 @@ target_to_m4k(struct target *target) struct mips_m4k_common, mips32); } +static inline void mips_m4k_isa_filter(enum mips32_isa_imp isa_imp, target_addr_t *addr) +{ + if (isa_imp <= 1) { /* if only one isa implemented */ + target_addr_t address = (*addr & ~1) | isa_imp; + + if (address != *addr) { + LOG_USER("Warning: isa bit changed due to isa not implemented"); + *addr = address; + } + } +} extern const struct command_registration mips_m4k_command_handlers[]; #endif /* OPENOCD_TARGET_MIPS_M4K_H */ -- cgit v1.1 From b702b16dc2d9bb0bcc4b9b4c909e8c1067aba238 Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Mon, 8 May 2017 09:44:50 +0200 Subject: mips32: add micromips breakpoints support Breakpoint setting based on length (kind) only. Added 16bit aligned 32bit software breakpoints support and same filtering before setting breakpoint. Set the required isa bit in hardware breakpoints. Drop the isa bit in software breakpoints. Change-Id: I7020f27be16015194b76f385d9b8e5af496d0dfc Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4124 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/target/mips_m4k.c | 151 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 105 insertions(+), 46 deletions(-) diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index 7ab30fe..e2007d9 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -631,6 +631,11 @@ static int mips_m4k_set_breakpoint(struct target *target, comparator_list[bp_num].used = 1; comparator_list[bp_num].bp_value = breakpoint->address; + if (breakpoint->length != 4) /* make sure isa bit set */ + comparator_list[bp_num].bp_value |= 1; + else /* make sure isa bit cleared */ + comparator_list[bp_num].bp_value &= ~1; + /* EJTAG 2.0 uses 30bit IBA. First 2 bits are reserved. * Warning: there is no IB ASID registers in 2.0. * Do not set it! :) */ @@ -648,41 +653,77 @@ static int mips_m4k_set_breakpoint(struct target *target, bp_num, comparator_list[bp_num].bp_value); } else if (breakpoint->type == BKPT_SOFT) { LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id); - if (breakpoint->length == 4) { + + uint32_t isa_req = breakpoint->length & 1; /* micro mips request bit */ + uint32_t bplength = breakpoint->length & ~1; /* drop micro mips request bit for length */ + uint32_t bpaddr = breakpoint->address & ~1; /* drop isa bit from address, if set */ + + if (bplength == 4) { uint32_t verify = 0xffffffff; + uint32_t sdbbp32_instr = MIPS32_SDBBP(isa_req); + if (ejtag_info->endianness && isa_req) + sdbbp32_instr = SWAP16(sdbbp32_instr); - retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1, - breakpoint->orig_instr); - if (retval != ERROR_OK) - return retval; - retval = target_write_u32(target, breakpoint->address, MIPS32_SDBBP(ejtag_info->isa)); - if (retval != ERROR_OK) - return retval; + if ((breakpoint->address & 3) == 0) { /* word alligned */ - retval = target_read_u32(target, breakpoint->address, &verify); - if (retval != ERROR_OK) - return retval; - if (verify != MIPS32_SDBBP(ejtag_info->isa)) { - LOG_ERROR("Unable to set 32-bit breakpoint at address " TARGET_ADDR_FMT - " - check that memory is read/writable", breakpoint->address); + retval = target_read_memory(target, bpaddr, bplength, 1, breakpoint->orig_instr); + if (retval != ERROR_OK) + return retval; + + retval = target_write_u32(target, bpaddr, sdbbp32_instr); + if (retval != ERROR_OK) + return retval; + + retval = target_read_u32(target, bpaddr, &verify); + if (retval != ERROR_OK) + return retval; + + if (verify != sdbbp32_instr) + verify = 0; + + } else { /* 16 bit aligned */ + retval = target_read_memory(target, bpaddr, 2, 2, breakpoint->orig_instr); + if (retval != ERROR_OK) + return retval; + + uint8_t sdbbp_buf[4]; + target_buffer_set_u32(target, sdbbp_buf, sdbbp32_instr); + + retval = target_write_memory(target, bpaddr, 2, 2, sdbbp_buf); + if (retval != ERROR_OK) + return retval; + + retval = target_read_memory(target, bpaddr, 2, 2, sdbbp_buf); + if (retval != ERROR_OK) + return retval; + + if (target_buffer_get_u32(target, sdbbp_buf) != sdbbp32_instr) + verify = 0; + } + + if (verify == 0) { + LOG_ERROR("Unable to set 32bit breakpoint at address %08" PRIx64 + " - check that memory is read/writable", breakpoint->address); return ERROR_OK; } + } else { uint16_t verify = 0xffff; - retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1, - breakpoint->orig_instr); + retval = target_read_memory(target, bpaddr, bplength, 1, breakpoint->orig_instr); if (retval != ERROR_OK) return retval; - retval = target_write_u16(target, breakpoint->address, MIPS16_SDBBP(ejtag_info->isa)); + + retval = target_write_u16(target, bpaddr, MIPS16_SDBBP(isa_req)); if (retval != ERROR_OK) return retval; - retval = target_read_u16(target, breakpoint->address, &verify); + retval = target_read_u16(target, bpaddr, &verify); if (retval != ERROR_OK) return retval; - if (verify != MIPS16_SDBBP(ejtag_info->isa)) { - LOG_ERROR("Unable to set 16-bit breakpoint at address " TARGET_ADDR_FMT + + if (verify != MIPS16_SDBBP(isa_req)) { + LOG_ERROR("Unable to set 16bit breakpoint at address %08" PRIx64 " - check that memory is read/writable", breakpoint->address); return ERROR_OK; } @@ -725,46 +766,58 @@ static int mips_m4k_unset_breakpoint(struct target *target, } else { /* restore original instruction (kept in target endianness) */ + uint32_t isa_req = breakpoint->length & 1; + uint32_t bplength = breakpoint->length & ~1; + uint8_t current_instr[4]; LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id); - if (breakpoint->length == 4) { - uint32_t current_instr; - - /* check that user program has not modified breakpoint instruction */ - retval = target_read_memory(target, breakpoint->address, 4, 1, - (uint8_t *)¤t_instr); - if (retval != ERROR_OK) - return retval; - - /** - * target_read_memory() gets us data in _target_ endianess. - * If we want to use this data on the host for comparisons with some macros - * we must first transform it to _host_ endianess using target_buffer_get_u32(). - */ - current_instr = target_buffer_get_u32(target, (uint8_t *)¤t_instr); - - if (current_instr == MIPS32_SDBBP(ejtag_info->isa)) { - retval = target_write_memory(target, breakpoint->address, 4, 1, - breakpoint->orig_instr); + if (bplength == 4) { + uint32_t sdbbp32_instr = MIPS32_SDBBP(isa_req); + if (ejtag_info->endianness && isa_req) + sdbbp32_instr = SWAP16(sdbbp32_instr); + + if ((breakpoint->address & 3) == 0) { /* 32bit aligned */ + /* check that user program has not modified breakpoint instruction */ + retval = target_read_memory(target, breakpoint->address, 4, 1, current_instr); + if (retval != ERROR_OK) + return retval; + /** + * target_read_memory() gets us data in _target_ endianess. + * If we want to use this data on the host for comparisons with some macros + * we must first transform it to _host_ endianess using target_buffer_get_u16(). + */ + if (sdbbp32_instr == target_buffer_get_u32(target, current_instr)) { + retval = target_write_memory(target, breakpoint->address, 4, 1, + breakpoint->orig_instr); + if (retval != ERROR_OK) + return retval; + } + } else { /* 16bit alligned */ + retval = target_read_memory(target, breakpoint->address, 2, 2, current_instr); if (retval != ERROR_OK) return retval; + + if (sdbbp32_instr == target_buffer_get_u32(target, current_instr)) { + retval = target_write_memory(target, breakpoint->address, 2, 2, + breakpoint->orig_instr); + if (retval != ERROR_OK) + return retval; + } } } else { - uint16_t current_instr; - /* check that user program has not modified breakpoint instruction */ - retval = target_read_memory(target, breakpoint->address, 2, 1, - (uint8_t *)¤t_instr); + retval = target_read_memory(target, breakpoint->address, 2, 1, current_instr); if (retval != ERROR_OK) return retval; - current_instr = target_buffer_get_u16(target, (uint8_t *)¤t_instr); - if (current_instr == MIPS16_SDBBP(ejtag_info->isa)) { + + if (target_buffer_get_u16(target, current_instr) == MIPS16_SDBBP(isa_req)) { retval = target_write_memory(target, breakpoint->address, 2, 1, - breakpoint->orig_instr); + breakpoint->orig_instr); if (retval != ERROR_OK) return retval; } } } + breakpoint->set = 0; return ERROR_OK; @@ -774,6 +827,12 @@ static int mips_m4k_add_breakpoint(struct target *target, struct breakpoint *bre { struct mips32_common *mips32 = target_to_mips32(target); + if ((breakpoint->length > 5 || breakpoint->length < 2) || /* out of range */ + (breakpoint->length == 4 && (breakpoint->address & 2)) || /* mips32 unaligned */ + (mips32->isa_imp == MIPS32_ONLY && breakpoint->length != 4) || /* misp32 specific */ + ((mips32->isa_imp & 1) != (breakpoint->length & 1))) /* isa not implemented */ + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + if (breakpoint->type == BKPT_HARD) { if (mips32->num_inst_bpoints_avail < 1) { LOG_INFO("no hardware breakpoint available"); -- cgit v1.1 From f22b89d9fbc0d44b23f56e71429d0df909430036 Mon Sep 17 00:00:00 2001 From: Salvador Arroyo Date: Mon, 20 Feb 2017 20:45:37 +0100 Subject: mips32, use scan32 function for reading impcode/idcode. There is no need to implement scan code in functions mips_ejtag_get_idcode/impcode(), use mips_ejtag_drscan_32(). Impcode/idcode saved in ejtag.info. Reorder the code in the callers of this functions. Change-Id: Ia829c783a0b24c6a65cade736113fa6f67b0a170 Signed-off-by: Salvador Arroyo Reviewed-on: http://openocd.zylin.com/4003 Tested-by: jenkins Reviewed-by: Peter Mamonov Reviewed-by: Freddie Chopin --- src/target/mips_ejtag.c | 55 +++++++++---------------------------------------- src/target/mips_ejtag.h | 2 +- src/target/mips_m4k.c | 22 +++++++------------- 3 files changed, 19 insertions(+), 60 deletions(-) diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index d335c1b..03a0952 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -48,54 +48,20 @@ void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, uint32_t new_instr) } } -int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info, uint32_t *idcode) +int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info) { - struct scan_field field; - uint8_t r[4]; - mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IDCODE); - field.num_bits = 32; - field.out_value = NULL; - field.in_value = r; - - jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE); - - int retval; - retval = jtag_execute_queue(); - if (retval != ERROR_OK) { - LOG_ERROR("register read failed"); - return retval; - } - - *idcode = buf_get_u32(field.in_value, 0, 32); - - return ERROR_OK; + ejtag_info->idcode = 0; + return mips_ejtag_drscan_32(ejtag_info, &ejtag_info->idcode); } -static int mips_ejtag_get_impcode(struct mips_ejtag *ejtag_info, uint32_t *impcode) +int mips_ejtag_get_impcode(struct mips_ejtag *ejtag_info) { - struct scan_field field; - uint8_t r[4]; - mips_ejtag_set_instr(ejtag_info, EJTAG_INST_IMPCODE); - field.num_bits = 32; - field.out_value = NULL; - field.in_value = r; - - jtag_add_dr_scan(ejtag_info->tap, 1, &field, TAP_IDLE); - - int retval; - retval = jtag_execute_queue(); - if (retval != ERROR_OK) { - LOG_ERROR("register read failed"); - return retval; - } - - *impcode = buf_get_u32(field.in_value, 0, 32); - - return ERROR_OK; + ejtag_info->impcode = 0; + return mips_ejtag_drscan_32(ejtag_info, &ejtag_info->impcode); } void mips_ejtag_add_scan_96(struct mips_ejtag *ejtag_info, uint32_t ctrl, uint32_t data, uint8_t *in_scan_buf) @@ -368,12 +334,11 @@ static void ejtag_main_print_imp(struct mips_ejtag *ejtag_info) int mips_ejtag_init(struct mips_ejtag *ejtag_info) { - int retval; - - retval = mips_ejtag_get_impcode(ejtag_info, &ejtag_info->impcode); - if (retval != ERROR_OK) + int retval = mips_ejtag_get_impcode(ejtag_info); + if (retval != ERROR_OK) { + LOG_ERROR("impcode read failed"); return retval; - LOG_DEBUG("impcode: 0x%8.8" PRIx32 "", ejtag_info->impcode); + } /* get ejtag version */ ejtag_info->ejtag_version = ((ejtag_info->impcode >> 29) & 0x07); diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index 226863f..71f5c1b 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -219,7 +219,7 @@ struct mips_ejtag { void mips_ejtag_set_instr(struct mips_ejtag *ejtag_info, uint32_t new_instr); int mips_ejtag_enter_debug(struct mips_ejtag *ejtag_info); int mips_ejtag_exit_debug(struct mips_ejtag *ejtag_info); -int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info, uint32_t *idcode); +int mips_ejtag_get_idcode(struct mips_ejtag *ejtag_info); void mips_ejtag_add_scan_96(struct mips_ejtag *ejtag_info, uint32_t ctrl, uint32_t data, uint8_t *in_scan_buf); void mips_ejtag_drscan_32_out(struct mips_ejtag *ejtag_info, uint32_t data); diff --git a/src/target/mips_m4k.c b/src/target/mips_m4k.c index e2007d9..7d1c06c 100644 --- a/src/target/mips_m4k.c +++ b/src/target/mips_m4k.c @@ -1174,36 +1174,30 @@ static int mips_m4k_target_create(struct target *target, Jim_Interp *interp) static int mips_m4k_examine(struct target *target) { - int retval; struct mips_m4k_common *mips_m4k = target_to_m4k(target); struct mips_ejtag *ejtag_info = &mips_m4k->mips32.ejtag_info; - uint32_t idcode = 0; if (!target_was_examined(target)) { - retval = mips_ejtag_get_idcode(ejtag_info, &idcode); - if (retval != ERROR_OK) + int retval = mips_ejtag_get_idcode(ejtag_info); + if (retval != ERROR_OK) { + LOG_ERROR("idcode read failed"); return retval; - ejtag_info->idcode = idcode; - - if (((idcode >> 1) & 0x7FF) == 0x29) { + } + if (((ejtag_info->idcode >> 1) & 0x7FF) == 0x29) { /* we are using a pic32mx so select ejtag port * as it is not selected by default */ mips_ejtag_set_instr(ejtag_info, MTAP_SW_ETAP); - LOG_DEBUG("PIC32MX Detected - using EJTAG Interface"); + LOG_DEBUG("PIC32 Detected - using EJTAG Interface"); mips_m4k->is_pic32mx = true; } } /* init rest of ejtag interface */ - retval = mips_ejtag_init(ejtag_info); + int retval = mips_ejtag_init(ejtag_info); if (retval != ERROR_OK) return retval; - retval = mips32_examine(target); - if (retval != ERROR_OK) - return retval; - - return ERROR_OK; + return mips32_examine(target); } static int mips_m4k_bulk_write_memory(struct target *target, target_addr_t address, -- cgit v1.1 From 753cf12700959d05fd4e000cbd9951c22c5a2bfa Mon Sep 17 00:00:00 2001 From: Juha Niskanen Date: Thu, 4 May 2017 13:43:08 +0300 Subject: stm32l4: support flashing L45x/46x devices Also fixes incorrect comment about MSI range. Change-Id: If1339a00e50db44195dfcd5c767ba3f5d9035451 Signed-off-by: Juha Niskanen Reviewed-on: http://openocd.zylin.com/4122 Tested-by: jenkins Reviewed-by: Freddie Chopin --- src/flash/nor/stm32l4x.c | 25 ++++++++++++++++++------- tcl/target/stm32l4x.cfg | 2 +- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/flash/nor/stm32l4x.c b/src/flash/nor/stm32l4x.c index db68539..fa0c48b 100644 --- a/src/flash/nor/stm32l4x.c +++ b/src/flash/nor/stm32l4x.c @@ -27,18 +27,22 @@ /* STM32L4xxx series for reference. * - * RM0351 - * http://www.st.com/st-web-ui/static/active/en/resource/technical/document/reference_manual/DM00083560.pdf + * RM0351 (STM32L4x5/STM32L4x6) + * http://www.st.com/resource/en/reference_manual/dm00083560.pdf * - * STM32L476RG Datasheet (for erase timing) - * http://www.st.com/st-web-ui/static/active/en/resource/technical/document/datasheet/DM00108832.pdf + * RM0394 (STM32L43x/44x/45x/46x) + * http://www.st.com/resource/en/reference_manual/dm00151940.pdf * + * STM32L476RG Datasheet (for erase timing) + * http://www.st.com/resource/en/datasheet/stm32l476rg.pdf * - * The device has normally two banks, but on 512 and 256 kiB devices an - * option byte is available to map all sectors to the first bank. + * The RM0351 devices have normally two banks, but on 512 and 256 kiB devices + * an option byte is available to map all sectors to the first bank. * Both STM32 banks are treated as one OpenOCD bank, as other STM32 devices * handlers do! * + * RM0394 devices have a single bank only. + * */ /* Erase time can be as high as 25ms, 10x this and assume it's toast... */ @@ -618,6 +622,9 @@ static int stm32l4_probe(struct flash_bank *bank) case 0x415: max_flash_size_in_kb = 1024; break; + case 0x462: + max_flash_size_in_kb = 512; + break; case 0x435: max_flash_size_in_kb = 256; break; @@ -725,8 +732,12 @@ static int get_stm32l4_info(struct flash_bank *bank, char *buf, int buf_size) device_str = "STM32L475/476/486"; break; + case 0x462: + device_str = "STM32L45x/46x"; + break; + case 0x435: - device_str = "STM32L43x"; + device_str = "STM32L43x/44x"; break; default: diff --git a/tcl/target/stm32l4x.cfg b/tcl/target/stm32l4x.cfg index 9cad7c4..ccee48e 100644 --- a/tcl/target/stm32l4x.cfg +++ b/tcl/target/stm32l4x.cfg @@ -75,7 +75,7 @@ $_TARGETNAME configure -event reset-init { # Use MSI 24 MHz clock, compliant even with VOS == 2. # 3 WS compliant with VOS == 2 and 24 MHz. mww 0x40022000 0x00000103 ;# FLASH_ACR = PRFTBE | 3(Latency) - mww 0x40021000 0x00000099 ;# RCC_CR = MSI_ON | MSIRGSEL| MSI Range 10 + mww 0x40021000 0x00000099 ;# RCC_CR = MSI_ON | MSIRGSEL | MSI Range 9 # Boost JTAG frequency adapter_khz 4000 } -- cgit v1.1 From 16655c1dd5b9961e1d087b09cfe250f7fc48156e Mon Sep 17 00:00:00 2001 From: Moritz Fischer Date: Tue, 25 Apr 2017 22:18:49 -0700 Subject: tcl/cpld: add config file for Altera 5M570Z CPLD (MAXV family) Change-Id: I229c746be27b7c4fa01f48a6ed54ab2679b50ab1 Signed-off-by: Moritz Fischer Reviewed-on: http://openocd.zylin.com/4109 Tested-by: jenkins Reviewed-by: Paul Fertser --- tcl/cpld/altera-5m570z-cpld.cfg | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 tcl/cpld/altera-5m570z-cpld.cfg diff --git a/tcl/cpld/altera-5m570z-cpld.cfg b/tcl/cpld/altera-5m570z-cpld.cfg new file mode 100644 index 0000000..22a422c --- /dev/null +++ b/tcl/cpld/altera-5m570z-cpld.cfg @@ -0,0 +1,6 @@ +# Altera MAXV 5M24OZ/5M570Z CPLD +# see MAX V Device Handbook +# Table 6-3: 32-Bit MAX V Device IDCODE +# Version Part Number Manuf. ID LSB +# 0000 0010 0000 1010 0111 000 0110 1110 1 +jtag newtap 5m570z tap -expected-id 0x020a60dd -irlen 10 -- cgit v1.1 From f6449a7cba11de589c40169a7dd3b183bd60d1f4 Mon Sep 17 00:00:00 2001 From: Forest Crossman Date: Sat, 30 Jan 2016 00:23:49 -0500 Subject: jtag/drivers: Add Cypress KitProg driver This patch adds a driver for the SWD-only Cypress KitProg programmer/debugger. Change-Id: I3a9a8011a762781d560ebb305597e782a4f9a8e5 Signed-off-by: Forest Crossman Reviewed-on: http://openocd.zylin.com/3221 Tested-by: jenkins Reviewed-by: Tomas Vanek --- configure.ac | 8 +- contrib/60-openocd.rules | 6 + doc/openocd.texi | 56 +++ src/jtag/drivers/Makefile.am | 4 + src/jtag/drivers/kitprog.c | 967 +++++++++++++++++++++++++++++++++++++++++++ src/jtag/interfaces.c | 6 + tcl/interface/kitprog.cfg | 12 + 7 files changed, 1058 insertions(+), 1 deletion(-) create mode 100644 src/jtag/drivers/kitprog.c create mode 100644 tcl/interface/kitprog.cfg diff --git a/configure.ac b/configure.ac index 6e60733..f5d3b9e 100644 --- a/configure.ac +++ b/configure.ac @@ -129,6 +129,9 @@ m4_define([USB0_ADAPTERS], m4_define([HIDAPI_ADAPTERS], [[[cmsis_dap], [CMSIS-DAP Compliant Debugger], [CMSIS_DAP]]]) +m4_define([HIDAPI_USB1_ADAPTERS], + [[[kitprog], [Cypress KitProg Programmer], [KITPROG]]]) + m4_define([LIBFTDI_ADAPTERS], [[[usb_blaster], [Altera USB-Blaster Compatible], [USB_BLASTER]], [[presto], [ASIX Presto Adapter], [PRESTO]], @@ -243,6 +246,7 @@ AC_ARG_ADAPTERS([ USB_ADAPTERS, USB0_ADAPTERS, HIDAPI_ADAPTERS, + HIDAPI_USB1_ADAPTERS, LIBFTDI_ADAPTERS, LIBJAYLINK_ADAPTERS ],[auto]) @@ -638,6 +642,7 @@ PROCESS_ADAPTERS([USB1_ADAPTERS], ["x$use_libusb1" = "xyes"], [libusb-1.x]) PROCESS_ADAPTERS([USB_ADAPTERS], ["x$use_libusb1" = "xyes" -o "x$use_libusb0" = "xyes"], [libusb-1.x or libusb-0.1]) PROCESS_ADAPTERS([USB0_ADAPTERS], ["x$use_libusb0" = "xyes"], [libusb-0.1]) PROCESS_ADAPTERS([HIDAPI_ADAPTERS], ["x$use_hidapi" = "xyes"], [hidapi]) +PROCESS_ADAPTERS([HIDAPI_USB1_ADAPTERS], ["x$use_hidapi" = "xyes" -a "x$use_libusb1" = "xyes"], [hidapi and libusb-1.x]) PROCESS_ADAPTERS([LIBFTDI_ADAPTERS], ["x$use_libftdi" = "xyes"], [libftdi]) PROCESS_ADAPTERS([LIBJAYLINK_ADAPTERS], ["x$use_libusb1" = "xyes" -a "x$use_internal_libjaylink" = "xyes" -o "x$use_libjaylink" = "xyes"], [libusb-1.x or libjaylink-0.1]) @@ -768,7 +773,8 @@ echo echo OpenOCD configuration summary echo -------------------------------------------------- m4_foreach([adapter], [USB1_ADAPTERS, USB_ADAPTERS, USB0_ADAPTERS, - HIDAPI_ADAPTERS, LIBFTDI_ADAPTERS, LIBJAYLINK_ADAPTERS], + HIDAPI_ADAPTERS, HIDAPI_USB1_ADAPTERS, LIBFTDI_ADAPTERS, + LIBJAYLINK_ADAPTERS], [s=m4_format(["%-40s"], ADAPTER_DESC([adapter])) AS_CASE([$ADAPTER_VAR([adapter])], [auto], [ diff --git a/contrib/60-openocd.rules b/contrib/60-openocd.rules index 3597c95..da760f8 100644 --- a/contrib/60-openocd.rules +++ b/contrib/60-openocd.rules @@ -62,6 +62,12 @@ ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE="660", GROUP="plugdev", # STLink v2-1 ATTRS{idVendor}=="0483", ATTRS{idProduct}=="374b", MODE="660", GROUP="plugdev", TAG+="uaccess" +# Cypress KitProg in KitProg mode +ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="f139", MODE="660", GROUP="plugdev", TAG+="uaccess" + +# Cypress KitProg in CMSIS-DAP mode +ATTRS{idVendor}=="04b4", ATTRS{idProduct}=="f138", MODE="660", GROUP="plugdev", TAG+="uaccess" + # Hilscher NXHX Boards ATTRS{idVendor}=="0640", ATTRS{idProduct}=="0028", MODE="660", GROUP="plugdev", TAG+="uaccess" diff --git a/doc/openocd.texi b/doc/openocd.texi index a60474b..845080e 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -2742,6 +2742,62 @@ As a configuration command, it can be used only before 'init'. @end deffn @end deffn +@deffn {Interface Driver} {kitprog} +This driver is for Cypress Semiconductor's KitProg adapters. The KitProg is an +SWD-only adapter that is designed to be used with Cypress's PSoC and PRoC device +families, but it is possible to use it with some other devices. If you are using +this adapter with a PSoC or a PRoC, you may need to add +@command{kitprog_init_acquire_psoc} or @command{kitprog acquire_psoc} to your +configuration script. + +Note that this driver is for the proprietary KitProg protocol, not the CMSIS-DAP +mode introduced in firmware 2.14. If the KitProg is in CMSIS-DAP mode, it cannot +be used with this driver, and must either be used with the cmsis-dap driver or +switched back to KitProg mode. See the Cypress KitProg User Guide for +instructions on how to switch KitProg modes. + +Known limitations: +@itemize @bullet +@item The frequency of SWCLK cannot be configured, and varies between 1.6 MHz +and 2.7 MHz. +@item For firmware versions below 2.14, "JTAG to SWD" sequences are replaced by +"SWD line reset" in the driver. This is for two reasons. First, the KitProg does +not support sending arbitrary SWD sequences, and only firmware 2.14 and later +implement both "JTAG to SWD" and "SWD line reset" in firmware. Earlier firmware +versions only implement "SWD line reset". Second, due to a firmware quirk, an +SWD sequence must be sent after every target reset in order to re-establish +communications with the target. +@item Due in part to the limitation above, KitProg devices with firmware below +version 2.14 will need to use @command{kitprog_init_acquire_psoc} in order to +communicate with PSoC 5LP devices. This is because, assuming debug is not +disabled on the PSoC, the PSoC 5LP needs its JTAG interface switched to SWD +mode before communication can begin, but prior to firmware 2.14, "JTAG to SWD" +could only be sent with an acquisition sequence. +@end itemize + +@deffn {Config Command} {kitprog_init_acquire_psoc} +Indicate that a PSoC acquisition sequence needs to be run during adapter init. +Please be aware that the acquisition sequence hard-resets the target. +@end deffn + +@deffn {Config Command} {kitprog_serial} serial +Select a KitProg device by its @var{serial}. If left unspecified, the first +device detected by OpenOCD will be used. +@end deffn + +@deffn {Command} {kitprog acquire_psoc} +Run a PSoC acquisition sequence immediately. Typically, this should not be used +outside of the target-specific configuration scripts since it hard-resets the +target as a side-effect. +This is necessary for "reset halt" on some PSoC 4 series devices. +@end deffn + +@deffn {Command} {kitprog info} +Display various adapter information, such as the hardware version, firmware +version, and target voltage. +@end deffn +@end deffn + @deffn {Interface Driver} {parport} Supports PC parallel port bit-banging cables: Wigglers, PLD download cable, and more. diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index e411412..e0c5421 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -153,6 +153,10 @@ if CMSIS_DAP DRIVERFILES += %D%/cmsis_dap_usb.c endif +if KITPROG +DRIVERFILES += %D%/kitprog.c +endif + DRIVERHEADERS = \ %D%/bitbang.h \ %D%/bitq.h \ diff --git a/src/jtag/drivers/kitprog.c b/src/jtag/drivers/kitprog.c new file mode 100644 index 0000000..c689848 --- /dev/null +++ b/src/jtag/drivers/kitprog.c @@ -0,0 +1,967 @@ +/*************************************************************************** + * Copyright (C) 2007 by Juergen Stuber * + * based on Dominic Rath's and Benedikt Sauter's usbprog.c * + * * + * Copyright (C) 2008 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * + * Copyright (C) 2011 by Jean-Christophe PLAGNIOL-VIILARD * + * plagnioj@jcrosoft.com * + * * + * Copyright (C) 2015 by Marc Schink * + * openocd-dev@marcschink.de * + * * + * Copyright (C) 2015 by Paul Fertser * + * fercerpav@gmail.com * + * * + * Copyright (C) 2015-2017 by Forest Crossman * + * cyrozap@gmail.com * + * * + * 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, see . * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include + +#include +#include +#include + +#include "libusb_common.h" + +#define VID 0x04b4 +#define PID 0xf139 + +#define BULK_EP_IN 1 +#define BULK_EP_OUT 2 + +#define CONTROL_TYPE_READ 0x01 +#define CONTROL_TYPE_WRITE 0x02 + +#define CONTROL_COMMAND_PROGRAM 0x07 + +#define CONTROL_MODE_POLL_PROGRAMMER_STATUS 0x01 +#define CONTROL_MODE_RESET_TARGET 0x04 +#define CONTROL_MODE_SET_PROGRAMMER_PROTOCOL 0x40 +#define CONTROL_MODE_SYNCHRONIZE_TRANSFER 0x41 +#define CONTROL_MODE_ACQUIRE_SWD_TARGET 0x42 +#define CONTROL_MODE_SEND_SWD_SEQUENCE 0x43 + +#define PROTOCOL_JTAG 0x00 +#define PROTOCOL_SWD 0x01 + +#define DEVICE_PSOC4 0x00 +#define DEVICE_PSOC3 0x01 +#define DEVICE_UNKNOWN 0x02 +#define DEVICE_PSOC5 0x03 + +#define ACQUIRE_MODE_RESET 0x00 +#define ACQUIRE_MODE_POWER_CYCLE 0x01 + +#define SEQUENCE_LINE_RESET 0x00 +#define SEQUENCE_JTAG_TO_SWD 0x01 + +#define PROGRAMMER_NOK_NACK 0x00 +#define PROGRAMMER_OK_ACK 0x01 + +#define HID_TYPE_WRITE 0x00 +#define HID_TYPE_READ 0x01 +#define HID_TYPE_START 0x02 + +#define HID_COMMAND_POWER 0x80 +#define HID_COMMAND_VERSION 0x81 +#define HID_COMMAND_RESET 0x82 +#define HID_COMMAND_CONFIGURE 0x8f +#define HID_COMMAND_BOOTLOADER 0xa0 + +/* 512 bytes seems to work reliably */ +#define SWD_MAX_BUFFER_LENGTH 512 + +struct kitprog { + hid_device *hid_handle; + struct jtag_libusb_device_handle *usb_handle; + uint16_t packet_size; + uint16_t packet_index; + uint8_t *packet_buffer; + char *serial; + uint8_t hardware_version; + uint8_t minor_version; + uint8_t major_version; + uint16_t millivolts; + + bool supports_jtag_to_swd; +}; + +struct pending_transfer_result { + uint8_t cmd; + uint32_t data; + void *buffer; +}; + +static char *kitprog_serial; +static bool kitprog_init_acquire_psoc; + +static int pending_transfer_count, pending_queue_len; +static struct pending_transfer_result *pending_transfers; + +static int queued_retval; + +static struct kitprog *kitprog_handle; + +static int kitprog_usb_open(void); +static void kitprog_usb_close(void); + +static int kitprog_hid_command(uint8_t *command, size_t command_length, + uint8_t *data, size_t data_length); +static int kitprog_get_version(void); +static int kitprog_get_millivolts(void); +static int kitprog_get_info(void); +static int kitprog_set_protocol(uint8_t protocol); +static int kitprog_get_status(void); +static int kitprog_set_unknown(void); +static int kitprog_acquire_psoc(uint8_t psoc_type, uint8_t acquire_mode, + uint8_t max_attempts); +static int kitprog_reset_target(void); +static int kitprog_swd_sync(void); +static int kitprog_swd_seq(uint8_t seq_type); + +static int kitprog_generic_acquire(void); + +static int kitprog_swd_run_queue(void); +static void kitprog_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data); +static int kitprog_swd_switch_seq(enum swd_special_seq seq); + + +static inline int mm_to_version(uint8_t major, uint8_t minor) +{ + return (major << 8) | minor; +} + +static int kitprog_init(void) +{ + int retval; + + kitprog_handle = malloc(sizeof(struct kitprog)); + if (kitprog_handle == NULL) { + LOG_ERROR("Failed to allocate memory"); + return ERROR_FAIL; + } + + if (kitprog_usb_open() != ERROR_OK) { + LOG_ERROR("Can't find a KitProg device! Please check device connections and permissions."); + return ERROR_JTAG_INIT_FAILED; + } + + /* Get the current KitProg version and target voltage */ + if (kitprog_get_info() != ERROR_OK) + return ERROR_FAIL; + + /* Compatibility check */ + kitprog_handle->supports_jtag_to_swd = true; + int kitprog_version = mm_to_version(kitprog_handle->major_version, kitprog_handle->minor_version); + if (kitprog_version < mm_to_version(2, 14)) { + LOG_WARNING("KitProg firmware versions below v2.14 do not support sending JTAG to SWD sequences. These sequences will be substituted with SWD line resets."); + kitprog_handle->supports_jtag_to_swd = false; + } + + /* I have no idea what this does */ + if (kitprog_set_unknown() != ERROR_OK) + return ERROR_FAIL; + + /* SWD won't work unless we do this */ + if (kitprog_swd_sync() != ERROR_OK) + return ERROR_FAIL; + + /* Set the protocol to SWD */ + if (kitprog_set_protocol(PROTOCOL_SWD) != ERROR_OK) + return ERROR_FAIL; + + /* Reset the SWD bus */ + if (kitprog_swd_seq(SEQUENCE_LINE_RESET) != ERROR_OK) + return ERROR_FAIL; + + if (kitprog_init_acquire_psoc) { + /* Try to acquire any device that will respond */ + retval = kitprog_generic_acquire(); + if (retval != ERROR_OK) { + LOG_ERROR("No PSoC devices found"); + return retval; + } + } + + /* Allocate packet buffers and queues */ + kitprog_handle->packet_size = SWD_MAX_BUFFER_LENGTH; + kitprog_handle->packet_buffer = malloc(SWD_MAX_BUFFER_LENGTH); + if (kitprog_handle->packet_buffer == NULL) { + LOG_ERROR("Failed to allocate memory for the packet buffer"); + return ERROR_FAIL; + } + + pending_queue_len = SWD_MAX_BUFFER_LENGTH / 5; + pending_transfers = malloc(pending_queue_len * sizeof(*pending_transfers)); + if (pending_transfers == NULL) { + LOG_ERROR("Failed to allocate memory for the SWD transfer queue"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_quit(void) +{ + kitprog_usb_close(); + + if (kitprog_handle->packet_buffer != NULL) + free(kitprog_handle->packet_buffer); + if (kitprog_handle->serial != NULL) + free(kitprog_handle->serial); + if (kitprog_handle != NULL) + free(kitprog_handle); + + if (kitprog_serial != NULL) + free(kitprog_serial); + + if (pending_transfers != NULL) + free(pending_transfers); + + return ERROR_OK; +} + +/*************** kitprog usb functions *********************/ + +static int kitprog_get_usb_serial(void) +{ + int retval; + const uint8_t str_index = 128; /* This seems to be a constant */ + char desc_string[256+1]; /* Max size of string descriptor */ + + retval = libusb_get_string_descriptor_ascii(kitprog_handle->usb_handle, + str_index, (unsigned char *)desc_string, sizeof(desc_string)-1); + if (retval < 0) { + LOG_ERROR("libusb_get_string_descriptor_ascii() failed with %d", retval); + return ERROR_FAIL; + } + + /* Null terminate descriptor string */ + desc_string[retval] = '\0'; + + /* Allocate memory for the serial number */ + kitprog_handle->serial = calloc(retval + 1, sizeof(char)); + if (kitprog_handle->serial == NULL) { + LOG_ERROR("Failed to allocate memory for the serial number"); + return ERROR_FAIL; + } + + /* Store the serial number */ + strncpy(kitprog_handle->serial, desc_string, retval + 1); + + return ERROR_OK; +} + +static int kitprog_usb_open(void) +{ + const uint16_t vids[] = { VID, 0 }; + const uint16_t pids[] = { PID, 0 }; + + if (jtag_libusb_open(vids, pids, kitprog_serial, + &kitprog_handle->usb_handle) != ERROR_OK) { + LOG_ERROR("Failed to open or find the device"); + return ERROR_FAIL; + } + + /* Get the serial number for the device */ + if (kitprog_get_usb_serial() != ERROR_OK) + LOG_WARNING("Failed to get KitProg serial number"); + + /* Convert the ASCII serial number into a (wchar_t *) */ + size_t len = strlen(kitprog_handle->serial); + wchar_t *hid_serial = calloc(len + 1, sizeof(wchar_t)); + if (hid_serial == NULL) { + LOG_ERROR("Failed to allocate memory for the serial number"); + return ERROR_FAIL; + } + if (mbstowcs(hid_serial, kitprog_handle->serial, len + 1) == (size_t)-1) { + free(hid_serial); + LOG_ERROR("Failed to convert serial number"); + return ERROR_FAIL; + } + + /* Use HID for the KitBridge interface */ + kitprog_handle->hid_handle = hid_open(VID, PID, hid_serial); + free(hid_serial); + if (kitprog_handle->hid_handle == NULL) { + LOG_ERROR("Failed to open KitBridge (HID) interface"); + return ERROR_FAIL; + } + + /* Claim the KitProg Programmer (bulk transfer) interface */ + if (jtag_libusb_claim_interface(kitprog_handle->usb_handle, 1) != ERROR_OK) { + LOG_ERROR("Failed to claim KitProg Programmer (bulk transfer) interface"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static void kitprog_usb_close(void) +{ + if (kitprog_handle->hid_handle != NULL) { + hid_close(kitprog_handle->hid_handle); + hid_exit(); + } + + jtag_libusb_close(kitprog_handle->usb_handle); +} + +/*************** kitprog lowlevel functions *********************/ + +static int kitprog_hid_command(uint8_t *command, size_t command_length, + uint8_t *data, size_t data_length) +{ + int ret; + + ret = hid_write(kitprog_handle->hid_handle, command, command_length); + if (ret < 0) { + LOG_DEBUG("HID write returned %i", ret); + return ERROR_FAIL; + } + + ret = hid_read(kitprog_handle->hid_handle, data, data_length); + if (ret < 0) { + LOG_DEBUG("HID read returned %i", ret); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_get_version(void) +{ + int ret; + + unsigned char command[3] = {HID_TYPE_START | HID_TYPE_WRITE, 0x00, HID_COMMAND_VERSION}; + unsigned char data[64]; + + ret = kitprog_hid_command(command, sizeof command, data, sizeof data); + if (ret != ERROR_OK) + return ret; + + kitprog_handle->hardware_version = data[1]; + kitprog_handle->minor_version = data[2]; + kitprog_handle->major_version = data[3]; + + return ERROR_OK; +} + +static int kitprog_get_millivolts(void) +{ + int ret; + + unsigned char command[3] = {HID_TYPE_START | HID_TYPE_READ, 0x00, HID_COMMAND_POWER}; + unsigned char data[64]; + + ret = kitprog_hid_command(command, sizeof command, data, sizeof data); + if (ret != ERROR_OK) + return ret; + + kitprog_handle->millivolts = (data[4] << 8) | data[3]; + + return ERROR_OK; +} + +static int kitprog_get_info(void) +{ + /* Get the device version information */ + if (kitprog_get_version() == ERROR_OK) { + LOG_INFO("KitProg v%u.%02u", + kitprog_handle->major_version, kitprog_handle->minor_version); + LOG_INFO("Hardware version: %u", + kitprog_handle->hardware_version); + } else { + LOG_ERROR("Failed to get KitProg version"); + return ERROR_FAIL; + } + + /* Get the current reported target voltage */ + if (kitprog_get_millivolts() == ERROR_OK) { + LOG_INFO("VTARG = %u.%03u V", + kitprog_handle->millivolts / 1000, kitprog_handle->millivolts % 1000); + } else { + LOG_ERROR("Failed to get target voltage"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_set_protocol(uint8_t protocol) +{ + int transferred; + char status = PROGRAMMER_NOK_NACK; + + transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + CONTROL_TYPE_WRITE, + (CONTROL_MODE_SET_PROGRAMMER_PROTOCOL << 8) | CONTROL_COMMAND_PROGRAM, + protocol, &status, 1, 0); + + if (transferred == 0) { + LOG_DEBUG("Zero bytes transferred"); + return ERROR_FAIL; + } + + if (status != PROGRAMMER_OK_ACK) { + LOG_DEBUG("Programmer did not respond OK"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_get_status(void) +{ + int transferred = 0; + char status = PROGRAMMER_NOK_NACK; + + /* Try a maximum of three times */ + for (int i = 0; (i < 3) && (transferred == 0); i++) { + transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + CONTROL_TYPE_READ, + (CONTROL_MODE_POLL_PROGRAMMER_STATUS << 8) | CONTROL_COMMAND_PROGRAM, + 0, &status, 1, 0); + jtag_sleep(1000); + } + + if (transferred == 0) { + LOG_DEBUG("Zero bytes transferred"); + return ERROR_FAIL; + } + + if (status != PROGRAMMER_OK_ACK) { + LOG_DEBUG("Programmer did not respond OK"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_set_unknown(void) +{ + int transferred; + char status = PROGRAMMER_NOK_NACK; + + transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + CONTROL_TYPE_WRITE, + (0x03 << 8) | 0x04, + 0, &status, 1, 0); + + if (transferred == 0) { + LOG_DEBUG("Zero bytes transferred"); + return ERROR_FAIL; + } + + if (status != PROGRAMMER_OK_ACK) { + LOG_DEBUG("Programmer did not respond OK"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_acquire_psoc(uint8_t psoc_type, uint8_t acquire_mode, + uint8_t max_attempts) +{ + int transferred; + char status = PROGRAMMER_NOK_NACK; + + transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + CONTROL_TYPE_WRITE, + (CONTROL_MODE_ACQUIRE_SWD_TARGET << 8) | CONTROL_COMMAND_PROGRAM, + (max_attempts << 8) | (acquire_mode << 4) | psoc_type, &status, 1, 0); + + if (transferred == 0) { + LOG_DEBUG("Zero bytes transferred"); + return ERROR_FAIL; + } + + if (status != PROGRAMMER_OK_ACK) { + LOG_DEBUG("Programmer did not respond OK"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_reset_target(void) +{ + int transferred; + char status = PROGRAMMER_NOK_NACK; + + transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + CONTROL_TYPE_WRITE, + (CONTROL_MODE_RESET_TARGET << 8) | CONTROL_COMMAND_PROGRAM, + 0, &status, 1, 0); + + if (transferred == 0) { + LOG_DEBUG("Zero bytes transferred"); + return ERROR_FAIL; + } + + if (status != PROGRAMMER_OK_ACK) { + LOG_DEBUG("Programmer did not respond OK"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_swd_sync(void) +{ + int transferred; + char status = PROGRAMMER_NOK_NACK; + + transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + CONTROL_TYPE_WRITE, + (CONTROL_MODE_SYNCHRONIZE_TRANSFER << 8) | CONTROL_COMMAND_PROGRAM, + 0, &status, 1, 0); + + if (transferred == 0) { + LOG_DEBUG("Zero bytes transferred"); + return ERROR_FAIL; + } + + if (status != PROGRAMMER_OK_ACK) { + LOG_DEBUG("Programmer did not respond OK"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_swd_seq(uint8_t seq_type) +{ + int transferred; + char status = PROGRAMMER_NOK_NACK; + + transferred = jtag_libusb_control_transfer(kitprog_handle->usb_handle, + LIBUSB_ENDPOINT_IN | LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_RECIPIENT_DEVICE, + CONTROL_TYPE_WRITE, + (CONTROL_MODE_SEND_SWD_SEQUENCE << 8) | CONTROL_COMMAND_PROGRAM, + seq_type, &status, 1, 0); + + if (transferred == 0) { + LOG_DEBUG("Zero bytes transferred"); + return ERROR_FAIL; + } + + if (status != PROGRAMMER_OK_ACK) { + LOG_DEBUG("Programmer did not respond OK"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_generic_acquire(void) +{ + const uint8_t devices[] = {DEVICE_PSOC4, DEVICE_PSOC3, DEVICE_PSOC5}; + + int retval; + int acquire_count = 0; + + /* Due to the way the SWD port is shared between the Test Controller (TC) + * and the Cortex-M3 DAP on the PSoC 5LP, the TC is the default SWD target + * after power is applied. To access the DAP, the PSoC 5LP requires at least + * one acquisition sequence to be run (which switches the SWD mux from the + * TC to the DAP). However, after the mux is switched, the Cortex-M3 will be + * held in reset until a series of registers are written to (see section 5.2 + * of the PSoC 5LP Device Programming Specifications for details). + * + * Instead of writing the registers in this function, we just do what the + * Cypress tools do and run the acquisition sequence a second time. This + * will take the Cortex-M3 out of reset and enable debugging. + */ + for (int i = 0; i < 2; i++) { + for (uint8_t j = 0; j < sizeof devices && acquire_count == i; j++) { + retval = kitprog_acquire_psoc(devices[j], ACQUIRE_MODE_RESET, 3); + if (retval != ERROR_OK) { + LOG_DEBUG("Aquisition function failed for device 0x%02x.", devices[j]); + return retval; + } + + if (kitprog_get_status() == ERROR_OK) + acquire_count++; + } + + jtag_sleep(10); + } + + if (acquire_count < 2) + return ERROR_FAIL; + + return ERROR_OK; +} + +/*************** swd wrapper functions *********************/ + +static int kitprog_swd_init(void) +{ + return ERROR_OK; +} + +static void kitprog_swd_write_reg(uint8_t cmd, uint32_t value, uint32_t ap_delay_clk) +{ + assert(!(cmd & SWD_CMD_RnW)); + kitprog_swd_queue_cmd(cmd, NULL, value); +} + +static void kitprog_swd_read_reg(uint8_t cmd, uint32_t *value, uint32_t ap_delay_clk) +{ + assert(cmd & SWD_CMD_RnW); + kitprog_swd_queue_cmd(cmd, value, 0); +} + +/*************** swd lowlevel functions ********************/ + +static int kitprog_swd_switch_seq(enum swd_special_seq seq) +{ + switch (seq) { + case JTAG_TO_SWD: + if (kitprog_handle->supports_jtag_to_swd) { + LOG_DEBUG("JTAG to SWD"); + if (kitprog_swd_seq(SEQUENCE_JTAG_TO_SWD) != ERROR_OK) + return ERROR_FAIL; + break; + } else { + LOG_DEBUG("JTAG to SWD not supported"); + /* Fall through to fix target reset issue */ + } + case LINE_RESET: + LOG_DEBUG("SWD line reset"); + if (kitprog_swd_seq(SEQUENCE_LINE_RESET) != ERROR_OK) + return ERROR_FAIL; + break; + default: + LOG_ERROR("Sequence %d not supported.", seq); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int kitprog_swd_run_queue(void) +{ + int ret; + + size_t read_count = 0; + size_t read_index = 0; + size_t write_count = 0; + uint8_t *buffer = kitprog_handle->packet_buffer; + + do { + LOG_DEBUG("Executing %d queued transactions", pending_transfer_count); + + if (queued_retval != ERROR_OK) { + LOG_DEBUG("Skipping due to previous errors: %d", queued_retval); + break; + } + + if (!pending_transfer_count) + break; + + for (int i = 0; i < pending_transfer_count; i++) { + uint8_t cmd = pending_transfers[i].cmd; + uint32_t data = pending_transfers[i].data; + + /* When proper WAIT handling is implemented in the + * common SWD framework, this kludge can be + * removed. However, this might lead to minor + * performance degradation as the adapter wouldn't be + * able to automatically retry anything (because ARM + * has forgotten to implement sticky error flags + * clearing). See also comments regarding + * cmsis_dap_cmd_DAP_TFER_Configure() and + * cmsis_dap_cmd_DAP_SWD_Configure() in + * cmsis_dap_init(). + */ + if (!(cmd & SWD_CMD_RnW) && + !(cmd & SWD_CMD_APnDP) && + (cmd & SWD_CMD_A32) >> 1 == DP_CTRL_STAT && + (data & CORUNDETECT)) { + LOG_DEBUG("refusing to enable sticky overrun detection"); + data &= ~CORUNDETECT; + } + +#if 0 + LOG_DEBUG("%s %s reg %x %"PRIx32, + cmd & SWD_CMD_APnDP ? "AP" : "DP", + cmd & SWD_CMD_RnW ? "read" : "write", + (cmd & SWD_CMD_A32) >> 1, data); +#endif + + buffer[write_count++] = (cmd | SWD_CMD_START | SWD_CMD_PARK) & ~SWD_CMD_STOP; + read_count++; + if (!(cmd & SWD_CMD_RnW)) { + buffer[write_count++] = (data) & 0xff; + buffer[write_count++] = (data >> 8) & 0xff; + buffer[write_count++] = (data >> 16) & 0xff; + buffer[write_count++] = (data >> 24) & 0xff; + } else { + read_count += 4; + } + } + + ret = jtag_libusb_bulk_write(kitprog_handle->usb_handle, + BULK_EP_OUT, (char *)buffer, write_count, 0); + if (ret > 0) { + queued_retval = ERROR_OK; + } else { + LOG_ERROR("Bulk write failed"); + queued_retval = ERROR_FAIL; + break; + } + + /* We use the maximum buffer size here because the KitProg sometimes + * doesn't like bulk reads of fewer than 62 bytes. (?!?!) + */ + ret = jtag_libusb_bulk_read(kitprog_handle->usb_handle, + BULK_EP_IN | LIBUSB_ENDPOINT_IN, (char *)buffer, + SWD_MAX_BUFFER_LENGTH, 0); + if (ret > 0) { + /* Handle garbage data by offsetting the initial read index */ + if ((unsigned int)ret > read_count) + read_index = ret - read_count; + queued_retval = ERROR_OK; + } else { + LOG_ERROR("Bulk read failed"); + queued_retval = ERROR_FAIL; + break; + } + + for (int i = 0; i < pending_transfer_count; i++) { + if (pending_transfers[i].cmd & SWD_CMD_RnW) { + uint32_t data = le_to_h_u32(&buffer[read_index]); + +#if 0 + LOG_DEBUG("Read result: %"PRIx32, data); +#endif + + if (pending_transfers[i].buffer) + *(uint32_t *)pending_transfers[i].buffer = data; + + read_index += 4; + } + + uint8_t ack = buffer[read_index] & 0x07; + if (ack != SWD_ACK_OK || (buffer[read_index] & 0x08)) { + LOG_DEBUG("SWD ack not OK: %d %s", i, + ack == SWD_ACK_WAIT ? "WAIT" : ack == SWD_ACK_FAULT ? "FAULT" : "JUNK"); + queued_retval = ack == SWD_ACK_WAIT ? ERROR_WAIT : ERROR_FAIL; + break; + } + read_index++; + } + } while (0); + + pending_transfer_count = 0; + int retval = queued_retval; + queued_retval = ERROR_OK; + + return retval; +} + +static void kitprog_swd_queue_cmd(uint8_t cmd, uint32_t *dst, uint32_t data) +{ + if (pending_transfer_count == pending_queue_len) { + /* Not enough room in the queue. Run the queue. */ + queued_retval = kitprog_swd_run_queue(); + } + + if (queued_retval != ERROR_OK) + return; + + pending_transfers[pending_transfer_count].data = data; + pending_transfers[pending_transfer_count].cmd = cmd; + if (cmd & SWD_CMD_RnW) { + /* Queue a read transaction */ + pending_transfers[pending_transfer_count].buffer = dst; + } + pending_transfer_count++; +} + +/*************** jtag lowlevel functions ********************/ + +static void kitprog_execute_reset(struct jtag_command *cmd) +{ + int retval = ERROR_OK; + + if (cmd->cmd.reset->srst == 1) { + retval = kitprog_reset_target(); + /* Since the previous command also disables SWCLK output, we need to send an + * SWD bus reset command to re-enable it. For some reason, running + * kitprog_swd_seq() immediately after kitprog_reset_target() won't + * actually fix this. Instead, kitprog_swd_seq() will be run once OpenOCD + * tries to send a JTAG-to-SWD sequence, which should happen during + * swd_check_reconnect (see the JTAG_TO_SWD case in kitprog_swd_switch_seq). + */ + } + + if (retval != ERROR_OK) + LOG_ERROR("KitProg: Interface reset failed"); +} + +static void kitprog_execute_sleep(struct jtag_command *cmd) +{ + jtag_sleep(cmd->cmd.sleep->us); +} + +static void kitprog_execute_command(struct jtag_command *cmd) +{ + switch (cmd->type) { + case JTAG_RESET: + kitprog_execute_reset(cmd); + break; + case JTAG_SLEEP: + kitprog_execute_sleep(cmd); + break; + default: + LOG_ERROR("BUG: unknown JTAG command type encountered"); + exit(-1); + } +} + +static int kitprog_execute_queue(void) +{ + struct jtag_command *cmd = jtag_command_queue; + + while (cmd != NULL) { + kitprog_execute_command(cmd); + cmd = cmd->next; + } + + return ERROR_OK; +} + +COMMAND_HANDLER(kitprog_handle_info_command) +{ + int retval = kitprog_get_info(); + + return retval; +} + + +COMMAND_HANDLER(kitprog_handle_acquire_psoc_command) +{ + int retval = kitprog_generic_acquire(); + + return retval; +} + +COMMAND_HANDLER(kitprog_handle_serial_command) +{ + if (CMD_ARGC == 1) { + size_t len = strlen(CMD_ARGV[0]); + kitprog_serial = calloc(len + 1, sizeof(char)); + if (kitprog_serial == NULL) { + LOG_ERROR("Failed to allocate memory for the serial number"); + return ERROR_FAIL; + } + strncpy(kitprog_serial, CMD_ARGV[0], len + 1); + } else { + LOG_ERROR("expected exactly one argument to kitprog_serial "); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +COMMAND_HANDLER(kitprog_handle_init_acquire_psoc_command) +{ + kitprog_init_acquire_psoc = true; + + return ERROR_OK; +} + +static const struct command_registration kitprog_subcommand_handlers[] = { + { + .name = "info", + .handler = &kitprog_handle_info_command, + .mode = COMMAND_EXEC, + .usage = "", + .help = "show KitProg info", + }, + { + .name = "acquire_psoc", + .handler = &kitprog_handle_acquire_psoc_command, + .mode = COMMAND_EXEC, + .usage = "", + .help = "try to acquire a PSoC", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct command_registration kitprog_command_handlers[] = { + { + .name = "kitprog", + .mode = COMMAND_ANY, + .help = "perform KitProg management", + .usage = "", + .chain = kitprog_subcommand_handlers, + }, + { + .name = "kitprog_serial", + .handler = &kitprog_handle_serial_command, + .mode = COMMAND_CONFIG, + .help = "set the serial number of the adapter", + .usage = "serial_string", + }, + { + .name = "kitprog_init_acquire_psoc", + .handler = &kitprog_handle_init_acquire_psoc_command, + .mode = COMMAND_CONFIG, + .help = "try to acquire a PSoC during init", + .usage = "", + }, + COMMAND_REGISTRATION_DONE +}; + +static const struct swd_driver kitprog_swd = { + .init = kitprog_swd_init, + .switch_seq = kitprog_swd_switch_seq, + .read_reg = kitprog_swd_read_reg, + .write_reg = kitprog_swd_write_reg, + .run = kitprog_swd_run_queue, +}; + +static const char * const kitprog_transports[] = { "swd", NULL }; + +struct jtag_interface kitprog_interface = { + .name = "kitprog", + .commands = kitprog_command_handlers, + .transports = kitprog_transports, + .swd = &kitprog_swd, + .execute_queue = kitprog_execute_queue, + .init = kitprog_init, + .quit = kitprog_quit +}; diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index ad656a8..396043d 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -123,6 +123,9 @@ extern struct jtag_interface bcm2835gpio_interface; #if BUILD_CMSIS_DAP == 1 extern struct jtag_interface cmsis_dap_interface; #endif +#if BUILD_KITPROG == 1 +extern struct jtag_interface kitprog_interface; +#endif #endif /* standard drivers */ /** @@ -216,6 +219,9 @@ struct jtag_interface *jtag_interfaces[] = { #if BUILD_CMSIS_DAP == 1 &cmsis_dap_interface, #endif +#if BUILD_KITPROG == 1 + &kitprog_interface, +#endif #endif /* standard drivers */ NULL, }; diff --git a/tcl/interface/kitprog.cfg b/tcl/interface/kitprog.cfg new file mode 100644 index 0000000..9449714 --- /dev/null +++ b/tcl/interface/kitprog.cfg @@ -0,0 +1,12 @@ +# +# Cypress Semiconductor KitProg +# +# Note: This is the driver for the proprietary KitPtog protocol. If the +# KitProg is in CMSIS-DAP mode, you should either use the cmsis-dap +# interface driver or switch the KitProg to KitProg mode. +# + +interface kitprog + +# Optionally specify the serial number of the KitProg you want to use. +#kitprog_serial 1926402735485200 -- cgit v1.1 From 83c67b7ac7635260d09d9fe15a50a34440c0c4bb Mon Sep 17 00:00:00 2001 From: Grzegorz Kostka Date: Tue, 18 Apr 2017 16:12:58 +0200 Subject: imx_gpio: add mmap based jtag interface for IMX processors For some targets (like nrf51) sysfs driver is too slow. This patch implements memory maped driver for IMX processors. Mostly based on bcm2835gpio. Tested on imx6ul CPU. However, it should work on any NXP IMX CPU. Change-Id: Idace4c98181c6e9c64dd158bfa52631204b5c4a7 Signed-off-by: Grzegorz Kostka Reviewed-on: http://openocd.zylin.com/4106 Tested-by: jenkins Reviewed-by: Paul Fertser --- configure.ac | 12 + doc/openocd.texi | 15 ++ src/jtag/drivers/Makefile.am | 5 +- src/jtag/drivers/imx_gpio.c | 552 +++++++++++++++++++++++++++++++++++++++++++ src/jtag/interfaces.c | 6 + tcl/interface/imx-native.cfg | 35 +++ 6 files changed, 623 insertions(+), 2 deletions(-) create mode 100644 src/jtag/drivers/imx_gpio.c create mode 100644 tcl/interface/imx-native.cfg diff --git a/configure.ac b/configure.ac index f5d3b9e..c680bda 100644 --- a/configure.ac +++ b/configure.ac @@ -298,11 +298,15 @@ AS_CASE(["${host_cpu}"], AC_ARG_ENABLE([bcm2835gpio], AS_HELP_STRING([--enable-bcm2835gpio], [Enable building support for bitbanging on BCM2835 (as found in Raspberry Pi)]), [build_bcm2835gpio=$enableval], [build_bcm2835gpio=no]) + AC_ARG_ENABLE([imx_gpio], + AS_HELP_STRING([--enable-imx_gpio], [Enable building support for bitbanging on NXP IMX processors]), + [build_imx_gpio=$enableval], [build_imx_gpio=no]) ], [ build_ep93xx=no build_at91rm9200=no build_bcm2835gpio=no + build_imx_gpio=no ]) AC_ARG_ENABLE([gw16012], @@ -516,6 +520,13 @@ AS_IF([test "x$build_bcm2835gpio" = "xyes"], [ AC_DEFINE([BUILD_BCM2835GPIO], [0], [0 if you don't want bcm2835gpio.]) ]) +AS_IF([test "x$build_imx_gpio" = "xyes"], [ + build_bitbang=yes + AC_DEFINE([BUILD_IMX_GPIO], [1], [1 if you want imx_gpio.]) +], [ + AC_DEFINE([BUILD_IMX_GPIO], [0], [0 if you don't want imx_gpio.]) +]) + AS_IF([test "x$parport_use_ppdev" = "xyes"], [ AC_DEFINE([PARPORT_USE_PPDEV], [1], [1 if you want parport to use ppdev.]) ], [ @@ -686,6 +697,7 @@ AM_CONDITIONAL([ZY1000_MASTER], [test "x$build_zy1000_master" = "xyes"]) AM_CONDITIONAL([IOUTIL], [test "x$build_ioutil" = "xyes"]) AM_CONDITIONAL([AT91RM9200], [test "x$build_at91rm9200" = "xyes"]) AM_CONDITIONAL([BCM2835GPIO], [test "x$build_bcm2835gpio" = "xyes"]) +AM_CONDITIONAL([IMX_GPIO], [test "x$build_imx_gpio" = "xyes"]) AM_CONDITIONAL([BITBANG], [test "x$build_bitbang" = "xyes"]) AM_CONDITIONAL([JTAG_VPI], [test "x$build_jtag_vpi" = "xyes" -o "x$build_jtag_vpi" = "xyes"]) AM_CONDITIONAL([USB_BLASTER_DRIVER], [test "x$enable_usb_blaster" != "xno" -o "x$enable_usb_blaster_2" != "xno"]) diff --git a/doc/openocd.texi b/doc/openocd.texi index 845080e..373eacb 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -595,6 +595,9 @@ produced, PDF schematics are easily found and it is easy to make. @item @b{bcm2835gpio} @* A BCM2835-based board (e.g. Raspberry Pi) using the GPIO pins of the expansion header. +@item @b{imx_gpio} +@* A NXP i.MX-based board (e.g. Wandboard) using the GPIO pins (should work on any i.MX processor). + @item @b{jtag_vpi} @* A JTAG driver acting as a client for the JTAG VPI server interface. @* Link: @url{http://github.com/fjullien/jtag_vpi} @@ -2992,6 +2995,18 @@ pinout. @end deffn +@deffn {Interface Driver} {imx_gpio} +i.MX SoC is present in many community boards. Wandboard is an example +of the one which is most popular. + +This driver is mostly the same as bcm2835gpio. + +See @file{interface/imx-native.cfg} for a sample config and +pinout. + +@end deffn + + @deffn {Interface Driver} {openjtag} OpenJTAG compatible USB adapter. This defines some driver-specific commands: diff --git a/src/jtag/drivers/Makefile.am b/src/jtag/drivers/Makefile.am index e0c5421..3e5974d 100644 --- a/src/jtag/drivers/Makefile.am +++ b/src/jtag/drivers/Makefile.am @@ -144,14 +144,15 @@ endif if BCM2835GPIO DRIVERFILES += %D%/bcm2835gpio.c endif - if OPENJTAG DRIVERFILES += %D%/openjtag.c endif - if CMSIS_DAP DRIVERFILES += %D%/cmsis_dap_usb.c endif +if IMX_GPIO +DRIVERFILES += %D%/imx_gpio.c +endif if KITPROG DRIVERFILES += %D%/kitprog.c diff --git a/src/jtag/drivers/imx_gpio.c b/src/jtag/drivers/imx_gpio.c new file mode 100644 index 0000000..f33d109 --- /dev/null +++ b/src/jtag/drivers/imx_gpio.c @@ -0,0 +1,552 @@ +/*************************************************************************** + * Copyright (C) 2017 by Grzegorz Kostka, kostka.grzegorz@gmail.com * + * * + * Based on bcm2835gpio.c * + * * + * 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, see . * + ***************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include "bitbang.h" + +#include + +#define IMX_GPIO_BASE 0x0209c000 +#define IMX_GPIO_SIZE 0x00004000 +#define IMX_GPIO_REGS_COUNT 8 + +static uint32_t imx_gpio_peri_base = IMX_GPIO_BASE; + +struct imx_gpio_regs { + uint32_t dr; + uint32_t gdir; + uint32_t psr; + uint32_t icr1; + uint32_t icr2; + uint32_t imr; + uint32_t isr; + uint32_t edge_sel; +} __attribute__((aligned(IMX_GPIO_SIZE))); + +static int dev_mem_fd; +static volatile struct imx_gpio_regs *pio_base; + +/* GPIO setup functions */ +static inline bool gpio_mode_get(int g) +{ + return pio_base[g / 32].gdir >> (g & 0x1F) & 1; +} + +static inline void gpio_mode_input_set(int g) +{ + pio_base[g / 32].gdir &= ~(1u << (g & 0x1F)); +} + +static inline void gpio_mode_output_set(int g) +{ + pio_base[g / 32].gdir |= (1u << (g & 0x1F)); +} + +static inline void gpio_mode_set(int g, int m) +{ + (m) ? gpio_mode_output_set(g) : gpio_mode_input_set(g); +} + +static inline void gpio_set(int g) +{ + pio_base[g / 32].dr |= (1u << (g & 0x1F)); +} + +static inline void gpio_clear(int g) +{ + pio_base[g / 32].dr &= ~(1u << (g & 0x1F)); +} + +static inline bool gpio_level(int g) +{ + return pio_base[g / 32].dr >> (g & 0x1F) & 1; +} + +static int imx_gpio_read(void); +static void imx_gpio_write(int tck, int tms, int tdi); +static void imx_gpio_reset(int trst, int srst); + +static int imx_gpio_swdio_read(void); +static void imx_gpio_swdio_drive(bool is_output); + +static int imx_gpio_init(void); +static int imx_gpio_quit(void); + +static struct bitbang_interface imx_gpio_bitbang = { + .read = imx_gpio_read, + .write = imx_gpio_write, + .reset = imx_gpio_reset, + .swdio_read = imx_gpio_swdio_read, + .swdio_drive = imx_gpio_swdio_drive, + .blink = NULL +}; + +/* GPIO numbers for each signal. Negative values are invalid */ +static int tck_gpio = -1; +static int tck_gpio_mode; +static int tms_gpio = -1; +static int tms_gpio_mode; +static int tdi_gpio = -1; +static int tdi_gpio_mode; +static int tdo_gpio = -1; +static int tdo_gpio_mode; +static int trst_gpio = -1; +static int trst_gpio_mode; +static int srst_gpio = -1; +static int srst_gpio_mode; +static int swclk_gpio = -1; +static int swclk_gpio_mode; +static int swdio_gpio = -1; +static int swdio_gpio_mode; + +/* Transition delay coefficients. Tuned for IMX6UL 528MHz. Adjusted + * experimentally for:10kHz, 100Khz, 500KHz. Speeds above 800Khz are impossible + * to reach via memory mapped method (at least for IMX6UL@528MHz). + * Measured mmap raw GPIO toggling speed on IMX6UL@528MHz: 1.3MHz. + */ +static int speed_coeff = 50000; +static int speed_offset = 100; +static unsigned int jtag_delay; + +static int imx_gpio_read(void) +{ + return gpio_level(tdo_gpio); +} + +static void imx_gpio_write(int tck, int tms, int tdi) +{ + tms ? gpio_set(tms_gpio) : gpio_clear(tms_gpio); + tdi ? gpio_set(tdi_gpio) : gpio_clear(tdi_gpio); + tck ? gpio_set(tck_gpio) : gpio_clear(tck_gpio); + + for (unsigned int i = 0; i < jtag_delay; i++) + asm volatile (""); +} + +static void imx_gpio_swd_write(int tck, int tms, int tdi) +{ + tdi ? gpio_set(swdio_gpio) : gpio_clear(swdio_gpio); + tck ? gpio_set(swclk_gpio) : gpio_clear(swclk_gpio); + + for (unsigned int i = 0; i < jtag_delay; i++) + asm volatile (""); +} + +/* (1) assert or (0) deassert reset lines */ +static void imx_gpio_reset(int trst, int srst) +{ + if (trst_gpio != -1) + trst ? gpio_set(trst_gpio) : gpio_clear(trst_gpio); + + if (srst_gpio != -1) + srst ? gpio_set(srst_gpio) : gpio_clear(srst_gpio); +} + +static void imx_gpio_swdio_drive(bool is_output) +{ + if (is_output) + gpio_mode_output_set(swdio_gpio); + else + gpio_mode_input_set(swdio_gpio); +} + +static int imx_gpio_swdio_read(void) +{ + return gpio_level(swdio_gpio); +} + +static int imx_gpio_khz(int khz, int *jtag_speed) +{ + if (!khz) { + LOG_DEBUG("RCLK not supported"); + return ERROR_FAIL; + } + *jtag_speed = speed_coeff/khz - speed_offset; + if (*jtag_speed < 0) + *jtag_speed = 0; + return ERROR_OK; +} + +static int imx_gpio_speed_div(int speed, int *khz) +{ + *khz = speed_coeff/(speed + speed_offset); + return ERROR_OK; +} + +static int imx_gpio_speed(int speed) +{ + jtag_delay = speed; + return ERROR_OK; +} + +static int is_gpio_valid(int gpio) +{ + return gpio >= 0 && gpio < 32 * IMX_GPIO_REGS_COUNT; +} + +COMMAND_HANDLER(imx_gpio_handle_jtag_gpionums) +{ + if (CMD_ARGC == 4) { + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio); + COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio); + COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio); + COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio); + } else if (CMD_ARGC != 0) { + return ERROR_COMMAND_SYNTAX_ERROR; + } + + command_print(CMD_CTX, + "imx_gpio GPIO config: tck = %d, tms = %d, tdi = %d, tdo = %d", + tck_gpio, tms_gpio, tdi_gpio, tdo_gpio); + + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tck) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio); + + command_print(CMD_CTX, "imx_gpio GPIO config: tck = %d", tck_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tms) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio); + + command_print(CMD_CTX, "imx_gpio GPIO config: tms = %d", tms_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tdo) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio); + + command_print(CMD_CTX, "imx_gpio GPIO config: tdo = %d", tdo_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_tdi) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio); + + command_print(CMD_CTX, "imx_gpio GPIO config: tdi = %d", tdi_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_srst) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio); + + command_print(CMD_CTX, "imx_gpio GPIO config: srst = %d", srst_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_jtag_gpionum_trst) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio); + + command_print(CMD_CTX, "imx_gpio GPIO config: trst = %d", trst_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_swd_gpionums) +{ + if (CMD_ARGC == 2) { + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio); + COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio); + } else if (CMD_ARGC != 0) { + return ERROR_COMMAND_SYNTAX_ERROR; + } + + command_print(CMD_CTX, + "imx_gpio GPIO nums: swclk = %d, swdio = %d", + swclk_gpio, swdio_gpio); + + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_swd_gpionum_swclk) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio); + + command_print(CMD_CTX, "imx_gpio num: swclk = %d", swclk_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_swd_gpionum_swdio) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_gpio); + + command_print(CMD_CTX, "imx_gpio num: swdio = %d", swdio_gpio); + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_speed_coeffs) +{ + if (CMD_ARGC == 2) { + COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], speed_coeff); + COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], speed_offset); + } + return ERROR_OK; +} + +COMMAND_HANDLER(imx_gpio_handle_peripheral_base) +{ + if (CMD_ARGC == 1) + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], imx_gpio_peri_base); + return ERROR_OK; +} + +static const struct command_registration imx_gpio_command_handlers[] = { + { + .name = "imx_gpio_jtag_nums", + .handler = &imx_gpio_handle_jtag_gpionums, + .mode = COMMAND_CONFIG, + .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)", + .usage = "(tck tms tdi tdo)* ", + }, + { + .name = "imx_gpio_tck_num", + .handler = &imx_gpio_handle_jtag_gpionum_tck, + .mode = COMMAND_CONFIG, + .help = "gpio number for tck.", + }, + { + .name = "imx_gpio_tms_num", + .handler = &imx_gpio_handle_jtag_gpionum_tms, + .mode = COMMAND_CONFIG, + .help = "gpio number for tms.", + }, + { + .name = "imx_gpio_tdo_num", + .handler = &imx_gpio_handle_jtag_gpionum_tdo, + .mode = COMMAND_CONFIG, + .help = "gpio number for tdo.", + }, + { + .name = "imx_gpio_tdi_num", + .handler = &imx_gpio_handle_jtag_gpionum_tdi, + .mode = COMMAND_CONFIG, + .help = "gpio number for tdi.", + }, + { + .name = "imx_gpio_swd_nums", + .handler = &imx_gpio_handle_swd_gpionums, + .mode = COMMAND_CONFIG, + .help = "gpio numbers for swclk, swdio. (in that order)", + .usage = "(swclk swdio)* ", + }, + { + .name = "imx_gpio_swclk_num", + .handler = &imx_gpio_handle_swd_gpionum_swclk, + .mode = COMMAND_CONFIG, + .help = "gpio number for swclk.", + }, + { + .name = "imx_gpio_swdio_num", + .handler = &imx_gpio_handle_swd_gpionum_swdio, + .mode = COMMAND_CONFIG, + .help = "gpio number for swdio.", + }, + { + .name = "imx_gpio_srst_num", + .handler = &imx_gpio_handle_jtag_gpionum_srst, + .mode = COMMAND_CONFIG, + .help = "gpio number for srst.", + }, + { + .name = "imx_gpio_trst_num", + .handler = &imx_gpio_handle_jtag_gpionum_trst, + .mode = COMMAND_CONFIG, + .help = "gpio number for trst.", + }, + { + .name = "imx_gpio_speed_coeffs", + .handler = &imx_gpio_handle_speed_coeffs, + .mode = COMMAND_CONFIG, + .help = "SPEED_COEFF and SPEED_OFFSET for delay calculations.", + }, + { + .name = "imx_gpio_peripheral_base", + .handler = &imx_gpio_handle_peripheral_base, + .mode = COMMAND_CONFIG, + .help = "peripheral base to access GPIOs (0x0209c000 for most IMX).", + }, + + COMMAND_REGISTRATION_DONE +}; + +static const char * const imx_gpio_transports[] = { "jtag", "swd", NULL }; + +struct jtag_interface imx_gpio_interface = { + .name = "imx_gpio", + .supported = DEBUG_CAP_TMS_SEQ, + .execute_queue = bitbang_execute_queue, + .transports = imx_gpio_transports, + .swd = &bitbang_swd, + .speed = imx_gpio_speed, + .khz = imx_gpio_khz, + .speed_div = imx_gpio_speed_div, + .commands = imx_gpio_command_handlers, + .init = imx_gpio_init, + .quit = imx_gpio_quit, +}; + +static bool imx_gpio_jtag_mode_possible(void) +{ + if (!is_gpio_valid(tck_gpio)) + return 0; + if (!is_gpio_valid(tms_gpio)) + return 0; + if (!is_gpio_valid(tdi_gpio)) + return 0; + if (!is_gpio_valid(tdo_gpio)) + return 0; + return 1; +} + +static bool imx_gpio_swd_mode_possible(void) +{ + if (!is_gpio_valid(swclk_gpio)) + return 0; + if (!is_gpio_valid(swdio_gpio)) + return 0; + return 1; +} + +static int imx_gpio_init(void) +{ + bitbang_interface = &imx_gpio_bitbang; + + LOG_INFO("imx_gpio GPIO JTAG/SWD bitbang driver"); + + if (imx_gpio_jtag_mode_possible()) { + if (imx_gpio_swd_mode_possible()) + LOG_INFO("JTAG and SWD modes enabled"); + else + LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)"); + } else if (imx_gpio_swd_mode_possible()) { + LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode)"); + } else { + LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode and/or swclk and swdio gpio for SWD mode"); + return ERROR_JTAG_INIT_FAILED; + } + + dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC); + if (dev_mem_fd < 0) { + perror("open"); + return ERROR_JTAG_INIT_FAILED; + } + + + LOG_INFO("imx_gpio mmap: pagesize: %u, regionsize: %u", + sysconf(_SC_PAGE_SIZE), IMX_GPIO_REGS_COUNT * IMX_GPIO_SIZE); + pio_base = mmap(NULL, IMX_GPIO_REGS_COUNT * IMX_GPIO_SIZE, + PROT_READ | PROT_WRITE, + MAP_SHARED, dev_mem_fd, imx_gpio_peri_base); + + if (pio_base == MAP_FAILED) { + perror("mmap"); + close(dev_mem_fd); + return ERROR_JTAG_INIT_FAILED; + } + + /* + * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST + * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high. + */ + if (imx_gpio_jtag_mode_possible()) { + tdo_gpio_mode = gpio_mode_get(tdo_gpio); + tdi_gpio_mode = gpio_mode_get(tdi_gpio); + tck_gpio_mode = gpio_mode_get(tck_gpio); + tms_gpio_mode = gpio_mode_get(tms_gpio); + + gpio_clear(tdi_gpio); + gpio_clear(tck_gpio); + gpio_set(tms_gpio); + + gpio_mode_input_set(tdo_gpio); + gpio_mode_output_set(tdi_gpio); + gpio_mode_output_set(tck_gpio); + gpio_mode_output_set(tms_gpio); + } + if (imx_gpio_swd_mode_possible()) { + swclk_gpio_mode = gpio_mode_get(swclk_gpio); + swdio_gpio_mode = gpio_mode_get(swdio_gpio); + + gpio_clear(swdio_gpio); + gpio_clear(swclk_gpio); + gpio_mode_output_set(swclk_gpio); + gpio_mode_output_set(swdio_gpio); + } + if (trst_gpio != -1) { + trst_gpio_mode = gpio_mode_get(trst_gpio); + gpio_set(trst_gpio); + gpio_mode_output_set(trst_gpio); + } + if (srst_gpio != -1) { + srst_gpio_mode = gpio_mode_get(srst_gpio); + gpio_set(srst_gpio); + gpio_mode_output_set(srst_gpio); + } + + LOG_DEBUG("saved pinmux settings: tck %d tms %d tdi %d " + "tdo %d trst %d srst %d", tck_gpio_mode, tms_gpio_mode, + tdi_gpio_mode, tdo_gpio_mode, trst_gpio_mode, srst_gpio_mode); + + if (swd_mode) { + imx_gpio_bitbang.write = imx_gpio_swd_write; + bitbang_switch_to_swd(); + } + + return ERROR_OK; +} + +static int imx_gpio_quit(void) +{ + if (imx_gpio_jtag_mode_possible()) { + gpio_mode_set(tdo_gpio, tdo_gpio_mode); + gpio_mode_set(tdi_gpio, tdi_gpio_mode); + gpio_mode_set(tck_gpio, tck_gpio_mode); + gpio_mode_set(tms_gpio, tms_gpio_mode); + } + if (imx_gpio_swd_mode_possible()) { + gpio_mode_set(swclk_gpio, swclk_gpio_mode); + gpio_mode_set(swdio_gpio, swdio_gpio_mode); + } + if (trst_gpio != -1) + gpio_mode_set(trst_gpio, trst_gpio_mode); + if (srst_gpio != -1) + gpio_mode_set(srst_gpio, srst_gpio_mode); + + return ERROR_OK; +} diff --git a/src/jtag/interfaces.c b/src/jtag/interfaces.c index 396043d..174c63a 100644 --- a/src/jtag/interfaces.c +++ b/src/jtag/interfaces.c @@ -126,6 +126,9 @@ extern struct jtag_interface cmsis_dap_interface; #if BUILD_KITPROG == 1 extern struct jtag_interface kitprog_interface; #endif +#if BUILD_IMX_GPIO == 1 +extern struct jtag_interface imx_gpio_interface; +#endif #endif /* standard drivers */ /** @@ -222,6 +225,9 @@ struct jtag_interface *jtag_interfaces[] = { #if BUILD_KITPROG == 1 &kitprog_interface, #endif +#if BUILD_IMX_GPIO == 1 + &imx_gpio_interface, +#endif #endif /* standard drivers */ NULL, }; diff --git a/tcl/interface/imx-native.cfg b/tcl/interface/imx-native.cfg new file mode 100644 index 0000000..c2f80eb --- /dev/null +++ b/tcl/interface/imx-native.cfg @@ -0,0 +1,35 @@ +# +# Config for using NXP IMX CPU +# +# This is best used with a fast enough buffer but also +# is suitable for direct connection if the target voltage +# matches to host voltage and the cable is short enough. +# +# + +interface imx_gpio + +# For most IMX processors 0x0209c000 +imx_gpio_peripheral_base 0x0209c000 + +# Transition delay calculation: SPEED_COEFF/khz - SPEED_OFFSET +# These depend on system clock, calibrated for IMX6UL@528MHz +# imx_gpio_speed SPEED_COEFF SPEED_OFFSET +imx_gpio_speed_coeffs 50000 50 + +# Each of the JTAG lines need a gpio number set: tck tms tdi tdo. +# Example configuration: +# imx_gpio_jtag_nums 6 7 8 9 + +# SWD interface pins: swclk swdio +# Example configuration: +imx_gpio_swd_nums 1 6 + +# imx_gpio_trst_num 10 +# reset_config trst_only + +# imx_gpio_srst_num 11 +# reset_config srst_only srst_push_pull + +# or if you have both connected, +# reset_config trst_and_srst srst_push_pull \ No newline at end of file -- cgit v1.1 From 6b9d19d3675a82ccc501fd7cba036c5b04d04590 Mon Sep 17 00:00:00 2001 From: Tobias Diedrich Date: Mon, 1 Aug 2016 15:57:20 +0200 Subject: flash: Add support for Atheros (ath79) SPI interface Supported SoCs: AR71xx, AR724x, AR91xx, AR93xx, QCA9558 Extended and revised version of my original patch submitted by Dmytro here: http://openocd.zylin.com/#/c/3390 This driver is using pure SPI mode, so the flash base address is not used except some flash commands (e.g. "flash program") need it to distinguish the banks. Example config with all 3 chip selects: flash bank flash0 ath79 0 0 0 0 $_TARGETNAME cs0 flash bank flash1 ath79 0x10000000 0 0 0 $_TARGETNAME cs1 flash bank flash2 ath79 0x20000000 0 0 0 $_TARGETNAME cs2 Example usage: > flash probe flash0 Found flash device 'win w25q128fv' (ID 0x001840ef) flash 'ath79' found at 0x00000000 > flash probe flash1 No SPI flash found > flash probe flash2 No SPI flash found > flash banks > flash read_bank flash0 /tmp/test.bin 0x00000000 0x1000 reading 4096 bytes from flash @0x00000000 wrote 4096 bytes to file /tmp/test.bin from flash bank 0 at offset 0x00000000 in 28.688066s (0.139 KiB/s) Change-Id: I5feb697722c07e83a9c1b361a9db7b06bc699aa8 Signed-off-by: Tobias Diedrich Reviewed-on: http://openocd.zylin.com/3612 Tested-by: jenkins Reviewed-by: Dmytro Reviewed-by: Paul Fertser --- README | 2 +- doc/openocd.texi | 39 ++ src/flash/nor/Makefile.am | 1 + src/flash/nor/ath79.c | 903 ++++++++++++++++++++++++++++++++++++++++++++++ src/flash/nor/drivers.c | 2 + src/target/mips32_pracc.h | 2 + 6 files changed, 948 insertions(+), 1 deletion(-) create mode 100644 src/flash/nor/ath79.c diff --git a/README b/README index 581082e..f2d704b 100644 --- a/README +++ b/README @@ -123,7 +123,7 @@ XScale, Intel Quark. Flash drivers ------------- -ADUC702x, AT91SAM, AVR, CFI, DSP5680xx, EFM32, EM357, FM3, FM4, Kinetis, +ADUC702x, AT91SAM, ATH79, AVR, CFI, DSP5680xx, EFM32, EM357, FM3, FM4, Kinetis, LPC8xx/LPC1xxx/LPC2xxx/LPC541xx, LPC2900, LPCSPIFI, Marvell QSPI, Milandr, NIIET, NuMicro, PIC32mx, PSoC4, SiM3x, Stellaris, STM32, STMSMI, STR7x, STR9x, nRF51; NAND controllers of AT91SAM9, LPC3180, LPC32xx, diff --git a/doc/openocd.texi b/doc/openocd.texi index 373eacb..59d2d4f 100644 --- a/doc/openocd.texi +++ b/doc/openocd.texi @@ -4999,6 +4999,45 @@ flash bank $_FLASHNAME mrvlqspi 0x0 0 0 0 $_TARGETNAME 0x46010000 @end deffn +@deffn {Flash Driver} ath79 +@cindex Atheros ath79 SPI driver +@cindex ath79 +Members of ATH79 SoC family from Atheros include a SPI interface with 3 +chip selects. +On reset a SPI flash connected to the first chip select (CS0) is made +directly read-accessible in the CPU address space (up to 16MBytes) +and is usually used to store the bootloader and operating system. +Normal OpenOCD commands like @command{mdw} can be used to display +the flash content while it is in memory-mapped mode (only the first +4MBytes are accessible without additional configuration on reset). + +The setup command only requires the @var{base} parameter in order +to identify the memory bank. The actual value for the base address +is not otherwise used by the driver. However the mapping is passed +to gdb. Thus for the memory mapped flash (chipselect CS0) the base +address should be the actual memory mapped base address. For unmapped +chipselects (CS1 and CS2) care should be taken to use a base address +that does not overlap with real memory regions. +Additional information, like flash size, are detected automatically. +An optional additional parameter sets the chipselect for the bank, +with the default CS0. +CS1 and CS2 require additional GPIO setup before they can be used +since the alternate function must be enabled on the GPIO pin +CS1/CS2 is routed to on the given SoC. + +@example +flash bank $_FLASHNAME ath79 0 0 0 0 $_TARGETNAME + +# When using multiple chipselects the base should be different for each, +# otherwise the write_image command is not able to distinguish the +# banks. +flash bank flash0 ath79 0x00000000 0 0 0 $_TARGETNAME cs0 +flash bank flash1 ath79 0x10000000 0 0 0 $_TARGETNAME cs1 +flash bank flash2 ath79 0x20000000 0 0 0 $_TARGETNAME cs2 +@end example + +@end deffn + @subsection Internal Flash (Microcontrollers) @deffn {Flash Driver} aduc702x diff --git a/src/flash/nor/Makefile.am b/src/flash/nor/Makefile.am index 727e4f2..5a992fe 100644 --- a/src/flash/nor/Makefile.am +++ b/src/flash/nor/Makefile.am @@ -15,6 +15,7 @@ NOR_DRIVERS = \ %D%/at91samd.c \ %D%/at91sam3.c \ %D%/at91sam7.c \ + %D%/ath79.c \ %D%/atsamv.c \ %D%/avrf.c \ %D%/cfi.c \ diff --git a/src/flash/nor/ath79.c b/src/flash/nor/ath79.c new file mode 100644 index 0000000..0543085 --- /dev/null +++ b/src/flash/nor/ath79.c @@ -0,0 +1,903 @@ +/*************************************************************************** + * Copyright (C) 2015 by Tobias Diedrich * + * * + * * + * based on the stmsmi code written by Antonio Borneo * + * * + * * + * 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. * + * * + ***************************************************************************/ +/* + * Driver for the Atheros AR7xxx/AR9xxx SPI flash interface. + * + * Since no SPI mode register is present, presumably only + * SPI "mode 3" (CPOL=1 and CPHA=1) is supported. + * + * The SPI interface supports up to 3 chip selects, however the SPI flash + * used for booting the system must be connected to CS0. + * + * On boot, the first 4MiB of flash space are memory-mapped into the + * area bf000000 - bfffffff (4 copies), so the MIPS bootstrap + * vector bfc00000 is mapped to the beginning of the flash. + * + * By writing a 1 to the REMAP_DISABLE bit in the SPI_CONTROL register, + * the full area of 16MiB is mapped. + * + * By writing a 0 to the SPI_FUNCTION_SELECT register (write-only dword + * register @bf000000), memory mapping is disabled and the SPI registers + * are exposed to the CPU instead: + * bf000000 SPI_FUNCTION_SELECT + * bf000004 SPI_CONTROL + * bf000008 SPI_IO_CONTROL + * bf00000c SPI_READ_DATA + * + * When not memory-mapped, the SPI interface is essentially bitbanged + * using SPI_CONTROL and SPI_IO_CONTROL with the only hardware-assistance + * being the 32bit read-only shift-register SPI_READ_DATA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "imp.h" +#include "spi.h" +#include +#include +#include +#include +#include +#include + +#define BITS_PER_BYTE 8 + +#define ATH79_REG_FS 0 +#define ATH79_REG_CLOCK 4 +#define ATH79_REG_WRITE 8 +#define ATH79_REG_DATA 12 + +#define ATH79_SPI_CS_ALLHI 0x70000 +#define ATH79_SPI_CS0_HI 0x10000 +#define ATH79_SPI_CS1_HI 0x20000 +#define ATH79_SPI_CS2_HI 0x40000 +#define ATH79_SPI_CE_HI 0x00100 +#define ATH79_SPI_DO_HI 0x00001 + +#define ATH79_XFER_FINAL 0x00000001 +#define ATH79_XFER_PARTIAL 0x00000000 + +/* Timeout in ms */ +#define ATH79_MAX_TIMEOUT (3000) + +struct ath79_spi_ctx { + uint8_t *page_buf; + int pre_deselect; + int post_deselect; +}; + +struct ath79_flash_bank { + int probed; + int chipselect; + uint32_t io_base; + const struct flash_device *dev; + struct ath79_spi_ctx spi; +}; + +struct ath79_target { + char *name; + uint32_t tap_idcode; + uint32_t io_base; +}; + +static const struct ath79_target target_devices[] = { + /* name, tap_idcode, io_base */ + { "ATH79", 0x00000001, 0xbf000000 }, + { NULL, 0, 0 } +}; + +static const uint32_t ath79_chipselects[] = { + (~ATH79_SPI_CS0_HI & ATH79_SPI_CS_ALLHI), + (~ATH79_SPI_CS1_HI & ATH79_SPI_CS_ALLHI), + (~ATH79_SPI_CS2_HI & ATH79_SPI_CS_ALLHI), +}; + +static void ath79_pracc_addn(struct pracc_queue_info *ctx, + const uint32_t *instr, + int n) +{ + for (int i = 0; i < n; i++) + pracc_add(ctx, 0, instr[i]); +} + +static int ath79_spi_bitbang_codegen(struct ath79_flash_bank *ath79_info, + struct pracc_queue_info *ctx, + uint8_t *data, int len, + int partial_xfer) +{ + uint32_t cs_high = ATH79_SPI_CS_ALLHI; + uint32_t cs_low = ath79_chipselects[ath79_info->chipselect]; + uint32_t clock_high = cs_low | ATH79_SPI_CE_HI; + uint32_t clock_low = cs_low; + uint32_t pracc_out = 0; + uint32_t io_base = ath79_info->io_base; + + const uint32_t preamble1[] = { + /* $15 = MIPS32_PRACC_BASE_ADDR */ + MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR), + /* $1 = io_base */ + MIPS32_LUI(1, UPPER16(io_base)), + }; + ath79_pracc_addn(ctx, preamble1, ARRAY_SIZE(preamble1)); + if (ath79_info->spi.pre_deselect) { + /* Clear deselect flag so we don't deselect again if + * this is a partial xfer. + */ + ath79_info->spi.pre_deselect = 0; + const uint32_t pre_deselect[] = { + /* [$1 + FS] = 1 (enable flash io register access) */ + MIPS32_LUI(2, UPPER16(1)), + MIPS32_ORI(2, 2, LOWER16(1)), + MIPS32_SW(2, ATH79_REG_FS, 1), + /* deselect flash just in case */ + /* $2 = SPI_CS_DIS */ + MIPS32_LUI(2, UPPER16(cs_high)), + MIPS32_ORI(2, 2, LOWER16(cs_high)), + /* [$1 + WRITE] = $2 */ + MIPS32_SW(2, ATH79_REG_WRITE, 1), + }; + ath79_pracc_addn(ctx, pre_deselect, ARRAY_SIZE(pre_deselect)); + } + const uint32_t preamble2[] = { + /* t0 = CLOCK_LOW + 0-bit */ + MIPS32_LUI(8, UPPER16((clock_low + 0))), + MIPS32_ORI(8, 8, LOWER16((clock_low + 0))), + /* t1 = CLOCK_LOW + 1-bit */ + MIPS32_LUI(9, UPPER16((clock_low + 1))), + MIPS32_ORI(9, 9, LOWER16((clock_low + 1))), + /* t2 = CLOCK_HIGH + 0-bit */ + MIPS32_LUI(10, UPPER16((clock_high + 0))), + MIPS32_ORI(10, 10, LOWER16((clock_high + 0))), + /* t3 = CLOCK_HIGH + 1-bit */ + MIPS32_LUI(11, UPPER16((clock_high + 1))), + MIPS32_ORI(11, 11, LOWER16((clock_high + 1))), + }; + ath79_pracc_addn(ctx, preamble2, ARRAY_SIZE(preamble2)); + + for (int i = 0; i < len; i++) { + uint8_t x = data[i]; + + /* Generate bitbang code for one byte, highest bit first .*/ + for (int j = BITS_PER_BYTE - 1; j >= 0; j--) { + int bit = ((x >> j) & 1); + + if (bit) { + /* [$1 + WRITE] = t1 */ + pracc_add(ctx, 0, + MIPS32_SW(9, ATH79_REG_WRITE, 1)); + /* [$1 + WRITE] = t3 */ + pracc_add(ctx, 0, + MIPS32_SW(11, ATH79_REG_WRITE, 1)); + } else { + /* [$1 + WRITE] = t0 */ + pracc_add(ctx, 0, + MIPS32_SW(8, ATH79_REG_WRITE, 1)); + /* [$1 + WRITE] = t2 */ + pracc_add(ctx, 0, + MIPS32_SW(10, ATH79_REG_WRITE, 1)); + } + } + if (i % 4 == 3) { + /* $3 = [$1 + DATA] */ + pracc_add(ctx, 0, MIPS32_LW(3, ATH79_REG_DATA, 1)); + /* [OUTi] = $3 */ + pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + pracc_out, + MIPS32_SW(3, PRACC_OUT_OFFSET + + pracc_out, 15)); + pracc_out += 4; + } + } + if (len & 3) { /* not a multiple of 4 bytes */ + /* $3 = [$1 + DATA] */ + pracc_add(ctx, 0, MIPS32_LW(3, ATH79_REG_DATA, 1)); + /* [OUTi] = $3 */ + pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + pracc_out, + MIPS32_SW(3, PRACC_OUT_OFFSET + pracc_out, 15)); + pracc_out += 4; + } + + if (ath79_info->spi.post_deselect && !partial_xfer) { + const uint32_t post_deselect[] = { + /* $2 = SPI_CS_DIS */ + MIPS32_LUI(2, UPPER16(cs_high)), + MIPS32_ORI(2, 2, LOWER16(cs_high)), + /* [$1 + WRITE] = $2 */ + MIPS32_SW(2, ATH79_REG_WRITE, 1), + + /* [$1 + FS] = 0 (disable flash io register access) */ + MIPS32_XORI(2, 2, 0), + MIPS32_SW(2, ATH79_REG_FS, 1), + }; + ath79_pracc_addn(ctx, post_deselect, ARRAY_SIZE(post_deselect)); + } + + /* common pracc epilogue */ + /* jump to start */ + pracc_add(ctx, 0, MIPS32_B(NEG16(ctx->code_count + 1))); + /* restore $15 from DeSave */ + pracc_add(ctx, 0, MIPS32_MFC0(15, 31, 0)); + + return pracc_out / 4; +} + +static int ath79_spi_bitbang_chunk(struct flash_bank *bank, + uint8_t *data, int len, int *transferred) +{ + struct target *target = bank->target; + struct ath79_flash_bank *ath79_info = bank->driver_priv; + struct mips32_common *mips32 = target_to_mips32(target); + struct mips_ejtag *ejtag_info = &mips32->ejtag_info; + int pracc_words; + + /* + * These constants must match the worst case in the above code + * generator function ath79_spi_bitbang_codegen. + */ + const int pracc_pre_post = 26; + const int pracc_loop_byte = 8 * 2 + 2; + + struct pracc_queue_info ctx = { + .max_code = PRACC_MAX_INSTRUCTIONS + }; + int max_len = (ctx.max_code - pracc_pre_post) / pracc_loop_byte; + int to_xfer = len > max_len ? max_len : len; + int partial_xfer = len != to_xfer; + int padded_len = (to_xfer + 3) & ~3; + uint32_t *out = malloc(padded_len); + + if (!out) { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + + *transferred = 0; + pracc_queue_init(&ctx); + if (ctx.retval != ERROR_OK) + goto exit; + + LOG_DEBUG("ath79_spi_bitbang_bytes(%p, %08x, %p, %d)", + target, ath79_info->io_base, data, len); + + LOG_DEBUG("max code %d => max len %d. to_xfer %d", + ctx.max_code, max_len, to_xfer); + + pracc_words = ath79_spi_bitbang_codegen( + ath79_info, &ctx, data, to_xfer, partial_xfer); + + LOG_DEBUG("Assembled %d instructions, %d stores", + ctx.code_count, ctx.store_count); + + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, out); + if (ctx.retval != ERROR_OK) + goto exit; + + if (to_xfer & 3) { /* Not a multiple of 4 bytes. */ + /* + * Need to realign last word since we didn't shift the + * full 32 bits. + */ + int missed_bytes = 4 - (to_xfer & 3); + + out[pracc_words - 1] <<= BITS_PER_BYTE * missed_bytes; + } + + /* + * pracc reads return uint32_t in host endianness, convert to + * target endianness. + * Since we know the ATH79 target is big endian and the SPI + * shift register has the bytes in highest to lowest bit order, + * this will ensure correct memory byte order regardless of host + * endianness. + */ + target_buffer_set_u32_array(target, (uint8_t *)out, pracc_words, out); + + if (LOG_LEVEL_IS(LOG_LVL_DEBUG)) { + for (int i = 0; i < to_xfer; i++) { + LOG_DEBUG("bitbang %02x => %02x", + data[i], ((uint8_t *)out)[i]); + } + } + memcpy(data, out, to_xfer); + *transferred = to_xfer; + +exit: + pracc_queue_free(&ctx); + free(out); + return ctx.retval; +} + +static void ath79_spi_bitbang_prepare(struct flash_bank *bank) +{ + struct ath79_flash_bank *ath79_info = bank->driver_priv; + + ath79_info->spi.pre_deselect = 1; +} + +static int ath79_spi_bitbang_bytes(struct flash_bank *bank, + uint8_t *data, int len, uint32_t flags) +{ + struct ath79_flash_bank *ath79_info = bank->driver_priv; + int retval; + int transferred; + + ath79_info->spi.post_deselect = !!(flags & ATH79_XFER_FINAL); + + do { + transferred = 0; + retval = ath79_spi_bitbang_chunk( + bank, data, len, &transferred); + if (retval != ERROR_OK) + return retval; + + data += transferred; + len -= transferred; + } while (len > 0); + + return ERROR_OK; +} + +FLASH_BANK_COMMAND_HANDLER(ath79_flash_bank_command) +{ + struct ath79_flash_bank *ath79_info; + int chipselect = 0; + + LOG_DEBUG("%s", __func__); + + if (CMD_ARGC < 6 || CMD_ARGC > 7) + return ERROR_COMMAND_SYNTAX_ERROR; + + if (CMD_ARGC == 7) { + if (strcmp(CMD_ARGV[6], "cs0") == 0) + chipselect = 0; /* default */ + else if (strcmp(CMD_ARGV[6], "cs1") == 0) + chipselect = 1; + else if (strcmp(CMD_ARGV[6], "cs2") == 0) + chipselect = 2; + else { + LOG_ERROR("Unknown arg: %s", CMD_ARGV[6]); + return ERROR_COMMAND_SYNTAX_ERROR; + } + } + + ath79_info = calloc(1, sizeof(struct ath79_flash_bank)); + if (!ath79_info) { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + + ath79_info->chipselect = chipselect; + bank->driver_priv = ath79_info; + + return ERROR_OK; +} + +/* Read the status register of the external SPI flash chip. */ +static int read_status_reg(struct flash_bank *bank, uint32_t *status) +{ + uint8_t spi_bytes[] = {SPIFLASH_READ_STATUS, 0}; + int retval; + + /* Send SPI command "read STATUS" */ + ath79_spi_bitbang_prepare(bank); + retval = ath79_spi_bitbang_bytes( + bank, spi_bytes, sizeof(spi_bytes), + ATH79_XFER_FINAL); + + *status = spi_bytes[1]; + + return retval; +} + +/* check for WIP (write in progress) bit in status register */ +/* timeout in ms */ +static int wait_till_ready(struct flash_bank *bank, int timeout) +{ + uint32_t status; + int retval; + long long endtime; + + endtime = timeval_ms() + timeout; + do { + /* read flash status register */ + retval = read_status_reg(bank, &status); + if (retval != ERROR_OK) + return retval; + + if ((status & SPIFLASH_BSY_BIT) == 0) + return ERROR_OK; + alive_sleep(1); + } while (timeval_ms() < endtime); + + LOG_ERROR("timeout"); + return ERROR_FAIL; +} + +/* Send "write enable" command to SPI flash chip. */ +static int ath79_write_enable(struct flash_bank *bank) +{ + uint32_t status; + int retval; + + uint8_t spi_bytes[] = {SPIFLASH_WRITE_ENABLE}; + + /* Send SPI command "write enable" */ + ath79_spi_bitbang_prepare(bank); + retval = ath79_spi_bitbang_bytes( + bank, spi_bytes, sizeof(spi_bytes), + ATH79_XFER_FINAL); + if (retval != ERROR_OK) + return retval; + + /* read flash status register */ + retval = read_status_reg(bank, &status); + if (retval != ERROR_OK) + return retval; + + /* Check write enabled */ + if ((status & SPIFLASH_WE_BIT) == 0) { + LOG_ERROR("Cannot enable write to flash. Status=0x%08" PRIx32, + status); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int erase_command(struct flash_bank *bank, int sector) +{ + struct ath79_flash_bank *ath79_info = bank->driver_priv; + uint32_t offset = bank->sectors[sector].offset; + + uint8_t spi_bytes[] = { + ath79_info->dev->erase_cmd, + offset >> 16, + offset >> 8, + offset + }; + + /* bitbang command */ + ath79_spi_bitbang_prepare(bank); + return ath79_spi_bitbang_bytes( + bank, spi_bytes, sizeof(spi_bytes), + ATH79_XFER_FINAL); +} + +static int ath79_erase_sector(struct flash_bank *bank, int sector) +{ + int retval = ath79_write_enable(bank); + + if (retval != ERROR_OK) + return retval; + + /* send SPI command "block erase" */ + retval = erase_command(bank, sector); + if (retval != ERROR_OK) + return retval; + + /* poll WIP for end of self timed Sector Erase cycle */ + return wait_till_ready(bank, ATH79_MAX_TIMEOUT); +} + +static int ath79_erase(struct flash_bank *bank, int first, int last) +{ + struct target *target = bank->target; + struct ath79_flash_bank *ath79_info = bank->driver_priv; + int retval = ERROR_OK; + int sector; + + LOG_DEBUG("%s: from sector %d to sector %d", __func__, first, last); + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if ((first < 0) || (last < first) || (last >= bank->num_sectors)) { + LOG_ERROR("Flash sector invalid"); + return ERROR_FLASH_SECTOR_INVALID; + } + + if (!ath79_info->probed) { + LOG_ERROR("Flash bank not probed"); + return ERROR_FLASH_BANK_NOT_PROBED; + } + + for (sector = first; sector <= last; sector++) { + if (bank->sectors[sector].is_protected) { + LOG_ERROR("Flash sector %d protected", sector); + return ERROR_FAIL; + } + } + + for (sector = first; sector <= last; sector++) { + retval = ath79_erase_sector(bank, sector); + if (retval != ERROR_OK) + break; + keep_alive(); + } + + return retval; +} + +static int ath79_protect(struct flash_bank *bank, int set, + int first, int last) +{ + int sector; + + for (sector = first; sector <= last; sector++) + bank->sectors[sector].is_protected = set; + return ERROR_OK; +} + +static int ath79_write_page(struct flash_bank *bank, const uint8_t *buffer, + uint32_t address, uint32_t len) +{ + struct ath79_flash_bank *ath79_info = bank->driver_priv; + uint8_t spi_bytes[] = { + SPIFLASH_PAGE_PROGRAM, + address >> 16, + address >> 8, + address, + }; + int retval; + uint32_t i; + + if (address & 0xff) { + LOG_ERROR("ath79_write_page: unaligned write address: %08x", + address); + return ERROR_FAIL; + } + if (!ath79_info->spi.page_buf) { + LOG_ERROR("ath79_write_page: page buffer not initialized"); + return ERROR_FAIL; + } + if (len > ath79_info->dev->pagesize) { + LOG_ERROR("ath79_write_page: len bigger than page size %d: %d", + ath79_info->dev->pagesize, len); + return ERROR_FAIL; + } + + for (i = 0; i < len; i++) { + if (buffer[i] != 0xff) + break; + } + if (i == len) /* all 0xff, no need to program. */ + return ERROR_OK; + + LOG_INFO("writing %d bytes to flash page @0x%08x", len, address); + + memcpy(ath79_info->spi.page_buf, buffer, len); + + /* unlock writes */ + retval = ath79_write_enable(bank); + if (retval != ERROR_OK) + return retval; + + /* bitbang command */ + ath79_spi_bitbang_prepare(bank); + retval = ath79_spi_bitbang_bytes( + bank, spi_bytes, sizeof(spi_bytes), + ATH79_XFER_PARTIAL); + if (retval != ERROR_OK) + return retval; + + /* write data */ + return ath79_spi_bitbang_bytes( + bank, ath79_info->spi.page_buf, len, + ATH79_XFER_FINAL); +} + +static int ath79_write_buffer(struct flash_bank *bank, const uint8_t *buffer, + uint32_t address, uint32_t len) +{ + struct ath79_flash_bank *ath79_info = bank->driver_priv; + const uint32_t page_size = ath79_info->dev->pagesize; + int retval; + + LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32, + __func__, address, len); + + while (len > 0) { + int page_len = len > page_size ? page_size : len; + + retval = ath79_write_page( + bank, buffer, address, page_len); + if (retval != ERROR_OK) + return retval; + + buffer += page_size; + address += page_size; + len -= page_len; + } + + return ERROR_OK; +} + +static int ath79_write(struct flash_bank *bank, const uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + struct target *target = bank->target; + int sector; + + LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32, + __func__, offset, count); + + if (offset < bank->base || offset >= bank->base + bank->size) { + LOG_ERROR("Start address out of range"); + return ERROR_FAIL; + } + + offset -= bank->base; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (offset + count > bank->size) { + LOG_WARNING("Write pasts end of flash. Extra data discarded."); + count = bank->size - offset; + } + + /* Check sector protection */ + for (sector = 0; sector < bank->num_sectors; sector++) { + /* Start offset in or before this sector? */ + /* End offset in or behind this sector? */ + struct flash_sector *bs = &bank->sectors[sector]; + + if ((offset < (bs->offset + bs->size)) && + ((offset + count - 1) >= bs->offset) && + bs->is_protected) { + LOG_ERROR("Flash sector %d protected", sector); + return ERROR_FAIL; + } + } + + return ath79_write_buffer(bank, buffer, offset, count); +} + +static int ath79_read_buffer(struct flash_bank *bank, uint8_t *buffer, + uint32_t address, uint32_t len) +{ + uint8_t spi_bytes[] = { + SPIFLASH_READ, + address >> 16, + address >> 8, + address, + }; + int retval; + + LOG_DEBUG("%s: address=0x%08" PRIx32 " len=0x%08" PRIx32, + __func__, address, len); + + if (address & 0xff) { + LOG_ERROR("ath79_read_buffer: unaligned read address: %08x", + address); + return ERROR_FAIL; + } + + LOG_INFO("reading %d bytes from flash @0x%08x", len, address); + + /* bitbang command */ + ath79_spi_bitbang_prepare(bank); + retval = ath79_spi_bitbang_bytes( + bank, spi_bytes, sizeof(spi_bytes), ATH79_XFER_PARTIAL); + if (retval != ERROR_OK) + return retval; + + /* read data */ + return ath79_spi_bitbang_bytes( + bank, buffer, len, ATH79_XFER_FINAL); +} + +static int ath79_read(struct flash_bank *bank, uint8_t *buffer, + uint32_t offset, uint32_t count) +{ + struct target *target = bank->target; + + LOG_DEBUG("%s: offset=0x%08" PRIx32 " count=0x%08" PRIx32, + __func__, offset, count); + + if (offset < bank->base || offset >= bank->base + bank->size) { + LOG_ERROR("Start address out of range"); + return ERROR_FAIL; + } + + offset -= bank->base; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + if (offset + count > bank->size) { + LOG_WARNING("Reads past end of flash. Extra data discarded."); + count = bank->size - offset; + } + + return ath79_read_buffer(bank, buffer, offset, count); +} + +/* Return ID of flash device */ +static int read_flash_id(struct flash_bank *bank, uint32_t *id) +{ + struct target *target = bank->target; + int retval; + uint8_t spi_bytes[] = {SPIFLASH_READ_ID, 0, 0, 0}; + + if (target->state != TARGET_HALTED) { + LOG_ERROR("Target not halted"); + return ERROR_TARGET_NOT_HALTED; + } + + /* Send SPI command "read ID" */ + ath79_spi_bitbang_prepare(bank); + retval = ath79_spi_bitbang_bytes( + bank, spi_bytes, sizeof(spi_bytes), ATH79_XFER_FINAL); + if (retval != ERROR_OK) + return retval; + + *id = (spi_bytes[1] << 0) + | (spi_bytes[2] << 8) + | (spi_bytes[3] << 16); + + if (*id == 0xffffff) { + LOG_ERROR("No SPI flash found"); + return ERROR_FAIL; + } + + return ERROR_OK; +} + +static int ath79_probe(struct flash_bank *bank) +{ + struct target *target = bank->target; + struct ath79_flash_bank *ath79_info = bank->driver_priv; + struct flash_sector *sectors; + uint32_t id = 0; /* silence uninitialized warning */ + const struct ath79_target *target_device; + int retval; + + if (ath79_info->probed) { + free(bank->sectors); + free(ath79_info->spi.page_buf); + } + ath79_info->probed = 0; + + for (target_device = target_devices; target_device->name; + ++target_device) + if (target_device->tap_idcode == target->tap->idcode) + break; + if (!target_device->name) { + LOG_ERROR("Device ID 0x%" PRIx32 " is not known", + target->tap->idcode); + return ERROR_FAIL; + } + + ath79_info->io_base = target_device->io_base; + + LOG_DEBUG("Found device %s at address 0x%" PRIx32, + target_device->name, bank->base); + + retval = read_flash_id(bank, &id); + if (retval != ERROR_OK) + return retval; + + ath79_info->dev = NULL; + for (const struct flash_device *p = flash_devices; p->name; p++) + if (p->device_id == id) { + ath79_info->dev = p; + break; + } + + if (!ath79_info->dev) { + LOG_ERROR("Unknown flash device (ID 0x%08" PRIx32 ")", id); + return ERROR_FAIL; + } + + LOG_INFO("Found flash device \'%s\' (ID 0x%08" PRIx32 ")", + ath79_info->dev->name, ath79_info->dev->device_id); + + /* Set correct size value */ + bank->size = ath79_info->dev->size_in_bytes; + + /* create and fill sectors array */ + bank->num_sectors = + ath79_info->dev->size_in_bytes / ath79_info->dev->sectorsize; + sectors = calloc(1, sizeof(struct flash_sector) * bank->num_sectors); + if (!sectors) { + LOG_ERROR("not enough memory"); + return ERROR_FAIL; + } + ath79_info->spi.page_buf = malloc(ath79_info->dev->pagesize); + if (!ath79_info->spi.page_buf) { + LOG_ERROR("not enough memory"); + free(sectors); + return ERROR_FAIL; + } + + for (int sector = 0; sector < bank->num_sectors; sector++) { + sectors[sector].offset = sector * ath79_info->dev->sectorsize; + sectors[sector].size = ath79_info->dev->sectorsize; + sectors[sector].is_erased = 0; + sectors[sector].is_protected = 1; + } + + bank->sectors = sectors; + ath79_info->probed = 1; + return ERROR_OK; +} + +static int ath79_auto_probe(struct flash_bank *bank) +{ + struct ath79_flash_bank *ath79_info = bank->driver_priv; + + if (ath79_info->probed) + return ERROR_OK; + return ath79_probe(bank); +} + +static int ath79_flash_blank_check(struct flash_bank *bank) +{ + /* Not implemented */ + return ERROR_OK; +} + +static int ath79_protect_check(struct flash_bank *bank) +{ + /* Not implemented */ + return ERROR_OK; +} + +static int get_ath79_info(struct flash_bank *bank, char *buf, int buf_size) +{ + struct ath79_flash_bank *ath79_info = bank->driver_priv; + + if (!ath79_info->probed) { + snprintf(buf, buf_size, + "\nATH79 flash bank not probed yet\n"); + return ERROR_OK; + } + + snprintf(buf, buf_size, "\nATH79 flash information:\n" + " Device \'%s\' (ID 0x%08" PRIx32 ")\n", + ath79_info->dev->name, ath79_info->dev->device_id); + + return ERROR_OK; +} + +struct flash_driver ath79_flash = { + .name = "ath79", + .flash_bank_command = ath79_flash_bank_command, + .erase = ath79_erase, + .protect = ath79_protect, + .write = ath79_write, + .read = ath79_read, + .probe = ath79_probe, + .auto_probe = ath79_auto_probe, + .erase_check = ath79_flash_blank_check, + .protect_check = ath79_protect_check, + .info = get_ath79_info, +}; diff --git a/src/flash/nor/drivers.c b/src/flash/nor/drivers.c index 56a5cb2..4ad1d92 100644 --- a/src/flash/nor/drivers.c +++ b/src/flash/nor/drivers.c @@ -28,6 +28,7 @@ extern struct flash_driver at91sam4_flash; extern struct flash_driver at91sam4l_flash; extern struct flash_driver at91sam7_flash; extern struct flash_driver at91samd_flash; +extern struct flash_driver ath79_flash; extern struct flash_driver atsamv_flash; extern struct flash_driver avr_flash; extern struct flash_driver cfi_flash; @@ -80,6 +81,7 @@ static struct flash_driver *flash_drivers[] = { &at91sam4l_flash, &at91sam7_flash, &at91samd_flash, + &ath79_flash, &atsamv_flash, &avr_flash, &cfi_flash, diff --git a/src/target/mips32_pracc.h b/src/target/mips32_pracc.h index fe9f814..b8b93c6 100644 --- a/src/target/mips32_pracc.h +++ b/src/target/mips32_pracc.h @@ -34,6 +34,8 @@ #define MIPS32_PRACC_PARAM_OUT 0xFF202000 #define PRACC_UPPER_BASE_ADDR (MIPS32_PRACC_BASE_ADDR >> 16) +#define PRACC_MAX_CODE (MIPS32_PRACC_PARAM_OUT - MIPS32_PRACC_TEXT) +#define PRACC_MAX_INSTRUCTIONS (PRACC_MAX_CODE / 4) #define PRACC_OUT_OFFSET (MIPS32_PRACC_PARAM_OUT - MIPS32_PRACC_BASE_ADDR) #define MIPS32_FASTDATA_HANDLER_SIZE 0x80 -- cgit v1.1 From 1025be363e2bf42f1613083223a2322cc3a9bd4c Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Wed, 31 May 2017 16:57:34 +0300 Subject: flash: nor: ath79: fix build failure due to recent MIPS changes Change-Id: I7139b0658f048afea2d16216c93e8946356a630d Signed-off-by: Paul Fertser Reviewed-on: http://openocd.zylin.com/4151 Tested-by: jenkins Reviewed-by: Salvador Arroyo --- src/flash/nor/ath79.c | 72 +++++++++++++++++++++++++-------------------------- 1 file changed, 35 insertions(+), 37 deletions(-) diff --git a/src/flash/nor/ath79.c b/src/flash/nor/ath79.c index 0543085..451e843 100644 --- a/src/flash/nor/ath79.c +++ b/src/flash/nor/ath79.c @@ -136,9 +136,9 @@ static int ath79_spi_bitbang_codegen(struct ath79_flash_bank *ath79_info, const uint32_t preamble1[] = { /* $15 = MIPS32_PRACC_BASE_ADDR */ - MIPS32_LUI(15, PRACC_UPPER_BASE_ADDR), + MIPS32_LUI(0, 15, PRACC_UPPER_BASE_ADDR), /* $1 = io_base */ - MIPS32_LUI(1, UPPER16(io_base)), + MIPS32_LUI(0, 1, UPPER16(io_base)), }; ath79_pracc_addn(ctx, preamble1, ARRAY_SIZE(preamble1)); if (ath79_info->spi.pre_deselect) { @@ -148,31 +148,31 @@ static int ath79_spi_bitbang_codegen(struct ath79_flash_bank *ath79_info, ath79_info->spi.pre_deselect = 0; const uint32_t pre_deselect[] = { /* [$1 + FS] = 1 (enable flash io register access) */ - MIPS32_LUI(2, UPPER16(1)), - MIPS32_ORI(2, 2, LOWER16(1)), - MIPS32_SW(2, ATH79_REG_FS, 1), + MIPS32_LUI(0, 2, UPPER16(1)), + MIPS32_ORI(0, 2, 2, LOWER16(1)), + MIPS32_SW(0, 2, ATH79_REG_FS, 1), /* deselect flash just in case */ /* $2 = SPI_CS_DIS */ - MIPS32_LUI(2, UPPER16(cs_high)), - MIPS32_ORI(2, 2, LOWER16(cs_high)), + MIPS32_LUI(0, 2, UPPER16(cs_high)), + MIPS32_ORI(0, 2, 2, LOWER16(cs_high)), /* [$1 + WRITE] = $2 */ - MIPS32_SW(2, ATH79_REG_WRITE, 1), + MIPS32_SW(0, 2, ATH79_REG_WRITE, 1), }; ath79_pracc_addn(ctx, pre_deselect, ARRAY_SIZE(pre_deselect)); } const uint32_t preamble2[] = { /* t0 = CLOCK_LOW + 0-bit */ - MIPS32_LUI(8, UPPER16((clock_low + 0))), - MIPS32_ORI(8, 8, LOWER16((clock_low + 0))), + MIPS32_LUI(0, 8, UPPER16((clock_low + 0))), + MIPS32_ORI(0, 8, 8, LOWER16((clock_low + 0))), /* t1 = CLOCK_LOW + 1-bit */ - MIPS32_LUI(9, UPPER16((clock_low + 1))), - MIPS32_ORI(9, 9, LOWER16((clock_low + 1))), + MIPS32_LUI(0, 9, UPPER16((clock_low + 1))), + MIPS32_ORI(0, 9, 9, LOWER16((clock_low + 1))), /* t2 = CLOCK_HIGH + 0-bit */ - MIPS32_LUI(10, UPPER16((clock_high + 0))), - MIPS32_ORI(10, 10, LOWER16((clock_high + 0))), + MIPS32_LUI(0, 10, UPPER16((clock_high + 0))), + MIPS32_ORI(0, 10, 10, LOWER16((clock_high + 0))), /* t3 = CLOCK_HIGH + 1-bit */ - MIPS32_LUI(11, UPPER16((clock_high + 1))), - MIPS32_ORI(11, 11, LOWER16((clock_high + 1))), + MIPS32_LUI(0, 11, UPPER16((clock_high + 1))), + MIPS32_ORI(0, 11, 11, LOWER16((clock_high + 1))), }; ath79_pracc_addn(ctx, preamble2, ARRAY_SIZE(preamble2)); @@ -186,58 +186,58 @@ static int ath79_spi_bitbang_codegen(struct ath79_flash_bank *ath79_info, if (bit) { /* [$1 + WRITE] = t1 */ pracc_add(ctx, 0, - MIPS32_SW(9, ATH79_REG_WRITE, 1)); + MIPS32_SW(0, 9, ATH79_REG_WRITE, 1)); /* [$1 + WRITE] = t3 */ pracc_add(ctx, 0, - MIPS32_SW(11, ATH79_REG_WRITE, 1)); + MIPS32_SW(0, 11, ATH79_REG_WRITE, 1)); } else { /* [$1 + WRITE] = t0 */ pracc_add(ctx, 0, - MIPS32_SW(8, ATH79_REG_WRITE, 1)); + MIPS32_SW(0, 8, ATH79_REG_WRITE, 1)); /* [$1 + WRITE] = t2 */ pracc_add(ctx, 0, - MIPS32_SW(10, ATH79_REG_WRITE, 1)); + MIPS32_SW(0, 10, ATH79_REG_WRITE, 1)); } } if (i % 4 == 3) { /* $3 = [$1 + DATA] */ - pracc_add(ctx, 0, MIPS32_LW(3, ATH79_REG_DATA, 1)); + pracc_add(ctx, 0, MIPS32_LW(0, 3, ATH79_REG_DATA, 1)); /* [OUTi] = $3 */ pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + pracc_out, - MIPS32_SW(3, PRACC_OUT_OFFSET + + MIPS32_SW(0, 3, PRACC_OUT_OFFSET + pracc_out, 15)); pracc_out += 4; } } if (len & 3) { /* not a multiple of 4 bytes */ /* $3 = [$1 + DATA] */ - pracc_add(ctx, 0, MIPS32_LW(3, ATH79_REG_DATA, 1)); + pracc_add(ctx, 0, MIPS32_LW(0, 3, ATH79_REG_DATA, 1)); /* [OUTi] = $3 */ pracc_add(ctx, MIPS32_PRACC_PARAM_OUT + pracc_out, - MIPS32_SW(3, PRACC_OUT_OFFSET + pracc_out, 15)); + MIPS32_SW(0, 3, PRACC_OUT_OFFSET + pracc_out, 15)); pracc_out += 4; } if (ath79_info->spi.post_deselect && !partial_xfer) { const uint32_t post_deselect[] = { /* $2 = SPI_CS_DIS */ - MIPS32_LUI(2, UPPER16(cs_high)), - MIPS32_ORI(2, 2, LOWER16(cs_high)), + MIPS32_LUI(0, 2, UPPER16(cs_high)), + MIPS32_ORI(0, 2, 2, LOWER16(cs_high)), /* [$1 + WRITE] = $2 */ - MIPS32_SW(2, ATH79_REG_WRITE, 1), + MIPS32_SW(0, 2, ATH79_REG_WRITE, 1), /* [$1 + FS] = 0 (disable flash io register access) */ - MIPS32_XORI(2, 2, 0), - MIPS32_SW(2, ATH79_REG_FS, 1), + MIPS32_XORI(0, 2, 2, 0), + MIPS32_SW(0, 2, ATH79_REG_FS, 1), }; ath79_pracc_addn(ctx, post_deselect, ARRAY_SIZE(post_deselect)); } /* common pracc epilogue */ /* jump to start */ - pracc_add(ctx, 0, MIPS32_B(NEG16(ctx->code_count + 1))); + pracc_add(ctx, 0, MIPS32_B(0, NEG16(ctx->code_count + 1))); /* restore $15 from DeSave */ - pracc_add(ctx, 0, MIPS32_MFC0(15, 31, 0)); + pracc_add(ctx, 0, MIPS32_MFC0(0, 15, 31, 0)); return pracc_out / 4; } @@ -259,9 +259,9 @@ static int ath79_spi_bitbang_chunk(struct flash_bank *bank, const int pracc_loop_byte = 8 * 2 + 2; struct pracc_queue_info ctx = { - .max_code = PRACC_MAX_INSTRUCTIONS + .ejtag_info = ejtag_info }; - int max_len = (ctx.max_code - pracc_pre_post) / pracc_loop_byte; + int max_len = (PRACC_MAX_INSTRUCTIONS - pracc_pre_post) / pracc_loop_byte; int to_xfer = len > max_len ? max_len : len; int partial_xfer = len != to_xfer; int padded_len = (to_xfer + 3) & ~3; @@ -274,14 +274,12 @@ static int ath79_spi_bitbang_chunk(struct flash_bank *bank, *transferred = 0; pracc_queue_init(&ctx); - if (ctx.retval != ERROR_OK) - goto exit; LOG_DEBUG("ath79_spi_bitbang_bytes(%p, %08x, %p, %d)", target, ath79_info->io_base, data, len); LOG_DEBUG("max code %d => max len %d. to_xfer %d", - ctx.max_code, max_len, to_xfer); + PRACC_MAX_INSTRUCTIONS, max_len, to_xfer); pracc_words = ath79_spi_bitbang_codegen( ath79_info, &ctx, data, to_xfer, partial_xfer); @@ -289,7 +287,7 @@ static int ath79_spi_bitbang_chunk(struct flash_bank *bank, LOG_DEBUG("Assembled %d instructions, %d stores", ctx.code_count, ctx.store_count); - ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, out); + ctx.retval = mips32_pracc_queue_exec(ejtag_info, &ctx, out, 1); if (ctx.retval != ERROR_OK) goto exit; -- cgit v1.1