Skip to content

Commit

Permalink
Merge branch 'add_stlink_v3_support' of git://github.com/martonmiklos…
Browse files Browse the repository at this point in the history
…/stlink into develop
  • Loading branch information
Nightwalker-87 committed May 7, 2020
2 parents 9b207de + 0a91936 commit 442ade8
Show file tree
Hide file tree
Showing 8 changed files with 286 additions and 121 deletions.
59 changes: 55 additions & 4 deletions include/stlink.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,17 @@ extern "C" {
//#define Q_BUF_LEN 96
#define Q_BUF_LEN (1024 * 100)

// STLINK_DEBUG_RESETSYS, etc:
// STLINK_DEBUG_RESETSYS, etc:
enum target_state {
TARGET_UNKNOWN = 0,
TARGET_RUNNING = 1,
TARGET_HALTED = 2,
TARGET_RESET = 3,
TARGET_DEBUG_RUNNING = 4,
};

#define STLINK_CORE_RUNNING 0x80
#define STLINK_CORE_HALTED 0x81
#define STLINK_CORE_STAT_UNKNOWN -1

#define STLINK_GET_VERSION 0xf1
#define STLINK_GET_CURRENT_MODE 0xf5
Expand Down Expand Up @@ -75,8 +82,42 @@ extern "C" {

#define STLINK_V3_MAX_FREQ_NB 10

/* Cortex Debug Control Block */
#define DCB_DHCSR 0xE000EDF0
#define DCB_DCRSR 0xE000EDF4
#define DCB_DCRDR 0xE000EDF8
#define DCB_DEMCR 0xE000EDFC

/* DCB_DHCSR bit and field definitions */
#define DBGKEY (0xA05F << 16)
#define C_DEBUGEN (1 << 0)
#define C_HALT (1 << 1)
#define C_STEP (1 << 2)
#define C_MASKINTS (1 << 3)
#define S_REGRDY (1 << 16)
#define S_HALT (1 << 17)
#define S_SLEEP (1 << 18)
#define S_LOCKUP (1 << 19)
#define S_RETIRE_ST (1 << 24)
#define S_RESET_ST (1 << 25)


/*
* Map the relevant features, quirks and workaround for specific firmware
* version of stlink
*/
#define STLINK_F_HAS_TRACE (1<<0)
#define STLINK_F_HAS_SWD_SET_FREQ (1<<1)
#define STLINK_F_HAS_JTAG_SET_FREQ (1<<2)
#define STLINK_F_HAS_MEM_16BIT (1<<3)
#define STLINK_F_HAS_GETLASTRWSTATUS2 (1<<4)
#define STLINK_F_HAS_DAP_REG (1<<5)
#define STLINK_F_QUIRK_JTAG_DP_READ (1<<6)
#define STLINK_F_HAS_AP_INIT (1<<7)
#define STLINK_F_HAS_DPBANKSEL (1<<8)
#define STLINK_F_HAS_RW8_512BYTES (1<<9)


/* Enough space to hold both a V2 command or a V1 command packaged as generic scsi*/
#define C_BUF_LEN 32

enum stlink_flash_type {
Expand Down Expand Up @@ -120,12 +161,22 @@ typedef struct flash_loader {
uint8_t revision;
} cortex_m3_cpuid_t;

enum stlink_jtag_api_version {
STLINK_JTAG_API_V1 = 1,
STLINK_JTAG_API_V2,
STLINK_JTAG_API_V3,
};

typedef struct stlink_version_ {
uint32_t stlink_v;
uint32_t jtag_v;
uint32_t swim_v;
uint32_t st_vid;
uint32_t stlink_pid;
/** jtag api version supported */
enum stlink_jtag_api_version jtag_api;
/** one bit for each feature supported. See macros STLINK_F_* */
uint32_t flags;
} stlink_version_t;

enum transport_type {
Expand Down Expand Up @@ -154,7 +205,7 @@ typedef struct flash_loader {
int opt;
uint32_t core_id; // set by stlink_core_id(), result from STLINK_DEBUGREADCOREID
uint32_t chip_id; // set by stlink_load_device_params(), used to identify flash and sram
int core_stat; // set by stlink_status(), values STLINK_CORE_xxxxx
enum target_state core_stat; // set by stlink_status()

char serial[STLINK_SERIAL_MAX_SIZE];
int serial_size;
Expand Down
49 changes: 29 additions & 20 deletions include/stlink/commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,35 @@
#define STLINK_COMMANDS_H_

enum stlink_debug_commands {
STLINK_DEBUG_ENTER_JTAG = 0x00,
STLINK_DEBUG_GETSTATUS = 0x01,
STLINK_DEBUG_FORCEDEBUG = 0x02,
STLINK_DEBUG_RESETSYS = 0x03,
STLINK_DEBUG_READALLREGS = 0x04,
STLINK_DEBUG_READREG = 0x05,
STLINK_DEBUG_WRITEREG = 0x06,
STLINK_DEBUG_READMEM_32BIT = 0x07,
STLINK_DEBUG_WRITEMEM_32BIT = 0x08,
STLINK_DEBUG_RUNCORE = 0x09,
STLINK_DEBUG_STEPCORE = 0x0a,
STLINK_DEBUG_SETFP = 0x0b,
STLINK_DEBUG_WRITEMEM_8BIT = 0x0d,
STLINK_DEBUG_CLEARFP = 0x0e,
STLINK_DEBUG_WRITEDEBUGREG = 0x0f,
STLINK_DEBUG_ENTER = 0x20,
STLINK_DEBUG_EXIT = 0x21,
STLINK_DEBUG_READCOREID = 0x22,
STLINK_DEBUG_APIV2_ENTER = 0x30,
STLINK_DEBUG_ENTER_SWD = 0xa3
STLINK_DEBUG_ENTER_JTAG = 0x00,
STLINK_DEBUG_GETSTATUS = 0x01,
STLINK_DEBUG_FORCEDEBUG = 0x02,
STLINK_DEBUG_APIV1_RESETSYS = 0x03,
STLINK_DEBUG_APIV1_READALLREGS = 0x04,
STLINK_DEBUG_APIV1_READREG = 0x05,
STLINK_DEBUG_APIV1_WRITEREG = 0x06,
STLINK_DEBUG_READMEM_32BIT = 0x07,
STLINK_DEBUG_WRITEMEM_32BIT = 0x08,
STLINK_DEBUG_RUNCORE = 0x09,
STLINK_DEBUG_STEPCORE = 0x0a,
STLINK_DEBUG_APIV1_SETFP = 0x0b,
STLINK_DEBUG_WRITEMEM_8BIT = 0x0d,
STLINK_DEBUG_APIV1_CLEARFP = 0x0e,
STLINK_DEBUG_APIV1_WRITEDEBUGREG = 0x0f,
STLINK_DEBUG_APIV1_ENTER = 0x20,
STLINK_DEBUG_EXIT = 0x21,
STLINK_DEBUG_READCOREID = 0x22,
STLINK_DEBUG_APIV2_ENTER = 0x30,
STLINK_DEBUG_APIV2_READ_IDCODES = 0x31,
STLINK_DEBUG_APIV2_RESETSYS = 0x32,
STLINK_DEBUG_APIV2_READREG = 0x33,
STLINK_DEBUG_APIV2_WRITEREG = 0x34,
STLINK_DEBUG_APIV2_WRITEDEBUGREG = 0x35,
STLINK_DEBUG_APIV2_READDEBUGREG = 0x36,
STLINK_DEBUG_APIV2_READALLREGS = 0x3A,
STLINK_DEBUG_APIV2_GETLASTRWSTATUS = 0x3B,
STLINK_DEBUG_APIV2_GETLASTRWSTATUS2 = 0x3E,
STLINK_DEBUG_ENTER_SWD = 0xa3
};

#endif /* STLINK_COMMANDS_H_ */
52 changes: 29 additions & 23 deletions src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -1225,6 +1225,7 @@ int stlink_status(stlink_t *sl) {
* @param slv output parsed version object
*/
void _parse_version(stlink_t *sl, stlink_version_t *slv) {
sl->version.flags = 0;
if (sl->version.stlink_v < 3) {
uint32_t b0 = sl->q_buf[0]; //lsb
uint32_t b1 = sl->q_buf[1];
Expand All @@ -1242,6 +1243,15 @@ void _parse_version(stlink_t *sl, stlink_version_t *slv) {
slv->swim_v = b1 & 0x3f;
slv->st_vid = (b3 << 8) | b2;
slv->stlink_pid = (b5 << 8) | b4;
/* ST-LINK/V1 from J11 switch to api-v2 (and support SWD) */
if (slv->stlink_v == 1)
slv->jtag_api = slv->jtag_v > 11? STLINK_JTAG_API_V2 : STLINK_JTAG_API_V1;
else {
slv->jtag_api = STLINK_JTAG_API_V2;
/* preferred API to get last R/W status from J15 */
if (sl->version.jtag_v >= 15)
sl->version.flags |= STLINK_F_HAS_GETLASTRWSTATUS2;
}
} else {
// V3 uses different version format, for reference see OpenOCD source
// (that was written from docs available from ST under NDA):
Expand All @@ -1251,6 +1261,9 @@ void _parse_version(stlink_t *sl, stlink_version_t *slv) {
slv->jtag_v = sl->q_buf[2];
slv->st_vid = (uint32_t)((sl->q_buf[9] << 8) | sl->q_buf[8]);
slv->stlink_pid = (uint32_t)((sl->q_buf[11] << 8) | sl->q_buf[10]);
slv->jtag_api = STLINK_JTAG_API_V3;
/* preferred API to get last R/W status */
sl->version.flags |= STLINK_F_HAS_GETLASTRWSTATUS2;
}
return;
}
Expand Down Expand Up @@ -1408,13 +1421,8 @@ int stlink_write_unsupported_reg(stlink_t *sl, uint32_t val, int r_idx, struct s

bool stlink_is_core_halted(stlink_t *sl)
{
bool ret = false;

stlink_status(sl);
if (sl->q_buf[0] == STLINK_CORE_HALTED)
ret = true;

return ret;
return sl->core_stat == TARGET_HALTED;
}

int stlink_step(stlink_t *sl) {
Expand Down Expand Up @@ -1481,29 +1489,29 @@ void stlink_run_at(stlink_t *sl, stm32_addr_t addr) {
// this function is called by stlink_status()
// do not call stlink_core_stat() directly, always use stlink_status()
void stlink_core_stat(stlink_t *sl) {
if (sl->q_len <= 0)
return;

switch (sl->q_buf[0]) {
case STLINK_CORE_RUNNING:
sl->core_stat = STLINK_CORE_RUNNING;
switch (sl->core_stat ) {
case TARGET_RUNNING:
DLOG(" core status: running\n");
return;
case STLINK_CORE_HALTED:
sl->core_stat = STLINK_CORE_HALTED;
case TARGET_HALTED:
DLOG(" core status: halted\n");
return;
case TARGET_RESET:
DLOG(" core status: reset\n");
return;
case TARGET_DEBUG_RUNNING:
DLOG(" core status: debug running\n");
return;
default:
sl->core_stat = STLINK_CORE_STAT_UNKNOWN;
fprintf(stderr, " core status: unknown\n");
DLOG(" core status: unknown\n");
}
}

void stlink_print_data(stlink_t * sl) {
if (sl->q_len <= 0 || sl->verbose < UDEBUG)
return;
if (sl->verbose > 2)
fprintf(stdout, "data_len = %d 0x%x\n", sl->q_len, sl->q_len);
DLOG("data_len = %d 0x%x\n", sl->q_len, sl->q_len);

for (int i = 0; i < sl->q_len; i++) {
if (i % 16 == 0) {
Expand All @@ -1514,9 +1522,9 @@ void stlink_print_data(stlink_t * sl) {
fprintf(stdout, "\n-> 0x%08x ", sl->q_addr + i);
*/
}
fprintf(stdout, " %02x", (unsigned int) sl->q_buf[i]);
DLOG(" %02x", (unsigned int) sl->q_buf[i]);
}
fputs("\n\n", stdout);
DLOG("\n\n");
}

/* memory mapped file */
Expand Down Expand Up @@ -2464,17 +2472,15 @@ int stlink_write_flash(stlink_t *sl, stm32_addr_t addr, uint8_t* base, uint32_t
/* erase each page */
int page_count = 0;
for (off = 0; off < len; off += stlink_calculate_pagesize(sl, addr + (uint32_t) off)) {
/* addr must be an addr inside the page */
// addr must be an addr inside the page
if (stlink_erase_flash_page(sl, addr + (uint32_t) off) == -1) {
ELOG("Failed to erase_flash_page(%#zx) == -1\n", addr + off);
return -1;
}
fprintf(stdout,"\rFlash page at addr: 0x%08lx erased",
ILOG("Flash page at addr: 0x%08lx erased\n",
(unsigned long)(addr + off));
fflush(stdout);
page_count++;
}
fprintf(stdout,"\n");
ILOG("Finished erasing %d pages of %d (%#x) bytes\n",
page_count, sl->flash_pgsz, sl->flash_pgsz);

Expand Down
4 changes: 3 additions & 1 deletion src/flash_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,9 @@ int stlink_flash_loader_write_to_sram(stlink_t *sl, stm32_addr_t* addr, size_t*
}

memcpy(sl->q_buf, loader_code, loader_size);
stlink_write_mem32(sl, sl->sram_base, loader_size);
int ret = stlink_write_mem32(sl, sl->sram_base, loader_size);
if (ret)
return ret;

*addr = sl->sram_base;
*size = loader_size;
Expand Down
2 changes: 1 addition & 1 deletion src/logging.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

#include "logging.h"

static int max_level = UINFO;
static int max_level = UDEBUG;

int ugly_init(int maximum_threshold) {
max_level = maximum_threshold;
Expand Down
20 changes: 10 additions & 10 deletions src/sg.c
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ int _stlink_sg_current_mode(stlink_t *stl) {
int _stlink_sg_enter_swd_mode(stlink_t *sl) {
struct stlink_libsg *sg = sl->backend_data;
clear_cdb(sg);
sg->cdb_cmd_blk[1] = STLINK_DEBUG_ENTER;
sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_ENTER;
sg->cdb_cmd_blk[2] = STLINK_DEBUG_ENTER_SWD;
sl->q_len = 0; // >0 -> aboard
return stlink_q(sl);
Expand All @@ -439,7 +439,7 @@ int _stlink_sg_enter_jtag_mode(stlink_t *sl) {
struct stlink_libsg *sg = sl->backend_data;
DLOG("\n*** stlink_enter_jtag_mode ***\n");
clear_cdb(sg);
sg->cdb_cmd_blk[1] = STLINK_DEBUG_ENTER;
sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_ENTER;
sg->cdb_cmd_blk[2] = STLINK_DEBUG_ENTER_JTAG;
sl->q_len = 0;
return stlink_q(sl);
Expand Down Expand Up @@ -519,7 +519,7 @@ int _stlink_sg_core_id(stlink_t *sl) {
int _stlink_sg_reset(stlink_t *sl) {
struct stlink_libsg *sg = sl->backend_data;
clear_cdb(sg);
sg->cdb_cmd_blk[1] = STLINK_DEBUG_RESETSYS;
sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_RESETSYS;
sl->q_len = 2;
sg->q_addr = 0;
if (stlink_q(sl))
Expand Down Expand Up @@ -579,7 +579,7 @@ int _stlink_sg_read_all_regs(stlink_t *sl, struct stlink_reg *regp) {
struct stlink_libsg *sg = sl->backend_data;

clear_cdb(sg);
sg->cdb_cmd_blk[1] = STLINK_DEBUG_READALLREGS;
sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_READALLREGS;
sl->q_len = 84;
sg->q_addr = 0;
if (stlink_q(sl))
Expand Down Expand Up @@ -620,7 +620,7 @@ int _stlink_sg_read_all_regs(stlink_t *sl, struct stlink_reg *regp) {
int _stlink_sg_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) {
struct stlink_libsg *sg = sl->backend_data;
clear_cdb(sg);
sg->cdb_cmd_blk[1] = STLINK_DEBUG_READREG;
sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_READREG;
sg->cdb_cmd_blk[2] = r_idx;
sl->q_len = 4;
sg->q_addr = 0;
Expand Down Expand Up @@ -665,7 +665,7 @@ int _stlink_sg_read_reg(stlink_t *sl, int r_idx, struct stlink_reg *regp) {
int _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;
sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_WRITEREG;
// 2: reg index
// 3-6: reg content
sg->cdb_cmd_blk[2] = idx;
Expand All @@ -686,7 +686,7 @@ 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;
sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_WRITEDEBUGREG;
// 2-5: address of reg of the debug module
// 6-9: reg content
write_uint32(sg->cdb_cmd_blk + 2, addr);
Expand Down Expand Up @@ -733,7 +733,7 @@ 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;
sg->cdb_cmd_blk[1] = STLINK_DEBUG_APIV1_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)
Expand All @@ -752,7 +752,7 @@ 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[1] = STLINK_DEBUG_APIV1_CLEARFP;
sg->cdb_cmd_blk[2] = fp_nr;

sl->q_len = 2;
Expand Down Expand Up @@ -1014,7 +1014,7 @@ static stlink_t* stlink_open(const int verbose) {
sl->backend_data = slsg;
sl->backend = &_stlink_sg_backend;

sl->core_stat = STLINK_CORE_STAT_UNKNOWN;
sl->core_stat = TARGET_UNKNOWN;
slsg->q_addr = 0;

return sl;
Expand Down
2 changes: 1 addition & 1 deletion src/st-util/gdb-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -1419,7 +1419,7 @@ int serve(stlink_t *sl, st_state_t *st) {
if (ret) {
DLOG("Semihost: status failed\n");
}
if (sl->core_stat == STLINK_CORE_HALTED) {
if(sl->core_stat == TARGET_HALTED) {
struct stlink_reg reg;
stm32_addr_t pc;
stm32_addr_t addr;
Expand Down
Loading

0 comments on commit 442ade8

Please sign in to comment.