mingw: make simavr compilable with MinGW
authorStephan Veigl <veigl@gmx.net>
Fri, 30 Nov 2012 12:31:54 +0000 (13:31 +0100)
committerStephan Veigl <veigl@gmx.net>
Sun, 2 Dec 2012 12:49:00 +0000 (13:49 +0100)
- patch makefiles to work with MinGW
- compile to run_avr.exe on windows, otherwise run_avr cannot be started from the normal windows command prompt
- add sim_network.h to encapsulate the network functions of different platforms
    (use winsock2 for Windows network functions)
- make network helper functions static
- force open() to use binary mode (on Windows default is text mode)
- do not change stderr on Windows
- exclude simduino example on Windows
- add MinGW README

Signed-off-by: Stephan Veigl <veigl@gmx.net>
14 files changed:
Makefile.common
README.mingw [new file with mode: 0644]
examples/Makefile
examples/Makefile.opengl
examples/parts/uart_pty.c
examples/parts/uart_udp.c
examples/parts/uart_udp.h
simavr/.gitignore
simavr/Makefile
simavr/sim/sim_elf.c
simavr/sim/sim_gdb.c
simavr/sim/sim_network.h [new file with mode: 0644]
simavr/sim/sim_vcd_file.c
tests/tests.c

index 813901f..205ef6b 100644 (file)
@@ -58,8 +58,18 @@ else
 AVR_ROOT       := /usr/lib/avr
 AVR_INC        := ${AVR_ROOT}
 AVR            := avr-
 AVR_ROOT       := /usr/lib/avr
 AVR_INC        := ${AVR_ROOT}
 AVR            := avr-
+ifeq (${shell uname -o}, Msys)
+AVR_ROOT    := ${shell echo "${AVR32_HOME}" | tr '\\' '/'}
+AVR_INC     := ${AVR_ROOT}/avr
+AVR         := ${AVR_ROOT}/bin/avr-
+IPATH       += ${PREFIX}/include
+CFLAGS      += -I${PREFIX}/include
+LDFLAGS                += -L/lib -L/local/lib
+CFLAGS                 += -DNO_COLOR
+else
 CFLAGS                 += -fPIC
 endif
 CFLAGS                 += -fPIC
 endif
+endif
 
 CPPFLAGS       += --std=gnu99 -Wall
 CPPFLAGS       += ${patsubst %,-I%,${subst :, ,${IPATH}}}
 
 CPPFLAGS       += --std=gnu99 -Wall
 CPPFLAGS       += ${patsubst %,-I%,${subst :, ,${IPATH}}}
@@ -79,6 +89,10 @@ LDFLAGS      += -L${LIBDIR} -lsimavr
 
 LDFLAGS        += -lelf 
 
 
 LDFLAGS        += -lelf 
 
+ifeq (${shell uname -o}, Msys)
+LDFLAGS      += -lws2_32
+endif
+
 ifeq (${shell uname}, Linux)
 ifeq ($(RELEASE),1)
 # allow the shared library to be found in the build directory
 ifeq (${shell uname}, Linux)
 ifeq ($(RELEASE),1)
 # allow the shared library to be found in the build directory
