X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fjtag%2Fdrivers%2Fstlink_usb.c;h=b2f380aecb6172189cdad362769c4265e78ad15e;hp=98eeb09029d8de9584097a3ab60935d34c4704d6;hb=f019c4f7d63c8a8d15f5c64c4456f99bbf6efbd3;hpb=cfdfe5119de8f3e2cbaebd9f912e920a03f0168b diff --git a/src/jtag/drivers/stlink_usb.c b/src/jtag/drivers/stlink_usb.c index 98eeb09029..b2f380aecb 100644 --- a/src/jtag/drivers/stlink_usb.c +++ b/src/jtag/drivers/stlink_usb.c @@ -2,6 +2,9 @@ * Copyright (C) 2011-2012 by Mathias Kuester * * Mathias Kuester * * * + * Copyright (C) 2012 by Spencer Oliver * + * spen@spen-soft.co.uk * + * * * This code is based on https://github.com/texane/stlink * * * * This program is free software; you can redistribute it and/or modify * @@ -32,6 +35,8 @@ #include #include +#include + #include "libusb_common.h" #define ENDPOINT_IN 0x80 @@ -46,7 +51,7 @@ #define STLINK_CMD_SIZE_V1 (10) enum stlink_jtag_api_version { - STLINK_JTAG_API_V1 = 0, + STLINK_JTAG_API_V1 = 1, STLINK_JTAG_API_V2, }; @@ -142,9 +147,11 @@ struct stlink_usb_handle_s { #define STLINK_DEBUG_APIV2_RESETSYS 0x32 #define STLINK_DEBUG_APIV2_READREG 0x33 #define STLINK_DEBUG_APIV2_WRITEREG 0x34 +#define STLINK_DEBUG_APIV2_WRITEDEBUGREG 0x35 +#define STLINK_DEBUG_APIV2_READDEBUGREG 0x36 #define STLINK_DEBUG_APIV2_READALLREGS 0x3A - +#define STLINK_DEBUG_APIV2_GETLASTRWSTATUS 0x3B #define STLINK_DEBUG_APIV2_DRIVE_NRST 0x3C #define STLINK_DEBUG_APIV2_DRIVE_NRST_LOW 0x00 @@ -396,15 +403,14 @@ static int stlink_usb_version(void *handle) h->pid = buf_get_u32(h->databuf, 32, 16); /* set the supported jtag api version - * V1 doesn't support API V2 at all - * V2 support API V2 since JTAG V13 + * API V2 is supported since JTAG V11 */ - if ((h->version.stlink == 2) && (h->version.jtag > 12)) + if (h->version.jtag >= 11) h->version.jtag_api_max = STLINK_JTAG_API_V2; else h->version.jtag_api_max = STLINK_JTAG_API_V1; - LOG_DEBUG("STLINK v%d JTAG v%d API v%d SWIM v%d VID %04X PID %04X", + LOG_DEBUG("STLINK v%d JTAG v%d API v%d SWIM v%d VID 0x%04X PID 0x%04X", h->version.stlink, h->version.jtag, (h->version.jtag_api_max == STLINK_JTAG_API_V1) ? 1 : 2, @@ -552,7 +558,7 @@ static int stlink_usb_init_mode(void *handle) if (res != ERROR_OK) return res; - LOG_DEBUG("MODE: %02X", mode); + LOG_DEBUG("MODE: 0x%02X", mode); /* try to exit current mode */ switch (mode) { @@ -584,7 +590,7 @@ static int stlink_usb_init_mode(void *handle) if (res != ERROR_OK) return res; - LOG_DEBUG("MODE: %02X", mode); + LOG_DEBUG("MODE: 0x%02X", mode); /* set selected mode */ switch (h->transport) { @@ -617,7 +623,7 @@ static int stlink_usb_init_mode(void *handle) if (res != ERROR_OK) return res; - LOG_DEBUG("MODE: %02X", mode); + LOG_DEBUG("MODE: 0x%02X", mode); return ERROR_OK; } @@ -644,11 +650,83 @@ static int stlink_usb_idcode(void *handle, uint32_t *idcode) *idcode = le_to_h_u32(h->databuf); - LOG_DEBUG("IDCODE: %08X", *idcode); + LOG_DEBUG("IDCODE: 0x%08X", *idcode); return ERROR_OK; } +static int stlink_usb_v2_read_debug_reg(void *handle, uint32_t addr, uint32_t *val) +{ + struct stlink_usb_handle_s *h; + int res; + + assert(handle != NULL); + + h = (struct stlink_usb_handle_s *)handle; + + stlink_usb_init_buffer(handle, STLINK_RX_EP, 8); + + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READDEBUGREG; + h_u32_to_le(h->cmdbuf+h->cmdidx, addr); + h->cmdidx += 4; + + res = stlink_usb_xfer(handle, h->databuf, 8); + + if (res != ERROR_OK) + return res; + + *val = le_to_h_u32(h->databuf + 4); + + return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; +} + +static int stlink_usb_write_debug_reg(void *handle, uint32_t addr, uint32_t val) +{ + int res; + struct stlink_usb_handle_s *h; + + assert(handle != NULL); + + h = (struct stlink_usb_handle_s *)handle; + + stlink_usb_init_buffer(handle, STLINK_RX_EP, 2); + + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; + if (h->jtag_api == STLINK_JTAG_API_V1) + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV1_WRITEDEBUGREG; + else + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_WRITEDEBUGREG; + h_u32_to_le(h->cmdbuf+h->cmdidx, addr); + h->cmdidx += 4; + h_u32_to_le(h->cmdbuf+h->cmdidx, val); + h->cmdidx += 4; + + res = stlink_usb_xfer(handle, h->databuf, 2); + + if (res != ERROR_OK) + return res; + + return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; +} + +static enum target_state stlink_usb_v2_get_status(void *handle) +{ + int result; + uint32_t status; + + result = stlink_usb_v2_read_debug_reg(handle, DCB_DHCSR, &status); + if (result != ERROR_OK) + return TARGET_UNKNOWN; + + if (status & S_HALT) + return TARGET_HALTED; + else if (status & S_RESET_ST) + return TARGET_RESET; + + return TARGET_RUNNING; +} + /** */ static enum target_state stlink_usb_state(void *handle) { @@ -660,7 +738,7 @@ static enum target_state stlink_usb_state(void *handle) h = (struct stlink_usb_handle_s *)handle; if (h->jtag_api == STLINK_JTAG_API_V2) - return TARGET_UNKNOWN; + return stlink_usb_v2_get_status(handle); stlink_usb_init_buffer(handle, STLINK_RX_EP, 2); @@ -704,9 +782,35 @@ static int stlink_usb_reset(void *handle) if (res != ERROR_OK) return res; - LOG_DEBUG("RESET: %08X", h->databuf[0]); + LOG_DEBUG("RESET: 0x%08X", h->databuf[0]); - return ERROR_OK; + return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; +} + +static int stlink_usb_assert_srst(void *handle, int srst) +{ + int res; + struct stlink_usb_handle_s *h; + + assert(handle != NULL); + + h = (struct stlink_usb_handle_s *)handle; + + if (h->jtag_api == STLINK_JTAG_API_V1) + return ERROR_COMMAND_NOTFOUND; + + stlink_usb_init_buffer(handle, STLINK_RX_EP, 2); + + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_DRIVE_NRST; + h->cmdbuf[h->cmdidx++] = srst; + + res = stlink_usb_xfer(handle, h->databuf, 2); + + if (res != ERROR_OK) + return res; + + return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; } /** */ @@ -720,7 +824,7 @@ static int stlink_usb_run(void *handle) h = (struct stlink_usb_handle_s *)handle; if (h->jtag_api == STLINK_JTAG_API_V2) - return ERROR_FAIL; + return stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_DEBUGEN); stlink_usb_init_buffer(handle, STLINK_RX_EP, 2); @@ -732,7 +836,7 @@ static int stlink_usb_run(void *handle) if (res != ERROR_OK) return res; - return ERROR_OK; + return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; } /** */ @@ -746,7 +850,7 @@ static int stlink_usb_halt(void *handle) h = (struct stlink_usb_handle_s *)handle; if (h->jtag_api == STLINK_JTAG_API_V2) - return ERROR_FAIL; + return stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_DEBUGEN); stlink_usb_init_buffer(handle, STLINK_RX_EP, 2); @@ -758,7 +862,7 @@ static int stlink_usb_halt(void *handle) if (res != ERROR_OK) return res; - return ERROR_OK; + return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; } /** */ @@ -771,8 +875,13 @@ static int stlink_usb_step(void *handle) h = (struct stlink_usb_handle_s *)handle; - if (h->jtag_api == STLINK_JTAG_API_V2) - return ERROR_FAIL; + if (h->jtag_api == STLINK_JTAG_API_V2) { + /* TODO: this emulates the v1 api, it should really use a similar auto mask isr + * that the cortex-m3 currently does. */ + stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_MASKINTS|C_DEBUGEN); + stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_STEP|C_MASKINTS|C_DEBUGEN); + return stlink_usb_write_debug_reg(handle, DCB_DHCSR, DBGKEY|C_HALT|C_DEBUGEN); + } stlink_usb_init_buffer(handle, STLINK_RX_EP, 2); @@ -784,7 +893,7 @@ static int stlink_usb_step(void *handle) if (res != ERROR_OK) return res; - return ERROR_OK; + return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; } /** */ @@ -823,7 +932,7 @@ static int stlink_usb_read_reg(void *handle, int num, uint32_t *val) h = (struct stlink_usb_handle_s *)handle; - stlink_usb_init_buffer(handle, STLINK_RX_EP, 4); + stlink_usb_init_buffer(handle, STLINK_RX_EP, h->jtag_api == STLINK_JTAG_API_V1 ? 4 : 8); h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; if (h->jtag_api == STLINK_JTAG_API_V1) @@ -832,12 +941,17 @@ static int stlink_usb_read_reg(void *handle, int num, uint32_t *val) h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_READREG; h->cmdbuf[h->cmdidx++] = num; - res = stlink_usb_xfer(handle, h->databuf, 4); + res = stlink_usb_xfer(handle, h->databuf, h->jtag_api == STLINK_JTAG_API_V1 ? 4 : 8); if (res != ERROR_OK) return res; - *val = le_to_h_u32(h->databuf); + if (h->jtag_api == STLINK_JTAG_API_V1) + *val = le_to_h_u32(h->databuf); + else { + *val = le_to_h_u32(h->databuf + 4); + return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; + } return ERROR_OK; } @@ -868,7 +982,32 @@ static int stlink_usb_write_reg(void *handle, int num, uint32_t val) if (res != ERROR_OK) return res; - return ERROR_OK; + return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : ERROR_FAIL; +} + +static int stlink_usb_get_rw_status(void *handle) +{ + int res; + struct stlink_usb_handle_s *h; + + assert(handle != NULL); + + h = (struct stlink_usb_handle_s *)handle; + + if (h->jtag_api == STLINK_JTAG_API_V1) + return ERROR_OK; + + stlink_usb_init_buffer(handle, STLINK_RX_EP, 2); + + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_COMMAND; + h->cmdbuf[h->cmdidx++] = STLINK_DEBUG_APIV2_GETLASTRWSTATUS; + + res = stlink_usb_xfer(handle, h->databuf, 2); + + if (res != ERROR_OK) + return res; + + return h->databuf[0] == STLINK_DEBUG_ERR_OK ? ERROR_OK : res; } /** */ @@ -903,7 +1042,7 @@ static int stlink_usb_read_mem8(void *handle, uint32_t addr, uint16_t len, memcpy(buffer, h->databuf, len); - return ERROR_OK; + return stlink_usb_get_rw_status(handle); } /** */ @@ -926,17 +1065,17 @@ static int stlink_usb_write_mem8(void *handle, uint32_t addr, uint16_t len, h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; - res = stlink_usb_xfer(handle, (uint8_t *) buffer, len); + res = stlink_usb_xfer(handle, buffer, len); if (res != ERROR_OK) return res; - return ERROR_OK; + return stlink_usb_get_rw_status(handle); } /** */ static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, - uint32_t *buffer) + uint8_t *buffer) { int res; struct stlink_usb_handle_s *h; @@ -963,12 +1102,12 @@ static int stlink_usb_read_mem32(void *handle, uint32_t addr, uint16_t len, memcpy(buffer, h->databuf, len); - return ERROR_OK; + return stlink_usb_get_rw_status(handle); } /** */ static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, - const uint32_t *buffer) + const uint8_t *buffer) { int res; struct stlink_usb_handle_s *h; @@ -988,12 +1127,12 @@ static int stlink_usb_write_mem32(void *handle, uint32_t addr, uint16_t len, h_u16_to_le(h->cmdbuf+h->cmdidx, len); h->cmdidx += 2; - res = stlink_usb_xfer(handle, (uint8_t *) buffer, len); + res = stlink_usb_xfer(handle, buffer, len); if (res != ERROR_OK) return res; - return ERROR_OK; + return stlink_usb_get_rw_status(handle); } /** */ @@ -1001,6 +1140,7 @@ static int stlink_usb_open(struct stlink_interface_param_s *param, void **fd) { int err; struct stlink_usb_handle_s *h; + enum stlink_jtag_api_version api; LOG_DEBUG("stlink_usb_open"); @@ -1016,7 +1156,7 @@ static int stlink_usb_open(struct stlink_interface_param_s *param, void **fd) const uint16_t vids[] = { param->vid, 0 }; const uint16_t pids[] = { param->pid, 0 }; - LOG_DEBUG("transport: %d vid: %04x pid: %04x", param->transport, + LOG_DEBUG("transport: %d vid: 0x%04x pid: 0x%04x", param->transport, param->vid, param->pid); if (jtag_libusb_open(vids, pids, &h->fd) != ERROR_OK) { @@ -1053,7 +1193,7 @@ static int stlink_usb_open(struct stlink_interface_param_s *param, void **fd) /* compare usb vid/pid */ if ((param->vid != h->vid) || (param->pid != h->pid)) - LOG_INFO("vid/pid are not identical: %04X/%04X %04X/%04X", + LOG_INFO("vid/pid are not identical: 0x%04X/0x%04X 0x%04X/0x%04X", param->vid, param->pid, h->vid, h->pid); @@ -1082,8 +1222,17 @@ static int stlink_usb_open(struct stlink_interface_param_s *param, void **fd) return err; } - /* set the used jtag api */ - h->jtag_api = STLINK_JTAG_API_V1; + api = h->version.jtag_api_max; + + /* check that user has not requested certain api version + * and if they have check it is supported */ + if ((param->api != 0) && (param->api <= h->version.jtag_api_max)) { + api = param->api; + LOG_INFO("using stlink api v%d", api); + } + + /* set the used jtag api, this will default to the newest supported version */ + h->jtag_api = api; /* initialize the debug hardware */ err = stlink_usb_init_mode(h); @@ -1119,6 +1268,8 @@ struct stlink_layout_api_s stlink_usb_layout_api = { /** */ .reset = stlink_usb_reset, /** */ + .assert_srst = stlink_usb_assert_srst, + /** */ .run = stlink_usb_run, /** */ .halt = stlink_usb_halt, @@ -1138,4 +1289,6 @@ struct stlink_layout_api_s stlink_usb_layout_api = { .read_mem32 = stlink_usb_read_mem32, /** */ .write_mem32 = stlink_usb_write_mem32, + /** */ + .write_debug_reg = stlink_usb_write_debug_reg };