You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by an...@apache.org on 2017/12/18 13:55:11 UTC

[mynewt-nimble] 01/01: porting: Add FreeRTOS port (based on nRF5 SDK)

This is an automated email from the ASF dual-hosted git repository.

andk pushed a commit to branch freertos-port
in repository https://gitbox.apache.org/repos/asf/mynewt-nimble.git

commit c1b85089e0c11a32cb26a115433f286aa13697f7
Author: Andrzej Kaczmarek <an...@codecoup.pl>
AuthorDate: Wed Dec 6 10:36:40 2017 +0100

    porting: Add FreeRTOS port (based on nRF5 SDK)
    
    This patch adds port of Nimble stack to FreeRTOS based on nRF5 SDK.
    It's split into 'common' part which can be used a base for porting to
    any other platform and 'freertos_nrf5_sdk' which has FreeRTOS-specific
    files and makefile.
    
    Building and flashing is similar to other demo apps from nRF5 SDK:
    $ make -C porting/freertos_nrf5_sdk
    
    The resulting image can be flashed on nRF52 DK:
    $ make -C porting/freertos_nrf5_sdk flash
    
    Location of nRF5 SDK is set by NRF5_SDK_ROOT variable. By default it is
    set to 'nrf5_sdk' subdirectory so a symlink would work just fine:
    $ ln -s <x>/nRF5_SDK_12.3.0_d7731ad porting/freertos_nrf5_sdk/nrf5_sdk
---
 .gitignore                                         |    3 +
 porting/common/include/bsp/bsp.h                   |   14 +
 porting/common/include/console/console.h           |  116 ++
 porting/common/include/hal/hal_timer.h             |  105 ++
 porting/common/include/log/ignore.h                |   64 +
 porting/common/include/log/log.h                   |   89 ++
 porting/common/include/mem/mem.h                   |   66 +
 porting/common/include/nimble_port.h               |   35 +
 porting/common/include/os/endian.h                 |  225 ++++
 porting/common/include/os/os.h                     |   99 ++
 porting/common/include/os/os_arch.h                |   26 +
 porting/common/include/os/os_callout.h             |   62 +
 porting/common/include/os/os_cfg.h                 |   33 +
 porting/common/include/os/os_cputime.h             |  242 ++++
 porting/common/include/os/os_dev.h                 |  123 ++
 porting/common/include/os/os_error.h               |   52 +
 porting/common/include/os/os_eventq.h              |   68 +
 porting/common/include/os/os_fault.h               |   34 +
 porting/common/include/os/os_heap.h                |   38 +
 porting/common/include/os/os_malloc.h              |   42 +
 porting/common/include/os/os_mbuf.h                |  305 +++++
 porting/common/include/os/os_mempool.h             |  108 ++
 porting/common/include/os/os_mutex.h               |   67 +
 porting/common/include/os/os_sanity.h              |   64 +
 porting/common/include/os/os_sched.h               |   54 +
 porting/common/include/os/os_sem.h                 |   66 +
 porting/common/include/os/os_task.h                |  128 ++
 porting/common/include/os/os_test.h                |   33 +
 porting/common/include/os/os_time.h                |  120 ++
 porting/common/include/os/os_trace_api.h           |   84 ++
 porting/common/include/os/queue.h                  |  522 ++++++++
 porting/common/include/stats/stats.h               |   83 ++
 porting/common/include/sysinit/sysinit.h           |  128 ++
 porting/common/src/mem/mem.c                       |  245 ++++
 porting/common/src/nimble_port.c                   |   65 +
 porting/common/src/os/endian.c                     |  218 ++++
 porting/common/src/os/os.c                         |  240 ++++
 porting/common/src/os/os_callout.c                 |  230 ++++
 porting/common/src/os/os_cputime.c                 |  215 +++
 porting/common/src/os/os_cputime_1mhz.c            |   52 +
 porting/common/src/os/os_cputime_high.c            |   84 ++
 porting/common/src/os/os_cputime_pwr2.c            |   90 ++
 porting/common/src/os/os_dev.c                     |  346 +++++
 porting/common/src/os/os_eventq.c                  |  354 +++++
 porting/common/src/os/os_heap.c                    |  124 ++
 porting/common/src/os/os_mbuf.c                    | 1368 ++++++++++++++++++++
 porting/common/src/os/os_mempool.c                 |  321 +++++
 porting/common/src/os/os_msys_init.c               |   88 ++
 porting/common/src/os/os_mutex.c                   |  262 ++++
 porting/common/src/os/os_priv.h                    |   41 +
 porting/common/src/os/os_sanity.c                  |  250 ++++
 porting/common/src/os/os_sched.c                   |  377 ++++++
 porting/common/src/os/os_sem.c                     |  225 ++++
 porting/common/src/os/os_task.c                    |  284 ++++
 porting/common/src/os/os_time.c                    |  268 ++++
 porting/common/src/sysinit/sysinit.c               |   64 +
 porting/freertos_nrf5_sdk/Makefile                 |  257 ++++
 porting/freertos_nrf5_sdk/config/FreeRTOSConfig.h  |  229 ++++
 porting/freertos_nrf5_sdk/config/sdk_config.h      |  699 ++++++++++
 porting/freertos_nrf5_sdk/include/bsp/cmsis_nvic.h |   29 +
 porting/freertos_nrf5_sdk/include/mcu/nrf52_hal.h  |   70 +
 porting/freertos_nrf5_sdk/include/os/os_arch.h     |   25 +
 porting/freertos_nrf5_sdk/include/os/os_callout.h  |   52 +
 porting/freertos_nrf5_sdk/include/os/os_eventq.h   |   67 +
 porting/freertos_nrf5_sdk/include/os/os_mutex.h    |   46 +
 porting/freertos_nrf5_sdk/include/os/os_sem.h      |   27 +
 porting/freertos_nrf5_sdk/include/syscfg/syscfg.h  |  967 ++++++++++++++
 .../freertos_nrf5_sdk/nimble_FreeRTOS_gcc_nrf52.ld |   35 +
 porting/freertos_nrf5_sdk/src/ble_task.c           |  175 +++
 porting/freertos_nrf5_sdk/src/cmsis_nvic.c         |   73 ++
 porting/freertos_nrf5_sdk/src/hal_timer.c          |  932 +++++++++++++
 porting/freertos_nrf5_sdk/src/main.c               |   60 +
 porting/freertos_nrf5_sdk/src/os_port.c            |  348 +++++
 73 files changed, 13200 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..dfb676a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+# note: no / at the end since it could be either symlink or directory