diff --git a/README.mingw b/README.mingw
new file mode 100644 (file)
index 0000000..012c2f7
--- /dev/null
@@ -0,0 +1,78 @@
+ENVIRONMENT
+===========
+
+Microsoft SDK
+-------------
+Make sure that you have installed the ws2_32.lib, which is part of the Microsoft SDK.
+
+MinGW
+-----
+http://www.mingw.org/
+goto Downloads
+download and install mingw_get_inst-?????
+Select
+       C Compiler
+       C++ Compiler
+       MSYS Basic System
+
+Set the MINGW_HOME environment variable.
+Add %MINGW_HOME%\msys\1.0\bin;%MINGW_HOME%\bin; to your PATH
+Open a command shell and make sure that gcc is working: gcc \96v
+
+LibELF
+------
+Build and install libelf with mingw, or download the pre-compiled patch and copy it into your mingw root folder.
+https://gitorious.org/mingw-libs-for-simavr/mingw-libs-for-simavr/trees/master
+
+FreeGLUT
+--------
+Build and install freeglut with mingw, or download the pre-compiled patch and copy it into your mingw root folder.
+https://gitorious.org/mingw-libs-for-simavr/mingw-libs-for-simavr/trees/master
+
+
+WinAVR
+-----------
+If you have not already, download and install WinAVR.
+http://winavr.sourceforge.net/
+(This tutorial assumes you are using WinAVR-20100110.)
+Make sure that AVR32_HOME is set correctly and pointing do your WinAVR installation directory.
+%AVR32_HOME%\bin\gcc \96v
+In the output you see that the target is avr, while the target of the host gcc is mingw32.
+
+
+INSTALL simavr
+===============
+
+get simavr Sources
+-------------------
+Download the patched simavr sources of the mingw branch from:
+       https://github.com/the-real-orca/simavr/tree/mingw
+       and extract the sources to your development directory
+- or - clone the GIT repository
+       https://github.com/the-real-orca/simavr.git 
+       and switch to the mingw branch
+
+
+compile simavr
+---------------
+
+Open a command window and change to your simavr directory:
+      make all
+- or -
+      make \96r all      (this is a bit faster)
+
+TEST
+====
+
+make \96C tests run_tests
+
+
+INSTALL
+=======
+
+make install DESTDIR=C:\path-to-your-development-directory
+
+It will create the following sub-directories and put the according simavr files into them.
+ - bin
+ - lib
+ - include
index 3fd6771..65cc893 100644 (file)
@@ -1,6 +1,11 @@
 
 boards_base=${wildcard board_*}
 
 boards_base=${wildcard board_*}
+# Remove simduino until FileMapping is implemented to work around missing mmap in Win32
+ifeq (${shell uname -o}, Msys)
+boards=${subst board_usb,,${subst board_simduino,,$(boards_base)}}
+else
 boards=$(boards_base)
 boards=$(boards_base)
+endif
 
 all:
        for bi in ${boards}; do $(MAKE) -C $$bi; done
 
 all:
        for bi in ${boards}; do $(MAKE) -C $$bi; done
index 5d30b80..158be54 100644 (file)
@@ -8,10 +8,14 @@ ifeq  (${UNAME}, Linux)
 CPPFLAGS       += ${shell pkg-config --cflags glu}
 LDFLAGS        += ${shell pkg-config --libs glu} -lglut
 else
 CPPFLAGS       += ${shell pkg-config --cflags glu}
 LDFLAGS        += ${shell pkg-config --libs glu} -lglut
 else
+ifeq (${shell uname -o}, Msys)
+LDFLAGS        += -mwindows -lopengl32 -lfreeglut
+else
 CPPFLAGS       += ${shell pkg-config --cflags glu glut} -DFREEBSD=1
 LDFLAGS        += ${shell pkg-config --libs glu glut}
 endif
 endif
 CPPFLAGS       += ${shell pkg-config --cflags glu glut} -DFREEBSD=1
 LDFLAGS        += ${shell pkg-config --libs glu glut}
 endif
 endif
+endif
 
 ifeq  (${UNAME}, FreeBSD)
 CPPFLAGS       += -DFREEBSD=1 -DNO_ALLOCA=1
 
 ifeq  (${UNAME}, FreeBSD)
 CPPFLAGS       += -DFREEBSD=1 -DNO_ALLOCA=1
index ff95942..cbdedbc 100644 (file)
@@ -19,7 +19,7 @@
        along with simavr.  If not, see <http://www.gnu.org/licenses/>.
  */
 
        along with simavr.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <sys/select.h>
+#include "sim_network.h"
 #include <stdlib.h>
 #include <pthread.h>
 #include <string.h>
 #include <stdlib.h>
 #include <pthread.h>
 #include <string.h>
index 4a99803..d3ad0db 100644 (file)
        along with simavr.  If not, see <http://www.gnu.org/licenses/>.
  */
 
        along with simavr.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <sys/time.h>
 #include <pthread.h>
 #include <string.h>
 #include <stdio.h>
 #include <pthread.h>
 #include <string.h>
 #include <stdio.h>
index 10b06fe..ee99505 100644 (file)
@@ -23,7 +23,7 @@
 #ifndef __UART_UDP_H___
 #define __UART_UDP_H___
 
 #ifndef __UART_UDP_H___
 #define __UART_UDP_H___
 
