diff --git a/src/Makefile b/src/Makefile index b6930f27..b3f6f7ac 100644 --- a/src/Makefile +++ b/src/Makefile @@ -31,7 +31,6 @@ SRC = \ gdb_hostio.c \ gdb_packet.c \ hex_utils.c \ - jtag_devs.c \ jtag_scan.c \ lmi.c \ lpc_common.c \ diff --git a/src/gdb_main.c b/src/gdb_main.c index fcf79e69..19bcc31a 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -284,6 +284,8 @@ int gdb_main_loop(struct target_controller *tc, bool in_syscall) else if(last_target) { cur_target = target_attach(last_target, &gdb_controller); + if(cur_target) + morse(NULL, false); target_reset(cur_target); } break; @@ -428,35 +430,36 @@ 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_controller); - if(cur_target) + if(cur_target) { + morse(NULL, false); gdb_putpacketz("T05"); - else + } else gdb_putpacketz("E01"); } else if (!strncmp(packet, "vRun", 4)) { /* Parse command line for get_cmdline semihosting call */ char cmdline[83]; - char *pbuf = cmdline; + char *pcmdline = cmdline; char *tok = packet + 4; if (*tok == ';') tok++; *cmdline='\0'; while(*tok != '\0') { if(strlen(cmdline)+3 >= sizeof(cmdline)) break; if (*tok == ';') { - *pbuf++=' '; - *pbuf='\0'; + *pcmdline++=' '; + *pcmdline='\0'; tok++; continue; } if (isxdigit(*tok) && isxdigit(*(tok+1))) { - unhexify(pbuf, tok, 2); - if ((*pbuf == ' ') || (*pbuf == '\\')) { - *(pbuf+1)=*pbuf; - *pbuf++='\\'; + unhexify(pcmdline, tok, 2); + if ((*pcmdline == ' ') || (*pcmdline == '\\')) { + *(pcmdline+1)=*pcmdline; + *pcmdline++='\\'; } - pbuf++; + pcmdline++; tok+=2; - *pbuf='\0'; + *pcmdline='\0'; continue; } break; @@ -470,12 +473,13 @@ handle_v_packet(char *packet, int plen) cur_target = target_attach(last_target, &gdb_controller); - /* If we were able to attach to the target again */ - if (cur_target) { + /* If we were able to attach to the target again */ + if (cur_target) { target_set_cmdline(cur_target, cmdline); - target_reset(cur_target); - gdb_putpacketz("T05"); - } else gdb_putpacketz("E01"); + target_reset(cur_target); + morse(NULL, false); + gdb_putpacketz("T05"); + } else gdb_putpacketz("E01"); } else gdb_putpacketz("E01"); diff --git a/src/gdb_packet.c b/src/gdb_packet.c index 6f31e138..41920f26 100644 --- a/src/gdb_packet.c +++ b/src/gdb_packet.c @@ -158,7 +158,7 @@ void gdb_putpacket(const char *packet, int size) else DEBUG_GDB_WIRE("\\x%02X", c); #endif - if((c == '$') || (c == '#') || (c == '}')) { + if((c == '$') || (c == '#') || (c == '}') || (c == '*')) { gdb_if_putchar('}', 0); gdb_if_putchar(c ^ 0x20, 0); csum += '}' + (c ^ 0x20); diff --git a/src/include/general.h b/src/include/general.h index ba86da22..25f83a4b 100644 --- a/src/include/general.h +++ b/src/include/general.h @@ -21,7 +21,9 @@ #ifndef __GENERAL_H #define __GENERAL_H -#define _GNU_SOURCE +#if !defined(_GNU_SOURCE) +# define _GNU_SOURCE +#endif #if !defined(__USE_MINGW_ANSI_STDIO) # define __USE_MINGW_ANSI_STDIO 1 #endif @@ -57,18 +59,21 @@ enum BMP_DEBUG { * BMP PC-Hosted is the preferred way. Printing DEBUG_WARN * and DEBUG_INFO is kept for comptibiluty. */ -# if defined(ENABLE_DEBUG) -# define DEBUG_WARN printf -# define DEBUG_INFO printf -# else -# define DEBUG_WARN(...) -# define DEBUG_INFO(...) +# if !defined(PLATFORM_PRINTF) +# define PLATFORM_PRINTF printf # endif -# define DEBUG_GDB(...) -# define DEBUG_TARGET(...) -# define DEBUG_PROBE(...) -# define DEBUG_WIRE(...) -# define DEBUG_GDB_WIRE(...) +# if defined(ENABLE_DEBUG) +# define DEBUG_WARN PLATFORM_PRINTF +# define DEBUG_INFO PLATFORM_PRINTF +# else +# define DEBUG_WARN(...) do {} while(0) +# define DEBUG_INFO(...) do {} while(0) +# endif +# define DEBUG_GDB(...) do {} while(0) +# define DEBUG_TARGET(...) do {} while(0) +# define DEBUG_PROBE(...) do {} while(0) +# define DEBUG_WIRE(...) do {} while(0) +# define DEBUG_GDB_WIRE(...) do {} while(0) #else # include extern int cl_debuglevel; @@ -159,5 +164,11 @@ static inline void DEBUG_WIRE(const char *format, ...) #undef MAX #define MAX(x, y) (((x) > (y)) ? (x) : (y)) +#if !defined(SYSTICKHZ) +# define SYSTICKHZ 100 +#endif +#define SYSTICKMS (1000 / SYSTICKHZ) +#define MORSECNT ((SYSTICKHZ / 10) - 1) + #endif diff --git a/src/morse.c b/src/morse.c index 0fb947a6..fd3b6486 100644 --- a/src/morse.c +++ b/src/morse.c @@ -64,7 +64,7 @@ void morse(const char *msg, char repeat) DEBUG_WARN("%s\n", msg); (void) repeat; #else -morse_msg = morse_ptr = msg; + morse_msg = morse_ptr = msg; morse_repeat = repeat; #endif } diff --git a/src/platforms/common/cdcacm.c b/src/platforms/common/cdcacm.c index 0c9986ad..9765ccf6 100644 --- a/src/platforms/common/cdcacm.c +++ b/src/platforms/common/cdcacm.c @@ -51,7 +51,7 @@ static int cdcacm_gdb_dtr = 1; static void cdcacm_set_modem_state(usbd_device *dev, int iface, bool dsr, bool dcd); -static const struct usb_device_descriptor dev = { +static const struct usb_device_descriptor dev_desc = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, .bcdUSB = 0x0200, @@ -555,7 +555,7 @@ void cdcacm_init(void) serial_no_read(serial_no); - usbdev = usbd_init(&USB_DRIVER, &dev, &config, usb_strings, + usbdev = usbd_init(&USB_DRIVER, &dev_desc, &config, usb_strings, sizeof(usb_strings)/sizeof(char *), usbd_control_buffer, sizeof(usbd_control_buffer)); diff --git a/src/platforms/f4discovery/Makefile.inc b/src/platforms/f4discovery/Makefile.inc index c1771508..ae6b75a6 100644 --- a/src/platforms/f4discovery/Makefile.inc +++ b/src/platforms/f4discovery/Makefile.inc @@ -8,8 +8,15 @@ CFLAGS += -Istm32/include -mcpu=cortex-m4 -mthumb \ -DSTM32F4 -I../libopencm3/include \ -Iplatforms/stm32 +ifeq ($(BLACKPILL), 1) +LINKER_SCRIPT=platforms/stm32/blackpillv2.ld +CFLAGS += -DBLACKPILL=1 +else +LINKER_SCRIPT=platforms/stm32/f4discovery.ld +endif + LDFLAGS_BOOT = -lopencm3_stm32f4 \ - -Wl,-T,platforms/stm32/f4discovery.ld -nostartfiles -lc -lnosys \ + -Wl,-T,$(LINKER_SCRIPT) -nostartfiles -lc -lnosys \ -Wl,-Map=mapfile -mthumb -mcpu=cortex-m4 -Wl,-gc-sections \ -mfloat-abi=hard -mfpu=fpv4-sp-d16 \ -L../libopencm3/lib diff --git a/src/platforms/f4discovery/Readme.md b/src/platforms/f4discovery/Readme.md index a3dae25f..cef87483 100644 --- a/src/platforms/f4discovery/Readme.md +++ b/src/platforms/f4discovery/Readme.md @@ -11,3 +11,55 @@ PC6: TDO/TRACESWO
PC1: TRST
PC8: SRST
+ +# Alternate build for stm32f401 stm32f411 MiniF4 aka BlackPillV2 boards. + +https://github.com/WeActTC/MiniSTM32F4x1 + +## Connections: + +* JTAG/SWD + * PA1: TDI + * PA13: TMS/SWDIO + * PA14: TCK/SWCLK + * PB3: TDO/TRACESWO + * PB5: TRST + * PB4: SRST + +* USB USART + * PB6: USART1 TX (usbuart_xxx) + * PB7: USART1 RX (usbuart_xxx) + +* +3V3. + * PB8 - turn on IRLML5103 transistor + +How to Build +======================================== +``` +cd blackmagic +make clean +make PROBE_HOST=f4discovery BLACKPILL=1 +``` + +How to Flash with dfu +======================================== +* After build: + * 1) `apt install dfu-util` + * 2) Force the F4 into system bootloader mode by jumpering "BOOT0" to "3V3" and "PB2/BOOT1" to "GND" and reset (RESET button). System bootloader should appear. + * 3) `dfu-util -a 0 --dfuse-address 0x08000000 -D blackmagic.bin` + +To exit from dfu mode press a "key" and "reset", release reset. BMP firmware should appear + + +10 pin male from pins +======================================== + +| PB3/TDO | PB7/RX | PB8/TX | X | PA1/TDI | +| -------- | ----------- | ---------- | ---------- | ------- | +| PB4/SRST | +3V3/PB8 SW | PA13/SWDIO | PA14/SWCLK | GND | + +SWJ frequency setting +==================================== +https://github.com/blacksphere/blackmagic/pull/783#issue-529197718 + +`mon freq 900k` helps at most diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c index 2eb6bcbc..4233f10a 100644 --- a/src/platforms/f4discovery/platform.c +++ b/src/platforms/f4discovery/platform.c @@ -37,20 +37,32 @@ #include #include +#ifdef BLACKPILL +#include +#endif + + jmp_buf fatal_error_jmpbuf; extern char _ebss[]; void platform_init(void) { volatile uint32_t *magic = (uint32_t *)_ebss; - /* Check the USER button*/ + /* Enable GPIO peripherals */ rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOC); +#ifdef BLACKPILL + rcc_periph_clock_enable(RCC_GPIOB); +#else + rcc_periph_clock_enable(RCC_GPIOD); +#endif + /* Check the USER button*/ if (gpio_get(GPIOA, GPIO0) || - ((magic[0] == BOOTMAGIC0) && (magic[1] == BOOTMAGIC1))) { + ((magic[0] == BOOTMAGIC0) && (magic[1] == BOOTMAGIC1))) + { magic[0] = 0; magic[1] = 0; /* Assert blue LED as indicator we are in the bootloader */ - rcc_periph_clock_enable(RCC_GPIOD); gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_BOOTLOADER); gpio_set(LED_PORT, LED_BOOTLOADER); @@ -58,44 +70,65 @@ void platform_init(void) As we just come out of reset, no other deinit is needed!*/ rcc_periph_clock_enable(RCC_SYSCFG); SYSCFG_MEMRM &= ~3; - SYSCFG_MEMRM |= 1; + SYSCFG_MEMRM |= 1; scb_reset_core(); } - +#ifdef BLACKPILL + rcc_clock_setup_pll(&rcc_hse_25mhz_3v3[RCC_CLOCK_3V3_84MHZ]); +#else rcc_clock_setup_pll(&rcc_hse_8mhz_3v3[RCC_CLOCK_3V3_168MHZ]); +#endif /* Enable peripherals */ rcc_periph_clock_enable(RCC_OTGFS); - rcc_periph_clock_enable(RCC_GPIOC); - rcc_periph_clock_enable(RCC_GPIOD); rcc_periph_clock_enable(RCC_CRC); /* Set up USB Pins and alternate function*/ - gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9 | GPIO11 | GPIO12); + gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9 | GPIO11 | GPIO12); gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO10 | GPIO11 | GPIO12); - GPIOC_OSPEEDR &=~0xF30; +#ifdef BLACKPILL + GPIOA_OSPEEDR &= 0x3C00000C; + GPIOA_OSPEEDR |= 0x28000008; +#else + GPIOC_OSPEEDR &= ~0xF30; GPIOC_OSPEEDR |= 0xA20; +#endif + gpio_mode_setup(JTAG_PORT, GPIO_MODE_OUTPUT, - GPIO_PUPD_NONE, - TCK_PIN | TDI_PIN); + GPIO_PUPD_NONE, + TCK_PIN | TDI_PIN); gpio_mode_setup(JTAG_PORT, GPIO_MODE_INPUT, - GPIO_PUPD_NONE, TMS_PIN); + 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_PUPD_NONE, + TDO_PIN); gpio_set_output_options(TDO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, - TDO_PIN| TMS_PIN); + TDO_PIN | TMS_PIN); gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, - GPIO_PUPD_NONE, - LED_UART | LED_IDLE_RUN | LED_ERROR | LED_BOOTLOADER); + GPIO_PUPD_NONE, + LED_IDLE_RUN | LED_ERROR | LED_BOOTLOADER); + + gpio_mode_setup(LED_PORT_UART, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, LED_UART); + +#ifdef PLATFORM_HAS_POWER_SWITCH + gpio_set(PWR_BR_PORT, PWR_BR_PIN); + gpio_mode_setup(PWR_BR_PORT, GPIO_MODE_OUTPUT, + GPIO_PUPD_NONE, + PWR_BR_PIN); +#endif platform_timing_init(); usbuart_init(); cdcacm_init(); +#ifdef BLACKPILL + // https://github.com/libopencm3/libopencm3/pull/1256#issuecomment-779424001 + OTG_FS_GCCFG |= OTG_GCCFG_NOVBUSSENS | OTG_GCCFG_PWRDWN; + OTG_FS_GCCFG &= ~(OTG_GCCFG_VBUSBSEN | OTG_GCCFG_VBUSASEN); +#endif } void platform_srst_set_val(bool assert) { (void)assert; } @@ -108,8 +141,20 @@ const char *platform_target_voltage(void) void platform_request_boot(void) { - uint32_t *magic = (uint32_t *) &_ebss; + uint32_t *magic = (uint32_t *)&_ebss; magic[0] = BOOTMAGIC0; magic[1] = BOOTMAGIC1; scb_reset_system(); } + +#ifdef PLATFORM_HAS_POWER_SWITCH +bool platform_target_get_power(void) +{ + return !gpio_get(PWR_BR_PORT, PWR_BR_PIN); +} + +void platform_target_set_power(bool power) +{ + gpio_set_val(PWR_BR_PORT, PWR_BR_PIN, !power); +} +#endif \ No newline at end of file diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index a1a06f88..0865e476 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -31,6 +31,55 @@ #include #define PLATFORM_HAS_TRACESWO +#ifdef BLACKPILL +#define PLATFORM_IDENT "(F4Discovery/BlackPillV2) " +/* Important pin mappings for STM32 implementation: + * JTAG/SWD + * PA1: TDI
+ * PA13: TMS/SWDIO
+ * PA14: TCK/SWCLK
+ * PB3: TDO/TRACESWO
+ * PB5: TRST
+ * PB4: SRST
+ * USB USART + * PB6: USART1 TX + * PB7: USART1 RX + * +3V3 + * PB8 - turn on IRLML5103 transistor + * Force DFU mode button: PA0 + */ + +/* Hardware definitions... */ +#define JTAG_PORT GPIOA +#define TDI_PORT JTAG_PORT +#define TMS_PORT JTAG_PORT +#define TCK_PORT JTAG_PORT +#define TDO_PORT GPIOB +#define TDI_PIN GPIO1 +#define TMS_PIN GPIO13 +#define TCK_PIN GPIO14 +#define TDO_PIN GPIO3 + +#define SWDIO_PORT JTAG_PORT +#define SWCLK_PORT JTAG_PORT +#define SWDIO_PIN TMS_PIN +#define SWCLK_PIN TCK_PIN + +#define TRST_PORT GPIOB +#define TRST_PIN GPIO5 +#define SRST_PORT GPIOB +#define SRST_PIN GPIO4 + +#define PWR_BR_PORT GPIOB +#define PWR_BR_PIN GPIO8 + +#define LED_PORT GPIOC +#define LED_PORT_UART GPIOA +#define LED_UART GPIO1 +#define LED_IDLE_RUN GPIO15 +#define LED_ERROR GPIO14 +#define LED_BOOTLOADER GPIO13 +#else #define PLATFORM_IDENT "(F4Discovery) " /* Important pin mappings for STM32 implementation: @@ -78,6 +127,8 @@ #define LED_IDLE_RUN GPIO13 #define LED_ERROR GPIO14 #define LED_BOOTLOADER GPIO15 +#endif + #define BOOTMAGIC0 0xb007da7a #define BOOTMAGIC1 0xbaadfeed diff --git a/src/platforms/hosted/Makefile.inc b/src/platforms/hosted/Makefile.inc index cd0ce561..b1322358 100644 --- a/src/platforms/hosted/Makefile.inc +++ b/src/platforms/hosted/Makefile.inc @@ -2,12 +2,12 @@ SYS = $(shell $(CC) -dumpmachine) CFLAGS += -DENABLE_DEBUG -DPLATFORM_HAS_DEBUG CFLAGS +=-I ./target -I./platforms/pc -# Define HOSTED_BMP_ONLY to '1' in order to build the hosted blackmagic -# executable with support for native BMP probes only. This makes -# linking against the libftdi and libusb libraries unnecessary. This can -# be useful to minimize external dependencies, and make building on -# windows systems easier. -HOSTED_BMP_ONLY ?= 0 +# Define HOSTED_BMP_ONLY to '0' in order to build the hosted blackmagic +# executable with support for other probes beside BMP. Default HOSTED_BMP_ONLY +# == 1 makes linking against the libftdi and libusb libraries unnecessary. +# This can be useful to minimize external dependencies, and make building on +# windows systems easier and is default now. +HOSTED_BMP_ONLY ?= 1 CFLAGS += -DHOSTED_BMP_ONLY=$(HOSTED_BMP_ONLY) ifneq (, $(findstring linux, $(SYS))) @@ -59,7 +59,7 @@ ifneq ($(HOSTED_BMP_ONLY), 1) endif VPATH += platforms/pc -SRC += timing.c cl_utils.c utils.c +SRC += timing.c cl_utils.c utils.c jtag_devs.c SRC += bmp_remote.c remote_swdptap.c remote_jtagtap.c ifneq ($(HOSTED_BMP_ONLY), 1) SRC += bmp_libusb.c stlinkv2.c diff --git a/src/platforms/hosted/Readme.md b/src/platforms/hosted/Readme.md index 5f3e24d1..a1d56c5e 100644 --- a/src/platforms/hosted/Readme.md +++ b/src/platforms/hosted/Readme.md @@ -1,5 +1,7 @@ # PC-Hosted BMP -Compile in src with "make PROBE_HOST=hosted" +Compile in src with "make PROBE_HOST=hosted". This needs minimal external +support. "make PROBE_HOST=hosted HOSTED_BMP=0" will compile support for FTDI, +STLink, CMSIS-DAP and JLINK probes, but requires external libraries. ## Description PC-hosted BMP run on the PC and compiles as "blackmagic". When started, @@ -8,7 +10,7 @@ if either only one probe is attached to the PC or enough information is given on the command line to select one of several probes. When started without any other argument beside the probe selection, a -GDB server is started as port 2000 and up. Connect to the server as you would +GDB server is started on port 2000 and up. Connect to the server as you would connect to the BMP with the CDCACM GDB serial server. GDB functionality is the same, monitor option may vary. @@ -60,9 +62,9 @@ blackmagic -M "option help" ## Compiling on windows You can crosscompile blackmagic for windows with mingw or on windows -with cygwin. For compilation, headers for libftdi1 and libusb-1.0 are -needed. For running, libftdi1.dll and libusb-1.0.dll are needed and -the executable must be able to find them. Mingw on cygwin does not provide +with cygwin. For suppport of other probes beside BMP, headers for libftdi1 and +libusb-1.0 are needed. For running, libftdi1.dll and libusb-1.0.dll are needed +and the executable must be able to find them. Mingw on cygwin does not provide a libftdi package yet. PC-hosted BMP for windows can also be built with [MSYS2](https://www.msys2.org/), @@ -78,7 +80,8 @@ pacman -S mingw-w64-x86_64-gcc --needed PROBE_HOST=hosted make ``` -To prepare libusb access to the ftdi/stlink/jlink/cmsis-dap devices, run zadig +For suppport of other probes beside BMP, libusb access is needed. To prepare +libusb access to the ftdi/stlink/jlink/cmsis-dap devices, run zadig https://zadig.akeo.ie/. Choose WinUSB(libusb-1.0). Running cygwin/blackmagic in a cygwin console, the program does not react @@ -91,6 +94,7 @@ REMOTE_BMP is a "normal" BMP usb connected | Debugger | Speed | Remarks | ------------ | ----- | ------ | REMOTE_BMP | +++ | Requires recent firmware for decent speed +Probes below only when compiled with HOSTED_BMP=0 | ST-Link V3 | ++++ | Requires recent firmware, Only STM32 devices supported! | ST-Link V2 | +++ | Requires recent firmware, No CDCACM uart! Cortex only! | ST-Link V2/1 | +++ | Requires recent firmware, Cortex only! diff --git a/src/platforms/hosted/bmp_libusb.c b/src/platforms/hosted/bmp_libusb.c index 8739710d..f7a15fa7 100644 --- a/src/platforms/hosted/bmp_libusb.c +++ b/src/platforms/hosted/bmp_libusb.c @@ -229,8 +229,9 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info) DEBUG_WARN("BMP in botloader mode found. Restart or reflash!\n"); continue; } - } else if ((type = find_cmsis_dap_interface(dev, info)) != BMP_TYPE_NONE) { - /* type was set by the expression */ + } else if ((type == BMP_TYPE_NONE) && + ((type = find_cmsis_dap_interface(dev, info)) != BMP_TYPE_NONE)) { + /* find_cmsis_dap_interface has set valid type*/ } else if ((strstr(manufacturer, "CMSIS")) || (strstr(product, "CMSIS"))) { type = BMP_TYPE_CMSIS_DAP_V1; } else if (desc.idVendor == VENDOR_ID_STLINK) { diff --git a/src/platforms/hosted/cmsis_dap.c b/src/platforms/hosted/cmsis_dap.c index 19c49e39..002c44a4 100644 --- a/src/platforms/hosted/cmsis_dap.c +++ b/src/platforms/hosted/cmsis_dap.c @@ -349,7 +349,7 @@ static void cmsis_dap_jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks) { dap_jtagtap_tdi_tdo_seq(DO, (final_tms), NULL, DI, ticks); - DEBUG_PROBE("jtagtap_tdi_tdo_seq %d, %02x-> %02x\n", ticks, DI[0], DO[0]); + DEBUG_PROBE("jtagtap_tdi_tdo_seq %d, %02x-> %02x\n", ticks, DI[0], (DO)? DO[0] : 0); } static void cmsis_dap_jtagtap_tdi_seq(const uint8_t final_tms, diff --git a/src/platforms/hosted/dap.c b/src/platforms/hosted/dap.c index 5acc03e5..7da956b8 100644 --- a/src/platforms/hosted/dap.c +++ b/src/platforms/hosted/dap.c @@ -644,15 +644,16 @@ void dap_write_single(ADIv5_AP_t *ap, uint32_t dest, const void *src, void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS, const uint8_t *DI, int ticks) { + DEBUG_PROBE("dap_jtagtap_tdi_tdo_seq %s %d ticks\n", + (final_tms) ? "final" : "", ticks); uint8_t buf[64]; + const uint8_t *din = DI; + uint8_t *dout = DO; if (!TMS) { - int last_byte = 0; - int last_bit = 0; - if (final_tms) { - last_byte = ticks >> 3; - last_bit = ticks & 7; + int last_byte = last_byte = (ticks - 1) >> 3; + int last_bit = (ticks - 1) & 7; + if (final_tms) ticks --; - } while (ticks) { int transfers = ticks; if (transfers > 64) @@ -660,11 +661,12 @@ void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS, uint8_t *p = buf; *p++ = ID_DAP_JTAG_SEQUENCE; *p++ = 1; - *p++ = transfers | ((DO) ? DAP_JTAG_TDO_CAPTURE : 0); + *p++ = ((transfers == 64) ? 0 : transfers) | + ((DO) ? DAP_JTAG_TDO_CAPTURE : 0); int n_di_bytes = (transfers + 7) >> 3; - if (DI) { - p = memcpy(p, DI, n_di_bytes); - DI += n_di_bytes; + if (din) { + p = memcpy(p, din, n_di_bytes); + din += n_di_bytes; } else { p = memset(p, 0xff, n_di_bytes); } @@ -672,9 +674,9 @@ void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS, dbg_dap_cmd(buf, sizeof(buf), p - buf); if (buf[0] != DAP_OK) DEBUG_WARN("dap_jtagtap_tdi_tdo_seq failed %02x\n", buf[0]); - if (DO) { - memcpy(DO, &buf[1], (transfers + 7) >> 3); - DO += (transfers + 7) >> 3; + if (dout) { + memcpy(dout, &buf[1], (transfers + 7) >> 3); + dout += (transfers + 7) >> 3; } ticks -= transfers; } @@ -682,8 +684,8 @@ void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS, uint8_t *p = buf; *p++ = ID_DAP_JTAG_SEQUENCE; *p++ = 1; - *p++ = 1 | ((DO) ? DAP_JTAG_TDO_CAPTURE : 0) | DAP_JTAG_TMS; - if (DI) { + *p++ = 1 | ((dout) ? DAP_JTAG_TDO_CAPTURE : 0) | DAP_JTAG_TMS; + if (din) { *p++ = ((DI[last_byte] & (1 << last_bit)) ? 1 : 0); } else { *p++ = 0; @@ -691,7 +693,7 @@ void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS, dbg_dap_cmd(buf, sizeof(buf), p - buf); if (buf[0] == DAP_ERROR) DEBUG_WARN("dap_jtagtap_tdi_tdo_seq failed %02x\n", buf[0]); - if (DO) { + if (dout) { if (buf[1] & 1) DO[last_byte] |= (1 << last_bit); else @@ -709,11 +711,11 @@ void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS, *p++ = transfers; for (int i = 0; i < transfers; i++) { *p++ = 1 | ((DO) ? DAP_JTAG_TDO_CAPTURE : 0) | - ((TMS[i >> 8] & (1 << (i & 7))) ? DAP_JTAG_TMS : 0); + ((TMS[i / 8] & (1 << (i & 7))) ? DAP_JTAG_TMS : 0); if (DI) - *p++ = (DI[i >> 8] & (1 << (i & 7))) ? 1 : 0; + *p++ = (DI[i / 8] & (1 << (i & 7))) ? 1 : 0; else - *p++ = 0x55; + *p++ = 1; } dbg_dap_cmd(buf, sizeof(buf), p - buf); if (buf[0] == DAP_ERROR) @@ -721,9 +723,9 @@ void dap_jtagtap_tdi_tdo_seq(uint8_t *DO, bool final_tms, const uint8_t *TMS, if (DO) { for (int i = 0; i < transfers; i++) { if (buf[i + 1]) - DO[i >> 8] |= (1 << (i & 7)); + DO[i / 8] |= (1 << (i & 7)); else - DO[i >> 8] &= ~(1 << (i & 7)); + DO[i / 8] &= ~(1 << (i & 7)); } } ticks -= transfers; diff --git a/src/platforms/hosted/ftdi_bmp.c b/src/platforms/hosted/ftdi_bmp.c index f05a86b7..7d515f1c 100644 --- a/src/platforms/hosted/ftdi_bmp.c +++ b/src/platforms/hosted/ftdi_bmp.c @@ -123,8 +123,8 @@ cable_desc_t cable_desc[] = { .init.ddr_low = PIN4, .init.data_high = PIN4 | PIN3 | PIN2, .init.ddr_high = PIN4 | PIN3 | PIN2 | PIN1 | PIN0, - .assert_srst.data_high = ~PIN2, - .deassert_srst.data_high = PIN2, + .assert_srst.data_high = ~PIN3, + .deassert_srst.data_high = PIN3, .srst_get_port_cmd = GET_BITS_LOW, .srst_get_pin = PIN6, .description = "FTDIJTAG", @@ -421,11 +421,11 @@ static void libftdi_set_data(data_desc_t* data) if ((data->data_low) || (data->ddr_low)) { if (data->data_low > 0) active_state.data_low |= (data->data_low & 0xff); - else + else if (data->data_low < 0) active_state.data_low &= (data->data_low & 0xff); if (data->ddr_low > 0) active_state.ddr_low |= (data->ddr_low & 0xff); - else + else if (data->ddr_low < 0) active_state.ddr_low &= (data->ddr_low & 0xff); cmd[index++] = SET_BITS_LOW; cmd[index++] = active_state.data_low; @@ -434,11 +434,11 @@ static void libftdi_set_data(data_desc_t* data) if ((data->data_high) || (data->ddr_high)) { if (data->data_high > 0) active_state.data_high |= (data->data_high & 0xff); - else + else if (data->data_high < 0) active_state.data_high &= (data->data_high & 0xff); if (data->ddr_high > 0) active_state.ddr_high |= (data->ddr_high & 0xff); - else + else if (data->ddr_high < 0) active_state.ddr_high &= (data->ddr_high & 0xff); cmd[index++] = SET_BITS_HIGH; cmd[index++] = active_state.data_high; @@ -552,7 +552,8 @@ void libftdi_jtagtap_tdi_tdo_seq( if(!ticks) return; if (!DI && !DO) return; -// printf("ticks: %d\n", ticks); + DEBUG_WIRE("libftdi_jtagtap_tdi_tdo_seq %s ticks: %d\n", + (DI && DO) ? "read/write" : ((DI) ? "read" : "write"),ticks); if(final_tms) ticks--; rticks = ticks & 7; ticks >>= 3; @@ -593,7 +594,6 @@ void libftdi_jtagtap_tdi_tdo_seq( if(final_tms) rsize--; while(rsize--) { - /*if(rsize) printf("%02X ", tmp[index]);*/ *DO++ = tmp[index++]; } if (rticks == 0) @@ -606,7 +606,6 @@ void libftdi_jtagtap_tdi_tdo_seq( if(rticks) { *DO >>= (8-rticks); } - /*printf("%02X\n", *DO);*/ } } diff --git a/src/platforms/hosted/ftdi_bmp.h b/src/platforms/hosted/ftdi_bmp.h index 931b1aa6..e5553a44 100644 --- a/src/platforms/hosted/ftdi_bmp.h +++ b/src/platforms/hosted/ftdi_bmp.h @@ -114,6 +114,8 @@ void libftdi_jtagtap_tdi_tdo_seq( bool libftdi_swd_possible(bool *do_mpsse, bool *direct_bb_swd) {return false;}; void libftdi_max_frequency_set(uint32_t freq) {}; uint32_t libftdi_max_frequency_get(void) {return 0;}; +void libftdi_srst_set_val(bool assert){}; +bool libftdi_srst_get_val(void) { return false;}; # pragma GCC diagnostic pop #else #include @@ -134,6 +136,8 @@ void libftdi_jtagtap_tdi_tdo_seq( bool libftdi_swd_possible(bool *do_mpsse, bool *direct_bb_swd); void libftdi_max_frequency_set(uint32_t freq); uint32_t libftdi_max_frequency_get(void); +void libftdi_srst_set_val(bool assert); +bool libftdi_srst_get_val(void); #endif #define MPSSE_SK 1 diff --git a/src/platforms/hosted/platform.c b/src/platforms/hosted/platform.c index a408fde4..df657d5f 100644 --- a/src/platforms/hosted/platform.c +++ b/src/platforms/hosted/platform.c @@ -299,6 +299,8 @@ void platform_srst_set_val(bool assert) return remote_srst_set_val(assert); case BMP_TYPE_JLINK: return jlink_srst_set_val(&info, assert); + case BMP_TYPE_LIBFTDI: + return libftdi_srst_set_val(assert); default: break; } @@ -313,6 +315,8 @@ bool platform_srst_get_val(void) return stlink_srst_get_val(); case BMP_TYPE_JLINK: return jlink_srst_get_val(&info); + case BMP_TYPE_LIBFTDI: + return libftdi_srst_get_val(); default: break; } diff --git a/src/platforms/hosted/platform.h b/src/platforms/hosted/platform.h index bf3fa141..339fec85 100644 --- a/src/platforms/hosted/platform.h +++ b/src/platforms/hosted/platform.h @@ -10,6 +10,8 @@ void platform_buffer_flush(void); #define SET_IDLE_STATE(x) #define SET_RUN_STATE(x) +#define SYSTICKHZ 1000 + #define VENDOR_ID_BMP 0x1d50 #define PRODUCT_ID_BMP_BL 0x6017 #define PRODUCT_ID_BMP 0x6018 diff --git a/src/platforms/hosted/remote_jtagtap.c b/src/platforms/hosted/remote_jtagtap.c index 601a3e90..a92a253c 100644 --- a/src/platforms/hosted/remote_jtagtap.c +++ b/src/platforms/hosted/remote_jtagtap.c @@ -104,35 +104,53 @@ static void jtagtap_tms_seq(uint32_t MS, int ticks) } } +/* At least up to v1.7.1-233, remote handles only up to 32 ticks in one + * call. Break up large calls. + * + * FIXME: Provide and test faster call and keep fallback + * for old firmware + */ static void jtagtap_tdi_tdo_seq( uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks) { uint8_t construct[REMOTE_MAX_MSG_SIZE]; int s; - uint64_t DIl=*(uint64_t *)DI; + if(!ticks || (!DI && !DO)) + return; + uint64_t *DIl = (uint64_t *)DI; + uint64_t *DOl = (uint64_t *)DO; + while (ticks) { + int chunk; + if (ticks < 65) + chunk = ticks; + else { + chunk = 64; + } + ticks -= chunk; + uint64_t dil; + if (DI) + dil = *DIl++; + else + dil = 0; + /* Reduce the length of DI according to the bits we're transmitting */ + if (chunk < 64) + dil &= ((1LL << chunk) - 1); + s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, + "!J%c%02x%" PRIx64 "%c", + (!ticks && final_tms) ? + REMOTE_TDITDO_TMS : REMOTE_TDITDO_NOTMS, + chunk, dil, REMOTE_EOM); + platform_buffer_write(construct,s); - if(!ticks || !DI) return; - - /* Reduce the length of DI according to the bits we're transmitting */ - DIl &= (1LL << (ticks + 1))-1; - - s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE, - REMOTE_JTAG_TDIDO_STR, - final_tms ? REMOTE_TDITDO_TMS : REMOTE_TDITDO_NOTMS, - ticks, DIl); - platform_buffer_write(construct,s); - - s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); - if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { - DEBUG_WARN("jtagtap_tms_seq failed, error %s\n", - s ? (char *)&(construct[1]) : "unknown"); - exit(-1); - } - - if (DO) { - uint64_t DOl = remotehston(-1, (char *)&construct[1]); - *(uint64_t *)DO = DOl; + s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE); + if ((!s) || (construct[0] == REMOTE_RESP_ERR)) { + DEBUG_WARN("jtagtap_tms_seq failed, error %s\n", + s ? (char *)&(construct[1]) : "unknown"); + exit(-1); + } + if (DO) + *DOl++ = remotehston(-1, (char *)&construct[1]); } } diff --git a/src/platforms/hosted/stlinkv2.c b/src/platforms/hosted/stlinkv2.c index 211ad10b..5dd99dd4 100644 --- a/src/platforms/hosted/stlinkv2.c +++ b/src/platforms/hosted/stlinkv2.c @@ -1008,7 +1008,7 @@ int jtag_scan_stlinkv2(bmp_info_t *info, const uint8_t *irlens) if((jtag_devs[i].jd_idcode & dev_descr[j].idmask) == dev_descr[j].idcode) { if(dev_descr[j].handler) - dev_descr[j].handler(i, dev_descr[j].idcode); + dev_descr[j].handler(&jtag_devs[i]); break; } diff --git a/src/platforms/jeff/Makefile.inc b/src/platforms/jeff/Makefile.inc index 727a7ff8..3dad8f85 100644 --- a/src/platforms/jeff/Makefile.inc +++ b/src/platforms/jeff/Makefile.inc @@ -21,7 +21,7 @@ ifeq ($(ENABLE_DEBUG), 1) CFLAGS += -g3 -ggdb endif -CFLAGS += -mthumb -mcpu=cortex-m0plus \ +CFLAGS += -mthumb -mcpu=cortex-m0plus -DDFU_SERIAL_LENGTH=9 \ -DSAMD -DSAMD21E17 -DBLACKMAGIC -I../libopencm3/include \ -Iplatforms/samd -msoft-float -ffunction-sections -fdata-sections -MD diff --git a/src/platforms/jeff/platform.c b/src/platforms/jeff/platform.c index 9e07420b..f2dc273a 100644 --- a/src/platforms/jeff/platform.c +++ b/src/platforms/jeff/platform.c @@ -252,11 +252,8 @@ const char *platform_target_voltage(void) return out; } -char *serial_no_read(char *s, int max) +char *serial_no_read(char *s) { - if (max >= 8) - max = 8; - #ifdef CUSTOM_SER s[0] = 'J'; s[1] = 'E'; @@ -265,17 +262,18 @@ char *serial_no_read(char *s, int max) return s; #else int i; + volatile uint32_t unique_id = *(volatile uint32_t *)0x0080A00C + *(volatile uint32_t *)0x0080A040 + *(volatile uint32_t *)0x0080A044 + *(volatile uint32_t *)0x0080A048; /* Fetch serial number from chip's unique ID */ - for(i = 0; i < max; i++) { + for(i = 0; i < 8; i++) { s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; } - for(i = 0; i < max; i++) + for(i = 0; i < 8; i++) if(s[i] > '9') s[i] += 'A' - '9' - 1; s[8] = 0; diff --git a/src/platforms/launchpad-icdi/platform.c b/src/platforms/launchpad-icdi/platform.c index d62a8cda..83189192 100644 --- a/src/platforms/launchpad-icdi/platform.c +++ b/src/platforms/launchpad-icdi/platform.c @@ -25,9 +25,6 @@ #include #include -#define SYSTICKHZ 100 -#define SYSTICKMS (1000 / SYSTICKHZ) - #define PLL_DIV_80MHZ 5 #define PLL_DIV_25MHZ 16 diff --git a/src/platforms/pc/cl_utils.c b/src/platforms/pc/cl_utils.c index fc34496f..65de1cf9 100644 --- a/src/platforms/pc/cl_utils.c +++ b/src/platforms/pc/cl_utils.c @@ -24,6 +24,7 @@ #include "general.h" #include +#include #include #include #include @@ -151,10 +152,10 @@ static void cl_help(char **argv) DEBUG_WARN("\tDefault mode is to start the debug server at :2000\n"); DEBUG_WARN("\t-j\t\t: Use JTAG. SWD is default.\n"); DEBUG_WARN("\t-f\t\t: Set minimum high and low times of SWJ waveform.\n"); - DEBUG_WARN("\t-C\t\t: Connect under reset\n"); + DEBUG_WARN("\t-C\t\t: Connect under hardware reset\n"); DEBUG_WARN("\t-t\t\t: Scan SWD or JTAG and display information about \n" "\t\t\t connected devices\n"); - DEBUG_WARN("\t-T\t\t: Continious read/write-back some value to allow\n" + DEBUG_WARN("\t-T\t\t: Continuous read/write-back some value to allow\n" "\t\t\t timing insection of SWJ. Abort with ^C\n"); DEBUG_WARN("\t-e\t\t: Assume \"resistor SWD connection\" on FTDI: TDI\n" "\t\t\t connected to TMS, TDO to TDI with eventual resistor\n"); @@ -164,7 +165,7 @@ static void cl_help(char **argv) "\t\t\t with -w to verify right after programming.\n"); 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-R[h]\t\t: Reset device. Default via SWJ or by hardware(h)\n"); DEBUG_WARN("\t-H\t\t: Do not use high level commands (BMP-Remote)\n"); DEBUG_WARN("\t-m \t: Use (target)id for SWD multi-drop.\n"); DEBUG_WARN("\t-M \t: Run target specific monitor commands. Quote multi\n"); @@ -185,7 +186,7 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) opt->opt_flash_size = 0xffffffff; opt->opt_flash_start = 0xffffffff; opt->opt_max_swj_frequency = 4000000; - while((c = getopt(argc, argv, "eEhHv:d:f:s:I:c:Cln:m:M:wVtTa:S:jpP:rR")) != -1) { + while((c = getopt(argc, argv, "eEhHv:d:f:s:I:c:Cln:m:M:wVtTa:S:jpP:rR::")) != -1) { switch(c) { case 'c': if (optarg) @@ -268,7 +269,10 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) opt->opt_mode = BMP_MODE_FLASH_READ; break; case 'R': - opt->opt_mode = BMP_MODE_RESET; + if ((optarg) && (tolower(optarg[0]) == 'h')) + opt->opt_mode = BMP_MODE_RESET_HW; + else + opt->opt_mode = BMP_MODE_RESET; break; case 'p': opt->opt_tpwr = true; @@ -321,7 +325,8 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv) /* Checks */ if ((opt->opt_flash_file) && ((opt->opt_mode == BMP_MODE_TEST ) || (opt->opt_mode == BMP_MODE_SWJ_TEST) || - (opt->opt_mode == BMP_MODE_RESET))) { + (opt->opt_mode == BMP_MODE_RESET) || + (opt->opt_mode == BMP_MODE_RESET_HW))) { DEBUG_WARN("Ignoring filename in reset/test mode\n"); opt->opt_flash_file = NULL; } @@ -352,6 +357,12 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) platform_target_set_power(true); platform_delay(500); } + if (opt->opt_mode == BMP_MODE_RESET_HW) { + platform_srst_set_val(true); + platform_delay(1); + platform_srst_set_val(false); + return 0; + } if (opt->opt_connect_under_reset) DEBUG_INFO("Connecting under reset\n"); connect_assert_srst = opt->opt_connect_under_reset; @@ -364,7 +375,7 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) } else { num_targets = platform_adiv5_swdp_scan(opt->opt_targetid); if (!num_targets) { - DEBUG_INFO("Scan SWD failed, trying JTAG!\n"); + DEBUG_WARN("Scan SWD failed, trying JTAG!\n"); num_targets = platform_jtag_scan(NULL); } } @@ -419,9 +430,9 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) if (opt->opt_flash_start == 0xffffffff) opt->opt_flash_start = lowest_flash_start; if ((opt->opt_flash_size == 0xffffffff) && - (opt->opt_mode != BMP_MODE_FLASH_WRITE) && + (opt->opt_mode != BMP_MODE_FLASH_WRITE) && (opt->opt_mode != BMP_MODE_FLASH_VERIFY) && - (opt->opt_mode != BMP_MODE_FLASH_VERIFY)) + (opt->opt_mode != BMP_MODE_FLASH_WRITE_VERIFY)) opt->opt_flash_size = lowest_flash_size; if (opt->opt_mode == BMP_MODE_SWJ_TEST) { switch (t->core[0]) { @@ -466,7 +477,7 @@ int cl_execute(BMP_CL_OPTIONS_t *opt) map.size = opt->opt_flash_size; if (opt->opt_mode == BMP_MODE_RESET) { target_reset(t); - } else if (opt->opt_mode == BMP_MODE_FLASH_ERASE) { + } else if (opt->opt_mode == BMP_MODE_FLASH_ERASE) { DEBUG_INFO("Erase %zu bytes at 0x%08" PRIx32 "\n", opt->opt_flash_size, opt->opt_flash_start); unsigned int erased = target_flash_erase(t, opt->opt_flash_start, diff --git a/src/platforms/pc/cl_utils.h b/src/platforms/pc/cl_utils.h index 4a0c1e20..ff43610d 100644 --- a/src/platforms/pc/cl_utils.h +++ b/src/platforms/pc/cl_utils.h @@ -30,6 +30,7 @@ enum bmp_cl_mode { BMP_MODE_DEBUG, BMP_MODE_TEST, BMP_MODE_RESET, + BMP_MODE_RESET_HW, BMP_MODE_FLASH_ERASE, BMP_MODE_FLASH_WRITE, BMP_MODE_FLASH_WRITE_VERIFY, diff --git a/src/platforms/stm32/blackpillv2.ld b/src/platforms/stm32/blackpillv2.ld new file mode 100644 index 00000000..4dbc774f --- /dev/null +++ b/src/platforms/stm32/blackpillv2.ld @@ -0,0 +1,28 @@ +/* + * This file is part of the libopenstm32 project. + * + * Copyright (C) 2010 Thomas Otto + * + * 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 . + */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 96K +} + +/* Include the common ld script from libopenstm32. */ +INCLUDE cortex-m-generic.ld diff --git a/src/platforms/stm32/dfucore.c b/src/platforms/stm32/dfucore.c index 3ddadb60..b94a1142 100644 --- a/src/platforms/stm32/dfucore.c +++ b/src/platforms/stm32/dfucore.c @@ -63,7 +63,7 @@ static struct { } prog; static uint8_t current_error; -const struct usb_device_descriptor dev = { +const struct usb_device_descriptor dev_desc = { .bLength = USB_DT_DEVICE_SIZE, .bDescriptorType = USB_DT_DEVICE, .bcdUSB = 0x0200, @@ -293,7 +293,7 @@ void dfu_init(const usbd_driver *driver) { get_dev_unique_id(serial_no); - usbdev = usbd_init(driver, &dev, &config, + usbdev = usbd_init(driver, &dev_desc, &config, usb_strings, 4, usbd_control_buffer, sizeof(usbd_control_buffer)); diff --git a/src/platforms/stm32/serialno.c b/src/platforms/stm32/serialno.c index 973dee16..a8b2898b 100644 --- a/src/platforms/stm32/serialno.c +++ b/src/platforms/stm32/serialno.c @@ -40,7 +40,7 @@ char *serial_no_read(char *s) uint16_t *uid = (uint16_t *)DESIG_UNIQUE_ID_BASE; # if defined(STM32F4) || defined(STM32F7) int offset = 3; -# elif defined(STM32L0) || defined(STM32F3) +# elif defined(STM32L0) || defined(STM32F0) || defined(STM32F3) int offset = 5; # endif sprintf(s, "%04X%04X%04X", diff --git a/src/platforms/stm32/timing_stm32.c b/src/platforms/stm32/timing_stm32.c index dbf5cc3a..9f9c6984 100644 --- a/src/platforms/stm32/timing_stm32.c +++ b/src/platforms/stm32/timing_stm32.c @@ -27,12 +27,14 @@ uint8_t running_status; static volatile uint32_t time_ms; uint32_t swd_delay_cnt = 0; +static int morse_tick; + void platform_timing_init(void) { /* Setup heartbeat timer */ systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); /* Interrupt us at 10 Hz */ - systick_set_reload(rcc_ahb_frequency / (8 * 10) ); + systick_set_reload(rcc_ahb_frequency / (8 * SYSTICKHZ) ); /* SYSTICK_IRQ with low priority */ nvic_set_priority(NVIC_SYSTICK_IRQ, 14 << 4); systick_interrupt_enable(); @@ -48,12 +50,16 @@ void platform_delay(uint32_t ms) void sys_tick_handler(void) { - if(running_status) - gpio_toggle(LED_PORT, LED_IDLE_RUN); + time_ms += SYSTICKMS; - time_ms += 100; - - SET_ERROR_STATE(morse_update()); + if (morse_tick >= MORSECNT) { + if(running_status) + gpio_toggle(LED_PORT, LED_IDLE_RUN); + SET_ERROR_STATE(morse_update()); + morse_tick = 0; + } else { + morse_tick++; + } } uint32_t platform_time_ms(void) diff --git a/src/platforms/stm32/usbuart.c b/src/platforms/stm32/usbuart.c index 8c04db7b..c7f4a1bd 100644 --- a/src/platforms/stm32/usbuart.c +++ b/src/platforms/stm32/usbuart.c @@ -50,8 +50,12 @@ #define TX_LED_ACT (1 << 0) #define RX_LED_ACT (1 << 1) -#define RX_FIFO_SIZE (128) -#define TX_BUF_SIZE (128) +/* F072 with st_usbfs_v2_usb_drive drops characters at the 64 byte boundary!*/ +#if !defined(USART_DMA_BUF_SIZE) +# define USART_DMA_BUF_SIZE 128 +#endif +#define RX_FIFO_SIZE (USART_DMA_BUF_SIZE) +#define TX_BUF_SIZE (USART_DMA_BUF_SIZE) /* TX double buffer */ static uint8_t buf_tx[TX_BUF_SIZE * 2]; @@ -164,11 +168,19 @@ void usbuart_init(void) /* Enable interrupts */ nvic_set_priority(USBUSART_IRQ, IRQ_PRI_USBUSART); +#if defined(USBUSART_DMA_RXTX_IRQ) + nvic_set_priority(USBUSART_DMA_RXTX_IRQ, IRQ_PRI_USBUSART_DMA); +#else nvic_set_priority(USBUSART_DMA_TX_IRQ, IRQ_PRI_USBUSART_DMA); nvic_set_priority(USBUSART_DMA_RX_IRQ, IRQ_PRI_USBUSART_DMA); +#endif nvic_enable_irq(USBUSART_IRQ); +#if defined(USBUSART_DMA_RXTX_IRQ) + nvic_enable_irq(USBUSART_DMA_RXTX_IRQ); +#else nvic_enable_irq(USBUSART_DMA_TX_IRQ); nvic_enable_irq(USBUSART_DMA_RX_IRQ); +#endif /* Finally enable the USART */ usart_enable(USBUSART); @@ -392,7 +404,11 @@ static void usbuart_run(void) void USBUSART_ISR(void) { +#if defined(USBUSART_DMA_RXTX_IRQ) + nvic_disable_irq(USBUSART_DMA_RXTX_IRQ); +#else nvic_disable_irq(USBUSART_DMA_RX_IRQ); +#endif /* Get IDLE flag and reset interrupt flags */ const bool isIdle = usart_get_flag(USBUSART, USART_FLAG_IDLE); @@ -409,7 +425,11 @@ void USBUSART_ISR(void) usbuart_run(); } +#if defined(USBUSART_DMA_RXTX_IRQ) + nvic_enable_irq(USBUSART_DMA_RXTX_IRQ); +#else nvic_enable_irq(USBUSART_DMA_RX_IRQ); +#endif } void USBUSART_DMA_TX_ISR(void) @@ -449,6 +469,16 @@ void USBUSART_DMA_RX_ISR(void) nvic_enable_irq(USBUSART_IRQ); } +#if defined(USBUSART_DMA_RXTX_ISR) +void USBUSART_DMA_RXTX_ISR(void) +{ + if (dma_get_interrupt_flag(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN, DMA_CGIF)) + USBUSART_DMA_RX_ISR(); + if (dma_get_interrupt_flag(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN, DMA_CGIF)) + USBUSART_DMA_TX_ISR(); +} +#endif + #ifdef ENABLE_DEBUG enum { RDI_SYS_OPEN = 0x01, diff --git a/src/remote.c b/src/remote.c index 691f1e9e..ea093212 100644 --- a/src/remote.c +++ b/src/remote.c @@ -144,6 +144,7 @@ void remotePacketProcessSWD(uint8_t i, char *packet) if (i==2) { remote_dp.dp_read = firmware_swdp_read; remote_dp.low_access = firmware_swdp_low_access; + remote_dp.abort = firmware_swdp_abort; swdptap_init(&remote_dp); _respond(REMOTE_RESP_OK, 0); } else { @@ -194,6 +195,7 @@ void remotePacketProcessJTAG(uint8_t i, char *packet) case REMOTE_INIT: /* JS = initialise ============================= */ remote_dp.dp_read = fw_adiv5_jtagdp_read; remote_dp.low_access = fw_adiv5_jtagdp_low_access; + remote_dp.abort = adiv5_jtagdp_abort; jtagtap_init(); _respond(REMOTE_RESP_OK, 0); break; @@ -226,7 +228,8 @@ void remotePacketProcessJTAG(uint8_t i, char *packet) jtag_proc.jtagtap_tdi_tdo_seq((void *)&DO, (packet[1]==REMOTE_TDITDO_TMS), (void *)&DI, ticks); /* Mask extra bits on return value... */ - DO &= (1LL << (ticks + 1)) - 1; + if (ticks < 64) + DO &= (1LL << ticks) - 1; _respond(REMOTE_RESP_OK, DO); } diff --git a/src/target/adiv5.c b/src/target/adiv5.c index 38c3c9f9..1994ea67 100644 --- a/src/target/adiv5.c +++ b/src/target/adiv5.c @@ -334,7 +334,7 @@ static bool cortexm_prepare(ADIv5_AP_t *ap) uint32_t dhcsr_ctl = CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN | CORTEXM_DHCSR_C_HALT; uint32_t dhcsr_valid = CORTEXM_DHCSR_S_HALT | CORTEXM_DHCSR_C_DEBUGEN; -#ifdef PLATFORM_HAS_DEBUG +#if defined(ENABLE_DEBUG) && defined(PLATFORM_HAS_DEBUG) uint32_t start_time = platform_time_ms(); #endif uint32_t dhcsr; @@ -414,16 +414,11 @@ static void adiv5_component_probe(ADIv5_AP_t *ap, uint32_t addr, int recursion, if (addr == 0) /* No rom table on this AP */ return; volatile uint32_t cidr; - volatile struct exception e; - TRY_CATCH (e, EXCEPTION_TIMEOUT) { - cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET); - } - if (e.type) { - DEBUG_WARN("CIDR read timeout on AP%d, aborting.\n", num_entry); - adiv5_dp_abort(ap->dp, ADIV5_DP_ABORT_DAPABORT); + cidr = adiv5_ap_read_id(ap, addr + CIDR0_OFFSET); + if (ap->dp->fault) { + DEBUG_WARN("CIDR read timeout on AP%d, aborting.\n", ap->apsel); return; } - if ((cidr & ~CID_CLASS_MASK) != CID_PREAMBLE) return; #if defined(ENABLE_DEBUG) @@ -603,6 +598,15 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel) if(!tmpap.idr) /* IDR Invalid */ return NULL; + tmpap.csw = adiv5_ap_read(&tmpap, ADIV5_AP_CSW) & + ~(ADIV5_AP_CSW_SIZE_MASK | ADIV5_AP_CSW_ADDRINC_MASK); + + if (tmpap.csw & ADIV5_AP_CSW_TRINPROG) { + DEBUG_WARN("AP %d: Transaction in progress. AP is not be usable!\n", + apsel); + return NULL; + } + /* It's valid to so create a heap copy */ ap = malloc(sizeof(*ap)); if (!ap) { /* malloc failed: heap exhaustion */ @@ -612,14 +616,6 @@ ADIv5_AP_t *adiv5_new_ap(ADIv5_DP_t *dp, uint8_t apsel) memcpy(ap, &tmpap, sizeof(*ap)); - ap->csw = adiv5_ap_read(ap, ADIV5_AP_CSW) & - ~(ADIV5_AP_CSW_SIZE_MASK | ADIV5_AP_CSW_ADDRINC_MASK); - - if (ap->csw & ADIV5_AP_CSW_TRINPROG) { - DEBUG_WARN("AP transaction in progress. Target may not be usable.\n"); - ap->csw &= ~ADIV5_AP_CSW_TRINPROG; - } - #if defined(ENABLE_DEBUG) uint32_t cfg = adiv5_ap_read(ap, ADIV5_AP_CFG); DEBUG_INFO("AP %3d: IDR=%08"PRIx32" CFG=%08"PRIx32" BASE=%08" PRIx32 diff --git a/src/target/adiv5.h b/src/target/adiv5.h index 1d2a2270..2c58d02b 100644 --- a/src/target/adiv5.h +++ b/src/target/adiv5.h @@ -88,19 +88,23 @@ #define ADIV5_AP_BASE ADIV5_AP_REG(0xF8) #define ADIV5_AP_IDR ADIV5_AP_REG(0xFC) -/* Known designers seen in SYSROM-PIDR. Ignore Bit 0 from - * the designer bits to get JEDEC Ids with bit 7 ignored.*/ +/* Known designers seen in SYSROM-PIDR and JTAG IDCode. + * Ignore Bit 0 from the designer bits to get JEDEC Ids. + * Should get it's one file as not only related to Adiv5! + */ #define AP_DESIGNER_FREESCALE 0x00e #define AP_DESIGNER_TEXAS 0x017 #define AP_DESIGNER_ATMEL 0x01f #define AP_DESIGNER_STM 0x020 #define AP_DESIGNER_CYPRESS 0x034 #define AP_DESIGNER_INFINEON 0x041 +#define DESIGNER_XILINX 0x049 #define AP_DESIGNER_NORDIC 0x244 #define AP_DESIGNER_ARM 0x43b /*LPC845 with designer 501. Strange!? */ #define AP_DESIGNER_SPECULAR 0x501 #define AP_DESIGNER_CS 0x555 +#define DESIGNER_XAMBALA 0x61e #define AP_DESIGNER_ENERGY_MICRO 0x673 #define AP_DESIGNER_GIGADEVICE 0x751 #define AP_DESIGNER_RASPBERRY 0x927 @@ -286,7 +290,7 @@ void adiv5_ap_ref(ADIv5_AP_t *ap); void adiv5_ap_unref(ADIv5_AP_t *ap); void platform_add_jtag_dev(const int dev_index, const jtag_dev_t *jtag_dev); -void adiv5_jtag_dp_handler(uint8_t jd_index, uint32_t j_idcode); +void adiv5_jtag_dp_handler(jtag_dev_t *jd); int platform_jtag_dp_init(ADIv5_DP_t *dp); int swdptap_init(ADIv5_DP_t *dp); @@ -310,4 +314,5 @@ uint32_t fw_adiv5_jtagdp_read(ADIv5_DP_t *dp, uint16_t addr); uint32_t firmware_swdp_error(ADIv5_DP_t *dp); void firmware_swdp_abort(ADIv5_DP_t *dp, uint32_t abort); +void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort); #endif diff --git a/src/target/adiv5_jtagdp.c b/src/target/adiv5_jtagdp.c index 11f11ed7..52737461 100644 --- a/src/target/adiv5_jtagdp.c +++ b/src/target/adiv5_jtagdp.c @@ -39,9 +39,7 @@ static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp); -static void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort); - -void adiv5_jtag_dp_handler(uint8_t jd_index, uint32_t j_idcode) +void adiv5_jtag_dp_handler(jtag_dev_t *jd) { ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); if (!dp) { /* calloc failed: heap exhaustion */ @@ -49,8 +47,8 @@ void adiv5_jtag_dp_handler(uint8_t jd_index, uint32_t j_idcode) return; } - dp->dp_jd_index = jd_index; - dp->idcode = j_idcode; + dp->dp_jd_index = jd->jd_dev; + dp->idcode = jd->jd_idcode; if ((PC_HOSTED == 0 ) || (!platform_jtag_dp_init(dp))) { dp->dp_read = fw_adiv5_jtagdp_read; dp->error = adiv5_jtagdp_error; @@ -87,23 +85,25 @@ uint32_t fw_adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, jtag_dev_write_ir(&jtag_proc, dp->dp_jd_index, APnDP ? IR_APACC : IR_DPACC); - platform_timeout_set(&timeout, 2000); + platform_timeout_set(&timeout, 20); do { jtag_dev_shift_dr(&jtag_proc, dp->dp_jd_index, (uint8_t*)&response, (uint8_t*)&request, 35); ack = response & 0x07; } while(!platform_timeout_is_expired(&timeout) && (ack == JTAGDP_ACK_WAIT)); - if (ack == JTAGDP_ACK_WAIT) - raise_exception(EXCEPTION_TIMEOUT, "JTAG-DP ACK timeout"); - + if (ack == JTAGDP_ACK_WAIT) { + dp->abort(dp, ADIV5_DP_ABORT_DAPABORT); + dp->fault = 1; + return 0; + } if((ack != JTAGDP_ACK_OK)) raise_exception(EXCEPTION_ERROR, "JTAG-DP invalid ACK"); return (uint32_t)(response >> 3); } -static void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort) +void adiv5_jtagdp_abort(ADIv5_DP_t *dp, uint32_t abort) { uint64_t request = (uint64_t)abort << 3; jtag_dev_write_ir(&jtag_proc, dp->dp_jd_index, IR_ABORT); diff --git a/src/target/adiv5_swdp.c b/src/target/adiv5_swdp.c index 6477c800..a148aab6 100644 --- a/src/target/adiv5_swdp.c +++ b/src/target/adiv5_swdp.c @@ -75,24 +75,18 @@ static bool firmware_dp_low_read(ADIv5_DP_t *dp, uint16_t addr, uint32_t *res) */ int adiv5_swdp_scan(uint32_t targetid) { - ADIv5_DP_t idp, *initial_dp = &idp; + ADIv5_DP_t idp = { + .dp_low_write = firmware_dp_low_write, + .dp_low_read = firmware_dp_low_read, + .error = firmware_swdp_error, + .dp_read = firmware_swdp_read, + .low_access = firmware_swdp_low_access, + .abort = firmware_swdp_abort, + }; + ADIv5_DP_t *initial_dp = &idp; target_list_free(); - memset(initial_dp, 0, sizeof(ADIv5_DP_t)); if (swdptap_init(initial_dp)) return -1; - /* Set defaults when no procedure given*/ - if (!initial_dp->dp_low_write) - initial_dp->dp_low_write = firmware_dp_low_write; - if (!initial_dp->dp_low_read) - initial_dp->dp_low_read = firmware_dp_low_read; - if (!initial_dp->error) - initial_dp->error = firmware_swdp_error; - if (!initial_dp->dp_read) - initial_dp->dp_read = firmware_swdp_read; - if (!initial_dp->error) - initial_dp->error = firmware_swdp_error; - if (!initial_dp->low_access) - initial_dp->low_access = firmware_swdp_low_access; /* DORMANT-> SWD sequence*/ initial_dp->seq_out(0xFFFFFFFF, 32); initial_dp->seq_out(0xFFFFFFFF, 32); @@ -125,14 +119,14 @@ int adiv5_swdp_scan(uint32_t targetid) initial_dp->seq_out(0xE79E, 16); /* 0b0111100111100111 */ dp_line_reset(initial_dp); initial_dp->fault = 0; - volatile struct exception e; - TRY_CATCH (e, EXCEPTION_ALL) { + volatile struct exception e2; + TRY_CATCH (e2, EXCEPTION_ALL) { idcode = initial_dp->low_access(initial_dp, ADIV5_LOW_READ, ADIV5_DP_IDCODE, 0); } - if (e.type) { + if (e2.type) { DEBUG_WARN("No usable DP found\n"); - return -1; + return 0; } } if ((idcode & ADIV5_DP_VERSION_MASK) == ADIV5_DPv2) { @@ -241,7 +235,7 @@ uint32_t firmware_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, if((addr & ADIV5_APnDP) && dp->fault) return 0; - platform_timeout_set(&timeout, 2000); + platform_timeout_set(&timeout, 20); do { dp->seq_out(request, 8); ack = dp->seq_in(3); @@ -251,8 +245,11 @@ uint32_t firmware_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, } } while (ack == SWDP_ACK_WAIT && !platform_timeout_is_expired(&timeout)); - if (ack == SWDP_ACK_WAIT) - raise_exception(EXCEPTION_TIMEOUT, "SWDP ACK timeout"); + if (ack == SWDP_ACK_WAIT) { + dp->abort(dp, ADIV5_DP_ABORT_DAPABORT); + dp->fault = 1; + return 0; + } if(ack == SWDP_ACK_FAULT) { dp->fault = 1; diff --git a/src/target/cortexm.c b/src/target/cortexm.c index 82e22b66..d0877b7e 100644 --- a/src/target/cortexm.c +++ b/src/target/cortexm.c @@ -526,7 +526,7 @@ bool cortexm_attach(target *t) platform_timeout timeout; platform_timeout_set(&timeout, 1000); while (1) { - uint32_t dhcsr = target_mem_read32(t, CORTEXM_DHCSR); + dhcsr = target_mem_read32(t, CORTEXM_DHCSR); if (!(dhcsr & CORTEXM_DHCSR_S_RESET_ST)) break; if (platform_timeout_is_expired(&timeout)) { @@ -572,8 +572,8 @@ static void cortexm_regs_read(target *t, void *data) for(i = 0; i < sizeof(regnum_cortex_m) / 4; i++) *regs++ = base_regs[regnum_cortex_m[i]]; if (t->target_options & TOPT_FLAVOUR_V7MF) - for(size_t t = 0; t < sizeof(regnum_cortex_mf) / 4; t++) - *regs++ = ap->dp->ap_reg_read(ap, regnum_cortex_mf[t]); + for(i = 0; i < sizeof(regnum_cortex_mf) / 4; i++) + *regs++ = ap->dp->ap_reg_read(ap, regnum_cortex_mf[i]); } #else if (0) {} diff --git a/src/target/efm32.c b/src/target/efm32.c index 547eadc8..4589c00b 100644 --- a/src/target/efm32.c +++ b/src/target/efm32.c @@ -979,11 +979,6 @@ const struct command_s efm32_aap_cmd_list[] = { {NULL, NULL, NULL} }; -static bool nop_function(void) -{ - return true; -} - /** * AAP Probe */ @@ -1019,17 +1014,7 @@ void efm32_aap_probe(ADIv5_AP_t *ap) "EFM32 Authentication Access Port rev.%d", aap_revision); t->driver = priv_storage->aap_driver_string; - t->attach = (void*)nop_function; - t->detach = (void*)nop_function; - t->check_error = (void*)nop_function; - t->mem_read = (void*)nop_function; - t->mem_write = (void*)nop_function; t->regs_size = 4; - t->regs_read = (void*)nop_function; - t->regs_write = (void*)nop_function; - t->reset = (void*)nop_function; - t->halt_request = (void*)nop_function; - t->halt_resume = (void*)nop_function; target_add_commands(t, efm32_aap_cmd_list, t->driver); } diff --git a/src/target/jtag_devs.h b/src/target/jtag_devs.h index 8c2c0b5a..8f877985 100644 --- a/src/target/jtag_devs.h +++ b/src/target/jtag_devs.h @@ -22,7 +22,7 @@ typedef const struct jtag_dev_descr_s { const uint32_t idcode; const uint32_t idmask; const char * const descr; - void (*const handler)(uint8_t jd_index, uint32_t j_idcode); + void (*const handler)(jtag_dev_t *jd); } jtag_dev_descr_t; extern jtag_dev_descr_t dev_descr[]; diff --git a/src/target/jtag_scan.c b/src/target/jtag_scan.c index 127f1ffd..eb1efc80 100644 --- a/src/target/jtag_scan.c +++ b/src/target/jtag_scan.c @@ -3,6 +3,7 @@ * * Copyright (C) 2011 Black Sphere Technologies Ltd. * Written by Gareth McMullin + * Copyright (C) 2021 Uwe Bonnes(bon@elektron.ikp.physik.tu-darmstadt.de) * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -25,16 +26,14 @@ #include "general.h" #include "jtagtap.h" -#include "jtag_scan.h" #include "target.h" #include "adiv5.h" -#include "jtag_devs.h" -struct jtag_dev_s jtag_devs[JTAG_MAX_DEVS+1]; +jtag_dev_t jtag_devs[JTAG_MAX_DEVS+1]; int jtag_dev_count; /* bucket of ones for don't care TDI */ -static const uint8_t ones[] = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; +static const uint8_t ones[] = {0xff, 0xFF, 0xFF, 0xFF}; #if PC_HOSTED == 0 void jtag_add_device(const int dev_index, const jtag_dev_t *jtag_dev) @@ -47,36 +46,32 @@ void jtag_add_device(const int dev_index, const jtag_dev_t *jtag_dev) #endif /* Scan JTAG chain for devices, store IR length and IDCODE (if present). - * Reset TAP state machine. - * Select Shift-IR state. - * Each device is assumed to shift out IR at 0x01. (this may not always be true) - * Shift in ones until we read two consecutive ones, then we have shifted out the - * IRs of all devices. * - * After this process all the IRs are loaded with the BYPASS command. - * Select Shift-DR state. - * Shift in ones and count zeros shifted out. Should be one for each device. - * Check this against device count obtained by IR scan above. + * https://www.fpga4fun.com/JTAG3.html + * Count the number of devices in the JTAG chain + * + * shift enough ones in IR + * shift enough zeros in DR + * Now shift out ones and stop if first '1' is seen. This gets the number + * of devices + * + * Assume max 32 devices with max IR len 16 = 512 bits = 16 loops * 32 bit * * Reset the TAP state machine again. This should load all IRs with IDCODE. - * For each device, shift out one bit. If this is zero IDCODE isn't present, - * continue to next device. If this is one shift out the remaining 31 bits - * of the IDCODE register. - */ + * Read 32 bit IDCODE for all devices. + */ + int jtag_scan(const uint8_t *irlens) { int i; - uint32_t j; - + void (*jd_handlers[JTAG_MAX_DEVS])(jtag_dev_t *jd); target_list_free(); - jtag_dev_count = 0; - memset(&jtag_devs, 0, sizeof(jtag_devs)); + memset(jd_handlers, 0, sizeof(jd_handlers)); - /* Run throught the SWD to JTAG sequence for the case where an attached SWJ-DP is - * in SW-DP mode. + /* Run throught the SWD to JTAG sequence for the case where an + * attached SWJ-DP is in SW-DP mode. */ - DEBUG_INFO("Resetting TAP\n"); #if PC_HOSTED == 1 if (platform_jtagtap_init()) { DEBUG_WARN("JTAG not available\n"); @@ -86,139 +81,146 @@ int jtag_scan(const uint8_t *irlens) jtagtap_init(); #endif jtag_proc.jtagtap_reset(); - - if (irlens) { - DEBUG_WARN("Given list of IR lengths, skipping probe\n"); - DEBUG_INFO("Change state to Shift-IR\n"); - jtagtap_shift_ir(); - j = 0; - while((jtag_dev_count <= JTAG_MAX_DEVS) && - (jtag_devs[jtag_dev_count].ir_len <= JTAG_MAX_IR_LEN)) { - uint32_t irout; - if(*irlens == 0) - break; - jtag_proc.jtagtap_tdi_tdo_seq((uint8_t*)&irout, 0, ones, *irlens); - if (!(irout & 1)) { - DEBUG_WARN("check failed: IR[0] != 1\n"); - return -1; - } - jtag_devs[jtag_dev_count].ir_len = *irlens; - jtag_devs[jtag_dev_count].ir_prescan = j; - jtag_devs[jtag_dev_count].jd_dev = jtag_dev_count; - j += *irlens; - irlens++; - jtag_dev_count++; - } - } else { - DEBUG_INFO("Change state to Shift-IR\n"); - jtagtap_shift_ir(); - - DEBUG_INFO("Scanning out IRs\n"); - if(!jtag_proc.jtagtap_next(0, 1)) { - DEBUG_WARN("jtag_scan: Sanity check failed: IR[0] shifted out " - "as 0\n"); - jtag_dev_count = -1; - return -1; /* must be 1 */ - } - jtag_devs[0].ir_len = 1; j = 1; - while((jtag_dev_count <= JTAG_MAX_DEVS) && - (jtag_devs[jtag_dev_count].ir_len <= JTAG_MAX_IR_LEN)) { - if(jtag_proc.jtagtap_next(0, 1)) { - if(jtag_devs[jtag_dev_count].ir_len == 1) break; - jtag_devs[++jtag_dev_count].ir_len = 1; - jtag_devs[jtag_dev_count].ir_prescan = j; - jtag_devs[jtag_dev_count].jd_dev = jtag_dev_count; - } else jtag_devs[jtag_dev_count].ir_len++; - j++; - } - if(jtag_dev_count > JTAG_MAX_DEVS) { - DEBUG_WARN("jtag_scan: Maximum device count exceeded\n"); - jtag_dev_count = -1; - return -1; - } - if(jtag_devs[jtag_dev_count].ir_len > JTAG_MAX_IR_LEN) { - DEBUG_WARN("jtag_scan: Maximum IR length exceeded\n"); - jtag_dev_count = -1; - return -1; - } +#define LOOPS 16 + jtagtap_shift_ir(); + i = LOOPS; + uint8_t ir_chain[64], *din = ir_chain; + while (i--) { + jtag_proc.jtagtap_tdi_tdo_seq(din, (i == 0) ? 1 : 0, ones, + sizeof(ones) * 8); + din += sizeof(ones); } - - DEBUG_INFO("Return to Run-Test/Idle\n"); - jtag_proc.jtagtap_next(1, 1); - jtagtap_return_idle(); - - /* All devices should be in BYPASS now */ - - /* Count device on chain */ - DEBUG_INFO("Change state to Shift-DR\n"); - jtagtap_shift_dr(); - for(i = 0; (jtag_proc.jtagtap_next(0, 1) == 0) && (i <= jtag_dev_count); i++) - jtag_devs[i].dr_postscan = jtag_dev_count - i - 1; - - if(i != jtag_dev_count) { - DEBUG_WARN("jtag_scan: Sanity check failed: " - "BYPASS dev count doesn't match IR scan\n"); - jtag_dev_count = -1; - return -1; - } - - DEBUG_INFO("Return to Run-Test/Idle\n"); - jtag_proc.jtagtap_next(1, 1); - jtagtap_return_idle(); - if(!jtag_dev_count) { + if (!(ir_chain[0] & 1)) { + DEBUG_WARN("Unexpected IR chain!\n"); return 0; } - - /* Fill in the ir_postscan fields */ - for(i = jtag_dev_count - 1; i; i--) - jtag_devs[i-1].ir_postscan = jtag_devs[i].ir_postscan + - jtag_devs[i].ir_len; - - /* Reset jtagtap: should take all devs to IDCODE */ + jtagtap_return_idle(); + jtagtap_shift_dr(); + i = LOOPS; + uint8_t zeros[] = {0, 0, 0, 0}; + while(i--) { + jtag_proc.jtagtap_tdi_seq(0, zeros, sizeof(zeros) * 8); + } + int num_devices = 0; + while (!jtag_proc.jtagtap_next(0,1) && (i++ < 6)) + num_devices++; jtag_proc.jtagtap_reset(); jtagtap_shift_dr(); - for(i = 0; i < jtag_dev_count; i++) { - if(!jtag_proc.jtagtap_next(0, 1)) continue; - jtag_devs[i].jd_idcode = 1; - for(j = 2; j; j <<= 1) - if(jtag_proc.jtagtap_next(0, 1)) jtag_devs[i].jd_idcode |= j; - + jtag_dev_count = num_devices; + if (!num_devices) + return 0; + DEBUG_TARGET("Found %d devices\n", num_devices); + int irbit = 1; + int j = 0; + for (i = 0; i < num_devices; i++) { + uint8_t id[4]; + jtag_proc.jtagtap_tdi_tdo_seq(id, 0, ones, 32); + if (!(id[0] & 1)) { + DEBUG_WARN("Invalid IDCode!\n"); + return 0; + } + uint32_t idcode = id[3] << 24 | id[2] << 16 | id[1] << 8 | id[0]; + unsigned int designer = ((id[1] & 0xf) << 8) | (id[0] >> 1); + unsigned int product = id[2] | ((id[3] & 0xf) << 8); + unsigned int expected_irlen = 0; + switch (designer) { + case AP_DESIGNER_ARM: + switch (product) { + case 0xba0: + jtag_devs[i].jd_descr = "ADIv5 JTAG-DP port"; + jd_handlers[i] = adiv5_jtag_dp_handler; + expected_irlen = 4; + break; + default: + jtag_devs[i].jd_descr = "ARM"; + } + break; + case AP_DESIGNER_STM: + expected_irlen = 5; + jtag_devs[i].jd_descr = "STM32 BSD"; + break; + case AP_DESIGNER_ATMEL: + if ((product >= 0x940) & (product < 0x990)) { + jtag_devs[i].jd_descr = "ATMEL AVR8"; + expected_irlen = 4; + break; + } + jtag_devs[i].jd_descr = "ATMEL"; + break; + case DESIGNER_XILINX: + if (!irlens) { + /* Guessed irlen for XILINX devices is wrong. + * IR data contains status bits! + */ + DEBUG_WARN("Please provide irlens as chain contains XILINX devices!\n"); + return 0; + } + jtag_devs[i].jd_descr = "XILINX"; + break; + case DESIGNER_XAMBALA: + expected_irlen = 5; + jtag_devs[i].jd_descr = "RVDBG013"; + break; + case AP_DESIGNER_GIGADEVICE: + expected_irlen = 5; + jtag_devs[i].jd_descr = "GIGADEVICE BSD"; + break; + } + if (!jtag_devs[i].jd_descr) { + DEBUG_WARN("Unhandled designer %x\n", designer); + jtag_devs[i].jd_descr = "Unknow"; + } + bool bit; + int guessed_irlen = 0; + int advance = irbit; + do { + /* Guess IR length from the IR scan after JTAG Reset + * First bit should be '1', following bits are '0', if not used + * for instruction capture, as for Xilinx parts. + */ + bit = (ir_chain[advance / 8] & (1 << (advance & 7))); + guessed_irlen++; + advance++; + } while (!bit && (advance < (JTAG_MAX_DEVS * 16))); + if (irlens) { /* Allow to overwrite from the command line!*/ + if (*irlens != guessed_irlen) { + DEBUG_TARGET("Provides irlen %d vs guessed %d for device %d\n", + *irlens, guessed_irlen, i + 1); + } + expected_irlen = *irlens++; + } + if (!expected_irlen) { + expected_irlen = guessed_irlen++; + } + jtag_devs[i].ir_len = expected_irlen; + jtag_devs[i].ir_prescan = j; + jtag_devs[i].jd_dev = i; + jtag_devs[i].jd_idcode = idcode; + jtag_devs[i].dr_postscan = jtag_dev_count - i - 1; + jtag_devs[i].current_ir = -1; + j += expected_irlen; + irbit += expected_irlen; + DEBUG_INFO("%2d: IDCODE: 0x%08" PRIx32 ", IR len %d %s%s\n", i + 1, + idcode,jtag_devs[i].ir_len, jtag_devs[i].jd_descr, + (jd_handlers[i]) ? "" : " (Unhandled) "); + } + jtag_proc.jtagtap_reset(); + /* Fill in the ir_postscan fields */ + for(i = jtag_dev_count - 1; i; i--) { + jtag_devs[i-1].ir_postscan = jtag_devs[i].ir_postscan + + jtag_devs[i].ir_len; } - DEBUG_INFO("Return to Run-Test/Idle\n"); - jtag_proc.jtagtap_next(1, 1); - jtagtap_return_idle(); #if PC_HOSTED == 1 /*Transfer needed device information to firmware jtag_devs*/ - for(i = 0; i < jtag_dev_count; i++) - platform_add_jtag_dev(i, &jtag_devs[i]); for(i = 0; i < jtag_dev_count; i++) { - DEBUG_INFO("Idcode 0x%08" PRIx32, jtag_devs[i].jd_idcode); - for(j = 0; dev_descr[j].idcode; j++) { - if((jtag_devs[i].jd_idcode & dev_descr[j].idmask) == - dev_descr[j].idcode) { - DEBUG_INFO(": %s", - (dev_descr[j].descr) ? dev_descr[j].descr : "unknown"); - break; - } - } - DEBUG_INFO("\n"); + platform_add_jtag_dev(i, &jtag_devs[i]); } #endif - /* Check for known devices and handle accordingly */ for(i = 0; i < jtag_dev_count; i++) - for(j = 0; dev_descr[j].idcode; j++) - if((jtag_devs[i].jd_idcode & dev_descr[j].idmask) == - dev_descr[j].idcode) { - jtag_devs[i].current_ir = -1; - /* Save description in table */ - jtag_devs[i].jd_descr = dev_descr[j].descr; - /* Call handler to initialise/probe device further */ - if(dev_descr[j].handler) - dev_descr[j].handler(i, dev_descr[j].idcode); - break; - } - + /* Call handler to initialise/probe device further */ + if (jd_handlers[i]) + jd_handlers[i](&jtag_devs[i]); return jtag_dev_count; } diff --git a/src/target/jtag_scan.h b/src/target/jtag_scan.h index cc6d361a..bc76e0bc 100644 --- a/src/target/jtag_scan.h +++ b/src/target/jtag_scan.h @@ -40,7 +40,7 @@ typedef struct jtag_dev_s { uint32_t current_ir; } jtag_dev_t; -extern struct jtag_dev_s jtag_devs[JTAG_MAX_DEVS+1]; +extern jtag_dev_t jtag_devs[JTAG_MAX_DEVS+1]; extern int jtag_dev_count; void jtag_dev_write_ir(jtag_proc_t *jp, uint8_t jd_index, uint32_t ir); diff --git a/src/target/lpc11xx.c b/src/target/lpc11xx.c index 5b12e1c6..e8012ea4 100644 --- a/src/target/lpc11xx.c +++ b/src/target/lpc11xx.c @@ -90,40 +90,55 @@ lpc11xx_probe(target *t) uint32_t idcode; /* read the device ID register */ - /* See UM10462 Rev. 5.5 Chapter 20.13.11 Table 377 */ + /* For LPC11xx & LPC11Cxx see UM10398 Rev. 12.4 Chapter 26.5.11 Table 387 + * For LPC11Uxx see UM10462 Rev. 5.5 Chapter 20.13.11 Table 377 + * Nota Bene: the DEVICE_ID register at address 0x400483F4 is not valid + * for: + * 1) the LPC11xx & LPC11Cxx "XL" series, see UM10398 Rev.12.4 Chapter 3.1 + * 2) the LPC11U3x series, see UM10462 Rev.5.5 Chapter 3.1 + * But see the comment for the LPC8xx series below. + */ idcode = target_mem_read32(t, LPC11XX_DEVICE_ID); switch (idcode) { - case 0x041E502B: - case 0x2516D02B: - case 0x0416502B: - case 0x2516902B: /* lpc1111 */ - case 0x2524D02B: - case 0x0425502B: - case 0x2524902B: - case 0x1421102B: /* lpc1112 */ - case 0x0434502B: - case 0x2532902B: - case 0x0434102B: - case 0x2532102B: /* lpc1113 */ - case 0x0444502B: - case 0x2540902B: - case 0x0444102B: - case 0x2540102B: - case 0x1440102B: /* lpc1114 */ - case 0x0A40902B: - case 0x1A40902B: - case 0x00050080: /* lpc1115 and lpc1115L (not the XL version. See UM10398 Rev12.4 Chapter 3.1 ) */ - case 0x1431102B: /* lpc11c22 */ - case 0x1430102B: /* lpc11c24 */ - case 0x095C802B: /* lpc11u12x/201 */ - case 0x295C802B: - case 0x097A802B: /* lpc11u13/201 */ - case 0x297A802B: - case 0x0998802B: /* lpc11u14x/201 */ - case 0x2998802B: - case 0x2972402B: /* lpc11u23/301 */ - case 0x2988402B: /* lpc11u24x/301 */ - case 0x2980002B: /* lpc11u24x/401 */ + case 0x0A07102B: /* LPC1110 - 4K Flash 1K SRAM */ + case 0x1A07102B: /* LPC1110 - 4K Flash 1K SRAM */ + case 0x0A16D02B: /* LPC1111/002 - 8K Flash 2K SRAM */ + case 0x1A16D02B: /* LPC1111/002 - 8K Flash 2K SRAM */ + case 0x041E502B: /* LPC1111/101 - 8K Flash 2K SRAM */ + case 0x2516D02B: /* LPC1111/101/102 - 8K Flash 2K SRAM */ + case 0x0416502B: /* LPC1111/201 - 8K Flash 4K SRAM */ + case 0x2516902B: /* LPC1111/201/202 - 8K Flash 4K SRAM */ + case 0x0A23902B: /* LPC1112/102 - 16K Flash 4K SRAM */ + case 0x1A23902B: /* LPC1112/102 - 16K Flash 4K SRAM */ + case 0x042D502B: /* LPC1112/101 - 16K Flash 2K SRAM */ + case 0x2524D02B: /* LPC1112/101/102 - 16K Flash 2K SRAM */ + case 0x0425502B: /* LPC1112/201 - 16K Flash 4K SRAM */ + case 0x2524902B: /* LPC1112/201/202 - 16K Flash 4K SRAM */ + case 0x0434502B: /* LPC1113/201 - 24K Flash 4K SRAM */ + case 0x2532902B: /* LPC1113/201/202 - 24K Flash 4K SRAM */ + case 0x0434102B: /* LPC1113/301 - 24K Flash 8K SRAM */ + case 0x2532102B: /* LPC1113/301/302 - 24K Flash 8K SRAM */ + case 0x0A40902B: /* LPC1114/102 - 32K Flash 4K SRAM */ + case 0x1A40902B: /* LPC1114/102 - 32K Flash 4K SRAM */ + case 0x0444502B: /* LPC1114/201 - 32K Flash 4K SRAM */ + case 0x2540902B: /* LPC1114/201/202 - 32K Flash 4K SRAM */ + case 0x0444102B: /* LPC1114/301 - 32K Flash 8K SRAM */ + case 0x2540102B: /* LPC1114/301/302 & LPC11D14/302 - 32K Flash 8K SRAM */ + case 0x00050080: /* LPC1115/303 - 64K Flash 8K SRAM (redundant? see UM10398, XL has Device ID at different address) */ + case 0x1421102B: /* LPC11c12/301 - 16K Flash 8K SRAM */ + case 0x1440102B: /* LPC11c14/301 - 32K Flash 8K SRAM */ + case 0x1431102B: /* LPC11c22/301 - 16K Flash 8K SRAM */ + case 0x1430102B: /* LPC11c24/301 - 32K Flash 8K SRAM */ + case 0x095C802B: /* LPC11u12x/201 - 16K Flash 4K SRAM */ + case 0x295C802B: /* LPC11u12x/201 - 16K Flash 4K SRAM */ + case 0x097A802B: /* LPC11u13/201 - 24K Flash 4K SRAM */ + case 0x297A802B: /* LPC11u13/201 - 24K Flash 4K SRAM */ + case 0x0998802B: /* LPC11u14/201 - 32K Flash 4K SRAM */ + case 0x2998802B: /* LPC11u14/201 - 32K Flash 4K SRAM */ + case 0x2954402B: /* LPC11u22/301 - 16K Flash 6K SRAM */ + case 0x2972402B: /* LPC11u23/301 - 24K Flash 6K SRAM */ + case 0x2988402B: /* LPC11u24x/301 - 32K Flash 6K SRAM */ + case 0x2980002B: /* LPC11u24x/401 - 32K Flash 8K SRAM */ t->driver = "LPC11xx"; target_add_ram(t, 0x10000000, 0x2000); lpc11xx_add_flash(t, 0x00000000, 0x20000, 0x1000, IAP_ENTRY_MOST, 0); @@ -152,7 +167,7 @@ lpc11xx_probe(target *t) target_add_ram(t, 0x10000000, 0x2000); /* UM11074/ Flash controller/15.2: The two topmost sectors * contain the initialization code and IAP firmware. - * Do not touch the! */ + * Do not touch them! */ lpc11xx_add_flash(t, 0x00000000, 0x7800, 0x400, IAP_ENTRY_MOST, 0); target_add_commands(t, lpc11xx_cmd_list, "LPC8N04"); return true; @@ -160,91 +175,115 @@ lpc11xx_probe(target *t) if ((t->t_designer != AP_DESIGNER_SPECULAR) && idcode) { DEBUG_INFO("LPC11xx: Unknown IDCODE 0x%08" PRIx32 "\n", idcode); } + /* For LPC802, see UM11045 Rev. 1.4 Chapter 6.6.29 Table 84 + * For LPC804, see UM11065 Rev. 1.0 Chapter 6.6.31 Table 87 + * For LPC81x, see UM10601 Rev. 1.6 Chapter 4.6.33 Table 50 + * For LPC82x, see UM10800 Rev. 1.2 Chapter 5.6.34 Table 55 + * For LPC83x, see UM11021 Rev. 1.1 Chapter 5.6.34 Table 53 + * For LPC84x, see UM11029 Rev. 1.4 Chapter 8.6.49 Table 174 + * + * Not documented, but the DEVICE_ID register at address 0x400483F8 + * for the LPC8xx series is also valid for the LPC11xx "XL" and the + * LPC11U3x variants. + */ idcode = target_mem_read32(t, LPC8XX_DEVICE_ID); switch (idcode) { - case 0x00008021: /* 802M001JDH20 */ - case 0x00008022: /* 802M011JDH20 */ - case 0x00008023: /* 802M001JDH16 */ - case 0x00008024: /* 802M001JHI33 */ + case 0x00008021: /* LPC802M001JDH20 - 16K Flash 2K SRAM */ + case 0x00008022: /* LPC802M011JDH20 */ + case 0x00008023: /* LPC802M001JDH16 */ + case 0x00008024: /* LPC802M001JHI33 */ t->driver = "LPC802"; target_add_ram(t, 0x10000000, 0x800); lpc11xx_add_flash(t, 0x00000000, 0x4000, 0x400, IAP_ENTRY_84x, 2); target_add_commands(t, lpc11xx_cmd_list, "LPC802"); return true; - case 0x00008040: /* 804M101JBD64 */ - case 0x00008041: /* 804M101JDH20 */ - case 0x00008042: /* 804M101JDH24 */ - case 0x00008043: /* 804M111JDH24 */ - case 0x00008044: /* 804M101JHI33 */ + case 0x00008040: /* LPC804M101JBD64 - 32K Flash 4K SRAM */ + case 0x00008041: /* LPC804M101JDH20 */ + case 0x00008042: /* LPC804M101JDH24 */ + case 0x00008043: /* LPC804M111JDH24 */ + case 0x00008044: /* LPC804M101JHI33 */ t->driver = "LPC804"; target_add_ram(t, 0x10000000, 0x1000); lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x400, IAP_ENTRY_84x, 2); target_add_commands(t, lpc11xx_cmd_list, "LPC804"); return true; - case 0x00008100: /* LPC810M021FN8 */ - case 0x00008110: /* LPC811M001JDH16 */ - case 0x00008120: /* LPC812M101JDH16 */ - case 0x00008121: /* LPC812M101JD20 */ - case 0x00008122: /* LPC812M101JDH20 / LPC812M101JTB16 */ + case 0x00008100: /* LPC810M021FN8 - 4K Flash 1K SRAM */ + case 0x00008110: /* LPC811M001JDH16 - 8K Flash 2K SRAM */ + case 0x00008120: /* LPC812M101JDH16 - 16K Flash 4K SRAM */ + case 0x00008121: /* LPC812M101JD20 - 16K Flash 4K SRAM */ + case 0x00008122: /* LPC812M101JDH20 / LPC812M101JTB16 - 16K Flash 4K SRAM */ t->driver = "LPC81x"; target_add_ram(t, 0x10000000, 0x1000); lpc11xx_add_flash(t, 0x00000000, 0x4000, 0x400, IAP_ENTRY_MOST, 0); target_add_commands(t, lpc11xx_cmd_list, "LPC81x"); return true; - case 0x00008221: /* LPC822M101JHI33 */ - case 0x00008222: /* LPC822M101JDH20 */ - case 0x00008241: /* LPC824M201JHI33 */ - case 0x00008242: /* LPC824M201JDH20 */ + case 0x00008221: /* LPC822M101JHI33 - 16K Flash 4K SRAM */ + case 0x00008222: /* LPC822M101JDH20 */ + case 0x00008241: /* LPC824M201JHI33 - 32K Flash 8K SRAM */ + case 0x00008242: /* LPC824M201JDH20 */ t->driver = "LPC82x"; target_add_ram(t, 0x10000000, 0x2000); lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x400, IAP_ENTRY_MOST, 0); target_add_commands(t, lpc11xx_cmd_list, "LPC82x"); return true; - case 0x00008322: /* LPC832M101FDH20 */ + case 0x00008322: /* LPC832M101FDH20 - 16K Flash 4K SRAM */ t->driver = "LPC832"; target_add_ram(t, 0x10000000, 0x1000); lpc11xx_add_flash(t, 0x00000000, 0x4000, 0x400, IAP_ENTRY_MOST, 0); target_add_commands(t, lpc11xx_cmd_list, "LPC832"); return true; - case 0x00008341: /* LPC8341201FHI33 */ + case 0x00008341: /* LPC834M101FHI33 - 32K Flash 4K SRAM */ t->driver = "LPC834"; target_add_ram(t, 0x10000000, 0x1000); lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x400, IAP_ENTRY_MOST, 0); target_add_commands(t, lpc11xx_cmd_list, "LPC834"); return true; - case 0x00008441: - case 0x00008442: - case 0x00008443: /* UM11029 Rev.1.4 list 8442 */ - case 0x00008444: + case 0x00008441: /* LPC844M201JBD64 - 64K Flash 8K SRAM */ + case 0x00008442: /* LPC844M201JBD48 */ + case 0x00008443: /* LPC844M201JHI48, note UM11029 Rev.1.4 table 29 is wrong, see table 174 (in same manual) */ + case 0x00008444: /* LPC844M201JHI33 */ t->driver = "LPC844"; target_add_ram(t, 0x10000000, 0x2000); lpc11xx_add_flash(t, 0x00000000, 0x10000, 0x400, IAP_ENTRY_84x, 0); + target_add_commands(t, lpc11xx_cmd_list, "LPC844"); return true; - case 0x00008451: - case 0x00008452: - case 0x00008453: - case 0x00008454: + case 0x00008451: /* LPC845M301JBD64 - 64K Flash 16K SRAM */ + case 0x00008452: /* LPC845M301JBD48 */ + case 0x00008453: /* LPC845M301JHI48 */ + case 0x00008454: /* LPC845M301JHI33 */ t->driver = "LPC845"; target_add_ram(t, 0x10000000, 0x4000); lpc11xx_add_flash(t, 0x00000000, 0x10000, 0x400, IAP_ENTRY_84x, 0); + target_add_commands(t, lpc11xx_cmd_list, "LPC845"); return true; - case 0x0003D440: /* LPC11U34/311 */ - case 0x0001cc40: /* LPC11U34/421 */ - case 0x0001BC40: /* LPC11U35/401 */ - case 0x0000BC40: /* LPC11U35/501 */ - case 0x00019C40: /* LPC11U36/401 */ - case 0x00017C40: /* LPC11U37FBD48/401 */ - case 0x00007C44: /* LPC11U37HFBD64/401 */ - case 0x00007C40: /* LPC11U37FBD64/501 */ + case 0x0003D440: /* LPC11U34/311 - 40K Flash 8K SRAM */ + case 0x0001cc40: /* LPC11U34/421 - 48K Flash 8K SRAM */ + case 0x0001BC40: /* LPC11U35/401 - 64K Flash 8K SRAM */ + case 0x0000BC40: /* LPC11U35/501 - 64K Flash 8K SRAM */ + case 0x00019C40: /* LPC11U36/401 - 96K Flash 8K SRAM */ + case 0x00017C40: /* LPC11U37FBD48/401 - 128K Flash 8K SRAM */ + case 0x00007C44: /* LPC11U37HFBD64/401 */ + case 0x00007C40: /* LPC11U37FBD64/501 */ t->driver = "LPC11U3x"; target_add_ram(t, 0x10000000, 0x2000); lpc11xx_add_flash(t, 0x00000000, 0x20000, 0x1000, IAP_ENTRY_MOST, 0); + target_add_commands(t, lpc11xx_cmd_list, "LPC11U3x"); return true; - case 0x00040070: /* LPC1114/333 */ - case 0x00050080: /* lpc1115XL */ - t->driver = "LPC1100XL"; + case 0x00010013: /* LPC1111/103 - 8K Flash 2K SRAM */ + case 0x00010012: /* LPC1111/203 - 8K Flash 4K SRAM */ + case 0x00020023: /* LPC1112/103 - 16K Flash 2K SRAM */ + case 0x00020022: /* LPC1112/203 - 16K Flash 4K SRAM */ + case 0x00030030: /* LPC1113/303 - 24K Flash 8K SRAM */ + case 0x00030032: /* LPC1113/203 - 24K Flash 4K SRAM */ + case 0x00040040: /* LPC1114/303 - 32K Flash 8K SRAM */ + case 0x00040042: /* LPC1114/203 - 32K Flash 4K SRAM */ + case 0x00040060: /* LPC1114/323 - 48K Flash 8K SRAM */ + case 0x00040070: /* LPC1114/333 - 56K Flash 8K SRAM */ + case 0x00050080: /* LPC1115/303 - 64K Flash 8K SRAM */ + t->driver = "LPC11xx-XL"; target_add_ram(t, 0x10000000, 0x2000); lpc11xx_add_flash(t, 0x00000000, 0x20000, 0x1000, IAP_ENTRY_MOST, 0); + target_add_commands(t, lpc11xx_cmd_list, "LPC11xx-XL"); return true; } if (idcode) { diff --git a/src/target/lpc_common.c b/src/target/lpc_common.c index 7b6b2efc..f70c0d6e 100644 --- a/src/target/lpc_common.c +++ b/src/target/lpc_common.c @@ -184,7 +184,7 @@ int lpc_flash_erase(struct target_flash *tf, target_addr addr, size_t len) if (f->reserved_pages && ((addr + len) >= tf->length - 0x400) ) { last_full_sector -= 1; } - if (start >= last_full_sector) { + if (start <= last_full_sector) { /* Sector erase */ if (lpc_iap_call(f, NULL, IAP_CMD_ERASE, start, last_full_sector, CPU_CLK_KHZ, f->bank)) return -2; diff --git a/src/target/nrf51.c b/src/target/nrf51.c index 038e8a8b..4021c0a9 100644 --- a/src/target/nrf51.c +++ b/src/target/nrf51.c @@ -31,6 +31,7 @@ static int nrf51_flash_write(struct target_flash *f, target_addr dest, const void *src, size_t len); static bool nrf51_cmd_erase_all(target *t, int argc, const char **argv); +static bool nrf51_cmd_erase_uicr(target *t, int argc, const char **argv); static bool nrf51_cmd_read_hwid(target *t, int argc, const char **argv); static bool nrf51_cmd_read_fwid(target *t, int argc, const char **argv); static bool nrf51_cmd_read_deviceid(target *t, int argc, const char **argv); @@ -41,6 +42,7 @@ static bool nrf51_cmd_read(target *t, int argc, const char **argv); const struct command_s nrf51_cmd_list[] = { {"erase_mass", (cmd_handler)nrf51_cmd_erase_all, "Erase entire flash memory"}, + {"erase_uicr", (cmd_handler)nrf51_cmd_erase_uicr, "Erase UICR registers"}, {"read", (cmd_handler)nrf51_cmd_read, "Read device parameters"}, {NULL, NULL, NULL} }; @@ -244,6 +246,31 @@ static bool nrf51_cmd_erase_all(target *t, int argc, const char **argv) return true; } +static bool nrf51_cmd_erase_uicr(target *t, int argc, const char **argv) +{ + (void)argc; + (void)argv; + tc_printf(t, "erase..\n"); + + /* Enable erase */ + target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN); + + /* Poll for NVMC_READY */ + while (target_mem_read32(t, NRF51_NVMC_READY) == 0) + if(target_check_error(t)) + return false; + + /* Erase UICR */ + target_mem_write32(t, NRF51_NVMC_ERASEUICR, 1); + + /* Poll for NVMC_READY */ + while (target_mem_read32(t, NRF51_NVMC_READY) == 0) + if(target_check_error(t)) + return false; + + return true; +} + static bool nrf51_cmd_read_hwid(target *t, int argc, const char **argv) { (void)argc; diff --git a/src/target/sam3x.c b/src/target/sam3x.c index c869d722..4a1ba08b 100644 --- a/src/target/sam3x.c +++ b/src/target/sam3x.c @@ -248,7 +248,7 @@ bool sam3x_probe(target *t) case CHIPID_CIDR_ARCH_SAM4SDC | CHIPID_CIDR_EPROC_CM4: t->driver = "Atmel SAM4S"; target_add_ram(t, 0x20000000, 0x400000); - size_t size = sam_flash_size(cidr); + size = sam_flash_size(cidr); if (size <= 0x80000) { /* Smaller devices have a single bank */ sam4_add_flash(t, SAM4S_EEFC_BASE(0), 0x400000, size); diff --git a/src/target/stm32f1.c b/src/target/stm32f1.c index a0ade734..3bc728fd 100644 --- a/src/target/stm32f1.c +++ b/src/target/stm32f1.c @@ -386,7 +386,7 @@ static bool stm32f1_cmd_erase_mass(target *t, int argc, const char **argv) if(target_check_error(t)) return false; /* Check for error */ - uint16_t sr = target_mem_read32(t, FLASH_SR + FLASH_BANK2_OFFSET); + sr = target_mem_read32(t, FLASH_SR + FLASH_BANK2_OFFSET); if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP)) return false; } diff --git a/src/target/stm32f4.c b/src/target/stm32f4.c index 148497c1..bc32cc22 100644 --- a/src/target/stm32f4.c +++ b/src/target/stm32f4.c @@ -384,9 +384,9 @@ static int stm32f4_flash_erase(struct target_flash *f, target_addr addr, stm32f4_flash_unlock(t); enum align psize = ALIGN_WORD; - for (struct target_flash *f = t->flash; f; f = f->next) { - if (f->write == stm32f4_flash_write) { - psize = ((struct stm32f4_flash *)f)->psize; + for (struct target_flash *currf = t->flash; currf; currf = currf->next) { + if (currf->write == stm32f4_flash_write) { + psize = ((struct stm32f4_flash *)currf)->psize; } } while(len) { diff --git a/src/target/target.c b/src/target/target.c index 4f4bcace..d356a9a6 100644 --- a/src/target/target.c +++ b/src/target/target.c @@ -34,6 +34,11 @@ static bool nop_function(void) return true; } +static int null_function(void) +{ + return 0; +} + target *target_new(void) { target *t = (void*)calloc(1, sizeof(*t)); @@ -63,6 +68,7 @@ target *target_new(void) t->halt_request = (void*)nop_function; t->halt_poll = (void*)nop_function; t->halt_resume = (void*)nop_function; + t->check_error = (void*)null_function; t->target_storage = NULL; @@ -276,7 +282,7 @@ int target_flash_done(target *t) if (tmp) return tmp; if (f->done) { - int tmp = f->done(f); + tmp = f->done(f); if (tmp) return tmp; } diff --git a/src/timing.c b/src/timing.c index 1717bf5a..6c9a6da9 100644 --- a/src/timing.c +++ b/src/timing.c @@ -21,10 +21,12 @@ void platform_timeout_set(platform_timeout *t, uint32_t ms) { + if (ms <= SYSTICKMS) + ms = SYSTICKMS; t->time = platform_time_ms() + ms; } bool platform_timeout_is_expired(platform_timeout *t) { - return platform_time_ms() >= t->time; + return platform_time_ms() > t->time; }