+/porting/freertos_nrf5_sdk/nrf5_sdk
+/porting/freertos_nrf5_sdk/_build/
diff --git a/porting/common/include/bsp/bsp.h b/porting/common/include/bsp/bsp.h
new file mode 100644
index 0000000..60f8a3c
--- /dev/null
+++ b/porting/common/include/bsp/bsp.h
@@ -0,0 +1,14 @@
+#ifndef H_BSP_H
+#define H_BSP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define bssnz_t
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* H_BSP_H */
diff --git a/porting/common/include/console/console.h b/porting/common/include/console/console.h
new file mode 100644
index 0000000..7f9f0ed
--- /dev/null
+++ b/porting/common/include/console/console.h
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef __CONSOLE_H__
+#define __CONSOLE_H__
+
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct os_eventq;
+
+struct console_input {
+    char line[0];
+};
+
+typedef void (*console_rx_cb)(void);
+typedef int (*console_append_char_cb)(char *line, uint8_t byte);
+typedef void (*completion_cb)(char *str, console_append_char_cb cb);
+
+static int inline
+console_is_init(void)
+{
+    return 0;
+}
+
+static int inline
+console_init(console_rx_cb rx_cb)
+{
+    return 0;
+}
+
+static void inline
+console_write(const char *str, int cnt)
+{
+}
+
+static int inline
+console_read(char *str, int cnt, int *newline)
+{
+    *newline = 0;
+    return 0;
+}
+
+static void inline
+console_blocking_mode(void)
+{
+}
+
+static void inline
+console_non_blocking_mode(void)
+{
+}
+
+static void inline
+console_echo(int on)
+{
+}
+
+static int inline console_printf(const char *fmt, ...)
+    __attribute__ ((format (printf, 1, 2)));
+
+static int inline
+console_printf(const char *fmt, ...)
+{
+    return 0;
+}
+
+static void inline
+console_set_queues(struct os_eventq *avail_queue,
+                   struct os_eventq *cmd_queue)
+{
+}
+
+static void inline
+console_set_completion_cb(void (*completion)(char *str, console_append_char_cb cb))
+{
+}
+
+static int inline
+console_handle_char(uint8_t byte)
+{
+    return 0;
+}
+
+static int inline
+console_out(int character)
+{
+    return 0;
+}
+
+#define console_is_midline  (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __CONSOLE__ */
+
diff --git a/porting/common/include/hal/hal_timer.h b/porting/common/include/hal/hal_timer.h
new file mode 100644
index 0000000..1937130
--- /dev/null
+++ b/porting/common/include/hal/hal_timer.h
@@ -0,0 +1,105 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_HAL_TIMER_
+#define H_HAL_TIMER_
+
+#include <inttypes.h>
+#include "os/queue.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <inttypes.h>
+
+#include "os/queue.h"
+
+/* HAL timer struct */
+typedef void (*hal_timer_cb)(void *arg);
+
+/**
+ * The HAL timer structure. The user can declare as many of these structures
+ * as desired. They are enqueued on a particular HW timer queue when the user
+ * calls the hal_timer_start or hal_timer_start_at API. The user must have
+ * called hal_timer_set_cb before starting a timer.
+ *
+ * NOTE: the user should not have to modify/examine the contents of this
+ * structure; the hal timer API should be used.
+ */
+struct hal_timer
+{
+    void                *bsp_timer; /* Internal platform specific pointer */
+    hal_timer_cb        cb_func;    /* Callback function */
+    void                *cb_arg;    /* Callback argument */
+    uint32_t            expiry;     /* Tick at which timer should expire */
+    TAILQ_ENTRY(hal_timer) link;    /* Queue linked list structure */
+};
+
+/* Initialize a HW timer. */
+int hal_timer_init(int timer_num, void *cfg);
+
+/* Un-initialize a HW timer. */
+int hal_timer_deinit(int timer_num);
+
+/*
+ * Config a HW timer at the given frequency and start it. If the exact
+ * frequency is not obtainable the closest obtainable frequency is set.
+ */
+int hal_timer_config(int timer_num, uint32_t freq_hz);
+
+/*
+ * Returns the resolution of the HW timer. NOTE: the frequency may not be
+ * obtainable so the caller can use this to determine the resolution.
+ * Returns resolution in nanoseconds. A return value of 0 indicates an invalid
+ * timer was used.
+ */
+uint32_t hal_timer_get_resolution(int timer_num);
+
+/* Returns the HW timer current tick value */
+uint32_t hal_timer_read(int timer_num);
+
+/* Perform a blocking delay for a number of ticks. */
+int hal_timer_delay(int timer_num, uint32_t ticks);
+
+/*
+ * Set the timer structure prior to use. Should not be called if the timer
+ * is running. Must be called at least once prior to using timer.
+ */
+int hal_timer_set_cb(int timer_num, struct hal_timer *tmr, hal_timer_cb cb_func,
+                     void *arg);
+
+/* Start a timer that will expire in 'ticks' ticks. Ticks cannot be 0 */
+int hal_timer_start(struct hal_timer *, uint32_t ticks);
+
+/*
+ * Start a timer that will expire when the timer reaches 'tick'. If tick
+ * has already passed the timer callback will be called "immediately" (at
+ * interrupt context).
+ */
+int hal_timer_start_at(struct hal_timer *, uint32_t tick);
+
+/* Stop a currently running timer; associated callback will NOT be called */
+int hal_timer_stop(struct hal_timer *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_HAL_TIMER_ */
diff --git a/porting/common/include/log/ignore.h b/porting/common/include/log/ignore.h
new file mode 100644
index 0000000..46282a0
--- /dev/null
+++ b/porting/common/include/log/ignore.h
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_IGNORE_
+#define H_IGNORE_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * These macros prevent the "set but not used" warnings for log writes below
+ * the log level.
+ */
+
+#define IGN_1(X) ((void)(X))
+#define IGN_2(X, ...) ((void)(X));IGN_1(__VA_ARGS__)
+#define IGN_3(X, ...) ((void)(X));IGN_2(__VA_ARGS__)
+#define IGN_4(X, ...) ((void)(X));IGN_3(__VA_ARGS__)
+#define IGN_5(X, ...) ((void)(X));IGN_4(__VA_ARGS__)
+#define IGN_6(X, ...) ((void)(X));IGN_5(__VA_ARGS__)
+#define IGN_7(X, ...) ((void)(X));IGN_6(__VA_ARGS__)
+#define IGN_8(X, ...) ((void)(X));IGN_7(__VA_ARGS__)
+#define IGN_9(X, ...) ((void)(X));IGN_8(__VA_ARGS__)
+#define IGN_10(X, ...) ((void)(X));IGN_9(__VA_ARGS__)
+#define IGN_11(X, ...) ((void)(X));IGN_10(__VA_ARGS__)
+#define IGN_12(X, ...) ((void)(X));IGN_11(__VA_ARGS__)
+#define IGN_13(X, ...) ((void)(X));IGN_12(__VA_ARGS__)
+#define IGN_14(X, ...) ((void)(X));IGN_13(__VA_ARGS__)
+#define IGN_15(X, ...) ((void)(X));IGN_14(__VA_ARGS__)
+#define IGN_16(X, ...) ((void)(X));IGN_15(__VA_ARGS__)
+#define IGN_17(X, ...) ((void)(X));IGN_16(__VA_ARGS__)
+#define IGN_18(X, ...) ((void)(X));IGN_17(__VA_ARGS__)
+#define IGN_19(X, ...) ((void)(X));IGN_18(__VA_ARGS__)
+#define IGN_20(X, ...) ((void)(X));IGN_19(__VA_ARGS__)
+
+#define GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, \
+                  _13, _14, _15, _16, _17, _18, _19, _20, NAME, ...) NAME
+#define IGNORE(...) \
+    GET_MACRO(__VA_ARGS__, IGN_20, IGN_19, IGN_18, IGN_17, IGN_16, IGN_15, \
+              IGN_14, IGN_13, IGN_12, IGN_11, IGN_10, IGN_9, IGN_8, IGN_7, \
+              IGN_6, IGN_5, IGN_4, IGN_3, IGN_2, IGN_1)(__VA_ARGS__)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/porting/common/include/log/log.h b/porting/common/include/log/log.h
new file mode 100644
index 0000000..ac4d7e7
--- /dev/null
+++ b/porting/common/include/log/log.h
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef __SYS_LOG_STUB_H__
+#define __SYS_LOG_STUB_H__
+
+#include <inttypes.h>
+#include "syscfg/syscfg.h"
+#include "log/ignore.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define LOG_DEBUG(__l, __mod, ...) IGNORE(__VA_ARGS__)
+#define LOG_INFO(__l, __mod, ...) IGNORE(__VA_ARGS__)
+#define LOG_WARN(__l, __mod, ...) IGNORE(__VA_ARGS__)
+#define LOG_ERROR(__l, __mod, ...) IGNORE(__VA_ARGS__)
+#define LOG_CRITICAL(__l, __mod, ...) IGNORE(__VA_ARGS__)
+
+#define LOG_LEVEL_DEBUG         0
+#define LOG_LEVEL_INFO          1
+#define LOG_LEVEL_WARN          2
+#define LOG_LEVEL_ERROR         3
+#define LOG_LEVEL_CRITICAL      4
+/* Up to 7 custom log levels. */
+#define LOG_LEVEL_MAX           UINT8_MAX
+#define LOG_SYSLEVEL            UINT8_MAX
+
+/* Logging medium */
+#define LOG_STORE_CONSOLE    1
+#define LOG_STORE_CBMEM      2
+#define LOG_STORE_FCB        3
+
+/* Global log info */
+struct log_info {
+    uint32_t li_next_index;
+    uint8_t li_version;
+};
+
+struct log_info g_log_info;
+
+struct log {
+};
+
+struct log_handler {
+};
+
+static inline int
+log_register(char *name, struct log *log, const struct log_handler *h,
+             void *arg, uint8_t level)
+{
+    return 0;
+}
+
+static inline void
+log_init(void)
+{
+}
+
+#define log_printf(...)
+
+/*
+ * Dummy handler exports.
+ */
+const struct log_handler log_console_handler;
+const struct log_handler log_cbmem_handler;
+const struct log_handler log_fcb_handler;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SYS_LOG_STUB_H__ */
diff --git a/porting/common/include/mem/mem.h b/porting/common/include/mem/mem.h
new file mode 100644
index 0000000..18461b6
--- /dev/null
+++ b/porting/common/include/mem/mem.h
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_UTIL_MEM_
+#define H_UTIL_MEM_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct os_mempool;
+struct os_mbuf_pool;
+
+int mem_malloc_mempool(struct os_mempool *mempool, int num_blocks,
+                       int block_size, char *name, void **out_buf);
+
+int mem_malloc_mbuf_pool(struct os_mempool *mempool,
+                         struct os_mbuf_pool *mbuf_pool, int num_blocks,
+                         int block_size, char *name,
+                         void **out_buf);
+int mem_malloc_mbufpkt_pool(struct os_mempool *mempool,
+                            struct os_mbuf_pool *mbuf_pool, int num_blocks,
+                            int block_size, char *name,
+                            void **out_buf);
+int mem_init_mbuf_pool(void *mem, struct os_mempool *mempool,
+                       struct os_mbuf_pool *mbuf_pool, int num_blocks,
+                       int block_size, char *name);
+
+/**
+ * Specifies a function used as a callback.  Functions of this type allocate an
+ * mbuf chain meant to hold a packet fragment.  The resulting mbuf must contain
+ * a pkthdr.
+ *
+ * @param frag_size             The number of data bytes that the mbuf will
+ *                                  eventually contain.
+ * @param arg                   A generic parameter.
+ *
+ * @return                      An allocated mbuf chain on success;
+ *                              NULL on failure.
+ */
+typedef struct os_mbuf *mem_frag_alloc_fn(uint16_t frag_size, void *arg);
+
+struct os_mbuf *mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz,
+                               mem_frag_alloc_fn *alloc_cb, void *cb_arg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/porting/common/include/nimble_port.h b/porting/common/include/nimble_port.h
new file mode 100755
index 0000000..6d5e214
--- /dev/null
+++ b/porting/common/include/nimble_port.h
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef __NIMBLE_PORT_H__
+#define __NIMBLE_PORT_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void nimble_init(void);
+
+void nimble_run(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __NIMBLE_PORT_H__ */
diff --git a/porting/common/include/os/endian.h b/porting/common/include/os/endian.h
new file mode 100644
index 0000000..ca8698d
--- /dev/null
+++ b/porting/common/include/os/endian.h
@@ -0,0 +1,225 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_ENDIAN_
+#define H_ENDIAN_
+
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Internal helpers */
+#ifndef os_bswap_64
+#define os_bswap_64(x)   ((uint64_t)                \
+     ((((x) & 0xff00000000000000ull) >> 56) |       \
+      (((x) & 0x00ff000000000000ull) >> 40) |       \
+      (((x) & 0x0000ff0000000000ull) >> 24) |       \
+      (((x) & 0x000000ff00000000ull) >>  8) |       \
+      (((x) & 0x00000000ff000000ull) <<  8) |       \
+      (((x) & 0x0000000000ff0000ull) << 24) |       \
+      (((x) & 0x000000000000ff00ull) << 40) |       \
+      (((x) & 0x00000000000000ffull) << 56)))
+#endif
+
+#ifndef os_bswap_32
+#define os_bswap_32(x)    ((uint32_t)               \
+    ((((x) & 0xff000000) >> 24) |                   \
+     (((x) & 0x00ff0000) >>  8) |                   \
+     (((x) & 0x0000ff00) <<  8) |                   \
+     (((x) & 0x000000ff) << 24)))
+#endif
+
+#ifndef os_bswap_16
+#define os_bswap_16(x)   ((uint16_t)                \
+    ((((x) & 0xff00) >> 8) |                        \
+     (((x) & 0x00ff) << 8)))
+#endif
+
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+
+#ifndef ntohll
+#define ntohll(x)  ((uint64_t)(x))
+#endif
+
+#ifndef htonll
+#define htonll(x)  ((uint64_t)(x))
+#endif
+
+#ifndef ntohl
+#define ntohl(x)   ((uint32_t)(x))
+#endif
+
+#ifndef htonl
+#define htonl(x)   ((uint32_t)(x))
+#endif
+
+#ifndef ntohs
+#define ntohs(x)   ((uint16_t)(x))
+#endif
+
+#ifndef htons
+#define htons(x)   ((uint16_t)(x))
+#endif
+
+#ifndef htobe16
+#define htobe16(x) ((uint16_t)(x))
+#endif
+
+#ifndef htole16
+#define htole16(x) os_bswap_16 (x)
+#endif
+
+#ifndef be16toh
+#define be16toh(x) ((uint16_t)(x))
+#endif
+
+#ifndef le16toh
+#define le16toh(x) os_bswap_16 (x)
+#endif
+
+#ifndef htobe32
+#define htobe32(x) ((uint32_t)(x))
+#endif
+
+#ifndef htole32
+#define htole32(x) os_bswap_32 (x)
+#endif
+
+#ifndef be32toh
+#define be32toh(x) ((uint32_t)(x))
+#endif
+
+#ifndef le32toh
+#define le32toh(x) os_bswap_32 (x)
+#endif
+
+#ifndef htobe64
+#define htobe64(x) ((uint64_t)(x))
+#endif
+
+#ifndef htole64
+#define htole64(x) os_bswap_64 (x)
+#endif
+
+#ifndef be64toh
+#define be64toh(x) ((uint64_t)(x))
+#endif
+
+#ifndef le64toh
+#define le64toh(x) os_bswap_64 (x)
+#endif
+
+#else
+
+#ifndef ntohll
+#define ntohll(x)   os_bswap_64(x)
+#endif
+
+#ifndef htonll
+#define htonll      ntohll
+#endif
+
+#ifndef ntohl
+#define ntohl(x)    os_bswap_32(x)
+#endif
+
+#ifndef htonl
+#define htonl       ntohl
+#endif
+
+#ifndef htons
+#define htons(x)    os_bswap_16(x)
+#endif
+
+#ifndef ntohs
+#define ntohs       htons
+#endif
+
+#ifndef htobe16
+#define htobe16(x) os_bswap_16(x)
+#endif
+
+#ifndef htole16
+#define htole16(x) ((uint16_t)(x))
+#endif
+
+#ifndef be16toh
+#define be16toh(x) os_bswap_16(x)
+#endif
+
+#ifndef le16toh
+#define le16toh(x) ((uint16_t)(x))
+#endif
+
+#ifndef htobe32
+#define htobe32(x) os_bswap_32(x)
+#endif
+
+#ifndef htole32
+#define htole32(x) ((uint32_t)(x))
+#endif
+
+#ifndef be32toh
+#define be32toh(x) os_bswap_32(x)
+#endif
+
+#ifndef le32toh
+#define le32toh(x) ((uint32_t)(x))
+#endif
+
+#ifndef htobe64
+#define htobe64(x) os_bswap64(x)
+#endif
+
+#ifndef htole64
+#define htole64(x) ((uint64_t)(x))
+#endif
+
+#ifndef be64toh
+#define be64toh(x) os_bswap64(x)
+#endif
+
+#ifndef le64toh
+#define le64toh(x) ((uint64_t)(x))
+#endif
+
+#endif
+
+void put_le16(void *buf, uint16_t x);
+void put_le32(void *buf, uint32_t x);
+void put_le64(void *buf, uint64_t x);
+uint16_t get_le16(const void *buf);
+uint32_t get_le32(const void *buf);
+uint64_t get_le64(const void *buf);
+void put_be16(void *buf, uint16_t x);
+void put_be32(void *buf, uint32_t x);
+void put_be64(void *buf, uint64_t x);
+uint16_t get_be16(const void *buf);
+uint32_t get_be32(const void *buf);
+uint64_t get_be64(const void *buf);
+void swap_in_place(void *buf, int len);
+void swap_buf(uint8_t *dst, const uint8_t *src, int len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/porting/common/include/os/os.h b/porting/common/include/os/os.h
new file mode 100644
index 0000000..9ff6ed5
--- /dev/null
+++ b/porting/common/include/os/os.h
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _OS_H
+#define _OS_H
+
+#include <stdlib.h>
+#include <inttypes.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef min
+#define min(a, b) ((a)<(b)?(a):(b))
+#endif
+
+#ifndef max
+#define max(a, b) ((a)>(b)?(a):(b))
+#endif
+
+#define os_get_return_addr() (__builtin_return_address(0))
+
+#define OS_ALIGN(__n, __a) (                             \
+        (((__n) & ((__a) - 1)) == 0)                   ? \
+            (__n)                                      : \
+            ((__n) + ((__a) - ((__n) & ((__a) - 1))))    \
+        )
+
+
+#define CTASSERT(x) typedef int __ctasssert ## __LINE__[(x) ? 1 : -1]
+
+
+/**
+ * Whether or not the operating system has been started.  Set to
+ * 1 right before first task is run.
+ */
+extern int g_os_started;
+
+int os_info_init(void);
+
+/**
+ * Returns 1 if the OS has been started, 0 if it has not yet been
+ * been started.
+ */
+int os_started(void);
+
+#define OS_WAIT_FOREVER (-1)
+
+#define OS_IDLE_PRIO (0xff)
+#define OS_MAIN_TASK_PRIO       MYNEWT_VAL(OS_MAIN_TASK_PRIO)
+#define OS_MAIN_STACK_SIZE      MYNEWT_VAL(OS_MAIN_STACK_SIZE)
+
+void os_init(int (*fn)(int argc, char **argv));
+void os_start(void);
+
+/* XXX: Not sure if this should go here; I want to differentiate API that
+ * should be called by application developers as those that should not. */
+void os_init_idle_task(void);
+
+#include "os/endian.h"
+#include "os/os_arch.h"
+#include "os/os_callout.h"
+#include "os/os_cputime.h"
+#include "os/os_dev.h"
+#include "os/os_error.h"
+#include "os/os_eventq.h"
+#include "os/os_heap.h"
+#include "os/os_fault.h"
+#include "os/os_mbuf.h"
+#include "os/os_mempool.h"
+#include "os/os_mutex.h"
+#include "os/os_sanity.h"
+#include "os/os_sched.h"
+#include "os/os_sem.h"
+#include "os/os_task.h"
+#include "os/os_time.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_H */
diff --git a/porting/common/include/os/os_arch.h b/porting/common/include/os/os_arch.h
new file mode 100755
index 0000000..22d47f7
--- /dev/null
+++ b/porting/common/include/os/os_arch.h
@@ -0,0 +1,26 @@
+#ifndef _OS_ARCH_H
+#define _OS_ARCH_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef int os_sr_t;
+typedef int os_stack_t;
+
+#define OS_ALIGNMENT (4)
+#define OS_TICKS_PER_SEC (1000)
+
+extern void vPortEnterCritical(void);
+extern void vPortExitCritical(void);
+
+#define OS_ENTER_CRITICAL(unused) do { (void)unused; vPortEnterCritical(); } while (0)
+#define OS_EXIT_CRITICAL(unused) do { (void)unused; vPortExitCritical(); } while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_ARCH_H */
diff --git a/porting/common/include/os/os_callout.h b/porting/common/include/os/os_callout.h
new file mode 100644
index 0000000..254d7a4
--- /dev/null
+++ b/porting/common/include/os/os_callout.h
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+#ifndef _OS_CALLOUT_H
+#define _OS_CALLOUT_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define OS_CALLOUT_F_QUEUED (0x01)
+
+#include "os/os_eventq.h"
+
+struct os_callout {
+    struct os_event c_ev;
+    struct os_eventq *c_evq;
+    uint32_t c_ticks;
+    TAILQ_ENTRY(os_callout) c_next;
+};
+
+TAILQ_HEAD(os_callout_list, os_callout);
+
+void os_callout_init(struct os_callout *cf, struct os_eventq *evq,
+                     os_event_fn *ev_cb, void *ev_arg);
+void os_callout_stop(struct os_callout *);
+int os_callout_reset(struct os_callout *, int32_t);
+void os_callout_tick(void);
+os_time_t os_callout_wakeup_ticks(os_time_t now);
+os_time_t os_callout_remaining_ticks(struct os_callout *c, os_time_t now);
+
+static inline int
+os_callout_queued(struct os_callout *c)
+{
+    return c->c_next.tqe_prev != NULL;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_CALLOUT_H */
+
+
+
diff --git a/porting/common/include/os/os_cfg.h b/porting/common/include/os/os_cfg.h
new file mode 100644
index 0000000..15f43d5
--- /dev/null
+++ b/porting/common/include/os/os_cfg.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+#ifndef _OS_CFG_H_
+#define _OS_CFG_H_ 
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_CFG_H_ */
diff --git a/porting/common/include/os/os_cputime.h b/porting/common/include/os/os_cputime.h
new file mode 100644
index 0000000..fc3b881
--- /dev/null
+++ b/porting/common/include/os/os_cputime.h
@@ -0,0 +1,242 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_OS_CPUTIME_
+#define H_OS_CPUTIME_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "syscfg/syscfg.h"
+#include "os/queue.h"
+#include "hal/hal_timer.h"
+
+/*
+ * NOTE: these definitions allow one to override the cputime frequency used.
+ * The reason these definitions exist is to make the code more
+ * efficient/smaller when CPUTIME counts at 1 MHz.
+ *
+ * For those who want a different cputime frequency, you can set the config
+ * definition for OS_CPUTIME_FREQ to the desired frequency in your project,
+ * target or bsp.
+ */
+#if (MYNEWT_VAL(OS_CPUTIME_FREQ) == 1000000)
+
+#define OS_CPUTIME_FREQ_1MHZ
+
+#elif MYNEWT_VAL(OS_CPUTIME_FREQ) == 256        ||  \
+      MYNEWT_VAL(OS_CPUTIME_FREQ) == 512        ||  \
+      MYNEWT_VAL(OS_CPUTIME_FREQ) == 1024       ||  \
+      MYNEWT_VAL(OS_CPUTIME_FREQ) == 2048       ||  \
+      MYNEWT_VAL(OS_CPUTIME_FREQ) == 4096       ||  \
+      MYNEWT_VAL(OS_CPUTIME_FREQ) == 8192       ||  \
+      MYNEWT_VAL(OS_CPUTIME_FREQ) == 16384      ||  \
+      MYNEWT_VAL(OS_CPUTIME_FREQ) == 32768      ||  \
+      MYNEWT_VAL(OS_CPUTIME_FREQ) == 65536      ||  \
+      MYNEWT_VAL(OS_CPUTIME_FREQ) == 131072     ||  \
+      MYNEWT_VAL(OS_CPUTIME_FREQ) == 262144     ||  \
+      MYNEWT_VAL(OS_CPUTIME_FREQ) == 524288
+
+#define OS_CPUTIME_FREQ_PWR2
+
+#elif MYNEWT_VAL(OS_CPUTIME_FREQ) > 1000000
+
+#define OS_CPUTIME_FREQ_HIGH
+
+#else
+
+#error "Invalid OS_CPUTIME_FREQ value.  Value must be one of a) a power of 2" \
+       ">= 256Hz, or b) any value >= 1MHz"
+
+#endif
+
+#if defined(OS_CPUTIME_FREQ_HIGH)
+/* CPUTIME data. */
+struct os_cputime_data
+{
+    uint32_t ticks_per_usec;    /* number of ticks per usec */
+};
+extern struct os_cputime_data g_os_cputime;
+#endif
+
+/* Helpful macros to compare cputimes */
+#define CPUTIME_LT(__t1, __t2) ((int32_t)   ((__t1) - (__t2)) < 0)
+#define CPUTIME_GT(__t1, __t2) ((int32_t)   ((__t1) - (__t2)) > 0)
+#define CPUTIME_GEQ(__t1, __t2) ((int32_t)  ((__t1) - (__t2)) >= 0)
+#define CPUTIME_LEQ(__t1, __t2) ((int32_t)  ((__t1) - (__t2)) <= 0)
+
+/**
+ * os cputime init
+ *
+ * Initialize the cputime module. This must be called after os_init is called
+ * and before any other timer API are used. This should be called only once
+ * and should be called before the hardware timer is used.
+ *
+ * @param clock_freq The desired cputime frequency, in hertz (Hz).
+ *
+ * @return int 0 on success; -1 on error.
+ */
+int os_cputime_init(uint32_t clock_freq);
+
+/**
+ * os cputime get32
+ *
+ * Returns the low 32 bits of cputime.
+ *
+ * @return uint32_t The lower 32 bits of cputime
+ */
+uint32_t os_cputime_get32(void);
+
+#if !defined(OS_CPUTIME_FREQ_PWR2)
+/**
+ * os cputime nsecs to ticks
+ *
+ * Converts the given number of nanoseconds into cputime ticks.
+ *
+ * @param usecs The number of nanoseconds to convert to ticks
+ *
+ * @return uint32_t The number of ticks corresponding to 'nsecs'
+ */
+uint32_t os_cputime_nsecs_to_ticks(uint32_t nsecs);
+
+/**
+ * os cputime ticks to nsecs
+ *
+ * Convert the given number of ticks into nanoseconds.
+ *
+ * @param ticks The number of ticks to convert to nanoseconds.
+ *
+ * @return uint32_t The number of nanoseconds corresponding to 'ticks'
+ */
+uint32_t os_cputime_ticks_to_nsecs(uint32_t ticks);
+
+/**
+ * os cputime delay nsecs
+ *
+ * Wait until 'nsecs' nanoseconds has elapsed. This is a blocking delay.
+ *
+ * @param nsecs The number of nanoseconds to wait.
+ */
+void os_cputime_delay_nsecs(uint32_t nsecs);
+#endif
+
+#if defined(OS_CPUTIME_FREQ_1MHZ)
+#define os_cputime_usecs_to_ticks(x)    (x)
+#define os_cputime_ticks_to_usecs(x)    (x)
+#else
+/**
+ * os cputime usecs to ticks
+ *
+ * Converts the given number of microseconds into cputime ticks.
+ *
+ * @param usecs The number of microseconds to convert to ticks
+ *
+ * @return uint32_t The number of ticks corresponding to 'usecs'
+ */
+uint32_t os_cputime_usecs_to_ticks(uint32_t usecs);
+
+/**
+ * os cputime ticks to usecs
+ *
+ * Convert the given number of ticks into microseconds.
+ *
+ * @param ticks The number of ticks to convert to microseconds.
+ *
+ * @return uint32_t The number of microseconds corresponding to 'ticks'
+ */
+uint32_t os_cputime_ticks_to_usecs(uint32_t ticks);
+#endif
+
+/**
+ * os cputime delay ticks
+ *
+ * Wait until the number of ticks has elapsed. This is a blocking delay.
+ *
+ * @param ticks The number of ticks to wait.
+ */
+void os_cputime_delay_ticks(uint32_t ticks);
+
+/**
+ * os cputime delay usecs
+ *
+ * Wait until 'usecs' microseconds has elapsed. This is a blocking delay.
+ *
+ * @param usecs The number of usecs to wait.
+ */
+void os_cputime_delay_usecs(uint32_t usecs);
+
+/**
+ * os cputime timer init
+ *
+ * @param timer The timer to initialize. Cannot be NULL.
+ * @param fp    The timer callback function. Cannot be NULL.
+ * @param arg   Pointer to data object to pass to timer.
+ */
+void os_cputime_timer_init(struct hal_timer *timer, hal_timer_cb fp, void *arg);
+
+/**
+ * os cputime timer start
+ *
+ * Start a cputimer that will expire at 'cputime'. If cputime has already
+ * passed, the timer callback will still be called (at interrupt context).
+ *
+ * NOTE: This must be called when the timer is stopped.
+ *
+ * @param timer     Pointer to timer to start. Cannot be NULL.
+ * @param cputime   The cputime at which the timer should expire.
+ *
+ * @return int 0 on success; EINVAL if timer already started or timer struct
+ *         invalid
+ *
+ */
+int os_cputime_timer_start(struct hal_timer *timer, uint32_t cputime);
+
+/**
+ * os cputimer timer relative
+ *
+ * Sets a cpu timer that will expire 'usecs' microseconds from the current
+ * cputime.
+ *
+ * NOTE: This must be called when the timer is stopped.
+ *
+ * @param timer Pointer to timer. Cannot be NULL.
+ * @param usecs The number of usecs from now at which the timer will expire.
+ *
+ * @return int 0 on success; EINVAL if timer already started or timer struct
+ *         invalid
+ */
+int os_cputime_timer_relative(struct hal_timer *timer, uint32_t usecs);
+
+/**
+ * os cputime timer stop
+ *
+ * Stops a cputimer from running. The timer is removed from the timer queue
+ * and interrupts are disabled if no timers are left on the queue. Can be
+ * called even if timer is not running.
+ *
+ * @param timer Pointer to cputimer to stop. Cannot be NULL.
+ */
+void os_cputime_timer_stop(struct hal_timer *timer);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* H_OS_CPUTIME_ */
diff --git a/porting/common/include/os/os_dev.h b/porting/common/include/os/os_dev.h
new file mode 100644
index 0000000..ed65a08
--- /dev/null
+++ b/porting/common/include/os/os_dev.h
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _OS_DEV_H
+#define _OS_DEV_H
+
+#include <os/os.h>
+
+#include "os/queue.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct os_dev;
+
+/*
+ * Initialization order, defines when a device should be initialized
+ * by the Mynewt kernel.
+ *
+ */
+#define OS_DEV_INIT_PRIMARY   (1)
+#define OS_DEV_INIT_SECONDARY (2)
+#define OS_DEV_INIT_KERNEL    (3)
+
+#define OS_DEV_INIT_F_CRITICAL (1 << 0)
+
+
+#define OS_DEV_INIT_PRIO_DEFAULT (0xff)
+
+/**
+ * Device status, so functions can ensure device is called in a
+ * consistent state.
+ */
+#define OS_DEV_F_STATUS_READY     (1 << 0)
+#define OS_DEV_F_STATUS_OPEN      (1 << 1)
+#define OS_DEV_F_STATUS_SUSPENDED (1 << 2)
+#define OS_DEV_F_INIT_CRITICAL    (1 << 3)
+
+typedef int (*os_dev_init_func_t)(struct os_dev *, void *);
+typedef int (*os_dev_open_func_t)(struct os_dev *, uint32_t,
+        void *);
+typedef int (*os_dev_suspend_func_t)(struct os_dev *, os_time_t, int);
+typedef int (*os_dev_resume_func_t)(struct os_dev *);
+typedef int (*os_dev_close_func_t)(struct os_dev *);
+
+struct os_dev_handlers {
+    os_dev_open_func_t od_open;
+    os_dev_suspend_func_t od_suspend;
+    os_dev_resume_func_t od_resume;
+    os_dev_close_func_t od_close;
+};
+
+/*
+ * Device structure.
+ */
+struct os_dev {
+    struct os_dev_handlers od_handlers;
+    os_dev_init_func_t od_init;
+    void *od_init_arg;
+    uint8_t od_stage;
+    uint8_t od_priority;
+    uint8_t od_open_ref;
+    uint8_t od_flags;
+    char *od_name;
+    STAILQ_ENTRY(os_dev) od_next;
+};
+
+#define OS_DEV_SETHANDLERS(__dev, __open, __close)          \
+    (__dev)->od_handlers.od_open = (__open);                \
+    (__dev)->od_handlers.od_close = (__close);
+
+static inline int
+os_dev_suspend(struct os_dev *dev, os_time_t suspend_t, uint8_t force)
+{
+    if (dev->od_handlers.od_suspend == NULL) {
+        return (0);
+    } else {
+        return (dev->od_handlers.od_suspend(dev, suspend_t, force));
+    }
+}
+
+static inline int
+os_dev_resume(struct os_dev *dev)
+{
+    if (dev->od_handlers.od_resume == NULL) {
+        return (0);
+    } else {
+        return (dev->od_handlers.od_resume(dev));
+    }
+}
+
+int os_dev_create(struct os_dev *dev, char *name, uint8_t stage,
+        uint8_t priority, os_dev_init_func_t od_init, void *arg);
+struct os_dev *os_dev_lookup(char *name);
+int os_dev_initialize_all(uint8_t stage);
+int os_dev_suspend_all(os_time_t, uint8_t);
+int os_dev_resume_all(void);
+struct os_dev *os_dev_open(char *devname, uint32_t timo, void *arg);
+int os_dev_close(struct os_dev *dev);
+void os_dev_reset(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_DEV_H */
diff --git a/porting/common/include/os/os_error.h b/porting/common/include/os/os_error.h
new file mode 100644
index 0000000..01df389
--- /dev/null
+++ b/porting/common/include/os/os_error.h
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_OS_ERROR_
+#define H_OS_ERROR_
+
+#include "syscfg/syscfg.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* OS error enumerations */
+enum os_error {
+    OS_OK = 0,
+    OS_ENOMEM = 1,
+    OS_EINVAL = 2,
+    OS_INVALID_PARM = 3,
+    OS_MEM_NOT_ALIGNED = 4,
+    OS_BAD_MUTEX = 5,
+    OS_TIMEOUT = 6,
+    OS_ERR_IN_ISR = 7,      /* Function cannot be called from ISR */
+    OS_ERR_PRIV = 8,        /* Privileged access error */
+    OS_NOT_STARTED = 9,     /* OS must be started to call this function, but isn't */
+    OS_ENOENT = 10,         /* No such thing */
+    OS_EBUSY = 11,          /* Resource busy */
+    OS_ERROR = 12,          /* Generic Error */
+};
+
+typedef enum os_error os_error_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/porting/common/include/os/os_eventq.h b/porting/common/include/os/os_eventq.h
new file mode 100644
index 0000000..b0c3abd
--- /dev/null
+++ b/porting/common/include/os/os_eventq.h
@@ -0,0 +1,68 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _OS_EVENTQ_H
+#define _OS_EVENTQ_H
+
+#include <inttypes.h>
+#include "os/os_time.h"
+#include "os/queue.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct os_event;
+typedef void os_event_fn(struct os_event *ev);
+
+struct os_event {
+    uint8_t ev_queued;
+    os_event_fn *ev_cb;
+    void *ev_arg;
+    STAILQ_ENTRY(os_event) ev_next;
+};
+
+#define OS_EVENT_QUEUED(__ev) ((__ev)->ev_queued)
+
+struct os_eventq {
+    struct os_task *evq_owner;  /* owner task */
+    struct os_task *evq_task;   /* sleeper; must be either NULL, or the owner */
+    STAILQ_HEAD(, os_event) evq_list;
+};
+
+void os_eventq_init(struct os_eventq *);
+int os_eventq_inited(const struct os_eventq *evq);
+void os_eventq_put(struct os_eventq *, struct os_event *);
+struct os_event *os_eventq_get_no_wait(struct os_eventq *evq);
+struct os_event *os_eventq_get(struct os_eventq *);
+void os_eventq_run(struct os_eventq *evq);
+struct os_event *os_eventq_poll(struct os_eventq **, int, os_time_t);
+void os_eventq_remove(struct os_eventq *, struct os_event *);
+struct os_eventq *os_eventq_dflt_get(void);
+
+/* [DEPRECATED] */
+void os_eventq_designate(struct os_eventq **dst, struct os_eventq *val,
+                         struct os_event *start_ev);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_EVENTQ_H */
+
diff --git a/porting/common/include/os/os_fault.h b/porting/common/include/os/os_fault.h
new file mode 100644
index 0000000..4ce34c2
--- /dev/null
+++ b/porting/common/include/os/os_fault.h
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _OS_FAULT_H
+#define _OS_FAULT_H
+
+#ifdef __cplusplus
+extern "c" {
+#endif
+
+void __assert_func(const char *, int, const char *, const char *)
+    __attribute((noreturn));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_FAULT_H */
diff --git a/porting/common/include/os/os_heap.h b/porting/common/include/os/os_heap.h
new file mode 100644
index 0000000..4413568
--- /dev/null
+++ b/porting/common/include/os/os_heap.h
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_OS_HEAP_
+#define H_OS_HEAP_
+
+#include <stddef.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void *os_malloc(size_t size);
+void os_free(void *mem);
+void *os_realloc(void *ptr, size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/porting/common/include/os/os_malloc.h b/porting/common/include/os/os_malloc.h
new file mode 100644
index 0000000..32b72c2
--- /dev/null
+++ b/porting/common/include/os/os_malloc.h
@@ -0,0 +1,42 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_OS_MALLOC_
+#define H_OS_MALLOC_
+
+#include "os/os_heap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#undef  malloc
+#define malloc  os_malloc
+
+#undef  free
+#define free    os_free
+
+#undef  realloc
+#define realloc  os_realloc
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/porting/common/include/os/os_mbuf.h b/porting/common/include/os/os_mbuf.h
new file mode 100644
index 0000000..314a2eb
--- /dev/null
+++ b/porting/common/include/os/os_mbuf.h
@@ -0,0 +1,305 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _OS_MBUF_H
+#define _OS_MBUF_H
+
+#include "os/queue.h"
+#include "os/os_eventq.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * A mbuf pool from which to allocate mbufs. This contains a pointer to the os
+ * mempool to allocate mbufs out of, the total number of elements in the pool,
+ * and the amount of "user" data in a non-packet header mbuf. The total pool
+ * size, in bytes, should be:
+ *  os_mbuf_count * (omp_databuf_len + sizeof(struct os_mbuf))
+ */
+struct os_mbuf_pool {
+    /**
+     * Total length of the databuf in each mbuf.  This is the size of the
+     * mempool block, minus the mbuf header
+     */
+    uint16_t omp_databuf_len;
+    /**
+     * Total number of memblock's allocated in this mempool.
+     */
+    uint16_t omp_mbuf_count;
+    /**
+     * The memory pool which to allocate mbufs out of
+     */
+    struct os_mempool *omp_pool;
+
+    /**
+     * Link to the next mbuf pool for system memory pools.
+     */
+    STAILQ_ENTRY(os_mbuf_pool) omp_next;
+};
+
+
+/**
+ * A packet header structure that preceeds the mbuf packet headers.
+ */
+struct os_mbuf_pkthdr {
+    /**
+     * Overall length of the packet.
+     */
+    uint16_t omp_len;
+    /**
+     * Flags
+     */
+    uint16_t omp_flags;
+    /**
+     * Next packet in the mbuf chain.
+     */
+    STAILQ_ENTRY(os_mbuf_pkthdr) omp_next;
+};
+
+/**
+ * Chained memory buffer.
+ */
+struct os_mbuf {
+    /**
+     * Current pointer to data in the structure
+     */
+    uint8_t *om_data;
+    /**
+     * Flags associated with this buffer, see OS_MBUF_F_* defintions
+     */
+    uint8_t om_flags;
+    /**
+     * Length of packet header
+     */
+    uint8_t om_pkthdr_len;
+    /**
+     * Length of data in this buffer
+     */
+    uint16_t om_len;
+
+    /**
+     * The mbuf pool this mbuf was allocated out of
+     */
+    struct os_mbuf_pool *om_omp;
+
+    /**
+     * Pointer to next entry in the chained memory buffer
+     */
+    SLIST_ENTRY(os_mbuf) om_next;
+
+    /**
+     * Pointer to the beginning of the data, after this buffer
+     */
+    uint8_t om_databuf[0];
+};
+
+struct os_mqueue {
+    STAILQ_HEAD(, os_mbuf_pkthdr) mq_head;
+    struct os_event mq_ev;
+};
+
+/*
+ * Given a flag number, provide the mask for it
+ *
+ * @param __n The number of the flag in the mask
+ */
+#define OS_MBUF_F_MASK(__n) (1 << (__n))
+
+/*
+ * Checks whether a given mbuf is a packet header mbuf
+ *
+ * @param __om The mbuf to check
+ */
+#define OS_MBUF_IS_PKTHDR(__om) \
+    ((__om)->om_pkthdr_len >= sizeof (struct os_mbuf_pkthdr))
+
+/* Get a packet header pointer given an mbuf pointer */
+#define OS_MBUF_PKTHDR(__om) ((struct os_mbuf_pkthdr *)     \
+    ((uint8_t *)&(__om)->om_data + sizeof(struct os_mbuf)))
+
+/* Given a mbuf packet header pointer, return a pointer to the mbuf */
+#define OS_MBUF_PKTHDR_TO_MBUF(__hdr)   \
+     (struct os_mbuf *)((uint8_t *)(__hdr) - sizeof(struct os_mbuf))
+
+/**
+ * Gets the length of an entire mbuf chain.  The specified mbuf must have a
+ * packet header.
+ */
+#define OS_MBUF_PKTLEN(__om) (OS_MBUF_PKTHDR(__om)->omp_len)
+
+/*
+ * Access the data of a mbuf, and cast it to type
+ *
+ * @param __om The mbuf to access, and cast
+ * @param __type The type to cast it to
+ */
+#define OS_MBUF_DATA(__om, __type) \
+     (__type) ((__om)->om_data)
+
+/**
+ * Access the "user header" in the head of an mbuf chain.
+ *
+ * @param om                    Pointer to the head of an mbuf chain.
+ */
+#define OS_MBUF_USRHDR(om)                              \
+    (void *)((uint8_t *)om + sizeof (struct os_mbuf) +  \
+             sizeof (struct os_mbuf_pkthdr))
+
+/**
+ * Retrieves the length of the user header in an mbuf.
+ *
+ * @param om                    Pointer to the mbuf to query.
+ */
+#define OS_MBUF_USRHDR_LEN(om) \
+    ((om)->om_pkthdr_len - sizeof (struct os_mbuf_pkthdr))
+
+/*
+ * Called by OS_MBUF_LEADINGSPACE() macro
+ */
+static inline uint16_t
+_os_mbuf_leadingspace(struct os_mbuf *om)
+{
+    uint16_t startoff;
+    uint16_t leadingspace;
+
+    startoff = 0;
+    if (OS_MBUF_IS_PKTHDR(om)) {
+        startoff = om->om_pkthdr_len;
+    }
+
+    leadingspace = (uint16_t) (OS_MBUF_DATA(om, uint8_t *) -
+        ((uint8_t *) &om->om_databuf[0] + startoff));
+
+    return (leadingspace);
+}
+
+/**
+ * Returns the leading space (space at the beginning) of the mbuf.
+ * Works on both packet header, and regular mbufs, as it accounts
+ * for the additional space allocated to the packet header.
+ *
+ * @param __omp Is the mbuf pool (which contains packet header length.)
+ * @param __om  Is the mbuf in that pool to get the leadingspace for
+ *
+ * @return Amount of leading space available in the mbuf
+ */
+#define OS_MBUF_LEADINGSPACE(__om) _os_mbuf_leadingspace(__om)
+
+/* Called by OS_MBUF_TRAILINGSPACE() macro. */
+static inline uint16_t
+_os_mbuf_trailingspace(struct os_mbuf *om)
+{
+    struct os_mbuf_pool *omp;
+
+    omp = om->om_omp;
+
+    return (&om->om_databuf[0] + omp->omp_databuf_len) -
+      (om->om_data + om->om_len);
+}
+
+/**
+ * Returns the trailing space (space at the end) of the mbuf.
+ * Works on both packet header and regular mbufs.
+ *
+ * @param __omp The mbuf pool for this mbuf
+ * @param __om  Is the mbuf in that pool to get trailing space for
+ *
+ * @return The amount of trailing space available in the mbuf
+ */
+#define OS_MBUF_TRAILINGSPACE(__om) _os_mbuf_trailingspace(__om)
+
+/* Mbuf queue functions */
+
+/* Initialize a mbuf queue */
+int os_mqueue_init(struct os_mqueue *mq, os_event_fn *ev_cb, void *arg);
+
+/* Get an element from a mbuf queue */
+struct os_mbuf *os_mqueue_get(struct os_mqueue *);
+
+/* Put an element in a mbuf queue */
+int os_mqueue_put(struct os_mqueue *, struct os_eventq *, struct os_mbuf *);
+
+/* Register an mbuf pool with the system pool registry */
+int os_msys_register(struct os_mbuf_pool *);
+
+/* Return a mbuf from the system pool, given an indicative mbuf size */
+struct os_mbuf *os_msys_get(uint16_t dsize, uint16_t leadingspace);
+
+/* De-registers all mbuf pools from msys. */
+void os_msys_reset(void);
+
+/* Return a packet header mbuf from the system pool */
+struct os_mbuf *os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len);
+
+int os_msys_count(void);
+int os_msys_num_free(void);
+
+/* Initialize a mbuf pool */
+int os_mbuf_pool_init(struct os_mbuf_pool *, struct os_mempool *mp,
+        uint16_t, uint16_t);
+
+/* Allocate a new mbuf out of the os_mbuf_pool */
+struct os_mbuf *os_mbuf_get(struct os_mbuf_pool *omp, uint16_t);
+
+/* Allocate a new packet header mbuf out of the os_mbuf_pool */
+struct os_mbuf *os_mbuf_get_pkthdr(struct os_mbuf_pool *omp,
+        uint8_t pkthdr_len);
+
+/* Duplicate a mbuf from the pool */
+struct os_mbuf *os_mbuf_dup(struct os_mbuf *m);
+
+struct os_mbuf *os_mbuf_off(const struct os_mbuf *om, int off,
+                            uint16_t *out_off);
+
+/* Copy data from an mbuf to a flat buffer. */
+int os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst);
+
+/* Append data onto a mbuf */
+int os_mbuf_append(struct os_mbuf *m, const void *, uint16_t);
+
+int os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src,
+                       uint16_t src_off, uint16_t len);
+
+/* Free a mbuf */
+int os_mbuf_free(struct os_mbuf *mb);
+
+/* Free a mbuf chain */
+int os_mbuf_free_chain(struct os_mbuf *om);
+
+void os_mbuf_adj(struct os_mbuf *mp, int req_len);
+int os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len);
+int os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1,
+                 const struct os_mbuf *om2, uint16_t offset2,
+                 uint16_t len);
+
+struct os_mbuf *os_mbuf_prepend(struct os_mbuf *om, int len);
+struct os_mbuf *os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len);
+int os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len);
+void os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second);
+void *os_mbuf_extend(struct os_mbuf *om, uint16_t len);
+struct os_mbuf *os_mbuf_pullup(struct os_mbuf *om, uint16_t len);
+struct os_mbuf *os_mbuf_trim_front(struct os_mbuf *om);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_MBUF_H */ 
diff --git a/porting/common/include/os/os_mempool.h b/porting/common/include/os/os_mempool.h
new file mode 100644
index 0000000..0f5cca9
--- /dev/null
+++ b/porting/common/include/os/os_mempool.h
@@ -0,0 +1,108 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _OS_MEMPOOL_H_
+#define _OS_MEMPOOL_H_
+
+#include <stdbool.h>
+#include "os/os.h"
+#include "os/queue.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * A memory block structure. This simply contains a pointer to the free list
+ * chain and is only used when the block is on the free list. When the block
+ * has been removed from the free list the entire memory block is usable by the
+ * caller.
+ */
+struct os_memblock {
+    SLIST_ENTRY(os_memblock) mb_next;
+};
+
+/* XXX: Change this structure so that we keep the first address in the pool? */
+/* XXX: add memory debug structure and associated code */
+/* XXX: Change how I coded the SLIST_HEAD here. It should be named:
+   SLIST_HEAD(,os_memblock) mp_head; */
+
+/* Memory pool */
+struct os_mempool {
+    int mp_block_size;          /* Size of the memory blocks, in bytes. */
+    int mp_num_blocks;          /* The number of memory blocks. */
+    int mp_num_free;            /* The number of free blocks left */
+    int mp_min_free;            /* The lowest number of free blocks seen */
+    uint32_t mp_membuf_addr;    /* Address of memory buffer used by pool */
+    STAILQ_ENTRY(os_mempool) mp_list;
+    SLIST_HEAD(,os_memblock);   /* Pointer to list of free blocks */
+    char *name;                 /* Name for memory block */
+};
+
+#define OS_MEMPOOL_INFO_NAME_LEN (32)
+
+struct os_mempool_info {
+    int omi_block_size;
+    int omi_num_blocks;
+    int omi_num_free;
+    int omi_min_free;
+    char omi_name[OS_MEMPOOL_INFO_NAME_LEN];
+};
+
+struct os_mempool *os_mempool_info_get_next(struct os_mempool *,
+        struct os_mempool_info *);
+
+/*
+ * To calculate size of the memory buffer needed for the pool. NOTE: This size
+ * is NOT in bytes! The size is the number of os_membuf_t elements required for
+ * the memory pool.
+ */
+#if (OS_CFG_ALIGNMENT == OS_CFG_ALIGN_4)
+#define OS_MEMPOOL_SIZE(n,blksize)      ((((blksize) + 3) / 4) * (n))
+typedef uint32_t os_membuf_t;
+#else
+#define OS_MEMPOOL_SIZE(n,blksize)      ((((blksize) + 7) / 8) * (n))
+typedef uint64_t os_membuf_t;
+#endif
+
+/** Calculates the number of bytes required to initialize a memory pool. */
+#define OS_MEMPOOL_BYTES(n,blksize)     \
+    (sizeof (os_membuf_t) * OS_MEMPOOL_SIZE((n), (blksize)))
+
+/* Initialize a memory pool */
+os_error_t os_mempool_init(struct os_mempool *mp, int blocks, int block_size,
+                           void *membuf, char *name);
+
+/* Performs an integrity check of the specified mempool. */
+bool os_mempool_is_sane(const struct os_mempool *mp);
+
+/* Checks if a memory block was allocated from the specified mempool. */
+int os_memblock_from(const struct os_mempool *mp, const void *block_addr);
+
+/* Get a memory block from the pool */
+void *os_memblock_get(struct os_mempool *mp);
+
+/* Put the memory block back into the pool */
+os_error_t os_memblock_put(struct os_mempool *mp, void *block_addr);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* _OS_MEMPOOL_H_ */
diff --git a/porting/common/include/os/os_mutex.h b/porting/common/include/os/os_mutex.h
new file mode 100644
index 0000000..2964edb
--- /dev/null
+++ b/porting/common/include/os/os_mutex.h
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _OS_MUTEX_H_
+#define _OS_MUTEX_H_
+
+#include "os/os.h"
+#include "os/queue.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct os_mutex
+{
+    SLIST_HEAD(, os_task) mu_head;  /* chain of waiting tasks */
+    uint8_t     _pad;
+    uint8_t     mu_prio;            /* owner's default priority*/
+    uint16_t    mu_level;           /* call nesting level */
+    struct os_task *mu_owner;       /* owners task */
+};
+
+/* 
+  XXX: NOTES
+    -> Should we add a magic number or flag to the mutex structure so
+    that we know that this is a mutex? We can use it for double checking
+    that a proper mutex was passed in to the API.
+    -> What debug information should we add to this structure? Who last
+    acquired the mutex? File/line where it was released?
+    -> Should we add a name to the mutex?
+    -> Should we add a "os_mutex_inspect() api?
+*/
+
+/* XXX: api to create
+os_mutex_inspect(); 
+*/ 
+
+/* Initialize a mutex */
+os_error_t os_mutex_init(struct os_mutex *mu);
+
+/* Release a mutex */
+os_error_t os_mutex_release(struct os_mutex *mu);
+
+/* Pend (wait) for a mutex */
+os_error_t os_mutex_pend(struct os_mutex *mu, uint32_t timeout);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* _OS_MUTEX_H_ */
diff --git a/porting/common/include/os/os_sanity.h b/porting/common/include/os/os_sanity.h
new file mode 100644
index 0000000..e74f2f9
--- /dev/null
+++ b/porting/common/include/os/os_sanity.h
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _OS_SANITY_H
+#define _OS_SANITY_H
+
+#include <stdint.h>
+
+#include "os/os_time.h"
+#include "os/queue.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct os_sanity_check;
+typedef int (*os_sanity_check_func_t)(struct os_sanity_check *, void *);
+
+struct os_sanity_check {
+    os_time_t sc_checkin_last;
+    os_time_t sc_checkin_itvl;
+    os_sanity_check_func_t sc_func;
+    void *sc_arg;
+
+    SLIST_ENTRY(os_sanity_check) sc_next;
+
+};
+
+#define OS_SANITY_CHECK_SETFUNC(__sc, __f, __arg, __itvl)  \
+    (__sc)->sc_func = (__f);                               \
+    (__sc)->sc_arg = (__arg);                              \
+    (__sc)->sc_checkin_itvl = (__itvl) * OS_TICKS_PER_SEC;
+
+int os_sanity_init(void);
+void os_sanity_run(void);
+
+struct os_task;
+int os_sanity_task_checkin(struct os_task *);
+
+int os_sanity_check_init(struct os_sanity_check *);
+int os_sanity_check_register(struct os_sanity_check *);
+int os_sanity_check_reset(struct os_sanity_check *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_SANITY_H */
diff --git a/porting/common/include/os/os_sched.h b/porting/common/include/os/os_sched.h
new file mode 100644
index 0000000..be6b7fd
--- /dev/null
+++ b/porting/common/include/os/os_sched.h
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _OS_SCHED_H
+#define _OS_SCHED_H
+
+#include "os/os_task.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct os_task;
+
+TAILQ_HEAD(os_task_list, os_task);
+
+extern struct os_task *g_current_task;
+extern struct os_task_list g_os_run_list;
+extern struct os_task_list g_os_sleep_list;
+
+void os_sched_ctx_sw_hook(struct os_task *);
+struct os_task *os_sched_get_current_task(void);
+void os_sched_set_current_task(struct os_task *);
+struct os_task *os_sched_next_task(void);
+void os_sched(struct os_task *);
+void os_sched_os_timer_exp(void);
+os_error_t os_sched_insert(struct os_task *);
+int os_sched_sleep(struct os_task *, os_time_t nticks);
+int os_sched_wakeup(struct os_task *);
+int os_sched_remove(struct os_task *);
+void os_sched_resort(struct os_task *);
+os_time_t os_sched_wakeup_ticks(os_time_t now);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_SCHED_H */
diff --git a/porting/common/include/os/os_sem.h b/porting/common/include/os/os_sem.h
new file mode 100644
index 0000000..d5451ab
--- /dev/null
+++ b/porting/common/include/os/os_sem.h
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _OS_SEM_H_
+#define _OS_SEM_H_
+
+#include "os/queue.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct os_sem
+{
+    SLIST_HEAD(, os_task) sem_head;     /* chain of waiting tasks */
+    uint16_t    _pad;
+    uint16_t    sem_tokens;             /* # of tokens */
+};
+
+/* 
+  XXX: NOTES
+    -> Should we add a magic number or flag to the semaphore structure so
+    that we know that this is a semaphore? We can use it for double checking
+    that a proper semaphore was passed in to the API.
+    -> What debug information should we add to this structure? Who last
+    acquired the semaphore? File/line where it was released?
+    -> Should we add a name to the semaphore?
+    -> Should we add a "os_sem_inspect() api, like ucos?
+*/ 
+
+/* Create a semaphore */
+os_error_t os_sem_init(struct os_sem *sem, uint16_t tokens);
+
+/* Release a semaphore */
+os_error_t os_sem_release(struct os_sem *sem);
+
+/* Pend (wait) for a semaphore */
+os_error_t os_sem_pend(struct os_sem *sem, uint32_t timeout);
+
+/* Get current semaphore's count */
+static inline uint16_t os_sem_get_count(struct os_sem *sem)
+{
+    return sem->sem_tokens;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* _OS_SEM_H_ */
diff --git a/porting/common/include/os/os_task.h b/porting/common/include/os/os_task.h
new file mode 100644
index 0000000..a9e420f
--- /dev/null
+++ b/porting/common/include/os/os_task.h
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef _OS_TASK_H
+#define _OS_TASK_H
+
+#include "os/os.h"
+#include "os/os_sanity.h"
+#include "os/queue.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The highest and lowest task priorities */
+#define OS_TASK_PRI_HIGHEST (0)
+#define OS_TASK_PRI_LOWEST  (0xff)
+
+/*
+ * Generic "object" structure. All objects that a task can wait on must
+ * have a SLIST_HEAD(, os_task) head_name as the first element in the object
+ * structure. The element 'head_name' can be any name. See os_mutex.h or
+ * os_sem.h for an example.
+ */
+struct os_task_obj {
+    SLIST_HEAD(, os_task) obj_head;     /* chain of waiting tasks */
+};
+
+/* Task states */
+typedef enum os_task_state {
+    OS_TASK_READY = 1,
+    OS_TASK_SLEEP = 2,
+} os_task_state_t;
+
+/* Task flags */
+#define OS_TASK_FLAG_NO_TIMEOUT     (0x01U)
+#define OS_TASK_FLAG_SEM_WAIT       (0x02U)
+#define OS_TASK_FLAG_MUTEX_WAIT     (0x04U)
+#define OS_TASK_FLAG_EVQ_WAIT       (0x08U)
+
+typedef void (*os_task_func_t)(void *);
+
+#define OS_TASK_MAX_NAME_LEN (32)
+
+struct os_task {
+    os_stack_t *t_stackptr;
+    os_stack_t *t_stacktop;
+
+    uint16_t t_stacksize;
+    uint8_t t_taskid;
+    uint8_t t_prio;
+
+    uint8_t t_state;
+    uint8_t t_flags;
+    uint8_t t_lockcnt;
+    uint8_t t_pad;
+
+    const char *t_name;
+    os_task_func_t t_func;
+    void *t_arg;
+
+    void *t_obj;
+
+    struct os_sanity_check t_sanity_check;
+
+    os_time_t t_next_wakeup;
+    os_time_t t_run_time;
+    uint32_t t_ctx_sw_cnt;
+
+    /* Global list of all tasks, irrespective of run or sleep lists */
+    STAILQ_ENTRY(os_task) t_os_task_list;
+
+    /* Used to chain task to either the run or sleep list */
+    TAILQ_ENTRY(os_task) t_os_list;
+
+    /* Used to chain task to an object such as a semaphore or mutex */
+    SLIST_ENTRY(os_task) t_obj_list;
+};
+
+STAILQ_HEAD(os_task_stailq, os_task);
+
+extern struct os_task_stailq g_os_task_list;
+
+int os_task_init(struct os_task *, const char *, os_task_func_t, void *,
+        uint8_t, os_time_t, os_stack_t *, uint16_t);
+
+int os_task_remove(struct os_task *t);
+
+uint8_t os_task_count(void);
+
+struct os_task_info {
+    uint8_t oti_prio;
+    uint8_t oti_taskid;
+    uint8_t oti_state;
+    uint16_t oti_stkusage;
+    uint16_t oti_stksize;
+    uint32_t oti_cswcnt;
+    uint32_t oti_runtime;
+    os_time_t oti_last_checkin;
+    os_time_t oti_next_checkin;
+
+    char oti_name[OS_TASK_MAX_NAME_LEN];
+};
+
+struct os_task *os_task_info_get_next(const struct os_task *,
+        struct os_task_info *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_TASK_H */
diff --git a/porting/common/include/os/os_test.h b/porting/common/include/os/os_test.h
new file mode 100644
index 0000000..b71d608
--- /dev/null
+++ b/porting/common/include/os/os_test.h
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_OS_TEST_
+#define H_OS_TEST_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int os_test_all(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/porting/common/include/os/os_time.h b/porting/common/include/os/os_time.h
new file mode 100644
index 0000000..2fa07e9
--- /dev/null
+++ b/porting/common/include/os/os_time.h
@@ -0,0 +1,120 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/*-
+ * Copyright (c) 1982, 1986, 1993
+ *      The Regents of the University of California.  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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *      @(#)time.h      8.5 (Berkeley) 5/4/95
+ * $FreeBSD$
+ */
+
+#ifndef _OS_TIME_H
+#define _OS_TIME_H
+
+#include <stdbool.h>
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef UINT32_MAX
+#define UINT32_MAX  0xFFFFFFFFU
+#endif
+
+typedef uint32_t os_time_t;
+typedef int32_t os_stime_t;
+#define OS_TIME_MAX UINT32_MAX
+ 
+/* Used to wait forever for events and mutexs */
+#define OS_TIMEOUT_NEVER    (UINT32_MAX)
+
+os_time_t os_time_get(void);
+void os_time_advance(int ticks);
+void os_time_delay(int32_t osticks);
+
+#define OS_TIME_TICK_LT(__t1, __t2) ((os_stime_t) ((__t1) - (__t2)) < 0)
+#define OS_TIME_TICK_GT(__t1, __t2) ((os_stime_t) ((__t1) - (__t2)) > 0)
+#define OS_TIME_TICK_GEQ(__t1, __t2) ((os_stime_t) ((__t1) - (__t2)) >= 0)
+
+struct os_timeval {
+    int64_t tv_sec;         /* seconds since Jan 1 1970 */
+    int32_t tv_usec;        /* microseconds within the second */
+};
+
+struct os_timezone {
+    int16_t tz_minuteswest;     /* with respect to GMT */
+    int16_t tz_dsttime;         /* daylight savings time correction (if any) */
+};
+
+#define os_timeradd(tvp, uvp, vvp)                                      \
+        do {                                                            \
+                (vvp)->tv_sec = (tvp)->tv_sec + (uvp)->tv_sec;          \
+                (vvp)->tv_usec = (tvp)->tv_usec + (uvp)->tv_usec;       \
+                if ((vvp)->tv_usec >= 1000000) {                        \
+                        (vvp)->tv_sec++;                                \
+                        (vvp)->tv_usec -= 1000000;                      \
+                }                                                       \
+        } while (0)
+
+#define os_timersub(tvp, uvp, vvp)                                      \
+        do {                                                            \
+                (vvp)->tv_sec = (tvp)->tv_sec - (uvp)->tv_sec;          \
+                (vvp)->tv_usec = (tvp)->tv_usec - (uvp)->tv_usec;       \
+                if ((vvp)->tv_usec < 0) {                               \
+                        (vvp)->tv_sec--;                                \
+                        (vvp)->tv_usec += 1000000;                      \
+                }                                                       \
+        } while (0)
+
+int os_settimeofday(struct os_timeval *utctime, struct os_timezone *tz);
+int os_gettimeofday(struct os_timeval *utctime, struct os_timezone *tz);
+int64_t os_get_uptime_usec(void);
+int os_time_ms_to_ticks(uint32_t ms, uint32_t *out_ticks);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _OS_TIME_H */
diff --git a/porting/common/include/os/os_trace_api.h b/porting/common/include/os/os_trace_api.h
new file mode 100644
index 0000000..e01ff20
--- /dev/null
+++ b/porting/common/include/os/os_trace_api.h
@@ -0,0 +1,84 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef OS_TRACE_API_H
+#define OS_TRACE_API_H
+
+#include <stdint.h>
+
+#include "syscfg/syscfg.h"
+#include "os/os.h"
+
+#define OS_TRACE_ID_OFFSET                    (32u)
+
+#define OS_TRACE_ID_EVQ_PUT                   (1u + OS_TRACE_ID_OFFSET)
+#define OS_TRACE_ID_EVQ_GET                   (2u + OS_TRACE_ID_OFFSET)
+#define OS_TRACE_ID_MUTEX_INIT                (3u + OS_TRACE_ID_OFFSET)
+#define OS_TRACE_ID_MUTEX_RELEASE             (4u + OS_TRACE_ID_OFFSET)
+#define OS_TRACE_ID_MUTEX_PEND                (5u + OS_TRACE_ID_OFFSET)
+
+#if MYNEWT_VAL(OS_SYSVIEW)
+void os_trace_enter_isr(void);
+void os_trace_exit_isr(void);
+void os_trace_exit_isr_to_scheduler(void);
+void os_trace_task_info(const struct os_task *p_task);
+void os_trace_task_create(uint32_t task_id);
+void os_trace_task_start_exec(uint32_t task_id);
+void os_trace_task_stop_exec(void);
+void os_trace_task_start_ready(uint32_t task_id);
+void os_trace_task_stop_ready(uint32_t task_id, unsigned reason);
+void os_trace_idle(void);
+
+void os_trace_void(unsigned id);
+void os_trace_u32(unsigned id, uint32_t para0);
+void os_trace_u32x2(unsigned id, uint32_t para0, uint32_t para1);
+void os_trace_u32x3(unsigned id, uint32_t para0, uint32_t para1, uint32_t para2);
+void os_trace_u32x4(unsigned id, uint32_t para0, uint32_t para1, uint32_t para2, uint32_t para3);
+void os_trace_u32x5(unsigned id, uint32_t para0, uint32_t para1, uint32_t para2, uint32_t para3, uint32_t para4);
+void os_trace_enter_timer(uint32_t timer_id);
+void os_trace_exit_timer(void);
+
+void os_trace_end_call(unsigned id);
+void os_trace_end_call_return_value(unsigned id, uint32_t return_value);
+
+#else
+
+static inline void os_trace_enter_isr(void){}
+static inline void os_trace_exit_isr(void){}
+static inline void os_trace_exit_isr_to_scheduler(void){}
+static inline void os_trace_task_info(const struct os_task *p_task){}
+static inline void os_trace_task_create(uint32_t task_id){}
+static inline void os_trace_task_start_exec(uint32_t task_id){}
+static inline void os_trace_task_stop_exec(void){}
+static inline void os_trace_task_start_ready(uint32_t task_id){}
+static inline void os_trace_task_stop_ready(uint32_t task_id, unsigned reason){}
+static inline void os_trace_idle(void){}
+static inline void os_trace_void(unsigned id){}
+static inline void os_trace_u32(unsigned id, uint32_t para0){}
+static inline void os_trace_u32x2(unsigned id, uint32_t para0, uint32_t para1){}
+static inline void os_trace_u32x3(unsigned id, uint32_t para0, uint32_t para1, uint32_t para2){}
+static inline void os_trace_u32x4(unsigned id, uint32_t para0, uint32_t para1, uint32_t para2, uint32_t para3){}
+static inline void os_trace_u32x5(unsigned id, uint32_t para0, uint32_t para1, uint32_t para2, uint32_t para3, uint32_t para4){}
+static inline void os_trace_enter_timer(uint32_t timer_id){}
+static inline void os_trace_exit_timer(void){}
+static inline void os_trace_end_call(unsigned id){}
+static inline void os_trace_end_call_return_value(unsigned id, uint32_t return_value){}
+#endif
+
+#endif
diff --git a/porting/common/include/os/queue.h b/porting/common/include/os/queue.h
new file mode 100755
index 0000000..faffd85
--- /dev/null
+++ b/porting/common/include/os/queue.h
@@ -0,0 +1,522 @@
+/*
+ * Copyright (c) 1991, 1993
+ *	The Regents of the University of California.  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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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.
+ *
+ *	@(#)queue.h	8.5 (Berkeley) 8/20/94
+ * $FreeBSD: src/sys/sys/queue.h,v 1.32.2.7 2002/04/17 14:21:02 des Exp $
+ */
+
+#ifndef _QUEUE_H_
+#define	_QUEUE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists, tail queues, and circular queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction.  Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ *                      SLIST   LIST    STAILQ  TAILQ   CIRCLEQ
+ * _HEAD                +       +       +       +       +
+ * _HEAD_INITIALIZER    +       +       +       +       +
+ * _ENTRY               +       +       +       +       +
+ * _INIT                +       +       +       +       +
+ * _EMPTY               +       +       +       +       +
+ * _FIRST               +       +       +       +       +
+ * _NEXT                +       +       +       +       +
+ * _PREV                -       -       -       +       +
+ * _LAST                -       -       +       +       +
+ * _FOREACH             +       +       +       +       +
+ * _FOREACH_REVERSE     -       -       -       +       +
+ * _INSERT_HEAD         +       +       +       +       +
+ * _INSERT_BEFORE       -       +       -       +       +
+ * _INSERT_AFTER        +       +       +       +       +
+ * _INSERT_TAIL         -       -       +       +       +
+ * _REMOVE_HEAD         +       -       +       -       -
+ * _REMOVE              +       +       +       +       +
+ *
+ */
+
+/*
+ * Singly-linked List declarations.
+ */
+#define	SLIST_HEAD(name, type)                          \
+struct name {                                           \
+    struct type *slh_first;	/* first element */         \
+}
+
+#define	SLIST_HEAD_INITIALIZER(head)                    \
+    { NULL }
+ 
+#define	SLIST_ENTRY(type)                               \
+struct {                                                \
+    struct type *sle_next;  /* next element */          \
+}
+ 
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_EMPTY(head)   ((head)->slh_first == NULL)
+
+#define SLIST_FIRST(head)   ((head)->slh_first)
+
+#define SLIST_FOREACH(var, head, field)                 \
+    for ((var) = SLIST_FIRST((head));                   \
+        (var);                                          \
+        (var) = SLIST_NEXT((var), field))
+
+#define SLIST_INIT(head) do {                           \
+        SLIST_FIRST((head)) = NULL;                     \
+} while (0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do {           \
+    SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);   \
+    SLIST_NEXT((slistelm), field) = (elm);                      \
+} while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do {            \
+    SLIST_NEXT((elm), field) = SLIST_FIRST((head));         \
+    SLIST_FIRST((head)) = (elm);                            \
+} while (0)
+
+#define SLIST_NEXT(elm, field)	((elm)->field.sle_next)
+
+#define SLIST_REMOVE(head, elm, type, field) do {           \
+    if (SLIST_FIRST((head)) == (elm)) {                     \
+        SLIST_REMOVE_HEAD((head), field);                   \
+    }                                                       \
+    else {                                                  \
+        struct type *curelm = SLIST_FIRST((head));          \
+        while (SLIST_NEXT(curelm, field) != (elm))          \
+            curelm = SLIST_NEXT(curelm, field);             \
+        SLIST_NEXT(curelm, field) =                         \
+            SLIST_NEXT(SLIST_NEXT(curelm, field), field);   \
+    }                                                       \
+} while (0)
+
+#define SLIST_REMOVE_HEAD(head, field) do {                         \
+    SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);   \
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define	STAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *stqh_first;/* first element */			\
+	struct type **stqh_last;/* addr of last next element */		\
+}
+
+#define	STAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).stqh_first }
+
+#define	STAILQ_ENTRY(type)						\
+struct {								\
+	struct type *stqe_next;	/* next element */			\
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL)
+
+#define	STAILQ_FIRST(head)	((head)->stqh_first)
+
+#define	STAILQ_FOREACH(var, head, field)				\
+	for((var) = STAILQ_FIRST((head));				\
+	   (var);							\
+	   (var) = STAILQ_NEXT((var), field))
+
+#define	STAILQ_INIT(head) do {						\
+	STAILQ_FIRST((head)) = NULL;					\
+	(head)->stqh_last = &STAILQ_FIRST((head));			\
+} while (0)
+
+#define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\
+	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+	STAILQ_NEXT((tqelm), field) = (elm);				\
+} while (0)
+
+#define	STAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+	STAILQ_FIRST((head)) = (elm);					\
+} while (0)
+
+#define	STAILQ_INSERT_TAIL(head, elm, field) do {			\
+	STAILQ_NEXT((elm), field) = NULL;				\
+	*(head)->stqh_last = (elm);					\
+	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\
+} while (0)
+
+#define	STAILQ_LAST(head, type, field)					\
+	(STAILQ_EMPTY(head) ?						\
+		NULL :							\
+	        ((struct type *)					\
+		((char *)((head)->stqh_last) - offsetof(struct type, field))))
+
+#define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next)
+
+#define	STAILQ_REMOVE(head, elm, type, field) do {			\
+	if (STAILQ_FIRST((head)) == (elm)) {				\
+		STAILQ_REMOVE_HEAD(head, field);			\
+	}								\
+	else {								\
+		struct type *curelm = STAILQ_FIRST((head));		\
+		while (STAILQ_NEXT(curelm, field) != (elm))		\
+			curelm = STAILQ_NEXT(curelm, field);		\
+		if ((STAILQ_NEXT(curelm, field) =			\
+		     STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\
+			(head)->stqh_last = &STAILQ_NEXT((curelm), field);\
+	}								\
+} while (0)
+
+#define	STAILQ_REMOVE_HEAD(head, field) do {				\
+	if ((STAILQ_FIRST((head)) =					\
+	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\
+		(head)->stqh_last = &STAILQ_FIRST((head));		\
+} while (0)
+
+#define	STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {			\
+	if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL)	\
+		(head)->stqh_last = &STAILQ_FIRST((head));		\
+} while (0)
+
+#define STAILQ_REMOVE_AFTER(head, elm, field) do {			\
+	if ((STAILQ_NEXT(elm, field) =					\
+	     STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL)	\
+		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\
+} while (0)
+
+/*
+ * List declarations.
+ */
+#define	LIST_HEAD(name, type)						\
+struct name {								\
+	struct type *lh_first;	/* first element */			\
+}
+
+#define	LIST_HEAD_INITIALIZER(head)					\
+	{ NULL }
+
+#define	LIST_ENTRY(type)						\
+struct {								\
+	struct type *le_next;	/* next element */			\
+	struct type **le_prev;	/* address of previous next element */	\
+}
+
+/*
+ * List functions.
+ */
+
+#define	LIST_EMPTY(head)	((head)->lh_first == NULL)
+
+#define	LIST_FIRST(head)	((head)->lh_first)
+
+#define	LIST_FOREACH(var, head, field)					\
+	for ((var) = LIST_FIRST((head));				\
+	    (var);							\
+	    (var) = LIST_NEXT((var), field))
+
+#define	LIST_INIT(head) do {						\
+	LIST_FIRST((head)) = NULL;					\
+} while (0)
+
+#define	LIST_INSERT_AFTER(listelm, elm, field) do {			\
+	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+		LIST_NEXT((listelm), field)->field.le_prev =		\
+		    &LIST_NEXT((elm), field);				\
+	LIST_NEXT((listelm), field) = (elm);				\
+	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\
+} while (0)
+
+#define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.le_prev = (listelm)->field.le_prev;		\
+	LIST_NEXT((elm), field) = (listelm);				\
+	*(listelm)->field.le_prev = (elm);				\
+	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\
+} while (0)
+
+#define	LIST_INSERT_HEAD(head, elm, field) do {				\
+	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\
+		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+	LIST_FIRST((head)) = (elm);					\
+	(elm)->field.le_prev = &LIST_FIRST((head));			\
+} while (0)
+
+#define	LIST_NEXT(elm, field)	((elm)->field.le_next)
+
+#define	LIST_REMOVE(elm, field) do {					\
+	if (LIST_NEXT((elm), field) != NULL)				\
+		LIST_NEXT((elm), field)->field.le_prev = 		\
+		    (elm)->field.le_prev;				\
+	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\
+} while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#define	TAILQ_HEAD(name, type)						\
+struct name {								\
+	struct type *tqh_first;	/* first element */			\
+	struct type **tqh_last;	/* addr of last next element */		\
+}
+
+#define	TAILQ_HEAD_INITIALIZER(head)					\
+	{ NULL, &(head).tqh_first }
+
+#define	TAILQ_ENTRY(type)						\
+struct {								\
+	struct type *tqe_next;	/* next element */			\
+	struct type **tqe_prev;	/* address of previous next element */	\
+}
+
+/*
+ * Tail queue functions.
+ */
+#define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL)
+
+#define	TAILQ_FIRST(head)	((head)->tqh_first)
+
+#define	TAILQ_FOREACH(var, head, field)					\
+	for ((var) = TAILQ_FIRST((head));				\
+	    (var);							\
+	    (var) = TAILQ_NEXT((var), field))
+
+#define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\
+	for ((var) = TAILQ_LAST((head), headname);			\
+	    (var);							\
+	    (var) = TAILQ_PREV((var), headname, field))
+
+#define	TAILQ_INIT(head) do {						\
+	TAILQ_FIRST((head)) = NULL;					\
+	(head)->tqh_last = &TAILQ_FIRST((head));			\
+} while (0)
+
+#define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
+		    &TAILQ_NEXT((elm), field);				\
+	else								\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+	TAILQ_NEXT((listelm), field) = (elm);				\
+	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\
+} while (0)
+
+#define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\
+	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\
+	TAILQ_NEXT((elm), field) = (listelm);				\
+	*(listelm)->field.tqe_prev = (elm);				\
+	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\
+} while (0)
+
+#define	TAILQ_INSERT_HEAD(head, elm, field) do {			\
+	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\
+		TAILQ_FIRST((head))->field.tqe_prev =			\
+		    &TAILQ_NEXT((elm), field);				\
+	else								\
+		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\
+	TAILQ_FIRST((head)) = (elm);					\
+	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\
+} while (0)
+
+#define	TAILQ_INSERT_TAIL(head, elm, field) do {			\
+	TAILQ_NEXT((elm), field) = NULL;				\
+	(elm)->field.tqe_prev = (head)->tqh_last;			\
+	*(head)->tqh_last = (elm);					\
+	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\
+} while (0)
+
+#define	TAILQ_LAST(head, headname)					\
+	(*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define	TAILQ_PREV(elm, headname, field)				\
+	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define	TAILQ_REMOVE(head, elm, field) do {				\
+	if ((TAILQ_NEXT((elm), field)) != NULL)				\
+		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\
+		    (elm)->field.tqe_prev;				\
+	else								\
+		(head)->tqh_last = (elm)->field.tqe_prev;		\
+	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\
+} while (0)
+
+/*
+ * Circular queue declarations.
+ */
+#define	CIRCLEQ_HEAD(name, type)					\
+struct name {								\
+	struct type *cqh_first;		/* first element */		\
+	struct type *cqh_last;		/* last element */		\
+}
+
+#define	CIRCLEQ_HEAD_INITIALIZER(head)					\
+	{ (void *)&(head), (void *)&(head) }
+
+#define	CIRCLEQ_ENTRY(type)						\
+struct {								\
+	struct type *cqe_next;		/* next element */		\
+	struct type *cqe_prev;		/* previous element */		\
+}
+
+/*
+ * Circular queue functions.
+ */
+#define	CIRCLEQ_EMPTY(head)	((head)->cqh_first == (void *)(head))
+
+#define	CIRCLEQ_FIRST(head)	((head)->cqh_first)
+
+#define	CIRCLEQ_FOREACH(var, head, field)				\
+	for ((var) = CIRCLEQ_FIRST((head));				\
+	    (var) != (void *)(head) || ((var) = NULL);			\
+	    (var) = CIRCLEQ_NEXT((var), field))
+
+#define	CIRCLEQ_FOREACH_REVERSE(var, head, field)			\
+	for ((var) = CIRCLEQ_LAST((head));				\
+	    (var) != (void *)(head) || ((var) = NULL);			\
+	    (var) = CIRCLEQ_PREV((var), field))
+
+#define	CIRCLEQ_INIT(head) do {						\
+	CIRCLEQ_FIRST((head)) = (void *)(head);				\
+	CIRCLEQ_LAST((head)) = (void *)(head);				\
+} while (0)
+
+#define	CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do {		\
+	CIRCLEQ_NEXT((elm), field) = CIRCLEQ_NEXT((listelm), field);	\
+	CIRCLEQ_PREV((elm), field) = (listelm);				\
+	if (CIRCLEQ_NEXT((listelm), field) == (void *)(head))		\
+		CIRCLEQ_LAST((head)) = (elm);				\
+	else								\
+		CIRCLEQ_PREV(CIRCLEQ_NEXT((listelm), field), field) = (elm);\
+	CIRCLEQ_NEXT((listelm), field) = (elm);				\
+} while (0)
+
+#define	CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do {		\
+	CIRCLEQ_NEXT((elm), field) = (listelm);				\
+	CIRCLEQ_PREV((elm), field) = CIRCLEQ_PREV((listelm), field);	\
+	if (CIRCLEQ_PREV((listelm), field) == (void *)(head))		\
+		CIRCLEQ_FIRST((head)) = (elm);				\
+	else								\
+		CIRCLEQ_NEXT(CIRCLEQ_PREV((listelm), field), field) = (elm);\
+	CIRCLEQ_PREV((listelm), field) = (elm);				\
+} while (0)
+
+#define	CIRCLEQ_INSERT_HEAD(head, elm, field) do {			\
+	CIRCLEQ_NEXT((elm), field) = CIRCLEQ_FIRST((head));		\
+	CIRCLEQ_PREV((elm), field) = (void *)(head);			\
+	if (CIRCLEQ_LAST((head)) == (void *)(head))			\
+		CIRCLEQ_LAST((head)) = (elm);				\
+	else								\
+		CIRCLEQ_PREV(CIRCLEQ_FIRST((head)), field) = (elm);	\
+	CIRCLEQ_FIRST((head)) = (elm);					\
+} while (0)
+
+#define	CIRCLEQ_INSERT_TAIL(head, elm, field) do {			\
+	CIRCLEQ_NEXT((elm), field) = (void *)(head);			\
+	CIRCLEQ_PREV((elm), field) = CIRCLEQ_LAST((head));		\
+	if (CIRCLEQ_FIRST((head)) == (void *)(head))			\
+		CIRCLEQ_FIRST((head)) = (elm);				\
+	else								\
+		CIRCLEQ_NEXT(CIRCLEQ_LAST((head)), field) = (elm);	\
+	CIRCLEQ_LAST((head)) = (elm);					\
+} while (0)
+
+#define	CIRCLEQ_LAST(head)	((head)->cqh_last)
+
+#define	CIRCLEQ_NEXT(elm,field)	((elm)->field.cqe_next)
+
+#define	CIRCLEQ_PREV(elm,field)	((elm)->field.cqe_prev)
+
+#define	CIRCLEQ_REMOVE(head, elm, field) do {				\
+	if (CIRCLEQ_NEXT((elm), field) == (void *)(head))		\
+		CIRCLEQ_LAST((head)) = CIRCLEQ_PREV((elm), field);	\
+	else								\
+		CIRCLEQ_PREV(CIRCLEQ_NEXT((elm), field), field) =	\
+		    CIRCLEQ_PREV((elm), field);				\
+	if (CIRCLEQ_PREV((elm), field) == (void *)(head))		\
+		CIRCLEQ_FIRST((head)) = CIRCLEQ_NEXT((elm), field);	\
+	else								\
+		CIRCLEQ_NEXT(CIRCLEQ_PREV((elm), field), field) =	\
+		    CIRCLEQ_NEXT((elm), field);				\
+} while (0)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* !_QUEUE_H_ */
diff --git a/porting/common/include/stats/stats.h b/porting/common/include/stats/stats.h
new file mode 100644
index 0000000..ac2a182
--- /dev/null
+++ b/porting/common/include/stats/stats.h
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#ifndef __UTIL_STATS_H__
+#define __UTIL_STATS_H__
+
+#include <stdint.h>
+#include "syscfg/syscfg.h"
+#include "os/queue.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct stats_name_map {
+    uint16_t snm_off;
+    char *snm_name;
+} __attribute__((packed));
+
+struct stats_hdr {
+    char *s_name;
+    uint8_t s_size;
+    uint8_t s_cnt;
+    uint16_t s_pad1;
+#if MYNEWT_VAL(STATS_NAMES)
+    const struct stats_name_map *s_map;
+    int s_map_cnt;
+#endif
+    STAILQ_ENTRY(stats_hdr) s_next;
+};
+
+#define STATS_SECT_DECL(__name)                                         \
+    struct stats_ ## __name
+#define STATS_SECT_END };
+
+#define STATS_SECT_START(__name)                                        \
+    STATS_SECT_DECL(__name) {
+#define STATS_SECT_VAR(__var)
+
+#define STATS_HDR(__sectname)
+
+#define STATS_SECT_ENTRY(__var)
+#define STATS_SECT_ENTRY16(__var)
+#define STATS_SECT_ENTRY32(__var)
+#define STATS_SECT_ENTRY64(__var)
+#define STATS_RESET(__var)
+
+#define STATS_SIZE_INIT_PARMS(__sectvarname, __size) 0, 0
+
+#define STATS_INC(__sectvarname, __var)
+#define STATS_INCN(__sectvarname, __var, __n)
+#define STATS_CLEAR(__sectvarname, __var)
+
+#define STATS_NAME_START(__name)
+#define STATS_NAME(__name, __entry)
+#define STATS_NAME_END(__name)
+#define STATS_NAME_INIT_PARMS(__name) NULL, 0
+
+#define stats_init(...) 0
+#define stats_register(name, shdr) 0
+#define stats_init_and_reg(...) 0
+#define stats_reset(shdr)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __UTIL_STATS_H__ */
diff --git a/porting/common/include/sysinit/sysinit.h b/porting/common/include/sysinit/sysinit.h
new file mode 100644
index 0000000..7694c42
--- /dev/null
+++ b/porting/common/include/sysinit/sysinit.h
@@ -0,0 +1,128 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_SYSINIT_
+#define H_SYSINIT_
+
+#include <inttypes.h>
+#include <assert.h>
+#include "syscfg/syscfg.h"
+
+#if MYNEWT_VAL(SPLIT_APPLICATION)
+#include "split/split.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern uint8_t sysinit_active;
+
+void sysinit_start(void);
+void sysinit_end(void);
+
+typedef void sysinit_panic_fn(const char *file, int line, const char *func,
+                              const char *expr, const char *msg);
+
+extern sysinit_panic_fn *sysinit_panic_cb;
+
+void sysinit_panic_set(sysinit_panic_fn *panic_fn);
+
+#if MYNEWT_VAL(SYSINIT_PANIC_MESSAGE)
+
+#if MYNEWT_VAL(SYSINIT_PANIC_FILE_LINE)
+#define SYSINIT_PANIC_MSG(msg) sysinit_panic_cb(__FILE__, __LINE__, 0, 0, msg)
+#else
+#define SYSINIT_PANIC_MSG(msg) sysinit_panic_cb(0, 0, 0, 0, msg)
+#endif
+
+#else
+
+#if MYNEWT_VAL(SYSINIT_PANIC_FILE_LINE)
+#define SYSINIT_PANIC_MSG(msg) sysinit_panic_cb(__FILE__, __LINE__, 0, 0, 0)
+#else
+#define SYSINIT_PANIC_MSG(msg) sysinit_panic_cb(0, 0, 0, 0, 0)
+#endif
+
+#endif
+
+#define SYSINIT_PANIC() SYSINIT_PANIC_MSG(NULL)
+
+#define SYSINIT_PANIC_ASSERT_MSG(rc, msg) do \
+{                                            \
+    if (!(rc)) {                             \
+        SYSINIT_PANIC_MSG(msg);              \
+    }                                        \
+} while (0)
+
+#define SYSINIT_PANIC_ASSERT(rc) SYSINIT_PANIC_ASSERT_MSG(rc, NULL)
+
+/**
+ * Asserts that system initialization is in progress.  This macro is used to
+ * ensure packages don't get initialized a second time after system
+ * initialization has completed.
+ */
+#if MYNEWT_VAL(SYSINIT_CONSTRAIN_INIT)
+#define SYSINIT_ASSERT_ACTIVE() assert(sysinit_active)
+#else
+#define SYSINIT_ASSERT_ACTIVE()
+#endif
+
+#if MYNEWT_VAL(SPLIT_LOADER)
+
+/*** System initialization for loader (first stage of split image). */
+void sysinit_loader(void);
+#define sysinit() do                                                        \
+{                                                                           \
+    sysinit_start();                                                        \
+    sysinit_loader();                                                       \
+    sysinit_end();                                                          \
+} while (0)
+
+#elif MYNEWT_VAL(SPLIT_APPLICATION)
+
+/*** System initialization for split-app (second stage of split image). */
+void sysinit_app(void);
+#define sysinit() do                                                        \
+{                                                                           \
+    /* Record that a split app is running; imgmgt needs to know this. */    \
+    split_app_active_set(1);                                                \
+    sysinit_start();                                                        \
+    sysinit_app();                                                          \
+    sysinit_end();                                                          \
+} while (0)
+
+#else
+
+/*** System initialization for a unified image (no split). */
+void sysinit_app(void);
+#define sysinit() do                                                        \
+{                                                                           \
+    sysinit_start();                                                        \
+    sysinit_app();                                                          \
+    sysinit_end();                                                          \
+} while (0)
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/porting/common/src/mem/mem.c b/porting/common/src/mem/mem.c
new file mode 100644
index 0000000..340e60e
--- /dev/null
+++ b/porting/common/src/mem/mem.c
@@ -0,0 +1,245 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "os/os.h"
+#include "mem/mem.h"
+
+/**
+ * Mallocs a block of memory and initializes a mempool to use it.
+ *
+ * @param mempool               The mempool to initialize.
+ * @param num_blocks            The total number of memory blocks in the
+ *                                  mempool.
+ * @param block_size            The size of each mempool entry.
+ * @param name                  The name to give the mempool.
+ * @param out_buf               On success, this points to the malloced memory.
+ *                                  Pass NULL if you don't need this
+ *                                  information.
+ *
+ * @return                      0 on success;
+ *                              OS_ENOMEM on malloc failure;
+ *                              Other OS code on unexpected error.
+ */
+int
+mem_malloc_mempool(struct os_mempool *mempool, int num_blocks, int block_size,
+                   char *name, void **out_buf)
+{
+    void *buf;
+    int rc;
+
+    block_size = OS_ALIGN(block_size, OS_ALIGNMENT);
+
+    if (num_blocks > 0) {
+        buf = malloc(OS_MEMPOOL_BYTES(num_blocks, block_size));
+        if (buf == NULL) {
+            return OS_ENOMEM;
+        }
+    } else {
+        buf = NULL;
+    }
+
+    rc = os_mempool_init(mempool, num_blocks, block_size, buf, name);
+    if (rc != 0) {
+        free(buf);
+        return rc;
+    }
+
+    if (out_buf != NULL) {
+        *out_buf = buf;
+    }
+
+    return 0;
+}
+
+/**
+ * Mallocs a block of memory and initializes an mbuf pool to use it.  The
+ * specified block_size indicates the size of an mbuf acquired from the pool if
+ * it does not contain a pkthdr.
+ *
+ * @param mempool               The mempool to initialize.
+ * @param mbuf_pool             The mbuf pool to initialize.
+ * @param num_blocks            The total number of mbufs in the pool.
+ * @param block_size            The size of each mbuf.
+ * @param name                  The name to give the mempool.
+ * @param out_buf               On success, this points to the malloced memory.
+ *                                  Pass NULL if you don't need this
+ *                                  information.
+ *
+ * @return                      0 on success;
+ *                              OS_ENOMEM on malloc failure;
+ *                              Other OS code on unexpected error.
+ */
+int
+mem_malloc_mbuf_pool(struct os_mempool *mempool,
+                     struct os_mbuf_pool *mbuf_pool, int num_blocks,
+                     int block_size, char *name,
+                     void **out_buf)
+{
+    void *buf;
+    int rc;
+
+    block_size = OS_ALIGN(block_size + sizeof (struct os_mbuf), OS_ALIGNMENT);
+
+    rc = mem_malloc_mempool(mempool, num_blocks, block_size, name, &buf);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = os_mbuf_pool_init(mbuf_pool, mempool, block_size, num_blocks);
+    if (rc != 0) {
+        free(buf);
+        return rc;
+    }
+
+    if (out_buf != NULL) {
+        *out_buf = buf;
+    }
+
+    return 0;
+}
+
+/**
+ * Mallocs a block of memory and initializes an mbuf pool to use it.  The
+ * specified block_size indicates the size of an mbuf acquired from the pool if
+ * it contains a pkthdr.
+ *
+ * @param mempool               The mempool to initialize.
+ * @param mbuf_pool             The mbuf pool to initialize.
+ * @param num_blocks            The total number of mbufs in the pool.
+ * @param block_size            The size of each mbuf.
+ * @param name                  The name to give the mempool.
+ * @param out_buf               On success, this points to the malloced memory.
+ *                                  Pass NULL if you don't need this
+ *                                  information.
+ *
+ * @return                      0 on success;
+ *                              OS_ENOMEM on malloc failure;
+ *                              Other OS code on unexpected error.
+ */
+int
+mem_malloc_mbufpkt_pool(struct os_mempool *mempool,
+                        struct os_mbuf_pool *mbuf_pool, int num_blocks,
+                        int block_size, char *name,
+                        void **out_buf)
+{
+    int rc;
+
+    rc = mem_malloc_mbuf_pool(mempool, mbuf_pool, num_blocks,
+                              block_size + sizeof (struct os_mbuf_pkthdr),
+                              name, out_buf);
+    return rc;
+}
+
+int
+mem_init_mbuf_pool(void *mem, struct os_mempool *mempool,
+                   struct os_mbuf_pool *mbuf_pool, int num_blocks,
+                   int block_size, char *name)
+{
+    int rc;
+
+    rc = os_mempool_init(mempool, num_blocks, block_size, mem, name);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = os_mbuf_pool_init(mbuf_pool, mempool, block_size, num_blocks);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
+
+/*
+ * Splits an appropriately-sized fragment from the front of an mbuf chain, as
+ * neeeded.  If the length of the mbuf chain greater than specified maximum
+ * fragment size, a new mbuf is allocated, and data is moved from the source
+ * mbuf to the new mbuf.  If the mbuf chain is small enough to fit in a single
+ * fragment, the source mbuf itself is returned unmodified, and the suplied
+ * pointer is set to NULL.
+ *
+ * This function is expected to be called in a loop until the entire mbuf chain
+ * has been consumed.  For example:
+ *
+ *     struct os_mbuf *frag;
+ *     struct os_mbuf *rsp;
+ *     // [...]
+ *     while (rsp != NULL) {
+ *         frag = mem_split_frag(&rsp, get_mtu(), frag_alloc, NULL);
+ *         if (frag == NULL) {
+ *             os_mbuf_free_chain(rsp);
+ *             return SYS_ENOMEM;
+ *         }
+ *         send_packet(frag)
+ *     }
+ *
+ * @param om                    The packet to fragment.  Upon fragmentation,
+ *                                  this mbuf is adjusted such that the
+ *                                  fragment data is removed.  If the packet
+ *                                  constitutes a single fragment, this gets
+ *                                  set to NULL on success.
+ * @param max_frag_sz           The maximum payload size of a fragment.
+ *                                  Typically this is the MTU of the
+ *                                  connection.
+ * @param alloc_cb              Points to a function that allocates an mbuf to
+ *                                  hold a fragment.  This function gets called
+ *                                  before the source mbuf chain is modified,
+ *                                  so it can safely inspect it.
+ * @param cb_arg                Generic parameter that gets passed to the
+ *                                  callback function.
+ *
+ * @return                      The next fragment to send on success;
+ *                              NULL on failure.
+ */
+struct os_mbuf *
+mem_split_frag(struct os_mbuf **om, uint16_t max_frag_sz,
+               mem_frag_alloc_fn *alloc_cb, void *cb_arg)
+{
+    struct os_mbuf *frag;
+    int rc;
+
+    if (OS_MBUF_PKTLEN(*om) <= max_frag_sz) {
+        /* Final fragment. */
+        frag = *om;
+        *om = NULL;
+        return frag;
+    }
+
+    /* Packet needs to be split.  Allocate a new buffer for the fragment. */
+    frag = alloc_cb(max_frag_sz, cb_arg);
+    if (frag == NULL) {
+        goto err;
+    }
+
+    /* Move data from the front of the packet into the fragment mbuf. */
+    rc = os_mbuf_appendfrom(frag, *om, 0, max_frag_sz);
+    if (rc != 0) {
+        goto err;
+    }
+    os_mbuf_adj(*om, max_frag_sz);
+
+    /* Free unused portion of of source mbuf chain, if possible. */
+    *om = os_mbuf_trim_front(*om);
+
+    return frag;
+
+err:
+    os_mbuf_free_chain(frag);
+    return NULL;
+}
diff --git a/porting/common/src/nimble_port.c b/porting/common/src/nimble_port.c
new file mode 100644
index 0000000..8f8daa9
--- /dev/null
+++ b/porting/common/src/nimble_port.c
@@ -0,0 +1,65 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <stddef.h>
+#include "os/os.h"
+#include "sysinit/sysinit.h"
+#include "host/ble_hs.h"
+#include "services/gap/ble_svc_gap.h"
+#include "services/gatt/ble_svc_gatt.h"
+#include "services/ans/ble_svc_ans.h"
+#include "services/ias/ble_svc_ias.h"
+#include "services/lls/ble_svc_lls.h"
+#include "services/tps/ble_svc_tps.h"
+#include "controller/ble_ll.h"
+
+void
+nimble_init(void)
+{
+    void os_msys_init(void);
+    void ble_hci_ram_pkg_init(void);
+    void ble_store_ram_init(void);
+
+    sysinit_start();
+    os_msys_init();
+    ble_hci_ram_pkg_init();
+    ble_hs_init();
+    ble_ll_init();
+    ble_svc_gap_init();
+    ble_svc_gatt_init();
+    ble_svc_ans_init();
+    ble_svc_ias_init();
+    ble_svc_lls_init();
+    ble_svc_tps_init();
+    ble_store_ram_init();
+    sysinit_end();
+}
+
+void
+nimble_run(void)
+{
+    while (1) {
+        struct os_event *ev;
+
+        ev = os_eventq_get(os_eventq_dflt_get());
+        assert(ev->ev_cb != NULL);
+
+        ev->ev_cb(ev);
+    }
+}
diff --git a/porting/common/src/os/endian.c b/porting/common/src/os/endian.c
new file mode 100644
index 0000000..1311f43
--- /dev/null
+++ b/porting/common/src/os/endian.c
@@ -0,0 +1,218 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "os/endian.h"
+
+void
+put_le16(void *buf, uint16_t x)
+{
+    uint8_t *u8ptr;
+
+    u8ptr = buf;
+    u8ptr[0] = (uint8_t)x;
+    u8ptr[1] = (uint8_t)(x >> 8);
+}
+
+void
+put_le32(void *buf, uint32_t x)
+{
+    uint8_t *u8ptr;
+
+    u8ptr = buf;
+    u8ptr[0] = (uint8_t)x;
+    u8ptr[1] = (uint8_t)(x >> 8);
+    u8ptr[2] = (uint8_t)(x >> 16);
+    u8ptr[3] = (uint8_t)(x >> 24);
+}
+
+void
+put_le64(void *buf, uint64_t x)
+{
+    uint8_t *u8ptr;
+
+    u8ptr = buf;
+    u8ptr[0] = (uint8_t)x;
+    u8ptr[1] = (uint8_t)(x >> 8);
+    u8ptr[2] = (uint8_t)(x >> 16);
+    u8ptr[3] = (uint8_t)(x >> 24);
+    u8ptr[4] = (uint8_t)(x >> 32);
+    u8ptr[5] = (uint8_t)(x >> 40);
+    u8ptr[6] = (uint8_t)(x >> 48);
+    u8ptr[7] = (uint8_t)(x >> 56);
+}
+
+uint16_t
+get_le16(const void *buf)
+{
+    const uint8_t *u8ptr;
+    uint16_t x;
+
+    u8ptr = buf;
+    x = u8ptr[0];
+    x |= (uint16_t)u8ptr[1] << 8;
+
+    return x;
+}
+
+uint32_t
+get_le32(const void *buf)
+{
+    const uint8_t *u8ptr;
+    uint32_t x;
+
+    u8ptr = buf;
+    x = u8ptr[0];
+    x |= (uint32_t)u8ptr[1] << 8;
+    x |= (uint32_t)u8ptr[2] << 16;
+    x |= (uint32_t)u8ptr[3] << 24;
+
+    return x;
+}
+
+uint64_t
+get_le64(const void *buf)
+{
+    const uint8_t *u8ptr;
+    uint64_t x;
+
+    u8ptr = buf;
+    x = u8ptr[0];
+    x |= (uint64_t)u8ptr[1] << 8;
+    x |= (uint64_t)u8ptr[2] << 16;
+    x |= (uint64_t)u8ptr[3] << 24;
+    x |= (uint64_t)u8ptr[4] << 32;
+    x |= (uint64_t)u8ptr[5] << 40;
+    x |= (uint64_t)u8ptr[6] << 48;
+    x |= (uint64_t)u8ptr[7] << 56;
+
+    return x;
+}
+
+void
+put_be16(void *buf, uint16_t x)
+{
+    uint8_t *u8ptr;
+
+    u8ptr = buf;
+    u8ptr[0] = (uint8_t)(x >> 8);
+    u8ptr[1] = (uint8_t)x;
+}
+
+void
+put_be32(void *buf, uint32_t x)
+{
+    uint8_t *u8ptr;
+
+    u8ptr = buf;
+    u8ptr[0] = (uint8_t)(x >> 24);
+    u8ptr[1] = (uint8_t)(x >> 16);
+    u8ptr[2] = (uint8_t)(x >> 8);
+    u8ptr[3] = (uint8_t)x;
+}
+
+void
+put_be64(void *buf, uint64_t x)
+{
+    uint8_t *u8ptr;
+
+    u8ptr = buf;
+    u8ptr[0] = (uint8_t)(x >> 56);
+    u8ptr[1] = (uint8_t)(x >> 48);
+    u8ptr[2] = (uint8_t)(x >> 40);
+    u8ptr[3] = (uint8_t)(x >> 32);
+    u8ptr[4] = (uint8_t)(x >> 24);
+    u8ptr[5] = (uint8_t)(x >> 16);
+    u8ptr[6] = (uint8_t)(x >> 8);
+    u8ptr[7] = (uint8_t)x;
+}
+
+uint16_t
+get_be16(const void *buf)
+{
+    const uint8_t *u8ptr;
+    uint16_t x;
+
+    u8ptr = buf;
+    x = (uint16_t)u8ptr[0] << 8;
+    x |= u8ptr[1];
+
+    return x;
+}
+
+uint32_t
+get_be32(const void *buf)
+{
+    const uint8_t *u8ptr;
+    uint32_t x;
+
+    u8ptr = buf;
+    x = (uint32_t)u8ptr[0] << 24;
+    x |= (uint32_t)u8ptr[1] << 16;
+    x |= (uint32_t)u8ptr[2] << 8;
+    x |= u8ptr[3];
+
+    return x;
+}
+
+uint64_t
+get_be64(const void *buf)
+{
+    const uint8_t *u8ptr;
+    uint64_t x;
+
+    u8ptr = buf;
+    x = (uint64_t)u8ptr[0] << 56;
+    x |= (uint64_t)u8ptr[1] << 48;
+    x |= (uint64_t)u8ptr[2] << 40;
+    x |= (uint64_t)u8ptr[3] << 32;
+    x |= (uint64_t)u8ptr[4] << 24;
+    x |= (uint64_t)u8ptr[5] << 16;
+    x |= (uint64_t)u8ptr[6] << 8;
+    x |= u8ptr[7];
+
+    return x;
+}
+void
+swap_in_place(void *buf, int len)
+{
+    uint8_t *u8ptr;
+    uint8_t tmp;
+    int i;
+    int j;
+
+    u8ptr = buf;
+
+    for (i = 0, j = len - 1; i < j; i++, j--) {
+        tmp = u8ptr[i];
+
+        u8ptr[i] = u8ptr[j];
+        u8ptr[j] = tmp;
+    }
+}
+
+/* swap octets */
+void
+swap_buf(uint8_t *dst, const uint8_t *src, int len)
+{
+    int i;
+
+    for (i = 0; i < len; i++) {
+        dst[len - 1 - i] = src[i];
+    }
+}
diff --git a/porting/common/src/os/os.c b/porting/common/src/os/os.c
new file mode 100644
index 0000000..b8ec3ff
--- /dev/null
+++ b/porting/common/src/os/os.c
@@ -0,0 +1,240 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "sysinit/sysinit.h"
+#include "os/os.h"
+#include "os/queue.h"
+#include "os/os_dev.h"
+#include "os/os_trace_api.h"
+#include "hal/hal_os_tick.h"
+#include "hal/hal_bsp.h"
+#include "hal/hal_watchdog.h"
+
+#include <assert.h>
+#include "../os/os_priv.h"
+
+/**
+ * @defgroup OSKernel Operating System Kernel
+ * @brief This section contains documentation for the core operating system kernel
+ * of Apache Mynewt.
+ * @{
+ *   @addtogroup OSGeneral General Functions
+ *   @{
+ */
+
+struct os_task g_idle_task;
+os_stack_t g_idle_task_stack[OS_STACK_ALIGN(OS_IDLE_STACK_SIZE)];
+
+uint32_t g_os_idle_ctr;
+
+static struct os_task os_main_task;
+static os_stack_t os_main_stack[OS_STACK_ALIGN(OS_MAIN_STACK_SIZE)];
+
+/* Default zero.  Set by the architecture specific code when os is started.
+ */
+int g_os_started;
+
+#ifdef ARCH_sim
+#define MIN_IDLE_TICKS  1
+#else
+#define MIN_IDLE_TICKS  (100 * OS_TICKS_PER_SEC / 1000) /* 100 msec */
+#endif
+#define MAX_IDLE_TICKS  (600 * OS_TICKS_PER_SEC)        /* 10 minutes */
+
+
+/**
+ * Idle operating system task, runs when no other tasks are running.
+ * The idle task operates in tickless mode, which means it looks for
+ * the next time an event in the system needs to run, and then tells
+ * the architecture specific functions to sleep until that time.
+ *
+ * @param arg unused
+ */
+void
+os_idle_task(void *arg)
+{
+    os_sr_t sr;
+    os_time_t now;
+    os_time_t iticks, sticks, cticks;
+    os_time_t sanity_last;
+    os_time_t sanity_itvl_ticks;
+
+    sanity_itvl_ticks = (MYNEWT_VAL(SANITY_INTERVAL) * OS_TICKS_PER_SEC) / 1000;
+    sanity_last = 0;
+
+    hal_watchdog_tickle();
+
+    while (1) {
+        ++g_os_idle_ctr;
+
+        now = os_time_get();
+        if (OS_TIME_TICK_GT(now, sanity_last + sanity_itvl_ticks)) {
+            os_sanity_run();
+            /* Tickle the watchdog after successfully running sanity */
+            hal_watchdog_tickle();
+            sanity_last = now;
+        }
+
+        OS_ENTER_CRITICAL(sr);
+        now = os_time_get();
+        sticks = os_sched_wakeup_ticks(now);
+        cticks = os_callout_wakeup_ticks(now);
+        iticks = min(sticks, cticks);
+        /* Wakeup in time to run sanity as well from the idle context,
+         * as the idle task does not schedule itself.
+         */
+        iticks = min(iticks, ((sanity_last + sanity_itvl_ticks) - now));
+
+        if (iticks < MIN_IDLE_TICKS) {
+            iticks = 0;
+        } else if (iticks > MAX_IDLE_TICKS) {
+            iticks = MAX_IDLE_TICKS;
+        } else {
+            /* NOTHING */
+        }
+        /* Tell the architecture specific support to put the processor to sleep
+         * for 'n' ticks.
+         */
+
+        os_trace_idle();
+        os_tick_idle(iticks);
+        OS_EXIT_CRITICAL(sr);
+    }
+}
+
+/**
+ * Has the operating system started.
+ *
+ * @return 1 if the operating system has started, 0 if it hasn't
+ */
+int
+os_started(void)
+{
+    return (g_os_started);
+}
+
+static void
+os_main(void *arg)
+{
+    int (*fn)(int argc, char **argv) = arg;
+
+#if !MYNEWT_VAL(SELFTEST)
+    fn(0, NULL);
+#else
+    (void)fn;
+    while (1) {
+        os_eventq_run(os_eventq_dflt_get());
+    }
+#endif
+    assert(0);
+}
+
+void
+os_init_idle_task(void)
+{
+    int rc;
+
+    rc = os_task_init(&g_idle_task, "idle", os_idle_task, NULL,
+            OS_IDLE_PRIO, OS_WAIT_FOREVER, g_idle_task_stack,
+            OS_STACK_ALIGN(OS_IDLE_STACK_SIZE));
+    assert(rc == 0);
+
+    /* Initialize sanity */
+    rc = os_sanity_init();
+    assert(rc == 0);
+
+    assert(MYNEWT_VAL(WATCHDOG_INTERVAL) - 200 > MYNEWT_VAL(SANITY_INTERVAL));
+
+    rc = hal_watchdog_init(MYNEWT_VAL(WATCHDOG_INTERVAL));
+    assert(rc == 0);
+}
+
+/**
+ * Initialize the operating system, calls into the architecture specific
+ * support to initialize the operating system.
+ */
+void
+os_init(int (*main_fn)(int argc, char **arg))
+{
+    os_error_t err;
+
+    TAILQ_INIT(&g_callout_list);
+    STAILQ_INIT(&g_os_task_list);
+    os_eventq_init(os_eventq_dflt_get());
+
+    /* Initialize device list. */
+    os_dev_reset();
+
+    err = os_arch_os_init();
+    assert(err == OS_OK);
+
+    if (main_fn) {
+        err = os_task_init(&os_main_task, "main", os_main, main_fn,
+                           OS_MAIN_TASK_PRIO, OS_WAIT_FOREVER, os_main_stack,
+                           OS_STACK_ALIGN(OS_MAIN_STACK_SIZE));
+        assert(err == 0);
+    }
+    /* Call bsp related OS initializations */
+    hal_bsp_init();
+
+    err = (os_error_t) os_dev_initialize_all(OS_DEV_INIT_PRIMARY);
+    assert(err == OS_OK);
+
+    err = (os_error_t) os_dev_initialize_all(OS_DEV_INIT_SECONDARY);
+    assert(err == OS_OK);
+}
+
+/**
+ * Start the operating system, calls into the architecture specific support
+ * to start the operating system.
+ */
+void
+os_start(void)
+{
+#if MYNEWT_VAL(OS_SCHEDULING)
+    os_error_t err;
+
+    /* Enable the watchdog prior to starting the OS */
+    hal_watchdog_enable();
+
+    err = os_arch_os_start();
+    assert(err == OS_OK);
+#else
+    assert(0);
+#endif
+}
+
+void
+os_pkg_init(void)
+{
+    os_error_t err;
+
+    /* Ensure this function only gets called by sysinit. */
+    SYSINIT_ASSERT_ACTIVE();
+
+    err = os_dev_initialize_all(OS_DEV_INIT_KERNEL);
+    assert(err == OS_OK);
+
+    os_msys_init();
+}
+
+/**
+ *   }@ General OS functions
+ * }@ OS Kernel
+ */
diff --git a/porting/common/src/os/os_callout.c b/porting/common/src/os/os_callout.c
new file mode 100644
index 0000000..e8deeab
--- /dev/null
+++ b/porting/common/src/os/os_callout.c
@@ -0,0 +1,230 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "../os/os_priv.h"
+#include "os/os.h"
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSCallouts Event Timers (Callouts)
+ *   @{
+ */
+struct os_callout_list g_callout_list;
+
+/**
+ * Initialize a callout.
+ *
+ * Callouts are used to schedule events in the future onto a task's event
+ * queue.  Callout timers are scheduled using the os_callout_reset()
+ * function.  When the timer expires, an event is posted to the event
+ * queue specified in os_callout_init().  The event argument given here
+ * is posted in the ev_arg field of that event.
+ *
+ * @param c The callout to initialize
+ * @param evq The event queue to post an OS_EVENT_T_TIMER event to
+ * @param timo_func The function to call on this callout for the host task
+ *                  used to provide multiple timer events to a task
+ *                  (this can be NULL.)
+ * @param ev_arg The argument to provide to the event when posting the
+ *               timer.
+ */
+void os_callout_init(struct os_callout *c, struct os_eventq *evq,
+                     os_event_fn *ev_cb, void *ev_arg)
+{
+    memset(c, 0, sizeof(*c));
+    c->c_ev.ev_cb = ev_cb;
+    c->c_ev.ev_arg = ev_arg;
+    c->c_evq = evq;
+}
+
+/**
+ * Stop the callout from firing off, any pending events will be cleared.
+ *
+ * @param c The callout to stop
+ */
+void
+os_callout_stop(struct os_callout *c)
+{
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+
+    if (os_callout_queued(c)) {
+        TAILQ_REMOVE(&g_callout_list, c, c_next);
+        c->c_next.tqe_prev = NULL;
+    }
+
+    if (c->c_evq) {
+        os_eventq_remove(c->c_evq, &c->c_ev);
+    }
+
+    OS_EXIT_CRITICAL(sr);
+}
+
+/**
+ * Reset the callout to fire off in 'ticks' ticks.
+ *
+ * @param c The callout to reset
+ * @param ticks The number of ticks to wait before posting an event
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+os_callout_reset(struct os_callout *c, int32_t ticks)
+{
+    struct os_callout *entry;
+    os_sr_t sr;
+    int rc;
+
+    if (ticks < 0) {
+        rc = OS_EINVAL;
+        goto err;
+    }
+
+    OS_ENTER_CRITICAL(sr);
+
+    os_callout_stop(c);
+
+    if (ticks == 0) {
+        ticks = 1;
+    }
+
+    c->c_ticks = os_time_get() + ticks;
+
+    entry = NULL;
+    TAILQ_FOREACH(entry, &g_callout_list, c_next) {
+        if (OS_TIME_TICK_LT(c->c_ticks, entry->c_ticks)) {
+            break;
+        }
+    }
+
+    if (entry) {
+        TAILQ_INSERT_BEFORE(entry, c, c_next);
+    } else {
+        TAILQ_INSERT_TAIL(&g_callout_list, c, c_next);
+    }
+
+    OS_EXIT_CRITICAL(sr);
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * This function is called by the OS in the time tick.  It searches the list
+ * of callouts, and sees if any of them are ready to run.  If they are ready
+ * to run, it posts an event for each callout that's ready to run,
+ * to the event queue provided to os_callout_init().
+ */
+void
+os_callout_tick(void)
+{
+    os_sr_t sr;
+    struct os_callout *c;
+    uint32_t now;
+
+    now = os_time_get();
+
+    while (1) {
+        OS_ENTER_CRITICAL(sr);
+        c = TAILQ_FIRST(&g_callout_list);
+        if (c) {
+            if (OS_TIME_TICK_GEQ(now, c->c_ticks)) {
+                TAILQ_REMOVE(&g_callout_list, c, c_next);
+                c->c_next.tqe_prev = NULL;
+            } else {
+                c = NULL;
+            }
+        }
+        OS_EXIT_CRITICAL(sr);
+
+        if (c) {
+            if (c->c_evq) {
+                os_eventq_put(c->c_evq, &c->c_ev);
+            } else {
+                c->c_ev.ev_cb(&c->c_ev);
+            }
+        } else {
+            break;
+        }
+    }
+}
+
+/*
+ * Returns the number of ticks to the first pending callout. If there are no
+ * pending callouts then return OS_TIMEOUT_NEVER instead.
+ *
+ * @param now The time now
+ *
+ * @return Number of ticks to first pending callout
+ */
+os_time_t
+os_callout_wakeup_ticks(os_time_t now)
+{
+    os_time_t rt;
+    struct os_callout *c;
+
+    OS_ASSERT_CRITICAL();
+
+    c = TAILQ_FIRST(&g_callout_list);
+    if (c != NULL) {
+        if (OS_TIME_TICK_GEQ(c->c_ticks, now)) {
+            rt = c->c_ticks - now;
+        } else {
+            rt = 0;     /* callout time is in the past */
+        }
+    } else {
+        rt = OS_TIMEOUT_NEVER;
+    }
+
+    return (rt);
+}
+
+/*
+ * Returns the number of ticks which remains to callout..
+ *
+ * @param c callout
+ * @param now The time now
+ *
+ * @return Number of ticks to first pending callout
+ */
+os_time_t os_callout_remaining_ticks(struct os_callout *c, os_time_t now)
+{
+    os_time_t rt;
+
+    OS_ASSERT_CRITICAL();
+
+    if (OS_TIME_TICK_GEQ(c->c_ticks, now)) {
+        rt = c->c_ticks - now;
+    } else {
+        rt = 0;     /* callout time is in the past */
+    }
+
+    return rt;
+}
+
+/**
+ *   @} Callout Timers
+ * @} OS Kernel
+ */
diff --git a/porting/common/src/os/os_cputime.c b/porting/common/src/os/os_cputime.c
new file mode 100644
index 0000000..19b0b82
--- /dev/null
+++ b/porting/common/src/os/os_cputime.c
@@ -0,0 +1,215 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <string.h>
+#include <stdint.h>
+#include <assert.h>
+#include "os/os.h"
+#include "os/os_cputime.h"
+
+/**
+ * @addtogroup OSKernel Operating System Kernel
+ * @{
+ *   @defgroup OSCPUTime High Resolution Timers
+ *   @{
+ */
+
+#if defined(OS_CPUTIME_FREQ_HIGH)
+struct os_cputime_data g_os_cputime;
+#endif
+
+/**
+ * os cputime init
+ *
+ * Initialize the cputime module. This must be called after os_init is called
+ * and before any other timer API are used. This should be called only once
+ * and should be called before the hardware timer is used.
+ *
+ * @param clock_freq The desired cputime frequency, in hertz (Hz).
+ *
+ * @return int 0 on success; -1 on error.
+ */
+int
+os_cputime_init(uint32_t clock_freq)
+{
+    int rc;
+
+    /* Set the ticks per microsecond. */
+#if defined(OS_CPUTIME_FREQ_HIGH)
+    g_os_cputime.ticks_per_usec = clock_freq / 1000000U;
+#endif
+    rc = hal_timer_config(MYNEWT_VAL(OS_CPUTIME_TIMER_NUM), clock_freq);
+    return rc;
+}
+
+/**
+ * os cputime delay ticks
+ *
+ * Wait until the number of ticks has elapsed. This is a blocking delay.
+ *
+ * @param ticks The number of ticks to wait.
+ */
+void
+os_cputime_delay_ticks(uint32_t ticks)
+{
+    uint32_t until;
+
+    until = os_cputime_get32() + ticks;
+    while ((int32_t)(os_cputime_get32() - until) < 0) {
+        /* Loop here till finished */
+    }
+}
+
+#if !defined(OS_CPUTIME_FREQ_PWR2)
+/**
+ * os cputime delay nsecs
+ *
+ * Wait until 'nsecs' nanoseconds has elapsed. This is a blocking delay.
+ *
+ * @param nsecs The number of nanoseconds to wait.
+ */
+void
+os_cputime_delay_nsecs(uint32_t nsecs)
+{
+    uint32_t ticks;
+
+    ticks = os_cputime_nsecs_to_ticks(nsecs);
+    os_cputime_delay_ticks(ticks);
+}
+#endif
+
+/**
+ * os cputime delay usecs
+ *
+ * Wait until 'usecs' microseconds has elapsed. This is a blocking delay.
+ *
+ * @param usecs The number of usecs to wait.
+ */
+void
+os_cputime_delay_usecs(uint32_t usecs)
+{
+    uint32_t ticks;
+
+    ticks = os_cputime_usecs_to_ticks(usecs);
+    os_cputime_delay_ticks(ticks);
+}
+
+/**
+ * os cputime timer init
+ *
+ * @param timer The timer to initialize. Cannot be NULL.
+ * @param fp    The timer callback function. Cannot be NULL.
+ * @param arg   Pointer to data object to pass to timer.
+ */
+void
+os_cputime_timer_init(struct hal_timer *timer, hal_timer_cb fp, void *arg)
+{
+    assert(timer != NULL);
+    assert(fp != NULL);
+
+    hal_timer_set_cb(MYNEWT_VAL(OS_CPUTIME_TIMER_NUM), timer, fp, arg);
+}
+
+/**
+ * os cputime timer start
+ *
+ * Start a cputimer that will expire at 'cputime'. If cputime has already
+ * passed, the timer callback will still be called (at interrupt context).
+ *
+ * NOTE: This must be called when the timer is stopped.
+ *
+ * @param timer     Pointer to timer to start. Cannot be NULL.
+ * @param cputime   The cputime at which the timer should expire.
+ *
+ * @return int 0 on success; EINVAL if timer already started or timer struct
+ *         invalid
+ *
+ */
+int
+os_cputime_timer_start(struct hal_timer *timer, uint32_t cputime)
+{
+    int rc;
+
+    rc = hal_timer_start_at(timer, cputime);
+    return rc;
+}
+
+/**
+ * os cputimer timer relative
+ *
+ * Sets a cpu timer that will expire 'usecs' microseconds from the current
+ * cputime.
+ *
+ * NOTE: This must be called when the timer is stopped.
+ *
+ * @param timer Pointer to timer. Cannot be NULL.
+ * @param usecs The number of usecs from now at which the timer will expire.
+ *
+ * @return int 0 on success; EINVAL if timer already started or timer struct
+ *         invalid
+ */
+int
+os_cputime_timer_relative(struct hal_timer *timer, uint32_t usecs)
+{
+    int rc;
+    uint32_t cputime;
+
+    assert(timer != NULL);
+
+    cputime = os_cputime_get32() + os_cputime_usecs_to_ticks(usecs);
+    rc = hal_timer_start_at(timer, cputime);
+
+    return rc;
+}
+
+/**
+ * os cputime timer stop
+ *
+ * Stops a cputimer from running. The timer is removed from the timer queue
+ * and interrupts are disabled if no timers are left on the queue. Can be
+ * called even if timer is not running.
+ *
+ * @param timer Pointer to cputimer to stop. Cannot be NULL.
+ */
+void
+os_cputime_timer_stop(struct hal_timer *timer)
+{
+    hal_timer_stop(timer);
+}
+
+/**
+ * os cputime get32
+ *
+ * Returns current value of cputime.
+ *
+ * @return uint32_t cputime
+ */
+uint32_t
+os_cputime_get32(void)
+{
+    uint32_t cpu_time;
+
+    cpu_time = hal_timer_read(MYNEWT_VAL(OS_CPUTIME_TIMER_NUM));
+    return cpu_time;
+}
+
+/**
+ *   @} OSCPUTime
+ * @} OSKernel
+ */
diff --git a/porting/common/src/os/os_cputime_1mhz.c b/porting/common/src/os/os_cputime_1mhz.c
new file mode 100644
index 0000000..4e76968
--- /dev/null
+++ b/porting/common/src/os/os_cputime_1mhz.c
@@ -0,0 +1,52 @@
+#include "os/os_cputime.h"
+
+/**
+ * This module implements cputime functionality for timers whose frequency is
+ * exactly 1 MHz.
+ */
+
+#if defined(OS_CPUTIME_FREQ_1MHZ)
+
+/**
+ * @addtogroup OSKernel Operating System Kernel
+ * @{
+ *   @defgroup OSCPUTime High Resolution Timers
+ *   @{
+ */
+
+/**
+ * os cputime nsecs to ticks
+ *
+ * Converts the given number of nanoseconds into cputime ticks.
+ *
+ * @param usecs The number of nanoseconds to convert to ticks
+ *
+ * @return uint32_t The number of ticks corresponding to 'nsecs'
+ */
+uint32_t
+os_cputime_nsecs_to_ticks(uint32_t nsecs)
+{
+    return (nsecs + 999) / 1000;
+}
+
+/**
+ * os cputime ticks to nsecs
+ *
+ * Convert the given number of ticks into nanoseconds.
+ *
+ * @param ticks The number of ticks to convert to nanoseconds.
+ *
+ * @return uint32_t The number of nanoseconds corresponding to 'ticks'
+ */
+uint32_t
+os_cputime_ticks_to_nsecs(uint32_t ticks)
+{
+    return ticks * 1000;
+}
+
+/**
+ *   @} OSCPUTime
+ * @} OSKernel
+ */
+
+#endif
diff --git a/porting/common/src/os/os_cputime_high.c b/porting/common/src/os/os_cputime_high.c
new file mode 100644
index 0000000..bb71662
--- /dev/null
+++ b/porting/common/src/os/os_cputime_high.c
@@ -0,0 +1,84 @@
+#include "os/os_cputime.h"
+
+/**
+ * This module implements cputime functionality for timers whose frequency is
+ * greater than 1 MHz.
+ */
+
+#if defined(OS_CPUTIME_FREQ_HIGH)
+
+/**
+ * @addtogroup OSKernel Operating System Kernel
+ * @{
+ *   @defgroup OSCPUTime High Resolution Timers
+ *   @{
+ */
+
+/**
+ * os cputime usecs to ticks
+ *
+ * Converts the given number of microseconds into cputime ticks.
+ *
+ * @param usecs The number of microseconds to convert to ticks
+ *
+ * @return uint32_t The number of ticks corresponding to 'usecs'
+ */
+uint32_t
+os_cputime_usecs_to_ticks(uint32_t usecs)
+{
+    return usecs * g_os_cputime.ticks_per_usec;
+}
+
+/**
+ * cputime ticks to usecs
+ *
+ * Convert the given number of ticks into microseconds.
+ *
+ * @param ticks The number of ticks to convert to microseconds.
+ *
+ * @return uint32_t The number of microseconds corresponding to 'ticks'
+ */
+uint32_t
+os_cputime_ticks_to_usecs(uint32_t ticks)
+{
+    return (ticks + g_os_cputime.ticks_per_usec - 1) /
+           g_os_cputime.ticks_per_usec;
+}
+
+/**
+ * os cputime nsecs to ticks
+ *
+ * Converts the given number of nanoseconds into cputime ticks.
+ *
+ * @param usecs The number of nanoseconds to convert to ticks
+ *
+ * @return uint32_t The number of ticks corresponding to 'nsecs'
+ */
+uint32_t
+os_cputime_nsecs_to_ticks(uint32_t nsecs)
+{
+    return (nsecs * g_os_cputime.ticks_per_usec + 999) / 1000;
+}
+
+/**
+ * os cputime ticks to nsecs
+ *
+ * Convert the given number of ticks into nanoseconds.
+ *
+ * @param ticks The number of ticks to convert to nanoseconds.
+ *
+ * @return uint32_t The number of nanoseconds corresponding to 'ticks'
+ */
+uint32_t
+os_cputime_ticks_to_nsecs(uint32_t ticks)
+{
+    return (ticks * 1000 + g_os_cputime.ticks_per_usec - 1) /
+           g_os_cputime.ticks_per_usec;
+}
+
+/**
+ *   @} OSCPUTime
+ * @} OSKernel
+ */
+
+#endif
diff --git a/porting/common/src/os/os_cputime_pwr2.c b/porting/common/src/os/os_cputime_pwr2.c
new file mode 100644
index 0000000..5a05b96
--- /dev/null
+++ b/porting/common/src/os/os_cputime_pwr2.c
@@ -0,0 +1,90 @@
+#include "os/os_cputime.h"
+
+/**
+ * This module implements cputime functionality for timers for which:
+ *     a. freq is a power of 2 Hz, and
+ *     b. 256 Hz <= freq < 1 MHz
+ */
+
+#if defined(OS_CPUTIME_FREQ_PWR2)
+
+/**
+ * @addtogroup OSKernel Operating System Kernel
+ * @{
+ *   @defgroup OSCPUTime High Resolution Timers
+ *   @{
+ */
+
+/**
+ * os cputime usecs to ticks
+ *
+ * Converts the given number of microseconds into cputime ticks.
+ *
+ * @param usecs The number of microseconds to convert to ticks
+ *
+ * @return uint32_t The number of ticks corresponding to 'usecs'
+ */
+uint32_t
+os_cputime_usecs_to_ticks(uint32_t usecs)
+{
+    uint64_t ticks;
+
+    /*
+     * Faster calculation but could be off 1 full tick since we do not
+     * add residual back. Adding back the residual is commented out below, but
+     * shown.
+     */
+    ticks = (1ULL << 32) * MYNEWT_VAL(OS_CPUTIME_FREQ) / 1000000 * usecs;
+
+    /* Residual for 32768 Hz. */
+    //ticks += ((uint64_t)usecs * (1526122139+1)) >> 32;
+
+    return ticks >> 32;
+}
+
+/**
+ * cputime ticks to usecs
+ *
+ * Convert the given number of ticks into microseconds.
+ *
+ * @param ticks The number of ticks to convert to microseconds.
+ *
+ * @return uint32_t The number of microseconds corresponding to 'ticks'
+ *
+ * NOTE: This calculation will overflow if the value for ticks is greater
+ * than 140737488. I am not going to check that here because that many ticks
+ * is about 4222 seconds, way more than what this routine should be used for.
+ */
+uint32_t
+os_cputime_ticks_to_usecs(uint32_t ticks)
+{
+    uint32_t usecs;
+    uint32_t shift;
+    uint32_t freq;
+
+    /* Given: `freq = 2^n`, calculate `n`. */
+    /* Note: this looks like a lot of work, but gcc can optimize it away since
+     * `freq` is known at compile time.
+     */
+    freq = MYNEWT_VAL(OS_CPUTIME_FREQ);
+    shift = 0;
+    while (freq != 0) {
+        freq >>= 1;
+        shift++;
+    }
+
+    if (shift <= 7) {
+        return 0;
+    }
+    shift -= 7;
+
+    usecs = ((ticks >> shift) * 15625) + (((ticks & 0x1ff) * 15625) >> shift);
+    return usecs;
+}
+
+/**
+ *   @} OSCPUTime
+ * @} OSKernel
+ */
+
+#endif
diff --git a/porting/common/src/os/os_dev.c b/porting/common/src/os/os_dev.c
new file mode 100644
index 0000000..07b1c54
--- /dev/null
+++ b/porting/common/src/os/os_dev.c
@@ -0,0 +1,346 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "os/os.h"
+#include "os/queue.h"
+#include "os/os_dev.h"
+
+#include <string.h>
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSDevice Device Framework
+ *   @{
+ */
+
+static STAILQ_HEAD(, os_dev) g_os_dev_list;
+
+static int
+os_dev_init(struct os_dev *dev, char *name, uint8_t stage,
+        uint8_t priority, os_dev_init_func_t od_init, void *arg)
+{
+    dev->od_name = name;
+    dev->od_stage = stage;
+    dev->od_priority = priority;
+    /* assume these are set after the fact. */
+    dev->od_flags = 0;
+    dev->od_open_ref = 0;
+    dev->od_init = od_init;
+    dev->od_init_arg = arg;
+    memset(&dev->od_handlers, 0, sizeof(dev->od_handlers));
+
+    return (0);
+}
+
+/**
+ * Add the device to the device tree.  This is a private function.
+ *
+ * @param dev The device to add to the device tree.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+os_dev_add(struct os_dev *dev)
+{
+    struct os_dev *cur_dev;
+
+    /* If no devices present, insert into head */
+    if (STAILQ_FIRST(&g_os_dev_list) == NULL) {
+        STAILQ_INSERT_HEAD(&g_os_dev_list, dev, od_next);
+        return (0);
+    }
+
+    /* Add devices to the list, sorted first by stage, then by
+     * priority.  Keep sorted in this order for initialization
+     * stage.
+     */
+    cur_dev = NULL;
+    STAILQ_FOREACH(cur_dev, &g_os_dev_list, od_next) {
+        if (cur_dev->od_stage > dev->od_stage) {
+            continue;
+        }
+
+        if (dev->od_priority >= cur_dev->od_priority) {
+            break;
+        }
+    }
+
+    if (cur_dev) {
+        STAILQ_INSERT_AFTER(&g_os_dev_list, cur_dev, dev, od_next);
+    } else {
+        STAILQ_INSERT_TAIL(&g_os_dev_list, dev, od_next);
+    }
+
+    return (0);
+}
+
+/**
+ * Call device initialize routine, and mark it ready. This is a private
+ * function.
+ *
+ * @param dev The device to initialize.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+static int
+os_dev_initialize(struct os_dev *dev)
+{
+    int rc;
+
+    rc = dev->od_init(dev, dev->od_init_arg);
+    if (rc != 0) {
+        if (dev->od_flags & OS_DEV_F_INIT_CRITICAL) {
+            goto err;
+        }
+    } else {
+        dev->od_flags |= OS_DEV_F_STATUS_READY;
+    }
+    return 0;
+err:
+    return rc;
+}
+
+
+/**
+ * Create a new device in the kernel.
+ *
+ * @param dev The device to create.
+ * @param name The name of the device to create.
+ * @param stage The stage to initialize that device to.
+ * @param priority The priority of initializing that device
+ * @param od_init The initialization function to call for this
+ *                device.
+ * @param arg The argument to provide this device initialization
+ *            function.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+os_dev_create(struct os_dev *dev, char *name, uint8_t stage,
+        uint8_t priority, os_dev_init_func_t od_init, void *arg)
+{
+    int rc;
+
+    rc = os_dev_init(dev, name, stage, priority, od_init, arg);
+    if (rc != 0) {
+        goto err;
+    }
+
+    rc = os_dev_add(dev);
+    if (rc != 0) {
+        goto err;
+    }
+
+    if (g_os_started) {
+        rc = os_dev_initialize(dev);
+    }
+err:
+    return (rc);
+}
+
+/**
+ * Initialize all devices for a given state.
+ *
+ * @param stage The stage to initialize.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+os_dev_initialize_all(uint8_t stage)
+{
+    struct os_dev *dev;
+    int rc = 0;
+
+    STAILQ_FOREACH(dev, &g_os_dev_list, od_next) {
+        if (dev->od_stage == stage) {
+            rc = os_dev_initialize(dev);
+            if (rc) {
+                break;
+            }
+        }
+    }
+
+    return (rc);
+}
+
+/**
+ * Suspend all devices.
+ *
+ * @param dev The device to suspend
+ * @param suspend_t The number of ticks to suspend this device for
+ * @param force Whether or not to force suspending the device
+ *
+ * @return 0 on success, or a non-zero error code if one of the devices
+ *                       returned it.
+ */
+int
+os_dev_suspend_all(os_time_t suspend_t, uint8_t force)
+{
+    struct os_dev *dev;
+    int suspend_failure;
+    int rc;
+
+    suspend_failure = 0;
+    STAILQ_FOREACH(dev, &g_os_dev_list, od_next) {
+        rc = os_dev_suspend(dev, suspend_t, force);
+        if (rc != 0) {
+            suspend_failure = OS_ERROR;
+        }
+    }
+
+    return (suspend_failure);
+}
+
+/**
+ * Resume all the devices that were suspended.
+ *
+ * @return 0 on success, -1 if any of the devices have failed to resume.
+ */
+int
+os_dev_resume_all(void)
+{
+    struct os_dev *dev;
+    int rc;
+
+    STAILQ_FOREACH(dev, &g_os_dev_list, od_next) {
+        rc = os_dev_resume(dev);
+        if (rc != 0) {
+            goto err;
+        }
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * Lookup a device by name.
+ *
+ * WARNING: This should be called before any locking on the device is done, or
+ * the device list itself is modified in any context.  There is no locking.
+ *
+ * @param name The name of the device to look up.
+ *
+ * @return A pointer to the device corresponding to name, or NULL if not found.
+ */
+struct os_dev *
+os_dev_lookup(char *name)
+{
+    struct os_dev *dev;
+
+    dev = NULL;
+    STAILQ_FOREACH(dev, &g_os_dev_list, od_next) {
+        if (!strcmp(dev->od_name, name)) {
+            break;
+        }
+    }
+    return (dev);
+}
+
+/**
+ * Open a device.
+ *
+ * @param dev The device to open
+ * @param timo The timeout to open the device, if not specified.
+ * @param arg The argument to the device open() call.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+struct os_dev *
+os_dev_open(char *devname, uint32_t timo, void *arg)
+{
+    struct os_dev *dev;
+    os_sr_t sr;
+    int rc;
+
+    dev = os_dev_lookup(devname);
+    if (dev == NULL) {
+        return (NULL);
+    }
+
+    /* Device is not ready to be opened. */
+    if ((dev->od_flags & OS_DEV_F_STATUS_READY) == 0) {
+        return (NULL);
+    }
+
+    if (dev->od_handlers.od_open) {
+        rc = dev->od_handlers.od_open(dev, timo, arg);
+        if (rc != 0) {
+            goto err;
+        }
+    }
+
+    OS_ENTER_CRITICAL(sr);
+    ++dev->od_open_ref;
+    dev->od_flags |= OS_DEV_F_STATUS_OPEN;
+    OS_EXIT_CRITICAL(sr);
+
+    return (dev);
+err:
+    return (NULL);
+}
+
+/**
+ * Close a device.
+ *
+ * @param dev The device to close
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+os_dev_close(struct os_dev *dev)
+{
+    int rc;
+    os_sr_t sr;
+
+    if (dev->od_handlers.od_close) {
+        rc = dev->od_handlers.od_close(dev);
+        if (rc != 0) {
+            goto err;
+        }
+    }
+
+    OS_ENTER_CRITICAL(sr);
+    if (--dev->od_open_ref == 0) {
+        dev->od_flags &= ~OS_DEV_F_STATUS_OPEN;
+    }
+    OS_EXIT_CRITICAL(sr);
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * Clears the device list.  This function does not close any devices or free
+ * any resources; its purpose is to allow a full system reset between unit
+ * tests.
+ */
+void
+os_dev_reset(void)
+{
+    STAILQ_INIT(&g_os_dev_list);
+}
+
+/**
+ *   @} OSDevice
+ * @} OSKernel
+ */
diff --git a/porting/common/src/os/os_eventq.c b/porting/common/src/os/os_eventq.c
new file mode 100644
index 0000000..b09c81f
--- /dev/null
+++ b/porting/common/src/os/os_eventq.c
@@ -0,0 +1,354 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <string.h>
+#include "os/os_trace_api.h"
+
+#include "os/os.h"
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSEvent Event Queues
+ *   @{
+ */
+
+static struct os_eventq os_eventq_main;
+
+/**
+ * Initialize the event queue
+ *
+ * @param evq The event queue to initialize
+ */
+void
+os_eventq_init(struct os_eventq *evq)
+{
+    memset(evq, 0, sizeof(*evq));
+    STAILQ_INIT(&evq->evq_list);
+}
+
+int
+os_eventq_inited(const struct os_eventq *evq)
+{
+    return evq->evq_list.stqh_last != NULL;
+}
+
+/**
+ * Put an event on the event queue.
+ *
+ * @param evq The event queue to put an event on
+ * @param ev The event to put on the queue
+ */
+void
+os_eventq_put(struct os_eventq *evq, struct os_event *ev)
+{
+    int resched;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+
+    /* Do not queue if already queued */
+    if (OS_EVENT_QUEUED(ev)) {
+        OS_EXIT_CRITICAL(sr);
+        return;
+    }
+
+    os_trace_void(OS_TRACE_ID_EVQ_PUT);
+
+    /* Queue the event */
+    ev->ev_queued = 1;
+    STAILQ_INSERT_TAIL(&evq->evq_list, ev, ev_next);
+
+    resched = 0;
+    if (evq->evq_task) {
+        /* If task waiting on event, wake it up.
+         * Check if task is sleeping, because another event
+         * queue may have woken this task up beforehand.
+         */
+        if (evq->evq_task->t_state == OS_TASK_SLEEP) {
+            os_sched_wakeup(evq->evq_task);
+            resched = 1;
+        }
+        /* Either way, NULL out the task, because the task will
+         * be awake upon exit of this function.
+         */
+        evq->evq_task = NULL;
+    }
+
+    os_trace_end_call(OS_TRACE_ID_EVQ_PUT);
+    OS_EXIT_CRITICAL(sr);
+
+    if (resched) {
+        os_sched(NULL);
+    }
+}
+
+struct os_event *
+os_eventq_get_no_wait(struct os_eventq *evq)
+{
+    struct os_event *ev;
+
+    ev = STAILQ_FIRST(&evq->evq_list);
+    if (ev) {
+        STAILQ_REMOVE(&evq->evq_list, ev, os_event, ev_next);
+        ev->ev_queued = 0;
+    }
+
+    return ev;
+}
+
+/**
+ * Pull a single item from an event queue.  This function blocks until there
+ * is an item on the event queue to read.
+ *
+ * @param evq The event queue to pull an event from
+ *
+ * @return The event from the queue
+ */
+struct os_event *
+os_eventq_get(struct os_eventq *evq)
+{
+    struct os_event *ev;
+    os_sr_t sr;
+    struct os_task *t;
+
+    t = os_sched_get_current_task();
+    if (evq->evq_owner != t) {
+        if (evq->evq_owner == NULL) {
+            evq->evq_owner = t;
+        } else {
+            /*
+             * A task is trying to read from event queue which is handled
+             * by another.
+             */
+            assert(0);
+        }
+    }
+    OS_ENTER_CRITICAL(sr);
+    os_trace_void(OS_TRACE_ID_EVQ_GET);
+pull_one:
+    ev = STAILQ_FIRST(&evq->evq_list);
+    if (ev) {
+        STAILQ_REMOVE(&evq->evq_list, ev, os_event, ev_next);
+        ev->ev_queued = 0;
+        t->t_flags &= ~OS_TASK_FLAG_EVQ_WAIT;
+    } else {
+        evq->evq_task = t;
+        os_sched_sleep(evq->evq_task, OS_TIMEOUT_NEVER);
+        t->t_flags |= OS_TASK_FLAG_EVQ_WAIT;
+        OS_EXIT_CRITICAL(sr);
+
+        os_sched(NULL);
+
+        OS_ENTER_CRITICAL(sr);
+        evq->evq_task = NULL;
+        goto pull_one;
+    }
+    os_trace_end_call(OS_TRACE_ID_EVQ_GET);
+    OS_EXIT_CRITICAL(sr);
+
+    return (ev);
+}
+
+void
+os_eventq_run(struct os_eventq *evq)
+{
+    struct os_event *ev;
+
+    ev = os_eventq_get(evq);
+    assert(ev->ev_cb != NULL);
+
+    ev->ev_cb(ev);
+}
+
+static struct os_event *
+os_eventq_poll_0timo(struct os_eventq **evq, int nevqs)
+{
+    struct os_event *ev;
+    os_sr_t sr;
+    int i;
+
+    ev = NULL;
+
+    OS_ENTER_CRITICAL(sr);
+    for (i = 0; i < nevqs; i++) {
+        ev = STAILQ_FIRST(&evq[i]->evq_list);
+        if (ev) {
+            STAILQ_REMOVE(&evq[i]->evq_list, ev, os_event, ev_next);
+            ev->ev_queued = 0;
+            break;
+        }
+    }
+    OS_EXIT_CRITICAL(sr);
+
+    return ev;
+}
+
+/**
+ * Poll the list of event queues specified by the evq parameter
+ * (size nevqs), and return the "first" event available on any of
+ * the queues.  Event queues are searched in the order that they
+ * are passed in the array.
+ *
+ * @param evq Array of event queues
+ * @param nevqs Number of event queues in evq
+ * @param timo Timeout, forever if OS_WAIT_FOREVER is passed to poll.
+ *
+ * @return An event, or NULL if no events available
+ */
+struct os_event *
+os_eventq_poll(struct os_eventq **evq, int nevqs, os_time_t timo)
+{
+    struct os_event *ev;
+    struct os_task *cur_t;
+    int i, j;
+    os_sr_t sr;
+
+    /* If the timeout is 0, don't involve the scheduler at all.  Grab an event
+     * if one is available, else return immediately.
+     */
+    if (timo == 0) {
+        return os_eventq_poll_0timo(evq, nevqs);
+    }
+
+    ev = NULL;
+
+    OS_ENTER_CRITICAL(sr);
+    cur_t = os_sched_get_current_task();
+
+    for (i = 0; i < nevqs; i++) {
+        ev = STAILQ_FIRST(&evq[i]->evq_list);
+        if (ev) {
+            STAILQ_REMOVE(&evq[i]->evq_list, ev, os_event, ev_next);
+            ev->ev_queued = 0;
+            /* Reset the items that already have an evq task set. */
+            for (j = 0; j < i; j++) {
+                evq[j]->evq_task = NULL;
+            }
+
+            OS_EXIT_CRITICAL(sr);
+            goto has_event;
+        }
+        evq[i]->evq_task = cur_t;
+    }
+
+    cur_t->t_flags |= OS_TASK_FLAG_EVQ_WAIT;
+
+    os_sched_sleep(cur_t, timo);
+    OS_EXIT_CRITICAL(sr);
+
+    os_sched(NULL);
+
+    OS_ENTER_CRITICAL(sr);
+    cur_t->t_flags &= ~OS_TASK_FLAG_EVQ_WAIT;
+    for (i = 0; i < nevqs; i++) {
+        /* Go through the entire loop to clear the evq_task variable,
+         * given this task is no longer sleeping on the event queues.
+         * Return the first event found, so only grab the event if
+         * we haven't found one.
+         */
+        if (!ev) {
+            ev = STAILQ_FIRST(&evq[i]->evq_list);
+            if (ev) {
+                STAILQ_REMOVE(&evq[i]->evq_list, ev, os_event, ev_next);
+                ev->ev_queued = 0;
+            }
+        }
+        evq[i]->evq_task = NULL;
+    }
+    OS_EXIT_CRITICAL(sr);
+
+has_event:
+    return (ev);
+}
+
+/**
+ * Remove an event from the queue.
+ *
+ * @param evq The event queue to remove the event from
+ * @param ev  The event to remove from the queue
+ */
+void
+os_eventq_remove(struct os_eventq *evq, struct os_event *ev)
+{
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+    if (OS_EVENT_QUEUED(ev)) {
+        STAILQ_REMOVE(&evq->evq_list, ev, os_event, ev_next);
+    }
+    ev->ev_queued = 0;
+    OS_EXIT_CRITICAL(sr);
+}
+
+/**
+ * Retrieves the default event queue processed by OS main task.
+ *
+ * @return                      The default event queue.
+ */
+struct os_eventq *
+os_eventq_dflt_get(void)
+{
+    return &os_eventq_main;
+}
+
+/**
+ * [DEPRECATED - packages should manually enqueue start events to the default
+ * task instead of calling this function]
+ *
+ * Reassigns an event queue pointer to the specified value.  This function is
+ * used for configuring a package to use a particular event queue.  A package's
+ * event queue can generally be reassigned repeatedly.  If the package has a
+ * startup event, the event is moved from the current queue (if any) to the
+ * specified queue.
+ *
+ * @param cur_evq               Points to the eventq pointer to reassign.
+ *                                  *cur_evq should be NULL if the package's
+ *                                  eventq has not been assigned yet.
+ * @param new_evq               The eventq that the package should be
+ *                                  associated with.
+ * @param start_ev              The package's startup event, if any.  If this
+ *                                  is non-NULL, the event gets removed from
+ *                                  the current queue (if set), and enqueued to
+ *                                  the new eventq.
+ */
+void
+os_eventq_designate(struct os_eventq **cur_evq,
+                    struct os_eventq *new_evq,
+                    struct os_event *start_ev)
+{
+    struct os_eventq *prev_evq;
+
+    prev_evq = *cur_evq;
+    *cur_evq = new_evq;
+
+    if (start_ev != NULL) {
+        if (start_ev->ev_queued) {
+            assert(prev_evq != NULL);
+            os_eventq_remove(prev_evq, start_ev);
+        }
+        os_eventq_put(new_evq, start_ev);
+    }
+}
+
+/**
+ *   @} OSEvent
+ * @} OSKernel
+ */
diff --git a/porting/common/src/os/os_heap.c b/porting/common/src/os/os_heap.c
new file mode 100644
index 0000000..0d94325
--- /dev/null
+++ b/porting/common/src/os/os_heap.c
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include "syscfg/syscfg.h"
+
+#include <assert.h>
+#include "os/os_mutex.h"
+#include "os/os_heap.h"
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSGeneral
+ *   @{
+ */
+
+#if MYNEWT_VAL(OS_SCHEDULING)
+static struct os_mutex os_malloc_mutex;
+#endif
+
+static void
+os_malloc_lock(void)
+{
+#if MYNEWT_VAL(OS_SCHEDULING)
+    int rc;
+
+    if (g_os_started) {
+        rc = os_mutex_pend(&os_malloc_mutex, 0xffffffff);
+        assert(rc == 0);
+    }
+#endif
+}
+
+static void
+os_malloc_unlock(void)
+{
+#if MYNEWT_VAL(OS_SCHEDULING)
+    int rc;
+
+    if (g_os_started) {
+        rc = os_mutex_release(&os_malloc_mutex);
+        assert(rc == 0);
+    }
+#endif
+}
+
+/**
+ * Operating system level malloc().   This ensures that a safe malloc occurs
+ * within the context of the OS.  Depending on platform, the OS may rely on
+ * libc's malloc() implementation, which is not guaranteed to be thread-safe.
+ * This malloc() will always be thread-safe.
+ *
+ * @param size The number of bytes to allocate
+ *
+ * @return A pointer to the memory region allocated.
+ */
+void *
+os_malloc(size_t size)
+{
+    void *ptr;
+
+    os_malloc_lock();
+    ptr = malloc(size);
+    os_malloc_unlock();
+
+    return ptr;
+}
+
+/**
+ * Operating system level free().  See description of os_malloc() for reasoning.
+ *
+ * Free's memory allocated by malloc.
+ *
+ * @param mem The memory to free.
+ */
+void
+os_free(void *mem)
+{
+    os_malloc_lock();
+    free(mem);
+    os_malloc_unlock();
+}
+
+/**
+ * Operating system level realloc(). See description of os_malloc() for reasoning.
+ *
+ * Reallocates the memory at ptr, to be size contiguouos bytes.
+ *
+ * @param ptr A pointer to the memory to allocate
+ * @param size The number of contiguouos bytes to allocate at that location
+ *
+ * @return A pointer to memory of size, or NULL on failure to allocate
+ */
+void *
+os_realloc(void *ptr, size_t size)
+{
+    void *new_ptr;
+
+    os_malloc_lock();
+    new_ptr = realloc(ptr, size);
+    os_malloc_unlock();
+
+    return new_ptr;
+}
+
+/**
+ *   @} OSGeneral
+ * @} OS Kernel
+ */
diff --git a/porting/common/src/os/os_mbuf.c b/porting/common/src/os/os_mbuf.c
new file mode 100644
index 0000000..52c81ae
--- /dev/null
+++ b/porting/common/src/os/os_mbuf.c
@@ -0,0 +1,1368 @@
+/*
+ * Software in this file is based heavily on code written in the FreeBSD source
+ * code repostiory.  While the code is written from scratch, it contains
+ * many of the ideas and logic flow in the original source, this is a
+ * derivative work, and the following license applies as well:
+ *
+ * Copyright (c) 1982, 1986, 1988, 1991, 1993
+ *  The Regents of the University of California.  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.
+ * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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 "os/os.h"
+
+#include <assert.h>
+#include <string.h>
+#include <limits.h>
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSMqueue Queue of Mbufs
+ *   @{
+ */
+
+STAILQ_HEAD(, os_mbuf_pool) g_msys_pool_list =
+    STAILQ_HEAD_INITIALIZER(g_msys_pool_list);
+
+/**
+ * Initializes an mqueue.  An mqueue is a queue of mbufs that ties to a
+ * particular task's event queue.  Mqueues form a helper API around a common
+ * paradigm: wait on an event queue until at least one packet is available,
+ * then process a queue of packets.
+ *
+ * When mbufs are available on the queue, an event OS_EVENT_T_MQUEUE_DATA
+ * will be posted to the task's mbuf queue.
+ *
+ * @param mq                    The mqueue to initialize
+ * @param ev_cb                 The callback to associate with the mqeueue
+ *                                  event.  Typically, this callback pulls each
+ *                                  packet off the mqueue and processes them.
+ * @param arg                   The argument to associate with the mqueue event.
+ *
+ * @return                      0 on success, non-zero on failure.
+ */
+int
+os_mqueue_init(struct os_mqueue *mq, os_event_fn *ev_cb, void *arg)
+{
+    struct os_event *ev;
+
+    STAILQ_INIT(&mq->mq_head);
+
+    ev = &mq->mq_ev;
+    memset(ev, 0, sizeof(*ev));
+    ev->ev_cb = ev_cb;
+    ev->ev_arg = arg;
+
+    return (0);
+}
+
+/**
+ * Remove and return a single mbuf from the mbuf queue.  Does not block.
+ *
+ * @param mq The mbuf queue to pull an element off of.
+ *
+ * @return The next mbuf in the queue, or NULL if queue has no mbufs.
+ */
+struct os_mbuf *
+os_mqueue_get(struct os_mqueue *mq)
+{
+    struct os_mbuf_pkthdr *mp;
+    struct os_mbuf *m;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+    mp = STAILQ_FIRST(&mq->mq_head);
+    if (mp) {
+        STAILQ_REMOVE_HEAD(&mq->mq_head, omp_next);
+    }
+    OS_EXIT_CRITICAL(sr);
+
+    if (mp) {
+        m = OS_MBUF_PKTHDR_TO_MBUF(mp);
+    } else {
+        m = NULL;
+    }
+
+    return (m);
+}
+
+/**
+ * Adds a packet (i.e. packet header mbuf) to an mqueue. The event associated
+ * with the mqueue gets posted to the specified eventq.
+ *
+ * @param mq                    The mbuf queue to append the mbuf to.
+ * @param evq                   The event queue to post an event to.
+ * @param m                     The mbuf to append to the mbuf queue.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+os_mqueue_put(struct os_mqueue *mq, struct os_eventq *evq, struct os_mbuf *m)
+{
+    struct os_mbuf_pkthdr *mp;
+    os_sr_t sr;
+    int rc;
+
+    /* Can only place the head of a chained mbuf on the queue. */
+    if (!OS_MBUF_IS_PKTHDR(m)) {
+        rc = OS_EINVAL;
+        goto err;
+    }
+
+    mp = OS_MBUF_PKTHDR(m);
+
+    OS_ENTER_CRITICAL(sr);
+    STAILQ_INSERT_TAIL(&mq->mq_head, mp, omp_next);
+    OS_EXIT_CRITICAL(sr);
+
+    /* Only post an event to the queue if its specified */
+    if (evq) {
+        os_eventq_put(evq, &mq->mq_ev);
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ *   @} OSMqueue
+ * @} OSKernel
+ */
+
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSMsys System level mbuf
+ *   @{
+ */
+
+/**
+ * MSYS is a system level mbuf registry.  Allows the system to share
+ * packet buffers amongst the various networking stacks that can be running
+ * simultaeneously.
+ *
+ * Mbuf pools are created in the system initialization code, and then when
+ * a mbuf is allocated out of msys, it will try and find the best fit based
+ * upon estimated mbuf size.
+ *
+ * os_msys_register() registers a mbuf pool with MSYS, and allows MSYS to
+ * allocate mbufs out of it.
+ *
+ * @param new_pool The pool to register with MSYS
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+os_msys_register(struct os_mbuf_pool *new_pool)
+{
+    struct os_mbuf_pool *pool;
+
+    pool = NULL;
+    STAILQ_FOREACH(pool, &g_msys_pool_list, omp_next) {
+        if (new_pool->omp_databuf_len > pool->omp_databuf_len) {
+            break;
+        }
+    }
+
+    if (pool) {
+        STAILQ_INSERT_AFTER(&g_msys_pool_list, pool, new_pool, omp_next);
+    } else {
+        STAILQ_INSERT_TAIL(&g_msys_pool_list, new_pool, omp_next);
+    }
+
+    return (0);
+}
+
+/**
+ * De-registers all mbuf pools from msys.
+ */
+void
+os_msys_reset(void)
+{
+    STAILQ_INIT(&g_msys_pool_list);
+}
+
+static struct os_mbuf_pool *
+_os_msys_find_pool(uint16_t dsize)
+{
+    struct os_mbuf_pool *pool;
+
+    pool = NULL;
+    STAILQ_FOREACH(pool, &g_msys_pool_list, omp_next) {
+        if (dsize <= pool->omp_databuf_len) {
+            break;
+        }
+    }
+
+    if (!pool) {
+        pool = STAILQ_LAST(&g_msys_pool_list, os_mbuf_pool, omp_next);
+    }
+
+    return (pool);
+}
+
+/**
+ * Allocate a mbuf from msys.  Based upon the data size requested,
+ * os_msys_get() will choose the mbuf pool that has the best fit.
+ *
+ * @param dsize The estimated size of the data being stored in the mbuf
+ * @param leadingspace The amount of leadingspace to allocate in the mbuf
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ *
+ */
+struct os_mbuf *
+os_msys_get(uint16_t dsize, uint16_t leadingspace)
+{
+    struct os_mbuf *m;
+    struct os_mbuf_pool *pool;
+
+    pool = _os_msys_find_pool(dsize);
+    if (!pool) {
+        goto err;
+    }
+
+    m = os_mbuf_get(pool, leadingspace);
+    return (m);
+err:
+    return (NULL);
+}
+
+/**
+ * Allocate a packet header structure from the MSYS pool.  See
+ * os_msys_register() for a description of MSYS.
+ *
+ * @param dsize The estimated size of the data being stored in the mbuf
+ * @param user_hdr_len The length to allocate for the packet header structure
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *
+os_msys_get_pkthdr(uint16_t dsize, uint16_t user_hdr_len)
+{
+    uint16_t total_pkthdr_len;
+    struct os_mbuf *m;
+    struct os_mbuf_pool *pool;
+
+    total_pkthdr_len =  user_hdr_len + sizeof(struct os_mbuf_pkthdr);
+    pool = _os_msys_find_pool(dsize + total_pkthdr_len);
+    if (!pool) {
+        goto err;
+    }
+
+    m = os_mbuf_get_pkthdr(pool, user_hdr_len);
+    return (m);
+err:
+    return (NULL);
+}
+
+int
+os_msys_count(void)
+{
+    struct os_mbuf_pool *omp;
+    int total;
+
+    total = 0;
+    STAILQ_FOREACH(omp, &g_msys_pool_list, omp_next) {
+        total += omp->omp_pool->mp_num_blocks;
+    }
+
+    return total;
+}
+
+int
+os_msys_num_free(void)
+{
+    struct os_mbuf_pool *omp;
+    int total;
+
+    total = 0;
+    STAILQ_FOREACH(omp, &g_msys_pool_list, omp_next) {
+        total += omp->omp_pool->mp_num_free;
+    }
+
+    return total;
+}
+
+/**
+ *   @} OSMsys
+ * @} OSKernel
+ */
+
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSMbuf Chained Memory Buffers
+ *   @{
+ */
+
+
+/**
+ * Initialize a pool of mbufs.
+ *
+ * @param omp     The mbuf pool to initialize
+ * @param mp      The memory pool that will hold this mbuf pool
+ * @param buf_len The length of the buffer itself.
+ * @param nbufs   The number of buffers in the pool
+ *
+ * @return 0 on success, error code on failure.
+ */
+int
+os_mbuf_pool_init(struct os_mbuf_pool *omp, struct os_mempool *mp,
+                  uint16_t buf_len, uint16_t nbufs)
+{
+    omp->omp_databuf_len = buf_len - sizeof(struct os_mbuf);
+    omp->omp_mbuf_count = nbufs;
+    omp->omp_pool = mp;
+
+    return (0);
+}
+
+/**
+ * Get an mbuf from the mbuf pool.  The mbuf is allocated, and initialized
+ * prior to being returned.
+ *
+ * @param omp The mbuf pool to return the packet from
+ * @param leadingspace The amount of leadingspace to put before the data
+ *     section by default.
+ *
+ * @return An initialized mbuf on success, and NULL on failure.
+ */
+struct os_mbuf *
+os_mbuf_get(struct os_mbuf_pool *omp, uint16_t leadingspace)
+{
+    struct os_mbuf *om;
+
+    if (leadingspace > omp->omp_databuf_len) {
+        goto err;
+    }
+
+    om = os_memblock_get(omp->omp_pool);
+    if (!om) {
+        goto err;
+    }
+
+    SLIST_NEXT(om, om_next) = NULL;
+    om->om_flags = 0;
+    om->om_pkthdr_len = 0;
+    om->om_len = 0;
+    om->om_data = (&om->om_databuf[0] + leadingspace);
+    om->om_omp = omp;
+
+    return (om);
+err:
+    return (NULL);
+}
+
+/**
+ * Allocate a new packet header mbuf out of the os_mbuf_pool.
+ *
+ * @param omp The mbuf pool to allocate out of
+ * @param user_pkthdr_len The packet header length to reserve for the caller.
+ *
+ * @return A freshly allocated mbuf on success, NULL on failure.
+ */
+struct os_mbuf *
+os_mbuf_get_pkthdr(struct os_mbuf_pool *omp, uint8_t user_pkthdr_len)
+{
+    uint16_t pkthdr_len;
+    struct os_mbuf_pkthdr *pkthdr;
+    struct os_mbuf *om;
+
+    /* User packet header must fit inside mbuf */
+    pkthdr_len = user_pkthdr_len + sizeof(struct os_mbuf_pkthdr);
+    if ((pkthdr_len > omp->omp_databuf_len) || (pkthdr_len > 255)) {
+        return NULL;
+    }
+
+    om = os_mbuf_get(omp, 0);
+    if (om) {
+        om->om_pkthdr_len = pkthdr_len;
+        om->om_data += pkthdr_len;
+
+        pkthdr = OS_MBUF_PKTHDR(om);
+        pkthdr->omp_len = 0;
+        pkthdr->omp_flags = 0;
+        STAILQ_NEXT(pkthdr, omp_next) = NULL;
+    }
+
+    return om;
+}
+
+/**
+ * Release a mbuf back to the pool
+ *
+ * @param omp The Mbuf pool to release back to
+ * @param om  The Mbuf to release back to the pool
+ *
+ * @return 0 on success, -1 on failure
+ */
+int
+os_mbuf_free(struct os_mbuf *om)
+{
+    int rc;
+
+    if (om->om_omp != NULL) {
+        rc = os_memblock_put(om->om_omp->omp_pool, om);
+        if (rc != 0) {
+            goto err;
+        }
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * Free a chain of mbufs
+ *
+ * @param omp The mbuf pool to free the chain of mbufs into
+ * @param om  The starting mbuf of the chain to free back into the pool
+ *
+ * @return 0 on success, -1 on failure
+ */
+int
+os_mbuf_free_chain(struct os_mbuf *om)
+{
+    struct os_mbuf *next;
+    int rc;
+
+    while (om != NULL) {
+        next = SLIST_NEXT(om, om_next);
+
+        rc = os_mbuf_free(om);
+        if (rc != 0) {
+            goto err;
+        }
+
+        om = next;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * Copy a packet header from one mbuf to another.
+ *
+ * @param omp The mbuf pool associated with these buffers
+ * @param new_buf The new buffer to copy the packet header into
+ * @param old_buf The old buffer to copy the packet header from
+ */
+static inline void
+_os_mbuf_copypkthdr(struct os_mbuf *new_buf, struct os_mbuf *old_buf)
+{
+    assert(new_buf->om_len == 0);
+
+    memcpy(&new_buf->om_databuf[0], &old_buf->om_databuf[0],
+           old_buf->om_pkthdr_len);
+    new_buf->om_pkthdr_len = old_buf->om_pkthdr_len;
+    new_buf->om_data = new_buf->om_databuf + old_buf->om_pkthdr_len;
+}
+
+/**
+ * Append data onto a mbuf
+ *
+ * @param om   The mbuf to append the data onto
+ * @param data The data to append onto the mbuf
+ * @param len  The length of the data to append
+ *
+ * @return 0 on success, and an error code on failure
+ */
+int
+os_mbuf_append(struct os_mbuf *om, const void *data,  uint16_t len)
+{
+    struct os_mbuf_pool *omp;
+    struct os_mbuf *last;
+    struct os_mbuf *new;
+    int remainder;
+    int space;
+    int rc;
+
+    if (om == NULL) {
+        rc = OS_EINVAL;
+        goto err;
+    }
+
+    omp = om->om_omp;
+
+    /* Scroll to last mbuf in the chain */
+    last = om;
+    while (SLIST_NEXT(last, om_next) != NULL) {
+        last = SLIST_NEXT(last, om_next);
+    }
+
+    remainder = len;
+    space = OS_MBUF_TRAILINGSPACE(last);
+
+    /* If room in current mbuf, copy the first part of the data into the
+     * remaining space in that mbuf.
+     */
+    if (space > 0) {
+        if (space > remainder) {
+            space = remainder;
+        }
+
+        memcpy(OS_MBUF_DATA(last, uint8_t *) + last->om_len , data, space);
+
+        last->om_len += space;
+        data += space;
+        remainder -= space;
+    }
+
+    /* Take the remaining data, and keep allocating new mbufs and copying
+     * data into it, until data is exhausted.
+     */
+    while (remainder > 0) {
+        new = os_mbuf_get(omp, 0);
+        if (!new) {
+            break;
+        }
+
+        new->om_len = min(omp->omp_databuf_len, remainder);
+        memcpy(OS_MBUF_DATA(new, void *), data, new->om_len);
+        data += new->om_len;
+        remainder -= new->om_len;
+        SLIST_NEXT(last, om_next) = new;
+        last = new;
+    }
+
+    /* Adjust the packet header length in the buffer */
+    if (OS_MBUF_IS_PKTHDR(om)) {
+        OS_MBUF_PKTHDR(om)->omp_len += len - remainder;
+    }
+
+    if (remainder != 0) {
+        rc = OS_ENOMEM;
+        goto err;
+    }
+
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * Reads data from one mbuf and appends it to another.  On error, the specified
+ * data range may be partially appended.  Neither mbuf is required to contain
+ * an mbuf packet header.
+ *
+ * @param dst                   The mbuf to append to.
+ * @param src                   The mbuf to copy data from.
+ * @param src_off               The absolute offset within the source mbuf
+ *                                  chain to read from.
+ * @param len                   The number of bytes to append.
+ *
+ * @return                      0 on success;
+ *                              OS_EINVAL if the specified range extends beyond
+ *                                  the end of the source mbuf chain.
+ */
+int
+os_mbuf_appendfrom(struct os_mbuf *dst, const struct os_mbuf *src,
+                   uint16_t src_off, uint16_t len)
+{
+    const struct os_mbuf *src_cur_om;
+    uint16_t src_cur_off;
+    uint16_t chunk_sz;
+    int rc;
+
+    src_cur_om = os_mbuf_off(src, src_off, &src_cur_off);
+    while (len > 0) {
+        if (src_cur_om == NULL) {
+            return OS_EINVAL;
+        }
+
+        chunk_sz = min(len, src_cur_om->om_len - src_cur_off);
+        rc = os_mbuf_append(dst, src_cur_om->om_data + src_cur_off, chunk_sz);
+        if (rc != 0) {
+            return rc;
+        }
+
+        len -= chunk_sz;
+        src_cur_om = SLIST_NEXT(src_cur_om, om_next);
+        src_cur_off = 0;
+    }
+
+    return 0;
+}
+
+/**
+ * Duplicate a chain of mbufs.  Return the start of the duplicated chain.
+ *
+ * @param omp The mbuf pool to duplicate out of
+ * @param om  The mbuf chain to duplicate
+ *
+ * @return A pointer to the new chain of mbufs
+ */
+struct os_mbuf *
+os_mbuf_dup(struct os_mbuf *om)
+{
+    struct os_mbuf_pool *omp;
+    struct os_mbuf *head;
+    struct os_mbuf *copy;
+
+    omp = om->om_omp;
+
+    head = NULL;
+    copy = NULL;
+
+    for (; om != NULL; om = SLIST_NEXT(om, om_next)) {
+        if (head) {
+            SLIST_NEXT(copy, om_next) = os_mbuf_get(omp,
+                    OS_MBUF_LEADINGSPACE(om));
+            if (!SLIST_NEXT(copy, om_next)) {
+                os_mbuf_free_chain(head);
+                goto err;
+            }
+
+            copy = SLIST_NEXT(copy, om_next);
+        } else {
+            head = os_mbuf_get(omp, OS_MBUF_LEADINGSPACE(om));
+            if (!head) {
+                goto err;
+            }
+
+            if (OS_MBUF_IS_PKTHDR(om)) {
+                _os_mbuf_copypkthdr(head, om);
+            }
+            copy = head;
+        }
+        copy->om_flags = om->om_flags;
+        copy->om_len = om->om_len;
+        memcpy(OS_MBUF_DATA(copy, uint8_t *), OS_MBUF_DATA(om, uint8_t *),
+                om->om_len);
+    }
+
+    return (head);
+err:
+    return (NULL);
+}
+
+/**
+ * Locates the specified absolute offset within an mbuf chain.  The offset
+ * can be one past than the total length of the chain, but no greater.
+ *
+ * @param om                    The start of the mbuf chain to seek within.
+ * @param off                   The absolute address to find.
+ * @param out_off               On success, this points to the relative offset
+ *                                  within the returned mbuf.
+ *
+ * @return                      The mbuf containing the specified offset on
+ *                                  success.
+ *                              NULL if the specified offset is out of bounds.
+ */
+struct os_mbuf *
+os_mbuf_off(const struct os_mbuf *om, int off, uint16_t *out_off)
+{
+    struct os_mbuf *next;
+    struct os_mbuf *cur;
+
+    /* Cast away const. */
+    cur = (struct os_mbuf *)om;
+
+    while (1) {
+        if (cur == NULL) {
+            return NULL;
+        }
+
+        next = SLIST_NEXT(cur, om_next);
+
+        if (cur->om_len > off ||
+            (cur->om_len == off && next == NULL)) {
+
+            *out_off = off;
+            return cur;
+        }
+
+        off -= cur->om_len;
+        cur = next;
+    }
+}
+
+/*
+ * Copy data from an mbuf chain starting "off" bytes from the beginning,
+ * continuing for "len" bytes, into the indicated buffer.
+ *
+ * @param m The mbuf chain to copy from
+ * @param off The offset into the mbuf chain to begin copying from
+ * @param len The length of the data to copy
+ * @param dst The destination buffer to copy into
+ *
+ * @return                      0 on success;
+ *                              -1 if the mbuf does not contain enough data.
+ */
+int
+os_mbuf_copydata(const struct os_mbuf *m, int off, int len, void *dst)
+{
+    unsigned int count;
+    uint8_t *udst;
+
+    if (!len) {
+        return 0;
+    }
+
+    udst = dst;
+
+    while (off > 0) {
+        if (!m) {
+            return (-1);
+        }
+
+        if (off < m->om_len)
+            break;
+        off -= m->om_len;
+        m = SLIST_NEXT(m, om_next);
+    }
+    while (len > 0 && m != NULL) {
+        count = min(m->om_len - off, len);
+        memcpy(udst, m->om_data + off, count);
+        len -= count;
+        udst += count;
+        off = 0;
+        m = SLIST_NEXT(m, om_next);
+    }
+
+    return (len > 0 ? -1 : 0);
+}
+
+/**
+ * Adjust the length of a mbuf, trimming either from the head or the tail
+ * of the mbuf.
+ *
+ * @param mp The mbuf chain to adjust
+ * @param req_len The length to trim from the mbuf.  If positive, trims
+ *                from the head of the mbuf, if negative, trims from the
+ *                tail of the mbuf.
+ */
+void
+os_mbuf_adj(struct os_mbuf *mp, int req_len)
+{
+    int len = req_len;
+    struct os_mbuf *m;
+    int count;
+
+    if ((m = mp) == NULL)
+        return;
+    if (len >= 0) {
+        /*
+         * Trim from head.
+         */
+        while (m != NULL && len > 0) {
+            if (m->om_len <= len) {
+                len -= m->om_len;
+                m->om_len = 0;
+                m = SLIST_NEXT(m, om_next);
+            } else {
+                m->om_len -= len;
+                m->om_data += len;
+                len = 0;
+            }
+        }
+        if (OS_MBUF_IS_PKTHDR(mp))
+            OS_MBUF_PKTHDR(mp)->omp_len -= (req_len - len);
+    } else {
+        /*
+         * Trim from tail.  Scan the mbuf chain,
+         * calculating its length and finding the last mbuf.
+         * If the adjustment only affects this mbuf, then just
+         * adjust and return.  Otherwise, rescan and truncate
+         * after the remaining size.
+         */
+        len = -len;
+        count = 0;
+        for (;;) {
+            count += m->om_len;
+            if (SLIST_NEXT(m, om_next) == (struct os_mbuf *)0)
+                break;
+            m = SLIST_NEXT(m, om_next);
+        }
+        if (m->om_len >= len) {
+            m->om_len -= len;
+            if (OS_MBUF_IS_PKTHDR(mp))
+                OS_MBUF_PKTHDR(mp)->omp_len -= len;
+            return;
+        }
+        count -= len;
+        if (count < 0)
+            count = 0;
+        /*
+         * Correct length for chain is "count".
+         * Find the mbuf with last data, adjust its length,
+         * and toss data from remaining mbufs on chain.
+         */
+        m = mp;
+        if (OS_MBUF_IS_PKTHDR(m))
+            OS_MBUF_PKTHDR(m)->omp_len = count;
+        for (; m; m = SLIST_NEXT(m, om_next)) {
+            if (m->om_len >= count) {
+                m->om_len = count;
+                if (SLIST_NEXT(m, om_next) != NULL) {
+                    os_mbuf_free_chain(SLIST_NEXT(m, om_next));
+                    SLIST_NEXT(m, om_next) = NULL;
+                }
+                break;
+            }
+            count -= m->om_len;
+        }
+    }
+}
+
+/**
+ * Performs a memory compare of the specified region of an mbuf chain against a
+ * flat buffer.
+ *
+ * @param om                    The start of the mbuf chain to compare.
+ * @param off                   The offset within the mbuf chain to start the
+ *                                  comparison.
+ * @param data                  The flat buffer to compare.
+ * @param len                   The length of the flat buffer.
+ *
+ * @return                      0 if both memory regions are identical;
+ *                              A memcmp return code if there is a mismatch;
+ *                              INT_MAX if the mbuf is too short.
+ */
+int
+os_mbuf_cmpf(const struct os_mbuf *om, int off, const void *data, int len)
+{
+    uint16_t chunk_sz;
+    uint16_t data_off;
+    uint16_t om_off;
+    int rc;
+
+    if (len <= 0) {
+        return 0;
+    }
+
+    data_off = 0;
+    om = os_mbuf_off(om, off, &om_off);
+    while (1) {
+        if (om == NULL) {
+            return INT_MAX;
+        }
+
+        chunk_sz = min(om->om_len - om_off, len - data_off);
+        if (chunk_sz > 0) {
+            rc = memcmp(om->om_data + om_off, data + data_off, chunk_sz);
+            if (rc != 0) {
+                return rc;
+            }
+        }
+
+        data_off += chunk_sz;
+        if (data_off == len) {
+            return 0;
+        }
+
+        om = SLIST_NEXT(om, om_next);
+        om_off = 0;
+
+        if (om == NULL) {
+            return INT_MAX;
+        }
+    }
+}
+
+/**
+ * Compares the contents of two mbuf chains.  The ranges of the two chains to
+ * be compared are specified via the two offset parameters and the len
+ * parameter.  Neither mbuf chain is required to contain a packet header.
+ *
+ * @param om1                   The first mbuf chain to compare.
+ * @param offset1               The absolute offset within om1 at which to
+ *                                  start the comparison.
+ * @param om2                   The second mbuf chain to compare.
+ * @param offset2               The absolute offset within om2 at which to
+ *                                  start the comparison.
+ * @param len                   The number of bytes to compare.
+ *
+ * @return                      0 if both mbuf segments are identical;
+ *                              A memcmp() return code if the segment contents
+ *                                  differ;
+ *                              INT_MAX if a specified range extends beyond the
+ *                                  end of its corresponding mbuf chain.
+ */
+int
+os_mbuf_cmpm(const struct os_mbuf *om1, uint16_t offset1,
+             const struct os_mbuf *om2, uint16_t offset2,
+             uint16_t len)
+{
+    const struct os_mbuf *cur1;
+    const struct os_mbuf *cur2;
+    uint16_t bytes_remaining;
+    uint16_t chunk_sz;
+    uint16_t om1_left;
+    uint16_t om2_left;
+    uint16_t om1_off;
+    uint16_t om2_off;
+    int rc;
+
+    om1_off = 0;
+    om2_off = 0;
+
+    cur1 = os_mbuf_off(om1, offset1, &om1_off);
+    cur2 = os_mbuf_off(om2, offset2, &om2_off);
+
+    bytes_remaining = len;
+    while (1) {
+        if (bytes_remaining == 0) {
+            return 0;
+        }
+
+        while (cur1 != NULL && om1_off >= cur1->om_len) {
+            cur1 = SLIST_NEXT(cur1, om_next);
+            om1_off = 0;
+        }
+        while (cur2 != NULL && om2_off >= cur2->om_len) {
+            cur2 = SLIST_NEXT(cur2, om_next);
+            om2_off = 0;
+        }
+
+        if (cur1 == NULL || cur2 == NULL) {
+            return INT_MAX;
+        }
+
+        om1_left = cur1->om_len - om1_off;
+        om2_left = cur2->om_len - om2_off;
+        chunk_sz = min(min(om1_left, om2_left), bytes_remaining);
+
+        rc = memcmp(cur1->om_data + om1_off, cur2->om_data + om2_off,
+                    chunk_sz);
+        if (rc != 0) {
+            return rc;
+        }
+
+        om1_off += chunk_sz;
+        om2_off += chunk_sz;
+        bytes_remaining -= chunk_sz;
+    }
+}
+
+/**
+ * Increases the length of an mbuf chain by adding data to the front.  If there
+ * is insufficient room in the leading mbuf, additional mbufs are allocated and
+ * prepended as necessary.  If this function fails to allocate an mbuf, the
+ * entire chain is freed.
+ *
+ * The specified mbuf chain does not need to contain a packet header.
+ *
+ * @param omp                   The mbuf pool to allocate from.
+ * @param om                    The head of the mbuf chain.
+ * @param len                   The number of bytes to prepend.
+ *
+ * @return                      The new head of the chain on success;
+ *                              NULL on failure.
+ */
+struct os_mbuf *
+os_mbuf_prepend(struct os_mbuf *om, int len)
+{
+    struct os_mbuf *p;
+    int leading;
+
+    while (1) {
+        /* Fill the available space at the front of the head of the chain, as
+         * needed.
+         */
+        leading = min(len, OS_MBUF_LEADINGSPACE(om));
+
+        om->om_data -= leading;
+        om->om_len += leading;
+        if (OS_MBUF_IS_PKTHDR(om)) {
+            OS_MBUF_PKTHDR(om)->omp_len += leading;
+        }
+
+        len -= leading;
+        if (len == 0) {
+            break;
+        }
+
+        /* The current head didn't have enough space; allocate a new head. */
+        if (OS_MBUF_IS_PKTHDR(om)) {
+            p = os_mbuf_get_pkthdr(om->om_omp,
+                om->om_pkthdr_len - sizeof (struct os_mbuf_pkthdr));
+        } else {
+            p = os_mbuf_get(om->om_omp, 0);
+        }
+        if (p == NULL) {
+            os_mbuf_free_chain(om);
+            om = NULL;
+            break;
+        }
+
+        if (OS_MBUF_IS_PKTHDR(om)) {
+            _os_mbuf_copypkthdr(p, om);
+            om->om_pkthdr_len = 0;
+        }
+
+        /* Move the new head's data pointer to the end so that data can be
+         * prepended.
+         */
+        p->om_data += OS_MBUF_TRAILINGSPACE(p);
+
+        SLIST_NEXT(p, om_next) = om;
+        om = p;
+    }
+
+    return om;
+}
+
+/**
+ * Prepends a chunk of empty data to the specified mbuf chain and ensures the
+ * chunk is contiguous.  If either operation fails, the specified mbuf chain is
+ * freed and NULL is returned.
+ *
+ * @param om                    The mbuf chain to prepend to.
+ * @param len                   The number of bytes to prepend and pullup.
+ *
+ * @return                      The modified mbuf on success;
+ *                              NULL on failure (and the mbuf chain is freed).
+ */
+struct os_mbuf *
+os_mbuf_prepend_pullup(struct os_mbuf *om, uint16_t len)
+{
+    om = os_mbuf_prepend(om, len);
+    if (om == NULL) {
+        return NULL;
+    }
+
+    om = os_mbuf_pullup(om, len);
+    if (om == NULL) {
+        return NULL;
+    }
+
+    return om;
+}
+
+/**
+ * Copies the contents of a flat buffer into an mbuf chain, starting at the
+ * specified destination offset.  If the mbuf is too small for the source data,
+ * it is extended as necessary.  If the destination mbuf contains a packet
+ * header, the header length is updated.
+ *
+ * @param omp                   The mbuf pool to allocate from.
+ * @param om                    The mbuf chain to copy into.
+ * @param off                   The offset within the chain to copy to.
+ * @param src                   The source buffer to copy from.
+ * @param len                   The number of bytes to copy.
+ *
+ * @return                      0 on success; nonzero on failure.
+ */
+int
+os_mbuf_copyinto(struct os_mbuf *om, int off, const void *src, int len)
+{
+    struct os_mbuf *next;
+    struct os_mbuf *cur;
+    const uint8_t *sptr;
+    uint16_t cur_off;
+    int copylen;
+    int rc;
+
+    /* Find the mbuf,offset pair for the start of the destination. */
+    cur = os_mbuf_off(om, off, &cur_off);
+    if (cur == NULL) {
+        return -1;
+    }
+
+    /* Overwrite existing data until we reach the end of the chain. */
+    sptr = src;
+    while (1) {
+        copylen = min(cur->om_len - cur_off, len);
+        if (copylen > 0) {
+            memcpy(cur->om_data + cur_off, sptr, copylen);
+            sptr += copylen;
+            len -= copylen;
+
+            copylen = 0;
+        }
+
+        if (len == 0) {
+            /* All the source data fit in the existing mbuf chain. */
+            return 0;
+        }
+
+        next = SLIST_NEXT(cur, om_next);
+        if (next == NULL) {
+            break;
+        }
+
+        cur = next;
+        cur_off = 0;
+    }
+
+    /* Append the remaining data to the end of the chain. */
+    rc = os_mbuf_append(cur, sptr, len);
+    if (rc != 0) {
+        return rc;
+    }
+
+    /* Fix up the packet header, if one is present. */
+    if (OS_MBUF_IS_PKTHDR(om)) {
+        OS_MBUF_PKTHDR(om)->omp_len =
+            max(OS_MBUF_PKTHDR(om)->omp_len, off + len);
+    }
+
+    return 0;
+}
+
+/**
+ * Attaches a second mbuf chain onto the end of the first.  If the first chain
+ * contains a packet header, the header's length is updated.  If the second
+ * chain has a packet header, its header is cleared.
+ *
+ * @param first                 The mbuf chain being attached to.
+ * @param second                The mbuf chain that gets attached.
+ */
+void
+os_mbuf_concat(struct os_mbuf *first, struct os_mbuf *second)
+{
+    struct os_mbuf *next;
+    struct os_mbuf *cur;
+
+    /* Point 'cur' to the last buffer in the first chain. */
+    cur = first;
+    while (1) {
+        next = SLIST_NEXT(cur, om_next);
+        if (next == NULL) {
+            break;
+        }
+
+        cur = next;
+    }
+
+    /* Attach the second chain to the end of the first. */
+    SLIST_NEXT(cur, om_next) = second;
+
+    /* If the first chain has a packet header, calculate the length of the
+     * second chain and add it to the header length.
+     */
+    if (OS_MBUF_IS_PKTHDR(first)) {
+        if (OS_MBUF_IS_PKTHDR(second)) {
+            OS_MBUF_PKTHDR(first)->omp_len += OS_MBUF_PKTHDR(second)->omp_len;
+        } else {
+            for (cur = second; cur != NULL; cur = SLIST_NEXT(cur, om_next)) {
+                OS_MBUF_PKTHDR(first)->omp_len += cur->om_len;
+            }
+        }
+    }
+
+    second->om_pkthdr_len = 0;
+}
+
+/**
+ * Increases the length of an mbuf chain by the specified amount.  If there is
+ * not sufficient room in the last buffer, a new buffer is allocated and
+ * appended to the chain.  It is an error to request more data than can fit in
+ * a single buffer.
+ *
+ * @param omp
+ * @param om                    The head of the chain to extend.
+ * @param len                   The number of bytes to extend by.
+ *
+ * @return                      A pointer to the new data on success;
+ *                              NULL on failure.
+ */
+void *
+os_mbuf_extend(struct os_mbuf *om, uint16_t len)
+{
+    struct os_mbuf *newm;
+    struct os_mbuf *last;
+    void *data;
+
+    if (len > om->om_omp->omp_databuf_len) {
+        return NULL;
+    }
+
+    /* Scroll to last mbuf in the chain */
+    last = om;
+    while (SLIST_NEXT(last, om_next) != NULL) {
+        last = SLIST_NEXT(last, om_next);
+    }
+
+    if (OS_MBUF_TRAILINGSPACE(last) < len) {
+        newm = os_mbuf_get(om->om_omp, 0);
+        if (newm == NULL) {
+            return NULL;
+        }
+
+        SLIST_NEXT(last, om_next) = newm;
+        last = newm;
+    }
+
+    data = last->om_data + last->om_len;
+    last->om_len += len;
+
+    if (OS_MBUF_IS_PKTHDR(om)) {
+        OS_MBUF_PKTHDR(om)->omp_len += len;
+    }
+
+    return data;
+}
+
+/**
+ * Rearrange a mbuf chain so that len bytes are contiguous,
+ * and in the data area of an mbuf (so that OS_MBUF_DATA() will
+ * work on a structure of size len.)  Returns the resulting
+ * mbuf chain on success, free's it and returns NULL on failure.
+ *
+ * If there is room, it will add up to "max_protohdr - len"
+ * extra bytes to the contiguous region, in an attempt to avoid being
+ * called next time.
+ *
+ * @param omp The mbuf pool to take the mbufs out of
+ * @param om The mbuf chain to make contiguous
+ * @param len The number of bytes in the chain to make contiguous
+ *
+ * @return The contiguous mbuf chain on success, NULL on failure.
+ */
+struct os_mbuf *
+os_mbuf_pullup(struct os_mbuf *om, uint16_t len)
+{
+    struct os_mbuf_pool *omp;
+    struct os_mbuf *next;
+    struct os_mbuf *om2;
+    int count;
+    int space;
+
+    omp = om->om_omp;
+
+    /*
+     * If first mbuf has no cluster, and has room for len bytes
+     * without shifting current data, pullup into it,
+     * otherwise allocate a new mbuf to prepend to the chain.
+     */
+    if (om->om_len >= len) {
+        return (om);
+    }
+    if (om->om_len + OS_MBUF_TRAILINGSPACE(om) >= len &&
+        SLIST_NEXT(om, om_next)) {
+        om2 = om;
+        om = SLIST_NEXT(om, om_next);
+        len -= om2->om_len;
+    } else {
+        if (len > omp->omp_databuf_len - om->om_pkthdr_len) {
+            goto bad;
+        }
+
+        om2 = os_mbuf_get(omp, 0);
+        if (om2 == NULL) {
+            goto bad;
+        }
+
+        if (OS_MBUF_IS_PKTHDR(om)) {
+            _os_mbuf_copypkthdr(om2, om);
+        }
+    }
+    space = OS_MBUF_TRAILINGSPACE(om2);
+    do {
+        count = min(min(len, space), om->om_len);
+        memcpy(om2->om_data + om2->om_len, om->om_data, count);
+        len -= count;
+        om2->om_len += count;
+        om->om_len -= count;
+        space -= count;
+        if (om->om_len) {
+            om->om_data += count;
+        } else {
+            next = SLIST_NEXT(om, om_next);
+            os_mbuf_free(om);
+            om = next;
+        }
+    } while (len > 0 && om);
+    if (len > 0) {
+        os_mbuf_free(om2);
+        goto bad;
+    }
+    SLIST_NEXT(om2, om_next) = om;
+    return (om2);
+bad:
+    os_mbuf_free_chain(om);
+    return (NULL);
+}
+
+/**
+ * Removes and frees empty mbufs from the front of a chain.  If the chain
+ * contains a packet header, it is preserved.
+ *
+ * @param om                    The mbuf chain to trim.
+ *
+ * @return                      The head of the trimmed mbuf chain.
+ */
+struct os_mbuf *
+os_mbuf_trim_front(struct os_mbuf *om)
+{
+    struct os_mbuf *next;
+    struct os_mbuf *cur;
+
+    /* Abort early if there is nothing to trim. */
+    if (om->om_len != 0) {
+        return om;
+    }
+
+    /* Starting with the second mbuf in the chain, continue removing and
+     * freeing mbufs until an non-empty one is encountered.
+     */
+    cur = SLIST_NEXT(om, om_next);
+    while (cur != NULL && cur->om_len == 0) {
+        next = SLIST_NEXT(cur, om_next);
+
+        SLIST_NEXT(om, om_next) = next;
+        os_mbuf_free(cur);
+
+        cur = next;
+    }
+
+    if (cur == NULL) {
+        /* All buffers after the first have been freed. */
+        return om;
+    }
+
+    /* Try to remove the first mbuf in the chain.  If this buffer contains a
+     * packet header, make sure the second buffer can accommodate it.
+     */
+    if (OS_MBUF_LEADINGSPACE(cur) >= om->om_pkthdr_len) {
+        /* Second buffer has room; copy packet header. */
+        cur->om_pkthdr_len = om->om_pkthdr_len;
+        memcpy(OS_MBUF_PKTHDR(cur), OS_MBUF_PKTHDR(om), om->om_pkthdr_len);
+
+        /* Free first buffer. */
+        os_mbuf_free(om);
+        om = cur;
+    }
+
+    return om;
+}
+
+/**
+ *   @} OSMbuf
+ * @} OSKernel
+ */
diff --git a/porting/common/src/os/os_mempool.c b/porting/common/src/os/os_mempool.c
new file mode 100644
index 0000000..65e4f61
--- /dev/null
+++ b/porting/common/src/os/os_mempool.c
@@ -0,0 +1,321 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "os/os.h"
+
+#include <string.h>
+#include <assert.h>
+#include <stdbool.h>
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSMempool Memory Pools
+ *   @{
+ */
+
+#define OS_MEM_TRUE_BLOCK_SIZE(bsize)   OS_ALIGN(bsize, OS_ALIGNMENT)
+#define OS_MEMPOOL_TRUE_BLOCK_SIZE(mp) OS_MEM_TRUE_BLOCK_SIZE(mp->mp_block_size)
+
+STAILQ_HEAD(, os_mempool) g_os_mempool_list =
+    STAILQ_HEAD_INITIALIZER(g_os_mempool_list);
+
+#if MYNEWT_VAL(OS_MEMPOOL_POISON)
+static uint32_t os_mem_poison = 0xde7ec7ed;
+
+static void
+os_mempool_poison(void *start, int sz)
+{
+    int i;
+    char *p = start;
+
+    for (i = sizeof(struct os_memblock); i < sz;
+         i = i + sizeof(os_mem_poison)) {
+        memcpy(p + i, &os_mem_poison, min(sizeof(os_mem_poison), sz - i));
+    }
+}
+
+static void
+os_mempool_poison_check(void *start, int sz)
+{
+    int i;
+    char *p = start;
+
+    for (i = sizeof(struct os_memblock); i < sz;
+         i = i + sizeof(os_mem_poison)) {
+        assert(!memcmp(p + i, &os_mem_poison,
+               min(sizeof(os_mem_poison), sz - i)));
+    }
+}
+#else
+#define os_mempool_poison(start, sz)
+#define os_mempool_poison_check(start, sz)
+#endif
+
+/**
+ * os mempool init
+ *
+ * Initialize a memory pool.
+ *
+ * @param mp            Pointer to a pointer to a mempool
+ * @param blocks        The number of blocks in the pool
+ * @param blocks_size   The size of the block, in bytes.
+ * @param membuf        Pointer to memory to contain blocks.
+ * @param name          Name of the pool.
+ *
+ * @return os_error_t
+ */
+os_error_t
+os_mempool_init(struct os_mempool *mp, int blocks, int block_size,
+                void *membuf, char *name)
+{
+    int true_block_size;
+    uint8_t *block_addr;
+    struct os_memblock *block_ptr;
+
+    /* Check for valid parameters */
+    if (!mp || (blocks < 0) || (block_size <= sizeof(struct os_memblock))) {
+        return OS_INVALID_PARM;
+    }
+
+    if ((!membuf) && (blocks != 0)) {
+        return OS_INVALID_PARM;
+    }
+
+    if (membuf != NULL) {
+        /* Blocks need to be sized properly and memory buffer should be
+         * aligned
+         */
+        if (((uint32_t)membuf & (OS_ALIGNMENT - 1)) != 0) {
+            return OS_MEM_NOT_ALIGNED;
+        }
+    }
+    true_block_size = OS_MEM_TRUE_BLOCK_SIZE(block_size);
+
+    /* Initialize the memory pool structure */
+    mp->mp_block_size = block_size;
+    mp->mp_num_free = blocks;
+    mp->mp_min_free = blocks;
+    mp->mp_num_blocks = blocks;
+    mp->mp_membuf_addr = (uint32_t)membuf;
+    mp->name = name;
+    os_mempool_poison(membuf, true_block_size);
+    SLIST_FIRST(mp) = membuf;
+
+    /* Chain the memory blocks to the free list */
+    block_addr = (uint8_t *)membuf;
+    block_ptr = (struct os_memblock *)block_addr;
+    while (blocks > 1) {
+        block_addr += true_block_size;
+        os_mempool_poison(block_addr, true_block_size);
+        SLIST_NEXT(block_ptr, mb_next) = (struct os_memblock *)block_addr;
+        block_ptr = (struct os_memblock *)block_addr;
+        --blocks;
+    }
+
+    /* Last one in the list should be NULL */
+    SLIST_NEXT(block_ptr, mb_next) = NULL;
+
+    STAILQ_INSERT_TAIL(&g_os_mempool_list, mp, mp_list);
+
+    return OS_OK;
+}
+
+/**
+ * Performs an integrity check of the specified mempool.  This function
+ * attempts to detect memory corruption in the specified memory pool.
+ *
+ * @param mp                    The mempool to check.
+ *
+ * @return                      true if the memory pool passes the integrity
+ *                                  check;
+ *                              false if the memory pool is corrupt.
+ */
+bool
+os_mempool_is_sane(const struct os_mempool *mp)
+{
+    struct os_memblock *block;
+
+    /* Verify that each block in the free list belongs to the mempool. */
+    SLIST_FOREACH(block, mp, mb_next) {
+        if (!os_memblock_from(mp, block)) {
+            return false;
+        }
+        os_mempool_poison_check(block, OS_MEMPOOL_TRUE_BLOCK_SIZE(mp));
+    }
+
+    return true;
+}
+
+/**
+ * Checks if a memory block was allocated from the specified mempool.
+ *
+ * @param mp                    The mempool to check as parent.
+ * @param block_addr            The memory block to check as child.
+ *
+ * @return                      0 if the block does not belong to the mempool;
+ *                              1 if the block does belong to the mempool.
+ */
+int
+os_memblock_from(const struct os_mempool *mp, const void *block_addr)
+{
+    uint32_t true_block_size;
+    uint32_t baddr32;
+    uint32_t end;
+
+    _Static_assert(sizeof block_addr == sizeof baddr32,
+                   "Pointer to void must be 32-bits.");
+
+    baddr32 = (uint32_t)block_addr;
+    true_block_size = OS_MEMPOOL_TRUE_BLOCK_SIZE(mp);
+    end = mp->mp_membuf_addr + (mp->mp_num_blocks * true_block_size);
+
+    /* Check that the block is in the memory buffer range. */
+    if ((baddr32 < mp->mp_membuf_addr) || (baddr32 >= end)) {
+        return 0;
+    }
+
+    /* All freed blocks should be on true block size boundaries! */
+    if (((baddr32 - mp->mp_membuf_addr) % true_block_size) != 0) {
+        return 0;
+    }
+
+    return 1;
+}
+
+/**
+ * os memblock get
+ *
+ * Get a memory block from a memory pool
+ *
+ * @param mp Pointer to the memory pool
+ *
+ * @return void* Pointer to block if available; NULL otherwise
+ */
+void *
+os_memblock_get(struct os_mempool *mp)
+{
+    os_sr_t sr;
+    struct os_memblock *block;
+
+    /* Check to make sure they passed in a memory pool (or something) */
+    block = NULL;
+    if (mp) {
+        OS_ENTER_CRITICAL(sr);
+        /* Check for any free */
+        if (mp->mp_num_free) {
+            /* Get a free block */
+            block = SLIST_FIRST(mp);
+
+            os_mempool_poison_check(block, OS_MEMPOOL_TRUE_BLOCK_SIZE(mp));
+
+            /* Set new free list head */
+            SLIST_FIRST(mp) = SLIST_NEXT(block, mb_next);
+
+            /* Decrement number free by 1 */
+            mp->mp_num_free--;
+            if (mp->mp_min_free > mp->mp_num_free) {
+                mp->mp_min_free = mp->mp_num_free;
+            }
+        }
+        OS_EXIT_CRITICAL(sr);
+    }
+
+    return (void *)block;
+}
+
+/**
+ * os memblock put
+ *
+ * Puts the memory block back into the pool
+ *
+ * @param mp Pointer to memory pool
+ * @param block_addr Pointer to memory block
+ *
+ * @return os_error_t
+ */
+os_error_t
+os_memblock_put(struct os_mempool *mp, void *block_addr)
+{
+    os_sr_t sr;
+    struct os_memblock *block;
+
+    /* Make sure parameters are valid */
+    if ((mp == NULL) || (block_addr == NULL)) {
+        return OS_INVALID_PARM;
+    }
+
+#if MYNEWT_VAL(OS_MEMPOOL_CHECK)
+    /* Check that the block we are freeing is a valid block! */
+    assert(os_memblock_from(mp, block_addr));
+
+    /*
+     * Check for duplicate free.
+     */
+    SLIST_FOREACH(block, mp, mb_next) {
+        assert(block != (struct os_memblock *)block_addr);
+    }
+#endif
+    os_mempool_poison(block_addr, OS_MEMPOOL_TRUE_BLOCK_SIZE(mp));
+    block = (struct os_memblock *)block_addr;
+    OS_ENTER_CRITICAL(sr);
+
+    /* Chain current free list pointer to this block; make this block head */
+    SLIST_NEXT(block, mb_next) = SLIST_FIRST(mp);
+    SLIST_FIRST(mp) = block;
+
+    /* XXX: Should we check that the number free <= number blocks? */
+    /* Increment number free */
+    mp->mp_num_free++;
+
+    OS_EXIT_CRITICAL(sr);
+
+    return OS_OK;
+}
+
+
+struct os_mempool *
+os_mempool_info_get_next(struct os_mempool *mp, struct os_mempool_info *omi)
+{
+    struct os_mempool *cur;
+
+    if (mp == NULL) {
+        cur = STAILQ_FIRST(&g_os_mempool_list);
+    } else {
+        cur = STAILQ_NEXT(mp, mp_list);
+    }
+
+    if (cur == NULL) {
+        return (NULL);
+    }
+
+    omi->omi_block_size = cur->mp_block_size;
+    omi->omi_num_blocks = cur->mp_num_blocks;
+    omi->omi_num_free = cur->mp_num_free;
+    omi->omi_min_free = cur->mp_min_free;
+    strncpy(omi->omi_name, cur->name, sizeof(omi->omi_name));
+
+    return (cur);
+}
+
+
+/**
+ *   @} OSMempool
+ * @} OSKernel
+ */
diff --git a/porting/common/src/os/os_msys_init.c b/porting/common/src/os/os_msys_init.c
new file mode 100644
index 0000000..a907b41
--- /dev/null
+++ b/porting/common/src/os/os_msys_init.c
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+
+#include "../os/os_priv.h"
+#include "sysinit/sysinit.h"
+#include "syscfg/syscfg.h"
+#include "os/os_mempool.h"
+#include "mem/mem.h"
+
+#if MYNEWT_VAL(MSYS_1_BLOCK_COUNT) > 0
+#define SYSINIT_MSYS_1_MEMBLOCK_SIZE                \
+    OS_ALIGN(MYNEWT_VAL(MSYS_1_BLOCK_SIZE), 4)
+#define SYSINIT_MSYS_1_MEMPOOL_SIZE                 \
+    OS_MEMPOOL_SIZE(MYNEWT_VAL(MSYS_1_BLOCK_COUNT),  \
+                    SYSINIT_MSYS_1_MEMBLOCK_SIZE)
+static os_membuf_t os_msys_init_1_data[SYSINIT_MSYS_1_MEMPOOL_SIZE];
+static struct os_mbuf_pool os_msys_init_1_mbuf_pool;
+static struct os_mempool os_msys_init_1_mempool;
+#endif
+
+#if MYNEWT_VAL(MSYS_2_BLOCK_COUNT) > 0
+#define SYSINIT_MSYS_2_MEMBLOCK_SIZE                \
+    OS_ALIGN(MYNEWT_VAL(MSYS_2_BLOCK_SIZE), 4)
+#define SYSINIT_MSYS_2_MEMPOOL_SIZE                 \
+    OS_MEMPOOL_SIZE(MYNEWT_VAL(MSYS_2_BLOCK_COUNT),  \
+                    SYSINIT_MSYS_2_MEMBLOCK_SIZE)
+static os_membuf_t os_msys_init_2_data[SYSINIT_MSYS_2_MEMPOOL_SIZE];
+static struct os_mbuf_pool os_msys_init_2_mbuf_pool;
+static struct os_mempool os_msys_init_2_mempool;
+#endif
+
+static void
+os_msys_init_once(void *data, struct os_mempool *mempool,
+                  struct os_mbuf_pool *mbuf_pool,
+                  int block_count, int block_size, char *name)
+{
+    int rc;
+
+    rc = mem_init_mbuf_pool(data, mempool, mbuf_pool, block_count, block_size,
+                            name);
+    SYSINIT_PANIC_ASSERT(rc == 0);
+
+    rc = os_msys_register(mbuf_pool);
+    SYSINIT_PANIC_ASSERT(rc == 0);
+}
+
+void
+os_msys_init(void)
+{
+    os_msys_reset();
+
+    (void)os_msys_init_once;
+#if MYNEWT_VAL(MSYS_1_BLOCK_COUNT) > 0
+    os_msys_init_once(os_msys_init_1_data,
+                      &os_msys_init_1_mempool,
+                      &os_msys_init_1_mbuf_pool,
+                      MYNEWT_VAL(MSYS_1_BLOCK_COUNT),
+                      SYSINIT_MSYS_1_MEMBLOCK_SIZE,
+                      "msys_1");
+#endif
+
+#if MYNEWT_VAL(MSYS_2_BLOCK_COUNT) > 0
+    os_msys_init_once(os_msys_init_2_data,
+                      &os_msys_init_2_mempool,
+                      &os_msys_init_2_mbuf_pool,
+                      MYNEWT_VAL(MSYS_2_BLOCK_COUNT),
+                      SYSINIT_MSYS_2_MEMBLOCK_SIZE,
+                      "msys_2");
+#endif
+}
diff --git a/porting/common/src/os/os_mutex.c b/porting/common/src/os/os_mutex.c
new file mode 100644
index 0000000..117045f
--- /dev/null
+++ b/porting/common/src/os/os_mutex.c
@@ -0,0 +1,262 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "os/os.h"
+#include "os/os_trace_api.h"
+#include <assert.h>
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSMutex Mutexes
+ *   @{
+ */
+
+
+/**
+ * os mutex create
+ *
+ * Create a mutex and initialize it.
+ *
+ * @param mu Pointer to mutex
+ *
+ * @return os_error_t
+ *      OS_INVALID_PARM     Mutex passed in was NULL.
+ *      OS_OK               no error.
+ */
+os_error_t
+os_mutex_init(struct os_mutex *mu)
+{
+    if (!mu) {
+        return OS_INVALID_PARM;
+    }
+
+    os_trace_void(OS_TRACE_ID_MUTEX_INIT);
+    /* Initialize to 0 */
+    mu->mu_prio = 0;
+    mu->mu_level = 0;
+    mu->mu_owner = NULL;
+    SLIST_FIRST(&mu->mu_head) = NULL;
+    os_trace_end_call(OS_TRACE_ID_MUTEX_INIT);
+
+    return OS_OK;
+}
+
+/**
+ * os mutex release
+ *
+ * Release a mutex.
+ *
+ * @param mu Pointer to the mutex to be released
+ *
+ * @return os_error_t
+ *      OS_INVALID_PARM Mutex passed in was NULL.
+ *      OS_BAD_MUTEX    Mutex was not granted to current task (not owner).
+ *      OS_OK           No error
+ */
+os_error_t
+os_mutex_release(struct os_mutex *mu)
+{
+    int resched;
+    os_sr_t sr;
+    struct os_task *current;
+    struct os_task *rdy;
+
+    /* Check if OS is started */
+    if (!g_os_started) {
+        return (OS_NOT_STARTED);
+    }
+
+    /* Check for valid mutex */
+    if (!mu) {
+        return OS_INVALID_PARM;
+    }
+
+    /* We better own this mutex! */
+    current = os_sched_get_current_task();
+    if ((mu->mu_level == 0) || (mu->mu_owner != current)) {
+        return (OS_BAD_MUTEX);
+    }
+
+    /* Decrement nesting level by 1. If not zero, nested (so dont release!) */
+    --mu->mu_level;
+    if (mu->mu_level != 0) {
+        return (OS_OK);
+    }
+
+    OS_ENTER_CRITICAL(sr);
+    os_trace_void(OS_TRACE_ID_MUTEX_RELEASE);
+
+    /* Restore owner task's priority; resort list if different  */
+    if (current->t_prio != mu->mu_prio) {
+        current->t_prio = mu->mu_prio;
+        os_sched_resort(current);
+    }
+
+    /* Check if tasks are waiting for the mutex */
+    rdy = SLIST_FIRST(&mu->mu_head);
+    if (rdy) {
+        /* There is one waiting. Wake it up */
+        assert(rdy->t_obj);
+        os_sched_wakeup(rdy);
+
+        /* Set mutex internals */
+        mu->mu_level = 1;
+        mu->mu_prio = rdy->t_prio;
+    }
+
+    /* Set new owner of mutex (or NULL if not owned) */
+    mu->mu_owner = rdy;
+    if (rdy) {
+        rdy->t_lockcnt++;
+    }
+    --current->t_lockcnt;
+
+    /* Do we need to re-schedule? */
+    resched = 0;
+    rdy = os_sched_next_task();
+    if (rdy != current) {
+        resched = 1;
+    }
+    OS_EXIT_CRITICAL(sr);
+
+    /* Re-schedule if needed */
+    if (resched) {
+        os_sched(rdy);
+    }
+    os_trace_end_call(OS_TRACE_ID_MUTEX_RELEASE);
+
+    return OS_OK;
+}
+
+/**
+ * os mutex pend
+ *
+ * Pend (wait) for a mutex.
+ *
+ * @param mu Pointer to mutex.
+ * @param timeout Timeout, in os ticks. A timeout of 0 means do
+ *                not wait if not available. A timeout of
+ *                0xFFFFFFFF means wait forever.
+ *
+ *
+ * @return os_error_t
+ *      OS_INVALID_PARM     Mutex passed in was NULL.
+ *      OS_TIMEOUT          Mutex was owned by another task and timeout=0
+ *      OS_OK               no error.
+ */
+os_error_t
+os_mutex_pend(struct os_mutex *mu, uint32_t timeout)
+{
+    os_sr_t sr;
+    os_error_t rc;
+    struct os_task *current;
+    struct os_task *entry;
+    struct os_task *last;
+
+    /* OS must be started when calling this function */
+    if (!g_os_started) {
+        return (OS_NOT_STARTED);
+    }
+
+    /* Check for valid mutex */
+    if (!mu) {
+        return OS_INVALID_PARM;
+    }
+
+    OS_ENTER_CRITICAL(sr);
+
+    /* Is this owned? */
+    current = os_sched_get_current_task();
+    if (mu->mu_level == 0) {
+        mu->mu_owner = current;
+        mu->mu_prio  = current->t_prio;
+        current->t_lockcnt++;
+        mu->mu_level = 1;
+        OS_EXIT_CRITICAL(sr);
+        return OS_OK;
+    }
+
+    /* Are we owner? */
+    if (mu->mu_owner == current) {
+        ++mu->mu_level;
+        OS_EXIT_CRITICAL(sr);
+        return OS_OK;
+    }
+
+    /* Mutex is not owned by us. If timeout is 0, return immediately */
+    if (timeout == 0) {
+        OS_EXIT_CRITICAL(sr);
+        return OS_TIMEOUT;
+    }
+
+    os_trace_void(OS_TRACE_ID_MUTEX_PEND);
+
+    /* Change priority of owner if needed */
+    if (mu->mu_owner->t_prio > current->t_prio) {
+        mu->mu_owner->t_prio = current->t_prio;
+        os_sched_resort(mu->mu_owner);
+    }
+
+    /* Link current task to tasks waiting for mutex */
+    last = NULL;
+    if (!SLIST_EMPTY(&mu->mu_head)) {
+        /* Insert in priority order */
+        SLIST_FOREACH(entry, &mu->mu_head, t_obj_list) {
+            if (current->t_prio < entry->t_prio) {
+                break;
+            }
+            last = entry;
+        }
+    }
+
+    if (last) {
+        SLIST_INSERT_AFTER(last, current, t_obj_list);
+    } else {
+        SLIST_INSERT_HEAD(&mu->mu_head, current, t_obj_list);
+    }
+
+    /* Set mutex pointer in task */
+    current->t_obj = mu;
+    current->t_flags |= OS_TASK_FLAG_MUTEX_WAIT;
+    os_sched_sleep(current, timeout);
+    OS_EXIT_CRITICAL(sr);
+
+    os_sched(NULL);
+
+    OS_ENTER_CRITICAL(sr);
+    current->t_flags &= ~OS_TASK_FLAG_MUTEX_WAIT;
+    OS_EXIT_CRITICAL(sr);
+
+    /* If we are owner we did not time out. */
+    if (mu->mu_owner == current) {
+        rc = OS_OK;
+    } else {
+        rc = OS_TIMEOUT;
+    }
+    os_trace_end_call(OS_TRACE_ID_MUTEX_PEND);
+
+    return rc;
+}
+
+
+/**
+ *   @} OSMutex
+ * @} OSKernel
+ */
diff --git a/porting/common/src/os/os_priv.h b/porting/common/src/os/os_priv.h
new file mode 100644
index 0000000..be7f458
--- /dev/null
+++ b/porting/common/src/os/os_priv.h
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef H_OS_PRIV_
+#define H_OS_PRIV_
+
+#include "os/queue.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern struct os_task g_idle_task;
+extern struct os_task_list g_os_run_list;
+extern struct os_task_list g_os_sleep_list;
+extern struct os_task_stailq g_os_task_list;
+extern struct os_callout_list g_callout_list;
+
+void os_msys_init(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/porting/common/src/os/os_sanity.c b/porting/common/src/os/os_sanity.c
new file mode 100644
index 0000000..5b96711
--- /dev/null
+++ b/porting/common/src/os/os_sanity.c
@@ -0,0 +1,250 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <string.h>
+
+#include "os/os.h"
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSSanity Sanity
+ *   @{
+ */
+
+SLIST_HEAD(, os_sanity_check) g_os_sanity_check_list =
+    SLIST_HEAD_INITIALIZER(os_sanity_check_list);
+
+struct os_mutex g_os_sanity_check_mu;
+
+/**
+ * Initialize a sanity check
+ *
+ * @param sc The sanity check to initialize
+ *
+ * @return 0 on success, error code on failure.
+ */
+int
+os_sanity_check_init(struct os_sanity_check *sc)
+{
+    memset(sc, 0, sizeof(*sc));
+
+    return (0);
+}
+
+/**
+ * Lock the sanity check list
+ *
+ * @return 0 on success, error code on failure.
+ */
+static int
+os_sanity_check_list_lock(void)
+{
+    int rc;
+
+    if (!g_os_started) {
+        return (0);
+    }
+
+    rc = os_mutex_pend(&g_os_sanity_check_mu, OS_WAIT_FOREVER);
+    if (rc != OS_OK) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * Unlock the sanity check list
+ *
+ * @return 0 on success, error code on failure
+ */
+static int
+os_sanity_check_list_unlock(void)
+{
+    int rc;
+
+    if (!g_os_started) {
+        return (0);
+    }
+
+    rc = os_mutex_release(&g_os_sanity_check_mu);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ * Provide a "task checkin" for the sanity task.
+ *
+ * @param t The task to check in
+ *
+ * @return 0 on success, error code on failure
+ */
+int
+os_sanity_task_checkin(struct os_task *t)
+{
+    int rc;
+
+    if (t == NULL) {
+        t = os_sched_get_current_task();
+    }
+
+    rc = os_sanity_check_reset(&t->t_sanity_check);
+    if (rc != OS_OK) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+
+/**
+ * Register a sanity check
+ *
+ * @param sc The sanity check to register
+ *
+ * @return 0 on success, error code on failure
+ */
+int
+os_sanity_check_register(struct os_sanity_check *sc)
+{
+    int rc;
+
+    rc = os_sanity_check_list_lock();
+    if (rc != OS_OK) {
+        goto err;
+    }
+
+    SLIST_INSERT_HEAD(&g_os_sanity_check_list, sc, sc_next);
+
+    rc = os_sanity_check_list_unlock();
+    if (rc != OS_OK) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+
+/**
+ * Reset the os sanity check, so that it doesn't trip up the
+ * sanity timer.
+ *
+ * @param sc The sanity check to reset
+ *
+ * @return 0 on success, error code on failure
+ */
+int
+os_sanity_check_reset(struct os_sanity_check *sc)
+{
+    int rc;
+
+    rc = os_sanity_check_list_lock();
+    if (rc != OS_OK) {
+        goto err;
+    }
+
+    sc->sc_checkin_last = os_time_get();
+
+    rc = os_sanity_check_list_unlock();
+    if (rc != OS_OK) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+/*
+ * Called from the IDLE task context, every MYNEWT_VAL(SANITY_INTERVAL) msecs.
+ *
+ * Goes through the sanity check list, and performs sanity checks.  If any of
+ * these checks failed, or tasks have not checked in, it resets the processor.
+ */
+void
+os_sanity_run(void)
+{
+    struct os_sanity_check *sc;
+    int rc;
+
+    rc = os_sanity_check_list_lock();
+    if (rc != 0) {
+        assert(0);
+    }
+
+    SLIST_FOREACH(sc, &g_os_sanity_check_list, sc_next) {
+        rc = OS_OK;
+
+        if (sc->sc_func) {
+            rc = sc->sc_func(sc, sc->sc_arg);
+            if (rc == OS_OK) {
+                sc->sc_checkin_last = os_time_get();
+                continue;
+            }
+        }
+
+        if (OS_TIME_TICK_GT(os_time_get(),
+                    sc->sc_checkin_last + sc->sc_checkin_itvl)) {
+            assert(0);
+        }
+    }
+
+    rc = os_sanity_check_list_unlock();
+    if (rc != 0) {
+        assert(0);
+    }
+}
+
+/**
+ * Initialize the sanity task and mutex.
+ *
+ * @return 0 on success, error code on failure
+ */
+int
+os_sanity_init(void)
+{
+    int rc;
+
+    rc = os_mutex_init(&g_os_sanity_check_mu);
+    if (rc != 0) {
+        goto err;
+    }
+
+    return (0);
+err:
+    return (rc);
+}
+
+/**
+ *   @} OSSanity
+ * @} OSKernel
+ */
diff --git a/porting/common/src/os/os_sched.c b/porting/common/src/os/os_sched.c
new file mode 100644
index 0000000..9204a73
--- /dev/null
+++ b/porting/common/src/os/os_sched.c
@@ -0,0 +1,377 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "os/os.h"
+#include "os/os_trace_api.h"
+#include "os/queue.h"
+#include <assert.h>
+#include "../os/os_priv.h"
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSSched Scheduler
+ *   @{
+ */
+
+struct os_task_list g_os_run_list = TAILQ_HEAD_INITIALIZER(g_os_run_list);
+struct os_task_list g_os_sleep_list = TAILQ_HEAD_INITIALIZER(g_os_sleep_list);
+
+struct os_task *g_current_task;
+
+extern os_time_t g_os_time;
+os_time_t g_os_last_ctx_sw_time;
+
+/**
+ * os sched insert
+ *
+ * Insert a task into the scheduler list. This causes the task to be evaluated
+ * for running when os_sched is called.
+ *
+ * @param t     Pointer to task to insert in run list
+ *
+ * @return int  OS_OK: task was inserted into run list
+ *              OS_EINVAL: Task was not in ready state.
+ */
+os_error_t
+os_sched_insert(struct os_task *t)
+{
+    struct os_task *entry;
+    os_sr_t sr;
+    os_error_t rc;
+
+    if (t->t_state != OS_TASK_READY) {
+        rc = OS_EINVAL;
+        goto err;
+    }
+
+    entry = NULL;
+    OS_ENTER_CRITICAL(sr);
+    TAILQ_FOREACH(entry, &g_os_run_list, t_os_list) {
+        if (t->t_prio < entry->t_prio) {
+            break;
+        }
+    }
+    if (entry) {
+        TAILQ_INSERT_BEFORE(entry, (struct os_task *) t, t_os_list);
+    } else {
+        TAILQ_INSERT_TAIL(&g_os_run_list, (struct os_task *) t, t_os_list);
+    }
+    OS_EXIT_CRITICAL(sr);
+
+    return (0);
+err:
+    return (rc);
+}
+
+void
+os_sched_ctx_sw_hook(struct os_task *next_t)
+{
+#if MYNEWT_VAL(OS_CTX_SW_STACK_CHECK)
+    os_stack_t *top;
+    int i;
+
+    top = g_current_task->t_stacktop - g_current_task->t_stacksize;
+    for (i = 0; i < MYNEWT_VAL(OS_CTX_SW_STACK_GUARD); i++) {
+        assert(top[i] == OS_STACK_PATTERN);
+    }
+#endif
+    os_trace_task_start_exec(next_t->t_taskid);
+    next_t->t_ctx_sw_cnt++;
+    g_current_task->t_run_time += g_os_time - g_os_last_ctx_sw_time;
+    g_os_last_ctx_sw_time = g_os_time;
+}
+
+/**
+ * os sched get current task
+ *
+ * Returns the currently running task. Note that this task may or may not be
+ * the highest priority task ready to run.
+ *
+ *
+ * @return struct os_task*
+ */
+struct os_task *
+os_sched_get_current_task(void)
+{
+    return (g_current_task);
+}
+
+/**
+ * os sched set current task
+ *
+ * Sets the currently running task to 't'. Note that this function simply sets
+ * the global variable holding the currently running task. It does not perform
+ * a context switch or change the os run or sleep list.
+ *
+ * @param t Pointer to currently running task.
+ */
+void
+os_sched_set_current_task(struct os_task *t)
+{
+    g_current_task = t;
+}
+
+/**
+ * os sched
+ *
+ * Performs a context switch. When called, it will either find the highest
+ * priority task ready to run if next_t is NULL (i.e. the head of the os run
+ * list) or will schedule next_t as the task to run.
+ *
+ * @param next_t Task to run
+ */
+void
+os_sched(struct os_task *next_t)
+{
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+
+    if (!next_t) {
+        next_t = os_sched_next_task();
+    }
+
+    os_arch_ctx_sw(next_t);
+
+    OS_EXIT_CRITICAL(sr);
+}
+
+/**
+ * os sched sleep
+ *
+ * Removes the task from the run list and puts it on the sleep list.
+ *
+ * @param t Task to put to sleep
+ * @param nticks Number of ticks to put task to sleep
+ *
+ * @return int
+ *
+ * NOTE: must be called with interrupts disabled! This function does not call
+ * the scheduler
+ */
+int
+os_sched_sleep(struct os_task *t, os_time_t nticks)
+{
+    struct os_task *entry;
+
+    entry = NULL;
+
+    TAILQ_REMOVE(&g_os_run_list, t, t_os_list);
+    t->t_state = OS_TASK_SLEEP;
+    t->t_next_wakeup = os_time_get() + nticks;
+    if (nticks == OS_TIMEOUT_NEVER) {
+        t->t_flags |= OS_TASK_FLAG_NO_TIMEOUT;
+        TAILQ_INSERT_TAIL(&g_os_sleep_list, t, t_os_list);
+    } else {
+        TAILQ_FOREACH(entry, &g_os_sleep_list, t_os_list) {
+            if ((entry->t_flags & OS_TASK_FLAG_NO_TIMEOUT) ||
+                    OS_TIME_TICK_GT(entry->t_next_wakeup, t->t_next_wakeup)) {
+                break;
+            }
+        }
+        if (entry) {
+            TAILQ_INSERT_BEFORE(entry, t, t_os_list);
+        } else {
+            TAILQ_INSERT_TAIL(&g_os_sleep_list, t, t_os_list);
+        }
+    }
+
+    os_trace_task_stop_ready(t->t_taskid, OS_TASK_SLEEP);
+    return (0);
+}
+
+/**
+ * os sched remove
+ *
+ * XXX
+ * NOTE - This routine is currently experimental and not ready for common use
+ *
+ * Stops a task and removes it from the task list.
+ *
+ * @return int
+ *
+ * NOTE: must be called with interrupts disabled! This function does not call
+ * the scheduler
+ */
+int
+os_sched_remove(struct os_task *t)
+{
+
+    if (t->t_state == OS_TASK_SLEEP) {
+        TAILQ_REMOVE(&g_os_sleep_list, t, t_os_list);
+    } else if (t->t_state == OS_TASK_READY) {
+        TAILQ_REMOVE(&g_os_run_list, t, t_os_list);
+    }
+    t->t_next_wakeup = 0;
+    t->t_flags |= OS_TASK_FLAG_NO_TIMEOUT;
+
+    STAILQ_REMOVE(&g_os_task_list, t, os_task, t_os_task_list);
+
+    os_trace_task_stop_exec();
+    return OS_OK;
+}
+
+/**
+ * os sched wakeup
+ *
+ * Called to wake up a task. Waking up a task consists of setting the task state
+ * to READY and moving it from the sleep list to the run list.
+ *
+ * @param t     Pointer to task to wake up.
+ *
+ * @return int
+ *
+ * NOTE: This function must be called with interrupts disabled.
+ */
+int
+os_sched_wakeup(struct os_task *t)
+{
+    struct os_task_obj *os_obj;
+
+    assert(t->t_state == OS_TASK_SLEEP);
+
+    /* Remove self from object list if waiting on one */
+    if (t->t_obj) {
+        os_obj = (struct os_task_obj *)t->t_obj;
+        assert(!SLIST_EMPTY(&os_obj->obj_head));
+        SLIST_REMOVE(&os_obj->obj_head, t, os_task, t_obj_list);
+        SLIST_NEXT(t, t_obj_list) = NULL;
+        t->t_obj = NULL;
+    }
+
+    /* Remove task from sleep list */
+    t->t_state = OS_TASK_READY;
+    t->t_next_wakeup = 0;
+    t->t_flags &= ~OS_TASK_FLAG_NO_TIMEOUT;
+    TAILQ_REMOVE(&g_os_sleep_list, t, t_os_list);
+    os_sched_insert(t);
+
+    return (0);
+}
+
+/**
+ * os sched os timer exp
+ *
+ * Called when the OS tick timer expires. Search the sleep list for any tasks
+ * that need waking up. This occurs when the current OS time exceeds the next
+ * wakeup time stored in the task. Any tasks that need waking up will be
+ * removed from the sleep list and added to the run list.
+ *
+ */
+void
+os_sched_os_timer_exp(void)
+{
+    struct os_task *t;
+    struct os_task *next;
+    os_time_t now;
+    os_sr_t sr;
+
+    now = os_time_get();
+
+    OS_ENTER_CRITICAL(sr);
+
+    /*
+     * Wakeup any tasks that have their sleep timer expired
+     */
+    t = TAILQ_FIRST(&g_os_sleep_list);
+    while (t) {
+        /* If task waiting forever, do not check next wakeup time */
+        if (t->t_flags & OS_TASK_FLAG_NO_TIMEOUT) {
+            break;
+        }
+        next = TAILQ_NEXT(t, t_os_list);
+        if (OS_TIME_TICK_GEQ(now, t->t_next_wakeup)) {
+            os_trace_task_start_ready(t->t_taskid);
+            os_sched_wakeup(t);
+        } else {
+            break;
+        }
+        t = next;
+    }
+
+    OS_EXIT_CRITICAL(sr);
+}
+
+/*
+ * Return the number of ticks until the first sleep timer expires.If there are
+ * no such tasks then return OS_TIMEOUT_NEVER instead.
+ */
+os_time_t
+os_sched_wakeup_ticks(os_time_t now)
+{
+    os_time_t rt;
+    struct os_task *t;
+
+    OS_ASSERT_CRITICAL();
+
+    t = TAILQ_FIRST(&g_os_sleep_list);
+    if (t == NULL || (t->t_flags & OS_TASK_FLAG_NO_TIMEOUT)) {
+        rt = OS_TIMEOUT_NEVER;
+    } else if (OS_TIME_TICK_GEQ(t->t_next_wakeup, now)) {
+        rt = t->t_next_wakeup - now;
+    } else {
+        rt = 0;     /* wakeup time was in the past */
+    }
+    return (rt);
+}
+
+/**
+ * os sched next task
+ *
+ * Returns the task that we should be running. This is the task at the head
+ * of the run list.
+ *
+ * NOTE: if you want to guarantee that the os run list does not change after
+ * calling this function you have to call it with interrupts disabled.
+ *
+ * @return struct os_task*
+ */
+struct os_task *
+os_sched_next_task(void)
+{
+    return (TAILQ_FIRST(&g_os_run_list));
+}
+
+/**
+ * os sched resort
+ *
+ * Resort a task that is in the ready list as its priority has
+ * changed. If the task is not in the ready state, there is
+ * nothing to do.
+ *
+ * @param t Pointer to task to insert back into ready to run
+ *          list.
+ *
+ * NOTE: this function expects interrupts to be disabled so they
+ * are not disabled here.
+ */
+void
+os_sched_resort(struct os_task *t)
+{
+    if (t->t_state == OS_TASK_READY) {
+        TAILQ_REMOVE(&g_os_run_list, t, t_os_list);
+        os_sched_insert(t);
+    }
+}
+
+/**
+ *   @} OSSched
+ * @} OSKernel
+ */
diff --git a/porting/common/src/os/os_sem.c b/porting/common/src/os/os_sem.c
new file mode 100644
index 0000000..7566087
--- /dev/null
+++ b/porting/common/src/os/os_sem.c
@@ -0,0 +1,225 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "os/os.h"
+#include <assert.h>
+
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSSem Semaphores
+ *   @{
+ */
+
+/* XXX:
+ * 1) Should I check to see if we are within an ISR for some of these?
+ * 2) Would I do anything different for os_sem_release() if we were in an
+ *    ISR when this was called?
+ */
+
+/**
+ * os sem initialize
+ *
+ * Initialize a semaphore
+ *
+ * @param sem Pointer to semaphore
+ *        tokens: # of tokens the semaphore should contain initially.
+ *
+ * @return os_error_t
+ *      OS_INVALID_PARM     Semaphore passed in was NULL.
+ *      OS_OK               no error.
+ */
+os_error_t
+os_sem_init(struct os_sem *sem, uint16_t tokens)
+{
+    if (!sem) {
+        return OS_INVALID_PARM;
+    }
+
+    sem->sem_tokens = tokens;
+    SLIST_FIRST(&sem->sem_head) = NULL;
+
+    return OS_OK;
+}
+
+/**
+ * os sem release
+ *
+ * Release a semaphore.
+ *
+ * @param sem Pointer to the semaphore to be released
+ *
+ * @return os_error_t
+ *      OS_INVALID_PARM Semaphore passed in was NULL.
+ *      OS_OK No error
+ */
+os_error_t
+os_sem_release(struct os_sem *sem)
+{
+    int resched;
+    os_sr_t sr;
+    struct os_task *current;
+    struct os_task *rdy;
+
+    /* OS must be started to release semaphores */
+    if (!g_os_started) {
+        return (OS_NOT_STARTED);
+    }
+
+    /* Check for valid semaphore */
+    if (!sem) {
+        return OS_INVALID_PARM;
+    }
+
+    /* Get current task */
+    resched = 0;
+    current = os_sched_get_current_task();
+
+    OS_ENTER_CRITICAL(sr);
+
+    /* Check if tasks are waiting for the semaphore */
+    rdy = SLIST_FIRST(&sem->sem_head);
+    if (rdy) {
+        /* Clear flag that we are waiting on the semaphore; wake up task */
+        rdy->t_flags &= ~OS_TASK_FLAG_SEM_WAIT;
+        os_sched_wakeup(rdy);
+
+        /* Schedule if waiting task higher priority */
+        if (current->t_prio > rdy->t_prio) {
+            resched = 1;
+        }
+    } else {
+        /* Add to the number of tokens */
+        sem->sem_tokens++;
+    }
+
+    OS_EXIT_CRITICAL(sr);
+
+    /* Re-schedule if needed */
+    if (resched) {
+        os_sched(rdy);
+    }
+
+    return OS_OK;
+}
+
+/**
+ * os sem pend
+ *
+ * Pend (wait) for a semaphore.
+ *
+ * @param mu Pointer to semaphore.
+ * @param timeout Timeout, in os ticks. A timeout of 0 means do
+ *                not wait if not available. A timeout of
+ *                0xFFFFFFFF means wait forever.
+ *
+ *
+ * @return os_error_t
+ *      OS_INVALID_PARM     Semaphore passed in was NULL.
+ *      OS_TIMEOUT          Semaphore was owned by another task and timeout=0
+ *      OS_OK               no error.
+ */
+os_error_t
+os_sem_pend(struct os_sem *sem, uint32_t timeout)
+{
+    os_sr_t sr;
+    os_error_t rc;
+    int sched;
+    struct os_task *current;
+    struct os_task *entry;
+    struct os_task *last;
+
+    /* Check if OS is started */
+    if (!g_os_started) {
+        return (OS_NOT_STARTED);
+    }
+
+    /* Check for valid semaphore */
+    if (!sem) {
+        return OS_INVALID_PARM;
+    }
+
+    /* Assume we dont have to put task to sleep; get current task */
+    sched = 0;
+    current = os_sched_get_current_task();
+
+    OS_ENTER_CRITICAL(sr);
+
+    /*
+     * If there is a token available, take it. If no token, either return
+     * with error if timeout was 0 or put this task to sleep.
+     */
+    if (sem->sem_tokens != 0) {
+        sem->sem_tokens--;
+        rc = OS_OK;
+    } else if (timeout == 0) {
+        rc = OS_TIMEOUT;
+    } else {
+        /* Silence gcc maybe-uninitialized warning. */
+        rc = OS_OK;
+
+        /* Link current task to tasks waiting for semaphore */
+        current->t_obj = sem;
+        current->t_flags |= OS_TASK_FLAG_SEM_WAIT;
+        last = NULL;
+        if (!SLIST_EMPTY(&sem->sem_head)) {
+            /* Insert in priority order */
+            SLIST_FOREACH(entry, &sem->sem_head, t_obj_list) {
+                if (current->t_prio < entry->t_prio) {
+                    break;
+                }
+                last = entry;
+            }
+        }
+
+        if (last) {
+            SLIST_INSERT_AFTER(last, current, t_obj_list);
+        } else {
+            SLIST_INSERT_HEAD(&sem->sem_head, current, t_obj_list);
+        }
+
+        /* We will put this task to sleep */
+        sched = 1;
+        os_sched_sleep(current, timeout);
+    }
+
+    OS_EXIT_CRITICAL(sr);
+
+    if (sched) {
+        os_sched(NULL);
+        /* Check if we timed out or got the semaphore */
+        if (current->t_flags & OS_TASK_FLAG_SEM_WAIT) {
+            OS_ENTER_CRITICAL(sr);
+            current->t_flags &= ~OS_TASK_FLAG_SEM_WAIT;
+            OS_EXIT_CRITICAL(sr);
+            rc = OS_TIMEOUT;
+        } else {
+            rc = OS_OK;
+        }
+    }
+
+    return rc;
+}
+
+
+/**
+ *   @} OSSched
+ * @} OSKernel
+ */
diff --git a/porting/common/src/os/os_task.c b/porting/common/src/os/os_task.c
new file mode 100644
index 0000000..4f96209
--- /dev/null
+++ b/porting/common/src/os/os_task.c
@@ -0,0 +1,284 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+#include "os/os.h"
+#include "os/os_trace_api.h"
+
+#include <assert.h>
+#include <string.h>
+#include "../os/os_priv.h"
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSTask Tasks
+ *   @{
+ */
+
+uint8_t g_task_id;
+
+struct os_task_stailq g_os_task_list;
+
+static void
+_clear_stack(os_stack_t *stack_bottom, int size)
+{
+    int i;
+
+    for (i = 0; i < size; i++) {
+        stack_bottom[i] = OS_STACK_PATTERN;
+    }
+}
+
+static inline uint8_t
+os_task_next_id(void)
+{
+    uint8_t rc;
+    os_sr_t sr;
+
+    OS_ENTER_CRITICAL(sr);
+    rc = g_task_id;
+    g_task_id++;
+    OS_EXIT_CRITICAL(sr);
+
+    return (rc);
+}
+
+/**
+ * Return the number of tasks initialized.
+ *
+ * @return number of tasks initialized
+ */
+uint8_t
+os_task_count(void)
+{
+    return (g_task_id);
+}
+
+/**
+ * Initialize a task.
+ *
+ * This function initializes the task structure pointed to by t,
+ * clearing and setting it's stack pointer, provides sane defaults
+ * and sets the task as ready to run, and inserts it into the operating
+ * system scheduler.
+ *
+ * @param t The task to initialize
+ * @param name The name of the task to initialize
+ * @param func The task function to call
+ * @param arg The argument to pass to this task function
+ * @param prio The priority at which to run this task
+ * @param sanity_itvl The time at which this task should check in with the
+ *                    sanity task.  OS_WAIT_FOREVER means never check in
+ *                    here.
+ * @param stack_bottom A pointer to the bottom of a task's stack
+ * @param stack_size The overall size of the task's stack.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+os_task_init(struct os_task *t, const char *name, os_task_func_t func,
+        void *arg, uint8_t prio, os_time_t sanity_itvl,
+        os_stack_t *stack_bottom, uint16_t stack_size)
+{
+    struct os_sanity_check *sc;
+    int rc;
+    struct os_task *task;
+
+    memset(t, 0, sizeof(*t));
+
+    t->t_func = func;
+    t->t_arg = arg;
+
+    t->t_taskid = os_task_next_id();
+    t->t_prio = prio;
+
+    t->t_state = OS_TASK_READY;
+    t->t_name = name;
+    t->t_next_wakeup = 0;
+
+    rc = os_sanity_check_init(&t->t_sanity_check);
+    if (rc != OS_OK) {
+        goto err;
+    }
+
+    if (sanity_itvl != OS_WAIT_FOREVER) {
+        sc = (struct os_sanity_check *) &t->t_sanity_check;
+        sc->sc_checkin_itvl = sanity_itvl;
+
+        rc = os_sanity_check_register(sc);
+        if (rc != OS_OK) {
+            goto err;
+        }
+    }
+
+    _clear_stack(stack_bottom, stack_size);
+    t->t_stacktop = &stack_bottom[stack_size];
+    t->t_stacksize = stack_size;
+    t->t_stackptr = os_arch_task_stack_init(t, t->t_stacktop,
+            t->t_stacksize);
+
+    STAILQ_FOREACH(task, &g_os_task_list, t_os_task_list) {
+        assert(t->t_prio != task->t_prio);
+    }
+
+    /* insert this task into the task list */
+    STAILQ_INSERT_TAIL(&g_os_task_list, t, t_os_task_list);
+
+    /* insert this task into the scheduler list */
+    rc = os_sched_insert(t);
+    if (rc != OS_OK) {
+        goto err;
+    }
+
+    os_trace_task_info(t);
+
+    return (0);
+err:
+    return (rc);
+}
+
+/*
+ * Removes specified task
+ * XXX
+ * NOTE: This interface is currently experimental and not ready for common use
+ */
+int
+os_task_remove(struct os_task *t)
+{
+    struct os_task *current;
+    int rc;
+    os_sr_t sr;
+
+    current = os_sched_get_current_task();
+    /*
+     * Can't suspend yourself
+     */
+    if (t->t_taskid == current->t_taskid) {
+        return OS_INVALID_PARM;
+    }
+
+    /*
+     * If state is not READY or SLEEP, assume task has not been initialized
+     */
+    if (t->t_state != OS_TASK_READY && t->t_state != OS_TASK_SLEEP)
+    {
+        return OS_NOT_STARTED;
+    }
+
+    /*
+     * Disallow suspending tasks which are waiting on a lock
+     */
+    if (t->t_flags & (OS_TASK_FLAG_SEM_WAIT | OS_TASK_FLAG_MUTEX_WAIT |
+                                               OS_TASK_FLAG_EVQ_WAIT)) {
+        return OS_EBUSY;
+    }
+
+    /*
+     * Disallowing suspending tasks which are holding a mutex
+     */
+    if (t->t_lockcnt) {
+        return OS_EBUSY;
+    }
+
+    OS_ENTER_CRITICAL(sr);
+    rc = os_sched_remove(t);
+    OS_EXIT_CRITICAL(sr);
+    return rc;
+}
+
+/**
+ * Iterate through tasks, and return the following information about them:
+ *
+ * - Priority
+ * - Task ID
+ * - State (ACTIVE, SLEEP)
+ * - Total Stack Usage
+ * - Stack Size
+ * - Context Switch Count
+ * - Runtime
+ * - Last & Next Sanity checkin
+ * - Task Name
+ *
+ * To get the first task in the list, call os_task_info_get_next() with a
+ * NULL pointer in the prev argument, and os_task_info_get_next() will
+ * return a pointer to the task structure, and fill out the os_task_info
+ * structure pointed to by oti.
+ *
+ * To get the next task in the list, provide the task structure returned
+ * by the previous call to os_task_info_get_next(), and os_task_info_get_next()
+ * will fill out the task structure pointed to by oti again, and return
+ * the next task in the list.
+ *
+ * @param prev The previous task returned by os_task_info_get_next(), or NULL
+ *             to begin iteration.
+ * @param oti  The OS task info structure to fill out.
+ *
+ * @return A pointer to the OS task that has been read, or NULL when finished
+ *         iterating through all tasks.
+ */
+struct os_task *
+os_task_info_get_next(const struct os_task *prev, struct os_task_info *oti)
+{
+    struct os_task *next;
+    os_stack_t *top;
+    os_stack_t *bottom;
+
+    if (prev != NULL) {
+        next = STAILQ_NEXT(prev, t_os_task_list);
+    } else {
+        next = STAILQ_FIRST(&g_os_task_list);
+    }
+
+    if (next == NULL) {
+        return (NULL);
+    }
+
+    /* Otherwise, copy OS task information into the OTI structure, and
+     * return 1, which means continue
+     */
+    oti->oti_prio = next->t_prio;
+    oti->oti_taskid = next->t_taskid;
+    oti->oti_state = next->t_state;
+
+    top = next->t_stacktop;
+    bottom = next->t_stacktop - next->t_stacksize;
+    while (bottom < top) {
+        if (*bottom != OS_STACK_PATTERN) {
+            break;
+        }
+        ++bottom;
+    }
+
+    oti->oti_stkusage = (uint16_t) (next->t_stacktop - bottom);
+    oti->oti_stksize = next->t_stacksize;
+    oti->oti_cswcnt = next->t_ctx_sw_cnt;
+    oti->oti_runtime = next->t_run_time;
+    oti->oti_last_checkin = next->t_sanity_check.sc_checkin_last;
+    oti->oti_next_checkin = next->t_sanity_check.sc_checkin_last +
+        next->t_sanity_check.sc_checkin_itvl;
+    strncpy(oti->oti_name, next->t_name, sizeof(oti->oti_name));
+
+    return (next);
+}
+
+/**
+ *   @} OSTask
+ * @} OSKernel
+ */
diff --git a/porting/common/src/os/os_time.c b/porting/common/src/os/os_time.c
new file mode 100644
index 0000000..3f6816d
--- /dev/null
+++ b/porting/common/src/os/os_time.c
@@ -0,0 +1,268 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+#include "syscfg/syscfg.h"
+
+#include <assert.h>
+
+#include "os/os.h"
+#include "os/queue.h"
+
+/**
+ * @addtogroup OSKernel
+ * @{
+ *   @defgroup OSTime Time
+ *   @{
+ */
+
+CTASSERT(sizeof(os_time_t) == 4);
+
+#define OS_USEC_PER_TICK    (1000000 / OS_TICKS_PER_SEC)
+
+os_time_t g_os_time;
+
+/*
+ * Time-of-day collateral.
+ */
+static struct {
+    os_time_t ostime;
+    struct os_timeval uptime;
+    struct os_timeval utctime;
+    struct os_timezone timezone;
+} basetod;
+
+static void
+os_deltatime(os_time_t delta, const struct os_timeval *base,
+    struct os_timeval *result)
+{
+    struct os_timeval tvdelta;
+
+    tvdelta.tv_sec = delta / OS_TICKS_PER_SEC;
+    tvdelta.tv_usec = (delta % OS_TICKS_PER_SEC) * OS_USEC_PER_TICK;
+    os_timeradd(base, &tvdelta, result);
+}
+
+/**
+ * Get the current OS time in ticks
+ *
+ * @return OS time in ticks
+ */
+os_time_t
+os_time_get(void)
+{
+    return (g_os_time);
+}
+
+#if MYNEWT_VAL(OS_SCHEDULING)
+static void
+os_time_tick(int ticks)
+{
+    os_sr_t sr;
+    os_time_t delta, prev_os_time;
+
+    assert(ticks >= 0);
+
+    OS_ENTER_CRITICAL(sr);
+    prev_os_time = g_os_time;
+    g_os_time += ticks;
+
+    /*
+     * Update 'basetod' when 'g_os_time' crosses the 0x00000000 and
+     * 0x80000000 thresholds.
+     */
+    if ((prev_os_time ^ g_os_time) >> 31) {
+        delta = g_os_time - basetod.ostime;
+        os_deltatime(delta, &basetod.uptime, &basetod.uptime);
+        os_deltatime(delta, &basetod.utctime, &basetod.utctime);
+        basetod.ostime = g_os_time;
+    }
+    OS_EXIT_CRITICAL(sr);
+}
+
+/**
+ * Move OS time forward ticks.
+ *
+ * @param ticks The number of ticks to move time forward.
+ */
+void
+os_time_advance(int ticks)
+{
+    assert(ticks >= 0);
+
+    if (ticks > 0) {
+        if (!os_started()) {
+            g_os_time += ticks;
+        } else {
+            os_time_tick(ticks);
+            os_callout_tick();
+            os_sched_os_timer_exp();
+            os_sched(NULL);
+        }
+    }
+}
+#else
+void
+os_time_advance(int ticks)
+{
+    g_os_time += ticks;
+}
+#endif
+
+/**
+ * Puts the current task to sleep for the specified number of os ticks. There
+ * is no delay if ticks is <= 0.
+ *
+ * @param osticks Number of ticks to delay (<= 0 means no delay).
+ */
+void
+os_time_delay(int32_t osticks)
+{
+    os_sr_t sr;
+
+    if (osticks > 0) {
+        OS_ENTER_CRITICAL(sr);
+        os_sched_sleep(os_sched_get_current_task(), (os_time_t)osticks);
+        OS_EXIT_CRITICAL(sr);
+        os_sched(NULL);
+    }
+}
+
+/**
+ * Set the time of day.  This does not modify os time, but rather just modifies
+ * the offset by which we are tracking real time against os time.
+ *
+ * @param utctime A timeval representing the UTC time we are setting
+ * @param tz The time-zone to apply against the utctime being set.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+os_settimeofday(struct os_timeval *utctime, struct os_timezone *tz)
+{
+    os_sr_t sr;
+    os_time_t delta;
+
+    OS_ENTER_CRITICAL(sr);
+    if (utctime != NULL) {
+        /*
+         * Update all time-of-day base values.
+         */
+        delta = os_time_get() - basetod.ostime;
+        os_deltatime(delta, &basetod.uptime, &basetod.uptime);
+        basetod.utctime = *utctime;
+        basetod.ostime += delta;
+    }
+
+    if (tz != NULL) {
+        basetod.timezone = *tz;
+    }
+    OS_EXIT_CRITICAL(sr);
+
+    return (0);
+}
+
+/**
+ * Get the current time of day.  Returns the time of day in UTC
+ * into the tv argument, and returns the timezone (if set) into
+ * tz.
+ *
+ * @param tv The structure to put the UTC time of day into
+ * @param tz The structure to put the timezone information into
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+os_gettimeofday(struct os_timeval *tv, struct os_timezone *tz)
+{
+    os_sr_t sr;
+    os_time_t delta;
+
+    OS_ENTER_CRITICAL(sr);
+    if (tv != NULL) {
+        delta = os_time_get() - basetod.ostime;
+        os_deltatime(delta, &basetod.utctime, tv);
+    }
+
+    if (tz != NULL) {
+        *tz = basetod.timezone;
+    }
+    OS_EXIT_CRITICAL(sr);
+
+    return (0);
+}
+
+/**
+ * Get time since boot in microseconds.
+ *
+ * @return time since boot in microseconds
+ */
+int64_t
+os_get_uptime_usec(void)
+{
+  struct os_timeval tv;
+  os_time_t delta;
+  os_sr_t sr;
+  os_time_t ostime;
+
+
+  OS_ENTER_CRITICAL(sr);
+  tv = basetod.uptime;
+  ostime = basetod.ostime;
+  delta = os_time_get() - ostime;
+  OS_EXIT_CRITICAL(sr);
+
+  os_deltatime(delta, &tv, &tv);
+
+  return(tv.tv_sec * 1000000 + tv.tv_usec);
+}
+
+/**
+ * Converts milliseconds to OS ticks.
+ *
+ * @param ms                    The milliseconds input.
+ * @param out_ticks             The OS ticks output.
+ *
+ * @return                      0 on success; OS_EINVAL if the result is too
+ *                                  large to fit in a uint32_t.
+ */
+int
+os_time_ms_to_ticks(uint32_t ms, uint32_t *out_ticks)
+{
+    uint64_t ticks;
+
+#if OS_TICKS_PER_SEC == 1000
+    *out_ticks = ms;
+    return 0;
+#endif
+
+    _Static_assert(OS_TICKS_PER_SEC <= UINT32_MAX,
+                   "OS_TICKS_PER_SEC must be <= UINT32_MAX");
+
+    ticks = (uint64_t)ms * OS_TICKS_PER_SEC / 1000;
+    if (ticks > UINT32_MAX) {
+        return OS_EINVAL;
+    }
+
+    *out_ticks = ticks;
+    return 0;
+}
+
+/**
+ *   @} OSKernel
+ * @} OSTime
+ */
diff --git a/porting/common/src/sysinit/sysinit.c b/porting/common/src/sysinit/sysinit.c
new file mode 100644
index 0000000..393d1c5
--- /dev/null
+++ b/porting/common/src/sysinit/sysinit.c
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <stdio.h>
+#include <stddef.h>
+#include <limits.h>
+#include "os/os_fault.h"
+#include "syscfg/syscfg.h"
+#include "sysinit/sysinit.h"
+
+static void
+sysinit_dflt_panic_cb(const char *file, int line, const char *func,
+                      const char *expr, const char *msg)
+{
+#if MYNEWT_VAL(SYSINIT_PANIC_MESSAGE)
+    if (msg != NULL) {
+        fprintf(stderr, "sysinit failure: %s\n", msg);
+    }
+#endif
+
+    __assert_func(file, line, func, expr);
+}
+
+sysinit_panic_fn *sysinit_panic_cb = sysinit_dflt_panic_cb;
+
+uint8_t sysinit_active;
+
+/**
+ * Sets the sysinit panic function; i.e., the function which executes when
+ * initialization fails.  By default, a panic triggers a failed assertion.
+ */
+void
+sysinit_panic_set(sysinit_panic_fn *panic_cb)
+{
+    sysinit_panic_cb = panic_cb;
+}
+
+void
+sysinit_start(void)
+{
+    sysinit_active = 1;
+}
+
+void
+sysinit_end(void)
+{
+    sysinit_active = 0;
+}
diff --git a/porting/freertos_nrf5_sdk/Makefile b/porting/freertos_nrf5_sdk/Makefile
new file mode 100644
index 0000000..fb2818b
--- /dev/null
+++ b/porting/freertos_nrf5_sdk/Makefile
@@ -0,0 +1,257 @@
+PROJECT_NAME     := nimble_FreeRTOS_pca10040
+TARGETS          := nrf52832_xxaa
+OUTPUT_DIRECTORY := _build
+
+NRF5_SDK_ROOT ?= ./nrf5_sdk
+PROJ_ROOT := ../..
+
+$(OUTPUT_DIRECTORY)/nrf52832_xxaa.out: \
+  LINKER_SCRIPT  := nimble_FreeRTOS_gcc_nrf52.ld
+
+# Source files common to all targets
+SRC_FILES += \
+  $(NRF5_SDK_ROOT)/components/libraries/log/src/nrf_log_backend_serial.c \
+  $(NRF5_SDK_ROOT)/components/libraries/log/src/nrf_log_frontend.c \
+  $(NRF5_SDK_ROOT)/components/libraries/button/app_button.c \
+  $(NRF5_SDK_ROOT)/components/libraries/util/app_error.c \
+  $(NRF5_SDK_ROOT)/components/libraries/util/app_error_weak.c \
+  $(NRF5_SDK_ROOT)/components/libraries/timer/app_timer_freertos.c \
+  $(NRF5_SDK_ROOT)/components/libraries/util/app_util_platform.c \
+  $(NRF5_SDK_ROOT)/components/libraries/util/nrf_assert.c \
+  $(NRF5_SDK_ROOT)/components/libraries/util/sdk_errors.c \
+  $(NRF5_SDK_ROOT)/external/freertos/source/croutine.c \
+  $(NRF5_SDK_ROOT)/external/freertos/source/event_groups.c \
+  $(NRF5_SDK_ROOT)/external/freertos/source/portable/MemMang/heap_1.c \
+  $(NRF5_SDK_ROOT)/external/freertos/source/list.c \
+  $(NRF5_SDK_ROOT)/external/freertos/portable/GCC/nrf52/port.c \
+  $(NRF5_SDK_ROOT)/external/freertos/portable/CMSIS/nrf52/port_cmsis.c \
+  $(NRF5_SDK_ROOT)/external/freertos/portable/CMSIS/nrf52/port_cmsis_systick.c \
+  $(NRF5_SDK_ROOT)/external/freertos/source/queue.c \
+  $(NRF5_SDK_ROOT)/external/freertos/source/tasks.c \
+  $(NRF5_SDK_ROOT)/external/freertos/source/timers.c \
+  $(NRF5_SDK_ROOT)/components/boards/boards.c \
+  $(NRF5_SDK_ROOT)/components/drivers_nrf/clock/nrf_drv_clock.c \
+  $(NRF5_SDK_ROOT)/components/drivers_nrf/common/nrf_drv_common.c \
+  $(NRF5_SDK_ROOT)/components/drivers_nrf/gpiote/nrf_drv_gpiote.c \
+  $(NRF5_SDK_ROOT)/components/drivers_nrf/uart/nrf_drv_uart.c \
+  $(NRF5_SDK_ROOT)/components/drivers_nrf/nrf_soc_nosd/nrf_nvic.c \
+  $(NRF5_SDK_ROOT)/components/drivers_nrf/nrf_soc_nosd/nrf_soc.c \
+  $(NRF5_SDK_ROOT)/components/libraries/bsp/bsp.c \
+  $(NRF5_SDK_ROOT)/components/libraries/bsp/bsp_nfc.c \
+  $(NRF5_SDK_ROOT)/external/segger_rtt/RTT_Syscalls_GCC.c \
+  $(NRF5_SDK_ROOT)/external/segger_rtt/SEGGER_RTT.c \
+  $(NRF5_SDK_ROOT)/external/segger_rtt/SEGGER_RTT_printf.c \
+  $(NRF5_SDK_ROOT)/components/toolchain/gcc/gcc_startup_nrf52.S \
+  $(NRF5_SDK_ROOT)/components/toolchain/system_nrf52.c \
+  ./src/main.c \
+  ./src/ble_task.c \
+  ./src/os_port.c \
+  ./src/cmsis_nvic.c \
+  ./src/hal_timer.c \
+  $(PROJ_ROOT)/porting/common/src/nimble_port.c \
+  $(PROJ_ROOT)/porting/common/src/mem/mem.c \
+  $(PROJ_ROOT)/porting/common/src/os/endian.c \
+  $(PROJ_ROOT)/porting/common/src/os/os_cputime.c \
+  $(PROJ_ROOT)/porting/common/src/os/os_cputime_pwr2.c \
+  $(PROJ_ROOT)/porting/common/src/os/os_mbuf.c \
+  $(PROJ_ROOT)/porting/common/src/os/os_mempool.c \
+  $(PROJ_ROOT)/porting/common/src/os/os_msys_init.c \
+  $(PROJ_ROOT)/porting/common/src/sysinit/sysinit.c \
+  $(PROJ_ROOT)/nimble/src/ble_util.c \
+  $(PROJ_ROOT)/nimble/src/hci_common.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_att_clt.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_att_cmd.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_att.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_att_svr.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_eddystone.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_gap.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_gattc.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_gatts_lcl.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_gatts.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs_adv.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs_atomic.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs_cfg.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs_conn.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs_dbg.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs_hci_cmd.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs_hci_evt.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs_hci.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs_hci_util.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs_id.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs_log.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs_mbuf.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs_misc.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs_pvcy.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_hs_startup.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_ibeacon.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_l2cap_coc.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_l2cap.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_l2cap_sig_cmd.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_l2cap_sig.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_monitor.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_sm_alg.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_sm_cmd.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_sm_lgcy.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_sm.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_sm_sc.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_store.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_store_util.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_uuid.c \
+  $(PROJ_ROOT)/nimble/host/src/ble_uuid.c \
+  $(PROJ_ROOT)/nimble/host/services/ans/src/ble_svc_ans.c \
+  $(PROJ_ROOT)/nimble/host/services/gap/src/ble_svc_gap.c \
+  $(PROJ_ROOT)/nimble/host/services/gatt/src/ble_svc_gatt.c \
+  $(PROJ_ROOT)/nimble/host/services/ias/src/ble_svc_ias.c \
+  $(PROJ_ROOT)/nimble/host/services/lls/src/ble_svc_lls.c \
+  $(PROJ_ROOT)/nimble/host/services/tps/src/ble_svc_tps.c \
+  $(PROJ_ROOT)/nimble/host/store/ram/src/ble_store_ram.c \
+  $(PROJ_ROOT)/nimble/controller/src/ble_ll_sched.c \
+  $(PROJ_ROOT)/nimble/controller/src/ble_ll_xcvr.c \
+  $(PROJ_ROOT)/nimble/controller/src/ble_ll_whitelist.c \
+  $(PROJ_ROOT)/nimble/controller/src/ble_ll_ctrl.c \
+  $(PROJ_ROOT)/nimble/controller/src/ble_ll_hci.c \
+  $(PROJ_ROOT)/nimble/controller/src/ble_ll_supp_cmd.c \
+  $(PROJ_ROOT)/nimble/controller/src/ble_ll_adv.c \
+  $(PROJ_ROOT)/nimble/controller/src/ble_ll_conn.c \
+  $(PROJ_ROOT)/nimble/controller/src/ble_ll_resolv.c \
+  $(PROJ_ROOT)/nimble/controller/src/ble_ll_conn_hci.c \
+  $(PROJ_ROOT)/nimble/controller/src/ble_ll_rand.c \
+  $(PROJ_ROOT)/nimble/controller/src/ble_ll.c \
+  $(PROJ_ROOT)/nimble/controller/src/ble_ll_scan.c \
+  $(PROJ_ROOT)/nimble/controller/src/ble_ll_hci_ev.c \
+  $(PROJ_ROOT)/nimble/transport/ram/src/ble_hci_ram.c \
+  $(PROJ_ROOT)/nimble/drivers/nrf52/src/ble_hw.c \
+  $(PROJ_ROOT)/nimble/drivers/nrf52/src/ble_phy.c \
+  $(PROJ_ROOT)/tinycrypt/src/aes_decrypt.c \
+  $(PROJ_ROOT)/tinycrypt/src/aes_encrypt.c \
+  $(PROJ_ROOT)/tinycrypt/src/cmac_mode.c \
+  $(PROJ_ROOT)/tinycrypt/src/ecc.c \
+  $(PROJ_ROOT)/tinycrypt/src/ecc_dh.c \
+  $(PROJ_ROOT)/tinycrypt/src/utils.c \
+
+# Include folders common to all targets
+INC_FOLDERS += \
+  ./config \
+  $(NRF5_SDK_ROOT)/components \
+  $(NRF5_SDK_ROOT)/components/toolchain/cmsis/include \
+  $(NRF5_SDK_ROOT)/external/freertos/source/include \
+  $(NRF5_SDK_ROOT)/external/freertos/config \
+  $(NRF5_SDK_ROOT)/components/libraries/util \
+  $(NRF5_SDK_ROOT)/components/drivers_nrf/uart \
+  $(NRF5_SDK_ROOT)/components/libraries/bsp \
+  $(NRF5_SDK_ROOT)/components/device \
+  $(NRF5_SDK_ROOT)/components/libraries/log \
+  $(NRF5_SDK_ROOT)/components/libraries/button \
+  $(NRF5_SDK_ROOT)/components/libraries/timer \
+  $(NRF5_SDK_ROOT)/external/freertos/portable/CMSIS/nrf52 \
+  $(NRF5_SDK_ROOT)/components/drivers_nrf/gpiote \
+  $(NRF5_SDK_ROOT)/external/segger_rtt \
+  $(NRF5_SDK_ROOT)/components/drivers_nrf/nrf_soc_nosd \
+  $(NRF5_SDK_ROOT)/components/boards \
+  $(NRF5_SDK_ROOT)/components/drivers_nrf/hal \
+  $(NRF5_SDK_ROOT)/components/toolchain/gcc \
+  $(NRF5_SDK_ROOT)/components/toolchain \
+  $(NRF5_SDK_ROOT)/components/drivers_nrf/common \
+  $(NRF5_SDK_ROOT)/components/drivers_nrf/clock \
+  $(NRF5_SDK_ROOT)/external/freertos/portable/GCC/nrf52 \
+  $(NRF5_SDK_ROOT)/components/libraries/log/src \
+  ./include \
+  $(PROJ_ROOT)/porting/common/include \
+  $(PROJ_ROOT)/nimble/include \
+  $(PROJ_ROOT)/nimble/host/include \
+  $(PROJ_ROOT)/nimble/host/mesh/include \
+  $(PROJ_ROOT)/nimble/host/services/ans/include \
+  $(PROJ_ROOT)/nimble/host/services/gap/include \
+  $(PROJ_ROOT)/nimble/host/services/gatt/include \
+  $(PROJ_ROOT)/nimble/host/services/ias/include \
+  $(PROJ_ROOT)/nimble/host/services/lls/include \
+  $(PROJ_ROOT)/nimble/host/services/tps/include \
+  $(PROJ_ROOT)/nimble/host/store/ram/include \
+  $(PROJ_ROOT)/nimble/controller/include \
+  $(PROJ_ROOT)/nimble/transport/ram/include \
+  $(PROJ_ROOT)/nimble/drivers/nrf52/include \
+  $(PROJ_ROOT)/tinycrypt/include \
+
+# Libraries common to all targets
+LIB_FILES += \
+
+# C flags common to all targets
+CFLAGS += -DNRF52_PAN_12
+CFLAGS += -DNRF52_PAN_15
+CFLAGS += -DNRF52_PAN_58
+CFLAGS += -DFREERTOS
+CFLAGS += -DNRF52_PAN_20
+CFLAGS += -DNRF52_PAN_54
+CFLAGS += -DNRF52
+CFLAGS += -DNRF52_PAN_51
+CFLAGS += -DNRF52_PAN_36
+CFLAGS += -DCONFIG_GPIO_AS_PINRESET
+CFLAGS += -DNRF52_PAN_64
+CFLAGS += -DNRF52_PAN_55
+CFLAGS += -DBOARD_PCA10040
+CFLAGS += -DNRF52_PAN_31
+CFLAGS += -DNRF52832
+CFLAGS += -mcpu=cortex-m4
+CFLAGS += -mthumb -mabi=aapcs
+CFLAGS +=  -Wall -Werror -Og -g3
+CFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
+# keep every function in separate section, this allows linker to discard unused ones
+CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
+CFLAGS += -fno-builtin --short-enums 
+
+# C++ flags common to all targets
+CXXFLAGS += \
+
+# Assembler flags common to all targets
+ASMFLAGS += -x assembler-with-cpp
+ASMFLAGS += -DNRF52_PAN_12
+ASMFLAGS += -DNRF52_PAN_15
+ASMFLAGS += -DNRF52_PAN_58
+ASMFLAGS += -DFREERTOS
+ASMFLAGS += -DNRF52_PAN_20
+ASMFLAGS += -DNRF52_PAN_54
+ASMFLAGS += -DNRF52
+ASMFLAGS += -DNRF52_PAN_51
+ASMFLAGS += -DNRF52_PAN_36
+ASMFLAGS += -DCONFIG_GPIO_AS_PINRESET
+ASMFLAGS += -DNRF52_PAN_64
+ASMFLAGS += -DNRF52_PAN_55
+ASMFLAGS += -DBOARD_PCA10040
+ASMFLAGS += -DNRF52_PAN_31
+ASMFLAGS += -DNRF52832
+
+# Linker flags
+LDFLAGS += -mthumb -mabi=aapcs -L $(TEMPLATE_PATH) -T$(LINKER_SCRIPT)
+LDFLAGS += -mcpu=cortex-m4
+LDFLAGS += -mfloat-abi=hard -mfpu=fpv4-sp-d16
+# let linker to dump unused sections
+LDFLAGS += -Wl,--gc-sections
+# use newlib in nano version
+LDFLAGS += --specs=nano.specs -lc -lnosys
+
+
+.PHONY: $(TARGETS) default all clean help flash 
+
+# Default target - first one defined
+default: nrf52832_xxaa
+
+# Print all targets that can be built
+help:
+	@echo following targets are available:
+	@echo 	nrf52832_xxaa
+
+TEMPLATE_PATH := $(NRF5_SDK_ROOT)/components/toolchain/gcc
+
+include $(TEMPLATE_PATH)/Makefile.common
+
+$(foreach target, $(TARGETS), $(call define_target, $(target)))
+
+# Flash the program
+flash: $(OUTPUT_DIRECTORY)/nrf52832_xxaa.hex
+	@echo Flashing: $<
+	nrfjprog --program $< -f nrf52 --sectorerase
+	nrfjprog --reset -f nrf52
+
+erase:
+	nrfjprog --eraseall -f nrf52
diff --git a/porting/freertos_nrf5_sdk/config/FreeRTOSConfig.h b/porting/freertos_nrf5_sdk/config/FreeRTOSConfig.h
new file mode 100644
index 0000000..7569484
--- /dev/null
+++ b/porting/freertos_nrf5_sdk/config/FreeRTOSConfig.h
@@ -0,0 +1,229 @@
+/*
+    FreeRTOS V8.0.1 - Copyright (C) 2014 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that has become a de facto standard.             *
+     *                                                                       *
+     *    Help yourself get started quickly and support the FreeRTOS         *
+     *    project by purchasing a FreeRTOS tutorial book, reference          *
+     *    manual, or both from: http://www.FreeRTOS.org/Documentation        *
+     *                                                                       *
+     *    Thank you!                                                         *
+     *                                                                       *
+    ***************************************************************************
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available from the following
+    link: http://www.freertos.org/a00114.html
+
+    1 tab == 4 spaces!
+
+    ***************************************************************************
+     *                                                                       *
+     *    Having a problem?  Start by reading the FAQ "My application does   *
+     *    not run, what could be wrong?"                                     *
+     *                                                                       *
+     *    http://www.FreeRTOS.org/FAQHelp.html                               *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org - Documentation, books, training, latest versions,
+    license and Real Time Engineers Ltd. contact details.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
+    Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+
+#ifdef SOFTDEVICE_PRESENT
+#include "nrf_soc.h"
+#endif
+
+/*-----------------------------------------------------------
+ * Possible configurations for system timer
+ */
+#define FREERTOS_USE_RTC      0 /**< Use real time clock for the system */
+#define FREERTOS_USE_SYSTICK  1 /**< Use SysTick timer for system */
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *
+ * See http://www.freertos.org/a00110.html.
+ *----------------------------------------------------------*/
+
+#define configTICK_SOURCE FREERTOS_USE_RTC
+
+#define configUSE_PREEMPTION 1
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
+#define configUSE_TICKLESS_IDLE 1
+#define configUSE_TICKLESS_IDLE_SIMPLE_DEBUG                                      1 /* See into vPortSuppressTicksAndSleep source code for explanation */
+#define configCPU_CLOCK_HZ                                                        ( SystemCoreClock )
+#define configTICK_RATE_HZ                                                        1000
+#define configMAX_PRIORITIES                                                      ( 3 )
+#define configMINIMAL_STACK_SIZE                                                  ( 60 )
+#define configTOTAL_HEAP_SIZE                                                     ( 6144 )
+#define configMAX_TASK_NAME_LEN                                                   ( 4 )
+#define configUSE_16_BIT_TICKS                                                    0
+#define configIDLE_SHOULD_YIELD                                                   1
+#define configUSE_MUTEXES                                                         1
+#define configUSE_RECURSIVE_MUTEXES                                               1
+#define configUSE_COUNTING_SEMAPHORES                                             1
+#define configUSE_ALTERNATIVE_API                                                 0    /* Deprecated! */
+#define configQUEUE_REGISTRY_SIZE                                                 2
+#define configUSE_QUEUE_SETS                                                      0
+#define configUSE_TIME_SLICING                                                    0
+#define configUSE_NEWLIB_REENTRANT                                                0
+#define configENABLE_BACKWARD_COMPATIBILITY                                       1
+
+/* Hook function related definitions. */
+#define configUSE_IDLE_HOOK                                                       0
+#define configUSE_TICK_HOOK                                                       0
+#define configCHECK_FOR_STACK_OVERFLOW                                            0
+#define configUSE_MALLOC_FAILED_HOOK                                              0
+
+/* Run time and task stats gathering related definitions. */
+#define configGENERATE_RUN_TIME_STATS                                             0
+#define configUSE_TRACE_FACILITY                                                  0
+#define configUSE_STATS_FORMATTING_FUNCTIONS                                      0
+
+/* Co-routine definitions. */
+#define configUSE_CO_ROUTINES                                                     0
+#define configMAX_CO_ROUTINE_PRIORITIES                                           ( 2 )
+
+/* Software timer definitions. */
+#define configUSE_TIMERS 1
+#define configTIMER_TASK_PRIORITY                                                 ( 2 )
+#define configTIMER_QUEUE_LENGTH                                                  32
+#define configTIMER_TASK_STACK_DEPTH                                              ( 80 )
+
+/* Tickless Idle configuration. */
+#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP                                     2
+
+/* Tickless idle/low power functionality. */
+
+
+/* Define to trap errors during development. */
+#if defined(DEBUG_NRF) || defined(DEBUG_NRF_USER)
+#define configASSERT( x )                                                         ASSERT(x)
+#endif
+
+/* FreeRTOS MPU specific definitions. */
+#define configINCLUDE_APPLICATION_DEFINED_PRIVILEGED_FUNCTIONS                    1
+
+/* Optional functions - most linkers will remove unused functions anyway. */
+#define INCLUDE_vTaskPrioritySet                                                  1
+#define INCLUDE_uxTaskPriorityGet                                                 1
+#define INCLUDE_vTaskDelete                                                       1
+#define INCLUDE_vTaskSuspend                                                      1
+#define INCLUDE_xResumeFromISR                                                    1
+#define INCLUDE_vTaskDelayUntil                                                   1
+#define INCLUDE_vTaskDelay                                                        1
+#define INCLUDE_xTaskGetSchedulerState                                            1
+#define INCLUDE_xTaskGetCurrentTaskHandle                                         1
+#define INCLUDE_uxTaskGetStackHighWaterMark                                       1
+#define INCLUDE_xTaskGetIdleTaskHandle                                            1
+#define INCLUDE_xTimerGetTimerDaemonTaskHandle                                    1
+#define INCLUDE_pcTaskGetTaskName                                                 1
+#define INCLUDE_eTaskGetState                                                     1
+#define INCLUDE_xEventGroupSetBitFromISR                                          1
+#define INCLUDE_xTimerPendFunctionCall                                            1
+
+/* The lowest interrupt priority that can be used in a call to a "set priority"
+function. */
+#define configLIBRARY_LOWEST_INTERRUPT_PRIORITY         0xf
+
+/* The highest interrupt priority that can be used by any interrupt service
+routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
+INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
+PRIORITY THAN THIS! (higher priorities are lower numeric values. */
+#define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY    1
+
+/* Interrupt priorities used by the kernel port layer itself.  These are generic
+to all Cortex-M ports, and do not rely on any particular library functions. */
+#define configKERNEL_INTERRUPT_PRIORITY                 configLIBRARY_LOWEST_INTERRUPT_PRIORITY
+/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
+See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY            configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY
+
+/* Definitions that map the FreeRTOS port interrupt handlers to their CMSIS
+standard names - or at least those used in the unmodified vector table. */
+
+#define vPortSVCHandler                                                           SVC_Handler
+#define xPortPendSVHandler                                                        PendSV_Handler
... 3734 lines suppressed ...

-- 
To stop receiving notification emails like this one, please contact
"commits@mynewt.apache.org" <co...@mynewt.apache.org>.