-#include <netinet/in.h>
+#include "sim_network.h"
 #include "sim_irq.h"
 #include "fifo_declare.h"
 
 #include "sim_irq.h"
 #include "fifo_declare.h"
 
index aba978b..2d16800 100644 (file)
@@ -1,2 +1,3 @@
 sim_core_decl.h
 sim_core_config.h
 sim_core_decl.h
 sim_core_config.h
+/run_avr.exe
index d805820..bfac68f 100644 (file)
@@ -79,10 +79,14 @@ endif
 ${OBJ}/${target}.elf   : ${OBJ}/${target}.o
 
 ${target}      : ${OBJ}/${target}.elf
 ${OBJ}/${target}.elf   : ${OBJ}/${target}.o
 
 ${target}      : ${OBJ}/${target}.elf
+ifeq (${shell uname -o}, Msys)
+       ln -sf $< $@.exe
+else
        ln -sf $< $@
        ln -sf $< $@
+endif
  
 clean: clean-${OBJ}
  
 clean: clean-${OBJ}
-       rm -rf ${target} *.a *.so
+       rm -rf ${target} *.a *.so *.exe
        rm -f sim_core_*.h
 
 DESTDIR = /usr/local
        rm -f sim_core_*.h
 
 DESTDIR = /usr/local
