build with mingw
authorDave Murphy <davem@devkitpro.org>
Sun, 29 Apr 2012 13:43:46 +0000 (14:43 +0100)
committerDave Murphy <davem@devkitpro.org>
Sun, 29 Apr 2012 13:43:46 +0000 (14:43 +0100)
Makefile.am
configure.ac
gdbserver/gdb-remote.c
gdbserver/gdb-server.c
mingw/mingw.c [new file with mode: 0644]
mingw/mingw.h [new file with mode: 0644]

index 28e11d5e59a6e1589aad4b7c4bf75b194331c75a..a315dd726419d2e3ac9daea21c6f093720b66dff 100644 (file)
@@ -7,7 +7,7 @@ bin_PROGRAMS = st-flash st-util
 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 \
@@ -28,10 +28,10 @@ libstlink_a_CPPFLAGS        = -std=gnu99 -Wall -Wextra -O2
 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
 
index a19bba4f1a366f9d37b115352098c2e3805c1472..7b4d59041c97d5cb374eb9db6d3d0dfa4c3898f0 100644 (file)
@@ -14,10 +14,10 @@ AC_PROG_INSTALL
 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)
 
@@ -29,6 +29,11 @@ AC_CHECK_LIB([usbpath],[usb_path2devnum],,,-lusb)
 LIBS="$LIBS $USB_LIBS"
 CFLAGS="$CFLAGS $USB_CFLAGS"
 
+case "${host}" in
+       *-mingw32*)
+               LIBS="$LIBS -lws2_32"
+       ;;
+esac
 AC_CONFIG_FILES([Makefile])
 AC_OUTPUT
 
index f6bf02d26a82c0faaaa45196e885fe8d8eeddc25..1b0488e322a84a25a3e2ff287b53bdca8bc1ddff 100644 (file)
 #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";
 
@@ -24,7 +28,7 @@ int gdb_send_packet(int fd, char* data) {
        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];
        }
index 94784fcdb896d7c88fdcc6894d7f52366af73ee2..b0b43d8e24209611ac995fef11ffc28c6948108a 100644 (file)
 #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>
 
@@ -203,15 +207,15 @@ static const char* const memory_map_template =
   "<!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) {
@@ -291,7 +295,7 @@ static int add_data_watchpoint(stlink_t *sl, enum watchfun wf, stm32_addr_t addr
                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) {
@@ -461,7 +465,7 @@ static int flash_add_block(stm32_addr_t addr, unsigned length, stlink_t *sl) {
 }
 
 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--------
@@ -553,7 +557,8 @@ int serve(stlink_t *sl, int port) {
        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);
@@ -576,7 +581,7 @@ int serve(stlink_t *sl, int 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;
@@ -633,17 +638,17 @@ int serve(stlink_t *sl, int port) {
                        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
@@ -729,13 +734,13 @@ int serve(stlink_t *sl, int port) {
                        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
@@ -749,13 +754,13 @@ int serve(stlink_t *sl, int port) {
                                        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
@@ -763,7 +768,7 @@ int serve(stlink_t *sl, int port) {
                                // 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;
@@ -919,7 +924,7 @@ int serve(stlink_t *sl, int port) {
                                                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];
                        }
@@ -935,7 +940,7 @@ int serve(stlink_t *sl, int port) {
                        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;
diff --git a/mingw/mingw.c b/mingw/mingw.c
new file mode 100644 (file)
index 0000000..c394a16
--- /dev/null
@@ -0,0 +1,263 @@
+#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
+
+
diff --git a/mingw/mingw.h b/mingw/mingw.h
new file mode 100644 (file)
index 0000000..93b3702
--- /dev/null
@@ -0,0 +1,61 @@
+#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