Merge commit '2a0d608b07487300a63908baa62e73a51a11e811' into sam-update

This commit is contained in:
Jason Kotzin 2022-08-10 20:14:55 -07:00
commit 9ec6693e4d
33 changed files with 429 additions and 217 deletions

View File

@ -184,7 +184,7 @@ if __name__ == "__main__":
print("Invoking DFU Device")
timeout = 0
while True :
sleep(0.5)
sleep(1)
timeout = timeout + 0.5
dfudev = stm32_scan(args, True)
if dfudev: break

View File

@ -38,8 +38,6 @@
# include "traceswo.h"
#endif
typedef bool (*cmd_handler)(target *t, int argc, const char **argv);
static bool cmd_version(target *t, int argc, char **argv);
static bool cmd_serial(target *t, int argc, char **argv);
static bool cmd_help(target *t, int argc, char **argv);

View File

@ -41,7 +41,6 @@
#include <libopencm3/usb/cdc.h>
#include <libopencm3/cm3/scb.h>
#include <libopencm3/usb/dfu.h>
#include <stdlib.h>
#define DFU_IF_NO 4

View File

@ -12,8 +12,9 @@ CFLAGS += -DHOSTED_BMP_ONLY=$(HOSTED_BMP_ONLY)
ifneq (, $(findstring linux, $(SYS)))
SRC += serial_unix.c
HIDAPILIB = hidapi-libusb
ifeq ($(ASAN), 1)
CFLAGS += -fsanitize=address
CFLAGS += -fsanitize=address -Wno-format-truncation
LDFLAGS += -lasan
endif
else ifneq (, $(findstring mingw, $(SYS)))
@ -36,6 +37,7 @@ SRC += serial_unix.c
LDFLAGS += -lhidapi
LDFLAGS += -framework CoreFoundation
CFLAGS += -Ihidapi/hidapi
HIDAPILIB = hidapi
endif
ifneq ($(HOSTED_BMP_ONLY), 1)
@ -51,8 +53,8 @@ ifneq ($(HOSTED_BMP_ONLY), 1)
ifneq (, $(findstring mingw, $(SYS)))
SRC += hid.c
else
CFLAGS += $(shell pkg-config --cflags hidapi-libusb)
LDFLAGS += $(shell pkg-config --libs hidapi-libusb)
CFLAGS += $(shell pkg-config --cflags $(HIDAPILIB))
LDFLAGS += $(shell pkg-config --libs $(HIDAPILIB))
endif
endif

View File