index fee7cb8..90afccf 100644 (file)
 #include "sim_vcd_file.h"
 #include "avr_eeprom.h"
 
 #include "sim_vcd_file.h"
 #include "avr_eeprom.h"
 
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
 void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware)
 {
        if (firmware->frequency)
 void avr_load_firmware(avr_t * avr, elf_firmware_t * firmware)
 {
        if (firmware->frequency)
@@ -175,7 +179,7 @@ int elf_read_firmware(const char * file, elf_firmware_t * firmware)
        Elf *elf = NULL;                       /* Our Elf pointer for libelf */
        int fd; // File Descriptor
 
        Elf *elf = NULL;                       /* Our Elf pointer for libelf */
        int fd; // File Descriptor
 
-       if ((fd = open(file, O_RDONLY)) == -1 ||
+       if ((fd = open(file, O_RDONLY | O_BINARY)) == -1 ||
                        (read(fd, &elf_header, sizeof(elf_header))) < sizeof(elf_header)) {
                printf("could not read %s\n", file);
                perror(file);
                        (read(fd, &elf_header, sizeof(elf_header))) < sizeof(elf_header)) {
                printf("could not read %s\n", file);
                perror(file);
@@ -280,16 +284,18 @@ int elf_read_firmware(const char * file, elf_firmware_t * firmware)
                        (data_text ? data_text->d_size : 0) +
                        (data_data ? data_data->d_size : 0);
        firmware->flash = malloc(firmware->flashsize);
                        (data_text ? data_text->d_size : 0) +
                        (data_data ? data_data->d_size : 0);
        firmware->flash = malloc(firmware->flashsize);
+       
+       // using unsigned int for output, since there is no AVR with 4GB
        if (data_text) {
        //      hdump("code", data_text->d_buf, data_text->d_size);
                memcpy(firmware->flash + offset, data_text->d_buf, data_text->d_size);
                offset += data_text->d_size;
        if (data_text) {
        //      hdump("code", data_text->d_buf, data_text->d_size);
                memcpy(firmware->flash + offset, data_text->d_buf, data_text->d_size);
                offset += data_text->d_size;
-               printf("Loaded %zu .text\n", data_text->d_size);
+               printf("Loaded %u .text\n", (unsigned int)data_text->d_size);
        }
        if (data_data) {
        //      hdump("data", data_data->d_buf, data_data->d_size);
                memcpy(firmware->flash + offset, data_data->d_buf, data_data->d_size);
        }
        if (data_data) {
        //      hdump("data", data_data->d_buf, data_data->d_size);
                memcpy(firmware->flash + offset, data_data->d_buf, data_data->d_size);
-               printf("Loaded %zu .data\n", data_data->d_size);
+               printf("Loaded %u .data\n", (unsigned int)data_data->d_size);
                offset += data_data->d_size;
                firmware->datasize = data_data->d_size;
        }
                offset += data_data->d_size;
                firmware->datasize = data_data->d_size;
        }
@@ -297,7 +303,7 @@ int elf_read_firmware(const char * file, elf_firmware_t * firmware)
        //      hdump("eeprom", data_ee->d_buf, data_ee->d_size);
                firmware->eeprom = malloc(data_ee->d_size);
                memcpy(firmware->eeprom, data_ee->d_buf, data_ee->d_size);
        //      hdump("eeprom", data_ee->d_buf, data_ee->d_size);
                firmware->eeprom = malloc(data_ee->d_size);
                memcpy(firmware->eeprom, data_ee->d_buf, data_ee->d_size);
-               printf("Loaded %zu .eeprom\n", data_ee->d_size);
+               printf("Loaded %u .eeprom\n", (unsigned int)data_ee->d_size);
                firmware->eesize = data_ee->d_size;
        }
 //     hdump("flash", avr->flash, offset);
                firmware->eesize = data_ee->d_size;
        }
 //     hdump("flash", avr->flash, offset);
index faa016f..7ddfb60 100644 (file)
        along with simavr.  If not, see <http://www.gnu.org/licenses/>.
  */
 
        along with simavr.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
+#include "sim_network.h"
 #include <sys/time.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
 #include <sys/time.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
-#include <poll.h>
 #include <pthread.h>
 #include "sim_avr.h"
 #include "sim_core.h" // for SET_SREG_FROM, READ_SREG_INTO
 #include <pthread.h>
 #include "sim_avr.h"
 #include "sim_core.h" // for SET_SREG_FROM, READ_SREG_INTO
@@ -536,13 +532,18 @@ int avr_gdb_init(avr_t * avr)
 
        avr->gdb = NULL;
 
 
        avr->gdb = NULL;
 
+       if ( network_init() ) {
+               AVR_LOG(avr, LOG_ERROR, "GDB: Can't initialize network");
+               return -1;
+       }
+       
        if ((g->listen = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
                AVR_LOG(avr, LOG_ERROR, "GDB: Can't create socket: %s", strerror(errno));
                return -1;
        }
 
        if ((g->listen = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
                AVR_LOG(avr, LOG_ERROR, "GDB: Can't create socket: %s", strerror(errno));
                return -1;
        }
 
-       int i = 1;
-       setsockopt(g->listen, SOL_SOCKET, SO_REUSEADDR, &i, sizeof(i));
+       int optval = 1;
+       setsockopt(g->listen, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval));
 
        struct sockaddr_in address = { 0 };
        address.sin_family = AF_INET;
 
        struct sockaddr_in address = { 0 };
        address.sin_family = AF_INET;
@@ -574,4 +575,6 @@ void avr_deinit_gdb(avr_t * avr)
        if (avr->gdb->s != -1)
           close(avr->gdb->s);
        free(avr->gdb);
        if (avr->gdb->s != -1)
           close(avr->gdb->s);
        free(avr->gdb);
+
+       network_release();
 }
 }
diff --git a/simavr/sim/sim_network.h b/simavr/sim/sim_network.h
new file mode 100644 (file)
index 0000000..a43e1d8
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+       sim_network.h
+
+       Copyright 2012 Stephan Veigl <veigl@gmx.net>
+
+       This file is part of simavr.
+
+       simavr is free software: you can redistribute it and/or modify
+       it under the terms of the GNU General Public License as published by
+       the Free Software Foundation, either version 3 of the License, or
+       (at your option) any later version.
+
+       simavr is distributed in the hope that it will be useful,
+       but WITHOUT ANY WARRANTY; without even the implied warranty of
+       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+       GNU General Public License for more details.
+
+       You should have received a copy of the GNU General Public License
+       along with simavr.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __SIM_NETWORK_H__
+#define __SIM_NETWORK_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __MINGW32__
+
+// Windows with MinGW
+
+#include <windows.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+
+#define send(sockfd, buf, len, flags) \
+       (ssize_t)send( (sockfd), (const char *)(buf), (len), (flags))
+#define setsockopt(sockfd, level, optname, optval, optlen) \
+       setsockopt( (sockfd), (level), (optname), (void *)(optval), (optlen))
+#define recv(sockfd, buf, len, flags) \
+       (ssize_t)recv( (sockfd), (char *)(buf), (len), (flags))
+#define sleep(x) Sleep((x)*1000)
+
+static inline int network_init()
+{
+       // Windows requires WinSock to be init before use
+       WSADATA wsaData;
+       if ( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) )
+               return -1;
+
+       return 0;
+}
+
+static inline void network_release()
+{
+       // close WinSock
+       WSACleanup();
+}
+
+#else
+
+// native Linux
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <poll.h>
+
+static inline int network_init()
+{
+       // nothing to do
+       return 0;
+}
+
+static inline void network_release()
+{
+       // nothing to do
+}
+
+#endif
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif /*__SIM_NETWORK_H__*/
index 8d87f87..c6ce06c 100644 (file)
@@ -25,6 +25,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 #include <stdlib.h>
+#include<inttypes.h>
 #include "sim_vcd_file.h"
 #include "sim_avr.h"
 #include "sim_time.h"
 #include "sim_vcd_file.h"
 #include "sim_avr.h"
 #include "sim_time.h"
