Merge commit '35687018eb634ea329609c86d9ed476bb79c0e91' into sam-update
# Conflicts: # src/platforms/common/cdcacm.c # src/target/adiv5_swdp.c
This commit is contained in:
commit
9dc79becc2
@ -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 \
|
||||
|
@ -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");
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 <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
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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));
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
@ -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
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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!
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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);*/
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,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,
|
||||
|
@ -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,
|
||||
|
28
src/platforms/stm32/blackpillv2.ld
Normal file
28
src/platforms/stm32/blackpillv2.ld
Normal 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
|
@ -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));
|
||||
|
||||
|
@ -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",
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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) {}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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[];
|
||||
|
||||
|
@ -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");
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user