Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Basic compatibility for STLink-v3 programmer #954

Merged
merged 8 commits into from
May 17, 2020
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