@@ -129,7 +130,7 @@ static void avr_vcd_flush_log(avr_vcd_t * vcd)
                        
                if (base > oldbase || li == 0) {
                        seen = 0;
                        
                if (base > oldbase || li == 0) {
                        seen = 0;
-                       fprintf(vcd->output, "#%llu\n", (long long unsigned int)base);
+                       fprintf(vcd->output, "#%" PRIu64  "\n", base);
                        oldbase = base;
                }
                seen |= (1 << l->signal->irq.irq);      // mark this trace as seen for this timestamp
                        oldbase = base;
                }
                seen |= (1 << l->signal->irq.irq);      // mark this trace as seen for this timestamp
index d502fde..3b94cab 100644 (file)
@@ -14,17 +14,28 @@ avr_cycle_count_t tests_cycle_count = 0;
 int tests_disable_stdout = 1;
 
 static char *test_name = "(uninitialized test)";
 int tests_disable_stdout = 1;
 
 static char *test_name = "(uninitialized test)";
-static FILE *orig_stderr = NULL;
 static int finished = 0;
 
 static int finished = 0;
 
+#ifdef __MINGW32__
+#define restore_stderr()       {}
+#define map_stderr()           {}
+#else
+static FILE *orig_stderr = NULL;
+#define restore_stderr()       { if (orig_stderr) stderr = orig_stderr; }
+#define map_stderr()           { if (tests_disable_stdout) { \
+                                                               orig_stderr = stderr;   \
+                                                               fclose(stdout);                 \
+                                                               stderr = stdout;                \
+                                                       } }
+#endif
+               
 static void atexit_handler(void) {
        if (!finished)
                _fail(NULL, 0, "Test exit without indicating success.");
 }
 
 void tests_success(void) {
 static void atexit_handler(void) {
        if (!finished)
                _fail(NULL, 0, "Test exit without indicating success.");
 }
 
 void tests_success(void) {
-       if (orig_stderr)
-               stderr = orig_stderr;
+       restore_stderr();
        fprintf(stderr, "OK: %s\n", test_name);
        finished = 1;
 }
        fprintf(stderr, "OK: %s\n", test_name);
        finished = 1;
 }
@@ -96,11 +107,8 @@ static int my_avr_run(avr_t * avr)
 
 avr_t *tests_init_avr(const char *elfname) {
        tests_cycle_count = 0;
 
 avr_t *tests_init_avr(const char *elfname) {
        tests_cycle_count = 0;
-       if (tests_disable_stdout) {
-               orig_stderr = stderr;
-               fclose(stdout);
-               stderr = stdout;
-       }
+       map_stderr();
+       
        elf_firmware_t fw;
        if (elf_read_firmware(elfname, &fw))
                fail("Failed to read ELF firmware \"%s\"", elfname);
        elf_firmware_t fw;
        if (elf_read_firmware(elfname, &fw))
                fail("Failed to read ELF firmware \"%s\"", elfname);
@@ -229,8 +237,7 @@ void tests_assert_cycles_between(unsigned long min, unsigned long max) {
 }
 
 void _fail(const char *filename, int linenum, const char *fmt, ...) {
 }
 
 void _fail(const char *filename, int linenum, const char *fmt, ...) {
-       if (orig_stderr)
-               stderr = orig_stderr;
+       restore_stderr();
 
        if (filename)
                fprintf(stderr, "%s:%d: ", filename, linenum);
 
        if (filename)
                fprintf(stderr, "%s:%d: ", filename, linenum);