Infrastructure for command line interface to target
- Program, read and verify flash - Test mode: Probe and attach to device and exit
This commit is contained in:
parent
ab396f9745
commit
da5a0cd3f5
|
@ -8,4 +8,5 @@ else ifneq (, $(findstring cygwin, $(SYS)))
|
|||
LDFLAGS += -lusb-1.0 -lws2_32
|
||||
endif
|
||||
VPATH += platforms/pc
|
||||
SRC += timing.c \
|
||||
SRC += timing.c cl_utils.c
|
||||
CFLAGS +=-I ./target -I./platforms/pc
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
struct ftdi_context *ftdic;
|
||||
|
||||
#include "cl_utils.h"
|
||||
|
||||
#define BUF_SIZE 4096
|
||||
static uint8_t outbuf[BUF_SIZE];
|
||||
static uint16_t bufptr = 0;
|
||||
|
@ -180,29 +182,21 @@ cable_desc_t cable_desc[] = {
|
|||
|
||||
void platform_init(int argc, char **argv)
|
||||
{
|
||||
int err;
|
||||
int c;
|
||||
unsigned index = 0;
|
||||
char *serial = NULL;
|
||||
char * cablename = "ftdi";
|
||||
while((c = getopt(argc, argv, "c:s:")) != -1) {
|
||||
switch(c) {
|
||||
case 'c':
|
||||
cablename = optarg;
|
||||
break;
|
||||
case 's':
|
||||
serial = optarg;
|
||||
break;
|
||||
}
|
||||
}
|
||||
BMP_CL_OPTIONS_t cl_opts = {0};
|
||||
cl_opts.opt_idstring = "Blackmagic Debug Probe for FTDI/MPSSE";
|
||||
cl_opts.opt_cable = "ftdi";
|
||||
cl_init(&cl_opts, argc, argv);
|
||||
|
||||
int err;
|
||||
unsigned index = 0;
|
||||
int ret = -1;
|
||||
for(index = 0; index < sizeof(cable_desc)/sizeof(cable_desc[0]);
|
||||
index++)
|
||||
if (strcmp(cable_desc[index].name, cablename) == 0)
|
||||
if (strcmp(cable_desc[index].name, cl_opts.opt_cable) == 0)
|
||||
break;
|
||||
|
||||
if (index == sizeof(cable_desc)/sizeof(cable_desc[0])){
|
||||
fprintf(stderr, "No cable matching %s found\n",cablename);
|
||||
fprintf(stderr, "No cable matching %s found\n", cl_opts.opt_cable);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
|
@ -226,32 +220,42 @@ void platform_init(int argc, char **argv)
|
|||
if((err = ftdi_set_interface(ftdic, active_cable->interface)) != 0) {
|
||||
fprintf(stderr, "ftdi_set_interface: %d: %s\n",
|
||||
err, ftdi_get_error_string(ftdic));
|
||||
abort();
|
||||
goto error_1;
|
||||
}
|
||||
if((err = ftdi_usb_open_desc(
|
||||
ftdic, active_cable->vendor, active_cable->product,
|
||||
active_cable->description, serial)) != 0) {
|
||||
active_cable->description, cl_opts.opt_serial)) != 0) {
|
||||
fprintf(stderr, "unable to open ftdi device: %d (%s)\n",
|
||||
err, ftdi_get_error_string(ftdic));
|
||||
abort();
|
||||
goto error_1;
|
||||
}
|
||||
|
||||
if((err = ftdi_set_latency_timer(ftdic, 1)) != 0) {
|
||||
fprintf(stderr, "ftdi_set_latency_timer: %d: %s\n",
|
||||
err, ftdi_get_error_string(ftdic));
|
||||
abort();
|
||||
goto error_2;
|
||||
}
|
||||
if((err = ftdi_set_baudrate(ftdic, 1000000)) != 0) {
|
||||
fprintf(stderr, "ftdi_set_baudrate: %d: %s\n",
|
||||
err, ftdi_get_error_string(ftdic));
|
||||
abort();
|
||||
goto error_2;
|
||||
}
|
||||
if((err = ftdi_write_data_set_chunksize(ftdic, BUF_SIZE)) != 0) {
|
||||
fprintf(stderr, "ftdi_write_data_set_chunksize: %d: %s\n",
|
||||
err, ftdi_get_error_string(ftdic));
|
||||
abort();
|
||||
goto error_2;
|
||||
}
|
||||
assert(gdb_if_init() == 0);
|
||||
if (cl_opts.opt_mode != BMP_MODE_DEBUG) {
|
||||
ret = cl_execute(&cl_opts);
|
||||
} else {
|
||||
assert(gdb_if_init() == 0);
|
||||
return;
|
||||
}
|
||||
error_2:
|
||||
ftdi_usb_close(ftdic);
|
||||
error_1:
|
||||
ftdi_free(ftdic);
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
void platform_srst_set_val(bool assert)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
TARGET=blackmagic_stlinkv2
|
||||
SYS = $(shell $(CC) -dumpmachine)
|
||||
CFLAGS += -DPC_HOSTED -DNO_LIBOPENCM3 -DSTLINKV2 -DJTAG_HL -DENABLE_DEBUG
|
||||
CFLAGS +=-I ./target
|
||||
CFLAGS +=-I ./target -I./platforms/pc
|
||||
LDFLAGS += -lusb-1.0
|
||||
ifneq (, $(findstring mingw, $(SYS)))
|
||||
LDFLAGS += -lws2_32
|
||||
|
@ -9,5 +9,5 @@ else ifneq (, $(findstring cygwin, $(SYS)))
|
|||
LDFLAGS += -lws2_32
|
||||
endif
|
||||
VPATH += platforms/pc
|
||||
SRC += timing.c stlinkv2.c
|
||||
SRC += timing.c stlinkv2.c cl_utils.c
|
||||
OWN_HL = 1
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
#include <ctype.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "cl_utils.h"
|
||||
|
||||
#if !defined(timersub)
|
||||
/* This is a copy from GNU C Library (GNU LGPL 2.1), sys/time.h. */
|
||||
# define timersub(a, b, result) \
|
||||
|
@ -687,46 +689,18 @@ static void stlink_resetsys(void)
|
|||
send_recv(cmd, 16, data, 2);
|
||||
}
|
||||
|
||||
void stlink_help(char **argv)
|
||||
{
|
||||
DEBUG("Blackmagic Debug Probe on STM StlinkV2 and 3\n\n");
|
||||
DEBUG("Usage: %s [options]\n", argv[0]);
|
||||
DEBUG("\t-v[1|2]\t\t: Increasing verbosity\n");
|
||||
DEBUG("\t-s \"string\"\t: Use Stlink with (partial) "
|
||||
"serial number \"string\"\n");
|
||||
DEBUG("\t-n\t\t: Exit immediate if no device found\n");
|
||||
DEBUG("\t-h\t\t: This help.\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void stlink_init(int argc, char **argv)
|
||||
{
|
||||
BMP_CL_OPTIONS_t cl_opts = {0};
|
||||
cl_opts.opt_idstring = "Blackmagic Debug Probe on StlinkV2/3";
|
||||
cl_init(&cl_opts, argc, argv);
|
||||
libusb_device **devs, *dev;
|
||||
int r;
|
||||
int ret = -1;
|
||||
atexit(exit_function);
|
||||
signal(SIGTERM, sigterm_handler);
|
||||
signal(SIGINT, sigterm_handler);
|
||||
libusb_init(&Stlink.libusb_ctx);
|
||||
char *serial = NULL;
|
||||
int c;
|
||||
bool wait_for_attach = true;
|
||||
while((c = getopt(argc, argv, "ns:v:h")) != -1) {
|
||||
switch(c) {
|
||||
case 'n':
|
||||
wait_for_attach = false;
|
||||
break;
|
||||
case 's':
|
||||
serial = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
if (optarg)
|
||||
debug_level = atoi(optarg);
|
||||
break;
|
||||
case 'h':
|
||||
stlink_help(argv);
|
||||
break;
|
||||
}
|
||||
}
|
||||
r = libusb_init(NULL);
|
||||
if (r < 0)
|
||||
DEBUG("Failed: %s", libusb_strerror(r));
|
||||
|
@ -794,7 +768,8 @@ void stlink_init(int argc, char **argv)
|
|||
else
|
||||
snprintf(s, 3, "%02x", *p & 0xff);
|
||||
}
|
||||
if (serial && (!strncmp(Stlink.serial, serial, strlen(serial))))
|
||||
if (cl_opts.opt_serial && (!strncmp(Stlink.serial, cl_opts.opt_serial,
|
||||
strlen(cl_opts.opt_serial))))
|
||||
DEBUG("Found ");
|
||||
if (desc.idProduct == PRODUCT_ID_STLINKV2) {
|
||||
DEBUG("STLINKV20 serial %s\n", Stlink.serial);
|
||||
|
@ -820,8 +795,9 @@ void stlink_init(int argc, char **argv)
|
|||
DEBUG("Unknown STLINK variant, serial %s\n", Stlink.serial);
|
||||
}
|
||||
nr_stlinks++;
|
||||
if (serial) {
|
||||
if (!strncmp(Stlink.serial, serial, strlen(serial))) {
|
||||
if (cl_opts.opt_serial) {
|
||||
if (!strncmp(Stlink.serial, cl_opts.opt_serial,
|
||||
strlen(cl_opts.opt_serial))) {
|
||||
break;
|
||||
} else {
|
||||
libusb_close(Stlink.handle);
|
||||
|
@ -835,15 +811,15 @@ void stlink_init(int argc, char **argv)
|
|||
}
|
||||
libusb_free_device_list(devs, 1);
|
||||
if (!Stlink.handle) {
|
||||
if (nr_stlinks && serial) {
|
||||
DEBUG("No Stlink with given serial number %s\n", serial);
|
||||
if (nr_stlinks && cl_opts.opt_serial) {
|
||||
DEBUG("No Stlink with given serial number %s\n", cl_opts.opt_serial);
|
||||
} else if (nr_stlinks > 1) {
|
||||
DEBUG("Multiple Stlinks. Please specify serial number\n");
|
||||
goto error;
|
||||
} else {
|
||||
DEBUG("No Stlink device found!\n");
|
||||
}
|
||||
if (hotplug && wait_for_attach) {
|
||||
if (hotplug && !cl_opts.opt_no_wait) {
|
||||
libusb_hotplug_callback_handle hp;
|
||||
int rc = libusb_hotplug_register_callback
|
||||
(NULL, LIBUSB_HOTPLUG_EVENT_DEVICE_ARRIVED, 0,
|
||||
|
@ -855,9 +831,9 @@ void stlink_init(int argc, char **argv)
|
|||
goto error;
|
||||
}
|
||||
DEBUG("Waiting for %sST device%s%s to attach\n",
|
||||
(serial)? "" : "some ",
|
||||
(serial)? " with serial ": "",
|
||||
(serial)? serial: "");
|
||||
(cl_opts.opt_serial)? "" : "some ",
|
||||
(cl_opts.opt_serial)? " with serial ": "",
|
||||
(cl_opts.opt_serial)? cl_opts.opt_serial: "");
|
||||
DEBUG("Terminate with ^C\n");
|
||||
while (has_attached == 0) {
|
||||
rc = libusb_handle_events (NULL);
|
||||
|
@ -925,13 +901,17 @@ void stlink_init(int argc, char **argv)
|
|||
}
|
||||
stlink_leave_state();
|
||||
stlink_resetsys();
|
||||
assert(gdb_if_init() == 0);
|
||||
return;
|
||||
if (cl_opts.opt_mode != BMP_MODE_DEBUG) {
|
||||
ret = cl_execute(&cl_opts);
|
||||
} else {
|
||||
assert(gdb_if_init() == 0);
|
||||
return;
|
||||
}
|
||||
error_1:
|
||||
libusb_close(Stlink.handle);
|
||||
error:
|
||||
libusb_exit(Stlink.libusb_ctx);
|
||||
exit(-1);
|
||||
exit(ret);
|
||||
}
|
||||
|
||||
void stlink_srst_set_val(bool assert)
|
||||
|
|
|
@ -0,0 +1,355 @@
|
|||
/*
|
||||
* This file is part of the Black Magic Debug project.
|
||||
*
|
||||
* Copyright (C) 2019
|
||||
* Written by 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
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* This file allows pc-hosted BMP platforms to erase and flash a
|
||||
* binary file from the command line.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "general.h"
|
||||
#include "target.h"
|
||||
#include "target_internal.h"
|
||||
|
||||
#include "cl_utils.h"
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
#else
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
struct mmap_data {
|
||||
void *data;
|
||||
size_t size;
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
HANDLE hFile;
|
||||
HANDLE hMapFile;
|
||||
#else
|
||||
int fd;
|
||||
#endif
|
||||
};
|
||||
|
||||
static int bmp_mmap(char *file, struct mmap_data *map)
|
||||
{
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
map->hFile = CreateFile(file, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ,
|
||||
NULL, OPEN_ALWAYS, 0, NULL);
|
||||
if (map->hFile == INVALID_HANDLE_VALUE) {
|
||||
DEBUG("Open file %s failed: %s\n", file, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
map->size = GetFileSize(map->hFile, NULL);
|
||||
map->hMapFile = CreateFileMapping(
|
||||
map->hFile,
|
||||
NULL, /* default security */
|
||||
PAGE_READONLY , /* read only access */
|
||||
0, /* max. object size high */
|
||||
0, /* max. object size low */
|
||||
NULL); /* name of mapping object */
|
||||
|
||||
if (map->hMapFile == NULL || map->hMapFile == INVALID_HANDLE_VALUE) {
|
||||
DEBUG("Map file %s failed: %s\n", file, strerror(errno));
|
||||
CloseHandle(map->hFile);
|
||||
return -1;
|
||||
}
|
||||
map->data = MapViewOfFile(map->hMapFile, FILE_MAP_READ, 0, 0, 0);
|
||||
if (!map->data) {
|
||||
printf("Could not create file mapping object (%s).\n",
|
||||
strerror(errno));
|
||||
CloseHandle(map->hMapFile);
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
map->fd = open(file, O_RDONLY | O_BINARY);
|
||||
if (map->fd < 0) {
|
||||
DEBUG("Open file %s failed: %s\n", file, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
struct stat stat;
|
||||
if (fstat(map->fd, &stat))
|
||||
return -1;
|
||||
map->size = stat.st_size;
|
||||
map->data = mmap(NULL, stat.st_size, PROT_READ, MAP_PRIVATE, map->fd, 0);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void bmp_munmap(struct mmap_data *map)
|
||||
{
|
||||
#if defined(_WIN32) || defined(__CYGWIN__)
|
||||
UnmapViewOfFile(map->data);
|
||||
CloseHandle(map->hMapFile);
|
||||
CloseHandle(map->hFile);
|
||||
#else
|
||||
munmap(map->data, map->size);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void cl_help(char **argv, BMP_CL_OPTIONS_t *opt)
|
||||
{
|
||||
printf("%s\n\n", opt->opt_idstring);
|
||||
printf("Usage: %s [options]\n", argv[0]);
|
||||
printf("\t-h\t\t: This help.\n");
|
||||
printf("\t-v[1|2]\t\t: Increasing verbosity\n");
|
||||
printf("\t-s \"string\"\t: Use dongle with (partial) "
|
||||
"serial number \"string\"\n");
|
||||
printf("\t-c \"string\"\t: Use ftdi dongle with type \"string\"\n");
|
||||
printf("\t-n\t\t: Exit immediate if no device found\n");
|
||||
printf("\tRun mode related options:\n");
|
||||
printf("\t-t\t\t: Scan SWD, with no target found scan jtag and exit\n");
|
||||
printf("\t-V\t\t: Verify flash against binary file\n");
|
||||
printf("\t-r\t\t: Read flash and write to binary file\n");
|
||||
printf("\t\tDefault mode is starting the debug server\n");
|
||||
printf("\tFlash operation modifiers options:\n");
|
||||
printf("\t-a <num>\t: Start flash operation at flash address <num>\n"
|
||||
"\t\t\tDefault start is 0x08000000\n");
|
||||
printf("\t-S <num>\t: Read <num> bytes. Default is until read fails.\n");
|
||||
printf("\t-j\t\t: Use JTAG. SWD is default.\n");
|
||||
printf("\t <file>\t\t: Use (binary) file <file> for flash operation\n"
|
||||
"\t\t\tGiven <file> writes to flash if neither -r or -V is given\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv)
|
||||
{
|
||||
int c;
|
||||
opt->opt_target_dev = 1;
|
||||
opt->opt_flash_start = 0x08000000;
|
||||
opt->opt_flash_size = 16 * 1024 *1024;
|
||||
while((c = getopt(argc, argv, "hv::s:c:nN:tVta:S:jr")) != -1) {
|
||||
switch(c) {
|
||||
case 'c':
|
||||
if (optarg)
|
||||
opt->opt_cable = optarg;
|
||||
break;
|
||||
case 'h':
|
||||
cl_help(argv, opt);
|
||||
break;
|
||||
case 'v':
|
||||
if (optarg)
|
||||
opt->opt_debuglevel = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case 'j':
|
||||
opt->opt_usejtag = true;
|
||||
break;
|
||||
case 'n':
|
||||
opt->opt_no_wait = true;
|
||||
break;
|
||||
case 's':
|
||||
if (optarg)
|
||||
opt->opt_serial = optarg;
|
||||
break;
|
||||
case 't':
|
||||
opt->opt_mode = BMP_MODE_TEST;
|
||||
break;
|
||||
case 'V':
|
||||
opt->opt_mode = BMP_MODE_FLASH_VERIFY;
|
||||
break;
|
||||
case 'r':
|
||||
opt->opt_mode = BMP_MODE_FLASH_READ;
|
||||
break;
|
||||
case 'a':
|
||||
if (optarg)
|
||||
opt->opt_flash_start = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case 'N':
|
||||
if (optarg)
|
||||
opt->opt_target_dev = strtol(optarg, NULL, 0);
|
||||
break;
|
||||
case 'S':
|
||||
if (optarg) {
|
||||
char *endptr;
|
||||
opt->opt_flash_size = strtol(optarg, &endptr, 0);
|
||||
if (endptr) {
|
||||
switch(endptr[0]) {
|
||||
case 'k':
|
||||
case 'K':
|
||||
opt->opt_flash_size *= 1024;
|
||||
break;
|
||||
case 'm':
|
||||
case 'M':
|
||||
opt->opt_flash_size *= 1024 * 1024;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((optind) && argv[optind]) {
|
||||
if (opt->opt_mode == BMP_MODE_DEBUG)
|
||||
opt->opt_mode = BMP_MODE_FLASH_WRITE;
|
||||
opt->opt_flash_file = argv[optind];
|
||||
}
|
||||
/* Checks */
|
||||
if ((opt->opt_flash_file) && (opt->opt_mode == BMP_MODE_TEST)) {
|
||||
printf("Ignoring filename in test mode\n");
|
||||
opt->opt_flash_file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int cl_execute(BMP_CL_OPTIONS_t *opt)
|
||||
{
|
||||
int res = -1;
|
||||
int num_targets;
|
||||
if (opt->opt_mode == BMP_MODE_TEST) {
|
||||
printf("Running in Test Mode\n");
|
||||
num_targets = adiv5_swdp_scan();
|
||||
if (num_targets == 0)
|
||||
num_targets = jtag_scan(NULL);
|
||||
if (num_targets)
|
||||
return 0;
|
||||
else
|
||||
return res;
|
||||
}
|
||||
if (opt->opt_usejtag) {
|
||||
num_targets = jtag_scan(NULL);
|
||||
} else {
|
||||
num_targets = adiv5_swdp_scan();
|
||||
}
|
||||
if (!num_targets) {
|
||||
DEBUG("No target found\n");
|
||||
return res;
|
||||
}
|
||||
if (opt->opt_target_dev > num_targets) {
|
||||
DEBUG("Given target nummer %d not available\n", opt->opt_target_dev);
|
||||
return res;
|
||||
}
|
||||
struct target_controller tc = {NULL};
|
||||
target *t = target_attach_n(opt->opt_target_dev, &tc);
|
||||
if (!t) {
|
||||
DEBUG("Can not attach to target %d\n", opt->opt_target_dev);
|
||||
goto target_detach;
|
||||
}
|
||||
int read_file = -1;
|
||||
struct mmap_data map = {0};
|
||||
if ((opt->opt_mode == BMP_MODE_FLASH_WRITE) ||
|
||||
(opt->opt_mode == BMP_MODE_FLASH_VERIFY)) {
|
||||
int mmap_res = bmp_mmap(opt->opt_flash_file, &map);
|
||||
if (mmap_res) {
|
||||
DEBUG("Can not map file: %s. Aborting!\n", strerror(errno));
|
||||
goto target_detach;
|
||||
}
|
||||
} else {
|
||||
/* Open as binary */
|
||||
read_file = open(opt->opt_flash_file, O_CREAT | O_RDWR | O_BINARY,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (read_file == -1) {
|
||||
printf("Error opening flashfile %s for read: %s\n",
|
||||
opt->opt_flash_file, strerror(errno));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
if (opt->opt_flash_size < map.size)
|
||||
/* restrict to size given on command line */
|
||||
map.size = opt->opt_flash_size;
|
||||
if (opt->opt_mode == BMP_MODE_FLASH_WRITE) {
|
||||
DEBUG("Erase %zu bytes at 0x%08" PRIx32 "\n", map.size,
|
||||
opt->opt_flash_start);
|
||||
unsigned int erased = target_flash_erase(t, opt->opt_flash_start,
|
||||
map.size);
|
||||
if (erased) {
|
||||
DEBUG("Erased failed!\n");
|
||||
goto free_map;
|
||||
} else {
|
||||
DEBUG("Flashing %zu bytes at 0x%08" PRIx32 "\n",
|
||||
map.size, opt->opt_flash_start);
|
||||
unsigned int flashed = target_flash_write(t, opt->opt_flash_start,
|
||||
map.data, map.size);
|
||||
/* Buffered write cares for padding*/
|
||||
if (flashed) {
|
||||
DEBUG("Flashing failed!\n");
|
||||
} else {
|
||||
DEBUG("Success!\n");
|
||||
res = 0;
|
||||
}
|
||||
}
|
||||
target_flash_done(t);
|
||||
} else {
|
||||
#define WORKSIZE 1024
|
||||
uint8_t *data = malloc(WORKSIZE);
|
||||
if (!data) {
|
||||
printf("Can not malloc memory for flash read/verify operation\n");
|
||||
return res;
|
||||
}
|
||||
if (opt->opt_mode == BMP_MODE_FLASH_READ)
|
||||
printf("Reading flash from 0x%08" PRIx32 " for %zu"
|
||||
" bytes to %s\n", opt->opt_flash_start, opt->opt_flash_size,
|
||||
opt->opt_flash_file);
|
||||
uint32_t flash_src = opt->opt_flash_start;
|
||||
size_t size = opt->opt_flash_size;
|
||||
int bytes_read = 0;
|
||||
void *flash = map.data;
|
||||
while (size) {
|
||||
int worksize = (size > WORKSIZE) ? WORKSIZE : size;
|
||||
int n_read = target_mem_read(t, data, flash_src, worksize);
|
||||
if (n_read) {
|
||||
if (opt->opt_flash_size == 0) {/* we reached end of flash */
|
||||
printf("Reached end of flash at size %" PRId32 "\n",
|
||||
flash_src - opt->opt_flash_start);
|
||||
break;
|
||||
} else {
|
||||
printf("Read failed at flash address 0x%08" PRIx32 "\n",
|
||||
flash_src);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
bytes_read += worksize;
|
||||
}
|
||||
if (opt->opt_mode == BMP_MODE_FLASH_VERIFY) {
|
||||
int difference = memcmp(data, flash, worksize);
|
||||
if (difference){
|
||||
printf("Verify failed at flash region 0x%08" PRIx32 "\n",
|
||||
flash_src);
|
||||
return -1;
|
||||
}
|
||||
flash += worksize;
|
||||
} else if (read_file != -1) {
|
||||
int written = write(read_file, data, worksize);
|
||||
if (written < worksize) {
|
||||
printf("Read failed at flash region 0x%08" PRIx32 "\n",
|
||||
flash_src);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
flash_src += worksize;
|
||||
size -= worksize;
|
||||
if (size <= 0)
|
||||
res = 0;
|
||||
}
|
||||
if (read_file != -1)
|
||||
close(read_file);
|
||||
printf("Read/Verifed succeeded for %d bytes\n", bytes_read);
|
||||
}
|
||||
target_reset(t);
|
||||
free_map:
|
||||
if (map.size)
|
||||
bmp_munmap(&map);
|
||||
target_detach:
|
||||
if (t)
|
||||
target_detach(t);
|
||||
return res;
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* This file is part of the Black Magic Debug project.
|
||||
*
|
||||
* Copyright (C) 2019 Uwe Bonnes
|
||||
* Written by 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
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* This file implements the interface to command line command for PC-Hosted
|
||||
* platforms.
|
||||
*/
|
||||
#if !defined(__CL_UTILS_H)
|
||||
#define __CL_UTILS_H
|
||||
|
||||
enum bmp_cl_mode {
|
||||
BMP_MODE_DEBUG,
|
||||
BMP_MODE_TEST,
|
||||
BMP_MODE_FLASH_WRITE,
|
||||
BMP_MODE_FLASH_READ,
|
||||
BMP_MODE_FLASH_VERIFY
|
||||
};
|
||||
|
||||
typedef struct BMP_CL_OPTIONS_s {
|
||||
enum bmp_cl_mode opt_mode;
|
||||
bool opt_usejtag;
|
||||
bool opt_no_wait;
|
||||
char *opt_flash_file;
|
||||
char *opt_serial;
|
||||
char *opt_cable;
|
||||
int opt_debuglevel;
|
||||
int opt_target_dev;
|
||||
uint32_t opt_flash_start;
|
||||
size_t opt_flash_size;
|
||||
char *opt_idstring;
|
||||
}BMP_CL_OPTIONS_t;
|
||||
|
||||
void cl_init(BMP_CL_OPTIONS_t *opt, int argc, char **argv);
|
||||
int cl_execute(BMP_CL_OPTIONS_t *opt);
|
||||
#endif
|
Loading…
Reference in New Issue