Merge commit '35687018eb634ea329609c86d9ed476bb79c0e91' into sam-update

# Conflicts:
#	src/platforms/common/cdcacm.c
#	src/target/adiv5_swdp.c
This commit is contained in:
Jason Kotzin 2022-08-10 20:19:55 -07:00
commit 9dc79becc2
49 changed files with 785 additions and 449 deletions

View File

@ -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 \

View File

@ -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;
@ -474,6 +477,7 @@ handle_v_packet(char *packet, int plen)
if (cur_target) {
target_set_cmdline(cur_target, cmdline);
target_reset(cur_target);
morse(NULL, false);
gdb_putpacketz("T05");
} else gdb_putpacketz("E01");

View File

@ -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);

View File

@ -21,7 +21,9 @@
#ifndef __GENERAL_H
#define __GENERAL_H
#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 <stdarg.h>
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

View File

@ -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));

View File

@ -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

View File

@ -11,3 +11,55 @@ PC6: TDO/TRACESWO<br>
PC1: TRST<br>
PC8: SRST<br>
# 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

View File

@ -37,20 +37,32 @@
#include <libopencm3/cm3/systick.h>
#include <libopencm3/cm3/cortex.h>
#ifdef BLACKPILL
#include <libopencm3/usb/dwc/otg_fs.h>
#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);
@ -61,21 +73,28 @@ void platform_init(void)
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_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO10 | GPIO11 | GPIO12);
#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);
@ -91,11 +110,25 @@ void platform_init(void)
gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT,
GPIO_PUPD_NONE,
LED_UART | LED_IDLE_RUN | LED_ERROR | LED_BOOTLOADER);
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; }
@ -113,3 +146,15 @@ void platform_request_boot(void)
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

View File

@ -31,6 +31,55 @@
#include <setjmp.h>
#define PLATFORM_HAS_TRACESWO
#ifdef BLACKPILL
#define PLATFORM_IDENT "(F4Discovery/BlackPillV2) "
/* Important pin mappings for STM32 implementation:
* JTAG/SWD
* PA1: TDI<br>
* PA13: TMS/SWDIO<br>
* PA14: TCK/SWCLK<br>
* PB3: TDO/TRACESWO<br>
* PB5: TRST<br>
* PB4: SRST<br>
* 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

View File

@ -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

View File

@ -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!

View File

@ -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) {

View File

@ -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,

View File

@ -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;

View File

@ -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);*/
}
}

View File

@ -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 <ftdi.h>
@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -104,23 +104,43 @@ 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) return;
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 */
DIl &= (1LL << (ticks + 1))-1;
if (chunk < 64)
dil &= ((1LL << chunk) - 1);
s = snprintf((char *)construct, REMOTE_MAX_MSG_SIZE,
REMOTE_JTAG_TDIDO_STR,
final_tms ? REMOTE_TDITDO_TMS : REMOTE_TDITDO_NOTMS,
ticks, DIl);
"!J%c%02x%" PRIx64 "%c",
(!ticks && final_tms) ?
REMOTE_TDITDO_TMS : REMOTE_TDITDO_NOTMS,
chunk, dil, REMOTE_EOM);
platform_buffer_write(construct,s);
s = platform_buffer_read(construct, REMOTE_MAX_MSG_SIZE);
@ -129,10 +149,8 @@ static void jtagtap_tdi_tdo_seq(
s ? (char *)&(construct[1]) : "unknown");
exit(-1);
}
if (DO) {
uint64_t DOl = remotehston(-1, (char *)&construct[1]);
*(uint64_t *)DO = DOl;
if (DO)
*DOl++ = remotehston(-1, (char *)&construct[1]);
}
}

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -25,9 +25,6 @@
#include <libopencm3/cm3/systick.h>
#include <libopencm3/lm4f/usb.h>
#define SYSTICKHZ 100
#define SYSTICKMS (1000 / SYSTICKHZ)
#define PLL_DIV_80MHZ 5
#define PLL_DIV_25MHZ 16

View File

@ -24,6 +24,7 @@
#include "general.h"
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
@ -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 <target>\t: Use (target)id for SWD multi-drop.\n");
DEBUG_WARN("\t-M <string>\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,6 +269,9 @@ void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
opt->opt_mode = BMP_MODE_FLASH_READ;
break;
case 'R':
if ((optarg) && (tolower(optarg[0]) == 'h'))
opt->opt_mode = BMP_MODE_RESET_HW;
else
opt->opt_mode = BMP_MODE_RESET;
break;
case 'p':
@ -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);
}
}
@ -421,7 +432,7 @@ int cl_execute(BMP_CL_OPTIONS_t *opt)
if ((opt->opt_flash_size == 0xffffffff) &&
(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]) {

View File

@ -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,

View File

@ -0,0 +1,28 @@
/*
* This file is part of the libopenstm32 project.
*
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/* 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

View File

@ -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));

View File

@ -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",

View File

@ -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)
{
time_ms += SYSTICKMS;
if (morse_tick >= MORSECNT) {
if(running_status)
gpio_toggle(LED_PORT, LED_IDLE_RUN);
time_ms += 100;
SET_ERROR_STATE(morse_update());
morse_tick = 0;
} else {
morse_tick++;
}
}
uint32_t platform_time_ms(void)

View File

@ -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,

View File

@ -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);
}

View File

@ -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);
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

View File

@ -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

View File

@ -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);

View File

@ -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;

View File

@ -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) {}

View File

@ -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);
}

View File

@ -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[];

View File

@ -3,6 +3,7 @@
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* 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");
#define LOOPS 16
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;
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);
}
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;
}
}
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;
}
if (jd_handlers[i])
jd_handlers[i](&jtag_devs[i]);
return jtag_dev_count;
}

View File

@ -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);

View File

@ -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 0x00008221: /* LPC822M101JHI33 - 16K Flash 4K SRAM */
case 0x00008222: /* LPC822M101JDH20 */
case 0x00008241: /* LPC824M201JHI33 */
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 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) {

View File

@ -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;

View File

@ -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;

View File

@ -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);

View File

@ -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;
}

View File

@ -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) {

View File

@ -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;
}

View File

@ -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;
}