noinst_LIBRARIES = libstlink.a
st_flash_SOURCES = flash/main.c
-st_util_SOURCES = gdbserver/gdb-remote.c gdbserver/gdb-remote.h gdbserver/gdb-server.c
+st_util_SOURCES = gdbserver/gdb-remote.c gdbserver/gdb-remote.h gdbserver/gdb-server.c mingw/mingw.c mingw/mingw.h
CFILES = \
src/stlink-common.c \
libstlink_a_LIBADD = $(LIBOBJS)
st_flash_LDADD = libstlink.a
-st_flash_CPPFLAGS = -std=gnu99 -Wall -Wextra -O2 -I$(top_srcdir)/src
+st_flash_CPPFLAGS = -std=gnu99 -Wall -Wextra -O2 -I$(top_srcdir)/src -I$(top_srcdir)/mingw
st_util_LDADD = libstlink.a
-st_util_CPPFLAGS = -std=gnu99 -Wall -Wextra -O2 -I$(top_srcdir)/src
+st_util_CPPFLAGS = -std=gnu99 -Wall -Wextra -O2 -I$(top_srcdir)/src -I$(top_srcdir)/mingw
EXTRA_DIST = autogen.sh
AC_CANONICAL_HOST
AC_CANONICAL_BUILD
AC_PROG_RANLIB
-#AC_PROG_LIBTOOL
AM_PROG_CC_C_O
AC_CHECK_HEADERS(sys/mman.h)
+AC_CHECK_HEADERS(sys/poll.h)
AC_CHECK_FUNCS(mmap)
AC_REPLACE_FUNCS(mmap pread)
LIBS="$LIBS $USB_LIBS"
CFLAGS="$CFLAGS $USB_CFLAGS"
+case "${host}" in
+ *-mingw32*)
+ LIBS="$LIBS -lws2_32"
+ ;;
+esac
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
#include <stdlib.h>
#include <unistd.h>
#include <stdint.h>
+#ifdef __MINGW32__
+#include "mingw.h"
+#else
#include <sys/poll.h>
+#endif
static const char hex[] = "0123456789abcdef";
packet[0] = '$';
uint8_t cksum = 0;
- for(int i = 0; i < strlen(data); i++) {
+ for(unsigned int i = 0; i < strlen(data); i++) {
packet[i + 1] = data[i];
cksum += data[i];
}
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
+#ifdef __MINGW32__
+#include "mingw.h"
+#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
+#endif
#include <stlink-common.h>
"<!DOCTYPE memory-map PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\""
" \"http://sourceware.org/gdb/gdb-memory-map.dtd\">"
"<memory-map>"
- " <memory type=\"rom\" start=\"0x00000000\" length=\"0x%x\"/>" // code = sram, bootrom or flash; flash is bigger
- " <memory type=\"ram\" start=\"0x20000000\" length=\"0x%x\"/>" // sram 8k
- " <memory type=\"flash\" start=\"0x08000000\" length=\"0x%x\">"
- " <property name=\"blocksize\">0x%x</property>"
+ " <memory type=\"rom\" start=\"0x00000000\" length=\"0x%zx\"/>" // code = sram, bootrom or flash; flash is bigger
+ " <memory type=\"ram\" start=\"0x20000000\" length=\"0x%zx\"/>" // sram 8k
+ " <memory type=\"flash\" start=\"0x08000000\" length=\"0x%zx\">"
+ " <property name=\"blocksize\">0x%zx</property>"
" </memory>"
" <memory type=\"ram\" start=\"0x40000000\" length=\"0x1fffffff\"/>" // peripheral regs
" <memory type=\"ram\" start=\"0xe0000000\" length=\"0x1fffffff\"/>" // cortex regs
- " <memory type=\"rom\" start=\"0x%08x\" length=\"0x%x\"/>" // bootrom
- " <memory type=\"rom\" start=\"0x1ffff800\" length=\"0x8\"/>" // option byte area
+ " <memory type=\"rom\" start=\"0x%08x\" length=\"0x%zx\"/>" // bootrom
+ " <memory type=\"rom\" start=\"0x1ffff800\" length=\"0x8x\"/>" // option byte area
"</memory-map>";
char* make_memory_map(stlink_t *sl) {
mask++;
}
- if((mask != -1) && (mask < 16)) {
+ if((mask != (uint32_t)-1) && (mask < 16)) {
for(i = 0; i < DATA_WATCH_NUM; i++) {
// is this an empty slot ?
if(data_watches[i].fun == WATCHDISABLED) {
}
static int flash_populate(stm32_addr_t addr, uint8_t* data, unsigned length) {
- int fit_blocks = 0, fit_length = 0;
+ unsigned int fit_blocks = 0, fit_length = 0;
for(struct flash_block* fb = flash_root; fb; fb = fb->next) {
/* Block: ------X------Y--------
unsigned int val = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
- struct sockaddr_in serv_addr = {0};
+ struct sockaddr_in serv_addr;
+ bzero(&serv_addr,sizeof(struct sockaddr_in));
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
serv_addr.sin_port = htons(port);
printf("Listening at *:%d...\n", port);
int client = accept(sock, NULL, NULL);
- signal (SIGINT, SIG_DFL);
+ //signal (SIGINT, SIG_DFL);
if(client < 0) {
perror("accept");
return 1;
if(!strcmp(queryName, "Supported")) {
reply = strdup("PacketSize=3fff;qXfer:memory-map:read+");
} else if(!strcmp(queryName, "Xfer")) {
- char *type, *op, *s_addr, *s_length;
+ char *type, *op, *__s_addr, *s_length;
char *tok = params;
char *annex __attribute__((unused));
type = strsep(&tok, ":");
op = strsep(&tok, ":");
annex = strsep(&tok, ":");
- s_addr = strsep(&tok, ",");
+ __s_addr = strsep(&tok, ",");
s_length = tok;
- unsigned addr = strtoul(s_addr, NULL, 16),
+ unsigned addr = strtoul(__s_addr, NULL, 16),
length = strtoul(s_length, NULL, 16);
#ifdef DEBUG
cmdName++; // vCommand -> Command
if(!strcmp(cmdName, "FlashErase")) {
- char *s_addr, *s_length;
+ char *__s_addr, *s_length;
char *tok = params;
- s_addr = strsep(&tok, ",");
+ __s_addr = strsep(&tok, ",");
s_length = tok;
- unsigned addr = strtoul(s_addr, NULL, 16),
+ unsigned addr = strtoul(__s_addr, NULL, 16),
length = strtoul(s_length, NULL, 16);
#ifdef DEBUG
reply = strdup("OK");
}
} else if(!strcmp(cmdName, "FlashWrite")) {
- char *s_addr, *data;
+ char *__s_addr, *data;
char *tok = params;
- s_addr = strsep(&tok, ":");
+ __s_addr = strsep(&tok, ":");
data = tok;
- unsigned addr = strtoul(s_addr, NULL, 16);
+ unsigned addr = strtoul(__s_addr, NULL, 16);
unsigned data_length = status - (data - packet);
// Length of decoded data cannot be more than
// Additional byte is reserved for alignment fix.
uint8_t *decoded = calloc(data_length + 1, 1);
unsigned dec_index = 0;
- for(int i = 0; i < data_length; i++) {
+ for(unsigned int i = 0; i < data_length; i++) {
if(data[i] == 0x7d) {
i++;
decoded[dec_index++] = data[i] ^ 0x20;
count : count + 4 - (count % 4));
reply = calloc(count * 2 + 1, 1);
- for(int i = 0; i < count; i++) {
+ for(unsigned int i = 0; i < count; i++) {
reply[i * 2 + 0] = hex[sl->q_buf[i + adj_start] >> 4];
reply[i * 2 + 1] = hex[sl->q_buf[i + adj_start] & 0xf];
}
stm32_addr_t start = strtoul(s_start, NULL, 16);
unsigned count = strtoul(s_count, NULL, 16);
- for(int i = 0; i < count; i ++) {
+ for(unsigned int i = 0; i < count; i ++) {
char hex[3] = { hexdata[i*2], hexdata[i*2+1], 0 };
uint8_t byte = strtoul(hex, NULL, 16);
sl->q_buf[i] = byte;
--- /dev/null
+#ifdef __MINGW32__
+
+#include "mingw.h"
+
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+
+int win32_poll(struct pollfd *fds, unsigned int nfds, int timo)
+{
+ struct timeval timeout, *toptr;
+ fd_set ifds, ofds, efds, *ip, *op;
+ int i, rc;
+
+ /* Set up the file-descriptor sets in ifds, ofds and efds. */
+ FD_ZERO(&ifds);
+ FD_ZERO(&ofds);
+ FD_ZERO(&efds);
+ for (i = 0, op = ip = 0; i < nfds; ++i) {
+ fds[i].revents = 0;
+ if(fds[i].events & (POLLIN|POLLPRI)) {
+ ip = &ifds;
+ FD_SET(fds[i].fd, ip);
+ }
+ if(fds[i].events & POLLOUT) {
+ op = &ofds;
+ FD_SET(fds[i].fd, op);
+ }
+ FD_SET(fds[i].fd, &efds);
+ }
+
+ /* Set up the timeval structure for the timeout parameter */
+ if(timo < 0) {
+ toptr = 0;
+ } else {
+ toptr = &timeout;
+ timeout.tv_sec = timo / 1000;
+ timeout.tv_usec = (timo - timeout.tv_sec * 1000) * 1000;
+ }
+
+#ifdef DEBUG_POLL
+ printf("Entering select() sec=%ld usec=%ld ip=%lx op=%lx\n",
+ (long)timeout.tv_sec, (long)timeout.tv_usec, (long)ip, (long)op);
+#endif
+ rc = select(0, ip, op, &efds, toptr);
+#ifdef DEBUG_POLL
+ printf("Exiting select rc=%d\n", rc);
+#endif
+
+ if(rc <= 0)
+ return rc;
+
+ if(rc > 0) {
+ for (i = 0; i < nfds; ++i) {
+ int fd = fds[i].fd;
+ if(fds[i].events & (POLLIN|POLLPRI) && FD_ISSET(fd, &ifds))
+ fds[i].revents |= POLLIN;
+ if(fds[i].events & POLLOUT && FD_ISSET(fd, &ofds))
+ fds[i].revents |= POLLOUT;
+ if(FD_ISSET(fd, &efds))
+ /* Some error was detected ... should be some way to know. */
+ fds[i].revents |= POLLHUP;
+#ifdef DEBUG_POLL
+ printf("%d %d %d revent = %x\n",
+ FD_ISSET(fd, &ifds), FD_ISSET(fd, &ofds), FD_ISSET(fd, &efds),
+ fds[i].revents
+ );
+#endif
+ }
+ }
+ return rc;
+}
+static void
+set_connect_errno(int winsock_err)
+{
+ switch(winsock_err) {
+ case WSAEINVAL:
+ case WSAEALREADY:
+ case WSAEWOULDBLOCK:
+ errno = EINPROGRESS;
+ break;
+ default:
+ errno = winsock_err;
+ break;
+ }
+}
+
+static void
+set_socket_errno(int winsock_err)
+{
+ switch(winsock_err) {
+ case WSAEWOULDBLOCK:
+ errno = EAGAIN;
+ break;
+ default:
+ errno = winsock_err;
+ break;
+ }
+}
+/*
+ * A wrapper around the socket() function. The purpose of this wrapper
+ * is to ensure that the global errno symbol is set if an error occurs,
+ * even if we are using winsock.
+ */
+SOCKET
+win32_socket(int domain, int type, int protocol)
+{
+ SOCKET fd = socket(domain, type, protocol);
+ if(fd == INVALID_SOCKET) {
+ set_socket_errno(WSAGetLastError());
+ }
+ return fd;
+}
+/*
+ * A wrapper around the connect() function. The purpose of this wrapper
+ * is to ensure that the global errno symbol is set if an error occurs,
+ * even if we are using winsock.
+ */
+int
+win32_connect(SOCKET fd, struct sockaddr *addr, socklen_t addr_len)
+{
+ int rc = connect(fd, addr, addr_len);
+ assert(rc == 0 || rc == SOCKET_ERROR);
+ if(rc == SOCKET_ERROR) {
+ set_connect_errno(WSAGetLastError());
+ }
+ return rc;
+}
+
+/*
+ * A wrapper around the accept() function. The purpose of this wrapper
+ * is to ensure that the global errno symbol is set if an error occurs,
+ * even if we are using winsock.
+ */
+SOCKET
+win32_accept(SOCKET fd, struct sockaddr *addr, socklen_t *addr_len)
+{
+ SOCKET newfd = accept(fd, addr, addr_len);
+ if(newfd == INVALID_SOCKET) {
+ set_socket_errno(WSAGetLastError());
+ newfd = -1;
+ }
+ return newfd;
+}
+
+/*
+ * A wrapper around the shutdown() function. The purpose of this wrapper
+ * is to ensure that the global errno symbol is set if an error occurs,
+ * even if we are using winsock.
+ */
+int
+win32_shutdown(SOCKET fd, int mode)
+{
+ int rc = shutdown(fd, mode);
+ assert(rc == 0 || rc == SOCKET_ERROR);
+ if(rc == SOCKET_ERROR) {
+ set_socket_errno(WSAGetLastError());
+ }
+ return rc;
+}
+int win32_close_socket(SOCKET fd) {
+ int rc;
+
+ rc = closesocket(fd);
+ return 0;
+}
+
+
+int win32_write_socket(SOCKET fd, void *buf, int n)
+{
+ int rc = send(fd, buf, n, 0);
+ if(rc == SOCKET_ERROR) {
+ set_socket_errno(WSAGetLastError());
+ }
+ return rc;
+}
+
+int win32_read_socket(SOCKET fd, void *buf, int n)
+{
+ int rc = recv(fd, buf, n, 0);
+ if(rc == SOCKET_ERROR) {
+ set_socket_errno(WSAGetLastError());
+ }
+ return rc;
+}
+
+
+char * win32_strtok_r(char *s, const char *delim, char **lasts)
+{
+ register char *spanp;
+ register int c, sc;
+ char *tok;
+
+
+ if (s == NULL && (s = *lasts) == NULL)
+ return (NULL);
+
+ /*
+ * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+ */
+cont:
+ c = *s++;
+ for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
+ if (c == sc)
+ goto cont;
+ }
+
+ if (c == 0) { /* no non-delimiter characters */
+ *lasts = NULL;
+ return (NULL);
+ }
+ tok = s - 1;
+
+ /*
+ * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+ * Note that delim must have one NUL; we stop if we see that, too.
+ */
+ for (;;) {
+ c = *s++;
+ spanp = (char *)delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *lasts = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
+
+char *win32_strsep (char **stringp, const char *delim)
+{
+ register char *s;
+ register const char *spanp;
+ register int c, sc;
+ char *tok;
+
+ if ((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
+
+#endif
+
+
--- /dev/null
+#ifdef __MINGW32__
+
+#include <io.h>
+
+#include <winsock.h>
+
+#define ENOTCONN WSAENOTCONN
+#define EWOULDBLOCK WSAEWOULDBLOCK
+#define ENOBUFS WSAENOBUFS
+#define ECONNRESET WSAECONNRESET
+#define ESHUTDOWN WSAESHUTDOWN
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+#define EINPROGRESS WSAEINPROGRESS
+#define EISCONN WSAEISCONN
+
+/* winsock doesn't feature poll(), so there is a version implemented
+ * in terms of select() in mingw.c. The following definitions
+ * are copied from linux man pages. A poll() macro is defined to
+ * call the version in mingw.c.
+ */
+#define POLLIN 0x0001 /* There is data to read */
+#define POLLPRI 0x0002 /* There is urgent data to read */
+#define POLLOUT 0x0004 /* Writing now will not block */
+#define POLLERR 0x0008 /* Error condition */
+#define POLLHUP 0x0010 /* Hung up */
+#define POLLNVAL 0x0020 /* Invalid request: fd not open */
+struct pollfd {
+ SOCKET fd; /* file descriptor */
+ short events; /* requested events */
+ short revents; /* returned events */
+};
+#define poll(x, y, z) win32_poll(x, y, z)
+
+/* These wrappers do nothing special except set the global errno variable if
+ * an error occurs (winsock doesn't do this by default). They set errno
+ * to unix-like values (i.e. WSAEWOULDBLOCK is mapped to EAGAIN), so code
+ * outside of this file "shouldn't" have to worry about winsock specific error
+ * handling.
+ */
+#define socket(x, y, z) win32_socket(x, y, z)
+#define connect(x, y, z) win32_connect(x, y, z)
+#define accept(x, y, z) win32_accept(x, y, z)
+#define shutdown(x, y) win32_shutdown(x, y)
+
+/* Winsock uses int instead of the usual socklen_t */
+typedef int socklen_t;
+
+int win32_poll(struct pollfd *, unsigned int, int);
+SOCKET win32_socket(int, int, int);
+int win32_connect(SOCKET, struct sockaddr*, socklen_t);
+SOCKET win32_accept(SOCKET, struct sockaddr*, socklen_t *);
+int win32_shutdown(SOCKET, int);
+
+#define strtok_r(x, y, z) win32_strtok_r(x, y, z)
+#define strsep(x,y) win32_strsep(x,y)
+
+char *win32_strtok_r(char *s, const char *delim, char **lasts);
+char *win32_strsep(char **stringp, const char *delim);
+
+#endif