summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorroot <root@lab.panaceas.james.local>2018-04-08 01:14:30 +0100
committerroot <root@lab.panaceas.james.local>2018-04-08 01:14:30 +0100
commit25e6afd831b94b9735cc6691ee19c8edc921aca7 (patch)
treecc194e7cb067c929b3e8bc9c03552d2d300c301b
downloadclock-25e6afd831b94b9735cc6691ee19c8edc921aca7.tar.gz
clock-25e6afd831b94b9735cc6691ee19c8edc921aca7.tar.bz2
clock-25e6afd831b94b9735cc6691ee19c8edc921aca7.zip
working decoding
-rw-r--r--.gitignore7
-rw-r--r--.gitmodules6
-rw-r--r--Makefile.include48
-rw-r--r--Makefile.rules242
-rw-r--r--app/Makefile96
-rw-r--r--app/abs.c41
-rw-r--r--app/gdb.script2
-rw-r--r--app/led.c38
-rw-r--r--app/lwip/lwip-1.4.1/src/core/ipv4/.dummy0
-rw-r--r--app/lwip/lwip-1.4.1/src/netif/.dummy0
-rw-r--r--app/lwip/lwipopts.h202
-rw-r--r--app/lwip_glue.c402
-rw-r--r--app/main.c55
-rw-r--r--app/msf.c226
-rw-r--r--app/ntp.c79
-rw-r--r--app/pins.h46
-rw-r--r--app/pll.c123
-rw-r--r--app/project.h43
-rw-r--r--app/prototypes.h64
-rw-r--r--app/ring.c77
-rw-r--r--app/ring.h6
-rw-r--r--app/stdio.c81
-rw-r--r--app/steth.c366
-rw-r--r--app/ticker.c79
-rw-r--r--app/time_fn.c225
-rw-r--r--app/time_fn.h19
-rw-r--r--app/usart.c100
-rw-r--r--arch_max.ld12
m---------libopencm30
-rw-r--r--libopencm3-local/libopencm3/ethernet/mac/stm32fxx7.h1
m---------lwip/lwip-1.4.10
-rw-r--r--lwip/lwip-local/port/stm32f4x7/arch/bpstruct.h36
-rw-r--r--lwip/lwip-local/port/stm32f4x7/arch/cc.h64
-rw-r--r--lwip/lwip-local/port/stm32f4x7/arch/cpu.h37
-rw-r--r--lwip/lwip-local/port/stm32f4x7/arch/epstruct.h36
-rw-r--r--lwip/lwip-local/port/stm32f4x7/arch/init.h44
-rw-r--r--lwip/lwip-local/port/stm32f4x7/arch/lib.h38
-rw-r--r--lwip/lwip-local/port/stm32f4x7/arch/perf.h38
-rw-r--r--lwip/lwip-local/port/stm32f4x7/arch/sys_arch.h66
-rw-r--r--lwip/lwip-local/port/stm32f4x7/ethernetif.h11
-rw-r--r--oocd/board/arch_max.cfg4
-rw-r--r--oocd/interface/cmsis-dap.cfg6
-rw-r--r--oocd/interface/j-link.cfg5
-rw-r--r--oocd/interface/stlink-v2.cfg11
-rw-r--r--oocd/stm32-f407.cfg6
45 files changed, 3088 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..09e26f4
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,7 @@
+*.d
+*.o
+*.elf
+*.orig
+*.hex
+*.map
+.*.swp
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..a8ff31b
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,6 @@
+[submodule "libopencm3"]
+ path = libopencm3
+ url = ssh://git@git.panaceas.org/git/stm32/libopencm3
+[submodule "lwip/lwip-1.4.1"]
+ path = lwip/lwip-1.4.1
+ url = ssh://git@git.panaceas.org/git/stm32/lwip-1.4.1.git
diff --git a/Makefile.include b/Makefile.include
new file mode 100644
index 0000000..1288fe0
--- /dev/null
+++ b/Makefile.include
@@ -0,0 +1,48 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+## Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
+## Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
+##
+## This library is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This library 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 Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with this library. If not, see <http://www.gnu.org/licenses/>.
+##
+
+LIBNAME = opencm3_stm32f4
+DEFS = -DSTM32F4
+
+FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16
+ARCH_FLAGS = -mthumb -mcpu=cortex-m4 $(FP_FLAGS)
+
+################################################################################
+# OpenOCD specific variables
+
+OOCD ?= openocd
+OOCD_INTERFACE ?= cmsis-dap
+OOCD_BOARD ?= arch_max
+
+################################################################################
+# Black Magic Probe specific variables
+# Set the BMP_PORT to a serial port and then BMP is used for flashing
+BMP_PORT ?=
+
+################################################################################
+# texane/stlink specific variables
+#STLINK_PORT ?= :4242
+
+
+include ../Makefile.rules
+
+
+
diff --git a/Makefile.rules b/Makefile.rules
new file mode 100644
index 0000000..fe31837
--- /dev/null
+++ b/Makefile.rules
@@ -0,0 +1,242 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+## Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
+## Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
+##
+## This library is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This library 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 Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with this library. If not, see <http://www.gnu.org/licenses/>.
+##
+
+# Be silent per default, but 'make V=1' will show all compiler calls.
+ifneq ($(V),1)
+Q := @
+NULL := 2>/dev/null
+endif
+
+###############################################################################
+# Executables
+
+PREFIX ?= arm-none-eabi
+
+CC := $(PREFIX)-gcc
+CXX := $(PREFIX)-g++
+LD := $(PREFIX)-gcc
+AR := $(PREFIX)-ar
+AS := $(PREFIX)-as
+OBJCOPY := $(PREFIX)-objcopy
+OBJDUMP := $(PREFIX)-objdump
+GDB := $(PREFIX)-gdb
+STFLASH = $(shell which st-flash)
+STYLECHECK := /checkpatch.pl
+STYLECHECKFLAGS := --no-tree -f --terse --mailback
+STYLECHECKFILES := $(shell find . -name '*.[ch]')
+
+
+###############################################################################
+# Source files
+
+LDSCRIPT ?= $(BINARY).ld
+
+#OBJS += $(BINARY).o
+
+
+ifeq ($(strip $(OPENCM3_DIR)),)
+# user has not specified the library path, so we try to detect it
+
+# where we search for the library
+LIBPATHS := ../libopencm3
+
+OPENCM3_DIR := $(wildcard $(LIBPATHS:=/locm3.sublime-project))
+OPENCM3_DIR := $(firstword $(dir $(OPENCM3_DIR)))
+
+ifeq ($(strip $(OPENCM3_DIR)),)
+$(warning Cannot find libopencm3 library in the standard search paths.)
+$(error Please specify it through OPENCM3_DIR variable!)
+endif
+endif
+
+ifeq ($(V),1)
+$(info Using $(OPENCM3_DIR) path to library)
+endif
+
+INCLUDE_DIR = $(OPENCM3_DIR)/include
+LIB_DIR = $(OPENCM3_DIR)/lib
+SCRIPT_DIR = $(OPENCM3_DIR)/scripts
+
+###############################################################################
+# C flags
+
+#CFLAGS += -Os -g
+CFLAGS += -g
+CFLAGS += -Wextra -Wshadow -Wimplicit-function-declaration
+CFLAGS += -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes
+CFLAGS += -fno-common -ffunction-sections -fdata-sections
+
+###############################################################################
+# C++ flags
+
+CXXFLAGS += -Os -g
+CXXFLAGS += -Wextra -Wshadow -Wredundant-decls -Weffc++
+CXXFLAGS += -fno-common -ffunction-sections -fdata-sections
+
+###############################################################################
+# C & C++ preprocessor common flags
+
+CPPFLAGS += -MD
+CPPFLAGS += -Wall -Wundef
+CPPFLAGS += -I$(INCLUDE_DIR) $(DEFS)
+
+###############################################################################
+# Linker flags
+
+LDFLAGS += --static -nostartfiles
+LDFLAGS += -L$(LIB_DIR) -L/usr/arm-none-eabi/lib/armv7e-m/fpu
+LDFLAGS += -T$(LDSCRIPT)
+LDFLAGS += -Wl,-Map=$(*).map
+LDFLAGS += -Wl,--gc-sections
+ifeq ($(V),99)
+LDFLAGS += -Wl,--print-gc-sections
+endif
+
+###############################################################################
+# Used libraries
+
+LDLIBS += -l$(LIBNAME)
+LDLIBS += -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
+
+###############################################################################
+###############################################################################
+###############################################################################
+
+.SUFFIXES: .elf .bin .hex .srec .list .map .images
+.SECONDEXPANSION:
+.SECONDARY:
+
+all: elf
+
+elf: $(BINARY).elf
+bin: $(BINARY).bin
+hex: $(BINARY).hex
+srec: $(BINARY).srec
+list: $(BINARY).list
+
+images: $(BINARY).images
+flash: $(BINARY).flash
+
+%.images: %.bin %.hex %.srec %.list %.map
+ @#printf "*** $* images generated ***\n"
+
+%.bin: %.elf
+ @#printf " OBJCOPY $(*).bin\n"
+ $(Q)$(OBJCOPY) -Obinary $(*).elf $(*).bin
+
+%.hex: %.elf
+ @#printf " OBJCOPY $(*).hex\n"
+ $(Q)$(OBJCOPY) -Oihex $(*).elf $(*).hex
+
+%.srec: %.elf
+ @#printf " OBJCOPY $(*).srec\n"
+ $(Q)$(OBJCOPY) -Osrec $(*).elf $(*).srec
+
+%.list: %.elf
+ @#printf " OBJDUMP $(*).list\n"
+ $(Q)$(OBJDUMP) -S $(*).elf > $(*).list
+
+%.elf %.map: $(OBJS) $(LDSCRIPT) $(LIB_DIR)/lib$(LIBNAME).a
+ @#printf " LD $(*).elf\n"
+ $(Q)$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(*).elf
+
+%.o: %.c
+ @mkdir -p $(dir $@)
+ @#printf " CC $(<)\n"
+ $(Q)$(CC) $(CFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(<)
+
+%.o: %.cxx
+ @#printf " CXX $(*).cxx\n"
+ $(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).cxx
+
+%.o: %.cpp
+ @#printf " CXX $(*).cpp\n"
+ $(Q)$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(ARCH_FLAGS) -o $(*).o -c $(*).cpp
+
+clean:
+ @#printf " CLEAN\n"
+ $(Q)$(RM) *.o *.d *.elf *.bin *.hex *.srec *.list *.map
+ $(Q)$(RM) -rf $(EXTRA_CLEAN)
+
+stylecheck: $(STYLECHECKFILES:=.stylecheck)
+styleclean: $(STYLECHECKFILES:=.styleclean)
+
+# the cat is due to multithreaded nature - we like to have consistent chunks of text on the output
+%.stylecheck: %
+ $(Q)$(SCRIPT_DIR)$(STYLECHECK) $(STYLECHECKFLAGS) $* > $*.stylecheck; \
+ if [ -s $*.stylecheck ]; then \
+ cat $*.stylecheck; \
+ else \
+ rm -f $*.stylecheck; \
+ fi;
+
+%.styleclean:
+ $(Q)rm -f $*.stylecheck;
+
+
+%.stlink-flash: %.bin
+ @printf " FLASH $<\n"
+ $(Q)$(STFLASH) write $(*).bin 0x8000000
+
+ifeq ($(STLINK_PORT),)
+ifeq ($(BMP_PORT),)
+ifeq ($(OOCD_SERIAL),)
+%.flash: %.hex
+ @printf " FLASH $<\n"
+ @# IMPORTANT: Don't use "resume", only "reset" will work correctly!
+ $(Q)$(OOCD) -f ../oocd/interface/$(OOCD_INTERFACE).cfg \
+ -f ../oocd/board/$(OOCD_BOARD).cfg \
+ -c "init" -c "reset init" \
+ -c "flash write_image erase $(*).hex" \
+ -c "reset" \
+ -c "shutdown" $(NULL)
+else
+%.flash: %.hex
+ @printf " FLASH $<\n"
+ @# IMPORTANT: Don't use "resume", only "reset" will work correctly!
+ $(Q)$(OOCD) -f ../oocd/interface/$(OOCD_INTERFACE).cfg \
+ -f ../oocd/board/$(OOCD_BOARD).cfg \
+ -c "ft2232_serial $(OOCD_SERIAL)" \
+ -c "init" -c "reset init" \
+ -c "flash write_image erase $(*).hex" \
+ -c "reset" \
+ -c "shutdown" $(NULL)
+endif
+else
+%.flash: %.elf
+ @printf " GDB $(*).elf (flash)\n"
+ $(Q)$(GDB) --batch \
+ -ex 'target extended-remote $(BMP_PORT)' \
+ -x $(SCRIPT_DIR)/black_magic_probe_flash.scr \
+ $(*).elf
+endif
+else
+%.flash: %.elf
+ @printf " GDB $(*).elf (flash)\n"
+ $(Q)$(GDB) --batch \
+ -ex 'target extended-remote $(STLINK_PORT)' \
+ -x $(SCRIPT_DIR)/stlink_flash.scr \
+ $(*).elf
+endif
+
+.PHONY: images clean stylecheck styleclean elf bin hex srec list
+
+-include $(OBJS:.o=.d)
diff --git a/app/Makefile b/app/Makefile
new file mode 100644
index 0000000..0d8d19d
--- /dev/null
+++ b/app/Makefile
@@ -0,0 +1,96 @@
+##
+## This file is part of the libopencm3 project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
+##
+## This library is free software: you can redistribute it and/or modify
+## it under the terms of the GNU Lesser General Public License as published by
+## the Free Software Foundation, either version 3 of the License, or
+## (at your option) any later version.
+##
+## This library 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 Lesser General Public License for more details.
+##
+## You should have received a copy of the GNU Lesser General Public License
+## along with this library. If not, see <http://www.gnu.org/licenses/>.
+##
+
+LDSCRIPT = ../arch_max.ld
+
+CPROTO=cproto
+PROG=msf
+
+V=1
+default: ${PROG}.elf
+
+CSRCS=led.c ticker.c ring.c usart.c stdio.c lwip_glue.c steth.c msf.c abs.c pll.c main.c time_fn.c ntp.c
+HSRCS=project.h ring.h pins.h
+
+LWIP=lwip/lwip-1.4.1
+LWIP_PATH=..
+
+VPATH=${LWIP_PATH}
+
+LWIP_API=#${LWIP}/src/api/err.c ${LWIP}/src/api/netdb.c ${LWIP}/src/api/api_msg.c ${LWIP}/src/api/tcpip.c ${LWIP}/src/api/sockets.c ${LWIP}/src/api/api_lib.c ${LWIP}/src/api/netbuf.c ${LWIP}/src/api/netifapi.c
+LWIP_CORE=${LWIP}/src/core/memp.c ${LWIP}/src/core/sys.c ${LWIP}/src/core/init.c ${LWIP}/src/core/pbuf.c ${LWIP}/src/core/dhcp.c ${LWIP}/src/core/ipv4/ip_addr.c ${LWIP}/src/core/ipv4/ip.c ${LWIP}/src/core/ipv4/ip_frag.c ${LWIP}/src/core/ipv4/inet.c ${LWIP}/src/core/ipv4/autoip.c ${LWIP}/src/core/ipv4/icmp.c ${LWIP}/src/core/ipv4/inet_chksum.c ${LWIP}/src/core/timers.c ${LWIP}/src/core/def.c ${LWIP}/src/core/netif.c ${LWIP}/src/netif/etharp.c ${LWIP}/src/core/raw.c ${LWIP}/src/core/mem.c ${LWIP}/src/core/udp.c
+
+DEFINES=#
+#${LWIP}/src/core/tcp.c ${LWIP}/src/core/tcp_out.c #${LWIP}/src/core/tcp_in.c
+
+# ${LWIP}/src/core/snmp/asn1_enc.c ${LWIP}/src/core/snmp/msg_in.c ${LWIP}/src/core/snmp/mib_structs.c ${LWIP}/src/core/snmp/mib2.c ${LWIP}/src/core/snmp/asn1_dec.c ${LWIP}/src/core/snmp/msg_out.c ${LWIP}/src/core/ipv6/icmp6.c ${LWIP}/src/core/ipv6/ip6.c ${LWIP}/src/core/ipv6/ip6_addr.c ${LWIP}/src/core/ipv6/inet6.c
+# ${LWIP}/src/core/dns.c ${LWIP}/src/core/stats.c ${LWIP}/src/core/ipv4/igmp.c
+
+
+LWIP_INC=${LWIP_PATH}/${LWIP}
+LWIP_LOCAL=${LWIP_PATH}/lwip/lwip-local
+
+
+LWIP_CSRCS=${LWIP_API} ${LWIP_CORE}
+EXTRA_CLEAN=${LWIP}
+
+
+BINARY = ${PROG}
+MYOBJS = ${CSRCS:%.c=%.o}
+LWIP_OBJS = ${LWIP_CSRCS:%.c=%.o}
+
+objs:${OBJS}
+
+${MYOBJS}: project.h prototypes.h
+${LWIP_OBJS}: lwip/lwipopts.h
+
+OBJS=${MYOBJS} ${LWIP_OBJS}
+
+include ../Makefile.include
+
+CFLAGS+=-Wno-redundant-decls -Wno-unused-parameter
+CPPFLAGS += -I../libopencm3-local -I${LWIP_PATH}/${LWIP}/src/include -Ilwip -I${LWIP_PATH}/${LWIP}/src/include/ipv4 -I${LWIP_LOCAL}/port/stm32f4x7 -I.
+
+fish: ${OBJS}
+ echo ${OBJS}
+
+program: ${PROG}.hex
+ echo init | nc -t localhost 4444
+ echo reset init | nc -t localhost 4444
+ echo flash write_image erase ${PWD}/$< | nc -t localhost 4444
+ echo reset run | nc -t localhost 4444
+
+ds:
+ $(Q)$(OOCD) -f ../oocd/interface/$(OOCD_INTERFACE).cfg \
+ -f ../oocd/board/$(OOCD_BOARD).cfg
+
+debug: ${PROG}.elf
+ ${PREFIX}-gdb -x gdb.script ${PROG}.elf
+
+# openocd
+
+protos: ${CSRCS}
+ echo -n > prototypes.h
+ ${CPROTO} -E "${CPP} $(CPPFLAGS)" -e -v ${CSRCS} > prototypes.h.tmp
+ mv -f prototypes.h.tmp prototypes.h
+
+EXTRA_CLEAN=${OBJS} ${LWIP_OBJS:%.o=%.d}
+
+tidy:
+ astyle -A3 -s2 --attach-extern-c -L -c -w -Y -m0 -f -p -H -U -k3 -xj -xd ${CSRCS} ${HSRCS}
diff --git a/app/abs.c b/app/abs.c
new file mode 100644
index 0000000..769da7a
--- /dev/null
+++ b/app/abs.c
@@ -0,0 +1,41 @@
+#include "project.h"
+
+
+static uint32_t high_tick;
+
+
+uint64_t abs_extend (uint32_t now)
+{
+ static uint32_t then;
+
+
+ uint64_t ret;
+
+
+ if (now < then)
+ high_tick++;
+
+ then = now;
+
+
+ ret = high_tick;
+ ret <<= 32;
+ ret |= now;
+
+ return ret;
+}
+
+
+
+
+uint64_t abs_get (void)
+{
+ uint32_t now = SCS_DWT_CYCCNT;
+ return abs_extend (now);
+}
+
+
+void abs_slow_tick()
+{
+ abs_get();
+}
diff --git a/app/gdb.script b/app/gdb.script
new file mode 100644
index 0000000..7cf9d09
--- /dev/null
+++ b/app/gdb.script
@@ -0,0 +1,2 @@
+target remote localhost:3333
+cont
diff --git a/app/led.c b/app/led.c
new file mode 100644
index 0000000..825bd0d
--- /dev/null
+++ b/app/led.c
@@ -0,0 +1,38 @@
+#include "project.h"
+
+#define LED (GPIO3)
+#define LED_PORT GPIOB
+
+
+void
+led_init (void)
+{
+
+ MAP_OUTPUT_PP (LED);
+}
+
+
+void
+led_clear (void)
+{
+ CLEAR (LED);
+}
+
+void
+led_set()
+{
+ gpio_set (LED_PORT, LED);
+}
+
+void
+led_slow_tick (void)
+{
+ static int c;
+
+ c = !c;
+
+ if (c)
+ led_set();
+ else
+ led_clear();
+}
diff --git a/app/lwip/lwip-1.4.1/src/core/ipv4/.dummy b/app/lwip/lwip-1.4.1/src/core/ipv4/.dummy
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/lwip/lwip-1.4.1/src/core/ipv4/.dummy
diff --git a/app/lwip/lwip-1.4.1/src/netif/.dummy b/app/lwip/lwip-1.4.1/src/netif/.dummy
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/lwip/lwip-1.4.1/src/netif/.dummy
diff --git a/app/lwip/lwipopts.h b/app/lwip/lwipopts.h
new file mode 100644
index 0000000..e535e59
--- /dev/null
+++ b/app/lwip/lwipopts.h
@@ -0,0 +1,202 @@
+/**
+ ******************************************************************************
+ * @file lwipopts.h
+ * @author MCD Application Team
+ * @version V1.0.0
+ * @date 31-October-2011
+ * @brief lwIP Options Configuration.
+ * This file is based on Utilities\lwip_v1.3.2\src\include\lwip\opt.h
+ * and contains the lwIP configuration for the STM32F4x7 demonstration.
+ ******************************************************************************
+ * @attention
+ *
+ * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+ * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+ * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+ * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+ * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ *
+ * <h2><center>&copy; COPYRIGHT 2011 STMicroelectronics</center></h2>
+ ******************************************************************************
+ */
+
+#ifndef __LWIPOPTS_H__
+#define __LWIPOPTS_H__
+
+
+#include <stdio.h>
+
+#define MTU 1500
+
+#if 0
+#define ICMP_DEBUG LWIP_DBG_ON
+#define UDP_DEBUG LWIP_DBG_ON
+#define IP_DEBUG LWIP_DBG_ON
+#define ETHARP_DEBUG LWIP_DBG_ON
+#define LWIP_DBG_TYPES_ON (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT)
+#define LWIP_DEBUG 1
+#define LWIP_PLATFORM_DIAG(a) printf a
+#endif
+
+
+/**
+ * SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
+ * critical regions during buffer allocation, deallocation and memory
+ * allocation and deallocation.
+ */
+#define SYS_LIGHTWEIGHT_PROT 0
+
+/**
+ * NO_SYS==1: Provides VERY minimal functionality. Otherwise,
+ * use lwIP facilities.
+ */
+#define NO_SYS 1
+
+/* ---------- Memory options ---------- */
+/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
+ lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
+ byte alignment -> define MEM_ALIGNMENT to 2. */
+#define MEM_ALIGNMENT 4
+
+/* MEM_SIZE: the size of the heap memory. If the application will send
+a lot of data that needs to be copied, this should be set high. */
+#define MEM_SIZE (10*1024)
+
+/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
+ sends a lot of data out of ROM (or other static memory), this
+ should be set high. */
+#define MEMP_NUM_PBUF 100
+/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
+ per active UDP "connection". */
+#define MEMP_NUM_UDP_PCB 6
+/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
+ connections. */
+
+#define PBUF_POOL_FREE_OOSEQ 0
+
+#define MEMP_NUM_TCP_PCB 10
+/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
+ connections. */
+#define MEMP_NUM_TCP_PCB_LISTEN 6
+/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
+ segments. */
+#define MEMP_NUM_TCP_SEG 12
+/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
+ timeouts. */
+#define MEMP_NUM_SYS_TIMEOUT 3
+
+
+#define PBUF_POOL_FREE_OOSEQ 0
+
+/* ---------- Pbuf options ---------- */
+/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
+#define PBUF_POOL_SIZE 20
+
+/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
+#define PBUF_POOL_BUFSIZE ((MTU)+8)
+
+
+/* ---------- TCP options ---------- */
+#define LWIP_TCP 0
+#define TCP_TTL 255
+
+/* Controls if TCP should queue segments that arrive out of
+ order. Define to 0 if your device is low on memory. */
+#define TCP_QUEUE_OOSEQ 0
+
+/* TCP Maximum segment size. */
+#define TCP_MSS (MTU - 40) /* TCP_MSS = (Ethernet MTU - IP header size - TCP header size) */
+
+/* TCP sender buffer space (bytes). */
+#define TCP_SND_BUF (2*TCP_MSS)
+
+/* TCP_SND_QUEUELEN: TCP sender buffer space (pbufs). This must be at least
+ as much as (2 * TCP_SND_BUF/TCP_MSS) for things to work. */
+
+#define TCP_SND_QUEUELEN (2* TCP_SND_BUF/TCP_MSS)
+
+/* TCP receive window. */
+#define TCP_WND (2*TCP_MSS)
+
+
+/* ---------- ICMP options ---------- */
+#define LWIP_ICMP 1
+
+
+/* ---------- DHCP options ---------- */
+/* Define LWIP_DHCP to 1 if you want DHCP configuration of
+ interfaces. DHCP is not implemented in lwIP 0.5.1, however, so
+ turning this on does currently not work. */
+#define LWIP_DHCP 0
+#define LWIP_AUTOIP 0
+
+
+/* ---------- UDP options ---------- */
+#define LWIP_UDP 1
+#define UDP_TTL 255
+
+
+/* ---------- Statistics options ---------- */
+#define LWIP_STATS 0
+#undef LWIP_PROVIDE_ERRNO
+#define ETHARP_STATS 0
+
+
+/*
+ --------------------------------------
+ ---------- Checksum options ----------
+ --------------------------------------
+*/
+
+/*
+The STM32F4x7 allows computing and verifying the IP, UDP, TCP and ICMP checksums by hardware:
+ - To use this feature let the following define uncommented.
+ - To disable it and process by CPU comment the the checksum.
+*/
+
+ /* CHECKSUM_GEN_IP==0: Generate checksums by hardware for outgoing IP packets.*/
+#define CHECKSUM_GEN_IP 0
+ /* CHECKSUM_GEN_UDP==0: Generate checksums by hardware for outgoing UDP packets.*/
+#define CHECKSUM_GEN_UDP 0
+ /* CHECKSUM_GEN_TCP==0: Generate checksums by hardware for outgoing TCP packets.*/
+#define CHECKSUM_GEN_TCP 0
+ /* CHECKSUM_CHECK_IP==0: Check checksums by hardware for incoming IP packets.*/
+#define CHECKSUM_CHECK_IP 1
+ /* CHECKSUM_CHECK_UDP==0: Check checksums by hardware for incoming UDP packets.*/
+#define CHECKSUM_CHECK_UDP 1
+ /* CHECKSUM_CHECK_TCP==0: Check checksums by hardware for incoming TCP packets.*/
+#define CHECKSUM_CHECK_TCP 1
+
+
+/*
+ ----------------------------------------------
+ ---------- Sequential layer options ----------
+ ----------------------------------------------
+*/
+/**
+ * LWIP_NETCONN==1: Enable Netconn API (require to use api_lib.c)
+ */
+#define LWIP_NETCONN 0
+
+/*
+ ------------------------------------
+ ---------- Socket options ----------
+ ------------------------------------
+*/
+/**
+ * LWIP_SOCKET==1: Enable Socket API (require to use sockets.c)
+ */
+#define LWIP_SOCKET 0
+
+
+/*
+ ----------------------------------------
+ ---------- Lwip Debug options ----------
+ ----------------------------------------
+*/
+//#define LWIP_DEBUG 1
+
+#endif /* __LWIPOPTS_H__ */
+
+/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/
diff --git a/app/lwip_glue.c b/app/lwip_glue.c
new file mode 100644
index 0000000..6c66de8
--- /dev/null
+++ b/app/lwip_glue.c
@@ -0,0 +1,402 @@
+#include <project.h>
+
+struct netif if0;
+
+
+uint32_t sys_now (void)
+{
+ return ticks;
+}
+
+void dispatch_lwip (void)
+{
+#if 0
+
+ /* check if any packet received */
+ if (ETH_CheckFrameReceived())
+ ethernetif_input (&if0);
+
+#endif
+
+#if 0
+
+ if (link_lost())
+ netif_set_down (&if0);
+
+ if (link_gained())
+ netif_set_up (&if0);
+
+#endif
+
+ sys_check_timeouts();
+
+#if 0
+
+ /* Fine DHCP periodic process every 500ms */
+ if (localtime - DHCPfineTimer >= DHCP_FINE_TIMER_MSECS) {
+ DHCPfineTimer = localtime;
+ dhcp_fine_tmr();
+
+ if ((DHCP_state != DHCP_ADDRESS_ASSIGNED) && (DHCP_state != DHCP_TIMEOUT)) {
+ /* toggle LED1 to indicate DHCP on-going process */
+ STM_EVAL_LEDToggle (LED1);
+
+ /* process DHCP state machine */
+ LwIP_DHCP_Process_Handle();
+ }
+ }
+
+ /* DHCP Coarse periodic process every 60s */
+ if (localtime - DHCPcoarseTimer >= DHCP_COARSE_TIMER_MSECS) {
+ DHCPcoarseTimer = localtime;
+ dhcp_coarse_tmr();
+ }
+
+#endif
+}
+
+
+
+void start_lwip (void)
+{
+ struct ip_addr ipaddr;
+ struct ip_addr netmask;
+ struct ip_addr gw;
+
+ // uint8_t macaddress[6]={0,0,0,0,0,1};
+
+ lwip_init();
+
+ IP4_ADDR (&ipaddr, 10, 32, 48, 99);
+ IP4_ADDR (&netmask, 255, 255, 255, 0);
+ IP4_ADDR (&gw, 10, 32, 48, 1);
+
+
+ //Set_MAC_Address(macaddress);
+
+ /* - netif_add(struct netif *netif, struct ip_addr *ipaddr,
+ struct ip_addr *netmask, struct ip_addr *gw,
+ void *state, err_t (* init)(struct netif *netif),
+ err_t (* input)(struct pbuf *p, struct netif *netif))
+
+ Adds your network interface to the netif_list. Allocate a struct
+ netif and pass a pointer to this structure as the first argument.
+ Give pointers to cleared ip_addr structures when using DHCP,
+ or fill them with sane numbers otherwise. The state pointer may be NULL.
+
+ The init function pointer must point to a initialization function for
+ your ethernet netif interface. The following code illustrates it's use.*/
+
+
+ //netif_add(&if0, &ipaddr, &netmask, &gw, NULL, &ethernetif_init, &ethernetif_input);
+ netif_add (&if0, &ipaddr, &netmask, &gw, NULL, steth_lwip_init , ethernet_input);
+
+ /* Registers the default network interface.*/
+ netif_set_default (&if0);
+
+
+ netif_set_up (&if0);
+
+
+}
+
+
+
+
+
+
+
+
+
+
+
+#if 0
+/**
+ ******************************************************************************
+ * @file netconf.c
+ * @author MCD Application Team
+ * @version V1.0.0
+ * @date 11/20/2009
+ * @brief Network connection configuration
+ ******************************************************************************
+ * @copy
+ *
+ * THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
+ * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
+ * TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
+ * DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
+ * FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
+ * CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ *
+ * <h2><center>&copy; COPYRIGHT 2009 STMicroelectronics</center></h2>
+ */
+
+#include "lwip/memp.h"
+#include "lwip/tcp.h"
+#include "lwip/udp.h"
+#include "netif/etharp.h"
+//include "lwip/dhcp.h"
+#include "ethernetif.h"
+#include <stdint.h>
+#include "stm32f4x7_eth.h"
+#include <string.h>
+#include "netconf.h"
+
+struct netif netif;
+uint32_t TCPTimer = 0;
+uint32_t ARPTimer = 0;
+
+/* Ethernet Rx & Tx DMA Descriptors */
+extern ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB];
+
+/* Ethernet Driver Receive buffers */
+extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE];
+
+/* Ethernet Driver Transmit buffers */
+extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE];
+
+/* Global pointers to track current transmit and receive descriptors */
+extern ETH_DMADESCTypeDef *DMATxDescToSet;
+extern ETH_DMADESCTypeDef *DMARxDescToGet;
+
+/* Put ethernet related stuff in struct so it causes less namespace pollution
+ * and is easier to access from debugger */
+struct {
+ uint8_t connected_;
+ uint16_t lost_links_;
+ uint32_t last_link_up_time_;
+} ethernet_state;
+
+void send_raw_packet()
+{
+ //ETH_TxPkt_ChainMode(l);
+}
+
+/**
+ * @brief Initializes the lwIP stack
+ * @param None
+ * @retval None
+ *
+ * Should only be called once at start-up. Ethernet interface does not
+ * need to have link for this to be called.
+ */
+/** \brief Checks PHY's link status
+ * \returns true if there is a link, false if there is an error, or no link
+ */
+uint8_t checkEthernetLink()
+{
+ // PHY_BSR -- defined in stm32f4x7_eth.h
+ // The basic status register number for the Micrel KSZ8051MLL PHY is 0x1
+ // If MDIO read times out, ETH_ReadPHYRegister returns ETH_ERROR (0) which make link look down
+ uint8_t has_link = (ETH_ReadPHYRegister (PHY_ADDRESS, PHY_BSR) & PHY_Linked_Status) ? 1 : 0;
+ return has_link;
+}
+
+/**
+ * @brief Called when a frame is received
+ * @param None
+ * @retval None
+ */
+void LwIP_Pkt_Handle (void)
+{
+ /* Read a received packet from the Ethernet buffers and send it to the lwIP for handling */
+ ethernetif_input (&if0);
+}
+
+/**
+ * @brief LwIP periodic tasks
+ * @param localtime the current LocalTime value
+ * @retval None
+ */
+#ifdef USE_DHCP
+/**
+ * @brief LwIP_DHCP_Process_Handle
+ * @param None
+ * @retval None
+ */
+void LwIP_DHCP_Process_Handle()
+{
+ struct ip_addr ipaddr;
+ struct ip_addr netmask;
+ struct ip_addr gw;
+ uint8_t iptab[4];
+ uint8_t iptxt[20];
+
+ switch (DHCP_state) {
+ case DHCP_START: {
+ dhcp_start (&if0);
+ IPaddress = 0;
+ DHCP_state = DHCP_WAIT_ADDRESS;
+ }
+ break;
+
+ case DHCP_WAIT_ADDRESS: {
+ /* Read the new IP address */
+ IPaddress = netif.ip_addr.addr;
+
+ if (IPaddress != 0) {
+ DHCP_state = DHCP_ADDRESS_ASSIGNED;
+
+ /* Stop DHCP */
+ dhcp_stop (&if0);
+ } else {
+ /* DHCP timeout */
+ if (netif.dhcp->tries > MAX_DHCP_TRIES) {
+ DHCP_state = DHCP_TIMEOUT;
+
+ /* Stop DHCP */
+ dhcp_stop (&if0);
+
+ /* Static address used */
+ IP4_ADDR (&ipaddr, IP_ADDR0 , IP_ADDR1 , IP_ADDR2 , IP_ADDR3);
+ IP4_ADDR (&netmask, NETMASK_ADDR0, NETMASK_ADDR1, NETMASK_ADDR2, NETMASK_ADDR3);
+ IP4_ADDR (&gw, GW_ADDR0, GW_ADDR1, GW_ADDR2, GW_ADDR3);
+ netif_set_addr (&if0, &ipaddr , &netmask, &gw);
+ }
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+}
+#endif
+
+/*void ETH_IRQHandler(void)
+{
+ while(ETH_GetRxPktSize() != 0)
+ {
+ LwIP_Pkt_Handle();
+ }
+
+ ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
+ ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
+}*/
+
+/**
+ * @brief Configures the Ethernet Interface
+ * @param None
+ * @retval ETH_ERROR on failure, ETH_SUCCESS on success
+ *
+ * Should be called everytime PHY gets a new link (in case link speed or duplex is differnet)
+ * Before being called, ethernet link should be set to "down" with netif_set_down()
+ * This prevents LwIP from attempt to send packets on link
+ */
+uint32_t Ethernet_Init (void)
+{
+ /* Enable SYSCFG clock */
+ RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
+
+ /* Enable ETHERNET clock */
+ //RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC | RCC_AHBPeriph_ETH_MAC_Tx |
+ // RCC_AHBPeriph_ETH_MAC_Rx, ENABLE);
+ //RCC->AHB1ENR |= RCC_AHB1ENR_ETHMACEN | RCC_AHB1ENR_ETHMACTXEN | RCC_AHB1ENR_ETHMACRXEN;
+
+ ETH_InitTypeDef ETH_InitStructure;
+
+ /* Configure MII_RMII selection bit */
+ SYSCFG_ETH_MediaInterfaceConfig (SYSCFG_ETH_MediaInterface_RMII);
+
+ /* Reset ETHERNET on AHB Bus */
+ ETH_DeInit();
+
+ /* Software reset */
+ ETH_SoftwareReset();
+ //RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN;
+
+ /* Wait for software reset */
+ while (ETH_GetSoftwareResetStatus() == SET);
+
+ RCC->AHB1ENR |= RCC_AHB1ENR_ETHMACEN | RCC_AHB1ENR_ETHMACTXEN | RCC_AHB1ENR_ETHMACRXEN;
+
+ /* ETHERNET Configuration ------------------------------------------------------*/
+ /* Call ETH_StructInit if you don't like to configure all ETH_InitStructure parameter */
+ ETH_StructInit (&ETH_InitStructure);
+
+ /* Fill ETH_InitStructure parametrs */
+ /*------------------------ MAC -----------------------------------*/
+ ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable ;
+ ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
+ ETH_InitStructure.ETH_RetryTransmission = ETH_RetryTransmission_Disable;
+ ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;
+ ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
+ ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;
+ ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
+ ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
+ ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
+#ifdef CHECKSUM_BY_HARDWARE
+ ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
+#endif
+
+ /*------------------------ DMA -----------------------------------*/
+
+ /* When we use the Checksum offload feature, we need to enable the Store and Forward mode:
+ the store and forward guarantee that a whole frame is stored in the FIFO, so the MAC can insert/verify the checksum,
+ if the checksum is OK the DMA can handle the frame otherwise the frame is dropped */
+ ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Enable;
+ ETH_InitStructure.ETH_ReceiveStoreForward = ETH_ReceiveStoreForward_Enable;
+ ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable;
+
+ ETH_InitStructure.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Disable;
+ ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Disable;
+ ETH_InitStructure.ETH_SecondFrameOperate = ETH_SecondFrameOperate_Enable;
+ ETH_InitStructure.ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable;
+ ETH_InitStructure.ETH_FixedBurst = ETH_FixedBurst_Enable;
+ ETH_InitStructure.ETH_RxDMABurstLength = ETH_RxDMABurstLength_32Beat;
+ ETH_InitStructure.ETH_TxDMABurstLength = ETH_TxDMABurstLength_32Beat;
+ ETH_InitStructure.ETH_DMAArbitration = ETH_DMAArbitration_RoundRobin_RxTx_2_1;
+
+ /* initialize MAC address in ethernet MAC */
+ ETH_MACAddressConfig (ETH_MAC_Address0, netif.hwaddr);
+
+ /* Configure Ethernet */
+ if (ETH_Init (&ETH_InitStructure, PHY_ADDRESS) == ETH_ERROR)
+ return ETH_ERROR;
+
+ /* Initialize Tx Descriptors list: Chain Mode */
+ ETH_DMATxDescChainInit (DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
+ /* Initialize Rx Descriptors list: Chain Mode */
+ ETH_DMARxDescChainInit (DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
+
+#ifdef CHECKSUM_BY_HARDWARE
+
+ /* Enable the TCP, UDP and ICMP checksum insertion for the Tx frames */
+ for (int i = 0; i < ETH_TXBUFNB; i++)
+ ETH_DMATxDescChecksumInsertionConfig (&DMATxDscrTab[i], ETH_DMATxDesc_ChecksumTCPUDPICMPFull);
+
+#endif
+
+ /* Note: TCP, UDP, ICMP checksum checking for received frame are enabled in DMA config */
+
+ /* Enable MAC and DMA transmission and reception */
+ ETH_Start();
+
+ /* Enable the Ethernet Rx Interrupt */
+ // ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_R, ENABLE);
+
+ // NVIC_InitTypeDef NVIC_InitStructure;
+
+ /* MACCR has an errata where writes that occur next to each other can be ignored.
+ * Have MACCR writen after a delay to guarentee that the register write goes through.
+ */
+ {
+ uint32_t i = 28 * 4; // delay about 4 us
+
+ while (i-- > 0)
+ __asm__ ("nop");
+ }
+ ETH_MACReceptionCmd (ENABLE);
+
+ /* Enable the Ethernet global Interrupt
+ NVIC_InitStructure.NVIC_IRQChannel = ETH_IRQn;
+ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
+ NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
+ NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
+ NVIC_Init(&NVIC_InitStructure); */
+ // NVIC_SetPriority(ETH_IRQn, 3);
+ // NVIC_EnableIRQ(ETH_IRQn);
+
+ return ETH_SUCCESS;
+}
+#endif
diff --git a/app/main.c b/app/main.c
new file mode 100644
index 0000000..2f25fb6
--- /dev/null
+++ b/app/main.c
@@ -0,0 +1,55 @@
+#include "project.h"
+
+
+static void
+board_setup (void)
+{
+ rcc_clock_setup_hse_3v3 (&hse_8mhz_3v3[CLOCK_3V3_168MHZ]);
+ rcc_periph_clock_enable (RCC_SYSCFG);
+ rcc_periph_clock_enable (RCC_GPIOA);
+ rcc_periph_clock_enable (RCC_GPIOB);
+ rcc_periph_clock_enable (RCC_GPIOC);
+ rcc_periph_clock_enable (RCC_GPIOD);
+ rcc_periph_clock_enable (RCC_USART6);
+
+ nvic_set_priority (NVIC_USART6_IRQ, 0xff);
+ nvic_set_priority (NVIC_EXTI0_IRQ, 0x80);
+ nvic_set_priority (NVIC_ETH_IRQ, 0x40);
+ nvic_set_priority (NVIC_SYSTICK_IRQ, 0x40);
+}
+
+
+static void
+system_init (void)
+{
+
+ board_setup();
+ led_init();
+ ticker_init();
+ usart_init();
+
+ radio_init();
+
+ start_lwip();
+ steth_init();
+
+}
+
+int
+main (void)
+{
+
+
+ system_init();
+
+ printf ("Fish\r\n");
+
+
+ while (1) {
+ dispatch_lwip();
+ steth_dispatch();
+
+ }
+
+ return 0;
+}
diff --git a/app/msf.c b/app/msf.c
new file mode 100644
index 0000000..392bfe7
--- /dev/null
+++ b/app/msf.c
@@ -0,0 +1,226 @@
+#include "project.h"
+
+#define P1 (GPIO1)
+#define P1_PORT GPIOB
+
+#define T (GPIO0)
+#define T_PORT GPIOB
+
+static uint8_t bitsa[60], bitsb[60];
+
+static int time_known;
+static int check_parity (uint8_t *d, unsigned s, unsigned e, uint8_t p)
+{
+ unsigned i;
+
+ for (i = s; i <= e; ++i)
+ p ^= d[i];
+
+ return !p;
+}
+
+
+static unsigned bcd (uint8_t *d, unsigned s, unsigned e)
+{
+ unsigned ret = 0, c, b, i;
+
+ for (i = e, c = 1, b = 0; i >= s; --i, b++) {
+
+ if (d[i]) ret += c;
+
+
+ switch (b & 3) {
+ case 0:
+ case 1:
+ case 2:
+ c <<= 1;
+ break;
+
+ default:
+ c >>= 3;
+ c *= 10;
+ }
+ }
+
+ return ret;
+}
+
+
+
+static int check_min_ident (uint8_t *i)
+{
+ if (i[0]) return 1;
+
+ if (!i[1]) return 1;
+
+ if (!i[2]) return 1;
+
+ if (!i[3]) return 1;
+
+ if (!i[4]) return 1;
+
+ if (!i[5]) return 1;
+
+ if (!i[6]) return 1;
+
+ if (i[7]) return 1;
+
+ return 0;
+}
+
+
+
+static void process_bits (uint64_t abs)
+{
+ UTC u;
+ EPOCH msf_time;
+
+
+ if (check_min_ident (&bitsa[52])) return;
+
+ if (check_parity (bitsa, 17, 24, bitsb[54])) return;
+
+ if (check_parity (bitsa, 25, 35, bitsb[55])) return;
+
+ if (check_parity (bitsa, 36, 38, bitsb[56])) return;
+
+ if (check_parity (bitsa, 39, 51, bitsb[57])) return;
+
+ u.jday = 0;
+ u.year = bcd (bitsa, 17, 24);
+ u.month = bcd (bitsa, 25, 29);
+ u.mday = bcd (bitsa, 30, 35);
+ u.hour = bcd (bitsa, 39, 44);
+ u.minute = bcd (bitsa, 45, 51);
+ u.second = 59;
+ u.nanosecond = 0;
+
+ /* This is always valid a check_min_ident will fail for leap seconds*/
+
+ msf_time = time_utc_to_epoch (u);
+ msf_time.s -= 59;
+
+ pll_set_offset (msf_time, abs);
+ time_known = 1;
+
+ printf ("Next minute is: %02d-%02d-%02d %02d:%02d\r\n", u.year, u.month, u.mday, u.hour, u.minute);
+ time_print_epoch (msf_time);
+}
+
+
+static void report_bits (uint64_t abs, int second, int a, int b)
+{
+ if ((!second) || (second > 59)) return;
+
+ bitsa[second] = a;
+ bitsb[second] = b;
+
+ if (second == 59) process_bits (abs);
+
+}
+
+static void report_time (uint64_t abs)
+{
+ EPOCH e = pll_decompose (abs);
+ time_print_epoch (e);
+ printf ("%d\r\n", (unsigned) e.s);
+}
+
+void exti0_isr (void)
+{
+ static uint32_t last_0;
+ static uint32_t last_1;
+ static uint32_t last_s;
+ static int second, bita, bitb, had_m;
+
+ uint32_t now = SCS_DWT_CYCCNT;
+ uint64_t abs;
+
+ uint32_t pulse_w, offset;
+ int is_s = 0;
+ int v;
+
+ nvic_disable_irq (NVIC_EXTI0_IRQ);
+ exti_reset_request (EXTI0);
+
+ v = !!gpio_get (T_PORT, T);
+
+ if (v) {
+ pulse_w = now - last_0;
+ pulse_w /= (HZ / 1000);
+
+ if (pulse_w > 300) {
+ last_s = now;
+ is_s = 1;
+ }
+
+ last_1 = now;
+
+ } else {
+ pulse_w = now - last_1;
+ pulse_w /= (HZ / 1000);
+
+ if (pulse_w > 400) {
+ had_m = 1;
+ second = 0;
+ }
+
+ last_0 = now;
+ }
+
+ offset = now - last_s;
+ offset /= (HZ / 1000);
+
+
+ if (is_s) {
+ abs = abs_extend (now);
+ pll_dispatch (abs);
+
+ if (had_m) {
+ report_bits (abs, second, bita, bitb);
+ second++;
+
+ }
+
+ if (time_known)
+ report_time (abs);
+ }
+
+
+
+ if (!v) { /* 1->0 transition */
+ if (offset < 150) {
+ bita = 0;
+ bitb = 0;
+ }
+
+ if (offset < 250)
+ bitb = 0;
+ } else { /* 0->1 transition*/
+ if (is_s) {
+ bita = 1;
+ bitb = 1;
+ } else if (offset < 250)
+ bitb = 1;
+ }
+
+
+
+ nvic_enable_irq (NVIC_EXTI0_IRQ);
+}
+
+void
+radio_init (void)
+{
+ MAP_INPUT (T);
+ MAP_OUTPUT_PP (P1);
+
+ gpio_clear (P1_PORT, P1);
+
+ exti_select_source (EXTI0, T_PORT);
+ exti_set_trigger (EXTI0, EXTI_TRIGGER_BOTH);
+ exti_enable_request (EXTI0);
+ nvic_enable_irq (NVIC_EXTI0_IRQ);
+}
+
+
diff --git a/app/ntp.c b/app/ntp.c
new file mode 100644
index 0000000..1c109ce
--- /dev/null
+++ b/app/ntp.c
@@ -0,0 +1,79 @@
+#include "project.h"
+
+
+typedef struct {
+ union {
+ struct {
+ uint32_t li: 2;
+ uint32_t vn: 3;
+ uint32_t mode: 3;
+ uint32_t stratum: 8;
+ uint32_t poll: 8;
+ uint32_t precision: 8;
+ };
+ uint32_t word_0;
+ };
+
+ uint32_t root_delay;
+ uint32_t root_dispersion;
+ uint32_t reference_id;
+
+ uint64_t reference_ts;
+ uint64_t origin_ts;
+ uint64_t receive_ts;
+ uint64_t transmit_ts;
+} ntp_packet_t;
+
+
+
+
+#if 0
+packet (uint8_t *_p)
+{
+ EPOCH reftime = pll_decompose (pll_last_update);
+
+ ntp_packet_t rx = (uint8_t *)_p;
+ ntp_packet_t tx;
+
+
+ tx.li = NTP LEAP_MEH;
+ tx.vn = NTP_VERSION;
+ tx.mode = NTP_MODE_SERVER;
+ tx.poll = ?
+ tx.precision = ?
+ tx.rootdelay = ?
+ tx.rootdisp = ?
+ tx.refid = FCC ('M', 'S', 'F', 0);
+ tx.reftime =;
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+}
+#endif
diff --git a/app/pins.h b/app/pins.h
new file mode 100644
index 0000000..16da24c
--- /dev/null
+++ b/app/pins.h
@@ -0,0 +1,46 @@
+
+
+#define MAP_AF(a, af) do { \
+ gpio_mode_setup( a ## _PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, a ); \
+ gpio_set_output_options( a ## _PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, a); \
+ gpio_set_af( a ## _PORT, af, a); \
+ } while (0)
+
+#define MAP_AF_PU(a, af) do { \
+ gpio_mode_setup( a ## _PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, a ); \
+ gpio_set_output_options( a ## _PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, a); \
+ gpio_set_af( a ## _PORT, af, a); \
+ } while (0)
+
+#define MAP_AF_OD(a, af) do { \
+ gpio_mode_setup( a ## _PORT, GPIO_MODE_AF, GPIO_PUPD_PULLUP, a ); \
+ gpio_set_output_options( a ## _PORT, GPIO_OTYPE_OD, GPIO_OSPEED_50MHZ, a); \
+ gpio_set_af( a ## _PORT, af, a); \
+ } while (0)
+
+
+#define MAP_OUTPUT_PP(a) do { \
+ gpio_mode_setup( a ## _PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, a ); \
+ gpio_set_output_options( a ## _PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, a); \
+ } while (0)
+
+
+#define MAP_OUTPUT_OD(a) do { \
+ gpio_mode_setup( a ## _PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, a ); \
+ gpio_set_output_options( a ## _PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, a); \
+ } while (0)
+
+
+#define MAP_INPUT_PU(a) do { \
+ gpio_mode_setup( a ## _PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, a ); \
+ } while (0)
+
+
+#define MAP_INPUT(a) do { \
+ gpio_mode_setup( a ## _PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, a ); \
+ } while (0)
+
+
+#define CLEAR(a) gpio_clear( a ## _PORT, a)
+#define SET(a) gpio_set( a ## _PORT, a)
+#define GET(a) gpio_get( a ## _PORT, a)
diff --git a/app/pll.c b/app/pll.c
new file mode 100644
index 0000000..4b89143
--- /dev/null
+++ b/app/pll.c
@@ -0,0 +1,123 @@
+#include "project.h"
+
+#define JUMP_THRESH 0.1
+#define JUMP_TICKS 30
+#define FEEDBACK 0.001
+
+
+static int64_t offset;
+static int64_t phase;
+static int64_t freq = HZ;
+
+static int out_of_lock = JUMP_TICKS + 1;
+
+uint64_t pll_last_update;
+int pll_valid = 0;
+
+
+
+static void modify_freq (uint64_t now, int d)
+{
+ int64_t pd1, pd2, te;
+
+ pd1 = now - phase;
+
+ te = pd1 / freq;
+ pd1 %= freq;
+
+ if (d > 0)
+ freq += d;
+ else
+ freq -= -d;
+
+
+ pd2 = pd1 + (te * freq);
+
+ phase = now - pd2;
+}
+
+void pll_dispatch (uint64_t edge)
+{
+ double f;
+ int64_t pd;
+
+ {
+ int diff, hf;
+
+ pd = edge - phase;
+ pd %= freq;
+
+ hf = (int) (freq >> 1);
+
+ diff = (int) pd;
+
+ if (diff > hf)
+ diff = diff - (int) freq;
+
+
+ f = (double) diff;
+ f /= (double) freq;
+ }
+
+ if ((f > (JUMP_THRESH)) || (f < - (JUMP_THRESH)))
+ out_of_lock++;
+ else
+ out_of_lock = 0;
+
+#if 0
+ printf ("PLL pd %.3f freq %d phase %d\r\n", (float) f, (int) freq, (int) phase);
+#endif
+
+ if (out_of_lock > JUMP_TICKS) {
+ phase += pd;
+ out_of_lock = 0;
+ printf ("PLL - jumping\r\n");
+ freq = HZ;
+ } else {
+
+ f *= FEEDBACK;
+ f *= (double) freq;
+
+ modify_freq (edge, (int) f);
+
+ }
+
+ pll_last_update = edge;
+}
+
+
+
+void pll_set_offset (EPOCH epoch, uint64_t abs)
+{
+ /* Find nearest second to abs*/
+ abs += freq >> 2;
+ abs -= phase;
+ abs /= freq;
+
+ offset = epoch.s - abs;
+
+ pll_valid = 1;
+}
+
+
+
+
+EPOCH pll_decompose (uint64_t abs)
+{
+ EPOCH ret;
+
+ abs -= phase;
+
+ ret.s = abs / freq;
+ abs -= freq * ret.s;
+
+
+ ret.s += offset;
+
+ abs *= (uint64_t) 1000000000;
+ abs = abs / freq;
+
+ ret.ns = abs;
+
+ return ret;
+}
diff --git a/app/project.h b/app/project.h
new file mode 100644
index 0000000..4fc679a
--- /dev/null
+++ b/app/project.h
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <inttypes.h>
+#include <libopencm3/stm32/rcc.h>
+#include <libopencm3/stm32/gpio.h>
+#include <libopencm3/stm32/usart.h>
+#include <libopencm3/stm32/dma.h>
+#include <libopencm3/stm32/i2c.h>
+#include <libopencm3/stm32/spi.h>
+#include <libopencm3/stm32/adc.h>
+#include <libopencm3/stm32/exti.h>
+#include <libopencm3/stm32/ethernet.h>
+#include <libopencm3/ethernet/phy.h>
+#include <libopencm3/stm32/syscfg.h>
+#include <libopencm3/cm3/systick.h>
+#include <libopencm3/cm3/nvic.h>
+#include <libopencm3/cm3/cortex.h>
+#include <libopencm3/cm3/scs.h>
+
+#include <lwip/init.h>
+#include <lwip/sys.h>
+#include <lwip/udp.h>
+#include <lwip/mem.h>
+#include <lwip/memp.h>
+#include <lwip/timers.h>
+#include <lwip/timers.h>
+#include <netif/etharp.h>
+
+#include "time_fn.h"
+
+#include "pins.h"
+
+#include "ring.h"
+
+#include "prototypes.h"
+
+#define HZ 168000000
+
+#define TRACE do { stdio_drain(); printf("%s:%d\r\n",__FUNCTION__,__LINE__); } while (0)
diff --git a/app/prototypes.h b/app/prototypes.h
new file mode 100644
index 0000000..279a182
--- /dev/null
+++ b/app/prototypes.h
@@ -0,0 +1,64 @@
+/* led.c */
+extern void led_init(void);
+extern void led_clear(void);
+extern void led_set(void);
+extern void led_slow_tick(void);
+/* ticker.c */
+extern volatile uint32_t ticks;
+extern void delay_us(uint32_t d);
+extern void sys_tick_handler(void);
+extern void delay_ms(uint32_t d);
+extern void ticker_init(void);
+/* ring.c */
+extern void ring_init(volatile ring_t *r, uint8_t *buf, size_t len);
+extern int ring_write_byte(volatile ring_t *r, uint8_t c);
+extern int ring_read_byte(volatile ring_t *r, uint8_t *c);
+extern int ring_write(volatile ring_t *r, uint8_t *buf, size_t len, int blocking);
+extern int ring_empty(volatile ring_t *r);
+/* usart.c */
+extern volatile ring_t rx6_ring;
+extern volatile ring_t tx6_ring;
+extern void usart6_isr(void);
+extern void usart6_queue(uint8_t d);
+extern void usart6_drain(void);
+extern int usart6_write(char *ptr, int len, int blocking);
+extern void usart_init(void);
+/* stdio.c */
+extern int _open(const char *name, int flags, int mode);
+extern int _close(int file);
+extern int _write(int file, char *buf, int nbytes);
+extern int _read(int file, char *buf, int nbytes);
+extern int _fstat(int file, struct stat *st);
+extern int _lseek(int file, int offset, int whence);
+extern int isatty(int file);
+extern void stdio_drain(void);
+/* lwip_glue.c */
+extern struct netif if0;
+extern uint32_t sys_now(void);
+extern void dispatch_lwip(void);
+extern void start_lwip(void);
+/* steth.c */
+extern _Bool phy_link_an_done(uint8_t phy);
+extern void eth_isr(void);
+extern void steth_isr(void);
+extern err_t steth_lwip_init(struct netif *netif);
+extern void steth_init(void);
+extern void steth_dispatch(void);
+/* msf.c */
+extern void exti0_isr(void);
+extern void radio_init(void);
+/* abs.c */
+extern uint64_t abs_extend(uint32_t now);
+extern uint64_t abs_get(void);
+extern void abs_slow_tick(void);
+/* pll.c */
+extern void pll_dispatch(uint64_t edge);
+extern void pll_set_offset(EPOCH epoch, uint64_t abs);
+extern EPOCH pll_decompose(uint64_t abs);
+/* main.c */
+extern int main(void);
+/* time_fn.c */
+extern UTC time_epoch_to_utc(EPOCH epoch);
+extern EPOCH time_utc_to_epoch(UTC u);
+extern void time_print_utc(UTC u);
+extern void time_print_epoch(EPOCH e);
diff --git a/app/ring.c b/app/ring.c
new file mode 100644
index 0000000..973f345
--- /dev/null
+++ b/app/ring.c
@@ -0,0 +1,77 @@
+#include "project.h"
+
+
+static inline size_t
+ring_next (volatile ring_t *r, size_t p)
+{
+ p++;
+
+ if (p >= r->size)
+ p -= r->size;
+
+ return p;
+}
+
+void
+ring_init (volatile ring_t *r, uint8_t *buf, size_t len)
+{
+ r->data = buf;
+ r->size = len;
+ r->write = 0;
+ r->read = 0;
+}
+
+int
+ring_write_byte (volatile ring_t *r, uint8_t c)
+{
+ size_t n = ring_next (r, r->write);
+
+ if (n == r->read)
+ return -EAGAIN;
+
+ r->data[r->write] = c;
+
+ r->write = n;
+
+ return 0;
+}
+
+
+int
+ring_read_byte (volatile ring_t *r, uint8_t *c)
+{
+ size_t n = ring_next (r, r->read);
+
+ if (r->read == r->write)
+ return -EAGAIN;
+
+ *c = r->data[r->read];
+ r->read = n;
+
+ return 0;
+}
+
+int
+ring_write (volatile ring_t *r, uint8_t *buf, size_t len, int blocking)
+{
+ while (len--) {
+ if (blocking) {
+ while (ring_write_byte (r, *buf));
+
+ buf++;
+ } else {
+ if (ring_write_byte (r, * (buf++)))
+ return -EAGAIN;
+ }
+ }
+
+ return 0;
+}
+
+
+
+int
+ring_empty (volatile ring_t *r)
+{
+ return (r->read == r->write) ? 1 : 0;
+}
diff --git a/app/ring.h b/app/ring.h
new file mode 100644
index 0000000..1eae65b
--- /dev/null
+++ b/app/ring.h
@@ -0,0 +1,6 @@
+typedef struct ring {
+ uint8_t *data;
+ size_t size;
+ size_t write;
+ size_t read;
+} ring_t;
diff --git a/app/stdio.c b/app/stdio.c
new file mode 100644
index 0000000..286d4d2
--- /dev/null
+++ b/app/stdio.c
@@ -0,0 +1,81 @@
+#include "project.h"
+
+int
+_open (const char *name,
+ int flags,
+ int mode)
+{
+ errno = ENOSYS;
+ return -1; /* Always fails */
+
+} /* _open () */
+
+int
+_close (int file)
+{
+ errno = EBADF;
+ return -1; /* Always fails */
+
+} /* _close () */
+
+int
+_write (int file,
+ char *buf,
+ int nbytes)
+{
+
+ int ret;
+
+
+ ret = usart6_write (buf, nbytes, 1);
+
+ if (ret < 0) {
+ errno = -ret;
+ return -1;
+ }
+
+ return ret;
+} /* _write () */
+
+
+int
+_read (int file,
+ char *buf,
+ int nbytes)
+{
+
+ errno = -EAGAIN;
+ return -1; /* EOF */
+
+} /* _read () */
+
+int
+_fstat (int file,
+ struct stat *st)
+{
+ st->st_mode = S_IFCHR;
+ return 0;
+
+} /* _fstat () */
+
+int
+_lseek (int file,
+ int offset,
+ int whence)
+{
+ return 0;
+
+} /* _lseek () */
+
+int
+isatty (int file)
+{
+ return 1;
+
+} /* _isatty () */
+
+
+void stdio_drain (void)
+{
+ usart6_drain();
+}
diff --git a/app/steth.c b/app/steth.c
new file mode 100644
index 0000000..2aa847f
--- /dev/null
+++ b/app/steth.c
@@ -0,0 +1,366 @@
+#include <project.h>
+
+
+#define PHY PHY0
+
+#define TXEN GPIO11
+#define TXEN_PORT GPIOB
+
+#define TXD0 GPIO12
+#define TXD0_PORT GPIOB
+
+#define TXD1 GPIO13
+#define TXD1_PORT GPIOB
+
+#define RXD0 GPIO4
+#define RXD0_PORT GPIOC
+
+#define RXD1 GPIO5
+#define RXD1_PORT GPIOC
+
+#define CRS_DV GPIO7
+#define CRS_DV_PORT GPIOA
+
+#define MDIO GPIO2
+#define MDIO_PORT GPIOA
+
+#define MDC GPIO1
+#define MDC_PORT GPIOC
+
+#define REF_CLK GPIO1
+#define REF_CLK_PORT GPIOA
+
+#define NRST GPIO2
+#define NRST_PORT GPIOE
+
+
+#define DESC_SZ 32
+#define FRAME_SZ 1516
+
+#define TX_BUFS 4
+#define RX_BUFS 4
+
+#define ETH_BUF_LEN ((TX_BUFS+ RX_BUFS) * (DESC_SZ+FRAME_SZ))
+
+static int running;
+
+static uint8_t __attribute__ ((aligned (4))) eth_buf[ETH_BUF_LEN];
+
+static uint8_t sa[ETHARP_HWADDR_LEN] = { 0xc0, 0xf1, 0xee, 0xc0, 0xff, 0xee };
+
+extern uint32_t TxBD;
+extern uint32_t RxBD;
+
+
+
+bool
+phy_link_an_done (uint8_t phy)
+{
+ return eth_smi_read (PHY, PHY_REG_BSR) & PHY_REG_BSR_ANDONE;
+}
+
+
+
+static err_t
+steth_tx (struct netif *netif, struct pbuf *p)
+{
+#if 0
+ static uint8_t tx_buf[FRAME_SZ];
+ uint32_t len, left;
+
+ len = 0;
+ left = FRAME_SZ;
+
+ for (; p != NULL; p = p->next) {
+ uint32_t sz = (left > p->len) ? p->len : left;
+ memcpy (&tx_buf[len], (u8_t *) p->payload, sz);
+ len += sz;
+ left -= sz;
+ }
+
+ // usart6_write ("X", 1, 0);
+
+ // hexdump(tx_buf,len);
+
+ while (!eth_tx (tx_buf, len));
+
+#else
+
+ if (p->next) return ERR_IF;
+
+ while (!eth_tx (p->payload, p->len));
+
+#endif
+
+ {
+ static int tx_cnt = 0;
+ printf ("TX %d\r\n", tx_cnt++);
+ }
+
+ return ERR_OK;
+}
+
+static err_t
+steth_rx (void)
+{
+ //err_t err;
+ struct pbuf *p;
+ uint32_t len;
+#if 0
+ struct pbuf *q;
+ static uint8_t rx_buf[FRAME_SZ];
+
+ len = 0;
+
+ if (!eth_rx (rx_buf, &len, sizeof (rx_buf))) {
+ usart6_write ("?", 1, 0);
+ return ERR_OK;
+ }
+
+ /* We allocate a pbuf chain of pbufs from the Lwip buffer pool */
+ p = pbuf_alloc (PBUF_RAW, len, PBUF_POOL);
+
+ if (!p) {
+ usart6_write ("!", 1, 0);
+ return ERR_MEM;
+ }
+
+ len = 0;
+
+ for (q = p; q != NULL; q = q->next) {
+ memcpy ((u8_t *) q->payload, (u8_t *) & rx_buf[len], q->len);
+ len += q->len;
+ }
+
+#else
+ p = pbuf_alloc (PBUF_RAW, MTU, PBUF_POOL);
+
+ if (!p) return ERR_MEM;
+
+ len = 0;
+
+ if (!eth_rx (p->payload, &len, MTU)) {
+ pbuf_free (p);
+ return ERR_IF;
+ }
+
+ pbuf_realloc (p, len);
+#endif
+
+
+
+ // usart6_write (".", 1, 0);
+
+ {
+ static int rx_cnt = 0;
+ printf ("RX %d\r\n", rx_cnt++);
+ }
+
+
+ return if0.input (p, &if0);
+}
+
+
+
+static void
+steth_nis (void)
+{
+ if (eth_irq_ack_pending (ETH_DMASR_RS))
+ steth_rx();
+}
+
+void
+eth_isr (void)
+{
+}
+
+void
+steth_isr (void)
+{
+ // printf ("eth\r\n");
+
+ if (eth_irq_ack_pending (ETH_DMASR_NIS))
+ steth_nis();
+
+}
+
+
+err_t
+steth_lwip_init (struct netif *netif)
+{
+ LWIP_ASSERT ("netif != NULL", (netif != NULL));
+
+#if LWIP_NETIF_HOSTNAME
+ /* Initialize interface hostname */
+ netif->hostname = "lwip";
+#endif /* LWIP_NETIF_HOSTNAME */
+
+ netif->name[0] = 's';
+ netif->name[1] = 't';
+ /* We directly use etharp_output() here to save a function call.
+ * You can instead declare your own function an call etharp_output()
+ * from it if you have to do some checks before sending (e.g. if link
+ * is available...) */
+ netif->output = etharp_output;
+ netif->linkoutput = steth_tx;
+
+ /* set MAC hardware address length */
+ netif->hwaddr_len = ETHARP_HWADDR_LEN;
+
+ /* set MAC hardware address */
+ memcpy (netif->hwaddr, sa, ETHARP_HWADDR_LEN);
+
+ /* maximum transfer unit */
+ netif->mtu = 1500;
+
+ /* device capabilities */
+ netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP;
+
+ return ERR_OK;
+}
+
+
+void
+steth_init (void)
+{
+
+
+ MAP_AF (TXEN, GPIO_AF11);
+ MAP_AF (TXD0, GPIO_AF11);
+ MAP_AF (TXD1, GPIO_AF11);
+
+ MAP_AF (RXD0, GPIO_AF11);
+ MAP_AF (RXD1, GPIO_AF11);
+
+ MAP_AF (CRS_DV, GPIO_AF11);
+
+ MAP_AF (MDIO, GPIO_AF11);
+ MAP_AF (MDC, GPIO_AF11);
+
+ MAP_AF (REF_CLK, GPIO_AF11);
+
+ MAP_OUTPUT_PP (NRST);
+
+ SET (NRST);
+
+ /* The switch to RMII has be done with steth under reset, with no clock */
+
+
+ rcc_periph_clock_disable (RCC_ETHMACPTP);
+ rcc_periph_clock_disable (RCC_ETHMACRX);
+ rcc_periph_clock_disable (RCC_ETHMACTX);
+ rcc_periph_clock_disable (RCC_ETHMAC);
+
+ RCC_AHB1RSTR |= RCC_AHB1RSTR_ETHMACRST; /*Assert RESET */
+ delay_us (1);
+
+#ifndef SYSCFG_PMC_MII_RMII_SEL
+#define SYSCFG_PMC_MII_RMII_SEL (1UL << 23)
+#endif
+
+ SYSCFG_PMC |= SYSCFG_PMC_MII_RMII_SEL;
+
+ RCC_AHB1RSTR &= ~RCC_AHB1RSTR_ETHMACRST; /*De-sssert RESET */
+
+
+ rcc_periph_clock_enable (RCC_ETHMAC);
+ rcc_periph_clock_enable (RCC_ETHMACTX);
+ rcc_periph_clock_enable (RCC_ETHMACRX);
+ rcc_periph_clock_enable (RCC_ETHMACPTP);
+
+ eth_desc_init (eth_buf, TX_BUFS, RX_BUFS, FRAME_SZ, FRAME_SZ, 1);
+
+ /*MDC = HCLK / 102 (0b100) => 1.6MHz */
+ eth_init (PHY, 0x4);
+ eth_enable_checksum_offload();
+
+
+ printf ("Waiting for link\r\n");
+
+ while (!phy_link_isup (PHY));
+
+ phy_autoneg_enable (PHY);
+ printf ("Waiting for autonegociation\r\n");
+
+ while (!phy_link_an_done (PHY));
+
+ switch (phy_link_status (PHY)) {
+ case LINK_HD_10M:
+ case LINK_FD_10M:
+ ETH_MACCR &= ~ETH_MACCR_FES;
+ break;
+
+ default:
+ ;
+ }
+
+
+ switch (phy_link_status (PHY)) {
+ case LINK_HD_10M:
+ case LINK_HD_100M:
+ ETH_MACCR &= ~ETH_MACCR_DM;
+ ETH_MACCR |= ETH_MACCR_ROD;
+ break;
+
+ default:
+ ;
+ }
+
+ ETH_MACCR &= ~ETH_MACCR_RD;
+
+ eth_set_mac (sa);
+
+ nvic_disable_irq (NVIC_ETH_IRQ);
+
+ eth_irq_enable (ETH_DMAIER_NISE);
+ eth_irq_enable (ETH_DMAIER_RIE);
+ eth_irq_enable (ETH_DMASR_TS);
+ //
+ eth_start();
+
+
+ running++;
+
+ printf ("Running\n");
+
+}
+
+
+void
+steth_dispatch (void)
+{
+#if 0
+ uint32_t d, s;
+#endif
+
+ if (!running)
+ return;
+
+#if 0
+ printf ("Net:\r\n");
+ printf (" ETH_MACCR: %08" PRIx32 "\r\n", ETH_MACCR);
+ printf (" ETH_MACDBGR: %08" PRIx32 "\r\n", ETH_MACDBGR);
+ printf (" ETH_DMASR: %08" PRIx32 "\r\n", ETH_DMASR);
+ printf (" ETH_DMAIER: %08" PRIx32 "\r\n", ETH_DMAIER);
+ printf (" ETH_DMACHTDR: %08" PRIx32 "\r\n", ETH_DMACHTDR);
+ printf (" ETH_DMACHRDR: %08" PRIx32 "\r\n", ETH_DMACHRDR);
+
+
+ s = d = RxBD;
+
+
+ do {
+ printf (" %08" PRIx32 ": %08" PRIx32 " %08" PRIx32 " %08" PRIx32 " %08"
+ PRIx32 "\r\n", d, ETH_DES0 (d), ETH_DES1 (d), ETH_DES2 (d),
+ ETH_DES3 (d));
+
+ d = ETH_DES3 (d);
+
+ } while (d != s);
+
+#endif
+
+ steth_isr();
+
+}
+
diff --git a/app/ticker.c b/app/ticker.c
new file mode 100644
index 0000000..af91d14
--- /dev/null
+++ b/app/ticker.c
@@ -0,0 +1,79 @@
+#include "project.h"
+
+static volatile uint32_t delay_ms_count;
+static uint32_t scale = 35;
+
+volatile uint32_t ticks;
+
+void
+delay_us (uint32_t d)
+{
+ d *= scale;
+
+ while (d--)
+ __asm__ ("nop");
+}
+
+void
+sys_tick_handler (void)
+{
+ static int slow;
+
+ if (delay_ms_count)
+ delay_ms_count--;
+
+ ticks++;
+
+ slow++;
+
+ if (slow < 1000)
+ return;
+
+ slow = 0;
+
+ led_slow_tick();
+ abs_slow_tick();
+}
+
+
+
+void
+delay_ms (uint32_t d)
+{
+ delay_ms_count = d;
+
+ while (delay_ms_count);
+}
+
+
+void
+ticker_init (void)
+{
+ uint32_t v, w;
+
+ /*168MHz / 168000 -> 1ms */
+ systick_set_reload (168000);
+ systick_set_clocksource (STK_CSR_CLKSOURCE_AHB);
+ systick_counter_enable();
+ /* this done last */
+ systick_interrupt_enable();
+
+
+ /*Calibrate the delay loop */
+
+ do {
+ scale--;
+ v = ticks;
+
+ while (v == ticks);
+
+ delay_us (1000);
+ w = ticks;
+ v++;
+ w -= v;
+ } while (w);
+
+ SCS_DEMCR |= SCS_DEMCR_TRCENA;
+ SCS_DWT_CTRL |= SCS_DWT_CTRL_CYCCNTENA;
+
+}
diff --git a/app/time_fn.c b/app/time_fn.c
new file mode 100644
index 0000000..5636ef1
--- /dev/null
+++ b/app/time_fn.c
@@ -0,0 +1,225 @@
+#include "project.h"
+
+static int is_leap (unsigned year)
+{
+ if (year % 4)
+ return 0;
+
+ if (year % 100)
+ return 1;
+
+ if (year % 400)
+ return 0;
+
+ return 1;
+}
+
+
+UTC time_epoch_to_utc (EPOCH epoch)
+{
+ UTC u;
+ uint64_t day;
+ unsigned y400, y100, y4;
+
+ day = epoch.s / 86400;
+ epoch.s -= day * 86400;
+
+ day += 134774;
+
+ u.wday = day % 7;
+ u.wday++;
+
+
+ y400 = day / 146097; /*146097 days in 400 years */
+ day -= (y400 * 146097);
+
+ y100 = day / 36524; /*36524 days in 100 years */
+ day -= (y100 * 36524);
+
+ y4 = day / 1461; /*1461 days in 4 years */
+ day -= (y4 * 1461);
+
+ /* This may look redundant but 31 Dec in year 4 is special case */
+ if (day < 1095) { /*1095 days in 3 years */
+ u.year = day / 365; /*365 days in a year */
+ day -= (365 * u.year);
+ } else {
+ u.year = 3;
+ day -= 1095;
+ }
+
+
+ /* Now put it all back together */
+ u.year += 1601;
+ u.year += 4 * y4;
+ u.year += 100 * y100;
+ u.year += 400 * y400;
+
+
+ u.jday = day + 1;
+
+ u.is_leap = is_leap (u.year);
+
+
+ if (!u.is_leap) {
+ /*Days and months for ordinary years */
+ if (u.jday < 32) {
+ u.month = 1;
+ u.mday = u.jday;
+ } else if (u.jday < 60) {
+ u.month = 2;
+ u.mday = u.jday - 31;
+ } else if (u.jday < 91) {
+ u.month = 3;
+ u.mday = u.jday - 59;
+ } else if (u.jday < 121) {
+ u.month = 4;
+ u.mday = u.jday - 90;
+ } else if (u.jday < 152) {
+ u.month = 5;
+ u.mday = u.jday - 120;
+ } else if (u.jday < 182) {
+ u.month = 6;
+ u.mday = u.jday - 151;
+ } else if (u.jday < 213) {
+ u.month = 7;
+ u.mday = u.jday - 181;
+ } else if (u.jday < 244) {
+ u.month = 8;
+ u.mday = u.jday - 212;
+ } else if (u.jday < 274) {
+ u.month = 9;
+ u.mday = u.jday - 243;
+ } else if (u.jday < 305) {
+ u.month = 10;
+ u.mday = u.jday - 273;
+ } else if (u.jday < 335) {
+ u.month = 11;
+ u.mday = u.jday - 304;
+ } else {
+ u.month = 12;
+ u.mday = u.jday - 334;
+ }
+ } else {
+ /*And leap years */
+ if (u.jday < 32) {
+ u.month = 1;
+ u.mday = u.jday;
+ } else if (u.jday < 61) {
+ u.month = 2;
+ u.mday = u.jday - 31;
+ } else if (u.jday < 92) {
+ u.month = 3;
+ u.mday = u.jday - 60;
+ } else if (u.jday < 122) {
+ u.month = 4;
+ u.mday = u.jday - 91;
+ } else if (u.jday < 153) {
+ u.month = 5;
+ u.mday = u.jday - 121;
+ } else if (u.jday < 183) {
+ u.month = 6;
+ u.mday = u.jday - 152;
+ } else if (u.jday < 214) {
+ u.month = 7;
+ u.mday = u.jday - 182;
+ } else if (u.jday < 245) {
+ u.month = 8;
+ u.mday = u.jday - 213;
+ } else if (u.jday < 275) {
+ u.month = 9;
+ u.mday = u.jday - 244;
+ } else if (u.jday < 306) {
+ u.month = 10;
+ u.mday = u.jday - 274;
+ } else if (u.jday < 336) {
+ u.month = 11;
+ u.mday = u.jday - 305;
+ } else {
+ u.month = 12;
+ u.mday = u.jday - 335;
+ }
+ }
+
+ u.hour = epoch.s / 3600;
+ epoch.s -= u.hour * 3600;
+ u.minute = epoch.s / 60;
+ epoch.s -= u.minute * 60;
+ u.second = epoch.s;
+
+ u.nanosecond = epoch.ns;
+
+ return u;
+}
+
+
+
+
+EPOCH time_utc_to_epoch (UTC u)
+{
+ unsigned y400;
+ unsigned y100;
+ unsigned y4;
+
+ EPOCH ret;
+
+ static int const mdays[] =
+ { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 };
+ static int const lmdays[] =
+ { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 };
+
+ u.is_leap = is_leap (u.year);
+
+ if (u.year < 100) u.year += 2000;
+
+
+ if (!u.jday) {
+ if (u.is_leap)
+ u.jday = u.mday + lmdays[u.month];
+ else
+ u.jday = u.mday + mdays[u.month];
+ }
+
+ u.year -= 1601;
+ y400 = u.year / 400;
+ u.year -= y400 * 400;
+ y100 = u.year / 100;
+ u.year -= y100 * 100;
+ y4 = u.year / 4;
+ u.year -= y4 * 4;
+
+
+
+ ret.s = u.jday - 1;
+ ret.s += u.year * 365;
+ ret.s += y4 * 1461;
+ ret.s += y100 * 36524;
+ ret.s += y400 * 146097;
+
+ ret.s -= 134774;
+
+ ret.s *= 86400;
+
+ ret.s += u.second;
+ ret.s += u.minute * 60;
+ ret.s += u.hour * 3600;
+
+ ret.ns = u.nanosecond;
+
+ return ret;
+}
+
+
+void time_print_utc (UTC u)
+{
+ const char *dname[] = {"Sun", "Mon", "Tue", "Wed", "Thr", "Fri", "Sat", "Sun"};
+ const char *mname[] = {"", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+ printf ("%s %04d-%s-%02d %02d:%02d:%02d.%09d\r\n", dname[u.wday], u.year, mname[u.month], u.mday, u.hour, u.minute, u.second, u.nanosecond);
+}
+
+void time_print_epoch (EPOCH e)
+{
+ UTC u = time_epoch_to_utc (e);
+ time_print_utc (u);
+}
+
diff --git a/app/time_fn.h b/app/time_fn.h
new file mode 100644
index 0000000..7cf75d3
--- /dev/null
+++ b/app/time_fn.h
@@ -0,0 +1,19 @@
+typedef struct {
+ unsigned year;
+ unsigned is_leap;
+ unsigned jday;
+ unsigned month;
+ unsigned mday;
+ unsigned wday;
+ unsigned hour;
+ unsigned minute;
+ unsigned second;
+ unsigned nanosecond;
+} UTC;
+
+typedef struct {
+ uint64_t s;
+ uint64_t ns;
+} EPOCH;
+
+
diff --git a/app/usart.c b/app/usart.c
new file mode 100644
index 0000000..9b2a454
--- /dev/null
+++ b/app/usart.c
@@ -0,0 +1,100 @@
+#include "project.h"
+
+#define BUFFER_SIZE 256
+#define BIG_BUFFER_SIZE 600
+
+volatile ring_t rx6_ring;
+static uint8_t rx6_ring_buf[BUFFER_SIZE];
+
+volatile ring_t tx6_ring;
+static uint8_t tx6_ring_buf[BUFFER_SIZE];
+
+
+#define TX6 GPIO6
+#define TX6_PORT GPIOC
+
+#define RX6 GPIO7
+#define RX6_PORT GPIOC
+
+
+void usart6_isr (void)
+{
+ uint8_t data;
+
+ /* Check if we were called because of RXNE. */
+ if (((USART_CR1 (USART6) & USART_CR1_RXNEIE) != 0) &&
+ ((USART_SR (USART6) & USART_SR_RXNE) != 0)) {
+
+ /* Retrieve the data from the peripheral. */
+ data = usart_recv (USART6);
+
+ ring_write_byte (&rx6_ring, data);
+ }
+
+ /* Check if we were called because of TXE. */
+ if (((USART_CR1 (USART6) & USART_CR1_TXEIE) != 0) &&
+ ((USART_SR (USART6) & USART_SR_TXE) != 0)) {
+
+ if (ring_read_byte (&tx6_ring, &data)) {
+ /*No more data, Disable the TXE interrupt, it's no longer needed. */
+ usart_disable_tx_interrupt (USART6);
+ } else
+ usart_send_blocking (USART6, data);
+ }
+
+}
+
+void
+usart6_queue (uint8_t d)
+{
+ ring_write_byte (&tx6_ring, d);
+ usart_enable_tx_interrupt (USART6);
+}
+
+void
+usart6_drain (void)
+{
+ while (!ring_empty (&tx6_ring));
+}
+
+
+int
+usart6_write (char *ptr, int len, int blocking)
+{
+ int ret;
+
+ ret = ring_write (&tx6_ring, (uint8_t *) ptr, len, blocking);
+ usart_enable_tx_interrupt (USART6);
+ return ret;
+}
+
+
+void
+usart_init (void)
+{
+
+ ring_init (&rx6_ring, rx6_ring_buf, sizeof (rx6_ring_buf));
+ ring_init (&tx6_ring, tx6_ring_buf, sizeof (tx6_ring_buf));
+
+ /* Map pins, and set usart2 to have pull ups */
+
+ MAP_AF (TX6, GPIO_AF8);
+ MAP_AF_PU (RX6, GPIO_AF8);
+
+ usart_set_baudrate (USART6, 38400);
+ usart_set_databits (USART6, 8);
+ usart_set_stopbits (USART6, USART_STOPBITS_1);
+ usart_set_parity (USART6, USART_PARITY_NONE);
+ usart_set_flow_control (USART6, USART_FLOWCONTROL_NONE);
+ usart_set_mode (USART6, USART_MODE_TX_RX);
+
+
+ usart_enable_rx_interrupt (USART6);
+
+ /* Finally enable the USARTs. */
+ usart_enable (USART6);
+
+ nvic_enable_irq (NVIC_USART6_IRQ);
+
+
+}
diff --git a/arch_max.ld b/arch_max.ld
new file mode 100644
index 0000000..f9e870a
--- /dev/null
+++ b/arch_max.ld
@@ -0,0 +1,12 @@
+/* Linker script for STM32F407VET6, 512K flash, 192K RAM. */
+
+/* Define memory regions. */
+MEMORY
+{
+ rom (rx) : ORIGIN = 0x08000000, LENGTH = 512K
+ ram (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
+}
+
+/* Include the common ld script. */
+INCLUDE libopencm3_stm32f4.ld
+
diff --git a/libopencm3 b/libopencm3
new file mode 160000
+Subproject 5c73d601763dd140bff020be8d6d06f03c2bea7
diff --git a/libopencm3-local/libopencm3/ethernet/mac/stm32fxx7.h b/libopencm3-local/libopencm3/ethernet/mac/stm32fxx7.h
new file mode 100644
index 0000000..ae9828d
--- /dev/null
+++ b/libopencm3-local/libopencm3/ethernet/mac/stm32fxx7.h
@@ -0,0 +1 @@
+#include <libopencm3/ethernet/mac_stm32fxx7.h>
diff --git a/lwip/lwip-1.4.1 b/lwip/lwip-1.4.1
new file mode 160000
+Subproject 5b8b5d459e7dd890724515bbfad86c705234f9e
diff --git a/lwip/lwip-local/port/stm32f4x7/arch/bpstruct.h b/lwip/lwip-local/port/stm32f4x7/arch/bpstruct.h
new file mode 100644
index 0000000..1e0dde0
--- /dev/null
+++ b/lwip/lwip-local/port/stm32f4x7/arch/bpstruct.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#if defined(__IAR_SYSTEMS_ICC__)
+#pragma pack(1)
+#endif
+
diff --git a/lwip/lwip-local/port/stm32f4x7/arch/cc.h b/lwip/lwip-local/port/stm32f4x7/arch/cc.h
new file mode 100644
index 0000000..e0f8ab6
--- /dev/null
+++ b/lwip/lwip-local/port/stm32f4x7/arch/cc.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef __CC_H__
+#define __CC_H__
+
+#include "cpu.h"
+
+typedef unsigned char u8_t;
+typedef signed char s8_t;
+typedef unsigned short u16_t;
+typedef signed short s16_t;
+typedef unsigned long u32_t;
+typedef signed long s32_t;
+typedef u32_t mem_ptr_t;
+typedef int sys_prot_t;
+
+
+#define U16_F "hu"
+#define S16_F "d"
+#define X16_F "hx"
+#define U32_F "u"
+#define S32_F "d"
+#define X32_F "x"
+#define SZT_F "uz"
+
+
+#define PACK_STRUCT_BEGIN
+#define PACK_STRUCT_STRUCT __attribute__ ((__packed__))
+#define PACK_STRUCT_END
+#define PACK_STRUCT_FIELD(x) x
+
+
+#define LWIP_PLATFORM_ASSERT(x) do { if(!(x)) while(1); } while(0)
+
+#endif /* __CC_H__ */
diff --git a/lwip/lwip-local/port/stm32f4x7/arch/cpu.h b/lwip/lwip-local/port/stm32f4x7/arch/cpu.h
new file mode 100644
index 0000000..2af31a8
--- /dev/null
+++ b/lwip/lwip-local/port/stm32f4x7/arch/cpu.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef __CPU_H__
+#define __CPU_H__
+
+#define BYTE_ORDER LITTLE_ENDIAN
+
+#endif /* __CPU_H__ */
diff --git a/lwip/lwip-local/port/stm32f4x7/arch/epstruct.h b/lwip/lwip-local/port/stm32f4x7/arch/epstruct.h
new file mode 100644
index 0000000..41951f7
--- /dev/null
+++ b/lwip/lwip-local/port/stm32f4x7/arch/epstruct.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#if defined(__IAR_SYSTEMS_ICC__)
+#pragma pack()
+#endif
+
diff --git a/lwip/lwip-local/port/stm32f4x7/arch/init.h b/lwip/lwip-local/port/stm32f4x7/arch/init.h
new file mode 100644
index 0000000..14b9515
--- /dev/null
+++ b/lwip/lwip-local/port/stm32f4x7/arch/init.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef __ARCH_INIT_H__
+#define __ARCH_INIT_H__
+
+#define TCPIP_INIT_DONE(arg) tcpip_init_done(arg)
+
+void tcpip_init_done(void *);
+int wait_for_tcpip_init(void);
+
+#endif /* __ARCH_INIT_H__ */
+
+
+
+
diff --git a/lwip/lwip-local/port/stm32f4x7/arch/lib.h b/lwip/lwip-local/port/stm32f4x7/arch/lib.h
new file mode 100644
index 0000000..9726dee
--- /dev/null
+++ b/lwip/lwip-local/port/stm32f4x7/arch/lib.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef __LIB_H__
+#define __LIB_H__
+
+#include <string.h>
+
+
+#endif /* __LIB_H__ */
diff --git a/lwip/lwip-local/port/stm32f4x7/arch/perf.h b/lwip/lwip-local/port/stm32f4x7/arch/perf.h
new file mode 100644
index 0000000..68afdb5
--- /dev/null
+++ b/lwip/lwip-local/port/stm32f4x7/arch/perf.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef __PERF_H__
+#define __PERF_H__
+
+#define PERF_START /* null definition */
+#define PERF_STOP(x) /* null definition */
+
+#endif /* __PERF_H__ */
diff --git a/lwip/lwip-local/port/stm32f4x7/arch/sys_arch.h b/lwip/lwip-local/port/stm32f4x7/arch/sys_arch.h
new file mode 100644
index 0000000..291f6b0
--- /dev/null
+++ b/lwip/lwip-local/port/stm32f4x7/arch/sys_arch.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2001-2003 Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
+ * SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * This file is part of the lwIP TCP/IP stack.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+#ifndef __SYS_RTXC_H__
+#define __SYS_RTXC_H__
+
+#include "FreeRTOS.h"
+#include "task.h"
+#include "queue.h"
+#include "semphr.h"
+
+#define SYS_MBOX_NULL (xQueueHandle)0
+#define SYS_SEM_NULL (xSemaphoreHandle)0
+#define SYS_DEFAULT_THREAD_STACK_DEPTH configMINIMAL_STACK_SIZE
+
+typedef xSemaphoreHandle sys_sem_t;
+typedef xQueueHandle sys_mbox_t;
+typedef xTaskHandle sys_thread_t;
+
+typedef struct _sys_arch_state_t
+{
+ // Task creation data.
+ char cTaskName[configMAX_TASK_NAME_LEN];
+ unsigned short nStackDepth;
+ unsigned short nTaskCount;
+} sys_arch_state_t;
+
+
+
+//extern sys_arch_state_t s_sys_arch_state;
+
+//void sys_set_default_state();
+//void sys_set_state(signed char *pTaskName, unsigned short nStackSize);
+
+/* Message queue constants. */
+#define archMESG_QUEUE_LENGTH ( 6 )
+#endif /* __SYS_RTXC_H__ */
+
diff --git a/lwip/lwip-local/port/stm32f4x7/ethernetif.h b/lwip/lwip-local/port/stm32f4x7/ethernetif.h
new file mode 100644
index 0000000..0db858b
--- /dev/null
+++ b/lwip/lwip-local/port/stm32f4x7/ethernetif.h
@@ -0,0 +1,11 @@
+#ifndef __ETHERNETIF_H__
+#define __ETHERNETIF_H__
+
+
+#include "lwip/err.h"
+#include "lwip/netif.h"
+
+err_t ethernetif_init(struct netif *netif);
+err_t ethernetif_input(struct netif *netif);
+
+#endif
diff --git a/oocd/board/arch_max.cfg b/oocd/board/arch_max.cfg
new file mode 100644
index 0000000..3ea3802
--- /dev/null
+++ b/oocd/board/arch_max.cfg
@@ -0,0 +1,4 @@
+
+source [find target/stm32f4x.cfg]
+
+#reset_config srst_only
diff --git a/oocd/interface/cmsis-dap.cfg b/oocd/interface/cmsis-dap.cfg
new file mode 100644
index 0000000..2dc6002
--- /dev/null
+++ b/oocd/interface/cmsis-dap.cfg
@@ -0,0 +1,6 @@
+#
+telnet_port 4444
+gdb_port 3333
+
+source [find interface/cmsis-dap.cfg]
+
diff --git a/oocd/interface/j-link.cfg b/oocd/interface/j-link.cfg
new file mode 100644
index 0000000..3e95768
--- /dev/null
+++ b/oocd/interface/j-link.cfg
@@ -0,0 +1,5 @@
+#
+telnet_port 4444
+gdb_port 3333
+
+source [find interface/jlink.cfg]
diff --git a/oocd/interface/stlink-v2.cfg b/oocd/interface/stlink-v2.cfg
new file mode 100644
index 0000000..0985230
--- /dev/null
+++ b/oocd/interface/stlink-v2.cfg
@@ -0,0 +1,11 @@
+#
+telnet_port 4444
+gdb_port 3333
+
+#interface hla
+#hla_layout stlink
+#hla_device_desc "ST-LINK/V2"
+#hla_vid_pid 0x0483 0x3748
+
+source [find interface/stlink-v2.cfg]
+
diff --git a/oocd/stm32-f407.cfg b/oocd/stm32-f407.cfg
new file mode 100644
index 0000000..0809223
--- /dev/null
+++ b/oocd/stm32-f407.cfg
@@ -0,0 +1,6 @@
+#
+telnet_port 4444
+gdb_port 3333
+
+source [find interface/jlink.cfg]
+source [find target/stm32f1x.cfg]