diff --git a/.gitignore b/.gitignore
index c80b86fd052e5298255e7e5d50e0af548c5cf685..5cdd4b63b657a24e4e48861796cfc61da90bf0a6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,7 +36,7 @@ COOJA.testlog
 *.simplelink
 *.sky
 *.firmware
-*.srf06-cc26xx
+*.cc26x0-cc13x0
 *.zoul
 
 # do not ignore platform makefiles
@@ -47,7 +47,7 @@ COOJA.testlog
 !Makefile.nrf52dk
 !Makefile.openmote-cc2538
 !Makefile.sky
-!Makefile.srf06-cc26xx
+!Makefile.cc26x0-cc13x0
 !Makefile.zoul
 
 # other nRF52 build artifacts
diff --git a/.gitmodules b/.gitmodules
index ed5ea056d8a40bafd4be6f3958a0d0cb065d6c0e..6481bbb934718a8093777d34ce1715195deaa39c 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -2,10 +2,10 @@
 	path = tools/cc2538-bsl
 	url = https://github.com/JelmerT/cc2538-bsl.git
 [submodule "arch/cpu/cc26xx-cc13xx/lib/cc26xxware"]
-	path = arch/cpu/cc26xx-cc13xx/lib/cc26xxware
+	path = arch/cpu/cc26x0-cc13x0/lib/cc26xxware
 	url = https://github.com/contiki-ng/cc26xxware.git
 [submodule "arch/cpu/cc26xx-cc13xx/lib/cc13xxware"]
-	path = arch/cpu/cc26xx-cc13xx/lib/cc13xxware
+	path = arch/cpu/cc26x0-cc13x0/lib/cc13xxware
 	url = https://github.com/contiki-ng/cc13xxware.git
 [submodule "tools/sensniff"]
 	path = tools/sensniff
@@ -26,5 +26,5 @@
 	path = arch/cpu/simplelink-cc13xx-cc26xx/lib/coresdk_cc13xx_cc26xx
 	url = https://github.com/contiki-ng/coresdk_cc13xx_cc26xx.git
 [submodule "arch/cpu/cc26xx-cc13xx/lib/cc2640r2-sdk"]
-	path = arch/cpu/cc26xx-cc13xx/lib/cc2640r2-sdk
+	path = arch/cpu/cc26x0-cc13x0/lib/cc2640r2-sdk
 	url = https://github.com/contiki-ng/cc2640r2-sdk.git
diff --git a/.travis.yml b/.travis.yml
index ca4dbf8d86ad4c0eca98a53c5c5e806991f03725..29e853d0e61eeb4ca0981e823d01fb542ad86237 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -80,4 +80,5 @@ env:
     - TEST_NAME='compile-tools'
     - TEST_NAME='native-runs'
     - TEST_NAME='ipv6' BUILD_COOJA=true
+    - TEST_NAME='ipv6-nbr' BUILD_COOJA=true
     - TEST_NAME='out-of-tree-build'
diff --git a/Makefile.gcc b/Makefile.gcc
new file mode 100644
index 0000000000000000000000000000000000000000..60796f791867da19c73b93554ffae87113221a82
--- /dev/null
+++ b/Makefile.gcc
@@ -0,0 +1,27 @@
+# -*- makefile -*-
+#
+# GCC specific definitions and actions
+#
+
+GCC_MAJOR_VERSION := $(shell $(CC) -v 2>&1 | grep "gcc version" | cut -b 13)
+GCC_MINOR_VERSION := $(shell $(CC) -v 2>&1 | grep "gcc version" | cut -b 15)
+
+# Warn if using version 6.3.x of arm-none-eabi-gcc
+ifeq ("$(CC)","arm-none-eabi-gcc")
+  ifeq (6,$(GCC_MAJOR_VERSION))
+    ifeq (3,$(GCC_MINOR_VERSION))
+      $(warning Warning: you're using a version of $(CC) that may create broken Contiki-NG executables.)
+      $(warning We recommend to upgrade or downgrade your toolchain.)
+    endif
+  endif
+endif
+
+# Warn if using 4.6.x or older msp430-gcc
+ifeq ("$(CC)","msp430-gcc")
+  ifeq ($(shell test $(GCC_MAJOR_VERSION) -lt 5; echo $$?),0)
+    ifeq ($(shell test $(GCC_MINOR_VERSION) -lt 7; echo $$?),0)
+      $(warning Warning: you're using an old version of $(CC).)
+      $(warning Upgrade to 4.7.x is recommended for extended memory support and bugfixes.)
+    endif
+  endif
+endif
diff --git a/Makefile.include b/Makefile.include
index 672c7f4c1ec4a51942a4f6562a78dfdba33d432e..6ebea14f4bb6266e8d69b5975bc63af819edca1d 100644
--- a/Makefile.include
+++ b/Makefile.include
@@ -39,7 +39,11 @@ endif
 
 BUILD_DIR = build
 BUILD_DIR_TARGET = $(BUILD_DIR)/$(TARGET)
-BUILD_DIR_BOARD = $(BUILD_DIR_TARGET)/$(BOARD)/$(BUILD_DIR_CONFIG)
+BUILD_DIR_TARGET_BOARD = $(BUILD_DIR_TARGET)/$(BOARD)
+# If BOARD was empty, make sure we don't end up with a sequence of slashes
+BUILD_DIR_FULL = $(BUILD_DIR_TARGET_BOARD:/=)/$(BUILD_DIR_CONFIG)
+# Ditto if BUILD_DIR_CONFIG was empty
+BUILD_DIR_BOARD = $(BUILD_DIR_FULL:/=)
 OBJECTDIR = $(BUILD_DIR_BOARD)/obj
 
 CONTIKI_NG_TARGET_LIB = $(BUILD_DIR_BOARD)/contiki-ng-$(TARGET).a
@@ -65,7 +69,7 @@ ifneq ("$(wildcard project-conf.h)","")
 CFLAGS += -DPROJECT_CONF_PATH=\"project-conf.h\"
 endif
 
-MODULES += os os/net os/net/mac os/net/mac/framer os/net/routing os/storage
+MODULES += os/net os/net/mac os/net/mac/framer os/net/routing os/storage
 
 define oname
 ${patsubst %.c,%.o, \
@@ -82,7 +86,10 @@ uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
 
 ### Include target makefile (TODO Unsafe?)
 
-target_makefile := $(wildcard $(CONTIKI)/arch/platform/$(TARGET)/Makefile.$(TARGET) ${foreach TDIR, $(TARGETDIRS), $(TDIR)/$(TARGET)/Makefile.$(TARGET)})
+# Configurable arch path
+ARCH_PATH ?= $(CONTIKI)/arch
+
+target_makefile := $(wildcard $(ARCH_PATH)/platform/$(TARGET)/Makefile.$(TARGET) ${foreach TDIR, $(TARGETDIRS), $(TDIR)/$(TARGET)/Makefile.$(TARGET)})
 
 # Check if the target makefile exists, and create the object directory if necessary.
 ifeq ($(strip $(target_makefile)),)
@@ -220,20 +227,27 @@ else ifeq ($(MAKE_ROUTING),MAKE_ROUTING_NULLROUTING)
   MODULES += os/net/routing/nullrouting
 endif
 
-MODULEDIRS = $(MODULES_REL) ${wildcard ${addprefix $(CONTIKI)/, $(MODULES)}}
+MODULEDIRS = $(MODULES_REL) ${addprefix $(CONTIKI)/, $(MODULES)}
 UNIQUEMODULES = $(call uniq,$(MODULEDIRS))
-MODULES_SOURCES = ${foreach d, $(MODULEDIRS), ${subst ${d}/,,${wildcard $(d)/*.c}}}
+MODULES_SOURCES = ${foreach d, $(UNIQUEMODULES), ${subst ${d}/,,${wildcard $(d)/*.c}}}
 CONTIKI_SOURCEFILES += $(MODULES_SOURCES)
 
 # Include module-specific makefiles
-MODULES_INCLUDES = ${wildcard ${foreach d, $(MODULEDIRS), $(d)/Makefile.${notdir $(d)}}}
-include $(MODULES_INCLUDES)
+MODULES_INCLUDES = ${wildcard ${foreach d, $(UNIQUEMODULES), $(d)/Makefile.${notdir $(d)}}}
+
+### Perform an immediate expansion of MODULES_INCLUDES and store it in a
+### variable. This will allow us to subsequently filter-out module Makefiles
+### that were included in the first pass, such that we don't end up including
+### them twice.
+MODULES_INCLUDED_FIRST_PASS := $(MODULES_INCLUDES)
+include $(MODULES_INCLUDED_FIRST_PASS)
+
 # Iterate once more: include the modules added from the previous include.
 # Only works with one level of nested module inclusion.
-include $(MODULES_INCLUDES)
+include $(filter-out $(MODULES_INCLUDED_FIRST_PASS),$(MODULES_INCLUDES))
 
 # C-include module-specific macros using -imacros
-MODULES_IMACROS = ${wildcard ${foreach d, $(MODULEDIRS), $(d)/module-macros.h}}
+MODULES_IMACROS = ${wildcard ${foreach d, $(UNIQUEMODULES), $(d)/module-macros.h}}
 ifneq ($(MODULES_IMACROS),)
   CFLAGS += ${foreach d, $(MODULES_IMACROS), -imacros $(d)}
 endif
@@ -276,7 +290,7 @@ CONTIKI_CPU_DIRS_CONCAT    = ${addprefix $(CONTIKI_CPU)/, \
 CONTIKI_ARCH_DIRS    = ${addprefix $(CONTIKI)/, arch}
 
 SOURCEDIRS = . $(PROJECTDIRS) $(CONTIKI_TARGET_DIRS_CONCAT) $(CONTIKI_ARCH_DIRS) \
-             $(CONTIKI_CPU_DIRS_CONCAT) $(CONTIKIDIRS) $(MODULEDIRS) $(EXTERNALDIRS) ${dir $(target_makefile)}
+             $(CONTIKI_CPU_DIRS_CONCAT) $(CONTIKIDIRS) $(MODULEDIRS) $(EXTERNALDIRS)
 
 vpath %.c $(SOURCEDIRS)
 vpath %.S $(SOURCEDIRS)
@@ -326,13 +340,13 @@ clean:
 	@echo Target $(TARGET) cleaned
 
 distclean:
-	@for TARG in `ls $(CONTIKI)/arch/platform $(TARGETDIRS)`; do \
+	@for TARG in `ls $(ARCH_PATH)/platform $(TARGETDIRS)`; do \
 		echo Running: $(MAKE) TARGET=$$TARG clean; \
 		$(MAKE) TARGET=$$TARG clean; \
 	done
 	-$(Q)rm -rf $(BUILD_DIR)
 
--include $(CONTIKI)/arch/platform/$(TARGET)/Makefile.customrules-$(TARGET)
+-include $(ARCH_PATH)/platform/$(TARGET)/Makefile.customrules-$(TARGET)
 
 ifndef CUSTOM_RULE_C_TO_OBJECTDIR_O
 $(OBJECTDIR)/%.o: %.c | $(OBJECTDIR)
@@ -414,7 +428,7 @@ endif
 include $(CONTIKI)/Makefile.help
 
 targets:
-	@ls $(CONTIKI)/arch/platform $(TARGETDIRS)
+	@ls $(ARCH_PATH)/platform $(TARGETDIRS)
 
 boards:
 ifdef BOARD
@@ -462,6 +476,9 @@ ifeq ($(findstring $(TARGET),native cooja),)
   include $(CONTIKI)/Makefile.embedded
 endif
 
+### Include Makefile.gcc for GCC specific definitions and actions
+include $(CONTIKI)/Makefile.gcc
+
 # Don't treat $(BUILD_DIR_BOARD)/%.$(TARGET) and $(TARGET) as intermediate
 # files because for many platforms they are in fact the primary target.
 .PRECIOUS: $(BUILD_DIR_BOARD)/%.$(TARGET) %.$(TARGET)
@@ -475,6 +492,8 @@ ifeq ($(PLATFORM_ACTION),skip)
 # Skip this target.
 $(CONTIKI_PROJECT):
 	@echo "Skipping $@: not for the '$(TARGET)/$(BOARD)' platform!"
+%.$(TARGET):
+	@echo "Skipping $@: not for the '$(TARGET)/$(BOARD)' platform!"
 else
 # Build this target.
 # Match-anything pattern rule to allow the project makefiles to
diff --git a/README.md b/README.md
index e9a1005ef3b1ca0f062e37cb35691e003b1f247e..99ee570f73b02e6bb76f0650a21c111d61be7951 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
+<img src="https://github.com/contiki-ng/contiki-ng.github.io/blob/master/images/logo/Contiki_logo_2RGB.png" alt="Logo" width="256">
+
 # Contiki-NG: The OS for Next Generation IoT Devices
 
 [![Build Status](https://travis-ci.org/contiki-ng/contiki-ng.svg?branch=master)](https://travis-ci.org/contiki-ng/contiki-ng/branches)
@@ -8,7 +10,7 @@
 
 Contiki-NG is an open-source, cross-platform operating system for Next-Generation IoT devices. It focuses on dependable (secure and reliable) low-power communication and standard protocols, such as IPv6/6LoWPAN, 6TiSCH, RPL, and CoAP. Contiki-NG comes with extensive documentation, tutorials, a roadmap, release cycle, and well-defined development flow for smooth integration of community contributions.
 
-Unless excplicitly stated otherwise, Contiki-NG sources are distributed under
+Unless explicitly stated otherwise, Contiki-NG sources are distributed under
 the terms of the [3-clause BSD license](LICENSE.md). This license gives
 everyone the right to use and distribute the code, either in binary or
 source code format, as long as the copyright license is retained in
diff --git a/arch/cpu/arm/Makefile.arm b/arch/cpu/arm/Makefile.arm
index e8befdb860cb66ea39792bf13ee1331b6c7b4429..d9893a34d3667debb2c7dc1b7ed407d8482e0030 100644
--- a/arch/cpu/arm/Makefile.arm
+++ b/arch/cpu/arm/Makefile.arm
@@ -10,6 +10,7 @@ CC       = arm-none-eabi-gcc
 CPP      = arm-none-eabi-cpp
 LD       = arm-none-eabi-gcc
 AR       = arm-none-eabi-ar
+AS       = arm-none-eabi-gcc
 OBJCOPY  = arm-none-eabi-objcopy
 OBJDUMP  = arm-none-eabi-objdump
 NM       = arm-none-eabi-nm
@@ -25,6 +26,11 @@ ifeq ($(WERROR),1)
   CFLAGS += -Werror
 endif
 
+### Pass CFLAGS along to assembly files in the build
+ASFLAGS += $(CFLAGS)
+### Specify '-c' option to assemble only and not link
+ASFLAGS += -c 
+
 LDFLAGS += -mthumb -mlittle-endian
 
 OBJDUMP_FLAGS += --disassemble --source --disassembler-options=force-thumb
diff --git a/arch/cpu/arm/cortex-m/Makefile.cortex-m b/arch/cpu/arm/cortex-m/Makefile.cortex-m
index 0ca1d54ffa663f211ccc0853f96571f25d82fdc7..3f14ead419419243bdd9e1c4ca6e1eabd1fc2afb 100644
--- a/arch/cpu/arm/cortex-m/Makefile.cortex-m
+++ b/arch/cpu/arm/cortex-m/Makefile.cortex-m
@@ -25,4 +25,4 @@ $(OUT_ELF): $(CPU_STARTFILES) $$(CONTIKI_OBJECTFILES) %.o $(PROJECT_OBJECTFILES)
 	$(TRACE_LD)
 	$(Q)$(LD) $(LDFLAGS) ${filter-out $(LDSCRIPT) %.a,$^} ${filter %.a,$^} $(TARGET_LIBFLAGS) -o $@
 
-include $(CONTIKI)/arch/cpu/arm/Makefile.arm
+include $(ARCH_PATH)/cpu/arm/Makefile.arm
diff --git a/arch/cpu/arm/cortex-m/atomic-cortex.h b/arch/cpu/arm/cortex-m/atomic-cortex.h
new file mode 100644
index 0000000000000000000000000000000000000000..51cbb11f73a2baf7c672a469ffd48701b77002b2
--- /dev/null
+++ b/arch/cpu/arm/cortex-m/atomic-cortex.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2019, Toshiba Corporation
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/*---------------------------------------------------------------------------*/
+/**
+ * \addtogroup arm
+ *
+ * Arm Cortex-M implementation of atomic operations using the LDREX,
+ * STREX and DMB instructions.
+ *
+ * @{
+ */
+#ifndef ATOMIC_CORTEX_H_
+#define ATOMIC_CORTEX_H_
+#include <contiki.h>
+
+#ifdef CMSIS_CONF_HEADER_PATH
+#include CMSIS_CONF_HEADER_PATH
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#define atomic_cas_uint8(t,o,n) atomic_cortex_cas_uint8((t),(o),(n))
+
+static inline bool
+atomic_cortex_cas_uint8(uint8_t *target, uint8_t old_val, uint8_t new_val)
+{
+  int status = 1;
+  
+  if(__LDREXB(target) == old_val) {
+    status = __STREXB(new_val, target);
+  }
+
+  __DMB();
+  
+  return status == 0 ? true : false;
+}
+
+#endif /* ATOMIC_CORTEX_H_ */
+/** @} */
diff --git a/arch/cpu/arm/cortex-m/cm3/Makefile.cm3 b/arch/cpu/arm/cortex-m/cm3/Makefile.cm3
index b4bf612dab747a8d3b20b6b508d340327e8de188..35051a0f77d7da809492d0488d70243d2a6e4862 100644
--- a/arch/cpu/arm/cortex-m/cm3/Makefile.cm3
+++ b/arch/cpu/arm/cortex-m/cm3/Makefile.cm3
@@ -6,4 +6,4 @@ LDFLAGS += -mcpu=cortex-m3 -nostartfiles
 
 TARGET_LIBFILES += -lm
 
-include $(CONTIKI)/arch/cpu/arm/cortex-m/Makefile.cortex-m
+include $(ARCH_PATH)/cpu/arm/cortex-m/Makefile.cortex-m
diff --git a/arch/cpu/arm/cortex-m/cm4/Makefile.cm4 b/arch/cpu/arm/cortex-m/cm4/Makefile.cm4
index 7443681ea6559c96004ead2b3de157001e164d80..dc470601ff30a2b0b7504f3f2bd087db9a8c5859 100644
--- a/arch/cpu/arm/cortex-m/cm4/Makefile.cm4
+++ b/arch/cpu/arm/cortex-m/cm4/Makefile.cm4
@@ -4,4 +4,4 @@ CFLAGS += -mcpu=cortex-m4
 
 LDFLAGS += -mcpu=cortex-m4
 
-include $(CONTIKI)/arch/cpu/arm/cortex-m/Makefile.cortex-m
+include $(ARCH_PATH)/cpu/arm/cortex-m/Makefile.cortex-m
diff --git a/arch/cpu/cc2538/Makefile.cc2538 b/arch/cpu/cc2538/Makefile.cc2538
index 51a5c40c75566512d4c6f3a8e0faeaafeb7d2de9..85f435320d8f0670b5ed26573be31fac26be467d 100644
--- a/arch/cpu/cc2538/Makefile.cc2538
+++ b/arch/cpu/cc2538/Makefile.cc2538
@@ -52,4 +52,4 @@ $(LDSCRIPT): $(SOURCE_LDSCRIPT) FORCE | $(OBJECTDIR)
 	$(TRACE_CC)
 	$(Q)$(CC) $(LDGENFLAGS) $< | grep -v '^\s*#\s*pragma\>' > $@
 
-include $(CONTIKI)/arch/cpu/arm/cortex-m/cm3/Makefile.cm3
+include $(ARCH_PATH)/cpu/arm/cortex-m/cm3/Makefile.cm3
diff --git a/arch/cpu/cc2538/cc2538-conf.h b/arch/cpu/cc2538/cc2538-conf.h
index d34c3dee5fe27aa203639a365b3ae65903492606..bb92fb7e38aa40b369fc44f0dd9b39417e4518c2 100644
--- a/arch/cpu/cc2538/cc2538-conf.h
+++ b/arch/cpu/cc2538/cc2538-conf.h
@@ -263,6 +263,11 @@
 #ifndef NETSTACK_CONF_RADIO
 #define NETSTACK_CONF_RADIO         cc2538_rf_driver
 #endif
+
+/**
+ * \brief Maximum packet size
+ */
+#define cc2538_rf_driver_max_payload_len       125
 /** @} */
 /*---------------------------------------------------------------------------*/
 /**
diff --git a/arch/cpu/cc2538/cc2538-def.h b/arch/cpu/cc2538/cc2538-def.h
index defa4ecb0c34dfbe7b5fedfb5fbb4c71807dbdcd..7189d63ee8a533e313879a2d8bd62b62437282bf 100644
--- a/arch/cpu/cc2538/cc2538-def.h
+++ b/arch/cpu/cc2538/cc2538-def.h
@@ -65,11 +65,14 @@
 /* Path to CMSIS header */
 #define CMSIS_CONF_HEADER_PATH               "cc2538_cm3.h"
 
-/* Path to headers with implementation of mutexes and memory barriers */
+/* Path to headers with implementation of mutexes, atomic and memory barriers */
 #define MUTEX_CONF_ARCH_HEADER_PATH          "mutex-cortex.h"
+#define ATOMIC_CONF_ARCH_HEADER_PATH         "atomic-cortex.h"
 #define MEMORY_BARRIER_CONF_ARCH_HEADER_PATH "memory-barrier-cortex.h"
-
+/*---------------------------------------------------------------------------*/
 #define GPIO_HAL_CONF_ARCH_HDR_PATH          "dev/gpio-hal-arch.h"
+#define GPIO_HAL_CONF_ARCH_SW_TOGGLE         1
+#define GPIO_HAL_CONF_PORT_PIN_NUMBERING     0
 /*---------------------------------------------------------------------------*/
 #endif /* CC2538_DEF_H_ */
 /*---------------------------------------------------------------------------*/
diff --git a/arch/cpu/cc2538/dev/cc2538-rf.c b/arch/cpu/cc2538/dev/cc2538-rf.c
index bddfcc9422b1ca8519322961ab7cc2910ae1c004..e1bbfbfd140bc8e30db67f0b3d6fd91e54ff320e 100644
--- a/arch/cpu/cc2538/dev/cc2538-rf.c
+++ b/arch/cpu/cc2538/dev/cc2538-rf.c
@@ -140,6 +140,8 @@ static const output_config_t output_power[] = {
   {-24, 0x00 },
 };
 
+static radio_result_t get_value(radio_param_t param, radio_value_t *value);
+
 #define OUTPUT_CONFIG_COUNT (sizeof(output_power) / sizeof(output_config_t))
 
 /* Max and Min Output Power in dBm */
@@ -394,6 +396,48 @@ get_sfd_timestamp(void)
   return RTIMER_NOW() - RADIO_TO_RTIMER(timer_val - sfd);
 }
 /*---------------------------------------------------------------------------*/
+/* Enable or disable radio test mode emmiting modulated or unmodulated
+ * (carrier) signal. See User's Guide pages 719 and 741.
+ */
+static uint32_t prev_FRMCTRL0, prev_MDMTEST1;
+static uint8_t was_on;
+
+static void
+set_test_mode(uint8_t enable, uint8_t modulated)
+{
+  radio_value_t mode;
+  get_value(RADIO_PARAM_POWER_MODE, &mode);
+
+  if(enable) {
+    if(mode == RADIO_POWER_MODE_CARRIER_ON) {
+      return;
+    }
+    was_on = (mode == RADIO_POWER_MODE_ON);
+    off();
+    prev_FRMCTRL0 = REG(RFCORE_XREG_FRMCTRL0);
+    /* This constantly transmits random data */
+    REG(RFCORE_XREG_FRMCTRL0) = 0x00000042;
+    if(!modulated) {
+      prev_MDMTEST1 = REG(RFCORE_XREG_MDMTEST1);
+      /* ...adding this we send an unmodulated carrier instead */
+      REG(RFCORE_XREG_MDMTEST1) = 0x00000018;
+    }
+    CC2538_RF_CSP_ISTXON();
+  } else {
+    if(mode != RADIO_POWER_MODE_CARRIER_ON) {
+      return;
+    }
+    CC2538_RF_CSP_ISRFOFF();
+    REG(RFCORE_XREG_FRMCTRL0) = prev_FRMCTRL0;
+    if(!modulated) {
+      REG(RFCORE_XREG_MDMTEST1) = prev_MDMTEST1;
+    }
+    if(was_on) {
+      on();
+    }
+  }
+}
+/*---------------------------------------------------------------------------*/
 /* Netstack API radio driver functions */
 /*---------------------------------------------------------------------------*/
 static int
@@ -556,6 +600,10 @@ prepare(const void *payload, unsigned short payload_len)
 {
   uint8_t i;
 
+  if(payload_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
+    return RADIO_TX_ERR;
+  }
+
   LOG_INFO("Prepare 0x%02x bytes\n", payload_len + CHECKSUM_LEN);
 
   /*
@@ -617,6 +665,10 @@ transmit(unsigned short transmit_len)
 
   LOG_INFO("Transmit\n");
 
+  if(transmit_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
+    return RADIO_TX_ERR;
+  }
+
   if(!(rf_flags & RX_ACTIVE)) {
     t0 = RTIMER_NOW();
     on();
@@ -806,8 +858,12 @@ get_value(radio_param_t param, radio_value_t *value)
 
   switch(param) {
   case RADIO_PARAM_POWER_MODE:
-    *value = (REG(RFCORE_XREG_RXENABLE) && RFCORE_XREG_RXENABLE_RXENMASK) == 0
-      ? RADIO_POWER_MODE_OFF : RADIO_POWER_MODE_ON;
+    if((REG(RFCORE_XREG_RXENABLE) & RFCORE_XREG_RXENABLE_RXENMASK) == 0) {
+      *value = RADIO_POWER_MODE_OFF;
+    } else {
+      *value = (REG(RFCORE_XREG_FRMCTRL0) & RFCORE_XREG_FRMCTRL0_TX_MODE) == 0
+        ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_CARRIER_ON;
+    }
     return RADIO_RESULT_OK;
   case RADIO_PARAM_CHANNEL:
     *value = (radio_value_t)get_channel();
@@ -896,6 +952,11 @@ set_value(radio_param_t param, radio_value_t value)
       off();
       return RADIO_RESULT_OK;
     }
+    if(value == RADIO_POWER_MODE_CARRIER_ON ||
+       value == RADIO_POWER_MODE_CARRIER_OFF) {
+      set_test_mode((value == RADIO_POWER_MODE_CARRIER_ON), 0);
+      return RADIO_RESULT_OK;
+    }
     return RADIO_RESULT_INVALID_VALUE;
   case RADIO_PARAM_CHANNEL:
     if(value < CC2538_RF_CHANNEL_MIN ||
@@ -978,6 +1039,7 @@ get_object(radio_param_t param, void *dest, size_t size)
     if(size != sizeof(uint16_t *) || !dest) {
       return RADIO_RESULT_INVALID_VALUE;
     }
+    /* Assigned value: a pointer to the TSCH timing in usec */
     *(const uint16_t **)dest = tsch_timeslot_timing_us_10000;
     return RADIO_RESULT_OK;
   }
diff --git a/arch/cpu/cc2538/dev/gpio-hal-arch.c b/arch/cpu/cc2538/dev/gpio-hal-arch.c
index bd2dfb92d8d57e58c2f9f84fd85a0b2c7beed6b5..8654945d4b09b5487fdf9089e96a183488739a02 100644
--- a/arch/cpu/cc2538/dev/gpio-hal-arch.c
+++ b/arch/cpu/cc2538/dev/gpio-hal-arch.c
@@ -45,7 +45,7 @@
 #include <stdint.h>
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg)
+gpio_hal_arch_no_port_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg)
 {
   uint8_t port, pin_num, pin_mask;
   uint32_t port_base;
@@ -94,7 +94,7 @@ gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg)
 }
 /*---------------------------------------------------------------------------*/
 gpio_hal_pin_cfg_t
-gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin)
+gpio_hal_arch_no_port_pin_cfg_get(gpio_hal_pin_t pin)
 {
   uint8_t port, pin_num, pin_mask;
   uint32_t port_base;
@@ -145,17 +145,17 @@ gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_write_pin(gpio_hal_pin_t pin, uint8_t value)
+gpio_hal_arch_no_port_write_pin(gpio_hal_pin_t pin, uint8_t value)
 {
   if(value == 1) {
-    gpio_hal_arch_set_pin(pin);
+    gpio_hal_arch_set_pin(GPIO_HAL_NULL_PORT, pin);
     return;
   }
-  gpio_hal_arch_clear_pin(pin);
+  gpio_hal_arch_clear_pin(GPIO_HAL_NULL_PORT, pin);
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_set_pins(gpio_hal_pin_mask_t pins)
+gpio_hal_arch_no_port_set_pins(gpio_hal_pin_mask_t pins)
 {
   GPIO_SET_PIN(GPIO_A_BASE, pins & 0xFF);
   GPIO_SET_PIN(GPIO_B_BASE, (pins >> 8) & 0xFF);
@@ -164,7 +164,7 @@ gpio_hal_arch_set_pins(gpio_hal_pin_mask_t pins)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_clear_pins(gpio_hal_pin_mask_t pins)
+gpio_hal_arch_no_port_clear_pins(gpio_hal_pin_mask_t pins)
 {
   GPIO_CLR_PIN(GPIO_A_BASE, pins & 0xFF);
   GPIO_CLR_PIN(GPIO_B_BASE, (pins >> 8) & 0xFF);
@@ -173,7 +173,7 @@ gpio_hal_arch_clear_pins(gpio_hal_pin_mask_t pins)
 }
 /*---------------------------------------------------------------------------*/
 gpio_hal_pin_mask_t
-gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins)
+gpio_hal_arch_no_port_read_pins(gpio_hal_pin_mask_t pins)
 {
   gpio_hal_pin_mask_t rv = 0;
 
@@ -186,7 +186,8 @@ gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_write_pins(gpio_hal_pin_mask_t pins, gpio_hal_pin_mask_t value)
+gpio_hal_arch_no_port_write_pins(gpio_hal_pin_mask_t pins,
+                                 gpio_hal_pin_mask_t value)
 {
   GPIO_WRITE_PIN(GPIO_A_BASE, pins & 0xFF, value & 0xFF);
   GPIO_WRITE_PIN(GPIO_B_BASE, (pins >> 8) & 0xFF, (value >> 8) & 0xFF);
diff --git a/arch/cpu/cc2538/dev/gpio-hal-arch.h b/arch/cpu/cc2538/dev/gpio-hal-arch.h
index ad2f24219e5704c281e430a084ed14e0675df1ca..5d8db3ce8534433e8ff6b713b87d0537c9e8e3d1 100644
--- a/arch/cpu/cc2538/dev/gpio-hal-arch.h
+++ b/arch/cpu/cc2538/dev/gpio-hal-arch.h
@@ -58,31 +58,31 @@
 /*---------------------------------------------------------------------------*/
 #define gpio_hal_arch_init() do { /* Do nothing */ } while(0)
 
-#define gpio_hal_arch_interrupt_enable(p) do { \
+#define gpio_hal_arch_interrupt_enable(port, p) do { \
   GPIO_ENABLE_INTERRUPT(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \
   NVIC_EnableIRQ(PIN_TO_PORT(p)); \
 } while(0);
 
-#define gpio_hal_arch_interrupt_disable(p) \
+#define gpio_hal_arch_interrupt_disable(port, p) \
   GPIO_DISABLE_INTERRUPT(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8))
 
-#define gpio_hal_arch_pin_set_input(p) do { \
+#define gpio_hal_arch_pin_set_input(port, p) do { \
   GPIO_SOFTWARE_CONTROL(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \
   GPIO_SET_INPUT(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \
 } while(0);
 
-#define gpio_hal_arch_pin_set_output(p) do { \
+#define gpio_hal_arch_pin_set_output(port, p) do { \
   GPIO_SOFTWARE_CONTROL(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \
   GPIO_SET_OUTPUT(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)); \
 } while(0);
 
-#define gpio_hal_arch_set_pin(p) \
+#define gpio_hal_arch_set_pin(port, p) \
   GPIO_SET_PIN(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8))
 
-#define gpio_hal_arch_clear_pin(p) \
+#define gpio_hal_arch_clear_pin(port, p) \
   GPIO_CLR_PIN(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8))
 
-#define gpio_hal_arch_read_pin(p) \
+#define gpio_hal_arch_read_pin(port, p) \
   (GPIO_READ_PIN(PIN_TO_PORT_BASE(p), GPIO_PIN_MASK((p) % 8)) == 0 ? 0 : 1)
 /*---------------------------------------------------------------------------*/
 #endif /* GPIO_HAL_ARCH_H_ */
diff --git a/arch/cpu/cc2538/usb/usb-arch.c b/arch/cpu/cc2538/usb/usb-arch.c
index 43da33946baa9c323bd608bafc43c6f07e6ea0ac..cacec7d4c1ea905b287f8980932fbec6dd2b34c0 100644
--- a/arch/cpu/cc2538/usb/usb-arch.c
+++ b/arch/cpu/cc2538/usb/usb-arch.c
@@ -1114,13 +1114,8 @@ ep_tx(uint8_t ep_hw)
     len -= copy;
     ep->buffer->left -= copy;
 
-    /*
-     * Delay somewhat if the previous packet has not yet left the IN FIFO,
-     * making sure the dog doesn't bark while we're waiting
-     */
-    while(REG(USB_CSIL) & USB_CSIL_INPKT_RDY) {
-      watchdog_periodic();
-    }
+    /* Delay somewhat if the previous packet has not yet left the IN FIFO */
+    while(REG(USB_CSIL) & USB_CSIL_INPKT_RDY);
 
     write_hw_buffer(EP_INDEX(ep_hw), ep->buffer->data, copy);
     ep->buffer->data += copy;
diff --git a/arch/cpu/cc26xx-cc13xx/Makefile.cc13xx b/arch/cpu/cc26x0-cc13x0/Makefile.cc13x0
similarity index 80%
rename from arch/cpu/cc26xx-cc13xx/Makefile.cc13xx
rename to arch/cpu/cc26x0-cc13x0/Makefile.cc13x0
index 5ea92e30c404fac49cca76ceabc83b71cb1bef30..c29ee727073138191592e00614d1dfc899681719 100644
--- a/arch/cpu/cc26xx-cc13xx/Makefile.cc13xx
+++ b/arch/cpu/cc26x0-cc13x0/Makefile.cc13x0
@@ -4,4 +4,4 @@ CONTIKI_CPU_SOURCEFILES += smartrf-settings.c prop-mode.c prop-mode-tx-power.c c
 
 CFLAGS += -DCPU_FAMILY_CC13X0=1 -DCPU_FAMILY_CC13XX=1
 
-include $(CONTIKI_CPU)/Makefile.cc26xx-cc13xx
+include $(CONTIKI_CPU)/Makefile.cc26x0-cc13x0
diff --git a/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx b/arch/cpu/cc26x0-cc13x0/Makefile.cc26x0
similarity index 65%
rename from arch/cpu/cc26xx-cc13xx/Makefile.cc26xx
rename to arch/cpu/cc26x0-cc13x0/Makefile.cc26x0
index 34a147f7b9b7d5df7811533b26e9aab15e8b9bc7..51db3f2052a5f9764da5b655742dbf2efc5b32bd 100644
--- a/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx
+++ b/arch/cpu/cc26x0-cc13x0/Makefile.cc26x0
@@ -2,4 +2,4 @@ TI_XXWARE_PATH = lib/cc26xxware
 
 CFLAGS += -DCPU_FAMILY_CC26X0=1 -DCPU_FAMILY_CC26XX=1
 
-include $(CONTIKI_CPU)/Makefile.cc26xx-cc13xx
+include $(CONTIKI_CPU)/Makefile.cc26x0-cc13x0
diff --git a/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx b/arch/cpu/cc26x0-cc13x0/Makefile.cc26x0-cc13x0
similarity index 94%
rename from arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx
rename to arch/cpu/cc26x0-cc13x0/Makefile.cc26x0-cc13x0
index 94f4e51119d4f1ef9caf808254b385b01200af6b..19da237ae9da20bcbbee93f20b304b531859660e 100644
--- a/arch/cpu/cc26xx-cc13xx/Makefile.cc26xx-cc13xx
+++ b/arch/cpu/cc26x0-cc13x0/Makefile.cc26x0-cc13x0
@@ -1,4 +1,4 @@
-CPU_ABS_PATH       = arch/cpu/cc26xx-cc13xx
+CPU_ABS_PATH       = arch/cpu/cc26x0-cc13x0
 TI_XXWARE = $(CONTIKI_CPU)/$(TI_XXWARE_PATH)
 
 ifeq (,$(wildcard $(TI_XXWARE)/*))
@@ -24,7 +24,7 @@ CFLAGS += -I$(TI_XXWARE) -I$(CONTIKI)/$(TI_XXWARE_SRC)
 CFLAGS += -I$(TI_XXWARE)/inc
 MODULES += $(TI_XXWARE_SRC)
 
-LDSCRIPT = $(CONTIKI_CPU)/cc26xx.ld
+LDSCRIPT ?= $(CONTIKI_CPU)/cc26xx.ld
 
 ### If the user-specified a Node ID, pass a define
 ifdef NODEID
@@ -44,6 +44,7 @@ CONTIKI_CPU_SOURCEFILES += rf-core.c rf-ble.c ieee-mode.c
 CONTIKI_CPU_SOURCEFILES += ble-cc2650.c ble-hal-cc26xx.c ble-addr.c rf-ble-cmd.c
 CONTIKI_CPU_SOURCEFILES += random.c soc-trng.c int-master.c
 CONTIKI_CPU_SOURCEFILES += spi-arch.c
+CONTIKI_CPU_SOURCEFILES += cc26xx-aes.c
 
 CONTIKI_SOURCEFILES += $(CONTIKI_CPU_SOURCEFILES)
 
@@ -81,7 +82,7 @@ STACK_SIZE = 0
 	@$(SIZE) -A $< | egrep "data|bss" | awk '{s+=$$2} END {s=s+$(STACK_SIZE); f=$(RAM_SIZE)-s; printf "[RAM]   used %6d, free %6d\n",s,f;}'
 	@$(SIZE) -A $< | egrep "text|isr_vector" | awk '{s+=$$2} END {f=$(FLASH_SIZE)-s; printf "[Flash] used %6d, free %6d\n",s,f;}'
 
-include $(CONTIKI)/arch/cpu/arm/cortex-m/cm3/Makefile.cm3
+include $(ARCH_PATH)/cpu/arm/cortex-m/cm3/Makefile.cm3
 
 ifeq ($(BOARD_SUPPORTS_BSL),1)
 %.upload: $(OUT_BIN)
@@ -96,4 +97,4 @@ else
 endif
 
 ### For the login etc targets
-BAUDRATE = 115200
+BAUDRATE ?= 115200
diff --git a/arch/cpu/cc26xx-cc13xx/Makefile.cc26x0r2f b/arch/cpu/cc26x0-cc13x0/Makefile.cc26x0r2f
similarity index 67%
rename from arch/cpu/cc26xx-cc13xx/Makefile.cc26x0r2f
rename to arch/cpu/cc26x0-cc13x0/Makefile.cc26x0r2f
index 56d0415166c20d92df25c4e171abd076b847c926..5118cd6a8e05da7bb16cf3d89a0d0206ef238719 100644
--- a/arch/cpu/cc26xx-cc13xx/Makefile.cc26x0r2f
+++ b/arch/cpu/cc26x0-cc13x0/Makefile.cc26x0r2f
@@ -2,4 +2,4 @@ TI_XXWARE_PATH = lib/cc2640r2-sdk
 
 CFLAGS += -DCPU_FAMILY_CC26X0R2=1 -DCPU_FAMILY_CC26XXR2=1
 
-include $(CONTIKI_CPU)/Makefile.cc26xx-cc13xx
+include $(CONTIKI_CPU)/Makefile.cc26x0-cc13x0
diff --git a/arch/cpu/cc26xx-cc13xx/ble-addr.c b/arch/cpu/cc26x0-cc13x0/ble-addr.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/ble-addr.c
rename to arch/cpu/cc26x0-cc13x0/ble-addr.c
diff --git a/arch/cpu/cc26xx-cc13xx/ble-addr.h b/arch/cpu/cc26x0-cc13x0/ble-addr.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/ble-addr.h
rename to arch/cpu/cc26x0-cc13x0/ble-addr.h
diff --git a/arch/cpu/cc26xx-cc13xx/cc13x0-cc26x0-cm3.h b/arch/cpu/cc26x0-cc13x0/cc13x0-cc26x0-cm3.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/cc13x0-cc26x0-cm3.h
rename to arch/cpu/cc26x0-cc13x0/cc13x0-cc26x0-cm3.h
diff --git a/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-conf.h b/arch/cpu/cc26x0-cc13x0/cc13xx-cc26xx-conf.h
similarity index 94%
rename from arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-conf.h
rename to arch/cpu/cc26x0-cc13x0/cc13xx-cc26xx-conf.h
index 7400c5ad9bd4fa5e7b7ee53552c3633c1452c777..8b8ea38795b2917fe8602879197b0224982dac33 100644
--- a/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-conf.h
+++ b/arch/cpu/cc26x0-cc13x0/cc13xx-cc26xx-conf.h
@@ -100,7 +100,17 @@
 #define CSMA_CONF_SEND_SOFT_ACK              0
 #endif /* CC13XX_CONF_PROP_MODE */
 
-#define NETSTACK_RADIO_MAX_PAYLOAD_LEN        125
+/* Platform-specific (H/W) AES implementation */
+#ifndef AES_128_CONF
+#define AES_128_CONF cc26xx_aes_128_driver
+#endif /* AES_128_CONF */
+
+/* This is fixed */
+#define ieee_mode_driver_max_payload_len      125
+/* This maybe changed in the future, with software upgrade */
+#define prop_mode_driver_max_payload_len      125
+/* This is not used, but needs to be defined in order to compile */
+#define ble_cc2650_driver_max_payload_len    125
 
 /** @} */
 /*---------------------------------------------------------------------------*/
diff --git a/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-def.h b/arch/cpu/cc26x0-cc13x0/cc13xx-cc26xx-def.h
similarity index 96%
rename from arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-def.h
rename to arch/cpu/cc26x0-cc13x0/cc13xx-cc26xx-def.h
index 97b188e1574c46d1d1bf10c914d95a9298aa3fb7..302becc3ff3cc43398e6488aa958656cc90fc876 100644
--- a/arch/cpu/cc26xx-cc13xx/cc13xx-cc26xx-def.h
+++ b/arch/cpu/cc26x0-cc13x0/cc13xx-cc26xx-def.h
@@ -133,13 +133,14 @@
 /* Path to CMSIS header */
 #define CMSIS_CONF_HEADER_PATH               "cc13x0-cc26x0-cm3.h"
 
-/* Path to headers with implementation of mutexes and memory barriers */
+/* Path to headers with implementation of mutexes, atomic and memory barriers */
 #define MUTEX_CONF_ARCH_HEADER_PATH          "mutex-cortex.h"
+#define ATOMIC_CONF_ARCH_HEADER_PATH         "atomic-cortex.h"
 #define MEMORY_BARRIER_CONF_ARCH_HEADER_PATH "memory-barrier-cortex.h"
-
-#define GPIO_HAL_CONF_ARCH_HDR_PATH          "dev/gpio-hal-arch.h"
 /*---------------------------------------------------------------------------*/
-#define GPIO_HAL_CONF_ARCH_SW_TOGGLE 0
+#define GPIO_HAL_CONF_ARCH_HDR_PATH          "dev/gpio-hal-arch.h"
+#define GPIO_HAL_CONF_ARCH_SW_TOGGLE         0
+#define GPIO_HAL_CONF_PORT_PIN_NUMBERING     0
 /*---------------------------------------------------------------------------*/
 #define SPI_CONF_CONTROLLER_COUNT    2
 /*---------------------------------------------------------------------------*/
diff --git a/arch/cpu/cc26xx-cc13xx/cc26xx.ld b/arch/cpu/cc26x0-cc13x0/cc26xx.ld
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/cc26xx.ld
rename to arch/cpu/cc26x0-cc13x0/cc26xx.ld
diff --git a/arch/cpu/cc26xx-cc13xx/ccxxware-conf.h b/arch/cpu/cc26x0-cc13x0/ccxxware-conf.h
similarity index 98%
rename from arch/cpu/cc26xx-cc13xx/ccxxware-conf.h
rename to arch/cpu/cc26x0-cc13x0/ccxxware-conf.h
index bc26f11710c8b26b14870ca2bba793a8ff9d6b57..c101deb08be8f16b56458f7ad780186ed8ea60fa 100644
--- a/arch/cpu/cc26xx-cc13xx/ccxxware-conf.h
+++ b/arch/cpu/cc26x0-cc13x0/ccxxware-conf.h
@@ -36,7 +36,7 @@
  * @{
  *
  * \file
- *  CCxxware-specific configuration for the cc26xx-cc13xx CPU family
+ *  CCxxware-specific configuration for the cc26x0-cc13x0 CPU family
  */
 #ifndef CCXXWARE_CONF_H_
 #define CCXXWARE_CONF_H_
diff --git a/arch/cpu/cc26xx-cc13xx/clock.c b/arch/cpu/cc26x0-cc13x0/clock.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/clock.c
rename to arch/cpu/cc26x0-cc13x0/clock.c
diff --git a/arch/cpu/cc26xx-cc13xx/dbg.c b/arch/cpu/cc26x0-cc13x0/dbg.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dbg.c
rename to arch/cpu/cc26x0-cc13x0/dbg.c
diff --git a/arch/cpu/cc26xx-cc13xx/dev/adc-sensor.c b/arch/cpu/cc26x0-cc13x0/dev/adc-sensor.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/adc-sensor.c
rename to arch/cpu/cc26x0-cc13x0/dev/adc-sensor.c
diff --git a/arch/cpu/cc26xx-cc13xx/dev/adc-sensor.h b/arch/cpu/cc26x0-cc13x0/dev/adc-sensor.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/adc-sensor.h
rename to arch/cpu/cc26x0-cc13x0/dev/adc-sensor.h
diff --git a/arch/cpu/cc26xx-cc13xx/dev/aux-ctrl.c b/arch/cpu/cc26x0-cc13x0/dev/aux-ctrl.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/aux-ctrl.c
rename to arch/cpu/cc26x0-cc13x0/dev/aux-ctrl.c
diff --git a/arch/cpu/cc26xx-cc13xx/dev/aux-ctrl.h b/arch/cpu/cc26x0-cc13x0/dev/aux-ctrl.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/aux-ctrl.h
rename to arch/cpu/cc26x0-cc13x0/dev/aux-ctrl.h
diff --git a/arch/cpu/cc26xx-cc13xx/dev/batmon-sensor.c b/arch/cpu/cc26x0-cc13x0/dev/batmon-sensor.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/batmon-sensor.c
rename to arch/cpu/cc26x0-cc13x0/dev/batmon-sensor.c
diff --git a/arch/cpu/cc26xx-cc13xx/dev/batmon-sensor.h b/arch/cpu/cc26x0-cc13x0/dev/batmon-sensor.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/batmon-sensor.h
rename to arch/cpu/cc26x0-cc13x0/dev/batmon-sensor.h
diff --git a/arch/cpu/cc26x0-cc13x0/dev/cc26xx-aes.c b/arch/cpu/cc26x0-cc13x0/dev/cc26xx-aes.c
new file mode 100755
index 0000000000000000000000000000000000000000..cacdfc61f90a00dc4fffd51a805eac12fed69cb7
--- /dev/null
+++ b/arch/cpu/cc26x0-cc13x0/dev/cc26xx-aes.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2016, University of Bristol - http://www.bristol.ac.uk
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup cc26xx-aes
+ * @{
+ *
+ * \file
+ *         Implementation of the AES driver for the CC26x0/CC13x0 SoC
+ * \author
+ *         Atis Elsts <atis.elsts@gmail.com>
+ */
+#include "contiki.h"
+#include "dev/cc26xx-aes.h"
+#include "ti-lib.h"
+/*---------------------------------------------------------------------------*/
+#include "sys/log.h"
+#define LOG_MODULE "cc26xx-aes"
+#define LOG_LEVEL LOG_LEVEL_MAIN
+/*---------------------------------------------------------------------------*/
+static uint32_t skey[AES_128_KEY_LENGTH / sizeof(uint32_t)];
+
+/*---------------------------------------------------------------------------*/
+void
+cc26xx_aes_set_key(const uint8_t *key)
+{
+  memcpy(skey, key, AES_128_KEY_LENGTH);
+}
+/*---------------------------------------------------------------------------*/
+static void
+encrypt_decrypt(uint8_t *plaintext_and_result, bool do_encrypt)
+{
+  uint32_t result[AES_128_BLOCK_SIZE / sizeof(uint32_t)];
+  unsigned status;
+  int i;
+
+  /* First, make sure the PERIPH PD is on */
+  ti_lib_prcm_power_domain_on(PRCM_DOMAIN_PERIPH);
+  while((ti_lib_prcm_power_domain_status(PRCM_DOMAIN_PERIPH)
+          != PRCM_DOMAIN_POWER_ON));
+
+  /* Enable CRYPTO peripheral */
+  ti_lib_prcm_peripheral_run_enable(PRCM_PERIPH_CRYPTO);
+  ti_lib_prcm_load_set();
+  while(!ti_lib_prcm_load_get());
+
+  status = ti_lib_crypto_aes_load_key(skey, CRYPTO_KEY_AREA_0);
+  if(status != AES_SUCCESS) {
+    LOG_WARN("load key failed: %u\n", status);
+  } else {
+
+    status = ti_lib_crypto_aes_ecb((uint32_t *)plaintext_and_result, result, CRYPTO_KEY_AREA_0, do_encrypt, false);
+    if(status != AES_SUCCESS) {
+      LOG_WARN("ecb failed: %u\n", status);
+    } else {
+
+      for(i = 0; i < 100; ++i) {
+        ti_lib_cpu_delay(10);
+        status = ti_lib_crypto_aes_ecb_status();
+        if(status != AES_DMA_BSY) {
+          break;
+        }
+      }
+
+      ti_lib_crypto_aes_ecb_finish();
+
+      if(status != AES_SUCCESS) {
+        LOG_WARN("ecb get result failed: %u\n", status);
+      }
+    }
+  }
+
+  ti_lib_prcm_peripheral_run_disable(PRCM_PERIPH_CRYPTO);
+  ti_lib_prcm_load_set();
+  while(!ti_lib_prcm_load_get());
+
+  if(status == AES_SUCCESS) {
+    memcpy(plaintext_and_result, result, AES_128_BLOCK_SIZE);
+  } else {
+    /* corrupt the result */
+    plaintext_and_result[0] ^= 1;
+  }
+}
+/*---------------------------------------------------------------------------*/
+void
+cc26xx_aes_encrypt(uint8_t *plaintext_and_result)
+{
+  encrypt_decrypt(plaintext_and_result, true);
+}
+/*---------------------------------------------------------------------------*/
+void
+cc26xx_aes_decrypt(uint8_t *cyphertext_and_result)
+{
+  encrypt_decrypt(cyphertext_and_result, false);
+}
+/*---------------------------------------------------------------------------*/
+const struct aes_128_driver cc26xx_aes_128_driver = {
+  cc26xx_aes_set_key,
+  cc26xx_aes_encrypt
+};
+
+/** @} */
diff --git a/arch/cpu/cc26x0-cc13x0/dev/cc26xx-aes.h b/arch/cpu/cc26x0-cc13x0/dev/cc26xx-aes.h
new file mode 100755
index 0000000000000000000000000000000000000000..a979cc5624312ade1d114d7acf2c8fa150c4faab
--- /dev/null
+++ b/arch/cpu/cc26x0-cc13x0/dev/cc26xx-aes.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2016, University of Bristol - http://www.bristol.ac.uk
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup cc26xx
+ * @{
+ *
+ * \defgroup cc26xx-aes CC26x0/CC13x0 AES-128
+ *
+ * AES-128 driver for the CC26x0/CC13x0 SoC
+ * @{
+ *
+ * \file
+ *         Header file of the AES-128 driver for the CC26xx SoC
+ * \author
+ *         Atis Elsts <atis.elsts@gmail.com>
+ */
+#ifndef CC2538_AES_H_
+#define CC2538_AES_H_
+
+#include "lib/aes-128.h"
+
+/**
+ * \brief Set a key to use in subsequent encryption & decryption operations.
+ * \param key The key to use
+ *
+ * The size of the key must be AES_128_KEY_LENGTH.
+ */
+void cc26xx_aes_set_key(const uint8_t *key);
+
+/**
+ * \brief Encrypt a message using the SoC AES-128 hardware implementation
+ * \param plaintext_and_result In: message to encrypt, out: the encrypted message.
+ *
+ * The size of the message must be AES_128_BLOCK_SIZE.
+ * The key to use in the encryption must be set before calling this function.
+ */
+void cc26xx_aes_encrypt(uint8_t *plaintext_and_result);
+
+/**
+ * \brief Decrypt a message using the SoC AES-128 hardware implementation
+ * \param cyphertext_and_result In: message to decrypt, out: the decrypted message.
+ *
+ * The size of the message must be AES_128_BLOCK_SIZE.
+ * The key to use in the decryption must be set before calling this function.
+ */
+void cc26xx_aes_decrypt(uint8_t *cyphertext_and_result);
+
+extern const struct aes_128_driver cc26xx_aes_128_driver;
+
+#endif /* CC2538_AES_H_ */
+/**
+ * @}
+ * @}
+ */
diff --git a/arch/cpu/cc26xx-cc13xx/dev/cc26xx-uart.c b/arch/cpu/cc26x0-cc13x0/dev/cc26xx-uart.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/cc26xx-uart.c
rename to arch/cpu/cc26x0-cc13x0/dev/cc26xx-uart.c
diff --git a/arch/cpu/cc26xx-cc13xx/dev/cc26xx-uart.h b/arch/cpu/cc26x0-cc13x0/dev/cc26xx-uart.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/cc26xx-uart.h
rename to arch/cpu/cc26x0-cc13x0/dev/cc26xx-uart.h
diff --git a/arch/cpu/cc26xx-cc13xx/dev/contiki-watchdog.c b/arch/cpu/cc26x0-cc13x0/dev/contiki-watchdog.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/contiki-watchdog.c
rename to arch/cpu/cc26x0-cc13x0/dev/contiki-watchdog.c
diff --git a/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.c b/arch/cpu/cc26x0-cc13x0/dev/gpio-hal-arch.c
similarity index 95%
rename from arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.c
rename to arch/cpu/cc26x0-cc13x0/dev/gpio-hal-arch.c
index 4fd4f768849084e81e3e3e4fa81274f5a69b90ce..8e3d0c783ccf739dc7350bc72c4ea6ace9ed8154 100644
--- a/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.c
+++ b/arch/cpu/cc26x0-cc13x0/dev/gpio-hal-arch.c
@@ -46,7 +46,7 @@
 #define CONFIG_MASK (IOC_IOPULL_M | IOC_INT_M | IOC_IOMODE_OPEN_SRC_INV)
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg)
+gpio_hal_arch_no_port_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg)
 {
   uint32_t config;
   gpio_hal_pin_cfg_t tmp;
@@ -86,7 +86,7 @@ gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg)
 }
 /*---------------------------------------------------------------------------*/
 gpio_hal_pin_cfg_t
-gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin)
+gpio_hal_arch_no_port_pin_cfg_get(gpio_hal_pin_t pin)
 {
   gpio_hal_pin_cfg_t cfg;
   uint32_t tmp;
@@ -129,7 +129,7 @@ gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin)
 }
 /*---------------------------------------------------------------------------*/
 gpio_hal_pin_mask_t
-gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins)
+gpio_hal_arch_no_port_read_pins(gpio_hal_pin_mask_t pins)
 {
   gpio_hal_pin_mask_t oe_pins;
 
@@ -143,7 +143,7 @@ gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins)
 }
 /*---------------------------------------------------------------------------*/
 uint8_t
-gpio_hal_arch_read_pin(gpio_hal_pin_t pin)
+gpio_hal_arch_no_port_read_pin(gpio_hal_pin_t pin)
 {
   if(ti_lib_gpio_get_output_enable_dio(pin)) {
     return (HWREG(GPIO_BASE + GPIO_O_DOUT31_0) >> pin) & 1;
diff --git a/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.h b/arch/cpu/cc26x0-cc13x0/dev/gpio-hal-arch.h
similarity index 73%
rename from arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.h
rename to arch/cpu/cc26x0-cc13x0/dev/gpio-hal-arch.h
index 3997c1062a2205599943b8e6e1725bada2dd1b1d..d142eefab5b7bb7e0ded6f335e44b16627afedf1 100644
--- a/arch/cpu/cc26xx-cc13xx/dev/gpio-hal-arch.h
+++ b/arch/cpu/cc26x0-cc13x0/dev/gpio-hal-arch.h
@@ -54,21 +54,21 @@
 /*---------------------------------------------------------------------------*/
 #define gpio_hal_arch_init()               do { /* Do nothing */ } while(0)
 
-#define gpio_hal_arch_interrupt_enable(p)  interrupt_enable(p)
+#define gpio_hal_arch_interrupt_enable(port, pin)  interrupt_enable(pin)
+#define gpio_hal_arch_interrupt_disable(port, pin) ti_lib_ioc_int_disable(pin)
 
-#define gpio_hal_arch_interrupt_disable(p) ti_lib_ioc_int_disable(p)
-#define gpio_hal_arch_pin_set_input(p)     ti_lib_ioc_pin_type_gpio_input(p)
-#define gpio_hal_arch_pin_set_output(p)    ti_lib_ioc_pin_type_gpio_output(p)
+#define gpio_hal_arch_pin_set_input(port, pin)     ti_lib_ioc_pin_type_gpio_input(pin)
+#define gpio_hal_arch_pin_set_output(port, pin)    ti_lib_ioc_pin_type_gpio_output(pin)
 
-#define gpio_hal_arch_set_pin(p)           ti_lib_gpio_set_dio(p)
-#define gpio_hal_arch_clear_pin(p)         ti_lib_gpio_clear_dio(p)
-#define gpio_hal_arch_toggle_pin(p)        ti_lib_gpio_toggle_dio(p)
-#define gpio_hal_arch_write_pin(p, v)      ti_lib_gpio_write_dio(p, v)
+#define gpio_hal_arch_set_pin(port, pin)           ti_lib_gpio_set_dio(pin)
+#define gpio_hal_arch_clear_pin(port, pin)         ti_lib_gpio_clear_dio(pin)
+#define gpio_hal_arch_toggle_pin(port, pin)        ti_lib_gpio_toggle_dio(pin)
+#define gpio_hal_arch_write_pin(port, pin, v)      ti_lib_gpio_write_dio(pin, v)
 
-#define gpio_hal_arch_set_pins(p)          ti_lib_gpio_set_multi_dio(p)
-#define gpio_hal_arch_clear_pins(p)        ti_lib_gpio_clear_multi_dio(p)
-#define gpio_hal_arch_toggle_pins(p)       ti_lib_gpio_toggle_multi_dio(p)
-#define gpio_hal_arch_write_pins(p, v)     ti_lib_gpio_write_multi_dio(p, v)
+#define gpio_hal_arch_set_pins(port, pin)          ti_lib_gpio_set_multi_dio(pin)
+#define gpio_hal_arch_clear_pins(port, pin)        ti_lib_gpio_clear_multi_dio(pin)
+#define gpio_hal_arch_toggle_pins(port, pin)       ti_lib_gpio_toggle_multi_dio(pin)
+#define gpio_hal_arch_write_pins(port, pin, v)     ti_lib_gpio_write_multi_dio(pin, v)
 /*---------------------------------------------------------------------------*/
 static inline void
 interrupt_enable(gpio_hal_pin_t pin)
diff --git a/arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.c b/arch/cpu/cc26x0-cc13x0/dev/gpio-interrupt.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/gpio-interrupt.c
rename to arch/cpu/cc26x0-cc13x0/dev/gpio-interrupt.c
diff --git a/arch/cpu/cc26xx-cc13xx/dev/oscillators.c b/arch/cpu/cc26x0-cc13x0/dev/oscillators.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/oscillators.c
rename to arch/cpu/cc26x0-cc13x0/dev/oscillators.c
diff --git a/arch/cpu/cc26xx-cc13xx/dev/oscillators.h b/arch/cpu/cc26x0-cc13x0/dev/oscillators.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/oscillators.h
rename to arch/cpu/cc26x0-cc13x0/dev/oscillators.h
diff --git a/arch/cpu/cc26xx-cc13xx/dev/soc-rtc.c b/arch/cpu/cc26x0-cc13x0/dev/soc-rtc.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/soc-rtc.c
rename to arch/cpu/cc26x0-cc13x0/dev/soc-rtc.c
diff --git a/arch/cpu/cc26xx-cc13xx/dev/soc-rtc.h b/arch/cpu/cc26x0-cc13x0/dev/soc-rtc.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/soc-rtc.h
rename to arch/cpu/cc26x0-cc13x0/dev/soc-rtc.h
diff --git a/arch/cpu/cc26xx-cc13xx/dev/soc-trng.c b/arch/cpu/cc26x0-cc13x0/dev/soc-trng.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/soc-trng.c
rename to arch/cpu/cc26x0-cc13x0/dev/soc-trng.c
diff --git a/arch/cpu/cc26xx-cc13xx/dev/soc-trng.h b/arch/cpu/cc26x0-cc13x0/dev/soc-trng.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/soc-trng.h
rename to arch/cpu/cc26x0-cc13x0/dev/soc-trng.h
diff --git a/arch/cpu/cc26xx-cc13xx/dev/spi-arch.c b/arch/cpu/cc26x0-cc13x0/dev/spi-arch.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/dev/spi-arch.c
rename to arch/cpu/cc26x0-cc13x0/dev/spi-arch.c
diff --git a/arch/cpu/cc26xx-cc13xx/doxygen-group.txt b/arch/cpu/cc26x0-cc13x0/doxygen-group.txt
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/doxygen-group.txt
rename to arch/cpu/cc26x0-cc13x0/doxygen-group.txt
diff --git a/arch/cpu/cc26xx-cc13xx/fault-handlers.c b/arch/cpu/cc26x0-cc13x0/fault-handlers.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/fault-handlers.c
rename to arch/cpu/cc26x0-cc13x0/fault-handlers.c
diff --git a/arch/cpu/cc26xx-cc13xx/ieee-addr.c b/arch/cpu/cc26x0-cc13x0/ieee-addr.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/ieee-addr.c
rename to arch/cpu/cc26x0-cc13x0/ieee-addr.c
diff --git a/arch/cpu/cc26xx-cc13xx/ieee-addr.h b/arch/cpu/cc26x0-cc13x0/ieee-addr.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/ieee-addr.h
rename to arch/cpu/cc26x0-cc13x0/ieee-addr.h
diff --git a/arch/cpu/cc26xx-cc13xx/int-master.c b/arch/cpu/cc26x0-cc13x0/int-master.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/int-master.c
rename to arch/cpu/cc26x0-cc13x0/int-master.c
diff --git a/arch/cpu/cc26xx-cc13xx/lib/cc13xxware b/arch/cpu/cc26x0-cc13x0/lib/cc13xxware
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/lib/cc13xxware
rename to arch/cpu/cc26x0-cc13x0/lib/cc13xxware
diff --git a/arch/cpu/cc26xx-cc13xx/lib/cc2640r2-sdk b/arch/cpu/cc26x0-cc13x0/lib/cc2640r2-sdk
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/lib/cc2640r2-sdk
rename to arch/cpu/cc26x0-cc13x0/lib/cc2640r2-sdk
diff --git a/arch/cpu/cc26xx-cc13xx/lib/cc26xxware b/arch/cpu/cc26x0-cc13x0/lib/cc26xxware
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/lib/cc26xxware
rename to arch/cpu/cc26x0-cc13x0/lib/cc26xxware
diff --git a/arch/cpu/cc26xx-cc13xx/lpm.c b/arch/cpu/cc26x0-cc13x0/lpm.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/lpm.c
rename to arch/cpu/cc26x0-cc13x0/lpm.c
diff --git a/arch/cpu/cc26xx-cc13xx/lpm.h b/arch/cpu/cc26x0-cc13x0/lpm.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/lpm.h
rename to arch/cpu/cc26x0-cc13x0/lpm.h
diff --git a/arch/cpu/cc26xx-cc13xx/random.c b/arch/cpu/cc26x0-cc13x0/random.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/random.c
rename to arch/cpu/cc26x0-cc13x0/random.c
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/api/ieee_cmd.h b/arch/cpu/cc26x0-cc13x0/rf-core/api/ieee_cmd.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/api/ieee_cmd.h
rename to arch/cpu/cc26x0-cc13x0/rf-core/api/ieee_cmd.h
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/api/ieee_mailbox.h b/arch/cpu/cc26x0-cc13x0/rf-core/api/ieee_mailbox.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/api/ieee_mailbox.h
rename to arch/cpu/cc26x0-cc13x0/rf-core/api/ieee_mailbox.h
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/ble-cc2650.c b/arch/cpu/cc26x0-cc13x0/rf-core/ble-cc2650.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/ble-cc2650.c
rename to arch/cpu/cc26x0-cc13x0/rf-core/ble-cc2650.c
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/ble-hal-cc26xx.c b/arch/cpu/cc26x0-cc13x0/rf-core/ble-hal/ble-hal-cc26xx.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/ble-hal-cc26xx.c
rename to arch/cpu/cc26x0-cc13x0/rf-core/ble-hal/ble-hal-cc26xx.c
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/ble-hal-cc26xx.h b/arch/cpu/cc26x0-cc13x0/rf-core/ble-hal/ble-hal-cc26xx.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/ble-hal-cc26xx.h
rename to arch/cpu/cc26x0-cc13x0/rf-core/ble-hal/ble-hal-cc26xx.h
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/rf-ble-cmd.c b/arch/cpu/cc26x0-cc13x0/rf-core/ble-hal/rf-ble-cmd.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/rf-ble-cmd.c
rename to arch/cpu/cc26x0-cc13x0/rf-core/ble-hal/rf-ble-cmd.c
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/rf-ble-cmd.h b/arch/cpu/cc26x0-cc13x0/rf-core/ble-hal/rf-ble-cmd.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/rf-ble-cmd.h
rename to arch/cpu/cc26x0-cc13x0/rf-core/ble-hal/rf-ble-cmd.h
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/cc13xx-50kbps-tsch.c b/arch/cpu/cc26x0-cc13x0/rf-core/cc13xx-50kbps-tsch.c
similarity index 97%
rename from arch/cpu/cc26xx-cc13xx/rf-core/cc13xx-50kbps-tsch.c
rename to arch/cpu/cc26x0-cc13x0/rf-core/cc13xx-50kbps-tsch.c
index af76d63e3dd0ee2e5a5bff9ec7dc168172391190..f2874fd0376ce35238a50af288c043832d282b2e 100644
--- a/arch/cpu/cc26xx-cc13xx/rf-core/cc13xx-50kbps-tsch.c
+++ b/arch/cpu/cc26x0-cc13x0/rf-core/cc13xx-50kbps-tsch.c
@@ -57,7 +57,7 @@
 #define CC13XX_TSCH_DEFAULT_TS_TIMESLOT_LENGTH  40000
 
 /* TSCH timeslot timing (microseconds) */
-const uint16_t tsch_timing_cc13xx_50kbps[tsch_ts_elements_count] = {
+const tsch_timeslot_timing_usec tsch_timing_cc13xx_50kbps = {
   CC13XX_TSCH_DEFAULT_TS_CCA_OFFSET,
   CC13XX_TSCH_DEFAULT_TS_CCA,
   CC13XX_TSCH_DEFAULT_TS_TX_OFFSET,
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/cc13xx-50kbps-tsch.h b/arch/cpu/cc26x0-cc13x0/rf-core/cc13xx-50kbps-tsch.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/cc13xx-50kbps-tsch.h
rename to arch/cpu/cc26x0-cc13x0/rf-core/cc13xx-50kbps-tsch.h
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/dot-15-4g.h b/arch/cpu/cc26x0-cc13x0/rf-core/dot-15-4g.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/dot-15-4g.h
rename to arch/cpu/cc26x0-cc13x0/rf-core/dot-15-4g.h
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c b/arch/cpu/cc26x0-cc13x0/rf-core/ieee-mode.c
similarity index 99%
rename from arch/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c
rename to arch/cpu/cc26x0-cc13x0/rf-core/ieee-mode.c
index 9f4021d215bb26b32f7b2bdd4d1413bc040f1197..3b9472f26c1f89acaaf5563edc8ec3a936c24dbe 100644
--- a/arch/cpu/cc26xx-cc13xx/rf-core/ieee-mode.c
+++ b/arch/cpu/cc26x0-cc13x0/rf-core/ieee-mode.c
@@ -767,9 +767,11 @@ init(void)
 static int
 prepare(const void *payload, unsigned short payload_len)
 {
-  int len = MIN(payload_len, TX_BUF_PAYLOAD_LEN);
+  if(payload_len > TX_BUF_PAYLOAD_LEN || payload_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
+    return RADIO_TX_ERR;
+  }
 
-  memcpy(&tx_buf[TX_BUF_HDR_LEN], payload, len);
+  memcpy(&tx_buf[TX_BUF_HDR_LEN], payload, payload_len);
   return 0;
 }
 /*---------------------------------------------------------------------------*/
@@ -784,6 +786,11 @@ transmit(unsigned short transmit_len)
   rtimer_clock_t t0;
   volatile rfc_CMD_IEEE_TX_t cmd;
 
+  if(transmit_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
+    PRINTF("transmit: too long\n");
+    return RADIO_TX_ERR;
+  }
+
   if(!rf_is_on()) {
     was_off = 1;
     if(on() != RF_CORE_CMD_OK) {
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/prop-mode-tx-power.c b/arch/cpu/cc26x0-cc13x0/rf-core/prop-mode-tx-power.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/prop-mode-tx-power.c
rename to arch/cpu/cc26x0-cc13x0/rf-core/prop-mode-tx-power.c
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/prop-mode.c b/arch/cpu/cc26x0-cc13x0/rf-core/prop-mode.c
similarity index 95%
rename from arch/cpu/cc26xx-cc13xx/rf-core/prop-mode.c
rename to arch/cpu/cc26x0-cc13x0/rf-core/prop-mode.c
index 0ce6de5dd98924125cbb8a997c1d261c2c0b14aa..7bee3ff15cbb254cb8a775f922abfcf9d8e68711 100644
--- a/arch/cpu/cc26xx-cc13xx/rf-core/prop-mode.c
+++ b/arch/cpu/cc26x0-cc13x0/rf-core/prop-mode.c
@@ -123,7 +123,9 @@
 
 static int8_t rssi_threshold = PROP_MODE_RSSI_THRESHOLD;
 /*---------------------------------------------------------------------------*/
+#if MAC_CONF_WITH_TSCH
 static volatile uint8_t is_receiving_packet;
+#endif
 /*---------------------------------------------------------------------------*/
 static int on(void);
 static int off(void);
@@ -645,9 +647,6 @@ init(void)
     return RF_CORE_CMD_ERROR;
   }
 
-  /* Enable the "sync word seen" interrupt */
-  ti_lib_rfc_hw_int_enable(RFC_DBELL_RFHWIEN_MDMSOFT);
-
   ENERGEST_ON(ENERGEST_TYPE_LISTEN);
 
   rf_core_primary_mode_register(&mode_prop);
@@ -662,9 +661,11 @@ init(void)
 static int
 prepare(const void *payload, unsigned short payload_len)
 {
-  int len = MIN(payload_len, TX_BUF_PAYLOAD_LEN);
+  if(payload_len > TX_BUF_PAYLOAD_LEN || payload_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
+    return RADIO_TX_ERR;
+  }
 
-  memcpy(&tx_buf[TX_BUF_HDR_LEN], payload, len);
+  memcpy(&tx_buf[TX_BUF_HDR_LEN], payload, payload_len);
   return 0;
 }
 /*---------------------------------------------------------------------------*/
@@ -679,6 +680,11 @@ transmit(unsigned short transmit_len)
   /* Length in .15.4g PHY HDR. Includes the CRC but not the HDR itself */
   uint16_t total_length;
 
+  if(transmit_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
+    PRINTF("transmit: too long\n");
+    return RADIO_TX_ERR;
+  }
+
   if(!rf_is_on()) {
     was_off = 1;
     if(on() != RF_CORE_CMD_OK) {
@@ -722,8 +728,6 @@ transmit(unsigned short transmit_len)
     /* If we enter here, TX actually started */
     ENERGEST_SWITCH(ENERGEST_TYPE_LISTEN, ENERGEST_TYPE_TRANSMIT);
 
-    watchdog_periodic();
-
     /* Idle away while the command is running */
     while((cmd_tx_adv->status & RF_CORE_RADIO_OP_MASKED_STATUS)
           == RF_CORE_RADIO_OP_MASKED_STATUS_RUNNING) {
@@ -822,8 +826,10 @@ read_frame(void *buf, unsigned short buf_len)
   while(entry->status == DATA_ENTRY_STATUS_BUSY
       && RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + (RTIMER_SECOND / 50)));
 
+#if MAC_CONF_WITH_TSCH
   /* Make sure the flag is reset */
   is_receiving_packet = 0;
+#endif
 
   if(entry->status != DATA_ENTRY_STATUS_FINISHED) {
     /* No available data */
@@ -937,6 +943,14 @@ receiving_packet(void)
     return 0;
   }
 
+#if MAC_CONF_WITH_TSCH
+  /*
+   * Under TSCH operation, we rely on "hints" from the MDMSOFT interrupt
+   * flag. This flag is set by the radio upon sync word detection, but it is
+   * not cleared automatically by hardware. We store state in a variable after
+   * first call. The assumption is that the TSCH code will keep calling us
+   * until frame reception has completed, at which point we can clear MDMSOFT.
+   */
   if(!is_receiving_packet) {
     /* Look for the modem synchronization word detection interrupt flag.
      * This flag is raised when the synchronization word is received.
@@ -954,6 +968,34 @@ receiving_packet(void)
   }
 
   return is_receiving_packet;
+#else
+  /*
+   * Under CSMA operation, there is no immediately straightforward logic as to
+   * when it's OK to clear the MDMSOFT interrupt flag:
+   *
+   *   - We cannot re-use the same logic as above, since CSMA may bail out of
+   *     frame TX immediately after a single call this function here. In this
+   *     scenario, is_receiving_packet would remain equal to one and we would
+   *     therefore erroneously signal ongoing RX in subsequent calls to this
+   *     function here, even _after_ reception has completed.
+   *   - We can neither clear inside read_frame() nor inside the RX frame
+   *     interrupt handler (remember, we are not in poll mode under CSMA),
+   *     since we risk clearing MDMSOFT after we have seen a sync word for the
+   *     _next_ frame. If this happens, this function here would incorrectly
+   *     return 0 during RX of this next frame.
+   *
+   * So to avoid a very convoluted logic of how to handle MDMSOFT, we simply
+   * perform a clear channel assessment here: We interpret channel activity
+   * as frame reception.
+   */
+
+  if(channel_clear() == RF_CORE_CCA_CLEAR) {
+    return 0;
+  }
+
+  return 1;
+
+#endif
 }
 /*---------------------------------------------------------------------------*/
 static int
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/prop-mode.h b/arch/cpu/cc26x0-cc13x0/rf-core/prop-mode.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/prop-mode.h
rename to arch/cpu/cc26x0-cc13x0/rf-core/prop-mode.h
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/rf-ble.c b/arch/cpu/cc26x0-cc13x0/rf-core/rf-ble.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/rf-ble.c
rename to arch/cpu/cc26x0-cc13x0/rf-core/rf-ble.c
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/rf-ble.h b/arch/cpu/cc26x0-cc13x0/rf-core/rf-ble.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/rf-ble.h
rename to arch/cpu/cc26x0-cc13x0/rf-core/rf-ble.h
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/rf-core.c b/arch/cpu/cc26x0-cc13x0/rf-core/rf-core.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/rf-core.c
rename to arch/cpu/cc26x0-cc13x0/rf-core/rf-core.c
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/rf-core.h b/arch/cpu/cc26x0-cc13x0/rf-core/rf-core.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/rf-core.h
rename to arch/cpu/cc26x0-cc13x0/rf-core/rf-core.h
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/rf-switch.h b/arch/cpu/cc26x0-cc13x0/rf-core/rf-switch.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/rf-switch.h
rename to arch/cpu/cc26x0-cc13x0/rf-core/rf-switch.h
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/smartrf-settings.c b/arch/cpu/cc26x0-cc13x0/rf-core/smartrf-settings.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/smartrf-settings.c
rename to arch/cpu/cc26x0-cc13x0/rf-core/smartrf-settings.c
diff --git a/arch/cpu/cc26xx-cc13xx/rf-core/smartrf-settings.h b/arch/cpu/cc26x0-cc13x0/rf-core/smartrf-settings.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rf-core/smartrf-settings.h
rename to arch/cpu/cc26x0-cc13x0/rf-core/smartrf-settings.h
diff --git a/arch/cpu/cc26xx-cc13xx/rtimer-arch.c b/arch/cpu/cc26x0-cc13x0/rtimer-arch.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rtimer-arch.c
rename to arch/cpu/cc26x0-cc13x0/rtimer-arch.c
diff --git a/arch/cpu/cc26xx-cc13xx/rtimer-arch.h b/arch/cpu/cc26x0-cc13x0/rtimer-arch.h
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/rtimer-arch.h
rename to arch/cpu/cc26x0-cc13x0/rtimer-arch.h
diff --git a/arch/cpu/cc26xx-cc13xx/slip-arch.c b/arch/cpu/cc26x0-cc13x0/slip-arch.c
similarity index 100%
rename from arch/cpu/cc26xx-cc13xx/slip-arch.c
rename to arch/cpu/cc26x0-cc13x0/slip-arch.c
diff --git a/arch/cpu/cc26xx-cc13xx/ti-lib.h b/arch/cpu/cc26x0-cc13x0/ti-lib.h
similarity index 98%
rename from arch/cpu/cc26xx-cc13xx/ti-lib.h
rename to arch/cpu/cc26x0-cc13x0/ti-lib.h
index d6c7363ee2319c392fc5a26199852d1d22393830..0d8400813de02341ee56ef60d06310eaebd6d888 100644
--- a/arch/cpu/cc26xx-cc13xx/ti-lib.h
+++ b/arch/cpu/cc26x0-cc13x0/ti-lib.h
@@ -572,6 +572,14 @@
 #define ti_lib_watchdog_stall_enable(...)   WatchdogStallEnable(__VA_ARGS__)
 #define ti_lib_watchdog_stall_disable(...)  WatchdogStallDisable(__VA_ARGS__)
 /*---------------------------------------------------------------------------*/
+/* crypto.h */
+#include "driverlib/crypto.h"
+
+#define ti_lib_crypto_aes_load_key(...)   CRYPTOAesLoadKey(__VA_ARGS__)
+#define ti_lib_crypto_aes_ecb(...)        CRYPTOAesEcb(__VA_ARGS__)
+#define ti_lib_crypto_aes_ecb_status(...) CRYPTOAesEcbStatus(__VA_ARGS__)
+#define ti_lib_crypto_aes_ecb_finish(...) CRYPTOAesEcbFinish(__VA_ARGS__)
+/*---------------------------------------------------------------------------*/
 #endif /* TI_LIB_H_ */
 /*---------------------------------------------------------------------------*/
 /**
diff --git a/arch/cpu/msp430/Makefile.msp430 b/arch/cpu/msp430/Makefile.msp430
index 841e11285cc02d9efe6353f8e7911e304854e189..7927002b67b265930ff7c8b39ac02ff9b3ce2dcc 100644
--- a/arch/cpu/msp430/Makefile.msp430
+++ b/arch/cpu/msp430/Makefile.msp430
@@ -11,7 +11,7 @@ CFLAGS += -gstabs+
 .SUFFIXES:
 
 ### Define the CPU directory
-CONTIKI_CPU=$(CONTIKI)/arch/cpu/msp430
+CONTIKI_CPU=$(ARCH_PATH)/cpu/msp430
 
 ### Define the source files we have in the MSP430 port
 
diff --git a/arch/cpu/msp430/msp430-conf.h b/arch/cpu/msp430/msp430-conf.h
index f4f0da54cc9a53947adb0796aa9a98867e1373a5..91ae6ac4df90f8003d888c9f4dd62e5b76eff2d8 100644
--- a/arch/cpu/msp430/msp430-conf.h
+++ b/arch/cpu/msp430/msp430-conf.h
@@ -56,6 +56,8 @@
 #endif
 #endif
 
+#define cc2420_driver_max_payload_len    125
+
 /*---------------------------------------------------------------------------*/
 #endif /* MSP430_CONF_H_ */
 /*---------------------------------------------------------------------------*/
diff --git a/arch/cpu/msp430/uip-ipchksum.c b/arch/cpu/msp430/uip-ipchksum.c
index e4cb308d0f5ba22a672efb8973981ff032fff672..442c154dcc06dbd4adffb498b6c5c7f158477ed3 100644
--- a/arch/cpu/msp430/uip-ipchksum.c
+++ b/arch/cpu/msp430/uip-ipchksum.c
@@ -51,7 +51,7 @@ uint16_t
 uip_ipchksum(void)
 {
   /* Assumes proper alignement of uip_buf. */
-  uint16_t *p = (uint16_t *)&uip_buf[UIP_LLH_LEN];
+  uint16_t *p = (uint16_t *)UIP_IP_BUF;
   register uint16_t sum;
 
   sum = p[0];
diff --git a/arch/cpu/native/dev/gpio-hal-arch.c b/arch/cpu/native/dev/gpio-hal-arch.c
index 366141d775bf9d25c7d7adf90ecea5c40ea081bc..1e56850812b867b5d7522427b11026f89f572427 100644
--- a/arch/cpu/native/dev/gpio-hal-arch.c
+++ b/arch/cpu/native/dev/gpio-hal-arch.c
@@ -49,7 +49,7 @@ gpio_hal_arch_init(void)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_interrupt_enable(gpio_hal_pin_t pin)
+gpio_hal_arch_no_port_interrupt_enable(gpio_hal_pin_t pin)
 {
   if(pin >= GPIO_HAL_PIN_COUNT) {
     LOG_ERR("Pin %u out of bounds\n", pin);
@@ -60,7 +60,7 @@ gpio_hal_arch_interrupt_enable(gpio_hal_pin_t pin)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_interrupt_disable(gpio_hal_pin_t pin)
+gpio_hal_arch_no_port_interrupt_disable(gpio_hal_pin_t pin)
 {
   if(pin >= GPIO_HAL_PIN_COUNT) {
     LOG_ERR("Pin %u out of bounds\n", pin);
@@ -71,7 +71,7 @@ gpio_hal_arch_interrupt_disable(gpio_hal_pin_t pin)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg)
+gpio_hal_arch_no_port_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg)
 {
   if(pin >= GPIO_HAL_PIN_COUNT) {
     LOG_ERR("Pin %u out of bounds\n", pin);
@@ -83,7 +83,7 @@ gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg)
 }
 /*---------------------------------------------------------------------------*/
 gpio_hal_pin_cfg_t
-gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin)
+gpio_hal_arch_no_port_pin_cfg_get(gpio_hal_pin_t pin)
 {
   if(pin >= GPIO_HAL_PIN_COUNT) {
     LOG_ERR("Pin %u out of bounds\n", pin);
@@ -95,7 +95,7 @@ gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_pin_set_input(gpio_hal_pin_t pin)
+gpio_hal_arch_no_port_pin_set_input(gpio_hal_pin_t pin)
 {
   if(pin >= GPIO_HAL_PIN_COUNT) {
     LOG_ERR("Pin %u out of bounds\n", pin);
@@ -106,7 +106,7 @@ gpio_hal_arch_pin_set_input(gpio_hal_pin_t pin)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_pin_set_output(gpio_hal_pin_t pin)
+gpio_hal_arch_no_port_pin_set_output(gpio_hal_pin_t pin)
 {
   if(pin >= GPIO_HAL_PIN_COUNT) {
     LOG_ERR("Pin %u out of bounds\n", pin);
@@ -117,7 +117,7 @@ gpio_hal_arch_pin_set_output(gpio_hal_pin_t pin)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_set_pin(gpio_hal_pin_t pin)
+gpio_hal_arch_no_port_set_pin(gpio_hal_pin_t pin)
 {
   if(pin >= GPIO_HAL_PIN_COUNT) {
     LOG_ERR("Pin %u out of bounds\n", pin);
@@ -129,7 +129,7 @@ gpio_hal_arch_set_pin(gpio_hal_pin_t pin)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_clear_pin(gpio_hal_pin_t pin)
+gpio_hal_arch_no_port_clear_pin(gpio_hal_pin_t pin)
 {
   if(pin >= GPIO_HAL_PIN_COUNT) {
     LOG_ERR("Pin %u out of bounds\n", pin);
@@ -141,7 +141,7 @@ gpio_hal_arch_clear_pin(gpio_hal_pin_t pin)
 }
 /*---------------------------------------------------------------------------*/
 uint8_t
-gpio_hal_arch_read_pin(gpio_hal_pin_t pin)
+gpio_hal_arch_no_port_read_pin(gpio_hal_pin_t pin)
 {
   if(pin >= GPIO_HAL_PIN_COUNT) {
     LOG_ERR("Pin %u out of bounds\n", pin);
@@ -153,7 +153,7 @@ gpio_hal_arch_read_pin(gpio_hal_pin_t pin)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_write_pin(gpio_hal_pin_t pin, uint8_t value)
+gpio_hal_arch_no_port_write_pin(gpio_hal_pin_t pin, uint8_t value)
 {
   if(pin >= GPIO_HAL_PIN_COUNT) {
     LOG_ERR("Pin %u out of bounds\n", pin);
@@ -165,7 +165,7 @@ gpio_hal_arch_write_pin(gpio_hal_pin_t pin, uint8_t value)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_set_pins(gpio_hal_pin_mask_t pins)
+gpio_hal_arch_no_port_set_pins(gpio_hal_pin_mask_t pins)
 {
   gpio_hal_pin_t pin;
 
@@ -179,7 +179,7 @@ gpio_hal_arch_set_pins(gpio_hal_pin_mask_t pins)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_clear_pins(gpio_hal_pin_mask_t pins)
+gpio_hal_arch_no_port_clear_pins(gpio_hal_pin_mask_t pins)
 {
   gpio_hal_pin_t pin;
 
@@ -193,7 +193,7 @@ gpio_hal_arch_clear_pins(gpio_hal_pin_mask_t pins)
 }
 /*---------------------------------------------------------------------------*/
 gpio_hal_pin_mask_t
-gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins)
+gpio_hal_arch_no_port_read_pins(gpio_hal_pin_mask_t pins)
 {
   gpio_hal_pin_t pin;
   gpio_hal_pin_mask_t state = 0;
@@ -207,7 +207,8 @@ gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_write_pins(gpio_hal_pin_mask_t pins, gpio_hal_pin_mask_t value)
+gpio_hal_arch_no_port_write_pins(gpio_hal_pin_mask_t pins,
+                                 gpio_hal_pin_mask_t value)
 {
   gpio_hal_pin_t pin;
 
diff --git a/arch/cpu/native/native-def.h b/arch/cpu/native/native-def.h
index d85ae7100440cf0ec9451ca1506d1e7db7e2e853..6d6b817552fc29a6d06c68ab23c658e3335a9b30 100644
--- a/arch/cpu/native/native-def.h
+++ b/arch/cpu/native/native-def.h
@@ -32,7 +32,8 @@
 #ifndef NATIVE_DEF_H_
 #define NATIVE_DEF_H_
 /*---------------------------------------------------------------------------*/
-#define GPIO_HAL_CONF_ARCH_SW_TOGGLE 1
+#define GPIO_HAL_CONF_ARCH_SW_TOGGLE     1
+#define GPIO_HAL_CONF_PORT_PIN_NUMBERING 0
 /*---------------------------------------------------------------------------*/
 #endif /* NATIVE_DEF_H_ */
 /*---------------------------------------------------------------------------*/
diff --git a/arch/cpu/native/net/tun6-net.c b/arch/cpu/native/net/tun6-net.c
index d46d91d4279a1932e76ea168bb36dc0bedd6e930..f1e8c2e774dd578af8abc6ecfe05c02c9a6c6dfd 100644
--- a/arch/cpu/native/net/tun6-net.c
+++ b/arch/cpu/native/net/tun6-net.c
@@ -263,7 +263,7 @@ output(const linkaddr_t *localdest)
 {
   LOG_DBG("SUT: %u\n", uip_len);
   if(uip_len > 0) {
-    return tun_output(&uip_buf[UIP_LLH_LEN], uip_len);
+    return tun_output(uip_buf, uip_len);
   }
   return 0;
 }
@@ -297,7 +297,7 @@ handle_fd(fd_set *rset, fd_set *wset)
   LOG_INFO("Tun6-handle FD\n");
 
   if(FD_ISSET(tunfd, rset)) {
-    size = tun_input(&uip_buf[UIP_LLH_LEN], sizeof(uip_buf));
+    size = tun_input(uip_buf, sizeof(uip_buf));
     LOG_DBG("TUN data incoming read:%d\n", size);
     uip_len = size;
     tcpip_input();
diff --git a/arch/cpu/nrf52832/Makefile.nrf52832 b/arch/cpu/nrf52832/Makefile.nrf52832
index 098033ce46398491b3ea6455fd1aa4abcde482ff..102e74486045320eb2cb33f3fd68381710dad0d8 100644
--- a/arch/cpu/nrf52832/Makefile.nrf52832
+++ b/arch/cpu/nrf52832/Makefile.nrf52832
@@ -25,9 +25,9 @@ ifneq ($(NRF52_WITHOUT_SOFTDEVICE),1)
     NRF52_SOFTDEVICE := $(shell find $(NRF52_SDK_ROOT) -name *iot*_softdevice.hex | head -n 1)
   endif
   $(info SoftDevice: $(NRF52_SOFTDEVICE))
-  LDSCRIPT := $(CONTIKI_CPU)/ld/nrf52-$(NRF52_DK_REVISION)-sd.ld
+  LDSCRIPT ?= $(CONTIKI_CPU)/ld/nrf52-$(NRF52_DK_REVISION)-sd.ld
 else
-  LDSCRIPT := $(CONTIKI_CPU)/ld/nrf52.ld
+  LDSCRIPT ?= $(CONTIKI_CPU)/ld/nrf52.ld
 endif
 
 OUTPUT_FILENAME := $(CONTIKI_PROJECT)
@@ -185,10 +185,12 @@ $(OBJECT_DIRECTORY)/%.o: %.s
 	$(TRACE_CC)
 	$(Q)$(CC) $(ASMFLAGS) $(addprefix -I$(NRF52_SDK_ROOT)/, $(INC_PATHS)) -c -o $@ $<
 
-%.jlink:
-	sed -e 's/#OUTPUT_FILENAME#/$*.hex/' $(CONTIKI_CPU)/flash.jlink > $@
+include $(ARCH_PATH)/cpu/arm/cortex-m/cm4/Makefile.cm4
 
-%.flash: %.hex %.jlink
+%.jlink: $(OUT_HEX)
+	sed -e 's,#OUTPUT_FILENAME#,$<,' $(CONTIKI_CPU)/flash.jlink > $@
+
+%.flash: %.jlink
 	@echo Flashing: $^
 	$(JLINK) $(JLINK_OPTS) -CommanderScript $*.jlink
 
@@ -203,5 +205,3 @@ erase:
 	$(JLINK) $(JLINK_OPTS) -CommanderScript $(CONTIKI_CPU)/erase.jlink
 
 .PHONY: softdevice.jlink
-
-include $(CONTIKI)/arch/cpu/arm/cortex-m/cm4/Makefile.cm4
diff --git a/arch/cpu/nrf52832/ble/ble-mac.c b/arch/cpu/nrf52832/ble/ble-mac.c
index 4fe1ef93492f4eeaf85dd7554d03c4ba6dba4418..d47a3c2afcb9bca8089aa335d5fe9f6c0e41520a 100644
--- a/arch/cpu/nrf52832/ble/ble-mac.c
+++ b/arch/cpu/nrf52832/ble/ble-mac.c
@@ -314,7 +314,6 @@ send_packet(mac_callback_t sent, void *ptr)
     for(i = 0; i < BLE_MAC_MAX_INTERFACE_NUM; i++) {
       if(interfaces[i].handle.cid != 0 && interfaces[i].handle.conn_handle != 0) {
         ret = send_to_peer(&interfaces[i].handle);
-        watchdog_periodic();
       }
     }
   } else if((handle = find_handle(dest)) != NULL) {
@@ -326,7 +325,6 @@ send_packet(mac_callback_t sent, void *ptr)
   if(ret) {
     busy_tx = 1;
     while(busy_tx) {
-      watchdog_periodic();
       sd_app_evt_wait();
     }
     mac_call_sent_callback(sent, ptr, MAC_TX_OK, 1);
@@ -347,6 +345,12 @@ off(void)
   return 1;
 }
 /*---------------------------------------------------------------------------*/
+static int
+max_payload(void)
+{
+  return PACKETBUF_SIZE;
+}
+/*---------------------------------------------------------------------------*/
 static void
 init(void)
 {
@@ -371,7 +375,8 @@ const struct mac_driver ble_ipsp_mac_driver = {
   send_packet,
   NULL,
   on,
-  off
+  off,
+  max_payload
 };
 /*---------------------------------------------------------------------------*/
 /**
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/Makefile.cc13xx-cc26xx b/arch/cpu/simplelink-cc13xx-cc26xx/Makefile.cc13xx-cc26xx
index dfd14637e0f5685cdb2bc188fba40c66e6a8b652..bb7bf82f59297314e39654d6d6f0d685066fb903 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/Makefile.cc13xx-cc26xx
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/Makefile.cc13xx-cc26xx
@@ -3,7 +3,7 @@
 
 CC13x2_CC26x2_PRE_RTM ?= 1
 
-# Core SDK is placed as a submodule under arch/cpu/cc13xx-cc26xx/lib.
+# Core SDK is placed as a submodule under arch/cpu/simplelink-cc13xx-cc26xx/lib.
 # Do a sanity check that Core SDK submodule has been initialized.
 ifndef CORE_SDK
  CORE_SDK := $(CONTIKI_CPU)/lib/coresdk_cc13xx_cc26xx
@@ -120,7 +120,7 @@ LDFLAGS += -nostartfiles
 LDFLAGS += -static
 
 # Linker script
-LDSCRIPT := $(CONTIKI_CPU)/$(SUBFAMILY)/$(SUBFAMILY).lds
+LDSCRIPT ?= $(CONTIKI_CPU)/$(SUBFAMILY)/$(SUBFAMILY).lds
 
 # Globally linked libraries
 TARGET_LIBFILES += -lc -lgcc -lnosys -lm
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/cc13x0-cc26x0/Makefile.cc13x0-cc26x0 b/arch/cpu/simplelink-cc13xx-cc26xx/cc13x0-cc26x0/Makefile.cc13x0-cc26x0
index 9aa7c5be2d8b45cb7954c44761f49342b26cf945..9be4ad6ab3811f0c34a3fcb392dbd8988e4ef3a5 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/cc13x0-cc26x0/Makefile.cc13x0-cc26x0
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/cc13x0-cc26x0/Makefile.cc13x0-cc26x0
@@ -8,4 +8,4 @@ TARGET_LIBFILES += $(SDK_DRIVERS)/lib/drivers_$(SDK_LIB_NAME).am3g
 TARGET_LIBFILES += $(SDK_DEVICES)/driverlib/bin/gcc/driverlib.lib
 
 # CC13x0/CC26x0 is a Cortex-M3 architecture
-include $(CONTIKI)/arch/cpu/arm/cortex-m/cm3/Makefile.cm3
+include $(ARCH_PATH)/cpu/arm/cortex-m/cm3/Makefile.cm3
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/cc13x0-cc26x0/cc13x0-cc26x0.lds b/arch/cpu/simplelink-cc13xx-cc26xx/cc13x0-cc26x0/cc13x0-cc26x0.lds
index 26930dea8d1455515588e22c1a983c33d628503c..2bc8ec8cca28da5312e184bf68ed780e007aee06 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/cc13x0-cc26x0/cc13x0-cc26x0.lds
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/cc13x0-cc26x0/cc13x0-cc26x0.lds
@@ -95,42 +95,42 @@ SECTIONS {
      * --------- DO NOT MODIFY -----------
      */
     UDMACC26XX_dmaSpi0RxControlTableEntry_is_placed = 0;
-    .dmaSpi0RxControlTableEntry DMA_SPI0_RX_CTEA : AT (DMA_SPI0_RX_CTEA) {
+    .dmaSpi0RxControlTableEntry DMA_SPI0_RX_CTEA (NOLOAD) : AT (DMA_SPI0_RX_CTEA) {
         *(.dmaSpi0RxControlTableEntry)
     } > REGION_DATA
 
     UDMACC26XX_dmaSpi0TxControlTableEntry_is_placed = 0;
-    .dmaSpi0TxControlTableEntry DMA_SPI0_TX_CTEA : AT (DMA_SPI0_TX_CTEA) {
+    .dmaSpi0TxControlTableEntry DMA_SPI0_TX_CTEA (NOLOAD) : AT (DMA_SPI0_TX_CTEA) {
         *(.dmaSpi0TxControlTableEntry)
     } > REGION_DATA
 
     UDMACC26XX_dmaADCPriControlTableEntry_is_placed = 0;
-    .dmaADCPriControlTableEntry DMA_ADC_PRI_CTEA : AT (DMA_ADC_PRI_CTEA) {
+    .dmaADCPriControlTableEntry DMA_ADC_PRI_CTEA (NOLOAD) : AT (DMA_ADC_PRI_CTEA) {
         *(.dmaADCPriControlTableEntry)
     } > REGION_DATA
 
     UDMACC26XX_dmaGPT0APriControlTableEntry_is_placed = 0;
-    .dmaGPT0APriControlTableEntry DMA_GPT0A_PRI_CTEA : AT (DMA_GPT0A_PRI_CTEA) {
+    .dmaGPT0APriControlTableEntry DMA_GPT0A_PRI_CTEA (NOLOAD) : AT (DMA_GPT0A_PRI_CTEA) {
         *(.dmaGPT0APriControlTableEntry)
     } > REGION_DATA
 
     UDMACC26XX_dmaSpi1RxControlTableEntry_is_placed = 0;
-    .dmaSpi1RxControlTableEntry DMA_SPI1_RX_CTEA : AT (DMA_SPI1_RX_CTEA) {
+    .dmaSpi1RxControlTableEntry DMA_SPI1_RX_CTEA (NOLOAD) : AT (DMA_SPI1_RX_CTEA) {
         *(.dmaSpi1RxControlTableEntry)
     } > REGION_DATA
 
     UDMACC26XX_dmaSpi1TxControlTableEntry_is_placed = 0;
-    .dmaSpi1TxControlTableEntry DMA_SPI1_TX_CTEA : AT (DMA_SPI1_TX_CTEA) {
+    .dmaSpi1TxControlTableEntry DMA_SPI1_TX_CTEA (NOLOAD) : AT (DMA_SPI1_TX_CTEA) {
         *(.dmaSpi1TxControlTableEntry)
     } > REGION_DATA
 
     UDMACC26XX_dmaADCAltControlTableEntry_is_placed = 0;
-    .dmaADCAltControlTableEntry DMA_ADC_ALT_CTEA : AT (DMA_ADC_ALT_CTEA) {
+    .dmaADCAltControlTableEntry DMA_ADC_ALT_CTEA (NOLOAD) : AT (DMA_ADC_ALT_CTEA) {
         *(.dmaADCAltControlTableEntry)
     } > REGION_DATA
 
     UDMACC26XX_dmaGPT0AAltControlTableEntry_is_placed = 0;
-    .dmaGPT0AAltControlTableEntry DMA_GPT0A_ALT_CTEA : AT (DMA_GPT0A_ALT_CTEA) {
+    .dmaGPT0AAltControlTableEntry DMA_GPT0A_ALT_CTEA (NOLOAD) : AT (DMA_GPT0A_ALT_CTEA) {
         *(.dmaGPT0AAltControlTableEntry)
     } > REGION_DATA
 
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/cc13x2-cc26x2/Makefile.cc13x2-cc26x2 b/arch/cpu/simplelink-cc13xx-cc26xx/cc13x2-cc26x2/Makefile.cc13x2-cc26x2
index 52333f47d785aa77a7de8b0ade2229d1c278e735..afe0ae4292ef523377e5942fe1b3629c6e6a933f 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/cc13x2-cc26x2/Makefile.cc13x2-cc26x2
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/cc13x2-cc26x2/Makefile.cc13x2-cc26x2
@@ -8,4 +8,4 @@ TARGET_LIBFILES += $(SDK_DRIVERS)/lib/drivers_$(SDK_LIB_NAME).am4fg
 TARGET_LIBFILES += $(SDK_DEVICES)/driverlib/bin/gcc/driverlib.lib
 
 # CC13x2/CC26x2 is a Cortex-M4 architecture
-include $(CONTIKI)/arch/cpu/arm/cortex-m/cm4/Makefile.cm4
+include $(ARCH_PATH)/cpu/arm/cortex-m/cm4/Makefile.cm4
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/cc13x2-cc26x2/cc13x2-cc26x2.lds b/arch/cpu/simplelink-cc13xx-cc26xx/cc13x2-cc26x2/cc13x2-cc26x2.lds
index 9c2211cb829f0f21986300a13a2092a83bde7aef..dc1a608be47fa06ec395b0f10dd8791de95a1aae 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/cc13x2-cc26x2/cc13x2-cc26x2.lds
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/cc13x2-cc26x2/cc13x2-cc26x2.lds
@@ -95,42 +95,42 @@ SECTIONS {
      * --------- DO NOT MODIFY -----------
      */
     UDMACC26XX_dmaSpi0RxControlTableEntry_is_placed = 0;
-    .dmaSpi0RxControlTableEntry DMA_SPI0_RX_CTEA : AT (DMA_SPI0_RX_CTEA) {
+    .dmaSpi0RxControlTableEntry DMA_SPI0_RX_CTEA (NOLOAD) : AT (DMA_SPI0_RX_CTEA) {
         *(.dmaSpi0RxControlTableEntry)
     } > REGION_DATA
 
     UDMACC26XX_dmaSpi0TxControlTableEntry_is_placed = 0;
-    .dmaSpi0TxControlTableEntry DMA_SPI0_TX_CTEA : AT (DMA_SPI0_TX_CTEA) {
+    .dmaSpi0TxControlTableEntry DMA_SPI0_TX_CTEA (NOLOAD) : AT (DMA_SPI0_TX_CTEA) {
         *(.dmaSpi0TxControlTableEntry)
     } > REGION_DATA
 
     UDMACC26XX_dmaADCPriControlTableEntry_is_placed = 0;
-    .dmaADCPriControlTableEntry DMA_ADC_PRI_CTEA : AT (DMA_ADC_PRI_CTEA) {
+    .dmaADCPriControlTableEntry DMA_ADC_PRI_CTEA (NOLOAD) : AT (DMA_ADC_PRI_CTEA) {
         *(.dmaADCPriControlTableEntry)
     } > REGION_DATA
 
     UDMACC26XX_dmaGPT0APriControlTableEntry_is_placed = 0;
-    .dmaGPT0APriControlTableEntry DMA_GPT0A_PRI_CTEA : AT (DMA_GPT0A_PRI_CTEA) {
+    .dmaGPT0APriControlTableEntry DMA_GPT0A_PRI_CTEA (NOLOAD) : AT (DMA_GPT0A_PRI_CTEA) {
         *(.dmaGPT0APriControlTableEntry)
     } > REGION_DATA
 
     UDMACC26XX_dmaSpi1RxControlTableEntry_is_placed = 0;
-    .dmaSpi1RxControlTableEntry DMA_SPI1_RX_CTEA : AT (DMA_SPI1_RX_CTEA) {
+    .dmaSpi1RxControlTableEntry DMA_SPI1_RX_CTEA (NOLOAD) : AT (DMA_SPI1_RX_CTEA) {
         *(.dmaSpi1RxControlTableEntry)
     } > REGION_DATA
 
     UDMACC26XX_dmaSpi1TxControlTableEntry_is_placed = 0;
-    .dmaSpi1TxControlTableEntry DMA_SPI1_TX_CTEA : AT (DMA_SPI1_TX_CTEA) {
+    .dmaSpi1TxControlTableEntry DMA_SPI1_TX_CTEA (NOLOAD) : AT (DMA_SPI1_TX_CTEA) {
         *(.dmaSpi1TxControlTableEntry)
     } > REGION_DATA
 
     UDMACC26XX_dmaADCAltControlTableEntry_is_placed = 0;
-    .dmaADCAltControlTableEntry DMA_ADC_ALT_CTEA : AT (DMA_ADC_ALT_CTEA) {
+    .dmaADCAltControlTableEntry DMA_ADC_ALT_CTEA (NOLOAD) : AT (DMA_ADC_ALT_CTEA) {
         *(.dmaADCAltControlTableEntry)
     } > REGION_DATA
 
     UDMACC26XX_dmaGPT0AAltControlTableEntry_is_placed = 0;
-    .dmaGPT0AAltControlTableEntry DMA_GPT0A_ALT_CTEA : AT (DMA_GPT0A_ALT_CTEA) {
+    .dmaGPT0AAltControlTableEntry DMA_GPT0A_ALT_CTEA (NOLOAD) : AT (DMA_GPT0A_ALT_CTEA) {
         *(.dmaGPT0AAltControlTableEntry)
     } > REGION_DATA
 
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/cc13xx-cc26xx-conf.h b/arch/cpu/simplelink-cc13xx-cc26xx/cc13xx-cc26xx-conf.h
index 87fa922b9ee56205ac763164f980d22ae8a34fd4..2cfb9f43960ce6b50c740e250bf9f08860bc2171 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/cc13xx-cc26xx-conf.h
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/cc13xx-cc26xx-conf.h
@@ -61,15 +61,6 @@
 #define BOARD_CONF_SENSORS_DISABLE          0
 #endif
 /*---------------------------------------------------------------------------*/
-/**
- * \name GPIO HAL configuration.
- *
- * @{
- */
-#define GPIO_HAL_CONF_ARCH_SW_TOGGLE        0
-#define GPIO_HAL_CONF_ARCH_HDR_PATH         "dev/gpio-hal-arch.h"
-/** @} */
-/*---------------------------------------------------------------------------*/
 /**
  * \name Watchdog Configuration.
  *
@@ -79,8 +70,8 @@
 #define WATCHDOG_CONF_DISABLE               0
 #endif
 
-#ifndef WATCHDOG_CONF_TIMER_TOP
-#define WATCHDOG_CONF_TIMER_TOP             0xFFFFF
+#ifndef WATCHDOG_CONF_TIMEOUT_MS
+#define WATCHDOG_CONF_TIMEOUT_MS            1000
 #endif
 /** @} */
 /*---------------------------------------------------------------------------*/
@@ -133,6 +124,32 @@
 #define RF_MODE                      RF_CONF_MODE
 #endif /* RF_CONF_MODE */
 
+/* Sub-1 GHz path front-end mode configuration */
+#ifdef RF_SUB_1_GHZ_CONF_FRONT_END_MODE
+#define RF_SUB_1_GHZ_FRONT_END_MODE     RF_SUB_1_GHZ_CONF_FRONT_END_MODE
+#else
+#define RF_SUB_1_GHZ_FRONT_END_MODE     RF_FRONT_END_MODE_DIFFERENTIAL
+#endif
+
+#ifdef RF_SUB_1_GHZ_CONF_BIAS_MODE
+#define RF_SUB_1_GHZ_BIAS_MODE          RF_SUB_1_GHZ_CONF_BIAS_MODE
+#else
+#define RF_SUB_1_GHZ_BIAS_MODE          RF_BIAS_MODE_INTERNAL
+#endif
+
+/* 2.4 GHz path front-end mode configuration */
+#ifdef RF_2_4_GHZ_CONF_FRONT_END_MODE
+#define RF_2_4_GHZ_FRONT_END_MODE       RF_2_4_GHZ_CONF_FRONT_END_MODE
+#else
+#define RF_2_4_GHZ_FRONT_END_MODE       RF_FRONT_END_MODE_DIFFERENTIAL
+#endif
+
+#ifdef RF_2_4_GHZ_CONF_BIAS_MODE
+#define RF_2_4_GHZ_BIAS_MODE            RF_2_4_GHZ_CONF_BIAS_MODE
+#else
+#define RF_2_4_GHZ_BIAS_MODE            RF_BIAS_MODE_INTERNAL
+#endif
+
 /* Number of RX buffers. */
 #ifndef RF_CONF_RX_BUF_CNT
 #define RF_CONF_RX_BUF_CNT           4
@@ -218,6 +235,9 @@
 #error "Unsupported Device Line defined"
 #endif /* Unsupported device line */
 
+#define prop_mode_driver_max_payload_len      125
+#define ieee_mode_driver_max_payload_len      125
+
 /** @} */
 /*---------------------------------------------------------------------------*/
 /**
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/cc13xx-cc26xx-def.h b/arch/cpu/simplelink-cc13xx-cc26xx/cc13xx-cc26xx-def.h
index 5bcde9d93e144df6c471f2a4d02c6dee4442d057..7c79cc611be4b8b8181a1b975c9c8e37cf03ab7a 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/cc13xx-cc26xx-def.h
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/cc13xx-cc26xx-def.h
@@ -125,10 +125,16 @@
 #define CMSIS_CONF_HEADER_PATH              "cc13x2-cc26x2-cm4.h"
 #endif
 /*---------------------------------------------------------------------------*/
-/* Path to headers with implementation of mutexes and memory barriers */
+/* Path to headers with implementation of mutexes, atomic and memory barriers */
 #define MUTEX_CONF_ARCH_HEADER_PATH          "mutex-cortex.h"
+#define ATOMIC_CONF_ARCH_HEADER_PATH         "atomic-cortex.h"
 #define MEMORY_BARRIER_CONF_ARCH_HEADER_PATH "memory-barrier-cortex.h"
 /*---------------------------------------------------------------------------*/
+/* GPIO HAL configuration */
+#define GPIO_HAL_CONF_ARCH_HDR_PATH         "dev/gpio-hal-arch.h"
+#define GPIO_HAL_CONF_ARCH_SW_TOGGLE        0
+#define GPIO_HAL_CONF_PORT_PIN_NUMBERING    0
+/*---------------------------------------------------------------------------*/
 #endif /* CC13XX_CC26XX_DEF_H_ */
 /*---------------------------------------------------------------------------*/
 /** @} */
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/dev/clock-arch.c b/arch/cpu/simplelink-cc13xx-cc26xx/dev/clock-arch.c
index ef2d4e1c918ed8b2e6d279063f41b67b8de046e4..6df55733a1ab3ee30bd419be16d972f9feee3ead 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/dev/clock-arch.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/dev/clock-arch.c
@@ -28,98 +28,204 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 /**
- * \addtogroup cc13xx-cc26xx-cpu
+ * \addtogroup cc13xx-cc26xx-clock
  * @{
  *
- * \defgroup cc13xx-cc26xx-clock CC13xx/CC26xx clock library
- *
- * @{
  * \file
  *        Implementation of the clock libary for CC13xx/CC26xx.
- * \author
- *        Edvard Pettersen <e.pettersen@ti.com>
+ *
+ *        The periodic polling of etimer is implemented using SysTick. Since
+ *        SysTick is paused when the system clock stopped, that is when the
+ *        device enters some low-power mode, a wakeup clock is armed with the
+ *        next etimer expiration time OR watchdog timeout everytime the device
+ *        enters some low-power mode.
  */
 /*---------------------------------------------------------------------------*/
 #include "contiki.h"
+#include "sys/cc.h"
+#include "sys/clock.h"
 #include "sys/etimer.h"
 /*---------------------------------------------------------------------------*/
 #include <ti/devices/DeviceFamily.h>
 #include DeviceFamily_constructPath(driverlib/aon_rtc.h)
-#include DeviceFamily_constructPath(driverlib/cpu.h)
-#include DeviceFamily_constructPath(driverlib/interrupt.h)
-#include DeviceFamily_constructPath(driverlib/prcm.h)
-#include DeviceFamily_constructPath(driverlib/timer.h)
+#include DeviceFamily_constructPath(driverlib/systick.h)
 
 #include <ti/drivers/dpl/ClockP.h>
-#include <ti/drivers/dpl/HwiP.h>
-#include <ti/drivers/power/PowerCC26XX.h>
 /*---------------------------------------------------------------------------*/
-static volatile clock_time_t count;
-static ClockP_Struct etimer_clock;
+#include "watchdog-arch.h"
+/*---------------------------------------------------------------------------*/
+#include <stdbool.h>
+#include <stdint.h>
+/*---------------------------------------------------------------------------*/
+static ClockP_Struct wakeup_clk;
+/*---------------------------------------------------------------------------*/
+#define H_WAKEUP_CLK    (ClockP_handle(&wakeup_clk))
+
+#define NO_TIMEOUT      (~(uint32_t)0)
+
+#define CLOCK_TO_SYSTEM(t) \
+    (uint32_t)(((uint64_t)(t) * 1000 * 1000) / (CLOCK_SECOND * ClockP_getSystemTickPeriod()))
+#define SYSTEM_TO_CLOCK(t) \
+    (clock_time_t)(((uint64_t)(t) * CLOCK_SECOND * ClockP_getSystemTickPeriod()) / (1000 * 1000))
+
+#define RTC_SUBSEC_FRAC  ((uint64_t)1 << 32)  /* Important to cast to 64-bit */
+/*---------------------------------------------------------------------------*/
+static void
+check_etimer(void)
+{
+  clock_time_t now;
+  clock_time_t next_etimer;
+
+  if(etimer_pending()) {
+    now = clock_time();
+    next_etimer = etimer_next_expiration_time();
+
+    if(!CLOCK_LT(now, next_etimer)) {
+      etimer_request_poll();
+    }
+  }
+}
+/*---------------------------------------------------------------------------*/
+static void
+systick_fxn(void)
+{
+  check_etimer();
+}
 /*---------------------------------------------------------------------------*/
 static void
-clock_update_cb(void)
+wakeup_fxn(uintptr_t arg)
 {
-  const uintptr_t key = HwiP_disable();
-  count += 1;
-  HwiP_restore(key);
+  (void)arg;
+  check_etimer();
+}
+/*---------------------------------------------------------------------------*/
+static uint32_t
+get_etimer_timeout(void)
+{
+  clock_time_t now;
+  clock_time_t next_etimer;
 
-  /* Notify the etimer system. */
   if(etimer_pending()) {
-    etimer_request_poll();
+    now = clock_time();
+    next_etimer = etimer_next_expiration_time();
+
+    if(!CLOCK_LT(now, next_etimer)) {
+      etimer_request_poll();
+      /* etimer already expired, return 0 */
+      return 0;
+
+    } else {
+      /* Convert from clock ticks to system ticks */
+      return CLOCK_TO_SYSTEM(next_etimer - now);
+    }
+  } else {
+    /* No expiration */
+    return NO_TIMEOUT;
   }
 }
 /*---------------------------------------------------------------------------*/
-static inline clock_time_t
-get_count(void)
+static uint32_t
+get_watchdog_timeout(void)
+{
+#if (WATCHDOG_DISABLE == 0)
+  /* Convert from watchdog ticks to system ticks */
+  return watchdog_arch_next_timeout() / ClockP_getSystemTickPeriod();
+
+#else
+  /* No expiration */
+  return NO_TIMEOUT;
+#endif
+}
+/*---------------------------------------------------------------------------*/
+bool
+clock_arch_enter_idle(void)
 {
-  clock_time_t count_read;
+  /*
+   * If the Watchdog is enabled, we must take extra care to wakeup before the
+   * Watchdog times out if the next watchdog timeout is before the next etimer
+   * timeout. This is because the Watchdog only pauses if the device enters
+   * standby. If the device enters idle, the Watchdog still runs and hence the
+   * watchdog will timeout if the next etimer timeout is longer than the
+   * watchdog timeout.
+   */
 
-  const uintptr_t key = HwiP_disable();
-  count_read = count;
-  HwiP_restore(key);
+  uint32_t etimer_timeout;
+  uint32_t watchdog_timeout;
+  uint32_t timeout;
 
-  return count_read;
+  etimer_timeout = get_etimer_timeout();
+  watchdog_timeout = get_watchdog_timeout();
+
+  timeout = MIN(etimer_timeout, watchdog_timeout);
+  if(timeout == 0) {
+    /* We are not going to sleep, and hence we don't arm the wakeup clock. */
+    return false;
+  }
+  if(timeout == NO_TIMEOUT) {
+    /* We are going to some low-power mode without arming the wakeup clock. */
+    return true;
+  }
+
+  /*
+   * We are going to some low-power mode. Arm the wakeup clock with the
+   * calculated.
+   */
+  ClockP_setTimeout(H_WAKEUP_CLK, timeout);
+  ClockP_start(H_WAKEUP_CLK);
+  return true;
+}
+/*---------------------------------------------------------------------------*/
+void
+clock_arch_exit_idle(void)
+{
+  ClockP_stop(H_WAKEUP_CLK);
 }
 /*---------------------------------------------------------------------------*/
 void
 clock_init(void)
 {
-  /* ClockP_getSystemTickPeriod() returns ticks per us. */
-  const uint32_t clockp_ticks_second =
-    (uint32_t)(1000 * 1000) / (CLOCK_SECOND) / ClockP_getSystemTickPeriod();
+  ClockP_Params clk_params;
+  ClockP_FreqHz freq;
 
-  count = 0;
+  ClockP_Params_init(&clk_params);
+  clk_params.startFlag = false;
+  clk_params.period = 0;
+  ClockP_construct(&wakeup_clk, wakeup_fxn, 0, &clk_params);
 
-  ClockP_Params params;
-  ClockP_Params_init(&params);
+  ClockP_getCpuFreq(&freq);
 
-  params.period = clockp_ticks_second;
-  params.startFlag = true;
-
-  ClockP_construct(&etimer_clock, (ClockP_Fxn)clock_update_cb,
-                   clockp_ticks_second, &params);
+  SysTickPeriodSet(freq.lo / CLOCK_SECOND);
+  SysTickIntRegister(systick_fxn);
+  SysTickIntEnable();
+  SysTickEnable();
 }
 /*---------------------------------------------------------------------------*/
 clock_time_t
 clock_time(void)
 {
-  return get_count();
+  /*
+   * RTC counter is in a 64-bits format (SEC[31:0].SUBSEC[31:0]), where SUBSEC
+   * is represented in fractions of a second (VALUE/2^32).
+   */
+  uint64_t now = AONRTCCurrent64BitValueGet();
+  clock_time_t ticks = (clock_time_t)(now / (RTC_SUBSEC_FRAC / CLOCK_SECOND));
+  return ticks;
 }
 /*---------------------------------------------------------------------------*/
 unsigned long
 clock_seconds(void)
 {
-  return (unsigned long)get_count() / CLOCK_SECOND;
+  unsigned long sec = (unsigned long)AONRTCSecGet();
+  return sec;
 }
 /*---------------------------------------------------------------------------*/
 void
 clock_wait(clock_time_t i)
 {
-  clock_time_t start;
+  uint32_t usec;
 
-  start = clock_time();
-  while(clock_time() - start < i);
+  usec = (uint32_t)((1000 * 1000 * i) / CLOCK_SECOND);
+  clock_delay_usec(usec);
 }
 /*---------------------------------------------------------------------------*/
 void
@@ -139,6 +245,5 @@ clock_delay(unsigned int i)
 }
 /*---------------------------------------------------------------------------*/
 /**
- * @}
  * @}
  */
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/dev/clock-arch.h b/arch/cpu/simplelink-cc13xx-cc26xx/dev/clock-arch.h
new file mode 100644
index 0000000000000000000000000000000000000000..6d0499d5633d55ddd0faec9e3b62f35bce2ac273
--- /dev/null
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/dev/clock-arch.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup cc13xx-cc26xx-cpu
+ * @{
+ *
+ * \defgroup cc13xx-cc26xx-clock CC13xx/CC26xx clock implementation
+ *
+ * @{
+ *
+ * \file
+ *        Header file for the  CC13xx/CC26xx clock implementation.
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef CLOCK_ARCH_H_
+#define CLOCK_ARCH_H_
+/*---------------------------------------------------------------------------*/
+#include <stdbool.h>
+/*---------------------------------------------------------------------------*/
+/**
+ * \brief   Prepare to enter some low-power mode. Return value indicates if we
+ *          are ready or not to enter some low-power mode.
+ * \return  true if ready; else false.
+ */
+bool clock_arch_enter_idle(void);
+/*---------------------------------------------------------------------------*/
+/**
+ * \brief   Cleanup after returning from low-power mode.
+ */
+void clock_arch_exit_idle(void);
+/*---------------------------------------------------------------------------*/
+#endif /* CLOCK_ARCH_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ * @}
+ */
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/dev/gpio-hal-arch.c b/arch/cpu/simplelink-cc13xx-cc26xx/dev/gpio-hal-arch.c
index e219faa93d6969438e1c8b1acc409e4026dd334d..1cd8c1d919f075a3584f9b737ae921af47540d2a 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/dev/gpio-hal-arch.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/dev/gpio-hal-arch.c
@@ -96,7 +96,7 @@ to_hal_cfg(PIN_Config pin_cfg, gpio_hal_pin_cfg_t *cfg)
   /* Input config */
   if(pin_cfg & PIN_BM_INPUT_MODE) {
     /* Hysteresis config */
-    if((pin_cfg & PIN_BM_HYSTERESIS) == PIN_HYSTERESIS) {
+    if((pin_cfg & PIN_BM_HYSTERESIS) == PIN_BM_HYSTERESIS) {
       *cfg |= GPIO_HAL_PIN_CFG_HYSTERESIS;
     }
 
@@ -147,7 +147,7 @@ gpio_hal_arch_init(void)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_interrupt_enable(gpio_hal_pin_t pin)
+gpio_hal_arch_no_port_interrupt_enable(gpio_hal_pin_t pin)
 {
   PIN_Config pin_cfg;
   PIN_Config irq_cfg;
@@ -160,7 +160,7 @@ gpio_hal_arch_interrupt_enable(gpio_hal_pin_t pin)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_interrupt_disable(gpio_hal_pin_t pin)
+gpio_hal_arch_no_port_interrupt_disable(gpio_hal_pin_t pin)
 {
   PIN_add(pin_handle, PIN_getConfig(pin));
 
@@ -168,7 +168,7 @@ gpio_hal_arch_interrupt_disable(gpio_hal_pin_t pin)
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg)
+gpio_hal_arch_no_port_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg)
 {
   PIN_add(pin_handle, PIN_getConfig(pin));
 
@@ -182,7 +182,7 @@ gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg)
 }
 /*---------------------------------------------------------------------------*/
 gpio_hal_pin_cfg_t
-gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin)
+gpio_hal_arch_no_port_pin_cfg_get(gpio_hal_pin_t pin)
 {
   PIN_Config pin_cfg = PIN_getConfig(pin);
   gpio_hal_pin_cfg_t cfg = 0;
@@ -193,7 +193,7 @@ gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin)
 }
 /*---------------------------------------------------------------------------*/
 gpio_hal_pin_mask_t
-gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins)
+gpio_hal_arch_no_port_read_pins(gpio_hal_pin_mask_t pins)
 {
   /* For pins configured as output we need to read DOUT31_0 */
   gpio_hal_pin_mask_t oe_pins = GPIO_getOutputEnableMultiDio(pins);
@@ -205,7 +205,7 @@ gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins)
 }
 /*---------------------------------------------------------------------------*/
 uint8_t
-gpio_hal_arch_read_pin(gpio_hal_pin_t pin)
+gpio_hal_arch_no_port_read_pin(gpio_hal_pin_t pin)
 {
   return (GPIO_getOutputEnableDio(pin))
          ? PINCC26XX_getOutputValue(pin)
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/dev/gpio-hal-arch.h b/arch/cpu/simplelink-cc13xx-cc26xx/dev/gpio-hal-arch.h
index 3ca169a82fdfe7ed5721ec5925d3a006f0ca5738..55e67128e059db1d1d2dc2c150ae0eb8baef62fd 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/dev/gpio-hal-arch.h
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/dev/gpio-hal-arch.h
@@ -53,20 +53,20 @@
 
 #include <ti/drivers/pin/PINCC26XX.h>
 /*---------------------------------------------------------------------------*/
-#define gpio_hal_arch_pin_set_input(p)        PINCC26XX_setOutputEnable(p, false)
-#define gpio_hal_arch_pin_set_output(p)       PINCC26XX_setOutputEnable(p, true)
+#define gpio_hal_arch_pin_set_input(port, pin)  PINCC26XX_setOutputEnable(pin, false)
+#define gpio_hal_arch_pin_set_output(port, pin) PINCC26XX_setOutputEnable(pin, true)
 
-#define gpio_hal_arch_set_pin(p)              PINCC26XX_setOutputValue(p, 1)
-#define gpio_hal_arch_clear_pin(p)            PINCC26XX_setOutputValue(p, 0)
-#define gpio_hal_arch_toggle_pin(p)           PINCC26XX_setOutputValue(p, \
-                                                PINCC26XX_getOutputValue(p) \
+#define gpio_hal_arch_set_pin(port, pin)        PINCC26XX_setOutputValue(pin, 1)
+#define gpio_hal_arch_clear_pin(port, pin)      PINCC26XX_setOutputValue(pin, 0)
+#define gpio_hal_arch_toggle_pin(port, pin)     PINCC26XX_setOutputValue(pin, \
+                                                  PINCC26XX_getOutputValue(pin) \
                                                   ? 0 : 1)
-#define gpio_hal_arch_write_pin(p, v)         PINCC26XX_setOutputValue(p, v)
+#define gpio_hal_arch_write_pin(port, pin, v)   PINCC26XX_setOutputValue(pin, v)
 
-#define gpio_hal_arch_set_pins(p)             GPIO_setMultiDio(p)
-#define gpio_hal_arch_clear_pins(p)           GPIO_clearMultiDio(p)
-#define gpio_hal_arch_toggle_pins(p)          GPIO_toggleMultiDio(p)
-#define gpio_hal_arch_write_pins(p, v)        GPIO_writeMultiDio(p, v)
+#define gpio_hal_arch_set_pins(port, pin)       GPIO_setMultiDio(pin)
+#define gpio_hal_arch_clear_pins(port, pin)     GPIO_clearMultiDio(pin)
+#define gpio_hal_arch_toggle_pins(port, pin)    GPIO_toggleMultiDio(pin)
+#define gpio_hal_arch_write_pins(port, pin, v)  GPIO_writeMultiDio(pin, v)
 /*---------------------------------------------------------------------------*/
 #endif /* GPIO_HAL_ARCH_H_ */
 /*---------------------------------------------------------------------------*/
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/dev/watchdog-arch.c b/arch/cpu/simplelink-cc13xx-cc26xx/dev/watchdog-arch.c
index 6cba086b48fa5df3d2b6e37dd0a34af649213b1d..57e63f5103f3857faf7f715d8da1ee6ed15f6986 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/dev/watchdog-arch.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/dev/watchdog-arch.c
@@ -28,19 +28,11 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  */
  /**
- * \addtogroup cc13xx-cc26xx-cpu
- * @{
- *
- * \defgroup cc13xx-cc26xx-watchdog CC13xx/CC26xx watchdog timer driver
- *
- * Driver for the CC13xx/CC26xx Watchdog Timer
- *
- * This file is not called watchdog.c because the filename is in use by
- * TI CC26xxware/CC13xxware
+ * \addtogroup cc13xx-cc26xx-watchdog
  * @{
  *
  * \file
- * Implementation of the CC13xx/CC26xx watchdog driver.
+ *        Implementation of the CC13xx/CC26xx watchdog driver.
  */
 /*---------------------------------------------------------------------------*/
 #include "contiki.h"
@@ -49,14 +41,22 @@
 #include <Board.h>
 
 #include <ti/drivers/Watchdog.h>
+#include <ti/drivers/dpl/ClockP.h>
+
+#include <ti/devices/DeviceFamily.h>
+#include DeviceFamily_constructPath(driverlib/watchdog.h)
+/*---------------------------------------------------------------------------*/
+#include "watchdog-arch.h"
 /*---------------------------------------------------------------------------*/
 #include <stdbool.h>
 #include <stdint.h>
 /*---------------------------------------------------------------------------*/
-#define WATCHDOG_DISABLE    WATCHDOG_CONF_DISABLE
-#define WATCHDOG_TIMER_TOP  WATCHDOG_CONF_TIMER_TOP
+#define WATCHDOG_DIV_RATIO       32    /* Watchdog division ratio */
+#define WATCHDOG_TIMEOUT_MARGIN  1500  /* 1ms margin in Watchdog ticks */
 /*---------------------------------------------------------------------------*/
+#if (WATCHDOG_DISABLE == 0)
 static Watchdog_Handle wdt_handle;
+#endif
 /*---------------------------------------------------------------------------*/
 /**
  * \brief  Initialises the Watchdog module.
@@ -67,10 +67,7 @@ static Watchdog_Handle wdt_handle;
 void
 watchdog_init(void)
 {
-  if(WATCHDOG_DISABLE) {
-    return;
-  }
-
+#if (WATCHDOG_DISABLE == 0)
   Watchdog_init();
 
   Watchdog_Params wdt_params;
@@ -80,6 +77,32 @@ watchdog_init(void)
   wdt_params.debugStallMode = Watchdog_DEBUG_STALL_ON;
 
   wdt_handle = Watchdog_open(Board_WATCHDOG0, &wdt_params);
+#endif
+}
+/*---------------------------------------------------------------------------*/
+uint32_t
+watchdog_arch_next_timeout(void)
+{
+  if(!WatchdogRunning()) {
+    return 0;
+  }
+
+  ClockP_FreqHz freq;
+  ClockP_getCpuFreq(&freq);
+  uint64_t value = (uint64_t)WatchdogValueGet();
+  uint32_t timeout = (uint32_t)((value * 1000 * 1000 * WATCHDOG_DIV_RATIO) / freq.lo);
+
+  /*
+   * A margin should be applied to the timeout to ensure there is enough time
+   * to enter low-power mode, wakeup, and clear the Watchdog timer before it
+   * times out. If the timeout is equals to or less than the margin, simply
+   * return the lowest possible timeout.
+   */
+  if(timeout <= WATCHDOG_TIMEOUT_MARGIN) {
+    return 1;
+  } else {
+    return timeout - WATCHDOG_TIMEOUT_MARGIN;
+  }
 }
 /*---------------------------------------------------------------------------*/
 /**
@@ -88,11 +111,9 @@ watchdog_init(void)
 void
 watchdog_start(void)
 {
-  if(WATCHDOG_DISABLE) {
-    return;
-  }
-
+#if (WATCHDOG_DISABLE == 0)
   watchdog_periodic();
+#endif
 }
 /*---------------------------------------------------------------------------*/
 /**
@@ -101,11 +122,10 @@ watchdog_start(void)
 void
 watchdog_periodic(void)
 {
-  if(WATCHDOG_DISABLE) {
-    return;
-  }
-
-  Watchdog_setReload(wdt_handle, WATCHDOG_TIMER_TOP);
+#if (WATCHDOG_DISABLE == 0)
+  uint32_t timeout_ticks = Watchdog_convertMsToTicks(wdt_handle, WATCHDOG_TIMEOUT_MS);
+  Watchdog_setReload(wdt_handle, timeout_ticks);
+#endif
 }
 /*---------------------------------------------------------------------------*/
 /**
@@ -115,11 +135,9 @@ watchdog_periodic(void)
 void
 watchdog_stop(void)
 {
-  if(WATCHDOG_DISABLE) {
-    return;
-  }
-
+#if (WATCHDOG_DISABLE == 0)
   Watchdog_clear(wdt_handle);
+#endif
 }
 /*---------------------------------------------------------------------------*/
 /**
@@ -128,17 +146,14 @@ watchdog_stop(void)
 void
 watchdog_reboot(void)
 {
-  if(WATCHDOG_DISABLE) {
-    return;
-  }
-
+#if (WATCHDOG_DISABLE == 0)
   watchdog_start();
 
   /* Busy loop until watchdog times out */
   for (;;) { /* hang */ }
+#endif
 }
 /*---------------------------------------------------------------------------*/
 /**
- * @}
  * @}
  */
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/dev/watchdog-arch.h b/arch/cpu/simplelink-cc13xx-cc26xx/dev/watchdog-arch.h
new file mode 100644
index 0000000000000000000000000000000000000000..f86538973b3beec21fa8889b24a40b34e90d9045
--- /dev/null
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/dev/watchdog-arch.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+ /**
+ * \addtogroup cc13xx-cc26xx-cpu
+ * @{
+ *
+ * \defgroup cc13xx-cc26xx-watchdog CC13xx/CC26xx watchdog timer driver.
+ *
+ * @{
+ *
+ * \file
+ *        Header file of the CC13xx/CC26xx watchdog driver.
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef WATCHDOG_ARCH_H_
+#define WATCHDOG_ARCH_H_
+/*---------------------------------------------------------------------------*/
+#include "contiki.h"
+/*---------------------------------------------------------------------------*/
+#define WATCHDOG_DISABLE     WATCHDOG_CONF_DISABLE
+#define WATCHDOG_TIMEOUT_MS  WATCHDOG_CONF_TIMEOUT_MS
+/*---------------------------------------------------------------------------*/
+/**
+ * \brief   Return the next expiration time for the Watchdog.
+ * \return  Non-zero value of the next expiration time in Watchdog ticks. If
+ *          the Watchdog is not running, this returns 0.
+ */
+uint32_t watchdog_arch_next_timeout(void);
+/*---------------------------------------------------------------------------*/
+#endif /* WATCHDOG_ARCH_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ * @}
+ */
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/ble-settings.c b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/ble-settings.c
index 7fc79ae2dcea4b2366356213444f70513f6d7937..f9902f826f7bd3ac176d50075c59507b76a7758d 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/ble-settings.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/ble-settings.c
@@ -56,12 +56,18 @@
 /* TI-RTOS RF Mode Object */
 RF_Mode rf_ble_mode =
 {
-  .rfMode = RF_MODE_BLE,
+  .rfMode = RF_MODE_MULTIPLE,
   .cpePatchFxn = &rf_patch_cpe_ble,
   .mcePatchFxn = 0,
   .rfePatchFxn = &rf_patch_rfe_ble,
 };
 /*---------------------------------------------------------------------------*/
+/*
+ * CMD_RADIO_SETUP must be configured with default TX power value
+ * in the .txPower field.
+ */
+#define DEFAULT_TX_POWER    0x5F3C /* 5 dBm */
+/*---------------------------------------------------------------------------*/
 /* Overrides for CMD_RADIO_SETUP */
 uint32_t rf_ble_overrides[] CC_ALIGN(4) =
 {
@@ -109,46 +115,14 @@ rfc_CMD_RADIO_SETUP_t rf_ble_cmd_radio_setup =
   .condition.nSkip = 0x0,
   .mode = 0x00,
   .loDivider = 0x00,
-  .config.frontEndMode = 0x0,
-  .config.biasMode = 0x0,
+  .config.frontEndMode = 0x0, /* set by driver */
+  .config.biasMode = 0x0, /* set by driver */
   .config.analogCfgMode = 0x0,
   .config.bNoFsPowerUp = 0x0,
-  .txPower = 0x3D3F,
+  .txPower = DEFAULT_TX_POWER,
   .pRegOverride = rf_ble_overrides,
 };
 /*---------------------------------------------------------------------------*/
-/* Structure for CMD_BLE_ADV_NC.pParams */
-rfc_bleAdvPar_t rf_ble_adv_par =
-{
-  .pRxQ = 0,
-  .rxConfig.bAutoFlushIgnored = 0x0,
-  .rxConfig.bAutoFlushCrcErr = 0x0,
-  .rxConfig.bAutoFlushEmpty = 0x0,
-  .rxConfig.bIncludeLenByte = 0x0,
-  .rxConfig.bIncludeCrc = 0x0,
-  .rxConfig.bAppendRssi = 0x0,
-  .rxConfig.bAppendStatus = 0x0,
-  .rxConfig.bAppendTimestamp = 0x0,
-  .advConfig.advFilterPolicy = 0x0,
-  .advConfig.deviceAddrType = 0x0,
-  .advConfig.peerAddrType = 0x0,
-  .advConfig.bStrictLenFilter = 0x0,
-  .advConfig.rpaMode = 0x0,
-  .advLen = 0x18,
-  .scanRspLen = 0x00,
-  .pAdvData = 0,
-  .pScanRspData = 0,
-  .pDeviceAddress = 0,
-  .pWhiteList = 0,
-  .__dummy0 = 0x0000,
-  .__dummy1 = 0x00,
-  .endTrigger.triggerType = TRIG_NEVER,
-  .endTrigger.bEnaCmd = 0x0,
-  .endTrigger.triggerNo = 0x0,
-  .endTrigger.pastTrig = 0x0,
-  .endTime = 0x00000000,
-};
-/*---------------------------------------------------------------------------*/
 /* CMD_BLE_ADV_NC: BLE Non-Connectable Advertiser Command */
 rfc_CMD_BLE_ADV_NC_t rf_ble_cmd_ble_adv_nc =
 {
@@ -159,13 +133,13 @@ rfc_CMD_BLE_ADV_NC_t rf_ble_cmd_ble_adv_nc =
   .startTrigger.triggerType = TRIG_NOW,
   .startTrigger.bEnaCmd = 0x0,
   .startTrigger.triggerNo = 0x0,
-  .startTrigger.pastTrig = 0x0,
-  .condition.rule = COND_NEVER,
+  .startTrigger.pastTrig = 0x1,
+  .condition.rule = 0x0, /* set by driver */
   .condition.nSkip = 0x0,
-  .channel = 0x8C,
-  .whitening.init = 0x51,
+  .channel = 0x00, /* set by driver */
+  .whitening.init = 0x00, /* set by driver */
   .whitening.bOverride = 0x1,
-  .pParams = &rf_ble_adv_par,
-  .pOutput = 0,
+  .pParams = 0x00000000, /* set by driver */
+  .pOutput = 0x00000000, /* set by driver */
 };
 /*---------------------------------------------------------------------------*/
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/ble-settings.h b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/ble-settings.h
index 81fbf67ba040c4f9aa1d2650bd75fdf412d98050..4d94edca8605eb46a9fd8b47482a46e1ad10aab5 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/ble-settings.h
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/ble-settings.h
@@ -43,7 +43,6 @@ extern RF_Mode               rf_ble_mode;
 /*---------------------------------------------------------------------------*/
 /* RF Core API commands */
 extern rfc_CMD_RADIO_SETUP_t rf_ble_cmd_radio_setup;
-extern rfc_bleAdvPar_t       rf_ble_adv_par;
 extern rfc_CMD_BLE_ADV_NC_t  rf_ble_cmd_ble_adv_nc;
 /*---------------------------------------------------------------------------*/
 /* RF Core API Overrides */
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/ieee-settings.c b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/ieee-settings.c
index 2a383e6c6301166f13a0c883eb02f4a22bddc6a0..1537f693ce30e4931aca0b8ad2ce4ffb0fa7c4aa 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/ieee-settings.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/ieee-settings.c
@@ -57,7 +57,7 @@
 /* TI-RTOS RF Mode Object */
 RF_Mode rf_ieee_mode =
 {
-  .rfMode = RF_MODE_IEEE_15_4,
+  .rfMode = RF_MODE_MULTIPLE,
   .cpePatchFxn = 0,
   .mcePatchFxn = 0,
   .rfePatchFxn = 0,
@@ -110,8 +110,8 @@ rfc_CMD_RADIO_SETUP_t rf_cmd_ieee_radio_setup =
   .condition.rule = COND_NEVER,
   .condition.nSkip = 0x0,
   .mode = 0x01,
-  .config.frontEndMode = 0x0,
-  .config.biasMode = 0x0,
+  .config.frontEndMode = 0x0, /* set by driver */
+  .config.biasMode = 0x0, /* set by driver */
   .config.analogCfgMode = 0x0,
   .config.bNoFsPowerUp = 0x0,
   .txPower = DEFAULT_TX_POWER, /* 5 dBm default */
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/prop-settings.c b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/prop-settings.c
index 64dbe591f486614acd658c42e3d905870e5e002f..3d57fc3a3ba43afc9cf411e8ad40720ff4f4da06 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/prop-settings.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x0/prop-settings.c
@@ -68,7 +68,7 @@
 /* TI-RTOS RF Mode Object */
 RF_Mode rf_prop_mode =
 {
-  .rfMode = RF_MODE_PROPRIETARY_SUB_1,
+  .rfMode = RF_MODE_MULTIPLE,
   .cpePatchFxn = &rf_patch_cpe_genfsk,
   .mcePatchFxn = 0,
   .rfePatchFxn = &rf_patch_rfe_genfsk,
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/ble-settings.c b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/ble-settings.c
index b9e32a04d604a61b06e5d5bb783330653c436eb4..b43ce21a694b1f354e7835097ac9eedc62360716 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/ble-settings.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/ble-settings.c
@@ -47,7 +47,7 @@
 #include DeviceFamily_constructPath(driverlib/rf_mailbox.h)
 #include DeviceFamily_constructPath(driverlib/rf_common_cmd.h)
 #include DeviceFamily_constructPath(driverlib/rf_ble_cmd.h)
-#include DeviceFamily_constructPath(rf_patches/rf_patch_cpe_bt5.h)
+#include DeviceFamily_constructPath(rf_patches/rf_patch_cpe_multi_protocol.h)
 #include DeviceFamily_constructPath(rf_patches/rf_patch_rfe_bt5.h)
 #include DeviceFamily_constructPath(rf_patches/rf_patch_mce_bt5.h)
 
@@ -59,11 +59,17 @@
 RF_Mode rf_ble_mode =
 {
   .rfMode = RF_MODE_AUTO,
-  .cpePatchFxn = &rf_patch_cpe_bt5,
+  .cpePatchFxn = &rf_patch_cpe_multi_protocol,
   .mcePatchFxn = &rf_patch_mce_bt5,
   .rfePatchFxn = &rf_patch_rfe_bt5,
 };
 /*---------------------------------------------------------------------------*/
+/*
+ * CMD_RADIO_SETUP must be configured with default TX power value
+ * in the .txPower field.
+ */
+#define DEFAULT_TX_POWER    0x941E /* 5 dBm */
+/*---------------------------------------------------------------------------*/
 /* Overrides for CMD_BLE5_RADIO_SETUP */
 uint32_t rf_ble_overrides_common[] CC_ALIGN(4) =
 {
@@ -137,71 +143,39 @@ rfc_CMD_BLE5_RADIO_SETUP_t rf_ble_cmd_radio_setup =
   .defaultPhy.mainMode = 0x0,
   .defaultPhy.coding = 0x0,
   .loDivider = 0x00,
-  .config.frontEndMode = 0x0,
-  .config.biasMode = 0x0,
+  .config.frontEndMode = 0x0, /* set by driver */
+  .config.biasMode = 0x0, /* set by driver */
   .config.analogCfgMode = 0x0,
   .config.bNoFsPowerUp = 0x0,
-  .txPower = 0x941E,
+  .txPower = DEFAULT_TX_POWER,
   .pRegOverrideCommon = rf_ble_overrides_common,
   .pRegOverride1Mbps = rf_ble_overrides_1mbps,
   .pRegOverride2Mbps = rf_ble_overrides_2mbps,
   .pRegOverrideCoded = rf_ble_overrides_coded,
 };
 /*---------------------------------------------------------------------------*/
-/* Structure for CMD_BLE5_ADV_NC.pParams */
-rfc_bleAdvPar_t rf_ble_adv_par =
-{
-  .pRxQ = 0,
-  .rxConfig.bAutoFlushIgnored = 0x0,
-  .rxConfig.bAutoFlushCrcErr = 0x0,
-  .rxConfig.bAutoFlushEmpty = 0x0,
-  .rxConfig.bIncludeLenByte = 0x0,
-  .rxConfig.bIncludeCrc = 0x0,
-  .rxConfig.bAppendRssi = 0x0,
-  .rxConfig.bAppendStatus = 0x0,
-  .rxConfig.bAppendTimestamp = 0x0,
-  .advConfig.advFilterPolicy = 0x0,
-  .advConfig.deviceAddrType = 0x0,
-  .advConfig.peerAddrType = 0x0,
-  .advConfig.bStrictLenFilter = 0x0,
-  .advConfig.rpaMode = 0x0,
-  .advLen = 0x18,
-  .scanRspLen = 0x00,
-  .pAdvData = 0,
-  .pScanRspData = 0,
-  .pDeviceAddress = 0,
-  .pWhiteList = 0,
-  .__dummy0 = 0x0000,
-  .__dummy1 = 0x00,
-  .endTrigger.triggerType = TRIG_NEVER,
-  .endTrigger.bEnaCmd = 0x0,
-  .endTrigger.triggerNo = 0x0,
-  .endTrigger.pastTrig = 0x0,
-  .endTime = 0x00000000,
-};
-/*---------------------------------------------------------------------------*/
 /* CMD_BLE5_ADV_NC: Bluetooth 5 Non-Connectable Advertiser Command */
 rfc_CMD_BLE5_ADV_NC_t rf_ble_cmd_ble_adv_nc =
 {
-  .commandNo = 0x182D,
-  .status = 0x0000,
-  .pNextOp = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
+  .commandNo = CMD_BLE5_ADV_NC,
+  .status = IDLE,
+  .pNextOp = 0,
   .startTime = 0x00000000,
-  .startTrigger.triggerType = 0x0,
+  .startTrigger.triggerType = TRIG_NOW,
   .startTrigger.bEnaCmd = 0x0,
   .startTrigger.triggerNo = 0x0,
-  .startTrigger.pastTrig = 0x0,
-  .condition.rule = 0x1,
+  .startTrigger.pastTrig = 0x1,
+  .condition.rule = 0x0, /* set by driver */
   .condition.nSkip = 0x0,
-  .channel = 0x8C,
-  .whitening.init = 0x51,
+  .channel = 0x00, /* set by driver */
+  .whitening.init = 0x00, /* set by driver */
   .whitening.bOverride = 0x1,
   .phyMode.mainMode = 0x0,
   .phyMode.coding = 0x0,
   .rangeDelay = 0x00,
   .txPower = 0x0000,
-  .pParams = &rf_ble_adv_par,
-  .pOutput = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
+  .pParams = 0x00000000, /* set by driver */
+  .pOutput = 0x00000000, /* set by driver */
   .tx20Power = 0x00000000,
 };
 /*---------------------------------------------------------------------------*/
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/ble-settings.h b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/ble-settings.h
index 2e6defa71453d333dc5e73762fdde6a143c8d9ba..c5295c868d779d1cd2ce5fa932a3c3815e72aaf7 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/ble-settings.h
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/ble-settings.h
@@ -43,7 +43,6 @@ extern RF_Mode                    rf_ble_mode;
 /*---------------------------------------------------------------------------*/
 /* RF Core API commands */
 extern rfc_CMD_BLE5_RADIO_SETUP_t rf_ble_cmd_radio_setup;
-extern rfc_bleAdvPar_t            rf_ble_adv_par;
 extern rfc_CMD_BLE5_ADV_NC_t      rf_ble_cmd_ble_adv_nc;
 /*---------------------------------------------------------------------------*/
 /* RF Core API Overrides */
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/ieee-settings.c b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/ieee-settings.c
index 1f5e3d8d7ba18240da0fab97fc76eee426f699f6..a81a8338586dd989e44ff6e2487984eea24e2779 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/ieee-settings.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/ieee-settings.c
@@ -51,7 +51,7 @@
 #include DeviceFamily_constructPath(driverlib/rf_mailbox.h)
 #include DeviceFamily_constructPath(driverlib/rf_common_cmd.h)
 #include DeviceFamily_constructPath(driverlib/rf_ieee_cmd.h)
-#include DeviceFamily_constructPath(rf_patches/rf_patch_cpe_ieee_802_15_4.h)
+#include DeviceFamily_constructPath(rf_patches/rf_patch_cpe_multi_protocol.h)
 #include DeviceFamily_constructPath(rf_patches/rf_patch_mce_ieee_802_15_4.h)
 
 #include <ti/drivers/rf/RF.h>
@@ -62,7 +62,7 @@
 RF_Mode rf_ieee_mode =
 {
   .rfMode = RF_MODE_AUTO,
-  .cpePatchFxn = &rf_patch_cpe_ieee_802_15_4,
+  .cpePatchFxn = &rf_patch_cpe_multi_protocol,
   .mcePatchFxn = &rf_patch_mce_ieee_802_15_4,
   .rfePatchFxn = 0,
 };
@@ -180,8 +180,8 @@ rfc_CMD_RADIO_SETUP_t rf_cmd_ieee_radio_setup =
   .condition.nSkip = 0x0,
   .mode = 0x01,
   .loDivider = 0x00,
-  .config.frontEndMode = 0x0,
-  .config.biasMode = 0x0,
+  .config.frontEndMode = 0x0, /* set by driver */
+  .config.biasMode = 0x0, /* set by driver */
   .config.analogCfgMode = 0x0,
   .config.bNoFsPowerUp = 0x0,
   .txPower = DEFAULT_TX_POWER, /* 5 dBm default */
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/prop-settings.c b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/prop-settings.c
index c63e6bef7437715ed5a3e27742b713cb037dbb4f..0f098c5e15fb4b4db7a4523e26b9677dbb2f72ec 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/prop-settings.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc13x2/prop-settings.c
@@ -63,7 +63,7 @@
 #include DeviceFamily_constructPath(driverlib/rf_mailbox.h)
 #include DeviceFamily_constructPath(driverlib/rf_common_cmd.h)
 #include DeviceFamily_constructPath(driverlib/rf_prop_cmd.h)
-#include DeviceFamily_constructPath(rf_patches/rf_patch_cpe_prop.h)
+#include DeviceFamily_constructPath(rf_patches/rf_patch_cpe_multi_protocol.h)
 #include DeviceFamily_constructPath(rf_patches/rf_patch_rfe_genfsk.h)
 #include DeviceFamily_constructPath(rf_patches/rf_patch_mce_genfsk.h)
 
@@ -75,7 +75,7 @@
 RF_Mode rf_prop_mode =
 {
   .rfMode = RF_MODE_AUTO,
-  .cpePatchFxn = &rf_patch_cpe_prop,
+  .cpePatchFxn = &rf_patch_cpe_multi_protocol,
   .mcePatchFxn = &rf_patch_mce_genfsk,
   .rfePatchFxn = &rf_patch_rfe_genfsk,
 };
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x0/ble-settings.c b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x0/ble-settings.c
index 7edc3e487914c269c70f114f4e37b61b55b92b14..9c19021fdfdd2a1a8149c1f3441717a378c115fb 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x0/ble-settings.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x0/ble-settings.c
@@ -55,12 +55,18 @@
 /* TI-RTOS RF Mode Object */
 RF_Mode rf_ble_mode =
 {
-  .rfMode = RF_MODE_BLE,
+  .rfMode = RF_MODE_MULTIPLE,
   .cpePatchFxn = &rf_patch_cpe_ble,
   .mcePatchFxn = 0,
   .rfePatchFxn = &rf_patch_rfe_ble,
 };
 /*---------------------------------------------------------------------------*/
+/*
+ * CMD_RADIO_SETUP must be configured with default TX power value
+ * in the .txPower field.
+ */
+#define DEFAULT_TX_POWER    0x9330 /* 5 dBm */
+/*---------------------------------------------------------------------------*/
 /* Overrides for CMD_RADIO_SETUP */
 uint32_t rf_ble_overrides[] CC_ALIGN(4) =
 {
@@ -105,46 +111,14 @@ rfc_CMD_RADIO_SETUP_t rf_ble_cmd_radio_setup =
   .condition.nSkip = 0x0,
   .mode = 0x00,
   .__dummy0 = 0x00,
-  .config.frontEndMode = 0x0,
-  .config.biasMode = 0x0,
+  .config.frontEndMode = 0x0, /* set by driver */
+  .config.biasMode = 0x0, /* set by driver */
   .config.analogCfgMode = 0x0,
   .config.bNoFsPowerUp = 0x0,
-  .txPower = 0x9330,
+  .txPower = DEFAULT_TX_POWER,
   .pRegOverride = rf_ble_overrides,
 };
 /*---------------------------------------------------------------------------*/
-/* Structure for CMD_BLE_ADV_NC.pParams */
-rfc_bleAdvPar_t rf_ble_adv_par =
-{
-  .pRxQ = 0,
-  .rxConfig.bAutoFlushIgnored = 0x0,
-  .rxConfig.bAutoFlushCrcErr = 0x0,
-  .rxConfig.bAutoFlushEmpty = 0x0,
-  .rxConfig.bIncludeLenByte = 0x0,
-  .rxConfig.bIncludeCrc = 0x0,
-  .rxConfig.bAppendRssi = 0x0,
-  .rxConfig.bAppendStatus = 0x0,
-  .rxConfig.bAppendTimestamp = 0x0,
-  .advConfig.advFilterPolicy = 0x0,
-  .advConfig.deviceAddrType = 0x0,
-  .advConfig.peerAddrType = 0x0,
-  .advConfig.bStrictLenFilter = 0x0,
-  .advConfig.rpaMode = 0x0,
-  .advLen = 0x18,
-  .scanRspLen = 0x00,
-  .pAdvData = 0,
-  .pScanRspData = 0,
-  .pDeviceAddress = 0,
-  .pWhiteList = 0,
-  .__dummy0 = 0x0000,
-  .__dummy1 = 0x00,
-  .endTrigger.triggerType = TRIG_NEVER,
-  .endTrigger.bEnaCmd = 0x0,
-  .endTrigger.triggerNo = 0x0,
-  .endTrigger.pastTrig = 0x0,
-  .endTime = 0x00000000,
-};
-/*---------------------------------------------------------------------------*/
 /* CMD_BLE_ADV_NC: BLE Non-Connectable Advertiser Command */
 rfc_CMD_BLE_ADV_NC_t rf_ble_cmd_ble_adv_nc =
 {
@@ -155,13 +129,13 @@ rfc_CMD_BLE_ADV_NC_t rf_ble_cmd_ble_adv_nc =
   .startTrigger.triggerType = TRIG_NOW,
   .startTrigger.bEnaCmd = 0x0,
   .startTrigger.triggerNo = 0x0,
-  .startTrigger.pastTrig = 0x0,
-  .condition.rule = COND_NEVER,
+  .startTrigger.pastTrig = 0x1,
+  .condition.rule = 0x0, /* set by driver */
   .condition.nSkip = 0x0,
-  .channel = 0x8C,
-  .whitening.init = 0x51,
+  .channel = 0x00, /* set by driver */
+  .whitening.init = 0x00, /* set by driver */
   .whitening.bOverride = 0x1,
-  .pParams = &rf_ble_adv_par,
-  .pOutput = 0,
+  .pParams = 0x00000000, /* set by driver */
+  .pOutput = 0x00000000, /* set by driver */
 };
 /*---------------------------------------------------------------------------*/
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x0/ble-settings.h b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x0/ble-settings.h
index c893041055847710c7a41c5d72dc14d1d8a236f9..0679265d6f9dab63d729f353fdc67a7a73b27467 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x0/ble-settings.h
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x0/ble-settings.h
@@ -43,7 +43,6 @@ extern RF_Mode                rf_ble_mode;
 /*---------------------------------------------------------------------------*/
 /* RF Core API commands */
 extern rfc_CMD_RADIO_SETUP_t  rf_ble_cmd_radio_setup;
-extern rfc_bleAdvPar_t        rf_ble_adv_par;
 extern rfc_CMD_BLE_ADV_NC_t   rf_ble_cmd_ble_adv_nc;
 /*---------------------------------------------------------------------------*/
 /* RF Core API Overrides */
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x0/ieee-settings.c b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x0/ieee-settings.c
index e9356196223f73b3007c0e680d1461ba279b4665..4d860109d707694104302459003e762679049025 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x0/ieee-settings.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x0/ieee-settings.c
@@ -53,7 +53,7 @@
 /* TI-RTOS RF Mode Object */
 RF_Mode rf_ieee_mode =
 {
-  .rfMode = RF_MODE_IEEE_15_4,
+  .rfMode = RF_MODE_MULTIPLE,
   .cpePatchFxn = &rf_patch_cpe_ieee,
   .mcePatchFxn = 0,
   .rfePatchFxn = 0,
@@ -107,8 +107,8 @@ rfc_CMD_RADIO_SETUP_t rf_cmd_ieee_radio_setup =
   .condition.nSkip = 0x0,
   .mode = 0x01,
   .__dummy0 = 0x00,
-  .config.frontEndMode = 0x0,
-  .config.biasMode = 0x0,
+  .config.frontEndMode = 0x0, /* set by driver */
+  .config.biasMode = 0x0, /* set by driver */
   .config.analogCfgMode = 0x0,
   .config.bNoFsPowerUp = 0x0,
   .txPower = DEFAULT_TX_POWER, /* 5 dBm default */
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x2/ble-settings.c b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x2/ble-settings.c
index 8ee2b2684c32296db0ed126001b60bfe866ed83c..21ed73201961fa0c2f313edd9c8e0c0e26229449 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x2/ble-settings.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x2/ble-settings.c
@@ -46,7 +46,7 @@
 #include DeviceFamily_constructPath(driverlib/rf_mailbox.h)
 #include DeviceFamily_constructPath(driverlib/rf_common_cmd.h)
 #include DeviceFamily_constructPath(driverlib/rf_ble_cmd.h)
-#include DeviceFamily_constructPath(rf_patches/rf_patch_cpe_bt5.h)
+#include DeviceFamily_constructPath(rf_patches/rf_patch_cpe_multi_protocol.h)
 #include DeviceFamily_constructPath(rf_patches/rf_patch_rfe_bt5.h)
 #include DeviceFamily_constructPath(rf_patches/rf_patch_mce_bt5.h)
 
@@ -58,11 +58,17 @@
 RF_Mode rf_ble_mode =
 {
   .rfMode = RF_MODE_AUTO,
-  .cpePatchFxn = &rf_patch_cpe_bt5,
+  .cpePatchFxn = &rf_patch_cpe_multi_protocol,
   .mcePatchFxn = &rf_patch_mce_bt5,
   .rfePatchFxn = &rf_patch_rfe_bt5,
 };
 /*---------------------------------------------------------------------------*/
+/*
+ * CMD_RADIO_SETUP must be configured with default TX power value
+ * in the .txPower field.
+ */
+#define DEFAULT_TX_POWER    0x941E /* 5 dBm */
+/*---------------------------------------------------------------------------*/
 /* Overrides for CMD_BLE5_RADIO_SETUP */
 uint32_t rf_ble_overrides_common[] CC_ALIGN(4) =
 {
@@ -137,71 +143,39 @@ rfc_CMD_BLE5_RADIO_SETUP_t rf_ble_cmd_radio_setup =
   .defaultPhy.mainMode = 0x0,
   .defaultPhy.coding = 0x0,
   .loDivider = 0x00,
-  .config.frontEndMode = 0x0,
-  .config.biasMode = 0x0,
+  .config.frontEndMode = 0x0, /* set by driver */
+  .config.biasMode = 0x0, /* set by driver */
   .config.analogCfgMode = 0x0,
   .config.bNoFsPowerUp = 0x0,
-  .txPower = 0x941E,
+  .txPower = DEFAULT_TX_POWER,
   .pRegOverrideCommon = rf_ble_overrides_common,
   .pRegOverride1Mbps = rf_ble_overrides_1mbps,
   .pRegOverride2Mbps = rf_ble_overrides_2mbps,
   .pRegOverrideCoded = rf_ble_overrides_coded,
 };
 /*---------------------------------------------------------------------------*/
-/* Structure for CMD_BLE5_ADV_NC.pParams */
-rfc_bleAdvPar_t rf_ble_adv_par =
-{
-  .pRxQ = 0,
-  .rxConfig.bAutoFlushIgnored = 0x0,
-  .rxConfig.bAutoFlushCrcErr = 0x0,
-  .rxConfig.bAutoFlushEmpty = 0x0,
-  .rxConfig.bIncludeLenByte = 0x0,
-  .rxConfig.bIncludeCrc = 0x0,
-  .rxConfig.bAppendRssi = 0x0,
-  .rxConfig.bAppendStatus = 0x0,
-  .rxConfig.bAppendTimestamp = 0x0,
-  .advConfig.advFilterPolicy = 0x0,
-  .advConfig.deviceAddrType = 0x0,
-  .advConfig.peerAddrType = 0x0,
-  .advConfig.bStrictLenFilter = 0x0,
-  .advConfig.rpaMode = 0x0,
-  .advLen = 0x18,
-  .scanRspLen = 0x00,
-  .pAdvData = 0,
-  .pScanRspData = 0,
-  .pDeviceAddress = 0,
-  .pWhiteList = 0,
-  .__dummy0 = 0x0000,
-  .__dummy1 = 0x00,
-  .endTrigger.triggerType = TRIG_NEVER,
-  .endTrigger.bEnaCmd = 0x0,
-  .endTrigger.triggerNo = 0x0,
-  .endTrigger.pastTrig = 0x0,
-  .endTime = 0x00000000,
-};
-/*---------------------------------------------------------------------------*/
 /* CMD_BLE5_ADV_NC: Bluetooth 5 Non-Connectable Advertiser Command */
 rfc_CMD_BLE5_ADV_NC_t rf_ble_cmd_ble_adv_nc =
 {
-  .commandNo = 0x182D,
-  .status = 0x0000,
-  .pNextOp = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
+  .commandNo = CMD_BLE5_ADV_NC,
+  .status = IDLE,
+  .pNextOp = 0,
   .startTime = 0x00000000,
-  .startTrigger.triggerType = 0x0,
+  .startTrigger.triggerType = TRIG_NOW,
   .startTrigger.bEnaCmd = 0x0,
   .startTrigger.triggerNo = 0x0,
-  .startTrigger.pastTrig = 0x0,
-  .condition.rule = 0x1,
+  .startTrigger.pastTrig = 0x1,
+  .condition.rule = 0x0, /* set by driver */
   .condition.nSkip = 0x0,
-  .channel = 0x8C,
-  .whitening.init = 0x51,
+  .channel = 0x00, /* set by driver */
+  .whitening.init = 0x00, /* set by driver */
   .whitening.bOverride = 0x1,
   .phyMode.mainMode = 0x0,
   .phyMode.coding = 0x0,
   .rangeDelay = 0x00,
   .txPower = 0x0000,
-  .pParams = &rf_ble_adv_par,
-  .pOutput = 0, // INSERT APPLICABLE POINTER: (uint8_t*)&xxx
+  .pParams = 0x00000000, /* set by driver */
+  .pOutput = 0x00000000, /* set by driver */
   .tx20Power = 0x00000000,
 };
 /*---------------------------------------------------------------------------*/
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x2/ble-settings.h b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x2/ble-settings.h
index 2e6defa71453d333dc5e73762fdde6a143c8d9ba..c5295c868d779d1cd2ce5fa932a3c3815e72aaf7 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x2/ble-settings.h
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x2/ble-settings.h
@@ -43,7 +43,6 @@ extern RF_Mode                    rf_ble_mode;
 /*---------------------------------------------------------------------------*/
 /* RF Core API commands */
 extern rfc_CMD_BLE5_RADIO_SETUP_t rf_ble_cmd_radio_setup;
-extern rfc_bleAdvPar_t            rf_ble_adv_par;
 extern rfc_CMD_BLE5_ADV_NC_t      rf_ble_cmd_ble_adv_nc;
 /*---------------------------------------------------------------------------*/
 /* RF Core API Overrides */
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x2/ieee-settings.c b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x2/ieee-settings.c
index cc012da89962b33d3a01f35b85f4ce8e61b2607b..d95ff87ba3390ec216bd8f8c87229dae6e038f55 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x2/ieee-settings.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf-settings/cc26x2/ieee-settings.c
@@ -44,7 +44,7 @@
 #include DeviceFamily_constructPath(driverlib/rf_mailbox.h)
 #include DeviceFamily_constructPath(driverlib/rf_common_cmd.h)
 #include DeviceFamily_constructPath(driverlib/rf_ieee_cmd.h)
-#include DeviceFamily_constructPath(rf_patches/rf_patch_cpe_ieee_802_15_4.h)
+#include DeviceFamily_constructPath(rf_patches/rf_patch_cpe_multi_protocol.h)
 #include DeviceFamily_constructPath(rf_patches/rf_patch_mce_ieee_802_15_4.h)
 
 #include <ti/drivers/rf/RF.h>
@@ -55,7 +55,7 @@
 RF_Mode rf_ieee_mode =
 {
   .rfMode = RF_MODE_AUTO,
-  .cpePatchFxn = &rf_patch_cpe_ieee_802_15_4,
+  .cpePatchFxn = &rf_patch_cpe_multi_protocol,
   .mcePatchFxn = &rf_patch_mce_ieee_802_15_4,
   .rfePatchFxn = 0,
 };
@@ -104,8 +104,8 @@ rfc_CMD_RADIO_SETUP_t rf_cmd_ieee_radio_setup =
   .condition.nSkip = 0x0,
   .mode = 0x01,
   .loDivider = 0x00,
-  .config.frontEndMode = 0x0,
-  .config.biasMode = 0x0,
+  .config.frontEndMode = 0x0, /* set by driver */
+  .config.biasMode = 0x0, /* set by driver */
   .config.analogCfgMode = 0x0,
   .config.bNoFsPowerUp = 0x0,
   .txPower = DEFAULT_TX_POWER,
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf/ble-addr.c b/arch/cpu/simplelink-cc13xx-cc26xx/rf/ble-addr.c
index 357e7e7c574694baefedc1d514736eae9ce81601..7a445a2299cba226dc2785030f2706f7a20c32a0 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf/ble-addr.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf/ble-addr.c
@@ -81,7 +81,7 @@ ble_addr_ptr(void)
 }
 /*---------------------------------------------------------------------------*/
 int
-ble_addr_cpy(uint8_t *dst)
+ble_addr_be_cpy(uint8_t *dst)
 {
   if(!dst) {
     return -1;
@@ -102,6 +102,23 @@ ble_addr_cpy(uint8_t *dst)
 }
 /*---------------------------------------------------------------------------*/
 int
+ble_addr_le_cpy(uint8_t *dst)
+{
+  if(!dst) {
+    return -1;
+  }
+
+  volatile const uint8_t *const ble_addr = ble_addr_ptr();
+
+  size_t i;
+  for(i = 0; i < BLE_ADDR_SIZE; i++) {
+    dst[i] = ble_addr[i];
+  }
+
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
+int
 ble_addr_to_eui64(uint8_t *dst, uint8_t *src)
 {
   if(!dst || !src) {
@@ -126,7 +143,7 @@ ble_addr_to_eui64_cpy(uint8_t *dst)
   int res;
   uint8_t ble_addr[BLE_ADDR_SIZE];
 
-  res = ble_addr_cpy(ble_addr);
+  res = ble_addr_le_cpy(ble_addr);
   if(res) {
     return -1;
   }
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf/ble-addr.h b/arch/cpu/simplelink-cc13xx-cc26xx/rf/ble-addr.h
index fd63c17d01f9eb143b76e35d9dc5df8846d27eba..effc95d2283d63931d7d58af72e56b5b0640365d 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf/ble-addr.h
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf/ble-addr.h
@@ -59,6 +59,7 @@ uint8_t *ble_addr_ptr(void);
 /*---------------------------------------------------------------------------*/
 /**
  * \brief Copy the node's factory BLE address to a destination memory area
+ *        in big-endian (be) order.
  * \param dst A pointer to the destination area where the BLE address is to be
  *            written
  * \return  0 : Returned successfully
@@ -68,7 +69,21 @@ uint8_t *ble_addr_ptr(void);
  * the process. The factory address on devices is normally little-endian,
  * therefore you should expect dst to store the address in a big-endian order.
  */
-int ble_addr_cpy(uint8_t *dst);
+int ble_addr_be_cpy(uint8_t *dst);
+/*---------------------------------------------------------------------------*/
+/**
+ * \brief Copy the node's factory BLE address to a destination memory area
+ *        in little-endian (le) order.
+ * \param dst A pointer to the destination area where the BLE address is to be
+ *            written
+ * \return  0 : Returned successfully
+ *         -1 : Returned with error
+ *
+ * This function will copy 6 bytes, but will **not** invert the byte order.
+ * This is usefull for the RF core which assumes the BLE MAC address in
+ * little-endian order.
+ */
+int ble_addr_le_cpy(uint8_t *dst);
 /*---------------------------------------------------------------------------*/
 /**
  * \brief Copy the node's BLE address to a destination memory area and converts
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf/ble-beacond.c b/arch/cpu/simplelink-cc13xx-cc26xx/rf/ble-beacond.c
index 383d168bea028aa68ae50ecace7e8bffdc864ea6..2e8d9d4bc8e920492a419888bb30f32641a22304 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf/ble-beacond.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf/ble-beacond.c
@@ -52,6 +52,7 @@
 
 #include <ti/drivers/rf/RF.h>
 /*---------------------------------------------------------------------------*/
+#include "rf/rf.h"
 #include "rf/sched.h"
 #include "rf/ble-addr.h"
 #include "rf/ble-beacond.h"
@@ -70,32 +71,58 @@
 /*---------------------------------------------------------------------------*/
 #if RF_CONF_BLE_BEACON_ENABLE
 /*---------------------------------------------------------------------------*/
-/* BLE Advertisement channels. Not to be changed by the user. */
-typedef enum {
-  BLE_ADV_CHANNEL_37 = (1 << 0),
-  BLE_ADV_CHANNEL_38 = (1 << 1),
-  BLE_ADV_CHANNEL_39 = (1 << 2),
-
-  BLE_ADV_CHANNEL_ALL = (BLE_ADV_CHANNEL_37 |
-                         BLE_ADV_CHANNEL_38 |
-                         BLE_ADV_CHANNEL_39),
-} ble_adv_channel_t;
-
-#define BLE_ADV_CHANNEL_MIN         37
-#define BLE_ADV_CHANNEL_MAX         39
-/*---------------------------------------------------------------------------*/
 /* Maximum BLE advertisement size. Not to be changed by the user. */
 #define BLE_ADV_MAX_SIZE            31
 /*---------------------------------------------------------------------------*/
-/* BLE Intervals: Send a burst of advertisements every BLE_ADV_INTERVAL secs */
-#define BLE_ADV_INTERVAL            (CLOCK_SECOND * 5)
-#define BLE_ADV_DUTY_CYCLE          (CLOCK_SECOND / 10)
-#define BLE_ADV_MESSAGES            10
-
-/* BLE Advertisement-related macros */
-#define BLE_ADV_TYPE_DEVINFO        0x01
-#define BLE_ADV_TYPE_NAME           0x09
-#define BLE_ADV_TYPE_MANUFACTURER   0xFF
+/*
+ * BLE Intervals: Send a burst of advertisements every BLE_ADV_INTERVAL
+ * specified in milliseconds.
+ */
+#define BLE_ADV_INTERVAL                        ((100 * CLOCK_SECOND) / 1000)
+
+/* GAP Advertisement data types */
+#define BLE_ADV_TYPE_FLAGS                      0x01
+#define BLE_ADV_TYPE_16BIT_MORE                 0x02
+#define BLE_ADV_TYPE_16BIT_COMPLETE             0x03
+#define BLE_ADV_TYPE_32BIT_MORE                 0x04
+#define BLE_ADV_TYPE_32BIT_COMPLETE             0x05
+#define BLE_ADV_TYPE_128BIT_MORE                0x06
+#define BLE_ADV_TYPE_128BIT_COMPLETE            0x07
+#define BLE_ADV_TYPE_LOCAL_NAME_SHORT           0x08
+#define BLE_ADV_TYPE_LOCAL_NAME_COMPLETE        0x09
+#define BLE_ADV_TYPE_POWER_LEVEL                0x0A
+#define BLE_ADV_TYPE_OOB_CLASS_OF_DEVICE        0x0D
+#define BLE_ADV_TYPE_OOB_SIMPLE_PAIRING_HASHC   0x0E
+#define BLE_ADV_TYPE_OOB_SIMPLE_PAIRING_RANDR   0x0F
+#define BLE_ADV_TYPE_SM_TK                      0x10
+#define BLE_ADV_TYPE_SM_OOB_FLAG                0x11
+#define BLE_ADV_TYPE_SLAVE_CONN_INTERVAL_RANGE  0x12
+#define BLE_ADV_TYPE_SIGNED_DATA                0x13
+#define BLE_ADV_TYPE_SERVICE_LIST_16BIT         0x14
+#define BLE_ADV_TYPE_SERVICE_LIST_128BIT        0x15
+#define BLE_ADV_TYPE_SERVICE_DATA               0x16
+#define BLE_ADV_TYPE_PUBLIC_TARGET_ADDR         0x17
+#define BLE_ADV_TYPE_RANDOM_TARGET_ADDR         0x18
+#define BLE_ADV_TYPE_APPEARANCE                 0x19
+#define BLE_ADV_TYPE_ADV_INTERVAL               0x1A
+#define BLE_ADV_TYPE_LE_BD_ADDR                 0x1B
+#define BLE_ADV_TYPE_LE_ROLE                    0x1C
+#define BLE_ADV_TYPE_SIMPLE_PAIRING_HASHC_256   0x1D
+#define BLE_ADV_TYPE_SIMPLE_PAIRING_RANDR_256   0x1E
+#define BLE_ADV_TYPE_SERVICE_DATA_32BIT         0x20
+#define BLE_ADV_TYPE_SERVICE_DATA_128BIT        0x21
+#define BLE_ADV_TYPE_3D_INFO_DATA               0x3D
+#define BLE_ADV_TYPE_MANUFACTURER_SPECIFIC      0xFF
+
+/* GAP Advertisement data type flags */
+
+/* Discovery Mode: LE Limited Discoverable Mode */
+#define BLE_ADV_TYPE_FLAGS_LIMITED              0x01
+/* Discovery Mode: LE General Discoverable Mode */
+#define BLE_ADV_TYPE_FLAGS_GENERAL              0x02
+/* Discovery Mode: BR/EDR Not Supported */
+#define BLE_ADV_TYPE_FLAGS_BREDR_NOT_SUPPORTED  0x04
+
 #define BLE_ADV_NAME_BUF_LEN        BLE_ADV_MAX_SIZE
 #define BLE_ADV_PAYLOAD_BUF_LEN     64
 #define BLE_UUID_SIZE               16
@@ -117,6 +144,11 @@ typedef struct {
 
   /* RF driver */
   RF_Handle rf_handle;
+
+  /* BLE command specific structures. Common accross BLE and BLE5. */
+  uint8_t ble_mac_addr[6];
+  rfc_bleAdvPar_t ble_adv_par;
+  rfc_bleAdvOutput_t ble_adv_output;
 } ble_beacond_t;
 
 static ble_beacond_t ble_beacond;
@@ -126,13 +158,13 @@ PROCESS(ble_beacond_process, "RF BLE Beacon Daemon Process");
 rf_ble_beacond_result_t
 rf_ble_beacond_init(void)
 {
-  ble_adv_par.pDeviceAddress = (uint16_t *)ble_addr_ptr();
+  ble_cmd_radio_setup.config.frontEndMode = RF_2_4_GHZ_FRONT_END_MODE;
+  ble_cmd_radio_setup.config.biasMode = RF_2_4_GHZ_BIAS_MODE;
 
   RF_Params rf_params;
   RF_Params_init(&rf_params);
 
-  /* Should immediately turn off radio if possible */
-  rf_params.nInactivityTimeout = 0;
+  rf_params.nInactivityTimeout = RF_CONF_INACTIVITY_TIMEOUT;
 
   ble_beacond.rf_handle = ble_open(&rf_params);
 
@@ -140,6 +172,18 @@ rf_ble_beacond_init(void)
     return RF_BLE_BEACOND_ERROR;
   }
 
+  /*
+   * It is important that the contents of the BLE MAC address is copied into
+   * RAM, as the System CPU, and subsequently flash, goes idle when pending
+   * on an RF command. This causes pend to hang forever.
+   */
+  ble_addr_le_cpy(ble_beacond.ble_mac_addr);
+  ble_beacond.ble_adv_par.pDeviceAddress = (uint16_t *)ble_beacond.ble_mac_addr;
+  ble_beacond.ble_adv_par.endTrigger.triggerType = TRIG_NEVER;
+
+  rf_ble_cmd_ble_adv_nc.pParams = &ble_beacond.ble_adv_par;
+  rf_ble_cmd_ble_adv_nc.pOutput = &ble_beacond.ble_adv_output;
+
   return RF_BLE_BEACOND_OK;
 }
 /*---------------------------------------------------------------------------*/
@@ -154,12 +198,14 @@ rf_ble_beacond_config(clock_time_t interval, const char *name)
     ble_beacond.ble_adv_interval = interval;
 
     res = RF_BLE_BEACOND_OK;
+  } else {
+    ble_beacond.ble_adv_interval = BLE_ADV_INTERVAL;
   }
 
   if(name != NULL) {
     const size_t name_len = strlen(name);
 
-    if((name_len == 0) || (name_len >= BLE_ADV_NAME_BUF_LEN)) {
+    if((0 < name_len) && (name_len < BLE_ADV_NAME_BUF_LEN)) {
       ble_beacond.adv_name_len = name_len;
       memcpy(ble_beacond.adv_name, name, name_len);
 
@@ -235,37 +281,9 @@ rf_ble_get_tx_power(void)
   return dbm;
 }
 /*---------------------------------------------------------------------------*/
-static rf_ble_beacond_result_t
-ble_beacon_burst(uint8_t channels_bm, uint8_t *data, uint8_t len)
-{
-  rf_result_t res;
-
-  uint8_t channel;
-  for(channel = BLE_ADV_CHANNEL_MIN; channel <= BLE_ADV_CHANNEL_MAX; ++channel) {
-    const uint8_t channel_bv = (1 << (channel - BLE_ADV_CHANNEL_MIN));
-    if((channel_bv & channels_bm) == 0) {
-      continue;
-    }
-
-    ble_adv_par.advLen = len;
-    ble_adv_par.pAdvData = data;
-
-    ble_cmd_beacon.channel = channel;
-
-    res = ble_sched_beacon(NULL, 0);
-
-    if(res != RF_RESULT_OK) {
-      return RF_BLE_BEACOND_ERROR;
-    }
-  }
-
-  return RF_BLE_BEACOND_OK;
-}
-/*---------------------------------------------------------------------------*/
 PROCESS_THREAD(ble_beacond_process, ev, data)
 {
-  static size_t i;
-  static size_t len;
+  size_t len;
 
   PROCESS_BEGIN();
 
@@ -278,30 +296,33 @@ PROCESS_THREAD(ble_beacond_process, ev, data)
       PROCESS_EXIT();
     }
 
+    /* Device info */
     /* Set the adv payload each pass: The device name may have changed */
     len = 0;
 
-    /* Device info */
-    ble_beacond.tx_buf[len++] = (uint8_t)0x02;          /* 2 bytes */
-    ble_beacond.tx_buf[len++] = (uint8_t)BLE_ADV_TYPE_DEVINFO;
-    ble_beacond.tx_buf[len++] = (uint8_t)0x1A;          /* LE general discoverable + BR/EDR */
-    ble_beacond.tx_buf[len++] = (uint8_t)ble_beacond.adv_name_len;
-    ble_beacond.tx_buf[len++] = (uint8_t)BLE_ADV_TYPE_NAME;
+    #define append_byte(x)  ble_beacond.tx_buf[len++] = (uint8_t)((x))
+
+    /* 2 bytes */
+    append_byte(2);
+    append_byte(BLE_ADV_TYPE_FLAGS);
+    /* LE general discoverable + BR/EDR not supported */
+    append_byte(BLE_ADV_TYPE_FLAGS_GENERAL |
+                BLE_ADV_TYPE_FLAGS_BREDR_NOT_SUPPORTED);
+
+    /* 1 + len(name) bytes (excluding zero termination) */
+    append_byte(1 + ble_beacond.adv_name_len);
+    append_byte(BLE_ADV_TYPE_LOCAL_NAME_COMPLETE);
 
     memcpy(ble_beacond.tx_buf + len, ble_beacond.adv_name, ble_beacond.adv_name_len);
     len += ble_beacond.adv_name_len;
 
-    /*
-     * Send BLE_ADV_MESSAGES beacon bursts. Each burst on all three
-     * channels, with a BLE_ADV_DUTY_CYCLE interval between bursts
-     */
-    ble_beacon_burst(BLE_ADV_CHANNEL_ALL, ble_beacond.tx_buf, len);
-    for(i = 1; i < BLE_ADV_MESSAGES; ++i) {
-      etimer_set(&ble_beacond.ble_adv_et, BLE_ADV_DUTY_CYCLE);
-      PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&ble_beacond.ble_adv_et));
+    #undef append_byte
 
-      ble_beacon_burst(BLE_ADV_CHANNEL_ALL, ble_beacond.tx_buf, len);
-    }
+    /* Send advertisements on all three channels */
+    ble_beacond.ble_adv_par.advLen = len;
+    ble_beacond.ble_adv_par.pAdvData = ble_beacond.tx_buf;
+
+    ble_sched_beacons(BLE_ADV_CHANNEL_ALL);
   }
   PROCESS_END();
 }
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf/ieee-mode.c b/arch/cpu/simplelink-cc13xx-cc26xx/rf/ieee-mode.c
index d9f3a5acf7f0877c112ca4d82bfdf0641a62306f..d1e71fd46073855a52c7d2c1b941f2bd7def48ca 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf/ieee-mode.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf/ieee-mode.c
@@ -217,6 +217,9 @@ rat_overflow_cb(void *arg)
 static void
 init_rf_params(void)
 {
+  cmd_radio_setup.config.frontEndMode = RF_2_4_GHZ_FRONT_END_MODE;
+  cmd_radio_setup.config.biasMode = RF_2_4_GHZ_BIAS_MODE;
+
   data_queue_t *rx_q = data_queue_init(sizeof(lensz_t));
 
   cmd_rx.pRxQ = rx_q;
@@ -399,10 +402,10 @@ init(void)
 static int
 prepare(const void *payload, unsigned short payload_len)
 {
-  const size_t len = MIN((size_t)payload_len,
-                         (size_t)TX_BUF_SIZE);
-
-  memcpy(ieee_radio.tx_buf, payload, len);
+  if(payload_len > TX_BUF_SIZE || payload_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
+    return RADIO_TX_ERR;
+  }
+  memcpy(ieee_radio.tx_buf, payload, payload_len);
   return 0;
 }
 /*---------------------------------------------------------------------------*/
@@ -411,6 +414,11 @@ transmit(unsigned short transmit_len)
 {
   rf_result_t res;
 
+  if(transmit_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
+    LOG_ERR("Too long\n");
+    return RADIO_TX_ERR;
+  }
+
   if(ieee_radio.send_on_cca && channel_clear() != 1) {
     LOG_WARN("Channel is not clear for transmission\n");
     return RADIO_TX_COLLISION;
@@ -550,32 +558,42 @@ read(void *buf, unsigned short buf_len)
 static rf_result_t
 cca_request(cmd_cca_req_t *cmd_cca_req)
 {
+  RF_Stat stat = RF_StatRadioInactiveError;
   rf_result_t res;
+  bool stop_rx = false;
+
+  /* RX is required to be running in order to do a CCA request */
+  if(!rx_is_active()) {
+    /* If RX is not pending, i.e. soon to be running, schedule the RX command */
+    if(cmd_rx.status != PENDING) {
+      res = netstack_sched_rx(false);
+      if(res != RF_RESULT_OK) {
+        LOG_ERR("CCA request failed to schedule RX\n");
+        return res;
+      }
 
-  const bool rx_is_idle = !rx_is_active();
+      /* We only stop RX if we had to schedule it */
+      stop_rx = true;
+    }
 
-  if(rx_is_idle) {
-    res = netstack_sched_rx(false);
-    if(res != RF_RESULT_OK) {
+    /* Make sure RX is running before we continue, unless we timeout and fail */
+    RTIMER_BUSYWAIT_UNTIL(!rx_is_active(), TIMEOUT_ENTER_RX_WAIT);
+
+    if(!rx_is_active()) {
+      LOG_ERR("CCA request failed to turn on RX, RX status=0x%04X\n", cmd_rx.status);
       return RF_RESULT_ERROR;
     }
   }
 
-  const rtimer_clock_t t0 = RTIMER_NOW();
-  while((cmd_rx.status != ACTIVE) &&
-        RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + TIMEOUT_ENTER_RX_WAIT)) ;
-
-  RF_Stat stat = RF_StatRadioInactiveError;
-  if(rx_is_active()) {
-    stat = RF_runImmediateCmd(ieee_radio.rf_handle, (uint32_t *)&cmd_cca_req);
-  }
+  /* Perform the CCA request */
+  stat = RF_runImmediateCmd(ieee_radio.rf_handle, (uint32_t *)cmd_cca_req);
 
-  if(rx_is_idle) {
+  if(stop_rx) {
     netstack_stop_rx();
   }
 
   if(stat != RF_StatCmdDoneSuccess) {
-    LOG_ERR("CCA request failed, stat=0x%02X\n", stat);
+    LOG_ERR("CCA request command failed, stat=0x%02X\n", stat);
     return RF_RESULT_ERROR;
   }
 
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf/prop-mode.c b/arch/cpu/simplelink-cc13xx-cc26xx/rf/prop-mode.c
index a100f262a1f283d44b7ab447c838e88f7a140f54..eae5c53b85f71052caae68f802cd5f17cc798032 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf/prop-mode.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf/prop-mode.c
@@ -61,6 +61,7 @@
 #include <ti/drivers/rf/RF.h>
 /*---------------------------------------------------------------------------*/
 /* Platform RF dev */
+#include "rf/rf.h"
 #include "rf/dot-15-4g.h"
 #include "rf/sched.h"
 #include "rf/data-queue.h"
@@ -193,6 +194,8 @@ static int off(void);
 static void
 init_rf_params(void)
 {
+  cmd_radio_setup.config.frontEndMode = RF_SUB_1_GHZ_FRONT_END_MODE;
+  cmd_radio_setup.config.biasMode = RF_SUB_1_GHZ_BIAS_MODE;
   cmd_radio_setup.centerFreq = PROP_MODE_CENTER_FREQ;
   cmd_radio_setup.loDivider = PROP_MODE_LO_DIVIDER;
 
@@ -207,26 +210,36 @@ static int8_t
 get_rssi(void)
 {
   rf_result_t res;
+  bool stop_rx = false;
+  int8_t rssi = RF_GET_RSSI_ERROR_VAL;
 
-  const bool rx_is_idle = !rx_is_active();
-
-  if(rx_is_idle) {
-    res = netstack_sched_rx(false);
-    if(res != RF_RESULT_OK) {
-      return RF_GET_RSSI_ERROR_VAL;
+ /* RX is required to be running in order to do a RSSI measurement */
+  if(!rx_is_active()) {
+    /* If RX is not pending, i.e. soon to be running, schedule the RX command */
+    if(cmd_rx.status != PENDING) {
+      res = netstack_sched_rx(false);
+      if(res != RF_RESULT_OK) {
+        LOG_ERR("RSSI measurement failed to schedule RX\n");
+        return res;
+      }
+
+      /* We only stop RX if we had to schedule it */
+      stop_rx = true;
     }
-  }
 
-  const rtimer_clock_t t0 = RTIMER_NOW();
-  while((cmd_rx.status != ACTIVE) &&
-        RTIMER_CLOCK_LT(RTIMER_NOW(), t0 + TIMEOUT_ENTER_RX_WAIT)) ;
+    /* Make sure RX is running before we continue, unless we timeout and fail */
+    RTIMER_BUSYWAIT_UNTIL(!rx_is_active(), TIMEOUT_ENTER_RX_WAIT);
 
-  int8_t rssi = RF_GET_RSSI_ERROR_VAL;
-  if(rx_is_active()) {
-    rssi = RF_getRssi(prop_radio.rf_handle);
+    if(!rx_is_active()) {
+      LOG_ERR("RSSI measurement failed to turn on RX, RX status=0x%04X\n", cmd_rx.status);
+      return RF_RESULT_ERROR;
+    }
   }
 
-  if(rx_is_idle) {
+  /* Perform the RSSI measurement */
+  rssi = RF_getRssi(prop_radio.rf_handle);
+
+  if(stop_rx) {
     netstack_stop_rx();
   }
 
@@ -307,10 +320,11 @@ calculate_lqi(int8_t rssi)
 static int
 prepare(const void *payload, unsigned short payload_len)
 {
-  const size_t len = MIN((size_t)payload_len,
-                         (size_t)TX_BUF_PAYLOAD_LEN);
+  if(payload_len > TX_BUF_PAYLOAD_LEN || payload_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
+    return RADIO_TX_ERR;
+  }
 
-  memcpy(prop_radio.tx_buf + TX_BUF_HDR_LEN, payload, len);
+  memcpy(prop_radio.tx_buf + TX_BUF_HDR_LEN, payload, payload_len);
   return 0;
 }
 /*---------------------------------------------------------------------------*/
@@ -319,6 +333,11 @@ transmit(unsigned short transmit_len)
 {
   rf_result_t res;
 
+  if(transmit_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
+    LOG_ERR("Too long\n");
+    return RADIO_TX_ERR;
+  }
+
   if(tx_is_active()) {
     LOG_ERR("A transmission is already active\n");
     return RADIO_TX_ERR;
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf/rf.h b/arch/cpu/simplelink-cc13xx-cc26xx/rf/rf.h
index cfc6b2277ba206f90e87e690aa9db872dfc6490a..65b2b1543517cd44706d92e580765ce36d323a5b 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf/rf.h
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf/rf.h
@@ -60,6 +60,37 @@
                                 RF_MODE_2_4_GHZ)
 /** @} */
 /*---------------------------------------------------------------------------*/
+/**
+ * \name  The different front-end modes the CC13xx/CC26xx devices support. The
+ *        front-end mode can be configured independently of the bias mode. The
+ *        two types of modes are as follows:
+ *        - Differential: Both RF_P and RF_N are used as a differential RF
+ *          interface.
+ *        - Single ended: Either the RF_P pin or the RF_N pin is used as the
+ *          RF path.
+ *
+ * @{
+ */
+/* Available front-end mode configurations */
+#define RF_FRONT_END_MODE_DIFFERENTIAL      0
+#define RF_FRONT_END_MODE_SINGLE_ENDED_RFP  1
+#define RF_FRONT_END_MODE_SINGLE_ENDED_RFN  2
+/** @} */
+/*---------------------------------------------------------------------------*/
+/**
+ * \name  The different bias modes the CC13xx/CC26xx devices support. The
+ *        bias mode can be configured independently of the front-end mode. The
+ *        two different modes are as follows:
+ *        - Internal bias: the LNA is biased by an internal bias.
+ *        - External bias: the LNA is biased by an external bias.
+ *
+ * @{
+ */
+/* Available bias mode configurations */
+#define RF_BIAS_MODE_INTERNAL       0
+#define RF_BIAS_MODE_EXTERNAL       1
+/** @} */
+/*---------------------------------------------------------------------------*/
 #endif /* RF_CORE_H_ */
 /*---------------------------------------------------------------------------*/
 /**
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf/sched.c b/arch/cpu/simplelink-cc13xx-cc26xx/rf/sched.c
index 44387c1386daac12f73e081da080b2a35d637375..f15d33d2fae1b9ae3b3e5158a94d4161706ae31f 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf/sched.c
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf/sched.c
@@ -51,6 +51,7 @@
 #include <ti/devices/DeviceFamily.h>
 #include DeviceFamily_constructPath(driverlib/rf_common_cmd.h)
 #include DeviceFamily_constructPath(driverlib/rf_mailbox.h)
+#include DeviceFamily_constructPath(driverlib/rf_ble_mailbox.h)
 
 #include <ti/drivers/rf/RF.h>
 /*---------------------------------------------------------------------------*/
@@ -68,8 +69,6 @@
 #define LOG_MODULE "Radio"
 #define LOG_LEVEL LOG_LEVEL_NONE
 /*---------------------------------------------------------------------------*/
-/* Configuration parameters */
-/*---------------------------------------------------------------------------*/
 #define CMD_FS_RETRIES          3
 
 #define RF_EVENTS_CMD_DONE      (RF_EventCmdDone | RF_EventLastCmdDone | \
@@ -82,6 +81,13 @@
 
 #define EVENTS_CMD_DONE(events) (((events) & RF_EVENTS_CMD_DONE) != 0)
 /*---------------------------------------------------------------------------*/
+/* BLE advertisement channel range (inclusive) */
+#define BLE_ADV_CHANNEL_MIN     37
+#define BLE_ADV_CHANNEL_MAX     39
+
+/* Number of BLE advertisement channels */
+#define NUM_BLE_ADV_CHANNELS    (BLE_ADV_CHANNEL_MAX - BLE_ADV_CHANNEL_MIN + 1)
+/*---------------------------------------------------------------------------*/
 /* Synth re-calibration every 3 minutes */
 #define SYNTH_RECAL_INTERVAL    (CLOCK_SECOND * 60 * 3)
 /* Set re-calibration interval with a jitter of 10 seconds */
@@ -89,6 +95,12 @@
 
 static struct etimer synth_recal_timer;
 /*---------------------------------------------------------------------------*/
+#if (DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X0_CC26X0)
+typedef rfc_CMD_BLE_ADV_NC_t ble_cmd_adv_nc_t;
+#elif (DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X2_CC26X2)
+typedef rfc_CMD_BLE5_ADV_NC_t ble_cmd_adv_nc_t;
+#endif
+/*---------------------------------------------------------------------------*/
 static RF_Object rf_netstack;
 
 #if RF_CONF_BLE_BEACON_ENABLE
@@ -479,45 +491,171 @@ ble_open(RF_Params *params)
 #endif
 }
 /*---------------------------------------------------------------------------*/
+#if RF_CONF_BLE_BEACON_ENABLE
+static RF_Op *
+init_ble_adv_array(ble_cmd_adv_nc_t *ble_adv_array, uint8_t bm_channel)
+{
+  RF_Op *first_ble_adv = NULL;
+  ble_cmd_adv_nc_t *cmd_adv_37 = &ble_adv_array[0];
+  ble_cmd_adv_nc_t *cmd_adv_38 = &ble_adv_array[1];
+  ble_cmd_adv_nc_t *cmd_adv_39 = &ble_adv_array[2];
+
+  /* Setup channel 37 advertisement if enabled */
+  if(bm_channel & BLE_ADV_CHANNEL_37) {
+    /* Default configurations from ble_cmd_adv_nc */
+    memcpy(cmd_adv_37, &ble_cmd_adv_nc, sizeof(ble_cmd_adv_nc));
+
+    cmd_adv_37->channel = 37;
+    /* Magic number: initialization for whitener, specific for channel 37 */
+    cmd_adv_37->whitening.init = 0x65;
+
+    /*
+     * The next advertisement is chained depending on whether they are
+     * enbled or not. If both 38 and 39 are disabled, then there is no
+     * chaining.
+     */
+    if(bm_channel & BLE_ADV_CHANNEL_38) {
+      cmd_adv_37->pNextOp = (RF_Op *)cmd_adv_38;
+      cmd_adv_37->condition.rule = COND_ALWAYS;
+    } else if(bm_channel & BLE_ADV_CHANNEL_39) {
+      cmd_adv_37->pNextOp = (RF_Op *)cmd_adv_39;
+      cmd_adv_37->condition.rule = COND_ALWAYS;
+    } else {
+      cmd_adv_37->pNextOp = NULL;
+      cmd_adv_37->condition.rule = COND_NEVER;
+    }
+
+    /* Channel 37 will always be first if enabled */
+    first_ble_adv = (RF_Op *)cmd_adv_37;
+  }
+
+  /* Setup channel 38 advertisement if enabled */
+  if(bm_channel & BLE_ADV_CHANNEL_38) {
+    memcpy(cmd_adv_38, &ble_cmd_adv_nc, sizeof(ble_cmd_adv_nc));
+
+    cmd_adv_38->channel = 38;
+    /* Magic number: initialization for whitener, specific for channel 38 */
+    cmd_adv_38->whitening.init = 0x66;
+
+    /*
+     * The next advertisement is chained depending on whether they are
+     * enbled or not. If 39 is disabled, then there is no chaining.
+     */
+    if(bm_channel & BLE_ADV_CHANNEL_39) {
+      cmd_adv_38->pNextOp = (RF_Op *)cmd_adv_39;
+      cmd_adv_38->condition.rule = COND_ALWAYS;
+    } else {
+      cmd_adv_38->pNextOp = NULL;
+      cmd_adv_38->condition.rule = COND_NEVER;
+    }
+
+    /*
+     * Channel 38 is only first if the first_ble_adv pointer is not
+     * set by channel 37.
+     */
+    if(first_ble_adv == NULL) {
+      first_ble_adv = (RF_Op *)cmd_adv_38;
+    }
+  }
+
+  /* Setup channel 39 advertisement if enabled */
+  if(bm_channel & BLE_ADV_CHANNEL_39) {
+    memcpy(cmd_adv_39, &ble_cmd_adv_nc, sizeof(ble_cmd_adv_nc));
+
+    cmd_adv_39->channel = 39;
+    /* Magic number: initialization for whitener, specific for channel 39 */
+    cmd_adv_39->whitening.init = 0x67;
+
+    /* Channel 39 is always the last advertisement in the chain */
+    cmd_adv_39->pNextOp = NULL;
+    cmd_adv_39->condition.rule = COND_NEVER;
+
+    /*
+     * Channel 39 is only first if the first_ble_adv pointer is not
+     * set by channel 37 or channel 38.
+     */
+    if(first_ble_adv == NULL) {
+      first_ble_adv = (RF_Op *)cmd_adv_39;
+    }
+  }
+
+  return first_ble_adv;
+}
+#endif /* RF_CONF_BLE_BEACON_ENABLE */
+/*---------------------------------------------------------------------------*/
 rf_result_t
-ble_sched_beacon(RF_Callback cb, RF_EventMask bm_event)
+ble_sched_beacons(uint8_t bm_channel)
 {
 #if RF_CONF_BLE_BEACON_ENABLE
+  /*
+   * Allocate the advertisement commands on the stack rather than statically
+   * to RAM in order to save space. We don't need them after the
+   * advertisements have been transmitted.
+   */
+  ble_cmd_adv_nc_t ble_cmd_adv_nc_array[NUM_BLE_ADV_CHANNELS];
+
+  RF_Op *initial_adv = NULL;
   RF_ScheduleCmdParams sched_params;
-  RF_ScheduleCmdParams_init(&sched_params);
+  RF_CmdHandle beacon_handle;
+  RF_EventMask beacon_events;
+  rf_result_t rf_result;
+
+  /* If no channels are mapped, then early return OK */
+  if((bm_channel & BLE_ADV_CHANNEL_ALL) == 0) {
+    return RF_RESULT_OK;
+  }
 
+  initial_adv = init_ble_adv_array(ble_cmd_adv_nc_array, bm_channel);
+
+  if(initial_adv == NULL) {
+    LOG_ERR("Initializing BLE Advertisement chain failed\n");
+    return RF_RESULT_ERROR;
+  }
+
+  RF_ScheduleCmdParams_init(&sched_params);
   sched_params.priority = RF_PriorityNormal;
   sched_params.endTime = 0;
   sched_params.allowDelay = RF_AllowDelayAny;
 
-  CMD_STATUS(ble_cmd_beacon) = PENDING;
-
-  RF_CmdHandle beacon_handle = RF_scheduleCmd(
-      &rf_ble,
-      (RF_Op *)&ble_cmd_beacon,
-      &sched_params,
-      cb,
-      bm_event);
+  /*
+   * The most efficient way to schedule the command is as follows:
+   *   1. Schedule the BLE advertisement chain
+   *   2. Reschedule the RX command IF it was running.
+   *   3. Pend on the BLE avertisement chain
+   */
+  beacon_handle = RF_scheduleCmd(
+    &rf_ble,
+    initial_adv,
+    &sched_params,
+    NULL,
+    0);
 
   if(!CMD_HANDLE_OK(beacon_handle)) {
     LOG_ERR("Unable to schedule BLE Beacon command, handle=%d status=0x%04x\n",
-            beacon_handle, CMD_STATUS(ble_cmd_beacon));
+            beacon_handle, CMD_STATUS(ble_cmd_adv_nc));
+
     return RF_RESULT_ERROR;
   }
 
-  const uint_fast8_t rx_key = cmd_rx_disable();
+  /* Note that this only reschedules RX if it is running */
+  rf_result = cmd_rx_restore(cmd_rx_disable());
 
   /* Wait until Beacon operation finishes */
-  RF_EventMask beacon_events = RF_pendCmd(&rf_ble, beacon_handle, 0);
+  beacon_events = RF_pendCmd(&rf_ble, beacon_handle, 0);
+
+  if(rf_result != RF_RESULT_OK) {
+    LOG_ERR("Rescheduling CMD_RX failed when BLE advertising\n");
+
+    return RF_RESULT_ERROR;
+  }
+
   if(!EVENTS_CMD_DONE(beacon_events)) {
     LOG_ERR("Pending on scheduled BLE Beacon command generated error, events=0x%08llx status=0x%04x\n",
-            beacon_events, CMD_STATUS(ble_cmd_beacon));
+            beacon_events, CMD_STATUS(ble_cmd_adv_nc));
 
-    cmd_rx_restore(rx_key);
     return RF_RESULT_ERROR;
   }
 
-  cmd_rx_restore(rx_key);
   return RF_RESULT_OK;
 
 #else
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf/sched.h b/arch/cpu/simplelink-cc13xx-cc26xx/rf/sched.h
index de32dbbd421f0d24306c80060360eceb5f460572..fe49630361dd034e38c6e43e98b1aa460b331ebf 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf/sched.h
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf/sched.h
@@ -58,6 +58,16 @@ typedef enum {
   RF_RESULT_ERROR,
 } rf_result_t;
 /*---------------------------------------------------------------------------*/
+typedef enum {
+    BLE_ADV_CHANNEL_37 = (1 << 0),
+    BLE_ADV_CHANNEL_38 = (1 << 1),
+    BLE_ADV_CHANNEL_39 = (1 << 2),
+
+    BLE_ADV_CHANNEL_ALL = (BLE_ADV_CHANNEL_37 |
+                           BLE_ADV_CHANNEL_38 |
+                           BLE_ADV_CHANNEL_39),
+} ble_adv_channel_t;
+/*---------------------------------------------------------------------------*/
 /**
  * \name Common RF scheduler functionality.
  *
@@ -91,7 +101,7 @@ rf_result_t netstack_stop_rx(void);
  * @{
  */
 RF_Handle   ble_open(RF_Params *params);
-rf_result_t ble_sched_beacon(RF_Callback cb, RF_EventMask bm_event);
+rf_result_t ble_sched_beacons(uint8_t bm_adv_channel);
 /** @} */
 /*---------------------------------------------------------------------------*/
 #endif /* RF_SCHED_H_ */
diff --git a/arch/cpu/simplelink-cc13xx-cc26xx/rf/settings.h b/arch/cpu/simplelink-cc13xx-cc26xx/rf/settings.h
index 174114bfbe6cbb13db13f4970fa99a736293e9e7..1d20fce91e1e1376e64dd605e71a01375d4de78d 100644
--- a/arch/cpu/simplelink-cc13xx-cc26xx/rf/settings.h
+++ b/arch/cpu/simplelink-cc13xx-cc26xx/rf/settings.h
@@ -89,7 +89,7 @@
 #define ble_mode                rf_ble_mode
 #define ble_cmd_radio_setup     rf_ble_cmd_radio_setup
 #define ble_adv_par             rf_ble_adv_par
-#define ble_cmd_beacon          rf_ble_cmd_ble_adv_nc
+#define ble_cmd_adv_nc          rf_ble_cmd_ble_adv_nc
 
 /* CC13x2/CC26x2 devices */
 #elif (DeviceFamily_PARENT == DeviceFamily_PARENT_CC13X2_CC26X2)
@@ -97,7 +97,7 @@
 #define ble_mode                rf_ble_mode
 #define ble_cmd_radio_setup     rf_ble_cmd_radio_setup
 #define ble_adv_par             rf_ble_adv_par
-#define ble_cmd_beacon          rf_ble_cmd_ble_adv_nc
+#define ble_cmd_adv_nc          rf_ble_cmd_ble_adv_nc
 
 #endif /* DeviceFamily_PARENT */
 
diff --git a/arch/dev/cc1200/cc1200-802154g-863-870-fsk-50kbps.c b/arch/dev/cc1200/cc1200-802154g-863-870-fsk-50kbps.c
index ad19b576912ff9570e426c9dad76cdb929a59332..f6b1e9a5ac6f60d9044dec438f16a1940fee6a7d 100644
--- a/arch/dev/cc1200/cc1200-802154g-863-870-fsk-50kbps.c
+++ b/arch/dev/cc1200/cc1200-802154g-863-870-fsk-50kbps.c
@@ -94,7 +94,7 @@ static const char rf_cfg_descriptor[] = "802.15.4g 863-870MHz MR-FSK mode #1";
                                                   )
 
 /* TSCH timeslot timing (mircoseconds) */
-static const uint16_t cc1200_50kbps_tsch_timing[tsch_ts_elements_count] = {
+static const tsch_timeslot_timing_usec cc1200_50kbps_tsch_timing = {
   CC1200_TSCH_DEFAULT_TS_CCA_OFFSET,
   CC1200_TSCH_DEFAULT_TS_CCA,
   CC1200_TSCH_DEFAULT_TS_TX_OFFSET,
diff --git a/arch/dev/cc1200/cc1200-868-4gfsk-1000kbps.c b/arch/dev/cc1200/cc1200-868-4gfsk-1000kbps.c
index 29beef6c0e132e1ea34f7b8870e5e651517c5a7a..5314bb5179b7149e01b799771c420d25e3c5edf7 100644
--- a/arch/dev/cc1200/cc1200-868-4gfsk-1000kbps.c
+++ b/arch/dev/cc1200/cc1200-868-4gfsk-1000kbps.c
@@ -86,7 +86,7 @@ static const char rf_cfg_descriptor[] = "868MHz 2-GFSK 1000 kbps";
                                                   )
 
 /* TSCH timeslot timing (in rtimer ticks) */
-static const uint16_t cc1200_1000kbps_tsch_timing[tsch_ts_elements_count] = {
+static const tsch_timeslot_timing_usec cc1200_1000kbps_tsch_timing = {
   CC1200_TSCH_DEFAULT_TS_CCA_OFFSET,
   CC1200_TSCH_DEFAULT_TS_CCA,
   CC1200_TSCH_DEFAULT_TS_TX_OFFSET,
diff --git a/arch/dev/cc1200/cc1200-conf.h b/arch/dev/cc1200/cc1200-conf.h
index 45517080f889c4228757be5194491e37627ca003..646fb04ba9abf6fae7a247122ff6665a0e1614ae 100644
--- a/arch/dev/cc1200/cc1200-conf.h
+++ b/arch/dev/cc1200/cc1200-conf.h
@@ -70,8 +70,10 @@
 #ifdef CC1200_CONF_MAX_PAYLOAD_LEN
 #define CC1200_MAX_PAYLOAD_LEN           CC1200_CONF_MAX_PAYLOAD_LEN
 #else
-#define CC1200_MAX_PAYLOAD_LEN           127
+#define CC1200_MAX_PAYLOAD_LEN           125
 #endif
+
+#define cc1200_driver_max_payload_len    CC1200_MAX_PAYLOAD_LEN
 /*---------------------------------------------------------------------------*/
 /*
  * The RX watchdog is used to check whether the radio is in RX mode at regular
diff --git a/arch/dev/cc1200/cc1200.c b/arch/dev/cc1200/cc1200.c
index dd90fdda762cca953d391c7eb65c4c6e10fecaf6..50babb93d29818a909e7442f97f32ee7c44e1f9a 100644
--- a/arch/dev/cc1200/cc1200.c
+++ b/arch/dev/cc1200/cc1200.c
@@ -1449,6 +1449,7 @@ get_object(radio_param_t param, void *dest, size_t size)
     if(size != sizeof(uint16_t *) || !dest) {
       return RADIO_RESULT_INVALID_VALUE;
     }
+    /* Assigned value: a pointer to the TSCH timing in usec */
     *(const uint16_t **)dest = CC1200_RF_CFG.tsch_timing;
     return RADIO_RESULT_OK;
   }
diff --git a/arch/dev/cc2420/cc2420-tsch-15ms.c b/arch/dev/cc2420/cc2420-tsch-15ms.c
index b3b8255842dd326261e279f8b79aed66c7c5abef..cccc63b3476ff7587307a7ede4ea4df6fa762f2c 100644
--- a/arch/dev/cc2420/cc2420-tsch-15ms.c
+++ b/arch/dev/cc2420/cc2420-tsch-15ms.c
@@ -45,7 +45,7 @@
  * \brief 15ms TSCH timeslot timings, required for cc2420 platforms as
  * they are unable to keep up with the defulat 10ms timeslots.
  */
-const uint16_t tsch_timeslot_timing_us_15000[tsch_ts_elements_count] = {
+const tsch_timeslot_timing_usec tsch_timeslot_timing_us_15000= {
   1800, /* CCAOffset */
    128, /* CCA */
   4000, /* TxOffset */
diff --git a/arch/dev/cc2420/cc2420.c b/arch/dev/cc2420/cc2420.c
index a1572b0ef86e799b54d32b2c198236ad11a7f86a..d462a15314aeef08b63ffdc3ad550f278f0728e2 100644
--- a/arch/dev/cc2420/cc2420.c
+++ b/arch/dev/cc2420/cc2420.c
@@ -114,6 +114,7 @@ PROCESS(cc2420_process, "CC2420 driver");
 #define CORR_THR(n) (((n) & 0x1f) << 6)
 #define FIFOP_THR(n) ((n) & 0x7f)
 #define RXBPF_LOCUR (1 << 13);
+#define TX_MODE (3 << 2)
 
 int cc2420_on(void);
 int cc2420_off(void);
@@ -135,6 +136,8 @@ static void set_poll_mode(uint8_t enable);
 static void set_send_on_cca(uint8_t enable);
 static void set_auto_ack(uint8_t enable);
 
+static void set_test_mode(uint8_t enable, uint8_t modulated);
+
 signed char cc2420_last_rssi;
 uint8_t cc2420_last_correlation;
 
@@ -156,7 +159,11 @@ get_value(radio_param_t param, radio_value_t *value)
   }
   switch(param) {
   case RADIO_PARAM_POWER_MODE:
-    *value = receive_on ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
+    if((getreg(CC2420_MDMCTRL1) & TX_MODE) & 0x08) {
+      *value = RADIO_POWER_MODE_CARRIER_ON;
+    } else {
+      *value = receive_on ? RADIO_POWER_MODE_ON : RADIO_POWER_MODE_OFF;
+    }
     return RADIO_RESULT_OK;
   case RADIO_PARAM_CHANNEL:
     *value = cc2420_get_channel();
@@ -237,6 +244,11 @@ set_value(radio_param_t param, radio_value_t value)
       cc2420_off();
       return RADIO_RESULT_OK;
     }
+    if(value == RADIO_POWER_MODE_CARRIER_ON ||
+       value == RADIO_POWER_MODE_CARRIER_OFF) {
+      set_test_mode((value == RADIO_POWER_MODE_CARRIER_ON), 0);
+      return RADIO_RESULT_OK;
+    }
     return RADIO_RESULT_INVALID_VALUE;
   case RADIO_PARAM_CHANNEL:
     if(value < 11 || value > 26) {
@@ -654,6 +666,10 @@ cc2420_transmit(unsigned short payload_len)
 {
   int i;
 
+  if(payload_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
+    return RADIO_TX_ERR;
+  }
+
   GET_LOCK();
 
   /* The TX FIFO can only hold one packet. Make sure to not overrun
@@ -720,6 +736,10 @@ cc2420_prepare(const void *payload, unsigned short payload_len)
 {
   uint8_t total_len;
 
+  if(payload_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
+    return RADIO_TX_ERR;
+  }
+
   GET_LOCK();
 
   PRINTF("cc2420: sending %d bytes\n", payload_len);
@@ -1120,3 +1140,45 @@ set_send_on_cca(uint8_t enable)
   send_on_cca = enable;
 }
 /*---------------------------------------------------------------------------*/
+/* Enable or disable radio test mode emmiting modulated or unmodulated
+ * (carrier) signal. See datasheet page 55.
+ */
+static uint16_t prev_MDMCTRL1, prev_DACTST;
+static uint8_t was_on;
+
+static void
+set_test_mode(uint8_t enable, uint8_t modulated)
+{
+  radio_value_t mode;
+  get_value(RADIO_PARAM_POWER_MODE, &mode);
+
+  if(enable) {
+    if(mode == RADIO_POWER_MODE_CARRIER_ON) {
+      return;
+    }
+    was_on = (mode == RADIO_POWER_MODE_ON);
+    off();
+    prev_MDMCTRL1 = getreg(CC2420_MDMCTRL1);
+    setreg(CC2420_MDMCTRL1, 0x050C);
+    if(!modulated) {
+      prev_DACTST = getreg(CC2420_DACTST);
+      setreg(CC2420_DACTST, 0x1800);
+    }
+    /* actually starts the test mode */
+    strobe(CC2420_STXON);
+  } else {
+    if(mode != RADIO_POWER_MODE_CARRIER_ON) {
+      return;
+    }
+    strobe(CC2420_SRFOFF);
+    if(!modulated) {
+      setreg(CC2420_DACTST, prev_DACTST);
+    }
+    setreg(CC2420_MDMCTRL1, prev_MDMCTRL1);
+    /* actually stops the carrier */
+    if(was_on) {
+      on();
+    }
+  }
+}
+/*---------------------------------------------------------------------------*/
diff --git a/arch/dev/ext-flash/ext-flash.c b/arch/dev/ext-flash/ext-flash.c
index c4b108271e3f3d69270286c29a357f84a99be977..d50198910f67a3a84d33b390402ca6b198f43159 100644
--- a/arch/dev/ext-flash/ext-flash.c
+++ b/arch/dev/ext-flash/ext-flash.c
@@ -100,6 +100,12 @@
 #define VERIFY_PART_OK               1
 /*---------------------------------------------------------------------------*/
 static const spi_device_t flash_spi_configuration_default = {
+#if GPIO_HAL_PORT_PIN_NUMBERING
+  .port_spi_sck = EXT_FLASH_SPI_PORT_SCK,
+  .port_spi_miso = EXT_FLASH_SPI_PORT_MISO,
+  .port_spi_mosi = EXT_FLASH_SPI_PORT_MOSI,
+  .port_spi_cs = EXT_FLASH_SPI_PORT_CS,
+#endif
   .spi_controller = EXT_FLASH_SPI_CONTROLLER,
   .pin_spi_sck = EXT_FLASH_SPI_PIN_SCK,
   .pin_spi_miso = EXT_FLASH_SPI_PIN_MISO,
diff --git a/arch/platform/cc2538dk/Makefile.cc2538dk b/arch/platform/cc2538dk/Makefile.cc2538dk
index 148c6e837e24e777204a82f71fe921e5e6320b27..bdbc7598f95919c4c99ebeae6a04fa01242e72c1 100644
--- a/arch/platform/cc2538dk/Makefile.cc2538dk
+++ b/arch/platform/cc2538dk/Makefile.cc2538dk
@@ -14,7 +14,7 @@ CONTIKI_TARGET_SOURCEFILES += board-buttons.c als-sensor.c
 CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES)
 
 ### Define the CPU directory
-CONTIKI_CPU=$(CONTIKI)/arch/cpu/cc2538
+CONTIKI_CPU=$(ARCH_PATH)/cpu/cc2538
 include $(CONTIKI_CPU)/Makefile.cc2538
 
 MODULES += os/storage/cfs
diff --git a/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx b/arch/platform/cc26x0-cc13x0/Makefile.cc26x0-cc13x0
similarity index 78%
rename from arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx
rename to arch/platform/cc26x0-cc13x0/Makefile.cc26x0-cc13x0
index 03eefcf8be564fb92d2a5840f06c1769a00b51b4..622445dd448a5ff19960763900f915b91c220924 100644
--- a/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx
+++ b/arch/platform/cc26x0-cc13x0/Makefile.cc26x0-cc13x0
@@ -1,17 +1,17 @@
-# srf06-cc26xx platform makefile
+# cc26x0-cc13x0 platform makefile
 
 ifndef CONTIKI
   $(error CONTIKI not defined! You must specify where CONTIKI resides!)
 endif
 
 ### Board and BSP selection
-BOARD ?= srf06/cc26xx
-BOARDS = srf06/cc26xx srf06/cc13xx launchpad/cc2640r2 launchpad/cc2650 launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350
+BOARD ?= srf06/cc26x0
+BOARDS = srf06/cc26x0 srf06/cc13x0 launchpad/cc2640r2 launchpad/cc2650 launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350
 
 CONTIKI_TARGET_DIRS += .
 
 ### Include the board-specific makefile
-PLATFORM_ROOT_DIR = $(CONTIKI)/arch/platform/$(TARGET)
+PLATFORM_ROOT_DIR = $(ARCH_PATH)/platform/$(TARGET)
 -include $(PLATFORM_ROOT_DIR)/$(BOARD)/Makefile.$(notdir $(BOARD))
 
 CONTIKI_TARGET_SOURCEFILES += platform.c leds-arch.c
@@ -25,5 +25,5 @@ SMALL ?= 0
 ### Define the CPU directory and pull in the correct CPU makefile. This will
 ### be defined by one of the makefiles included above and it can be either
 ### Makefile.cc26xx or Makefile.cc13xx
-CONTIKI_CPU=$(CONTIKI)/arch/cpu/cc26xx-cc13xx
+CONTIKI_CPU=$(ARCH_PATH)/cpu/cc26x0-cc13x0
 include $(CONTIKI_CPU)/Makefile.$(CPU_FAMILY)
diff --git a/arch/platform/srf06-cc26xx/cfs-coffee-arch.h b/arch/platform/cc26x0-cc13x0/cfs-coffee-arch.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/cfs-coffee-arch.h
rename to arch/platform/cc26x0-cc13x0/cfs-coffee-arch.h
diff --git a/arch/platform/srf06-cc26xx/common/xmem.c b/arch/platform/cc26x0-cc13x0/common/xmem.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/common/xmem.c
rename to arch/platform/cc26x0-cc13x0/common/xmem.c
diff --git a/arch/platform/srf06-cc26xx/contiki-conf.h b/arch/platform/cc26x0-cc13x0/contiki-conf.h
similarity index 98%
rename from arch/platform/srf06-cc26xx/contiki-conf.h
rename to arch/platform/cc26x0-cc13x0/contiki-conf.h
index 23c086db378896e2994f834dbd9b3ed1c337c66f..de61c102c367c46c729dac76db9d315b950dd3e4 100644
--- a/arch/platform/srf06-cc26xx/contiki-conf.h
+++ b/arch/platform/cc26x0-cc13x0/contiki-conf.h
@@ -32,7 +32,7 @@
  * @{
  *
  * \file
- *  Configuration for the srf06-cc26xx platform
+ *  Configuration for the cc26x0-cc13x0 platform
  */
 #ifndef CONTIKI_CONF_H
 #define CONTIKI_CONF_H
diff --git a/arch/platform/srf06-cc26xx/launchpad/Makefile.launchpad b/arch/platform/cc26x0-cc13x0/launchpad/Makefile.launchpad
similarity index 100%
rename from arch/platform/srf06-cc26xx/launchpad/Makefile.launchpad
rename to arch/platform/cc26x0-cc13x0/launchpad/Makefile.launchpad
diff --git a/arch/platform/srf06-cc26xx/launchpad/board-buttons.c b/arch/platform/cc26x0-cc13x0/launchpad/board-buttons.c
similarity index 98%
rename from arch/platform/srf06-cc26xx/launchpad/board-buttons.c
rename to arch/platform/cc26x0-cc13x0/launchpad/board-buttons.c
index f07fff09ebbb1dea36ad99c317562f8a8edc24a5..208e6b95c4372a5cbb1961ff88b844b6b7f36587 100644
--- a/arch/platform/srf06-cc26xx/launchpad/board-buttons.c
+++ b/arch/platform/cc26x0-cc13x0/launchpad/board-buttons.c
@@ -30,7 +30,7 @@
  */
 /*---------------------------------------------------------------------------*/
 /**
- * \addtogroup launchpad-cc26xx-peripherals
+ * \addtogroup launchpad-peripherals
  * @{
  *
  * \file
diff --git a/arch/platform/srf06-cc26xx/launchpad/board-peripherals.h b/arch/platform/cc26x0-cc13x0/launchpad/board-peripherals.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/launchpad/board-peripherals.h
rename to arch/platform/cc26x0-cc13x0/launchpad/board-peripherals.h
diff --git a/arch/platform/srf06-cc26xx/launchpad/board.c b/arch/platform/cc26x0-cc13x0/launchpad/board.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/launchpad/board.c
rename to arch/platform/cc26x0-cc13x0/launchpad/board.c
diff --git a/arch/platform/srf06-cc26xx/launchpad/cc1310/Makefile.cc1310 b/arch/platform/cc26x0-cc13x0/launchpad/cc1310/Makefile.cc1310
similarity index 91%
rename from arch/platform/srf06-cc26xx/launchpad/cc1310/Makefile.cc1310
rename to arch/platform/cc26x0-cc13x0/launchpad/cc1310/Makefile.cc1310
index 8d3d2abd46d23c364f8c92944d8cb970964f3bcb..e9f7bab91eaeb459de37dd8d142ac389fb8ec4c3 100644
--- a/arch/platform/srf06-cc26xx/launchpad/cc1310/Makefile.cc1310
+++ b/arch/platform/cc26x0-cc13x0/launchpad/cc1310/Makefile.cc1310
@@ -1,5 +1,5 @@
 ### Will allow the inclusion of the correct CPU makefile
-CPU_FAMILY = cc13xx
+CPU_FAMILY = cc13x0
 
 ### Add to the source dirs
 CONTIKI_TARGET_DIRS += launchpad/cc1310
diff --git a/arch/platform/srf06-cc26xx/launchpad/cc1310/board.h b/arch/platform/cc26x0-cc13x0/launchpad/cc1310/board.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/launchpad/cc1310/board.h
rename to arch/platform/cc26x0-cc13x0/launchpad/cc1310/board.h
diff --git a/arch/platform/srf06-cc26xx/launchpad/cc1350/Makefile.cc1350 b/arch/platform/cc26x0-cc13x0/launchpad/cc1350/Makefile.cc1350
similarity index 93%
rename from arch/platform/srf06-cc26xx/launchpad/cc1350/Makefile.cc1350
rename to arch/platform/cc26x0-cc13x0/launchpad/cc1350/Makefile.cc1350
index 0d1f6535969e6873bebc5cb86461fad58d17c63c..811a3f61b87a8e156581386347f977a3f9c2275a 100644
--- a/arch/platform/srf06-cc26xx/launchpad/cc1350/Makefile.cc1350
+++ b/arch/platform/cc26x0-cc13x0/launchpad/cc1350/Makefile.cc1350
@@ -1,5 +1,5 @@
 ### Will allow the inclusion of the correct CPU makefile
-CPU_FAMILY = cc13xx
+CPU_FAMILY = cc13x0
 
 ### Add to the source dirs
 CONTIKI_TARGET_DIRS += launchpad/cc1350
diff --git a/arch/platform/srf06-cc26xx/launchpad/cc1350/board.h b/arch/platform/cc26x0-cc13x0/launchpad/cc1350/board.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/launchpad/cc1350/board.h
rename to arch/platform/cc26x0-cc13x0/launchpad/cc1350/board.h
diff --git a/arch/platform/srf06-cc26xx/launchpad/cc1350/rf-switch.c b/arch/platform/cc26x0-cc13x0/launchpad/cc1350/rf-switch.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/launchpad/cc1350/rf-switch.c
rename to arch/platform/cc26x0-cc13x0/launchpad/cc1350/rf-switch.c
diff --git a/arch/platform/srf06-cc26xx/launchpad/cc1350/tx-power-driver.c b/arch/platform/cc26x0-cc13x0/launchpad/cc1350/tx-power-driver.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/launchpad/cc1350/tx-power-driver.c
rename to arch/platform/cc26x0-cc13x0/launchpad/cc1350/tx-power-driver.c
diff --git a/arch/platform/srf06-cc26xx/launchpad/cc2640r2/Makefile.cc2640r2 b/arch/platform/cc26x0-cc13x0/launchpad/cc2640r2/Makefile.cc2640r2
similarity index 100%
rename from arch/platform/srf06-cc26xx/launchpad/cc2640r2/Makefile.cc2640r2
rename to arch/platform/cc26x0-cc13x0/launchpad/cc2640r2/Makefile.cc2640r2
diff --git a/arch/platform/srf06-cc26xx/launchpad/cc2640r2/board.h b/arch/platform/cc26x0-cc13x0/launchpad/cc2640r2/board.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/launchpad/cc2640r2/board.h
rename to arch/platform/cc26x0-cc13x0/launchpad/cc2640r2/board.h
diff --git a/arch/platform/srf06-cc26xx/launchpad/cc2650/Makefile.cc2650 b/arch/platform/cc26x0-cc13x0/launchpad/cc2650/Makefile.cc2650
similarity index 91%
rename from arch/platform/srf06-cc26xx/launchpad/cc2650/Makefile.cc2650
rename to arch/platform/cc26x0-cc13x0/launchpad/cc2650/Makefile.cc2650
index 72e50de3aa1ff11ab37c3073c4824018a0978426..399cd79e5573d022d15fd3d263e2e0736e5ffdbb 100644
--- a/arch/platform/srf06-cc26xx/launchpad/cc2650/Makefile.cc2650
+++ b/arch/platform/cc26x0-cc13x0/launchpad/cc2650/Makefile.cc2650
@@ -1,5 +1,5 @@
 ### Will allow the inclusion of the correct CPU makefile
-CPU_FAMILY = cc26xx
+CPU_FAMILY = cc26x0
 
 ### Add to the source dirs
 CONTIKI_TARGET_DIRS += launchpad/cc2650
diff --git a/arch/platform/srf06-cc26xx/launchpad/cc2650/board.h b/arch/platform/cc26x0-cc13x0/launchpad/cc2650/board.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/launchpad/cc2650/board.h
rename to arch/platform/cc26x0-cc13x0/launchpad/cc2650/board.h
diff --git a/arch/platform/srf06-cc26xx/launchpad/leds-arch.c b/arch/platform/cc26x0-cc13x0/launchpad/leds-arch.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/launchpad/leds-arch.c
rename to arch/platform/cc26x0-cc13x0/launchpad/leds-arch.c
diff --git a/arch/platform/srf06-cc26xx/platform.c b/arch/platform/cc26x0-cc13x0/platform.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/platform.c
rename to arch/platform/cc26x0-cc13x0/platform.c
diff --git a/arch/platform/srf06-cc26xx/sensortag/Makefile.sensortag b/arch/platform/cc26x0-cc13x0/sensortag/Makefile.sensortag
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/Makefile.sensortag
rename to arch/platform/cc26x0-cc13x0/sensortag/Makefile.sensortag
diff --git a/arch/platform/srf06-cc26xx/sensortag/bmp-280-sensor.c b/arch/platform/cc26x0-cc13x0/sensortag/bmp-280-sensor.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/bmp-280-sensor.c
rename to arch/platform/cc26x0-cc13x0/sensortag/bmp-280-sensor.c
diff --git a/arch/platform/srf06-cc26xx/sensortag/bmp-280-sensor.h b/arch/platform/cc26x0-cc13x0/sensortag/bmp-280-sensor.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/bmp-280-sensor.h
rename to arch/platform/cc26x0-cc13x0/sensortag/bmp-280-sensor.h
diff --git a/arch/platform/srf06-cc26xx/sensortag/board-buttons.c b/arch/platform/cc26x0-cc13x0/sensortag/board-buttons.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/board-buttons.c
rename to arch/platform/cc26x0-cc13x0/sensortag/board-buttons.c
diff --git a/arch/platform/srf06-cc26xx/sensortag/board-i2c.c b/arch/platform/cc26x0-cc13x0/sensortag/board-i2c.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/board-i2c.c
rename to arch/platform/cc26x0-cc13x0/sensortag/board-i2c.c
diff --git a/arch/platform/srf06-cc26xx/sensortag/board-i2c.h b/arch/platform/cc26x0-cc13x0/sensortag/board-i2c.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/board-i2c.h
rename to arch/platform/cc26x0-cc13x0/sensortag/board-i2c.h
diff --git a/arch/platform/srf06-cc26xx/sensortag/board-peripherals.h b/arch/platform/cc26x0-cc13x0/sensortag/board-peripherals.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/board-peripherals.h
rename to arch/platform/cc26x0-cc13x0/sensortag/board-peripherals.h
diff --git a/arch/platform/srf06-cc26xx/sensortag/board.c b/arch/platform/cc26x0-cc13x0/sensortag/board.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/board.c
rename to arch/platform/cc26x0-cc13x0/sensortag/board.c
diff --git a/arch/platform/srf06-cc26xx/sensortag/buzzer.c b/arch/platform/cc26x0-cc13x0/sensortag/buzzer.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/buzzer.c
rename to arch/platform/cc26x0-cc13x0/sensortag/buzzer.c
diff --git a/arch/platform/srf06-cc26xx/sensortag/buzzer.h b/arch/platform/cc26x0-cc13x0/sensortag/buzzer.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/buzzer.h
rename to arch/platform/cc26x0-cc13x0/sensortag/buzzer.h
diff --git a/arch/platform/srf06-cc26xx/sensortag/cc1350/Makefile.cc1350 b/arch/platform/cc26x0-cc13x0/sensortag/cc1350/Makefile.cc1350
similarity index 91%
rename from arch/platform/srf06-cc26xx/sensortag/cc1350/Makefile.cc1350
rename to arch/platform/cc26x0-cc13x0/sensortag/cc1350/Makefile.cc1350
index cdae4c2b1c85f846880b3f0b777f7fc3bc6a7800..f0f924e9731d694c19f61f28d02e827622d4a5a8 100644
--- a/arch/platform/srf06-cc26xx/sensortag/cc1350/Makefile.cc1350
+++ b/arch/platform/cc26x0-cc13x0/sensortag/cc1350/Makefile.cc1350
@@ -1,5 +1,5 @@
 ### Will allow the inclusion of the correct CPU makefile
-CPU_FAMILY = cc13xx
+CPU_FAMILY = cc13x0
 
 ### Add to the source dirs
 CONTIKI_TARGET_DIRS += sensortag/cc1350
diff --git a/arch/platform/srf06-cc26xx/sensortag/cc1350/board.h b/arch/platform/cc26x0-cc13x0/sensortag/cc1350/board.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/cc1350/board.h
rename to arch/platform/cc26x0-cc13x0/sensortag/cc1350/board.h
diff --git a/arch/platform/srf06-cc26xx/sensortag/cc1350/leds-arch.c b/arch/platform/cc26x0-cc13x0/sensortag/cc1350/leds-arch.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/cc1350/leds-arch.c
rename to arch/platform/cc26x0-cc13x0/sensortag/cc1350/leds-arch.c
diff --git a/arch/platform/srf06-cc26xx/sensortag/cc2650/Makefile.cc2650 b/arch/platform/cc26x0-cc13x0/sensortag/cc2650/Makefile.cc2650
similarity index 91%
rename from arch/platform/srf06-cc26xx/sensortag/cc2650/Makefile.cc2650
rename to arch/platform/cc26x0-cc13x0/sensortag/cc2650/Makefile.cc2650
index e91cabda4680d462ba69f6f4a15bb800cb9e4c7e..4aa83e352b93bddeaac0d42c1bae808baa177533 100644
--- a/arch/platform/srf06-cc26xx/sensortag/cc2650/Makefile.cc2650
+++ b/arch/platform/cc26x0-cc13x0/sensortag/cc2650/Makefile.cc2650
@@ -1,5 +1,5 @@
 ### Will allow the inclusion of the correct CPU makefile
-CPU_FAMILY = cc26xx
+CPU_FAMILY = cc26x0
 
 ### Add to the source dirs
 CONTIKI_TARGET_DIRS += sensortag/cc2650
diff --git a/arch/platform/srf06-cc26xx/sensortag/cc2650/board.h b/arch/platform/cc26x0-cc13x0/sensortag/cc2650/board.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/cc2650/board.h
rename to arch/platform/cc26x0-cc13x0/sensortag/cc2650/board.h
diff --git a/arch/platform/srf06-cc26xx/sensortag/cc2650/leds-arch.c b/arch/platform/cc26x0-cc13x0/sensortag/cc2650/leds-arch.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/cc2650/leds-arch.c
rename to arch/platform/cc26x0-cc13x0/sensortag/cc2650/leds-arch.c
diff --git a/arch/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.c b/arch/platform/cc26x0-cc13x0/sensortag/hdc-1000-sensor.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.c
rename to arch/platform/cc26x0-cc13x0/sensortag/hdc-1000-sensor.c
diff --git a/arch/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.h b/arch/platform/cc26x0-cc13x0/sensortag/hdc-1000-sensor.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/hdc-1000-sensor.h
rename to arch/platform/cc26x0-cc13x0/sensortag/hdc-1000-sensor.h
diff --git a/arch/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.c b/arch/platform/cc26x0-cc13x0/sensortag/mpu-9250-sensor.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.c
rename to arch/platform/cc26x0-cc13x0/sensortag/mpu-9250-sensor.c
diff --git a/arch/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.h b/arch/platform/cc26x0-cc13x0/sensortag/mpu-9250-sensor.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/mpu-9250-sensor.h
rename to arch/platform/cc26x0-cc13x0/sensortag/mpu-9250-sensor.h
diff --git a/arch/platform/srf06-cc26xx/sensortag/opt-3001-sensor.c b/arch/platform/cc26x0-cc13x0/sensortag/opt-3001-sensor.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/opt-3001-sensor.c
rename to arch/platform/cc26x0-cc13x0/sensortag/opt-3001-sensor.c
diff --git a/arch/platform/srf06-cc26xx/sensortag/opt-3001-sensor.h b/arch/platform/cc26x0-cc13x0/sensortag/opt-3001-sensor.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/opt-3001-sensor.h
rename to arch/platform/cc26x0-cc13x0/sensortag/opt-3001-sensor.h
diff --git a/arch/platform/srf06-cc26xx/sensortag/sensor-common.c b/arch/platform/cc26x0-cc13x0/sensortag/sensor-common.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/sensor-common.c
rename to arch/platform/cc26x0-cc13x0/sensortag/sensor-common.c
diff --git a/arch/platform/srf06-cc26xx/sensortag/sensor-common.h b/arch/platform/cc26x0-cc13x0/sensortag/sensor-common.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/sensor-common.h
rename to arch/platform/cc26x0-cc13x0/sensortag/sensor-common.h
diff --git a/arch/platform/srf06-cc26xx/sensortag/sensortag-sensors.c b/arch/platform/cc26x0-cc13x0/sensortag/sensortag-sensors.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/sensortag-sensors.c
rename to arch/platform/cc26x0-cc13x0/sensortag/sensortag-sensors.c
diff --git a/arch/platform/srf06-cc26xx/sensortag/tmp-007-sensor.c b/arch/platform/cc26x0-cc13x0/sensortag/tmp-007-sensor.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/tmp-007-sensor.c
rename to arch/platform/cc26x0-cc13x0/sensortag/tmp-007-sensor.c
diff --git a/arch/platform/srf06-cc26xx/sensortag/tmp-007-sensor.h b/arch/platform/cc26x0-cc13x0/sensortag/tmp-007-sensor.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/sensortag/tmp-007-sensor.h
rename to arch/platform/cc26x0-cc13x0/sensortag/tmp-007-sensor.h
diff --git a/arch/platform/srf06-cc26xx/srf06/Makefile.srf06 b/arch/platform/cc26x0-cc13x0/srf06/Makefile.srf06
similarity index 100%
rename from arch/platform/srf06-cc26xx/srf06/Makefile.srf06
rename to arch/platform/cc26x0-cc13x0/srf06/Makefile.srf06
diff --git a/arch/platform/srf06-cc26xx/srf06/als-sensor.c b/arch/platform/cc26x0-cc13x0/srf06/als-sensor.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/srf06/als-sensor.c
rename to arch/platform/cc26x0-cc13x0/srf06/als-sensor.c
diff --git a/arch/platform/srf06-cc26xx/srf06/als-sensor.h b/arch/platform/cc26x0-cc13x0/srf06/als-sensor.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/srf06/als-sensor.h
rename to arch/platform/cc26x0-cc13x0/srf06/als-sensor.h
diff --git a/arch/platform/srf06-cc26xx/srf06/board-buttons.c b/arch/platform/cc26x0-cc13x0/srf06/board-buttons.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/srf06/board-buttons.c
rename to arch/platform/cc26x0-cc13x0/srf06/board-buttons.c
diff --git a/arch/platform/srf06-cc26xx/srf06/board-peripherals.h b/arch/platform/cc26x0-cc13x0/srf06/board-peripherals.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/srf06/board-peripherals.h
rename to arch/platform/cc26x0-cc13x0/srf06/board-peripherals.h
diff --git a/arch/platform/srf06-cc26xx/srf06/board.c b/arch/platform/cc26x0-cc13x0/srf06/board.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/srf06/board.c
rename to arch/platform/cc26x0-cc13x0/srf06/board.c
diff --git a/arch/platform/srf06-cc26xx/srf06/cc13xx/Makefile.cc13xx b/arch/platform/cc26x0-cc13x0/srf06/cc13x0/Makefile.cc13x0
similarity index 72%
rename from arch/platform/srf06-cc26xx/srf06/cc13xx/Makefile.cc13xx
rename to arch/platform/cc26x0-cc13x0/srf06/cc13x0/Makefile.cc13x0
index b8308465131fb0c9d8193351677bda7a4c1fe3a0..ec20fcb634e7c45da43a9337459b981aa2c07e35 100644
--- a/arch/platform/srf06-cc26xx/srf06/cc13xx/Makefile.cc13xx
+++ b/arch/platform/cc26x0-cc13x0/srf06/cc13x0/Makefile.cc13x0
@@ -1,7 +1,7 @@
 ### Will allow the inclusion of the correct CPU makefile
-CPU_FAMILY = cc13xx
+CPU_FAMILY = cc13x0
 
 ### Include the common sensortag makefile
 include $(PLATFORM_ROOT_DIR)/srf06/Makefile.srf06
 
-CONTIKI_TARGET_DIRS += srf06/cc13xx
+CONTIKI_TARGET_DIRS += srf06/cc13x0
diff --git a/arch/platform/srf06-cc26xx/srf06/cc13xx/board.h b/arch/platform/cc26x0-cc13x0/srf06/cc13x0/board.h
similarity index 100%
rename from arch/platform/srf06-cc26xx/srf06/cc13xx/board.h
rename to arch/platform/cc26x0-cc13x0/srf06/cc13x0/board.h
diff --git a/arch/platform/srf06-cc26xx/srf06/cc26xx/Makefile.cc26xx b/arch/platform/cc26x0-cc13x0/srf06/cc26x0/Makefile.cc26x0
similarity index 71%
rename from arch/platform/srf06-cc26xx/srf06/cc26xx/Makefile.cc26xx
rename to arch/platform/cc26x0-cc13x0/srf06/cc26x0/Makefile.cc26x0
index 841442a5cfaaddaeebe6222bd441d42ec3283521..84ef217a892c770ceabeeb1adfe38dbf25300c90 100644
--- a/arch/platform/srf06-cc26xx/srf06/cc26xx/Makefile.cc26xx
+++ b/arch/platform/cc26x0-cc13x0/srf06/cc26x0/Makefile.cc26x0
@@ -1,7 +1,7 @@
 ### Will allow the inclusion of the correct CPU makefile
-CPU_FAMILY = cc26xx
+CPU_FAMILY = cc26x0
 
 ### Include the common makefile
 include $(PLATFORM_ROOT_DIR)/srf06/Makefile.srf06
 
-CONTIKI_TARGET_DIRS += srf06/cc26xx
+CONTIKI_TARGET_DIRS += srf06/cc26x0
diff --git a/arch/platform/srf06-cc26xx/srf06/cc26xx/board.h b/arch/platform/cc26x0-cc13x0/srf06/cc26x0/board.h
similarity index 99%
rename from arch/platform/srf06-cc26xx/srf06/cc26xx/board.h
rename to arch/platform/cc26x0-cc13x0/srf06/cc26x0/board.h
index f31a94fb3580c182631478901c5630b7d7e8b345..cd6d2b1e41ae9858473916638310ce85cc7fe23f 100644
--- a/arch/platform/srf06-cc26xx/srf06/cc26xx/board.h
+++ b/arch/platform/cc26x0-cc13x0/srf06/cc26x0/board.h
@@ -31,7 +31,7 @@
 /** \addtogroup cc26xx-srf-tag
  * @{
  *
- * \defgroup srf06-cc26xx-peripherals Peripherals for the SmartRF06EB + CC26xxEM
+ * \defgroup cc26x0-cc13x0-peripherals Peripherals for the SmartRF06EB + CC26xxEM
  *
  * Defines related to the SmartRF06 Evaluation Board with a CC26xxEM
  *
diff --git a/arch/platform/srf06-cc26xx/srf06/leds-arch.c b/arch/platform/cc26x0-cc13x0/srf06/leds-arch.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/srf06/leds-arch.c
rename to arch/platform/cc26x0-cc13x0/srf06/leds-arch.c
diff --git a/arch/platform/srf06-cc26xx/srf06/srf06-sensors.c b/arch/platform/cc26x0-cc13x0/srf06/srf06-sensors.c
similarity index 100%
rename from arch/platform/srf06-cc26xx/srf06/srf06-sensors.c
rename to arch/platform/cc26x0-cc13x0/srf06/srf06-sensors.c
diff --git a/arch/platform/cooja/Makefile.cooja b/arch/platform/cooja/Makefile.cooja
index 6a6a9d49e3718e9dd7a12a2c41fb7f255e09a788..023fe3d9a3674ab173777c0f7a0ab5bf63a3c824 100644
--- a/arch/platform/cooja/Makefile.cooja
+++ b/arch/platform/cooja/Makefile.cooja
@@ -41,13 +41,13 @@ JNILIB = $(BUILD_DIR_BOARD)/$(LIBNAME).$(TARGET)
 CONTIKI_APP_OBJ = $(CONTIKI_APP).o
 
 ### COOJA platform sources
-COOJA = $(CONTIKI)/arch/platform/$(TARGET)
+COOJA = $(ARCH_PATH)/platform/$(TARGET)
 CONTIKI_TARGET_DIRS = . dev lib sys cfs net
 
 # (COOJA_SOURCEDIRS contains additional sources dirs set from simulator)
 vpath %.c $(COOJA_SOURCEDIRS)
 
-COOJA_BASE	= simEnvChange.c cooja_mt.c cooja_mtarch.c rtimer-arch.c slip.c watchdog.c
+COOJA_BASE	= simEnvChange.c cooja_mt.c cooja_mtarch.c rtimer-arch.c slip.c watchdog.c int-master.c
 
 COOJA_INTFS	= beep.c button-sensor.c ip.c leds-arch.c moteid.c \
 		    pir-sensor.c rs232.c vib-sensor.c \
@@ -67,7 +67,7 @@ CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES)
 CLEAN += COOJA.log
 
 ### Define the CPU directory
-CONTIKI_CPU=$(CONTIKI)/arch/cpu/x86
+CONTIKI_CPU=$(ARCH_PATH)/cpu/x86
 
 ### Compiler arguments
 #CC = gcc
diff --git a/arch/platform/cooja/contiki-conf.h b/arch/platform/cooja/contiki-conf.h
index 44c984dbfdd8dbdc0d2841c083f7cf197e283f60..ce5bc6b4c0305d33b947de4630bc631970fa41e9 100644
--- a/arch/platform/cooja/contiki-conf.h
+++ b/arch/platform/cooja/contiki-conf.h
@@ -70,19 +70,17 @@
 #define CSMA_CONF_ACK_WAIT_TIME                RTIMER_SECOND / 500
 #define CSMA_CONF_AFTER_ACK_DETECTED_WAIT_TIME 0
 
+#endif /* NETSTACK_CONF_H */
+
 /* Radio setup */
 #define NETSTACK_CONF_RADIO cooja_radio_driver
 
-#endif /* NETSTACK_CONF_H */
+#define cooja_radio_driver_max_payload_len 125
 
 /* Default network config */
 #if NETSTACK_CONF_WITH_IPV6
 
 
-
-/* Radio setup */
-#define NETSTACK_CONF_RADIO cooja_radio_driver
-
 /* configure network size and density */
 #ifndef NETSTACK_MAX_ROUTE_ENTRIES
 #define NETSTACK_MAX_ROUTE_ENTRIES   300
@@ -143,8 +141,6 @@ typedef unsigned long clock_time_t;
 
 #define CFS_CONF_OFFSET_TYPE	long
 
-#define NETSTACK_RADIO_MAX_PAYLOAD_LEN 125
-
 #define PLATFORM_CONF_SUPPORTS_STACK_CHECK  0
 
 #endif /* CONTIKI_CONF_H_ */
diff --git a/arch/platform/cooja/dev/cooja-radio.c b/arch/platform/cooja/dev/cooja-radio.c
index f0dee567ba577b06414eb5542354888759d6329e..f6daec31689235c88fbb9b96f02a4ade337dc40f 100644
--- a/arch/platform/cooja/dev/cooja-radio.c
+++ b/arch/platform/cooja/dev/cooja-radio.c
@@ -42,7 +42,7 @@
 #include "dev/radio.h"
 #include "dev/cooja-radio.h"
 
-#define COOJA_RADIO_BUFSIZE PACKETBUF_SIZE
+#define COOJA_RADIO_BUFSIZE cooja_radio_driver_max_payload_len
 #define CCA_SS_THRESHOLD -95
 
 const struct simInterface radio_interface;
@@ -246,6 +246,9 @@ radio_send(const void *payload, unsigned short payload_len)
 static int
 prepare_packet(const void *data, unsigned short len)
 {
+  if(len > COOJA_RADIO_BUFSIZE) {
+    return RADIO_TX_ERR;
+  }
   pending_data = data;
   return 0;
 }
diff --git a/arch/platform/cooja/int-master.c b/arch/platform/cooja/int-master.c
new file mode 100644
index 0000000000000000000000000000000000000000..177dbd4424c30967c00ee069a728791de85d161f
--- /dev/null
+++ b/arch/platform/cooja/int-master.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2018, George Oikonomou - http://www.spd.gr
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/*---------------------------------------------------------------------------*/
+#include "contiki.h"
+#include "sys/int-master.h"
+
+#include <stdbool.h>
+/*---------------------------------------------------------------------------*/
+#define DISABLED 0
+#define ENABLED  1
+/*---------------------------------------------------------------------------*/
+static int_master_status_t stat = DISABLED;
+/*---------------------------------------------------------------------------*/
+void
+int_master_enable(void)
+{
+  stat = ENABLED;
+}
+/*---------------------------------------------------------------------------*/
+int_master_status_t
+int_master_read_and_disable(void)
+{
+  int_master_status_t rv = stat;
+  stat = DISABLED;
+  return rv;
+}
+/*---------------------------------------------------------------------------*/
+void
+int_master_status_set(int_master_status_t status)
+{
+  stat = status;
+}
+/*---------------------------------------------------------------------------*/
+bool
+int_master_is_enabled(void)
+{
+  return stat == DISABLED ? false : true;
+}
+/*---------------------------------------------------------------------------*/
diff --git a/arch/platform/cooja/net/uip-driver.c b/arch/platform/cooja/net/uip-driver.c
index 0e7209a6c620074b5dbffc6ea581b2f0c5413a4f..fd86cc9c6ca381fadeeab90aa30811bdda8cb57d 100644
--- a/arch/platform/cooja/net/uip-driver.c
+++ b/arch/platform/cooja/net/uip-driver.c
@@ -48,7 +48,7 @@
 static uint8_t
 uip_driver_send(const linkaddr_t *addr)
 {
-  packetbuf_copyfrom(&uip_buf[UIP_LLH_LEN], uip_len);
+  packetbuf_copyfrom(uip_buf, uip_len);
 
   /* XXX we should provide a callback function that is called when the
      packet is sent. For now, we just supply a NULL pointer. */
@@ -64,9 +64,8 @@ init(void)
 static void
 input(void)
 {
-  if(packetbuf_datalen() > 0 &&
-     packetbuf_datalen() <= UIP_BUFSIZE - UIP_LLH_LEN) {
-    memcpy(&uip_buf[UIP_LLH_LEN], packetbuf_dataptr(), packetbuf_datalen());
+  if(packetbuf_datalen() > 0 && packetbuf_datalen() <= UIP_BUFSIZE) {
+    memcpy(uip_buf, packetbuf_dataptr(), packetbuf_datalen());
     uip_len = packetbuf_datalen();
     tcpip_input();
   }
diff --git a/arch/platform/cooja/rtimer-arch.h b/arch/platform/cooja/rtimer-arch.h
index 072333bc1955701a34db0a72af09b726f856db50..35bd892b448b035db8272529e7325a1c23cc7461 100644
--- a/arch/platform/cooja/rtimer-arch.h
+++ b/arch/platform/cooja/rtimer-arch.h
@@ -35,6 +35,8 @@
 
 #include "contiki.h"
 #include "sys/clock.h"
+#include "lib/simEnvChange.h"
+#include "sys/cooja_mt.h"
 
 #define RTIMER_ARCH_SECOND UINT64_C(1000000)
 
@@ -47,4 +49,17 @@ int rtimer_arch_check(void);
 int rtimer_arch_pending(void);
 rtimer_clock_t rtimer_arch_next(void);
 
+/** \brief A platform-specific implementation that calls cooja_mt_yield()
+ * periodically. Without this, Cooja will get stuck in the busy-loop
+ * without ever updating the current rtimer time. */
+#define RTIMER_BUSYWAIT_UNTIL_ABS(cond, t0, max_time) \
+  ({                                                                \
+    bool c;                                                         \
+    while(!(c = cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (max_time))) { \
+      simProcessRunValue = 1;                                       \
+      cooja_mt_yield();                                             \
+    }                                                               \
+    c;                                                              \
+  })
+
 #endif /* RTIMER_ARCH_H_ */
diff --git a/arch/platform/jn516x/contiki-conf.h b/arch/platform/jn516x/contiki-conf.h
index e4d741400e141e623e0726ee373576d50d177d9a..e161fd8537147fc34719ddfd61942f8b55bbf8d4 100644
--- a/arch/platform/jn516x/contiki-conf.h
+++ b/arch/platform/jn516x/contiki-conf.h
@@ -45,6 +45,8 @@
 #define NETSTACK_CONF_RADIO   micromac_radio_driver
 #endif /* NETSTACK_CONF_RADIO */
 
+#define micromac_radio_driver_max_payload_len 125
+
 /* Platform-specific (H/W) CCM* implementation */
 #ifndef CCM_STAR_CONF
 #define CCM_STAR_CONF ccm_star_driver_jn516x
diff --git a/arch/platform/jn516x/dev/micromac-radio.c b/arch/platform/jn516x/dev/micromac-radio.c
index bad81f4f0a6986511cc70f87151d74d41a7d1111..5f22122d30bb74f9afdee545867a7c594d538bde 100644
--- a/arch/platform/jn516x/dev/micromac-radio.c
+++ b/arch/platform/jn516x/dev/micromac-radio.c
@@ -350,6 +350,10 @@ transmit(unsigned short payload_len)
   if(tx_in_progress) {
     return RADIO_TX_COLLISION;
   }
+  if(payload_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN) {
+    return RADIO_TX_ERR;
+  }
+
   tx_in_progress = 1;
 
   /* Energest */
@@ -416,7 +420,7 @@ prepare(const void *payload, unsigned short payload_len)
   if(tx_in_progress) {
     return 1;
   }
-  if(payload_len > 127 || payload == NULL) {
+  if(payload_len > NETSTACK_RADIO_MAX_PAYLOAD_LEN || payload == NULL) {
     return 1;
   }
 #if MICROMAC_RADIO_MAC
diff --git a/arch/platform/jn516x/slip.c b/arch/platform/jn516x/slip.c
index 173a14d60ae3ecb1d2083f0bd2088537dcfd2e0d..41652e1815ac317b4e1ee956abe884bbe1cb261b 100644
--- a/arch/platform/jn516x/slip.c
+++ b/arch/platform/jn516x/slip.c
@@ -46,7 +46,6 @@
 
 #include <MicroInt.h>
 #include "net/ipv6/uip.h"
-#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
 
 #include "dev/slip.h"
 
@@ -117,7 +116,7 @@ unsigned long slip_received, slip_frames;
 #ifdef SLIP_CONF_RX_BUFSIZE
 #define RX_BUFSIZE SLIP_CONF_RX_BUFSIZE
 
-#if RX_BUFSIZE < (UIP_BUFSIZE - UIP_LLH_LEN + 16)
+#if RX_BUFSIZE < (UIP_BUFSIZE + 16)
 #error "SLIP_CONF_RX_BUFSIZE too small for UIP_BUFSIZE"
 #endif
 
@@ -195,7 +194,7 @@ slip_send(void)
 
   slip_arch_writeb(SLIP_END);
 
-  ptr = &uip_buf[UIP_LLH_LEN];
+  ptr = uip_buf;
   for(i = 0; i < uip_len; ++i) {
     c = *ptr++;
     slip_write_char(c);
@@ -317,8 +316,7 @@ PROCESS_THREAD(slip_process, ev, data)
     PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
 
     /* Move packet from rxbuf to buffer provided by uIP. */
-    uip_len = slip_poll_handler(&uip_buf[UIP_LLH_LEN],
-                                UIP_BUFSIZE - UIP_LLH_LEN);
+    uip_len = slip_poll_handler(uip_buf, UIP_BUFSIZE);
 
     PRINTF("SLIP: recv bytes %u frames RECV: %u. is_full %u, is_dropping %u.\n",
            end_counter, uip_len, is_full, is_dropping);
diff --git a/arch/platform/native/Makefile.native b/arch/platform/native/Makefile.native
index afeddd22f3150c1310e9ce5506d61dd23e9860b4..51681284ecd8e091a40ce61f33143d9dcd51b2df 100644
--- a/arch/platform/native/Makefile.native
+++ b/arch/platform/native/Makefile.native
@@ -28,5 +28,5 @@ CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES)
 MAKE_MAC ?= MAKE_MAC_NULLMAC
 
 ### Define the CPU directory
-CONTIKI_CPU=$(CONTIKI)/arch/cpu/native
-include $(CONTIKI)/arch/cpu/native/Makefile.native
+CONTIKI_CPU=$(ARCH_PATH)/cpu/native
+include $(ARCH_PATH)/cpu/native/Makefile.native
diff --git a/arch/platform/native/contiki-conf.h b/arch/platform/native/contiki-conf.h
index e8177d7b2ef26ba86965345091d7de174c9eb05d..15198d8cc0a49eee2c220a593f02251c7e27b374 100644
--- a/arch/platform/native/contiki-conf.h
+++ b/arch/platform/native/contiki-conf.h
@@ -76,6 +76,9 @@ typedef unsigned int uip_stats_t;
 #define NETSTACK_CONF_RADIO   nullradio_driver
 #endif /* NETSTACK_CONF_RADIO */
 
+/* for nullradio, allow unlimited packet size */
+#define nullradio_driver_max_payload_len ((unsigned short)-1)
+
 #define NETSTACK_CONF_LINUXRADIO_DEV "wpan0"
 
 /* configure network size and density */
diff --git a/arch/platform/native/platform.c b/arch/platform/native/platform.c
index d00efaac1ebc4f3d1eaed16a5532bdabc401551f..9b468efcda18db6848321cf05f77195ae5424e93 100644
--- a/arch/platform/native/platform.c
+++ b/arch/platform/native/platform.c
@@ -160,13 +160,21 @@ stdin_set_fd(fd_set *rset, fd_set *wset)
   FD_SET(STDIN_FILENO, rset);
   return 1;
 }
+
+static int (*input_handler)(unsigned char c);
+
+void native_uart_set_input(int (*input)(unsigned char c)) {
+  input_handler = input;
+}
+
+
 static void
 stdin_handle_fd(fd_set *rset, fd_set *wset)
 {
   char c;
   if(FD_ISSET(STDIN_FILENO, rset)) {
     if(read(STDIN_FILENO, &c, 1) > 0) {
-      serial_line_input_byte(c);
+      input_handler(c);
     }
   }
 }
@@ -196,16 +204,13 @@ set_lladdr(void)
 static void
 set_global_address(void)
 {
-  static uip_ipaddr_t ipaddr;
-  static uip_ipaddr_t *prefix = NULL;
+  uip_ipaddr_t ipaddr;
+  const uip_ipaddr_t *default_prefix = uip_ds6_default_prefix();
 
   /* Assign a unique local address (RFC4193,
      http://tools.ietf.org/html/rfc4193). */
-  if(prefix == NULL) {
-    uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
-  } else {
-    memcpy(&ipaddr, prefix, 8);
-  }
+  uip_ip6addr_copy(&ipaddr, default_prefix);
+
   /* Assumes that the uip_lladdr is set */
   uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
   uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
@@ -215,7 +220,8 @@ set_global_address(void)
   LOG_INFO_("\n");
 
   /* set the PREFIX::1 address to the IF */
-  uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 1);
+  uip_ip6addr_copy(&ipaddr, default_prefix);
+  ipaddr.u8[15] = 1;
   uip_ds6_defrt_add(&ipaddr, 0);
 }
 #endif
@@ -257,6 +263,11 @@ platform_init_stage_two()
 {
   set_lladdr();
   serial_line_init();
+
+  if (NULL == input_handler) {
+    native_uart_set_input(serial_line_input_byte);
+  }
+
 }
 /*---------------------------------------------------------------------------*/
 void
diff --git a/arch/platform/nrf52dk/Makefile.nrf52dk b/arch/platform/nrf52dk/Makefile.nrf52dk
index e1d56c090079d8c0fee73cc329425b2193c095fd..ff554b35c9775761843c044865612ec1d68b2623 100644
--- a/arch/platform/nrf52dk/Makefile.nrf52dk
+++ b/arch/platform/nrf52dk/Makefile.nrf52dk
@@ -3,7 +3,7 @@ ifndef CONTIKI
 endif
 
 ### Include the board-specific makefile
-PLATFORM_ROOT_DIR = $(CONTIKI)/arch/platform/$(TARGET)
+PLATFORM_ROOT_DIR = $(ARCH_PATH)/platform/$(TARGET)
 
 CONTIKI_TARGET_DIRS += . dev config
 CONTIKI_SOURCEFILES += platform.c leds-arch.c nrf52dk-sensors.c button-sensor.c temperature-sensor.c
@@ -21,5 +21,5 @@ endif
 SMALL ?= 0
 
 ### Define the CPU directory and pull in the correct CPU makefile.
-CONTIKI_CPU=$(CONTIKI)/arch/cpu/nrf52832
+CONTIKI_CPU=$(ARCH_PATH)/cpu/nrf52832
 include $(CONTIKI_CPU)/Makefile.nrf52832
diff --git a/arch/platform/nrf52dk/contiki-conf.h b/arch/platform/nrf52dk/contiki-conf.h
index 7b3b66314fa0830f4e1e8c7d45fdf03233bec065..f4d8dbabdbde2531dc331e8ed40b9b44d641758d 100644
--- a/arch/platform/nrf52dk/contiki-conf.h
+++ b/arch/platform/nrf52dk/contiki-conf.h
@@ -63,9 +63,6 @@
 #define NETSTACK_CONF_MAC     ble_ipsp_mac_driver
 #endif
 
-/* 6LoWPAN */
-#define SICSLOWPAN_CONF_MAC_MAX_PAYLOAD         1280
-
 #ifndef SICSLOWPAN_CONF_FRAG
 #define SICSLOWPAN_CONF_FRAG                    0     /**< We don't use 6LoWPAN fragmentation as IPSP takes care of that for us.*/
 #endif
@@ -74,6 +71,10 @@
 
 /* Packet buffer */
 #define PACKETBUF_CONF_SIZE                     1280  /**< Required IPv6 MTU size */
+
+/* Queuebuf */
+#define QUEUEBUF_CONF_ENABLED                   0
+
 /** @} */
 
 /**
diff --git a/arch/platform/nrf52dk/dev/temperature-sensor.c b/arch/platform/nrf52dk/dev/temperature-sensor.c
index 5aac8b3ef8cd9390e06b440acc240a0ff986aceb..f42fd3fe3d4f705c58a4f95159d62742c43640a5 100644
--- a/arch/platform/nrf52dk/dev/temperature-sensor.c
+++ b/arch/platform/nrf52dk/dev/temperature-sensor.c
@@ -64,7 +64,16 @@ static int
 value(int type)
 {
 #ifndef SOFTDEVICE_PRESENT
-  return nrf_temp_read();
+  int32_t volatile temp;
+
+  NRF_TEMP->TASKS_START = 1;
+  /* nRF52832 datasheet: one temperature measurement takes typically 36 us */
+  RTIMER_BUSYWAIT_UNTIL(NRF_TEMP->EVENTS_DATARDY, RTIMER_SECOND * 72 / 1000000);
+  NRF_TEMP->EVENTS_DATARDY = 0;
+  temp = nrf_temp_read();
+  NRF_TEMP->TASKS_STOP = 1;
+
+  return temp;
 #else
   int32_t temp;
   sd_temp_get(&temp);
diff --git a/arch/platform/openmote-cc2538/Makefile.openmote-cc2538 b/arch/platform/openmote-cc2538/Makefile.openmote-cc2538
index 8b25b0bfe8eeb14324b2f7a7f14660a27cbb1e3c..f720a9ae8bae758e9e418859741eedcba0cbf525 100644
--- a/arch/platform/openmote-cc2538/Makefile.openmote-cc2538
+++ b/arch/platform/openmote-cc2538/Makefile.openmote-cc2538
@@ -11,7 +11,7 @@ endif
 
 ### Configure the build for the board and pull in board-specific sources
 CONTIKI_TARGET_DIRS += . dev
-PLATFORM_ROOT_DIR = $(CONTIKI)/arch/platform/$(TARGET)
+PLATFORM_ROOT_DIR = $(ARCH_PATH)/platform/$(TARGET)
 
 ### Include
 CONTIKI_TARGET_SOURCEFILES += platform.c board.c
@@ -21,7 +21,7 @@ CONTIKI_TARGET_SOURCEFILES += antenna.c adxl346.c max44009.c sht21.c tps62730.c
 CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES)
 
 ### Define the CPU directory
-CONTIKI_CPU=$(CONTIKI)/arch/cpu/cc2538
+CONTIKI_CPU=$(ARCH_PATH)/cpu/cc2538
 include $(CONTIKI_CPU)/Makefile.cc2538
 
 MODULES += os/storage/cfs
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/Makefile.cc13xx-cc26xx b/arch/platform/simplelink/cc13xx-cc26xx/Makefile.cc13xx-cc26xx
index 9f2dbe45bcfad87354610325d90df09b6c037b2a..39a3fc5048b5ff9da9531db53ef2e30c98fc676a 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/Makefile.cc13xx-cc26xx
+++ b/arch/platform/simplelink/cc13xx-cc26xx/Makefile.cc13xx-cc26xx
@@ -51,7 +51,7 @@ CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES)
 CPU_FAMILY = cc13xx-cc26xx
 
 # Define the CPU directory and pull in the correct CPU Makefile
-CONTIKI_CPU := $(realpath $(CONTIKI)/arch/cpu/simplelink-$(CPU_FAMILY))
+CONTIKI_CPU := $(realpath $(ARCH_PATH)/cpu/simplelink-$(CPU_FAMILY))
 include $(CONTIKI_CPU)/Makefile.$(CPU_FAMILY)
 
 MODULES += os/net os/net/mac os/net/mac/framer
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/contiki-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/contiki-conf.h
index 212f4fd48cd265d0a037634c5148eac2673c4d13..542f69869b22d644c1700d300053bb58ac12ad7a 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/contiki-conf.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/contiki-conf.h
@@ -31,6 +31,10 @@
  * \addtogroup cc13xx-cc26xx-platform
  * @{
  *
+ * The order of which these header files are included is important in order
+ * for the configurations to be correctly set. This has to do with some
+ * slight unfortunate configuration dependencies of the board file.
+ *
  * \file
  *        Configuration for the SimpleLink CC13xx/CC26xx platform.
  * \author
@@ -40,18 +44,16 @@
 #ifndef CONTIKI_CONF_H_
 #define CONTIKI_CONF_H_
 /*---------------------------------------------------------------------------*/
-#include "board-conf.h"
-/*---------------------------------------------------------------------------*/
-/* Include Project Specific conf */
+/* Include project-specific configurations */
 #ifdef PROJECT_CONF_PATH
 #include PROJECT_CONF_PATH
 #endif
 /*---------------------------------------------------------------------------*/
-/* Include CPU-related configuration */
-#include "cc13xx-cc26xx-conf.h"
+/* Include board-specific configurations */
+#include "board-conf.h"
 /*---------------------------------------------------------------------------*/
-/* Must be included after cc13xx-cc26xx-conf.h */
-#include <Board.h>
+/* Include CPU-related configurations */
+#include "cc13xx-cc26xx-conf.h"
 /*---------------------------------------------------------------------------*/
 #endif /* CONTIKI_CONF_H_ */
 /*---------------------------------------------------------------------------*/
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/board-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/board-conf.h
index 71d59501d321921ec876a57090b2b594b55088c1..5e5c755288e2d90f336c5c7b265a757d6ba13448 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/board-conf.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/board-conf.h
@@ -50,7 +50,7 @@
 #ifndef BOARD_CONF_H_
 #define BOARD_CONF_H_
 /*---------------------------------------------------------------------------*/
-#include "contiki-conf.h"
+#include "rf-conf.h"
 /*---------------------------------------------------------------------------*/
 /**
  * \name LED configurations for the dev/leds.h API.
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1310/Board.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1310/Board.h
index 6b3c762d763dda61b8956ee284bbb4a9fc0320ac..88999fe6fa762723b8a099e12068c58fea567a86 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1310/Board.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1310/Board.h
@@ -36,6 +36,9 @@
 #define Board_CC1310_LAUNCHXL
 #define BOARD_STRING    "TI CC1310 LaunchPad"
 
+#define RF_CONF_FRONT_END_MODE  RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_CONF_BIAS_MODE       RF_BIAS_MODE_EXTERNAL
+
 #ifdef __cplusplus
 extern "C" {
 #endif
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1310/CC1310_LAUNCHXL.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1310/CC1310_LAUNCHXL.c
index b33dab9adf2e451be2ff9bc11e51aa78ade44126..b5db4e61d36e821b26c47f0b8d6ae6eae43a1cab 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1310/CC1310_LAUNCHXL.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1310/CC1310_LAUNCHXL.c
@@ -498,7 +498,7 @@ const PIN_Config BoardGpioInitTable[] = {
     CC1310_LAUNCHXL_PIN_BTN1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,          /* Button is active low       */
     CC1310_LAUNCHXL_PIN_BTN2 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,          /* Button is active low       */
     CC1310_LAUNCHXL_SPI_FLASH_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN,  /* External flash chip select */
-    CC1310_LAUNCHXL_UART_RX | PIN_INPUT_EN | PIN_PULLDOWN,                                              /* UART RX via debugger back channel */
+    CC1310_LAUNCHXL_UART_RX | PIN_INPUT_EN | PIN_PULLUP,                                                /* UART RX via debugger back channel */
     CC1310_LAUNCHXL_UART_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,                        /* UART TX via debugger back channel */
     CC1310_LAUNCHXL_SPI0_MOSI | PIN_INPUT_EN | PIN_PULLDOWN,                                            /* SPI master out - slave in */
     CC1310_LAUNCHXL_SPI0_MISO | PIN_INPUT_EN | PIN_PULLDOWN,                                            /* SPI master in - slave out */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1310/rf-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1310/rf-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..d26d3a86475fa17d323b42a9d901e24bb66d71ec
--- /dev/null
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1310/rf-conf.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup launchpad-peripherals
+ * @{
+ *
+ * \file
+ *        Header file with board-specific RF configurations.
+ * \author
+ *        Texas Instruments <e2e.ti.com>
+ * \note
+ *        This file should not be included directly
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef RF_CONF_H_
+#define RF_CONF_H_
+/*---------------------------------------------------------------------------*/
+#include "rf/rf.h"
+/*---------------------------------------------------------------------------*/
+/**
+ * \name  Board-specific front-end mode configurations for the Sub-1 GHz path
+ *        on the radio.
+ *
+ * These are the following front-end mode configurations for the
+ * CC1310-LAUNCHXL board:
+ *  - Sub-1 GHz: differential and external bias
+ *
+ * @{
+ */
+#define RF_SUB_1_GHZ_CONF_FRONT_END_MODE  RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_SUB_1_GHZ_CONF_BIAS_MODE       RF_BIAS_MODE_EXTERNAL
+/** @} */
+/*---------------------------------------------------------------------------*/
+#endif /* RF_CONF_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ * @}
+ */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1312r1/Board.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1312r1/Board.h
index c3763b01928e98a22f1ce96d21360a1a2cc41bf4..a230c764e3edf36d551396a7eecf054e05b1c441 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1312r1/Board.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1312r1/Board.h
@@ -33,15 +33,15 @@
 #ifndef __BOARD_H
 #define __BOARD_H
 
-#define Board_CC1312R1_LAUNCHXL
-#define BOARD_STRING    "TI CC1312R1 LaunchPad"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include "CC1312R1_LAUNCHXL.h"
 
+#define Board_CC1312R1_LAUNCHXL
+#define BOARD_STRING            "TI CC1312R1 LaunchPad"
+
 #define Board_initGeneral()      CC1312R1_LAUNCHXL_initGeneral()
 #define Board_shutDownExtFlash() CC1312R1_LAUNCHXL_shutDownExtFlash()
 #define Board_wakeUpExtFlash()   CC1312R1_LAUNCHXL_wakeUpExtFlash()
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1312r1/CC1312R1_LAUNCHXL.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1312r1/CC1312R1_LAUNCHXL.c
index 44fd410353cc15bb7fe656defff9a99184a3e5e8..a51bba632ba14d363b9162200cef41d77f61b938 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1312r1/CC1312R1_LAUNCHXL.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1312r1/CC1312R1_LAUNCHXL.c
@@ -619,7 +619,7 @@ const PIN_Config BoardGpioInitTable[] = {
     CC1312R1_LAUNCHXL_PIN_BTN1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,          /* Button is active low       */
     CC1312R1_LAUNCHXL_PIN_BTN2 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,          /* Button is active low       */
     CC1312R1_LAUNCHXL_SPI_FLASH_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN,  /* External flash chip select */
-    CC1312R1_LAUNCHXL_UART_RX | PIN_INPUT_EN | PIN_PULLDOWN,                                              /* UART RX via debugger back channel */
+    CC1312R1_LAUNCHXL_UART_RX | PIN_INPUT_EN | PIN_PULLUP,                                                /* UART RX via debugger back channel */
     CC1312R1_LAUNCHXL_UART_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,                        /* UART TX via debugger back channel */
     CC1312R1_LAUNCHXL_SPI0_MOSI | PIN_INPUT_EN | PIN_PULLDOWN,                                            /* SPI master out - slave in */
     CC1312R1_LAUNCHXL_SPI0_MISO | PIN_INPUT_EN | PIN_PULLDOWN,                                            /* SPI master in - slave out */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1312r1/rf-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1312r1/rf-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..f649dd170a889adaca7ae948d81671c5bf984d7b
--- /dev/null
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1312r1/rf-conf.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup launchpad-peripherals
+ * @{
+ *
+ * \file
+ *        Header file with board-specific RF configurations.
+ * \author
+ *        Texas Instruments <e2e.ti.com>
+ * \note
+ *        This file should not be included directly
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef RF_CONF_H_
+#define RF_CONF_H_
+/*---------------------------------------------------------------------------*/
+#include "rf/rf.h"
+/*---------------------------------------------------------------------------*/
+/**
+ * \name  Board-specific front-end mode configurations for the Sub-1 GHz path
+ *        on the radio.
+ *
+ * These are the following front-end mode configurations for the
+ * CC1312R1-LAUNCHXL board:
+ *  - Sub-1 GHz: differential and external bias
+ *
+ * @{
+ */
+#define RF_SUB_1_GHZ_CONF_FRONT_END_MODE  RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_SUB_1_GHZ_CONF_BIAS_MODE       RF_BIAS_MODE_EXTERNAL
+/** @} */
+/*---------------------------------------------------------------------------*/
+#endif /* RF_CONF_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350-4/Board.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350-4/Board.h
index c8094432a8f23d42ef7621532b7665799c83d47e..4b8fbe5c0ec5b1d8b05d1a5256f787cec42691bd 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350-4/Board.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350-4/Board.h
@@ -33,15 +33,15 @@
 #ifndef __BOARD_H
 #define __BOARD_H
 
-#define Board_CC1350_LAUNCHXL_433
-#define BOARD_STRING    "TI CC1350-433 LaunchPad"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include "CC1350_LAUNCHXL_433.h"
 
+#define Board_CC1350_LAUNCHXL_433
+#define BOARD_STRING            "TI CC1350-433 LaunchPad"
+
 #define Board_initGeneral()      CC1350_LAUNCHXL_433_initGeneral()
 #define Board_shutDownExtFlash() CC1350_LAUNCHXL_433_shutDownExtFlash()
 #define Board_wakeUpExtFlash()   CC1350_LAUNCHXL_433_wakeUpExtFlash()
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350-4/CC1350_LAUNCHXL_433.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350-4/CC1350_LAUNCHXL_433.c
index b4d34a54bb7dc9d769aee3d262641ffe2c1000bf..aa690dff419333ad3b7203e29d689e71fb534dd7 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350-4/CC1350_LAUNCHXL_433.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350-4/CC1350_LAUNCHXL_433.c
@@ -493,7 +493,7 @@ const PIN_Config BoardGpioInitTable[] = {
     CC1350_LAUNCHXL_433_PIN_BTN1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,             /* Button is active low          */
     CC1350_LAUNCHXL_433_PIN_BTN2 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,             /* Button is active low          */
     CC1350_LAUNCHXL_433_SPI_FLASH_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN,     /* External flash chip select    */
-    CC1350_LAUNCHXL_433_UART_RX | PIN_INPUT_EN | PIN_PULLDOWN,                                                 /* UART RX via debugger back channel */
+    CC1350_LAUNCHXL_433_UART_RX | PIN_INPUT_EN | PIN_PULLUP,                                                   /* UART RX via debugger back channel */
     CC1350_LAUNCHXL_433_UART_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,                           /* UART TX via debugger back channel */
     CC1350_LAUNCHXL_433_DIO1_RF_SUB1GHZ   | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* RF SW Switch defaults to 2.4 GHz path*/
     CC1350_LAUNCHXL_433_DIO30_RF_POWER | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,    /* External RF Switch is powered off by default */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350-4/CC1350_LAUNCHXL_433_fxns.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350-4/CC1350_LAUNCHXL_433_fxns.c
index a8a6b16c03dd0c8171d3ea66ea5825eb9ec094ee..92e349480f1a383a53ec7414f141dea6bb48eda6 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350-4/CC1350_LAUNCHXL_433_fxns.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350-4/CC1350_LAUNCHXL_433_fxns.c
@@ -165,23 +165,60 @@ void Board_initHook()
 #if defined(Board_RF_SUB1GHZ)
 
 /*
- * ======== CC1350_LAUNCHXL_433_rfDriverCallback ========
- * This is an implementation for the CC1350 launchpad which uses a
+ * Mask to be used to determine the effective value of the setup command's
+ * loDivider field.
+ */
+#define LODIVIDER_MASK   0x7F
+
+/*
+ * ======== rfDriverCallback ========
+ * This is an implementation for the CC1350 LaunchPad which uses a
  * single signal for antenna switching.
  */
 void rfDriverCallback(RF_Handle client, RF_GlobalEvent events, void *arg)
 {
+    /* Decode input arguments. */
     (void)client;
     RF_RadioSetup* setupCommand = (RF_RadioSetup*)arg;
 
+    /* Local variable. */
+    bool    sub1GHz   = false;
+    uint8_t loDivider = 0;
+
     if (events & RF_GlobalEventRadioSetup) {
         /* Power up the antenna switch */
         PINCC26XX_setOutputValue(Board_RF_POWER, 1);
 
-        if (setupCommand->common.commandNo == CMD_PROP_RADIO_DIV_SETUP) {
-            /* Sub-1 GHz, requires antenna switch high */
+        /* Decision about the frequency band shall be made based on the
+           loDivider field. */
+        switch (setupCommand->common.commandNo) {
+            case (CMD_RADIO_SETUP):
+            case (CMD_BLE5_RADIO_SETUP):
+                    loDivider = LODIVIDER_MASK & setupCommand->common.loDivider;
+
+                    /* Sub-1 GHz, requires antenna switch high. */
+                    if ((loDivider != 0) && (loDivider != 2)) {
+                            sub1GHz = true;
+                    }
+                    break;
+            case (CMD_PROP_RADIO_DIV_SETUP):
+                    loDivider = LODIVIDER_MASK & setupCommand->prop_div.loDivider;
+
+                    /* Sub-1 GHz, requires antenna switch high. */
+                    if ((loDivider != 0) && (loDivider != 2)) {
+                            sub1GHz = true;
+                    }
+                    break;
+            default:break;
+        }
+
+        /* Select the correct antenna. */
+        if (sub1GHz) {
             PINCC26XX_setOutputValue(Board_RF_SUB1GHZ, 1);
         }
+        else {
+            PINCC26XX_setOutputValue(Board_RF_SUB1GHZ, 0);
+        }
     }
     else if (events & RF_GlobalEventRadioPowerDown) {
         /* Disable antenna switch to save current */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350-4/rf-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350-4/rf-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..371af4d89cca805e530d9ce54af1909cce1db2fc
--- /dev/null
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350-4/rf-conf.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup launchpad-peripherals
+ * @{
+ *
+ * \file
+ *        Header file with board-specific RF configurations.
+ * \author
+ *        Texas Instruments <e2e.ti.com>
+ * \note
+ *        This file should not be included directly
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef RF_CONF_H_
+#define RF_CONF_H_
+/*---------------------------------------------------------------------------*/
+#include "rf/rf.h"
+/*---------------------------------------------------------------------------*/
+/**
+ * \name  Board-specific front-end mode configurations for both the Sub-1 GHz
+ *        path and the 2.4 GHz path on the radio.
+ *
+ * These are the following front-end mode configurations for the
+ * CC1350-4-LAUNCHXL board:
+ *  - Sub-1 GHz: differential and external bias
+ *  - 2.4 GHz: differential and external bias
+ *
+ * @{
+ */
+#define RF_SUB_1_GHZ_CONF_FRONT_END_MODE  RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_SUB_1_GHZ_CONF_BIAS_MODE       RF_BIAS_MODE_EXTERNAL
+
+#define RF_2_4_GHZ_CONF_FRONT_END_MODE    RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_2_4_GHZ_CONF_BIAS_MODE         RF_BIAS_MODE_EXTERNAL
+/** @} */
+/*---------------------------------------------------------------------------*/
+#endif /* RF_CONF_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350/Board.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350/Board.h
index 2099b1845f04ed5ad88dad611f5c3d7c2ba90150..97ff04a5972c2a35a33305bec1a3e677a66791c5 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350/Board.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350/Board.h
@@ -33,15 +33,15 @@
 #ifndef __BOARD_H
 #define __BOARD_H
 
-#define Board_CC1350_LAUNCHXL
-#define BOARD_STRING    "TI CC1350 LaunchPad"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include "CC1350_LAUNCHXL.h"
 
+#define Board_CC1350_LAUNCHXL
+#define BOARD_STRING            "TI CC1350 LaunchPad"
+
 #define Board_initGeneral()      CC1350_LAUNCHXL_initGeneral()
 #define Board_shutDownExtFlash() CC1350_LAUNCHXL_shutDownExtFlash()
 #define Board_wakeUpExtFlash()   CC1350_LAUNCHXL_wakeUpExtFlash()
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350/CC1350_LAUNCHXL.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350/CC1350_LAUNCHXL.c
index 1277fc66a37272585268c072557f3377a8b79386..ff7f473516c76fdd6735e77b5b76436382b729e6 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350/CC1350_LAUNCHXL.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350/CC1350_LAUNCHXL.c
@@ -498,7 +498,7 @@ const PIN_Config BoardGpioInitTable[] = {
     CC1350_LAUNCHXL_PIN_BTN1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,             /* Button is active low          */
     CC1350_LAUNCHXL_PIN_BTN2 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,             /* Button is active low          */
     CC1350_LAUNCHXL_SPI_FLASH_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN,     /* External flash chip select    */
-    CC1350_LAUNCHXL_UART_RX | PIN_INPUT_EN | PIN_PULLDOWN,                                                 /* UART RX via debugger back channel */
+    CC1350_LAUNCHXL_UART_RX | PIN_INPUT_EN | PIN_PULLUP,                                                   /* UART RX via debugger back channel */
     CC1350_LAUNCHXL_UART_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,                           /* UART TX via debugger back channel */
     CC1350_LAUNCHXL_DIO1_RF_SUB1GHZ   | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX, /* RF SW Switch defaults to 2.4 GHz path*/
     CC1350_LAUNCHXL_DIO30_RF_POWER | PIN_GPIO_OUTPUT_EN | PIN_GPIO_LOW | PIN_PUSHPULL | PIN_DRVSTR_MAX,    /* External RF Switch is powered off by default */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350/CC1350_LAUNCHXL_fxns.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350/CC1350_LAUNCHXL_fxns.c
index 90f69a0c03b7a725d48aebbf6d986754988ebb0c..56de7c562c42f419950680f79dbd9ae30b49bb9f 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350/CC1350_LAUNCHXL_fxns.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350/CC1350_LAUNCHXL_fxns.c
@@ -166,6 +166,12 @@ void Board_initHook()
  */
 #if defined(Board_RF_SUB1GHZ)
 
+/*
+ * Mask to be used to determine the effective value of the setup command's
+ * loDivider field.
+ */
+#define LODIVIDER_MASK   0x7F
+
 /*
  * ======== rfDriverCallback ========
  * This is an implementation for the CC1350 launchpad which uses a
@@ -173,17 +179,48 @@ void Board_initHook()
  */
 void rfDriverCallback(RF_Handle client, RF_GlobalEvent events, void *arg)
 {
+    /* Decode input arguments. */
     (void)client;
     RF_RadioSetup* setupCommand = (RF_RadioSetup*)arg;
 
+    /* Local variable. */
+    bool    sub1GHz   = false;
+    uint8_t loDivider = 0;
+
     if (events & RF_GlobalEventRadioSetup) {
         /* Power up the antenna switch */
         PINCC26XX_setOutputValue(Board_RF_POWER, 1);
 
-        if (setupCommand->common.commandNo == CMD_PROP_RADIO_DIV_SETUP) {
-            /* Sub-1 GHz, requires antenna switch high */
+        /* Decision about the frequency band shall be made based on the
+           loDivider field. */
+        switch (setupCommand->common.commandNo) {
+            case (CMD_RADIO_SETUP):
+            case (CMD_BLE5_RADIO_SETUP):
+                    loDivider = LODIVIDER_MASK & setupCommand->common.loDivider;
+
+                    /* Sub-1 GHz, requires antenna switch high. */
+                    if ((loDivider != 0) && (loDivider != 2)) {
+                            sub1GHz = true;
+                    }
+                    break;
+            case (CMD_PROP_RADIO_DIV_SETUP):
+                    loDivider = LODIVIDER_MASK & setupCommand->prop_div.loDivider;
+
+                    /* Sub-1 GHz, requires antenna switch high. */
+                    if ((loDivider != 0) && (loDivider != 2)) {
+                            sub1GHz = true;
+                    }
+                    break;
+            default:break;
+        }
+
+        /* Select the correct antenna. */
+        if (sub1GHz) {
             PINCC26XX_setOutputValue(Board_RF_SUB1GHZ, 1);
         }
+        else {
+            PINCC26XX_setOutputValue(Board_RF_SUB1GHZ, 0);
+        }
     }
     else if (events & RF_GlobalEventRadioPowerDown) {
         /* Disable antenna switch to save current */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350/rf-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350/rf-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..e6cd0b7447b5ace2f53d437b6a4af90182fb8c3b
--- /dev/null
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1350/rf-conf.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup launchpad-peripherals
+ * @{
+ *
+ * \file
+ *        Header file with board-specific RF configurations.
+ * \author
+ *        Texas Instruments <e2e.ti.com>
+ * \note
+ *        This file should not be included directly
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef RF_CONF_H_
+#define RF_CONF_H_
+/*---------------------------------------------------------------------------*/
+#include "rf/rf.h"
+/*---------------------------------------------------------------------------*/
+/**
+ * \name  Board-specific front-end mode configurations for both the Sub-1 GHz
+ *        path and the 2.4 GHz path on the radio.
+ *
+ * These are the following front-end mode configurations for the
+ * CC1350-LAUNCHXL board:
+ *  - Sub-1 GHz: differential and external bias
+ *  - 2.4 GHz: differential and external bias
+ *
+ * @{
+ */
+#define RF_SUB_1_GHZ_CONF_FRONT_END_MODE  RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_SUB_1_GHZ_CONF_BIAS_MODE       RF_BIAS_MODE_EXTERNAL
+
+#define RF_2_4_GHZ_CONF_FRONT_END_MODE    RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_2_4_GHZ_CONF_BIAS_MODE         RF_BIAS_MODE_EXTERNAL
+/** @} */
+/*---------------------------------------------------------------------------*/
+#endif /* RF_CONF_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-2/Board.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-2/Board.h
index d22d73c171cbb57b47b0bbe87032d78f93cb606b..40f76e18b7e2df3a6ebb6063fdad8ba608a880d4 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-2/Board.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-2/Board.h
@@ -33,15 +33,15 @@
 #ifndef __BOARD_H
 #define __BOARD_H
 
-#define Board_CC1352P_2_LAUNCHXL
-#define BOARD_STRING    "TI CC1352P-2 LaunchPad"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include "CC1352P_2_LAUNCHXL.h"
 
+#define Board_CC1352P_2_LAUNCHXL
+#define BOARD_STRING            "TI CC1352P-2 LaunchPad"
+
 #define Board_initGeneral()      CC1352P_2_LAUNCHXL_initGeneral()
 #define Board_shutDownExtFlash() CC1352P_2_LAUNCHXL_shutDownExtFlash()
 #define Board_wakeUpExtFlash()   CC1352P_2_LAUNCHXL_wakeUpExtFlash()
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-2/CC1352P_2_LAUNCHXL.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-2/CC1352P_2_LAUNCHXL.c
index a1b74bce438583a711ac555f7ee1c06dd5811b74..c2717cc70f6598200d1ba5c6abd2ca127ca27c5e 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-2/CC1352P_2_LAUNCHXL.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-2/CC1352P_2_LAUNCHXL.c
@@ -585,7 +585,7 @@ const PIN_Config BoardGpioInitTable[] = {
     CC1352P_2_LAUNCHXL_PIN_BTN1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,             /* Button is active low */
     CC1352P_2_LAUNCHXL_PIN_BTN2 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,             /* Button is active low */
     CC1352P_2_LAUNCHXL_SPI_FLASH_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN,     /* External flash chip select */
-    CC1352P_2_LAUNCHXL_UART0_RX | PIN_INPUT_EN | PIN_PULLDOWN,                                                /* UART RX via debugger back channel */
+    CC1352P_2_LAUNCHXL_UART0_RX | PIN_INPUT_EN | PIN_PULLUP,                                                  /* UART RX via debugger back channel */
     CC1352P_2_LAUNCHXL_UART0_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,                          /* UART TX via debugger back channel */
     CC1352P_2_LAUNCHXL_SPI0_MOSI | PIN_INPUT_EN | PIN_PULLDOWN,                                               /* SPI master out - slave in */
     CC1352P_2_LAUNCHXL_SPI0_MISO | PIN_INPUT_EN | PIN_PULLDOWN,                                               /* SPI master in - slave out */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-2/CC1352P_2_LAUNCHXL_fxns.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-2/CC1352P_2_LAUNCHXL_fxns.c
index f8b4930c84d69a6d4c6e7f34ed0910b2fc73f1f6..57f545360af5c12198aaee5fad02153e643834af 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-2/CC1352P_2_LAUNCHXL_fxns.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-2/CC1352P_2_LAUNCHXL_fxns.c
@@ -152,6 +152,12 @@ void CC1352P_2_LAUNCHXL_shutDownExtFlash(void)
  */
 #if defined(Board_RF_SUB1GHZ)
 
+/*
+ * Mask to be used to determine the effective value of the setup command's
+ * loDivider field.
+ */
+#define LODIVIDER_MASK   0x7F
+
 /*
  * ======== Antenna switching ========
  */
@@ -170,7 +176,7 @@ void initAntennaSwitch()
 }
 
 /*
- * ======== rfDriverCallback ========
+ * ======== CC1352P1_LAUNCHXL_rfDriverCallback ========
  * Sets up the antenna switch depending on the current PHY configuration.
  * Truth table:
  *
@@ -183,6 +189,10 @@ void initAntennaSwitch()
  */
 void rfDriverCallback(RF_Handle client, RF_GlobalEvent events, void *arg)
 {
+    /* Local variable. */
+    bool    sub1GHz   = false;
+    uint8_t loDivider = 0;
+
     /* Switch off all paths first. Needs to be done anyway in every sub-case below. */
     PINCC26XX_setOutputValue(Board_RF_24GHZ, 0);
     PINCC26XX_setOutputValue(Board_RF_HIGH_PA, 0);
@@ -195,15 +205,36 @@ void rfDriverCallback(RF_Handle client, RF_GlobalEvent events, void *arg)
         /* Decode the generic argument as a setup command. */
         RF_RadioSetup* setupCommand = (RF_RadioSetup*)arg;
 
-        if (setupCommand->common.commandNo == CMD_PROP_RADIO_DIV_SETUP) {
+        switch (setupCommand->common.commandNo) {
+            case (CMD_RADIO_SETUP):
+            case (CMD_BLE5_RADIO_SETUP):
+                    loDivider = LODIVIDER_MASK & setupCommand->common.loDivider;
+
+                    /* Sub-1GHz front-end. */
+                    if (loDivider != 0) {
+                        sub1GHz = true;
+                    }
+                    break;
+            case (CMD_PROP_RADIO_DIV_SETUP):
+                    loDivider = LODIVIDER_MASK & setupCommand->prop_div.loDivider;
+
+                    /* Sub-1GHz front-end. */
+                    if (loDivider != 0) {
+                        sub1GHz = true;
+                    }
+                    break;
+            default:break;
+        }
+
+        if (sub1GHz) {
             /* Sub-1 GHz */
             if (paType == RF_TxPowerTable_HighPA) {
                 /* PA enable --> HIGH PA
                  * LNA enable --> Sub-1 GHz
                  */
                 PINCC26XX_setMux(antennaPins, Board_RF_24GHZ, PINCC26XX_MUX_GPIO);
-                // Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
-                //       de-asserted on CC1352 Rev A.
+                /* Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
+                         de-asserted on CC1352 Rev A. */
                 PINCC26XX_setMux(antennaPins, Board_RF_HIGH_PA, PINCC26XX_MUX_RFC_GPO3);
                 PINCC26XX_setMux(antennaPins, Board_RF_SUB1GHZ, PINCC26XX_MUX_RFC_GPO0);
             } else {
@@ -221,8 +252,8 @@ void rfDriverCallback(RF_Handle client, RF_GlobalEvent events, void *arg)
                  * LNA enable --> 2.4 GHz
                  */
                 PINCC26XX_setMux(antennaPins, Board_RF_24GHZ, PINCC26XX_MUX_RFC_GPO0);
-                // Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
-                //       de-asserted on CC1352 Rev A.
+                /* Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
+                         de-asserted on CC1352 Rev A. */
                 PINCC26XX_setMux(antennaPins, Board_RF_HIGH_PA, PINCC26XX_MUX_RFC_GPO3);
                 PINCC26XX_setMux(antennaPins, Board_RF_SUB1GHZ, PINCC26XX_MUX_GPIO);
             } else {
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-2/rf-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-2/rf-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..1eb0926b70ed0f739b9f8a4c7dea0dd3f89f23f9
--- /dev/null
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-2/rf-conf.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup launchpad-peripherals
+ * @{
+ *
+ * \file
+ *        Header file with board-specific RF configurations.
+ * \author
+ *        Texas Instruments <e2e.ti.com>
+ * \note
+ *        This file should not be included directly
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef RF_CONF_H_
+#define RF_CONF_H_
+/*---------------------------------------------------------------------------*/
+#include "rf/rf.h"
+/*---------------------------------------------------------------------------*/
+/**
+ * \name  Board-specific front-end mode configurations for both the Sub-1 GHz
+ *        path and the 2.4 GHz path on the radio.
+ *
+ * These are the following front-end mode configurations for the
+ * CC1352P-2-LAUNCHXL board:
+ *  - Sub-1 GHz: differential and external bias
+ *  - 2.4 GHz: differential and external bias
+ *
+ * @{
+ */
+#define RF_SUB_1_GHZ_CONF_FRONT_END_MODE  RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_SUB_1_GHZ_CONF_BIAS_MODE       RF_BIAS_MODE_EXTERNAL
+
+#define RF_2_4_GHZ_CONF_FRONT_END_MODE    RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_2_4_GHZ_CONF_BIAS_MODE         RF_BIAS_MODE_EXTERNAL
+/** @} */
+/*---------------------------------------------------------------------------*/
+#endif /* RF_CONF_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-4/Board.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-4/Board.h
index 38165170824b242135cc51ea840450d66f33f1bf..de9bc8e9d2b1c0885acc76af77715a34eb50e598 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-4/Board.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-4/Board.h
@@ -33,15 +33,15 @@
 #ifndef __BOARD_H
 #define __BOARD_H
 
-#define Board_CC1352P_4_LAUNCHXL
-#define BOARD_STRING    "TI CC1352P-4 LaunchPad"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include "CC1352P_4_LAUNCHXL.h"
 
+#define Board_CC1352P_4_LAUNCHXL
+#define BOARD_STRING            "TI CC1352P-4 LaunchPad"
+
 #define Board_initGeneral()      CC1352P_4_LAUNCHXL_initGeneral()
 #define Board_shutDownExtFlash() CC1352P_4_LAUNCHXL_shutDownExtFlash()
 #define Board_wakeUpExtFlash()   CC1352P_4_LAUNCHXL_wakeUpExtFlash()
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-4/CC1352P_4_LAUNCHXL.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-4/CC1352P_4_LAUNCHXL.c
index 63a41d64bf9ff24f5094d9ab7bfa47370f48fb48..bd4f43032fc10c03f7c76109fa0da16b52d512dc 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-4/CC1352P_4_LAUNCHXL.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-4/CC1352P_4_LAUNCHXL.c
@@ -585,7 +585,7 @@ const PIN_Config BoardGpioInitTable[] = {
     CC1352P_4_LAUNCHXL_PIN_BTN1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,             /* Button is active low */
     CC1352P_4_LAUNCHXL_PIN_BTN2 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,             /* Button is active low */
     CC1352P_4_LAUNCHXL_SPI_FLASH_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN,     /* External flash chip select */
-    CC1352P_4_LAUNCHXL_UART0_RX | PIN_INPUT_EN | PIN_PULLDOWN,                                                /* UART RX via debugger back channel */
+    CC1352P_4_LAUNCHXL_UART0_RX | PIN_INPUT_EN | PIN_PULLUP,                                                  /* UART RX via debugger back channel */
     CC1352P_4_LAUNCHXL_UART0_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,                          /* UART TX via debugger back channel */
     CC1352P_4_LAUNCHXL_SPI0_MOSI | PIN_INPUT_EN | PIN_PULLDOWN,                                               /* SPI master out - slave in */
     CC1352P_4_LAUNCHXL_SPI0_MISO | PIN_INPUT_EN | PIN_PULLDOWN,                                               /* SPI master in - slave out */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-4/CC1352P_4_LAUNCHXL_fxns.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-4/CC1352P_4_LAUNCHXL_fxns.c
index ef9c0531c8f0e700fd3c57921adea4bc5756d063..eea9c3b33ea0a82328202e0adf605188f098a4a6 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-4/CC1352P_4_LAUNCHXL_fxns.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-4/CC1352P_4_LAUNCHXL_fxns.c
@@ -152,6 +152,12 @@ void CC1352P_4_LAUNCHXL_shutDownExtFlash(void)
  */
 #if defined(Board_RF_SUB1GHZ)
 
+/*
+ * Mask to be used to determine the effective value of the setup command's
+ * loDivider field.
+ */
+#define LODIVIDER_MASK   0x7F
+
 /*
  * ======== Antenna switching ========
  */
@@ -170,7 +176,7 @@ void initAntennaSwitch()
 }
 
 /*
- * ======== rfDriverCallback ========
+ * ======== CC1352P1_LAUNCHXL_rfDriverCallback ========
  * Sets up the antenna switch depending on the current PHY configuration.
  * Truth table:
  *
@@ -183,6 +189,10 @@ void initAntennaSwitch()
  */
 void rfDriverCallback(RF_Handle client, RF_GlobalEvent events, void *arg)
 {
+    /* Local variable. */
+    bool    sub1GHz   = false;
+    uint8_t loDivider = 0;
+
     /* Switch off all paths first. Needs to be done anyway in every sub-case below. */
     PINCC26XX_setOutputValue(Board_RF_24GHZ, 0);
     PINCC26XX_setOutputValue(Board_RF_HIGH_PA, 0);
@@ -195,15 +205,36 @@ void rfDriverCallback(RF_Handle client, RF_GlobalEvent events, void *arg)
         /* Decode the generic argument as a setup command. */
         RF_RadioSetup* setupCommand = (RF_RadioSetup*)arg;
 
-        if (setupCommand->common.commandNo == CMD_PROP_RADIO_DIV_SETUP) {
+        switch (setupCommand->common.commandNo) {
+            case (CMD_RADIO_SETUP):
+            case (CMD_BLE5_RADIO_SETUP):
+                    loDivider = LODIVIDER_MASK & setupCommand->common.loDivider;
+
+                    /* Sub-1GHz front-end. */
+                    if (loDivider != 0) {
+                        sub1GHz = true;
+                    }
+                    break;
+            case (CMD_PROP_RADIO_DIV_SETUP):
+                    loDivider = LODIVIDER_MASK & setupCommand->prop_div.loDivider;
+
+                    /* Sub-1GHz front-end. */
+                    if (loDivider != 0) {
+                        sub1GHz = true;
+                    }
+                    break;
+            default:break;
+        }
+
+        if (sub1GHz) {
             /* Sub-1 GHz */
             if (paType == RF_TxPowerTable_HighPA) {
                 /* PA enable --> HIGH PA
                  * LNA enable --> Sub-1 GHz
                  */
                 PINCC26XX_setMux(antennaPins, Board_RF_24GHZ, PINCC26XX_MUX_GPIO);
-                // Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
-                //       de-asserted on CC1352 Rev A.
+                /* Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
+                         de-asserted on CC1352 Rev A. */
                 PINCC26XX_setMux(antennaPins, Board_RF_HIGH_PA, PINCC26XX_MUX_RFC_GPO3);
                 PINCC26XX_setMux(antennaPins, Board_RF_SUB1GHZ, PINCC26XX_MUX_RFC_GPO0);
             } else {
@@ -221,8 +252,8 @@ void rfDriverCallback(RF_Handle client, RF_GlobalEvent events, void *arg)
                  * LNA enable --> 2.4 GHz
                  */
                 PINCC26XX_setMux(antennaPins, Board_RF_24GHZ, PINCC26XX_MUX_RFC_GPO0);
-                // Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
-                //       de-asserted on CC1352 Rev A.
+                /* Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
+                         de-asserted on CC1352 Rev A. */
                 PINCC26XX_setMux(antennaPins, Board_RF_HIGH_PA, PINCC26XX_MUX_RFC_GPO3);
                 PINCC26XX_setMux(antennaPins, Board_RF_SUB1GHZ, PINCC26XX_MUX_GPIO);
             } else {
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-4/rf-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-4/rf-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..af183614bd37ca4ffe6fb54c403c9184a94608a1
--- /dev/null
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p-4/rf-conf.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup launchpad-peripherals
+ * @{
+ *
+ * \file
+ *        Header file with board-specific RF configurations.
+ * \author
+ *        Texas Instruments <e2e.ti.com>
+ * \note
+ *        This file should not be included directly
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef RF_CONF_H_
+#define RF_CONF_H_
+/*---------------------------------------------------------------------------*/
+#include "rf/rf.h"
+/*---------------------------------------------------------------------------*/
+/**
+ * \name  Board-specific front-end mode configurations for both the Sub-1 GHz
+ *        path and the 2.4 GHz path on the radio.
+ *
+ * These are the following front-end mode configurations for the
+ * CC1352P-4-LAUNCHXL board:
+ *  - Sub-1 GHz: differential and external bias
+ *  - 2.4 GHz: differential and external bias
+ *
+ * @{
+ */
+#define RF_SUB_1_GHZ_CONF_FRONT_END_MODE  RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_SUB_1_GHZ_CONF_BIAS_MODE       RF_BIAS_MODE_EXTERNAL
+
+#define RF_2_4_GHZ_CONF_FRONT_END_MODE    RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_2_4_GHZ_CONF_BIAS_MODE         RF_BIAS_MODE_EXTERNAL
+/** @} */
+/*---------------------------------------------------------------------------*/
+#endif /* RF_CONF_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p1/Board.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p1/Board.h
index 1fef09180419a2acda9e5b9374ef44d2c3f08d43..db07b3a0d1d0bc390ad844b4dc21655d55ee8f3a 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p1/Board.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p1/Board.h
@@ -33,15 +33,15 @@
 #ifndef __BOARD_H
 #define __BOARD_H
 
-#define Board_CC1352P1_LAUNCHXL
-#define BOARD_STRING    "TI CC1352P1 LaunchPad"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include "CC1352P1_LAUNCHXL.h"
 
+#define Board_CC1352P1_LAUNCHXL
+#define BOARD_STRING            "TI CC1352P1 LaunchPad"
+
 #define Board_initGeneral()      CC1352P1_LAUNCHXL_initGeneral()
 #define Board_shutDownExtFlash() CC1352P1_LAUNCHXL_shutDownExtFlash()
 #define Board_wakeUpExtFlash()   CC1352P1_LAUNCHXL_wakeUpExtFlash()
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p1/CC1352P1_LAUNCHXL.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p1/CC1352P1_LAUNCHXL.c
index d4f953fba90ee92f83e6f4addf59199bb93b9b4e..cff74bc036101c9197c637ae9b40e72f6ef89260 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p1/CC1352P1_LAUNCHXL.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p1/CC1352P1_LAUNCHXL.c
@@ -585,7 +585,7 @@ const PIN_Config BoardGpioInitTable[] = {
     CC1352P1_LAUNCHXL_PIN_BTN1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,             /* Button is active low */
     CC1352P1_LAUNCHXL_PIN_BTN2 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,             /* Button is active low */
     CC1352P1_LAUNCHXL_SPI_FLASH_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN,     /* External flash chip select */
-    CC1352P1_LAUNCHXL_UART0_RX | PIN_INPUT_EN | PIN_PULLDOWN,                                                /* UART RX via debugger back channel */
+    CC1352P1_LAUNCHXL_UART0_RX | PIN_INPUT_EN | PIN_PULLUP,                                                  /* UART RX via debugger back channel */
     CC1352P1_LAUNCHXL_UART0_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,                          /* UART TX via debugger back channel */
     CC1352P1_LAUNCHXL_SPI0_MOSI | PIN_INPUT_EN | PIN_PULLDOWN,                                               /* SPI master out - slave in */
     CC1352P1_LAUNCHXL_SPI0_MISO | PIN_INPUT_EN | PIN_PULLDOWN,                                               /* SPI master in - slave out */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p1/CC1352P1_LAUNCHXL_fxns.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p1/CC1352P1_LAUNCHXL_fxns.c
index 9f30009290c6250dbb4dc6480a083bc6976e0a51..795f60106290be0e5e7df99c03f8867003117694 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p1/CC1352P1_LAUNCHXL_fxns.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p1/CC1352P1_LAUNCHXL_fxns.c
@@ -152,6 +152,12 @@ void CC1352P1_LAUNCHXL_shutDownExtFlash(void)
  */
 #if defined(Board_RF_SUB1GHZ)
 
+/*
+ * Mask to be used to determine the effective value of the setup command's
+ * loDivider field.
+ */
+#define LODIVIDER_MASK   0x7F
+
 /*
  * ======== Antenna switching ========
  */
@@ -170,7 +176,7 @@ void initAntennaSwitch()
 }
 
 /*
- * ======== rfDriverCallback ========
+ * ======== CC1352P1_LAUNCHXL_rfDriverCallback ========
  * Sets up the antenna switch depending on the current PHY configuration.
  * Truth table:
  *
@@ -183,6 +189,10 @@ void initAntennaSwitch()
  */
 void rfDriverCallback(RF_Handle client, RF_GlobalEvent events, void *arg)
 {
+    /* Local variable. */
+    bool    sub1GHz   = false;
+    uint8_t loDivider = 0;
+
     /* Switch off all paths first. Needs to be done anyway in every sub-case below. */
     PINCC26XX_setOutputValue(Board_RF_24GHZ, 0);
     PINCC26XX_setOutputValue(Board_RF_HIGH_PA, 0);
@@ -195,15 +205,36 @@ void rfDriverCallback(RF_Handle client, RF_GlobalEvent events, void *arg)
         /* Decode the generic argument as a setup command. */
         RF_RadioSetup* setupCommand = (RF_RadioSetup*)arg;
 
-        if (setupCommand->common.commandNo == CMD_PROP_RADIO_DIV_SETUP) {
+        switch (setupCommand->common.commandNo) {
+            case (CMD_RADIO_SETUP):
+            case (CMD_BLE5_RADIO_SETUP):
+                    loDivider = LODIVIDER_MASK & setupCommand->common.loDivider;
+
+                    /* Sub-1GHz front-end. */
+                    if (loDivider != 0) {
+                        sub1GHz = true;
+                    }
+                    break;
+            case (CMD_PROP_RADIO_DIV_SETUP):
+                    loDivider = LODIVIDER_MASK & setupCommand->prop_div.loDivider;
+
+                    /* Sub-1GHz front-end. */
+                    if (loDivider != 0) {
+                        sub1GHz = true;
+                    }
+                    break;
+            default:break;
+        }
+
+        if (sub1GHz) {
             /* Sub-1 GHz */
             if (paType == RF_TxPowerTable_HighPA) {
                 /* PA enable --> HIGH PA
                  * LNA enable --> Sub-1 GHz
                  */
                 PINCC26XX_setMux(antennaPins, Board_RF_24GHZ, PINCC26XX_MUX_GPIO);
-                // Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
-                //       de-asserted on CC1352 Rev A.
+                /* Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
+                         de-asserted on CC1352 Rev A. */
                 PINCC26XX_setMux(antennaPins, Board_RF_HIGH_PA, PINCC26XX_MUX_RFC_GPO3);
                 PINCC26XX_setMux(antennaPins, Board_RF_SUB1GHZ, PINCC26XX_MUX_RFC_GPO0);
             } else {
@@ -221,8 +252,8 @@ void rfDriverCallback(RF_Handle client, RF_GlobalEvent events, void *arg)
                  * LNA enable --> 2.4 GHz
                  */
                 PINCC26XX_setMux(antennaPins, Board_RF_24GHZ, PINCC26XX_MUX_RFC_GPO0);
-                // Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
-                //       de-asserted on CC1352 Rev A.
+                /* Note: RFC_GPO3 is a work-around because the RFC_GPO1 (PA enable signal) is sometimes not
+                         de-asserted on CC1352 Rev A. */
                 PINCC26XX_setMux(antennaPins, Board_RF_HIGH_PA, PINCC26XX_MUX_RFC_GPO3);
                 PINCC26XX_setMux(antennaPins, Board_RF_SUB1GHZ, PINCC26XX_MUX_GPIO);
             } else {
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p1/rf-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p1/rf-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..c18573f7afea3fd91107f33a31488e5a7785601a
--- /dev/null
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352p1/rf-conf.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup launchpad-peripherals
+ * @{
+ *
+ * \file
+ *        Header file with board-specific RF configurations.
+ * \author
+ *        Texas Instruments <e2e.ti.com>
+ * \note
+ *        This file should not be included directly
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef RF_CONF_H_
+#define RF_CONF_H_
+/*---------------------------------------------------------------------------*/
+#include "rf/rf.h"
+/*---------------------------------------------------------------------------*/
+/**
+ * \name  Board-specific front-end mode configurations for both the Sub-1 GHz
+ *        path and the 2.4 GHz path on the radio.
+ *
+ * These are the following front-end mode configurations for the
+ * CC1352P1-LAUNCHXL board:
+ *  - Sub-1 GHz: differential and external bias
+ *  - 2.4 GHz: differential and external bias
+ *
+ * @{
+ */
+#define RF_SUB_1_GHZ_CONF_FRONT_END_MODE  RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_SUB_1_GHZ_CONF_BIAS_MODE       RF_BIAS_MODE_EXTERNAL
+
+#define RF_2_4_GHZ_CONF_FRONT_END_MODE    RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_2_4_GHZ_CONF_BIAS_MODE         RF_BIAS_MODE_EXTERNAL
+/** @} */
+/*---------------------------------------------------------------------------*/
+#endif /* RF_CONF_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352r1/Board.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352r1/Board.h
index 8bf0ee00204089073c028d12a26f18a194e58167..83b27069a5d5b6038a052acacf75e76e7d5b212b 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352r1/Board.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352r1/Board.h
@@ -33,15 +33,15 @@
 #ifndef __BOARD_H
 #define __BOARD_H
 
-#define Board_CC1352R1_LAUNCHXL
-#define BOARD_STRING    "TI CC1352R1 LaunchPad"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include "CC1352R1_LAUNCHXL.h"
 
+#define Board_CC1352R1_LAUNCHXL
+#define BOARD_STRING            "TI CC1352R1 LaunchPad"
+
 #define Board_initGeneral()      CC1352R1_LAUNCHXL_initGeneral()
 #define Board_shutDownExtFlash() CC1352R1_LAUNCHXL_shutDownExtFlash()
 #define Board_wakeUpExtFlash()   CC1352R1_LAUNCHXL_wakeUpExtFlash()
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352r1/CC1352R1_LAUNCHXL.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352r1/CC1352R1_LAUNCHXL.c
index a9197a4f5f7de8072646e66f5d59361f50264e48..f3d002206e1db089110a68e3af7fd1c316026102 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352r1/CC1352R1_LAUNCHXL.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352r1/CC1352R1_LAUNCHXL.c
@@ -36,8 +36,6 @@
  *  CC1352R1_LAUNCHXL board.
  */
 
-#include "contiki.h"
-
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
@@ -609,7 +607,7 @@ const PIN_Config BoardGpioInitTable[] = {
     CC1352R1_LAUNCHXL_PIN_BTN1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,             /* Button is active low */
     CC1352R1_LAUNCHXL_PIN_BTN2 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,             /* Button is active low */
     CC1352R1_LAUNCHXL_SPI_FLASH_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN,     /* External flash chip select */
-    CC1352R1_LAUNCHXL_UART0_RX | PIN_INPUT_EN | PIN_PULLDOWN,                                                /* UART RX via debugger back channel */
+    CC1352R1_LAUNCHXL_UART0_RX | PIN_INPUT_EN | PIN_PULLUP,                                                  /* UART RX via debugger back channel */
     CC1352R1_LAUNCHXL_UART0_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,                          /* UART TX via debugger back channel */
     CC1352R1_LAUNCHXL_SPI0_MOSI | PIN_INPUT_EN | PIN_PULLDOWN,                                               /* SPI master out - slave in */
     CC1352R1_LAUNCHXL_SPI0_MISO | PIN_INPUT_EN | PIN_PULLDOWN,                                               /* SPI master in - slave out */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352r1/CC1352R1_LAUNCHXL_fxns.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352r1/CC1352R1_LAUNCHXL_fxns.c
index 520b9129767e8b35a46b970f6971b328ae65310c..79d97d7b634ab0d08c316bcb5d13f0b812c6349f 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352r1/CC1352R1_LAUNCHXL_fxns.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352r1/CC1352R1_LAUNCHXL_fxns.c
@@ -164,23 +164,61 @@ void Board_initHook()
  */
 #if defined(Board_RF_SUB1GHZ)
 
+/*
+ * Mask to be used to determine the effective value of the setup command's
+ * loDivider field.
+ */
+#define LODIVIDER_MASK   0x7F
+
 /*
  * ======== rfDriverCallback ========
- * This is an implementation for the CC1352R1 launchpad which uses a
+ * This is an implementation for the CC1352R launchpad which uses a
  * single signal for antenna switching.
  */
 void rfDriverCallback(RF_Handle client, RF_GlobalEvent events, void *arg)
 {
+    /* Decode input arguments. */
     (void)client;
     RF_RadioSetup* setupCommand = (RF_RadioSetup*)arg;
 
-    if ((events & RF_GlobalEventRadioSetup) &&
-            (setupCommand->common.commandNo == CMD_PROP_RADIO_DIV_SETUP)) {
-        /* Sub-1 GHz, requires antenna switch high */
-        PINCC26XX_setOutputValue(Board_RF_SUB1GHZ, 1);
+    /* Local variable. */
+    bool    sub1GHz   = false;
+    uint8_t loDivider = 0;
+
+    if (events & RF_GlobalEventRadioSetup) {
+        /* Decision about the frequency band shall be made based on the
+           loDivider field. */
+        switch (setupCommand->common.commandNo) {
+            case (CMD_RADIO_SETUP):
+            case (CMD_BLE5_RADIO_SETUP):
+                    loDivider = LODIVIDER_MASK & setupCommand->common.loDivider;
+
+                    /* Sub-1GHz front-end. */
+                    if (loDivider != 0) {
+                        sub1GHz = true;
+                    }
+                    break;
+            case (CMD_PROP_RADIO_DIV_SETUP):
+                    loDivider = LODIVIDER_MASK & setupCommand->prop_div.loDivider;
+
+                    /* Sub-1GHz front-end. */
+                    if (loDivider != 0) {
+                        sub1GHz = true;
+                    }
+                    break;
+            default:break;
+        }
+
+        /* Select the correct antenna. */
+        if (sub1GHz) {
+            PINCC26XX_setOutputValue(Board_RF_SUB1GHZ, 1);
+        }
+        else {
+            PINCC26XX_setOutputValue(Board_RF_SUB1GHZ, 0);
+        }
     }
     else if (events & RF_GlobalEventRadioPowerDown) {
-        /* Disable antenna switch to save current */
+        /* Set the antenna to 2.4 GHz as default. */
         PINCC26XX_setOutputValue(Board_RF_SUB1GHZ, 0);
     }
 }
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352r1/rf-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352r1/rf-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..ba652cd53b1119dd5a90159984d192cb4a391164
--- /dev/null
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc1352r1/rf-conf.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup launchpad-peripherals
+ * @{
+ *
+ * \file
+ *        Header file with board-specific RF configurations.
+ * \author
+ *        Texas Instruments <e2e.ti.com>
+ * \note
+ *        This file should not be included directly
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef RF_CONF_H_
+#define RF_CONF_H_
+/*---------------------------------------------------------------------------*/
+#include "rf/rf.h"
+/*---------------------------------------------------------------------------*/
+/**
+ * \name  Board-specific front-end mode configurations for both the Sub-1 GHz
+ *        path and the 2.4 GHz path on the radio.
+ *
+ * These are the following front-end mode configurations for the
+ * CC1352R1-LAUNCHXL board:
+ *  - Sub-1 GHz: differential and external bias
+ *  - 2.4 GHz: differential and external bias
+ *
+ * @{
+ */
+#define RF_SUB_1_GHZ_CONF_FRONT_END_MODE  RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_SUB_1_GHZ_CONF_BIAS_MODE       RF_BIAS_MODE_EXTERNAL
+
+#define RF_2_4_GHZ_CONF_FRONT_END_MODE    RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_2_4_GHZ_CONF_BIAS_MODE         RF_BIAS_MODE_EXTERNAL
+/** @} */
+/*---------------------------------------------------------------------------*/
+#endif /* RF_CONF_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc2650/Board.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc2650/Board.h
index 8f3e437f04f2b0667822fbbcb4282c8f5150a7d1..577ce04223290afc9027f9fb66d416d846f3b7ad 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc2650/Board.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc2650/Board.h
@@ -33,18 +33,18 @@
 #ifndef __BOARD_H
 #define __BOARD_H
 
-#define Board_CC2650_LAUNCHXL
-#define BOARD_STRING    "TI CC2650 LaunchPad"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include "CC2650_LAUNCHXL.h"
 
-#define Board_initGeneral()     CC2650_LAUNCHXL_initGeneral()
+#define Board_CC2650_LAUNCHXL
+#define BOARD_STRING            "TI CC2650 LaunchPad"
+
+#define Board_initGeneral()      CC2650_LAUNCHXL_initGeneral()
 #define Board_shutDownExtFlash() CC2650_LAUNCHXL_shutDownExtFlash()
-#define Board_wakeUpExtFlash() CC2650_LAUNCHXL_wakeUpExtFlash()
+#define Board_wakeUpExtFlash()   CC2650_LAUNCHXL_wakeUpExtFlash()
 
 /* These #defines allow us to reuse TI-RTOS across other device families */
 
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc2650/CC2650_LAUNCHXL.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc2650/CC2650_LAUNCHXL.c
index ed0a4796e3a1d8a3cd49d0e7b818dffa60a2bc09..02fd96471bb64aa4ad25ec5afb76d7617a5486c4 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc2650/CC2650_LAUNCHXL.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc2650/CC2650_LAUNCHXL.c
@@ -497,7 +497,7 @@ const PIN_Config BoardGpioInitTable[] = {
     CC2650_LAUNCHXL_PIN_BTN1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,          /* Button is active low */
     CC2650_LAUNCHXL_PIN_BTN2 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,          /* Button is active low */
     CC2650_LAUNCHXL_SPI_FLASH_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN,  /* External flash chip select */
-    CC2650_LAUNCHXL_UART_RX | PIN_INPUT_EN | PIN_PULLDOWN,                                              /* UART RX via debugger back channel */
+    CC2650_LAUNCHXL_UART_RX | PIN_INPUT_EN | PIN_PULLUP,                                                /* UART RX via debugger back channel */
     CC2650_LAUNCHXL_UART_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,                        /* UART TX via debugger back channel */
     CC2650_LAUNCHXL_SPI0_MOSI | PIN_INPUT_EN | PIN_PULLDOWN,                                            /* SPI master out - slave in */
     CC2650_LAUNCHXL_SPI0_MISO | PIN_INPUT_EN | PIN_PULLDOWN,                                            /* SPI master in - slave out */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc2650/rf-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc2650/rf-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..9d6abaeaca9832fb1932f569fb2c762778dcf84d
--- /dev/null
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc2650/rf-conf.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup launchpad-peripherals
+ * @{
+ *
+ * \file
+ *        Header file with board-specific RF configurations.
+ * \author
+ *        Texas Instruments <e2e.ti.com>
+ * \note
+ *        This file should not be included directly
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef RF_CONF_H_
+#define RF_CONF_H_
+/*---------------------------------------------------------------------------*/
+#include "rf/rf.h"
+/*---------------------------------------------------------------------------*/
+/**
+ * \name  Board-specific front-end mode configurations for the 2.4 GHz path
+ *        on the radio.
+ *
+ * These are the following front-end mode configurations for the
+ * CC2650-LAUNCHXL board:
+ *  - 2.4 GHz: differential and internal bias
+ *
+ * @{
+ */
+#define RF_2_4_GHZ_CONF_FRONT_END_MODE    RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_2_4_GHZ_CONF_BIAS_MODE         RF_BIAS_MODE_INTERNAL
+/** @} */
+/*---------------------------------------------------------------------------*/
+#endif /* RF_CONF_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc26x2r1/Board.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc26x2r1/Board.h
index a19145b2c48598292a8e8062f47c482282e4f771..ddf5e4946bd62f3ad93f64cbd623aef1ac4385ba 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc26x2r1/Board.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc26x2r1/Board.h
@@ -33,20 +33,18 @@
 #ifndef __BOARD_H
 #define __BOARD_H
 
-#define Board_CC26X2R1_LAUNCHXL
-#define BOARD_STRING    "TI CC26x2R1 LaunchPad"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include "CC26X2R1_LAUNCHXL.h"
 
-#define Board_initGeneral()     CC26X2R1_LAUNCHXL_initGeneral()
+#define Board_CC26X2R1_LAUNCHXL
+#define BOARD_STRING            "TI CC26x2R1 LaunchPad"
 
+#define Board_initGeneral()      CC26X2R1_LAUNCHXL_initGeneral()
 #define Board_shutDownExtFlash() CC26X2R1_LAUNCHXL_shutDownExtFlash()
-
-#define Board_wakeUpExtFlash() CC26X2R1_LAUNCHXL_wakeUpExtFlash()
+#define Board_wakeUpExtFlash()   CC26X2R1_LAUNCHXL_wakeUpExtFlash()
 
 /* These #defines allow us to reuse TI-RTOS across other device families */
 
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc26x2r1/CC26X2R1_LAUNCHXL.c b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc26x2r1/CC26X2R1_LAUNCHXL.c
index db47744de360025101917ec0d6d679606e003a78..854d1d2ba22dbbe152cfbc19678fbabe6bb2fab1 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc26x2r1/CC26X2R1_LAUNCHXL.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc26x2r1/CC26X2R1_LAUNCHXL.c
@@ -35,7 +35,6 @@
  *  This file is responsible for setting up the board specific items for the
  *  CC26X2R1_LAUNCHXL board.
  */
-#include "contiki.h"
 
 #include <stdbool.h>
 #include <stddef.h>
@@ -619,7 +618,7 @@ const PIN_Config BoardGpioInitTable[] = {
     CC26X2R1_LAUNCHXL_PIN_BTN1 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,          /* Button is active low */
     CC26X2R1_LAUNCHXL_PIN_BTN2 | PIN_INPUT_EN | PIN_PULLUP | PIN_IRQ_BOTHEDGES | PIN_HYSTERESIS,          /* Button is active low */
     CC26X2R1_LAUNCHXL_SPI_FLASH_CS | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL | PIN_DRVSTR_MIN,  /* External flash chip select */
-    CC26X2R1_LAUNCHXL_UART0_RX | PIN_INPUT_EN | PIN_PULLDOWN,                                             /* UART RX via debugger back channel */
+    CC26X2R1_LAUNCHXL_UART0_RX | PIN_INPUT_EN | PIN_PULLUP,                                               /* UART RX via debugger back channel */
     CC26X2R1_LAUNCHXL_UART0_TX | PIN_GPIO_OUTPUT_EN | PIN_GPIO_HIGH | PIN_PUSHPULL,                       /* UART TX via debugger back channel */
     CC26X2R1_LAUNCHXL_SPI0_MOSI | PIN_INPUT_EN | PIN_PULLDOWN,                                            /* SPI master out - slave in */
     CC26X2R1_LAUNCHXL_SPI0_MISO | PIN_INPUT_EN | PIN_PULLDOWN,                                            /* SPI master in - slave out */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc26x2r1/rf-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc26x2r1/rf-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..ed58c87326ceafa5ba39029c6ad3119d827b09d8
--- /dev/null
+++ b/arch/platform/simplelink/cc13xx-cc26xx/launchpad/cc26x2r1/rf-conf.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup launchpad-peripherals
+ * @{
+ *
+ * \file
+ *        Header file with board-specific RF configurations.
+ * \author
+ *        Texas Instruments <e2e.ti.com>
+ * \note
+ *        This file should not be included directly
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef RF_CONF_H_
+#define RF_CONF_H_
+/*---------------------------------------------------------------------------*/
+#include "rf/rf.h"
+/*---------------------------------------------------------------------------*/
+/**
+ * \name  Board-specific front-end mode configurations for the 2.4 GHz path
+ *        on the radio.
+ *
+ * These are the following front-end mode configurations for the
+ * CC26X2R1-LAUNCHXL board:
+ *  - 2.4 GHz: differential and internal bias
+ *
+ * @{
+ */
+#define RF_2_4_GHZ_CONF_FRONT_END_MODE    RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_2_4_GHZ_CONF_BIAS_MODE         RF_BIAS_MODE_INTERNAL
+/** @} */
+/*---------------------------------------------------------------------------*/
+#endif /* RF_CONF_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/platform.c b/arch/platform/simplelink/cc13xx-cc26xx/platform.c
index c78fe1946fdf49cca516133124299612f755915a..4b509cc5df40e8b812e1c4987efab311064e7300 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/platform.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/platform.c
@@ -48,6 +48,7 @@
 #include "dev/gpio-hal.h"
 #include "dev/serial-line.h"
 #include "dev/leds.h"
+#include "dev/watchdog.h"
 #include "net/mac/framer/frame802154.h"
 #include "lib/random.h"
 #include "lib/sensors.h"
@@ -71,6 +72,7 @@
 #include <ti/drivers/UART.h>
 /*---------------------------------------------------------------------------*/
 #include "board-peripherals.h"
+#include "clock-arch.h"
 #include "uart0-arch.h"
 #include "trng-arch.h"
 /*---------------------------------------------------------------------------*/
@@ -250,9 +252,9 @@ platform_init_stage_three(void)
   LOG_INFO("RF: Channel %d", chan);
 
   if(NETSTACK_RADIO.get_value(RADIO_PARAM_PAN_ID, &pan) == RADIO_RESULT_OK) {
-    LOG_INFO(", PANID 0x%04X", pan);
+    LOG_INFO_(", PANID 0x%04X", pan);
   }
-  LOG_INFO("\n");
+  LOG_INFO_("\n");
 
   LOG_INFO("Node ID: %d\n", node_id);
 
@@ -266,8 +268,23 @@ platform_init_stage_three(void)
 void
 platform_idle(void)
 {
-  /* Drop to some low power mode */
-  Power_idleFunc();
+  /* Clear the Watchdog before we potentially go to some low power mode */
+  watchdog_periodic();
+  /*
+   * Arm the wakeup clock. If it returns false, some timers already expired
+   * and we shouldn't go to low-power yet.
+   */
+  if(clock_arch_enter_idle()) {
+    /* Drop to some low power mode */
+    Power_idleFunc();
+    /*
+     * Clear the Watchdog immediately after wakeup, as the wakeup reason could
+     * be to clear the watchdog. See the implementation of
+     * clock_arch_set_wakeup() for why this might be the case.
+     */
+    watchdog_periodic();
+    clock_arch_exit_idle();
+  }
 }
 /*---------------------------------------------------------------------------*/
 /**
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/sensortag/board-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/sensortag/board-conf.h
index bb8689c982e6ddee232ebfd512a31d7dea6cd5c2..5ff2f78d82cb42bf8cf60816952c8ee6e4b117a4 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/sensortag/board-conf.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/sensortag/board-conf.h
@@ -50,8 +50,7 @@
 #ifndef BOARD_CONF_H_
 #define BOARD_CONF_H_
 /*---------------------------------------------------------------------------*/
-#include "contiki-conf.h"
-/*---------------------------------------------------------------------------*/
+#include "rf-conf.h"
 #include "leds-arch.h"
 /*---------------------------------------------------------------------------*/
 /**
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/sensortag/cc1350/Board.h b/arch/platform/simplelink/cc13xx-cc26xx/sensortag/cc1350/Board.h
index ecdb6d2af990a50c17f8bd865679812c17c46403..e32e74fc12dc36ce914e1be55c34464aca5fa4c7 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/sensortag/cc1350/Board.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/sensortag/cc1350/Board.h
@@ -33,15 +33,15 @@
 #ifndef __BOARD_H
 #define __BOARD_H
 
-#define Board_CC1350STK
-#define BOARD_STRING    "TI CC1350 SensorTag"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include "CC1350STK.h"
 
+#define Board_CC1350STK
+#define BOARD_STRING            "TI CC1350 SensorTag"
+
 #define Board_initGeneral()      CC1350STK_initGeneral()
 #define Board_shutDownExtFlash() CC1350STK_shutDownExtFlash()
 #define Board_wakeUpExtFlash()   CC1350STK_wakeUpExtFlash()
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/sensortag/cc1350/rf-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/sensortag/cc1350/rf-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..1f3dfbe52d49bb72daddaa0d62dc4a7cd0ae9b3b
--- /dev/null
+++ b/arch/platform/simplelink/cc13xx-cc26xx/sensortag/cc1350/rf-conf.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup launchpad-peripherals
+ * @{
+ *
+ * \file
+ *        Header file with board-specific RF configurations.
+ * \author
+ *        Texas Instruments <e2e.ti.com>
+ * \note
+ *        This file should not be included directly
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef RF_CONF_H_
+#define RF_CONF_H_
+/*---------------------------------------------------------------------------*/
+#include "rf/rf.h"
+/*---------------------------------------------------------------------------*/
+/**
+ * \name  Board-specific front-end mode configurations for both the Sub-1 GHz
+ *        path and the 2.4 GHz path on the radio.
+ *
+ * These are the following front-end mode configurations for the
+ * CC1350STK board:
+ *  - Sub-1 GHz: single-ended RFN and external bias
+ *  - 2.4 GHz: single-ended RFP and external bias
+ *
+ * @{
+ */
+#define RF_SUB_1_GHZ_CONF_FRONT_END_MODE  RF_FRONT_END_MODE_SINGLE_ENDED_RFN
+#define RF_SUB_1_GHZ_CONF_BIAS_MODE       RF_BIAS_MODE_EXTERNAL
+
+#define RF_2_4_GHZ_CONF_FRONT_END_MODE    RF_FRONT_END_MODE_SINGLE_ENDED_RFP
+#define RF_2_4_GHZ_CONF_BIAS_MODE         RF_BIAS_MODE_EXTERNAL
+/** @} */
+/*---------------------------------------------------------------------------*/
+#endif /* RF_CONF_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/sensortag/cc2650/Board.h b/arch/platform/simplelink/cc13xx-cc26xx/sensortag/cc2650/Board.h
index e334645bb5225a8787fc50b42903aef100b13ecf..8425de45426e47e432b31159cc4ddfac70fde056 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/sensortag/cc2650/Board.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/sensortag/cc2650/Board.h
@@ -33,15 +33,15 @@
 #ifndef __BOARD_H
 #define __BOARD_H
 
-#define Board_CC2650STK
-#define BOARD_STRING    "TI CC2650 SensorTag"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include "CC2650STK.h"
 
+#define Board_CC2650STK
+#define BOARD_STRING            "TI CC2650 SensorTag"
+
 #define Board_initGeneral()      CC2650STK_initGeneral()
 #define Board_shutDownExtFlash() CC2650STK_shutDownExtFlash()
 #define Board_wakeUpExtFlash()   CC2650STK_wakeUpExtFlash()
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/sensortag/cc2650/rf-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/sensortag/cc2650/rf-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..48db37a9600cdd1c7341b142468cef017521f438
--- /dev/null
+++ b/arch/platform/simplelink/cc13xx-cc26xx/sensortag/cc2650/rf-conf.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup launchpad-peripherals
+ * @{
+ *
+ * \file
+ *        Header file with board-specific RF configurations.
+ * \author
+ *        Texas Instruments <e2e.ti.com>
+ * \note
+ *        This file should not be included directly
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef RF_CONF_H_
+#define RF_CONF_H_
+/*---------------------------------------------------------------------------*/
+#include "rf/rf.h"
+/*---------------------------------------------------------------------------*/
+/**
+ * \name  Board-specific front-end mode configurations for the 2.4 GHz path
+ *        on the radio.
+ *
+ * These are the following front-end mode configurations for the
+ * CC2650STK board:
+ *  - 2.4 GHz: differential and internal bias
+ *
+ * @{
+ */
+#define RF_2_4_GHZ_CONF_FRONT_END_MODE    RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_2_4_GHZ_CONF_BIAS_MODE         RF_BIAS_MODE_INTERNAL
+/** @} */
+/*---------------------------------------------------------------------------*/
+#endif /* RF_CONF_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/sensortag/opt-3001-sensor.c b/arch/platform/simplelink/cc13xx-cc26xx/sensortag/opt-3001-sensor.c
index 885fefe88483205558c80a98e3f60d749dbaee2a..42e3976d8e3f3e39d3f4c361b9e989ef94d9c171 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/sensortag/opt-3001-sensor.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/sensortag/opt-3001-sensor.c
@@ -303,9 +303,13 @@ value(int type)
 
   result_value = SWAP16(result_value);
 
-  uint32_t e = (result_value & 0x0FFF) >> 0;
-  uint32_t m = (result_value & 0xF000) >> 12;
-  uint32_t converted = m * 100 * (1 << e);
+  /* formula for computing lux: lux = 0.01 * 2^e * m
+   * scale up by 100 to avoid floating point, then require
+   * users to scale down by same.
+   */
+  uint32_t m = (result_value & 0x0FFF) >> 0;
+  uint32_t e = (result_value & 0xF000) >> 12;
+  uint32_t converted = m * (1 << e);
 
   PRINTF("OPT: %04X            r=%d (centilux)\n", result_value,
          (int)(converted));
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/srf06/als-sensor.c b/arch/platform/simplelink/cc13xx-cc26xx/srf06/als-sensor.c
index 4f625943ba438da49b17172c403e2af9c5c16767..c633974e64eae213b9b937fd4fb82ee706881c4f 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/srf06/als-sensor.c
+++ b/arch/platform/simplelink/cc13xx-cc26xx/srf06/als-sensor.c
@@ -74,14 +74,14 @@ config(int type, int enable)
     return init();
 
   case SENSORS_ACTIVE:
-    gpio_hal_arch_pin_set_output(Board_ALS_PWR);
-    gpio_hal_arch_pin_set_input(Board_ALS_OUT);
+    PINCC26XX_setOutputEnable(Board_ALS_PWR, true);
+    PINCC26XX_setOutputEnable(Board_ALS_OUT, false);
 
     if(enable) {
-      gpio_hal_arch_set_pin(Board_ALS_PWR);
+      PINCC26XX_setOutputValue(Board_ALS_PWR, 1);
       clock_delay_usec(2000);
     } else {
-      gpio_hal_arch_clear_pin(Board_ALS_PWR);
+      PINCC26XX_setOutputValue(Board_ALS_PWR, 0);
     }
     break;
 
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/srf06/board-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/srf06/board-conf.h
index 037e7eb3fd7bd03498f08c832b56e9404682e9cd..7d6f8328f6935cc370ad06a426472738ab4c79eb 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/srf06/board-conf.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/srf06/board-conf.h
@@ -42,6 +42,8 @@
 #ifndef BOARD_CONF_H_
 #define BOARD_CONF_H_
 /*---------------------------------------------------------------------------*/
+#include "rf-conf.h"
+/*---------------------------------------------------------------------------*/
 /**
  * \name LED configurations for the dev/leds.h API.
  *
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/srf06/cc13x0/Board.h b/arch/platform/simplelink/cc13xx-cc26xx/srf06/cc13x0/Board.h
index 0941b222f69cb5476823655bd0aa95ab4f8975e1..48d232e54c6d8e52a3c804d4fbe5c7285c02f0aa 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/srf06/cc13x0/Board.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/srf06/cc13x0/Board.h
@@ -33,15 +33,15 @@
 #ifndef __BOARD_H
 #define __BOARD_H
 
-#define Board_CC1350DK_7XD
-#define BOARD_STRING    "TI SmartRF06EB + CC13x0 EM"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include "CC1350DK_7XD.h"
 
+#define Board_CC1350DK_7XD
+#define BOARD_STRING            "TI SmartRF06EB + CC13x0 EM"
+
 #define Board_initGeneral()      CC1350DK_7XD_initGeneral()
 #define Board_shutDownExtFlash() CC1350DK_7XD_shutDownExtFlash()
 #define Board_wakeUpExtFlash()   CC1350DK_7XD_wakeUpExtFlash()
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/srf06/cc13x0/rf-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/srf06/cc13x0/rf-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..327e8fb5d87410687a2ab5f7a9bf6512081e7aad
--- /dev/null
+++ b/arch/platform/simplelink/cc13xx-cc26xx/srf06/cc13x0/rf-conf.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup launchpad-peripherals
+ * @{
+ *
+ * \file
+ *        Header file with board-specific RF configurations.
+ * \author
+ *        Texas Instruments <e2e.ti.com>
+ * \note
+ *        This file should not be included directly
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef RF_CONF_H_
+#define RF_CONF_H_
+/*---------------------------------------------------------------------------*/
+#include "rf/rf.h"
+/*---------------------------------------------------------------------------*/
+/**
+ * \name  Board-specific front-end mode configurations for both the Sub-1 GHz
+ *        path and the 2.4 GHz path on the radio.
+ *
+ * These are the following front-end mode configurations for the
+ * CC1350DK-7XD board:
+ *  - Sub-1 GHz: differential and external bias
+ *  - 2.4 GHz: differential and external bias
+ *
+ * @{
+ */
+#define RF_SUB_1_GHZ_CONF_FRONT_END_MODE  RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_SUB_1_GHZ_CONF_BIAS_MODE       RF_BIAS_MODE_EXTERNAL
+
+#define RF_2_4_GHZ_CONF_FRONT_END_MODE    RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_2_4_GHZ_CONF_BIAS_MODE         RF_BIAS_MODE_EXTERNAL
+/** @} */
+/*---------------------------------------------------------------------------*/
+#endif /* RF_CONF_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ */
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/srf06/cc26x0/Board.h b/arch/platform/simplelink/cc13xx-cc26xx/srf06/cc26x0/Board.h
index c42d3a16904978d259543359c1150a41977ac8dd..d90291418346de9a8977cdb5b3d86eaca9028774 100644
--- a/arch/platform/simplelink/cc13xx-cc26xx/srf06/cc26x0/Board.h
+++ b/arch/platform/simplelink/cc13xx-cc26xx/srf06/cc26x0/Board.h
@@ -33,15 +33,15 @@
 #ifndef __BOARD_H
 #define __BOARD_H
 
-#define Board_CC2650DK_7ID
-#define BOARD_STRING    "TI SmartRF06EB + CC26x0 EM"
-
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 #include "CC2650DK_7ID.h"
 
+#define Board_CC2650DK_7ID
+#define BOARD_STRING            "TI SmartRF06EB + CC26x0 EM"
+
 #define Board_initGeneral()      CC2650DK_7ID_initGeneral()
 #define Board_shutDownExtFlash() CC2650DK_7ID_shutDownExtFlash()
 #define Board_wakeUpExtFlash()   CC2650DK_7ID_wakeUpExtFlash()
diff --git a/arch/platform/simplelink/cc13xx-cc26xx/srf06/cc26x0/rf-conf.h b/arch/platform/simplelink/cc13xx-cc26xx/srf06/cc26x0/rf-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..bdbade005980558eb7544ae22c101b528426b5e9
--- /dev/null
+++ b/arch/platform/simplelink/cc13xx-cc26xx/srf06/cc26x0/rf-conf.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018, Texas Instruments Incorporated - http://www.ti.com/
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/**
+ * \addtogroup launchpad-peripherals
+ * @{
+ *
+ * \file
+ *        Header file with board-specific RF configurations.
+ * \author
+ *        Texas Instruments <e2e.ti.com>
+ * \note
+ *        This file should not be included directly
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef RF_CONF_H_
+#define RF_CONF_H_
+/*---------------------------------------------------------------------------*/
+#include "rf/rf.h"
+/*---------------------------------------------------------------------------*/
+/**
+ * \name  Board-specific front-end mode configurations for the 2.4 GHz path
+ *        on the radio.
+ *
+ * These are the following front-end mode configurations for the
+ * CC2650DK-7ID board:
+ *  - 2.4 GHz: differential and internal bias
+ *
+ * @{
+ */
+#define RF_2_4_GHZ_CONF_FRONT_END_MODE    RF_FRONT_END_MODE_DIFFERENTIAL
+#define RF_2_4_GHZ_CONF_BIAS_MODE         RF_BIAS_MODE_INTERNAL
+/** @} */
+/*---------------------------------------------------------------------------*/
+#endif /* RF_CONF_H_ */
+/*---------------------------------------------------------------------------*/
+/**
+ * @}
+ */
diff --git a/arch/platform/sky/Makefile.common b/arch/platform/sky/Makefile.common
index 5018da3dafca30fddc71f5c34306ce895b6b4a3e..b72f92ed80dcf2f05884bde5310e53c81da6d761 100644
--- a/arch/platform/sky/Makefile.common
+++ b/arch/platform/sky/Makefile.common
@@ -18,7 +18,7 @@ endif
 CONTIKI_TARGET_SOURCEFILES += $(ARCH) $(UIPDRIVERS)
 
 MCU=msp430f1611
-include $(CONTIKI)/arch/cpu/msp430/Makefile.msp430
+include $(ARCH_PATH)/cpu/msp430/Makefile.msp430
 
 
 ifdef IAR
diff --git a/arch/platform/sky/Makefile.sky b/arch/platform/sky/Makefile.sky
index 0398486b0a024c039c18651c590083b7e186b35b..ec232408572c633d17e0f64887ac0c22871e7422 100644
--- a/arch/platform/sky/Makefile.sky
+++ b/arch/platform/sky/Makefile.sky
@@ -4,6 +4,6 @@ CONTIKI_TARGET_SOURCEFILES += contiki-sky-platform.c \
 	sht11.c sht11-sensor.c light-sensor.c battery-sensor.c \
 	button-sensor.c
 
-include $(CONTIKI)/arch/platform/sky/Makefile.common
+include $(ARCH_PATH)/platform/sky/Makefile.common
 
 MODULES += arch/dev/cc2420 arch/dev/sht11 arch/dev/ds2411 os/storage/cfs
diff --git a/arch/platform/z1/Makefile.common b/arch/platform/z1/Makefile.common
new file mode 100644
index 0000000000000000000000000000000000000000..42172022bb2d7de83e5072e14aef390d2957d743
--- /dev/null
+++ b/arch/platform/z1/Makefile.common
@@ -0,0 +1,145 @@
+
+#
+# Currently enabling SMALL breaks the build on this platform.
+# No large effect is expected anyway: unused sections are discarded even if SMALL is not set.
+#
+SMALL=0
+
+ARCH = leds.c xmem.c i2cmaster.c \
+       spi-legacy.c cc2420.c cc2420-arch.c cc2420-arch-sfd.c\
+       node-id-z1.c sensors.c button-sensor.c cfs-coffee.c \
+       uart0.c uart0-putchar.c uip-ipchksum.c \
+       slip.c slip_uart0.c z1-sensors.c adxl345.c temperature-sensor.c \
+       z1-phidgets.c light-sensor.c battery-sensor.c sky-sensors.c tmp102.c \
+       platform.c
+
+CONTIKI_TARGET_DIRS = . dev apps
+ifndef CONTIKI_TARGET_MAIN
+CONTIKI_TARGET_MAIN = contiki-main.c
+endif
+
+CONTIKI_TARGET_SOURCEFILES += $(ARCH)
+
+MCU=msp430f2617
+CPU_HAS_MSP430X=1
+
+LDFLAGS += -Wl,--defsym -Wl,__P1SEL2=0x0041 -Wl,--defsym -Wl,__P5SEL2=0x0045
+
+ifdef nodemac
+CFLAGS += -DMACID=$(nodemac)
+endif
+
+CFLAGS += -g
+
+include $(ARCH_PATH)/cpu/msp430/Makefile.msp430
+
+
+NUMPAR=20
+IHEXFILE=tmpimage.ihex
+
+ifeq ($(HOST_OS),Darwin)
+  ifndef MOTELIST
+      USBDEVPREFIX=
+      SERIALDUMP = $(CONTIKI)/tools/sky/serialdump-linux
+      MOTELIST = $(CONTIKI)/tools/zolertia/motelist-zolertia-macos
+      BSL = $(CONTIKI)/tools/zolertia/z1-bsl-nopic --z1
+      BSL_FILETYPE = -I
+      MOTES = $(shell $(MOTELIST) -b z1 -c 2>&- | \
+              cut -f 2 -d ,)
+      REFNUM = $(shell $(MOTELIST) -c 2>&- | \
+               cut -f 1 -d , | tail -c5 | sed 's/^0*//')
+      ifneq (,$(REFNUM))
+        # No device fo-und
+        ifeq (,$(findstring und, $(REFNUM)))
+          CFLAGS += -DSERIALNUM=$(REFNUM:0%=%)
+        endif
+      endif
+  endif
+else
+  # If we are not running under Mac, we assume Linux
+    ifndef MOTELIST
+      USBDEVPREFIX=
+      SERIALDUMP = $(CONTIKI)/tools/sky/serialdump-linux
+      MOTELIST = $(CONTIKI)/tools/zolertia/motelist-zolertia
+      BSL = $(CONTIKI)/tools/zolertia/z1-bsl-nopic --z1
+      BSL_FILETYPE = -I
+      MOTES = $(shell $(MOTELIST) -b z1 -c 2>&- | \
+              cut -f 2 -d , | \
+              perl -ne 'print $$1 . " " if(m-(/dev/\w+)-);')
+      CMOTES=$(MOTES)
+      REFNUM = $(shell $(MOTELIST) -c 2>&- | \
+               cut -f 1 -d , | tail -c5 | sed 's/^0*//')
+      ifneq (,$(REFNUM))
+        # No device fo-und
+        ifeq (,$(findstring und, $(REFNUM)))
+          CFLAGS += -DSERIALNUM=$(REFNUM)
+        endif
+      endif
+    endif
+endif
+
+motelist:
+	$(MOTELIST)
+z1-motelist:
+	$(MOTELIST) -b z1
+z1-motes:
+	@echo $(MOTES)
+
+ifdef MOTE
+%.upload: %.ihex
+	cp $< $(IHEXFILE)
+	$(MAKE) z1-u.$(subst /,-,$(word $(MOTE), $(MOTES)))
+else # MOTE
+%.upload: %.ihex
+	cp $< $(IHEXFILE)
+	@echo $(MOTES)
+	$(MAKE) z1-reset z1-upload
+endif # MOTE
+
+z1-upload: z1-reset
+	$(MAKE) -j $(NUMPAR) z1-upload-sequence
+
+z1-upload-sequence:	$(foreach PORT, $(MOTES), z1-u.$(subst /,-,$(PORT)))
+	@echo Done
+
+z1-reset:
+	$(MAKE) -k -j $(NUMPAR) z1-reset-sequence
+
+z1-reset-sequence:	$(foreach PORT, $(MOTES), z1-r.$(subst /,-,$(PORT)))
+	@echo Done
+
+z1-u.%:
+	@echo +++++ Erasing $(subst -,/,$*); \
+	$(BSL) -c $(subst -,/,$*) -e && sleep 2 ; \
+	echo +++++ Programming $(subst -,/,$*) ; \
+	$(BSL) -c $(subst -,/,$*) $(BSL_FILETYPE) -p $(IHEXFILE) && sleep 2 ; \
+	echo +++++ Resetting $(subst -,/,$*) ; \
+	$(BSL) -c $(subst -,/,$*) -r
+
+z1-r.%:
+	$(BSL) -c $(subst -,/,$*) -r
+
+sizeplot:
+	msp430-size $(OBJECTDIR)/*.o | $(CONTIKI)/tools/sky/check-size > size-data
+	gnuplot $(CONTIKI)/tools/sky/plot-size
+	gv size.pdf
+
+winslip:
+ifdef INTERFACE
+	$(CONTIKI)/tools/wpcapslip/wpcapslip -s $(USBDEVPREFIX)$(firstword $(CMOTES)) $(INTERFACE) 172.16.0.0 255.255.0.0
+else
+	@echo "Usage: \"$(MAKE) $@ INTERFACE=<the IP address of a local network interface>\""
+	@echo "Use the \"ipconfig\" command to find out the IP addresses of the local interfaces"
+endif
+
+linslip: $(CONTIKI)/tools/tunslip
+	$(CONTIKI)/tools/tunslip -s $(USBDEVPREFIX)$(firstword $(CMOTES)) 172.16.0.0 255.255.0.0
+
+$(CONTIKI)/tools/tunslip:
+	(cd $(CONTIKI)/tools; $(MAKE) tunslip)
+
+ifdef MOTE
+  PORT = $(USBDEVPREFIX)$(word $(MOTE), $(CMOTES))
+else
+  PORT = $(USBDEVPREFIX)$(firstword $(CMOTES))
+endif
diff --git a/arch/platform/z1/Makefile.z1 b/arch/platform/z1/Makefile.z1
new file mode 100644
index 0000000000000000000000000000000000000000..aeff61bf2e3a22052834c006fa4b7dd52c56c767
--- /dev/null
+++ b/arch/platform/z1/Makefile.z1
@@ -0,0 +1,11 @@
+# Common Makefile between Z1 and Z1SP
+
+CONTIKI_TARGET_SOURCEFILES += contiki-z1-platform.c 
+
+include $(ARCH_PATH)/platform/z1/Makefile.common
+
+ifeq ($(ZOLERTIA_Z1SP),1)
+include $(ARCH_PATH)/platform/z1/Makefile.z1sp
+endif
+
+MODULES += arch/dev/cc2420 os/storage/cfs
diff --git a/arch/platform/z1/Makefile.z1sp b/arch/platform/z1/Makefile.z1sp
new file mode 100644
index 0000000000000000000000000000000000000000..29b8fcbd1b87f5506c0a1caa529683a6adfad847
--- /dev/null
+++ b/arch/platform/z1/Makefile.z1sp
@@ -0,0 +1,6 @@
+# Makefile for Z1 Starter Platform
+
+# This is the actual flag we need to include specific Z1SP components
+CFLAGS += -DZ1_IS_Z1SP
+
+CONTIKI_TARGET_SOURCEFILES += potentiometer-sensor.c
diff --git a/arch/platform/z1/README.z1sp b/arch/platform/z1/README.z1sp
new file mode 100644
index 0000000000000000000000000000000000000000..8db1e48da2153983eedf53c1411718e6dce2a031
--- /dev/null
+++ b/arch/platform/z1/README.z1sp
@@ -0,0 +1,9 @@
+Using the Z1 starter platform (Z1SP)
+============================================
+
+To enable the Z1SP components, you should include in your application Makefile
+the ZOLERTIA_Z1SP flag set to 1, see "examples/z1/Makefile".
+
+For Z1SP specific information please go to:
+
+http://zolertia.sourceforge.net/wiki/index.php/Mainpage:z1sp
diff --git a/arch/platform/z1/apps/burn-nodeid.c b/arch/platform/z1/apps/burn-nodeid.c
new file mode 100644
index 0000000000000000000000000000000000000000..0f469cac41456bdbe9ee61521d34af182c879e45
--- /dev/null
+++ b/arch/platform/z1/apps/burn-nodeid.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2006, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *         A program for burning a node ID into the flash ROM of a Tmote Sky node.
+ * \author
+ *         Adam Dunkels <adam@sics.se>
+ */
+
+#include "dev/leds.h"
+#include "dev/watchdog.h"
+#include "sys/node-id.h"
+#include "contiki.h"
+#include "sys/etimer.h"
+
+#include "node-id-z1.h"
+
+#include <stdio.h>
+
+static struct etimer etimer;
+
+PROCESS(burn_process, "Burn node id");
+AUTOSTART_PROCESSES(&burn_process);
+/*---------------------------------------------------------------------------*/
+PROCESS_THREAD(burn_process, ev, data)
+{
+  PROCESS_BEGIN();
+
+  etimer_set(&etimer, 5*CLOCK_SECOND);
+  PROCESS_WAIT_UNTIL(etimer_expired(&etimer));
+
+  watchdog_stop();
+  leds_on(LEDS_RED);
+#if NODEID
+  #warning "***** BURNING NODE ID"
+  printf("Burning node id %d\n", NODEID);
+  node_id_burn(NODEID);
+  leds_on(LEDS_BLUE);
+  node_id_restore();
+  printf("Restored node id %d\n", node_id);
+#else
+#error "burn-nodeid must be compiled with nodeid=<the ID of the node>"
+  node_id_restore();
+  printf("Restored node id %d\n", node_id);
+#endif
+  leds_off(LEDS_RED + LEDS_BLUE);
+  watchdog_start();
+  while(1) {
+    PROCESS_WAIT_EVENT();
+  }
+  PROCESS_END();
+}
+/*---------------------------------------------------------------------------*/
diff --git a/arch/platform/z1/cfs-coffee-arch.h b/arch/platform/z1/cfs-coffee-arch.h
new file mode 100644
index 0000000000000000000000000000000000000000..3225e2f321267665c1f517a7ee4ba293e5ab8e14
--- /dev/null
+++ b/arch/platform/z1/cfs-coffee-arch.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2008, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *	Coffee architecture-dependent header for the Zolertia Z1 platform.
+ * \author
+ * 	Nicolas Tsiftes <nvt@sics.se>
+ *      Enric M. Calvo <ecalvo@zolertia.com>
+ */
+
+#ifndef CFS_COFFEE_ARCH_H
+#define CFS_COFFEE_ARCH_H
+
+#include "contiki-conf.h"
+#include "dev/xmem.h"
+
+/*** M25P16 Memory Organization
+The memory is organized as: 
+16Mbit = 2 097 152 bytes (8 bits each) 
+32 sectors (512 Kbits, 65536 bytes each) 
+8192 pages (256 bytes each). 
+Each page can be individually programmed (bits are programmed from 1 to 0). The device is 
+sector or bulk erasable (bits are erased from 0 to 1) but not page erasable
+*/
+
+/* Total size of the External Flash Memory in the Z1 */
+#define COFFEE_XMEM_TOTAL_SIZE_KB       2048UL  
+
+/* Coffee configuration parameters. */
+#define COFFEE_SECTOR_SIZE		65536UL  
+#define COFFEE_PAGE_SIZE		256UL
+#define COFFEE_START			COFFEE_SECTOR_SIZE
+#define COFFEE_SIZE			(COFFEE_XMEM_TOTAL_SIZE_KB * 1024UL - COFFEE_START)
+#define COFFEE_NAME_LENGTH		16
+#define COFFEE_MAX_OPEN_FILES		6
+#define COFFEE_FD_SET_SIZE		8
+#define COFFEE_LOG_TABLE_LIMIT		256
+#define COFFEE_DYN_SIZE			4*1024
+#define COFFEE_LOG_SIZE			1024
+
+#define COFFEE_MICRO_LOGS		1
+
+/* Flash operations. */
+#define COFFEE_WRITE(buf, size, offset)				\
+		xmem_pwrite((char *)(buf), (size), COFFEE_START + (offset))
+
+#define COFFEE_READ(buf, size, offset)				\
+  		xmem_pread((char *)(buf), (size), COFFEE_START + (offset))
+
+#define COFFEE_ERASE(sector)					\
+  		xmem_erase(COFFEE_SECTOR_SIZE, COFFEE_START + (sector) * COFFEE_SECTOR_SIZE)
+
+/* Coffee types. */
+typedef int16_t coffee_page_t;
+
+#endif /* !CFS_COFFEE_ARCH_H */
diff --git a/arch/platform/z1/contiki-conf.h b/arch/platform/z1/contiki-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..e31a9fbcdc5cc1e4b1522edb3e3fccf37dfdc1ae
--- /dev/null
+++ b/arch/platform/z1/contiki-conf.h
@@ -0,0 +1,72 @@
+#ifndef CONTIKI_CONF_H
+#define CONTIKI_CONF_H
+
+/* include the project config */
+#ifdef PROJECT_CONF_PATH
+#include PROJECT_CONF_PATH
+#endif /* PROJECT_CONF_PATH */
+/*---------------------------------------------------------------------------*/
+#include "z1-def.h"
+#include "msp430-def.h"
+/*---------------------------------------------------------------------------*/
+
+/* Configure radio driver */
+#ifndef NETSTACK_CONF_RADIO
+#define NETSTACK_CONF_RADIO   cc2420_driver
+#endif /* NETSTACK_CONF_RADIO */
+
+/* Symbol for the TSCH 15ms timeslot timing template */
+#define TSCH_CONF_ARCH_HDR_PATH "dev/cc2420/cc2420-tsch-15ms.h"
+
+/* The TSCH default slot length of 10ms is a bit too short for this platform,
+ * use 15ms instead. */
+#ifndef TSCH_CONF_DEFAULT_TIMESLOT_TIMING
+#define TSCH_CONF_DEFAULT_TIMESLOT_TIMING tsch_timeslot_timing_us_15000
+#endif /* TSCH_CONF_DEFAULT_TIMESLOT_TIMING */
+
+/* Save RAM through a smaller uIP buffer */
+#ifndef UIP_CONF_BUFFER_SIZE
+#define UIP_CONF_BUFFER_SIZE		140
+#endif
+
+#define PROCESS_CONF_NUMEVENTS       8
+#define PROCESS_CONF_STATS           1
+/*#define PROCESS_CONF_FASTPOLL      4*/
+
+/* So far, printfs without interrupt. */
+#define UART0_CONF_TX_WITH_INTERRUPT 0
+/* This does not work in Cooja. */
+#define UART0_CONF_RX_WITH_DMA       0
+
+/* Handle 10 neighbors */
+#ifndef NBR_TABLE_CONF_MAX_NEIGHBORS
+#define NBR_TABLE_CONF_MAX_NEIGHBORS    10
+#endif
+
+/* Handle 10 routes    */
+#ifndef NETSTACK_MAX_ROUTE_ENTRIES
+#define NETSTACK_MAX_ROUTE_ENTRIES      10
+#endif
+
+/* Handle 10 links    */
+#ifndef TSCH_SCHEDULE_CONF_MAX_LINKS
+#define TSCH_SCHEDULE_CONF_MAX_LINKS    10
+#endif
+
+#ifndef TSCH_CONF_MAX_INCOMING_PACKETS
+#define TSCH_CONF_MAX_INCOMING_PACKETS    2
+#endif
+
+#ifndef TSCH_QUEUE_CONF_NUM_PER_NEIGHBOR
+#define TSCH_QUEUE_CONF_NUM_PER_NEIGHBOR  4
+#endif
+
+/* Platform-specific (H/W) AES implementation */
+#ifndef AES_128_CONF
+#define AES_128_CONF cc2420_aes_128_driver
+#endif /* AES_128_CONF */
+
+/*---------------------------------------------------------------------------*/
+#include "msp430-conf.h"
+/*---------------------------------------------------------------------------*/
+#endif /* CONTIKI_CONF_H */
diff --git a/arch/platform/z1/contiki-z1-platform.c b/arch/platform/z1/contiki-z1-platform.c
new file mode 100644
index 0000000000000000000000000000000000000000..60272bb003a4b5183c91586e094b3f10528b896a
--- /dev/null
+++ b/arch/platform/z1/contiki-z1-platform.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011, Zolertia(TM) is a trademark of Advancare,SL
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ *
+ *
+ * Author: Enric M. Calvo <ecalvo@zolertia.com> based on previous work by
+ *         Niclas Finne <nfi@sics.se>, Joakim Eriksson <joakime@sics.se>
+ *
+ */
+
+#include "dev/button-sensor.h"
+
+void
+init_platform(void)
+{
+  process_start(&sensors_process, NULL);
+}
diff --git a/arch/platform/z1/dev/adxl345.c b/arch/platform/z1/dev/adxl345.c
new file mode 100644
index 0000000000000000000000000000000000000000..08e1704324690d4757d1b98630d05aaf4b3ae37b
--- /dev/null
+++ b/arch/platform/z1/dev/adxl345.c
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 2010, Swedish Institute of Computer Science.
+ * Copyright (c) 2016, Zolertia <http://www.zolertia.com>
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+/*---------------------------------------------------------------------------*/
+/**
+ * \file
+ *         Device drivers for adxl345 accelerometer in Zolertia Z1.
+ * \author
+ *         Marcus Lundén, SICS <mlunden@sics.se>
+ *         Enric M. Calvo, Zolertia <ecalvo@zolertia.com>
+ *         Antonio Lignan, Zolertia <alinan@zolertia.com>
+ */
+/*---------------------------------------------------------------------------*/
+#include <stdio.h>
+#include "contiki.h"
+#include "adxl345.h"
+#include "cc2420.h"
+#include "i2cmaster.h"
+#include "isr_compat.h"
+#include "lib/sensors.h"
+/*---------------------------------------------------------------------------*/
+#define DEBUG 0
+#if DEBUG
+#define PRINTF(...) printf(__VA_ARGS__)
+#else
+#define PRINTF(...)
+#endif
+/*---------------------------------------------------------------------------*/
+static uint8_t enabled;
+/*---------------------------------------------------------------------------*/
+/* Callback pointers when interrupt occurs */
+void (*accm_int1_cb)(uint8_t reg);
+void (*accm_int2_cb)(uint8_t reg);
+/*---------------------------------------------------------------------------*/
+/* Bitmasks for the interrupts */
+static uint16_t int1_mask = 0, int2_mask = 0;
+
+/* Default values for adxl345 at startup.
+ * This will be sent to the adxl345 in a
+ * stream at init to set it up in a default state
+ */
+
+static uint8_t adxl345_default_settings[] = {
+  /* Note, as the two first two bulks are to be written in a stream, they contain
+   * the register address as first byte in that section.
+   * 0--14 are in one stream, start at ADXL345_THRESH_TAP
+   */
+  /* XXX NB Register address, not register value!! */
+  ADXL345_THRESH_TAP,
+  ADXL345_THRESH_TAP_DEFAULT,
+  ADXL345_OFSX_DEFAULT,
+  ADXL345_OFSY_DEFAULT,
+  ADXL345_OFSZ_DEFAULT,
+  ADXL345_DUR_DEFAULT,
+  ADXL345_LATENT_DEFAULT,
+  ADXL345_WINDOW_DEFAULT,
+  ADXL345_THRESH_ACT_DEFAULT,
+  ADXL345_THRESH_INACT_DEFAULT,
+  ADXL345_TIME_INACT_DEFAULT,
+  ADXL345_ACT_INACT_CTL_DEFAULT,
+  ADXL345_THRESH_FF_DEFAULT,
+  ADXL345_TIME_FF_DEFAULT,
+  ADXL345_TAP_AXES_DEFAULT,
+
+  /* 15--19 start at ADXL345_BW_RATE */
+  /* XXX NB Register address, not register value!! */
+  ADXL345_BW_RATE,    
+  ADXL345_BW_RATE_DEFAULT,
+  ADXL345_POWER_CTL_DEFAULT,
+  ADXL345_INT_ENABLE_DEFAULT,
+  ADXL345_INT_MAP_DEFAULT,
+
+  /* These two: 20, 21 write separately */
+  ADXL345_DATA_FORMAT_DEFAULT,
+  ADXL345_FIFO_CTL_DEFAULT
+};
+/*---------------------------------------------------------------------------*/
+PROCESS(accmeter_process, "Accelerometer process");
+/*---------------------------------------------------------------------------*/
+static void
+accm_write_reg(uint8_t reg, uint8_t val)
+{
+  uint8_t tx_buf[] = {reg, val};
+
+  i2c_transmitinit(ADXL345_ADDR);
+  while (i2c_busy());
+  PRINTF("ADXL345: I2C Ready to TX\n");
+
+  i2c_transmit_n(2, tx_buf);
+  while (i2c_busy());
+  PRINTF("ADXL345: WRITE_REG 0x%02X @ reg 0x%02X\n", val, reg);
+}
+/*---------------------------------------------------------------------------*/
+/* First byte in stream must be the register address to begin writing to.
+ * The data is then written from second byte and increasing.
+ */
+static void
+accm_write_stream(uint8_t len, uint8_t *data)
+{
+  i2c_transmitinit(ADXL345_ADDR);
+  while (i2c_busy());
+  PRINTF("ADXL345: I2C Ready to TX(stream)\n");
+
+  i2c_transmit_n(len, data);	// start tx and send conf reg 
+  while (i2c_busy());
+  PRINTF("ADXL345: WRITE_STR %u B to 0x%02X\n", len, data[0]);
+}
+
+/*---------------------------------------------------------------------------*/
+static uint8_t
+accm_read_reg(uint8_t reg)
+{
+  uint8_t retVal = 0;
+  uint8_t rtx = reg;
+  PRINTF("ADXL345: READ_REG 0x%02X\n", reg);
+
+  /* transmit the register to read */
+  i2c_transmitinit(ADXL345_ADDR);
+  while (i2c_busy());
+  i2c_transmit_n(1, &rtx);
+  while (i2c_busy());
+
+  /* receive the data */
+  i2c_receiveinit(ADXL345_ADDR);
+  while (i2c_busy());
+  i2c_receive_n(1, &retVal);
+  while (i2c_busy());
+
+  return retVal;
+}
+/*---------------------------------------------------------------------------*/
+static void
+accm_read_stream(uint8_t reg, uint8_t len, uint8_t *whereto)
+{
+  uint8_t rtx = reg;
+  PRINTF("ADXL345: READ_STR %u B from 0x%02X\n", len, reg);
+
+  /* transmit the register to start reading from */
+  i2c_transmitinit(ADXL345_ADDR);
+  while (i2c_busy());
+  i2c_transmit_n(1, &rtx);
+  while (i2c_busy());
+
+  /* receive the data */
+  i2c_receiveinit(ADXL345_ADDR);
+  while (i2c_busy());
+  i2c_receive_n(len, whereto);
+  while (i2c_busy());
+}
+
+/*---------------------------------------------------------------------------*/
+/* Read an axis of the accelerometer (x, y or z). Return value is a signed
+ * 10 bit int.
+ * The resolution of the acceleration measurement can be increased up to 13 bit,
+ * but will change the data format of this read out. Refer to the data sheet if
+ * so is wanted/needed.
+ */
+int16_t
+accm_read_axis(enum ADXL345_AXIS axis)
+{
+  int16_t rd = 0;
+  uint8_t tmp[2];
+  if(axis > Z_AXIS){
+    return 0;
+  }
+  accm_read_stream(ADXL345_DATAX0 + axis, 2, &tmp[0]);
+  rd = (int16_t)(tmp[0] | (tmp[1]<<8));  
+  return rd;
+}
+/*---------------------------------------------------------------------------*/
+int
+accm_set_grange(uint8_t grange)
+{
+  uint8_t tempreg = 0;
+
+  if(grange > ADXL345_RANGE_16G) {
+    PRINTF("ADXL345: grange invalid: %u\n", grange);
+    return ADXL345_ERROR;
+  }
+
+  if(!enabled) {
+    return ADXL345_ERROR;
+  }
+
+  /* Keep the previous contents of the register, zero out the last two bits */
+  tempreg = (accm_read_reg(ADXL345_DATA_FORMAT) & 0xFC);
+  tempreg |= grange;
+  accm_write_reg(ADXL345_DATA_FORMAT, tempreg);
+  return ADXL345_SUCCESS;
+}
+
+/*---------------------------------------------------------------------------*/
+void
+accm_init(void)
+{
+  PRINTF("ADXL345: init\n");
+  accm_int1_cb = NULL;
+  accm_int2_cb = NULL;
+
+  /* Set up ports and pins for interrups. */
+  ADXL345_DIR  &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN);
+  ADXL345_SEL  &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN);
+  ADXL345_SEL2 &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN);
+
+  /* Set up ports and pins for I2C communication */
+  i2c_enable();
+
+  /* set default register values. */
+  accm_write_stream(15, &adxl345_default_settings[0]);
+  accm_write_stream(5, &adxl345_default_settings[15]);
+  accm_write_reg(ADXL345_DATA_FORMAT, adxl345_default_settings[20]);
+  accm_write_reg(ADXL345_FIFO_CTL, adxl345_default_settings[21]);
+
+  process_start(&accmeter_process, NULL);
+
+  /* Enable msp430 interrupts on the two interrupt pins. */
+  dint();
+  /* low to high transition interrupts */
+  ADXL345_IES &=~ (ADXL345_INT1_PIN | ADXL345_INT2_PIN);
+  /* enable interrupts */
+  ADXL345_IE |= (ADXL345_INT1_PIN | ADXL345_INT2_PIN);
+  eint();
+
+  enabled = 1;
+}
+/*---------------------------------------------------------------------------*/
+void
+accm_stop(void)
+{
+  dint();
+  ADXL345_IE &= ~(ADXL345_INT1_PIN | ADXL345_INT2_PIN);
+  accm_write_reg(ADXL345_INT_ENABLE, ~(int1_mask | int2_mask));
+  accm_write_reg(ADXL345_INT_MAP, ~int2_mask);
+  eint();
+  enabled = 0;
+}
+/*---------------------------------------------------------------------------*/
+int
+accm_set_irq(uint8_t int1, uint8_t int2)
+{
+  if(!enabled) {
+    return ADXL345_ERROR;
+  }
+
+  /* Set the corresponding interrupt mapping to INT1 or INT2 */
+  PRINTF("ADXL345: IRQs set to INT1: 0x%02X IRQ2: 0x%02X\n", int1, int2);
+
+  int1_mask = int1;
+  int2_mask = int2;
+
+  accm_write_reg(ADXL345_INT_ENABLE, (int1 | int2));
+  /* int1 bits are zeroes in the map register so this is for both ints */
+  accm_write_reg(ADXL345_INT_MAP, int2);
+  return ADXL345_SUCCESS;
+}
+/*---------------------------------------------------------------------------*/
+/* Invoked after an interrupt happened. Reads the interrupt source reg at the
+ * accelerometer, which resets the interrupts, and invokes the corresponding
+ * callback. It passes the source register value so the callback can determine
+ * what interrupt happened, if several interrupts are mapped to the same pin.
+ */
+static void
+poll_handler(void)
+{
+  uint8_t ireg = 0;
+  ireg = accm_read_reg(ADXL345_INT_SOURCE);
+
+  /* Invoke callbacks for the corresponding interrupts */
+  if(ireg & int1_mask){
+    if(accm_int1_cb != NULL){
+      PRINTF("ADXL345: INT1 cb invoked\n");
+      accm_int1_cb(ireg);
+    }
+  } else if(ireg & int2_mask){
+    if(accm_int2_cb != NULL){
+      PRINTF("ADXL345: INT2 cb invoked\n");
+      accm_int2_cb(ireg);
+    }
+  }
+}
+/*---------------------------------------------------------------------------*/
+/* This process is sleeping until an interrupt from the accelerometer occurs,
+ * which polls this process from the interrupt service routine. */
+PROCESS_THREAD(accmeter_process, ev, data)
+{
+  PROCESS_POLLHANDLER(poll_handler());
+  PROCESS_EXITHANDLER();
+  PROCESS_BEGIN();
+  while(1){
+    PROCESS_WAIT_EVENT_UNTIL(0);
+  }
+  PROCESS_END();
+}
+/*---------------------------------------------------------------------------*/
+/* This interrupt vector is shared with the interrupts from CC2420, so that
+ * was moved here
+ */
+static struct timer suppressTimer1, suppressTimer2;
+
+ISR(PORT1, port1_isr)
+{
+  /* ADXL345_IFG.x goes high when interrupt occurs, use to check what
+   * interrupted
+   */
+  if((ADXL345_IFG & ADXL345_INT1_PIN) && !(ADXL345_IFG & BV(CC2420_FIFOP_PIN))){
+    /* Check if this should be suppressed or not */
+    if(timer_expired(&suppressTimer1)) {
+      timer_set(&suppressTimer1, SUPPRESS_TIME_INT1);
+      ADXL345_IFG &= ~ADXL345_INT1_PIN;   // clear interrupt flag
+      process_poll(&accmeter_process);
+      LPM4_EXIT;
+    }
+  } else if((ADXL345_IFG & ADXL345_INT2_PIN) &&
+           !(ADXL345_IFG & BV(CC2420_FIFOP_PIN))){
+    /* Check if this should be suppressed or not */
+    if(timer_expired(&suppressTimer2)) {
+      timer_set(&suppressTimer2, SUPPRESS_TIME_INT2);
+      /* clear interrupt flag */
+      ADXL345_IFG &= ~ADXL345_INT2_PIN;
+      process_poll(&accmeter_process);
+      LPM4_EXIT;
+    }
+  } else {
+    /* CC2420 interrupt */
+    if(cc2420_interrupt()) {
+      LPM4_EXIT;
+    }
+  }
+}
+/*---------------------------------------------------------------------------*/
+static int
+configure(int type, int value)
+{
+  if(type != SENSORS_ACTIVE) {
+    return ADXL345_ERROR;
+  }
+
+  if(value) {
+    accm_init();
+  } else {
+    accm_stop();
+  }
+  enabled = value;
+  return ADXL345_SUCCESS;
+}
+/*---------------------------------------------------------------------------*/
+static int
+status(int type)
+{
+  switch(type) {
+  case SENSORS_ACTIVE:
+  case SENSORS_READY:
+    return enabled;
+  }
+  return ADXL345_SUCCESS;
+}
+/*---------------------------------------------------------------------------*/
+static int
+value(int type)
+{
+  if(!enabled) {
+    return ADXL345_ERROR;
+  }
+
+  if((type != X_AXIS) && (type != Y_AXIS) && (type != Z_AXIS)) {
+    return ADXL345_ERROR;
+  }
+
+  switch(type) {
+    case X_AXIS:
+      return accm_read_axis(X_AXIS);
+    case Y_AXIS:
+      return accm_read_axis(Y_AXIS);
+    case Z_AXIS:
+      return accm_read_axis(Z_AXIS);
+    default:
+      return ADXL345_ERROR;
+  }
+}
+/*---------------------------------------------------------------------------*/
+SENSORS_SENSOR(adxl345, ADXL345_SENSOR, value, configure, status);
+/*---------------------------------------------------------------------------*/
diff --git a/arch/platform/z1/dev/adxl345.h b/arch/platform/z1/dev/adxl345.h
new file mode 100644
index 0000000000000000000000000000000000000000..a8d4789d8ae57950d4decd0eb043bdce00d5f30a
--- /dev/null
+++ b/arch/platform/z1/dev/adxl345.h
@@ -0,0 +1,246 @@
+/*
+ * Copyright (c) 2010, Swedish Institute of Computer Science.
+ * Copyright (c) 2016, Zolertia <http://www.zolertia.com>
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+/*---------------------------------------------------------------------------*/
+/**
+ * \file
+ *         Device drivers header file for adxl345 accelerometer in Zolertia Z1.
+ * \author
+ *         Marcus Lundén, SICS <mlunden@sics.se>
+ *         Enric Calvo, Zolertia <ecalvo@zolertia.com>
+ *         Antonio Lignan, Zolertia <alinan@zolertia.com>
+ */
+/*---------------------------------------------------------------------------*/
+#ifndef ADXL345_H_
+#define ADXL345_H_
+#include <stdio.h>
+#include "dev/i2cmaster.h"
+#include "lib/sensors.h"
+/*---------------------------------------------------------------------------*/
+/* Used in accm_read_axis(), eg accm_read_axis(X_AXIS) */
+enum ADXL345_AXIS {
+  X_AXIS = 0,
+  Y_AXIS = 2,
+  Z_AXIS = 4,
+};
+/* -------------------------------------------------------------------------- */
+/* Init the accelerometer: ports, pins, registers, interrupts (none enabled),
+ * I2C, default threshold values etc.
+ */
+void accm_init(void);
+
+/* Read an axis of the accelerometer (x, y or z). Return value is a signed 10
+ * bit int.
+ * The resolution of the acceleration measurement can be increased up to 13 bit,
+ * but will change the data format of this read out. Refer to the data sheet if
+ * so is wanted/needed.
+ */
+int16_t accm_read_axis(enum ADXL345_AXIS axis);
+
+/* Sets the g-range, ie the range the accelerometer measures (ie 2g means -2 to
+ * +2 g on every axis). Possible values:
+ * - ADXL345_RANGE_2G
+ * - ADXL345_RANGE_4G
+ * - ADXL345_RANGE_8G
+ * - ADXL345_RANGE_16G
+ */
+int accm_set_grange(uint8_t grange);
+
+/* Map interrupt (FF, tap, dbltap etc) to interrupt pin (IRQ_INT1, IRQ_INT2).
+ * This must come after accm_init() as the registers will otherwise be
+ * overwritten.
+ */
+int accm_set_irq(uint8_t int1, uint8_t int2);
+
+/* Macros for setting the pointers to callback functions from the interrupts.
+ * The function will be called with an uint8_t as parameter, containing the
+ * interrupt flag register from the ADXL345. That way, several interrupts can be
+ * mapped to the same pin and be read
+ */
+#define ACCM_REGISTER_INT1_CB(ptr)   accm_int1_cb = ptr;
+#define ACCM_REGISTER_INT2_CB(ptr)   accm_int2_cb = ptr;
+/* -------------------------------------------------------------------------- */
+/* Application definitions, change if required by application. */
+
+/* Time after an interrupt that subsequent interrupts are suppressed. Should
+ * later be turned into one specific time per type of interrupt (tap, freefall.
+ * etc)
+ */
+#define SUPPRESS_TIME_INT1    CLOCK_SECOND/4
+#define SUPPRESS_TIME_INT2    CLOCK_SECOND/4
+
+/* Suggested defaults according to the data sheet etc */
+#define ADXL345_THRESH_TAP_DEFAULT      0x48  /* 4.5g (0x30 == 3.0g) */
+#define ADXL345_OFSX_DEFAULT            0x00  /* for calibration only */
+#define ADXL345_OFSY_DEFAULT            0x00
+#define ADXL345_OFSZ_DEFAULT            0x00
+#define ADXL345_DUR_DEFAULT             0x20  /* 20 ms (datasheet: 10ms++) */
+#define ADXL345_LATENT_DEFAULT          0x50  /* 100 ms (datasheet: 20ms++) */
+#define ADXL345_WINDOW_DEFAULT          0xFF  /* 320 ms (datasheet: 80ms++) */
+#define ADXL345_THRESH_ACT_DEFAULT      0x15  /* 1.3g (62.5 mg/LSB) */
+#define ADXL345_THRESH_INACT_DEFAULT    0x08  /* 0.5g (62.5 mg/LSB) */
+#define ADXL345_TIME_INACT_DEFAULT      0x02  /* 2 s (1 s/LSB) */
+#define ADXL345_ACT_INACT_CTL_DEFAULT   0xFF  /* all axis, ac-coupled */
+#define ADXL345_THRESH_FF_DEFAULT       0x09  /* 563 mg */
+#define ADXL345_TIME_FF_DEFAULT         0x20  /* 60 ms */
+#define ADXL345_TAP_AXES_DEFAULT        0x07  /* all axis, no suppression */
+
+#define ADXL345_BW_RATE_DEFAULT         (0x00 | ADXL345_SRATE_100) /* 100 Hz */
+/* link bit set, no autosleep, start normal measuring */
+#define ADXL345_POWER_CTL_DEFAULT       0x28
+#define ADXL345_INT_ENABLE_DEFAULT      0x00    /* no interrupts enabled */
+#define ADXL345_INT_MAP_DEFAULT         0x00    /* all mapped to int_1 */
+
+/* XXX NB: In the data format register, data format of axis readings is chosen
+ * between left or right justify. This affects the position of the MSB/LSB and is
+ * different depending on g-range and resolution. If changed, make sure this is
+ * reflected in the _read_axis() function. Also, the resolution can be increased
+ * from 10 bit to at most 13 bit, but this also changes position of MSB etc on data
+ * format so check this in read_axis() too.
+ */
+/* right-justify, 2g, 10-bit mode, int is active high */
+#define ADXL345_DATA_FORMAT_DEFAULT     (0x00 | ADXL345_RANGE_2G)
+#define ADXL345_FIFO_CTL_DEFAULT        0x00    /* FIFO bypass mode */
+
+/* -------------------------------------------------------------------------- */
+/* Reference definitions, should not be changed */
+/* adxl345 slave address */
+#define ADXL345_ADDR            0x53
+
+/* ADXL345 registers */
+#define ADXL345_DEVID           0x00
+/* registers 0x01 to 0x1C are reserved, do not access */
+#define ADXL345_THRESH_TAP      0x1D
+#define ADXL345_OFSX            0x1E
+#define ADXL345_OFSY            0x1F
+#define ADXL345_OFSZ            0x20
+#define ADXL345_DUR             0x21
+#define ADXL345_LATENT          0x22
+#define ADXL345_WINDOW          0x23
+#define ADXL345_THRESH_ACT      0x24
+#define ADXL345_THRESH_INACT    0x25
+#define ADXL345_TIME_INACT      0x26
+#define ADXL345_ACT_INACT_CTL   0x27
+#define ADXL345_THRESH_FF       0x28
+#define ADXL345_TIME_FF         0x29
+#define ADXL345_TAP_AXES        0x2A
+#define ADXL345_ACT_TAP_STATUS  0x2B
+#define ADXL345_BW_RATE         0x2C
+#define ADXL345_POWER_CTL       0x2D
+#define ADXL345_INT_ENABLE      0x2E
+#define ADXL345_INT_MAP         0x2F
+#define ADXL345_INT_SOURCE      0x30
+#define ADXL345_DATA_FORMAT     0x31
+#define ADXL345_DATAX0          0x32  /* read only, LSByte X, two's complement */
+#define ADXL345_DATAX1          0x33  /* read only, MSByte X */
+#define ADXL345_DATAY0          0x34  /* read only, LSByte Y */
+#define ADXL345_DATAY1          0x35  /* read only, MSByte X */
+#define ADXL345_DATAZ0          0x36  /* read only, LSByte Z */
+#define ADXL345_DATAZ1          0x37  /* read only, MSByte X */
+#define ADXL345_FIFO_CTL        0x38
+#define ADXL345_FIFO_STATUS     0x39  /* read only */
+
+/* ADXL345 interrupts */
+#define ADXL345_INT_DISABLE     0X00  /* used for disabling interrupts */
+#define ADXL345_INT_OVERRUN     0X01
+#define ADXL345_INT_WATERMARK   0X02
+#define ADXL345_INT_FREEFALL    0X04
+#define ADXL345_INT_INACTIVITY  0X08
+#define ADXL345_INT_ACTIVITY    0X10
+#define ADXL345_INT_DOUBLETAP   0X20
+#define ADXL345_INT_TAP         0X40
+#define ADXL345_INT_DATAREADY   0X80
+
+/* Accelerometer hardware ports, pins and registers on the msp430 µC */
+#define ADXL345_DIR        P1DIR
+#define ADXL345_PIN        P1PIN
+#define ADXL345_REN        P1REN
+#define ADXL345_SEL        P1SEL
+#define ADXL345_SEL2       P1SEL2
+#define ADXL345_INT1_PIN   (1<<6)    /* P1.6 */
+#define ADXL345_INT2_PIN   (1<<7)    /* P1.7 */
+#define ADXL345_IES        P1IES
+#define ADXL345_IE         P1IE
+#define ADXL345_IFG        P1IFG
+#define ADXL345_VECTOR     PORT1_VECTOR
+
+/* g-range for DATA_FORMAT register */
+#define ADXL345_RANGE_2G    0x00
+#define ADXL345_RANGE_4G    0x01
+#define ADXL345_RANGE_8G    0x02
+#define ADXL345_RANGE_16G   0x03
+
+
+/* The adxl345 has programmable sample rates, but unexpected results may occur
+ * if the wrong  rate and I2C bus speed is used (see datasheet p 17). Sample
+ * rates in Hz. This setting does not change the internal sampling rate, just
+ * how often it is piped to the output registers (ie the interrupt features use
+ * the full sample rate internally).
+ * Example use:
+ *   adxl345_set_reg(ADXL345_BW_RATE, ((_ADXL345_STATUS & LOW_POWER)
+ *                  | ADXL345_SRATE_50));
+ */
+
+/* XXX NB don't use at all as I2C data rate<= 400kHz */
+#define ADXL345_SRATE_3200    0x0F
+/* XXX NB don't use at all as I2C data rate<= 400kHz */
+#define ADXL345_SRATE_1600    0x0E
+#define ADXL345_SRATE_800     0x0D  /* when I2C data rate == 400 kHz */
+#define ADXL345_SRATE_400     0x0C  /* when I2C data rate == 400 kHz */
+#define ADXL345_SRATE_200     0x0B  /* when I2C data rate >= 100 kHz */
+#define ADXL345_SRATE_100     0x0A  /* when I2C data rate >= 100 kHz */
+#define ADXL345_SRATE_50      0x09  /* when I2C data rate >= 100 kHz */
+#define ADXL345_SRATE_25      0x08  /* when I2C data rate >= 100 kHz */
+#define ADXL345_SRATE_12_5    0x07  /* 12.5 Hz, when I2C data rate >= 100 kHz */
+#define ADXL345_SRATE_6_25    0x06  /* when I2C data rate >= 100 kHz */
+#define ADXL345_SRATE_3_13    0x05  /* when I2C data rate >= 100 kHz */
+#define ADXL345_SRATE_1_56    0x04  /* when I2C data rate >= 100 kHz */
+#define ADXL345_SRATE_0_78    0x03  /* when I2C data rate >= 100 kHz */
+#define ADXL345_SRATE_0_39    0x02  /* when I2C data rate >= 100 kHz */
+#define ADXL345_SRATE_0_20    0x01  /* when I2C data rate >= 100 kHz */
+#define ADXL345_SRATE_0_10    0x00  /* 0.10 Hz, when I2C data rate >= 100 kHz */
+/* -------------------------------------------------------------------------- */
+/* Callback pointers for the interrupts */
+extern void (*accm_int1_cb)(uint8_t reg);
+extern void (*accm_int2_cb)(uint8_t reg);
+/* -------------------------------------------------------------------------- */
+#define ACCM_INT1              0x01
+#define ACCM_INT2              0x02
+#define ADXL345_SUCCESS        0x00
+#define ADXL345_ERROR          (-1)
+/* -------------------------------------------------------------------------- */
+#define ADXL345_SENSOR         "ADXL345 sensor"
+/* -------------------------------------------------------------------------- */
+extern const struct sensors_sensor adxl345;
+/* -------------------------------------------------------------------------- */
+/* -------------------------------------------------------------------------- */
+#endif /* ifndef ADXL345_H_ */
diff --git a/arch/platform/z1/dev/battery-sensor.c b/arch/platform/z1/dev/battery-sensor.c
new file mode 100644
index 0000000000000000000000000000000000000000..dd787ccae501e148af72d08f3a005b69073347db
--- /dev/null
+++ b/arch/platform/z1/dev/battery-sensor.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2006, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ *
+ *
+ * -----------------------------------------------------------------
+ *
+ * Author  : Adam Dunkels, Joakim Eriksson, Niclas Finne
+ * Created : 2005-11-01
+ * Updated : $Date: 2010/08/25 19:30:52 $
+ *           $Revision: 1.11 $
+ */
+#include "contiki.h"
+#include "dev/battery-sensor.h"
+#include "dev/sky-sensors.h"
+
+/* Configure ADC12_2 to sample channel 11 (voltage) and use */
+/* the Vref+ as reference (SREF_1) since it is a stable reference */
+#define INPUT_CHANNEL   (1 << INCH_11)
+#define INPUT_REFERENCE SREF_1
+#define BATTERY_MEM     ADC12MEM11
+
+const struct sensors_sensor battery_sensor;
+/*---------------------------------------------------------------------------*/
+static int
+value(int type)
+{
+  return BATTERY_MEM;
+}
+/*---------------------------------------------------------------------------*/
+static int
+configure(int type, int c)
+{
+  return sky_sensors_configure(INPUT_CHANNEL, INPUT_REFERENCE, type, c);
+}
+/*---------------------------------------------------------------------------*/
+static int
+status(int type)
+{
+  return sky_sensors_status(INPUT_CHANNEL, type);
+}
+/*---------------------------------------------------------------------------*/
+SENSORS_SENSOR(battery_sensor, BATTERY_SENSOR, value, configure, status);
diff --git a/tools/sky/uip6-bridge/dev/slip.h b/arch/platform/z1/dev/button-sensor.c
similarity index 51%
rename from tools/sky/uip6-bridge/dev/slip.h
rename to arch/platform/z1/dev/button-sensor.c
index d164ee97c8d1eadb592587a536e4fa828482a7fd..58479bf3bb9f6115db2536f7b3c756107885f06a 100644
--- a/tools/sky/uip6-bridge/dev/slip.h
+++ b/arch/platform/z1/dev/button-sensor.c
@@ -1,4 +1,3 @@
-/* -*- C -*- */
 /*
  * Copyright (c) 2005, Swedish Institute of Computer Science
  * All rights reserved.
@@ -31,62 +30,72 @@
  *
  */
 
-#ifndef SLIP_H_
-#define SLIP_H_
-
 #include "contiki.h"
+#include "lib/sensors.h"
+#include "dev/hwconf.h"
+#include "dev/button-sensor.h"
+#include "isr_compat.h"
 
-PROCESS_NAME(slip_process);
-
-/**
- * Send an IP packet from the uIP buffer with SLIP.
- */
-uint8_t slip_send(void);
+const struct sensors_sensor button_sensor;
 
-/**
- * Input a SLIP byte.
- *
- * This function is called by the RS232/SIO device driver to pass
- * incoming bytes to the SLIP driver. The function can be called from
- * an interrupt context.
- *
- * For systems using low-power CPU modes, the return value of the
- * function can be used to determine if the CPU should be woken up or
- * not. If the function returns non-zero, the CPU should be powered
- * up. If the function returns zero, the CPU can continue to be
- * powered down.
- *
- * \param c The data that is to be passed to the SLIP driver
- *
- * \return Non-zero if the CPU should be powered up, zero otherwise.
- */
-int slip_input_byte(unsigned char c);
+static struct timer debouncetimer;
+static int status(int type);
 
-uint8_t slip_write(const void *ptr, int len);
+HWCONF_PIN(BUTTON, 2, 5);
+HWCONF_IRQ(BUTTON, 2, 5);
 
-/* Did we receive any bytes lately? */
-extern uint8_t slip_active;
+/*---------------------------------------------------------------------------*/
+ISR(PORT2, irq_p2)
+{
+  if(BUTTON_CHECK_IRQ()) {
+    if(timer_expired(&debouncetimer)) {
+      timer_set(&debouncetimer, CLOCK_SECOND / 4);
+      sensors_changed(&button_sensor);
+      LPM4_EXIT;
+    }
+  }
+  P2IFG = 0x00;
+}
+/*---------------------------------------------------------------------------*/
+static int
+value(int type)
+{
+  return BUTTON_READ() || !timer_expired(&debouncetimer);
+}
+/*---------------------------------------------------------------------------*/
+static int
+configure(int type, int c)
+{
+  switch (type) {
+  case SENSORS_ACTIVE:
+    if (c) {
+      if(!status(SENSORS_ACTIVE)) {
+	timer_set(&debouncetimer, 0);
+	BUTTON_IRQ_EDGE_SELECTD();
 
-/* Statistics. */
-extern uint16_t slip_rubbish, slip_twopackets, slip_overflow, slip_ip_drop;
-
-/**
- * Set a function to be called when there is activity on the SLIP
- * interface; used for detecting if a node is a gateway node.
- */
-void slip_set_input_callback(void (*callback)(void));
-
-/**
- * Set a function to be called when a packet has been received.
- * Default is tcpip_input().
- */
-void slip_set_tcpip_input_callback(void (*callback)(void));
-
-/*
- * These machine dependent functions and an interrupt service routine
- * must be provided externally (slip_arch.c).
- */
-void slip_arch_init(void);
-void slip_arch_writeb(unsigned char c);
+	BUTTON_SELECT();
+	BUTTON_MAKE_INPUT();
 
-#endif /* SLIP_H_ */
+	BUTTON_ENABLE_IRQ();
+      }
+    } else {
+      BUTTON_DISABLE_IRQ();
+    }
+    return 1;
+  }
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
+static int
+status(int type)
+{
+  switch (type) {
+  case SENSORS_ACTIVE:
+  case SENSORS_READY:
+    return BUTTON_IRQ_ENABLED();
+  }
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
+SENSORS_SENSOR(button_sensor, BUTTON_SENSOR,
+	       value, configure, status);
diff --git a/arch/platform/z1/dev/cc2420-arch.c b/arch/platform/z1/dev/cc2420-arch.c
new file mode 100644
index 0000000000000000000000000000000000000000..394c5c5699ee37db35f58bc97a06f6247c7a497c
--- /dev/null
+++ b/arch/platform/z1/dev/cc2420-arch.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2006, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ *
+ */
+
+#include "contiki.h"
+#include "contiki-net.h"
+#include "dev/spi-legacy.h"
+#include "cc2420.h"
+#include "isr_compat.h"
+
+#ifdef CC2420_CONF_SFD_TIMESTAMPS
+#define CONF_SFD_TIMESTAMPS CC2420_CONF_SFD_TIMESTAMPS
+#endif /* CC2420_CONF_SFD_TIMESTAMPS */
+
+#ifndef CONF_SFD_TIMESTAMPS
+#define CONF_SFD_TIMESTAMPS 0
+#endif /* CONF_SFD_TIMESTAMPS */
+
+#ifdef CONF_SFD_TIMESTAMPS
+#include "cc2420-arch-sfd.h"
+#endif /* CONF_SFD_TIMESTAMPS */
+
+/*---------------------------------------------------------------------------*/
+#if 0
+/* this is now handled in the ADXL345 accelerometer code as it uses irq on port1 too. */
+ISR(CC2420_IRQ, cc24240_port1_interrupt)
+{
+  if(cc2420_interrupt()) {
+    LPM4_EXIT;
+  }
+}
+#endif
+/*---------------------------------------------------------------------------*/
+void
+cc2420_arch_init(void)
+{
+  spi_init();
+
+  /* all input by default, set these as output */
+  CC2420_CSN_PORT(DIR) |= BV(CC2420_CSN_PIN);
+  CC2420_VREG_PORT(DIR) |= BV(CC2420_VREG_PIN);
+  CC2420_RESET_PORT(DIR) |= BV(CC2420_RESET_PIN);
+
+#if CONF_SFD_TIMESTAMPS
+  cc2420_arch_sfd_init();
+#endif /* CONF_SFD_TIMESTAMPS */
+
+  CC2420_SPI_DISABLE();                /* Unselect radio. */
+}
+/*---------------------------------------------------------------------------*/
diff --git a/arch/platform/z1/dev/i2cmaster.c b/arch/platform/z1/dev/i2cmaster.c
new file mode 100644
index 0000000000000000000000000000000000000000..59437b904caff39dcb41d97f06526e49abf34f2b
--- /dev/null
+++ b/arch/platform/z1/dev/i2cmaster.c
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2010, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *         I2C communication device drivers for Zolertia Z1 sensor node.
+ * \author
+ *         Enric M. Calvo, Zolertia <ecalvo@zolertia.com>
+ *         Marcus Lundén, SICS <mlunden@sics.se>
+ */
+
+#include "i2cmaster.h"
+#include "isr_compat.h"
+
+signed char tx_byte_ctr, rx_byte_ctr;
+unsigned char rx_buf[2];
+unsigned char *tx_buf_ptr;
+unsigned char *rx_buf_ptr;
+unsigned char receive_data;
+unsigned char transmit_data1;
+unsigned char transmit_data2;
+unsigned char prescale_lsb = I2C_PRESC_Z1_LSB;
+unsigned char prescale_msb = I2C_PRESC_Z1_MSB;
+volatile unsigned int i;  /* volatile to prevent optimization */
+
+/* ------------------------------------------------------------------------------
+ * Change the data rate prior initializing transmission or reception
+ * ----------------------------------------------------------------------------- */
+void
+i2c_setrate(uint8_t p_lsb, uint8_t p_msb)
+{
+  prescale_lsb = p_lsb;
+  prescale_lsb = p_msb;
+}
+/* ------------------------------------------------------------------------------
+ * This function initializes the USCI module for master-receive operation.
+ * ----------------------------------------------------------------------------- */
+void
+i2c_receiveinit(uint8_t slave_address)
+{
+  UCB1CTL1 = UCSWRST;                    /* Enable SW reset */
+  UCB1CTL0 = UCMST + UCMODE_3 + UCSYNC;  /* I2C Master, synchronous mode */
+  UCB1CTL1 = UCSSEL_2 | UCSWRST;         /* Use SMCLK, keep SW reset */
+  UCB1BR0 = prescale_lsb;                /* prescaler (default 400 kHz) */
+  UCB1BR1 = prescale_msb;
+  UCB1I2CSA = slave_address;           /* set slave address */
+  UCB1CTL1 &= ~UCTR;                 /* I2C Receiver */
+  UCB1CTL1 &= ~UCSWRST;                  /* Clear SW reset, resume operation */
+  UCB1I2CIE = UCNACKIE;
+#if I2C_RX_WITH_INTERRUPT
+  UC1IE = UCB1RXIE;                      /* Enable RX interrupt if desired */
+#endif
+}
+/* ------------------------------------------------------------------------------
+ * Initializes USCI for master-transmit operation.
+ * ------------------------------------------------------------------------------ */
+void
+i2c_transmitinit(uint8_t slave_address)
+{
+  UCB1CTL1 |= UCSWRST;               /* Enable SW reset */
+  UCB1CTL0 |= (UCMST | UCMODE_3 | UCSYNC); /* I2C Master, synchronous mode */
+  UCB1CTL1 = UCSSEL_2 + UCSWRST;           /* Use SMCLK, keep SW reset */
+  UCB1BR0 = prescale_lsb;                  /* prescaler (default 400 kHz) */
+  UCB1BR1 = prescale_msb;
+  UCB1I2CSA = slave_address;             /* Set slave address */
+  UCB1CTL1 &= ~UCSWRST;                    /* Clear SW reset, resume operation */
+  UCB1I2CIE = UCNACKIE;
+  UC1IE = UCB1TXIE;              /* Enable TX ready interrupt */
+}
+/* ------------------------------------------------------------------------------
+ * This function is used to start an I2C communication in master-receiver mode WITHOUT INTERRUPTS
+ * for more than 1 byte
+ * ------------------------------------------------------------------------------ */
+static volatile uint8_t rx_byte_tot = 0;
+uint8_t
+i2c_receive_n(uint8_t byte_ctr, uint8_t *rx_buf)
+{
+
+  rx_byte_tot = byte_ctr;
+  rx_byte_ctr = byte_ctr;
+  rx_buf_ptr = rx_buf;
+
+  while((UCB1CTL1 & UCTXSTT) || (UCB1STAT & UCNACKIFG))   /* Slave acks address or not? */
+    PRINTFDEBUG("____ UCTXSTT not clear OR NACK received\n");
+
+#if I2C_RX_WITH_INTERRUPT
+  PRINTFDEBUG(" RX Interrupts: YES \n");
+
+  /* SPECIAL-CASE: Stop condition must be sent while receiving the 1st byte for 1-byte only read operations */
+  if(rx_byte_tot == 1) {                /* See page 537 of slau144e.pdf */
+    dint();
+    UCB1CTL1 |= UCTXSTT;    /* I2C start condition */
+    while(UCB1CTL1 & UCTXSTT)           /* Waiting for Start bit to clear */
+      PRINTFDEBUG("____ STT clear wait\n");
+    UCB1CTL1 |= UCTXSTP;    /* I2C stop condition */
+    eint();
+  } else {                              /* all other cases */
+    UCB1CTL1 |= UCTXSTT;    /* I2C start condition */
+  }
+  return 0;
+
+#else
+  uint8_t n_received = 0;
+
+  PRINTFDEBUG(" RX Interrupts: NO \n");
+
+  UCB1CTL1 |= UCTXSTT;    /* I2C start condition */
+
+  while(rx_byte_ctr > 0) {
+    if(UC1IFG & UCB1RXIFG) {    /* Waiting for Data */
+      rx_buf[rx_byte_tot - rx_byte_ctr] = UCB1RXBUF;
+      rx_byte_ctr--;
+      UC1IFG &= ~UCB1RXIFG;     /* Clear USCI_B1 RX int flag */
+      n_received++;
+    }
+  }
+  UCB1CTL1 |= UCTXSTP;    /* I2C stop condition */
+  return n_received;
+#endif
+}
+/* ------------------------------------------------------------------------------
+ * This function is used to check if there is communication in progress.
+ * ------------------------------------------------------------------------------ */
+uint8_t
+i2c_busy(void)
+{
+  return UCB1STAT & UCBBUSY;
+}
+/*----------------------------------------------------------------------------
+ * Setup ports and pins for I2C use.
+ * ------------------------------------------------------------------------------ */
+
+void
+i2c_enable(void)
+{
+  I2C_PxSEL |= (I2C_SDA | I2C_SCL);    /* Secondary function (USCI) selected */
+  I2C_PxSEL2 |= (I2C_SDA | I2C_SCL);   /* Secondary function (USCI) selected */
+  I2C_PxDIR |= I2C_SCL;                /* SCL is output (not needed?) */
+  I2C_PxDIR &= ~I2C_SDA;         /* SDA is input (not needed?) */
+  I2C_PxREN |= (I2C_SDA | I2C_SCL);    /* Activate internal pull-up/-down resistors */
+  I2C_PxOUT |= (I2C_SDA | I2C_SCL);    /* Select pull-up resistors */
+}
+void
+i2c_disable(void)
+{
+  I2C_PxSEL &= ~(I2C_SDA | I2C_SCL);    /* GPIO function selected */
+  I2C_PxSEL2 &= ~(I2C_SDA | I2C_SCL);   /* GPIO function selected */
+  I2C_PxREN &= ~(I2C_SDA | I2C_SCL);    /* Deactivate internal pull-up/-down resistors */
+  I2C_PxOUT &= ~(I2C_SDA | I2C_SCL);    /* Select pull-up resistors */
+}
+/* ------------------------------------------------------------------------------
+ * This function is used to start an I2C communication in master-transmit mode.
+ * ------------------------------------------------------------------------------ */
+static volatile uint8_t tx_byte_tot = 0;
+void
+i2c_transmit_n(uint8_t byte_ctr, uint8_t *tx_buf)
+{
+  tx_byte_tot = byte_ctr;
+  tx_byte_ctr = byte_ctr;
+  tx_buf_ptr = tx_buf;
+  UCB1CTL1 |= UCTR + UCTXSTT;    /* I2C TX, start condition */
+}
+/*----------------------------------------------------------------------------*/
+ISR(USCIAB1TX, i2c_tx_interrupt)
+{
+  /* TX Part */
+  if(UC1IFG & UCB1TXIFG) {         /* TX int. condition */
+    if(tx_byte_ctr == 0) {
+      UCB1CTL1 |= UCTXSTP;     /* I2C stop condition */
+      UC1IFG &= ~UCB1TXIFG;    /* Clear USCI_B1 TX int flag */
+    } else {
+      UCB1TXBUF = tx_buf_ptr[tx_byte_tot - tx_byte_ctr];
+      tx_byte_ctr--;
+    }
+  }
+  /* RX Part */
+#if I2C_RX_WITH_INTERRUPT
+  else if(UC1IFG & UCB1RXIFG) {    /* RX int. condition */
+    rx_buf_ptr[rx_byte_tot - rx_byte_ctr] = UCB1RXBUF;
+    rx_byte_ctr--;
+    if(rx_byte_ctr == 1) { /* stop condition should be set before receiving last byte */
+      /* Only for 1-byte transmissions, STOP is handled in receive_n_int */
+      if(rx_byte_tot != 1) {
+        UCB1CTL1 |= UCTXSTP;       /* I2C stop condition */
+      }
+      UC1IFG &= ~UCB1RXIFG;          /* Clear USCI_B1 RX int flag. XXX Just in case, check if necessary */
+    }
+  }
+#endif
+}
+
+ISR(USCIAB1RX, i2c_rx_interrupt)
+{
+  if(UCB1STAT & UCNACKIFG) {
+    PRINTFDEBUG("!!! NACK received in RX\n");
+    UCB1CTL1 |= UCTXSTP;
+    UCB1STAT &= ~UCNACKIFG;
+  }
+}
diff --git a/arch/platform/z1/dev/i2cmaster.h b/arch/platform/z1/dev/i2cmaster.h
new file mode 100644
index 0000000000000000000000000000000000000000..cf9d96e6d4529e2a0f8ac29e7596d5caa3fc9bd9
--- /dev/null
+++ b/arch/platform/z1/dev/i2cmaster.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2010, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *         I2C communication device driver header file for Zolertia Z1 sensor node.
+ * \author
+ *         Enric Calvo, Zolertia <ecalvo@zolertia.com>
+ *         Marcus Lundén, SICS <mlunden@sics.se>
+ */
+
+#ifndef I2CMASTER_H_
+#define I2CMASTER_H_
+
+#include "contiki.h"
+
+void i2c_enable(void);
+void i2c_disable(void);
+
+void i2c_receiveinit(uint8_t slave_address);
+uint8_t i2c_receive_n(uint8_t byte_ctr, uint8_t *rx_buf);
+
+void i2c_transmitinit(uint8_t slave_address);
+void i2c_transmit_n(uint8_t byte_ctr, uint8_t *tx_buf);
+
+uint8_t i2c_busy(void);
+void i2c_setrate(uint8_t p_lsb, uint8_t p_msb);
+
+#if 0
+#include <stdio.h>
+#define PRINTFDEBUG(...) printf(__VA_ARGS__)
+#else
+#define PRINTFDEBUG(...)
+#endif
+
+#endif /* #ifdef I2CMASTER_H_ */
diff --git a/arch/platform/z1/dev/light-sensor.c b/arch/platform/z1/dev/light-sensor.c
new file mode 100644
index 0000000000000000000000000000000000000000..ebc52d4dbc025bde2e88a5d14446e3049dd84de9
--- /dev/null
+++ b/arch/platform/z1/dev/light-sensor.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 2005-2010, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+#include "contiki.h"
+#include "lib/sensors.h"
+#include "dev/sky-sensors.h"
+#include "dev/light-sensor.h"
+#include "dev/potentiometer-sensor.h"
+
+/* Photodiode 1 (P64) on INCH_4 */
+/* Photodiode 2 (P65) on INCH_5 */
+/* Enric#define INPUT_CHANNEL      ((1 << INCH_4) | (1 << INCH_5)) */
+#ifndef INPUT_CHANNEL
+#define INPUT_CHANNEL      (1 << INCH_4)
+#endif
+
+#ifndef INPUT_REFERENCE
+#define INPUT_REFERENCE     SREF_0
+#endif
+
+#ifdef POTENTIOMETER_MEM
+#define PHOTOSYNTHETIC_MEM  POTENTIOMETER_MEM
+#define TOTAL_SOLAR_MEM     POTENTIOMETER_MEM
+#else
+#define PHOTOSYNTHETIC_MEM  ADC12MEM4
+#define TOTAL_SOLAR_MEM     ADC12MEM4
+#endif
+
+
+const struct sensors_sensor light_sensor;
+
+/*---------------------------------------------------------------------------*/
+static int
+value(int type)
+{
+  switch(type) {
+    /* Photosynthetically Active Radiation. */
+  case LIGHT_SENSOR_PHOTOSYNTHETIC:
+    return PHOTOSYNTHETIC_MEM;
+
+    /* Total Solar Radiation. */
+  case LIGHT_SENSOR_TOTAL_SOLAR:
+    return TOTAL_SOLAR_MEM;
+  }
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
+static int
+status(int type)
+{
+  return sky_sensors_status(INPUT_CHANNEL, type);
+}
+/*---------------------------------------------------------------------------*/
+static int
+configure(int type, int c)
+{
+  return sky_sensors_configure(INPUT_CHANNEL, INPUT_REFERENCE, type, c);
+}
+/*---------------------------------------------------------------------------*/
+SENSORS_SENSOR(light_sensor, "Light", value, configure, status);
diff --git a/arch/platform/z1/dev/light-sensor.h b/arch/platform/z1/dev/light-sensor.h
new file mode 100644
index 0000000000000000000000000000000000000000..411c6fa33d67c3f07ded01847649a39056b966ab
--- /dev/null
+++ b/arch/platform/z1/dev/light-sensor.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2010, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ *
+ *
+ *
+ * -----------------------------------------------------------------
+ *
+ * Author  : Adam Dunkels, Joakim Eriksson, Niclas Finne
+ * Created : 2010-01-08
+ * Updated : $Date: 2010/01/14 20:23:02 $
+ *           $Revision: 1.2 $
+ */
+
+#ifndef LIGHT_SENSOR_H_
+#define LIGHT_SENSOR_H_
+
+#include "lib/sensors.h"
+
+extern const struct sensors_sensor light_sensor;
+
+#define LIGHT_SENSOR_PHOTOSYNTHETIC 0
+#define LIGHT_SENSOR_TOTAL_SOLAR    1
+
+
+#endif /* LIGHT-SENSOR_H_ */
diff --git a/arch/platform/z1/dev/light-ziglet.c b/arch/platform/z1/dev/light-ziglet.c
new file mode 100644
index 0000000000000000000000000000000000000000..3f322e30ad7dbe68be52197b46f587dee330b1ca
--- /dev/null
+++ b/arch/platform/z1/dev/light-ziglet.c
@@ -0,0 +1,219 @@
+/*
+ * Copyright (c) 2010, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *         Device drivers for light ziglet sensor in Zolertia Z1.
+ *         It is recommended to use with a 100KHz data rate
+ * \author
+ *         Antonio Lignan, Zolertia <alinan@zolertia.com>
+ *         Marcus Lundén, SICS <mlunden@sics.se>
+ */
+
+#include <stdio.h>
+#include "contiki.h"
+#include "i2cmaster.h"
+#include "light-ziglet.h"
+
+#if 0
+#define PRINTFDEBUG(...) printf(__VA_ARGS__)
+#else
+#define PRINTFDEBUG(...)
+#endif
+
+/* Bitmasks and bit flag variable for keeping track of tmp102 status. */
+enum TSL2563_STATUSTYPES {
+  /* must be a bit and not more, not using 0x00. */
+  INITED = 0x01,
+  RUNNING = 0x02,
+  STOPPED = 0x04,
+};
+
+static enum TSL2563_STATUSTYPES _TSL2563_STATUS = 0x00;
+
+uint16_t
+calculateLux(uint16_t *buffer)
+{
+  uint32_t ch0, ch1 = 0;
+  uint32_t aux = (1 << 14);
+  uint32_t ratio, lratio, tmp = 0;
+
+  ch0 = (buffer[0] * aux) >> 10;
+  ch1 = (buffer[1] * aux) >> 10;
+
+  PRINTFDEBUG("B0 %u, B1 %u\n", buffer[0], buffer[1]);
+  PRINTFDEBUG("ch0 %lu, ch1 %lu\n", ch0, ch1);
+
+  ratio = (ch1 << 10);
+  ratio = ratio / ch0;
+  lratio = (ratio + 1) >> 1;
+
+  PRINTFDEBUG("ratio %lu, lratio %lu\n", ratio, lratio);
+
+  if((lratio >= 0) && (lratio <= K1T)) {
+    tmp = (ch0 * B1T) - (ch1 * M1T);
+  } else if(lratio <= K2T) {
+    tmp = (ch0 * B2T) - (ch1 * M2T);
+  } else if(lratio <= K3T) {
+    tmp = (ch0 * B3T) - (ch1 * M3T);
+  } else if(lratio <= K4T) {
+    tmp = (ch0 * B4T) - (ch1 * M4T);
+  } else if(lratio <= K5T) {
+    tmp = (ch0 * B5T) - (ch1 * M5T);
+  } else if(lratio <= K6T) {
+    tmp = (ch0 * B6T) - (ch1 * M6T);
+  } else if(lratio <= K7T) {
+    tmp = (ch0 * B7T) - (ch1 * M7T);
+  } else if(lratio > K8T) {
+    tmp = (ch0 * B8T) - (ch1 * M8T);
+  }
+
+  if(tmp < 0) {
+    tmp = 0;
+  }
+
+  tmp += (1 << 13);
+
+  PRINTFDEBUG("tmp %lu\n", tmp);
+
+  return tmp >> 14;
+}
+/*---------------------------------------------------------------------------*/
+/* Init the light ziglet sensor: ports, pins, registers, interrupts (none enabled), I2C,
+    default threshold values etc. */
+
+void
+light_ziglet_init(void)
+{
+  if(!(_TSL2563_STATUS & INITED)) {
+    PRINTFDEBUG("light ziglet init\n");
+    _TSL2563_STATUS |= INITED;
+
+    /* Set up ports and pins for I2C communication */
+    i2c_enable();
+    return;
+  }
+}
+/*---------------------------------------------------------------------------*/
+/* Write to a 16-bit register.
+    args:
+      reg       register to write to
+      val       value to write
+ */
+
+void
+tsl2563_write_reg(uint8_t reg, uint16_t val)
+{
+  uint8_t tx_buf[] = { reg, 0x00, 0x00 };
+
+  tx_buf[1] = (uint8_t)(val >> 8);
+  tx_buf[2] = (uint8_t)(val & 0x00FF);
+
+  i2c_transmitinit(TSL2563_ADDR);
+  while(i2c_busy());
+  PRINTFDEBUG("I2C Ready to TX\n");
+
+  i2c_transmit_n(3, tx_buf);
+  while(i2c_busy());
+  PRINTFDEBUG("WRITE_REG 0x%04X @ reg 0x%02X\n", val, reg);
+}
+/*---------------------------------------------------------------------------*/
+/* Read register.
+    args:
+      reg       what register to read
+    returns the value of the read register type uint16_t
+ */
+
+uint16_t
+tsl2563_read_reg(uint8_t reg)
+{
+  uint16_t readBuf[] = { 0x00, 0x00 };
+  uint8_t buf[] = { 0x00, 0x00, 0x00, 0x00 };
+  uint16_t retVal = 0;
+  uint8_t rtx = reg;
+
+  /* Transmit the register to read */
+  i2c_transmitinit(TSL2563_ADDR);
+  while(i2c_busy());
+  i2c_transmit_n(1, &rtx);
+  while(i2c_busy());
+
+  /* Receive the data */
+  i2c_receiveinit(TSL2563_ADDR);
+  while(i2c_busy());
+  i2c_receive_n(4, buf);
+  while(i2c_busy());
+
+  PRINTFDEBUG("\nb0 %u, b1 %u, b2 %u, b3 %u\n", buf[0], buf[1], buf[2], buf[3]);
+
+  readBuf[0] = (buf[1] << 8 | (buf[0]));
+  readBuf[1] = (buf[3] << 8 | (buf[2]));
+
+  retVal = calculateLux(readBuf);
+  return retVal;
+}
+uint16_t
+light_ziglet_on(void)
+{
+  uint16_t data;
+  uint8_t regon = TSL2563_PWRN;
+  /* Turn on the sensor */
+  i2c_transmitinit(TSL2563_ADDR);
+  while(i2c_busy());
+  i2c_transmit_n(1, &regon);
+  while(i2c_busy());
+  data = (uint16_t)tsl2563_read_reg(TSL2563_READ);
+  return data;
+}
+void
+light_ziglet_off(void)
+{
+  uint8_t regoff = 0x00;
+  /* Turn off the sensor */
+  i2c_transmitinit(TSL2563_ADDR);
+  while(i2c_busy());
+  i2c_transmit_n(1, &regoff);
+  while(i2c_busy());
+  return;
+}
+/*---------------------------------------------------------------------------*/
+/* Read light ziglet sensor
+ */
+
+uint16_t
+light_ziglet_read(void)
+{
+  uint16_t lux = 0;
+  lux = light_ziglet_on();
+  light_ziglet_off();
+  return lux;
+}
diff --git a/arch/platform/z1/dev/light-ziglet.h b/arch/platform/z1/dev/light-ziglet.h
new file mode 100644
index 0000000000000000000000000000000000000000..4db18e24e12c361fa0925b461215d157cd3527ef
--- /dev/null
+++ b/arch/platform/z1/dev/light-ziglet.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2010, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *         Device drivers header file for light ziglet sensor in Zolertia Z1 WSN Platform.
+ * \author
+ *         Antonio Lignan, Zolertia <alinan@zolertia.com>
+ *         Marcus Lundén, SICS <mlunden@sics.se>
+ */
+
+#ifndef LIGHT_ZIGLET_H_
+#define LIGHT_ZIGLET_H_
+#include <stdio.h>
+#include "i2cmaster.h"
+
+/* Init the light ziglet sensor: ports, pins, I2C, interrupts */
+void  light_ziglet_init(void);
+
+/* Write to a register.
+    args:
+      reg       register to write to
+      val       value to write
+ */
+void   tsl2563_write_reg(uint8_t reg, uint16_t val);
+
+/* Read one register.
+    args:
+      reg       what register to read
+    returns the value of the read register
+ */
+uint16_t tsl2563_read_reg(uint8_t reg);
+
+/* Takes a single light reading
+   args: none
+   returns a lux value
+ */
+uint16_t light_ziglet_read();
+
+/* Calculates the lux values from the calibration table
+   args: raw values from sensor
+   returns a lux value
+ */
+uint16_t calculateLux(uint16_t *readRaw);
+
+/* Turns the light ziglet ON and polls the sensor for a light reading */
+uint16_t light_ziglet_on(void);
+
+/* -------------------------------------------------------------------------- */
+/* Reference definitions */
+
+/* TSL2563 slave address */
+#define TSL2563_ADDR 0x39
+
+/* Registers */
+#define TSL2563_READ 0xAC
+#define TSL2563_PWRN 0x03
+
+/* Calibration settings */
+#define K1T 0X0040
+#define B1T 0x01f2
+#define M1T 0x01b2
+
+#define K2T 0x0080
+#define B2T 0x0214
+#define M2T 0x02d1
+
+#define K3T 0x00c0
+#define B3T 0x023f
+#define M3T 0x037b
+
+#define K4T 0x0100
+#define B4T 0x0270
+#define M4T 0x03fe
+
+#define K5T 0x0138
+#define B5T 0x016f
+#define M5T 0x01fc
+
+#define K6T 0x019a
+#define B6T 0x00d2
+#define M6T 0x00fb
+
+#define K7T 0x029a
+#define B7T 0x0018
+#define M7T 0x0012
+
+#define K8T 0x029a
+#define B8T 0x0000
+#define M8T 0x0000
+
+/* -------------------------------------------------------------------------- */
+#endif /* ifndef LIGHT_ZIGLET_H_ */
+
diff --git a/arch/platform/z1/dev/potentiometer-sensor.c b/arch/platform/z1/dev/potentiometer-sensor.c
new file mode 100644
index 0000000000000000000000000000000000000000..12597bd0e73b9b89c5fecc8fe2a44bc5541874bd
--- /dev/null
+++ b/arch/platform/z1/dev/potentiometer-sensor.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2011 Zolertia(TM) is a trademark by Advancare,SL
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ *
+ *
+ * -----------------------------------------------------------------
+ *
+ * Author  : Enric M. Calvo (based on work by A. Dunkels, J. Eriksson, N. Finne)
+ * Created : 2011-02-22
+ *           $Revision: 1.0 $
+ */
+
+#include "dev/potentiometer-sensor.h"
+#include "dev/sky-sensors.h"
+#include "contiki.h"
+
+/* Configure ADC12_2 to sample channel 11 (voltage) and use */
+/* the Vref+ as reference (SREF_1) since it is a stable reference */
+#define INPUT_CHANNEL          (1 << INCH_4)
+#define INPUT_REFERENCE        SREF_0
+#define POTENTIOMETER_MEM      ADC12MEM4
+
+const struct sensors_sensor potentiometer_sensor;
+/*---------------------------------------------------------------------------*/
+static int
+value(int type)
+{
+  return POTENTIOMETER_MEM;
+}
+/*---------------------------------------------------------------------------*/
+static int
+configure(int type, int c)
+{
+  return sky_sensors_configure(INPUT_CHANNEL, INPUT_REFERENCE, type, c);
+}
+/*---------------------------------------------------------------------------*/
+static int
+status(int type)
+{
+  return sky_sensors_status(INPUT_CHANNEL, type);
+}
+/*---------------------------------------------------------------------------*/
+SENSORS_SENSOR(potentiometer_sensor, POTENTIOMETER_SENSOR, value, configure, status);
diff --git a/arch/platform/z1/dev/potentiometer-sensor.h b/arch/platform/z1/dev/potentiometer-sensor.h
new file mode 100644
index 0000000000000000000000000000000000000000..d9d8b983d8e68fb94a6e214fd4818cf8ea2e5791
--- /dev/null
+++ b/arch/platform/z1/dev/potentiometer-sensor.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2011 Zolertia(TM) is a trademark by Advancare,SL
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ *
+ *
+ * -----------------------------------------------------------------
+ *
+ * Author  : Enric M. Calvo (based on work by A. Dunkels, J. Eriksson, N. Finne)
+ * Created : 2011-02-22
+ *           $Revision: 1.0 $
+ */
+
+#ifndef POTENTIOMETER_SENSOR_H_
+#define POTENTIOMETER_SENSOR_H_
+
+#include "lib/sensors.h"
+
+extern const struct sensors_sensor potentiometer_sensor;
+
+#define POTENTIOMETER_SENSOR "Potentiometer"
+
+#endif /* POTENTIOMETER_SENSOR_H_ */
diff --git a/arch/platform/z1/dev/reed-sensor.c b/arch/platform/z1/dev/reed-sensor.c
new file mode 100644
index 0000000000000000000000000000000000000000..7e7a0df6da952cfce83d8cb581bd2d0d415c4c1c
--- /dev/null
+++ b/arch/platform/z1/dev/reed-sensor.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2015, Zolertia <http://www.zolertia.com>
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+/**
+ * \file
+ *         Reed sensor driver file
+ * \author
+ *         Antonio Lignan <alinan@zolertia.com>
+ */
+
+#include "contiki.h"
+#include "lib/sensors.h"
+#include "dev/reed-sensor.h"
+#include "sys/process.h"
+#include "sys/ctimer.h"
+/*---------------------------------------------------------------------------*/
+#ifndef REED_CHECK_PERIOD
+#define REED_CHECK_PERIOD    CLOCK_SECOND
+#endif
+/*---------------------------------------------------------------------------*/
+static int current_status = -1;
+static struct ctimer change_timer;
+process_event_t reed_sensor_event_changed;
+/*---------------------------------------------------------------------------*/
+static int
+status(int type)
+{
+  switch(type) {
+  case SENSORS_ACTIVE:
+  case SENSORS_READY:
+    return ~(REED_PORT_DIR & REED_READ_PIN);
+  }
+  return REED_SENSOR_ERROR;
+}
+/*---------------------------------------------------------------------------*/
+static int
+value(int type)
+{
+  if((!status(SENSORS_ACTIVE)) || (type != REED_SENSOR_VAL)) {
+    return REED_SENSOR_ERROR;
+  }
+  return (REED_PORT_READ & REED_READ_PIN) ? REED_CLOSED : REED_OPEN;
+}
+/*---------------------------------------------------------------------------*/
+static void
+check_callback(void *data)
+{
+  static int new_status;
+  if(current_status == -1) {
+    ctimer_stop(&change_timer);
+    return;
+  }
+
+  new_status = value(REED_SENSOR_VAL);
+  if(new_status != current_status) {
+    current_status = new_status;
+    process_post(PROCESS_BROADCAST, reed_sensor_event_changed, &current_status);
+  }
+  ctimer_reset(&change_timer);
+}
+/*---------------------------------------------------------------------------*/
+static int
+configure(int type, int c)
+{
+  switch(type) {
+  case SENSORS_ACTIVE:
+    if(c) {
+      if(!status(SENSORS_ACTIVE)) {
+        REED_PORT_SEL |= REED_READ_PIN;
+        REED_PORT_DIR &= ~REED_READ_PIN;
+        REED_PORT_REN |= REED_READ_PIN;
+        REED_PORT_PRES |= REED_READ_PIN;
+      }
+    } else {
+      REED_PORT_DIR |= REED_READ_PIN;
+      REED_PORT_REN &= ~REED_READ_PIN;
+    }
+    return REED_SENSOR_SUCCESS;
+  case REED_SENSOR_MODE:
+    if(c == REED_SENSOR_EVENT_MODE) {
+      current_status = value(REED_SENSOR_VAL);
+      ctimer_set(&change_timer, REED_CHECK_PERIOD, check_callback, NULL);
+    } else if(c == REED_SENSOR_EVENT_POLL) {
+      current_status = -1;
+      ctimer_stop(&change_timer);
+    } else {
+      return REED_SENSOR_ERROR;
+    }
+    return REED_SENSOR_SUCCESS;
+  }
+  return REED_SENSOR_ERROR;
+}
+/*---------------------------------------------------------------------------*/
+SENSORS_SENSOR(reed_sensor, REED_SENSOR, value, configure, status);
diff --git a/arch/platform/z1/dev/reed-sensor.h b/arch/platform/z1/dev/reed-sensor.h
new file mode 100644
index 0000000000000000000000000000000000000000..7e86716f50f4b0d00305de6e4742f53e8beed8b3
--- /dev/null
+++ b/arch/platform/z1/dev/reed-sensor.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2015, Zolertia <http://www.zolertia.com>
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+/**
+ * Header file for the reed sensor
+ *
+ * The Reed sensor allows to be used either by polling the sensor status or by
+ * setting up a timer on the background ticking every REED_CHECK_PERIOD, posting
+ * a reed_sensor_event_changed event, informing the application about a change
+ * in the sensor status (basically open or closed).  To enable each mode
+ * (default is polling) call the configure() function with REED_SENSOR_MODE
+ * using REED_SENSOR_EVENT_MODE or REED_SENSOR_POLL_MODE, after having
+ * initialized the device using SENSORS_ACTIVATE(reed_sensor).
+ *
+ * \file
+ *         Reed sensor header file
+ * \author
+ *         Antonio Lignan <alinan@zolertia.com>
+ */
+#include "lib/sensors.h"
+
+#ifndef REED_SENSOR_H_
+#define REED_SENSOR_H_
+/* -------------------------------------------------------------------------- */
+#define REED_SENSOR_ERROR       -1
+#define REED_SENSOR_SUCCESS     0x00
+#define REED_SENSOR_VAL         0x01
+/* -------------------------------------------------------------------------- */
+#define REED_OPEN               0x00
+#define REED_CLOSED             0x01
+/* -------------------------------------------------------------------------- */
+#define REED_SENSOR_MODE        0x01
+#define REED_SENSOR_EVENT_MODE  0x0A
+#define REED_SENSOR_EVENT_POLL  0x0B
+/* -------------------------------------------------------------------------- */
+#define REED_PORT_DIR           P4DIR
+#define REED_PORT_SEL           P4SEL
+#define REED_PORT_REN           P4REN
+#define REED_PORT_READ          P4IN
+#define REED_PORT_PRES          P4OUT
+#define REED_READ_PIN           (1 << 2)
+/* -------------------------------------------------------------------------- */
+#define REED_SENSOR             "Reed Sensor"
+/* -------------------------------------------------------------------------- */
+extern const struct sensors_sensor reed_sensor;
+extern process_event_t reed_sensor_event_changed;
+/* -------------------------------------------------------------------------- */
+#endif /* ifndef REED_SENSOR_H_ */
diff --git a/arch/platform/z1/dev/relay-phidget.c b/arch/platform/z1/dev/relay-phidget.c
new file mode 100644
index 0000000000000000000000000000000000000000..d78734b216a15d55f983304f34364549dab0a532
--- /dev/null
+++ b/arch/platform/z1/dev/relay-phidget.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2010, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ *
+ * -----------------------------------------------------------------
+ *
+ * \file
+ *         Device simple driver for generic relay in phidget port of Zolertia Z1
+ * \author
+ *         Antonio Lignan, Zolertia <alinan@zolertia.com>
+ *
+ */
+
+#include "contiki.h"
+#include "relay-phidget.h"
+
+static uint8_t controlPin;
+
+enum PHIDGET_RELAY_STATUSTYPES {
+  /* must be a bit and not more, not using 0x00. */
+  INITED = 0x01,
+  RUNNING = 0x02,
+  STOPPED = 0x04,
+};
+
+static enum PHIDGET_RELAY_STATUSTYPES _RELAY_STATUS = 0x00;
+
+/*---------------------------------------------------------------------------*/
+
+void
+relay_enable(uint8_t pin)
+{
+
+  if(!(_RELAY_STATUS & INITED)) {
+
+    _RELAY_STATUS |= INITED;
+
+    /* Selects the pin to be configure as the control pin of the relay module */
+    controlPin = (1 << pin);
+
+    /* Configures the control pin */
+    P6SEL &= ~controlPin;
+    P6DIR |= controlPin;
+  }
+}
+/*---------------------------------------------------------------------------*/
+
+void
+relay_on()
+{
+  if((_RELAY_STATUS & INITED)) {
+    P6OUT |= controlPin;
+  }
+}
+/*---------------------------------------------------------------------------*/
+void
+relay_off()
+{
+  if((_RELAY_STATUS & INITED)) {
+    P6OUT &= ~controlPin;
+  }
+}
+/*---------------------------------------------------------------------------*/
+
+int8_t
+relay_toggle()
+{
+  if((_RELAY_STATUS & INITED)) {
+    P6OUT ^= controlPin;
+    if((P6OUT & controlPin)) {
+      return 1;
+    }
+    return 0;
+  }
+  return -1;
+}
+/*---------------------------------------------------------------------------*/
+
diff --git a/arch/platform/z1/dev/relay-phidget.h b/arch/platform/z1/dev/relay-phidget.h
new file mode 100644
index 0000000000000000000000000000000000000000..580151f5861a529799d58d74cbb133b3ff8b30ac
--- /dev/null
+++ b/arch/platform/z1/dev/relay-phidget.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ * -----------------------------------------------------------------
+ *
+ * \file
+ *         Device simple driver for generic relay in phidget port of Zolertia Z1
+ * \author
+ *         Antonio Lignan, Zolertia <alinan@zolertia.com>
+ *
+ */
+
+#ifndef RELAY_PHIDGET_H_
+#define RELAY_PHIDGETS_H_
+
+void relay_enable(uint8_t pin);
+
+void relay_on();
+void relay_off();
+int8_t relay_toggle();
+
+#endif /* RELAY_PHIDGET_H_ */
diff --git a/arch/platform/z1/dev/sht11-arch.h b/arch/platform/z1/dev/sht11-arch.h
new file mode 100644
index 0000000000000000000000000000000000000000..1cd1bc8e6302f26df665a07897b7eb25a824ec31
--- /dev/null
+++ b/arch/platform/z1/dev/sht11-arch.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2011, Zolertia(TM) is a trademark of Advancare,SL
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *	Architecture-specific definitions for the SHT11 sensor on Zolertia Z1
+ *      when connected to the Ziglet port.
+ * \author
+ *      Enric M. Calvo <ecalvo@zolertia.com>, adapted from work by
+ * 	Nicolas Tsiftes <nvt@sics.se>
+ */
+
+#ifndef SHT11_ARCH_H
+#define SHT11_ARCH_H
+
+/* Architecture-specific definitions for the SHT11 sensor on Zolertia Z1
+ * when connected to the Ziglet port. 
+ * CAUTION: I2C needs to be disabled to use the bitbang protocol of SHT11
+ */
+
+#define SHT11_ARCH_SDA	1	/* P5.1 */
+#define SHT11_ARCH_SCL	2	/* P5.2 */
+/* SHT11_ARCH_PWR is not needed, but until and *-arch abstraction exists, this
+ * should fix it 
+ */
+#define SHT11_ARCH_PWR	3	/* P5.3 -- unused pin */ 
+
+#define	SHT11_PxDIR	P5DIR
+#define SHT11_PxIN	P5IN
+#define SHT11_PxOUT	P5OUT
+#define SHT11_PxSEL	P5SEL
+#define SHT11_PxREN     P5REN
+
+#endif
diff --git a/tools/sky/uip6-bridge/uip6-bridge-tap.c b/arch/platform/z1/dev/sht25.c
similarity index 50%
rename from tools/sky/uip6-bridge/uip6-bridge-tap.c
rename to arch/platform/z1/dev/sht25.c
index 694499b6d938defbe18b4144fd9f45e3c3eee7e0..b8356087bdc889e7aef7efa80b6e33bbde095b81 100644
--- a/tools/sky/uip6-bridge/uip6-bridge-tap.c
+++ b/arch/platform/z1/dev/sht25.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Swedish Institute of Computer Science.
+ * Copyright (c) 2015, Zolertia <http://www.zolertia.com>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -26,127 +26,109 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
+ * This file is part of the Contiki operating system.
  *
  */
-
 /**
  * \file
- *         A brief description of what this file is
+ *         SHT25 temperature and humidity sensor driver
  * \author
- *         Niclas Finne <nfi@sics.se>
- *         Joakim Eriksson <joakime@sics.se>
+ *         Antonio Lignan <alinan@zolertia.com>
  */
-
-#include "contiki.h"
-#include "net/ipv6/uip.h"
-#include "dev/slip.h"
-#include "dev/leds.h"
-#include "sicslow_ethernet.h"
-
-#include "net/packetbuf.h"
-
 #include <stdio.h>
-#include <string.h>
-
-#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-
-PROCESS(uip6_bridge, "IPv6/6lowpan TAP bridge");
-PROCESS(tcpip_process, "tcpip dummy");
-AUTOSTART_PROCESSES(&uip6_bridge);
-
+#include "contiki.h"
+#include "i2cmaster.h"
+#include "dev/sht25.h"
+#include "lib/sensors.h"
+/*---------------------------------------------------------------------------*/
+static uint8_t enabled;
 /*---------------------------------------------------------------------------*/
-static uint8_t (* outputfunc)(const uip_lladdr_t *a);
-uint8_t
-tcpip_output(const uip_lladdr_t *a)
+static int
+configure(int type, int value)
 {
-  if(outputfunc != NULL) {
-    outputfunc(a);
-    leds_toggle(LEDS_GREEN);
+  if(type != SENSORS_ACTIVE) {
+    return SHT25_ERROR;
   }
+  if(value) {
+    i2c_enable();
+  } else {
+    i2c_disable();
+  }
+  enabled = value;
   return 0;
 }
-void
-tcpip_ipv6_output(void)
-{
-}
-void
-tcpip_set_outputfunc(uint8_t (*f)(const uip_lladdr_t *))
-{
-  outputfunc = f;
-}
-PROCESS_THREAD(tcpip_process, ev, data)
-{
-  PROCESS_BEGIN();
-  PROCESS_END();
-}
 /*---------------------------------------------------------------------------*/
-/* Packet from SICSLoWPAN */
-void
-tcpip_input(void)
+static int
+status(int type)
 {
-  if(uip_len > 0) {
-    mac_LowpanToEthernet();
-    if(uip_len > 0) {
-      slip_write(uip_buf, uip_len);
-      leds_toggle(LEDS_RED);
-      uip_clear_buf();
-    }
+  switch(type) {
+  case SENSORS_ACTIVE:
+  case SENSORS_READY:
+    return enabled;
   }
+  return 0;
 }
 /*---------------------------------------------------------------------------*/
-/* Packet from SLIP */
-static void
-slip_tcpip_input(void)
+static uint16_t
+sht25_read_reg(uint8_t reg)
 {
-  /* TODO Should fix this in slip configuration */
-  memmove(uip_buf, &uip_buf[UIP_LLH_LEN], uip_len);
-  mac_ethernetToLowpan(uip_buf);
+  uint8_t buf[] = { 0x00, 0x00 };
+  uint16_t retval;
+  uint8_t rtx = reg;
+
+  /* transmit the register to read */
+  i2c_transmitinit(SHT25_ADDR);
+  while(i2c_busy());
+  i2c_transmit_n(1, &rtx);
+  while(i2c_busy());
+  /* receive the data */
+  i2c_receiveinit(SHT25_ADDR);
+  while(i2c_busy());
+  i2c_receive_n(2, &buf[0]);
+  while(i2c_busy());
+
+  retval = (uint16_t)(buf[0] << 8 | (buf[1]));
+  return retval;
 }
 /*---------------------------------------------------------------------------*/
-static void
-slip_activity(void)
+static int16_t
+sht25_convert(uint8_t variable, uint16_t value)
 {
-  leds_toggle(LEDS_BLUE);
+  int16_t rd;
+  uint32_t buff;
+  buff = (uint32_t)value;
+  if(variable == SHT25_VAL_TEMP) {
+    buff *= 17572;
+    buff = buff >> 16;
+    rd = (int16_t)buff - 4685;
+  } else {
+    buff *= 12500;
+    buff = buff >> 16;
+    rd = (int16_t)buff - 600;
+    rd = (rd > 10000) ? 10000 : rd;
+  }
+  return rd;
 }
 /*---------------------------------------------------------------------------*/
-PROCESS_THREAD(uip6_bridge, ev, data)
+static int16_t
+sht25_read(uint8_t variable)
 {
-  PROCESS_BEGIN();
-
-  printf("Setting up SLIP\n");
-
-  mac_ethernetSetup();
-
-  slip_arch_init();
-  slip_set_input_callback(slip_activity);
-  slip_set_tcpip_input_callback(slip_tcpip_input);
-  process_start(&slip_process, NULL);
+  int16_t rd;
+  uint16_t raw;
 
-  PROCESS_END();
+  if((variable != SHT25_VAL_TEMP) && (variable != SHT25_VAL_HUM)) {
+    return SHT25_ERROR;
+  }
+  raw = sht25_read_reg(variable);
+  rd = sht25_convert(variable, raw);
+  return rd;
 }
 /*---------------------------------------------------------------------------*/
-int
-putchar(int c)
+static int
+value(int type)
 {
-#define SLIP_END     0300
-  static char debug_frame = 0;
-
-  if(!debug_frame) {		/* Start of debug output */
-    slip_arch_writeb(SLIP_END);
-    slip_arch_writeb('\r');	/* Type debug line == '\r' */
-    debug_frame = 1;
-  }
-
-  slip_arch_writeb((char)c);
-
-  /*
-   * Line buffered output, a newline marks the end of debug output and
-   * implicitly flushes debug output.
-   */
-  if(c == '\n') {
-    slip_arch_writeb(SLIP_END);
-    debug_frame = 0;
-  }
-  return c;
+  return sht25_read(type);
 }
 /*---------------------------------------------------------------------------*/
+SENSORS_SENSOR(sht25, SHT25_SENSOR, value, configure, status);
+/*---------------------------------------------------------------------------*/
diff --git a/arch/platform/z1/dev/sht25.h b/arch/platform/z1/dev/sht25.h
new file mode 100644
index 0000000000000000000000000000000000000000..65d9399d36f147f331bd4dd9d415c905e6d0951b
--- /dev/null
+++ b/arch/platform/z1/dev/sht25.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2015, Zolertia <http://www.zolertia.com>
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+/**
+ * \file
+ *         SHT25 temperature and humidity sensor driver
+ * \author
+ *         Antonio Lignan <alinan@zolertia.com>
+ */
+#include "lib/sensors.h"
+
+#ifndef SHT25_H_
+#define SHT25_H_
+
+/* -------------------------------------------------------------------------- */
+#define SHT25_ADDR            0x40
+#define SHT25_TEMP_HOLD       0xE3
+#define SHT25_HUM_HOLD        0xE5
+#define SHT25_TEMP_NO_HOLD    0xF3
+#define SHT25_HUM_NO_HOLD     0xF5
+#define SHT2X_UREG_WRITE      0xE6
+#define SHT2X_UREG_READ       0xE7
+#define SHT2X_SOFT_RESET      0XFE
+#define SHT2X_NULL            0x00
+/* -------------------------------------------------------------------------- */
+#define SHT2X_RES_14T_12RH    0x00
+#define SHT2X_RES_12T_08RH    0x01
+#define SHT2X_RES_13T_10RH    0x80
+#define SHT2X_RES_11T_11RH    0x81
+#define SHT2X_HEATER_ON       0x04
+#define SHT2X_HEATER_OFF      0x00
+#define SHT2X_OTP_RELOAD_EN   0x00
+#define SHT2X_OTP_RELOAD_DIS  0x02
+/* -------------------------------------------------------------------------- */
+#define SHT25_VAL_TEMP        SHT25_TEMP_HOLD
+#define SHT25_VAL_HUM         SHT25_HUM_HOLD
+#define SHT25_ERROR           -1
+/* -------------------------------------------------------------------------- */
+#define SHT25_SENSOR "SHT25 Sensor"
+/* -------------------------------------------------------------------------- */
+extern const struct sensors_sensor sht25;
+/* -------------------------------------------------------------------------- */
+#endif /* ifndef SHT25_H_ */
diff --git a/arch/platform/z1/dev/sky-sensors.c b/arch/platform/z1/dev/sky-sensors.c
new file mode 100644
index 0000000000000000000000000000000000000000..48ac224282b4fb522c4a339e0aed0a4699dc7d80
--- /dev/null
+++ b/arch/platform/z1/dev/sky-sensors.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2010, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ *
+ * -----------------------------------------------------------------
+ *
+ * Author  : Joakim Eriksson
+ * Created : 2010-02-02
+ * Updated : $Date: 2010/08/25 19:30:53 $
+ *           $Revision: 1.3 $
+ */
+#include "contiki.h"
+#include "lib/sensors.h"
+
+#define ADC12MCTL_NO(adcno) ((unsigned char *) ADC12MCTL0_)[adcno]
+
+static uint16_t adc_on;
+static uint16_t ready;
+/*---------------------------------------------------------------------------*/
+static CC_INLINE void
+start(void)
+{
+  uint16_t c, last;
+
+  /* Set up the ADC. */
+  P6DIR = 0xff;
+  P6OUT = 0x00;
+
+  /* Setup ADC12, ref., sampling time */
+  /* XXX Note according to the specification a minimum of 17 ms should
+     be allowed after turn on of the internal reference generator. */
+  ADC12CTL0 = REF2_5V + SHT0_6 + SHT1_6 + MSC + REFON;
+  /* Use sampling timer, repeat-sequence-of-channels */
+  ADC12CTL1 = SHP + CONSEQ_3;
+
+  last = 15;
+  for(c = 0; c < 16; c++) {
+    /* Clear all end-of-sequences */
+    ADC12MCTL_NO(c) &= ~EOS;
+    if(adc_on & (1 << c)) {
+      if(last == 15) {
+        /* Set new start of sequence to lowest active memory holder */
+        ADC12CTL1 |= (c * CSTARTADD_1);
+      }
+      last = c;
+    }
+  }
+
+  /* Set highest end-of-sequence. */
+  ADC12MCTL_NO(last) |= EOS;
+
+  ADC12CTL0 |= ADC12ON;
+  ADC12CTL0 |= ENC;                   /* enable conversion */
+  ADC12CTL0 |= ADC12SC;               /* sample & convert */
+}
+/*---------------------------------------------------------------------------*/
+static CC_INLINE void
+stop(void)
+{
+  /* stop converting immediately, turn off reference voltage, etc. */
+
+  ADC12CTL0 &= ~ENC;
+  /* need to remove CONSEQ_3 if not EOS is configured */
+  ADC12CTL1 &= ~CONSEQ_3;
+
+  /* wait for conversion to stop */
+  while(ADC12CTL1 & ADC12BUSY);
+
+  /* clear any pending interrupts */
+  ADC12IFG = 0;
+}
+/*---------------------------------------------------------------------------*/
+int
+sky_sensors_status(uint16_t input, int type)
+{
+  if(type == SENSORS_ACTIVE) {
+    return (adc_on & input) == input;
+  }
+  if(type == SENSORS_READY) {
+    ready |= ADC12IFG & adc_on & input;
+    return (ready & adc_on & input) == input;
+  }
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
+int
+sky_sensors_configure(uint16_t input, uint8_t ref, int type, int value)
+{
+  uint16_t c;
+
+  if(type == SENSORS_ACTIVE) {
+    stop();
+
+    if(value) {
+      adc_on |= input;
+      P6SEL |= input & 0xff;
+
+      /* Set ADC config */
+      for(c = 0; c < 16; c++) {
+        if(input & (1 << c)) {
+          ADC12MCTL_NO(c) = (c * INCH_1) | ref;
+        }
+      }
+
+    } else {
+      adc_on &= ~input;
+      ready &= ~input;
+      P6SEL &= ~(input & 0xff);
+    }
+
+    if(adc_on == 0) {
+      P6DIR = 0x00;
+      P6SEL = 0x00;
+
+      /* Turn off ADC and internal reference generator */
+      ADC12CTL0 = 0;
+      ADC12CTL1 = 0;
+    } else {
+      start();
+    }
+    return 1;
+  }
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
diff --git a/arch/platform/z1/dev/sky-sensors.h b/arch/platform/z1/dev/sky-sensors.h
new file mode 100644
index 0000000000000000000000000000000000000000..df2aeea48c230d4d3638c2255f0f59eec7b5cf86
--- /dev/null
+++ b/arch/platform/z1/dev/sky-sensors.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2010, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ * -----------------------------------------------------------------
+ *
+ * Author  : Joakim Eriksson
+ * Created : 2010-02-02
+ * Updated : $Date: 2010/08/25 19:30:53 $
+ *           $Revision: 1.2 $
+ */
+
+#ifndef SKY_SENSORS_H_
+#define SKY_SENSORS_H_
+
+int  sky_sensors_status(uint16_t input, int type);
+int  sky_sensors_configure(uint16_t input, uint8_t reference,
+                           int type, int value);
+
+#endif /* SKY_SENSORS_H_ */
diff --git a/arch/platform/z1/dev/temperature-sensor.c b/arch/platform/z1/dev/temperature-sensor.c
new file mode 100644
index 0000000000000000000000000000000000000000..1d4328d24899ee10543bf460b07a18d18ec6d01c
--- /dev/null
+++ b/arch/platform/z1/dev/temperature-sensor.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2010, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ *
+ */
+
+/**
+ * \file
+ *         Sensor driver for reading the built-in temperature sensor in the CPU.
+ * \author
+ *         Adam Dunkels <adam@sics.se>
+ *         Joakim Eriksson <joakime@sics.se>
+ *         Niclas Finne <nfi@sics.se>
+ */
+
+#include "dev/temperature-sensor.h"
+#include "dev/sky-sensors.h"
+#include "contiki.h"
+
+#define INPUT_CHANNEL      (1 << INCH_10)
+#define INPUT_REFERENCE    SREF_1
+#define TEMPERATURE_MEM    ADC12MEM10
+
+const struct sensors_sensor temperature_sensor;
+
+/*---------------------------------------------------------------------------*/
+static int
+value(int type)
+{
+  return TEMPERATURE_MEM;
+}
+/*---------------------------------------------------------------------------*/
+static int
+configure(int type, int c)
+{
+  return sky_sensors_configure(INPUT_CHANNEL, INPUT_REFERENCE, type, c);
+}
+/*---------------------------------------------------------------------------*/
+static int
+status(int type)
+{
+  return sky_sensors_status(INPUT_CHANNEL, type);
+}
+/*---------------------------------------------------------------------------*/
+SENSORS_SENSOR(temperature_sensor, TEMPERATURE_SENSOR,
+               value, configure, status);
diff --git a/tools/sky/uip6-bridge/project-conf.h b/arch/platform/z1/dev/temperature-sensor.h
similarity index 81%
rename from tools/sky/uip6-bridge/project-conf.h
rename to arch/platform/z1/dev/temperature-sensor.h
index 651d45cdaaef72e782ce4f8a1d0a35b9d49a8fde..05eafe8525538ea25be86b87d0ccca1c2c2254f0 100644
--- a/tools/sky/uip6-bridge/project-conf.h
+++ b/arch/platform/z1/dev/temperature-sensor.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, Swedish Institute of Computer Science.
+ * Copyright (c) 2010, Swedish Institute of Computer Science.
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -30,20 +30,20 @@
 
 /**
  * \file
- *         A brief description of what this file is
+ *         Temperature sensor header file.
  * \author
- *         Niclas Finne <nfi@sics.se>
+ *         Adam Dunkels <adam@sics.se>
  *         Joakim Eriksson <joakime@sics.se>
+ *         Niclas Finne <nfi@sics.se>
  */
 
-#ifndef BRIDGE_CONF_H_
-#define BRIDGE_CONF_H_
+#ifndef TEMPERATURE_SENSOR_H_
+#define TEMPERATURE_SENSOR_H_
+
+#include "lib/sensors.h"
 
-#undef UIP_CONF_ROUTER
+extern const struct sensors_sensor temperature_sensor;
 
-#undef UIP_CONF_LLH_LEN
-#define UIP_CONF_LLH_LEN         14
+#define TEMPERATURE_SENSOR "Temperature"
 
-#undef UIP_CONF_BUFFER_SIZE
-#define UIP_CONF_BUFFER_SIZE  256
-#endif /* BRIDGE_CONF_H_ */
+#endif /* TEMPERATURE_SENSOR_H_ */
diff --git a/arch/platform/z1/dev/tlc59116.c b/arch/platform/z1/dev/tlc59116.c
new file mode 100644
index 0000000000000000000000000000000000000000..2db0bf09345ab05aceac661aa42a7a2bde584ffe
--- /dev/null
+++ b/arch/platform/z1/dev/tlc59116.c
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2013, Jelmer Tiete.
+ * 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 Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *         Device drivers for tlc59116 i2c led driver on Zolertia Z1.
+ *         See http://www.ti.com/product/tlc59116 for datasheet.
+ * \author
+ *         Jelmer Tiete, VUB <jelmer@tiete.be>
+ */
+
+#include <stdio.h>
+#include "contiki.h"
+#include "tlc59116.h"
+#include "i2cmaster.h"
+
+/*---------------------------------------------------------------------------*/
+/* Write to a register.
+ *  args:
+ *    reg       register to write to
+ *    val       value to write
+ */
+
+void
+tlc59116_write_reg(uint8_t reg, uint8_t val)
+{
+  uint8_t tx_buf[] = { reg, val };
+
+  i2c_transmitinit(TLC59116_ADDR);
+  while(i2c_busy());
+  PRINTFDEBUG("I2C Ready to TX\n");
+
+  i2c_transmit_n(2, tx_buf);
+  while(i2c_busy());
+  PRINTFDEBUG("WRITE_REG 0x%02X @ reg 0x%02X\n", val, reg);
+}
+/*---------------------------------------------------------------------------*/
+/* Write several registers from a stream.
+ *  args:
+ *    len       number of bytes to write
+ *    data      pointer to where the data is written from
+ *
+ * First byte in stream must be the register address to begin writing to.
+ * The data is then written from second byte and increasing.
+ */
+
+void
+tlc59116_write_stream(uint8_t len, uint8_t *data)
+{
+  i2c_transmitinit(TLC59116_ADDR);
+  while(i2c_busy());
+  PRINTFDEBUG("I2C Ready to TX(stream)\n");
+
+  i2c_transmit_n(len, data);    /* start tx and send conf reg */
+  while(i2c_busy());
+  PRINTFDEBUG("WRITE_STR %u B to 0x%02X\n", len, data[0]);
+}
+/*---------------------------------------------------------------------------*/
+/* Read one register.
+ *  args:
+ *    reg       what register to read
+ *  returns the value of the read register
+ */
+
+uint8_t
+tlc59116_read_reg(uint8_t reg)
+{
+  uint8_t retVal = 0;
+  uint8_t rtx = reg;
+
+  PRINTFDEBUG("READ_REG 0x%02X\n", reg);
+
+  /* transmit the register to read */
+  i2c_transmitinit(TLC59116_ADDR);
+  while(i2c_busy());
+  i2c_transmit_n(1, &rtx);
+  while(i2c_busy());
+
+  /* receive the data */
+  i2c_receiveinit(TLC59116_ADDR);
+  while(i2c_busy());
+  i2c_receive_n(1, &retVal);
+  while(i2c_busy());
+
+  return retVal;
+}
+/*---------------------------------------------------------------------------*/
+/* Read several registers in a stream.
+ *  args:
+ *    reg       what register to start reading from
+ *    len       number of bytes to read
+ *    whereto   pointer to where the data is saved
+ */
+
+void
+tlc59116_read_stream(uint8_t reg, uint8_t len, uint8_t *whereto)
+{
+  uint8_t rtx = reg;
+
+  PRINTFDEBUG("READ_STR %u B from 0x%02X\n", len, reg);
+
+  /* transmit the register to start reading from */
+  i2c_transmitinit(TLC59116_ADDR);
+  while(i2c_busy());
+  i2c_transmit_n(1, &rtx);
+  while(i2c_busy());
+
+  /* receive the data */
+  i2c_receiveinit(TLC59116_ADDR);
+  while(i2c_busy());
+  i2c_receive_n(len, whereto);
+  while(i2c_busy());
+}
+/*---------------------------------------------------------------------------*/
+/* Set pwm value for individual led. Make sure PWM mode is enabled.
+ *  args:
+ *    led       led output -> 0 till 15
+ *    pwm       led pwm value
+ */
+
+void
+tlc59116_led(uint8_t led, uint8_t pwm)
+{
+  if((led < 0) || (led > 15)) {
+    PRINTFDEBUG("TLC59116: wrong led value.");
+  } else {
+    tlc59116_write_reg(led + TLC59116_PWM0, pwm);
+  }
+}
+/*---------------------------------------------------------------------------*/
+/* Init the led driver: ports, pins, registers, interrupts (none enabled), I2C,
+ * default threshold values etc.
+ */
+
+void
+tlc59116_init(void)
+{
+  /* Set up ports and pins for I2C communication */
+  i2c_enable();
+
+  /* set default register values. */
+  tlc59116_write_reg(TLC59116_MODE1, TLC59116_MODE1_DEFAULT);
+  tlc59116_write_reg(TLC59116_MODE2, TLC59116_MODE2_DEFAULT);
+
+  /*Set all PWM values to 0x00 (off) */
+  /*This would maybe be better with a SWRST */
+  uint8_t tx_buf[] =
+  { TLC59116_PWM0_AUTOINCR, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+  tlc59116_write_stream(17, tx_buf);
+
+  /* set all leds to PWM control */
+  tlc59116_write_reg(TLC59116_LEDOUT0, TLC59116_LEDOUT_PWM);
+  tlc59116_write_reg(TLC59116_LEDOUT1, TLC59116_LEDOUT_PWM);
+  tlc59116_write_reg(TLC59116_LEDOUT2, TLC59116_LEDOUT_PWM);
+  tlc59116_write_reg(TLC59116_LEDOUT3, TLC59116_LEDOUT_PWM);
+}
diff --git a/arch/platform/z1/dev/tlc59116.h b/arch/platform/z1/dev/tlc59116.h
new file mode 100644
index 0000000000000000000000000000000000000000..c5b74f76a7da9c265477eab57e0a4e42ffd9c1a9
--- /dev/null
+++ b/arch/platform/z1/dev/tlc59116.h
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) 2013, Jelmer Tiete.
+ * 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 Contiki operating system.
+ * 
+ */
+
+/**
+ * \file
+ *         Device drivers header file for TLC59116 i2c led driver on Zolertia Z1.
+ *         See http://www.ti.com/product/tlc59116 for datasheet.
+ * \author
+ *         Jelmer Tiete, VUB <jelmer@tiete.be>
+ */
+
+#ifndef TLC59116_H_
+#define TLC59116_H_
+#include <stdio.h>
+#include "dev/i2cmaster.h"
+
+#if 0
+#include <stdio.h>
+#define PRINTFDEBUG(...) printf(__VA_ARGS__)
+#else
+#define PRINTFDEBUG(...)
+#endif
+
+
+/* -------------------------------------------------------------------------- */
+/* Init the led driver: ports, pins, registers, I2C*/
+void tlc59116_init(void);
+
+/* Write to a register.
+ *  args:
+ *    reg       register to write to
+ *    val       value to write
+ */
+void tlc59116_write_reg(uint8_t reg, uint8_t val);
+
+/* Write several registers from a stream.
+ *  args:
+ *    len       number of bytes to read
+ *    data      pointer to where the data is read from
+ * First byte in stream must be the register address to begin writing to.
+ * The data is then written from the second byte and increasing. The address byte
+ * is not included in length len.
+ */
+void tlc59116_write_stream(uint8_t len, uint8_t * data);
+
+/* Read one register.
+ *  args:
+ *    reg       what register to read
+ *  returns the value of the read register
+ */
+uint8_t tlc59116_read_reg(uint8_t reg);
+
+/* Read several registers in a stream.
+ *  args:
+ *    reg       what register to start reading from
+ *    len       number of bytes to read
+ *    whereto   pointer to where the data is saved
+ */
+void tlc59116_read_stream(uint8_t reg, uint8_t len, uint8_t * whereto);
+
+/* Set pwm value for individual led
+ *  args:
+ *    led       led output -> 0 till 15
+ *    pwm       led pwm value
+ */
+void tlc59116_led(uint8_t led, uint8_t pwm);
+
+
+/* -------------------------------------------------------------------------- */
+/* Application definitions, change if required by application. */
+
+/* Suggested defaults according to the data sheet etc */
+#define TLC59116_MODE1_DEFAULT   0x00   /* Default (no sub or all call) + OSC on */
+#define TLC59116_MODE2_DEFAULT   0x00   /* Default (output change on stop) */
+
+#define TLC59116_LEDOUT_PWM      0xAA   /* LDRx = 01 -> PWM; 4 leds per reg: 01010101b -> 0xAA */
+
+/* -------------------------------------------------------------------------- */
+/* Reference definitions, should not be changed */
+/* TLC59116 slave address */
+#define TLC59116_ADDR            0x60   /* 7bit adress, 8bit write adress: 0xC0 */
+                                        /* address with all address pins pulled to ground */
+/* TLC59116 registers */
+#define TLC59116_MODE1           0x00
+#define TLC59116_MODE2           0x01
+#define TLC59116_PWM0_AUTOINCR   0xA2   /* auto increment address for first pwm register */
+#define TLC59116_PWM0            0x02
+#define TLC59116_PWM1            0x03
+#define TLC59116_PWM2            0x04
+#define TLC59116_PWM3            0x05
+#define TLC59116_PWM4            0x06
+#define TLC59116_PWM5            0x07
+#define TLC59116_PWM6            0x08
+#define TLC59116_PWM7            0x09
+#define TLC59116_PWM8            0x0A
+#define TLC59116_PWM9            0x0B
+#define TLC59116_PWM10           0x0C
+#define TLC59116_PWM11           0x0D
+#define TLC59116_PWM12           0x0E
+#define TLC59116_PWM13           0x0F
+#define TLC59116_PWM14           0x10
+#define TLC59116_PWM15           0x11
+#define TLC59116_GRPPWM          0x12
+#define TLC59116_GRPFREQ         0x13
+#define TLC59116_LEDOUT0         0x14
+#define TLC59116_LEDOUT1         0x15
+#define TLC59116_LEDOUT2         0x16
+#define TLC59116_LEDOUT3         0x17
+
+/* More registers follow, but not used in this implementation */
+
+/* -------------------------------------------------------------------------- */
+#endif /* ifndef TLC59116_H_ */
diff --git a/arch/platform/z1/dev/tmp102.c b/arch/platform/z1/dev/tmp102.c
new file mode 100644
index 0000000000000000000000000000000000000000..4bf267246aef549039e322e1bf6f953962dbec12
--- /dev/null
+++ b/arch/platform/z1/dev/tmp102.c
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2010, Swedish Institute of Computer Science.
+ * Copyright (c) 2016, Zolertia <http://www.zolertia.com>
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+/*---------------------------------------------------------------------------*/
+/**
+ * \file
+ *         Device drivers for tmp102 temperature sensor in Zolertia Z1.
+ * \author
+ *         Enric M. Calvo, Zolertia <ecalvo@zolertia.com>
+ *         Marcus Lundén, SICS <mlunden@sics.se>
+ *         Antonio Lignan, Zolertia <alinan@zolertia.com>
+ */
+/*---------------------------------------------------------------------------*/
+#include <stdio.h>
+#include "contiki.h"
+#include "i2cmaster.h"
+#include "tmp102.h"
+#include "lib/sensors.h"
+/*---------------------------------------------------------------------------*/
+#define DEBUG 0
+#if DEBUG
+#define PRINTF(...) printf(__VA_ARGS__)
+#else
+#define PRINTF(...)
+#endif
+/*---------------------------------------------------------------------------*/
+static uint8_t enabled;
+/*---------------------------------------------------------------------------*/
+void
+tmp102_init(void)
+{
+  /* Power Up TMP102 via pin */
+  TMP102_PWR_DIR |= TMP102_PWR_PIN;
+  TMP102_PWR_SEL &= ~TMP102_PWR_SEL;
+  TMP102_PWR_SEL2 &= ~TMP102_PWR_SEL;
+  TMP102_PWR_REN &= ~TMP102_PWR_SEL;
+  TMP102_PWR_OUT |= TMP102_PWR_PIN;
+
+  /* Set up ports and pins for I2C communication */
+  i2c_enable();
+
+  enabled = 1;
+}
+/*---------------------------------------------------------------------------*/
+void
+tmp102_stop(void)
+{
+  /* Power off */
+  TMP102_PWR_OUT &= ~TMP102_PWR_PIN;
+  enabled = 0;
+}
+/*---------------------------------------------------------------------------*/
+void
+tmp102_write_reg(uint8_t reg, uint16_t val)
+{
+  uint8_t tx_buf[] = { reg, 0x00, 0x00 };
+
+  tx_buf[1] = (uint8_t)(val >> 8);
+  tx_buf[2] = (uint8_t)(val & 0x00FF);
+
+  i2c_transmitinit(TMP102_ADDR);
+  while(i2c_busy());
+  PRINTF("I2C Ready to TX\n");
+
+  i2c_transmit_n(3, tx_buf);
+  while(i2c_busy());
+  PRINTF("WRITE_REG 0x%04X @ reg 0x%02X\n", val, reg);
+}
+/*---------------------------------------------------------------------------*/
+uint16_t
+tmp102_read_reg(uint8_t reg)
+{
+  uint8_t buf[] = { 0x00, 0x00 };
+  uint16_t retVal = 0;
+  uint8_t rtx = reg;
+  PRINTF("READ_REG 0x%02X\n", reg);
+
+  /* transmit the register to read */
+  i2c_transmitinit(TMP102_ADDR);
+  while(i2c_busy());
+  i2c_transmit_n(1, &rtx);
+  while(i2c_busy());
+
+  /* receive the data */
+  i2c_receiveinit(TMP102_ADDR);
+  while(i2c_busy());
+  i2c_receive_n(2, &buf[0]);
+  while(i2c_busy());
+
+  retVal = (uint16_t)(buf[0] << 8 | (buf[1]));
+
+  return retVal;
+}
+/*---------------------------------------------------------------------------*/
+uint16_t
+tmp102_read_temp_raw(void)
+{
+  uint16_t rd = 0;
+  rd = tmp102_read_reg(TMP102_TEMP);
+  return rd;
+}
+/*---------------------------------------------------------------------------*/
+int16_t
+tmp102_read_temp_x100(void)
+{
+  int16_t raw = 0;
+  int16_t sign = 1;
+  int16_t abstemp, temp_int;
+
+  raw = (int16_t)tmp102_read_reg(TMP102_TEMP);
+  if(raw < 0) {
+    abstemp = (raw ^ 0xFFFF) + 1;
+    sign = -1;
+  } else {
+    abstemp = raw;
+  }
+
+  /* Integer part of the temperature value and percents*/
+  temp_int = (abstemp >> 8) * sign * 100;
+  temp_int += ((abstemp & 0xff) * 100) / 0x100;
+  return temp_int;
+}
+/*---------------------------------------------------------------------------*/
+int8_t
+tmp102_read_temp_simple(void)
+{
+  /* Casted to int8_t: We don't expect temperatures outside -128 to 127 C */
+  return tmp102_read_temp_x100() / 100;
+}
+/*---------------------------------------------------------------------------*/
+static int
+configure(int type, int value)
+{
+  if(type != SENSORS_ACTIVE) {
+    return TMP102_ERROR;
+  }
+  if(value) {
+    tmp102_init();
+  } else {
+    tmp102_stop();
+  }
+  enabled = value;
+  return TMP102_SUCCESS;
+}
+/*---------------------------------------------------------------------------*/
+static int
+status(int type)
+{
+  switch(type) {
+  case SENSORS_ACTIVE:
+  case SENSORS_READY:
+    return enabled;
+  }
+  return TMP102_SUCCESS;
+}
+/*---------------------------------------------------------------------------*/
+static int
+value(int type)
+{
+  return (int)tmp102_read_temp_x100();
+}
+/*---------------------------------------------------------------------------*/
+SENSORS_SENSOR(tmp102, TMP102_SENSOR, value, configure, status);
+/*---------------------------------------------------------------------------*/
diff --git a/arch/platform/z1/dev/tmp102.h b/arch/platform/z1/dev/tmp102.h
new file mode 100644
index 0000000000000000000000000000000000000000..cf7a71eb86989a74d1e642546f1a4cc17ba8b871
--- /dev/null
+++ b/arch/platform/z1/dev/tmp102.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2010, Swedish Institute of Computer Science.
+ * Copyright (c) 2016, Zolertia <http://www.zolertia.com>
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *         Device drivers header file for tmp102 temperature sensor in Zolertia
+ *         Z1 WSN Platform.
+ * \author
+ *         Enric M. Calvo, Zolertia <ecalvo@zolertia.com>
+ *         Marcus Lundén, SICS <mlunden@sics.se>
+ *         Antonio Lignan, Zolertia <alinan@zolertia.com>
+ */
+/* -------------------------------------------------------------------------- */
+#ifndef TMP102_H_
+#define TMP102_H_
+#include <stdio.h>
+#include "lib/sensors.h"
+#include "i2cmaster.h"
+/* -------------------------------------------------------------------------- */
+void tmp102_init(void);
+void tmp102_write_reg(uint8_t reg, uint16_t val);
+uint16_t tmp102_read_reg(uint8_t reg);
+uint16_t tmp102_read_temp_raw();
+int8_t tmp102_read_temp_simple();
+int16_t tmp102_read_temp_x100();
+/* -------------------------------------------------------------------------- */
+#define TMP102_ADDR           0x48
+#define TMP102_TEMP           0x00
+#define TMP102_CONF           0x01    
+#define TMP102_TLOW           0x02    
+#define TMP102_THIGH          0x03   
+
+/* TMP102 pin-out */
+#define TMP102_PWR_DIR        P5DIR
+#define TMP102_PWR_SEL        P5SEL
+#define TMP102_PWR_SEL2       P5SEL2
+#define TMP102_PWR_REN        P5REN
+#define TMP102_PWR_OUT        P5OUT
+#define TMP102_PWR_PIN        (1<<0) /* P5.0 */
+/* -------------------------------------------------------------------------- */
+#define TMP102_SUCCESS        0
+#define TMP102_ERROR          (-1)
+#define TMP102_READ           0x01
+/* -------------------------------------------------------------------------- */
+#define TMP102_SENSOR         "TMP102 sensor"
+/* -------------------------------------------------------------------------- */
+extern const struct sensors_sensor tmp102;
+/* -------------------------------------------------------------------------- */
+#endif /* ifndef TMP102_H_ */
diff --git a/arch/platform/z1/dev/xmem.c b/arch/platform/z1/dev/xmem.c
new file mode 100644
index 0000000000000000000000000000000000000000..89ca9c17b6838d2fe02e2cda7063931681f0a4a9
--- /dev/null
+++ b/arch/platform/z1/dev/xmem.c
@@ -0,0 +1,256 @@
+/*
+ * Copyright (c) 2006, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ *
+ */
+
+/**
+ * \file
+ *         Device driver for the ST M25P16 40MHz 1Mbyte external memory.
+ * \author
+ *         Bj�rn Gr�nvall <bg@sics.se>
+ *         Enric M. Calvo <ecalvo@zolertia.com>
+ *
+ *         Data is written bit inverted (~-operator) to flash so that
+ *         unwritten data will read as zeros (UNIX style).
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "contiki.h"
+#include "dev/spi-legacy.h"
+#include "dev/xmem.h"
+#include "dev/watchdog.h"
+
+#if 1
+#define PRINTF(...) printf(__VA_ARGS__)
+#else
+#define PRINTF(...) do {} while (0)
+#endif
+
+#define  SPI_FLASH_INS_WREN        0x06
+#define  SPI_FLASH_INS_WRDI        0x04
+#define  SPI_FLASH_INS_RDSR        0x05
+#define  SPI_FLASH_INS_WRSR        0x01
+#define  SPI_FLASH_INS_READ        0x03
+#define  SPI_FLASH_INS_FAST_READ   0x0b
+#define  SPI_FLASH_INS_PP          0x02
+#define  SPI_FLASH_INS_SE          0xd8
+#define  SPI_FLASH_INS_BE          0xc7
+#define  SPI_FLASH_INS_DP          0xb9
+#define  SPI_FLASH_INS_RES         0xab
+/*---------------------------------------------------------------------------*/
+static void
+write_enable(void)
+{
+  int s;
+
+  s = splhigh();
+  SPI_FLASH_ENABLE();
+  
+  SPI_WRITE(SPI_FLASH_INS_WREN);
+
+  SPI_FLASH_DISABLE();
+  splx(s);
+}
+/*---------------------------------------------------------------------------*/
+static unsigned
+read_status_register(void)
+{
+  unsigned char u;
+
+  int s;
+
+  s = splhigh();
+  SPI_FLASH_ENABLE();
+  
+
+  SPI_WRITE(SPI_FLASH_INS_RDSR);
+
+  SPI_FLUSH();
+  SPI_READ(u);
+
+  SPI_FLASH_DISABLE();
+  splx(s);
+
+  return u;
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * Wait for a write/erase operation to finish.
+ */
+static unsigned
+wait_ready(void)
+{
+  unsigned u;
+  do {
+    u = read_status_register();
+    watchdog_periodic();
+  } while(u & 0x01);		/* WIP=1, write in progress */
+  return u;
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * Erase 64k bytes of data. It takes about 1s before WIP goes low!
+ */
+static void
+erase_sector(unsigned long offset)
+{
+  int s;
+  wait_ready();
+
+  write_enable();
+
+  s = splhigh();
+  SPI_FLASH_ENABLE();
+  
+  SPI_WRITE_FAST(SPI_FLASH_INS_SE);
+  SPI_WRITE_FAST(offset >> 16);	/* MSB */
+  SPI_WRITE_FAST(offset >> 8);
+  SPI_WRITE_FAST(offset >> 0);	/* LSB */
+  SPI_WAITFORTx_ENDED();
+
+  SPI_FLASH_DISABLE();
+  splx(s);
+}
+/*---------------------------------------------------------------------------*/
+/*
+ * Initialize external flash *and* SPI bus!
+ */
+void
+xmem_init(void)
+{
+  spi_init();
+
+  P4DIR |= BV(FLASH_CS);   /* Unnecessary for Zolertia Z1  | BV(FLASH_PWR); */
+  P5DIR |= BV(FLASH_HOLD); /* In P5 for Z1 */
+
+  SPI_FLASH_DISABLE();		/* Unselect flash. */
+  SPI_FLASH_UNHOLD();
+}
+/*---------------------------------------------------------------------------*/
+int
+xmem_pread(void *_p, int size, unsigned long offset)
+{
+  unsigned char *p = _p;
+  const unsigned char *end = p + size;
+  int s;
+  wait_ready();
+
+  s = splhigh();
+  SPI_FLASH_ENABLE();
+
+  SPI_WRITE_FAST(SPI_FLASH_INS_READ);
+  SPI_WRITE_FAST(offset >> 16);	/* MSB */
+  SPI_WRITE_FAST(offset >> 8);
+  SPI_WRITE_FAST(offset >> 0);	/* LSB */
+  SPI_WAITFORTx_ENDED();
+  
+  SPI_FLUSH();
+  for(; p < end; p++) {
+    unsigned char u;
+    SPI_READ(u);
+    *p = ~u;
+  }
+
+  SPI_FLASH_DISABLE();
+  splx(s);
+
+  return size;
+}
+/*---------------------------------------------------------------------------*/
+static const unsigned char *
+program_page(unsigned long offset, const unsigned char *p, int nbytes)
+{
+  const unsigned char *end = p + nbytes;
+  int s;
+
+  wait_ready();
+
+  write_enable();
+
+  s = splhigh();
+  SPI_FLASH_ENABLE();
+  
+  SPI_WRITE_FAST(SPI_FLASH_INS_PP);
+  SPI_WRITE_FAST(offset >> 16);	/* MSB */
+  SPI_WRITE_FAST(offset >> 8);
+  SPI_WRITE_FAST(offset >> 0);	/* LSB */
+
+  for(; p < end; p++) {
+    SPI_WRITE_FAST(~*p);
+  }
+  SPI_WAITFORTx_ENDED();
+
+  SPI_FLASH_DISABLE();
+  splx(s);
+
+  return p;
+}
+/*---------------------------------------------------------------------------*/
+int
+xmem_pwrite(const void *_buf, int size, unsigned long addr)
+{
+  const unsigned char *p = _buf;
+  const unsigned long end = addr + size;
+  unsigned long i, next_page;
+ 
+  for(i = addr; i < end;) {
+    next_page = (i | 0xff) + 1;
+    if(next_page > end) {
+      next_page = end;
+    }
+    p = program_page(i, p, next_page - i);
+    i = next_page;
+  }
+
+  return size;
+}
+/*---------------------------------------------------------------------------*/
+int
+xmem_erase(long size, unsigned long addr)
+{
+  unsigned long end = addr + size;
+
+  if(size % XMEM_ERASE_UNIT_SIZE != 0) {
+    PRINTF("xmem_erase: bad size\n");
+    return -1;
+  }
+
+  if(addr % XMEM_ERASE_UNIT_SIZE != 0) {
+    PRINTF("xmem_erase: bad offset\n");
+    return -1;
+  }
+
+  for (; addr < end; addr += XMEM_ERASE_UNIT_SIZE) {
+    erase_sector(addr);
+  }
+
+  return size;
+}
+/*---------------------------------------------------------------------------*/
diff --git a/arch/platform/z1/dev/z1-phidgets.c b/arch/platform/z1/dev/z1-phidgets.c
new file mode 100644
index 0000000000000000000000000000000000000000..e86c3e2f00bdc26b31c181d9ade91d12ed61f448
--- /dev/null
+++ b/arch/platform/z1/dev/z1-phidgets.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright (c) 2010, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ *
+ * -----------------------------------------------------------------
+ *
+ * Author  : Joakim Eriksson
+ * Created : 2010-02-02
+ * Updated : $Date: 2010/11/05 10:31:57 $
+ *           $Revision: 1.3 $
+ */
+
+#include "contiki.h"
+#include "lib/sensors.h"
+#include "dev/z1-phidgets.h"
+
+static uint8_t adc_on;
+static uint8_t active;
+/*---------------------------------------------------------------------------*/
+static void
+sensors_activate(uint8_t type)
+{
+  uint8_t pre = adc_on;
+
+  adc_on |= type;
+
+  if(pre == 0 && adc_on > 0) {
+    P6DIR = 0xff;
+    P6OUT = 0x00;
+    P6SEL |= 0x8b; /* bit 7 + 3 + 1 + 0 */
+
+    /* if nothing was started before, start up the ADC system */
+    /* Set up the ADC. */
+    ADC12CTL0 = REF2_5V + SHT0_6 + SHT1_6 + MSC; /* Setup ADC12, ref., sampling time */
+    ADC12CTL1 = SHP + CONSEQ_3 + CSTARTADD_0;	/* Use sampling timer, repeat-sequenc-of-channels */
+    /* convert up to MEM4 */
+    ADC12MCTL4 |= EOS;
+
+    ADC12CTL0 |= ADC12ON + REFON;
+    ADC12CTL0 |= ENC;		/* enable conversion */
+    ADC12CTL0 |= ADC12SC;		/* sample & convert */
+  }
+}
+/*---------------------------------------------------------------------------*/
+static void
+sensors_deactivate(uint8_t type)
+{
+  adc_on &= ~type;
+
+  if(adc_on == 0) {
+    /* stop converting immediately, turn off reference voltage, etc. */
+    /* wait for conversion to stop */
+
+    ADC12CTL0 &= ~ENC;
+    /* need to remove CONSEQ_3 if not EOS is configured */
+    ADC12CTL1 &= ~CONSEQ_3;
+
+    while(ADC12CTL1 & ADC12BUSY);
+
+    ADC12CTL0 = 0;
+    ADC12CTL1 = 0;
+
+    P6DIR = 0x00;
+    P6OUT = 0x00;
+    P6SEL = 0x00;
+  }
+}
+/*---------------------------------------------------------------------------*/
+static int
+value(int type)
+{
+  /* ADC0 corresponds to the port under the logo, ADC1 to the port over the logo,
+     ADC2 and ADC3 corresponds to port on the JCreate bottom expansion port) */
+  switch(type) {
+    case PHIDGET5V_1:
+      return ADC12MEM0;
+    case PHIDGET5V_2:
+      return ADC12MEM1;
+    case PHIDGET3V_1:
+      return ADC12MEM2;
+    case PHIDGET3V_2:
+      return ADC12MEM3;
+  }
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
+static int
+status(int type)
+{
+  switch(type) {
+    case SENSORS_ACTIVE:
+    case SENSORS_READY:
+      return active;
+  }
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
+static int
+configure(int type, int c)
+{
+  switch(type) {
+    case SENSORS_ACTIVE:
+      if(c) {
+        if(!status(SENSORS_ACTIVE)) {
+          /* SREF_1 is Vref+ */
+          /* MemReg6 == P6.0/A0 == 5V 1  */
+          ADC12MCTL0 = (INCH_0 + SREF_0);
+          /* MemReg7 == P6.3/A3 == 5V 2 */
+          ADC12MCTL1 = (INCH_3 + SREF_0);
+          /* MemReg8 == P6.1/A1 == 3V 1 */
+          ADC12MCTL2 = (INCH_1 + SREF_0);
+          /* MemReg9 == P6.7/A7 == 3V_2 */
+          ADC12MCTL3 = (INCH_7 + SREF_0);
+
+          sensors_activate(0x0F);
+          active = 1;
+        }
+      } else {
+        sensors_deactivate(0x0F);
+        active = 0;
+      }
+  }
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
+SENSORS_SENSOR(phidgets, "Phidgets", value, configure, status);
diff --git a/arch/platform/z1/dev/z1-phidgets.h b/arch/platform/z1/dev/z1-phidgets.h
new file mode 100644
index 0000000000000000000000000000000000000000..f56356508cc2b938625c2306cf68f4a9421cd1f1
--- /dev/null
+++ b/arch/platform/z1/dev/z1-phidgets.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2010, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ *
+ * -----------------------------------------------------------------
+ *
+ * Author  : Joakim Eriksson
+ * Created : 2010-08-26
+ * Updated : $Date: 2010/08/27 12:58:57 $
+ *           $Revision: 1.2 $
+ */
+#ifndef Z1_PHIDGETS_H_
+#define Z1_PHIDGETS_H_
+
+#define PHIDGET5V_1 0
+#define PHIDGET5V_2 1
+#define PHIDGET3V_1 2
+#define PHIDGET3V_2 3
+
+extern const struct sensors_sensor phidgets;
+
+#endif /* Z1_PHIDGETS_H_ */
diff --git a/arch/platform/z1/dev/z1-sensors.c b/arch/platform/z1/dev/z1-sensors.c
new file mode 100644
index 0000000000000000000000000000000000000000..db5b418b9f356ef1b8f0b9762fcee6727f573865
--- /dev/null
+++ b/arch/platform/z1/dev/z1-sensors.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, Zolertia - http://www.zolertia.com
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/*---------------------------------------------------------------------------*/
+/**
+ * \file
+ *         Zolertia Z1 on-board sensors
+ * \author
+ *         Antonio Lignan, Zolertia <alinan@zolertia.com>
+ */
+/*---------------------------------------------------------------------------*/
+#include "contiki.h"
+#include "lib/sensors.h"
+#include "dev/button-sensor.h"
+#include "dev/tmp102.h"
+#include "dev/adxl345.h"
+/*---------------------------------------------------------------------------*/
+/** \brief Exports global symbols for the sensor API */
+SENSORS(&button_sensor, &adxl345, &tmp102);
+/*---------------------------------------------------------------------------*/
diff --git a/arch/platform/z1/node-id-z1.c b/arch/platform/z1/node-id-z1.c
new file mode 100644
index 0000000000000000000000000000000000000000..7f65e2c58039e31a97a70b51523a7cc863a4af2a
--- /dev/null
+++ b/arch/platform/z1/node-id-z1.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2006, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *         Utility to store a node id in the external flash
+ * \author
+ *         Adam Dunkels <adam@sics.se>
+ */
+
+#include "contiki.h"
+#include "sys/node-id.h"
+#include "dev/xmem.h"
+#include <string.h>
+
+unsigned char node_mac[8];
+
+/*---------------------------------------------------------------------------*/
+void
+node_id_z1_restore(void)
+{
+  unsigned char buf[12];
+  xmem_pread(buf, 12, NODE_ID_XMEM_OFFSET);
+  if(buf[0] == 0xad &&
+     buf[1] == 0xde) {
+    node_id = (buf[2] << 8) | buf[3];
+    memcpy(node_mac, &buf[4], 8);
+  } else {
+    node_id = 0;
+  }
+}
+/*---------------------------------------------------------------------------*/
+void
+node_id_z1_burn(unsigned short id)
+{
+  unsigned char buf[12];
+  memset(buf, 0, sizeof(buf));
+  buf[0] = 0xad;
+  buf[1] = 0xde;
+  buf[2] = id >> 8;
+  buf[3] = id & 0xff;
+  xmem_erase(XMEM_ERASE_UNIT_SIZE, NODE_ID_XMEM_OFFSET);
+  xmem_pwrite(buf, 12, NODE_ID_XMEM_OFFSET);
+}
+/*---------------------------------------------------------------------------*/
diff --git a/arch/platform/z1/node-id-z1.h b/arch/platform/z1/node-id-z1.h
new file mode 100644
index 0000000000000000000000000000000000000000..d70c018d68e4a301936f1eb5ef0701eb8a8d1c64
--- /dev/null
+++ b/arch/platform/z1/node-id-z1.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2006, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ */
+
+#ifndef NODE_ID_Z1_H_
+#define NODE_ID_Z1_H_
+
+#include <sys/node-id.h>
+
+void node_id_z1_restore(void);
+void node_id_z1_burn(uint16_t node_id);
+
+#endif /* NODE_ID_Z1_H_ */
diff --git a/arch/platform/z1/platform.c b/arch/platform/z1/platform.c
new file mode 100644
index 0000000000000000000000000000000000000000..0d8d248c5c9b4bb43cf4d52882b31c82b3c3d11c
--- /dev/null
+++ b/arch/platform/z1/platform.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright (c) 2006, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ *
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+
+#include "contiki.h"
+#include "cc2420.h"
+#include "dev/leds.h"
+#include "dev/serial-line.h"
+#include "dev/slip.h"
+#include "dev/uart0.h"
+#include "dev/watchdog.h"
+#include "dev/xmem.h"
+#include "lib/random.h"
+#include "net/netstack.h"
+#include "net/mac/framer/frame802154.h"
+#include "dev/adxl345.h"
+#include "sys/clock.h"
+#include "sys/energest.h"
+
+#if NETSTACK_CONF_WITH_IPV6
+#include "net/ipv6/uip-ds6.h"
+#endif /* NETSTACK_CONF_WITH_IPV6 */
+
+#include "node-id-z1.h"
+#include "cfs-coffee-arch.h"
+#include "cfs/cfs-coffee.h"
+
+extern unsigned char node_mac[8];
+
+#if DCOSYNCH_CONF_ENABLED
+static struct timer mgt_timer;
+#endif
+extern int msp430_dco_required;
+
+#define UIP_OVER_MESH_CHANNEL 8
+#if NETSTACK_CONF_WITH_IPV4
+static uint8_t is_gateway;
+#endif /* NETSTACK_CONF_WITH_IPV4 */
+
+#ifdef EXPERIMENT_SETUP
+#include "experiment-setup.h"
+#endif
+
+void init_platform(void);
+/*---------------------------------------------------------------------------*/
+/* Log configuration */
+#include "sys/log.h"
+#define LOG_MODULE "Z1"
+#define LOG_LEVEL LOG_LEVEL_MAIN
+/*---------------------------------------------------------------------------*/
+#ifdef UART0_CONF_BAUD_RATE
+#define UART0_BAUD_RATE UART0_CONF_BAUD_RATE
+#else
+#define UART0_BAUD_RATE 115200
+#endif
+/*---------------------------------------------------------------------------*/
+#if 0
+int
+force_float_inclusion()
+{
+  extern int __fixsfsi;
+  extern int __floatsisf;
+  extern int __mulsf3;
+  extern int __subsf3;
+
+  return __fixsfsi + __floatsisf + __mulsf3 + __subsf3;
+}
+#endif
+/*---------------------------------------------------------------------------*/
+void
+uip_log(char *msg)
+{
+  puts(msg);
+}
+/*---------------------------------------------------------------------------*/
+#if 0
+void
+force_inclusion(int d1, int d2)
+{
+  snprintf(NULL, 0, "%d", d1 % d2);
+}
+#endif
+/*---------------------------------------------------------------------------*/
+static void
+set_lladdr(void)
+{
+  linkaddr_t addr;
+
+  memset(&addr, 0, sizeof(linkaddr_t));
+#if NETSTACK_CONF_WITH_IPV6
+  memcpy(addr.u8, node_mac, sizeof(addr.u8));
+#else
+  if(node_id == 0) {
+    int i;
+    for(i = 0; i < sizeof(linkaddr_t); ++i) {
+      addr.u8[i] = node_mac[7 - i];
+    }
+  } else {
+    addr.u8[0] = node_id & 0xff;
+    addr.u8[1] = node_id >> 8;
+  }
+#endif
+  linkaddr_set_node_addr(&addr);
+}
+/*---------------------------------------------------------------------------*/
+void
+platform_init_stage_one(void)
+{
+  /*
+   * Initalize hardware.
+   */
+  msp430_cpu_init();
+
+  leds_init();
+  leds_on(LEDS_RED);
+}
+/*---------------------------------------------------------------------------*/
+void
+platform_init_stage_two(void)
+{
+  clock_wait(100);
+
+  uart0_init(BAUD2UBR(UART0_BAUD_RATE)); /* Must come before first printf */
+
+  xmem_init();
+
+  leds_off(LEDS_RED);
+  /*
+   * Hardware initialization done!
+   */
+
+    /* Restore node id if such has been stored in external mem */
+  node_id_z1_restore();
+
+  /* If no MAC address was burned, we use the node id or the Z1 product ID */
+  if(!(node_mac[0] | node_mac[1] | node_mac[2] | node_mac[3] |
+       node_mac[4] | node_mac[5] | node_mac[6] | node_mac[7])) {
+
+#ifdef SERIALNUM
+    if(!node_id) {
+      LOG_INFO("Node id is not set, using Z1 product ID\n");
+      node_id = SERIALNUM;
+    }
+#endif
+    node_mac[0] = 0xc1;  /* Hardcoded for Z1 */
+    node_mac[1] = 0x0c;  /* Hardcoded for Revision C */
+    node_mac[2] = 0x00;  /* Hardcoded to arbitrary even number so that
+                            the 802.15.4 MAC address is compatible with
+                            an Ethernet MAC address - byte 0 (byte 2 in
+                            the DS ID) */
+    node_mac[3] = 0x00;  /* Hardcoded */
+    node_mac[4] = 0x00;  /* Hardcoded */
+    node_mac[5] = 0x00;  /* Hardcoded */
+    node_mac[6] = node_id >> 8;
+    node_mac[7] = node_id & 0xff;
+  }
+
+  /* Overwrite node MAC if desired at compile time */
+#ifdef MACID
+#warning "***** CHANGING DEFAULT MAC *****"
+  node_mac[0] = 0xc1;  /* Hardcoded for Z1 */
+  node_mac[1] = 0x0c;  /* Hardcoded for Revision C */
+  node_mac[2] = 0x00;  /* Hardcoded to arbitrary even number so that
+                          the 802.15.4 MAC address is compatible with
+                          an Ethernet MAC address - byte 0 (byte 2 in
+                          the DS ID) */
+  node_mac[3] = 0x00;  /* Hardcoded */
+  node_mac[4] = 0x00;  /* Hardcoded */
+  node_mac[5] = 0x00;  /* Hardcoded */
+  node_mac[6] = MACID >> 8;
+  node_mac[7] = MACID & 0xff;
+#endif
+
+#ifdef IEEE_802154_MAC_ADDRESS
+  /* for setting "hardcoded" IEEE 802.15.4 MAC addresses */
+  {
+    uint8_t ieee[] = IEEE_802154_MAC_ADDRESS;
+    memcpy(node_mac, ieee, sizeof(uip_lladdr.addr));
+    node_mac[7] = node_id & 0xff;
+  }
+#endif /* IEEE_802154_MAC_ADDRESS */
+
+  random_init(node_mac[6] + node_mac[7]);
+
+  set_lladdr();
+
+  /*
+   * main() will turn the radio on inside netstack_init(). The CC2420
+   * must already be initialised by that time, so we do this here early.
+   * Later on in stage three we set correct values for PANID and radio
+   * short/long address.
+   */
+  cc2420_init();
+
+  SENSORS_ACTIVATE(adxl345);
+
+  leds_off(LEDS_ALL);
+}
+/*---------------------------------------------------------------------------*/
+void
+platform_init_stage_three(void)
+{
+  uint8_t longaddr[8];
+  uint16_t shortaddr;
+
+  init_platform();
+
+  shortaddr = (linkaddr_node_addr.u8[0] << 8) + linkaddr_node_addr.u8[1];
+  memset(longaddr, 0, sizeof(longaddr));
+  linkaddr_copy((linkaddr_t *)&longaddr, &linkaddr_node_addr);
+
+  cc2420_set_pan_addr(IEEE802154_PANID, shortaddr, longaddr);
+
+  LOG_INFO("CC2420 CCA threshold %i\n", CC2420_CONF_CCA_THRESH);
+
+#if DCOSYNCH_CONF_ENABLED
+  timer_set(&mgt_timer, DCOSYNCH_PERIOD * CLOCK_SECOND);
+#endif
+}
+/*---------------------------------------------------------------------------*/  
+void
+platform_idle(void)
+{
+  /*
+   * Idle processing.
+   */
+  int s = splhigh();    /* Disable interrupts. */
+  /* uart0_active is for avoiding LPM3 when still sending or receiving */
+  if(process_nevents() != 0 || uart0_active()) {
+    splx(s);      /* Re-enable interrupts. */
+  } else {
+#if DCOSYNCH_CONF_ENABLED
+    /* before going down to sleep possibly do some management */
+    if(timer_expired(&mgt_timer)) {
+      watchdog_periodic();
+      timer_reset(&mgt_timer);
+      msp430_sync_dco();
+#if CC2420_CONF_SFD_TIMESTAMPS
+      cc2420_arch_sfd_init();
+#endif /* CC2420_CONF_SFD_TIMESTAMPS */
+    }
+#endif
+
+    /* Re-enable interrupts and go to sleep atomically. */
+    ENERGEST_SWITCH(ENERGEST_TYPE_CPU, ENERGEST_TYPE_LPM);
+    watchdog_stop();
+    /* check if the DCO needs to be on - if so - only LPM 1 */
+    if (msp430_dco_required) {
+      _BIS_SR(GIE | CPUOFF); /* LPM1 sleep for DMA to work!. */
+    } else {
+      _BIS_SR(GIE | SCG0 | SCG1 | CPUOFF); /* LPM3 sleep. This
+						statement will block
+						until the CPU is
+						woken up by an
+						interrupt that sets
+						the wake up flag. */
+    }
+    watchdog_start();
+    ENERGEST_SWITCH(ENERGEST_TYPE_LPM, ENERGEST_TYPE_CPU);
+  }
+}
+/*---------------------------------------------------------------------------*/
diff --git a/arch/platform/z1/z1-def.h b/arch/platform/z1/z1-def.h
new file mode 100644
index 0000000000000000000000000000000000000000..e59165ee3915f21577c80bf47d7539ee8fc53994
--- /dev/null
+++ b/arch/platform/z1/z1-def.h
@@ -0,0 +1,287 @@
+/*
+ * Copyright (c) 2010, 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ */
+
+/**
+ * \file
+ *         Platform configuration for the Z1 platform
+ * \author
+ *         Joakim Eriksson <joakime@sics.se>
+ */
+
+#ifndef Z1_DEF_H_
+#define Z1_DEF_H_
+
+#include <iomacros.h>
+
+/*
+ * Definitions below are dictated by the hardware and not really
+ * changeable!
+ */
+
+#define ZOLERTIA_Z1 1  /* Enric */
+
+/* 1 len byte, 2 bytes CRC */
+ #define RADIO_PHY_OVERHEAD         3
+ /* 250kbps data rate. One byte = 32us */
+ #define RADIO_BYTE_AIR_TIME       32
+/* Delay between GO signal and SFD: radio fixed delay + 4Bytes preample + 1B SFD -- 1Byte time is 32us
+ * ~327us + 129preample = 456 us */
+#define RADIO_DELAY_BEFORE_TX ((unsigned)US_TO_RTIMERTICKS(456))
+/* Delay between GO signal and start listening
+ * ~50us delay + 129preample + ?? = 183 us */
+#define RADIO_DELAY_BEFORE_RX ((unsigned)US_TO_RTIMERTICKS(183))
+/* Delay between the SFD finishes arriving and it is detected in software */
+#define RADIO_DELAY_BEFORE_DETECT 0
+
+#define PLATFORM_HAS_LEDS    1
+#define PLATFORM_HAS_BUTTON  1
+#define PLATFORM_HAS_RADIO   1
+#define PLATFORM_HAS_BATTERY 1
+
+/* CPU target speed in Hz */
+#define F_CPU 8000000uL /* 8MHz by default */
+
+/* the low-level radio driver */
+#define NETSTACK_CONF_RADIO   cc2420_driver
+
+/* XXX Temporary place for defines that are lacking in mspgcc4's gpio.h */
+#ifdef __IAR_SYSTEMS_ICC__
+#ifndef P1SEL2_
+#define P1SEL2_              (0x0041u)  /* Port 1 Selection 2*/
+DEFC(P1SEL2, P1SEL2_)
+#endif
+#ifndef P5SEL2_
+#define P5SEL2_              (0x0045u)  /* Port 5 Selection 2*/
+DEFC(P5SEL2, P5SEL2_)
+#endif
+#else /* __IAR_SYSTEMS_ICC__ */
+#ifdef __GNUC__
+#ifndef P1SEL2_
+#define P1SEL2_             0x0041    /* Port 1 Selection 2*/
+sfrb(P1SEL2, P1SEL2_);
+#endif
+#ifndef P5SEL2_
+#define P5SEL2_             0x0045    /* Port 5 Selection 2*/
+sfrb(P5SEL2, P5SEL2_);
+#endif
+#endif /* __GNUC__ */
+#endif /* __IAR_SYSTEMS_ICC__ */
+
+/*
+ * Definitions below are dictated by the hardware and not really
+ * changeable!
+ */
+
+/* LED ports */
+#ifdef Z1_IS_Z1SP
+#define LEDS_PxDIR P4DIR
+#define LEDS_PxOUT P4OUT
+#define LEDS_CONF_RED    0x04
+#define LEDS_CONF_GREEN  0x01
+#define LEDS_CONF_YELLOW 0x80
+#else
+#define LEDS_PxDIR P5DIR
+#define LEDS_PxOUT P5OUT
+#define LEDS_CONF_RED    0x10
+#define LEDS_CONF_GREEN  0x40
+#define LEDS_CONF_YELLOW 0x20
+#endif /* Z1_IS_Z1SP */
+
+#define LEDS_CONF_LEGACY_API 1
+
+/* DCO speed resynchronization for more robust UART, etc. */
+#ifndef DCOSYNCH_CONF_ENABLED
+#define DCOSYNCH_CONF_ENABLED (!(MAC_CONF_WITH_TSCH)) /* TSCH needs timerB
+for SFD timestamping */
+#endif /* DCOSYNCH_CONF_ENABLED */
+
+#ifndef CC2420_CONF_SFD_TIMESTAMPS
+#define CC2420_CONF_SFD_TIMESTAMPS (MAC_CONF_WITH_TSCH) /* TSCH needs SFD timestamping */
+#endif /* CC2420_CONF_SFD_TIMESTAMPS */
+
+#ifndef DCOSYNCH_CONF_PERIOD
+#define DCOSYNCH_CONF_PERIOD 30
+#endif /* DCOSYNCH_CONF_PERIOD */
+
+#define ROM_ERASE_UNIT_SIZE  512
+#define XMEM_ERASE_UNIT_SIZE (64 * 1024L)
+
+#define CFS_CONF_OFFSET_TYPE    long
+
+/* Use the first 64k of external flash for node configuration */
+#define NODE_ID_XMEM_OFFSET     (0 * XMEM_ERASE_UNIT_SIZE)
+
+/* Use the second 64k of external flash for codeprop. */
+#define EEPROMFS_ADDR_CODEPROP  (1 * XMEM_ERASE_UNIT_SIZE)
+
+#define CFS_XMEM_CONF_OFFSET    (2 * XMEM_ERASE_UNIT_SIZE)
+#define CFS_XMEM_CONF_SIZE      (1 * XMEM_ERASE_UNIT_SIZE)
+
+#define CFS_RAM_CONF_SIZE 4096
+
+/*
+ * SPI bus configuration for the Z1 mote.
+ */
+
+/* SPI input/output registers. */
+#define SPI_TXBUF UCB0TXBUF
+#define SPI_RXBUF UCB0RXBUF
+
+/* USART0 Tx ready? */
+#define SPI_WAITFOREOTx() while((UCB0STAT & UCBUSY) != 0)
+/* USART0 Rx ready? */
+#define SPI_WAITFOREORx() while((IFG2 & UCB0RXIFG) == 0)
+/* USART0 Tx buffer ready? */
+#define SPI_WAITFORTxREADY() while((IFG2 & UCB0TXIFG) == 0)
+
+#define MOSI           1  /* P3.1 - Output: SPI Master out - slave in (MOSI) */
+#define MISO           2  /* P3.2 - Input:  SPI Master in - slave out (MISO) */
+#define SCK            3  /* P3.3 - Output: SPI Serial Clock (SCLK) */
+
+/*
+ * SPI bus - M25P80 external flash configuration.
+ */
+/* FLASH_PWR P4.3 Output ALWAYS POWERED ON Z1 */
+#define FLASH_CS  4 /* P4.4 Output */
+#define FLASH_HOLD  7 /* P5.7 Output */
+
+/* Enable/disable flash access to the SPI bus (active low). */
+
+#define SPI_FLASH_ENABLE()  (P4OUT &= ~BV(FLASH_CS))
+#define SPI_FLASH_DISABLE() (P4OUT |= BV(FLASH_CS))
+
+#define SPI_FLASH_HOLD()    (P5OUT &= ~BV(FLASH_HOLD))
+#define SPI_FLASH_UNHOLD()    (P5OUT |= BV(FLASH_HOLD))
+
+/*
+ * SPI bus - CC2420 pin configuration.
+ */
+
+#define CC2420_CONF_SYMBOL_LOOP_COUNT 1302  /* 326us msp430X @ 8MHz */
+
+/* P1.2 - Input: FIFOP from CC2420 */
+#define CC2420_FIFOP_PORT(type)   P1##type
+#define CC2420_FIFOP_PIN          2
+/* P1.3 - Input: FIFO from CC2420 */
+#define CC2420_FIFO_PORT(type)     P1##type
+#define CC2420_FIFO_PIN            3
+/* P1.4 - Input: CCA from CC2420 */
+#define CC2420_CCA_PORT(type)      P1##type
+#define CC2420_CCA_PIN             4
+/* P4.1 - Input:  SFD from CC2420 */
+#define CC2420_SFD_PORT(type)      P4##type
+#define CC2420_SFD_PIN             1
+/* P3.0 - Output: SPI Chip Select (CS_N) */
+#define CC2420_CSN_PORT(type)      P3##type
+#define CC2420_CSN_PIN             0
+/* P4.5 - Output: VREG_EN to CC2420 */
+#define CC2420_VREG_PORT(type)     P4##type
+#define CC2420_VREG_PIN            5
+/* P4.6 - Output: RESET_N to CC2420 */
+#define CC2420_RESET_PORT(type)    P4##type
+#define CC2420_RESET_PIN           6
+
+#define CC2420_IRQ_VECTOR PORT1_VECTOR
+
+/* Pin status. */
+#define CC2420_FIFOP_IS_1 (!!(CC2420_FIFOP_PORT(IN) & BV(CC2420_FIFOP_PIN)))
+#define CC2420_FIFO_IS_1  (!!(CC2420_FIFO_PORT(IN) & BV(CC2420_FIFO_PIN)))
+#define CC2420_CCA_IS_1   (!!(CC2420_CCA_PORT(IN) & BV(CC2420_CCA_PIN)))
+#define CC2420_SFD_IS_1   (!!(CC2420_SFD_PORT(IN) & BV(CC2420_SFD_PIN)))
+
+/* The CC2420 reset pin. */
+#define SET_RESET_INACTIVE()   (CC2420_RESET_PORT(OUT) |= BV(CC2420_RESET_PIN))
+#define SET_RESET_ACTIVE()     (CC2420_RESET_PORT(OUT) &= ~BV(CC2420_RESET_PIN))
+
+/* CC2420 voltage regulator enable pin. */
+#define SET_VREG_ACTIVE()       (CC2420_VREG_PORT(OUT) |= BV(CC2420_VREG_PIN))
+#define SET_VREG_INACTIVE()     (CC2420_VREG_PORT(OUT) &= ~BV(CC2420_VREG_PIN))
+
+/* CC2420 rising edge trigger for external interrupt 0 (FIFOP). */
+#define CC2420_FIFOP_INT_INIT() do { \
+    CC2420_FIFOP_PORT(IES) &= ~BV(CC2420_FIFOP_PIN); \
+    CC2420_CLEAR_FIFOP_INT(); \
+} while(0)
+
+/* FIFOP on external interrupt 0. */
+#define CC2420_ENABLE_FIFOP_INT()  do { CC2420_FIFOP_PORT(IE) |= BV(CC2420_FIFOP_PIN); } while(0)
+#define CC2420_DISABLE_FIFOP_INT() do { CC2420_FIFOP_PORT(IE) &= ~BV(CC2420_FIFOP_PIN); } while(0)
+#define CC2420_CLEAR_FIFOP_INT()   do { CC2420_FIFOP_PORT(IFG) &= ~BV(CC2420_FIFOP_PIN); } while(0)
+
+/*
+ * Enables/disables CC2420 access to the SPI bus (not the bus).
+ * (Chip Select)
+ */
+
+/* ENABLE CSn (active low) */
+#define CC2420_SPI_ENABLE()     (CC2420_CSN_PORT(OUT) &= ~BV(CC2420_CSN_PIN))
+/* DISABLE CSn (active low) */
+#define CC2420_SPI_DISABLE()    (CC2420_CSN_PORT(OUT) |= BV(CC2420_CSN_PIN))
+#define CC2420_SPI_IS_ENABLED() ((CC2420_CSN_PORT(OUT) & BV(CC2420_CSN_PIN)) != BV(CC2420_CSN_PIN))
+
+/*
+ * I2C configuration
+ */
+
+#define I2C_PxDIR   P5DIR
+#define I2C_PxIN    P5IN
+#define I2C_PxOUT   P5OUT
+#define I2C_PxSEL   P5SEL
+#define I2C_PxSEL2  P5SEL2
+#define I2C_PxREN   P5REN
+
+#define I2C_SDA       (1 << 1)    /* SDA == P5.1 */
+#define I2C_SCL       (1 << 2)    /* SCL == P5.2 */
+#define I2C_PRESC_1KHZ_LSB      0x00
+#define I2C_PRESC_1KHZ_MSB      0x20
+#define I2C_PRESC_100KHZ_LSB    0x50
+#define I2C_PRESC_100KHZ_MSB    0x00
+#define I2C_PRESC_400KHZ_LSB    0x14
+#define I2C_PRESC_400KHZ_MSB    0x00
+
+/* Set rate as high as possible by default */
+#ifndef I2C_PRESC_Z1_LSB
+#define I2C_PRESC_Z1_LSB I2C_PRESC_400KHZ_LSB
+#endif
+
+#ifndef I2C_PRESC_Z1_MSB
+#define I2C_PRESC_Z1_MSB I2C_PRESC_400KHZ_MSB
+#endif
+
+/* I2C configuration with RX interrupts */
+#ifdef I2C_CONF_RX_WITH_INTERRUPT
+#define I2C_RX_WITH_INTERRUPT I2C_CONF_RX_WITH_INTERRUPT
+#else /* I2C_CONF_RX_WITH_INTERRUPT */
+#define I2C_RX_WITH_INTERRUPT 1
+#endif /* I2C_CONF_RX_WITH_INTERRUPT */
+
+/* Platform-specific define for the end of the stack region */
+#define STACK_CONF_ORIGIN     ((void *)0x3100)
+
+#endif /* PLATFORM_CONF_H_ */
diff --git a/arch/platform/zoul/Makefile.zoul b/arch/platform/zoul/Makefile.zoul
index e43f84744d9f787f229edfbbac9661b29fd7cbb6..d5bb3df15e40b1e030d4b857d736f439a396671e 100644
--- a/arch/platform/zoul/Makefile.zoul
+++ b/arch/platform/zoul/Makefile.zoul
@@ -24,8 +24,8 @@ CFLAGS += -DDATE="\"`date +"%02u %02d %02m %02y %02H %02M %02S"`\""
 
 ### Configure the build for the board and pull in board-specific sources
 CONTIKI_TARGET_DIRS += . dev
-CONTIKI_TARGET_DIRS += . $(BOARD)
-PLATFORM_ROOT_DIR = $(CONTIKI)/arch/platform/$(TARGET)
+CONTIKI_TARGET_DIRS += $(BOARD)
+PLATFORM_ROOT_DIR = $(ARCH_PATH)/platform/$(TARGET)
 
 ### Include the board dir if one exists
 -include $(PLATFORM_ROOT_DIR)/$(BOARD)/Makefile.$(BOARD)
@@ -39,7 +39,7 @@ CONTIKI_TARGET_SOURCEFILES += $(BOARD_SOURCEFILES)
 CONTIKI_SOURCEFILES += $(CONTIKI_TARGET_SOURCEFILES)
 
 ### Define the CPU directory
-CONTIKI_CPU=$(CONTIKI)/arch/cpu/cc2538
+CONTIKI_CPU=$(ARCH_PATH)/cpu/cc2538
 include $(CONTIKI_CPU)/Makefile.cc2538
 
 MODULES += arch/dev/cc1200 arch/dev/rgb-led os/storage/cfs
@@ -86,5 +86,5 @@ zoul-motes:
 	@echo $(MOTES)
 
 ### For the login etc targets
-BAUDRATE = 115200
+BAUDRATE ?= 115200
 PORT = $(USBDEVPREFIX)$(firstword $(MOTES))
diff --git a/arch/platform/zoul/platform.c b/arch/platform/zoul/platform.c
index bed948829c42ad6d1c564cb0549e230c7b67a84c..49158b5b4e8928339385263eece2d39876ebd2a2 100644
--- a/arch/platform/zoul/platform.c
+++ b/arch/platform/zoul/platform.c
@@ -295,6 +295,7 @@ radio_delay_before_detect(void) {
 uint16_t *
 radio_tsch_timeslot_timing(void) {
   uint16_t *ret;
+  /* Get and return pointer to TSCH timings in usec */
   NETSTACK_RADIO.get_object(RADIO_CONST_TSCH_TIMING, &ret, sizeof(ret));
   return ret;
 }
diff --git a/arch/platform/zoul/remote-revb/power-mgmt.c b/arch/platform/zoul/remote-revb/power-mgmt.c
index 0de8a890352f0e27a0cb9ddf53b338d5cb6a482a..8076ccc409a40556210f7e24e088d9a483e3d14a 100644
--- a/arch/platform/zoul/remote-revb/power-mgmt.c
+++ b/arch/platform/zoul/remote-revb/power-mgmt.c
@@ -62,7 +62,7 @@
 #define PM_ENABLE_AS_OUTPUT      GPIO_SET_OUTPUT(PM_ENABLE_PORT_BASE, \
                                                  PM_ENABLE_PIN_MASK)
 #define PM_ENABLE_LINE_CMD       PM_ENABLE_LINE_SET; \
-                                 clock_delay_usec(100);
+  clock_delay_usec(100);
 
 /* -------------------------------------------------------------------------- */
 #define PM_NUMBITS(X)            (1 << ((X)-1))
@@ -215,7 +215,7 @@ pm_get_num_cycles(void)
   }
   PM_ENABLE_LINE_CLR;
   PRINTF("PM: Sleep cycles: 0x%02x%02x%02x%02x\n", lbuf[0], lbuf[1], lbuf[2],
-                                                   lbuf[3]);
+         lbuf[3]);
   return retval;
 }
 /* -------------------------------------------------------------------------- */
@@ -249,6 +249,8 @@ pm_shutdown_now(uint8_t type)
 int8_t
 pm_get_voltage(uint16_t *state)
 {
+  float result = 0x00;
+
   if(!initialized) {
     return PM_ERROR;
   }
@@ -260,10 +262,12 @@ pm_get_voltage(uint16_t *state)
       *state = (uint16_t)lbuf[0] << 8;
       *state += lbuf[1];
 
-      /* Delay required for the command to finish */
-      clock_delay_usec(3000);
+      /* Compensation */
+      result = *state - PM_VBAT_OFF;
+      result /= PM_VBAT_MULT;
+
+      *state = (uint16_t)(result * 100);
 
-      PRINTF("PM: Voltage %u [%u][%u]\n", *state, lbuf[0], lbuf[1]);
       PM_ENABLE_LINE_CLR;
       return PM_SUCCESS;
     }
diff --git a/arch/platform/zoul/remote-revb/power-mgmt.h b/arch/platform/zoul/remote-revb/power-mgmt.h
index d7ea54d795509117308314cab67eef758bba13be..502b59a86473d8f5ac046a6299097caa1d95a8b1 100644
--- a/arch/platform/zoul/remote-revb/power-mgmt.h
+++ b/arch/platform/zoul/remote-revb/power-mgmt.h
@@ -132,6 +132,12 @@ typedef enum {
   PM_USBSUSPEND      /* USB in suspend mode */
 } pm_charge_current_states;
 
+/*
+ *  VBAT Curve compensation
+ */
+#define PM_VBAT_MULT    (float)-181.9
+#define PM_VBAT_OFF     (float)1294.72
+
 /** @} */
 /* -------------------------------------------------------------------------- */
 /** \name Power Management functions
diff --git a/examples/6tisch/6p-packet/Makefile b/examples/6tisch/6p-packet/Makefile
index 3ba74d3b9bfb93281a2653dce97a98352b6161d2..707a024852763f9615993e989e09960cd004781e 100644
--- a/examples/6tisch/6p-packet/Makefile
+++ b/examples/6tisch/6p-packet/Makefile
@@ -1,7 +1,7 @@
 CONTIKI_PROJECT      = sixp-node
 PROJECT_SOURCEFILES += test-sf.c
 
-PLATFORMS_EXCLUDE = sky nrf52dk native simplelink
+PLATFORMS_EXCLUDE = sky z1 nrf52dk native simplelink
 
 CONTIKI  = ../../../
 
diff --git a/examples/6tisch/channel-selection-demo/Makefile b/examples/6tisch/channel-selection-demo/Makefile
index a44c76f1026174308dfbb6b0a4b1dd121a9b5425..e3c4288f652cef1c57334a062e773ee8ba9072bd 100644
--- a/examples/6tisch/channel-selection-demo/Makefile
+++ b/examples/6tisch/channel-selection-demo/Makefile
@@ -3,8 +3,8 @@ all: $(CONTIKI_PROJECT)
 
 CONTIKI=../../..
 
-PLATFORMS_EXCLUDE = sky nrf52dk native
-BOARDS_EXCLUDE = srf06/cc13xx launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350
+PLATFORMS_EXCLUDE = sky z1 nrf52dk native
+BOARDS_EXCLUDE = srf06/cc13x0 launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350
 
 # The channel selection library
 MODULES += os/services/tsch-cs
diff --git a/examples/6tisch/etsi-plugtest-2017/Makefile b/examples/6tisch/etsi-plugtest-2017/Makefile
index 6dc463078bb76f5cbbf6ad702cdaf9259fa22f6c..6b1a23a4cfeeccfea18fdcc22ec26fe6c6901586 100644
--- a/examples/6tisch/etsi-plugtest-2017/Makefile
+++ b/examples/6tisch/etsi-plugtest-2017/Makefile
@@ -1,7 +1,7 @@
 CONTIKI_PROJECT = node
 all: $(CONTIKI_PROJECT)
 
-PLATFORMS_EXCLUDE = sky nrf52dk native simplelink
+PLATFORMS_EXCLUDE = sky z1 nrf52dk native simplelink
 BOARDS_EXCLUDE = sensortag/cc2650 sensortag/cc1350
 
 MAKE_WITH_SECURITY   ?= 0 # force Security from command line
diff --git a/examples/6tisch/etsi-plugtest-2017/README.md b/examples/6tisch/etsi-plugtest-2017/README.md
index ab296bff8ec35dba5c7410d429abd12c2afbf599..7369918fa16317bc5429af87cab47349ca272d9e 100644
--- a/examples/6tisch/etsi-plugtest-2017/README.md
+++ b/examples/6tisch/etsi-plugtest-2017/README.md
@@ -18,7 +18,7 @@ The following hardwares were used in the event:
 
 * Zolertia Remote (TARGET=`zoul`, BOARD=`remote`)
 * JN156x (TARGET=`jn516`)
-* CC2650 LaunchPad (TARGET=`srf06-cc26xx`, BOARD=`launchpad/cc2650`)
+* CC2650 LaunchPad (TARGET=`cc26x0-cc13x0`, BOARD=`launchpad/cc2650`)
 
 ## Usage
 
diff --git a/examples/6tisch/simple-node/node.c b/examples/6tisch/simple-node/node.c
index 381d81f8ef43b29206a72689e482158d6d19bc92..b8e29e7f68985118284ca33c7c8b778499c56cc9 100644
--- a/examples/6tisch/simple-node/node.c
+++ b/examples/6tisch/simple-node/node.c
@@ -60,7 +60,7 @@ PROCESS_THREAD(node_process, ev, data)
 
   is_coordinator = 0;
 
-#if CONTIKI_TARGET_COOJA
+#if CONTIKI_TARGET_COOJA || CONTIKI_TARGET_Z1
   is_coordinator = (node_id == 1);
 #endif
 
diff --git a/examples/6tisch/sixtop/Makefile b/examples/6tisch/sixtop/Makefile
index 5c35696e452c7dc62c55c8ebdfdfed52f679702a..1e6f0ef5fa0a49bb282546f3e6833c7bcba1814d 100644
--- a/examples/6tisch/sixtop/Makefile
+++ b/examples/6tisch/sixtop/Makefile
@@ -1,7 +1,7 @@
 CONTIKI_PROJECT = node-sixtop
 all: $(CONTIKI_PROJECT)
 
-PLATFORMS_EXCLUDE = sky nrf52dk native simplelink
+PLATFORMS_EXCLUDE = sky z1 nrf52dk native simplelink
 
 PROJECT_SOURCEFILES += sf-simple.c
 CONTIKI=../../..
diff --git a/examples/6tisch/timesync-demo/Makefile b/examples/6tisch/timesync-demo/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..85c29659fc2ddcefdb082c2ee7869458256c8f78
--- /dev/null
+++ b/examples/6tisch/timesync-demo/Makefile
@@ -0,0 +1,24 @@
+CONTIKI_PROJECT = node
+all: $(CONTIKI_PROJECT)
+
+CONTIKI=../../..
+
+PLATFORMS_EXCLUDE = sky z1 nrf52dk native
+
+# force Orchestra from command line
+MAKE_WITH_ORCHESTRA ?= 0
+# force Security from command line
+MAKE_WITH_SECURITY ?= 0
+
+MAKE_MAC = MAKE_MAC_TSCH
+MODULES += os/services/shell
+
+ifeq ($(MAKE_WITH_ORCHESTRA),1)
+MODULES += os/services/orchestra
+endif
+
+ifeq ($(MAKE_WITH_SECURITY),1)
+CFLAGS += -DWITH_SECURITY=1
+endif
+
+include $(CONTIKI)/Makefile.include
diff --git a/examples/6tisch/timesync-demo/README.md b/examples/6tisch/timesync-demo/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..cf130ee7363bc77103b0f03c37c491e92acffcdf
--- /dev/null
+++ b/examples/6tisch/timesync-demo/README.md
@@ -0,0 +1,18 @@
+This is a demonstration of application-level time synchronization using TSCH.
+
+In a TSCH network, all nodes are synchronized to a global time counter maintained
+by the coordinator. This fact can be exploited to measure properties such as latency.
+
+The modes periodically send their detected network uptime to the coordinator.
+The coordinator receives these packets, prints its local network uptime
+and the time difference. This time difference is equal to the end-to-end latency,
+which includes both the time to prepare the packet, the time until an appropriate
+slot in the TSCH schedule, the over-the-air time (negligible). If the packet
+does not arrive with the first attempt, it also includes the retransmission time.
+
+The nodes in this example do not have any notion of the wall-clock time.
+That would need additional synchronization between the TSCH network and an external clock source.
+For example, one can periodically distribute UNIX timestamps over the UART interface
+on the border router to implement this feature. Alternatively, the data collected from
+the TSCH network can be timestamped with just TSCH timestamps, and them on the external gateway
+these timestamps could be converted to wall-clock time.
\ No newline at end of file
diff --git a/examples/6tisch/timesync-demo/node.c b/examples/6tisch/timesync-demo/node.c
new file mode 100644
index 0000000000000000000000000000000000000000..408421cec1d8276fce6df317e3d9404fa61d0b2b
--- /dev/null
+++ b/examples/6tisch/timesync-demo/node.c
@@ -0,0 +1,139 @@
+/*
+ * Copyright (c) 2015, SICS Swedish ICT.
+ * Copyright (c) 2018, University of Bristol - http://www.bristol.ac.uk
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ *
+ */
+/**
+ * \file
+ *         A RPL+TSCH node demonstrating application-level time syncrhonization.
+ *
+ * \author Atis Elsts <atis.elsts@bristol.ac.uk>
+ *         Simon Duquennoy <simonduq@sics.se>
+ */
+
+#include "contiki.h"
+#include "net/routing/routing.h"
+#include "net/netstack.h"
+#include "net/ipv6/simple-udp.h"
+#include "net/mac/tsch/tsch.h"
+#include "lib/random.h"
+#include "sys/node-id.h"
+
+#include "sys/log.h"
+#define LOG_MODULE "App"
+#define LOG_LEVEL LOG_LEVEL_INFO
+
+#define UDP_CLIENT_PORT	8765
+#define UDP_SERVER_PORT	5678
+
+#define SEND_INTERVAL		  (60 * CLOCK_SECOND)
+/*---------------------------------------------------------------------------*/
+static struct simple_udp_connection client_conn, server_conn;
+
+PROCESS(node_process, "RPL Node");
+AUTOSTART_PROCESSES(&node_process);
+/*---------------------------------------------------------------------------*/
+static void
+udp_rx_callback(struct simple_udp_connection *c,
+         const uip_ipaddr_t *sender_addr,
+         uint16_t sender_port,
+         const uip_ipaddr_t *receiver_addr,
+         uint16_t receiver_port,
+         const uint8_t *data,
+         uint16_t datalen)
+{
+  uint64_t local_time_clock_ticks = tsch_get_network_uptime_ticks();
+  uint64_t remote_time_clock_ticks;
+
+  if(datalen >= sizeof(remote_time_clock_ticks)) {
+    memcpy(&remote_time_clock_ticks, data, sizeof(remote_time_clock_ticks));
+
+    LOG_INFO("Received from ");
+    LOG_INFO_6ADDR(sender_addr);
+    LOG_INFO_(", created at %lu, now %lu, latency %lu clock ticks\n",
+              (unsigned long)remote_time_clock_ticks,
+              (unsigned long)local_time_clock_ticks,
+              (unsigned long)(local_time_clock_ticks - remote_time_clock_ticks));
+  }
+}
+/*---------------------------------------------------------------------------*/
+PROCESS_THREAD(node_process, ev, data)
+{
+  static struct etimer periodic_timer;
+  int is_coordinator;
+  uip_ipaddr_t dest_ipaddr;
+
+  PROCESS_BEGIN();
+
+  is_coordinator = 0;
+
+#if CONTIKI_TARGET_COOJA
+  is_coordinator = (node_id == 1);
+#endif
+
+  if(is_coordinator) {
+    NETSTACK_ROUTING.root_start();
+  }
+
+  /* Initialize UDP connections */
+  simple_udp_register(&server_conn, UDP_SERVER_PORT, NULL,
+                      UDP_CLIENT_PORT, udp_rx_callback);
+  simple_udp_register(&client_conn, UDP_CLIENT_PORT, NULL,
+                      UDP_SERVER_PORT, NULL);
+
+  NETSTACK_MAC.on();
+
+  etimer_set(&periodic_timer, random_rand() % SEND_INTERVAL);
+
+  while(1) {
+    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&periodic_timer));
+
+    if(tsch_is_coordinator) {
+      break;
+    }
+
+    if(NETSTACK_ROUTING.node_is_reachable() && NETSTACK_ROUTING.get_root_ipaddr(&dest_ipaddr)) {
+      /* Send network uptime timestamp to the DAG root */
+      uint64_t network_uptime;
+      network_uptime = tsch_get_network_uptime_ticks();
+      simple_udp_sendto(&client_conn, &network_uptime, sizeof(network_uptime), &dest_ipaddr);
+      LOG_INFO("Sent network uptime timestamp %lu to ", (unsigned long)network_uptime);
+      LOG_INFO_6ADDR(&dest_ipaddr);
+      LOG_INFO_("\n");
+    } else {
+      LOG_INFO("Not reachable yet\n");
+    }
+
+    /* Add some jitter */
+    etimer_set(&periodic_timer, SEND_INTERVAL
+               - CLOCK_SECOND + (random_rand() % (2 * CLOCK_SECOND)));
+  }
+
+  PROCESS_END();
+}
+/*---------------------------------------------------------------------------*/
diff --git a/examples/6tisch/timesync-demo/project-conf.h b/examples/6tisch/timesync-demo/project-conf.h
new file mode 100644
index 0000000000000000000000000000000000000000..f787b8dfe53b93ab4d64a7f53cc3c90481a7b0b4
--- /dev/null
+++ b/examples/6tisch/timesync-demo/project-conf.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2015, SICS Swedish ICT.
+ * Copyright (c) 2018, University of Bristol - http://www.bristol.ac.uk
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ *
+ */
+
+/**
+ * \author Simon Duquennoy <simonduq@sics.se>
+ *         Atis Elsts <atis.elsts@bristol.ac.uk>
+ */
+
+#ifndef __PROJECT_CONF_H__
+#define __PROJECT_CONF_H__
+
+/* Set to enable TSCH security */
+#ifndef WITH_SECURITY
+#define WITH_SECURITY 0
+#endif /* WITH_SECURITY */
+
+/* USB serial takes space, free more space elsewhere */
+#define SICSLOWPAN_CONF_FRAG 0
+#define UIP_CONF_BUFFER_SIZE 160
+
+/*******************************************************/
+/******************* Configure TSCH ********************/
+/*******************************************************/
+
+/* IEEE802.15.4 PANID */
+#define IEEE802154_CONF_PANID 0x81a5
+
+/* Do not start TSCH at init, wait for NETSTACK_MAC.on() */
+#define TSCH_CONF_AUTOSTART 0
+
+/* 6TiSCH minimal schedule length.
+ * Larger values result in less frequent active slots: reduces capacity and saves energy. */
+#define TSCH_SCHEDULE_CONF_DEFAULT_LENGTH 3
+
+#if WITH_SECURITY
+
+/* Enable security */
+#define LLSEC802154_CONF_ENABLED 1
+
+#endif /* WITH_SECURITY */
+
+/*******************************************************/
+/************* Other system configuration **************/
+/*******************************************************/
+
+/* Logging */
+#define LOG_CONF_LEVEL_RPL                         LOG_LEVEL_WARN
+#define LOG_CONF_LEVEL_TCPIP                       LOG_LEVEL_WARN
+#define LOG_CONF_LEVEL_IPV6                        LOG_LEVEL_WARN
+#define LOG_CONF_LEVEL_6LOWPAN                     LOG_LEVEL_WARN
+#define LOG_CONF_LEVEL_MAC                         LOG_LEVEL_WARN
+#define LOG_CONF_LEVEL_FRAMER                      LOG_LEVEL_WARN
+#define TSCH_LOG_CONF_PER_SLOT                     0
+
+#endif /* __PROJECT_CONF_H__ */
diff --git a/examples/6tisch/tsch-stats/Makefile b/examples/6tisch/tsch-stats/Makefile
index 0c8863301d6cde373094deb5cfe747f19e86ff50..156c0d526769eb6fdabe24ccd01955d8c64c21fc 100644
--- a/examples/6tisch/tsch-stats/Makefile
+++ b/examples/6tisch/tsch-stats/Makefile
@@ -3,8 +3,8 @@ all: $(CONTIKI_PROJECT)
 
 CONTIKI=../../..
 
-PLATFORMS_EXCLUDE = sky nrf52dk native
-BOARDS_EXCLUDE = srf06/cc13xx launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350
+PLATFORMS_EXCLUDE = sky z1 nrf52dk native
+BOARDS_EXCLUDE = srf06/cc13x0 launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350
 
 # force Orchestra from command line
 MAKE_WITH_ORCHESTRA ?= 0
diff --git a/examples/benchmarks/rpl-req-resp/Makefile b/examples/benchmarks/rpl-req-resp/Makefile
index 11413ecd34cbacb79e95c0f34464ece37ff8c9ca..dadd7a2d7caad2978da388a74837458e590450db 100644
--- a/examples/benchmarks/rpl-req-resp/Makefile
+++ b/examples/benchmarks/rpl-req-resp/Makefile
@@ -1,8 +1,8 @@
 CONTIKI_PROJECT = node
 all: $(CONTIKI_PROJECT)
 
-PLATFORMS_EXCLUDE = sky nrf52dk native simplelink
-BOARDS_EXCLUDE = srf06/cc13xx launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350
+PLATFORMS_EXCLUDE = sky z1 nrf52dk native simplelink
+BOARDS_EXCLUDE = srf06/cc13x0 launchpad/cc1310 launchpad/cc1350 sensortag/cc2650 sensortag/cc1350
 
 MODULES_REL += ../testbeds
 MODULES += os/services/deployment
diff --git a/examples/benchmarks/rpl-req-resp/node.c b/examples/benchmarks/rpl-req-resp/node.c
index 4b92415f982b932f66d8c4ed1da2e612bb93c9b8..bc755279754be3570edd0fc62a34fc49e408de85 100644
--- a/examples/benchmarks/rpl-req-resp/node.c
+++ b/examples/benchmarks/rpl-req-resp/node.c
@@ -42,6 +42,8 @@
 #include "contiki-net.h"
 #include "services/deployment/deployment.h"
 
+#include <inttypes.h>
+
 /* Log configuration */
 #include "sys/log.h"
 #define LOG_MODULE "App"
diff --git a/examples/benchmarks/rpl-req-resp/parse.py b/examples/benchmarks/rpl-req-resp/parse.py
index a15b9c49bd7b0cb3485c9907b30cde28e917bf5b..dd36ef4c9d5c6561026d14602a9127ebdded1494 100644
--- a/examples/benchmarks/rpl-req-resp/parse.py
+++ b/examples/benchmarks/rpl-req-resp/parse.py
@@ -70,6 +70,9 @@ def parseRPL(log):
     if res:
         # This was the last line, commit full topology
         return {'event': 'topology' }
+    res = re.compile('initialized DAG').match(log)
+    if res:
+        return {'event': 'DAGinit' }
     return None
 
 def parseEnergest(log):
@@ -123,6 +126,7 @@ def doParse(file):
         "ranks": [],
         "trickle": [],
         "switches": [],
+        "DAGinits": [],
         "topology": [],
     }
 
@@ -178,6 +182,8 @@ def doParse(file):
                         arrays["trickle"].append(entry)
                     elif(ret['event'] == 'switch'):
                         arrays["switches"].append(entry)
+                    elif(ret['event'] == 'DAGinit'):
+                        arrays["DAGinits"].append(entry)
                     elif(ret['event'] == 'sending'):
                         if not ret['message'] in arrays:
                             arrays[ret['message']] = []
@@ -255,6 +261,7 @@ def main():
 
     outputStats(dfs, "ranks", "rank", "mean", "RPL rank (ETX-128)")
     outputStats(dfs, "switches", "pswitch", "count", "RPL parent switches (#)")
+    outputStats(dfs, "DAGinits", "event", "count", "RPL joining DAG (#)")
     outputStats(dfs, "trickle", "trickle", "mean", "RPL Trickle period (min)")
 
     outputStats(dfs, "DIS", "message", "count", "RPL DIS sent (#)", "rpl-dis")
diff --git a/examples/coap/coap-example-client/Makefile b/examples/coap/coap-example-client/Makefile
index 1d34409907e0b9db0f8bd8052f450842d4f8e340..21c9649e7d10480b9d930751cbcada94e571d083 100644
--- a/examples/coap/coap-example-client/Makefile
+++ b/examples/coap/coap-example-client/Makefile
@@ -3,7 +3,7 @@ CONTIKI_PROJECT = coap-example-client
 all: $(CONTIKI_PROJECT)
 
 # Do not try to build on Sky because of code size limitation
-PLATFORMS_EXCLUDE = sky
+PLATFORMS_EXCLUDE = sky z1
 
 # Include the CoAP implementation
 MODULES += os/net/app-layer/coap
diff --git a/examples/coap/coap-example-server/Makefile b/examples/coap/coap-example-server/Makefile
index 6d9e2db85ab36e2874128abda05db11428515f31..1647568cbf0039ebd038ea666ec01f4dd0d5c1d9 100644
--- a/examples/coap/coap-example-server/Makefile
+++ b/examples/coap/coap-example-server/Makefile
@@ -2,7 +2,7 @@ CONTIKI_PROJECT = coap-example-server
 all: $(CONTIKI_PROJECT)
 
 # Do not try to build on Sky because of code size limitation
-PLATFORMS_EXCLUDE = sky
+PLATFORMS_EXCLUDE = sky z1
 
 # Include the CoAP implementation
 MODULES += os/net/app-layer/coap
diff --git a/examples/coap/coap-example-server/resources/res-push.c b/examples/coap/coap-example-server/resources/res-push.c
index ffc8c9c0786c2c583de2d3fa52413a257225d2e8..3056f3a0daf0f362773471a90954428be2f114e6 100644
--- a/examples/coap/coap-example-server/resources/res-push.c
+++ b/examples/coap/coap-example-server/resources/res-push.c
@@ -50,7 +50,7 @@ PERIODIC_RESOURCE(res_push,
                   NULL,
                   NULL,
                   NULL,
-                  5 * CLOCK_SECOND,
+                  5000,
                   res_periodic_handler);
 
 /*
diff --git a/examples/coap/coap-example-server/resources/res-temperature.c b/examples/coap/coap-example-server/resources/res-temperature.c
index ac34dbe33cdd90b80254951352767ab218443dd6..5616924a6b0070e30d839df4320b72c921dd3825 100644
--- a/examples/coap/coap-example-server/resources/res-temperature.c
+++ b/examples/coap/coap-example-server/resources/res-temperature.c
@@ -66,7 +66,7 @@ PERIODIC_RESOURCE(res_temperature,
          NULL,
          NULL,
          NULL,
-         CLOCK_SECOND,
+         1000,
          res_periodic_handler);
 
 static void
diff --git a/examples/coap/coap-plugtest-server/resources/res-plugtest-obs.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-obs.c
index 7d191e7516797f04a7e809765e44417a0d4b6077..3200d1d8831c736b87eb04be02f1145249375984 100644
--- a/examples/coap/coap-plugtest-server/resources/res-plugtest-obs.c
+++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-obs.c
@@ -58,7 +58,7 @@ PERIODIC_RESOURCE(res_plugtest_obs,
                   NULL,
                   res_put_handler,
                   res_delete_handler,
-                  5 * CLOCK_SECOND,
+                  5000,
                   res_periodic_handler);
 
 static int32_t obs_counter = 0;
diff --git a/examples/coap/coap-plugtest-server/resources/res-plugtest-separate.c b/examples/coap/coap-plugtest-server/resources/res-plugtest-separate.c
index c0ae81d114fe807bb6e1108cacd95cb6023770d2..bbcfc9d776fb48a691e54c11939ffcc5a6f0c9a3 100644
--- a/examples/coap/coap-plugtest-server/resources/res-plugtest-separate.c
+++ b/examples/coap/coap-plugtest-server/resources/res-plugtest-separate.c
@@ -57,7 +57,7 @@ PERIODIC_RESOURCE(res_plugtest_separate,
                   NULL,
                   NULL,
                   NULL,
-                  3 * CLOCK_SECOND,
+                  3000,
                   res_resume_handler);
 
 /* A structure to store the required information */
diff --git a/examples/dev/button-hal/Makefile b/examples/dev/button-hal/Makefile
index b2a73fe3c91ac9751e35615a9f978f8931955691..263e9ec6586e3906b8f9b3d4bc12a98e521fb533 100644
--- a/examples/dev/button-hal/Makefile
+++ b/examples/dev/button-hal/Makefile
@@ -3,6 +3,6 @@ CONTIKI = ../../..
 
 all: $(CONTIKI_PROJECT)
 
-PLATFORMS_ONLY = srf06-cc26xx cc2538dk openmote-cc2538 zoul native simplelink
+PLATFORMS_ONLY = cc26x0-cc13x0 cc2538dk openmote-cc2538 zoul native simplelink
 
 include $(CONTIKI)/Makefile.include
diff --git a/examples/dev/gpio-hal/Makefile b/examples/dev/gpio-hal/Makefile
index 70f38a11ab4dbb35ee986289c64ff373e3708de4..234388c090efd51e0f83ff5d811d98f7022cc7b8 100644
--- a/examples/dev/gpio-hal/Makefile
+++ b/examples/dev/gpio-hal/Makefile
@@ -1,7 +1,7 @@
 CONTIKI_PROJECT = gpio-hal-example
 CONTIKI = ../../..
 
-PLATFORMS_ONLY = srf06-cc26xx cc2538dk openmote-cc2538 zoul native simplelink
+PLATFORMS_ONLY = cc26x0-cc13x0 cc2538dk openmote-cc2538 zoul native simplelink
 
 include $(CONTIKI)/Makefile.identify-target
 
diff --git a/examples/dev/gpio-hal/README.md b/examples/dev/gpio-hal/README.md
index 84ab68f88372352da07eb060feb79519c23b0931..ac756b0bc67a2a77ee143556a7cbf5b4aff17e2c 100644
--- a/examples/dev/gpio-hal/README.md
+++ b/examples/dev/gpio-hal/README.md
@@ -8,7 +8,9 @@ developing a new port.
 
 This example assumes a device with:
 
-* 3 output pins (e.g. LEDs).
+* 3 output pins (e.g. LEDs). If the platform uses the port/pin GPIO numbering
+  scheme then this example assumes that at least 2 of those pins are part of
+  the same port.
 * 1 button.
 
 # Supported devices
@@ -34,3 +36,10 @@ board that you wish to test with the example. For example, if you have a LED
 connected to pin 20, then you will need to
 
     gpio_hal_pin_t out_pin1 = 20;
+
+If the platform uses the port/pin GPIO numbering scheme then you will also
+need to provide definitions for the following variables:
+
+* `out_port1` and `out_port2_3`. `out_port2_3` corresponds to the port that
+  `out_pin2` and `out_pin3` are members of.
+* `btn_port` for the button pin's port.
diff --git a/examples/dev/gpio-hal/srf06-cc26xx/pins.c b/examples/dev/gpio-hal/cc26x0-cc13x0/pins.c
similarity index 100%
rename from examples/dev/gpio-hal/srf06-cc26xx/pins.c
rename to examples/dev/gpio-hal/cc26x0-cc13x0/pins.c
diff --git a/examples/dev/gpio-hal/gpio-hal-example.c b/examples/dev/gpio-hal/gpio-hal-example.c
index 75137e26ae2578c6727f8c866d505d7ddc3b9c50..dc29b4674ad26286cac8a6e3cb324f042628a548 100644
--- a/examples/dev/gpio-hal/gpio-hal-example.c
+++ b/examples/dev/gpio-hal/gpio-hal-example.c
@@ -40,6 +40,15 @@
 /*---------------------------------------------------------------------------*/
 extern gpio_hal_pin_t out_pin1, out_pin2, out_pin3;
 extern gpio_hal_pin_t btn_pin;
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+extern gpio_hal_port_t out_port1, out_port2_3;
+extern gpio_hal_port_t btn_port;
+#else
+#define out_port1   GPIO_HAL_NULL_PORT
+#define out_port2_3 GPIO_HAL_NULL_PORT
+#define btn_port    GPIO_HAL_NULL_PORT
+#endif
 /*---------------------------------------------------------------------------*/
 static struct etimer et;
 static uint8_t counter;
@@ -69,70 +78,70 @@ PROCESS_THREAD(gpio_hal_example, ev, data)
     if(ev == PROCESS_EVENT_TIMER && data == &et) {
       if((counter & 7) == 0) {
         /* Set output and test write, high */
-        gpio_hal_arch_pin_set_output(out_pin1);
-        gpio_hal_arch_pin_set_output(out_pin2);
-        gpio_hal_arch_pin_set_output(out_pin3);
+        gpio_hal_arch_pin_set_output(out_port1, out_pin1);
+        gpio_hal_arch_pin_set_output(out_port2_3, out_pin2);
+        gpio_hal_arch_pin_set_output(out_port2_3, out_pin3);
 
-        gpio_hal_arch_write_pin(out_pin1, 1);
-        gpio_hal_arch_write_pins(
+        gpio_hal_arch_write_pin(out_port1, out_pin1, 1);
+        gpio_hal_arch_write_pins(out_port2_3,
           gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3),
           gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3));
       } else if((counter & 7) == 1) {
         /* Test write, low */
-        gpio_hal_arch_write_pin(out_pin1, 0);
-        gpio_hal_arch_write_pins(
+        gpio_hal_arch_write_pin(out_port1, out_pin1, 0);
+        gpio_hal_arch_write_pins(out_port2_3,
           gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3), 0);
       } else if((counter & 7) == 2) {
         /* Test set */
-        gpio_hal_arch_set_pin(out_pin1);
-        gpio_hal_arch_set_pins(
+        gpio_hal_arch_set_pin(out_port1, out_pin1);
+        gpio_hal_arch_set_pins(out_port2_3,
           gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3));
       } else if((counter & 7) == 3) {
         /* Test clear */
-        gpio_hal_arch_clear_pin(out_pin1);
-        gpio_hal_arch_clear_pins(
+        gpio_hal_arch_clear_pin(out_port1, out_pin1);
+        gpio_hal_arch_clear_pins(out_port2_3,
           gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3));
       } else if((counter & 7) == 4) {
         /* Test toggle (should go high) */
-        gpio_hal_arch_toggle_pin(out_pin1);
-        gpio_hal_arch_toggle_pins(
+        gpio_hal_arch_toggle_pin(out_port1, out_pin1);
+        gpio_hal_arch_toggle_pins(out_port2_3,
           gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3));
       } else if((counter & 7) == 5) {
         /* Test toggle (should go low) */
-        gpio_hal_arch_toggle_pin(out_pin1);
-        gpio_hal_arch_toggle_pins(
+        gpio_hal_arch_toggle_pin(out_port1, out_pin1);
+        gpio_hal_arch_toggle_pins(out_port2_3,
           gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3));
       } else if((counter & 7) == 6) {
         /* Set to input and then set. Should stay off */
-        gpio_hal_arch_pin_set_input(out_pin1);
-        gpio_hal_arch_pin_set_input(out_pin2);
-        gpio_hal_arch_pin_set_input(out_pin3);
-        gpio_hal_arch_set_pin(out_pin1);
-        gpio_hal_arch_set_pins(
+        gpio_hal_arch_pin_set_input(out_port1, out_pin1);
+        gpio_hal_arch_pin_set_input(out_port2_3, out_pin2);
+        gpio_hal_arch_pin_set_input(out_port2_3, out_pin3);
+        gpio_hal_arch_set_pin(out_port1, out_pin1);
+        gpio_hal_arch_set_pins(out_port2_3,
           gpio_hal_pin_to_mask(out_pin2) | gpio_hal_pin_to_mask(out_pin3));
       } else if((counter & 7) == 7) {
         /* Toggle button interrupt */
         gpio_hal_pin_cfg_t interrupt;
 
-        interrupt = gpio_hal_arch_pin_cfg_get(btn_pin) &
+        interrupt = gpio_hal_arch_pin_cfg_get(btn_port, btn_pin) &
           GPIO_HAL_PIN_CFG_INT_ENABLE;
 
         if(interrupt == 0) {
           printf("Enabling button interrupt\n");
-          gpio_hal_arch_interrupt_enable(btn_pin);
+          gpio_hal_arch_interrupt_enable(btn_port, btn_pin);
         } else {
           printf("Disabling button interrupt\n");
-          gpio_hal_arch_interrupt_disable(btn_pin);
+          gpio_hal_arch_interrupt_disable(btn_port, btn_pin);
         }
       }
 
       /* Test read */
       printf("%u: Pins are 1-%u, 2=%u, 3=%u, mask=" PIN_MASK_FMT "\n",
              counter & 7,
-             gpio_hal_arch_read_pin(out_pin1),
-             gpio_hal_arch_read_pin(out_pin2),
-             gpio_hal_arch_read_pin(out_pin3),
-             gpio_hal_arch_read_pins(gpio_hal_pin_to_mask(out_pin1) |
+             gpio_hal_arch_read_pin(out_port1, out_pin1),
+             gpio_hal_arch_read_pin(out_port2_3, out_pin2),
+             gpio_hal_arch_read_pin(out_port2_3, out_pin3),
+             gpio_hal_arch_read_pins(out_port2_3,
                                      gpio_hal_pin_to_mask(out_pin2) |
                                      gpio_hal_pin_to_mask(out_pin3)));
 
diff --git a/examples/libs/ipv6-hooks/ipv6-hooks.c b/examples/libs/ipv6-hooks/ipv6-hooks.c
index d3ca8861c3954c266bcd36a0117adec23d42a1b0..8d8561049d8248fdbabafd54445c91e6e9db0df2 100644
--- a/examples/libs/ipv6-hooks/ipv6-hooks.c
+++ b/examples/libs/ipv6-hooks/ipv6-hooks.c
@@ -10,8 +10,6 @@
 #define LOG_MODULE "App"
 #define LOG_LEVEL LOG_LEVEL_INFO
 
-#define UIP_IP_BUF       ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-
 /*---------------------------------------------------------------------------*/
 PROCESS(ipv6_hooks_process, "IPv6 Hooks");
 AUTOSTART_PROCESSES(&ipv6_hooks_process);
diff --git a/examples/libs/ipv6-uipbuf/udp-client.c b/examples/libs/ipv6-uipbuf/udp-client.c
index bee1cda83da2e758bb95474f66b3647dda9ef9af..5616874b5f9237723d28f3dd77b501b7f962ee9b 100644
--- a/examples/libs/ipv6-uipbuf/udp-client.c
+++ b/examples/libs/ipv6-uipbuf/udp-client.c
@@ -12,9 +12,6 @@
 #define UDP_CLIENT_PORT	8765
 #define UDP_SERVER_PORT	5678
 
-static struct simple_udp_connection udp_conn;
-
-#define START_INTERVAL		(15 * CLOCK_SECOND)
 #define SEND_INTERVAL		  (60 * CLOCK_SECOND)
 
 static struct simple_udp_connection udp_conn;
diff --git a/examples/libs/stack-check/example-stack-check.c b/examples/libs/stack-check/example-stack-check.c
index 8f4b0f0aee9dc60db2380de5d778f8c6d1b0bccf..b48f1a4505d3afe73f4628150b8be0f63b63904b 100644
--- a/examples/libs/stack-check/example-stack-check.c
+++ b/examples/libs/stack-check/example-stack-check.c
@@ -42,6 +42,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <alloca.h>
+#include <inttypes.h>
 /*---------------------------------------------------------------------------*/
 PROCESS(example_process, "Stack check example");
 AUTOSTART_PROCESSES(&example_process);
@@ -49,7 +50,7 @@ AUTOSTART_PROCESSES(&example_process);
 static void
 nested_function(void)
 {
-  printf("stack usage: %u permitted: %u\n",
+  printf("stack usage: %" PRId32 " permitted: %" PRId32 "\n",
          stack_check_get_usage(), stack_check_get_reserved_size());
 }
 /*---------------------------------------------------------------------------*/
diff --git a/examples/lwm2m-ipso-objects/Makefile b/examples/lwm2m-ipso-objects/Makefile
index c2cef2cfd00515e0cef078329e437f6d919459e0..a8d461859cc197ac401c8c631d4a73373e44e33e 100644
--- a/examples/lwm2m-ipso-objects/Makefile
+++ b/examples/lwm2m-ipso-objects/Makefile
@@ -2,7 +2,7 @@ CONTIKI_PROJECT = example-ipso-objects
 
 CONTIKI_SOURCEFILES += serial-protocol.c example-ipso-temperature.c
 
-PLATFORMS_EXCLUDE = sky
+PLATFORMS_EXCLUDE = sky z1
 
 all: $(CONTIKI_PROJECT)
 
diff --git a/examples/lwm2m-ipso-objects/example-ipso-objects.c b/examples/lwm2m-ipso-objects/example-ipso-objects.c
index 51bd84040fb0bcd58e82b6b20a7beecb2582bd8a..60ca4bdb9eda8c90b4d1686061b065939a57c47e 100644
--- a/examples/lwm2m-ipso-objects/example-ipso-objects.c
+++ b/examples/lwm2m-ipso-objects/example-ipso-objects.c
@@ -34,6 +34,7 @@
  * \author
  *      Joakim Eriksson, joakime@sics.se
  *      Niclas Finne, nfi@sics.se
+ *      Carlos Gonzalo Peces, carlosgp143@gmail.com
  */
 
 #include "contiki.h"
@@ -51,18 +52,28 @@
 #define DEBUG DEBUG_NONE
 #include "net/ipv6/uip-debug.h"
 
+/* Define this macro to non-zero to register via a bootstrap server */
 #ifndef REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER
 #define REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER 0
 #endif
 
-#ifndef REGISTER_WITH_LWM2M_SERVER
-#define REGISTER_WITH_LWM2M_SERVER 1
+#if REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER
+#define SERVER_TYPE LWM2M_RD_CLIENT_BOOTSTRAP_SERVER
+#else
+#define SERVER_TYPE LWM2M_RD_CLIENT_LWM2M_SERVER
 #endif
 
 #ifndef LWM2M_SERVER_ADDRESS
 #define LWM2M_SERVER_ADDRESS "coap://[fd00::1]"
 #endif
 
+static lwm2m_session_info_t session_info;
+
+/* Define this macro to register with a second LWM2M server */
+#ifdef LWM2M_SERVER_ADDRESS_SECOND
+static lwm2m_session_info_t session_info_second;
+#endif
+
 #if BOARD_SENSORTAG
 #include "board-peripherals.h"
 
@@ -148,13 +159,17 @@ setup_lwm2m_servers(void)
   coap_endpoint_t server_ep;
   if(coap_endpoint_parse(LWM2M_SERVER_ADDRESS, strlen(LWM2M_SERVER_ADDRESS),
                          &server_ep) != 0) {
-    lwm2m_rd_client_register_with_bootstrap_server(&server_ep);
-    lwm2m_rd_client_register_with_server(&server_ep);
+    lwm2m_rd_client_register_with_server(&session_info, &server_ep, SERVER_TYPE);
   }
 #endif /* LWM2M_SERVER_ADDRESS */
 
-  lwm2m_rd_client_use_bootstrap_server(REGISTER_WITH_LWM2M_BOOTSTRAP_SERVER);
-  lwm2m_rd_client_use_registration_server(REGISTER_WITH_LWM2M_SERVER);
+#ifdef LWM2M_SERVER_ADDRESS_SECOND
+  coap_endpoint_t server_ep_second;
+  if(coap_endpoint_parse(LWM2M_SERVER_ADDRESS_SECOND, strlen(LWM2M_SERVER_ADDRESS_SECOND),
+                         &server_ep_second) != 0) {
+    lwm2m_rd_client_register_with_server(&session_info_second, &server_ep_second, SERVER_TYPE);
+  }
+#endif /* LWM2M_SERVER_ADDRESS_SECOND */
 }
 /*---------------------------------------------------------------------------*/
 PROCESS_THREAD(example_ipso_objects, ev, data)
diff --git a/examples/mqtt-client/Makefile b/examples/mqtt-client/Makefile
index a9ab116131d322d8b8c411670b344f5c9eb2d997..29b3267e16efed7a410619be22c4262e5b36da4a 100644
--- a/examples/mqtt-client/Makefile
+++ b/examples/mqtt-client/Makefile
@@ -8,6 +8,6 @@ CONTIKI = ../..
 
 MODULES_REL += arch/platform/$(TARGET)
 
-PLATFORMS_ONLY = srf06-cc26xx cc2538dk openmote-cc2538 zoul native simplelink
+PLATFORMS_ONLY = cc26x0-cc13x0 cc2538dk openmote-cc2538 zoul native simplelink
 
 include $(CONTIKI)/Makefile.include
diff --git a/examples/mqtt-client/arch/cpu/cc26xx-cc13xx/builtin-sensors.c b/examples/mqtt-client/arch/cpu/cc26x0-cc13x0/builtin-sensors.c
similarity index 100%
rename from examples/mqtt-client/arch/cpu/cc26xx-cc13xx/builtin-sensors.c
rename to examples/mqtt-client/arch/cpu/cc26x0-cc13x0/builtin-sensors.c
diff --git a/examples/mqtt-client/arch/cpu/cc26xx-cc13xx/builtin-sensors.h b/examples/mqtt-client/arch/cpu/cc26x0-cc13x0/builtin-sensors.h
similarity index 100%
rename from examples/mqtt-client/arch/cpu/cc26xx-cc13xx/builtin-sensors.h
rename to examples/mqtt-client/arch/cpu/cc26x0-cc13x0/builtin-sensors.h
diff --git a/examples/mqtt-client/arch/platform/cc26x0-cc13x0/Makefile.cc26x0-cc13x0 b/examples/mqtt-client/arch/platform/cc26x0-cc13x0/Makefile.cc26x0-cc13x0
new file mode 100644
index 0000000000000000000000000000000000000000..7c74123c61d779d1872dcb91dc4e6f162acfce91
--- /dev/null
+++ b/examples/mqtt-client/arch/platform/cc26x0-cc13x0/Makefile.cc26x0-cc13x0
@@ -0,0 +1 @@
+MODULES_REL += arch/cpu/cc26x0-cc13x0
diff --git a/examples/mqtt-client/arch/platform/srf06-cc26xx/module-macros.h b/examples/mqtt-client/arch/platform/cc26x0-cc13x0/module-macros.h
similarity index 100%
rename from examples/mqtt-client/arch/platform/srf06-cc26xx/module-macros.h
rename to examples/mqtt-client/arch/platform/cc26x0-cc13x0/module-macros.h
diff --git a/examples/mqtt-client/arch/platform/srf06-cc26xx/mqtt-client-extensions.c b/examples/mqtt-client/arch/platform/cc26x0-cc13x0/mqtt-client-extensions.c
similarity index 100%
rename from examples/mqtt-client/arch/platform/srf06-cc26xx/mqtt-client-extensions.c
rename to examples/mqtt-client/arch/platform/cc26x0-cc13x0/mqtt-client-extensions.c
diff --git a/examples/mqtt-client/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx b/examples/mqtt-client/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx
deleted file mode 100644
index dcec87bad6f160196a78bf52e3eeb83da4c77e77..0000000000000000000000000000000000000000
--- a/examples/mqtt-client/arch/platform/srf06-cc26xx/Makefile.srf06-cc26xx
+++ /dev/null
@@ -1 +0,0 @@
-MODULES_REL += arch/cpu/cc26xx-cc13xx
diff --git a/examples/mqtt-client/mqtt-client.c b/examples/mqtt-client/mqtt-client.c
index b71a193eae9b5572513f83867c01b782eb2bb1f2..35e669e245b9f77f7187a075f4dcf49fe977036d 100644
--- a/examples/mqtt-client/mqtt-client.c
+++ b/examples/mqtt-client/mqtt-client.c
@@ -572,7 +572,7 @@ connect_to_broker(void)
 {
   /* Connect to MQTT server */
   mqtt_connect(&conn, conf.broker_ip, conf.broker_port,
-               conf.pub_interval * 3);
+               (conf.pub_interval * 3) / CLOCK_SECOND);
 
   state = STATE_CONNECTING;
 }
diff --git a/examples/multicast/Makefile b/examples/multicast/Makefile
index 86c16e481ea4b508f45856f685a711173d37f913..3e8a88d4a056e4d0d5bc55829623ed10405a1690 100644
--- a/examples/multicast/Makefile
+++ b/examples/multicast/Makefile
@@ -3,8 +3,8 @@ all: $(CONTIKI_PROJECT)
 
 # nrf52dk only supports slave mode, i.e., with no routing
 PLATFORMS_EXCLUDE = nrf52dk
-# does not fit sky motes
-PLATFORMS_EXCLUDE += sky
+# does not fit on sky and z1 motes
+PLATFORMS_EXCLUDE += sky z1
 
 CONTIKI = ../..
 
diff --git a/examples/multicast/srf06-cc26xx/module-macros.h b/examples/multicast/cc26x0-cc13x0/module-macros.h
similarity index 100%
rename from examples/multicast/srf06-cc26xx/module-macros.h
rename to examples/multicast/cc26x0-cc13x0/module-macros.h
diff --git a/examples/multicast/project-conf.h b/examples/multicast/project-conf.h
index c1bb6910e27f0a153747858b95f31e4876865361..c0e318022c8558d83ccba4d56b357d13a19e0c54 100644
--- a/examples/multicast/project-conf.h
+++ b/examples/multicast/project-conf.h
@@ -45,11 +45,13 @@
 
 /* Change this to switch engines. Engine codes in uip-mcast6-engines.h */
 #ifndef UIP_MCAST6_CONF_ENGINE
-#define UIP_MCAST6_CONF_ENGINE UIP_MCAST6_ENGINE_ROLL_TM
+#define UIP_MCAST6_CONF_ENGINE UIP_MCAST6_ENGINE_MPL
 #endif
 
 /* For Imin: Use 16 over CSMA, 64 over Contiki MAC */
 #define ROLL_TM_CONF_IMIN_1         64
+#define MPL_CONF_DATA_MESSAGE_IMIN  64
+#define MPL_CONF_CONTROL_MESSAGE_IMIN  64
 
 #define UIP_MCAST6_ROUTE_CONF_ROUTES 1
 
diff --git a/examples/multicast/root.c b/examples/multicast/root.c
index 59d5d2aa8dc89f8e8916f1a82a08635d284c6890..872b423a36b60540545222c1e9450aafcf3b2b6b 100644
--- a/examples/multicast/root.c
+++ b/examples/multicast/root.c
@@ -96,11 +96,19 @@ prepare_mcast(void)
 {
   uip_ipaddr_t ipaddr;
 
+#if UIP_MCAST6_CONF_ENGINE == UIP_MCAST6_ENGINE_MPL
+/*
+ * MPL defines a well-known MPL domain, MPL_ALL_FORWARDERS, which
+ *  MPL nodes are automatically members of. Send to that domain.
+ */
+  uip_ip6addr(&ipaddr, 0xFF03,0,0,0,0,0,0,0xFC);
+#else
   /*
    * IPHC will use stateless multicast compression for this destination
    * (M=1, DAC=0), with 32 inline bits (1E 89 AB CD)
    */
   uip_ip6addr(&ipaddr, 0xFF1E,0,0,0,0,0,0x89,0xABCD);
+#endif
   mcast_conn = udp_new(&ipaddr, UIP_HTONS(MCAST_SINK_UDP_PORT), NULL);
 }
 /*---------------------------------------------------------------------------*/
diff --git a/examples/multicast/sink.c b/examples/multicast/sink.c
index 34ad6009d78b2ad838f345e75d913ad26349f32d..c3b4f09ba8481fc01286875810f1baf022c259be 100644
--- a/examples/multicast/sink.c
+++ b/examples/multicast/sink.c
@@ -55,8 +55,6 @@
 static struct uip_udp_conn *sink_conn;
 static uint16_t count;
 
-#define UIP_IP_BUF   ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-
 #if !NETSTACK_CONF_WITH_IPV6 || !UIP_CONF_ROUTER || !UIP_IPV6_MULTICAST || !UIP_CONF_IPV6_RPL
 #error "This example can not work with the current contiki configuration"
 #error "Check the values of: NETSTACK_CONF_WITH_IPV6, UIP_CONF_ROUTER, UIP_CONF_IPV6_RPL"
@@ -77,14 +75,16 @@ tcpip_handler(void)
   return;
 }
 /*---------------------------------------------------------------------------*/
+#if UIP_MCAST6_CONF_ENGINE != UIP_MCAST6_ENGINE_MPL
 static uip_ds6_maddr_t *
 join_mcast_group(void)
 {
   uip_ipaddr_t addr;
   uip_ds6_maddr_t *rv;
+  const uip_ipaddr_t *default_prefix = uip_ds6_default_prefix();
 
   /* First, set our v6 global */
-  uip_ip6addr(&addr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
+  uip_ip6addr_copy(&addr, default_prefix);
   uip_ds6_set_addr_iid(&addr, &uip_lladdr);
   uip_ds6_addr_add(&addr, 0, ADDR_AUTOCONF);
 
@@ -102,6 +102,7 @@ join_mcast_group(void)
   }
   return rv;
 }
+#endif
 /*---------------------------------------------------------------------------*/
 PROCESS_THREAD(mcast_sink_process, ev, data)
 {
@@ -109,10 +110,16 @@ PROCESS_THREAD(mcast_sink_process, ev, data)
 
   PRINTF("Multicast Engine: '%s'\n", UIP_MCAST6.name);
 
+  /*
+   * MPL nodes are automatically configured to subscribe to the ALL_MPL_FORWARDERS
+   *  well-known address, so this isn't needed.
+   */
+#if UIP_MCAST6_CONF_ENGINE != UIP_MCAST6_ENGINE_MPL
   if(join_mcast_group() == NULL) {
     PRINTF("Failed to join multicast group\n");
     PROCESS_EXIT();
   }
+#endif
 
   count = 0;
 
diff --git a/examples/platform-specific/cc26xx/Makefile b/examples/platform-specific/cc26x0-cc13x0/Makefile
similarity index 57%
rename from examples/platform-specific/cc26xx/Makefile
rename to examples/platform-specific/cc26x0-cc13x0/Makefile
index 40e484bcc71dd25c4069b5dcf1e357f68279dd99..bd9600c78f23ca701e60604e3ad0d97e227be58a 100644
--- a/examples/platform-specific/cc26xx/Makefile
+++ b/examples/platform-specific/cc26x0-cc13x0/Makefile
@@ -1,6 +1,6 @@
-CONTIKI_PROJECT = cc26xx-demo
+CONTIKI_PROJECT = cc26x0-demo
 
-PLATFORMS_ONLY = srf06-cc26xx
+PLATFORMS_ONLY = cc26x0-cc13x0
 
 all: $(CONTIKI_PROJECT)
 
diff --git a/examples/platform-specific/cc26x0-cc13x0/Makefile.target b/examples/platform-specific/cc26x0-cc13x0/Makefile.target
new file mode 100644
index 0000000000000000000000000000000000000000..bd54a4fc745fc86a3545e3d6c01d4412787e56fc
--- /dev/null
+++ b/examples/platform-specific/cc26x0-cc13x0/Makefile.target
@@ -0,0 +1 @@
+TARGET = cc26x0-cc13x0
diff --git a/examples/platform-specific/cc26xx/README.md b/examples/platform-specific/cc26x0-cc13x0/README.md
similarity index 100%
rename from examples/platform-specific/cc26xx/README.md
rename to examples/platform-specific/cc26x0-cc13x0/README.md
diff --git a/examples/platform-specific/cc26x0-cc13x0/ble-ipv6/Makefile b/examples/platform-specific/cc26x0-cc13x0/ble-ipv6/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..052927896d4cd378609ff18f67bd670531509be5
--- /dev/null
+++ b/examples/platform-specific/cc26x0-cc13x0/ble-ipv6/Makefile
@@ -0,0 +1,11 @@
+CONTIKI_PROJECT=client
+
+all: $(CONTIKI_PROJECT)
+
+PLATFORMS_ONLY = cc26x0-cc13x0
+BOARDS_ONLY = launchpad/cc2650 sensortag/cc2650 srf06/cc26x0
+
+MAKE_MAC = MAKE_MAC_BLE
+MAKE_NET = MAKE_NET_IPV6
+CONTIKI = ../../../..
+include $(CONTIKI)/Makefile.include
diff --git a/examples/platform-specific/cc26xx/ble-ipv6/README.md b/examples/platform-specific/cc26x0-cc13x0/ble-ipv6/README.md
similarity index 93%
rename from examples/platform-specific/cc26xx/ble-ipv6/README.md
rename to examples/platform-specific/cc26x0-cc13x0/ble-ipv6/README.md
index d33c7329f393ef8c427c29f09e9c8c22c366248b..3d1aeda385abca2fd55e523d6c53fce90d5f2147 100644
--- a/examples/platform-specific/cc26xx/ble-ipv6/README.md
+++ b/examples/platform-specific/cc26x0-cc13x0/ble-ipv6/README.md
@@ -28,12 +28,12 @@ It has been tested on the TI CC2650 SensorTag and the TI CC2650 LaunchPad hardwa
 The IPv6-over-BLE stack comes with the following modules:
 
 ### BLE radio
-The implementation of the BLE radio for the TI CC26xx platform is implemented in `arch/cpu/cc26xx-cc13xx/rf-core/ble-cc2650.c`
-and `arch/cpu/cc26xx-cc13xx/rf-core/ble-hal/*.[ch]`.
+The implementation of the BLE radio for the TI CC26xx platform is implemented in `arch/cpu/cc26x0-cc13x0/rf-core/ble-cc2650.c`
+and `arch/cpu/cc26x0-cc13x0/rf-core/ble-hal/*.[ch]`.
 These files contain all the hardware specific code for supporting BLE as a link layer.
 
 ### BLE L2CAP layer
-The L2CAP LE credit-based flow control support is implemented in `arch/cpu/cc26xx-cc13xx/rf-core/ble-l2cap.c`.
+The L2CAP LE credit-based flow control support is implemented in `arch/cpu/cc26x0-cc13x0/rf-core/ble-l2cap.c`.
 Besides implementing rudimentary L2CAP support, this module handles fragmentation of large IPv6 packets.
 
 ## Using BLEach
@@ -54,7 +54,6 @@ To enable IPv6 over BLE, the project conf needs to contain:
 #define RTIMER_CONF_MULTIPLE_ACCESS       1
 
 /* 6LoWPAN settings */
-#define SICSLOWPAN_CONF_MAC_MAX_PAYLOAD       1280
 #define SICSLOWPAN_CONF_COMPRESSION           SICSLOWPAN_COMPRESSION_HC06
 #define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD   0  /* always use compression */
 #define SICSLOWPAN_CONF_FRAG                    0
diff --git a/examples/platform-specific/cc26xx/ble-ipv6/client.c b/examples/platform-specific/cc26x0-cc13x0/ble-ipv6/client.c
similarity index 100%
rename from examples/platform-specific/cc26xx/ble-ipv6/client.c
rename to examples/platform-specific/cc26x0-cc13x0/ble-ipv6/client.c
diff --git a/examples/platform-specific/cc26xx/ble-ipv6/project-conf.h b/examples/platform-specific/cc26x0-cc13x0/ble-ipv6/project-conf.h
similarity index 98%
rename from examples/platform-specific/cc26xx/ble-ipv6/project-conf.h
rename to examples/platform-specific/cc26x0-cc13x0/ble-ipv6/project-conf.h
index b311a2fa5ee369d79537e89adc40a14e67d513b0..9f625f14e8bda67243cc49980b6c10554c8a948b 100644
--- a/examples/platform-specific/cc26xx/ble-ipv6/project-conf.h
+++ b/examples/platform-specific/cc26x0-cc13x0/ble-ipv6/project-conf.h
@@ -53,7 +53,6 @@
 #define BLE_CONF_ADV_INTERVAL         25
 
 /*/ * 6LoWPAN settings * / */
-#define SICSLOWPAN_CONF_MAC_MAX_PAYLOAD       1280
 #define SICSLOWPAN_CONF_COMPRESSION           SICSLOWPAN_COMPRESSION_6LORH
 #define SICSLOWPAN_CONF_COMPRESSION_THRESHOLD   0  /* always use compression */
 #define SICSLOWPAN_CONF_FRAG                    0
diff --git a/examples/platform-specific/cc26xx/cc26xx-demo.c b/examples/platform-specific/cc26x0-cc13x0/cc26x0-demo.c
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-demo.c
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-demo.c
index 81e99f3fad24c297a63e3d0fa735c0cb6a5ce5fc..1b71feeb715589bb4fdcebb62d7721c6c8ac1087 100644
--- a/examples/platform-specific/cc26xx/cc26xx-demo.c
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-demo.c
@@ -42,7 +42,7 @@
  *   Example project demonstrating the CC13xx/CC26xx platforms
  *
  *   This example will work for the following boards:
- *   - srf06-cc26xx: SmartRF06EB + CC13xx/CC26xx EM
+ *   - cc26x0-cc13x0: SmartRF06EB + CC13xx/CC26xx EM
  *   - CC2650 and CC1350 SensorTag
  *   - CC1310, CC1350, CC2650 LaunchPads
  *
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/Makefile b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/Makefile
similarity index 87%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/Makefile
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/Makefile
index 05dbface10a5da1cd3c5a6400289326591faf3ca..6d70a3a2407df13e9bf09446198f814fdb0a8a1d 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/Makefile
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/Makefile
@@ -1,7 +1,7 @@
-CONTIKI_PROJECT = cc26xx-web-demo
+CONTIKI_PROJECT = cc26x0-web-demo
 all: $(CONTIKI_PROJECT)
 
-PLATFORMS_ONLY = srf06-cc26xx
+PLATFORMS_ONLY = cc26x0-cc13x0
 
 MODULES_REL += ./resources
 
diff --git a/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/Makefile.target b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/Makefile.target
new file mode 100644
index 0000000000000000000000000000000000000000..bd54a4fc745fc86a3545e3d6c01d4412787e56fc
--- /dev/null
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/Makefile.target
@@ -0,0 +1 @@
+TARGET = cc26x0-cc13x0
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/README.md b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/README.md
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/README.md
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/README.md
index 912fcb72ab0e37f01b9c7214721c54caed1a4caf..6a85ee0b50ae4210ea23c812a09e1a377523dab8 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/README.md
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/README.md
@@ -180,6 +180,6 @@ parser into the firmware.
 
 IBM Watson IoT Platform
 ----------------------------
-To use IBM Watson IoT Platform, you have to go to SECURITY tab of Device page to select "TLS Optional". This step is critical. If you don't do this, you need to use TLS for connection and default cc26xx-web-demo won't work.
+To use IBM Watson IoT Platform, you have to go to SECURITY tab of Device page to select "TLS Optional". This step is critical. If you don't do this, you need to use TLS for connection and default cc26x0-web-demo won't work.
 
 ![IBM Watson IoT Platform TLS Optional Configuration](img/ibm-watson-iot-platform-tls-optional.png)
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cc26x0-web-demo.c
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cc26x0-web-demo.c
index 3944a58b24ae11c93a9af4a37f6fdf3e91517691..6333d5ad53e7ae9ec817fbfa8ca02df5633b3c7f 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.c
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cc26x0-web-demo.c
@@ -28,7 +28,7 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 /**
- * \addtogroup cc26xx-web-demo
+ * \addtogroup cc26x0-web-demo
  * @{
  *
  * \file
@@ -48,7 +48,7 @@
 #include "dev/button-hal.h"
 #include "batmon-sensor.h"
 #include "httpd-simple.h"
-#include "cc26xx-web-demo.h"
+#include "cc26x0-web-demo.h"
 #include "mqtt-client.h"
 #include "coap-server.h"
 
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cc26x0-web-demo.h
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cc26x0-web-demo.h
index f59e41bc7b4c7c817f4ae92901b6137c9d6b8fb1..e7252496ce6768fe5fc18750ade60451735c0a9f 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/cc26xx-web-demo.h
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cc26x0-web-demo.h
@@ -31,7 +31,7 @@
  * \addtogroup cc26xx-examples
  * @{
  *
- * \defgroup cc26xx-web-demo CC26xx Web Demo
+ * \defgroup cc26x0-web-demo CC26xx Web Demo
  * @{
  *
  *   An example demonstrating:
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cetic-6lbr-client.c
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cetic-6lbr-client.c
index 569a36a89024ef711a82f2cd605d339aae6c0eaf..fc80443807293bc17181336e4cda4f1c0726bf7a 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/cetic-6lbr-client.c
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cetic-6lbr-client.c
@@ -24,7 +24,7 @@
  * SUCH DAMAGE.
  */
 /**
- * \addtogroup cc26xx-web-demo
+ * \addtogroup cc26x0-web-demo
  * @{
  *
  * \file
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.c b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/coap-server.c
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.c
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/coap-server.c
index 37b9a295d5cc0f050b4525f4a740356cffe0f9d5..bda7eb8ff71c2474605ba3de7f6d1731f3f611f3 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.c
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/coap-server.c
@@ -28,7 +28,7 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 /**
- * \addtogroup cc26xx-web-demo
+ * \addtogroup cc26x0-web-demo
  * @{
  *
  * \file
@@ -40,7 +40,7 @@
 #include "coap-engine.h"
 #include "board-peripherals.h"
 #include "rf-core/rf-ble.h"
-#include "cc26xx-web-demo.h"
+#include "cc26x0-web-demo.h"
 
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.h b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/coap-server.h
similarity index 98%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.h
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/coap-server.h
index 7399597c8b55b212279e724b4354533b46769700..0d8c1d40bf08f8724da889335389baac6510963f 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/coap-server.h
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/coap-server.h
@@ -28,7 +28,7 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 /**
- * \addtogroup cc26xx-web-demo
+ * \addtogroup cc26x0-web-demo
  * @{
  *
  * \file
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/httpd-simple.c b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/httpd-simple.c
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/httpd-simple.c
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/httpd-simple.c
index e23e78efe25a7471e9402ee514ae3b85135a0a8e..101b6441bfb09ae4acbd15f7ecd99fad79f59919 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/httpd-simple.c
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/httpd-simple.c
@@ -29,7 +29,7 @@
  *
  */
 /**
- * \addtogroup cc26xx-web-demo
+ * \addtogroup cc26x0-web-demo
  * @{
  *
  * \file
@@ -38,11 +38,12 @@
 /*---------------------------------------------------------------------------*/
 #include "contiki.h"
 #include "httpd-simple.h"
+#include "net/ipv6/uip-ds6-nbr.h"
 #include "net/ipv6/uip-ds6-route.h"
 #include "batmon-sensor.h"
 #include "lib/sensors.h"
 #include "lib/list.h"
-#include "cc26xx-web-demo.h"
+#include "cc26x0-web-demo.h"
 #include "mqtt-client.h"
 #include "net-uart.h"
 
@@ -436,8 +437,8 @@ PT_THREAD(generate_index(struct httpd_state *s))
   PT_WAIT_THREAD(&s->generate_pt,
                  enqueue_chunk(s, 0, SECTION_OPEN "Neighbors" CONTENT_OPEN));
 
-  for(s->nbr = nbr_table_head(ds6_neighbors); s->nbr != NULL;
-      s->nbr = nbr_table_next(ds6_neighbors, s->nbr)) {
+  for(s->nbr = uip_ds6_nbr_head(); s->nbr != NULL;
+      s->nbr = uip_ds6_nbr_next(s->nbr)) {
 
     PT_WAIT_THREAD(&s->generate_pt, enqueue_chunk(s, 0, "\n"));
 
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/httpd-simple.h b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/httpd-simple.h
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/httpd-simple.h
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/httpd-simple.h
index 25b8db3e5fe4ff8cea2c4a4fd9b245ba9ee0f14e..2b04b264c687938fa24082f7673d094e31b3b0e1 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/httpd-simple.h
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/httpd-simple.h
@@ -44,7 +44,7 @@
 /*---------------------------------------------------------------------------*/
 #include "contiki-net.h"
 #include "sys/process.h"
-#include "cc26xx-web-demo.h"
+#include "cc26x0-web-demo.h"
 /*---------------------------------------------------------------------------*/
 /* Ideally a multiple of TCP_MSS */
 #ifdef HTTPD_SIMPLE_CONF_MAIN_BUF_SIZE
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/img/6lbr-web.png b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/img/6lbr-web.png
similarity index 100%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/img/6lbr-web.png
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/img/6lbr-web.png
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/img/ibm-watson-iot-platform-tls-optional.png b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/img/ibm-watson-iot-platform-tls-optional.png
similarity index 100%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/img/ibm-watson-iot-platform-tls-optional.png
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/img/ibm-watson-iot-platform-tls-optional.png
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/img/quickstart-sensortag.png b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/img/quickstart-sensortag.png
similarity index 100%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/img/quickstart-sensortag.png
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/img/quickstart-sensortag.png
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/img/sensor-readings-config.png b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/img/sensor-readings-config.png
similarity index 100%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/img/sensor-readings-config.png
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/img/sensor-readings-config.png
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/img/well-known-core.png b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/img/well-known-core.png
similarity index 100%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/img/well-known-core.png
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/img/well-known-core.png
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/mqtt-client.c b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/mqtt-client.c
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/mqtt-client.c
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/mqtt-client.c
index 7562fb89a3298e938740c47401b853cd4ee7d8b2..0250de322ea76cb8a6cecb03e1819e6fd694af27 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/mqtt-client.c
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/mqtt-client.c
@@ -28,7 +28,7 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 /**
- * \addtogroup cc26xx-web-demo
+ * \addtogroup cc26x0-web-demo
  * @{
  *
  * \file
@@ -45,7 +45,7 @@
 #include "lib/sensors.h"
 #include "dev/button-hal.h"
 #include "board-peripherals.h"
-#include "cc26xx-web-demo.h"
+#include "cc26x0-web-demo.h"
 #include "dev/leds.h"
 #include "mqtt-client.h"
 #include "httpd-simple.h"
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/mqtt-client.h b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/mqtt-client.h
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/mqtt-client.h
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/mqtt-client.h
index ab7c08227530b1e2e7cedf514aebdf691d6bc4ef..68b26af6d4bdd464fe4a13c1b188f6883f3e2aa1 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/mqtt-client.h
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/mqtt-client.h
@@ -28,7 +28,7 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 /**
- * \addtogroup cc26xx-web-demo
+ * \addtogroup cc26x0-web-demo
  * @{
  *
  * \file
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/net-uart.c b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/net-uart.c
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/net-uart.c
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/net-uart.c
index ca3bf8c82a0c5735252bbdf0883e8b59a337c269..a2ea899da1bbda3b781bb0944f961c3bd35cd143 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/net-uart.c
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/net-uart.c
@@ -28,7 +28,7 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 /**
- * \addtogroup cc26xx-web-demo
+ * \addtogroup cc26x0-web-demo
  * @{
  *
  * \file
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/net-uart.h b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/net-uart.h
similarity index 100%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/net-uart.h
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/net-uart.h
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/project-conf.h b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/project-conf.h
similarity index 100%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/project-conf.h
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/project-conf.h
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-ble-advd.c
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-ble-advd.c
index a94a0b7a050506e60396f64ae073e9cbae7f3c9a..b32cb82ecd996de4c5c860b184263fee52e4f638 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-ble-advd.c
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-ble-advd.c
@@ -28,7 +28,7 @@
  */
 /*---------------------------------------------------------------------------*/
 /**
- * \addtogroup cc26xx-web-demo
+ * \addtogroup cc26x0-web-demo
  * @{
  *
  * \file
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-device.c
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-device.c
index 46344d1efcfc76f53b407a3db56495eb4d2b73e2..bc61b85107e8504d1c6a841fe72dc452d528a269 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-device.c
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-device.c
@@ -29,7 +29,7 @@
  */
 /*---------------------------------------------------------------------------*/
 /**
- * \addtogroup cc26xx-web-demo
+ * \addtogroup cc26x0-web-demo
  * @{
  *
  * \file
@@ -41,7 +41,7 @@
 #include "coap.h"
 #include "sys/clock.h"
 #include "coap-server.h"
-#include "cc26xx-web-demo.h"
+#include "cc26x0-web-demo.h"
 
 #include "ti-lib.h"
 
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-leds.c
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-leds.c
index 6c396145c5b7a9e05c2b1805ea87ceefe625e645..538ecc0bdb8b0ee63bc5036a27a98a11d60dec4d 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-leds.c
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-leds.c
@@ -29,7 +29,7 @@
  */
 /*---------------------------------------------------------------------------*/
 /**
- * \addtogroup cc26xx-web-demo
+ * \addtogroup cc26x0-web-demo
  * @{
  *
  * \file
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-net.c
similarity index 98%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-net.c
index 81575f345ed6ca7753c0054a0f137cd0ddd6dff1..43a4da354f426818aee8c0da21d12a0c88edbd9f 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-net.c
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-net.c
@@ -29,7 +29,7 @@
  */
 /*---------------------------------------------------------------------------*/
 /**
- * \addtogroup cc26xx-web-demo
+ * \addtogroup cc26x0-web-demo
  * @{
  *
  * \file
@@ -41,7 +41,7 @@
 #include "coap.h"
 #include "net/ipv6/uip-ds6.h"
 #include "coap-server.h"
-#include "cc26xx-web-demo.h"
+#include "cc26x0-web-demo.h"
 
 #include "ti-lib.h"
 
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-sensors.c
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-sensors.c
index 9ccc79e977eaa082d3eabd82baa9b8ea607934e9..1852f7cb6ab876065ef34ace6b5b9a0447e3f60a 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-sensors.c
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-sensors.c
@@ -29,7 +29,7 @@
  */
 /*---------------------------------------------------------------------------*/
 /**
- * \addtogroup cc26xx-web-demo
+ * \addtogroup cc26x0-web-demo
  * @{
  *
  * \file
@@ -39,7 +39,7 @@
 #include "contiki.h"
 #include "coap-engine.h"
 #include "coap.h"
-#include "cc26xx-web-demo.h"
+#include "cc26x0-web-demo.h"
 #include "coap-server.h"
 
 #include <stdio.h>
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-toggle-leds.c
similarity index 99%
rename from examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c
rename to examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-toggle-leds.c
index 1c708b53979d3f5f89ae513efb8520a674ae24a7..00e632cef62cc9892a3309432535d94de2ed39e3 100644
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/resources/res-toggle-leds.c
+++ b/examples/platform-specific/cc26x0-cc13x0/cc26x0-web-demo/resources/res-toggle-leds.c
@@ -31,7 +31,7 @@
  */
 /*---------------------------------------------------------------------------*/
 /**
- * \addtogroup cc26xx-web-demo
+ * \addtogroup cc26x0-web-demo
  * @{
  *
  * \file
diff --git a/examples/platform-specific/cc26xx/project-conf.h b/examples/platform-specific/cc26x0-cc13x0/project-conf.h
similarity index 100%
rename from examples/platform-specific/cc26xx/project-conf.h
rename to examples/platform-specific/cc26x0-cc13x0/project-conf.h
diff --git a/examples/platform-specific/cc26xx/very-sleepy-demo/Makefile b/examples/platform-specific/cc26x0-cc13x0/very-sleepy-demo/Makefile
similarity index 83%
rename from examples/platform-specific/cc26xx/very-sleepy-demo/Makefile
rename to examples/platform-specific/cc26x0-cc13x0/very-sleepy-demo/Makefile
index 46da822d30de30865dc3c9aeade785630b8c713d..d62dff3e3908718b149b1f63369de6bfcc605c40 100644
--- a/examples/platform-specific/cc26xx/very-sleepy-demo/Makefile
+++ b/examples/platform-specific/cc26x0-cc13x0/very-sleepy-demo/Makefile
@@ -1,6 +1,6 @@
 CONTIKI_PROJECT = very-sleepy-demo
 
-PLATFORMS_ONLY = srf06-cc26xx
+PLATFORMS_ONLY = cc26x0-cc13x0
 
 all: $(CONTIKI_PROJECT)
 
diff --git a/examples/platform-specific/cc26x0-cc13x0/very-sleepy-demo/Makefile.target b/examples/platform-specific/cc26x0-cc13x0/very-sleepy-demo/Makefile.target
new file mode 100644
index 0000000000000000000000000000000000000000..bd54a4fc745fc86a3545e3d6c01d4412787e56fc
--- /dev/null
+++ b/examples/platform-specific/cc26x0-cc13x0/very-sleepy-demo/Makefile.target
@@ -0,0 +1 @@
+TARGET = cc26x0-cc13x0
diff --git a/examples/platform-specific/cc26xx/very-sleepy-demo/README.md b/examples/platform-specific/cc26x0-cc13x0/very-sleepy-demo/README.md
similarity index 100%
rename from examples/platform-specific/cc26xx/very-sleepy-demo/README.md
rename to examples/platform-specific/cc26x0-cc13x0/very-sleepy-demo/README.md
diff --git a/examples/platform-specific/cc26xx/very-sleepy-demo/project-conf.h b/examples/platform-specific/cc26x0-cc13x0/very-sleepy-demo/project-conf.h
similarity index 100%
rename from examples/platform-specific/cc26xx/very-sleepy-demo/project-conf.h
rename to examples/platform-specific/cc26x0-cc13x0/very-sleepy-demo/project-conf.h
diff --git a/examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c b/examples/platform-specific/cc26x0-cc13x0/very-sleepy-demo/very-sleepy-demo.c
similarity index 100%
rename from examples/platform-specific/cc26xx/very-sleepy-demo/very-sleepy-demo.c
rename to examples/platform-specific/cc26x0-cc13x0/very-sleepy-demo/very-sleepy-demo.c
diff --git a/examples/platform-specific/cc26xx/Makefile.target b/examples/platform-specific/cc26xx/Makefile.target
deleted file mode 100644
index 15890aa6a6a43ab4a63a76175585365df3847951..0000000000000000000000000000000000000000
--- a/examples/platform-specific/cc26xx/Makefile.target
+++ /dev/null
@@ -1 +0,0 @@
-TARGET = srf06-cc26xx
diff --git a/examples/platform-specific/cc26xx/ble-ipv6/Makefile b/examples/platform-specific/cc26xx/ble-ipv6/Makefile
deleted file mode 100644
index 4ba928ad3fa1280cfb8070ed691a54c2e636d5ed..0000000000000000000000000000000000000000
--- a/examples/platform-specific/cc26xx/ble-ipv6/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-CONTIKI_PROJECT=client
-
-all: $(CONTIKI_PROJECT)
-
-PLATFORMS_ONLY = srf06-cc26xx
-BOARDS_ONLY = launchpad/cc2650 sensortag/cc2650 srf06/cc26xx
-
-MAKE_MAC = MAKE_MAC_BLE
-MAKE_NET = MAKE_NET_IPV6
-CONTIKI = ../../../..
-include $(CONTIKI)/Makefile.include
\ No newline at end of file
diff --git a/examples/platform-specific/cc26xx/cc26xx-web-demo/Makefile.target b/examples/platform-specific/cc26xx/cc26xx-web-demo/Makefile.target
deleted file mode 100644
index 15890aa6a6a43ab4a63a76175585365df3847951..0000000000000000000000000000000000000000
--- a/examples/platform-specific/cc26xx/cc26xx-web-demo/Makefile.target
+++ /dev/null
@@ -1 +0,0 @@
-TARGET = srf06-cc26xx
diff --git a/examples/platform-specific/cc26xx/very-sleepy-demo/Makefile.target b/examples/platform-specific/cc26xx/very-sleepy-demo/Makefile.target
deleted file mode 100644
index 15890aa6a6a43ab4a63a76175585365df3847951..0000000000000000000000000000000000000000
--- a/examples/platform-specific/cc26xx/very-sleepy-demo/Makefile.target
+++ /dev/null
@@ -1 +0,0 @@
-TARGET = srf06-cc26xx
diff --git a/examples/platform-specific/jn516x/tsch/common-conf-jn516x.h b/examples/platform-specific/jn516x/tsch/common-conf-jn516x.h
index 568fd4b6d5e0b278f2fa38c5806796da83276eff..32f7534e73269d4569a7d076e6f7991d3118b565 100644
--- a/examples/platform-specific/jn516x/tsch/common-conf-jn516x.h
+++ b/examples/platform-specific/jn516x/tsch/common-conf-jn516x.h
@@ -44,7 +44,7 @@
 #define REST_MAX_CHUNK_SIZE      256
 
 /* Network config */
-//#define UIP_CONF_BUFFER_SIZE   (REST_MAX_CHUNK_SIZE + UIP_LLH_LEN + UIP_IPUDPH_LEN + COAP_MAX_HEADER_SIZE)
+//#define UIP_CONF_BUFFER_SIZE   (REST_MAX_CHUNK_SIZE + UIP_IPUDPH_LEN + COAP_MAX_HEADER_SIZE)
 //#define UIP_CONF_BUFFER_SIZE   (REST_MAX_CHUNK_SIZE + 0 + 48 + 70)
 #define UIP_CONF_BUFFER_SIZE     1280 /* ipv6 required minimum */
 
diff --git a/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/node.c b/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/node.c
index 251b0d1355c5f70bf6c9bf622c5cffc1330b0e5a..b3ef311fd10a9625cdf4cc36ce5c593b1de769d4 100644
--- a/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/node.c
+++ b/examples/platform-specific/jn516x/tsch/simple-sensor-network/node/node.c
@@ -50,8 +50,6 @@
 #define DEBUG DEBUG_PRINT
 #include "net/ipv6/uip-debug.h"
 
-#define UIP_IP_BUF   ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-
 #define INTERVAL    (10)
 #define BLINK_TIME  (CLOCK_SECOND/4)
 
diff --git a/examples/platform-specific/nrf52dk/coap-demo/coap-server/coap-server.c b/examples/platform-specific/nrf52dk/coap-demo/coap-server/coap-server.c
index 584f54318a30ecca10cc03ee9858bb2eff35b0fb..9e38d5d3a3fe742f9689d37dd83e1fa143937ca9 100644
--- a/examples/platform-specific/nrf52dk/coap-demo/coap-server/coap-server.c
+++ b/examples/platform-specific/nrf52dk/coap-demo/coap-server/coap-server.c
@@ -97,7 +97,6 @@ PROCESS_THREAD(er_example_server, ev, data)
   PRINTF("Starting Erbium Example Server\n");
 
   PRINTF("uIP buffer: %u\n", UIP_BUFSIZE);
-  PRINTF("LL header: %u\n", UIP_LLH_LEN);
   PRINTF("IP+UDP header: %u\n", UIP_IPUDPH_LEN);
   PRINTF("REST max chunk: %u\n", COAP_MAX_CHUNK_SIZE);
 
diff --git a/examples/platform-specific/zoul/Makefile b/examples/platform-specific/zoul/Makefile
index 3b57eb0355415bfcbab1d711395b0ff4eedb51fa..1f29bda4cada99850e2c3656f2883bc7eb6612ba 100644
--- a/examples/platform-specific/zoul/Makefile
+++ b/examples/platform-specific/zoul/Makefile
@@ -4,7 +4,7 @@ CONTIKI_PROJECT += test-grove-light-sensor test-grove-loudness-sensor
 CONTIKI_PROJECT += test-weather-meter test-grove-gyro test-lcd test-iaq
 CONTIKI_PROJECT += test-pm10-sensor test-vac-sensor test-aac-sensor
 CONTIKI_PROJECT += test-zonik test-dht22 test-ac-dimmer
-CONTIKI_PROJECT += test-bme280
+CONTIKI_PROJECT += test-bme280 test-vbat
 
 CONTIKI_TARGET_SOURCEFILES += tsl256x.c sht25.c bmpx8x.c motion-sensor.c
 CONTIKI_TARGET_SOURCEFILES += adc-sensors.c weather-meter.c grove-gyro.c
diff --git a/examples/platform-specific/zoul/orion/ip64-router/ip64-router.c b/examples/platform-specific/zoul/orion/ip64-router/ip64-router.c
index 5f2a98e24e41060f1f83d263e1f7f45c418515cb..4b3279e44cb9fba96c4ef4bdf78becfcdab61904 100644
--- a/examples/platform-specific/zoul/orion/ip64-router/ip64-router.c
+++ b/examples/platform-specific/zoul/orion/ip64-router/ip64-router.c
@@ -45,6 +45,7 @@
 #include "contiki-net.h"
 #include "net/ipv6/uip.h"
 #include "net/ipv6/uip-ds6.h"
+#include "net/ipv6/uip-ds6-nbr.h"
 #include "net/routing/routing.h"
 #include "dev/leds.h"
 #include "ip64/ip64.h"
@@ -142,9 +143,9 @@ PT_THREAD(generate_routes(struct httpd_state *s))
 #endif
   ADD("Neighbors<pre>");
 
-  for(nbr = nbr_table_head(ds6_neighbors);
+  for(nbr = uip_ds6_nbr_head();
       nbr != NULL;
-      nbr = nbr_table_next(ds6_neighbors, nbr)) {
+      nbr = uip_ds6_nbr_next(nbr)) {
 
 #if WEBSERVER_CONF_NEIGHBOR_STATUS
 #if BUF_USES_STACK
diff --git a/examples/platform-specific/zoul/test-vbat.c b/examples/platform-specific/zoul/test-vbat.c
new file mode 100644
index 0000000000000000000000000000000000000000..e72c6ef8c33c1c9f5d756ac81be25bbc61ab5460
--- /dev/null
+++ b/examples/platform-specific/zoul/test-vbat.c
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2016, Zolertia - http://www.zolertia.com
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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.
+ *
+ */
+/*---------------------------------------------------------------------------*/
+/**
+ * \file
+ *         An example showing how to get VBAT Voltage functionality on
+ *         RE-Mote Platform
+ * \author
+ *         Erik Bellido <ebellido@zolertia.com>
+ *         Aitor Mejias <amejias@zolertia.com>
+ */
+/*---------------------------------------------------------------------------*/
+/* This is the main contiki header, it should be included always */
+#include "contiki.h"
+#include "power-mgmt.h"
+#include "dev/i2c.h"
+#include "sys/etimer.h"
+/*---------------------------------------------------------------------------*/
+
+/*#define freq I2C_SCL_NORMAL_BUS_SPEED */
+static struct etimer et;
+
+/* RE-Mote revision B, low-power PIC version */
+#define PM_EXPECTED_VERSION               0x20
+
+/*---------------------------------------------------------------------------*/
+/* We are going to create three different processes, with its own printable
+ * name.  Processes are a great way to run different applications and features
+ * in parallel
+ */
+PROCESS(test_VBAT_process, "Test VBAT process");
+
+/* But we are only going to automatically start the first two */
+AUTOSTART_PROCESSES(&test_VBAT_process);
+/*---------------------------------------------------------------------------*/
+PROCESS_THREAD(test_VBAT_process, ev, data)
+{
+
+  static uint8_t aux = 0x00;
+  static uint16_t voltage = 0x00;
+
+  PROCESS_BEGIN();
+
+  if(pm_enable() != PM_SUCCESS) {
+    printf("PM Failed \n");
+  } else if(pm_enable() == PM_SUCCESS) {
+    printf("Process PM started\n");
+  }
+
+  if((pm_get_fw_ver(&aux) == PM_ERROR) || (aux != PM_EXPECTED_VERSION)) {
+    printf("PM: unexpected version 0x%02X\n", aux);
+  }
+  printf("PM: firmware version 0x%02X OK\n", aux);
+
+  while(1) {
+
+    etimer_set(&et, CLOCK_SECOND);
+
+    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
+
+    /*-------------------voltage VBAT --------------*/
+    if(pm_get_voltage(&voltage) != PM_SUCCESS) {
+      printf("PM: error retrieving voltage\n");
+    } else {
+      printf("%u.%u V\n", voltage / 100, voltage % 100);
+    }
+  }
+  PROCESS_END();
+}
diff --git a/examples/rpl-border-router/Makefile b/examples/rpl-border-router/Makefile
index 4d2db2a8525bf1ee516d195d87bb7e1e11d73e09..8d210dd3c5e91b850879e8a6ffbf8e16aef9d7d2 100644
--- a/examples/rpl-border-router/Makefile
+++ b/examples/rpl-border-router/Makefile
@@ -3,7 +3,7 @@ all: $(CONTIKI_PROJECT)
 CONTIKI = ../..
 
 # The BR is either native or embedded, and in the latter case must support SLIP
-PLATFORMS_EXCLUDE = nrf52dk
+PLATFORMS_EXCLUDE = nrf52dk z1
 
 # Include RPL BR module
 MODULES += os/services/rpl-border-router
diff --git a/examples/rpl-border-router/webserver/webserver.c b/examples/rpl-border-router/webserver/webserver.c
index 3658381bfc40ca22766cf5c6d5bc9c5844309f37..c4b472837781ec09daa84caf2b8584989e1320fd 100644
--- a/examples/rpl-border-router/webserver/webserver.c
+++ b/examples/rpl-border-router/webserver/webserver.c
@@ -32,6 +32,7 @@
 
 #include "contiki.h"
 #include "net/routing/routing.h"
+#include "net/ipv6/uip-ds6-nbr.h"
 #include "net/ipv6/uip-ds6-route.h"
 #include "net/ipv6/uip-sr.h"
 
@@ -90,9 +91,9 @@ PT_THREAD(generate_routes(struct httpd_state *s))
 
   ADD("  Neighbors\n  <ul>\n");
   SEND(&s->sout);
-  for(nbr = nbr_table_head(ds6_neighbors);
+  for(nbr = uip_ds6_nbr_head();
       nbr != NULL;
-      nbr = nbr_table_next(ds6_neighbors, nbr)) {
+      nbr = uip_ds6_nbr_next(nbr)) {
     ADD("    <li>");
     ipaddr_add(&nbr->ipaddr);
     ADD("</li>\n");
diff --git a/examples/rpl-udp/udp-client.c b/examples/rpl-udp/udp-client.c
index 1fb0300349505aba150572632faacc746ee1b518..5dc7a07639782e58036974d6aceaa85913160308 100644
--- a/examples/rpl-udp/udp-client.c
+++ b/examples/rpl-udp/udp-client.c
@@ -12,9 +12,6 @@
 #define UDP_CLIENT_PORT	8765
 #define UDP_SERVER_PORT	5678
 
-static struct simple_udp_connection udp_conn;
-
-#define START_INTERVAL		(15 * CLOCK_SECOND)
 #define SEND_INTERVAL		  (60 * CLOCK_SECOND)
 
 static struct simple_udp_connection udp_conn;
@@ -32,16 +29,21 @@ udp_rx_callback(struct simple_udp_connection *c,
          const uint8_t *data,
          uint16_t datalen)
 {
-  unsigned count = *(unsigned *)data;
-  LOG_INFO("Received response %u from ", count);
+
+  LOG_INFO("Received response '%.*s' from ", datalen, (char *) data);
   LOG_INFO_6ADDR(sender_addr);
+#if LLSEC802154_CONF_ENABLED
+  LOG_INFO_(" LLSEC LV:%d", uipbuf_get_attr(UIPBUF_ATTR_LLSEC_LEVEL));
+#endif
   LOG_INFO_("\n");
+
 }
 /*---------------------------------------------------------------------------*/
 PROCESS_THREAD(udp_client_process, ev, data)
 {
   static struct etimer periodic_timer;
   static unsigned count;
+  static char str[32];
   uip_ipaddr_t dest_ipaddr;
 
   PROCESS_BEGIN();
@@ -59,7 +61,8 @@ PROCESS_THREAD(udp_client_process, ev, data)
       LOG_INFO("Sending request %u to ", count);
       LOG_INFO_6ADDR(&dest_ipaddr);
       LOG_INFO_("\n");
-      simple_udp_sendto(&udp_conn, &count, sizeof(count), &dest_ipaddr);
+      snprintf(str, sizeof(str), "hello %d", count);
+      simple_udp_sendto(&udp_conn, str, strlen(str), &dest_ipaddr);
       count++;
     } else {
       LOG_INFO("Not reachable yet\n");
diff --git a/examples/rpl-udp/udp-server.c b/examples/rpl-udp/udp-server.c
index 399cabfc4c3156ae9f24bde6ab556c77e0663fd5..072eb8ae8694e4606317d06d9f71a7d4b506c937 100644
--- a/examples/rpl-udp/udp-server.c
+++ b/examples/rpl-udp/udp-server.c
@@ -54,15 +54,13 @@ udp_rx_callback(struct simple_udp_connection *c,
          const uint8_t *data,
          uint16_t datalen)
 {
-  unsigned count = *(unsigned *)data;
-  LOG_INFO("Received request %u from ", count);
+  LOG_INFO("Received request '%.*s' from ", datalen, (char *) data);
   LOG_INFO_6ADDR(sender_addr);
   LOG_INFO_("\n");
 #if WITH_SERVER_REPLY
-  LOG_INFO("Sending response %u to ", count);
-  LOG_INFO_6ADDR(sender_addr);
-  LOG_INFO_("\n");
-  simple_udp_sendto(&udp_conn, &count, sizeof(count), sender_addr);
+  /* send back the same string to the client as an echo reply */
+  LOG_INFO("Sending response.\n");
+  simple_udp_sendto(&udp_conn, data, datalen, sender_addr);
 #endif /* WITH_SERVER_REPLY */
 }
 /*---------------------------------------------------------------------------*/
diff --git a/examples/sensniff/Makefile b/examples/sensniff/Makefile
index 090bc694d758191a79121377e74dfdf02b6a6a1f..f931aed775f6cef2c6926863ce4853fbd0327658 100644
--- a/examples/sensniff/Makefile
+++ b/examples/sensniff/Makefile
@@ -1,7 +1,7 @@
 CONTIKI_PROJECT = sensniff
 CONTIKI = ../..
 
-PLATFORMS_ONLY = cc2538dk openmote-cc2538 zoul srf06-cc26xx jn516x simplelink
+PLATFORMS_ONLY = cc2538dk openmote-cc2538 z1 zoul cc26x0-cc13x0 jn516x simplelink
 
 PROJECT_SOURCEFILES += sensniff-mac.c netstack.c
 MODULES_REL += pool $(TARGET)
@@ -10,9 +10,11 @@ include $(CONTIKI)/Makefile.identify-target
 
 all: $(CONTIKI_PROJECT)
 
+# Disable all networking layer 3 upwards 
+MAKE_NET=MAKE_NET_NULLNET
+
 # use a custom MAC driver: sensniff_mac_driver
 MAKE_MAC = MAKE_MAC_OTHER
-include $(CONTIKI)/Makefile.include
 
 PYTHON ?= python
 SENSNIFF = $(CONTIKI)/tools/sensniff/sensniff.py
@@ -27,6 +29,8 @@ ifneq ($(PORT),)
   SENSNIFF_FLAGS += -d $(PORT)
 endif
 
+include $(CONTIKI)/Makefile.include
+
 sniff:
 ifeq ($(wildcard $(SENSNIFF)), )
 	$(error Could not find the sensniff script. Did you run 'git submodule update --init' ?")
diff --git a/examples/sensniff/srf06-cc26xx/target-conf.h b/examples/sensniff/cc26x0-cc13x0/target-conf.h
similarity index 100%
rename from examples/sensniff/srf06-cc26xx/target-conf.h
rename to examples/sensniff/cc26x0-cc13x0/target-conf.h
diff --git a/examples/sensniff/sensniff-mac.c b/examples/sensniff/sensniff-mac.c
index aa78897b66ff4dbecb83c8b11ad25709406707c3..75525de1a680fccf3e18025058107ef6fc3e84b6 100644
--- a/examples/sensniff/sensniff-mac.c
+++ b/examples/sensniff/sensniff-mac.c
@@ -69,12 +69,19 @@ init(void)
   on();
 }
 /*---------------------------------------------------------------------------*/
+static int
+max_payload(void)
+{
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
 const struct mac_driver sensniff_mac_driver = {
   "sensniff-rdc",
   init,
   send,
   input,
   on,
-  off
+  off,
+  max_payload,
 };
 /*---------------------------------------------------------------------------*/
diff --git a/examples/sensniff/pool/cc2530-cc2531-io.h b/examples/sensniff/z1/target-conf.h
similarity index 87%
rename from examples/sensniff/pool/cc2530-cc2531-io.h
rename to examples/sensniff/z1/target-conf.h
index cfed98f1de887a60ba40ae9cad5372582c30fdec..6e3db2b48ef66b9bca0795ddbfd3dd14a4753050 100644
--- a/examples/sensniff/pool/cc2530-cc2531-io.h
+++ b/examples/sensniff/z1/target-conf.h
@@ -29,15 +29,13 @@
  * OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 /*---------------------------------------------------------------------------*/
-#ifndef CC2530_CC2531_IO_H_
-#define CC2530_CC2531_IO_H_
+#ifndef TARGET_CONF_H_
+#define TARGET_CONF_H_
 /*---------------------------------------------------------------------------*/
-#include "contiki.h"
-#include "dev/io-arch.h"
+#define MSP430_IO_CONF_USE_UART1             0
+#define UART0_CONF_BAUD_RATE            460800
 /*---------------------------------------------------------------------------*/
-#define sensniff_io_byte_out(b)  io_arch_writeb(b)
-#define sensniff_io_flush()      io_arch_flush()
-#define sensniff_io_set_input(f) io_arch_set_input(f)
+#define SENSNIFF_IO_DRIVER_H "pool/msp430-io.h"
 /*---------------------------------------------------------------------------*/
-#endif /* CC2530_CC2531_IO_H_ */
+#endif /* TARGET_CONF_H_ */
 /*---------------------------------------------------------------------------*/
diff --git a/examples/slip-radio/slip-radio.c b/examples/slip-radio/slip-radio.c
index a20bd86765739b0c644b609f5aaea33e6e7d69e4..8ef22ff55892b38e9a656e68a5881bf72815c599 100644
--- a/examples/slip-radio/slip-radio.c
+++ b/examples/slip-radio/slip-radio.c
@@ -226,12 +226,11 @@ slip_radio_cmd_handler(const uint8_t *data, int len)
 static void
 slip_input_callback(void)
 {
-  LOG_DBG("SR-SIN: %u '%c%c'\n", uip_len,
-          uip_buf[UIP_LLH_LEN], uip_buf[UIP_LLH_LEN + 1]);
-  if(!cmd_input(&uip_buf[UIP_LLH_LEN], uip_len)) {
+  LOG_DBG("SR-SIN: %u '%c%c'\n", uip_len, uip_buf[0], uip_buf[1]);
+  if(!cmd_input(uip_buf, uip_len)) {
     cmd_send((uint8_t *)"EUnknown command", 16);
   }
-  uip_clear_buf();
+  uipbuf_clear();
 }
 /*---------------------------------------------------------------------------*/
 static void
diff --git a/examples/storage/cfs-coffee/README.md b/examples/storage/cfs-coffee/README.md
index 028f518f83d024246595e22be706e71d9ab21ee2..640124d5629e246000b995178d86eabf8a704637 100644
--- a/examples/storage/cfs-coffee/README.md
+++ b/examples/storage/cfs-coffee/README.md
@@ -23,7 +23,7 @@ Supported Hardware (tested or known to work)
 * cc2538dk
 * openmote-cc2538
 * zoul
-* TI srf06-cc26xx
+* TI cc26x0-cc13x0
     - sensortag
     - launchpad
 
diff --git a/examples/websocket/Makefile b/examples/websocket/Makefile
index 87d0789c19c35c28e489b3cfe5db5d2b6de076fb..d0b38d95d27cb9f8a18805947e632cd57b1b0787 100644
--- a/examples/websocket/Makefile
+++ b/examples/websocket/Makefile
@@ -3,6 +3,6 @@ all: $(CONTIKI_PROJECT)
 CONTIKI=../..
 MODULES += os/net/app-layer/http-socket
 
-PLATFORMS_EXCLUDE = sky
+PLATFORMS_EXCLUDE = sky z1
 
 include $(CONTIKI)/Makefile.include
diff --git a/os/contiki-default-conf.h b/os/contiki-default-conf.h
index f8fbc9933933bf0b299f7e2305ee9ae8ad2c4740..947b5f3f68338d783c4b870e11896d76a052a3b7 100644
--- a/os/contiki-default-conf.h
+++ b/os/contiki-default-conf.h
@@ -197,14 +197,6 @@
 #define SICSLOWPAN_CONF_FRAG 1
 #endif /* SICSLOWPAN_CONF_FRAG */
 
-/* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD is the maximum available size for
-   frame headers, link layer security-related overhead,  as well as
-   6LoWPAN payload. By default, SICSLOWPAN_CONF_MAC_MAX_PAYLOAD is
-   127 bytes (MTU of 802.15.4) - 2 bytes (Footer of 802.15.4). */
-#ifndef SICSLOWPAN_CONF_MAC_MAX_PAYLOAD
-#define SICSLOWPAN_CONF_MAC_MAX_PAYLOAD (127 - 2)
-#endif /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */
-
 /* SICSLOWPAN_CONF_COMPRESSION specifies what 6lowpan compression
    mechanism to be used. 6lowpan hc06 is the default in Contiki. */
 #ifndef SICSLOWPAN_CONF_COMPRESSION
diff --git a/os/contiki-main.c b/os/contiki-main.c
index db88937170db239ed0c5f00d6d62d003730e6fe0..43e3017464a74e73a60b443a992a3f484d66042a 100644
--- a/os/contiki-main.c
+++ b/os/contiki-main.c
@@ -48,6 +48,7 @@
 #include "sys/stack-check.h"
 #include "dev/watchdog.h"
 
+#include "net/queuebuf.h"
 #include "net/app-layer/coap/coap-engine.h"
 #include "services/rpl-border-router/rpl-border-router.h"
 #include "services/orchestra/orchestra.h"
@@ -89,6 +90,9 @@ main(void)
 
   platform_init_stage_two();
 
+#if QUEUEBUF_ENABLED
+  queuebuf_init();
+#endif /* QUEUEBUF_ENABLED */
   netstack_init();
   node_id_init();
 
diff --git a/os/contiki-net.h b/os/contiki-net.h
index 1eb50dd8d0aaeba60d0a6000787892d985d91f58..6384c51ef9222055aee22073f40637c2a633f075 100644
--- a/os/contiki-net.h
+++ b/os/contiki-net.h
@@ -44,10 +44,8 @@
 #include "net/ipv6/uip-nameserver.h"
 #include "net/routing/routing.h"
 
-#if NETSTACK_CONF_WITH_IPV6
 #include "net/ipv6/uip-icmp6.h"
 #include "net/ipv6/uip-ds6.h"
-#endif /* NETSTACK_CONF_WITH_IPV6 */
 
 #include "net/ipv6/resolv.h"
 
diff --git a/os/dev/button-hal.c b/os/dev/button-hal.c
index 58cded79023b43c137b40957d468faa7ed2a3485..547407432a8ce9436bf6ef4cf14647fa47dc3a23 100644
--- a/os/dev/button-hal.c
+++ b/os/dev/button-hal.c
@@ -62,6 +62,12 @@ extern button_hal_button_t *button_hal_buttons[];
 /* Common handler for all handler events, and register it with the GPIO HAL */
 static gpio_hal_event_handler_t button_event_handler;
 /*---------------------------------------------------------------------------*/
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define BTN_PORT(b) (b)->port
+#else
+#define BTN_PORT(b) GPIO_HAL_NULL_PORT
+#endif
+/*---------------------------------------------------------------------------*/
 static void
 duration_exceeded_callback(void *btn)
 {
@@ -121,7 +127,11 @@ debounce_handler(void *btn)
 }
 /*---------------------------------------------------------------------------*/
 static void
-press_release_handler(gpio_hal_pin_mask_t pin_mask)
+press_release_handler(
+#if GPIO_HAL_PORT_PIN_NUMBERING
+                      gpio_hal_port_t port,
+#endif
+                      gpio_hal_pin_mask_t pin_mask)
 {
   pmask |= pin_mask;
   process_poll(&button_hal_process);
@@ -154,7 +164,7 @@ button_hal_get_by_index(uint8_t index)
 uint8_t
 button_hal_get_state(button_hal_button_t *button)
 {
-  uint8_t pin_state = gpio_hal_arch_read_pin(button->pin);
+  uint8_t pin_state = gpio_hal_arch_read_pin(BTN_PORT(button), button->pin);
 
   if((pin_state == 0 && button->negative_logic == true) ||
      (pin_state == 1 && button->negative_logic == false)) {
@@ -180,9 +190,9 @@ button_hal_init()
   for(button = button_hal_buttons; *button != NULL; button++) {
     cfg = GPIO_HAL_PIN_CFG_EDGE_BOTH | GPIO_HAL_PIN_CFG_INT_ENABLE |
       (*button)->pull;
-    gpio_hal_arch_pin_set_input((*button)->pin);
-    gpio_hal_arch_pin_cfg_set((*button)->pin, cfg);
-    gpio_hal_arch_interrupt_enable((*button)->pin);
+    gpio_hal_arch_pin_set_input(BTN_PORT(*button), (*button)->pin);
+    gpio_hal_arch_pin_cfg_set(BTN_PORT(*button), (*button)->pin, cfg);
+    gpio_hal_arch_interrupt_enable(BTN_PORT(*button), (*button)->pin);
     button_event_handler.pin_mask |= gpio_hal_pin_to_mask((*button)->pin);
   }
 
diff --git a/os/dev/button-hal.h b/os/dev/button-hal.h
index c1822ff8eb276a1b3c035511d22891dc3a52c343..8b6110ee217d90ce1fab6433bd37026c8b7d55b2 100644
--- a/os/dev/button-hal.h
+++ b/os/dev/button-hal.h
@@ -151,6 +151,11 @@ struct button_hal_button_s {
   /** True if the button uses negative logic (active: low) */
   const bool negative_logic;
 
+#if GPIO_HAL_PORT_PIN_NUMBERING
+  /** The gpio port connected to the button */
+  gpio_hal_port_t port;
+#endif
+
   /** The gpio pin connected to the button */
   const gpio_hal_pin_t pin;
 
@@ -172,23 +177,36 @@ struct button_hal_button_s {
 };
 /*---------------------------------------------------------------------------*/
 #if BUTTON_HAL_WITH_DESCRIPTION
+#if GPIO_HAL_PORT_PIN_NUMBERING
 /**
  * \brief Define a button to be used by the HAL
  * \param name The variable name for the button
  * \param descr A textual description
- * \param p The pin connected to the button
+ * \param po The port connected to the button
+ * \param pi The pin connected to the button
  * \param nl True if the button is connected using negative logic
  * \param u The button's pull configuration
  * \param id A unique numeric identifier
  */
-#define BUTTON_HAL_BUTTON(name, descr, p, u, id, nl) \
+#define BUTTON_HAL_BUTTON(name, descr, po, pi, u, id, nl) \
   static button_hal_button_t name = { \
     .description = descr, \
-    .pin = p, \
+    .port = po, \
+    .pin = pi, \
     .pull = u, \
     .unique_id = id, \
     .negative_logic = nl, \
   }
+#else /* GPIO_HAL_PORT_PIN_NUMBERING */
+#define BUTTON_HAL_BUTTON(name, descr, pi, u, id, nl) \
+  static button_hal_button_t name = { \
+    .description = descr, \
+    .pin = pi, \
+    .pull = u, \
+    .unique_id = id, \
+    .negative_logic = nl, \
+  }
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
 
 /**
  * \brief Retrieve the textual description of a button
@@ -198,17 +216,30 @@ struct button_hal_button_s {
  * BUTTON_HAL_WITH_DESCRIPTION is 0 then this macro will return ""
  */
 #define BUTTON_HAL_GET_DESCRIPTION(b) (b)->description
-#else
-#define BUTTON_HAL_BUTTON(name, descr, p, u, id, nl) \
+
+#else /* BUTTON_HAL_WITH_DESCRIPTION */
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define BUTTON_HAL_BUTTON(name, descr, po, pi, u, id, nl) \
+  static button_hal_button_t name = { \
+    .port = po, \
+    .pin = pi, \
+    .pull = u, \
+    .unique_id = id, \
+    .negative_logic = nl, \
+  }
+#else /* GPIO_HAL_PORT_PIN_NUMBERING */
+#define BUTTON_HAL_BUTTON(name, descr, pi, u, id, nl) \
   static button_hal_button_t name = { \
-    .pin = p, \
+    .pin = pi, \
     .pull = u, \
     .unique_id = id, \
     .negative_logic = nl, \
   }
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
 
 #define BUTTON_HAL_GET_DESCRIPTION(b) ""
-#endif
+#endif /* BUTTON_HAL_WITH_DESCRIPTION */
 /*---------------------------------------------------------------------------*/
 #define BUTTON_HAL_BUTTONS(...) \
   button_hal_button_t *button_hal_buttons[] = {__VA_ARGS__, NULL}; \
diff --git a/os/dev/gpio-hal.c b/os/dev/gpio-hal.c
index 949d829a7282122e37fcec328e272bac44b27878..880985502ad13ed3e6a1176a81f36c731d5be613 100644
--- a/os/dev/gpio-hal.c
+++ b/os/dev/gpio-hal.c
@@ -57,6 +57,24 @@ gpio_hal_register_handler(gpio_hal_event_handler_t *handler)
   list_add(handlers, handler);
 }
 /*---------------------------------------------------------------------------*/
+#if GPIO_HAL_PORT_PIN_NUMBERING
+/*---------------------------------------------------------------------------*/
+void
+gpio_hal_event_handler(gpio_hal_port_t port, gpio_hal_pin_mask_t pins)
+{
+  gpio_hal_event_handler_t *this;
+
+  for(this = list_head(handlers); this != NULL; this = this->next) {
+    if((port == this->port) && (pins & this->pin_mask)) {
+      if(this->handler != NULL) {
+        this->handler(port, pins & this->pin_mask);
+      }
+    }
+  }
+}
+/*---------------------------------------------------------------------------*/
+#else
+/*---------------------------------------------------------------------------*/
 void
 gpio_hal_event_handler(gpio_hal_pin_mask_t pins)
 {
@@ -71,6 +89,8 @@ gpio_hal_event_handler(gpio_hal_pin_mask_t pins)
   }
 }
 /*---------------------------------------------------------------------------*/
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+/*---------------------------------------------------------------------------*/
 void
 gpio_hal_init()
 {
@@ -81,20 +101,35 @@ gpio_hal_init()
 #if GPIO_HAL_ARCH_SW_TOGGLE
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_toggle_pin(gpio_hal_pin_t pin)
+gpio_hal_arch_port_toggle_pin(gpio_hal_port_t port, gpio_hal_pin_t pin)
+{
+  gpio_hal_arch_write_pin(port, pin, gpio_hal_arch_read_pin(port, pin) ^ 1);
+}
+/*---------------------------------------------------------------------------*/
+void
+gpio_hal_arch_port_toggle_pins(gpio_hal_port_t port, gpio_hal_pin_mask_t pins)
+{
+  gpio_hal_arch_write_pins(port, pins, ~gpio_hal_arch_read_pins(port, pins));
+}
+/*---------------------------------------------------------------------------*/
+void
+gpio_hal_arch_no_port_toggle_pin(gpio_hal_pin_t pin)
 {
   if(pin >= GPIO_HAL_PIN_COUNT) {
     LOG_ERR("Pin %u out of bounds\n", pin);
     return;
   }
 
-  gpio_hal_arch_write_pin(pin, gpio_hal_arch_read_pin(pin) ^ 1);
+  gpio_hal_arch_write_pin(GPIO_HAL_NULL_PORT, pin,
+                          gpio_hal_arch_read_pin(GPIO_HAL_NULL_PORT, pin) ^ 1);
 }
 /*---------------------------------------------------------------------------*/
 void
-gpio_hal_arch_toggle_pins(gpio_hal_pin_mask_t pins)
+gpio_hal_arch_no_port_toggle_pins(gpio_hal_pin_mask_t pins)
 {
-  gpio_hal_arch_write_pins(pins, ~gpio_hal_arch_read_pins(pins));
+  gpio_hal_arch_write_pins(GPIO_HAL_NULL_PORT, pins,
+                           ~gpio_hal_arch_read_pins(GPIO_HAL_NULL_PORT,
+                                                    pins));
 }
 /*---------------------------------------------------------------------------*/
 #endif /* GPIO_HAL_ARCH_SW_TOGGLE */
diff --git a/os/dev/gpio-hal.h b/os/dev/gpio-hal.h
index 5ad9f472bc2efea2625d11812edcda8129d1d143..cc7748cc5acc14a26c2637ee7e609690a7c8d123 100644
--- a/os/dev/gpio-hal.h
+++ b/os/dev/gpio-hal.h
@@ -55,6 +55,24 @@
 
 #include <stdint.h>
 /*---------------------------------------------------------------------------*/
+/**
+ * \brief Specifies whether the HAL should support a port/pin convention
+ *
+ * Some MCUs specify GPIOs as a port/pin combination, whereas some others
+ * only use a pin number. Our GPIO HAL supports both conventions in a portable
+ * fashion and this define is used to set the HAL in the desired of the two
+ * modes.
+ *
+ * The port developer should define GPIO_HAL_CONF_PORT_PIN_NUMBERING as a if
+ * the platform uses port/pin numbering, or to 0 if the platform only uses
+ * a simple number.
+ */
+#ifdef GPIO_HAL_CONF_PORT_PIN_NUMBERING
+#define GPIO_HAL_PORT_PIN_NUMBERING GPIO_HAL_CONF_PORT_PIN_NUMBERING
+#else
+#define GPIO_HAL_PORT_PIN_NUMBERING 1
+#endif
+/*---------------------------------------------------------------------------*/
 /**
  * \brief Specifies whether software-based pin toggle is required
  *
@@ -71,11 +89,26 @@
 #define GPIO_HAL_ARCH_SW_TOGGLE 1
 #endif
 /*---------------------------------------------------------------------------*/
+/**
+ * \brief Convenience macro to use this as the port argument of macros
+ *
+ * Use this as the port \e argument of macros when GPIO_HAL_PORT_PIN_NUMBERING
+ * is zero
+ */
+#define GPIO_HAL_NULL_PORT      0
+/*---------------------------------------------------------------------------*/
 /**
  * \brief GPIO pin number representation
  */
 typedef uint8_t gpio_hal_pin_t;
 
+/**
+ * \brief A data structure that represents ports.
+ *
+ * This is only relevant if GPIO_HAL_PORT_PIN_NUMBERING is non-zero
+ */
+typedef uint8_t gpio_hal_port_t;
+
 /**
  * \brief GPIO pin configuration
  *
@@ -84,22 +117,37 @@ typedef uint8_t gpio_hal_pin_t;
  */
 typedef uint32_t gpio_hal_pin_cfg_t;
 
+/**
+ * \brief Specifies the total number of pins on a device
+ *
+ * This macro has no effect if GPIO_HAL_PORT_PIN_NUMBERING is non-zero.
+ */
 #ifdef GPIO_HAL_CONF_PIN_COUNT
 #define GPIO_HAL_PIN_COUNT GPIO_HAL_CONF_PIN_COUNT
 #else
 #define GPIO_HAL_PIN_COUNT 32
 #endif
 
-#if GPIO_HAL_PIN_COUNT > 32
+#if GPIO_HAL_PIN_COUNT > 32 && !GPIO_HAL_PORT_PIN_NUMBERING
 typedef uint64_t gpio_hal_pin_mask_t;
 #else
 /**
  * \brief GPIO pin mask representation
+ *
+ * A mask that can be used to represent multiple pins using a single variable.
+ *
+ * When GPIO_HAL_PORT_PIN_NUMBERING is non-zero, such variables can only be
+ * used to represent pins within the same port.
  */
 typedef uint32_t gpio_hal_pin_mask_t;
 #endif
-
+/*---------------------------------------------------------------------------*/
+#if GPIO_HAL_PORT_PIN_NUMBERING
+typedef void (*gpio_hal_callback_t)(gpio_hal_port_t port,
+                                    gpio_hal_pin_mask_t pin_mask);
+#else
 typedef void (*gpio_hal_callback_t)(gpio_hal_pin_mask_t pin_mask);
+#endif
 /*---------------------------------------------------------------------------*/
 #define GPIO_HAL_PIN_CFG_PULL_NONE        0x00
 #define GPIO_HAL_PIN_CFG_PULL_UP          0x01
@@ -125,10 +173,16 @@ typedef void (*gpio_hal_callback_t)(gpio_hal_pin_mask_t pin_mask);
  * A GPIO event handler is a function that gets called whenever a pin triggers
  * an event. The same handler can be registered to handle events for more than
  * one pin by setting the respective pin's position but in \e pin_mask.
+ *
+ * If GPIO_HAL_PORT_PIN_NUMBERING is non-zero, a separate handler is required
+ * per port.
  */
 typedef struct gpio_hal_event_handler_s {
   struct gpio_hal_event_handler_s *next;
   gpio_hal_callback_t handler;
+#if GPIO_HAL_PORT_PIN_NUMBERING
+  gpio_hal_port_t port;
+#endif
   gpio_hal_pin_mask_t pin_mask;
 } gpio_hal_event_handler_t;
 /*---------------------------------------------------------------------------*/
@@ -163,8 +217,10 @@ void gpio_hal_init(void);
  */
 void gpio_hal_register_handler(gpio_hal_event_handler_t *handler);
 
+#if GPIO_HAL_PORT_PIN_NUMBERING
 /**
  * \brief The platform-independent GPIO event handler
+ * \param port The GPIO port, if applicable
  * \param pins OR mask of pins that generated an event
  *
  * Whenever a GPIO input interrupt occurs (edge or level detection) and an ISR
@@ -177,12 +233,19 @@ void gpio_hal_register_handler(gpio_hal_event_handler_t *handler);
  * If a pin set in the mask has an event handler registered, this function
  * will call the registered handler.
  *
+ * If GPIO_HAL_PORT_PIN_NUMBERING is non-zero the function will also accept
+ * as its first argument the port associated to the pins that triggered the
+ * edge detection.
+ *
  * This function will not clear any CPU interrupt flags, this should be done
  * by the calling ISR.
  *
  * \sa gpio_hal_register_handler
  */
+void gpio_hal_event_handler(gpio_hal_port_t port, gpio_hal_pin_mask_t pins);
+#else
 void gpio_hal_event_handler(gpio_hal_pin_mask_t pins);
+#endif
 
 /**
  * \brief Convert a pin to a pin mask
@@ -193,29 +256,45 @@ void gpio_hal_event_handler(gpio_hal_pin_mask_t pins);
 /** @} */
 /*---------------------------------------------------------------------------*/
 /**
- * \name Functions to be provided by the platform
+ * \name GPIO pin manipulation functions to be provided by the platform code.
+ *
+ * All functions have two flavours:
+ * - gpio_hal_arch_port_foo are used when GPIO_HAL_PORT_PIN_NUMBERING is
+ *   non-zero and expect a gpio_hal_port_t as one of their arguments
+ * - gpio_hal_arch_no_port_foo are used when GPIO_HAL_PORT_PIN_NUMBERING is 0
+ *   and do _not_ expect a gpio_hal_port_t as one of their arguments
+ *
+ * Macros are provided that automatically expand to the desirable prototype
+ * depending on the value of GPIO_HAL_PORT_PIN_NUMBERING. In order to achieve
+ * code portability, all platform-independent code should use those macros to
+ * manipulate GPIOs instead of using the port_ / no_port_ functions directly.
+ * A convenience macro GPIO_HAL_NULL_PORT is provided to be used as the port
+ * argument of macros when GPIO_HAL_PORT_PIN_NUMBERING is zero.
  *
  * All the functions below must be provided by the platform's developer. The
  * HAL offers the developer a number of options of how to provide the required
  * functionality.
  *
  * - The developer can provide a symbol. For example, the developer can create
- *   a .c file and implement a function called gpio_hal_arch_set_pin()
+ *   a .c file and implement a function called gpio_hal_arch_set_port_pin().
+ *   In this scenario the developer only needs to provide a symbol for the
+ *   gpio_hal_arch_port_foo / gpio_hal_arch_no_port_foo that applies.
+ *
  * - The developer can provide a function-like macro that has the same name as
- *   the function declared here. In this scenario, the declaration here will
- *   be removed by the pre-processor. For example, the developer can do
- *   something like:
+ *   one of the manipulation macros declared here. In this scenario, the
+ *   declaration here will be removed by the pre-processor. For example, the
+ *   developer can do something like:
  *
  *   \code
- *   #define gpio_hal_arch_write_pin(p, v) platform_sdk_function(p, v)
+ *   #define gpio_hal_arch_write_pin(port, pin, v) sdk_function(port, pin, v)
  *   \endcode
  *
  * - The developer can provide a static inline implementation. For this to
  *   work, the developer can do something like:
  *
  *   \code
- *   #define gpio_hal_arch_set_pin(p) set_pin(p)
- *   static inline void set_pin(gpio_hal_pin_t pin) { ... }
+ *   #define gpio_hal_arch_set_pin(port, pin) set_pin(port, pin)
+ *   static inline void set_pin(gpio_hal_port_t port, gpio_hal_pin_t pin) { ... }
  *   \endcode
  *
  * In the latter two cases, the developer will likely provide implementations
@@ -226,7 +305,6 @@ void gpio_hal_event_handler(gpio_hal_pin_mask_t pins);
  * \code
  * #define GPIO_HAL_CONF_ARCH_HDR_PATH          "dev/gpio-hal-arch.h"
  * \endcode
- *
  * @{
  */
 /*---------------------------------------------------------------------------*/
@@ -248,6 +326,22 @@ void gpio_hal_arch_init(void);
 #endif
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_interrupt_enable
+/**
+ * \brief Enable interrupts for a gpio pin
+ * \param port The GPIO port
+ * \param pin The GPIO pin number
+ *
+ * It is the platform developer's responsibility to provide an implementation.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+void gpio_hal_arch_port_interrupt_enable(gpio_hal_port_t port,
+                                         gpio_hal_pin_t pin);
+
 /**
  * \brief Enable interrupts for a gpio pin
  * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
@@ -256,26 +350,65 @@ void gpio_hal_arch_init(void);
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-void gpio_hal_arch_interrupt_enable(gpio_hal_pin_t pin);
-#endif
+void gpio_hal_arch_no_port_interrupt_enable(gpio_hal_pin_t pin);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_interrupt_enable(port, pin) \
+  gpio_hal_arch_port_interrupt_enable(port, pin)
+#else
+#define gpio_hal_arch_interrupt_enable(port, pin) \
+  gpio_hal_arch_no_port_interrupt_enable(pin)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_interrupt_enable */
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_interrupt_disable
 /**
  * \brief Disable interrupts for a gpio pin
+ * \param port The GPIO port
  * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
  *
  * It is the platform developer's responsibility to provide an implementation.
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-void gpio_hal_arch_interrupt_disable(gpio_hal_pin_t pin);
-#endif
+void gpio_hal_arch_port_interrupt_disable(gpio_hal_port_t port,
+                                          gpio_hal_pin_t pin);
+
+/**
+ * \brief Disable interrupts for a gpio pin
+ * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
+ *
+ * It is the platform developer's responsibility to provide an implementation.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+void gpio_hal_arch_no_port_interrupt_disable(gpio_hal_pin_t pin);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_interrupt_disable(port, pin) \
+  gpio_hal_arch_port_interrupt_disable(port, pin)
+#else
+#define gpio_hal_arch_interrupt_disable(port, pin) \
+  gpio_hal_arch_no_port_interrupt_disable(pin)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_interrupt_disable */
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_pin_cfg_set
 /**
  * \brief Configure a gpio pin
+ * \param port The GPIO port
  * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
  * \param cfg The configuration
  *
@@ -288,13 +421,48 @@ void gpio_hal_arch_interrupt_disable(gpio_hal_pin_t pin);
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-void gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg);
-#endif
+void gpio_hal_arch_port_pin_cfg_set(gpio_hal_port_t port,
+                                    gpio_hal_pin_t pin,
+                                    gpio_hal_pin_cfg_t cfg);
+
+/**
+ * \brief Configure a gpio pin
+ * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
+ * \param cfg The configuration
+ *
+ * \e cfg is an OR mask of GPIO_HAL_PIN_CFG_xyz
+ *
+ * The implementation of this function also has to make sure that \e pin is
+ * configured as software-controlled GPIO.
+ *
+ * It is the platform developer's responsibility to provide an implementation.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+void gpio_hal_arch_no_port_pin_cfg_set(gpio_hal_pin_t pin,
+                                       gpio_hal_pin_cfg_t cfg);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_pin_cfg_set(port, pin, cfg) \
+  gpio_hal_arch_port_pin_cfg_set(port, pin, cfg)
+#else
+#define gpio_hal_arch_pin_cfg_set(port, pin, cfg) \
+  gpio_hal_arch_no_port_pin_cfg_set(pin, cfg)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_pin_cfg_set */
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_pin_cfg_get
 /**
  * \brief Read the configuration of a GPIO pin
+ * \param port The GPIO port
  * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
  * \return An OR mask of GPIO_HAL_PIN_CFG_xyz
  *
@@ -302,13 +470,41 @@ void gpio_hal_arch_pin_cfg_set(gpio_hal_pin_t pin, gpio_hal_pin_cfg_t cfg);
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-gpio_hal_pin_cfg_t gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin);
-#endif
+gpio_hal_pin_cfg_t gpio_hal_arch_port_pin_cfg_get(gpio_hal_port_t port,
+                                                  gpio_hal_pin_t pin);
+
+/**
+ * \brief Read the configuration of a GPIO pin
+ * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
+ * \return An OR mask of GPIO_HAL_PIN_CFG_xyz
+ *
+ * It is the platform developer's responsibility to provide an implementation.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+gpio_hal_pin_cfg_t gpio_hal_arch_no_port_pin_cfg_get(gpio_hal_pin_t pin);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_pin_cfg_get(port, pin) \
+  gpio_hal_arch_port_pin_cfg_get(port, pin)
+#else
+#define gpio_hal_arch_pin_cfg_get(port, pin) \
+  gpio_hal_arch_no_port_pin_cfg_get(pin)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_pin_cfg_get */
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_pin_set_input
 /**
  * \brief Configure a pin as GPIO input
+ * \param port The GPIO port
  * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
  *
  * The implementation of this function also has to make sure that \e pin is
@@ -318,13 +514,43 @@ gpio_hal_pin_cfg_t gpio_hal_arch_pin_cfg_get(gpio_hal_pin_t pin);
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-void gpio_hal_arch_pin_set_input(gpio_hal_pin_t pin);
-#endif
+void gpio_hal_arch_port_pin_set_input(gpio_hal_port_t port,
+                                      gpio_hal_pin_t pin);
+
+/**
+ * \brief Configure a pin as GPIO input
+ * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
+ *
+ * The implementation of this function also has to make sure that \e pin is
+ * configured as software-controlled GPIO.
+ *
+ * It is the platform developer's responsibility to provide an implementation.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+void gpio_hal_arch_no_port_pin_set_input(gpio_hal_pin_t pin);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_pin_set_input(port, pin) \
+  gpio_hal_arch_port_pin_set_input(port, pin)
+#else
+#define gpio_hal_arch_pin_set_input(port, pin) \
+  gpio_hal_arch_no_port_pin_set_input(pin)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_pin_set_input */
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_pin_set_output
 /**
  * \brief Configure a pin as GPIO output
+ * \param port The GPIO port
  * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
  *
  * The implementation of this function also has to make sure that \e pin is
@@ -334,39 +560,121 @@ void gpio_hal_arch_pin_set_input(gpio_hal_pin_t pin);
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-void gpio_hal_arch_pin_set_output(gpio_hal_pin_t pin);
-#endif
+void gpio_hal_arch_port_pin_set_output(gpio_hal_port_t port,
+                                       gpio_hal_pin_t pin);
+
+/**
+ * \brief Configure a pin as GPIO output
+ * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
+ *
+ * The implementation of this function also has to make sure that \e pin is
+ * configured as software-controlled GPIO.
+ *
+ * It is the platform developer's responsibility to provide an implementation.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+void gpio_hal_arch_no_port_pin_set_output(gpio_hal_pin_t pin);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_pin_set_output(port, pin) \
+  gpio_hal_arch_port_pin_set_output(port, pin)
+#else
+#define gpio_hal_arch_pin_set_output(port, pin) \
+  gpio_hal_arch_no_port_pin_set_output(pin)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_pin_set_output */
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_set_pin
 /**
  * \brief Set a GPIO pin to logical high
+ * \param port The GPIO port
  * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
  *
  * It is the platform developer's responsibility to provide an implementation.
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-void gpio_hal_arch_set_pin(gpio_hal_pin_t pin);
-#endif
+void gpio_hal_arch_port_set_pin(gpio_hal_port_t port, gpio_hal_pin_t pin);
+
+/**
+ * \brief Set a GPIO pin to logical high
+ * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
+ *
+ * It is the platform developer's responsibility to provide an implementation.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+void gpio_hal_arch_no_port_set_pin(gpio_hal_pin_t pin);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_set_pin(port, pin) \
+  gpio_hal_arch_port_set_pin(port, pin)
+#else
+#define gpio_hal_arch_set_pin(port, pin) \
+  gpio_hal_arch_no_port_set_pin(pin)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_set_pin */
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_clear_pin
 /**
  * \brief Clear a GPIO pin (logical low)
+ * \param port The GPIO port
  * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
  *
  * It is the platform developer's responsibility to provide an implementation.
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-void gpio_hal_arch_clear_pin(gpio_hal_pin_t pin);
-#endif
+void gpio_hal_arch_port_clear_pin(gpio_hal_port_t port, gpio_hal_pin_t pin);
+
+/**
+ * \brief Clear a GPIO pin (logical low)
+ * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
+ *
+ * It is the platform developer's responsibility to provide an implementation.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+void gpio_hal_arch_no_port_clear_pin(gpio_hal_pin_t pin);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_clear_pin(port, pin) \
+  gpio_hal_arch_port_clear_pin(port, pin)
+#else
+#define gpio_hal_arch_clear_pin(port, pin) \
+  gpio_hal_arch_no_port_clear_pin(pin)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_clear_pin */
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_toggle_pin
 /**
  * \brief Toggle a GPIO pin
+ * \param port The GPIO port
  * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
  *
  * Some MCUs allow GPIO pin toggling directly via register access. In this
@@ -378,13 +686,44 @@ void gpio_hal_arch_clear_pin(gpio_hal_pin_t pin);
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-void gpio_hal_arch_toggle_pin(gpio_hal_pin_t pin);
-#endif
+void gpio_hal_arch_port_toggle_pin(gpio_hal_port_t port, gpio_hal_pin_t pin);
+
+/**
+ * \brief Toggle a GPIO pin
+ * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
+ *
+ * Some MCUs allow GPIO pin toggling directly via register access. In this
+ * case, it is a good idea to provide an implementation of this function.
+ * However, a default, software-based implementation is also provided by the
+ * HAL and can be used if the MCU does not have a pin toggle register. To use
+ * the HAL function, define GPIO_HAL_ARCH_SW_TOGGLE as 1. To provide your own
+ * implementation, define GPIO_HAL_ARCH_SW_TOGGLE as 0.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+void gpio_hal_arch_no_port_toggle_pin(gpio_hal_pin_t pin);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_toggle_pin(port, pin) \
+  gpio_hal_arch_port_toggle_pin(port, pin)
+#else
+#define gpio_hal_arch_toggle_pin(port, pin) \
+  gpio_hal_arch_no_port_toggle_pin(pin)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_toggle_pin */
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_read_pin
 /**
  * \brief Read a GPIO pin
+ * \param port The GPIO port
  * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
  * \retval 0 The pin is logical low
  * \retval 1 The pin is logical high
@@ -393,13 +732,41 @@ void gpio_hal_arch_toggle_pin(gpio_hal_pin_t pin);
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-uint8_t gpio_hal_arch_read_pin(gpio_hal_pin_t pin);
-#endif
+uint8_t gpio_hal_arch_port_read_pin(gpio_hal_port_t port, gpio_hal_pin_t pin);
+
+/**
+ * \brief Read a GPIO pin
+ * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
+ * \retval 0 The pin is logical low
+ * \retval 1 The pin is logical high
+ *
+ * It is the platform developer's responsibility to provide an implementation.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+uint8_t gpio_hal_arch_no_port_read_pin(gpio_hal_pin_t pin);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_read_pin(port, pin) \
+  gpio_hal_arch_port_read_pin(port, pin)
+#else
+#define gpio_hal_arch_read_pin(port, pin) \
+  gpio_hal_arch_no_port_read_pin(pin)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_read_pin */
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_write_pin
 /**
  * \brief Write a GPIO pin
+ * \param port The GPIO port
  * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
  * \param value 0: Logical low; 1: Logical high
  *
@@ -407,13 +774,42 @@ uint8_t gpio_hal_arch_read_pin(gpio_hal_pin_t pin);
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-void gpio_hal_arch_write_pin(gpio_hal_pin_t pin, uint8_t value);
-#endif
+void gpio_hal_arch_port_write_pin(gpio_hal_port_t port,
+                                  gpio_hal_pin_t pin,
+                                  uint8_t value);
+
+/**
+ * \brief Write a GPIO pin
+ * \param pin The GPIO pin number (0...GPIO_HAL_PIN_COUNT - 1)
+ * \param value 0: Logical low; 1: Logical high
+ *
+ * It is the platform developer's responsibility to provide an implementation.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+void gpio_hal_arch_no_port_write_pin(gpio_hal_pin_t pin, uint8_t value);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_write_pin(port, pin, value) \
+  gpio_hal_arch_port_write_pin(port, pin, value)
+#else
+#define gpio_hal_arch_write_pin(port, pin, value) \
+  gpio_hal_arch_no_port_write_pin(pin, value)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_write_pin */
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_set_pins
 /**
  * \brief Set multiple pins to logical high
+ * \param port The GPIO port
  * \param pins An ORd pin mask of the pins to set
  *
  * A pin will be set to logical high if its position in \e pins is set. For
@@ -423,13 +819,43 @@ void gpio_hal_arch_write_pin(gpio_hal_pin_t pin, uint8_t value);
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-void gpio_hal_arch_set_pins(gpio_hal_pin_mask_t pins);
-#endif
+void gpio_hal_arch_port_set_pins(gpio_hal_port_t port,
+                                 gpio_hal_pin_mask_t pins);
+
+/**
+ * \brief Set multiple pins to logical high
+ * \param pins An ORd pin mask of the pins to set
+ *
+ * A pin will be set to logical high if its position in \e pins is set. For
+ * example you can set pins 0 and 3 by passing 0x09.
+ *
+ * It is the platform developer's responsibility to provide an implementation.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+void gpio_hal_arch_no_port_set_pins(gpio_hal_pin_mask_t pins);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_set_pins(port, pin) \
+  gpio_hal_arch_port_set_pins(port, pin)
+#else
+#define gpio_hal_arch_set_pins(port, pin) \
+  gpio_hal_arch_no_port_set_pins(pin)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_set_pins */
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_clear_pins
 /**
  * \brief Clear multiple pins to logical low
+ * \param port The GPIO port
  * \param pins An ORd pin mask of the pins to clear
  *
  * A pin will be set to logical low if its position in \e pins is set. For
@@ -439,13 +865,43 @@ void gpio_hal_arch_set_pins(gpio_hal_pin_mask_t pins);
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-void gpio_hal_arch_clear_pins(gpio_hal_pin_mask_t pins);
-#endif
+void gpio_hal_arch_port_clear_pins(gpio_hal_port_t port,
+                                   gpio_hal_pin_mask_t pins);
+
+/**
+ * \brief Clear multiple pins to logical low
+ * \param pins An ORd pin mask of the pins to clear
+ *
+ * A pin will be set to logical low if its position in \e pins is set. For
+ * example you can clear pins 0 and 3 by passing 0x09.
+ *
+ * It is the platform developer's responsibility to provide an implementation.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+void gpio_hal_arch_no_port_clear_pins(gpio_hal_pin_mask_t pins);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_clear_pins(port, pin) \
+  gpio_hal_arch_port_clear_pins(port, pin)
+#else
+#define gpio_hal_arch_clear_pins(port, pin) \
+  gpio_hal_arch_no_port_clear_pins(pin)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_clear_pins */
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_toggle_pins
 /**
  * \brief Toggle multiple pins
+ * \param port The GPIO port
  * \param pins An ORd pin mask of the pins to toggle
  *
  * A pin will be toggled if its position in \e pins is set. For example you
@@ -460,13 +916,48 @@ void gpio_hal_arch_clear_pins(gpio_hal_pin_mask_t pins);
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-void gpio_hal_arch_toggle_pins(gpio_hal_pin_mask_t pins);
-#endif
+void gpio_hal_arch_port_toggle_pins(gpio_hal_port_t port,
+                                    gpio_hal_pin_mask_t pins);
+
+/**
+ * \brief Toggle multiple pins
+ * \param pins An ORd pin mask of the pins to toggle
+ *
+ * A pin will be toggled if its position in \e pins is set. For example you
+ * can toggle pins 0 and 3 by passing 0x09.
+ *
+ * Some MCUs allow GPIO pin toggling directly via register access. In this
+ * case, it is a good idea to provide an implementation of this function.
+ * However, a default, software-based implementation is also provided by the
+ * HAL and can be used if the MCU does not have a pin toggle register. To use
+ * the HAL function, define GPIO_HAL_ARCH_SW_TOGGLE as 1. To provide your own
+ * implementation, define GPIO_HAL_ARCH_SW_TOGGLE as 0.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+void gpio_hal_arch_no_port_toggle_pins(gpio_hal_pin_mask_t pins);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_toggle_pins(port, pin) \
+  gpio_hal_arch_port_toggle_pins(port, pin)
+#else
+#define gpio_hal_arch_toggle_pins(port, pin) \
+  gpio_hal_arch_no_port_toggle_pins(pin)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_toggle_pins */
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_read_pins
 /**
  * \brief Read multiple pins
+ * \param port The GPIO port
  * \param pins An ORd pin mask of the pins to read
  * \retval An ORd mask of the pins that are high
  *
@@ -479,13 +970,46 @@ void gpio_hal_arch_toggle_pins(gpio_hal_pin_mask_t pins);
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-gpio_hal_pin_mask_t gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins);
-#endif
+gpio_hal_pin_mask_t gpio_hal_arch_port_read_pins(gpio_hal_port_t port,
+                                                 gpio_hal_pin_mask_t pins);
+
+/**
+ * \brief Read multiple pins
+ * \param pins An ORd pin mask of the pins to read
+ * \retval An ORd mask of the pins that are high
+ *
+ * If the position of the pin in \e pins is set and the pin is logical high
+ * then the position of the pin in the return value will be set. For example,
+ * if you pass 0x09 as the value of \e pins and the return value is 0x08 then
+ * pin 3 is logical high and pin 0 is logical low.
+ *
+ * It is the platform developer's responsibility to provide an implementation.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+gpio_hal_pin_mask_t gpio_hal_arch_no_port_read_pins(gpio_hal_pin_mask_t pins);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_read_pins(port, pin) \
+  gpio_hal_arch_port_read_pins(port, pin)
+#else
+#define gpio_hal_arch_read_pins(port, pin) \
+  gpio_hal_arch_no_port_read_pins(pin)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_read_pins */
 /*---------------------------------------------------------------------------*/
 #ifndef gpio_hal_arch_write_pins
 /**
  * \brief Write multiple pins
+ * \param port The GPIO port
  * \param pins An ORd pin mask of the pins to write
  * \param value An ORd mask of the value to write
  *
@@ -502,10 +1026,47 @@ gpio_hal_pin_mask_t gpio_hal_arch_read_pins(gpio_hal_pin_mask_t pins);
  *
  * The implementation can be provided as a global symbol, an inline function
  * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
  */
-void gpio_hal_arch_write_pins(gpio_hal_pin_mask_t pins,
-                              gpio_hal_pin_mask_t value);
-#endif
+void gpio_hal_arch_port_write_pins(gpio_hal_port_t port,
+                                   gpio_hal_pin_mask_t pins,
+                                   gpio_hal_pin_mask_t value);
+
+/**
+ * \brief Write multiple pins
+ * \param pins An ORd pin mask of the pins to write
+ * \param value An ORd mask of the value to write
+ *
+ * The function will modify GPIO pins that have their position in the mask set.
+ * pins, the function will write the value specified in the corresponding
+ * position in \e value.
+
+ * For example, you can set pin 3 and clear pin 0 by a single call to this
+ * function. To achieve this, \e pins must be 0x09 and \e value 0x08.
+ *
+ * It is the platform developer's responsibility to provide an implementation.
+ *
+ * There is no guarantee that this function will result in an atomic operation.
+ *
+ * The implementation can be provided as a global symbol, an inline function
+ * or a function-like macro, as described above.
+ *
+ * \note Code should not call this function directly. Use GPIO manipulation
+ * macros instead.
+ */
+void gpio_hal_arch_no_port_write_pins(gpio_hal_pin_mask_t pins,
+                                      gpio_hal_pin_mask_t value);
+
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define gpio_hal_arch_write_pins(port, pin, value) \
+  gpio_hal_arch_port_write_pins(port, pin, value)
+#else
+#define gpio_hal_arch_write_pins(port, pin, value) \
+  gpio_hal_arch_no_port_write_pins(pin, value)
+#endif /* GPIO_HAL_PORT_PIN_NUMBERING */
+#endif /* gpio_hal_arch_write_pins */
 /** @} */
 /*---------------------------------------------------------------------------*/
 #endif /* GPIO_HAL_H_ */
diff --git a/os/dev/leds.c b/os/dev/leds.c
index f2ce82c29229b9eb659d645c5a5d3dfac46d532e..8c7607b030f11c62f65142e022feb91123f1e114 100644
--- a/os/dev/leds.c
+++ b/os/dev/leds.c
@@ -103,13 +103,20 @@ extern const leds_t leds_arch_leds[];
 static const leds_t *leds_arch_leds = NULL;
 #endif
 /*---------------------------------------------------------------------------*/
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define LED_PORT(led) (led).port
+#else
+#define LED_PORT(led) GPIO_HAL_NULL_PORT
+#endif
+/*---------------------------------------------------------------------------*/
 void
 leds_init()
 {
   leds_num_t led;
 
   for(led = 0; led < LEDS_COUNT; led++) {
-    gpio_hal_arch_pin_set_output(leds_arch_leds[led].pin);
+    gpio_hal_arch_pin_set_output(LED_PORT(leds_arch_leds[led]),
+                                 leds_arch_leds[led].pin);
   }
   leds_off(LEDS_ALL);
 }
@@ -122,9 +129,11 @@ leds_single_on(leds_num_t led)
   }
 
   if(leds_arch_leds[led].negative_logic) {
-    gpio_hal_arch_clear_pin(leds_arch_leds[led].pin);
+    gpio_hal_arch_clear_pin(LED_PORT(leds_arch_leds[led]),
+                                     leds_arch_leds[led].pin);
   } else {
-    gpio_hal_arch_set_pin(leds_arch_leds[led].pin);
+    gpio_hal_arch_set_pin(LED_PORT(leds_arch_leds[led]),
+                          leds_arch_leds[led].pin);
   }
 }
 /*---------------------------------------------------------------------------*/
@@ -136,9 +145,11 @@ leds_single_off(leds_num_t led)
   }
 
   if(leds_arch_leds[led].negative_logic) {
-    gpio_hal_arch_set_pin(leds_arch_leds[led].pin);
+    gpio_hal_arch_set_pin(LED_PORT(leds_arch_leds[led]),
+                          leds_arch_leds[led].pin);
   } else {
-    gpio_hal_arch_clear_pin(leds_arch_leds[led].pin);
+    gpio_hal_arch_clear_pin(LED_PORT(leds_arch_leds[led]),
+                            leds_arch_leds[led].pin);
   }
 }
 /*---------------------------------------------------------------------------*/
@@ -149,7 +160,8 @@ leds_single_toggle(leds_num_t led)
     return;
   }
 
-  gpio_hal_arch_toggle_pin(leds_arch_leds[led].pin);
+  gpio_hal_arch_toggle_pin(LED_PORT(leds_arch_leds[led]),
+                           leds_arch_leds[led].pin);
 }
 /*---------------------------------------------------------------------------*/
 void
@@ -160,9 +172,11 @@ leds_on(leds_mask_t leds)
   for(led = 0; led < LEDS_COUNT; led++) {
     if((1 << led) & leds) {
       if(leds_arch_leds[led].negative_logic) {
-        gpio_hal_arch_clear_pin(leds_arch_leds[led].pin);
+        gpio_hal_arch_clear_pin(LED_PORT(leds_arch_leds[led]),
+                                leds_arch_leds[led].pin);
       } else {
-        gpio_hal_arch_set_pin(leds_arch_leds[led].pin);
+        gpio_hal_arch_set_pin(LED_PORT(leds_arch_leds[led]),
+                              leds_arch_leds[led].pin);
       }
     }
   }
@@ -176,9 +190,11 @@ leds_off(leds_mask_t leds)
   for(led = 0; led < LEDS_COUNT; led++) {
     if((1 << led) & leds) {
       if(leds_arch_leds[led].negative_logic) {
-        gpio_hal_arch_set_pin(leds_arch_leds[led].pin);
+        gpio_hal_arch_set_pin(LED_PORT(leds_arch_leds[led]),
+                              leds_arch_leds[led].pin);
       } else {
-        gpio_hal_arch_clear_pin(leds_arch_leds[led].pin);
+        gpio_hal_arch_clear_pin(LED_PORT(leds_arch_leds[led]),
+                                leds_arch_leds[led].pin);
       }
     }
   }
@@ -191,7 +207,8 @@ leds_toggle(leds_mask_t leds)
 
   for(led = 0; led < LEDS_COUNT; led++) {
     if((1 << led) & leds) {
-      gpio_hal_arch_toggle_pin(leds_arch_leds[led].pin);
+      gpio_hal_arch_toggle_pin(LED_PORT(leds_arch_leds[led]),
+                               leds_arch_leds[led].pin);
     }
   }
 }
@@ -211,7 +228,8 @@ leds_get()
   uint8_t pin_state;
 
   for(led = 0; led < LEDS_COUNT; led++) {
-    pin_state = gpio_hal_arch_read_pin(leds_arch_leds[led].pin);
+    pin_state = gpio_hal_arch_read_pin(LED_PORT(leds_arch_leds[led]),
+                                       leds_arch_leds[led].pin);
 
     if((leds_arch_leds[led].negative_logic == false && pin_state == 1) ||
        (leds_arch_leds[led].negative_logic == true && pin_state == 0)) {
diff --git a/os/dev/leds.h b/os/dev/leds.h
index 654ed250eee09af5e8873954a5cb52b3c901556e..21912a8ec8fd4627d90841fac706aed1e2bde712 100644
--- a/os/dev/leds.h
+++ b/os/dev/leds.h
@@ -208,10 +208,19 @@ void leds_arch_set(leds_mask_t leds);
  * \e pin corresponds to the GPIO pin a LED is driven by, using GPIO HAL pin
  * representation.
  *
+ * \e port corresponds to the GPIO port that the pin is connected to. This
+ * only makes sense if GPIO_HAL_CONF_PORT_PIN_NUMBERING is non-zero.
+ *
  * \e negative_logic should be set to false if the LED is active low.
+ *
+ * \note Do not access the \e port member of this struct direct, use the
+ * LED_PORT() macro instead.
  */
 typedef struct leds_s {
   gpio_hal_pin_t pin;
+#if GPIO_HAL_PORT_PIN_NUMBERING
+  gpio_hal_port_t port;
+#endif
   bool negative_logic;
 } leds_t;
 /*---------------------------------------------------------------------------*/
diff --git a/os/dev/radio.h b/os/dev/radio.h
index e6ca64f3d49d1f54c9698ae2149bf547ba1675a9..4cb266608ad80d97ab1931c16959d612faf7ca2d 100644
--- a/os/dev/radio.h
+++ b/os/dev/radio.h
@@ -185,18 +185,35 @@ enum {
   /* The maximum transmission power in dBm. */
   RADIO_CONST_TXPOWER_MAX,
 
+  /* A pointer to TSCH timings in micro-seconds (tsch_timeslot_timing_usec *) */
   RADIO_CONST_TSCH_TIMING,
+
+  /* The physical layer header+footer overhead in bytes, after SFD.
+   * On IEEE 802.15.4 at 2.4 GHz: 1 byte for len + 2 for CRC => 3 */
   RADIO_CONST_PHY_OVERHEAD,
+
+  /* The air time of one byte in usec, e.g. 32 for IEEE 802.15.4 at 2.4 GHz */
   RADIO_CONST_BYTE_AIR_TIME,
+
+  /* The delay in usec between a call to the radio API's transmit function and
+   * the end of SFD transmission */
   RADIO_CONST_DELAY_BEFORE_TX,
+
+  /* The delay in usec between turning on the radio and it being actually
+   * listening (able to hear a preamble) */
   RADIO_CONST_DELAY_BEFORE_RX,
+
+  /* The delay in usec between the end of SFD reception for an incoming frame
+   * and the radio API starting to return receiving_packet() != 0 */
   RADIO_CONST_DELAY_BEFORE_DETECT,
 };
 
 /* Radio power modes */
 enum {
   RADIO_POWER_MODE_OFF,
-  RADIO_POWER_MODE_ON
+  RADIO_POWER_MODE_ON,
+  RADIO_POWER_MODE_CARRIER_ON,
+  RADIO_POWER_MODE_CARRIER_OFF
 };
 
 /**
diff --git a/os/dev/slip.c b/os/dev/slip.c
index 3cfe9ea078d06e379af7c1f1dd65ac44e7280a25..7426151c469cd2829b6122745816a29e30e36731 100644
--- a/os/dev/slip.c
+++ b/os/dev/slip.c
@@ -52,7 +52,7 @@ static uint16_t slip_rubbish, slip_twopackets, slip_overflow, slip_ip_drop;
 #endif
 /*---------------------------------------------------------------------------*/
 /* Must be at least one byte larger than UIP_BUFSIZE! */
-#define RX_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN + 16)
+#define RX_BUFSIZE (UIP_BUFSIZE + 16)
 /*---------------------------------------------------------------------------*/
 enum {
   STATE_TWOPACKETS = 0, /* We have 2 packets and drop incoming data. */
@@ -87,7 +87,7 @@ slip_set_input_callback(void (*c)(void))
 void
 slip_send(void)
 {
-  slip_write(&uip_buf[UIP_LLH_LEN], uip_len);
+  slip_write(uip_buf, uip_len);
 }
 /*---------------------------------------------------------------------------*/
 void
@@ -252,8 +252,7 @@ PROCESS_THREAD(slip_process, ev, data)
     slip_active = 1;
 
     /* Move packet from rxbuf to buffer provided by uIP. */
-    uip_len = slip_poll_handler(&uip_buf[UIP_LLH_LEN],
-                                UIP_BUFSIZE - UIP_LLH_LEN);
+    uip_len = slip_poll_handler(uip_buf, UIP_BUFSIZE);
 
     if(uip_len > 0) {
       if(input_callback) {
diff --git a/os/dev/spi.c b/os/dev/spi.c
index 091cf8e51c0afe876248f9e7c99399b4f22c7bc8..af2e0cefd865080275a0994a76c134a34b4e4cee 100644
--- a/os/dev/spi.c
+++ b/os/dev/spi.c
@@ -71,7 +71,7 @@ spi_select(const spi_device_t *dev)
     return SPI_DEV_STATUS_BUS_NOT_OWNED;
   }
 
-  gpio_hal_arch_clear_pin(dev->pin_spi_cs);
+  gpio_hal_arch_clear_pin(SPI_DEVICE_PORT(cs, dev), dev->pin_spi_cs);
 
   return SPI_DEV_STATUS_OK;
 }
@@ -79,7 +79,7 @@ spi_select(const spi_device_t *dev)
 spi_status_t
 spi_deselect(const spi_device_t *dev)
 {
-  gpio_hal_arch_set_pin(dev->pin_spi_cs);
+  gpio_hal_arch_set_pin(SPI_DEVICE_PORT(cs, dev), dev->pin_spi_cs);
 
   return SPI_DEV_STATUS_OK;
 }
diff --git a/os/dev/spi.h b/os/dev/spi.h
index 9dda05b8efdd44fb382a2035d098fb0f3c54be9d..8eb2709e4484c1a77b1b9556872dd6a0d5ca4e16 100644
--- a/os/dev/spi.h
+++ b/os/dev/spi.h
@@ -92,10 +92,18 @@ typedef enum {
  *
  * This is a structure to an architecture-independent SPI configuration.
  *
+ * \note Do not access the port_spi_foo members directly. Access them by using
+ * the SPI_DEVICE_PORT() macro instead
  * @{
  */
 
 typedef struct spi_device {
+#if GPIO_HAL_PORT_PIN_NUMBERING
+  gpio_hal_port_t port_spi_sck;       /* SPI SCK port */
+  gpio_hal_port_t port_spi_miso;      /* SPI MISO port */
+  gpio_hal_port_t port_spi_mosi;      /* SPI MOSI port */
+  gpio_hal_port_t port_spi_cs;        /* SPI Chip Select port */
+#endif
   gpio_hal_pin_t pin_spi_sck;       /* SPI SCK pin */
   gpio_hal_pin_t pin_spi_miso;      /* SPI MISO  pin */
   gpio_hal_pin_t pin_spi_mosi;      /* SPI MOSI pin */
@@ -107,6 +115,22 @@ typedef struct spi_device {
 } spi_device_t;
 /** @} */
 /*---------------------------------------------------------------------------*/
+/**
+ * \brief Retrieve the SPI device's port number if applicable
+ * \param member Retrieve struct member port_spi_member (e.g. port_spi_miso)
+ * \param device A pointer the a variable of type spi_device_t
+ *
+ * The same macro is used for all four port_spi_foo members of the struct. So
+ * to retrieve port_spi_cs, use SPI_DEVICE_PORT(cs, device). Replace cs with
+ * mosi to retrieve port_spi_mosi.
+ *
+ */
+#if GPIO_HAL_PORT_PIN_NUMBERING
+#define SPI_DEVICE_PORT(member, device) (device)->port_spi_##member
+#else
+#define SPI_DEVICE_PORT(member, device) GPIO_HAL_NULL_PORT
+#endif
+/*---------------------------------------------------------------------------*/
 /* These are architecture-independent functions to be used by SPI devices.   */
 /*---------------------------------------------------------------------------*/
 /**
diff --git a/os/dev/watchdog.h b/os/dev/watchdog.h
index 3985239aa3e74a1f439bbc06186f4027436f54dc..7feac1b11268eec1b773a3f42091990a39aec555 100644
--- a/os/dev/watchdog.h
+++ b/os/dev/watchdog.h
@@ -34,6 +34,8 @@
 
 void watchdog_init(void);
 void watchdog_start(void);
+
+/* Do not use this function from within an interrupt context */
 void watchdog_periodic(void);
 void watchdog_stop(void);
 
diff --git a/os/lib/circular-list.h b/os/lib/circular-list.h
index 2edcaf808e3cb605169f9efa8e8f15ee9ebdad8c..da9d1d58bbd582edae1c7586ab756ed7be55a72b 100644
--- a/os/lib/circular-list.h
+++ b/os/lib/circular-list.h
@@ -48,6 +48,8 @@
  * update the list's head and item order. If you call one of these functions
  * as part of a list traversal, it is advised to stop / restart traversing
  * after the respective function returns.
+ *
+ * This library is not safe to be used within an interrupt context.
  * @{
  */
 /*---------------------------------------------------------------------------*/
diff --git a/os/lib/dbl-circ-list.h b/os/lib/dbl-circ-list.h
index 08eba8188078b4ee9b927388d9a53d26be65924d..e39d6eb8fcdb781726c58e603d242a955e6e9739 100644
--- a/os/lib/dbl-circ-list.h
+++ b/os/lib/dbl-circ-list.h
@@ -49,6 +49,8 @@
  * update the list's head and item order. If you call one of these functions
  * as part of a list traversal, it is advised to stop / restart traversing
  * after the respective function returns.
+ *
+ * This library is not safe to be used within an interrupt context.
  * @{
  */
 /*---------------------------------------------------------------------------*/
diff --git a/os/lib/dbl-list.h b/os/lib/dbl-list.h
index 88caf30ce628b95b4abf423e2afe9783b2498de6..779deb81780f82c2553b5590e0ded8c8e9a58b0e 100644
--- a/os/lib/dbl-list.h
+++ b/os/lib/dbl-list.h
@@ -49,6 +49,8 @@
  * update the list's head and item order. If you call one of these functions
  * as part of a list traversal, it is advised to stop / restart traversing
  * after the respective function returns.
+ *
+ * This library is not safe to be used within an interrupt context.
  * @{
  */
 /*---------------------------------------------------------------------------*/
diff --git a/os/lib/list.h b/os/lib/list.h
index af01364353af97d7adeb6f05638ea8a04b3bdafe..80198f542658b89275c26ba423014942a99e5e4c 100644
--- a/os/lib/list.h
+++ b/os/lib/list.h
@@ -60,6 +60,7 @@
  * list with list_remove(). The head and tail of a list can be
  * extracted using list_head() and list_tail(), respectively.
  *
+ * This library is not safe to be used within an interrupt context.
  * @{
  */
 
diff --git a/os/lib/queue.h b/os/lib/queue.h
index 9d65fec9e2a55765c03d85e5a7bae69b2f608b1a..4ca80495b1b19bd8b002077997a8fba59fd2c13e 100644
--- a/os/lib/queue.h
+++ b/os/lib/queue.h
@@ -44,6 +44,8 @@
  * struct, the first field must be a pointer called \e next. This field will
  * be used by the library to maintain the queue. Application code must not
  * modify this field directly.
+ *
+ * This library is not safe to be used within an interrupt context.
  * @{
  */
 /*---------------------------------------------------------------------------*/
diff --git a/os/lib/stack.h b/os/lib/stack.h
index 8d56e46ef148bbb644490a49a2040634758ae6c8..01d4a0275c25fb161cc091db06acfede407300fa 100644
--- a/os/lib/stack.h
+++ b/os/lib/stack.h
@@ -44,6 +44,8 @@
  * struct, the first field must be a pointer called \e next. This field will
  * be used by the library to maintain the stack. Application code must not
  * modify this field directly.
+ *
+ * This library is not safe to be used within an interrupt context.
  * @{
  */
 /*---------------------------------------------------------------------------*/
diff --git a/os/lib/trickle-timer.c b/os/lib/trickle-timer.c
index 9180e1bf393b416ac1a281060b2d29ac75379bcb..a6a9e38b4cd8aa158ec284fe8ed8542ca395c185 100644
--- a/os/lib/trickle-timer.c
+++ b/os/lib/trickle-timer.c
@@ -81,7 +81,7 @@ static void double_interval(void *ptr);
 static uint32_t
 wide_rand(void)
 {
-  return ((uint32_t)random_rand() << 16 | random_rand());
+  return (uint32_t)random_rand() << 16 | random_rand();
 }
 #endif
 /*---------------------------------------------------------------------------*/
@@ -98,7 +98,7 @@ static uint8_t
 max_imax(clock_time_t value)
 {
   uint8_t zeros = 0;
-#if (TRICKLE_TIMER_MAX_IMAX_WIDTH==TRICKLE_TIMER_MAX_IMAX_GENERIC)
+#if (TRICKLE_TIMER_MAX_IMAX_WIDTH == TRICKLE_TIMER_MAX_IMAX_GENERIC)
   uint8_t i;
   clock_time_t mask = 0xFFFF;
 
@@ -111,7 +111,7 @@ max_imax(clock_time_t value)
     }
   }
 
-#elif (TRICKLE_TIMER_MAX_IMAX_WIDTH==TRICKLE_TIMER_MAX_IMAX_16_BIT)
+#elif (TRICKLE_TIMER_MAX_IMAX_WIDTH == TRICKLE_TIMER_MAX_IMAX_16_BIT)
   if((value & 0xFF00) == 0) {
     zeros += 8;
     value <<= 8;
@@ -127,7 +127,7 @@ max_imax(clock_time_t value)
   if((value & 0x8000) == 0) {
     zeros++;
   }
-#elif (TRICKLE_TIMER_MAX_IMAX_WIDTH==TRICKLE_TIMER_MAX_IMAX_32_BIT)
+#elif (TRICKLE_TIMER_MAX_IMAX_WIDTH == TRICKLE_TIMER_MAX_IMAX_32_BIT)
   if((value & 0xFFFF0000) == 0) {
     zeros += 16;
     value <<= 16;
@@ -307,6 +307,9 @@ new_interval(struct trickle_timer *tt)
 void
 trickle_timer_consistency(struct trickle_timer *tt)
 {
+  if(tt->i_cur == TRICKLE_TIMER_IS_STOPPED) {
+    return;
+  }
   if(tt->c < 0xFF) {
     tt->c++;
   }
@@ -316,6 +319,9 @@ trickle_timer_consistency(struct trickle_timer *tt)
 void
 trickle_timer_inconsistency(struct trickle_timer *tt)
 {
+  if(tt->i_cur == TRICKLE_TIMER_IS_STOPPED) {
+    return;
+  }
   /* "If I is equal to Imin when Trickle hears an "inconsistent" transmission,
    * Trickle does nothing." */
   if(tt->i_cur != tt->i_min) {
@@ -366,6 +372,8 @@ trickle_timer_config(struct trickle_timer *tt, clock_time_t i_min,
   tt->i_max = i_max;
   tt->i_max_abs = i_min << i_max;
   tt->k = k;
+  tt->i_cur = TRICKLE_TIMER_IS_STOPPED;
+  tt->cb = NULL;
 
   PRINTF("trickle_timer config: Imin=%lu, Imax=%u, k=%u\n",
          (unsigned long)tt->i_min, tt->i_max, tt->k);
diff --git a/os/lib/trickle-timer.h b/os/lib/trickle-timer.h
index 20b694e1ef7e942dcbcc69571095526c919befa3..d2ce2ebde3fe2cad1da521807b2a4cf245b56b0c 100644
--- a/os/lib/trickle-timer.h
+++ b/os/lib/trickle-timer.h
@@ -65,6 +65,7 @@
  * 'consistent' or 'inconsistent' message and when an 'external event' occurs
  * (in this context, those terms have the exact same meaning as in the RFC).
  *
+ * It is \e not safe to manipulate trickle timers within an interrupt context.
  * @{
  */
 
diff --git a/os/net/app-layer/coap/coap-uip.c b/os/net/app-layer/coap/coap-uip.c
index e2be92326e3d91faefdd87216dc229322c540bd4..8109db20e91f5a81ba3637939abcc4f3e93c052d 100644
--- a/os/net/app-layer/coap/coap-uip.c
+++ b/os/net/app-layer/coap/coap-uip.c
@@ -70,21 +70,13 @@
 #endif /* WITH_DTLS */
 
 /* sanity check for configured values */
-#if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPH_LEN - UIP_UDPH_LEN)
+#if COAP_MAX_PACKET_SIZE > (UIP_BUFSIZE - UIP_IPH_LEN - UIP_UDPH_LEN)
 #error "UIP_CONF_BUFFER_SIZE too small for COAP_MAX_CHUNK_SIZE"
 #endif
 
 #define SERVER_LISTEN_PORT        UIP_HTONS(COAP_DEFAULT_PORT)
 #define SERVER_LISTEN_SECURE_PORT UIP_HTONS(COAP_DEFAULT_SECURE_PORT)
 
-/* direct access into the buffer */
-#define UIP_IP_BUF   ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-#if NETSTACK_CONF_WITH_IPV6
-#define UIP_UDP_BUF  ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#else
-#define UIP_UDP_BUF  ((struct uip_udp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN])
-#endif
-
 #ifdef WITH_DTLS
 static dtls_handler_t cb;
 static dtls_context_t *dtls_context = NULL;
diff --git a/os/net/app-layer/mqtt/mqtt.c b/os/net/app-layer/mqtt/mqtt.c
index 9571244d87957b4c3a7260f29d306e03fd8fe4d2..47ffc6a7ae315c29485df81cb4adc71ea5a79e30 100644
--- a/os/net/app-layer/mqtt/mqtt.c
+++ b/os/net/app-layer/mqtt/mqtt.c
@@ -416,16 +416,16 @@ PT_THREAD(connect_pt(struct pt *pt, struct mqtt_connection *conn))
   PT_MQTT_WRITE_BYTE(conn, conn->connect_vhdr_flags);
   PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive >> 8));
   PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive & 0x00FF));
-  PT_MQTT_WRITE_BYTE(conn, conn->client_id.length << 8);
+  PT_MQTT_WRITE_BYTE(conn, conn->client_id.length >> 8);
   PT_MQTT_WRITE_BYTE(conn, conn->client_id.length & 0x00FF);
   PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->client_id.string,
                       conn->client_id.length);
   if(conn->connect_vhdr_flags & MQTT_VHDR_WILL_FLAG) {
-    PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length << 8);
+    PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length >> 8);
     PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length & 0x00FF);
     PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->will.topic.string,
                         conn->will.topic.length);
-    PT_MQTT_WRITE_BYTE(conn, conn->will.message.length << 8);
+    PT_MQTT_WRITE_BYTE(conn, conn->will.message.length >> 8);
     PT_MQTT_WRITE_BYTE(conn, conn->will.message.length & 0x00FF);
     PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->will.message.string,
                         conn->will.message.length);
@@ -436,14 +436,14 @@ PT_THREAD(connect_pt(struct pt *pt, struct mqtt_connection *conn))
         conn->will.message.length);
   }
   if(conn->connect_vhdr_flags & MQTT_VHDR_USERNAME_FLAG) {
-    PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length << 8);
+    PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length >> 8);
     PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length & 0x00FF);
     PT_MQTT_WRITE_BYTES(conn,
                         (uint8_t *)conn->credentials.username.string,
                         conn->credentials.username.length);
   }
   if(conn->connect_vhdr_flags & MQTT_VHDR_PASSWORD_FLAG) {
-    PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length << 8);
+    PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length >> 8);
     PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length & 0x00FF);
     PT_MQTT_WRITE_BYTES(conn,
                         (uint8_t *)conn->credentials.password.string,
@@ -534,7 +534,7 @@ PT_THREAD(subscribe_pt(struct pt *pt, struct mqtt_connection *conn))
                       conn->out_packet.remaining_length_enc,
                       conn->out_packet.remaining_length_enc_bytes);
   /* Write Variable Header */
-  PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8));
+  PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid >> 8));
   PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF));
   /* Write Payload */
   PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8));
@@ -596,7 +596,7 @@ PT_THREAD(unsubscribe_pt(struct pt *pt, struct mqtt_connection *conn))
   PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.remaining_length_enc,
                       conn->out_packet.remaining_length_enc_bytes);
   /* Write Variable Header */
-  PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8));
+  PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid >> 8));
   PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF));
   /* Write Payload */
   PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8));
@@ -669,7 +669,7 @@ PT_THREAD(publish_pt(struct pt *pt, struct mqtt_connection *conn))
   PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.topic,
                       conn->out_packet.topic_length);
   if(conn->out_packet.qos > MQTT_QOS_LEVEL_0) {
-    PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8));
+    PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid >> 8));
     PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF));
   }
   /* Write Payload */
@@ -772,7 +772,7 @@ handle_connack(struct mqtt_connection *conn)
 static void
 handle_pingresp(struct mqtt_connection *conn)
 {
-  DBG("MQTT - Got RINGRESP\n");
+  DBG("MQTT - Got PINGRESP\n");
 }
 /*---------------------------------------------------------------------------*/
 static void
diff --git a/os/net/ipv6/multicast/esmrf.c b/os/net/ipv6/multicast/esmrf.c
index 5b6f1b8634e7da1cfeff716449e1fc55ea4a7f7d..169064b25d994595fa6e8f6c4b8058d1dbead58e 100644
--- a/os/net/ipv6/multicast/esmrf.c
+++ b/os/net/ipv6/multicast/esmrf.c
@@ -103,26 +103,18 @@ static struct uip_udp_conn *c;
 static uip_ipaddr_t src_ip;
 static uip_ipaddr_t des_ip;
 /*---------------------------------------------------------------------------*/
-/* uIPv6 Pointers */
-/*---------------------------------------------------------------------------*/
-#define UIP_IP_BUF        ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-#define UIP_ICMP_BUF      ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_ICMP_PAYLOAD  ((unsigned char *)&uip_buf[uip_l2_l3_icmp_hdr_len])
-#define UIP_UDP_BUF       ((struct uip_udp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN])
-/*---------------------------------------------------------------------------*/
 /* Local function prototypes */
 /*---------------------------------------------------------------------------*/
 static void icmp_input(void);
 static void icmp_output(void);
 static void mcast_fwd(void *p);
-int remove_ext_hdr(void);
 /*---------------------------------------------------------------------------*/
 /* Internal Data Structures */
 /*---------------------------------------------------------------------------*/
 struct multicast_on_behalf{   /*  ICMP message of multicast_on_behalf */
   uint16_t mcast_port;
   uip_ipaddr_t mcast_ip;
-  uint8_t mcast_payload[UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN];
+  uint8_t mcast_payload[UIP_BUFSIZE - UIP_IPUDPH_LEN];
 };
 #define UIP_ICMP_MOB 18 /* Size of multicast_on_behalf ICMP header */
 /*---------------------------------------------------------------------------*/
@@ -143,7 +135,7 @@ icmp_output()
 
   struct multicast_on_behalf *mob;
   mob = (struct multicast_on_behalf *)UIP_ICMP_PAYLOAD;
-  memcpy(&mob->mcast_payload, &uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], uip_slen);
+  memcpy(&mob->mcast_payload, &uip_buf[UIP_IPUDPH_LEN], uip_slen);
 
   UIP_IP_BUF->vtc = 0x60;
   UIP_IP_BUF->tcflow = 0;
@@ -164,8 +156,7 @@ icmp_output()
   PRINT6ADDR(&UIP_IP_BUF->destipaddr);
   PRINTF("\n");
 
-  UIP_IP_BUF->len[0] = (UIP_ICMPH_LEN + payload_len) >> 8;
-  UIP_IP_BUF->len[1] = (UIP_ICMPH_LEN + payload_len) & 0xff;
+  uipbuf_set_len_field(UIP_IP_BUF, UIP_ICMPH_LEN + payload_len);
 
   UIP_ICMP_BUF->type = ICMP6_ESMRF;
   UIP_ICMP_BUF->icode = ESMRF_ICMP_CODE;
@@ -199,7 +190,7 @@ icmp_input()
   }
 #endif
 
-  remove_ext_hdr();
+  uip_remove_ext_hdr();
 
   PRINTF("ESMRF: ICMPv6 In from ");
   PRINT6ADDR(&UIP_IP_BUF->srcipaddr);
@@ -210,11 +201,11 @@ icmp_input()
   VERBOSE_PRINTF("ESMRF: ICMPv6 In, parse from %p to %p\n",
                  UIP_ICMP_PAYLOAD,
                  (uint8_t *)UIP_ICMP_PAYLOAD + uip_len -
-                 uip_l2_l3_icmp_hdr_len);
+                 uip_l3_icmp_hdr_len);
 
 
   locmobptr = (struct multicast_on_behalf *) UIP_ICMP_PAYLOAD;
-  loclen = uip_len - (uip_l2_l3_icmp_hdr_len + UIP_ICMP_MOB);
+  loclen = uip_len - (uip_l3_icmp_hdr_len + UIP_ICMP_MOB);
 
   uip_ipaddr_copy(&src_ip, &UIP_IP_BUF->srcipaddr);
   uip_ipaddr_copy(&des_ip, &UIP_IP_BUF->destipaddr);
@@ -224,13 +215,13 @@ icmp_input()
   c->rport = locmobptr->mcast_port;
   uip_slen = loclen;
   uip_udp_conn=c;
-  memcpy(&uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], locmobptr->mcast_payload,
-         loclen > UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN?
-         UIP_BUFSIZE - UIP_LLH_LEN - UIP_IPUDPH_LEN: loclen);
+  memcpy(&uip_buf[UIP_IPUDPH_LEN], locmobptr->mcast_payload,
+         loclen > UIP_BUFSIZE - UIP_IPUDPH_LEN?
+         UIP_BUFSIZE - UIP_IPUDPH_LEN: loclen);
 
   uip_process(UIP_UDP_SEND_CONN);
 
-  memcpy(&mcast_buf, &uip_buf[UIP_LLH_LEN], uip_len);
+  memcpy(&mcast_buf, uip_buf, uip_len);
   mcast_len = uip_len;
   /* pass the packet to our uip_process to check if it is allowed to
    * accept this packet or not */
@@ -240,7 +231,7 @@ icmp_input()
 
   uip_process(UIP_DATA);
 
-  memcpy(&uip_buf[UIP_LLH_LEN], &mcast_buf, mcast_len);
+  memcpy(uip_buf, &mcast_buf, mcast_len);
   uip_len = mcast_len;
   /* Return the IP of the original Multicast sender */
   uip_ipaddr_copy(&UIP_IP_BUF->srcipaddr, &src_ip);
@@ -252,17 +243,17 @@ icmp_input()
     /* If we enter here, we will definitely forward */
     tcpip_ipv6_output();
   }
-  uip_clear_buf();
+  uipbuf_clear();
 }
 /*---------------------------------------------------------------------------*/
 static void
 mcast_fwd(void *p)
 {
-  memcpy(&uip_buf[UIP_LLH_LEN], &mcast_buf, mcast_len);
+  memcpy(uip_buf, &mcast_buf, mcast_len);
   uip_len = mcast_len;
   UIP_IP_BUF->ttl--;
   tcpip_output(NULL);
-  uip_clear_buf();
+  uipbuf_clear();
 }
 /*---------------------------------------------------------------------------*/
 static uint8_t
@@ -352,7 +343,7 @@ in()
         fwd_delay = fwd_delay * (1 + ((random_rand() >> 11) % fwd_spread));
       }
 
-      memcpy(&mcast_buf, &uip_buf[UIP_LLH_LEN], uip_len);
+      memcpy(&mcast_buf, uip_buf, uip_len);
       mcast_len = uip_len;
       ctimer_set(&mcast_periodic, fwd_delay, mcast_fwd, NULL);
     }
diff --git a/os/net/ipv6/multicast/mpl.c b/os/net/ipv6/multicast/mpl.c
new file mode 100644
index 0000000000000000000000000000000000000000..1879d821692381078aeee7edb50a977e6d73157e
--- /dev/null
+++ b/os/net/ipv6/multicast/mpl.c
@@ -0,0 +1,1797 @@
+/*
+ * Copyright (c) 2018, University of Bristol - http://www.bristol.ac.uk/
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ */
+
+/**
+ * \addtogroup mpl
+ * @{
+ */
+/**
+ * \file
+ *    Implementation of the MPL protocol
+ * \author
+ *    Ed Rose - <er15406@bris.ac.uk>
+ */
+
+#include "contiki.h"
+#include "contiki-lib.h"
+#include "contiki-net.h"
+#include "net/ipv6/uip.h"
+#include "net/ipv6/uip-ds6.h"
+#include "net/ipv6/uip-icmp6.h"
+#include "net/ipv6/multicast/uip-mcast6.h"
+#include "net/ipv6/multicast/mpl.h"
+#include "dev/watchdog.h"
+#include "os/lib/trickle-timer.h"
+#include "os/lib/list.h"
+#include "sys/ctimer.h"
+#include <string.h>
+
+#include "sys/log.h"
+#define LOG_MODULE "MPL"
+#define LOG_LEVEL LOG_LEVEL_NONE
+
+/*---------------------------------------------------------------------------*/
+/* Check Parameters are Correct */
+/*---------------------------------------------------------------------------*/
+/* MPL Seed IDs */
+#if MPL_SEED_ID_TYPE < 0 || MPL_SEED_ID_TYPE > 3
+#error Invalid value for MPL_SEED_ID_TYPE
+#endif
+#if MPL_SEED_ID_TYPE == 0 && (MPL_SEED_ID_H > 0x00 || MPL_SEED_ID_L > 0x00)
+#warning MPL Seed ID Set but not used due to Seed ID type setting
+#endif
+#if MPL_SEED_ID_TYPE == 1 && MPL_SEED_ID_H > 0x00
+#warning MPL Seed ID upper 64 bits set but not used due to Seed ID type setting
+#endif
+#if MPL_SEED_ID_TYPE == 1 && MPL_SEED_ID_L > 0xFFFF
+#error MPL Seed ID too large for Seed ID type setting
+#endif
+#if MPL_SEED_ID_TYPE == 2 && MPL_SEED_ID_H > 0x00
+#warning MPL Seed ID upper 64 bits set yet not used due to Seed ID type setting
+#endif
+/*---------------------------------------------------------------------------*/
+/* Data Representation */
+/*---------------------------------------------------------------------------*/
+/* MPL Seed IDs */
+typedef struct seed_id_s {
+  uint8_t s;
+  uint8_t id[16];
+} seed_id_t;
+#define MPL_SEED_ID_UNKNOWN 0xFF
+/* Define a way of logging the seed id */
+#define LOG_SEED(level, seed_id) do { \
+    if(level <= (LOG_LEVEL)) { \
+      LOG_OUTPUT("0x%.2hx%.2hx%.2hx%.2hx%.2hx%.2hx%.2hx%.2hx%.2hx%.2hx%.2hx%.2hx%.2hx%.2hx%.2hx%.2hx", \
+                 seed_id.id[15], seed_id.id[14], seed_id.id[13], seed_id.id[12], \
+                 seed_id.id[11], seed_id.id[10], seed_id.id[9], seed_id.id[8], \
+                 seed_id.id[7], seed_id.id[6], seed_id.id[5], seed_id.id[4], \
+                 seed_id.id[3], seed_id.id[2], seed_id.id[1], seed_id.id[0]); \
+    } \
+} while(0);
+/* Macros to print seed id in logs */
+#define LOG_INFO_SEED(...) LOG_SEED(LOG_LEVEL_INFO, __VA_ARGS__)
+#define LOG_WARN_SEED(...) LOG_SEED(LOG_LEVEL_WARN, __VA_ARGS__)
+#define LOG_ERR_SEED(...) LOG_SEED(LOG_LEVEL_ERR, __VA_ARGS__)
+#define LOG_DBG_SEED(...) LOG_SEED(LOG_LEVEL_DBG, __VA_ARGS__)
+
+/* MPL Seed IDs can be either 16 bits, 64 bits, or 128 bits. If they are 128
+ *  bits then the IPV6 Source address may also be used as the seed ID.
+ *  These are always represented in contiki as a 128 bit number in the type
+ *  seed_id_t. The functions below convert a seed id of various lengths to
+ *  this 128 bit representation.
+ */
+/**
+ * \brief Set the seed id to a 16 bit constant
+ * dst: seed_id_t to set to the constant
+ * src: 16 bit integer to set
+ */
+#define SEED_ID_S1(dst, src) { (*(uint16_t *)&(dst)->id) = (src); (dst)->s = 1; }
+/**
+ * \brief Set the seed id to a 64 bit constant
+ * dst: seed_id_t to set to the constant
+ * src: 64 bit integer to set
+ */
+#define SEED_ID_S2(dst, src) { (*(uint64_t *)&(dst)->id) = (src); (dst)->s = 2; }
+/**
+ * \brief Set the seed id to a 128 bit constant
+ * dst: seed_id_t to set to the constant
+ * l: Lower 64 bits of the seed id to set
+ * h: Upper 64 bits of the seed id to set
+ */
+#define SEED_ID_S3(dst, l, h) { (*(uint64_t *)&(dst)->id) = (l); (*(uint64_t *)&(dst)->id[8]) = (h); (dst)->s = 3; }
+/**
+ * \brief Compare two contiki seed ids represented as seed_id_t types
+ * a: First value to compare
+ * b: Second value to compare
+ */
+#define seed_id_cmp(a, b) (memcmp((a)->id, (b)->id, sizeof(uint8_t) * 16) == 0)
+/**
+ * \brief Copy one seed_id_t into another.
+ * a: Destination
+ * b: Source
+ */
+#define seed_id_cpy(a, b) (memcpy((a), (b), sizeof(seed_id_t)))
+/**
+ * \brief Clear a seed id value to zero
+ * a: Value to clear
+ */
+#define seed_id_clr(a) (memset((a), 0, sizeof(seed_id_t)))
+/*---------------------------------------------------------------------------*/
+/* Buffered message set
+ *  This is implemented as a linked list since the majority of operations
+ *  involve finding the minimum sequence number and iterating up the list.
+ */
+struct mpl_msg {
+  struct mpl_msg *next; /* Next message in the set, or NULL if this is largest */
+  struct mpl_seed *seed; /* The seed set this message belongs to */
+  struct trickle_timer tt; /* The trickle timer associated with this msg */
+  uip_ip6addr_t srcipaddr; /* The original ip this message was sent from */
+  uint16_t size; /* Side of the data stored above */
+  uint8_t seq; /* The sequence number of the message */
+  uint8_t e; /* Expiration count for trickle timer */
+  uint8_t data[UIP_BUFSIZE]; /* Message payload */
+};
+/**
+ * \brief Get the state of the used flag in the buffered message set entry
+ * h: pointer to the message set entry
+ */
+#define MSG_SET_IS_USED(h) ((h)->seed != NULL)
+/**
+ * \brief Clear the state of the used flag in the buffered message set entry
+ * h: pointer to the message set entry
+ */
+#define MSG_SET_CLEAR_USED(h) ((h)->seed = NULL)
+/* RFC 1982 Serial Number Arithmetic */
+/**
+ * \brief s1 is said to be equal s2 if SEQ_VAL_IS_EQ(s1, s2) == 1
+ */
+#define SEQ_VAL_IS_EQ(i1, i2) ((i1) == (i2))
+
+/**
+ * \brief s1 is said to be less than s2 if SEQ_VAL_IS_LT(s1, s2) == 1
+ */
+#define SEQ_VAL_IS_LT(i1, i2) \
+  ( \
+    ((i1) != (i2)) && \
+    ((((i1) < (i2)) && ((int16_t)((i2) - (i1)) < 0x100)) || \
+     (((i1) > (i2)) && ((int16_t)((i1) - (i2)) > 0x100))) \
+  )
+
+/**
+ * \brief s1 is said to be greater than s2 iif SEQ_VAL_IS_LT(s1, s2) == 1
+ */
+#define SEQ_VAL_IS_GT(i1, i2) \
+  ( \
+    ((i1) != (i2)) && \
+    ((((i1) < (i2)) && ((int16_t)((i2) - (i1)) > 0x100)) || \
+     (((i1) > (i2)) && ((int16_t)((i1) - (i2)) < 0x100))) \
+  )
+
+/**
+ * \brief Add n to s: (s + n) modulo (2 ^ SERIAL_BITS) => ((s + n) % 0x8000)
+ */
+#define SEQ_VAL_ADD(s, n) (((s) + (n)) % 0x100)
+/*---------------------------------------------------------------------------*/
+/* Seed Set */
+struct mpl_seed {
+  seed_id_t seed_id;
+  uint8_t min_seqno; /* Used when the seed set is empty */
+  uint8_t lifetime; /* Decrements by one every minute */
+  uint8_t count; /* Only used for determining largest msg set during reclaim */
+  LIST_STRUCT(min_seq); /* Pointer to the first msg in this seed's set */
+  struct mpl_domain *domain; /* The domain this seed belongs to */
+};
+/**
+ * \brief Get the state of the used flag in the buffered message set entry
+ * h: pointer to the message set entry
+ */
+#define SEED_SET_IS_USED(h) (((h)->domain != NULL))
+/**
+ * \brief Clear the state of the used flag in the buffered message set entry
+ * h: pointer to the message set entry
+ */
+#define SEED_SET_CLEAR_USED(h) ((h)->domain = NULL)
+/*---------------------------------------------------------------------------*/
+/* Domain Set */
+struct mpl_domain {
+  uip_ip6addr_t data_addr; /* Data address for this MPL domain */
+  uip_ip6addr_t ctrl_addr; /* Link-local scoped version of data address */
+  struct trickle_timer tt;
+  uint8_t e; /* Expiration count for trickle timer */
+};
+/**
+ * \brief Get the state of the used flag in the buffered message set entry
+ * h: pointer to the message set entry
+ */
+#define DOMAIN_SET_IS_USED(h) (uip_is_addr_mcast(&(h)->data_addr))
+/**
+ * \brief Clear the state of the used flag in the buffered message set entry
+ * h: pointer to the message set entry
+ */
+#define DOMAIN_SET_CLEAR_USED(h) (memset(&(h)->data_addr, 0, sizeof(uip_ip6addr_t)))
+/*---------------------------------------------------------------------------*/
+/**
+ * Hop-by-Hop Options Header
+ * The header can take different forms depending on the length of the seed id,
+ * so all the different representations are shown here.
+ */
+struct mpl_hbho {
+  uint8_t type;
+  uint8_t len;
+  uint8_t flags;
+  uint8_t seq;
+  struct uip_ext_hdr_opt_padn padn;
+};
+struct mpl_hbho_s1 {
+  uint8_t type;
+  uint8_t len;
+  uint8_t flags;
+  uint8_t seq;
+  uint16_t seed_id;
+};
+struct mpl_hbho_s2 {
+  uint8_t type;
+  uint8_t len;
+  uint8_t flags;
+  uint8_t seq;
+  uint64_t seed_id;
+  struct uip_ext_hdr_opt_padn padn;
+};
+struct mpl_hbho_s3 {
+  uint8_t type;
+  uint8_t len;
+  uint8_t flags;
+  uint8_t seq;
+  uint8_t seed_id[16];
+  struct uip_ext_hdr_opt_padn padn;
+};
+/**
+ * \brief Get the MPL Parametrization for a multicast HBHO header
+ * m: pointer to the HBHO header
+ */
+#define HBH_GET_S(h) (((h)->flags & 0xC0) >> 6)
+
+/**
+ * \brief Set the MPL Parametrization bit for a multicast HBHO header
+ * m: pointer to the HBHO header
+ */
+#define HBH_SET_S(h, s) ((h)->flags |= ((s & 0x03) << 6))
+
+/**
+ * \brief Clear the MPL Parametrization bit for a multicast HBHO header
+ * m: pointer to the HBHO header
+ */
+#define HBH_CLR_S(h) ((h)->flags &= ~0xC0)
+
+/**
+ * \brief Get the MPL Parametrization for a multicast HBHO header
+ * m: pointer to the HBHO header
+ */
+#define HBH_GET_M(h) (((h)->flags & 0x20) == 0x20)
+
+/**
+ * \brief Set the MPL Parametrization bit for a multicast HBHO header
+ * m: pointer to the HBHO header
+ */
+#define HBH_SET_M(h) ((h)->flags |= 0x20)
+
+/**
+ * \brief Get the MPL Parametrization for a multicast HBHO header
+ * m: pointer to the HBHO header
+ */
+#define HBH_GET_V(h) (((h)->flags & 0x10) == 0x10)
+
+/**
+ * \brief Set the MPL Parametrization bit for a multicast HBHO header
+ * m: pointer to the HBHO header
+ */
+#define HBH_CLR_V(h) ((h)->flags &= ~0x10)
+/* Outdoing msg HBHO Sizes */
+#if MPL_SEED_ID_TYPE == 0
+#define HBHO_TOTAL_LEN HBHO_BASE_LEN + HBHO_S0_LEN
+#elif MPL_SEED_ID_TYPE == 1
+#define HBHO_TOTAL_LEN HBHO_BASE_LEN + HBHO_S1_LEN
+#elif MPL_SEED_ID_TYPE == 2
+#define HBHO_TOTAL_LEN HBHO_BASE_LEN + HBHO_S2_LEN
+#elif MPL_SEED_ID_TYPE == 3
+#define HBHO_TOTAL_LEN HBHO_BASE_LEN + HBHO_S3_LEN
+#endif
+/*---------------------------------------------------------------------------*/
+/** Seed Info Payload
+ * This is the payload sent in ICMP Control messages. It changes based on the
+ * Seed ID length being sent, so all the different representations it can take
+ * are shown here.
+ */
+struct seed_info {
+  uint8_t min_seqno;
+  uint8_t bm_len_S; /* First 6 bits bm-len, last 2 S */
+};
+struct seed_info_s1 {
+  uint8_t min_seqno;
+  uint8_t bm_len_S; /* First 6 bits bm-len, last 2 S */
+  uint16_t seed_id;
+};
+struct seed_info_s2 {
+  uint8_t min_seqno;
+  uint8_t bm_len_S; /* First 6 bits bm-len, last 2 S */
+  uint64_t seed_id;
+};
+struct seed_info_s3 {
+  uint8_t min_seqno;
+  uint8_t bm_len_S; /* First 6 bits bm-len, last 2 S */
+  uint8_t seed_id[16];
+};
+/**
+ * \brief Get the S bits in the length/S field in the seed info header
+ * h: pointer to the seed info struct
+ */
+#define SEED_INFO_GET_S(h) ((h)->bm_len_S & 0x03)
+/**
+ * \brief Clear the S bits within the length/S field in the seed info header
+ * h: pointer to the seed info struct
+ */
+#define SEED_INFO_CLR_S(h) ((h)->bm_len_S &= ~0x03)
+/**
+ * \brief Set the S bits within the seed info struct. These must be cleared beforehand.
+ * h: Pointer to the seed info struct
+ * s: value (0-3) that the S bits should be set to
+ */
+#define SEED_INFO_SET_S(h, s) ((h)->bm_len_S |= (s & 0x03))
+/**
+ * \brief Get the length bits from the seed info struct.
+ * h: pointer to seed info struct.
+ */
+#define SEED_INFO_GET_LEN(h) ((h)->bm_len_S >> 2)
+/**
+ * \brief Clear the length bits in the seed info struct.
+ * h: pointer to the seed info struct
+ */
+#define SEED_INFO_CLR_LEN(h) ((h)->bm_len_S &= 0x03)
+/**
+ * \brief Set the length bits in the seed info struct. These must be cleared beforehand.
+ * h: pointer to the seed info struct
+ * l: Length value (0-63) that the length bits should be set to
+ */
+#define SEED_INFO_SET_LEN(h, l) ((h)->bm_len_S |= (l << 2))
+/*---------------------------------------------------------------------------*/
+/* Maintain Stats */
+/*---------------------------------------------------------------------------*/
+#if UIP_MCAST6_STATS
+static struct mpl_stats stats;
+
+#define MPL_STATS_ADD(x) stats.x++
+#define MPL_STATS_INIT() do { memset(&stats, 0, sizeof(stats)); } while(0)
+#else /* UIP_MCAST6_STATS */
+#define MPL_STATS_ADD(x)
+#define MPL_STATS_INIT()
+#endif
+/*---------------------------------------------------------------------------*/
+/* Internal Data Structures */
+/*---------------------------------------------------------------------------*/
+static struct mpl_msg buffered_message_set[MPL_BUFFERED_MESSAGE_SET_SIZE];
+static struct mpl_seed seed_set[MPL_SEED_SET_SIZE];
+static struct mpl_domain domain_set[MPL_DOMAIN_SET_SIZE];
+static uint16_t last_seq;
+static seed_id_t local_seed_id;
+#if MPL_SUB_TO_ALL_FORWARDERS
+static uip_ip6addr_t all_forwarders;
+#endif
+static struct ctimer lifetime_timer;
+/*---------------------------------------------------------------------------*/
+/* Temporary Stores */
+/*---------------------------------------------------------------------------*/
+static struct mpl_hbho *lochbhmptr;  /* HBH Header Pointer */
+static struct mpl_seed *locssptr;  /* Seed Set Pointer */
+static struct mpl_msg *locmmptr;  /* MPL Message Pointer */
+static struct mpl_domain *locdsptr;  /* Domain set pointer */
+static struct seed_info *locsiptr;  /* Seed Info Pointer */
+/*---------------------------------------------------------------------------*/
+/* uIPv6 Pointers */
+/*---------------------------------------------------------------------------*/
+#define UIP_EXT_BUF       ((struct uip_ext_hdr *)UIP_IP_PAYLOAD(0))
+#define UIP_EXT_BUF_NEXT  ((uint8_t *)(UIP_IP_PAYLOAD(HBHO_TOTAL_LEN)))
+#define UIP_EXT_OPT_FIRST ((struct mpl_hbho *)(UIP_IP_PAYLOAD(0) + 2))
+extern uint16_t uip_slen;
+/*---------------------------------------------------------------------------*/
+/* Local Macros */
+/*---------------------------------------------------------------------------*/
+/**
+ * \brief Start the trickle timer for a control message
+ * t: Pointer to set that should be reset
+ */
+#define mpl_control_trickle_timer_start(t) { (t)->e = 0; trickle_timer_set(&(t)->tt, control_message_expiration, (t)); }
+/**
+ * \brief Start the trickle timer for a data message
+ * t: Pointer to set that should be reset
+ */
+#define mpl_data_trickle_timer_start(t) { (t)->e = 0; trickle_timer_set(&(t)->tt, data_message_expiration, (t)); }
+/**
+ * \brief Call inconsistency on the provided timer
+ * t: Pointer to set that should be reset
+ */
+#define mpl_trickle_timer_inconsistency(t) { (t)->e = 0; trickle_timer_inconsistency(&(t)->tt); }
+/**
+ * \brief Reset the trickle timer and expiration count for the set
+ * t: Pointer to set that should be reset
+ */
+#define mpl_trickle_timer_reset(t) { (t)->e = 0; trickle_timer_reset_event(&(t)->tt); }
+/**
+ * \brief Set a single bit within a bit vector that spans multiple bytes
+ * v: The bit vector
+ * b: The 0-indexed bit to set
+ */
+#define BIT_VECTOR_SET_BIT(v, b) (v[b / 8] |= (0x80 >> b % 8))
+/**
+ * \brief Get the value of a bit in a bit vector
+ * v: The bit vector
+ * b: The 0-indexed bit to get
+ */
+#define BIT_VECTOR_GET_BIT(v, b) ((v[b / 8] & (0x80 >> b % 8)) == (0x80 >> b % 8))
+/**
+ * \brief Modify an ipv6 address to give it link local scope
+ * a: uip_ip6addr_t address to modify
+ */
+#define UIP_ADDR_MAKE_LINK_LOCAL(a) (((uip_ip6addr_t *)a)->u8[1] = UIP_MCAST6_SCOPE_LINK_LOCAL)
+/*---------------------------------------------------------------------------*/
+/* Local function prototypes */
+/*---------------------------------------------------------------------------*/
+static void icmp_in(void);
+UIP_ICMP6_HANDLER(mpl_icmp_handler, ICMP6_MPL, 0, icmp_in);
+
+static struct mpl_msg *
+buffer_allocate(void)
+{
+  for(locmmptr = &buffered_message_set[MPL_BUFFERED_MESSAGE_SET_SIZE - 1]; locmmptr >= buffered_message_set; locmmptr--) {
+    if(!MSG_SET_IS_USED(locmmptr)) {
+      memset(locmmptr, 0, sizeof(struct mpl_msg));
+      return locmmptr;
+    }
+  }
+  return NULL;
+}
+static void
+buffer_free(struct mpl_msg *msg)
+{
+  if(trickle_timer_is_running(&msg->tt)) {
+    trickle_timer_stop(&msg->tt);
+  }
+  MSG_SET_CLEAR_USED(msg);
+}
+static struct mpl_msg *
+buffer_reclaim(void)
+{
+  static struct mpl_seed *ssptr; /* Can't use locssptr since it's used by calling function */
+  static struct mpl_seed *largest;
+  static struct mpl_msg *reclaim;
+
+  /* Reclaim the message with min_seq in the largest seed set */
+  largest = NULL;
+  reclaim = NULL;
+  for(ssptr = &seed_set[MPL_SEED_SET_SIZE]; ssptr >= seed_set; ssptr--) {
+    if(SEED_SET_IS_USED(ssptr) && (largest == NULL || ssptr->count > largest->count)) {
+      largest = ssptr;
+    }
+  }
+  /**
+   * To reclaim this, we need to increment the min seq number to
+   *   the next largest sequence number in the set.
+   * This won't necessarily be min_seq + 1 because MPL does not require or
+   *   ensure that sequence number are sequential, it just denotes the
+   *   order messages are sent.
+   * We've already worked out what this new value is.
+   */
+  if(largest != NULL) {
+    reclaim = list_pop(locssptr->min_seq);
+    largest->min_seqno = list_item_next(reclaim) == NULL ? reclaim->seq : ((struct mpl_msg *)list_item_next(reclaim))->seq;
+    largest->count--;
+    trickle_timer_stop(&reclaim->tt);
+    mpl_trickle_timer_reset(reclaim->seed->domain);
+    memset(reclaim, 0, sizeof(struct mpl_msg));
+  }
+  return reclaim;
+}
+static struct mpl_domain *
+domain_set_allocate(uip_ip6addr_t *address)
+{
+  uip_ip6addr_t data_addr;
+  uip_ip6addr_t ctrl_addr;
+  /* Determine the two addresses for this domain */
+  if(uip_mcast6_get_address_scope(address) == UIP_MCAST6_SCOPE_LINK_LOCAL) {
+    LOG_DBG("Domain Set Allocate has a local scoped address\n");
+    memcpy(&data_addr, address, sizeof(uip_ip6addr_t));
+    memcpy(&ctrl_addr, address, sizeof(uip_ip6addr_t));
+    do {
+      data_addr.u8[1]++;
+      if(uip_ds6_maddr_lookup(&data_addr)) {
+        LOG_DBG("Found higher scoped address in table\n");
+        break;
+      }
+    } while(data_addr.u8[1] <= 5);
+    if(data_addr.u8[1] > 5) {
+      LOG_ERR("Failed to find MPL domain data address in table\n");
+      return NULL;
+    }
+  } else {
+    memcpy(&data_addr, address, sizeof(uip_ip6addr_t));
+    memcpy(&ctrl_addr, address, sizeof(uip_ip6addr_t));
+    UIP_ADDR_MAKE_LINK_LOCAL(&ctrl_addr);
+  }
+  /* Now try the allocation */
+  for(locdsptr = &domain_set[MPL_DOMAIN_SET_SIZE - 1]; locdsptr >= domain_set; locdsptr--) {
+    if(!DOMAIN_SET_IS_USED(locdsptr)) {
+      if(!uip_ds6_maddr_lookup(&ctrl_addr) && !uip_ds6_maddr_add(&ctrl_addr)) {
+        LOG_ERR("Failed to subscribe to link local address for domain ");
+        LOG_ERR_6ADDR(address);
+        LOG_ERR_("\n");
+        return NULL;
+      }
+      memset(locdsptr, 0, sizeof(struct mpl_domain));
+      memcpy(&locdsptr->data_addr, &data_addr, sizeof(uip_ip6addr_t));
+      memcpy(&locdsptr->ctrl_addr, &ctrl_addr, sizeof(uip_ip6addr_t));
+      if(!trickle_timer_config(&locdsptr->tt,
+                               MPL_CONTROL_MESSAGE_IMIN,
+                               MPL_CONTROL_MESSAGE_IMAX,
+                               MPL_CONTROL_MESSAGE_K)) {
+        LOG_ERR("Unable to configure trickle timer for domain. Dropping,...\n");
+        DOMAIN_SET_CLEAR_USED(locdsptr);
+        return NULL;
+      }
+      return locdsptr;
+    }
+  }
+  return NULL;
+}
+/* Lookup the seed id in the seed set */
+static struct mpl_seed *
+seed_set_lookup(seed_id_t *seed_id, struct mpl_domain *domain)
+{
+  for(locssptr = &seed_set[MPL_SEED_SET_SIZE - 1]; locssptr >= seed_set; locssptr--) {
+    if(SEED_SET_IS_USED(locssptr) && seed_id_cmp(seed_id, &locssptr->seed_id) && locssptr->domain == domain) {
+      return locssptr;
+    }
+  }
+  return NULL;
+}
+static struct mpl_seed *
+seed_set_allocate(void)
+{
+  for(locssptr = &seed_set[MPL_SEED_SET_SIZE - 1]; locssptr >= seed_set; locssptr--) {
+    if(!SEED_SET_IS_USED(locssptr)) {
+      locssptr->count = 0;
+      LIST_STRUCT_INIT(locssptr, min_seq);
+      return locssptr;
+    }
+  }
+  return NULL;
+}
+static void
+seed_set_free(struct mpl_seed *s)
+{
+  while((locmmptr = list_pop(s->min_seq)) != NULL) {
+    buffer_free(locmmptr);
+  }
+  SEED_SET_CLEAR_USED(s);
+}
+static struct mpl_domain *
+domain_set_lookup(uip_ip6addr_t *domain)
+{
+  for(locdsptr = &domain_set[MPL_DOMAIN_SET_SIZE - 1]; locdsptr >= domain_set; locdsptr--) {
+    if(DOMAIN_SET_IS_USED(locdsptr)) {
+      if(uip_ip6addr_cmp(domain, &locdsptr->data_addr)
+         || uip_ip6addr_cmp(domain, &locdsptr->ctrl_addr)) {
+        return locdsptr;
+      }
+    }
+  }
+  return NULL;
+}
+static void
+domain_set_free(struct mpl_domain *domain)
+{
+  uip_ds6_maddr_t *addr;
+  /* Must include freeing seeds otherwise we leak memory */
+  for(locssptr = &seed_set[MPL_SEED_SET_SIZE]; locssptr >= seed_set; locssptr--) {
+    if(SEED_SET_IS_USED(locssptr) && locssptr->domain == domain) {
+      seed_set_free(locssptr);
+    }
+  }
+  addr = uip_ds6_maddr_lookup(&domain->data_addr);
+  if(addr != NULL) {
+    uip_ds6_maddr_rm(addr);
+  }
+  addr = uip_ds6_maddr_lookup(&domain->ctrl_addr);
+  if(addr != NULL) {
+    uip_ds6_maddr_rm(addr);
+  }
+  if(trickle_timer_is_running(&domain->tt)) {
+    trickle_timer_stop(&domain->tt);
+  }
+  DOMAIN_SET_CLEAR_USED(domain);
+}
+static void
+seed_id_net_to_host(seed_id_t *dst, void *src, uint8_t s)
+{
+  /**
+   * Convert a seed id in network order header format and length S to
+   * internal representation.
+   */
+  static uint8_t i;
+  static uint8_t *ptr;
+  ptr = src;
+  switch(s) {
+  case 0:
+    /* 128 bit seed ID from IPV6 Address */
+    dst->s = 0;
+    for(i = 0; i < 16; i++) {
+      dst->id[i] = ptr[15 - i];
+    }
+    return;
+  case 1:
+    /* 16 bit seed ID */
+    dst->s = 1;
+    for(i = 2; i < 15; i++) {
+      /* Clear the first 13 bytes in the id */
+      dst->id[i] = 0;
+    }
+    dst->id[0] = ptr[1];
+    dst->id[1] = ptr[0];
+    return;
+  case 2:
+    /* 64 bit Seed ID */
+    dst->s = 2;
+    for(i = 0; i < 8; i++) {
+      /* Reverse the byte order */
+      dst->id[i] = ptr[7 - i];
+    }
+    for(i = 8; i < 16; i++) {
+      /* Set the remainder to zero */
+      dst->id[i] = 0;
+    }
+    return;
+  case 3:
+    /* 128 bit seed ID */
+    dst->s = 3;
+    for(i = 0; i < 16; i++) {
+      dst->id[i] = ptr[15 - i];
+    }
+    return;
+  default:
+    /* Invalid seed size */
+    return;
+  }
+}
+static void
+seed_id_host_to_net(void *dst, seed_id_t *src)
+{
+  /**
+   * Convert a seed id from our internal representation to network
+   * order and representation based on length s.
+   */
+  static uint8_t i;
+  static uint8_t *ptr;
+  ptr = dst;
+  switch(src->s) {
+  case 0:
+  case 3:
+    /* Both use 128 bit seed IDs and do exactly the same thing */
+    for(i = 0; i < 16; i++) {
+      /* Byte order must be swapped */
+      ptr[i] = src->id[15 - i];
+    }
+    return;
+  case 1:
+    /* 16 bit seed id */
+    ptr[0] = src->id[1];
+    ptr[1] = src->id[0];
+    return;
+  case 2:
+    /* 64 bit Seed ID */
+    for(i = 0; i < 8; i++) {
+      ptr[i] = src->id[7 - i];
+    }
+    return;
+  default:
+    /* Invalid seed size */
+    return;
+  }
+}
+static void
+update_seed_id(void)
+{
+  /* Load my seed ID into memory */
+#if MPL_SEED_ID_TYPE == 0
+  /* Copy seed ID from out link local ip address */
+  static uip_ds6_addr_t *my_ip6_addr;
+  my_ip6_addr = uip_ds6_get_global(ADDR_PREFERRED);
+  if(my_ip6_addr != NULL) {
+    seed_id_net_to_host(&local_seed_id, &my_ip6_addr->ipaddr, 0);
+  } else {
+    local_seed_id.s = MPL_SEED_ID_UNKNOWN;
+    LOG_DBG("Seed id not yet known.\n");
+    return;
+  }
+#elif MPL_SEED_ID_TYPE == 1
+  /* 16 bit seed id */
+  SEED_ID_S1(&local_seed_id, MPL_SEED_ID_L);
+#elif MPL_SEED_ID_TYPE == 2
+  /* 64 bit seed id */
+  SEED_ID_S2(&local_seed_id, MPL_SEED_ID_L);
+#elif MPL_SEED_ID_TYPE == 3
+  /* 128 bit seed id */
+  SEED_ID_S3(&local_seed_id, MPL_SEED_ID_L, MPL_SEED_ID_H);
+#endif
+
+  LOG_DBG("My seed id is ");
+  LOG_DBG_SEED(local_seed_id);
+  LOG_DBG_(" with S=%u\n", local_seed_id.s);
+}
+void
+icmp_out(struct mpl_domain *dom)
+{
+  uint8_t vector[32];
+  uint8_t vec_size;
+  uint8_t vec_len;
+  uint16_t payload_len;
+  uip_ds6_addr_t *addr;
+  size_t seed_info_len;
+
+  LOG_INFO("MPL Control Message Out\n");
+
+  UIP_IP_BUF->vtc = 0x60;
+  UIP_IP_BUF->tcflow = 0;
+  UIP_IP_BUF->flow = 0;
+  UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
+  UIP_IP_BUF->ttl = MPL_IP_HOP_LIMIT;
+
+  locsiptr = (struct seed_info *)UIP_ICMP_PAYLOAD;
+  payload_len = 0;
+
+  /* Set the source address to link local for now. If we need to, we can try changing it to global later */
+  uip_ip6addr_copy(&UIP_IP_BUF->destipaddr, &dom->ctrl_addr);
+  uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
+
+  /* Iterate over seed set to create payload */
+  for(locssptr = &seed_set[MPL_SEED_SET_SIZE - 1]; locssptr >= seed_set; locssptr--) {
+    if(SEED_SET_IS_USED(locssptr) && locssptr->domain == dom) {
+      locsiptr->min_seqno = locssptr->min_seqno;
+      SEED_INFO_CLR_LEN(locsiptr);
+      SEED_INFO_CLR_S(locsiptr);
+
+      /* Try setting our source address to global */
+      addr = uip_ds6_get_global(ADDR_PREFERRED);
+      if(addr) {
+        uip_ip6addr_copy(&UIP_IP_BUF->srcipaddr, &addr->ipaddr);
+      } else {
+        /* Failed setting a global ip address, fallback to link local */
+        uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
+        if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
+          LOG_ERR("icmp out: Cannot set src ip\n");
+          uipbuf_clear();
+          return;
+        }
+      }
+
+      /* Set the Seed ID */
+      switch(locssptr->seed_id.s) {
+      case 0:
+        if(uip_ip6addr_cmp((uip_ip6addr_t *)&locssptr->seed_id.id, &UIP_IP_BUF->srcipaddr)) {
+          /* We can use an S=0 Seed ID */
+          SEED_INFO_SET_LEN(locsiptr, 0);
+          break;
+        } /* Else fall down into the S = 3 case */
+      case 3:
+        seed_id_host_to_net(&((struct seed_info_s3 *)locsiptr)->seed_id, &locssptr->seed_id);
+        SEED_INFO_SET_S(locsiptr, 3);
+        break;
+      case 1:
+        seed_id_host_to_net(&((struct seed_info_s1 *)locsiptr)->seed_id, &locssptr->seed_id);
+        SEED_INFO_SET_S(locsiptr, 1);
+        break;
+      case 2:
+        seed_id_host_to_net(&((struct seed_info_s2 *)locsiptr)->seed_id, &locssptr->seed_id);
+        SEED_INFO_SET_S(locsiptr, 2);
+        break;
+      }
+
+      /* Populate the seed info message vector */
+      memset(vector, 0, sizeof(vector));
+      vec_len = 0;
+      locmmptr = list_head(locssptr->min_seq);
+      while(locmmptr != NULL) {
+        if(locmmptr->seq == SEQ_VAL_ADD(locssptr->min_seqno, vec_len)) {
+          BIT_VECTOR_SET_BIT(vector, vec_len);
+          locmmptr = list_item_next(locmmptr);
+        }
+        vec_len++;
+      }
+
+      /* Convert vector length from bits to bytes */
+      vec_size = (vec_len - 1) / 8 + 1;
+
+      SEED_INFO_SET_LEN(locsiptr, vec_size);
+
+      LOG_DBG("--- Control Message Entry ---\n");
+      LOG_DBG("Seed ID: ");
+      LOG_DBG_SEED(locssptr->seed_id);
+      LOG_DBG_("\n");
+      LOG_DBG("S=%u\n", locssptr->seed_id.s);
+      LOG_DBG("Min Sequence Number: %u\n", locssptr->min_seqno);
+      LOG_DBG("Size of message set: %u\n", vec_len);
+      LOG_DBG("Vector is %u bytes\n", vec_size);
+
+      /* Copy vector into payload and point ptr to next location */
+      switch(SEED_INFO_GET_S(locsiptr)) {
+      case 0:
+        seed_info_len = sizeof(struct seed_info);
+        break;
+      case 1:
+        seed_info_len = sizeof(struct seed_info_s1);
+        break;
+      case 2:
+        seed_info_len = sizeof(struct seed_info_s2);
+        break;
+      case 3:
+        seed_info_len = sizeof(struct seed_info_s3);
+        break;
+      }
+      memcpy(((void *)locsiptr) + seed_info_len, vector, vec_size);
+      locsiptr = ((void *)locsiptr) + seed_info_len + vec_size;
+      payload_len += seed_info_len + vec_size;
+    }
+    /* Now go to next seed in set */
+  }
+  LOG_DBG("--- End of Messages --\n");
+
+  /* Finish off construction of ICMP Packet */
+  uipbuf_set_len_field(UIP_IP_BUF, UIP_ICMPH_LEN + payload_len);
+  UIP_ICMP_BUF->type = ICMP6_MPL;
+  UIP_ICMP_BUF->icode = 0;
+  uip_len = UIP_IPH_LEN + UIP_ICMPH_LEN + payload_len;
+  UIP_ICMP_BUF->icmpchksum = 0;
+  UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
+
+  LOG_DBG("ICMP Out from ");
+  LOG_DBG_6ADDR(&UIP_IP_BUF->srcipaddr);
+  LOG_DBG_(" to ");
+  LOG_DBG_6ADDR(&UIP_IP_BUF->destipaddr);
+  LOG_DBG_("\n");
+
+  LOG_DBG("MPL Contol Message Out - %u bytes\n", payload_len);
+
+  tcpip_ipv6_output();
+  uipbuf_clear();
+  MPL_STATS_ADD(icmp_out);
+  return;
+}
+static void
+data_message_expiration(void *ptr, uint8_t suppress)
+{
+  /* Callback for data message trickle timers */
+  locmmptr = ((struct mpl_msg *)ptr);
+  if(locmmptr->e > MPL_DATA_MESSAGE_TIMER_EXPIRATIONS) {
+    /* Terminate the trickle timer here if we've already expired enough times */
+    trickle_timer_stop(&locmmptr->tt);
+    return;
+  }
+  if(suppress == TRICKLE_TIMER_TX_OK) { /* Only transmit if not suppressed */
+    LOG_DBG("Data message TX\n");
+    LOG_DBG("Seed ID=");
+    LOG_DBG_SEED(locmmptr->seed->seed_id);
+    LOG_DBG_(", S=%u, Seq=%u\n", locmmptr->seed->seed_id.s, locmmptr->seq);
+    /* Setup the IP Header */
+    UIP_IP_BUF->vtc = 0x60;
+    UIP_IP_BUF->tcflow = 0;
+    UIP_IP_BUF->flow = 0;
+    UIP_IP_BUF->proto = UIP_PROTO_HBHO;
+    /*UIP_IP_BUF->ttl = MPL_IP_HOP_LIMIT; */
+    uip_ip6addr_copy(&UIP_IP_BUF->destipaddr, &locmmptr->seed->domain->data_addr);
+    uip_len = UIP_IPH_LEN;
+    /* Setup the HBHO Header */
+    UIP_EXT_BUF->next = UIP_PROTO_UDP;
+    lochbhmptr = UIP_EXT_OPT_FIRST;
+    lochbhmptr->type = HBHO_OPT_TYPE_MPL;
+    lochbhmptr->flags = 0x00;
+    switch(locmmptr->seed->seed_id.s) {
+    case 0:
+      UIP_EXT_BUF->len = HBHO_S0_LEN / 8;
+      lochbhmptr->len = MPL_OPT_LEN_S0;
+      HBH_CLR_S(lochbhmptr);
+      HBH_SET_S(lochbhmptr, 0);
+      uip_len += HBHO_BASE_LEN + HBHO_S0_LEN;
+      uip_ext_len += HBHO_BASE_LEN + HBHO_S0_LEN;
+      lochbhmptr->padn.opt_type = UIP_EXT_HDR_OPT_PADN;
+      lochbhmptr->padn.opt_len = 0x00;
+      break;
+    case 1:
+      UIP_EXT_BUF->len = HBHO_S1_LEN / 8;
+      lochbhmptr->len = MPL_OPT_LEN_S1;
+      HBH_CLR_S(lochbhmptr);
+      HBH_SET_S(lochbhmptr, 1);
+      seed_id_host_to_net(&((struct mpl_hbho_s1 *)lochbhmptr)->seed_id, &locmmptr->seed->seed_id);
+      uip_len += HBHO_BASE_LEN + HBHO_S1_LEN;
+      uip_ext_len += HBHO_BASE_LEN + HBHO_S1_LEN;
+      break;
+    case 2:
+      UIP_EXT_BUF->len = HBHO_S2_LEN / 8;
+      lochbhmptr->len = MPL_OPT_LEN_S2;
+      HBH_CLR_S(lochbhmptr);
+      HBH_SET_S(lochbhmptr, 2);
+      seed_id_host_to_net(&((struct mpl_hbho_s2 *)lochbhmptr)->seed_id, &locmmptr->seed->seed_id);
+      uip_len += HBHO_BASE_LEN + HBHO_S2_LEN;
+      uip_ext_len += HBHO_BASE_LEN + HBHO_S2_LEN;
+      ((struct mpl_hbho_s2 *)lochbhmptr)->padn.opt_type = UIP_EXT_HDR_OPT_PADN;
+      ((struct mpl_hbho_s2 *)lochbhmptr)->padn.opt_len = 0x00;
+      break;
+    case 3:
+      UIP_EXT_BUF->len = HBHO_S3_LEN / 8;
+      lochbhmptr->len = MPL_OPT_LEN_S3;
+      HBH_CLR_S(lochbhmptr);
+      HBH_SET_S(lochbhmptr, 3);
+      seed_id_host_to_net(&((struct mpl_hbho_s3 *)lochbhmptr)->seed_id, &locmmptr->seed->seed_id);
+      uip_len += HBHO_BASE_LEN + HBHO_S3_LEN;
+      uip_ext_len += HBHO_BASE_LEN + HBHO_S3_LEN;
+      ((struct mpl_hbho_s3 *)lochbhmptr)->padn.opt_type = UIP_EXT_HDR_OPT_PADN;
+      ((struct mpl_hbho_s3 *)lochbhmptr)->padn.opt_len = 0x00;
+      break;
+    }
+    lochbhmptr->seq = locmmptr->seq;
+    if(list_item_next(locmmptr) == NULL) {
+      HBH_SET_M(lochbhmptr);
+    }
+    /* Now insert payload */
+    memcpy(((void *)UIP_EXT_BUF) + 8 + UIP_EXT_BUF->len * 8, &locmmptr->data, locmmptr->size);
+    uip_len += locmmptr->size;
+    uipbuf_set_len_field(UIP_IP_BUF, uip_len - UIP_IPH_LEN);
+    uip_ip6addr_copy(&UIP_IP_BUF->srcipaddr, &locmmptr->srcipaddr);
+    tcpip_output(NULL);
+    uipbuf_clear();
+    UIP_MCAST6_STATS_ADD(mcast_out);
+  }
+
+  locmmptr->e++;
+}
+static void
+control_message_expiration(void *ptr, uint8_t suppress)
+{
+  /* Control message timer callback */
+  locdsptr = ((struct mpl_domain *)ptr);
+  if(locdsptr->e > MPL_CONTROL_MESSAGE_TIMER_EXPIRATIONS) {
+    /* Disable the trickle timer for now */
+    trickle_timer_stop(&locdsptr->tt);
+    return;
+  }
+  if(suppress == TRICKLE_TIMER_TX_OK) {
+    /* Send an MPL Control Message */
+    icmp_out(locdsptr);
+  }
+  locdsptr->e++;
+}
+static void
+mpl_maddr_check(void)
+{
+  /* Check for new multicast addresses that aren't in our domain set */
+  uip_ds6_maddr_t *elem;
+  for(elem = &uip_ds6_if.maddr_list[UIP_DS6_MADDR_NB - 1];
+      elem >= uip_ds6_if.maddr_list;
+      elem--) {
+    if(elem->isused && uip_mcast6_get_address_scope(&elem->ipaddr) > UIP_MCAST6_SCOPE_LINK_LOCAL) {
+      locdsptr = domain_set_lookup(&elem->ipaddr);
+      if(!locdsptr) {
+        locdsptr = domain_set_allocate(&elem->ipaddr);
+        if(!locdsptr) {
+          LOG_ERR("Failed to allocate domain set in mpl_maddr_check()\n");
+        }
+      }
+    }
+  }
+  /* Check for domain set addresses that aren't in our maddr table */
+  for(locdsptr = &domain_set[MPL_DOMAIN_SET_SIZE - 1]; locdsptr >= domain_set; locdsptr--) {
+    if(DOMAIN_SET_IS_USED(locdsptr) && !uip_ds6_maddr_lookup(&locdsptr->data_addr)) {
+      domain_set_free(locdsptr);
+    }
+  }
+}
+static void
+lifetime_timer_expiration(void *ptr)
+{
+  /* Called once per minute to decrement seed lifetime counters */
+  for(locssptr = &seed_set[MPL_SEED_SET_SIZE - 1]; seed_set <= locssptr; locssptr--) {
+    if(SEED_SET_IS_USED(locssptr) && locssptr->lifetime == 0) {
+      /* Check no timers are running */
+      locmmptr = list_head(locssptr->min_seq);
+      while(locmmptr != NULL) {
+        if(trickle_timer_is_running(&locmmptr->tt)) {
+          /* We must keep this seed */
+          break;
+        }
+        locmmptr = list_item_next(locmmptr);
+      }
+      if(locmmptr == NULL) {
+        /* We can now free this seed set */
+        LOG_INFO("Seed ");
+        LOG_INFO_SEED(locssptr->seed_id);
+        LOG_INFO_(" expired. Freeing...\n");
+        seed_set_free(locssptr);
+      }
+    }
+    if(locssptr->lifetime > 0) {
+      locssptr->lifetime--;
+    }
+  }
+  mpl_maddr_check();
+  ctimer_reset(&lifetime_timer);
+}
+static void
+icmp_in(void)
+{
+  static seed_id_t seed_id;
+  static uint8_t r;
+  static uint8_t *vector;
+  static uint8_t vector_len;
+  static uint8_t r_missing;
+  static uint8_t l_missing;
+
+  LOG_INFO("MPL ICMP Control Message In\n");
+
+#if UIP_CONF_IPV6_CHECKS
+  if(!uip_is_addr_mcast_non_routable(&UIP_IP_BUF->destipaddr)) {
+    LOG_ERR("ICMPv6 In, bad dest ");
+    LOG_ERR_6ADDR(&UIP_IP_BUF->destipaddr);
+    LOG_ERR_("\n");
+    MPL_STATS_ADD(icmp_bad);
+    goto discard;
+  }
+
+  if(UIP_ICMP_BUF->type != ICMP6_MPL) {
+    LOG_ERR("ICMPv6 In, bad ICMP type\n");
+    MPL_STATS_ADD(icmp_bad);
+    goto discard;
+  }
+
+  if(UIP_ICMP_BUF->icode != 0) {
+    LOG_ERR("ICMPv6 In, bad ICMP type\n");
+    MPL_STATS_ADD(icmp_bad);
+    goto discard;
+  }
+
+  if(UIP_IP_BUF->ttl != MPL_IP_HOP_LIMIT) {
+    LOG_ERR("ICMPv6 In, bad TTL\n");
+    MPL_STATS_ADD(icmp_bad);
+    goto discard;
+  }
+#endif
+
+  LOG_INFO("MPL ICMP Control Message from ");
+  LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
+  LOG_INFO_(" len %u, ext %u\n", uip_len, uip_ext_len);
+
+  MPL_STATS_ADD(icmp_in);
+
+  /* Find the domain that this has come from */
+  locdsptr = domain_set_lookup(&UIP_IP_BUF->destipaddr);
+
+  if(!locdsptr) {
+    LOG_INFO("New MPL Domain ");
+    LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
+    LOG_INFO_("\n");
+    locdsptr = domain_set_allocate(&UIP_IP_BUF->destipaddr);
+    if(!locdsptr) {
+      LOG_ERR("Couldn't allocate new domain. Dropping.\n");
+      UIP_MCAST6_STATS_ADD(icmp_bad);
+      goto discard;
+    }
+    mpl_control_trickle_timer_start(locdsptr);
+  }
+  l_missing = 0;
+  r_missing = 0;
+
+  /* Iterate over our seed set and check all are present in the remote seed sed */
+  locsiptr = (struct seed_info *)UIP_ICMP_PAYLOAD;
+  for(locssptr = &seed_set[MPL_SEED_SET_SIZE - 1]; locssptr >= seed_set; locssptr--) {
+    if(SEED_SET_IS_USED(locssptr) && locssptr->domain == locdsptr) {
+      LOG_DBG("Checking remote for seed ");
+      LOG_DBG_SEED(locssptr->seed_id);
+      LOG_DBG_("\n");
+      while(locsiptr <
+            (struct seed_info *)((void *)UIP_ICMP_PAYLOAD + uip_len - uip_l3_icmp_hdr_len)) {
+        switch(SEED_INFO_GET_S(locsiptr)) {
+        case 0:
+          seed_id_net_to_host(&seed_id, &UIP_IP_BUF->srcipaddr, 0);
+          locsiptr = ((void *)locsiptr) + sizeof(struct seed_info) + SEED_INFO_GET_LEN(locsiptr);
+          if(seed_id_cmp(&seed_id, &locssptr->seed_id)) {
+            goto seed_present;
+          }
+          break;
+        case 1:
+          seed_id_net_to_host(&seed_id, &((struct seed_info_s1 *)locsiptr)->seed_id, 1);
+          locsiptr = ((void *)locsiptr) + sizeof(struct seed_info_s1) + SEED_INFO_GET_LEN(locsiptr);
+          if(seed_id_cmp(&seed_id, &locssptr->seed_id)) {
+            goto seed_present;
+          }
+          break;
+        case 2:
+          seed_id_net_to_host(&seed_id, &((struct seed_info_s2 *)locsiptr)->seed_id, 2);
+          locsiptr = ((void *)locsiptr) + sizeof(struct seed_info_s2) + SEED_INFO_GET_LEN(locsiptr);
+          if(seed_id_cmp(&seed_id, &locssptr->seed_id)) {
+            goto seed_present;
+          }
+          break;
+        case 3:
+          seed_id_net_to_host(&seed_id, &((struct seed_info_s3 *)locsiptr)->seed_id, 3);
+          locsiptr = ((void *)locsiptr) + sizeof(struct seed_info_s3) + SEED_INFO_GET_LEN(locsiptr);
+          if(seed_id_cmp(&seed_id, &locssptr->seed_id)) {
+            goto seed_present;
+          }
+          break;
+        }
+      }
+      /* If we made it this far, the seed is missing from the remote. Reset all message timers */
+      LOG_DBG("Remote is missing seed ");
+      LOG_DBG_SEED(locssptr->seed_id);
+      LOG_DBG_("\n");
+      r_missing = 1;
+      if(list_head(locssptr->min_seq) != NULL) {
+        for(locmmptr = list_head(locssptr->min_seq); locmmptr != NULL; locmmptr = list_item_next(locmmptr)) {
+          LOG_DBG("Resetting timer for messages\n");
+          if(!trickle_timer_is_running(&locmmptr->tt)) {
+            LOG_DBG("Starting timer for messages\n");
+            mpl_data_trickle_timer_start(locmmptr);
+          }
+          mpl_trickle_timer_inconsistency(locmmptr);
+        }
+      }
+      /* Otherwise we jump here and continute */
+seed_present:
+      continue;
+    }
+  }
+
+  /* Iterate over remote seed info and they're present locally. Additionally check messages match */
+  locsiptr = (struct seed_info *)UIP_ICMP_PAYLOAD;
+  while(locsiptr <
+        (struct seed_info *)((void *)UIP_ICMP_PAYLOAD + uip_len - uip_l3_icmp_hdr_len)) {
+    /* Extract the seed id */
+    if(SEED_INFO_GET_S(locsiptr) > 0) {
+      seed_id_net_to_host(&seed_id, &((struct seed_info_s1 *)locsiptr)->seed_id, SEED_INFO_GET_S(locsiptr));
+    } else {
+      /* Always set as S3 because it will never be us */
+      seed_id_net_to_host(&seed_id, &UIP_IP_BUF->srcipaddr, 3);
+    }
+
+    LOG_DBG("Control Message for Seed Id: ");
+    LOG_DBG_SEED(seed_id);
+    LOG_DBG_("Min Seq Number: %u, %u bytes\n", locsiptr->min_seqno, SEED_INFO_GET_LEN(locsiptr));
+
+    /* Do we have this seed? */
+    locssptr = seed_set_lookup(&seed_id, locdsptr);
+    if(!locssptr) {
+      LOG_DBG("Unknown seed in seed info\n");
+      /* We don't know this seed */
+      l_missing = 1;
+      goto next;
+    }
+
+    /* Work out where remote bit vector starts */
+    vector_len = SEED_INFO_GET_LEN(locsiptr) * 8;
+    switch(SEED_INFO_GET_S(locsiptr)) {
+    case 0:
+      vector = ((void *)locsiptr) + sizeof(struct seed_info);
+      break;
+    case 1:
+      vector = ((void *)locsiptr) + sizeof(struct seed_info_s1);
+      break;
+    case 2:
+      vector = ((void *)locsiptr) + sizeof(struct seed_info_s2);
+      break;
+    case 3:
+      vector = ((void *)locsiptr) + sizeof(struct seed_info_s3);
+      break;
+    }
+
+    /* Potential quick resolution here */
+    locmmptr = list_head(locssptr->min_seq);
+    if(locmmptr == NULL) {
+      /* We have nothing! */
+      if(vector[0] > 0) {
+        /* They have something! */
+        l_missing = 1;
+      }
+      goto next;
+    }
+    /**
+     * Work out what offset the local or remote message set need so that the
+     * sequence numbers match up
+     */
+    r = 0;
+    if(locmmptr->seq != locsiptr->min_seqno) {
+      if(SEQ_VAL_IS_GT(locmmptr->seq, locsiptr->min_seqno)) {
+        while(locmmptr->seq != SEQ_VAL_ADD(locsiptr->min_seqno, r) && r <= vector_len) {
+          r++;
+        }
+      } else {
+        while(locmmptr != NULL && locmmptr->seq != locsiptr->min_seqno) {
+          locmmptr = list_item_next(locmmptr);
+        }
+      }
+
+      /* There is no overlap in message sets */
+      if(r > vector_len || locmmptr == NULL) {
+        LOG_WARN("Seed sets of local and remote have no overlap.\n");
+        /* Work out who is behind who */
+        locmmptr = list_head(locssptr->min_seq);
+        while(list_item_next(locmmptr) != NULL) {
+          locmmptr = list_item_next(locmmptr);
+        }
+        r = vector_len;
+        while(!BIT_VECTOR_GET_BIT(vector, r)) {
+          r--;
+        }
+        if(SEQ_VAL_IS_GT(locmmptr->seq, SEQ_VAL_ADD(locsiptr->min_seqno, r))) {
+          /* Our max sequence number is greater than their max sequence number */
+          LOG_DBG("Our max sequence number is greater than their max sequence number\n");
+          r_missing = 1;
+          /* Additionally all data message timers in set if r is behind us */
+          if(list_head(locssptr->min_seq) != NULL) {
+            for(locmmptr = list_head(locssptr->min_seq); locmmptr != NULL; locmmptr = list_item_next(locmmptr)) {
+              if(!trickle_timer_is_running(&locmmptr->tt)) {
+                mpl_data_trickle_timer_start(locmmptr);
+              }
+              mpl_trickle_timer_inconsistency(locmmptr);
+            }
+          }
+        } else {
+          l_missing = 1;
+        }
+        goto next;
+      }
+    }
+
+    /**
+     * If we've made it this far, our sets overlap and we can work out specific
+     *   messages that may be missing from each set.
+     */
+    do {
+      /* This won't occur on first iteration */
+      /* Resyncronise our pointers to local and remote messages after previous iteration */
+      while(locmmptr->seq != SEQ_VAL_ADD(locsiptr->min_seqno, r)) {
+        /**
+         * If we enter this loop it means there is a gap in local sequence numbers.
+         *  Check that same gap exists in the remote set.
+         */
+        if(BIT_VECTOR_GET_BIT(vector, r)) {
+          /* We are missing a message. Reset timer */
+          LOG_DBG("We are missing seq=%u\n", SEQ_VAL_ADD(locsiptr->min_seqno, r));
+          l_missing = 1;
+        }
+        r++;
+      }
+      /* At this point the local pointer and remote pointer will be in sync */
+
+      /* Check whether the remote is missing the current message */
+      if(!BIT_VECTOR_GET_BIT(vector, r)) {
+        /* Local message is missing from remote set. Reset control and data timers */
+        LOG_DBG("Remote is missing seq=%u\n", locmmptr->seq);
+        r_missing = 1;
+        if(!trickle_timer_is_running(&locmmptr->tt)) {
+          mpl_data_trickle_timer_start(locmmptr);
+        }
+        mpl_trickle_timer_inconsistency(locmmptr);
+      }
+
+      /* Now increment our pointers */
+      r++;
+      locmmptr = list_item_next(locmmptr);
+      /* These are then resyncronised at the top of the loop */
+    } while(locmmptr != NULL && r <= vector_len);
+
+    /* If we have stopped short of either message set then we may have inconsistencies */
+    if(locmmptr != NULL || r < vector_len) {
+      /**
+       * We have reached the end of local set, the remainder of the remote set should
+       *  be zero else local is missing a message.
+       */
+      while(r < vector_len) {
+        if(BIT_VECTOR_GET_BIT(vector, r)) {
+          /* We are missing a message */
+          LOG_DBG("We are missing seq=%u which is greater than our max seq number\n", SEQ_VAL_ADD(locsiptr->min_seqno, r));
+          l_missing = 1;
+        }
+        r++;
+      }
+    } else if(r >= vector_len && locmmptr != NULL) {
+      /* We have reached the end of the remote set.
+       *  Any remaining messages are missing and should be reset.
+       */
+      while(locmmptr != NULL) {
+        LOG_DBG("Remote is missing all above seq=%u\n", locmmptr->seq);
+        if(!trickle_timer_is_running(&locmmptr->tt)) {
+          mpl_data_trickle_timer_start(locmmptr);
+        }
+        mpl_trickle_timer_inconsistency(locmmptr);
+        r_missing = 1;
+        locmmptr = list_item_next(locmmptr);
+      }
+    }
+    /* Now point to next seed info */
+next:
+    switch(SEED_INFO_GET_S(locsiptr)) {
+    case 0:
+      locsiptr = ((void *)locsiptr) + sizeof(struct seed_info) + SEED_INFO_GET_LEN(locsiptr);
+      break;
+    case 1:
+      locsiptr = ((void *)locsiptr) + sizeof(struct seed_info_s1) + SEED_INFO_GET_LEN(locsiptr);
+      break;
+    case 2:
+      locsiptr = ((void *)locsiptr) + sizeof(struct seed_info_s2) + SEED_INFO_GET_LEN(locsiptr);
+      break;
+    case 3:
+      locsiptr = ((void *)locsiptr) + sizeof(struct seed_info_s3) + SEED_INFO_GET_LEN(locsiptr);
+      break;
+    }
+  }
+
+  /* Now sort out control message timers */
+  if(l_missing && !trickle_timer_is_running(&locdsptr->tt)) {
+    mpl_control_trickle_timer_start(locdsptr);
+  }
+  if(l_missing || r_missing) {
+    LOG_INFO("Inconsistency detected l=%u, r=%u\n", l_missing, r_missing);
+    if(trickle_timer_is_running(&locdsptr->tt)) {
+      mpl_trickle_timer_inconsistency(locdsptr);
+    }
+  } else {
+    LOG_INFO("Domain is consistent \n");
+    trickle_timer_consistency(&locdsptr->tt);
+  }
+
+discard:
+  uip_len = 0;
+  uipbuf_clear();
+  return;
+}
+static uint8_t
+accept(uint8_t in)
+{
+  static seed_id_t seed_id;
+  static uint16_t seq_val;
+  static uint8_t S;
+  static struct mpl_msg *mmiterptr;
+  static struct uip_ext_hdr *hptr;
+
+  LOG_INFO("Multicast I/O\n");
+
+#if UIP_CONF_IPV6_CHECKS
+  if(uip_is_addr_mcast_non_routable(&UIP_IP_BUF->destipaddr)) {
+    LOG_ERR("Mcast I/O, bad destination\n");
+    UIP_MCAST6_STATS_ADD(mcast_bad);
+    return UIP_MCAST6_DROP;
+  }
+  /*
+   * Abort transmission if the v6 src is unspecified. This may happen if the
+   * seed tries to TX while it's still performing DAD or waiting for a prefix
+   */
+  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
+    LOG_ERR("Mcast I/O, bad source\n");
+    UIP_MCAST6_STATS_ADD(mcast_bad);
+    return UIP_MCAST6_DROP;
+  }
+#endif
+
+  if(uip_ds6_is_my_addr(&UIP_IP_BUF->srcipaddr) && in == MPL_DGRAM_IN) {
+    LOG_WARN("Received message from ourselves.\n");
+    return UIP_MCAST6_DROP;
+  }
+
+  /* Check the Next Header field: Must be HBHO */
+  if(UIP_IP_BUF->proto != UIP_PROTO_HBHO) {
+    LOG_ERR("Mcast I/O, bad proto\n");
+    LOG_DBG("Next Proto was %u\n", UIP_IP_BUF->proto);
+    UIP_MCAST6_STATS_ADD(mcast_bad);
+    return UIP_MCAST6_DROP;
+  } else {
+    /* Check the Option Type */
+    if(UIP_EXT_OPT_FIRST->type != HBHO_OPT_TYPE_MPL) {
+      LOG_ERR("Mcast I/O, bad HBHO type\n");
+      UIP_MCAST6_STATS_ADD(mcast_bad);
+      return UIP_MCAST6_DROP;
+    }
+  }
+  lochbhmptr = UIP_EXT_OPT_FIRST;
+
+  LOG_DBG("HBHO T=%u, L=%u, M=%u, V=%u, S=%u, SEQ=0x%x\n",
+          lochbhmptr->type, lochbhmptr->len, HBH_GET_M(lochbhmptr),
+          HBH_GET_V(lochbhmptr), HBH_GET_S(lochbhmptr),
+          lochbhmptr->seq);
+
+#if UIP_MCAST6_STATS
+  if(in == MPL_DGRAM_IN) {
+    UIP_MCAST6_STATS_ADD(mcast_in_all);
+  }
+#endif
+  /* Do a check on the V bit */
+  if(HBH_GET_V(lochbhmptr)) {
+    /* The V bit MUST be zero otherwise we drop the message */
+    LOG_ERR("Invalid V bit - dropping...\n");
+    return UIP_MCAST6_DROP;
+  }
+  /* Is this for a known seed and domain? */
+  S = HBH_GET_S(lochbhmptr);
+  LOG_DBG("Incoming message S value = %u\n", S);
+
+  if(S == 0) {
+    /* Seed ID is the IPV6 Source Address */
+    seed_id_net_to_host(&seed_id, &UIP_IP_BUF->srcipaddr, S);
+  } else {
+    /**
+     * Seed ID is embedded in the header where padding would otherwise be.
+     * Since we're only interested in the address the specific s1/s2/s3
+     * type doesn't matter.
+     */
+    seed_id_net_to_host(&seed_id, &((struct mpl_hbho_s1 *)lochbhmptr)->seed_id, S);
+  }
+
+  LOG_DBG("MPL Domain is ");
+  LOG_DBG_6ADDR(&UIP_IP_BUF->destipaddr);
+  LOG_DBG_("\n");
+
+  /* First check the MPL Domain */
+  locdsptr = domain_set_lookup(&UIP_IP_BUF->destipaddr);
+
+  if(!locdsptr) {
+    locdsptr = domain_set_allocate(&UIP_IP_BUF->destipaddr);
+    LOG_INFO("New MPL Domain ");
+    LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
+    LOG_INFO_("\n");
+    if(!locdsptr) {
+      LOG_ERR("Couldn't add to MPL Domain Set. Dropping.\n");
+      UIP_MCAST6_STATS_ADD(mcast_dropped);
+      return UIP_MCAST6_DROP;
+    }
+
+    /* Setup new MPL Domain */
+    if(!trickle_timer_config(&locdsptr->tt,
+                             MPL_CONTROL_MESSAGE_IMIN,
+                             MPL_CONTROL_MESSAGE_IMAX,
+                             MPL_CONTROL_MESSAGE_K)) {
+      LOG_ERR("Unable to configure trickle timer for domain. Dropping,...\n");
+      domain_set_free(locdsptr);
+      return UIP_MCAST6_DROP;
+    }
+  }
+
+  /* Now lookup this seed */
+  locssptr = seed_set_lookup(&seed_id, locdsptr);
+
+  seq_val = lochbhmptr->seq;
+
+  if(locssptr) {
+    if(SEQ_VAL_IS_LT(seq_val, locssptr->min_seqno)) {
+      /* Too old, drop */
+      LOG_INFO("Too old\n");
+      UIP_MCAST6_STATS_ADD(mcast_dropped);
+      return UIP_MCAST6_DROP;
+    }
+    if(list_head(locssptr->min_seq) != NULL) {
+      for(locmmptr = list_head(locssptr->min_seq); locmmptr != NULL; locmmptr = list_item_next(locmmptr)) {
+        if(SEQ_VAL_IS_EQ(seq_val, locmmptr->seq)) {
+          /* Seen before , drop */
+          LOG_INFO("Seen before\n");
+          if(HBH_GET_M(lochbhmptr) && list_item_next(locmmptr) != NULL) {
+            mpl_trickle_timer_inconsistency(locmmptr);
+          } else {
+            trickle_timer_consistency(&locmmptr->tt);
+          }
+          UIP_MCAST6_STATS_ADD(mcast_dropped);
+          return UIP_MCAST6_DROP;
+        }
+      }
+    }
+  }
+  /* We have not seen this message before */
+
+  /* Allocate a seed set if we have to */
+  if(!locssptr) {
+    locssptr = seed_set_allocate();
+    LOG_INFO("New seed\n");
+    if(!locssptr) {
+      /* Couldn't allocate seed set, drop */
+      LOG_ERR("Failed to allocate seed set\n");
+      UIP_MCAST6_STATS_ADD(mcast_dropped);
+      return UIP_MCAST6_DROP;
+    }
+    memset(locssptr, 0, sizeof(struct mpl_seed));
+    LIST_STRUCT_INIT(locssptr, min_seq);
+    seed_id_cpy(&locssptr->seed_id, &seed_id);
+    locssptr->domain = locdsptr;
+  }
+
+  /* Allocate a buffer */
+  locmmptr = buffer_allocate();
+  if(!locmmptr) {
+    LOG_INFO("Buffer allocation failed. Reclaiming...\n");
+    locmmptr = buffer_reclaim();
+    if(!locmmptr) {
+      LOG_ERR("Buffer reclaim failed. Dropping...\n");
+      UIP_MCAST6_STATS_ADD(mcast_dropped);
+      return UIP_MCAST6_DROP;
+    }
+  }
+
+  /* We have a domain set, a seed set, and we have a buffer. Accept this message */
+  LOG_INFO("Message from seed ");
+  LOG_INFO_SEED(locssptr->seed_id);
+  LOG_INFO_("\n");
+
+  /* Set the source IP of the message */
+  uip_ip6addr_copy(&locmmptr->srcipaddr, &UIP_IP_BUF->srcipaddr);
+
+#if UIP_MCAST6_STATS
+  if(in == MPL_DGRAM_IN) {
+    UIP_MCAST6_STATS_ADD(mcast_in_unique);
+  }
+#endif
+
+  /* Find the start of the payload */
+  hptr = (struct uip_ext_hdr *)UIP_EXT_BUF;
+  while(hptr->next != UIP_PROTO_UDP) {
+    hptr = ((void *)hptr) + hptr->len * 8 + 8;
+  }
+  hptr = ((void *)hptr) + hptr->len * 8 + 8;
+  locmmptr->size = uip_len - UIP_IPH_LEN - uip_ext_len;
+  memcpy(&locmmptr->data, hptr, locmmptr->size);
+  locmmptr->seq = seq_val;
+  locmmptr->seed = locssptr;
+  if(!trickle_timer_config(&locmmptr->tt,
+                           MPL_DATA_MESSAGE_IMIN,
+                           MPL_DATA_MESSAGE_IMAX,
+                           MPL_DATA_MESSAGE_K)) {
+    LOG_ERR("Failed to configure timer for message. Dropping...\n");
+    buffer_free(locmmptr);
+    return UIP_MCAST6_DROP;
+  }
+
+  /* Place the message into the buffered message linked list */
+  if(list_head(locssptr->min_seq) == NULL) {
+    list_push(locssptr->min_seq, locmmptr);
+    locssptr->min_seqno = locmmptr->seq;
+  } else {
+    for(mmiterptr = list_head(locssptr->min_seq); mmiterptr != NULL; mmiterptr = list_item_next(mmiterptr)) {
+      if(list_item_next(mmiterptr) == NULL
+         || (SEQ_VAL_IS_GT(locmmptr->seq, mmiterptr->seq) && SEQ_VAL_IS_LT(locmmptr->seq, ((struct mpl_msg *)list_item_next(mmiterptr))->seq))) {
+        list_insert(locssptr->min_seq, mmiterptr, locmmptr);
+        break;
+      }
+    }
+  }
+  locssptr->count++;
+
+#if MPL_PROACTIVE_FORWARDING
+  /* Start Forwarding the message */
+  mpl_data_trickle_timer_start(locmmptr);
+#endif
+
+  LOG_INFO("Min Seq Number=%u, %u values\n", locssptr->min_seqno, locssptr->count);
+  locssptr->lifetime = MPL_SEED_SET_ENTRY_LIFETIME;
+
+  /* Start the control message timer if needed */
+#if MPL_CONTROL_MESSAGE_TIMER_EXPIRATIONS > 0
+  if(!trickle_timer_is_running(&locdsptr->tt)) {
+    mpl_control_trickle_timer_start(locdsptr);
+  } else {
+    mpl_trickle_timer_reset(locdsptr);
+  }
+#endif
+
+  /**
+   * Check for inconsistency
+   * MPL Defines an inconsistent packet as "receiving
+   *  an MPL Data Message that has the same MPL Domain Address, seed-id
+   *  value, and the M flag set, but has a sequence value less than that
+   *  of the MPL Data Message managed by the Trickle timer."
+   * We have already satisfied the domain address and seed-id conditions,
+   *  now check the rest.
+   */
+#if MPL_PROACTIVE_FORWARDING
+  if(HBH_GET_M(lochbhmptr) == 1 && list_item_next(locmmptr) != NULL) {
+    LOG_DBG("MPL Domain is inconsistent\n");
+    mpl_trickle_timer_inconsistency(locmmptr);
+  } else {
+    LOG_DBG("MPL Domain is consistent\n");
+    trickle_timer_consistency(&locmmptr->tt);
+  }
+#endif
+
+  /* Deliver if necessary */
+  return UIP_MCAST6_ACCEPT;
+}
+static void
+out(void)
+{
+  /* Check we know our seed ID */
+  if(local_seed_id.s == MPL_SEED_ID_UNKNOWN) {
+    update_seed_id();
+    if(local_seed_id.s == MPL_SEED_ID_UNKNOWN) {
+      LOG_ERR("Our seed ID is not yet known.\n");
+      goto drop;
+    }
+  }
+
+  /* Check we have enough space for the options header */
+  if(uip_len + HBHO_TOTAL_LEN > UIP_BUFSIZE) {
+    LOG_ERR("Multicast Out can not add HBHO. Packet too long\n");
+    goto drop;
+  }
+
+  /* Slide 'right' by HBHO_TOTAL_LEN bytes */
+  memmove(UIP_EXT_BUF_NEXT, UIP_EXT_BUF, uip_len - UIP_IPH_LEN);
+  memset(UIP_EXT_BUF, 0, HBHO_TOTAL_LEN);
+
+  /* Insert the option header into the packet and set it's length */
+  /* This depends entirely on our seed ID size */
+  UIP_EXT_BUF->next = UIP_IP_BUF->proto;
+#if MPL_SEED_ID_TYPE == 0
+  UIP_EXT_BUF->len = HBHO_S0_LEN / 8;
+#elif MPL_SEED_ID_TYPE == 1
+  UIP_EXT_BUF->len = HBHO_S1_LEN / 8;
+#elif MPL_SEED_ID_TYPE == 2
+  UIP_EXT_BUF->len = HBHO_S2_LEN / 8;
+#elif MPL_SEED_ID_TYPE == 3
+  UIP_EXT_BUF->len = HBHO_S3_LEN / 8;
+#endif
+
+  /* Get a reference to the HBHO and set the type */
+  lochbhmptr = UIP_EXT_OPT_FIRST;
+  lochbhmptr->type = HBHO_OPT_TYPE_MPL;
+  lochbhmptr->flags = 0x00;
+  HBH_CLR_S(lochbhmptr);
+  HBH_SET_S(lochbhmptr, MPL_SEED_ID_TYPE);
+  HBH_CLR_V(lochbhmptr);
+#if MPL_SEED_ID_TYPE == 0
+  lochbhmptr->len = MPL_OPT_LEN_S0;
+  /* In this case the Seed ID is our IPV6 address */
+  lochbhmptr->padn.opt_type = UIP_EXT_HDR_OPT_PADN;
+  lochbhmptr->padn.opt_type = 0x00;
+#elif MPL_SEED_ID_TYPE == 1
+  lochbhmptr->len = MPL_OPT_LEN_S1;
+  seed_id_host_to_net(&((struct mpl_hbho_s1 *)lochbhmptr)->seed_id, &local_seed_id);
+#elif MPL_SEED_ID_TYPE == 2
+  lochbhmptr->len = MPL_OPT_LEN_S2;
+  seed_id_host_to_net(&((struct mpl_hbho_s2 *)lochbhmptr)->seed_id, &local_seed_id);
+  ((struct mpl_hbho_s2 *)lochbhmptr)->padn.opt_type = UIP_EXT_HDR_OPT_PADN;
+  ((struct mpl_hbho_s2 *)lochbhmptr)->padn.opt_len = 0x00;
+#elif MPL_SEED_ID_TYPE == 3
+  lochbhmptr->len = MPL_OPT_LEN_S3;
+  seed_id_host_to_net(&((struct mpl_hbho_s3 *)lochbhmptr)->seed_id, &local_seed_id);
+  ((struct mpl_hbho_s3 *)lochbhmptr)->padn.opt_type = UIP_EXT_HDR_OPT_PADN;
+  ((struct mpl_hbho_s3 *)lochbhmptr)->padn.opt_len = 0x00;
+#endif
+
+  /* Set the sequence ID */
+  last_seq = SEQ_VAL_ADD(last_seq, 1);
+  lochbhmptr->seq = last_seq;
+  HBH_SET_M(lochbhmptr);
+
+  uip_ext_len += HBHO_TOTAL_LEN;
+  uip_len += HBHO_TOTAL_LEN;
+
+  /* Update the proto and length field in the v6 header */
+  UIP_IP_BUF->proto = UIP_PROTO_HBHO;
+  UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
+  UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
+
+  LOG_INFO("Multicast Out\n");
+  LOG_DBG("HBHO: Next Header=0x%x, Header Len (exc. 1st 8 bytes)=%u\n",
+          UIP_EXT_BUF->next, UIP_EXT_BUF->len);
+  LOG_DBG("MPL Option Type 0x%x: Len=%u, S=%u, M=%u, V=%u, Seq=0x%x\n",
+          lochbhmptr->type, lochbhmptr->len, HBH_GET_S(lochbhmptr),
+          HBH_GET_M(lochbhmptr), HBH_GET_V(lochbhmptr), lochbhmptr->seq);
+
+  /*
+   * We need to remember this message and advertise it in subsequent ICMP
+   * messages. Otherwise, our neighs will think we are inconsistent and will
+   * bounce it back to us.
+   *
+   * Queue this message but don't set its MUST_SEND flag. We reset the trickle
+   * timer and we send it immediately. We then set uip_len = 0 to stop the core
+   * from re-sending it.
+   */
+  if(accept(MPL_DGRAM_OUT)) {
+    tcpip_output(NULL);
+    UIP_MCAST6_STATS_ADD(mcast_out);
+  }
+
+drop:
+  uip_slen = 0;
+  uipbuf_clear();
+}
+static uint8_t
+in(void)
+{
+  if(!uip_ds6_is_my_maddr(&UIP_IP_BUF->destipaddr)) {
+    LOG_INFO("Not in our domain. No further processing\n");
+    return UIP_MCAST6_DROP;
+  }
+  /*
+   * We call accept() which will sort out caching and forwarding. Depending
+   * on accept()'s return value, we then need to signal the core
+   * whether to deliver this to higher layers
+   */
+  if(accept(MPL_DGRAM_IN) == UIP_MCAST6_DROP) {
+    LOG_INFO("Packet dropped\n");
+    return UIP_MCAST6_DROP;
+  } else {
+    LOG_INFO("Ours. Deliver to upper layers\n");
+    UIP_MCAST6_STATS_ADD(mcast_in_ours);
+    return UIP_MCAST6_ACCEPT;
+  }
+}
+static void
+init(void)
+{
+  LOG_INFO("Multicast Protocol for Low Power and Lossy Networks - RFC7731\n");
+
+  /* Clear out all sets */
+  memset(domain_set, 0, sizeof(struct mpl_domain) * MPL_DOMAIN_SET_SIZE);
+  memset(seed_set, 0, sizeof(struct mpl_seed) * MPL_SEED_SET_SIZE);
+  memset(buffered_message_set, 0, sizeof(struct mpl_msg) * MPL_BUFFERED_MESSAGE_SET_SIZE);
+
+  /* Register the ICMPv6 input handler */
+  uip_icmp6_register_input_handler(&mpl_icmp_handler);
+
+  update_seed_id();
+
+  /* Init MPL Stats */
+  MPL_STATS_INIT();
+
+#if MPL_SUB_TO_ALL_FORWARDERS
+  /* Subscribe to the All MPL Forwarders Address by default */
+  ALL_MPL_FORWARDERS(&all_forwarders, UIP_MCAST6_SCOPE_REALM_LOCAL);
+  if(!uip_ds6_maddr_add(&all_forwarders)) {
+    LOG_ERR("Failed to subscribe to All Forwarders MPL Address\n");
+  }
+#endif
+  mpl_maddr_check();
+
+  /* Setup Minute lifetime timer */
+  ctimer_set(&lifetime_timer, CLOCK_SECOND * 60, lifetime_timer_expiration, NULL);
+}
+/*---------------------------------------------------------------------------*/
+/**
+ * \brief The MPL engine driver
+ */
+const struct uip_mcast6_driver mpl_driver = {
+  "MPL",
+  init,
+  out,
+  in
+};
+/*---------------------------------------------------------------------------*/
+/** @} */
diff --git a/os/net/ipv6/multicast/mpl.h b/os/net/ipv6/multicast/mpl.h
new file mode 100644
index 0000000000000000000000000000000000000000..41cfc1f0235ae86de4d95ff4ea9193c5178acd8d
--- /dev/null
+++ b/os/net/ipv6/multicast/mpl.h
@@ -0,0 +1,297 @@
+/*
+ * Copyright (c) 2018, University of Bristol - http://www.bristol.ac.uk/
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ */
+
+/**
+ * \addtogroup uip-multicast
+ * @{
+ */
+/**
+ * \defgroup mpl Multicast Protocol for Low Power and Lossy Networks
+ *
+ * IPv6 multicast according to the algorithm in RFC7731
+ *
+ * The current version of the specification can be found in
+ * https://tools.ietf.org/html/rfc7731
+ *
+ * @{
+ */
+/**
+ * \file
+ *    Header file for the implementation of the MPL protocol
+ * \author
+ *    Ed Rose - <er15406@bris.ac.uk>
+ */
+
+#ifndef MPL_H
+#define MPL_H
+#include "contiki.h"
+#include "net/ipv6/uip.h"
+#include "net/ipv6/multicast/uip-mcast6-stats.h"
+
+/*---------------------------------------------------------------------------*/
+/* Protocol Constants */
+/*---------------------------------------------------------------------------*/
+#define ALL_MPL_FORWARDERS(a, r)   uip_ip6addr(a, 0xFF00 + r,0x00,0x00,0x00,0x00,0x00,0x00,0xFC)
+#define HBHO_OPT_TYPE_MPL          0x6D
+#define MPL_IP_HOP_LIMIT           0xFF   /**< Hop limit for ICMP messages */
+#define HBHO_BASE_LEN              8
+#define HBHO_S0_LEN                0
+#define HBHO_S1_LEN                0
+#define HBHO_S2_LEN                8
+#define HBHO_S3_LEN                16
+#define MPL_OPT_LEN_S0             2
+#define MPL_OPT_LEN_S1             4
+#define MPL_OPT_LEN_S2             10
+#define MPL_OPT_LEN_S3             18
+#define MPL_DGRAM_OUT              0
+#define MPL_DGRAM_IN               1
+
+/* Trickle timer configuration */
+#ifndef MPL_CONF_DATA_MESSAGE_IMIN
+#define MPL_DATA_MESSAGE_IMIN               32
+#else
+#define MPL_DATA_MESSAGE_IMIN MPL_CONF_DATA_MESSAGE_IMIN
+#endif
+
+#ifndef MPL_CONF_DATA_MESSAGE_IMAX
+#define MPL_DATA_MESSAGE_IMAX               MPL_CONTROL_MESSAGE_IMIN
+#else
+#define MPL_DATA_MESSAGE_IMAX MPL_CONF_DATA_MESSAGE_IMAX
+#endif
+
+#ifndef MPL_CONF_DATA_MESSAGE_K
+#define MPL_DATA_MESSAGE_K                  1
+#else
+#define MPL_CONF_DATA_MESSAGE_K MPL_DATA_MESSAGE_K
+#endif
+
+#ifndef MPL_CONF_CONTROL_MESSAGE_IMIN
+#define MPL_CONTROL_MESSAGE_IMIN            32
+#else
+#define MPL_CONTROL_MESSAGE_IMIN MPL_CONF_CONTROL_MESSAGE_IMIN
+#endif
+
+#ifndef MPL_CONF_CONTROL_MESSAGE_IMAX
+#define MPL_CONTROL_MESSAGE_IMAX            32
+#else
+#define MPL_CONTROL_MESSAGE_IMAX MPL_CONF_CONTROL_MESSAGE_IMAX
+#endif
+
+#ifndef MPL_CONF_CONTROL_MESSAGE_K
+#define MPL_CONTROL_MESSAGE_K               1
+#else
+#define MPL_CONTROL_MESSAGE_K MPL_CONF_CONTROL_MESSAGE_K
+#endif
+
+/*---------------------------------------------------------------------------*/
+/* Protocol Configuration */
+/*---------------------------------------------------------------------------*/
+/**
+ * Seed ID Length
+ * The MPL Protocol requires that each seed is identified by an ID that is
+ * unique to the MPL domain. The Seed ID can be either a 16 bit, 64 bit,
+ * or 128 bit unsigned integer. It it's an 128 bit unsigned integer then the
+ * IPv6 address may be used. The format of the Seed ID is set in the
+ * three-bit 'S' field in MPL header options, and the value below mirrors this.
+ * 0 - The seed id will be the IPv6 address of this device. The values of
+ *      MPL_CONF_SEED_ID_L and MPL_CONF_SEED_ID_H are ignored.
+ * 1 - The seed id will be a 16 bit unsigned integer defined
+ *      in MPL_CONF_SEED_ID_L
+ * 2 - The seed id will be a 64 bit unsigned integer defined in
+ *      in MPL_CONF_SEED_ID_L
+ * 3 - The seed id will be an 128 bit unsigned integer defined in both
+ *      MPL_CONF_SEED_ID_L and MPL_CONF_SEED_ID_H
+ */
+#ifndef MPL_CONF_SEED_ID_TYPE
+#define MPL_SEED_ID_TYPE                    0
+#else
+#define MPL_SEED_ID_TYPE MPL_CONF_SEED_ID_TYPE
+#endif
+/*---------------------------------------------------------------------------*/
+/**
+ * Seed ID Alias
+ * Points to MPL_CONF_SEED_ID_L
+ */
+#ifdef MPL_CONF_SEED_ID
+#define MPL_CONF_SEED_ID_L MPL_CONF_SEED_ID
+#endif
+/*---------------------------------------------------------------------------*/
+/**
+* Seed ID Low Bits
+ * If the Seed ID Length setting is 1 or 2, this setting defines the seed
+ * id for this seed. If the seed id setting is 3, then this defines the lower
+ * 64 bits of the seed id.
+ */
+#ifndef MPL_CONF_SEED_ID_L
+#define MPL_SEED_ID_L                       0x00
+#else
+#define MPL_SEED_ID_L MPL_CONF_SEED_ID_L
+#endif
+/*---------------------------------------------------------------------------*/
+/**
+* Seed ID High Bits
+ * If the Seed ID Length setting is 3, this setting defines the upper 64 bits
+ * for the seed id. Else it's ignored.
+ */
+#ifndef MPL_CONF_SEED_ID_H
+#define MPL_SEED_ID_H                       0x00
+#else
+#define MPL_SEED_ID_H MPL_CONF_SEED_ID_H
+#endif
+/*---------------------------------------------------------------------------*/
+/**
+ * Subscribe to All MPL Forwarders
+ *  By default, an MPL forwarder will subscribe to the ALL_MPL_FORWARDERS
+ *  address with realm-local scope: FF03::FC. This behaviour can be disabled
+ *  using the macro below.
+ */
+#ifndef MPL_CONF_SUB_TO_ALL_FORWARDERS
+#define MPL_SUB_TO_ALL_FORWARDERS           1
+#else
+#define MPL_SUB_TO_ALL_FORWARDERS MPL_CONF_SUB_TO_ALL_FORWARDERS
+#endif
+/*---------------------------------------------------------------------------*/
+/**
+ * Domain Set Size
+ * MPL Forwarders maintain a Domain Set which maps MPL domains to trickle
+ * timers. The size of this should reflect the number of MPL domains this
+ * forwarder is participating in.
+ */
+#ifndef MPL_CONF_DOMAIN_SET_SIZE
+#define MPL_DOMAIN_SET_SIZE                 1
+#else
+#define MPL_DOMAIN_SET_SIZE MPL_CONF_DOMAIN_SET_SIZE
+#endif
+/*---------------------------------------------------------------------------*/
+/**
+ * Seed Set Size
+ * MPL Forwarders maintain a Seed Set to keep track of the MPL messages that a
+ * particular seed has sent recently. Seeds remain on the Seed Set for the
+ * time specified in the Seed Set Entry Lifetime setting.
+ */
+#ifndef MPL_CONF_SEED_SET_SIZE
+#define MPL_SEED_SET_SIZE                   2
+#else
+#define MPL_SEED_SET_SIZE MPL_CONF_SEED_SET_SIZE
+#endif
+/*---------------------------------------------------------------------------*/
+/**
+ * Buffered Message Set Size
+ * MPL Forwarders maintain a buffer of data messages that are periodically
+ * forwarded around the MPL domain. These are forwarded when trickle timers
+ * expire, and remain in the buffer for the number of timer expirations
+ * set in Data Message Timer Expirations.
+ */
+#ifndef MPL_CONF_BUFFERED_MESSAGE_SET_SIZE
+#define MPL_BUFFERED_MESSAGE_SET_SIZE       6
+#else
+#define MPL_BUFFERED_MESSAGE_SET_SIZE MPL_CONF_BUFFERED_MESSAGE_SET_SIZE
+#endif
+/*---------------------------------------------------------------------------*/
+/**
+ * MPL Forwarding Strategy
+ * Two forwarding strategies are defined for MPL. With Proactive forwarding
+ * enabled, the forwarder will schedule transmissions of new messages
+ * before any control messages are received to indicate that neighbouring nodes
+ * have yet to receive the messages. With Reactive forwarding enabled, MPL
+ * forwarders will only schedule transmissions of new MPL messages once control
+ * messages have been received indicating that they are missing those messages.
+ * 1 - Indicates that proactive forwarding be enabled
+ * 0 - Indicates that proactive forwarding be disabled
+ */
+#ifndef MPL_CONF_PROACTIVE_FORWARDING
+#define MPL_PROACTIVE_FORWARDING            0
+#else
+#define MPL_PROACTIVE_FORWARDING MPL_CONF_PROACTIVE_FORWARDING
+#endif
+/*---------------------------------------------------------------------------*/
+/**
+ * Seed Set Entry Lifetime
+ * MPL Seed set entries remain in the seed set for a set period of time after
+ * the last message that was received by that seed. This is called the
+ * lifetime of the seed, and is defined in minutes.
+ */
+#ifndef MPL_CONF_SEED_SET_ENTRY_LIFETIME
+#define MPL_SEED_SET_ENTRY_LIFETIME         30
+#else
+#define MPL_SEED_SET_ENTRY_LIFETIME MPL_CONF_SEED_SET_ENTRY_LIFETIME
+#endif
+/*---------------------------------------------------------------------------*/
+/**
+ * Data Message Timer Expirations
+ * MPL data message trickle timers are stopped after they expire a set number
+ * of times. The number of times they expire before being stopped is set below.
+ */
+#ifndef MPL_CONF_DATA_MESSAGE_TIMER_EXPIRATIONS
+#define MPL_DATA_MESSAGE_TIMER_EXPIRATIONS  5
+#else
+#define MPL_DATA_MESSAGE_TIMER_EXPIRATIONS MPL_CONF_DATA_MESSAGE_TIMER_EXPIRATIONS
+#endif
+/*---------------------------------------------------------------------------*/
+/**
+ * Control Message Timer Expirations
+ * An MPL Forwarder forwards MPL messages for a particular domain using a
+ * trickle timer which is mapped using the Domain Set. MPL domains remain in
+ * the Domain Set for the number of timer expirations below. New messages on
+ * that domain cause the expirations counter to reset.
+ */
+#ifndef MPL_CONF_CONTROL_MESSAGE_TIMER_EXPIRATIONS
+#define MPL_CONTROL_MESSAGE_TIMER_EXPIRATIONS 10
+#else
+#define MPL_CONTROL_MESSAGE_TIMER_EXPIRATIONS MPL_CONF_CONTROL_MESSAGE_TIMER_EXPIRATIONS
+#endif
+/*---------------------------------------------------------------------------*/
+/* Misc System Config */
+/*---------------------------------------------------------------------------*/
+
+/* Configure the correct number of multicast addresses for MPL */
+#define UIP_CONF_DS6_MADDR_NBU MPL_DOMAIN_SET_SIZE * 2
+
+/*---------------------------------------------------------------------------*/
+/* Stats datatype */
+/*---------------------------------------------------------------------------*/
+/**
+ * \brief Multicast stats extension for the MPL engine
+ */
+struct mpl_stats {
+  /** Number of received ICMP datagrams */
+  UIP_MCAST6_STATS_DATATYPE icmp_in;
+
+  /** Number of ICMP datagrams sent */
+  UIP_MCAST6_STATS_DATATYPE icmp_out;
+
+  /** Number of malformed ICMP datagrams seen by us */
+  UIP_MCAST6_STATS_DATATYPE icmp_bad;
+};
+#endif
+/*---------------------------------------------------------------------------*/
+/** @} */
+/** @} */
\ No newline at end of file
diff --git a/os/net/ipv6/multicast/roll-tm.c b/os/net/ipv6/multicast/roll-tm.c
index 1d19512d6c4af7d428e0278a4a108678277df686..909ebbfb61d55ddec1cdc577ac063baa2cd04964 100644
--- a/os/net/ipv6/multicast/roll-tm.c
+++ b/os/net/ipv6/multicast/roll-tm.c
@@ -276,7 +276,7 @@ struct mcast_packet {
   uint16_t seq_val;             /* host-byte order */
   struct sliding_window *sw;    /* Pointer to the SW this packet belongs to */
   uint8_t flags;                /* Is-Used, Must Send, Is Listed */
-  uint8_t buff[UIP_BUFSIZE - UIP_LLH_LEN];
+  uint8_t buff[UIP_BUFSIZE];
 };
 
 /* Flag bits */
@@ -289,7 +289,7 @@ struct mcast_packet {
 #define MCAST_PACKET_GET_SEED(p) ((seed_id_t *)&((p)->seed_id))
 #else
 #define MCAST_PACKET_GET_SEED(p) \
-    ((seed_id_t *)&((struct uip_ip_hdr *)&(p)->buff[UIP_LLH_LEN])->srcipaddr)
+    ((seed_id_t *)&((struct uip_ip_hdr *)&(p)->buff[0])->srcipaddr)
 #endif
 
 /**
@@ -456,14 +456,9 @@ static uint16_t last_seq;
 /*---------------------------------------------------------------------------*/
 /* uIPv6 Pointers */
 /*---------------------------------------------------------------------------*/
-#define UIP_DATA_BUF      ((uint8_t *)&uip_buf[uip_l2_l3_hdr_len + UIP_UDPH_LEN])
-#define UIP_UDP_BUF       ((struct uip_udp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_EXT_BUF       ((struct uip_ext_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN])
-#define UIP_EXT_BUF_NEXT  ((uint8_t *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN + HBHO_TOTAL_LEN])
-#define UIP_EXT_OPT_FIRST ((struct hbho_mcast *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN + 2])
-#define UIP_IP_BUF        ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-#define UIP_ICMP_BUF      ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_ICMP_PAYLOAD  ((unsigned char *)&uip_buf[uip_l2_l3_icmp_hdr_len])
+#define UIP_EXT_BUF        ((struct uip_ext_hdr *)UIP_IP_PAYLOAD(0))
+#define UIP_EXT_BUF_NEXT            ((uint8_t *)(UIP_IP_PAYLOAD(HBHO_TOTAL_LEN)))
+#define UIP_EXT_OPT_FIRST ((struct hbho_mcast *)(UIP_IP_PAYLOAD(0) + 2))
 extern uint16_t uip_slen;
 /*---------------------------------------------------------------------------*/
 /* Local function prototypes */
@@ -864,8 +859,7 @@ icmp_output()
   roll_tm_create_dest(&UIP_IP_BUF->destipaddr);
   uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
 
-  UIP_IP_BUF->len[0] = (UIP_ICMPH_LEN + payload_len) >> 8;
-  UIP_IP_BUF->len[1] = (UIP_ICMPH_LEN + payload_len) & 0xff;
+  uipbuf_set_len_field(UIP_IP_BUF, UIP_ICMPH_LEN + payload_len);
 
   UIP_ICMP_BUF->type = ICMP6_ROLL_TM;
   UIP_ICMP_BUF->icode = ROLL_TM_ICMP_CODE;
@@ -1153,10 +1147,10 @@ icmp_input()
   VERBOSE_PRINTF("ROLL TM: ICMPv6 In, parse from %p to %p\n",
                  UIP_ICMP_PAYLOAD,
                  (uint8_t *)UIP_ICMP_PAYLOAD + uip_len -
-                 uip_l2_l3_icmp_hdr_len);
+                 uip_l3_icmp_hdr_len);
   while(locslhptr <
         (struct sequence_list_header *)((uint8_t *)UIP_ICMP_PAYLOAD +
-                                        uip_len - uip_l2_l3_icmp_hdr_len)) {
+                                        uip_len - uip_l3_icmp_hdr_len)) {
     VERBOSE_PRINTF("ROLL TM: ICMPv6 In, seq hdr @ %p\n", locslhptr);
 
     if((locslhptr->flags & SEQUENCE_LIST_RES) != 0) {
@@ -1321,7 +1315,7 @@ static void
 out()
 {
 
-  if(uip_len + HBHO_TOTAL_LEN > UIP_BUFSIZE - UIP_LLH_LEN) {
+  if(uip_len + HBHO_TOTAL_LEN > UIP_BUFSIZE) {
     PRINTF("ROLL TM: Multicast Out can not add HBHO. Packet too long\n");
     goto drop;
   }
@@ -1355,13 +1349,11 @@ out()
   HBH_SET_M(lochbhmptr);
 #endif
 
-  uip_ext_len += HBHO_TOTAL_LEN;
-  uip_len += HBHO_TOTAL_LEN;
+  uipbuf_add_ext_hdr(HBHO_TOTAL_LEN);
 
   /* Update the proto and length field in the v6 header */
   UIP_IP_BUF->proto = UIP_PROTO_HBHO;
-  UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
-  UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
+  uipbuf_set_len_field(UIP_IP_BUF, uip_len - UIP_IPH_LEN);
 
   PRINTF("ROLL TM: Multicast Out, HBHO: T=%u, L=%u, M=%u, S=0x%02x%02x\n",
          lochbhmptr->type, lochbhmptr->len, HBH_GET_M(lochbhmptr),
@@ -1383,7 +1375,7 @@ out()
 
 drop:
   uip_slen = 0;
-  uip_clear_buf();
+  uipbuf_clear();
 }
 /*---------------------------------------------------------------------------*/
 static uint8_t
diff --git a/os/net/ipv6/multicast/smrf.c b/os/net/ipv6/multicast/smrf.c
index 86a05364833710a68b5c74d8e6d249b159914283..dd24968ba1aeaaa586a14700f0809e35cbba1f56 100644
--- a/os/net/ipv6/multicast/smrf.c
+++ b/os/net/ipv6/multicast/smrf.c
@@ -77,18 +77,14 @@ static uip_buf_t mcast_buf;
 static uint8_t fwd_delay;
 static uint8_t fwd_spread;
 /*---------------------------------------------------------------------------*/
-/* uIPv6 Pointers */
-/*---------------------------------------------------------------------------*/
-#define UIP_IP_BUF        ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-/*---------------------------------------------------------------------------*/
 static void
 mcast_fwd(void *p)
 {
-  memcpy(&uip_buf[UIP_LLH_LEN], &mcast_buf, mcast_len);
+  memcpy(uip_buf, &mcast_buf, mcast_len);
   uip_len = mcast_len;
   UIP_IP_BUF->ttl--;
   tcpip_output(NULL);
-  uip_clear_buf();
+  uipbuf_clear();
 }
 /*---------------------------------------------------------------------------*/
 static uint8_t
@@ -178,7 +174,7 @@ in()
         fwd_delay = fwd_delay * (1 + ((random_rand() >> 11) % fwd_spread));
       }
 
-      memcpy(&mcast_buf, &uip_buf[UIP_LLH_LEN], uip_len);
+      memcpy(&mcast_buf, uip_buf, uip_len);
       mcast_len = uip_len;
       ctimer_set(&mcast_periodic, fwd_delay, mcast_fwd, NULL);
     }
diff --git a/os/net/ipv6/multicast/uip-mcast6-engines.h b/os/net/ipv6/multicast/uip-mcast6-engines.h
index 93e8da40fc086062a8f2a0972eee3d1e779c7ec7..f341577cc374414136870c53f627e1183cd297e3 100644
--- a/os/net/ipv6/multicast/uip-mcast6-engines.h
+++ b/os/net/ipv6/multicast/uip-mcast6-engines.h
@@ -51,6 +51,7 @@
 #define UIP_MCAST6_ENGINE_SMRF        1 /**< The SMRF engine */
 #define UIP_MCAST6_ENGINE_ROLL_TM     2 /**< The ROLL TM engine */
 #define UIP_MCAST6_ENGINE_ESMRF       3 /**< The ESMRF engine */
+#define UIP_MCAST6_ENGINE_MPL         4 /**< The MPL (RFC7731) engine */
 
 #endif /* UIP_MCAST6_ENGINES_H_ */
 /** @} */
diff --git a/os/net/ipv6/multicast/uip-mcast6.h b/os/net/ipv6/multicast/uip-mcast6.h
index 67277828bb4bd746009a4909eb65452dc1f2a582..4c2124b4f1854f3bf85d2180e8625dc2a4cc3a7d 100644
--- a/os/net/ipv6/multicast/uip-mcast6.h
+++ b/os/net/ipv6/multicast/uip-mcast6.h
@@ -65,6 +65,7 @@
 #include "net/ipv6/multicast/smrf.h"
 #include "net/ipv6/multicast/esmrf.h"
 #include "net/ipv6/multicast/roll-tm.h"
+#include "net/ipv6/multicast/mpl.h"
 
 #include <string.h>
 /*---------------------------------------------------------------------------*/
@@ -165,6 +166,10 @@ struct uip_mcast6_driver {
 #define RPL_WITH_MULTICAST     1
 #define UIP_MCAST6             esmrf_driver
 
+#elif UIP_MCAST6_ENGINE == UIP_MCAST6_ENGINE_MPL
+#define RPL_WITH_MULTICAST     0
+#define UIP_MCAST6             mpl_driver
+
 #else
 #error "Multicast Enabled with an Unknown Engine."
 #error "Check the value of UIP_MCAST6_CONF_ENGINE in conf files."
diff --git a/os/net/ipv6/resolv.c b/os/net/ipv6/resolv.c
index 2bcd3983be28053ac639d2b8d605ff4df89ec367..29af2b4cf8c0d4cab01b243e79b9d9391d808c18 100644
--- a/os/net/ipv6/resolv.c
+++ b/os/net/ipv6/resolv.c
@@ -116,8 +116,6 @@ int strcasecmp(const char *s1, const char *s2);
 int strncasecmp(const char *s1, const char *s2, size_t n);
 #endif /* __SDCC */
 
-#define UIP_UDP_BUF ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
-
 /* If RESOLV_CONF_SUPPORTS_MDNS is set, then queries
  * for domain names in the local TLD will use mDNS as
  * described by draft-cheshire-dnsext-multicastdns.
@@ -837,7 +835,7 @@ newdata(void)
         } else {
           uip_udp_packet_sendto(resolv_conn, uip_appdata,
                                 mdns_prep_host_announce_packet(),
-                                &UIP_UDP_BUF->srcipaddr,
+                                &UIP_IP_BUF->srcipaddr,
                                 UIP_UDP_BUF->srcport);
         }
         return;
diff --git a/os/net/ipv6/sicslowpan.c b/os/net/ipv6/sicslowpan.c
index 9e4e3a8b4fcd7413bb545664b1ab7bd191abda75..d61d44bafa3937792d6d4a9a7188b44904857a46 100644
--- a/os/net/ipv6/sicslowpan.c
+++ b/os/net/ipv6/sicslowpan.c
@@ -121,33 +121,11 @@
 #define SICSLOWPAN_UDP_BUF(buf)  ((struct uip_udp_hdr *)&buf[UIP_IPH_LEN])
 #define SICSLOWPAN_IPPAYLOAD_BUF(buf) (&buf[UIP_IPH_LEN])
 
-
-#define UIP_IP_BUF          ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-#define UIP_UDP_BUF(p)          ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN + p])
-#define UIP_TCP_BUF          ((struct uip_tcp_hdr *)&uip_buf[UIP_LLIPH_LEN])
-#define UIP_ICMP_BUF          ((struct uip_icmp_hdr *)&uip_buf[UIP_LLIPH_LEN])
-#define UIP_IPPAYLOAD_BUF(pos)          (&uip_buf[UIP_LLIPH_LEN + pos])
+#define UIP_IPPAYLOAD_BUF_POS(pos)         (&uip_buf[UIP_IPH_LEN + (pos)])
+#define UIP_UDP_BUF_POS(pos)               ((struct uip_udp_hdr *)UIP_IPPAYLOAD_BUF_POS(pos))
 
 /** @} */
 
-
-/** \brief Maximum available size for frame headers,
-           link layer security-related overhead, as well as
-           6LoWPAN payload. */
-#ifdef SICSLOWPAN_CONF_MAC_MAX_PAYLOAD
-#define MAC_MAX_PAYLOAD SICSLOWPAN_CONF_MAC_MAX_PAYLOAD
-#else /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */
-#define MAC_MAX_PAYLOAD (127 - 2)
-#endif /* SICSLOWPAN_CONF_MAC_MAX_PAYLOAD */
-
-/** \brief Maximum size of a frame header. This value is
- * used in case framer returns an error */
-#ifdef SICSLOWPAN_CONF_MAC_MAX_HEADER
-#define MAC_MAX_HEADER SICSLOWPAN_CONF_MAC_MAX_HEADER
-#else /* SICSLOWPAN_CONF_MAC_MAX_HEADER */
-#define MAC_MAX_HEADER 21
-#endif /* SICSLOWPAN_CONF_MAC_MAX_HEADER */
-
 /* set this to zero if not compressing EXT_HDR - for backwards compatibility */
 #ifdef SICSLOWPAN_CONF_COMPRESS_EXT_HDR
 #define COMPRESS_EXT_HDR SICSLOWPAN_CONF_COMPRESS_EXT_HDR
@@ -250,7 +228,7 @@ static uint16_t my_tag;
 #define SICSLOWPAN_FRAGMENT_SIZE SICSLOWPAN_CONF_FRAGMENT_SIZE
 #else
 /* The default fragment size (110 bytes for 127-2 bytes frames) */
-#define SICSLOWPAN_FRAGMENT_SIZE (MAC_MAX_PAYLOAD - 15)
+#define SICSLOWPAN_FRAGMENT_SIZE (127 - 2 - 15)
 #endif
 
 /* Assuming that the worst growth for uncompression is 38 bytes */
@@ -466,9 +444,9 @@ set_packet_attrs(void)
 
   /* assign values to the channel attribute (port or type + code) */
   if(UIP_IP_BUF->proto == UIP_PROTO_UDP) {
-    c = UIP_UDP_BUF(0)->srcport;
-    if(UIP_UDP_BUF(0)->destport < c) {
-      c = UIP_UDP_BUF(0)->destport;
+    c = UIP_UDP_BUF_POS(0)->srcport;
+    if(UIP_UDP_BUF_POS(0)->destport < c) {
+      c = UIP_UDP_BUF_POS(0)->destport;
     }
   } else if(UIP_IP_BUF->proto == UIP_PROTO_TCP) {
     c = UIP_TCP_BUF->srcport;
@@ -919,7 +897,7 @@ compress_hdr_iphc(linkaddr_t *link_destaddr)
       /* Handle the header here! */
       {
         struct uip_ext_hdr *ext_hdr =
-          (struct uip_ext_hdr *) UIP_IPPAYLOAD_BUF(ext_hdr_len);
+          (struct uip_ext_hdr *) UIP_IPPAYLOAD_BUF_POS(ext_hdr_len);
         int len;
         proto = proto == -1 ? SICSLOWPAN_NHC_ETX_HDR_DESTO : proto;
         /* Len is defined to be in octets from the length byte */
@@ -958,7 +936,7 @@ compress_hdr_iphc(linkaddr_t *link_destaddr)
     case UIP_PROTO_UDP:
       /* allocate a byte for the next header posision as UDP has no next */
       hc06_ptr++;
-      udp_buf = UIP_UDP_BUF(ext_hdr_len);
+      udp_buf = UIP_UDP_BUF_POS(ext_hdr_len);
       LOG_DBG("compression: inlined UDP ports on send side: %x, %x\n",
              UIP_HTONS(udp_buf->srcport), UIP_HTONS(udp_buf->destport));
       /* Mask out the last 4 bits can be used as a mask */
@@ -1548,8 +1526,6 @@ fragment_copy_payload_and_send(uint16_t uip_offset, linkaddr_t *dest) {
 static uint8_t
 output(const linkaddr_t *localdest)
 {
-  int framer_hdrlen;
-  int max_payload;
   int frag_needed;
 
   /* The MAC address of the destination of the packet */
@@ -1588,14 +1564,24 @@ output(const linkaddr_t *localdest)
 
 /* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_MAC */
   packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
-  framer_hdrlen = NETSTACK_FRAMER.length();
-  if(framer_hdrlen < 0) {
-   /* Framing failed, we assume the maximum header length */
-   framer_hdrlen = MAC_MAX_HEADER;
+#if LLSEC802154_USES_AUX_HEADER
+  /* copy LLSEC level */
+  packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL,
+    uipbuf_get_attr(UIPBUF_ATTR_LLSEC_LEVEL));
+#if LLSEC802154_USES_EXPLICIT_KEYS
+  packetbuf_set_attr(PACKETBUF_ATTR_KEY_INDEX,
+    uipbuf_get_attr(UIPBUF_ATTR_LLSEC_KEY_ID));
+#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
+#endif /*  LLSEC802154_USES_AUX_HEADER */
+
+  mac_max_payload = NETSTACK_MAC.max_payload();
+
+  if(mac_max_payload <= 0) {
+  /* Framing failed, drop packet */
+    LOG_WARN("output: failed to calculate payload size - dropping packet\n");
+    return 0;
   }
 
-  mac_max_payload = MAC_MAX_PAYLOAD - framer_hdrlen;
-
   /* Try to compress the headers */
 #if SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPV6
   compress_hdr_ipv6(&dest);
@@ -1615,22 +1601,17 @@ output(const linkaddr_t *localdest)
   }
 #endif /* SICSLOWPAN_COMPRESSION >= SICSLOWPAN_COMPRESSION_IPHC */
 
-  /* Calculate NETSTACK_FRAMER's header length, that will be added in the NETSTACK_MAC.
-   * We calculate it here only to make a better decision of whether the outgoing packet
-   * needs to be fragmented or not. */
+  /* Use the mac_max_payload to understand what is the max payload in a MAC
+   * packet. We calculate it here only to make a better decision of whether
+   * the outgoing packet needs to be fragmented or not. */
+
   packetbuf_set_addr(PACKETBUF_ADDR_RECEIVER, &dest);
-  framer_hdrlen = NETSTACK_FRAMER.length();
-  if(framer_hdrlen < 0) {
-    /* Framing failed, we assume the maximum header length */
-    framer_hdrlen = MAC_MAX_HEADER;
-  }
 
-  max_payload = MAC_MAX_PAYLOAD - framer_hdrlen;
-  frag_needed = (int)uip_len - (int)uncomp_hdr_len + (int)packetbuf_hdr_len > max_payload;
+  frag_needed = (int)uip_len - (int)uncomp_hdr_len + (int)packetbuf_hdr_len > mac_max_payload;
   LOG_INFO("output: header len %d -> %d, total len %d -> %d, MAC max payload %d, frag_needed %d\n",
             uncomp_hdr_len, packetbuf_hdr_len,
             uip_len, uip_len - uncomp_hdr_len + packetbuf_hdr_len,
-            max_payload, frag_needed);
+            mac_max_payload, frag_needed);
 
   if(frag_needed) {
 #if SICSLOWPAN_CONF_FRAG
@@ -1650,11 +1631,11 @@ output(const linkaddr_t *localdest)
      /* Total IPv6 payload */
     int total_payload = (uip_len - uncomp_hdr_len);
     /* IPv6 payload that goes to first fragment */
-    int frag1_payload = (max_payload - packetbuf_hdr_len - SICSLOWPAN_FRAG1_HDR_LEN) & 0xfffffff8;
+    int frag1_payload = (mac_max_payload - packetbuf_hdr_len - SICSLOWPAN_FRAG1_HDR_LEN) & 0xfffffff8;
     /* max IPv6 payload in each FRAGN. Must be multiple of 8 bytes */
-    int fragn_max_payload = (max_payload - SICSLOWPAN_FRAGN_HDR_LEN) & 0xfffffff8;
+    int fragn_max_payload = (mac_max_payload - SICSLOWPAN_FRAGN_HDR_LEN) & 0xfffffff8;
     /* max IPv6 payload in the last fragment. Needs not be multiple of 8 bytes */
-    int last_fragn_max_payload = max_payload - SICSLOWPAN_FRAGN_HDR_LEN;
+    int last_fragn_max_payload = mac_max_payload - SICSLOWPAN_FRAGN_HDR_LEN;
     /* sum of all IPv6 payload that goes to non-first and non-last fragments */
     int middle_fragn_total_payload = MAX(total_payload - frag1_payload - last_fragn_max_payload, 0);
     /* Ceiling of: 2 + middle_fragn_total_payload / fragn_max_payload */
@@ -1806,6 +1787,9 @@ input(void)
     return;
   }
 
+  /* Clear uipbuf and set default attributes */
+  uipbuf_clear();
+
   /* This is default uip_buf since we assume that this is not fragmented */
   buffer = (uint8_t *)UIP_IP_BUF;
 
@@ -1840,7 +1824,6 @@ input(void)
       }
 
       buffer = frag_info[frag_context].first_frag;
-
       break;
     case SICSLOWPAN_DISPATCH_FRAGN:
       /*
@@ -1936,12 +1919,12 @@ input(void)
 
   /* Sanity-check size of incoming packet to avoid buffer overflow */
   {
-    int req_size = UIP_LLH_LEN + uncomp_hdr_len + (uint16_t)(frag_offset << 3)
+    int req_size = uncomp_hdr_len + (uint16_t)(frag_offset << 3)
         + packetbuf_payload_len;
     if(req_size > sizeof(uip_buf)) {
       LOG_ERR(
-          "input: packet dropped, minimum required IP_BUF size: %d+%d+%d+%d=%d (current size: %u)\n",
-          UIP_LLH_LEN, uncomp_hdr_len, (uint16_t)(frag_offset << 3),
+          "input: packet dropped, minimum required IP_BUF size: %d+%d+%d=%d (current size: %u)\n",
+          uncomp_hdr_len, (uint16_t)(frag_offset << 3),
           packetbuf_payload_len, req_size, (unsigned)sizeof(uip_buf));
       return;
     }
@@ -2004,6 +1987,19 @@ input(void)
       callback->input_callback();
     }
 
+#if LLSEC802154_USES_AUX_HEADER
+    /*
+     * Assuming that the last packet in packetbuf is containing
+     *  the LLSEC state so that it can be copied to uipbuf.
+     */
+    uipbuf_set_attr(UIPBUF_ATTR_LLSEC_LEVEL,
+      packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL));
+#if LLSEC802154_USES_EXPLICIT_KEYS
+    uipbuf_set_attr(UIPBUF_ATTR_LLSEC_KEY_ID,
+      packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX));
+#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
+#endif /*  LLSEC802154_USES_AUX_HEADER */
+
     tcpip_input();
 #if SICSLOWPAN_CONF_FRAG
   }
@@ -2061,11 +2057,6 @@ sicslowpan_init(void)
 #endif /* SICSLOWPAN_CONF_MAX_ADDR_CONTEXTS > 1 */
 
 #endif /* SICSLOWPAN_COMPRESSION == SICSLOWPAN_COMPRESSION_IPHC */
-
-  /* We use the queuebuf module if fragmentation is enabled */
-#if SICSLOWPAN_CONF_FRAG
-  queuebuf_init();
-#endif
 }
 /*--------------------------------------------------------------------*/
 int
diff --git a/os/net/ipv6/simple-udp.c b/os/net/ipv6/simple-udp.c
index c98107c9973815dc225fecb3843671f1244c92da..08986d827a07c6fe692d15d9351d3ea0b688f5c0 100644
--- a/os/net/ipv6/simple-udp.c
+++ b/os/net/ipv6/simple-udp.c
@@ -52,8 +52,6 @@ PROCESS(simple_udp_process, "Simple UDP process");
 static uint8_t started = 0;
 static uint8_t databuffer[UIP_BUFSIZE];
 
-#define UIP_IP_BUF   ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
-
 /*---------------------------------------------------------------------------*/
 static void
 init_simple_udp(void)
@@ -134,7 +132,7 @@ PROCESS_THREAD(simple_udp_process, ev, data)
 {
   struct simple_udp_connection *c;
   PROCESS_BEGIN();
-  
+
   while(1) {
     PROCESS_WAIT_EVENT();
     if(ev == tcpip_event) {
@@ -165,9 +163,9 @@ PROCESS_THREAD(simple_udp_process, ev, data)
             PROCESS_CONTEXT_BEGIN(c->client_process);
             c->receive_callback(c,
                                 &(UIP_IP_BUF->srcipaddr),
-                                UIP_HTONS(UIP_IP_BUF->srcport),
+                                UIP_HTONS(UIP_UDP_BUF->srcport),
                                 &(UIP_IP_BUF->destipaddr),
-                                UIP_HTONS(UIP_IP_BUF->destport),
+                                UIP_HTONS(UIP_UDP_BUF->destport),
                                 databuffer, uip_datalen());
             PROCESS_CONTEXT_END();
           }
diff --git a/os/net/ipv6/tcpip.c b/os/net/ipv6/tcpip.c
index 8d546c1d7d61538ed5acd593cea2c0aa19f2307d..16176e6e2cba49a0a794803ef45f18af2152e1b6 100644
--- a/os/net/ipv6/tcpip.c
+++ b/os/net/ipv6/tcpip.c
@@ -55,10 +55,6 @@
 #define LOG_MODULE "TCP/IP"
 #define LOG_LEVEL LOG_LEVEL_TCPIP
 
-#define UIP_ICMP_BUF ((struct uip_icmp_hdr *)&uip_buf[UIP_LLIPH_LEN + uip_ext_len])
-#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-#define UIP_TCP_BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
-
 #ifdef UIP_FALLBACK_INTERFACE
 extern struct uip_fallback_interface UIP_FALLBACK_INTERFACE;
 #endif
@@ -129,7 +125,7 @@ tcpip_output(const uip_lladdr_t *a)
     return ret;
   } else {
     /* Ok, ignore and drop... */
-    uip_clear_buf();
+    uipbuf_clear();
     return 0;
   }
 }
@@ -452,18 +448,16 @@ tcpip_input(void)
      NETSTACK_IP_PROCESS) {
     process_post_synch(&tcpip_process, PACKET_INPUT, NULL);
   } /* else - do nothing and drop */
-  uip_clear_buf();
+  uipbuf_clear();
 }
 /*---------------------------------------------------------------------------*/
-extern void remove_ext_hdr(void);
-/*---------------------------------------------------------------------------*/
 static void
 output_fallback(void)
 {
 #ifdef UIP_FALLBACK_INTERFACE
   LOG_INFO("fallback: removing ext hdrs & setting proto %d %d\n",
          uip_ext_len, *((uint8_t *)UIP_IP_BUF + 40));
-  remove_ext_hdr();
+  uip_remove_ext_hdr();
   /* Inform the other end that the destination is not reachable. If it's
    * not informed routes might get lost unexpectedly until there's a need
    * to send a new packet to the peer */
@@ -658,7 +652,7 @@ tcpip_ipv6_output(void)
   if(!NETSTACK_ROUTING.ext_header_update()) {
     /* Packet can not be forwarded */
     LOG_ERR("output: routing protocol extension header update error\n");
-    uip_clear_buf();
+    uipbuf_clear();
     return;
   }
 
@@ -746,7 +740,7 @@ send_packet:
   }
 
 exit:
-  uip_clear_buf();
+  uipbuf_clear();
   return;
 }
 /*---------------------------------------------------------------------------*/
diff --git a/os/net/ipv6/udp-socket.c b/os/net/ipv6/udp-socket.c
index 700306ca13e92634941246cbdfd498e4afd92cf4..f104a6b6c6fd72e43ffcccb584d475b1c27116da 100644
--- a/os/net/ipv6/udp-socket.c
+++ b/os/net/ipv6/udp-socket.c
@@ -38,9 +38,6 @@ PROCESS(udp_socket_process, "UDP socket process");
 
 static uint8_t buf[UIP_BUFSIZE];
 
-#define UIP_IP_BUF   ((struct uip_udpip_hdr *)&uip_buf[UIP_LLH_LEN])
-
-
 /*---------------------------------------------------------------------------*/
 static void
 init(void)
@@ -182,9 +179,9 @@ PROCESS_THREAD(udp_socket_process, ev, data)
             PROCESS_CONTEXT_BEGIN(c->p);
             c->input_callback(c, c->ptr,
                               &(UIP_IP_BUF->srcipaddr),
-                              UIP_HTONS(UIP_IP_BUF->srcport),
+                              UIP_HTONS(UIP_UDP_BUF->srcport),
                               &(UIP_IP_BUF->destipaddr),
-                              UIP_HTONS(UIP_IP_BUF->destport),
+                              UIP_HTONS(UIP_UDP_BUF->destport),
                               buf, uip_datalen());
             PROCESS_CONTEXT_END();
           }
diff --git a/os/net/ipv6/uip-ds6-nbr.c b/os/net/ipv6/uip-ds6-nbr.c
index f937986b503e8d5aea58c8479ca0888991ce91e1..b8f8b63d7f9297d893ec46919cdb75803612e10a 100644
--- a/os/net/ipv6/uip-ds6-nbr.c
+++ b/os/net/ipv6/uip-ds6-nbr.c
@@ -55,19 +55,67 @@
 #include "net/ipv6/uip-nd6.h"
 #include "net/routing/routing.h"
 
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+#include "lib/memb.h"
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
+
 /* Log configuration */
 #include "sys/log.h"
 #define LOG_MODULE "IPv6 Nbr"
 #define LOG_LEVEL LOG_LEVEL_IPV6
 
-NBR_TABLE_GLOBAL(uip_ds6_nbr_t, ds6_neighbors);
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+/**
+ * Add nbr to the list in nbr_entry. In other words, this function associates an
+ * IPv6 address in nbr with a link-layer address in nbr_entry.
+ * \param nbr the neighbor cache entry for an IPv6 address
+ * \param nbr_entry the nbr_table entry for an link-layer address
+ */
+static void add_uip_ds6_nbr_to_nbr_entry(uip_ds6_nbr_t *nbr,
+                                         uip_ds6_nbr_entry_t *nbr_entry);
+
+/**
+ * Remove nbr from the list of the corresponding nbr_entry
+ * \param nbr a neighbor cache entry (nbr) to be removed
+ */
+static void remove_uip_ds6_nbr_from_nbr_entry(uip_ds6_nbr_t *nbr);
+
+/**
+ * Remove nbr_etnry from nbr_table
+ * \param nbr_entry a nbr_table entry (nbr_entry) to be removed
+ */
+static void remove_nbr_entry(uip_ds6_nbr_entry_t *nbr_entry);
+
+/**
+ * Free memory for a specified neighbor cache entry
+ * \param nbr a neighbor cache entry to be freed
+ */
+static void free_uip_ds6_nbr(uip_ds6_nbr_t *nbr);
+
+/**
+ * Callback function called when a nbr_table entry is removed
+ * \param nbr_entry a nbr_entry to be removed
+ */
+static void callback_nbr_entry_removal(uip_ds6_nbr_entry_t *nbr_entry);
+
+NBR_TABLE(uip_ds6_nbr_entry_t, uip_ds6_nbr_entries);
+MEMB(uip_ds6_nbr_memb, uip_ds6_nbr_t, UIP_DS6_NBR_MAX_NEIGHBOR_CACHES);
+#else
+NBR_TABLE(uip_ds6_nbr_t, ds6_neighbors);
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
 
 /*---------------------------------------------------------------------------*/
 void
 uip_ds6_neighbors_init(void)
 {
   link_stats_init();
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+  memb_init(&uip_ds6_nbr_memb);
+  nbr_table_register(uip_ds6_nbr_entries,
+                     (nbr_table_callback *)callback_nbr_entry_removal);
+#else
   nbr_table_register(ds6_neighbors, (nbr_table_callback *)uip_ds6_nbr_rm);
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
 }
 /*---------------------------------------------------------------------------*/
 uip_ds6_nbr_t *
@@ -75,8 +123,63 @@ uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr,
                 uint8_t isrouter, uint8_t state, nbr_table_reason_t reason,
                 void *data)
 {
-  uip_ds6_nbr_t *nbr = nbr_table_add_lladdr(ds6_neighbors, (linkaddr_t*)lladdr
-                                            , reason, data);
+  uip_ds6_nbr_t *nbr;
+
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+  uip_ds6_nbr_entry_t *nbr_entry;
+
+  assert(uip_ds6_nbr_lookup(ipaddr) == NULL);
+  if(uip_ds6_nbr_lookup(ipaddr)) {
+    LOG_ERR("%s: uip_ds6_nbr for ", __func__);
+    LOG_ERR_6ADDR(ipaddr);
+    LOG_ERR_("has already existed\n");
+    return NULL;
+  }
+
+  /* firstly, allocate memory for a new nbr cache entry */
+  if((nbr = (uip_ds6_nbr_t *)memb_alloc(&uip_ds6_nbr_memb)) == NULL) {
+    LOG_ERR("%s: cannot allocate a new uip_ds6_nbr\n", __func__);
+    return NULL;
+  }
+
+  /* secondly, get or allocate nbr_entry for the link-layer address */
+  nbr_entry = nbr_table_get_from_lladdr(uip_ds6_nbr_entries,
+                                        (const linkaddr_t *)lladdr);
+  if(nbr_entry == NULL) {
+    if((nbr_entry =
+        nbr_table_add_lladdr(uip_ds6_nbr_entries,
+                             (linkaddr_t*)lladdr, reason, data)) == NULL) {
+      LOG_ERR("%s: cannot allocate a new uip_ds6_nbr_entry\n", __func__);
+      /* return from this function later */
+    } else {
+      LIST_STRUCT_INIT(nbr_entry, uip_ds6_nbrs);
+    }
+  }
+
+  /* free nbr and return if nbr_entry is not available */
+  if((nbr_entry == NULL) ||
+     (list_length(nbr_entry->uip_ds6_nbrs) == UIP_DS6_NBR_MAX_6ADDRS_PER_NBR)) {
+    if(list_length(nbr_entry->uip_ds6_nbrs) == UIP_DS6_NBR_MAX_6ADDRS_PER_NBR) {
+      /*
+       * it's already had the maximum number of IPv6 addresses; cannot
+       * add another.
+       */
+      LOG_ERR("%s: no room in nbr_entry for ", __func__);
+      LOG_ERR_LLADDR((const linkaddr_t *)lladdr);
+      LOG_ERR_("\n");
+    }
+    /* free the newly allocated memory in this function call */
+    memb_free(&uip_ds6_nbr_memb, nbr);
+    return NULL;
+  } else {
+    /* everything is fine; nbr is ready to be used */
+    /* it has room to add another IPv6 address */
+    add_uip_ds6_nbr_to_nbr_entry(nbr, nbr_entry);
+  }
+#else
+  nbr = nbr_table_add_lladdr(ds6_neighbors, (linkaddr_t*)lladdr, reason, data);
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
+
   if(nbr) {
     uip_ipaddr_copy(&nbr->ipaddr, ipaddr);
 #if UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
@@ -113,10 +216,91 @@ uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr, const uip_lladdr_t *lladdr,
   }
 }
 
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+/*---------------------------------------------------------------------------*/
+static void
+add_uip_ds6_nbr_to_nbr_entry(uip_ds6_nbr_t *nbr,
+                               uip_ds6_nbr_entry_t *nbr_entry)
+{
+  LOG_DBG("%s: add nbr(%p) to nbr_entry (%p)\n",
+          __func__, nbr, nbr_entry);
+  nbr->nbr_entry = nbr_entry;
+  list_add(nbr_entry->uip_ds6_nbrs, nbr);
+}
+/*---------------------------------------------------------------------------*/
+static void
+remove_uip_ds6_nbr_from_nbr_entry(uip_ds6_nbr_t *nbr)
+{
+  if(nbr == NULL) {
+    return;
+  }
+  LOG_DBG("%s: remove nbr(%p) from nbr_entry (%p)\n",
+          __func__, nbr, nbr->nbr_entry);
+  list_remove(nbr->nbr_entry->uip_ds6_nbrs, nbr);
+}
+/*---------------------------------------------------------------------------*/
+static void
+remove_nbr_entry(uip_ds6_nbr_entry_t *nbr_entry)
+{
+  if(nbr_entry == NULL) {
+    return;
+  }
+  LOG_DBG("%s: remove nbr_entry (%p) from nbr_table\n",
+          __func__, nbr_entry);
+  (void)nbr_table_remove(uip_ds6_nbr_entries, nbr_entry);
+}
+/*---------------------------------------------------------------------------*/
+static void
+free_uip_ds6_nbr(uip_ds6_nbr_t *nbr)
+{
+  if(nbr == NULL) {
+    return;
+  }
+#if UIP_CONF_IPV6_QUEUE_PKT
+  uip_packetqueue_free(&nbr->packethandle);
+#endif /* UIP_CONF_IPV6_QUEUE_PKT */
+  NETSTACK_ROUTING.neighbor_state_changed(nbr);
+  assert(nbr->nbr_entry != NULL);
+  if(nbr->nbr_entry == NULL) {
+    LOG_ERR("%s: unexpected error nbr->nbr_entry is NULL\n", __func__);
+  } else {
+    remove_uip_ds6_nbr_from_nbr_entry(nbr);
+    if(list_length(nbr->nbr_entry->uip_ds6_nbrs) == 0) {
+      remove_nbr_entry(nbr->nbr_entry);
+    }
+  }
+  LOG_DBG("%s: free memory for nbr(%p)\n", __func__, nbr);
+  memb_free(&uip_ds6_nbr_memb, nbr);
+}
+/*---------------------------------------------------------------------------*/
+static void
+callback_nbr_entry_removal(uip_ds6_nbr_entry_t *nbr_entry)
+{
+  uip_ds6_nbr_t *nbr;
+  uip_ds6_nbr_t *next_nbr;
+  if(nbr_entry == NULL) {
+    return;
+  }
+  for(nbr = (uip_ds6_nbr_t *)list_head(nbr_entry->uip_ds6_nbrs);
+      nbr != NULL;
+      nbr = next_nbr) {
+    next_nbr = (uip_ds6_nbr_t *)list_item_next(nbr);
+    free_uip_ds6_nbr(nbr);
+  }
+}
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
 /*---------------------------------------------------------------------------*/
 int
 uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr)
 {
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+  if(nbr == NULL) {
+    return 0;
+  } else {
+    free_uip_ds6_nbr(nbr);
+    return 1;
+  }
+#else /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
   if(nbr != NULL) {
 #if UIP_CONF_IPV6_QUEUE_PKT
     uip_packetqueue_free(&nbr->packethandle);
@@ -125,19 +309,52 @@ uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr)
     return nbr_table_remove(ds6_neighbors, nbr);
   }
   return 0;
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
 }
 
 /*---------------------------------------------------------------------------*/
 int
 uip_ds6_nbr_update_ll(uip_ds6_nbr_t **nbr_pp, const uip_lladdr_t *new_ll_addr)
 {
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+  uip_ds6_nbr_entry_t *nbr_entry;
+  uip_ds6_nbr_t *nbr;
+#else
   uip_ds6_nbr_t nbr_backup;
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
 
   if(nbr_pp == NULL || new_ll_addr == NULL) {
     LOG_ERR("%s: invalid argument\n", __func__);
     return -1;
   }
 
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+
+  if((nbr_entry =
+      nbr_table_get_from_lladdr(uip_ds6_nbr_entries,
+                                (const linkaddr_t *)new_ll_addr)) == NULL) {
+    if((nbr_entry =
+        nbr_table_add_lladdr(uip_ds6_nbr_entries,
+                             (const linkaddr_t*)new_ll_addr,
+                             NBR_TABLE_REASON_IPV6_ND, NULL)) == NULL) {
+      LOG_ERR("%s: cannot allocate a nbr_entry for", __func__);
+      LOG_ERR_LLADDR((const linkaddr_t *)new_ll_addr);
+      return -1;
+    } else {
+      LIST_STRUCT_INIT(nbr_entry, uip_ds6_nbrs);
+    }
+  }
+
+  nbr = *nbr_pp;
+
+  remove_uip_ds6_nbr_from_nbr_entry(nbr);
+  if(list_length(nbr->nbr_entry->uip_ds6_nbrs) == 0) {
+    remove_nbr_entry(nbr->nbr_entry);
+  }
+  add_uip_ds6_nbr_to_nbr_entry(nbr, nbr_entry);
+
+#else /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
+
   /* make sure new_ll_addr is not used in some other nbr */
   if(uip_ds6_nbr_ll_lookup(new_ll_addr) != NULL) {
     LOG_ERR("%s: new_ll_addr, ", __func__);
@@ -159,6 +376,7 @@ uip_ds6_nbr_update_ll(uip_ds6_nbr_t **nbr_pp, const uip_lladdr_t *new_ll_addr)
     return -1;
   }
   memcpy(*nbr_pp, &nbr_backup, sizeof(uip_ds6_nbr_t));
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
 
   return 0;
 }
@@ -173,46 +391,88 @@ uip_ds6_nbr_get_ipaddr(const uip_ds6_nbr_t *nbr)
 const uip_lladdr_t *
 uip_ds6_nbr_get_ll(const uip_ds6_nbr_t *nbr)
 {
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+  if(nbr == NULL) {
+    return NULL;
+  }
+  return (const uip_lladdr_t *)nbr_table_get_lladdr(uip_ds6_nbr_entries,
+                                                    nbr->nbr_entry);
+#else
   return (const uip_lladdr_t *)nbr_table_get_lladdr(ds6_neighbors, nbr);
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
 }
 /*---------------------------------------------------------------------------*/
 int
 uip_ds6_nbr_num(void)
 {
-  uip_ds6_nbr_t *nbr;
-  int num;
+  int num = 0;
 
-  num = 0;
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+  uip_ds6_nbr_entry_t *nbr_entry;
+  for(nbr_entry = nbr_table_head(uip_ds6_nbr_entries);
+      nbr_entry != NULL;
+      nbr_entry = nbr_table_next(uip_ds6_nbr_entries, nbr_entry)) {
+    num += list_length(nbr_entry->uip_ds6_nbrs);
+  }
+#else
+  uip_ds6_nbr_t *nbr;
   for(nbr = nbr_table_head(ds6_neighbors);
       nbr != NULL;
       nbr = nbr_table_next(ds6_neighbors, nbr)) {
     num++;
   }
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
   return num;
 }
 /*---------------------------------------------------------------------------*/
 uip_ds6_nbr_t *
 uip_ds6_nbr_head(void)
 {
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+  uip_ds6_nbr_entry_t *nbr_entry;
+  if((nbr_entry = nbr_table_head(uip_ds6_nbr_entries)) == NULL) {
+    return NULL;
+  }
+  assert(list_head(nbr_entry->uip_ds6_nbrs) != NULL);
+  return (uip_ds6_nbr_t *)list_head(nbr_entry->uip_ds6_nbrs);
+#else
   return nbr_table_head(ds6_neighbors);
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
 }
 /*---------------------------------------------------------------------------*/
 uip_ds6_nbr_t *
 uip_ds6_nbr_next(uip_ds6_nbr_t *nbr)
 {
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+  uip_ds6_nbr_entry_t *nbr_entry;
+  if(nbr == NULL) {
+    return NULL;
+  }
+  if(list_item_next(nbr) != NULL) {
+    return list_item_next(nbr);
+  }
+  nbr_entry = nbr_table_next(uip_ds6_nbr_entries, nbr->nbr_entry);
+  if(nbr_entry == NULL) {
+    return NULL;
+  } else {
+    assert(list_head(nbr_entry->uip_ds6_nbrs) != NULL);
+    return (uip_ds6_nbr_t *)list_head(nbr_entry->uip_ds6_nbrs);
+  }
+#else
   return nbr_table_next(ds6_neighbors, nbr);
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
 }
 /*---------------------------------------------------------------------------*/
 uip_ds6_nbr_t *
 uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr)
 {
-  uip_ds6_nbr_t *nbr = nbr_table_head(ds6_neighbors);
-  if(ipaddr != NULL) {
-    while(nbr != NULL) {
-      if(uip_ipaddr_cmp(&nbr->ipaddr, ipaddr)) {
-        return nbr;
-      }
-      nbr = nbr_table_next(ds6_neighbors, nbr);
+  uip_ds6_nbr_t *nbr;
+  if(ipaddr == NULL) {
+    return NULL;
+  }
+  for(nbr = uip_ds6_nbr_head(); nbr != NULL; nbr = uip_ds6_nbr_next(nbr)) {
+    if(uip_ipaddr_cmp(&nbr->ipaddr, ipaddr)) {
+      return nbr;
     }
   }
   return NULL;
@@ -221,7 +481,23 @@ uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr)
 uip_ds6_nbr_t *
 uip_ds6_nbr_ll_lookup(const uip_lladdr_t *lladdr)
 {
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+  uip_ds6_nbr_entry_t *nbr_entry;
+  /*
+   * we cannot determine which entry should return by lladdr alone;
+   * return the first entry associated with lladdr.
+   */
+  nbr_entry =
+    (uip_ds6_nbr_entry_t *)nbr_table_get_from_lladdr(uip_ds6_nbr_entries,
+                                                     (linkaddr_t*)lladdr);
+  if(nbr_entry == NULL) {
+    return NULL;
+  }
+  assert(list_head(nbr_entry->uip_ds6_nbrs) != NULL);
+  return (uip_ds6_nbr_t *)list_head(nbr_entry->uip_ds6_nbrs);
+#else
   return nbr_table_get_from_lladdr(ds6_neighbors, (linkaddr_t*)lladdr);
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
 }
 
 /*---------------------------------------------------------------------------*/
@@ -239,6 +515,20 @@ uip_ds6_nbr_lladdr_from_ipaddr(const uip_ipaddr_t *ipaddr)
   uip_ds6_nbr_t *nbr = uip_ds6_nbr_lookup(ipaddr);
   return nbr ? uip_ds6_nbr_get_ll(nbr) : NULL;
 }
+#if UIP_DS6_LL_NUD
+/*---------------------------------------------------------------------------*/
+static void
+update_nbr_reachable_state_by_ack(uip_ds6_nbr_t *nbr, const linkaddr_t *lladdr)
+{
+  if(nbr != NULL && nbr->state != NBR_INCOMPLETE) {
+    nbr->state = NBR_REACHABLE;
+    stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
+    LOG_INFO("received a link layer ACK : ");
+    LOG_INFO_LLADDR(lladdr);
+    LOG_INFO_(" is reachable.\n");
+  }
+}
+#endif /* UIP_DS6_LL_NUD */
 /*---------------------------------------------------------------------------*/
 void
 uip_ds6_link_callback(int status, int numtx)
@@ -266,14 +556,22 @@ uip_ds6_link_callback(int status, int numtx)
    * acknowledges link packets. */
   if(status == MAC_TX_OK) {
     uip_ds6_nbr_t *nbr;
-    nbr = uip_ds6_nbr_ll_lookup((uip_lladdr_t *)dest);
-    if(nbr != NULL && nbr->state != NBR_INCOMPLETE) {
-      nbr->state = NBR_REACHABLE;
-      stimer_set(&nbr->reachable, UIP_ND6_REACHABLE_TIME / 1000);
-      LOG_INFO("received a link layer ACK : ");
-      LOG_INFO_LLADDR((uip_lladdr_t *)dest);
-      LOG_INFO_(" is reachable.\n");
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+    uip_ds6_nbr_entry_t *nbr_entry;
+    if((nbr_entry =
+        (uip_ds6_nbr_entry_t *)nbr_table_get_from_lladdr(uip_ds6_nbr_entries,
+                                                         dest)) == NULL) {
+      return;
+    }
+    for(nbr = (uip_ds6_nbr_t *)list_head(nbr_entry->uip_ds6_nbrs);
+        nbr != NULL;
+        nbr = (uip_ds6_nbr_t *)list_item_next(nbr)) {
+      update_nbr_reachable_state_by_ack(nbr, dest);
     }
+#else /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
+    nbr = uip_ds6_nbr_ll_lookup((uip_lladdr_t *)dest);
+    update_nbr_reachable_state_by_ack(nbr, dest);
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
   }
 #endif /* UIP_DS6_LL_NUD */
 }
@@ -283,7 +581,7 @@ uip_ds6_link_callback(int status, int numtx)
 void
 uip_ds6_neighbor_periodic(void)
 {
-  uip_ds6_nbr_t *nbr = nbr_table_head(ds6_neighbors);
+  uip_ds6_nbr_t *nbr = uip_ds6_nbr_head();
   while(nbr != NULL) {
     switch(nbr->state) {
     case NBR_REACHABLE:
@@ -354,7 +652,7 @@ uip_ds6_neighbor_periodic(void)
     default:
       break;
     }
-    nbr = nbr_table_next(ds6_neighbors, nbr);
+    nbr = uip_ds6_nbr_next(nbr);
   }
 }
 /*---------------------------------------------------------------------------*/
@@ -373,7 +671,7 @@ uip_ds6_nbr_refresh_reachable_state(const uip_ipaddr_t *ipaddr)
 uip_ds6_nbr_t *
 uip_ds6_get_least_lifetime_neighbor(void)
 {
-  uip_ds6_nbr_t *nbr = nbr_table_head(ds6_neighbors);
+  uip_ds6_nbr_t *nbr = uip_ds6_nbr_head();
   uip_ds6_nbr_t *nbr_expiring = NULL;
   while(nbr != NULL) {
     if(nbr_expiring != NULL) {
@@ -384,7 +682,7 @@ uip_ds6_get_least_lifetime_neighbor(void)
     } else {
       nbr_expiring = nbr;
     }
-    nbr = nbr_table_next(ds6_neighbors, nbr);
+    nbr = uip_ds6_nbr_next(nbr);
   }
   return nbr_expiring;
 }
diff --git a/os/net/ipv6/uip-ds6-nbr.h b/os/net/ipv6/uip-ds6-nbr.h
index d645ac627acac8d239be419550399b2cc476a2a9..6479c972ebdf368f09ead561e51106ef82642e2a 100644
--- a/os/net/ipv6/uip-ds6-nbr.h
+++ b/os/net/ipv6/uip-ds6-nbr.h
@@ -54,6 +54,10 @@
 #if UIP_CONF_IPV6_QUEUE_PKT
 #include "net/ipv6/uip-packetqueue.h"
 #endif                          /*UIP_CONF_QUEUE_PKT */
+#if UIP_DS6_NBR_CONF_MULTI_IPV6_ADDRS
+#include "lib/assert.h"
+#include "lib/list.h"
+#endif
 
 /*--------------------------------------------------*/
 /** \brief Possible states for the nbr cache entries */
@@ -63,10 +67,46 @@
 #define  NBR_DELAY 3
 #define  NBR_PROBE 4
 
-NBR_TABLE_DECLARE(ds6_neighbors);
+/** \brief Set non-zero (1) to enable multiple IPv6 addresses to be
+ * associated with a link-layer address */
+#ifdef UIP_DS6_NBR_CONF_MULTI_IPV6_ADDRS
+#define UIP_DS6_NBR_MULTI_IPV6_ADDRS UIP_DS6_NBR_CONF_MULTI_IPV6_ADDRS
+#else
+#define UIP_DS6_NBR_MULTI_IPV6_ADDRS 0
+#endif /* UIP_DS6_NBR_CONF_MULTI_IPV6_ADDRS */
 
-/** \brief An entry in the nbr cache */
+/** \brief Set the maximum number of IPv6 addresses per link-layer
+ * address */
+#ifdef UIP_DS6_NBR_CONF_MAX_6ADDRS_PER_NBR
+#define UIP_DS6_NBR_MAX_6ADDRS_PER_NBR UIP_DS6_NBR_CONF_MAX_6ADDRS_PER_NBR
+#else
+#define UIP_DS6_NBR_MAX_6ADDRS_PER_NBR 2
+#endif /* UIP_DS6_NBR_CONF_MAX_6ADDRS_PER_NBR */
+
+/** \brief Set the maximum number of neighbor cache entries */
+#ifdef UIP_DS6_NBR_CONF_MAX_NEIGHBOR_CACHES
+#define UIP_DS6_NBR_MAX_NEIGHBOR_CACHES UIP_DS6_NBR_CONF_MAX_NEIGHBOR_CACHES
+#else
+#define UIP_DS6_NBR_MAX_NEIGHBOR_CACHES \
+  (NBR_TABLE_MAX_NEIGHBORS * UIP_DS6_NBR_MAX_6ADDRS_PER_NBR)
+#endif /* UIP_DS6_NBR_CONF_MAX_NEIGHBOR_CACHES */
+
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+/** \brief nbr_table entry when UIP_DS6_NBR_MULTI_IPV6_ADDRS is
+ * enabled. uip_ds6_nbrs is a list of uip_ds6_nbr_t objects */
+typedef struct {
+  LIST_STRUCT(uip_ds6_nbrs);
+} uip_ds6_nbr_entry_t;
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
+
+/** \brief The default nbr_table entry (when
+ * UIP_DS6_NBR_MULTI_IPV6_ADDRS is disabled), that implements nbr
+ * cache */
 typedef struct uip_ds6_nbr {
+#if UIP_DS6_NBR_MULTI_IPV6_ADDRS
+  struct uip_ds6_nbr *next;
+  uip_ds6_nbr_entry_t *nbr_entry;
+#endif /* UIP_DS6_NBR_MULTI_IPV6_ADDRS */
   uip_ipaddr_t ipaddr;
   uint8_t isrouter;
   uint8_t state;
@@ -83,25 +123,119 @@ typedef struct uip_ds6_nbr {
 
 void uip_ds6_neighbors_init(void);
 
-/** \brief Neighbor Cache basic routines */
+/**
+ * Add a neighbor cache for a specified IPv6 address, which is
+ *  associated with a specified link-layer address
+ * \param ipaddr IPv6 address of a neighbor to add
+ * \param lladdr Link-layer address to associate with ipaddr
+ * \param isrouter Set 1 if the neighbor is a router
+ * \param state Set the initial neighbor cache state (e.g.,
+ * NBR_INCOMPLETE)
+ * \param reason Set a reason of the addition (e.g.,
+ * NBR_TABLE_REASON_RPL_DIO)
+ * \param data Set data associated with the nbr cache
+ * \return the address of a newly added nbr cache on success, NULL on
+ * failure
+*/
 uip_ds6_nbr_t *uip_ds6_nbr_add(const uip_ipaddr_t *ipaddr,
                                const uip_lladdr_t *lladdr,
                                uint8_t isrouter, uint8_t state,
                                nbr_table_reason_t reason, void *data);
+
+/**
+ * Remove a neighbor cache
+ * \param nbr the address of a neighbor cache to remove
+ * \return 1 on success, 0 on failure (nothing was removed)
+ */
 int uip_ds6_nbr_rm(uip_ds6_nbr_t *nbr);
+
+/**
+ * Get the link-layer address associated with a specified nbr cache
+ * \param nbr the address of a neighbor cache
+ * \return pointer to the link-layer address on success, NULL on failure
+ */
 const uip_lladdr_t *uip_ds6_nbr_get_ll(const uip_ds6_nbr_t *nbr);
+
+/**
+ * Get the link-layer address associated with a specified IPv6 address
+ * \param ipaddr an IPv6 address used as a search key
+ * \return the pointer to the link-layer address on success, NULL on failure
+ */
+const uip_lladdr_t *uip_ds6_nbr_lladdr_from_ipaddr(const uip_ipaddr_t *ipaddr);
+
+/**
+ * Update the link-layer address associated with an  IPv6 address
+ * \param nbr the double pointer to a neighbor cache which has the
+ * target IPv6 address
+ * \param new_ll_addr the new link-layer address of the IPv6 address
+ * return 0 on success, -1 on failure
+ */
 int uip_ds6_nbr_update_ll(uip_ds6_nbr_t **nbr, const uip_lladdr_t *new_ll_addr);
+
+/**
+ * Get an IPv6 address of a neighbor cache
+ * \param nbr the pointer to a neighbor cache
+ * \return the pointer to an IPv6 address associated with the neighbor cache
+ * \note This returns the first IPv6 address found in the neighbor
+ * cache when UIP_DS6_NBR_MULTI_IPV6_ADDRS is enabled
+ */
 const uip_ipaddr_t *uip_ds6_nbr_get_ipaddr(const uip_ds6_nbr_t *nbr);
+
+/**
+ * Get an IPv6 address associated with a specified link-layer address
+ * \param lladdr a link-layer address used as a search key
+ * \return the pointer to an IPv6 address associated with the neighbor cache
+ * \note This returns the first IPv6 address found in the neighbor
+ * cache when UIP_DS6_NBR_MULTI_IPV6_ADDRS is enabled
+ */
+uip_ipaddr_t *uip_ds6_nbr_ipaddr_from_lladdr(const uip_lladdr_t *lladdr);
+
+/**
+ * Get the neighbor cache associated with a specified IPv6 address
+ * \param ipaddr an IPv6 address used as a search key
+ * \return the pointer to a neighbor cache on success, NULL on failure
+ */
 uip_ds6_nbr_t *uip_ds6_nbr_lookup(const uip_ipaddr_t *ipaddr);
+
+/**
+ * Get the neighbor cache associated with a specified link-layer address
+ * \param lladdr a link-layer address used as a search key
+ * \return the pointer to a neighbor cache on success, NULL on failure
+ */
 uip_ds6_nbr_t *uip_ds6_nbr_ll_lookup(const uip_lladdr_t *lladdr);
-uip_ipaddr_t *uip_ds6_nbr_ipaddr_from_lladdr(const uip_lladdr_t *lladdr);
-const uip_lladdr_t *uip_ds6_nbr_lladdr_from_ipaddr(const uip_ipaddr_t *ipaddr);
-void uip_ds6_link_callback(int status, int numtx);
-void uip_ds6_neighbor_periodic(void);
+
+/**
+ * Return the number of neighbor caches
+ * \return the number of neighbor caches in use
+ */
 int uip_ds6_nbr_num(void);
+
+/**
+ * Get the first neighbor cache in nbr_table
+ * \return the pointer to the first neighbor cache entry
+ */
 uip_ds6_nbr_t *uip_ds6_nbr_head(void);
+
+/**
+ * Get the next neighbor cache of a specified one
+ * \param nbr the pointer to a neighbor cache
+ * \return the pointer to the next one on success, NULL on failure
+ */
 uip_ds6_nbr_t *uip_ds6_nbr_next(uip_ds6_nbr_t *nbr);
 
+/**
+ * The callback function to update link-layer stats in a neighbor
+ * cache
+ * \param status MAC return value defined in mac.h
+ * \param numtx the number of transmissions happened for a packet
+ */
+void uip_ds6_link_callback(int status, int numtx);
+
+/**
+ * The housekeeping function called periodically
+ */
+void uip_ds6_neighbor_periodic(void);
+
 #if UIP_ND6_SEND_NS
 /**
  * \brief Refresh the reachable state of a neighbor. This function
diff --git a/os/net/ipv6/uip-ds6.c b/os/net/ipv6/uip-ds6.c
index 4e82b3745025644ba1b5b8c517beb4cfd94d044b..bcfb9b0c834172420e0d3b96bf38fc8cfcbdb5c3 100644
--- a/os/net/ipv6/uip-ds6.c
+++ b/os/net/ipv6/uip-ds6.c
@@ -95,10 +95,29 @@ static uip_ds6_prefix_t *locprefix;
 static const uint8_t iid_prefix[] = { 0x00, 0x00 , 0x00 , 0xff , 0xfe , 0x00 };
 #endif /* (UIP_LLADDR_LEN == 2) */
 
+/* The default prefix */
+static uip_ip6addr_t default_prefix = {
+    .u16 = { 0, 0, 0, 0, 0, 0, 0, 0 }
+};
+/*---------------------------------------------------------------------------*/
+const uip_ip6addr_t *
+uip_ds6_default_prefix()
+{
+  return &default_prefix;
+}
+/*---------------------------------------------------------------------------*/
+void
+uip_ds6_set_default_prefix(const uip_ip6addr_t *prefix)
+{
+  uip_ip6addr_copy(&default_prefix, prefix);
+}
 /*---------------------------------------------------------------------------*/
 void
 uip_ds6_init(void)
 {
+  if(uip_is_addr_unspecified(&default_prefix)) {
+    uip_ip6addr(&default_prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
+  }
 
   uip_ds6_neighbors_init();
   uip_ds6_route_init();
diff --git a/os/net/ipv6/uip-ds6.h b/os/net/ipv6/uip-ds6.h
index 45394fec3f918311a4305779c99d486ffce1d0db..0edc1fd6d42d32c62c6f70ab07096c8dc9fbc18f 100644
--- a/os/net/ipv6/uip-ds6.h
+++ b/os/net/ipv6/uip-ds6.h
@@ -296,6 +296,22 @@ uip_ds6_prefix_t *uip_ds6_prefix_lookup(uip_ipaddr_t *ipaddr,
                                         uint8_t ipaddrlen);
 uint8_t uip_ds6_is_addr_onlink(uip_ipaddr_t *ipaddr);
 
+/**
+ * \brief Retrieve the Default IPv6 prefix
+ * \retval A pointer to the default prefix
+ */
+const uip_ip6addr_t *uip_ds6_default_prefix(void);
+
+/**
+ * \brief Set the Default IPv6 prefix
+ * \param prefix A pointer to the new default prefix
+ *
+ * uip_ds6_init() will set the default prefix to UIP_DS6_DEFAULT_PREFIX
+ * unless this function here has been called beforehand to set a new default
+ * prefix.
+ */
+void uip_ds6_set_default_prefix(const uip_ip6addr_t *prefix);
+
 /** @} */
 
 /** \name Unicast address list basic routines */
diff --git a/os/net/ipv6/uip-icmp6.c b/os/net/ipv6/uip-icmp6.c
index 707a13309d69940fdecd9ee7f499910513845b93..e04d66165c6bdc82cd17ff31bcebf893369e7228 100644
--- a/os/net/ipv6/uip-icmp6.c
+++ b/os/net/ipv6/uip-icmp6.c
@@ -53,11 +53,7 @@
 #define LOG_MODULE "ICMPv6"
 #define LOG_LEVEL LOG_LEVEL_IPV6
 
-#define UIP_IP_BUF                ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-#define UIP_ICMP_BUF            ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_ICMP6_ERROR_BUF  ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len])
-#define UIP_EXT_BUF              ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_FIRST_EXT_BUF        ((struct uip_ext_hdr *)&uip_buf[UIP_LLIPH_LEN])
+#define UIP_ICMP6_ERROR_BUF  ((struct uip_icmp6_error *)UIP_ICMP_PAYLOAD)
 
 /** \brief temporary IP address */
 static uip_ipaddr_t tmp_ipaddr;
@@ -134,22 +130,7 @@ echo_request_input(void)
     uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &tmp_ipaddr);
   }
 
-  if(uip_ext_len > 0) {
-    /* Remove extension headers if any */
-    UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
-    uip_len -= uip_ext_len;
-    UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
-    UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
-    /* move the echo request payload (starting after the icmp header)
-     * to the new location in the reply.
-     * The shift is equal to the length of the extension headers present
-     * Note: UIP_ICMP_BUF still points to the echo request at this stage
-     */
-    memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - uip_ext_len,
-        (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN,
-        (uip_len - UIP_IPH_LEN - UIP_ICMPH_LEN));
-    uip_ext_len = 0;
-  }
+  uip_remove_ext_hdr();
 
   /* Below is important for the correctness of UIP_ICMP_BUF and the
    * checksum
@@ -171,59 +152,55 @@ echo_request_input(void)
 }
 /*---------------------------------------------------------------------------*/
 void
-uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) {
+uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param)
+{
   /* check if originating packet is not an ICMP error */
-  if(uip_ext_len) {
-    if(UIP_EXT_BUF->next == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128) {
-      uip_clear_buf();
-      return;
-    }
-  } else {
-    if(UIP_IP_BUF->proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128) {
-      uip_clear_buf();
-      return;
-    }
+  uint16_t shift;
+
+  if(uip_last_proto == UIP_PROTO_ICMP6 && UIP_ICMP_BUF->type < 128) {
+    uipbuf_clear();
+    return;
   }
 
-  /* Remove all extension headers related to the routing protocol in place */
-  NETSTACK_ROUTING.ext_header_remove();
+  /* the source should not be unspecified nor multicast */
+  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr) ||
+     uip_is_addr_mcast(&UIP_IP_BUF->srcipaddr)) {
+    uipbuf_clear();
+    return;
+  }
+
+  /* Remove all extension headers related to the routing protocol in place.
+   * Keep all other extension headers, so as to match original packet. */
+  if(NETSTACK_ROUTING.ext_header_remove() == 0) {
+    LOG_WARN("Unable to remove ext header before sending ICMPv6 ERROR message\n");
+  }
 
   /* remember data of original packet before shifting */
   uip_ipaddr_copy(&tmp_ipaddr, &UIP_IP_BUF->destipaddr);
 
-  uip_len += UIP_IPICMPH_LEN + UIP_ICMP6_ERROR_LEN;
-
-  if(uip_len > UIP_LINK_MTU) {
-    uip_len = UIP_LINK_MTU;
-  }
-
-  memmove((uint8_t *)UIP_ICMP6_ERROR_BUF + uip_ext_len + UIP_ICMP6_ERROR_LEN,
-          (void *)UIP_IP_BUF, uip_len - UIP_IPICMPH_LEN - uip_ext_len - UIP_ICMP6_ERROR_LEN);
+  /* The ICMPv6 error message contains as much of possible of the invoking packet
+   * (see RFC 4443 section 3). Make space for the additional IPv6 and
+   * ICMPv6 headers here and move payload to the "right". What we move includes
+    * extension headers */
+  shift = UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ICMP6_ERROR_LEN;
+  uip_len += shift;
+  uip_len = MIN(uip_len, UIP_LINK_MTU);
+  uip_ext_len = 0;
+  memmove(uip_buf + shift, (void *)UIP_IP_BUF, uip_len - shift);
 
   UIP_IP_BUF->vtc = 0x60;
   UIP_IP_BUF->tcflow = 0;
   UIP_IP_BUF->flow = 0;
-  if (uip_ext_len) {
-    UIP_FIRST_EXT_BUF->next = UIP_PROTO_ICMP6;
-  } else {
-    UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
-  }
+  UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
   UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit;
 
-  /* the source should not be unspecified nor multicast, the check for
-     multicast is done in uip_process */
-  if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)){
-    uip_clear_buf();
-    return;
-  }
-
   uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &UIP_IP_BUF->srcipaddr);
 
   if(uip_is_addr_mcast(&tmp_ipaddr)){
     if(type == ICMP6_PARAM_PROB && code == ICMP6_PARAMPROB_OPTION){
       uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &tmp_ipaddr);
     } else {
-      uip_clear_buf();
+      uipbuf_clear();
       return;
     }
   } else {
@@ -234,8 +211,7 @@ uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param) {
   UIP_ICMP_BUF->type = type;
   UIP_ICMP_BUF->icode = code;
   UIP_ICMP6_ERROR_BUF->param = uip_htonl(param);
-  UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
-  UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
+  uipbuf_set_len_field(UIP_IP_BUF, uip_len - UIP_IPH_LEN);
   UIP_ICMP_BUF->icmpchksum = 0;
   UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
 
@@ -258,8 +234,7 @@ uip_icmp6_send(const uip_ipaddr_t *dest, int type, int code, int payload_len)
   UIP_IP_BUF->flow = 0;
   UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
   UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit;
-  UIP_IP_BUF->len[0] = (UIP_ICMPH_LEN + payload_len) >> 8;
-  UIP_IP_BUF->len[1] = (UIP_ICMPH_LEN + payload_len) & 0xff;
+  uipbuf_set_len_field(UIP_IP_BUF, UIP_ICMPH_LEN + payload_len);
 
   memcpy(&UIP_IP_BUF->destipaddr, dest, sizeof(*dest));
   uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
@@ -297,22 +272,7 @@ echo_reply_input(void)
   uip_ipaddr_copy(&sender, &UIP_IP_BUF->srcipaddr);
   ttl = UIP_IP_BUF->ttl;
 
-  if(uip_ext_len > 0) {
-    /* Remove extension headers if any */
-    UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
-    uip_len -= uip_ext_len;
-    UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
-    UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
-    /* move the echo reply payload (starting after the icmp header)
-     * to the new location in the reply.  The shift is equal to the
-     * length of the extension headers present Note: UIP_ICMP_BUF
-     * still points to the echo request at this stage
-     */
-    memmove((uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN - uip_ext_len,
-        (uint8_t *)UIP_ICMP_BUF + UIP_ICMPH_LEN,
-        (uip_len - UIP_IPH_LEN - UIP_ICMPH_LEN));
-    uip_ext_len = 0;
-  }
+  uip_remove_ext_hdr();
 
   /* Call all registered applications to let them know an echo reply
      has been received. */
@@ -329,7 +289,7 @@ echo_reply_input(void)
     }
   }
 
-  uip_clear_buf();
+  uipbuf_clear();
   return;
 }
 /*---------------------------------------------------------------------------*/
diff --git a/os/net/ipv6/uip-icmp6.h b/os/net/ipv6/uip-icmp6.h
index 2808ea7de433cce037a79d81abd4191f70d1bed9..21d2aeeebe5a764072f192c2b62824ad90246d70 100644
--- a/os/net/ipv6/uip-icmp6.h
+++ b/os/net/ipv6/uip-icmp6.h
@@ -38,7 +38,7 @@
 /**
  * \file
  *    Header file for ICMPv6 message and error handing (RFC 4443)
- * \author Julien Abeille <jabeille@cisco.com> 
+ * \author Julien Abeille <jabeille@cisco.com>
  * \author Mathilde Durvy <mdurvy@cisco.com>
  */
 
@@ -52,8 +52,8 @@
 /** @{ */
 #define ICMP6_DST_UNREACH                 1	/**< dest unreachable */
 #define ICMP6_PACKET_TOO_BIG	            2	/**< packet too big */
-#define ICMP6_TIME_EXCEEDED	            3	/**< time exceeded */
-#define ICMP6_PARAM_PROB	               4	/**< ip6 header bad */
+#define ICMP6_TIME_EXCEEDED	              3	/**< time exceeded */
+#define ICMP6_PARAM_PROB	                4	/**< ip6 header bad */
 #define ICMP6_ECHO_REQUEST              128  /**< Echo request */
 #define ICMP6_ECHO_REPLY                129  /**< Echo reply */
 
@@ -64,6 +64,7 @@
 #define ICMP6_REDIRECT                  137  /**< Redirect */
 
 #define ICMP6_RPL                       155  /**< RPL */
+#define ICMP6_MPL                       159  /**< MPL */
 #define ICMP6_PRIV_EXP_100              100  /**< Private Experimentation */
 #define ICMP6_PRIV_EXP_101              101  /**< Private Experimentation */
 #define ICMP6_PRIV_EXP_200              200  /**< Private Experimentation */
@@ -76,10 +77,10 @@
 /** \name ICMPv6 Destination Unreachable message codes*/
 /** @{ */
 #define ICMP6_DST_UNREACH_NOROUTE         0 /**< no route to destination */
-#define ICMP6_DST_UNREACH_ADMIN	         1 /**< administratively prohibited */
+#define ICMP6_DST_UNREACH_ADMIN	          1 /**< administratively prohibited */
 #define ICMP6_DST_UNREACH_NOTNEIGHBOR     2 /**< not a neighbor(obsolete) */
 #define ICMP6_DST_UNREACH_BEYONDSCOPE     2 /**< beyond scope of source address */
-#define ICMP6_DST_UNREACH_ADDR	         3 /**< address unreachable */
+#define ICMP6_DST_UNREACH_ADDR	          3 /**< address unreachable */
 #define ICMP6_DST_UNREACH_NOPORT          4 /**< port unreachable */
 /** @} */
 
@@ -116,7 +117,7 @@ typedef struct uip_icmp6_error{
  * \param param 32 bit parameter of the error message, semantic depends on error
  */
 void
-uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param); 
+uip_icmp6_error_output(uint8_t type, uint8_t code, uint32_t param);
 
 /**
  * \brief Send an icmpv6 message
diff --git a/os/net/ipv6/uip-nameserver.c b/os/net/ipv6/uip-nameserver.c
index 83a1943b0c204cb847c31f2f8240cb9d0a7c76a0..755b33992d378d9af241d36e84efe3b101eef9a0 100644
--- a/os/net/ipv6/uip-nameserver.c
+++ b/os/net/ipv6/uip-nameserver.c
@@ -108,7 +108,7 @@ uip_nameserver_update(const uip_ipaddr_t *nameserver, uint32_t lifetime)
        *          the the eldest ones */
     }
   }
-  
+
   if(e == NULL) {
     if((e = memb_alloc(&dnsmemb)) != NULL) {
       list_add(dns, e);
@@ -221,11 +221,7 @@ uip_nameserver_count(void)
   }
   return list_length(dns);
 #else /* UIP_NAMESERVER_POOL_SIZE > 1 */
-#if NETSTACK_CONF_WITH_IPV6
   if(uip_is_addr_unspecified(&serveraddr)) {
-#else /* NETSTACK_CONF_WITH_IPV6 */
-  if(uip_ipaddr_cmp(&serveraddr, &uip_all_zeroes_addr)) {
-#endif /* NETSTACK_CONF_WITH_IPV6 */
     return 0;
   } else {
     return 1;
diff --git a/os/net/ipv6/uip-nd6.c b/os/net/ipv6/uip-nd6.c
index 63ae46b475a4b610e5212ff8f940bbd3290b3d11..f6efc83de076d089da91b8d52c8092835cfb5502 100644
--- a/os/net/ipv6/uip-nd6.c
+++ b/os/net/ipv6/uip-nd6.c
@@ -84,29 +84,20 @@
 /*------------------------------------------------------------------*/
 /** @{ */
 /** \name Pointers to the header structures.
- *  All pointers except UIP_IP_BUF depend on uip_ext_len, which at
- *  packet reception, is the total length of the extension headers.
- *
- *  The pointer to ND6 options header also depends on nd6_opt_offset,
- *  which we set in each function.
- *
- *  Care should be taken when manipulating these buffers about the
- *  value of these length variables
  */
 
-#define UIP_IP_BUF                ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])  /**< Pointer to IP header */
-#define UIP_ICMP_BUF            ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])  /**< Pointer to ICMP header*/
 /**@{  Pointers to messages just after icmp header */
-#define UIP_ND6_RS_BUF            ((uip_nd6_rs *)&uip_buf[uip_l2_l3_icmp_hdr_len])
-#define UIP_ND6_RA_BUF            ((uip_nd6_ra *)&uip_buf[uip_l2_l3_icmp_hdr_len])
-#define UIP_ND6_NS_BUF            ((uip_nd6_ns *)&uip_buf[uip_l2_l3_icmp_hdr_len])
-#define UIP_ND6_NA_BUF            ((uip_nd6_na *)&uip_buf[uip_l2_l3_icmp_hdr_len])
+#define UIP_ND6_RS_BUF            ((uip_nd6_rs *)UIP_ICMP_PAYLOAD)
+#define UIP_ND6_RA_BUF            ((uip_nd6_ra *)UIP_ICMP_PAYLOAD)
+#define UIP_ND6_NS_BUF            ((uip_nd6_ns *)UIP_ICMP_PAYLOAD)
+#define UIP_ND6_NA_BUF            ((uip_nd6_na *)UIP_ICMP_PAYLOAD)
 /** @} */
 /** Pointer to ND option */
-#define UIP_ND6_OPT_HDR_BUF  ((uip_nd6_opt_hdr *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
-#define UIP_ND6_OPT_PREFIX_BUF ((uip_nd6_opt_prefix_info *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
-#define UIP_ND6_OPT_MTU_BUF ((uip_nd6_opt_mtu *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
-#define UIP_ND6_OPT_RDNSS_BUF ((uip_nd6_opt_dns *)&uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset])
+#define ND6_OPT(opt)                         ((unsigned char *)(UIP_ICMP_PAYLOAD + (opt)))
+#define ND6_OPT_HDR_BUF(opt)               ((uip_nd6_opt_hdr *)ND6_OPT(opt))
+#define ND6_OPT_PREFIX_BUF(opt)    ((uip_nd6_opt_prefix_info *)ND6_OPT(opt))
+#define ND6_OPT_MTU_BUF(opt)               ((uip_nd6_opt_mtu *)ND6_OPT(opt))
+#define ND6_OPT_RDNSS_BUF(opt)             ((uip_nd6_opt_dns *)ND6_OPT(opt))
 /** @} */
 
 #if UIP_ND6_SEND_NS || UIP_ND6_SEND_NA || UIP_ND6_SEND_RA || !UIP_CONF_ROUTER
@@ -203,14 +194,14 @@ ns_input(void)
   nd6_opt_offset = UIP_ND6_NS_LEN;
   while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
 #if UIP_CONF_IPV6_CHECKS
-    if(UIP_ND6_OPT_HDR_BUF->len == 0) {
+    if(ND6_OPT_HDR_BUF(nd6_opt_offset)->len == 0) {
       LOG_ERR("NS received is bad\n");
       goto discard;
     }
 #endif /* UIP_CONF_IPV6_CHECKS */
-    switch (UIP_ND6_OPT_HDR_BUF->type) {
+    switch (ND6_OPT_HDR_BUF(nd6_opt_offset)->type) {
     case UIP_ND6_OPT_SLLAO:
-      nd6_opt_llao = &uip_buf[uip_l2_l3_icmp_hdr_len + nd6_opt_offset];
+      nd6_opt_llao = &uip_buf[uip_l3_icmp_hdr_len + nd6_opt_offset];
 #if UIP_CONF_IPV6_CHECKS
       /* There must be NO option in a DAD NS */
       if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
@@ -252,7 +243,7 @@ ns_input(void)
       LOG_WARN("ND option not supported in NS");
       break;
     }
-    nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
+    nd6_opt_offset += (ND6_OPT_HDR_BUF(nd6_opt_offset)->len << 3);
   }
 
   addr = uip_ds6_addr_lookup(&UIP_ND6_NS_BUF->tgtipaddr);
@@ -323,12 +314,11 @@ create_na:
 #if UIP_CONF_ROUTER
     flags = flags | UIP_ND6_NA_FLAG_ROUTER;
 #endif
-  uip_ext_len = 0;
+  uipbuf_clear();
   UIP_IP_BUF->vtc = 0x60;
   UIP_IP_BUF->tcflow = 0;
   UIP_IP_BUF->flow = 0;
-  UIP_IP_BUF->len[0] = 0;       /* length will not be more than 255 */
-  UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN;
+  uipbuf_set_len_field(UIP_IP_BUF, UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN);
   UIP_IP_BUF->proto = UIP_PROTO_ICMP6;
   UIP_IP_BUF->ttl = UIP_ND6_HOP_LIMIT;
 
@@ -338,14 +328,13 @@ create_na:
   UIP_ND6_NA_BUF->flagsreserved = flags;
   memcpy(&UIP_ND6_NA_BUF->tgtipaddr, &addr->ipaddr, sizeof(uip_ipaddr_t));
 
-  create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NA_LEN],
+  create_llao(&uip_buf[uip_l3_icmp_hdr_len + UIP_ND6_NA_LEN],
               UIP_ND6_OPT_TLLAO);
 
   UIP_ICMP_BUF->icmpchksum = 0;
   UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
 
-  uip_len =
-    UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN;
+  uipbuf_set_len(UIP_IPH_LEN + UIP_ICMPH_LEN + UIP_ND6_NA_LEN + UIP_ND6_OPT_LLAO_LEN);
 
   UIP_STAT(++uip_stat.nd6.sent);
   LOG_INFO("Sending NA to ");
@@ -358,7 +347,7 @@ create_na:
   return;
 
 discard:
-  uip_clear_buf();
+  uipbuf_clear();
   return;
 }
 #endif /* UIP_ND6_SEND_NA */
@@ -369,7 +358,7 @@ discard:
 void
 uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
 {
-  uip_ext_len = 0;
+  uipbuf_clear();
   UIP_IP_BUF->vtc = 0x60;
   UIP_IP_BUF->tcflow = 0;
   UIP_IP_BUF->flow = 0;
@@ -385,7 +374,6 @@ uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
   UIP_ICMP_BUF->icode = 0;
   UIP_ND6_NS_BUF->reserved = 0;
   uip_ipaddr_copy((uip_ipaddr_t *) &UIP_ND6_NS_BUF->tgtipaddr, tgt);
-  UIP_IP_BUF->len[0] = 0;       /* length will not be more than 255 */
   /*
    * check if we add a SLLAO option: for DAD, MUST NOT, for NUD, MAY
    * (here yes), for Address resolution , MUST
@@ -398,13 +386,12 @@ uip_nd6_ns_output(uip_ipaddr_t * src, uip_ipaddr_t * dest, uip_ipaddr_t * tgt)
     }
     if (uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
       LOG_ERR("Dropping NS due to no suitable source address\n");
-      uip_clear_buf();
+      uipbuf_clear();
       return;
     }
-    UIP_IP_BUF->len[1] =
-      UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN;
+    uipbuf_set_len_field(UIP_IP_BUF, UIP_ICMPH_LEN + UIP_ND6_NS_LEN + UIP_ND6_OPT_LLAO_LEN);
 
-    create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_NS_LEN],
+    create_llao(&uip_buf[uip_l3_icmp_hdr_len + UIP_ND6_NS_LEN],
                 UIP_ND6_OPT_SLLAO);
 
     uip_len =
@@ -493,20 +480,20 @@ na_input(void)
   nd6_opt_llao = NULL;
   while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
 #if UIP_CONF_IPV6_CHECKS
-    if(UIP_ND6_OPT_HDR_BUF->len == 0) {
+    if(ND6_OPT_HDR_BUF(nd6_opt_offset)->len == 0) {
       LOG_ERR("NA received is bad\n");
       goto discard;
     }
 #endif /*UIP_CONF_IPV6_CHECKS */
-    switch (UIP_ND6_OPT_HDR_BUF->type) {
+    switch (ND6_OPT_HDR_BUF(nd6_opt_offset)->type) {
     case UIP_ND6_OPT_TLLAO:
-      nd6_opt_llao = (uint8_t *)UIP_ND6_OPT_HDR_BUF;
+      nd6_opt_llao = (uint8_t *)ND6_OPT_HDR_BUF(nd6_opt_offset);
       break;
     default:
       LOG_WARN("ND option not supported in NA\n");
       break;
     }
-    nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
+    nd6_opt_offset += (ND6_OPT_HDR_BUF(nd6_opt_offset)->len << 3);
   }
   addr = uip_ds6_addr_lookup(&UIP_ND6_NA_BUF->tgtipaddr);
   /* Message processing, including TLLAO if any */
@@ -605,7 +592,7 @@ na_input(void)
 #endif /*UIP_CONF_IPV6_QUEUE_PKT */
 
 discard:
-  uip_clear_buf();
+  uipbuf_clear();
   return;
 }
 #endif /* UIP_ND6_SEND_NS */
@@ -644,20 +631,20 @@ rs_input(void)
 
   while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
 #if UIP_CONF_IPV6_CHECKS
-    if(UIP_ND6_OPT_HDR_BUF->len == 0) {
+    if(ND6_OPT_HDR_BUF(nd6_opt_offset)->len == 0) {
       LOG_ERR("RS received is bad\n");
       goto discard;
     }
 #endif /*UIP_CONF_IPV6_CHECKS */
-    switch (UIP_ND6_OPT_HDR_BUF->type) {
+    switch (ND6_OPT_HDR_BUF(nd6_opt_offset)->type) {
     case UIP_ND6_OPT_SLLAO:
-      nd6_opt_llao = (uint8_t *)UIP_ND6_OPT_HDR_BUF;
+      nd6_opt_llao = (uint8_t *)ND6_OPT_HDR_BUF(nd6_opt_offset);
       break;
     default:
       LOG_WARN("ND option not supported in RS\n");
       break;
     }
-    nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
+    nd6_opt_offset += (ND6_OPT_HDR_BUF(nd6_opt_offset)->len << 3);
   }
   /* Options processing: only SLLAO */
   if(nd6_opt_llao != NULL) {
@@ -701,7 +688,7 @@ rs_input(void)
   uip_ds6_send_ra_sollicited();
 
 discard:
-  uip_clear_buf();
+  uipbuf_clear();
   return;
 }
 
@@ -746,31 +733,31 @@ uip_nd6_ra_output(uip_ipaddr_t * dest)
   for(prefix = uip_ds6_prefix_list;
       prefix < uip_ds6_prefix_list + UIP_DS6_PREFIX_NB; prefix++) {
     if((prefix->isused) && (prefix->advertise)) {
-      UIP_ND6_OPT_PREFIX_BUF->type = UIP_ND6_OPT_PREFIX_INFO;
-      UIP_ND6_OPT_PREFIX_BUF->len = UIP_ND6_OPT_PREFIX_INFO_LEN / 8;
-      UIP_ND6_OPT_PREFIX_BUF->preflen = prefix->length;
-      UIP_ND6_OPT_PREFIX_BUF->flagsreserved1 = prefix->l_a_reserved;
-      UIP_ND6_OPT_PREFIX_BUF->validlt = uip_htonl(prefix->vlifetime);
-      UIP_ND6_OPT_PREFIX_BUF->preferredlt = uip_htonl(prefix->plifetime);
-      UIP_ND6_OPT_PREFIX_BUF->reserved2 = 0;
-      uip_ipaddr_copy(&(UIP_ND6_OPT_PREFIX_BUF->prefix), &(prefix->ipaddr));
+      ND6_OPT_PREFIX_BUF(nd6_opt_offset)->type = UIP_ND6_OPT_PREFIX_INFO;
+      ND6_OPT_PREFIX_BUF(nd6_opt_offset)->len = UIP_ND6_OPT_PREFIX_INFO_LEN / 8;
+      ND6_OPT_PREFIX_BUF(nd6_opt_offset)->preflen = prefix->length;
+      ND6_OPT_PREFIX_BUF(nd6_opt_offset)->flagsreserved1 = prefix->l_a_reserved;
+      ND6_OPT_PREFIX_BUF(nd6_opt_offset)->validlt = uip_htonl(prefix->vlifetime);
+      ND6_OPT_PREFIX_BUF(nd6_opt_offset)->preferredlt = uip_htonl(prefix->plifetime);
+      ND6_OPT_PREFIX_BUF(nd6_opt_offset)->reserved2 = 0;
+      uip_ipaddr_copy(&(ND6_OPT_PREFIX_BUF(nd6_opt_offset)->prefix), &(prefix->ipaddr));
       nd6_opt_offset += UIP_ND6_OPT_PREFIX_INFO_LEN;
       uip_len += UIP_ND6_OPT_PREFIX_INFO_LEN;
     }
   }
 
   /* Source link-layer option */
-  create_llao((uint8_t *)UIP_ND6_OPT_HDR_BUF, UIP_ND6_OPT_SLLAO);
+  create_llao((uint8_t *)ND6_OPT_HDR_BUF(nd6_opt_offset), UIP_ND6_OPT_SLLAO);
 
   uip_len += UIP_ND6_OPT_LLAO_LEN;
   nd6_opt_offset += UIP_ND6_OPT_LLAO_LEN;
 
   /* MTU */
-  UIP_ND6_OPT_MTU_BUF->type = UIP_ND6_OPT_MTU;
-  UIP_ND6_OPT_MTU_BUF->len = UIP_ND6_OPT_MTU_LEN >> 3;
-  UIP_ND6_OPT_MTU_BUF->reserved = 0;
-  //UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(uip_ds6_if.link_mtu);
-  UIP_ND6_OPT_MTU_BUF->mtu = uip_htonl(1500);
+  ND6_OPT_MTU_BUF(nd6_opt_offset)->type = UIP_ND6_OPT_MTU;
+  ND6_OPT_MTU_BUF(nd6_opt_offset)->len = UIP_ND6_OPT_MTU_LEN >> 3;
+  ND6_OPT_MTU_BUF(nd6_opt_offset)->reserved = 0;
+  //ND6_OPT_MTU_BUF(nd6_opt_offset)->mtu = uip_htonl(uip_ds6_if.link_mtu);
+  ND6_OPT_MTU_BUF(nd6_opt_offset)->mtu = uip_htonl(1500);
 
   uip_len += UIP_ND6_OPT_MTU_LEN;
   nd6_opt_offset += UIP_ND6_OPT_MTU_LEN;
@@ -778,27 +765,26 @@ uip_nd6_ra_output(uip_ipaddr_t * dest)
 #if UIP_ND6_RA_RDNSS
   if(uip_nameserver_count() > 0) {
     uint8_t i = 0;
-    uip_ipaddr_t *ip = &UIP_ND6_OPT_RDNSS_BUF->ip;
+    uip_ipaddr_t *ip = &ND6_OPT_RDNSS_BUF(nd6_opt_offset)->ip;
     uip_ipaddr_t *dns = NULL;
-    UIP_ND6_OPT_RDNSS_BUF->type = UIP_ND6_OPT_RDNSS;
-    UIP_ND6_OPT_RDNSS_BUF->reserved = 0;
-    UIP_ND6_OPT_RDNSS_BUF->lifetime = uip_nameserver_next_expiration();
-    if(UIP_ND6_OPT_RDNSS_BUF->lifetime != UIP_NAMESERVER_INFINITE_LIFETIME) {
-      UIP_ND6_OPT_RDNSS_BUF->lifetime -= clock_seconds();
+    ND6_OPT_RDNSS_BUF(nd6_opt_offset)->type = UIP_ND6_OPT_RDNSS;
+    ND6_OPT_RDNSS_BUF(nd6_opt_offset)->reserved = 0;
+    ND6_OPT_RDNSS_BUF(nd6_opt_offset)->lifetime = uip_nameserver_next_expiration();
+    if(ND6_OPT_RDNSS_BUF(nd6_opt_offset)->lifetime != UIP_NAMESERVER_INFINITE_LIFETIME) {
+      ND6_OPT_RDNSS_BUF(nd6_opt_offset)->lifetime -= clock_seconds();
     }
     while((dns = uip_nameserver_get(i)) != NULL) {
       uip_ipaddr_copy(ip++, dns);
       i++;
     }
-    UIP_ND6_OPT_RDNSS_BUF->len = UIP_ND6_OPT_RDNSS_LEN + (i << 1);
+    ND6_OPT_RDNSS_BUF(nd6_opt_offset)->len = UIP_ND6_OPT_RDNSS_LEN + (i << 1);
     LOG_INFO("%d nameservers reported\n", i);
-    uip_len += UIP_ND6_OPT_RDNSS_BUF->len << 3;
-    nd6_opt_offset += UIP_ND6_OPT_RDNSS_BUF->len << 3;
+    uip_len += ND6_OPT_RDNSS_BUF(nd6_opt_offset)->len << 3;
+    nd6_opt_offset += ND6_OPT_RDNSS_BUF(nd6_opt_offset)->len << 3;
   }
 #endif /* UIP_ND6_RA_RDNSS */
 
-  UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
-  UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
+  uipbuf_set_len_field(UIP_IP_BUF, uip_len - UIP_IPH_LEN);
 
   /*ICMP checksum */
   UIP_ICMP_BUF->icmpchksum = 0;
@@ -829,17 +815,15 @@ uip_nd6_rs_output(void)
   uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
   UIP_ICMP_BUF->type = ICMP6_RS;
   UIP_ICMP_BUF->icode = 0;
-  UIP_IP_BUF->len[0] = 0;       /* length will not be more than 255 */
 
   if(uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr)) {
     UIP_IP_BUF->len[1] = UIP_ICMPH_LEN + UIP_ND6_RS_LEN;
     uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN;
   } else {
     uip_len = uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN;
-    UIP_IP_BUF->len[1] =
-      UIP_ICMPH_LEN + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN;
+    uipbuf_set_len_field(UIP_IP_BUF, UIP_ICMPH_LEN + UIP_ND6_RS_LEN + UIP_ND6_OPT_LLAO_LEN);
 
-    create_llao(&uip_buf[uip_l2_l3_icmp_hdr_len + UIP_ND6_RS_LEN],
+    create_llao(&uip_buf[uip_l3_icmp_hdr_len + UIP_ND6_RS_LEN],
                 UIP_ND6_OPT_SLLAO);
   }
 
@@ -904,14 +888,14 @@ ra_input(void)
   /* Options processing */
   nd6_opt_offset = UIP_ND6_RA_LEN;
   while(uip_l3_icmp_hdr_len + nd6_opt_offset < uip_len) {
-    if(UIP_ND6_OPT_HDR_BUF->len == 0) {
+    if(ND6_OPT_HDR_BUF(nd6_opt_offset)->len == 0) {
       LOG_ERR("RA received is bad");
       goto discard;
     }
-    switch (UIP_ND6_OPT_HDR_BUF->type) {
+    switch (ND6_OPT_HDR_BUF(nd6_opt_offset)->type) {
     case UIP_ND6_OPT_SLLAO:
       LOG_DBG("Processing SLLAO option in RA\n");
-      nd6_opt_llao = (uint8_t *) UIP_ND6_OPT_HDR_BUF;
+      nd6_opt_llao = (uint8_t *) ND6_OPT_HDR_BUF(nd6_opt_offset);
       nbr = uip_ds6_nbr_lookup(&UIP_IP_BUF->srcipaddr);
       if(!extract_lladdr_from_llao_aligned(&lladdr_aligned)) {
         /* failed to extract llao - discard packet */
@@ -944,11 +928,11 @@ ra_input(void)
     case UIP_ND6_OPT_MTU:
       LOG_DBG("Processing MTU option in RA\n");
       uip_ds6_if.link_mtu =
-        uip_ntohl(((uip_nd6_opt_mtu *) UIP_ND6_OPT_HDR_BUF)->mtu);
+        uip_ntohl(((uip_nd6_opt_mtu *) ND6_OPT_HDR_BUF(nd6_opt_offset))->mtu);
       break;
     case UIP_ND6_OPT_PREFIX_INFO:
       LOG_DBG("Processing PREFIX option in RA\n");
-      nd6_opt_prefix_info = (uip_nd6_opt_prefix_info *) UIP_ND6_OPT_HDR_BUF;
+      nd6_opt_prefix_info = (uip_nd6_opt_prefix_info *) ND6_OPT_HDR_BUF(nd6_opt_offset);
       if((uip_ntohl(nd6_opt_prefix_info->validlt) >=
           uip_ntohl(nd6_opt_prefix_info->preferredlt))
          && (!uip_is_addr_linklocal(&nd6_opt_prefix_info->prefix))) {
@@ -1035,14 +1019,14 @@ ra_input(void)
 #if UIP_ND6_RA_RDNSS
     case UIP_ND6_OPT_RDNSS:
       LOG_DBG("Processing RDNSS option\n");
-      uint8_t naddr = (UIP_ND6_OPT_RDNSS_BUF->len - 1) / 2;
-      uip_ipaddr_t *ip = (uip_ipaddr_t *)(&UIP_ND6_OPT_RDNSS_BUF->ip);
+      uint8_t naddr = (ND6_OPT_RDNSS_BUF(nd6_opt_offset)->len - 1) / 2;
+      uip_ipaddr_t *ip = (uip_ipaddr_t *)(&ND6_OPT_RDNSS_BUF(nd6_opt_offset)->ip);
       LOG_DBG("got %d nameservers\n", naddr);
       while(naddr-- > 0) {
         LOG_DBG("nameserver: ");
         LOG_DBG_6ADDR(ip);
-        LOG_DBG_(" lifetime: %"PRIx32"\n", uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime));
-        uip_nameserver_update(ip, uip_ntohl(UIP_ND6_OPT_RDNSS_BUF->lifetime));
+        LOG_DBG_(" lifetime: %"PRIx32"\n", uip_ntohl(ND6_OPT_RDNSS_BUF(nd6_opt_offset)->lifetime));
+        uip_nameserver_update(ip, uip_ntohl(ND6_OPT_RDNSS_BUF(nd6_opt_offset)->lifetime));
         ip++;
       }
       break;
@@ -1051,7 +1035,7 @@ ra_input(void)
       LOG_ERR("ND option not supported in RA\n");
       break;
     }
-    nd6_opt_offset += (UIP_ND6_OPT_HDR_BUF->len << 3);
+    nd6_opt_offset += (ND6_OPT_HDR_BUF(nd6_opt_offset)->len << 3);
   }
 
   defrt = uip_ds6_defrt_lookup(&UIP_IP_BUF->srcipaddr);
@@ -1092,7 +1076,7 @@ ra_input(void)
 #endif /*UIP_CONF_IPV6_QUEUE_PKT */
 
 discard:
-  uip_clear_buf();
+  uipbuf_clear();
   return;
 }
 #endif /* !UIP_CONF_ROUTER */
diff --git a/os/net/ipv6/uip-packetqueue.h b/os/net/ipv6/uip-packetqueue.h
index b265b1ecf8210c9ebab976739086fdc4373b879f..1deacb9baf1f629222c41cf8c727236bac0dfc65 100644
--- a/os/net/ipv6/uip-packetqueue.h
+++ b/os/net/ipv6/uip-packetqueue.h
@@ -7,7 +7,7 @@ struct uip_packetqueue_handle;
 
 struct uip_packetqueue_packet {
   struct uip_ds6_queued_packet *next;
-  uint8_t queue_buf[UIP_BUFSIZE - UIP_LLH_LEN];
+  uint8_t queue_buf[UIP_BUFSIZE];
   uint16_t queue_buf_len;
   struct ctimer lifetimer;
   struct uip_packetqueue_handle *handle;
diff --git a/os/net/ipv6/uip-udp-packet.c b/os/net/ipv6/uip-udp-packet.c
index 91ddf598c0842a7e4c4af783c8efac592cd0d08a..c5526b16246bf38fbc467d0c250d8346082b39ac 100644
--- a/os/net/ipv6/uip-udp-packet.c
+++ b/os/net/ipv6/uip-udp-packet.c
@@ -51,10 +51,10 @@ void
 uip_udp_packet_send(struct uip_udp_conn *c, const void *data, int len)
 {
 #if UIP_UDP
-  if(data != NULL && len <= (UIP_BUFSIZE - (UIP_LLH_LEN + UIP_IPUDPH_LEN))) {
+  if(data != NULL && len <= (UIP_BUFSIZE - UIP_IPUDPH_LEN)) {
     uip_udp_conn = c;
     uip_slen = len;
-    memmove(&uip_buf[UIP_LLH_LEN + UIP_IPUDPH_LEN], data, len);
+    memmove(&uip_buf[UIP_IPUDPH_LEN], data, len);
     uip_process(UIP_UDP_SEND_CONN);
 
 #if UIP_IPV6_MULTICAST
diff --git a/os/net/ipv6/uip.h b/os/net/ipv6/uip.h
index 9f5eb159daad4f1a952a236f82d1d0b367c93e18..0ac14fd5062c5a36030b12b1b2d5d52d364bcdc2 100755
--- a/os/net/ipv6/uip.h
+++ b/os/net/ipv6/uip.h
@@ -62,22 +62,24 @@
 
 #define UIP_IPUDPH_LEN (UIP_UDPH_LEN + UIP_IPH_LEN)   /* Size of IP + UDP header */
 #define UIP_IPTCPH_LEN (UIP_TCPH_LEN + UIP_IPH_LEN)   /* Size of IP + TCP header */
-#define UIP_TCPIP_HLEN UIP_IPTCPH_LEN
-#define UIP_IPICMPH_LEN (UIP_IPH_LEN + UIP_ICMPH_LEN) /* Size of ICMP + IP header */
-#define UIP_LLIPH_LEN (UIP_LLH_LEN + UIP_IPH_LEN)     /* Size of L2 + IP header */
-#if NETSTACK_CONF_WITH_IPV6
-/**
- * The sums below are quite used in ND. When used for uip_buf, we
- * include link layer length when used for uip_len, we do not, hence
- * we need values with and without LLH_LEN we do not use capital
- * letters as these values are variable
- */
-#define uip_l2_l3_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len)
-#define uip_l2_l3_icmp_hdr_len (UIP_LLH_LEN + UIP_IPH_LEN + uip_ext_len + UIP_ICMPH_LEN)
-#define uip_l3_hdr_len (UIP_IPH_LEN + uip_ext_len)
+
 #define uip_l3_icmp_hdr_len (UIP_IPH_LEN + uip_ext_len + UIP_ICMPH_LEN)
-#endif /*NETSTACK_CONF_WITH_IPV6*/
 
+/**
+ * Direct access to IPv6 header
+ */
+#define UIP_IP_BUF                             ((struct uip_ip_hdr *)uip_buf)
+#define UIP_IP_PAYLOAD(ext)                        ((unsigned char *)uip_buf + UIP_IPH_LEN + (ext))
+
+/**
+ * Direct access to ICMP, UDP, and TCP headers and payload, with implicit ext header offset (global uip_ext_len)
+ */
+#define UIP_ICMP_BUF                         ((struct uip_icmp_hdr *)UIP_IP_PAYLOAD(uip_ext_len))
+#define UIP_ICMP_PAYLOAD                           ((unsigned char *)UIP_IP_PAYLOAD(uip_ext_len) + UIP_ICMPH_LEN)
+#define UIP_UDP_BUF                           ((struct uip_udp_hdr *)UIP_IP_PAYLOAD(uip_ext_len))
+#define UIP_UDP_PAYLOAD                            ((unsigned char *)UIP_IP_PAYLOAD(uip_ext_len) + UIP_UDPH_LEN)
+#define UIP_TCP_BUF                           ((struct uip_tcp_hdr *)UIP_IP_PAYLOAD(uip_ext_len))
+#define UIP_TCP_PAYLOAD                            ((unsigned char *)UIP_IP_PAYLOAD(uip_ext_len) + UIP_TCPH_LEN)
 
 #include "net/ipv6/uipopt.h"
 #include "net/ipv6/uipbuf.h"
@@ -100,12 +102,7 @@ typedef union uip_ip6addr_t {
   uint16_t u16[8];
 } uip_ip6addr_t;
 
-#if NETSTACK_CONF_WITH_IPV6
 typedef uip_ip6addr_t uip_ipaddr_t;
-#else /* NETSTACK_CONF_WITH_IPV6 */
-typedef uip_ip4addr_t uip_ipaddr_t;
-#endif /* NETSTACK_CONF_WITH_IPV6 */
-
 
 /*---------------------------------------------------------------------------*/
 #define UIP_802154_SHORTADDR_LEN 2
@@ -1048,11 +1045,7 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport);
                                        (addr1)->u16[1] == (addr2)->u16[1])
 #define uip_ip6addr_cmp(addr1, addr2) (memcmp(addr1, addr2, sizeof(uip_ip6addr_t)) == 0)
 
-#if NETSTACK_CONF_WITH_IPV6
 #define uip_ipaddr_cmp(addr1, addr2) uip_ip6addr_cmp(addr1, addr2)
-#else /* NETSTACK_CONF_WITH_IPV6 */
-#define uip_ipaddr_cmp(addr1, addr2) uip_ip4addr_cmp(addr1, addr2)
-#endif /* NETSTACK_CONF_WITH_IPV6 */
 
 /**
  * Compare two IP addresses with netmasks
@@ -1307,32 +1300,17 @@ extern uint16_t uip_len;
 /**
  * The length of the extension headers
  */
-extern uint8_t uip_ext_len;
+extern uint16_t uip_ext_len;
+
+/** The final protocol after IPv6 extension headers:
+  * UIP_PROTO_TCP, UIP_PROTO_UDP or UIP_PROTO_ICMP6 */
+extern uint8_t uip_last_proto;
 /** @} */
 
 #if UIP_URGDATA > 0
 extern uint16_t uip_urglen, uip_surglen;
 #endif /* UIP_URGDATA > 0 */
 
-/*
- * Clear uIP buffer
- *
- * This function clears the uIP buffer by reseting the uip_len and
- * uip_ext_len pointers.
- */
-#if NETSTACK_CONF_WITH_IPV6
-#define uip_clear_buf() { \
-  uip_len = 0; \
-  uip_ext_len = 0; \
-  uipbuf_clear_attr();\
-}
-#else /*NETSTACK_CONF_WITH_IPV6*/
-#define uip_clear_buf() { \
-  uip_len = 0; \
-  uipbuf_clear_attr();\
-}
-#endif /*NETSTACK_CONF_WITH_IPV6*/
-
 /**
  * Representation of a uIP TCP connection.
  *
@@ -1494,13 +1472,11 @@ struct uip_stats {
                                checksum. */
   } udp;                  /**< UDP statistics. */
 #endif /* UIP_UDP */
-#if NETSTACK_CONF_WITH_IPV6
   struct {
     uip_stats_t drop;     /**< Number of dropped ND6 packets. */
     uip_stats_t recv;     /**< Number of recived ND6 packets */
     uip_stats_t sent;     /**< Number of sent ND6 packets */
   } nd6;
-#endif /*NETSTACK_CONF_WITH_IPV6*/
 };
 
 
@@ -1619,113 +1595,14 @@ void uip_process(uint8_t flag);
 
 #define UIP_STOPPED      16
 
-/* The TCP and IP headers. */
-struct uip_tcpip_hdr {
-#if NETSTACK_CONF_WITH_IPV6
-  /* IPv6 header. */
-  uint8_t vtc,
-    tcflow;
-  uint16_t flow;
-  uint8_t len[2];
-  uint8_t proto, ttl;
-  uip_ip6addr_t srcipaddr, destipaddr;
-#else /* NETSTACK_CONF_WITH_IPV6 */
-  /* IPv4 header. */
-  uint8_t vhl,
-    tos,
-    len[2],
-    ipid[2],
-    ipoffset[2],
-    ttl,
-    proto;
-  uint16_t ipchksum;
-  uip_ipaddr_t srcipaddr, destipaddr;
-#endif /* NETSTACK_CONF_WITH_IPV6 */
-
-  /* TCP header. */
-  uint16_t srcport,
-    destport;
-  uint8_t seqno[4],
-    ackno[4],
-    tcpoffset,
-    flags,
-    wnd[2];
-  uint16_t tcpchksum;
-  uint8_t urgp[2];
-  uint8_t optdata[4];
-};
-
-/* The ICMP and IP headers. */
-struct uip_icmpip_hdr {
-#if NETSTACK_CONF_WITH_IPV6
-  /* IPv6 header. */
-  uint8_t vtc,
-    tcf;
-  uint16_t flow;
-  uint8_t len[2];
-  uint8_t proto, ttl;
-  uip_ip6addr_t srcipaddr, destipaddr;
-#else /* NETSTACK_CONF_WITH_IPV6 */
-  /* IPv4 header. */
-  uint8_t vhl,
-    tos,
-    len[2],
-    ipid[2],
-    ipoffset[2],
-    ttl,
-    proto;
-  uint16_t ipchksum;
-  uip_ipaddr_t srcipaddr, destipaddr;
-#endif /* NETSTACK_CONF_WITH_IPV6 */
-
-  /* ICMP header. */
-  uint8_t type, icode;
-  uint16_t icmpchksum;
-#if !NETSTACK_CONF_WITH_IPV6
-  uint16_t id, seqno;
-  uint8_t payload[1];
-#endif /* !NETSTACK_CONF_WITH_IPV6 */
-};
-
-
-/* The UDP and IP headers. */
-struct uip_udpip_hdr {
-#if NETSTACK_CONF_WITH_IPV6
-  /* IPv6 header. */
-  uint8_t vtc,
-    tcf;
-  uint16_t flow;
-  uint8_t len[2];
-  uint8_t proto, ttl;
-  uip_ip6addr_t srcipaddr, destipaddr;
-#else /* NETSTACK_CONF_WITH_IPV6 */
-  /* IP header. */
-  uint8_t vhl,
-    tos,
-    len[2],
-    ipid[2],
-    ipoffset[2],
-    ttl,
-    proto;
-  uint16_t ipchksum;
-  uip_ipaddr_t srcipaddr, destipaddr;
-#endif /* NETSTACK_CONF_WITH_IPV6 */
-
-  /* UDP header. */
-  uint16_t srcport,
-    destport;
-  uint16_t udplen;
-  uint16_t udpchksum;
-};
-
 /*
  * In IPv6 the length of the L3 headers before the transport header is
  * not fixed, due to the possibility to include extension option headers
  * after the IP header. hence we split here L3 and L4 headers
  */
 /* The IP header */
+
 struct uip_ip_hdr {
-#if NETSTACK_CONF_WITH_IPV6
   /* IPV6 header */
   uint8_t vtc;
   uint8_t tcflow;
@@ -1733,18 +1610,6 @@ struct uip_ip_hdr {
   uint8_t len[2];
   uint8_t proto, ttl;
   uip_ip6addr_t srcipaddr, destipaddr;
-#else /* NETSTACK_CONF_WITH_IPV6 */
-  /* IPV4 header */
-  uint8_t vhl,
-    tos,
-    len[2],
-    ipid[2],
-    ipoffset[2],
-    ttl,
-    proto;
-  uint16_t ipchksum;
-  uip_ipaddr_t srcipaddr, destipaddr;
-#endif /* NETSTACK_CONF_WITH_IPV6 */
 };
 
 
@@ -1860,9 +1725,6 @@ struct uip_tcp_hdr {
 struct uip_icmp_hdr {
   uint8_t type, icode;
   uint16_t icmpchksum;
-#if !NETSTACK_CONF_WITH_IPV6
-  uint16_t id, seqno;
-#endif /* !NETSTACK_CONF_WITH_IPV6 */
 };
 
 
@@ -1889,8 +1751,7 @@ struct uip_udp_hdr {
  *
  * \hideinitializer
  */
-#define UIP_APPDATA_SIZE (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
-#define UIP_APPDATA_PTR (void *)&uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN]
+#define UIP_APPDATA_SIZE (UIP_BUFSIZE - UIP_IPTCPH_LEN)
 
 #define UIP_PROTO_ICMP  1
 #define UIP_PROTO_TCP   6
@@ -1898,7 +1759,6 @@ struct uip_udp_hdr {
 #define UIP_PROTO_ICMP6 58
 
 
-#if NETSTACK_CONF_WITH_IPV6
 /** @{ */
 /** \brief  extension headers types */
 #define UIP_PROTO_HBHO        0
@@ -1908,13 +1768,14 @@ struct uip_udp_hdr {
 #define UIP_PROTO_NONE        59
 /** @} */
 
-#define uip_is_proto_ext_hdr(proto) (proto == UIP_PROTO_HBHO || proto == UIP_PROTO_DESTO || proto == UIP_PROTO_ROUTING || proto == UIP_PROTO_FRAG || proto == UIP_PROTO_NONE)
+#define uip_is_proto_ext_hdr(proto) ((proto) != UIP_PROTO_TCP && (proto) != UIP_PROTO_UDP && (proto) != UIP_PROTO_ICMP6)
 
 /** @{ */
 /** \brief  Destination and Hop By Hop extension headers option types */
 #define UIP_EXT_HDR_OPT_PAD1  0
 #define UIP_EXT_HDR_OPT_PADN  1
 #define UIP_EXT_HDR_OPT_RPL   0x63
+#define UIP_EXT_HDR_OPT_MPL   0x6D
 
 /** @} */
 
@@ -1937,9 +1798,6 @@ struct uip_udp_hdr {
 /** @} */
 
 
-#endif /* NETSTACK_CONF_WITH_IPV6 */
-
-
 #if UIP_FIXEDADDR
 extern const uip_ipaddr_t uip_hostaddr, uip_netmask, uip_draddr;
 #else /* UIP_FIXEDADDR */
@@ -1954,10 +1812,6 @@ extern const uip_lladdr_t uip_lladdr;
 extern uip_lladdr_t uip_lladdr;
 #endif
 
-
-
-
-#if NETSTACK_CONF_WITH_IPV6
 /** Length of the link local prefix */
 #define UIP_LLPREF_LEN     10
 
@@ -2174,8 +2028,6 @@ extern uip_lladdr_t uip_lladdr;
    (((a)->u8[14])  == ((b)->u8[14])) &&                 \
    (((a)->u8[15])  == ((b)->u8[15])))
 
-#endif /*NETSTACK_CONF_WITH_IPV6*/
-
 /**
  * A non-error message that indicates that a packet should be
  * processed locally.
@@ -2288,6 +2140,13 @@ uint16_t uip_udpchksum(void);
  */
 uint16_t uip_icmp6chksum(void);
 
+/**
+ * Removes all IPv6 extension headers from uip_buf, updates length fields
+ * (uip_len and uip_ext_len)
+ *
+ * \return true upon success, false otherwise.
+ */
+bool uip_remove_ext_hdr(void);
 
 #endif /* UIP_H_ */
 
diff --git a/os/net/ipv6/uip6.c b/os/net/ipv6/uip6.c
index dfbec52b703989febd0b1147c5a69c36425e2722..bbb85b781899ec6797b6c00c0e5d91b68a178aff 100644
--- a/os/net/ipv6/uip6.c
+++ b/os/net/ipv6/uip6.c
@@ -114,46 +114,26 @@ uip_lladdr_t uip_lladdr = {{0x00,0x06,0x98,0x00,0x02,0x32}};
  * @{
  */
 /*---------------------------------------------------------------------------*/
-/**
- * \brief Type of the next header in IPv6 header or extension headers
- *
- * Can be the next header field in the IPv6 header or in an extension header.
- * When doing fragment reassembly, we must change the value of the next header
- * field in the header before the fragmentation header, hence we need a pointer
- * to this field.
- */
-uint8_t *uip_next_hdr;
 /** \brief bitmap we use to record which IPv6 headers we have already seen */
 uint8_t uip_ext_bitmap = 0;
 /**
- * \brief length of the extension headers read. updated each time we process
- * a header
+ * \brief Total length of all IPv6 extension headers
  */
-uint8_t uip_ext_len = 0;
-/** \brief length of the header options read */
-uint8_t uip_ext_opt_offset = 0;
+uint16_t uip_ext_len = 0;
+/** \brief The final protocol after IPv6 extension headers:
+  * UIP_PROTO_TCP, UIP_PROTO_UDP or UIP_PROTO_ICMP6 */
+uint8_t uip_last_proto = 0;
 /** @} */
 
 /*---------------------------------------------------------------------------*/
 /* Buffers                                                                   */
 /*---------------------------------------------------------------------------*/
 /**
- * \name Buffer defines
+ * \name Reassembly buffer definition
  * @{
  */
-#define FBUF                             ((struct uip_tcpip_hdr *)&uip_reassbuf[0])
-#define UIP_IP_BUF                          ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-#define UIP_ICMP_BUF                      ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_UDP_BUF                        ((struct uip_udp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN])
-#define UIP_TCP_BUF                        ((struct uip_tcp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN])
-#define UIP_EXT_BUF                        ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_ROUTING_BUF                ((struct uip_routing_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_FRAG_BUF                      ((struct uip_frag_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_HBHO_BUF                      ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_DESTO_BUF                    ((struct uip_desto_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_EXT_HDR_OPT_BUF            ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
-#define UIP_EXT_HDR_OPT_PADN_BUF  ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
-#define UIP_ICMP6_ERROR_BUF            ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len])
+#define FBUF                                ((struct uip_ip_hdr *)&uip_reassbuf[0])
+
 /** @} */
 /**
  * \name Buffer variables
@@ -341,7 +321,7 @@ uip_ipchksum(void)
 {
   uint16_t sum;
 
-  sum = chksum(0, &uip_buf[UIP_LLH_LEN], UIP_IPH_LEN);
+  sum = chksum(0, uip_buf, UIP_IPH_LEN);
   LOG_DBG("uip_ipchksum: sum 0x%04x\n", sum);
   return (sum == 0) ? 0xffff : uip_htons(sum);
 }
@@ -362,10 +342,10 @@ upper_layer_chksum(uint8_t proto)
   volatile uint16_t upper_layer_len;
   uint16_t sum;
 
-  upper_layer_len = (((uint16_t)(UIP_IP_BUF->len[0]) << 8) + UIP_IP_BUF->len[1] - uip_ext_len);
+  upper_layer_len = uipbuf_get_len_field(UIP_IP_BUF) - uip_ext_len;
 
   LOG_DBG("Upper layer checksum len: %d from: %d\n", upper_layer_len,
-         UIP_IPH_LEN + UIP_LLH_LEN + uip_ext_len);
+         (int)(UIP_IP_PAYLOAD(uip_ext_len) - uip_buf));
 
   /* First sum pseudoheader. */
   /* IP protocol and length fields. This addition cannot carry. */
@@ -373,9 +353,8 @@ upper_layer_chksum(uint8_t proto)
   /* Sum IP source and destination addresses. */
   sum = chksum(sum, (uint8_t *)&UIP_IP_BUF->srcipaddr, 2 * sizeof(uip_ipaddr_t));
 
-  /* Sum TCP header and data. */
-  sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN + uip_ext_len],
-               upper_layer_len);
+  /* Sum upper-layer header and data. */
+  sum = chksum(sum, UIP_IP_PAYLOAD(uip_ext_len), upper_layer_len);
 
   return (sum == 0) ? 0xffff : uip_htons(sum);
 }
@@ -409,6 +388,7 @@ uip_init(void)
 {
   int c;
 
+  uipbuf_init();
   uip_ds6_init();
   uip_icmp6_init();
   uip_nd6_init();
@@ -509,31 +489,32 @@ uip_connect(const uip_ipaddr_t *ripaddr, uint16_t rport)
 }
 #endif /* UIP_TCP && UIP_ACTIVE_OPEN */
 /*---------------------------------------------------------------------------*/
-void
-remove_ext_hdr(void)
+bool
+uip_remove_ext_hdr(void)
 {
-  int last_uip_ext_len;
   /* Remove ext header before TCP/UDP processing. */
   if(uip_ext_len > 0) {
-    LOG_DBG("Cutting ext-header before processing (extlen: %d, uiplen: %d)\n",
+    LOG_DBG("Removing IPv6 extension headers (extlen: %d, uiplen: %d)\n",
            uip_ext_len, uip_len);
     if(uip_len < UIP_IPH_LEN + uip_ext_len) {
-      LOG_ERR("ERROR: uip_len too short compared to ext len\n");
-      uip_clear_buf();
-      return;
+      LOG_ERR("uip_len too short compared to ext len\n");
+      uipbuf_clear();
+      return false;
     }
-    last_uip_ext_len = uip_ext_len;
-    uip_ext_len = 0;
-    UIP_IP_BUF->proto = UIP_EXT_BUF->next;
-    memmove(((uint8_t *)UIP_TCP_BUF), (uint8_t *)UIP_TCP_BUF + last_uip_ext_len,
-	    uip_len - UIP_IPH_LEN - last_uip_ext_len);
 
-    uip_len -= last_uip_ext_len;
+    /* Set proto */
+    UIP_IP_BUF->proto = uip_last_proto;
+    /* Move IP payload to the "left"*/
+    memmove(UIP_IP_PAYLOAD(0), UIP_IP_PAYLOAD(uip_ext_len),
+	    uip_len - UIP_IPH_LEN - uip_ext_len);
 
     /* Update the IP length. */
-    UIP_IP_BUF->len[0] = (uip_len - UIP_IPH_LEN) >> 8;
-    UIP_IP_BUF->len[1] = (uip_len - UIP_IPH_LEN) & 0xff;
+    if(uipbuf_add_ext_hdr(-uip_ext_len) == false) {
+      return false;
+    }
+    uipbuf_set_len_field(UIP_IP_BUF, uip_len - UIP_IPH_LEN);
   }
+  return true;
 }
 /*---------------------------------------------------------------------------*/
 #if UIP_UDP
@@ -610,7 +591,7 @@ uip_listen(uint16_t port)
 /*---------------------------------------------------------------------------*/
 
 #if UIP_CONF_IPV6_REASSEMBLY
-#define UIP_REASS_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN)
+#define UIP_REASS_BUFSIZE (UIP_BUFSIZE)
 
 static uint8_t uip_reassbuf[UIP_REASS_BUFSIZE];
 
@@ -646,11 +627,12 @@ static uint32_t uip_id; /* For every packet that is to be fragmented, the source
 #define IP_MF   0x0001
 
 static uint16_t
-uip_reass(void)
+uip_reass(uint8_t *prev_proto_ptr)
 {
   uint16_t offset=0;
   uint16_t len;
   uint16_t i;
+  struct uip_frag_hdr *frag_buf = (struct uip_frag_hdr *)UIP_IP_PAYLOAD(uip_ext_len);
 
   /* If ip_reasstmr is zero, no packet is present in the buffer */
   /* We first write the unfragmentable part of IP header into the reassembly
@@ -662,7 +644,7 @@ uip_reass(void)
     etimer_set(&uip_reass_timer, UIP_REASS_MAXAGE*CLOCK_SECOND);
     uip_reass_on = 1;
     uip_reassflags = 0;
-    uip_id = UIP_FRAG_BUF->id;
+    uip_id = frag_buf->id;
     /* Clear the bitmap. */
     memset(uip_reassbitmap, 0, sizeof(uip_reassbitmap));
   }
@@ -673,9 +655,9 @@ uip_reass(void)
    */
   if(uip_ipaddr_cmp(&FBUF->srcipaddr, &UIP_IP_BUF->srcipaddr) &&
      uip_ipaddr_cmp(&FBUF->destipaddr, &UIP_IP_BUF->destipaddr) &&
-     UIP_FRAG_BUF->id == uip_id) {
+     frag_buf->id == uip_id) {
     len = uip_len - uip_ext_len - UIP_IPH_LEN - UIP_FRAGH_LEN;
-    offset = (uip_ntohs(UIP_FRAG_BUF->offsetresmore) & 0xfff8);
+    offset = (uip_ntohs(frag_buf->offsetresmore) & 0xfff8);
     /* in byte, originaly in multiple of 8 bytes*/
     LOG_INFO("len %d\n", len);
     LOG_INFO("offset %d\n", offset);
@@ -686,7 +668,7 @@ uip_reass(void)
        * Part is obtained from the Next Header field of the first
        * fragment's Fragment header.
        */
-      *uip_next_hdr = UIP_FRAG_BUF->next;
+      *prev_proto_ptr = frag_buf->next;
       memcpy(FBUF, UIP_IP_BUF, uip_ext_len + UIP_IPH_LEN);
       LOG_INFO("src ");
       LOG_INFO_6ADDR(&FBUF->srcipaddr);
@@ -707,7 +689,7 @@ uip_reass(void)
 
     /* If this fragment has the More Fragments flag set to zero, it is the
        last fragment*/
-    if((uip_ntohs(UIP_FRAG_BUF->offsetresmore) & IP_MF) == 0) {
+    if((uip_ntohs(frag_buf->offsetresmore) & IP_MF) == 0) {
       uip_reassflags |= UIP_REASS_FLAG_LASTFRAG;
       /*calculate the size of the entire packet*/
       uip_reasslen = offset + len;
@@ -731,7 +713,7 @@ uip_reass(void)
     /* Copy the fragment into the reassembly buffer, at the right
        offset. */
     memcpy((uint8_t *)FBUF + UIP_IPH_LEN + uip_ext_len + offset,
-           (uint8_t *)UIP_FRAG_BUF + UIP_FRAGH_LEN, len);
+           (uint8_t *)frag_buf + UIP_FRAGH_LEN, len);
 
     /* Update the bitmap. */
     if(offset >> 6 == (offset + len) >> 6) {
@@ -777,10 +759,8 @@ uip_reass(void)
 
       uip_reasslen += UIP_IPH_LEN + uip_ext_len;
       memcpy(UIP_IP_BUF, FBUF, uip_reasslen);
-      UIP_IP_BUF->len[0] = ((uip_reasslen - UIP_IPH_LEN) >> 8);
-      UIP_IP_BUF->len[1] = ((uip_reasslen - UIP_IPH_LEN) & 0xff);
-      LOG_INFO("reassembled packet %d (%d)\n", uip_reasslen,
-             (UIP_IP_BUF->len[0] << 8) | UIP_IP_BUF->len[1]);
+      uipbuf_set_len_field(UIP_IP_BUF, uip_reasslen - UIP_IPH_LEN);
+      LOG_INFO("reassembled packet %d (%d)\n", uip_reasslen, uipbuf_get_len_field(UIP_IP_BUF));
 
       return uip_reasslen;
 
@@ -810,7 +790,7 @@ uip_reass_over(void)
      * any RFC, we decided not to include it as it reduces the size of
      * the packet.
      */
-    uip_clear_buf();
+    uipbuf_clear();
     memcpy(UIP_IP_BUF, FBUF, UIP_IPH_LEN); /* copy the header for src
                                               and dest address*/
     uip_icmp6_error_output(ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_REASSEMBLY, 0);
@@ -840,16 +820,29 @@ uip_add_rcv_nxt(uint16_t n)
  * \brief Process the options in Destination and Hop By Hop extension headers
  */
 static uint8_t
-ext_hdr_options_process(void)
+ext_hdr_options_process(uint8_t *ext_buf)
 {
   /*
    * Length field in the extension header: length of the header in units of
    * 8 bytes, excluding the first 8 bytes
    * length field in an option : the length of data in the option
    */
-  uip_ext_opt_offset = 2;
-  while(uip_ext_opt_offset < ((UIP_EXT_BUF->len << 3) + 8)) {
-    switch(UIP_EXT_HDR_OPT_BUF->type) {
+  uint16_t opt_offset = 2; /* 2 first bytes in ext header */
+  struct uip_hbho_hdr *ext_hdr = (struct uip_hbho_hdr *)ext_buf;
+  uint16_t ext_hdr_len = (ext_hdr->len << 3) + 8;
+
+  while(opt_offset + 2 <= ext_hdr_len) { /* + 2 for opt header */
+    struct uip_ext_hdr_opt *opt_hdr = (struct uip_ext_hdr_opt *)(ext_buf + opt_offset);
+    uint16_t opt_len = opt_hdr->len + 2;
+
+    if(opt_offset + opt_len > ext_hdr_len) {
+      LOG_ERR("Extension header option too long: dropping packet\n");
+      uip_icmp6_error_output(ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION,
+          (ext_buf + opt_offset) - uip_buf);
+      return 2;
+    }
+
+    switch(opt_hdr->type) {
     /*
      * for now we do not support any options except padding ones
      * PAD1 does not make sense as the header must be 8bytes aligned,
@@ -857,11 +850,11 @@ ext_hdr_options_process(void)
      */
     case UIP_EXT_HDR_OPT_PAD1:
       LOG_DBG("Processing PAD1 option\n");
-      uip_ext_opt_offset += 1;
+      opt_offset += 1;
       break;
     case UIP_EXT_HDR_OPT_PADN:
       LOG_DBG("Processing PADN option\n");
-      uip_ext_opt_offset += UIP_EXT_HDR_OPT_PADN_BUF->opt_len + 2;
+      opt_offset += opt_len;
       break;
     case UIP_EXT_HDR_OPT_RPL:
       /* Fixes situation when a node that is not using RPL
@@ -872,12 +865,23 @@ ext_hdr_options_process(void)
        * Using this fix, the header is ignored, and the next header (if
        * present) is processed.
        */
-      if(!NETSTACK_ROUTING.ext_header_hbh_update(uip_ext_opt_offset)) {
+      LOG_DBG("Processing RPL option\n");
+      if(!NETSTACK_ROUTING.ext_header_hbh_update(ext_buf, opt_offset)) {
         LOG_ERR("RPL Option Error: Dropping Packet\n");
         return 1;
       }
-      uip_ext_opt_offset += (UIP_EXT_HDR_OPT_BUF->len) + 2;
-      return 0;
+      opt_offset += opt_len;
+      break;
+#if UIP_MCAST6_ENGINE == UIP_MCAST6_ENGINE_MPL
+    case UIP_EXT_HDR_OPT_MPL:
+      /* MPL (RFC7731) Introduces the 0x6D hop by hop option. Hosts that do not
+      *  recognise the option should drop the packet. Since we want to keep the packet,
+      *  we want to process the option and not revert to the default case.
+      */
+      LOG_DBG("Processing MPL option\n");
+      opt_offset += opt_len + opt_len;
+      break;
+#endif
     default:
       /*
        * check the two highest order bits of the option
@@ -892,8 +896,8 @@ ext_hdr_options_process(void)
        *   Problem, Code 2, message to the packet's Source Address,
        *   pointing to the unrecognized Option Type.
        */
-      LOG_DBG("MSB %x\n", UIP_EXT_HDR_OPT_BUF->type);
-      switch(UIP_EXT_HDR_OPT_BUF->type & 0xC0) {
+      LOG_DBG("Unrecognized option, MSB 0x%x\n", opt_hdr->type);
+      switch(opt_hdr->type & 0xC0) {
       case 0:
         break;
       case 0x40:
@@ -904,22 +908,49 @@ ext_hdr_options_process(void)
         }
       case 0x80:
         uip_icmp6_error_output(ICMP6_PARAM_PROB, ICMP6_PARAMPROB_OPTION,
-            (uint32_t)UIP_IPH_LEN + uip_ext_len + uip_ext_opt_offset);
+            (ext_buf + opt_offset) - uip_buf);
         return 2;
       }
       /* in the cases were we did not discard, update ext_opt* */
-      uip_ext_opt_offset += UIP_EXT_HDR_OPT_BUF->len + 2;
+      opt_offset += opt_len;
       break;
     }
   }
   return 0;
 }
-
-
+/*---------------------------------------------------------------------------*/
+static bool
+uip_check_mtu(void)
+{
+  if(uip_len > UIP_LINK_MTU) {
+    uip_icmp6_error_output(ICMP6_PACKET_TOO_BIG, 0, UIP_LINK_MTU);
+    UIP_STAT(++uip_stat.ip.drop);
+    return false;
+  } else {
+    return true;
+  }
+}
+/*---------------------------------------------------------------------------*/
+static bool
+uip_update_ttl(void)
+{
+  if(UIP_IP_BUF->ttl <= 1) {
+    uip_icmp6_error_output(ICMP6_TIME_EXCEEDED, ICMP6_TIME_EXCEED_TRANSIT, 0);
+    UIP_STAT(++uip_stat.ip.drop);
+    return false;
+  } else {
+    UIP_IP_BUF->ttl = UIP_IP_BUF->ttl - 1;
+    return true;
+  }
+}
 /*---------------------------------------------------------------------------*/
 void
 uip_process(uint8_t flag)
 {
+  uint8_t *last_header;
+  uint8_t protocol;
+  uint8_t *next_header;
+  struct uip_ext_hdr *ext_ptr;
 #if UIP_TCP
   int c;
   uint16_t tmp16;
@@ -931,7 +962,7 @@ uip_process(uint8_t flag)
     goto udp_send;
   }
 #endif /* UIP_UDP */
-  uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN];
+  uip_sappdata = uip_appdata = &uip_buf[UIP_IPTCPH_LEN];
 
   /* Check if we were invoked because of a poll request for a
      particular connection. */
@@ -955,7 +986,7 @@ uip_process(uint8_t flag)
   } else if(flag == UIP_TIMER) {
     /* Reset the length variables. */
 #if UIP_TCP
-    uip_clear_buf();
+    uipbuf_clear();
     uip_slen = 0;
 
     /* Increase the initial sequence number. */
@@ -1068,7 +1099,7 @@ uip_process(uint8_t flag)
   if(flag == UIP_UDP_TIMER) {
     if(uip_udp_conn->lport != 0) {
       uip_conn = NULL;
-      uip_sappdata = uip_appdata = &uip_buf[UIP_IPUDPH_LEN + UIP_LLH_LEN];
+      uip_sappdata = uip_appdata = &uip_buf[UIP_IPUDPH_LEN];
       uip_len = uip_slen = 0;
       uip_flags = UIP_POLL;
       UIP_UDP_APPCALL();
@@ -1085,6 +1116,13 @@ uip_process(uint8_t flag)
 
   /* Start of IP input header processing code. */
 
+  /* First check that we have received a full IPv6 header. */
+  if(uip_len < UIP_IPH_LEN) {
+    UIP_STAT(++uip_stat.ip.drop);
+    LOG_WARN("incomplete IPv6 header received (%d bytes)\n", (int)uip_len);
+    goto drop;
+  }
+
   /* Check validity of the IP header. */
   if((UIP_IP_BUF->vtc & 0xf0) != 0x60)  { /* IP version and header length. */
     UIP_STAT(++uip_stat.ip.drop);
@@ -1092,32 +1130,50 @@ uip_process(uint8_t flag)
     LOG_ERR("invalid version\n");
     goto drop;
   }
+
   /*
    * Check the size of the packet. If the size reported to us in
    * uip_len is smaller the size reported in the IP header, we assume
-   * that the packet has been corrupted in transit. If the size of
-   * uip_len is larger than the size reported in the IP packet header,
-   * the packet has been padded and we set uip_len to the correct
-   * value..
+   * that the packet has been corrupted in transit.
+   *
+   * If the size of uip_len is larger than the size reported in the IP
+   * packet header, the packet has been padded, and we set uip_len to
+   * the correct value.
+   */
+  if(uip_len < uipbuf_get_len_field(UIP_IP_BUF)) {
+    UIP_STAT(++uip_stat.ip.drop);
+    LOG_ERR("packet shorter than reported in IP header\n");
+    goto drop;
+  }
+
+  /*
+   * The length reported in the IPv6 header is the length of the
+   * payload that follows the header. However, uIP uses the uip_len
+   * variable for holding the size of the entire packet, including the
+   * IP header. For IPv4 this is not a problem as the length field in
+   * the IPv4 header contains the length of the entire packet. But for
+   * IPv6 we need to add the size of the IPv6 header (40 bytes).
    */
+  uip_len = uipbuf_get_len_field(UIP_IP_BUF) + UIP_IPH_LEN;
 
-  if((UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] <= uip_len) {
-    uip_len = (UIP_IP_BUF->len[0] << 8) + UIP_IP_BUF->len[1] + UIP_IPH_LEN;
-    /*
-     * The length reported in the IPv6 header is the
-     * length of the payload that follows the
-     * header. However, uIP uses the uip_len variable
-     * for holding the size of the entire packet,
-     * including the IP header. For IPv4 this is not a
-     * problem as the length field in the IPv4 header
-     * contains the length of the entire packet. But
-     * for IPv6 we need to add the size of the IPv6
-     * header (40 bytes).
-     */
-  } else {
-    LOG_ERR("packet shorter than reported in IP header.");
+  /* Check that the packet length is acceptable given our IP buffer size. */
+  if(uip_len > sizeof(uip_buf)) {
+    UIP_STAT(++uip_stat.ip.drop);
+    LOG_WARN("dropping packet with length %d > %d\n",
+	     (int)uip_len, (int)sizeof(uip_buf));
+    goto drop;
+  }
+
+  /* Check sanity of extension headers, and compute the total extension header
+   * length (uip_ext_len) as well as the final protocol (uip_last_proto) */
+  uip_last_proto = 0;
+  last_header = uipbuf_get_last_header(uip_buf, uip_len, &uip_last_proto);
+  if(last_header == NULL) {
+    LOG_ERR("invalid extension header chain\n");
     goto drop;
   }
+  /* Set uip_ext_len */
+  uip_ext_len = last_header - UIP_IP_PAYLOAD(0);
 
   LOG_INFO("packet received from ");
   LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
@@ -1140,32 +1196,20 @@ uip_process(uint8_t flag)
 
 #if UIP_CONF_ROUTER
   /*
-   * Next header field processing. In IPv6, we can have extension headers,
-   * if present, the Hop-by-Hop Option must be processed before forwarding
+   * If present, the Hop-by-Hop Option must be processed before forwarding
    * the packet.
    */
-  uip_next_hdr = &UIP_IP_BUF->proto;
-  uip_ext_len = 0;
-  uip_ext_bitmap = 0;
-  if(*uip_next_hdr == UIP_PROTO_HBHO) {
-#if UIP_CONF_IPV6_CHECKS
-    uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_HBHO;
-#endif /* UIP_CONF_IPV6_CHECKS */
-    switch(ext_hdr_options_process()) {
+
+  next_header = uipbuf_get_next_header(uip_buf, uip_len, &protocol, true);
+  if(next_header != NULL && protocol == UIP_PROTO_HBHO) {
+    switch(ext_hdr_options_process(next_header)) {
     case 0:
-      /* continue */
-      uip_next_hdr = &UIP_EXT_BUF->next;
-      uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
-      break;
+      break; /* done */
     case 1:
-      LOG_ERR("Dropping packet after extension header processing\n");
-      /* silently discard */
-      goto drop;
+      goto drop; /* silently discard */
     case 2:
-      LOG_ERR("Sending error message after extension header processing\n");
-      /* send icmp error message (created in ext_hdr_options_process)
-       * and discard*/
-      goto send;
+      goto send; /* send icmp error message (created in
+                    ext_hdr_options_process) and discard */
     }
   }
 
@@ -1201,23 +1245,12 @@ uip_process(uint8_t flag)
        !uip_is_addr_unspecified(&UIP_IP_BUF->srcipaddr) &&
        !uip_is_addr_loopback(&UIP_IP_BUF->destipaddr)) {
 
-
-      /* Check MTU */
-      if(uip_len > UIP_LINK_MTU) {
-        uip_icmp6_error_output(ICMP6_PACKET_TOO_BIG, 0, UIP_LINK_MTU);
-        UIP_STAT(++uip_stat.ip.drop);
-        goto send;
-      }
-      /* Check Hop Limit */
-      if(UIP_IP_BUF->ttl <= 1) {
-        uip_icmp6_error_output(ICMP6_TIME_EXCEEDED,
-                               ICMP6_TIME_EXCEED_TRANSIT, 0);
-        UIP_STAT(++uip_stat.ip.drop);
+      if(!uip_check_mtu() || !uip_update_ttl()) {
+        /* Send ICMPv6 error, prepared by the function that just returned false */
         goto send;
       }
 
-      UIP_IP_BUF->ttl = UIP_IP_BUF->ttl - 1;
-      LOG_INFO("Forwarding packet towards ");
+      LOG_INFO("Forwarding packet to next hop ");
       LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
       LOG_INFO_("\n");
       UIP_STAT(++uip_stat.ip.forwarded);
@@ -1246,35 +1279,20 @@ uip_process(uint8_t flag)
     UIP_STAT(++uip_stat.ip.drop);
     goto drop;
   }
-
-  /*
-   * Next header field processing. In IPv6, we can have extension headers,
-   * they are processed here
-   */
-  uip_next_hdr = &UIP_IP_BUF->proto;
-  uip_ext_len = 0;
-  uip_ext_bitmap = 0;
 #endif /* UIP_CONF_ROUTER */
 
 #if UIP_IPV6_MULTICAST && UIP_CONF_ROUTER
   process:
 #endif /* UIP_IPV6_MULTICAST && UIP_CONF_ROUTER */
 
-  while(1) {
-    switch(*uip_next_hdr){
-#if UIP_TCP
-    case UIP_PROTO_TCP:
-      /* TCP, for both IPv4 and IPv6 */
-      goto tcp_input;
-#endif /* UIP_TCP */
-#if UIP_UDP
-    case UIP_PROTO_UDP:
-      /* UDP, for both IPv4 and IPv6 */
-      goto udp_input;
-#endif /* UIP_UDP */
-    case UIP_PROTO_ICMP6:
-      /* ICMPv6 */
-      goto icmp6_input;
+  /* IPv6 extension header processing: loop until reaching upper-layer protocol */
+  uip_ext_bitmap = 0;
+  for(next_header = uipbuf_get_next_header(uip_buf, uip_len, &protocol, true);
+      next_header != NULL && uip_is_proto_ext_hdr(protocol);
+      next_header = uipbuf_get_next_header(next_header, uip_len - (next_header - uip_buf), &protocol, false)) {
+
+    ext_ptr = (struct uip_ext_hdr *)next_header;
+    switch(protocol) {
     case UIP_PROTO_HBHO:
       LOG_DBG("Processing hbh header\n");
       /* Hop by hop option header */
@@ -1286,145 +1304,140 @@ uip_process(uint8_t flag)
         uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_HBHO;
       }
 #endif /*UIP_CONF_IPV6_CHECKS*/
-      switch(ext_hdr_options_process()) {
+      switch(ext_hdr_options_process(next_header)) {
       case 0:
-        /*continue*/
-        uip_next_hdr = &UIP_EXT_BUF->next;
-        uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
-        break;
+        break; /* done */
       case 1:
-        /*silently discard*/
-        goto drop;
+        goto drop; /* silently discard */
       case 2:
-        /* send icmp error message (created in ext_hdr_options_process)
-         * and discard*/
-        goto send;
+        goto send; /* send icmp error message (created in
+                      ext_hdr_options_process) and discard */
       }
       break;
-      case UIP_PROTO_DESTO:
+    case UIP_PROTO_DESTO:
 #if UIP_CONF_IPV6_CHECKS
-        /* Destination option header. if we saw two already, drop */
-        LOG_DBG("Processing desto header\n");
-        if(uip_ext_bitmap & UIP_EXT_HDR_BITMAP_DESTO1) {
-          if(uip_ext_bitmap & UIP_EXT_HDR_BITMAP_DESTO2) {
-            goto bad_hdr;
-          } else{
-            uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_DESTO2;
-          }
-        } else {
-          uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_DESTO1;
+      /* Destination option header. if we saw two already, drop */
+      LOG_DBG("Processing desto header\n");
+      if(uip_ext_bitmap & UIP_EXT_HDR_BITMAP_DESTO1) {
+        if(uip_ext_bitmap & UIP_EXT_HDR_BITMAP_DESTO2) {
+          goto bad_hdr;
+        } else{
+          uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_DESTO2;
         }
+      } else {
+        uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_DESTO1;
+      }
 #endif /*UIP_CONF_IPV6_CHECKS*/
-        switch(ext_hdr_options_process()) {
-        case 0:
-          /*continue*/
-          uip_next_hdr = &UIP_EXT_BUF->next;
-          uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
-          break;
-        case 1:
-          /*silently discard*/
-          goto drop;
-        case 2:
-          /* send icmp error message (created in ext_hdr_options_process)
-           * and discard*/
-          goto send;
-        }
-        break;
-        case UIP_PROTO_ROUTING:
+      switch(ext_hdr_options_process(next_header)) {
+      case 0:
+        break; /* done */
+      case 1:
+        goto drop; /* silently discard */
+      case 2:
+        goto send; /* send icmp error message (created in
+                      ext_hdr_options_process) and discard */
+      }
+      break;
+    case UIP_PROTO_ROUTING:
 #if UIP_CONF_IPV6_CHECKS
-          /* Routing header. If we saw one already, drop */
-          if(uip_ext_bitmap & UIP_EXT_HDR_BITMAP_ROUTING) {
-            goto bad_hdr;
-          } else {
-            uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_ROUTING;
-          }
+      /* Routing header. If we saw one already, drop */
+      if(uip_ext_bitmap & UIP_EXT_HDR_BITMAP_ROUTING) {
+        goto bad_hdr;
+      } else {
+        uip_ext_bitmap |= UIP_EXT_HDR_BITMAP_ROUTING;
+      }
 #endif /*UIP_CONF_IPV6_CHECKS*/
-          /*
-           * Routing Header  length field is in units of 8 bytes, excluding
-           * As per RFC2460 section 4.4, if routing type is unrecognized:
-           * if segments left = 0, ignore the header
-           * if segments left > 0, discard packet and send icmp error pointing
-           * to the routing type
-           */
+      /*
+       * Routing Header  length field is in units of 8 bytes, excluding
+       * As per RFC2460 section 4.4, if routing type is unrecognized:
+       * if segments left = 0, ignore the header
+       * if segments left > 0, discard packet and send icmp error pointing
+       * to the routing type
+       */
 
-          LOG_DBG("Processing Routing header\n");
-          if(UIP_ROUTING_BUF->seg_left > 0) {
-            if(NETSTACK_ROUTING.ext_header_srh_update()) {
-
-              /* With routing header, the detination address is us and will
-               * be swapped later to the next hop. Because of this, the MTU
-               * and TTL were not checked and updated yet. Do this now. */
-
-              /* Check MTU */
-              if(uip_len > UIP_LINK_MTU) {
-                uip_icmp6_error_output(ICMP6_PACKET_TOO_BIG, 0, UIP_LINK_MTU);
-                UIP_STAT(++uip_stat.ip.drop);
-                goto send;
-              }
-              /* Check Hop Limit */
-              if(UIP_IP_BUF->ttl <= 1) {
-                uip_icmp6_error_output(ICMP6_TIME_EXCEEDED,
-                                       ICMP6_TIME_EXCEED_TRANSIT, 0);
-                UIP_STAT(++uip_stat.ip.drop);
-                goto send;
-              }
-              UIP_IP_BUF->ttl = UIP_IP_BUF->ttl - 1;
-
-              LOG_INFO("Forwarding packet to next hop ");
-              LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
-              LOG_INFO_("\n");
-              UIP_STAT(++uip_stat.ip.forwarded);
-
-              goto send; /* Proceed to forwarding */
-            }
-            uip_icmp6_error_output(ICMP6_PARAM_PROB, ICMP6_PARAMPROB_HEADER, UIP_IPH_LEN + uip_ext_len + 2);
-            UIP_STAT(++uip_stat.ip.drop);
-            LOG_ERR("unrecognized routing type");
+      LOG_DBG("Processing Routing header\n");
+      if(((struct uip_routing_hdr *)ext_ptr)->seg_left > 0) {
+        /* Process source routing header */
+        if(NETSTACK_ROUTING.ext_header_srh_update()) {
+
+          /* The MTU and TTL were not checked and updated yet, because with
+           * a routing header, the IPv6 destination address was set to us
+           * even though we act only as forwarder. Check MTU and TTL now */
+          if(!uip_check_mtu() || !uip_update_ttl()) {
+            /* Send ICMPv6 error, prepared by the function that just returned false */
             goto send;
           }
-          uip_next_hdr = &UIP_EXT_BUF->next;
-          uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
-          break;
-        case UIP_PROTO_FRAG:
-          /* Fragmentation header:call the reassembly function, then leave */
+
+          LOG_INFO("Forwarding packet to next hop ");
+          LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
+          LOG_INFO_("\n");
+          UIP_STAT(++uip_stat.ip.forwarded);
+
+          goto send; /* Proceed to forwarding */
+        } else {
+          LOG_ERR("Unrecognized routing type\n");
+          goto bad_hdr;
+        }
+      }
+      break;
+    case UIP_PROTO_FRAG:
+      /* Fragmentation header:call the reassembly function, then leave */
 #if UIP_CONF_IPV6_REASSEMBLY
-          LOG_INFO("Processing fragmentation header\n");
-          uip_len = uip_reass();
-          if(uip_len == 0) {
-            goto drop;
-          }
-          if(uip_reassflags & UIP_REASS_FLAG_ERROR_MSG){
-            /* we are not done with reassembly, this is an error message */
-            goto send;
-          }
-          /*packet is reassembled, reset the next hdr to the beginning
-           of the IP header and restart the parsing of the reassembled pkt*/
-          LOG_INFO("Processing reassembled packet\n");
-          uip_ext_len = 0;
-          uip_ext_bitmap = 0;
-          uip_next_hdr = &UIP_IP_BUF->proto;
-          break;
+      LOG_INFO("Processing fragmentation header\n");
+      uip_len = uip_reass(&ext_ptr->next);
+      if(uip_len == 0) {
+        goto drop;
+      }
+      if(uip_reassflags & UIP_REASS_FLAG_ERROR_MSG) {
+        /* we are not done with reassembly, this is an error message */
+        goto send;
+      }
+      /* packet is reassembled. Restart the parsing of the reassembled pkt */
+      LOG_INFO("Processing reassembled packet\n");
+      uip_ext_bitmap = 0;
+      next_header = uipbuf_get_next_header(uip_buf, uip_len, &protocol, true);
+      break;
 #else /* UIP_CONF_IPV6_REASSEMBLY */
-          UIP_STAT(++uip_stat.ip.drop);
-          UIP_STAT(++uip_stat.ip.fragerr);
-          LOG_ERR("fragment dropped.");
-          goto drop;
+      UIP_STAT(++uip_stat.ip.drop);
+      UIP_STAT(++uip_stat.ip.fragerr);
+      LOG_ERR("fragment dropped.");
+      goto drop;
 #endif /* UIP_CONF_IPV6_REASSEMBLY */
-        case UIP_PROTO_NONE:
-          goto drop;
-        default:
-          goto bad_hdr;
+    case UIP_PROTO_NONE:
+      goto drop;
+    default:
+      goto bad_hdr;
     }
   }
+
+  /* Process upper-layer input */
+  if(next_header != NULL) {
+    switch(protocol) {
+#if UIP_TCP
+    case UIP_PROTO_TCP:
+      /* TCP, for both IPv4 and IPv6 */
+      goto tcp_input;
+#endif
+#if UIP_UDP
+    case UIP_PROTO_UDP:
+      /* UDP, for both IPv4 and IPv6 */
+      goto udp_input;
+#endif
+    case UIP_PROTO_ICMP6:
+      /* ICMPv6 */
+      goto icmp6_input;
+    }
+  }
+
   bad_hdr:
   /*
    * RFC 2460 send error message parameterr problem, code unrecognized
    * next header, pointing to the next header field
    */
-  uip_icmp6_error_output(ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER, (uint32_t)(uip_next_hdr - (uint8_t *)UIP_IP_BUF));
+  uip_icmp6_error_output(ICMP6_PARAM_PROB, ICMP6_PARAMPROB_NEXTHEADER, (uint32_t)(next_header - uip_buf));
   UIP_STAT(++uip_stat.ip.drop);
   UIP_STAT(++uip_stat.ip.protoerr);
-  LOG_ERR("unrecognized header");
+  LOG_ERR("unrecognized header\n");
   goto send;
   /* End of headers processing */
 
@@ -1465,7 +1478,7 @@ uip_process(uint8_t flag)
     LOG_ERR("Unknown ICMPv6 message type/code %d\n", UIP_ICMP_BUF->type);
     UIP_STAT(++uip_stat.icmp.drop);
     UIP_STAT(++uip_stat.icmp.typeerr);
-    uip_clear_buf();
+    uipbuf_clear();
   }
 
   if(uip_len > 0) {
@@ -1480,7 +1493,7 @@ uip_process(uint8_t flag)
   /* UDP input processing. */
   udp_input:
 
-  remove_ext_hdr();
+  uip_remove_ext_hdr();
 
   LOG_INFO("Receiving UDP packet\n");
 
@@ -1540,10 +1553,10 @@ uip_process(uint8_t flag)
   UIP_STAT(++uip_stat.udp.recv);
 
   uip_len = uip_len - UIP_IPUDPH_LEN;
-  uip_appdata = &uip_buf[UIP_IPUDPH_LEN + UIP_LLH_LEN];
+  uip_appdata = &uip_buf[UIP_IPUDPH_LEN];
   uip_conn = NULL;
   uip_flags = UIP_NEWDATA;
-  uip_sappdata = uip_appdata = &uip_buf[UIP_IPUDPH_LEN + UIP_LLH_LEN];
+  uip_sappdata = uip_appdata = &uip_buf[UIP_IPUDPH_LEN];
   uip_slen = 0;
   UIP_UDP_APPCALL();
 
@@ -1557,8 +1570,7 @@ uip_process(uint8_t flag)
 
   /* For IPv6, the IP length field does not include the IPv6 IP header
      length. */
-  UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
-  UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
+  uipbuf_set_len_field(UIP_IP_BUF, uip_len - UIP_IPH_LEN);
 
   UIP_IP_BUF->vtc = 0x60;
   UIP_IP_BUF->tcflow = 0x00;
@@ -1574,7 +1586,7 @@ uip_process(uint8_t flag)
   uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &uip_udp_conn->ripaddr);
   uip_ds6_select_src(&UIP_IP_BUF->srcipaddr, &UIP_IP_BUF->destipaddr);
 
-  uip_appdata = &uip_buf[UIP_LLH_LEN + UIP_IPTCPH_LEN];
+  uip_appdata = &uip_buf[UIP_IPTCPH_LEN];
 
 #if UIP_UDP_CHECKSUMS
   /* Calculate UDP checksum. */
@@ -1592,7 +1604,7 @@ uip_process(uint8_t flag)
   /* TCP input processing. */
   tcp_input:
 
-  remove_ext_hdr();
+  uip_remove_ext_hdr();
 
   UIP_STAT(++uip_stat.tcp.recv);
   LOG_INFO("Receiving TCP packet\n");
@@ -1609,7 +1621,7 @@ uip_process(uint8_t flag)
 
   /* Make sure that the TCP port number is not zero. */
   if(UIP_TCP_BUF->destport == 0 || UIP_TCP_BUF->srcport == 0) {
-    LOG_ERR("tcp: zero port.");
+    LOG_ERR("tcp: zero port\n");
     goto drop;
   }
 
@@ -1726,7 +1738,7 @@ uip_process(uint8_t flag)
        the remote end will retransmit the packet at a time when we
        have more spare connections. */
     UIP_STAT(++uip_stat.tcp.syndrop);
-    LOG_ERR("tcp: found no unused connections.");
+    LOG_ERR("tcp: found no unused connections\n");
     goto drop;
   }
   uip_conn = uip_connr;
@@ -1757,7 +1769,7 @@ uip_process(uint8_t flag)
   /* Parse the TCP MSS option, if present. */
   if((UIP_TCP_BUF->tcpoffset & 0xf0) > 0x50) {
     for(c = 0; c < ((UIP_TCP_BUF->tcpoffset >> 4) - 5) << 2 ;) {
-      opt = uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + c];
+      opt = uip_buf[UIP_IPTCPH_LEN + c];
       if(opt == TCP_OPT_END) {
         /* End of options. */
         break;
@@ -1765,10 +1777,10 @@ uip_process(uint8_t flag)
         ++c;
         /* NOP option. */
       } else if(opt == TCP_OPT_MSS &&
-                uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
+                uip_buf[UIP_IPTCPH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
         /* An MSS option with the right option length. */
-        tmp16 = ((uint16_t)uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
-          (uint16_t)uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + 3 + c];
+        tmp16 = ((uint16_t)uip_buf[UIP_IPTCPH_LEN + 2 + c] << 8) |
+          (uint16_t)uip_buf[UIP_IPTCPH_LEN + 3 + c];
         uip_connr->initialmss = uip_connr->mss =
           tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
 
@@ -1777,12 +1789,12 @@ uip_process(uint8_t flag)
       } else {
         /* All other options have a length field, so that we easily
            can skip past them. */
-        if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
+        if(uip_buf[UIP_IPTCPH_LEN + 1 + c] == 0) {
           /* If the length field is zero, the options are malformed
              and we don't process them further. */
           break;
         }
-        c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
+        c += uip_buf[UIP_IPTCPH_LEN + 1 + c];
       }
     }
   }
@@ -1944,7 +1956,7 @@ uip_process(uint8_t flag)
       /* Parse the TCP MSS option, if present. */
       if((UIP_TCP_BUF->tcpoffset & 0xf0) > 0x50) {
         for(c = 0; c < ((UIP_TCP_BUF->tcpoffset >> 4) - 5) << 2 ;) {
-          opt = uip_buf[UIP_IPTCPH_LEN + UIP_LLH_LEN + c];
+          opt = uip_buf[UIP_IPTCPH_LEN + c];
           if(opt == TCP_OPT_END) {
             /* End of options. */
             break;
@@ -1952,10 +1964,10 @@ uip_process(uint8_t flag)
             ++c;
             /* NOP option. */
           } else if(opt == TCP_OPT_MSS &&
-              uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
+              uip_buf[UIP_IPTCPH_LEN + 1 + c] == TCP_OPT_MSS_LEN) {
             /* An MSS option with the right option length. */
-            tmp16 = (uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 2 + c] << 8) |
-                uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 3 + c];
+            tmp16 = (uip_buf[UIP_IPTCPH_LEN + 2 + c] << 8) |
+                uip_buf[UIP_IPTCPH_LEN + 3 + c];
             uip_connr->initialmss =
                 uip_connr->mss = tmp16 > UIP_TCP_MSS? UIP_TCP_MSS: tmp16;
 
@@ -1964,12 +1976,12 @@ uip_process(uint8_t flag)
           } else {
             /* All other options have a length field, so that we easily
                  can skip past them. */
-            if(uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c] == 0) {
+            if(uip_buf[UIP_IPTCPH_LEN + 1 + c] == 0) {
               /* If the length field is zero, the options are malformed
                    and we don't process them further. */
               break;
             }
-            c += uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN + 1 + c];
+            c += uip_buf[UIP_IPTCPH_LEN + 1 + c];
           }
         }
       }
@@ -1981,7 +1993,7 @@ uip_process(uint8_t flag)
       uip_add_rcv_nxt(1);
       uip_flags = UIP_CONNECTED | UIP_NEWDATA;
       uip_connr->len = 0;
-      uip_clear_buf();
+      uipbuf_clear();
       uip_slen = 0;
       UIP_APPCALL();
       goto appsend;
@@ -2083,7 +2095,7 @@ uip_process(uint8_t flag)
          When the application is called, the global variable uip_len
          contains the length of the incoming data. The application can
          access the incoming data through the global pointer
-         uip_appdata, which usually points UIP_IPTCPH_LEN + UIP_LLH_LEN
+         uip_appdata, which usually points UIP_IPTCPH_LEN
          bytes into the uip_buf array.
 
          If the application wishes to send any data, this data should be
@@ -2152,7 +2164,7 @@ uip_process(uint8_t flag)
            packet had new data in it, we must send out a packet. */
       if(uip_slen > 0 && uip_connr->len > 0) {
         /* Add the length of the IP and TCP headers. */
-        uip_len = uip_connr->len + UIP_TCPIP_HLEN;
+        uip_len = uip_connr->len + UIP_IPTCPH_LEN;
         /* We always set the ACK flag in response packets. */
         UIP_TCP_BUF->flags = TCP_ACK | TCP_PSH;
         /* Send the packet. */
@@ -2161,7 +2173,7 @@ uip_process(uint8_t flag)
       /* If there is no data to send, just send out a pure ACK if
            there is newdata. */
       if(uip_flags & UIP_NEWDATA) {
-        uip_len = UIP_TCPIP_HLEN;
+        uip_len = UIP_IPTCPH_LEN;
         UIP_TCP_BUF->flags = TCP_ACK;
         goto tcp_send_noopts;
       }
@@ -2289,8 +2301,7 @@ uip_process(uint8_t flag)
   UIP_IP_BUF->proto = UIP_PROTO_TCP;
 
   UIP_IP_BUF->ttl = uip_ds6_if.cur_hop_limit;
-  UIP_IP_BUF->len[0] = ((uip_len - UIP_IPH_LEN) >> 8);
-  UIP_IP_BUF->len[1] = ((uip_len - UIP_IPH_LEN) & 0xff);
+  uipbuf_set_len_field(UIP_IP_BUF, uip_len - UIP_IPH_LEN);
 
   UIP_TCP_BUF->urgp[0] = UIP_TCP_BUF->urgp[1] = 0;
 
@@ -2305,8 +2316,7 @@ uip_process(uint8_t flag)
 #endif
   UIP_IP_BUF->flow = 0x00;
   send:
-  LOG_INFO("Sending packet with length %d (%d)\n", uip_len,
-      (UIP_IP_BUF->len[0] << 8) | UIP_IP_BUF->len[1]);
+  LOG_INFO("Sending packet with length %d (%d)\n", uip_len, uipbuf_get_len_field(UIP_IP_BUF));
 
   UIP_STAT(++uip_stat.ip.sent);
   /* Return and let the caller do the actual transmission. */
@@ -2314,7 +2324,7 @@ uip_process(uint8_t flag)
   return;
 
   drop:
-  uip_clear_buf();
+  uipbuf_clear();
   uip_ext_bitmap = 0;
   uip_flags = 0;
   return;
@@ -2338,18 +2348,16 @@ uip_send(const void *data, int len)
   int copylen;
 
   if(uip_sappdata != NULL) {
-    copylen = MIN(len, UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN -
-        (int)((char *)uip_sappdata -
-            (char *)&uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN]));
+    copylen = MIN(len, UIP_BUFSIZE - UIP_IPTCPH_LEN -
+        (int)((char *)uip_sappdata - (char *)UIP_TCP_PAYLOAD));
   } else {
-    copylen = MIN(len, UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN);
+    copylen = MIN(len, UIP_BUFSIZE - UIP_IPTCPH_LEN);
   }
   if(copylen > 0) {
     uip_slen = copylen;
     if(data != uip_sappdata) {
       if(uip_sappdata == NULL) {
-        memcpy((char *)&uip_buf[UIP_LLH_LEN + UIP_TCPIP_HLEN],
-            (data), uip_slen);
+        memcpy(UIP_TCP_PAYLOAD, (data), uip_slen);
       } else {
         memcpy(uip_sappdata, (data), uip_slen);
       }
diff --git a/os/net/ipv6/uipbuf.c b/os/net/ipv6/uipbuf.c
index 6ccbb99aa37d18fafb9c255dcff75547fdb49a9f..59466b3763005ebd09447963aa509c72bd9b3f3b 100644
--- a/os/net/ipv6/uipbuf.c
+++ b/os/net/ipv6/uipbuf.c
@@ -30,53 +30,150 @@
  *
  */
 #include "contiki.h"
-#include "uip.h"
+#include "net/ipv6/uip.h"
 #include "net/ipv6/uipbuf.h"
 #include <string.h>
 
 /*---------------------------------------------------------------------------*/
 
 static uint16_t uipbuf_attrs[UIPBUF_ATTR_MAX];
+static uint16_t uipbuf_default_attrs[UIPBUF_ATTR_MAX];
 
+/*---------------------------------------------------------------------------*/
+void
+uipbuf_clear(void)
+{
+  uip_len = 0;
+  uip_ext_len = 0;
+  uip_last_proto = 0;
+  uipbuf_clear_attr();
+}
+/*---------------------------------------------------------------------------*/
+bool
+uipbuf_add_ext_hdr(int16_t len)
+{
+  if(len + uip_len <= UIP_LINK_MTU && len + uip_len >= 0 && len + uip_ext_len >= 0) {
+    uip_ext_len += len;
+    uip_len += len;
+    return true;
+  } else {
+    return false;
+  }
+}
+/*---------------------------------------------------------------------------*/
+bool
+uipbuf_set_len(uint16_t len)
+{
+  if(len <= UIP_LINK_MTU) {
+    uip_len = len;
+    return true;
+  } else {
+    return false;
+  }
+}
+/*---------------------------------------------------------------------------*/
+void
+uipbuf_set_len_field(struct uip_ip_hdr *hdr, uint16_t len)
+{
+  hdr->len[0] = (len >> 8);
+  hdr->len[1] = (len & 0xff);
+}
+/*---------------------------------------------------------------------------*/
+uint16_t
+uipbuf_get_len_field(struct uip_ip_hdr *hdr)
+{
+  return ((uint16_t)(hdr->len[0]) << 8) + hdr->len[1];
+}
 /*---------------------------------------------------------------------------*/
 /* Get the next header given the buffer - start indicates that this is
    start of the IPv6 header - needs to be set to 0 when in an ext hdr */
-uint8_t*
-uipbuf_get_next_header(uint8_t *buffer, uint16_t size, uint8_t *protocol, uint8_t start)
+uint8_t *
+uipbuf_get_next_header(uint8_t *buffer, uint16_t size, uint8_t *protocol, bool start)
 {
-  int ext_len = 0;
-  struct uip_ip_hdr *ipbuf = (struct uip_ip_hdr *) buffer;
-  struct uip_ext_hdr *ext = NULL;
+  int curr_hdr_len = 0;
+  int next_hdr_len = 0;
+  uint8_t *next_header = NULL;
+  struct uip_ip_hdr *ipbuf = NULL;
+  struct uip_ext_hdr *curr_ext = NULL;
+  struct uip_ext_hdr *next_ext = NULL;
 
   if(start) {
     /* protocol in the IP buffer */
+    ipbuf = (struct uip_ip_hdr *)buffer;
     *protocol = ipbuf->proto;
-    return buffer + UIP_IPH_LEN;
+    curr_hdr_len = UIP_IPH_LEN;
   } else {
     /* protocol in the Ext hdr */
-    ext = (struct uip_ext_hdr *) buffer;
-    *protocol = ext->next;
+    curr_ext = (struct uip_ext_hdr *)buffer;
+    *protocol = curr_ext->next;
     /* This is just an ext header */
-    ext_len = (ext->len << 3) + 8;
-    return buffer + ext_len;
+    curr_hdr_len = (curr_ext->len << 3) + 8;
+  }
+
+  /* Check first if enough space for current header */
+  if(curr_hdr_len > size) {
+    return NULL;
+  }
+  next_header = buffer + curr_hdr_len;
+
+  /* Check if the buffer is large enough for the next header */
+  if(uip_is_proto_ext_hdr(*protocol)) {
+    next_ext = (struct uip_ext_hdr *)next_header;
+    next_hdr_len = (next_ext->len << 3) + 8;
+  } else {
+    if(*protocol == UIP_PROTO_TCP) {
+      next_hdr_len = UIP_TCPH_LEN;
+    } else if(*protocol == UIP_PROTO_UDP) {
+      next_hdr_len = UIP_UDPH_LEN;
+    } else if(*protocol == UIP_PROTO_ICMP6) {
+      next_hdr_len = UIP_ICMPH_LEN;
+    }
+  }
+
+  /* Size must be enough to hold both the current and next header */
+  if(next_hdr_len == 0 || curr_hdr_len + next_hdr_len > size) {
+    return NULL;
   }
+
+  return next_header;
 }
 /*---------------------------------------------------------------------------*/
 /* Get the final header given the buffer - that is assumed to be at start
    of an IPv6 header */
-uint8_t*
+uint8_t *
 uipbuf_get_last_header(uint8_t *buffer, uint16_t size, uint8_t *protocol)
 {
   uint8_t *nbuf;
 
-  nbuf = uipbuf_get_next_header(buffer, size, protocol, 1);
-  while(uip_is_proto_ext_hdr(*protocol)) {
-    /* send in and move beyond the ext hdr */
-    nbuf = uipbuf_get_next_header(nbuf, size - (nbuf - buffer), protocol, 0);
+  nbuf = uipbuf_get_next_header(buffer, size, protocol, true);
+  while(nbuf != NULL && uip_is_proto_ext_hdr(*protocol)) {
+    /* move to the ext hdr */
+    nbuf = uipbuf_get_next_header(nbuf, size - (nbuf - buffer), protocol, false);
   }
+
+  /* In case the buffer wasn't large enough for all headers, return NULL */
   return nbuf;
 }
 /*---------------------------------------------------------------------------*/
+uint8_t *
+uipbuf_search_header(uint8_t *buffer, uint16_t size, uint8_t protocol)
+{
+  uint8_t *nbuf;
+  uint8_t next_proto;
+
+  nbuf = uipbuf_get_next_header(buffer, size, &next_proto, true);
+  while(nbuf != NULL && next_proto != protocol && uip_is_proto_ext_hdr(next_proto)) {
+    /* move to the ext hdr */
+    nbuf = uipbuf_get_next_header(nbuf, size - (nbuf - buffer), &next_proto, false);
+  }
+
+  if(next_proto == protocol) {
+    return nbuf;
+  } else {
+    return NULL;
+  }
+}
+/*---------------------------------------------------------------------------*/
 /**
  * Common functions for uipbuf (attributes, etc).
  *
@@ -101,15 +198,21 @@ uipbuf_set_attr(uint8_t type, uint16_t value)
   return 0;
 }
 /*---------------------------------------------------------------------------*/
+int
+uipbuf_set_default_attr(uint8_t type, uint16_t value)
+{
+  if(type < UIPBUF_ATTR_MAX) {
+    uipbuf_default_attrs[type] = value;
+    return 1;
+  }
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
 void
 uipbuf_clear_attr(void)
 {
-  /* set everything to "zero" */
-  memset(uipbuf_attrs, 0, sizeof(uipbuf_attrs));
-
-  /* And initialize anything that should be initialized */
-  uipbuf_set_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS,
-                  UIP_MAX_MAC_TRANSMISSIONS_UNDEFINED);
+  /* set everything to "defaults" */
+  memcpy(uipbuf_attrs, uipbuf_default_attrs, sizeof(uipbuf_attrs));
 }
 /*---------------------------------------------------------------------------*/
 void
@@ -131,3 +234,17 @@ uipbuf_is_attr_flag(uint16_t flag)
   return (uipbuf_attrs[UIPBUF_ATTR_FLAGS] & flag) == flag;
 }
 /*---------------------------------------------------------------------------*/
+void
+uipbuf_init(void)
+{
+  memset(uipbuf_default_attrs, 0, sizeof(uipbuf_default_attrs));
+  /* And initialize anything that should be initialized */
+  uipbuf_set_default_attr(UIPBUF_ATTR_MAX_MAC_TRANSMISSIONS,
+                          UIP_MAX_MAC_TRANSMISSIONS_UNDEFINED);
+  /* set the not-set default value - this will cause the MAC layer to
+     configure its default */
+  uipbuf_set_default_attr(UIPBUF_ATTR_LLSEC_LEVEL,
+                          UIPBUF_ATTR_LLSEC_LEVEL_MAC_DEFAULT);
+}
+
+/*---------------------------------------------------------------------------*/
diff --git a/os/net/ipv6/uipbuf.h b/os/net/ipv6/uipbuf.h
index 337ffe17f6509054c0bf411402fd61f3f6e74659..fdea60b28dd7f84261fffb9b6f8901e9aad01112 100644
--- a/os/net/ipv6/uipbuf.h
+++ b/os/net/ipv6/uipbuf.h
@@ -34,6 +34,40 @@
 #define UIPBUF_H_
 
 #include "contiki.h"
+struct uip_ip_hdr;
+
+/**
+ * \brief          Resets uIP buffer
+ */
+void uipbuf_clear(void);
+
+/**
+ * \brief          Update uip buffer length for addition of an extension header
+ * \param len      The length of the new extension header
+ * \retval         true if the length fields were successfully set, false otherwise
+ */
+bool uipbuf_add_ext_hdr(int16_t len);
+
+/**
+ * \brief          Set the length of the uIP buffer
+ * \param len      The new length
+ * \retval         true if the len was successfully set, false otherwise
+ */
+bool uipbuf_set_len(uint16_t len);
+
+/**
+ * \brief          Updates the length field in the uIP buffer
+ * \param buffer   The IPv6 header
+ * \param len      The new length value
+ */
+void uipbuf_set_len_field(struct uip_ip_hdr *hdr, uint16_t len);
+
+/**
+ * \brief          Returns the value of the length field in the uIP buffer
+ * \param buffer   The IPv6 header
+ * \retvel         The length value
+ */
+uint16_t uipbuf_get_len_field(struct uip_ip_hdr *hdr);
 
 /**
  * \brief          Get the next IPv6 header.
@@ -41,11 +75,11 @@
  * \param size     The size of the data in the buffer
  * \param protocol A pointer to a variable where the protocol of the header will be stored
  * \param start    A flag that indicates if this is expected to be the IPv6 packet header or a later header (Extension header)
- * \retval         returns address of the starting position of the next header
+ * \retval         returns address of the next header, or NULL in case of insufficient buffer space
  *
  *                 This function moves to the next header in a IPv6 packet.
  */
-uint8_t* uipbuf_get_next_header(uint8_t *buffer, uint16_t size, uint8_t *protocol, uint8_t start);
+uint8_t *uipbuf_get_next_header(uint8_t *buffer, uint16_t size, uint8_t *protocol, bool start);
 
 
 /**
@@ -53,12 +87,22 @@ uint8_t* uipbuf_get_next_header(uint8_t *buffer, uint16_t size, uint8_t *protoco
  * \param buffer   A pointer to the buffer holding the IPv6 packet
  * \param size     The size of the data in the buffer
  * \param protocol A pointer to a variable where the protocol of the header will be stored
- * \retval         returns address of the starting position of the next header
+ * \retval         returns address of the last header, or NULL in case of insufficient buffer space
  *
  *                 This function moves to the last header of the IPv6 packet.
  */
-uint8_t* uipbuf_get_last_header(uint8_t *buffer, uint16_t size, uint8_t *protocol);
+uint8_t *uipbuf_get_last_header(uint8_t *buffer, uint16_t size, uint8_t *protocol);
 
+/**
+ * \brief          Get an IPv6 header with a given protocol field.
+ * \param buffer   A pointer to the buffer holding the IPv6 packet
+ * \param size     The size of the data in the buffer
+ * \param protocol The protocol we are looking for
+ * \retval         returns address of the header if found, else NULL
+ *
+ *                 This function moves to the last header of the IPv6 packet.
+ */
+uint8_t *uipbuf_search_header(uint8_t *buffer, uint16_t size, uint8_t protocol);
 
 /**
  * \brief          Get the value of the attribute
@@ -81,6 +125,17 @@ uint16_t uipbuf_get_attr(uint8_t type);
  */
 int uipbuf_set_attr(uint8_t type, uint16_t value);
 
+/**
+ * \brief          Set the default value of the attribute
+ * \param type     The attribute to set the default value of
+ * \param value    The value to set
+ * \retval         0 - indicates failure of setting the value
+ * \retval         1 - indicates success of setting the value
+ *
+ *                 This function sets the default value of a uipbuf attribute.
+ */
+int uipbuf_set_default_attr(uint8_t type, uint16_t value);
+
 /**
  * \brief          Set bits in the uipbuf attribute flags.
  * \param flag_bits The bits to set in the flag.
@@ -115,6 +170,14 @@ uint16_t uipbuf_is_attr_flag(uint16_t flag_bits);
  */
 void uipbuf_clear_attr(void);
 
+/**
+ * \brief          Initialize uipbuf attributes.
+ *
+ *                 This function initialize all attributes in the uipbuf
+ *                 attributes including all flags.
+ */
+void uipbuf_init(void);
+
 /**
  * \brief The bits defined for uipbuf attributes flag.
  *
@@ -124,6 +187,9 @@ void uipbuf_clear_attr(void);
 /* Avoid using prefix compression on the packet (6LoWPAN) */
 #define UIPBUF_ATTR_FLAGS_6LOWPAN_NO_PREFIX_COMPRESSION   0x02
 
+/* MAC will set the default for this packet */
+#define UIPBUF_ATTR_LLSEC_LEVEL_MAC_DEFAULT               0xffff
+
 /**
  * \brief The attributes defined for uipbuf attributes function.
  *
diff --git a/os/net/ipv6/uiplib.c b/os/net/ipv6/uiplib.c
index a6d8b4f0c983042e0dec6b9b22db8cc0c43ac417..e4a7a49b7986fa17d0829bd29e5ee8dea44b97da 100644
--- a/os/net/ipv6/uiplib.c
+++ b/os/net/ipv6/uiplib.c
@@ -56,7 +56,6 @@
 #define LOG_LEVEL  LOG_LEVEL_NONE
 
 /*---------------------------------------------------------------------------*/
-#if NETSTACK_CONF_WITH_IPV6
 int
 uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *ipaddr)
 {
@@ -118,7 +117,6 @@ uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *ipaddr)
 
   return 1;
 }
-#endif /* NETSTACK_CONF_WITH_IPV6 */
 /*---------------------------------------------------------------------------*/
 /* Parse a IPv4-address from a string. Returns the number of characters read
  * for the address. */
diff --git a/os/net/ipv6/uiplib.h b/os/net/ipv6/uiplib.h
index b30a1bcb502251d7479325bca9a360a660944709..aaf91282f3f6a12999b0f9d01a2595482b1c6b9d 100644
--- a/os/net/ipv6/uiplib.h
+++ b/os/net/ipv6/uiplib.h
@@ -68,11 +68,7 @@
  * \retval 0 If the IP address could not be parsed.
  * \retval Non-zero If the IP address was parsed.
  */
-#if NETSTACK_CONF_WITH_IPV6
 #define uiplib_ipaddrconv uiplib_ip6addrconv
-#else /* NETSTACK_CONF_WITH_IPV6 */
-#define uiplib_ipaddrconv uiplib_ip4addrconv
-#endif /* NETSTACK_CONF_WITH_IPV6 */
 
 int uiplib_ip4addrconv(const char *addrstr, uip_ip4addr_t *addr);
 int uiplib_ip6addrconv(const char *addrstr, uip_ip6addr_t *addr);
diff --git a/os/net/ipv6/uipopt.h b/os/net/ipv6/uipopt.h
index 15c79e20a9eaaf879b40f04f6703588652b4e884..a75c59ea0acd1ad4fafe7ac57c5db49f3b8fc8d0 100644
--- a/os/net/ipv6/uipopt.h
+++ b/os/net/ipv6/uipopt.h
@@ -121,26 +121,6 @@
  * @{
  */
 
-/**
- * The link level header length.
- *
- * This is the offset into the uip_buf where the IP header can be
- * found. For Ethernet, this should be set to 14. For SLIP, this
- * should be set to 0.
- *
- * \note we probably won't use this constant for other link layers than
- * ethernet as they have variable header length (this is due to variable
- * number and type of address fields and to optional security features)
- * E.g.: 802.15.4 -> 2 + (1/2*4/8) + 0/5/6/10/14
- *       802.11 -> 4 + (6*3/4) + 2
- * \hideinitializer
- */
-#ifdef UIP_CONF_LLH_LEN
-#define UIP_LLH_LEN (UIP_CONF_LLH_LEN)
-#else /* UIP_LLH_LEN */
-#define UIP_LLH_LEN     0
-#endif /* UIP_CONF_LLH_LEN */
-
 /**
  * The size of the uIP packet buffer.
  *
@@ -151,12 +131,11 @@
  * \hideinitializer
  */
 #ifndef UIP_CONF_BUFFER_SIZE
-#define UIP_BUFSIZE (UIP_LINK_MTU + UIP_LLH_LEN)
+#define UIP_BUFSIZE (UIP_LINK_MTU)
 #else /* UIP_CONF_BUFFER_SIZE */
 #define UIP_BUFSIZE (UIP_CONF_BUFFER_SIZE)
 #endif /* UIP_CONF_BUFFER_SIZE */
 
-
 /**
  * Determines if statistics support should be compiled in.
  *
@@ -248,11 +227,6 @@ void uip_log(char *msg);
 /** The maximum transmission unit at the IP Layer*/
 #define UIP_LINK_MTU 1280
 
-#ifndef NETSTACK_CONF_WITH_IPV6
-/** Do we use IPv6 or not (default: no) */
-#define NETSTACK_CONF_WITH_IPV6                 0
-#endif
-
 #ifndef UIP_CONF_IPV6_QUEUE_PKT
 /** Do we do per %neighbor queuing during address resolution (default: no) */
 #define UIP_CONF_IPV6_QUEUE_PKT       0
@@ -440,15 +414,15 @@ void uip_log(char *msg);
  * The TCP maximum segment size.
  *
  * This is should not be to set to more than
- * UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN.
+ * UIP_BUFSIZE - UIP_IPTCPH_LEN.
  */
 #ifdef UIP_CONF_TCP_MSS
-#if UIP_CONF_TCP_MSS > (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
+#if UIP_CONF_TCP_MSS > (UIP_BUFSIZE - UIP_IPTCPH_LEN)
 #error UIP_CONF_TCP_MSS is too large for the current UIP_BUFSIZE
-#endif /* UIP_CONF_TCP_MSS > (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN) */
+#endif /* UIP_CONF_TCP_MSS > (UIP_BUFSIZE - UIP_IPTCPH_LEN) */
 #define UIP_TCP_MSS     (UIP_CONF_TCP_MSS)
 #else /* UIP_CONF_TCP_MSS */
-#define UIP_TCP_MSS     (UIP_BUFSIZE - UIP_LLH_LEN - UIP_TCPIP_HLEN)
+#define UIP_TCP_MSS     (UIP_BUFSIZE - UIP_IPTCPH_LEN)
 #endif /* UIP_CONF_TCP_MSS */
 
 /**
diff --git a/os/net/mac/ble/ble-l2cap.c b/os/net/mac/ble/ble-l2cap.c
index 076d919e8eed36f8aeaf6ed5925ec3d199e88609..fb755cc85316e8c755936aa4a540ecb1d1b3f5e5 100644
--- a/os/net/mac/ble/ble-l2cap.c
+++ b/os/net/mac/ble/ble-l2cap.c
@@ -505,6 +505,12 @@ off(void)
   return 0;
 }
 /*---------------------------------------------------------------------------*/
+static int
+max_payload(void)
+{
+  return BLE_L2CAP_NODE_MTU;
+}
+/*---------------------------------------------------------------------------*/
 const struct mac_driver ble_l2cap_driver = {
   "ble-l2cap",
   init,
@@ -512,6 +518,7 @@ const struct mac_driver ble_l2cap_driver = {
   input,
   on,
   off,
+  max_payload,
 };
 /*---------------------------------------------------------------------------*/
 PROCESS_THREAD(ble_l2cap_tx_process, ev, data)
diff --git a/os/net/mac/csma/anti-replay.c b/os/net/mac/csma/anti-replay.c
new file mode 100644
index 0000000000000000000000000000000000000000..347674184e6c0531a6433a42b107a272bc978cac
--- /dev/null
+++ b/os/net/mac/csma/anti-replay.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (c) 2014, Hasso-Plattner-Institut.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *         Protects against replay attacks by comparing with the last
+ *         unicast or broadcast frame counter of the sender.
+ * \author
+ *         Konrad Krentz <konrad.krentz@gmail.com>
+ */
+
+/**
+ * \addtogroup csma
+ * @{
+ */
+
+#include "net/mac/csma/anti-replay.h"
+#include "net/packetbuf.h"
+#include "net/mac/llsec802154.h"
+
+#if LLSEC802154_USES_FRAME_COUNTER
+
+/* This node's current frame counter value */
+static uint32_t counter;
+
+/*---------------------------------------------------------------------------*/
+void
+anti_replay_set_counter(void)
+{
+  frame802154_frame_counter_t reordered_counter;
+
+  ++counter;
+  reordered_counter.u32 = LLSEC802154_HTONL(counter);
+  
+  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1, reordered_counter.u16[0]);
+  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3, reordered_counter.u16[1]);
+}
+/*---------------------------------------------------------------------------*/
+uint32_t
+anti_replay_get_counter(void)
+{
+  frame802154_frame_counter_t disordered_counter;
+  
+  disordered_counter.u16[0] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1);
+  disordered_counter.u16[1] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3);
+  
+  return LLSEC802154_HTONL(disordered_counter.u32); 
+}
+/*---------------------------------------------------------------------------*/
+void
+anti_replay_init_info(struct anti_replay_info *info)
+{
+  info->last_broadcast_counter
+      = info->last_unicast_counter
+      = anti_replay_get_counter();
+}
+/*---------------------------------------------------------------------------*/
+int
+anti_replay_was_replayed(struct anti_replay_info *info)
+{
+  uint32_t received_counter;
+  
+  received_counter = anti_replay_get_counter();
+  
+  if(packetbuf_holds_broadcast()) {
+    /* broadcast */
+    if(received_counter <= info->last_broadcast_counter) {
+      return 1;
+    } else {
+      info->last_broadcast_counter = received_counter;
+      return 0;
+    }
+  } else {
+    /* unicast */
+    if(received_counter <= info->last_unicast_counter) {
+      return 1;
+    } else {
+      info->last_unicast_counter = received_counter;
+      return 0;
+    }
+  }
+}
+/*---------------------------------------------------------------------------*/
+#endif /* LLSEC802154_USES_FRAME_COUNTER */
+
+/** @} */
diff --git a/os/net/mac/csma/anti-replay.h b/os/net/mac/csma/anti-replay.h
new file mode 100644
index 0000000000000000000000000000000000000000..9211a6e7ad011959cec2f5a31b6c9a74e9f887db
--- /dev/null
+++ b/os/net/mac/csma/anti-replay.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2014, Hasso-Plattner-Institut.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *         Interface to anti-replay mechanisms.
+ * \author
+ *         Konrad Krentz <konrad.krentz@gmail.com>
+ */
+
+/**
+ * \addtogroup llsec802154
+ * @{
+ */
+
+#ifndef ANTI_REPLAY_H
+#define ANTI_REPLAY_H
+
+#include "contiki.h"
+
+struct anti_replay_info {
+  uint32_t last_broadcast_counter;
+  uint32_t last_unicast_counter;
+};
+
+/**
+ * \brief Sets the frame counter packetbuf attributes.
+ */
+void anti_replay_set_counter(void);
+
+/**
+ * \brief Gets the frame counter from packetbuf.
+ */
+uint32_t anti_replay_get_counter(void);
+
+/**
+ * \brief Initializes the anti-replay information about the sender
+ * \param info Anti-replay information about the sender
+ */
+void anti_replay_init_info(struct anti_replay_info *info);
+
+/**
+ * \brief               Checks if received frame was replayed
+ * \param info          Anti-replay information about the sender
+ * \retval 0            <-> received frame was not replayed
+ */
+int anti_replay_was_replayed(struct anti_replay_info *info);
+
+#endif /* ANTI_REPLAY_H */
+
+/** @} */
diff --git a/os/net/mac/csma/ccm-star-packetbuf.c b/os/net/mac/csma/ccm-star-packetbuf.c
new file mode 100644
index 0000000000000000000000000000000000000000..17b9befdc783b61d0e0be36b3b646a11694e6b85
--- /dev/null
+++ b/os/net/mac/csma/ccm-star-packetbuf.c
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2013, Hasso-Plattner-Institut.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *         CCM* convenience functions for LLSEC use
+ * \author
+ *         Justin King-Lacroix <justin.kinglacroix@gmail.com>
+ *         Konrad Krentz <konrad.krentz@gmail.com>
+ */
+
+#include "net/linkaddr.h"
+#include "net/packetbuf.h"
+#include "net/mac/llsec802154.h"
+#include <string.h>
+
+#if LLSEC802154_USES_AUX_HEADER && LLSEC802154_USES_FRAME_COUNTER
+
+/*---------------------------------------------------------------------------*/
+static const uint8_t *
+get_extended_address(const linkaddr_t *addr)
+#if LINKADDR_SIZE == 2
+{
+  /* workaround for short addresses: derive EUI64 as in RFC 6282 */
+  static linkaddr_extended_t template = { { 0x00 , 0x00 , 0x00 ,
+                                            0xFF , 0xFE , 0x00 , 0x00 , 0x00 } };
+  template.u16[3] = LLSEC802154_HTONS(addr->u16);
+
+  return template.u8;
+}
+#else /* LINKADDR_SIZE == 2 */
+{
+  return addr->u8;
+}
+#endif /* LINKADDR_SIZE == 2 */
+/*---------------------------------------------------------------------------*/
+void
+ccm_star_packetbuf_set_nonce(uint8_t *nonce, int forward)
+{
+  const linkaddr_t *source_addr;
+
+  source_addr = forward ? &linkaddr_node_addr : packetbuf_addr(PACKETBUF_ADDR_SENDER);
+  memcpy(nonce, get_extended_address(source_addr), 8);
+  nonce[8] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) >> 8;
+  nonce[9] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3) & 0xff;
+  nonce[10] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) >> 8;
+  nonce[11] = packetbuf_attr(PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1) & 0xff;
+  nonce[12] = packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL);
+}
+/*---------------------------------------------------------------------------*/
+#endif /* LLSEC802154_USES_AUX_HEADER && LLSEC802154_USES_FRAME_COUNTER */
diff --git a/os/net/mac/csma/ccm-star-packetbuf.h b/os/net/mac/csma/ccm-star-packetbuf.h
new file mode 100644
index 0000000000000000000000000000000000000000..578bdef963301c42d2cc5dc93ec1bb6029a2d010
--- /dev/null
+++ b/os/net/mac/csma/ccm-star-packetbuf.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2013, Hasso-Plattner-Institut.
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+#ifndef CCM_STAR_PACKETBUF_H_
+#define CCM_STAR_PACKETBUF_H_
+
+/*---------------------------------------------------------------------------*/
+void ccm_star_packetbuf_set_nonce(uint8_t *nonce, int forward);
+
+#endif /* CCM_STAR_PACKETBUF_H_ */
diff --git a/os/net/mac/csma/csma-output.c b/os/net/mac/csma/csma-output.c
index 1773e0cb00b8d2de9da8e307b0713bf946e5114b..6537439671275da08a0e546d7854f7b1d97fdbb8 100644
--- a/os/net/mac/csma/csma-output.c
+++ b/os/net/mac/csma/csma-output.c
@@ -40,6 +40,7 @@
  */
 
 #include "net/mac/csma/csma.h"
+#include "net/mac/csma/csma-security.h"
 #include "net/packetbuf.h"
 #include "net/queuebuf.h"
 #include "dev/watchdog.h"
@@ -49,6 +50,7 @@
 #include "net/netstack.h"
 #include "lib/list.h"
 #include "lib/memb.h"
+#include "lib/assert.h"
 
 /* Log configuration */
 #include "sys/log.h"
@@ -130,7 +132,10 @@ MEMB(packet_memb, struct packet_queue, MAX_QUEUED_PACKETS);
 MEMB(metadata_memb, struct qbuf_metadata, MAX_QUEUED_PACKETS);
 LIST(neighbor_list);
 
-static void packet_sent(void *ptr, int status, int num_transmissions);
+static void packet_sent(struct neighbor_queue *n,
+    struct packet_queue *q,
+    int status,
+    int num_transmissions);
 static void transmit_from_queue(void *ptr);
 /*---------------------------------------------------------------------------*/
 static struct neighbor_queue *
@@ -161,7 +166,7 @@ backoff_period(void)
 }
 /*---------------------------------------------------------------------------*/
 static int
-send_one_packet(void *ptr)
+send_one_packet(struct neighbor_queue *n, struct packet_queue *q)
 {
   int ret;
   int last_sent_ok = 0;
@@ -169,9 +174,16 @@ send_one_packet(void *ptr)
   packetbuf_set_addr(PACKETBUF_ADDR_SENDER, &linkaddr_node_addr);
   packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, 1);
 
-  if(NETSTACK_FRAMER.create() < 0) {
+#if LLSEC802154_ENABLED
+#if LLSEC802154_USES_EXPLICIT_KEYS
+  /* This should possibly be taken from upper layers in the future */
+  packetbuf_set_attr(PACKETBUF_ATTR_KEY_ID_MODE, CSMA_LLSEC_KEY_ID_MODE);
+#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
+#endif /* LLSEC802154_ENABLED */
+
+  if(csma_security_create_frame() < 0) {
     /* Failed to allocate space for headers */
-    LOG_ERR("failed to create packet\n");
+    LOG_ERR("failed to create packet, seqno: %d\n", packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO));
     ret = MAC_TX_ERR_FATAL;
   } else {
     int is_broadcast;
@@ -237,7 +249,7 @@ send_one_packet(void *ptr)
     last_sent_ok = 1;
   }
 
-  packet_sent(ptr, ret, 1);
+  packet_sent(n, q, ret, 1);
   return last_sent_ok;
 }
 /*---------------------------------------------------------------------------*/
@@ -255,7 +267,7 @@ transmit_from_queue(void *ptr)
         n->transmissions, list_length(n->packet_queue));
       /* Send first packet in the neighbor queue */
       queuebuf_to_packetbuf(q->buf);
-      send_one_packet(n);
+      send_one_packet(n, q);
     }
   }
 }
@@ -388,30 +400,15 @@ tx_ok(struct packet_queue *q, struct neighbor_queue *n, int num_transmissions)
 }
 /*---------------------------------------------------------------------------*/
 static void
-packet_sent(void *ptr, int status, int num_transmissions)
+packet_sent(struct neighbor_queue *n,
+    struct packet_queue *q,
+    int status,
+    int num_transmissions)
 {
-  struct neighbor_queue *n;
-  struct packet_queue *q;
+  assert(n != NULL);
+  assert(q != NULL);
 
-  n = ptr;
-  if(n == NULL) {
-    return;
-  }
-
-  /* Find out what packet this callback refers to */
-  for(q = list_head(n->packet_queue);
-      q != NULL; q = list_item_next(q)) {
-    if(queuebuf_attr(q->buf, PACKETBUF_ATTR_MAC_SEQNO) ==
-       packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO)) {
-      break;
-    }
-  }
-
-  if(q == NULL) {
-    LOG_WARN("packet sent: seqno %u not found\n",
-           packetbuf_attr(PACKETBUF_ATTR_MAC_SEQNO));
-    return;
-  } else if(q->ptr == NULL) {
+  if(q->ptr == NULL) {
     LOG_WARN("packet sent: no metadata\n");
     return;
   }
@@ -539,5 +536,4 @@ csma_output_init(void)
   memb_init(&packet_memb);
   memb_init(&metadata_memb);
   memb_init(&neighbor_memb);
-  queuebuf_init();
 }
diff --git a/os/net/mac/csma/csma-security.c b/os/net/mac/csma/csma-security.c
new file mode 100644
index 0000000000000000000000000000000000000000..0b44fa348d726dffaee6c0038ba68af10990b81f
--- /dev/null
+++ b/os/net/mac/csma/csma-security.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright (c) 2017, RISE SICS
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *         CSMA security
+ * \author
+ *         Joakim Eriksson <joakim.eriksson@ri.se>
+ */
+
+/**
+ * \addtogroup csma
+ * @{
+*/
+
+#include "contiki.h"
+#include "net/mac/csma/csma.h"
+#include "net/mac/csma/anti-replay.h"
+#include "net/mac/csma/csma-security.h"
+#include "net/mac/framer/frame802154.h"
+#include "net/mac/framer/framer-802154.h"
+#include "net/mac/llsec802154.h"
+#include "net/netstack.h"
+#include "net/packetbuf.h"
+#include "lib/ccm-star.h"
+#include "lib/aes-128.h"
+#include <stdio.h>
+#include <string.h>
+#include "ccm-star-packetbuf.h"
+/* Log configuration */
+#include "sys/log.h"
+#define LOG_MODULE "CSMA"
+#define LOG_LEVEL LOG_LEVEL_MAC
+
+#if LOG_LEVEL == LOG_LEVEL_DBG
+static const char * HEX = "0123456789ABCDEF";
+#endif
+
+#if LLSEC802154_USES_AUX_HEADER && LLSEC802154_USES_FRAME_COUNTER
+
+#define MIC_LEN(level) LLSEC802154_MIC_LEN(level)
+
+#if LLSEC802154_USES_EXPLICIT_KEYS
+#define LLSEC_KEY_INDEX (FRAME802154_IMPLICIT_KEY == packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE) \
+                          ? 0 \
+                          : packetbuf_attr(PACKETBUF_ATTR_KEY_INDEX))
+#define LLSEC_KEY_MODE (packetbuf_attr(PACKETBUF_ATTR_KEY_ID_MODE))
+#else
+#define LLSEC_KEY_INDEX (0)
+#define LLSEC_KEY_MODE (FRAME802154_IMPLICIT_KEY)
+#endif /* LLSEC802154_USES_EXPLICIT_KEYS */
+
+/**
+ *  The keys for LLSEC for CSMA
+ */
+typedef struct {
+  uint8_t u8[16];
+} aes_key_t;
+static aes_key_t keys[CSMA_LLSEC_MAXKEYS];
+
+/* assumed to be 16 bytes */
+int
+csma_security_set_key(uint8_t index, const uint8_t *key)
+{
+  if(key != NULL && index < CSMA_LLSEC_MAXKEYS) {
+    memcpy(keys[index].u8, key, 16);
+    return 1;
+  }
+  return 0;
+}
+
+#define N_KEYS (sizeof(keys) / sizeof(aes_key))
+/*---------------------------------------------------------------------------*/
+static int
+aead(uint8_t hdrlen, int forward)
+{
+  uint8_t totlen;
+  uint8_t nonce[CCM_STAR_NONCE_LENGTH];
+  uint8_t *m;
+  uint8_t m_len;
+  uint8_t *a;
+  uint8_t a_len;
+  uint8_t *result;
+  /* Allocate for MAX level */
+  uint8_t generated_mic[MIC_LEN(7)];
+  uint8_t *mic;
+  uint8_t key_index;
+  aes_key_t *key;
+  uint8_t with_encryption;
+
+  key_index = LLSEC_KEY_INDEX;
+  if(key_index >= CSMA_LLSEC_MAXKEYS) {
+    LOG_ERR("Key not available: %u\n", key_index);
+    return 0;
+  }
+
+  key = &keys[key_index];
+
+  ccm_star_packetbuf_set_nonce(nonce, forward);
+  totlen = packetbuf_totlen();
+  a = packetbuf_hdrptr();
+
+  with_encryption =
+    (packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & 0x4) ? 1 : 0;
+
+  if(with_encryption) {
+    a_len = hdrlen;
+    m = a + a_len;
+    m_len = totlen - hdrlen;
+  } else {
+    a_len = totlen;
+    m = NULL;
+    m_len = 0;
+  }
+
+  mic = a + totlen;
+  result = forward ? mic : generated_mic;
+
+  CCM_STAR.set_key(key->u8);
+  CCM_STAR.aead(nonce,
+      m, m_len,
+      a, a_len,
+      result, MIC_LEN(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & 0x07),
+      forward);
+
+  if(forward) {
+    packetbuf_set_datalen(packetbuf_datalen() + MIC_LEN(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & 0x07));
+    return 1;
+  } else {
+    return (memcmp(generated_mic, mic, MIC_LEN(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & 0x07)) == 0);
+  }
+}
+
+/*---------------------------------------------------------------------------*/
+int
+csma_security_create_frame(void)
+{
+  int hdr_len;
+
+  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
+  if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) > 0 &&
+     LLSEC_KEY_INDEX != 0xffff) {
+    anti_replay_set_counter();
+  }
+
+  hdr_len = NETSTACK_FRAMER.create();
+  if(hdr_len < 0) {
+    return hdr_len;
+  }
+
+  if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) > 0) {
+#if LOG_LEVEL == LOG_LEVEL_DBG
+    int i = 0;
+    uint8_t *p;
+    LOG_DBG("  Payload before (%d):", packetbuf_totlen());
+    p = packetbuf_hdrptr();
+    for(i = 0; i < packetbuf_totlen(); i++) {
+      LOG_DBG_("%c%c", HEX[(p[i] >> 4) & 0x0f], HEX[p[i] & 0x0f]);
+    }
+    LOG_DBG("\n");
+#endif
+
+    if(!aead(hdr_len, 1)) {
+      LOG_ERR("failed to encrypt packet to ");
+      LOG_ERR_LLADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
+      LOG_ERR_("\n");
+      return FRAMER_FAILED;
+    }
+    LOG_INFO("LLSEC-OUT:");
+    LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
+    LOG_INFO_(" ");
+    LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
+    LOG_INFO_(" %u (%u) LV:%d, KEY:0x%02x\n", packetbuf_datalen(), packetbuf_totlen(),
+              packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL), LLSEC_KEY_INDEX);
+
+#if LOG_LEVEL == LOG_LEVEL_DBG
+    LOG_DBG("  Payload after: (%d)", packetbuf_totlen());
+    p = packetbuf_hdrptr();
+    for(i = 0; i < packetbuf_totlen(); i++) {
+      LOG_DBG_("%c%c", HEX[(p[i] >> 4) & 0x0f], HEX[p[i] & 0x0f]);
+    }
+    LOG_DBG_("\n");
+#endif
+
+  }
+  return hdr_len;
+}
+
+/*---------------------------------------------------------------------------*/
+int
+csma_security_frame_len(void)
+{
+  if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) > 0 &&
+     LLSEC_KEY_INDEX != 0xffff) {
+    return NETSTACK_FRAMER.length() +
+      MIC_LEN(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & 0x07);
+  }
+  return NETSTACK_FRAMER.length();
+}
+/*---------------------------------------------------------------------------*/
+int
+csma_security_parse_frame(void)
+{
+  int hdr_len;
+
+  hdr_len = NETSTACK_FRAMER.parse();
+  if(hdr_len < 0) {
+    return hdr_len;
+  }
+
+  if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) == 0) {
+    /* No security - no more processing required */
+    return hdr_len;
+  }
+
+  LOG_INFO("LLSEC-IN: ");
+  LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
+  LOG_INFO_(" ");
+  LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
+  LOG_INFO_(" %d %u (%u) LV:%d KM:%d KEY:0x%02x\n", hdr_len, packetbuf_datalen(),
+            packetbuf_totlen(), packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL),
+            LLSEC_KEY_MODE,
+            LLSEC_KEY_INDEX);
+
+  if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) != CSMA_LLSEC_SECURITY_LEVEL) {
+    LOG_INFO("received frame with wrong security level (%u) from ",
+           packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL));
+    LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
+    LOG_INFO_("\n");
+    return FRAMER_FAILED;
+  }
+
+  if(LLSEC_KEY_MODE != CSMA_LLSEC_KEY_ID_MODE) {
+    LOG_INFO("received frame with wrong key id mode (%u) from ", LLSEC_KEY_MODE);
+    LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
+    LOG_INFO("\n");
+    return FRAMER_FAILED;
+  }
+
+  if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), &linkaddr_node_addr)) {
+    LOG_INFO("frame from ourselves\n");
+    return FRAMER_FAILED;
+  }
+
+  if(packetbuf_datalen() <= MIC_LEN(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & 0x07)) {
+    LOG_ERR("MIC error - too little data in frame!\n");
+    return FRAMER_FAILED;
+  }
+
+  packetbuf_set_datalen(packetbuf_datalen() - MIC_LEN(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) & 0x07));
+  if(!aead(hdr_len, 0)) {
+    LOG_INFO("received unauthentic frame %u from ",
+             (unsigned int) anti_replay_get_counter());
+    LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_SENDER));
+    LOG_INFO_("\n");
+    return FRAMER_FAILED;
+  }
+
+  /* TODO anti-reply protection */
+  return hdr_len;
+}
+/*---------------------------------------------------------------------------*/
+#else
+/* The "unsecure" version of the create frame / parse frame */
+int
+csma_security_create_frame(void)
+{
+  packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, FRAME802154_DATAFRAME);
+  return NETSTACK_FRAMER.create();
+}
+int
+csma_security_parse_frame(void)
+{
+  return NETSTACK_FRAMER.parse();
+}
+
+#endif /* LLSEC802154_USES_AUX_HEADER && LLSEC802154_USES_FRAME_COUNTER */
+
+/** @} */
diff --git a/os/net/mac/csma/csma-security.h b/os/net/mac/csma/csma-security.h
new file mode 100644
index 0000000000000000000000000000000000000000..97092b84d22bfe1112f798cc4ef3e55fb415c387
--- /dev/null
+++ b/os/net/mac/csma/csma-security.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2018, Tiny Mesh AS
+ * 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. Neither the name of the Institute nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
+ *
+ */
+
+/**
+ * \file
+ *         LLSEC802154 Security related configuration
+ * \author
+ *         Olav Frengstad <olav@tiny-mesh.com>
+ */
+
+#ifndef CSMA_SECURITY_H_
+#define CSMA_SECURITY_H_
+
+
+#ifdef CSMA_CONF_LLSEC_DEFAULT_KEY0
+#define CSMA_LLSEC_DEFAULT_KEY0 CSMA_CONF_LLSEC_DEFAULT_KEY0
+#else
+#define CSMA_LLSEC_DEFAULT_KEY0 {0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f}
+#endif
+
+#ifdef CSMA_CONF_LLSEC_SECURITY_LEVEL
+#define CSMA_LLSEC_SECURITY_LEVEL   CSMA_CONF_LLSEC_SECURITY_LEVEL
+#else
+#define CSMA_LLSEC_SECURITY_LEVEL   5
+#endif /* CSMA_CONF_LLSEC_SECURITY_LEVEL */
+
+#ifdef CSMA_CONF_LLSEC_KEY_ID_MODE
+#define CSMA_LLSEC_KEY_ID_MODE   CSMA_CONF_LLSEC_KEY_ID_MODE
+#else
+#define CSMA_LLSEC_KEY_ID_MODE   FRAME802154_IMPLICIT_KEY
+#endif /* CSMA_CONF_LLSEC_KEY_ID_MODE */
+
+#ifdef CSMA_CONF_LLSEC_KEY_INDEX
+#define CSMA_LLSEC_KEY_INDEX   CSMA_CONF_LLSEC_KEY_INDEX
+#else
+#define CSMA_LLSEC_KEY_INDEX   0
+#endif /* CSMA_CONF_LLSEC_KEY_INDEX */
+
+#ifdef CSMA_CONF_LLSEC_MAXKEYS
+#define CSMA_LLSEC_MAXKEYS CSMA_CONF_LLSEC_MAXKEYS
+#else
+#define CSMA_LLSEC_MAXKEYS 1
+#endif
+
+#endif /* CSMA_SECURITY_H_ */
diff --git a/os/net/mac/csma/csma.c b/os/net/mac/csma/csma.c
index 7259e35c8e80becfed2a4f30e3a2a0e326aea4d2..87aa6a1afe4e65ab7ea2dadb1d70a72cac6d35a8 100644
--- a/os/net/mac/csma/csma.c
+++ b/os/net/mac/csma/csma.c
@@ -49,10 +49,25 @@
 #define LOG_MODULE "CSMA"
 #define LOG_LEVEL LOG_LEVEL_MAC
 
+
+static void
+init_sec(void)
+{
+#if LLSEC802154_USES_AUX_HEADER
+  if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) ==
+     PACKETBUF_ATTR_SECURITY_LEVEL_DEFAULT) {
+    packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL,
+                       CSMA_LLSEC_SECURITY_LEVEL);
+  }
+#endif
+}
 /*---------------------------------------------------------------------------*/
 static void
 send_packet(mac_callback_t sent, void *ptr)
 {
+
+  init_sec();
+
   csma_output_packet(sent, ptr);
 }
 /*---------------------------------------------------------------------------*/
@@ -60,22 +75,20 @@ static void
 input_packet(void)
 {
 #if CSMA_SEND_SOFT_ACK
-  int original_datalen;
-  uint8_t *original_dataptr;
-
-  original_datalen = packetbuf_datalen();
-  original_dataptr = packetbuf_dataptr();
+  uint8_t ackdata[CSMA_ACK_LEN];
 #endif
 
   if(packetbuf_datalen() == CSMA_ACK_LEN) {
     /* Ignore ack packets */
     LOG_DBG("ignored ack\n");
-  } else if(NETSTACK_FRAMER.parse() < 0) {
+  } else if(csma_security_parse_frame() < 0) {
     LOG_ERR("failed to parse %u\n", packetbuf_datalen());
   } else if(!linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_RECEIVER),
                                          &linkaddr_node_addr) &&
             !packetbuf_holds_broadcast()) {
     LOG_WARN("not for us\n");
+  } else if(linkaddr_cmp(packetbuf_addr(PACKETBUF_ADDR_SENDER), &linkaddr_node_addr)) {
+    LOG_WARN("frame from ourselves\n");
   } else {
     int duplicate = 0;
 
@@ -91,20 +104,11 @@ input_packet(void)
     }
 
 #if CSMA_SEND_SOFT_ACK
-    {
-      frame802154_t info154;
-      frame802154_parse(original_dataptr, original_datalen, &info154);
-      if(info154.fcf.frame_type == FRAME802154_DATAFRAME &&
-         info154.fcf.ack_required != 0 &&
-         linkaddr_cmp((linkaddr_t *)&info154.dest_addr,
-                      &linkaddr_node_addr)) {
-        uint8_t ackdata[CSMA_ACK_LEN] = {0, 0, 0};
-
-        ackdata[0] = FRAME802154_ACKFRAME;
-        ackdata[1] = 0;
-        ackdata[2] = info154.seq;
-        NETSTACK_RADIO.send(ackdata, CSMA_ACK_LEN);
-      }
+    if(packetbuf_attr(PACKETBUF_ATTR_MAC_ACK)) {
+      ackdata[0] = FRAME802154_ACKFRAME;
+      ackdata[1] = 0;
+      ackdata[2] = ((uint8_t *)packetbuf_hdrptr())[2];
+      NETSTACK_RADIO.send(ackdata, CSMA_ACK_LEN);
     }
 #endif /* CSMA_SEND_SOFT_ACK */
     if(!duplicate) {
@@ -131,16 +135,41 @@ off(void)
 static void
 init(void)
 {
+
+#if LLSEC802154_USES_AUX_HEADER
+#ifdef CSMA_LLSEC_DEFAULT_KEY0
+  uint8_t key[16] = CSMA_LLSEC_DEFAULT_KEY0;
+  csma_security_set_key(0, key);
+#endif
+#endif /* LLSEC802154_USES_AUX_HEADER */
   csma_output_init();
   on();
 }
 /*---------------------------------------------------------------------------*/
+static int
+max_payload(void)
+{
+  int framer_hdrlen;
+
+  init_sec();
+
+  framer_hdrlen = NETSTACK_FRAMER.length();
+
+  if(framer_hdrlen < 0) {
+    /* Framing failed, we assume the maximum header length */
+    framer_hdrlen = CSMA_MAC_MAX_HEADER;
+  }
+
+  return CSMA_MAC_LEN - framer_hdrlen;
+}
+/*---------------------------------------------------------------------------*/
 const struct mac_driver csma_driver = {
   "CSMA",
   init,
   send_packet,
   input_packet,
   on,
-  off
+  off,
+  max_payload,
 };
 /*---------------------------------------------------------------------------*/
diff --git a/os/net/mac/csma/csma.h b/os/net/mac/csma/csma.h
index 9e0773f28fd9d30e2bb370a3a6d0f6988728e860..a2664ef0436703f8c244bad5d2688d4ae01d4e27 100644
--- a/os/net/mac/csma/csma.h
+++ b/os/net/mac/csma/csma.h
@@ -29,6 +29,13 @@
  * This file is part of the Contiki operating system.
  *
  */
+/**
+ * \addtogroup link-layer
+ * @{
+ *
+ * \defgroup csma Implementation of the 802.15.4 standard CSMA protocol
+ * @{
+*/
 
 /**
  * \file
@@ -43,6 +50,8 @@
 
 #include "contiki.h"
 #include "net/mac/mac.h"
+#include "net/packetbuf.h"
+#include "net/netstack.h"
 #include "dev/radio.h"
 
 #ifdef CSMA_CONF_SEND_SOFT_ACK
@@ -65,6 +74,29 @@
 
 #define CSMA_ACK_LEN 3
 
+/* Default MAC len for 802.15.4 classic */
+#ifdef  CSMA_MAC_CONF_LEN
+#define CSMA_MAC_LEN CSMA_MAC_CONF_LEN
+#else
+#define CSMA_MAC_LEN MIN(NETSTACK_RADIO_MAX_PAYLOAD_LEN, PACKETBUF_SIZE)
+#endif
+
+/* just a default - with LLSEC, etc */
+#define CSMA_MAC_MAX_HEADER 21
+
+
 extern const struct mac_driver csma_driver;
 
+/* CSMA security framer functions */
+int csma_security_create_frame(void);
+int csma_security_parse_frame(void);
+
+/* key management for CSMA */
+int csma_security_set_key(uint8_t index, const uint8_t *key);
+
+
 #endif /* CSMA_H_ */
+/**
+ * @}
+ * @}
+ */
diff --git a/os/net/mac/framer/framer-802154.c b/os/net/mac/framer/framer-802154.c
index b4c24da1933e2753befdc05b363fd485acaa65c6..8e92b9b2d1f569da1d43c8adeac993df81ad596c 100644
--- a/os/net/mac/framer/framer-802154.c
+++ b/os/net/mac/framer/framer-802154.c
@@ -240,6 +240,7 @@ parse(void)
 
   if(hdr_len && packetbuf_hdrreduce(hdr_len)) {
     packetbuf_set_attr(PACKETBUF_ATTR_FRAME_TYPE, frame.fcf.frame_type);
+    packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, frame.fcf.ack_required);
 
     if(frame.fcf.dest_addr_mode) {
       if(frame.dest_pid != frame802154_get_pan_id() &&
diff --git a/os/net/mac/framer/nullframer.c b/os/net/mac/framer/nullframer.c
index 019ed2209eda93e1cf2f9fc2ad321149f020affe..ae7bc925d22ee0df3259732885e5903feacf91db 100644
--- a/os/net/mac/framer/nullframer.c
+++ b/os/net/mac/framer/nullframer.c
@@ -87,6 +87,7 @@ parse(void)
     }
     packetbuf_set_addr(PACKETBUF_ADDR_SENDER, (linkaddr_t *)&frame.src_addr);
     packetbuf_set_attr(PACKETBUF_ATTR_MAC_SEQNO, frame.seq);
+    packetbuf_set_attr(PACKETBUF_ATTR_MAC_ACK, frame.fcf.ack_required);
     return 0;
   }
 #endif
diff --git a/os/net/mac/llsec802154.h b/os/net/mac/llsec802154.h
index fe1a9d231393b056d74d30757b314d033f369fb3..e808fef7a016a1323d545f487b365a22f04a1297 100644
--- a/os/net/mac/llsec802154.h
+++ b/os/net/mac/llsec802154.h
@@ -74,6 +74,12 @@
 #define LLSEC802154_USES_AUX_HEADER    LLSEC802154_ENABLED
 #endif /* LLSEC802154_CONF_USES_AUX_HEADER */
 
+#ifdef LLSEC802154_CONF_USES_FRAME_COUNTER
+#define LLSEC802154_USES_FRAME_COUNTER LLSEC802154_CONF_USES_FRAME_COUNTER
+#else
+#define LLSEC802154_USES_FRAME_COUNTER LLSEC802154_ENABLED
+#endif /* LLSEC802154_CONF_USES_FRAME_COUNTER */
+
 #if UIP_BYTE_ORDER == UIP_LITTLE_ENDIAN
 #define LLSEC802154_HTONS(n) (n)
 #define LLSEC802154_HTONL(n) (n)
diff --git a/os/net/mac/mac.h b/os/net/mac/mac.h
index 4f2a75b15143b0e38fb90f8052eb6c681794c126..f64838b4cb870d77c862bccc8c2dac93e5391e8e 100644
--- a/os/net/mac/mac.h
+++ b/os/net/mac/mac.h
@@ -76,6 +76,9 @@ struct mac_driver {
 
   /** Turn the MAC layer off. */
   int (* off)(void);
+
+  /** Read out estimated max payload size based on payload in packetbuf */
+  int (* max_payload)(void);
 };
 
 /* Generic MAC return values. */
diff --git a/os/net/mac/nullmac/nullmac.c b/os/net/mac/nullmac/nullmac.c
index a6199a3f9600889c76af74b72a39a7c6ea3d040b..de92ee5d8be0b0582d647a7fb90c70e60be4819c 100644
--- a/os/net/mac/nullmac/nullmac.c
+++ b/os/net/mac/nullmac/nullmac.c
@@ -67,6 +67,12 @@ off(void)
   return 0;
 }
 /*---------------------------------------------------------------------------*/
+static int
+max_payload(void)
+{
+  return 0;
+}
+/*---------------------------------------------------------------------------*/
 static void
 init(void)
 {
@@ -78,6 +84,7 @@ const struct mac_driver nullmac_driver = {
   send_packet,
   packet_input,
   on,
-  off
+  off,
+  max_payload,
 };
 /*---------------------------------------------------------------------------*/
diff --git a/os/net/mac/tsch/tsch-adaptive-timesync.c b/os/net/mac/tsch/tsch-adaptive-timesync.c
index cf10e9cf117e43e93c05c1f1b977293f910d66a3..2745abca21c1e06b293d018b000fd06346a53eef 100644
--- a/os/net/mac/tsch/tsch-adaptive-timesync.c
+++ b/os/net/mac/tsch/tsch-adaptive-timesync.c
@@ -45,6 +45,7 @@
 
 #include "net/mac/tsch/tsch.h"
 #include <stdio.h>
+#include <inttypes.h>
 
 #if TSCH_ADAPTIVE_TIMESYNC
 
diff --git a/os/net/mac/tsch/tsch-const.h b/os/net/mac/tsch/tsch-const.h
index d158c802c195c56f07e155e95fac99df540645a0..f07508a098db506d92603aa094f1e9ceeb223141 100644
--- a/os/net/mac/tsch/tsch-const.h
+++ b/os/net/mac/tsch/tsch-const.h
@@ -44,6 +44,7 @@
 
 /********** Includes **********/
 #include "net/packetbuf.h"
+#include "net/netstack.h"
 #include "net/mac/tsch/tsch-conf.h" /* Required for timestlot timing consts */
 
 /********** Constants **********/
@@ -66,8 +67,8 @@
 /* 1 channel, sequence length 1 */
 #define TSCH_HOPPING_SEQUENCE_1_1 (uint8_t[]){ 20 }
 
-/* Max TSCH packet lenght */
-#define TSCH_PACKET_MAX_LEN MIN(127, PACKETBUF_SIZE)
+/* Max TSCH packet lenght - last bytes are CRC in default 802.15.4 packets */
+#define TSCH_PACKET_MAX_LEN MIN(NETSTACK_RADIO_MAX_PAYLOAD_LEN, PACKETBUF_SIZE)
 
 /* The jitter to remove in ticks.
  * This should be the sum of measurement errors on Tx and Rx nodes.
diff --git a/os/net/mac/tsch/tsch-rpl.c b/os/net/mac/tsch/tsch-rpl.c
index 951648d91d5f45d34f309377a95a6019b85f6427..e8db94b574d0fa22d61130e8df1cd94a2c609e6a 100644
--- a/os/net/mac/tsch/tsch-rpl.c
+++ b/os/net/mac/tsch/tsch-rpl.c
@@ -136,5 +136,13 @@ tsch_rpl_callback_parent_switch(rpl_parent_t *old, rpl_parent_t *new)
         rpl_parent_get_ipaddr(new)));
   }
 }
+/*---------------------------------------------------------------------------*/
+/* Check RPL has joined DODAG.
+ * To use, set #define TSCH_RPL_CHECK_DODAG_JOINED tsch_rpl_check_dodag_joined */
+int
+tsch_rpl_check_dodag_joined(void)
+{
+  return NETSTACK_ROUTING.node_has_joined();
+}
 #endif /* UIP_CONF_IPV6_RPL */
 /** @} */
diff --git a/os/net/mac/tsch/tsch-rpl.h b/os/net/mac/tsch/tsch-rpl.h
index 23a148db86833e051f12f4830c2b77c8ed60db2a..95412e3d21d9a19a647e75cb9331ee53b99b2c43 100644
--- a/os/net/mac/tsch/tsch-rpl.h
+++ b/os/net/mac/tsch/tsch-rpl.h
@@ -79,6 +79,12 @@ void tsch_rpl_callback_new_dio_interval(clock_time_t dio_interval);
  * \param new The new RPL parent
  */
 void tsch_rpl_callback_parent_switch(rpl_parent_t *old, rpl_parent_t *new);
+/**
+ * \brief Check RPL has joined DODAG.
+ * To use, set TSCH_RPL_CHECK_DODAG_JOINED tsch_rpl_check_dodag_joined
+ * \return 1 if joined, 0 otherwise
+ */
+int tsch_rpl_check_dodag_joined(void);
 
 #endif /* __TSCH_RPL_H__ */
 /** @} */
diff --git a/os/net/mac/tsch/tsch-slot-operation.c b/os/net/mac/tsch/tsch-slot-operation.c
index a801bc92eeea4ae7eb648116e11b1d3619e6df68..a34b10fab5745e430e6fa0a436606cf8ff47639f 100644
--- a/os/net/mac/tsch/tsch-slot-operation.c
+++ b/os/net/mac/tsch/tsch-slot-operation.c
@@ -52,6 +52,7 @@
 #include "net/queuebuf.h"
 #include "net/mac/framer/framer-802154.h"
 #include "net/mac/tsch/tsch.h"
+#include "sys/critical.h"
 
 #include "sys/log.h"
 /* TSCH debug macros, i.e. to set LEDs or GPIOs on various TSCH
@@ -126,9 +127,10 @@ struct tsch_packet *dequeued_array[TSCH_DEQUEUED_ARRAY_SIZE];
 struct ringbufindex input_ringbuf;
 struct input_packet input_array[TSCH_MAX_INCOMING_PACKETS];
 
+/* Updates and reads of the next two variables must be atomic (i.e. both together) */
 /* Last time we received Sync-IE (ACK or data packet from a time source) */
 static struct tsch_asn_t last_sync_asn;
-clock_time_t last_sync_time; /* Same info, in clock_time_t units */
+clock_time_t tsch_last_sync_time; /* Same info, in clock_time_t units */
 
 /* A global lock for manipulating data structures safely from outside of interrupt */
 static volatile int tsch_locked = 0;
@@ -347,6 +349,33 @@ get_packet_and_neighbor_for_link(struct tsch_link *link, struct tsch_neighbor **
   return p;
 }
 /*---------------------------------------------------------------------------*/
+uint64_t
+tsch_get_network_uptime_ticks(void)
+{
+  uint64_t uptime_asn;
+  uint64_t uptime_ticks;
+  int_master_status_t status;
+
+  if(!tsch_is_associated) {
+    /* not associated, network uptime is not known */
+    return (uint64_t)-1;
+  }
+
+  status = critical_enter();
+
+  uptime_asn = last_sync_asn.ls4b + ((uint64_t)last_sync_asn.ms1b << 32);
+  /* first calculate the at the uptime at the last sync in rtimer ticks */
+  uptime_ticks = uptime_asn * tsch_timing[tsch_ts_timeslot_length];
+  /* then convert to clock ticks (assume that CLOCK_SECOND divides RTIMER_ARCH_SECOND) */
+  uptime_ticks /= (RTIMER_ARCH_SECOND / CLOCK_SECOND);
+  /* then add the ticks passed since the last timesync */
+  uptime_ticks += (clock_time() - tsch_last_sync_time);
+
+  critical_exit(status);
+
+  return uptime_ticks;
+}
+/*---------------------------------------------------------------------------*/
 /**
  * This function turns on the radio. Its semantics is dependent on
  * the value of TSCH_RADIO_ON_DURING_TIMESLOT constant:
@@ -623,7 +652,7 @@ PT_THREAD(tsch_tx_slot(struct pt *pt, struct rtimer *t))
                   tsch_timesync_update(current_neighbor, since_last_timesync, drift_correction);
                   /* Keep track of sync time */
                   last_sync_asn = tsch_current_asn;
-                  last_sync_time = clock_time();
+                  tsch_last_sync_time = clock_time();
                   tsch_schedule_keepalive();
                 }
                 mac_tx_status = MAC_TX_OK;
@@ -820,8 +849,12 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
 #endif /* LLSEC802154_ENABLED */
 
         if(frame_valid) {
-          if(linkaddr_cmp(&destination_address, &linkaddr_node_addr)
-             || linkaddr_cmp(&destination_address, &linkaddr_null)) {
+          /* Check that frome is for us or broadcast, AND that it is not from
+           * ourselves. This is for consistency with CSMA and to avoid adding
+           * ourselves to neighbor tables in case frames are being replayed. */
+          if((linkaddr_cmp(&destination_address, &linkaddr_node_addr)
+               || linkaddr_cmp(&destination_address, &linkaddr_null))
+             && !linkaddr_cmp(&source_address, &linkaddr_node_addr)) {
             int do_nack = 0;
             rx_count++;
             estimated_drift = RTIMER_CLOCK_DIFF(expected_rx_time, rx_start_time);
@@ -882,7 +915,7 @@ PT_THREAD(tsch_rx_slot(struct pt *pt, struct rtimer *t))
               int32_t since_last_timesync = TSCH_ASN_DIFF(tsch_current_asn, last_sync_asn);
               /* Keep track of last sync time */
               last_sync_asn = tsch_current_asn;
-              last_sync_time = clock_time();
+              tsch_last_sync_time = clock_time();
               /* Save estimated drift */
               drift_correction = -estimated_drift;
               is_drift_correction_used = 1;
@@ -1014,6 +1047,13 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
 
     /* End of slot operation, schedule next slot or resynchronize */
 
+    if(tsch_is_coordinator) {
+      /* Update the `last_sync_*` variables to avoid large errors
+       * in the application-level time synchronization */
+      last_sync_asn = tsch_current_asn;
+      tsch_last_sync_time = clock_time();
+    }
+
     /* Do we need to resynchronize? i.e., wait for EB again */
     if(!tsch_is_coordinator && (TSCH_ASN_DIFF(tsch_current_asn, last_sync_asn) >
         (100 * TSCH_CLOCK_TO_SLOTS(TSCH_DESYNC_THRESHOLD / 100, tsch_timing[tsch_ts_timeslot_length])))) {
@@ -1043,7 +1083,7 @@ PT_THREAD(tsch_slot_operation(struct rtimer *t, void *ptr))
 
         /* A burst link was scheduled. Replay the current link at the
         next time offset */
-        if(burst_link_scheduled) {
+        if(burst_link_scheduled && current_link != NULL) {
           timeslot_diff = 1;
           backup_link = NULL;
           /* Keep track of the number of repetitions */
@@ -1115,10 +1155,14 @@ void
 tsch_slot_operation_sync(rtimer_clock_t next_slot_start,
     struct tsch_asn_t *next_slot_asn)
 {
+  int_master_status_t status;
+
   current_slot_start = next_slot_start;
   tsch_current_asn = *next_slot_asn;
+  status = critical_enter();
   last_sync_asn = tsch_current_asn;
-  last_sync_time = clock_time();
+  tsch_last_sync_time = clock_time();
+  critical_exit(status);
   current_link = NULL;
 }
 /*---------------------------------------------------------------------------*/
diff --git a/os/net/mac/tsch/tsch-slot-operation.h b/os/net/mac/tsch/tsch-slot-operation.h
index b1c05697b264100fe91cff633e368a38647ebaf5..22547a2c91b3bd861970f43b9014bb4f55bb1844 100644
--- a/os/net/mac/tsch/tsch-slot-operation.h
+++ b/os/net/mac/tsch/tsch-slot-operation.h
@@ -56,7 +56,7 @@ extern struct tsch_packet *dequeued_array[TSCH_DEQUEUED_ARRAY_SIZE];
 extern struct ringbufindex input_ringbuf;
 extern struct input_packet input_array[TSCH_MAX_INCOMING_PACKETS];
 /* Last clock_time_t where synchronization happened */
-extern clock_time_t last_sync_time;
+extern clock_time_t tsch_last_sync_time;
 /* Counts the length of the current burst */
 extern int tsch_current_burst_count;
 
diff --git a/os/net/mac/tsch/tsch-timeslot-timing.c b/os/net/mac/tsch/tsch-timeslot-timing.c
index a75676101aa408e816405a8ee1a42c8d7671c1f4..1d598a4ae0da7ec6d9630570fcd3ce4a8434aaa4 100644
--- a/os/net/mac/tsch/tsch-timeslot-timing.c
+++ b/os/net/mac/tsch/tsch-timeslot-timing.c
@@ -61,7 +61,7 @@
  * (TxOffset - (RxWait / 2)) instead
  */
 
-const uint16_t tsch_timeslot_timing_us_10000[tsch_ts_elements_count] = {
+const tsch_timeslot_timing_usec tsch_timeslot_timing_us_10000 = {
    1800, /* CCAOffset */
     128, /* CCA */
    2120, /* TxOffset */
diff --git a/os/net/mac/tsch/tsch-types.h b/os/net/mac/tsch/tsch-types.h
index 20f9911f6812f7846a4806b89d6a01dc53d99cbb..1c2cdb13ab8c6aadbfa9f95aa16861c5e38aa23e 100644
--- a/os/net/mac/tsch/tsch-types.h
+++ b/os/net/mac/tsch/tsch-types.h
@@ -142,6 +142,12 @@ enum tsch_timeslot_timing_elements {
   tsch_ts_elements_count, /* Not a timing element */
 };
 
+/** \brief TSCH timeslot timing elements in rtimer ticks */
+typedef rtimer_clock_t tsch_timeslot_timing_ticks[tsch_ts_elements_count];
+
+/** \brief TSCH timeslot timing elements in micro-seconds */
+typedef uint16_t tsch_timeslot_timing_usec[tsch_ts_elements_count];
+
 /** \brief Stores data about an incoming packet */
 struct input_packet {
   uint8_t payload[TSCH_PACKET_MAX_LEN]; /* Packet payload */
diff --git a/os/net/mac/tsch/tsch.c b/os/net/mac/tsch/tsch.c
index 25b565809278134f890213894d1740387d58d19c..7256c30a2926eece29f8bf73d238fdfb3f272fc6 100644
--- a/os/net/mac/tsch/tsch.c
+++ b/os/net/mac/tsch/tsch.c
@@ -243,11 +243,49 @@ tsch_reset(void)
 }
 /* TSCH keep-alive functions */
 
+/*---------------------------------------------------------------------------*/
+/* Resynchronize to last_eb_nbr.
+ * Return non-zero if this function schedules the next keepalive.
+ * Return zero otherwise.
+ */
+static int
+resynchronize(const linkaddr_t *original_time_source_addr)
+{
+  const struct tsch_neighbor *current_time_source = tsch_queue_get_time_source();
+  if(current_time_source && !linkaddr_cmp(&current_time_source->addr, original_time_source_addr)) {
+    /* Time source has already been changed (e.g. by RPL). Let's see if it works. */
+    LOG_INFO("time source has been changed to ");
+    LOG_INFO_LLADDR(&current_time_source->addr);
+    LOG_INFO_("\n");
+    return 0;
+  }
+  /* Switch time source to the last neighbor we received an EB from */
+  if(linkaddr_cmp(&last_eb_nbr_addr, &linkaddr_null)) {
+    LOG_WARN("not able to re-synchronize, received no EB from other neighbors\n");
+    if(sync_count == 0) {
+      /* We got no synchronization at all in this session, leave the network */
+      tsch_disassociate();
+    }
+    return 0;
+  } else {
+    LOG_WARN("re-synchronizing on ");
+    LOG_WARN_LLADDR(&last_eb_nbr_addr);
+    LOG_WARN_("\n");
+    /* We simply pick the last neighbor we receiver sync information from */
+    tsch_queue_update_time_source(&last_eb_nbr_addr);
+    tsch_join_priority = last_eb_nbr_jp + 1;
+    /* Try to get in sync ASAP */
+    tsch_schedule_keepalive_immediately();
+    return 1;
+  }
+}
+
 /*---------------------------------------------------------------------------*/
 /* Tx callback for keepalive messages */
 static void
 keepalive_packet_sent(void *ptr, int status, int transmissions)
 {
+  int schedule_next_keepalive = 1;
   /* Update neighbor link statistics */
   link_stats_packet_sent(packetbuf_addr(PACKETBUF_ADDR_RECEIVER), status, transmissions);
   /* Call RPL callback if RPL is enabled */
@@ -258,28 +296,14 @@ keepalive_packet_sent(void *ptr, int status, int transmissions)
   LOG_INFO_LLADDR(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
   LOG_INFO_(", st %d-%d\n", status, transmissions);
 
-  /* We got no ack, try to recover by switching to the last neighbor we received an EB from */
+  /* We got no ack, try to resynchronize */
   if(status == MAC_TX_NOACK) {
-    if(linkaddr_cmp(&last_eb_nbr_addr, &linkaddr_null)) {
-      LOG_WARN("not able to re-synchronize, received no EB from other neighbors\n");
-      if(sync_count == 0) {
-        /* We got no synchronization at all in this session, leave the network */
-        tsch_disassociate();
-      }
-    } else {
-      LOG_WARN("re-synchronizing on ");
-      LOG_WARN_LLADDR(&last_eb_nbr_addr);
-      LOG_WARN_("\n");
-      /* We simply pick the last neighbor we receiver sync information from */
-      tsch_queue_update_time_source(&last_eb_nbr_addr);
-      tsch_join_priority = last_eb_nbr_jp + 1;
-      /* Try to get in sync ASAP */
-      tsch_schedule_keepalive_immediately();
-      return;
-    }
+    schedule_next_keepalive = !resynchronize(packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
   }
 
-  tsch_schedule_keepalive();
+  if(schedule_next_keepalive) {
+    tsch_schedule_keepalive();
+  }
 }
 /*---------------------------------------------------------------------------*/
 /* Prepare and send a keepalive message */
@@ -511,7 +535,7 @@ tsch_disassociate(void)
 {
   if(tsch_is_associated == 1) {
     tsch_is_associated = 0;
-    process_post(&tsch_process, PROCESS_EVENT_POLL, NULL);
+    process_poll(&tsch_process);
   }
 }
 /*---------------------------------------------------------------------------*/
@@ -837,7 +861,12 @@ PROCESS_THREAD(tsch_send_eb_process, ev, data)
   while(1) {
     unsigned long delay;
 
-    if(tsch_is_associated && tsch_current_eb_period > 0) {
+    if(tsch_is_associated && tsch_current_eb_period > 0
+#ifdef TSCH_RPL_CHECK_DODAG_JOINED
+      /* Implementation section 6.3 of RFC 8180 */
+      && TSCH_RPL_CHECK_DODAG_JOINED()
+#endif /* TSCH_RPL_CHECK_DODAG_JOINED */
+        ) {
       /* Enqueue EB only if there isn't already one in queue */
       if(tsch_queue_packet_count(&tsch_eb_address) == 0) {
         uint8_t hdr_len = 0;
@@ -948,8 +977,7 @@ tsch_init(void)
     return;
   }
 
-  /* Init the queuebuf and TSCH sub-modules */
-  queuebuf_init();
+  /* Init TSCH sub-modules */
   tsch_reset();
   tsch_queue_init();
   tsch_schedule_init();
@@ -1128,13 +1156,21 @@ turn_off(void)
   return 1;
 }
 /*---------------------------------------------------------------------------*/
+static int
+max_payload(void)
+{
+  /* Setup security... before. */
+  return TSCH_PACKET_MAX_LEN -  NETSTACK_FRAMER.length();
+}
+/*---------------------------------------------------------------------------*/
 const struct mac_driver tschmac_driver = {
   "TSCH",
   tsch_init,
   send_packet,
   packet_input,
   turn_on,
-  turn_off
+  turn_off,
+  max_payload,
 };
 /*---------------------------------------------------------------------------*/
 /** @} */
diff --git a/os/net/mac/tsch/tsch.h b/os/net/mac/tsch/tsch.h
index db23b4851d061c93062a546644d7c46ee7f3213a..6991c08c44bc0a5e74ad471d0418d431ec629cbf 100644
--- a/os/net/mac/tsch/tsch.h
+++ b/os/net/mac/tsch/tsch.h
@@ -88,6 +88,10 @@ frequency hopping for enhanced reliability.
 #define TSCH_CALLBACK_KA_SENT tsch_rpl_callback_ka_sent
 #endif /* TSCH_CALLBACK_KA_SENT */
 
+#ifndef TSCH_RPL_CHECK_DODAG_JOINED
+#define TSCH_RPL_CHECK_DODAG_JOINED tsch_rpl_check_dodag_joined
+#endif /* TSCH_RPL_CHECK_DODAG_JOINED */
+
 #endif /* UIP_CONF_IPV6_RPL */
 
 #if BUILD_WITH_ORCHESTRA
@@ -117,6 +121,11 @@ void TSCH_CALLBACK_LEAVING_NETWORK();
 void TSCH_CALLBACK_KA_SENT();
 #endif
 
+/* Called by TSCH before sending a EB */
+#ifdef TSCH_RPL_CHECK_DODAG_JOINED
+int TSCH_RPL_CHECK_DODAG_JOINED();
+#endif
+
 /* Called by TSCH form interrupt after receiving a frame, enabled upper-layer to decide
  * whether to ACK or NACK */
 #ifdef TSCH_CALLBACK_DO_NACK
@@ -158,9 +167,9 @@ extern uint8_t tsch_current_channel;
 extern uint8_t tsch_hopping_sequence[TSCH_HOPPING_SEQUENCE_MAX_LEN];
 extern struct tsch_asn_divisor_t tsch_hopping_sequence_length;
 /* TSCH timeslot timing (in micro-second) */
-extern uint16_t tsch_timing_us[tsch_ts_elements_count];
+extern tsch_timeslot_timing_usec tsch_timing_us;
 /* TSCH timeslot timing (in rtimer ticks) */
-extern rtimer_clock_t tsch_timing[tsch_ts_elements_count];
+extern tsch_timeslot_timing_ticks tsch_timing;
 /* Statistics on the current session */
 extern unsigned long tx_count;
 extern unsigned long rx_count;
@@ -168,7 +177,7 @@ extern unsigned long sync_count;
 extern int32_t min_drift_seen;
 extern int32_t max_drift_seen;
 /* The TSCH standard 10ms timeslot timing */
-extern const uint16_t tsch_timeslot_timing_us_10000[tsch_ts_elements_count];
+extern const tsch_timeslot_timing_usec tsch_timeslot_timing_us_10000;
 
 /* TSCH processes */
 PROCESS_NAME(tsch_process);
@@ -226,6 +235,12 @@ void tsch_schedule_keepalive(void);
   * Schedule a keep-alive immediately
   */
 void tsch_schedule_keepalive_immediately(void);
+/**
+  * Get the time, in clock ticks, since the TSCH network was started.
+  *
+  * \return The network uptime, or -1 if the node is not part of a TSCH network.
+  */
+uint64_t tsch_get_network_uptime_ticks(void);
 /**
   * Leave the TSCH network we are currently in
   */
diff --git a/os/net/nbr-table.c b/os/net/nbr-table.c
index 8a8eaeb78027f5a5c9a3c91d2ca8561dcf986d3a..588315e58a32d7795b88bcb971d5a75a1e035293 100644
--- a/os/net/nbr-table.c
+++ b/os/net/nbr-table.c
@@ -354,6 +354,10 @@ nbr_table_add_lladdr(nbr_table_t *table, const linkaddr_t *lladdr, nbr_table_rea
   nbr_table_item_t *item;
   nbr_table_key_t *key;
 
+  if(table == NULL) {
+    return NULL;
+  }
+
   /* Allow lladdr-free insertion, useful e.g. for IPv6 ND.
    * Only one such entry is possible at a time, indexed by linkaddr_null. */
   if(lladdr == NULL) {
diff --git a/os/net/netstack.h b/os/net/netstack.h
index 8528e3fffe01a2b6f516b6744788bcdf3501cf6f..dcfc1d344481480fec5892a5a4d93151972fb602 100644
--- a/os/net/netstack.h
+++ b/os/net/netstack.h
@@ -44,7 +44,7 @@
 #include "contiki.h"
 
 /* Routing protocol configuration. The Routing protocol is configured through the Makefile,
-   via the flag MAC_ROUTING */
+   via the flag MAKE_ROUTING */
 #ifdef NETSTACK_CONF_ROUTING
 #define NETSTACK_ROUTING NETSTACK_CONF_ROUTING
 #else /* NETSTACK_CONF_ROUTING */
@@ -60,7 +60,7 @@
 #endif /* NETSTACK_CONF_ROUTING */
 
 /* Network layer configuration. The NET layer is configured through the Makefile,
-   via the flag MAC_NET */
+   via the flag MAKE_NET */
 #ifdef NETSTACK_CONF_NETWORK
 #define NETSTACK_NETWORK NETSTACK_CONF_NETWORK
 #else /* NETSTACK_CONF_NETWORK */
@@ -96,6 +96,8 @@
 #define NETSTACK_RADIO NETSTACK_CONF_RADIO
 #else /* NETSTACK_CONF_RADIO */
 #define NETSTACK_RADIO   nullradio_driver
+/* for nullradio, allow unlimited packet size */
+#define nullradio_driver_max_payload_len ((unsigned short)-1)
 #endif /* NETSTACK_CONF_RADIO */
 
 /* Framer selection. The framer is used by the MAC implementation
@@ -106,6 +108,12 @@
 #define NETSTACK_FRAMER   framer_802154
 #endif /* NETSTACK_CONF_FRAMER */
 
+/* Maximal packet length. Each radio driver should define this.
+   When Contiki-NG is compiled for a specific platform (radio), that value is used. */
+#define NETSTACK_RADIO_MAX_PAYLOAD_LEN_XX(radio) radio##_max_payload_len
+#define NETSTACK_RADIO_MAX_PAYLOAD_LEN_X(radio) NETSTACK_RADIO_MAX_PAYLOAD_LEN_XX(radio)
+#define NETSTACK_RADIO_MAX_PAYLOAD_LEN NETSTACK_RADIO_MAX_PAYLOAD_LEN_X(NETSTACK_RADIO)
+
 #include "net/mac/mac.h"
 #include "net/mac/framer/framer.h"
 #include "dev/radio.h"
diff --git a/os/net/packetbuf.h b/os/net/packetbuf.h
index 20e07147486865304bc7dd823e496b7d9c0ac0a8..c077ae940b65ae6fcdee23ec56bdeaa852b887ec 100644
--- a/os/net/packetbuf.h
+++ b/os/net/packetbuf.h
@@ -55,6 +55,7 @@
 #include "contiki.h"
 #include "net/linkaddr.h"
 #include "net/mac/llsec802154.h"
+#include "net/mac/csma/csma-security.h"
 #include "net/mac/tsch/tsch-conf.h"
 
 /**
@@ -238,6 +239,11 @@ enum {
   PACKETBUF_ATTR_KEY_INDEX,
 #endif /* LLSEC802154_USES_EXPLICIT_KEYS */
 
+#if LLSEC802154_USES_FRAME_COUNTER
+  PACKETBUF_ATTR_FRAME_COUNTER_BYTES_0_1,
+  PACKETBUF_ATTR_FRAME_COUNTER_BYTES_2_3,
+#endif /* LLSEC802154_USES_FRAME_COUNTER */
+
   /* Scope 2 attributes: used between end-to-end nodes. */
   /* These must be last */
   PACKETBUF_ADDR_SENDER,
@@ -277,6 +283,8 @@ void              packetbuf_attr_copyfrom(struct packetbuf_attr *attrs,
 #define PACKETBUF_ATTR_BYTE 8
 #define PACKETBUF_ADDRSIZE (LINKADDR_SIZE * PACKETBUF_ATTR_BYTE)
 
+#define PACKETBUF_ATTR_SECURITY_LEVEL_DEFAULT 0xffff
+
 struct packetbuf_attrlist {
   uint8_t type;
   uint8_t len;
diff --git a/os/net/queuebuf.h b/os/net/queuebuf.h
index 60216465d3e2590449b4a4b204d707bc21b097f7..ef66da780eb353b4967388d87c2620abed40d22b 100644
--- a/os/net/queuebuf.h
+++ b/os/net/queuebuf.h
@@ -55,6 +55,12 @@
 
 #include "net/packetbuf.h"
 
+#ifdef QUEUEBUF_CONF_ENABLED
+#define QUEUEBUF_ENABLED QUEUEBUF_CONF_ENABLED
+#else /* QUEUEBUF_CONF_ENABLED */
+#define QUEUEBUF_ENABLED 1
+#endif /* QUEUEBUF_CONF_ENABLED */
+
 /* QUEUEBUF_NUM is the total number of queuebuf */
 #ifdef QUEUEBUF_CONF_NUM
 #define QUEUEBUF_NUM QUEUEBUF_CONF_NUM
diff --git a/os/net/routing/nullrouting/nullrouting.c b/os/net/routing/nullrouting/nullrouting.c
index bb1399fbb6d545fe647aa4d6ba0689d0f6c53c28..aeb6550ac8b5894a3aec8186739c411adb3f7146 100644
--- a/os/net/routing/nullrouting/nullrouting.c
+++ b/os/net/routing/nullrouting/nullrouting.c
@@ -30,7 +30,7 @@
  */
 
 /**
- * \addtogroup null-routing
+ * \addtogroup routing
  * @{
  *
  * \file
@@ -103,11 +103,13 @@ local_repair(const char *str)
 {
 }
 /*---------------------------------------------------------------------------*/
-static void
+static bool
 ext_header_remove(void)
 {
 #if NETSTACK_CONF_WITH_IPV6
-  uip_ext_len = 0;
+  return uip_remove_ext_hdr();
+#else
+  return true;
 #endif /* NETSTACK_CONF_WITH_IPV6 */
 }
 /*---------------------------------------------------------------------------*/
@@ -118,7 +120,7 @@ ext_header_update(void)
 }
 /*---------------------------------------------------------------------------*/
 static int
-ext_header_hbh_update(int uip_ext_opt_offset)
+ext_header_hbh_update(uint8_t *ext_buf, int opt_offset)
 {
   return 1;
 }
diff --git a/os/net/routing/routing.h b/os/net/routing/routing.h
index 7fe6e7ca8ea0d1603d73bf6ea3da71bf9d05e68d..89e486711506746cbb88ba1a998e8006d83caa23 100644
--- a/os/net/routing/routing.h
+++ b/os/net/routing/routing.h
@@ -29,6 +29,13 @@
  * This file is part of the Contiki operating system.
  *
  */
+/**
+ * \addtogroup net-layer
+ * @{
+ *
+ * \defgroup routing An API for routing
+ * @{
+*/
 
 /**
  * \file
@@ -57,7 +64,7 @@ struct routing_driver {
   /**
    * Set the prefix, for nodes that will operate as root
    *
-   * \param prefix The prefix. If NULL, UIP_DS6_DEFAULT_PREFIX is used instead
+   * \param prefix The prefix. If NULL, uip_ds6_default_prefix() is used instead
    * \param iid The IID. If NULL, it will be built from uip_ds6_set_addr_iid.
   */
   void (* root_set_prefix)(uip_ipaddr_t *prefix, uip_ipaddr_t *iid);
@@ -119,8 +126,10 @@ struct routing_driver {
   void (* local_repair)(const char *str);
   /**
    * Removes all extension headers that pertain to the routing protocol.
+   *
+   * \return true in case of success, false otherwise
   */
-  void (* ext_header_remove)(void);
+  bool (* ext_header_remove)(void);
   /**
    * Adds/updates routing protocol extension headers to current uIP packet.
    *
@@ -131,12 +140,13 @@ struct routing_driver {
   * Process and update the routing protocol hob-by-hop
   * extention headers of the current uIP packet.
   *
-  * \param uip_ext_opt_offset The offset within the uIP packet where
-  * extension headers start
+  * \param ext_buf A pointer to the ext header buffer
+  * \param opt_offset The offset within the extension header where
+  * the option starts
   * \return 1 in case the packet is valid and to be processed further,
   * 0 in case the packet must be dropped.
   */
-  int (* ext_header_hbh_update)(int uip_ext_opt_offset);
+  int (* ext_header_hbh_update)(uint8_t *ext_buf, int opt_offset);
   /**
   * Process and update SRH in-place,
   * i.e. internal address swapping as per RFC6554
@@ -175,3 +185,7 @@ struct routing_driver {
 };
 
 #endif /* ROUTING_H_ */
+/**
+ * @}
+ * @}
+ */
diff --git a/os/net/routing/rpl-classic/rpl-dag-root.c b/os/net/routing/rpl-classic/rpl-dag-root.c
index 3a0162627e01da2bbb9231a684af379275490fb7..f45c2d317d25b4f9b5fe4a29e4edbfe3ea44e087 100644
--- a/os/net/routing/rpl-classic/rpl-dag-root.c
+++ b/os/net/routing/rpl-classic/rpl-dag-root.c
@@ -48,12 +48,15 @@ static void
 set_global_address(uip_ipaddr_t *prefix, uip_ipaddr_t *iid)
 {
   static uip_ipaddr_t root_ipaddr;
+  const uip_ipaddr_t *default_prefix;
   int i;
 
+  default_prefix = uip_ds6_default_prefix();
+
   /* Assign a unique local address (RFC4193,
      http://tools.ietf.org/html/rfc4193). */
   if(prefix == NULL) {
-    uip_ip6addr(&root_ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
+    uip_ip6addr_copy(&root_ipaddr, default_prefix);
   } else {
     memcpy(&root_ipaddr, prefix, 8);
   }
@@ -115,9 +118,11 @@ rpl_dag_root_start(void)
     if(root_if != NULL) {
       rpl_dag_t *dag;
       uip_ipaddr_t prefix;
+      const uip_ipaddr_t *default_prefix;
 
       rpl_set_root(RPL_DEFAULT_INSTANCE, ipaddr);
       dag = rpl_get_any_dag();
+      default_prefix = uip_ds6_default_prefix();
 
       /* If there are routes in this dag, we remove them all as we are
          from now on the new dag root and the old routes are wrong */
@@ -129,7 +134,7 @@ rpl_dag_root_start(void)
         dag->instance->def_route = NULL;
       }
 
-      uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
+      uip_ip6addr_copy(&prefix, default_prefix);
       rpl_set_prefix(dag, &prefix, 64);
       LOG_INFO("root_set_prefix: created a new RPL dag\n");
       return 0;
diff --git a/os/net/routing/rpl-classic/rpl-dag.c b/os/net/routing/rpl-classic/rpl-dag.c
index cbaee6959143f5ff34beba3fd59eb2f0cd668fe2..e1a4042d2ce12421b248077ccc67222aaa1256ec 100644
--- a/os/net/routing/rpl-classic/rpl-dag.c
+++ b/os/net/routing/rpl-classic/rpl-dag.c
@@ -101,23 +101,24 @@ rpl_print_neighbor_list(void)
     rpl_parent_t *p = nbr_table_head(rpl_parents);
     clock_time_t clock_now = clock_time();
 
-    printf("RPL: MOP %u OCP %u rank %u dioint %u, nbr count %u\n",
+    LOG_DBG("RPL: MOP %u OCP %u rank %u dioint %u, nbr count %u\n",
         default_instance->mop, default_instance->of->ocp, curr_rank, curr_dio_interval, uip_ds6_nbr_num());
     while(p != NULL) {
       const struct link_stats *stats = rpl_get_parent_link_stats(p);
-      printf("RPL: nbr %3u %5u, %5u => %5u -- %2u %c%c (last tx %u min ago)\n",
-          rpl_parent_get_ipaddr(p)->u8[15],
+      uip_ipaddr_t *parent_addr = rpl_parent_get_ipaddr(p);
+      LOG_DBG("RPL: nbr %02x %5u, %5u => %5u -- %2u %c%c (last tx %u min ago)\n",
+          parent_addr != NULL ? parent_addr->u8[15] : 0x0,
           p->rank,
           rpl_get_parent_link_metric(p),
           rpl_rank_via_parent(p),
           stats != NULL ? stats->freshness : 0,
           link_stats_is_fresh(stats) ? 'f' : ' ',
           p == default_instance->current_dag->preferred_parent ? 'p' : ' ',
-          (unsigned)((clock_now - stats->last_tx_time) / (60 * CLOCK_SECOND))
+          stats != NULL ? (unsigned)((clock_now - stats->last_tx_time) / (60 * CLOCK_SECOND)) : -1u
       );
       p = nbr_table_next(rpl_parents, p);
     }
-    printf("RPL: end of list\n");
+    LOG_DBG("RPL: end of list\n");
   }
 }
 /*---------------------------------------------------------------------------*/
@@ -126,7 +127,7 @@ rpl_get_nbr(rpl_parent_t *parent)
 {
   const linkaddr_t *lladdr = rpl_get_parent_lladdr(parent);
   if(lladdr != NULL) {
-    return nbr_table_get_from_lladdr(ds6_neighbors, lladdr);
+    return uip_ds6_nbr_ll_lookup((const uip_lladdr_t *)lladdr);
   } else {
     return NULL;
   }
@@ -145,9 +146,9 @@ rpl_dag_init(void)
 }
 /*---------------------------------------------------------------------------*/
 rpl_parent_t *
-rpl_get_parent(uip_lladdr_t *addr)
+rpl_get_parent(const uip_lladdr_t *addr)
 {
-  rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (linkaddr_t *)addr);
+  rpl_parent_t *p = nbr_table_get_from_lladdr(rpl_parents, (const linkaddr_t *)addr);
   return p;
 }
 /*---------------------------------------------------------------------------*/
@@ -196,6 +197,9 @@ uip_ipaddr_t *
 rpl_parent_get_ipaddr(rpl_parent_t *p)
 {
   const linkaddr_t *lladdr = rpl_get_parent_lladdr(p);
+  if(lladdr == NULL) {
+    return NULL;
+  }
   return uip_ds6_nbr_ipaddr_from_lladdr((uip_lladdr_t *)lladdr);
 }
 /*---------------------------------------------------------------------------*/
@@ -368,15 +372,16 @@ rpl_set_root(uint8_t instance_id, uip_ipaddr_t *dag_id)
         if(uip_ipaddr_cmp(&dag->dag_id, dag_id)) {
           version = dag->version;
           RPL_LOLLIPOP_INCREMENT(version);
-        }
-        if(dag == dag->instance->current_dag) {
-          LOG_INFO("Dropping a joined DAG when setting this node as root\n");
-          rpl_set_default_route(instance, NULL);
-          dag->instance->current_dag = NULL;
         } else {
-          LOG_INFO("Dropping a DAG when setting this node as root\n");
+          if(dag == dag->instance->current_dag) {
+            LOG_INFO("Dropping a joined DAG when setting this node as root\n");
+            rpl_set_default_route(instance, NULL);
+            dag->instance->current_dag = NULL;
+          } else {
+            LOG_INFO("Dropping a DAG when setting this node as root\n");
+          }
+          rpl_free_dag(dag);
         }
-        rpl_free_dag(dag);
       }
     }
   }
@@ -552,7 +557,7 @@ rpl_set_default_route(rpl_instance_t *instance, uip_ipaddr_t *from)
   if(from != NULL) {
     LOG_DBG("Adding default route through ");
     LOG_DBG_6ADDR(from);
-    LOG_DBG("\n");
+    LOG_DBG_("\n");
     instance->def_route = uip_ds6_defrt_add(from,
         RPL_DEFAULT_ROUTE_INFINITE_LIFETIME ? 0 : RPL_LIFETIME(instance, instance->default_lifetime));
     if(instance->def_route == NULL) {
@@ -1397,7 +1402,7 @@ rpl_process_parent_event(rpl_instance_t *instance, rpl_parent_t *p)
     rpl_remove_routes_by_nexthop(rpl_parent_get_ipaddr(p), p->dag);
   }
 
-  if(!acceptable_rank(p->dag, p->rank)) {
+  if(!acceptable_rank(p->dag, rpl_rank_via_parent(p))) {
     /* The candidate parent is no longer valid: the rank increase resulting
        from the choice of it as a parent would be too high. */
     LOG_WARN("Unacceptable rank %u (Current min %u, MaxRankInc %u)\n", (unsigned)p->rank,
diff --git a/os/net/routing/rpl-classic/rpl-ext-header.c b/os/net/routing/rpl-classic/rpl-ext-header.c
index 8488d5ac63391844af4e22a63a4596e45bf3b706..173f78c2be0781309ffa9429451a544b67794b03 100644
--- a/os/net/routing/rpl-classic/rpl-ext-header.c
+++ b/os/net/routing/rpl-classic/rpl-ext-header.c
@@ -60,46 +60,35 @@
 #include <limits.h>
 #include <string.h>
 
-/*---------------------------------------------------------------------------*/
-#define UIP_IP_BUF                ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-#define UIP_EXT_BUF               ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_HBHO_BUF              ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_HBHO_NEXT_BUF         ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_HOP_BY_HOP_LEN])
-#define UIP_RH_BUF                ((struct uip_routing_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_RPL_SRH_BUF           ((struct uip_rpl_srh_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_RH_LEN])
-#define UIP_EXT_HDR_OPT_BUF       ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
-#define UIP_EXT_HDR_OPT_PADN_BUF  ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
-#define UIP_EXT_HDR_OPT_RPL_BUF   ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
 /*---------------------------------------------------------------------------*/
 int
-rpl_ext_header_hbh_update(int uip_ext_opt_offset)
+rpl_ext_header_hbh_update(uint8_t *ext_buf, int opt_offset)
 {
   rpl_instance_t *instance;
   int down;
   uint16_t sender_rank;
   uint8_t sender_closer;
   uip_ds6_route_t *route;
-  rpl_parent_t *sender = NULL;
+  rpl_parent_t *sender;
+  struct uip_hbho_hdr *hbh_hdr = (struct uip_hbho_hdr *)ext_buf;
+  struct uip_ext_hdr_opt_rpl *rpl_opt = (struct uip_ext_hdr_opt_rpl *)(ext_buf + opt_offset);
 
-  if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
-      || UIP_EXT_HDR_OPT_RPL_BUF->opt_type != UIP_EXT_HDR_OPT_RPL
-      || UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) {
+  if(hbh_hdr->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
+      || rpl_opt->opt_type != UIP_EXT_HDR_OPT_RPL
+      || rpl_opt->opt_len != RPL_HDR_OPT_LEN) {
 
     LOG_ERR("Hop-by-hop extension header has wrong size or type (%u %u %u)\n",
-        UIP_HBHO_BUF->len,
-        UIP_EXT_HDR_OPT_RPL_BUF->opt_type,
-        UIP_EXT_HDR_OPT_RPL_BUF->opt_len);
+        hbh_hdr->len, rpl_opt->opt_type, rpl_opt->opt_len);
     return 0; /* Drop */
   }
 
-  instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance);
+  instance = rpl_get_instance(rpl_opt->instance);
   if(instance == NULL) {
-    LOG_ERR("Unknown instance: %u\n",
-           UIP_EXT_HDR_OPT_RPL_BUF->instance);
+    LOG_ERR("Unknown instance: %u\n", rpl_opt->instance);
     return 0;
   }
 
-  if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_FWD_ERR) {
+  if(rpl_opt->flags & RPL_HDR_OPT_FWD_ERR) {
     LOG_ERR("Forward error!\n");
     /* We should try to repair it by removing the neighbor that caused
          the packet to be forwareded in the first place. We drop any
@@ -123,14 +112,14 @@ rpl_ext_header_hbh_update(int uip_ext_opt_offset)
     return 0;
   }
   down = 0;
-  if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) {
+  if(rpl_opt->flags & RPL_HDR_OPT_DOWN) {
     down = 1;
   }
 
-  sender_rank = UIP_HTONS(UIP_EXT_HDR_OPT_RPL_BUF->senderrank);
+  sender_rank = UIP_HTONS(rpl_opt->senderrank);
   sender = nbr_table_get_from_lladdr(rpl_parents, packetbuf_addr(PACKETBUF_ADDR_SENDER));
 
-  if(sender != NULL && (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR)) {
+  if(sender != NULL && (rpl_opt->flags & RPL_HDR_OPT_RANK_ERR)) {
     /* A rank error was signalled, attempt to repair it by updating
      * the sender's rank from ext header */
     sender->rank = sender_rank;
@@ -160,7 +149,7 @@ rpl_ext_header_hbh_update(int uip_ext_opt_offset)
       instance->unicast_dio_target = sender;
       rpl_schedule_unicast_dio_immediately(instance);
     }
-    if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) {
+    if(rpl_opt->flags & RPL_HDR_OPT_RANK_ERR) {
       RPL_STAT(rpl_stats.loop_errors++);
       LOG_ERR(" Rank error signalled in RPL option!\n");
       /* Packet must be dropped and dio trickle timer reset, see RFC6550 - 11.2.2.2 */
@@ -169,7 +158,7 @@ rpl_ext_header_hbh_update(int uip_ext_opt_offset)
     }
     LOG_WARN("Single error tolerated\n");
     RPL_STAT(rpl_stats.loop_warnings++);
-    UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR;
+    rpl_opt->flags |= RPL_HDR_OPT_RANK_ERR;
     return 1;
   }
 
@@ -181,41 +170,19 @@ int
 rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr)
 {
 #if RPL_WITH_NON_STORING
-  uint8_t *uip_next_hdr;
-  int last_uip_ext_len = uip_ext_len;
+  struct uip_routing_hdr *rh_header;
   rpl_dag_t *dag;
   uip_sr_node_t *dest_node;
   uip_sr_node_t *root_node;
 
-  uip_ext_len = 0;
-  uip_next_hdr = &UIP_IP_BUF->proto;
-
-  /* Look for routing header */
-  while(uip_next_hdr != NULL && *uip_next_hdr != UIP_PROTO_ROUTING) {
-    switch(*uip_next_hdr) {
-      case UIP_PROTO_HBHO:
-      case UIP_PROTO_DESTO:
-        /*
-         * As per RFC 2460, only the Hop-by-Hop Options header and
-         * Destination Options header can appear before the Routing
-         * header.
-         */
-        /* Move to next header */
-        uip_next_hdr = &UIP_EXT_BUF->next;
-        uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
-        break;
-      default:
-        uip_next_hdr = NULL;
-        break;
-    }
-  }
+  /* Look for routing ext header */
+  rh_header = (struct uip_routing_hdr *)uipbuf_search_header(uip_buf, uip_len, UIP_PROTO_ROUTING);
 
   dag = rpl_get_dag(&UIP_IP_BUF->destipaddr);
   root_node = uip_sr_get_node(dag, &dag->dag_id);
   dest_node = uip_sr_get_node(dag, &UIP_IP_BUF->destipaddr);
 
-  if((uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING
-      && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) ||
+  if((rh_header != NULL && rh_header->routing_type == RPL_RH_TYPE_SRH) ||
      (dest_node != NULL && root_node != NULL &&
       dest_node->parent == root_node)) {
     /* Routing header found or the packet destined for a direct child of the root.
@@ -224,11 +191,9 @@ rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr)
      * forwarding to next hop */
     uip_ipaddr_copy(ipaddr, &UIP_IP_BUF->destipaddr);
     uip_create_linklocal_prefix(ipaddr);
-    uip_ext_len = last_uip_ext_len;
     return 1;
   }
 
-  uip_ext_len = last_uip_ext_len;
   return 0;
 #else /* RPL_WITH_NON_STORING */
   return 0; /* SRH not found */
@@ -239,34 +204,13 @@ int
 rpl_ext_header_srh_update(void)
 {
 #if RPL_WITH_NON_STORING
-  uint8_t *uip_next_hdr;
-  int last_uip_ext_len = uip_ext_len;
-
-  uip_ext_len = 0;
-  uip_next_hdr = &UIP_IP_BUF->proto;
-
-  /* Look for routing header */
-  while(uip_next_hdr != NULL && *uip_next_hdr != UIP_PROTO_ROUTING) {
-    switch(*uip_next_hdr) {
-      case UIP_PROTO_HBHO:
-      case UIP_PROTO_DESTO:
-        /*
-         * As per RFC 2460, only the Hop-by-Hop Options header and
-         * Destination Options header can appear before the Routing
-         * header.
-         */
-        /* Move to next header */
-        uip_next_hdr = &UIP_EXT_BUF->next;
-        uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
-        break;
-      default:
-        uip_next_hdr = NULL;
-        break;
-    }
-  }
+  struct uip_routing_hdr *rh_header;
+  struct uip_rpl_srh_hdr *srh_header;
 
-  if(uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING
-      && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) {
+  /* Look for routing ext header */
+  rh_header = (struct uip_routing_hdr *)uipbuf_search_header(uip_buf, uip_len, UIP_PROTO_ROUTING);
+
+  if(rh_header != NULL && rh_header->routing_type == RPL_RH_TYPE_SRH) {
     /* SRH found, now look for next hop */
     uint8_t cmpri, cmpre;
     uint8_t ext_len;
@@ -275,11 +219,12 @@ rpl_ext_header_srh_update(void)
     uint8_t segments_left;
     uip_ipaddr_t current_dest_addr;
 
-    segments_left = UIP_RH_BUF->seg_left;
-    ext_len = (UIP_RH_BUF->len * 8) + 8;
-    cmpri = UIP_RPL_SRH_BUF->cmpr >> 4;
-    cmpre = UIP_RPL_SRH_BUF->cmpr & 0x0f;
-    padding = UIP_RPL_SRH_BUF->pad >> 4;
+    srh_header = (struct uip_rpl_srh_hdr *)(((uint8_t *)rh_header) + RPL_RH_LEN);
+    segments_left = rh_header->seg_left;
+    ext_len = rh_header->len * 8 + 8;
+    cmpri = srh_header->cmpr >> 4;
+    cmpre = srh_header->cmpr & 0x0f;
+    padding = srh_header->pad >> 4;
     path_len = ((ext_len - padding - RPL_RH_LEN - RPL_SRH_LEN - (16 - cmpre)) / (16 - cmpri)) + 1;
     (void)path_len;
 
@@ -290,7 +235,7 @@ rpl_ext_header_srh_update(void)
       /* We are the final destination, do nothing */
     } else {
       uint8_t i = path_len - segments_left; /* The index of the next address to be visited */
-      uint8_t *addr_ptr = ((uint8_t *)UIP_RH_BUF) + RPL_RH_LEN + RPL_SRH_LEN + (i * (16 - cmpri));
+      uint8_t *addr_ptr = ((uint8_t *)rh_header) + RPL_RH_LEN + RPL_SRH_LEN + (i * (16 - cmpri));
       uint8_t cmpr = segments_left == 1 ? cmpre : cmpri;
 
       /* As per RFC6554: swap the IPv6 destination address and address[i] */
@@ -303,17 +248,15 @@ rpl_ext_header_srh_update(void)
       memcpy(addr_ptr, ((uint8_t *)&current_dest_addr) + cmpr, 16 - cmpr);
 
       /* Update segments left field */
-      UIP_RH_BUF->seg_left--;
+      rh_header->seg_left--;
 
       LOG_INFO("SRH next hop ");
       LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
       LOG_INFO_("\n");
     }
-    uip_ext_len = last_uip_ext_len;
     return 1;
   }
 
-  uip_ext_len = last_uip_ext_len;
   return 0;
 #else /* RPL_WITH_NON_STORING */
   return 0; /* SRH not found */
@@ -336,7 +279,6 @@ static int
 insert_srh_header(void)
 {
   /* Implementation of RFC6554 */
-  uint8_t temp_len;
   uint8_t path_len;
   uint8_t ext_len;
   uint8_t cmpri, cmpre; /* ComprI and ComprE fields of the RPL Source Routing Header */
@@ -348,6 +290,10 @@ insert_srh_header(void)
   rpl_dag_t *dag;
   uip_ipaddr_t node_addr;
 
+  /* Always insest SRH as first extension header */
+  struct uip_routing_hdr *rh_hdr = (struct uip_routing_hdr *)UIP_IP_PAYLOAD(0);
+  struct uip_rpl_srh_hdr *srh_hdr = (struct uip_rpl_srh_hdr *)(UIP_IP_PAYLOAD(0) + RPL_RH_LEN);
+
   LOG_INFO("SRH creating source routing header with destination ");
   LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
   LOG_INFO_("\n");
@@ -418,33 +364,33 @@ insert_srh_header(void)
       path_len, cmpri, cmpre, ext_len, padding);
 
   /* Check if there is enough space to store the extension header */
-  if(uip_len + ext_len > UIP_BUFSIZE - UIP_LLH_LEN) {
+  if(uip_len + ext_len > UIP_LINK_MTU) {
     LOG_ERR("Packet too long: impossible to add source routing header (%u bytes)\n", ext_len);
     return 0;
   }
 
-  /* Move existing ext headers and payload uip_ext_len further */
-  memmove(uip_buf + uip_l2_l3_hdr_len + ext_len,
-      uip_buf + uip_l2_l3_hdr_len, uip_len - UIP_IPH_LEN);
-  memset(uip_buf + uip_l2_l3_hdr_len, 0, ext_len);
+  /* Move existing ext headers and payload ext_len further */
+  memmove(uip_buf + UIP_IPH_LEN + uip_ext_len + ext_len,
+      uip_buf + UIP_IPH_LEN + uip_ext_len, uip_len - UIP_IPH_LEN);
+  memset(uip_buf + UIP_IPH_LEN + uip_ext_len, 0, ext_len);
 
-  /* Insert source routing header */
-  UIP_RH_BUF->next = UIP_IP_BUF->proto;
+  /* Insert source routing header (as first ext header) */
+  rh_hdr->next = UIP_IP_BUF->proto;
   UIP_IP_BUF->proto = UIP_PROTO_ROUTING;
 
   /* Initialize IPv6 Routing Header */
-  UIP_RH_BUF->len = (ext_len - 8) / 8;
-  UIP_RH_BUF->routing_type = RPL_RH_TYPE_SRH;
-  UIP_RH_BUF->seg_left = path_len;
+  rh_hdr->len = (ext_len - 8) / 8;
+  rh_hdr->routing_type = RPL_RH_TYPE_SRH;
+  rh_hdr->seg_left = path_len;
 
   /* Initialize RPL Source Routing Header */
-  UIP_RPL_SRH_BUF->cmpr = (cmpri << 4) + cmpre;
-  UIP_RPL_SRH_BUF->pad = padding << 4;
+  srh_hdr->cmpr = (cmpri << 4) + cmpre;
+  srh_hdr->pad = padding << 4;
 
   /* Initialize addresses field (the actual source route).
    * From last to first. */
   node = dest_node;
-  hop_ptr = ((uint8_t *)UIP_RH_BUF) + ext_len - padding; /* Pointer where to write the next hop compressed address */
+  hop_ptr = ((uint8_t *)rh_hdr) + ext_len - padding; /* Pointer where to write the next hop compressed address */
 
   while(node != NULL && node->parent != root_node) {
     NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node);
@@ -459,15 +405,9 @@ insert_srh_header(void)
   NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node);
   uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &node_addr);
 
-  /* In-place update of IPv6 length field */
-  temp_len = UIP_IP_BUF->len[1];
-  UIP_IP_BUF->len[1] += ext_len;
-  if(UIP_IP_BUF->len[1] < temp_len) {
-    UIP_IP_BUF->len[0]++;
-  }
-
-  uip_ext_len += ext_len;
-  uip_len += ext_len;
+  /* Update the IPv6 length field */
+  uipbuf_add_ext_hdr(ext_len);
+  uipbuf_set_len_field(UIP_IP_BUF, uip_len - UIP_IPH_LEN);
 
   return 1;
 }
@@ -476,44 +416,37 @@ static int
 update_hbh_header(void)
 {
   rpl_instance_t *instance;
-  int uip_ext_opt_offset;
-  int last_uip_ext_len;
   rpl_parent_t *parent;
+  struct uip_hbho_hdr *hbh_hdr = (struct uip_hbho_hdr *)UIP_IP_PAYLOAD(0);
+  struct uip_ext_hdr_opt_rpl *rpl_opt = (struct uip_ext_hdr_opt_rpl *)(UIP_IP_PAYLOAD(0) + 2);
 
-  last_uip_ext_len = uip_ext_len;
-  uip_ext_len = 0;
-  uip_ext_opt_offset = 2;
-
-  if(UIP_IP_BUF->proto == UIP_PROTO_HBHO && UIP_EXT_HDR_OPT_RPL_BUF->opt_type == UIP_EXT_HDR_OPT_RPL) {
-    if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
-        || UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) {
+  if(UIP_IP_BUF->proto == UIP_PROTO_HBHO && rpl_opt->opt_type == UIP_EXT_HDR_OPT_RPL) {
+    if(hbh_hdr->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
+        || rpl_opt->opt_len != RPL_HDR_OPT_LEN) {
 
-      LOG_ERR("Hop-by-hop extension header has wrong size (%u %u)\n",
-          UIP_EXT_HDR_OPT_RPL_BUF->opt_len,
-          uip_ext_len);
+      LOG_ERR("Hop-by-hop extension header has wrong size (%u)\n", rpl_opt->opt_len);
       return 0; /* Drop */
     }
 
-    instance = rpl_get_instance(UIP_EXT_HDR_OPT_RPL_BUF->instance);
+    instance = rpl_get_instance(rpl_opt->instance);
     if(instance == NULL || !instance->used || !instance->current_dag->joined) {
       LOG_ERR("Unable to add/update hop-by-hop extension header: incorrect instance\n");
-      uip_ext_len = last_uip_ext_len;
       return 0; /* Drop */
     }
 
     LOG_INFO("Updating RPL option\n");
     /* Update sender rank and instance, will update flags next */
-    UIP_EXT_HDR_OPT_RPL_BUF->senderrank = UIP_HTONS(instance->current_dag->rank);
-    UIP_EXT_HDR_OPT_RPL_BUF->instance = instance->instance_id;
+    rpl_opt->senderrank = UIP_HTONS(instance->current_dag->rank);
+    rpl_opt->instance = instance->instance_id;
 
     if(RPL_IS_STORING(instance)) { /* In non-storing mode, downwards traffic does not have the HBH option */
       /* Check the direction of the down flag, as per Section 11.2.2.3,
             which states that if a packet is going down it should in
             general not go back up again. If this happens, a
             RPL_HDR_OPT_FWD_ERR should be flagged. */
-      if((UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN)) {
+      if((rpl_opt->flags & RPL_HDR_OPT_DOWN)) {
         if(uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr) == NULL) {
-          UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_FWD_ERR;
+          rpl_opt->flags |= RPL_HDR_OPT_FWD_ERR;
           LOG_WARN("RPL forwarding error\n");
           /* We should send back the packet to the originating parent,
                 but it is not feasible yet, so we send a No-Path DAO instead */
@@ -532,119 +465,110 @@ update_hbh_header(void)
         if(uip_ds6_route_lookup(&UIP_IP_BUF->destipaddr) == NULL) {
           /* No route was found, so this packet will go towards the RPL
                 root. If so, we should not set the down flag. */
-          UIP_EXT_HDR_OPT_RPL_BUF->flags &= ~RPL_HDR_OPT_DOWN;
+          rpl_opt->flags &= ~RPL_HDR_OPT_DOWN;
           LOG_DBG("RPL option going up\n");
         } else {
           /* A DAO route was found so we set the down flag. */
-          UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_DOWN;
+          rpl_opt->flags |= RPL_HDR_OPT_DOWN;
           LOG_DBG("RPL option going down\n");
         }
       }
     }
   }
 
-  uip_ext_len = last_uip_ext_len;
   return 1;
 }
 /*---------------------------------------------------------------------------*/
 static int
 insert_hbh_header(const rpl_instance_t *instance)
 {
-  int uip_ext_opt_offset;
-  int last_uip_ext_len;
-  uint8_t temp_len;
-
-  last_uip_ext_len = uip_ext_len;
-  uip_ext_len = 0;
-  uip_ext_opt_offset = 2;
+  struct uip_hbho_hdr *hbh_hdr = (struct uip_hbho_hdr *)UIP_IP_PAYLOAD(0);
+  struct uip_ext_hdr_opt_rpl *rpl_opt = (struct uip_ext_hdr_opt_rpl *)(UIP_IP_PAYLOAD(2));
 
   /* Insert hop-by-hop header */
   LOG_DBG("Creating hop-by-hop option\n");
-  if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_BUFSIZE - UIP_LLH_LEN) {
+  if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_LINK_MTU) {
     LOG_ERR("Packet too long: impossible to add hop-by-hop option\n");
-    uip_ext_len = last_uip_ext_len;
     return 0;
   }
 
-  /* Move existing ext headers and payload UIP_EXT_BUF further */
-  memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF, uip_len - UIP_IPH_LEN);
-  memset(UIP_HBHO_BUF, 0, RPL_HOP_BY_HOP_LEN);
+  /* Move existing ext headers and payload RPL_HOP_BY_HOP_LEN further */
+  memmove(UIP_IP_PAYLOAD(RPL_HOP_BY_HOP_LEN), UIP_IP_PAYLOAD(0), uip_len - UIP_IPH_LEN);
+  memset(UIP_IP_PAYLOAD(0), 0, RPL_HOP_BY_HOP_LEN);
 
-  /* Update IP and HBH protocol and fields */
-  UIP_HBHO_BUF->next = UIP_IP_BUF->proto;
+  /* Insert HBH header (as first ext header) */
+  hbh_hdr->next = UIP_IP_BUF->proto;
   UIP_IP_BUF->proto = UIP_PROTO_HBHO;
 
   /* Initialize HBH option */
-  UIP_HBHO_BUF->len = (RPL_HOP_BY_HOP_LEN - 8) / 8;
-  UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL;
-  UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN;
-  UIP_EXT_HDR_OPT_RPL_BUF->flags = 0;
-  UIP_EXT_HDR_OPT_RPL_BUF->senderrank = UIP_HTONS(instance->current_dag->rank);
-  UIP_EXT_HDR_OPT_RPL_BUF->instance = instance->instance_id;
-  uip_len += RPL_HOP_BY_HOP_LEN;
-  temp_len = UIP_IP_BUF->len[1];
-  UIP_IP_BUF->len[1] += RPL_HOP_BY_HOP_LEN;
-  if(UIP_IP_BUF->len[1] < temp_len) {
-    UIP_IP_BUF->len[0]++;
-  }
+  hbh_hdr->len = (RPL_HOP_BY_HOP_LEN - 8) / 8;
+  rpl_opt->opt_type = UIP_EXT_HDR_OPT_RPL;
+  rpl_opt->opt_len = RPL_HDR_OPT_LEN;
+  rpl_opt->flags = 0;
+  rpl_opt->senderrank = UIP_HTONS(instance->current_dag->rank);
+  rpl_opt->instance = instance->instance_id;
 
-  uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN;
+  uipbuf_add_ext_hdr(RPL_HOP_BY_HOP_LEN);
+  uipbuf_set_len_field(UIP_IP_BUF, uip_len - UIP_IPH_LEN);
 
   /* Update header before returning */
   return update_hbh_header();
 }
 /*---------------------------------------------------------------------------*/
-void
+bool
 rpl_ext_header_remove(void)
 {
-  uint8_t temp_len;
-  uint8_t rpl_ext_hdr_len;
-  int uip_ext_opt_offset;
-  uint8_t *uip_next_hdr;
-
-  uip_ext_len = 0;
-  uip_ext_opt_offset = 2;
-  uip_next_hdr = &UIP_IP_BUF->proto;
-
-  /* Look for hop-by-hop and routing headers */
-  while(uip_next_hdr != NULL) {
-    switch(*uip_next_hdr) {
-      case UIP_PROTO_HBHO:
-      case UIP_PROTO_ROUTING:
-        if((*uip_next_hdr != UIP_PROTO_HBHO || UIP_EXT_HDR_OPT_RPL_BUF->opt_type == UIP_EXT_HDR_OPT_RPL)) {
-          /* Remove hop-by-hop and routing headers */
-          *uip_next_hdr = UIP_EXT_BUF->next;
-          rpl_ext_hdr_len = (UIP_EXT_BUF->len * 8) + 8;
-          temp_len = UIP_IP_BUF->len[1];
-          uip_len -= rpl_ext_hdr_len;
-          UIP_IP_BUF->len[1] -= rpl_ext_hdr_len;
-          if(UIP_IP_BUF->len[1] > temp_len) {
-            UIP_IP_BUF->len[0]--;
-          }
-          LOG_DBG("Removing RPL extension header (type %u, len %u)\n", *uip_next_hdr, rpl_ext_hdr_len);
-          memmove(UIP_EXT_BUF, ((uint8_t *)UIP_EXT_BUF) + rpl_ext_hdr_len, uip_len - UIP_IPH_LEN);
-        } else {
-          uip_next_hdr = &UIP_EXT_BUF->next;
-          uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
-        }
-        break;
-      case UIP_PROTO_DESTO:
-        /*
-         * As per RFC 2460, any header other than the Destination
-         * Options header does not appear between the Hop-by-Hop
-         * Options header and the Routing header.
-         *
-         * We're moving to the next header only if uip_next_hdr has
-         * UIP_PROTO_DESTO. Otherwise, we'll return.
-         */
-        /* Move to next header */
-        uip_next_hdr = &UIP_EXT_BUF->next;
-        uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
+  uint8_t *prev_proto_ptr;
+  uint8_t protocol;
+  uint16_t ext_len;
+  uint8_t *next_header;
+  struct uip_ext_hdr *ext_ptr;
+  struct uip_ext_hdr_opt *opt_ptr;
+
+  next_header = uipbuf_get_next_header(uip_buf, uip_len, &protocol, true);
+  if(next_header == NULL) {
+    return true;
+  }
+  ext_ptr = (struct uip_ext_hdr *)next_header;
+  prev_proto_ptr = &UIP_IP_BUF->proto;
+
+  while(uip_is_proto_ext_hdr(protocol)) {
+    opt_ptr = (struct uip_ext_hdr_opt *)(next_header + 2);
+    if(protocol == UIP_PROTO_ROUTING ||
+       (protocol == UIP_PROTO_HBHO && opt_ptr->type == UIP_EXT_HDR_OPT_RPL)) {
+      /* Remove ext header */
+      *prev_proto_ptr = ext_ptr->next;
+      ext_len = ext_ptr->len * 8 + 8;
+      if(uipbuf_add_ext_hdr(-ext_len) == false) {
+        return false;
+      }
+
+      /* Update length field and rest of packet to the "left" */
+      uipbuf_set_len_field(UIP_IP_BUF, uip_len - UIP_IPH_LEN);
+      if(uip_len <= next_header - uip_buf) {
+        /* No more data to move. */
+        return false;
+      }
+      memmove(next_header, next_header + ext_len,
+              uip_len - (next_header - uip_buf));
+
+      /* Update loop variables */
+      protocol = *prev_proto_ptr;
+    } else {
+      /* move to the ext hdr */
+      next_header = uipbuf_get_next_header(next_header,
+                                           uip_len - (next_header - uip_buf),
+                                           &protocol, false);
+      if(next_header == NULL) {
+        /* Processing finished. */
         break;
-    default:
-      return;
+      }
+      ext_ptr = (struct uip_ext_hdr *)next_header;
+      prev_proto_ptr = &ext_ptr->next;
     }
   }
+
+  return true;
 }
 /*---------------------------------------------------------------------------*/
 int
diff --git a/os/net/routing/rpl-classic/rpl-icmp6.c b/os/net/routing/rpl-classic/rpl-icmp6.c
index a246e576e616136f5b605d5cfe7598fa8fb42ad5..baa6b08a725d24d2bfcfd2f115b1d4e832f668e7 100644
--- a/os/net/routing/rpl-classic/rpl-icmp6.c
+++ b/os/net/routing/rpl-classic/rpl-icmp6.c
@@ -70,9 +70,6 @@
 #define RPL_DIO_MOP_MASK                 0x38
 #define RPL_DIO_PREFERENCE_MASK          0x07
 
-#define UIP_IP_BUF       ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-#define UIP_ICMP_BUF     ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_ICMP_PAYLOAD ((unsigned char *)&uip_buf[uip_l2_l3_icmp_hdr_len])
 /*---------------------------------------------------------------------------*/
 static void dis_input(void);
 static void dio_input(void);
@@ -251,7 +248,7 @@ dis_input(void)
       }
     }
   }
-  uip_clear_buf();
+  uipbuf_clear();
 }
 /*---------------------------------------------------------------------------*/
 void
@@ -471,7 +468,7 @@ dio_input(void)
   rpl_process_dio(&from, &dio);
 
 discard:
-  uip_clear_buf();
+  uipbuf_clear();
 }
 /*---------------------------------------------------------------------------*/
 void
@@ -810,7 +807,7 @@ dao_input_storing(void)
     /* independent if we remove or not - ACK the request */
     if(flags & RPL_DAO_K_FLAG) {
       /* indicate that we accepted the no-path DAO */
-      uip_clear_buf();
+      uipbuf_clear();
       dao_ack_output(instance, &dao_sender_addr, sequence,
                      RPL_DAO_ACK_UNCONDITIONAL_ACCEPT);
     }
@@ -900,7 +897,7 @@ fwd_dao:
     }
     if(should_ack) {
       LOG_DBG("Sending DAO ACK\n");
-      uip_clear_buf();
+      uipbuf_clear();
       dao_ack_output(instance, &dao_sender_addr, sequence,
                      RPL_DAO_ACK_UNCONDITIONAL_ACCEPT);
     }
@@ -1014,7 +1011,7 @@ dao_input_nonstoring(void)
 
   if(flags & RPL_DAO_K_FLAG) {
     LOG_DBG("Sending DAO ACK\n");
-    uip_clear_buf();
+    uipbuf_clear();
     dao_ack_output(instance, &dao_sender_addr, sequence,
                    RPL_DAO_ACK_UNCONDITIONAL_ACCEPT);
   }
@@ -1047,7 +1044,7 @@ dao_input(void)
   }
 
 discard:
-  uip_clear_buf();
+  uipbuf_clear();
 }
 /*---------------------------------------------------------------------------*/
 #if RPL_WITH_DAO_ACK
@@ -1286,7 +1283,7 @@ dao_ack_input(void)
 
   instance = rpl_get_instance(instance_id);
   if(instance == NULL) {
-    uip_clear_buf();
+    uipbuf_clear();
     return;
   }
 
@@ -1294,7 +1291,7 @@ dao_ack_input(void)
     parent = rpl_find_parent(instance->current_dag, &UIP_IP_BUF->srcipaddr);
     if(parent == NULL) {
       /* not a known instance - drop the packet and ignore */
-      uip_clear_buf();
+      uipbuf_clear();
       return;
     }
   } else {
@@ -1303,7 +1300,7 @@ dao_ack_input(void)
 
   if(instance->current_dag->rank == ROOT_RANK(instance)) {
     LOG_DBG("DODAG root received a DAO ACK, ignoring it\n");
-    uip_clear_buf();
+    uipbuf_clear();
     return;
   }
 
@@ -1363,7 +1360,7 @@ dao_ack_input(void)
     }
   }
 #endif /* RPL_WITH_DAO_ACK */
-  uip_clear_buf();
+  uipbuf_clear();
 }
 /*---------------------------------------------------------------------------*/
 void
diff --git a/os/net/routing/rpl-classic/rpl-nbr-policy.c b/os/net/routing/rpl-classic/rpl-nbr-policy.c
index 344840d0e05621df46928a36da2b9c09d6db0af5..d23111e46278c6f2d7e6f9cffe256bc6db9e31cf 100644
--- a/os/net/routing/rpl-classic/rpl-nbr-policy.c
+++ b/os/net/routing/rpl-classic/rpl-nbr-policy.c
@@ -65,12 +65,11 @@
  * neighbors and are not only MAC neighbors.
  */
 #define MAX_CHILDREN (NBR_TABLE_MAX_NEIGHBORS - 2)
-#define UIP_IP_BUF       ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
 
 static int num_parents; /* any node that are possible parents */
 static int num_children;  /* all children that we have as nexthop */
 static int num_free;
-static linkaddr_t *worst_rank_nbr; /* the parent that has the worst rank */
+static const linkaddr_t *worst_rank_nbr; /* the parent that has the worst rank */
 static rpl_rank_t worst_rank;
 /*---------------------------------------------------------------------------*/
 #if LOG_DBG_ENABLED
@@ -112,9 +111,9 @@ update_nbr(void)
   num_parents = 0;
   num_children = 0;
 
-  nbr = nbr_table_head(ds6_neighbors);
+  nbr = uip_ds6_nbr_head();
   while(nbr != NULL) {
-    linkaddr_t *lladdr = nbr_table_get_lladdr(ds6_neighbors, nbr);
+    const linkaddr_t *lladdr = (const linkaddr_t *)uip_ds6_nbr_get_ll(nbr);
     is_used = 0;
 
     /*
@@ -127,7 +126,7 @@ update_nbr(void)
       num_children++;
     }
 
-    parent = rpl_get_parent((uip_lladdr_t *)lladdr);
+    parent = rpl_get_parent((const uip_lladdr_t *)lladdr);
     if(parent != NULL) {
       num_parents++;
 
@@ -159,7 +158,7 @@ update_nbr(void)
       LOG_DBG_("\n");
     }
 
-    nbr = nbr_table_next(ds6_neighbors, nbr);
+    nbr = uip_ds6_nbr_next(nbr);
     num_used++;
   }
   /* how many more IP neighbors can be have? */
diff --git a/os/net/routing/rpl-classic/rpl-timers.c b/os/net/routing/rpl-classic/rpl-timers.c
index 0bcfc57dd556adfad2d02198b3568dd96713232e..b2c61607c40cac77a3fb632cc777c55ce8dbaded 100644
--- a/os/net/routing/rpl-classic/rpl-timers.c
+++ b/os/net/routing/rpl-classic/rpl-timers.c
@@ -479,13 +479,14 @@ handle_probing_timer(void *ptr)
   /* Perform probing */
   if(target_ipaddr != NULL) {
     const struct link_stats *stats = rpl_get_parent_link_stats(probing_target);
-    (void)stats;
+    const linkaddr_t *lladdr = rpl_get_parent_lladdr(probing_target);
     LOG_INFO("probing %u %s last tx %u min ago\n",
-        rpl_get_parent_lladdr(probing_target)->u8[7],
-        instance->urgent_probing_target != NULL ? "(urgent)" : "",
-        probing_target != NULL ?
-        (unsigned)((clock_time() - stats->last_tx_time) / (60 * CLOCK_SECOND)) : 0
-        );
+          lladdr != NULL ? lladdr->u8[7] : 0x0,
+          instance->urgent_probing_target != NULL ? "(urgent)" : "",
+          probing_target != NULL && stats != NULL ?
+           (unsigned)((clock_time() - stats->last_tx_time) / (60 * CLOCK_SECOND)) : 0
+      );
+
     /* Send probe, e.g. unicast DIO or DIS */
     RPL_PROBING_SEND_FUNC(instance, target_ipaddr);
   }
diff --git a/os/net/routing/rpl-classic/rpl.h b/os/net/routing/rpl-classic/rpl.h
index db87cc8246d868b2402bcf7cbe6d58b5f57326b8..34d0269788056f21e4e51cc1f67d4c8c04ae7e92 100644
--- a/os/net/routing/rpl-classic/rpl.h
+++ b/os/net/routing/rpl-classic/rpl.h
@@ -275,9 +275,9 @@ rpl_dag_t *rpl_get_dag(const uip_ipaddr_t *addr);
 rpl_dag_t *rpl_get_any_dag(void);
 rpl_instance_t *rpl_get_instance(uint8_t instance_id);
 int rpl_ext_header_update(void);
-int rpl_ext_header_hbh_update(int);
+int rpl_ext_header_hbh_update(uint8_t *, int);
 void rpl_insert_header(void);
-void rpl_ext_header_remove(void);
+bool rpl_ext_header_remove(void);
 const struct link_stats *rpl_get_parent_link_stats(rpl_parent_t *p);
 int rpl_parent_is_fresh(rpl_parent_t *p);
 int rpl_parent_is_reachable(rpl_parent_t *p);
@@ -285,7 +285,7 @@ uint16_t rpl_get_parent_link_metric(rpl_parent_t *p);
 rpl_rank_t rpl_rank_via_parent(rpl_parent_t *p);
 const linkaddr_t *rpl_get_parent_lladdr(rpl_parent_t *p);
 uip_ipaddr_t *rpl_parent_get_ipaddr(rpl_parent_t *nbr);
-rpl_parent_t *rpl_get_parent(uip_lladdr_t *addr);
+rpl_parent_t *rpl_get_parent(const uip_lladdr_t *addr);
 rpl_rank_t rpl_get_parent_rank(uip_lladdr_t *addr);
 void rpl_dag_init(void);
 uip_ds6_nbr_t *rpl_get_nbr(rpl_parent_t *parent);
diff --git a/os/net/routing/rpl-lite/rpl-dag-root.c b/os/net/routing/rpl-lite/rpl-dag-root.c
index c3e3568284f5c59639ead244099edf9b7fb24ab1..38f5697e7c8ea10354fc49e8c95d9863624c12fc 100644
--- a/os/net/routing/rpl-lite/rpl-dag-root.c
+++ b/os/net/routing/rpl-lite/rpl-dag-root.c
@@ -76,13 +76,16 @@ static void
 set_global_address(uip_ipaddr_t *prefix, uip_ipaddr_t *iid)
 {
   static uip_ipaddr_t root_ipaddr;
+  const uip_ipaddr_t *default_prefix;
   int i;
   uint8_t state;
 
+  default_prefix = uip_ds6_default_prefix();
+
   /* Assign a unique local address (RFC4193,
      http://tools.ietf.org/html/rfc4193). */
   if(prefix == NULL) {
-    uip_ip6addr(&root_ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
+    uip_ip6addr_copy(&root_ipaddr, default_prefix);
   } else {
     memcpy(&root_ipaddr, prefix, 8);
   }
diff --git a/os/net/routing/rpl-lite/rpl-dag-root.h b/os/net/routing/rpl-lite/rpl-dag-root.h
index 71b9997658943200514a3c6377e4c7994ac51ddf..f035e8595f4192074d23ed0946337e629dcff8ca 100644
--- a/os/net/routing/rpl-lite/rpl-dag-root.h
+++ b/os/net/routing/rpl-lite/rpl-dag-root.h
@@ -45,7 +45,7 @@
 /**
  * Set a prefix in case the node is later set as dag root.
  *
- * \param prefix The prefix. If NULL, UIP_DS6_DEFAULT_PREFIX is used instead
+ * \param prefix The prefix. If NULL, uip_ds6_default_prefix() is used instead
  * \param iid The IID. If NULL, it will be built from uip_ds6_set_addr_iid.
 */
 void rpl_dag_root_set_prefix(uip_ipaddr_t *prefix, uip_ipaddr_t *iid);
diff --git a/os/net/routing/rpl-lite/rpl-dag.c b/os/net/routing/rpl-lite/rpl-dag.c
index 09caa9625eb9a07be5fbed106b71ed43a12b942c..5ec080c15e66cbfa76f4d1628fa226ef619970d0 100644
--- a/os/net/routing/rpl-lite/rpl-dag.c
+++ b/os/net/routing/rpl-lite/rpl-dag.c
@@ -104,7 +104,7 @@ rpl_dag_leave(void)
 
   /* Issue a no-path DAO */
   if(!rpl_dag_root_is_root()) {
-    RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_curr_seqno);
+    RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_last_seqno);
     rpl_icmp6_dao_output(0);
   }
 
@@ -507,7 +507,7 @@ init_dag(uint8_t instance_id, uip_ipaddr_t *dag_id, rpl_ocp_t ocp,
   curr_instance.dag.lowest_rank = RPL_INFINITE_RANK;
   curr_instance.dag.dao_last_seqno = RPL_LOLLIPOP_INIT;
   curr_instance.dag.dao_last_acked_seqno = RPL_LOLLIPOP_INIT;
-  curr_instance.dag.dao_curr_seqno = RPL_LOLLIPOP_INIT;
+  curr_instance.dag.dao_last_seqno = RPL_LOLLIPOP_INIT;
   memcpy(&curr_instance.dag.dag_id, dag_id, sizeof(curr_instance.dag.dag_id));
 
   return 1;
@@ -657,6 +657,8 @@ rpl_process_dao_ack(uint8_t sequence, uint8_t status)
       curr_instance.dag.state = DAG_REACHABLE;
       rpl_timers_dio_reset("Reachable");
     }
+    /* Let the rpl-timers module know that we got an ACK for the last DAO */
+    rpl_timers_notify_dao_ack();
 
     if(!status_ok) {
       /* We got a NACK, start poisoning and leave */
diff --git a/os/net/routing/rpl-lite/rpl-ext-header.c b/os/net/routing/rpl-lite/rpl-ext-header.c
index af67cdaff88568bebf661b1c371925b708dabe7a..2c262d26bd84477e7919f06f448a3c36cca7ce83 100644
--- a/os/net/routing/rpl-lite/rpl-ext-header.c
+++ b/os/net/routing/rpl-lite/rpl-ext-header.c
@@ -53,46 +53,16 @@
 #define LOG_MODULE "RPL"
 #define LOG_LEVEL LOG_LEVEL_RPL
 
-/*---------------------------------------------------------------------------*/
-#define UIP_IP_BUF                ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-#define UIP_EXT_BUF               ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_HBHO_BUF              ((struct uip_hbho_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_HBHO_NEXT_BUF         ((struct uip_ext_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_HOP_BY_HOP_LEN])
-#define UIP_RH_BUF                ((struct uip_routing_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_RPL_SRH_BUF           ((struct uip_rpl_srh_hdr *)&uip_buf[uip_l2_l3_hdr_len + RPL_RH_LEN])
-#define UIP_EXT_HDR_OPT_BUF       ((struct uip_ext_hdr_opt *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
-#define UIP_EXT_HDR_OPT_PADN_BUF  ((struct uip_ext_hdr_opt_padn *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
-#define UIP_EXT_HDR_OPT_RPL_BUF   ((struct uip_ext_hdr_opt_rpl *)&uip_buf[uip_l2_l3_hdr_len + uip_ext_opt_offset])
-
 /*---------------------------------------------------------------------------*/
 int
 rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr)
 {
-  uint8_t *uip_next_hdr;
-  int last_uip_ext_len = uip_ext_len;
+  struct uip_routing_hdr *rh_header;
   uip_sr_node_t *dest_node;
   uip_sr_node_t *root_node;
 
-  uip_ext_len = 0;
-  uip_next_hdr = &UIP_IP_BUF->proto;
-
-  /* Look for routing header */
-  while(uip_next_hdr != NULL && *uip_next_hdr != UIP_PROTO_ROUTING) {
-    switch(*uip_next_hdr) {
-      case UIP_PROTO_HBHO:
-      case UIP_PROTO_DESTO:
-        /*
-         * As per RFC 2460, only the Hop-by-Hop Options header and
-         * Destination Options header can appear before the Routing header.
-         */
-        uip_next_hdr = &UIP_EXT_BUF->next;
-        uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
-        break;
-      default:
-        uip_next_hdr = NULL;
-        break;
-    }
-  }
+  /* Look for routing ext header */
+  rh_header = (struct uip_routing_hdr *)uipbuf_search_header(uip_buf, uip_len, UIP_PROTO_ROUTING);
 
   if(!rpl_is_addr_in_our_dag(&UIP_IP_BUF->destipaddr)) {
     return 0;
@@ -101,8 +71,7 @@ rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr)
   root_node = uip_sr_get_node(NULL, &curr_instance.dag.dag_id);
   dest_node = uip_sr_get_node(NULL, &UIP_IP_BUF->destipaddr);
 
-  if((uip_next_hdr != NULL && *uip_next_hdr == UIP_PROTO_ROUTING
-      && UIP_RH_BUF->routing_type == RPL_RH_TYPE_SRH) ||
+  if((rh_header != NULL && rh_header->routing_type == RPL_RH_TYPE_SRH) ||
      (dest_node != NULL && root_node != NULL &&
       dest_node->parent == root_node)) {
     /* Routing header found or the packet destined for a direct child of the root.
@@ -111,20 +80,18 @@ rpl_ext_header_srh_get_next_hop(uip_ipaddr_t *ipaddr)
      * forwarding to next hop */
     uip_ipaddr_copy(ipaddr, &UIP_IP_BUF->destipaddr);
     uip_create_linklocal_prefix(ipaddr);
-    uip_ext_len = last_uip_ext_len;
     return 1;
   }
 
   LOG_DBG("no SRH found\n");
-  uip_ext_len = last_uip_ext_len;
   return 0;
 }
 /*---------------------------------------------------------------------------*/
 int
 rpl_ext_header_srh_update(void)
 {
-  uint8_t *uip_next_hdr;
-  int last_uip_ext_len = uip_ext_len;
+  struct uip_routing_hdr *rh_header;
+  struct uip_rpl_srh_hdr *srh_header;
   uint8_t cmpri, cmpre;
   uint8_t ext_len;
   uint8_t padding;
@@ -132,40 +99,21 @@ rpl_ext_header_srh_update(void)
   uint8_t segments_left;
   uip_ipaddr_t current_dest_addr;
 
-  uip_ext_len = 0;
-  uip_next_hdr = &UIP_IP_BUF->proto;
-
-  /* Look for routing header */
-  while(uip_next_hdr != NULL && *uip_next_hdr != UIP_PROTO_ROUTING) {
-    switch(*uip_next_hdr) {
-      case UIP_PROTO_HBHO:
-      case UIP_PROTO_DESTO:
-        /*
-         * As per RFC 2460, only the Hop-by-Hop Options header and
-         * Destination Options header can appear before the Routing header.
-         */
-        uip_next_hdr = &UIP_EXT_BUF->next;
-        uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
-        break;
-      default:
-        uip_next_hdr = NULL;
-        break;
-    }
-  }
+  /* Look for routing ext header */
+  rh_header = (struct uip_routing_hdr *)uipbuf_search_header(uip_buf, uip_len, UIP_PROTO_ROUTING);
 
-  if(uip_next_hdr == NULL || *uip_next_hdr != UIP_PROTO_ROUTING
-      || UIP_RH_BUF->routing_type != RPL_RH_TYPE_SRH) {
+  if(rh_header == NULL || rh_header->routing_type != RPL_RH_TYPE_SRH) {
     LOG_INFO("SRH not found\n");
-    uip_ext_len = last_uip_ext_len;
     return 0;
   }
 
   /* Parse SRH */
-  segments_left = UIP_RH_BUF->seg_left;
-  ext_len = (UIP_RH_BUF->len * 8) + 8;
-  cmpri = UIP_RPL_SRH_BUF->cmpr >> 4;
-  cmpre = UIP_RPL_SRH_BUF->cmpr & 0x0f;
-  padding = UIP_RPL_SRH_BUF->pad >> 4;
+  srh_header = (struct uip_rpl_srh_hdr *)(((uint8_t *)rh_header) + RPL_RH_LEN);
+  segments_left = rh_header->seg_left;
+  ext_len = rh_header->len * 8 + 8;
+  cmpri = srh_header->cmpr >> 4;
+  cmpre = srh_header->cmpr & 0x0f;
+  padding = srh_header->pad >> 4;
   path_len = ((ext_len - padding - RPL_RH_LEN - RPL_SRH_LEN - (16 - cmpre)) / (16 - cmpri)) + 1;
   (void)path_len;
 
@@ -177,7 +125,7 @@ rpl_ext_header_srh_update(void)
     /* We are the final destination, do nothing */
   } else {
     uint8_t i = path_len - segments_left; /* The index of the next address to be visited */
-    uint8_t *addr_ptr = ((uint8_t *)UIP_RH_BUF) + RPL_RH_LEN + RPL_SRH_LEN + (i * (16 - cmpri));
+    uint8_t *addr_ptr = ((uint8_t *)rh_header) + RPL_RH_LEN + RPL_SRH_LEN + (i * (16 - cmpri));
     uint8_t cmpr = segments_left == 1 ? cmpre : cmpri;
 
     /* As per RFC6554: swap the IPv6 destination address with address[i] */
@@ -190,14 +138,13 @@ rpl_ext_header_srh_update(void)
     memcpy(addr_ptr, ((uint8_t *)&current_dest_addr) + cmpr, 16 - cmpr);
 
     /* Update segments left field */
-    UIP_RH_BUF->seg_left--;
+    rh_header->seg_left--;
 
     LOG_INFO("SRH next hop ");
     LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
     LOG_INFO_("\n");
   }
 
-  uip_ext_len = last_uip_ext_len;
   return 1;
 }
 /*---------------------------------------------------------------------------*/
@@ -223,7 +170,6 @@ static int
 insert_srh_header(void)
 {
   /* Implementation of RFC6554 */
-  uint8_t temp_len;
   uint8_t path_len;
   uint8_t ext_len;
   uint8_t cmpri, cmpre; /* ComprI and ComprE fields of the RPL Source Routing Header */
@@ -234,6 +180,10 @@ insert_srh_header(void)
   uip_sr_node_t *node;
   uip_ipaddr_t node_addr;
 
+  /* Always insest SRH as first extension header */
+  struct uip_routing_hdr *rh_hdr = (struct uip_routing_hdr *)UIP_IP_PAYLOAD(0);
+  struct uip_rpl_srh_hdr *srh_hdr = (struct uip_rpl_srh_hdr *)(UIP_IP_PAYLOAD(0) + RPL_RH_LEN);
+
   LOG_INFO("SRH creating source routing header with destination ");
   LOG_INFO_6ADDR(&UIP_IP_BUF->destipaddr);
   LOG_INFO_(" \n");
@@ -304,33 +254,33 @@ insert_srh_header(void)
       path_len, cmpri, cmpre, ext_len, padding);
 
   /* Check if there is enough space to store the extension header */
-  if(uip_len + ext_len > UIP_BUFSIZE - UIP_LLH_LEN) {
+  if(uip_len + ext_len > UIP_LINK_MTU) {
     LOG_ERR("packet too long: impossible to add source routing header (%u bytes)\n", ext_len);
     return 0;
   }
 
-  /* Move existing ext headers and payload uip_ext_len further */
-  memmove(uip_buf + uip_l2_l3_hdr_len + ext_len,
-      uip_buf + uip_l2_l3_hdr_len, uip_len - UIP_IPH_LEN);
-  memset(uip_buf + uip_l2_l3_hdr_len, 0, ext_len);
+  /* Move existing ext headers and payload ext_len further */
+  memmove(uip_buf + UIP_IPH_LEN + uip_ext_len + ext_len,
+      uip_buf + UIP_IPH_LEN + uip_ext_len, uip_len - UIP_IPH_LEN);
+  memset(uip_buf + UIP_IPH_LEN + uip_ext_len, 0, ext_len);
 
-  /* Insert source routing header */
-  UIP_RH_BUF->next = UIP_IP_BUF->proto;
+  /* Insert source routing header (as first ext header) */
+  rh_hdr->next = UIP_IP_BUF->proto;
   UIP_IP_BUF->proto = UIP_PROTO_ROUTING;
 
   /* Initialize IPv6 Routing Header */
-  UIP_RH_BUF->len = (ext_len - 8) / 8;
-  UIP_RH_BUF->routing_type = RPL_RH_TYPE_SRH;
-  UIP_RH_BUF->seg_left = path_len;
+  rh_hdr->len = (ext_len - 8) / 8;
+  rh_hdr->routing_type = RPL_RH_TYPE_SRH;
+  rh_hdr->seg_left = path_len;
 
   /* Initialize RPL Source Routing Header */
-  UIP_RPL_SRH_BUF->cmpr = (cmpri << 4) + cmpre;
-  UIP_RPL_SRH_BUF->pad = padding << 4;
+  srh_hdr->cmpr = (cmpri << 4) + cmpre;
+  srh_hdr->pad = padding << 4;
 
   /* Initialize addresses field (the actual source route).
    * From last to first. */
   node = dest_node;
-  hop_ptr = ((uint8_t *)UIP_RH_BUF) + ext_len - padding; /* Pointer where to write the next hop compressed address */
+  hop_ptr = ((uint8_t *)rh_hdr) + ext_len - padding; /* Pointer where to write the next hop compressed address */
 
   while(node != NULL && node->parent != root_node) {
     NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node);
@@ -345,21 +295,15 @@ insert_srh_header(void)
   NETSTACK_ROUTING.get_sr_node_ipaddr(&node_addr, node);
   uip_ipaddr_copy(&UIP_IP_BUF->destipaddr, &node_addr);
 
-  /* In-place update of IPv6 length field */
-  temp_len = UIP_IP_BUF->len[1];
-  UIP_IP_BUF->len[1] += ext_len;
-  if(UIP_IP_BUF->len[1] < temp_len) {
-    UIP_IP_BUF->len[0]++;
-  }
-
-  uip_ext_len += ext_len;
-  uip_len += ext_len;
+  /* Update the IPv6 length field */
+  uipbuf_add_ext_hdr(ext_len);
+  uipbuf_set_len_field(UIP_IP_BUF, uip_len - UIP_IPH_LEN);
 
   return 1;
 }
 /*---------------------------------------------------------------------------*/
 int
-rpl_ext_header_hbh_update(int uip_ext_opt_offset)
+rpl_ext_header_hbh_update(uint8_t *ext_buf, int opt_offset)
 {
   int down;
   int rank_error_signaled;
@@ -367,32 +311,31 @@ rpl_ext_header_hbh_update(int uip_ext_opt_offset)
   uint16_t sender_rank;
   uint8_t sender_closer;
   rpl_nbr_t *sender;
-  uint8_t opt_type = UIP_EXT_HDR_OPT_RPL_BUF->opt_type;
-  uint8_t opt_len = UIP_EXT_HDR_OPT_RPL_BUF->opt_len;
+  struct uip_hbho_hdr *hbh_hdr = (struct uip_hbho_hdr *)ext_buf;
+  struct uip_ext_hdr_opt_rpl *rpl_opt = (struct uip_ext_hdr_opt_rpl *)(ext_buf + opt_offset);
 
-  if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
-      || opt_type != UIP_EXT_HDR_OPT_RPL
-      || opt_len != RPL_HDR_OPT_LEN) {
+  if(hbh_hdr->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
+      || rpl_opt->opt_type != UIP_EXT_HDR_OPT_RPL
+      || rpl_opt->opt_len != RPL_HDR_OPT_LEN) {
     LOG_ERR("hop-by-hop extension header has wrong size or type (%u %u %u)\n",
-        UIP_HBHO_BUF->len, opt_type, opt_len);
+        hbh_hdr->len, rpl_opt->opt_type, rpl_opt->opt_len);
     return 0; /* Drop */
   }
 
-  if(!curr_instance.used || curr_instance.instance_id != UIP_EXT_HDR_OPT_RPL_BUF->instance) {
-    LOG_ERR("unknown instance: %u\n",
-           UIP_EXT_HDR_OPT_RPL_BUF->instance);
+  if(!curr_instance.used || curr_instance.instance_id != rpl_opt->instance) {
+    LOG_ERR("unknown instance: %u\n", rpl_opt->instance);
     return 0; /* Drop */
   }
 
-  if(UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_FWD_ERR) {
+  if(rpl_opt->flags & RPL_HDR_OPT_FWD_ERR) {
     LOG_ERR("forward error!\n");
     return 0; /* Drop */
   }
 
-  down = (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_DOWN) ? 1 : 0;
-  sender_rank = UIP_HTONS(UIP_EXT_HDR_OPT_RPL_BUF->senderrank);
+  down = (rpl_opt->flags & RPL_HDR_OPT_DOWN) ? 1 : 0;
+  sender_rank = UIP_HTONS(rpl_opt->senderrank);
   sender = nbr_table_get_from_lladdr(rpl_neighbors, packetbuf_addr(PACKETBUF_ADDR_SENDER));
-  rank_error_signaled = (UIP_EXT_HDR_OPT_RPL_BUF->flags & RPL_HDR_OPT_RANK_ERR) ? 1 : 0;
+  rank_error_signaled = (rpl_opt->flags & RPL_HDR_OPT_RANK_ERR) ? 1 : 0;
   sender_closer = sender_rank < curr_instance.dag.rank;
   loop_detected = (down && !sender_closer) || (!down && sender_closer);
 
@@ -406,7 +349,7 @@ rpl_ext_header_hbh_update(int uip_ext_opt_offset)
 
   if(loop_detected) {
     /* Set forward error flag */
-    UIP_EXT_HDR_OPT_RPL_BUF->flags |= RPL_HDR_OPT_RANK_ERR;
+    rpl_opt->flags |= RPL_HDR_OPT_RANK_ERR;
   }
 
   return rpl_process_hbh(sender, sender_rank, loop_detected, rank_error_signaled);
@@ -418,34 +361,27 @@ rpl_ext_header_hbh_update(int uip_ext_opt_offset)
 static int
 update_hbh_header(void)
 {
-  int uip_ext_opt_offset;
-  int last_uip_ext_len;
-
-  last_uip_ext_len = uip_ext_len;
-  uip_ext_len = 0;
-  uip_ext_opt_offset = 2;
+  struct uip_hbho_hdr *hbh_hdr = (struct uip_hbho_hdr *)UIP_IP_PAYLOAD(0);
+  struct uip_ext_hdr_opt_rpl *rpl_opt = (struct uip_ext_hdr_opt_rpl *)(UIP_IP_PAYLOAD(2));
 
-  if(UIP_IP_BUF->proto == UIP_PROTO_HBHO && UIP_EXT_HDR_OPT_RPL_BUF->opt_type == UIP_EXT_HDR_OPT_RPL) {
-    if(UIP_HBHO_BUF->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
-        || UIP_EXT_HDR_OPT_RPL_BUF->opt_len != RPL_HDR_OPT_LEN) {
+  if(UIP_IP_BUF->proto == UIP_PROTO_HBHO && rpl_opt->opt_type == UIP_EXT_HDR_OPT_RPL) {
+    if(hbh_hdr->len != ((RPL_HOP_BY_HOP_LEN - 8) / 8)
+        || rpl_opt->opt_len != RPL_HDR_OPT_LEN) {
 
-      LOG_ERR("hop-by-hop extension header has wrong size (%u %u)\n",
-          UIP_EXT_HDR_OPT_RPL_BUF->opt_len, uip_ext_len);
+      LOG_ERR("hop-by-hop extension header has wrong size (%u)\n", rpl_opt->opt_len);
       return 0; /* Drop */
     }
 
-    if(!curr_instance.used || curr_instance.instance_id != UIP_EXT_HDR_OPT_RPL_BUF->instance) {
+    if(!curr_instance.used || curr_instance.instance_id != rpl_opt->instance) {
       LOG_ERR("unable to add/update hop-by-hop extension header: incorrect instance\n");
-      uip_ext_len = last_uip_ext_len;
       return 0; /* Drop */
     }
 
     /* Update sender rank and instance, will update flags next */
-    UIP_EXT_HDR_OPT_RPL_BUF->senderrank = UIP_HTONS(curr_instance.dag.rank);
-    UIP_EXT_HDR_OPT_RPL_BUF->instance = curr_instance.instance_id;
+    rpl_opt->senderrank = UIP_HTONS(curr_instance.dag.rank);
+    rpl_opt->instance = curr_instance.instance_id;
   }
 
-  uip_ext_len = last_uip_ext_len;
   return 1;
 }
 /*---------------------------------------------------------------------------*/
@@ -456,45 +392,34 @@ update_hbh_header(void)
 static int
 insert_hbh_header(void)
 {
-  int uip_ext_opt_offset;
-  int last_uip_ext_len;
-  uint8_t temp_len;
-
-  last_uip_ext_len = uip_ext_len;
-  uip_ext_len = 0;
-  uip_ext_opt_offset = 2;
+  struct uip_hbho_hdr *hbh_hdr = (struct uip_hbho_hdr *)UIP_IP_PAYLOAD(0);
+  struct uip_ext_hdr_opt_rpl *rpl_opt = (struct uip_ext_hdr_opt_rpl *)(UIP_IP_PAYLOAD(2));
 
   /* Insert hop-by-hop header */
   LOG_INFO("creating hop-by-hop option\n");
-  if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_BUFSIZE - UIP_LLH_LEN) {
+  if(uip_len + RPL_HOP_BY_HOP_LEN > UIP_LINK_MTU) {
     LOG_ERR("packet too long: impossible to add hop-by-hop option\n");
-    uip_ext_len = last_uip_ext_len;
     return 0;
   }
 
-  /* Move existing ext headers and payload UIP_EXT_BUF further */
-  memmove(UIP_HBHO_NEXT_BUF, UIP_EXT_BUF, uip_len - UIP_IPH_LEN);
-  memset(UIP_HBHO_BUF, 0, RPL_HOP_BY_HOP_LEN);
+  /* Move existing ext headers and payload RPL_HOP_BY_HOP_LEN further */
+  memmove(UIP_IP_PAYLOAD(RPL_HOP_BY_HOP_LEN), UIP_IP_PAYLOAD(0), uip_len - UIP_IPH_LEN);
+  memset(UIP_IP_PAYLOAD(0), 0, RPL_HOP_BY_HOP_LEN);
 
-  /* Update IP and HBH protocol and fields */
-  UIP_HBHO_BUF->next = UIP_IP_BUF->proto;
+  /* Insert HBH header (as first ext header) */
+  hbh_hdr->next = UIP_IP_BUF->proto;
   UIP_IP_BUF->proto = UIP_PROTO_HBHO;
 
   /* Initialize HBH option */
-  UIP_HBHO_BUF->len = (RPL_HOP_BY_HOP_LEN - 8) / 8;
-  UIP_EXT_HDR_OPT_RPL_BUF->opt_type = UIP_EXT_HDR_OPT_RPL;
-  UIP_EXT_HDR_OPT_RPL_BUF->opt_len = RPL_HDR_OPT_LEN;
-  UIP_EXT_HDR_OPT_RPL_BUF->flags = 0;
-  UIP_EXT_HDR_OPT_RPL_BUF->senderrank = UIP_HTONS(curr_instance.dag.rank);
-  UIP_EXT_HDR_OPT_RPL_BUF->instance = curr_instance.instance_id;
-  uip_len += RPL_HOP_BY_HOP_LEN;
-  temp_len = UIP_IP_BUF->len[1];
-  UIP_IP_BUF->len[1] += RPL_HOP_BY_HOP_LEN;
-  if(UIP_IP_BUF->len[1] < temp_len) {
-    UIP_IP_BUF->len[0]++;
-  }
+  hbh_hdr->len = (RPL_HOP_BY_HOP_LEN - 8) / 8;
+  rpl_opt->opt_type = UIP_EXT_HDR_OPT_RPL;
+  rpl_opt->opt_len = RPL_HDR_OPT_LEN;
+  rpl_opt->flags = 0;
+  rpl_opt->senderrank = UIP_HTONS(curr_instance.dag.rank);
+  rpl_opt->instance = curr_instance.instance_id;
 
-  uip_ext_len = last_uip_ext_len + RPL_HOP_BY_HOP_LEN;
+  uipbuf_add_ext_hdr(RPL_HOP_BY_HOP_LEN);
+  uipbuf_set_len_field(UIP_IP_BUF, uip_len - UIP_IPH_LEN);
 
   /* Update header before returning */
   return update_hbh_header();
@@ -528,57 +453,59 @@ rpl_ext_header_update(void)
   }
 }
 /*---------------------------------------------------------------------------*/
-void
+bool
 rpl_ext_header_remove(void)
 {
-  uint8_t temp_len;
-  uint8_t rpl_ext_hdr_len;
-  int uip_ext_opt_offset;
-  uint8_t *uip_next_hdr;
-
-  uip_ext_len = 0;
-  uip_ext_opt_offset = 2;
-  uip_next_hdr = &UIP_IP_BUF->proto;
-
-  /* Look for hop-by-hop and routing headers */
-  while(uip_next_hdr != NULL) {
-    switch(*uip_next_hdr) {
-      case UIP_PROTO_HBHO:
-      case UIP_PROTO_ROUTING:
-        if((*uip_next_hdr != UIP_PROTO_HBHO || UIP_EXT_HDR_OPT_RPL_BUF->opt_type == UIP_EXT_HDR_OPT_RPL)) {
-          /* Remove hop-by-hop and routing headers */
-          *uip_next_hdr = UIP_EXT_BUF->next;
-          rpl_ext_hdr_len = (UIP_EXT_BUF->len * 8) + 8;
-          temp_len = UIP_IP_BUF->len[1];
-          uip_len -= rpl_ext_hdr_len;
-          UIP_IP_BUF->len[1] -= rpl_ext_hdr_len;
-          if(UIP_IP_BUF->len[1] > temp_len) {
-            UIP_IP_BUF->len[0]--;
-          }
-          LOG_INFO("removing RPL extension header (type %u, len %u)\n", *uip_next_hdr, rpl_ext_hdr_len);
-          memmove(UIP_EXT_BUF, ((uint8_t *)UIP_EXT_BUF) + rpl_ext_hdr_len, uip_len - UIP_IPH_LEN);
-        } else {
-          uip_next_hdr = &UIP_EXT_BUF->next;
-          uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
-        }
-        break;
-      case UIP_PROTO_DESTO:
-        /*
-         * As per RFC 2460, any header other than the Destination
-         * Options header does not appear between the Hop-by-Hop
-         * Options header and the Routing header.
-         *
-         * We're moving to the next header only if uip_next_hdr has
-         * UIP_PROTO_DESTO. Otherwise, we'll return.
-         */
-        /* Move to next header */
-        uip_next_hdr = &UIP_EXT_BUF->next;
-        uip_ext_len += (UIP_EXT_BUF->len << 3) + 8;
+  uint8_t *prev_proto_ptr;
+  uint8_t protocol;
+  uint16_t ext_len;
+  uint8_t *next_header;
+  struct uip_ext_hdr *ext_ptr;
+  struct uip_ext_hdr_opt *opt_ptr;
+
+  next_header = uipbuf_get_next_header(uip_buf, uip_len, &protocol, true);
+  if(next_header == NULL) {
+    return true;
+  }
+  ext_ptr = (struct uip_ext_hdr *)next_header;
+  prev_proto_ptr = &UIP_IP_BUF->proto;
+
+  while(uip_is_proto_ext_hdr(protocol)) {
+    opt_ptr = (struct uip_ext_hdr_opt *)(next_header + 2);
+    if(protocol == UIP_PROTO_ROUTING ||
+       (protocol == UIP_PROTO_HBHO && opt_ptr->type == UIP_EXT_HDR_OPT_RPL)) {
+      /* Remove ext header */
+      *prev_proto_ptr = ext_ptr->next;
+      ext_len = ext_ptr->len * 8 + 8;
+      if(uipbuf_add_ext_hdr(-ext_len) == false) {
+        return false;
+      }
+
+      /* Update length field and move rest of packet to the "left" */
+      uipbuf_set_len_field(UIP_IP_BUF, uip_len - UIP_IPH_LEN);
+      if(uip_len <= next_header - uip_buf) {
+        /* No more data to move. */
+        return false;
+      }
+      memmove(next_header, next_header + ext_len,
+              uip_len - (next_header - uip_buf));
+
+      /* Update loop variables */
+      protocol = *prev_proto_ptr;
+    } else {
+      /* move to the ext hdr */
+      next_header = uipbuf_get_next_header(next_header,
+                                           uip_len - (next_header - uip_buf),
+                                           &protocol, false);
+      if(next_header == NULL) {
+        /* Processing finished. */
         break;
-    default:
-      return;
+      }
+      ext_ptr = (struct uip_ext_hdr *)next_header;
+      prev_proto_ptr = &ext_ptr->next;
     }
   }
-}
 
+  return true;
+}
 /** @}*/
diff --git a/os/net/routing/rpl-lite/rpl-ext-header.h b/os/net/routing/rpl-lite/rpl-ext-header.h
index df61bc325f1a9f1a263cd76a65bbd2e13bae6849..1328a14999407a4bfeb3dcd57aa238de4aed6875 100644
--- a/os/net/routing/rpl-lite/rpl-ext-header.h
+++ b/os/net/routing/rpl-lite/rpl-ext-header.h
@@ -63,12 +63,13 @@ int rpl_ext_header_srh_update(void);
 * Process and update the RPL hop-by-hop extension headers of
 * the current uIP packet.
 *
-* \param uip_ext_opt_offset The offset within the uIP packet where
-* extension headers start
+* \param ext_buf A pointer to the ext header buffer
+* \param opt_offset The offset within the extension header where
+* the option starts
 * \return 1 in case the packet is valid and to be processed further,
 * 0 in case the packet must be dropped.
 */
-int rpl_ext_header_hbh_update(int uip_ext_opt_offset);
+int rpl_ext_header_hbh_update(uint8_t *ext_buf, int opt_offset);
 
 /**
  * Adds/updates all RPL extension headers to current uIP packet.
@@ -79,8 +80,10 @@ int rpl_ext_header_update(void);
 
 /**
  * Removes all RPL extension headers.
+ *
+ * \return true in case of success, false otherwise
 */
-void rpl_ext_header_remove(void);
+bool rpl_ext_header_remove(void);
 
  /** @} */
 
diff --git a/os/net/routing/rpl-lite/rpl-icmp6.c b/os/net/routing/rpl-lite/rpl-icmp6.c
index be5ea2948430cb7c4ecc9be6fa7d2f36cd0f7214..335c640d92ac68eb0ac2a937dcb6147c0ef85040 100644
--- a/os/net/routing/rpl-lite/rpl-icmp6.c
+++ b/os/net/routing/rpl-lite/rpl-icmp6.c
@@ -62,10 +62,6 @@
 #define RPL_DIO_MOP_MASK                 0x38
 #define RPL_DIO_PREFERENCE_MASK          0x07
 
-#define UIP_IP_BUF       ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-#define UIP_ICMP_BUF     ((struct uip_icmp_hdr *)&uip_buf[uip_l2_l3_hdr_len])
-#define UIP_ICMP_PAYLOAD ((unsigned char *)&uip_buf[uip_l2_l3_icmp_hdr_len])
-
 /*---------------------------------------------------------------------------*/
 static void dis_input(void);
 static void dio_input(void);
@@ -147,7 +143,7 @@ dis_input(void)
   rpl_process_dis(&UIP_IP_BUF->srcipaddr, uip_is_addr_mcast(&UIP_IP_BUF->destipaddr));
 
   discard:
-    uip_clear_buf();
+    uipbuf_clear();
 }
 /*---------------------------------------------------------------------------*/
 void
@@ -329,7 +325,7 @@ dio_input(void)
   rpl_process_dio(&from, &dio);
 
 discard:
-  uip_clear_buf();
+  uipbuf_clear();
 }
 /*---------------------------------------------------------------------------*/
 void
@@ -540,7 +536,7 @@ dao_input(void)
   rpl_process_dao(&from, &dao);
 
   discard:
-    uip_clear_buf();
+    uipbuf_clear();
 }
 /*---------------------------------------------------------------------------*/
 void
@@ -583,7 +579,7 @@ rpl_icmp6_dao_output(uint8_t lifetime)
 #endif /* RPL_WITH_DAO_ACK */
   ++pos;
   buffer[pos++] = 0; /* reserved */
-  buffer[pos++] = curr_instance.dag.dao_curr_seqno;
+  buffer[pos++] = curr_instance.dag.dao_last_seqno;
 
   /* create target subopt */
   prefixlen = sizeof(*prefix) * CHAR_BIT;
@@ -610,7 +606,7 @@ rpl_icmp6_dao_output(uint8_t lifetime)
 
   LOG_INFO("sending a %sDAO seqno %u, tx count %u, lifetime %u, prefix ",
          lifetime == 0 ? "No-path " : "",
-         curr_instance.dag.dao_curr_seqno, curr_instance.dag.dao_transmissions, lifetime);
+         curr_instance.dag.dao_last_seqno, curr_instance.dag.dao_transmissions, lifetime);
   LOG_INFO_6ADDR(prefix);
   LOG_INFO_(" to ");
   LOG_INFO_6ADDR(&curr_instance.dag.dag_id);
@@ -644,14 +640,14 @@ dao_ack_input(void)
 
   LOG_INFO("received a DAO-%s with seqno %d (%d %d) and status %d from ",
          status < RPL_DAO_ACK_UNABLE_TO_ACCEPT ? "ACK" : "NACK", sequence,
-         curr_instance.dag.dao_curr_seqno, curr_instance.dag.dao_curr_seqno, status);
+         curr_instance.dag.dao_last_seqno, curr_instance.dag.dao_last_seqno, status);
   LOG_INFO_6ADDR(&UIP_IP_BUF->srcipaddr);
   LOG_INFO_("\n");
 
   rpl_process_dao_ack(sequence, status);
 
   discard:
-    uip_clear_buf();
+    uipbuf_clear();
 }
 /*---------------------------------------------------------------------------*/
 void
diff --git a/os/net/routing/rpl-lite/rpl-nbr-policy.c b/os/net/routing/rpl-lite/rpl-nbr-policy.c
index 9752b1446efcf19da9cf5543b92409a820438a1c..188ceb648e609c553ecb3489a7a7e1990a9dc9e0 100644
--- a/os/net/routing/rpl-lite/rpl-nbr-policy.c
+++ b/os/net/routing/rpl-lite/rpl-nbr-policy.c
@@ -59,11 +59,10 @@
  * NOTE: this policy assumes that all neighbors end up being IPv6
  * neighbors and are not only MAC neighbors.
  */
-#define UIP_IP_BUF    ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
 
 static int num_parents;   /* all nodes that are possible parents */
 static int num_free;
-static linkaddr_t *worst_rank_nbr_lladdr; /* lladdr of the the neighbor with the worst rank */
+static const linkaddr_t *worst_rank_nbr_lladdr; /* lladdr of the the neighbor with the worst rank */
 static rpl_rank_t worst_rank;
 
 /*---------------------------------------------------------------------------*/
@@ -79,10 +78,10 @@ update_state(void)
   worst_rank_nbr_lladdr = NULL;
   num_parents = 0;
 
-  ds6_nbr = nbr_table_head(ds6_neighbors);
+  ds6_nbr = uip_ds6_nbr_head();
   while(ds6_nbr != NULL) {
 
-    linkaddr_t *nbr_lladdr = nbr_table_get_lladdr(ds6_neighbors, ds6_nbr);
+    const linkaddr_t *nbr_lladdr = (const linkaddr_t *)uip_ds6_nbr_get_ll(ds6_nbr);
     rpl_nbr = rpl_neighbor_get_from_lladdr((uip_lladdr_t *)nbr_lladdr);
 
     if(rpl_nbr != NULL && rpl_neighbor_is_parent(rpl_nbr)) {
@@ -98,7 +97,7 @@ update_state(void)
       worst_rank_nbr_lladdr = nbr_lladdr;
     }
 
-    ds6_nbr = nbr_table_next(ds6_neighbors, ds6_nbr);
+    ds6_nbr = uip_ds6_nbr_next(ds6_nbr);
     num_used++;
   }
   /* how many more IP neighbors can be have? */
diff --git a/os/net/routing/rpl-lite/rpl-neighbor.c b/os/net/routing/rpl-lite/rpl-neighbor.c
index a0f5d95b0ad0010f7d3d6b28cb6f5b764217c281..6d33e7be3dbdbe04a71290b80c6c6c5bdc5b52fc 100644
--- a/os/net/routing/rpl-lite/rpl-neighbor.c
+++ b/os/net/routing/rpl-lite/rpl-neighbor.c
@@ -181,9 +181,9 @@ rpl_neighbor_count(void)
 static uip_ds6_nbr_t *
 rpl_get_ds6_nbr(rpl_nbr_t *nbr)
 {
-  const linkaddr_t *lladdr = rpl_neighbor_get_lladdr(nbr);
+  const uip_lladdr_t *lladdr = (const uip_lladdr_t *)rpl_neighbor_get_lladdr(nbr);
   if(lladdr != NULL) {
-    return nbr_table_get_from_lladdr(ds6_neighbors, lladdr);
+    return uip_ds6_nbr_ll_lookup(lladdr);
   } else {
     return NULL;
   }
@@ -196,9 +196,12 @@ remove_neighbor(rpl_nbr_t *nbr)
   /* Make sure we don't point to a removed neighbor. Note that we do not need
   to worry about preferred_parent here, as it is locked in the the table
   and will never be removed by external modules. */
+#if RPL_WITH_PROBING
   if(nbr == curr_instance.dag.urgent_probing_target) {
     curr_instance.dag.urgent_probing_target = NULL;
   }
+#endif
+
   if(nbr == curr_instance.dag.unicast_dio_target) {
     curr_instance.dag.unicast_dio_target = NULL;
   }
@@ -357,8 +360,9 @@ best_parent(int fresh_only)
   /* Search for the best parent according to the OF */
   for(nbr = nbr_table_head(rpl_neighbors); nbr != NULL; nbr = nbr_table_next(rpl_neighbors, nbr)) {
 
-    if(!acceptable_rank(nbr->rank) || !curr_instance.of->nbr_is_acceptable_parent(nbr)) {
-      /* Exclude neighbors with a rank that is not acceptable) */
+    if(!acceptable_rank(rpl_neighbor_rank_via_nbr(nbr))
+      || !curr_instance.of->nbr_is_acceptable_parent(nbr)) {
+      /* Exclude neighbors with a rank that is not acceptable */
       continue;
     }
 
diff --git a/os/net/routing/rpl-lite/rpl-timers.c b/os/net/routing/rpl-lite/rpl-timers.c
index c41b9294818c7954a061abee26ddc055d2f31ed1..169226fd5c4c156df73c9b469f7c07c0001b58a6 100644
--- a/os/net/routing/rpl-lite/rpl-timers.c
+++ b/os/net/routing/rpl-lite/rpl-timers.c
@@ -71,8 +71,9 @@ clock_time_t RPL_PROBING_DELAY_FUNC(void);
 static void handle_dis_timer(void *ptr);
 static void handle_dio_timer(void *ptr);
 static void handle_unicast_dio_timer(void *ptr);
-static void handle_dao_timer(void *ptr);
+static void send_new_dao(void *ptr);
 #if RPL_WITH_DAO_ACK
+static void resend_dao(void *ptr);
 static void handle_dao_ack_timer(void *ptr);
 #endif /* RPL_WITH_DAO_ACK */
 #if RPL_WITH_PROBING
@@ -224,7 +225,7 @@ static void
 schedule_dao_retransmission(void)
 {
   clock_time_t expiration_time = RPL_DAO_RETRANSMISSION_TIMEOUT / 2 + (random_rand() % (RPL_DAO_RETRANSMISSION_TIMEOUT));
-  ctimer_set(&curr_instance.dag.dao_timer, expiration_time, handle_dao_timer, NULL);
+  ctimer_set(&curr_instance.dag.dao_timer, expiration_time, resend_dao, NULL);
 }
 #endif /* RPL_WITH_DAO_ACK */
 /*---------------------------------------------------------------------------*/
@@ -247,9 +248,8 @@ schedule_dao_refresh(void)
       target_refresh -= safety_margin;
     }
 
-    /* Increment next sequno */
-    RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_curr_seqno);
-    ctimer_set(&curr_instance.dag.dao_timer, target_refresh, handle_dao_timer, NULL);
+    /* Schedule transmission */
+    ctimer_set(&curr_instance.dag.dao_timer, target_refresh, send_new_dao, NULL);
   }
 }
 /*---------------------------------------------------------------------------*/
@@ -261,36 +261,16 @@ rpl_timers_schedule_dao(void)
     * only serves storing mode. Use simple delay instead, with the only purpose
     * to reduce congestion. */
     clock_time_t expiration_time = RPL_DAO_DELAY / 2 + (random_rand() % (RPL_DAO_DELAY));
-    /* Increment next seqno */
-    RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_curr_seqno);
-    ctimer_set(&curr_instance.dag.dao_timer, expiration_time, handle_dao_timer, NULL);
+    ctimer_set(&curr_instance.dag.dao_timer, expiration_time, send_new_dao, NULL);
   }
 }
 /*---------------------------------------------------------------------------*/
 static void
-handle_dao_timer(void *ptr)
+send_new_dao(void *ptr)
 {
 #if RPL_WITH_DAO_ACK
-  if(rpl_lollipop_greater_than(curr_instance.dag.dao_curr_seqno,
-    curr_instance.dag.dao_last_seqno)) {
-    /* We are sending a new DAO here. Prepare retransmissions */
-    curr_instance.dag.dao_transmissions = 0;
-  } else {
-    /* We are called for the same DAO again */
-    if(curr_instance.dag.dao_last_acked_seqno == curr_instance.dag.dao_last_seqno) {
-      /* The last seqno sent is ACKed! Schedule refresh to avoid route expiration */
-      schedule_dao_refresh();
-      return;
-    }
-    /* We need to re-send the last DAO */
-    if(curr_instance.dag.dao_transmissions >= RPL_DAO_MAX_RETRANSMISSIONS) {
-      /* No more retransmissions. Perform local repair and hope to find another . */
-      rpl_local_repair("DAO max rtx");
-      return;
-    }
-  }
-  /* Increment transmission counter before sending */
-  curr_instance.dag.dao_transmissions++;
+  /* We are sending a new DAO here. Prepare retransmissions */
+  curr_instance.dag.dao_transmissions = 1;
   /* Schedule next retransmission */
   schedule_dao_retransmission();
 #else /* RPL_WITH_DAO_ACK */
@@ -299,19 +279,14 @@ handle_dao_timer(void *ptr)
     curr_instance.dag.state = DAG_REACHABLE;
   }
   rpl_timers_dio_reset("Reachable");
+  /* There is no DAO-ACK, schedule a refresh. */
+  schedule_dao_refresh();
 #endif /* !RPL_WITH_DAO_ACK */
 
-  curr_instance.dag.dao_last_seqno = curr_instance.dag.dao_curr_seqno;
+  /* Increment seqno */
+  RPL_LOLLIPOP_INCREMENT(curr_instance.dag.dao_last_seqno);
   /* Send a DAO with own prefix as target and default lifetime */
   rpl_icmp6_dao_output(curr_instance.default_lifetime);
-
-#if !RPL_WITH_DAO_ACK
-  /* There is no DAO-ACK, schedule a refresh. Must be done after rpl_icmp6_dao_output,
-  because we increment curr_instance.dag.dao_curr_seqno for the next DAO (refresh).
-  Where there is DAO-ACK, the refresh is scheduled after reception of the ACK.
-  Happens when handle_dao_timer is called again next. */
-  schedule_dao_refresh();
-#endif /* !RPL_WITH_DAO_ACK */
 }
 #if RPL_WITH_DAO_ACK
 /*---------------------------------------------------------------------------*/
@@ -334,6 +309,32 @@ handle_dao_ack_timer(void *ptr)
   rpl_icmp6_dao_ack_output(&curr_instance.dag.dao_ack_target,
     curr_instance.dag.dao_ack_sequence, RPL_DAO_ACK_UNCONDITIONAL_ACCEPT);
 }
+/*---------------------------------------------------------------------------*/
+void
+rpl_timers_notify_dao_ack(void)
+{
+  /* The last DAO was ACKed. Schedule refresh to avoid route expiration. This
+  implicitly de-schedules resend_dao, as both share curr_instance.dag.dao_timer */
+  schedule_dao_refresh();
+}
+/*---------------------------------------------------------------------------*/
+static void
+resend_dao(void *ptr)
+{
+  /* Increment transmission counter before sending */
+  curr_instance.dag.dao_transmissions++;
+  /* Send a DAO with own prefix as target and default lifetime */
+  rpl_icmp6_dao_output(curr_instance.default_lifetime);
+
+  /* Schedule next retransmission, or abort */
+  if(curr_instance.dag.dao_transmissions < RPL_DAO_MAX_RETRANSMISSIONS) {
+    schedule_dao_retransmission();
+  } else {
+    /* No more retransmissions. Perform local repair. */
+    rpl_local_repair("DAO max rtx");
+    return;
+  }
+}
 #endif /* RPL_WITH_DAO_ACK */
 /*---------------------------------------------------------------------------*/
 /*------------------------------- Probing----------------------------------- */
diff --git a/os/net/routing/rpl-lite/rpl-timers.h b/os/net/routing/rpl-lite/rpl-timers.h
index e153858fc6f78254f9a71336db85b4f240f8200d..5d9498b97074b0df3053f4c4e90d51c55de4a999 100644
--- a/os/net/routing/rpl-lite/rpl-timers.h
+++ b/os/net/routing/rpl-lite/rpl-timers.h
@@ -99,6 +99,11 @@ void rpl_timers_schedule_dao(void);
 */
 void rpl_timers_schedule_dao_ack(uip_ipaddr_t *target, uint16_t sequence);
 
+/**
+ * Let the rpl-timers module know that the last DAO was ACKed
+*/
+void rpl_timers_notify_dao_ack(void);
+
 /**
  * Schedule probing with delay RPL_PROBING_DELAY_FUNC()
 */
diff --git a/os/net/routing/rpl-lite/rpl-types.h b/os/net/routing/rpl-lite/rpl-types.h
index 16dfa057e6c1350446ab3b0d778efc5807dae1da..2c57bf664dc83d88a037fad91d07c88113f9fc6f 100644
--- a/os/net/routing/rpl-lite/rpl-types.h
+++ b/os/net/routing/rpl-lite/rpl-types.h
@@ -198,7 +198,6 @@ struct rpl_dag {
   uint8_t dio_counter; /* internal trickle timer state: redundancy counter */
   uint8_t dao_last_seqno; /* the node's last sent DAO seqno */
   uint8_t dao_last_acked_seqno; /* the last seqno we got an ACK for */
-  uint8_t dao_curr_seqno; /* the node's current DAO seqno (sent or to be sent) */
   uint8_t dao_transmissions; /* the number of transmissions for the current DAO */
   enum rpl_dag_state state;
 
diff --git a/os/net/routing/rpl-lite/rpl.c b/os/net/routing/rpl-lite/rpl.c
index 47ffc53877adb145cb750c8cd1fba405996293fa..681b85d9ee8e99ff4f62c70b11d68c16a81b6f85 100644
--- a/os/net/routing/rpl-lite/rpl.c
+++ b/os/net/routing/rpl-lite/rpl.c
@@ -101,9 +101,11 @@ rpl_link_callback(const linkaddr_t *addr, int status, int numtx)
     if(nbr != NULL) {
       /* If this is the neighbor we were probing urgently, mark urgent
       probing as done */
+#if RPL_WITH_PROBING
       if(curr_instance.dag.urgent_probing_target == nbr) {
         curr_instance.dag.urgent_probing_target = NULL;
       }
+#endif
       /* Link stats were updated, and we need to update our internal state.
       Updating from here is unsafe; postpone */
       LOG_INFO("packet sent to ");
diff --git a/os/net/routing/rpl-lite/rpl.h b/os/net/routing/rpl-lite/rpl.h
index e39c825c4d0babc57c9fc03beddab758bf1e82c0..0627e5d1dd31d122d017e4ed064b8e035024f20b 100644
--- a/os/net/routing/rpl-lite/rpl.h
+++ b/os/net/routing/rpl-lite/rpl.h
@@ -28,7 +28,7 @@
  *
  * This file is part of the Contiki operating system.
  *
- * \ingroup net-layer
+ * \ingroup routing
  * \addtogroup rpl-lite
  RPL-lite is a lightweight implementation of RPL tailored for reliability.
  Supports only non-storing mode, one instance and one DAG.
diff --git a/os/services/deployment/deployment.h b/os/services/deployment/deployment.h
index 29cd5214b0250e2d106afec74906b94ed6246a6d..21e25a4c9d77f347d4f8c81173ecfb14d2808c69 100644
--- a/os/services/deployment/deployment.h
+++ b/os/services/deployment/deployment.h
@@ -29,14 +29,16 @@
  */
 
 /**
-* \addtogroup deployment
-* @{
-*
-* \file
-     Per-deployment MAC <-> nodeid mapping
-* \author Simon Duquennoy <simon.duquennoy@ri.se>
-*
-*/
+ * \addtogroup lib
+ * @{
+ *
+ * \defgroup deployment A module to handle Node IDs and MAC addresses in deployments
+ * @{
+ *
+ * \file
+ *   Per-deployment MAC <-> nodeid mapping
+ * \author Simon Duquennoy <simon.duquennoy@ri.se>
+ */
 
 #ifndef DEPLOYMENT_H_
 #define DEPLOYMENT_H_
@@ -123,4 +125,7 @@ void deployment_iid_from_id(uip_ipaddr_t *ipaddr, uint16_t id);
 uint16_t deployment_id_from_index(uint16_t index);
 
 #endif /* DEPLOYMENT_H_ */
-/** @} */
+/**
+ * @}
+ * @}
+ */
diff --git a/os/services/ip64/ip64-arp.c b/os/services/ip64/ip64-arp.c
index 75197558d7919da4d9407297d822bbc16be8f839..6fd996920b831a4a685399eb6ee391d293d321da 100644
--- a/os/services/ip64/ip64-arp.c
+++ b/os/services/ip64/ip64-arp.c
@@ -139,7 +139,7 @@ ip64_arp_timer(void)
 {
   struct arp_entry *tabptr;
   int i;
-  
+
   ++arptime;
   for(i = 0; i < UIP_ARPTAB_SIZE; ++i) {
     tabptr = &arp_table[i];
@@ -157,7 +157,7 @@ arp_update(uip_ip4addr_t *ipaddr, struct uip_eth_addr *ethaddr)
 {
   register struct arp_entry *tabptr = arp_table;
   int i, c;
-  
+
   /* Walk through the ARP mapping table and try to find an entry to
      update. If none is found, the IP -> MAC address mapping is
      inserted in the ARP table. */
@@ -170,7 +170,7 @@ arp_update(uip_ip4addr_t *ipaddr, struct uip_eth_addr *ethaddr)
       /* Check if the source IP address of the incoming packet matches
          the IP address in this ARP table entry. */
       if(uip_ip4addr_cmp(ipaddr, &tabptr->ipaddr)) {
-	 
+
 	/* An old entry found, update this and return. */
 	memcpy(tabptr->ethaddr.addr, ethaddr->addr, 6);
 	tabptr->time = arptime;
@@ -239,7 +239,7 @@ ip64_arp_arp_input(const uint8_t *packet, uint16_t packet_len)
 	 table, since it is likely that we will do more communication
 	 with this host in the future. */
       arp_update(&arphdr->sipaddr, &arphdr->shwaddr);
-      
+
       arphdr->opcode = UIP_HTONS(ARP_REPLY);
 
       memcpy(arphdr->dhwaddr.addr, arphdr->shwaddr.addr, 6);
@@ -275,7 +275,7 @@ ip64_arp_check_cache(const uint8_t *nlhdr)
 
   printf("check cache %d.%d.%d.%d\n",
 	 uip_ipaddr_to_quad(&ipv4_hdr->destipaddr));
-  
+
   /* First check if destination is a local broadcast. */
   uip_ipaddr(&broadcast_addr, 255,255,255,255);
   if(uip_ip4addr_cmp(&ipv4_hdr->destipaddr, &broadcast_addr)) {
@@ -321,7 +321,7 @@ ip64_arp_create_ethhdr(uint8_t *llhdr, const uint8_t *nlhdr)
   struct ipv4_hdr *ipv4_hdr = (struct ipv4_hdr *)nlhdr;
   struct ip64_eth_hdr *ethhdr = (struct ip64_eth_hdr *)llhdr;
   uip_ip4addr_t broadcast_addr;
-  
+
   /* Find the destination IP address in the ARP table and construct
      the Ethernet header. If the destination IP addres isn't on the
      local network, we use the default router's IP address instead.
@@ -371,7 +371,7 @@ ip64_arp_create_ethhdr(uint8_t *llhdr, const uint8_t *nlhdr)
 
   }
   memcpy(ethhdr->src.addr, ip64_eth_addr.addr, 6);
-  
+
   ethhdr->type = UIP_HTONS(IP64_ETH_TYPE_IP);
   return sizeof(struct ip64_eth_hdr);
 }
@@ -382,7 +382,7 @@ ip64_arp_create_arp_request(uint8_t *llhdr, const uint8_t *nlhdr)
   struct ipv4_hdr *ipv4_hdr = (struct ipv4_hdr *)nlhdr;
   struct arp_hdr *arp_hdr = (struct arp_hdr *)llhdr;
   uip_ip4addr_t ipaddr;
-  
+
   if(!uip_ipaddr_maskcmp(&ipv4_hdr->destipaddr,
 			 ip64_get_hostaddr(),
 			 ip64_get_netmask())) {
@@ -394,7 +394,7 @@ ip64_arp_create_arp_request(uint8_t *llhdr, const uint8_t *nlhdr)
     /* Else, we use the destination IP address. */
     uip_ip4addr_copy(&ipaddr, &ipv4_hdr->destipaddr);
   }
-  
+
   memset(arp_hdr->ethhdr.dest.addr, 0xff, 6);
   memset(arp_hdr->dhwaddr.addr, 0x00, 6);
   memcpy(arp_hdr->ethhdr.src.addr, ip64_eth_addr.addr, 6);
@@ -408,8 +408,8 @@ ip64_arp_create_arp_request(uint8_t *llhdr, const uint8_t *nlhdr)
   arp_hdr->hwlen = 6;
   arp_hdr->protolen = 4;
   arp_hdr->ethhdr.type = UIP_HTONS(IP64_ETH_TYPE_ARP);
-  
-  uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN];
+
+  uip_appdata = &uip_buf[UIP_IPTCPH_LEN];
 
   return sizeof(struct arp_hdr);
 }
diff --git a/os/services/ip64/ip64-dhcpc.c b/os/services/ip64/ip64-dhcpc.c
index 8e8e286f8913bcb49eee112d9e09e2a22350af08..10a5184e3f3003534ff90168566d7ccdf8c105d4 100644
--- a/os/services/ip64/ip64-dhcpc.c
+++ b/os/services/ip64/ip64-dhcpc.c
@@ -61,7 +61,7 @@ struct dhcp_msg {
   uint8_t options[312];
 };
 
-#if (UIP_BUFSIZE - UIP_LLH_LEN - UIP_UDPIP_HLEN) < 548
+#if (UIP_BUFSIZE - UIP_UDPIP_HLEN) < 548
 #error UIP_CONF_BUFFER_SIZE may be too small to accomodate DHCPv4 packets
 #error Increase UIP_CONF_BUFFER_SIZE in your project-conf.h, or contiki-conf.h
 #error A good size is 600 bytes
@@ -191,12 +191,12 @@ send_request(void)
   struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
 
   create_msg(m);
-  
+
   end = add_msg_type(&m->options[4], DHCPREQUEST);
   end = add_server_id(end);
   end = add_req_ipaddr(end);
   end = add_end(end);
-  
+
   uip_send(uip_appdata, (int)(end - (uint8_t *)uip_appdata));
 }
 /*---------------------------------------------------------------------------*/
@@ -239,7 +239,7 @@ static uint8_t
 parse_msg(void)
 {
   struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
-  
+
   if(m->op == DHCP_REPLY &&
      memcmp(m->xid, &xid, sizeof(xid)) == 0 &&
      memcmp(m->chaddr, s.mac_addr, s.mac_len) == 0) {
@@ -258,7 +258,7 @@ msg_for_me(void)
   struct dhcp_msg *m = (struct dhcp_msg *)uip_appdata;
   uint8_t *optptr = &m->options[4];
   uint8_t *end = (uint8_t*)uip_appdata + uip_datalen();
-  
+
   if(m->op == DHCP_REPLY &&
      memcmp(m->xid, &xid, sizeof(xid)) == 0 &&
      memcmp(m->chaddr, s.mac_addr, s.mac_len) == 0) {
@@ -280,7 +280,7 @@ PT_THREAD(handle_dhcp(process_event_t ev, void *data))
   clock_time_t ticks;
 
   PT_BEGIN(&s.pt);
-  
+
  init:
   xid++;
   s.state = STATE_SENDING;
@@ -305,7 +305,7 @@ PT_THREAD(handle_dhcp(process_event_t ev, void *data))
       s.ticks *= 2;
     }
   }
-  
+
  selecting:
   s.ticks = CLOCK_SECOND;
   do {
@@ -330,7 +330,7 @@ PT_THREAD(handle_dhcp(process_event_t ev, void *data))
       goto init;
     }
   } while(s.state != STATE_CONFIG_RECEIVED);
-  
+
  bound:
 #if 0
   printf("Got IP address %d.%d.%d.%d\n", uip_ipaddr_to_quad(&s.ipaddr));
@@ -343,7 +343,7 @@ PT_THREAD(handle_dhcp(process_event_t ev, void *data))
 #endif
 
   ip64_dhcpc_configured(&s);
-  
+
 #define MAX_TICKS (~((clock_time_t)0) / 2)
 #define MAX_TICKS32 (~((uint32_t)0))
 #define IMIN(a, b) ((a) < (b) ? (a) : (b))
@@ -407,12 +407,12 @@ ip64_dhcpc_init(const void *mac_addr, int mac_len)
   uip_ip6addr_t v6addr;
   uip_ip4addr_t v4addr;
   struct uip_udp_conn *conn2;
-  
+
   s.mac_addr = mac_addr;
   s.mac_len  = mac_len;
 
   s.state = STATE_INITIAL;
-  uip_ipaddr(&v4addr, 255,255,255,255); 
+  uip_ipaddr(&v4addr, 255,255,255,255);
   ip64_addr_4to6(&v4addr, &v6addr);
   s.conn = udp_new(&v6addr, UIP_HTONS(IP64_DHCPC_SERVER_PORT), NULL);
   conn2 = udp_new(NULL, UIP_HTONS(IP64_DHCPC_SERVER_PORT), NULL);
@@ -437,7 +437,7 @@ void
 ip64_dhcpc_request(void)
 {
   uip_ipaddr_t ipaddr;
-  
+
   if(s.state == STATE_INITIAL) {
     uip_ipaddr(&ipaddr, 0,0,0,0);
     uip_sethostaddr(&ipaddr);
diff --git a/os/services/ip64/ip64-eth-interface.c b/os/services/ip64/ip64-eth-interface.c
index 1dcaeb5ad52b234f65193791d7dd350b6447ea45..dc89610e512488c1bfab8e5e430b1dfd04023e6a 100644
--- a/os/services/ip64/ip64-eth-interface.c
+++ b/os/services/ip64/ip64-eth-interface.c
@@ -39,8 +39,6 @@
 
 #include <string.h>
 
-#define UIP_IP_BUF        ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-
 #define DEBUG DEBUG_NONE
 #include "net/ipv6/uip-debug.h"
 #define printf(...)
@@ -62,7 +60,7 @@ ip64_eth_interface_input(uint8_t *packet, uint16_t len)
     printf("-------------->\n");
     uip_len = ip64_4to6(&packet[sizeof(struct ip64_eth_hdr)],
 			len - sizeof(struct ip64_eth_hdr),
-			&uip_buf[UIP_LLH_LEN]);
+			uip_buf);
     if(uip_len > 0) {
       printf("ip64_interface_process: converted %d bytes\n", uip_len);
 
@@ -96,7 +94,7 @@ output(void)
   PRINTF("\n");
 
   printf("<--------------\n");
-  len = ip64_6to4(&uip_buf[UIP_LLH_LEN], uip_len,
+  len = ip64_6to4(uip_buf, uip_len,
 		  &ip64_packet_buffer[sizeof(struct ip64_eth_hdr)]);
 
   printf("ip64-interface: output len %d\n", len);
diff --git a/os/services/ip64/ip64-slip-interface.c b/os/services/ip64/ip64-slip-interface.c
index 10422f2c7d94136e84bf33957e465b02e2e6b68a..fb4f69627bea80dff03d2744a8ad5414442aeebe 100644
--- a/os/services/ip64/ip64-slip-interface.c
+++ b/os/services/ip64/ip64-slip-interface.c
@@ -38,8 +38,6 @@
 #include <string.h>
 #include <stdio.h>
 
-#define UIP_IP_BUF        ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-
 #define DEBUG DEBUG_NONE
 #include "net/ipv6/uip-debug.h"
 
@@ -57,24 +55,24 @@ static void
 input_callback(void)
 {
   /*PRINTF("SIN: %u\n", uip_len);*/
-  if(uip_buf[UIP_LLH_LEN] == '!') {
-    PRINTF("Got configuration message of type %c\n", uip_buf[UIP_LLH_LEN + 1]);
-    uip_clear_buf();
+  if(uip_buf[0] == '!') {
+    PRINTF("Got configuration message of type %c\n", uip_buf[1]);
+    uipbuf_clear();
 #if 0
-    if(uip_buf[UIP_LLH_LEN + 1] == 'P') {
+    if(uip_buf[1] == 'P') {
       uip_ipaddr_t prefix;
       /* Here we set a prefix !!! */
       memset(&prefix, 0, 16);
-      memcpy(&prefix, &uip_buf[UIP_LLH_LEN + 2], 8);
+      memcpy(&prefix, &uip_buf[2], 8);
       PRINTF("Setting prefix ");
       PRINT6ADDR(&prefix);
       PRINTF("\n");
       set_prefix_64(&prefix);
     }
 #endif
-  } else if(uip_buf[UIP_LLH_LEN] == '?') {
-    PRINTF("Got request message of type %c\n", uip_buf[UIP_LLH_LEN + 1]);
-    if(uip_buf[UIP_LLH_LEN + 1] == 'M') {
+  } else if(uip_buf[0] == '?') {
+    PRINTF("Got request message of type %c\n", uip_buf[1]);
+    if(uip_buf[1] == 'M') {
       const char *hexchar = "0123456789abcdef";
       int j;
       /* this is just a test so far... just to see if it works */
@@ -86,21 +84,21 @@ input_callback(void)
       uip_len = 18;
       slip_write(uip_buf, uip_len);
     }
-    uip_clear_buf();
+    uipbuf_clear();
   } else {
-    
+
     /* Save the last sender received over SLIP to avoid bouncing the
        packet back if no route is found */
     uip_ipaddr_copy(&last_sender, &UIP_IP_BUF->srcipaddr);
-    
-    uint16_t len = ip64_4to6(&uip_buf[UIP_LLH_LEN], uip_len, 
+
+    uint16_t len = ip64_4to6(uip_buf, uip_len,
 			     ip64_packet_buffer);
     if(len > 0) {
-      memcpy(&uip_buf[UIP_LLH_LEN], ip64_packet_buffer, len);
+      memcpy(uip_buf, ip64_packet_buffer, len);
       uip_len = len;
       /*      PRINTF("send len %d\n", len); */
     } else {
-      uip_clear_buf();
+      uipbuf_clear();
     }
   }
 }
@@ -129,11 +127,11 @@ output(void)
   if(uip_ipaddr_cmp(&last_sender, &UIP_IP_BUF->srcipaddr)) {
     PRINTF("ip64-interface: output, not sending bounced message\n");
   } else {
-    len = ip64_6to4(&uip_buf[UIP_LLH_LEN], uip_len,
+    len = ip64_6to4(uip_buf, uip_len,
 		    ip64_packet_buffer);
     PRINTF("ip64-interface: output len %d\n", len);
     if(len > 0) {
-      memcpy(&uip_buf[UIP_LLH_LEN], ip64_packet_buffer, len);
+      memcpy(uip_buf, ip64_packet_buffer, len);
       uip_len = len;
       slip_send();
       return len;
diff --git a/os/services/lwm2m/lwm2m-queue-mode-object.h b/os/services/lwm2m/lwm2m-queue-mode-object.h
index 017b797fca6fcc1ab1c8c720110e314c4014aa21..0a47db21963715d4ac9a83fb7df50b7a8aeddb2f 100644
--- a/os/services/lwm2m/lwm2m-queue-mode-object.h
+++ b/os/services/lwm2m/lwm2m-queue-mode-object.h
@@ -29,7 +29,7 @@
  */
 
 /**
- * \addtogroup oma-lwm2m
+ * \addtogroup lwm2m
  * @{
  */
 
@@ -49,4 +49,4 @@
 void lwm2m_queue_mode_object_init(void);
 
 #endif /* LWM2M_Q_OBJECT_H_ */
-/** @} */
\ No newline at end of file
+/** @} */
diff --git a/os/services/lwm2m/lwm2m-queue-mode.h b/os/services/lwm2m/lwm2m-queue-mode.h
index 5c65face5d87fdb0bf390148391584f38bfb40c7..019f80f28d24ceef6f509280a5859b235f8a8a36 100644
--- a/os/services/lwm2m/lwm2m-queue-mode.h
+++ b/os/services/lwm2m/lwm2m-queue-mode.h
@@ -29,7 +29,7 @@
  */
 
 /**
- * \addtogroup oma-lwm2m
+ * \addtogroup lwm2m
  * @{
  */
 
diff --git a/os/services/lwm2m/lwm2m-rd-client.c b/os/services/lwm2m/lwm2m-rd-client.c
index 4b4b1152896ba0d6e80635a78059f739d170261b..6bb58f91a0d54ee0b16b5b96a9f60919d69b180d 100644
--- a/os/services/lwm2m/lwm2m-rd-client.c
+++ b/os/services/lwm2m/lwm2m-rd-client.c
@@ -54,6 +54,7 @@
 #include "coap-endpoint.h"
 #include "coap-callback-api.h"
 #include "lwm2m-security.h"
+#include "lib/list.h"
 #include <stdio.h>
 #include <string.h>
 #include <inttypes.h>
@@ -76,18 +77,11 @@
 #define LWM2M_DEFAULT_CLIENT_LIFETIME 30 /* sec */
 #endif
 
-#define MAX_RD_UPDATE_WAIT 5000
-
 #define REMOTE_PORT        UIP_HTONS(COAP_DEFAULT_PORT)
 #define BS_REMOTE_PORT     UIP_HTONS(5685)
 
 #define STATE_MACHINE_UPDATE_INTERVAL 500
 
-static struct lwm2m_session_info session_info;
-static coap_callback_request_state_t rd_request_state;
-
-static coap_message_t request[1];      /* This way the message can be treated as pointer as usual. */
-
 /* The states for the RD client state machine */
 /* When node is unregistered it ends up in UNREGISTERED
    and this is going to be there until use X or Y kicks it
@@ -114,38 +108,32 @@ static coap_message_t request[1];      /* This way the message can be treated as
 #define FLAG_RD_DATA_UPDATE_TRIGGERED 0x02
 #define FLAG_RD_DATA_UPDATE_ON_DIRTY  0x10
 
-static uint8_t rd_state = 0;
-static uint8_t rd_flags = FLAG_RD_DATA_UPDATE_ON_DIRTY;
-static uint64_t wait_until_network_check = 0;
-static uint64_t last_update;
+LIST(session_info_list);
 
+/* Shared by all sessions, used by only one at a time in the FSM */
 static char query_data[64]; /* allocate some data for queries and updates */
 static uint8_t rd_data[128]; /* allocate some data for the RD */
 
-static uint32_t rd_block1;
-static uint8_t rd_more;
-static coap_timer_t rd_timer;
-static void (*rd_callback)(coap_callback_request_state_t *callback_state);
-
-static coap_timer_t block1_timer;
+static coap_timer_t rd_timer; /* Timer to tick the FSM periodically */
+static char default_ep[20];
 
 #if LWM2M_QUEUE_MODE_ENABLED
-static coap_timer_t queue_mode_client_awake_timer; /* Timer to control the client's 
-                                                * awake time 
-                                                */
-static uint8_t queue_mode_client_awake; /* 1 - client is awake, 
-                                     * 0 - client is sleeping 
-                                     */
+static coap_timer_t queue_mode_client_awake_timer; /* Timer to control the client's
+                                                    * awake time
+                                                    */
+static uint8_t queue_mode_client_awake; /* 1 - client is awake,
+                                         * 0 - client is sleeping
+                                         */
 static uint16_t queue_mode_client_awake_time; /* The time to be awake */
 /* Callback for the client awake timer */
-static void queue_mode_awake_timer_callback(coap_timer_t *timer); 
+static void queue_mode_awake_timer_callback(coap_timer_t *timer);
 #endif
 
 static void check_periodic_observations();
 static void update_callback(coap_callback_request_state_t *callback_state);
-
+/*---------------------------------------------------------------------------*/
 static int
-set_rd_data(coap_message_t *request)
+set_rd_data(lwm2m_session_info_t *session_info)
 {
   lwm2m_buffer_t outbuf;
 
@@ -155,31 +143,31 @@ set_rd_data(coap_message_t *request)
   outbuf.len = 0;
 
   /* this will also set the request payload */
-  rd_more = lwm2m_engine_set_rd_data(&outbuf, 0);
-  coap_set_payload(request, rd_data, outbuf.len);
+  session_info->rd_more = lwm2m_engine_set_rd_data(&outbuf, 0);
+  coap_set_payload(session_info->request, rd_data, outbuf.len);
 
-  if(rd_more) {
+  if(session_info->rd_more) {
     /* set the first block here */
     LOG_DBG("Setting block1 in request\n");
-    coap_set_header_block1(request, 0, 1, sizeof(rd_data));
+    coap_set_header_block1(session_info->request, 0, 1, sizeof(rd_data));
   }
   return outbuf.len;
 }
 /*---------------------------------------------------------------------------*/
 static void
-prepare_update(coap_message_t *request, int triggered)
+prepare_update(lwm2m_session_info_t *session_info, int triggered)
 {
-  coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0);
-  coap_set_header_uri_path(request, session_info.assigned_ep);
+  coap_init_message(session_info->request, COAP_TYPE_CON, COAP_POST, 0);
+  coap_set_header_uri_path(session_info->request, session_info->assigned_ep);
 
-  snprintf(query_data, sizeof(query_data) - 1, "?lt=%d&b=%s", session_info.lifetime, session_info.binding);
-  LOG_DBG("UPDATE:%s %s\n", session_info.assigned_ep, query_data);
-  coap_set_header_uri_query(request, query_data);
+  snprintf(query_data, sizeof(query_data) - 1, "?lt=%d&b=%s", session_info->lifetime, session_info->binding);
+  LOG_DBG("UPDATE:%s %s\n", session_info->assigned_ep, query_data);
+  coap_set_header_uri_query(session_info->request, query_data);
 
-  if((triggered || rd_flags & FLAG_RD_DATA_UPDATE_ON_DIRTY) && (rd_flags & FLAG_RD_DATA_DIRTY)) {
-    rd_flags &= ~FLAG_RD_DATA_DIRTY;
-    set_rd_data(request);
-    rd_callback = update_callback;
+  if((triggered || session_info->rd_flags & FLAG_RD_DATA_UPDATE_ON_DIRTY) && (session_info->rd_flags & FLAG_RD_DATA_DIRTY)) {
+    session_info->rd_flags &= ~FLAG_RD_DATA_DIRTY;
+    set_rd_data(session_info);
+    session_info->rd_callback = update_callback;
   }
 }
 /*---------------------------------------------------------------------------*/
@@ -198,164 +186,152 @@ has_network_access(void)
 }
 /*---------------------------------------------------------------------------*/
 int
-lwm2m_rd_client_is_registered(void)
+lwm2m_rd_client_is_registered(lwm2m_session_info_t *session_info)
 {
-  return rd_state == REGISTRATION_DONE || rd_state == UPDATE_SENT;
-}
-/*---------------------------------------------------------------------------*/
-void
-lwm2m_rd_client_use_bootstrap_server(int use)
-{
-  session_info.use_bootstrap = use != 0;
-  if(session_info.use_bootstrap) {
-    rd_state = INIT;
-  }
+  return session_info->rd_state == REGISTRATION_DONE || session_info->rd_state == UPDATE_SENT;
 }
 /*---------------------------------------------------------------------------*/
 /* will take another argument when we support multiple sessions */
 void
-lwm2m_rd_client_set_session_callback(session_callback_t cb)
+lwm2m_rd_client_set_session_callback(lwm2m_session_info_t *session_info, session_callback_t cb)
 {
-  session_info.callback = cb;
+  session_info->callback = cb;
 }
 /*---------------------------------------------------------------------------*/
 static void
-perform_session_callback(int state)
+perform_session_callback(lwm2m_session_info_t *session_info, int state)
 {
-  if(session_info.callback != NULL) {
+  if(session_info->callback != NULL) {
     LOG_DBG("Performing session callback: %d cb:%p\n",
-            state, session_info.callback);
-    session_info.callback(&session_info, state);
-  }
-}
-/*---------------------------------------------------------------------------*/
-void
-lwm2m_rd_client_use_registration_server(int use)
-{
-  session_info.use_registration = use != 0;
-  if(session_info.use_registration) {
-    rd_state = INIT;
+            state, session_info->callback);
+    session_info->callback(session_info, state);
   }
 }
 /*---------------------------------------------------------------------------*/
 uint16_t
-lwm2m_rd_client_get_lifetime(void)
+lwm2m_rd_client_get_lifetime(lwm2m_session_info_t *session_info)
 {
-  return session_info.lifetime;
+  return session_info->lifetime;
 }
 /*---------------------------------------------------------------------------*/
 void
-lwm2m_rd_client_set_lifetime(uint16_t lifetime)
+lwm2m_rd_client_set_lifetime(lwm2m_session_info_t *session_info, uint16_t lifetime)
 {
   if(lifetime > 0) {
-    session_info.lifetime = lifetime;
+    session_info->lifetime = lifetime;
   } else {
-    session_info.lifetime = LWM2M_DEFAULT_CLIENT_LIFETIME;
+    session_info->lifetime = LWM2M_DEFAULT_CLIENT_LIFETIME;
   }
 }
 /*---------------------------------------------------------------------------*/
 void
-lwm2m_rd_client_set_update_rd(void)
+lwm2m_rd_client_set_endpoint_name(lwm2m_session_info_t *session_info, const char *endpoint)
 {
-  rd_flags |= FLAG_RD_DATA_DIRTY;
+  if(endpoint != NULL) {
+    session_info->ep = endpoint;
+  }
 }
 /*---------------------------------------------------------------------------*/
 void
-lwm2m_rd_client_set_automatic_update(int update)
+lwm2m_rd_client_set_default_endpoint_name(const char *endpoint)
 {
-  rd_flags = (rd_flags & ~FLAG_RD_DATA_UPDATE_ON_DIRTY) |
-    (update != 0 ? FLAG_RD_DATA_UPDATE_ON_DIRTY : 0);
+  strncpy(default_ep, endpoint, sizeof(default_ep) - 1);
+  default_ep[sizeof(default_ep) - 1] = '\0';
 }
 /*---------------------------------------------------------------------------*/
 void
-lwm2m_rd_client_register_with_server(const coap_endpoint_t *server)
+lwm2m_rd_client_set_update_rd(void)
 {
-  coap_endpoint_copy(&session_info.server_ep, server);
-  session_info.has_registration_server_info = 1;
-  session_info.registered = 0;
-  if(session_info.use_registration) {
-    rd_state = INIT;
+  lwm2m_session_info_t *session_info = (lwm2m_session_info_t *)list_head(session_info_list);
+  while(session_info != NULL) {
+    session_info->rd_flags |= FLAG_RD_DATA_DIRTY;
+    session_info = session_info->next;
   }
 }
 /*---------------------------------------------------------------------------*/
-static int
-update_registration_server(void)
+void
+lwm2m_rd_client_set_automatic_update(lwm2m_session_info_t *session_info, int update)
 {
-  if(session_info.has_registration_server_info) {
-    return 1;
-  }
-
-#if UIP_CONF_IPV6_RPL
-  {
-    rpl_dag_t *dag;
-
-    /* Use the DAG id as server address if no other has been specified */
-    dag = rpl_get_any_dag();
-    if(dag != NULL) {
-      /* create coap-endpoint? */
-      /* uip_ipaddr_copy(&server_ipaddr, &dag->dag_id); */
-      /* server_port = REMOTE_PORT; */
-      return 1;
-    }
-  }
-#endif /* UIP_CONF_IPV6_RPL */
-
-  return 0;
+  session_info->rd_flags = (session_info->rd_flags & ~FLAG_RD_DATA_UPDATE_ON_DIRTY) |
+    (update != 0 ? FLAG_RD_DATA_UPDATE_ON_DIRTY : 0);
 }
 /*---------------------------------------------------------------------------*/
 void
-lwm2m_rd_client_register_with_bootstrap_server(const coap_endpoint_t *server)
-{
-  coap_endpoint_copy(&session_info.bs_server_ep, server);
-  session_info.has_bs_server_info = 1;
-  session_info.bootstrapped = 0;
-  session_info.registered = 0;
-  if(session_info.use_bootstrap) {
-    rd_state = INIT;
+lwm2m_rd_client_register_with_server(lwm2m_session_info_t *session_info,
+                                     const coap_endpoint_t *server,
+                                     lwm2m_rd_client_server_type_t server_type)
+{
+  if(session_info->ep == NULL) {
+    session_info->ep = default_ep;
   }
+  /* default binding U = UDP, UQ = UDP Q-mode*/
+#if LWM2M_QUEUE_MODE_CONF_ENABLED
+  session_info->binding = "UQ";
+  /* Enough margin to ensure that the client is not unregistered (we
+   * do not know the time it can stay awake)
+   */
+  session_info->lifetime = (LWM2M_QUEUE_MODE_DEFAULT_CLIENT_SLEEP_TIME / 1000) * 2;
+#else
+  session_info->binding = "U";
+  if(session_info->lifetime == 0) {
+    session_info->lifetime = LWM2M_DEFAULT_CLIENT_LIFETIME;
+  }
+#endif /* LWM2M_QUEUE_MODE_CONF_ENABLED */
+
+  session_info->rd_flags = FLAG_RD_DATA_UPDATE_ON_DIRTY;
+  session_info->has_bs_server_info = 0;
+  session_info->has_registration_server_info = 0;
+  session_info->wait_until_network_check = 0;
+  session_info->last_update = 0;
+  session_info->last_rd_progress = 0;
+  session_info->bootstrapped = 0;
+  session_info->rd_state = INIT;
+
+  if(server_type == LWM2M_RD_CLIENT_BOOTSTRAP_SERVER) {
+    coap_endpoint_copy(&session_info->bs_server_ep, server);
+    session_info->has_bs_server_info = 1;
+    session_info->use_server_type = LWM2M_RD_CLIENT_BOOTSTRAP_SERVER;
+  } else {
+    coap_endpoint_copy(&session_info->server_ep, server);
+    session_info->use_server_type = LWM2M_RD_CLIENT_LWM2M_SERVER;
+    session_info->has_registration_server_info = 1;
+  }
+
+  list_add(session_info_list, session_info); /* Add to the list of sessions */
 }
 /*---------------------------------------------------------------------------*/
 int
-lwm2m_rd_client_deregister(void)
+lwm2m_rd_client_deregister(lwm2m_session_info_t *session_info)
 {
-  if(lwm2m_rd_client_is_registered()) {
-    rd_state = DEREGISTER;
+  if(lwm2m_rd_client_is_registered(session_info)) {
+    session_info->rd_state = DEREGISTER;
     return 1;
   }
   /* Not registered */
   return 0;
 }
 /*---------------------------------------------------------------------------*/
-void
-lwm2m_rd_client_update_triggered(void)
+static lwm2m_session_info_t *
+get_session_info_from_server_ep(const coap_endpoint_t *server_ep)
 {
-  rd_flags |= FLAG_RD_DATA_UPDATE_TRIGGERED;
-  /* Here we need to do an CoAP timer poll - to get a quick request transmission! */
+  lwm2m_session_info_t *session_info = (lwm2m_session_info_t *)list_head(session_info_list);
+  while(session_info != NULL) {
+    if(coap_endpoint_cmp(&session_info->server_ep, server_ep)) {
+      return session_info;
+    }
+    session_info = session_info->next;
+  }
+  return NULL;
 }
 /*---------------------------------------------------------------------------*/
-static int
-update_bootstrap_server(void)
+void
+lwm2m_rd_client_update_triggered(const coap_endpoint_t *server_ep)
 {
-  if(session_info.has_bs_server_info) {
-    return 1;
+  lwm2m_session_info_t *session_info = get_session_info_from_server_ep(server_ep);
+  if(session_info) {
+    session_info->rd_flags |= FLAG_RD_DATA_UPDATE_TRIGGERED;
   }
-
-#if UIP_CONF_IPV6_RPL
-  {
-    rpl_dag_t *dag;
-
-    /* Use the DAG id as server address if no other has been specified */
-    dag = rpl_get_any_dag();
-    if(dag != NULL) {
-      /* create coap endpoint */
-      /* uip_ipaddr_copy(&bs_server_ipaddr, &dag->dag_id); */
-      /* bs_server_port = REMOTE_PORT; */
-      return 1;
-    }
-  }
-#endif /* UIP_CONF_IPV6_RPL */
-
-  return 0;
+  /* Here we need to do an CoAP timer poll - to get a quick request transmission! */
 }
 /*---------------------------------------------------------------------------*/
 /*
@@ -373,29 +349,32 @@ bootstrap_callback(coap_callback_request_state_t *callback_state)
 {
   coap_request_state_t *state = &callback_state->state;
   LOG_DBG("Bootstrap callback Response: %d, ", state->response != NULL);
+
+  lwm2m_session_info_t *session_info = (lwm2m_session_info_t *)state->user_data;
+
   if(state->status == COAP_REQUEST_STATUS_RESPONSE) {
     if(CHANGED_2_04 == state->response->code) {
       LOG_DBG_("Considered done!\n");
-      rd_state = BOOTSTRAP_DONE;
+      session_info->rd_state = BOOTSTRAP_DONE;
       return;
     }
     /* Possible error response codes are 4.00 Bad request & 4.15 Unsupported content format */
     LOG_DBG_("Failed with code %d. Retrying\n", state->response->code);
     /* TODO Application callback? */
-    rd_state = INIT;
-  } else if(state->status == COAP_REQUEST_STATUS_TIMEOUT) { 
+    session_info->rd_state = INIT;
+  } else if(state->status == COAP_REQUEST_STATUS_TIMEOUT) {
     LOG_DBG_("Server not responding! Retry?");
-    rd_state = DO_BOOTSTRAP;
+    session_info->rd_state = DO_BOOTSTRAP;
   } else if(state->status == COAP_REQUEST_STATUS_FINISHED) {
     LOG_DBG_("Request finished. Ignore\n");
   } else {
     LOG_DBG_("Unexpected error! Retry?");
-    rd_state = DO_BOOTSTRAP;
+    session_info->rd_state = DO_BOOTSTRAP;
   }
 }
 /*---------------------------------------------------------------------------*/
 static void
-produce_more_rd(void)
+produce_more_rd(lwm2m_session_info_t *session_info)
 {
   lwm2m_buffer_t outbuf;
 
@@ -406,23 +385,23 @@ produce_more_rd(void)
   outbuf.size = sizeof(rd_data);
   outbuf.len = 0;
 
-  rd_block1++;
+  session_info->rd_block1++;
 
   /* this will also set the request payload */
-  rd_more = lwm2m_engine_set_rd_data(&outbuf, rd_block1);
-  coap_set_payload(request, rd_data, outbuf.len);
+  session_info->rd_more = lwm2m_engine_set_rd_data(&outbuf, session_info->rd_block1);
+  coap_set_payload(session_info->request, rd_data, outbuf.len);
 
   LOG_DBG("Setting block1 in request - block: %d more: %d\n",
-          (int)rd_block1, (int)rd_more);
-  coap_set_header_block1(request, rd_block1, rd_more, sizeof(rd_data));
+          (int)session_info->rd_block1, (int)session_info->rd_more);
+  coap_set_header_block1(session_info->request, session_info->rd_block1, session_info->rd_more, sizeof(rd_data));
 
-  coap_send_request(&rd_request_state, &session_info.server_ep, request, rd_callback);
+  coap_send_request(&session_info->rd_request_state, &session_info->server_ep, session_info->request, session_info->rd_callback);
 }
 /*---------------------------------------------------------------------------*/
 static void
 block1_rd_callback(coap_timer_t *timer)
 {
-  produce_more_rd();
+  produce_more_rd((lwm2m_session_info_t *)timer->user_data);
 }
 /*---------------------------------------------------------------------------*/
 /*
@@ -433,20 +412,24 @@ registration_callback(coap_callback_request_state_t *callback_state)
 {
   coap_request_state_t *state = &callback_state->state;
   LOG_DBG("Registration callback. Status: %d. Response: %d, ", state->status, state->response != NULL);
+  lwm2m_session_info_t *session_info = (lwm2m_session_info_t *)state->user_data;
+
   if(state->status == COAP_REQUEST_STATUS_RESPONSE) {
     /* check state and possibly set registration to done */
     /* If we get a continue - we need to call the rd generator one more time */
+
     if(CONTINUE_2_31 == state->response->code) {
       /* We assume that size never change?! */
-      coap_get_header_block1(state->response, &rd_block1, NULL, NULL, NULL);
-      coap_timer_set_callback(&block1_timer, block1_rd_callback);
-      coap_timer_set(&block1_timer, 1); /* delay 1 ms */
+      coap_get_header_block1(state->response, &session_info->rd_block1, NULL, NULL, NULL);
+      coap_timer_set_user_data(&session_info->block1_timer, (void *)session_info);
+      coap_timer_set_callback(&session_info->block1_timer, block1_rd_callback);
+      coap_timer_set(&session_info->block1_timer, 1); /* delay 1 ms */
       LOG_DBG_("Continue\n");
     } else if(CREATED_2_01 == state->response->code) {
       if(state->response->location_path_len < LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN) {
-        memcpy(session_info.assigned_ep, state->response->location_path,
+        memcpy(session_info->assigned_ep, state->response->location_path,
                state->response->location_path_len);
-        session_info.assigned_ep[state->response->location_path_len] = 0;
+        session_info->assigned_ep[state->response->location_path_len] = 0;
         /* if we decide to not pass the lt-argument on registration, we should force an initial "update" to register lifetime with server */
 #if LWM2M_QUEUE_MODE_ENABLED
 #if LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION
@@ -454,14 +437,14 @@ registration_callback(coap_callback_request_state_t *callback_state)
           lwm2m_queue_mode_set_first_request();
         }
 #endif
-        lwm2m_rd_client_fsm_execute_queue_mode_awake(); /* Avoid 500 ms delay and move directly to the state*/
+        lwm2m_rd_client_fsm_execute_queue_mode_awake(session_info); /* Avoid 500 ms delay and move directly to the state*/
 #else
-        rd_state = REGISTRATION_DONE;
+        session_info->rd_state = REGISTRATION_DONE;
 #endif
         /* remember the last reg time */
-        last_update = coap_timer_uptime();
-        LOG_DBG_("Done (assigned EP='%s')!\n", session_info.assigned_ep);
-        perform_session_callback(LWM2M_RD_CLIENT_REGISTERED);
+        session_info->last_update = coap_timer_uptime();
+        LOG_DBG_("Done (assigned EP='%s')!\n", session_info->assigned_ep);
+        perform_session_callback(session_info, LWM2M_RD_CLIENT_REGISTERED);
         return;
       }
 
@@ -474,15 +457,15 @@ registration_callback(coap_callback_request_state_t *callback_state)
       LOG_DBG_("failed with code %d. Re-init network\n", state->response->code);
     }
     /* TODO Application callback? */
-    rd_state = INIT;
+    session_info->rd_state = INIT;
   } else if(state->status == COAP_REQUEST_STATUS_TIMEOUT) {
     LOG_DBG_("Server not responding, trying to reconnect\n");
-    rd_state = INIT;
-  } else if(state->status == COAP_REQUEST_STATUS_FINISHED){
+    session_info->rd_state = INIT;
+  } else if(state->status == COAP_REQUEST_STATUS_FINISHED) {
     LOG_DBG_("Request finished. Ignore\n");
   } else {
     LOG_DBG_("Unexpected error, trying to reconnect\n");
-    rd_state = INIT;
+    session_info->rd_state = INIT;
   }
 }
 /*---------------------------------------------------------------------------*/
@@ -495,18 +478,20 @@ update_callback(coap_callback_request_state_t *callback_state)
   coap_request_state_t *state = &callback_state->state;
   LOG_DBG("Update callback. Status: %d. Response: %d, ", state->status, state->response != NULL);
 
+  lwm2m_session_info_t *session_info = (lwm2m_session_info_t *)state->user_data;
+
   if(state->status == COAP_REQUEST_STATUS_RESPONSE) {
     /* If we get a continue - we need to call the rd generator one more time */
     if(CONTINUE_2_31 == state->response->code) {
       /* We assume that size never change?! */
       LOG_DBG_("Continue\n");
-      coap_get_header_block1(state->response, &rd_block1, NULL, NULL, NULL);
-      coap_timer_set_callback(&block1_timer, block1_rd_callback);
-      coap_timer_set(&block1_timer, 1); /* delay 1 ms */
+      coap_get_header_block1(state->response, &session_info->rd_block1, NULL, NULL, NULL);
+      coap_timer_set_callback(&session_info->block1_timer, block1_rd_callback);
+      coap_timer_set(&session_info->block1_timer, 1); /* delay 1 ms */
     } else if(CHANGED_2_04 == state->response->code) {
       LOG_DBG_("Done!\n");
       /* remember the last reg time */
-      last_update = coap_timer_uptime();
+      session_info->last_update = coap_timer_uptime();
 #if LWM2M_QUEUE_MODE_ENABLED
       /* If it has been waked up by a notification, send the stored notifications in queue */
       if(lwm2m_queue_mode_is_waked_up_by_notification()) {
@@ -519,25 +504,26 @@ update_callback(coap_callback_request_state_t *callback_state)
         lwm2m_queue_mode_set_first_request();
       }
 #endif /* LWM2M_QUEUE_MODE_INCLUDE_DYNAMIC_ADAPTATION */
-      lwm2m_rd_client_fsm_execute_queue_mode_awake(); /* Avoid 500 ms delay and move directly to the state*/
+      lwm2m_rd_client_fsm_execute_queue_mode_awake(session_info); /* Avoid 500 ms delay and move directly to the state*/
 #else
-      rd_state = REGISTRATION_DONE;
-      rd_flags &= ~FLAG_RD_DATA_UPDATE_TRIGGERED;
-#endif /* LWM2M_QUEUE_MODE_ENABLED */
+
+      session_info->rd_state = REGISTRATION_DONE;
+      session_info->rd_flags &= ~FLAG_RD_DATA_UPDATE_TRIGGERED;
+#endif /* LWM2M_QUEUE_MODE_DEFAULT_CLIENT_SLEEP_TIME */
     } else {
       /* Possible error response codes are 4.00 Bad request & 4.04 Not Found */
       LOG_DBG_("Failed with code %d. Retrying registration\n",
                state->response->code);
-      rd_state = DO_REGISTRATION;
+      session_info->rd_state = DO_REGISTRATION;
     }
   } else if(state->status == COAP_REQUEST_STATUS_TIMEOUT) {
     LOG_DBG_("Server not responding, trying to reconnect\n");
-    rd_state = INIT;
-  } else if(state->status == COAP_REQUEST_STATUS_FINISHED){
+    session_info->rd_state = INIT;
+  } else if(state->status == COAP_REQUEST_STATUS_FINISHED) {
     LOG_DBG_("Request finished. Ignore\n");
   } else {
     LOG_DBG_("Unexpected error, trying to reconnect\n");
-    rd_state = INIT;
+    session_info->rd_state = INIT;
   }
 }
 /*---------------------------------------------------------------------------*/
@@ -549,19 +535,49 @@ deregister_callback(coap_callback_request_state_t *callback_state)
           state->status,
           state->response != NULL ? state->response->code : 0);
 
+  lwm2m_session_info_t *session_info = (lwm2m_session_info_t *)state->user_data;
+
   if(state->status == COAP_REQUEST_STATUS_RESPONSE && (DELETED_2_02 == state->response->code)) {
     LOG_DBG("Deregistration success\n");
-    rd_state = DEREGISTERED;
-    perform_session_callback(LWM2M_RD_CLIENT_DEREGISTERED);
+    session_info->rd_state = DEREGISTERED;
+    perform_session_callback(session_info, LWM2M_RD_CLIENT_DEREGISTERED);
   } else {
     LOG_DBG("Deregistration failed\n");
-    if(rd_state == DEREGISTER_SENT) {
-      rd_state = DEREGISTER_FAILED;
-      perform_session_callback(LWM2M_RD_CLIENT_DEREGISTER_FAILED);
+    if(session_info->rd_state == DEREGISTER_SENT) {
+      session_info->rd_state = DEREGISTER_FAILED;
+      perform_session_callback(session_info, LWM2M_RD_CLIENT_DEREGISTER_FAILED);
     }
   }
 }
 /*---------------------------------------------------------------------------*/
+#if LWM2M_QUEUE_MODE_ENABLED
+static int
+all_sessions_in_queue_mode_state(void)
+{
+  lwm2m_session_info_t *session_info = (lwm2m_session_info_t *)list_head(session_info_list);
+  while(session_info != NULL) {
+    if(((session_info->rd_state & 0xF) != 0xE)) {
+      return 0;
+    }
+    session_info = session_info->next;
+  }
+  return 1;
+}
+/*---------------------------------------------------------------------------*/
+static int
+all_sessions_in_queue_mode_awake(void)
+{
+  lwm2m_session_info_t *session_info = (lwm2m_session_info_t *)list_head(session_info_list);
+  while(session_info != NULL) {
+    if(session_info->rd_state != QUEUE_MODE_AWAKE) {
+      return 0;
+    }
+    session_info = session_info->next;
+  }
+  return 1;
+}
+#endif /* LWM2M_QUEUE_MODE_ENABLED */
+/*---------------------------------------------------------------------------*/
 /* CoAP timer callback */
 static void
 periodic_process(coap_timer_t *timer)
@@ -571,7 +587,7 @@ periodic_process(coap_timer_t *timer)
   /* reschedule the CoAP timer */
 #if LWM2M_QUEUE_MODE_ENABLED
   /* In Queue Mode, the machine is not executed periodically, but with the awake/sleeping times */
-  if(!((rd_state & 0xF) == 0xE)) {
+  if(!all_sessions_in_queue_mode_state()) {
     coap_timer_reset(&rd_timer, STATE_MACHINE_UPDATE_INTERVAL);
   }
 #else
@@ -580,233 +596,243 @@ periodic_process(coap_timer_t *timer)
 
   now = coap_timer_uptime();
 
-  LOG_DBG("RD Client - state: %d, ms: %lu\n", rd_state,
-          (unsigned long)coap_timer_uptime());
-
-  switch(rd_state) {
-  case INIT:
-    LOG_DBG("RD Client started with endpoint '%s' and client lifetime %d\n", session_info.ep, session_info.lifetime);
-    rd_state = WAIT_NETWORK;
-    break;
-  case WAIT_NETWORK:
-    if(now > wait_until_network_check) {
-      /* check each 10 seconds before next check */
-      LOG_DBG("Checking for network... %lu\n",
-              (unsigned long)wait_until_network_check);
-      wait_until_network_check = now + 10000;
-      if(has_network_access()) {
-        /* Either do bootstrap then registration */
-        if(session_info.use_bootstrap) {
-          rd_state = DO_BOOTSTRAP;
-        } else {
-          rd_state = DO_REGISTRATION;
+  lwm2m_session_info_t *session_info = (lwm2m_session_info_t *)list_head(session_info_list);
+  while(session_info != NULL) {
+
+    LOG_DBG("RD Client with assigned ep: %s - state: %d, ms: %lu\n", session_info->assigned_ep, session_info->rd_state,
+            (unsigned long)coap_timer_uptime());
+
+    switch(session_info->rd_state) {
+    case INIT:
+      LOG_DBG("RD Client started with endpoint '%s' and client lifetime %d\n", session_info->ep, session_info->lifetime);
+      session_info->rd_state = WAIT_NETWORK;
+      break;
+    case WAIT_NETWORK:
+      if(now > session_info->wait_until_network_check) {
+        /* check each 10 seconds before next check */
+        LOG_DBG("Checking for network... %lu\n",
+                (unsigned long)session_info->wait_until_network_check);
+        session_info->wait_until_network_check = now + 10000;
+        if(has_network_access()) {
+          /* Either do bootstrap then registration */
+          if(session_info->use_server_type == LWM2M_RD_CLIENT_BOOTSTRAP_SERVER) {
+            session_info->rd_state = DO_BOOTSTRAP;
+          } else {
+            session_info->rd_state = DO_REGISTRATION;
+          }
         }
+        /* Otherwise wait until for a network to join */
       }
-      /* Otherwise wait until for a network to join */
-    }
-    break;
-  case DO_BOOTSTRAP:
-    if(session_info.use_bootstrap && session_info.bootstrapped == 0) {
-      if(update_bootstrap_server()) {
+      break;
+    case DO_BOOTSTRAP:
+      if(session_info->use_server_type == LWM2M_RD_CLIENT_BOOTSTRAP_SERVER &&
+         session_info->bootstrapped == 0 &&
+         session_info->has_bs_server_info) {
+
         /* prepare request, TID is set by COAP_BLOCKING_REQUEST() */
-        coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0);
-        coap_set_header_uri_path(request, "/bs");
+        coap_init_message(session_info->request, COAP_TYPE_CON, COAP_POST, 0);
+        coap_set_header_uri_path(session_info->request, "/bs");
 
-        snprintf(query_data, sizeof(query_data) - 1, "?ep=%s", session_info.ep);
-        coap_set_header_uri_query(request, query_data);
+        snprintf(query_data, sizeof(query_data) - 1, "?ep=%s", session_info->ep);
+        coap_set_header_uri_query(session_info->request, query_data);
         LOG_INFO("Registering ID with bootstrap server [");
-        LOG_INFO_COAP_EP(&session_info.bs_server_ep);
+        LOG_INFO_COAP_EP(&session_info->bs_server_ep);
         LOG_INFO_("] as '%s'\n", query_data);
-
-        if(coap_send_request(&rd_request_state, &session_info.bs_server_ep,
-                          request, bootstrap_callback)) {
-          rd_state = BOOTSTRAP_SENT;
+        /* Add session info as user data to use it in the callbacks */
+        session_info->rd_request_state.state.user_data = (void *)session_info;
+        if(coap_send_request(&session_info->rd_request_state, &session_info->bs_server_ep,
+                             session_info->request, bootstrap_callback)) {
+          session_info->rd_state = BOOTSTRAP_SENT;
         }
       }
-    }
-    break;
-  case BOOTSTRAP_SENT:
-    /* Just wait for bootstrap to be done...  */
-    break;
-  case BOOTSTRAP_DONE:
-    /* check that we should still use bootstrap */
-    if(session_info.use_bootstrap) {
-      lwm2m_security_server_t *security;
-      LOG_DBG("*** Bootstrap - checking for server info...\n");
-      /* get the security object - ignore bootstrap servers */
-      for(security = lwm2m_security_get_first();
-          security != NULL;
-          security = lwm2m_security_get_next(security)) {
-        if(security->bootstrap == 0) {
-          break;
+      break;
+    case BOOTSTRAP_SENT:
+      /* Just wait for bootstrap to be done...  */
+      break;
+    case BOOTSTRAP_DONE:
+      /* check that we should still use bootstrap */
+      if(session_info->use_server_type == LWM2M_RD_CLIENT_BOOTSTRAP_SERVER) {
+        lwm2m_security_server_t *security;
+        LOG_DBG("*** Bootstrap - checking for server info...\n");
+        /* get the security object - ignore bootstrap servers */
+        for(security = lwm2m_security_get_first();
+            security != NULL;
+            security = lwm2m_security_get_next(security)) {
+          if(security->bootstrap == 0) {
+            break;
+          }
         }
-      }
 
-      if(security != NULL) {
-        /* get the server URI */
-        if(security->server_uri_len > 0) {
-          uint8_t secure = 0;
-
-          LOG_DBG("**** Found security instance using: ");
-          LOG_DBG_COAP_STRING((const char *)security->server_uri,
-                              security->server_uri_len);
-          LOG_DBG_(" (len %d) \n", security->server_uri_len);
-          /* TODO Should verify it is a URI */
-          /* Check if secure */
-          secure = strncmp((const char *)security->server_uri,
-                           "coaps:", 6) == 0;
-
-          if(!coap_endpoint_parse((const char *)security->server_uri,
-                                  security->server_uri_len,
-                                  &session_info.server_ep)) {
-            LOG_DBG("Failed to parse server URI!\n");
-          } else {
-            LOG_DBG("Server address:");
-            LOG_DBG_COAP_EP(&session_info.server_ep);
-            LOG_DBG_("\n");
-            if(secure) {
-              LOG_DBG("Secure CoAP requested but not supported - can not bootstrap\n");
+        if(security != NULL) {
+          /* get the server URI */
+          if(security->server_uri_len > 0) {
+            uint8_t secure = 0;
+
+            LOG_DBG("**** Found security instance using: ");
+            LOG_DBG_COAP_STRING((const char *)security->server_uri,
+                                security->server_uri_len);
+            LOG_DBG_(" (len %d) \n", security->server_uri_len);
+            /* TODO Should verify it is a URI */
+            /* Check if secure */
+            secure = strncmp((const char *)security->server_uri,
+                             "coaps:", 6) == 0;
+
+            if(!coap_endpoint_parse((const char *)security->server_uri,
+                                    security->server_uri_len,
+                                    &session_info->server_ep)) {
+              LOG_DBG("Failed to parse server URI!\n");
             } else {
-              lwm2m_rd_client_register_with_server(&session_info.server_ep);
-              session_info.bootstrapped++;
+              LOG_DBG("Server address:");
+              LOG_DBG_COAP_EP(&session_info->server_ep);
+              LOG_DBG_("\n");
+              if(secure) {
+                LOG_DBG("Secure CoAP requested but not supported - can not bootstrap\n");
+              } else {
+                lwm2m_rd_client_register_with_server(session_info, &session_info->server_ep, LWM2M_RD_CLIENT_LWM2M_SERVER);
+                session_info->bootstrapped++;
+              }
             }
+          } else {
+            LOG_DBG("** failed to parse URI ");
+            LOG_DBG_COAP_STRING((const char *)security->server_uri,
+                                security->server_uri_len);
+            LOG_DBG_("\n");
           }
+        }
+
+        /* if we did not register above - then fail this and restart... */
+        if(session_info->bootstrapped == 0) {
+          /* Not ready. Lets retry with the bootstrap server again */
+          session_info->rd_state = DO_BOOTSTRAP;
         } else {
-          LOG_DBG("** failed to parse URI ");
-          LOG_DBG_COAP_STRING((const char *)security->server_uri,
-                              security->server_uri_len);
-          LOG_DBG_("\n");
+          session_info->rd_state = DO_REGISTRATION;
         }
       }
-
-      /* if we did not register above - then fail this and restart... */
-      if(session_info.bootstrapped == 0) {
-        /* Not ready. Lets retry with the bootstrap server again */
-        rd_state = DO_BOOTSTRAP;
-      } else {
-        rd_state = DO_REGISTRATION;
+      break;
+    case DO_REGISTRATION:
+      if(!coap_endpoint_is_connected(&session_info->server_ep)) {
+        /* Not connected... wait a bit... and retry connection */
+        coap_endpoint_connect(&session_info->server_ep);
+        LOG_DBG("Wait until connected... \n");
+        return;
       }
-    }
-    break;
-  case DO_REGISTRATION:
-    if(!coap_endpoint_is_connected(&session_info.server_ep)) {
-      /* Not connected... wait a bit... and retry connection */
-      coap_endpoint_connect(&session_info.server_ep);
-      LOG_DBG("Wait until connected... \n");
-      return;
-    }
-    if(session_info.use_registration && !session_info.registered &&
-       update_registration_server()) {
-      int len;
 
-      /* prepare request, TID was set by COAP_BLOCKING_REQUEST() */
-      coap_init_message(request, COAP_TYPE_CON, COAP_POST, 0);
-      coap_set_header_uri_path(request, "/rd");
+      if(session_info->use_server_type == LWM2M_RD_CLIENT_LWM2M_SERVER &&
+         !lwm2m_rd_client_is_registered(session_info) &&
+         session_info->has_registration_server_info) {
+        int len;
 
-      snprintf(query_data, sizeof(query_data) - 1, "?ep=%s&lt=%d&b=%s", session_info.ep, session_info.lifetime, session_info.binding);
-      coap_set_header_uri_query(request, query_data);
+        /* prepare request, TID was set by COAP_BLOCKING_REQUEST() */
+        coap_init_message(session_info->request, COAP_TYPE_CON, COAP_POST, 0);
+        coap_set_header_uri_path(session_info->request, "/rd");
 
-      len = set_rd_data(request);
-      rd_callback = registration_callback;
+        snprintf(query_data, sizeof(query_data) - 1, "?ep=%s&lt=%d&b=%s", session_info->ep, session_info->lifetime, session_info->binding);
+        coap_set_header_uri_query(session_info->request, query_data);
 
-      LOG_INFO("Registering with [");
-      LOG_INFO_COAP_EP(&session_info.server_ep);
-      LOG_INFO_("] lwm2m endpoint '%s': '", query_data);
-      if(len) {
-        LOG_INFO_COAP_STRING((const char *)rd_data, len);
-      }
-      LOG_INFO_("' More:%d\n", rd_more);
+        len = set_rd_data(session_info);
+        session_info->rd_callback = registration_callback;
+
+        LOG_INFO("Registering with [");
+        LOG_INFO_COAP_EP(&session_info->server_ep);
+        LOG_INFO_("] lwm2m endpoint '%s': '", query_data);
+        if(len) {
+          LOG_INFO_COAP_STRING((const char *)rd_data, len);
+        }
+        LOG_INFO_("' More:%d\n", session_info->rd_more);
+
+        /* Add session info as user data to use it in the callbacks */
+        session_info->rd_request_state.state.user_data = (void *)session_info;
+        if(coap_send_request(&session_info->rd_request_state, &session_info->server_ep,
+                             session_info->request, registration_callback)) {
 
-      if(coap_send_request(&rd_request_state, &session_info.server_ep,
-                        request, registration_callback)){
-        rd_state = REGISTRATION_SENT;
+          session_info->rd_state = REGISTRATION_SENT;
+        }
+        session_info->last_rd_progress = coap_timer_uptime();
       }
-    }
-    break;
-  case REGISTRATION_SENT:
-    /* just wait until the callback kicks us to the next state... */
-    break;
-  case REGISTRATION_DONE:
-    /* All is done! */
-
-    check_periodic_observations(); /* TODO: manage periodic observations */
-
-    /* check if it is time for the next update */
-    if((rd_flags & FLAG_RD_DATA_UPDATE_TRIGGERED) ||
-       ((uint32_t)session_info.lifetime * 500) <= now - last_update) {
-      /* triggered or time to send an update to the server, at half-time! sec vs ms */
-      prepare_update(request, rd_flags & FLAG_RD_DATA_UPDATE_TRIGGERED);
-      if(coap_send_request(&rd_request_state, &session_info.server_ep, request,
-                        update_callback)) {
-        rd_state = UPDATE_SENT;
+      break;
+    case REGISTRATION_SENT:
+      /* just wait until the callback kicks us to the next state... */
+      break;
+    case REGISTRATION_DONE:
+      /* All is done! */
+
+      check_periodic_observations(); /* TODO: manage periodic observations */
+
+      /* check if it is time for the next update */
+      if((session_info->rd_flags & FLAG_RD_DATA_UPDATE_TRIGGERED) ||
+         ((uint32_t)session_info->lifetime * 500) <= now - session_info->last_update) {
+        /* triggered or time to send an update to the server, at half-time! sec vs ms */
+        prepare_update(session_info, session_info->rd_flags & FLAG_RD_DATA_UPDATE_TRIGGERED);
+
+        /* Add session info as user data to use it in the callbacks */
+        session_info->rd_request_state.state.user_data = (void *)session_info;
+        if(coap_send_request(&session_info->rd_request_state, &session_info->server_ep, session_info->request,
+                             update_callback)) {
+          session_info->rd_state = UPDATE_SENT;
+        }
+        session_info->last_rd_progress = coap_timer_uptime();
       }
-    }
-    break;
+      break;
+
 #if LWM2M_QUEUE_MODE_ENABLED
-  case QUEUE_MODE_AWAKE:
-    LOG_DBG("Queue Mode: Client is AWAKE at %lu\n", (unsigned long)coap_timer_uptime());
-    queue_mode_client_awake = 1;
-    queue_mode_client_awake_time = lwm2m_queue_mode_get_awake_time();
-    coap_timer_set(&queue_mode_client_awake_timer, queue_mode_client_awake_time);
-    break;
-  case QUEUE_MODE_SEND_UPDATE:
-/* Define this macro to make the necessary actions for waking up, 
- * depending on the platform 
- */
+    case QUEUE_MODE_AWAKE:
+      LOG_DBG("Queue Mode: Client is AWAKE at %lu\n", (unsigned long)coap_timer_uptime());
+      if((queue_mode_client_awake = all_sessions_in_queue_mode_awake())) {
+        queue_mode_client_awake_time = lwm2m_queue_mode_get_awake_time();
+        coap_timer_set(&queue_mode_client_awake_timer, queue_mode_client_awake_time);
+      }
+      break;
+    case QUEUE_MODE_SEND_UPDATE:
+      /* Define this macro to make the necessary actions for waking up,
+       * depending on the platform
+       */
 #ifdef LWM2M_QUEUE_MODE_WAKE_UP
-    LWM2M_QUEUE_MODE_WAKE_UP();
+      LWM2M_QUEUE_MODE_WAKE_UP();
 #endif /* LWM2M_QUEUE_MODE_WAKE_UP */
-    prepare_update(request, rd_flags & FLAG_RD_DATA_UPDATE_TRIGGERED);
-    if(coap_send_request(&rd_request_state, &session_info.server_ep, request,
-                      update_callback)) {
-      rd_state = UPDATE_SENT;
-    }
-    break;
+      prepare_update(session_info, session_info->rd_flags & FLAG_RD_DATA_UPDATE_TRIGGERED);
+      /* Add session info as user data to use it in the callbacks */
+      session_info->rd_request_state.state.user_data = (void *)session_info;
+      if(coap_send_request(&session_info->rd_request_state, &session_info->server_ep, session_info->request,
+                           update_callback)) {
+        session_info->rd_state = UPDATE_SENT;
+      }
+      session_info->last_rd_progress = coap_timer_uptime();
+      break;
 #endif /* LWM2M_QUEUE_MODE_ENABLED */
 
-  case UPDATE_SENT:
-    /* just wait until the callback kicks us to the next state... */
-    break;
-  case DEREGISTER:
-    LOG_INFO("DEREGISTER %s\n", session_info.assigned_ep);
-    coap_init_message(request, COAP_TYPE_CON, COAP_DELETE, 0);
-    coap_set_header_uri_path(request, session_info.assigned_ep);
-    if(coap_send_request(&rd_request_state, &session_info.server_ep, request,
-                      deregister_callback)) {
-      rd_state = DEREGISTER_SENT;
+    case UPDATE_SENT:
+      /* just wait until the callback kicks us to the next state... */
+      break;
+    case DEREGISTER:
+      LOG_INFO("DEREGISTER %s\n", session_info->assigned_ep);
+      coap_init_message(session_info->request, COAP_TYPE_CON, COAP_DELETE, 0);
+      coap_set_header_uri_path(session_info->request, session_info->assigned_ep);
+
+      /* Add session info as user data to use it in the callbacks */
+      session_info->rd_request_state.state.user_data = (void *)session_info;
+      if(coap_send_request(&session_info->rd_request_state, &session_info->server_ep, session_info->request,
+                           deregister_callback)) {
+        session_info->rd_state = DEREGISTER_SENT;
+      }
+      break;
+    case DEREGISTER_SENT:
+      break;
+    case DEREGISTER_FAILED:
+      break;
+    case DEREGISTERED:
+      break;
+
+    default:
+      LOG_WARN("Unhandled state: %d\n", session_info->rd_state);
     }
-    break;
-  case DEREGISTER_SENT:
-    break;
-  case DEREGISTER_FAILED:
-    break;
-  case DEREGISTERED:
-    break;
-
-  default:
-    LOG_WARN("Unhandled state: %d\n", rd_state);
+    session_info = session_info->next;
   }
 }
 /*---------------------------------------------------------------------------*/
 void
 lwm2m_rd_client_init(const char *ep)
 {
-  session_info.ep = ep;
-  /* default binding U = UDP, UQ = UDP Q-mode*/
-#if LWM2M_QUEUE_MODE_ENABLED
-  session_info.binding = "UQ";
-  /* Enough margin to ensure that the client is not unregistered (we
-   * do not know the time it can stay awake)
-   */
-  session_info.lifetime = (LWM2M_QUEUE_MODE_DEFAULT_CLIENT_SLEEP_TIME / 1000) * 2; 
-#else
-  session_info.binding = "U";
-  if(session_info.lifetime == 0) {
-    session_info.lifetime = LWM2M_DEFAULT_CLIENT_LIFETIME;
-  }
-#endif
-
-  rd_state = INIT;
+  lwm2m_rd_client_set_default_endpoint_name(ep);
 
   /* call the RD client periodically */
   coap_timer_set_callback(&rd_timer, periodic_process);
@@ -823,7 +849,7 @@ check_periodic_observations(void)
 }
 /*---------------------------------------------------------------------------*/
 /*
-   *Queue Mode Support
+ * Queue Mode Support
  */
 #if LWM2M_QUEUE_MODE_ENABLED
 /*---------------------------------------------------------------------------*/
@@ -846,27 +872,31 @@ queue_mode_awake_timer_callback(coap_timer_t *timer)
   LOG_DBG("Queue Mode: Client is SLEEPING at %lu\n", (unsigned long)coap_timer_uptime());
   queue_mode_client_awake = 0;
 
-/* Define this macro to enter sleep mode depending on the platform */
+  lwm2m_session_info_t *session_info = (lwm2m_session_info_t *)list_head(session_info_list);
+  while(session_info != NULL) {
+    session_info->rd_state = QUEUE_MODE_SEND_UPDATE;
+    session_info = session_info->next;
+  }
+  coap_timer_set(&rd_timer, lwm2m_queue_mode_get_sleep_time());
+  /* Define this macro to enter sleep mode depending on the platform */
 #ifdef LWM2M_QUEUE_MODE_SLEEP_MS
   LWM2M_QUEUE_MODE_SLEEP_MS(lwm2m_queue_mode_get_sleep_time());
 #endif /* LWM2M_QUEUE_MODE_SLEEP_MS */
-  rd_state = QUEUE_MODE_SEND_UPDATE;
-  coap_timer_set(&rd_timer, lwm2m_queue_mode_get_sleep_time());
 }
 /*---------------------------------------------------------------------------*/
 void
-lwm2m_rd_client_fsm_execute_queue_mode_awake()
+lwm2m_rd_client_fsm_execute_queue_mode_awake(lwm2m_session_info_t *session_info)
 {
   coap_timer_stop(&rd_timer);
-  rd_state = QUEUE_MODE_AWAKE;
+  session_info->rd_state = QUEUE_MODE_AWAKE;
   periodic_process(&rd_timer);
 }
 /*---------------------------------------------------------------------------*/
 void
-lwm2m_rd_client_fsm_execute_queue_mode_update()
+lwm2m_rd_client_fsm_execute_queue_mode_update(lwm2m_session_info_t *session_info)
 {
   coap_timer_stop(&rd_timer);
-  rd_state = QUEUE_MODE_SEND_UPDATE;
+  session_info->rd_state = QUEUE_MODE_SEND_UPDATE;
   periodic_process(&rd_timer);
 }
 /*---------------------------------------------------------------------------*/
diff --git a/os/services/lwm2m/lwm2m-rd-client.h b/os/services/lwm2m/lwm2m-rd-client.h
index cfc5c549d3ddf5baa0b225dc6de94679cc47d3c4..58fa0a8c20702424f5092c0ce094c0034ab547c9 100644
--- a/os/services/lwm2m/lwm2m-rd-client.h
+++ b/os/services/lwm2m/lwm2m-rd-client.h
@@ -46,6 +46,13 @@
 #ifndef LWM2M_RD_CLIENT_H_
 #define LWM2M_RD_CLIENT_H_
 
+/* The type of server to use for registration: bootstrap or LWM2M */
+typedef enum {
+  LWM2M_RD_CLIENT_BOOTSTRAP_SERVER,
+  LWM2M_RD_CLIENT_LWM2M_SERVER
+} lwm2m_rd_client_server_type_t;
+
+/* Session callback states */
 #define LWM2M_RD_CLIENT_BOOTSTRAPPED       1
 #define LWM2M_RD_CLIENT_REGISTERED         2
 #define LWM2M_RD_CLIENT_DEREGISTERED       3
@@ -54,58 +61,77 @@
 
 #include "lwm2m-object.h"
 #include "lwm2m-queue-mode-conf.h"
+#include "coap-endpoint.h"
+#include "coap-callback-api.h"
 
 struct lwm2m_session_info;
 typedef void (*session_callback_t)(struct lwm2m_session_info *session, int status);
 
-int  lwm2m_rd_client_is_registered(void);
-void lwm2m_rd_client_use_bootstrap_server(int use);
-void lwm2m_rd_client_use_registration_server(int use);
-void lwm2m_rd_client_register_with_server(const coap_endpoint_t *server);
-void lwm2m_rd_client_register_with_bootstrap_server(const coap_endpoint_t *server);
-uint16_t lwm2m_rd_client_get_lifetime(void);
-void lwm2m_rd_client_set_lifetime(uint16_t lifetime);
-/* Indicate that something in the object list have changed */
-void lwm2m_rd_client_set_update_rd(void);
-/* Control if the object list should be automatically updated at updates of lifetime */
-void lwm2m_rd_client_set_automatic_update(int update);
-/* trigger an immediate update */
-void lwm2m_rd_client_update_triggered(void);
-
-int  lwm2m_rd_client_deregister(void);
-void lwm2m_rd_client_init(const char *ep);
-
-void lwm2m_rd_client_set_session_callback(session_callback_t cb);
-
-#if LWM2M_QUEUE_MODE_ENABLED
-uint8_t lwm2m_rd_client_is_client_awake(void);
-void lwm2m_rd_client_restart_client_awake_timer(void);
-void lwm2m_rd_client_fsm_execute_queue_mode_awake();
-void lwm2m_rd_client_fsm_execute_queue_mode_update();
-#endif
-
 #ifndef LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN
 #define LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN    15
 #endif /* LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN */
-
 /*---------------------------------------------------------------------------*/
-/*- Server session-*Currently single session only*---------------------------*/
+/*- Server session----------------------------*/
 /*---------------------------------------------------------------------------*/
-struct lwm2m_session_info {
+typedef struct lwm2m_session_info {
+
+  struct lwm2m_session_info *next;
+  /* Information */
   const char *ep;
   const char *binding;
   char assigned_ep[LWM2M_RD_CLIENT_ASSIGNED_ENDPOINT_MAX_LEN];
   uint16_t lifetime;
   coap_endpoint_t bs_server_ep;
   coap_endpoint_t server_ep;
-  uint8_t use_bootstrap;
+  lwm2m_rd_client_server_type_t use_server_type;
   uint8_t has_bs_server_info;
-  uint8_t use_registration;
   uint8_t has_registration_server_info;
-  uint8_t registered;
   uint8_t bootstrapped; /* bootstrap done */
   session_callback_t callback;
-};
+
+  /* CoAP Request */
+  coap_callback_request_state_t rd_request_state;
+  coap_message_t request[1];      /* This way the message can be treated as pointer as usual. */
+
+  /* RD parameters */
+  uint8_t rd_state;
+  uint8_t rd_flags;
+  uint64_t wait_until_network_check;
+  uint64_t last_update;
+  uint64_t last_rd_progress;
+
+  /* Blosk Transfer */
+  uint32_t rd_block1;
+  uint8_t rd_more;
+  void (*rd_callback)(coap_callback_request_state_t *state);
+  coap_timer_t block1_timer;
+} lwm2m_session_info_t;
+
+int  lwm2m_rd_client_is_registered(lwm2m_session_info_t *session_info);
+void lwm2m_rd_client_register_with_server(lwm2m_session_info_t *session_info, const coap_endpoint_t *server, lwm2m_rd_client_server_type_t server_type);
+uint16_t lwm2m_rd_client_get_lifetime(lwm2m_session_info_t *session_info);
+void lwm2m_rd_client_set_lifetime(lwm2m_session_info_t *session_info, uint16_t lifetime);
+void lwm2m_rd_client_set_endpoint_name(lwm2m_session_info_t *session_info, const char *endpoint);
+void lwm2m_rd_client_set_default_endpoint_name(const char *endpoint);
+
+/* Indicate that something in the object list have changed */
+void lwm2m_rd_client_set_update_rd(void);
+/* Control if the object list should be automatically updated at updates of lifetime */
+void lwm2m_rd_client_set_automatic_update(lwm2m_session_info_t *session_info, int update);
+/* trigger an immediate update */
+void lwm2m_rd_client_update_triggered(const coap_endpoint_t *server_ep);
+
+int  lwm2m_rd_client_deregister(lwm2m_session_info_t *session_info);
+void lwm2m_rd_client_init(const char *ep);
+
+void lwm2m_rd_client_set_session_callback(lwm2m_session_info_t *session_info, session_callback_t cb);
+
+#if LWM2M_QUEUE_MODE_ENABLED
+uint8_t lwm2m_rd_client_is_client_awake(void);
+void lwm2m_rd_client_restart_client_awake_timer(void);
+void lwm2m_rd_client_fsm_execute_queue_mode_awake();
+void lwm2m_rd_client_fsm_execute_queue_mode_update();
+#endif
 
 #endif /* LWM2M_RD_CLIENT_H_ */
 /** @} */
diff --git a/os/services/lwm2m/lwm2m-server.c b/os/services/lwm2m/lwm2m-server.c
index bf0398b4f7e17f4bccad68cb6b4c2c6e72933653..b777d72d69efb1436bd0e17a165133eff73c7c1c 100644
--- a/os/services/lwm2m/lwm2m-server.c
+++ b/os/services/lwm2m/lwm2m-server.c
@@ -221,7 +221,7 @@ lwm2m_callback(lwm2m_object_instance_t *object,
   } else if(ctx->operation == LWM2M_OP_EXECUTE) {
     switch(ctx->resource_id) {
     case LWM2M_SERVER_REG_UPDATE_TRIGGER_ID:
-      lwm2m_rd_client_update_triggered();
+      lwm2m_rd_client_update_triggered(ctx->request->src_ep);
       break;
     }
   } else {
diff --git a/os/services/rpl-border-router/embedded/slip-bridge.c b/os/services/rpl-border-router/embedded/slip-bridge.c
index d1f97339db2c18816d772a4a395d998e52a0ae78..b1349ac0abd91d99799441d3ef6064bde0c40e17 100644
--- a/os/services/rpl-border-router/embedded/slip-bridge.c
+++ b/os/services/rpl-border-router/embedded/slip-bridge.c
@@ -43,8 +43,6 @@
 #include "dev/slip.h"
 #include <string.h>
 /*---------------------------------------------------------------------------*/
-#define UIP_IP_BUF        ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-/*---------------------------------------------------------------------------*/
 /* Log configuration */
 #include "sys/log.h"
 #define LOG_MODULE "SLIP"
@@ -63,34 +61,34 @@ request_prefix(void)
   uip_buf[1] = 'P';
   uip_len = 2;
   slip_write(uip_buf, uip_len);
-  uip_clear_buf();
+  uipbuf_clear();
 }
 /*---------------------------------------------------------------------------*/
 static void
 slip_input_callback(void)
 {
   LOG_DBG("SIN: %u\n", uip_len);
-  if(uip_buf[UIP_LLH_LEN] == '!') {
+  if(uip_buf[0] == '!') {
     LOG_INFO("Got configuration message of type %c\n",
-             uip_buf[UIP_LLH_LEN + 1]);
-    if(uip_buf[UIP_LLH_LEN + 1] == 'P') {
+             uip_buf[1]);
+    if(uip_buf[1] == 'P') {
       uip_ipaddr_t prefix;
       /* Here we set a prefix !!! */
       memset(&prefix, 0, 16);
-      memcpy(&prefix, &uip_buf[UIP_LLH_LEN + 2], 8);
+      memcpy(&prefix, &uip_buf[2], 8);
 
-      uip_clear_buf();
+      uipbuf_clear();
 
       LOG_INFO("Setting prefix ");
       LOG_INFO_6ADDR(&prefix);
       LOG_INFO_("\n");
       set_prefix_64(&prefix);
     }
-    uip_clear_buf();
+    uipbuf_clear();
 
-  } else if(uip_buf[UIP_LLH_LEN] == '?') {
-    LOG_INFO("Got request message of type %c\n", uip_buf[UIP_LLH_LEN + 1]);
-    if(uip_buf[UIP_LLH_LEN + 1] == 'M') {
+  } else if(uip_buf[0] == '?') {
+    LOG_INFO("Got request message of type %c\n", uip_buf[1]);
+    if(uip_buf[1] == 'M') {
       char *hexchar = "0123456789abcdef";
       int j;
       /* this is just a test so far... just to see if it works */
@@ -102,7 +100,7 @@ slip_input_callback(void)
       uip_len = 18;
       slip_write(uip_buf, uip_len);
     }
-    uip_clear_buf();
+    uipbuf_clear();
   } else {
     /* Save the last sender received over SLIP to avoid bouncing the
        packet back if no route is found */
diff --git a/os/services/rpl-border-router/native/border-router-mac.c b/os/services/rpl-border-router/native/border-router-mac.c
index fbf8b64960ee860f054e0036cd27f2204b393dcf..7fe4fc6ed7aea1d644287a272e560d7c7501e6e6 100644
--- a/os/services/rpl-border-router/native/border-router-mac.c
+++ b/os/services/rpl-border-router/native/border-router-mac.c
@@ -64,6 +64,20 @@ struct tx_callback {
 /*---------------------------------------------------------------------------*/
 static struct tx_callback callbacks[MAX_CALLBACKS];
 /*---------------------------------------------------------------------------*/
+void
+init_sec(void)
+{
+  /* use the CSMA LLSEC config parameter */
+#if LLSEC802154_USES_AUX_HEADER
+  if(packetbuf_attr(PACKETBUF_ATTR_SECURITY_LEVEL) ==
+     PACKETBUF_ATTR_SECURITY_LEVEL_DEFAULT) {
+    packetbuf_set_attr(PACKETBUF_ATTR_SECURITY_LEVEL,
+                       CSMA_LLSEC_SECURITY_LEVEL);
+  }
+#endif
+}
+/*---------------------------------------------------------------------------*/
+
 void
 packet_sent(uint8_t sessionid, uint8_t status, uint8_t tx)
 {
@@ -164,6 +178,13 @@ off()
   return 1;
 }
 /*---------------------------------------------------------------------------*/
+static int
+max_payload()
+{
+  init_sec();
+  return 127 - NETSTACK_FRAMER.length();
+}
+/*---------------------------------------------------------------------------*/
 static void
 init(void)
 {
@@ -176,6 +197,7 @@ const struct mac_driver border_router_mac_driver = {
   send_packet,
   packet_input,
   on,
-  off
+  off,
+  max_payload,
 };
 /*---------------------------------------------------------------------------*/
diff --git a/os/services/rpl-border-router/native/slip-config.c b/os/services/rpl-border-router/native/slip-config.c
index a8e17f22c735055576de09617e94343d35dffdad..7797a129f4e635b8530beea4725d4402ec7faf92 100644
--- a/os/services/rpl-border-router/native/slip-config.c
+++ b/os/services/rpl-border-router/native/slip-config.c
@@ -142,14 +142,20 @@ slip_config_handle_arguments(int argc, char **argv)
       fprintf(stderr, " -a host        Connect via TCP to server at <host>\n");
       fprintf(stderr, " -p port        Connect via TCP to server at <host>:<port>\n");
       fprintf(stderr, " -t tundev      Name of interface (default tun0)\n");
+#ifdef __APPLE__
+      fprintf(stderr, " -v level       Verbosity level\n");
+#else
       fprintf(stderr, " -v[level]      Verbosity level\n");
+#endif
       fprintf(stderr, "    -v0         No messages\n");
       fprintf(stderr, "    -v1         Encapsulated SLIP debug messages (default)\n");
       fprintf(stderr, "    -v2         Printable strings after they are received\n");
       fprintf(stderr, "    -v3         Printable strings and SLIP packet notifications\n");
       fprintf(stderr, "    -v4         All printable characters as they are received\n");
       fprintf(stderr, "    -v5         All SLIP packets in hex\n");
+#ifndef __APPLE__
       fprintf(stderr, "    -v          Equivalent to -v3\n");
+#endif
       fprintf(stderr, " -d[basedelay]  Minimum delay between outgoing SLIP packets.\n");
       fprintf(stderr, "                Actual delay is basedelay*(#6LowPAN fragments) milliseconds.\n");
       fprintf(stderr, "                -d is equivalent to -d10.\n");
diff --git a/os/services/rpl-border-router/native/tun-bridge.c b/os/services/rpl-border-router/native/tun-bridge.c
index 289a32185d4dd8eb0f5605251d0e7fd0972cce69..26bc80bd77f2ff6967089b00a68e5582dd30d010 100644
--- a/os/services/rpl-border-router/native/tun-bridge.c
+++ b/os/services/rpl-border-router/native/tun-bridge.c
@@ -256,7 +256,7 @@ output(void)
 {
   LOG_DBG("SUT: %u\n", uip_len);
   if(uip_len > 0) {
-    return tun_output(&uip_buf[UIP_LLH_LEN], uip_len);
+    return tun_output(uip_buf, uip_len);
   }
   return 0;
 }
@@ -298,7 +298,7 @@ handle_fd(fd_set *rset, fd_set *wset)
     int size;
 
     if(FD_ISSET(tunfd, rset)) {
-      size = tun_input(&uip_buf[UIP_LLH_LEN], sizeof(uip_buf));
+      size = tun_input(uip_buf, sizeof(uip_buf));
       /* printf("TUN data incoming read:%d\n", size); */
       uip_len = size;
       tcpip_input();
diff --git a/os/services/shell/Makefile.shell b/os/services/shell/Makefile.shell
deleted file mode 100644
index 9b95490182221bcdf362376138f4311348a541a0..0000000000000000000000000000000000000000
--- a/os/services/shell/Makefile.shell
+++ /dev/null
@@ -1 +0,0 @@
-CFLAGS += -DBUILD_WITH_SHELL=1
diff --git a/os/services/shell/module-macros.h b/os/services/shell/module-macros.h
new file mode 100644
index 0000000000000000000000000000000000000000..dc40e1196ad852aaacd7f4f9653613b83daf22a1
--- /dev/null
+++ b/os/services/shell/module-macros.h
@@ -0,0 +1 @@
+#define BUILD_WITH_SHELL 1
diff --git a/os/services/shell/shell-commands.c b/os/services/shell/shell-commands.c
index e8bb4b6b2b170b997e2fa7cf8ed8cef3199351a2..0a48f7ce9bd868a66ba5043ff5bc712b88b6d3ce 100644
--- a/os/services/shell/shell-commands.c
+++ b/os/services/shell/shell-commands.c
@@ -55,6 +55,9 @@
 #if MAC_CONF_WITH_TSCH
 #include "net/mac/tsch/tsch.h"
 #endif /* MAC_CONF_WITH_TSCH */
+#if MAC_CONF_WITH_CSMA
+#include "net/mac/csma/csma.h"
+#endif
 #include "net/routing/routing.h"
 #include "net/mac/llsec802154.h"
 
@@ -69,16 +72,19 @@
 
 #define PING_TIMEOUT (5 * CLOCK_SECOND)
 
+#if NETSTACK_CONF_WITH_IPV6
 static struct uip_icmp6_echo_reply_notification echo_reply_notification;
 static shell_output_func *curr_ping_output_func = NULL;
 static struct process *curr_ping_process;
 static uint8_t curr_ping_ttl;
 static uint16_t curr_ping_datalen;
+#endif /* NETSTACK_CONF_WITH_IPV6 */
 #if TSCH_WITH_SIXTOP
 static shell_command_6top_sub_cmd_t sixtop_sub_cmd = NULL;
 #endif /* TSCH_WITH_SIXTOP */
 static struct shell_command_set_t builtin_shell_command_set;
 LIST(shell_command_sets);
+#if NETSTACK_CONF_WITH_IPV6
 /*---------------------------------------------------------------------------*/
 static const char *
 ds6_nbr_state_to_str(uint8_t state)
@@ -98,6 +104,64 @@ ds6_nbr_state_to_str(uint8_t state)
       return "Unknown";
   }
 }
+/*---------------------------------------------------------------------------*/
+static void
+echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data, uint16_t datalen)
+{
+  if(curr_ping_output_func != NULL) {
+    curr_ping_output_func = NULL;
+    curr_ping_ttl = ttl;
+    curr_ping_datalen = datalen;
+    process_poll(curr_ping_process);
+  }
+}
+/*---------------------------------------------------------------------------*/
+static
+PT_THREAD(cmd_ping(struct pt *pt, shell_output_func output, char *args))
+{
+  static uip_ipaddr_t remote_addr;
+  static struct etimer timeout_timer;
+  char *next_args;
+
+  PT_BEGIN(pt);
+
+  SHELL_ARGS_INIT(args, next_args);
+
+  /* Get argument (remote IPv6) */
+  SHELL_ARGS_NEXT(args, next_args);
+  if(args == NULL) {
+    SHELL_OUTPUT(output, "Destination IPv6 address is not specified\n");
+    PT_EXIT(pt);
+  } else if(uiplib_ipaddrconv(args, &remote_addr) == 0) {
+    SHELL_OUTPUT(output, "Invalid IPv6 address: %s\n", args);
+    PT_EXIT(pt);
+  }
+
+  SHELL_OUTPUT(output, "Pinging ");
+  shell_output_6addr(output, &remote_addr);
+  SHELL_OUTPUT(output, "\n");
+
+  /* Send ping request */
+  curr_ping_process = PROCESS_CURRENT();
+  curr_ping_output_func = output;
+  etimer_set(&timeout_timer, PING_TIMEOUT);
+  uip_icmp6_send(&remote_addr, ICMP6_ECHO_REQUEST, 0, 4);
+  PT_WAIT_UNTIL(pt, curr_ping_output_func == NULL || etimer_expired(&timeout_timer));
+
+  if(curr_ping_output_func != NULL) {
+    SHELL_OUTPUT(output, "Timeout\n");
+    curr_ping_output_func = NULL;
+  } else {
+    SHELL_OUTPUT(output, "Received ping reply from ");
+    shell_output_6addr(output, &remote_addr);
+    SHELL_OUTPUT(output, ", len %u, ttl %u, delay %lu ms\n",
+      curr_ping_datalen, curr_ping_ttl, (1000*(clock_time() - timeout_timer.timer.start))/CLOCK_SECOND);
+  }
+
+  PT_END(pt);
+}
+#endif /* NETSTACK_CONF_WITH_IPV6 */
+
 #if ROUTING_CONF_RPL_LITE
 /*---------------------------------------------------------------------------*/
 static const char *
@@ -215,63 +279,18 @@ PT_THREAD(cmd_rpl_status(struct pt *pt, shell_output_func output, char *args))
 
   PT_END(pt);
 }
-#endif /* ROUTING_CONF_RPL_LITE */
-/*---------------------------------------------------------------------------*/
-static void
-echo_reply_handler(uip_ipaddr_t *source, uint8_t ttl, uint8_t *data, uint16_t datalen)
-{
-  if(curr_ping_output_func != NULL) {
-    curr_ping_output_func = NULL;
-    curr_ping_ttl = ttl;
-    curr_ping_datalen = datalen;
-    process_poll(curr_ping_process);
-  }
-}
 /*---------------------------------------------------------------------------*/
 static
-PT_THREAD(cmd_ping(struct pt *pt, shell_output_func output, char *args))
+PT_THREAD(cmd_rpl_refresh_routes(struct pt *pt, shell_output_func output, char *args))
 {
-  static uip_ipaddr_t remote_addr;
-  static struct etimer timeout_timer;
-  char *next_args;
-
   PT_BEGIN(pt);
 
-  SHELL_ARGS_INIT(args, next_args);
-
-  /* Get argument (remote IPv6) */
-  SHELL_ARGS_NEXT(args, next_args);
-  if(args == NULL) {
-    SHELL_OUTPUT(output, "Destination IPv6 address is not specified\n");
-    PT_EXIT(pt);
-  } else if(uiplib_ipaddrconv(args, &remote_addr) == 0) {
-    SHELL_OUTPUT(output, "Invalid IPv6 address: %s\n", args);
-    PT_EXIT(pt);
-  }
-
-  SHELL_OUTPUT(output, "Pinging ");
-  shell_output_6addr(output, &remote_addr);
-  SHELL_OUTPUT(output, "\n");
-
-  /* Send ping request */
-  curr_ping_process = PROCESS_CURRENT();
-  curr_ping_output_func = output;
-  etimer_set(&timeout_timer, PING_TIMEOUT);
-  uip_icmp6_send(&remote_addr, ICMP6_ECHO_REQUEST, 0, 4);
-  PT_WAIT_UNTIL(pt, curr_ping_output_func == NULL || etimer_expired(&timeout_timer));
-
-  if(curr_ping_output_func != NULL) {
-    SHELL_OUTPUT(output, "Timeout\n");
-    curr_ping_output_func = NULL;
-  } else {
-    SHELL_OUTPUT(output, "Received ping reply from ");
-    shell_output_6addr(output, &remote_addr);
-    SHELL_OUTPUT(output, ", len %u, ttl %u, delay %lu ms\n",
-      curr_ping_datalen, curr_ping_ttl, (1000*(clock_time() - timeout_timer.timer.start))/CLOCK_SECOND);
-  }
+  SHELL_OUTPUT(output, "Triggering routes refresh\n");
+  rpl_refresh_routes("Shell");
 
   PT_END(pt);
 }
+#endif /* ROUTING_CONF_RPL_LITE */
 /*---------------------------------------------------------------------------*/
 static void
 shell_output_log_levels(shell_output_func output)
@@ -394,7 +413,8 @@ PT_THREAD(cmd_rpl_set_root(struct pt *pt, shell_output_func output, char *args))
       PT_EXIT(pt);
     }
   } else {
-    uip_ip6addr(&prefix, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
+    const uip_ipaddr_t *default_prefix = uip_ds6_default_prefix();
+    uip_ip6addr_copy(&prefix, default_prefix);
   }
 
   if(is_on) {
@@ -424,7 +444,7 @@ PT_THREAD(cmd_rpl_global_repair(struct pt *pt, shell_output_func output, char *a
 {
   PT_BEGIN(pt);
 
-  SHELL_OUTPUT(output, "Triggering routing global repair\n")
+  SHELL_OUTPUT(output, "Triggering routing global repair\n");
   NETSTACK_ROUTING.global_repair("Shell");
 
   PT_END(pt);
@@ -440,20 +460,20 @@ PT_THREAD(cmd_rpl_local_repair(struct pt *pt, shell_output_func output, char *ar
 
   PT_END(pt);
 }
+#endif /* UIP_CONF_IPV6_RPL */
 /*---------------------------------------------------------------------------*/
-#if ROUTING_CONF_RPL_LITE
 static
-PT_THREAD(cmd_rpl_refresh_routes(struct pt *pt, shell_output_func output, char *args))
+PT_THREAD(cmd_macaddr(struct pt *pt, shell_output_func output, char *args))
 {
   PT_BEGIN(pt);
 
-  SHELL_OUTPUT(output, "Triggering routes refresh\n")
-  rpl_refresh_routes("Shell");
+  SHELL_OUTPUT(output, "Node MAC address: ");
+  shell_output_lladdr(output, &linkaddr_node_addr);
+  SHELL_OUTPUT(output, "\n");
 
   PT_END(pt);
 }
-#endif /* ROUTING_CONF_RPL_LITE */
-#endif /* UIP_CONF_IPV6_RPL */
+#if NETSTACK_CONF_WITH_IPV6
 /*---------------------------------------------------------------------------*/
 static
 PT_THREAD(cmd_ipaddr(struct pt *pt, shell_output_func output, char *args))
@@ -475,7 +495,6 @@ PT_THREAD(cmd_ipaddr(struct pt *pt, shell_output_func output, char *args))
   }
 
   PT_END(pt);
-
 }
 /*---------------------------------------------------------------------------*/
 static
@@ -506,6 +525,7 @@ PT_THREAD(cmd_ip_neighbors(struct pt *pt, shell_output_func output, char *args))
   PT_END(pt);
 
 }
+#endif /* NETSTACK_CONF_WITH_IPV6 */
 #if MAC_CONF_WITH_TSCH
 /*---------------------------------------------------------------------------*/
 static
@@ -581,13 +601,18 @@ PT_THREAD(cmd_tsch_status(struct pt *pt, shell_output_func output, char *args))
     } else {
       SHELL_OUTPUT(output, "none\n");
     }
-    SHELL_OUTPUT(output, "-- Last synchronized: %lu seconds ago\n", (clock_time() - last_sync_time) / CLOCK_SECOND);
-    SHELL_OUTPUT(output, "-- Drift w.r.t. coordinator: %ld ppm\n", tsch_adaptive_timesync_get_drift_ppm());
+    SHELL_OUTPUT(output, "-- Last synchronized: %lu seconds ago\n",
+                 (clock_time() - tsch_last_sync_time) / CLOCK_SECOND);
+    SHELL_OUTPUT(output, "-- Drift w.r.t. coordinator: %ld ppm\n",
+                 tsch_adaptive_timesync_get_drift_ppm());
+    SHELL_OUTPUT(output, "-- Network uptime: %lu seconds\n",
+                 (unsigned long)(tsch_get_network_uptime_ticks() / CLOCK_SECOND));
   }
 
   PT_END(pt);
 }
 #endif /* MAC_CONF_WITH_TSCH */
+#if NETSTACK_CONF_WITH_IPV6
 /*---------------------------------------------------------------------------*/
 static
 PT_THREAD(cmd_routes(struct pt *pt, shell_output_func output, char *args))
@@ -653,6 +678,7 @@ PT_THREAD(cmd_routes(struct pt *pt, shell_output_func output, char *args))
 
   PT_END(pt);
 }
+#endif /* NETSTACK_CONF_WITH_IPV6 */
 /*---------------------------------------------------------------------------*/
 static
 PT_THREAD(cmd_reboot(struct pt *pt, shell_output_func output, char *args))
@@ -729,14 +755,83 @@ PT_THREAD(cmd_6top(struct pt *pt, shell_output_func output, char *args))
 }
 #endif /* TSCH_WITH_SIXTOP */
 /*---------------------------------------------------------------------------*/
+#if LLSEC802154_ENABLED
+static
+PT_THREAD(cmd_llsec_setlv(struct pt *pt, shell_output_func output, char *args))
+{
+
+  PT_BEGIN(pt);
+
+  if(args == NULL) {
+    SHELL_OUTPUT(output, "Default LLSEC level is %d\n",
+                 uipbuf_get_attr(UIPBUF_ATTR_LLSEC_LEVEL));
+    PT_EXIT(pt);
+  } else {
+    int lv = atoi(args);
+    if(lv < 0 || lv > 7) {
+      SHELL_OUTPUT(output, "Illegal LLSEC Level %d\n", lv);
+      PT_EXIT(pt);
+    } else {
+      uipbuf_set_default_attr(UIPBUF_ATTR_LLSEC_LEVEL, lv);
+      uipbuf_clear_attr();
+      SHELL_OUTPUT(output, "LLSEC default level set %d\n", lv);
+    }
+  }
+
+  PT_END(pt);
+}
+/*---------------------------------------------------------------------------*/
+static
+PT_THREAD(cmd_llsec_setkey(struct pt *pt, shell_output_func output, char *args))
+{
+  char *next_args;
+
+  PT_BEGIN(pt);
+
+  SHELL_ARGS_INIT(args, next_args);
+
+  if(args == NULL) {
+    SHELL_OUTPUT(output, "Provide an index and a 16-char string for the key\n");
+    PT_EXIT(pt);
+  } else {
+    int key;
+    SHELL_ARGS_NEXT(args, next_args);
+    key = atoi(args);
+    if(key < 0) {
+      SHELL_OUTPUT(output, "Illegal LLSEC Key index %d\n", key);
+      PT_EXIT(pt);
+    } else {
+#if MAC_CONF_WITH_CSMA
+      /* Get next arg (key-string) */
+      SHELL_ARGS_NEXT(args, next_args);
+      if(args == NULL) {
+        SHELL_OUTPUT(output, "Provide both an index and a key\n");
+      } else if(strlen(args) == 16) {
+        csma_security_set_key(key, (const uint8_t *) args);
+        SHELL_OUTPUT(output, "Set key for index %d\n", key);
+      } else {
+        SHELL_OUTPUT(output, "Wrong length of key: '%s' (%d)\n", args, strlen(args));
+      }
+#else
+      SHELL_OUTPUT(output, "Set key not supported.\n");
+      PT_EXIT(pt);
+#endif
+    }
+  }
+  PT_END(pt);
+}
+#endif /* LLSEC802154_ENABLED */
+/*---------------------------------------------------------------------------*/
 void
 shell_commands_init(void)
 {
   list_init(shell_command_sets);
   list_add(shell_command_sets, &builtin_shell_command_set);
+#if NETSTACK_CONF_WITH_IPV6
   /* Set up Ping Reply callback */
   uip_icmp6_echo_reply_callback_add(&echo_reply_notification,
                                     echo_reply_handler);
+#endif /* NETSTACK_CONF_WITH_IPV6 */
 }
 /*---------------------------------------------------------------------------*/
 void
@@ -776,23 +871,24 @@ shell_command_lookup(const char *name)
 const struct shell_command_t builtin_shell_commands[] = {
   { "help",                 cmd_help,                 "'> help': Shows this help" },
   { "reboot",               cmd_reboot,               "'> reboot': Reboot the board by watchdog_reboot()" },
+  { "log",                  cmd_log,                  "'> log module level': Sets log level (0--4) for a given module (or \"all\"). For module \"mac\", level 4 also enables per-slot logging." },
+  { "mac-addr",             cmd_macaddr,               "'> mac-addr': Shows the node's MAC address" },
+#if NETSTACK_CONF_WITH_IPV6
   { "ip-addr",              cmd_ipaddr,               "'> ip-addr': Shows all IPv6 addresses" },
   { "ip-nbr",               cmd_ip_neighbors,         "'> ip-nbr': Shows all IPv6 neighbors" },
-  { "log",                  cmd_log,                  "'> log module level': Sets log level (0--4) for a given module (or \"all\"). For module \"mac\", level 4 also enables per-slot logging." },
   { "ping",                 cmd_ping,                 "'> ping addr': Pings the IPv6 address 'addr'" },
+  { "routes",               cmd_routes,               "'> routes': Shows the route entries" },
+#endif /* NETSTACK_CONF_WITH_IPV6 */
 #if UIP_CONF_IPV6_RPL
   { "rpl-set-root",         cmd_rpl_set_root,         "'> rpl-set-root 0/1 [prefix]': Sets node as root (1) or not (0). A /64 prefix can be optionally specified." },
   { "rpl-local-repair",     cmd_rpl_local_repair,     "'> rpl-local-repair': Triggers a RPL local repair" },
 #if ROUTING_CONF_RPL_LITE
   { "rpl-refresh-routes",   cmd_rpl_refresh_routes,   "'> rpl-refresh-routes': Refreshes all routes through a DTSN increment" },
-#endif /* ROUTING_CONF_RPL_LITE */
-  { "rpl-global-repair",    cmd_rpl_global_repair,    "'> rpl-global-repair': Triggers a RPL global repair" },
-#endif /* UIP_CONF_IPV6_RPL */
-#if ROUTING_CONF_RPL_LITE
   { "rpl-status",           cmd_rpl_status,           "'> rpl-status': Shows a summary of the current RPL state" },
   { "rpl-nbr",              cmd_rpl_nbr,              "'> rpl-nbr': Shows the RPL neighbor table" },
 #endif /* ROUTING_CONF_RPL_LITE */
-  { "routes",               cmd_routes,               "'> routes': Shows the route entries" },
+  { "rpl-global-repair",    cmd_rpl_global_repair,    "'> rpl-global-repair': Triggers a RPL global repair" },
+#endif /* UIP_CONF_IPV6_RPL */
 #if MAC_CONF_WITH_TSCH
   { "tsch-set-coordinator", cmd_tsch_set_coordinator, "'> tsch-set-coordinator 0/1 [0/1]': Sets node as coordinator (1) or not (0). Second, optional parameter: enable (1) or disable (0) security." },
   { "tsch-schedule",        cmd_tsch_schedule,        "'> tsch-schedule': Shows the current TSCH schedule" },
@@ -801,6 +897,10 @@ const struct shell_command_t builtin_shell_commands[] = {
 #if TSCH_WITH_SIXTOP
   { "6top",                 cmd_6top,                 "'> 6top help': Shows 6top command usage" },
 #endif /* TSCH_WITH_SIXTOP */
+#if LLSEC802154_ENABLED
+  { "llsec-set-level", cmd_llsec_setlv, "'> llsec-set-level <lv>': Set the level of link layer security (show if no lv argument)"},
+  { "llsec-set-key", cmd_llsec_setkey, "'> llsec-set-key <id> <key>': Set the key of link layer security"},
+#endif /* LLSEC802154_ENABLED */
   { NULL, NULL, NULL },
 };
 
diff --git a/os/services/shell/shell-commands.h b/os/services/shell/shell-commands.h
index f510e861d7d48aa347cb33eec77a3bf2872f6351..87c72a2793df2fd78cdff4348776ac347335e7c2 100644
--- a/os/services/shell/shell-commands.h
+++ b/os/services/shell/shell-commands.h
@@ -37,7 +37,7 @@
  *         Simon Duquennoy <simon.duquennoy@inria.fr>
  */
 
-/** \addtogroup apps
+/** \addtogroup shell
  * @{ */
 
 #ifndef _SHELL_COMMANDS_H_
diff --git a/os/services/shell/shell.c b/os/services/shell/shell.c
index c219b19031d285eaf5d04b51b59b93c642def5cb..1aa40d7c432a6179567d27760960b5f2152ced8b 100644
--- a/os/services/shell/shell.c
+++ b/os/services/shell/shell.c
@@ -38,10 +38,7 @@
  */
 
 /**
- * \addtogroup shell Shell
- The shell enables to inspect and manage the network layer and provides
- other system functionalities
- * \ingroup lib
+ * \addtogroup shell
  * @{
  */
 
@@ -52,6 +49,7 @@
 #include "net/ipv6/ip64-addr.h"
 #include "net/ipv6/uiplib.h"
 
+#if NETSTACK_CONF_WITH_IPV6
 /*---------------------------------------------------------------------------*/
 void
 shell_output_6addr(shell_output_func output, const uip_ipaddr_t *ipaddr)
@@ -60,6 +58,7 @@ shell_output_6addr(shell_output_func output, const uip_ipaddr_t *ipaddr)
   uiplib_ipaddr_snprint(buf, sizeof(buf), ipaddr);
   SHELL_OUTPUT(output, "%s", buf);
 }
+#endif /* NETSTACK_CONF_WITH_IPV6 */
 /*---------------------------------------------------------------------------*/
 void
 shell_output_lladdr(shell_output_func output, const linkaddr_t *lladdr)
@@ -98,19 +97,22 @@ PT_THREAD(shell_input(struct pt *pt, shell_output_func output, const char *cmd))
     cmd++;
   }
 
-  /* Look for arguments */
-  args = strchr(cmd, ' ');
-  if(args != NULL) {
-    *args = '\0';
-    args++;
-  }
+  /* Skip empty lines */
+  if(*cmd != '\0') {
+    /* Look for arguments */
+    args = strchr(cmd, ' ');
+    if(args != NULL) {
+      *args = '\0';
+      args++;
+    }
 
-  cmd_descr = shell_command_lookup(cmd);
-  if(cmd_descr != NULL) {
-    static struct pt cmd_pt;
-    PT_SPAWN(pt, &cmd_pt, cmd_descr->func(&cmd_pt, output, args));
-  } else {
-    SHELL_OUTPUT(output, "Command not found. Type 'help' for a list of commands\n");
+    cmd_descr = shell_command_lookup(cmd);
+    if(cmd_descr != NULL) {
+      static struct pt cmd_pt;
+      PT_SPAWN(pt, &cmd_pt, cmd_descr->func(&cmd_pt, output, args));
+    } else {
+      SHELL_OUTPUT(output, "Command not found. Type 'help' for a list of commands\n");
+    }
   }
 
   output_prompt(output);
diff --git a/os/services/shell/shell.h b/os/services/shell/shell.h
index 4f1b4186c45203c700b305361f3f83573a6313f4..f6b9876ce46fcfb62883aabd22a93569de2fdf0f 100644
--- a/os/services/shell/shell.h
+++ b/os/services/shell/shell.h
@@ -29,6 +29,17 @@
  * This file is part of the Contiki operating system.
  *
  */
+/**
+* \addtogroup lib
+* @{
+*
+* \defgroup shell Contiki-NG interactive management shell
+*
+* The shell enables to inspect and manage the network layer and provides
+* other system functionalities
+*
+* @{
+*/
 
 /**
  * \file
@@ -36,10 +47,6 @@
  * \author
  *         Simon Duquennoy <simon.duquennoy@inria.fr>
  */
-
-/** \addtogroup apps
- * @{ */
-
 #ifndef SHELL_H_
 #define SHELL_H_
 
@@ -104,5 +111,7 @@ void shell_output_6addr(shell_output_func output, const uip_ipaddr_t *ipaddr);
 void shell_output_lladdr(shell_output_func output, const linkaddr_t *lladdr);
 
 #endif /* SHELL_H_ */
-
-/** @} */
+/**
+ * @}
+ * @}
+ */
diff --git a/os/services/simple-energest/simple-energest.h b/os/services/simple-energest/simple-energest.h
index 4f7281e9c6c35af6f87c1b69f76c61b6a365179e..893991d3f27e406dd88b69e9072965ffff01c4a1 100644
--- a/os/services/simple-energest/simple-energest.h
+++ b/os/services/simple-energest/simple-energest.h
@@ -28,8 +28,11 @@
  *
  */
 
- /**
- * \addtogroup simple-energest
+/**
+ * \addtogroup lib
+ * @{
+ *
+ * \defgroup simple-energest The Simple Energest module
  * @{
  */
 
@@ -57,4 +60,7 @@
 void simple_energest_init(void);
 
 #endif /* SIMPLE_ENERGEST_H_ */
-/** @} */
+/**
+ * @}
+ * @}
+ */
diff --git a/os/sys/atomic.c b/os/sys/atomic.c
new file mode 100644
index 0000000000000000000000000000000000000000..8348e27d4476a8a7add3fdeff11297e5b883e9ce
--- /dev/null
+++ b/os/sys/atomic.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2019, Toshiba Corporation
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+
+/**
+ * \addtogroup atomic
+ * @{
+ */
+
+#include "atomic.h"
+#include <sys/critical.h>
+
+/*---------------------------------------------------------------------------*/
+bool
+atomic_generic_cas_uint8(uint8_t *target, uint8_t old_val, uint8_t new_val)
+{
+  bool ret = false;
+  int_master_status_t status = critical_enter();
+  if(*target == old_val) {
+    *target = new_val;
+    ret = true;
+  }
+  critical_exit(status);
+  return ret;
+}
+/** @} */
diff --git a/os/sys/atomic.h b/os/sys/atomic.h
new file mode 100644
index 0000000000000000000000000000000000000000..61282a5d8cadf8616069e2f1ac448fc36a2f8329
--- /dev/null
+++ b/os/sys/atomic.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2019, Toshiba Corporation
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+/*---------------------------------------------------------------------------*/
+/**
+ * \addtogroup sys
+ * @{
+ *
+ * \defgroup atomic Atomic operations
+ * @{
+ *
+ * This library provides an API and generic implementation of atomic
+ * operations.
+ *
+ * The structure of this library is more or less the same as
+ * sys/mutex. By default, atomic operations are implemented by
+ * disabling interrupts temporarily. Platforms can provide better
+ * implementation using platform-specific features.
+ *
+ */
+#ifndef ATOMIC_H_
+#define ATOMIC_H_
+
+#include <contiki.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+#ifdef ATOMIC_CONF_ARCH_HEADER_PATH
+#include ATOMIC_CONF_ARCH_HEADER_PATH
+#endif /* ATOMIC_CONF_ARCH_HEADER_PATH */
+
+/**
+ * \brief Atomic compare-and-swap (CAS) on a byte.
+ * 
+ * This macro expands to atomic_generic_cas_uint8() or CPU-provided
+ * implementation. Platform-independent code should use this macro
+ * instead of atomic_generic_cas_uint8(). 
+ */  
+#ifndef atomic_cas_uint8
+#define atomic_cas_uint8(t,o,n) atomic_generic_cas_uint8((t),(o),(n))
+#endif /* atomic_cas_uint8 */
+
+/**
+ * \brief Atomic compare-and-swap (CAS) on a byte (generic impl.)
+ * \param target Pointer to the target byte to manipulate.
+ * \param old_val Value that is expected to be stored in the target.
+ * \param new_val Value that it stores to the target.
+ *
+ * If value of target is equal to old_val, store new_val to
+ * target. If the store operation succeeds, it returns true.
+ * Otherwise, it just returns false without storing.
+ */
+bool atomic_generic_cas_uint8(uint8_t *target, uint8_t old_val, uint8_t new_val);
+
+#endif /* ATOMIC_H_ */
+/**
+ * @}
+ * @}
+ */
diff --git a/os/sys/ctimer.h b/os/sys/ctimer.h
index e7e463ac432f9071c712c9499cc4fbb5217ff706..6f05d7c16cb69cb3ed9b0206dd63a4f1d54f8f5d 100644
--- a/os/sys/ctimer.h
+++ b/os/sys/ctimer.h
@@ -49,6 +49,7 @@
  * The ctimer module provides a timer mechanism that calls a specified
  * C function when a ctimer expires.
  *
+ * It is \e not safe to manipulate callback timers within an interrupt context.
  */
 
 #ifndef CTIMER_H_
diff --git a/os/sys/etimer.h b/os/sys/etimer.h
index 2922b9aa282dff3bd62bd62466567f3e980995d7..a9447bf24bc7f8d81187167bee879a2ea24e29af 100644
--- a/os/sys/etimer.h
+++ b/os/sys/etimer.h
@@ -56,6 +56,7 @@
  * \sa \ref timer "Simple timer library"
  * \sa \ref clock "Clock library" (used by the timer library)
  *
+ * It is \e not safe to manipulate event timers within an interrupt context.
  * @{
  */
 
diff --git a/os/sys/node-id.h b/os/sys/node-id.h
index 58909ddaa991457a996d9b6ecddbbabf9e06c6ea..5f1bd1b962d7a7b3a469d819ac72b6e4470bf106 100644
--- a/os/sys/node-id.h
+++ b/os/sys/node-id.h
@@ -31,7 +31,10 @@
  */
 
  /**
-  * \addtogroup node-id
+  * \addtogroup sys
+  * @{
+  *
+  * \defgroup node-id Node ID management
   * @{
   *
   * \file
@@ -51,5 +54,7 @@ extern uint16_t node_id;
 void node_id_init(void);
 
 #endif /* NODE_ID_H_ */
- /** @} */
- 
+/**
+ * @}
+ * @}
+ */
diff --git a/os/sys/rtimer.h b/os/sys/rtimer.h
index 260f08950a35a639bdd4eead58287b68ac082221..783e1569bb34cc2276d94f0e0286edc9e7c55588 100644
--- a/os/sys/rtimer.h
+++ b/os/sys/rtimer.h
@@ -189,14 +189,14 @@ void rtimer_arch_schedule(rtimer_clock_t t);
 #endif /* RTIMER_CONF_GUARD_TIME */
 
 /** \brief Busy-wait until a condition. Start time is t0, max wait time is max_time */
+#ifndef RTIMER_BUSYWAIT_UNTIL_ABS
 #define RTIMER_BUSYWAIT_UNTIL_ABS(cond, t0, max_time) \
   ({                                                                \
     bool c;                                                         \
-    while(!(c = cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (max_time))) { \
-      watchdog_periodic();                                          \
-    }                                                               \
+    while(!(c = cond) && RTIMER_CLOCK_LT(RTIMER_NOW(), (t0) + (max_time))); \
     c;                                                              \
   })
+#endif /* RTIMER_BUSYWAIT_UNTIL_ABS */
 
 /** \brief Busy-wait until a condition for at most max_time */
 #define RTIMER_BUSYWAIT_UNTIL(cond, max_time)       \
diff --git a/os/sys/stack-check.c b/os/sys/stack-check.c
index 61f8d98abb02de36876f36a6404ec8499cd1af66..fb3014ed2b12dc429a938e3c04f7a4799524fcad 100644
--- a/os/sys/stack-check.c
+++ b/os/sys/stack-check.c
@@ -44,6 +44,7 @@
 #include "sys/stack-check.h"
 #include "dev/watchdog.h"
 #include <string.h>
+#include <inttypes.h>
 
 #include "sys/log.h"
 #define LOG_MODULE "Stack"
@@ -91,7 +92,7 @@ stack_check_init(void)
 #endif
 }
 /*---------------------------------------------------------------------------*/
-uint16_t
+int32_t
 stack_check_get_usage(void)
 {
   uint8_t *p = &_stack;
@@ -116,13 +117,13 @@ stack_check_get_usage(void)
 
   if(p >= (uint8_t*)GET_STACK_ORIGIN()) {
     /* This means the stack is screwed. */
-    return 0xffff;
+    return -1;
   }
 
   return (uint8_t *)GET_STACK_ORIGIN() - p;
 }
 /*---------------------------------------------------------------------------*/
-uint16_t
+int32_t
 stack_check_get_reserved_size(void)
 {
   return (uint8_t *)GET_STACK_ORIGIN() - &_stack;
@@ -139,16 +140,18 @@ PROCESS_THREAD(stack_check_process, ev, data)
   etimer_set(&et, STACK_CHECK_PERIOD);
 
   while(1) {
-    uint16_t actual, allowed;
+    int32_t actual, allowed;
 
     PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et));
 
     actual = stack_check_get_usage();
     allowed = stack_check_get_reserved_size();
-    if(actual > allowed) {
-      LOG_ERR("Check failed: %u vs. %u\n", actual, allowed);
+    if(actual < 0 || allowed < 0) {
+      LOG_ERR("Check in inconsistent state: %" PRId32 " vs. %" PRId32 "\n", actual, allowed);
+    } else if(actual > allowed) {
+      LOG_ERR("Check failed: %" PRId32 " vs. %" PRId32 "\n", actual, allowed);
     } else {
-      LOG_DBG("Check ok: %u vs. %u\n", actual, allowed);
+      LOG_DBG("Check ok: %" PRId32 " vs. %" PRId32 "\n", actual, allowed);
     }
 
     etimer_reset(&et);
diff --git a/os/sys/stack-check.h b/os/sys/stack-check.h
index 805c4b7da6e6b229abd0de4a5e9d6b641f2cb030..9472be193816934924cc0209719c0887cba32dda 100644
--- a/os/sys/stack-check.h
+++ b/os/sys/stack-check.h
@@ -105,7 +105,7 @@ void stack_check_init(void);
  *             has been completely used, but it cannot detect
  *             and warn if stack overflow has already taken place.
  */
-uint16_t stack_check_get_usage(void);
+int32_t stack_check_get_usage(void);
 
 /**
  * \brief      Calculate the maximal permitted stack usage.
@@ -113,7 +113,7 @@ uint16_t stack_check_get_usage(void);
  *             This function returns the number of bytes between the origin
  *             of the stack and the end of heap.
  */
-uint16_t stack_check_get_reserved_size(void);
+int32_t stack_check_get_reserved_size(void);
 
 /**
  * \brief      The origin point from which the stack grows (an optional #define)
diff --git a/tests/01-compile-base/Makefile b/tests/01-compile-base/Makefile
index 09f89418ded15ed00ae440776abc730fe619afb0..51e68f9a258cea9c22e13e3e05a7cabdd6ce348b 100644
--- a/tests/01-compile-base/Makefile
+++ b/tests/01-compile-base/Makefile
@@ -6,6 +6,7 @@ hello-world/native \
 hello-world/native:MAKE_NET=MAKE_NET_NULLNET \
 hello-world/native:MAKE_ROUTING=MAKE_ROUTING_RPL_CLASSIC \
 hello-world/sky \
+hello-world/z1 \
 storage/eeprom-test/native \
 libs/logging/native \
 libs/energest/native \
@@ -30,6 +31,7 @@ mqtt-client/native \
 coap/coap-example-client/native \
 coap/coap-example-server/native \
 coap/coap-plugtest-server/native \
+sensniff/z1 \
 
 TOOLS=
 
diff --git a/tests/02-compile-arm-ports-01/Makefile b/tests/02-compile-arm-ports-01/Makefile
index aaebab164c1a7c350e29df2ae7902a2c6a0eaf00..43e008c8e8a581b70e0b34177b2e9b471841b622 100644
--- a/tests/02-compile-arm-ports-01/Makefile
+++ b/tests/02-compile-arm-ports-01/Makefile
@@ -2,41 +2,41 @@ EXAMPLESDIR=../../examples
 TOOLSDIR=../../tools
 
 EXAMPLES = \
-platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx \
-platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:MAKE_ROUTING=MAKE_ROUTING_RPL_CLASSIC \
-platform-specific/cc26xx/very-sleepy-demo/srf06-cc26xx:BOARD=sensortag/cc2650 \
-platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=sensortag/cc2650 \
-platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=sensortag/cc1350 \
-platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=srf06/cc13xx \
-platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=launchpad/cc2650 \
-platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=launchpad/cc1310 \
-platform-specific/cc26xx/cc26xx-web-demo/srf06-cc26xx:BOARD=launchpad/cc1350 \
-platform-specific/cc26xx/very-sleepy-demo/srf06-cc26xx \
-platform-specific/cc26xx/ble-ipv6/srf06-cc26xx:BOARD=sensortag/cc2650 \
-nullnet/srf06-cc26xx:BOARD=sensortag/cc2650 \
-rpl-border-router/srf06-cc26xx:BOARD=launchpad/cc2650 \
-sensniff/srf06-cc26xx \
-sensniff/srf06-cc26xx:BOARD=launchpad/cc1310 \
-dev/gpio-hal/srf06-cc26xx:BOARD=srf06/cc13xx \
-dev/gpio-hal/srf06-cc26xx:BOARD=srf06/cc26xx \
-dev/gpio-hal/srf06-cc26xx:BOARD=sensortag/cc1350 \
-dev/gpio-hal/srf06-cc26xx:BOARD=sensortag/cc2650 \
-dev/gpio-hal/srf06-cc26xx:BOARD=launchpad/cc1310 \
-dev/gpio-hal/srf06-cc26xx:BOARD=launchpad/cc1350 \
-dev/gpio-hal/srf06-cc26xx:BOARD=launchpad/cc2650 \
-dev/gpio-hal/srf06-cc26xx:BOARD=launchpad/cc2640r2 \
-dev/leds/srf06-cc26xx:BOARD=srf06/cc13xx \
-dev/leds/srf06-cc26xx:BOARD=srf06/cc26xx \
-dev/leds/srf06-cc26xx:BOARD=sensortag/cc1350 \
-dev/leds/srf06-cc26xx:BOARD=sensortag/cc2650 \
-dev/leds/srf06-cc26xx:BOARD=launchpad/cc1310 \
-dev/leds/srf06-cc26xx:BOARD=launchpad/cc1350 \
-dev/leds/srf06-cc26xx:BOARD=launchpad/cc2650 \
-dev/leds/srf06-cc26xx:BOARD=launchpad/cc2640r2 \
-6tisch/etsi-plugtest-2017/srf06-cc26xx:BOARD=launchpad/cc2650 \
-mqtt-client/srf06-cc26xx:BOARD=srf06/cc26xx \
-mqtt-client/srf06-cc26xx:BOARD=launchpad/cc2650 \
-mqtt-client/srf06-cc26xx:BOARD=sensortag/cc2650 \
+platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cc26x0-cc13x0 \
+platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cc26x0-cc13x0:MAKE_ROUTING=MAKE_ROUTING_RPL_CLASSIC \
+platform-specific/cc26x0-cc13x0/very-sleepy-demo/cc26x0-cc13x0:BOARD=sensortag/cc2650 \
+platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cc26x0-cc13x0:BOARD=sensortag/cc2650 \
+platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cc26x0-cc13x0:BOARD=sensortag/cc1350 \
+platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cc26x0-cc13x0:BOARD=srf06/cc13x0 \
+platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cc26x0-cc13x0:BOARD=launchpad/cc2650 \
+platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cc26x0-cc13x0:BOARD=launchpad/cc1310 \
+platform-specific/cc26x0-cc13x0/cc26x0-web-demo/cc26x0-cc13x0:BOARD=launchpad/cc1350 \
+platform-specific/cc26x0-cc13x0/very-sleepy-demo/cc26x0-cc13x0 \
+platform-specific/cc26x0-cc13x0/ble-ipv6/cc26x0-cc13x0:BOARD=sensortag/cc2650 \
+nullnet/cc26x0-cc13x0:BOARD=sensortag/cc2650 \
+rpl-border-router/cc26x0-cc13x0:BOARD=launchpad/cc2650 \
+sensniff/cc26x0-cc13x0 \
+sensniff/cc26x0-cc13x0:BOARD=launchpad/cc1310 \
+dev/gpio-hal/cc26x0-cc13x0:BOARD=srf06/cc13x0 \
+dev/gpio-hal/cc26x0-cc13x0:BOARD=srf06/cc26x0 \
+dev/gpio-hal/cc26x0-cc13x0:BOARD=sensortag/cc1350 \
+dev/gpio-hal/cc26x0-cc13x0:BOARD=sensortag/cc2650 \
+dev/gpio-hal/cc26x0-cc13x0:BOARD=launchpad/cc1310 \
+dev/gpio-hal/cc26x0-cc13x0:BOARD=launchpad/cc1350 \
+dev/gpio-hal/cc26x0-cc13x0:BOARD=launchpad/cc2650 \
+dev/gpio-hal/cc26x0-cc13x0:BOARD=launchpad/cc2640r2 \
+dev/leds/cc26x0-cc13x0:BOARD=srf06/cc13x0 \
+dev/leds/cc26x0-cc13x0:BOARD=srf06/cc26x0 \
+dev/leds/cc26x0-cc13x0:BOARD=sensortag/cc1350 \
+dev/leds/cc26x0-cc13x0:BOARD=sensortag/cc2650 \
+dev/leds/cc26x0-cc13x0:BOARD=launchpad/cc1310 \
+dev/leds/cc26x0-cc13x0:BOARD=launchpad/cc1350 \
+dev/leds/cc26x0-cc13x0:BOARD=launchpad/cc2650 \
+dev/leds/cc26x0-cc13x0:BOARD=launchpad/cc2640r2 \
+6tisch/etsi-plugtest-2017/cc26x0-cc13x0:BOARD=launchpad/cc2650 \
+mqtt-client/cc26x0-cc13x0:BOARD=srf06/cc26x0 \
+mqtt-client/cc26x0-cc13x0:BOARD=launchpad/cc2650 \
+mqtt-client/cc26x0-cc13x0:BOARD=sensortag/cc2650 \
 hello-world/simplelink:BOARD=launchpad/cc26x2r1 \
 hello-world/simplelink:BOARD=sensortag/cc2650 \
 nullnet/simplelink:BOARD=sensortag/cc2650 \
diff --git a/tests/07-simulation-base/07-hello-world-z1.csc b/tests/07-simulation-base/07-hello-world-z1.csc
new file mode 100644
index 0000000000000000000000000000000000000000..33963c36c8bdd80f6b63deedc56534dceba09011
--- /dev/null
+++ b/tests/07-simulation-base/07-hello-world-z1.csc
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<simconf>
+  <simulation>
+    <title>Hello World (Z1)</title>
+    <randomseed>generated</randomseed>
+    <motedelay_us>1000000</motedelay_us>
+    <radiomedium>
+      org.contikios.cooja.radiomediums.UDGM
+      <transmitting_range>50.0</transmitting_range>
+      <interference_range>100.0</interference_range>
+      <success_ratio_tx>1.0</success_ratio_tx>
+      <success_ratio_rx>1.0</success_ratio_rx>
+    </radiomedium>
+    <events>
+      <logoutput>40000</logoutput>
+    </events>
+    <motetype>
+      org.contikios.cooja.mspmote.Z1MoteType
+      <identifier>z11</identifier>
+      <description>Z1 Mote Type #z11</description>
+      <source EXPORT="discard">[CONTIKI_DIR]/examples/hello-world/hello-world.c</source>
+      <commands EXPORT="discard">make hello-world.z1 TARGET=z1</commands>
+      <firmware EXPORT="copy">[CONTIKI_DIR]/examples/hello-world/hello-world.z1</firmware>
+      <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
+      <moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
+      <moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
+      <moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
+      <moteinterface>org.contikios.cooja.mspmote.interfaces.MspDefaultSerial</moteinterface>
+      <moteinterface>org.contikios.cooja.mspmote.interfaces.MspLED</moteinterface>
+      <moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
+    </motetype>
+    <mote>
+      <breakpoints />
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>94.96401380574989</x>
+        <y>21.247662337471553</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.mspmote.interfaces.MspMoteID
+        <id>1</id>
+      </interface_config>
+      <motetype_identifier>z11</motetype_identifier>
+    </mote>
+  </simulation>
+  <plugin>
+    org.contikios.cooja.plugins.SimControl
+    <width>280</width>
+    <z>2</z>
+    <height>160</height>
+    <location_x>38</location_x>
+    <location_y>13</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.LogListener
+    <plugin_config>
+      <filter />
+    </plugin_config>
+    <width>680</width>
+    <z>1</z>
+    <height>240</height>
+    <location_x>109</location_x>
+    <location_y>377</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.ScriptRunner
+    <plugin_config>
+      <scriptfile>[CONFIG_DIR]/hello-world.js</scriptfile>
+      <active>true</active>
+    </plugin_config>
+    <width>600</width>
+    <z>0</z>
+    <height>700</height>
+    <location_x>330</location_x>
+    <location_y>24</location_y>
+  </plugin>
+</simconf>
+
diff --git a/tests/07-simulation-base/14-cooja-multicast-11-hops-mpl.csc b/tests/07-simulation-base/14-cooja-multicast-11-hops-mpl.csc
new file mode 100644
index 0000000000000000000000000000000000000000..9c337fb5b2037d42fd81e28eb044fea27329e1ff
--- /dev/null
+++ b/tests/07-simulation-base/14-cooja-multicast-11-hops-mpl.csc
@@ -0,0 +1,366 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<simconf>
+  <project EXPORT="discard">[APPS_DIR]/mrm</project>
+  <project EXPORT="discard">[APPS_DIR]/mspsim</project>
+  <project EXPORT="discard">[APPS_DIR]/avrora</project>
+  <project EXPORT="discard">[APPS_DIR]/serial_socket</project>
+  <project EXPORT="discard">[APPS_DIR]/powertracker</project>
+  <simulation>
+    <title>Multicast regression test</title>
+    <randomseed>123456</randomseed>
+    <motedelay_us>1000000</motedelay_us>
+    <radiomedium>
+      org.contikios.cooja.radiomediums.UDGM
+      <transmitting_range>15.0</transmitting_range>
+      <interference_range>0.0</interference_range>
+      <success_ratio_tx>1.0</success_ratio_tx>
+      <success_ratio_rx>1.0</success_ratio_rx>
+    </radiomedium>
+    <events>
+      <logoutput>40000</logoutput>
+    </events>
+    <motetype>
+      org.contikios.cooja.contikimote.ContikiMoteType
+      <identifier>mtype612</identifier>
+      <description>Root/sender</description>
+      <source>[CONTIKI_DIR]/examples/multicast/root.c</source>
+      <commands>make TARGET=cooja clean
+make -j root.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_MPL</commands>
+      <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
+      <symbols>false</symbols>
+    </motetype>
+    <motetype>
+      org.contikios.cooja.contikimote.ContikiMoteType
+      <identifier>mtype890</identifier>
+      <description>Intermediate</description>
+      <source>[CONTIKI_DIR]/examples/multicast/intermediate.c</source>
+      <commands>make -j intermediate.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_MPL</commands>
+      <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
+      <symbols>false</symbols>
+    </motetype>
+    <motetype>
+      org.contikios.cooja.contikimote.ContikiMoteType
+      <identifier>mtype956</identifier>
+      <description>Receiver</description>
+      <source>[CONTIKI_DIR]/examples/multicast/sink.c</source>
+      <commands>make sink.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_MPL</commands>
+      <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
+      <symbols>false</symbols>
+    </motetype>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>-7.983976888750106</x>
+        <y>0.37523218201044733</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>1</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <motetype_identifier>mtype612</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>0.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>2</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <motetype_identifier>mtype890</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>10.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>3</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <motetype_identifier>mtype890</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>20.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>4</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <motetype_identifier>mtype890</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>30.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>5</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <motetype_identifier>mtype890</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>40.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>6</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <motetype_identifier>mtype890</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>50.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>7</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <motetype_identifier>mtype890</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>60.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>8</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <motetype_identifier>mtype890</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>70.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>9</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <motetype_identifier>mtype890</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>79.93950307524713</x>
+        <y>-0.043451055913349</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>10</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <motetype_identifier>mtype890</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>90.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>11</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <motetype_identifier>mtype890</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>99.61761525766555</x>
+        <y>0.37523218201044733</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>12</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <motetype_identifier>mtype956</motetype_identifier>
+    </mote>
+  </simulation>
+  <plugin>
+    org.contikios.cooja.plugins.SimControl
+    <width>280</width>
+    <z>1</z>
+    <height>160</height>
+    <location_x>400</location_x>
+    <location_y>0</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.Visualizer
+    <plugin_config>
+      <moterelations>true</moterelations>
+      <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin>
+      <skin>org.contikios.cooja.plugins.skins.GridVisualizerSkin</skin>
+      <skin>org.contikios.cooja.plugins.skins.TrafficVisualizerSkin</skin>
+      <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin>
+      <skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin>
+      <viewport>2.388440494916608 0.0 0.0 2.388440494916608 109.06925371156906 149.10378026149033</viewport>
+    </plugin_config>
+    <width>400</width>
+    <z>3</z>
+    <height>400</height>
+    <location_x>1</location_x>
+    <location_y>1</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.LogListener
+    <plugin_config>
+      <filter />
+      <formatted_time />
+      <coloring />
+    </plugin_config>
+    <width>1200</width>
+    <z>2</z>
+    <height>240</height>
+    <location_x>400</location_x>
+    <location_y>160</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.Notes
+    <plugin_config>
+      <notes>Enter notes here</notes>
+      <decorations>true</decorations>
+    </plugin_config>
+    <width>920</width>
+    <z>4</z>
+    <height>160</height>
+    <location_x>680</location_x>
+    <location_y>0</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.ScriptRunner
+    <plugin_config>
+      <script>TIMEOUT(300000);&#xD;
+&#xD;
+WAIT_UNTIL(msg.startsWith("In: "));&#xD;
+&#xD;
+log.testOK(); /* Report test success and quit */</script>
+      <active>true</active>
+    </plugin_config>
+    <width>600</width>
+    <z>0</z>
+    <height>700</height>
+    <location_x>843</location_x>
+    <location_y>77</location_y>
+  </plugin>
+</simconf>
diff --git a/tests/07-simulation-base/15-cooja-multicast-11-hops-rollt-tm.csc b/tests/07-simulation-base/15-cooja-multicast-11-hops-rollt-tm.csc
index 473df16dd17e1eb2fb49ea9a0e0c729d98161dc8..bf3c790f643f98fdd3dd89e205efaced0878c3e6 100644
--- a/tests/07-simulation-base/15-cooja-multicast-11-hops-rollt-tm.csc
+++ b/tests/07-simulation-base/15-cooja-multicast-11-hops-rollt-tm.csc
@@ -24,7 +24,8 @@
       <identifier>mtype612</identifier>
       <description>Root/sender</description>
       <source>[CONTIKI_DIR]/examples/multicast/root.c</source>
-      <commands>make -j root.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_ROLL_TM</commands>
+      <commands>make TARGET=cooja clean
+make -j root.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_ROLL_TM</commands>
       <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
       <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
       <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
diff --git a/tests/07-simulation-base/16-cooja-multicast-11-hops-smrf.csc b/tests/07-simulation-base/16-cooja-multicast-11-hops-smrf.csc
index e20a30cb6860ff43c4c44276adb6489a39c655c4..1a62203d3273eecff8b02246b6f2a6a65abcc173 100644
--- a/tests/07-simulation-base/16-cooja-multicast-11-hops-smrf.csc
+++ b/tests/07-simulation-base/16-cooja-multicast-11-hops-smrf.csc
@@ -24,7 +24,8 @@
       <identifier>mtype612</identifier>
       <description>Root/sender</description>
       <source>[CONTIKI_DIR]/examples/multicast/root.c</source>
-      <commands>make -j root.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_SMRF</commands>
+      <commands>make TARGET=cooja clean
+make -j root.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_SMRF</commands>
       <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
       <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
       <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
diff --git a/tests/07-simulation-base/17-cooja-multicast-11-hops-esmrf.csc b/tests/07-simulation-base/17-cooja-multicast-11-hops-esmrf.csc
index 14b74b41ed08c090800a218d94aa7fd7063e7a82..c874b993038469e7c6121f31d75975eb500218b0 100644
--- a/tests/07-simulation-base/17-cooja-multicast-11-hops-esmrf.csc
+++ b/tests/07-simulation-base/17-cooja-multicast-11-hops-esmrf.csc
@@ -24,7 +24,8 @@
       <identifier>mtype612</identifier>
       <description>Root/sender</description>
       <source>[CONTIKI_DIR]/examples/multicast/root.c</source>
-      <commands>make -j root.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_ESMRF</commands>
+      <commands>make TARGET=cooja clean
+make -j root.cooja TARGET=cooja DEFINES=UIP_MCAST6_CONF_ENGINE=UIP_MCAST6_ENGINE_ESMRF</commands>
       <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
       <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
       <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
diff --git a/tests/07-simulation-base/18-cooja-multicast-31-hops.csc b/tests/07-simulation-base/18-cooja-multicast-31-hops.csc
index 86ae6916f2e151ea1d8615fdb54498c11d7913e4..922d1ddb488823f375c451fb7d7762d347bdbc7e 100644
--- a/tests/07-simulation-base/18-cooja-multicast-31-hops.csc
+++ b/tests/07-simulation-base/18-cooja-multicast-31-hops.csc
@@ -24,7 +24,8 @@
       <identifier>mtype816</identifier>
       <description>Root/sender</description>
       <source>[CONTIKI_DIR]/examples/multicast/root.c</source>
-      <commands>make -j root.cooja TARGET=cooja</commands>
+      <commands>make TARGET=cooja clean
+make -j root.cooja TARGET=cooja</commands>
       <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
       <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
       <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
diff --git a/tests/07-simulation-base/23-rpl-tsch-z1.csc b/tests/07-simulation-base/23-rpl-tsch-z1.csc
new file mode 100644
index 0000000000000000000000000000000000000000..170300f55080c31d8613921788bcb534fd1f4b13
--- /dev/null
+++ b/tests/07-simulation-base/23-rpl-tsch-z1.csc
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<simconf>
+  <project EXPORT="discard">[APPS_DIR]/mrm</project>
+  <project EXPORT="discard">[APPS_DIR]/mspsim</project>
+  <project EXPORT="discard">[APPS_DIR]/avrora</project>
+  <project EXPORT="discard">[APPS_DIR]/serial_socket</project>
+  <project EXPORT="discard">[APPS_DIR]/powertracker</project>
+  <simulation>
+    <title>RPL+TSCH (Z1)</title>
+    <randomseed>1</randomseed>
+    <motedelay_us>1000000</motedelay_us>
+    <radiomedium>
+      org.contikios.cooja.radiomediums.UDGM
+      <transmitting_range>50.0</transmitting_range>
+      <interference_range>100.0</interference_range>
+      <success_ratio_tx>1.0</success_ratio_tx>
+      <success_ratio_rx>1.0</success_ratio_rx>
+    </radiomedium>
+    <events>
+      <logoutput>40000</logoutput>
+    </events>
+    <motetype>
+      org.contikios.cooja.mspmote.Z1MoteType
+      <identifier>z11</identifier>
+      <description>Z1 Mote Type #z11</description>
+      <source EXPORT="discard">[CONTIKI_DIR]/examples/6tisch/simple-node/node.c</source>
+      <commands EXPORT="discard">make TARGET=z1 clean
+      make -j node.z1 TARGET=z1 MAKE_WITH_ORCHESTRA=0 MAKE_WITH_SECURITY=0 MAKE_WITH_PERIODIC_ROUTES_PRINT=1</commands>
+      <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.IPAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
+      <moteinterface>org.contikios.cooja.mspmote.interfaces.MspClock</moteinterface>
+      <moteinterface>org.contikios.cooja.mspmote.interfaces.MspMoteID</moteinterface>
+      <moteinterface>org.contikios.cooja.mspmote.interfaces.Msp802154Radio</moteinterface>
+      <moteinterface>org.contikios.cooja.mspmote.interfaces.MspDefaultSerial</moteinterface>
+      <moteinterface>org.contikios.cooja.mspmote.interfaces.MspLED</moteinterface>
+      <moteinterface>org.contikios.cooja.mspmote.interfaces.MspDebugOutput</moteinterface>
+    </motetype>
+    <mote>
+      <breakpoints />
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>-1.285769821276336</x>
+        <y>38.58045647334346</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.mspmote.interfaces.MspMoteID
+        <id>1</id>
+      </interface_config>
+      <motetype_identifier>z11</motetype_identifier>
+    </mote>
+    <mote>
+      <breakpoints />
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>-19.324109516886306</x>
+        <y>76.23135780254927</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.mspmote.interfaces.MspMoteID
+        <id>2</id>
+      </interface_config>
+      <motetype_identifier>z11</motetype_identifier>
+    </mote>
+    <mote>
+      <breakpoints />
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>5.815501305791592</x>
+        <y>76.77463755494317</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.mspmote.interfaces.MspMoteID
+        <id>3</id>
+      </interface_config>
+      <motetype_identifier>z11</motetype_identifier>
+    </mote>
+    <mote>
+      <breakpoints />
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>31.920697784030082</x>
+        <y>50.5212265977149</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.mspmote.interfaces.MspMoteID
+        <id>4</id>
+      </interface_config>
+      <motetype_identifier>z11</motetype_identifier>
+    </mote>
+    <mote>
+      <breakpoints />
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>47.21747673247198</x>
+        <y>30.217765340599726</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.mspmote.interfaces.MspMoteID
+        <id>5</id>
+      </interface_config>
+      <motetype_identifier>z11</motetype_identifier>
+    </mote>
+  </simulation>
+  <plugin>
+    org.contikios.cooja.plugins.SimControl
+    <width>242</width>
+    <z>4</z>
+    <height>160</height>
+    <location_x>11</location_x>
+    <location_y>241</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.Visualizer
+    <plugin_config>
+      <moterelations>true</moterelations>
+      <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin>
+      <skin>org.contikios.cooja.plugins.skins.GridVisualizerSkin</skin>
+      <skin>org.contikios.cooja.plugins.skins.TrafficVisualizerSkin</skin>
+      <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin>
+      <viewport>1.7405603810040515 0.0 0.0 1.7405603810040515 47.95980153208088 -42.576134155447555</viewport>
+    </plugin_config>
+    <width>236</width>
+    <z>3</z>
+    <height>230</height>
+    <location_x>1</location_x>
+    <location_y>1</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.LogListener
+    <plugin_config>
+      <filter>ID:1</filter>
+      <formatted_time />
+      <coloring />
+    </plugin_config>
+    <width>1031</width>
+    <z>0</z>
+    <height>394</height>
+    <location_x>273</location_x>
+    <location_y>6</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.TimeLine
+    <plugin_config>
+      <mote>0</mote>
+      <mote>1</mote>
+      <mote>2</mote>
+      <mote>3</mote>
+      <mote>4</mote>
+      <showRadioRXTX />
+      <showRadioHW />
+      <showLEDs />
+      <zoomfactor>16529.88882215865</zoomfactor>
+    </plugin_config>
+    <width>1304</width>
+    <z>2</z>
+    <height>311</height>
+    <location_x>0</location_x>
+    <location_y>412</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.ScriptRunner
+    <plugin_config>
+      <script>TIMEOUT(360000); /* Time out after 6 minutes */&#xD;
+/* Wait until a node (can only be the DAGRoot) has&#xD;
+ * 5 routing entries including one for the root (i.e. can reach every node) */&#xD;
+log.log("Waiting for routing links to fill\n");&#xD;
+while(true) {;&#xD;
+  WAIT_UNTIL(id == 1 &amp;&amp; msg.contains("Routing links"));&#xD;
+  log.log(msg + "\n");&#xD;
+  if(msg.contains("Routing links: 5")) {&#xD;
+    log.testOK(); /* Report test success and quit */&#xD;
+  }&#xD;
+  YIELD();&#xD;
+}</script>
+      <active>true</active>
+    </plugin_config>
+    <width>764</width>
+    <z>1</z>
+    <height>995</height>
+    <location_x>963</location_x>
+    <location_y>111</location_y>
+  </plugin>
+</simconf>
diff --git a/tests/07-simulation-base/code-ipv6/receiver/udp-receiver.c b/tests/07-simulation-base/code-ipv6/receiver/udp-receiver.c
index e84c57637db43b12c344037d1328633c7815c1f7..0a3b16b15d12919b18ce4926dec7600bca04df0f 100644
--- a/tests/07-simulation-base/code-ipv6/receiver/udp-receiver.c
+++ b/tests/07-simulation-base/code-ipv6/receiver/udp-receiver.c
@@ -36,10 +36,13 @@ PROCESS_THREAD(udp_process, ev, data)
   static struct etimer send_timer;
   uip_ipaddr_t addr;
   static int alive;
+  const uip_ipaddr_t *default_prefix;
 
   PROCESS_BEGIN();
 
-  uip_ip6addr(&addr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 2);
+  default_prefix = uip_ds6_default_prefix();
+  uip_ip6addr_copy(&addr, default_prefix);
+  addr.u16[7] = UIP_HTONS(2);
   uip_ds6_addr_add(&addr, 0, ADDR_AUTOCONF);
 
   simple_udp_register(&broadcast_connection, UDP_PORT,
diff --git a/tests/07-simulation-base/code-ipv6/sender/unicast-sender.c b/tests/07-simulation-base/code-ipv6/sender/unicast-sender.c
index 4e2e664b343ba9dbbd85c595818a7890a650867f..e56daa34292c5b857df3fbfe159db57b59c093e1 100644
--- a/tests/07-simulation-base/code-ipv6/sender/unicast-sender.c
+++ b/tests/07-simulation-base/code-ipv6/sender/unicast-sender.c
@@ -51,12 +51,15 @@ PROCESS_THREAD(udp_process, ev, data)
   etimer_set(&periodic_timer, SEND_INTERVAL);
 
   while(1) {
+    const uip_ipaddr_t *default_prefix;
     uint8_t buf[SIZE];
     PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&periodic_timer));
     etimer_reset(&periodic_timer);
 
     printf("Sending unicast\n");
-    uip_ip6addr(&addr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 2);
+    default_prefix = uip_ds6_default_prefix();
+    uip_ip6addr_copy(&addr, default_prefix);
+    addr.u16[7] = UIP_HTONS(2);
     simple_udp_sendto(&broadcast_connection, buf, sizeof(buf), &addr);
   }
 
diff --git a/tests/07-simulation-base/hello-world.js b/tests/07-simulation-base/hello-world.js
new file mode 100644
index 0000000000000000000000000000000000000000..5afaabe18ca07ae2bc85c9fbb7cbc91c29c8db7c
--- /dev/null
+++ b/tests/07-simulation-base/hello-world.js
@@ -0,0 +1,9 @@
+TIMEOUT(5000);
+
+while(true) {
+  log.log("> " + msg + "\n");
+  if (msg.equals('Hello, world')) {
+    log.testOK();
+  }
+  YIELD();
+}
diff --git a/tests/08-native-runs/02-mqtt-client.sh b/tests/08-native-runs/02-mqtt-client.sh
index cb1ee937af777d0fb6b42365610f8989d89dd925..1c3b089f034d30024e3ec28bfdf45a36eecadab3 100755
--- a/tests/08-native-runs/02-mqtt-client.sh
+++ b/tests/08-native-runs/02-mqtt-client.sh
@@ -28,7 +28,7 @@ sleep 2
 
 # Starting Contiki-NG native node
 echo "Starting native node"
-make -C $CODE_DIR TARGET=native \
+make -C $CODE_DIR -B TARGET=native \
   DEFINES=MQTT_CLIENT_CONF_ORG_ID=\\\"travis-test\\\",MQTT_CLIENT_CONF_LOG_LEVEL=LOG_LEVEL_DBG \
   > make.log 2> make.err
 sudo $CODE_DIR/$CODE.native > $CLIENT_LOG 2> $CLIENT_ERR &
diff --git a/tests/09-ipv6/09-ping-lla-ula-csma-w-rpl.csc b/tests/09-ipv6/09-ping-lla-ula-csma-w-rpl.csc
new file mode 100644
index 0000000000000000000000000000000000000000..66e2a8c9a61af6ff6716db67b081d4858156d6a0
--- /dev/null
+++ b/tests/09-ipv6/09-ping-lla-ula-csma-w-rpl.csc
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<simconf>
+  <project EXPORT="discard">[APPS_DIR]/mrm</project>
+  <project EXPORT="discard">[APPS_DIR]/mspsim</project>
+  <project EXPORT="discard">[APPS_DIR]/avrora</project>
+  <project EXPORT="discard">[APPS_DIR]/serial_socket</project>
+  <project EXPORT="discard">[APPS_DIR]/powertracker</project>
+  <simulation>
+    <title>My simulation</title>
+    <speedlimit>1.0</speedlimit>
+    <randomseed>123456</randomseed>
+    <motedelay_us>1000000</motedelay_us>
+    <radiomedium>
+      org.contikios.cooja.radiomediums.UDGM
+      <transmitting_range>50.0</transmitting_range>
+      <interference_range>100.0</interference_range>
+      <success_ratio_tx>1.0</success_ratio_tx>
+      <success_ratio_rx>1.0</success_ratio_rx>
+    </radiomedium>
+    <events>
+      <logoutput>40000</logoutput>
+    </events>
+    <motetype>
+      org.contikios.cooja.contikimote.ContikiMoteType
+      <identifier>mtype787</identifier>
+      <description>Cooja Mote Type #1</description>
+      <source>[CONTIKI_DIR]/tests/09-ipv6/code/node.c</source>
+      <commands>make clean
+      make WITH_ULA=1 WITH_CSMA=1 node.cooja</commands>
+      <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
+      <symbols>false</symbols>
+    </motetype>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>14.03051207883138</x>
+        <y>82.02801380504546</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>1</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRS232
+        <history>ip-nbr~;ping fe80::202:2:2:2~;ip-nbr~;help~;je;p~;ping da~;ping~;help~;</history>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype787</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>28.22612889898729</x>
+        <y>43.60027658221718</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>2</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype787</motetype_identifier>
+    </mote>
+  </simulation>
+  <plugin>
+    org.contikios.cooja.plugins.ScriptRunner
+    <plugin_config>
+      <scriptfile>[CONTIKI_DIR]/tests/09-ipv6/js/ping-test-lla-ula.js</scriptfile>
+      <active>true</active>
+    </plugin_config>
+    <width>495</width>
+    <z>0</z>
+    <height>525</height>
+    <location_x>190</location_x>
+    <location_y>18</location_y>
+  </plugin>
+</simconf>
diff --git a/tests/09-ipv6/10-ping-lla-ula-tsch-w-rpl.csc b/tests/09-ipv6/10-ping-lla-ula-tsch-w-rpl.csc
new file mode 100644
index 0000000000000000000000000000000000000000..e6957af28dd137314a8567eb7828fc4fd2e5a55e
--- /dev/null
+++ b/tests/09-ipv6/10-ping-lla-ula-tsch-w-rpl.csc
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<simconf>
+  <project EXPORT="discard">[APPS_DIR]/mrm</project>
+  <project EXPORT="discard">[APPS_DIR]/mspsim</project>
+  <project EXPORT="discard">[APPS_DIR]/avrora</project>
+  <project EXPORT="discard">[APPS_DIR]/serial_socket</project>
+  <project EXPORT="discard">[APPS_DIR]/powertracker</project>
+  <simulation>
+    <title>My simulation</title>
+    <speedlimit>1.0</speedlimit>
+    <randomseed>123456</randomseed>
+    <motedelay_us>1000000</motedelay_us>
+    <radiomedium>
+      org.contikios.cooja.radiomediums.UDGM
+      <transmitting_range>50.0</transmitting_range>
+      <interference_range>100.0</interference_range>
+      <success_ratio_tx>1.0</success_ratio_tx>
+      <success_ratio_rx>1.0</success_ratio_rx>
+    </radiomedium>
+    <events>
+      <logoutput>40000</logoutput>
+    </events>
+    <motetype>
+      org.contikios.cooja.contikimote.ContikiMoteType
+      <identifier>mtype787</identifier>
+      <description>Cooja Mote Type #1</description>
+      <source>[CONTIKI_DIR]/tests/09-ipv6/code/node.c</source>
+      <commands>make clean
+      make WITH_ULA=1 WITH_TSCH=1 node.cooja</commands>
+      <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
+      <symbols>false</symbols>
+    </motetype>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>14.03051207883138</x>
+        <y>82.02801380504546</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>1</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRS232
+        <history>ip-nbr~;ping fe80::202:2:2:2~;ip-nbr~;help~;je;p~;ping da~;ping~;help~;</history>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype787</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>28.22612889898729</x>
+        <y>43.60027658221718</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>2</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype787</motetype_identifier>
+    </mote>
+  </simulation>
+  <plugin>
+    org.contikios.cooja.plugins.ScriptRunner
+    <plugin_config>
+      <scriptfile>[CONTIKI_DIR]/tests/09-ipv6/js/ping-test-lla-ula.js</scriptfile>
+      <active>true</active>
+    </plugin_config>
+    <width>495</width>
+    <z>0</z>
+    <height>525</height>
+    <location_x>190</location_x>
+    <location_y>18</location_y>
+  </plugin>
+</simconf>
diff --git a/tests/09-ipv6/11-ping-lla-ula-csma-wo-rpl.csc b/tests/09-ipv6/11-ping-lla-ula-csma-wo-rpl.csc
new file mode 100644
index 0000000000000000000000000000000000000000..b95a1ff4b441c27a3801a6202057520c8978d9e1
--- /dev/null
+++ b/tests/09-ipv6/11-ping-lla-ula-csma-wo-rpl.csc
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<simconf>
+  <project EXPORT="discard">[APPS_DIR]/mrm</project>
+  <project EXPORT="discard">[APPS_DIR]/mspsim</project>
+  <project EXPORT="discard">[APPS_DIR]/avrora</project>
+  <project EXPORT="discard">[APPS_DIR]/serial_socket</project>
+  <project EXPORT="discard">[APPS_DIR]/powertracker</project>
+  <simulation>
+    <title>My simulation</title>
+    <speedlimit>1.0</speedlimit>
+    <randomseed>123456</randomseed>
+    <motedelay_us>1000000</motedelay_us>
+    <radiomedium>
+      org.contikios.cooja.radiomediums.UDGM
+      <transmitting_range>50.0</transmitting_range>
+      <interference_range>100.0</interference_range>
+      <success_ratio_tx>1.0</success_ratio_tx>
+      <success_ratio_rx>1.0</success_ratio_rx>
+    </radiomedium>
+    <events>
+      <logoutput>40000</logoutput>
+    </events>
+    <motetype>
+      org.contikios.cooja.contikimote.ContikiMoteType
+      <identifier>mtype787</identifier>
+      <description>Cooja Mote Type #1</description>
+      <source>[CONTIKI_DIR]/tests/09-ipv6/code/node.c</source>
+      <commands>make clean
+      make WITH_NBR_MULTI_IPV6_ADDRS=1 WITH_ULA=1 WITH_CSMA=1 WITHOUT_RPL=1 node.cooja</commands>
+      <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
+      <symbols>false</symbols>
+    </motetype>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>14.03051207883138</x>
+        <y>82.02801380504546</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>1</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRS232
+        <history>ip-nbr~;ping fe80::202:2:2:2~;ip-nbr~;help~;je;p~;ping da~;ping~;help~;</history>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype787</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>28.22612889898729</x>
+        <y>43.60027658221718</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>2</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype787</motetype_identifier>
+    </mote>
+  </simulation>
+  <plugin>
+    org.contikios.cooja.plugins.ScriptRunner
+    <plugin_config>
+      <scriptfile>[CONTIKI_DIR]/tests/09-ipv6/js/ping-test-lla-ula.js</scriptfile>
+      <active>true</active>
+    </plugin_config>
+    <width>495</width>
+    <z>0</z>
+    <height>525</height>
+    <location_x>190</location_x>
+    <location_y>18</location_y>
+  </plugin>
+</simconf>
diff --git a/tests/09-ipv6/12-ping-lla-ula-tsch-wo-rpl.csc b/tests/09-ipv6/12-ping-lla-ula-tsch-wo-rpl.csc
new file mode 100644
index 0000000000000000000000000000000000000000..20f8a12aea7aa5ec438fb9a843c4339382a5509c
--- /dev/null
+++ b/tests/09-ipv6/12-ping-lla-ula-tsch-wo-rpl.csc
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<simconf>
+  <project EXPORT="discard">[APPS_DIR]/mrm</project>
+  <project EXPORT="discard">[APPS_DIR]/mspsim</project>
+  <project EXPORT="discard">[APPS_DIR]/avrora</project>
+  <project EXPORT="discard">[APPS_DIR]/serial_socket</project>
+  <project EXPORT="discard">[APPS_DIR]/powertracker</project>
+  <simulation>
+    <title>My simulation</title>
+    <speedlimit>1.0</speedlimit>
+    <randomseed>123456</randomseed>
+    <motedelay_us>1000000</motedelay_us>
+    <radiomedium>
+      org.contikios.cooja.radiomediums.UDGM
+      <transmitting_range>50.0</transmitting_range>
+      <interference_range>100.0</interference_range>
+      <success_ratio_tx>1.0</success_ratio_tx>
+      <success_ratio_rx>1.0</success_ratio_rx>
+    </radiomedium>
+    <events>
+      <logoutput>40000</logoutput>
+    </events>
+    <motetype>
+      org.contikios.cooja.contikimote.ContikiMoteType
+      <identifier>mtype787</identifier>
+      <description>Cooja Mote Type #1</description>
+      <source>[CONTIKI_DIR]/tests/09-ipv6/code/node.c</source>
+      <commands>make clean
+      make WITH_NBR_MULTI_IPV6_ADDRS=1 WITH_ULA=1 WITH_TSCH=1 WITHOUT_RPL=1 node.cooja</commands>
+      <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
+      <symbols>false</symbols>
+    </motetype>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>14.03051207883138</x>
+        <y>82.02801380504546</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>1</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRS232
+        <history>ip-nbr~;ping fe80::202:2:2:2~;ip-nbr~;help~;je;p~;ping da~;ping~;help~;</history>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype787</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>28.22612889898729</x>
+        <y>43.60027658221718</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>2</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype787</motetype_identifier>
+    </mote>
+  </simulation>
+  <plugin>
+    org.contikios.cooja.plugins.ScriptRunner
+    <plugin_config>
+      <scriptfile>[CONTIKI_DIR]/tests/09-ipv6/js/ping-test-lla-ula.js</scriptfile>
+      <active>true</active>
+    </plugin_config>
+    <width>495</width>
+    <z>0</z>
+    <height>525</height>
+    <location_x>190</location_x>
+    <location_y>18</location_y>
+  </plugin>
+</simconf>
diff --git a/tests/09-ipv6/code/Makefile b/tests/09-ipv6/code/Makefile
index 2c910f1cd5f82c1e953621ffc9c7c8c8e0320f54..d8f4cab55f6f74b8c7df131f5ab18a0d3b2c2d86 100644
--- a/tests/09-ipv6/code/Makefile
+++ b/tests/09-ipv6/code/Makefile
@@ -28,6 +28,10 @@ ifeq ($(WITH_TSCH),1)
   CFLAGS += -DTSCH_CONF_DEFAULT_HOPPING_SEQUENCE=TSCH_HOPPING_SEQUENCE_1_1
 endif
 
+ifeq ($(WITH_NBR_MULTI_IPV6_ADDRS),1)
+  CFLAGS += -DUIP_DS6_NBR_CONF_MULTI_IPV6_ADDRS=1
+endif
+
 PLATFORM_ONLY = cooja
 TARGET = cooja
 
diff --git a/tests/09-ipv6/code/node.c b/tests/09-ipv6/code/node.c
index f465e26424278caffb4364077bcd58eb968bced2..a99261865eb80752ac1c281eb9f5328093dda46f 100644
--- a/tests/09-ipv6/code/node.c
+++ b/tests/09-ipv6/code/node.c
@@ -44,6 +44,7 @@ PROCESS_THREAD(node_process, ev, data)
   static struct etimer et;
 #if WITH_ULA
   static uip_ipaddr_t ipaddr;
+  const uip_ipaddr_t *default_prefix;
 #endif /* WITH_ULA */
 
 #if WITH_TSCH
@@ -60,7 +61,8 @@ PROCESS_THREAD(node_process, ev, data)
 #endif /* WITH_TSCH */
 
 #if WITH_ULA
-  uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
+  default_prefix = uip_ds6_default_prefix();
+  uip_ip6addr_copy(&ipaddr, default_prefix);
   uip_ds6_prefix_add(&ipaddr, UIP_DEFAULT_PREFIX_LEN, 0, 0, 0, 0);
   uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
   uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
diff --git a/tests/09-ipv6/js/ping-test-lla-ula.js b/tests/09-ipv6/js/ping-test-lla-ula.js
new file mode 100644
index 0000000000000000000000000000000000000000..c15dcbf154344d09d3744d1161ed38527dde79c3
--- /dev/null
+++ b/tests/09-ipv6/js/ping-test-lla-ula.js
@@ -0,0 +1,72 @@
+TIMEOUT(20000, log.testFailed());
+
+dst_lla = "fe80::202:2:2:2";
+dst_ula = "fd00::202:2:2:2";
+dst_mac = "0002.0002.0002.0002";
+step = 0;
+rpl_is_enabled = false;
+
+while(1) {
+  YIELD();
+  log.log(time + " " + id + " "+ msg + "\n");
+
+  if(msg.contains("Node ID: ")) {
+    if(id == 1) {
+      write(sim.getMoteWithID(1), "rpl-set-root 1");
+    }
+    step += 1;
+  }
+
+  if(msg.contains("Setting as DAG root")) {
+    rpl_is_enabled = true;
+  }
+
+  if(step == 2 && time > 15000000) {
+    write(sim.getMoteWithID(1), "ping " + dst_lla);
+    step += 1;
+  }
+
+  if(step == 4 && time > 15000000) {
+    write(sim.getMoteWithID(1), "ping " + dst_ula);
+    step += 1;
+  }
+
+  if(msg.contains("Received ping reply")) {
+    if(step == 3) {
+      step += 1;
+    } else {
+      step += 1;
+      write(sim.getMoteWithID(1), "ip-nbr");
+    }
+  }
+
+  if(step == 6 && rpl_is_enabled) {
+    /* when RPL is enabled, we skip examining ip-nbr results */
+    log.testOK();
+  }
+
+  if(msg.contains("<->")) {
+    re = /-- | <-> |, router|, state /;
+    nc = msg.split(re);
+    ip_addr = nc[1];
+    ll_addr = nc[2];
+    is_router = nc[3];
+    state = nc[4].trim();
+    if(ll_addr == dst_mac &&
+       state == "Reachable") {
+      if(step == 6 && ip_addr == dst_lla) {
+        step += 1;
+      } else if(step == 7 && ip_addr == dst_ula) {
+        log.testOK();
+      } else {
+        /* unexpected case */
+        log.testFailed();
+      }
+    } else {
+      log.log(ip_addr + "\n");
+      log.log(ll_addr + "\n");
+      log.log(state + "\n");
+      log.testFailed();
+    }
+  }
+}
diff --git a/tests/10-ipv6-nbr/01-test-nbr-multi-addrs.sh b/tests/10-ipv6-nbr/01-test-nbr-multi-addrs.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8f73ee237149cf23ff4876889895714b850e261b
--- /dev/null
+++ b/tests/10-ipv6-nbr/01-test-nbr-multi-addrs.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+TEST_NAME=01-test-nbr-multi-addrs
+
+if [ $# -eq 1 ]; then
+    # a (relative) path to CONTIKI_DIR is supposed to be given as $1
+    TEST_DIR=$1/tests/10-ipv6-nbr
+else
+    TEST_DIR=.//tests/10-ipv6-nbr
+fi
+SRC_DIR=${TEST_DIR}/nbr-multi-addrs
+EXEC_FILE_NAME=test.native
+
+make -C ${SRC_DIR} clean
+
+echo "build the test program"...
+make -C ${SRC_DIR} > ${TEST_NAME}.log
+
+echo "run the test..."
+${TEST_DIR}/${SRC_DIR}/${EXEC_FILE_NAME} | tee ${TEST_NAME}.log | \
+    grep -vE '^\[' >> ${TEST_NAME}.testlog
diff --git a/tests/10-ipv6-nbr/Makefile b/tests/10-ipv6-nbr/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..c46e5271d5a3d2374a99b4d70b09ac5e8870495b
--- /dev/null
+++ b/tests/10-ipv6-nbr/Makefile
@@ -0,0 +1 @@
+include ../Makefile.script-test
diff --git a/tests/10-ipv6-nbr/nbr-multi-addrs/Makefile b/tests/10-ipv6-nbr/nbr-multi-addrs/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..711bf09871d23745701ea5ffefb0bcfce7879d58
--- /dev/null
+++ b/tests/10-ipv6-nbr/nbr-multi-addrs/Makefile
@@ -0,0 +1,14 @@
+CONTIKI_PROJECT = test
+all: $(CONTIKI_PROJECT)
+
+CFLAGS += -DUNIT_TEST_PRINT_FUNCTION=my_test_print
+CFLAGS += -DLOG_CONF_LEVEL_IPV6=LOG_LEVEL_DBG
+CFLAGS += -DNBR_TABLE_FIND_REMOVABLE=my_always_return_null
+CFLAGS += -DUIP_DS6_NBR_CONF_MULTI_IPV6_ADDRS=1
+
+PLATFORM_ONLY = native
+TARGET = native
+MODULES += os/sys/log os/services/unit-test
+
+CONTIKI = ../../../
+include $(CONTIKI)/Makefile.include
diff --git a/tests/10-ipv6-nbr/nbr-multi-addrs/test.c b/tests/10-ipv6-nbr/nbr-multi-addrs/test.c
new file mode 100644
index 0000000000000000000000000000000000000000..2cefd7ccaf7d67cccde93f3f5cf1cfd845643d81
--- /dev/null
+++ b/tests/10-ipv6-nbr/nbr-multi-addrs/test.c
@@ -0,0 +1,260 @@
+/*
+ * Copyright (c) 2018, Yasuyuki Tanaka
+ * 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. Neither the name of the copyright holder nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``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
+ * COPYRIGHT HOLDER OR CONTRIBUTORS 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.
+ */
+
+#include <contiki.h>
+#include <sys/log.h>
+#include <lib/random.h>
+#include <net/nbr-table.h>
+#include <net/ipv6/uip-ds6-nbr.h>
+#include <unit-test/unit-test.h>
+
+#include <stdlib.h>
+
+#define LOG_MODULE "test"
+#define LOG_LEVEL LOG_LEVEL_DBG
+
+/* report function defined in unit-test.c */
+void unit_test_print_report(const unit_test_t *utp);
+
+static const uint8_t is_router = 1;
+static const uint8_t state = NBR_INCOMPLETE;
+static const nbr_table_reason_t reason = NBR_TABLE_REASON_UNDEFINED;
+
+static void remove_all_entries_in_neighbor_cache(void);
+
+PROCESS(node_process, "Node");
+AUTOSTART_PROCESSES(&node_process);
+
+void
+my_test_print(const unit_test_t *utp)
+{
+  unit_test_print_report(utp);
+  if(utp->result == unit_test_failure) {
+    printf("\nTEST FAILED\n");
+    exit(1); /* exit by failure */
+  }
+}
+
+/* my_always_return_null() is set to NBR_TABLE_FIND_REMOVABLE */
+const linkaddr_t *
+my_always_return_null(nbr_table_reason_t reason, void *data)
+{
+  return NULL;
+}
+
+void
+remove_all_entries_in_neighbor_cache(void)
+{
+  uip_ds6_nbr_t *nbr, *next_nbr;
+  for(nbr = uip_ds6_nbr_head(); nbr != NULL; nbr = next_nbr) {
+    next_nbr = uip_ds6_nbr_next(nbr);
+    uip_ds6_nbr_rm(nbr);
+  }
+  /*
+   * uip_ds6_nbr_rm() cannot free the memory for an entry in nbr-table. There is
+   * no API to free or deallocate unused nbr-table entry. Because of that,
+   * nbr-table has some link-layer addresses even though this function removes
+   * all the neighbor cache entries.
+   */
+}
+
+UNIT_TEST_REGISTER(add_v6addrs_to_neighbor,
+                   "add IPv6 addresses to a single neighbor");
+UNIT_TEST(add_v6addrs_to_neighbor)
+{
+  uip_ipaddr_t ipaddr;
+  uip_lladdr_t lladdr;
+  uip_ds6_nbr_t *nbr;
+  const uip_lladdr_t *ret_lladdr;
+
+  memset(&ipaddr, 0, sizeof(ipaddr));
+  memset(&lladdr, 0, sizeof(lladdr));
+
+  UNIT_TEST_BEGIN();
+
+  /* make sure the neighbor cache table is empty */
+  remove_all_entries_in_neighbor_cache();
+  UNIT_TEST_ASSERT(uip_ds6_nbr_head() == NULL);
+  UNIT_TEST_ASSERT(uip_ds6_nbr_num() == 0);
+
+  /* prepare a link-layer address */
+  LOG_DBG("link-layer addr: ");
+  LOG_DBG_LLADDR((const linkaddr_t *)&lladdr);
+  LOG_DBG_("\n");
+
+  for(int i = 0; i <= UIP_DS6_NBR_MAX_6ADDRS_PER_NBR; i++) {
+    ipaddr.u8[0] = i;
+    LOG_DBG("adding ipv6 addr (");
+    LOG_DBG_6ADDR(&ipaddr);
+    LOG_DBG_("[i=%u])\n", i);
+
+    /* add a binding of the IPv6 address and the MAC address */
+    nbr = uip_ds6_nbr_add(&ipaddr, &lladdr, is_router, state, reason, NULL);
+    if(i < UIP_DS6_NBR_MAX_6ADDRS_PER_NBR) {
+      UNIT_TEST_ASSERT(nbr != NULL);
+      UNIT_TEST_ASSERT(memcmp(&nbr->ipaddr, &ipaddr, sizeof(ipaddr)) == 0);
+      UNIT_TEST_ASSERT(nbr->state == state);
+      UNIT_TEST_ASSERT(uip_ds6_nbr_num() == (i + 1));
+      /*
+       * for some reason, nbr->isrouter is not set if both UIP_ND6_SEND_RA and
+       * !UIP_CONF_ROUTER is 0 (see uip-ds6-nbr.c)
+       */
+      // UNIT_TEST_ASSERT(nbr->isrouter == is_router);
+      ret_lladdr = uip_ds6_nbr_lladdr_from_ipaddr((const uip_ipaddr_t *)&ipaddr);
+      UNIT_TEST_ASSERT(ret_lladdr != NULL);
+      UNIT_TEST_ASSERT(memcmp(ret_lladdr, &lladdr, sizeof(lladdr)) == 0);
+
+    } else {
+      /* i == UIP_DS6_NBR_MAX_6ADDRS_PER_NBR; the address shouldn't be added */
+      UNIT_TEST_ASSERT(nbr == NULL);
+    }
+  }
+
+  UNIT_TEST_END();
+}
+
+UNIT_TEST_REGISTER(remove_v6addrs_of_neighbor,
+                   "remove IPv6 addresses associated with a single neighbor");
+UNIT_TEST(remove_v6addrs_of_neighbor)
+{
+  uip_ipaddr_t ipaddr;
+  uip_lladdr_t lladdr;
+  uip_ds6_nbr_t *nbr, *next_nbr;
+
+  memset(&ipaddr, 0, sizeof(ipaddr));
+  memset(&lladdr, 0, sizeof(lladdr));
+
+  UNIT_TEST_BEGIN();
+
+  /* make sure the neighbor cache table is empty */
+  remove_all_entries_in_neighbor_cache();
+  UNIT_TEST_ASSERT(uip_ds6_nbr_head() == NULL);
+  UNIT_TEST_ASSERT(uip_ds6_nbr_num() == 0);
+
+  /* prepare a link-layer address */
+  LOG_DBG("link-layer addr: ");
+  LOG_DBG_LLADDR((const linkaddr_t *)&lladdr);
+  LOG_DBG_("\n");
+
+  /* fill the neighbor entry associated with the link-layer address */
+  for(int i = 0; i < UIP_DS6_NBR_MAX_6ADDRS_PER_NBR; i++) {
+    ipaddr.u8[0] = i;
+    nbr = uip_ds6_nbr_add(&ipaddr, &lladdr, is_router, state, reason, NULL);
+    UNIT_TEST_ASSERT(nbr != NULL);
+    UNIT_TEST_ASSERT(uip_ds6_nbr_num() == (i + 1));
+  }
+
+  /* remove IPv6 addresses for the link-layer address one by one */
+  for(nbr = uip_ds6_nbr_head(); nbr != NULL; nbr = next_nbr) {
+    LOG_DBG("removing nbr:%p\n", nbr);
+    next_nbr = uip_ds6_nbr_next(nbr);
+    UNIT_TEST_ASSERT(uip_ds6_nbr_rm(nbr) == 1);
+  }
+  UNIT_TEST_ASSERT(uip_ds6_nbr_num() == 0);
+  UNIT_TEST_ASSERT(uip_ds6_nbr_head() == NULL);
+
+  UNIT_TEST_END();
+
+}
+
+UNIT_TEST_REGISTER(fill_neighbor_cache_table,
+                   "fill the neighbor cache table");
+UNIT_TEST(fill_neighbor_cache_table)
+{
+  /*
+   * We should be able to add the same number of link-layer addresses as
+   * NBR_TABLE_MAX_NEIGHBORS. In addition, we should be add the same number of
+   * IPv6 addresses per link-layer address as
+   * UIP_DS6_NBR_CONF_MAX_6ADDRS_PER_NBR.
+   */
+  uip_ipaddr_t ipaddr;
+  uip_lladdr_t lladdr;
+  uip_ds6_nbr_t *nbr;
+
+  memset(&ipaddr, 0, sizeof(ipaddr));
+  memset(&lladdr, 0, sizeof(lladdr));
+
+  UNIT_TEST_BEGIN();
+
+  /* make sure the neighbor cache table is empty */
+  remove_all_entries_in_neighbor_cache();
+  UNIT_TEST_ASSERT(uip_ds6_nbr_head() == NULL);
+  UNIT_TEST_ASSERT(uip_ds6_nbr_num() == 0);
+
+  for(int i = 0; i <= NBR_TABLE_MAX_NEIGHBORS; i++) {
+    lladdr.addr[0] = i & 0xFF;
+    lladdr.addr[1] = i >> 8;
+    for(int j = 0; j <= UIP_DS6_NBR_MAX_6ADDRS_PER_NBR; j++) {
+      ipaddr.u8[0] = i & 0xFF;
+      ipaddr.u8[1] = i >> 8;
+      ipaddr.u8[2] = j;
+      LOG_DBG("adding ipv6 addr (");
+      LOG_DBG_6ADDR(&ipaddr);
+      LOG_DBG_(") to link-layer addr (");
+      LOG_DBG_LLADDR((const linkaddr_t *)&lladdr);
+      LOG_DBG_(") [i=%u,j=%u]\n", i, j);
+
+      nbr = uip_ds6_nbr_add(&ipaddr, &lladdr, is_router, state, reason, NULL);
+      if((i < NBR_TABLE_MAX_NEIGHBORS) &&
+         (j < UIP_DS6_NBR_MAX_6ADDRS_PER_NBR)) {
+        UNIT_TEST_ASSERT(nbr != NULL);
+      } else if(i == NBR_TABLE_MAX_NEIGHBORS) {
+        /* we should not be able to add a link-layer address any more */
+        UNIT_TEST_ASSERT(j == 0);
+        UNIT_TEST_ASSERT(nbr == NULL);
+        break;
+      } else if(j == UIP_DS6_NBR_MAX_6ADDRS_PER_NBR) {
+        /* we should not be able to add an IPv6 address any more */
+        UNIT_TEST_ASSERT(i < NBR_TABLE_MAX_NEIGHBORS);
+        UNIT_TEST_ASSERT(nbr == NULL);
+        break;
+      } else {
+        /* shouldn't come here */
+        UNIT_TEST_ASSERT(false);
+      }
+    }
+  }
+
+  UNIT_TEST_END();
+}
+
+PROCESS_THREAD(node_process, ev, data)
+{
+  PROCESS_BEGIN();
+
+  UNIT_TEST_RUN(add_v6addrs_to_neighbor);
+  UNIT_TEST_RUN(remove_v6addrs_of_neighbor);
+  UNIT_TEST_RUN(fill_neighbor_cache_table);
+
+  printf("\nTEST SUCCEEDED\n");
+  exit(0); /* success: all the test passed */
+
+  PROCESS_END();
+}
diff --git a/tests/13-ieee802154/code-6tisch/common.c b/tests/13-ieee802154/code-6tisch/common.c
index 8572b4a1948d03b164e65dd7851aa34580cb073a..279d09a159c6e1176f821297b5c26475f63f1ac2 100644
--- a/tests/13-ieee802154/code-6tisch/common.c
+++ b/tests/13-ieee802154/code-6tisch/common.c
@@ -38,6 +38,8 @@
 #include "lib/simEnvChange.h"
 #include "sys/cooja_mt.h"
 
+#define TEST_MAC_MAX_PAYLOAD_LEN 100
+
 static uint8_t send_is_called;
 
 void
@@ -73,11 +75,36 @@ send(mac_callback_t sent_callback, void *ptr)
   send_is_called = 1;
 }
 
+static void
+input(void)
+{
+  /* do nothing */
+}
+
+static int
+on(void)
+{
+  return 1; /* always on */
+}
+
+static int
+off(void)
+{
+  return 0; /* never be turned off */
+}
+
+static int
+max_payload(void)
+{
+  return TEST_MAC_MAX_PAYLOAD_LEN;
+}
+
 const struct mac_driver test_mac_driver = {
   "Test MAC",
   init,
   send,
-  NULL,
-  NULL,
-  NULL
+  input,
+  on,
+  off,
+  max_payload,
 };
diff --git a/tests/14-rpl-lite/02-rpl-root-reboot-2.csc b/tests/14-rpl-lite/02-rpl-root-reboot-2.csc
new file mode 100644
index 0000000000000000000000000000000000000000..a0ed17bd1ac2516069c7cbb3ad6bc1e9e8c1dcb2
--- /dev/null
+++ b/tests/14-rpl-lite/02-rpl-root-reboot-2.csc
@@ -0,0 +1,295 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<simconf>
+  <project EXPORT="discard">[APPS_DIR]/mrm</project>
+  <project EXPORT="discard">[APPS_DIR]/mspsim</project>
+  <project EXPORT="discard">[APPS_DIR]/avrora</project>
+  <project EXPORT="discard">[APPS_DIR]/serial_socket</project>
+  <project EXPORT="discard">[APPS_DIR]/powertracker</project>
+  <simulation>
+    <title>My simulation</title>
+    <speedlimit>10.0</speedlimit>
+    <randomseed>123456</randomseed>
+    <motedelay_us>1000000</motedelay_us>
+    <radiomedium>
+      org.contikios.cooja.radiomediums.UDGM
+      <transmitting_range>50.0</transmitting_range>
+      <interference_range>100.0</interference_range>
+      <success_ratio_tx>1.0</success_ratio_tx>
+      <success_ratio_rx>1.0</success_ratio_rx>
+    </radiomedium>
+    <events>
+      <logoutput>40000</logoutput>
+    </events>
+    <motetype>
+      org.contikios.cooja.contikimote.ContikiMoteType
+      <identifier>mtype34</identifier>
+      <description>mote</description>
+      <source>[CONTIKI_DIR]/examples/libs/shell/example.c</source>
+      <commands>make TARGET=cooja clean
+make example.cooja TARGET=cooja MAKE_ROUTING=MAKE_ROUTING_RPL_LITE -j</commands>
+      <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
+      <symbols>false</symbols>
+    </motetype>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>50.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>3</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype34</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>100.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>2</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype34</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>150.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>1</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRS232
+        <history>ip-addr~;routes~;routing~;</history>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype34</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>0.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>4</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype34</motetype_identifier>
+    </mote>
+  </simulation>
+  <plugin>
+    org.contikios.cooja.plugins.SimControl
+    <width>280</width>
+    <z>0</z>
+    <height>160</height>
+    <location_x>400</location_x>
+    <location_y>0</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.Visualizer
+    <plugin_config>
+      <moterelations>true</moterelations>
+      <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin>
+      <skin>org.contikios.cooja.plugins.skins.GridVisualizerSkin</skin>
+      <skin>org.contikios.cooja.plugins.skins.TrafficVisualizerSkin</skin>
+      <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin>
+      <skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin>
+      <viewport>0.9090909090909091 0.0 0.0 0.9090909090909091 125.81818181818181 173.0</viewport>
+    </plugin_config>
+    <width>400</width>
+    <z>4</z>
+    <height>400</height>
+    <location_x>1</location_x>
+    <location_y>1</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.LogListener
+    <plugin_config>
+      <filter />
+      <formatted_time />
+      <coloring />
+    </plugin_config>
+    <width>604</width>
+    <z>3</z>
+    <height>784</height>
+    <location_x>400</location_x>
+    <location_y>160</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.Notes
+    <plugin_config>
+      <notes>Enter notes here</notes>
+      <decorations>true</decorations>
+    </plugin_config>
+    <width>944</width>
+    <z>1</z>
+    <height>160</height>
+    <location_x>680</location_x>
+    <location_y>0</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.ScriptRunner
+    <plugin_config>
+      <script>var last_msg = 0;
+var root_id = 4;
+var ip_addresses = [];
+var rpl_done = 60000; // 1 minute - expected time for all motes to be part of rpl instance
+
+function MY_GENERATE_MSG(wait, string)
+{
+    last_msg += wait;
+    GENERATE_MSG(last_msg, string);
+}
+
+/* All motes starts from scratch */
+MY_GENERATE_MSG(1000, "set root");
+MY_GENERATE_MSG(rpl_done, "get ip addresses");
+MY_GENERATE_MSG(1000, "check ip addresses");
+
+/* Root restarts and acts as root before rejoining existing rpl instance */
+MY_GENERATE_MSG(1000, "remove root " + root_id);
+MY_GENERATE_MSG(1000, "add root " + root_id);
+MY_GENERATE_MSG(1000, "set root");
+MY_GENERATE_MSG(rpl_done, "get ip addresses");
+MY_GENERATE_MSG(1000, "check ip addresses");
+/* Set root 2nd time should be ignored */
+MY_GENERATE_MSG(100, "set root");
+MY_GENERATE_MSG(1000, "get ip addresses");
+MY_GENERATE_MSG(1000, "check ip addresses");
+
+/* Root restarts and rejoins existing rpl instance */
+MY_GENERATE_MSG(1000, "remove root " + root_id);
+MY_GENERATE_MSG(1000, "add root " + root_id);
+MY_GENERATE_MSG(rpl_done, "get ip addresses");
+MY_GENERATE_MSG(1000, "check ip addresses");
+/* Root starts acting as root again */
+MY_GENERATE_MSG(1000, "set root");
+MY_GENERATE_MSG(rpl_done, "get ip addresses");
+MY_GENERATE_MSG(1000, "check ip addresses");
+
+/* Sink test */
+
+/* End test */
+MY_GENERATE_MSG(1000, "end test");
+
+while(true) {
+    YIELD();
+    if(msg.equals("set root")) {
+        m = sim.getMoteWithID(root_id);
+        write(m, "rpl-set-root 1");
+        log.log("root set\n");
+    } else if(msg.contains("get ip addresses")) {
+        var motes = sim.getMotes();
+        for(var i in motes) {
+			write(motes[i], "ip-addr");
+        }
+    } else if(msg.contains("-- fd00::20")) {
+		ip_addresses.push(msg);
+    } else if(msg.startsWith("check ip addresses")) {
+        var motes = sim.getMotes();
+        var motes_found = [];
+        for(var i in motes) {
+			var ip_address = "fd00::" + (motes[i].getID() + 200);
+			for(var j in ip_addresses) {
+				if(ip_addresses[j].contains(ip_address)) {
+					motes_found.push(motes[i].getID());
+					break;
+				}
+			}
+        }
+		if(motes.length == motes_found.length) {
+			log.log("all motes are in rpl\n");
+		} else {
+			log.log("some motes is missing, found:\n" + motes_found + "\n");
+			if(!msg.contains("skip fail")) {
+				log.testFailed(); /* Report test failure and quit */
+			}
+		}
+        ip_addresses = [];
+    } else if(msg.startsWith("remove root")) {
+		//TODO: Use id from generated msg
+        m = sim.getMoteWithID(root_id);
+        sim.removeMote(m);
+        log.log("root removed\n");
+		//TODO: Save type and position, so it can be used in add
+    } else if(msg.startsWith("add root")) {
+		//TODO: Use id from generated msg
+		//TODO: Use saved type and position
+        m = sim.getMoteTypes()[0].generateMote(sim);
+        m.getInterfaces().getMoteID().setMoteID(root_id);
+        sim.addMote(m);
+        log.log("root added\n");
+    } else if(msg.equals("end test")) {
+      break;
+    }
+}
+
+log.testOK(); /* Report test success and quit */</script>
+      <active>true</active>
+    </plugin_config>
+    <width>617</width>
+    <z>2</z>
+    <height>785</height>
+    <location_x>1007</location_x>
+    <location_y>160</location_y>
+  </plugin>
+</simconf>
+
diff --git a/tests/14-rpl-lite/code/receiver-node.c b/tests/14-rpl-lite/code/receiver-node.c
index b5265d3f7f3f8bebd57d503a5d43a35d0e48ee33..b5cd26a15de58f82883bcbf4d0e666885bd8a468 100644
--- a/tests/14-rpl-lite/code/receiver-node.c
+++ b/tests/14-rpl-lite/code/receiver-node.c
@@ -73,8 +73,9 @@ set_global_address(void)
   static uip_ipaddr_t ipaddr;
   int i;
   uint8_t state;
+  const uip_ipaddr_t *default_prefix = uip_ds6_default_prefix();
 
-  uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
+  uip_ip6addr_copy(&ipaddr, default_prefix);
   uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
   uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
 
diff --git a/tests/14-rpl-lite/code/sender-node.c b/tests/14-rpl-lite/code/sender-node.c
index 3507581105875ec8d5641fcc6ba2235cc39a834f..00bd6d5c58c02a01df3dafa6b537f2ba2d86709b 100644
--- a/tests/14-rpl-lite/code/sender-node.c
+++ b/tests/14-rpl-lite/code/sender-node.c
@@ -71,8 +71,9 @@ set_global_address(void)
   uip_ipaddr_t ipaddr;
   int i;
   uint8_t state;
+  const uip_ipaddr_t *default_prefix = uip_ds6_default_prefix();
 
-  uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
+  uip_ip6addr_copy(&ipaddr, default_prefix);
   uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
   uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
 
@@ -92,6 +93,7 @@ PROCESS_THREAD(sender_node_process, ev, data)
   static struct etimer periodic_timer;
   static struct etimer send_timer;
   uip_ipaddr_t addr;
+  const uip_ipaddr_t *default_prefix;
 
   PROCESS_BEGIN();
 
@@ -109,7 +111,13 @@ PROCESS_THREAD(sender_node_process, ev, data)
 
     PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&send_timer));
 
-    uip_ip6addr(&addr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0x0201, 0x001, 0x001, 0x001);
+    default_prefix = uip_ds6_default_prefix();
+    uip_ip6addr_copy(&addr, default_prefix);
+
+    addr.u16[4] = UIP_HTONS(0x0201);
+    addr.u16[5] = UIP_HTONS(0x0001);
+    addr.u16[6] = UIP_HTONS(0x0001);
+    addr.u16[7] = UIP_HTONS(0x0001);
 
     {
       static unsigned int message_number;
diff --git a/tests/15-rpl-classic/02-rpl-root-reboot-2.csc b/tests/15-rpl-classic/02-rpl-root-reboot-2.csc
new file mode 100644
index 0000000000000000000000000000000000000000..7f8b827837177d4aab26fa08ad444416a02e3add
--- /dev/null
+++ b/tests/15-rpl-classic/02-rpl-root-reboot-2.csc
@@ -0,0 +1,295 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<simconf>
+  <project EXPORT="discard">[APPS_DIR]/mrm</project>
+  <project EXPORT="discard">[APPS_DIR]/mspsim</project>
+  <project EXPORT="discard">[APPS_DIR]/avrora</project>
+  <project EXPORT="discard">[APPS_DIR]/serial_socket</project>
+  <project EXPORT="discard">[APPS_DIR]/powertracker</project>
+  <simulation>
+    <title>My simulation</title>
+    <speedlimit>10.0</speedlimit>
+    <randomseed>123456</randomseed>
+    <motedelay_us>1000000</motedelay_us>
+    <radiomedium>
+      org.contikios.cooja.radiomediums.UDGM
+      <transmitting_range>50.0</transmitting_range>
+      <interference_range>100.0</interference_range>
+      <success_ratio_tx>1.0</success_ratio_tx>
+      <success_ratio_rx>1.0</success_ratio_rx>
+    </radiomedium>
+    <events>
+      <logoutput>40000</logoutput>
+    </events>
+    <motetype>
+      org.contikios.cooja.contikimote.ContikiMoteType
+      <identifier>mtype512</identifier>
+      <description>mote</description>
+      <source>[CONTIKI_DIR]/examples/libs/shell/example.c</source>
+      <commands>make TARGET=cooja clean
+make example.cooja TARGET=cooja MAKE_ROUTING=MAKE_ROUTING_RPL_CLASSIC -j</commands>
+      <moteinterface>org.contikios.cooja.interfaces.Position</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Battery</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiVib</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiMoteID</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRS232</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiBeeper</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.RimeAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiIPAddress</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiRadio</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiButton</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiPIR</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiClock</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiLED</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiCFS</moteinterface>
+      <moteinterface>org.contikios.cooja.contikimote.interfaces.ContikiEEPROM</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.Mote2MoteRelations</moteinterface>
+      <moteinterface>org.contikios.cooja.interfaces.MoteAttributes</moteinterface>
+      <symbols>false</symbols>
+    </motetype>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>50.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>3</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype512</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>100.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>2</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype512</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>150.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>1</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRS232
+        <history>ip-addr~;routes~;routing~;</history>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype512</motetype_identifier>
+    </mote>
+    <mote>
+      <interface_config>
+        org.contikios.cooja.interfaces.Position
+        <x>0.0</x>
+        <y>0.0</y>
+        <z>0.0</z>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiMoteID
+        <id>4</id>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiRadio
+        <bitrate>250.0</bitrate>
+      </interface_config>
+      <interface_config>
+        org.contikios.cooja.contikimote.interfaces.ContikiEEPROM
+        <eeprom>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==</eeprom>
+      </interface_config>
+      <motetype_identifier>mtype512</motetype_identifier>
+    </mote>
+  </simulation>
+  <plugin>
+    org.contikios.cooja.plugins.SimControl
+    <width>280</width>
+    <z>0</z>
+    <height>160</height>
+    <location_x>400</location_x>
+    <location_y>0</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.Visualizer
+    <plugin_config>
+      <moterelations>true</moterelations>
+      <skin>org.contikios.cooja.plugins.skins.IDVisualizerSkin</skin>
+      <skin>org.contikios.cooja.plugins.skins.GridVisualizerSkin</skin>
+      <skin>org.contikios.cooja.plugins.skins.TrafficVisualizerSkin</skin>
+      <skin>org.contikios.cooja.plugins.skins.UDGMVisualizerSkin</skin>
+      <skin>org.contikios.cooja.plugins.skins.MoteTypeVisualizerSkin</skin>
+      <viewport>0.9090909090909091 0.0 0.0 0.9090909090909091 125.81818181818181 173.0</viewport>
+    </plugin_config>
+    <width>400</width>
+    <z>4</z>
+    <height>400</height>
+    <location_x>1</location_x>
+    <location_y>1</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.LogListener
+    <plugin_config>
+      <filter />
+      <formatted_time />
+      <coloring />
+    </plugin_config>
+    <width>604</width>
+    <z>3</z>
+    <height>784</height>
+    <location_x>400</location_x>
+    <location_y>160</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.Notes
+    <plugin_config>
+      <notes>Enter notes here</notes>
+      <decorations>true</decorations>
+    </plugin_config>
+    <width>944</width>
+    <z>1</z>
+    <height>160</height>
+    <location_x>680</location_x>
+    <location_y>0</location_y>
+  </plugin>
+  <plugin>
+    org.contikios.cooja.plugins.ScriptRunner
+    <plugin_config>
+      <script>var last_msg = 0;
+var root_id = 4;
+var ip_addresses = [];
+var rpl_done = 60000; // 1 minute - expected time for all motes to be part of rpl instance
+
+function MY_GENERATE_MSG(wait, string)
+{
+    last_msg += wait;
+    GENERATE_MSG(last_msg, string);
+}
+
+/* All motes starts from scratch */
+MY_GENERATE_MSG(1000, "set root");
+MY_GENERATE_MSG(rpl_done, "get ip addresses");
+MY_GENERATE_MSG(1000, "check ip addresses");
+
+/* Root restarts and acts as root before rejoining existing rpl instance */
+MY_GENERATE_MSG(1000, "remove root " + root_id);
+MY_GENERATE_MSG(1000, "add root " + root_id);
+MY_GENERATE_MSG(1000, "set root");
+MY_GENERATE_MSG(rpl_done, "get ip addresses");
+MY_GENERATE_MSG(1000, "check ip addresses");
+/* Set root 2nd time should be ignored */
+MY_GENERATE_MSG(100, "set root");
+MY_GENERATE_MSG(1000, "get ip addresses");
+MY_GENERATE_MSG(1000, "check ip addresses");
+
+/* Root restarts and rejoins existing rpl instance */
+MY_GENERATE_MSG(1000, "remove root " + root_id);
+MY_GENERATE_MSG(1000, "add root " + root_id);
+MY_GENERATE_MSG(rpl_done, "get ip addresses");
+MY_GENERATE_MSG(1000, "check ip addresses");
+/* Root starts acting as root again */
+MY_GENERATE_MSG(1000, "set root");
+MY_GENERATE_MSG(rpl_done, "get ip addresses");
+MY_GENERATE_MSG(1000, "check ip addresses");
+
+/* Sink test */
+
+/* End test */
+MY_GENERATE_MSG(1000, "end test");
+
+while(true) {
+    YIELD();
+    if(msg.equals("set root")) {
+        m = sim.getMoteWithID(root_id);
+        write(m, "rpl-set-root 1");
+        log.log("root set\n");
+    } else if(msg.contains("get ip addresses")) {
+        var motes = sim.getMotes();
+        for(var i in motes) {
+			write(motes[i], "ip-addr");
+        }
+    } else if(msg.contains("-- fd00::20")) {
+		ip_addresses.push(msg);
+    } else if(msg.startsWith("check ip addresses")) {
+        var motes = sim.getMotes();
+        var motes_found = [];
+        for(var i in motes) {
+			var ip_address = "fd00::" + (motes[i].getID() + 200);
+			for(var j in ip_addresses) {
+				if(ip_addresses[j].contains(ip_address)) {
+					motes_found.push(motes[i].getID());
+					break;
+				}
+			}
+        }
+		if(motes.length == motes_found.length) {
+			log.log("all motes are in rpl\n");
+		} else {
+			log.log("some motes is missing, found:\n" + motes_found + "\n");
+			if(!msg.contains("skip fail")) {
+				log.testFailed(); /* Report test failure and quit */
+			}
+		}
+        ip_addresses = [];
+    } else if(msg.startsWith("remove root")) {
+		//TODO: Use id from generated msg
+        m = sim.getMoteWithID(root_id);
+        sim.removeMote(m);
+        log.log("root removed\n");
+		//TODO: Save type and position, so it can be used in add
+    } else if(msg.startsWith("add root")) {
+		//TODO: Use id from generated msg
+		//TODO: Use saved type and position
+        m = sim.getMoteTypes()[0].generateMote(sim);
+        m.getInterfaces().getMoteID().setMoteID(root_id);
+        sim.addMote(m);
+        log.log("root added\n");
+    } else if(msg.equals("end test")) {
+      break;
+    }
+}
+
+log.testOK(); /* Report test success and quit */</script>
+      <active>true</active>
+    </plugin_config>
+    <width>617</width>
+    <z>2</z>
+    <height>785</height>
+    <location_x>1007</location_x>
+    <location_y>160</location_y>
+  </plugin>
+</simconf>
+
diff --git a/tests/15-rpl-classic/code/receiver-node.c b/tests/15-rpl-classic/code/receiver-node.c
index 798aea84d2d78accc8b632a31aa8bfebe1924167..3854784d07722899d1edd20f322502845894c71a 100644
--- a/tests/15-rpl-classic/code/receiver-node.c
+++ b/tests/15-rpl-classic/code/receiver-node.c
@@ -73,8 +73,9 @@ set_global_address(void)
   static uip_ipaddr_t ipaddr;
   int i;
   uint8_t state;
+  const uip_ipaddr_t *default_prefix = uip_ds6_default_prefix();
 
-  uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
+  uip_ip6addr_copy(&ipaddr, default_prefix);
   uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
   uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
 
diff --git a/tests/15-rpl-classic/code/sender-node.c b/tests/15-rpl-classic/code/sender-node.c
index 3507581105875ec8d5641fcc6ba2235cc39a834f..00bd6d5c58c02a01df3dafa6b537f2ba2d86709b 100644
--- a/tests/15-rpl-classic/code/sender-node.c
+++ b/tests/15-rpl-classic/code/sender-node.c
@@ -71,8 +71,9 @@ set_global_address(void)
   uip_ipaddr_t ipaddr;
   int i;
   uint8_t state;
+  const uip_ipaddr_t *default_prefix = uip_ds6_default_prefix();
 
-  uip_ip6addr(&ipaddr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0, 0, 0, 0);
+  uip_ip6addr_copy(&ipaddr, default_prefix);
   uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr);
   uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF);
 
@@ -92,6 +93,7 @@ PROCESS_THREAD(sender_node_process, ev, data)
   static struct etimer periodic_timer;
   static struct etimer send_timer;
   uip_ipaddr_t addr;
+  const uip_ipaddr_t *default_prefix;
 
   PROCESS_BEGIN();
 
@@ -109,7 +111,13 @@ PROCESS_THREAD(sender_node_process, ev, data)
 
     PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&send_timer));
 
-    uip_ip6addr(&addr, UIP_DS6_DEFAULT_PREFIX, 0, 0, 0, 0x0201, 0x001, 0x001, 0x001);
+    default_prefix = uip_ds6_default_prefix();
+    uip_ip6addr_copy(&addr, default_prefix);
+
+    addr.u16[4] = UIP_HTONS(0x0201);
+    addr.u16[5] = UIP_HTONS(0x0001);
+    addr.u16[6] = UIP_HTONS(0x0001);
+    addr.u16[7] = UIP_HTONS(0x0001);
 
     {
       static unsigned int message_number;
diff --git a/tests/17-tun-rpl-br/test-native-border-router.sh b/tests/17-tun-rpl-br/test-native-border-router.sh
index e2e205f20685f0908966a2fb8a8d113415fa2fc4..08b70dd2f150bf6b5e54d2994ede11dd842d2557 100755
--- a/tests/17-tun-rpl-br/test-native-border-router.sh
+++ b/tests/17-tun-rpl-br/test-native-border-router.sh
@@ -30,7 +30,7 @@ sleep 20
 
 # Connect to the simulation
 echo "Starting native border-router"
-nohup make -C $CONTIKI/examples/rpl-border-router/ connect-router-cooja TARGET=native >> $BASENAME.nbr.log 2>&1 &
+nohup make -C $CONTIKI/examples/rpl-border-router/ -B connect-router-cooja TARGET=native >> $BASENAME.nbr.log 2>&1 &
 MPID=$!
 printf "Waiting for network formation (%d seconds)\n" "$WAIT_TIME"
 sleep $WAIT_TIME
diff --git a/tests/18-coap-lwm2m/example-lwm2m-standalone b/tests/18-coap-lwm2m/example-lwm2m-standalone
index 67b858437f7cf1e4e027d821c4c2ac15fdf2ab44..3b23ca8d6a19d281b6330d3f24afc2e1bb14ddb7 160000
--- a/tests/18-coap-lwm2m/example-lwm2m-standalone
+++ b/tests/18-coap-lwm2m/example-lwm2m-standalone
@@ -1 +1 @@
-Subproject commit 67b858437f7cf1e4e027d821c4c2ac15fdf2ab44
+Subproject commit 3b23ca8d6a19d281b6330d3f24afc2e1bb14ddb7
diff --git a/tests/19-out-of-tree-build/Makefile b/tests/19-out-of-tree-build/Makefile
index 759027062b73ae19a94438e1d3b288b029a734bb..30d7e230284016ca40df841f36bf3eec7bc288f8 100644
--- a/tests/19-out-of-tree-build/Makefile
+++ b/tests/19-out-of-tree-build/Makefile
@@ -10,7 +10,7 @@ hello-world/nrf52dk \
 hello-world/cc2538dk \
 hello-world/zoul \
 hello-world/openmote-cc2538 \
-hello-world/srf06-cc26xx \
+hello-world/cc26x0-cc13x0 \
 hello-world/jn516x \
 hello-world/simplelink:BOARD=launchpad/cc26x2r1 \
 hello-world/simplelink:BOARD=sensortag/cc2650 \
diff --git a/tools/doxygen/Doxyfile b/tools/doxygen/Doxyfile
index dab2c18e3535231adace234e50903b000356edcb..2cd7dba72c061812457a02928e80aa9670bc8577 100644
--- a/tools/doxygen/Doxyfile
+++ b/tools/doxygen/Doxyfile
@@ -807,8 +807,8 @@ EXCLUDE_SYMLINKS       = NO
 # Note that the wildcards are matched against the file with absolute path, so to
 # exclude all test directories for example use the pattern */test/*
 
-EXCLUDE_PATTERNS       = */cpu/cc26xx-cc13xx/lib/* \
-                         */cpu/cc26xx-cc13xx/rf-core/api/* \
+EXCLUDE_PATTERNS       = */cpu/cc26x0-cc13x0/lib/* \
+                         */cpu/cc26x0-cc13x0/rf-core/api/* \
                          */cpu/simplelink-cc13xx-cc26xx/lib/* \
                          */cpu/simplelink-cc13xx-cc26xx/rf-settings/* \
                          */cpu/simplelink-cc13xx-cc26xx/cc13x0-cc26x0/driverlib/* \
diff --git a/tools/sensniff b/tools/sensniff
index 3b3ac51b0a11a234a93ca50279181c648bf07976..33874210c7a3b0eb8a11363474d2bbef7ede38d2 160000
--- a/tools/sensniff
+++ b/tools/sensniff
@@ -1 +1 @@
-Subproject commit 3b3ac51b0a11a234a93ca50279181c648bf07976
+Subproject commit 33874210c7a3b0eb8a11363474d2bbef7ede38d2
diff --git a/tools/serial-io/tunslip6.c b/tools/serial-io/tunslip6.c
index 48b0ecd0ffaa8a4e1b510cea1a1cc273c739760a..61013c30c11e75e3b328f25b87ea07b567340cd8 100644
--- a/tools/serial-io/tunslip6.c
+++ b/tools/serial-io/tunslip6.c
@@ -856,14 +856,20 @@ fprintf(stderr," -s siodev      Serial device (default /dev/ttyUSB0)\n");
 fprintf(stderr," -M             Interface MTU (default and min: 1280)\n");
 fprintf(stderr," -T             Make tap interface (default is tun interface)\n");
 fprintf(stderr," -t tundev      Name of interface (default tap0 or tun0)\n");
+#ifdef __APPLE__
+fprintf(stderr," -v level       Verbosity level\n");
+#else
 fprintf(stderr," -v[level]      Verbosity level\n");
+#endif
 fprintf(stderr,"    -v0         No messages\n");
 fprintf(stderr,"    -v1         Encapsulated SLIP debug messages (default)\n");
 fprintf(stderr,"    -v2         Printable strings after they are received\n");
 fprintf(stderr,"    -v3         Printable strings and SLIP packet notifications\n");
 fprintf(stderr,"    -v4         All printable characters as they are received\n");
 fprintf(stderr,"    -v5         All SLIP packets in hex\n");
+#ifndef __APPLE__
 fprintf(stderr,"    -v          Equivalent to -v3\n");
+#endif
 fprintf(stderr," -d[basedelay]  Minimum delay between outgoing SLIP packets.\n");
 fprintf(stderr,"                Actual delay is basedelay*(#6LowPAN fragments) milliseconds.\n");
 fprintf(stderr,"                -d is equivalent to -d10.\n");
diff --git a/tools/sky/uip6-bridge/Makefile b/tools/sky/uip6-bridge/Makefile
deleted file mode 100644
index 55da6798e933a9da262f94f23f71a2730bd75d16..0000000000000000000000000000000000000000
--- a/tools/sky/uip6-bridge/Makefile
+++ /dev/null
@@ -1,39 +0,0 @@
-ifdef CONTIKI_HOME
-CONTIKI = $(CONTIKI_HOME)
-else
-ifndef CONTIKI
-CONTIKI=../../..
-endif
-endif
-
-DEFINES=WITH_SLIP=1
-
-ifndef TARGET
-TARGET=sky
-endif
-
-MODULES_REL += dev
-PROJECT_SOURCEFILES = fakeuip.c sicslow_ethernet.c
-
-all:	uip6-bridge-tap.sky
-
-upload: uip6-bridge-tap.ihex
-	cp $< $(IHEXFILE)
-	$(MAKE) sky-u.$(subst /,-,$(word $(MOTE), $(MOTES)))
-
-include $(CONTIKI)/Makefile.include
-
-../../tapslip6: ../../tapslip6.c
-	(cd ../../; $(MAKE) tapslip6)
-
-ifndef MOTE
-MOTE=1
-endif
-
-connect: ../../tapslip6
-	sudo ../../tapslip6 -t tap0 -s $(USBDEVPREFIX)$(word $(MOTE), $(CMOTES)) 127.0.0.1 255.0.0.0
-
-bridge:
-	@sudo service radvd restart || echo radvd could not be restarted
-	sudo route add -6 fd00::/64 tap0
-	sudo ip -6 address add fd00::1/64 dev tap0
diff --git a/tools/sky/uip6-bridge/dev/slip.c b/tools/sky/uip6-bridge/dev/slip.c
deleted file mode 100644
index e8062e515bff0372f1ca5619ca30b23a355126f6..0000000000000000000000000000000000000000
--- a/tools/sky/uip6-bridge/dev/slip.c
+++ /dev/null
@@ -1,323 +0,0 @@
-/* -*- C -*- */
-/*
- * Copyright (c) 2005, 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. Neither the name of the Institute nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``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 INSTITUTE OR CONTRIBUTORS 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 Contiki operating system.
- *
- */
-
-
-#include <stdio.h>
-#include <string.h>
-#include "dev/ds2411/ds2411.h"
-#include "contiki.h"
-
-#include "net/ipv6/uip.h"
-#define BUF ((struct uip_tcpip_hdr *)&uip_buf[UIP_LLH_LEN])
-
-#include "dev/slip.h"
-
-#define SLIP_END     0300
-#define SLIP_ESC     0333
-#define SLIP_ESC_END 0334
-#define SLIP_ESC_ESC 0335
-
-PROCESS(slip_process, "SLIP driver");
-
-uint8_t slip_active;
-
-#if 1
-#define SLIP_STATISTICS(statement)
-#else
-uint16_t slip_rubbish, slip_twopackets, slip_overflow, slip_ip_drop;
-#define SLIP_STATISTICS(statement) statement
-#endif
-
-/* Must be at least one byte larger than UIP_BUFSIZE! */
-#define RX_BUFSIZE (UIP_BUFSIZE - UIP_LLH_LEN + 16)
-
-enum {
-  STATE_TWOPACKETS = 0,	/* We have 2 packets and drop incoming data. */
-  STATE_OK = 1,
-  STATE_ESC = 2,
-  STATE_RUBBISH = 3,
-};
-
-/*
- * Variables begin and end manage the buffer space in a cyclic
- * fashion. The first used byte is at begin and end is one byte past
- * the last. I.e. [begin, end) is the actively used space.
- *
- * If begin != pkt_end we have a packet at [begin, pkt_end),
- * furthermore, if state == STATE_TWOPACKETS we have one more packet at
- * [pkt_end, end). If more bytes arrive in state STATE_TWOPACKETS
- * they are discarded.
- */
-
-static uint8_t state = STATE_TWOPACKETS;
-static uint16_t begin, end;
-static uint8_t rxbuf[RX_BUFSIZE];
-static uint16_t pkt_end;		/* SLIP_END tracker. */
-
-static void (* input_callback)(void) = NULL;
-static void (* tcpip_input_callback)(void) = NULL;
-/*---------------------------------------------------------------------------*/
-void
-slip_set_input_callback(void (*c)(void))
-{
-  input_callback = c;
-}
-/*---------------------------------------------------------------------------*/
-void
-slip_set_tcpip_input_callback(void (*c)(void))
-{
-  tcpip_input_callback = c;
-}
-/*---------------------------------------------------------------------------*/
-uint8_t
-slip_write(const void *_ptr, int len)
-{
-  const uint8_t *ptr = _ptr;
-  uint16_t i;
-  uint8_t c;
-
-  slip_arch_writeb(SLIP_END);
-
-  for(i = 0; i < len; ++i) {
-    c = *ptr++;
-    if(c == SLIP_END) {
-      slip_arch_writeb(SLIP_ESC);
-      c = SLIP_ESC_END;
-    } else if(c == SLIP_ESC) {
-      slip_arch_writeb(SLIP_ESC);
-      c = SLIP_ESC_ESC;
-    }
-    slip_arch_writeb(c);
-  }
-  slip_arch_writeb(SLIP_END);
-
-  return len;
-}
-/*---------------------------------------------------------------------------*/
-static void
-rxbuf_init(void)
-{
-  begin = end = pkt_end = 0;
-  state = STATE_OK;
-}
-/*---------------------------------------------------------------------------*/
-/* Upper half does the polling. */
-static uint16_t
-slip_poll_handler(uint8_t *outbuf, uint16_t blen)
-{
-  /* This is a hack and won't work across buffer edge! */
-  if(rxbuf[begin] == 'C') {
-    int i;
-    if(begin < end && (end - begin) >= 6
-       && memcmp(&rxbuf[begin], "CLIENT", 6) == 0) {
-      state = STATE_TWOPACKETS;	/* Interrupts do nothing. */
-      memset(&rxbuf[begin], 0x0, 6);
-
-      rxbuf_init();
-
-      for(i = 0; i < 13; i++) {
-	slip_arch_writeb("CLIENTSERVER\300"[i]);
-      }
-      return 0;
-    }
-  } else if(rxbuf[begin] == '?') {
-    int i, j;
-    char* hexchar = "0123456789abcdef";
-    if(begin < end && (end - begin) >= 2
-       && rxbuf[begin + 1] == 'M') {
-      state = STATE_TWOPACKETS;	/* Interrupts do nothing. */
-      rxbuf[begin] = 0;
-      rxbuf[begin + 1] = 0;
-
-      rxbuf_init();
-
-      /* this is just a test so far... just to see if it works */
-      slip_arch_writeb('!');
-      slip_arch_writeb('M');
-      for(j = 0; j < 8; j++) {
-	slip_arch_writeb(hexchar[ds2411_id[j] >> 4]);
-	slip_arch_writeb(hexchar[ds2411_id[j] & 15]);
-      }
-      slip_arch_writeb(SLIP_END);
-      return 0;
-    }
-  }
-
-  /*
-   * Interrupt can not change begin but may change pkt_end.
-   * If pkt_end != begin it will not change again.
-   */
-  if(begin != pkt_end) {
-    uint16_t len;
-
-    if(begin < pkt_end) {
-      len = pkt_end - begin;
-      if(len > blen) {
-	len = 0;
-      } else {
-	memcpy(outbuf, &rxbuf[begin], len);
-      }
-    } else {
-      len = (RX_BUFSIZE - begin) + (pkt_end - 0);
-      if(len > blen) {
-	len = 0;
-      } else {
-	unsigned i;
-	for(i = begin; i < RX_BUFSIZE; i++) {
-	  *outbuf++ = rxbuf[i];
-	}
-	for(i = 0; i < pkt_end; i++) {
-	  *outbuf++ = rxbuf[i];
-	}
-      }
-    }
-
-    /* Remove data from buffer together with the copied packet. */
-    begin = pkt_end;
-    if(state == STATE_TWOPACKETS) {
-      pkt_end = end;
-      state = STATE_OK;		/* Assume no bytes where lost! */
-
-      /* One more packet is buffered, need to be polled again! */
-      process_poll(&slip_process);
-    }
-    return len;
-  }
-
-  return 0;
-}
-/*---------------------------------------------------------------------------*/
-PROCESS_THREAD(slip_process, ev, data)
-{
-  PROCESS_BEGIN();
-
-  rxbuf_init();
-
-  while(1) {
-    PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
-
-    slip_active = 1;
-
-    /* Move packet from rxbuf to buffer provided by uIP. */
-    uip_len = slip_poll_handler(&uip_buf[UIP_LLH_LEN],
-				UIP_BUFSIZE - UIP_LLH_LEN);
-    if(uip_len > 0) {
-      if(tcpip_input_callback) {
-        tcpip_input_callback();
-      } else {
-        tcpip_input();
-      }
-    }
-  }
-
-  PROCESS_END();
-}
-/*---------------------------------------------------------------------------*/
-int
-slip_input_byte(unsigned char c)
-{
-  switch(state) {
-  case STATE_RUBBISH:
-    if(c == SLIP_END) {
-      state = STATE_OK;
-    }
-    return 0;
-
-  case STATE_TWOPACKETS:       /* Two packets are already buffered! */
-    return 0;
-
-  case STATE_ESC:
-    if(c == SLIP_ESC_END) {
-      c = SLIP_END;
-    } else if(c == SLIP_ESC_ESC) {
-      c = SLIP_ESC;
-    } else {
-      state = STATE_RUBBISH;
-      SLIP_STATISTICS(slip_rubbish++);
-      end = pkt_end;		/* remove rubbish */
-      return 0;
-    }
-    state = STATE_OK;
-    break;
-
-  case STATE_OK:
-    if(c == SLIP_ESC) {
-      state = STATE_ESC;
-      return 0;
-    } else if(c == SLIP_END) {
-	/*
-	 * We have a new packet, possibly of zero length.
-	 *
-	 * There may already be one packet buffered.
-	 */
-      if(end != pkt_end) {	/* Non zero length. */
-	if(begin == pkt_end) {	/* None buffered. */
-	  pkt_end = end;
-	} else {
-	  state = STATE_TWOPACKETS;
-	  SLIP_STATISTICS(slip_twopackets++);
-	}
-	process_poll(&slip_process);
-	return 1;
-      }
-      return 0;
-    }
-    break;
-  }
-
-  /* add_char: */
-  {
-    unsigned next;
-    next = end + 1;
-    if(next == RX_BUFSIZE) {
-      next = 0;
-    }
-    if(next == begin) {		/* rxbuf is full */
-      state = STATE_RUBBISH;
-      SLIP_STATISTICS(slip_overflow++);
-      end = pkt_end;		/* remove rubbish */
-      return 0;
-    }
-    rxbuf[end] = c;
-    end = next;
-  }
-
-  /* There could be a separate poll routine for this. */
-  if(c == 'T' && rxbuf[begin] == 'C') {
-    process_poll(&slip_process);
-    return 1;
-  }
-
-  return 0;
-}
-/*---------------------------------------------------------------------------*/
diff --git a/tools/sky/uip6-bridge/fakeuip.c b/tools/sky/uip6-bridge/fakeuip.c
deleted file mode 100644
index 84f6440ce12c9ce57656b9d17ab008995b0c4bd0..0000000000000000000000000000000000000000
--- a/tools/sky/uip6-bridge/fakeuip.c
+++ /dev/null
@@ -1,136 +0,0 @@
-
-/* Various stub functions and uIP variables other code might need to
- * compile. Allows you to save needing to compile all of uIP in just
- * to get a few things */
-
-
-#include "net/ipv6/uip.h"
-#include "net/ipv6/uip-ds6.h"
-#include <string.h>
-
-#define UIP_IP_BUF   ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-
-uip_buf_t uip_aligned_buf;
-
-uint16_t uip_len;
-
-struct uip_stats uip_stat;
-
-uip_lladdr_t uip_lladdr;
-
-uint16_t uip_htons(uint16_t val) { return UIP_HTONS(val);}
-
-uip_ds6_netif_t uip_ds6_if;
-
-/********** UIP_DS6.c **********/
-
-void
-uip_ds6_set_addr_iid(uip_ipaddr_t *ipaddr, uip_lladdr_t *lladdr)
-{
-  /* We consider only links with IEEE EUI-64 identifier or
-     IEEE 48-bit MAC addresses */
-#if (UIP_LLADDR_LEN == 8)
-  memcpy(ipaddr->u8 + 8, lladdr, UIP_LLADDR_LEN);
-  ipaddr->u8[8] ^= 0x02;
-#elif (UIP_LLADDR_LEN == 6)
-  memcpy(ipaddr->u8 + 8, lladdr, 3);
-  ipaddr->u8[11] = 0xff;
-  ipaddr->u8[12] = 0xfe;
-  memcpy(ipaddr->u8 + 13, lladdr + 3, 3);
-  ipaddr->u8[8] ^= 0x02;
-#else
-#error fakeuip.c cannot build interface address when UIP_LLADDR_LEN is not 6 or 8
-#endif
-}
-
-/*---------------------------------------------------------------------------*/
-/*
- * get a link local address -
- * state = -1 => any address is ok. Otherwise state = desired state of addr.
- * (TENTATIVE, PREFERRED, DEPRECATED)
- */
-uip_ds6_addr_t *
-uip_ds6_get_link_local(int8_t state) {
-  uip_ds6_addr_t *locaddr;
-  for(locaddr = uip_ds6_if.addr_list;
-      locaddr < uip_ds6_if.addr_list + UIP_DS6_ADDR_NB; locaddr++) {
-    if((locaddr->isused) && (state == - 1 || locaddr->state == state)
-       && (uip_is_addr_linklocal(&locaddr->ipaddr))) {
-      return locaddr;
-    }
-  }
-  return NULL;
-}
-
-uip_ds6_addr_t *
-uip_ds6_addr_add(uip_ipaddr_t *ipaddr, unsigned long vlifetime, uint8_t type)
-{
-  return NULL;
-}
-/********** UIP.c ****************/
-
-static uint16_t
-chksum(uint16_t sum, const uint8_t *data, uint16_t len)
-{
-  uint16_t t;
-  const uint8_t *dataptr;
-  const uint8_t *last_byte;
-
-  dataptr = data;
-  last_byte = data + len - 1;
-
-  while(dataptr < last_byte) {   /* At least two more bytes */
-    t = (dataptr[0] << 8) + dataptr[1];
-    sum += t;
-    if(sum < t) {
-      sum++;      /* carry */
-    }
-    dataptr += 2;
-  }
-
-  if(dataptr == last_byte) {
-    t = (dataptr[0] << 8) + 0;
-    sum += t;
-    if(sum < t) {
-      sum++;      /* carry */
-    }
-  }
-
-  /* Return sum in host byte order. */
-  return sum;
-}
-
-static uint16_t
-upper_layer_chksum(uint8_t proto)
-{
-  uint16_t upper_layer_len;
-  uint16_t sum;
-
-  upper_layer_len = (((uint16_t)(UIP_IP_BUF->len[0]) << 8) + UIP_IP_BUF->len[1]) ;
-
-  /* First sum pseudoheader. */
-  /* IP protocol and length fields. This addition cannot carry. */
-  sum = upper_layer_len + proto;
-  /* Sum IP source and destination addresses. */
-  sum = chksum(sum, (uint8_t *)&UIP_IP_BUF->srcipaddr, 2 * sizeof(uip_ipaddr_t));
-
-  /* Sum TCP header and data. */
-  sum = chksum(sum, &uip_buf[UIP_IPH_LEN + UIP_LLH_LEN],
-               upper_layer_len);
-
-  return (sum == 0) ? 0xffff : uip_htons(sum);
-}
-
-/*---------------------------------------------------------------------------*/
-uint16_t
-uip_icmp6chksum(void)
-{
-  return upper_layer_chksum(UIP_PROTO_ICMP6);
-}
-
-/*---------------------------------------------------------------------------*/
-void
-uip_ds6_link_callback(int status, int numtx)
-{
-
-}
diff --git a/tools/sky/uip6-bridge/radvd.conf b/tools/sky/uip6-bridge/radvd.conf
deleted file mode 100644
index d6dd41e2b5b143ce5056ad0ee0d859332dddfaca..0000000000000000000000000000000000000000
--- a/tools/sky/uip6-bridge/radvd.conf
+++ /dev/null
@@ -1,16 +0,0 @@
-interface tap0 {    
-	  AdvSendAdvert on;
-	  AdvLinkMTU 1280;
-	  AdvCurHopLimit 128;
-          AdvReachableTime 360000;
-          MinRtrAdvInterval 100;
-          MaxRtrAdvInterval 150;
-          AdvDefaultLifetime 200;
-          prefix AAAA::/64
-	  {
-	           AdvOnLink on;
-		   AdvAutonomous on;
-		   AdvPreferredLifetime 4294967295;
-		   AdvValidLifetime 4294967295;     
-	  };
-};
diff --git a/tools/sky/uip6-bridge/sicslow_ethernet.c b/tools/sky/uip6-bridge/sicslow_ethernet.c
deleted file mode 100644
index 7217e3229537ce043f2a7f3e136d6509148a9a98..0000000000000000000000000000000000000000
--- a/tools/sky/uip6-bridge/sicslow_ethernet.c
+++ /dev/null
@@ -1,882 +0,0 @@
-/**
- * \file sicslow_ethernet.c
- *         Routines to interface between Ethernet and 6LowPan
- *
- * \author
- *         Colin O'Flynn <coflynn@newae.com>
- *
- * \addtogroup usbstick
- */
-
-/* Copyright (c) 2008 by:
- * Colin O'Flynn coflynn@newae.com
- * Eric Gnoske egnoske@gmail.com
- * Blake Leverett bleverett@gmail.com
- * Mike Vidales mavida404@gmail.com
- * Kevin Brown kbrown3@uccs.edu
- * Nate Bohlmann nate@elfwerks.com
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * 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.
- * * Neither the name of the copyright holders nor the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
- */
-
-/**
-   \ingroup usbstick
-   \defgroup sicslowinterop 6LowPan Ethernet Interop
-   @{
-*/
-
-
-/**
-   \par Ethernet to 6LowPan Address Translation
-
-   It should be obvious that since 802.15.4 addresses are 8
-   bytes, and 802.3 addresses are 6 bytes, some form of
-   address translation is needed. These routines provide this
-
-   \par 802.3 Address Formats
-
-   802.3 MAC addresses used here have this form:
-
-   \verbatim
-   +----+----+----+----+----+----+----+----+
-   +    +    +    +    +    + TR + GL + MU +
-   +----+----+----+----+----+----+----+----+
-   \endverbatim
-
-
-   It can be seen this is like a normal ethernet MAC address,
-   with GL being the Global/Local bit, and MU being the
-   Multicast/Unicast bit.
-
-   The addition is the 'TR' bit, which if set indicates that
-   the address must be translated when going between 802.15.4
-   and 802.3.
-
-   \par Address Translation
-
-   If the TRANSLATE (TR) bit is CLEAR, this means the 5th and
-   4th LSBytes of the 802.15.4 address are fffe, aka the address
-   has the hexidecial form:
-
-   xxxxxxfffexxxxxx
-
-   \note
-   You should always aim to set the 802.15.4 addresses
-   of the devices on your network to ones that will
-   satisfy this requirement. Some examples are:
-   \note
-   0x02 23 42 ff fe 73 92 28
-   \note
-   0x82 00 82 ff fe cd ee 22
-
-   \note
-   So the most significant octets MUST
-   have bit 0 CLEAR, bit 1 SET, and bit 2 CLEAR. The remaining
-   bits in this octet can be anything.
-
-   If the TRANSLATE bit is SET, this means the address on the
-   802.3 side does not directly convert to an 802.15.4 address.
-   To translate it, the remainder of the octet is used as an
-   index in a look-up table. This look-up table simply stores
-   the 4th, 5th, and 8th octet of the 802.15.4 address, and attaches
-   them to the remaining 5 bytes of the 802.3 address.
-
-   In this way there can be 32 different 802.15.4 'prefixes',
-   requiring only 96 bytes of RAM in a storage table on the
-   802.3 to 802.15.4 bridge.
-
-   Mulitcast addresses on 802.3 are mapped to broadcast addresses on
-   802.15.4 and vis-versa. Since IPv6 does not use 802.3 broadcast,
-   this code will drop all 802.3 broadcast packets. They are most
-   likely something unwanted, such as IPv4 packets that snuck in.
-
-   \par Notes on how addresses are stored
-
-   An 802.15.4 address will be reported for example as:
-
-   0x8877665544332211
-
-   Stored in the array as passed to these functions, it will be:
-   \verbatim
-   array[0] = 0x88;
-   array[1] = 0x77;
-   array[2] = 0x66;
-   etc.
-   \endverbatim
-
-   An 802.3 address will be reported for example as:
-   02:43:53:35:45:45
-
-   Stored in the array as passed to these functions, it will be:
-   \verbatim
-   array[0] = 0x02;
-   array[1] = 0x43;
-   array[2] = 0x53;
-   array[3] = 0x35
-   etc.
-   \endverbatim
-*/
-
-#include "uip.h"
-#include "uip_arp.h" /* For ethernet header structure */
-#include "net/ipv6/sicslowpan.h"
-#include "sicslow_ethernet.h"
-
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-//#define PRINTF printf
-#define PRINTF(...)
-
-#define UIP_IP_BUF   ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
-#define ETHBUF(x) ((struct uip_eth_hdr *)x)
-
-//For little endian, such as our friend mr. AVR
-#ifndef LSB
-#define LSB(u16)     (((uint8_t  *)&(u16))[0])  //!< Least significant byte of \a u16.
-#define MSB(u16)     (((uint8_t  *)&(u16))[1])  //!< Most significant byte of \a u16.
-#endif
-
-usbstick_mode_t usbstick_mode;
-
-uint8_t mac_createSicslowpanLongAddr(uint8_t * ethernet, uip_lladdr_t * lowpan);
-uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan);
-/* uint8_t memcmp_reverse(uint8_t * a, uint8_t * b, uint8_t num); */
-/* void mac_ethhijack_nondata(const struct mac_driver *r); */
-/* void mac_ethhijack(const struct mac_driver *r); */
-
-/* extern void (*sicslowmac_snifferhook)(const struct mac_driver *r); */
-
-
-//! Location of TRANSLATE (TR) bit in Ethernet address
-#define TRANSLATE_BIT_MASK (1<<2)
-//! Location of LOCAL (GL) bit in Ethernet address
-#define LOCAL_BIT_MASK     (1<<1)
-//! Location of MULTICAST (MU) bit in Ethernet address
-#define MULTICAST_BIT_MASK (1<<0)
-
-#define PREFIX_BUFFER_SIZE 32
-
-uint8_t prefixCounter;
-uint8_t prefixBuffer[PREFIX_BUFFER_SIZE][3];
-
-/* 6lowpan max size + ethernet header size + 1 */
-uint8_t raw_buf[127+ UIP_LLH_LEN +1];
-
-
-/* void tcpip_input( void ) */
-/* { */
-/*   mac_LowpanToEthernet(); */
-/* } */
-
-/**
- * \brief   Perform any setup needed
- */
-/*  struct mac_driver * pmac; */
-void mac_ethernetSetup(void)
-{
-  usbstick_mode.sicslowpan = 1;
-  usbstick_mode.sendToRf = 1;
-  usbstick_mode.translate = 1;
-  usbstick_mode.raw = 1;
-
-/*   sicslowinput = pinput; */
-
-
-/*   pmac = sicslowmac_get_driver();			 */
-/*   pmac->set_receive_function(mac_ethhijack);			   */
-/*   sicslowmac_snifferhook = mac_ethhijack_nondata; */
-}
-
-
-/**
- * \brief   Take a packet received over the ethernet link, and send it
- * out over 802.15.4
- */
-void mac_ethernetToLowpan(uint8_t * ethHeader)
-{
-  //Dest address
-  uip_lladdr_t destAddr;
-  uip_lladdr_t *destAddrPtr = NULL;
-
-  PRINTF("Packet type: %x\n", ((struct uip_eth_hdr *) ethHeader)->type);
-
-   //RUM doesn't support sending data
-   #if UIP_CONF_USE_RUM
-   return;
-   #endif
-
-  //If not IPv6 we don't do anything
-  if (((struct uip_eth_hdr *) ethHeader)->type != UIP_HTONS(UIP_ETHTYPE_IPV6)) {
-    PRINTF("eth2low: Packet is not IPv6, dropping\n");
-/*     rndis_stat.txbad++; */
-    uip_clear_buf();
-    return;
-  }
-
-  // In sniffer mode we don't ever send anything
-  if (usbstick_mode.sendToRf == 0) {
-    uip_clear_buf();
-    return;
-  }
-
-  /* IPv6 uses 33-33-xx-xx-xx-xx prefix for multicast ND stuff */
-  if ( (((struct uip_eth_hdr *) ethHeader)->dest.addr[0] == 0x33) &&
-       (((struct uip_eth_hdr *) ethHeader)->dest.addr[1] == 0x33) )
-  {
-    PRINTF("eth2low: Ethernet multicast packet received\n");
-    ;//Do Nothing
-  } else if ( (((struct uip_eth_hdr *) ethHeader)->dest.addr[0] == 0xFF) &&
-            (((struct uip_eth_hdr *) ethHeader)->dest.addr[1] == 0xFF) &&
-            (((struct uip_eth_hdr *) ethHeader)->dest.addr[2] == 0xFF) &&
-            (((struct uip_eth_hdr *) ethHeader)->dest.addr[3] == 0xFF) &&
-            (((struct uip_eth_hdr *) ethHeader)->dest.addr[4] == 0xFF) &&
-            (((struct uip_eth_hdr *) ethHeader)->dest.addr[5] == 0xFF) ) {
-    /* IPv6 does not use broadcast addresses, hence this should not happen */
-    PRINTF("eth2low: Ethernet broadcast address received, should not happen?\n");
-/*     rndis_stat.txbad++; */
-    uip_clear_buf();
-    return;
-  } else {
-    PRINTF("eth2low: Addressed packet received... ");
-    //Check this returns OK
-    if (mac_createSicslowpanLongAddr( &(((struct uip_eth_hdr *) ethHeader)->dest.addr[0]), &destAddr) == 0) {
-      PRINTF(" translation failed\n");
-/*       rndis_stat.txbad++; */
-      uip_clear_buf();
-      return;
-    }
-    PRINTF(" translated OK\n");
-    destAddrPtr = &destAddr;
-  }
-
-  //Remove header from length before passing onward
-  if(uip_len > UIP_LLH_LEN) {
-    uip_len -= UIP_LLH_LEN;
-
-    //Some IP packets have link layer in them, need to change them around!
-    if (usbstick_mode.translate) {
-      /*     uint8_t transReturn = */
-      mac_translateIPLinkLayer(ll_802154_type);
-      PRINTF("IPTranslation: returns %d\n", transReturn);
-    }
-
-    if (usbstick_mode.sendToRf){
-      tcpip_output(destAddrPtr);
-      /* 	  rndis_stat.txok++; */
-    }
-  }
-
-  uip_clear_buf();
-
-}
-
-
-/**
- * \brief Take a packet received over the 802.15.4 link, and send it
- * out over ethernet, performing any translations needed.
- */
-void mac_LowpanToEthernet(void)
-{
-/*   parsed_frame = sicslowmac_get_frame(); */
-
-  //Setup generic ethernet stuff
-  ETHBUF(uip_buf)->type = uip_htons(UIP_ETHTYPE_IPV6);
-
-  //Check for broadcast message
-  if(packetbuf_holds_broadcast()) {
-/*   if(  ( parsed_frame->fcf->destAddrMode == SHORTADDRMODE) && */
-/*        ( parsed_frame->dest_addr->addr16 == 0xffff) ) { */
-    ETHBUF(uip_buf)->dest.addr[0] = 0x33;
-    ETHBUF(uip_buf)->dest.addr[1] = 0x33;
-    ETHBUF(uip_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12];
-    ETHBUF(uip_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13];
-    ETHBUF(uip_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14];
-    ETHBUF(uip_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15];
-  } else {
-	//Otherwise we have a real address
-	mac_createEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->dest.addr[0]),
-                        (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
-  }
-
-
-  mac_createEthernetAddr((uint8_t *) &(ETHBUF(uip_buf)->src.addr[0]),
-                         (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
-
-  //We only do address translation in network mode!
-  if (usbstick_mode.translate) {
-    //Some IP packets have link layer in them, need to change them around!
-    mac_translateIPLinkLayer(ll_8023_type);
-  }
-
-  PRINTF("Low2Eth: Sending packet to ethernet\n");
-
-  uip_len += UIP_LLH_LEN;
-
-/*   rndis_send(uip_buf, uip_len, 1); */
-/*   rndis_stat.rxok++; */
-/*   uip_clear_buf(); */
-}
-
-/**
- * \brief Translate IP packet's possible link-layer addresses, passing
- *        the message to the appropriate higher level function for this
- *        packet (aka: ICMP)
- * \param target The target we want to end up with - either ll_8023_type
- *        for ethernet, or ll_802154_type for 802.15.4
- * \return    Returns how successful the translation was
- * \retval 0  Addresses, if present, were translated.
- * \retval <0 Negative return values indicate various errors, as defined
- *            by the higher level function.
- */
-int8_t mac_translateIPLinkLayer(lltype_t target)
-{
-
-#if UIP_LLADDR_LEN == 8
-  if (UIP_IP_BUF->proto == UIP_PROTO_ICMP6) {
-    PRINTF("eth2low: ICMP Message detected\n");
-    return mac_translateIcmpLinkLayer(target);
-  }
-  return 0;
-#else
-  return 1;
-#endif
-
-}
-
-#include "net/ipv6/uip-icmp6.h"
-#include "net/ipv6/uip-nd6.h"
-
-typedef struct {
-  uint8_t type;
-  uint8_t length;
-  uint8_t data[16];
-} icmp_opts_t;
-
-#define UIP_ICMP_BUF     ((struct uip_icmp_hdr *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN])
-#define UIP_ICMP_OPTS(x) ((icmp_opts_t *)&uip_buf[UIP_LLH_LEN + UIP_IPH_LEN + x])
-
-void slide(uint8_t * data, uint8_t length, int16_t slide);
-
-/**
- * \brief Translate the link-layer (L2) addresses in an ICMP packet.
- *        This will just be NA/NS/RA/RS packets currently.
- * \param target The target we want to end up with - either ll_8023_type
- *        for ethernet, or ll_802154_type for 802.15.4
- * \return       Returns how successful the translation was
- * \retval 0     Addresses, if present, were translated.
- * \retval -1    ICMP message was unknown type, nothing done.
- * \retval -2    ICMP Length does not make sense?
- * \retval -3    Unknown 'target' type
- */
-int8_t mac_translateIcmpLinkLayer(lltype_t target)
-{
-  uint16_t icmp_opt_offset = 0;
-  int16_t len = UIP_IP_BUF->len[1] | (UIP_IP_BUF->len[0] << 8);
-
-  uint16_t iplen;
-
-  uint8_t i;
-
-  int16_t sizechange;
-
-  uint8_t llbuf[16];
-
-  //Figure out offset to start of options
-  switch(UIP_ICMP_BUF->type) {
-    case ICMP6_NS:
-    case ICMP6_NA:
-      icmp_opt_offset = 24;
-      break;
-
-    case ICMP6_RS:
-      icmp_opt_offset = 8;
-      break;
-
-    case ICMP6_RA:
-      icmp_opt_offset = 16;
-      break;
-
-    case ICMP6_REDIRECT:
-      icmp_opt_offset = 40;
-      break;
-
-      /** Things without link-layer */
-    case ICMP6_DST_UNREACH:
-    case ICMP6_PACKET_TOO_BIG:
-    case ICMP6_TIME_EXCEEDED:
-    case ICMP6_PARAM_PROB:
-    case ICMP6_ECHO_REQUEST:
-    case ICMP6_ECHO_REPLY:
-      return 0;
-      break;
-
-    default:
-      return -1;
-  }
-
-  //Figure out length of options
-  len -= icmp_opt_offset;
-
-  //Sanity check
-  if (len < 8) return -2;
-
-  //While we have options to do...
-  while (len >= 8){
-
-    //If we have one of these, we have something useful!
-    if (((UIP_ICMP_OPTS(icmp_opt_offset)->type) == UIP_ND6_OPT_SLLAO) ||
-        ((UIP_ICMP_OPTS(icmp_opt_offset)->type) == UIP_ND6_OPT_TLLAO) ) {
-
-      /* Shrinking the buffer may thrash things, so we store the old
-         link-layer address */
-      for(i = 0; i < (UIP_ICMP_OPTS(icmp_opt_offset)->length*8 - 2); i++) {
-        llbuf[i] = UIP_ICMP_OPTS(icmp_opt_offset)->data[i];
-      }
-
-      //Shrink/grow buffer as needed
-      if (target == ll_802154_type) {
-        //Current is 802.3, Hence current link-layer option is 6 extra bytes
-        sizechange = 8;
-        slide(UIP_ICMP_OPTS(icmp_opt_offset)->data + 6, len - 6, sizechange);
-      } else if (target == ll_8023_type) {
-        /* Current is 802.15.4, Hence current link-layer option is 14 extra
-         * bytes.
-         * (Actual LL is 8 bytes, but total option length is in multiples of
-         * 8 Bytes, hence 8 + 2 = 10. Closest is 16 bytes, then 16 bytes for
-         * total optional length - 2 bytes for type + length leaves 14 )
-         */
-        sizechange = -8;
-        slide(UIP_ICMP_OPTS(icmp_opt_offset)->data + 14, len - 14, sizechange);
-      } else {
-        return -3; //Uh-oh!
-      }
-
-      //Translate addresses
-      if (target == ll_802154_type) {
-        mac_createSicslowpanLongAddr(llbuf, (uip_lladdr_t *)UIP_ICMP_OPTS(icmp_opt_offset)->data);
-      } else {
-        mac_createEthernetAddr(UIP_ICMP_OPTS(icmp_opt_offset)->data, (uip_lladdr_t *)llbuf);
-      }
-
-      //Adjust the length
-      if (target == ll_802154_type) {
-        UIP_ICMP_OPTS(icmp_opt_offset)->length = 2;
-      } else {
-        UIP_ICMP_OPTS(icmp_opt_offset)->length = 1;
-      }
-
-      //Adjust the IP header length, as well as uIP length
-      iplen = UIP_IP_BUF->len[1] | (UIP_IP_BUF->len[0]<<8);
-      iplen += sizechange;
-      len += sizechange;
-
-      UIP_IP_BUF->len[1] = (uint8_t)iplen;
-      UIP_IP_BUF->len[0] = (uint8_t)(iplen >> 8);
-
-      uip_len += sizechange;
-
-      //We broke ICMP checksum, be sure to fix that
-      UIP_ICMP_BUF->icmpchksum = 0;
-      UIP_ICMP_BUF->icmpchksum = ~uip_icmp6chksum();
-
-      //Finally set up next run in while loop
-      len -= 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length;
-      icmp_opt_offset += 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length;
-    } else {
-
-      //Not an option we care about, ignore it
-      len -= 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length;
-
-      //This shouldn't happen!
-      if (UIP_ICMP_OPTS(icmp_opt_offset)->length == 0) {
-        PRINTF("Option in ND packet has length zero, error?\n");
-        len = 0;
-      }
-
-      icmp_opt_offset += 8 * UIP_ICMP_OPTS(icmp_opt_offset)->length;
-
-    } //If ICMP_OPT is one we care about
-
-  } //while(len >= 8)
-
-  return 0;
-
-}
-
-
-/**
- * \brief Create a 802.15.4 long address from a 802.3 address
- * \param ethernet   Pointer to ethernet address
- * \param lowpan     Pointer to 802.15.4 address
- */
-uint8_t mac_createSicslowpanLongAddr(uint8_t * ethernet, uip_lladdr_t * lowpan)
-{
-  uint8_t index;
-
-#if UIP_LLADDR_LEN == 8
-  //Special case - if the address is our address, we just copy over what we know to be
-  //our 802.15.4 address
-
-/*   if (memcmp_reverse((uint8_t *)&rndis_ethernet_addr, ethernet, 6) == 0) { */
-  if (memcmp((uint8_t *)&uip_lladdr.addr[2], ethernet, 6) == 0) {
-		memcpy((uint8_t *)lowpan, uip_lladdr.addr, 8);
-/* 		byte_reverse((uint8_t *)lowpan, 8); */
-
-		return 1;
-	}
-
-  //Check if translate bit is set, hence we have to look up the prefix
-  if (ethernet[0] & TRANSLATE_BIT_MASK) {
-
-    //Get top bits
-    index = ethernet[0] >> 3;
-
-    //Check this is plausible...
-    if (index >= prefixCounter) {
-      return 0;
-    }
-
-    //Copy over prefix
-    lowpan->addr[0] = prefixBuffer[index][0];
-	lowpan->addr[3] = prefixBuffer[index][1];
-	lowpan->addr[4] = prefixBuffer[index][2];
-
-    //Bit is clear
-    //so we copy all six
-  } else {
-    lowpan->addr[0] = ethernet[0];
-    lowpan->addr[3] = 0xff;
-    lowpan->addr[4] = 0xfe;
-  }
-
-  //Copy over reamining five bytes
-    lowpan->addr[1] = ethernet[1];
-    lowpan->addr[2] = ethernet[2];
-    lowpan->addr[5] = ethernet[3];
-    lowpan->addr[6] = ethernet[4];
-    lowpan->addr[7] = ethernet[5];
-
-#else
-  uint8_t i;
-
-	for(i = 0; i < UIP_LLADDR_LEN; i++) {
-		lowpan->addr[i] = ethernet[i];
-	}
-#endif
-
-  return 1;
-}
-
-
-/**
- * \brief Create a 802.3 address from a 802.15.4 long address
- * \param ethernet   Pointer to ethernet address
- * \param lowpan     Pointer to 802.15.4 address
- */
-uint8_t mac_createEthernetAddr(uint8_t * ethernet, uip_lladdr_t * lowpan)
-{
-  uint8_t index = 0;
-  uint8_t i;
-/*   uint8_t j, match; */
-
-#if UIP_LLADDR_LEN == 8
-
-   //Special case - if the address is our address, we just copy over what we know to be
-  //our 802.3 address
-/*   if (memcmp_reverse(uip_lladdr.addr, (uint8_t *)lowpan, 8) == 0) { */
-  if (memcmp(uip_lladdr.addr, (uint8_t *)lowpan, 8) == 0) {
-		memcpy(ethernet, &uip_lladdr.addr[2], 6);
-/* 		byte_reverse(ethernet, 6); */
-
-		return 1;
-	}
-
-
-  //Check if we need to do anything:
-  if ((lowpan->addr[3] == 0xff) && (lowpan->addr[4] == 0xfe) &&
-      ((lowpan->addr[0] & TRANSLATE_BIT_MASK) == 0) &&
-      ((lowpan->addr[0] & MULTICAST_BIT_MASK) == 0) &&
-      (lowpan->addr[0] & LOCAL_BIT_MASK)) {
-
-    /** Nope: just copy over 6 bytes **/
-      ethernet[0] = lowpan->addr[0];
-	  ethernet[1] = lowpan->addr[1];
-	  ethernet[2] = lowpan->addr[2];
-	  ethernet[3] = lowpan->addr[5];
-	  ethernet[4] = lowpan->addr[6];
-	  ethernet[5] = lowpan->addr[7];
-
-
-  } else {
-
-    /** Yes: need to store prefix **/
-    for (i = 0; i < prefixCounter; i++)	{
-      //Check the current prefix - if it fails, check next one
-
-
-       if ((lowpan->addr[0] == prefixBuffer[i][0]) &&
-           (lowpan->addr[3] == prefixBuffer[i][1]) &&
-           (lowpan->addr[4] == prefixBuffer[i][2])) {
-			break;
-	   }
-
-    }
-
-    index = i;
-
-    //Deal with overflow, iron-fist style
-    if (index >= PREFIX_BUFFER_SIZE) {
-      index = 0;
-      prefixCounter = PREFIX_BUFFER_SIZE;
-    } else {
-      //Are we making a new one?
-      if (index == prefixCounter) {
-        prefixCounter++;
-      }
-    }
-
-    //Copy the prefix over, no matter if we have a new or old one
-    prefixBuffer[index][0] = lowpan->addr[0];
-	prefixBuffer[index][1] = lowpan->addr[3];
-	prefixBuffer[index][2] = lowpan->addr[4];
-
-    //Create ethernet MAC address now
-    ethernet[1] = lowpan->addr[1];
-	ethernet[2] = lowpan->addr[2];
-	ethernet[3] = lowpan->addr[5];
-	ethernet[4] = lowpan->addr[6];
-    ethernet[5] = lowpan->addr[7];
-
-
-    ethernet[0] = TRANSLATE_BIT_MASK | LOCAL_BIT_MASK | (index << 3);
-  }
-
-#else
-
-    //Create ethernet MAC address now
-	for(i = 0; i < UIP_LLADDR_LEN; i++) {
-		ethernet[i] = lowpan->addr[i];
-	}
-#endif
-
-  return 1;
-}
-
-
-/**
- * \brief        Slide the pointed to memory up a certain amount,
- *               growing/shrinking a buffer
- * \param data   Pointer to start of data buffer
- * \param length Length of the data buffer
- * \param slide  How many bytes to slide the buffer up in memory (if +) or
- *               down in memory (if -)
- */
-void slide(uint8_t * data, uint8_t length, int16_t slide)
-{
-  //Sanity checks
-  if (!length) return;
-  if (!slide) return;
-
-  uint8_t i = 0;
-
-  while(length) {
-    length--;
-
-    //If we are sliding up, we do from the top of the buffer down
-    if (slide > 0) {
-      *(data + length + slide) = *(data + length);
-
-      //If we are sliding down, we do from the bottom of the buffer up
-    } else {
-      *(data + slide + i) = *(data + i);
-    }
-
-    i++;
-  }
-}
-
-/*--------------------------------------------------------------------*/
-/** \brief Process a received 6lowpan packet. Hijack function.
- *  \param r The MAC layer
- *
- *  The 6lowpan packet is put in packetbuf by the MAC. This routine calls
- *  any other needed layers (either 6lowpan, or just raw ethernet dump)
- */
-#if 0
-void mac_ethhijack(const struct mac_driver *r)
-{
-	if (usbstick_mode.raw) {
-		mac_802154raw(r);
-	}
-
-	if (usbstick_mode.sicslowpan) {
-
-#if UIP_CONF_USE_RUM
-	if (parsed_frame->payload[4]) { /* RUM 6lowpan frame type */
-#endif
-		sicslowinput(r);
-#if UIP_CONF_USE_RUM
-	}
-#endif
-
-
-	}
-
-}
-#endif
-
-#if 0
-void mac_ethhijack_nondata(const struct mac_driver *r)
-{
-	if (usbstick_mode.raw)
-		mac_802154raw(r);
-}
-#endif
-
-/*--------------------------------------------------------------------*/
-/*--------------------------------------------------------------------*/
-/** \brief Logs a sent 6lowpan frame
- *
- *  This routine passes a frame
- *  directly to the ethernet layer without decompressing.
- */
-#if 0
-void mac_logTXtoEthernet(frame_create_params_t *p,frame_result_t *frame_result)
-{
-  uint8_t sendlen;
-
-  /* Make sure we are supposed to do this */
-  if (usbstick_mode.raw == 0) return;
-
-/* Get the raw frame */
-  memcpy(&raw_buf[UIP_LLH_LEN], frame_result->frame, frame_result->length);
-  sendlen = frame_result->length;
-
- //Setup generic ethernet stuff
-  ETHBUF(raw_buf)->type = uip_htons(UIP_ETHTYPE_802154);
-
-  uint64_t tempaddr;
-
-
-  //Check for broadcast message
-  //if(linkaddr_cmp((const linkaddr_t *)destAddr, &linkaddr_null)) {
-  if(  ( p->fcf.destAddrMode == SHORTADDRMODE) &&
-       ( p->dest_addr.addr16 == 0xffff) ) {
-    ETHBUF(raw_buf)->dest.addr[0] = 0x33;
-    ETHBUF(raw_buf)->dest.addr[1] = 0x33;
-    ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12];
-    ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13];
-    ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14];
-    ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15];
-  } else {
-
-	tempaddr = p->dest_addr.addr64;
-
-	byte_reverse((uint8_t *)&tempaddr, 8);
-
-	//Otherwise we have a real address
-	mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]),
-            (uip_lladdr_t *)&tempaddr);
-
-  }
-
-	tempaddr = p->src_addr.addr64;
-
-	byte_reverse((uint8_t *)&tempaddr, 8);
-
-  mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]),
-                         (uip_lladdr_t *)&tempaddr);
-
-   PRINTF("Low2Eth: Sending 802.15.4 packet to ethernet\n");
-
-  sendlen += UIP_LLH_LEN;
-
-  rndis_send(raw_buf, sendlen, 0);
-  rndis_stat.rxok++;
-  return;
-}
-#endif
-
-/*--------------------------------------------------------------------*/
-/** \brief Process a received 6lowpan packet.
- *  \param r The MAC layer
- *
- *  The 6lowpan packet is put in packetbuf by the MAC. This routine passes
- *  it directly to the ethernet layer without decompressing.
- */
-#if 0
-void mac_802154raw(const struct mac_driver *r)
-{
-  uint8_t sendlen;
-
-  parsed_frame = sicslowmac_get_frame();
-
-  /* Get the raw frame */
-  memcpy(&raw_buf[UIP_LLH_LEN], radio_frame_data(), radio_frame_length());
-  sendlen = radio_frame_length();
-
- //Setup generic ethernet stuff
-  ETHBUF(raw_buf)->type = uip_htons(UIP_ETHTYPE_802154);
-
-
-  //Check for broadcast message
-  //if(linkaddr_cmp((const linkaddr_t *)destAddr, &linkaddr_null)) {
-  if(  ( parsed_frame->fcf->destAddrMode == SHORTADDRMODE) &&
-       ( parsed_frame->dest_addr->addr16 == 0xffff) ) {
-    ETHBUF(raw_buf)->dest.addr[0] = 0x33;
-    ETHBUF(raw_buf)->dest.addr[1] = 0x33;
-    ETHBUF(raw_buf)->dest.addr[2] = UIP_IP_BUF->destipaddr.u8[12];
-    ETHBUF(raw_buf)->dest.addr[3] = UIP_IP_BUF->destipaddr.u8[13];
-    ETHBUF(raw_buf)->dest.addr[4] = UIP_IP_BUF->destipaddr.u8[14];
-    ETHBUF(raw_buf)->dest.addr[5] = UIP_IP_BUF->destipaddr.u8[15];
-  } else {
-
-	//Otherwise we have a real address
-	mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->dest.addr[0]),
-            (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_RECEIVER));
-
-  }
-
-  mac_createEthernetAddr((uint8_t *) &(ETHBUF(raw_buf)->src.addr[0]),
-                         (uip_lladdr_t *)packetbuf_addr(PACKETBUF_ADDR_SENDER));
-
-  PRINTF("Low2Eth: Sending 802.15.4 packet to ethernet\n");
-
-  sendlen += UIP_LLH_LEN;
-
-  rndis_send(raw_buf, sendlen, 1);
-  rndis_stat.rxok++;
-
-  return;
-}
-#endif
-/** @} */
-/** @} */
diff --git a/tools/sky/uip6-bridge/sicslow_ethernet.h b/tools/sky/uip6-bridge/sicslow_ethernet.h
deleted file mode 100644
index 2e48c188eb1eea8ac42dcaa259ea9373db3d57fa..0000000000000000000000000000000000000000
--- a/tools/sky/uip6-bridge/sicslow_ethernet.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/**
- * \file sicslow_ethernet.c
- *         Routines to interface between Ethernet and 6LowPan
- *
- * \author
- *         Colin O'Flynn <coflynn@newae.com>
- *
- * \addtogroup usbstick
- */
-
-/* Copyright (c) 2008 by:
-
-	Colin O'Flynn coflynn@newae.com
-	Eric Gnoske egnoske@gmail.com
-	Blake Leverett bleverett@gmail.com
-	Mike Vidales mavida404@gmail.com
-	Kevin Brown kbrown3@uccs.edu
-	Nate Bohlmann nate@elfwerks.com
-
-   All rights reserved.
-
-   Redistribution and use in source and binary forms, with or without
-   modification, are permitted provided that the following conditions are met:
-
-   * Redistributions of source code must retain the above copyright
-     notice, this list of conditions and the following disclaimer.
-   * 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.
-   * Neither the name of the copyright holders nor the names of
-     contributors may be used to endorse or promote products derived
-     from this software without specific prior written permission.
-
-  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR CONTRIBUTORS 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.
-*/
-
-#ifndef SICSLOW_ETHERNET_H
-#define SICSLOW_ETHERNET_H
-
-typedef enum {
-  ll_802154_type,
-  ll_8023_type
-} lltype_t;
-
-
-typedef struct {
-	uint8_t	sicslowpan	:1;
-	uint8_t sendToRf	:1;
-	uint8_t translate	:1;
-	uint8_t raw         :1;
-} usbstick_mode_t;
-
-
-#define UIP_ETHTYPE_802154 0x809A
-
-extern usbstick_mode_t usbstick_mode;
-
-
-int8_t mac_translateIcmpLinkLayer(lltype_t target);
-int8_t mac_translateIPLinkLayer(lltype_t target);
-void mac_LowpanToEthernet(void);
-void mac_ethernetToLowpan(uint8_t * ethHeader);
-void mac_ethernetSetup(void);
-/* void mac_802154raw(const struct mac_driver *r); */
-/* void mac_logTXtoEthernet(frame_create_params_t *p,frame_result_t *frame_result); */
-
-#endif
diff --git a/tools/viewconf/viewconf.c b/tools/viewconf/viewconf.c
index b5fe8dc7f3cf852d1fc56cf10d79aed16f78755c..c762e02f6f8f72df4d7bff8b7dbb895760d8b5dc 100644
--- a/tools/viewconf/viewconf.c
+++ b/tools/viewconf/viewconf.c
@@ -88,6 +88,8 @@
 ##### "NBR_TABLE_CONF_MAX_NEIGHBORS": __________ -> NBR_TABLE_MAX_NEIGHBORS
 #endif
 
+##### "NETSTACK_RADIO_MAX_PAYLOAD_LEN": ________ == NETSTACK_RADIO_MAX_PAYLOAD_LEN
+
 ##### "NETSTACK_MAX_ROUTE_ENTRIES": ____________ == NETSTACK_MAX_ROUTE_ENTRIES
 ##### "UIP_CONF_BUFFER_SIZE": __________________ == UIP_CONF_BUFFER_SIZE
 ##### "UIP_CONF_UDP": __________________________ == UIP_CONF_UDP
diff --git a/tools/wpcapslip/wpcap.c b/tools/wpcapslip/wpcap.c
index 54fc4e87333478252b69ad9716c207ebcda54bae..0d667d61775fabe8a43ff1de44a68c1184507dcf 100644
--- a/tools/wpcapslip/wpcap.c
+++ b/tools/wpcapslip/wpcap.c
@@ -451,7 +451,7 @@ arp_out(struct ethip_hdr *iphdr, int len)
       arphdr->protolen = 4;
       arphdr->ethhdr.type = UIP_HTONS(UIP_ETHTYPE_ARP);
 
-      /*      uip_appdata = &uip_buf[UIP_TCPIP_HLEN + UIP_LLH_LEN];*/
+      /*      uip_appdata = &uip_buf[UIP_IPTCPH_LEN];*/
 
       return sizeof(struct arp_hdr);
     }
diff --git a/tools/zolertia/license-bsl.txt b/tools/zolertia/license-bsl.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e6775e9d7adb9b54be880dbad975047adb4c60a5
--- /dev/null
+++ b/tools/zolertia/license-bsl.txt
@@ -0,0 +1,62 @@
+Copyright (c) 2001-2003 Chris Liechti <cliechti@gmx.net>
+
+All Rights Reserved.
+
+This is the Python license. In short, you can use this product in
+commercial and non-commercial applications, modify it, redistribute it.
+A notification to the author when you use and/or modify it is welcome.
+
+TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING THIS SOFTWARE
+============================================
+
+LICENSE AGREEMENT
+-----------------
+
+1. This LICENSE AGREEMENT is between the copyright holder of this
+product, and the Individual or Organization ("Licensee") accessing
+and otherwise using this product in source or binary form and its
+associated documentation.
+
+2. Subject to the terms and conditions of this License Agreement,
+the copyright holder hereby grants Licensee a nonexclusive,
+royalty-free, world-wide license to reproduce, analyze, test,
+perform and/or display publicly, prepare derivative works, distribute,
+and otherwise use this product alone or in any derivative version,
+provided, however, that copyright holders License Agreement and
+copyright holders notice of copyright are retained in this product
+alone or in any derivative version prepared by Licensee.
+
+3. In the event Licensee prepares a derivative work that is based on
+or incorporates this product or any part thereof, and wants to make
+the derivative work available to others as provided herein, then
+Licensee hereby agrees to include in any such work a brief summary of
+the changes made to this product.
+
+4. The copyright holder is making this product available to Licensee
+on an "AS IS" basis. THE COPYRIGHT HOLDER MAKES NO REPRESENTATIONS
+OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT
+LIMITATION, THE COPYRIGHT HOLDER MAKES NO AND DISCLAIMS ANY
+REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR
+ANY PARTICULAR PURPOSE OR THAT THE USE OF THIS PRODUCT WILL
+NOT INFRINGE ANY THIRD PARTY RIGHTS.
+
+5. THE COPYRIGHT HOLDER SHALL NOT BE LIABLE TO LICENSEE OR ANY
+OTHER USERS OF THIS PRODUCT FOR ANY INCIDENTAL, SPECIAL, OR
+CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING,
+DISTRIBUTING, OR OTHERWISE USING THIS PRODUCT, OR ANY
+DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY
+THEREOF.
+
+6. This License Agreement will automatically terminate upon a
+material breach of its terms and conditions.
+
+7. Nothing in this License Agreement shall be deemed to create any
+relationship of agency, partnership, or joint venture between the
+copyright holder and Licensee. This License Agreement does not grant
+permission to use trademarks or trade names from the copyright holder
+in a trademark sense to endorse or promote products or services of
+Licensee, or any third party.
+
+8. By copying, installing or otherwise using this product, Licensee
+agrees to be bound by the terms and conditions of this License
+Agreement.
diff --git a/tools/zolertia/motelist-zolertia b/tools/zolertia/motelist-zolertia
new file mode 100755
index 0000000000000000000000000000000000000000..e5f7da99e108c6ff082cb7d463df3a2763d12f4e
--- /dev/null
+++ b/tools/zolertia/motelist-zolertia
@@ -0,0 +1,295 @@
+#!/usr/bin/perl -w
+use strict;
+# $Id: motelist-z1,v 1.1 2010/08/24 15:48:20 joxe Exp $
+# @author Cory Sharp <cory@moteiv.com>
+# @author Joe Polastre
+
+my $help = <<'EOF';
+usage: motelist [options]
+
+  $Revision: 1.1 $
+
+options:
+  -h  display this help
+  -c  compact format, not pretty but easier for parsing
+  -f  specify the usb-serial file (for smote.cs)
+  -k  kernel version: 2.4, 2.6, auto (default)
+  -m  method to scan usb: procfs, sysfs, auto (default)
+  -dev_prefix  force the device prefix for the serial device
+  -usb  display extra usb information
+  -b  specify which Zolertia board to list (z1, remote, etc)
+EOF
+
+my %Opt = (
+  compact => 0,
+  usb => 0,
+  board => "",
+  method => "auto",
+  kernel => "auto",
+  dev_prefix => [ "/dev/usb/tts/", "/dev/ttyUSB", "/dev/tts/USB" ],
+  usbserial => "sudo cat /proc/tty/driver/usbserial |",
+);
+
+while (@ARGV) {
+  last unless $ARGV[0] =~ /^-/;
+  my $opt = shift @ARGV;
+  if( $opt eq "-h" ) { print "$help\n"; exit 0; }
+  elsif( $opt eq "-c" ) { $Opt{compact} = 1; }
+  elsif( $opt eq "-f" ) { $Opt{usbserial} = shift @ARGV; }
+  elsif( $opt eq "-k" ) { $Opt{kernel} = shift @ARGV; }
+  elsif( $opt eq "-m" ) { $Opt{method} = shift @ARGV; }
+  elsif( $opt eq "-dev_prefix" ) { $Opt{dev_prefix} = shift @ARGV; }
+  elsif( $opt eq "-usb" ) { $Opt{usb} = 1; }
+  elsif( $opt eq "-b" ) { $Opt{board} = shift @ARGV; }
+  else { print STDERR "$help\nerror, unknown command line option $opt\n"; exit 1; }
+}
+
+if( $Opt{kernel} eq "auto" ) {
+  $Opt{kernel} = "unknown";
+  $Opt{kernel} = $1 if snarf("/proc/version") =~ /\bLinux version (\d+\.\d+)/;
+}
+
+if( $Opt{method} eq "auto" ) {
+  $Opt{method} = ($Opt{kernel} eq "2.4") ? "procfs" : "sysfs";
+}
+
+if( $Opt{board} eq "z1" ) {
+  $Opt{board} = "Zolertia Z1";
+} elsif( $Opt{board} eq "remote" ) {
+  $Opt{board} = "Zolertia RE-Mote platform";
+} elsif( $Opt{board} eq "firefly" ) {
+  $Opt{board} = "Zolertia Firefly platform";
+} elsif( $Opt{board} eq "orion" ) {
+  $Opt{board} = "Zolertia Orion Ethernet router";
+}
+
+my @devs = $Opt{method} eq "procfs" ? scan_procfs() : scan_sysfs();
+print_motelist( sort { cmp_usbdev($a,$b) } @devs );
+
+
+#
+#  SysFS
+#
+sub scan_sysfs {
+
+  my $tmp = '($_->{UsbVendor}||"") eq "10c4" && ($_->{UsbProduct}||"") eq "ea60"';
+
+  if($Opt{board}) {
+    $tmp = '($_->{ProductString}||"") eq $Opt{board} && ' . $tmp
+  }
+
+  #  Scan /sys/bus/usb/drivers/usb for CP210x devices
+  my @cpdevs =
+    grep { eval "$tmp" }
+    map { {
+      SysPath => $_,
+      UsbVendor => snarf("$_/idVendor",1),
+      UsbProduct => snarf("$_/idProduct",1),
+      ProductString => snarf("$_/product",1),
+    } }
+   glob("/sys/bus/usb/drivers/usb/*");
+
+  #  Gather information about each CP210x device
+  for my $f (@cpdevs) {
+    my $syspath = $f->{SysPath};
+    $f->{InfoSerial} = snarf("$syspath/serial",1);
+    $f->{InfoManufacturer} = snarf("$syspath/manufacturer",1);
+    $f->{InfoProduct} = snarf("$syspath/product",1);
+    $f->{UsbDevNum} = snarf("$syspath/devnum",1);
+
+    my $devstr = readlink($syspath);
+    if( $devstr =~ m{([^/]+)/usb(\d+)/.*-([^/]+)$} ) {
+      $f->{UsbPath} = "usb-$1-$3";
+      $f->{UsbBusNum} = $2;
+    }
+    ($f->{SysDev} = $syspath) =~ s{^.*/}{};
+
+    my $port = "$syspath/$f->{SysDev}:1.0";
+    ($f->{DriverName} = readlink("$port/driver")) =~ s{^.*/}{} if -l "$port/driver";
+    ($f->{SerialDevName} = (glob("$port/tty*"),undef)[0]) =~ s{^.*/}{};
+    $f->{SerialDevNum} = $1 if $f->{SerialDevName} =~ /(\d+)/;
+    $f->{SerialDevName} = getSerialDevName( $f->{SerialDevNum} ) || "  (none)";
+  }
+  return @cpdevs;
+}
+
+
+#
+#  Scan Procfs
+#
+sub scan_procfs {
+
+  my $text_devs = snarf("< /proc/bus/usb/devices");
+  my $text_serial = snarf($Opt{usbserial});
+
+  my @usbdevs = map { {parse_usb_devices_text($_)} }
+                grep { !/^\s*$/ } split /\n+(?=T:)/, $text_devs;
+  my %usbtree = build_usb_tree( @usbdevs );
+  my %usbserialtree = build_usbserial_tree( $text_serial );
+  for my $tts ( values %usbserialtree ) {
+    $usbtree{usbkey($tts->{path})}{usbserial} = $tts if defined $tts->{path};
+  }
+
+  my @cpdevs = map { {
+      UsbVendor => $_->{Vendor},
+      UsbProduct => $_->{ProdID},
+      InfoManufacturer => $_->{Manufacturer},
+      InfoProduct => $_->{Product},
+      InfoSerial => $_->{SerialNumber},
+      UsbBusNum => $_->{nbus},
+      UsbDevNum => $_->{ndev},
+      UsbPath => (($Opt{kernel} eq "2.4") ? $_->{usbserial}{path} : $_->{usbpath}),
+      DriverName => $_->{driver},
+      SerialDevNum => $_->{usbserial}{tts},
+      SerialDevName => getSerialDevName($_->{usbserial}{tts}) || "  (none)",
+    } }
+    grep { ($_->{Vendor}||"") eq "0403" && ($_->{ProdID}||"") eq "6001" }
+    values %usbtree;
+
+  return @cpdevs;
+}
+
+sub build_usb_tree {
+  my @devs = @_;
+  my %tree = ();
+  for my $dev (sort { $a->{Lev} <=> $b->{Lev} } @devs) {
+    my ($bus,$lev,$prnt) = ( $dev->{Bus}+0, $dev->{Lev}+0, $dev->{Prnt}+0 );
+    my $devnum = $dev->{"Dev#"}+0;
+    $dev->{nbus} = $bus;
+    $dev->{ndev} = $devnum;
+    $tree{"bus$bus"} = {} unless exists $tree{"bus$bus"};
+    $tree{"bus$bus"}{"dev$devnum"} = $dev;
+    if( $lev == 0 ) {
+      $dev->{usbpath} = "usb-$dev->{SerialNumber}";
+    } else {
+      my $sep = ($lev==1) ? "-" : ".";
+      $dev->{parent} = $tree{"bus$bus"}{"dev$prnt"};
+      $dev->{usbpath} = $dev->{parent}{usbpath} . $sep . ($dev->{Port}+1);
+    }
+    $tree{usbkey($dev->{usbpath})} = $dev;
+  }
+  return %tree;
+}
+
+sub parse_usb_devices_text {
+  my $text = shift;
+  $text =~ s/^\S+\s*//gm;
+  return ($text =~ m/([^\s=]+)=\s*(.*?\S)\s*(?=[^\s=]+=|$)/mg);
+}
+
+sub build_usbserial_tree {
+  my $text = shift;
+  my %tree = ();
+  while( $text =~ /^([^:]+):(.*)/mg ) {
+    my ($tts,$params) = ($1,$2);
+    $tree{$tts} = { tts => $tts };
+    while ($params =~ m/\s+([^:]+):(?:"([^"]*)"|(\S+))/g) {
+      $tree{$tts}{$1} = $2||$3;
+    }
+  }
+  return %tree;
+}
+
+sub usbkey {
+  if( $Opt{kernel} eq "2.4" ) {
+    (my $key = $_[0]) =~ s/^.*-//;
+    return $key;
+  }
+  return $_[0];
+}
+
+
+#
+#  getSerialDevName
+#
+#  For each device, force to use dev_prefix if it's not an array.  Otherwise,
+#  assume it's a list of candidate prefixes.  Check them and commit to the
+#  first one that actually exists.
+#
+sub getSerialDevName {
+  my $devnum = shift;
+  my $devname = undef;
+  if( defined $devnum ) {
+    if( ref($Opt{dev_prefix}) eq "ARRAY" ) {
+      $devname = $devnum;
+      for my $prefix (@{$Opt{dev_prefix}}) {
+        my $file = $prefix . $devnum;
+        if( -e $file ) { $devname = $file; last; }
+      }
+    } else {
+      $devname = $Opt{dev_prefix} . $devnum;
+    }
+  }
+  return $devname;
+}
+
+
+#
+#  Print motelist
+#
+sub print_motelist {
+  my @devs = @_;
+
+  #  If none were found, quit
+  if( @devs == 0 ) {
+    print "No devices found.\n";
+    return;
+  }
+
+  #  Print a header
+  if( !$Opt{compact} ) {
+    if( $Opt{usb} ) {
+      print << "EOF" unless $Opt{compact};
+--- --- ------------------------ -------------- ---------------- -------------------------------------
+Bus Dev USB Path                 Reference      Device           Description
+--- --- ------------------------ -------------- ---------------- -------------------------------------
+EOF
+    } else {
+      print << "EOF" unless $Opt{compact};
+-------------- ---------------- ---------------------------------------------
+Reference      Device           Description
+-------------- ---------------- ---------------------------------------------
+EOF
+    }
+  }
+
+  #  Print the usb information
+  for my $dev (sort { cmp_usbdev($a,$b) } @devs) {
+    my $desc = join( " ", $dev->{InfoManufacturer}||"", $dev->{InfoProduct}||"" ) || " (none)";
+    my @output = ( $dev->{InfoSerial}||" (none)", $dev->{SerialDevName}, $desc );
+    @output = ( $dev->{UsbBusNum}, $dev->{UsbDevNum}, $dev->{UsbPath}, @output ) if $Opt{usb};
+    if( $Opt{compact} ) {
+      print join(",",@output) . "\n";
+    } else {
+      printf( ($Opt{usb}?"%3d %3d %-24s ":"")."%-14s %-16s %s\n", @output );
+    }
+  }
+}
+
+
+#
+#  Cmp Usbdev's
+#
+sub cmp_usbdev {
+  my ($a,$b) = @_;
+  if( defined $a->{SerialDevNum} ) {
+    if( defined $b->{SerialDevNum} ) {
+      return $a->{SerialDevNum} <=> $b->{SerialDevNum};
+    }
+    return -1;
+  }
+  return 1 if defined $b->{SerialDevNum};
+  return ($a->{InfoSerial}||"") cmp ($b->{InfoSerial}||"");
+}
+
+#
+#  Read a file in
+#
+sub snarf {
+  open my $fh, $_[0] or return undef;
+  my $text = do{local $/;<$fh>};
+  close $fh;
+  $text =~ s/\s+$// if $_[1];
+  return $text;
+}
+
diff --git a/tools/zolertia/motelist-zolertia-macos b/tools/zolertia/motelist-zolertia-macos
new file mode 100755
index 0000000000000000000000000000000000000000..526b4887e934a90540ea027b89284ac959ace22d
--- /dev/null
+++ b/tools/zolertia/motelist-zolertia-macos
@@ -0,0 +1,75 @@
+#!/usr/bin/perl -w
+use strict;
+
+my $help = <<'EOF';
+usage: motelist [options]
+
+options:
+  -h  display this help
+  -c  compact format, not pretty but easier for parsing
+EOF
+
+my %Opt = (
+  compact => 0,
+  dev_prefix => [ "/dev/tty.SLAB" ],
+);
+
+while (@ARGV) {
+  last unless $ARGV[0] =~ /^-/;
+  my $opt = shift @ARGV;
+  if( $opt eq "-h" ) { print "$help\n"; exit 0; }
+  elsif( $opt eq "-c" ) { $Opt{compact} = 1; }
+  else { print STDERR "$help\nerror, unknown command line option $opt\n"; exit 1; }
+}
+
+print_motelist( scan_dev() );
+
+#
+#  Scan /dev for tty.SLAB*
+#
+sub  scan_dev {
+  my @devs;
+  foreach (`ls /dev/tty.SLAB* 2>&1`) {
+    my($dev, $serial) = /(\/dev\/tty.SLAB(\S+))/;
+    if ($serial ne "*:") {
+      my $d;
+      $d->{"InfoSerial"} = $serial;
+      $d->{"SerialDevName"} = $dev;
+      push(@devs, $d);
+    }
+  }
+  return @devs;
+}
+
+
+#
+#  Print motelist
+#
+sub print_motelist {
+  my @devs = @_;
+
+  #  If none were found, quit
+  if( @devs == 0 ) {
+    #print "No devices found.\n";
+    return;
+  }
+
+  #  Print a header
+  if( !$Opt{compact} ) {
+    print << "EOF" unless $Opt{compact};
+Reference  Device                      Description
+---------- --------------------------- ---------------------------------------
+EOF
+  }
+
+  #  Print the usb information
+  for my $dev (@devs) {
+    my $desc = "(none)";
+    my @output = ( $dev->{"InfoSerial"}, $dev->{"SerialDevName"}, $desc );
+    if( $Opt{compact} ) {
+      print join(",",@output) . "\n";
+    } else {
+      printf( "%-10s %-27s %s\n", @output );
+    }
+  }
+}
diff --git a/tools/zolertia/z1-bsl b/tools/zolertia/z1-bsl
new file mode 100755
index 0000000000000000000000000000000000000000..31d58d1dfca61180076a87c123225351962d2698
--- /dev/null
+++ b/tools/zolertia/z1-bsl
@@ -0,0 +1,1929 @@
+#!/usr/bin/env python
+# Serial Bootstrap Loader software for the MSP430 embedded proccessor.
+#
+# (C) 2001-2003 Chris Liechti <cliechti@gmx.net>
+# this is distributed under a free software license, see license-bsl.txt
+#
+# fixes from Colin Domoney
+#
+# based on the application note slas96b.pdf from Texas Instruments, Inc.,
+# Volker Rzehak
+# additional infos from slaa089a.pdf
+# 
+# Forked by Travis Goodspeed <travis at tnbelt.com> for use with the GoodFET
+# JTAG programmer.
+
+import sys, time, string, cStringIO, struct
+sys.path.append("/usr/lib/tinyos")
+import serial, os, glob
+
+#forked from TinyOS Telos version.
+VERSION = string.split("Revision: 1.39-goodfet-8 z1 fork")[1] 
+
+DEBUG = 0                                       #disable debug messages by default
+
+#copy of the patch file provided by TI
+#this part is (C) by Texas Instruments
+PATCH = """@0220
+31 40 1A 02 09 43 B0 12 2A 0E B0 12 BA 0D 55 42
+0B 02 75 90 12 00 1F 24 B0 12 BA 02 55 42 0B 02
+75 90 16 00 16 24 75 90 14 00 11 24 B0 12 84 0E
+06 3C B0 12 94 0E 03 3C 21 53 B0 12 8C 0E B2 40
+10 A5 2C 01 B2 40 00 A5 28 01 30 40 42 0C 30 40
+76 0D 30 40 AC 0C 16 42 0E 02 17 42 10 02 E2 B2
+08 02 14 24 B0 12 10 0F 36 90 00 10 06 28 B2 40
+00 A5 2C 01 B2 40 40 A5 28 01 D6 42 06 02 00 00
+16 53 17 83 EF 23 B0 12 BA 02 D3 3F B0 12 10 0F
+17 83 FC 23 B0 12 BA 02 D0 3F 18 42 12 02 B0 12
+10 0F D2 42 06 02 12 02 B0 12 10 0F D2 42 06 02
+13 02 38 E3 18 92 12 02 BF 23 E2 B3 08 02 BC 23
+30 41
+q
+"""
+
+#These BSL's are (C) by TI. They come with the application note slaa089a
+F1X_BSL = """@0220
+24 02 2E 02 31 40 20 02 2B D2 C0 43 EA FF 32 C2
+F2 C0 32 00 00 00 B2 40 80 5A 20 01 F2 40 85 00
+57 00 F2 40 80 00 56 00 E2 D3 21 00 E2 D3 22 00
+E2 C3 26 00 E2 C2 2A 00 E2 C2 2E 00 B2 40 10 A5
+2C 01 B2 40 00 A5 28 01 3B C0 3A 00 B0 12 D6 04
+82 43 12 02 09 43 36 40 0A 02 37 42 B0 12 AC 05
+C6 4C 00 00 16 53 17 83 F9 23 D2 92 0C 02 0D 02
+28 20 55 42 0B 02 75 90 12 00 80 24 75 90 10 00
+6D 24 B0 12 9C 04 55 42 0B 02 75 90 18 00 31 24
+75 90 1E 00 B8 24 75 90 20 00 17 24 2B B2 11 24
+75 90 16 00 22 24 75 90 14 00 B3 24 75 90 1A 00
+18 24 75 90 1C 00 45 24 04 3C B0 12 36 05 BE 3F
+21 53 B0 12 3C 05 BA 3F 03 43 B0 12 36 05 D2 42
+0E 02 56 00 D2 42 0F 02 57 00 D2 42 10 02 16 02
+AD 3F B0 12 36 05 10 42 0E 02 16 42 0E 02 15 43
+07 3C 36 40 FE FF B2 40 06 A5 10 02 35 40 0C 00
+B2 40 00 A5 2C 01 92 42 10 02 28 01 B6 43 00 00
+92 B3 2C 01 FD 23 15 83 F3 23 36 90 FE FF CD 27
+37 40 80 00 36 F0 80 FF 36 90 00 11 0E 28 07 57
+36 F0 00 FF 36 90 00 12 08 28 07 57 36 F0 00 FE
+04 3C 16 42 0E 02 17 42 10 02 35 43 75 96 03 20
+17 83 FC 23 B2 3F 82 46 00 02 B3 3F 36 40 E0 FF
+37 40 20 00 B0 12 AC 05 7C 96 01 24 2B D3 17 83
+F9 23 2B C2 B0 12 9C 04 2B D2 9F 3F 16 42 0E 02
+17 42 10 02 2B B2 38 24 3B D0 10 00 B0 12 AC 05
+36 90 00 10 06 2C 36 90 00 01 09 2C C6 4C 00 00
+25 3C B2 40 00 A5 2C 01 B2 40 40 A5 28 01 16 B3
+03 20 C2 4C 14 02 1A 3C C2 4C 15 02 86 9A FD FF
+08 24 2B D3 3B B0 20 00 04 20 3B D0 20 00 82 46
+00 02 36 90 01 02 04 28 3B D2 3B B0 10 00 02 24
+3B C0 32 00 1A 42 14 02 86 4A FF FF 16 53 17 83
+CD 23 B0 12 9C 04 61 3F B0 12 AC 05 17 83 FC 23
+B0 12 9C 04 5E 3F B2 40 F0 0F 0E 02 B2 40 10 00
+10 02 B2 40 80 00 0A 02 D2 42 10 02 0C 02 D2 42
+10 02 0D 02 82 43 12 02 09 43 36 40 0A 02 27 42
+7C 46 B0 12 40 05 17 83 FB 23 16 42 0E 02 17 42
+10 02 36 90 00 01 0A 28 B2 46 14 02 5C 42 14 02
+B0 12 40 05 17 83 5C 42 15 02 01 3C 7C 46 B0 12
+40 05 17 83 EE 23 B2 E3 12 02 5C 42 12 02 B0 12
+40 05 5C 42 13 02 B0 12 40 05 E0 3E 18 42 12 02
+B0 12 AC 05 C2 4C 12 02 B0 12 AC 05 C2 4C 13 02
+38 E3 3B B2 0A 24 86 9A FE FF 07 24 3B B0 20 00
+04 20 16 53 82 46 00 02 2B D3 18 92 12 02 08 23
+2B B3 06 23 30 41 E2 B2 28 00 FD 27 E2 B2 28 00
+FD 23 B2 40 24 02 60 01 E2 B2 28 00 FD 27 15 42
+70 01 05 11 05 11 05 11 82 45 02 02 05 11 82 45
+04 02 B2 80 1E 00 04 02 57 42 16 02 37 80 03 00
+05 11 05 11 17 53 FD 23 35 50 40 A5 82 45 2A 01
+35 42 B2 40 24 02 60 01 92 92 70 01 02 02 FC 2F
+15 83 F7 23 09 43 7C 40 90 00 02 3C 7C 40 A0 00
+C2 43 07 02 C9 EC 12 02 19 E3 1B C3 55 42 07 02
+55 45 56 05 00 55 0C 2E 2E 2E 2E 2E 2E 2E 2E 1A
+34 34 92 42 70 01 72 01 B2 50 0C 00 72 01 07 3C
+1B B3 0B 20 82 43 62 01 92 B3 62 01 FD 27 E2 C3
+21 00 0A 3C 4C 11 F6 2B 1B E3 82 43 62 01 92 B3
+62 01 FD 27 E2 D3 21 00 92 52 02 02 72 01 D2 53
+07 02 F0 90 0C 00 61 FC D1 23 30 41 C2 43 09 02
+1B C3 55 42 09 02 55 45 BC 05 00 55 0C 56 56 56
+56 56 56 56 56 36 76 00 E2 B2 28 00 FD 23 92 42
+70 01 72 01 92 52 04 02 72 01 82 43 62 01 92 B3
+62 01 FD 27 E2 B2 28 00 1E 28 2B D3 1C 3C 4C 10
+1A 3C 82 43 62 01 92 B3 62 01 FD 27 E2 B2 28 00
+01 28 1B E3 1B B3 01 24 2B D3 C9 EC 12 02 19 E3
+0A 3C 82 43 62 01 92 B3 62 01 FD 27 E2 B2 28 00
+E6 2B 4C 10 1B E3 92 52 02 02 72 01 D2 53 09 02
+C0 3F 82 43 62 01 92 B3 62 01 FD 27 E2 B2 28 00
+01 2C 2B D3 30 41
+q
+"""
+
+F4X_BSL = """@0220
+24 02 2E 02 31 40 20 02 2B D2 C0 43 EA FF 32 C2
+F2 C0 32 00 00 00 B2 40 80 5A 20 01 32 D0 40 00
+C2 43 50 00 F2 40 98 00 51 00 F2 C0 80 00 52 00
+D2 D3 21 00 D2 D3 22 00 D2 C3 26 00 E2 C3 22 00
+E2 C3 26 00 B2 40 10 A5 2C 01 B2 40 00 A5 28 01
+3B C0 3A 00 B0 12 DE 04 82 43 12 02 09 43 36 40
+0A 02 37 42 B0 12 B4 05 C6 4C 00 00 16 53 17 83
+F9 23 D2 92 0C 02 0D 02 28 20 55 42 0B 02 75 90
+12 00 80 24 75 90 10 00 6D 24 B0 12 A4 04 55 42
+0B 02 75 90 18 00 31 24 75 90 1E 00 B8 24 75 90
+20 00 17 24 2B B2 11 24 75 90 16 00 22 24 75 90
+14 00 B3 24 75 90 1A 00 18 24 75 90 1C 00 45 24
+04 3C B0 12 3E 05 BE 3F 21 53 B0 12 44 05 BA 3F
+03 43 B0 12 3E 05 D2 42 0E 02 50 00 D2 42 0F 02
+51 00 D2 42 10 02 16 02 AD 3F B0 12 3E 05 10 42
+0E 02 16 42 0E 02 15 43 07 3C 36 40 FE FF B2 40
+06 A5 10 02 35 40 0C 00 B2 40 00 A5 2C 01 92 42
+10 02 28 01 B6 43 00 00 92 B3 2C 01 FD 23 15 83
+F3 23 36 90 FE FF CD 27 37 40 80 00 36 F0 80 FF
+36 90 00 11 0E 28 07 57 36 F0 00 FF 36 90 00 12
+08 28 07 57 36 F0 00 FE 04 3C 16 42 0E 02 17 42
+10 02 35 43 75 96 03 20 17 83 FC 23 B2 3F 82 46
+00 02 B3 3F 36 40 E0 FF 37 40 20 00 B0 12 B4 05
+7C 96 01 24 2B D3 17 83 F9 23 2B C2 B0 12 A4 04
+2B D2 9F 3F 16 42 0E 02 17 42 10 02 2B B2 38 24
+3B D0 10 00 B0 12 B4 05 36 90 00 10 06 2C 36 90
+00 01 09 2C C6 4C 00 00 25 3C B2 40 00 A5 2C 01
+B2 40 40 A5 28 01 16 B3 03 20 C2 4C 14 02 1A 3C
+C2 4C 15 02 86 9A FD FF 08 24 2B D3 3B B0 20 00
+04 20 3B D0 20 00 82 46 00 02 36 90 01 02 04 28
+3B D2 3B B0 10 00 02 24 3B C0 32 00 1A 42 14 02
+86 4A FF FF 16 53 17 83 CD 23 B0 12 A4 04 61 3F
+B0 12 B4 05 17 83 FC 23 B0 12 A4 04 5E 3F B2 40
+F0 0F 0E 02 B2 40 10 00 10 02 B2 40 80 00 0A 02
+D2 42 10 02 0C 02 D2 42 10 02 0D 02 82 43 12 02
+09 43 36 40 0A 02 27 42 7C 46 B0 12 48 05 17 83
+FB 23 16 42 0E 02 17 42 10 02 36 90 00 01 0A 28
+B2 46 14 02 5C 42 14 02 B0 12 48 05 17 83 5C 42
+15 02 01 3C 7C 46 B0 12 48 05 17 83 EE 23 B2 E3
+12 02 5C 42 12 02 B0 12 48 05 5C 42 13 02 B0 12
+48 05 E0 3E 18 42 12 02 B0 12 B4 05 C2 4C 12 02
+B0 12 B4 05 C2 4C 13 02 38 E3 3B B2 0A 24 86 9A
+FE FF 07 24 3B B0 20 00 04 20 16 53 82 46 00 02
+2B D3 18 92 12 02 08 23 2B B3 06 23 30 41 E2 B3
+20 00 FD 27 E2 B3 20 00 FD 23 B2 40 24 02 60 01
+E2 B3 20 00 FD 27 15 42 70 01 05 11 05 11 05 11
+82 45 02 02 05 11 82 45 04 02 B2 80 1E 00 04 02
+57 42 16 02 37 80 03 00 05 11 05 11 17 53 FD 23
+35 50 40 A5 82 45 2A 01 35 42 B2 40 24 02 60 01
+92 92 70 01 02 02 FC 2F 15 83 F7 23 09 43 7C 40
+90 00 02 3C 7C 40 A0 00 C2 43 07 02 C9 EC 12 02
+19 E3 1B C3 55 42 07 02 55 45 5E 05 00 55 0C 2E
+2E 2E 2E 2E 2E 2E 2E 1A 34 34 92 42 70 01 72 01
+B2 50 0C 00 72 01 07 3C 1B B3 0B 20 82 43 62 01
+92 B3 62 01 FD 27 D2 C3 21 00 0A 3C 4C 11 F6 2B
+1B E3 82 43 62 01 92 B3 62 01 FD 27 D2 D3 21 00
+92 52 02 02 72 01 D2 53 07 02 F0 90 0C 00 59 FC
+D1 23 30 41 C2 43 09 02 1B C3 55 42 09 02 55 45
+C4 05 00 55 0C 56 56 56 56 56 56 56 56 36 76 00
+E2 B3 20 00 FD 23 92 42 70 01 72 01 92 52 04 02
+72 01 82 43 62 01 92 B3 62 01 FD 27 E2 B3 20 00
+1E 28 2B D3 1C 3C 4C 10 1A 3C 82 43 62 01 92 B3
+62 01 FD 27 E2 B3 20 00 01 28 1B E3 1B B3 01 24
+2B D3 C9 EC 12 02 19 E3 0A 3C 82 43 62 01 92 B3
+62 01 FD 27 E2 B3 20 00 E6 2B 4C 10 1B E3 92 52
+02 02 72 01 D2 53 09 02 C0 3F 82 43 62 01 92 B3
+62 01 FD 27 E2 B3 20 00 01 2C 2B D3 30 41
+q
+"""
+
+CALIB_TABLES = """
+84 C0 16 FE FF FF FF FF FF FF FF FF FF FF FF FF
+FF FF FF FF FF FF FF FF FF FF 10 08 80 00 00 01
+7E 27 0B 79 0D AA 7E 4D 06 DF 08 33 08 FE FF FF
+FF FF FF FF FF FF 08 01 8F 95 8E 9A 8D 88 86 D1
+"""
+
+#cpu types for "change baudrate"
+#use strings as ID so that they can be used in outputs too
+F1x                     = "F1x family"
+F2x                     = "F2x family"
+F4x                     = "F4x family"
+
+#known device list
+deviceids = {
+    0xf149: F1x,
+    0xf16c: F1x, #for GoodFET10 to '20
+    0xf112: F1x,
+    0xf413: F4x,
+    0xf123: F1x,
+    0xf449: F4x,
+    0x1232: F1x,
+    0xf26f: F2x, #for GoodFET20
+    0xf227: F2x, #for GoodFET30
+}
+
+#GoodFET firmware
+firmware = {
+    0xf16c: "http://goodfet.sourceforge.net/dist/msp430x1612.hex",
+    0xf26f: "http://goodfet.sourceforge.net/dist/msp430x2618.hex",
+    0xf227: "http://goodfet.sourceforge.net/dist/msp430x2274.hex"
+}
+
+class BSLException(Exception):
+    pass
+
+class LowLevel:
+    "lowlevel communication"
+    #Constants
+    MODE_SSP                = 0
+    MODE_BSL                = 1
+
+    BSL_SYNC                = 0x80
+    BSL_TXPWORD             = 0x10
+    BSL_TXBLK               = 0x12 #Transmit block to boot loader
+    BSL_UNLOCK_INFO         = 0x12 #unlocks / locks info segment A Not working on msp430f2617
+    BSL_RXBLK               = 0x14 #Receive  block from boot loader
+    BSL_ERASE               = 0x16 #Erase one segment
+    BSL_MERAS               = 0x18 #Erase complete FLASH memory
+    BSL_CHANGEBAUD          = 0x20 #Change baudrate
+    BSL_LOADPC              = 0x1A #Load PC and start execution
+    BSL_TXVERSION           = 0x1E #Get BSL version
+
+    #Upper limit of address range that might be modified by
+    #"BSL checksum bug".
+    BSL_CRITICAL_ADDR       = 0x0A00
+
+    #Header Definitions
+    CMD_FAILED              = 0x70
+    DATA_FRAME              = 0x80
+    DATA_ACK                = 0x90
+    DATA_NAK                = 0xA0
+
+    QUERY_POLL              = 0xB0
+    QUERY_RESPONSE          = 0x50
+
+    OPEN_CONNECTION         = 0xC0
+    ACK_CONNECTION          = 0x40
+
+    DEFAULT_TIMEOUT         =   1
+    DEFAULT_PROLONG         =  10
+    MAX_FRAME_SIZE          = 256
+    MAX_DATA_BYTES          = 250
+    MAX_DATA_WORDS          = 125
+
+    MAX_FRAME_COUNT         = 16
+
+    #Error messages
+    ERR_COM                 = "Unspecific error"
+    ERR_RX_NAK              = "NAK received (wrong password?)"
+    #ERR_CMD_NOT_COMPLETED   = "Command did not send ACK: indicates that it didn't complete correctly"
+    ERR_CMD_FAILED          = "Command failed, is not defined or is not allowed"
+    ERR_BSL_SYNC            = "Bootstrap loader synchronization error"
+    ERR_FRAME_NUMBER        = "Frame sequence number error."
+
+    def calcChecksum(self, data, length):
+        """Calculates a checksum of "data"."""
+        checksum = 0
+
+        for i in range(length/2):
+            checksum = checksum ^ (ord(data[i*2]) | (ord(data[i*2+1]) << 8))    #xor-ing
+        return 0xffff & (checksum ^ 0xffff)         #inverting
+
+    def __init__(self, aTimeout = None, aProlongFactor = None):
+        """init bsl object, don't connect yet"""
+        if aTimeout is None:
+            self.timeout = self.DEFAULT_TIMEOUT
+        else:
+            self.timeout = aTimeout
+        if aProlongFactor is None:
+            self.prolongFactor = self.DEFAULT_PROLONG
+        else:
+            self.prolongFactor = aProlongFactor
+
+        #flags for inverted use of control pins
+        #used for some hardware
+        self.invertRST = 0
+        self.invertTEST = 0
+    	self.swapRSTTEST = 0
+    	self.telosLatch = 0
+    	self.telosI2C = 0
+        
+        self.z1 = 0
+        
+        self.protocolMode = self.MODE_BSL
+        self.BSLMemAccessWarning = 0                #Default: no warning.
+        self.slowmode = 0
+
+    def comInit(self, port):
+        """Tries to open the serial port given and
+        initialises the port and variables.
+        The timeout and the number of allowed errors is multiplied by
+        'aProlongFactor' after transmission of a command to give
+        plenty of time to the micro controller to finish the command.
+        Returns zero if the function is successful."""
+        if DEBUG > 1: sys.stderr.write("* comInit()\n")
+        self.seqNo = 0
+        self.reqNo = 0
+        self.rxPtr = 0
+        self.txPtr = 0
+        # Startup-Baudrate: 9600,8,E,1, 1s timeout
+        self.serialport = serial.Serial(
+            port,
+            9600,
+            parity = serial.PARITY_EVEN,
+            timeout = self.timeout
+        )
+        if DEBUG: sys.stderr.write("using serial port %r\n" % self.serialport.portstr)
+        #self.SetRSTpin()                        #enable power
+        #self.SetTESTpin()                       #enable power
+        self.serialport.flushInput()
+        self.serialport.flushOutput()
+
+    def comDone(self):
+        """Closes the used serial port.
+        This function must be called at the end of a program,
+        otherwise the serial port might not be released and can not be
+        used in other programs.
+        Returns zero if the function is successful."""
+        if DEBUG > 1: sys.stderr.write("* comDone()")
+        self.SetRSTpin(1)                       #disable power
+        self.SetTESTpin(0)                      #disable power
+        self.serialport.close()
+
+    def comRxHeader(self):
+        """receive header and split data"""
+        if DEBUG > 1: sys.stderr.write("* comRxHeader()\n")
+
+        hdr = self.serialport.read(1)
+        if not hdr: raise BSLException("Timeout")
+        rxHeader = ord(hdr) & 0xf0;
+        rxNum    = ord(hdr) & 0x0f;
+
+        if self.protocolMode == self.MODE_BSL:
+            self.reqNo = 0
+            self.seqNo = 0
+            rxNum = 0
+        if DEBUG > 1: sys.stderr.write("* comRxHeader() OK\n")
+        return rxHeader, rxNum
+
+    def comRxFrame(self, rxNum):
+        if DEBUG > 1: sys.stderr.write("* comRxFrame()\n")
+        rxFrame = chr(self.DATA_FRAME | rxNum)
+
+        if DEBUG > 2: sys.stderr.write("  comRxFrame() header...\n")
+        rxFramedata = self.serialport.read(3)
+        if len(rxFramedata) != 3: raise BSLException("Timeout")
+        rxFrame = rxFrame + rxFramedata
+
+        if DEBUG > 3: sys.stderr.write("  comRxFrame() check header...\n")
+        if rxFrame[1] == chr(0) and rxFrame[2] == rxFrame[3]:   #Add. header info. correct?
+            rxLengthCRC = ord(rxFrame[2]) + 2       #Add CRC-Bytes to length
+            if DEBUG > 2: sys.stderr.write("  comRxFrame() receiving data, size: %s\n" % rxLengthCRC)
+
+            rxFramedata = self.serialport.read(rxLengthCRC)
+            if len(rxFramedata) != rxLengthCRC: raise BSLException("Timeout")
+            rxFrame = rxFrame + rxFramedata
+            #Check received frame:
+            if DEBUG > 3: sys.stderr.write("  comRxFrame() crc check\n")
+            #rxLength+4: Length with header but w/o CRC:
+            checksum = self.calcChecksum(rxFrame, ord(rxFrame[2]) + 4)
+            if rxFrame[ord(rxFrame[2])+4] == chr(0xff & checksum) and \
+               rxFrame[ord(rxFrame[2])+5] == chr(0xff & (checksum >> 8)): #Checksum correct?
+                #Frame received correctly (=> send next frame)
+                if DEBUG > 2: sys.stderr.write("* comRxFrame() OK\n")
+                return rxFrame
+            else:
+                if DEBUG: sys.stderr.write("  comRxFrame() Checksum wrong\n")
+        else:
+            if DEBUG: sys.stderr.write("  comRxFrame() Header corrupt %r" % rxFrame)
+        raise BSLException(self.ERR_COM)            #Frame has errors!
+
+    def comTxHeader(self, txHeader):
+        """send header"""
+        if DEBUG > 1: sys.stderr.write("* txHeader()\n")
+        self.serialport.write(txHeader)
+
+    def comTxRx(self, cmd, dataOut, length):
+        """Sends the command cmd with the data given in dataOut to the
+        microcontroller and expects either an acknowledge or a frame
+        with result from the microcontroller.  The results are stored
+        in dataIn (if not a NULL pointer is passed).
+        In this routine all the necessary protocol stuff is handled.
+        Returns zero if the function was successful."""
+        if DEBUG > 1: sys.stderr.write("* comTxRx()\n")
+        txFrame     = []
+        rxHeader    = 0
+        rxNum       = 0
+
+        dataOut = list(dataOut)     #convert to a list for simpler data fill in
+        #Transmitting part ----------------------------------------
+        #Prepare data for transmit
+        if (length % 2) != 0:
+            #/* Fill with one byte to have even number of bytes to send */
+            if self.protocolMode == self.MODE_BSL:
+                dataOut.append(0xFF)  #fill with 0xFF
+            else:
+                dataOut.append(0)     #fill with zero
+
+        txFrame = "%c%c%c%c" % (self.DATA_FRAME | self.seqNo, cmd, len(dataOut), len(dataOut))
+
+        self.reqNo = (self.seqNo + 1) % self.MAX_FRAME_COUNT
+
+        txFrame = txFrame + string.join(dataOut,'')
+        checksum = self.calcChecksum(txFrame, length + 4)
+        txFrame = txFrame + chr(checksum & 0xff)
+        txFrame = txFrame + chr((checksum >> 8) & 0xff)
+
+        accessAddr = (0x0212 + (checksum^0xffff)) & 0xfffe  #0x0212: Address of wCHKSUM
+        if self.BSLMemAccessWarning and accessAddr < self.BSL_CRITICAL_ADDR:
+            sys.stderr.write("WARNING: This command might change data at address %04x or %04x!\n" % (accessAddr, accessAddr + 1))
+
+        self.serialport.flushInput()                #clear receiving queue
+        #TODO: Check after each transmitted character,
+        #TODO: if microcontroller did send a character (probably a NAK!).
+        for c in txFrame:
+            self.serialport.write(c)
+            if DEBUG > 3: sys.stderr.write("\ttx %02x" % ord(c))
+            #if self.serialport.inWaiting(): break  #abort when BSL replies, probably NAK
+        else:
+            if DEBUG > 1: sys.stderr.write( "  comTxRx() transmit OK\n")
+
+        #Receiving part -------------------------------------------
+        rxHeader, rxNum = self.comRxHeader()        #receive header
+        if DEBUG > 1: sys.stderr.write("  comTxRx() rxHeader=0x%02x, rxNum=%d, seqNo=%d, reqNo=%s\n" % (rxHeader, rxNum, self.seqNo, self.reqNo))
+        if rxHeader == self.DATA_ACK:               #acknowledge/OK
+            if DEBUG > 2: sys.stderr.write("  comTxRx() DATA_ACK\n")
+            if rxNum == self.reqNo:
+                self.seqNo = self.reqNo
+                if DEBUG > 2: sys.stderr.write("* comTxRx() DATA_ACK OK\n")
+                return          #Acknowledge received correctly => next frame
+            raise BSLException(self.ERR_FRAME_NUMBER)
+        elif rxHeader == self.DATA_NAK:             #not acknowledge/error
+            if DEBUG > 2: sys.stderr.write("* comTxRx() DATA_NAK\n")
+            raise BSLException(self.ERR_RX_NAK)
+        elif rxHeader == self.DATA_FRAME:           #receive data
+            if DEBUG > 2: sys.stderr.write("* comTxRx() DATA_FRAME\n")
+            if rxNum == self.reqNo:
+                rxFrame = self.comRxFrame(rxNum)
+                return rxFrame
+            raise BSLException(self.ERR_FRAME_NUMBER)
+        elif rxHeader == self.CMD_FAILED:           #Frame ok, but command failed.
+            if DEBUG > 2: sys.stderr.write("*  comTxRx() CMD_FAILED\n")
+            raise BSLException(self.ERR_CMD_FAILED)
+
+        raise BSLException("Unknown header 0x%02x\nAre you downloading to RAM into an old device that requires the patch? Try option -U" % rxHeader)
+
+    def SetDTR(self, level, invert):
+        """Controls DTR pin (0: GND; 1: VCC; unless inverted flag is set)"""
+        #print 'fucking the dtr'
+        if invert:
+            self.serialport.setDTR(not level)
+        else:
+            self.serialport.setDTR(level)
+        if self.slowmode:
+            time.sleep(0.040)
+
+    def SetRTS(self, level, invert):
+        """Controls RTS pin (0: GND; 1: VCC; unless inverted flag is set)"""
+        if invert:
+            self.serialport.setRTS(not level)
+        else:
+            self.serialport.setRTS(level)
+        if self.slowmode:
+            time.sleep(0.040)
+
+    def SetRSTpin(self, level=1):
+        """Controls RST/NMI pin (0: GND; 1: VCC; unless inverted flag is set)"""
+        if self.swapRSTTEST:
+            self.SetRTS(level, self.invertRST)
+        else:
+            self.SetDTR(level, self.invertRST)
+
+    def SetTESTpin(self, level=1):
+        """Controls TEST pin (inverted on board: 0: VCC; 1: GND; unless inverted flag is set)"""
+        if self.swapRSTTEST:
+            self.SetDTR(level, self.invertTEST)
+        else:
+            self.SetRTS(level, self.invertTEST)
+
+
+    def writepicROM(self, address, data):
+        ''' Writes data to @address'''
+        for i in range(7,-1,-1):
+            self.picROMclock((address >> i) & 0x01)
+        self.picROMclock(0)
+        recbuf = 0
+        for i in range(7,-1,-1):
+            s = ((data >> i) & 0x01)
+            #print s
+            if i < 1:
+                r = not self.picROMclock(s, True)
+            else:
+                r = not self.picROMclock(s)
+            recbuf = (recbuf << 1) + r
+
+        self.picROMclock(0, True)
+        #k = 1
+        #while not self.serial.getCTS():
+        #    pass 
+        #time.sleep(0.1)
+        return recbuf
+
+    def readpicROM(self, address):
+        ''' reads a byte from @address'''
+        for i in range(7,-1,-1):
+            self.picROMclock((address >> i) & 0x01)
+        self.picROMclock(1)
+        recbuf = 0
+        r = 0
+        for i in range(7,-1,-1):
+            r = self.picROMclock(0)
+            recbuf = (recbuf << 1) + r
+        self.picROMclock(r)
+        #time.sleep(0.1)
+        return recbuf
+        
+    def picROMclock(self, masterout, slow = False):
+        #print "setting masterout to "+str(masterout)
+        self.serialport.setRTS(masterout)
+        self.serialport.setDTR(1)
+        #time.sleep(0.02)
+        self.serialport.setDTR(0)
+        if slow:
+            time.sleep(0.02)
+        return self.serialport.getCTS()
+
+    def picROMfastclock(self, masterout):
+        #print "setting masterout to "+str(masterout)
+        self.serialport.setRTS(masterout)
+        self.serialport.setDTR(1)
+        self.serialport.setDTR(0)
+        time.sleep(0.02)
+        return self.serialport.getCTS()
+
+    def bslResetZ1(self, invokeBSL=0):
+        '''
+        Applies BSL entry sequence on RST/NMI and TEST/VPP pins
+        Parameters:
+            invokeBSL = 1: complete sequence
+            invokeBSL = 0: only RST/NMI pin accessed
+            
+        By now only BSL mode is accessed
+        '''
+        
+        if DEBUG > 1: sys.stderr.write("* bslReset(invokeBSL=%s)\n" % invokeBSL)
+        if invokeBSL:
+            #sys.stderr.write("in Z1 bsl reset...\n")
+            time.sleep(0.1)
+            self.writepicROM(0xFF, 0xFF)
+            time.sleep(0.1)
+            #sys.stderr.write("z1 bsl reset done...\n")
+        else:
+            #sys.stderr.write("in Z1 reset...\n")
+            time.sleep(0.1)
+            self.writepicROM(0xFF, 0xFE)
+            time.sleep(0.1)
+            #sys.stderr.write("z1 reset done...\n")
+
+    def telosSetSCL(self, level):
+        self.serialport.setRTS(not level)
+
+    def telosSetSDA(self, level):
+        self.serialport.setDTR(not level)
+
+    def telosI2CStart(self):
+    	self.telosSetSDA(1)
+    	self.telosSetSCL(1)
+    	self.telosSetSDA(0)
+
+    def telosI2CStop(self):
+    	self.telosSetSDA(0)
+    	self.telosSetSCL(1)
+    	self.telosSetSDA(1)
+
+    def telosI2CWriteBit(self, bit):
+    	self.telosSetSCL(0)
+    	self.telosSetSDA(bit)
+        time.sleep(2e-6)
+    	self.telosSetSCL(1)
+        time.sleep(1e-6)
+    	self.telosSetSCL(0)
+
+    def telosI2CWriteByte(self, byte):
+        self.telosI2CWriteBit( byte & 0x80 );
+        self.telosI2CWriteBit( byte & 0x40 );
+        self.telosI2CWriteBit( byte & 0x20 );
+        self.telosI2CWriteBit( byte & 0x10 );
+        self.telosI2CWriteBit( byte & 0x08 );
+        self.telosI2CWriteBit( byte & 0x04 );
+        self.telosI2CWriteBit( byte & 0x02 );
+        self.telosI2CWriteBit( byte & 0x01 );
+        self.telosI2CWriteBit( 0 );  # "acknowledge"
+
+    def telosI2CWriteCmd(self, addr, cmdbyte):
+    	self.telosI2CStart()
+        self.telosI2CWriteByte( 0x90 | (addr << 1) )
+    	self.telosI2CWriteByte( cmdbyte )
+    	self.telosI2CStop()
+
+    def telosBReset(self,invokeBSL=0):
+    	# "BSL entry sequence at dedicated JTAG pins"
+            # rst !s0: 0 0 0 0 1 1
+    	# tck !s1: 1 0 1 0 0 1
+            #   s0|s1: 1 3 1 3 2 0
+    
+    	# "BSL entry sequence at shared JTAG pins"
+            # rst !s0: 0 0 0 0 1 1
+    	# tck !s1: 0 1 0 1 1 0
+            #   s0|s1: 3 1 3 1 0 2
+    	if invokeBSL:
+    	  self.telosI2CWriteCmd(0,1)
+    	  self.telosI2CWriteCmd(0,3)
+    	  self.telosI2CWriteCmd(0,1)
+    	  self.telosI2CWriteCmd(0,3)
+    	  self.telosI2CWriteCmd(0,2)
+    	  self.telosI2CWriteCmd(0,0)
+    	else:
+    	  self.telosI2CWriteCmd(0,3)
+    	  self.telosI2CWriteCmd(0,2)
+    	  self.telosI2CWriteCmd(0,0)
+          time.sleep(0.250)       #give MSP430's oscillator time to stabilize
+    	self.serialport.flushInput()  #clear buffers
+
+    def bslReset(self, invokeBSL=0):
+        """Applies BSL entry sequence on RST/NMI and TEST/VPP pins
+        Parameters:
+            invokeBSL = 1: complete sequence
+            invokeBSL = 0: only RST/NMI pin accessed
+
+        RST is inverted twice on boot loader hardware
+        TEST is inverted (only once)
+        Need positive voltage on DTR, RTS for power-supply of hardware"""
+        
+        #print 'goint to reset!'
+        
+    	if self.telosI2C:
+    	    self.telosBReset(invokeBSL)
+    	    return
+    
+        if self.z1:
+            if DEBUG > 1: sys.stderr.write("* entering bsl with z1\n")
+            self.bslResetZ1(invokeBSL)
+            return
+    
+        if DEBUG > 1: sys.stderr.write("* bslReset(invokeBSL=%s)\n" % invokeBSL)
+        self.SetRSTpin(1)       #power suply
+        self.SetTESTpin(1)      #power suply
+        time.sleep(0.250)       #charge capacitor on boot loader hardware
+    
+    	if self.telosLatch:
+    	    self.SetTESTpin(0)
+    	    self.SetRSTpin(0)
+    	    self.SetTESTpin(1)
+    
+            self.SetRSTpin(0)       #RST  pin: GND
+        if invokeBSL:
+            self.SetTESTpin(1)  #TEST pin: GND
+            self.SetTESTpin(0)  #TEST pin: Vcc
+            self.SetTESTpin(1)  #TEST pin: GND
+            self.SetTESTpin(0)  #TEST pin: Vcc
+            self.SetRSTpin (1)  #RST  pin: Vcc
+            self.SetTESTpin(1)  #TEST pin: GND
+        else:
+            self.SetRSTpin(1)   #RST  pin: Vcc
+        time.sleep(0.250)       #give MSP430's oscillator time to stabilize
+    
+        self.serialport.flushInput()    #clear buffers
+
+    def bslSync(self,wait=0):
+        """Transmits Synchronization character and expects to receive Acknowledge character
+        if wait is 0 it must work the first time. otherwise if wait is 1
+        it is retried (forever).
+        """
+        loopcnt = 5                                 #Max. tries to get synchronization
+
+        if DEBUG > 1: sys.stderr.write("* bslSync(wait=%d)\n" % wait)
+        while wait or loopcnt:
+            loopcnt = loopcnt - 1                   #count down tries
+            self.serialport.flushInput()            #clear input, in case a prog is running
+
+            self.serialport.write(chr(self.BSL_SYNC))   #Send synchronization byte
+            c = self.serialport.read(1)             #read answer
+            if c == chr(self.DATA_ACK):             #ACk
+                if DEBUG > 1: sys.stderr.write("  bslSync() OK\n")
+                return                              #Sync. successful
+            elif not c:                             #timeout
+                    if loopcnt > 4:
+                        if DEBUG > 1:
+                            sys.stderr.write("  bslSync() timeout, retry ...\n")
+                    elif loopcnt == 4:
+                        #nmi may have caused the first reset to be ignored, try again
+                        self.bslReset(0) 
+                        self.bslReset(1)
+                    elif loopcnt > 0:
+                        if DEBUG > 1:
+                            sys.stderr.write("  bslSync() timeout, retry ...\n")
+                    else :
+                        if DEBUG > 1:
+                            sys.stderr.write("  bslSync() timeout\n")
+            else:                                   #garbage
+                if DEBUG > 1: sys.stderr.write("  bslSync() failed (0x%02x), retry ...\n" % ord(c))
+                
+                raise BSLException(self.ERR_BSL_SYNC)       #Sync. failed
+
+    def bslTxRx(self, cmd, addr, length = 0, blkout = None, wait=0):
+        """Transmits a command (cmd) with its parameters:
+        start-address (addr), length (len) and additional
+        data (blkout) to boot loader.
+        wait specified if the bsl sync should be tried once or
+        repeated, forever
+        Parameters return by boot loader are passed via blkin.
+        """
+        if DEBUG > 1: sys.stderr.write("* bslTxRx()\n")
+
+        if cmd == self.BSL_TXBLK:
+            #Align to even start address
+            if (addr % 2) != 0:
+                addr = addr - 1                     #Decrement address and
+                blkout = chr(0xFF) + blkOut         #fill first byte of blkout with 0xFF
+                length = length + 1
+            #Make sure that len is even
+            if (length % 2) != 0:
+                blkout = blkout + chr(0xFF)         #Inc. len and fill last byte of blkout with 0xFF
+                length = length + 1
+
+        elif cmd == self.BSL_RXBLK:
+            #Align to even start address
+            if (addr % 2) != 0:
+                addr = addr - 1                     #Decrement address but
+                length = length + 1                 #request an additional byte
+            #Make sure that len is even
+            if (length % 2) != 0:
+                length = length + 1
+
+        #if cmd == self.BSL_TXBLK or cmd == self.BSL_TXPWORD:
+        #    length = len + 4
+
+        #Add necessary information data to frame
+        dataOut =  struct.pack("<HH", addr, length)
+
+        if blkout: #Copy data out of blkout into frame
+            dataOut = dataOut + blkout
+
+        self.bslSync(wait)                          #synchronize BSL
+        rxFrame = self.comTxRx(cmd, dataOut, len(dataOut))  #Send frame
+        if rxFrame:                                 #test answer
+            return rxFrame[4:] #return only data w/o [hdr,null,len,len]
+        else:
+            return rxFrame
+
+
+class Segment:
+    """store a string with memory contents along with its startaddress"""
+    def __init__(self, startaddress = 0, data=None):
+        if data is None:
+            self.data = ''
+        else:
+            self.data = data
+        self.startaddress = startaddress
+
+    def __getitem__(self, index):
+        return self.data[index]
+
+    def __len__(self):
+        return len(self.data)
+
+    def __repr__(self):
+        return "Segment(startaddress = 0x%04x, data=%r)" % (self.startaddress, self.data)
+
+class Memory:
+    """represent memory contents. with functions to load files"""
+    def __init__(self, filename=None):
+        self.segments = []
+        if filename:
+            self.filename = filename
+            self.loadFile(filename)
+
+    def append(self, seg):
+        self.segments.append(seg)
+
+    def __getitem__(self, index):
+        return self.segments[index]
+
+    def __len__(self):
+        return len(self.segments)
+
+    def loadIHex(self, file):
+        """load data from a (opened) file in Intel-HEX format"""
+        segmentdata = []
+        currentAddr = 0
+        startAddr   = 0
+        lines = file.readlines()
+        for l in lines:
+            if l[0] != ':': raise BSLException("File Format Error\n")
+            l = l.strip()       #fix CR-LF issues...
+            length  = int(l[1:3],16)
+            address = int(l[3:7],16)
+            type    = int(l[7:9],16)
+            check   = int(l[-2:],16)
+            if type == 0x00:
+                if currentAddr != address:
+                    if segmentdata:
+                        self.segments.append( Segment(startAddr, string.join(segmentdata,'')) )
+                    startAddr = currentAddr = address
+                    segmentdata = []
+                for i in range(length):
+                    segmentdata.append( chr(int(l[9+2*i:11+2*i],16)) )
+                currentAddr = length + currentAddr
+            elif type in (0x01, 0x02, 0x03, 0x04, 0x05):
+                pass
+            else:
+                sys.stderr.write("Ignored unknown field (type 0x%02x) in ihex file.\n" % type)
+        if segmentdata:
+            self.segments.append( Segment(startAddr, string.join(segmentdata,'')) )
+
+    def loadTIText(self, file):
+        """load data from a (opened) file in TI-Text format"""
+        next        = 1
+        startAddr   = 0
+        segmentdata = []
+        #Convert data for MSP430, TXT-File is parsed line by line
+        while next >= 1:
+            #Read one line
+            l = file.readline()
+            if not l: break #EOF
+            l = l.strip()
+            if l[0] == 'q': break
+            elif l[0] == '@':        #if @ => new address => send frame and set new addr.
+                #create a new segment
+                if segmentdata:
+                    self.segments.append( Segment(startAddr, string.join(segmentdata,'')) )
+                startAddr = int(l[1:],16)
+                segmentdata = []
+            else:
+                for i in string.split(l):
+                    segmentdata.append(chr(int(i,16)))
+        if segmentdata:
+            self.segments.append( Segment(startAddr, string.join(segmentdata,'')) )
+
+    def loadELF(self, file):
+        """load data from a (opened) file in ELF object format.
+        File must be seekable"""
+        import elf
+        obj = elf.ELFObject()
+        obj.fromFile(file)
+        if obj.e_type != elf.ELFObject.ET_EXEC:
+            raise Exception("No executable")
+        for section in obj.getSections():
+            if DEBUG:
+                sys.stderr.write("ELF section %s at 0x%04x %d bytes\n" % (section.name, section.lma, len(section.data)))
+            if len(section.data):
+                self.segments.append( Segment(section.lma, section.data) )
+        
+    def loadFile(self, filename):
+        """fill memory with the contents of a file. file type is determined from extension"""
+        #TODO: do a contents based detection
+        if filename[-4:].lower() == '.txt':
+            self.loadTIText(open(filename, "rb"))
+        elif filename[-4:].lower() in ('.a43', '.hex'):
+            self.loadIHex(open(filename, "rb"))
+        else:
+            self.loadELF(open(filename, "rb"))
+
+    def getMemrange(self, fromadr, toadr):
+        """get a range of bytes from the memory. unavailable values are filled with 0xff."""
+        res = ''
+        toadr = toadr + 1   #python indxes are excluding end, so include it
+        while fromadr < toadr:
+            #print "fromto: %04x %04x" % (fromadr, toadr)
+            for seg in self.segments:
+                #print seg
+                segend = seg.startaddress + len(seg.data)
+                if seg.startaddress <= fromadr and fromadr < segend:
+                    #print "startok 0x%04x %d" % (seg.startaddress, len(seg.data))
+                    #print ("0x%04x "*3) % (segend, fromadr, toadr)
+                    if toadr > segend:   #not all data in segment
+                        #print "out of segment"
+                        catchlength = segend-fromadr
+                    else:
+                        catchlength = toadr-fromadr
+                    #print toadr-fromadr
+                    #print catchlength
+                    res = res + seg.data[fromadr-seg.startaddress : fromadr-seg.startaddress+catchlength]
+                    fromadr = fromadr + catchlength    #adjust start
+                    if len(res) >= toadr-fromadr:
+                        break#return res
+            else:
+                    res = res + chr(255)
+                    fromadr = fromadr + 1 #adjust start
+                    #print "fill FF"
+        #print "res: %r" % res
+        return res
+
+
+class BootStrapLoader(LowLevel):
+    """higher level Bootstrap Loader functions."""
+
+    ERR_VERIFY_FAILED       = "Error: verification failed"
+    ERR_ERASE_CHECK_FAILED  = "Error: erase check failed"
+
+    ACTION_PROGRAM          = 0x01 #Mask: program data
+    ACTION_VERIFY           = 0x02 #Mask: verify data
+    ACTION_ERASE_CHECK      = 0x04 #Mask: erase check
+
+    #Max. bytes sent within one frame if parsing a TI TXT file.
+    #( >= 16 and == n*16 and <= MAX_DATA_BYTES!)
+    MAXDATA                 = 240-16
+
+
+    def __init__(self, *args, **kargs):
+        LowLevel.__init__(self, *args, **kargs)
+        self.byteCtr        = 0
+        self.meraseCycles   = 1
+        self.patchRequired  = 0
+        self.patchLoaded    = 0
+        self.bslVer         = 0
+        self.passwd         = None
+        self.data           = None
+        self.maxData        = self.MAXDATA
+        self.cpu            = None
+        self.pwdsent        = False
+
+
+    def preparePatch(self):
+        """prepare to download patch"""
+        if DEBUG > 1: sys.stderr.write("* preparePatch()\n")
+
+        if self.patchLoaded:
+            #Load PC with 0x0220.
+            #This will invoke the patched bootstrap loader subroutines.
+            self.bslTxRx(self.BSL_LOADPC,           #Command: Load PC
+                           0x0220)                  #Address to load into PC
+            self.BSLMemAccessWarning = 0 #Error is removed within workaround code
+        return
+
+    def postPatch(self):
+        """setup after the patch is loaded"""
+        if DEBUG > 1: sys.stderr.write("* postPatch()\n")
+        if self.patchLoaded:
+            self.BSLMemAccessWarning = 1                #Turn warning back on.
+
+    
+    def verifyBlk(self, addr, blkout, action):
+        """verify memory against data or 0xff"""
+        if DEBUG > 1: sys.stderr.write("* verifyBlk()\n")
+
+        if action & self.ACTION_VERIFY or action & self.ACTION_ERASE_CHECK:
+            if DEBUG: sys.stderr.write("  Check starting at 0x%04x, %d bytes ... \n" % (addr, len(blkout)))
+
+            self.preparePatch()
+            blkin = self.bslTxRx(self.BSL_RXBLK, addr, len(blkout))
+            self.postPatch()
+
+            for i in range(len(blkout)):
+                if action & self.ACTION_VERIFY:
+                    #Compare data in blkout and blkin
+                    if blkin[i] != blkout[i]:
+                        sys.stderr.write("Verification failed at 0x%04x (0x%02x, 0x%02x)\n" % (addr+i, ord(blkin[i]), ord(blkout[i])))
+                        sys.stderr.flush()
+                        raise BSLException(self.ERR_VERIFY_FAILED)      #Verify failed!
+                    continue
+                elif action & self.ACTION_ERASE_CHECK:
+                    #Compare data in blkin with erase pattern
+                    if blkin[i] != chr(0xff):
+                        sys.stderr.write("Erase Check failed at 0x%04x (0x%02x)\n" % (addr+i, ord(blkin[i])))
+                        sys.stderr.flush()
+                        raise BSLException(self.ERR_ERASE_CHECK_FAILED) #Erase Check failed!
+                    continue
+    def readBlk(self,adr,len):
+        """Read a block of memory."""
+        blkin = self.bslTxRx(self.BSL_RXBLK, addr, len(blkout))
+        
+    def programBlk(self, addr, blkout, action):
+        """program a memory block"""
+        if DEBUG > 1: sys.stderr.write("* programBlk()\n")
+
+        #Check, if specified range is erased
+        self.verifyBlk(addr, blkout, action & self.ACTION_ERASE_CHECK)
+
+        if action & self.ACTION_PROGRAM:
+            if DEBUG: sys.stderr.write("  Program starting at 0x%04x, %i bytes ...\n" % (addr, len(blkout)))
+            self.preparePatch()
+            #Program block
+            self.bslTxRx(self.BSL_TXBLK, addr, len(blkout), blkout)
+            self.postPatch()
+
+        #Verify block
+        self.verifyBlk(addr, blkout, action & self.ACTION_VERIFY)
+
+    #segments:
+    #list of tuples or lists:
+    #segements = [ (addr1, [d0,d1,d2,...]), (addr2, [e0,e1,e2,...])]
+    def programData(self, segments, action):
+        """programm or verify data"""
+        if DEBUG > 1: sys.stderr.write("* programData()\n")
+        for seg in segments:
+            currentAddr = seg.startaddress
+            pstart = 0
+            while pstart<len(seg.data):
+                length = self.MAXDATA
+                if pstart+length > len(seg.data):
+                    length = len(seg.data) - pstart
+                self.programBlk(currentAddr, seg.data[pstart:pstart+length], action)
+                pstart = pstart + length
+                currentAddr = currentAddr + length
+                self.byteCtr = self.byteCtr + length #total sum
+    
+    def uploadData(self, startaddress, size, wait=0):
+        """upload a datablock"""
+        if DEBUG > 1: sys.stderr.write("* uploadData()\n")
+        data = ''
+        pstart = 0
+        while pstart<size:
+            length = self.maxData
+            if pstart+length > size:
+                length = size - pstart
+            data = data + self.bslTxRx(self.BSL_RXBLK,
+                                       pstart+startaddress,
+                                       length,
+                                       wait=wait)[:-2] #cut away checksum
+            pstart = pstart + length
+        return data
+
+    def txPasswd(self, passwd=None, wait=0):
+        """transmit password, default if None is given."""
+        if DEBUG > 1: sys.stderr.write("* txPassword(%r)\n" % passwd)
+        if passwd is None or self.pwdsent:
+            #Send "standard" password to get access to protected functions.
+            sys.stderr.write("Transmit default password ...\n")
+            sys.stderr.flush()
+            #Flash is completely erased, the contents of all Flash cells is 0xff
+            passwd = chr(0xff)*32
+        else:
+            #sanity check of password
+            if len(passwd) != 32:
+                raise ValueError, "password has wrong length (%d)\n" % len(passwd)
+            sys.stderr.write('Transmit password ...\n')
+            sys.stderr.flush()
+        #send the password
+        self.bslTxRx(self.BSL_TXPWORD,      #Command: Transmit Password
+                       0xffe0,              #Address of interupt vectors
+                       0x0020,              #Number of bytes
+                       passwd,              #password
+                       wait=wait)           #if wait is 1, try to sync forever
+        self.pwdsent = True
+        
+
+    def getNewPassword(self):
+        print 'getting new password'
+        newpassword = self.bslTxRx(self.BSL_RXBLK, 0xffe0, 0x0020)
+        return newpassword
+
+
+    def writeCalibTables(self):
+        print 'writing new tables'
+        print CALIB_TABLES
+        calibtables = ["84C016FEFFFFFFFFFFFFFFFFFFFFFFFF",
+                       "FFFFFFFFFFFFFFFFFFFF100880000001",
+                       "7E270B790DAA7E4D06DF083308FEFFFF",
+                       "FFFFFFFFFFFF08018F958E9A8D8886D1"]
+        self.programBlk(0x10C0, "84C016FEFFFFFFFFFFFFFFFFFFFFFFFF", self.ACTION_PROGRAM)
+        self.programBlk(0x10D0, "FFFFFFFFFFFFFFFFFFFF100880000001", self.ACTION_PROGRAM)
+        self.programBlk(0x10E0, "7E270B790DAA7E4D06DF083308FEFFFF", self.ACTION_PROGRAM)
+        self.programBlk(0x10F0, "FFFFFFFFFFFF08018F958E9A8D8886D1", self.ACTION_PROGRAM)
+
+    def writeCalibTables2(self):
+        print 'writing new tables 2ond part'
+        #self.programBlk(0x10C0, "84C016FEFFFFFFFFFFFFFFFFFFFFFFFF", self.ACTION_PROGRAM)
+        #self.programBlk(0x10D0, "FFFFFFFFFFFFFFFFFFFF100880000001", self.ACTION_PROGRAM)
+        #self.programBlk(0x10E0, "7E270B790DAA7E4D06DF083308FEFFFF", self.ACTION_PROGRAM)
+        #self.programBlk(0x10F0, "FFFFFFFFFFFF08018F958E9A8D8886D1", self.ACTION_PROGRAM)
+
+    def actionSecureInfoSegment(self):
+        print 'securing info segment'
+        self.programBlk(0xFFBE, "0000", self.ACTION_PROGRAM)
+        print 'info segment secured'
+
+    #-----------------------------------------------------------------
+
+    def actionMassErase(self):
+        """Erase the flash memory completely (with mass erase command)"""
+        sys.stderr.write("Mass Erase...\n")
+        sys.stderr.flush()
+        self.bslReset(1)                            #Invoke the boot loader.
+        for i in range(self.meraseCycles):
+            if i == 1: sys.stderr.write("Additional Mass Erase Cycles...\n")
+            self.bslTxRx(self.BSL_MERAS,            #Command: Mass Erase
+                                0xff00,             #Any address within flash memory.
+                                0xa506)             #Required setting for mass erase!
+        self.passwd = None                          #No password file required!
+        #print "Mass Erase complete"
+        #Transmit password to get access to protected BSL functions.
+        self.txPasswd()
+
+    def actionMainErase(self):
+        """Erase the main flash memory only"""
+        sys.stderr.write("Main Erase...\n")
+        sys.stderr.flush()
+        self.bslTxRx(self.BSL_ERASE,                #Command: Segment Erase
+                            0xfffe,                 #Any address within flash memory.
+                            0xa504)                 #Required setting for main erase!
+        #self.passwd = None                          #Password gets erased WHY??
+
+
+
+    def actionStartBSL(self, usepatch=1, adjsp=1, replacementBSL=None, forceBSL=0, mayuseBSL=0, speed=None, bslreset=1):
+        """start BSL, download patch if desired and needed, adjust SP if desired"""
+        sys.stderr.write("Invoking BSL...\n")
+        sys.stderr.flush()
+        
+        #for '30, invertTEST=0, else =1
+        if bslreset:
+            #detext if is z1?
+            self.bslReset(1)                        #Invoke the boot loader.
+        
+        
+        if(self.z1):
+            ''' recover password from pic'''
+        
+        self.txPasswd(self.passwd)                  #transmit password
+
+        #Read actual bootstrap loader version.
+        #sys.stderr.write("Reading BSL version ...\n")
+        blkin = self.bslTxRx(self.BSL_RXBLK,        #Command: Read/Receive Block
+                          0x0ff0,                   #Start address
+                          16)                       #No. of bytes to read
+        dev_id, bslVerHi, bslVerLo = struct.unpack(">H8xBB4x", blkin[:-2]) #cut away checksum and extract data
+        self.dev_id=dev_id;
+        
+        
+        if self.cpu is None:                        #cpy type forced?
+            if deviceids.has_key(dev_id):
+                self.cpu = deviceids[dev_id]        #try to autodectect CPU type
+                
+                if DEBUG:
+                    sys.stderr.write("Autodetect successful: %04x -> %s\n" % (dev_id, self.cpu))
+            else:
+                sys.stderr.write("Autodetect failed! Unkown ID: %04x. Trying to continue anyway.\n" % dev_id)
+                self.cpu = F1x                      #assume something and try anyway..
+
+        sys.stderr.write("Current bootstrap loader version: %x.%x (Device ID: %04x)\n" % (bslVerHi, bslVerLo, dev_id))
+        sys.stderr.flush()
+        self.bslVer = (bslVerHi << 8) | bslVerLo
+
+        if self.bslVer <= 0x0110:                   #check if patch is needed
+            self.BSLMemAccessWarning = 1
+        else:
+            self.BSLMemAccessWarning = 0 #Fixed in newer versions of BSL.
+
+        if self.bslVer <= 0x0130 and adjsp:
+            #only do this on BSL where it's needed to prevent
+            #malfunction with F4xx devices/ newer ROM-BSLs
+            
+            #Execute function within bootstrap loader
+            #to prepare stack pointer for the following patch.
+            #This function will lock the protected functions again.
+            sys.stderr.write("Adjust SP. Load PC with 0x0C22 ...\n")
+            self.bslTxRx(self.BSL_LOADPC,           #Command: Load PC
+                                0x0C22)             #Address to load into PC
+            #Re-send password to re-gain access to protected functions.
+            self.txPasswd(self.passwd)
+
+        #get internal BSL replacement if needed or forced by the user
+        #required if speed is set but an old BSL is in the device
+        #if a BSL is given by the user, that one is used and not the internal one
+        if ((mayuseBSL and speed and self.bslVer < 0x0150) or forceBSL) and replacementBSL is None:
+            replacementBSL = Memory() #File to program
+            if self.cpu == F4x:
+                if DEBUG:
+                    sys.stderr.write("Using built in BSL replacement for F4x devices\n")
+                    sys.stderr.flush()
+                replacementBSL.loadTIText(cStringIO.StringIO(F4X_BSL))  #parse embedded BSL
+            else:
+                if DEBUG:
+                    sys.stderr.write("Using built in BSL replacement for F1x devices\n")
+                    sys.stderr.flush()
+                replacementBSL.loadTIText(cStringIO.StringIO(F1X_BSL))  #parse embedded BSL
+    
+        #now download the new BSL, if allowed and needed (version lower than the
+        #the replacement) or forced
+        if replacementBSL is not None:
+            self.actionDownloadBSL(replacementBSL)
+
+        #debug message with the real BSL version in use (may have changed after replacement BSL)
+        if DEBUG:
+            sys.stderr.write("Current bootstrap loader version: 0x%04x\n" % (self.bslVer,))
+            sys.stderr.flush()
+
+        #now apply workarounds or patches if BSL in use requires that
+        if self.bslVer <= 0x0110:                   #check if patch is needed
+            if usepatch:                            #test if patch is desired
+                sys.stderr.write("Patch for flash programming required!\n")
+                self.patchRequired = 1
+
+                sys.stderr.write("Load and verify patch ...\n")
+                sys.stderr.flush()
+                #Programming and verification is done in one pass.
+                #The patch file is only read and parsed once.
+                segments = Memory()                     #data to program
+                segments.loadTIText(cStringIO.StringIO(PATCH))  #parse embedded patch
+                #program patch
+                self.programData(segments, self.ACTION_PROGRAM | self.ACTION_VERIFY)
+                self.patchLoaded = 1
+            else:
+                if DEBUG:
+                    sys.stderr.write("Device needs patch, but not applied (usepatch is false).\n")    #message if not patched
+
+        #should the baudrate be changed?
+        if speed is not None:
+            self.actionChangeBaudrate(speed)            #change baudrate
+
+    def actionDownloadBSL(self, bslsegments):
+        sys.stderr.write("Load new BSL into RAM...\n")
+        sys.stderr.flush()
+        self.programData(bslsegments, self.ACTION_PROGRAM)
+        sys.stderr.write("Verify new BSL...\n")
+        sys.stderr.flush()
+        self.programData(bslsegments, self.ACTION_VERIFY) #File to verify
+
+        #Read startvector of bootstrap loader
+        #blkin = self.bslTxRx(self.BSL_RXBLK, 0x0300, 2)
+        #blkin = self.bslTxRx(self.BSL_RXBLK, 0x0220, 2)
+        blkin = self.bslTxRx(self.BSL_RXBLK, bslsegments[0].startaddress, 2)
+        startaddr = struct.unpack("<H", blkin[:2])[0]
+
+        sys.stderr.write("Starting new BSL at 0x%04x...\n" % startaddr)
+        sys.stderr.flush()
+        self.bslTxRx(self.BSL_LOADPC,  #Command: Load PC
+                     startaddr)        #Address to load into PC
+
+        #BSL-Bugs should be fixed within "new" BSL
+        self.BSLMemAccessWarning = 0
+        self.patchRequired = 0
+        self.patchLoaded   = 0
+
+        #Re-send password to re-gain access to protected functions.
+        self.txPasswd(self.passwd)
+
+        #update version info
+        #verison only valid for the internal ones, but it also makes sure 
+        #that the patches are not applied if the user d/ls one
+        self.bslVer = 0x0150
+
+    def actionEraseCheck(self):
+        """check the erasure of required flash cells."""
+        sys.stderr.write("Erase Check by file ...\n")
+        sys.stderr.flush()
+        if self.data is not None:
+            self.programData(self.data, self.ACTION_ERASE_CHECK)
+        else:
+            raise BSLException, "cannot do erase check against data with not knowing the actual data"
+
+    def actionProgram(self):
+        """program data into flash memory."""
+        if self.data is not None:
+            sys.stderr.write("Program ...\n")
+            sys.stderr.flush()
+            self.programData(self.data, self.ACTION_PROGRAM)
+            sys.stderr.write("%i bytes programmed.\n" % self.byteCtr)
+            sys.stderr.flush()
+        else:
+            raise BSLException, "programming without data not possible"
+    def actionFromweb(self):
+        """Grab GoodFET firmware from the web, then flash it."""
+        print "Grabbing %x firmware." % self.dev_id;
+        print "%s" % firmware[self.dev_id];
+        fn="/tmp/.goodfet.hex"
+        os.system("curl %s >%s" % (firmware[self.dev_id],fn))
+        
+        fw=Memory(fn);
+        #fw.loadIhex(open(fn,"rb"));
+        
+        sys.stderr.write("Program ...\n")
+        sys.stderr.flush()
+        self.programData(fw, self.ACTION_PROGRAM | self.ACTION_VERIFY)
+        sys.stderr.write("%i bytes programmed.\n" % self.byteCtr)
+        sys.stderr.flush()
+        
+    def actionVerify(self):
+        """Verify programmed data"""
+        if self.data is not None:
+            sys.stderr.write("Verify ...\n")
+            sys.stderr.flush()
+            self.programData(self.data, self.ACTION_VERIFY)
+        else:
+            raise BSLException, "verify without data not possible"
+
+    def actionReset(self):
+        """perform a reset, start user programm"""
+        sys.stderr.write("Reset device ...\n")
+        sys.stderr.flush()
+        self.bslReset(0) #only reset
+
+    def actionRun(self, address=0x220):
+        """start program at specified address"""
+        sys.stderr.write("Load PC with 0x%04x ...\n" % address)
+        sys.stderr.flush()
+        self.bslTxRx(self.BSL_LOADPC, #Command: Load PC
+                            address)  #Address to load into PC
+
+    #table with values from slaa089a.pdf
+    bauratetable = {
+        F1x: {
+             9600:[0x8580, 0x0000],
+            19200:[0x86e0, 0x0001],
+            38400:[0x87e0, 0x0002],
+        },
+        F2x: {
+             9600:[0x8580, 0x0000],
+            19200:[0x8B00, 0x0001],
+            38400:[0x8C80, 0x0002],
+        },
+        F4x: {
+             9600:[0x9800, 0x0000],
+            19200:[0xb000, 0x0001],
+            38400:[0xc800, 0x0002],
+        },
+    }
+    def actionChangeBaudrate(self, baudrate=9600):
+        """change baudrate. first the command is sent, then the comm
+        port is reprogrammed. only possible with newer MSP430-BSL versions.
+        (ROM >=1.6, downloadable >=1.5)"""
+        try:
+            baudconfigs = self.bauratetable[self.cpu]
+        except KeyError:
+            raise ValueError, "unknown CPU type %s, can't switch baudrate" % self.cpu
+        try:
+            a,l = baudconfigs[baudrate]
+        except KeyError:
+            raise ValueError, "baudrate not valid. valid values are %r" % baudconfigs.keys()
+        
+        sys.stderr.write("Changing baudrate to %d ...\n" % baudrate)
+        sys.stderr.flush()
+        self.bslTxRx(self.BSL_CHANGEBAUD,   #Command: change baudrate
+                    a, l)                   #args are coded in adr and len
+        self.serialport.flush()
+        time.sleep(0.010)                   #recomended delay
+        self.serialport.baudrate = baudrate
+
+    def actionReadBSLVersion(self):
+        """informational output of BSL version number.
+        (newer MSP430-BSLs only)"""
+        ans = self.bslTxRx(self.BSL_TXVERSION, 0) #Command: receive version info
+        #the following values are in big endian style!!!
+        family_type, bsl_version = struct.unpack(">H8xH4x", ans[:-2]) #cut away checksum and extract data
+        print "Device Type: 0x%04x\nBSL version: 0x%04x\n" % (family_type, bsl_version)
+
+    def actionWriteNewPassword(self):
+        passwd = self.getNewPassword()
+        #print passwd
+        self.picWritePassword(passwd)
+
+    def actionRecoverPassword(self):
+        p = self.picRecoverPassword()
+        #print p
+        self.passwd = p
+
+    def picRecoverPassword(self):
+        ''' recovers password from picrom'''
+        print 'recovering pic password',
+        p = ''
+        
+        for i in range(0,32):
+             c = self.readpicROM(i)
+             print c,
+             p = p + chr(c)
+             
+        print 'done'
+        return p
+        
+    def picWritePassword(self, password):
+        ''' writes a new password to picrom'''
+        print 'writing new password',
+        for i in range(0,32):
+            c = ord(password[i])
+            print c,
+            self.writepicROM(i, c)
+        print 'done'
+
+
+def usage():
+    """print some help message"""
+    sys.stderr.write("""
+USAGE: %s [options] [file]
+Version: %s
+
+If "-" is specified as file the data is read from the stdinput.
+A file ending with ".txt" is considered to be in TIText format,
+'.a43' and '.hex' as IntelHex and all other filenames are
+considered as ELF files.
+
+General options:
+  -h, --help            Show this help screen.
+  -c, --comport=port    Specify the communication port to be used.
+                        (Default is 0)
+                                0->COM1 / ttyS0
+                                1->COM2 / ttyS1
+                                etc.
+  -P, --password=file   Specify a file with the interrupt vectors that
+                        are used as password. This can be any file that
+                        has previously been used to program the device.
+                        (e.g. -P INT_VECT.TXT).
+  -f, --framesize=num   Max. number of data bytes within one transmitted
+                        frame (16 to 240 in steps of 16) (e.g. -f 240).
+  -m, --erasecycles=num Number of mass erase cycles (default is 1). Some
+                        old F149 devices need additional erase cycles.
+                        On newer devices it is no longer needed. (e.g. for
+                        an old F149: -m20)
+  -U, --unpatched       Do not download the BSL patch, even when it is
+                        needed. This is used when a program is downloaded
+                        into RAM and executed from there (and where flash
+                        programming is not needed.)
+  -D, --debug           Increase level of debug messages. This won't be
+                        very useful for the average user...
+  -I, --intelhex        Force fileformat to IntelHex
+  -T, --titext          Force fileformat to be TIText
+  -N, --notimeout       Don't use timeout on serial port (use with care)
+  -B, --bsl=bsl.txt     Load and use new BSL from the TI Text file
+  -S, --speed=baud      Reconfigure speed, only possible with newer
+                        MSP403-BSL versions (>1.5, read slaa089a.pdf for
+                        details). If the --bsl option is not used, an
+                        internal BSL replacement will be loaded.
+                        Needs a target with at least 2kB RAM!
+                        Possible values are 9600, 19200, 38400
+                        (default 9600)
+  -1, --f1x             Specify CPU family, in case autodetect fails
+  -2, --f2x             Specify CPU family, in case autodetect fails
+  -4, --f4x             Specify CPU family, in case autodetect fails
+                        --F1x and --f2x are only needed when the "change
+                        baudrate" feature is used and the autodetect feature
+                        fails. If the device ID that is uploaded is known, it
+                        has precedence to the command line option.
+  --invert-reset        Invert signal on RST pin (used for some BSL hardware)
+  --invert-test         Invert signal on TEST/TCK pin (used for some BSL
+                        hardware)
+  --swap-reset-test     Swap the RST and TEST pins (used for some BSL hardware)
+  --telos-latch         Special twiddle in BSL reset for Telos hardware
+  --telos-i2c           DTR/RTS map via an I2C switch to TCK/RST in Telos Rev.B
+  --telos               Implies options --invert-reset, --invert-test, 
+                        --swap-reset-test, and --telos-latch
+  --telosb              Implies options --swap-reset-test, --telos-i2c,
+                        --no-BSL-download, and --speed=38400
+  --goodfet10
+  --goodfet20
+  --goodfet30
+  --tmote               Identical operation to --telosb
+  --z1                  Bootstrap a Z1
+  --no-BSL-download     Do not download replacement BSL (disable automatic)
+  --force-BSL-download  Download replacement BSL even if not needed (the one
+                        in the device would have the required features)
+  --slow                Add delays when operating the conrol pins. Useful if
+                        the pins/circuit has high capacitance.
+
+Program Flow Specifiers:
+  -e, --masserase       Mass Erase (clear all flash memory)
+  -E, --erasecheck      Erase Check by file
+  -p, --program         Program file
+  -v, --verify          Verify by file
+
+The order of the above options matters! The table is ordered by normal
+execution order. For the options "Epv" a file must be specified.
+Program flow specifiers default to "pvr" if a file is given.
+Don't forget to specify "e" or "eE" when programming flash!
+
+Data retreiving:
+  -u, --upload=addr     Upload a datablock (see also: -s).
+  -s, --size=num        Size of the data block do upload. (Default is 2)
+  -x, --hex             Show a hexadecimal display of the uploaded data.
+                        (Default)
+  -b, --bin             Get binary uploaded data. This can be used
+                        to redirect the output into a file.
+
+Do before exit:
+  -g, --go=address      Start programm execution at specified address.
+                        This implies option --wait.
+  -r, --reset           Reset connected MSP430. Starts application.
+                        This is a normal device reset and will start
+                        the programm that is specified in the reset
+                        vector. (see also -g)
+  -w, --wait            Wait for <ENTER> before closing serial port.
+
+If it says "NAK received" it's probably because you specified no or a
+wrong password.
+""" % (sys.argv[0], VERSION))
+
+#add some arguments to a function, but don't call it yet, instead return
+#a wrapper object for later invocation
+class curry:
+    """create a callable with some arguments specified in advance"""
+    def __init__(self, fun, *args, **kwargs):
+        self.fun = fun
+        self.pending = args[:]
+        self.kwargs = kwargs.copy()
+
+    def __call__(self, *args, **kwargs):
+        if kwargs and self.kwargs:
+            kw = self.kwargs.copy()
+            kw.update(kwargs)
+        else:
+            kw = kwargs or self.kwargs
+        return apply(self.fun, self.pending + args, kw)
+
+    def __repr__(self):
+        #first try if it a function
+        try:
+            return "curry(%s, %r, %r)" % (self.fun.func_name, self.pending, self.kwargs)
+        except AttributeError:
+            #fallback for callable classes
+            return "curry(%s, %r, %r)" % (self.fun, self.pending, self.kwargs)
+
+def hexify(line, bytes, width=16):
+    return  '%04x  %s%s %s' % (
+        line,
+        ('%02x '*len(bytes)) % tuple(bytes),
+        '   '* (width-len(bytes)),
+        ('%c'*len(bytes)) % tuple(map(lambda x: (x>=32 and x<127) and x or ord('.'), bytes))
+        )
+
+#Main:
+def main(itest=1):
+    global DEBUG
+    import getopt
+    filetype    = None
+    filename    = None
+    comPort     = None     #Default setting.
+    speed       = None
+    unpatched   = 0
+    reset       = 0
+    wait        = 0     #wait at the end
+    goaddr      = None
+    bsl         = BootStrapLoader()
+    toinit      = []
+    todo        = []
+    startaddr   = None
+    size        = 2
+    hexoutput   = 1
+    notimeout   = 0
+    bslrepl     = None
+    mayuseBSL   = 1
+    forceBSL    = 0
+    dumpivt     = 0
+    dumpinfo    = 0
+    
+    bsl.invertRST = 1
+    bsl.invertTEST = itest
+    
+    if comPort is None and os.environ.get("GOODFET")!=None:
+        glob_list = glob.glob(os.environ.get("GOODFET"));
+        if len(glob_list) > 0:
+            comPort = glob_list[0];
+    if comPort is None:
+        glob_list = glob.glob("/dev/tty.usbserial*");
+        if len(glob_list) > 0:
+            comPort = glob_list[0];
+    if comPort is None:
+        glob_list = glob.glob("/dev/ttyUSB*");
+        if len(glob_list) > 0:
+            comPort = glob_list[0];
+    
+    
+    sys.stderr.write("MSP430 Bootstrap Loader Version: %s\n" % VERSION)
+
+    try:
+        opts, args = getopt.getopt(sys.argv[1:],
+            "hc:P:wf:m:neEpvrg:UDudsxbITNB:S:V14",
+            ["help", "comport=", "password=", "wait", "framesize=",
+             "erasecycles=", "masserase", "erasecheck", "program",
+             "verify", "reset", "go=", "unpatched", "debug",
+             "upload=", "download=", "size=", "hex", "bin",
+             "intelhex", "titext", "notimeout", "bsl=", "speed=",
+             "bslversion", "f1x", "f2x", "f4x", "invert-reset", "invert-test",
+	     "swap-reset-test", "telos-latch", "telos-i2c", "telos", "telosb",
+             "tmote","no-BSL-download", "force-BSL-download", "slow",
+             "dumpivt", "dumpinfo", "fromweb",
+	"goodfet30", "goodfet20", "goodfet10", "z1", "mainerase"
+	]
+        )
+    except getopt.GetoptError:
+        # print help information and exit:
+        usage()
+        sys.exit(2)
+
+    for o, a in opts:
+        if o in ("-h", "--help"):
+            usage()
+            sys.exit()
+        elif o in ("-c", "--comport"):
+            try:
+                comPort = int(a)                    #try to convert decimal
+            except ValueError:
+                comPort = a                         #take the string and let serial driver decide
+        elif o in ("-P", "--password"):
+            #extract password from file
+            bsl.passwd = Memory(a).getMemrange(0xffe0, 0xffff)
+        elif o in ("-w", "--wait"):
+            wait = 1
+        elif o in ("--dumpivt"):
+            dumpivt=1;
+        elif o in ("--dumpinfo"):
+            dumpinfo=1;
+        elif o in ("-f", "--framesize"):
+            try:
+                maxData = int(a)                    #try to convert decimal
+            except ValueError:
+                sys.stderr.write("framesize must be a valid number\n")
+                sys.exit(2)
+            #Make sure that conditions for maxData are met:
+            #( >= 16 and == n*16 and <= MAX_DATA_BYTES!)
+            if maxData > BootStrapLoader.MAX_DATA_BYTES:
+                maxData = BootStrapLoader.MAX_DATA_BYTES
+            elif maxData < 16:
+                maxData = 16
+            bsl.maxData = maxData - (maxData % 16)
+            sys.stderr.write( "Max. number of data bytes within one frame set to %i.\n" % maxData)
+        elif o in ("-m", "--erasecycles"):
+            try:
+                meraseCycles = int(a)               #try to convert decimal
+            except ValueError:
+                sys.stderr.write("erasecycles must be a valid number\n")
+                sys.exit(2)
+            #sanity check of value
+            if meraseCycles < 1:
+                sys.stderr.write("erasecycles must be a positive number\n")
+                sys.exit(2)
+            if meraseCycles > 20:
+                sys.stderr.write("warning: erasecycles set to a large number (>20): %d\n" % meraseCycles)
+            sys.stderr.write( "Number of mass erase cycles set to %i.\n" % meraseCycles)
+            bsl.meraseCycles = meraseCycles
+        elif o in ("-e", "--masserase"):
+            #toinit.append(bsl.actionMassErase)        #Erase Flash
+            todo.append(bsl.actionMainErase)        #Erase Flash
+            #todo.append(bsl.actionSecureInfoSegment)
+        elif o in ("-n", "--mainerase"):
+            #todo.append(bsl.actionMainErase)        #Erase Flash
+            toinit.append(bsl.actionMassErase)        #Erase Flash
+        elif o in ("-E", "--erasecheck"):
+            toinit.append(bsl.actionEraseCheck)       #Erase Check (by file)
+        elif o in ("-p", "--program"):
+            #pass
+            todo.append(bsl.actionProgram)          #Program file
+            if bsl.z1:
+                #todo.append(bsl.actionUnlockInfo)
+                #todo.append(bsl.writeCalibTables)
+                #todo.append(bsl.writeCalibTables2)
+                
+                todo.append(bsl.actionWriteNewPassword)
+                
+                pass
+        elif o in ("--fromweb"):
+            toinit.append(bsl.actionMassErase)        #Erase Flash
+            todo.append(bsl.actionFromweb)          #Program GoodFET code
+        elif o in ("-v", "--verify"):
+            todo.append(bsl.actionVerify)           #Verify file
+        elif o in ("-r", "--reset"):
+            reset = 1
+        elif o in ("-g", "--go"):
+            try:
+                goaddr = int(a)                    #try to convert decimal
+            except ValueError:
+                try:
+                    goaddr = int(a[2:],16)         #try to convert hex
+                except ValueError:
+                    sys.stderr.write("go address must be a valid number\n")
+                    sys.exit(2)
+            wait = 1
+        elif o in ("-U", "--unpatched"):
+            unpatched = 1
+        elif o in ("-D", "--debug"):
+            DEBUG = DEBUG + 1
+        elif o in ("-u", "--upload"):
+            try:
+                startaddr = int(a)                  #try to convert decimal
+            except ValueError:
+                try:
+                    startaddr = int(a,16)           #try to convert hex
+                except ValueError:
+                    sys.stderr.write("upload address must be a valid number\n")
+                    sys.exit(2)
+        elif o in ("-s", "--size"):
+            try:
+                size = int(a)
+            except ValueError:
+                try:
+                    size = int(a,16)
+                except ValueError:
+                    sys.stderr.write("size must be a valid number\n")
+                    sys.exit(2)
+        elif o in ("-x", "--hex"):
+            hexoutput = 1
+        elif o in ("-b", "--bin"):
+            hexoutput = 0
+        elif o in ("-I", "--intelhex"):
+            filetype = 0
+        elif o in ("-T", "--titext"):
+            filetype = 1
+        elif o in ("-N", "--notimeout"):
+            notimeout = 1
+        elif o in ("-B", "--bsl"):
+            bslrepl = Memory() #File to program
+            bslrepl.loadFile(a)
+        elif o in ("-V", "--bslversion"):
+            todo.append(bsl.actionReadBSLVersion) #load replacement BSL as first item
+        elif o in ("-S", "--speed"):
+            try:
+                speed = int(a)                    #try to convert decimal
+            except ValueError:
+                sys.stderr.write("speed must be decimal number\n")
+                sys.exit(2)
+        elif o in ("-1", "--f1x"):
+            bsl.cpu = F1x
+        elif o in ("-2", "--f2x"):
+            bsl.cpu = F2x
+        elif o in ("-4", "--f4x"):
+            bsl.cpu = F4x
+        elif o in ("--invert-reset", ):
+            bsl.invertRST = 1
+        elif o in ("--invert-test", ):
+            bsl.invertTEST = 1
+        elif o in ("--swap-reset-test", ):
+            bsl.swapRSTTEST = 1
+        elif o in ("--telos-latch", ):
+            bsl.telosLatch = 1
+        elif o in ("--telos-i2c", ):
+            bsl.telosI2C = 1
+        elif o in ("--telos", ):
+            bsl.invertRST = 1
+            bsl.invertTEST = 1
+            bsl.swapRSTTEST = 1
+            bsl.telosLatch = 1
+    	elif o in ("--goodfet10", ):
+    	    bsl.invertRST = 1
+    	    bsl.invertTEST = 1
+    	elif o in ("--goodfet20", ):
+    	    bsl.invertRST = 1
+    	    bsl.invertTEST = 1
+    	elif o in ("--goodfet30", ):
+    	    bsl.invertRST = 1
+    	    bsl.invertTEST = 0
+        elif o in ("--telosb", ):
+            bsl.swapRSTTEST = 1
+            bsl.telosI2C = 1
+            mayuseBSL = 0
+            speed = 38400
+        elif o in ("--tmote", ):
+            bsl.swapRSTTEST = 1
+            bsl.telosI2C = 1
+            mayuseBSL = 0
+            speed = 38400
+        elif o in ("--z1", ):
+            bsl.z1 = 1
+            speed = 38400
+            toinit.append(bsl.actionRecoverPassword)
+        elif o in ("--no-BSL-download", ):
+            mayuseBSL = 0
+        elif o in ("--force-BSL-download", ):
+            forceBSL = 1
+        elif o in ("--slow", ):
+            bsl.slowmode = 1
+
+    if len(args) == 0:
+        sys.stderr.write("Use -h for help\n");
+        sys.stderr.write("Use --fromweb to upgrade a GoodFET.\n")
+    elif len(args) == 1:                            #a filename is given
+        if not todo:                                #if there are no actions yet
+            todo.extend([                           #add some useful actions...
+                bsl.actionProgram,
+                bsl.actionVerify,
+            ])
+        filename = args[0]
+    else:                                           #number of args is wrong
+        usage()
+        sys.exit(2)
+
+    if DEBUG:   #debug infos
+        sys.stderr.write("Debug level set to %d\n" % DEBUG)
+        sys.stderr.write("Python version: %s\n" % sys.version)
+
+    #sanity check of options
+    if notimeout and goaddr is not None and startaddr is not None:
+        sys.stderr.write("Option --notimeout can not be used together with both --upload and --go\n")
+        sys.exit(1)
+
+    if notimeout:
+        sys.stderr.write("Warning: option --notimeout can cause improper function in some cases!\n")
+        bsl.timeout = 0
+
+    if goaddr and reset:
+        sys.stderr.write("Warning: option --reset ignored as --go is specified!\n")
+        reset = 0
+
+    if startaddr and reset:
+        sys.stderr.write("Warning: option --reset ignored as --upload is specified!\n")
+        reset = 0
+
+    sys.stderr.flush()
+    
+    #prepare data to download
+    bsl.data = Memory()                             #prepare downloaded data
+    if filetype is not None:                        #if the filetype is given...
+        if filename is None:
+            raise ValueError("no filename but filetype specified")
+        if filename == '-':                         #get data from stdin
+            file = sys.stdin
+        else:
+            file = open(filename, "rb")             #or from a file
+        if filetype == 0:                           #select load function
+            bsl.data.loadIHex(file)                 #intel hex
+        elif filetype == 1:
+            bsl.data.loadTIText(file)               #TI's format
+        else:
+            raise ValueError("illegal filetype specified")
+    else:                                           #no filetype given...
+        if filename == '-':                         #for stdin:
+            bsl.data.loadIHex(sys.stdin)            #assume intel hex
+        elif filename:
+            bsl.data.loadFile(filename)             #autodetect otherwise
+
+    if DEBUG > 3: sys.stderr.write("File: %r" % filename)
+
+    bsl.comInit(comPort)                            #init port
+
+    #initialization list
+    if toinit:  #erase and erase check
+        if DEBUG: sys.stderr.write("Preparing device ...\n")
+        #bsl.actionStartBSL(usepatch=0, adjsp=0)     #no workarounds needed
+        #if speed: bsl.actionChangeBaudrate(speed)   #change baud rate as fast as possible
+        for f in toinit: f()
+
+    if todo or goaddr or startaddr:
+        if DEBUG: sys.stderr.write("Actions ...\n")
+        #connect to the BSL
+        bsl.actionStartBSL(
+            usepatch=not unpatched,
+            replacementBSL=bslrepl,
+            forceBSL=forceBSL,
+            mayuseBSL=mayuseBSL,
+            speed=speed,
+        )
+
+    #work list
+    if todo:
+        if DEBUG > 0:       #debug
+            #show a nice list of sheduled actions
+            sys.stderr.write("TODO list:\n")
+            for f in todo:
+                try:
+                    sys.stderr.write("   %s\n" % f.func_name)
+                except AttributeError:
+                    sys.stderr.write("   %r\n" % f)
+        for f in todo: f()                          #work through todo list
+
+    if reset:                                       #reset device first if desired
+        bsl.actionReset()
+    if dumpivt:
+        bsl.txPasswd(); #default pass
+        data=bsl.uploadData(0xc00,1024);
+        hex="";
+        for c in data:
+            hex+=("%02x "%ord(c));
+        print hex;
+    if dumpinfo:
+        bsl.txPasswd(); #default pass
+        data=bsl.uploadData(0x1000,256);
+        hex="@1000\n";
+        for c in data:
+            hex+=("%02x "%ord(c));
+        hex+="\nq\n";
+        print hex;
+    
+    if goaddr is not None:                          #start user programm at specified address
+        bsl.actionRun(goaddr)                       #load PC and execute
+
+    #upload datablock and output
+    if startaddr is not None:
+        if goaddr:                                  #if a program was started...
+            #don't restart BSL but wait for the device to enter it itself
+            sys.stderr.write("Waiting for device to reconnect for upload: ")
+            sys.stderr.flush()
+            bsl.txPasswd(bsl.passwd, wait=1)        #synchronize, try forever...
+            data = bsl.uploadData(startaddr, size)  #upload data
+        else:
+            data = bsl.uploadData(startaddr, size)  #upload data
+        if hexoutput:                               #depending on output format
+            m = 0
+            while m < len(data):                    #print a hex display
+                print hexify(startaddr+m, map(ord,data[m:m+16]))
+                m = m + 16
+        else:
+            sys.stdout.write(data)                  #binary output w/o newline!
+        wait = 0    #wait makes no sense as after the upload the device is still in BSL
+
+    if wait:                                        #wait at the end if desired
+        sys.stderr.write("Press <ENTER> ...\n")     #display a prompt
+        sys.stderr.flush()
+        raw_input()                                 #wait for newline
+
+    bsl.comDone()           #Release serial communication port
+
+if __name__ == '__main__':
+    try:
+        main(1)
+    except SystemExit:
+        raise               #let pass exit() calls
+    except KeyboardInterrupt:
+        if DEBUG: raise     #show full trace in debug mode
+        sys.stderr.write("user abort.\n")   #short messy in user mode
+        sys.exit(1)         #set errorlevel for script usage
+    except Exception, msg:  #every Exception is caught and displayed
+        if DEBUG: raise     #show full trace in debug mode
+        #sys.stderr.write("\nAn error occoured:\n%s\n" % msg) #short messy in user mode
+        #sys.exit(1)         #set errorlevel for script usage
+        main(0);
diff --git a/tools/zolertia/z1-bsl-nopic b/tools/zolertia/z1-bsl-nopic
new file mode 100755
index 0000000000000000000000000000000000000000..8b5edd8f5947497b210e26e7b086e12a231af027
--- /dev/null
+++ b/tools/zolertia/z1-bsl-nopic
@@ -0,0 +1,1941 @@
+#!/usr/bin/env python2
+# Serial Bootstrap Loader software for the MSP430 embedded proccessor.
+#
+# (C) 2001-2003 Chris Liechti <cliechti@gmx.net>
+# this is distributed under a free software license, see license-bsl.txt
+#
+# fixes from Colin Domoney
+#
+# based on the application note slas96b.pdf from Texas Instruments, Inc.,
+# Volker Rzehak
+# additional infos from slaa089a.pdf
+# 
+# Forked by Travis Goodspeed <travis at tnbelt.com> for use with the GoodFET
+# JTAG programmer.
+
+import sys, time, string, cStringIO, struct
+sys.path.append("/usr/lib/tinyos")
+import serial, os, glob
+
+#forked from TinyOS Telos version.
+VERSION = string.split("Revision: 1.39-goodfet-8 z1 fork")[1] 
+
+DEBUG = 0                                       #disable debug messages by default
+
+#copy of the patch file provided by TI
+#this part is (C) by Texas Instruments
+PATCH = """@0220
+31 40 1A 02 09 43 B0 12 2A 0E B0 12 BA 0D 55 42
+0B 02 75 90 12 00 1F 24 B0 12 BA 02 55 42 0B 02
+75 90 16 00 16 24 75 90 14 00 11 24 B0 12 84 0E
+06 3C B0 12 94 0E 03 3C 21 53 B0 12 8C 0E B2 40
+10 A5 2C 01 B2 40 00 A5 28 01 30 40 42 0C 30 40
+76 0D 30 40 AC 0C 16 42 0E 02 17 42 10 02 E2 B2
+08 02 14 24 B0 12 10 0F 36 90 00 10 06 28 B2 40
+00 A5 2C 01 B2 40 40 A5 28 01 D6 42 06 02 00 00
+16 53 17 83 EF 23 B0 12 BA 02 D3 3F B0 12 10 0F
+17 83 FC 23 B0 12 BA 02 D0 3F 18 42 12 02 B0 12
+10 0F D2 42 06 02 12 02 B0 12 10 0F D2 42 06 02
+13 02 38 E3 18 92 12 02 BF 23 E2 B3 08 02 BC 23
+30 41
+q
+"""
+
+#These BSL's are (C) by TI. They come with the application note slaa089a
+F1X_BSL = """@0220
+24 02 2E 02 31 40 20 02 2B D2 C0 43 EA FF 32 C2
+F2 C0 32 00 00 00 B2 40 80 5A 20 01 F2 40 85 00
+57 00 F2 40 80 00 56 00 E2 D3 21 00 E2 D3 22 00
+E2 C3 26 00 E2 C2 2A 00 E2 C2 2E 00 B2 40 10 A5
+2C 01 B2 40 00 A5 28 01 3B C0 3A 00 B0 12 D6 04
+82 43 12 02 09 43 36 40 0A 02 37 42 B0 12 AC 05
+C6 4C 00 00 16 53 17 83 F9 23 D2 92 0C 02 0D 02
+28 20 55 42 0B 02 75 90 12 00 80 24 75 90 10 00
+6D 24 B0 12 9C 04 55 42 0B 02 75 90 18 00 31 24
+75 90 1E 00 B8 24 75 90 20 00 17 24 2B B2 11 24
+75 90 16 00 22 24 75 90 14 00 B3 24 75 90 1A 00
+18 24 75 90 1C 00 45 24 04 3C B0 12 36 05 BE 3F
+21 53 B0 12 3C 05 BA 3F 03 43 B0 12 36 05 D2 42
+0E 02 56 00 D2 42 0F 02 57 00 D2 42 10 02 16 02
+AD 3F B0 12 36 05 10 42 0E 02 16 42 0E 02 15 43
+07 3C 36 40 FE FF B2 40 06 A5 10 02 35 40 0C 00
+B2 40 00 A5 2C 01 92 42 10 02 28 01 B6 43 00 00
+92 B3 2C 01 FD 23 15 83 F3 23 36 90 FE FF CD 27
+37 40 80 00 36 F0 80 FF 36 90 00 11 0E 28 07 57
+36 F0 00 FF 36 90 00 12 08 28 07 57 36 F0 00 FE
+04 3C 16 42 0E 02 17 42 10 02 35 43 75 96 03 20
+17 83 FC 23 B2 3F 82 46 00 02 B3 3F 36 40 E0 FF
+37 40 20 00 B0 12 AC 05 7C 96 01 24 2B D3 17 83
+F9 23 2B C2 B0 12 9C 04 2B D2 9F 3F 16 42 0E 02
+17 42 10 02 2B B2 38 24 3B D0 10 00 B0 12 AC 05
+36 90 00 10 06 2C 36 90 00 01 09 2C C6 4C 00 00
+25 3C B2 40 00 A5 2C 01 B2 40 40 A5 28 01 16 B3
+03 20 C2 4C 14 02 1A 3C C2 4C 15 02 86 9A FD FF
+08 24 2B D3 3B B0 20 00 04 20 3B D0 20 00 82 46
+00 02 36 90 01 02 04 28 3B D2 3B B0 10 00 02 24
+3B C0 32 00 1A 42 14 02 86 4A FF FF 16 53 17 83
+CD 23 B0 12 9C 04 61 3F B0 12 AC 05 17 83 FC 23
+B0 12 9C 04 5E 3F B2 40 F0 0F 0E 02 B2 40 10 00
+10 02 B2 40 80 00 0A 02 D2 42 10 02 0C 02 D2 42
+10 02 0D 02 82 43 12 02 09 43 36 40 0A 02 27 42
+7C 46 B0 12 40 05 17 83 FB 23 16 42 0E 02 17 42
+10 02 36 90 00 01 0A 28 B2 46 14 02 5C 42 14 02
+B0 12 40 05 17 83 5C 42 15 02 01 3C 7C 46 B0 12
+40 05 17 83 EE 23 B2 E3 12 02 5C 42 12 02 B0 12
+40 05 5C 42 13 02 B0 12 40 05 E0 3E 18 42 12 02
+B0 12 AC 05 C2 4C 12 02 B0 12 AC 05 C2 4C 13 02
+38 E3 3B B2 0A 24 86 9A FE FF 07 24 3B B0 20 00
+04 20 16 53 82 46 00 02 2B D3 18 92 12 02 08 23
+2B B3 06 23 30 41 E2 B2 28 00 FD 27 E2 B2 28 00
+FD 23 B2 40 24 02 60 01 E2 B2 28 00 FD 27 15 42
+70 01 05 11 05 11 05 11 82 45 02 02 05 11 82 45
+04 02 B2 80 1E 00 04 02 57 42 16 02 37 80 03 00
+05 11 05 11 17 53 FD 23 35 50 40 A5 82 45 2A 01
+35 42 B2 40 24 02 60 01 92 92 70 01 02 02 FC 2F
+15 83 F7 23 09 43 7C 40 90 00 02 3C 7C 40 A0 00
+C2 43 07 02 C9 EC 12 02 19 E3 1B C3 55 42 07 02
+55 45 56 05 00 55 0C 2E 2E 2E 2E 2E 2E 2E 2E 1A
+34 34 92 42 70 01 72 01 B2 50 0C 00 72 01 07 3C
+1B B3 0B 20 82 43 62 01 92 B3 62 01 FD 27 E2 C3
+21 00 0A 3C 4C 11 F6 2B 1B E3 82 43 62 01 92 B3
+62 01 FD 27 E2 D3 21 00 92 52 02 02 72 01 D2 53
+07 02 F0 90 0C 00 61 FC D1 23 30 41 C2 43 09 02
+1B C3 55 42 09 02 55 45 BC 05 00 55 0C 56 56 56
+56 56 56 56 56 36 76 00 E2 B2 28 00 FD 23 92 42
+70 01 72 01 92 52 04 02 72 01 82 43 62 01 92 B3
+62 01 FD 27 E2 B2 28 00 1E 28 2B D3 1C 3C 4C 10
+1A 3C 82 43 62 01 92 B3 62 01 FD 27 E2 B2 28 00
+01 28 1B E3 1B B3 01 24 2B D3 C9 EC 12 02 19 E3
+0A 3C 82 43 62 01 92 B3 62 01 FD 27 E2 B2 28 00
+E6 2B 4C 10 1B E3 92 52 02 02 72 01 D2 53 09 02
+C0 3F 82 43 62 01 92 B3 62 01 FD 27 E2 B2 28 00
+01 2C 2B D3 30 41
+q
+"""
+
+F4X_BSL = """@0220
+24 02 2E 02 31 40 20 02 2B D2 C0 43 EA FF 32 C2
+F2 C0 32 00 00 00 B2 40 80 5A 20 01 32 D0 40 00
+C2 43 50 00 F2 40 98 00 51 00 F2 C0 80 00 52 00
+D2 D3 21 00 D2 D3 22 00 D2 C3 26 00 E2 C3 22 00
+E2 C3 26 00 B2 40 10 A5 2C 01 B2 40 00 A5 28 01
+3B C0 3A 00 B0 12 DE 04 82 43 12 02 09 43 36 40
+0A 02 37 42 B0 12 B4 05 C6 4C 00 00 16 53 17 83
+F9 23 D2 92 0C 02 0D 02 28 20 55 42 0B 02 75 90
+12 00 80 24 75 90 10 00 6D 24 B0 12 A4 04 55 42
+0B 02 75 90 18 00 31 24 75 90 1E 00 B8 24 75 90
+20 00 17 24 2B B2 11 24 75 90 16 00 22 24 75 90
+14 00 B3 24 75 90 1A 00 18 24 75 90 1C 00 45 24
+04 3C B0 12 3E 05 BE 3F 21 53 B0 12 44 05 BA 3F
+03 43 B0 12 3E 05 D2 42 0E 02 50 00 D2 42 0F 02
+51 00 D2 42 10 02 16 02 AD 3F B0 12 3E 05 10 42
+0E 02 16 42 0E 02 15 43 07 3C 36 40 FE FF B2 40
+06 A5 10 02 35 40 0C 00 B2 40 00 A5 2C 01 92 42
+10 02 28 01 B6 43 00 00 92 B3 2C 01 FD 23 15 83
+F3 23 36 90 FE FF CD 27 37 40 80 00 36 F0 80 FF
+36 90 00 11 0E 28 07 57 36 F0 00 FF 36 90 00 12
+08 28 07 57 36 F0 00 FE 04 3C 16 42 0E 02 17 42
+10 02 35 43 75 96 03 20 17 83 FC 23 B2 3F 82 46
+00 02 B3 3F 36 40 E0 FF 37 40 20 00 B0 12 B4 05
+7C 96 01 24 2B D3 17 83 F9 23 2B C2 B0 12 A4 04
+2B D2 9F 3F 16 42 0E 02 17 42 10 02 2B B2 38 24
+3B D0 10 00 B0 12 B4 05 36 90 00 10 06 2C 36 90
+00 01 09 2C C6 4C 00 00 25 3C B2 40 00 A5 2C 01
+B2 40 40 A5 28 01 16 B3 03 20 C2 4C 14 02 1A 3C
+C2 4C 15 02 86 9A FD FF 08 24 2B D3 3B B0 20 00
+04 20 3B D0 20 00 82 46 00 02 36 90 01 02 04 28
+3B D2 3B B0 10 00 02 24 3B C0 32 00 1A 42 14 02
+86 4A FF FF 16 53 17 83 CD 23 B0 12 A4 04 61 3F
+B0 12 B4 05 17 83 FC 23 B0 12 A4 04 5E 3F B2 40
+F0 0F 0E 02 B2 40 10 00 10 02 B2 40 80 00 0A 02
+D2 42 10 02 0C 02 D2 42 10 02 0D 02 82 43 12 02
+09 43 36 40 0A 02 27 42 7C 46 B0 12 48 05 17 83
+FB 23 16 42 0E 02 17 42 10 02 36 90 00 01 0A 28
+B2 46 14 02 5C 42 14 02 B0 12 48 05 17 83 5C 42
+15 02 01 3C 7C 46 B0 12 48 05 17 83 EE 23 B2 E3
+12 02 5C 42 12 02 B0 12 48 05 5C 42 13 02 B0 12
+48 05 E0 3E 18 42 12 02 B0 12 B4 05 C2 4C 12 02
+B0 12 B4 05 C2 4C 13 02 38 E3 3B B2 0A 24 86 9A
+FE FF 07 24 3B B0 20 00 04 20 16 53 82 46 00 02
+2B D3 18 92 12 02 08 23 2B B3 06 23 30 41 E2 B3
+20 00 FD 27 E2 B3 20 00 FD 23 B2 40 24 02 60 01
+E2 B3 20 00 FD 27 15 42 70 01 05 11 05 11 05 11
+82 45 02 02 05 11 82 45 04 02 B2 80 1E 00 04 02
+57 42 16 02 37 80 03 00 05 11 05 11 17 53 FD 23
+35 50 40 A5 82 45 2A 01 35 42 B2 40 24 02 60 01
+92 92 70 01 02 02 FC 2F 15 83 F7 23 09 43 7C 40
+90 00 02 3C 7C 40 A0 00 C2 43 07 02 C9 EC 12 02
+19 E3 1B C3 55 42 07 02 55 45 5E 05 00 55 0C 2E
+2E 2E 2E 2E 2E 2E 2E 1A 34 34 92 42 70 01 72 01
+B2 50 0C 00 72 01 07 3C 1B B3 0B 20 82 43 62 01
+92 B3 62 01 FD 27 D2 C3 21 00 0A 3C 4C 11 F6 2B
+1B E3 82 43 62 01 92 B3 62 01 FD 27 D2 D3 21 00
+92 52 02 02 72 01 D2 53 07 02 F0 90 0C 00 59 FC
+D1 23 30 41 C2 43 09 02 1B C3 55 42 09 02 55 45
+C4 05 00 55 0C 56 56 56 56 56 56 56 56 36 76 00
+E2 B3 20 00 FD 23 92 42 70 01 72 01 92 52 04 02
+72 01 82 43 62 01 92 B3 62 01 FD 27 E2 B3 20 00
+1E 28 2B D3 1C 3C 4C 10 1A 3C 82 43 62 01 92 B3
+62 01 FD 27 E2 B3 20 00 01 28 1B E3 1B B3 01 24
+2B D3 C9 EC 12 02 19 E3 0A 3C 82 43 62 01 92 B3
+62 01 FD 27 E2 B3 20 00 E6 2B 4C 10 1B E3 92 52
+02 02 72 01 D2 53 09 02 C0 3F 82 43 62 01 92 B3
+62 01 FD 27 E2 B3 20 00 01 2C 2B D3 30 41
+q
+"""
+
+CALIB_TABLES = """
+84 C0 16 FE FF FF FF FF FF FF FF FF FF FF FF FF
+FF FF FF FF FF FF FF FF FF FF 10 08 80 00 00 01
+7E 27 0B 79 0D AA 7E 4D 06 DF 08 33 08 FE FF FF
+FF FF FF FF FF FF 08 01 8F 95 8E 9A 8D 88 86 D1
+"""
+
+#cpu types for "change baudrate"
+#use strings as ID so that they can be used in outputs too
+F1x                     = "F1x family"
+F2x                     = "F2x family"
+F4x                     = "F4x family"
+
+#known device list
+deviceids = {
+    0xf149: F1x,
+    0xf16c: F1x, #for GoodFET10 to '20
+    0xf112: F1x,
+    0xf413: F4x,
+    0xf123: F1x,
+    0xf449: F4x,
+    0x1232: F1x,
+    0xf26f: F2x, #for GoodFET20
+    0xf227: F2x, #for GoodFET30
+}
+
+#GoodFET firmware
+firmware = {
+    0xf16c: "http://goodfet.sourceforge.net/dist/msp430x1612.hex",
+    0xf26f: "http://goodfet.sourceforge.net/dist/msp430x2618.hex",
+    0xf227: "http://goodfet.sourceforge.net/dist/msp430x2274.hex"
+}
+
+class BSLException(Exception):
+    pass
+
+class LowLevel:
+    "lowlevel communication"
+    #Constants
+    MODE_SSP                = 0
+    MODE_BSL                = 1
+
+    BSL_SYNC                = 0x80
+    BSL_TXPWORD             = 0x10
+    BSL_TXBLK               = 0x12 #Transmit block to boot loader
+    BSL_UNLOCK_INFO         = 0x12 #unlocks / locks info segment A Not working on msp430f2617
+    BSL_RXBLK               = 0x14 #Receive  block from boot loader
+    BSL_ERASE               = 0x16 #Erase one segment
+    BSL_MERAS               = 0x18 #Erase complete FLASH memory
+    BSL_CHANGEBAUD          = 0x20 #Change baudrate
+    BSL_SETMEMOFFSET        = 0x21 #Set memory offset
+    BSL_LOADPC              = 0x1A #Load PC and start execution
+    BSL_TXVERSION           = 0x1E #Get BSL version
+
+    #Upper limit of address range that might be modified by
+    #"BSL checksum bug".
+    BSL_CRITICAL_ADDR       = 0x0A00
+
+    #Header Definitions
+    CMD_FAILED              = 0x70
+    DATA_FRAME              = 0x80
+    DATA_ACK                = 0x90
+    DATA_NAK                = 0xA0
+
+    QUERY_POLL              = 0xB0
+    QUERY_RESPONSE          = 0x50
+
+    OPEN_CONNECTION         = 0xC0
+    ACK_CONNECTION          = 0x40
+
+    DEFAULT_TIMEOUT         =   1
+    DEFAULT_PROLONG         =  10
+    MAX_FRAME_SIZE          = 256
+    MAX_DATA_BYTES          = 250
+    MAX_DATA_WORDS          = 125
+
+    MAX_FRAME_COUNT         = 16
+
+    #Error messages
+    ERR_COM                 = "Unspecific error"
+    ERR_RX_NAK              = "NAK received (wrong password?)"
+    #ERR_CMD_NOT_COMPLETED   = "Command did not send ACK: indicates that it didn't complete correctly"
+    ERR_CMD_FAILED          = "Command failed, is not defined or is not allowed"
+    ERR_BSL_SYNC            = "Bootstrap loader synchronization error"
+    ERR_FRAME_NUMBER        = "Frame sequence number error."
+
+    def calcChecksum(self, data, length):
+        """Calculates a checksum of "data"."""
+        checksum = 0
+
+        for i in range(length/2):
+            checksum = checksum ^ (ord(data[i*2]) | (ord(data[i*2+1]) << 8))    #xor-ing
+        return 0xffff & (checksum ^ 0xffff)         #inverting
+
+    def __init__(self, aTimeout = None, aProlongFactor = None):
+        """init bsl object, don't connect yet"""
+        if aTimeout is None:
+            self.timeout = self.DEFAULT_TIMEOUT
+        else:
+            self.timeout = aTimeout
+        if aProlongFactor is None:
+            self.prolongFactor = self.DEFAULT_PROLONG
+        else:
+            self.prolongFactor = aProlongFactor
+
+        #flags for inverted use of control pins
+        #used for some hardware
+        self.invertRST = 0
+        self.invertTEST = 0
+        self.swapRSTTEST = 0
+        self.telosLatch = 0
+        self.telosI2C = 0
+        
+        self.z1 = 0
+        
+        self.protocolMode = self.MODE_BSL
+        self.BSLMemAccessWarning = 0                #Default: no warning.
+        self.slowmode = 0
+
+    def comInit(self, port):
+        """Tries to open the serial port given and
+        initialises the port and variables.
+        The timeout and the number of allowed errors is multiplied by
+        'aProlongFactor' after transmission of a command to give
+        plenty of time to the micro controller to finish the command.
+        Returns zero if the function is successful."""
+        if DEBUG > 1: sys.stderr.write("* comInit()\n")
+        self.seqNo = 0
+        self.reqNo = 0
+        self.rxPtr = 0
+        self.txPtr = 0
+        # Startup-Baudrate: 9600,8,E,1, 1s timeout
+        self.serialport = serial.Serial(
+            port,
+            9600,
+            parity = serial.PARITY_EVEN,
+            timeout = self.timeout
+        )
+        if DEBUG: sys.stderr.write("using serial port %r\n" % self.serialport.portstr)
+        #self.SetRSTpin()                        #enable power
+        #self.SetTESTpin()                       #enable power
+        self.serialport.flushInput()
+        self.serialport.flushOutput()
+
+    def comDone(self):
+        """Closes the used serial port.
+        This function must be called at the end of a program,
+        otherwise the serial port might not be released and can not be
+        used in other programs.
+        Returns zero if the function is successful."""
+        if DEBUG > 1: sys.stderr.write("* comDone()")
+        self.SetRSTpin(1)                       #disable power
+        self.SetTESTpin(0)                      #disable power
+        self.serialport.close()
+
+    def comRxHeader(self):
+        """receive header and split data"""
+        if DEBUG > 1: sys.stderr.write("* comRxHeader()\n")
+
+        hdr = self.serialport.read(1)
+        if not hdr: raise BSLException("Timeout")
+        rxHeader = ord(hdr) & 0xf0;
+        rxNum    = ord(hdr) & 0x0f;
+
+        if self.protocolMode == self.MODE_BSL:
+            self.reqNo = 0
+            self.seqNo = 0
+            rxNum = 0
+        if DEBUG > 1: sys.stderr.write("* comRxHeader() OK\n")
+        return rxHeader, rxNum
+
+    def comRxFrame(self, rxNum):
+        if DEBUG > 1: sys.stderr.write("* comRxFrame()\n")
+        rxFrame = chr(self.DATA_FRAME | rxNum)
+
+        if DEBUG > 2: sys.stderr.write("  comRxFrame() header...\n")
+        rxFramedata = self.serialport.read(3)
+        if len(rxFramedata) != 3: raise BSLException("Timeout")
+        rxFrame = rxFrame + rxFramedata
+
+        if DEBUG > 3: sys.stderr.write("  comRxFrame() check header...\n")
+        if rxFrame[1] == chr(0) and rxFrame[2] == rxFrame[3]:   #Add. header info. correct?
+            rxLengthCRC = ord(rxFrame[2]) + 2       #Add CRC-Bytes to length
+            if DEBUG > 2: sys.stderr.write("  comRxFrame() receiving data, size: %s\n" % rxLengthCRC)
+
+            rxFramedata = self.serialport.read(rxLengthCRC)
+            if len(rxFramedata) != rxLengthCRC: raise BSLException("Timeout")
+            rxFrame = rxFrame + rxFramedata
+            #Check received frame:
+            if DEBUG > 3: sys.stderr.write("  comRxFrame() crc check\n")
+            #rxLength+4: Length with header but w/o CRC:
+            checksum = self.calcChecksum(rxFrame, ord(rxFrame[2]) + 4)
+            if rxFrame[ord(rxFrame[2])+4] == chr(0xff & checksum) and \
+               rxFrame[ord(rxFrame[2])+5] == chr(0xff & (checksum >> 8)): #Checksum correct?
+                #Frame received correctly (=> send next frame)
+                if DEBUG > 2: sys.stderr.write("* comRxFrame() OK\n")
+                return rxFrame
+            else:
+                if DEBUG: sys.stderr.write("  comRxFrame() Checksum wrong\n")
+        else:
+            if DEBUG: sys.stderr.write("  comRxFrame() Header corrupt %r" % rxFrame)
+        raise BSLException(self.ERR_COM)            #Frame has errors!
+
+    def comTxHeader(self, txHeader):
+        """send header"""
+        if DEBUG > 1: sys.stderr.write("* txHeader()\n")
+        self.serialport.write(txHeader)
+
+    def comTxRx(self, cmd, dataOut, length):
+        """Sends the command cmd with the data given in dataOut to the
+        microcontroller and expects either an acknowledge or a frame
+        with result from the microcontroller.  The results are stored
+        in dataIn (if not a NULL pointer is passed).
+        In this routine all the necessary protocol stuff is handled.
+        Returns zero if the function was successful."""
+        if DEBUG > 1: sys.stderr.write("* comTxRx()\n")
+        txFrame     = []
+        rxHeader    = 0
+        rxNum       = 0
+
+        dataOut = list(dataOut)     #convert to a list for simpler data fill in
+        #Transmitting part ----------------------------------------
+        #Prepare data for transmit
+        if (length % 2) != 0:
+            #/* Fill with one byte to have even number of bytes to send */
+            if self.protocolMode == self.MODE_BSL:
+                dataOut.append(0xFF)  #fill with 0xFF
+            else:
+                dataOut.append(0)     #fill with zero
+
+        txFrame = "%c%c%c%c" % (self.DATA_FRAME | self.seqNo, cmd, len(dataOut), len(dataOut))
+
+        self.reqNo = (self.seqNo + 1) % self.MAX_FRAME_COUNT
+
+        txFrame = txFrame + string.join(dataOut,'')
+        checksum = self.calcChecksum(txFrame, length + 4)
+        txFrame = txFrame + chr(checksum & 0xff)
+        txFrame = txFrame + chr((checksum >> 8) & 0xff)
+
+        accessAddr = (0x0212 + (checksum^0xffff)) & 0xfffe  #0x0212: Address of wCHKSUM
+        if self.BSLMemAccessWarning and accessAddr < self.BSL_CRITICAL_ADDR:
+            sys.stderr.write("WARNING: This command might change data at address %04x or %04x!\n" % (accessAddr, accessAddr + 1))
+
+        self.serialport.flushInput()                #clear receiving queue
+        #TODO: Check after each transmitted character,
+        #TODO: if microcontroller did send a character (probably a NAK!).
+        for c in txFrame:
+            self.serialport.write(c)
+            if DEBUG > 3: sys.stderr.write("\ttx %02x" % ord(c))
+            #if self.serialport.inWaiting(): break  #abort when BSL replies, probably NAK
+        else:
+            if DEBUG > 1: sys.stderr.write( "  comTxRx() transmit OK\n")
+
+        #Receiving part -------------------------------------------
+        rxHeader, rxNum = self.comRxHeader()        #receive header
+        if DEBUG > 1: sys.stderr.write("  comTxRx() rxHeader=0x%02x, rxNum=%d, seqNo=%d, reqNo=%s\n" % (rxHeader, rxNum, self.seqNo, self.reqNo))
+        if rxHeader == self.DATA_ACK:               #acknowledge/OK
+            if DEBUG > 2: sys.stderr.write("  comTxRx() DATA_ACK\n")
+            if rxNum == self.reqNo:
+                self.seqNo = self.reqNo
+                if DEBUG > 2: sys.stderr.write("* comTxRx() DATA_ACK OK\n")
+                return          #Acknowledge received correctly => next frame
+            raise BSLException(self.ERR_FRAME_NUMBER)
+        elif rxHeader == self.DATA_NAK:             #not acknowledge/error
+            if DEBUG > 2: sys.stderr.write("* comTxRx() DATA_NAK\n")
+            raise BSLException(self.ERR_RX_NAK)
+        elif rxHeader == self.DATA_FRAME:           #receive data
+            if DEBUG > 2: sys.stderr.write("* comTxRx() DATA_FRAME\n")
+            if rxNum == self.reqNo:
+                rxFrame = self.comRxFrame(rxNum)
+                return rxFrame
+            raise BSLException(self.ERR_FRAME_NUMBER)
+        elif rxHeader == self.CMD_FAILED:           #Frame ok, but command failed.
+            if DEBUG > 2: sys.stderr.write("*  comTxRx() CMD_FAILED\n")
+            raise BSLException(self.ERR_CMD_FAILED)
+
+        raise BSLException("Unknown header 0x%02x\nAre you downloading to RAM into an old device that requires the patch? Try option -U" % rxHeader)
+
+    def SetDTR(self, level, invert):
+        """Controls DTR pin (0: GND; 1: VCC; unless inverted flag is set)"""
+        #print 'fucking the dtr'
+        if invert:
+            self.serialport.setDTR(not level)
+        else:
+            self.serialport.setDTR(level)
+        if self.slowmode:
+            time.sleep(0.040)
+
+    def SetRTS(self, level, invert):
+        """Controls RTS pin (0: GND; 1: VCC; unless inverted flag is set)"""
+        if invert:
+            self.serialport.setRTS(not level)
+        else:
+            self.serialport.setRTS(level)
+        if self.slowmode:
+            time.sleep(0.040)
+
+    def SetRSTpin(self, level=1):
+        """Controls RST/NMI pin (0: GND; 1: VCC; unless inverted flag is set)"""
+        if self.swapRSTTEST:
+            self.SetRTS(level, self.invertRST)
+        else:
+            self.SetDTR(level, self.invertRST)
+
+    def SetTESTpin(self, level=1):
+        """Controls TEST pin (inverted on board: 0: VCC; 1: GND; unless inverted flag is set)"""
+        if self.swapRSTTEST:
+            self.SetDTR(level, self.invertTEST)
+        else:
+            self.SetRTS(level, self.invertTEST)
+
+
+    def writepicROM(self, address, data):
+        ''' Writes data to @address'''
+        for i in range(7,-1,-1):
+            self.picROMclock((address >> i) & 0x01)
+        self.picROMclock(0)
+        recbuf = 0
+        for i in range(7,-1,-1):
+            s = ((data >> i) & 0x01)
+            #print s
+            if i < 1:
+                r = not self.picROMclock(s, True)
+            else:
+                r = not self.picROMclock(s)
+            recbuf = (recbuf << 1) + r
+
+        self.picROMclock(0, True)
+        #k = 1
+        #while not self.serial.getCTS():
+        #    pass 
+        #time.sleep(0.1)
+        return recbuf
+
+    def readpicROM(self, address):
+        ''' reads a byte from @address'''
+        for i in range(7,-1,-1):
+            self.picROMclock((address >> i) & 0x01)
+        self.picROMclock(1)
+        recbuf = 0
+        r = 0
+        for i in range(7,-1,-1):
+            r = self.picROMclock(0)
+            recbuf = (recbuf << 1) + r
+        self.picROMclock(r)
+        #time.sleep(0.1)
+        return recbuf
+        
+    def picROMclock(self, masterout, slow = False):
+        #print "setting masterout to "+str(masterout)
+        self.serialport.setRTS(masterout)
+        self.serialport.setDTR(1)
+        #time.sleep(0.02)
+        self.serialport.setDTR(0)
+        if slow:
+            time.sleep(0.02)
+        return self.serialport.getCTS()
+
+    def picROMfastclock(self, masterout):
+        #print "setting masterout to "+str(masterout)
+        self.serialport.setRTS(masterout)
+        self.serialport.setDTR(1)
+        self.serialport.setDTR(0)
+        time.sleep(0.02)
+        return self.serialport.getCTS()
+
+    def bslResetZ1(self, invokeBSL=0):
+        '''
+        Applies BSL entry sequence on RST/NMI and TEST/VPP pins
+        Parameters:
+            invokeBSL = 1: complete sequence
+            invokeBSL = 0: only RST/NMI pin accessed
+            
+        By now only BSL mode is accessed
+        '''
+        
+        if DEBUG > 1: sys.stderr.write("* bslReset(invokeBSL=%s)\n" % invokeBSL)
+        if invokeBSL:
+            #sys.stderr.write("in Z1 bsl reset...\n")
+            time.sleep(0.1)
+            self.writepicROM(0xFF, 0xFF)
+            time.sleep(0.1)
+            #sys.stderr.write("z1 bsl reset done...\n")
+        else:
+            #sys.stderr.write("in Z1 reset...\n")
+            time.sleep(0.1)
+            self.writepicROM(0xFF, 0xFE)
+            time.sleep(0.1)
+            #sys.stderr.write("z1 reset done...\n")
+
+    def telosSetSCL(self, level):
+        self.serialport.setRTS(not level)
+
+    def telosSetSDA(self, level):
+        self.serialport.setDTR(not level)
+
+    def telosI2CStart(self):
+        self.telosSetSDA(1)
+        self.telosSetSCL(1)
+        self.telosSetSDA(0)
+
+    def telosI2CStop(self):
+        self.telosSetSDA(0)
+        self.telosSetSCL(1)
+        self.telosSetSDA(1)
+
+    def telosI2CWriteBit(self, bit):
+        self.telosSetSCL(0)
+        self.telosSetSDA(bit)
+        time.sleep(2e-6)
+        self.telosSetSCL(1)
+        time.sleep(1e-6)
+        self.telosSetSCL(0)
+
+    def telosI2CWriteByte(self, byte):
+        self.telosI2CWriteBit( byte & 0x80 );
+        self.telosI2CWriteBit( byte & 0x40 );
+        self.telosI2CWriteBit( byte & 0x20 );
+        self.telosI2CWriteBit( byte & 0x10 );
+        self.telosI2CWriteBit( byte & 0x08 );
+        self.telosI2CWriteBit( byte & 0x04 );
+        self.telosI2CWriteBit( byte & 0x02 );
+        self.telosI2CWriteBit( byte & 0x01 );
+        self.telosI2CWriteBit( 0 );  # "acknowledge"
+
+    def telosI2CWriteCmd(self, addr, cmdbyte):
+        self.telosI2CStart()
+        self.telosI2CWriteByte( 0x90 | (addr << 1) )
+        self.telosI2CWriteByte( cmdbyte )
+        self.telosI2CStop()
+
+    def telosBReset(self,invokeBSL=0):
+        # "BSL entry sequence at dedicated JTAG pins"
+            # rst !s0: 0 0 0 0 1 1
+        # tck !s1: 1 0 1 0 0 1
+            #   s0|s1: 1 3 1 3 2 0
+    
+        # "BSL entry sequence at shared JTAG pins"
+            # rst !s0: 0 0 0 0 1 1
+        # tck !s1: 0 1 0 1 1 0
+            #   s0|s1: 3 1 3 1 0 2
+        if invokeBSL:
+          self.telosI2CWriteCmd(0,1)
+          self.telosI2CWriteCmd(0,3)
+          self.telosI2CWriteCmd(0,1)
+          self.telosI2CWriteCmd(0,3)
+          self.telosI2CWriteCmd(0,2)
+          self.telosI2CWriteCmd(0,0)
+        else:
+          self.telosI2CWriteCmd(0,3)
+          self.telosI2CWriteCmd(0,2)
+          self.telosI2CWriteCmd(0,0)
+          time.sleep(0.250)       #give MSP430's oscillator time to stabilize
+        self.serialport.flushInput()  #clear buffers
+
+    def bslReset(self, invokeBSL=0):
+        """Applies BSL entry sequence on RST/NMI and TEST/VPP pins
+        Parameters:
+            invokeBSL = 1: complete sequence
+            invokeBSL = 0: only RST/NMI pin accessed
+
+        RST is inverted twice on boot loader hardware
+        TEST is inverted (only once)
+        Need positive voltage on DTR, RTS for power-supply of hardware"""
+        
+        #print 'goint to reset!'
+        
+        if self.telosI2C:
+            self.telosBReset(invokeBSL)
+            return
+    
+        if self.z1:
+            if DEBUG > 1: sys.stderr.write("* entering bsl with z1\n")
+            self.bslResetZ1(invokeBSL)
+            return
+    
+        if DEBUG > 1: sys.stderr.write("* bslReset(invokeBSL=%s)\n" % invokeBSL)
+        self.SetRSTpin(1)       #power suply
+        self.SetTESTpin(1)      #power suply
+        time.sleep(0.250)       #charge capacitor on boot loader hardware
+    
+        if self.telosLatch:
+            self.SetTESTpin(0)
+            self.SetRSTpin(0)
+            self.SetTESTpin(1)
+    
+            self.SetRSTpin(0)       #RST  pin: GND
+        if invokeBSL:
+            self.SetTESTpin(1)  #TEST pin: GND
+            self.SetTESTpin(0)  #TEST pin: Vcc
+            self.SetTESTpin(1)  #TEST pin: GND
+            self.SetTESTpin(0)  #TEST pin: Vcc
+            self.SetRSTpin (1)  #RST  pin: Vcc
+            self.SetTESTpin(1)  #TEST pin: GND
+        else:
+            self.SetRSTpin(1)   #RST  pin: Vcc
+        time.sleep(0.250)       #give MSP430's oscillator time to stabilize
+    
+        self.serialport.flushInput()    #clear buffers
+
+    def bslSync(self,wait=0):
+        """Transmits Synchronization character and expects to receive Acknowledge character
+        if wait is 0 it must work the first time. otherwise if wait is 1
+        it is retried (forever).
+        """
+        loopcnt = 5                                 #Max. tries to get synchronization
+
+        if DEBUG > 1: sys.stderr.write("* bslSync(wait=%d)\n" % wait)
+        while wait or loopcnt:
+            loopcnt = loopcnt - 1                   #count down tries
+            self.serialport.flushInput()            #clear input, in case a prog is running
+
+            self.serialport.write(chr(self.BSL_SYNC))   #Send synchronization byte
+            c = self.serialport.read(1)             #read answer
+            if c == chr(self.DATA_ACK):             #ACk
+                if DEBUG > 1: sys.stderr.write("  bslSync() OK\n")
+                return                              #Sync. successful
+            elif not c:                             #timeout
+                    if loopcnt > 4:
+                        if DEBUG > 1:
+                            sys.stderr.write("  bslSync() timeout, retry ...\n")
+                    elif loopcnt == 4:
+                        #nmi may have caused the first reset to be ignored, try again
+                        self.bslReset(0) 
+                        self.bslReset(1)
+                    elif loopcnt > 0:
+                        if DEBUG > 1:
+                            sys.stderr.write("  bslSync() timeout, retry ...\n")
+                    else :
+                        if DEBUG > 1:
+                            sys.stderr.write("  bslSync() timeout\n")
+            else:                                   #garbage
+                if DEBUG > 1: sys.stderr.write("  bslSync() failed (0x%02x), retry ...\n" % ord(c))
+                
+                raise BSLException(self.ERR_BSL_SYNC)       #Sync. failed
+
+    def bslTxRx(self, cmd, addr, length = 0, blkout = None, wait=0):
+        """Transmits a command (cmd) with its parameters:
+        start-address (addr), length (len) and additional
+        data (blkout) to boot loader.
+        wait specified if the bsl sync should be tried once or
+        repeated, forever
+        Parameters return by boot loader are passed via blkin.
+        """
+        if DEBUG > 1: sys.stderr.write("* bslTxRx()\n")
+
+        if cmd == self.BSL_TXBLK:
+            #Align to even start address
+            if (addr % 2) != 0:
+                addr = addr - 1                     #Decrement address and
+                blkout = chr(0xFF) + blkOut         #fill first byte of blkout with 0xFF
+                length = length + 1
+            #Make sure that len is even
+            if (length % 2) != 0:
+                blkout = blkout + chr(0xFF)         #Inc. len and fill last byte of blkout with 0xFF
+                length = length + 1
+
+        elif cmd == self.BSL_RXBLK:
+            #Align to even start address
+            if (addr % 2) != 0:
+                addr = addr - 1                     #Decrement address but
+                length = length + 1                 #request an additional byte
+            #Make sure that len is even
+            if (length % 2) != 0:
+                length = length + 1
+
+        #if cmd == self.BSL_TXBLK or cmd == self.BSL_TXPWORD:
+        #    length = len + 4
+
+        #Add necessary information data to frame
+        dataOut =  struct.pack("<HH", addr, length)
+
+        if blkout: #Copy data out of blkout into frame
+            dataOut = dataOut + blkout
+
+        self.bslSync(wait)                          #synchronize BSL
+        rxFrame = self.comTxRx(cmd, dataOut, len(dataOut))  #Send frame
+        if rxFrame:                                 #test answer
+            return rxFrame[4:] #return only data w/o [hdr,null,len,len]
+        else:
+            return rxFrame
+
+
+class Segment:
+    """store a string with memory contents along with its startaddress"""
+    def __init__(self, startaddress = 0, data=None):
+        if data is None:
+            self.data = ''
+        else:
+            self.data = data
+        self.startaddress = startaddress
+
+    def __getitem__(self, index):
+        return self.data[index]
+
+    def __len__(self):
+        return len(self.data)
+
+    def __repr__(self):
+        return "Segment(startaddress = 0x%04x, data=%r)" % (self.startaddress, self.data)
+
+class Memory:
+    """represent memory contents. with functions to load files"""
+    def __init__(self, filename=None):
+        self.segments = []
+        if filename:
+            self.filename = filename
+            self.loadFile(filename)
+
+    def append(self, seg):
+        self.segments.append(seg)
+
+    def __getitem__(self, index):
+        return self.segments[index]
+
+    def __len__(self):
+        return len(self.segments)
+
+    def loadIHex(self, file):
+        """load data from a (opened) file in Intel-HEX format"""
+        segmentdata = []
+        currentAddr = 0
+        startAddr   = 0
+        offsetAddr  = 0
+        lines = file.readlines()
+        for l in lines:
+            if l[0] != ':': raise BSLException("File Format Error\n")
+            l = l.strip()       #fix CR-LF issues...
+            length  = int(l[1:3],16)
+            address = int(l[3:7],16)
+            type    = int(l[7:9],16)
+            check   = int(l[-2:],16)
+            if type == 0x00:
+                if currentAddr != offsetAddr + address:
+                    if segmentdata:
+                        self.segments.append( Segment(startAddr, string.join(segmentdata,'')) )
+                    startAddr = currentAddr = offsetAddr + address
+                    segmentdata = []
+                for i in range(length):
+                    segmentdata.append( chr(int(l[9+2*i:11+2*i],16)) )
+                currentAddr = length + currentAddr
+            elif type == 0x02:
+                if segmentdata:
+                    self.segments.append( Segment(startAddr, string.join(segmentdata,'')) )
+                offsetAddr = int(l[9:13],16)*16
+                startAddr = currentAddr = offsetAddr
+                segmentdata = []
+            elif type in (0x01, 0x03, 0x04, 0x05):
+                pass
+            else:
+                sys.stderr.write("Ignored unknown field (type 0x%02x) in ihex file.\n" % type)
+        if segmentdata:
+            self.segments.append( Segment(startAddr, string.join(segmentdata,'')) )
+
+        if DEBUG:
+            sys.stderr.write("loadIHex\n")
+            for segment in self.segments:
+                sys.stderr.write("  Segment(startadress = 0x%04x, len = %i)\n" % (segment.startaddress, len(segment)))
+
+    def loadTIText(self, file):
+        """load data from a (opened) file in TI-Text format"""
+        next        = 1
+        startAddr   = 0
+        segmentdata = []
+        #Convert data for MSP430, TXT-File is parsed line by line
+        while next >= 1:
+            #Read one line
+            l = file.readline()
+            if not l: break #EOF
+            l = l.strip()
+            if l[0] == 'q': break
+            elif l[0] == '@':        #if @ => new address => send frame and set new addr.
+                #create a new segment
+                if segmentdata:
+                    self.segments.append( Segment(startAddr, string.join(segmentdata,'')) )
+                startAddr = int(l[1:],16)
+                segmentdata = []
+            else:
+                for i in string.split(l):
+                    segmentdata.append(chr(int(i,16)))
+        if segmentdata:
+            self.segments.append( Segment(startAddr, string.join(segmentdata,'')) )
+
+    def loadELF(self, file):
+        """load data from a (opened) file in ELF object format.
+        File must be seekable"""
+        import elf
+        obj = elf.ELFObject()
+        obj.fromFile(file)
+        if obj.e_type != elf.ELFObject.ET_EXEC:
+            raise Exception("No executable")
+        for section in obj.getSections():
+            if DEBUG:
+                sys.stderr.write("ELF section %s at 0x%04x %d bytes\n" % (section.name, section.lma, len(section.data)))
+            if len(section.data):
+                self.segments.append( Segment(section.lma, section.data) )
+        
+    def loadFile(self, filename):
+        """fill memory with the contents of a file. file type is determined from extension"""
+        #TODO: do a contents based detection
+        if filename[-4:].lower() == '.txt':
+            self.loadTIText(open(filename, "rb"))
+        elif filename[-4:].lower() in ('.a43', '.hex'):
+            self.loadIHex(open(filename, "rb"))
+        else:
+            self.loadELF(open(filename, "rb"))
+
+    def getMemrange(self, fromadr, toadr):
+        """get a range of bytes from the memory. unavailable values are filled with 0xff."""
+        res = ''
+        toadr = toadr + 1   #python indxes are excluding end, so include it
+        while fromadr < toadr:
+            #print "fromto: %04x %04x" % (fromadr, toadr)
+            for seg in self.segments:
+                #print seg
+                segend = seg.startaddress + len(seg.data)
+                if seg.startaddress <= fromadr and fromadr < segend:
+                    #print "startok 0x%04x %d" % (seg.startaddress, len(seg.data))
+                    #print ("0x%04x "*3) % (segend, fromadr, toadr)
+                    if toadr > segend:   #not all data in segment
+                        #print "out of segment"
+                        catchlength = segend-fromadr
+                    else:
+                        catchlength = toadr-fromadr
+                    #print toadr-fromadr
+                    #print catchlength
+                    res = res + seg.data[fromadr-seg.startaddress : fromadr-seg.startaddress+catchlength]
+                    fromadr = fromadr + catchlength    #adjust start
+                    if len(res) >= toadr-fromadr:
+                        break#return res
+            else:
+                    res = res + chr(255)
+                    fromadr = fromadr + 1 #adjust start
+                    #print "fill FF"
+        #print "res: %r" % res
+        return res
+
+
+class BootStrapLoader(LowLevel):
+    """higher level Bootstrap Loader functions."""
+
+    ERR_VERIFY_FAILED       = "Error: verification failed"
+    ERR_ERASE_CHECK_FAILED  = "Error: erase check failed"
+
+    ACTION_PROGRAM          = 0x01 #Mask: program data
+    ACTION_VERIFY           = 0x02 #Mask: verify data
+    ACTION_ERASE_CHECK      = 0x04 #Mask: erase check
+
+    #Max. bytes sent within one frame if parsing a TI TXT file.
+    #( >= 16 and == n*16 and <= MAX_DATA_BYTES!)
+    MAXDATA                 = 240-16
+
+
+    def __init__(self, *args, **kargs):
+        LowLevel.__init__(self, *args, **kargs)
+        self.byteCtr        = 0
+        self.meraseCycles   = 1
+        self.patchRequired  = 0
+        self.patchLoaded    = 0
+        self.bslVer         = 0
+        self.passwd         = None
+        self.data           = None
+        self.maxData        = self.MAXDATA
+        self.cpu            = None
+        self.pwdsent        = False
+
+
+    def preparePatch(self):
+        """prepare to download patch"""
+        if DEBUG > 1: sys.stderr.write("* preparePatch()\n")
+
+        if self.patchLoaded:
+            #Load PC with 0x0220.
+            #This will invoke the patched bootstrap loader subroutines.
+            self.bslTxRx(self.BSL_LOADPC,           #Command: Load PC
+                           0x0220)                  #Address to load into PC
+            self.BSLMemAccessWarning = 0 #Error is removed within workaround code
+        return
+
+    def postPatch(self):
+        """setup after the patch is loaded"""
+        if DEBUG > 1: sys.stderr.write("* postPatch()\n")
+        if self.patchLoaded:
+            self.BSLMemAccessWarning = 1                #Turn warning back on.
+
+    
+    def verifyBlk(self, addr, blkout, action):
+        """verify memory against data or 0xff"""
+        if DEBUG > 1: sys.stderr.write("* verifyBlk()\n")
+
+        if action & self.ACTION_VERIFY or action & self.ACTION_ERASE_CHECK:
+            if DEBUG: sys.stderr.write("  Check starting at 0x%04x, %d bytes ... \n" % (addr, len(blkout)))
+
+            self.preparePatch()
+            blkin = self.bslTxRx(self.BSL_RXBLK, addr, len(blkout))
+            self.postPatch()
+
+            for i in range(len(blkout)):
+                if action & self.ACTION_VERIFY:
+                    #Compare data in blkout and blkin
+                    if blkin[i] != blkout[i]:
+                        sys.stderr.write("Verification failed at 0x%04x (0x%02x, 0x%02x)\n" % (addr+i, ord(blkin[i]), ord(blkout[i])))
+                        sys.stderr.flush()
+                        raise BSLException(self.ERR_VERIFY_FAILED)      #Verify failed!
+                    continue
+                elif action & self.ACTION_ERASE_CHECK:
+                    #Compare data in blkin with erase pattern
+                    if blkin[i] != chr(0xff):
+                        sys.stderr.write("Erase Check failed at 0x%04x (0x%02x)\n" % (addr+i, ord(blkin[i])))
+                        sys.stderr.flush()
+                        raise BSLException(self.ERR_ERASE_CHECK_FAILED) #Erase Check failed!
+                    continue
+    def readBlk(self,adr,len):
+        """Read a block of memory."""
+        blkin = self.bslTxRx(self.BSL_RXBLK, addr, len(blkout))
+        
+    def programBlk(self, addr, blkout, action):
+        """program a memory block"""
+        if DEBUG > 1: sys.stderr.write("* programBlk()\n")
+
+        #Check, if specified range is erased
+        self.verifyBlk(addr, blkout, action & self.ACTION_ERASE_CHECK)
+
+        if action & self.ACTION_PROGRAM:
+            if DEBUG: sys.stderr.write("  Program starting at 0x%04x, %i bytes ...\n" % (addr, len(blkout)))
+            self.preparePatch()
+            #Program block
+            self.bslTxRx(self.BSL_TXBLK, addr, len(blkout), blkout)
+            self.postPatch()
+
+        #Verify block
+        self.verifyBlk(addr, blkout, action & self.ACTION_VERIFY)
+
+    #segments:
+    #list of tuples or lists:
+    #segements = [ (addr1, [d0,d1,d2,...]), (addr2, [e0,e1,e2,...])]
+    def programData(self, segments, action):
+        """programm or verify data"""
+        if DEBUG > 1: sys.stderr.write("* programData()\n")
+        for seg in segments:
+            currentAddr = seg.startaddress
+            offsetAddr = 0
+            if (seg.startaddress > 0xFFFF):
+                offsetAddr = seg.startaddress >> 16
+                self.bslTxRx(self.BSL_SETMEMOFFSET, 0, offsetAddr)
+                currentAddr = currentAddr - (offsetAddr << 16)
+            pstart = 0
+            while pstart<len(seg.data):
+                length = self.MAXDATA
+                if pstart+length > len(seg.data):
+                    length = len(seg.data) - pstart
+                self.programBlk(currentAddr, seg.data[pstart:pstart+length], action)
+                pstart = pstart + length
+                currentAddr = currentAddr + length
+                self.byteCtr = self.byteCtr + length #total sum
+    
+    def uploadData(self, startaddress, size, wait=0):
+        """upload a datablock"""
+        if DEBUG > 1: sys.stderr.write("* uploadData()\n")
+        data = ''
+        pstart = 0
+        while pstart<size:
+            length = self.maxData
+            if pstart+length > size:
+                length = size - pstart
+            data = data + self.bslTxRx(self.BSL_RXBLK,
+                                       pstart+startaddress,
+                                       length,
+                                       wait=wait)[:-2] #cut away checksum
+            pstart = pstart + length
+        return data
+
+    def txPasswd(self, passwd=None, wait=0):
+        """transmit password, default if None is given."""
+        if DEBUG > 1: sys.stderr.write("* txPassword(%r)\n" % passwd)
+        if passwd is None or self.pwdsent:
+            #Send "standard" password to get access to protected functions.
+            sys.stderr.write("Transmit default password ...\n")
+            sys.stderr.flush()
+            #Flash is completely erased, the contents of all Flash cells is 0xff
+            passwd = chr(0xff)*32
+        else:
+            #sanity check of password
+            if len(passwd) != 32:
+                raise ValueError, "password has wrong length (%d)\n" % len(passwd)
+            sys.stderr.write('Transmit password ...\n')
+            sys.stderr.flush()
+        #send the password
+        self.bslTxRx(self.BSL_TXPWORD,      #Command: Transmit Password
+                       0xffe0,              #Address of interupt vectors
+                       0x0020,              #Number of bytes
+                       passwd,              #password
+                       wait=wait)           #if wait is 1, try to sync forever
+        self.pwdsent = True
+        
+
+    def getNewPassword(self):
+        print 'getting new password'
+        newpassword = self.bslTxRx(self.BSL_RXBLK, 0xffe0, 0x0020)
+        return newpassword
+
+
+    def writeCalibTables(self):
+        print 'writing new tables'
+        print CALIB_TABLES
+        calibtables = ["84C016FEFFFFFFFFFFFFFFFFFFFFFFFF",
+                       "FFFFFFFFFFFFFFFFFFFF100880000001",
+                       "7E270B790DAA7E4D06DF083308FEFFFF",
+                       "FFFFFFFFFFFF08018F958E9A8D8886D1"]
+        self.programBlk(0x10C0, "84C016FEFFFFFFFFFFFFFFFFFFFFFFFF", self.ACTION_PROGRAM)
+        self.programBlk(0x10D0, "FFFFFFFFFFFFFFFFFFFF100880000001", self.ACTION_PROGRAM)
+        self.programBlk(0x10E0, "7E270B790DAA7E4D06DF083308FEFFFF", self.ACTION_PROGRAM)
+        self.programBlk(0x10F0, "FFFFFFFFFFFF08018F958E9A8D8886D1", self.ACTION_PROGRAM)
+
+    def writeCalibTables2(self):
+        print 'writing new tables 2ond part'
+        #self.programBlk(0x10C0, "84C016FEFFFFFFFFFFFFFFFFFFFFFFFF", self.ACTION_PROGRAM)
+        #self.programBlk(0x10D0, "FFFFFFFFFFFFFFFFFFFF100880000001", self.ACTION_PROGRAM)
+        #self.programBlk(0x10E0, "7E270B790DAA7E4D06DF083308FEFFFF", self.ACTION_PROGRAM)
+        #self.programBlk(0x10F0, "FFFFFFFFFFFF08018F958E9A8D8886D1", self.ACTION_PROGRAM)
+
+
+    #-----------------------------------------------------------------
+
+    def actionMassErase(self):
+        """Erase the flash memory completely (with mass erase command)"""
+        sys.stderr.write("Mass Erase...\n")
+        sys.stderr.flush()
+        self.bslReset(1)                            #Invoke the boot loader.
+        for i in range(self.meraseCycles):
+            if i == 1: sys.stderr.write("Additional Mass Erase Cycles...\n")
+            self.bslTxRx(self.BSL_MERAS,            #Command: Mass Erase
+                                0xff00,             #Any address within flash memory.
+                                0xa506)             #Required setting for mass erase!
+        self.passwd = None                          #No password file required!
+        #print "Mass Erase complete"
+        #Transmit password to get access to protected BSL functions.
+        self.txPasswd()
+
+    def actionMainErase(self):
+        """Erase the main flash memory only"""
+        sys.stderr.write("Main Erase...\n")
+        sys.stderr.flush()
+        self.bslTxRx(self.BSL_ERASE,                #Command: Segment Erase
+                            0xfffe,                 #Any address within flash memory.
+                            0xa504)                 #Required setting for main erase!
+        #self.passwd = None                          #Password gets erased WHY??
+
+
+
+    def actionStartBSL(self, usepatch=1, adjsp=1, replacementBSL=None, forceBSL=0, mayuseBSL=0, speed=None, bslreset=1):
+        """start BSL, download patch if desired and needed, adjust SP if desired"""
+        sys.stderr.write("Invoking BSL...\n")
+        sys.stderr.flush()
+        
+        #for '30, invertTEST=0, else =1
+        if bslreset:
+            #detext if is z1?
+            self.bslReset(1)                        #Invoke the boot loader.
+        
+        
+        if(self.z1):
+            ''' recover password from pic'''
+        
+        self.txPasswd(self.passwd)                  #transmit password
+
+        #Read actual bootstrap loader version.
+        #sys.stderr.write("Reading BSL version ...\n")
+        blkin = self.bslTxRx(self.BSL_RXBLK,        #Command: Read/Receive Block
+                          0x0ff0,                   #Start address
+                          16)                       #No. of bytes to read
+        dev_id, bslVerHi, bslVerLo = struct.unpack(">H8xBB4x", blkin[:-2]) #cut away checksum and extract data
+        self.dev_id=dev_id;
+        
+        
+        if self.cpu is None:                        #cpy type forced?
+            if deviceids.has_key(dev_id):
+                self.cpu = deviceids[dev_id]        #try to autodectect CPU type
+                
+                if DEBUG:
+                    sys.stderr.write("Autodetect successful: %04x -> %s\n" % (dev_id, self.cpu))
+            else:
+                sys.stderr.write("Autodetect failed! Unkown ID: %04x. Trying to continue anyway.\n" % dev_id)
+                self.cpu = F1x                      #assume something and try anyway..
+
+        sys.stderr.write("Current bootstrap loader version: %x.%x (Device ID: %04x)\n" % (bslVerHi, bslVerLo, dev_id))
+        sys.stderr.flush()
+        self.bslVer = (bslVerHi << 8) | bslVerLo
+
+        if self.bslVer <= 0x0110:                   #check if patch is needed
+            self.BSLMemAccessWarning = 1
+        else:
+            self.BSLMemAccessWarning = 0 #Fixed in newer versions of BSL.
+
+        if self.bslVer <= 0x0130 and adjsp:
+            #only do this on BSL where it's needed to prevent
+            #malfunction with F4xx devices/ newer ROM-BSLs
+            
+            #Execute function within bootstrap loader
+            #to prepare stack pointer for the following patch.
+            #This function will lock the protected functions again.
+            sys.stderr.write("Adjust SP. Load PC with 0x0C22 ...\n")
+            self.bslTxRx(self.BSL_LOADPC,           #Command: Load PC
+                                0x0C22)             #Address to load into PC
+            #Re-send password to re-gain access to protected functions.
+            self.txPasswd(self.passwd)
+
+        #get internal BSL replacement if needed or forced by the user
+        #required if speed is set but an old BSL is in the device
+        #if a BSL is given by the user, that one is used and not the internal one
+        if ((mayuseBSL and speed and self.bslVer < 0x0150) or forceBSL) and replacementBSL is None:
+            replacementBSL = Memory() #File to program
+            if self.cpu == F4x:
+                if DEBUG:
+                    sys.stderr.write("Using built in BSL replacement for F4x devices\n")
+                    sys.stderr.flush()
+                replacementBSL.loadTIText(cStringIO.StringIO(F4X_BSL))  #parse embedded BSL
+            else:
+                if DEBUG:
+                    sys.stderr.write("Using built in BSL replacement for F1x devices\n")
+                    sys.stderr.flush()
+                replacementBSL.loadTIText(cStringIO.StringIO(F1X_BSL))  #parse embedded BSL
+    
+        #now download the new BSL, if allowed and needed (version lower than the
+        #the replacement) or forced
+        if replacementBSL is not None:
+            self.actionDownloadBSL(replacementBSL)
+
+        #debug message with the real BSL version in use (may have changed after replacement BSL)
+        if DEBUG:
+            sys.stderr.write("Current bootstrap loader version: 0x%04x\n" % (self.bslVer,))
+            sys.stderr.flush()
+
+        #now apply workarounds or patches if BSL in use requires that
+        if self.bslVer <= 0x0110:                   #check if patch is needed
+            if usepatch:                            #test if patch is desired
+                sys.stderr.write("Patch for flash programming required!\n")
+                self.patchRequired = 1
+
+                sys.stderr.write("Load and verify patch ...\n")
+                sys.stderr.flush()
+                #Programming and verification is done in one pass.
+                #The patch file is only read and parsed once.
+                segments = Memory()                     #data to program
+                segments.loadTIText(cStringIO.StringIO(PATCH))  #parse embedded patch
+                #program patch
+                self.programData(segments, self.ACTION_PROGRAM | self.ACTION_VERIFY)
+                self.patchLoaded = 1
+            else:
+                if DEBUG:
+                    sys.stderr.write("Device needs patch, but not applied (usepatch is false).\n")    #message if not patched
+
+        #should the baudrate be changed?
+        if speed is not None:
+            self.actionChangeBaudrate(speed)            #change baudrate
+
+    def actionDownloadBSL(self, bslsegments):
+        sys.stderr.write("Load new BSL into RAM...\n")
+        sys.stderr.flush()
+        self.programData(bslsegments, self.ACTION_PROGRAM)
+        sys.stderr.write("Verify new BSL...\n")
+        sys.stderr.flush()
+        self.programData(bslsegments, self.ACTION_VERIFY) #File to verify
+
+        #Read startvector of bootstrap loader
+        #blkin = self.bslTxRx(self.BSL_RXBLK, 0x0300, 2)
+        #blkin = self.bslTxRx(self.BSL_RXBLK, 0x0220, 2)
+        blkin = self.bslTxRx(self.BSL_RXBLK, bslsegments[0].startaddress, 2)
+        startaddr = struct.unpack("<H", blkin[:2])[0]
+
+        sys.stderr.write("Starting new BSL at 0x%04x...\n" % startaddr)
+        sys.stderr.flush()
+        self.bslTxRx(self.BSL_LOADPC,  #Command: Load PC
+                     startaddr)        #Address to load into PC
+
+        #BSL-Bugs should be fixed within "new" BSL
+        self.BSLMemAccessWarning = 0
+        self.patchRequired = 0
+        self.patchLoaded   = 0
+
+        #Re-send password to re-gain access to protected functions.
+        self.txPasswd(self.passwd)
+
+        #update version info
+        #verison only valid for the internal ones, but it also makes sure 
+        #that the patches are not applied if the user d/ls one
+        self.bslVer = 0x0150
+
+    def actionEraseCheck(self):
+        """check the erasure of required flash cells."""
+        sys.stderr.write("Erase Check by file ...\n")
+        sys.stderr.flush()
+        if self.data is not None:
+            self.programData(self.data, self.ACTION_ERASE_CHECK)
+        else:
+            raise BSLException, "cannot do erase check against data with not knowing the actual data"
+
+    def actionProgram(self):
+        """program data into flash memory."""
+        if self.data is not None:
+            sys.stderr.write("Program ...\n")
+            sys.stderr.flush()
+            self.programData(self.data, self.ACTION_PROGRAM)
+            sys.stderr.write("%i bytes programmed.\n" % self.byteCtr)
+            sys.stderr.flush()
+        else:
+            raise BSLException, "programming without data not possible"
+    def actionFromweb(self):
+        """Grab GoodFET firmware from the web, then flash it."""
+        print "Grabbing %x firmware." % self.dev_id;
+        print "%s" % firmware[self.dev_id];
+        fn="/tmp/.goodfet.hex"
+        os.system("curl %s >%s" % (firmware[self.dev_id],fn))
+        
+        fw=Memory(fn);
+        #fw.loadIhex(open(fn,"rb"));
+        
+        sys.stderr.write("Program ...\n")
+        sys.stderr.flush()
+        self.programData(fw, self.ACTION_PROGRAM | self.ACTION_VERIFY)
+        sys.stderr.write("%i bytes programmed.\n" % self.byteCtr)
+        sys.stderr.flush()
+        
+    def actionVerify(self):
+        """Verify programmed data"""
+        if self.data is not None:
+            sys.stderr.write("Verify ...\n")
+            sys.stderr.flush()
+            self.programData(self.data, self.ACTION_VERIFY)
+        else:
+            raise BSLException, "verify without data not possible"
+
+    def actionReset(self):
+        """perform a reset, start user programm"""
+        sys.stderr.write("Reset device ...\n")
+        sys.stderr.flush()
+        self.bslReset(0) #only reset
+
+    def actionRun(self, address=0x220):
+        """start program at specified address"""
+        sys.stderr.write("Load PC with 0x%04x ...\n" % address)
+        sys.stderr.flush()
+        self.bslTxRx(self.BSL_LOADPC, #Command: Load PC
+                            address)  #Address to load into PC
+
+    #table with values from slaa089a.pdf
+    bauratetable = {
+        F1x: {
+             9600:[0x8580, 0x0000],
+            19200:[0x86e0, 0x0001],
+            38400:[0x87e0, 0x0002],
+        },
+        F2x: {
+             9600:[0x8580, 0x0000],
+            19200:[0x8B00, 0x0001],
+            38400:[0x8C80, 0x0002],
+        },
+        F4x: {
+             9600:[0x9800, 0x0000],
+            19200:[0xb000, 0x0001],
+            38400:[0xc800, 0x0002],
+        },
+    }
+    def actionChangeBaudrate(self, baudrate=9600):
+        """change baudrate. first the command is sent, then the comm
+        port is reprogrammed. only possible with newer MSP430-BSL versions.
+        (ROM >=1.6, downloadable >=1.5)"""
+        try:
+            baudconfigs = self.bauratetable[self.cpu]
+        except KeyError:
+            raise ValueError, "unknown CPU type %s, can't switch baudrate" % self.cpu
+        try:
+            a,l = baudconfigs[baudrate]
+        except KeyError:
+            raise ValueError, "baudrate not valid. valid values are %r" % baudconfigs.keys()
+        
+        sys.stderr.write("Changing baudrate to %d ...\n" % baudrate)
+        sys.stderr.flush()
+        self.bslTxRx(self.BSL_CHANGEBAUD,   #Command: change baudrate
+                    a, l)                   #args are coded in adr and len
+        self.serialport.flush()
+        time.sleep(0.010)                   #recomended delay
+        self.serialport.baudrate = baudrate
+
+    def actionReadBSLVersion(self):
+        """informational output of BSL version number.
+        (newer MSP430-BSLs only)"""
+        ans = self.bslTxRx(self.BSL_TXVERSION, 0) #Command: receive version info
+        #the following values are in big endian style!!!
+        family_type, bsl_version = struct.unpack(">H8xH4x", ans[:-2]) #cut away checksum and extract data
+        print "Device Type: 0x%04x\nBSL version: 0x%04x\n" % (family_type, bsl_version)
+
+    def actionWriteNewPassword(self):
+        passwd = self.getNewPassword()
+        #print passwd
+        self.picWritePassword(passwd)
+
+    def actionRecoverPassword(self):
+        p = self.picRecoverPassword()
+        #print p
+        self.passwd = p
+
+    def picRecoverPassword(self):
+        ''' recovers password from picrom'''
+        print 'recovering pic password',
+        p = ''
+        
+        for i in range(0,32):
+             c = self.readpicROM(i)
+             print c,
+             p = p + chr(c)
+             
+        print 'done'
+        return p
+        
+    def picWritePassword(self, password):
+        ''' writes a new password to picrom'''
+        print 'writing new password',
+        for i in range(0,32):
+            c = ord(password[i])
+            print c,
+            self.writepicROM(i, c)
+        print 'done'
+
+
+def usage():
+    """print some help message"""
+    sys.stderr.write("""
+USAGE: %s [options] [file]
+Version: %s
+
+If "-" is specified as file the data is read from the stdinput.
+A file ending with ".txt" is considered to be in TIText format,
+'.a43' and '.hex' as IntelHex and all other filenames are
+considered as ELF files.
+
+General options:
+  -h, --help            Show this help screen.
+  -c, --comport=port    Specify the communication port to be used.
+                        (Default is 0)
+                                0->COM1 / ttyS0
+                                1->COM2 / ttyS1
+                                etc.
+  -P, --password=file   Specify a file with the interrupt vectors that
+                        are used as password. This can be any file that
+                        has previously been used to program the device.
+                        (e.g. -P INT_VECT.TXT).
+  -f, --framesize=num   Max. number of data bytes within one transmitted
+                        frame (16 to 240 in steps of 16) (e.g. -f 240).
+  -m, --erasecycles=num Number of mass erase cycles (default is 1). Some
+                        old F149 devices need additional erase cycles.
+                        On newer devices it is no longer needed. (e.g. for
+                        an old F149: -m20)
+  -U, --unpatched       Do not download the BSL patch, even when it is
+                        needed. This is used when a program is downloaded
+                        into RAM and executed from there (and where flash
+                        programming is not needed.)
+  -D, --debug           Increase level of debug messages. This won't be
+                        very useful for the average user...
+  -I, --intelhex        Force fileformat to IntelHex
+  -T, --titext          Force fileformat to be TIText
+  -N, --notimeout       Don't use timeout on serial port (use with care)
+  -B, --bsl=bsl.txt     Load and use new BSL from the TI Text file
+  -S, --speed=baud      Reconfigure speed, only possible with newer
+                        MSP403-BSL versions (>1.5, read slaa089a.pdf for
+                        details). If the --bsl option is not used, an
+                        internal BSL replacement will be loaded.
+                        Needs a target with at least 2kB RAM!
+                        Possible values are 9600, 19200, 38400
+                        (default 9600)
+  -1, --f1x             Specify CPU family, in case autodetect fails
+  -2, --f2x             Specify CPU family, in case autodetect fails
+  -4, --f4x             Specify CPU family, in case autodetect fails
+                        --F1x and --f2x are only needed when the "change
+                        baudrate" feature is used and the autodetect feature
+                        fails. If the device ID that is uploaded is known, it
+                        has precedence to the command line option.
+  --invert-reset        Invert signal on RST pin (used for some BSL hardware)
+  --invert-test         Invert signal on TEST/TCK pin (used for some BSL
+                        hardware)
+  --swap-reset-test     Swap the RST and TEST pins (used for some BSL hardware)
+  --telos-latch         Special twiddle in BSL reset for Telos hardware
+  --telos-i2c           DTR/RTS map via an I2C switch to TCK/RST in Telos Rev.B
+  --telos               Implies options --invert-reset, --invert-test, 
+                        --swap-reset-test, and --telos-latch
+  --telosb              Implies options --swap-reset-test, --telos-i2c,
+                        --no-BSL-download, and --speed=38400
+  --goodfet10
+  --goodfet20
+  --goodfet30
+  --tmote               Identical operation to --telosb
+  --z1                  Bootstrap a Z1
+  --no-BSL-download     Do not download replacement BSL (disable automatic)
+  --force-BSL-download  Download replacement BSL even if not needed (the one
+                        in the device would have the required features)
+  --slow                Add delays when operating the conrol pins. Useful if
+                        the pins/circuit has high capacitance.
+
+Program Flow Specifiers:
+  -e, --masserase       Mass Erase (clear all flash memory)
+  -E, --erasecheck      Erase Check by file
+  -p, --program         Program file
+  -v, --verify          Verify by file
+
+The order of the above options matters! The table is ordered by normal
+execution order. For the options "Epv" a file must be specified.
+Program flow specifiers default to "pvr" if a file is given.
+Don't forget to specify "e" or "eE" when programming flash!
+
+Data retreiving:
+  -u, --upload=addr     Upload a datablock (see also: -s).
+  -s, --size=num        Size of the data block do upload. (Default is 2)
+  -x, --hex             Show a hexadecimal display of the uploaded data.
+                        (Default)
+  -b, --bin             Get binary uploaded data. This can be used
+                        to redirect the output into a file.
+
+Do before exit:
+  -g, --go=address      Start programm execution at specified address.
+                        This implies option --wait.
+  -r, --reset           Reset connected MSP430. Starts application.
+                        This is a normal device reset and will start
+                        the programm that is specified in the reset
+                        vector. (see also -g)
+  -w, --wait            Wait for <ENTER> before closing serial port.
+
+If it says "NAK received" it's probably because you specified no or a
+wrong password.
+""" % (sys.argv[0], VERSION))
+
+#add some arguments to a function, but don't call it yet, instead return
+#a wrapper object for later invocation
+class curry:
+    """create a callable with some arguments specified in advance"""
+    def __init__(self, fun, *args, **kwargs):
+        self.fun = fun
+        self.pending = args[:]
+        self.kwargs = kwargs.copy()
+
+    def __call__(self, *args, **kwargs):
+        if kwargs and self.kwargs:
+            kw = self.kwargs.copy()
+            kw.update(kwargs)
+        else:
+            kw = kwargs or self.kwargs
+        return apply(self.fun, self.pending + args, kw)
+
+    def __repr__(self):
+        #first try if it a function
+        try:
+            return "curry(%s, %r, %r)" % (self.fun.func_name, self.pending, self.kwargs)
+        except AttributeError:
+            #fallback for callable classes
+            return "curry(%s, %r, %r)" % (self.fun, self.pending, self.kwargs)
+
+def hexify(line, bytes, width=16):
+    return  '%04x  %s%s %s' % (
+        line,
+        ('%02x '*len(bytes)) % tuple(bytes),
+        '   '* (width-len(bytes)),
+        ('%c'*len(bytes)) % tuple(map(lambda x: (x>=32 and x<127) and x or ord('.'), bytes))
+        )
+
+#Main:
+def main(itest=1):
+    global DEBUG
+    import getopt
+    filetype    = None
+    filename    = None
+    comPort     = None     #Default setting.
+    speed       = None
+    unpatched   = 0
+    reset       = 0
+    wait        = 0     #wait at the end
+    goaddr      = None
+    bsl         = BootStrapLoader()
+    toinit      = []
+    todo        = []
+    startaddr   = None
+    size        = 2
+    hexoutput   = 1
+    notimeout   = 0
+    bslrepl     = None
+    mayuseBSL   = 1
+    forceBSL    = 0
+    dumpivt     = 0
+    dumpinfo    = 0
+    
+    bsl.invertRST = 1
+    bsl.invertTEST = itest
+    
+    if comPort is None and os.environ.get("GOODFET")!=None:
+        glob_list = glob.glob(os.environ.get("GOODFET"));
+        if len(glob_list) > 0:
+            comPort = glob_list[0];
+    if comPort is None:
+        glob_list = glob.glob("/dev/tty.usbserial*");
+        if len(glob_list) > 0:
+            comPort = glob_list[0];
+    if comPort is None:
+        glob_list = glob.glob("/dev/ttyUSB*");
+        if len(glob_list) > 0:
+            comPort = glob_list[0];
+    
+    
+    sys.stderr.write("MSP430 Bootstrap Loader Version: %s\n" % VERSION)
+
+    try:
+        opts, args = getopt.getopt(sys.argv[1:],
+            "hc:P:wf:m:neEpvrg:UDudsxbITNB:S:V14",
+            ["help", "comport=", "password=", "wait", "framesize=",
+             "erasecycles=", "masserase", "erasecheck", "program",
+             "verify", "reset", "go=", "unpatched", "debug",
+             "upload=", "download=", "size=", "hex", "bin",
+             "intelhex", "titext", "notimeout", "bsl=", "speed=",
+             "bslversion", "f1x", "f2x", "f4x", "invert-reset", "invert-test",
+             "swap-reset-test", "telos-latch", "telos-i2c", "telos", "telosb",
+             "tmote","no-BSL-download", "force-BSL-download", "slow",
+             "dumpivt", "dumpinfo", "fromweb",
+        "goodfet30", "goodfet20", "goodfet10", "z1", "mainerase"
+        ]
+        )
+    except getopt.GetoptError:
+        # print help information and exit:
+        usage()
+        sys.exit(2)
+
+    for o, a in opts:
+        if o in ("-h", "--help"):
+            usage()
+            sys.exit()
+        elif o in ("-c", "--comport"):
+            try:
+                comPort = int(a)                    #try to convert decimal
+            except ValueError:
+                comPort = a                         #take the string and let serial driver decide
+        elif o in ("-P", "--password"):
+            #extract password from file
+            bsl.passwd = Memory(a).getMemrange(0xffe0, 0xffff)
+        elif o in ("-w", "--wait"):
+            wait = 1
+        elif o in ("--dumpivt"):
+            dumpivt=1;
+        elif o in ("--dumpinfo"):
+            dumpinfo=1;
+        elif o in ("-f", "--framesize"):
+            try:
+                maxData = int(a)                    #try to convert decimal
+            except ValueError:
+                sys.stderr.write("framesize must be a valid number\n")
+                sys.exit(2)
+            #Make sure that conditions for maxData are met:
+            #( >= 16 and == n*16 and <= MAX_DATA_BYTES!)
+            if maxData > BootStrapLoader.MAX_DATA_BYTES:
+                maxData = BootStrapLoader.MAX_DATA_BYTES
+            elif maxData < 16:
+                maxData = 16
+            bsl.maxData = maxData - (maxData % 16)
+            sys.stderr.write( "Max. number of data bytes within one frame set to %i.\n" % maxData)
+        elif o in ("-m", "--erasecycles"):
+            try:
+                meraseCycles = int(a)               #try to convert decimal
+            except ValueError:
+                sys.stderr.write("erasecycles must be a valid number\n")
+                sys.exit(2)
+            #sanity check of value
+            if meraseCycles < 1:
+                sys.stderr.write("erasecycles must be a positive number\n")
+                sys.exit(2)
+            if meraseCycles > 20:
+                sys.stderr.write("warning: erasecycles set to a large number (>20): %d\n" % meraseCycles)
+            sys.stderr.write( "Number of mass erase cycles set to %i.\n" % meraseCycles)
+            bsl.meraseCycles = meraseCycles
+        elif o in ("-e", "--masserase"):
+            toinit.append(bsl.actionMassErase)        #Erase Flash
+            #todo.append(bsl.actionMainErase)        #Erase Flash
+        elif o in ("-n", "--mainerase"):
+            todo.append(bsl.actionMainErase)        #Erase Flash
+            #toinit.append(bsl.actionMassErase)        #Erase Flash
+        elif o in ("-E", "--erasecheck"):
+            toinit.append(bsl.actionEraseCheck)       #Erase Check (by file)
+        elif o in ("-p", "--program"):
+            #pass
+            todo.append(bsl.actionProgram)          #Program file
+            if bsl.z1:
+                #todo.append(bsl.actionUnlockInfo)
+                #todo.append(bsl.writeCalibTables)
+                #todo.append(bsl.writeCalibTables2)
+                
+                #todo.append(bsl.actionWriteNewPassword)
+                pass
+        elif o in ("--fromweb"):
+            toinit.append(bsl.actionMassErase)        #Erase Flash
+            todo.append(bsl.actionFromweb)          #Program GoodFET code
+        elif o in ("-v", "--verify"):
+            todo.append(bsl.actionVerify)           #Verify file
+        elif o in ("-r", "--reset"):
+            reset = 1
+        elif o in ("-g", "--go"):
+            try:
+                goaddr = int(a)                    #try to convert decimal
+            except ValueError:
+                try:
+                    goaddr = int(a[2:],16)         #try to convert hex
+                except ValueError:
+                    sys.stderr.write("go address must be a valid number\n")
+                    sys.exit(2)
+            wait = 1
+        elif o in ("-U", "--unpatched"):
+            unpatched = 1
+        elif o in ("-D", "--debug"):
+            DEBUG = DEBUG + 1
+        elif o in ("-u", "--upload"):
+            try:
+                startaddr = int(a)                  #try to convert decimal
+            except ValueError:
+                try:
+                    startaddr = int(a,16)           #try to convert hex
+                except ValueError:
+                    sys.stderr.write("upload address must be a valid number\n")
+                    sys.exit(2)
+        elif o in ("-s", "--size"):
+            try:
+                size = int(a)
+            except ValueError:
+                try:
+                    size = int(a,16)
+                except ValueError:
+                    sys.stderr.write("size must be a valid number\n")
+                    sys.exit(2)
+        elif o in ("-x", "--hex"):
+            hexoutput = 1
+        elif o in ("-b", "--bin"):
+            hexoutput = 0
+        elif o in ("-I", "--intelhex"):
+            filetype = 0
+        elif o in ("-T", "--titext"):
+            filetype = 1
+        elif o in ("-N", "--notimeout"):
+            notimeout = 1
+        elif o in ("-B", "--bsl"):
+            bslrepl = Memory() #File to program
+            bslrepl.loadFile(a)
+        elif o in ("-V", "--bslversion"):
+            todo.append(bsl.actionReadBSLVersion) #load replacement BSL as first item
+        elif o in ("-S", "--speed"):
+            try:
+                speed = int(a)                    #try to convert decimal
+            except ValueError:
+                sys.stderr.write("speed must be decimal number\n")
+                sys.exit(2)
+        elif o in ("-1", "--f1x"):
+            bsl.cpu = F1x
+        elif o in ("-2", "--f2x"):
+            bsl.cpu = F2x
+        elif o in ("-4", "--f4x"):
+            bsl.cpu = F4x
+        elif o in ("--invert-reset", ):
+            bsl.invertRST = 1
+        elif o in ("--invert-test", ):
+            bsl.invertTEST = 1
+        elif o in ("--swap-reset-test", ):
+            bsl.swapRSTTEST = 1
+        elif o in ("--telos-latch", ):
+            bsl.telosLatch = 1
+        elif o in ("--telos-i2c", ):
+            bsl.telosI2C = 1
+        elif o in ("--telos", ):
+            bsl.invertRST = 1
+            bsl.invertTEST = 1
+            bsl.swapRSTTEST = 1
+            bsl.telosLatch = 1
+        elif o in ("--goodfet10", ):
+            bsl.invertRST = 1
+            bsl.invertTEST = 1
+        elif o in ("--goodfet20", ):
+            bsl.invertRST = 1
+            bsl.invertTEST = 1
+        elif o in ("--goodfet30", ):
+            bsl.invertRST = 1
+            bsl.invertTEST = 0
+        elif o in ("--telosb", ):
+            bsl.swapRSTTEST = 1
+            bsl.telosI2C = 1
+            mayuseBSL = 0
+            speed = 38400
+        elif o in ("--tmote", ):
+            bsl.swapRSTTEST = 1
+            bsl.telosI2C = 1
+            mayuseBSL = 0
+            speed = 38400
+        elif o in ("--z1", ):
+            bsl.z1 = 1
+            speed = 38400
+            #toinit.append(bsl.actionRecoverPassword)
+        elif o in ("--no-BSL-download", ):
+            mayuseBSL = 0
+        elif o in ("--force-BSL-download", ):
+            forceBSL = 1
+        elif o in ("--slow", ):
+            bsl.slowmode = 1
+
+    if len(args) == 0:
+        sys.stderr.write("Use -h for help\n");
+        sys.stderr.write("Use --fromweb to upgrade a GoodFET.\n")
+    elif len(args) == 1:                            #a filename is given
+        if not todo:                                #if there are no actions yet
+            todo.extend([                           #add some useful actions...
+                bsl.actionProgram,
+                bsl.actionVerify,
+            ])
+        filename = args[0]
+    else:                                           #number of args is wrong
+        usage()
+        sys.exit(2)
+
+    if DEBUG:   #debug infos
+        sys.stderr.write("Debug level set to %d\n" % DEBUG)
+        sys.stderr.write("Python version: %s\n" % sys.version)
+
+    #sanity check of options
+    if notimeout and goaddr is not None and startaddr is not None:
+        sys.stderr.write("Option --notimeout can not be used together with both --upload and --go\n")
+        sys.exit(1)
+
+    if notimeout:
+        sys.stderr.write("Warning: option --notimeout can cause improper function in some cases!\n")
+        bsl.timeout = 0
+
+    if goaddr and reset:
+        sys.stderr.write("Warning: option --reset ignored as --go is specified!\n")
+        reset = 0
+
+    if startaddr and reset:
+        sys.stderr.write("Warning: option --reset ignored as --upload is specified!\n")
+        reset = 0
+
+    sys.stderr.flush()
+    
+    #prepare data to download
+    bsl.data = Memory()                             #prepare downloaded data
+    if filetype is not None:                        #if the filetype is given...
+        if filename is None:
+            raise ValueError("no filename but filetype specified")
+        if filename == '-':                         #get data from stdin
+            file = sys.stdin
+        else:
+            file = open(filename, "rb")             #or from a file
+        if filetype == 0:                           #select load function
+            bsl.data.loadIHex(file)                 #intel hex
+        elif filetype == 1:
+            bsl.data.loadTIText(file)               #TI's format
+        else:
+            raise ValueError("illegal filetype specified")
+    else:                                           #no filetype given...
+        if filename == '-':                         #for stdin:
+            bsl.data.loadIHex(sys.stdin)            #assume intel hex
+        elif filename:
+            bsl.data.loadFile(filename)             #autodetect otherwise
+
+    if DEBUG > 3: sys.stderr.write("File: %r" % filename)
+
+    bsl.comInit(comPort)                            #init port
+
+    #initialization list
+    if toinit:  #erase and erase check
+        if DEBUG: sys.stderr.write("Preparing device ...\n")
+        #bsl.actionStartBSL(usepatch=0, adjsp=0)     #no workarounds needed
+        #if speed: bsl.actionChangeBaudrate(speed)   #change baud rate as fast as possible
+        for f in toinit: f()
+
+    if todo or goaddr or startaddr:
+        if DEBUG: sys.stderr.write("Actions ...\n")
+        #connect to the BSL
+        bsl.actionStartBSL(
+            usepatch=not unpatched,
+            replacementBSL=bslrepl,
+            forceBSL=forceBSL,
+            mayuseBSL=mayuseBSL,
+            speed=speed,
+        )
+
+    #work list
+    if todo:
+        if DEBUG > 0:       #debug
+            #show a nice list of sheduled actions
+            sys.stderr.write("TODO list:\n")
+            for f in todo:
+                try:
+                    sys.stderr.write("   %s\n" % f.func_name)
+                except AttributeError:
+                    sys.stderr.write("   %r\n" % f)
+        for f in todo: f()                          #work through todo list
+
+    if reset:                                       #reset device first if desired
+        bsl.actionReset()
+    if dumpivt:
+        bsl.txPasswd(); #default pass
+        data=bsl.uploadData(0xc00,1024);
+        hex="";
+        for c in data:
+            hex+=("%02x "%ord(c));
+        print hex;
+    if dumpinfo:
+        bsl.txPasswd(); #default pass
+        data=bsl.uploadData(0x1000,256);
+        hex="@1000\n";
+        for c in data:
+            hex+=("%02x "%ord(c));
+        hex+="\nq\n";
+        print hex;
+    
+    if goaddr is not None:                          #start user programm at specified address
+        bsl.actionRun(goaddr)                       #load PC and execute
+
+    #upload datablock and output
+    if startaddr is not None:
+        if goaddr:                                  #if a program was started...
+            #don't restart BSL but wait for the device to enter it itself
+            sys.stderr.write("Waiting for device to reconnect for upload: ")
+            sys.stderr.flush()
+            bsl.txPasswd(bsl.passwd, wait=1)        #synchronize, try forever...
+            data = bsl.uploadData(startaddr, size)  #upload data
+        else:
+            data = bsl.uploadData(startaddr, size)  #upload data
+        if hexoutput:                               #depending on output format
+            m = 0
+            while m < len(data):                    #print a hex display
+                print hexify(startaddr+m, map(ord,data[m:m+16]))
+                m = m + 16
+        else:
+            sys.stdout.write(data)                  #binary output w/o newline!
+        wait = 0    #wait makes no sense as after the upload the device is still in BSL
+
+    if wait:                                        #wait at the end if desired
+        sys.stderr.write("Press <ENTER> ...\n")     #display a prompt
+        sys.stderr.flush()
+        raw_input()                                 #wait for newline
+
+    bsl.comDone()           #Release serial communication port
+
+if __name__ == '__main__':
+    try:
+        main(1)
+    except SystemExit:
+        raise               #let pass exit() calls
+    except KeyboardInterrupt:
+        if DEBUG: raise     #show full trace in debug mode
+        sys.stderr.write("user abort.\n")   #short messy in user mode
+        sys.exit(1)         #set errorlevel for script usage
+    except Exception, msg:  #every Exception is caught and displayed
+        if DEBUG: raise     #show full trace in debug mode
+        #sys.stderr.write("\nAn error occoured:\n%s\n" % msg) #short messy in user mode
+        #sys.exit(1)         #set errorlevel for script usage
+        main(0);