@ -201,9 +201,11 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
}
if (res < 0)
serial[0] = 0;
manufacturer[0] = 0;
res = libusb_get_string_descriptor_ascii(
handle, desc.iManufacturer, (uint8_t*)manufacturer,
sizeof(manufacturer));
product[0] = 0;
res = libusb_get_string_descriptor_ascii(
handle, desc.iProduct, (uint8_t*)product,
sizeof(product));
@ -222,8 +224,9 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
if (desc.idVendor == VENDOR_ID_BMP) {
if (desc.idProduct == PRODUCT_ID_BMP) {
type = BMP_TYPE_BMP;
} else if (desc.idProduct == PRODUCT_ID_BMP_BL) {
DEBUG_WARN("BMP in botloader mode found. Restart or reflash!\n");
} else {
if (desc.idProduct == PRODUCT_ID_BMP_BL)
DEBUG_WARN("BMP in botloader mode found. Restart or reflash!\n");
continue;
}
} else if ((type = find_cmsis_dap_interface(dev, info)) != BMP_TYPE_NONE) {
@ -252,13 +255,13 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts,bmp_info_t *info)
if ((cable->vendor != desc.idVendor) || (cable->product != desc.idProduct))
continue; /* VID/PID do not match*/
if (cl_opts->opt_cable) {
if (strcmp(cable->name, cl_opts->opt_cable))
if (strncmp(cable->name, cl_opts->opt_cable, strlen(cable->name)))
continue; /* cable names do not match*/
else
found = true;
}
if (cable->description) {
if (strcmp(cable->description, product))
if (strncmp(cable->description, product, strlen(cable->description)))
continue; /* discriptions do not match*/
else
found = true;

View File

@ -22,7 +22,6 @@
#include "general.h"
#include "gdb_if.h"
#include "version.h"
#include "platform.h"
#include "remote.h"
#include "target.h"
#include "bmp_remote.h"
@ -33,7 +32,6 @@
#include <sys/time.h>
#include <sys/time.h>
#include <errno.h>
#include <string.h>
#include "adiv5.h"

View File

@ -19,18 +19,18 @@
/* Find all known serial connected debuggers */
#include "general.h"
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include "general.h"
#include "platform.h"
#include "bmp_hosted.h"
#include "version.h"
void bmp_ident(bmp_info_t *info)
{
(void) info;
if (!info)
return;
DEBUG_INFO("BMP hosted (BMP Only) %s\n", FIRMWARE_VERSION);
DEBUG_INFO("Using:\n %s %s %s\n", info->manufacturer, info->version, info->serial);
}
void libusb_exit_function(bmp_info_t *info) {(void)info;};
@ -154,6 +154,10 @@ print_probes_info:
}
#else
/* Old ID: Black_Sphere_Technologies_Black_Magic_Probe_BFE4D6EC-if00
* Recent: Black_Sphere_Technologies_Black_Magic_Probe_v1.7.1-212-g212292ab_7BAE7AB8-if00
* usb-Black_Sphere_Technologies_Black_Magic_Probe__SWLINK__v1.7.1-155-gf55ad67b-dirty_DECB8811-if00
*/
#define BMP_IDSTRING "usb-Black_Sphere_Technologies_Black_Magic_Probe"
#define DEVICE_BY_ID "/dev/serial/by-id/"
@ -172,41 +176,45 @@ static int scan_linux_id(char *name, char *type, char *version, char *serial)
DEBUG_WARN("Unexpected end\n");
return -1;
}
char *p = strchr(name, '_');
if (!p) {
DEBUG_WARN("type not found\n");
return -1;
char *p = name;
char *delims[4] = {0,0,0,0};
int underscores = 0;
while (*p) {
if (*p == '_') {
while (p[1] == '_')
p++; /* remove multiple underscores */
if (underscores > 2)
return -1;
delims[underscores] = p;
underscores ++;
}
p++;
}
strncpy(type, name, p - name);
type[p - name] = 0;
name = p;
while (*name != 'v')
name++;
if (!*name) {
DEBUG_WARN("Unexpected end after type\n");
return -1;
if (underscores == 0) { /* Old BMP native */
int res;
res = sscanf(name, "%8s-if00", serial);
if (res != 1)
return -1;
strcpy(type, "Native");
strcpy(version, "Unknown");
} else if (underscores == 2) {
strncpy(type, name, delims[0] - name - 1);
strncpy(version, delims[0] + 1, delims[1] - delims[0] - 1);
int res = sscanf(delims[1] + 1, "%8s-if00", serial);
if (!res)
return -1;
} else {
int res = sscanf(delims[0] + 1, "%8s-if00", serial);
if (!res)
return -1;
if (name[0] == 'v') {
strcpy(type, "Unknown");
strncpy(version, name, delims[0] - name - 1);
} else {
strncpy(type, name, delims[0] - name);
strcpy(type, "Unknown");
}
}
p = strchr(name, '_');
if (!p) {
DEBUG_WARN("version not found\n");
return -1;
}
strncpy(version, name, p - name);
version[p - name] = 0;
name = p;
while (*name == '_')
name++;
if (!*name) {
DEBUG_WARN("Unexpected end after version\n");
return -1;
}
p = strchr(name, '-');
if (!p) {
DEBUG_WARN("Serial not found\n");
return -1;
}
strncpy(serial, name, p - name);
serial[p - name] = 0;
return 0;
}
@ -234,8 +242,9 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
(cl_opts->opt_position && cl_opts->opt_position == i)) {
/* With serial number given and partial match, we are done!*/
strncpy(info->serial, serial, sizeof(info->serial));
strncpy(info->manufacturer, "BMP", sizeof(info->manufacturer));
strncpy(info->product, type, sizeof(info->product));
int res = snprintf(info->manufacturer, sizeof(info->manufacturer), "Black Magic Probe (%s)", type);
if (res)
DEBUG_WARN("Overflow\n");
strncpy(info->version, version, sizeof(info->version));
found_bmps = 1;
break;
@ -265,8 +274,7 @@ int find_debuggers(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
strncpy(info->serial, serial, sizeof(info->serial));
found_bmps = 1;
strncpy(info->serial, serial, sizeof(info->serial));
strncpy(info->manufacturer, "BMP", sizeof(info->manufacturer));
strncpy(info->product, type, sizeof(info->product));
snprintf(info->manufacturer, sizeof(info->manufacturer), "Black Magic Probe (%s)", type);
strncpy(info->version, version, sizeof(info->version));
break;
} else if (found_bmps > 0) {

View File

@ -44,10 +44,10 @@ uint32_t dap_swj_clock(uint32_t clock) {return 0;}
void dap_exit_function(void) {};
void dap_adiv5_dp_defaults(ADIv5_DP_t *dp) {};
int cmsis_dap_jtagtap_init(jtag_proc_t *jtag_proc) {return -1;}
int dap_swdptap_init(swd_proc_t *swd_proc) {return -1;}
int dap_swdptap_init(ADIv5_DP_t *dp) {return -1;}
int dap_jtag_dp_init(ADIv5_DP_t *dp) {return -1;}
void dap_swd_configure(uint8_t cfg) {};
## pragma GCC diagnostic pop
# pragma GCC diagnostic pop
#endif

View File

@ -32,7 +32,6 @@
/*- Includes ----------------------------------------------------------------*/
#include <general.h>
#include <stdlib.h>
#include "dap.h"
#include "jtag_scan.h"

View File

@ -20,7 +20,6 @@
*/
#include "general.h"
#include "gdb_if.h"
#include "platform.h"
#include "target.h"
#include <assert.h>
@ -270,7 +269,7 @@ int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
int err;
cable_desc_t *cable = &cable_desc[0];
for(; cable->name; cable++) {
if (strcmp(cable->name, cl_opts->opt_cable) == 0)
if (strncmp(cable->name, cl_opts->opt_cable, strlen(cable->name)) == 0)
break;
}
@ -282,7 +281,7 @@ int ftdi_bmp_init(BMP_CL_OPTIONS_t *cl_opts, bmp_info_t *info)
active_cable = cable;
memcpy(&active_state, &active_cable->init, sizeof(data_desc_t));
/* If swd_(read|write) is not given for the selected cable and
the 'r' command line argument is give, assume resistor SWD
the 'e' command line argument is give, assume resistor SWD
connection.*/
if (cl_opts->external_resistor_swd &&
(active_cable->mpsse_swd_read.set_data_low == 0) &&

View File

@ -21,13 +21,10 @@
*
*/
#include <stdio.h>
#include "general.h"
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include "general.h"
#include "exception.h"
#include "jlink.h"

View File

@ -22,15 +22,12 @@
*
*/
#include <stdio.h>
#include "general.h"
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <ftdi.h>
#include "platform.h"
#include "ftdi_bmp.h"
#include "general.h"
extern cable_desc_t *active_cable;
extern struct ftdi_context *ftdic;

View File

@ -21,12 +21,10 @@
* Speed is sensible.
*/
#include <stdio.h>
#include "general.h"
#include <assert.h>
#include "general.h"
#include <ftdi.h>
#include "platform.h"
#include "ftdi_bmp.h"
enum swdio_status{

View File

@ -26,13 +26,11 @@
* Should share interface with swdptap.c or at least clean up...
*/
#include <stdio.h>
#include "general.h"
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include "general.h"
#include "remote.h"
#include "jtagtap.h"
#include "bmp_remote.h"

View File

@ -24,12 +24,10 @@
#include "general.h"
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include "version.h"
#include "target.h"
#include "target_internal.h"
#include "cortexm.h"
#include "command.h"
@ -135,6 +133,7 @@ static void cl_help(char **argv)
DEBUG_WARN("\t-h\t\t: This help.\n");
DEBUG_WARN("\t-v[bitmask]\t: Increasing verbosity. Bitmask:\n");
DEBUG_WARN("\t\t\t 1 = INFO, 2 = GDB, 4 = TARGET, 8 = PROBE, 16 = WIRE\n");
DEBUG_WARN("\t-l\t\t: List available probes\n");
DEBUG_WARN("Probe selection arguments:\n");
DEBUG_WARN("\t-d \"path\"\t: Use serial BMP device at <path>");
#if HOSTED_BMP_ONLY == 1 && defined(__APPLE__)
@ -419,7 +418,10 @@ 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)
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_flash_size = lowest_flash_size;
if (opt->opt_mode == BMP_MODE_SWJ_TEST) {
switch (t->core[0]) {

View File

@ -36,13 +36,11 @@
# include <fcntl.h>
#endif
#include <stdio.h>
#include "general.h"
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include "general.h"
#include "gdb_if.h"
static int gdb_if_serv, gdb_if_conn;
@ -51,8 +49,13 @@ static int gdb_if_serv, gdb_if_conn;
int gdb_if_init(void)
{
#if defined(_WIN32) || defined(__CYGWIN__)
int iResult;
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
DEBUG_WARN("WSAStartup failed with error: %ld\n", iResult);
exit(1);
}
#endif
struct sockaddr_in addr;
int opt;
@ -67,23 +70,47 @@ int gdb_if_init(void)
addr.sin_addr.s_addr = htonl(INADDR_ANY);
gdb_if_serv = socket(PF_INET, SOCK_STREAM, 0);
if (gdb_if_serv == -1)
if (gdb_if_serv == -1) {
DEBUG_WARN("PF_INET %d\n",gdb_if_serv);
continue;
}
opt = 1;
if (setsockopt(gdb_if_serv, SOL_SOCKET, SO_REUSEADDR, (void*)&opt, sizeof(opt)) == -1) {
#if defined(_WIN32) || defined(__CYGWIN__)
DEBUG_WARN("error setsockopt SOL_SOCKET : %d error: %d\n", gdb_if_serv,
WSAGetLastError());
#else
DEBUG_WARN("error setsockopt SOL_SOCKET : %d error: %d\n", gdb_if_serv,
strerror(errno));
#endif
close(gdb_if_serv);
continue;
}
if (setsockopt(gdb_if_serv, IPPROTO_TCP, TCP_NODELAY, (void*)&opt, sizeof(opt)) == -1) {
#if defined(_WIN32) || defined(__CYGWIN__)
DEBUG_WARN("error setsockopt IPPROTO_TCP : %d error: %d\n", gdb_if_serv,
WSAGetLastError());
#else
DEBUG_WARN("error setsockopt IPPROTO_TCP : %d error: %d\n", gdb_if_serv,
strerror(errno));
#endif
close(gdb_if_serv);
continue;
}
if (bind(gdb_if_serv, (void*)&addr, sizeof(addr)) == -1) {
#if defined(_WIN32) || defined(__CYGWIN__)
DEBUG_WARN("error when binding socket: %d error: %d\n", gdb_if_serv,
WSAGetLastError());
#else
DEBUG_WARN("error when binding socket: %d error: %d\n", gdb_if_serv,
strerror(errno));
#endif
close(gdb_if_serv);
continue;
}
if (listen(gdb_if_serv, 1) == -1) {
DEBUG_WARN("listen closed %d\n",gdb_if_serv);
close(gdb_if_serv);
continue;
}
@ -100,6 +127,7 @@ unsigned char gdb_if_getchar(void)
unsigned char ret;
int i = 0;
#if defined(_WIN32) || defined(__CYGWIN__)
int iResult;
unsigned long opt;
#else
int flags;
@ -108,7 +136,10 @@ unsigned char gdb_if_getchar(void)
if(gdb_if_conn <= 0) {
#if defined(_WIN32) || defined(__CYGWIN__)
opt = 1;
ioctlsocket(gdb_if_serv, FIONBIO, &opt);
iResult = ioctlsocket(gdb_if_serv, FIONBIO, &opt);
if (iResult != NO_ERROR) {
DEBUG_WARN("ioctlsocket failed with error: %ld\n", iResult);
}
#else
flags = fcntl(gdb_if_serv, F_GETFL);
fcntl(gdb_if_serv, F_SETFL, flags | O_NONBLOCK);

View File

@ -61,9 +61,7 @@ extern "C" {
} /* extern "C" */
#endif
#include <stdio.h>
#include <stdlib.h>
#include <general.h>
#include "hidapi.h"

View File

@ -17,16 +17,15 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/types.h>
#include "general.h"
#include <sys/stat.h>
#include <sys/select.h>
#include <dirent.h>
#include <fcntl.h>
#include <errno.h>
#include <termios.h>
#include <unistd.h>
#include <string.h>
#include "general.h"
#include "remote.h"
#include "cl_utils.h"
#include "cortexm.h"
@ -60,8 +59,9 @@ static int set_interface_attribs(void)
tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
// enable reading
tty.c_cflag &= ~CSTOPB;
#if defined(CRTSCTS)
tty.c_cflag &= ~CRTSCTS;
#endif
if (tcsetattr (fd, TCSANOW, &tty) != 0) {
DEBUG_WARN("error %d from tcsetattr", errno);
return -1;

View File

@ -17,7 +17,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/types.h>
#include "general.h"
#include <windows.h>
#include "remote.h"

View File

@ -44,7 +44,14 @@ int vasprintf(char **strp, const char *fmt, va_list ap)
void platform_delay(uint32_t ms)
{
usleep(ms * 1000);
#if defined(_WIN32) && !defined(__MINGW32__)
Sleep(ms);
#else
# if !defined(usleep)
int usleep(unsigned int);
# endif
usleep(ms);
#endif
}
uint32_t platform_time_ms(void)

View File

@ -39,6 +39,7 @@ static inline void _gpio_set(uint32_t gpioport, uint16_t gpios)
{
GPIO_BSRR(gpioport) = gpios;
#ifdef STM32F4
/* FIXME: Check if doubling is still needed */
GPIO_BSRR(gpioport) = gpios;
#endif
}
@ -46,11 +47,14 @@ static inline void _gpio_set(uint32_t gpioport, uint16_t gpios)
static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios)
{
#ifndef STM32F4
#if defined(STM32F4)
GPIO_BSRR(gpioport) = gpios<<16;
/* FIXME: Check if doubling is still needed */
GPIO_BSRR(gpioport) = gpios<<16;
#elif defined(GPIO_BRR)
GPIO_BRR(gpioport) = gpios;
#else
GPIO_BSRR(gpioport) = gpios<<16;
GPIO_BSRR(gpioport) = gpios<<16;
#endif
}
#define gpio_clear _gpio_clear

View File

@ -118,8 +118,14 @@ void usbuart_init(void)
USBUSART_CR1 |= USART_CR1_IDLEIE;
/* Setup USART TX DMA */
#if !defined(USBUSART_TDR) && defined(USBUSART_DR)
# define USBUSART_TDR USBUSART_DR
#endif
#if !defined(USBUSART_RDR) && defined(USBUSART_DR)
# define USBUSART_RDR USBUSART_DR
#endif
dma_channel_reset(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN);
dma_set_peripheral_address(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN, (uint32_t)&USBUSART_DR);
dma_set_peripheral_address(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN, (uint32_t)&USBUSART_TDR);
dma_enable_memory_increment_mode(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN);
dma_set_peripheral_size(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN, DMA_PSIZE_8BIT);
dma_set_memory_size(USBUSART_DMA_BUS, USBUSART_DMA_TX_CHAN, DMA_MSIZE_8BIT);
@ -136,7 +142,7 @@ void usbuart_init(void)
/* Setup USART RX DMA */
dma_channel_reset(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN);
dma_set_peripheral_address(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN, (uint32_t)&USBUSART_DR);
dma_set_peripheral_address(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN, (uint32_t)&USBUSART_RDR);
dma_set_memory_address(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN, (uint32_t)buf_rx);
dma_set_number_of_data(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN, RX_FIFO_SIZE);
dma_enable_memory_increment_mode(USBUSART_DMA_BUS, USBUSART_DMA_RX_CHAN);
@ -393,8 +399,15 @@ void USBUSART_ISR(void)
usart_recv(USBUSART);
/* If line is now idle, then transmit a packet */
if (isIdle)
if (isIdle) {
#if defined(USART_ICR)
USART_ICR(USBUSART) = USART_ICR_IDLECF;
#else
/* On the older uarts, the sequence "read flags", "read DR"
* as above cleared the flags */
#endif
usbuart_run();
}
nvic_enable_irq(USBUSART_DMA_RX_IRQ);
}

View File

@ -24,7 +24,6 @@
#include "gdb_packet.h"
#include "jtagtap.h"
#include "gdb_if.h"
#include "platform.h"
#include "version.h"
#include "exception.h"
#include <stdarg.h>

View File

@ -661,8 +661,8 @@ void adiv5_dp_init(ADIv5_DP_t *dp)
return;
}
DEBUG_INFO("DPIDR 0x%08" PRIx32 " (v%d %srev%d)\n", dp->idcode,
(dp->idcode >> 12) & 0xf,
(dp->idcode & 0x10000) ? "MINDP " : "", dp->idcode >> 28);
(uint8_t)((dp->idcode >> 12) & 0xf),
(dp->idcode & 0x10000) ? "MINDP " : "", (uint16_t)(dp->idcode >> 28));
volatile uint32_t ctrlstat = 0;
#if PC_HOSTED == 1
platform_adiv5_dp_defaults(dp);

View File

@ -33,7 +33,6 @@
#include "target.h"
#include "target_internal.h"
#include "cortexm.h"
#include "platform.h"
#include "command.h"
#include "gdb_packet.h"
@ -328,7 +327,7 @@ bool cortexm_probe(ADIv5_AP_t *ap)
break;
default:
if (ap->ap_designer != AP_DESIGNER_ATMEL) /* Protected Atmel device?*/{
DEBUG_WARN("Unexpected CortexM CPUID partno %04x\n", cpuid_partno);
DEBUG_WARN("Unexpected CortexM CPUID partno %04" PRIx32 "\n", cpuid_partno);
}
}
DEBUG_INFO("CPUID 0x%08" PRIx32 " (%s var %" PRIx32 " rev %" PRIx32 ")\n",
@ -441,6 +440,7 @@ bool cortexm_probe(ADIv5_AP_t *ap)
if (ap->ap_partno == 0x4c0) { /* Cortex-M0+ ROM */
if ((ap->dp->targetid & 0xfff) == AP_DESIGNER_RASPBERRY)
PROBE(rp_probe);
PROBE(lpc11xx_probe); /* LPC8 */
} else if (ap->ap_partno == 0x4c3) { /* Cortex-M3 ROM */
PROBE(stm32f1_probe); /* Care for STM32F1 clones */
PROBE(lpc15xx_probe); /* Thanks to JojoS for testing */

View File

@ -267,75 +267,75 @@ const struct command_s efm32_cmd_list[] = {
/* -------------------------------------------------------------------------- */
typedef struct efm32_device_t {
uint16_t family_id; /* Family for device matching */
char* name; /* Friendly device family name */
uint32_t flash_page_size; /* Flash page size */
uint32_t msc_addr; /* MSC Address */
uint8_t family_id; /* Family for device matching */
bool has_radio; /* Indicates a device has attached radio */
uint32_t user_data_size; /* User Data (UD) region size */
uint32_t bootloader_size; /* Bootloader (BL) region size (may be 0 for no BL region) */
uint16_t flash_page_size; /* Flash page size */
char* name; /* Friendly device family name */
uint32_t msc_addr; /* MSC Address */
uint16_t user_data_size; /* User Data (UD) region size */
uint16_t bootloader_size; /* Bootloader (BL) region size (may be 0 for no BL region) */
char* description; /* Human-readable description */
} efm32_device_t;
efm32_device_t const efm32_devices[] = {
/* First gen micros */
{71, "EFM32G", 512, 0x400c0000, false, 512, 0, "Gecko"},
{72, "EFM32GG", 2048, 0x400c0000, false, 4096, 0, "Giant Gecko"},
{73, "EFM32TG", 512, 0x400c0000, false, 512, 0, "Tiny Gecko"},
{74, "EFM32LG", 2048, 0x400c0000, false, 2048, 0, "Leopard Gecko"},
{75, "EFM32WG", 2048, 0x400c0000, false, 2048, 0, "Wonder Gecko"},
{76, "EFM32ZG", 1024, 0x400c0000, false, 1024, 0, "Zero Gecko"},
{77, "EFM32HG", 1024, 0x400c0000, false, 1024, 0, "Happy Gecko"},
{ 71, false, 512, "EFM32G" , 0x400c0000, 512, 0, "Gecko"},
{ 72, false, 2048, "EFM32GG" , 0x400c0000, 4096, 0, "Giant Gecko"},
{ 73, false, 512, "EFM32TG" , 0x400c0000, 512, 0, "Tiny Gecko"},
{ 74, false, 2048, "EFM32LG" , 0x400c0000, 2048, 0, "Leopard Gecko"},
{ 75, false, 2048, "EFM32WG" , 0x400c0000, 2048, 0, "Wonder Gecko"},
{ 76, false, 1024, "EFM32ZG" , 0x400c0000, 1024, 0, "Zero Gecko"},
{ 77, false, 1024, "EFM32HG" , 0x400c0000, 1024, 0, "Happy Gecko"},
/* First (1.5) gen micro + radio */
{120, "EZR32WG", 2048, 0x400c0000, true, 2048, 0, "EZR Wonder Gecko"},
{121, "EZR32LG", 2048, 0x400c0000, true, 2048, 0, "EZR Leopard Gecko"},
{122, "EZR32HG", 1024, 0x400c0000, true, 1024, 0, "EZR Happy Gecko"},
{120, true , 2048, "EZR32WG" , 0x400c0000, 2048, 0, "EZR Wonder Gecko"},
{121, true , 2048, "EZR32LG" , 0x400c0000, 2048, 0, "EZR Leopard Gecko"},
{122, true , 1024, "EZR32HG" , 0x400c0000, 1024, 0, "EZR Happy Gecko"},
/* Second gen micros */
{81, "EFM32PG1B", 2048, 0x400e0000, false, 2048, 10240, "Pearl Gecko"},
{83, "EFM32JG1B", 2048, 0x400e0000, false, 2048, 10240, "Jade Gecko"},
{85, "EFM32PG12B", 2048, 0x400e0000, false, 2048, 32768,"Pearl Gecko 12"},
{87, "EFM32JG12B", 2048, 0x400e0000, false, 2048, 32768, "Jade Gecko 12"},
{ 81, false, 2048, "EFM32PG1B" , 0x400e0000, 2048, 10240, "Pearl Gecko"},
{ 83, false, 2048, "EFM32JG1B" , 0x400e0000, 2048, 10240, "Jade Gecko"},
{ 85, false, 2048, "EFM32PG12B", 0x400e0000, 2048, 32768,"Pearl Gecko 12"},
{ 87, false, 2048, "EFM32JG12B", 0x400e0000, 2048, 32768, "Jade Gecko 12"},
/* Second (2.5) gen micros, with re-located MSC */
{100, "EFM32GG11B", 4096, 0x40000000, false, 4096, 32768, "Giant Gecko 11"},
{103, "EFM32TG11B", 2048, 0x40000000, false, 2048, 18432, "Tiny Gecko 11"},
{106, "EFM32GG12B", 2048, 0x40000000, false, 2048, 32768, "Giant Gecko 12"},
{100, false, 4096, "EFM32GG11B", 0x40000000, 4096, 32768, "Giant Gecko 11"},
{103, false, 2048, "EFM32TG11B", 0x40000000, 2048, 18432, "Tiny Gecko 11"},
{106, false, 2048, "EFM32GG12B", 0x40000000, 2048, 32768, "Giant Gecko 12"},
/* Second gen devices micro + radio */
{16, "EFR32MG1P", 2048, 0x400e0000, true, 2048, 10240, "Mighty Gecko"},
{17, "EFR32MG1B", 2048, 0x400e0000, true, 2048, 10240, "Mighty Gecko"},
{18, "EFR32MG1V", 2048, 0x400e0000, true, 2048, 10240, "Mighty Gecko"},
{19, "EFR32BG1P", 2048, 0x400e0000, true, 2048, 10240, "Blue Gecko"},
{20, "EFR32BG1B", 2048, 0x400e0000, true, 2048, 10240, "Blue Gecko"},
{21, "EFR32BG1V", 2048, 0x400e0000, true, 2048, 10240, "Blue Gecko"},
{25, "EFR32FG1P", 2048, 0x400e0000, true, 2048, 10240, "Flex Gecko"},
{26, "EFR32FG1B", 2048, 0x400e0000, true, 2048, 10240, "Flex Gecko"},
{27, "EFR32FG1V", 2048, 0x400e0000, true, 2048, 10240, "Flex Gecko"},
{28, "EFR32MG12P", 2048, 0x400e0000, true, 2048, 32768, "Mighty Gecko"},
{29, "EFR32MG12B", 2048, 0x400e0000, true, 2048, 32768, "Mighty Gecko"},
{30, "EFR32MG12V", 2048, 0x400e0000, true, 2048, 32768, "Mighty Gecko"},
{31, "EFR32BG12P", 2048, 0x400e0000, true, 2048, 32768, "Blue Gecko"},
{32, "EFR32BG12B", 2048, 0x400e0000, true, 2048, 32768, "Blue Gecko"},
{33, "EFR32BG12V", 2048, 0x400e0000, true, 2048, 32768, "Blue Gecko"},
{37, "EFR32FG12P", 2048, 0x400e0000, true, 2048, 32768, "Flex Gecko"},
{38, "EFR32FG12B", 2048, 0x400e0000, true, 2048, 32768, "Flex Gecko"},
{39, "EFR32FG12V", 2048, 0x400e0000, true, 2048, 32768, "Flex Gecko"},
{40, "EFR32MG13P", 2048, 0x400e0000, true, 2048, 16384, "Mighty Gecko"},
{41, "EFR32MG13B", 2048, 0x400e0000, true, 2048, 16384, "Mighty Gecko"},
{42, "EFR32MG13V", 2048, 0x400e0000, true, 2048, 16384, "Mighty Gecko"},
{43, "EFR32BG13P", 2048, 0x400e0000, true, 2048, 16384, "Blue Gecko"},
{44, "EFR32BG13B", 2048, 0x400e0000, true, 2048, 16384, "Blue Gecko"},
{45, "EFR32BG13V", 2048, 0x400e0000, true, 2048, 16384, "Blue Gecko"},
{49, "EFR32FG13P", 2048, 0x400e0000, true, 2048, 16384, "Flex Gecko"},
{50, "EFR32FG13B", 2048, 0x400e0000, true, 2048, 16384, "Flex Gecko"},
{51, "EFR32FG13V", 2048, 0x400e0000, true, 2048, 16384, "Flex Gecko"},
{52, "EFR32MG14P", 2048, 0x400e0000, true, 2048, 16384, "Mighty Gecko"},
{53, "EFR32MG14B", 2048, 0x400e0000, true, 2048, 16384, "Mighty Gecko"},
{54, "EFR32MG14V", 2048, 0x400e0000, true, 2048, 16384, "Mighty Gecko"},
{55, "EFR32BG14P", 2048, 0x400e0000, true, 2048, 16384, "Blue Gecko"},
{56, "EFR32BG14B", 2048, 0x400e0000, true, 2048, 16384, "Blue Gecko"},
{57, "EFR32BG14V", 2048, 0x400e0000, true, 2048, 16384, "Blue Gecko"},
{61, "EFR32FG14P", 2048, 0x400e0000, true, 2048, 16384, "Flex Gecko"},
{62, "EFR32FG14B", 2048, 0x400e0000, true, 2048, 16384, "Flex Gecko"},
{63, "EFR32FG14V", 2048, 0x400e0000, true, 2048, 16384, "Flex Gecko"},
{ 16, true , 2048, "EFR32MG1P" , 0x400e0000, 2048, 10240, "Mighty Gecko"},
{ 17, true , 2048, "EFR32MG1B" , 0x400e0000, 2048, 10240, "Mighty Gecko"},
{ 18, true , 2048, "EFR32MG1V" , 0x400e0000, 2048, 10240, "Mighty Gecko"},
{ 19, true , 2048, "EFR32BG1P" , 0x400e0000, 2048, 10240, "Blue Gecko"},
{ 20, true , 2048, "EFR32BG1B" , 0x400e0000, 2048, 10240, "Blue Gecko"},
{ 21, true , 2048, "EFR32BG1V" , 0x400e0000, 2048, 10240, "Blue Gecko"},
{ 25, true , 2048, "EFR32FG1P" , 0x400e0000, 2048, 10240, "Flex Gecko"},
{ 26, true , 2048, "EFR32FG1B" , 0x400e0000, 2048, 10240, "Flex Gecko"},
{ 27, true , 2048, "EFR32FG1V" , 0x400e0000, 2048, 10240, "Flex Gecko"},
{ 28, true , 2048, "EFR32MG12P", 0x400e0000, 2048, 32768, "Mighty Gecko"},
{ 29, true , 2048, "EFR32MG12B", 0x400e0000, 2048, 32768, "Mighty Gecko"},
{ 30, true , 2048, "EFR32MG12V", 0x400e0000, 2048, 32768, "Mighty Gecko"},
{ 31, true , 2048, "EFR32BG12P", 0x400e0000, 2048, 32768, "Blue Gecko"},
{ 32, true , 2048, "EFR32BG12B", 0x400e0000, 2048, 32768, "Blue Gecko"},
{ 33, true , 2048, "EFR32BG12V", 0x400e0000, 2048, 32768, "Blue Gecko"},
{ 37, true , 2048, "EFR32FG12P", 0x400e0000, 2048, 32768, "Flex Gecko"},
{ 38, true , 2048, "EFR32FG12B", 0x400e0000, 2048, 32768, "Flex Gecko"},
{ 39, true , 2048, "EFR32FG12V", 0x400e0000, 2048, 32768, "Flex Gecko"},
{ 40, true , 2048, "EFR32MG13P", 0x400e0000, 2048, 16384, "Mighty Gecko"},
{ 41, true , 2048, "EFR32MG13B", 0x400e0000, 2048, 16384, "Mighty Gecko"},
{ 42, true , 2048, "EFR32MG13V", 0x400e0000, 2048, 16384, "Mighty Gecko"},
{ 43, true , 2048, "EFR32BG13P", 0x400e0000, 2048, 16384, "Blue Gecko"},
{ 44, true , 2048, "EFR32BG13B", 0x400e0000, 2048, 16384, "Blue Gecko"},
{ 45, true , 2048, "EFR32BG13V", 0x400e0000, 2048, 16384, "Blue Gecko"},
{ 49, true , 2048, "EFR32FG13P", 0x400e0000, 2048, 16384, "Flex Gecko"},
{ 50, true , 2048, "EFR32FG13B", 0x400e0000, 2048, 16384, "Flex Gecko"},
{ 51, true , 2048, "EFR32FG13V", 0x400e0000, 2048, 16384, "Flex Gecko"},
{ 52, true , 2048, "EFR32MG14P", 0x400e0000, 2048, 16384, "Mighty Gecko"},
{ 53, true , 2048, "EFR32MG14B", 0x400e0000, 2048, 16384, "Mighty Gecko"},
{ 54, true , 2048, "EFR32MG14V", 0x400e0000, 2048, 16384, "Mighty Gecko"},
{ 55, true , 2048, "EFR32BG14P", 0x400e0000, 2048, 16384, "Blue Gecko"},
{ 56, true , 2048, "EFR32BG14B", 0x400e0000, 2048, 16384, "Blue Gecko"},
{ 57, true , 2048, "EFR32BG14V", 0x400e0000, 2048, 16384, "Blue Gecko"},
{ 61, true , 2048, "EFR32FG14P", 0x400e0000, 2048, 16384, "Flex Gecko"},
{ 62, true , 2048, "EFR32FG14B", 0x400e0000, 2048, 16384, "Flex Gecko"},
{ 63, true , 2048, "EFR32FG14V", 0x400e0000, 2048, 16384, "Flex Gecko"},
};

View File

@ -36,6 +36,22 @@
#define LPC11XX_DEVICE_ID 0x400483F4
#define LPC8XX_DEVICE_ID 0x400483F8
/*
* CHIP Ram Flash page sector Rsvd pages EEPROM
* LPX80x 2k 16k 64 1024 2
* LPC804 4k 32k 64 1024 2
* LPC8N04 8k 32k 64 1024 32
* LPC810 1k 4k 64 1024 0
* LPC811 2k 8k 64 1024 0
* LPC812 4k 16k 64 1024
* LPC822 4k 16k 64 1024
* LPC822 8k 32k 64 1024
* LPC832 4k 16k 64 1024
* LPC834 4k 32k 64 1024
* LPC844 8k 64k 64 1024
* LPC845 16k 64k 64 1024
*/
static bool lpc11xx_read_uid(target *t, int argc, const char *argv[])
{
(void)argc;
@ -56,7 +72,7 @@ const struct command_s lpc11xx_cmd_list[] = {
{NULL, NULL, NULL}
};
void lpc11xx_add_flash(target *t, uint32_t addr, size_t len, size_t erasesize, uint32_t iap_entry)
void lpc11xx_add_flash(target *t, uint32_t addr, size_t len, size_t erasesize, uint32_t iap_entry, uint8_t reserved_pages)
{
struct lpc_flash *lf = lpc_add_flash(t, addr, len);
lf->f.blocksize = erasesize;
@ -65,6 +81,7 @@ void lpc11xx_add_flash(target *t, uint32_t addr, size_t len, size_t erasesize, u
lf->iap_entry = iap_entry;
lf->iap_ram = IAP_RAM_BASE;
lf->iap_msp = IAP_RAM_BASE + MIN_RAM_SIZE - RAM_USAGE_FOR_IAP_ROUTINES;
lf->reserved_pages = reserved_pages;
}
bool
@ -109,7 +126,7 @@ lpc11xx_probe(target *t)
case 0x2980002B: /* lpc11u24x/401 */
t->driver = "LPC11xx";
target_add_ram(t, 0x10000000, 0x2000);
lpc11xx_add_flash(t, 0x00000000, 0x20000, 0x1000, IAP_ENTRY_MOST);
lpc11xx_add_flash(t, 0x00000000, 0x20000, 0x1000, IAP_ENTRY_MOST, 0);
target_add_commands(t, lpc11xx_cmd_list, "LPC11xx");
return true;
@ -117,23 +134,26 @@ lpc11xx_probe(target *t)
case 0x1A24902B:
t->driver = "LPC1112";
target_add_ram(t, 0x10000000, 0x1000);
lpc11xx_add_flash(t, 0x00000000, 0x10000, 0x1000, IAP_ENTRY_MOST);
lpc11xx_add_flash(t, 0x00000000, 0x10000, 0x1000, IAP_ENTRY_MOST, 0);
return true;
case 0x1000002b: // FX LPC11U6 32 kB SRAM/256 kB flash (max)
t->driver = "LPC11U6";
target_add_ram(t, 0x10000000, 0x8000);
lpc11xx_add_flash(t, 0x00000000, 0x40000, 0x1000, IAP_ENTRY_MOST);
lpc11xx_add_flash(t, 0x00000000, 0x40000, 0x1000, IAP_ENTRY_MOST, 0);
return true;
case 0x3000002B:
case 0x3D00002B:
t->driver = "LPC1343";
target_add_ram(t, 0x10000000, 0x2000);
lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x1000, IAP_ENTRY_MOST);
lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x1000, IAP_ENTRY_MOST, 0);
return true;
case 0x00008A04: /* LPC8N04 (see UM11074 Rev.1.3 section 4.5.19) */
t->driver = "LPC8N04";
target_add_ram(t, 0x10000000, 0x2000);
lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x400, IAP_ENTRY_MOST);
/* UM11074/ Flash controller/15.2: The two topmost sectors
* contain the initialization code and IAP firmware.
* Do not touch the! */
lpc11xx_add_flash(t, 0x00000000, 0x7800, 0x400, IAP_ENTRY_MOST, 0);
target_add_commands(t, lpc11xx_cmd_list, "LPC8N04");
return true;
}
@ -148,7 +168,7 @@ lpc11xx_probe(target *t)
case 0x00008024: /* 802M001JHI33 */
t->driver = "LPC802";
target_add_ram(t, 0x10000000, 0x800);
lpc11xx_add_flash(t, 0x00000000, 0x4000, 0x400, IAP_ENTRY_84x);
lpc11xx_add_flash(t, 0x00000000, 0x4000, 0x400, IAP_ENTRY_84x, 2);
target_add_commands(t, lpc11xx_cmd_list, "LPC802");
return true;
case 0x00008040: /* 804M101JBD64 */
@ -158,7 +178,7 @@ lpc11xx_probe(target *t)
case 0x00008044: /* 804M101JHI33 */
t->driver = "LPC804";
target_add_ram(t, 0x10000000, 0x1000);
lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x400, IAP_ENTRY_84x);
lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x400, IAP_ENTRY_84x, 2);
target_add_commands(t, lpc11xx_cmd_list, "LPC804");
return true;
case 0x00008100: /* LPC810M021FN8 */
@ -168,7 +188,7 @@ lpc11xx_probe(target *t)
case 0x00008122: /* LPC812M101JDH20 / LPC812M101JTB16 */
t->driver = "LPC81x";
target_add_ram(t, 0x10000000, 0x1000);
lpc11xx_add_flash(t, 0x00000000, 0x4000, 0x400, IAP_ENTRY_MOST);
lpc11xx_add_flash(t, 0x00000000, 0x4000, 0x400, IAP_ENTRY_MOST, 0);
target_add_commands(t, lpc11xx_cmd_list, "LPC81x");
return true;
case 0x00008221: /* LPC822M101JHI33 */
@ -177,19 +197,19 @@ lpc11xx_probe(target *t)
case 0x00008242: /* LPC824M201JDH20 */
t->driver = "LPC82x";
target_add_ram(t, 0x10000000, 0x2000);
lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x400, IAP_ENTRY_MOST);
lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x400, IAP_ENTRY_MOST, 0);
target_add_commands(t, lpc11xx_cmd_list, "LPC82x");
return true;
case 0x00008322: /* LPC832M101FDH20 */
t->driver = "LPC832";
target_add_ram(t, 0x10000000, 0x1000);
lpc11xx_add_flash(t, 0x00000000, 0x4000, 0x400, IAP_ENTRY_MOST);
lpc11xx_add_flash(t, 0x00000000, 0x4000, 0x400, IAP_ENTRY_MOST, 0);
target_add_commands(t, lpc11xx_cmd_list, "LPC832");
return true;
case 0x00008341: /* LPC8341201FHI33 */
t->driver = "LPC834";
target_add_ram(t, 0x10000000, 0x1000);
lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x400, IAP_ENTRY_MOST);
lpc11xx_add_flash(t, 0x00000000, 0x8000, 0x400, IAP_ENTRY_MOST, 0);
target_add_commands(t, lpc11xx_cmd_list, "LPC834");
return true;
case 0x00008441:
@ -198,7 +218,7 @@ lpc11xx_probe(target *t)
case 0x00008444:
t->driver = "LPC844";
target_add_ram(t, 0x10000000, 0x2000);
lpc11xx_add_flash(t, 0x00000000, 0x10000, 0x400, IAP_ENTRY_84x);
lpc11xx_add_flash(t, 0x00000000, 0x10000, 0x400, IAP_ENTRY_84x, 0);
return true;
case 0x00008451:
case 0x00008452:
@ -206,7 +226,7 @@ lpc11xx_probe(target *t)
case 0x00008454:
t->driver = "LPC845";
target_add_ram(t, 0x10000000, 0x4000);
lpc11xx_add_flash(t, 0x00000000, 0x10000, 0x400, IAP_ENTRY_84x);
lpc11xx_add_flash(t, 0x00000000, 0x10000, 0x400, IAP_ENTRY_84x, 0);
return true;
case 0x0003D440: /* LPC11U34/311 */
case 0x0001cc40: /* LPC11U34/421 */
@ -218,13 +238,13 @@ lpc11xx_probe(target *t)
case 0x00007C40: /* LPC11U37FBD64/501 */
t->driver = "LPC11U3x";
target_add_ram(t, 0x10000000, 0x2000);
lpc11xx_add_flash(t, 0x00000000, 0x20000, 0x1000, IAP_ENTRY_MOST);
lpc11xx_add_flash(t, 0x00000000, 0x20000, 0x1000, IAP_ENTRY_MOST, 0);
return true;
case 0x00040070: /* LPC1114/333 */
case 0x00050080: /* lpc1115XL */
t->driver = "LPC1100XL";
target_add_ram(t, 0x10000000, 0x2000);
lpc11xx_add_flash(t, 0x00000000, 0x20000, 0x1000, IAP_ENTRY_MOST);
lpc11xx_add_flash(t, 0x00000000, 0x20000, 0x1000, IAP_ENTRY_MOST, 0);
return true;
}
if (idcode) {

View File

@ -33,6 +33,45 @@ struct flash_param {
uint32_t result[4];
} __attribute__((aligned(4)));
char *iap_error[] = {
"CMD_SUCCESS",
"Invalid command",
"Unaligned src address",
"Dst address not on boundary",
"Src not mapped",
"Dst not mapped",
"Invalid byte count",
"Invalid sector",
"Sector not blank",
"Sector not prepared",
"Compare error",
"Flash interface busy",
"Invalid or missing parameter",
"Address not on boundary",
"Address not mapped",
"Checksum error",
"16",
"17",
"18",
"19",
"20",
"21",
"22",
"FRO not powered",
"Flash not powered",
"25",
"26",
"Flash clock disabled",
"Reinvoke error",
"Invalid image",
"30",
"31",
"Flash erase failed",
"Page is invalid",
};
static int lpc_flash_write(struct target_flash *tf,
target_addr dest, const void *src, size_t len);
struct lpc_flash *lpc_add_flash(target *t, target_addr addr, size_t length)
{
@ -109,11 +148,17 @@ enum iap_status lpc_iap_call(struct lpc_flash *f, void *result, enum iap_cmd cmd
if (result != NULL)
memcpy(result, param.result, sizeof(param.result));
#if defined(ENABLE_DEBUG)
if (param.status != IAP_STATUS_CMD_SUCCESS) {
DEBUG_WARN("IAP failure code %d for cmd %d\n",
(enum iap_status)param.status, cmd);
if (param.status > (sizeof(iap_error) / sizeof(char*)))
DEBUG_WARN("IAP cmd %d : %d\n", cmd, param.status);
else
DEBUG_WARN("IAP cmd %d : %s\n", cmd, iap_error[param.status]);
DEBUG_WARN("return parameters: %08" PRIx32 " %08" PRIx32 " %08" PRIx32
" %08" PRIx32 "\n", param.result[0],
param.result[1], param.result[2], param.result[3]);
}
#endif
return param.status;
}
@ -122,43 +167,80 @@ static uint8_t lpc_sector_for_addr(struct lpc_flash *f, uint32_t addr)
return f->base_sector + (addr - f->f.start) / f->f.blocksize;
}
#define LPX80X_SECTOR_SIZE 0x400
#define LPX80X_PAGE_SIZE 0x40
int lpc_flash_erase(struct target_flash *tf, target_addr addr, size_t len)
{
struct lpc_flash *f = (struct lpc_flash *)tf;
uint32_t start = lpc_sector_for_addr(f, addr);
uint32_t end = lpc_sector_for_addr(f, addr + len - 1);
uint32_t last_full_sector = end;
if (lpc_iap_call(f, NULL, IAP_CMD_PREPARE, start, end, f->bank))
return -1;
/* and now erase them */
if (lpc_iap_call(f, NULL, IAP_CMD_ERASE, start, end, CPU_CLK_KHZ, f->bank))
return -2;
/* Only LPC80x has reserved pages!*/
if (f->reserved_pages && ((addr + len) >= tf->length - 0x400) ) {
last_full_sector -= 1;
}
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;
/* check erase ok */
if (lpc_iap_call(f, NULL, IAP_CMD_BLANKCHECK, start, end, f->bank))
return -3;
/* check erase ok */
if (lpc_iap_call(f, NULL, IAP_CMD_BLANKCHECK, start, last_full_sector, f->bank))
return -3;
}
if (last_full_sector != end) {
uint32_t page_start = (addr + len - LPX80X_SECTOR_SIZE) / LPX80X_PAGE_SIZE;
uint32_t page_end = page_start + LPX80X_SECTOR_SIZE/LPX80X_PAGE_SIZE - 1 - f->reserved_pages;
if (lpc_iap_call(f, NULL, IAP_CMD_PREPARE, end, end, f->bank))
return -1;
if (lpc_iap_call(f, NULL, IAP_CMD_ERASE_PAGE, page_start, page_end, CPU_CLK_KHZ, f->bank))
return -2;
/* Blank check omitted!*/
}
return 0;
}
int lpc_flash_write(struct target_flash *tf,
static int lpc_flash_write(struct target_flash *tf,
target_addr dest, const void *src, size_t len)
{
struct lpc_flash *f = (struct lpc_flash *)tf;
/* prepare... */
uint32_t sector = lpc_sector_for_addr(f, dest);
if (lpc_iap_call(f, NULL, IAP_CMD_PREPARE, sector, sector, f->bank))
if (lpc_iap_call(f, NULL, IAP_CMD_PREPARE, sector, sector, f->bank)) {
DEBUG_WARN("Prepare failed\n");
return -1;
/* Write payload to target ram */
}
uint32_t bufaddr = ALIGN(f->iap_ram + sizeof(struct flash_param), 4);
target_mem_write(f->f.t, bufaddr, src, len);
/* set the destination address and program */
if (lpc_iap_call(f, NULL, IAP_CMD_PROGRAM, dest, bufaddr, len, CPU_CLK_KHZ))
return -2;
/* Only LPC80x has reserved pages!*/
if ((!f->reserved_pages) || ((dest + len) <= (tf->length - len))) {
/* Write payload to target ram */
/* set the destination address and program */
if (lpc_iap_call(f, NULL, IAP_CMD_PROGRAM, dest, bufaddr, len, CPU_CLK_KHZ))
return -2;
} else {
/* On LPC80x, write top sector in pages.
* Silently ignore write to the 2 reserved pages at top!*/
len -= 0x40 * f->reserved_pages;
while (len) {
if (lpc_iap_call(f, NULL, IAP_CMD_PREPARE, sector, sector, f->bank)) {
DEBUG_WARN("Prepare failed\n");
return -1;
}
/* set the destination address and program */
if (lpc_iap_call(f, NULL, IAP_CMD_PROGRAM, dest, bufaddr, LPX80X_PAGE_SIZE, CPU_CLK_KHZ))
return -2;
dest += LPX80X_PAGE_SIZE;
bufaddr += LPX80X_PAGE_SIZE;
len -= LPX80X_PAGE_SIZE;
}
}
return 0;
}

View File

@ -21,14 +21,23 @@
#define __LPC_COMMON_H
enum iap_cmd {
IAP_CMD_READ_FACTORY_SETTINGS = 40,
IAP_CMD_INIT = 49,
IAP_CMD_PREPARE = 50,
IAP_CMD_PROGRAM = 51,
IAP_CMD_ERASE = 52,
IAP_CMD_BLANKCHECK = 53,
IAP_CMD_PARTID = 54,
IAP_CMD_READ_BOOTROM_VERSION = 55,
IAP_CMD_COMPARE = 56,
IAP_CMD_REINVOKE_ISP = 57,
IAP_CMD_READUID = 58,
IAP_CMD_ERASE_PAGE = 59,
IAP_CMD_SET_ACTIVE_BANK = 60,
IAP_CMD_READ_SIGNATURE = 70,
IAP_CMD_EXTENDED_READ_SIGNATURE = 73,
IAP_CMD_READ_EEPROM_PAGE = 80,
IAP_CMD_WRITE_EEPROM_PAGE = 81,
};
enum iap_status {
@ -44,6 +53,16 @@ enum iap_status {
IAP_STATUS_SECTOR_NOT_PREPARED = 9,
IAP_STATUS_COMPARE_ERROR = 10,
IAP_STATUS_BUSY = 11,
IAP_STATUS_MISSING_PARAMETERS = 12,
IAP_STATUS_UNALIGNED_ADDRESS = 13,
IAP_STATUS_ADDRESS_NOT_MAPPED = 14,
IAP_STATUS_FRO_NO_POWER = 23,
IAP_STATUS_FLASH_NO_POWER = 24,
IAP_STATUS_NO_CLOCK = 27,
IAP_STATUS_REINVOKE_CFG_ERR = 28,
IAP_STATUS_NO_VALID_IMAGE = 29,
IAP_STATUS_FLASH_ERASE = 32,
IAP_STATUS_INVALID_PAGE = 33,
};
/* CPU Frequency */
@ -53,6 +72,7 @@ struct lpc_flash {
struct target_flash f;
uint8_t base_sector;
uint8_t bank;
uint8_t reserved_pages;
/* Info filled in by specific driver */
void (*wdt_kick)(target *t);
uint32_t iap_entry;
@ -63,8 +83,6 @@ struct lpc_flash {
struct lpc_flash *lpc_add_flash(target *t, target_addr addr, size_t length);
enum iap_status lpc_iap_call(struct lpc_flash *f, void *result, enum iap_cmd cmd, ...);
int lpc_flash_erase(struct target_flash *f, target_addr addr, size_t len);
int lpc_flash_write(struct target_flash *f,
target_addr dest, const void *src, size_t len);
int lpc_flash_write_magic_vect(struct target_flash *f,
target_addr dest, const void *src, size_t len);

View File

@ -59,6 +59,7 @@ struct rp_priv_s {
uint16_t _flash_enter_cmd_xip;
uint16_t reset_usb_boot;
bool is_prepared;
bool is_monitor;
uint32_t regs[0x20];/* Register playground*/
};
@ -112,7 +113,7 @@ static bool rp2040_fill_table(struct rp_priv_s *priv, uint16_t *table, int max)
/* RP ROM functions calls
*
* timout == 0: Do not wait for poll, use for reset_usb_boot()
* timeout > 400 (ms) : display spinner
* timeout > 500 (ms) : display spinner
*/
static bool rp_rom_call(target *t, uint32_t *regs, uint32_t cmd,
uint32_t timeout)
@ -131,14 +132,23 @@ static bool rp_rom_call(target *t, uint32_t *regs, uint32_t cmd,
target_halt_resume(t, false);
if (!timeout)
return false;
DEBUG_INFO("Call cmd %04x\n", cmd);
DEBUG_INFO("Call cmd %04" PRIx32 "\n", cmd);
platform_timeout to;
platform_timeout_set(&to, timeout);
platform_timeout to_spinner;
if (timeout > 500)
platform_timeout_set(&to_spinner, 500);
else
/* never trigger if timeout is short */
platform_timeout_set(&to_spinner, timeout + 1);
do {
if (timeout > 400)
tc_printf(t, "\b%c", spinner[spinindex++ % 4]);
if (platform_timeout_is_expired(&to_spinner)) {
if (ps->is_monitor)
tc_printf(t, "\b%c", spinner[spinindex++ % 4]);
platform_timeout_set(&to_spinner, 500);
}
if (platform_timeout_is_expired(&to)) {
DEBUG_WARN("RP Run timout %d ms reached: ", timeout);
DEBUG_WARN("RP Run timout %d ms reached: ", (int)timeout);
break;
}
} while (!target_halt_poll(t, NULL));
@ -146,7 +156,7 @@ static bool rp_rom_call(target *t, uint32_t *regs, uint32_t cmd,
target_regs_read(t, dbg_regs);
bool ret = ((dbg_regs[REG_PC] &~1) != (ps->_debug_trampoline_end & ~1));
if (ret) {
DEBUG_WARN("rp_rom_call cmd %04x failed, PC %08" PRIx32 "\n",
DEBUG_WARN("rp_rom_call cmd %04" PRIx32 " failed, PC %08" PRIx32 "\n",
cmd, dbg_regs[REG_PC]);
}
return ret;
@ -156,6 +166,7 @@ static void rp_flash_prepare(target *t)
{
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
if (!ps->is_prepared) {
DEBUG_INFO("rp_flash_prepare\n");
/* connect*/
rp_rom_call(t, ps->regs, ps->_connect_internal_flash,100);
/* exit_xip */
@ -164,6 +175,19 @@ static void rp_flash_prepare(target *t)
}
}
static void rp_flash_resume(target *t)
{
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
if (ps->is_prepared) {
DEBUG_INFO("rp_flash_resume\n");
/* flush */
rp_rom_call(t, ps->regs, ps->_flash_flush_cache,100);
/* enter_cmd_xip */
rp_rom_call(t, ps->regs, ps->_flash_enter_cmd_xip, 100);
ps->is_prepared = false;
}
}
/* FLASHCMD_SECTOR_ERASE 45/ 400 ms
* 32k block erase 120/ 1600 ms
* 64k block erase 150/ 2000 ms
@ -181,7 +205,7 @@ static int rp_flash_erase(struct target_flash *f, target_addr addr,
DEBUG_WARN("Unaligned len\n");
len = (len + 0xfff) & ~0xfff;
}
DEBUG_INFO("Erase addr %08" PRIx32 " len 0x%" PRIx32 "\n", addr, len);
DEBUG_INFO("Erase addr %08" PRIx32 " len 0x%" PRIx32 "\n", addr, (uint32_t)len);
target *t = f->t;
rp_flash_prepare(t);
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
@ -195,6 +219,7 @@ static int rp_flash_erase(struct target_flash *f, target_addr addr,
addr -= XIP_FLASH_START;
if (len > MAX_FLASH)
len = MAX_FLASH;
bool ret = 0;
while (len) {
ps->regs[0] = addr;
ps->regs[2] = -1;
@ -202,14 +227,14 @@ static int rp_flash_erase(struct target_flash *f, target_addr addr,
ps->regs[1] = MAX_FLASH;
ps->regs[3] = FLASHCMD_CHIP_ERASE;
DEBUG_WARN("BULK_ERASE\n");
rp_rom_call(t, ps->regs, ps->_flash_range_erase, 25100);
ret = rp_rom_call(t, ps->regs, ps->_flash_range_erase, 25100);
len = 0;
} else if (len >= (64 * 1024)) {
uint32_t chunk = len & ~((1 << 16) - 1);
ps->regs[1] = chunk;
ps->regs[3] = FLASHCMD_BLOCK64K_ERASE;
DEBUG_WARN("64k_ERASE\n");
rp_rom_call(t, ps->regs, ps->_flash_range_erase, 2100);
ret = rp_rom_call(t, ps->regs, ps->_flash_range_erase, 2100);
len -= chunk ;
addr += chunk;
} else if (len >= (32 * 1024)) {
@ -217,7 +242,7 @@ static int rp_flash_erase(struct target_flash *f, target_addr addr,
ps->regs[1] = chunk;
ps->regs[3] = FLASHCMD_BLOCK32K_ERASE;
DEBUG_WARN("32k_ERASE\n");
rp_rom_call(t, ps->regs, ps->_flash_range_erase, 1700);
ret = rp_rom_call(t, ps->regs, ps->_flash_range_erase, 1700);
len -= chunk;
addr += chunk;
} else {
@ -225,18 +250,23 @@ static int rp_flash_erase(struct target_flash *f, target_addr addr,
ps->regs[2] = MAX_FLASH;
ps->regs[3] = FLASHCMD_SECTOR_ERASE;
DEBUG_WARN("Sector_ERASE\n");
rp_rom_call(t, ps->regs, ps->_flash_range_erase, 410);
ret = rp_rom_call(t, ps->regs, ps->_flash_range_erase, 410);
len = 0;
}
if (ret) {
DEBUG_WARN("Erase failed!\n");
break;
}
}
DEBUG_INFO("\nErase done!\n");
return 0;
rp_flash_resume(t);
DEBUG_INFO("Erase done!\n");
return ret;
}
int rp_flash_write(struct target_flash *f,
target_addr dest, const void *src, size_t len)
{
DEBUG_INFO("RP Write %08" PRIx32 " len 0x%" PRIx32 "\n", dest, len);
DEBUG_INFO("RP Write %08" PRIx32 " len 0x%" PRIx32 "\n", dest, (uint32_t)len);
if ((dest & 0xff) || (len & 0xff)) {
DEBUG_WARN("Unaligned erase\n");
return -1;
@ -246,6 +276,7 @@ int rp_flash_write(struct target_flash *f,
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
/* Write payload to target ram */
dest -= XIP_FLASH_START;
bool ret = 0;
#define MAX_WRITE_CHUNK 0x1000
while (len) {
uint32_t chunksize = (len <= MAX_WRITE_CHUNK) ? len : MAX_WRITE_CHUNK;
@ -254,13 +285,23 @@ int rp_flash_write(struct target_flash *f,
ps->regs[0] = dest;
ps->regs[1] = SRAM_START;
ps->regs[2] = chunksize;
rp_rom_call(t, ps->regs, ps->flash_range_program,
(3 * chunksize) >> 8); /* 3 ms per 256 byte page */
/* Loading takes 3 ms per 256 byte page
* however it takes much longer if the XOSC is not enabled
* so lets give ourselves a little bit more time (x10)
*/
ret |= rp_rom_call(t, ps->regs, ps->flash_range_program,
(3 * chunksize * 10) >> 8);
if (ret) {
DEBUG_WARN("Write failed!\n");
break;
}
len -= chunksize;
src += chunksize;
dest += chunksize;
}
return 0;
rp_flash_resume(t);
DEBUG_INFO("Write done!\n");
return ret;
}
static bool rp_cmd_reset_usb_boot(target *t, int argc, const char *argv[])
@ -284,7 +325,11 @@ static bool rp_cmd_erase_mass(target *t, int argc, const char *argv[])
(void) argv;
struct target_flash f;
f.t = t;
return (rp_flash_erase(&f, XIP_FLASH_START, MAX_FLASH)) ? false: true;
struct rp_priv_s *ps = (struct rp_priv_s*)t->target_storage;
ps->is_monitor = true;
bool res = (rp_flash_erase(&f, XIP_FLASH_START, MAX_FLASH)) ? false: true;
ps->is_monitor = false;
return res;
}
const struct command_s rp_cmd_list[] = {

View File

@ -19,7 +19,6 @@
*/
#include "general.h"
#include "target.h"
#include "target_internal.h"
#include <stdarg.h>
@ -342,7 +341,6 @@ void target_detach(target *t)
t->detach(t);
t->attached = false;
#if PC_HOSTED == 1
# include "platform.h"
platform_buffer_flush();
#endif
}