to your /etc/modprobe.conf or /etc/modprobe.d/local.conf (or add the "quirks=..."
part to an existing options line for usb-storage).
+
+ https://wiki.kubuntu.org/Kernel/Debugging/USB explains the protocoll and
+ would allow to replace the sg access to pure libusb access
*/
#include <sys/stat.h>
#include <sys/mman.h>
-// sgutils2 (apt-get install libsgutils2-dev)
-#include <scsi/sg_lib.h>
-#include <scsi/sg_pt.h>
-
#include "stlink-common.h"
#include "stlink-sg.h"
+#include "uglylogging.h"
+#define LOG_TAG __FILE__
+#define DLOG(format, args...) ugly_log(UDEBUG, LOG_TAG, format, ## args)
+#define ILOG(format, args...) ugly_log(UINFO, LOG_TAG, format, ## args)
+#define WLOG(format, args...) ugly_log(UWARN, LOG_TAG, format, ## args)
+#define fatal(format, args...) ugly_log(UFATAL, LOG_TAG, format, ## args)
// Suspends execution of the calling process for
// (at least) ms milliseconds.
usleep(1000 * ms);
}
-static void write_uint32(unsigned char* buf, uint32_t ui) {
- if (!is_bigendian()) { // le -> le (don't swap)
- buf[0] = ((unsigned char*) &ui)[0];
- buf[1] = ((unsigned char*) &ui)[1];
- buf[2] = ((unsigned char*) &ui)[2];
- buf[3] = ((unsigned char*) &ui)[3];
- } else {
- buf[0] = ((unsigned char*) &ui)[3];
- buf[1] = ((unsigned char*) &ui)[2];
- buf[2] = ((unsigned char*) &ui)[1];
- buf[3] = ((unsigned char*) &ui)[0];
- }
-}
-
-static void write_uint16(unsigned char* buf, uint16_t ui) {
- if (!is_bigendian()) { // le -> le (don't swap)
- buf[0] = ((unsigned char*) &ui)[0];
- buf[1] = ((unsigned char*) &ui)[1];
- } else {
- buf[0] = ((unsigned char*) &ui)[1];
- buf[1] = ((unsigned char*) &ui)[0];
- }
-}
-
-static uint32_t read_uint32(const unsigned char *c, const int pt) {
- uint32_t ui;
- char *p = (char *) &ui;
-
- if (!is_bigendian()) { // le -> le (don't swap)
- p[0] = c[pt];
- p[1] = c[pt + 1];
- p[2] = c[pt + 2];
- p[3] = c[pt + 3];
- } else {
- p[0] = c[pt + 3];
- p[1] = c[pt + 2];
- p[2] = c[pt + 1];
- p[3] = c[pt];
- }
- return ui;
-}
-
static void clear_cdb(struct stlink_libsg *sl) {
- for (int i = 0; i < sizeof (sl->cdb_cmd_blk); i++)
+ for (size_t i = 0; i < sizeof (sl->cdb_cmd_blk); i++)
sl->cdb_cmd_blk[i] = 0;
// set default
sl->cdb_cmd_blk[0] = STLINK_DEBUG_COMMAND;
// E.g. make the valgrind happy.
static void clear_buf(stlink_t *sl) {
- DD(sl, "*** clear_buf ***\n");
- for (int i = 0; i < sizeof (sl->q_buf); i++)
+ DLOG("*** clear_buf ***\n");
+ for (size_t i = 0; i < sizeof (sl->q_buf); i++)
sl->q_buf[i] = 0;
}
void _stlink_sg_close(stlink_t *sl) {
if (sl) {
+#if FINISHED_WITH_SG
struct stlink_libsg *slsg = sl->backend_data;
scsi_pt_close_device(slsg->sg_fd);
- // CAUTION!? s this right?
free(slsg);
- free(sl);
- }
-}
-
-// Exit the jtag or swd mode and enter the mass mode.
-
-void _stlink_sg_exit_debug_mode(stlink_t *stl) {
-
- if (stl) {
- struct stlink_libsg* sl = stl->backend_data;
- clear_cdb(sl);
- sl->cdb_cmd_blk[1] = STLINK_DEBUG_EXIT;
- stl->q_len = 0; // >0 -> aboard
- stlink_q(stl);
+#endif
}
}
-
//TODO rewrite/cleanup, save the error in sl
+#if FINISHED_WITH_SG
static void stlink_confirm_inq(stlink_t *stl, struct sg_pt_base *ptvp) {
struct stlink_libsg *sl = stl->backend_data;
const int e = sl->do_scsi_pt_err;
}
const int duration = get_scsi_pt_duration_ms(ptvp);
if ((stl->verbose > 1) && (duration >= 0))
- DD(stl, " duration=%d ms\n", duration);
+ DLOG(" duration=%d ms\n", duration);
// XXX stlink fw sends broken residue, so ignore it and use the known q_len
// "usb-storage quirks=483:3744:r"
switch (cat) {
case SCSI_PT_RESULT_GOOD:
if (stl->verbose && (resid > 0))
- DD(stl, " notice: requested %d bytes but "
+ DLOG(" notice: requested %d bytes but "
"got %d bytes, ignore [broken] residue = %d\n",
stl->q_len, dsize, resid);
break;
sg_get_scsi_status_str(
get_scsi_pt_status_response(ptvp), sizeof (buf),
buf);
- DD(stl, " scsi status: %s\n", buf);
+ DLOG(" scsi status: %s\n", buf);
}
return;
case SCSI_PT_RESULT_SENSE:
if (stl->verbose) {
sg_get_sense_str("", sl->sense_buf, slen, (stl->verbose
> 1), sizeof (buf), buf);
- DD(stl, "%s", buf);
+ DLOG("%s", buf);
}
if (stl->verbose && (resid > 0)) {
if ((stl->verbose) || (stl->q_len > 0))
- DD(stl, " requested %d bytes but "
+ DLOG(" requested %d bytes but "
"got %d bytes\n", stl->q_len, dsize);
}
return;
// The 'host_status' field has the following values:
// [0x07] Internal error detected in the host adapter.
// This may not be fatal (and the command may have succeeded).
- DD(stl, " transport: %s", buf);
+ DLOG(" transport: %s", buf);
}
return;
case SCSI_PT_RESULT_OS_ERR:
if (stl->verbose) {
get_scsi_pt_os_err_str(ptvp, sizeof (buf), buf);
- DD(stl, " os: %s", buf);
+ DLOG(" os: %s", buf);
}
return;
default:
"category (%d)\n", cat);
}
}
+#endif
-void stlink_q(stlink_t *stl) {
- struct stlink_libsg* sl = stl->backend_data;
- DD(stl, "CDB[");
+void stlink_q(stlink_t *sl) {
+#if FINISHED_WITH_SG
+ struct stlink_libsg* sg = sl->backend_data;
+ DLOG("CDB[");
for (int i = 0; i < CDB_SL; i++)
- DD(stl, " 0x%02x", (unsigned int) sl->cdb_cmd_blk[i]);
- DD(stl, "]\n");
+ DLOG(" 0x%02x", (unsigned int) sg->cdb_cmd_blk[i]);
+ DLOG("]\n");
// Get control command descriptor of scsi structure,
// (one object per command!!)
return;
}
- set_scsi_pt_cdb(ptvp, sl->cdb_cmd_blk, sizeof (sl->cdb_cmd_blk));
+ set_scsi_pt_cdb(ptvp, sg->cdb_cmd_blk, sizeof (sg->cdb_cmd_blk));
// set buffer for sense (error information) data
- set_scsi_pt_sense(ptvp, sl->sense_buf, sizeof (sl->sense_buf));
+ set_scsi_pt_sense(ptvp, sg->sense_buf, sizeof (sg->sense_buf));
// Set a buffer to be used for data transferred from device
- if (sl->q_data_dir == Q_DATA_IN) {
+ if (sg->q_data_dir == Q_DATA_IN) {
//clear_buf(sl);
- set_scsi_pt_data_in(ptvp, stl->q_buf, stl->q_len);
+ set_scsi_pt_data_in(ptvp, sl->q_buf, sl->q_len);
} else {
- set_scsi_pt_data_out(ptvp, stl->q_buf, stl->q_len);
+ set_scsi_pt_data_out(ptvp, sl->q_buf, sl->q_len);
}
// Executes SCSI command (or at least forwards it to lower layers).
- sl->do_scsi_pt_err = do_scsi_pt(ptvp, sl->sg_fd, SG_TIMEOUT_SEC,
- stl->verbose);
+ sg->do_scsi_pt_err = do_scsi_pt(ptvp, sg->sg_fd, SG_TIMEOUT_SEC,
+ sl->verbose);
// check for scsi errors
- stlink_confirm_inq(stl, ptvp);
+ stlink_confirm_inq(sl, ptvp);
// TODO recycle: clear_scsi_pt_obj(struct sg_pt_base * objp);
destruct_scsi_pt_obj(ptvp);
+#endif
}
// TODO thinking, cleanup
-void stlink_parse_version(stlink_t *stl) {
- struct stlink_libsg *sl = stl->backend_data;
- sl->st_vid = 0;
- sl->stlink_pid = 0;
- if (stl->q_len <= 0) {
- fprintf(stderr, "Error: could not parse the stlink version");
- return;
- }
- stlink_print_data(stl);
- uint32_t b0 = stl->q_buf[0]; //lsb
- uint32_t b1 = stl->q_buf[1];
- uint32_t b2 = stl->q_buf[2];
- uint32_t b3 = stl->q_buf[3];
- uint32_t b4 = stl->q_buf[4];
- uint32_t b5 = stl->q_buf[5]; //msb
-
- // b0 b1 || b2 b3 | b4 b5
- // 4b | 6b | 6b || 2B | 2B
- // stlink_v | jtag_v | swim_v || st_vid | stlink_pid
-
- sl->stlink_v = (b0 & 0xf0) >> 4;
- sl->jtag_v = ((b0 & 0x0f) << 2) | ((b1 & 0xc0) >> 6);
- sl->swim_v = b1 & 0x3f;
- sl->st_vid = (b3 << 8) | b2;
- sl->stlink_pid = (b5 << 8) | b4;
-
- if (stl->verbose < 2)
- return;
-
- DD(stl, "st vid = 0x%04x (expect 0x%04x)\n",
- sl->st_vid, USB_ST_VID);
- DD(stl, "stlink pid = 0x%04x (expect 0x%04x)\n",
- sl->stlink_pid, USB_STLINK_PID);
- DD(stl, "stlink version = 0x%x\n", sl->stlink_v);
- DD(stl, "jtag version = 0x%x\n", sl->jtag_v);
- DD(stl, "swim version = 0x%x\n", sl->swim_v);
- if (sl->jtag_v == 0)
- DD(stl,
- " notice: the firmware doesn't support a jtag/swd interface\n");
- if (sl->swim_v == 0)
- DD(stl,
- " notice: the firmware doesn't support a swim interface\n");
-
-}
-
-int stlink_mode(stlink_t *stl) {
- if (stl->q_len <= 0)
- return STLINK_DEV_UNKNOWN_MODE;
-
- stlink_print_data(stl);
-
- switch (stl->q_buf[0]) {
- case STLINK_DEV_DFU_MODE:
- DD(stl, "stlink mode: dfu\n");
- return STLINK_DEV_DFU_MODE;
- case STLINK_DEV_DEBUG_MODE:
- DD(stl, "stlink mode: debug (jtag or swd)\n");
- return STLINK_DEV_DEBUG_MODE;
- case STLINK_DEV_MASS_MODE:
- DD(stl, "stlink mode: mass\n");
- return STLINK_DEV_MASS_MODE;
- }
- return STLINK_DEV_UNKNOWN_MODE;
-}
-
void stlink_stat(stlink_t *stl, char *txt) {
if (stl->q_len <= 0)
return;
switch (stl->q_buf[0]) {
case STLINK_OK:
- DD(stl, " %s: ok\n", txt);
+ DLOG(" %s: ok\n", txt);
return;
case STLINK_FALSE:
- DD(stl, " %s: false\n", txt);
+ DLOG(" %s: false\n", txt);
return;
default:
- DD(stl, " %s: unknown\n", txt);
+ DLOG(" %s: unknown\n", txt);
}
}
+
void _stlink_sg_version(stlink_t *stl) {
struct stlink_libsg *sl = stl->backend_data;
- D(stl, "\n*** stlink_version ***\n");
+ DLOG("\n*** stlink_version ***\n");
clear_cdb(sl);
sl->cdb_cmd_blk[0] = STLINK_GET_VERSION;
stl->q_len = 6;
sl->q_addr = 0;
stlink_q(stl);
- stlink_parse_version(stl);
}
// Get stlink mode:
// STLINK_DEV_DFU_MODE || STLINK_DEV_MASS_MODE || STLINK_DEV_DEBUG_MODE
// usb dfu || usb mass || jtag or swd
-int stlink_current_mode(stlink_t *stl) {
+int _stlink_sg_current_mode(stlink_t *stl) {
struct stlink_libsg *sl = stl->backend_data;
- D(stl, "\n*** stlink_current_mode ***\n");
clear_cdb(sl);
sl->cdb_cmd_blk[0] = STLINK_GET_CURRENT_MODE;
stl->q_len = 2;
sl->q_addr = 0;
stlink_q(stl);
- return stlink_mode(stl);
+ return stl->q_buf[0];
}
// Exit the mass mode and enter the swd debug mode.
void _stlink_sg_enter_jtag_mode(stlink_t *sl) {
struct stlink_libsg *sg = sl->backend_data;
- D(sl, "\n*** stlink_enter_jtag_mode ***\n");
+ DLOG("\n*** stlink_enter_jtag_mode ***\n");
clear_cdb(sg);
sg->cdb_cmd_blk[1] = STLINK_DEBUG_ENTER;
sg->cdb_cmd_blk[2] = STLINK_DEBUG_ENTER_JTAG;
void _stlink_sg_exit_dfu_mode(stlink_t *sl) {
struct stlink_libsg *sg = sl->backend_data;
- D(sl, "\n*** stlink_exit_dfu_mode ***\n");
+ DLOG("\n*** stlink_exit_dfu_mode ***\n");
clear_cdb(sg);
sg->cdb_cmd_blk[0] = STLINK_DFU_COMMAND;
sg->cdb_cmd_blk[1] = STLINK_DFU_EXIT;
sg->q_addr = 0;
stlink_q(sl);
sl->core_id = read_uint32(sl->q_buf, 0);
- if (sl->verbose < 2)
- return;
- stlink_print_data(sl);
}
// Arm-core reset -> halted state.
void _stlink_sg_reset(stlink_t *sl) {
struct stlink_libsg *sg = sl->backend_data;
- D(sl, "\n*** stlink_reset ***\n");
clear_cdb(sg);
sg->cdb_cmd_blk[1] = STLINK_DEBUG_RESETSYS;
sl->q_len = 2;
// Arm-core status: halted or running.
-void _stlink_sg_status(struct stlink_libsg *sl) {
- D(sl, "\n*** stlink_status ***\n");
- clear_cdb(sl);
- sl->cdb_cmd_blk[1] = STLINK_DEBUG_GETSTATUS;
+void _stlink_sg_status(stlink_t *sl) {
+ struct stlink_libsg *sg = sl->backend_data;
+ DLOG("\n*** stlink_status ***\n");
+ clear_cdb(sg);
+ sg->cdb_cmd_blk[1] = STLINK_DEBUG_GETSTATUS;
sl->q_len = 2;
- sl->q_addr = 0;
+ sg->q_addr = 0;
stlink_q(sl);
}
// Force the core into the debug mode -> halted state.
-void stlink_force_debug(struct stlink_libsg *sl) {
- D(sl, "\n*** stlink_force_debug ***\n");
- clear_cdb(sl);
- sl->cdb_cmd_blk[1] = STLINK_DEBUG_FORCEDEBUG;
+void _stlink_sg_force_debug(stlink_t *sl) {
+ struct stlink_libsg *sg = sl->backend_data;
+ DLOG("\n*** stlink_force_debug ***\n");
+ clear_cdb(sg);
+ sg->cdb_cmd_blk[1] = STLINK_DEBUG_FORCEDEBUG;
sl->q_len = 2;
- sl->q_addr = 0;
+ sg->q_addr = 0;
stlink_q(sl);
stlink_stat(sl, "force debug");
}
// Read all arm-core registers.
-void stlink_read_all_regs(struct stlink_libsg *sl) {
- D(sl, "\n*** stlink_read_all_regs ***\n");
- clear_cdb(sl);
- sl->cdb_cmd_blk[1] = STLINK_DEBUG_READALLREGS;
+void _stlink_sg_read_all_regs(stlink_t *sl, reg *regp) {
+ struct stlink_libsg *sg = sl->backend_data;
+
+ /* unused */
+ regp = regp;
+
+ clear_cdb(sg);
+ sg->cdb_cmd_blk[1] = STLINK_DEBUG_READALLREGS;
sl->q_len = 84;
- sl->q_addr = 0;
+ sg->q_addr = 0;
stlink_q(sl);
stlink_print_data(sl);
+ // TODO - most of this should be re-extracted up....
+
// 0-3 | 4-7 | ... | 60-63 | 64-67 | 68-71 | 72-75 | 76-79 | 80-83
// r0 | r1 | ... | r15 | xpsr | main_sp | process_sp | rw | rw2
for (int i = 0; i < 16; i++) {
- sl->reg.r[i] = read_uint32(sl->q_buf, 4 * i);
+ sg->reg.r[i] = read_uint32(sl->q_buf, 4 * i);
if (sl->verbose > 1)
- DD(sl, "r%2d = 0x%08x\n", i, sl->reg.r[i]);
+ DLOG("r%2d = 0x%08x\n", i, sg->reg.r[i]);
}
- sl->reg.xpsr = read_uint32(sl->q_buf, 64);
- sl->reg.main_sp = read_uint32(sl->q_buf, 68);
- sl->reg.process_sp = read_uint32(sl->q_buf, 72);
- sl->reg.rw = read_uint32(sl->q_buf, 76);
- sl->reg.rw2 = read_uint32(sl->q_buf, 80);
+ sg->reg.xpsr = read_uint32(sl->q_buf, 64);
+ sg->reg.main_sp = read_uint32(sl->q_buf, 68);
+ sg->reg.process_sp = read_uint32(sl->q_buf, 72);
+ sg->reg.rw = read_uint32(sl->q_buf, 76);
+ sg->reg.rw2 = read_uint32(sl->q_buf, 80);
if (sl->verbose < 2)
return;
- DD(sl, "xpsr = 0x%08x\n", sl->reg.xpsr);
- DD(sl, "main_sp = 0x%08x\n", sl->reg.main_sp);
- DD(sl, "process_sp = 0x%08x\n", sl->reg.process_sp);
- DD(sl, "rw = 0x%08x\n", sl->reg.rw);
- DD(sl, "rw2 = 0x%08x\n", sl->reg.rw2);
+ DLOG("xpsr = 0x%08x\n", sg->reg.xpsr);
+ DLOG("main_sp = 0x%08x\n", sg->reg.main_sp);
+ DLOG("process_sp = 0x%08x\n", sg->reg.process_sp);
+ DLOG("rw = 0x%08x\n", sg->reg.rw);
+ DLOG("rw2 = 0x%08x\n", sg->reg.rw2);
}
// Read an arm-core register, the index must be in the range 0..20.
// 0 | 1 | ... | 15 | 16 | 17 | 18 | 19 | 20
// r0 | r1 | ... | r15 | xpsr | main_sp | process_sp | rw | rw2
-void stlink_read_reg(struct stlink_libsg *sl, int r_idx) {
- D(sl, "\n*** stlink_read_reg");
- DD(sl, " (%d) ***\n", r_idx);
-
- if (r_idx > 20 || r_idx < 0) {
- fprintf(stderr, "Error: register index must be in [0..20]\n");
- return;
- }
- clear_cdb(sl);
- sl->cdb_cmd_blk[1] = STLINK_DEBUG_READREG;
- sl->cdb_cmd_blk[2] = r_idx;
+void _stlink_sg_read_reg(stlink_t *sl, int r_idx, reg *regp) {
+ struct stlink_libsg *sg = sl->backend_data;
+ clear_cdb(sg);
+ sg->cdb_cmd_blk[1] = STLINK_DEBUG_READREG;
+ sg->cdb_cmd_blk[2] = r_idx;
sl->q_len = 4;
- sl->q_addr = 0;
+ sg->q_addr = 0;
stlink_q(sl);
// 0 | 1 | ... | 15 | 16 | 17 | 18 | 19 | 20
// 0-3 | 4-7 | ... | 60-63 | 64-67 | 68-71 | 72-75 | 76-79 | 80-83
stlink_print_data(sl);
uint32_t r = read_uint32(sl->q_buf, 0);
- DD(sl, "r_idx (%2d) = 0x%08x\n", r_idx, r);
+ DLOG("r_idx (%2d) = 0x%08x\n", r_idx, r);
switch (r_idx) {
case 16:
- sl->reg.xpsr = r;
+ regp->xpsr = r;
break;
case 17:
- sl->reg.main_sp = r;
+ regp->main_sp = r;
break;
case 18:
- sl->reg.process_sp = r;
+ regp->process_sp = r;
break;
case 19:
- sl->reg.rw = r; //XXX ?(primask, basemask etc.)
+ regp->rw = r; //XXX ?(primask, basemask etc.)
break;
case 20:
- sl->reg.rw2 = r; //XXX ?(primask, basemask etc.)
+ regp->rw2 = r; //XXX ?(primask, basemask etc.)
break;
default:
- sl->reg.r[r_idx] = r;
+ regp->r[r_idx] = r;
}
}
// 0 | 1 | ... | 15 | 16 | 17 | 18 | 19 | 20
// r0 | r1 | ... | r15 | xpsr | main_sp | process_sp | rw | rw2
-void stlink_write_reg(struct stlink_libsg *sl, uint32_t reg, int idx) {
- D(sl, "\n*** stlink_write_reg ***\n");
- clear_cdb(sl);
- sl->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEREG;
+void _stlink_sg_write_reg(stlink_t *sl, uint32_t reg, int idx) {
+ struct stlink_libsg *sg = sl->backend_data;
+ clear_cdb(sg);
+ sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEREG;
// 2: reg index
// 3-6: reg content
- sl->cdb_cmd_blk[2] = idx;
- write_uint32(sl->cdb_cmd_blk + 3, reg);
+ sg->cdb_cmd_blk[2] = idx;
+ write_uint32(sg->cdb_cmd_blk + 3, reg);
sl->q_len = 2;
- sl->q_addr = 0;
+ sg->q_addr = 0;
stlink_q(sl);
stlink_stat(sl, "write reg");
}
// XXX ?(atomic writes)
// TODO test
-void stlink_write_dreg(struct stlink_libsg *sl, uint32_t reg, uint32_t addr) {
- D(sl, "\n*** stlink_write_dreg ***\n");
- clear_cdb(sl);
- sl->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEDEBUGREG;
+void stlink_write_dreg(stlink_t *sl, uint32_t reg, uint32_t addr) {
+ struct stlink_libsg *sg = sl->backend_data;
+ DLOG("\n*** stlink_write_dreg ***\n");
+ clear_cdb(sg);
+ sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEDEBUGREG;
// 2-5: address of reg of the debug module
// 6-9: reg content
- write_uint32(sl->cdb_cmd_blk + 2, addr);
- write_uint32(sl->cdb_cmd_blk + 6, reg);
+ write_uint32(sg->cdb_cmd_blk + 2, addr);
+ write_uint32(sg->cdb_cmd_blk + 6, reg);
sl->q_len = 2;
- sl->q_addr = addr;
+ sg->q_addr = addr;
stlink_q(sl);
stlink_stat(sl, "write debug reg");
}
// Force the core exit the debug mode.
-void _stlink_sg_run(stlink_t *stl) {
- struct stlink_libsg sl = stl->backend_data;
- D(stl, "\n*** stlink_run ***\n");
- clear_cdb(sl);
- sl->cdb_cmd_blk[1] = STLINK_DEBUG_RUNCORE;
+void _stlink_sg_run(stlink_t *sl) {
+ struct stlink_libsg *sg = sl->backend_data;
+ DLOG("\n*** stlink_run ***\n");
+ clear_cdb(sg);
+ sg->cdb_cmd_blk[1] = STLINK_DEBUG_RUNCORE;
sl->q_len = 2;
- sl->q_addr = 0;
+ sg->q_addr = 0;
stlink_q(sl);
stlink_stat(sl, "run core");
}
-// same as above with entrypoint.
-static unsigned int is_core_halted(struct stlink_libsg*);
-
-void stlink_run_at(struct stlink *sl_libsg, stm32_addr_t addr) {
- stlink_write_reg(sl, addr, 15); /* pc register */
-
- stlink_run(sl);
-
- while (is_core_halted(sl) == 0)
- usleep(3000000);
-}
-
// Step the arm-core.
-void stlink_step(struct stlink_libsg *sl) {
- D(sl, "\n*** stlink_step ***\n");
- clear_cdb(sl);
- sl->cdb_cmd_blk[1] = STLINK_DEBUG_STEPCORE;
+void _stlink_sg_step(stlink_t *sl) {
+ struct stlink_libsg *sg = sl->backend_data;
+ clear_cdb(sg);
+ sg->cdb_cmd_blk[1] = STLINK_DEBUG_STEPCORE;
sl->q_len = 2;
- sl->q_addr = 0;
+ sg->q_addr = 0;
stlink_q(sl);
stlink_stat(sl, "step core");
}
// TODO test
// see Cortex-M3 Technical Reference Manual
-
-void stlink_set_hw_bp(struct stlink_libsg *sl, int fp_nr, uint32_t addr, int fp) {
- D(sl, "\n*** stlink_set_hw_bp ***\n");
- clear_cdb(sl);
- sl->cdb_cmd_blk[1] = STLINK_DEBUG_SETFP;
+// TODO make delegate!
+void stlink_set_hw_bp(stlink_t *sl, int fp_nr, uint32_t addr, int fp) {
+ DLOG("\n*** stlink_set_hw_bp ***\n");
+ struct stlink_libsg *sg = sl->backend_data;
+ clear_cdb(sg);
+ sg->cdb_cmd_blk[1] = STLINK_DEBUG_SETFP;
// 2:The number of the flash patch used to set the breakpoint
// 3-6: Address of the breakpoint (LSB)
// 7: FP_ALL (0x02) / FP_UPPER (0x01) / FP_LOWER (0x00)
// TODO test
-void stlink_clr_hw_bp(struct stlink_libsg *sl, int fp_nr) {
- D(sl, "\n*** stlink_clr_hw_bp ***\n");
- clear_cdb(sl);
- sl->cdb_cmd_blk[1] = STLINK_DEBUG_CLEARFP;
- sl->cdb_cmd_blk[2] = fp_nr;
+// TODO make delegate!
+void stlink_clr_hw_bp(stlink_t *sl, int fp_nr) {
+ struct stlink_libsg *sg = sl->backend_data;
+ DLOG("\n*** stlink_clr_hw_bp ***\n");
+ clear_cdb(sg);
+ sg->cdb_cmd_blk[1] = STLINK_DEBUG_CLEARFP;
+ sg->cdb_cmd_blk[2] = fp_nr;
sl->q_len = 2;
stlink_q(sl);
// Read a "len" bytes to the sl->q_buf from the memory, max 6kB (6144 bytes)
-void stlink_read_mem32(struct stlink_libsg *sl, uint32_t addr, uint16_t len) {
- D(sl, "\n*** stlink_read_mem32 ***\n");
- if (len % 4 != 0) { // !!! never ever: fw gives just wrong values
- fprintf(
- stderr,
- "Error: Data length doesn't have a 32 bit alignment: +%d byte.\n",
- len % 4);
- return;
- }
- clear_cdb(sl);
- sl->cdb_cmd_blk[1] = STLINK_DEBUG_READMEM_32BIT;
+void _stlink_sg_read_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
+ struct stlink_libsg *sg = sl->backend_data;
+ clear_cdb(sg);
+ sg->cdb_cmd_blk[1] = STLINK_DEBUG_READMEM_32BIT;
// 2-5: addr
// 6-7: len
- write_uint32(sl->cdb_cmd_blk + 2, addr);
- write_uint16(sl->cdb_cmd_blk + 6, len);
+ write_uint32(sg->cdb_cmd_blk + 2, addr);
+ write_uint16(sg->cdb_cmd_blk + 6, len);
// data_in 0-0x40-len
// !!! len _and_ q_len must be max 6k,
// !!! if len < q_len: 64*k, 1024*n, n=1..5 -> aboard
// (broken residue issue)
sl->q_len = len;
- sl->q_addr = addr;
+ sg->q_addr = addr;
stlink_q(sl);
stlink_print_data(sl);
}
// Write a "len" bytes from the sl->q_buf to the memory, max 64 Bytes.
-void _stlink_sg_write_mem8(struct stlink_libsg *sl, uint32_t addr, uint16_t len) {
- D(sl, "\n*** stlink_write_mem8 ***\n");
- clear_cdb(sl);
- sl->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEMEM_8BIT;
+void _stlink_sg_write_mem8(stlink_t *sl, uint32_t addr, uint16_t len) {
+ struct stlink_libsg *sg = sl->backend_data;
+ clear_cdb(sg);
+ sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEMEM_8BIT;
// 2-5: addr
// 6-7: len (>0x40 (64) -> aboard)
- write_uint32(sl->cdb_cmd_blk + 2, addr);
- write_uint16(sl->cdb_cmd_blk + 6, len);
+ write_uint32(sg->cdb_cmd_blk + 2, addr);
+ write_uint16(sg->cdb_cmd_blk + 6, len);
// data_out 0-len
sl->q_len = len;
- sl->q_addr = addr;
- sl->q_data_dir = Q_DATA_OUT;
+ sg->q_addr = addr;
+ sg->q_data_dir = Q_DATA_OUT;
stlink_q(sl);
stlink_print_data(sl);
}
// Write a "len" bytes from the sl->q_buf to the memory, max Q_BUF_LEN bytes.
-void _stlink_sg_write_mem32(struct stlink_libsg *sl, uint32_t addr, uint16_t len) {
- clear_cdb(sl);
- sl->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEMEM_32BIT;
+void _stlink_sg_write_mem32(stlink_t *sl, uint32_t addr, uint16_t len) {
+ struct stlink_libsg *sg = sl->backend_data;
+ clear_cdb(sg);
+ sg->cdb_cmd_blk[1] = STLINK_DEBUG_WRITEMEM_32BIT;
// 2-5: addr
// 6-7: len "unlimited"
- write_uint32(sl->cdb_cmd_blk + 2, addr);
- write_uint16(sl->cdb_cmd_blk + 6, len);
+ write_uint32(sg->cdb_cmd_blk + 2, addr);
+ write_uint16(sg->cdb_cmd_blk + 6, len);
// data_out 0-0x40-...-len
sl->q_len = len;
- sl->q_addr = addr;
- sl->q_data_dir = Q_DATA_OUT;
+ sg->q_addr = addr;
+ sg->q_data_dir = Q_DATA_OUT;
stlink_q(sl);
stlink_print_data(sl);
}
-/* FPEC flash controller interface, pm0063 manual
- */
-
-#define FLASH_REGS_ADDR 0x40022000
-#define FLASH_REGS_SIZE 0x28
-
-#define FLASH_ACR (FLASH_REGS_ADDR + 0x00)
-#define FLASH_KEYR (FLASH_REGS_ADDR + 0x04)
-#define FLASH_SR (FLASH_REGS_ADDR + 0x0c)
-#define FLASH_CR (FLASH_REGS_ADDR + 0x10)
-#define FLASH_AR (FLASH_REGS_ADDR + 0x14)
-#define FLASH_OBR (FLASH_REGS_ADDR + 0x1c)
-#define FLASH_WRPR (FLASH_REGS_ADDR + 0x20)
-
-#define FLASH_RDPTR_KEY 0x00a5
-#define FLASH_KEY1 0x45670123
-#define FLASH_KEY2 0xcdef89ab
-
-#define FLASH_SR_BSY 0
-#define FLASH_SR_EOP 5
-
-#define FLASH_CR_PG 0
-#define FLASH_CR_PER 1
-#define FLASH_CR_MER 2
-#define FLASH_CR_STRT 6
-#define FLASH_CR_LOCK 7
-
-static uint32_t __attribute__((unused)) read_flash_rdp(struct stlink_libsg* sl) {
- stlink_read_mem32(sl, FLASH_WRPR, sizeof (uint32_t));
- return (*(uint32_t*) sl->q_buf) & 0xff;
-}
-
-static inline uint32_t read_flash_wrpr(struct stlink_libsg* sl) {
- stlink_read_mem32(sl, FLASH_WRPR, sizeof (uint32_t));
- return *(uint32_t*) sl->q_buf;
-}
-
-static inline uint32_t read_flash_obr(struct stlink_libsg* sl) {
- stlink_read_mem32(sl, FLASH_OBR, sizeof (uint32_t));
- return *(uint32_t*) sl->q_buf;
-}
-
-static inline uint32_t read_flash_cr(struct stlink_libsg* sl) {
- stlink_read_mem32(sl, FLASH_CR, sizeof (uint32_t));
- return *(uint32_t*) sl->q_buf;
-}
-
-static inline unsigned int is_flash_locked(struct stlink_libsg* sl) {
- /* return non zero for true */
- return read_flash_cr(sl) & (1 << FLASH_CR_LOCK);
-}
-
-static void unlock_flash(struct stlink_libsg* sl) {
- /* the unlock sequence consists of 2 write cycles where
- 2 key values are written to the FLASH_KEYR register.
- an invalid sequence results in a definitive lock of
- the FPEC block until next reset.
- */
-
- write_uint32(sl->q_buf, FLASH_KEY1);
- stlink_write_mem32(sl, FLASH_KEYR, sizeof (uint32_t));
-
- write_uint32(sl->q_buf, FLASH_KEY2);
- stlink_write_mem32(sl, FLASH_KEYR, sizeof (uint32_t));
-}
-
-static int unlock_flash_if(struct stlink_libsg* sl) {
- /* unlock flash if already locked */
-
- if (is_flash_locked(sl)) {
- unlock_flash(sl);
- if (is_flash_locked(sl))
- return -1;
- }
-
- return 0;
-}
-
-static void lock_flash(struct stlink_libsg* sl) {
- /* write to 1 only. reset by hw at unlock sequence */
-
- const uint32_t n = read_flash_cr(sl) | (1 << FLASH_CR_LOCK);
-
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static void set_flash_cr_pg(struct stlink_libsg* sl) {
- const uint32_t n = 1 << FLASH_CR_PG;
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static void __attribute__((unused)) clear_flash_cr_pg(struct stlink_libsg* sl) {
- const uint32_t n = read_flash_cr(sl) & ~(1 << FLASH_CR_PG);
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static void set_flash_cr_per(struct stlink_libsg* sl) {
- const uint32_t n = 1 << FLASH_CR_PER;
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static void __attribute__((unused)) clear_flash_cr_per(struct stlink_libsg* sl) {
- const uint32_t n = read_flash_cr(sl) & ~(1 << FLASH_CR_PER);
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static void set_flash_cr_mer(struct stlink_libsg* sl) {
- const uint32_t n = 1 << FLASH_CR_MER;
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static void __attribute__((unused)) clear_flash_cr_mer(struct stlink_libsg* sl) {
- const uint32_t n = read_flash_cr(sl) & ~(1 << FLASH_CR_MER);
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static void set_flash_cr_strt(struct stlink_libsg* sl) {
- /* assume come on the flash_cr_per path */
- const uint32_t n = (1 << FLASH_CR_PER) | (1 << FLASH_CR_STRT);
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_CR, sizeof (uint32_t));
-}
-
-static inline uint32_t read_flash_acr(struct stlink_libsg* sl) {
- stlink_read_mem32(sl, FLASH_ACR, sizeof (uint32_t));
- return *(uint32_t*) sl->q_buf;
-}
-
-static inline uint32_t read_flash_sr(struct stlink_libsg* sl) {
- stlink_read_mem32(sl, FLASH_SR, sizeof (uint32_t));
- return *(uint32_t*) sl->q_buf;
-}
-
-static inline unsigned int is_flash_busy(struct stlink_libsg* sl) {
- return read_flash_sr(sl) & (1 << FLASH_SR_BSY);
-}
-
-static void wait_flash_busy(struct stlink_libsg* sl) {
- /* todo: add some delays here */
- while (is_flash_busy(sl))
- ;
-}
-
-static inline unsigned int is_flash_eop(struct stlink_libsg* sl) {
- return read_flash_sr(sl) & (1 << FLASH_SR_EOP);
-}
-
-static void __attribute__((unused)) clear_flash_sr_eop(struct stlink_libsg* sl) {
- const uint32_t n = read_flash_sr(sl) & ~(1 << FLASH_SR_EOP);
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_SR, sizeof (uint32_t));
-}
-
-static void __attribute__((unused)) wait_flash_eop(struct stlink_libsg* sl) {
- /* todo: add some delays here */
- while (is_flash_eop(sl) == 0)
- ;
-}
-
-static inline void write_flash_ar(struct stlink_libsg* sl, uint32_t n) {
- write_uint32(sl->q_buf, n);
- stlink_write_mem32(sl, FLASH_AR, sizeof (uint32_t));
-}
-
-#if 0 /* todo */
-
-static void disable_flash_read_protection(struct stlink* sl) {
- /* erase the option byte area */
- /* rdp = 0x00a5; */
- /* reset */
-}
-#endif /* todo */
-
#if 0 /* not working */
static int write_flash_mem16
}
#endif /* not working */
-int stlink_erase_flash_page(struct stlink_libsg* sl, stm32_addr_t page) {
- /* page an addr in the page to erase */
-
- /* wait for ongoing op to finish */
- wait_flash_busy(sl);
-
- /* unlock if locked */
- unlock_flash_if(sl);
-
- /* set the page erase bit */
- set_flash_cr_per(sl);
-
- /* select the page to erase */
- write_flash_ar(sl, page);
-
- /* start erase operation, reset by hw with bsy bit */
- set_flash_cr_strt(sl);
-
- /* wait for completion */
- wait_flash_busy(sl);
-
- /* relock the flash */
- lock_flash(sl);
-
- /* todo: verify the erased page */
-
- return 0;
-}
-
-int stlink_erase_flash_mass(struct stlink_libsg* sl) {
- /* wait for ongoing op to finish */
- wait_flash_busy(sl);
-
- /* unlock if locked */
- unlock_flash_if(sl);
-
- /* set the mass erase bit */
- set_flash_cr_mer(sl);
-
- /* start erase operation, reset by hw with bsy bit */
- set_flash_cr_strt(sl);
-
- /* wait for completion */
- wait_flash_busy(sl);
-
- /* relock the flash */
- lock_flash(sl);
-
- /* todo: verify the erased memory */
-
- return 0;
-}
-
-static unsigned int is_core_halted(struct stlink_libsg* sl) {
- /* return non zero if core is halted */
- stlink_status(sl);
- return sl->q_buf[0] == STLINK_CORE_HALTED;
-}
-
-static int write_loader_to_sram
-(struct stlink* sl, stm32_addr_t* addr, size_t* size) {
- /* from openocd, contrib/loaders/flash/stm32.s */
- static const uint8_t loader_code[] ={
- 0x08, 0x4c, /* ldr r4, STM32_FLASH_BASE */
- 0x1c, 0x44, /* add r4, r3 */
- /* write_half_word: */
- 0x01, 0x23, /* movs r3, #0x01 */
- 0x23, 0x61, /* str r3, [r4, #STM32_FLASH_CR_OFFSET] */
- 0x30, 0xf8, 0x02, 0x3b, /* ldrh r3, [r0], #0x02 */
- 0x21, 0xf8, 0x02, 0x3b, /* strh r3, [r1], #0x02 */
- /* busy: */
- 0xe3, 0x68, /* ldr r3, [r4, #STM32_FLASH_SR_OFFSET] */
- 0x13, 0xf0, 0x01, 0x0f, /* tst r3, #0x01 */
- 0xfb, 0xd0, /* beq busy */
- 0x13, 0xf0, 0x14, 0x0f, /* tst r3, #0x14 */
- 0x01, 0xd1, /* bne exit */
- 0x01, 0x3a, /* subs r2, r2, #0x01 */
- 0xf0, 0xd1, /* bne write_half_word */
- /* exit: */
- 0x00, 0xbe, /* bkpt #0x00 */
- 0x00, 0x20, 0x02, 0x40, /* STM32_FLASH_BASE: .word 0x40022000 */
- };
-
- memcpy(sl->q_buf, loader_code, sizeof (loader_code));
- stlink_write_mem32(sl, sl->sram_base, sizeof (loader_code));
-
- *addr = sl->sram_base;
- *size = sizeof (loader_code);
-
- /* success */
- return 0;
-}
-
-
-int init_flash_loader(stlink_t *stl, flash_loader_t* fl) {
- struct stlink_libsg* sl = stl->backend_data;
- size_t size;
-
- /* allocate the loader in sram */
- if (write_loader_to_sram(sl, &fl->loader_addr, &size) == -1) {
- fprintf(stderr, "write_loader_to_sram() == -1\n");
- return -1;
- }
-
- /* allocate a one page buffer in sram right after loader */
- fl->buf_addr = fl->loader_addr + size;
-
- return 0;
-}
-
-static int run_flash_loader
-(stlink_t *stl, flash_loader_t* fl, stm32_addr_t target, const uint8_t* buf, size_t size) {
- struct stlink_libsg* sl = stl->backend_data;
- const size_t count = size / sizeof (uint16_t);
-
- if (write_buffer_to_sram(sl, fl, buf, size) == -1) {
- fprintf(stderr, "write_buffer_to_sram() == -1\n");
- return -1;
- }
-
- /* setup core */
- stlink_write_reg(sl, fl->buf_addr, 0); /* source */
- stlink_write_reg(sl, target, 1); /* target */
- stlink_write_reg(sl, count, 2); /* count (16 bits half words) */
- stlink_write_reg(sl, 0, 3); /* flash bank 0 (input) */
- stlink_write_reg(sl, fl->loader_addr, 15); /* pc register */
-
- /* unlock and set programming mode */
- unlock_flash_if(sl);
- set_flash_cr_pg(sl);
-
- /* run loader */
- stlink_run(sl);
-
- while (is_core_halted(sl) == 0)
- ;
-
- lock_flash(sl);
-
- /* not all bytes have been written */
- stlink_read_reg(sl, 2);
- if (sl->reg.r[2] != 0) {
- fprintf(stderr, "write error, count == %u\n", sl->reg.r[2]);
- return -1;
- }
-
- return 0;
-}
-
-static int stlink_fcheck_flash
-(struct stlink_libsg* sl, const char* path, stm32_addr_t addr) {
- /* check the contents of path are at addr */
-
- int res;
- mapped_file_t mf = MAPPED_FILE_INITIALIZER;
-
- if (map_file(&mf, path) == -1)
- return -1;
-
- res = check_file(sl, &mf, addr);
-
- unmap_file(&mf);
-
- return res;
-}
-
-// The stlink_fwrite_flash should not muck with mmapped files inside itself,
-// and should use this function instead. (Hell, what's the reason behind mmap
-// there?!) But, as it is not actually used anywhere, nobody cares.
-
-#define WRITE_BLOCK_SIZE 0x40
-
-int stlink_write_flash(struct stlink_libsg* sl, stm32_addr_t addr, uint8_t* base, unsigned len) {
- int error = -1;
- size_t off;
- flash_loader_t fl;
-
- /* check addr range is inside the flash */
- if (addr < sl->flash_base) {
- fprintf(stderr, "addr too low\n");
- return -1;
- } else if ((addr + len) < addr) {
- fprintf(stderr, "addr overruns\n");
- return -1;
- } else if ((addr + len) > (sl->flash_base + sl->flash_size)) {
- fprintf(stderr, "addr too high\n");
- return -1;
- } else if ((addr & 1) || (len & 1)) {
- fprintf(stderr, "unaligned addr or size\n");
- return -1;
- }
-
- /* flash loader initialization */
- if (init_flash_loader(sl, &fl) == -1) {
- fprintf(stderr, "init_flash_loader() == -1\n");
- return -1;
- }
-
- /* write each page. above WRITE_BLOCK_SIZE fails? */
- for (off = 0; off < len; off += WRITE_BLOCK_SIZE) {
- /* adjust last write size */
- size_t size = WRITE_BLOCK_SIZE;
- if ((off + WRITE_BLOCK_SIZE) > len)
- size = len - off;
-
- if (run_flash_loader(sl, &fl, addr + off, base + off, size) == -1) {
- fprintf(stderr, "run_flash_loader(0x%zx) == -1\n", addr + off);
- return -1;
- }
- }
-
- for (off = 0; off < len; off += sl->flash_pgsz) {
- size_t aligned_size;
-
- /* adjust last page size */
- size_t cmp_size = sl->flash_pgsz;
- if ((off + sl->flash_pgsz) > len)
- cmp_size = len - off;
-
- aligned_size = cmp_size;
- if (aligned_size & (4 - 1))
- aligned_size = (cmp_size + 4) & ~(4 - 1);
+// Exit the jtag or swd mode and enter the mass mode.
- stlink_read_mem32(sl, addr + off, aligned_size);
+void _stlink_sg_exit_debug_mode(stlink_t *stl) {
- if (memcmp(sl->q_buf, base + off, cmp_size))
- return -1;
+ if (stl) {
+ struct stlink_libsg* sl = stl->backend_data;
+ clear_cdb(sl);
+ sl->cdb_cmd_blk[1] = STLINK_DEBUG_EXIT;
+ stl->q_len = 0; // >0 -> aboard
+ stlink_q(stl);
}
-
- return 0;
}
-int stlink_fwrite_flash
-(stlink_t *sl, const char* path, stm32_addr_t addr) {
- /* write the file in flash at addr */
-
- int error = -1;
- size_t off;
- mapped_file_t mf = MAPPED_FILE_INITIALIZER;
- flash_loader_t fl;
-
- if (map_file(&mf, path) == -1) {
- fprintf(stderr, "map_file() == -1\n");
- return -1;
- }
-
- /* check addr range is inside the flash */
- if (addr < sl->flash_base) {
- fprintf(stderr, "addr too low\n");
- goto on_error;
- } else if ((addr + mf.len) < addr) {
- fprintf(stderr, "addr overruns\n");
- goto on_error;
- } else if ((addr + mf.len) > (sl->flash_base + sl->flash_size)) {
- fprintf(stderr, "addr too high\n");
- goto on_error;
- } else if ((addr & 1) || (mf.len & 1)) {
- /* todo */
- fprintf(stderr, "unaligned addr or size\n");
- goto on_error;
- }
-
- /* erase each page. todo: mass erase faster? */
- for (off = 0; off < mf.len; off += sl->flash_pgsz) {
- /* addr must be an addr inside the page */
- if (stlink_erase_flash_page(sl, addr + off) == -1) {
- fprintf(stderr, "erase_flash_page(0x%zx) == -1\n", addr + off);
- goto on_error;
- }
- }
-
- /* flash loader initialization */
- if (init_flash_loader(sl, &fl) == -1) {
- fprintf(stderr, "init_flash_loader() == -1\n");
- goto on_error;
- }
-
- /* write each page. above WRITE_BLOCK_SIZE fails? */
-#define WRITE_BLOCK_SIZE 0x40
- for (off = 0; off < mf.len; off += WRITE_BLOCK_SIZE) {
- /* adjust last write size */
- size_t size = WRITE_BLOCK_SIZE;
- if ((off + WRITE_BLOCK_SIZE) > mf.len)
- size = mf.len - off;
-
- if (run_flash_loader(sl, &fl, addr + off, mf.base + off, size) == -1) {
- fprintf(stderr, "run_flash_loader(0x%zx) == -1\n", addr + off);
- goto on_error;
- }
- }
-
- /* check the file ha been written */
- if (check_file(sl, &mf, addr) == -1) {
- fprintf(stderr, "check_file() == -1\n");
- goto on_error;
- }
-
- /* success */
- error = 0;
-
-on_error:
- unmap_file(&mf);
- return error;
-}
// 1) open a sg device, switch the stlink from dfu to mass mode
// 2) wait 5s until the kernel driver stops reseting the broken device
_stlink_sg_run,
_stlink_sg_status,
_stlink_sg_version,
+ _stlink_sg_read_mem32,
_stlink_sg_write_mem32,
- _stlink_sg_write_mem8
+ _stlink_sg_write_mem8,
+ _stlink_sg_read_all_regs,
+ _stlink_sg_read_reg,
+ _stlink_sg_write_reg,
+ _stlink_sg_step,
+ _stlink_sg_current_mode,
+ _stlink_sg_force_debug
};
-stlink_t* stlink_open(const char *dev_name, const int verbose) {
- fprintf(stderr, "\n*** stlink_open [%s] ***\n", dev_name);
- int sg_fd = scsi_pt_open_device(dev_name, RDWR, verbose);
- if (sg_fd < 0) {
- fprintf(stderr, "error opening device: %s: %s\n", dev_name,
- safe_strerror(-sg_fd));
+#if using_stm8_stuff_XXXX
+stlink *stlink_open(libusb_context *usb_context)
+{
+ stlink *stl = malloc(sizeof(stlink));
+ stl->handle = libusb_open_device_with_vid_pid(usb_context, USB_VID_ST, USB_PID_STLINK);
+ if (stl->handle == NULL) {
+ free(stl);
+ return NULL;
+ }
+
+ libusb_device *dev = libusb_get_device(stl->handle);
+ struct libusb_config_descriptor *conf_desc;
+ int ret = libusb_get_config_descriptor(dev, 0, &conf_desc);
+ if (ret != LIBUSB_SUCCESS) {
+ libusb_close(stl->handle);
+ free(stl);
return NULL;
}
+ for (int i = 0; i < conf_desc->bNumInterfaces; i++) {
+ printf("interface %d\n", i);
+ for (int j = 0; j < conf_desc->interface[i].num_altsetting; j++) {
+ for (int k = 0; k < conf_desc->interface[i].altsetting[j].bNumEndpoints; k++) {
+ const struct libusb_endpoint_descriptor *endpoint;
+ endpoint = &conf_desc->interface[i].altsetting[j].endpoint[k];
+ if (endpoint->bEndpointAddress & LIBUSB_ENDPOINT_IN) {
+ stl->endpoint_in = endpoint->bEndpointAddress;
+ printf("Found IN endpoint\n");
+ } else {
+ stl->endpoint_out = endpoint->bEndpointAddress;
+ printf("Found OUT endpoint\n");
+ }
+ }
+ }
+ }
+ libusb_free_config_descriptor(conf_desc);
+ ret = libusb_kernel_driver_active(stl->handle, 0);
+ if (ret == 1) {
+ printf("kernel driver active\n");
+ } else if (ret == 0) {
+ //printf("kernel driver not active\n");
+ } else {
+ fprintf(stderr, "libusb_kernel_driver_active = %d\n", ret);
+ }
+ ret = libusb_claim_interface(stl->handle, 0);
+ if (ret != LIBUSB_SUCCESS) {
+ fprintf(stderr, "claiming interface failed: %d\n", ret);
+ libusb_close(stl->handle);
+ free(stl);
+ return NULL;
+ }
+
+ return stl;
+}
+#endif
+
+
+static stlink_t* stlink_open(const char *dev_name, const int verbose) {
+ fprintf(stderr, "\n*** stlink_open [%s] ***\n", dev_name);
+
stlink_t *sl = malloc(sizeof (stlink_t));
struct stlink_libsg *slsg = malloc(sizeof (struct stlink_libsg));
if (sl == NULL || slsg == NULL) {
- fprintf(stderr, "Couldn't malloc stlink and stlink_sg structures out of memory!\n");
+ WLOG("Couldn't malloc stlink and stlink_sg structures out of memory!\n");
return NULL;
}
+
+ if (libusb_init(&(slsg->libusb_ctx))) {
+ WLOG("failed to init libusb context, wrong version of libraries?\n");
+ free(sl);
+ free(slsg);
+ return NULL;
+ }
+
+ slsg->handle = libusb_open_device_with_vid_pid(slsg->libusb_ctx, USB_ST_VID, USB_STLINK_PID);
+ if (slsg->handle == NULL) {
+ WLOG("Failed to find an stlink v1 by VID:PID\n");
+ free(sl);
+ free(slsg);
+ return NULL;
+ }
+
+ DLOG("Successfully opened stlinkv1 by libusb :)\n");
+
sl->verbose = verbose;
sl->backend_data = slsg;
sl->backend = &_stlink_sg_backend;
- slsg->sg_fd = sg_fd;
sl->core_stat = STLINK_CORE_STAT_UNKNOWN;
- slsg->core_id = 0;
slsg->q_addr = 0;
clear_buf(sl);
-stlink_t* stlink_quirk_open(const char *dev_name, const int verbose) {
-
+stlink_t* stlink_v1_open(const char *dev_name, const int verbose) {
+ ugly_init(verbose);
stlink_t *sl = stlink_open(dev_name, verbose);
if (sl == NULL) {
fputs("Error: could not open stlink device\n", stderr);
stlink_version(sl);
struct stlink_libsg *sg = sl->backend_data;
- if (sg->st_vid != USB_ST_VID || sg->stlink_pid != USB_STLINK_PID) {
+ if ((sl->version.st_vid != USB_ST_VID) || (sl->version.stlink_pid != USB_STLINK_PID)) {
fprintf(stderr, "Error: the device %s is not a stlink\n",
dev_name);
fprintf(stderr, " VID: got %04x expect %04x \n",
- sg->st_vid, USB_ST_VID);
+ sl->version.st_vid, USB_ST_VID);
fprintf(stderr, " PID: got %04x expect %04x \n",
- sg->stlink_pid, USB_STLINK_PID);
+ sl->version.stlink_pid, USB_STLINK_PID);
return NULL;
}
- D(sl, "\n*** stlink_force_open ***\n");
+ DLOG("\n*** stlink_force_open ***\n");
switch (stlink_current_mode(sl)) {
case STLINK_DEV_MASS_MODE:
return sl;
// TODO go to mass?
return sl;
}
- DD(sl, "\n*** switch the stlink to mass mode ***\n");
+ DLOG("\n*** switch the stlink to mass mode ***\n");
_stlink_sg_exit_dfu_mode(sl);
// exit the dfu mode -> the device is gone
- DD(sl, "\n*** reopen the stlink device ***\n");
+ DLOG("\n*** reopen the stlink device ***\n");
delay(1000);
stlink_close(sl);
delay(5000);
sl->q_buf[1024 * 6 - 1] = 0x42; //6kB
sl->q_buf[1024 * 8 - 1] = 0x42; //8kB
}
-#endif