diff --git a/src/Makefile b/src/Makefile index 956f96f2..e1fbfc5e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -39,6 +39,7 @@ SRC = \ lpc17xx.c \ lpc15xx.c \ lpc43xx.c \ + lpc546xx.c \ kinetis.c \ main.c \ morse.c \ @@ -145,5 +146,5 @@ command.c: include/version.h include/version.h: FORCE $(Q)echo " GIT include/version.h" - $(Q)echo "#define FIRMWARE_VERSION \"$(shell git describe --always --dirty)\"" > $@ + $(Q)echo "#define FIRMWARE_VERSION \"$(shell git describe --always --dirty --tags)\"" > $@ -include *.d diff --git a/src/platforms/common/swdptap.c b/src/platforms/common/swdptap.c index d6e82d21..65f863ec 100644 --- a/src/platforms/common/swdptap.c +++ b/src/platforms/common/swdptap.c @@ -117,6 +117,8 @@ static bool swdptap_seq_in_parity(uint32_t *ret, int ticks) DEBUG("%d", (res & (1 << i)) ? 1 : 0); #endif *ret = res; + /* Terminate the read cycle now */ + swdptap_turnaround(SWDIO_STATUS_DRIVE); return (parity & 1); } diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c index 7129ea15..04ac3785 100644 --- a/src/platforms/f4discovery/platform.c +++ b/src/platforms/f4discovery/platform.c @@ -81,10 +81,13 @@ void platform_init(void) TCK_PIN | TDI_PIN); gpio_mode_setup(JTAG_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, TMS_PIN); - + gpio_set_output_options(JTAG_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, + TCK_PIN | TDI_PIN | TMS_PIN); gpio_mode_setup(TDO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, TDO_PIN); + gpio_set_output_options(TDO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, + TDO_PIN| TMS_PIN); gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, diff --git a/src/platforms/hosted/Makefile.inc b/src/platforms/hosted/Makefile.inc index b3c65019..ddaec7ba 100644 --- a/src/platforms/hosted/Makefile.inc +++ b/src/platforms/hosted/Makefile.inc @@ -1,6 +1,5 @@ SYS = $(shell $(CC) -dumpmachine) CFLAGS += -DENABLE_DEBUG -DPLATFORM_HAS_DEBUG -CFLAGS += -DUSE_USB_VERSION_BIT CFLAGS +=-I ./target -I./platforms/pc ifneq (, $(findstring linux, $(SYS))) diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index 1bb738a6..e5bd906b 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -263,9 +263,10 @@ static int find_debuggers( BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) return (found_debuggers == 1) ? 0 : -1; } +static BMP_CL_OPTIONS_t cl_opts; + void platform_init(int argc, char **argv) { - BMP_CL_OPTIONS_t cl_opts = {0}; cl_opts.opt_idstring = "Blackmagic PC-Hosted"; cl_init(&cl_opts, argc, argv); atexit(exit_function); @@ -426,6 +427,10 @@ void platform_adiv5_dp_defaults(ADIv5_DP_t *dp) { switch (info.bmp_type) { case BMP_TYPE_BMP: + if (cl_opts.opt_no_hl) { + DEBUG_WARN("Not using HL commands\n"); + return; + } return remote_adiv5_dp_defaults(dp); case BMP_TYPE_STLINKV2: return stlink_adiv5_dp_defaults(dp); diff --git a/src/platforms/pc/cl_utils.c b/src/platforms/pc/cl_utils.c index 1ff350e7..f6efc7d3 100644 --- a/src/platforms/pc/cl_utils.c +++ b/src/platforms/pc/cl_utils.c @@ -143,6 +143,7 @@ static void cl_help(char **argv, BMP_CL_OPTIONS_t *opt) DEBUG_WARN("\t-r\t\t: Read flash and write to binary file\n"); DEBUG_WARN("\t-p\t\t: Supplies power to the target (where applicable)\n"); DEBUG_WARN("\t-R\t\t: Reset device\n"); + DEBUG_WARN("\t-H\t\t: Do not use high level commands (BMP-Remote)\n"); DEBUG_WARN("Flash operation modifiers options:\n"); DEBUG_WARN("\tDefault action with given file is to write to flash\n"); DEBUG_WARN("\t-a \t: Start flash operation at flash address \n" @@ -157,7 +158,7 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) int c; opt->opt_target_dev = 1; opt->opt_flash_size = 16 * 1024 *1024; - while((c = getopt(argc, argv, "eEhv:d:s:I:c:CnltVta:S:jpP:rR")) != -1) { + while((c = getopt(argc, argv, "eEhHv:d:s:I:c:CnltVta:S:jpP:rR")) != -1) { switch(c) { case 'c': if (optarg) @@ -166,6 +167,9 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) case 'h': cl_help(argv, opt); break; + case 'H': + opt->opt_no_hl = true; + break; case 'v': if (optarg) cl_debuglevel = strtol(optarg, NULL, 0) & (BMP_DEBUG_MAX - 1); diff --git a/src/platforms/pc/cl_utils.h b/src/platforms/pc/cl_utils.h index e2bd4356..f6f7b1fa 100644 --- a/src/platforms/pc/cl_utils.h +++ b/src/platforms/pc/cl_utils.h @@ -43,6 +43,7 @@ typedef struct BMP_CL_OPTIONS_s { bool opt_list_only; bool opt_connect_under_reset; bool external_resistor_swd; + bool opt_no_hl; char *opt_flash_file; char *opt_device; char *opt_serial; diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 638c1e54..5f032a3b 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -220,7 +220,7 @@ static const struct { {0x975, 0x13, 0x4a13, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M7 ETM", "(Embedded Trace)")}, {0x9a0, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("CoreSight PMU", "(Performance Monitoring Unit)")}, {0x9a1, 0x11, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M4 TPIU", "(Trace Port Interface Unit)")}, - {0x9a9, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M7 TPIU", "(Trace Port Interface Unit)")}, + {0x9a9, 0x11, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-M7 TPIU", "(Trace Port Interface Unit)")}, {0x9a5, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A5 ETM", "(Embedded Trace)")}, {0x9a7, 0x16, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A7 PMU", "(Performance Monitor Unit)")}, {0x9af, 0x00, 0, aa_nosupport, cidc_unknown, PIDR_PN_BIT_STRINGS("Cortex-A15 PMU", "(Performance Monitor Unit)")}, @@ -302,8 +302,9 @@ uint64_t adiv5_ap_read_pidr(ADIv5_AP_t *ap, uint32_t addr) static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, int num_entry) { (void) num_entry; - addr &= ~3; - uint64_t pidr = adiv5_ap_read_pidr(ap, addr); + addr &= 0xfffff000; /* Mask out base address */ + if (addr == 0) /* No rom table on this AP */ + return false; uint32_t cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET); bool res = false; #if defined(ENABLE_DEBUG) @@ -326,6 +327,7 @@ static bool adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, return false; } + uint64_t pidr = adiv5_ap_read_pidr(ap, addr); /* Extract Component ID class nibble */ uint32_t cid_class = (cidr & CID_CLASS_MASK) >> CID_CLASS_SHIFT; @@ -454,6 +456,14 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel) tmpap.apsel = apsel; tmpap.idr = adiv5_ap_read(&tmpap, ADIV5_AP_IDR); tmpap.base = adiv5_ap_read(&tmpap, ADIV5_AP_BASE); + /* Check the Debug Base Address register. See ADIv5 + * Specification C2.6.1 */ + if (tmpap.base == 0xffffffff) { + /* Debug Base Address not present in this MEM-AP */ + /* No debug entries... useless AP */ + /* AP0 on STM32MP157C reads 0x00000002 */ + return NULL; + } if(!tmpap.idr) /* IDR Invalid */ return NULL; @@ -467,7 +477,6 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel) memcpy(ap, &tmpap, sizeof(*ap)); adiv5_dp_ref(dp); - ap->base = adiv5_ap_read(ap, ADIV5_AP_BASE); ap->csw = adiv5_ap_read(ap, ADIV5_AP_CSW) & ~(ADIV5_AP_CSW_SIZE_MASK | ADIV5_AP_CSW_ADDRINC_MASK); @@ -611,16 +620,6 @@ void adiv5_dp_init(ADIv5_DP_t *dp) extern void efm32_aap_probe(ADIv5_AP_t *); efm32_aap_probe(ap); - /* Check the Debug Base Address register. See ADIv5 - * Specification C2.6.1 */ - if (!(ap->base & ADIV5_AP_BASE_PRESENT) || - (ap->base == 0xffffffff)) { - /* Debug Base Address not present in this MEM-AP */ - /* No debug entries... useless AP */ - adiv5_ap_unref(ap); - continue; - } - /* Should probe further here to make sure it's a valid target. * AP should be unref'd if not valid. */ diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 10ea6352..840200d1 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -411,6 +411,7 @@ bool cortexm_probe(ADIv5_AP_t *ap, bool forced) PROBE(lpc11xx_probe); PROBE(lpc15xx_probe); PROBE(lpc43xx_probe); + PROBE(lpc546xx_probe); PROBE(sam3x_probe); PROBE(sam4l_probe); PROBE(nrf51_probe); diff --git a/src/target/lpc546xx.c b/src/target/lpc546xx.c new file mode 100644 index 00000000..fff18bf6 --- /dev/null +++ b/src/target/lpc546xx.c @@ -0,0 +1,232 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2014 Allen Ibara + * Copyright (C) 2015 Gareth McMullin + * Copyright (C) 2020 Eivind Bergem + * + * 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 "target_internal.h" +#include "cortexm.h" +#include "lpc_common.h" + +#define LPC546XX_CHIPID 0x40000FF8 + +#define IAP_ENTRYPOINT_LOCATION 0x03000204 + +#define LPC546XX_ETBAHB_SRAM_BASE 0x20000000 +#define LPC546XX_ETBAHB_SRAM_SIZE (160*1024) + +#define LPC546XX_WDT_MODE 0x4000C000 +#define LPC546XX_WDT_CNT 0x4000C004 +#define LPC546XX_WDT_FEED 0x4000C008 +#define LPC546XX_WDT_PERIOD_MAX 0xFFFFFF +#define LPC546XX_WDT_PROTECT (1 << 4) + +#define IAP_RAM_SIZE LPC546XX_ETBAHB_SRAM_SIZE +#define IAP_RAM_BASE LPC546XX_ETBAHB_SRAM_BASE + +#define IAP_PGM_CHUNKSIZE 4096 + +#define FLASH_NUM_SECTOR 15 + +static bool lpc546xx_cmd_erase(target *t, int argc, const char *argv[]); +static bool lpc546xx_cmd_reset(target *t, int argc, const char *argv[]); +static int lpc546xx_flash_init(target *t); +static int lpc546xx_flash_erase(struct target_flash *f, target_addr addr, size_t len); +static void lpc546xx_set_internal_clock(target *t); +static void lpc546xx_wdt_set_period(target *t); +static void lpc546xx_wdt_pet(target *t); + +const struct command_s lpc546xx_cmd_list[] = { + {"erase_mass", lpc546xx_cmd_erase, "Erase entire flash memory"}, + {"reset", lpc546xx_cmd_reset, "Reset target"}, + {NULL, NULL, NULL} +}; + +void lpc546xx_add_flash(target *t, uint32_t iap_entry, + uint8_t base_sector, uint32_t addr, + size_t len, size_t erasesize) +{ + struct lpc_flash *lf = lpc_add_flash(t, addr, len); + lf->f.erase = lpc546xx_flash_erase; + lf->f.blocksize = erasesize; + lf->f.buf_size = IAP_PGM_CHUNKSIZE; + lf->bank = 0; + lf->base_sector = base_sector; + lf->iap_entry = iap_entry; + lf->iap_ram = IAP_RAM_BASE; + lf->iap_msp = IAP_RAM_BASE + IAP_RAM_SIZE; + lf->wdt_kick = lpc546xx_wdt_pet; +} + +bool lpc546xx_probe(target *t) +{ + uint32_t chipid; + uint32_t iap_entry; + uint32_t flash_size; + + chipid = target_mem_read32(t, LPC546XX_CHIPID); + + switch(chipid) { + case 0x7F954605: + t->driver = "LPC54605J256"; + flash_size = 0x40000; + break; + case 0x7F954606: + t->driver = "LPC54606J256"; + flash_size = 0x40000; + break; + case 0x7F954607: + t->driver = "LPC54607J256"; + flash_size = 0x40000; + break; + case 0x7F954616: + t->driver = "LPC54616J256"; + flash_size = 0x40000; + break; + case 0xFFF54605: + t->driver = "LPC54605J512"; + flash_size = 0x80000; + break; + case 0xFFF54606: + t->driver = "LPC54606J512"; + flash_size = 0x80000; + break; + case 0xFFF54607: + t->driver = "LPC54607J512"; + flash_size = 0x80000; + break; + case 0xFFF54608: + t->driver = "LPC54608J512"; + flash_size = 0x80000; + break; + case 0xFFF54616: + t->driver = "LPC54616J512"; + flash_size = 0x80000; + break; + case 0xFFF54618: + t->driver = "LPC54618J512"; + flash_size = 0x80000; + break; + case 0xFFF54628: + t->driver = "LPC54628J512"; + flash_size = 0x80000; + break; + default: + return false; + } + + iap_entry = target_mem_read32(t, + IAP_ENTRYPOINT_LOCATION); + lpc546xx_add_flash(t, iap_entry, 0, 0x0, + flash_size, 0x8000); + target_add_ram(t, 0x20000000, 0x28000); + target_add_commands(t, lpc546xx_cmd_list, "Lpc546xx"); + t->target_options |= CORTEXM_TOPT_INHIBIT_SRST; + + return false; +} + +/* Reset all major systems _except_ debug */ +static bool lpc546xx_cmd_reset(target *t, int argc, const char *argv[]) +{ + (void)argc; + (void)argv; + + /* Cortex-M4 Application Interrupt and Reset Control Register */ + static const uint32_t AIRCR = 0xE000ED0C; + /* Magic value key */ + static const uint32_t reset_val = 0x05FA0004; + + /* System reset on target */ + target_mem_write(t, AIRCR, &reset_val, sizeof(reset_val)); + + return true; +} + +static bool lpc546xx_cmd_erase(target *t, int argc, const char *argv[]) +{ + (void)argc; + (void)argv; + + lpc546xx_flash_init(t); + struct lpc_flash *f = (struct lpc_flash *)t->flash; + + if (lpc_iap_call(f, NULL, IAP_CMD_PREPARE, 0, FLASH_NUM_SECTOR-1)) + return false; + + if (lpc_iap_call(f, NULL, IAP_CMD_ERASE, 0, FLASH_NUM_SECTOR-1, CPU_CLK_KHZ)) + return false; + + tc_printf(t, "Erase OK.\n"); + + return true; +} + +static int lpc546xx_flash_init(target *t) +{ + /* Deal with WDT */ + lpc546xx_wdt_set_period(t); + + /* /\* Force internal clock *\/ */ + lpc546xx_set_internal_clock(t); + + /* Initialize flash IAP */ + struct lpc_flash *f = (struct lpc_flash *)t->flash; + if (lpc_iap_call(f, NULL, IAP_CMD_INIT)) + return -1; + + return 0; +} + +static int lpc546xx_flash_erase(struct target_flash *tf, target_addr addr, size_t len) +{ + if (lpc546xx_flash_init(tf->t)) + return -1; + + return lpc_flash_erase(tf, addr, len); +} + +static void lpc546xx_set_internal_clock(target *t) +{ + /* Switch to 12 Mhz FRO */ + target_mem_write32(t, 0x40000000 + 0x248, 0); +} + +static void lpc546xx_wdt_set_period(target *t) +{ + /* Check if WDT is on */ + uint32_t wdt_mode = target_mem_read32(t, LPC546XX_WDT_MODE); + + /* If WDT on, we can't disable it, but we may be able to set a long period */ + if (wdt_mode && !(wdt_mode & LPC546XX_WDT_PROTECT)) + target_mem_write32(t, LPC546XX_WDT_CNT, LPC546XX_WDT_PERIOD_MAX); +} + +static void lpc546xx_wdt_pet(target *t) +{ + /* Check if WDT is on */ + uint32_t wdt_mode = target_mem_read32(t, LPC546XX_WDT_MODE); + + /* If WDT on, pet */ + if (wdt_mode) { + target_mem_write32(t, LPC546XX_WDT_FEED, 0xAA); + target_mem_write32(t, LPC546XX_WDT_FEED, 0xFF); + } +} diff --git a/src/target/stm32h7.c b/src/target/stm32h7.c index 07ec6357..d71393cf 100644 --- a/src/target/stm32h7.c +++ b/src/target/stm32h7.c @@ -250,10 +250,10 @@ static bool stm32h7_flash_unlock(target *t, uint32_t addr) if(target_check_error(t)) return false; } - uint32_t sr = target_mem_read32(t, regbase + FLASH_SR); - if (sr & FLASH_SR_ERROR_MASK) { - tc_printf(t, "Error 0x%08lx", sr & FLASH_SR_ERROR_MASK); - target_mem_write32(t, regbase + FLASH_CCR, sr & FLASH_SR_ERROR_MASK); + uint32_t sr = target_mem_read32(t, regbase + FLASH_SR) & FLASH_SR_ERROR_MASK; + if (sr) { + DEBUG_WARN("%s error 0x%08" PRIx32, __func__, sr); + target_mem_write32(t, regbase + FLASH_CCR, sr); return false; } if (target_mem_read32(t, regbase + FLASH_CR) & FLASH_CR_LOCK) { diff --git a/src/target/target_internal.h b/src/target/target_internal.h index 7aa2c8ac..c2288af2 100644 --- a/src/target/target_internal.h +++ b/src/target/target_internal.h @@ -178,6 +178,7 @@ bool lpc11xx_probe(target *t); bool lpc15xx_probe(target *t); bool lpc17xx_probe(target *t); bool lpc43xx_probe(target *t); +bool lpc546xx_probe(target *t); bool sam3x_probe(target *t); bool sam4l_probe(target *t); bool nrf51_probe(target *t);