From 6b49fbe594db31ce34eee970be7a7416f96d7aec Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 29 Jun 2016 15:21:15 +1200 Subject: [PATCH 01/24] Quiet adiv5 probe. --- src/adiv5.c | 19 ++++++++++++------- src/cortexa.c | 4 ---- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/adiv5.c b/src/adiv5.c index 478f5be..6e0680e 100644 --- a/src/adiv5.c +++ b/src/adiv5.c @@ -277,8 +277,6 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr) /* Extract Component ID class nibble */ uint32_t cid_class = (cidr & CID_CLASS_MASK) >> CID_CLASS_SHIFT; - DEBUG("0x%X: \"%s\"\n", addr, cidc_debug_strings[cid_class]); - if (cid_class == cidc_romtab) { /* ROM table, probe recursively */ for (int i = 0; i < 256; i++) { uint32_t entry = adiv5_mem_read32(ap, addr + i*4); @@ -304,15 +302,18 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr) /* Find the part number in our part list and run the appropriate probe * routine if applicable. */ - for (int i = 0; pidr_pn_bits[i].arch != aa_end; i++) { + int i; + for (i = 0; pidr_pn_bits[i].arch != aa_end; i++) { if (pidr_pn_bits[i].part_number == part_number) { - DEBUG("0x%X: %s %s\n", addr, + DEBUG("0x%X: %s - %s %s\n", addr, + cidc_debug_strings[cid_class], pidr_pn_bits[i].type, pidr_pn_bits[i].full); /* Perform sanity check, if we know what to expect as component ID * class. */ - if (cid_class != pidr_pn_bits[i].cidc) { + if ((pidr_pn_bits[i].cidc != cidc_unknown) && + (cid_class != pidr_pn_bits[i].cidc)) { DEBUG("WARNING: \"%s\" !match expected \"%s\"\n", cidc_debug_strings[cid_class], cidc_debug_strings[pidr_pn_bits[i].cidc]); @@ -327,11 +328,15 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr) cortexa_probe(ap, addr); break; default: - DEBUG("-> skip\n"); + break; } break; } } + if (pidr_pn_bits[i].arch == aa_end) { + DEBUG("0x%X: %s - Unknown (PIDR = 0x%"PRIx64")\n", addr, + cidc_debug_strings[cid_class], pidr); + } } } @@ -372,7 +377,7 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel) ap->csw &= ~ADIV5_AP_CSW_TRINPROG; } - DEBUG("%3d: IDR=%08X CFG=%08X BASE=%08X CSW=%08X\n", + DEBUG(" AP %3d: IDR=%08X CFG=%08X BASE=%08X CSW=%08X\n", apsel, ap->idr, ap->cfg, ap->base, ap->csw); return ap; diff --git a/src/cortexa.c b/src/cortexa.c index 0d731d2..79c53a6 100644 --- a/src/cortexa.c +++ b/src/cortexa.c @@ -360,9 +360,6 @@ bool cortexa_probe(ADIv5_AP_t *apb, uint32_t debug_base) { target *t; - DEBUG("%s base=0x%08"PRIx32"\n", __func__, debug_base); - - /* Prepend to target list... */ t = target_new(sizeof(*t)); adiv5_ap_ref(apb); struct cortexa_priv *priv = calloc(1, sizeof(*priv)); @@ -391,7 +388,6 @@ bool cortexa_probe(ADIv5_AP_t *apb, uint32_t debug_base) adiv5_ap_write(apb, ADIV5_AP_CSW, csw); uint32_t dbgdidr = apb_read(t, DBGDIDR); priv->hw_breakpoint_max = ((dbgdidr >> 24) & 15)+1; - DEBUG("Target has %d breakpoints\n", priv->hw_breakpoint_max); t->check_error = cortexa_check_error; From 0fc61efe7ca5a0dab725f9011f79e9332d4d7433 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 29 Jun 2016 16:04:33 +1200 Subject: [PATCH 02/24] Move STM32L[01] bit definitions to their driver and remove header. --- src/include/stm32lx-nvm.h | 190 -------------------------------------- src/stm32l0.c | 83 ++++++++++++++--- 2 files changed, 72 insertions(+), 201 deletions(-) delete mode 100644 src/include/stm32lx-nvm.h diff --git a/src/include/stm32lx-nvm.h b/src/include/stm32lx-nvm.h deleted file mode 100644 index 2e9d8c5..0000000 --- a/src/include/stm32lx-nvm.h +++ /dev/null @@ -1,190 +0,0 @@ -/* @file stm32lx-nvm.h - * - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2014 Woollysoft - * Written by Marc Singer - * - * 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 3 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 . - */ - -#if !defined (STM32Lx_NVM_H_INCLUDED) -# define STM32Lx_NVM_H_INCLUDED - -/* ----- Includes */ - -#include - -/* ----- Macros */ - -/* ----- Types */ - -enum { - STM32Lx_STUB_PHYS = 0x20000000ul, - STM32Lx_STUB_INFO_PHYS = 0x20000004ul, - STM32Lx_STUB_DATA_PHYS = (0x20000000ul + 1024), - STM32Lx_STUB_DATA_MAX = 2048, - - STM32Lx_NVM_OPT_PHYS = 0x1ff80000ul, - STM32Lx_NVM_EEPROM_PHYS = 0x08080000ul, - - STM32L0_NVM_PHYS = 0x40022000ul, - STM32L0_NVM_PROG_PAGE_SIZE = 128, - STM32L0_NVM_DATA_PAGE_SIZE = 4, - STM32L0_NVM_OPT_SIZE = 12, - STM32L0_NVM_EEPROM_SIZE = 2*1024, - - STM32L1_NVM_PHYS = 0x40023c00ul, - STM32L1_NVM_PROG_PAGE_SIZE = 256, - STM32L1_NVM_DATA_PAGE_SIZE = 4, - STM32L1_NVM_OPT_SIZE = 32, - STM32L1_NVM_EEPROM_SIZE = 16*1024, - - STM32Lx_NVM_PEKEY1 = 0x89abcdeful, - STM32Lx_NVM_PEKEY2 = 0x02030405ul, - STM32Lx_NVM_PRGKEY1 = 0x8c9daebful, - STM32Lx_NVM_PRGKEY2 = 0x13141516ul, - STM32Lx_NVM_OPTKEY1 = 0xfbead9c8ul, - STM32Lx_NVM_OPTKEY2 = 0x24252627ul, - - STM32Lx_NVM_PECR_OBL_LAUNCH = (1<<18), - STM32Lx_NVM_PECR_ERRIE = (1<<17), - STM32Lx_NVM_PECR_EOPIE = (1<<16), - STM32Lx_NVM_PECR_FPRG = (1<<10), - STM32Lx_NVM_PECR_ERASE = (1<< 9), - STM32Lx_NVM_PECR_FIX = (1<< 8), /* FTDW */ - STM32Lx_NVM_PECR_DATA = (1<< 4), - STM32Lx_NVM_PECR_PROG = (1<< 3), - STM32Lx_NVM_PECR_OPTLOCK = (1<< 2), - STM32Lx_NVM_PECR_PRGLOCK = (1<< 1), - STM32Lx_NVM_PECR_PELOCK = (1<< 0), - - STM32Lx_NVM_SR_FWWERR = (1<<17), - STM32Lx_NVM_SR_NOTZEROERR = (1<<16), - STM32Lx_NVM_SR_RDERR = (1<<13), - STM32Lx_NVM_SR_OPTVER = (1<<11), - STM32Lx_NVM_SR_SIZERR = (1<<10), - STM32Lx_NVM_SR_PGAERR = (1<<9), - STM32Lx_NVM_SR_WRPERR = (1<<8), - STM32Lx_NVM_SR_READY = (1<<3), - STM32Lx_NVM_SR_HWOFF = (1<<2), - STM32Lx_NVM_SR_EOP = (1<<1), - STM32Lx_NVM_SR_BSY = (1<<0), - STM32Lx_NVM_SR_ERR_M = ( STM32Lx_NVM_SR_WRPERR - | STM32Lx_NVM_SR_PGAERR - | STM32Lx_NVM_SR_SIZERR - | STM32Lx_NVM_SR_NOTZEROERR), - - STM32L0_NVM_OPTR_BOOT1 = (1<<31), - STM32L0_NVM_OPTR_WDG_SW = (1<<20), - STM32L0_NVM_OPTR_WPRMOD = (1<<8), - STM32L0_NVM_OPTR_RDPROT_S = (0), - STM32L0_NVM_OPTR_RDPROT_M = (0xff), - STM32L0_NVM_OPTR_RDPROT_0 = (0xaa), - STM32L0_NVM_OPTR_RDPROT_2 = (0xcc), - - STM32L1_NVM_OPTR_nBFB2 = (1<<23), - STM32L1_NVM_OPTR_nRST_STDBY = (1<<22), - STM32L1_NVM_OPTR_nRST_STOP = (1<<21), - STM32L1_NVM_OPTR_WDG_SW = (1<<20), - STM32L1_NVM_OPTR_BOR_LEV_S = (16), - STM32L1_NVM_OPTR_BOR_LEV_M = (0xf), - STM32L1_NVM_OPTR_SPRMOD = (1<<8), - STM32L1_NVM_OPTR_RDPROT_S = (0), - STM32L1_NVM_OPTR_RDPROT_M = (0xff), - STM32L1_NVM_OPTR_RDPROT_0 = (0xaa), - STM32L1_NVM_OPTR_RDPROT_2 = (0xcc), - -}; - -#if defined (__cplusplus) - -namespace STM32 { - struct NVM { - volatile uint32_t acr; - volatile uint32_t pecr; - volatile uint32_t pdkeyr; - volatile uint32_t pkeyr; - volatile uint32_t prgkeyr; - volatile uint32_t optkeyr; - volatile uint32_t sr; - volatile uint32_t optr; - volatile uint32_t wrprot; - - static constexpr uint32_t PKEY1 = 0x89abcdef; - static constexpr uint32_t PKEY2 = 0x02030405; - static constexpr uint32_t PRGKEY1 = 0x8c9daebf; - static constexpr uint32_t PRGKEY2 = 0x13141516; - static constexpr uint32_t OPTKEY1 = 0xfbead9c8; - static constexpr uint32_t OPTKEY2 = 0x24252627; - static constexpr uint32_t PDKEY1 = 0x04152637; - static constexpr uint32_t PDKEY2 = 0xfafbfcfd; - }; - - static_assert(sizeof (NVM) == 9*4, "NVM size error"); -} -using stm32lx_stub_pointer_t = uint32_t*; - -#define Nvm(nvm) (*reinterpret_cast(nvm)) -#define Info (*reinterpret_cast(STM32Lx_STUB_INFO_PHYS)) - -namespace { - inline __attribute((always_inline)) bool unlock (STM32::NVM& nvm) { - // Lock guarantees unlock - nvm.pecr = STM32Lx_NVM_PECR_PELOCK; - - nvm.pkeyr = STM32::NVM::PKEY1; - nvm.pkeyr = STM32::NVM::PKEY2; - nvm.prgkeyr = STM32::NVM::PRGKEY1; - nvm.prgkeyr = STM32::NVM::PRGKEY2; - return !(nvm.pecr & STM32Lx_NVM_PECR_PRGLOCK); - } - inline __attribute((always_inline)) void lock (STM32::NVM& nvm) { - nvm.pecr = STM32Lx_NVM_PECR_PELOCK; } - -} - -#else - -typedef uint32_t stm32lx_stub_pointer_t; - -#define STM32Lx_NVM_PECR(p) ((p) + 0x04) -#define STM32Lx_NVM_PEKEYR(p) ((p) + 0x0C) -#define STM32Lx_NVM_PRGKEYR(p) ((p) + 0x10) -#define STM32Lx_NVM_OPTKEYR(p) ((p) + 0x14) -#define STM32Lx_NVM_SR(p) ((p) + 0x18) -#define STM32Lx_NVM_OPTR(p) ((p) + 0x1C) - -#endif - -enum { - OPT_STM32L1 = 1<<1, -}; - -struct stm32lx_nvm_stub_info { - stm32lx_stub_pointer_t destination; - int32_t size; - stm32lx_stub_pointer_t source; - uint32_t nvm; - uint16_t page_size; - uint16_t options; -} __attribute__((packed)); - -/* ----- Globals */ - -/* ----- Prototypes */ - - - -#endif /* STM32Lx_NVM_H_INCLUDED */ diff --git a/src/stm32l0.c b/src/stm32l0.c index 0c35577..b5ee548 100644 --- a/src/stm32l0.c +++ b/src/stm32l0.c @@ -80,7 +80,68 @@ #include "gdb_packet.h" #include "cortexm.h" -#include "stm32lx-nvm.h" +#define STM32Lx_NVM_PECR(p) ((p) + 0x04) +#define STM32Lx_NVM_PEKEYR(p) ((p) + 0x0C) +#define STM32Lx_NVM_PRGKEYR(p) ((p) + 0x10) +#define STM32Lx_NVM_OPTKEYR(p) ((p) + 0x14) +#define STM32Lx_NVM_SR(p) ((p) + 0x18) +#define STM32Lx_NVM_OPTR(p) ((p) + 0x1C) + +#define STM32L0_NVM_PHYS (0x40022000ul) +#define STM32L0_NVM_OPT_SIZE (12) +#define STM32L0_NVM_EEPROM_SIZE (2*1024) + +#define STM32L1_NVM_PHYS (0x40023c00ul) +#define STM32L1_NVM_OPT_SIZE (32) +#define STM32L1_NVM_EEPROM_SIZE (16*1024) + +#define STM32Lx_NVM_OPT_PHYS 0x1ff80000ul +#define STM32Lx_NVM_EEPROM_PHYS 0x08080000ul + +#define STM32Lx_NVM_PEKEY1 (0x89abcdeful) +#define STM32Lx_NVM_PEKEY2 (0x02030405ul) +#define STM32Lx_NVM_PRGKEY1 (0x8c9daebful) +#define STM32Lx_NVM_PRGKEY2 (0x13141516ul) +#define STM32Lx_NVM_OPTKEY1 (0xfbead9c8ul) +#define STM32Lx_NVM_OPTKEY2 (0x24252627ul) + +#define STM32Lx_NVM_PECR_OBL_LAUNCH (1<<18) +#define STM32Lx_NVM_PECR_ERRIE (1<<17) +#define STM32Lx_NVM_PECR_EOPIE (1<<16) +#define STM32Lx_NVM_PECR_FPRG (1<<10) +#define STM32Lx_NVM_PECR_ERASE (1<< 9) +#define STM32Lx_NVM_PECR_FIX (1<< 8) /* FTDW */ +#define STM32Lx_NVM_PECR_DATA (1<< 4) +#define STM32Lx_NVM_PECR_PROG (1<< 3) +#define STM32Lx_NVM_PECR_OPTLOCK (1<< 2) +#define STM32Lx_NVM_PECR_PRGLOCK (1<< 1) +#define STM32Lx_NVM_PECR_PELOCK (1<< 0) + +#define STM32Lx_NVM_SR_NOTZEROERR (1<<16) +#define STM32Lx_NVM_SR_SIZERR (1<<10) +#define STM32Lx_NVM_SR_PGAERR (1<<9) +#define STM32Lx_NVM_SR_WRPERR (1<<8) +#define STM32Lx_NVM_SR_EOP (1<<1) +#define STM32Lx_NVM_SR_BSY (1<<0) +#define STM32Lx_NVM_SR_ERR_M (STM32Lx_NVM_SR_WRPERR | \ + STM32Lx_NVM_SR_PGAERR | \ + STM32Lx_NVM_SR_SIZERR | \ + STM32Lx_NVM_SR_NOTZEROERR) + +#define STM32L0_NVM_OPTR_BOOT1 (1<<31) +#define STM32Lx_NVM_OPTR_WDG_SW (1<<20) +#define STM32L0_NVM_OPTR_WPRMOD (1<<8) +#define STM32Lx_NVM_OPTR_RDPROT_S (0) +#define STM32Lx_NVM_OPTR_RDPROT_M (0xff) +#define STM32Lx_NVM_OPTR_RDPROT_0 (0xaa) +#define STM32Lx_NVM_OPTR_RDPROT_2 (0xcc) + +#define STM32L1_NVM_OPTR_nBFB2 (1<<23) +#define STM32L1_NVM_OPTR_nRST_STDBY (1<<22) +#define STM32L1_NVM_OPTR_nRST_STOP (1<<21) +#define STM32L1_NVM_OPTR_BOR_LEV_S (16) +#define STM32L1_NVM_OPTR_BOR_LEV_M (0xf) +#define STM32L1_NVM_OPTR_SPRMOD (1<<8) static int stm32lx_nvm_prog_erase(struct target_flash* f, uint32_t addr, size_t len); @@ -566,11 +627,11 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv) if (stm32lx_is_stm32l1(t)) { uint32_t optr = target_mem_read32(t, STM32Lx_NVM_OPTR(nvm)); - uint8_t rdprot = (optr >> STM32L1_NVM_OPTR_RDPROT_S) - & STM32L1_NVM_OPTR_RDPROT_M; - if (rdprot == STM32L1_NVM_OPTR_RDPROT_0) + uint8_t rdprot = (optr >> STM32Lx_NVM_OPTR_RDPROT_S) + & STM32Lx_NVM_OPTR_RDPROT_M; + if (rdprot == STM32Lx_NVM_OPTR_RDPROT_0) rdprot = 0; - else if (rdprot == STM32L1_NVM_OPTR_RDPROT_2) + else if (rdprot == STM32Lx_NVM_OPTR_RDPROT_2) rdprot = 2; else rdprot = 1; @@ -581,18 +642,18 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv) (optr & STM32L1_NVM_OPTR_SPRMOD) ? 1 : 0, (optr >> STM32L1_NVM_OPTR_BOR_LEV_S) & STM32L1_NVM_OPTR_BOR_LEV_M, - (optr & STM32L1_NVM_OPTR_WDG_SW) ? 1 : 0, + (optr & STM32Lx_NVM_OPTR_WDG_SW) ? 1 : 0, (optr & STM32L1_NVM_OPTR_nRST_STOP) ? 1 : 0, (optr & STM32L1_NVM_OPTR_nRST_STDBY) ? 1 : 0, (optr & STM32L1_NVM_OPTR_nBFB2) ? 1 : 0); } else { uint32_t optr = target_mem_read32(t, STM32Lx_NVM_OPTR(nvm)); - uint8_t rdprot = (optr >> STM32L0_NVM_OPTR_RDPROT_S) - & STM32L0_NVM_OPTR_RDPROT_M; - if (rdprot == STM32L0_NVM_OPTR_RDPROT_0) + uint8_t rdprot = (optr >> STM32Lx_NVM_OPTR_RDPROT_S) + & STM32Lx_NVM_OPTR_RDPROT_M; + if (rdprot == STM32Lx_NVM_OPTR_RDPROT_0) rdprot = 0; - else if (rdprot == STM32L0_NVM_OPTR_RDPROT_2) + else if (rdprot == STM32Lx_NVM_OPTR_RDPROT_2) rdprot = 2; else rdprot = 1; @@ -600,7 +661,7 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv) "BOOT1 %d\n", optr, rdprot, (optr & STM32L0_NVM_OPTR_WPRMOD) ? 1 : 0, - (optr & STM32L0_NVM_OPTR_WDG_SW) ? 1 : 0, + (optr & STM32Lx_NVM_OPTR_WDG_SW) ? 1 : 0, (optr & STM32L0_NVM_OPTR_BOOT1) ? 1 : 0); } From 3c44cce935498492ba7eb2c3f5829bf70aad6de8 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 29 Jun 2016 17:56:20 +1200 Subject: [PATCH 03/24] Make generic jtagtap function weak and stop including the c file. --- src/Makefile | 1 + src/jtagtap_generic.c | 17 +++++------------ src/platforms/stm32/jtagtap.c | 8 -------- src/platforms/tm4c/jtagtap.c | 4 ---- 4 files changed, 6 insertions(+), 24 deletions(-) diff --git a/src/Makefile b/src/Makefile index f43ffff..ea5a857 100644 --- a/src/Makefile +++ b/src/Makefile @@ -34,6 +34,7 @@ SRC = \ hex_utils.c \ jtag_scan.c \ jtagtap.c \ + jtagtap_generic.c \ lmi.c \ lpc_common.c \ lpc11xx.c \ diff --git a/src/jtagtap_generic.c b/src/jtagtap_generic.c index 63c8e44..416bcb6 100644 --- a/src/jtagtap_generic.c +++ b/src/jtagtap_generic.c @@ -21,9 +21,10 @@ /* This file provides generic forms of the low-level jtagtap functions * for platforms that don't require optimised forms. */ +#include "general.h" +#include "jtagtap.h" -#ifdef PROVIDE_GENERIC_JTAGTAP_TMS_SEQ -void +void __attribute__((weak)) jtagtap_tms_seq(uint32_t MS, int ticks) { while(ticks--) { @@ -31,11 +32,8 @@ jtagtap_tms_seq(uint32_t MS, int ticks) MS >>= 1; } } -#endif - -#ifdef PROVIDE_GENERIC_JTAGTAP_TDI_TDO_SEQ -void +void __attribute__((weak)) jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks) { uint8_t index = 1; @@ -51,11 +49,8 @@ jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int } } } -#endif - -#ifdef PROVIDE_GENERIC_JTAGTAP_TDI_SEQ -void +void __attribute__((weak)) jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks) { uint8_t index = 1; @@ -67,6 +62,4 @@ jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks) } } } -#endif - diff --git a/src/platforms/stm32/jtagtap.c b/src/platforms/stm32/jtagtap.c index baaa149..ecd0698 100644 --- a/src/platforms/stm32/jtagtap.c +++ b/src/platforms/stm32/jtagtap.c @@ -66,11 +66,3 @@ inline uint8_t jtagtap_next(uint8_t dTMS, uint8_t dTDO) return ret != 0; } - - -#define PROVIDE_GENERIC_JTAGTAP_TMS_SEQ -#define PROVIDE_GENERIC_JTAGTAP_TDI_TDO_SEQ -#define PROVIDE_GENERIC_JTAGTAP_TDI_SEQ - -#include "jtagtap_generic.c" - diff --git a/src/platforms/tm4c/jtagtap.c b/src/platforms/tm4c/jtagtap.c index c32a437..c6b8d7e 100644 --- a/src/platforms/tm4c/jtagtap.c +++ b/src/platforms/tm4c/jtagtap.c @@ -41,7 +41,3 @@ jtagtap_next(const uint8_t dTMS, const uint8_t dTDO) return ret != 0; } -#define PROVIDE_GENERIC_JTAGTAP_TMS_SEQ -#define PROVIDE_GENERIC_JTAGTAP_TDI_TDO_SEQ -#define PROVIDE_GENERIC_JTAGTAP_TDI_SEQ -#include "jtagtap_generic.c" From 67bd1530b7dc3cf5e30a3302f0d459d58747806b Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 29 Jun 2016 19:48:01 +1200 Subject: [PATCH 04/24] Remove some unused includes. --- src/adiv5_swdp.c | 1 - src/gdb_main.c | 3 --- src/main.c | 2 -- 3 files changed, 6 deletions(-) diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index 57d0e67..7cba941 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -26,7 +26,6 @@ #include "exception.h" #include "adiv5.h" #include "swdptap.h" -#include "jtagtap.h" #include "command.h" #include "morse.h" #include "gdb_packet.h" diff --git a/src/gdb_main.c b/src/gdb_main.c index c2f2337..77d2ce0 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -29,9 +29,6 @@ #include "gdb_if.h" #include "gdb_packet.h" #include "gdb_main.h" -#include "jtagtap.h" -#include "jtag_scan.h" -#include "adiv5.h" #include "target.h" #include "command.h" #include "crc32.h" diff --git a/src/main.c b/src/main.c index 9f37107..de11953 100644 --- a/src/main.c +++ b/src/main.c @@ -25,8 +25,6 @@ #include "general.h" #include "gdb_if.h" #include "gdb_main.h" -#include "jtagtap.h" -#include "jtag_scan.h" #include "target.h" #include "exception.h" #include "gdb_packet.h" From 4e04c1ddedbc0a87af417b8f421f05826a0bf4f3 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 29 Jun 2016 20:03:32 +1200 Subject: [PATCH 05/24] Split out non-public target stuff into new header. Wrap target methods with functions instead of macros. --- src/Makefile | 1 + src/gdb_main.c | 9 +- src/include/target.h | 227 ++++++------------------------------------ src/target.c | 115 ++++++++++++++++++++- src/target_internal.h | 137 +++++++++++++++++++++++++ 5 files changed, 281 insertions(+), 208 deletions(-) create mode 100644 src/target_internal.h diff --git a/src/Makefile b/src/Makefile index ea5a857..7080875 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,6 +13,7 @@ OPT_FLAGS ?= -O2 CFLAGS += -Wall -Wextra -Werror -Wno-char-subscripts\ $(OPT_FLAGS) -std=gnu99 -g3 -MD \ -I. -Iinclude -Iplatforms/common -I$(PLATFORM_DIR) +LDFLAGS += $(OPT_FLAGS) ifeq ($(ENABLE_DEBUG), 1) CFLAGS += -DENABLE_DEBUG diff --git a/src/gdb_main.c b/src/gdb_main.c index 77d2ce0..124fbd2 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -365,14 +365,7 @@ handle_v_packet(char *packet, int plen) if (sscanf(packet, "vAttach;%08lx", &addr) == 1) { /* Attach to remote target processor */ - target *t; - uint32_t i; - for(t = target_list, i = 1; t; t = t->next, i++) - if(i == addr) { - cur_target = target_attach(t, - gdb_target_destroy_callback); - break; - } + cur_target = target_attach_n(addr, gdb_target_destroy_callback); if(cur_target) gdb_putpacketz("T05"); else diff --git a/src/include/target.h b/src/include/target.h index e0839a2..867035a 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -1,7 +1,7 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2011 Black Sphere Technologies Ltd. + * Copyright (C) 2016 Black Sphere Technologies Ltd. * Written by Gareth McMullin * * This program is free software: you can redistribute it and/or modify @@ -40,59 +40,39 @@ typedef void (*target_destroy_callback)(target *t); /* Halt/resume functions */ target *target_attach(target *t, target_destroy_callback destroy_cb); - -#define target_detach(target) \ - (target)->detach(target) - -#define target_check_error(target) \ - (target)->check_error(target) +target *target_attach_n(int n, target_destroy_callback destroy_cb); +void target_detach(target *t); +bool target_check_error(target *t); /* Memory access functions */ -#define target_mem_read(target, dest, src, len) \ - (target)->mem_read((target), (dest), (src), (len)) +void target_mem_read(target *t, void *dest, uint32_t src, size_t len); +void target_mem_write(target *t, uint32_t dest, const void *src, size_t len); -#define target_mem_write(target, dest, src, len) \ - (target)->mem_write((target), (dest), (src), (len)) +uint32_t target_mem_read32(target *t, uint32_t addr); +uint16_t target_mem_read16(target *t, uint32_t addr); +uint8_t target_mem_read8(target *t, uint32_t addr); +void target_mem_write32(target *t, uint32_t addr, uint32_t value); +void target_mem_write16(target *t, uint32_t addr, uint16_t value); +void target_mem_write8(target *t, uint32_t addr, uint8_t value); /* Register access functions */ -#define target_regs_read(target, data) \ - (target)->regs_read((target), (data)) - -#define target_regs_write(target, data) \ - (target)->regs_write((target), (data)) - +void target_regs_read(target *t, void *data); +void target_regs_write(target *t, const void *data); /* Halt/resume functions */ -#define target_reset(target) \ - (target)->reset(target) - -#define target_halt_request(target) \ - (target)->halt_request(target) - -#define target_halt_wait(target) \ - (target)->halt_wait(target) - -#define target_halt_resume(target, step) \ - (target)->halt_resume((target), (step)) +void target_reset(target *t); +void target_halt_request(target *t); +int target_halt_wait(target *t); +void target_halt_resume(target *t, bool step); /* Break-/watchpoint functions */ -#define target_set_hw_bp(target, addr, len) \ - (target)->set_hw_bp((target), (addr), (len)) +int target_set_hw_bp(target *t, uint32_t addr, uint8_t len); +int target_clear_hw_bp(target *t, uint32_t addr, uint8_t len); -#define target_clear_hw_bp(target, addr, len) \ - (target)->clear_hw_bp((target), (addr), (len)) - - -#define target_set_hw_wp(target, type, addr, len) \ - (target)->set_hw_wp((target), (type), (addr), (len)) - -#define target_clear_hw_wp(target, type, addr, len) \ - (target)->clear_hw_wp((target), (type), (addr), (len)) - - -#define target_check_hw_wp(target, addr) \ - ((target)->check_hw_wp?(target)->check_hw_wp((target), (addr)):0) +int target_set_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len); +int target_clear_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len); +int target_check_hw_wp(target *t, uint32_t *addr); /* Flash memory access functions */ int target_flash_erase(target *t, uint32_t addr, size_t len); @@ -101,103 +81,12 @@ int target_flash_write(target *t, int target_flash_done(target *t); /* Host I/O */ -#define target_hostio_reply(target, recode, errcode) \ - (target)->hostio_reply((target), (retcode), (errcode)) +void target_hostio_reply(target *t, int32_t retcode, uint32_t errcode); /* Accessor functions */ -#define target_regs_size(target) \ - ((target)->regs_size) - -#define target_tdesc(target) \ - ((target)->tdesc ? (target)->tdesc : "") - -struct target_ram { - uint32_t start; - uint32_t length; - struct target_ram *next; -}; - -struct target_flash; -typedef int (*flash_erase_func)(struct target_flash *f, uint32_t addr, size_t len); -typedef int (*flash_write_func)(struct target_flash *f, uint32_t dest, - const void *src, size_t len); -typedef int (*flash_done_func)(struct target_flash *f); -struct target_flash { - uint32_t start; - uint32_t length; - uint32_t blocksize; - flash_erase_func erase; - flash_write_func write; - flash_done_func done; - target *t; - struct target_flash *next; - int align; - uint8_t erased; - - /* For buffered flash */ - size_t buf_size; - flash_write_func write_buf; - uint32_t buf_addr; - void *buf; -}; - -struct target_s { - /* Notify controlling debugger if target is lost */ - target_destroy_callback destroy_callback; - - /* Attach/Detach funcitons */ - bool (*attach)(target *t); - void (*detach)(target *t); - bool (*check_error)(target *t); - - /* Memory access functions */ - void (*mem_read)(target *t, void *dest, uint32_t src, - size_t len); - void (*mem_write)(target *t, uint32_t dest, - const void *src, size_t len); - - /* Register access functions */ - int regs_size; - const char *tdesc; - void (*regs_read)(target *t, void *data); - void (*regs_write)(target *t, const void *data); - - /* Halt/resume functions */ - void (*reset)(target *t); - void (*halt_request)(target *t); - int (*halt_wait)(target *t); - void (*halt_resume)(target *t, bool step); - - /* Break-/watchpoint functions */ - int (*set_hw_bp)(target *t, uint32_t addr, uint8_t len); - int (*clear_hw_bp)(target *t, uint32_t addr, uint8_t len); - - int (*set_hw_wp)(target *t, uint8_t type, uint32_t addr, uint8_t len); - int (*clear_hw_wp)(target *t, uint8_t type, uint32_t addr, uint8_t len); - - int (*check_hw_wp)(target *t, uint32_t *addr); - - /* target-defined options */ - unsigned target_options; - uint32_t idcode; - - /* Target memory map */ - char *dyn_mem_map; - struct target_ram *ram; - struct target_flash *flash; - - /* Host I/O support */ - void (*hostio_reply)(target *t, int32_t retcode, uint32_t errcode); - - const char *driver; - struct target_command_s *commands; - - int size; - struct target_s *next; - - void *priv; - void (*priv_free)(void *); -}; +int target_regs_size(target *t); +const char *target_tdesc(target *t); +const char *target_mem_map(target *t); struct target_command_s { const char *specific_name; @@ -209,68 +98,8 @@ extern target *target_list; target *target_new(unsigned size); void target_list_free(void); -void target_add_commands(target *t, const struct command_s *cmds, const char *name); -void target_add_ram(target *t, uint32_t start, uint32_t len); -void target_add_flash(target *t, struct target_flash *f); -const char *target_mem_map(target *t); -int target_flash_write_buffered(struct target_flash *f, - uint32_t dest, const void *src, size_t len); -int target_flash_done_buffered(struct target_flash *f); -static inline uint32_t target_mem_read32(target *t, uint32_t addr) -{ - uint32_t ret; - target_mem_read(t, &ret, addr, sizeof(ret)); - return ret; -} - -static inline void target_mem_write32(target *t, uint32_t addr, uint32_t value) -{ - target_mem_write(t, addr, &value, sizeof(value)); -} - -static inline uint16_t target_mem_read16(target *t, uint32_t addr) -{ - uint16_t ret; - target_mem_read(t, &ret, addr, sizeof(ret)); - return ret; -} - -static inline void target_mem_write16(target *t, uint32_t addr, uint16_t value) -{ - target_mem_write(t, addr, &value, sizeof(value)); -} - -static inline uint8_t target_mem_read8(target *t, uint32_t addr) -{ - uint8_t ret; - target_mem_read(t, &ret, addr, sizeof(ret)); - return ret; -} - -static inline void target_mem_write8(target *t, uint32_t addr, uint8_t value) -{ - target_mem_write(t, addr, &value, sizeof(value)); -} - - -/* Probe for various targets. - * Actual functions implemented in their respective drivers. - */ -bool stm32f1_probe(target *t); -bool stm32f4_probe(target *t); -bool stm32l0_probe(target *t); -bool stm32l1_probe(target *t); -bool stm32l4_probe(target *t); -bool lmi_probe(target *t); -bool lpc11xx_probe(target *t); -bool lpc15xx_probe(target *t); -bool lpc43xx_probe(target *t); -bool sam3x_probe(target *t); -bool nrf51_probe(target *t); -bool samd_probe(target *t); -bool kinetis_probe(target *t); -bool efm32_probe(target *t); +#include "target_internal.h" #endif diff --git a/src/target.c b/src/target.c index 5e44c48..94a24cf 100644 --- a/src/target.c +++ b/src/target.c @@ -1,7 +1,7 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2012 Black Sphere Technologies Ltd. + * Copyright (C) 2016 Black Sphere Technologies Ltd. * Written by Gareth McMullin * * This program is free software: you can redistribute it and/or modify @@ -80,6 +80,16 @@ void target_add_commands(target *t, const struct command_s *cmds, const char *na tc->next = NULL; } +target *target_attach_n(int n, target_destroy_callback destroy_cb) +{ + target *t; + int i; + for(t = target_list, i = 1; t; t = t->next, i++) + if(i == n) + return target_attach(t, destroy_cb); + return NULL; +} + target *target_attach(target *t, target_destroy_callback destroy_cb) { if (t->destroy_callback) @@ -254,4 +264,107 @@ int target_flash_done_buffered(struct target_flash *f) return ret; } +/* Wrapper functions */ +void target_detach(target *t) { t->detach(t); } +bool target_check_error(target *t) { return t->check_error(t); } + +/* Memory access functions */ +void target_mem_read(target *t, void *dest, uint32_t src, size_t len) +{ + t->mem_read(t, dest, src, len); +} + +void target_mem_write(target *t, uint32_t dest, const void *src, size_t len) +{ + t->mem_write(t, dest, src, len); +} + +/* Register access functions */ +void target_regs_read(target *t, void *data) { t->regs_read(t, data); } +void target_regs_write(target *t, const void *data) { t->regs_write(t, data); } + +/* Halt/resume functions */ +void target_reset(target *t) { t->reset(t); } +void target_halt_request(target *t) { t->halt_request(t); } +int target_halt_wait(target *t) { return t->halt_wait(t); } +void target_halt_resume(target *t, bool step) { t->halt_resume(t, step); } + +/* Break-/watchpoint functions */ +int target_set_hw_bp(target *t, uint32_t addr, uint8_t len) +{ + return t->set_hw_bp(t, addr, len); +} + +int target_clear_hw_bp(target *t, uint32_t addr, uint8_t len) +{ + return t->clear_hw_bp(t, addr, len); +} + +int target_set_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len) +{ + return t->set_hw_wp(t, type, addr, len); +} + +int target_clear_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len) +{ + return t->clear_hw_wp(t, type, addr, len); +} + +int target_check_hw_wp(target *t, uint32_t *addr) +{ + return t->check_hw_wp(t, addr); +} + +/* Host I/O */ +void target_hostio_reply(target *t, int32_t retcode, uint32_t errcode) +{ + t->hostio_reply(t, retcode, errcode); +} + +/* Accessor functions */ +int target_regs_size(target *t) +{ + return t->regs_size; +} + +const char *target_tdesc(target *t) +{ + return t->tdesc ? t->tdesc : ""; +} + +uint32_t target_mem_read32(target *t, uint32_t addr) +{ + uint32_t ret; + target_mem_read(t, &ret, addr, sizeof(ret)); + return ret; +} + +void target_mem_write32(target *t, uint32_t addr, uint32_t value) +{ + target_mem_write(t, addr, &value, sizeof(value)); +} + +uint16_t target_mem_read16(target *t, uint32_t addr) +{ + uint16_t ret; + target_mem_read(t, &ret, addr, sizeof(ret)); + return ret; +} + +void target_mem_write16(target *t, uint32_t addr, uint16_t value) +{ + target_mem_write(t, addr, &value, sizeof(value)); +} + +uint8_t target_mem_read8(target *t, uint32_t addr) +{ + uint8_t ret; + target_mem_read(t, &ret, addr, sizeof(ret)); + return ret; +} + +void target_mem_write8(target *t, uint32_t addr, uint8_t value) +{ + target_mem_write(t, addr, &value, sizeof(value)); +} diff --git a/src/target_internal.h b/src/target_internal.h new file mode 100644 index 0000000..6eb8fcf --- /dev/null +++ b/src/target_internal.h @@ -0,0 +1,137 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2011 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * 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 3 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 __TARGET_INTERNAL_H +#define __TARGET_INTERNAL_H + +struct target_ram { + uint32_t start; + uint32_t length; + struct target_ram *next; +}; + +struct target_flash; +typedef int (*flash_erase_func)(struct target_flash *f, uint32_t addr, size_t len); +typedef int (*flash_write_func)(struct target_flash *f, uint32_t dest, + const void *src, size_t len); +typedef int (*flash_done_func)(struct target_flash *f); +struct target_flash { + uint32_t start; + uint32_t length; + uint32_t blocksize; + flash_erase_func erase; + flash_write_func write; + flash_done_func done; + target *t; + struct target_flash *next; + int align; + uint8_t erased; + + /* For buffered flash */ + size_t buf_size; + flash_write_func write_buf; + uint32_t buf_addr; + void *buf; +}; + +struct target_s { + /* Notify controlling debugger if target is lost */ + target_destroy_callback destroy_callback; + + /* Attach/Detach funcitons */ + bool (*attach)(target *t); + void (*detach)(target *t); + bool (*check_error)(target *t); + + /* Memory access functions */ + void (*mem_read)(target *t, void *dest, uint32_t src, + size_t len); + void (*mem_write)(target *t, uint32_t dest, + const void *src, size_t len); + + /* Register access functions */ + int regs_size; + const char *tdesc; + void (*regs_read)(target *t, void *data); + void (*regs_write)(target *t, const void *data); + + /* Halt/resume functions */ + void (*reset)(target *t); + void (*halt_request)(target *t); + int (*halt_wait)(target *t); + void (*halt_resume)(target *t, bool step); + + /* Break-/watchpoint functions */ + int (*set_hw_bp)(target *t, uint32_t addr, uint8_t len); + int (*clear_hw_bp)(target *t, uint32_t addr, uint8_t len); + + int (*set_hw_wp)(target *t, uint8_t type, uint32_t addr, uint8_t len); + int (*clear_hw_wp)(target *t, uint8_t type, uint32_t addr, uint8_t len); + + int (*check_hw_wp)(target *t, uint32_t *addr); + + /* target-defined options */ + unsigned target_options; + uint32_t idcode; + + /* Target memory map */ + char *dyn_mem_map; + struct target_ram *ram; + struct target_flash *flash; + + /* Host I/O support */ + void (*hostio_reply)(target *t, int32_t retcode, uint32_t errcode); + + const char *driver; + struct target_command_s *commands; + + struct target_s *next; + + void *priv; + void (*priv_free)(void *); +}; + +void target_add_commands(target *t, const struct command_s *cmds, const char *name); +void target_add_ram(target *t, uint32_t start, uint32_t len); +void target_add_flash(target *t, struct target_flash *f); +int target_flash_write_buffered(struct target_flash *f, + uint32_t dest, const void *src, size_t len); +int target_flash_done_buffered(struct target_flash *f); + +/* Probe for various targets. + * Actual functions implemented in their respective drivers. + */ +bool stm32f1_probe(target *t); +bool stm32f4_probe(target *t); +bool stm32l0_probe(target *t); +bool stm32l1_probe(target *t); +bool stm32l4_probe(target *t); +bool lmi_probe(target *t); +bool lpc11xx_probe(target *t); +bool lpc15xx_probe(target *t); +bool lpc43xx_probe(target *t); +bool sam3x_probe(target *t); +bool nrf51_probe(target *t); +bool samd_probe(target *t); +bool kinetis_probe(target *t); +bool efm32_probe(target *t); + +#endif + From e28e1587210080f01783e76ac53b59fb14d7fd5b Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 30 Jun 2016 10:24:09 +1200 Subject: [PATCH 06/24] Move *scan prototypes to target.h. --- src/command.c | 8 -------- src/include/adiv5.h | 1 - src/include/jtag_scan.h | 2 -- src/include/target.h | 10 +++++----- src/target_internal.h | 3 +++ 5 files changed, 8 insertions(+), 16 deletions(-) diff --git a/src/command.c b/src/command.c index 7ff4432..e6fe8f6 100644 --- a/src/command.c +++ b/src/command.c @@ -26,10 +26,8 @@ #include "exception.h" #include "command.h" #include "gdb_packet.h" -#include "jtag_scan.h" #include "target.h" #include "morse.h" -#include "adiv5.h" #include "version.h" #ifdef PLATFORM_HAS_TRACESWO @@ -185,12 +183,6 @@ static bool cmd_jtag_scan(target *t, int argc, char **argv) gdb_out("JTAG device scan failed!\n"); return false; } - gdb_outf("Device IR Len IDCODE Description\n"); - for(int i = 0; i < jtag_dev_count; i++) - gdb_outf("%d\t%d\t0x%08lX %s\n", i, - jtag_devs[i].ir_len, jtag_devs[i].idcode, - jtag_devs[i].descr); - gdb_out("\n"); cmd_targets(NULL); return true; } diff --git a/src/include/adiv5.h b/src/include/adiv5.h index 6bebd3e..ca81471 100644 --- a/src/include/adiv5.h +++ b/src/include/adiv5.h @@ -164,7 +164,6 @@ void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value); uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr); void adiv5_jtag_dp_handler(jtag_dev_t *dev); -int adiv5_swdp_scan(void); void adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len); void adiv5_mem_write(ADIv5_AP_t *ap, uint32_t dest, const void *src, size_t len); diff --git a/src/include/jtag_scan.h b/src/include/jtag_scan.h index 0819dfa..e96f6e7 100644 --- a/src/include/jtag_scan.h +++ b/src/include/jtag_scan.h @@ -45,8 +45,6 @@ typedef struct jtag_dev_s { extern struct jtag_dev_s jtag_devs[JTAG_MAX_DEVS+1]; extern int jtag_dev_count; -int jtag_scan(const uint8_t *lrlens); - void jtag_dev_write_ir(jtag_dev_t *dev, uint32_t ir); void jtag_dev_shift_dr(jtag_dev_t *dev, uint8_t *dout, const uint8_t *din, int ticks); diff --git a/src/include/target.h b/src/include/target.h index 867035a..16173e9 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -27,6 +27,11 @@ typedef struct target_s target; +int adiv5_swdp_scan(void); +int jtag_scan(const uint8_t *lrlens); + +void target_list_free(void); + /* The destroy callback function will be called by target_list_free() just * before the target is free'd. This may be because we're scanning for new * targets, or because of a communication failure. The target data may @@ -94,11 +99,6 @@ struct target_command_s { struct target_command_s *next; }; -extern target *target_list; - -target *target_new(unsigned size); -void target_list_free(void); - #include "target_internal.h" #endif diff --git a/src/target_internal.h b/src/target_internal.h index 6eb8fcf..ee5d1be 100644 --- a/src/target_internal.h +++ b/src/target_internal.h @@ -21,6 +21,9 @@ #ifndef __TARGET_INTERNAL_H #define __TARGET_INTERNAL_H +extern target *target_list; +target *target_new(unsigned size); + struct target_ram { uint32_t start; uint32_t length; From 72790893aea9887e78d5b57b95ae2e791dc57f62 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 30 Jun 2016 10:28:16 +1200 Subject: [PATCH 07/24] target: move mmio routines out of public interface. Fix crc routine to use buffered reads on stm32. --- src/adiv5.c | 3 +++ src/crc32.c | 38 +++++++++++++++++++------------------- src/include/crc32.h | 1 - src/include/target.h | 7 ------- src/target_internal.h | 8 ++++++++ 5 files changed, 30 insertions(+), 27 deletions(-) diff --git a/src/adiv5.c b/src/adiv5.c index 6e0680e..53e453f 100644 --- a/src/adiv5.c +++ b/src/adiv5.c @@ -504,6 +504,9 @@ adiv5_mem_read(ADIv5_AP_t *ap, void *dest, uint32_t src, size_t len) uint32_t osrc = src; enum align align = MIN(ALIGNOF(src), ALIGNOF(len)); + if (len == 0) + return; + len >>= align; ap_mem_access_setup(ap, src, align); adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); diff --git a/src/crc32.c b/src/crc32.c index 16cc565..881f12d 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -89,23 +89,21 @@ static const uint32_t crc32_table[] = { 0xBCB4666D, 0xB8757BDA, 0xB5365D03, 0xB1F740B4, }; -uint32_t crc32_calc(uint32_t crc, uint8_t data) +static uint32_t crc32_calc(uint32_t crc, uint8_t data) { return (crc << 8) ^ crc32_table[((crc >> 24) ^ data) & 255]; } -uint32_t generic_crc32(target *t, uint32_t base, int len) +uint32_t generic_crc32(target *t, uint32_t base, size_t len) { uint32_t crc = -1; - static uint8_t bytes[128]; + uint8_t bytes[128]; while (len) { - uint32_t i; - uint32_t read_len = len >= 128 ? 128 : len; - + size_t read_len = MIN(sizeof(bytes), len); target_mem_read(t, bytes, base, read_len); - for (i=0; i -uint32_t generic_crc32(target *t, uint32_t base, int len) +uint32_t generic_crc32(target *t, uint32_t base, size_t len) { - uint32_t data; + uint8_t bytes[128]; uint32_t crc; - size_t i; CRC_CR |= CRC_CR_RESET; while (len > 3) { - data = target_mem_read32(t, base); + size_t read_len = MIN(sizeof(bytes), len) & ~3; + target_mem_read(t, bytes, base, read_len); - CRC_DR = __builtin_bswap32(data); - base += 4; - len -= 4; + for (unsigned i = 0; i < read_len; i += 4) + CRC_DR = __builtin_bswap32(*(uint32_t*)(bytes+i)); + + base += read_len; + len -= read_len; } crc = CRC_DR; + target_mem_read(t, bytes, base, len); + uint8_t *data = bytes; while (len--) { - data = target_mem_read8(t, base++); - - crc ^= data << 24; - for (i = 0; i < 8; i++) { + crc ^= *data++ << 24; + for (int i = 0; i < 8; i++) { if (crc & 0x80000000) crc = (crc << 1) ^ 0x4C11DB7; else @@ -146,5 +146,5 @@ uint32_t generic_crc32(target *t, uint32_t base, int len) } return crc; } - #endif + diff --git a/src/include/crc32.h b/src/include/crc32.h index bd8d5c4..4e0f729 100644 --- a/src/include/crc32.h +++ b/src/include/crc32.h @@ -21,7 +21,6 @@ #ifndef __CRC32_H #define __CRC32_H -uint32_t crc32_calc(uint32_t crc, uint8_t data); uint32_t generic_crc32(target *t, uint32_t base, int len); #endif diff --git a/src/include/target.h b/src/include/target.h index 16173e9..9436af4 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -53,13 +53,6 @@ bool target_check_error(target *t); void target_mem_read(target *t, void *dest, uint32_t src, size_t len); void target_mem_write(target *t, uint32_t dest, const void *src, size_t len); -uint32_t target_mem_read32(target *t, uint32_t addr); -uint16_t target_mem_read16(target *t, uint32_t addr); -uint8_t target_mem_read8(target *t, uint32_t addr); -void target_mem_write32(target *t, uint32_t addr, uint32_t value); -void target_mem_write16(target *t, uint32_t addr, uint16_t value); -void target_mem_write8(target *t, uint32_t addr, uint8_t value); - /* Register access functions */ void target_regs_read(target *t, void *data); void target_regs_write(target *t, const void *data); diff --git a/src/target_internal.h b/src/target_internal.h index ee5d1be..408056f 100644 --- a/src/target_internal.h +++ b/src/target_internal.h @@ -118,6 +118,14 @@ int target_flash_write_buffered(struct target_flash *f, uint32_t dest, const void *src, size_t len); int target_flash_done_buffered(struct target_flash *f); +/* Convenience function for MMIO access */ +uint32_t target_mem_read32(target *t, uint32_t addr); +uint16_t target_mem_read16(target *t, uint32_t addr); +uint8_t target_mem_read8(target *t, uint32_t addr); +void target_mem_write32(target *t, uint32_t addr, uint32_t value); +void target_mem_write16(target *t, uint32_t addr, uint16_t value); +void target_mem_write8(target *t, uint32_t addr, uint8_t value); + /* Probe for various targets. * Actual functions implemented in their respective drivers. */ From 07f27d1b708f133257555bf69186ea786c346858 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 30 Jun 2016 12:04:39 +1200 Subject: [PATCH 08/24] Hide target list internals form command.c Remove unused support for extended target structure size. --- src/command.c | 25 ++++++++++++------------- src/cortexa.c | 2 +- src/cortexm.c | 2 +- src/include/target.h | 7 ++++--- src/target.c | 27 ++++++++++++++++++++++++--- src/target_internal.h | 3 ++- 6 files changed, 44 insertions(+), 22 deletions(-) diff --git a/src/command.c b/src/command.c index e6fe8f6..8b1a11a 100644 --- a/src/command.c +++ b/src/command.c @@ -39,7 +39,7 @@ static bool cmd_help(target *t); static bool cmd_jtag_scan(target *t, int argc, char **argv); static bool cmd_swdp_scan(void); -static bool cmd_targets(target *t); +static bool cmd_targets(void); static bool cmd_morse(void); static bool cmd_connect_srst(target *t, int argc, const char **argv); static bool cmd_hard_srst(void); @@ -183,7 +183,7 @@ static bool cmd_jtag_scan(target *t, int argc, char **argv) gdb_out("JTAG device scan failed!\n"); return false; } - cmd_targets(NULL); + cmd_targets(); return true; } @@ -214,27 +214,26 @@ bool cmd_swdp_scan(void) return false; } - cmd_targets(NULL); + cmd_targets(); return true; } -bool cmd_targets(target *cur_target) +static void display_target(int i, target *t, void *context) { - struct target_s *t; - int i; + (void)context; + gdb_outf("%2d %c %s\n", i, target_attached(t)?'*':' ', target_driver_name(t)); +} - if(!target_list) { +bool cmd_targets(void) +{ + gdb_out("Available Targets:\n"); + gdb_out("No. Att Driver\n"); + if (!target_foreach(display_target, NULL)) { gdb_out("No usable targets found.\n"); return false; } - gdb_out("Available Targets:\n"); - gdb_out("No. Att Driver\n"); - for(t = target_list, i = 1; t; t = t->next, i++) - gdb_outf("%2d %c %s\n", i, t==cur_target?'*':' ', - t->driver); - return true; } diff --git a/src/cortexa.c b/src/cortexa.c index 79c53a6..4baf4e0 100644 --- a/src/cortexa.c +++ b/src/cortexa.c @@ -360,7 +360,7 @@ bool cortexa_probe(ADIv5_AP_t *apb, uint32_t debug_base) { target *t; - t = target_new(sizeof(*t)); + t = target_new(); adiv5_ap_ref(apb); struct cortexa_priv *priv = calloc(1, sizeof(*priv)); t->priv = priv; diff --git a/src/cortexm.c b/src/cortexm.c index 570cdd9..1e538e6 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -229,7 +229,7 @@ bool cortexm_probe(ADIv5_AP_t *ap) { target *t; - t = target_new(sizeof(*t)); + t = target_new(); adiv5_ap_ref(ap); struct cortexm_priv *priv = calloc(1, sizeof(*priv)); t->priv = priv; diff --git a/src/include/target.h b/src/include/target.h index 9436af4..fe47e21 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -30,6 +30,7 @@ typedef struct target_s target; int adiv5_swdp_scan(void); int jtag_scan(const uint8_t *lrlens); +bool target_foreach(void (*cb)(int i, target *t, void *context), void *context); void target_list_free(void); /* The destroy callback function will be called by target_list_free() just @@ -48,6 +49,7 @@ target *target_attach(target *t, target_destroy_callback destroy_cb); target *target_attach_n(int n, target_destroy_callback destroy_cb); void target_detach(target *t); bool target_check_error(target *t); +bool target_attached(target *t); /* Memory access functions */ void target_mem_read(target *t, void *dest, uint32_t src, size_t len); @@ -69,13 +71,11 @@ int target_clear_hw_bp(target *t, uint32_t addr, uint8_t len); int target_set_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len); int target_clear_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len); - int target_check_hw_wp(target *t, uint32_t *addr); /* Flash memory access functions */ int target_flash_erase(target *t, uint32_t addr, size_t len); -int target_flash_write(target *t, - uint32_t dest, const void *src, size_t len); +int target_flash_write(target *t, uint32_t dest, const void *src, size_t len); int target_flash_done(target *t); /* Host I/O */ @@ -85,6 +85,7 @@ void target_hostio_reply(target *t, int32_t retcode, uint32_t errcode); int target_regs_size(target *t); const char *target_tdesc(target *t); const char *target_mem_map(target *t); +const char *target_driver_name(target *t); struct target_command_s { const char *specific_name; diff --git a/src/target.c b/src/target.c index 94a24cf..dc2d2b4 100644 --- a/src/target.c +++ b/src/target.c @@ -23,15 +23,24 @@ target *target_list = NULL; -target *target_new(unsigned size) +target *target_new(void) { - target *t = (void*)calloc(1, size); + target *t = (void*)calloc(1, sizeof(*t)); t->next = target_list; target_list = t; return t; } +bool target_foreach(void (*cb)(int, target *t, void *context), void *context) +{ + int i = 1; + target *t = target_list; + for (; t; t = t->next, i++) + cb(i, t, context); + return target_list != NULL; +} + void target_list_free(void) { struct target_command_s *tc; @@ -100,6 +109,7 @@ target *target_attach(target *t, target_destroy_callback destroy_cb) if (!t->attach(t)) return NULL; + t->attached = true; return t; } @@ -265,8 +275,14 @@ int target_flash_done_buffered(struct target_flash *f) } /* Wrapper functions */ -void target_detach(target *t) { t->detach(t); } +void target_detach(target *t) +{ + t->detach(t); + t->attached = false; +} + bool target_check_error(target *t) { return t->check_error(t); } +bool target_attached(target *t) { return t->attached; } /* Memory access functions */ void target_mem_read(target *t, void *dest, uint32_t src, size_t len) @@ -332,6 +348,11 @@ const char *target_tdesc(target *t) return t->tdesc ? t->tdesc : ""; } +const char *target_driver_name(target *t) +{ + return t->driver; +} + uint32_t target_mem_read32(target *t, uint32_t addr) { uint32_t ret; diff --git a/src/target_internal.h b/src/target_internal.h index 408056f..98f6239 100644 --- a/src/target_internal.h +++ b/src/target_internal.h @@ -22,7 +22,7 @@ #define __TARGET_INTERNAL_H extern target *target_list; -target *target_new(unsigned size); +target *target_new(void); struct target_ram { uint32_t start; @@ -55,6 +55,7 @@ struct target_flash { }; struct target_s { + bool attached; /* Notify controlling debugger if target is lost */ target_destroy_callback destroy_callback; From 1cd03b3fa45e80f8f182bb2f7a5713fd01c571f9 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 30 Jun 2016 12:05:20 +1200 Subject: [PATCH 09/24] Allow breakpoint and watchpoint methods to be left NULL. --- src/target.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/target.c b/src/target.c index dc2d2b4..415166e 100644 --- a/src/target.c +++ b/src/target.c @@ -308,26 +308,36 @@ void target_halt_resume(target *t, bool step) { t->halt_resume(t, step); } /* Break-/watchpoint functions */ int target_set_hw_bp(target *t, uint32_t addr, uint8_t len) { + if (t->set_hw_bp == NULL) + return 0; return t->set_hw_bp(t, addr, len); } int target_clear_hw_bp(target *t, uint32_t addr, uint8_t len) { + if (t->clear_hw_bp == NULL) + return 0; return t->clear_hw_bp(t, addr, len); } int target_set_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len) { + if (t->set_hw_wp == NULL) + return 0; return t->set_hw_wp(t, type, addr, len); } int target_clear_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len) { + if (t->clear_hw_wp == NULL) + return 0; return t->clear_hw_wp(t, type, addr, len); } int target_check_hw_wp(target *t, uint32_t *addr) { + if (t->check_hw_wp == NULL) + return 0; return t->check_hw_wp(t, addr); } From 5c5f76d60e63a535caa8b54bfc5f12e21467052a Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 30 Jun 2016 14:18:05 +1200 Subject: [PATCH 10/24] target: Remove last accesses to private structure from outside. Only include target_internal.h from inside target files. --- src/adiv5_swdp.c | 9 ++------- src/command.c | 26 ++++++++++++-------------- src/cortexa.c | 7 +------ src/cortexm.c | 4 +--- src/efm32.c | 4 +--- src/include/command.h | 8 -------- src/include/target.h | 10 +++------- src/jtag_scan.c | 6 ------ src/kinetis.c | 1 + src/lmi.c | 1 + src/lpc11xx.c | 1 + src/lpc15xx.c | 1 + src/lpc43xx.c | 2 +- src/lpc_common.c | 1 + src/nrf51.c | 3 +-- src/sam3x.c | 3 +-- src/samd.c | 4 +--- src/stm32f1.c | 3 +-- src/stm32f4.c | 3 +-- src/stm32l0.c | 3 +-- src/stm32l4.c | 3 +-- src/target.c | 21 +++++++++++++++++++++ src/target_internal.h | 14 ++++++++++++++ 23 files changed, 68 insertions(+), 70 deletions(-) diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index 7cba941..f396c7d 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -26,9 +26,8 @@ #include "exception.h" #include "adiv5.h" #include "swdptap.h" -#include "command.h" -#include "morse.h" -#include "gdb_packet.h" +#include "target.h" +#include "target_internal.h" #define SWDP_ACK_OK 0x01 #define SWDP_ACK_WAIT 0x02 @@ -58,7 +57,6 @@ int adiv5_swdp_scan(void) ack = swdptap_seq_in(3); if((ack != SWDP_ACK_OK) || swdptap_seq_in_parity(&dp->idcode, 32)) { DEBUG("\n"); - morse("NO TARGETS.", 1); free(dp); return -1; } @@ -71,9 +69,6 @@ int adiv5_swdp_scan(void) adiv5_swdp_error(dp); adiv5_dp_init(dp); - if(!target_list) morse("NO TARGETS.", 1); - else morse(NULL, 0); - return target_list?1:0; } diff --git a/src/command.c b/src/command.c index 8b1a11a..be53dad 100644 --- a/src/command.c +++ b/src/command.c @@ -34,6 +34,15 @@ # include "traceswo.h" #endif +typedef bool (*cmd_handler)(target *t, int argc, const char **argv); + +struct command_s { + const char *cmd; + cmd_handler handler; + + const char *help; +}; + static bool cmd_version(void); static bool cmd_help(target *t); @@ -81,7 +90,6 @@ bool debug_bmp; int command_process(target *t, char *cmd) { - struct target_command_s *tc; const struct command_s *c; int argc = 0; const char **argv; @@ -101,19 +109,14 @@ int command_process(target *t, char *cmd) /* Accept a partial match as GDB does. * So 'mon ver' will match 'monitor version' */ - if(!strncmp(argv[0], c->cmd, strlen(argv[0]))) + if ((argc == 0) || !strncmp(argv[0], c->cmd, strlen(argv[0]))) return !c->handler(t, argc, argv); } if (!t) return -1; - for (tc = t->commands; tc; tc = tc->next) - for(c = tc->cmds; c->cmd; c++) - if(!strncmp(argv[0], c->cmd, strlen(argv[0]))) - return !c->handler(t, argc, argv); - - return -1; + return target_command(t, argc, argv); } bool cmd_version(void) @@ -128,7 +131,6 @@ bool cmd_version(void) bool cmd_help(target *t) { - struct target_command_s *tc; const struct command_s *c; gdb_out("General commands:\n"); @@ -138,11 +140,7 @@ bool cmd_help(target *t) if (!t) return -1; - for (tc = t->commands; tc; tc = tc->next) { - gdb_outf("%s specific commands:\n", tc->specific_name); - for(c = tc->cmds; c->cmd; c++) - gdb_outf("\t%s -- %s\n", c->cmd, c->help); - } + target_command_help(t); return true; } diff --git a/src/cortexa.c b/src/cortexa.c index 4baf4e0..949fc5c 100644 --- a/src/cortexa.c +++ b/src/cortexa.c @@ -29,14 +29,10 @@ */ #include "general.h" #include "exception.h" -#include "jtagtap.h" -#include "jtag_scan.h" #include "adiv5.h" #include "target.h" -#include "command.h" +#include "target_internal.h" #include "gdb_packet.h" -#include "cortexm.h" -#include "morse.h" #include @@ -606,7 +602,6 @@ static int cortexa_halt_wait(target *t) case EXCEPTION_ERROR: /* Oh crap, there's no recovery from this... */ target_list_free(); - morse("TARGET LOST.", 1); return SIGLOST; case EXCEPTION_TIMEOUT: /* Timeout isn't a problem, target could be in WFI */ diff --git a/src/cortexm.c b/src/cortexm.c index 1e538e6..46fa6ed 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -29,10 +29,9 @@ #include "exception.h" #include "adiv5.h" #include "target.h" -#include "command.h" +#include "target_internal.h" #include "gdb_packet.h" #include "cortexm.h" -#include "morse.h" #include @@ -507,7 +506,6 @@ static int cortexm_halt_wait(target *t) case EXCEPTION_ERROR: /* Oh crap, there's no recovery from this... */ target_list_free(); - morse("TARGET LOST.", 1); return SIGLOST; case EXCEPTION_TIMEOUT: /* Timeout isn't a problem, target could be in WFI */ diff --git a/src/efm32.c b/src/efm32.c index 52b2ea0..e71d1a4 100644 --- a/src/efm32.c +++ b/src/efm32.c @@ -37,10 +37,8 @@ */ #include "general.h" -#include "jtagtap.h" -#include "adiv5.h" #include "target.h" -#include "command.h" +#include "target_internal.h" #include "gdb_packet.h" #include "cortexm.h" diff --git a/src/include/command.h b/src/include/command.h index 3910bbb..539af5c 100644 --- a/src/include/command.h +++ b/src/include/command.h @@ -24,14 +24,6 @@ #include "target.h" int command_process(target *t, char *cmd); -typedef bool (*cmd_handler)(target *t, int argc, const char **argv); - -struct command_s { - const char *cmd; - cmd_handler handler; - - const char *help; -}; #endif diff --git a/src/include/target.h b/src/include/target.h index fe47e21..182f1c6 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -87,13 +87,9 @@ const char *target_tdesc(target *t); const char *target_mem_map(target *t); const char *target_driver_name(target *t); -struct target_command_s { - const char *specific_name; - const struct command_s *cmds; - struct target_command_s *next; -}; - -#include "target_internal.h" +/* Command interpreter */ +void target_command_help(target *t); +int target_command(target *t, int argc, const char *argv[]); #endif diff --git a/src/jtag_scan.c b/src/jtag_scan.c index db39c5c..4546be5 100644 --- a/src/jtag_scan.c +++ b/src/jtag_scan.c @@ -25,9 +25,7 @@ #include "general.h" #include "jtagtap.h" -#include "morse.h" #include "jtag_scan.h" -#include "gdb_packet.h" #include "target.h" #include "adiv5.h" @@ -187,7 +185,6 @@ int jtag_scan(const uint8_t *irlens) jtagtap_next(1, 1); jtagtap_return_idle(); if(!jtag_dev_count) { - morse("NO TARGETS.", 1); return 0; } @@ -224,9 +221,6 @@ int jtag_scan(const uint8_t *irlens) break; } - if(!target_list) morse("NO TARGETS.", 1); - else morse(NULL, 0); - return jtag_dev_count; } diff --git a/src/kinetis.c b/src/kinetis.c index 914df7e..d8cb9f2 100644 --- a/src/kinetis.c +++ b/src/kinetis.c @@ -29,6 +29,7 @@ #include "general.h" #include "target.h" +#include "target_internal.h" #define SIM_SDID 0x40048024 diff --git a/src/lmi.c b/src/lmi.c index e2d1809..5989990 100644 --- a/src/lmi.c +++ b/src/lmi.c @@ -26,6 +26,7 @@ #include "general.h" #include "target.h" +#include "target_internal.h" #include "cortexm.h" #define SRAM_BASE 0x20000000 diff --git a/src/lpc11xx.c b/src/lpc11xx.c index fcf9f0e..e929d6a 100644 --- a/src/lpc11xx.c +++ b/src/lpc11xx.c @@ -20,6 +20,7 @@ #include "general.h" #include "target.h" +#include "target_internal.h" #include "cortexm.h" #include "lpc_common.h" diff --git a/src/lpc15xx.c b/src/lpc15xx.c index 3f23f9f..4e362e2 100644 --- a/src/lpc15xx.c +++ b/src/lpc15xx.c @@ -21,6 +21,7 @@ #include "general.h" #include "target.h" +#include "target_internal.h" #include "cortexm.h" #include "lpc_common.h" diff --git a/src/lpc43xx.c b/src/lpc43xx.c index b6c499a..699580c 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -19,8 +19,8 @@ */ #include "general.h" -#include "command.h" #include "target.h" +#include "target_internal.h" #include "gdb_packet.h" #include "cortexm.h" #include "lpc_common.h" diff --git a/src/lpc_common.c b/src/lpc_common.c index ad62e15..88ab4a8 100644 --- a/src/lpc_common.c +++ b/src/lpc_common.c @@ -18,6 +18,7 @@ */ #include "general.h" #include "target.h" +#include "target_internal.h" #include "cortexm.h" #include "lpc_common.h" diff --git a/src/nrf51.c b/src/nrf51.c index 88e63f5..df609f2 100644 --- a/src/nrf51.c +++ b/src/nrf51.c @@ -22,9 +22,8 @@ */ #include "general.h" -#include "adiv5.h" #include "target.h" -#include "command.h" +#include "target_internal.h" #include "gdb_packet.h" #include "cortexm.h" diff --git a/src/sam3x.c b/src/sam3x.c index 703bacc..4cd1227 100644 --- a/src/sam3x.c +++ b/src/sam3x.c @@ -25,9 +25,8 @@ */ #include "general.h" -#include "adiv5.h" #include "target.h" -#include "command.h" +#include "target_internal.h" #include "gdb_packet.h" static int sam4_flash_erase(struct target_flash *f, uint32_t addr, size_t len); diff --git a/src/samd.c b/src/samd.c index a39cc37..294018f 100644 --- a/src/samd.c +++ b/src/samd.c @@ -33,10 +33,8 @@ */ #include "general.h" -#include "jtagtap.h" -#include "adiv5.h" #include "target.h" -#include "command.h" +#include "target_internal.h" #include "gdb_packet.h" #include "cortexm.h" diff --git a/src/stm32f1.c b/src/stm32f1.c index 17d6126..13996b3 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -30,10 +30,9 @@ */ #include "general.h" -#include "adiv5.h" #include "target.h" +#include "target_internal.h" #include "cortexm.h" -#include "command.h" #include "gdb_packet.h" static bool stm32f1_cmd_erase_mass(target *t); diff --git a/src/stm32f4.c b/src/stm32f4.c index f94f8db..33844ae 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -31,10 +31,9 @@ */ #include "general.h" -#include "adiv5.h" #include "target.h" +#include "target_internal.h" #include "cortexm.h" -#include "command.h" #include "gdb_packet.h" static bool stm32f4_cmd_erase_mass(target *t); diff --git a/src/stm32l0.c b/src/stm32l0.c index b5ee548..699d23e 100644 --- a/src/stm32l0.c +++ b/src/stm32l0.c @@ -74,9 +74,8 @@ */ #include "general.h" -#include "adiv5.h" #include "target.h" -#include "command.h" +#include "target_internal.h" #include "gdb_packet.h" #include "cortexm.h" diff --git a/src/stm32l4.c b/src/stm32l4.c index d4e22a7..24d1eb8 100644 --- a/src/stm32l4.c +++ b/src/stm32l4.c @@ -31,10 +31,9 @@ */ #include "general.h" -#include "adiv5.h" #include "target.h" +#include "target_internal.h" #include "cortexm.h" -#include "command.h" #include "gdb_packet.h" static bool stm32l4_cmd_erase_mass(target *t); diff --git a/src/target.c b/src/target.c index 415166e..5e98009 100644 --- a/src/target.c +++ b/src/target.c @@ -20,6 +20,7 @@ #include "general.h" #include "target.h" +#include "target_internal.h" target *target_list = NULL; @@ -399,3 +400,23 @@ void target_mem_write8(target *t, uint32_t addr, uint8_t value) target_mem_write(t, addr, &value, sizeof(value)); } +#include "gdb_packet.h" + +void target_command_help(target *t) +{ + for (struct target_command_s *tc = t->commands; tc; tc = tc->next) { + gdb_outf("%s specific commands:\n", tc->specific_name); + for(const struct command_s *c = tc->cmds; c->cmd; c++) + gdb_outf("\t%s -- %s\n", c->cmd, c->help); + } +} + +int target_command(target *t, int argc, const char *argv[]) +{ + for (struct target_command_s *tc = t->commands; tc; tc = tc->next) + for(const struct command_s *c = tc->cmds; c->cmd; c++) + if(!strncmp(argv[0], c->cmd, strlen(argv[0]))) + return !c->handler(t, argc, argv); + return -1; +} + diff --git a/src/target_internal.h b/src/target_internal.h index 98f6239..190ea72 100644 --- a/src/target_internal.h +++ b/src/target_internal.h @@ -54,6 +54,20 @@ struct target_flash { void *buf; }; +typedef bool (*cmd_handler)(target *t, int argc, const char **argv); + +struct command_s { + const char *cmd; + cmd_handler handler; + const char *help; +}; + +struct target_command_s { + const char *specific_name; + const struct command_s *cmds; + struct target_command_s *next; +}; + struct target_s { bool attached; /* Notify controlling debugger if target is lost */ From 9b8e2c3ad1931d8560057d288046db6fd87126ef Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Fri, 1 Jul 2016 10:50:17 +1200 Subject: [PATCH 11/24] target: Replace all calls to gdb_out with new tc_printf. --- src/adiv5.c | 8 +-- src/cortexa.c | 5 +- src/cortexm.c | 12 ++--- src/efm32.c | 7 ++- src/gdb_packet.c | 13 +++-- src/include/gdb_packet.h | 3 ++ src/lpc43xx.c | 11 ++--- src/nrf51.c | 23 +++++---- src/sam3x.c | 5 +- src/samd.c | 27 +++++----- src/stm32f1.c | 15 +++--- src/stm32f4.c | 15 +++--- src/stm32l0.c | 104 +++++++++++++++++++-------------------- src/stm32l4.c | 13 +++-- src/target.c | 16 ++++-- src/target_internal.h | 3 ++ 16 files changed, 143 insertions(+), 137 deletions(-) diff --git a/src/adiv5.c b/src/adiv5.c index 53e453f..8a38057 100644 --- a/src/adiv5.c +++ b/src/adiv5.c @@ -22,8 +22,8 @@ * ARM Debug Interface v5 Architecure Specification, ARM doc IHI0031A. */ #include "general.h" -#include "jtag_scan.h" -#include "gdb_packet.h" +#include "target.h" +#include "target_internal.h" #include "adiv5.h" #include "cortexm.h" #include "exception.h" @@ -373,7 +373,7 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel) ~(ADIV5_AP_CSW_SIZE_MASK | ADIV5_AP_CSW_ADDRINC_MASK); if (ap->csw & ADIV5_AP_CSW_TRINPROG) { - gdb_out("AP transaction in progress. Target may not be usable.\n"); + DEBUG("AP transaction in progress. Target may not be usable.\n"); ap->csw &= ~ADIV5_AP_CSW_TRINPROG; } @@ -395,7 +395,7 @@ void adiv5_dp_init(ADIv5_DP_t *dp) ctrlstat = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT); } if (e.type) { - gdb_out("DP not responding! Trying abort sequence...\n"); + DEBUG("DP not responding! Trying abort sequence...\n"); adiv5_dp_abort(dp, ADIV5_DP_ABORT_DAPABORT); ctrlstat = adiv5_dp_read(dp, ADIV5_DP_CTRLSTAT); } diff --git a/src/cortexa.c b/src/cortexa.c index 949fc5c..24a8c6c 100644 --- a/src/cortexa.c +++ b/src/cortexa.c @@ -32,9 +32,6 @@ #include "adiv5.h" #include "target.h" #include "target_internal.h" -#include "gdb_packet.h" - -#include static char cortexa_driver_str[] = "ARM Cortex-A"; @@ -585,7 +582,7 @@ static void cortexa_halt_request(target *t) apb_write(t, DBGDRCR, DBGDRCR_HRQ); } if (e.type) { - gdb_out("Timeout sending interrupt, is target in WFI?\n"); + tc_printf(t, "Timeout sending interrupt, is target in WFI?\n"); } } diff --git a/src/cortexm.c b/src/cortexm.c index 46fa6ed..6c783a4 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -487,7 +487,7 @@ static void cortexm_halt_request(target *t) CORTEXM_DHCSR_C_DEBUGEN); } if (e.type) { - gdb_out("Timeout sending interrupt, is target in WFI?\n"); + tc_printf(t, "Timeout sending interrupt, is target in WFI?\n"); } } @@ -818,8 +818,8 @@ static bool cortexm_vector_catch(target *t, int argc, char *argv[]) unsigned i; if ((argc < 3) || ((argv[1][0] != 'e') && (argv[1][0] != 'd'))) { - gdb_out("usage: monitor vector_catch (enable|disable) " - "(hard|int|bus|stat|chk|nocp|mm|reset)\n"); + tc_printf(t, "usage: monitor vector_catch (enable|disable) " + "(hard|int|bus|stat|chk|nocp|mm|reset)\n"); } else { for (int j = 0; j < argc; j++) for (i = 0; i < sizeof(vectors) / sizeof(char*); i++) { @@ -835,14 +835,14 @@ static bool cortexm_vector_catch(target *t, int argc, char *argv[]) target_mem_write32(t, CORTEXM_DEMCR, priv->demcr); } - gdb_out("Catching vectors: "); + tc_printf(t, "Catching vectors: "); for (i = 0; i < sizeof(vectors) / sizeof(char*); i++) { if (!vectors[i]) continue; if (priv->demcr & (1 << i)) - gdb_outf("%s ", vectors[i]); + tc_printf(t, "%s ", vectors[i]); } - gdb_out("\n"); + tc_printf(t, "\n"); return true; } diff --git a/src/efm32.c b/src/efm32.c index e71d1a4..3725121 100644 --- a/src/efm32.c +++ b/src/efm32.c @@ -39,7 +39,6 @@ #include "general.h" #include "target.h" #include "target_internal.h" -#include "gdb_packet.h" #include "cortexm.h" #define SRAM_BASE 0x20000000 @@ -334,7 +333,7 @@ bool efm32_probe(target *t) /* Setup Target */ t->target_options |= CORTEXM_TOPT_INHIBIT_SRST; t->driver = variant_string; - gdb_outf("flash size %d page size %d\n", flash_size, flash_page_size); + tc_printf(t, "flash size %d page size %d\n", flash_size, flash_page_size); target_add_ram (t, SRAM_BASE, ram_size); efm32_add_flash(t, 0x00000000, flash_size, flash_page_size); target_add_commands(t, efm32_cmd_list, "EFM32"); @@ -416,7 +415,7 @@ static bool efm32_cmd_erase_all(target *t) /* Relock mass erase */ target_mem_write32(t, EFM32_MSC_MASSLOCK, 0); - gdb_outf("Erase successful!\n"); + tc_printf(t, "Erase successful!\n"); return true; } @@ -430,7 +429,7 @@ static bool efm32_cmd_serial(target *t) uint64_t eui = efm32_read_eui(t); /* 64 bits of unique number */ - gdb_outf("Unique Number: 0x%016llx\n", eui); + tc_printf(t, "Unique Number: 0x%016llx\n", eui); return true; } diff --git a/src/gdb_packet.c b/src/gdb_packet.c index 9ce63f2..f738996 100644 --- a/src/gdb_packet.c +++ b/src/gdb_packet.c @@ -153,16 +153,21 @@ void gdb_out(const char *buf) gdb_putpacket(hexdata, i); } -void gdb_outf(const char *fmt, ...) +void gdb_voutf(const char *fmt, va_list ap) { - va_list ap; char *buf; - va_start(ap, fmt); if (vasprintf(&buf, fmt, ap) < 0) return; gdb_out(buf); free(buf); - va_end(ap); } +void gdb_outf(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + gdb_voutf(fmt, ap); + va_end(ap); +} diff --git a/src/include/gdb_packet.h b/src/include/gdb_packet.h index aa1a654..789cfa1 100644 --- a/src/include/gdb_packet.h +++ b/src/include/gdb_packet.h @@ -21,12 +21,15 @@ #ifndef __GDB_PACKET_H #define __GDB_PACKET_H +#include + int gdb_getpacket(char *packet, int size); void gdb_putpacket(const char *packet, int size); #define gdb_putpacketz(packet) gdb_putpacket((packet), strlen(packet)) void gdb_putpacket_f(const char *packet, ...); void gdb_out(const char *buf); +void gdb_voutf(const char *fmt, va_list); void gdb_outf(const char *fmt, ...); #endif diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 699580c..1425ccf 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -21,7 +21,6 @@ #include "general.h" #include "target.h" #include "target_internal.h" -#include "gdb_packet.h" #include "cortexm.h" #include "lpc_common.h" @@ -174,7 +173,7 @@ static bool lpc43xx_cmd_erase(target *t, int argc, const char *argv[]) return false; } - gdb_outf("Erase OK.\n"); + tc_printf(t, "Erase OK.\n"); return true; } @@ -220,14 +219,14 @@ static bool lpc43xx_cmd_mkboot(target *t, int argc, const char *argv[]) { /* Usage: mkboot 0 or mkboot 1 */ if (argc != 2) { - gdb_outf("Expected bank argument 0 or 1.\n"); + tc_printf(t, "Expected bank argument 0 or 1.\n"); return false; } const long int bank = strtol(argv[1], NULL, 0); if ((bank != 0) && (bank != 1)) { - gdb_outf("Unexpected bank number, should be 0 or 1.\n"); + tc_printf(t, "Unexpected bank number, should be 0 or 1.\n"); return false; } @@ -236,11 +235,11 @@ static bool lpc43xx_cmd_mkboot(target *t, int argc, const char *argv[]) /* special command to compute/write magic vector for signature */ struct lpc_flash *f = (struct lpc_flash *)t->flash; if (lpc_iap_call(f, IAP_CMD_SET_ACTIVE_BANK, bank, CPU_CLK_KHZ)) { - gdb_outf("Set bootable failed.\n"); + tc_printf(t, "Set bootable failed.\n"); return false; } - gdb_outf("Set bootable OK.\n"); + tc_printf(t, "Set bootable OK.\n"); return true; } diff --git a/src/nrf51.c b/src/nrf51.c index df609f2..7012669 100644 --- a/src/nrf51.c +++ b/src/nrf51.c @@ -24,7 +24,6 @@ #include "general.h" #include "target.h" #include "target_internal.h" -#include "gdb_packet.h" #include "cortexm.h" static int nrf51_flash_erase(struct target_flash *f, uint32_t addr, size_t len); @@ -36,7 +35,7 @@ static bool nrf51_cmd_read_hwid(target *t); static bool nrf51_cmd_read_fwid(target *t); static bool nrf51_cmd_read_deviceid(target *t); static bool nrf51_cmd_read_deviceaddr(target *t); -static bool nrf51_cmd_read_help(void); +static bool nrf51_cmd_read_help(target *t); static bool nrf51_cmd_read(target *t, int argc, const char *argv[]); const struct command_s nrf51_cmd_list[] = { @@ -249,7 +248,7 @@ static int nrf51_flash_write(struct target_flash *f, static bool nrf51_cmd_erase_all(target *t) { - gdb_out("erase..\n"); + tc_printf(t, "erase..\n"); /* Enable erase */ target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN); @@ -273,14 +272,14 @@ static bool nrf51_cmd_erase_all(target *t) static bool nrf51_cmd_read_hwid(target *t) { uint32_t hwid = target_mem_read32(t, NRF51_FICR_CONFIGID) & 0xFFFF; - gdb_outf("Hardware ID: 0x%04X\n", hwid); + tc_printf(t, "Hardware ID: 0x%04X\n", hwid); return true; } static bool nrf51_cmd_read_fwid(target *t) { uint32_t fwid = (target_mem_read32(t, NRF51_FICR_CONFIGID) >> 16) & 0xFFFF; - gdb_outf("Firmware ID: 0x%04X\n", fwid); + tc_printf(t, "Firmware ID: 0x%04X\n", fwid); return true; } @@ -289,7 +288,7 @@ static bool nrf51_cmd_read_deviceid(target *t) uint32_t deviceid_low = target_mem_read32(t, NRF51_FICR_DEVICEID_LOW); uint32_t deviceid_high = target_mem_read32(t, NRF51_FICR_DEVICEID_HIGH); - gdb_outf("Device ID: 0x%08X%08X\n", deviceid_high, deviceid_low); + tc_printf(t, "Device ID: 0x%08X%08X\n", deviceid_high, deviceid_low); return true; } @@ -300,20 +299,20 @@ static bool nrf51_cmd_read_deviceaddr(target *t) uint32_t addr_high = target_mem_read32(t, NRF51_FICR_DEVICEADDR_HIGH) & 0xFFFF; if ((addr_type & 1) == 0) { - gdb_outf("Publicly Listed Address: 0x%04X%08X\n", addr_high, addr_low); + tc_printf(t, "Publicly Listed Address: 0x%04X%08X\n", addr_high, addr_low); } else { - gdb_outf("Randomly Assigned Address: 0x%04X%08X\n", addr_high, addr_low); + tc_printf(t, "Randomly Assigned Address: 0x%04X%08X\n", addr_high, addr_low); } return true; } -static bool nrf51_cmd_read_help(void) +static bool nrf51_cmd_read_help(target *t) { const struct command_s *c; - gdb_out("Read commands:\n"); + tc_printf(t, "Read commands:\n"); for(c = nrf51_read_cmd_list; c->cmd; c++) - gdb_outf("\t%s -- %s\n", c->cmd, c->help); + tc_printf(t, "\t%s -- %s\n", c->cmd, c->help); return true; } @@ -329,6 +328,6 @@ static bool nrf51_cmd_read(target *t, int argc, const char *argv[]) return !c->handler(t, argc - 1, &argv[1]); } - return nrf51_cmd_read_help(); + return nrf51_cmd_read_help(t); } diff --git a/src/sam3x.c b/src/sam3x.c index 4cd1227..d320c27 100644 --- a/src/sam3x.c +++ b/src/sam3x.c @@ -27,7 +27,6 @@ #include "general.h" #include "target.h" #include "target_internal.h" -#include "gdb_packet.h" static int sam4_flash_erase(struct target_flash *f, uint32_t addr, size_t len); static int sam3_flash_erase(struct target_flash *f, uint32_t addr, size_t len); @@ -334,7 +333,7 @@ static bool sam3x_cmd_gpnvm_get(target *t) uint32_t base = sam3x_flash_base(t); sam3x_flash_cmd(t, base, EEFC_FCR_FCMD_GGPB, 0); - gdb_outf("GPNVM: 0x%08X\n", target_mem_read32(t, EEFC_FRR(base))); + tc_printf(t, "GPNVM: 0x%08X\n", target_mem_read32(t, EEFC_FRR(base))); return true; } @@ -345,7 +344,7 @@ static bool sam3x_cmd_gpnvm_set(target *t, int argc, char *argv[]) uint32_t base = sam3x_flash_base(t); if (argc != 3) { - gdb_out("usage: monitor gpnvm_set \n"); + tc_printf(t, "usage: monitor gpnvm_set \n"); return false; } bit = atol(argv[1]); diff --git a/src/samd.c b/src/samd.c index 294018f..9ad99ce 100644 --- a/src/samd.c +++ b/src/samd.c @@ -35,7 +35,6 @@ #include "general.h" #include "target.h" #include "target_internal.h" -#include "gdb_packet.h" #include "cortexm.h" static int samd_flash_erase(struct target_flash *t, uint32_t addr, size_t len); @@ -538,17 +537,17 @@ static bool samd_cmd_erase_all(target *t) /* Test the protection error bit in Status A */ if (status & SAMD_STATUSA_PERR) { - gdb_outf("Erase failed due to a protection error.\n"); + tc_printf(t, "Erase failed due to a protection error.\n"); return true; } /* Test the fail bit in Status A */ if (status & SAMD_STATUSA_FAIL) { - gdb_outf("Erase failed.\n"); + tc_printf(t, "Erase failed.\n"); return true; } - gdb_outf("Erase successful!\n"); + tc_printf(t, "Erase successful!\n"); return true; } @@ -604,7 +603,7 @@ static bool samd_cmd_unlock_flash(target *t) static bool samd_cmd_read_userrow(target *t) { - gdb_outf("User Row: 0x%08x%08x\n", + tc_printf(t, "User Row: 0x%08x%08x\n", target_mem_read32(t, SAMD_NVM_USER_ROW_HIGH), target_mem_read32(t, SAMD_NVM_USER_ROW_LOW)); @@ -616,13 +615,13 @@ static bool samd_cmd_read_userrow(target *t) */ static bool samd_cmd_serial(target *t) { - gdb_outf("Serial Number: 0x"); + tc_printf(t, "Serial Number: 0x"); for (uint32_t i = 0; i < 4; i++) { - gdb_outf("%08x", target_mem_read32(t, SAMD_NVM_SERIAL(i))); + tc_printf(t, "%08x", target_mem_read32(t, SAMD_NVM_SERIAL(i))); } - gdb_outf("\n"); + tc_printf(t, "\n"); return true; } @@ -666,16 +665,16 @@ static bool samd_cmd_mbist(target *t) /* Test the protection error bit in Status A */ if (status & SAMD_STATUSA_PERR) { - gdb_outf("MBIST not run due to protection error.\n"); + tc_printf(t, "MBIST not run due to protection error.\n"); return true; } /* Test the fail bit in Status A */ if (status & SAMD_STATUSA_FAIL) { - gdb_outf("MBIST Fail @ 0x%08x\n", - target_mem_read32(t, SAMD_DSU_ADDRESS)); + tc_printf(t, "MBIST Fail @ 0x%08x\n", + target_mem_read32(t, SAMD_DSU_ADDRESS)); } else { - gdb_outf("MBIST Passed!\n"); + tc_printf(t, "MBIST Passed!\n"); } return true; @@ -694,8 +693,8 @@ static bool samd_cmd_ssb(target *t) if (target_check_error(t)) return -1; - gdb_outf("Set the security bit! " - "You will need to issue 'monitor erase_mass' to clear this.\n"); + tc_printf(t, "Set the security bit! " + "You will need to issue 'monitor erase_mass' to clear this.\n"); return true; } diff --git a/src/stm32f1.c b/src/stm32f1.c index 13996b3..7c92942 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -33,7 +33,6 @@ #include "target.h" #include "target_internal.h" #include "cortexm.h" -#include "gdb_packet.h" static bool stm32f1_cmd_erase_mass(target *t); static bool stm32f1_cmd_option(target *t, int argc, char *argv[]); @@ -166,7 +165,7 @@ bool stm32f1_probe(target *t) } flash_size = (target_mem_read32(t, FLASHSIZE_F0) & 0xffff) *0x400; - gdb_outf("flash size %d block_size %d\n", flash_size, block_size); + tc_printf(t, "flash size %d block_size %d\n", flash_size, block_size); target_add_ram(t, 0x20000000, 0x5000); stm32f1_add_flash(t, 0x8000000, flash_size, block_size); target_add_commands(t, stm32f1_cmd_list, "STM32F0"); @@ -323,16 +322,16 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[]) stm32f1_option_erase(t); stm32f1_option_write_erased(t, FLASH_OBP_RDP, flash_obp_rdp_key); } else if (rdprt) { - gdb_out("Device is Read Protected\n"); - gdb_out("Use \"monitor option erase\" to unprotect, erasing device\n"); + tc_printf(t, "Device is Read Protected\n"); + tc_printf(t, "Use \"monitor option erase\" to unprotect, erasing device\n"); return true; } else if (argc == 3) { addr = strtol(argv[1], NULL, 0); val = strtol(argv[2], NULL, 0); stm32f1_option_write(t, addr, val); } else { - gdb_out("usage: monitor option erase\n"); - gdb_out("usage: monitor option \n"); + tc_printf(t, "usage: monitor option erase\n"); + tc_printf(t, "usage: monitor option \n"); } if (0 && flash_obp_rdp_key == FLASH_OBP_RDP_KEY_F3) { @@ -347,8 +346,8 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[]) for (int i = 0; i < 0xf; i += 4) { addr = 0x1ffff800 + i; val = target_mem_read32(t, addr); - gdb_outf("0x%08X: 0x%04X\n", addr, val & 0xFFFF); - gdb_outf("0x%08X: 0x%04X\n", addr + 2, val >> 16); + tc_printf(t, "0x%08X: 0x%04X\n", addr, val & 0xFFFF); + tc_printf(t, "0x%08X: 0x%04X\n", addr + 2, val >> 16); } return true; } diff --git a/src/stm32f4.c b/src/stm32f4.c index 33844ae..2061925 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -34,7 +34,6 @@ #include "target.h" #include "target_internal.h" #include "cortexm.h" -#include "gdb_packet.h" static bool stm32f4_cmd_erase_mass(target *t); static bool stm32f4_cmd_option(target *t, int argc, char *argv[]); @@ -270,7 +269,7 @@ static bool stm32f4_cmd_erase_mass(target *t) const char spinner[] = "|/-\\"; int spinindex = 0; - gdb_out("Erasing flash... This may take a few seconds. "); + tc_printf(t, "Erasing flash... This may take a few seconds. "); stm32f4_flash_unlock(t); /* Flash mass erase start instruction */ @@ -279,13 +278,13 @@ static bool stm32f4_cmd_erase_mass(target *t) /* Read FLASH_SR to poll for BSY bit */ while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) { - gdb_outf("\b%c", spinner[spinindex++ % 4]); + tc_printf(t, "\b%c", spinner[spinindex++ % 4]); if(target_check_error(t)) { - gdb_out("\n"); + tc_printf(t, "\n"); return false; } } - gdb_out("\n"); + tc_printf(t, "\n"); /* Check for error */ uint16_t sr = target_mem_read32(t, FLASH_SR); @@ -336,14 +335,14 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) val = strtoul(argv[2], NULL, 0); stm32f4_option_write(t, val); } else { - gdb_out("usage: monitor option erase\n"); - gdb_out("usage: monitor option write \n"); + tc_printf(t, "usage: monitor option erase\n"); + tc_printf(t, "usage: monitor option write \n"); } for (int i = 0; i < len; i += 8) { uint32_t addr = start + i; val = target_mem_read32(t, addr); - gdb_outf("0x%08X: 0x%04X\n", addr, val & 0xFFFF); + tc_printf(t, "0x%08X: 0x%04X\n", addr, val & 0xFFFF); } return true; } diff --git a/src/stm32l0.c b/src/stm32l0.c index 699d23e..35fda48 100644 --- a/src/stm32l0.c +++ b/src/stm32l0.c @@ -76,7 +76,6 @@ #include "general.h" #include "target.h" #include "target_internal.h" -#include "gdb_packet.h" #include "cortexm.h" #define STM32Lx_NVM_PECR(p) ((p) + 0x04) @@ -576,7 +575,7 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv) const size_t opt_size = stm32lx_nvm_option_size(t); if (!stm32lx_nvm_opt_unlock(t, nvm)) { - gdb_out("unable to unlock NVM option bytes\n"); + tc_printf(t, "unable to unlock NVM option bytes\n"); return true; } @@ -589,25 +588,25 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv) else if (argc == 4 && !strncasecmp(argv[1], "raw", cb)) { uint32_t addr = strtoul(argv[2], NULL, 0); uint32_t val = strtoul(argv[3], NULL, 0); - gdb_outf("raw %08x <- %08x\n", addr, val); + tc_printf(t, "raw %08x <- %08x\n", addr, val); if ( addr < STM32Lx_NVM_OPT_PHYS || addr >= STM32Lx_NVM_OPT_PHYS + opt_size || (addr & 3)) goto usage; if (!stm32lx_option_write(t, addr, val)) - gdb_out("option write failed\n"); + tc_printf(t, "option write failed\n"); } else if (argc == 4 && !strncasecmp(argv[1], "write", cb)) { uint32_t addr = strtoul(argv[2], NULL, 0); uint32_t val = strtoul(argv[3], NULL, 0); val = (val & 0xffff) | ((~val & 0xffff) << 16); - gdb_outf("write %08x <- %08x\n", addr, val); + tc_printf(t, "write %08x <- %08x\n", addr, val); if ( addr < STM32Lx_NVM_OPT_PHYS || addr >= STM32Lx_NVM_OPT_PHYS + opt_size || (addr & 3)) goto usage; if (!stm32lx_option_write(t, addr, val)) - gdb_out("option write failed\n"); + tc_printf(t, "option write failed\n"); } else if (argc == 2 && !strncasecmp(argv[1], "show", cb)) ; @@ -618,10 +617,10 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv) for(unsigned i = 0; i < opt_size; i += sizeof(uint32_t)) { uint32_t addr = STM32Lx_NVM_OPT_PHYS + i; uint32_t val = target_mem_read32(t, addr); - gdb_outf("0x%08x: 0x%04x 0x%04x %s\n", - addr, val & 0xffff, (val >> 16) & 0xffff, - ((val & 0xffff) == ((~val >> 16) & 0xffff)) - ? "OK" : "ERR"); + tc_printf(t, "0x%08x: 0x%04x 0x%04x %s\n", + addr, val & 0xffff, (val >> 16) & 0xffff, + ((val & 0xffff) == ((~val >> 16) & 0xffff)) + ? "OK" : "ERR"); } if (stm32lx_is_stm32l1(t)) { @@ -634,17 +633,17 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv) rdprot = 2; else rdprot = 1; - gdb_outf("OPTR: 0x%08x, RDPRT %d, SPRMD %d, " - "BOR %d, WDG_SW %d, nRST_STP %d, nRST_STBY %d, " - "nBFB2 %d\n", - optr, rdprot, - (optr & STM32L1_NVM_OPTR_SPRMOD) ? 1 : 0, - (optr >> STM32L1_NVM_OPTR_BOR_LEV_S) - & STM32L1_NVM_OPTR_BOR_LEV_M, - (optr & STM32Lx_NVM_OPTR_WDG_SW) ? 1 : 0, - (optr & STM32L1_NVM_OPTR_nRST_STOP) ? 1 : 0, - (optr & STM32L1_NVM_OPTR_nRST_STDBY) ? 1 : 0, - (optr & STM32L1_NVM_OPTR_nBFB2) ? 1 : 0); + tc_printf(t, "OPTR: 0x%08x, RDPRT %d, SPRMD %d, " + "BOR %d, WDG_SW %d, nRST_STP %d, nRST_STBY %d, " + "nBFB2 %d\n", + optr, rdprot, + (optr & STM32L1_NVM_OPTR_SPRMOD) ? 1 : 0, + (optr >> STM32L1_NVM_OPTR_BOR_LEV_S) + & STM32L1_NVM_OPTR_BOR_LEV_M, + (optr & STM32Lx_NVM_OPTR_WDG_SW) ? 1 : 0, + (optr & STM32L1_NVM_OPTR_nRST_STOP) ? 1 : 0, + (optr & STM32L1_NVM_OPTR_nRST_STDBY) ? 1 : 0, + (optr & STM32L1_NVM_OPTR_nBFB2) ? 1 : 0); } else { uint32_t optr = target_mem_read32(t, STM32Lx_NVM_OPTR(nvm)); @@ -656,28 +655,28 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv) rdprot = 2; else rdprot = 1; - gdb_outf("OPTR: 0x%08x, RDPROT %d, WPRMOD %d, WDG_SW %d, " - "BOOT1 %d\n", - optr, rdprot, - (optr & STM32L0_NVM_OPTR_WPRMOD) ? 1 : 0, - (optr & STM32Lx_NVM_OPTR_WDG_SW) ? 1 : 0, - (optr & STM32L0_NVM_OPTR_BOOT1) ? 1 : 0); + tc_printf(t, "OPTR: 0x%08x, RDPROT %d, WPRMOD %d, WDG_SW %d, " + "BOOT1 %d\n", + optr, rdprot, + (optr & STM32L0_NVM_OPTR_WPRMOD) ? 1 : 0, + (optr & STM32Lx_NVM_OPTR_WDG_SW) ? 1 : 0, + (optr & STM32L0_NVM_OPTR_BOOT1) ? 1 : 0); } goto done; usage: - gdb_out("usage: monitor option [ARGS]\n"); - gdb_out(" show - Show options in NVM and as" - " loaded\n"); - gdb_out(" obl_launch - Reload options from NVM\n"); - gdb_out(" write - Set option half-word; " - "complement computed\n"); - gdb_out(" raw - Set option word\n"); - gdb_outf("The value of must be word aligned and from 0x%08x " - "to +0x%x\n", - STM32Lx_NVM_OPT_PHYS, - STM32Lx_NVM_OPT_PHYS + opt_size - sizeof(uint32_t)); + tc_printf(t, "usage: monitor option [ARGS]\n"); + tc_printf(t, " show - Show options in NVM and as" + " loaded\n"); + tc_printf(t, " obl_launch - Reload options from NVM\n"); + tc_printf(t, " write - Set option half-word; " + "complement computed\n"); + tc_printf(t, " raw - Set option word\n"); + tc_printf(t, "The value of must be word aligned and from 0x%08x " + "to +0x%x\n", + STM32Lx_NVM_OPT_PHYS, + STM32Lx_NVM_OPT_PHYS + opt_size - sizeof(uint32_t)); done: stm32lx_nvm_lock(t, nvm); @@ -690,7 +689,7 @@ static bool stm32lx_cmd_eeprom(target* t, int argc, char** argv) const uint32_t nvm = stm32lx_nvm_phys(t); if (!stm32lx_nvm_prog_data_unlock(t, nvm)) { - gdb_out("unable to unlock EEPROM\n"); + tc_printf(t, "unable to unlock EEPROM\n"); return true; } @@ -706,23 +705,23 @@ static bool stm32lx_cmd_eeprom(target* t, int argc, char** argv) goto usage; if (!strncasecmp(argv[1], "byte", cb)) { - gdb_outf("write byte 0x%08x <- 0x%08x\n", addr, val); + tc_printf(t, "write byte 0x%08x <- 0x%08x\n", addr, val); if (!stm32lx_eeprom_write(t, addr, 1, val)) - gdb_out("eeprom write failed\n"); + tc_printf(t, "eeprom write failed\n"); } else if (!strncasecmp(argv[1], "halfword", cb)) { val &= 0xffff; - gdb_outf("write halfword 0x%08x <- 0x%04x\n", + tc_printf(t, "write halfword 0x%08x <- 0x%04x\n", addr, val); if (addr & 1) goto usage; if (!stm32lx_eeprom_write(t, addr, 2, val)) - gdb_out("eeprom write failed\n"); + tc_printf(t, "eeprom write failed\n"); } else if (!strncasecmp(argv[1], "word", cb)) { - gdb_outf("write word 0x%08x <- 0x%08x\n", addr, val); + tc_printf(t, "write word 0x%08x <- 0x%08x\n", addr, val); if (addr & 3) goto usage; if (!stm32lx_eeprom_write(t, addr, 4, val)) - gdb_out("eeprom write failed\n"); + tc_printf(t, "eeprom write failed\n"); } else goto usage; @@ -733,14 +732,13 @@ static bool stm32lx_cmd_eeprom(target* t, int argc, char** argv) goto done; usage: - gdb_out("usage: monitor eeprom [ARGS]\n"); - gdb_out(" byte - Write a byte\n"); - gdb_out(" halfword - Write a half-word\n"); - gdb_out(" word - Write a word\n"); - gdb_outf("The value of must in the interval [0x%08x, 0x%x)\n", - STM32Lx_NVM_EEPROM_PHYS, - STM32Lx_NVM_EEPROM_PHYS - + stm32lx_nvm_eeprom_size(t)); + tc_printf(t, "usage: monitor eeprom [ARGS]\n"); + tc_printf(t, " byte - Write a byte\n"); + tc_printf(t, " halfword - Write a half-word\n"); + tc_printf(t, " word - Write a word\n"); + tc_printf(t, "The value of must in the interval [0x%08x, 0x%x)\n", + STM32Lx_NVM_EEPROM_PHYS, + STM32Lx_NVM_EEPROM_PHYS + stm32lx_nvm_eeprom_size(t)); done: stm32lx_nvm_lock(t, nvm); diff --git a/src/stm32l4.c b/src/stm32l4.c index 24d1eb8..78e14ac 100644 --- a/src/stm32l4.c +++ b/src/stm32l4.c @@ -34,7 +34,6 @@ #include "target.h" #include "target_internal.h" #include "cortexm.h" -#include "gdb_packet.h" static bool stm32l4_cmd_erase_mass(target *t); static bool stm32l4_cmd_erase_bank1(target *t); @@ -228,7 +227,7 @@ static bool stm32l4_cmd_erase(target *t, uint32_t action) const char spinner[] = "|/-\\"; int spinindex = 0; - gdb_out("Erasing flash... This may take a few seconds. "); + tc_printf(t, "Erasing flash... This may take a few seconds. "); stm32l4_flash_unlock(t); /* Flash erase action start instruction */ @@ -237,13 +236,13 @@ static bool stm32l4_cmd_erase(target *t, uint32_t action) /* Read FLASH_SR to poll for BSY bit */ while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) { - gdb_outf("\b%c", spinner[spinindex++ % 4]); + tc_printf(t, "\b%c", spinner[spinindex++ % 4]); if(target_check_error(t)) { - gdb_out("\n"); + tc_printf(t, "\n"); return false; } } - gdb_out("\n"); + tc_printf(t, "\n"); /* Check for error */ uint16_t sr = target_mem_read32(t, FLASH_SR); @@ -276,12 +275,12 @@ static bool stm32l4_cmd_option(target *t, int argc, char *argv[]) for (int i = 0; i < 0x23; i += 8) { addr = 0x1fff7800 + i; val = target_mem_read32(t, addr); - gdb_outf("0x%08X: 0x%08x\n", addr, val); + tc_printf(t, "0x%08X: 0x%08x\n", addr, val); } for (int i = 8; i < 0x23; i += 8) { addr = 0x1ffff800 + i; val = target_mem_read32(t, addr); - gdb_outf("0x%08X: 0x%08X\n", addr, val); + tc_printf(t, "0x%08X: 0x%08X\n", addr, val); } return true; } diff --git a/src/target.c b/src/target.c index 5e98009..9401815 100644 --- a/src/target.c +++ b/src/target.c @@ -400,14 +400,12 @@ void target_mem_write8(target *t, uint32_t addr, uint8_t value) target_mem_write(t, addr, &value, sizeof(value)); } -#include "gdb_packet.h" - void target_command_help(target *t) { for (struct target_command_s *tc = t->commands; tc; tc = tc->next) { - gdb_outf("%s specific commands:\n", tc->specific_name); + tc_printf(t, "%s specific commands:\n", tc->specific_name); for(const struct command_s *c = tc->cmds; c->cmd; c++) - gdb_outf("\t%s -- %s\n", c->cmd, c->help); + tc_printf(t, "\t%s -- %s\n", c->cmd, c->help); } } @@ -420,3 +418,13 @@ int target_command(target *t, int argc, const char *argv[]) return -1; } +#include "gdb_packet.h" +void tc_printf(target *t, const char *fmt, ...) +{ + (void)t; + va_list ap; + va_start(ap, fmt); + gdb_voutf(fmt, ap); + va_end(ap); +} + diff --git a/src/target_internal.h b/src/target_internal.h index 190ea72..ea0bfbc 100644 --- a/src/target_internal.h +++ b/src/target_internal.h @@ -141,6 +141,9 @@ void target_mem_write32(target *t, uint32_t addr, uint32_t value); void target_mem_write16(target *t, uint32_t addr, uint16_t value); void target_mem_write8(target *t, uint32_t addr, uint8_t value); +/* Access to host controller interface */ +void tc_printf(target *t, const char *fmt, ...); + /* Probe for various targets. * Actual functions implemented in their respective drivers. */ From 5832d8a42a16b862462d7cd91f2b986198a08ed5 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Fri, 1 Jul 2016 11:51:17 +1200 Subject: [PATCH 12/24] Clean up common SWD stuff. --- src/Makefile | 3 +- src/adiv5_swdp.c | 10 ++ src/include/swdptap.h | 8 +- src/platforms/{stm32 => common}/swdptap.c | 103 +++--------------- src/platforms/libftdi/swdptap.c | 97 ++--------------- src/platforms/tm4c/swdptap.c | 124 ---------------------- src/swdptap_generic.c | 79 ++++++++++++++ 7 files changed, 120 insertions(+), 304 deletions(-) rename src/platforms/{stm32 => common}/swdptap.c (57%) delete mode 100644 src/platforms/tm4c/swdptap.c create mode 100644 src/swdptap_generic.c diff --git a/src/Makefile b/src/Makefile index 7080875..5549277 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ PROBE_HOST ?= native PLATFORM_DIR = platforms/$(PROBE_HOST) -VPATH += platforms/common $(PLATFORM_DIR) +VPATH += $(PLATFORM_DIR) platforms/common ENABLE_DEBUG ?= ifneq ($(V), 1) @@ -53,6 +53,7 @@ SRC = \ stm32l0.c \ stm32l4.c \ swdptap.c \ + swdptap_generic.c \ target.c \ include $(PLATFORM_DIR)/Makefile.inc diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index f396c7d..d62a18e 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -50,6 +50,16 @@ int adiv5_swdp_scan(void) ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); swdptap_init(); + + /* Switch from JTAG to SWD mode */ + swdptap_seq_out(0xFFFF, 16); + for(int i = 0; i < 50; i++) + swdptap_bit_out(1); + swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */ + for(int i = 0; i < 50; i++) + swdptap_bit_out(1); + swdptap_seq_out(0, 16); + /* Read the SW-DP IDCODE register to syncronise */ /* This could be done with adiv_swdp_low_access(), but this doesn't * allow the ack to be checked here. */ diff --git a/src/include/swdptap.h b/src/include/swdptap.h index 3263a1d..c51a28c 100644 --- a/src/include/swdptap.h +++ b/src/include/swdptap.h @@ -22,10 +22,14 @@ #define __SWDPTAP_H int swdptap_init(void); -void swdptap_reset(void); +/* Primitive functions */ +bool swdptap_bit_in(void); +void swdptap_bit_out(bool val); + +/* High level functions, provided as weak in swdptap_generic.c */ uint32_t swdptap_seq_in(int ticks); -uint8_t swdptap_seq_in_parity(uint32_t *data, int ticks); +bool swdptap_seq_in_parity(uint32_t *data, int ticks); void swdptap_seq_out(uint32_t MS, int ticks); void swdptap_seq_out_parity(uint32_t MS, int ticks); diff --git a/src/platforms/stm32/swdptap.c b/src/platforms/common/swdptap.c similarity index 57% rename from src/platforms/stm32/swdptap.c rename to src/platforms/common/swdptap.c index e7049d3..bcc3ccb 100644 --- a/src/platforms/stm32/swdptap.c +++ b/src/platforms/common/swdptap.c @@ -20,24 +20,24 @@ /* This file implements the low-level SW-DP interface. */ -#include - #include "general.h" - #include "swdptap.h" -#include "gdb_packet.h" +int swdptap_init(void) +{ + return 0; +} static void swdptap_turnaround(uint8_t dir) { static uint8_t olddir = 0; - DEBUG("%s", dir ? "\n-> ":"\n<- "); - /* Don't turnaround if direction not changing */ if(dir == olddir) return; olddir = dir; + DEBUG("%s", dir ? "\n-> ":"\n<- "); + if(dir) SWDIO_MODE_FLOAT(); gpio_set(SWCLK_PORT, SWCLK_PIN); @@ -46,10 +46,12 @@ static void swdptap_turnaround(uint8_t dir) SWDIO_MODE_DRIVE(); } -static uint8_t swdptap_bit_in(void) +bool swdptap_bit_in(void) { uint16_t ret; + swdptap_turnaround(1); + ret = gpio_get(SWDIO_PORT, SWDIO_PIN); gpio_set(SWCLK_PORT, SWCLK_PIN); gpio_clear(SWCLK_PORT, SWCLK_PIN); @@ -59,95 +61,14 @@ static uint8_t swdptap_bit_in(void) return ret != 0; } -static void swdptap_bit_out(uint8_t val) +void swdptap_bit_out(bool val) { DEBUG("%d", val); + swdptap_turnaround(0); + gpio_set_val(SWDIO_PORT, SWDIO_PIN, val); gpio_set(SWCLK_PORT, SWCLK_PIN); gpio_clear(SWCLK_PORT, SWCLK_PIN); } -int swdptap_init(void) -{ - /* This must be investigated in more detail. - * As described in STM32 Reference Manual... */ - swdptap_reset(); - swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */ - swdptap_reset(); - swdptap_seq_out(0, 16); - - return 0; -} - - -void swdptap_reset(void) -{ - swdptap_turnaround(0); - /* 50 clocks with TMS high */ - for(int i = 0; i < 50; i++) swdptap_bit_out(1); -} - - -uint32_t swdptap_seq_in(int ticks) -{ - uint32_t index = 1; - uint32_t ret = 0; - - swdptap_turnaround(1); - - while(ticks--) { - if(swdptap_bit_in()) ret |= index; - index <<= 1; - } - - return ret; -} - - -uint8_t swdptap_seq_in_parity(uint32_t *ret, int ticks) -{ - uint32_t index = 1; - uint8_t parity = 0; - *ret = 0; - - swdptap_turnaround(1); - - while(ticks--) { - if(swdptap_bit_in()) { - *ret |= index; - parity ^= 1; - } - index <<= 1; - } - if(swdptap_bit_in()) parity ^= 1; - - return parity; -} - - -void swdptap_seq_out(uint32_t MS, int ticks) -{ - swdptap_turnaround(0); - - while(ticks--) { - swdptap_bit_out(MS & 1); - MS >>= 1; - } -} - - -void swdptap_seq_out_parity(uint32_t MS, int ticks) -{ - uint8_t parity = 0; - - swdptap_turnaround(0); - - while(ticks--) { - swdptap_bit_out(MS & 1); - parity ^= MS; - MS >>= 1; - } - swdptap_bit_out(parity & 1); -} - diff --git a/src/platforms/libftdi/swdptap.c b/src/platforms/libftdi/swdptap.c index 6aafa7d..c48fb1a 100644 --- a/src/platforms/libftdi/swdptap.c +++ b/src/platforms/libftdi/swdptap.c @@ -29,9 +29,7 @@ #include "general.h" #include "swdptap.h" -static void swdptap_turnaround(uint8_t dir); -static uint8_t swdptap_bit_in(void); -static void swdptap_bit_out(uint8_t val); +static uint8_t olddir = 0; int swdptap_init(void) { @@ -46,33 +44,17 @@ int swdptap_init(void) } assert(ftdi_write_data(ftdic, (void*)"\xAB\xA8", 2) == 2); - - /* This must be investigated in more detail. - * As described in STM32 Reference Manual... */ - swdptap_seq_out(0xFFFF, 16); - swdptap_reset(); - swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */ - swdptap_reset(); - swdptap_seq_out(0, 16); + olddir = 0; return 0; } -void swdptap_reset(void) -{ - swdptap_turnaround(0); - /* 50 clocks with TMS high */ - for(int i = 0; i < 50; i++) - swdptap_bit_out(1); -} - static void swdptap_turnaround(uint8_t dir) { - static uint8_t olddir = 0; - platform_buffer_flush(); - if(dir == olddir) return; + if (dir == olddir) + return; olddir = dir; if(dir) /* SWDIO goes to input */ @@ -85,10 +67,12 @@ static void swdptap_turnaround(uint8_t dir) assert(ftdi_set_bitmode(ftdic, 0xAB, BITMODE_BITBANG) == 0); } -static uint8_t swdptap_bit_in(void) +bool swdptap_bit_in(void) { uint8_t ret; + swdptap_turnaround(1); + ftdi_read_pins(ftdic, &ret); ret &= 0x08; ftdi_write_data(ftdic, (void *)"\xA1\xA0", 2); @@ -96,75 +80,16 @@ static uint8_t swdptap_bit_in(void) return ret; } -static void swdptap_bit_out(uint8_t val) +void swdptap_bit_out(bool val) { uint8_t buf[3] = "\xA0\xA1\xA0"; - if(val) { + swdptap_turnaround(0); + + if (val) { for(int i = 0; i < 3; i++) buf[i] |= 0x08; } platform_buffer_write(buf, 3); } -uint32_t swdptap_seq_in(int ticks) -{ - uint32_t index = 1; - uint32_t ret = 0; - - swdptap_turnaround(1); - - while (ticks--) { - if (swdptap_bit_in()) - ret |= index; - index <<= 1; - } - - return ret; -} - -uint8_t swdptap_seq_in_parity(uint32_t *ret, int ticks) -{ - uint32_t index = 1; - uint8_t parity = 0; - *ret = 0; - - swdptap_turnaround(1); - - while (ticks--) { - if (swdptap_bit_in()) { - *ret |= index; - parity ^= 1; - } - index <<= 1; - } - if (swdptap_bit_in()) - parity ^= 1; - - return parity; -} - -void swdptap_seq_out(uint32_t MS, int ticks) -{ - swdptap_turnaround(0); - - while (ticks--) { - swdptap_bit_out(MS & 1); - MS >>= 1; - } -} - -void swdptap_seq_out_parity(uint32_t MS, int ticks) -{ - uint8_t parity = 0; - - swdptap_turnaround(0); - - while (ticks--) { - swdptap_bit_out(MS & 1); - parity ^= MS; - MS >>= 1; - } - swdptap_bit_out(parity & 1); -} - diff --git a/src/platforms/tm4c/swdptap.c b/src/platforms/tm4c/swdptap.c deleted file mode 100644 index 058f6ba..0000000 --- a/src/platforms/tm4c/swdptap.c +++ /dev/null @@ -1,124 +0,0 @@ -#include "general.h" -#include "swdptap.h" - -static void swdptap_turnaround(uint8_t dir) -{ - static uint8_t olddir = 0; - - DEBUG("%s", dir ? "\n-> ":"\n<- "); - - /* Don't turnaround if direction not changing */ - if(dir == olddir) return; - olddir = dir; - - if(dir) - SWDIO_MODE_FLOAT(); - gpio_set(SWCLK_PORT, SWCLK_PIN); - gpio_clear(SWCLK_PORT, SWCLK_PIN); - if(!dir) - SWDIO_MODE_DRIVE(); -} - -static uint8_t swdptap_bit_in(void) -{ - uint16_t ret; - - ret = gpio_get(SWDIO_PORT, SWDIO_PIN); - gpio_set(SWCLK_PORT, SWCLK_PIN); - gpio_clear(SWCLK_PORT, SWCLK_PIN); - - DEBUG("%d", ret?1:0); - - return ret != 0; -} - -static void swdptap_bit_out(uint8_t val) -{ - DEBUG("%d", val); - - gpio_set_val(SWDIO_PORT, SWDIO_PIN, val); - gpio_set(SWCLK_PORT, SWCLK_PIN); - gpio_clear(SWCLK_PORT, SWCLK_PIN); -} - -int -swdptap_init(void) -{ - swdptap_reset(); - swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */ - swdptap_reset(); - swdptap_seq_out(0, 16); - - return 0; -} - -void -swdptap_reset(void) -{ - swdptap_turnaround(0); - /* 50 clocks with TMS high */ - for(int i = 0; i < 50; i++) swdptap_bit_out(1); -} - -uint32_t -swdptap_seq_in(int ticks) -{ - uint32_t index = 1; - uint32_t ret = 0; - - swdptap_turnaround(1); - - while(ticks--) { - if(swdptap_bit_in()) ret |= index; - index <<= 1; - } - - return ret; -} - -uint8_t -swdptap_seq_in_parity(uint32_t *ret, int ticks) -{ - uint32_t index = 1; - uint8_t parity = 0; - *ret = 0; - - swdptap_turnaround(1); - - while(ticks--) { - if(swdptap_bit_in()) { - *ret |= index; - parity ^= 1; - } - index <<= 1; - } - if(swdptap_bit_in()) parity ^= 1; - - return parity; -} - -void -swdptap_seq_out(uint32_t MS, int ticks) -{ - swdptap_turnaround(0); - - while(ticks--) { - swdptap_bit_out(MS & 1); - MS >>= 1; - } -} - -void -swdptap_seq_out_parity(uint32_t MS, int ticks) -{ - uint8_t parity = 0; - - swdptap_turnaround(0); - - while(ticks--) { - swdptap_bit_out(MS & 1); - parity ^= MS; - MS >>= 1; - } - swdptap_bit_out(parity & 1); -} diff --git a/src/swdptap_generic.c b/src/swdptap_generic.c new file mode 100644 index 0000000..13ee02f --- /dev/null +++ b/src/swdptap_generic.c @@ -0,0 +1,79 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2016 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * 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 3 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 "general.h" +#include "swdptap.h" + +uint32_t __attribute__((weak)) +swdptap_seq_in(int ticks) +{ + uint32_t index = 1; + uint32_t ret = 0; + + while (ticks--) { + if (swdptap_bit_in()) + ret |= index; + index <<= 1; + } + + return ret; +} + +bool __attribute__((weak)) +swdptap_seq_in_parity(uint32_t *ret, int ticks) +{ + uint32_t index = 1; + uint8_t parity = 0; + *ret = 0; + + while (ticks--) { + if (swdptap_bit_in()) { + *ret |= index; + parity ^= 1; + } + index <<= 1; + } + if (swdptap_bit_in()) + parity ^= 1; + + return parity; +} + +void __attribute__((weak)) +swdptap_seq_out(uint32_t MS, int ticks) +{ + while (ticks--) { + swdptap_bit_out(MS & 1); + MS >>= 1; + } +} + +void __attribute__((weak)) +swdptap_seq_out_parity(uint32_t MS, int ticks) +{ + uint8_t parity = 0; + + while (ticks--) { + swdptap_bit_out(MS & 1); + parity ^= MS; + MS >>= 1; + } + swdptap_bit_out(parity & 1); +} + From b03cc59bea43ce93b15262d986caf3aecc03cca5 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Fri, 1 Jul 2016 13:10:44 +1200 Subject: [PATCH 13/24] target: Add target controller structure for indirect calls back to host. --- src/gdb_main.c | 25 +++++++++++++++++++------ src/include/target.h | 18 ++++++------------ src/target.c | 21 +++++++++++---------- src/target_internal.h | 3 +-- 4 files changed, 37 insertions(+), 30 deletions(-) diff --git a/src/gdb_main.c b/src/gdb_main.c index 124fbd2..7833980 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -47,8 +47,9 @@ static void handle_q_packet(char *packet, int len); static void handle_v_packet(char *packet, int len); static void handle_z_packet(char *packet, int len); -static void gdb_target_destroy_callback(target *t) +static void gdb_target_destroy_callback(struct target_controller *tc, target *t) { + (void)tc; if (cur_target == t) cur_target = NULL; @@ -56,6 +57,18 @@ static void gdb_target_destroy_callback(target *t) last_target = NULL; } +static void gdb_target_printf(struct target_controller *tc, + const char *fmt, va_list ap) +{ + (void)tc; + gdb_voutf(fmt, ap); +} + +static struct target_controller gdb_controller = { + .destroy_callback = gdb_target_destroy_callback, + .printf = gdb_target_printf, +}; + void gdb_main(void) { @@ -227,7 +240,7 @@ gdb_main(void) target_reset(cur_target); else if(last_target) { cur_target = target_attach(last_target, - gdb_target_destroy_callback); + &gdb_controller); target_reset(cur_target); } break; @@ -323,7 +336,7 @@ handle_q_packet(char *packet, int len) if((!cur_target) && last_target) { /* Attach to last target if detached. */ cur_target = target_attach(last_target, - gdb_target_destroy_callback); + &gdb_controller); } if (!cur_target) { gdb_putpacketz("E01"); @@ -336,7 +349,7 @@ handle_q_packet(char *packet, int len) if((!cur_target) && last_target) { /* Attach to last target if detached. */ cur_target = target_attach(last_target, - gdb_target_destroy_callback); + &gdb_controller); } if (!cur_target) { gdb_putpacketz("E01"); @@ -365,7 +378,7 @@ handle_v_packet(char *packet, int plen) if (sscanf(packet, "vAttach;%08lx", &addr) == 1) { /* Attach to remote target processor */ - cur_target = target_attach_n(addr, gdb_target_destroy_callback); + cur_target = target_attach_n(addr, &gdb_controller); if(cur_target) gdb_putpacketz("T05"); else @@ -378,7 +391,7 @@ handle_v_packet(char *packet, int plen) gdb_putpacketz("T05"); } else if(last_target) { cur_target = target_attach(last_target, - gdb_target_destroy_callback); + &gdb_controller); /* If we were able to attach to the target again */ if (cur_target) { diff --git a/src/include/target.h b/src/include/target.h index 182f1c6..ac9b844 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -33,20 +33,14 @@ int jtag_scan(const uint8_t *lrlens); bool target_foreach(void (*cb)(int i, target *t, void *context), void *context); void target_list_free(void); -/* The destroy callback function will be called by target_list_free() just - * before the target is free'd. This may be because we're scanning for new - * targets, or because of a communication failure. The target data may - * be assumed to be intact, but the communication medium may not be available, - * so access methods shouldn't be called. - * - * The callback is installed by target_attach() and only removed by attaching - * with a different callback. It remains intact after target_detach(). - */ -typedef void (*target_destroy_callback)(target *t); +struct target_controller { + void (*destroy_callback)(struct target_controller *, target *t); + void (*printf)(struct target_controller *, const char *fmt, va_list); +}; /* Halt/resume functions */ -target *target_attach(target *t, target_destroy_callback destroy_cb); -target *target_attach_n(int n, target_destroy_callback destroy_cb); +target *target_attach(target *t, struct target_controller *); +target *target_attach_n(int n, struct target_controller *); void target_detach(target *t); bool target_check_error(target *t); bool target_attached(target *t); diff --git a/src/target.c b/src/target.c index 9401815..235bbb9 100644 --- a/src/target.c +++ b/src/target.c @@ -22,6 +22,8 @@ #include "target.h" #include "target_internal.h" +#include + target *target_list = NULL; target *target_new(void) @@ -48,8 +50,8 @@ void target_list_free(void) while(target_list) { target *t = target_list->next; - if (target_list->destroy_callback) - target_list->destroy_callback(target_list); + if (target_list->tc) + target_list->tc->destroy_callback(target_list->tc, target_list); if (target_list->priv) target_list->priv_free(target_list->priv); while (target_list->commands) { @@ -90,22 +92,22 @@ void target_add_commands(target *t, const struct command_s *cmds, const char *na tc->next = NULL; } -target *target_attach_n(int n, target_destroy_callback destroy_cb) +target *target_attach_n(int n, struct target_controller *tc) { target *t; int i; for(t = target_list, i = 1; t; t = t->next, i++) if(i == n) - return target_attach(t, destroy_cb); + return target_attach(t, tc); return NULL; } -target *target_attach(target *t, target_destroy_callback destroy_cb) +target *target_attach(target *t, struct target_controller *tc) { - if (t->destroy_callback) - t->destroy_callback(t); + if (t->tc) + t->tc->destroy_callback(t->tc, t); - t->destroy_callback = destroy_cb; + t->tc = tc; if (!t->attach(t)) return NULL; @@ -418,13 +420,12 @@ int target_command(target *t, int argc, const char *argv[]) return -1; } -#include "gdb_packet.h" void tc_printf(target *t, const char *fmt, ...) { (void)t; va_list ap; va_start(ap, fmt); - gdb_voutf(fmt, ap); + t->tc->printf(t->tc, fmt, ap); va_end(ap); } diff --git a/src/target_internal.h b/src/target_internal.h index ea0bfbc..e8f6cc1 100644 --- a/src/target_internal.h +++ b/src/target_internal.h @@ -70,8 +70,7 @@ struct target_command_s { struct target_s { bool attached; - /* Notify controlling debugger if target is lost */ - target_destroy_callback destroy_callback; + struct target_controller *tc; /* Attach/Detach funcitons */ bool (*attach)(target *t); From b64472452075432d08ac214e1b46bbc25dbd23d4 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Fri, 1 Jul 2016 16:50:19 +1200 Subject: [PATCH 14/24] Overhaul of semihosting. Remove dependence of target on gdb_packet. --- src/Makefile | 1 + src/cortexm.c | 133 ++++++++++++++---------------------------- src/gdb_hostio.c | 132 +++++++++++++++++++++++++++++++++++++++++ src/gdb_hostio.h | 53 +++++++++++++++++ src/gdb_main.c | 54 ++++++++--------- src/include/target.h | 48 ++++++++++++++- src/target.c | 69 ++++++++++++++++++++-- src/target_internal.h | 21 ++++++- 8 files changed, 384 insertions(+), 127 deletions(-) create mode 100644 src/gdb_hostio.c create mode 100644 src/gdb_hostio.h diff --git a/src/Makefile b/src/Makefile index 5549277..488c2c5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -31,6 +31,7 @@ SRC = \ exception.c \ gdb_if.c \ gdb_main.c \ + gdb_hostio.c \ gdb_packet.c \ hex_utils.c \ jtag_scan.c \ diff --git a/src/cortexm.c b/src/cortexm.c index 6c783a4..fe05d5d 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -30,14 +30,10 @@ #include "adiv5.h" #include "target.h" #include "target_internal.h" -#include "gdb_packet.h" #include "cortexm.h" #include -/* On some systems this is a macro and causes problems */ -#undef errno - static char cortexm_driver_str[] = "ARM Cortex-M"; static bool cortexm_vector_catch(target *t, int argc, char *argv[]); @@ -78,7 +74,6 @@ static int cortexm_check_hw_wp(target *t, uint32_t *addr); #define CORTEXM_MAX_BREAKPOINTS 6 /* architecture says up to 127, no implementation has > 6 */ static int cortexm_hostio_request(target *t); -static void cortexm_hostio_reply(target *t, int32_t retcode, uint32_t errcode); struct cortexm_priv { ADIv5_AP_t *ap; @@ -97,10 +92,6 @@ struct cortexm_priv { unsigned hw_breakpoint_max; /* Copy of DEMCR for vector-catch */ uint32_t demcr; - /* Semihosting state */ - uint32_t syscall; - uint32_t errno; - uint32_t byte_count; }; /* Register number tables */ @@ -255,8 +246,6 @@ bool cortexm_probe(ADIv5_AP_t *ap) t->halt_resume = cortexm_halt_resume; t->regs_size = sizeof(regnum_cortex_m); - t->hostio_reply = cortexm_hostio_reply; - target_add_commands(t, cortexm_cmd_list, cortexm_driver_str); /* Probe for FP extension */ @@ -531,12 +520,11 @@ static int cortexm_halt_wait(target *t) uint16_t bkpt_instr; bkpt_instr = target_mem_read16(t, pc); if (bkpt_instr == 0xBEAB) { - int n = cortexm_hostio_request(t); - if (n > 0) { + if (cortexm_hostio_request(t)) { + return SIGINT; + } else { target_halt_resume(t, priv->stepping); return 0; - } else if (n < 0) { - return -1; } } } @@ -876,40 +864,30 @@ static bool cortexm_vector_catch(target *t, int argc, char *argv[]) #define SYS_WRITEC 0x03 #define SYS_WRITE0 0x04 -#define FILEIO_O_RDONLY 0 -#define FILEIO_O_WRONLY 1 -#define FILEIO_O_RDWR 2 -#define FILEIO_O_APPEND 0x008 -#define FILEIO_O_CREAT 0x200 -#define FILEIO_O_TRUNC 0x400 - -#define FILEIO_SEEK_SET 0 -#define FILEIO_SEEK_CUR 1 -#define FILEIO_SEEK_END 2 - static int cortexm_hostio_request(target *t) { - struct cortexm_priv *priv = t->priv; uint32_t arm_regs[t->regs_size]; uint32_t params[4]; + t->tc->interrupted = false; target_regs_read(t, arm_regs); target_mem_read(t, params, arm_regs[1], sizeof(params)); - priv->syscall = arm_regs[0]; + uint32_t syscall = arm_regs[0]; + int32_t ret = 0; - DEBUG("syscall 0x%x (%x %x %x %x)\n", priv->syscall, + DEBUG("syscall 0x%x (%x %x %x %x)\n", syscall, params[0], params[1], params[2], params[3]); - switch (priv->syscall) { + switch (syscall) { case SYS_OPEN:{ /* open */ /* Translate stupid fopen modes to open flags. * See DUI0471C, Table 8-3 */ const uint32_t flags[] = { - FILEIO_O_RDONLY, /* r, rb */ - FILEIO_O_RDWR, /* r+, r+b */ - FILEIO_O_WRONLY | FILEIO_O_CREAT | FILEIO_O_TRUNC,/*w*/ - FILEIO_O_RDWR | FILEIO_O_CREAT | FILEIO_O_TRUNC,/*w+*/ - FILEIO_O_WRONLY | FILEIO_O_CREAT | FILEIO_O_APPEND,/*a*/ - FILEIO_O_RDWR | FILEIO_O_CREAT | FILEIO_O_APPEND,/*a+*/ + TARGET_O_RDONLY, /* r, rb */ + TARGET_O_RDWR, /* r+, r+b */ + TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_TRUNC,/*w*/ + TARGET_O_RDWR | TARGET_O_CREAT | TARGET_O_TRUNC,/*w+*/ + TARGET_O_WRONLY | TARGET_O_CREAT | TARGET_O_APPEND,/*a*/ + TARGET_O_RDWR | TARGET_O_CREAT | TARGET_O_APPEND,/*a+*/ }; uint32_t pflag = flags[params[1] >> 1]; char filename[4]; @@ -917,91 +895,70 @@ static int cortexm_hostio_request(target *t) target_mem_read(t, filename, params[0], sizeof(filename)); /* handle requests for console i/o */ if (!strcmp(filename, ":tt")) { - if (pflag == FILEIO_O_RDONLY) - arm_regs[0] = STDIN_FILENO; - else if (pflag & FILEIO_O_TRUNC) - arm_regs[0] = STDOUT_FILENO; + if (pflag == TARGET_O_RDONLY) + ret = STDIN_FILENO; + else if (pflag & TARGET_O_TRUNC) + ret = STDOUT_FILENO; else - arm_regs[0] = STDERR_FILENO; - arm_regs[0]++; - target_regs_write(t, arm_regs); - return 1; + ret = STDERR_FILENO; + ret++; + break; } - gdb_putpacket_f("Fopen,%08X/%X,%08X,%08X", - params[0], params[2] + 1, - pflag, 0644); + ret = tc_open(t, params[0], params[2] + 1, pflag, 0644); + if (ret != -1) + ret++; break; } case SYS_CLOSE: /* close */ - gdb_putpacket_f("Fclose,%08X", params[0] - 1); + ret = tc_close(t, params[0] - 1); break; case SYS_READ: /* read */ - priv->byte_count = params[2]; - gdb_putpacket_f("Fread,%08X,%08X,%08X", - params[0] - 1, params[1], params[2]); + ret = tc_read(t, params[0] - 1, params[1], params[2]); + if (ret > 0) + ret = params[2] - ret; break; case SYS_WRITE: /* write */ - priv->byte_count = params[2]; - gdb_putpacket_f("Fwrite,%08X,%08X,%08X", - params[0] - 1, params[1], params[2]); + ret = tc_write(t, params[0] - 1, params[1], params[2]); + if (ret > 0) + ret = params[2] - ret; break; case SYS_WRITEC: /* writec */ - gdb_putpacket_f("Fwrite,2,%08X,1", arm_regs[1]); + ret = tc_write(t, 2, arm_regs[1], 1); break; case SYS_ISTTY: /* isatty */ - gdb_putpacket_f("Fisatty,%08X", params[0] - 1); + ret = tc_isatty(t, params[0] - 1); break; case SYS_SEEK: /* lseek */ - gdb_putpacket_f("Flseek,%08X,%08X,%08X", - params[0] - 1, params[1], FILEIO_SEEK_SET); + ret = tc_lseek(t, params[0] - 1, params[1], TARGET_SEEK_SET); break; case SYS_RENAME:/* rename */ - gdb_putpacket_f("Frename,%08X/%X,%08X/%X", - params[0] - 1, params[1] + 1, + ret = tc_rename(t, params[0] - 1, params[1] + 1, params[2], params[3] + 1); break; case SYS_REMOVE:/* unlink */ - gdb_putpacket_f("Funlink,%08X/%X", params[0] - 1, - params[1] + 1); + ret = tc_unlink(t, params[0] - 1, params[1] + 1); break; case SYS_SYSTEM:/* system */ - gdb_putpacket_f("Fsystem,%08X/%X", params[0] - 1, - params[1] + 1); + ret = tc_system(t, params[0] - 1, params[1] + 1); break; case SYS_FLEN: /* Not supported, fake success */ - priv->errno = 0; - return 1; + t->tc->errno_ = 0; + break; case SYS_ERRNO: /* Return last errno from GDB */ - arm_regs[0] = priv->errno; - target_regs_write(t, arm_regs); - return 1; + ret = t->tc->errno_; + break; case SYS_TIME: /* gettimeofday */ /* FIXME How do we use gdb's gettimeofday? */ - default: - return 0; + break; } - return -1; -} - -static void cortexm_hostio_reply(target *t, int32_t retcode, uint32_t errcode) -{ - struct cortexm_priv *priv = t->priv; - uint32_t arm_regs[t->regs_size]; - - DEBUG("syscall return ret=%d errno=%d\n", retcode, errcode); - target_regs_read(t, arm_regs); - if (((priv->syscall == SYS_READ) || (priv->syscall == SYS_WRITE)) && - (retcode > 0)) - retcode = priv->byte_count - retcode; - if ((priv->syscall == SYS_OPEN) && (retcode != -1)) - retcode++; - arm_regs[0] = retcode; + arm_regs[0] = ret; target_regs_write(t, arm_regs); - priv->errno = errcode; + + return t->tc->interrupted; } diff --git a/src/gdb_hostio.c b/src/gdb_hostio.c new file mode 100644 index 0000000..20fb8f4 --- /dev/null +++ b/src/gdb_hostio.c @@ -0,0 +1,132 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2016 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * 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 3 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 "general.h" +#include "target.h" +#include "gdb_main.h" +#include "gdb_hostio.h" +#include "gdb_packet.h" + +int gdb_main_loop(struct target_controller *, bool in_syscall); + +int hostio_reply(struct target_controller *tc, char *pbuf, int len) +{ + (void)len; + int retcode, items; + char c, *p; + if (pbuf[1] == '-') + p = &pbuf[2]; + else + p = &pbuf[1]; + items = sscanf(p, "%x,%x,%c", &retcode, &tc->errno_, &c); + if (pbuf[1] == '-') + retcode = -retcode; + + /* if break is requested */ + tc->interrupted = items == 3 && c == 'C'; + + return retcode; +} + +/* Interface to host system calls */ +int hostio_open(struct target_controller *tc, + target_addr path, unsigned path_len, + enum target_open_flags flags, mode_t mode) +{ + gdb_putpacket_f("Fopen,%08X/%X,%08X,%08X", path, path_len, flags, mode);;;; + return gdb_main_loop(tc, true); +} + +int hostio_close(struct target_controller *tc, int fd) +{ + gdb_putpacket_f("Fclose,%08X", fd); + return gdb_main_loop(tc, true); +} + +int hostio_read(struct target_controller *tc, + int fd, target_addr buf, unsigned int count) +{ + gdb_putpacket_f("Fread,%08X,%08X,%08X", fd, buf, count); + return gdb_main_loop(tc, true); +} + +int hostio_write(struct target_controller *tc, + int fd, target_addr buf, unsigned int count) +{ + gdb_putpacket_f("Fwrite,%08X,%08X,%08X", fd, buf, count); + return gdb_main_loop(tc, true); +} + +long hostio_lseek(struct target_controller *tc, + int fd, long offset, enum target_seek_flag flag) +{ + gdb_putpacket_f("Flseek,%08X,%08X,%08X", fd, offset, flag); + return gdb_main_loop(tc, true); +} + +int hostio_rename(struct target_controller *tc, + target_addr oldpath, unsigned old_len, + target_addr newpath, unsigned new_len) +{ + gdb_putpacket_f("Frename,%08X/%X,%08X/%X", + oldpath, old_len, newpath, new_len); + return gdb_main_loop(tc, true); +} + +int hostio_unlink(struct target_controller *tc, + target_addr path, unsigned path_len) +{ + gdb_putpacket_f("Funlink,%08X/%X", path, path_len); + return gdb_main_loop(tc, true); +} + +int hostio_stat(struct target_controller *tc, + target_addr path, unsigned path_len, target_addr buf) +{ + gdb_putpacket_f("Fstat,%08X/%X,%08X", path, path_len, buf); + return gdb_main_loop(tc, true); +} + +int hostio_fstat(struct target_controller *tc, int fd, target_addr buf) +{ + gdb_putpacket_f("Ffstat,%X,%08X", fd, buf); + return gdb_main_loop(tc, true); +} + +int hostio_gettimeofday(struct target_controller *tc, + target_addr tv, target_addr tz) +{ + gdb_putpacket_f("Fgettimeofday,%08X,%08X", tv, tz); + return gdb_main_loop(tc, true); +} + +int hostio_isatty(struct target_controller *tc, int fd) +{ + gdb_putpacket_f("Fisatty,%08X", fd); + return gdb_main_loop(tc, true); +} + +int hostio_system(struct target_controller *tc, + target_addr cmd, unsigned cmd_len) +{ + gdb_putpacket_f("Fsystem,%08X/%X", cmd, cmd_len); + return gdb_main_loop(tc, true); +} + diff --git a/src/gdb_hostio.h b/src/gdb_hostio.h new file mode 100644 index 0000000..eaa97bd --- /dev/null +++ b/src/gdb_hostio.h @@ -0,0 +1,53 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2016 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * 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 3 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 __GDB_SYSCALLS_H +#define __GDB_SYSCALLS_H + +#include "target.h" + +int hostio_reply(struct target_controller *tc, char *packet, int len); + +/* Interface to host system calls */ +int hostio_open(struct target_controller *, + target_addr path, unsigned path_len, + enum target_open_flags flags, mode_t mode); +int hostio_close(struct target_controller *, int fd); +int hostio_read(struct target_controller *, + int fd, target_addr buf, unsigned int count); +int hostio_write(struct target_controller *, + int fd, target_addr buf, unsigned int count); +long hostio_lseek(struct target_controller *, + int fd, long offset, enum target_seek_flag flag); +int hostio_rename(struct target_controller *, + target_addr oldpath, unsigned old_len, + target_addr newpath, unsigned new_len); +int hostio_unlink(struct target_controller *, + target_addr path, unsigned path_len); +int hostio_stat(struct target_controller *, + target_addr path, unsigned path_len, target_addr buf); +int hostio_fstat(struct target_controller *, int fd, target_addr buf); +int hostio_gettimeofday(struct target_controller *, + target_addr tv, target_addr tz); +int hostio_isatty(struct target_controller *, int fd); +int hostio_system(struct target_controller *, + target_addr cmd, unsigned cmd_len); + +#endif + diff --git a/src/gdb_main.c b/src/gdb_main.c index 7833980..f92589a 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -29,6 +29,7 @@ #include "gdb_if.h" #include "gdb_packet.h" #include "gdb_main.h" +#include "gdb_hostio.h" #include "target.h" #include "command.h" #include "crc32.h" @@ -67,14 +68,25 @@ static void gdb_target_printf(struct target_controller *tc, static struct target_controller gdb_controller = { .destroy_callback = gdb_target_destroy_callback, .printf = gdb_target_printf, + + .open = hostio_open, + .close = hostio_close, + .read = hostio_read, + .write = hostio_write, + .lseek = hostio_lseek, + .rename = hostio_rename, + .unlink = hostio_unlink, + .stat = hostio_stat, + .fstat = hostio_fstat, + .gettimeofday = hostio_gettimeofday, + .isatty = hostio_isatty, + .system = hostio_system, }; -void -gdb_main(void) +int gdb_main_loop(struct target_controller *tc, bool in_syscall) { int size; bool single_step = false; - char last_activity = 0; DEBUG("Entring GDB protocol main loop\n"); /* GDB protocol main loop */ @@ -82,7 +94,6 @@ gdb_main(void) SET_IDLE_STATE(1); size = gdb_getpacket(pbuf, BUF_SIZE); SET_IDLE_STATE(0); - continue_activity: switch(pbuf[0]) { /* Implementation of these is mandatory! */ case 'g': { /* 'g': Read general registers */ @@ -154,13 +165,11 @@ gdb_main(void) break; } - last_activity = pbuf[0]; /* Wait for target halt */ while(!(sig = target_halt_wait(cur_target))) { unsigned char c = gdb_if_getchar_to(0); if((c == '\x03') || (c == '\x04')) { target_halt_request(cur_target); - last_activity = 's'; } } SET_RUN_STATE(0); @@ -184,28 +193,14 @@ gdb_main(void) } break; } - case 'F': { /* Semihosting call finished */ - int retcode, errcode, items; - char c, *p; - if (pbuf[1] == '-') - p = &pbuf[2]; - else - p = &pbuf[1]; - items = sscanf(p, "%x,%x,%c", &retcode, &errcode, &c); - if (pbuf[1] == '-') - retcode = -retcode; - - target_hostio_reply(cur_target, retcode, errcode); - - /* if break is requested */ - if (items == 3 && c == 'C') { - gdb_putpacketz("T02"); - break; + case 'F': /* Semihosting call finished */ + if (in_syscall) { + return hostio_reply(tc, pbuf, size); + } else { + DEBUG("*** F packet when not in syscall! '%s'\n", pbuf); + gdb_putpacketz(""); } - - pbuf[0] = last_activity; - goto continue_activity; - } + break; /* Optional GDB packet support */ case '!': /* Enable Extended GDB Protocol. */ @@ -480,3 +475,8 @@ handle_z_packet(char *packet, int plen) gdb_putpacketz("E01"); } +void gdb_main(void) +{ + gdb_main_loop(&gdb_controller, false); +} + diff --git a/src/include/target.h b/src/include/target.h index ac9b844..fc3968b 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -25,7 +25,10 @@ #ifndef __TARGET_H #define __TARGET_H +#include + typedef struct target_s target; +typedef uint32_t target_addr; int adiv5_swdp_scan(void); int jtag_scan(const uint8_t *lrlens); @@ -33,9 +36,51 @@ int jtag_scan(const uint8_t *lrlens); bool target_foreach(void (*cb)(int i, target *t, void *context), void *context); void target_list_free(void); +enum target_open_flags { + TARGET_O_RDONLY = 0, + TARGET_O_WRONLY = 1, + TARGET_O_RDWR = 2, + TARGET_O_APPEND = 0x008, + TARGET_O_CREAT = 0x200, + TARGET_O_TRUNC = 0x400, +}; + +enum target_seek_flag { + TARGET_SEEK_SET = 0, + TARGET_SEEK_CUR = 1, + TARGET_SEEK_END = 2, +}; + struct target_controller { void (*destroy_callback)(struct target_controller *, target *t); void (*printf)(struct target_controller *, const char *fmt, va_list); + + /* Interface to host system calls */ + int (*open)(struct target_controller *, + target_addr path, unsigned path_len, + enum target_open_flags flags, mode_t mode); + int (*close)(struct target_controller *, int fd); + int (*read)(struct target_controller *, + int fd, target_addr buf, unsigned int count); + int (*write)(struct target_controller *, + int fd, target_addr buf, unsigned int count); + long (*lseek)(struct target_controller *, + int fd, long offset, enum target_seek_flag flag); + int (*rename)(struct target_controller *, + target_addr oldpath, unsigned old_len, + target_addr newpath, unsigned new_len); + int (*unlink)(struct target_controller *, + target_addr path, unsigned path_len); + int (*stat)(struct target_controller *, + target_addr path, unsigned path_len, target_addr buf); + int (*fstat)(struct target_controller *, int fd, target_addr buf); + int (*gettimeofday)(struct target_controller *, + target_addr tv, target_addr tz); + int (*isatty)(struct target_controller *, int fd); + int (*system)(struct target_controller *, + target_addr cmd, unsigned cmd_len); + int errno_; + bool interrupted; }; /* Halt/resume functions */ @@ -72,9 +117,6 @@ int target_flash_erase(target *t, uint32_t addr, size_t len); int target_flash_write(target *t, uint32_t dest, const void *src, size_t len); int target_flash_done(target *t); -/* Host I/O */ -void target_hostio_reply(target *t, int32_t retcode, uint32_t errcode); - /* Accessor functions */ int target_regs_size(target *t); const char *target_tdesc(target *t); diff --git a/src/target.c b/src/target.c index 235bbb9..3ae0b96 100644 --- a/src/target.c +++ b/src/target.c @@ -344,12 +344,6 @@ int target_check_hw_wp(target *t, uint32_t *addr) return t->check_hw_wp(t, addr); } -/* Host I/O */ -void target_hostio_reply(target *t, int32_t retcode, uint32_t errcode) -{ - t->hostio_reply(t, retcode, errcode); -} - /* Accessor functions */ int target_regs_size(target *t) { @@ -429,3 +423,66 @@ void tc_printf(target *t, const char *fmt, ...) va_end(ap); } +/* Interface to host system calls */ +int tc_open(target *t, target_addr path, unsigned plen, + enum target_open_flags flags, mode_t mode) +{ + return t->tc->open(t->tc, path, plen, flags, mode); +} + +int tc_close(target *t, int fd) +{ + return t->tc->close(t->tc, fd); +} + +int tc_read(target *t, int fd, target_addr buf, unsigned int count) +{ + return t->tc->read(t->tc, fd, buf, count); +} + +int tc_write(target *t, int fd, target_addr buf, unsigned int count) +{ + return t->tc->write(t->tc, fd, buf, count); +} + +long tc_lseek(target *t, int fd, long offset, enum target_seek_flag flag) +{ + return t->tc->lseek(t->tc, fd, offset, flag); +} + +int tc_rename(target *t, target_addr oldpath, unsigned oldlen, + target_addr newpath, unsigned newlen) +{ + return t->tc->rename(t->tc, oldpath, oldlen, newpath, newlen); +} + +int tc_unlink(target *t, target_addr path, unsigned plen) +{ + return t->tc->unlink(t->tc, path, plen); +} + +int tc_stat(target *t, target_addr path, unsigned plen, target_addr buf) +{ + return t->tc->stat(t->tc, path, plen, buf); +} + +int tc_fstat(target *t, int fd, target_addr buf) +{ + return t->tc->fstat(t->tc, fd, buf); +} + +int tc_gettimeofday(target *t, target_addr tv, target_addr tz) +{ + return t->tc->gettimeofday(t->tc, tv, tz); +} + +int tc_isatty(target *t, int fd) +{ + return t->tc->isatty(t->tc, fd); +} + +int tc_system(target *t, target_addr cmd, unsigned cmdlen) +{ + return t->tc->system(t->tc, cmd, cmdlen); +} + diff --git a/src/target_internal.h b/src/target_internal.h index e8f6cc1..6c7e13d 100644 --- a/src/target_internal.h +++ b/src/target_internal.h @@ -113,9 +113,7 @@ struct target_s { struct target_ram *ram; struct target_flash *flash; - /* Host I/O support */ - void (*hostio_reply)(target *t, int32_t retcode, uint32_t errcode); - + /* Other stuff */ const char *driver; struct target_command_s *commands; @@ -143,6 +141,23 @@ void target_mem_write8(target *t, uint32_t addr, uint8_t value); /* Access to host controller interface */ void tc_printf(target *t, const char *fmt, ...); +/* Interface to host system calls */ +int tc_open(target *, target_addr path, unsigned plen, + enum target_open_flags flags, mode_t mode); +int tc_close(target *t, int fd); +int tc_read(target *t, int fd, target_addr buf, unsigned int count); +int tc_write(target *t, int fd, target_addr buf, unsigned int count); +long tc_lseek(target *t, int fd, long offset, + enum target_seek_flag flag); +int tc_rename(target *t, target_addr oldpath, unsigned oldlen, + target_addr newpath, unsigned newlen); +int tc_unlink(target *t, target_addr path, unsigned plen); +int tc_stat(target *t, target_addr path, unsigned plen, target_addr buf); +int tc_fstat(target *t, int fd, target_addr buf); +int tc_gettimeofday(target *t, target_addr tv, target_addr tz); +int tc_isatty(target *t, int fd); +int tc_system(target *t, target_addr cmd, unsigned cmdlen); + /* Probe for various targets. * Actual functions implemented in their respective drivers. */ From b494279fe56c2d23c796cc55692b02057acee132 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 4 Jul 2016 07:37:25 +1200 Subject: [PATCH 15/24] Move target files into separate directory. --- src/Makefile | 2 +- src/{ => target}/adiv5.c | 0 src/{include => target}/adiv5.h | 0 src/{ => target}/adiv5_jtagdp.c | 0 src/{ => target}/adiv5_swdp.c | 0 src/{ => target}/cortexa.c | 0 src/{ => target}/cortexm.c | 0 src/{include => target}/cortexm.h | 0 src/{ => target}/efm32.c | 0 src/{ => target}/jtag_scan.c | 0 src/{include => target}/jtag_scan.h | 0 src/{ => target}/jtagtap_generic.c | 0 src/{ => target}/kinetis.c | 0 src/{ => target}/lmi.c | 0 src/{ => target}/lpc11xx.c | 0 src/{ => target}/lpc15xx.c | 0 src/{ => target}/lpc43xx.c | 0 src/{ => target}/lpc_common.c | 0 src/{include => target}/lpc_common.h | 0 src/{ => target}/nrf51.c | 0 src/{ => target}/sam3x.c | 0 src/{ => target}/samd.c | 0 src/{ => target}/stm32f1.c | 0 src/{ => target}/stm32f4.c | 0 src/{ => target}/stm32l0.c | 0 src/{ => target}/stm32l4.c | 0 src/{ => target}/swdptap_generic.c | 0 src/{ => target}/target.c | 0 src/{ => target}/target_internal.h | 0 29 files changed, 1 insertion(+), 1 deletion(-) rename src/{ => target}/adiv5.c (100%) rename src/{include => target}/adiv5.h (100%) rename src/{ => target}/adiv5_jtagdp.c (100%) rename src/{ => target}/adiv5_swdp.c (100%) rename src/{ => target}/cortexa.c (100%) rename src/{ => target}/cortexm.c (100%) rename src/{include => target}/cortexm.h (100%) rename src/{ => target}/efm32.c (100%) rename src/{ => target}/jtag_scan.c (100%) rename src/{include => target}/jtag_scan.h (100%) rename src/{ => target}/jtagtap_generic.c (100%) rename src/{ => target}/kinetis.c (100%) rename src/{ => target}/lmi.c (100%) rename src/{ => target}/lpc11xx.c (100%) rename src/{ => target}/lpc15xx.c (100%) rename src/{ => target}/lpc43xx.c (100%) rename src/{ => target}/lpc_common.c (100%) rename src/{include => target}/lpc_common.h (100%) rename src/{ => target}/nrf51.c (100%) rename src/{ => target}/sam3x.c (100%) rename src/{ => target}/samd.c (100%) rename src/{ => target}/stm32f1.c (100%) rename src/{ => target}/stm32f4.c (100%) rename src/{ => target}/stm32l0.c (100%) rename src/{ => target}/stm32l4.c (100%) rename src/{ => target}/swdptap_generic.c (100%) rename src/{ => target}/target.c (100%) rename src/{ => target}/target_internal.h (100%) diff --git a/src/Makefile b/src/Makefile index 488c2c5..abd8693 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ PROBE_HOST ?= native PLATFORM_DIR = platforms/$(PROBE_HOST) -VPATH += $(PLATFORM_DIR) platforms/common +VPATH += $(PLATFORM_DIR) platforms/common target ENABLE_DEBUG ?= ifneq ($(V), 1) diff --git a/src/adiv5.c b/src/target/adiv5.c similarity index 100% rename from src/adiv5.c rename to src/target/adiv5.c diff --git a/src/include/adiv5.h b/src/target/adiv5.h similarity index 100% rename from src/include/adiv5.h rename to src/target/adiv5.h diff --git a/src/adiv5_jtagdp.c b/src/target/adiv5_jtagdp.c similarity index 100% rename from src/adiv5_jtagdp.c rename to src/target/adiv5_jtagdp.c diff --git a/src/adiv5_swdp.c b/src/target/adiv5_swdp.c similarity index 100% rename from src/adiv5_swdp.c rename to src/target/adiv5_swdp.c diff --git a/src/cortexa.c b/src/target/cortexa.c similarity index 100% rename from src/cortexa.c rename to src/target/cortexa.c diff --git a/src/cortexm.c b/src/target/cortexm.c similarity index 100% rename from src/cortexm.c rename to src/target/cortexm.c diff --git a/src/include/cortexm.h b/src/target/cortexm.h similarity index 100% rename from src/include/cortexm.h rename to src/target/cortexm.h diff --git a/src/efm32.c b/src/target/efm32.c similarity index 100% rename from src/efm32.c rename to src/target/efm32.c diff --git a/src/jtag_scan.c b/src/target/jtag_scan.c similarity index 100% rename from src/jtag_scan.c rename to src/target/jtag_scan.c diff --git a/src/include/jtag_scan.h b/src/target/jtag_scan.h similarity index 100% rename from src/include/jtag_scan.h rename to src/target/jtag_scan.h diff --git a/src/jtagtap_generic.c b/src/target/jtagtap_generic.c similarity index 100% rename from src/jtagtap_generic.c rename to src/target/jtagtap_generic.c diff --git a/src/kinetis.c b/src/target/kinetis.c similarity index 100% rename from src/kinetis.c rename to src/target/kinetis.c diff --git a/src/lmi.c b/src/target/lmi.c similarity index 100% rename from src/lmi.c rename to src/target/lmi.c diff --git a/src/lpc11xx.c b/src/target/lpc11xx.c similarity index 100% rename from src/lpc11xx.c rename to src/target/lpc11xx.c diff --git a/src/lpc15xx.c b/src/target/lpc15xx.c similarity index 100% rename from src/lpc15xx.c rename to src/target/lpc15xx.c diff --git a/src/lpc43xx.c b/src/target/lpc43xx.c similarity index 100% rename from src/lpc43xx.c rename to src/target/lpc43xx.c diff --git a/src/lpc_common.c b/src/target/lpc_common.c similarity index 100% rename from src/lpc_common.c rename to src/target/lpc_common.c diff --git a/src/include/lpc_common.h b/src/target/lpc_common.h similarity index 100% rename from src/include/lpc_common.h rename to src/target/lpc_common.h diff --git a/src/nrf51.c b/src/target/nrf51.c similarity index 100% rename from src/nrf51.c rename to src/target/nrf51.c diff --git a/src/sam3x.c b/src/target/sam3x.c similarity index 100% rename from src/sam3x.c rename to src/target/sam3x.c diff --git a/src/samd.c b/src/target/samd.c similarity index 100% rename from src/samd.c rename to src/target/samd.c diff --git a/src/stm32f1.c b/src/target/stm32f1.c similarity index 100% rename from src/stm32f1.c rename to src/target/stm32f1.c diff --git a/src/stm32f4.c b/src/target/stm32f4.c similarity index 100% rename from src/stm32f4.c rename to src/target/stm32f4.c diff --git a/src/stm32l0.c b/src/target/stm32l0.c similarity index 100% rename from src/stm32l0.c rename to src/target/stm32l0.c diff --git a/src/stm32l4.c b/src/target/stm32l4.c similarity index 100% rename from src/stm32l4.c rename to src/target/stm32l4.c diff --git a/src/swdptap_generic.c b/src/target/swdptap_generic.c similarity index 100% rename from src/swdptap_generic.c rename to src/target/swdptap_generic.c diff --git a/src/target.c b/src/target/target.c similarity index 100% rename from src/target.c rename to src/target/target.c diff --git a/src/target_internal.h b/src/target/target_internal.h similarity index 100% rename from src/target_internal.h rename to src/target/target_internal.h From f9bdaf06a4e30f3df5c7a3acab14168528aa4f91 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 4 Jul 2016 08:44:04 +1200 Subject: [PATCH 16/24] Move flash stubs to target directory and update readme. --- flashstub/README | 19 ------------------- src/target/efm32.c | 2 +- {flashstub => src/target/flashstub}/Makefile | 2 +- src/target/flashstub/README.md | 13 +++++++++++++ {flashstub => src/target/flashstub}/efm32.c | 0 .../target/flashstub}/efm32.stub | 0 {flashstub => src/target/flashstub}/lmi.c | 0 {flashstub => src/target/flashstub}/lmi.stub | 0 {flashstub => src/target/flashstub}/nrf51.s | 0 .../target/flashstub}/nrf51.stub | 0 {flashstub => src/target/flashstub}/stm32f1.c | 0 .../target/flashstub}/stm32f1.stub | 0 {flashstub => src/target/flashstub}/stm32f4.c | 0 .../target/flashstub}/stm32f4.stub | 0 {flashstub => src/target/flashstub}/stm32l4.c | 0 .../target/flashstub}/stm32l4.stub | 0 {flashstub => src/target/flashstub}/stub.h | 0 src/target/lmi.c | 2 +- src/target/nrf51.c | 2 +- src/target/stm32f1.c | 2 +- src/target/stm32f4.c | 2 +- src/target/stm32l4.c | 2 +- 22 files changed, 20 insertions(+), 26 deletions(-) delete mode 100644 flashstub/README rename {flashstub => src/target/flashstub}/Makefile (90%) create mode 100644 src/target/flashstub/README.md rename {flashstub => src/target/flashstub}/efm32.c (100%) rename {flashstub => src/target/flashstub}/efm32.stub (100%) rename {flashstub => src/target/flashstub}/lmi.c (100%) rename {flashstub => src/target/flashstub}/lmi.stub (100%) rename {flashstub => src/target/flashstub}/nrf51.s (100%) rename {flashstub => src/target/flashstub}/nrf51.stub (100%) rename {flashstub => src/target/flashstub}/stm32f1.c (100%) rename {flashstub => src/target/flashstub}/stm32f1.stub (100%) rename {flashstub => src/target/flashstub}/stm32f4.c (100%) rename {flashstub => src/target/flashstub}/stm32f4.stub (100%) rename {flashstub => src/target/flashstub}/stm32l4.c (100%) rename {flashstub => src/target/flashstub}/stm32l4.stub (100%) rename {flashstub => src/target/flashstub}/stub.h (100%) diff --git a/flashstub/README b/flashstub/README deleted file mode 100644 index 90d164c..0000000 --- a/flashstub/README +++ /dev/null @@ -1,19 +0,0 @@ -Flash Stubs -=========== - -For most of the targets, these are assembler routines for executing -a flash write on the supported targets. They are kept here for -reference, but are not used, as the compiled binary code is included -in the target drivers. - -For the STM32l0x, the stubs are written in C++ and emitted as arrays -of half-words for inclusion in the target driver. The use of a higher -level language allows more detailed code and for easy revisions. -These stubs communicate with the driver through a structure defined in -the src/include/stm32l0-nvm.h header. - -The dump-to-array.sh helper script uses sed to transform the output of -'objdump -d' into a half-word array of the instructions that may be -included in C code to declare the stub. FWIW, objcopy doesn't produce -the same output as objdump. It omits some of the instructions, -probably because the object file isn't linked. diff --git a/src/target/efm32.c b/src/target/efm32.c index 3725121..7232743 100644 --- a/src/target/efm32.c +++ b/src/target/efm32.c @@ -49,7 +49,7 @@ static int efm32_flash_write(struct target_flash *f, uint32_t dest, const void *src, size_t len); static const uint16_t efm32_flash_write_stub[] = { -#include "../flashstub/efm32.stub" +#include "flashstub/efm32.stub" }; static bool efm32_cmd_erase_all(target *t); diff --git a/flashstub/Makefile b/src/target/flashstub/Makefile similarity index 90% rename from flashstub/Makefile rename to src/target/flashstub/Makefile index a18cd23..3b137a0 100644 --- a/flashstub/Makefile +++ b/src/target/flashstub/Makefile @@ -8,7 +8,7 @@ ifneq ($(V), 1) Q = @ endif -CFLAGS=-Os -std=gnu99 -mcpu=cortex-m0 -mthumb -I../libopencm3/include +CFLAGS=-Os -std=gnu99 -mcpu=cortex-m0 -mthumb -I../../../libopencm3/include ASFLAGS=-mcpu=cortex-m3 -mthumb all: lmi.stub stm32f4.stub stm32l4.stub nrf51.stub stm32f1.stub efm32.stub diff --git a/src/target/flashstub/README.md b/src/target/flashstub/README.md new file mode 100644 index 0000000..df6bb71 --- /dev/null +++ b/src/target/flashstub/README.md @@ -0,0 +1,13 @@ +Flash Stubs +=========== + +These are simple routines for programming the flash on various Cortex-M +microcontrollers. The routines should be provided with the naked attribute +as the stack may not be available, and must not make any function calls. +The stub must call `stub_exit(code)` provided by `stub.h` to return control +to the debugger. Up to 4 word sized parameters may be taken. + +These stubs are compiled instructions comma separated hex values in the +resulting `*.stub` files here, which may be included in the drivers for the +specific device. The drivers call these flash stubs on the target by calling +`cortexm_run_stub` defined in `cortexm.h`. diff --git a/flashstub/efm32.c b/src/target/flashstub/efm32.c similarity index 100% rename from flashstub/efm32.c rename to src/target/flashstub/efm32.c diff --git a/flashstub/efm32.stub b/src/target/flashstub/efm32.stub similarity index 100% rename from flashstub/efm32.stub rename to src/target/flashstub/efm32.stub diff --git a/flashstub/lmi.c b/src/target/flashstub/lmi.c similarity index 100% rename from flashstub/lmi.c rename to src/target/flashstub/lmi.c diff --git a/flashstub/lmi.stub b/src/target/flashstub/lmi.stub similarity index 100% rename from flashstub/lmi.stub rename to src/target/flashstub/lmi.stub diff --git a/flashstub/nrf51.s b/src/target/flashstub/nrf51.s similarity index 100% rename from flashstub/nrf51.s rename to src/target/flashstub/nrf51.s diff --git a/flashstub/nrf51.stub b/src/target/flashstub/nrf51.stub similarity index 100% rename from flashstub/nrf51.stub rename to src/target/flashstub/nrf51.stub diff --git a/flashstub/stm32f1.c b/src/target/flashstub/stm32f1.c similarity index 100% rename from flashstub/stm32f1.c rename to src/target/flashstub/stm32f1.c diff --git a/flashstub/stm32f1.stub b/src/target/flashstub/stm32f1.stub similarity index 100% rename from flashstub/stm32f1.stub rename to src/target/flashstub/stm32f1.stub diff --git a/flashstub/stm32f4.c b/src/target/flashstub/stm32f4.c similarity index 100% rename from flashstub/stm32f4.c rename to src/target/flashstub/stm32f4.c diff --git a/flashstub/stm32f4.stub b/src/target/flashstub/stm32f4.stub similarity index 100% rename from flashstub/stm32f4.stub rename to src/target/flashstub/stm32f4.stub diff --git a/flashstub/stm32l4.c b/src/target/flashstub/stm32l4.c similarity index 100% rename from flashstub/stm32l4.c rename to src/target/flashstub/stm32l4.c diff --git a/flashstub/stm32l4.stub b/src/target/flashstub/stm32l4.stub similarity index 100% rename from flashstub/stm32l4.stub rename to src/target/flashstub/stm32l4.stub diff --git a/flashstub/stub.h b/src/target/flashstub/stub.h similarity index 100% rename from flashstub/stub.h rename to src/target/flashstub/stub.h diff --git a/src/target/lmi.c b/src/target/lmi.c index 5989990..284e510 100644 --- a/src/target/lmi.c +++ b/src/target/lmi.c @@ -54,7 +54,7 @@ static int lmi_flash_write(struct target_flash *f, static const char lmi_driver_str[] = "TI Stellaris/Tiva"; static const uint16_t lmi_flash_write_stub[] = { -#include "../flashstub/lmi.stub" +#include "flashstub/lmi.stub" }; static void lmi_add_flash(target *t, size_t length) diff --git a/src/target/nrf51.c b/src/target/nrf51.c index 7012669..5025da0 100644 --- a/src/target/nrf51.c +++ b/src/target/nrf51.c @@ -85,7 +85,7 @@ const struct command_s nrf51_read_cmd_list[] = { #define STUB_BUFFER_BASE (SRAM_BASE + 0x28) static const uint16_t nrf51_flash_write_stub[] = { -#include "../flashstub/nrf51.stub" +#include "flashstub/nrf51.stub" }; static void nrf51_add_flash(target *t, diff --git a/src/target/stm32f1.c b/src/target/stm32f1.c index 7c92942..eb2606b 100644 --- a/src/target/stm32f1.c +++ b/src/target/stm32f1.c @@ -89,7 +89,7 @@ static int stm32f1_flash_write(struct target_flash *f, #define FLASHSIZE_F0 0x1FFFF7CC static const uint16_t stm32f1_flash_write_stub[] = { -#include "../flashstub/stm32f1.stub" +#include "flashstub/stm32f1.stub" }; #define SRAM_BASE 0x20000000 diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index 2061925..95d42cd 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -104,7 +104,7 @@ static const char stm32f2_driver_str[] = "STM32F2xx"; /* This routine uses word access. Only usable on target voltage >2.7V */ static const uint16_t stm32f4_flash_write_stub[] = { -#include "../flashstub/stm32f4.stub" +#include "flashstub/stm32f4.stub" }; #define SRAM_BASE 0x20000000 diff --git a/src/target/stm32l4.c b/src/target/stm32l4.c index 78e14ac..cd984b1 100644 --- a/src/target/stm32l4.c +++ b/src/target/stm32l4.c @@ -110,7 +110,7 @@ static const char stm32l4_driver_str[] = "STM32L4xx"; /* This routine is uses double word access.*/ static const uint16_t stm32l4_flash_write_stub[] = { -#include "../flashstub/stm32l4.stub" +#include "flashstub/stm32l4.stub" }; #define SRAM_BASE 0x20000000 From aeaca988c3504bf2165b0a5ae1f9b0856c157e91 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 4 Jul 2016 10:31:32 +1200 Subject: [PATCH 17/24] target: Use new target_addr type consistently in external interface. Flash routines still use uint32_t internally. --- src/gdb_main.c | 2 +- src/include/target.h | 18 +++++++++--------- src/target/cortexa.c | 18 +++++++++--------- src/target/cortexm.c | 24 ++++++++++++------------ src/target/target.c | 18 +++++++++--------- src/target/target_internal.h | 14 +++++++------- 6 files changed, 47 insertions(+), 47 deletions(-) diff --git a/src/gdb_main.c b/src/gdb_main.c index f92589a..c92a3e7 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -156,7 +156,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) case '?': { /* '?': Request reason for target halt */ /* This packet isn't documented as being mandatory, * but GDB doesn't work without it. */ - uint32_t watch_addr; + target_addr watch_addr; int sig; if(!cur_target) { diff --git a/src/include/target.h b/src/include/target.h index fc3968b..523f545 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -91,8 +91,8 @@ bool target_check_error(target *t); bool target_attached(target *t); /* Memory access functions */ -void target_mem_read(target *t, void *dest, uint32_t src, size_t len); -void target_mem_write(target *t, uint32_t dest, const void *src, size_t len); +void target_mem_read(target *t, void *dest, target_addr src, size_t len); +void target_mem_write(target *t, target_addr dest, const void *src, size_t len); /* Register access functions */ void target_regs_read(target *t, void *data); @@ -105,16 +105,16 @@ int target_halt_wait(target *t); void target_halt_resume(target *t, bool step); /* Break-/watchpoint functions */ -int target_set_hw_bp(target *t, uint32_t addr, uint8_t len); -int target_clear_hw_bp(target *t, uint32_t addr, uint8_t len); +int target_set_hw_bp(target *t, target_addr addr, uint8_t len); +int target_clear_hw_bp(target *t, target_addr addr, uint8_t len); -int target_set_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len); -int target_clear_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len); -int target_check_hw_wp(target *t, uint32_t *addr); +int target_set_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len); +int target_clear_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len); +int target_check_hw_wp(target *t, target_addr *addr); /* Flash memory access functions */ -int target_flash_erase(target *t, uint32_t addr, size_t len); -int target_flash_write(target *t, uint32_t dest, const void *src, size_t len); +int target_flash_erase(target *t, target_addr addr, size_t len); +int target_flash_write(target *t, target_addr dest, const void *src, size_t len); int target_flash_done(target *t); /* Accessor functions */ diff --git a/src/target/cortexa.c b/src/target/cortexa.c index 24a8c6c..c622197 100644 --- a/src/target/cortexa.c +++ b/src/target/cortexa.c @@ -54,8 +54,8 @@ static void cortexa_reset(target *t); static int cortexa_halt_wait(target *t); static void cortexa_halt_request(target *t); -static int cortexa_set_hw_bp(target *t, uint32_t addr, uint8_t len); -static int cortexa_clear_hw_bp(target *t, uint32_t addr, uint8_t len); +static int cortexa_set_hw_bp(target *t, target_addr addr, uint8_t len); +static int cortexa_clear_hw_bp(target *t, target_addr addr, uint8_t len); static uint32_t bp_bas(uint32_t addr, uint8_t len); static void apb_write(target *t, uint16_t reg, uint32_t val); @@ -221,7 +221,7 @@ static uint32_t va_to_pa(target *t, uint32_t va) return pa; } -static void cortexa_mem_read(target *t, void *dest, uint32_t src, size_t len) +static void cortexa_mem_read(target *t, void *dest, target_addr src, size_t len) { /* Clean cache before reading */ for (uint32_t cl = src & ~(CACHE_LINE_LENGTH-1); @@ -234,7 +234,7 @@ static void cortexa_mem_read(target *t, void *dest, uint32_t src, size_t len) adiv5_mem_read(ahb, dest, va_to_pa(t, src), len); } -static void cortexa_slow_mem_read(target *t, void *dest, uint32_t src, size_t len) +static void cortexa_slow_mem_read(target *t, void *dest, target_addr src, size_t len) { struct cortexa_priv *priv = t->priv; unsigned words = (len + (src & 3) + 3) / 4; @@ -273,7 +273,7 @@ static void cortexa_slow_mem_read(target *t, void *dest, uint32_t src, size_t le } } -static void cortexa_mem_write(target *t, uint32_t dest, const void *src, size_t len) +static void cortexa_mem_write(target *t, target_addr dest, const void *src, size_t len) { /* Clean and invalidate cache before writing */ for (uint32_t cl = dest & ~(CACHE_LINE_LENGTH-1); @@ -285,7 +285,7 @@ static void cortexa_mem_write(target *t, uint32_t dest, const void *src, size_t adiv5_mem_write(ahb, va_to_pa(t, dest), src, len); } -static void cortexa_slow_mem_write_bytes(target *t, uint32_t dest, const uint8_t *src, size_t len) +static void cortexa_slow_mem_write_bytes(target *t, target_addr dest, const uint8_t *src, size_t len) { struct cortexa_priv *priv = t->priv; @@ -304,7 +304,7 @@ static void cortexa_slow_mem_write_bytes(target *t, uint32_t dest, const uint8_t } } -static void cortexa_slow_mem_write(target *t, uint32_t dest, const void *src, size_t len) +static void cortexa_slow_mem_write(target *t, target_addr dest, const void *src, size_t len) { struct cortexa_priv *priv = t->priv; if (len == 0) @@ -677,7 +677,7 @@ static uint32_t bp_bas(uint32_t addr, uint8_t len) return DBGBCR_BAS_LOW_HW; } -static int cortexa_set_hw_bp(target *t, uint32_t addr, uint8_t len) +static int cortexa_set_hw_bp(target *t, target_addr addr, uint8_t len) { struct cortexa_priv *priv = t->priv; unsigned i; @@ -698,7 +698,7 @@ static int cortexa_set_hw_bp(target *t, uint32_t addr, uint8_t len) return 0; } -static int cortexa_clear_hw_bp(target *t, uint32_t addr, uint8_t len) +static int cortexa_clear_hw_bp(target *t, target_addr addr, uint8_t len) { struct cortexa_priv *priv = t->priv; unsigned i; diff --git a/src/target/cortexm.c b/src/target/cortexm.c index fe05d5d..2dd976e 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -62,13 +62,13 @@ static int cortexm_halt_wait(target *t); static void cortexm_halt_request(target *t); static int cortexm_fault_unwind(target *t); -static int cortexm_set_hw_bp(target *t, uint32_t addr, uint8_t len); -static int cortexm_clear_hw_bp(target *t, uint32_t addr, uint8_t len); +static int cortexm_set_hw_bp(target *t, target_addr addr, uint8_t len); +static int cortexm_clear_hw_bp(target *t, target_addr addr, uint8_t len); -static int cortexm_set_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len); -static int cortexm_clear_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len); +static int cortexm_set_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len); +static int cortexm_clear_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len); -static int cortexm_check_hw_wp(target *t, uint32_t *addr); +static int cortexm_check_hw_wp(target *t, target_addr *addr); #define CORTEXM_MAX_WATCHPOINTS 4 /* architecture says up to 15, no implementation has > 4 */ #define CORTEXM_MAX_BREAKPOINTS 6 /* architecture says up to 127, no implementation has > 6 */ @@ -193,12 +193,12 @@ ADIv5_AP_t *cortexm_ap(target *t) return ((struct cortexm_priv *)t->priv)->ap; } -static void cortexm_mem_read(target *t, void *dest, uint32_t src, size_t len) +static void cortexm_mem_read(target *t, void *dest, target_addr src, size_t len) { adiv5_mem_read(cortexm_ap(t), dest, src, len); } -static void cortexm_mem_write(target *t, uint32_t dest, const void *src, size_t len) +static void cortexm_mem_write(target *t, target_addr dest, const void *src, size_t len) { adiv5_mem_write(cortexm_ap(t), dest, src, len); } @@ -656,7 +656,7 @@ int cortexm_run_stub(target *t, uint32_t loadaddr, /* The following routines implement hardware breakpoints. * The Flash Patch and Breakpoint (FPB) system is used. */ -static int cortexm_set_hw_bp(target *t, uint32_t addr, uint8_t len) +static int cortexm_set_hw_bp(target *t, target_addr addr, uint8_t len) { (void)len; struct cortexm_priv *priv = t->priv; @@ -681,7 +681,7 @@ static int cortexm_set_hw_bp(target *t, uint32_t addr, uint8_t len) return 0; } -static int cortexm_clear_hw_bp(target *t, uint32_t addr, uint8_t len) +static int cortexm_clear_hw_bp(target *t, target_addr addr, uint8_t len) { (void)len; struct cortexm_priv *priv = t->priv; @@ -703,7 +703,7 @@ static int cortexm_clear_hw_bp(target *t, uint32_t addr, uint8_t len) * The Data Watch and Trace (DWT) system is used. */ static int -cortexm_set_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len) +cortexm_set_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len) { struct cortexm_priv *priv = t->priv; unsigned i; @@ -744,7 +744,7 @@ cortexm_set_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len) } static int -cortexm_clear_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len) +cortexm_clear_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len) { struct cortexm_priv *priv = t->priv; unsigned i; @@ -779,7 +779,7 @@ cortexm_clear_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len) return 0; } -static int cortexm_check_hw_wp(target *t, uint32_t *addr) +static int cortexm_check_hw_wp(target *t, target_addr *addr) { struct cortexm_priv *priv = t->priv; unsigned i; diff --git a/src/target/target.c b/src/target/target.c index 3ae0b96..4b20aff 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -183,7 +183,7 @@ static struct target_flash *flash_for_addr(target *t, uint32_t addr) return NULL; } -int target_flash_erase(target *t, uint32_t addr, size_t len) +int target_flash_erase(target *t, target_addr addr, size_t len) { int ret = 0; while (len) { @@ -197,7 +197,7 @@ int target_flash_erase(target *t, uint32_t addr, size_t len) } int target_flash_write(target *t, - uint32_t dest, const void *src, size_t len) + target_addr dest, const void *src, size_t len) { int ret = 0; while (len) { @@ -288,12 +288,12 @@ bool target_check_error(target *t) { return t->check_error(t); } bool target_attached(target *t) { return t->attached; } /* Memory access functions */ -void target_mem_read(target *t, void *dest, uint32_t src, size_t len) +void target_mem_read(target *t, void *dest, target_addr src, size_t len) { t->mem_read(t, dest, src, len); } -void target_mem_write(target *t, uint32_t dest, const void *src, size_t len) +void target_mem_write(target *t, target_addr dest, const void *src, size_t len) { t->mem_write(t, dest, src, len); } @@ -309,35 +309,35 @@ int target_halt_wait(target *t) { return t->halt_wait(t); } void target_halt_resume(target *t, bool step) { t->halt_resume(t, step); } /* Break-/watchpoint functions */ -int target_set_hw_bp(target *t, uint32_t addr, uint8_t len) +int target_set_hw_bp(target *t, target_addr addr, uint8_t len) { if (t->set_hw_bp == NULL) return 0; return t->set_hw_bp(t, addr, len); } -int target_clear_hw_bp(target *t, uint32_t addr, uint8_t len) +int target_clear_hw_bp(target *t, target_addr addr, uint8_t len) { if (t->clear_hw_bp == NULL) return 0; return t->clear_hw_bp(t, addr, len); } -int target_set_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len) +int target_set_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len) { if (t->set_hw_wp == NULL) return 0; return t->set_hw_wp(t, type, addr, len); } -int target_clear_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len) +int target_clear_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len) { if (t->clear_hw_wp == NULL) return 0; return t->clear_hw_wp(t, type, addr, len); } -int target_check_hw_wp(target *t, uint32_t *addr) +int target_check_hw_wp(target *t, target_addr *addr) { if (t->check_hw_wp == NULL) return 0; diff --git a/src/target/target_internal.h b/src/target/target_internal.h index 6c7e13d..9e52e7e 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -78,9 +78,9 @@ struct target_s { bool (*check_error)(target *t); /* Memory access functions */ - void (*mem_read)(target *t, void *dest, uint32_t src, + void (*mem_read)(target *t, void *dest, target_addr src, size_t len); - void (*mem_write)(target *t, uint32_t dest, + void (*mem_write)(target *t, target_addr dest, const void *src, size_t len); /* Register access functions */ @@ -96,13 +96,13 @@ struct target_s { void (*halt_resume)(target *t, bool step); /* Break-/watchpoint functions */ - int (*set_hw_bp)(target *t, uint32_t addr, uint8_t len); - int (*clear_hw_bp)(target *t, uint32_t addr, uint8_t len); + int (*set_hw_bp)(target *t, target_addr addr, uint8_t len); + int (*clear_hw_bp)(target *t, target_addr addr, uint8_t len); - int (*set_hw_wp)(target *t, uint8_t type, uint32_t addr, uint8_t len); - int (*clear_hw_wp)(target *t, uint8_t type, uint32_t addr, uint8_t len); + int (*set_hw_wp)(target *t, uint8_t type, target_addr addr, uint8_t len); + int (*clear_hw_wp)(target *t, uint8_t type, target_addr addr, uint8_t len); - int (*check_hw_wp)(target *t, uint32_t *addr); + int (*check_hw_wp)(target *t, target_addr *addr); /* target-defined options */ unsigned target_options; From 82cb6c8e8301dd55b67dd4afe60e8005e3e1ef05 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 4 Jul 2016 10:55:26 +1200 Subject: [PATCH 18/24] target: Use target_addr for flash routines. --- src/target/efm32.c | 10 +++++----- src/target/kinetis.c | 8 ++++---- src/target/lmi.c | 8 ++++---- src/target/lpc43xx.c | 4 ++-- src/target/lpc_common.c | 8 ++++---- src/target/lpc_common.h | 8 ++++---- src/target/nrf51.c | 8 ++++---- src/target/sam3x.c | 12 ++++++------ src/target/samd.c | 8 ++++---- src/target/stm32f1.c | 8 ++++---- src/target/stm32f4.c | 8 ++++---- src/target/stm32l0.c | 16 ++++++++-------- src/target/stm32l4.c | 8 ++++---- src/target/target.c | 10 +++++----- src/target/target_internal.h | 20 ++++++++++---------- 15 files changed, 72 insertions(+), 72 deletions(-) diff --git a/src/target/efm32.c b/src/target/efm32.c index 7232743..c76b17c 100644 --- a/src/target/efm32.c +++ b/src/target/efm32.c @@ -44,9 +44,9 @@ #define SRAM_BASE 0x20000000 #define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(efm32_flash_write_stub), 4) -static int efm32_flash_erase(struct target_flash *t, uint32_t addr, size_t len); +static int efm32_flash_erase(struct target_flash *t, target_addr addr, size_t len); static int efm32_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len); + target_addr dest, const void *src, size_t len); static const uint16_t efm32_flash_write_stub[] = { #include "flashstub/efm32.stub" @@ -230,7 +230,7 @@ uint16_t efm32_read_radio_part_number(target *t) -static void efm32_add_flash(target *t, uint32_t addr, size_t length, +static void efm32_add_flash(target *t, target_addr addr, size_t length, size_t page_size) { struct target_flash *f = calloc(1, sizeof(*f)); @@ -344,7 +344,7 @@ bool efm32_probe(target *t) /** * Erase flash row by row */ -static int efm32_flash_erase(struct target_flash *f, uint32_t addr, size_t len) +static int efm32_flash_erase(struct target_flash *f, target_addr addr, size_t len) { target *t = f->t; @@ -376,7 +376,7 @@ static int efm32_flash_erase(struct target_flash *f, uint32_t addr, size_t len) * Write flash page by page */ static int efm32_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len) + target_addr dest, const void *src, size_t len) { (void)len; target *t = f->t; diff --git a/src/target/kinetis.c b/src/target/kinetis.c index d8cb9f2..f8842a3 100644 --- a/src/target/kinetis.c +++ b/src/target/kinetis.c @@ -61,9 +61,9 @@ #define KL_GEN_PAGESIZE 0x400 -static int kl_gen_flash_erase(struct target_flash *f, uint32_t addr, size_t len); +static int kl_gen_flash_erase(struct target_flash *f, target_addr addr, size_t len); static int kl_gen_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len); + target_addr dest, const void *src, size_t len); static void kl_gen_add_flash(target *t, uint32_t addr, size_t length, size_t erasesize) @@ -159,7 +159,7 @@ kl_gen_command(target *t, uint8_t cmd, uint32_t addr, const uint8_t data[8]) return true; } -static int kl_gen_flash_erase(struct target_flash *f, uint32_t addr, size_t len) +static int kl_gen_flash_erase(struct target_flash *f, target_addr addr, size_t len) { while (len) { if (kl_gen_command(f->t, FTFA_CMD_ERASE_SECTOR, addr, NULL)) { @@ -173,7 +173,7 @@ static int kl_gen_flash_erase(struct target_flash *f, uint32_t addr, size_t len) } static int kl_gen_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len) + target_addr dest, const void *src, size_t len) { while (len) { if (kl_gen_command(f->t, FTFA_CMD_PROGRAM_LONGWORD, dest, src)) { diff --git a/src/target/lmi.c b/src/target/lmi.c index 284e510..e331b39 100644 --- a/src/target/lmi.c +++ b/src/target/lmi.c @@ -47,9 +47,9 @@ #define LMI_FLASH_FMC_COMT (1 << 3) #define LMI_FLASH_FMC_WRKEY 0xA4420000 -static int lmi_flash_erase(struct target_flash *f, uint32_t addr, size_t len); +static int lmi_flash_erase(struct target_flash *f, target_addr addr, size_t len); static int lmi_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len); + target_addr dest, const void *src, size_t len); static const char lmi_driver_str[] = "TI Stellaris/Tiva"; @@ -89,7 +89,7 @@ bool lmi_probe(target *t) return false; } -int lmi_flash_erase(struct target_flash *f, uint32_t addr, size_t len) +int lmi_flash_erase(struct target_flash *f, target_addr addr, size_t len) { target *t = f->t; while(len) { @@ -106,7 +106,7 @@ int lmi_flash_erase(struct target_flash *f, uint32_t addr, size_t len) } int lmi_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len) + target_addr dest, const void *src, size_t len) { target *t = f->t; diff --git a/src/target/lpc43xx.c b/src/target/lpc43xx.c index 1425ccf..f08c4f8 100644 --- a/src/target/lpc43xx.c +++ b/src/target/lpc43xx.c @@ -50,7 +50,7 @@ static bool lpc43xx_cmd_erase(target *t, int argc, const char *argv[]); static bool lpc43xx_cmd_reset(target *t, int argc, const char *argv[]); static bool lpc43xx_cmd_mkboot(target *t, int argc, const char *argv[]); static int lpc43xx_flash_init(target *t); -static int lpc43xx_flash_erase(struct target_flash *f, uint32_t addr, size_t len); +static int lpc43xx_flash_erase(struct target_flash *f, target_addr addr, size_t len); static void lpc43xx_set_internal_clock(target *t); static void lpc43xx_wdt_set_period(target *t); static void lpc43xx_wdt_pet(target *t); @@ -194,7 +194,7 @@ static int lpc43xx_flash_init(target *t) return 0; } -static int lpc43xx_flash_erase(struct target_flash *f, uint32_t addr, size_t len) +static int lpc43xx_flash_erase(struct target_flash *f, target_addr addr, size_t len) { if (lpc43xx_flash_init(f->t)) return -1; diff --git a/src/target/lpc_common.c b/src/target/lpc_common.c index 88ab4a8..3252ea6 100644 --- a/src/target/lpc_common.c +++ b/src/target/lpc_common.c @@ -33,7 +33,7 @@ struct flash_param { } __attribute__((aligned(4))); -struct lpc_flash *lpc_add_flash(target *t, uint32_t addr, size_t length) +struct lpc_flash *lpc_add_flash(target *t, target_addr addr, size_t length) { struct lpc_flash *lf = calloc(1, sizeof(*lf)); struct target_flash *f = &lf->f; @@ -94,7 +94,7 @@ static uint8_t lpc_sector_for_addr(struct lpc_flash *f, uint32_t addr) return f->base_sector + (addr - f->f.start) / f->f.blocksize; } -int lpc_flash_erase(struct target_flash *tf, uint32_t addr, size_t len) +int lpc_flash_erase(struct target_flash *tf, target_addr addr, size_t len) { struct lpc_flash *f = (struct lpc_flash *)tf; uint32_t start = lpc_sector_for_addr(f, addr); @@ -115,7 +115,7 @@ int lpc_flash_erase(struct target_flash *tf, uint32_t addr, size_t len) } int lpc_flash_write(struct target_flash *tf, - uint32_t dest, const void *src, size_t len) + target_addr dest, const void *src, size_t len) { struct lpc_flash *f = (struct lpc_flash *)tf; /* prepare... */ @@ -135,7 +135,7 @@ int lpc_flash_write(struct target_flash *tf, } int lpc_flash_write_magic_vect(struct target_flash *f, - uint32_t dest, const void *src, size_t len) + target_addr dest, const void *src, size_t len) { if (dest == 0) { /* Fill in the magic vector to allow booting the flash */ diff --git a/src/target/lpc_common.h b/src/target/lpc_common.h index 8ca361d..dd7dc88 100644 --- a/src/target/lpc_common.h +++ b/src/target/lpc_common.h @@ -58,13 +58,13 @@ struct lpc_flash { uint32_t iap_msp; }; -struct lpc_flash *lpc_add_flash(target *t, uint32_t addr, size_t length); +struct lpc_flash *lpc_add_flash(target *t, target_addr addr, size_t length); enum iap_status lpc_iap_call(struct lpc_flash *f, enum iap_cmd cmd, ...); -int lpc_flash_erase(struct target_flash *f, uint32_t addr, size_t len); +int lpc_flash_erase(struct target_flash *f, target_addr addr, size_t len); int lpc_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len); + target_addr dest, const void *src, size_t len); int lpc_flash_write_magic_vect(struct target_flash *f, - uint32_t dest, const void *src, size_t len); + target_addr dest, const void *src, size_t len); #endif diff --git a/src/target/nrf51.c b/src/target/nrf51.c index 5025da0..0649c59 100644 --- a/src/target/nrf51.c +++ b/src/target/nrf51.c @@ -26,9 +26,9 @@ #include "target_internal.h" #include "cortexm.h" -static int nrf51_flash_erase(struct target_flash *f, uint32_t addr, size_t len); +static int nrf51_flash_erase(struct target_flash *f, target_addr addr, size_t len); static int nrf51_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len); + target_addr dest, const void *src, size_t len); static bool nrf51_cmd_erase_all(target *t); static bool nrf51_cmd_read_hwid(target *t); @@ -172,7 +172,7 @@ bool nrf51_probe(target *t) return false; } -static int nrf51_flash_erase(struct target_flash *f, uint32_t addr, size_t len) +static int nrf51_flash_erase(struct target_flash *f, target_addr addr, size_t len) { target *t = f->t; /* Enable erase */ @@ -214,7 +214,7 @@ static int nrf51_flash_erase(struct target_flash *f, uint32_t addr, size_t len) } static int nrf51_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len) + target_addr dest, const void *src, size_t len) { target *t = f->t; uint32_t data[2 + len/4]; diff --git a/src/target/sam3x.c b/src/target/sam3x.c index d320c27..0f990d0 100644 --- a/src/target/sam3x.c +++ b/src/target/sam3x.c @@ -28,9 +28,9 @@ #include "target.h" #include "target_internal.h" -static int sam4_flash_erase(struct target_flash *f, uint32_t addr, size_t len); -static int sam3_flash_erase(struct target_flash *f, uint32_t addr, size_t len); -static int sam3x_flash_write(struct target_flash *f, uint32_t dest, +static int sam4_flash_erase(struct target_flash *f, target_addr addr, size_t len); +static int sam3_flash_erase(struct target_flash *f, target_addr addr, size_t len); +static int sam3x_flash_write(struct target_flash *f, target_addr dest, const void *src, size_t len); static bool sam3x_cmd_gpnvm_get(target *t); @@ -281,7 +281,7 @@ static uint32_t sam3x_flash_base(target *t) return SAM3N_EEFC_BASE; } -static int sam4_flash_erase(struct target_flash *f, uint32_t addr, size_t len) +static int sam4_flash_erase(struct target_flash *f, target_addr addr, size_t len) { target *t = f->t; uint32_t base = ((struct sam_flash *)f)->eefc_base; @@ -304,7 +304,7 @@ static int sam4_flash_erase(struct target_flash *f, uint32_t addr, size_t len) return 0; } -static int sam3_flash_erase(struct target_flash *f, uint32_t addr, size_t len) +static int sam3_flash_erase(struct target_flash *f, target_addr addr, size_t len) { /* The SAM3X/SAM3N don't really have a page erase function. * We do nothing here and use Erase/Write page in flash_write. @@ -313,7 +313,7 @@ static int sam3_flash_erase(struct target_flash *f, uint32_t addr, size_t len) return 0; } -static int sam3x_flash_write(struct target_flash *f, uint32_t dest, +static int sam3x_flash_write(struct target_flash *f, target_addr dest, const void *src, size_t len) { target *t = f->t; diff --git a/src/target/samd.c b/src/target/samd.c index 9ad99ce..7861873 100644 --- a/src/target/samd.c +++ b/src/target/samd.c @@ -37,9 +37,9 @@ #include "target_internal.h" #include "cortexm.h" -static int samd_flash_erase(struct target_flash *t, uint32_t addr, size_t len); +static int samd_flash_erase(struct target_flash *t, target_addr addr, size_t len); static int samd_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len); + target_addr dest, const void *src, size_t len); static bool samd_cmd_erase_all(target *t); static bool samd_cmd_lock_flash(target *t); @@ -457,7 +457,7 @@ static void samd_unlock_current_address(target *t) /** * Erase flash row by row */ -static int samd_flash_erase(struct target_flash *f, uint32_t addr, size_t len) +static int samd_flash_erase(struct target_flash *f, target_addr addr, size_t len) { target *t = f->t; while (len) { @@ -490,7 +490,7 @@ static int samd_flash_erase(struct target_flash *f, uint32_t addr, size_t len) * Write flash page by page */ static int samd_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len) + target_addr dest, const void *src, size_t len) { target *t = f->t; diff --git a/src/target/stm32f1.c b/src/target/stm32f1.c index eb2606b..4cc1661 100644 --- a/src/target/stm32f1.c +++ b/src/target/stm32f1.c @@ -45,9 +45,9 @@ const struct command_s stm32f1_cmd_list[] = { static int stm32f1_flash_erase(struct target_flash *f, - uint32_t addr, size_t len); + target_addr addr, size_t len); static int stm32f1_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len); + target_addr dest, const void *src, size_t len); /* Flash Program ad Erase Controller Register Map */ #define FPEC_BASE 0x40022000 @@ -179,7 +179,7 @@ static void stm32f1_flash_unlock(target *t) } static int stm32f1_flash_erase(struct target_flash *f, - uint32_t addr, size_t len) + target_addr addr, size_t len) { target *t = f->t; uint16_t sr; @@ -212,7 +212,7 @@ static int stm32f1_flash_erase(struct target_flash *f, } static int stm32f1_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len) + target_addr dest, const void *src, size_t len) { target *t = f->t; /* Write stub and data to target ram and set PC */ diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index 95d42cd..4749849 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -45,9 +45,9 @@ const struct command_s stm32f4_cmd_list[] = { }; -static int stm32f4_flash_erase(struct target_flash *f, uint32_t addr, size_t len); +static int stm32f4_flash_erase(struct target_flash *f, target_addr addr, size_t len); static int stm32f4_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len); + target_addr dest, const void *src, size_t len); static const char stm32f4_driver_str[] = "STM32F4xx"; static const char stm32f7_driver_str[] = "STM32F7xx"; @@ -219,7 +219,7 @@ static void stm32f4_flash_unlock(target *t) } } -static int stm32f4_flash_erase(struct target_flash *f, uint32_t addr, size_t len) +static int stm32f4_flash_erase(struct target_flash *f, target_addr addr, size_t len) { target *t = f->t; uint16_t sr; @@ -254,7 +254,7 @@ static int stm32f4_flash_erase(struct target_flash *f, uint32_t addr, size_t len } static int stm32f4_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len) + target_addr dest, const void *src, size_t len) { /* Write buffer to target ram call stub */ target_mem_write(f->t, SRAM_BASE, stm32f4_flash_write_stub, diff --git a/src/target/stm32l0.c b/src/target/stm32l0.c index 35fda48..8e81d84 100644 --- a/src/target/stm32l0.c +++ b/src/target/stm32l0.c @@ -142,16 +142,16 @@ #define STM32L1_NVM_OPTR_SPRMOD (1<<8) static int stm32lx_nvm_prog_erase(struct target_flash* f, - uint32_t addr, size_t len); + target_addr addr, size_t len); static int stm32lx_nvm_prog_write(struct target_flash* f, - uint32_t destination, + target_addr destination, const void* src, size_t size); static int stm32lx_nvm_data_erase(struct target_flash* f, - uint32_t addr, size_t len); + target_addr addr, size_t len); static int stm32lx_nvm_data_write(struct target_flash* f, - uint32_t destination, + target_addr destination, const void* source, size_t size); @@ -322,7 +322,7 @@ static bool stm32lx_nvm_opt_unlock(target *t, uint32_t nvm) flash array is erased for all pages from addr to addr+len inclusive. NVM register file address chosen from target. */ static int stm32lx_nvm_prog_erase(struct target_flash* f, - uint32_t addr, size_t len) + target_addr addr, size_t len) { target *t = f->t; const size_t page_size = f->blocksize; @@ -372,7 +372,7 @@ static int stm32lx_nvm_prog_erase(struct target_flash* f, /** Write to program flash using operations through the debug interface. */ static int stm32lx_nvm_prog_write(struct target_flash *f, - uint32_t dest, + target_addr dest, const void* src, size_t size) { @@ -415,7 +415,7 @@ static int stm32lx_nvm_prog_write(struct target_flash *f, addr+len, inclusive, on a word boundary. NVM register file address chosen from target. */ static int stm32lx_nvm_data_erase(struct target_flash *f, - uint32_t addr, size_t len) + target_addr addr, size_t len) { target *t = f->t; const size_t page_size = f->blocksize; @@ -467,7 +467,7 @@ static int stm32lx_nvm_data_erase(struct target_flash *f, destination writes are supported (though unaligned sources are not). */ static int stm32lx_nvm_data_write(struct target_flash *f, - uint32_t destination, + target_addr destination, const void* src, size_t size) { diff --git a/src/target/stm32l4.c b/src/target/stm32l4.c index cd984b1..d65caca 100644 --- a/src/target/stm32l4.c +++ b/src/target/stm32l4.c @@ -49,9 +49,9 @@ const struct command_s stm32l4_cmd_list[] = { }; -static int stm32l4_flash_erase(struct target_flash *f, uint32_t addr, size_t len); +static int stm32l4_flash_erase(struct target_flash *f, target_addr addr, size_t len); static int stm32l4_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len); + target_addr dest, const void *src, size_t len); static const char stm32l4_driver_str[] = "STM32L4xx"; @@ -171,7 +171,7 @@ static void stm32l4_flash_unlock(target *t) } } -static int stm32l4_flash_erase(struct target_flash *f, uint32_t addr, size_t len) +static int stm32l4_flash_erase(struct target_flash *f, target_addr addr, size_t len) { target *t = f->t; uint16_t sr; @@ -212,7 +212,7 @@ static int stm32l4_flash_erase(struct target_flash *f, uint32_t addr, size_t len } static int stm32l4_flash_write(struct target_flash *f, - uint32_t dest, const void *src, size_t len) + target_addr dest, const void *src, size_t len) { /* Write buffer to target ram call stub */ target_mem_write(f->t, SRAM_BASE, stm32l4_flash_write_stub, diff --git a/src/target/target.c b/src/target/target.c index 4b20aff..e0aa5dd 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -116,7 +116,7 @@ target *target_attach(target *t, struct target_controller *tc) return t; } -void target_add_ram(target *t, uint32_t start, uint32_t len) +void target_add_ram(target *t, target_addr start, uint32_t len) { struct target_ram *ram = malloc(sizeof(*ram)); ram->start = start; @@ -135,7 +135,7 @@ void target_add_flash(target *t, struct target_flash *f) static ssize_t map_ram(char *buf, size_t len, struct target_ram *ram) { return snprintf(buf, len, "", + "\" length=\"0x%08zx\"/>", ram->start, ram->length); } @@ -143,9 +143,9 @@ static ssize_t map_flash(char *buf, size_t len, struct target_flash *f) { int i = 0; i += snprintf(&buf[i], len - i, "", + "\" length=\"0x%08zx\">", f->start, f->length); - i += snprintf(&buf[i], len - i, "0x%08"PRIx32 + i += snprintf(&buf[i], len - i, "0x%08zx" "", f->blocksize); return i; @@ -231,7 +231,7 @@ int target_flash_done(target *t) } int target_flash_write_buffered(struct target_flash *f, - uint32_t dest, const void *src, size_t len) + target_addr dest, const void *src, size_t len) { int ret = 0; diff --git a/src/target/target_internal.h b/src/target/target_internal.h index 9e52e7e..6042a46 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -25,20 +25,20 @@ extern target *target_list; target *target_new(void); struct target_ram { - uint32_t start; - uint32_t length; + target_addr start; + size_t length; struct target_ram *next; }; struct target_flash; -typedef int (*flash_erase_func)(struct target_flash *f, uint32_t addr, size_t len); -typedef int (*flash_write_func)(struct target_flash *f, uint32_t dest, +typedef int (*flash_erase_func)(struct target_flash *f, target_addr addr, size_t len); +typedef int (*flash_write_func)(struct target_flash *f, target_addr dest, const void *src, size_t len); typedef int (*flash_done_func)(struct target_flash *f); struct target_flash { - uint32_t start; - uint32_t length; - uint32_t blocksize; + target_addr start; + size_t length; + size_t blocksize; flash_erase_func erase; flash_write_func write; flash_done_func done; @@ -50,7 +50,7 @@ struct target_flash { /* For buffered flash */ size_t buf_size; flash_write_func write_buf; - uint32_t buf_addr; + target_addr buf_addr; void *buf; }; @@ -124,10 +124,10 @@ struct target_s { }; void target_add_commands(target *t, const struct command_s *cmds, const char *name); -void target_add_ram(target *t, uint32_t start, uint32_t len); +void target_add_ram(target *t, target_addr start, uint32_t len); void target_add_flash(target *t, struct target_flash *f); int target_flash_write_buffered(struct target_flash *f, - uint32_t dest, const void *src, size_t len); + target_addr dest, const void *src, size_t len); int target_flash_done_buffered(struct target_flash *f); /* Convenience function for MMIO access */ From 26fab877da73d0ccb087806ce20bc2289ced4886 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 4 Jul 2016 13:23:05 +1200 Subject: [PATCH 19/24] target: Provide errno definitions and fallback for unimplemented syscalls. --- src/include/target.h | 24 +++++++++++++++++++++++- src/target/target.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/src/include/target.h b/src/include/target.h index 523f545..8ca7e74 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -36,6 +36,28 @@ int jtag_scan(const uint8_t *lrlens); bool target_foreach(void (*cb)(int i, target *t, void *context), void *context); void target_list_free(void); +enum target_errno { + TARGET_EPERM = 1, + TARGET_ENOENT = 2, + TARGET_EINTR = 4, + TARGET_EBADF = 9, + TARGET_EACCES = 13, + TARGET_EFAULT = 14, + TARGET_EBUSY = 16, + TARGET_EEXIST = 17, + TARGET_ENODEV = 19, + TARGET_ENOTDIR = 20, + TARGET_EISDIR = 21, + TARGET_EINVAL = 22, + TARGET_EMFILE = 24, + TARGET_ENFILE = 23, + TARGET_EFBIG = 27, + TARGET_ENOSPC = 28, + TARGET_ESPIPE = 29, + TARGET_EROFS = 30, + TARGET_ENAMETOOLONG = 36, +}; + enum target_open_flags { TARGET_O_RDONLY = 0, TARGET_O_WRONLY = 1, @@ -79,7 +101,7 @@ struct target_controller { int (*isatty)(struct target_controller *, int fd); int (*system)(struct target_controller *, target_addr cmd, unsigned cmd_len); - int errno_; + enum target_errno errno_; bool interrupted; }; diff --git a/src/target/target.c b/src/target/target.c index e0aa5dd..70224a1 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -427,62 +427,100 @@ void tc_printf(target *t, const char *fmt, ...) int tc_open(target *t, target_addr path, unsigned plen, enum target_open_flags flags, mode_t mode) { + if (t->tc->open == NULL) { + t->tc->errno_ = TARGET_ENFILE; + return -1; + } return t->tc->open(t->tc, path, plen, flags, mode); } int tc_close(target *t, int fd) { + if (t->tc->close == NULL) { + t->tc->errno_ = TARGET_EBADF; + return -1; + } return t->tc->close(t->tc, fd); } int tc_read(target *t, int fd, target_addr buf, unsigned int count) { + if (t->tc->read == NULL) + return 0; return t->tc->read(t->tc, fd, buf, count); } int tc_write(target *t, int fd, target_addr buf, unsigned int count) { + if (t->tc->write == NULL) + return 0; return t->tc->write(t->tc, fd, buf, count); } long tc_lseek(target *t, int fd, long offset, enum target_seek_flag flag) { + if (t->tc->lseek == NULL) + return 0; return t->tc->lseek(t->tc, fd, offset, flag); } int tc_rename(target *t, target_addr oldpath, unsigned oldlen, target_addr newpath, unsigned newlen) { + if (t->tc->rename == NULL) { + t->tc->errno_ = TARGET_ENOENT; + return -1; + } return t->tc->rename(t->tc, oldpath, oldlen, newpath, newlen); } int tc_unlink(target *t, target_addr path, unsigned plen) { + if (t->tc->unlink == NULL) { + t->tc->errno_ = TARGET_ENOENT; + return -1; + } return t->tc->unlink(t->tc, path, plen); } int tc_stat(target *t, target_addr path, unsigned plen, target_addr buf) { + if (t->tc->stat == NULL) { + t->tc->errno_ = TARGET_ENOENT; + return -1; + } return t->tc->stat(t->tc, path, plen, buf); } int tc_fstat(target *t, int fd, target_addr buf) { + if (t->tc->fstat == NULL) { + return 0; + } return t->tc->fstat(t->tc, fd, buf); } int tc_gettimeofday(target *t, target_addr tv, target_addr tz) { + if (t->tc->gettimeofday == NULL) { + return -1; + } return t->tc->gettimeofday(t->tc, tv, tz); } int tc_isatty(target *t, int fd) { + if (t->tc->isatty == NULL) { + return 1; + } return t->tc->isatty(t->tc, fd); } int tc_system(target *t, target_addr cmd, unsigned cmdlen) { + if (t->tc->system == NULL) { + return -1; + } return t->tc->system(t->tc, cmd, cmdlen); } From ab06243e938733297d4f7a282d793a73ac31d4be Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 4 Jul 2016 13:36:43 +1200 Subject: [PATCH 20/24] target: Use size_t instead of unsigned in syscall interface. --- src/gdb_hostio.c | 17 +++++++++-------- src/gdb_hostio.h | 12 ++++++------ src/include/target.h | 12 ++++++------ src/target/target.c | 12 ++++++------ src/target/target_internal.h | 12 ++++++------ 5 files changed, 33 insertions(+), 32 deletions(-) diff --git a/src/gdb_hostio.c b/src/gdb_hostio.c index 20fb8f4..82ff0a6 100644 --- a/src/gdb_hostio.c +++ b/src/gdb_hostio.c @@ -29,25 +29,26 @@ int gdb_main_loop(struct target_controller *, bool in_syscall); int hostio_reply(struct target_controller *tc, char *pbuf, int len) { (void)len; - int retcode, items; + int retcode, items, errno_; char c, *p; if (pbuf[1] == '-') p = &pbuf[2]; else p = &pbuf[1]; - items = sscanf(p, "%x,%x,%c", &retcode, &tc->errno_, &c); + items = sscanf(p, "%x,%x,%c", &retcode, &errno_, &c); if (pbuf[1] == '-') retcode = -retcode; /* if break is requested */ tc->interrupted = items == 3 && c == 'C'; + tc->errno_ = errno_; return retcode; } /* Interface to host system calls */ int hostio_open(struct target_controller *tc, - target_addr path, unsigned path_len, + target_addr path, size_t path_len, enum target_open_flags flags, mode_t mode) { gdb_putpacket_f("Fopen,%08X/%X,%08X,%08X", path, path_len, flags, mode);;;; @@ -82,8 +83,8 @@ long hostio_lseek(struct target_controller *tc, } int hostio_rename(struct target_controller *tc, - target_addr oldpath, unsigned old_len, - target_addr newpath, unsigned new_len) + target_addr oldpath, size_t old_len, + target_addr newpath, size_t new_len) { gdb_putpacket_f("Frename,%08X/%X,%08X/%X", oldpath, old_len, newpath, new_len); @@ -91,14 +92,14 @@ int hostio_rename(struct target_controller *tc, } int hostio_unlink(struct target_controller *tc, - target_addr path, unsigned path_len) + target_addr path, size_t path_len) { gdb_putpacket_f("Funlink,%08X/%X", path, path_len); return gdb_main_loop(tc, true); } int hostio_stat(struct target_controller *tc, - target_addr path, unsigned path_len, target_addr buf) + target_addr path, size_t path_len, target_addr buf) { gdb_putpacket_f("Fstat,%08X/%X,%08X", path, path_len, buf); return gdb_main_loop(tc, true); @@ -124,7 +125,7 @@ int hostio_isatty(struct target_controller *tc, int fd) } int hostio_system(struct target_controller *tc, - target_addr cmd, unsigned cmd_len) + target_addr cmd, size_t cmd_len) { gdb_putpacket_f("Fsystem,%08X/%X", cmd, cmd_len); return gdb_main_loop(tc, true); diff --git a/src/gdb_hostio.h b/src/gdb_hostio.h index eaa97bd..f95f707 100644 --- a/src/gdb_hostio.h +++ b/src/gdb_hostio.h @@ -26,7 +26,7 @@ int hostio_reply(struct target_controller *tc, char *packet, int len); /* Interface to host system calls */ int hostio_open(struct target_controller *, - target_addr path, unsigned path_len, + target_addr path, size_t path_len, enum target_open_flags flags, mode_t mode); int hostio_close(struct target_controller *, int fd); int hostio_read(struct target_controller *, @@ -36,18 +36,18 @@ int hostio_write(struct target_controller *, long hostio_lseek(struct target_controller *, int fd, long offset, enum target_seek_flag flag); int hostio_rename(struct target_controller *, - target_addr oldpath, unsigned old_len, - target_addr newpath, unsigned new_len); + target_addr oldpath, size_t old_len, + target_addr newpath, size_t new_len); int hostio_unlink(struct target_controller *, - target_addr path, unsigned path_len); + target_addr path, size_t path_len); int hostio_stat(struct target_controller *, - target_addr path, unsigned path_len, target_addr buf); + target_addr path, size_t path_len, target_addr buf); int hostio_fstat(struct target_controller *, int fd, target_addr buf); int hostio_gettimeofday(struct target_controller *, target_addr tv, target_addr tz); int hostio_isatty(struct target_controller *, int fd); int hostio_system(struct target_controller *, - target_addr cmd, unsigned cmd_len); + target_addr cmd, size_t cmd_len); #endif diff --git a/src/include/target.h b/src/include/target.h index 8ca7e74..86c7d98 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -79,7 +79,7 @@ struct target_controller { /* Interface to host system calls */ int (*open)(struct target_controller *, - target_addr path, unsigned path_len, + target_addr path, size_t path_len, enum target_open_flags flags, mode_t mode); int (*close)(struct target_controller *, int fd); int (*read)(struct target_controller *, @@ -89,18 +89,18 @@ struct target_controller { long (*lseek)(struct target_controller *, int fd, long offset, enum target_seek_flag flag); int (*rename)(struct target_controller *, - target_addr oldpath, unsigned old_len, - target_addr newpath, unsigned new_len); + target_addr oldpath, size_t old_len, + target_addr newpath, size_t new_len); int (*unlink)(struct target_controller *, - target_addr path, unsigned path_len); + target_addr path, size_t path_len); int (*stat)(struct target_controller *, - target_addr path, unsigned path_len, target_addr buf); + target_addr path, size_t path_len, target_addr buf); int (*fstat)(struct target_controller *, int fd, target_addr buf); int (*gettimeofday)(struct target_controller *, target_addr tv, target_addr tz); int (*isatty)(struct target_controller *, int fd); int (*system)(struct target_controller *, - target_addr cmd, unsigned cmd_len); + target_addr cmd, size_t cmd_len); enum target_errno errno_; bool interrupted; }; diff --git a/src/target/target.c b/src/target/target.c index 70224a1..750b17a 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -424,7 +424,7 @@ void tc_printf(target *t, const char *fmt, ...) } /* Interface to host system calls */ -int tc_open(target *t, target_addr path, unsigned plen, +int tc_open(target *t, target_addr path, size_t plen, enum target_open_flags flags, mode_t mode) { if (t->tc->open == NULL) { @@ -464,8 +464,8 @@ long tc_lseek(target *t, int fd, long offset, enum target_seek_flag flag) return t->tc->lseek(t->tc, fd, offset, flag); } -int tc_rename(target *t, target_addr oldpath, unsigned oldlen, - target_addr newpath, unsigned newlen) +int tc_rename(target *t, target_addr oldpath, size_t oldlen, + target_addr newpath, size_t newlen) { if (t->tc->rename == NULL) { t->tc->errno_ = TARGET_ENOENT; @@ -474,7 +474,7 @@ int tc_rename(target *t, target_addr oldpath, unsigned oldlen, return t->tc->rename(t->tc, oldpath, oldlen, newpath, newlen); } -int tc_unlink(target *t, target_addr path, unsigned plen) +int tc_unlink(target *t, target_addr path, size_t plen) { if (t->tc->unlink == NULL) { t->tc->errno_ = TARGET_ENOENT; @@ -483,7 +483,7 @@ int tc_unlink(target *t, target_addr path, unsigned plen) return t->tc->unlink(t->tc, path, plen); } -int tc_stat(target *t, target_addr path, unsigned plen, target_addr buf) +int tc_stat(target *t, target_addr path, size_t plen, target_addr buf) { if (t->tc->stat == NULL) { t->tc->errno_ = TARGET_ENOENT; @@ -516,7 +516,7 @@ int tc_isatty(target *t, int fd) return t->tc->isatty(t->tc, fd); } -int tc_system(target *t, target_addr cmd, unsigned cmdlen) +int tc_system(target *t, target_addr cmd, size_t cmdlen) { if (t->tc->system == NULL) { return -1; diff --git a/src/target/target_internal.h b/src/target/target_internal.h index 6042a46..9f55ea5 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -142,21 +142,21 @@ void target_mem_write8(target *t, uint32_t addr, uint8_t value); void tc_printf(target *t, const char *fmt, ...); /* Interface to host system calls */ -int tc_open(target *, target_addr path, unsigned plen, +int tc_open(target *, target_addr path, size_t plen, enum target_open_flags flags, mode_t mode); int tc_close(target *t, int fd); int tc_read(target *t, int fd, target_addr buf, unsigned int count); int tc_write(target *t, int fd, target_addr buf, unsigned int count); long tc_lseek(target *t, int fd, long offset, enum target_seek_flag flag); -int tc_rename(target *t, target_addr oldpath, unsigned oldlen, - target_addr newpath, unsigned newlen); -int tc_unlink(target *t, target_addr path, unsigned plen); -int tc_stat(target *t, target_addr path, unsigned plen, target_addr buf); +int tc_rename(target *t, target_addr oldpath, size_t oldlen, + target_addr newpath, size_t newlen); +int tc_unlink(target *t, target_addr path, size_t plen); +int tc_stat(target *t, target_addr path, size_t plen, target_addr buf); int tc_fstat(target *t, int fd, target_addr buf); int tc_gettimeofday(target *t, target_addr tv, target_addr tz); int tc_isatty(target *t, int fd); -int tc_system(target *t, target_addr cmd, unsigned cmdlen); +int tc_system(target *t, target_addr cmd, size_t cmdlen); /* Probe for various targets. * Actual functions implemented in their respective drivers. From 9136cf4c985c9785dc9dd4308c2502bfb8b858fb Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 7 Jul 2016 08:01:53 +1200 Subject: [PATCH 21/24] target: target_halt_wait and target_check_hw_wp replaced with target_halt_poll. The new function returns a stop reason which must be translated in gdb server. In the case of a watchpoint hit, the address is returned by a pointer parameter. Simplify the extenal interface for set/clear breaki-/watchpoints. --- src/gdb_main.c | 75 ++++++++++++++++-------------------- src/include/target.h | 29 ++++++++++---- src/target/cortexa.c | 30 +++++++-------- src/target/cortexm.c | 48 +++++++++++------------ src/target/lpc_common.c | 2 +- src/target/target.c | 67 +++++++++++++++++--------------- src/target/target_internal.h | 6 +-- 7 files changed, 129 insertions(+), 128 deletions(-) diff --git a/src/gdb_main.c b/src/gdb_main.c index c92a3e7..e52768e 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -34,6 +34,13 @@ #include "command.h" #include "crc32.h" +enum gdb_signal { + GDB_SIGINT = 2, + GDB_SIGTRAP = 5, + GDB_SIGSEGV = 11, + GDB_SIGLOST = 29, +}; + #define BUF_SIZE 1024 #define ERROR_IF_NO_TARGET() \ @@ -156,8 +163,8 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) case '?': { /* '?': Request reason for target halt */ /* This packet isn't documented as being mandatory, * but GDB doesn't work without it. */ - target_addr watch_addr; - int sig; + target_addr watch; + enum target_halt_reason reason; if(!cur_target) { /* Report "target exited" if no target */ @@ -166,7 +173,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) } /* Wait for target halt */ - while(!(sig = target_halt_wait(cur_target))) { + while(!(reason = target_halt_poll(cur_target, &watch))) { unsigned char c = gdb_if_getchar_to(0); if((c == '\x03') || (c == '\x04')) { target_halt_request(cur_target); @@ -174,22 +181,22 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) } SET_RUN_STATE(0); - /* Negative signal indicates we're in a syscall */ - if (sig < 0) + /* Translate reason to GDB signal */ + switch (reason) { + case TARGET_HALT_ERROR: + gdb_putpacket_f("X%02X", GDB_SIGLOST); break; - - /* Target disappeared */ - if (cur_target == NULL) { - gdb_putpacket_f("X%02X", sig); + case TARGET_HALT_REQUEST: + gdb_putpacket_f("T%02X", GDB_SIGINT); break; - } - - /* Report reason for halt */ - if(target_check_hw_wp(cur_target, &watch_addr)) { - /* Watchpoint hit */ - gdb_putpacket_f("T%02Xwatch:%08X;", sig, watch_addr); - } else { - gdb_putpacket_f("T%02X", sig); + case TARGET_HALT_WATCHPOINT: + gdb_putpacket_f("T%02Xwatch:%08X;", GDB_SIGTRAP, watch); + break; + case TARGET_HALT_FAULT: + gdb_putpacket_f("T%02X", GDB_SIGSEGV); + break; + default: + gdb_putpacket_f("T%02X", GDB_SIGTRAP); } break; } @@ -447,32 +454,18 @@ handle_z_packet(char *packet, int plen) //sscanf(packet, "%*[zZ]%hhd,%08lX,%hhd", &type, &addr, &len); type = packet[1] - '0'; sscanf(packet + 2, ",%" PRIx32 ",%d", &addr, &len); - switch(type) { - case 1: /* Hardware breakpoint */ - if(set) - ret = target_set_hw_bp(cur_target, addr, len); - else - ret = target_clear_hw_bp(cur_target, addr, len); - break; - - case 2: - case 3: - case 4: - if(set) - ret = target_set_hw_wp(cur_target, type, addr, len); - else - ret = target_clear_hw_wp(cur_target, type, addr, len); - break; - - default: - gdb_putpacketz(""); - return; - } - - if(!ret) - gdb_putpacketz("OK"); + if(set) + ret = target_breakwatch_set(cur_target, type, addr, len); else + ret = target_breakwatch_clear(cur_target, type, addr, len); + + if (ret < 0) { gdb_putpacketz("E01"); + } else if (ret > 0) { + gdb_putpacketz(""); + } else { + gdb_putpacketz("OK"); + } } void gdb_main(void) diff --git a/src/include/target.h b/src/include/target.h index 86c7d98..1b1d70b 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -121,18 +121,31 @@ void target_regs_read(target *t, void *data); void target_regs_write(target *t, const void *data); /* Halt/resume functions */ +enum target_halt_reason { + TARGET_HALT_RUNNING = 0, /* Target not halted */ + TARGET_HALT_ERROR, /* Failed to read target status */ + TARGET_HALT_REQUEST, + TARGET_HALT_STEPPING, + TARGET_HALT_BREAKPOINT, + TARGET_HALT_WATCHPOINT, + TARGET_HALT_FAULT, +}; + void target_reset(target *t); void target_halt_request(target *t); -int target_halt_wait(target *t); +enum target_halt_reason target_halt_poll(target *t, target_addr *watch); void target_halt_resume(target *t, bool step); /* Break-/watchpoint functions */ -int target_set_hw_bp(target *t, target_addr addr, uint8_t len); -int target_clear_hw_bp(target *t, target_addr addr, uint8_t len); - -int target_set_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len); -int target_clear_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len); -int target_check_hw_wp(target *t, target_addr *addr); +enum target_breakwatch { + TARGET_BREAK_SOFT, + TARGET_BREAK_HARD, + TARGET_WATCH_WRITE, + TARGET_WATCH_READ, + TARGET_WATCH_ACCESS, +}; +int target_breakwatch_set(target *t, enum target_breakwatch, target_addr, size_t); +int target_breakwatch_clear(target *t, enum target_breakwatch, target_addr, size_t); /* Flash memory access functions */ int target_flash_erase(target *t, target_addr addr, size_t len); @@ -140,7 +153,7 @@ int target_flash_write(target *t, target_addr dest, const void *src, size_t len) int target_flash_done(target *t); /* Accessor functions */ -int target_regs_size(target *t); +size_t target_regs_size(target *t); const char *target_tdesc(target *t); const char *target_mem_map(target *t); const char *target_driver_name(target *t); diff --git a/src/target/cortexa.c b/src/target/cortexa.c index c622197..a1af318 100644 --- a/src/target/cortexa.c +++ b/src/target/cortexa.c @@ -35,12 +35,6 @@ static char cortexa_driver_str[] = "ARM Cortex-A"; -/* Signals returned by cortexa_halt_wait() */ -#define SIGINT 2 -#define SIGTRAP 5 -#define SIGSEGV 11 -#define SIGLOST 29 - static bool cortexa_attach(target *t); static void cortexa_detach(target *t); static void cortexa_halt_resume(target *t, bool step); @@ -51,7 +45,7 @@ static void cortexa_regs_read_internal(target *t); static void cortexa_regs_write_internal(target *t); static void cortexa_reset(target *t); -static int cortexa_halt_wait(target *t); +static enum target_halt_reason cortexa_halt_poll(target *t, target_addr *watch); static void cortexa_halt_request(target *t); static int cortexa_set_hw_bp(target *t, target_addr addr, uint8_t len); @@ -395,7 +389,7 @@ bool cortexa_probe(ADIv5_AP_t *apb, uint32_t debug_base) t->reset = cortexa_reset; t->halt_request = cortexa_halt_request; - t->halt_wait = cortexa_halt_wait; + t->halt_poll = cortexa_halt_poll; t->halt_resume = cortexa_halt_resume; t->regs_size = sizeof(priv->reg_cache); @@ -422,7 +416,7 @@ bool cortexa_attach(target *t) target_halt_request(t); tries = 10; - while(!platform_srst_get_val() && !target_halt_wait(t) && --tries) + while(!platform_srst_get_val() && !target_halt_poll(t, NULL) && --tries) platform_delay(200); if(!tries) return false; @@ -586,8 +580,10 @@ static void cortexa_halt_request(target *t) } } -static int cortexa_halt_wait(target *t) +static enum target_halt_reason cortexa_halt_poll(target *t, target_addr *watch) { + (void)watch; /* No watchpoint support yet */ + volatile uint32_t dbgdscr = 0; volatile struct exception e; TRY_CATCH (e, EXCEPTION_ALL) { @@ -599,14 +595,14 @@ static int cortexa_halt_wait(target *t) case EXCEPTION_ERROR: /* Oh crap, there's no recovery from this... */ target_list_free(); - return SIGLOST; + return TARGET_HALT_ERROR; case EXCEPTION_TIMEOUT: /* Timeout isn't a problem, target could be in WFI */ - return 0; + return TARGET_HALT_RUNNING; } if (!(dbgdscr & DBGDSCR_HALTED)) /* Not halted */ - return 0; + return TARGET_HALT_RUNNING; DEBUG("%s: DBGDSCR = 0x%08x\n", __func__, dbgdscr); /* Reenable DBGITR */ @@ -614,18 +610,18 @@ static int cortexa_halt_wait(target *t) apb_write(t, DBGDSCR, dbgdscr); /* Find out why we halted */ - int sig; + enum target_halt_reason reason; switch (dbgdscr & DBGDSCR_MOE_MASK) { case DBGDSCR_MOE_HALT_REQ: - sig = SIGINT; + reason = TARGET_HALT_REQUEST; break; default: - sig = SIGTRAP; + reason = TARGET_HALT_BREAKPOINT; } cortexa_regs_read_internal(t); - return sig; + return reason; } void cortexa_halt_resume(target *t, bool step) diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 2dd976e..b0add80 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -47,18 +47,12 @@ const struct command_s cortexm_cmd_list[] = { #define TOPT_FLAVOUR_V6M (1<<0) /* if not set, target is assumed to be v7m */ #define TOPT_FLAVOUR_V7MF (1<<1) /* if set, floating-point enabled. */ -/* Signals returned by cortexm_halt_wait() */ -#define SIGINT 2 -#define SIGTRAP 5 -#define SIGSEGV 11 -#define SIGLOST 29 - static void cortexm_regs_read(target *t, void *data); static void cortexm_regs_write(target *t, const void *data); static uint32_t cortexm_pc_read(target *t); static void cortexm_reset(target *t); -static int cortexm_halt_wait(target *t); +static enum target_halt_reason cortexm_halt_poll(target *t, target_addr *watch); static void cortexm_halt_request(target *t); static int cortexm_fault_unwind(target *t); @@ -68,7 +62,7 @@ static int cortexm_clear_hw_bp(target *t, target_addr addr, uint8_t len); static int cortexm_set_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len); static int cortexm_clear_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len); -static int cortexm_check_hw_wp(target *t, target_addr *addr); +static target_addr cortexm_check_watch(target *t); #define CORTEXM_MAX_WATCHPOINTS 4 /* architecture says up to 15, no implementation has > 4 */ #define CORTEXM_MAX_BREAKPOINTS 6 /* architecture says up to 127, no implementation has > 6 */ @@ -242,7 +236,7 @@ bool cortexm_probe(ADIv5_AP_t *ap) t->reset = cortexm_reset; t->halt_request = cortexm_halt_request; - t->halt_wait = cortexm_halt_wait; + t->halt_poll = cortexm_halt_poll; t->halt_resume = cortexm_halt_resume; t->regs_size = sizeof(regnum_cortex_m); @@ -295,7 +289,7 @@ bool cortexm_attach(target *t) target_halt_request(t); tries = 10; - while(!platform_srst_get_val() && !target_halt_wait(t) && --tries) + while(!platform_srst_get_val() && !target_halt_poll(t, NULL) && --tries) platform_delay(200); if(!tries) return false; @@ -338,7 +332,6 @@ bool cortexm_attach(target *t) /* Data Watchpoint and Trace */ t->set_hw_wp = cortexm_set_hw_wp; t->clear_hw_wp = cortexm_clear_hw_wp; - t->check_hw_wp = cortexm_check_hw_wp; platform_srst_set_val(false); @@ -480,7 +473,7 @@ static void cortexm_halt_request(target *t) } } -static int cortexm_halt_wait(target *t) +static enum target_halt_reason cortexm_halt_poll(target *t, target_addr *watch) { struct cortexm_priv *priv = t->priv; @@ -495,21 +488,21 @@ static int cortexm_halt_wait(target *t) case EXCEPTION_ERROR: /* Oh crap, there's no recovery from this... */ target_list_free(); - return SIGLOST; + return TARGET_HALT_ERROR; case EXCEPTION_TIMEOUT: /* Timeout isn't a problem, target could be in WFI */ - return 0; + return TARGET_HALT_RUNNING; } if (!(dhcsr & CORTEXM_DHCSR_S_HALT)) - return 0; + return TARGET_HALT_RUNNING; /* We've halted. Let's find out why. */ uint32_t dfsr = target_mem_read32(t, CORTEXM_DFSR); target_mem_write32(t, CORTEXM_DFSR, dfsr); /* write back to reset */ if ((dfsr & CORTEXM_DFSR_VCATCH) && cortexm_fault_unwind(t)) - return SIGSEGV; + return TARGET_HALT_FAULT; /* Remember if we stopped on a breakpoint */ priv->on_bkpt = dfsr & (CORTEXM_DFSR_BKPT); @@ -521,7 +514,7 @@ static int cortexm_halt_wait(target *t) bkpt_instr = target_mem_read16(t, pc); if (bkpt_instr == 0xBEAB) { if (cortexm_hostio_request(t)) { - return SIGINT; + return TARGET_HALT_REQUEST; } else { target_halt_resume(t, priv->stepping); return 0; @@ -529,14 +522,18 @@ static int cortexm_halt_wait(target *t) } } - if (dfsr & (CORTEXM_DFSR_BKPT | CORTEXM_DFSR_DWTTRAP)) - return SIGTRAP; + if (dfsr & CORTEXM_DFSR_DWTTRAP) { + if (watch != NULL) + *watch = cortexm_check_watch(t); + return TARGET_HALT_WATCHPOINT; + } + if (dfsr & CORTEXM_DFSR_BKPT) + return TARGET_HALT_BREAKPOINT; if (dfsr & CORTEXM_DFSR_HALTED) - return priv->stepping ? SIGTRAP : SIGINT; - - return SIGTRAP; + return priv->stepping ? TARGET_HALT_STEPPING : TARGET_HALT_REQUEST; + return TARGET_HALT_BREAKPOINT; } void cortexm_halt_resume(target *t, bool step) @@ -642,7 +639,7 @@ int cortexm_run_stub(target *t, uint32_t loadaddr, /* Execute the stub */ cortexm_halt_resume(t, 0); - while (!cortexm_halt_wait(t)) + while (!cortexm_halt_poll(t, NULL)) ; uint32_t pc = cortexm_pc_read(t); @@ -779,7 +776,7 @@ cortexm_clear_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len) return 0; } -static int cortexm_check_hw_wp(target *t, target_addr *addr) +static target_addr cortexm_check_watch(target *t) { struct cortexm_priv *priv = t->priv; unsigned i; @@ -793,8 +790,7 @@ static int cortexm_check_hw_wp(target *t, target_addr *addr) if(i == priv->hw_watchpoint_max) return 0; - *addr = priv->hw_watchpoint[i].addr; - return 1; + return priv->hw_watchpoint[i].addr; } static bool cortexm_vector_catch(target *t, int argc, char *argv[]) diff --git a/src/target/lpc_common.c b/src/target/lpc_common.c index 3252ea6..63d844e 100644 --- a/src/target/lpc_common.c +++ b/src/target/lpc_common.c @@ -82,7 +82,7 @@ enum iap_status lpc_iap_call(struct lpc_flash *f, enum iap_cmd cmd, ...) /* start the target and wait for it to halt again */ target_halt_resume(t, false); - while (!target_halt_wait(t)); + while (!target_halt_poll(t, NULL)); /* copy back just the parameters structure */ target_mem_read(t, ¶m, f->iap_ram, sizeof(param)); diff --git a/src/target/target.c b/src/target/target.c index 750b17a..7f8e828 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -305,47 +305,52 @@ void target_regs_write(target *t, const void *data) { t->regs_write(t, data); } /* Halt/resume functions */ void target_reset(target *t) { t->reset(t); } void target_halt_request(target *t) { t->halt_request(t); } -int target_halt_wait(target *t) { return t->halt_wait(t); } +enum target_halt_reason target_halt_poll(target *t, target_addr *watch) +{ + return t->halt_poll(t, watch); +} + void target_halt_resume(target *t, bool step) { t->halt_resume(t, step); } /* Break-/watchpoint functions */ -int target_set_hw_bp(target *t, target_addr addr, uint8_t len) +int target_breakwatch_set(target *t, + enum target_breakwatch type, target_addr addr, size_t len) { - if (t->set_hw_bp == NULL) - return 0; - return t->set_hw_bp(t, addr, len); + switch (type) { + case TARGET_BREAK_HARD: + if (t->set_hw_bp) + return t->set_hw_bp(t, addr, len); + case TARGET_WATCH_WRITE: + case TARGET_WATCH_READ: + case TARGET_WATCH_ACCESS: + if (t->set_hw_wp) + return t->set_hw_wp(t, type, addr, len); + default: + break; + } + return 1; } -int target_clear_hw_bp(target *t, target_addr addr, uint8_t len) +int target_breakwatch_clear(target *t, + enum target_breakwatch type, target_addr addr, size_t len) { - if (t->clear_hw_bp == NULL) - return 0; - return t->clear_hw_bp(t, addr, len); -} - -int target_set_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len) -{ - if (t->set_hw_wp == NULL) - return 0; - return t->set_hw_wp(t, type, addr, len); -} - -int target_clear_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len) -{ - if (t->clear_hw_wp == NULL) - return 0; - return t->clear_hw_wp(t, type, addr, len); -} - -int target_check_hw_wp(target *t, target_addr *addr) -{ - if (t->check_hw_wp == NULL) - return 0; - return t->check_hw_wp(t, addr); + switch (type) { + case TARGET_BREAK_HARD: + if (t->set_hw_bp) + return t->set_hw_bp(t, addr, len); + case TARGET_WATCH_WRITE: + case TARGET_WATCH_READ: + case TARGET_WATCH_ACCESS: + if (t->set_hw_wp) + return t->set_hw_wp(t, type, addr, len); + default: + break; + } + return 1; } /* Accessor functions */ -int target_regs_size(target *t) +size_t target_regs_size(target *t) { return t->regs_size; } diff --git a/src/target/target_internal.h b/src/target/target_internal.h index 9f55ea5..13a131a 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -84,7 +84,7 @@ struct target_s { const void *src, size_t len); /* Register access functions */ - int regs_size; + size_t regs_size; const char *tdesc; void (*regs_read)(target *t, void *data); void (*regs_write)(target *t, const void *data); @@ -92,7 +92,7 @@ struct target_s { /* Halt/resume functions */ void (*reset)(target *t); void (*halt_request)(target *t); - int (*halt_wait)(target *t); + enum target_halt_reason (*halt_poll)(target *t, target_addr *watch); void (*halt_resume)(target *t, bool step); /* Break-/watchpoint functions */ @@ -102,8 +102,6 @@ struct target_s { int (*set_hw_wp)(target *t, uint8_t type, target_addr addr, uint8_t len); int (*clear_hw_wp)(target *t, uint8_t type, target_addr addr, uint8_t len); - int (*check_hw_wp)(target *t, target_addr *addr); - /* target-defined options */ unsigned target_options; uint32_t idcode; From 9aacc18f6033c742ac042dab17a02c04f5b5bd4b Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 7 Jul 2016 11:49:47 +1200 Subject: [PATCH 22/24] target: Restructure internal break/watch handling. cortexa: Implement soft breakpoints. --- src/target/cortexa.c | 98 ++++++++++------ src/target/cortexm.c | 216 +++++++++++++++-------------------- src/target/target.c | 69 +++++++---- src/target/target_internal.h | 16 ++- 4 files changed, 213 insertions(+), 186 deletions(-) diff --git a/src/target/cortexa.c b/src/target/cortexa.c index a1af318..a9c8593 100644 --- a/src/target/cortexa.c +++ b/src/target/cortexa.c @@ -48,8 +48,8 @@ static void cortexa_reset(target *t); static enum target_halt_reason cortexa_halt_poll(target *t, target_addr *watch); static void cortexa_halt_request(target *t); -static int cortexa_set_hw_bp(target *t, target_addr addr, uint8_t len); -static int cortexa_clear_hw_bp(target *t, target_addr addr, uint8_t len); +static int cortexa_breakwatch_set(target *t, struct breakwatch *); +static int cortexa_breakwatch_clear(target *t, struct breakwatch *); static uint32_t bp_bas(uint32_t addr, uint8_t len); static void apb_write(target *t, uint16_t reg, uint32_t val); @@ -68,7 +68,7 @@ struct cortexa_priv { uint64_t d[16]; } reg_cache; unsigned hw_breakpoint_max; - unsigned hw_breakpoint[16]; + bool hw_breakpoint[16]; uint32_t bpc0; bool mmu_fault; }; @@ -393,8 +393,8 @@ bool cortexa_probe(ADIv5_AP_t *apb, uint32_t debug_base) t->halt_resume = cortexa_halt_resume; t->regs_size = sizeof(priv->reg_cache); - t->set_hw_bp = cortexa_set_hw_bp; - t->clear_hw_bp = cortexa_clear_hw_bp; + t->breakwatch_set = cortexa_breakwatch_set; + t->breakwatch_clear = cortexa_breakwatch_clear; return true; } @@ -673,45 +673,75 @@ static uint32_t bp_bas(uint32_t addr, uint8_t len) return DBGBCR_BAS_LOW_HW; } -static int cortexa_set_hw_bp(target *t, target_addr addr, uint8_t len) +static int cortexa_breakwatch_set(target *t, struct breakwatch *bw) { struct cortexa_priv *priv = t->priv; unsigned i; - for(i = 0; i < priv->hw_breakpoint_max; i++) - if((priv->hw_breakpoint[i] & 1) == 0) break; + switch (bw->type) { + case TARGET_BREAK_SOFT: + switch (bw->size) { + case 2: + bw->reserved[0] = target_mem_read16(t, bw->addr); + target_mem_write16(t, bw->addr, 0xBE00); + return 0; + case 4: + bw->reserved[0] = target_mem_read32(t, bw->addr); + target_mem_write32(t, bw->addr, 0xE1200070); + return 0; + default: + return -1; + } + case TARGET_BREAK_HARD: + if ((bw->size != 4) && (bw->size != 2)) + return -1; - if(i == priv->hw_breakpoint_max) return -1; + for (i = 0; i < priv->hw_breakpoint_max; i++) + if ((priv->hw_breakpoint[i] & 1) == 0) + break; - priv->hw_breakpoint[i] = addr | 1; + if (i == priv->hw_breakpoint_max) + return -1; - apb_write(t, DBGBVR(i), addr & ~3); - uint32_t bpc = bp_bas(addr, len) | DBGBCR_EN; - apb_write(t, DBGBCR(i), bpc); - if (i == 0) - priv->bpc0 = bpc; + bw->reserved[0] = i; - return 0; + priv->hw_breakpoint[i] = true; + + apb_write(t, DBGBVR(i), bw->addr & ~3); + uint32_t bpc = bp_bas(bw->addr, bw->size) | DBGBCR_EN; + apb_write(t, DBGBCR(i), bpc); + if (i == 0) + priv->bpc0 = bpc; + + return 0; + default: + return 1; + } } -static int cortexa_clear_hw_bp(target *t, target_addr addr, uint8_t len) +static int cortexa_breakwatch_clear(target *t, struct breakwatch *bw) { struct cortexa_priv *priv = t->priv; - unsigned i; - - (void)len; - - for (i = 0; i < priv->hw_breakpoint_max; i++) - if ((priv->hw_breakpoint[i] & ~1) == addr) - break; - if (i == priv->hw_breakpoint_max) - return -1; - - priv->hw_breakpoint[i] = 0; - - apb_write(t, DBGBCR(i), 0); - if (i == 0) - priv->bpc0 = 0; - - return 0; + unsigned i = bw->reserved[0]; + switch (bw->type) { + case TARGET_BREAK_SOFT: + switch (bw->size) { + case 2: + target_mem_write16(t, bw->addr, i); + return 0; + case 4: + target_mem_write32(t, bw->addr, i); + return 0; + default: + return -1; + } + case TARGET_BREAK_HARD: + priv->hw_breakpoint[i] = false; + apb_write(t, DBGBCR(i), 0); + if (i == 0) + priv->bpc0 = 0; + return 0; + default: + return 1; + } } diff --git a/src/target/cortexm.c b/src/target/cortexm.c index b0add80..d768fde 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -56,12 +56,8 @@ static enum target_halt_reason cortexm_halt_poll(target *t, target_addr *watch); static void cortexm_halt_request(target *t); static int cortexm_fault_unwind(target *t); -static int cortexm_set_hw_bp(target *t, target_addr addr, uint8_t len); -static int cortexm_clear_hw_bp(target *t, target_addr addr, uint8_t len); - -static int cortexm_set_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len); -static int cortexm_clear_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len); - +static int cortexm_breakwatch_set(target *t, struct breakwatch *); +static int cortexm_breakwatch_clear(target *t, struct breakwatch *); static target_addr cortexm_check_watch(target *t); #define CORTEXM_MAX_WATCHPOINTS 4 /* architecture says up to 15, no implementation has > 4 */ @@ -74,15 +70,11 @@ struct cortexm_priv { bool stepping; bool on_bkpt; /* Watchpoint unit status */ - struct wp_unit_s { - uint32_t addr; - uint8_t type; - uint8_t size; - } hw_watchpoint[CORTEXM_MAX_WATCHPOINTS]; + bool hw_watchpoint[CORTEXM_MAX_WATCHPOINTS]; unsigned flash_patch_revision; unsigned hw_watchpoint_max; /* Breakpoint unit status */ - uint32_t hw_breakpoint[CORTEXM_MAX_BREAKPOINTS]; + bool hw_breakpoint[CORTEXM_MAX_BREAKPOINTS]; unsigned hw_breakpoint_max; /* Copy of DEMCR for vector-catch */ uint32_t demcr; @@ -240,6 +232,9 @@ bool cortexm_probe(ADIv5_AP_t *ap) t->halt_resume = cortexm_halt_resume; t->regs_size = sizeof(regnum_cortex_m); + t->breakwatch_set = cortexm_breakwatch_set; + t->breakwatch_clear = cortexm_breakwatch_clear; + target_add_commands(t, cortexm_cmd_list, cortexm_driver_str); /* Probe for FP extension */ @@ -320,18 +315,12 @@ bool cortexm_attach(target *t) /* Clear any stale watchpoints */ for(i = 0; i < priv->hw_watchpoint_max; i++) { target_mem_write32(t, CORTEXM_DWT_FUNC(i), 0); - priv->hw_watchpoint[i].type = 0; + priv->hw_watchpoint[i] = 0; } /* Flash Patch Control Register: set ENABLE */ target_mem_write32(t, CORTEXM_FPB_CTRL, CORTEXM_FPB_CTRL_KEY | CORTEXM_FPB_CTRL_ENABLE); - t->set_hw_bp = cortexm_set_hw_bp; - t->clear_hw_bp = cortexm_clear_hw_bp; - - /* Data Watchpoint and Trace */ - t->set_hw_wp = cortexm_set_hw_wp; - t->clear_hw_wp = cortexm_clear_hw_wp; platform_srst_set_val(false); @@ -650,130 +639,110 @@ int cortexm_run_stub(target *t, uint32_t loadaddr, return bkpt_instr & 0xff; } -/* The following routines implement hardware breakpoints. - * The Flash Patch and Breakpoint (FPB) system is used. */ +/* The following routines implement hardware breakpoints and watchpoints. + * The Flash Patch and Breakpoint (FPB) and Data Watch and Trace (DWT) + * systems are used. */ -static int cortexm_set_hw_bp(target *t, target_addr addr, uint8_t len) +static uint32_t dwt_mask(size_t len) { - (void)len; - struct cortexm_priv *priv = t->priv; - uint32_t val = addr; - unsigned i; - - if (priv->flash_patch_revision == 0) { - val = addr & 0x1FFFFFFC; - val |= (addr & 2)?0x80000000:0x40000000; + switch (len) { + case 1: + return CORTEXM_DWT_MASK_BYTE; + case 2: + return CORTEXM_DWT_MASK_HALFWORD; + case 4: + return CORTEXM_DWT_MASK_WORD; + default: + return -1; } - val |= 1; - - for(i = 0; i < priv->hw_breakpoint_max; i++) - if((priv->hw_breakpoint[i] & 1) == 0) break; - - if(i == priv->hw_breakpoint_max) return -1; - - priv->hw_breakpoint[i] = addr | 1; - - target_mem_write32(t, CORTEXM_FPB_COMP(i), val); - - return 0; } -static int cortexm_clear_hw_bp(target *t, target_addr addr, uint8_t len) +static uint32_t dwt_func(target *t, enum target_breakwatch type) { - (void)len; - struct cortexm_priv *priv = t->priv; - unsigned i; + uint32_t x = 0; - for(i = 0; i < priv->hw_breakpoint_max; i++) - if((priv->hw_breakpoint[i] & ~1) == addr) break; + if ((t->target_options & TOPT_FLAVOUR_V6M) == 0) + x = CORTEXM_DWT_FUNC_DATAVSIZE_WORD; - if(i == priv->hw_breakpoint_max) return -1; - - priv->hw_breakpoint[i] = 0; - - target_mem_write32(t, CORTEXM_FPB_COMP(i), 0); - - return 0; + switch (type) { + case TARGET_WATCH_WRITE: + return CORTEXM_DWT_FUNC_FUNC_WRITE | x; + case TARGET_WATCH_READ: + return CORTEXM_DWT_FUNC_FUNC_READ | x; + case TARGET_WATCH_ACCESS: + return CORTEXM_DWT_FUNC_FUNC_ACCESS | x; + default: + return -1; + } } -/* The following routines implement hardware watchpoints. - * The Data Watch and Trace (DWT) system is used. */ - -static int -cortexm_set_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len) +static int cortexm_breakwatch_set(target *t, struct breakwatch *bw) { struct cortexm_priv *priv = t->priv; unsigned i; + uint32_t val = bw->addr; - switch(len) { /* Convert bytes size to mask size */ - case 1: len = CORTEXM_DWT_MASK_BYTE; break; - case 2: len = CORTEXM_DWT_MASK_HALFWORD; break; - case 4: len = CORTEXM_DWT_MASK_WORD; break; - default: + switch (bw->type) { + case TARGET_BREAK_HARD: + if (priv->flash_patch_revision == 0) { + val &= 0x1FFFFFFC; + val |= (bw->addr & 2)?0x80000000:0x40000000; + } + val |= 1; + + for(i = 0; i < priv->hw_breakpoint_max; i++) + if (!priv->hw_breakpoint[i]) + break; + + if (i == priv->hw_breakpoint_max) return -1; - } - switch(type) { /* Convert gdb type to function type */ - case 2: type = CORTEXM_DWT_FUNC_FUNC_WRITE; break; - case 3: type = CORTEXM_DWT_FUNC_FUNC_READ; break; - case 4: type = CORTEXM_DWT_FUNC_FUNC_ACCESS; break; - default: + priv->hw_breakpoint[i] = true; + target_mem_write32(t, CORTEXM_FPB_COMP(i), val); + bw->reserved[0] = i; + return 0; + + case TARGET_WATCH_WRITE: + case TARGET_WATCH_READ: + case TARGET_WATCH_ACCESS: + for(i = 0; i < priv->hw_watchpoint_max; i++) + if (!priv->hw_watchpoint[i]) + break; + + if (i == priv->hw_watchpoint_max) return -1; + + priv->hw_watchpoint[i] = true; + + target_mem_write32(t, CORTEXM_DWT_COMP(i), val); + target_mem_write32(t, CORTEXM_DWT_MASK(i), dwt_mask(bw->size)); + target_mem_write32(t, CORTEXM_DWT_FUNC(i), dwt_func(t, bw->type)); + + bw->reserved[0] = i; + return 0; + default: + return 1; } - - for(i = 0; i < priv->hw_watchpoint_max; i++) - if((priv->hw_watchpoint[i].type == 0) && - ((target_mem_read32(t, CORTEXM_DWT_FUNC(i)) & 0xF) == 0)) - break; - - if(i == priv->hw_watchpoint_max) return -2; - - priv->hw_watchpoint[i].type = type; - priv->hw_watchpoint[i].addr = addr; - priv->hw_watchpoint[i].size = len; - - target_mem_write32(t, CORTEXM_DWT_COMP(i), addr); - target_mem_write32(t, CORTEXM_DWT_MASK(i), len); - target_mem_write32(t, CORTEXM_DWT_FUNC(i), type | - ((t->target_options & TOPT_FLAVOUR_V6M) ? 0: CORTEXM_DWT_FUNC_DATAVSIZE_WORD)); - - return 0; } -static int -cortexm_clear_hw_wp(target *t, uint8_t type, target_addr addr, uint8_t len) +static int cortexm_breakwatch_clear(target *t, struct breakwatch *bw) { struct cortexm_priv *priv = t->priv; - unsigned i; - - switch(len) { - case 1: len = CORTEXM_DWT_MASK_BYTE; break; - case 2: len = CORTEXM_DWT_MASK_HALFWORD; break; - case 4: len = CORTEXM_DWT_MASK_WORD; break; - default: - return -1; + unsigned i = bw->reserved[0]; + switch (bw->type) { + case TARGET_BREAK_HARD: + priv->hw_breakpoint[i] = false; + target_mem_write32(t, CORTEXM_FPB_COMP(i), 0); + return 0; + case TARGET_WATCH_WRITE: + case TARGET_WATCH_READ: + case TARGET_WATCH_ACCESS: + priv->hw_watchpoint[i] = false; + target_mem_write32(t, CORTEXM_DWT_FUNC(i), 0); + return 0; + default: + return 1; } - - switch(type) { - case 2: type = CORTEXM_DWT_FUNC_FUNC_WRITE; break; - case 3: type = CORTEXM_DWT_FUNC_FUNC_READ; break; - case 4: type = CORTEXM_DWT_FUNC_FUNC_ACCESS; break; - default: - return -1; - } - - for(i = 0; i < priv->hw_watchpoint_max; i++) - if((priv->hw_watchpoint[i].addr == addr) && - (priv->hw_watchpoint[i].type == type) && - (priv->hw_watchpoint[i].size == len)) break; - - if(i == priv->hw_watchpoint_max) return -2; - - priv->hw_watchpoint[i].type = 0; - - target_mem_write32(t, CORTEXM_DWT_FUNC(i), 0); - - return 0; } static target_addr cortexm_check_watch(target *t) @@ -783,14 +752,15 @@ static target_addr cortexm_check_watch(target *t) for(i = 0; i < priv->hw_watchpoint_max; i++) /* if SET and MATCHED then break */ - if(priv->hw_watchpoint[i].type && + if(priv->hw_watchpoint[i] && (target_mem_read32(t, CORTEXM_DWT_FUNC(i)) & CORTEXM_DWT_FUNC_MATCHED)) break; - if(i == priv->hw_watchpoint_max) return 0; + if (i == priv->hw_watchpoint_max) + return 0; - return priv->hw_watchpoint[i].addr; + return target_mem_read32(t, CORTEXM_DWT_COMP(i)); } static bool cortexm_vector_catch(target *t, int argc, char *argv[]) diff --git a/src/target/target.c b/src/target/target.c index 7f8e828..94aaa1e 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -73,6 +73,11 @@ void target_list_free(void) free(target_list->flash); target_list->flash = next; } + while (target_list->bw_list) { + void * next = target_list->bw_list->next; + free(target_list->bw_list); + target_list->bw_list = next; + } free(target_list); target_list = t; } @@ -316,37 +321,53 @@ void target_halt_resume(target *t, bool step) { t->halt_resume(t, step); } int target_breakwatch_set(target *t, enum target_breakwatch type, target_addr addr, size_t len) { - switch (type) { - case TARGET_BREAK_HARD: - if (t->set_hw_bp) - return t->set_hw_bp(t, addr, len); - case TARGET_WATCH_WRITE: - case TARGET_WATCH_READ: - case TARGET_WATCH_ACCESS: - if (t->set_hw_wp) - return t->set_hw_wp(t, type, addr, len); - default: - break; + struct breakwatch bw = { + .type = type, + .addr = addr, + .size = len, + }; + int ret = 1; + + if (t->breakwatch_set) + ret = t->breakwatch_set(t, &bw); + + if (ret == 0) { + /* Success, make a heap copy and add to list */ + struct breakwatch *bwm = malloc(sizeof bw); + memcpy(bwm, &bw, sizeof(bw)); + bwm->next = t->bw_list; + t->bw_list = bwm; } - return 1; + + return ret; } int target_breakwatch_clear(target *t, enum target_breakwatch type, target_addr addr, size_t len) { - switch (type) { - case TARGET_BREAK_HARD: - if (t->set_hw_bp) - return t->set_hw_bp(t, addr, len); - case TARGET_WATCH_WRITE: - case TARGET_WATCH_READ: - case TARGET_WATCH_ACCESS: - if (t->set_hw_wp) - return t->set_hw_wp(t, type, addr, len); - default: - break; + struct breakwatch *bwp = NULL, *bw; + int ret = 1; + for (bw = t->bw_list; bw; bw = bw->next, bwp = bw) + if ((bw->type == type) && + (bw->addr == addr) && + (bw->size == len)) + break; + + if (bw == NULL) + return -1; + + if (t->breakwatch_clear) + ret = t->breakwatch_clear(t, bw); + + if (ret == 0) { + if (bwp == NULL) { + t->bw_list = bw->next; + } else { + bwp->next = bw->next; + } + free(bw); } - return 1; + return ret; } /* Accessor functions */ diff --git a/src/target/target_internal.h b/src/target/target_internal.h index 13a131a..8ead4a2 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -68,6 +68,14 @@ struct target_command_s { struct target_command_s *next; }; +struct breakwatch { + struct breakwatch *next; + enum target_breakwatch type; + target_addr addr; + size_t size; + uint32_t reserved[4]; /* for use by the implementing driver */ +}; + struct target_s { bool attached; struct target_controller *tc; @@ -96,11 +104,9 @@ struct target_s { void (*halt_resume)(target *t, bool step); /* Break-/watchpoint functions */ - int (*set_hw_bp)(target *t, target_addr addr, uint8_t len); - int (*clear_hw_bp)(target *t, target_addr addr, uint8_t len); - - int (*set_hw_wp)(target *t, uint8_t type, target_addr addr, uint8_t len); - int (*clear_hw_wp)(target *t, uint8_t type, target_addr addr, uint8_t len); + int (*breakwatch_set)(target *t, struct breakwatch*); + int (*breakwatch_clear)(target *t, struct breakwatch*); + struct breakwatch *bw_list; /* target-defined options */ unsigned target_options; From 97f3fc6155aa006db5ab46639133f06e4ecd82fd Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 11 Jul 2016 10:42:26 +1200 Subject: [PATCH 23/24] Reorder target.h --- src/include/target.h | 113 +++++++++++++++++++++---------------------- 1 file changed, 56 insertions(+), 57 deletions(-) diff --git a/src/include/target.h b/src/include/target.h index 1b1d70b..a96da46 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -29,6 +29,7 @@ typedef struct target_s target; typedef uint32_t target_addr; +struct target_controller; int adiv5_swdp_scan(void); int jtag_scan(const uint8_t *lrlens); @@ -36,6 +37,61 @@ int jtag_scan(const uint8_t *lrlens); bool target_foreach(void (*cb)(int i, target *t, void *context), void *context); void target_list_free(void); +/* Attach/detach functions */ +target *target_attach(target *t, struct target_controller *); +target *target_attach_n(int n, struct target_controller *); +void target_detach(target *t); +bool target_check_error(target *t); +bool target_attached(target *t); +const char *target_driver_name(target *t); + +/* Memory access functions */ +const char *target_mem_map(target *t); +void target_mem_read(target *t, void *dest, target_addr src, size_t len); +void target_mem_write(target *t, target_addr dest, const void *src, size_t len); +/* Flash memory access functions */ +int target_flash_erase(target *t, target_addr addr, size_t len); +int target_flash_write(target *t, target_addr dest, const void *src, size_t len); +int target_flash_done(target *t); + +/* Register access functions */ +size_t target_regs_size(target *t); +const char *target_tdesc(target *t); +void target_regs_read(target *t, void *data); +void target_regs_write(target *t, const void *data); + +/* Halt/resume functions */ +enum target_halt_reason { + TARGET_HALT_RUNNING = 0, /* Target not halted */ + TARGET_HALT_ERROR, /* Failed to read target status */ + TARGET_HALT_REQUEST, + TARGET_HALT_STEPPING, + TARGET_HALT_BREAKPOINT, + TARGET_HALT_WATCHPOINT, + TARGET_HALT_FAULT, +}; + +void target_reset(target *t); +void target_halt_request(target *t); +enum target_halt_reason target_halt_poll(target *t, target_addr *watch); +void target_halt_resume(target *t, bool step); + +/* Break-/watchpoint functions */ +enum target_breakwatch { + TARGET_BREAK_SOFT, + TARGET_BREAK_HARD, + TARGET_WATCH_WRITE, + TARGET_WATCH_READ, + TARGET_WATCH_ACCESS, +}; +int target_breakwatch_set(target *t, enum target_breakwatch, target_addr, size_t); +int target_breakwatch_clear(target *t, enum target_breakwatch, target_addr, size_t); + +/* Command interpreter */ +void target_command_help(target *t); +int target_command(target *t, int argc, const char *argv[]); + + enum target_errno { TARGET_EPERM = 1, TARGET_ENOENT = 2, @@ -105,62 +161,5 @@ struct target_controller { bool interrupted; }; -/* Halt/resume functions */ -target *target_attach(target *t, struct target_controller *); -target *target_attach_n(int n, struct target_controller *); -void target_detach(target *t); -bool target_check_error(target *t); -bool target_attached(target *t); - -/* Memory access functions */ -void target_mem_read(target *t, void *dest, target_addr src, size_t len); -void target_mem_write(target *t, target_addr dest, const void *src, size_t len); - -/* Register access functions */ -void target_regs_read(target *t, void *data); -void target_regs_write(target *t, const void *data); - -/* Halt/resume functions */ -enum target_halt_reason { - TARGET_HALT_RUNNING = 0, /* Target not halted */ - TARGET_HALT_ERROR, /* Failed to read target status */ - TARGET_HALT_REQUEST, - TARGET_HALT_STEPPING, - TARGET_HALT_BREAKPOINT, - TARGET_HALT_WATCHPOINT, - TARGET_HALT_FAULT, -}; - -void target_reset(target *t); -void target_halt_request(target *t); -enum target_halt_reason target_halt_poll(target *t, target_addr *watch); -void target_halt_resume(target *t, bool step); - -/* Break-/watchpoint functions */ -enum target_breakwatch { - TARGET_BREAK_SOFT, - TARGET_BREAK_HARD, - TARGET_WATCH_WRITE, - TARGET_WATCH_READ, - TARGET_WATCH_ACCESS, -}; -int target_breakwatch_set(target *t, enum target_breakwatch, target_addr, size_t); -int target_breakwatch_clear(target *t, enum target_breakwatch, target_addr, size_t); - -/* Flash memory access functions */ -int target_flash_erase(target *t, target_addr addr, size_t len); -int target_flash_write(target *t, target_addr dest, const void *src, size_t len); -int target_flash_done(target *t); - -/* Accessor functions */ -size_t target_regs_size(target *t); -const char *target_tdesc(target *t); -const char *target_mem_map(target *t); -const char *target_driver_name(target *t); - -/* Command interpreter */ -void target_command_help(target *t); -int target_command(target *t, int argc, const char *argv[]); - #endif From 9a45d89b4a972baf1aa0e13455bb9b9de61be6f3 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 11 Jul 2016 10:53:54 +1200 Subject: [PATCH 24/24] target: Remove target_check_error from external interface. --- src/gdb_main.c | 9 +++------ src/include/target.h | 5 ++--- src/target/target.c | 18 ++++++++++-------- src/target/target_internal.h | 1 + 4 files changed, 16 insertions(+), 17 deletions(-) diff --git a/src/gdb_main.c b/src/gdb_main.c index e52768e..40cb829 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -117,8 +117,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) sscanf(pbuf, "m%" SCNx32 ",%" SCNx32, &addr, &len); DEBUG("m packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); uint8_t mem[len]; - target_mem_read(cur_target, mem, addr, len); - if(target_check_error(cur_target)) + if (target_mem_read(cur_target, mem, addr, len)) gdb_putpacketz("E01"); else gdb_putpacket(hexify(pbuf, mem, len), len*2); @@ -140,8 +139,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) DEBUG("M packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); uint8_t mem[len]; unhexify(mem, pbuf + hex, len); - target_mem_write(cur_target, addr, mem, len); - if(target_check_error(cur_target)) + if (target_mem_write(cur_target, addr, mem, len)) gdb_putpacketz("E01"); else gdb_putpacketz("OK"); @@ -253,8 +251,7 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) ERROR_IF_NO_TARGET(); sscanf(pbuf, "X%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &bin); DEBUG("X packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); - target_mem_write(cur_target, addr, pbuf+bin, len); - if(target_check_error(cur_target)) + if (target_mem_write(cur_target, addr, pbuf+bin, len)) gdb_putpacketz("E01"); else gdb_putpacketz("OK"); diff --git a/src/include/target.h b/src/include/target.h index a96da46..83afb03 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -41,14 +41,13 @@ void target_list_free(void); target *target_attach(target *t, struct target_controller *); target *target_attach_n(int n, struct target_controller *); void target_detach(target *t); -bool target_check_error(target *t); bool target_attached(target *t); const char *target_driver_name(target *t); /* Memory access functions */ const char *target_mem_map(target *t); -void target_mem_read(target *t, void *dest, target_addr src, size_t len); -void target_mem_write(target *t, target_addr dest, const void *src, size_t len); +int target_mem_read(target *t, void *dest, target_addr src, size_t len); +int target_mem_write(target *t, target_addr dest, const void *src, size_t len); /* Flash memory access functions */ int target_flash_erase(target *t, target_addr addr, size_t len); int target_flash_write(target *t, target_addr dest, const void *src, size_t len); diff --git a/src/target/target.c b/src/target/target.c index 94aaa1e..8ba1605 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -293,14 +293,16 @@ bool target_check_error(target *t) { return t->check_error(t); } bool target_attached(target *t) { return t->attached; } /* Memory access functions */ -void target_mem_read(target *t, void *dest, target_addr src, size_t len) +int target_mem_read(target *t, void *dest, target_addr src, size_t len) { t->mem_read(t, dest, src, len); + return target_check_error(t); } -void target_mem_write(target *t, target_addr dest, const void *src, size_t len) +int target_mem_write(target *t, target_addr dest, const void *src, size_t len) { t->mem_write(t, dest, src, len); + return target_check_error(t); } /* Register access functions */ @@ -389,37 +391,37 @@ const char *target_driver_name(target *t) uint32_t target_mem_read32(target *t, uint32_t addr) { uint32_t ret; - target_mem_read(t, &ret, addr, sizeof(ret)); + t->mem_read(t, &ret, addr, sizeof(ret)); return ret; } void target_mem_write32(target *t, uint32_t addr, uint32_t value) { - target_mem_write(t, addr, &value, sizeof(value)); + t->mem_write(t, addr, &value, sizeof(value)); } uint16_t target_mem_read16(target *t, uint32_t addr) { uint16_t ret; - target_mem_read(t, &ret, addr, sizeof(ret)); + t->mem_read(t, &ret, addr, sizeof(ret)); return ret; } void target_mem_write16(target *t, uint32_t addr, uint16_t value) { - target_mem_write(t, addr, &value, sizeof(value)); + t->mem_write(t, addr, &value, sizeof(value)); } uint8_t target_mem_read8(target *t, uint32_t addr) { uint8_t ret; - target_mem_read(t, &ret, addr, sizeof(ret)); + t->mem_read(t, &ret, addr, sizeof(ret)); return ret; } void target_mem_write8(target *t, uint32_t addr, uint8_t value) { - target_mem_write(t, addr, &value, sizeof(value)); + t->mem_write(t, addr, &value, sizeof(value)); } void target_command_help(target *t) diff --git a/src/target/target_internal.h b/src/target/target_internal.h index 8ead4a2..75bd743 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -141,6 +141,7 @@ uint8_t target_mem_read8(target *t, uint32_t addr); void target_mem_write32(target *t, uint32_t addr, uint32_t value); void target_mem_write16(target *t, uint32_t addr, uint16_t value); void target_mem_write8(target *t, uint32_t addr, uint8_t value); +bool target_check_error(target *t); /* Access to host controller interface */ void tc_printf(target *t, const char *fmt, ...);