Hi all,

The current openocd git doesn't have usable stlink-v1 support.

Memory writes are completely broken (meaning they don't work at all).
The current code tries to issue two SG commands and check the status
twice, while it should:
-send the command
-write the actual data bytes
-check the status

After reading texane's code it seems to me that all st-link commands
follow this pattern (although his code doesn't):
-send the command
-optionally send or receive data bytes (depends on the command)
-read the SG status (v1 only)

See stlink_usb_xfer_v1 in the patch.

Furthermore, the function stlink_usb_recv_v1_get_sense makes
absolutely no sense. The cdb buffer remains mostly uninitialised and
contains garbage, but it doesn't matter, because its contents are not
used (it is copied into sg_buffer, but then only the first 16 bytes of
that buffer are sent, which includes only the first byte of cdb). It
also duplicates code since it follows the exact same pattern as all
other st-link commands do. Is it even needed? There seems to be no
equivalent in texane's source. What's it supposed to do?

changes:
-it seems to be working now (but needs more testing)
-refactored / rewrote some of the code
-added stlink_usb_send for use by the stlink_usb_write_mem functions
-removed stlink_usb_recv_v1_get_sense since I couldn't make any sense of it

Initial testing done on STM32VLDISCOVERY (flashing and GDB).
I didn't check if stlink-v2 is still working (but it shouldn't break much).

Regards,

Szymon Modzelewski
--- a/src/jtag/drivers/stlink_usb.c	2012-02-21 05:07:13.790964417 +0100
+++ b/src/jtag/drivers/stlink_usb.c	2012-02-21 05:08:01.683201900 +0100
@@ -34,14 +34,16 @@
 
 #include "libusb_common.h"
 
-#define ENDPOINT_IN	0x80
-#define ENDPOINT_OUT	0x00
+#define ENDPOINT_IN		0x80
+#define ENDPOINT_OUT		0x00
 
-#define STLINK_RX_EP	(1|ENDPOINT_IN)
-#define STLINK_TX_EP	(2|ENDPOINT_OUT)
-#define STLINK_CMD_SIZE	(16)
-#define STLINK_TX_SIZE	(4*128)
-#define STLINK_RX_SIZE	(4*128)
+#define STLINK_RX_EP		(1|ENDPOINT_IN)
+#define STLINK_TX_EP		(2|ENDPOINT_OUT)
+#define STLINK_CMD_SIZE_V2	(16)
+#define STLINK_CMD_SIZE_V1	(10)
+#define STLINK_CMD_SIZE		STLINK_CMD_SIZE_V1
+#define STLINK_TX_SIZE		(4*128)
+#define STLINK_RX_SIZE		(4*128)
 
 enum stlink_jtag_api_version {
 	STLINK_JTAG_API_V1 = 0,
@@ -158,56 +160,40 @@
 };
 
 /** */
-static void stlink_usb_recv_v1_create_cmd(char *b, int s, uint32_t tag, uint32_t rxsize,
-			uint8_t flag, uint8_t lun, uint8_t length)
+static int stlink_usb_xfer_v1_send_cmd(void *handle, const uint8_t *cmd, int cmdsize, int ep, int size)
 {
-	int i = 0;
-
-	memset(b, 0x00, s);
-
-	/* fill the send buffer */
-	strcpy(b, "USBC");
-	i += 4;
-
-	buf_set_u32(b+i, 0, 32, tag);
-	i += 4;
-	buf_set_u32(b+i, 0, 32, rxsize);
-	i += 4;
-	b[i++] = flag;
-	b[i++] = lun;
-	b[i++] = length;
-}
-
-/** */
-static int stlink_usb_recv_v1_mass_storage_cmd(void *handle, const uint8_t *txbuf, int txsize, uint8_t *rxbuf,
-		    int rxsize)
-{
-	char sg_buffer[31];
+	uint8_t sg_buffer[31];
 	struct stlink_usb_handle_s *h;
 
 	assert(handle != NULL);
+	assert(cmdsize <= 16);
 
 	h = (struct stlink_usb_handle_s *)handle;
-	h->sg_tag = (h->sg_tag + 1) & 1;
-
-	stlink_usb_recv_v1_create_cmd(sg_buffer, 31, h->sg_tag, rxsize, STLINK_TX_EP, 0x00, txsize);
-
-	memcpy(sg_buffer+15, txbuf, 10);
-
-	if (jtag_libusb_bulk_write(h->fd, STLINK_TX_EP, (char *)sg_buffer, 31,
-				   1000) != 31) {
-		printf("send failed\n");
+	h->sg_tag = (h->sg_tag + 1) & 1; /* seriously? */
+	
+	memset(sg_buffer, 0, sizeof(sg_buffer));
+	
+	h_u32_to_le(sg_buffer, 0x43425355); /* USBC */	
+	h_u32_to_le(&sg_buffer[4], h->sg_tag);
+	h_u32_to_le(&sg_buffer[8], size);
+	
+	sg_buffer[12] = (ep == STLINK_RX_EP ? ENDPOINT_IN : ENDPOINT_OUT);
+	/* sg_buffer[13] = 0; */
+	sg_buffer[14] = (uint8_t)cmdsize;
+	
+	memcpy(&sg_buffer[15], cmd, cmdsize);
+	
+	if (jtag_libusb_bulk_write(h->fd, STLINK_TX_EP, (char *)sg_buffer, sizeof(sg_buffer),
+				   1000) != sizeof(sg_buffer)) {
+		LOG_DEBUG("send failed\n");
 		return ERROR_FAIL;
 	}
 
 	return ERROR_OK;
 }
 
-#define REQUEST_SENSE		0x03
-#define REQUEST_SENSE_LENGTH	18
-
 /** */
-static int stlink_usb_recv_v1_get_status(void *handle, char *sg_buffer, int len)
+static int stlink_usb_xfer_v1_get_status(void *handle, uint8_t *sg_buffer, int len)
 {
 	struct stlink_usb_handle_s *h;
 
@@ -216,16 +202,14 @@
 	h = (struct stlink_usb_handle_s *)handle;
 
 	/* read status */
-	memset(sg_buffer, 0x00, len);
+	memset(sg_buffer, 0, len);
 
 	if (jtag_libusb_bulk_read(h->fd, STLINK_RX_EP, (char *)sg_buffer,
 				len, 1000) != len)
 		return ERROR_FAIL;
-
-	uint32_t t1, t2;
-
-	t1 = buf_get_u32(sg_buffer+0, 0, 32);
-	t2 = buf_get_u32(sg_buffer+4, 0, 32);
+	
+	uint32_t t1 = le_to_h_u32(sg_buffer+0);
+	/* uint32_t t2 = le_to_h_u32(sg_buffer+4); */
 
 	/* check for USBS */
 	if (t1 != 0x53425355)
@@ -235,81 +219,93 @@
 }
 
 /** */
-static int stlink_usb_recv_v1_get_sense(void *handle)
+static int stlink_usb_xfer_v1_check_status(void *handle)
 {
-	struct stlink_usb_handle_s *h;
-	char cdb[16];
-	char sg_buffer[31];
+	int err;
+	uint8_t sg_buffer[13];
+	
+	err = stlink_usb_xfer_v1_get_status(handle, sg_buffer, sizeof(sg_buffer));
+	
+	if (err != ERROR_OK)
+		return err;
+	
+	/* check for sense */
+	if (sg_buffer[12] == 1) {
+		LOG_DEBUG("get sense");
+		
+		/* err = stlink_usb_xfer_v1_get_sense(...) ??? */
+	}
+	/* doesn't make any more sense either way */
 
-	assert(handle != NULL);
+	return err;
+}
 
+/** */
+static int stlink_usb_xfer_rw(void *handle, int ep, uint8_t *buf, int size)
+{
+	struct stlink_usb_handle_s *h;
+	
 	h = (struct stlink_usb_handle_s *)handle;
-	h->sg_tag = (h->sg_tag + 1) & 1;
-
-	cdb[0] = REQUEST_SENSE;
-	cdb[4] = REQUEST_SENSE_LENGTH;
-
-	stlink_usb_recv_v1_create_cmd(sg_buffer, 31, h->sg_tag, REQUEST_SENSE_LENGTH, STLINK_TX_EP,
-			0x00, 16);
+	
+	if (!size)
+		return ERROR_OK;
+	
+	if (ep == STLINK_RX_EP) {
+		if (jtag_libusb_bulk_read(h->fd, STLINK_RX_EP, (char *)buf,
+					  size, 1000) != size) {
+			return ERROR_FAIL;
+		}
+	} else {
+		if (jtag_libusb_bulk_write(h->fd, STLINK_TX_EP, (char *)buf,
+					  size, 1000) != size) {
+			return ERROR_FAIL;
+		}
+	}  
+	
+	return ERROR_OK;
+}
 
-	memcpy(sg_buffer+15, cdb, 16);
+/** */
+static int stlink_usb_xfer_v1(void *handle, const uint8_t *cmd, int cmdsize, int ep,
+			      uint8_t *buf, int size)
+{
+	int err;
 
-	if (jtag_libusb_bulk_write(h->fd, STLINK_TX_EP, (char *)sg_buffer, 16,
-				   1000) != 16)
-		return ERROR_FAIL;
+	assert(handle != NULL);
 
-	if (jtag_libusb_bulk_read(h->fd, STLINK_RX_EP, (char *)cdb,
-				  16, 1000) != 16)
-		return ERROR_FAIL;
+	err = stlink_usb_xfer_v1_send_cmd(handle, cmd, cmdsize, ep, size);
 
-	if (stlink_usb_recv_v1_get_status(handle, sg_buffer, 13) != ERROR_OK)
-		return ERROR_FAIL;
-	/* check for sense */
-	if (sg_buffer[12] != 0)
-		return ERROR_FAIL;
+	if (err != ERROR_OK)
+		return err;
+	
+	err = stlink_usb_xfer_rw(handle, ep, buf, size);
 
-	/* if (sense[0] != 0x70 && sense[0] != 0x71) */
+	if (err != ERROR_OK)
+		return err;
 
-	return ERROR_OK;
+	return stlink_usb_xfer_v1_check_status(handle);
 }
 
 /** */
-static int stlink_usb_recv_v1(void *handle, const uint8_t *txbuf, int txsize, uint8_t *rxbuf,
-		    int rxsize)
+static int stlink_usb_xfer_v2(void *handle, const uint8_t *cmd, int cmdsize, int ep,
+			      uint8_t *buf, int size)
 {
-	int err;
-	char sg_buffer[31];
 	struct stlink_usb_handle_s *h;
 
 	assert(handle != NULL);
 
 	h = (struct stlink_usb_handle_s *)handle;
 
-	err = stlink_usb_recv_v1_mass_storage_cmd(handle, txbuf, txsize, rxbuf, rxsize);
-
-	if (err != ERROR_OK)
-		return err;
-
-	if (rxsize && rxbuf) {
-		if (jtag_libusb_bulk_read(h->fd, STLINK_RX_EP, (char *)rxbuf,
-					  rxsize, 1000) != rxsize) {
-			LOG_DEBUG("jtag_libusb_bulk_read");
-			return ERROR_FAIL;
-		}
-	}
-
-	if (stlink_usb_recv_v1_get_status(handle, sg_buffer, 13) != ERROR_OK)
+	if (jtag_libusb_bulk_write(h->fd, STLINK_TX_EP, (char *)cmd, cmdsize,
+				   1000) != cmdsize) {
 		return ERROR_FAIL;
-	/* check for sense */
-	if (sg_buffer[12] == 1) {
-		LOG_DEBUG("get sense");
-		err = stlink_usb_recv_v1_get_sense(handle);
 	}
-	return err;
+	
+	return stlink_usb_xfer_rw(handle, ep, buf, size);
 }
 
 /** */
-static int stlink_usb_recv_v2(void *handle, const uint8_t *txbuf, int txsize, uint8_t *rxbuf,
+static int stlink_usb_recv(void *handle, const uint8_t *cmd, int cmdsize, uint8_t *rxbuf,
 		    int rxsize)
 {
 	struct stlink_usb_handle_s *h;
@@ -318,22 +314,18 @@
 
 	h = (struct stlink_usb_handle_s *)handle;
 
-	if (jtag_libusb_bulk_write(h->fd, STLINK_TX_EP, (char *)txbuf, txsize,
-				   1000) != txsize) {
-		return ERROR_FAIL;
-	}
-	if (rxsize && rxbuf) {
-		if (jtag_libusb_bulk_read(h->fd, STLINK_RX_EP, (char *)rxbuf,
-					  rxsize, 1000) != rxsize) {
-			return ERROR_FAIL;
-		}
+	if (h->version.stlink == 1) {
+		assert(cmdsize <= STLINK_CMD_SIZE_V1);
+		return stlink_usb_xfer_v1(handle, cmd, STLINK_CMD_SIZE_V1, STLINK_RX_EP, rxbuf, rxsize);
+	} else {
+		assert(cmdsize <= STLINK_CMD_SIZE_V2);
+		return stlink_usb_xfer_v2(handle, cmd, STLINK_CMD_SIZE_V2, STLINK_RX_EP, rxbuf, rxsize);
 	}
-	return ERROR_OK;
 }
 
 /** */
-static int stlink_usb_recv(void *handle, const uint8_t *txbuf, int txsize, uint8_t *rxbuf,
-		    int rxsize)
+static int stlink_usb_send(void *handle, const uint8_t *cmd, int cmdsize, uint8_t *txbuf,
+		    int txsize)
 {
 	struct stlink_usb_handle_s *h;
 
@@ -342,11 +334,11 @@
 	h = (struct stlink_usb_handle_s *)handle;
 
 	if (h->version.stlink == 1) {
-		return stlink_usb_recv_v1(handle, txbuf, txsize, rxbuf, rxsize);
+		assert(cmdsize <= STLINK_CMD_SIZE_V1);
+		return stlink_usb_xfer_v1(handle, cmd, STLINK_CMD_SIZE_V1, STLINK_TX_EP, txbuf, txsize);
 	} else {
-		if (txsize < STLINK_CMD_SIZE)
-			txsize = STLINK_CMD_SIZE;
-		return stlink_usb_recv_v2(handle, txbuf, txsize, rxbuf, rxsize);
+		assert(cmdsize <= STLINK_CMD_SIZE_V2);
+		return stlink_usb_xfer_v2(handle, cmd, STLINK_CMD_SIZE_V2, STLINK_TX_EP, txbuf, txsize);
 	}
 }
 
@@ -953,12 +945,7 @@
 	h_u32_to_le(h->txbuf + 2, addr);
 	h_u16_to_le(h->txbuf + 2 + 4, len);
 
-	res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, 0, 0);
-
-	if (res != ERROR_OK)
-		return res;
-
-	res = stlink_usb_recv(handle, (uint8_t *) buffer, len, 0, 0);
+	res = stlink_usb_send(handle, h->txbuf, STLINK_CMD_SIZE, (uint8_t *) buffer, len);
 
 	if (res != ERROR_OK)
 		return res;
@@ -1015,13 +1002,8 @@
 	h->txbuf[1] = STLINK_DEBUG_WRITEMEM_32BIT;
 	h_u32_to_le(h->txbuf + 2, addr);
 	h_u16_to_le(h->txbuf + 2 + 4, len);
-
-	res = stlink_usb_recv(handle, h->txbuf, STLINK_CMD_SIZE, 0, 0);
-
-	if (res != ERROR_OK)
-		return res;
-
-	res = stlink_usb_recv(handle, (uint8_t *) buffer, len, 0, 0);
+	
+	res = stlink_usb_send(handle, h->txbuf, STLINK_CMD_SIZE, (uint8_t *) buffer, len);
 
 	if (res != ERROR_OK)
 		return res;
------------------------------------------------------------------------------
Keep Your Developer Skills Current with LearnDevNow!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-d2d
_______________________________________________
OpenOCD-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/openocd-devel

Reply via email to